mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-11-07 06:19:43 -10:00
feat(core): make todo_write opt-in (#10645)
* feat(core): make todo_write opt-in * fix: address todo_write review feedback * fix: harden opt-in tool lookup * test(integration): verify todo_write tool results * fix(core): complete prompt test config mock --------- Co-authored-by: qwen-code-dev-bot <[email protected]>
This commit is contained in:
1 parent
53e3fc736e
commit
e36a536cab
30 files changed
+911
-343
No files matched your search
@@ -0,0 +1,75 @@
|
||||
# Make `todo_write` opt-in
|
||||
|
||||
## Summary
|
||||
|
||||
Disable the built-in `todo_write` tool by default in every interaction mode and
|
||||
allow users to restore it with `tools.todoWrite.enabled`. The default system
|
||||
prompt and Agent tool description must not advertise Todo-only behavior when
|
||||
the tool is unavailable.
|
||||
|
||||
## Motivation
|
||||
|
||||
`todo_write` rewrites a session checklist in a separate model turn. In
|
||||
headless mode that bookkeeping is not rendered as a dedicated progress view:
|
||||
text output hides the call, while JSON formats expose it only as a generic tool
|
||||
event. The extra tool round therefore adds latency and tokens without providing
|
||||
the interactive progress experience that originally justified the tool.
|
||||
|
||||
Newer models can maintain and revise a working approach without a mandatory
|
||||
checklist. Qwen Code also has shared task tools for the separate agent-team use
|
||||
case. Removing Todo from the default tool surface avoids steering ordinary
|
||||
sessions toward bookkeeping while preserving it for users and integrations
|
||||
that deliberately depend on it.
|
||||
|
||||
## Design
|
||||
|
||||
Add `tools.todoWrite.enabled`, a restart-required boolean setting whose default
|
||||
is `false`. The CLI passes the resolved value into `Config`; SDK callers can use
|
||||
the corresponding configuration parameter. Only this flag enables the tool.
|
||||
Tool allowlists, eager-tool selection, and permission rules continue to control
|
||||
registered tools but do not opt a disabled tool into existence.
|
||||
|
||||
When disabled:
|
||||
|
||||
- the tool registry does not register `todo_write`, eagerly or as a deferred
|
||||
tool;
|
||||
- an attempted call returns an actionable error naming the opt-in setting;
|
||||
- the default system prompt omits the Todo task-management section and all
|
||||
`todo_write` guidance while retaining adaptive planning guidance;
|
||||
- the Agent tool omits `todo_id` from its model-facing schema and usage notes;
|
||||
- the bundled new-application workflow does not require an unavailable tool.
|
||||
|
||||
When enabled, the existing Todo implementation remains unchanged. Persistence,
|
||||
hooks, active-Todo reminders, ACP rendering, and the daemon Todo Stop Guard
|
||||
remain downstream consumers of successful Todo calls. The Stop Guard is
|
||||
therefore effective only when both it and `tools.todoWrite.enabled` are on.
|
||||
|
||||
Custom system prompts remain user-owned and are not rewritten. Existing
|
||||
sessions may still contain historical Todo calls, but disabling the tool only
|
||||
changes future tool declarations and guidance; history loading and rendering
|
||||
continue to accept those records.
|
||||
|
||||
## Compatibility and rollout
|
||||
|
||||
This intentionally changes the default tool surface. Users who rely on Todo
|
||||
must add:
|
||||
|
||||
```json
|
||||
{
|
||||
"tools": {
|
||||
"todoWrite": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
No Todo data is deleted. Removing the setting restores the new default.
|
||||
|
||||
## Verification
|
||||
|
||||
Unit tests cover CLI setting propagation, registry behavior with the flag off
|
||||
and on, prompt guidance with the flag off and on, Agent schema guidance, and
|
||||
eager/deferred registration. Headless integration coverage verifies that the
|
||||
default tool declaration excludes `todo_write` and that explicitly enabling
|
||||
the setting restores a successful call.
|
||||
@@ -47,7 +47,7 @@ Qwen Code's built-in tools can be broadly categorized as follows:
|
||||
- **[Shell Tool](./shell.md) (`run_shell_command`):** For executing shell commands.
|
||||
- **[Monitor Tool](./monitor.md) (`monitor`):** For running long-lived shell commands that stream output back as background task notifications.
|
||||
- **[Web Fetch Tool](./web-fetch.md) (`web_fetch`):** For retrieving content from URLs.
|
||||
- **[Todo Write Tool](./todo-write.md) (`todo_write`):** For creating and managing structured task lists during coding sessions.
|
||||
- **[Todo Write Tool](./todo-write.md) (`todo_write`):** An opt-in tool for creating and managing structured task lists during coding sessions.
|
||||
- **[Agent Tool](./task.md) (`agent`):** For delegating complex tasks to specialized subagents.
|
||||
- **[Exit Plan Mode Tool](./exit-plan-mode.md) (`exit_plan_mode`):** For exiting plan mode and proceeding with implementation.
|
||||
|
||||
|
||||
@@ -6,6 +6,19 @@ This document describes the `todo_write` tool for Qwen Code.
|
||||
|
||||
Use `todo_write` to create and manage a structured task list for your current coding session. This tool helps the AI assistant track progress and organize complex tasks, providing you with visibility into what work is being performed.
|
||||
|
||||
The tool is disabled by default. Enable it in `settings.json` and restart Qwen
|
||||
Code:
|
||||
|
||||
```json
|
||||
{
|
||||
"tools": {
|
||||
"todoWrite": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Arguments
|
||||
|
||||
`todo_write` takes one argument:
|
||||
@@ -17,7 +30,7 @@ Use `todo_write` to create and manage a structured task list for your current co
|
||||
|
||||
## How to use `todo_write` with Qwen Code
|
||||
|
||||
The AI assistant will automatically use this tool when working on complex, multi-step tasks. You don't need to explicitly request it, but you can ask the assistant to create a todo list if you want to see the planned approach for your request.
|
||||
When the tool is enabled, the AI assistant may use it for complex, multi-step tasks. You can also ask the assistant to create a todo list if you want to see the planned approach for your request.
|
||||
|
||||
The tool stores todo lists in your home directory (`~/.qwen/todos/`) with session-specific files, so each coding session maintains its own task list.
|
||||
|
||||
@@ -58,6 +71,7 @@ todo_write(todos=[
|
||||
|
||||
## Important notes
|
||||
|
||||
- **Automatic usage:** The AI assistant manages todo lists automatically during complex tasks.
|
||||
- **Opt-in:** Set `tools.todoWrite.enabled` to `true` and restart Qwen Code before using the tool.
|
||||
- **Automatic usage when enabled:** The AI assistant manages todo lists during complex tasks.
|
||||
- **Progress visibility:** You'll see todo lists updated in real-time as work progresses.
|
||||
- **Session isolation:** Each coding session has its own todo list that doesn't interfere with others.
|
||||
@@ -384,6 +384,7 @@ If you are experiencing performance issues with file searching (e.g., with `@` c
|
||||
| `tools.toolSearch.enabled` | boolean | Load MCP tools on demand via ToolSearch to reduce prompt size. Disable this for models that rely on prefix-based KV caching (e.g. DeepSeek) to keep the prompt prefix stable and maximize cache hit rates. | `true` | Requires restart: Yes |
|
||||
| `tools.toolSearch.threshold` | number | Context-window percentage used as the session-start budget for preloading ordinary deferred tools (bundled built-ins and MCP alike). When their combined schemas fit within this budget, they are declared upfront instead of loaded on demand via ToolSearch. Tools demoted by `tools.eager` are excluded from this preload and stay on demand. Set `0` to always load deferred tools on demand. | `10` | Requires restart: Yes |
|
||||
| `tools.listDirectory.enabled` | boolean | Enable the built-in `list_directory` tool. Disabled by default because `glob` covers directory listing in most cases; the tool is also re-enabled automatically when explicitly listed in the `coreTools` allowlist (`--core-tools` / `tools.core`). | `false` | Requires restart: Yes |
|
||||
| `tools.todoWrite.enabled` | boolean | Enable the built-in `todo_write` tool and its system-prompt guidance. Disabled by default. | `false` | Requires restart: Yes |
|
||||
|
||||
> [!note]
|
||||
>
|
||||
@@ -614,16 +615,16 @@ Persistent sub-session concurrency settings for [`qwen serve`](../qwen-serve). C
|
||||
>
|
||||
> **Experimental features.** These toggles gate in-development capabilities and may change or be removed in future releases.
|
||||
|
||||
| Setting | Type | Description | Default |
|
||||
| -------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- |
|
||||
| `experimental.sessionWorkflow` | boolean | Show the daemon Web Shell Session Workflow DAG and present the existing `plan` approval mode as **Plan & Review**. This changes presentation only: it does not add an approval mode, alter Todo execution behavior, or schedule dependencies. Changes take effect without restarting. | `false` |
|
||||
| `experimental.cron` | boolean | Enable in-session cron/loop tools (`cron_create`, `cron_list`, `cron_delete`) so the model can create recurring prompts. Can be disabled via the `QWEN_CODE_DISABLE_CRON=1` environment variable. Requires restart. | `true` |
|
||||
| `experimental.todoStopGuard` | boolean | Allow daemon and ACP sessions to continue after a natural model stop when the current work chain successfully wrote an unfinished top-level Todo list. Adds at most two consecutive primary-model calls without new user input; mid-turn user input starts a fresh two-attempt stage. It is not restored after process restart and is forced off in safe, bare, and Approval `plan` modes. Requires restart. | `false` |
|
||||
| `experimental.sessionWriterLease` | boolean | Enable cross-process write fencing for persisted ACP and daemon sessions. The value is frozen when the ACP or daemon process starts. All concurrent ACP writers must enable the setting; mixed versions or configurations remain unsafe. Interactive and headless recorders are unaffected. Requires process restart. | `false` |
|
||||
| `experimental.cronRecurringMaxAgeDays` | number | Days a recurring cron/loop job lives before auto-expiring (it fires one final time, then is deleted). Set to `0` to disable expiry so jobs run until deleted — useful for long-running daemon deployments. Can be overridden via the `QWEN_CODE_CRON_MAX_AGE_DAYS` environment variable. Requires restart. | `7` |
|
||||
| `experimental.agentTeam` | boolean | Enable agent-team collaboration tools (`team_create`, `task_create`, `task_update`, `send_message`, etc.) for multi-agent coordination. Can also be enabled via `QWEN_CODE_ENABLE_AGENT_TEAM=1`. Requires restart. | `false` |
|
||||
| `experimental.artifact` | boolean | Enable artifact tools. Enabled by default. In interactive, non-SDK sessions, the model can publish a self-contained HTML page as an interactive Artifact and open it in the browser. Non-SDK daemon sessions can use metadata-only `record_artifact`. Set this to `false` or use `QWEN_CODE_DISABLE_ARTIFACT=1` to disable both. Requires restart. | `true` |
|
||||
| `experimental.emitToolUseSummaries` | boolean | Generate a short LLM-based label after each tool-call batch completes. See [Tool-Use Summaries](../features/tool-use-summaries). Requires a fast model to be configured (`fastModel`); silently skipped otherwise. Can be overridden per-session with `QWEN_CODE_EMIT_TOOL_USE_SUMMARIES=0` or `=1`. | `true` |
|
||||
| Setting | Type | Description | Default |
|
||||
| -------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- |
|
||||
| `experimental.sessionWorkflow` | boolean | Show the daemon Web Shell Session Workflow DAG and present the existing `plan` approval mode as **Plan & Review**. This changes presentation only: it does not add an approval mode, alter Todo execution behavior, or schedule dependencies. Changes take effect without restarting. | `false` |
|
||||
| `experimental.cron` | boolean | Enable in-session cron/loop tools (`cron_create`, `cron_list`, `cron_delete`) so the model can create recurring prompts. Can be disabled via the `QWEN_CODE_DISABLE_CRON=1` environment variable. Requires restart. | `true` |
|
||||
| `experimental.todoStopGuard` | boolean | Allow daemon and ACP sessions to continue after a natural model stop when the current work chain successfully wrote an unfinished top-level Todo list. Requires `tools.todoWrite.enabled`. Adds at most two consecutive primary-model calls without new user input; mid-turn user input starts a fresh two-attempt stage. It is not restored after process restart and is forced off in safe, bare, and Approval `plan` modes. Requires restart. | `false` |
|
||||
| `experimental.sessionWriterLease` | boolean | Enable cross-process write fencing for persisted ACP and daemon sessions. The value is frozen when the ACP or daemon process starts. All concurrent ACP writers must enable the setting; mixed versions or configurations remain unsafe. Interactive and headless recorders are unaffected. Requires process restart. | `false` |
|
||||
| `experimental.cronRecurringMaxAgeDays` | number | Days a recurring cron/loop job lives before auto-expiring (it fires one final time, then is deleted). Set to `0` to disable expiry so jobs run until deleted — useful for long-running daemon deployments. Can be overridden via the `QWEN_CODE_CRON_MAX_AGE_DAYS` environment variable. Requires restart. | `7` |
|
||||
| `experimental.agentTeam` | boolean | Enable agent-team collaboration tools (`team_create`, `task_create`, `task_update`, `send_message`, etc.) for multi-agent coordination. Can also be enabled via `QWEN_CODE_ENABLE_AGENT_TEAM=1`. Requires restart. | `false` |
|
||||
| `experimental.artifact` | boolean | Enable artifact tools. Enabled by default. In interactive, non-SDK sessions, the model can publish a self-contained HTML page as an interactive Artifact and open it in the browser. Non-SDK daemon sessions can use metadata-only `record_artifact`. Set this to `false` or use `QWEN_CODE_DISABLE_ARTIFACT=1` to disable both. Requires restart. | `true` |
|
||||
| `experimental.emitToolUseSummaries` | boolean | Generate a short LLM-based label after each tool-call batch completes. See [Tool-Use Summaries](../features/tool-use-summaries). Requires a fast model to be configured (`fastModel`); silently skipped otherwise. Can be overridden per-session with `QWEN_CODE_EMIT_TOOL_USE_SUMMARIES=0` or `=1`. | `true` |
|
||||
|
||||
#### mcpServers
|
||||
|
||||
|
||||
@@ -316,6 +316,11 @@ restart the daemon:
|
||||
{
|
||||
"experimental": {
|
||||
"todoStopGuard": true
|
||||
},
|
||||
"tools": {
|
||||
"todoWrite": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -335,8 +340,10 @@ coalesced per task until the chain yields.
|
||||
|
||||
The option defaults to `false`, requires restart, and is forced off in safe
|
||||
mode, bare mode, and Approval `plan` mode. It is in-memory only: loading Todo
|
||||
state from disk or restarting the daemon does not arm it. A new ordinary prompt
|
||||
must successfully run its own top-level `todo_write`; retry/continue and live
|
||||
state from disk or restarting the daemon does not arm it. Set
|
||||
`tools.todoWrite.enabled` in settings.json and restart Qwen Code, then a new
|
||||
ordinary prompt must successfully run its own top-level `todo_write`;
|
||||
retry/continue and live
|
||||
client reattach keep the current in-memory work chain. Successfully changing
|
||||
the session working directory clears it so an old Todo cannot resume in a new
|
||||
workspace.
|
||||
|
||||
@@ -5,14 +5,8 @@
|
||||
*/
|
||||
|
||||
import { describe, it, expect, afterEach, vi } from 'vitest';
|
||||
import {
|
||||
fakeServerHostOptions,
|
||||
IS_CONTAINER_SANDBOX,
|
||||
CONTAINER_SANDBOX_NO_PROXY,
|
||||
TestRig,
|
||||
} from '../test-helper.js';
|
||||
import { fakeToolCall, startFakeOpenAIServer } from '../fake-openai-server.js';
|
||||
import { join } from 'node:path';
|
||||
import { runForcedToolCallScenario, TestRig } from '../test-helper.js';
|
||||
import { fakeToolCall } from '../fake-openai-server.js';
|
||||
|
||||
/**
|
||||
* Drives a fake-server round trip whose first model response calls
|
||||
@@ -24,78 +18,37 @@ async function runListDirectoryScenario(options: {
|
||||
finalResponse: string;
|
||||
}): Promise<string> {
|
||||
const { rig, finalResponse } = options;
|
||||
|
||||
const noProxy = IS_CONTAINER_SANDBOX
|
||||
? CONTAINER_SANDBOX_NO_PROXY
|
||||
: '127.0.0.1,localhost';
|
||||
|
||||
let streamingRequestIndex = 0;
|
||||
const fakeServer = await startFakeOpenAIServer(({ body }) => {
|
||||
if (body['stream'] !== true) {
|
||||
return { content: '{"selected_memories":[]}' };
|
||||
}
|
||||
const requestIndex = streamingRequestIndex++;
|
||||
if (requestIndex === 0) {
|
||||
return {
|
||||
toolCalls: [
|
||||
fakeToolCall('list_directory', { path: rig.testDir! }, 'list-dir'),
|
||||
],
|
||||
};
|
||||
}
|
||||
return { content: finalResponse };
|
||||
}, fakeServerHostOptions());
|
||||
|
||||
vi.stubEnv('OPENAI_API_KEY', 'fake-key');
|
||||
vi.stubEnv('OPENAI_BASE_URL', fakeServer.baseUrl);
|
||||
vi.stubEnv('OPENAI_MODEL', 'fake-model');
|
||||
vi.stubEnv('QWEN_MODEL', 'fake-model');
|
||||
vi.stubEnv('QWEN_HOME', join(rig.testDir!, '.qwen-home'));
|
||||
vi.stubEnv('QWEN_RUNTIME_DIR', join(rig.testDir!, '.qwen-home'));
|
||||
vi.stubEnv('NO_PROXY', noProxy);
|
||||
vi.stubEnv('no_proxy', noProxy);
|
||||
|
||||
try {
|
||||
// Explicit CLI flags outrank a developer's ~/.qwen/settings.json
|
||||
// (settings.model.name beats the OPENAI_MODEL env var and can silently
|
||||
// route the run to a real model endpoint instead of the fake server).
|
||||
await rig.run(
|
||||
'Call the list_directory tool on the current directory.',
|
||||
'--auth-type',
|
||||
'openai',
|
||||
'--model',
|
||||
'fake-model',
|
||||
'--openai-base-url',
|
||||
fakeServer.baseUrl,
|
||||
'--openai-api-key',
|
||||
'fake-key',
|
||||
);
|
||||
|
||||
const toolResultRequest = fakeServer.requests.find(({ body }) => {
|
||||
const messages = body['messages'];
|
||||
return (
|
||||
Array.isArray(messages) &&
|
||||
messages.some(
|
||||
const requests = await runForcedToolCallScenario({
|
||||
rig,
|
||||
toolCall: fakeToolCall(
|
||||
'list_directory',
|
||||
{ path: rig.testDir! },
|
||||
'list-dir',
|
||||
),
|
||||
prompt: 'Call the list_directory tool on the current directory.',
|
||||
finalResponse,
|
||||
});
|
||||
const toolResultRequest = requests.find(({ messages }) =>
|
||||
Array.isArray(messages)
|
||||
? messages.some(
|
||||
(message) =>
|
||||
typeof message === 'object' &&
|
||||
message !== null &&
|
||||
'role' in message &&
|
||||
message.role === 'tool',
|
||||
)
|
||||
);
|
||||
});
|
||||
expect(
|
||||
toolResultRequest,
|
||||
'Expected a model request containing the list_directory result',
|
||||
).toBeDefined();
|
||||
const messages = toolResultRequest?.body['messages'] as
|
||||
| Array<{ role?: string; content?: unknown }>
|
||||
| undefined;
|
||||
return JSON.stringify(
|
||||
messages?.find((message) => message.role === 'tool')?.content ?? '',
|
||||
);
|
||||
} finally {
|
||||
await fakeServer.close();
|
||||
}
|
||||
: false,
|
||||
);
|
||||
expect(
|
||||
toolResultRequest,
|
||||
'Expected a model request containing the list_directory result',
|
||||
).toBeDefined();
|
||||
const messages = toolResultRequest?.['messages'] as
|
||||
| Array<{ role?: string; content?: unknown }>
|
||||
| undefined;
|
||||
return JSON.stringify(
|
||||
messages?.find((message) => message.role === 'tool')?.content ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
describe('list_directory', () => {
|
||||
|
||||
@@ -322,6 +322,7 @@ beforeAll(async () => {
|
||||
path.join(qwenHome, 'settings.json'),
|
||||
JSON.stringify({
|
||||
experimental: { todoStopGuard: true },
|
||||
tools: { todoWrite: { enabled: true } },
|
||||
ui: { enableFollowupSuggestions: false },
|
||||
}),
|
||||
);
|
||||
@@ -350,8 +351,8 @@ beforeAll(async () => {
|
||||
// tests below would all silently 404. A scratch workspace (not
|
||||
// the checkout) also keeps sessions hermetic: the daemon merges
|
||||
// the workspace's `.qwen/settings.json` into every session, and
|
||||
// a stray one on a shared runner (e.g. a `tools.sandbox` mode or
|
||||
// a `tools.core` allowlist missing `todo_write`) silently breaks
|
||||
// a stray one on a shared runner (e.g. a `tools.sandbox` mode or a
|
||||
// disabled `tools.todoWrite` setting) silently breaks
|
||||
// the Stop Guard flow below.
|
||||
'--workspace',
|
||||
workspaceDir,
|
||||
|
||||
@@ -4,17 +4,103 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { afterEach, describe, it, expect, vi } from 'vitest';
|
||||
import {
|
||||
runForcedToolCallScenario,
|
||||
TestRig,
|
||||
printDebugInfo,
|
||||
validateModelOutput,
|
||||
} from '../test-helper.js';
|
||||
import { fakeToolCall } from '../fake-openai-server.js';
|
||||
|
||||
async function runForcedTodoCall(rig: TestRig) {
|
||||
return runForcedToolCallScenario({
|
||||
rig,
|
||||
toolCall: fakeToolCall('todo_write', {
|
||||
todos: [{ id: '1', content: 'Verify Todo', status: 'pending' }],
|
||||
}),
|
||||
prompt: 'Complete the requested action.',
|
||||
finalResponse: 'done',
|
||||
});
|
||||
}
|
||||
|
||||
function inspectTodoRequests(requests: Array<Record<string, unknown>>) {
|
||||
const initialRequest = requests[0];
|
||||
const tools = (initialRequest?.['tools'] ?? []) as Array<{
|
||||
function?: { name?: string };
|
||||
}>;
|
||||
const systemMessage = (
|
||||
(initialRequest?.['messages'] ?? []) as Array<{
|
||||
role?: string;
|
||||
content?: unknown;
|
||||
}>
|
||||
).find(({ role }) => role === 'system');
|
||||
const toolResult = requests
|
||||
.flatMap(
|
||||
(request) =>
|
||||
((request?.['messages'] ?? []) as Array<{
|
||||
role?: string;
|
||||
content?: unknown;
|
||||
}>) ?? [],
|
||||
)
|
||||
.filter(({ role }) => role === 'tool')
|
||||
.map(({ content }) => JSON.stringify(content))
|
||||
.join('\n');
|
||||
return {
|
||||
tools,
|
||||
baseSystemPrompt: String(systemMessage?.content).split('\n\n---\n\n', 1)[0],
|
||||
toolResultRequest: JSON.stringify(requests[1]),
|
||||
toolResult,
|
||||
};
|
||||
}
|
||||
|
||||
describe('todo_write', () => {
|
||||
afterEach(() => {
|
||||
vi.unstubAllEnvs();
|
||||
});
|
||||
|
||||
it('should not declare todo_write by default', async () => {
|
||||
const rig = new TestRig();
|
||||
await rig.setup('should not declare todo_write by default');
|
||||
|
||||
const requests = await runForcedTodoCall(rig);
|
||||
const { tools, baseSystemPrompt, toolResultRequest } =
|
||||
inspectTodoRequests(requests);
|
||||
const toolDescriptionsWithTodo = tools
|
||||
.filter((tool) => JSON.stringify(tool).includes('todo_write'))
|
||||
.map((tool) => tool.function?.name);
|
||||
|
||||
expect(tools.map((tool) => tool.function?.name)).not.toContain(
|
||||
'todo_write',
|
||||
);
|
||||
expect(baseSystemPrompt).not.toContain('todo_write');
|
||||
expect(toolDescriptionsWithTodo).toEqual([]);
|
||||
expect(requests.length).toBeGreaterThanOrEqual(2);
|
||||
expect(toolResultRequest).toContain('disabled by default');
|
||||
expect(toolResultRequest).toContain('tools.todoWrite.enabled');
|
||||
});
|
||||
|
||||
it('should declare and execute todo_write when enabled', async () => {
|
||||
const rig = new TestRig();
|
||||
await rig.setup('should declare and execute todo_write when enabled', {
|
||||
settings: { tools: { todoWrite: { enabled: true } } },
|
||||
});
|
||||
|
||||
const requests = await runForcedTodoCall(rig);
|
||||
const { tools, baseSystemPrompt, toolResult } =
|
||||
inspectTodoRequests(requests);
|
||||
|
||||
expect(tools.map((tool) => tool.function?.name)).toContain('todo_write');
|
||||
expect(baseSystemPrompt).toContain('# Task Management');
|
||||
expect(toolResult).toContain('Verify Todo');
|
||||
expect(toolResult).not.toContain('disabled by default');
|
||||
});
|
||||
|
||||
it('should be able to create and manage a todo list', async () => {
|
||||
const rig = new TestRig();
|
||||
await rig.setup('should be able to create and manage a todo list');
|
||||
await rig.setup('should be able to create and manage a todo list', {
|
||||
settings: { tools: { todoWrite: { enabled: true } } },
|
||||
});
|
||||
|
||||
const prompt = `Please create a todo list with these three simple tasks:
|
||||
1. Buy milk
|
||||
|
||||
@@ -14,7 +14,12 @@ import fs from 'node:fs';
|
||||
import { EOL } from 'node:os';
|
||||
import * as pty from '@lydell/node-pty';
|
||||
import stripAnsi from 'strip-ansi';
|
||||
import type { FakeOpenAIServerOptions } from './fake-openai-server.js';
|
||||
import { vi } from 'vitest';
|
||||
import {
|
||||
startFakeOpenAIServer,
|
||||
type FakeOpenAIServerOptions,
|
||||
type FakeOpenAIToolCall,
|
||||
} from './fake-openai-server.js';
|
||||
import {
|
||||
e2eRendererEnv,
|
||||
pickE2eRenderer,
|
||||
@@ -966,3 +971,56 @@ export class TestRig {
|
||||
return { ptyProcess, promise };
|
||||
}
|
||||
}
|
||||
|
||||
export async function runForcedToolCallScenario(options: {
|
||||
rig: TestRig;
|
||||
toolCall: FakeOpenAIToolCall;
|
||||
prompt: string;
|
||||
finalResponse: string;
|
||||
}): Promise<Array<Record<string, unknown>>> {
|
||||
const { rig, toolCall, prompt, finalResponse } = options;
|
||||
let streamingRequestIndex = 0;
|
||||
const fakeServer = await startFakeOpenAIServer(({ body }) => {
|
||||
if (body['stream'] !== true) {
|
||||
return { content: '{"selected_memories":[]}' };
|
||||
}
|
||||
if (streamingRequestIndex++ === 0) {
|
||||
return { toolCalls: [toolCall] };
|
||||
}
|
||||
return { content: finalResponse };
|
||||
}, fakeServerHostOptions());
|
||||
|
||||
const noProxy = IS_CONTAINER_SANDBOX
|
||||
? CONTAINER_SANDBOX_NO_PROXY
|
||||
: '127.0.0.1,localhost';
|
||||
vi.stubEnv('OPENAI_API_KEY', 'fake-key');
|
||||
vi.stubEnv('OPENAI_BASE_URL', fakeServer.baseUrl);
|
||||
vi.stubEnv('OPENAI_MODEL', 'fake-model');
|
||||
vi.stubEnv('QWEN_MODEL', 'fake-model');
|
||||
vi.stubEnv('QWEN_HOME', join(rig.testDir!, '.qwen-home'));
|
||||
vi.stubEnv('QWEN_RUNTIME_DIR', join(rig.testDir!, '.qwen-home'));
|
||||
vi.stubEnv('NO_PROXY', noProxy);
|
||||
vi.stubEnv('no_proxy', noProxy);
|
||||
|
||||
try {
|
||||
// Explicit CLI flags outrank a developer's ~/.qwen/settings.json
|
||||
// (settings.model.name beats the OPENAI_MODEL env var and can silently
|
||||
// route the run to a real model endpoint instead of the fake server).
|
||||
await rig.run(
|
||||
prompt,
|
||||
'--auth-type',
|
||||
'openai',
|
||||
'--model',
|
||||
'fake-model',
|
||||
'--openai-base-url',
|
||||
fakeServer.baseUrl,
|
||||
'--openai-api-key',
|
||||
'fake-key',
|
||||
);
|
||||
return fakeServer.requests
|
||||
.filter(({ body }) => body['stream'] === true)
|
||||
.map(({ body }) => body);
|
||||
} finally {
|
||||
await fakeServer.close();
|
||||
}
|
||||
}
|
||||
@@ -929,6 +929,9 @@ describe('Session', () => {
|
||||
setSessionPrBoundCallback: vi.fn(),
|
||||
}),
|
||||
getToolRegistry: vi.fn().mockReturnValue(mockToolRegistry),
|
||||
getDisabledTools: vi.fn().mockReturnValue(new Set<string>()),
|
||||
getPermissionManager: vi.fn().mockReturnValue(null),
|
||||
isTodoWriteEnabled: vi.fn().mockReturnValue(false),
|
||||
getToolInvocationGuard: vi.fn().mockReturnValue(undefined),
|
||||
getFileService: vi.fn().mockReturnValue(fileService),
|
||||
getFileFilteringRespectGitIgnore: vi.fn().mockReturnValue(true),
|
||||
@@ -35314,11 +35317,17 @@ describe('Session', () => {
|
||||
bare?: boolean;
|
||||
plan?: boolean;
|
||||
disableHooks?: boolean;
|
||||
todoWriteEnabled?: boolean;
|
||||
} = {},
|
||||
) {
|
||||
session.dispose();
|
||||
(mockSettings as unknown as { merged: Record<string, unknown> }).merged =
|
||||
{ experimental: { todoStopGuard: true } };
|
||||
{
|
||||
experimental: { todoStopGuard: true },
|
||||
...(options.todoWriteEnabled === false
|
||||
? {}
|
||||
: { tools: { todoWrite: { enabled: true } } }),
|
||||
};
|
||||
mockConfig.getBareMode = vi.fn().mockReturnValue(options.bare ?? false);
|
||||
mockConfig.isSafeMode = vi.fn().mockReturnValue(options.safe ?? false);
|
||||
mockConfig.getApprovalMode = vi
|
||||
@@ -35453,6 +35462,58 @@ describe('Session', () => {
|
||||
});
|
||||
}
|
||||
|
||||
it('disables the guard and warns when todo_write is disabled', async () => {
|
||||
debugLoggerWarnSpy.mockClear();
|
||||
rebuildSessionWithGuard({ todoWriteEnabled: false });
|
||||
installPendingTodoTool();
|
||||
queuePendingTodoThenNaturalStops();
|
||||
|
||||
await runGuardPrompt();
|
||||
|
||||
expect(debugLoggerWarnSpy).toHaveBeenCalledWith(
|
||||
'experimental.todoStopGuard requires tools.todoWrite.enabled; the Todo Stop Guard is disabled.',
|
||||
);
|
||||
expect(mockChat.sendMessageStream).toHaveBeenCalledTimes(2);
|
||||
expect(
|
||||
vi
|
||||
.mocked(mockClient.sessionUpdate)
|
||||
.mock.calls.some(
|
||||
([params]) =>
|
||||
params.update.sessionUpdate === 'agent_message_chunk' &&
|
||||
params.update._meta?.['source'] === 'todo_stop_guard',
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it.each([
|
||||
['safe mode', { safe: true }],
|
||||
['bare mode', { bare: true }],
|
||||
] as const)('suppresses the missing Todo warning in %s', (_name, mode) => {
|
||||
debugLoggerWarnSpy.mockClear();
|
||||
rebuildSessionWithGuard({ ...mode, todoWriteEnabled: false });
|
||||
|
||||
expect(debugLoggerWarnSpy).not.toHaveBeenCalledWith(
|
||||
expect.stringContaining('tools.todoWrite.enabled'),
|
||||
);
|
||||
});
|
||||
|
||||
it('returns actionable Todo enablement guidance from daemon tool calls', async () => {
|
||||
rebuildSessionWithGuard({ todoWriteEnabled: false });
|
||||
mockToolRegistry.getTool.mockReturnValue(undefined);
|
||||
queuePendingTodoThenNaturalStops();
|
||||
|
||||
await runGuardPrompt();
|
||||
|
||||
expect(mockChat.sendMessageStream).toHaveBeenCalledTimes(2);
|
||||
const followUp = vi.mocked(mockChat.sendMessageStream).mock
|
||||
.calls[1][1] as {
|
||||
message: unknown;
|
||||
};
|
||||
expect(JSON.stringify(followUp.message)).toContain(
|
||||
'tools.todoWrite.enabled',
|
||||
);
|
||||
});
|
||||
|
||||
it('cleans up an admitted retry cancelled during previous-turn drain', async () => {
|
||||
rebuildSessionWithGuard();
|
||||
let releasePreviousTurn!: () => void;
|
||||
|
||||
@@ -113,6 +113,7 @@ import {
|
||||
getPlanModeSystemReminder,
|
||||
getArenaSystemReminder,
|
||||
getOutputStyleTurnReminder,
|
||||
getOptInToolNotFoundMessage,
|
||||
resolveMainSessionOutputStyle,
|
||||
wrapSystemReminder,
|
||||
isSystemReminderContent,
|
||||
@@ -2195,10 +2196,25 @@ export class Session implements SessionContext {
|
||||
? STANDALONE_SLASH_COMMAND_POLICY
|
||||
: undefined;
|
||||
this.runtimeBaseDir = config.storage.getRuntimeBaseDir();
|
||||
const todoStopGuardEnabled =
|
||||
this.settings.merged.experimental?.todoStopGuard === true &&
|
||||
const todoStopGuardConfigured =
|
||||
this.settings.merged.experimental?.todoStopGuard === true;
|
||||
const todoStopGuardModeAllowed =
|
||||
todoStopGuardConfigured &&
|
||||
!this.config.getBareMode() &&
|
||||
!this.config.isSafeMode();
|
||||
const todoWriteEnabled =
|
||||
this.settings.merged.tools?.todoWrite?.enabled === true;
|
||||
const todoStopGuardEnabled =
|
||||
todoStopGuardConfigured && todoStopGuardModeAllowed && todoWriteEnabled;
|
||||
if (
|
||||
todoStopGuardConfigured &&
|
||||
todoStopGuardModeAllowed &&
|
||||
!todoWriteEnabled
|
||||
) {
|
||||
debugLogger.warn(
|
||||
'experimental.todoStopGuard requires tools.todoWrite.enabled; the Todo Stop Guard is disabled.',
|
||||
);
|
||||
}
|
||||
// Capture the settings-derived gate value ONCE instead of tracking the
|
||||
// live settings view: this session's LoadedSettings is reloaded from
|
||||
// disk behind the session's back (e.g. `reloadSkillSettings` during a
|
||||
@@ -11576,8 +11592,15 @@ export class Session implements SessionContext {
|
||||
const tool = toolRegistry.getTool(toolName);
|
||||
|
||||
if (!tool) {
|
||||
const optInToolMessage = await getOptInToolNotFoundMessage(
|
||||
this.config,
|
||||
toolName,
|
||||
(canonicalName) => Boolean(toolRegistry.getTool(canonicalName)),
|
||||
);
|
||||
return earlyErrorResponse(
|
||||
new Error(`Tool "${toolName}" not found in registry.`),
|
||||
new Error(
|
||||
optInToolMessage ?? `Tool "${toolName}" not found in registry.`,
|
||||
),
|
||||
toolName,
|
||||
{
|
||||
status: 'error',
|
||||
|
||||
@@ -3362,6 +3362,23 @@ describe('mergeExcludeTools', () => {
|
||||
expect(config.isLsToolEnabled()).toBe(true);
|
||||
});
|
||||
|
||||
it('should default tools.todoWrite.enabled to false', async () => {
|
||||
process.argv = ['node', 'script.js'];
|
||||
const argv = await parseArguments();
|
||||
const config = await loadCliConfig({}, argv, undefined, []);
|
||||
expect(config.isTodoWriteEnabled()).toBe(false);
|
||||
});
|
||||
|
||||
it('should enable todo_write when tools.todoWrite.enabled is true', async () => {
|
||||
process.argv = ['node', 'script.js'];
|
||||
const argv = await parseArguments();
|
||||
const settings: Settings = {
|
||||
tools: { todoWrite: { enabled: true } },
|
||||
};
|
||||
const config = await loadCliConfig(settings, argv, undefined, []);
|
||||
expect(config.isTodoWriteEnabled()).toBe(true);
|
||||
});
|
||||
|
||||
it('should force tools.toolSearch.threshold to 0 in safe mode', async () => {
|
||||
process.argv = ['node', 'script.js', '--safe-mode'];
|
||||
const argv = await parseArguments();
|
||||
|
||||
@@ -2288,6 +2288,7 @@ export async function loadCliConfig(
|
||||
cronRecurringMaxAgeDays: settings.experimental?.cronRecurringMaxAgeDays,
|
||||
sessionWorkflowEnabled: settings.experimental?.sessionWorkflow ?? false,
|
||||
lsToolEnabled: settings.tools?.listDirectory?.enabled === true,
|
||||
todoWriteEnabled: settings.tools?.todoWrite?.enabled === true,
|
||||
agentTeamEnabled: settings.experimental?.agentTeam ?? false,
|
||||
artifactEnabled: settings.experimental?.artifact ?? true,
|
||||
artifactAutoOpen: settings.artifact?.autoOpen ?? true,
|
||||
|
||||
@@ -2730,6 +2730,28 @@ const SETTINGS_SCHEMA = {
|
||||
},
|
||||
},
|
||||
},
|
||||
todoWrite: {
|
||||
type: 'object',
|
||||
label: 'Todo Write',
|
||||
category: 'Tools',
|
||||
requiresRestart: true,
|
||||
default: {},
|
||||
description:
|
||||
'Settings for the built-in todo_write tool. Opt-in: the tool is disabled by default.',
|
||||
showInDialog: false,
|
||||
properties: {
|
||||
enabled: {
|
||||
type: 'boolean',
|
||||
label: 'Enable Todo Write',
|
||||
category: 'Tools',
|
||||
requiresRestart: true,
|
||||
default: false,
|
||||
description:
|
||||
'Enable the built-in todo_write tool and its system-prompt guidance.',
|
||||
showInDialog: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
shell: {
|
||||
type: 'object',
|
||||
label: 'Shell',
|
||||
@@ -3887,7 +3909,7 @@ const SETTINGS_SCHEMA = {
|
||||
requiresRestart: true,
|
||||
default: false,
|
||||
description:
|
||||
'Allow daemon and ACP sessions to continue an unfinished top-level Todo list for at most two consecutive primary-model calls without new user input. Mid-turn user input starts a fresh two-attempt stage. Disabled in safe, bare, and Approval plan modes.',
|
||||
'Allow daemon and ACP sessions to continue an unfinished top-level Todo list for at most two consecutive primary-model calls without new user input. Requires tools.todoWrite.enabled. Mid-turn user input starts a fresh two-attempt stage. Disabled in safe, bare, and Approval plan modes.',
|
||||
showInDialog: false,
|
||||
},
|
||||
sessionWriterLease: {
|
||||
|
||||
@@ -57,6 +57,7 @@ function makeMockConfig(contextWindowSize = 32_000): Config {
|
||||
getUserMemory: vi.fn().mockReturnValue(''),
|
||||
getSystemPrompt: vi.fn().mockReturnValue(undefined),
|
||||
getOutputStyle: vi.fn().mockReturnValue(undefined),
|
||||
isTodoWriteEnabled: vi.fn().mockReturnValue(false),
|
||||
getAutoMemoryPrompt: vi.fn().mockReturnValue(''),
|
||||
getSkillManager: vi.fn().mockReturnValue({
|
||||
listSkills: vi.fn().mockResolvedValue([]),
|
||||
@@ -95,6 +96,7 @@ describe('collectContextData (contextCommand)', () => {
|
||||
getUserMemory: vi.fn().mockReturnValue(''),
|
||||
getSystemPrompt: vi.fn().mockReturnValue(undefined),
|
||||
getOutputStyle: vi.fn().mockReturnValue(undefined),
|
||||
isTodoWriteEnabled: vi.fn().mockReturnValue(false),
|
||||
getAutoMemoryPrompt: vi.fn().mockReturnValue(''),
|
||||
getSkillManager: vi.fn().mockReturnValue({
|
||||
listSkills: vi.fn().mockResolvedValue([]),
|
||||
@@ -224,6 +226,7 @@ describe('collectContextData (contextCommand)', () => {
|
||||
getUserMemory: vi.fn().mockReturnValue(''),
|
||||
getSystemPrompt: vi.fn().mockReturnValue(undefined),
|
||||
getOutputStyle: vi.fn().mockReturnValue(undefined),
|
||||
isTodoWriteEnabled: vi.fn().mockReturnValue(false),
|
||||
getAutoMemoryPrompt: vi.fn().mockReturnValue(''),
|
||||
getSkillManager: vi.fn().mockReturnValue({
|
||||
listSkills: vi.fn().mockResolvedValue([]),
|
||||
@@ -273,6 +276,7 @@ describe('collectContextData (contextCommand)', () => {
|
||||
getUserMemory: vi.fn().mockReturnValue(''),
|
||||
getSystemPrompt: vi.fn().mockReturnValue(undefined),
|
||||
getOutputStyle: vi.fn().mockReturnValue(undefined),
|
||||
isTodoWriteEnabled: vi.fn().mockReturnValue(false),
|
||||
getAutoMemoryPrompt: vi.fn().mockReturnValue(''),
|
||||
getSkillManager: vi.fn().mockReturnValue({
|
||||
listSkills: vi.fn().mockResolvedValue([]),
|
||||
|
||||
@@ -74,6 +74,7 @@ const createMockConfig = (
|
||||
getSessionId: () => 'test-session',
|
||||
getUserMemory: () => '',
|
||||
getOutputStyle: (): ReturnType<typeof getBuiltInOutputStyle> => undefined,
|
||||
isTodoWriteEnabled: () => false,
|
||||
// Read by resolveMainSessionOutputStyle: the peer inherits the style the
|
||||
// main session actually carries, so the main session's prompt-override and
|
||||
// interaction-mode state is part of that decision.
|
||||
@@ -424,6 +425,7 @@ describe('ArenaManager', () => {
|
||||
mockConfig = {
|
||||
...createMockConfig(tempDir, { worktreeBaseDir: tempDir }),
|
||||
getOutputStyle: () => getBuiltInOutputStyle('Concise'),
|
||||
isTodoWriteEnabled: () => true,
|
||||
};
|
||||
const manager = new ArenaManager(mockConfig as never);
|
||||
|
||||
@@ -442,6 +444,7 @@ describe('ArenaManager', () => {
|
||||
'This is a non-interactive, single-turn run',
|
||||
);
|
||||
expect(systemPrompt).toContain('# Output Style: Concise');
|
||||
expect(systemPrompt).toContain('# Task Management');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1111,6 +1111,7 @@ export class ArenaManager {
|
||||
undefined,
|
||||
'headless',
|
||||
this.resolvePeerOutputStyle(),
|
||||
this.config.isTodoWriteEnabled(),
|
||||
),
|
||||
contextFiles: this.config.getUserMemory(),
|
||||
}),
|
||||
|
||||
@@ -9511,6 +9511,34 @@ describe('Server Config (config.ts)', () => {
|
||||
).toContain(ToolNames.LS);
|
||||
});
|
||||
|
||||
it('does not register todo_write by default', async () => {
|
||||
const config = new Config(baseParams);
|
||||
await config.initialize();
|
||||
|
||||
const registerToolMock = (
|
||||
(await vi.importMock('../tools/tool-registry')) as {
|
||||
ToolRegistry: { prototype: { registerFactory: Mock } };
|
||||
}
|
||||
).ToolRegistry.prototype.registerFactory;
|
||||
expect(
|
||||
(registerToolMock as Mock).mock.calls.map((call) => call[0]),
|
||||
).not.toContain(ToolNames.TODO_WRITE);
|
||||
});
|
||||
|
||||
it('registers todo_write when todoWriteEnabled is true', async () => {
|
||||
const config = new Config({ ...baseParams, todoWriteEnabled: true });
|
||||
await config.initialize();
|
||||
|
||||
const registerToolMock = (
|
||||
(await vi.importMock('../tools/tool-registry')) as {
|
||||
ToolRegistry: { prototype: { registerFactory: Mock } };
|
||||
}
|
||||
).ToolRegistry.prototype.registerFactory;
|
||||
expect(
|
||||
(registerToolMock as Mock).mock.calls.map((call) => call[0]),
|
||||
).toContain(ToolNames.TODO_WRITE);
|
||||
});
|
||||
|
||||
it.each([
|
||||
{ label: 'the canonical name', entry: ToolNames.LS },
|
||||
{ label: 'an alias', entry: 'ListFiles' },
|
||||
@@ -9910,6 +9938,7 @@ describe('Server Config (config.ts)', () => {
|
||||
...baseParams,
|
||||
useRipgrep: false,
|
||||
coreTools: undefined,
|
||||
todoWriteEnabled: true,
|
||||
// Mirrors the CLI wiring. `permissions.allow` is deliberately left
|
||||
// unset: the eager/deferred split is driven solely by tools.eager
|
||||
// (#10075).
|
||||
@@ -10072,11 +10101,12 @@ describe('Server Config (config.ts)', () => {
|
||||
(call) => call[0],
|
||||
) as string[];
|
||||
|
||||
// Without an allowlist nothing is gated at registry level
|
||||
// Without an allowlist ordinary built-ins are not gated at registry
|
||||
// level, but opt-in tools remain disabled.
|
||||
expect(registered).toContain(ToolNames.SEND_MESSAGE);
|
||||
expect(registered).toContain(ToolNames.UPDATE_GOAL);
|
||||
expect(registered).toContain(ToolNames.AGENT);
|
||||
expect(registered).toContain(ToolNames.TODO_WRITE);
|
||||
expect(registered).not.toContain(ToolNames.TODO_WRITE);
|
||||
expect(registered).toContain(ToolNames.READ_FILE);
|
||||
});
|
||||
|
||||
|
||||
@@ -1088,6 +1088,8 @@ export interface ConfigParameters {
|
||||
* listing the tool in the `coreTools` allowlist also re-enables it.
|
||||
*/
|
||||
lsToolEnabled?: boolean;
|
||||
/** Opt-in flag for the built-in `todo_write` tool. */
|
||||
todoWriteEnabled?: boolean;
|
||||
agentTeamEnabled?: boolean;
|
||||
workflowsEnabled?: boolean;
|
||||
/** Enable the opt-in ACP/Web Shell Session Workflow gate. */
|
||||
@@ -2362,6 +2364,7 @@ export class Config {
|
||||
* (the setting declares `requiresRestart`); `Infinity` = no expiry. */
|
||||
private readonly cronRecurringMaxAgeDays: number;
|
||||
private readonly lsToolEnabled: boolean = false;
|
||||
private readonly todoWriteEnabled: boolean = false;
|
||||
private readonly agentTeamEnabled: boolean = false;
|
||||
private readonly artifactEnabled: boolean = true;
|
||||
private readonly artifactAutoOpen: boolean = true;
|
||||
@@ -2681,6 +2684,7 @@ export class Config {
|
||||
params.cronRecurringMaxAgeDays,
|
||||
);
|
||||
this.lsToolEnabled = params.lsToolEnabled ?? false;
|
||||
this.todoWriteEnabled = params.todoWriteEnabled ?? false;
|
||||
this.agentTeamEnabled = params.agentTeamEnabled ?? false;
|
||||
this.artifactEnabled = params.artifactEnabled ?? true;
|
||||
this.artifactAutoOpen = params.artifactAutoOpen ?? true;
|
||||
@@ -7702,6 +7706,10 @@ export class Config {
|
||||
);
|
||||
}
|
||||
|
||||
isTodoWriteEnabled(): boolean {
|
||||
return this.todoWriteEnabled;
|
||||
}
|
||||
|
||||
isAgentTeamEnabled(): boolean {
|
||||
// Agent team is experimental and opt-in: enabled via settings or env var
|
||||
if (process.env['QWEN_CODE_ENABLE_AGENT_TEAM'] === '1') return true;
|
||||
@@ -9567,10 +9575,12 @@ export class Config {
|
||||
const { ShellTool } = await import('../tools/shell.js');
|
||||
return new ShellTool(this);
|
||||
});
|
||||
await registerLazy(ToolNames.TODO_WRITE, async () => {
|
||||
const { TodoWriteTool } = await import('../tools/todoWrite.js');
|
||||
return new TodoWriteTool(this);
|
||||
});
|
||||
if (this.isTodoWriteEnabled()) {
|
||||
await registerLazy(ToolNames.TODO_WRITE, async () => {
|
||||
const { TodoWriteTool } = await import('../tools/todoWrite.js');
|
||||
return new TodoWriteTool(this);
|
||||
});
|
||||
}
|
||||
await registerLazy(ToolNames.REPORT_FINDINGS, async () => {
|
||||
const { ReportFindingsTool } = await import(
|
||||
'../tools/report-findings.js'
|
||||
|
||||
@@ -19,22 +19,13 @@ exports[`Core System Prompt (prompts.ts) > should append userMemory with separat
|
||||
- **Plan before uncertain work:** If the task is not yet clear enough to safely execute, do not make small speculative edits. Continue read-only investigation, make a plan in the current mode, or follow the active interaction mode's question guidance. Do not enter plan mode or call enter_plan_mode on your own just because the task involves planning or complexity. Use plan mode only when the user explicitly asks you to switch to plan mode, has already enabled it, or confirms they want it.
|
||||
|
||||
|
||||
# Task Management
|
||||
You have access to the todo_write tool to keep user-visible progress for work that benefits from explicit tracking. Use it for complex, ambiguous, or multi-phase tasks or requests with multiple independent outcomes. Do not use it for simple or single-step queries that you can answer or complete immediately unless the user explicitly asks for a plan.
|
||||
|
||||
When you create a todo list:
|
||||
- Keep it short and outcome-oriented. Use a few meaningful, logically ordered, verifiable steps rather than one item per error, file, command, or minor edit.
|
||||
- When an active Todo plan covers work delegated through top-level Agent calls, pass the matching Todo ID as \`todo_id\` so the execution can be associated with that plan node. Do not create a Todo solely to wrap a delegation that does not otherwise need task tracking.
|
||||
- Keep at most one item in_progress. Keep the list current, mark finished work completed, and revise it when the scope or approach changes. When work completes together, update multiple statuses in one tool call rather than making bookkeeping-only calls.
|
||||
- Do not repeat the full todo list in prose after calling the tool; briefly communicate only important context or the next step.
|
||||
|
||||
# Primary Workflows
|
||||
|
||||
## Software Engineering Tasks
|
||||
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this iterative approach:
|
||||
- **Plan:** Use 'todo_write' for complex, ambiguous, or multi-step work when visible progress tracking adds value. Keep the plan short and outcome-oriented; skip it for simple tasks unless the user explicitly requests a plan.
|
||||
- **Plan:** For complex, ambiguous, or multi-step work, form a concise, outcome-oriented approach and revise it as you learn. Skip formal planning for simple tasks unless the user explicitly requests a plan.
|
||||
- **Implement:** Begin implementing while gathering context as needed. Use available search and editing tools strategically, adhering to project conventions (see 'Core Mandates'). Do not add features, refactor code, or make "improvements" beyond what was asked. Don't add error handling, fallbacks, or validation for scenarios that can't happen—only validate at system boundaries (user input, external APIs). Don't create helpers, utilities, or abstractions for one-time operations. Three similar lines of code is better than a premature abstraction. Prefer editing existing files over creating new ones.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If a todo list exists, keep it current as the scope or approach changes. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands. Before reporting a task complete, verify it actually works. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.
|
||||
- **Verify (Standards):** When your task involves a code or system change, 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 (or obtained from the user). This ensures code quality and adherence to standards. Read-only or explanatory turns do not require verification.
|
||||
- **Report outcomes faithfully:** If tests fail, say so with the relevant output. If you did not run a verification step, say that rather than implying it succeeded. Never claim "all tests pass" when output shows failures, never suppress failing checks to manufacture a green result, and never characterize incomplete or broken work as done.
|
||||
@@ -78,7 +69,6 @@ Final responses should be concise by default, but their shape and depth must mat
|
||||
- To search the content of files, use 'grep_search' instead of grep or rg
|
||||
- Reserve using the 'run_shell_command' exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool and only fallback on using the 'run_shell_command' tool for these if it is absolutely necessary.
|
||||
- **Tool Fallback:** If a tool returns empty, unhelpful, or unexpected results, try an alternative tool that can accomplish the same goal before telling the user it cannot be done. Never give up after a single tool failure.
|
||||
- **Task Management:** Use 'todo_write' only when explicit tracking adds value. Keep plans concise, outcome-oriented, and current; do not create a todo list for simple or single-step work unless the user explicitly requests one.
|
||||
- **Parallel Tool Calls:** You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead.
|
||||
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
|
||||
- **Background Processes:** Use background execution with \`is_background: true\` for commands that are unlikely to stop on their own, e.g. \`node server.js\`. Do not append a trailing \`&\` when using the shell tool's managed background mode. If unsure, follow the active interaction mode's question guidance.
|
||||
@@ -219,22 +209,13 @@ exports[`Core System Prompt (prompts.ts) > should include git instructions when
|
||||
- **Plan before uncertain work:** If the task is not yet clear enough to safely execute, do not make small speculative edits. Continue read-only investigation, make a plan in the current mode, or follow the active interaction mode's question guidance. Do not enter plan mode or call enter_plan_mode on your own just because the task involves planning or complexity. Use plan mode only when the user explicitly asks you to switch to plan mode, has already enabled it, or confirms they want it.
|
||||
|
||||
|
||||
# Task Management
|
||||
You have access to the todo_write tool to keep user-visible progress for work that benefits from explicit tracking. Use it for complex, ambiguous, or multi-phase tasks or requests with multiple independent outcomes. Do not use it for simple or single-step queries that you can answer or complete immediately unless the user explicitly asks for a plan.
|
||||
|
||||
When you create a todo list:
|
||||
- Keep it short and outcome-oriented. Use a few meaningful, logically ordered, verifiable steps rather than one item per error, file, command, or minor edit.
|
||||
- When an active Todo plan covers work delegated through top-level Agent calls, pass the matching Todo ID as \`todo_id\` so the execution can be associated with that plan node. Do not create a Todo solely to wrap a delegation that does not otherwise need task tracking.
|
||||
- Keep at most one item in_progress. Keep the list current, mark finished work completed, and revise it when the scope or approach changes. When work completes together, update multiple statuses in one tool call rather than making bookkeeping-only calls.
|
||||
- Do not repeat the full todo list in prose after calling the tool; briefly communicate only important context or the next step.
|
||||
|
||||
# Primary Workflows
|
||||
|
||||
## Software Engineering Tasks
|
||||
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this iterative approach:
|
||||
- **Plan:** Use 'todo_write' for complex, ambiguous, or multi-step work when visible progress tracking adds value. Keep the plan short and outcome-oriented; skip it for simple tasks unless the user explicitly requests a plan.
|
||||
- **Plan:** For complex, ambiguous, or multi-step work, form a concise, outcome-oriented approach and revise it as you learn. Skip formal planning for simple tasks unless the user explicitly requests a plan.
|
||||
- **Implement:** Begin implementing while gathering context as needed. Use available search and editing tools strategically, adhering to project conventions (see 'Core Mandates'). Do not add features, refactor code, or make "improvements" beyond what was asked. Don't add error handling, fallbacks, or validation for scenarios that can't happen—only validate at system boundaries (user input, external APIs). Don't create helpers, utilities, or abstractions for one-time operations. Three similar lines of code is better than a premature abstraction. Prefer editing existing files over creating new ones.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If a todo list exists, keep it current as the scope or approach changes. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands. Before reporting a task complete, verify it actually works. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.
|
||||
- **Verify (Standards):** When your task involves a code or system change, 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 (or obtained from the user). This ensures code quality and adherence to standards. Read-only or explanatory turns do not require verification.
|
||||
- **Report outcomes faithfully:** If tests fail, say so with the relevant output. If you did not run a verification step, say that rather than implying it succeeded. Never claim "all tests pass" when output shows failures, never suppress failing checks to manufacture a green result, and never characterize incomplete or broken work as done.
|
||||
@@ -278,7 +259,6 @@ Final responses should be concise by default, but their shape and depth must mat
|
||||
- To search the content of files, use 'grep_search' instead of grep or rg
|
||||
- Reserve using the 'run_shell_command' exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool and only fallback on using the 'run_shell_command' tool for these if it is absolutely necessary.
|
||||
- **Tool Fallback:** If a tool returns empty, unhelpful, or unexpected results, try an alternative tool that can accomplish the same goal before telling the user it cannot be done. Never give up after a single tool failure.
|
||||
- **Task Management:** Use 'todo_write' only when explicit tracking adds value. Keep plans concise, outcome-oriented, and current; do not create a todo list for simple or single-step work unless the user explicitly requests one.
|
||||
- **Parallel Tool Calls:** You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead.
|
||||
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
|
||||
- **Background Processes:** Use background execution with \`is_background: true\` for commands that are unlikely to stop on their own, e.g. \`node server.js\`. Do not append a trailing \`&\` when using the shell tool's managed background mode. If unsure, follow the active interaction mode's question guidance.
|
||||
@@ -435,22 +415,13 @@ exports[`Core System Prompt (prompts.ts) > should include non-sandbox instructio
|
||||
- **Plan before uncertain work:** If the task is not yet clear enough to safely execute, do not make small speculative edits. Continue read-only investigation, make a plan in the current mode, or follow the active interaction mode's question guidance. Do not enter plan mode or call enter_plan_mode on your own just because the task involves planning or complexity. Use plan mode only when the user explicitly asks you to switch to plan mode, has already enabled it, or confirms they want it.
|
||||
|
||||
|
||||
# Task Management
|
||||
You have access to the todo_write tool to keep user-visible progress for work that benefits from explicit tracking. Use it for complex, ambiguous, or multi-phase tasks or requests with multiple independent outcomes. Do not use it for simple or single-step queries that you can answer or complete immediately unless the user explicitly asks for a plan.
|
||||
|
||||
When you create a todo list:
|
||||
- Keep it short and outcome-oriented. Use a few meaningful, logically ordered, verifiable steps rather than one item per error, file, command, or minor edit.
|
||||
- When an active Todo plan covers work delegated through top-level Agent calls, pass the matching Todo ID as \`todo_id\` so the execution can be associated with that plan node. Do not create a Todo solely to wrap a delegation that does not otherwise need task tracking.
|
||||
- Keep at most one item in_progress. Keep the list current, mark finished work completed, and revise it when the scope or approach changes. When work completes together, update multiple statuses in one tool call rather than making bookkeeping-only calls.
|
||||
- Do not repeat the full todo list in prose after calling the tool; briefly communicate only important context or the next step.
|
||||
|
||||
# Primary Workflows
|
||||
|
||||
## Software Engineering Tasks
|
||||
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this iterative approach:
|
||||
- **Plan:** Use 'todo_write' for complex, ambiguous, or multi-step work when visible progress tracking adds value. Keep the plan short and outcome-oriented; skip it for simple tasks unless the user explicitly requests a plan.
|
||||
- **Plan:** For complex, ambiguous, or multi-step work, form a concise, outcome-oriented approach and revise it as you learn. Skip formal planning for simple tasks unless the user explicitly requests a plan.
|
||||
- **Implement:** Begin implementing while gathering context as needed. Use available search and editing tools strategically, adhering to project conventions (see 'Core Mandates'). Do not add features, refactor code, or make "improvements" beyond what was asked. Don't add error handling, fallbacks, or validation for scenarios that can't happen—only validate at system boundaries (user input, external APIs). Don't create helpers, utilities, or abstractions for one-time operations. Three similar lines of code is better than a premature abstraction. Prefer editing existing files over creating new ones.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If a todo list exists, keep it current as the scope or approach changes. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands. Before reporting a task complete, verify it actually works. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.
|
||||
- **Verify (Standards):** When your task involves a code or system change, 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 (or obtained from the user). This ensures code quality and adherence to standards. Read-only or explanatory turns do not require verification.
|
||||
- **Report outcomes faithfully:** If tests fail, say so with the relevant output. If you did not run a verification step, say that rather than implying it succeeded. Never claim "all tests pass" when output shows failures, never suppress failing checks to manufacture a green result, and never characterize incomplete or broken work as done.
|
||||
@@ -494,7 +465,6 @@ Final responses should be concise by default, but their shape and depth must mat
|
||||
- To search the content of files, use 'grep_search' instead of grep or rg
|
||||
- Reserve using the 'run_shell_command' exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool and only fallback on using the 'run_shell_command' tool for these if it is absolutely necessary.
|
||||
- **Tool Fallback:** If a tool returns empty, unhelpful, or unexpected results, try an alternative tool that can accomplish the same goal before telling the user it cannot be done. Never give up after a single tool failure.
|
||||
- **Task Management:** Use 'todo_write' only when explicit tracking adds value. Keep plans concise, outcome-oriented, and current; do not create a todo list for simple or single-step work unless the user explicitly requests one.
|
||||
- **Parallel Tool Calls:** You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead.
|
||||
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
|
||||
- **Background Processes:** Use background execution with \`is_background: true\` for commands that are unlikely to stop on their own, e.g. \`node server.js\`. Do not append a trailing \`&\` when using the shell tool's managed background mode. If unsure, follow the active interaction mode's question guidance.
|
||||
@@ -630,22 +600,13 @@ exports[`Core System Prompt (prompts.ts) > should include sandbox-specific instr
|
||||
- **Plan before uncertain work:** If the task is not yet clear enough to safely execute, do not make small speculative edits. Continue read-only investigation, make a plan in the current mode, or follow the active interaction mode's question guidance. Do not enter plan mode or call enter_plan_mode on your own just because the task involves planning or complexity. Use plan mode only when the user explicitly asks you to switch to plan mode, has already enabled it, or confirms they want it.
|
||||
|
||||
|
||||
# Task Management
|
||||
You have access to the todo_write tool to keep user-visible progress for work that benefits from explicit tracking. Use it for complex, ambiguous, or multi-phase tasks or requests with multiple independent outcomes. Do not use it for simple or single-step queries that you can answer or complete immediately unless the user explicitly asks for a plan.
|
||||
|
||||
When you create a todo list:
|
||||
- Keep it short and outcome-oriented. Use a few meaningful, logically ordered, verifiable steps rather than one item per error, file, command, or minor edit.
|
||||
- When an active Todo plan covers work delegated through top-level Agent calls, pass the matching Todo ID as \`todo_id\` so the execution can be associated with that plan node. Do not create a Todo solely to wrap a delegation that does not otherwise need task tracking.
|
||||
- Keep at most one item in_progress. Keep the list current, mark finished work completed, and revise it when the scope or approach changes. When work completes together, update multiple statuses in one tool call rather than making bookkeeping-only calls.
|
||||
- Do not repeat the full todo list in prose after calling the tool; briefly communicate only important context or the next step.
|
||||
|
||||
# Primary Workflows
|
||||
|
||||
## Software Engineering Tasks
|
||||
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this iterative approach:
|
||||
- **Plan:** Use 'todo_write' for complex, ambiguous, or multi-step work when visible progress tracking adds value. Keep the plan short and outcome-oriented; skip it for simple tasks unless the user explicitly requests a plan.
|
||||
- **Plan:** For complex, ambiguous, or multi-step work, form a concise, outcome-oriented approach and revise it as you learn. Skip formal planning for simple tasks unless the user explicitly requests a plan.
|
||||
- **Implement:** Begin implementing while gathering context as needed. Use available search and editing tools strategically, adhering to project conventions (see 'Core Mandates'). Do not add features, refactor code, or make "improvements" beyond what was asked. Don't add error handling, fallbacks, or validation for scenarios that can't happen—only validate at system boundaries (user input, external APIs). Don't create helpers, utilities, or abstractions for one-time operations. Three similar lines of code is better than a premature abstraction. Prefer editing existing files over creating new ones.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If a todo list exists, keep it current as the scope or approach changes. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands. Before reporting a task complete, verify it actually works. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.
|
||||
- **Verify (Standards):** When your task involves a code or system change, 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 (or obtained from the user). This ensures code quality and adherence to standards. Read-only or explanatory turns do not require verification.
|
||||
- **Report outcomes faithfully:** If tests fail, say so with the relevant output. If you did not run a verification step, say that rather than implying it succeeded. Never claim "all tests pass" when output shows failures, never suppress failing checks to manufacture a green result, and never characterize incomplete or broken work as done.
|
||||
@@ -689,7 +650,6 @@ Final responses should be concise by default, but their shape and depth must mat
|
||||
- To search the content of files, use 'grep_search' instead of grep or rg
|
||||
- Reserve using the 'run_shell_command' exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool and only fallback on using the 'run_shell_command' tool for these if it is absolutely necessary.
|
||||
- **Tool Fallback:** If a tool returns empty, unhelpful, or unexpected results, try an alternative tool that can accomplish the same goal before telling the user it cannot be done. Never give up after a single tool failure.
|
||||
- **Task Management:** Use 'todo_write' only when explicit tracking adds value. Keep plans concise, outcome-oriented, and current; do not create a todo list for simple or single-step work unless the user explicitly requests one.
|
||||
- **Parallel Tool Calls:** You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead.
|
||||
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
|
||||
- **Background Processes:** Use background execution with \`is_background: true\` for commands that are unlikely to stop on their own, e.g. \`node server.js\`. Do not append a trailing \`&\` when using the shell tool's managed background mode. If unsure, follow the active interaction mode's question guidance.
|
||||
@@ -825,22 +785,13 @@ exports[`Core System Prompt (prompts.ts) > should include seatbelt-specific inst
|
||||
- **Plan before uncertain work:** If the task is not yet clear enough to safely execute, do not make small speculative edits. Continue read-only investigation, make a plan in the current mode, or follow the active interaction mode's question guidance. Do not enter plan mode or call enter_plan_mode on your own just because the task involves planning or complexity. Use plan mode only when the user explicitly asks you to switch to plan mode, has already enabled it, or confirms they want it.
|
||||
|
||||
|
||||
# Task Management
|
||||
You have access to the todo_write tool to keep user-visible progress for work that benefits from explicit tracking. Use it for complex, ambiguous, or multi-phase tasks or requests with multiple independent outcomes. Do not use it for simple or single-step queries that you can answer or complete immediately unless the user explicitly asks for a plan.
|
||||
|
||||
When you create a todo list:
|
||||
- Keep it short and outcome-oriented. Use a few meaningful, logically ordered, verifiable steps rather than one item per error, file, command, or minor edit.
|
||||
- When an active Todo plan covers work delegated through top-level Agent calls, pass the matching Todo ID as \`todo_id\` so the execution can be associated with that plan node. Do not create a Todo solely to wrap a delegation that does not otherwise need task tracking.
|
||||
- Keep at most one item in_progress. Keep the list current, mark finished work completed, and revise it when the scope or approach changes. When work completes together, update multiple statuses in one tool call rather than making bookkeeping-only calls.
|
||||
- Do not repeat the full todo list in prose after calling the tool; briefly communicate only important context or the next step.
|
||||
|
||||
# Primary Workflows
|
||||
|
||||
## Software Engineering Tasks
|
||||
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this iterative approach:
|
||||
- **Plan:** Use 'todo_write' for complex, ambiguous, or multi-step work when visible progress tracking adds value. Keep the plan short and outcome-oriented; skip it for simple tasks unless the user explicitly requests a plan.
|
||||
- **Plan:** For complex, ambiguous, or multi-step work, form a concise, outcome-oriented approach and revise it as you learn. Skip formal planning for simple tasks unless the user explicitly requests a plan.
|
||||
- **Implement:** Begin implementing while gathering context as needed. Use available search and editing tools strategically, adhering to project conventions (see 'Core Mandates'). Do not add features, refactor code, or make "improvements" beyond what was asked. Don't add error handling, fallbacks, or validation for scenarios that can't happen—only validate at system boundaries (user input, external APIs). Don't create helpers, utilities, or abstractions for one-time operations. Three similar lines of code is better than a premature abstraction. Prefer editing existing files over creating new ones.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If a todo list exists, keep it current as the scope or approach changes. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands. Before reporting a task complete, verify it actually works. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.
|
||||
- **Verify (Standards):** When your task involves a code or system change, 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 (or obtained from the user). This ensures code quality and adherence to standards. Read-only or explanatory turns do not require verification.
|
||||
- **Report outcomes faithfully:** If tests fail, say so with the relevant output. If you did not run a verification step, say that rather than implying it succeeded. Never claim "all tests pass" when output shows failures, never suppress failing checks to manufacture a green result, and never characterize incomplete or broken work as done.
|
||||
@@ -884,7 +835,6 @@ Final responses should be concise by default, but their shape and depth must mat
|
||||
- To search the content of files, use 'grep_search' instead of grep or rg
|
||||
- Reserve using the 'run_shell_command' exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool and only fallback on using the 'run_shell_command' tool for these if it is absolutely necessary.
|
||||
- **Tool Fallback:** If a tool returns empty, unhelpful, or unexpected results, try an alternative tool that can accomplish the same goal before telling the user it cannot be done. Never give up after a single tool failure.
|
||||
- **Task Management:** Use 'todo_write' only when explicit tracking adds value. Keep plans concise, outcome-oriented, and current; do not create a todo list for simple or single-step work unless the user explicitly requests one.
|
||||
- **Parallel Tool Calls:** You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead.
|
||||
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
|
||||
- **Background Processes:** Use background execution with \`is_background: true\` for commands that are unlikely to stop on their own, e.g. \`node server.js\`. Do not append a trailing \`&\` when using the shell tool's managed background mode. If unsure, follow the active interaction mode's question guidance.
|
||||
@@ -1020,22 +970,13 @@ exports[`Core System Prompt (prompts.ts) > should not include git instructions w
|
||||
- **Plan before uncertain work:** If the task is not yet clear enough to safely execute, do not make small speculative edits. Continue read-only investigation, make a plan in the current mode, or follow the active interaction mode's question guidance. Do not enter plan mode or call enter_plan_mode on your own just because the task involves planning or complexity. Use plan mode only when the user explicitly asks you to switch to plan mode, has already enabled it, or confirms they want it.
|
||||
|
||||
|
||||
# Task Management
|
||||
You have access to the todo_write tool to keep user-visible progress for work that benefits from explicit tracking. Use it for complex, ambiguous, or multi-phase tasks or requests with multiple independent outcomes. Do not use it for simple or single-step queries that you can answer or complete immediately unless the user explicitly asks for a plan.
|
||||
|
||||
When you create a todo list:
|
||||
- Keep it short and outcome-oriented. Use a few meaningful, logically ordered, verifiable steps rather than one item per error, file, command, or minor edit.
|
||||
- When an active Todo plan covers work delegated through top-level Agent calls, pass the matching Todo ID as \`todo_id\` so the execution can be associated with that plan node. Do not create a Todo solely to wrap a delegation that does not otherwise need task tracking.
|
||||
- Keep at most one item in_progress. Keep the list current, mark finished work completed, and revise it when the scope or approach changes. When work completes together, update multiple statuses in one tool call rather than making bookkeeping-only calls.
|
||||
- Do not repeat the full todo list in prose after calling the tool; briefly communicate only important context or the next step.
|
||||
|
||||
# Primary Workflows
|
||||
|
||||
## Software Engineering Tasks
|
||||
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this iterative approach:
|
||||
- **Plan:** Use 'todo_write' for complex, ambiguous, or multi-step work when visible progress tracking adds value. Keep the plan short and outcome-oriented; skip it for simple tasks unless the user explicitly requests a plan.
|
||||
- **Plan:** For complex, ambiguous, or multi-step work, form a concise, outcome-oriented approach and revise it as you learn. Skip formal planning for simple tasks unless the user explicitly requests a plan.
|
||||
- **Implement:** Begin implementing while gathering context as needed. Use available search and editing tools strategically, adhering to project conventions (see 'Core Mandates'). Do not add features, refactor code, or make "improvements" beyond what was asked. Don't add error handling, fallbacks, or validation for scenarios that can't happen—only validate at system boundaries (user input, external APIs). Don't create helpers, utilities, or abstractions for one-time operations. Three similar lines of code is better than a premature abstraction. Prefer editing existing files over creating new ones.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If a todo list exists, keep it current as the scope or approach changes. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands. Before reporting a task complete, verify it actually works. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.
|
||||
- **Verify (Standards):** When your task involves a code or system change, 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 (or obtained from the user). This ensures code quality and adherence to standards. Read-only or explanatory turns do not require verification.
|
||||
- **Report outcomes faithfully:** If tests fail, say so with the relevant output. If you did not run a verification step, say that rather than implying it succeeded. Never claim "all tests pass" when output shows failures, never suppress failing checks to manufacture a green result, and never characterize incomplete or broken work as done.
|
||||
@@ -1079,7 +1020,6 @@ Final responses should be concise by default, but their shape and depth must mat
|
||||
- To search the content of files, use 'grep_search' instead of grep or rg
|
||||
- Reserve using the 'run_shell_command' exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool and only fallback on using the 'run_shell_command' tool for these if it is absolutely necessary.
|
||||
- **Tool Fallback:** If a tool returns empty, unhelpful, or unexpected results, try an alternative tool that can accomplish the same goal before telling the user it cannot be done. Never give up after a single tool failure.
|
||||
- **Task Management:** Use 'todo_write' only when explicit tracking adds value. Keep plans concise, outcome-oriented, and current; do not create a todo list for simple or single-step work unless the user explicitly requests one.
|
||||
- **Parallel Tool Calls:** You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead.
|
||||
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
|
||||
- **Background Processes:** Use background execution with \`is_background: true\` for commands that are unlikely to stop on their own, e.g. \`node server.js\`. Do not append a trailing \`&\` when using the shell tool's managed background mode. If unsure, follow the active interaction mode's question guidance.
|
||||
@@ -1215,22 +1155,13 @@ exports[`Core System Prompt (prompts.ts) > should return the base prompt when no
|
||||
- **Plan before uncertain work:** If the task is not yet clear enough to safely execute, do not make small speculative edits. Continue read-only investigation, make a plan in the current mode, or follow the active interaction mode's question guidance. Do not enter plan mode or call enter_plan_mode on your own just because the task involves planning or complexity. Use plan mode only when the user explicitly asks you to switch to plan mode, has already enabled it, or confirms they want it.
|
||||
|
||||
|
||||
# Task Management
|
||||
You have access to the todo_write tool to keep user-visible progress for work that benefits from explicit tracking. Use it for complex, ambiguous, or multi-phase tasks or requests with multiple independent outcomes. Do not use it for simple or single-step queries that you can answer or complete immediately unless the user explicitly asks for a plan.
|
||||
|
||||
When you create a todo list:
|
||||
- Keep it short and outcome-oriented. Use a few meaningful, logically ordered, verifiable steps rather than one item per error, file, command, or minor edit.
|
||||
- When an active Todo plan covers work delegated through top-level Agent calls, pass the matching Todo ID as \`todo_id\` so the execution can be associated with that plan node. Do not create a Todo solely to wrap a delegation that does not otherwise need task tracking.
|
||||
- Keep at most one item in_progress. Keep the list current, mark finished work completed, and revise it when the scope or approach changes. When work completes together, update multiple statuses in one tool call rather than making bookkeeping-only calls.
|
||||
- Do not repeat the full todo list in prose after calling the tool; briefly communicate only important context or the next step.
|
||||
|
||||
# Primary Workflows
|
||||
|
||||
## Software Engineering Tasks
|
||||
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this iterative approach:
|
||||
- **Plan:** Use 'todo_write' for complex, ambiguous, or multi-step work when visible progress tracking adds value. Keep the plan short and outcome-oriented; skip it for simple tasks unless the user explicitly requests a plan.
|
||||
- **Plan:** For complex, ambiguous, or multi-step work, form a concise, outcome-oriented approach and revise it as you learn. Skip formal planning for simple tasks unless the user explicitly requests a plan.
|
||||
- **Implement:** Begin implementing while gathering context as needed. Use available search and editing tools strategically, adhering to project conventions (see 'Core Mandates'). Do not add features, refactor code, or make "improvements" beyond what was asked. Don't add error handling, fallbacks, or validation for scenarios that can't happen—only validate at system boundaries (user input, external APIs). Don't create helpers, utilities, or abstractions for one-time operations. Three similar lines of code is better than a premature abstraction. Prefer editing existing files over creating new ones.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If a todo list exists, keep it current as the scope or approach changes. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands. Before reporting a task complete, verify it actually works. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.
|
||||
- **Verify (Standards):** When your task involves a code or system change, 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 (or obtained from the user). This ensures code quality and adherence to standards. Read-only or explanatory turns do not require verification.
|
||||
- **Report outcomes faithfully:** If tests fail, say so with the relevant output. If you did not run a verification step, say that rather than implying it succeeded. Never claim "all tests pass" when output shows failures, never suppress failing checks to manufacture a green result, and never characterize incomplete or broken work as done.
|
||||
@@ -1274,7 +1205,6 @@ Final responses should be concise by default, but their shape and depth must mat
|
||||
- To search the content of files, use 'grep_search' instead of grep or rg
|
||||
- Reserve using the 'run_shell_command' exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool and only fallback on using the 'run_shell_command' tool for these if it is absolutely necessary.
|
||||
- **Tool Fallback:** If a tool returns empty, unhelpful, or unexpected results, try an alternative tool that can accomplish the same goal before telling the user it cannot be done. Never give up after a single tool failure.
|
||||
- **Task Management:** Use 'todo_write' only when explicit tracking adds value. Keep plans concise, outcome-oriented, and current; do not create a todo list for simple or single-step work unless the user explicitly requests one.
|
||||
- **Parallel Tool Calls:** You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead.
|
||||
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
|
||||
- **Background Processes:** Use background execution with \`is_background: true\` for commands that are unlikely to stop on their own, e.g. \`node server.js\`. Do not append a trailing \`&\` when using the shell tool's managed background mode. If unsure, follow the active interaction mode's question guidance.
|
||||
@@ -1410,22 +1340,13 @@ exports[`Core System Prompt (prompts.ts) > should return the base prompt when us
|
||||
- **Plan before uncertain work:** If the task is not yet clear enough to safely execute, do not make small speculative edits. Continue read-only investigation, make a plan in the current mode, or follow the active interaction mode's question guidance. Do not enter plan mode or call enter_plan_mode on your own just because the task involves planning or complexity. Use plan mode only when the user explicitly asks you to switch to plan mode, has already enabled it, or confirms they want it.
|
||||
|
||||
|
||||
# Task Management
|
||||
You have access to the todo_write tool to keep user-visible progress for work that benefits from explicit tracking. Use it for complex, ambiguous, or multi-phase tasks or requests with multiple independent outcomes. Do not use it for simple or single-step queries that you can answer or complete immediately unless the user explicitly asks for a plan.
|
||||
|
||||
When you create a todo list:
|
||||
- Keep it short and outcome-oriented. Use a few meaningful, logically ordered, verifiable steps rather than one item per error, file, command, or minor edit.
|
||||
- When an active Todo plan covers work delegated through top-level Agent calls, pass the matching Todo ID as \`todo_id\` so the execution can be associated with that plan node. Do not create a Todo solely to wrap a delegation that does not otherwise need task tracking.
|
||||
- Keep at most one item in_progress. Keep the list current, mark finished work completed, and revise it when the scope or approach changes. When work completes together, update multiple statuses in one tool call rather than making bookkeeping-only calls.
|
||||
- Do not repeat the full todo list in prose after calling the tool; briefly communicate only important context or the next step.
|
||||
|
||||
# Primary Workflows
|
||||
|
||||
## Software Engineering Tasks
|
||||
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this iterative approach:
|
||||
- **Plan:** Use 'todo_write' for complex, ambiguous, or multi-step work when visible progress tracking adds value. Keep the plan short and outcome-oriented; skip it for simple tasks unless the user explicitly requests a plan.
|
||||
- **Plan:** For complex, ambiguous, or multi-step work, form a concise, outcome-oriented approach and revise it as you learn. Skip formal planning for simple tasks unless the user explicitly requests a plan.
|
||||
- **Implement:** Begin implementing while gathering context as needed. Use available search and editing tools strategically, adhering to project conventions (see 'Core Mandates'). Do not add features, refactor code, or make "improvements" beyond what was asked. Don't add error handling, fallbacks, or validation for scenarios that can't happen—only validate at system boundaries (user input, external APIs). Don't create helpers, utilities, or abstractions for one-time operations. Three similar lines of code is better than a premature abstraction. Prefer editing existing files over creating new ones.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If a todo list exists, keep it current as the scope or approach changes. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands. Before reporting a task complete, verify it actually works. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.
|
||||
- **Verify (Standards):** When your task involves a code or system change, 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 (or obtained from the user). This ensures code quality and adherence to standards. Read-only or explanatory turns do not require verification.
|
||||
- **Report outcomes faithfully:** If tests fail, say so with the relevant output. If you did not run a verification step, say that rather than implying it succeeded. Never claim "all tests pass" when output shows failures, never suppress failing checks to manufacture a green result, and never characterize incomplete or broken work as done.
|
||||
@@ -1469,7 +1390,6 @@ Final responses should be concise by default, but their shape and depth must mat
|
||||
- To search the content of files, use 'grep_search' instead of grep or rg
|
||||
- Reserve using the 'run_shell_command' exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool and only fallback on using the 'run_shell_command' tool for these if it is absolutely necessary.
|
||||
- **Tool Fallback:** If a tool returns empty, unhelpful, or unexpected results, try an alternative tool that can accomplish the same goal before telling the user it cannot be done. Never give up after a single tool failure.
|
||||
- **Task Management:** Use 'todo_write' only when explicit tracking adds value. Keep plans concise, outcome-oriented, and current; do not create a todo list for simple or single-step work unless the user explicitly requests one.
|
||||
- **Parallel Tool Calls:** You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead.
|
||||
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
|
||||
- **Background Processes:** Use background execution with \`is_background: true\` for commands that are unlikely to stop on their own, e.g. \`node server.js\`. Do not append a trailing \`&\` when using the shell tool's managed background mode. If unsure, follow the active interaction mode's question guidance.
|
||||
@@ -1605,22 +1525,13 @@ exports[`Core System Prompt (prompts.ts) > should return the base prompt when us
|
||||
- **Plan before uncertain work:** If the task is not yet clear enough to safely execute, do not make small speculative edits. Continue read-only investigation, make a plan in the current mode, or follow the active interaction mode's question guidance. Do not enter plan mode or call enter_plan_mode on your own just because the task involves planning or complexity. Use plan mode only when the user explicitly asks you to switch to plan mode, has already enabled it, or confirms they want it.
|
||||
|
||||
|
||||
# Task Management
|
||||
You have access to the todo_write tool to keep user-visible progress for work that benefits from explicit tracking. Use it for complex, ambiguous, or multi-phase tasks or requests with multiple independent outcomes. Do not use it for simple or single-step queries that you can answer or complete immediately unless the user explicitly asks for a plan.
|
||||
|
||||
When you create a todo list:
|
||||
- Keep it short and outcome-oriented. Use a few meaningful, logically ordered, verifiable steps rather than one item per error, file, command, or minor edit.
|
||||
- When an active Todo plan covers work delegated through top-level Agent calls, pass the matching Todo ID as \`todo_id\` so the execution can be associated with that plan node. Do not create a Todo solely to wrap a delegation that does not otherwise need task tracking.
|
||||
- Keep at most one item in_progress. Keep the list current, mark finished work completed, and revise it when the scope or approach changes. When work completes together, update multiple statuses in one tool call rather than making bookkeeping-only calls.
|
||||
- Do not repeat the full todo list in prose after calling the tool; briefly communicate only important context or the next step.
|
||||
|
||||
# Primary Workflows
|
||||
|
||||
## Software Engineering Tasks
|
||||
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this iterative approach:
|
||||
- **Plan:** Use 'todo_write' for complex, ambiguous, or multi-step work when visible progress tracking adds value. Keep the plan short and outcome-oriented; skip it for simple tasks unless the user explicitly requests a plan.
|
||||
- **Plan:** For complex, ambiguous, or multi-step work, form a concise, outcome-oriented approach and revise it as you learn. Skip formal planning for simple tasks unless the user explicitly requests a plan.
|
||||
- **Implement:** Begin implementing while gathering context as needed. Use available search and editing tools strategically, adhering to project conventions (see 'Core Mandates'). Do not add features, refactor code, or make "improvements" beyond what was asked. Don't add error handling, fallbacks, or validation for scenarios that can't happen—only validate at system boundaries (user input, external APIs). Don't create helpers, utilities, or abstractions for one-time operations. Three similar lines of code is better than a premature abstraction. Prefer editing existing files over creating new ones.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If a todo list exists, keep it current as the scope or approach changes. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands. Before reporting a task complete, verify it actually works. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.
|
||||
- **Verify (Standards):** When your task involves a code or system change, 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 (or obtained from the user). This ensures code quality and adherence to standards. Read-only or explanatory turns do not require verification.
|
||||
- **Report outcomes faithfully:** If tests fail, say so with the relevant output. If you did not run a verification step, say that rather than implying it succeeded. Never claim "all tests pass" when output shows failures, never suppress failing checks to manufacture a green result, and never characterize incomplete or broken work as done.
|
||||
@@ -1664,7 +1575,6 @@ Final responses should be concise by default, but their shape and depth must mat
|
||||
- To search the content of files, use 'grep_search' instead of grep or rg
|
||||
- Reserve using the 'run_shell_command' exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool and only fallback on using the 'run_shell_command' tool for these if it is absolutely necessary.
|
||||
- **Tool Fallback:** If a tool returns empty, unhelpful, or unexpected results, try an alternative tool that can accomplish the same goal before telling the user it cannot be done. Never give up after a single tool failure.
|
||||
- **Task Management:** Use 'todo_write' only when explicit tracking adds value. Keep plans concise, outcome-oriented, and current; do not create a todo list for simple or single-step work unless the user explicitly requests one.
|
||||
- **Parallel Tool Calls:** You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead.
|
||||
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
|
||||
- **Background Processes:** Use background execution with \`is_background: true\` for commands that are unlikely to stop on their own, e.g. \`node server.js\`. Do not append a trailing \`&\` when using the shell tool's managed background mode. If unsure, follow the active interaction mode's question guidance.
|
||||
@@ -1800,22 +1710,13 @@ exports[`Model-specific tool call formats > should preserve model-specific forma
|
||||
- **Plan before uncertain work:** If the task is not yet clear enough to safely execute, do not make small speculative edits. Continue read-only investigation, make a plan in the current mode, or follow the active interaction mode's question guidance. Do not enter plan mode or call enter_plan_mode on your own just because the task involves planning or complexity. Use plan mode only when the user explicitly asks you to switch to plan mode, has already enabled it, or confirms they want it.
|
||||
|
||||
|
||||
# Task Management
|
||||
You have access to the todo_write tool to keep user-visible progress for work that benefits from explicit tracking. Use it for complex, ambiguous, or multi-phase tasks or requests with multiple independent outcomes. Do not use it for simple or single-step queries that you can answer or complete immediately unless the user explicitly asks for a plan.
|
||||
|
||||
When you create a todo list:
|
||||
- Keep it short and outcome-oriented. Use a few meaningful, logically ordered, verifiable steps rather than one item per error, file, command, or minor edit.
|
||||
- When an active Todo plan covers work delegated through top-level Agent calls, pass the matching Todo ID as \`todo_id\` so the execution can be associated with that plan node. Do not create a Todo solely to wrap a delegation that does not otherwise need task tracking.
|
||||
- Keep at most one item in_progress. Keep the list current, mark finished work completed, and revise it when the scope or approach changes. When work completes together, update multiple statuses in one tool call rather than making bookkeeping-only calls.
|
||||
- Do not repeat the full todo list in prose after calling the tool; briefly communicate only important context or the next step.
|
||||
|
||||
# Primary Workflows
|
||||
|
||||
## Software Engineering Tasks
|
||||
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this iterative approach:
|
||||
- **Plan:** Use 'todo_write' for complex, ambiguous, or multi-step work when visible progress tracking adds value. Keep the plan short and outcome-oriented; skip it for simple tasks unless the user explicitly requests a plan.
|
||||
- **Plan:** For complex, ambiguous, or multi-step work, form a concise, outcome-oriented approach and revise it as you learn. Skip formal planning for simple tasks unless the user explicitly requests a plan.
|
||||
- **Implement:** Begin implementing while gathering context as needed. Use available search and editing tools strategically, adhering to project conventions (see 'Core Mandates'). Do not add features, refactor code, or make "improvements" beyond what was asked. Don't add error handling, fallbacks, or validation for scenarios that can't happen—only validate at system boundaries (user input, external APIs). Don't create helpers, utilities, or abstractions for one-time operations. Three similar lines of code is better than a premature abstraction. Prefer editing existing files over creating new ones.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If a todo list exists, keep it current as the scope or approach changes. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands. Before reporting a task complete, verify it actually works. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.
|
||||
- **Verify (Standards):** When your task involves a code or system change, 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 (or obtained from the user). This ensures code quality and adherence to standards. Read-only or explanatory turns do not require verification.
|
||||
- **Report outcomes faithfully:** If tests fail, say so with the relevant output. If you did not run a verification step, say that rather than implying it succeeded. Never claim "all tests pass" when output shows failures, never suppress failing checks to manufacture a green result, and never characterize incomplete or broken work as done.
|
||||
@@ -1859,7 +1760,6 @@ Final responses should be concise by default, but their shape and depth must mat
|
||||
- To search the content of files, use 'grep_search' instead of grep or rg
|
||||
- Reserve using the 'run_shell_command' exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool and only fallback on using the 'run_shell_command' tool for these if it is absolutely necessary.
|
||||
- **Tool Fallback:** If a tool returns empty, unhelpful, or unexpected results, try an alternative tool that can accomplish the same goal before telling the user it cannot be done. Never give up after a single tool failure.
|
||||
- **Task Management:** Use 'todo_write' only when explicit tracking adds value. Keep plans concise, outcome-oriented, and current; do not create a todo list for simple or single-step work unless the user explicitly requests one.
|
||||
- **Parallel Tool Calls:** You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead.
|
||||
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
|
||||
- **Background Processes:** Use background execution with \`is_background: true\` for commands that are unlikely to stop on their own, e.g. \`node server.js\`. Do not append a trailing \`&\` when using the shell tool's managed background mode. If unsure, follow the active interaction mode's question guidance.
|
||||
@@ -2020,22 +1920,13 @@ exports[`Model-specific tool call formats > should preserve model-specific forma
|
||||
- **Plan before uncertain work:** If the task is not yet clear enough to safely execute, do not make small speculative edits. Continue read-only investigation, make a plan in the current mode, or follow the active interaction mode's question guidance. Do not enter plan mode or call enter_plan_mode on your own just because the task involves planning or complexity. Use plan mode only when the user explicitly asks you to switch to plan mode, has already enabled it, or confirms they want it.
|
||||
|
||||
|
||||
# Task Management
|
||||
You have access to the todo_write tool to keep user-visible progress for work that benefits from explicit tracking. Use it for complex, ambiguous, or multi-phase tasks or requests with multiple independent outcomes. Do not use it for simple or single-step queries that you can answer or complete immediately unless the user explicitly asks for a plan.
|
||||
|
||||
When you create a todo list:
|
||||
- Keep it short and outcome-oriented. Use a few meaningful, logically ordered, verifiable steps rather than one item per error, file, command, or minor edit.
|
||||
- When an active Todo plan covers work delegated through top-level Agent calls, pass the matching Todo ID as \`todo_id\` so the execution can be associated with that plan node. Do not create a Todo solely to wrap a delegation that does not otherwise need task tracking.
|
||||
- Keep at most one item in_progress. Keep the list current, mark finished work completed, and revise it when the scope or approach changes. When work completes together, update multiple statuses in one tool call rather than making bookkeeping-only calls.
|
||||
- Do not repeat the full todo list in prose after calling the tool; briefly communicate only important context or the next step.
|
||||
|
||||
# Primary Workflows
|
||||
|
||||
## Software Engineering Tasks
|
||||
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this iterative approach:
|
||||
- **Plan:** Use 'todo_write' for complex, ambiguous, or multi-step work when visible progress tracking adds value. Keep the plan short and outcome-oriented; skip it for simple tasks unless the user explicitly requests a plan.
|
||||
- **Plan:** For complex, ambiguous, or multi-step work, form a concise, outcome-oriented approach and revise it as you learn. Skip formal planning for simple tasks unless the user explicitly requests a plan.
|
||||
- **Implement:** Begin implementing while gathering context as needed. Use available search and editing tools strategically, adhering to project conventions (see 'Core Mandates'). Do not add features, refactor code, or make "improvements" beyond what was asked. Don't add error handling, fallbacks, or validation for scenarios that can't happen—only validate at system boundaries (user input, external APIs). Don't create helpers, utilities, or abstractions for one-time operations. Three similar lines of code is better than a premature abstraction. Prefer editing existing files over creating new ones.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If a todo list exists, keep it current as the scope or approach changes. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands. Before reporting a task complete, verify it actually works. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.
|
||||
- **Verify (Standards):** When your task involves a code or system change, 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 (or obtained from the user). This ensures code quality and adherence to standards. Read-only or explanatory turns do not require verification.
|
||||
- **Report outcomes faithfully:** If tests fail, say so with the relevant output. If you did not run a verification step, say that rather than implying it succeeded. Never claim "all tests pass" when output shows failures, never suppress failing checks to manufacture a green result, and never characterize incomplete or broken work as done.
|
||||
@@ -2079,7 +1970,6 @@ Final responses should be concise by default, but their shape and depth must mat
|
||||
- To search the content of files, use 'grep_search' instead of grep or rg
|
||||
- Reserve using the 'run_shell_command' exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool and only fallback on using the 'run_shell_command' tool for these if it is absolutely necessary.
|
||||
- **Tool Fallback:** If a tool returns empty, unhelpful, or unexpected results, try an alternative tool that can accomplish the same goal before telling the user it cannot be done. Never give up after a single tool failure.
|
||||
- **Task Management:** Use 'todo_write' only when explicit tracking adds value. Keep plans concise, outcome-oriented, and current; do not create a todo list for simple or single-step work unless the user explicitly requests one.
|
||||
- **Parallel Tool Calls:** You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead.
|
||||
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
|
||||
- **Background Processes:** Use background execution with \`is_background: true\` for commands that are unlikely to stop on their own, e.g. \`node server.js\`. Do not append a trailing \`&\` when using the shell tool's managed background mode. If unsure, follow the active interaction mode's question guidance.
|
||||
@@ -2310,22 +2200,13 @@ exports[`Model-specific tool call formats > should use JSON format for qwen-vl m
|
||||
- **Plan before uncertain work:** If the task is not yet clear enough to safely execute, do not make small speculative edits. Continue read-only investigation, make a plan in the current mode, or follow the active interaction mode's question guidance. Do not enter plan mode or call enter_plan_mode on your own just because the task involves planning or complexity. Use plan mode only when the user explicitly asks you to switch to plan mode, has already enabled it, or confirms they want it.
|
||||
|
||||
|
||||
# Task Management
|
||||
You have access to the todo_write tool to keep user-visible progress for work that benefits from explicit tracking. Use it for complex, ambiguous, or multi-phase tasks or requests with multiple independent outcomes. Do not use it for simple or single-step queries that you can answer or complete immediately unless the user explicitly asks for a plan.
|
||||
|
||||
When you create a todo list:
|
||||
- Keep it short and outcome-oriented. Use a few meaningful, logically ordered, verifiable steps rather than one item per error, file, command, or minor edit.
|
||||
- When an active Todo plan covers work delegated through top-level Agent calls, pass the matching Todo ID as \`todo_id\` so the execution can be associated with that plan node. Do not create a Todo solely to wrap a delegation that does not otherwise need task tracking.
|
||||
- Keep at most one item in_progress. Keep the list current, mark finished work completed, and revise it when the scope or approach changes. When work completes together, update multiple statuses in one tool call rather than making bookkeeping-only calls.
|
||||
- Do not repeat the full todo list in prose after calling the tool; briefly communicate only important context or the next step.
|
||||
|
||||
# Primary Workflows
|
||||
|
||||
## Software Engineering Tasks
|
||||
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this iterative approach:
|
||||
- **Plan:** Use 'todo_write' for complex, ambiguous, or multi-step work when visible progress tracking adds value. Keep the plan short and outcome-oriented; skip it for simple tasks unless the user explicitly requests a plan.
|
||||
- **Plan:** For complex, ambiguous, or multi-step work, form a concise, outcome-oriented approach and revise it as you learn. Skip formal planning for simple tasks unless the user explicitly requests a plan.
|
||||
- **Implement:** Begin implementing while gathering context as needed. Use available search and editing tools strategically, adhering to project conventions (see 'Core Mandates'). Do not add features, refactor code, or make "improvements" beyond what was asked. Don't add error handling, fallbacks, or validation for scenarios that can't happen—only validate at system boundaries (user input, external APIs). Don't create helpers, utilities, or abstractions for one-time operations. Three similar lines of code is better than a premature abstraction. Prefer editing existing files over creating new ones.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If a todo list exists, keep it current as the scope or approach changes. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands. Before reporting a task complete, verify it actually works. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.
|
||||
- **Verify (Standards):** When your task involves a code or system change, 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 (or obtained from the user). This ensures code quality and adherence to standards. Read-only or explanatory turns do not require verification.
|
||||
- **Report outcomes faithfully:** If tests fail, say so with the relevant output. If you did not run a verification step, say that rather than implying it succeeded. Never claim "all tests pass" when output shows failures, never suppress failing checks to manufacture a green result, and never characterize incomplete or broken work as done.
|
||||
@@ -2369,7 +2250,6 @@ Final responses should be concise by default, but their shape and depth must mat
|
||||
- To search the content of files, use 'grep_search' instead of grep or rg
|
||||
- Reserve using the 'run_shell_command' exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool and only fallback on using the 'run_shell_command' tool for these if it is absolutely necessary.
|
||||
- **Tool Fallback:** If a tool returns empty, unhelpful, or unexpected results, try an alternative tool that can accomplish the same goal before telling the user it cannot be done. Never give up after a single tool failure.
|
||||
- **Task Management:** Use 'todo_write' only when explicit tracking adds value. Keep plans concise, outcome-oriented, and current; do not create a todo list for simple or single-step work unless the user explicitly requests one.
|
||||
- **Parallel Tool Calls:** You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead.
|
||||
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
|
||||
- **Background Processes:** Use background execution with \`is_background: true\` for commands that are unlikely to stop on their own, e.g. \`node server.js\`. Do not append a trailing \`&\` when using the shell tool's managed background mode. If unsure, follow the active interaction mode's question guidance.
|
||||
@@ -2530,22 +2410,13 @@ exports[`Model-specific tool call formats > should use XML format for qwen3-code
|
||||
- **Plan before uncertain work:** If the task is not yet clear enough to safely execute, do not make small speculative edits. Continue read-only investigation, make a plan in the current mode, or follow the active interaction mode's question guidance. Do not enter plan mode or call enter_plan_mode on your own just because the task involves planning or complexity. Use plan mode only when the user explicitly asks you to switch to plan mode, has already enabled it, or confirms they want it.
|
||||
|
||||
|
||||
# Task Management
|
||||
You have access to the todo_write tool to keep user-visible progress for work that benefits from explicit tracking. Use it for complex, ambiguous, or multi-phase tasks or requests with multiple independent outcomes. Do not use it for simple or single-step queries that you can answer or complete immediately unless the user explicitly asks for a plan.
|
||||
|
||||
When you create a todo list:
|
||||
- Keep it short and outcome-oriented. Use a few meaningful, logically ordered, verifiable steps rather than one item per error, file, command, or minor edit.
|
||||
- When an active Todo plan covers work delegated through top-level Agent calls, pass the matching Todo ID as \`todo_id\` so the execution can be associated with that plan node. Do not create a Todo solely to wrap a delegation that does not otherwise need task tracking.
|
||||
- Keep at most one item in_progress. Keep the list current, mark finished work completed, and revise it when the scope or approach changes. When work completes together, update multiple statuses in one tool call rather than making bookkeeping-only calls.
|
||||
- Do not repeat the full todo list in prose after calling the tool; briefly communicate only important context or the next step.
|
||||
|
||||
# Primary Workflows
|
||||
|
||||
## Software Engineering Tasks
|
||||
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this iterative approach:
|
||||
- **Plan:** Use 'todo_write' for complex, ambiguous, or multi-step work when visible progress tracking adds value. Keep the plan short and outcome-oriented; skip it for simple tasks unless the user explicitly requests a plan.
|
||||
- **Plan:** For complex, ambiguous, or multi-step work, form a concise, outcome-oriented approach and revise it as you learn. Skip formal planning for simple tasks unless the user explicitly requests a plan.
|
||||
- **Implement:** Begin implementing while gathering context as needed. Use available search and editing tools strategically, adhering to project conventions (see 'Core Mandates'). Do not add features, refactor code, or make "improvements" beyond what was asked. Don't add error handling, fallbacks, or validation for scenarios that can't happen—only validate at system boundaries (user input, external APIs). Don't create helpers, utilities, or abstractions for one-time operations. Three similar lines of code is better than a premature abstraction. Prefer editing existing files over creating new ones.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If a todo list exists, keep it current as the scope or approach changes. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands. Before reporting a task complete, verify it actually works. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.
|
||||
- **Verify (Standards):** When your task involves a code or system change, 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 (or obtained from the user). This ensures code quality and adherence to standards. Read-only or explanatory turns do not require verification.
|
||||
- **Report outcomes faithfully:** If tests fail, say so with the relevant output. If you did not run a verification step, say that rather than implying it succeeded. Never claim "all tests pass" when output shows failures, never suppress failing checks to manufacture a green result, and never characterize incomplete or broken work as done.
|
||||
@@ -2589,7 +2460,6 @@ Final responses should be concise by default, but their shape and depth must mat
|
||||
- To search the content of files, use 'grep_search' instead of grep or rg
|
||||
- Reserve using the 'run_shell_command' exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool and only fallback on using the 'run_shell_command' tool for these if it is absolutely necessary.
|
||||
- **Tool Fallback:** If a tool returns empty, unhelpful, or unexpected results, try an alternative tool that can accomplish the same goal before telling the user it cannot be done. Never give up after a single tool failure.
|
||||
- **Task Management:** Use 'todo_write' only when explicit tracking adds value. Keep plans concise, outcome-oriented, and current; do not create a todo list for simple or single-step work unless the user explicitly requests one.
|
||||
- **Parallel Tool Calls:** You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead.
|
||||
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
|
||||
- **Background Processes:** Use background execution with \`is_background: true\` for commands that are unlikely to stop on their own, e.g. \`node server.js\`. Do not append a trailing \`&\` when using the shell tool's managed background mode. If unsure, follow the active interaction mode's question guidance.
|
||||
@@ -2816,22 +2686,13 @@ exports[`Model-specific tool call formats > should use bracket format for generi
|
||||
- **Plan before uncertain work:** If the task is not yet clear enough to safely execute, do not make small speculative edits. Continue read-only investigation, make a plan in the current mode, or follow the active interaction mode's question guidance. Do not enter plan mode or call enter_plan_mode on your own just because the task involves planning or complexity. Use plan mode only when the user explicitly asks you to switch to plan mode, has already enabled it, or confirms they want it.
|
||||
|
||||
|
||||
# Task Management
|
||||
You have access to the todo_write tool to keep user-visible progress for work that benefits from explicit tracking. Use it for complex, ambiguous, or multi-phase tasks or requests with multiple independent outcomes. Do not use it for simple or single-step queries that you can answer or complete immediately unless the user explicitly asks for a plan.
|
||||
|
||||
When you create a todo list:
|
||||
- Keep it short and outcome-oriented. Use a few meaningful, logically ordered, verifiable steps rather than one item per error, file, command, or minor edit.
|
||||
- When an active Todo plan covers work delegated through top-level Agent calls, pass the matching Todo ID as \`todo_id\` so the execution can be associated with that plan node. Do not create a Todo solely to wrap a delegation that does not otherwise need task tracking.
|
||||
- Keep at most one item in_progress. Keep the list current, mark finished work completed, and revise it when the scope or approach changes. When work completes together, update multiple statuses in one tool call rather than making bookkeeping-only calls.
|
||||
- Do not repeat the full todo list in prose after calling the tool; briefly communicate only important context or the next step.
|
||||
|
||||
# Primary Workflows
|
||||
|
||||
## Software Engineering Tasks
|
||||
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this iterative approach:
|
||||
- **Plan:** Use 'todo_write' for complex, ambiguous, or multi-step work when visible progress tracking adds value. Keep the plan short and outcome-oriented; skip it for simple tasks unless the user explicitly requests a plan.
|
||||
- **Plan:** For complex, ambiguous, or multi-step work, form a concise, outcome-oriented approach and revise it as you learn. Skip formal planning for simple tasks unless the user explicitly requests a plan.
|
||||
- **Implement:** Begin implementing while gathering context as needed. Use available search and editing tools strategically, adhering to project conventions (see 'Core Mandates'). Do not add features, refactor code, or make "improvements" beyond what was asked. Don't add error handling, fallbacks, or validation for scenarios that can't happen—only validate at system boundaries (user input, external APIs). Don't create helpers, utilities, or abstractions for one-time operations. Three similar lines of code is better than a premature abstraction. Prefer editing existing files over creating new ones.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If a todo list exists, keep it current as the scope or approach changes. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands. Before reporting a task complete, verify it actually works. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.
|
||||
- **Verify (Standards):** When your task involves a code or system change, 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 (or obtained from the user). This ensures code quality and adherence to standards. Read-only or explanatory turns do not require verification.
|
||||
- **Report outcomes faithfully:** If tests fail, say so with the relevant output. If you did not run a verification step, say that rather than implying it succeeded. Never claim "all tests pass" when output shows failures, never suppress failing checks to manufacture a green result, and never characterize incomplete or broken work as done.
|
||||
@@ -2875,7 +2736,6 @@ Final responses should be concise by default, but their shape and depth must mat
|
||||
- To search the content of files, use 'grep_search' instead of grep or rg
|
||||
- Reserve using the 'run_shell_command' exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool and only fallback on using the 'run_shell_command' tool for these if it is absolutely necessary.
|
||||
- **Tool Fallback:** If a tool returns empty, unhelpful, or unexpected results, try an alternative tool that can accomplish the same goal before telling the user it cannot be done. Never give up after a single tool failure.
|
||||
- **Task Management:** Use 'todo_write' only when explicit tracking adds value. Keep plans concise, outcome-oriented, and current; do not create a todo list for simple or single-step work unless the user explicitly requests one.
|
||||
- **Parallel Tool Calls:** You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead.
|
||||
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
|
||||
- **Background Processes:** Use background execution with \`is_background: true\` for commands that are unlikely to stop on their own, e.g. \`node server.js\`. Do not append a trailing \`&\` when using the shell tool's managed background mode. If unsure, follow the active interaction mode's question guidance.
|
||||
@@ -3011,22 +2871,13 @@ exports[`Model-specific tool call formats > should use bracket format when no mo
|
||||
- **Plan before uncertain work:** If the task is not yet clear enough to safely execute, do not make small speculative edits. Continue read-only investigation, make a plan in the current mode, or follow the active interaction mode's question guidance. Do not enter plan mode or call enter_plan_mode on your own just because the task involves planning or complexity. Use plan mode only when the user explicitly asks you to switch to plan mode, has already enabled it, or confirms they want it.
|
||||
|
||||
|
||||
# Task Management
|
||||
You have access to the todo_write tool to keep user-visible progress for work that benefits from explicit tracking. Use it for complex, ambiguous, or multi-phase tasks or requests with multiple independent outcomes. Do not use it for simple or single-step queries that you can answer or complete immediately unless the user explicitly asks for a plan.
|
||||
|
||||
When you create a todo list:
|
||||
- Keep it short and outcome-oriented. Use a few meaningful, logically ordered, verifiable steps rather than one item per error, file, command, or minor edit.
|
||||
- When an active Todo plan covers work delegated through top-level Agent calls, pass the matching Todo ID as \`todo_id\` so the execution can be associated with that plan node. Do not create a Todo solely to wrap a delegation that does not otherwise need task tracking.
|
||||
- Keep at most one item in_progress. Keep the list current, mark finished work completed, and revise it when the scope or approach changes. When work completes together, update multiple statuses in one tool call rather than making bookkeeping-only calls.
|
||||
- Do not repeat the full todo list in prose after calling the tool; briefly communicate only important context or the next step.
|
||||
|
||||
# Primary Workflows
|
||||
|
||||
## Software Engineering Tasks
|
||||
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this iterative approach:
|
||||
- **Plan:** Use 'todo_write' for complex, ambiguous, or multi-step work when visible progress tracking adds value. Keep the plan short and outcome-oriented; skip it for simple tasks unless the user explicitly requests a plan.
|
||||
- **Plan:** For complex, ambiguous, or multi-step work, form a concise, outcome-oriented approach and revise it as you learn. Skip formal planning for simple tasks unless the user explicitly requests a plan.
|
||||
- **Implement:** Begin implementing while gathering context as needed. Use available search and editing tools strategically, adhering to project conventions (see 'Core Mandates'). Do not add features, refactor code, or make "improvements" beyond what was asked. Don't add error handling, fallbacks, or validation for scenarios that can't happen—only validate at system boundaries (user input, external APIs). Don't create helpers, utilities, or abstractions for one-time operations. Three similar lines of code is better than a premature abstraction. Prefer editing existing files over creating new ones.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If a todo list exists, keep it current as the scope or approach changes. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands. Before reporting a task complete, verify it actually works. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.
|
||||
- **Verify (Standards):** When your task involves a code or system change, 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 (or obtained from the user). This ensures code quality and adherence to standards. Read-only or explanatory turns do not require verification.
|
||||
- **Report outcomes faithfully:** If tests fail, say so with the relevant output. If you did not run a verification step, say that rather than implying it succeeded. Never claim "all tests pass" when output shows failures, never suppress failing checks to manufacture a green result, and never characterize incomplete or broken work as done.
|
||||
@@ -3070,7 +2921,6 @@ Final responses should be concise by default, but their shape and depth must mat
|
||||
- To search the content of files, use 'grep_search' instead of grep or rg
|
||||
- Reserve using the 'run_shell_command' exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool and only fallback on using the 'run_shell_command' tool for these if it is absolutely necessary.
|
||||
- **Tool Fallback:** If a tool returns empty, unhelpful, or unexpected results, try an alternative tool that can accomplish the same goal before telling the user it cannot be done. Never give up after a single tool failure.
|
||||
- **Task Management:** Use 'todo_write' only when explicit tracking adds value. Keep plans concise, outcome-oriented, and current; do not create a todo list for simple or single-step work unless the user explicitly requests one.
|
||||
- **Parallel Tool Calls:** You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead.
|
||||
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
|
||||
- **Background Processes:** Use background execution with \`is_background: true\` for commands that are unlikely to stop on their own, e.g. \`node server.js\`. Do not append a trailing \`&\` when using the shell tool's managed background mode. If unsure, follow the active interaction mode's question guidance.
|
||||
@@ -3206,22 +3056,13 @@ exports[`Model-specific tool call formats > should use native Gemma 4 format for
|
||||
- **Plan before uncertain work:** If the task is not yet clear enough to safely execute, do not make small speculative edits. Continue read-only investigation, make a plan in the current mode, or follow the active interaction mode's question guidance. Do not enter plan mode or call enter_plan_mode on your own just because the task involves planning or complexity. Use plan mode only when the user explicitly asks you to switch to plan mode, has already enabled it, or confirms they want it.
|
||||
|
||||
|
||||
# Task Management
|
||||
You have access to the todo_write tool to keep user-visible progress for work that benefits from explicit tracking. Use it for complex, ambiguous, or multi-phase tasks or requests with multiple independent outcomes. Do not use it for simple or single-step queries that you can answer or complete immediately unless the user explicitly asks for a plan.
|
||||
|
||||
When you create a todo list:
|
||||
- Keep it short and outcome-oriented. Use a few meaningful, logically ordered, verifiable steps rather than one item per error, file, command, or minor edit.
|
||||
- When an active Todo plan covers work delegated through top-level Agent calls, pass the matching Todo ID as \`todo_id\` so the execution can be associated with that plan node. Do not create a Todo solely to wrap a delegation that does not otherwise need task tracking.
|
||||
- Keep at most one item in_progress. Keep the list current, mark finished work completed, and revise it when the scope or approach changes. When work completes together, update multiple statuses in one tool call rather than making bookkeeping-only calls.
|
||||
- Do not repeat the full todo list in prose after calling the tool; briefly communicate only important context or the next step.
|
||||
|
||||
# Primary Workflows
|
||||
|
||||
## Software Engineering Tasks
|
||||
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this iterative approach:
|
||||
- **Plan:** Use 'todo_write' for complex, ambiguous, or multi-step work when visible progress tracking adds value. Keep the plan short and outcome-oriented; skip it for simple tasks unless the user explicitly requests a plan.
|
||||
- **Plan:** For complex, ambiguous, or multi-step work, form a concise, outcome-oriented approach and revise it as you learn. Skip formal planning for simple tasks unless the user explicitly requests a plan.
|
||||
- **Implement:** Begin implementing while gathering context as needed. Use available search and editing tools strategically, adhering to project conventions (see 'Core Mandates'). Do not add features, refactor code, or make "improvements" beyond what was asked. Don't add error handling, fallbacks, or validation for scenarios that can't happen—only validate at system boundaries (user input, external APIs). Don't create helpers, utilities, or abstractions for one-time operations. Three similar lines of code is better than a premature abstraction. Prefer editing existing files over creating new ones.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If a todo list exists, keep it current as the scope or approach changes. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands. Before reporting a task complete, verify it actually works. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.
|
||||
- **Verify (Standards):** When your task involves a code or system change, 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 (or obtained from the user). This ensures code quality and adherence to standards. Read-only or explanatory turns do not require verification.
|
||||
- **Report outcomes faithfully:** If tests fail, say so with the relevant output. If you did not run a verification step, say that rather than implying it succeeded. Never claim "all tests pass" when output shows failures, never suppress failing checks to manufacture a green result, and never characterize incomplete or broken work as done.
|
||||
@@ -3265,7 +3106,6 @@ Final responses should be concise by default, but their shape and depth must mat
|
||||
- To search the content of files, use 'grep_search' instead of grep or rg
|
||||
- Reserve using the 'run_shell_command' exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool and only fallback on using the 'run_shell_command' tool for these if it is absolutely necessary.
|
||||
- **Tool Fallback:** If a tool returns empty, unhelpful, or unexpected results, try an alternative tool that can accomplish the same goal before telling the user it cannot be done. Never give up after a single tool failure.
|
||||
- **Task Management:** Use 'todo_write' only when explicit tracking adds value. Keep plans concise, outcome-oriented, and current; do not create a todo list for simple or single-step work unless the user explicitly requests one.
|
||||
- **Parallel Tool Calls:** You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead.
|
||||
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
|
||||
- **Background Processes:** Use background execution with \`is_background: true\` for commands that are unlikely to stop on their own, e.g. \`node server.js\`. Do not append a trailing \`&\` when using the shell tool's managed background mode. If unsure, follow the active interaction mode's question guidance.
|
||||
|
||||
@@ -590,6 +590,7 @@ describe('Gemini Client (client.ts)', () => {
|
||||
getSystemPrompt: vi.fn().mockReturnValue(undefined),
|
||||
getAppendSystemPrompt: vi.fn().mockReturnValue(undefined),
|
||||
getOutputStyle: vi.fn().mockReturnValue(undefined),
|
||||
isTodoWriteEnabled: vi.fn().mockReturnValue(false),
|
||||
getStaticSystemPrefix: vi.fn().mockReturnValue(undefined),
|
||||
setStaticSystemPrefix: vi.fn(),
|
||||
getFullContext: vi.fn().mockReturnValue(false),
|
||||
@@ -14522,6 +14523,7 @@ Other open files:
|
||||
undefined,
|
||||
'headless',
|
||||
undefined,
|
||||
false,
|
||||
);
|
||||
expect(mockContentGenerator.generateContent).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
@@ -14554,6 +14556,7 @@ Other open files:
|
||||
undefined,
|
||||
'headless',
|
||||
concise,
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -14586,6 +14589,7 @@ Other open files:
|
||||
undefined,
|
||||
mode,
|
||||
undefined,
|
||||
false,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -365,6 +365,7 @@ type MainSessionPromptConfig = Pick<
|
||||
| 'getExperimentalZedIntegration'
|
||||
| 'getInputFormat'
|
||||
| 'isInteractive'
|
||||
| 'isTodoWriteEnabled'
|
||||
> &
|
||||
// A project style stops applying the moment the workspace loses trust, so
|
||||
// the resolver reads the live verdict on this path too. Optional, because
|
||||
@@ -388,6 +389,7 @@ export function getMainSessionBaseSystemPrompt(
|
||||
// `getOutputStyle()` directly — a prompt override carries no style
|
||||
// section, and a session must not be reminded of one it lacks.
|
||||
resolveMainSessionOutputStyle(config),
|
||||
config.isTodoWriteEnabled(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ import {
|
||||
convertToFunctionErrorResponse,
|
||||
convertToFunctionResponse,
|
||||
extractToolFilePaths,
|
||||
getOptInToolNotFoundMessage,
|
||||
isToolCallConcurrencySafe,
|
||||
} from './coreToolScheduler.js';
|
||||
import type { CallableTool, Part, PartListUnion } from '@google/genai';
|
||||
@@ -7171,6 +7172,23 @@ describe('CoreToolScheduler', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it.each(['toString', 'constructor', 'hasOwnProperty', 'valueOf'])(
|
||||
'keeps Object.prototype name %s on the generic not-found path',
|
||||
async (name) => {
|
||||
const message = await getOptInToolNotFoundMessage(
|
||||
{
|
||||
getDisabledTools: () => new Set<string>(),
|
||||
getPermissionManager: () => null,
|
||||
isTodoWriteEnabled: () => false,
|
||||
} as unknown as Config,
|
||||
name,
|
||||
() => false,
|
||||
);
|
||||
|
||||
expect(message).toBeUndefined();
|
||||
},
|
||||
);
|
||||
|
||||
it('should attribute a missing list_directory to the workspace tools toggle when it is disabled there', async () => {
|
||||
const mockToolRegistry = {
|
||||
getAllToolNames: () => ['glob', 'read_file'],
|
||||
@@ -7213,6 +7231,169 @@ describe('CoreToolScheduler', () => {
|
||||
expect(aliasMessage).not.toContain('disabled by default');
|
||||
});
|
||||
|
||||
it('should explain how to enable todo_write when it is not registered', async () => {
|
||||
const mockToolRegistry = {
|
||||
getAllToolNames: () => ['glob', 'read_file'],
|
||||
getTool: () => undefined,
|
||||
ensureTool: async () => undefined,
|
||||
} as unknown as ToolRegistry;
|
||||
|
||||
const mockConfig = {
|
||||
getToolRegistry: () => mockToolRegistry,
|
||||
getUseModelRouter: () => false,
|
||||
getLlmClient: () => null,
|
||||
getPermissionsDeny: () => undefined,
|
||||
isInteractive: () => true,
|
||||
getMessageBus: vi.fn().mockReturnValue(undefined),
|
||||
getDisableAllHooks: vi.fn().mockReturnValue(true),
|
||||
getDisabledTools: vi.fn().mockReturnValue(new Set<string>()),
|
||||
getPermissionManager: vi.fn().mockReturnValue(null),
|
||||
isTodoWriteEnabled: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
|
||||
const scheduler = new CoreToolScheduler({
|
||||
config: mockConfig,
|
||||
getPreferredEditor: () => 'vscode',
|
||||
onEditorClose: vi.fn(),
|
||||
});
|
||||
|
||||
for (const name of ['todo_write', 'TodoWrite']) {
|
||||
const message =
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
await (scheduler as any).getToolNotFoundMessage(name);
|
||||
expect(message).toContain('disabled by default');
|
||||
expect(message).toContain('tools.todoWrite.enabled');
|
||||
expect(message).toMatch(/restart Qwen Code/i);
|
||||
expect(message).not.toContain('Did you mean');
|
||||
}
|
||||
});
|
||||
|
||||
it('should name both controls when todo_write is disabled twice', async () => {
|
||||
const mockToolRegistry = {
|
||||
getAllToolNames: () => ['glob', 'read_file'],
|
||||
getTool: () => undefined,
|
||||
ensureTool: async () => undefined,
|
||||
} as unknown as ToolRegistry;
|
||||
|
||||
const mockConfig = {
|
||||
getToolRegistry: () => mockToolRegistry,
|
||||
getDisabledTools: vi
|
||||
.fn()
|
||||
.mockReturnValue(new Set<string>(['todo_write'])),
|
||||
getPermissionManager: vi.fn().mockReturnValue(null),
|
||||
isTodoWriteEnabled: vi.fn().mockReturnValue(false),
|
||||
} as unknown as Config;
|
||||
|
||||
const scheduler = new CoreToolScheduler({
|
||||
config: mockConfig,
|
||||
getPreferredEditor: () => 'vscode',
|
||||
onEditorClose: vi.fn(),
|
||||
});
|
||||
|
||||
for (const name of ['todo_write', 'TodoWrite']) {
|
||||
const message =
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
await (scheduler as any).getToolNotFoundMessage(name);
|
||||
expect(message).toContain('disabled for this workspace');
|
||||
expect(message).toContain('tools.todoWrite.enabled');
|
||||
expect(message).toMatch(/restart Qwen Code/i);
|
||||
expect(message).not.toContain('only controls');
|
||||
}
|
||||
});
|
||||
|
||||
it('should attribute enabled todo_write to the workspace toggle', async () => {
|
||||
const mockToolRegistry = {
|
||||
getAllToolNames: () => ['glob', 'read_file'],
|
||||
getTool: () => undefined,
|
||||
ensureTool: async () => undefined,
|
||||
} as unknown as ToolRegistry;
|
||||
|
||||
const mockConfig = {
|
||||
getToolRegistry: () => mockToolRegistry,
|
||||
getDisabledTools: vi
|
||||
.fn()
|
||||
.mockReturnValue(new Set<string>(['todo_write'])),
|
||||
getPermissionManager: vi.fn().mockReturnValue(null),
|
||||
isTodoWriteEnabled: vi.fn().mockReturnValue(true),
|
||||
} as unknown as Config;
|
||||
|
||||
const scheduler = new CoreToolScheduler({
|
||||
config: mockConfig,
|
||||
getPreferredEditor: () => 'vscode',
|
||||
onEditorClose: vi.fn(),
|
||||
});
|
||||
|
||||
for (const name of ['todo_write', 'TodoWrite']) {
|
||||
const message =
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
await (scheduler as any).getToolNotFoundMessage(name);
|
||||
expect(message).toContain('disabled for this workspace');
|
||||
expect(message).not.toContain('disabled by default');
|
||||
}
|
||||
});
|
||||
|
||||
it('should attribute enabled todo_write to the core tools allowlist', async () => {
|
||||
const mockToolRegistry = {
|
||||
getAllToolNames: () => ['glob', 'read_file'],
|
||||
getTool: () => undefined,
|
||||
ensureTool: async () => undefined,
|
||||
} as unknown as ToolRegistry;
|
||||
|
||||
const mockConfig = {
|
||||
getToolRegistry: () => mockToolRegistry,
|
||||
getDisabledTools: vi.fn().mockReturnValue(new Set<string>()),
|
||||
getPermissionManager: vi.fn().mockReturnValue({
|
||||
findMatchingDenyRule: vi.fn().mockReturnValue(undefined),
|
||||
isToolDisabledByCoreToolsAllowList: vi.fn().mockReturnValue(true),
|
||||
}),
|
||||
isTodoWriteEnabled: vi.fn().mockReturnValue(true),
|
||||
} as unknown as Config;
|
||||
|
||||
const scheduler = new CoreToolScheduler({
|
||||
config: mockConfig,
|
||||
getPreferredEditor: () => 'vscode',
|
||||
onEditorClose: vi.fn(),
|
||||
});
|
||||
|
||||
const message =
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
await (scheduler as any).getToolNotFoundMessage('todo_write');
|
||||
expect(message).toContain('core tools allowlist');
|
||||
expect(message).toContain('tools.core');
|
||||
expect(message).not.toContain(
|
||||
'Enable it with the tools.todoWrite.enabled',
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
{ settingEnabled: true, settingHint: false },
|
||||
{ settingEnabled: false, settingHint: true },
|
||||
])(
|
||||
'should attribute denied todo_write when settingEnabled=$settingEnabled',
|
||||
async ({ settingEnabled, settingHint }) => {
|
||||
const message = await getOptInToolNotFoundMessage(
|
||||
{
|
||||
getDisabledTools: () => new Set<string>(),
|
||||
getPermissionManager: () =>
|
||||
({
|
||||
findMatchingDenyRule: () => 'todo_write',
|
||||
isToolDisabledByCoreToolsAllowList: () => false,
|
||||
}) as unknown as PermissionManager,
|
||||
isTodoWriteEnabled: () => settingEnabled,
|
||||
} as unknown as Config,
|
||||
'todo_write',
|
||||
() => false,
|
||||
);
|
||||
|
||||
expect(message).toContain(
|
||||
'blocked by the permissions.deny or --exclude-tools rule',
|
||||
);
|
||||
expect(
|
||||
message?.includes('Enable tools.todoWrite.enabled as well.'),
|
||||
).toBe(settingHint);
|
||||
},
|
||||
);
|
||||
|
||||
it('should not claim list_directory is disabled when an alias is used for a registered tool', async () => {
|
||||
const lsTool = {
|
||||
name: 'list_directory',
|
||||
|
||||
@@ -255,6 +255,87 @@ const GATE_EXEMPT_TOOLS = new Set<string>([
|
||||
ToolNames.ENTER_PLAN_MODE,
|
||||
]);
|
||||
|
||||
const OPT_IN_TOOL_MESSAGES: Record<
|
||||
string,
|
||||
{ setting: string; defaultUnavailableMessage: string }
|
||||
> = {
|
||||
[ToolNames.LS]: {
|
||||
setting: 'tools.listDirectory.enabled',
|
||||
defaultUnavailableMessage:
|
||||
'is a built-in tool that is disabled by default because glob covers directory listing in most cases. Enable it with the tools.listDirectory.enabled setting. Use glob instead.',
|
||||
},
|
||||
[ToolNames.TODO_WRITE]: {
|
||||
setting: 'tools.todoWrite.enabled',
|
||||
defaultUnavailableMessage:
|
||||
'is a built-in tool that is disabled by default. Enable it with the tools.todoWrite.enabled setting and restart Qwen Code.',
|
||||
},
|
||||
};
|
||||
|
||||
type OptInToolMessageConfig = Pick<
|
||||
Config,
|
||||
'getDisabledTools' | 'getPermissionManager' | 'isTodoWriteEnabled'
|
||||
>;
|
||||
|
||||
export async function getOptInToolNotFoundMessage(
|
||||
config: OptInToolMessageConfig,
|
||||
unknownToolName: string,
|
||||
isCanonicalToolRegistered: (
|
||||
canonicalName: string,
|
||||
) => boolean | Promise<boolean>,
|
||||
): Promise<string | undefined> {
|
||||
const canonicalName = resolveToolName(unknownToolName);
|
||||
const definition = Object.hasOwn(OPT_IN_TOOL_MESSAGES, canonicalName)
|
||||
? OPT_IN_TOOL_MESSAGES[canonicalName]
|
||||
: undefined;
|
||||
if (!definition || (await isCanonicalToolRegistered(canonicalName))) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const workspaceDisabled = config.getDisabledTools().has(canonicalName);
|
||||
if (canonicalName === ToolNames.LS) {
|
||||
if (workspaceDisabled) {
|
||||
return `Tool "${unknownToolName}" has been disabled for this workspace via the workspace tools toggle. Re-enable it there; the ${definition.setting} setting only controls whether the tool is registered by default.`;
|
||||
}
|
||||
return `Tool "${unknownToolName}" ${definition.defaultUnavailableMessage}`;
|
||||
}
|
||||
|
||||
const settingEnabled = config.isTodoWriteEnabled();
|
||||
const permissionManager = config.getPermissionManager();
|
||||
const denyRule = permissionManager?.findMatchingDenyRule({
|
||||
toolName: canonicalName,
|
||||
});
|
||||
const omittedFromCoreTools =
|
||||
permissionManager?.isToolDisabledByCoreToolsAllowList(canonicalName) ===
|
||||
true;
|
||||
|
||||
if (workspaceDisabled) {
|
||||
const settingAction = settingEnabled
|
||||
? ''
|
||||
: ` Also enable ${definition.setting}.`;
|
||||
return `Tool "${unknownToolName}" has been disabled for this workspace via the workspace tools toggle. Re-enable it there.${settingAction} Restart Qwen Code after updating these controls.`;
|
||||
}
|
||||
|
||||
if (denyRule) {
|
||||
const settingAction = settingEnabled
|
||||
? ''
|
||||
: ` Enable ${definition.setting} as well.`;
|
||||
return `Tool "${unknownToolName}" is blocked by the permissions.deny or --exclude-tools rule "${denyRule}".${settingAction} Remove the deny rule and restart Qwen Code.`;
|
||||
}
|
||||
|
||||
if (omittedFromCoreTools) {
|
||||
const settingAction = settingEnabled
|
||||
? ''
|
||||
: ` Enable ${definition.setting} as well.`;
|
||||
return `Tool "${unknownToolName}" is not listed in the active core tools allowlist (--core-tools or settings tools.core).${settingAction} Add it to the allowlist and restart Qwen Code.`;
|
||||
}
|
||||
|
||||
if (!settingEnabled) {
|
||||
return `Tool "${unknownToolName}" ${definition.defaultUnavailableMessage}`;
|
||||
}
|
||||
|
||||
return `Tool "${unknownToolName}" is enabled by ${definition.setting} but is blocked by active tool registration rules. Check permissions.deny, --exclude-tools, and tools.core or --core-tools, then restart Qwen Code.`;
|
||||
}
|
||||
|
||||
function extractTextFromPartListUnion(c: PartListUnion): string {
|
||||
if (typeof c === 'string') return c;
|
||||
if (Array.isArray(c)) {
|
||||
@@ -2137,23 +2218,16 @@ export class CoreToolScheduler {
|
||||
return mcpMessage;
|
||||
}
|
||||
|
||||
// `list_directory` is an opt-in built-in: when it is genuinely unregistered,
|
||||
// say how to turn it on instead of suggesting unrelated tools by edit
|
||||
// distance. Resolve aliases (`ListFiles`, `ReadFolder`, ...) so an aliased
|
||||
// call gets the same explanation — but only once the canonical name is
|
||||
// confirmed absent. The registry is keyed by canonical names while the
|
||||
// lookup that lands here resolves legacy migrations only, so an alias call
|
||||
// misses even when the tool IS enabled; that case must keep the generic
|
||||
// path's "Did you mean list_directory" self-correction.
|
||||
const canonicalName = resolveToolName(unknownToolName);
|
||||
if (
|
||||
canonicalName === ToolNames.LS &&
|
||||
!(await this.toolRegistry.ensureTool(canonicalName))
|
||||
) {
|
||||
if (this.config.getDisabledTools().has(canonicalName)) {
|
||||
return `Tool "${unknownToolName}" has been disabled for this workspace via the workspace tools toggle. Re-enable it there; the tools.listDirectory.enabled setting only controls whether the tool is registered by default.`;
|
||||
}
|
||||
return `Tool "${unknownToolName}" is a built-in tool that is disabled by default because glob covers directory listing in most cases. Enable it with the tools.listDirectory.enabled setting. Use glob instead.`;
|
||||
// Resolve aliases before checking registration so enabled canonical tools
|
||||
// keep the generic "Did you mean" correction for an alias-only miss.
|
||||
const optInToolMessage = await getOptInToolNotFoundMessage(
|
||||
this.config,
|
||||
unknownToolName,
|
||||
async (canonicalName) =>
|
||||
Boolean(await this.toolRegistry.ensureTool(canonicalName)),
|
||||
);
|
||||
if (optInToolMessage) {
|
||||
return optInToolMessage;
|
||||
}
|
||||
|
||||
// Standard "not found" message with Levenshtein suggestions
|
||||
|
||||
@@ -69,6 +69,31 @@ describe('Core System Prompt (prompts.ts)', () => {
|
||||
expect(prompt).toMatchSnapshot(); // Use snapshot for base prompt structure
|
||||
});
|
||||
|
||||
it('does not advertise todo_write by default', () => {
|
||||
vi.stubEnv('SANDBOX', undefined);
|
||||
const prompt = getCoreSystemPrompt();
|
||||
|
||||
expect(prompt).not.toContain('todo_write');
|
||||
expect(prompt).not.toContain('# Task Management');
|
||||
expect(prompt).toContain('revise it as you learn');
|
||||
});
|
||||
|
||||
it('advertises todo_write when it is enabled', () => {
|
||||
vi.stubEnv('SANDBOX', undefined);
|
||||
const prompt = getCoreSystemPrompt(
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
'interactive',
|
||||
undefined,
|
||||
true,
|
||||
);
|
||||
|
||||
expect(prompt).toContain('# Task Management');
|
||||
expect(prompt).toContain("Use 'todo_write'");
|
||||
expect(prompt).toContain('pass the matching Todo ID as `todo_id`');
|
||||
});
|
||||
|
||||
it('instructs the model not to bypass denied tool calls through equivalent paths', () => {
|
||||
vi.stubEnv('SANDBOX', undefined);
|
||||
const prompt = getCoreSystemPrompt();
|
||||
@@ -178,7 +203,14 @@ describe('Core System Prompt (prompts.ts)', () => {
|
||||
|
||||
it('uses todos selectively and keeps plans outcome-oriented', () => {
|
||||
vi.stubEnv('SANDBOX', undefined);
|
||||
const prompt = getCoreSystemPrompt();
|
||||
const prompt = getCoreSystemPrompt(
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
'interactive',
|
||||
undefined,
|
||||
true,
|
||||
);
|
||||
|
||||
expect(prompt).toContain('complex, ambiguous, or multi-phase tasks');
|
||||
expect(prompt).toContain('Do not use it for simple or single-step queries');
|
||||
@@ -810,6 +842,7 @@ describe('main-session style: reminder decision matches prompt section', () => {
|
||||
getExperimentalZedIntegration: () => opts.acp,
|
||||
getInputFormat: () => InputFormat.TEXT,
|
||||
isInteractive: () => opts.interactive,
|
||||
isTodoWriteEnabled: () => false,
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -905,6 +938,15 @@ describe('main-session style: reminder decision matches prompt section', () => {
|
||||
'<function=run_shell_command>',
|
||||
);
|
||||
});
|
||||
|
||||
it('forwards the todo_write setting to the base prompt', () => {
|
||||
const config = {
|
||||
...makeConfig({ interactive: false, acp: false }),
|
||||
isTodoWriteEnabled: () => true,
|
||||
};
|
||||
|
||||
expect(getMainSessionBaseSystemPrompt(config)).toContain('todo_write');
|
||||
});
|
||||
});
|
||||
|
||||
describe('main-session style: project trust gate', () => {
|
||||
@@ -928,6 +970,7 @@ describe('main-session style: project trust gate', () => {
|
||||
getExperimentalZedIntegration: () => false,
|
||||
getInputFormat: () => InputFormat.TEXT,
|
||||
isInteractive: () => true,
|
||||
isTodoWriteEnabled: () => false,
|
||||
...(trusted === undefined ? {} : { isTrustedFolder: () => trusted }),
|
||||
});
|
||||
|
||||
|
||||
@@ -268,12 +268,18 @@ export function getCustomSystemPrompt(
|
||||
* exactly this section and nothing else — mandates, safety rules, tool
|
||||
* guidance and tone stay in force under every style.
|
||||
*/
|
||||
function getSoftwareEngineeringTasksSection(): string {
|
||||
function getSoftwareEngineeringTasksSection(todoWriteEnabled: boolean): string {
|
||||
const planGuidance = todoWriteEnabled
|
||||
? `Use '${ToolNames.TODO_WRITE}' for complex, ambiguous, or multi-step work when visible progress tracking adds value. Keep the plan short and outcome-oriented; skip it for simple tasks unless the user explicitly requests a plan.`
|
||||
: 'For complex, ambiguous, or multi-step work, form a concise, outcome-oriented approach and revise it as you learn. Skip formal planning for simple tasks unless the user explicitly requests a plan.';
|
||||
const todoAdaptationGuidance = todoWriteEnabled
|
||||
? ' If a todo list exists, keep it current as the scope or approach changes.'
|
||||
: '';
|
||||
return `## Software Engineering Tasks
|
||||
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this iterative approach:
|
||||
- **Plan:** Use '${ToolNames.TODO_WRITE}' for complex, ambiguous, or multi-step work when visible progress tracking adds value. Keep the plan short and outcome-oriented; skip it for simple tasks unless the user explicitly requests a plan.
|
||||
- **Plan:** ${planGuidance}
|
||||
- **Implement:** Begin implementing while gathering context as needed. Use available search and editing tools strategically, adhering to project conventions (see 'Core Mandates'). Do not add features, refactor code, or make "improvements" beyond what was asked. Don't add error handling, fallbacks, or validation for scenarios that can't happen—only validate at system boundaries (user input, external APIs). Don't create helpers, utilities, or abstractions for one-time operations. Three similar lines of code is better than a premature abstraction. Prefer editing existing files over creating new ones.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles. If a todo list exists, keep it current as the scope or approach changes. If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Adapt:** Refine your approach as you discover new information or encounter obstacles.${todoAdaptationGuidance} If an approach fails, diagnose why before switching tactics—read the error, check your assumptions, and try a focused fix. Don't retry blindly, but don't abandon a viable approach after a single failure.
|
||||
- **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands. Before reporting a task complete, verify it actually works. If you can't verify (no test exists, can't run the code), say so explicitly rather than claiming success.
|
||||
- **Verify (Standards):** When your task involves a code or system change, 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 (or obtained from the user). This ensures code quality and adherence to standards. Read-only or explanatory turns do not require verification.
|
||||
- **Report outcomes faithfully:** If tests fail, say so with the relevant output. If you did not run a verification step, say that rather than implying it succeeded. Never claim "all tests pass" when output shows failures, never suppress failing checks to manufacture a green result, and never characterize incomplete or broken work as done.
|
||||
@@ -293,6 +299,7 @@ function buildDefaultBasePrompt(
|
||||
interaction: { role: string; questions: string },
|
||||
model: string | undefined,
|
||||
outputStyle?: OutputStyleDefinition | null,
|
||||
todoWriteEnabled = false,
|
||||
): string {
|
||||
// A style with `keepCodingInstructions: false` drops exactly the
|
||||
// software-engineering workflow section; every other section, including the
|
||||
@@ -300,7 +307,24 @@ function buildDefaultBasePrompt(
|
||||
const softwareEngineeringTasks =
|
||||
outputStyle?.keepCodingInstructions === false
|
||||
? ''
|
||||
: getSoftwareEngineeringTasksSection();
|
||||
: getSoftwareEngineeringTasksSection(todoWriteEnabled);
|
||||
|
||||
const taskManagementSection = todoWriteEnabled
|
||||
? `# Task Management
|
||||
You have access to the ${ToolNames.TODO_WRITE} tool to keep user-visible progress for work that benefits from explicit tracking. Use it for complex, ambiguous, or multi-phase tasks or requests with multiple independent outcomes. Do not use it for simple or single-step queries that you can answer or complete immediately unless the user explicitly asks for a plan.
|
||||
|
||||
When you create a todo list:
|
||||
- Keep it short and outcome-oriented. Use a few meaningful, logically ordered, verifiable steps rather than one item per error, file, command, or minor edit.
|
||||
- When an active Todo plan covers work delegated through top-level Agent calls, pass the matching Todo ID as \`todo_id\` so the execution can be associated with that plan node. Do not create a Todo solely to wrap a delegation that does not otherwise need task tracking.
|
||||
- Keep at most one item in_progress. Keep the list current, mark finished work completed, and revise it when the scope or approach changes. When work completes together, update multiple statuses in one tool call rather than making bookkeeping-only calls.
|
||||
- Do not repeat the full todo list in prose after calling the tool; briefly communicate only important context or the next step.
|
||||
|
||||
`
|
||||
: '';
|
||||
const taskManagementToolGuidance = todoWriteEnabled
|
||||
? `- **Task Management:** Use '${ToolNames.TODO_WRITE}' only when explicit tracking adds value. Keep plans concise, outcome-oriented, and current; do not create a todo list for simple or single-step work unless the user explicitly requests one.
|
||||
`
|
||||
: '';
|
||||
|
||||
// A QWEN_SYSTEM_IDENTITY_MD override is inserted verbatim, so the styled
|
||||
// variant applies only to the default identity sentence — the override is
|
||||
@@ -327,16 +351,7 @@ ${coreIdentity}
|
||||
- **Plan before uncertain work:** If the task is not yet clear enough to safely execute, do not make small speculative edits. Continue read-only investigation, make a plan in the current mode, or follow the active interaction mode's question guidance. Do not enter plan mode or call ${ToolNames.ENTER_PLAN_MODE} on your own just because the task involves planning or complexity. Use plan mode only when the user explicitly asks you to switch to plan mode, has already enabled it, or confirms they want it.
|
||||
|
||||
|
||||
# Task Management
|
||||
You have access to the ${ToolNames.TODO_WRITE} tool to keep user-visible progress for work that benefits from explicit tracking. Use it for complex, ambiguous, or multi-phase tasks or requests with multiple independent outcomes. Do not use it for simple or single-step queries that you can answer or complete immediately unless the user explicitly asks for a plan.
|
||||
|
||||
When you create a todo list:
|
||||
- Keep it short and outcome-oriented. Use a few meaningful, logically ordered, verifiable steps rather than one item per error, file, command, or minor edit.
|
||||
- When an active Todo plan covers work delegated through top-level Agent calls, pass the matching Todo ID as \`todo_id\` so the execution can be associated with that plan node. Do not create a Todo solely to wrap a delegation that does not otherwise need task tracking.
|
||||
- Keep at most one item in_progress. Keep the list current, mark finished work completed, and revise it when the scope or approach changes. When work completes together, update multiple statuses in one tool call rather than making bookkeeping-only calls.
|
||||
- Do not repeat the full todo list in prose after calling the tool; briefly communicate only important context or the next step.
|
||||
|
||||
# Primary Workflows
|
||||
${taskManagementSection}# Primary Workflows
|
||||
|
||||
${softwareEngineeringTasks}- Tool results and user messages may include <system-reminder> tags. <system-reminder> tags contain useful information and reminders. They are NOT part of the user's provided input or the tool result.
|
||||
- When you see a <persisted-output> tag in a tool result, the full output was saved to disk because it was too large. Use the read_file tool to access the complete content if the preview is insufficient.
|
||||
@@ -375,8 +390,7 @@ Final responses should be concise by default, but their shape and depth must mat
|
||||
- To search the content of files, use '${ToolNames.GREP}' instead of grep or rg
|
||||
- Reserve using the '${ToolNames.SHELL}' exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool and only fallback on using the '${ToolNames.SHELL}' tool for these if it is absolutely necessary.
|
||||
- **Tool Fallback:** If a tool returns empty, unhelpful, or unexpected results, try an alternative tool that can accomplish the same goal before telling the user it cannot be done. Never give up after a single tool failure.
|
||||
- **Task Management:** Use '${ToolNames.TODO_WRITE}' only when explicit tracking adds value. Keep plans concise, outcome-oriented, and current; do not create a todo list for simple or single-step work unless the user explicitly requests one.
|
||||
- **Parallel Tool Calls:** You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead.
|
||||
${taskManagementToolGuidance}- **Parallel Tool Calls:** You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead.
|
||||
- **File Paths:** Always use absolute paths when referring to files with tools like '${ToolNames.READ_FILE}' or '${ToolNames.WRITE_FILE}'. Relative paths are not supported. You must provide an absolute path.
|
||||
- **Background Processes:** Use background execution with \`is_background: true\` for commands that are unlikely to stop on their own, e.g. \`node server.js\`. Do not append a trailing \`&\` when using the shell tool's managed background mode. If unsure, follow the active interaction mode's question guidance.
|
||||
- **Interactive Commands:** Try to avoid shell commands that are likely to require user interaction (e.g. \`git rebase -i\`). Use non-interactive versions of commands (e.g. \`npm init -y\` instead of \`npm init\`) when available, and otherwise remind the user that interactive shell commands are not supported and may cause hangs until canceled by the user.
|
||||
@@ -497,6 +511,7 @@ export function resolveMainSessionOutputStyle(config: {
|
||||
* @param interactionMode - Interactive vs. headless prompt variant.
|
||||
* @param outputStyle - Active output style, layered onto the base prompt.
|
||||
* Ignored when `QWEN_SYSTEM_MD` replaces the base prompt (see below).
|
||||
* @param todoWriteEnabled - Whether the default prompt may advertise Todo.
|
||||
*/
|
||||
export function getCoreSystemPrompt(
|
||||
userMemory?: string,
|
||||
@@ -504,6 +519,7 @@ export function getCoreSystemPrompt(
|
||||
appendInstruction?: string,
|
||||
interactionMode: SystemPromptInteractionMode = 'interactive',
|
||||
outputStyle?: OutputStyleDefinition | null,
|
||||
todoWriteEnabled = false,
|
||||
): string {
|
||||
const effectiveOutputStyle = resolveEffectiveOutputStyle(
|
||||
outputStyle,
|
||||
@@ -544,7 +560,12 @@ export function getCoreSystemPrompt(
|
||||
// effect (including empty-file clear).
|
||||
const basePrompt = systemMdEnabled
|
||||
? fs.readFileSync(systemMdPath, 'utf8')
|
||||
: buildDefaultBasePrompt(interaction, model, effectiveOutputStyle);
|
||||
: buildDefaultBasePrompt(
|
||||
interaction,
|
||||
model,
|
||||
effectiveOutputStyle,
|
||||
todoWriteEnabled,
|
||||
);
|
||||
|
||||
// if QWEN_WRITE_SYSTEM_MD is set (and not 0|false), write base system prompt to file
|
||||
const writeSystemMdResolution = resolvePathFromEnv(
|
||||
@@ -566,7 +587,12 @@ export function getCoreSystemPrompt(
|
||||
writePath,
|
||||
systemMdEnabled
|
||||
? basePrompt
|
||||
: buildDefaultBasePrompt(interaction, model, undefined),
|
||||
: buildDefaultBasePrompt(
|
||||
interaction,
|
||||
model,
|
||||
undefined,
|
||||
todoWriteEnabled,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,6 @@ when_to_use: When the user asks to create a new application, project, website, g
|
||||
- **3D Games:** HTML/CSS/JavaScript with Three.js.
|
||||
- **2D Games:** HTML/CSS/JavaScript.
|
||||
3. **User Approval:** Obtain user approval for the proposed plan.
|
||||
4. **Implementation:** Use the 'todo_write' tool to convert the approved plan into a structured todo list with specific, actionable tasks, then autonomously implement each task utilizing all available tools. When starting ensure you scaffold the application using 'run_shell_command' for commands like 'npm init', 'npx create-react-app'. Aim for full scope completion. Proactively create or source necessary placeholder assets (e.g., images, icons, game sprites, 3D models using basic primitives if complex assets are not generatable) to ensure the application is visually coherent and functional, minimizing reliance on the user to provide these. If the model can generate simple assets (e.g., a uniformly colored square sprite, a simple 3D cube), it should do so. Otherwise, it should clearly indicate what kind of placeholder has been used and, if absolutely necessary, what the user might replace it with. Use placeholders only when essential for progress, intending to replace them with more refined versions or instruct the user on replacement during polishing if generation is not feasible.
|
||||
4. **Implementation:** Convert the approved plan into specific, actionable steps and autonomously implement them using all available tools. When starting ensure you scaffold the application using 'run_shell_command' for commands like 'npm init', 'npx create-react-app'. Aim for full scope completion. Proactively create or source necessary placeholder assets (e.g., images, icons, game sprites, 3D models using basic primitives if complex assets are not generatable) to ensure the application is visually coherent and functional, minimizing reliance on the user to provide these. If the model can generate simple assets (e.g., a uniformly colored square sprite, a simple 3D cube), it should do so. Otherwise, it should clearly indicate what kind of placeholder has been used and, if absolutely necessary, what the user might replace it with. Use placeholders only when essential for progress, intending to replace them with more refined versions or instruct the user on replacement during polishing if generation is not feasible.
|
||||
5. **Verify:** Review work against the original request, the approved plan. Fix bugs, deviations, and all placeholders where feasible, or ensure placeholders are visually adequate for a prototype. Ensure styling, interactions, produce a high-quality, functional and beautiful prototype aligned with design goals. Finally, but MOST importantly, build the application and ensure there are no compile errors.
|
||||
6. **Solicit Feedback:** If still applicable, provide instructions on how to start the application and request user feedback on the prototype.
|
||||
@@ -214,6 +214,7 @@ describe('AgentTool', () => {
|
||||
getTranscriptPath: vi.fn().mockReturnValue('/test/transcript'),
|
||||
getTeamManager: vi.fn().mockReturnValue(undefined),
|
||||
isAgentTeamEnabled: vi.fn().mockReturnValue(false),
|
||||
isTodoWriteEnabled: vi.fn().mockReturnValue(true),
|
||||
getApprovalMode: vi.fn().mockReturnValue('default'),
|
||||
getSessionWorkflowPlanRevision: vi.fn().mockReturnValue(undefined),
|
||||
getModel: vi.fn().mockReturnValue('parent-model'),
|
||||
@@ -571,6 +572,19 @@ describe('AgentTool', () => {
|
||||
expect(agentTool.description).toContain('set `todo_id`');
|
||||
});
|
||||
|
||||
it('omits the todo association when todo_write is disabled', async () => {
|
||||
vi.mocked(config.isTodoWriteEnabled).mockReturnValue(false);
|
||||
const tool = new AgentTool(config);
|
||||
await vi.runAllTimersAsync();
|
||||
|
||||
const properties = tool.schema.parametersJsonSchema as {
|
||||
properties: { todo_id?: unknown };
|
||||
};
|
||||
expect(properties.properties.todo_id).toBeUndefined();
|
||||
expect(tool.description).not.toContain('todo_id');
|
||||
tool.dispose();
|
||||
});
|
||||
|
||||
it('declares fork_turns for fork agents without a none option', () => {
|
||||
const properties = agentTool.schema.parametersJsonSchema as {
|
||||
properties: {
|
||||
|
||||
@@ -705,12 +705,16 @@ export class AgentTool extends BaseDeclarativeTool<AgentParams, ToolResult> {
|
||||
type: 'string',
|
||||
description: 'The task for the agent to perform',
|
||||
},
|
||||
todo_id: {
|
||||
type: 'string',
|
||||
maxLength: 500,
|
||||
description:
|
||||
'ID of the todo this top-level agent execution implements. Use an ID from the current todo list when one exists.',
|
||||
},
|
||||
...(config.isTodoWriteEnabled()
|
||||
? {
|
||||
todo_id: {
|
||||
type: 'string',
|
||||
maxLength: 500,
|
||||
description:
|
||||
'ID of the todo this top-level agent execution implements. Use an ID from the current todo list when one exists.',
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
subagent_type: {
|
||||
type: 'string',
|
||||
description:
|
||||
@@ -840,6 +844,9 @@ export class AgentTool extends BaseDeclarativeTool<AgentParams, ToolResult> {
|
||||
const teamGuidance = this.config.isAgentTeamEnabled()
|
||||
? `**For tasks requiring multiple agents to coordinate, communicate, or work as a team**: Use ${ToolNames.TEAM_CREATE} first to create a team, then spawn teammates using the Agent tool with explicit \`name\` and \`subagent_type\` parameters (the active team is selected automatically). Named teammates always run concurrently and report through team messaging; omit \`run_in_background\` when spawning one — an explicit \`run_in_background: false\` is rejected, so for an inline blocking result omit \`name\` and use a regular agent instead. Set \`read_only: true\` for investigation teammates. A single writer teammate may be pinned to a leader-owned Git worktree with \`working_dir\`; shut it down before removing that worktree. Teams enable message passing between agents, shared task lists, and coordinated workflows. If the user asks for agents to collaborate, review each other's work, or produce a consolidated result — create a team.`
|
||||
: '';
|
||||
const todoGuidance = this.config.isTodoWriteEnabled()
|
||||
? '- When a user-visible todo plan exists, set `todo_id` to the ID of the plan node this top-level agent execution implements. Create the todo before launching the agent when practical. Omit `todo_id` for work that is not represented by the current plan.\n'
|
||||
: '';
|
||||
const baseDescription = `Launch a new agent to handle complex, multi-step tasks autonomously.
|
||||
The Agent tool launches specialized agents (subprocesses) that autonomously handle complex tasks. Each agent type has specific capabilities and tools available to it.
|
||||
|
||||
@@ -858,8 +865,7 @@ ${teamGuidance}
|
||||
|
||||
Usage notes:
|
||||
- Always include a short description (3-5 words) summarizing what the agent will do
|
||||
- When a user-visible todo plan exists, set \`todo_id\` to the ID of the plan node this top-level agent execution implements. Create the todo before launching the agent when practical. Omit \`todo_id\` for work that is not represented by the current plan.
|
||||
- Delegate only concrete, bounded tasks that can run independently.
|
||||
${todoGuidance}- Delegate only concrete, bounded tasks that can run independently.
|
||||
- Keep immediate critical-path work local when your next action depends on it.
|
||||
- Do not duplicate work between the parent and subagents.
|
||||
- Run agents concurrently only when their tasks are independent. For code changes, give concurrent agents disjoint write scopes; launch them in a single message with multiple tool uses.
|
||||
|
||||
@@ -1285,6 +1285,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"todoWrite": {
|
||||
"description": "Settings for the built-in todo_write tool. Opt-in: the tool is disabled by default.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Enable the built-in todo_write tool and its system-prompt guidance.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"shell": {
|
||||
"description": "Settings for shell execution.",
|
||||
"type": "object",
|
||||
@@ -3661,7 +3672,7 @@
|
||||
"default": true
|
||||
},
|
||||
"todoStopGuard": {
|
||||
"description": "Allow daemon and ACP sessions to continue an unfinished top-level Todo list for at most two consecutive primary-model calls without new user input. Mid-turn user input starts a fresh two-attempt stage. Disabled in safe, bare, and Approval plan modes.",
|
||||
"description": "Allow daemon and ACP sessions to continue an unfinished top-level Todo list for at most two consecutive primary-model calls without new user input. Requires tools.todoWrite.enabled. Mid-turn user input starts a fresh two-attempt stage. Disabled in safe, bare, and Approval plan modes.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user