Smart Context: deep (#1527)

<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Introduce a new "deep" Smart Context mode that supplies versioned
files (by commit) to the engine, adds code search rendering, stores
source commit hashes, improves search-replace recovery, and updates
UI/tests.
> 
> - **Smart Context (deep)**:
> - Replace `conservative` with `deep`; limit context to ~200 turns;
send `sourceCommitHash` per message.
> - Build and pass `versioned_files` (hash-id map + per-message file
refs) and `app_id` to engine.
> - **DB**:
>   - Add `messages.source_commit_hash` (+ migration/snapshot).
> - **Engine/Processing**:
> - Retry Turbo Edits v2: first re-read then fallback to `dyad-write` if
search-replace fails.
> - Include provider options and versioned files in requests; add
`getCurrentCommitHash`/`getFileAtCommit`.
> - **UI**:
>   - Pro mode selector: new `deep` option; tooltips polish.
> - Add `DyadCodeSearch` and `DyadCodeSearchResult` components; parser
supports new tags.
> - **Tests/E2E**:
> - New `smart_context_deep` e2e; update snapshots to include `app_id`
and deep mode; adjust Playwright timeout.
>   - Unit tests for versioned codebase context.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e3d3bffabb2bc6caf52103461f9d6f2d5ad39df8. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This commit is contained in:
Will Chen
2025-11-06 10:45:39 -08:00
committed by GitHub
parent ae1ec68453
commit 06ad1a7546
46 changed files with 3623 additions and 560 deletions

View File

@@ -6,7 +6,8 @@ import pathModule from "node:path";
import { exec } from "node:child_process";
import { promisify } from "node:util";
import { readSettings } from "../../main/settings";
import log from "electron-log";
const logger = log.scope("git_utils");
const execAsync = promisify(exec);
async function verboseExecAsync(
@@ -26,6 +27,18 @@ async function verboseExecAsync(
}
}
export async function getCurrentCommitHash({
path,
}: {
path: string;
}): Promise<string> {
return await git.resolveRef({
fs,
dir: path,
ref: "HEAD",
});
}
export async function gitCommit({
path,
message,
@@ -166,3 +179,45 @@ export async function gitAddAll({ path }: { path: string }): Promise<void> {
return git.add({ fs, dir: path, filepath: "." });
}
}
export async function getFileAtCommit({
path,
filePath,
commitHash,
}: {
path: string;
filePath: string;
commitHash: string;
}): Promise<string | null> {
const settings = readSettings();
if (settings.enableNativeGit) {
try {
const { stdout } = await execAsync(
`git -C "${path}" show "${commitHash}:${filePath}"`,
);
return stdout;
} catch (error: any) {
logger.error(
`Error getting file at commit ${commitHash}: ${error.message}`,
);
// File doesn't exist at this commit
return null;
}
} else {
try {
const { blob } = await git.readBlob({
fs,
dir: path,
oid: commitHash,
filepath: filePath,
});
return Buffer.from(blob).toString("utf-8");
} catch (error: any) {
logger.error(
`Error getting file at commit ${commitHash}: ${error.message}`,
);
// File doesn't exist at this commit
return null;
}
}
}