summaryrefslogtreecommitdiffhomepage
path: root/packages/api/src
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-05-27 17:22:52 +0900
committerAdam Malczewski <[email protected]>2026-05-27 17:22:52 +0900
commitda57842686ebfd157396551fc76d0c18f7676335 (patch)
tree31caa165c9c6188ee7fa27663ec832a13f6a7ac2 /packages/api/src
parent399e1509b93b9f3c56142f94b8fb2c30c2dedb2f (diff)
downloaddispatch-da57842686ebfd157396551fc76d0c18f7676335.tar.gz
dispatch-da57842686ebfd157396551fc76d0c18f7676335.zip
feat: tool-output truncation+spill, read_file pagination, read_file_slice, symlink-safe path resolution
Diffstat (limited to 'packages/api/src')
-rw-r--r--packages/api/src/agent-manager.ts18
1 files changed, 18 insertions, 0 deletions
diff --git a/packages/api/src/agent-manager.ts b/packages/api/src/agent-manager.ts
index 73b65f5..487b09f 100644
--- a/packages/api/src/agent-manager.ts
+++ b/packages/api/src/agent-manager.ts
@@ -7,9 +7,11 @@ import {
BackgroundShellStore,
BackgroundTranscriptStore,
type ClaudeAccount,
+ clearSpillForTab,
configToRuleset,
createConfigWatcher,
createListFilesTool,
+ createReadFileSliceTool,
createReadFileTool,
createRetrieveTool,
createRunShellTool,
@@ -41,6 +43,8 @@ import { setTabsAgentManager } from "./routes/tabs.js";
const TOOL_DESCRIPTIONS: Record<string, string> = {
read_file: "Read the contents of a file",
+ read_file_slice:
+ "Read a character-range slice of a single line in a file (for inspecting long lines that read_file truncated)",
list_files: "List files and directories",
write_file: "Write content to a file (creates parent directories if needed)",
run_shell:
@@ -369,6 +373,12 @@ export class AgentManager {
const allowed = new Set(tabAgent.toolsOverride);
if (allowed.has("read_file")) {
toolEntries.push({ name: "read_file", tool: createReadFileTool(workingDirectory) });
+ // read_file_slice is a companion to read_file — only useful for
+ // inspecting long lines that read_file truncated. Ship them together.
+ toolEntries.push({
+ name: "read_file_slice",
+ tool: createReadFileSliceTool(workingDirectory),
+ });
// list_files is bundled with read access
if (allowed.has("list_files")) {
toolEntries.push({ name: "list_files", tool: createListFilesTool(workingDirectory) });
@@ -432,6 +442,10 @@ export class AgentManager {
// Parent agent: use permission settings from DB
if (permRead) {
toolEntries.push({ name: "read_file", tool: createReadFileTool(workingDirectory) });
+ toolEntries.push({
+ name: "read_file_slice",
+ tool: createReadFileSliceTool(workingDirectory),
+ });
toolEntries.push({ name: "list_files", tool: createListFilesTool(workingDirectory) });
}
if (permEdit) {
@@ -607,6 +621,7 @@ export class AgentManager {
permissionChecker: this.permissionManager ?? undefined,
ruleset,
provider,
+ tabId,
...(claudeCredentials ? { claudeCredentials } : {}),
},
{
@@ -670,6 +685,9 @@ export class AgentManager {
deleteTab(tabId: string): void {
this.stopTab(tabId);
this.tabAgents.delete(tabId);
+ // Drop any spilled tool-output files this tab accumulated. Best-effort —
+ // errors are swallowed inside the helper. See packages/core/src/tools/truncate.ts.
+ clearSpillForTab(tabId);
}
/**