mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-08-03 21:51:11 -07:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5dde9cac7f | |||
| 27793d29fd | |||
| ab3c144cd6 | |||
| 557d34d4bd | |||
| e234c95b8a | |||
| 78114e904c | |||
| aed28faf0f | |||
| 2594201bee | |||
| 8d88fde964 | |||
| 78cd88fc7c | |||
| 4f72d4d9a7 | |||
| 047f180346 | |||
| c2ad740d66 | |||
| 692a8efe2a | |||
| 8be312c483 | |||
| 3371f5e11f | |||
| 4524e30e4e | |||
| 87ac43cdef | |||
| 09e7f615d6 | |||
| dd16aa0602 | |||
| a32f49aeaa |
@@ -146,7 +146,7 @@ their corresponding top-level category object in your `settings.json` file.
|
||||
- **`general.retryFetchErrors`** (boolean):
|
||||
- **Description:** Retry on "exception TypeError: fetch failed sending
|
||||
request" errors.
|
||||
- **Default:** `false`
|
||||
- **Default:** `true`
|
||||
|
||||
- **`general.debugKeystrokeLogging`** (boolean):
|
||||
- **Description:** Enable debug logging of keystrokes to the console.
|
||||
|
||||
Generated
+28
-1
@@ -2129,6 +2129,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.26.0.tgz",
|
||||
"integrity": "sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@hono/node-server": "^1.19.9",
|
||||
"ajv": "^8.17.1",
|
||||
@@ -2271,6 +2272,7 @@
|
||||
"integrity": "sha512-t54CUOsFMappY1Jbzb7fetWeO0n6K0k/4+/ZpkS+3Joz8I4VcvY9OiEBFRYISqaI2fq5sCiPtAjRDOzVYG8m+Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": "^6.0.0",
|
||||
"@octokit/graphql": "^9.0.2",
|
||||
@@ -2451,6 +2453,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
|
||||
"integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
@@ -2500,6 +2503,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.5.0.tgz",
|
||||
"integrity": "sha512-ka4H8OM6+DlUhSAZpONu0cPBtPPTQKxbxVzC4CzVx5+K4JnroJVBtDzLAMx4/3CDTJXRvVFhpFjtl4SaiTNoyQ==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@opentelemetry/semantic-conventions": "^1.29.0"
|
||||
},
|
||||
@@ -2874,6 +2878,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.5.0.tgz",
|
||||
"integrity": "sha512-F8W52ApePshpoSrfsSk1H2yJn9aKjCrbpQF1M9Qii0GHzbfVeFUB+rc3X4aggyZD8x9Gu3Slua+s6krmq6Dt8g==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@opentelemetry/core": "2.5.0",
|
||||
"@opentelemetry/semantic-conventions": "^1.29.0"
|
||||
@@ -2907,6 +2912,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.5.0.tgz",
|
||||
"integrity": "sha512-BeJLtU+f5Gf905cJX9vXFQorAr6TAfK3SPvTFqP+scfIpDQEJfRaGJWta7sJgP+m4dNtBf9y3yvBKVAZZtJQVA==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@opentelemetry/core": "2.5.0",
|
||||
"@opentelemetry/resources": "2.5.0"
|
||||
@@ -2961,6 +2967,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.5.0.tgz",
|
||||
"integrity": "sha512-VzRf8LzotASEyNDUxTdaJ9IRJ1/h692WyArDBInf5puLCjxbICD6XkHgpuudis56EndyS7LYFmtTMny6UABNdQ==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@opentelemetry/core": "2.5.0",
|
||||
"@opentelemetry/resources": "2.5.0",
|
||||
@@ -4124,6 +4131,7 @@
|
||||
"integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
@@ -4398,6 +4406,7 @@
|
||||
"integrity": "sha512-6sMvZePQrnZH2/cJkwRpkT7DxoAWh+g6+GFRK6bV3YQo7ogi3SX5rgF6099r5Q53Ma5qeT7LGmOmuIutF4t3lA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.35.0",
|
||||
"@typescript-eslint/types": "8.35.0",
|
||||
@@ -5323,6 +5332,7 @@
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -7863,6 +7873,7 @@
|
||||
"integrity": "sha512-GsGizj2Y1rCWDu6XoEekL3RLilp0voSePurjZIkxL3wlm5o5EC9VpgaP7lrCvjnkuLvzFBQWB3vWB3K5KQTveQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
@@ -8383,6 +8394,7 @@
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
|
||||
"integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"accepts": "^2.0.0",
|
||||
"body-parser": "^2.2.1",
|
||||
@@ -9679,6 +9691,7 @@
|
||||
"resolved": "https://registry.npmjs.org/hono/-/hono-4.11.9.tgz",
|
||||
"integrity": "sha512-Eaw2YTGM6WOxA6CXbckaEvslr2Ne4NFsKrvc0v97JD5awbmeBLO5w9Ho9L9kmKonrwF9RJlW6BxT1PVv/agBHQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=16.9.0"
|
||||
}
|
||||
@@ -9979,6 +9992,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@jrichman/ink/-/ink-6.4.11.tgz",
|
||||
"integrity": "sha512-93LQlzT7vvZ1XJcmOMwN4s+6W334QegendeHOMnEJBlhnpIzr8bws6/aOEHG8ZCuVD/vNeeea5m1msHIdAY6ig==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@alcalzone/ansi-tokenize": "^0.2.1",
|
||||
"ansi-escapes": "^7.0.0",
|
||||
@@ -13667,6 +13681,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
|
||||
"integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -13677,6 +13692,7 @@
|
||||
"integrity": "sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"shell-quote": "^1.6.1",
|
||||
"ws": "^7"
|
||||
@@ -15730,6 +15746,7 @@
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -15953,7 +15970,8 @@
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"dev": true,
|
||||
"license": "0BSD"
|
||||
"license": "0BSD",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/tsx": {
|
||||
"version": "4.20.3",
|
||||
@@ -15961,6 +15979,7 @@
|
||||
"integrity": "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "~0.25.0",
|
||||
"get-tsconfig": "^4.7.5"
|
||||
@@ -16121,6 +16140,7 @@
|
||||
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
|
||||
"devOptional": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -16328,6 +16348,7 @@
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-7.2.2.tgz",
|
||||
"integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.5.0",
|
||||
@@ -16441,6 +16462,7 @@
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -16453,6 +16475,7 @@
|
||||
"resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz",
|
||||
"integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/chai": "^5.2.2",
|
||||
"@vitest/expect": "3.2.4",
|
||||
@@ -17084,6 +17107,7 @@
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
||||
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
@@ -17162,6 +17186,7 @@
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/sdk": "^0.12.0",
|
||||
"@google/gemini-cli-core": "file:../core",
|
||||
"@google/gemini-cli-devtools": "file:../devtools",
|
||||
"@google/genai": "1.41.0",
|
||||
"@iarna/toml": "^2.2.5",
|
||||
"@modelcontextprotocol/sdk": "^1.23.0",
|
||||
@@ -17419,6 +17444,7 @@
|
||||
"shell-quote": "^1.8.3",
|
||||
"simple-git": "^3.28.0",
|
||||
"strip-ansi": "^7.1.0",
|
||||
"strip-json-comments": "^3.1.1",
|
||||
"systeminformation": "^5.25.11",
|
||||
"tree-sitter-bash": "^0.25.0",
|
||||
"undici": "^7.10.0",
|
||||
@@ -17619,6 +17645,7 @@
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/sdk": "^0.12.0",
|
||||
"@google/gemini-cli-core": "file:../core",
|
||||
"@google/gemini-cli-devtools": "file:../devtools",
|
||||
"@google/genai": "1.41.0",
|
||||
"@iarna/toml": "^2.2.5",
|
||||
"@modelcontextprotocol/sdk": "^1.23.0",
|
||||
|
||||
@@ -302,7 +302,7 @@ const SETTINGS_SCHEMA = {
|
||||
label: 'Retry Fetch Errors',
|
||||
category: 'General',
|
||||
requiresRestart: false,
|
||||
default: false,
|
||||
default: true,
|
||||
description:
|
||||
'Retry on "exception TypeError: fetch failed sending request" errors.',
|
||||
showInDialog: false,
|
||||
|
||||
@@ -14,5 +14,5 @@
|
||||
"./package.json"
|
||||
],
|
||||
"exclude": ["node_modules", "dist"],
|
||||
"references": [{ "path": "../core" }]
|
||||
"references": [{ "path": "../core" }, { "path": "../devtools" }]
|
||||
}
|
||||
|
||||
@@ -43,12 +43,12 @@ export const DEFAULT_QUERY_STRING = 'Get Started!';
|
||||
/**
|
||||
* The default maximum number of conversational turns for an agent.
|
||||
*/
|
||||
export const DEFAULT_MAX_TURNS = 15;
|
||||
export const DEFAULT_MAX_TURNS = 30;
|
||||
|
||||
/**
|
||||
* The default maximum execution time for an agent in minutes.
|
||||
*/
|
||||
export const DEFAULT_MAX_TIME_MINUTES = 5;
|
||||
export const DEFAULT_MAX_TIME_MINUTES = 10;
|
||||
|
||||
/**
|
||||
* Represents the validated input parameters passed to an agent upon invocation.
|
||||
|
||||
@@ -958,8 +958,13 @@ describe('Server Config (config.ts)', () => {
|
||||
});
|
||||
|
||||
describe('Shell Tool Inactivity Timeout', () => {
|
||||
it('should default to 300000ms (300 seconds) when not provided', () => {
|
||||
it('should default to 600000ms (600 seconds) for non-interactive when not provided', () => {
|
||||
const config = new Config(baseParams);
|
||||
expect(config.getShellToolInactivityTimeout()).toBe(600000);
|
||||
});
|
||||
|
||||
it('should default to 300000ms (300 seconds) for interactive when not provided', () => {
|
||||
const config = new Config({ ...baseParams, interactive: true });
|
||||
expect(config.getShellToolInactivityTimeout()).toBe(300000);
|
||||
});
|
||||
|
||||
|
||||
@@ -852,8 +852,9 @@ export class Config {
|
||||
this.continueOnFailedApiCall = params.continueOnFailedApiCall ?? true;
|
||||
this.enableShellOutputEfficiency =
|
||||
params.enableShellOutputEfficiency ?? true;
|
||||
const defaultShellTimeout = this.interactive ? 300 : 600; // 5 min interactive, 10 min non-interactive
|
||||
this.shellToolInactivityTimeout =
|
||||
(params.shellToolInactivityTimeout ?? 300) * 1000; // 5 minutes
|
||||
(params.shellToolInactivityTimeout ?? defaultShellTimeout) * 1000;
|
||||
this.extensionManagement = params.extensionManagement ?? true;
|
||||
this.enableExtensionReloading = params.enableExtensionReloading ?? false;
|
||||
this.storage = new Storage(this.targetDir, this.sessionId);
|
||||
@@ -877,7 +878,7 @@ export class Config {
|
||||
this.outputSettings = {
|
||||
format: params.output?.format ?? OutputFormat.TEXT,
|
||||
};
|
||||
this.retryFetchErrors = params.retryFetchErrors ?? false;
|
||||
this.retryFetchErrors = params.retryFetchErrors ?? true;
|
||||
this.disableYoloMode = params.disableYoloMode ?? false;
|
||||
this.rawOutput = params.rawOutput ?? false;
|
||||
this.acceptRawOutputRisk = params.acceptRawOutputRisk ?? false;
|
||||
|
||||
@@ -594,7 +594,7 @@ For example:
|
||||
# Primary Workflows
|
||||
|
||||
## Development Lifecycle
|
||||
Operate using a **Research -> Strategy -> Execution** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
Operate using a **Research -> Strategy -> Execution -> Review** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
|
||||
1. **Research:** Systematically map the codebase and validate assumptions. Use \`grep_search\` and \`glob\` search tools extensively (in parallel if independent) to understand file structures, existing code patterns, and conventions. Use \`read_file\` to validate all assumptions. **Prioritize empirical reproduction of reported issues to confirm the failure state.**
|
||||
2. **Strategy:** Formulate a grounded plan based on your research. Share a concise summary of your strategy.
|
||||
@@ -602,6 +602,11 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
|
||||
- **Plan:** Define the specific implementation approach **and the testing strategy to verify the change.**
|
||||
- **Act:** Apply targeted, surgical changes strictly related to the sub-task. Use the available tools (e.g., \`replace\`, \`write_file\`, \`run_shell_command\`). Ensure changes are idiomatically complete and follow all workspace standards, even if it requires multiple tool calls. **Include necessary automated tests; a change is incomplete without verification logic.** Avoid unrelated refactoring or "cleanup" of outside code. Before making manual code changes, check if an ecosystem tool (like 'eslint --fix', 'prettier --write', 'go fmt', 'cargo fmt') is available in the project to perform the task automatically.
|
||||
- **Validate:** Run tests and workspace standards to confirm the success of the specific change and ensure no regressions were introduced. After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project. If unsure about these commands, you can ask the user if they'd like you to run them and if so how to.
|
||||
4. **Review:** After any body of work where you write more than one file or make non-trivial code changes, you MUST execute a final review step:
|
||||
- **Analyze Diff:** If in a git repository, run \`git diff\` or \`git diff HEAD\` to visualize the exact changes made.
|
||||
- **Verify Completeness:** Compare the work done against the user's original prompt. Ensure the intent was completely satisfied and the codebase has landed in the desired end state. If there are gaps, formulate follow-up tasks to address them.
|
||||
- **Code Quality & Linting:** Verify that the generated code matches the codebase's linter preferences and any explicitly stated user preferences.
|
||||
- **Targeted Refinements:** Apply best practice final touches. Look for opportunities to de-duplicate logic, break up excessively large functions into more focused ones, and generally manage code complexity. Follow general programming and ecosystem-specific best practices, keeping in mind that explicit user preferences take precedence.
|
||||
|
||||
**Validation is the only path to finality.** Never assume success or settle for unverified changes. Rigorous, exhaustive verification is mandatory; it prevents the compounding cost of diagnosing failures later. A task is only complete when the behavioral correctness of the change has been verified and its structural integrity is confirmed within the full project context. Prioritize comprehensive validation above all else, utilizing redirection and focused analysis to manage high-output tasks without sacrificing depth. Never sacrifice validation rigor for the sake of brevity or to minimize tool-call overhead; partial or isolated checks are insufficient when more comprehensive validation is possible.
|
||||
|
||||
@@ -734,7 +739,7 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
# Primary Workflows
|
||||
|
||||
## Development Lifecycle
|
||||
Operate using a **Research -> Strategy -> Execution** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
Operate using a **Research -> Strategy -> Execution -> Review** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
|
||||
1. **Research:** Systematically map the codebase and validate assumptions. Utilize specialized sub-agents (e.g., \`codebase_investigator\`) as the primary mechanism for initial discovery when the task involves **complex refactoring, codebase exploration or system-wide analysis**. For **simple, targeted searches** (like finding a specific function name, file path, or variable declaration), use \`grep_search\` or \`glob\` directly in parallel. Use \`read_file\` to validate all assumptions. **Prioritize empirical reproduction of reported issues to confirm the failure state.**
|
||||
2. **Strategy:** Formulate a grounded plan based on your research.
|
||||
@@ -742,6 +747,11 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
|
||||
- **Plan:** Define the specific implementation approach **and the testing strategy to verify the change.**
|
||||
- **Act:** Apply targeted, surgical changes strictly related to the sub-task. Use the available tools (e.g., \`replace\`, \`write_file\`, \`run_shell_command\`). Ensure changes are idiomatically complete and follow all workspace standards, even if it requires multiple tool calls. **Include necessary automated tests; a change is incomplete without verification logic.** Avoid unrelated refactoring or "cleanup" of outside code. Before making manual code changes, check if an ecosystem tool (like 'eslint --fix', 'prettier --write', 'go fmt', 'cargo fmt') is available in the project to perform the task automatically.
|
||||
- **Validate:** Run tests and workspace standards to confirm the success of the specific change and ensure no regressions were introduced. After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project.
|
||||
4. **Review:** After any body of work where you write more than one file or make non-trivial code changes, you MUST execute a final review step:
|
||||
- **Analyze Diff:** If in a git repository, run \`git diff\` or \`git diff HEAD\` to visualize the exact changes made.
|
||||
- **Verify Completeness:** Compare the work done against the user's original prompt. Ensure the intent was completely satisfied and the codebase has landed in the desired end state. If there are gaps, formulate follow-up tasks to address them.
|
||||
- **Code Quality & Linting:** Verify that the generated code matches the codebase's linter preferences and any explicitly stated user preferences.
|
||||
- **Targeted Refinements:** Apply best practice final touches. Look for opportunities to de-duplicate logic, break up excessively large functions into more focused ones, and generally manage code complexity. Follow general programming and ecosystem-specific best practices, keeping in mind that explicit user preferences take precedence.
|
||||
|
||||
**Validation is the only path to finality.** Never assume success or settle for unverified changes. Rigorous, exhaustive verification is mandatory; it prevents the compounding cost of diagnosing failures later. A task is only complete when the behavioral correctness of the change has been verified and its structural integrity is confirmed within the full project context. Prioritize comprehensive validation above all else, utilizing redirection and focused analysis to manage high-output tasks without sacrificing depth. Never sacrifice validation rigor for the sake of brevity or to minimize tool-call overhead; partial or isolated checks are insufficient when more comprehensive validation is possible.
|
||||
|
||||
@@ -789,7 +799,51 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
|
||||
|
||||
## Interaction Details
|
||||
- **Help Command:** The user can use '/help' to display help information.
|
||||
- **Feedback:** To report a bug or provide feedback, please use the /bug command."
|
||||
- **Feedback:** To report a bug or provide feedback, please use the /bug command.
|
||||
|
||||
## File Creation (Non-Interactive)
|
||||
- **Prefer write_file over shell heredocs** for creating or overwriting files. The write_file tool is more reliable and avoids shell escaping issues.
|
||||
- Only use shell heredocs when you need to append to a file or when the content depends on shell variable expansion.
|
||||
- If you must use a heredoc, always use the full syntax: \`cat << 'EOF' > filename\` — never omit \`cat\`.
|
||||
|
||||
## Background Services (Non-Interactive)
|
||||
- To start a service that must persist across turns, use: \`nohup <command> > /tmp/<service>.log 2>&1 &\`
|
||||
- After starting, verify the process is running:
|
||||
1. \`echo $!\` to capture the PID immediately after starting
|
||||
2. \`sleep 1 && kill -0 <PID>\` to confirm it's still alive
|
||||
3. Check the log file for startup errors: \`cat /tmp/<service>.log\`
|
||||
- If a service fails to start, check the log file before retrying.
|
||||
- For services that need time to initialize (databases, web servers), add a brief \`sleep 2\` and verify the port is open before proceeding.
|
||||
|
||||
## Error Recovery (Non-Interactive)
|
||||
- **Don't blindly retry:** When a tool call fails, analyze the error before retrying. Do not immediately retry with the same arguments.
|
||||
- **Web fetch failures:** If web_fetch fails, try simplifying the prompt or use google_web_search as an alternative to find the information.
|
||||
- **Shell failures:** Check error codes and run diagnostic commands before retrying. For compilation errors, fix one issue at a time rather than attempting multiple fixes simultaneously.
|
||||
- **Maximum retries:** Attempt the same approach at most 2 times. If it fails twice, try an alternative strategy or tool.
|
||||
- **Avoid loops:** If you find yourself repeating the same sequence of actions, stop and reassess your approach.
|
||||
|
||||
## Missing Commands / "command not found"
|
||||
- When a command is not found, install the package that provides it before retrying.
|
||||
- Use \`apt-get install -y <package>\` (Debian/Ubuntu) or \`yum install -y <package>\` (RHEL/CentOS).
|
||||
- Common mappings:
|
||||
- pgrep, ps, pidof → procps
|
||||
- ss → iproute2
|
||||
- netstat, ifconfig → net-tools
|
||||
- curl → curl
|
||||
- jq → jq
|
||||
- dig, nslookup → dnsutils (or bind-utils on RHEL)
|
||||
- ip → iproute2
|
||||
- lsof → lsof
|
||||
- wget → wget
|
||||
- tree → tree
|
||||
- zip/unzip → zip / unzip
|
||||
- If you don't know the package name, try \`apt-cache search <command>\` or \`yum provides <command>\`.
|
||||
|
||||
## Process Verification Without pgrep
|
||||
- If pgrep/ps are unavailable and you can't install them, verify processes using:
|
||||
- \`ls /proc/[PID]\` to check if a PID is still running
|
||||
- \`kill -0 <PID>\` to test if a process exists (returns 0 if it does)
|
||||
- \`cat /proc/<PID>/cmdline\` to inspect what a process is running"
|
||||
`;
|
||||
|
||||
exports[`Core System Prompt (prompts.ts) > should handle CodebaseInvestigator with tools=grep_search,glob 1`] = `
|
||||
@@ -856,7 +910,7 @@ Use the following guidelines to optimize your search and read patterns.
|
||||
# Primary Workflows
|
||||
|
||||
## Development Lifecycle
|
||||
Operate using a **Research -> Strategy -> Execution** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
Operate using a **Research -> Strategy -> Execution -> Review** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
|
||||
1. **Research:** Systematically map the codebase and validate assumptions. Use \`grep_search\` and \`glob\` search tools extensively (in parallel if independent) to understand file structures, existing code patterns, and conventions. Use \`read_file\` to validate all assumptions. **Prioritize empirical reproduction of reported issues to confirm the failure state.**
|
||||
2. **Strategy:** Formulate a grounded plan based on your research.
|
||||
@@ -864,6 +918,11 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
|
||||
- **Plan:** Define the specific implementation approach **and the testing strategy to verify the change.**
|
||||
- **Act:** Apply targeted, surgical changes strictly related to the sub-task. Use the available tools (e.g., \`replace\`, \`write_file\`, \`run_shell_command\`). Ensure changes are idiomatically complete and follow all workspace standards, even if it requires multiple tool calls. **Include necessary automated tests; a change is incomplete without verification logic.** Avoid unrelated refactoring or "cleanup" of outside code. Before making manual code changes, check if an ecosystem tool (like 'eslint --fix', 'prettier --write', 'go fmt', 'cargo fmt') is available in the project to perform the task automatically.
|
||||
- **Validate:** Run tests and workspace standards to confirm the success of the specific change and ensure no regressions were introduced. After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project.
|
||||
4. **Review:** After any body of work where you write more than one file or make non-trivial code changes, you MUST execute a final review step:
|
||||
- **Analyze Diff:** If in a git repository, run \`git diff\` or \`git diff HEAD\` to visualize the exact changes made.
|
||||
- **Verify Completeness:** Compare the work done against the user's original prompt. Ensure the intent was completely satisfied and the codebase has landed in the desired end state. If there are gaps, formulate follow-up tasks to address them.
|
||||
- **Code Quality & Linting:** Verify that the generated code matches the codebase's linter preferences and any explicitly stated user preferences.
|
||||
- **Targeted Refinements:** Apply best practice final touches. Look for opportunities to de-duplicate logic, break up excessively large functions into more focused ones, and generally manage code complexity. Follow general programming and ecosystem-specific best practices, keeping in mind that explicit user preferences take precedence.
|
||||
|
||||
**Validation is the only path to finality.** Never assume success or settle for unverified changes. Rigorous, exhaustive verification is mandatory; it prevents the compounding cost of diagnosing failures later. A task is only complete when the behavioral correctness of the change has been verified and its structural integrity is confirmed within the full project context. Prioritize comprehensive validation above all else, utilizing redirection and focused analysis to manage high-output tasks without sacrificing depth. Never sacrifice validation rigor for the sake of brevity or to minimize tool-call overhead; partial or isolated checks are insufficient when more comprehensive validation is possible.
|
||||
|
||||
@@ -911,7 +970,51 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
|
||||
|
||||
## Interaction Details
|
||||
- **Help Command:** The user can use '/help' to display help information.
|
||||
- **Feedback:** To report a bug or provide feedback, please use the /bug command."
|
||||
- **Feedback:** To report a bug or provide feedback, please use the /bug command.
|
||||
|
||||
## File Creation (Non-Interactive)
|
||||
- **Prefer write_file over shell heredocs** for creating or overwriting files. The write_file tool is more reliable and avoids shell escaping issues.
|
||||
- Only use shell heredocs when you need to append to a file or when the content depends on shell variable expansion.
|
||||
- If you must use a heredoc, always use the full syntax: \`cat << 'EOF' > filename\` — never omit \`cat\`.
|
||||
|
||||
## Background Services (Non-Interactive)
|
||||
- To start a service that must persist across turns, use: \`nohup <command> > /tmp/<service>.log 2>&1 &\`
|
||||
- After starting, verify the process is running:
|
||||
1. \`echo $!\` to capture the PID immediately after starting
|
||||
2. \`sleep 1 && kill -0 <PID>\` to confirm it's still alive
|
||||
3. Check the log file for startup errors: \`cat /tmp/<service>.log\`
|
||||
- If a service fails to start, check the log file before retrying.
|
||||
- For services that need time to initialize (databases, web servers), add a brief \`sleep 2\` and verify the port is open before proceeding.
|
||||
|
||||
## Error Recovery (Non-Interactive)
|
||||
- **Don't blindly retry:** When a tool call fails, analyze the error before retrying. Do not immediately retry with the same arguments.
|
||||
- **Web fetch failures:** If web_fetch fails, try simplifying the prompt or use google_web_search as an alternative to find the information.
|
||||
- **Shell failures:** Check error codes and run diagnostic commands before retrying. For compilation errors, fix one issue at a time rather than attempting multiple fixes simultaneously.
|
||||
- **Maximum retries:** Attempt the same approach at most 2 times. If it fails twice, try an alternative strategy or tool.
|
||||
- **Avoid loops:** If you find yourself repeating the same sequence of actions, stop and reassess your approach.
|
||||
|
||||
## Missing Commands / "command not found"
|
||||
- When a command is not found, install the package that provides it before retrying.
|
||||
- Use \`apt-get install -y <package>\` (Debian/Ubuntu) or \`yum install -y <package>\` (RHEL/CentOS).
|
||||
- Common mappings:
|
||||
- pgrep, ps, pidof → procps
|
||||
- ss → iproute2
|
||||
- netstat, ifconfig → net-tools
|
||||
- curl → curl
|
||||
- jq → jq
|
||||
- dig, nslookup → dnsutils (or bind-utils on RHEL)
|
||||
- ip → iproute2
|
||||
- lsof → lsof
|
||||
- wget → wget
|
||||
- tree → tree
|
||||
- zip/unzip → zip / unzip
|
||||
- If you don't know the package name, try \`apt-cache search <command>\` or \`yum provides <command>\`.
|
||||
|
||||
## Process Verification Without pgrep
|
||||
- If pgrep/ps are unavailable and you can't install them, verify processes using:
|
||||
- \`ls /proc/[PID]\` to check if a PID is still running
|
||||
- \`kill -0 <PID>\` to test if a process exists (returns 0 if it does)
|
||||
- \`cat /proc/<PID>/cmdline\` to inspect what a process is running"
|
||||
`;
|
||||
|
||||
exports[`Core System Prompt (prompts.ts) > should handle git instructions when isGitRepository=false 1`] = `
|
||||
@@ -1480,7 +1583,7 @@ You have access to the following specialized skills. To activate a skill and rec
|
||||
# Primary Workflows
|
||||
|
||||
## Development Lifecycle
|
||||
Operate using a **Research -> Strategy -> Execution** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
Operate using a **Research -> Strategy -> Execution -> Review** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
|
||||
1. **Research:** Systematically map the codebase and validate assumptions. Use \`grep_search\` and \`glob\` search tools extensively (in parallel if independent) to understand file structures, existing code patterns, and conventions. Use \`read_file\` to validate all assumptions. **Prioritize empirical reproduction of reported issues to confirm the failure state.**
|
||||
2. **Strategy:** Formulate a grounded plan based on your research. Share a concise summary of your strategy.
|
||||
@@ -1488,6 +1591,11 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
|
||||
- **Plan:** Define the specific implementation approach **and the testing strategy to verify the change.**
|
||||
- **Act:** Apply targeted, surgical changes strictly related to the sub-task. Use the available tools (e.g., \`replace\`, \`write_file\`, \`run_shell_command\`). Ensure changes are idiomatically complete and follow all workspace standards, even if it requires multiple tool calls. **Include necessary automated tests; a change is incomplete without verification logic.** Avoid unrelated refactoring or "cleanup" of outside code. Before making manual code changes, check if an ecosystem tool (like 'eslint --fix', 'prettier --write', 'go fmt', 'cargo fmt') is available in the project to perform the task automatically.
|
||||
- **Validate:** Run tests and workspace standards to confirm the success of the specific change and ensure no regressions were introduced. After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project. If unsure about these commands, you can ask the user if they'd like you to run them and if so how to.
|
||||
4. **Review:** After any body of work where you write more than one file or make non-trivial code changes, you MUST execute a final review step:
|
||||
- **Analyze Diff:** If in a git repository, run \`git diff\` or \`git diff HEAD\` to visualize the exact changes made.
|
||||
- **Verify Completeness:** Compare the work done against the user's original prompt. Ensure the intent was completely satisfied and the codebase has landed in the desired end state. If there are gaps, formulate follow-up tasks to address them.
|
||||
- **Code Quality & Linting:** Verify that the generated code matches the codebase's linter preferences and any explicitly stated user preferences.
|
||||
- **Targeted Refinements:** Apply best practice final touches. Look for opportunities to de-duplicate logic, break up excessively large functions into more focused ones, and generally manage code complexity. Follow general programming and ecosystem-specific best practices, keeping in mind that explicit user preferences take precedence.
|
||||
|
||||
**Validation is the only path to finality.** Never assume success or settle for unverified changes. Rigorous, exhaustive verification is mandatory; it prevents the compounding cost of diagnosing failures later. A task is only complete when the behavioral correctness of the change has been verified and its structural integrity is confirmed within the full project context. Prioritize comprehensive validation above all else, utilizing redirection and focused analysis to manage high-output tasks without sacrificing depth. Never sacrifice validation rigor for the sake of brevity or to minimize tool-call overhead; partial or isolated checks are insufficient when more comprehensive validation is possible.
|
||||
|
||||
@@ -1619,7 +1727,7 @@ For example:
|
||||
# Primary Workflows
|
||||
|
||||
## Development Lifecycle
|
||||
Operate using a **Research -> Strategy -> Execution** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
Operate using a **Research -> Strategy -> Execution -> Review** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
|
||||
1. **Research:** Systematically map the codebase and validate assumptions. Use \`grep_search\` and \`glob\` search tools extensively (in parallel if independent) to understand file structures, existing code patterns, and conventions. Use \`read_file\` to validate all assumptions. **Prioritize empirical reproduction of reported issues to confirm the failure state.**
|
||||
2. **Strategy:** Formulate a grounded plan based on your research. Share a concise summary of your strategy.
|
||||
@@ -1627,6 +1735,11 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
|
||||
- **Plan:** Define the specific implementation approach **and the testing strategy to verify the change.**
|
||||
- **Act:** Apply targeted, surgical changes strictly related to the sub-task. Use the available tools (e.g., \`replace\`, \`write_file\`, \`run_shell_command\`). Ensure changes are idiomatically complete and follow all workspace standards, even if it requires multiple tool calls. **Include necessary automated tests; a change is incomplete without verification logic.** Avoid unrelated refactoring or "cleanup" of outside code. Before making manual code changes, check if an ecosystem tool (like 'eslint --fix', 'prettier --write', 'go fmt', 'cargo fmt') is available in the project to perform the task automatically.
|
||||
- **Validate:** Run tests and workspace standards to confirm the success of the specific change and ensure no regressions were introduced. After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project. If unsure about these commands, you can ask the user if they'd like you to run them and if so how to.
|
||||
4. **Review:** After any body of work where you write more than one file or make non-trivial code changes, you MUST execute a final review step:
|
||||
- **Analyze Diff:** If in a git repository, run \`git diff\` or \`git diff HEAD\` to visualize the exact changes made.
|
||||
- **Verify Completeness:** Compare the work done against the user's original prompt. Ensure the intent was completely satisfied and the codebase has landed in the desired end state. If there are gaps, formulate follow-up tasks to address them.
|
||||
- **Code Quality & Linting:** Verify that the generated code matches the codebase's linter preferences and any explicitly stated user preferences.
|
||||
- **Targeted Refinements:** Apply best practice final touches. Look for opportunities to de-duplicate logic, break up excessively large functions into more focused ones, and generally manage code complexity. Follow general programming and ecosystem-specific best practices, keeping in mind that explicit user preferences take precedence.
|
||||
|
||||
**Validation is the only path to finality.** Never assume success or settle for unverified changes. Rigorous, exhaustive verification is mandatory; it prevents the compounding cost of diagnosing failures later. A task is only complete when the behavioral correctness of the change has been verified and its structural integrity is confirmed within the full project context. Prioritize comprehensive validation above all else, utilizing redirection and focused analysis to manage high-output tasks without sacrificing depth. Never sacrifice validation rigor for the sake of brevity or to minimize tool-call overhead; partial or isolated checks are insufficient when more comprehensive validation is possible.
|
||||
|
||||
@@ -1762,7 +1875,7 @@ For example:
|
||||
# Primary Workflows
|
||||
|
||||
## Development Lifecycle
|
||||
Operate using a **Research -> Strategy -> Execution** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
Operate using a **Research -> Strategy -> Execution -> Review** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
|
||||
1. **Research:** Systematically map the codebase and validate assumptions. Use \`grep_search\` and \`glob\` search tools extensively (in parallel if independent) to understand file structures, existing code patterns, and conventions. Use \`read_file\` to validate all assumptions. **Prioritize empirical reproduction of reported issues to confirm the failure state.**
|
||||
2. **Strategy:** Formulate a grounded plan based on your research. Share a concise summary of your strategy.
|
||||
@@ -1770,6 +1883,11 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
|
||||
- **Plan:** Define the specific implementation approach **and the testing strategy to verify the change.**
|
||||
- **Act:** Apply targeted, surgical changes strictly related to the sub-task. Use the available tools (e.g., \`replace\`, \`write_file\`, \`run_shell_command\`). Ensure changes are idiomatically complete and follow all workspace standards, even if it requires multiple tool calls. **Include necessary automated tests; a change is incomplete without verification logic.** Avoid unrelated refactoring or "cleanup" of outside code. Before making manual code changes, check if an ecosystem tool (like 'eslint --fix', 'prettier --write', 'go fmt', 'cargo fmt') is available in the project to perform the task automatically.
|
||||
- **Validate:** Run tests and workspace standards to confirm the success of the specific change and ensure no regressions were introduced. After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project. If unsure about these commands, you can ask the user if they'd like you to run them and if so how to.
|
||||
4. **Review:** After any body of work where you write more than one file or make non-trivial code changes, you MUST execute a final review step:
|
||||
- **Analyze Diff:** If in a git repository, run \`git diff\` or \`git diff HEAD\` to visualize the exact changes made.
|
||||
- **Verify Completeness:** Compare the work done against the user's original prompt. Ensure the intent was completely satisfied and the codebase has landed in the desired end state. If there are gaps, formulate follow-up tasks to address them.
|
||||
- **Code Quality & Linting:** Verify that the generated code matches the codebase's linter preferences and any explicitly stated user preferences.
|
||||
- **Targeted Refinements:** Apply best practice final touches. Look for opportunities to de-duplicate logic, break up excessively large functions into more focused ones, and generally manage code complexity. Follow general programming and ecosystem-specific best practices, keeping in mind that explicit user preferences take precedence.
|
||||
|
||||
**Validation is the only path to finality.** Never assume success or settle for unverified changes. Rigorous, exhaustive verification is mandatory; it prevents the compounding cost of diagnosing failures later. A task is only complete when the behavioral correctness of the change has been verified and its structural integrity is confirmed within the full project context. Prioritize comprehensive validation above all else, utilizing redirection and focused analysis to manage high-output tasks without sacrificing depth. Never sacrifice validation rigor for the sake of brevity or to minimize tool-call overhead; partial or isolated checks are insufficient when more comprehensive validation is possible.
|
||||
|
||||
@@ -1905,7 +2023,7 @@ For example:
|
||||
# Primary Workflows
|
||||
|
||||
## Development Lifecycle
|
||||
Operate using a **Research -> Strategy -> Execution** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
Operate using a **Research -> Strategy -> Execution -> Review** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
|
||||
1. **Research:** Systematically map the codebase and validate assumptions. Use \`grep_search\` and \`glob\` search tools extensively (in parallel if independent) to understand file structures, existing code patterns, and conventions. Use \`read_file\` to validate all assumptions. **Prioritize empirical reproduction of reported issues to confirm the failure state.**
|
||||
2. **Strategy:** Formulate a grounded plan based on your research. Share a concise summary of your strategy.
|
||||
@@ -1913,6 +2031,11 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
|
||||
- **Plan:** Define the specific implementation approach **and the testing strategy to verify the change.**
|
||||
- **Act:** Apply targeted, surgical changes strictly related to the sub-task. Use the available tools (e.g., \`replace\`, \`write_file\`, \`run_shell_command\`). Ensure changes are idiomatically complete and follow all workspace standards, even if it requires multiple tool calls. **Include necessary automated tests; a change is incomplete without verification logic.** Avoid unrelated refactoring or "cleanup" of outside code. Before making manual code changes, check if an ecosystem tool (like 'eslint --fix', 'prettier --write', 'go fmt', 'cargo fmt') is available in the project to perform the task automatically.
|
||||
- **Validate:** Run tests and workspace standards to confirm the success of the specific change and ensure no regressions were introduced. After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project. If unsure about these commands, you can ask the user if they'd like you to run them and if so how to.
|
||||
4. **Review:** After any body of work where you write more than one file or make non-trivial code changes, you MUST execute a final review step:
|
||||
- **Analyze Diff:** If in a git repository, run \`git diff\` or \`git diff HEAD\` to visualize the exact changes made.
|
||||
- **Verify Completeness:** Compare the work done against the user's original prompt. Ensure the intent was completely satisfied and the codebase has landed in the desired end state. If there are gaps, formulate follow-up tasks to address them.
|
||||
- **Code Quality & Linting:** Verify that the generated code matches the codebase's linter preferences and any explicitly stated user preferences.
|
||||
- **Targeted Refinements:** Apply best practice final touches. Look for opportunities to de-duplicate logic, break up excessively large functions into more focused ones, and generally manage code complexity. Follow general programming and ecosystem-specific best practices, keeping in mind that explicit user preferences take precedence.
|
||||
|
||||
**Validation is the only path to finality.** Never assume success or settle for unverified changes. Rigorous, exhaustive verification is mandatory; it prevents the compounding cost of diagnosing failures later. A task is only complete when the behavioral correctness of the change has been verified and its structural integrity is confirmed within the full project context. Prioritize comprehensive validation above all else, utilizing redirection and focused analysis to manage high-output tasks without sacrificing depth. Never sacrifice validation rigor for the sake of brevity or to minimize tool-call overhead; partial or isolated checks are insufficient when more comprehensive validation is possible.
|
||||
|
||||
@@ -2044,7 +2167,7 @@ For example:
|
||||
# Primary Workflows
|
||||
|
||||
## Development Lifecycle
|
||||
Operate using a **Research -> Strategy -> Execution** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
Operate using a **Research -> Strategy -> Execution -> Review** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
|
||||
1. **Research:** Systematically map the codebase and validate assumptions. Use \`grep_search\` and \`glob\` search tools extensively (in parallel if independent) to understand file structures, existing code patterns, and conventions. Use \`read_file\` to validate all assumptions. **Prioritize empirical reproduction of reported issues to confirm the failure state.**
|
||||
2. **Strategy:** Formulate a grounded plan based on your research. Share a concise summary of your strategy.
|
||||
@@ -2052,6 +2175,11 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
|
||||
- **Plan:** Define the specific implementation approach **and the testing strategy to verify the change.**
|
||||
- **Act:** Apply targeted, surgical changes strictly related to the sub-task. Use the available tools (e.g., \`replace\`, \`write_file\`, \`run_shell_command\`). Ensure changes are idiomatically complete and follow all workspace standards, even if it requires multiple tool calls. **Include necessary automated tests; a change is incomplete without verification logic.** Avoid unrelated refactoring or "cleanup" of outside code. Before making manual code changes, check if an ecosystem tool (like 'eslint --fix', 'prettier --write', 'go fmt', 'cargo fmt') is available in the project to perform the task automatically.
|
||||
- **Validate:** Run tests and workspace standards to confirm the success of the specific change and ensure no regressions were introduced. After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project. If unsure about these commands, you can ask the user if they'd like you to run them and if so how to.
|
||||
4. **Review:** After any body of work where you write more than one file or make non-trivial code changes, you MUST execute a final review step:
|
||||
- **Analyze Diff:** If in a git repository, run \`git diff\` or \`git diff HEAD\` to visualize the exact changes made.
|
||||
- **Verify Completeness:** Compare the work done against the user's original prompt. Ensure the intent was completely satisfied and the codebase has landed in the desired end state. If there are gaps, formulate follow-up tasks to address them.
|
||||
- **Code Quality & Linting:** Verify that the generated code matches the codebase's linter preferences and any explicitly stated user preferences.
|
||||
- **Targeted Refinements:** Apply best practice final touches. Look for opportunities to de-duplicate logic, break up excessively large functions into more focused ones, and generally manage code complexity. Follow general programming and ecosystem-specific best practices, keeping in mind that explicit user preferences take precedence.
|
||||
|
||||
**Validation is the only path to finality.** Never assume success or settle for unverified changes. Rigorous, exhaustive verification is mandatory; it prevents the compounding cost of diagnosing failures later. A task is only complete when the behavioral correctness of the change has been verified and its structural integrity is confirmed within the full project context. Prioritize comprehensive validation above all else, utilizing redirection and focused analysis to manage high-output tasks without sacrificing depth. Never sacrifice validation rigor for the sake of brevity or to minimize tool-call overhead; partial or isolated checks are insufficient when more comprehensive validation is possible.
|
||||
|
||||
@@ -2183,7 +2311,7 @@ For example:
|
||||
# Primary Workflows
|
||||
|
||||
## Development Lifecycle
|
||||
Operate using a **Research -> Strategy -> Execution** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
Operate using a **Research -> Strategy -> Execution -> Review** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
|
||||
1. **Research:** Systematically map the codebase and validate assumptions. Use search tools extensively to understand file structures, existing code patterns, and conventions. Use \`read_file\` to validate all assumptions. **Prioritize empirical reproduction of reported issues to confirm the failure state.** If the request is ambiguous, broad in scope, or involves creating a new feature/application, you MUST use the \`enter_plan_mode\` tool to design your approach before making changes. Do NOT use Plan Mode for straightforward bug fixes, answering questions, or simple inquiries.
|
||||
2. **Strategy:** Formulate a grounded plan based on your research. Share a concise summary of your strategy.
|
||||
@@ -2191,6 +2319,11 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
|
||||
- **Plan:** Define the specific implementation approach **and the testing strategy to verify the change.**
|
||||
- **Act:** Apply targeted, surgical changes strictly related to the sub-task. Use the available tools (e.g., \`replace\`, \`write_file\`, \`run_shell_command\`). Ensure changes are idiomatically complete and follow all workspace standards, even if it requires multiple tool calls. **Include necessary automated tests; a change is incomplete without verification logic.** Avoid unrelated refactoring or "cleanup" of outside code. Before making manual code changes, check if an ecosystem tool (like 'eslint --fix', 'prettier --write', 'go fmt', 'cargo fmt') is available in the project to perform the task automatically.
|
||||
- **Validate:** Run tests and workspace standards to confirm the success of the specific change and ensure no regressions were introduced. After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project. If unsure about these commands, you can ask the user if they'd like you to run them and if so how to.
|
||||
4. **Review:** After any body of work where you write more than one file or make non-trivial code changes, you MUST execute a final review step:
|
||||
- **Analyze Diff:** If in a git repository, run \`git diff\` or \`git diff HEAD\` to visualize the exact changes made.
|
||||
- **Verify Completeness:** Compare the work done against the user's original prompt. Ensure the intent was completely satisfied and the codebase has landed in the desired end state. If there are gaps, formulate follow-up tasks to address them.
|
||||
- **Code Quality & Linting:** Verify that the generated code matches the codebase's linter preferences and any explicitly stated user preferences.
|
||||
- **Targeted Refinements:** Apply best practice final touches. Look for opportunities to de-duplicate logic, break up excessively large functions into more focused ones, and generally manage code complexity. Follow general programming and ecosystem-specific best practices, keeping in mind that explicit user preferences take precedence.
|
||||
|
||||
**Validation is the only path to finality.** Never assume success or settle for unverified changes. Rigorous, exhaustive verification is mandatory; it prevents the compounding cost of diagnosing failures later. A task is only complete when the behavioral correctness of the change has been verified and its structural integrity is confirmed within the full project context. Prioritize comprehensive validation above all else, utilizing redirection and focused analysis to manage high-output tasks without sacrificing depth. Never sacrifice validation rigor for the sake of brevity or to minimize tool-call overhead; partial or isolated checks are insufficient when more comprehensive validation is possible.
|
||||
|
||||
@@ -2321,7 +2454,7 @@ For example:
|
||||
# Primary Workflows
|
||||
|
||||
## Development Lifecycle
|
||||
Operate using a **Research -> Strategy -> Execution** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
Operate using a **Research -> Strategy -> Execution -> Review** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
|
||||
1. **Research:** Systematically map the codebase and validate assumptions. Use \`grep_search\` and \`glob\` search tools extensively (in parallel if independent) to understand file structures, existing code patterns, and conventions. Use \`read_file\` to validate all assumptions. **Prioritize empirical reproduction of reported issues to confirm the failure state.**
|
||||
2. **Strategy:** Formulate a grounded plan based on your research. Share a concise summary of your strategy.
|
||||
@@ -2329,6 +2462,11 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
|
||||
- **Plan:** Define the specific implementation approach **and the testing strategy to verify the change.**
|
||||
- **Act:** Apply targeted, surgical changes strictly related to the sub-task. Use the available tools (e.g., \`replace\`, \`write_file\`, \`run_shell_command\`). Ensure changes are idiomatically complete and follow all workspace standards, even if it requires multiple tool calls. **Include necessary automated tests; a change is incomplete without verification logic.** Avoid unrelated refactoring or "cleanup" of outside code. Before making manual code changes, check if an ecosystem tool (like 'eslint --fix', 'prettier --write', 'go fmt', 'cargo fmt') is available in the project to perform the task automatically.
|
||||
- **Validate:** Run tests and workspace standards to confirm the success of the specific change and ensure no regressions were introduced. After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project. If unsure about these commands, you can ask the user if they'd like you to run them and if so how to.
|
||||
4. **Review:** After any body of work where you write more than one file or make non-trivial code changes, you MUST execute a final review step:
|
||||
- **Analyze Diff:** If in a git repository, run \`git diff\` or \`git diff HEAD\` to visualize the exact changes made.
|
||||
- **Verify Completeness:** Compare the work done against the user's original prompt. Ensure the intent was completely satisfied and the codebase has landed in the desired end state. If there are gaps, formulate follow-up tasks to address them.
|
||||
- **Code Quality & Linting:** Verify that the generated code matches the codebase's linter preferences and any explicitly stated user preferences.
|
||||
- **Targeted Refinements:** Apply best practice final touches. Look for opportunities to de-duplicate logic, break up excessively large functions into more focused ones, and generally manage code complexity. Follow general programming and ecosystem-specific best practices, keeping in mind that explicit user preferences take precedence.
|
||||
|
||||
**Validation is the only path to finality.** Never assume success or settle for unverified changes. Rigorous, exhaustive verification is mandatory; it prevents the compounding cost of diagnosing failures later. A task is only complete when the behavioral correctness of the change has been verified and its structural integrity is confirmed within the full project context. Prioritize comprehensive validation above all else, utilizing redirection and focused analysis to manage high-output tasks without sacrificing depth. Never sacrifice validation rigor for the sake of brevity or to minimize tool-call overhead; partial or isolated checks are insufficient when more comprehensive validation is possible.
|
||||
|
||||
@@ -2701,7 +2839,7 @@ For example:
|
||||
# Primary Workflows
|
||||
|
||||
## Development Lifecycle
|
||||
Operate using a **Research -> Strategy -> Execution** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
Operate using a **Research -> Strategy -> Execution -> Review** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
|
||||
1. **Research:** Systematically map the codebase and validate assumptions. Use \`grep_search\` and \`glob\` search tools extensively (in parallel if independent) to understand file structures, existing code patterns, and conventions. Use \`read_file\` to validate all assumptions. **Prioritize empirical reproduction of reported issues to confirm the failure state.**
|
||||
2. **Strategy:** Formulate a grounded plan based on your research. Share a concise summary of your strategy.
|
||||
@@ -2709,6 +2847,11 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
|
||||
- **Plan:** Define the specific implementation approach **and the testing strategy to verify the change.**
|
||||
- **Act:** Apply targeted, surgical changes strictly related to the sub-task. Use the available tools (e.g., \`replace\`, \`write_file\`, \`run_shell_command\`). Ensure changes are idiomatically complete and follow all workspace standards, even if it requires multiple tool calls. **Include necessary automated tests; a change is incomplete without verification logic.** Avoid unrelated refactoring or "cleanup" of outside code. Before making manual code changes, check if an ecosystem tool (like 'eslint --fix', 'prettier --write', 'go fmt', 'cargo fmt') is available in the project to perform the task automatically.
|
||||
- **Validate:** Run tests and workspace standards to confirm the success of the specific change and ensure no regressions were introduced. After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project. If unsure about these commands, you can ask the user if they'd like you to run them and if so how to.
|
||||
4. **Review:** After any body of work where you write more than one file or make non-trivial code changes, you MUST execute a final review step:
|
||||
- **Analyze Diff:** If in a git repository, run \`git diff\` or \`git diff HEAD\` to visualize the exact changes made.
|
||||
- **Verify Completeness:** Compare the work done against the user's original prompt. Ensure the intent was completely satisfied and the codebase has landed in the desired end state. If there are gaps, formulate follow-up tasks to address them.
|
||||
- **Code Quality & Linting:** Verify that the generated code matches the codebase's linter preferences and any explicitly stated user preferences.
|
||||
- **Targeted Refinements:** Apply best practice final touches. Look for opportunities to de-duplicate logic, break up excessively large functions into more focused ones, and generally manage code complexity. Follow general programming and ecosystem-specific best practices, keeping in mind that explicit user preferences take precedence.
|
||||
|
||||
**Validation is the only path to finality.** Never assume success or settle for unverified changes. Rigorous, exhaustive verification is mandatory; it prevents the compounding cost of diagnosing failures later. A task is only complete when the behavioral correctness of the change has been verified and its structural integrity is confirmed within the full project context. Prioritize comprehensive validation above all else, utilizing redirection and focused analysis to manage high-output tasks without sacrificing depth. Never sacrifice validation rigor for the sake of brevity or to minimize tool-call overhead; partial or isolated checks are insufficient when more comprehensive validation is possible.
|
||||
|
||||
@@ -2840,7 +2983,7 @@ For example:
|
||||
# Primary Workflows
|
||||
|
||||
## Development Lifecycle
|
||||
Operate using a **Research -> Strategy -> Execution** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
Operate using a **Research -> Strategy -> Execution -> Review** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
|
||||
1. **Research:** Systematically map the codebase and validate assumptions. Use \`grep_search\` and \`glob\` search tools extensively (in parallel if independent) to understand file structures, existing code patterns, and conventions. Use \`read_file\` to validate all assumptions. **Prioritize empirical reproduction of reported issues to confirm the failure state.**
|
||||
2. **Strategy:** Formulate a grounded plan based on your research. Share a concise summary of your strategy.
|
||||
@@ -2848,6 +2991,11 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
|
||||
- **Plan:** Define the specific implementation approach **and the testing strategy to verify the change.**
|
||||
- **Act:** Apply targeted, surgical changes strictly related to the sub-task. Use the available tools (e.g., \`replace\`, \`write_file\`, \`run_shell_command\`). Ensure changes are idiomatically complete and follow all workspace standards, even if it requires multiple tool calls. **Include necessary automated tests; a change is incomplete without verification logic.** Avoid unrelated refactoring or "cleanup" of outside code. Before making manual code changes, check if an ecosystem tool (like 'eslint --fix', 'prettier --write', 'go fmt', 'cargo fmt') is available in the project to perform the task automatically.
|
||||
- **Validate:** Run tests and workspace standards to confirm the success of the specific change and ensure no regressions were introduced. After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project. If unsure about these commands, you can ask the user if they'd like you to run them and if so how to.
|
||||
4. **Review:** After any body of work where you write more than one file or make non-trivial code changes, you MUST execute a final review step:
|
||||
- **Analyze Diff:** If in a git repository, run \`git diff\` or \`git diff HEAD\` to visualize the exact changes made.
|
||||
- **Verify Completeness:** Compare the work done against the user's original prompt. Ensure the intent was completely satisfied and the codebase has landed in the desired end state. If there are gaps, formulate follow-up tasks to address them.
|
||||
- **Code Quality & Linting:** Verify that the generated code matches the codebase's linter preferences and any explicitly stated user preferences.
|
||||
- **Targeted Refinements:** Apply best practice final touches. Look for opportunities to de-duplicate logic, break up excessively large functions into more focused ones, and generally manage code complexity. Follow general programming and ecosystem-specific best practices, keeping in mind that explicit user preferences take precedence.
|
||||
|
||||
**Validation is the only path to finality.** Never assume success or settle for unverified changes. Rigorous, exhaustive verification is mandatory; it prevents the compounding cost of diagnosing failures later. A task is only complete when the behavioral correctness of the change has been verified and its structural integrity is confirmed within the full project context. Prioritize comprehensive validation above all else, utilizing redirection and focused analysis to manage high-output tasks without sacrificing depth. Never sacrifice validation rigor for the sake of brevity or to minimize tool-call overhead; partial or isolated checks are insufficient when more comprehensive validation is possible.
|
||||
|
||||
@@ -3091,7 +3239,7 @@ For example:
|
||||
# Primary Workflows
|
||||
|
||||
## Development Lifecycle
|
||||
Operate using a **Research -> Strategy -> Execution** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
Operate using a **Research -> Strategy -> Execution -> Review** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
|
||||
1. **Research:** Systematically map the codebase and validate assumptions. Use \`grep_search\` and \`glob\` search tools extensively (in parallel if independent) to understand file structures, existing code patterns, and conventions. Use \`read_file\` to validate all assumptions. **Prioritize empirical reproduction of reported issues to confirm the failure state.**
|
||||
2. **Strategy:** Formulate a grounded plan based on your research. Share a concise summary of your strategy.
|
||||
@@ -3099,6 +3247,11 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
|
||||
- **Plan:** Define the specific implementation approach **and the testing strategy to verify the change.**
|
||||
- **Act:** Apply targeted, surgical changes strictly related to the sub-task. Use the available tools (e.g., \`replace\`, \`write_file\`, \`run_shell_command\`). Ensure changes are idiomatically complete and follow all workspace standards, even if it requires multiple tool calls. **Include necessary automated tests; a change is incomplete without verification logic.** Avoid unrelated refactoring or "cleanup" of outside code. Before making manual code changes, check if an ecosystem tool (like 'eslint --fix', 'prettier --write', 'go fmt', 'cargo fmt') is available in the project to perform the task automatically.
|
||||
- **Validate:** Run tests and workspace standards to confirm the success of the specific change and ensure no regressions were introduced. After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project. If unsure about these commands, you can ask the user if they'd like you to run them and if so how to.
|
||||
4. **Review:** After any body of work where you write more than one file or make non-trivial code changes, you MUST execute a final review step:
|
||||
- **Analyze Diff:** If in a git repository, run \`git diff\` or \`git diff HEAD\` to visualize the exact changes made.
|
||||
- **Verify Completeness:** Compare the work done against the user's original prompt. Ensure the intent was completely satisfied and the codebase has landed in the desired end state. If there are gaps, formulate follow-up tasks to address them.
|
||||
- **Code Quality & Linting:** Verify that the generated code matches the codebase's linter preferences and any explicitly stated user preferences.
|
||||
- **Targeted Refinements:** Apply best practice final touches. Look for opportunities to de-duplicate logic, break up excessively large functions into more focused ones, and generally manage code complexity. Follow general programming and ecosystem-specific best practices, keeping in mind that explicit user preferences take precedence.
|
||||
|
||||
**Validation is the only path to finality.** Never assume success or settle for unverified changes. Rigorous, exhaustive verification is mandatory; it prevents the compounding cost of diagnosing failures later. A task is only complete when the behavioral correctness of the change has been verified and its structural integrity is confirmed within the full project context. Prioritize comprehensive validation above all else, utilizing redirection and focused analysis to manage high-output tasks without sacrificing depth. Never sacrifice validation rigor for the sake of brevity or to minimize tool-call overhead; partial or isolated checks are insufficient when more comprehensive validation is possible.
|
||||
|
||||
@@ -3230,7 +3383,7 @@ For example:
|
||||
# Primary Workflows
|
||||
|
||||
## Development Lifecycle
|
||||
Operate using a **Research -> Strategy -> Execution** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
Operate using a **Research -> Strategy -> Execution -> Review** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
|
||||
1. **Research:** Systematically map the codebase and validate assumptions. Use \`grep_search\` and \`glob\` search tools extensively (in parallel if independent) to understand file structures, existing code patterns, and conventions. Use \`read_file\` to validate all assumptions. **Prioritize empirical reproduction of reported issues to confirm the failure state.**
|
||||
2. **Strategy:** Formulate a grounded plan based on your research. Share a concise summary of your strategy.
|
||||
@@ -3238,6 +3391,11 @@ Operate using a **Research -> Strategy -> Execution** lifecycle. For the Executi
|
||||
- **Plan:** Define the specific implementation approach **and the testing strategy to verify the change.**
|
||||
- **Act:** Apply targeted, surgical changes strictly related to the sub-task. Use the available tools (e.g., \`replace\`, \`write_file\`, \`run_shell_command\`). Ensure changes are idiomatically complete and follow all workspace standards, even if it requires multiple tool calls. **Include necessary automated tests; a change is incomplete without verification logic.** Avoid unrelated refactoring or "cleanup" of outside code. Before making manual code changes, check if an ecosystem tool (like 'eslint --fix', 'prettier --write', 'go fmt', 'cargo fmt') is available in the project to perform the task automatically.
|
||||
- **Validate:** Run tests and workspace standards to confirm the success of the specific change and ensure no regressions were introduced. After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project. If unsure about these commands, you can ask the user if they'd like you to run them and if so how to.
|
||||
4. **Review:** After any body of work where you write more than one file or make non-trivial code changes, you MUST execute a final review step:
|
||||
- **Analyze Diff:** If in a git repository, run \`git diff\` or \`git diff HEAD\` to visualize the exact changes made.
|
||||
- **Verify Completeness:** Compare the work done against the user's original prompt. Ensure the intent was completely satisfied and the codebase has landed in the desired end state. If there are gaps, formulate follow-up tasks to address them.
|
||||
- **Code Quality & Linting:** Verify that the generated code matches the codebase's linter preferences and any explicitly stated user preferences.
|
||||
- **Targeted Refinements:** Apply best practice final touches. Look for opportunities to de-duplicate logic, break up excessively large functions into more focused ones, and generally manage code complexity. Follow general programming and ecosystem-specific best practices, keeping in mind that explicit user preferences take precedence.
|
||||
|
||||
**Validation is the only path to finality.** Never assume success or settle for unverified changes. Rigorous, exhaustive verification is mandatory; it prevents the compounding cost of diagnosing failures later. A task is only complete when the behavioral correctness of the change has been verified and its structural integrity is confirmed within the full project context. Prioritize comprehensive validation above all else, utilizing redirection and focused analysis to manage high-output tasks without sacrificing depth. Never sacrifice validation rigor for the sake of brevity or to minimize tool-call overhead; partial or isolated checks are insufficient when more comprehensive validation is possible.
|
||||
|
||||
|
||||
@@ -1207,7 +1207,7 @@ ${JSON.stringify(
|
||||
eventCount++;
|
||||
|
||||
// Safety check to prevent actual infinite loop in test
|
||||
if (eventCount > 200) {
|
||||
if (eventCount > 400) {
|
||||
abortController.abort();
|
||||
throw new Error(
|
||||
'Test exceeded expected event limit - possible actual infinite loop',
|
||||
@@ -1219,13 +1219,12 @@ ${JSON.stringify(
|
||||
expect(finalResult).toBeInstanceOf(Turn);
|
||||
|
||||
// If infinite loop protection is working, checkNextSpeaker should be called many times
|
||||
// but stop at MAX_TURNS (100). Since each recursive call should trigger checkNextSpeaker,
|
||||
// we expect it to be called multiple times before hitting the limit
|
||||
// but stop at maxTurns (200 for non-interactive). Since each recursive call should trigger
|
||||
// checkNextSpeaker, we expect it to be called multiple times before hitting the limit
|
||||
expect(mockCheckNextSpeaker).toHaveBeenCalled();
|
||||
|
||||
// The stream should produce events and eventually terminate
|
||||
expect(eventCount).toBeGreaterThanOrEqual(1);
|
||||
expect(eventCount).toBeLessThan(200); // Should not exceed our safety limit
|
||||
});
|
||||
|
||||
it('should yield MaxSessionTurns and stop when session turn limit is reached', async () => {
|
||||
@@ -1347,9 +1346,9 @@ ${JSON.stringify(
|
||||
const callCount = mockCheckNextSpeaker.mock.calls.length;
|
||||
|
||||
// With the fix: even when turns is set to a very high value,
|
||||
// the loop should stop at MAX_TURNS (100)
|
||||
expect(callCount).toBeLessThanOrEqual(100); // Should not exceed MAX_TURNS
|
||||
expect(eventCount).toBeLessThanOrEqual(200); // Should have reasonable number of events
|
||||
// the loop should stop at maxTurns (200 for non-interactive)
|
||||
expect(callCount).toBeLessThanOrEqual(200); // Should not exceed maxTurns
|
||||
expect(eventCount).toBeLessThanOrEqual(400); // Should have reasonable number of events
|
||||
});
|
||||
|
||||
it('should yield ContextWindowWillOverflow when the context window is about to overflow', async () => {
|
||||
|
||||
@@ -65,7 +65,8 @@ import { partToString } from '../utils/partUtils.js';
|
||||
import { coreEvents, CoreEvent } from '../utils/events.js';
|
||||
import type { LlmRole } from '../telemetry/types.js';
|
||||
|
||||
const MAX_TURNS = 100;
|
||||
const MAX_TURNS_INTERACTIVE = 100;
|
||||
const MAX_TURNS_NON_INTERACTIVE = 200;
|
||||
|
||||
type BeforeAgentHookReturn =
|
||||
| {
|
||||
@@ -86,6 +87,7 @@ export class GeminiClient {
|
||||
private readonly loopDetector: LoopDetectionService;
|
||||
private readonly compressionService: ChatCompressionService;
|
||||
private readonly toolOutputMaskingService: ToolOutputMaskingService;
|
||||
private readonly maxTurns: number;
|
||||
private lastPromptId: string;
|
||||
private currentSequenceModel: string | null = null;
|
||||
private lastSentIdeContext: IdeContext | undefined;
|
||||
@@ -102,6 +104,9 @@ export class GeminiClient {
|
||||
this.compressionService = new ChatCompressionService();
|
||||
this.toolOutputMaskingService = new ToolOutputMaskingService();
|
||||
this.lastPromptId = this.config.getSessionId();
|
||||
this.maxTurns = config.isInteractive()
|
||||
? MAX_TURNS_INTERACTIVE
|
||||
: MAX_TURNS_NON_INTERACTIVE;
|
||||
|
||||
coreEvents.on(CoreEvent.ModelChanged, this.handleModelChanged);
|
||||
}
|
||||
@@ -790,7 +795,7 @@ export class GeminiClient {
|
||||
request: PartListUnion,
|
||||
signal: AbortSignal,
|
||||
prompt_id: string,
|
||||
turns: number = MAX_TURNS,
|
||||
turns?: number,
|
||||
isInvalidStreamRetry: boolean = false,
|
||||
displayContent?: PartListUnion,
|
||||
): AsyncGenerator<ServerGeminiStreamEvent, Turn> {
|
||||
@@ -838,7 +843,7 @@ export class GeminiClient {
|
||||
}
|
||||
}
|
||||
|
||||
const boundedTurns = Math.min(turns, MAX_TURNS);
|
||||
const boundedTurns = Math.min(turns ?? this.maxTurns, this.maxTurns);
|
||||
let turn = new Turn(this.getChat(), prompt_id);
|
||||
|
||||
try {
|
||||
|
||||
@@ -1315,11 +1315,11 @@ describe('GeminiChat', () => {
|
||||
}
|
||||
}).rejects.toThrow(InvalidStreamError);
|
||||
|
||||
// Should be called 2 times (initial + 1 retry)
|
||||
// Should be called 3 times (initial + 2 retries)
|
||||
expect(mockContentGenerator.generateContentStream).toHaveBeenCalledTimes(
|
||||
2,
|
||||
3,
|
||||
);
|
||||
expect(mockLogContentRetry).toHaveBeenCalledTimes(1);
|
||||
expect(mockLogContentRetry).toHaveBeenCalledTimes(2);
|
||||
expect(mockLogContentRetryFailure).toHaveBeenCalledTimes(1);
|
||||
|
||||
// History should still contain the user message.
|
||||
|
||||
@@ -86,8 +86,8 @@ interface ContentRetryOptions {
|
||||
}
|
||||
|
||||
const INVALID_CONTENT_RETRY_OPTIONS: ContentRetryOptions = {
|
||||
maxAttempts: 2, // 1 initial call + 1 retry
|
||||
initialDelayMs: 500,
|
||||
maxAttempts: 3, // 1 initial call + 2 retries
|
||||
initialDelayMs: 1000,
|
||||
};
|
||||
|
||||
export const SYNTHETIC_THOUGHT_SIGNATURE = 'skip_thought_signature_validator';
|
||||
|
||||
@@ -280,7 +280,7 @@ export function renderPrimaryWorkflows(
|
||||
# Primary Workflows
|
||||
|
||||
## Development Lifecycle
|
||||
Operate using a **Research -> Strategy -> Execution** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
Operate using a **Research -> Strategy -> Execution -> Review** lifecycle. For the Execution phase, resolve each sub-task through an iterative **Plan -> Act -> Validate** cycle.
|
||||
|
||||
${workflowStepResearch(options)}
|
||||
${workflowStepStrategy(options)}
|
||||
@@ -288,6 +288,11 @@ ${workflowStepStrategy(options)}
|
||||
- **Plan:** Define the specific implementation approach **and the testing strategy to verify the change.**
|
||||
- **Act:** Apply targeted, surgical changes strictly related to the sub-task. Use the available tools (e.g., ${formatToolName(EDIT_TOOL_NAME)}, ${formatToolName(WRITE_FILE_TOOL_NAME)}, ${formatToolName(SHELL_TOOL_NAME)}). Ensure changes are idiomatically complete and follow all workspace standards, even if it requires multiple tool calls. **Include necessary automated tests; a change is incomplete without verification logic.** Avoid unrelated refactoring or "cleanup" of outside code. Before making manual code changes, check if an ecosystem tool (like 'eslint --fix', 'prettier --write', 'go fmt', 'cargo fmt') is available in the project to perform the task automatically.
|
||||
- **Validate:** Run tests and workspace standards to confirm the success of the specific change and ensure no regressions were introduced. After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project.${workflowVerifyStandardsSuffix(options.interactive)}
|
||||
4. **Review:** After any body of work where you write more than one file or make non-trivial code changes, you MUST execute a final review step:
|
||||
- **Analyze Diff:** If in a git repository, run \`git diff\` or \`git diff HEAD\` to visualize the exact changes made.
|
||||
- **Verify Completeness:** Compare the work done against the user's original prompt. Ensure the intent was completely satisfied and the codebase has landed in the desired end state. If there are gaps, formulate follow-up tasks to address them.
|
||||
- **Code Quality & Linting:** Verify that the generated code matches the codebase's linter preferences and any explicitly stated user preferences.
|
||||
- **Targeted Refinements:** Apply best practice final touches. Look for opportunities to de-duplicate logic, break up excessively large functions into more focused ones, and generally manage code complexity. Follow general programming and ecosystem-specific best practices, keeping in mind that explicit user preferences take precedence.
|
||||
|
||||
**Validation is the only path to finality.** Never assume success or settle for unverified changes. Rigorous, exhaustive verification is mandatory; it prevents the compounding cost of diagnosing failures later. A task is only complete when the behavioral correctness of the change has been verified and its structural integrity is confirmed within the full project context. Prioritize comprehensive validation above all else, utilizing redirection and focused analysis to manage high-output tasks without sacrificing depth. Never sacrifice validation rigor for the sake of brevity or to minimize tool-call overhead; partial or isolated checks are insufficient when more comprehensive validation is possible.
|
||||
|
||||
@@ -333,6 +338,9 @@ export function renderOperationalGuidelines(
|
||||
## Interaction Details
|
||||
- **Help Command:** The user can use '/help' to display help information.
|
||||
- **Feedback:** To report a bug or provide feedback, please use the /bug command.
|
||||
${!options.interactive ? nonInteractiveFileWritingGuidance() : ''}
|
||||
${!options.interactive ? nonInteractiveProcessGuidance() : ''}
|
||||
${!options.interactive ? nonInteractiveErrorRecovery() : ''}
|
||||
`.trim();
|
||||
}
|
||||
|
||||
@@ -674,6 +682,59 @@ function gitRepoKeepUserInformed(interactive: boolean): string {
|
||||
: '';
|
||||
}
|
||||
|
||||
function nonInteractiveFileWritingGuidance(): string {
|
||||
return `
|
||||
## File Creation (Non-Interactive)
|
||||
- **Prefer ${WRITE_FILE_TOOL_NAME} over shell heredocs** for creating or overwriting files. The ${WRITE_FILE_TOOL_NAME} tool is more reliable and avoids shell escaping issues.
|
||||
- Only use shell heredocs when you need to append to a file or when the content depends on shell variable expansion.
|
||||
- If you must use a heredoc, always use the full syntax: \`cat << 'EOF' > filename\` — never omit \`cat\`.`;
|
||||
}
|
||||
|
||||
function nonInteractiveProcessGuidance(): string {
|
||||
return `
|
||||
## Background Services (Non-Interactive)
|
||||
- To start a service that must persist across turns, use: \`nohup <command> > /tmp/<service>.log 2>&1 &\`
|
||||
- After starting, verify the process is running:
|
||||
1. \`echo $!\` to capture the PID immediately after starting
|
||||
2. \`sleep 1 && kill -0 <PID>\` to confirm it's still alive
|
||||
3. Check the log file for startup errors: \`cat /tmp/<service>.log\`
|
||||
- If a service fails to start, check the log file before retrying.
|
||||
- For services that need time to initialize (databases, web servers), add a brief \`sleep 2\` and verify the port is open before proceeding.`;
|
||||
}
|
||||
|
||||
function nonInteractiveErrorRecovery(): string {
|
||||
return `
|
||||
## Error Recovery (Non-Interactive)
|
||||
- **Don't blindly retry:** When a tool call fails, analyze the error before retrying. Do not immediately retry with the same arguments.
|
||||
- **Web fetch failures:** If web_fetch fails, try simplifying the prompt or use google_web_search as an alternative to find the information.
|
||||
- **Shell failures:** Check error codes and run diagnostic commands before retrying. For compilation errors, fix one issue at a time rather than attempting multiple fixes simultaneously.
|
||||
- **Maximum retries:** Attempt the same approach at most 2 times. If it fails twice, try an alternative strategy or tool.
|
||||
- **Avoid loops:** If you find yourself repeating the same sequence of actions, stop and reassess your approach.
|
||||
|
||||
## Missing Commands / "command not found"
|
||||
- When a command is not found, install the package that provides it before retrying.
|
||||
- Use \`apt-get install -y <package>\` (Debian/Ubuntu) or \`yum install -y <package>\` (RHEL/CentOS).
|
||||
- Common mappings:
|
||||
- pgrep, ps, pidof → procps
|
||||
- ss → iproute2
|
||||
- netstat, ifconfig → net-tools
|
||||
- curl → curl
|
||||
- jq → jq
|
||||
- dig, nslookup → dnsutils (or bind-utils on RHEL)
|
||||
- ip → iproute2
|
||||
- lsof → lsof
|
||||
- wget → wget
|
||||
- tree → tree
|
||||
- zip/unzip → zip / unzip
|
||||
- If you don't know the package name, try \`apt-cache search <command>\` or \`yum provides <command>\`.
|
||||
|
||||
## Process Verification Without pgrep
|
||||
- If pgrep/ps are unavailable and you can't install them, verify processes using:
|
||||
- \`ls /proc/[PID]\` to check if a PID is still running
|
||||
- \`kill -0 <PID>\` to test if a process exists (returns 0 if it does)
|
||||
- \`cat /proc/<PID>/cmdline\` to inspect what a process is running`;
|
||||
}
|
||||
|
||||
function formatToolName(name: string): string {
|
||||
return `\`${name}\``;
|
||||
}
|
||||
|
||||
@@ -718,8 +718,9 @@ describe('ChatCompressionService', () => {
|
||||
|
||||
it('should use high-fidelity original history for summarization when under the limit, but truncated version for active window', async () => {
|
||||
// Large response in the "to compress" section (first message)
|
||||
// 300,000 chars is ~75k tokens, well under the 1,000,000 summarizer limit.
|
||||
const massiveText = 'a'.repeat(300000);
|
||||
// 500,000 chars is ~125k tokens, well under the 1,000,000 summarizer limit
|
||||
// but exceeds COMPRESSION_FUNCTION_RESPONSE_TOKEN_BUDGET (75k).
|
||||
const massiveText = 'a'.repeat(500000);
|
||||
const history: Content[] = [
|
||||
{
|
||||
role: 'user',
|
||||
|
||||
@@ -43,12 +43,12 @@ const DEFAULT_COMPRESSION_TOKEN_THRESHOLD = 0.5;
|
||||
* The fraction of the latest chat history to keep. A value of 0.3
|
||||
* means that only the last 30% of the chat history will be kept after compression.
|
||||
*/
|
||||
const COMPRESSION_PRESERVE_THRESHOLD = 0.3;
|
||||
const COMPRESSION_PRESERVE_THRESHOLD = 0.4;
|
||||
|
||||
/**
|
||||
* The budget for function response tokens in the preserved history.
|
||||
*/
|
||||
const COMPRESSION_FUNCTION_RESPONSE_TOKEN_BUDGET = 50_000;
|
||||
const COMPRESSION_FUNCTION_RESPONSE_TOKEN_BUDGET = 75_000;
|
||||
|
||||
/**
|
||||
* Returns the index of the oldest item to keep when compressing. May return
|
||||
|
||||
@@ -26,7 +26,7 @@ vi.mock('../telemetry/loggers.js', () => ({
|
||||
logLlmLoopCheck: vi.fn(),
|
||||
}));
|
||||
|
||||
const TOOL_CALL_LOOP_THRESHOLD = 5;
|
||||
const TOOL_CALL_LOOP_THRESHOLD = 4;
|
||||
const CONTENT_LOOP_THRESHOLD = 10;
|
||||
const CONTENT_CHUNK_SIZE = 50;
|
||||
|
||||
@@ -806,15 +806,15 @@ describe('LoopDetectionService LLM Checks', () => {
|
||||
};
|
||||
|
||||
it('should not trigger LLM check before LLM_CHECK_AFTER_TURNS', async () => {
|
||||
await advanceTurns(29);
|
||||
await advanceTurns(19);
|
||||
expect(mockBaseLlmClient.generateJson).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should trigger LLM check on the 30th turn', async () => {
|
||||
it('should trigger LLM check on the 20th turn', async () => {
|
||||
mockBaseLlmClient.generateJson = vi
|
||||
.fn()
|
||||
.mockResolvedValue({ unproductive_state_confidence: 0.1 });
|
||||
await advanceTurns(30);
|
||||
await advanceTurns(20);
|
||||
expect(mockBaseLlmClient.generateJson).toHaveBeenCalledTimes(1);
|
||||
expect(mockBaseLlmClient.generateJson).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
@@ -828,12 +828,12 @@ describe('LoopDetectionService LLM Checks', () => {
|
||||
});
|
||||
|
||||
it('should detect a cognitive loop when confidence is high', async () => {
|
||||
// First check at turn 30
|
||||
// First check at turn 20
|
||||
mockBaseLlmClient.generateJson = vi.fn().mockResolvedValue({
|
||||
unproductive_state_confidence: 0.85,
|
||||
unproductive_state_analysis: 'Repetitive actions',
|
||||
});
|
||||
await advanceTurns(30);
|
||||
await advanceTurns(20);
|
||||
expect(mockBaseLlmClient.generateJson).toHaveBeenCalledTimes(1);
|
||||
expect(mockBaseLlmClient.generateJson).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
@@ -843,13 +843,13 @@ describe('LoopDetectionService LLM Checks', () => {
|
||||
|
||||
// The confidence of 0.85 will result in a low interval.
|
||||
// The interval will be: 5 + (15 - 5) * (1 - 0.85) = 5 + 10 * 0.15 = 6.5 -> rounded to 7
|
||||
await advanceTurns(6); // advance to turn 36
|
||||
await advanceTurns(6); // advance to turn 26
|
||||
|
||||
mockBaseLlmClient.generateJson = vi.fn().mockResolvedValue({
|
||||
unproductive_state_confidence: 0.95,
|
||||
unproductive_state_analysis: 'Repetitive actions',
|
||||
});
|
||||
const finalResult = await service.turnStarted(abortController.signal); // This is turn 37
|
||||
const finalResult = await service.turnStarted(abortController.signal); // This is turn 27
|
||||
|
||||
expect(finalResult).toBe(true);
|
||||
expect(loggers.logLoopDetected).toHaveBeenCalledWith(
|
||||
@@ -867,7 +867,7 @@ describe('LoopDetectionService LLM Checks', () => {
|
||||
unproductive_state_confidence: 0.5,
|
||||
unproductive_state_analysis: 'Looks okay',
|
||||
});
|
||||
await advanceTurns(30);
|
||||
await advanceTurns(20);
|
||||
const result = await service.turnStarted(abortController.signal);
|
||||
expect(result).toBe(false);
|
||||
expect(loggers.logLoopDetected).not.toHaveBeenCalled();
|
||||
@@ -878,13 +878,13 @@ describe('LoopDetectionService LLM Checks', () => {
|
||||
mockBaseLlmClient.generateJson = vi
|
||||
.fn()
|
||||
.mockResolvedValue({ unproductive_state_confidence: 0.0 });
|
||||
await advanceTurns(30); // First check at turn 30
|
||||
await advanceTurns(20); // First check at turn 20
|
||||
expect(mockBaseLlmClient.generateJson).toHaveBeenCalledTimes(1);
|
||||
|
||||
await advanceTurns(14); // Advance to turn 44
|
||||
await advanceTurns(14); // Advance to turn 34
|
||||
expect(mockBaseLlmClient.generateJson).toHaveBeenCalledTimes(1);
|
||||
|
||||
await service.turnStarted(abortController.signal); // Turn 45
|
||||
await service.turnStarted(abortController.signal); // Turn 35
|
||||
expect(mockBaseLlmClient.generateJson).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
@@ -892,7 +892,7 @@ describe('LoopDetectionService LLM Checks', () => {
|
||||
mockBaseLlmClient.generateJson = vi
|
||||
.fn()
|
||||
.mockRejectedValue(new Error('API error'));
|
||||
await advanceTurns(30);
|
||||
await advanceTurns(20);
|
||||
const result = await service.turnStarted(abortController.signal);
|
||||
expect(result).toBe(false);
|
||||
expect(loggers.logLoopDetected).not.toHaveBeenCalled();
|
||||
@@ -901,7 +901,7 @@ describe('LoopDetectionService LLM Checks', () => {
|
||||
it('should not trigger LLM check when disabled for session', async () => {
|
||||
service.disableForSession();
|
||||
expect(loggers.logLoopDetectionDisabled).toHaveBeenCalledTimes(1);
|
||||
await advanceTurns(30);
|
||||
await advanceTurns(20);
|
||||
const result = await service.turnStarted(abortController.signal);
|
||||
expect(result).toBe(false);
|
||||
expect(mockBaseLlmClient.generateJson).not.toHaveBeenCalled();
|
||||
@@ -924,7 +924,7 @@ describe('LoopDetectionService LLM Checks', () => {
|
||||
.fn()
|
||||
.mockResolvedValue({ unproductive_state_confidence: 0.1 });
|
||||
|
||||
await advanceTurns(30);
|
||||
await advanceTurns(20);
|
||||
|
||||
expect(mockBaseLlmClient.generateJson).toHaveBeenCalledTimes(1);
|
||||
const calledArg = vi.mocked(mockBaseLlmClient.generateJson).mock
|
||||
@@ -949,7 +949,7 @@ describe('LoopDetectionService LLM Checks', () => {
|
||||
unproductive_state_analysis: 'Main says loop',
|
||||
});
|
||||
|
||||
await advanceTurns(30);
|
||||
await advanceTurns(20);
|
||||
|
||||
// It should have called generateJson twice
|
||||
expect(mockBaseLlmClient.generateJson).toHaveBeenCalledTimes(2);
|
||||
@@ -989,7 +989,7 @@ describe('LoopDetectionService LLM Checks', () => {
|
||||
unproductive_state_analysis: 'Main says no loop',
|
||||
});
|
||||
|
||||
await advanceTurns(30);
|
||||
await advanceTurns(20);
|
||||
|
||||
expect(mockBaseLlmClient.generateJson).toHaveBeenCalledTimes(2);
|
||||
expect(mockBaseLlmClient.generateJson).toHaveBeenNthCalledWith(
|
||||
@@ -1032,7 +1032,7 @@ describe('LoopDetectionService LLM Checks', () => {
|
||||
unproductive_state_analysis: 'Flash says loop',
|
||||
});
|
||||
|
||||
await advanceTurns(30);
|
||||
await advanceTurns(20);
|
||||
|
||||
// It should have called generateJson only once
|
||||
expect(mockBaseLlmClient.generateJson).toHaveBeenCalledTimes(1);
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
} from '../utils/messageInspectors.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
const TOOL_CALL_LOOP_THRESHOLD = 5;
|
||||
const TOOL_CALL_LOOP_THRESHOLD = 4;
|
||||
const CONTENT_LOOP_THRESHOLD = 10;
|
||||
const CONTENT_CHUNK_SIZE = 50;
|
||||
const MAX_HISTORY_LENGTH = 5000;
|
||||
@@ -40,7 +40,7 @@ const LLM_LOOP_CHECK_HISTORY_COUNT = 20;
|
||||
/**
|
||||
* The number of turns that must pass in a single prompt before the LLM-based loop check is activated.
|
||||
*/
|
||||
const LLM_CHECK_AFTER_TURNS = 30;
|
||||
const LLM_CHECK_AFTER_TURNS = 20;
|
||||
|
||||
/**
|
||||
* The default interval, in number of turns, at which the LLM-based loop check is performed.
|
||||
@@ -105,6 +105,7 @@ export class LoopDetectionService {
|
||||
// Tool call tracking
|
||||
private lastToolCallKey: string | null = null;
|
||||
private toolCallRepetitionCount: number = 0;
|
||||
private recentToolCallKeys: string[] = [];
|
||||
|
||||
// Content streaming tracking
|
||||
private streamContentHistory = '';
|
||||
@@ -217,6 +218,53 @@ export class LoopDetectionService {
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Alternating pattern detection: track last 12 tool calls and detect
|
||||
// when a pattern of 2-3 distinct calls repeats 3+ times.
|
||||
this.recentToolCallKeys.push(key);
|
||||
if (this.recentToolCallKeys.length > 12) {
|
||||
this.recentToolCallKeys.shift();
|
||||
}
|
||||
if (this.detectAlternatingPattern()) {
|
||||
logLoopDetected(
|
||||
this.config,
|
||||
new LoopDetectedEvent(
|
||||
LoopType.CONSECUTIVE_IDENTICAL_TOOL_CALLS,
|
||||
this.promptId,
|
||||
),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects alternating patterns like A->B->A->B->A->B or A->B->C->A->B->C.
|
||||
* Checks if a pattern of length 2 or 3 repeats at least 3 times at the
|
||||
* end of the recent tool call history.
|
||||
*/
|
||||
private detectAlternatingPattern(): boolean {
|
||||
const keys = this.recentToolCallKeys;
|
||||
// Check patterns of length 2 and 3
|
||||
for (const patternLen of [2, 3]) {
|
||||
const minRequired = patternLen * 3; // Need at least 3 repetitions
|
||||
if (keys.length < minRequired) continue;
|
||||
|
||||
const pattern = keys.slice(keys.length - patternLen);
|
||||
let repetitions = 1;
|
||||
for (let i = keys.length - patternLen * 2; i >= 0; i -= patternLen) {
|
||||
const segment = keys.slice(i, i + patternLen);
|
||||
if (segment.every((k, idx) => k === pattern[idx])) {
|
||||
repetitions++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (repetitions >= 3) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -613,6 +661,7 @@ export class LoopDetectionService {
|
||||
private resetToolCallCount(): void {
|
||||
this.lastToolCallKey = null;
|
||||
this.toolCallRepetitionCount = 0;
|
||||
this.recentToolCallKeys = [];
|
||||
}
|
||||
|
||||
private resetContentTracking(resetHistory = true): void {
|
||||
|
||||
@@ -1106,6 +1106,7 @@ describe('loggers', () => {
|
||||
new ToolRegistry(cfg1, {} as unknown as MessageBus),
|
||||
|
||||
getUserMemory: () => 'user-memory',
|
||||
isInteractive: () => false,
|
||||
} as unknown as Config;
|
||||
|
||||
const mockGeminiClient = new GeminiClient(cfg2);
|
||||
|
||||
@@ -141,7 +141,7 @@ describe('WebFetchTool', () => {
|
||||
setApprovalMode: vi.fn(),
|
||||
getProxy: vi.fn(),
|
||||
getGeminiClient: mockGetGeminiClient,
|
||||
getRetryFetchErrors: vi.fn().mockReturnValue(false),
|
||||
getRetryFetchErrors: vi.fn().mockReturnValue(true),
|
||||
modelConfigService: {
|
||||
getResolvedConfig: vi.fn().mockImplementation(({ model }) => ({
|
||||
model,
|
||||
@@ -208,6 +208,8 @@ describe('WebFetchTool', () => {
|
||||
vi.spyOn(fetchUtils, 'fetchWithTimeout').mockRejectedValue(
|
||||
new Error('fetch failed'),
|
||||
);
|
||||
// Disable retries so test doesn't timeout waiting for backoff
|
||||
vi.mocked(mockConfig.getRetryFetchErrors).mockReturnValue(false);
|
||||
const tool = new WebFetchTool(mockConfig, bus);
|
||||
const params = { prompt: 'fetch https://private.ip' };
|
||||
const invocation = tool.build(params);
|
||||
|
||||
@@ -31,8 +31,8 @@ import { WEB_FETCH_DEFINITION } from './definitions/coreTools.js';
|
||||
import { resolveToolDeclaration } from './definitions/resolver.js';
|
||||
import { LRUCache } from 'mnemonist';
|
||||
|
||||
const URL_FETCH_TIMEOUT_MS = 10000;
|
||||
const MAX_CONTENT_LENGTH = 100000;
|
||||
const URL_FETCH_TIMEOUT_MS = 30000;
|
||||
const MAX_CONTENT_LENGTH = 200000;
|
||||
|
||||
// Rate limiting configuration
|
||||
const RATE_LIMIT_WINDOW_MS = 60000; // 1 minute
|
||||
@@ -156,67 +156,104 @@ class WebFetchToolInvocation extends BaseToolInvocation<
|
||||
super(params, messageBus, _toolName, _toolDisplayName);
|
||||
}
|
||||
|
||||
private async executeFallback(signal: AbortSignal): Promise<ToolResult> {
|
||||
const { validUrls: urls } = parsePrompt(this.params.prompt);
|
||||
// For now, we only support one URL for fallback
|
||||
let url = urls[0];
|
||||
|
||||
private async executeFallbackForUrl(
|
||||
url: string,
|
||||
signal: AbortSignal,
|
||||
perUrlBudget: number,
|
||||
): Promise<{ content: string; error?: string }> {
|
||||
// Convert GitHub blob URL to raw URL
|
||||
if (url.includes('github.com') && url.includes('/blob/')) {
|
||||
url = url
|
||||
let fetchUrl = url;
|
||||
if (fetchUrl.includes('github.com') && fetchUrl.includes('/blob/')) {
|
||||
fetchUrl = fetchUrl
|
||||
.replace('github.com', 'raw.githubusercontent.com')
|
||||
.replace('/blob/', '/');
|
||||
}
|
||||
|
||||
const response = await retryWithBackoff(
|
||||
async () => {
|
||||
const res = await fetchWithTimeout(fetchUrl, URL_FETCH_TIMEOUT_MS);
|
||||
if (!res.ok) {
|
||||
const error = new Error(
|
||||
`Request failed with status code ${res.status} ${res.statusText}`,
|
||||
);
|
||||
(error as ErrorWithStatus).status = res.status;
|
||||
throw error;
|
||||
}
|
||||
return res;
|
||||
},
|
||||
{
|
||||
retryFetchErrors: this.config.getRetryFetchErrors(),
|
||||
signal,
|
||||
},
|
||||
);
|
||||
|
||||
const rawContent = await response.text();
|
||||
const contentType = response.headers.get('content-type') || '';
|
||||
let textContent: string;
|
||||
|
||||
// Only use html-to-text if content type is HTML, or if no content type is provided (assume HTML)
|
||||
if (contentType.toLowerCase().includes('text/html') || contentType === '') {
|
||||
textContent = convert(rawContent, {
|
||||
wordwrap: false,
|
||||
selectors: [
|
||||
{ selector: 'a', options: { ignoreHref: true } },
|
||||
{ selector: 'img', format: 'skip' },
|
||||
],
|
||||
});
|
||||
} else {
|
||||
// For other content types (text/plain, application/json, etc.), use raw text
|
||||
textContent = rawContent;
|
||||
}
|
||||
|
||||
// Per-URL content budget is the total budget divided by number of URLs
|
||||
textContent = textContent.substring(0, perUrlBudget);
|
||||
return { content: textContent };
|
||||
}
|
||||
|
||||
private async executeFallback(signal: AbortSignal): Promise<ToolResult> {
|
||||
const { validUrls: urls } = parsePrompt(this.params.prompt);
|
||||
|
||||
try {
|
||||
const response = await retryWithBackoff(
|
||||
async () => {
|
||||
const res = await fetchWithTimeout(url, URL_FETCH_TIMEOUT_MS);
|
||||
if (!res.ok) {
|
||||
const error = new Error(
|
||||
`Request failed with status code ${res.status} ${res.statusText}`,
|
||||
);
|
||||
(error as ErrorWithStatus).status = res.status;
|
||||
throw error;
|
||||
}
|
||||
return res;
|
||||
},
|
||||
{
|
||||
retryFetchErrors: this.config.getRetryFetchErrors(),
|
||||
},
|
||||
);
|
||||
const allContent: string[] = [];
|
||||
const fetchedUrls: string[] = [];
|
||||
const errors: string[] = [];
|
||||
|
||||
const rawContent = await response.text();
|
||||
const contentType = response.headers.get('content-type') || '';
|
||||
let textContent: string;
|
||||
|
||||
// Only use html-to-text if content type is HTML, or if no content type is provided (assume HTML)
|
||||
if (
|
||||
contentType.toLowerCase().includes('text/html') ||
|
||||
contentType === ''
|
||||
) {
|
||||
textContent = convert(rawContent, {
|
||||
wordwrap: false,
|
||||
selectors: [
|
||||
{ selector: 'a', options: { ignoreHref: true } },
|
||||
{ selector: 'img', format: 'skip' },
|
||||
],
|
||||
});
|
||||
} else {
|
||||
// For other content types (text/plain, application/json, etc.), use raw text
|
||||
textContent = rawContent;
|
||||
const perUrlBudget = Math.floor(MAX_CONTENT_LENGTH / urls.length);
|
||||
for (const url of urls) {
|
||||
try {
|
||||
const result = await this.executeFallbackForUrl(
|
||||
url,
|
||||
signal,
|
||||
perUrlBudget,
|
||||
);
|
||||
allContent.push(`--- Content from ${url} ---\n${result.content}`);
|
||||
fetchedUrls.push(url);
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const error = e as Error;
|
||||
errors.push(`Error fetching ${url}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
textContent = textContent.substring(0, MAX_CONTENT_LENGTH);
|
||||
if (allContent.length === 0) {
|
||||
const errorMessage = `Error during fallback fetch: ${errors.join('; ')}`;
|
||||
return {
|
||||
llmContent: `Error: ${errorMessage}`,
|
||||
returnDisplay: `Error: ${errorMessage}`,
|
||||
error: {
|
||||
message: errorMessage,
|
||||
type: ToolErrorType.WEB_FETCH_FALLBACK_FAILED,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const combinedContent = allContent.join('\n\n');
|
||||
const geminiClient = this.config.getGeminiClient();
|
||||
const fallbackPrompt = `The user requested the following: "${this.params.prompt}".
|
||||
|
||||
I was unable to access the URL directly. Instead, I have fetched the raw content of the page. Please use the following content to answer the request. Do not attempt to access the URL again.
|
||||
I was unable to access the URL(s) directly. Instead, I have fetched the raw content of the page(s). Please use the following content to answer the request. Do not attempt to access the URLs again.
|
||||
|
||||
---
|
||||
${textContent}
|
||||
---
|
||||
${combinedContent}
|
||||
`;
|
||||
const result = await geminiClient.generateContent(
|
||||
{ model: 'web-fetch-fallback' },
|
||||
@@ -225,14 +262,15 @@ ${textContent}
|
||||
LlmRole.UTILITY_TOOL,
|
||||
);
|
||||
const resultText = getResponseText(result) || '';
|
||||
const displayUrls = fetchedUrls.join(', ');
|
||||
return {
|
||||
llmContent: resultText,
|
||||
returnDisplay: `Content for ${url} processed using fallback fetch.`,
|
||||
returnDisplay: `Content for ${displayUrls} processed using fallback fetch.`,
|
||||
};
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const error = e as Error;
|
||||
const errorMessage = `Error during fallback fetch for ${url}: ${error.message}`;
|
||||
const errorMessage = `Error during fallback fetch: ${error.message}`;
|
||||
return {
|
||||
llmContent: `Error: ${errorMessage}`,
|
||||
returnDisplay: `Error: ${errorMessage}`,
|
||||
@@ -289,25 +327,28 @@ ${textContent}
|
||||
async execute(signal: AbortSignal): Promise<ToolResult> {
|
||||
const userPrompt = this.params.prompt;
|
||||
const { validUrls: urls } = parsePrompt(userPrompt);
|
||||
const url = urls[0];
|
||||
|
||||
// Enforce rate limiting
|
||||
const rateLimitResult = checkRateLimit(url);
|
||||
if (!rateLimitResult.allowed) {
|
||||
const waitTimeSecs = Math.ceil((rateLimitResult.waitTimeMs || 0) / 1000);
|
||||
const errorMessage = `Rate limit exceeded for host. Please wait ${waitTimeSecs} seconds before trying again.`;
|
||||
debugLogger.warn(`[WebFetchTool] Rate limit exceeded for ${url}`);
|
||||
return {
|
||||
llmContent: `Error: ${errorMessage}`,
|
||||
returnDisplay: `Error: ${errorMessage}`,
|
||||
error: {
|
||||
message: errorMessage,
|
||||
type: ToolErrorType.WEB_FETCH_PROCESSING_ERROR,
|
||||
},
|
||||
};
|
||||
// Enforce rate limiting for all URLs
|
||||
for (const url of urls) {
|
||||
const rateLimitResult = checkRateLimit(url);
|
||||
if (!rateLimitResult.allowed) {
|
||||
const waitTimeSecs = Math.ceil(
|
||||
(rateLimitResult.waitTimeMs || 0) / 1000,
|
||||
);
|
||||
const errorMessage = `Rate limit exceeded for host. Please wait ${waitTimeSecs} seconds before trying again.`;
|
||||
debugLogger.warn(`[WebFetchTool] Rate limit exceeded for ${url}`);
|
||||
return {
|
||||
llmContent: `Error: ${errorMessage}`,
|
||||
returnDisplay: `Error: ${errorMessage}`,
|
||||
error: {
|
||||
message: errorMessage,
|
||||
type: ToolErrorType.WEB_FETCH_PROCESSING_ERROR,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const isPrivate = isPrivateIp(url);
|
||||
const isPrivate = urls.some((url) => isPrivateIp(url));
|
||||
|
||||
if (isPrivate) {
|
||||
logWebFetchFallbackAttempt(
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import React, { useState, useEffect, useRef, useMemo } from 'react';
|
||||
import { useDevToolsData, type ConsoleLog, type NetworkLog } from './hooks';
|
||||
import { useDevToolsData, type ConsoleLog, type NetworkLog } from './hooks.js';
|
||||
|
||||
type ThemeMode = 'light' | 'dark' | null; // null means follow system
|
||||
|
||||
@@ -115,7 +115,6 @@ export default function App() {
|
||||
if (!networkMap.has(id)) {
|
||||
networkMap.set(id, {
|
||||
...payload,
|
||||
type,
|
||||
timestamp,
|
||||
id,
|
||||
} as NetworkLog);
|
||||
@@ -125,8 +124,7 @@ export default function App() {
|
||||
networkMap.set(id, {
|
||||
...existing,
|
||||
...payload,
|
||||
// Ensure we don't overwrite the original timestamp or type
|
||||
type: existing.type,
|
||||
// Ensure we don't overwrite the original timestamp
|
||||
timestamp: existing.timestamp,
|
||||
} as NetworkLog);
|
||||
}
|
||||
@@ -158,7 +156,7 @@ export default function App() {
|
||||
const entries: Array<{ timestamp: number; data: object }> = [];
|
||||
|
||||
// Export console logs
|
||||
filteredConsoleLogs.forEach((log) => {
|
||||
filteredConsoleLogs.forEach((log: ConsoleLog) => {
|
||||
entries.push({
|
||||
timestamp: log.timestamp,
|
||||
data: {
|
||||
@@ -171,7 +169,7 @@ export default function App() {
|
||||
});
|
||||
|
||||
// Export network logs
|
||||
filteredNetworkLogs.forEach((log) => {
|
||||
filteredNetworkLogs.forEach((log: NetworkLog) => {
|
||||
entries.push({
|
||||
timestamp: log.timestamp,
|
||||
data: {
|
||||
@@ -230,7 +228,9 @@ export default function App() {
|
||||
if (selectedSessionId === importedSessionId && importedLogs) {
|
||||
return importedLogs.console;
|
||||
}
|
||||
return consoleLogs.filter((l) => l.sessionId === selectedSessionId);
|
||||
return consoleLogs.filter(
|
||||
(l: ConsoleLog) => l.sessionId === selectedSessionId,
|
||||
);
|
||||
}, [consoleLogs, selectedSessionId, importedSessionId, importedLogs]);
|
||||
|
||||
const filteredNetworkLogs = useMemo(() => {
|
||||
@@ -238,7 +238,9 @@ export default function App() {
|
||||
if (selectedSessionId === importedSessionId && importedLogs) {
|
||||
return importedLogs.network;
|
||||
}
|
||||
return networkLogs.filter((l) => l.sessionId === selectedSessionId);
|
||||
return networkLogs.filter(
|
||||
(l: NetworkLog) => l.sessionId === selectedSessionId,
|
||||
);
|
||||
}, [networkLogs, selectedSessionId, importedSessionId, importedLogs]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import App from './App';
|
||||
import App from './App.js';
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"lib": ["DOM", "DOM.Iterable", "ES2023"],
|
||||
"jsx": "react-jsx",
|
||||
"allowImportingTsExtensions": true,
|
||||
"noEmit": true
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["src", "client/src"]
|
||||
}
|
||||
|
||||
@@ -131,8 +131,8 @@
|
||||
"retryFetchErrors": {
|
||||
"title": "Retry Fetch Errors",
|
||||
"description": "Retry on \"exception TypeError: fetch failed sending request\" errors.",
|
||||
"markdownDescription": "Retry on \"exception TypeError: fetch failed sending request\" errors.\n\n- Category: `General`\n- Requires restart: `no`\n- Default: `false`",
|
||||
"default": false,
|
||||
"markdownDescription": "Retry on \"exception TypeError: fetch failed sending request\" errors.\n\n- Category: `General`\n- Requires restart: `no`\n- Default: `true`",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"debugKeystrokeLogging": {
|
||||
|
||||
Reference in New Issue
Block a user