refactor(coding-agent): renamed todo_write tool to todo
- Renamed `TodoWriteTool` to `TodoTool` and its source/prompt files. - Updated tool registration, schema, renderers, and gating to `todo`. - Adjusted cursor provider native tool names and tests to match. - Renamed strike-animation constants and `todo-error-reminder` type.
This commit is contained in:
@@ -203,7 +203,7 @@ import type { CheckpointState } from "../tools/checkpoint";
|
||||
import { outputMeta } from "../tools/output-meta";
|
||||
import { normalizeLocalScheme, resolveToCwd } from "../tools/path-utils";
|
||||
import { isAutoQaEnabled } from "../tools/report-tool-issue";
|
||||
import { getLatestTodoPhasesFromEntries, type TodoItem, type TodoPhase } from "../tools/todo-write";
|
||||
import { getLatestTodoPhasesFromEntries, type TodoItem, type TodoPhase } from "../tools/todo";
|
||||
import { ToolAbortError, ToolError } from "../tools/tool-errors";
|
||||
import { clampTimeout } from "../tools/tool-timeouts";
|
||||
import { parseCommandArgs } from "../utils/command-args";
|
||||
@@ -1807,21 +1807,21 @@ export class AgentSession {
|
||||
if (toolName === "edit" && details?.path) {
|
||||
this.#invalidateFileCacheForPath(details.path);
|
||||
}
|
||||
if (toolName === "todo_write" && !isError && Array.isArray(details?.phases)) {
|
||||
if (toolName === "todo" && !isError && Array.isArray(details?.phases)) {
|
||||
this.setTodoPhases(details.phases);
|
||||
}
|
||||
if (toolName === "todo_write" && isError) {
|
||||
if (toolName === "todo" && isError) {
|
||||
const errorText = content?.find(part => part.type === "text")?.text;
|
||||
const reminderText = [
|
||||
"<system-reminder>",
|
||||
"todo_write failed, so todo progress is not visible to the user.",
|
||||
errorText ? `Failure: ${errorText}` : "Failure: todo_write returned an error.",
|
||||
"Fix the todo payload and call todo_write again before continuing.",
|
||||
"todo failed, so todo progress is not visible to the user.",
|
||||
errorText ? `Failure: ${errorText}` : "Failure: todo returned an error.",
|
||||
"Fix the todo payload and call todo again before continuing.",
|
||||
"</system-reminder>",
|
||||
].join("\n");
|
||||
await this.sendCustomMessage(
|
||||
{
|
||||
customType: "todo-write-error-reminder",
|
||||
customType: "todo-error-reminder",
|
||||
content: reminderText,
|
||||
display: false,
|
||||
details: { toolName, errorText },
|
||||
@@ -4994,7 +4994,7 @@ export class AgentSession {
|
||||
// splice mutated canonical `#todoPhases` between tool calls, so the model
|
||||
// observed phase totals shrinking ("5 → 4") after marking tasks done. The
|
||||
// `tasks.todoClearDelay` setting is now inert; completed tasks survive
|
||||
// until the next explicit `todo_write` call removes them via `rm`/`drop`.
|
||||
// until the next explicit `todo` call removes them via `rm`/`drop`.
|
||||
|
||||
/**
|
||||
* Abort current operation and wait for agent to become idle.
|
||||
@@ -6553,16 +6553,16 @@ export class AgentSession {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!this.#toolRegistry.has("todo_write")) {
|
||||
logger.warn("Eager todo enforcement skipped because todo_write is unavailable", {
|
||||
if (!this.#toolRegistry.has("todo")) {
|
||||
logger.warn("Eager todo enforcement skipped because todo is unavailable", {
|
||||
activeToolNames: this.agent.state.tools.map(tool => tool.name),
|
||||
});
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const todoWriteToolChoice = buildNamedToolChoice("todo_write", this.model);
|
||||
if (!todoWriteToolChoice) {
|
||||
logger.warn("Eager todo enforcement skipped because the current model does not support forcing todo_write", {
|
||||
const todoToolChoice = buildNamedToolChoice("todo", this.model);
|
||||
if (!todoToolChoice) {
|
||||
logger.warn("Eager todo enforcement skipped because the current model does not support forcing todo", {
|
||||
modelApi: this.model?.api,
|
||||
modelId: this.model?.id,
|
||||
});
|
||||
@@ -6580,7 +6580,7 @@ export class AgentSession {
|
||||
attribution: "agent",
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
toolChoice: todoWriteToolChoice,
|
||||
toolChoice: todoToolChoice,
|
||||
};
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { logger, toError } from "@oh-my-pi/pi-utils";
|
||||
import { IndexedSessionStorage, type SessionStorageBackend, type SessionStorageIndexEntry } from "./indexed-session-storage";
|
||||
import {
|
||||
IndexedSessionStorage,
|
||||
type SessionStorageBackend,
|
||||
type SessionStorageIndexEntry,
|
||||
} from "./indexed-session-storage";
|
||||
|
||||
/**
|
||||
* Minimal subset of the `bun:redis` `RedisClient` surface used by
|
||||
|
||||
@@ -151,7 +151,6 @@ export class FileSessionStorage implements SessionStorage {
|
||||
fs.writeFileSync(fpath, content);
|
||||
}
|
||||
|
||||
|
||||
statSync(path: string): SessionStorageStat {
|
||||
const stats = fs.statSync(path);
|
||||
return { size: stats.size, mtimeMs: stats.mtimeMs, mtime: stats.mtime };
|
||||
@@ -465,7 +464,6 @@ export class MemorySessionStorage implements SessionStorage {
|
||||
entry.mtimeMs = mtimeMs;
|
||||
}
|
||||
|
||||
|
||||
statSync(path: string): SessionStorageStat {
|
||||
const entry = this.#requireEntry(path);
|
||||
return {
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { IndexedSessionStorage, type SessionStorageBackend, type SessionStorageIndexEntry } from "./indexed-session-storage";
|
||||
import {
|
||||
IndexedSessionStorage,
|
||||
type SessionStorageBackend,
|
||||
type SessionStorageIndexEntry,
|
||||
} from "./indexed-session-storage";
|
||||
|
||||
/**
|
||||
* Supported `bun:sql` adapter dialects. `Bun.SQL` reports this string on
|
||||
@@ -276,7 +280,9 @@ class SqlSessionStorageBackend implements SessionStorageBackend {
|
||||
|
||||
async readSlices(path: string, prefixBytes: number, suffixBytes: number): Promise<[string, string]> {
|
||||
const values =
|
||||
this.#adapter === "postgres" ? [prefixBytes, suffixBytes, path] : [prefixBytes, suffixBytes, suffixBytes, path];
|
||||
this.#adapter === "postgres"
|
||||
? [prefixBytes, suffixBytes, path]
|
||||
: [prefixBytes, suffixBytes, suffixBytes, path];
|
||||
const rows = (await this.#client.unsafe(this.#q.readSlices, values)) as SliceRow[];
|
||||
const row = rows[0];
|
||||
if (!row) throw enoent(path);
|
||||
|
||||
Reference in New Issue
Block a user