smart context v3 (#1022)

<!-- This is an auto-generated description by cubic. -->

## Summary by cubic
Adds Smart Context v3 with selectable modes (Off, Conservative,
Balanced) and surfaces token savings in chat. Also improves token
estimation by counting per-file tokens when Smart Context is enabled.

- **New Features**
- Smart Context selector in Pro settings with three options.
Conservative is the default when enabled without an explicit choice.
- New setting: proSmartContextOption ("balanced"); undefined implies
Conservative.
- Engine now receives enable_smart_files_context and smart_context_mode.
- Chat shows a DyadTokenSavings card when the message contains
token-savings?original-tokens=...&smart-context-tokens=..., with percent
saved and a tooltip for exact tokens.
- Token estimation uses extracted file contents for accuracy when Pro +
Smart Context is on; otherwise falls back to formatted codebase output.

<!-- End of auto-generated description by cubic. -->
This commit is contained in:
Will Chen
2025-08-20 14:16:07 -07:00
committed by GitHub
parent 34215db141
commit 4e9a927a7b
18 changed files with 764 additions and 26 deletions

View File

@@ -41,7 +41,7 @@ test("manage context - smart context", async ({ po }) => {
// Disabling smart context will automatically disable
// the auto-includes.
const proModesDialog = await po.openProModesDialog();
await proModesDialog.toggleSmartContext();
await proModesDialog.setSmartContextMode("off");
await proModesDialog.close();
await po.sendPrompt("[dump]");

View File

@@ -2,8 +2,6 @@ import { testSkipIfWindows } from "./helpers/test_helper";
testSkipIfWindows("send message to engine", async ({ po }) => {
await po.setUpDyadPro();
// By default, it's using auto which points to Flash 2.5 and doesn't
// use engine.
await po.selectModel({ provider: "Google", model: "Gemini 2.5 Pro" });
await po.sendPrompt("[dump] tc=turbo-edits");
@@ -11,6 +9,23 @@ testSkipIfWindows("send message to engine", async ({ po }) => {
await po.snapshotMessages({ replaceDumpPath: true });
});
testSkipIfWindows(
"send message to engine - smart context balanced",
async ({ po }) => {
await po.setUpDyadPro();
const proModesDialog = await po.openProModesDialog({
location: "home-chat-input-container",
});
await proModesDialog.setSmartContextMode("balanced");
await proModesDialog.close();
await po.selectModel({ provider: "Google", model: "Gemini 2.5 Pro" });
await po.sendPrompt("[dump] tc=turbo-edits");
await po.snapshotServerDump("request");
await po.snapshotMessages({ replaceDumpPath: true });
},
);
testSkipIfWindows("send message to engine - openai gpt-4.1", async ({ po }) => {
await po.setUpDyadPro();
// By default, it's using auto which points to Flash 2.5 and doesn't
@@ -52,7 +67,7 @@ testSkipIfWindows(
const proModesDialog = await po.openProModesDialog({
location: "home-chat-input-container",
});
await proModesDialog.toggleSmartContext();
await proModesDialog.setSmartContextMode("off");
await proModesDialog.close();
await po.sendPrompt("[dump] tc=turbo-edits");

View File

@@ -7,7 +7,7 @@ testSkipIfWindows("claude 4 sonnet", async ({ po }) => {
location: "home-chat-input-container",
});
await proModesDialog.toggleTurboEdits();
await proModesDialog.toggleSmartContext();
await proModesDialog.setSmartContextMode("off");
await proModesDialog.close();
await po.selectModel({ provider: "Anthropic", model: "Claude 4 Sonnet" });

View File

@@ -67,8 +67,12 @@ class ProModesDialog {
public close: () => Promise<void>,
) {}
async toggleSmartContext() {
await this.page.getByRole("switch", { name: "Smart Context" }).click();
async setSmartContextMode(mode: "balanced" | "off" | "conservative") {
await this.page
.getByRole("button", {
name: mode.charAt(0).toUpperCase() + mode.slice(1),
})
.click();
}
async toggleTurboEdits() {

View File

@@ -0,0 +1,15 @@
import { test } from "./helpers/test_helper";
test("switching smart context mode saves the right setting", async ({ po }) => {
await po.setUpDyadPro();
const proModesDialog = await po.openProModesDialog({
location: "home-chat-input-container",
});
await po.snapshotSettings();
await proModesDialog.setSmartContextMode("balanced");
await po.snapshotSettings();
await proModesDialog.setSmartContextMode("off");
await po.snapshotSettings();
await proModesDialog.setSmartContextMode("conservative");
await po.snapshotSettings();
});

View File

@@ -0,0 +1,6 @@
- paragraph: "[dump] tc=turbo-edits"
- paragraph: "[[dyad-dump-path=*]]"
- img
- text: less than a minute ago
- button "Retry":
- img

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,28 @@
{
"selectedModel": {
"name": "auto",
"provider": "auto"
},
"providerSettings": {
"auto": {
"apiKey": {
"value": "testdyadkey",
"encryptionType": "plaintext"
}
}
},
"telemetryConsent": "unset",
"telemetryUserId": "[UUID]",
"hasRunBefore": true,
"enableDyadPro": true,
"experiments": {},
"lastShownReleaseNotesVersion": "[scrubbed]",
"enableProLazyEditsMode": true,
"enableProSmartFilesContextMode": true,
"selectedTemplateId": "react",
"selectedChatMode": "build",
"enableAutoFixProblems": false,
"enableAutoUpdate": true,
"releaseChannel": "stable",
"isTestMode": true
}

View File

@@ -0,0 +1,29 @@
{
"selectedModel": {
"name": "auto",
"provider": "auto"
},
"providerSettings": {
"auto": {
"apiKey": {
"value": "testdyadkey",
"encryptionType": "plaintext"
}
}
},
"telemetryConsent": "unset",
"telemetryUserId": "[UUID]",
"hasRunBefore": true,
"enableDyadPro": true,
"experiments": {},
"lastShownReleaseNotesVersion": "[scrubbed]",
"enableProLazyEditsMode": true,
"enableProSmartFilesContextMode": true,
"proSmartContextOption": "balanced",
"selectedTemplateId": "react",
"selectedChatMode": "build",
"enableAutoFixProblems": false,
"enableAutoUpdate": true,
"releaseChannel": "stable",
"isTestMode": true
}

View File

@@ -0,0 +1,28 @@
{
"selectedModel": {
"name": "auto",
"provider": "auto"
},
"providerSettings": {
"auto": {
"apiKey": {
"value": "testdyadkey",
"encryptionType": "plaintext"
}
}
},
"telemetryConsent": "unset",
"telemetryUserId": "[UUID]",
"hasRunBefore": true,
"enableDyadPro": true,
"experiments": {},
"lastShownReleaseNotesVersion": "[scrubbed]",
"enableProLazyEditsMode": true,
"enableProSmartFilesContextMode": false,
"selectedTemplateId": "react",
"selectedChatMode": "build",
"enableAutoFixProblems": false,
"enableAutoUpdate": true,
"releaseChannel": "stable",
"isTestMode": true
}

View File

@@ -0,0 +1,28 @@
{
"selectedModel": {
"name": "auto",
"provider": "auto"
},
"providerSettings": {
"auto": {
"apiKey": {
"value": "testdyadkey",
"encryptionType": "plaintext"
}
}
},
"telemetryConsent": "unset",
"telemetryUserId": "[UUID]",
"hasRunBefore": true,
"enableDyadPro": true,
"experiments": {},
"lastShownReleaseNotesVersion": "[scrubbed]",
"enableProLazyEditsMode": true,
"enableProSmartFilesContextMode": true,
"selectedTemplateId": "react",
"selectedChatMode": "build",
"enableAutoFixProblems": false,
"enableAutoUpdate": true,
"releaseChannel": "stable",
"isTestMode": true
}