diff --git a/src/agent/prompts/repo.ts b/src/agent/prompts/repo.ts index 0c423d5d87997c2dff128d0417f857489dbb4e76..796fddb862903b3ba1188680b21cf1ac2f9a7986 100644 --- a/src/agent/prompts/repo.ts +++ b/src/agent/prompts/repo.ts @@ -1,5 +1,31 @@ -export const REPO_SYSTEM_PROMPT = `You are a research assistant focused on answering the user's question by exploring a git repository in the workspace. +export interface RepoPromptContext { + currentTime: string; + hasHistory: boolean; +} -Use read and grep to inspect files. Use git tools to explore history and refs. Prefer concrete file references and explain where information comes from. +export function buildRepoPrompt(ctx: RepoPromptContext): string { + const historyGuidance = ctx.hasHistory + ? "\nGit history is available. Blame and log can reveal why code exists and how it evolved. Use them when the question involves \"why\" or \"when,\" or when current code is confusing without context." + : ""; -Be concise and answer directly.`; + const historyEnv = ctx.hasHistory + ? "Git history: available (full clone)" + : "Git history: limited (shallow clone)"; + + return `You are a librarian of source code. You know the stacks—every file, every commit, every branch is a volume you can pull from the shelf. Your job is to find exactly the right reference for the question at hand, no more and no less. + + +If you need orientation, look first for agent instruction files (AGENTS.md, CLAUDE.md, .cursorrules, .github/copilot-instructions.md) — these often describe the project's architecture, conventions, and key commands. Failing that, check the README. Otherwise, go straight to targeted search. + +For large files, search first to find the relevant sections, then read those specifically. Stop once you have enough evidence to answer.${historyGuidance} + + + +Be precise. Only cite files, lines, and commits you actually examined. Reference specific file paths and line ranges. When citing git history, include commit hashes. If you cannot find sufficient information, say so and explain what you explored. + + + +Current time: ${ctx.currentTime} +${historyEnv} +`; +} diff --git a/src/agent/prompts/web.ts b/src/agent/prompts/web.ts index 2c0cc9981adde2fa35253ff4356bedc24f424353..ea53458f49b1a7ca3e82987eb8d1d095c5940bba 100644 --- a/src/agent/prompts/web.ts +++ b/src/agent/prompts/web.ts @@ -1,7 +1,21 @@ -export const WEB_SYSTEM_PROMPT = `You are a research assistant focused on answering the user's question using web sources. +export interface WebPromptContext { + currentTime: string; +} -You have tools to search the web, fetch URLs into markdown, and read or grep files in the workspace. +export function buildWebPrompt(ctx: WebPromptContext): string { + return `You are a field researcher. You go out into the world, find the best sources, and bring back what matters. Not everything, just what answers the question. -Use web_search to find sources. Use web_fetch to retrieve a URL. When content is large, it may be stored in the workspace; use read and grep to explore it. + +Prefer primary and official sources over blogs and SEO pages. -Be concise, cite sources with URLs, and answer directly.`; +When content is large, use grep to find the sections that matter, then read those specifically. Stop once you have enough evidence to answer. + + + +Be direct. Only cite URLs you actually accessed. Include version or date when it matters. If sources conflict, note the discrepancy. If you cannot find sufficient information, say so and explain what you tried. + + + +Current time: ${ctx.currentTime} +`; +} diff --git a/src/cli/commands/repo.ts b/src/cli/commands/repo.ts index e5d1fd7f0ab4802ddc9552cbcb0da0d8309225fa..0ca47695b0dde466d05434ad28a36d3284f76658 100644 --- a/src/cli/commands/repo.ts +++ b/src/cli/commands/repo.ts @@ -13,7 +13,7 @@ import { createGitDiffTool } from "../../agent/tools/git/diff.js"; import { createGitRefsTool } from "../../agent/tools/git/refs.js"; import { createGitCheckoutTool } from "../../agent/tools/git/checkout.js"; import { runAgent } from "../../agent/runner.js"; -import { REPO_SYSTEM_PROMPT } from "../../agent/prompts/repo.js"; +import { buildRepoPrompt } from "../../agent/prompts/repo.js"; import { createEventLogger, printUsageSummary } from "../output.js"; import { CloneError } from "../../util/errors.js"; import simpleGit from "simple-git"; @@ -40,7 +40,10 @@ export async function runRepoCommand(options: RepoCommandOptions): Promise try { const logger = createEventLogger({ verbose: options.verbose }); - let systemPrompt = REPO_SYSTEM_PROMPT; + let systemPrompt = buildRepoPrompt({ + currentTime: new Date().toISOString(), + hasHistory: options.full, + }); const promptPath = overrides.repo.system_prompt_path; if (promptPath) { systemPrompt = await readFile(expandHomePath(promptPath), "utf8"); diff --git a/src/cli/commands/web.ts b/src/cli/commands/web.ts index 547d9e0f15b6d204263546c9e45e325e624efca5..a402b584e27bf4807301db1fbdb54efafe35950a 100644 --- a/src/cli/commands/web.ts +++ b/src/cli/commands/web.ts @@ -11,7 +11,7 @@ import { createFindTool } from "../../agent/tools/find.js"; import { createWebFetchTool } from "../../agent/tools/web-fetch.js"; import { createWebSearchTool } from "../../agent/tools/web-search.js"; import { runAgent } from "../../agent/runner.js"; -import { WEB_SYSTEM_PROMPT } from "../../agent/prompts/web.js"; +import { buildWebPrompt } from "../../agent/prompts/web.js"; import { createEventLogger, printUsageSummary } from "../output.js"; import { ConfigError, FetchError } from "../../util/errors.js"; @@ -51,7 +51,9 @@ export async function runWebCommand(options: WebCommandOptions): Promise { throw new ConfigError("Web fetch requires TABSTACK_API_KEY (set via environment or config)"); } - let systemPrompt = WEB_SYSTEM_PROMPT; + let systemPrompt = buildWebPrompt({ + currentTime: new Date().toISOString(), + }); const promptPath = overrides.web.system_prompt_path; if (promptPath) { systemPrompt = await readFile(expandHomePath(promptPath), "utf8"); @@ -79,14 +81,16 @@ export async function runWebCommand(options: WebCommandOptions): Promise { } else { const filename = `web/${basename(new URL(options.url).pathname) || "index"}.md`; await writeWorkspaceFile(workspace.path, filename, text); - seededContext = `Fetched content stored at ${filename}`; + seededContext = `Content from ${options.url} was too large to include directly. It has been saved to ${filename} in your workspace.`; } } catch (error: any) { throw new FetchError(options.url, error?.message ?? String(error)); } } - const query = seededContext ? `${options.query}\n\n${seededContext}` : options.query; + const query = seededContext + ? `${options.query}\n\n\n${seededContext}\n` + : options.query; const result = await runAgent(query, { model: overrides.web.model ?? overrides.defaults.model,