zeitlich 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -31
- package/dist/index.cjs +305 -361
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -43
- package/dist/index.d.ts +24 -43
- package/dist/index.js +277 -336
- package/dist/index.js.map +1 -1
- package/dist/{workflow-BQf5EfNN.d.cts → workflow-D-2vp4Pq.d.cts} +265 -241
- package/dist/{workflow-BQf5EfNN.d.ts → workflow-D-2vp4Pq.d.ts} +265 -241
- package/dist/workflow.cjs +206 -253
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +2 -3
- package/dist/workflow.d.ts +2 -3
- package/dist/workflow.js +182 -231
- package/dist/workflow.js.map +1 -1
- package/package.json +3 -2
- package/src/activities.ts +1 -14
- package/src/index.ts +14 -11
- package/src/lib/session.ts +56 -99
- package/src/lib/thread-manager.ts +45 -37
- package/src/lib/tool-router.ts +143 -103
- package/src/lib/types.ts +32 -25
- package/src/tools/ask-user-question/handler.ts +5 -5
- package/src/tools/ask-user-question/tool.ts +3 -2
- package/src/tools/bash/bash.test.ts +12 -12
- package/src/tools/bash/handler.ts +5 -5
- package/src/tools/bash/tool.ts +3 -2
- package/src/tools/edit/handler.ts +78 -123
- package/src/tools/edit/tool.ts +3 -2
- package/src/tools/glob/handler.ts +17 -48
- package/src/tools/glob/tool.ts +3 -2
- package/src/tools/grep/tool.ts +3 -2
- package/src/tools/{read → read-file}/tool.ts +3 -2
- package/src/tools/task/handler.ts +2 -2
- package/src/tools/task/tool.ts +2 -9
- package/src/tools/task-create/handler.ts +5 -11
- package/src/tools/task-create/tool.ts +3 -2
- package/src/tools/task-get/handler.ts +5 -10
- package/src/tools/task-get/tool.ts +3 -2
- package/src/tools/task-list/handler.ts +5 -10
- package/src/tools/task-list/tool.ts +3 -2
- package/src/tools/task-update/handler.ts +5 -12
- package/src/tools/task-update/tool.ts +3 -2
- package/src/tools/{write → write-file}/tool.ts +5 -6
- package/src/workflow.ts +23 -19
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var workflow = require('@temporalio/workflow');
|
|
4
|
-
var
|
|
4
|
+
var z3 = require('zod');
|
|
5
5
|
var plugin = require('@temporalio/plugin');
|
|
6
6
|
var messages = require('@langchain/core/messages');
|
|
7
7
|
var crypto = require('crypto');
|
|
@@ -10,7 +10,7 @@ var justBash = require('just-bash');
|
|
|
10
10
|
|
|
11
11
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
12
|
|
|
13
|
-
var
|
|
13
|
+
var z3__default = /*#__PURE__*/_interopDefault(z3);
|
|
14
14
|
var crypto__default = /*#__PURE__*/_interopDefault(crypto);
|
|
15
15
|
|
|
16
16
|
// src/lib/session.ts
|
|
@@ -46,10 +46,10 @@ function createTaskTool(subagents) {
|
|
|
46
46
|
return {
|
|
47
47
|
name: TASK_TOOL,
|
|
48
48
|
description: buildTaskDescription(subagents),
|
|
49
|
-
schema:
|
|
50
|
-
subagent:
|
|
51
|
-
description:
|
|
52
|
-
prompt:
|
|
49
|
+
schema: z3__default.default.object({
|
|
50
|
+
subagent: z3__default.default.enum(names).describe("The type of subagent to launch"),
|
|
51
|
+
description: z3__default.default.string().describe("A short (3-5 word) description of the task"),
|
|
52
|
+
prompt: z3__default.default.string().describe("The task for the agent to perform")
|
|
53
53
|
})
|
|
54
54
|
};
|
|
55
55
|
}
|
|
@@ -84,107 +84,15 @@ function createTaskHandler(subagents) {
|
|
|
84
84
|
};
|
|
85
85
|
};
|
|
86
86
|
}
|
|
87
|
-
var createBashToolDescription = ({
|
|
88
|
-
fileTree
|
|
89
|
-
}) => `Execute shell commands in a bash environment.
|
|
90
|
-
|
|
91
|
-
Use this tool to:
|
|
92
|
-
- Run shell commands (ls, cat, grep, find, etc.)
|
|
93
|
-
- Execute scripts and chain commands with pipes (|) or logical operators (&&, ||)
|
|
94
|
-
- Inspect files and directories
|
|
95
|
-
|
|
96
|
-
Current file tree:
|
|
97
|
-
${fileTree}`;
|
|
98
|
-
var bashTool = {
|
|
99
|
-
name: "Bash",
|
|
100
|
-
description: `Execute shell commands in a sandboxed bash environment.
|
|
101
|
-
|
|
102
|
-
Use this tool to:
|
|
103
|
-
- Run shell commands (ls, cat, grep, find, etc.)
|
|
104
|
-
- Execute scripts and chain commands with pipes (|) or logical operators (&&, ||)
|
|
105
|
-
- Inspect files and directories
|
|
106
|
-
`,
|
|
107
|
-
schema: z5__default.default.object({
|
|
108
|
-
command: z5__default.default.string().describe(
|
|
109
|
-
"The bash command to execute. Can include pipes (|), redirects (>, >>), logical operators (&&, ||), and shell features like command substitution $(...)."
|
|
110
|
-
)
|
|
111
|
-
}),
|
|
112
|
-
strict: true
|
|
113
|
-
};
|
|
114
|
-
var taskCreateTool = {
|
|
115
|
-
name: "TaskCreate",
|
|
116
|
-
description: `Use this tool to create a structured task list for the control test. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
|
|
117
|
-
It also helps the user understand the progress of the task and overall progress of their requests.
|
|
118
|
-
|
|
119
|
-
## When to Use This Tool
|
|
120
|
-
|
|
121
|
-
Use this tool proactively in these scenarios:
|
|
122
|
-
|
|
123
|
-
- Complex multi-step tasks - When a task requires 3 or more distinct steps or actions
|
|
124
|
-
- Non-trivial and complex tasks - Tasks that require careful planning or multiple operations
|
|
125
|
-
- User explicitly requests todo list - When the user directly asks you to use the todo list
|
|
126
|
-
- User provides multiple tasks - When users provide a list of things to be done (numbered or comma-separated)
|
|
127
|
-
- After receiving new instructions - Immediately capture user requirements as tasks
|
|
128
|
-
- When you start working on a task - Mark it as in_progress BEFORE beginning work
|
|
129
|
-
- After completing a task - Mark it as completed and add any new follow-up tasks discovered during implementation
|
|
130
|
-
|
|
131
|
-
## When NOT to Use This Tool
|
|
132
|
-
|
|
133
|
-
Skip using this tool when:
|
|
134
|
-
- There is only a single, straightforward task
|
|
135
|
-
- The task is trivial and tracking it provides no organizational benefit
|
|
136
|
-
- The task can be completed in less than 3 trivial steps
|
|
137
|
-
- The task is purely conversational or informational
|
|
138
|
-
|
|
139
|
-
NOTE that you should not use this tool if there is only one trivial task to do. In this case you are better off just doing the task directly.
|
|
140
|
-
|
|
141
|
-
## Task Fields
|
|
142
|
-
|
|
143
|
-
- **subject**: A brief, actionable title in imperative form (e.g., "Fix authentication bug in login flow")
|
|
144
|
-
- **description**: Detailed description of what needs to be done, including context and acceptance criteria
|
|
145
|
-
- **activeForm**: Present continuous form shown in spinner when task is in_progress (e.g., "Fixing authentication bug"). This is displayed to the user while you work on the task.
|
|
146
|
-
|
|
147
|
-
**IMPORTANT**: Always provide activeForm when creating tasks. The subject should be imperative ("Run tests") while activeForm should be present continuous ("Running tests"). All tasks are created with status \`pending\`.
|
|
148
|
-
|
|
149
|
-
## Tips
|
|
150
|
-
|
|
151
|
-
- Create tasks with clear, specific subjects that describe the outcome
|
|
152
|
-
- Include enough detail in the description for another agent to understand and complete the task
|
|
153
|
-
- After creating tasks, use TaskUpdate to set up dependencies (blocks/blockedBy) if needed
|
|
154
|
-
- Check TaskList first to avoid creating duplicate tasks`,
|
|
155
|
-
schema: z5__default.default.object({
|
|
156
|
-
subject: z5__default.default.string().describe(
|
|
157
|
-
'A brief, actionable title in imperative form (e.g., "Fix authentication bug in login flow")'
|
|
158
|
-
),
|
|
159
|
-
description: z5__default.default.string().describe(
|
|
160
|
-
"Detailed description of what needs to be done, including context and acceptance criteria"
|
|
161
|
-
),
|
|
162
|
-
activeForm: z5__default.default.string().describe(
|
|
163
|
-
'Present continuous form shown in spinner when task is in_progress (e.g., "Fixing authentication bug"). This is displayed to the user while you work on the task.'
|
|
164
|
-
),
|
|
165
|
-
metadata: z5__default.default.record(z5__default.default.string(), z5__default.default.string()).describe("Arbitrary key-value pairs for tracking")
|
|
166
|
-
})
|
|
167
|
-
};
|
|
168
87
|
|
|
169
88
|
// src/lib/tool-router.ts
|
|
170
|
-
var buildIntoolDefinitions = {
|
|
171
|
-
[bashTool.name]: bashTool,
|
|
172
|
-
[taskCreateTool.name]: taskCreateTool
|
|
173
|
-
};
|
|
174
89
|
function createToolRouter(options) {
|
|
175
|
-
const { appendToolResult } =
|
|
176
|
-
startToCloseTimeout: "2m",
|
|
177
|
-
retry: {
|
|
178
|
-
maximumAttempts: 3,
|
|
179
|
-
initialInterval: "5s",
|
|
180
|
-
maximumInterval: "15m",
|
|
181
|
-
backoffCoefficient: 4
|
|
182
|
-
}
|
|
183
|
-
});
|
|
90
|
+
const { appendToolResult } = options;
|
|
184
91
|
const toolMap = /* @__PURE__ */ new Map();
|
|
185
92
|
for (const [_key, tool] of Object.entries(options.tools)) {
|
|
186
93
|
toolMap.set(tool.name, tool);
|
|
187
94
|
}
|
|
95
|
+
const isEnabled = (tool) => tool.enabled !== false;
|
|
188
96
|
if (options.subagents) {
|
|
189
97
|
const subagentHooksMap = /* @__PURE__ */ new Map();
|
|
190
98
|
for (const s of options.subagents) {
|
|
@@ -212,24 +120,6 @@ function createToolRouter(options) {
|
|
|
212
120
|
}
|
|
213
121
|
});
|
|
214
122
|
}
|
|
215
|
-
if (options.buildInTools) {
|
|
216
|
-
for (const [key, value] of Object.entries(options.buildInTools)) {
|
|
217
|
-
if (key === bashTool.name) {
|
|
218
|
-
toolMap.set(key, {
|
|
219
|
-
...buildIntoolDefinitions[key],
|
|
220
|
-
description: createBashToolDescription({
|
|
221
|
-
fileTree: options.fileTree
|
|
222
|
-
}),
|
|
223
|
-
handler: value
|
|
224
|
-
});
|
|
225
|
-
} else {
|
|
226
|
-
toolMap.set(key, {
|
|
227
|
-
...buildIntoolDefinitions[key],
|
|
228
|
-
handler: value
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
123
|
async function processToolCall(toolCall, turn, handlerContext) {
|
|
234
124
|
const startTime = Date.now();
|
|
235
125
|
const tool = toolMap.get(toolCall.name);
|
|
@@ -245,6 +135,7 @@ function createToolRouter(options) {
|
|
|
245
135
|
await appendToolResult({
|
|
246
136
|
threadId: options.threadId,
|
|
247
137
|
toolCallId: toolCall.id,
|
|
138
|
+
toolName: toolCall.name,
|
|
248
139
|
content: JSON.stringify({
|
|
249
140
|
skipped: true,
|
|
250
141
|
reason: "Skipped by PreToolUse hook"
|
|
@@ -266,6 +157,7 @@ function createToolRouter(options) {
|
|
|
266
157
|
await appendToolResult({
|
|
267
158
|
threadId: options.threadId,
|
|
268
159
|
toolCallId: toolCall.id,
|
|
160
|
+
toolName: toolCall.name,
|
|
269
161
|
content: JSON.stringify({
|
|
270
162
|
skipped: true,
|
|
271
163
|
reason: "Skipped by tool PreToolUse hook"
|
|
@@ -279,14 +171,22 @@ function createToolRouter(options) {
|
|
|
279
171
|
}
|
|
280
172
|
let result;
|
|
281
173
|
let content;
|
|
174
|
+
let resultAppended = false;
|
|
282
175
|
try {
|
|
283
176
|
if (tool) {
|
|
177
|
+
const enrichedContext = {
|
|
178
|
+
...handlerContext ?? {},
|
|
179
|
+
threadId: options.threadId,
|
|
180
|
+
toolCallId: toolCall.id,
|
|
181
|
+
toolName: toolCall.name
|
|
182
|
+
};
|
|
284
183
|
const response = await tool.handler(
|
|
285
184
|
effectiveArgs,
|
|
286
|
-
|
|
185
|
+
enrichedContext
|
|
287
186
|
);
|
|
288
187
|
result = response.data;
|
|
289
188
|
content = response.toolResponse;
|
|
189
|
+
resultAppended = response.resultAppended === true;
|
|
290
190
|
} else {
|
|
291
191
|
result = { error: `Unknown tool: ${toolCall.name}` };
|
|
292
192
|
content = JSON.stringify(result, null, 2);
|
|
@@ -332,11 +232,14 @@ function createToolRouter(options) {
|
|
|
332
232
|
throw error;
|
|
333
233
|
}
|
|
334
234
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
235
|
+
if (!resultAppended) {
|
|
236
|
+
await appendToolResult({
|
|
237
|
+
threadId: options.threadId,
|
|
238
|
+
toolCallId: toolCall.id,
|
|
239
|
+
toolName: toolCall.name,
|
|
240
|
+
content
|
|
241
|
+
});
|
|
242
|
+
}
|
|
340
243
|
const toolResult = {
|
|
341
244
|
toolCallId: toolCall.id,
|
|
342
245
|
name: toolCall.name,
|
|
@@ -366,11 +269,11 @@ function createToolRouter(options) {
|
|
|
366
269
|
return {
|
|
367
270
|
// --- Methods from registry ---
|
|
368
271
|
hasTools() {
|
|
369
|
-
return toolMap.
|
|
272
|
+
return Array.from(toolMap.values()).some(isEnabled);
|
|
370
273
|
},
|
|
371
274
|
parseToolCall(toolCall) {
|
|
372
275
|
const tool = toolMap.get(toolCall.name);
|
|
373
|
-
if (!tool) {
|
|
276
|
+
if (!tool || !isEnabled(tool)) {
|
|
374
277
|
throw new Error(`Tool ${toolCall.name} not found`);
|
|
375
278
|
}
|
|
376
279
|
const parsedArgs = tool.schema.parse(toolCall.args);
|
|
@@ -381,13 +284,14 @@ function createToolRouter(options) {
|
|
|
381
284
|
};
|
|
382
285
|
},
|
|
383
286
|
hasTool(name) {
|
|
384
|
-
|
|
287
|
+
const tool = toolMap.get(name);
|
|
288
|
+
return tool !== void 0 && isEnabled(tool);
|
|
385
289
|
},
|
|
386
290
|
getToolNames() {
|
|
387
|
-
return Array.from(toolMap.
|
|
291
|
+
return Array.from(toolMap.entries()).filter(([, tool]) => isEnabled(tool)).map(([name]) => name);
|
|
388
292
|
},
|
|
389
293
|
getToolDefinitions() {
|
|
390
|
-
return Array.from(toolMap).map(([name, tool]) => ({
|
|
294
|
+
return Array.from(toolMap).filter(([, tool]) => isEnabled(tool)).map(([name, tool]) => ({
|
|
391
295
|
name,
|
|
392
296
|
description: tool.description,
|
|
393
297
|
schema: tool.schema,
|
|
@@ -426,19 +330,28 @@ function createToolRouter(options) {
|
|
|
426
330
|
}
|
|
427
331
|
const handlerContext = context?.handlerContext ?? {};
|
|
428
332
|
const processOne = async (toolCall) => {
|
|
333
|
+
const enrichedContext = {
|
|
334
|
+
...handlerContext ?? {},
|
|
335
|
+
threadId: options.threadId,
|
|
336
|
+
toolCallId: toolCall.id,
|
|
337
|
+
toolName: toolCall.name
|
|
338
|
+
};
|
|
429
339
|
const response = await handler(
|
|
430
340
|
toolCall.args,
|
|
431
|
-
|
|
341
|
+
enrichedContext
|
|
432
342
|
);
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
343
|
+
if (!response.resultAppended) {
|
|
344
|
+
await appendToolResult({
|
|
345
|
+
threadId: options.threadId,
|
|
346
|
+
toolCallId: toolCall.id,
|
|
347
|
+
toolName: toolCall.name,
|
|
348
|
+
content: response.toolResponse
|
|
349
|
+
});
|
|
350
|
+
}
|
|
438
351
|
return {
|
|
439
352
|
toolCallId: toolCall.id,
|
|
440
353
|
name: toolCall.name,
|
|
441
|
-
data: response.data
|
|
354
|
+
data: response.data
|
|
442
355
|
};
|
|
443
356
|
};
|
|
444
357
|
if (options.parallel) {
|
|
@@ -464,6 +377,21 @@ function createToolRouter(options) {
|
|
|
464
377
|
}
|
|
465
378
|
};
|
|
466
379
|
}
|
|
380
|
+
function withAutoAppend(threadHandler, handler) {
|
|
381
|
+
return async (args, context) => {
|
|
382
|
+
const response = await handler(args, context);
|
|
383
|
+
const threadId = context.threadId;
|
|
384
|
+
const toolCallId = context.toolCallId;
|
|
385
|
+
const toolName = context.toolName;
|
|
386
|
+
await threadHandler({
|
|
387
|
+
threadId,
|
|
388
|
+
toolCallId,
|
|
389
|
+
toolName,
|
|
390
|
+
content: response.toolResponse
|
|
391
|
+
});
|
|
392
|
+
return { toolResponse: "", data: response.data, resultAppended: true };
|
|
393
|
+
};
|
|
394
|
+
}
|
|
467
395
|
function defineTool(tool) {
|
|
468
396
|
return tool;
|
|
469
397
|
}
|
|
@@ -475,51 +403,24 @@ function hasNoOtherToolCalls(toolCalls, excludeName) {
|
|
|
475
403
|
}
|
|
476
404
|
|
|
477
405
|
// src/lib/session.ts
|
|
478
|
-
async function resolvePrompt(prompt) {
|
|
479
|
-
if (typeof prompt === "function") {
|
|
480
|
-
return prompt();
|
|
481
|
-
}
|
|
482
|
-
return prompt;
|
|
483
|
-
}
|
|
484
406
|
var createSession = async ({
|
|
485
407
|
threadId,
|
|
486
408
|
agentName,
|
|
487
409
|
maxTurns = 50,
|
|
488
410
|
metadata = {},
|
|
489
411
|
runAgent,
|
|
490
|
-
|
|
491
|
-
instructionsPrompt,
|
|
412
|
+
threadOps,
|
|
492
413
|
buildContextMessage,
|
|
493
|
-
buildFileTree = async () => "",
|
|
494
414
|
subagents,
|
|
495
415
|
tools = {},
|
|
496
416
|
processToolsInParallel = true,
|
|
497
|
-
buildInTools = {},
|
|
498
417
|
hooks = {}
|
|
499
418
|
}) => {
|
|
500
|
-
const {
|
|
501
|
-
initializeThread,
|
|
502
|
-
appendHumanMessage,
|
|
503
|
-
parseToolCalls,
|
|
504
|
-
appendToolResult,
|
|
505
|
-
appendSystemMessage
|
|
506
|
-
} = workflow.proxyActivities({
|
|
507
|
-
startToCloseTimeout: "30m",
|
|
508
|
-
retry: {
|
|
509
|
-
maximumAttempts: 6,
|
|
510
|
-
initialInterval: "5s",
|
|
511
|
-
maximumInterval: "15m",
|
|
512
|
-
backoffCoefficient: 4
|
|
513
|
-
},
|
|
514
|
-
heartbeatTimeout: "5m"
|
|
515
|
-
});
|
|
516
|
-
const fileTree = await buildFileTree();
|
|
517
419
|
const toolRouter = createToolRouter({
|
|
518
420
|
tools,
|
|
421
|
+
appendToolResult: threadOps.appendToolResult,
|
|
519
422
|
threadId,
|
|
520
423
|
hooks,
|
|
521
|
-
buildInTools,
|
|
522
|
-
fileTree,
|
|
523
424
|
subagents,
|
|
524
425
|
parallel: processToolsInParallel
|
|
525
426
|
});
|
|
@@ -544,15 +445,8 @@ var createSession = async ({
|
|
|
544
445
|
});
|
|
545
446
|
}
|
|
546
447
|
stateManager.setTools(toolRouter.getToolDefinitions());
|
|
547
|
-
await initializeThread(threadId);
|
|
548
|
-
await
|
|
549
|
-
threadId,
|
|
550
|
-
[
|
|
551
|
-
await resolvePrompt(baseSystemPrompt),
|
|
552
|
-
await resolvePrompt(instructionsPrompt)
|
|
553
|
-
].join("\n")
|
|
554
|
-
);
|
|
555
|
-
await appendHumanMessage(threadId, await buildContextMessage());
|
|
448
|
+
await threadOps.initializeThread(threadId);
|
|
449
|
+
await threadOps.appendHumanMessage(threadId, await buildContextMessage());
|
|
556
450
|
let exitReason = "completed";
|
|
557
451
|
try {
|
|
558
452
|
while (stateManager.isRunning() && !stateManager.isTerminal() && stateManager.getTurns() < maxTurns) {
|
|
@@ -573,54 +467,25 @@ var createSession = async ({
|
|
|
573
467
|
exitReason = "completed";
|
|
574
468
|
return message;
|
|
575
469
|
}
|
|
576
|
-
const rawToolCalls = await parseToolCalls(message);
|
|
470
|
+
const rawToolCalls = await threadOps.parseToolCalls(message);
|
|
577
471
|
const parsedToolCalls = [];
|
|
578
|
-
for (const tc of rawToolCalls
|
|
579
|
-
(tc2) => tc2.name !== "Task"
|
|
580
|
-
)) {
|
|
472
|
+
for (const tc of rawToolCalls) {
|
|
581
473
|
try {
|
|
582
474
|
parsedToolCalls.push(toolRouter.parseToolCall(tc));
|
|
583
475
|
} catch (error) {
|
|
584
|
-
await appendToolResult({
|
|
476
|
+
await threadOps.appendToolResult({
|
|
585
477
|
threadId,
|
|
586
478
|
toolCallId: tc.id ?? "",
|
|
479
|
+
toolName: tc.name,
|
|
587
480
|
content: JSON.stringify({
|
|
588
481
|
error: `Invalid tool call for "${tc.name}": ${error instanceof Error ? error.message : String(error)}`
|
|
589
482
|
})
|
|
590
483
|
});
|
|
591
484
|
}
|
|
592
485
|
}
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
(tc2) => tc2.name === "Task"
|
|
597
|
-
)) {
|
|
598
|
-
try {
|
|
599
|
-
const parsedArgs = createTaskTool(subagents).schema.parse(
|
|
600
|
-
tc.args
|
|
601
|
-
);
|
|
602
|
-
taskToolCalls.push({
|
|
603
|
-
id: tc.id ?? "",
|
|
604
|
-
name: tc.name,
|
|
605
|
-
args: parsedArgs
|
|
606
|
-
});
|
|
607
|
-
} catch (error) {
|
|
608
|
-
await appendToolResult({
|
|
609
|
-
threadId,
|
|
610
|
-
toolCallId: tc.id ?? "",
|
|
611
|
-
content: JSON.stringify({
|
|
612
|
-
error: `Invalid tool call for "Task": ${error instanceof Error ? error.message : String(error)}`
|
|
613
|
-
})
|
|
614
|
-
});
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
await toolRouter.processToolCalls(
|
|
619
|
-
[...parsedToolCalls, ...taskToolCalls],
|
|
620
|
-
{
|
|
621
|
-
turn: currentTurn
|
|
622
|
-
}
|
|
623
|
-
);
|
|
486
|
+
await toolRouter.processToolCalls(parsedToolCalls, {
|
|
487
|
+
turn: currentTurn
|
|
488
|
+
});
|
|
624
489
|
if (stateManager.getStatus() === "WAITING_FOR_INPUT") {
|
|
625
490
|
exitReason = "waiting_for_input";
|
|
626
491
|
break;
|
|
@@ -639,6 +504,26 @@ var createSession = async ({
|
|
|
639
504
|
}
|
|
640
505
|
};
|
|
641
506
|
};
|
|
507
|
+
function proxyDefaultThreadOps(options) {
|
|
508
|
+
const activities = workflow.proxyActivities(
|
|
509
|
+
options ?? {
|
|
510
|
+
startToCloseTimeout: "30m",
|
|
511
|
+
retry: {
|
|
512
|
+
maximumAttempts: 6,
|
|
513
|
+
initialInterval: "5s",
|
|
514
|
+
maximumInterval: "15m",
|
|
515
|
+
backoffCoefficient: 4
|
|
516
|
+
},
|
|
517
|
+
heartbeatTimeout: "5m"
|
|
518
|
+
}
|
|
519
|
+
);
|
|
520
|
+
return {
|
|
521
|
+
initializeThread: activities.initializeThread,
|
|
522
|
+
appendHumanMessage: activities.appendHumanMessage,
|
|
523
|
+
appendToolResult: activities.appendToolResult,
|
|
524
|
+
parseToolCalls: activities.parseToolCalls
|
|
525
|
+
};
|
|
526
|
+
}
|
|
642
527
|
|
|
643
528
|
// src/lib/types.ts
|
|
644
529
|
function isTerminalStatus(status) {
|
|
@@ -741,7 +626,7 @@ function createAgentStateManager(initialState) {
|
|
|
741
626
|
tools = newTools.map((tool) => ({
|
|
742
627
|
name: tool.name,
|
|
743
628
|
description: tool.description,
|
|
744
|
-
schema:
|
|
629
|
+
schema: z3.z.toJSONSchema(tool.schema),
|
|
745
630
|
strict: tool.strict,
|
|
746
631
|
max_uses: tool.max_uses
|
|
747
632
|
}));
|
|
@@ -775,18 +660,18 @@ Usage notes:
|
|
|
775
660
|
* Use multiSelect: true to allow multiple answers to be selected for a question
|
|
776
661
|
* If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label
|
|
777
662
|
`,
|
|
778
|
-
schema:
|
|
779
|
-
questions:
|
|
780
|
-
|
|
781
|
-
question:
|
|
782
|
-
header:
|
|
783
|
-
options:
|
|
784
|
-
|
|
785
|
-
label:
|
|
786
|
-
description:
|
|
663
|
+
schema: z3__default.default.object({
|
|
664
|
+
questions: z3__default.default.array(
|
|
665
|
+
z3__default.default.object({
|
|
666
|
+
question: z3__default.default.string().describe("The full question text to display"),
|
|
667
|
+
header: z3__default.default.string().describe("Short label for the question (max 12 characters)"),
|
|
668
|
+
options: z3__default.default.array(
|
|
669
|
+
z3__default.default.object({
|
|
670
|
+
label: z3__default.default.string(),
|
|
671
|
+
description: z3__default.default.string()
|
|
787
672
|
})
|
|
788
673
|
).min(0).max(4).describe("Array of 0-4 choices, each with label and description"),
|
|
789
|
-
multiSelect:
|
|
674
|
+
multiSelect: z3__default.default.boolean().describe("If true, users can select multiple options")
|
|
790
675
|
})
|
|
791
676
|
)
|
|
792
677
|
}),
|
|
@@ -806,9 +691,9 @@ Examples:
|
|
|
806
691
|
- "**/*.test.ts" - Find all test files recursively
|
|
807
692
|
- "src/**/*.ts" - Find all TypeScript files in src directory
|
|
808
693
|
`,
|
|
809
|
-
schema:
|
|
810
|
-
pattern:
|
|
811
|
-
root:
|
|
694
|
+
schema: z3.z.object({
|
|
695
|
+
pattern: z3.z.string().describe("Glob pattern to match files against"),
|
|
696
|
+
root: z3.z.string().optional().describe("Optional root directory to search from")
|
|
812
697
|
}),
|
|
813
698
|
strict: true
|
|
814
699
|
};
|
|
@@ -826,13 +711,13 @@ Examples:
|
|
|
826
711
|
- Search for function definitions with "function.*handleClick"
|
|
827
712
|
- Search case-insensitively with ignoreCase: true
|
|
828
713
|
`,
|
|
829
|
-
schema:
|
|
830
|
-
pattern:
|
|
831
|
-
ignoreCase:
|
|
832
|
-
maxMatches:
|
|
833
|
-
includePatterns:
|
|
834
|
-
excludePatterns:
|
|
835
|
-
contextLines:
|
|
714
|
+
schema: z3.z.object({
|
|
715
|
+
pattern: z3.z.string().describe("Regex pattern to search for in file contents"),
|
|
716
|
+
ignoreCase: z3.z.boolean().optional().describe("Case-insensitive search (default: false)"),
|
|
717
|
+
maxMatches: z3.z.number().optional().describe("Maximum number of matches to return (default: 50)"),
|
|
718
|
+
includePatterns: z3.z.array(z3.z.string()).optional().describe("Glob patterns to include (e.g., ['*.ts', '*.js'])"),
|
|
719
|
+
excludePatterns: z3.z.array(z3.z.string()).optional().describe("Glob patterns to exclude (e.g., ['*.test.ts'])"),
|
|
720
|
+
contextLines: z3.z.number().optional().describe("Number of context lines to show around matches")
|
|
836
721
|
}),
|
|
837
722
|
strict: true
|
|
838
723
|
};
|
|
@@ -850,12 +735,12 @@ The tool returns the file content in an appropriate format:
|
|
|
850
735
|
- Images: Base64-encoded image data
|
|
851
736
|
- PDFs: Extracted text content
|
|
852
737
|
`,
|
|
853
|
-
schema:
|
|
854
|
-
path:
|
|
855
|
-
offset:
|
|
738
|
+
schema: z3.z.object({
|
|
739
|
+
path: z3.z.string().describe("Virtual path to the file to read"),
|
|
740
|
+
offset: z3.z.number().optional().describe(
|
|
856
741
|
"Line number to start reading from (1-indexed, for text files)"
|
|
857
742
|
),
|
|
858
|
-
limit:
|
|
743
|
+
limit: z3.z.number().optional().describe("Maximum number of lines to read (for text files)")
|
|
859
744
|
}),
|
|
860
745
|
strict: true
|
|
861
746
|
};
|
|
@@ -864,7 +749,7 @@ var writeTool = {
|
|
|
864
749
|
description: `Create or overwrite a file with new content.
|
|
865
750
|
|
|
866
751
|
Usage:
|
|
867
|
-
- Provide the absolute
|
|
752
|
+
- Provide the absolute path to the file
|
|
868
753
|
- The file will be created if it doesn't exist
|
|
869
754
|
- If the file exists, it will be completely overwritten
|
|
870
755
|
|
|
@@ -873,9 +758,9 @@ IMPORTANT:
|
|
|
873
758
|
- This is an atomic write operation - the entire file is replaced
|
|
874
759
|
- Path must be absolute (e.g., "/docs/readme.md", not "docs/readme.md")
|
|
875
760
|
`,
|
|
876
|
-
schema:
|
|
877
|
-
file_path:
|
|
878
|
-
content:
|
|
761
|
+
schema: z3.z.object({
|
|
762
|
+
file_path: z3.z.string().describe("The absolute path to the file to write"),
|
|
763
|
+
content: z3.z.string().describe("The content to write to the file")
|
|
879
764
|
}),
|
|
880
765
|
strict: true
|
|
881
766
|
};
|
|
@@ -895,18 +780,72 @@ IMPORTANT:
|
|
|
895
780
|
- The operation fails if old_string is not found
|
|
896
781
|
- old_string and new_string must be different
|
|
897
782
|
`,
|
|
898
|
-
schema:
|
|
899
|
-
file_path:
|
|
900
|
-
old_string:
|
|
901
|
-
new_string:
|
|
783
|
+
schema: z3.z.object({
|
|
784
|
+
file_path: z3.z.string().describe("The absolute virtual path to the file to modify"),
|
|
785
|
+
old_string: z3.z.string().describe("The exact text to replace"),
|
|
786
|
+
new_string: z3.z.string().describe(
|
|
902
787
|
"The text to replace it with (must be different from old_string)"
|
|
903
788
|
),
|
|
904
|
-
replace_all:
|
|
789
|
+
replace_all: z3.z.boolean().optional().describe(
|
|
905
790
|
"If true, replace all occurrences of old_string (default: false)"
|
|
906
791
|
)
|
|
907
792
|
}),
|
|
908
793
|
strict: true
|
|
909
794
|
};
|
|
795
|
+
var taskCreateTool = {
|
|
796
|
+
name: "TaskCreate",
|
|
797
|
+
description: `Use this tool to create a structured task list for the control test. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
|
|
798
|
+
It also helps the user understand the progress of the task and overall progress of their requests.
|
|
799
|
+
|
|
800
|
+
## When to Use This Tool
|
|
801
|
+
|
|
802
|
+
Use this tool proactively in these scenarios:
|
|
803
|
+
|
|
804
|
+
- Complex multi-step tasks - When a task requires 3 or more distinct steps or actions
|
|
805
|
+
- Non-trivial and complex tasks - Tasks that require careful planning or multiple operations
|
|
806
|
+
- User explicitly requests todo list - When the user directly asks you to use the todo list
|
|
807
|
+
- User provides multiple tasks - When users provide a list of things to be done (numbered or comma-separated)
|
|
808
|
+
- After receiving new instructions - Immediately capture user requirements as tasks
|
|
809
|
+
- When you start working on a task - Mark it as in_progress BEFORE beginning work
|
|
810
|
+
- After completing a task - Mark it as completed and add any new follow-up tasks discovered during implementation
|
|
811
|
+
|
|
812
|
+
## When NOT to Use This Tool
|
|
813
|
+
|
|
814
|
+
Skip using this tool when:
|
|
815
|
+
- There is only a single, straightforward task
|
|
816
|
+
- The task is trivial and tracking it provides no organizational benefit
|
|
817
|
+
- The task can be completed in less than 3 trivial steps
|
|
818
|
+
- The task is purely conversational or informational
|
|
819
|
+
|
|
820
|
+
NOTE that you should not use this tool if there is only one trivial task to do. In this case you are better off just doing the task directly.
|
|
821
|
+
|
|
822
|
+
## Task Fields
|
|
823
|
+
|
|
824
|
+
- **subject**: A brief, actionable title in imperative form (e.g., "Fix authentication bug in login flow")
|
|
825
|
+
- **description**: Detailed description of what needs to be done, including context and acceptance criteria
|
|
826
|
+
- **activeForm**: Present continuous form shown in spinner when task is in_progress (e.g., "Fixing authentication bug"). This is displayed to the user while you work on the task.
|
|
827
|
+
|
|
828
|
+
**IMPORTANT**: Always provide activeForm when creating tasks. The subject should be imperative ("Run tests") while activeForm should be present continuous ("Running tests"). All tasks are created with status \`pending\`.
|
|
829
|
+
|
|
830
|
+
## Tips
|
|
831
|
+
|
|
832
|
+
- Create tasks with clear, specific subjects that describe the outcome
|
|
833
|
+
- Include enough detail in the description for another agent to understand and complete the task
|
|
834
|
+
- After creating tasks, use TaskUpdate to set up dependencies (blocks/blockedBy) if needed
|
|
835
|
+
- Check TaskList first to avoid creating duplicate tasks`,
|
|
836
|
+
schema: z3__default.default.object({
|
|
837
|
+
subject: z3__default.default.string().describe(
|
|
838
|
+
'A brief, actionable title in imperative form (e.g., "Fix authentication bug in login flow")'
|
|
839
|
+
),
|
|
840
|
+
description: z3__default.default.string().describe(
|
|
841
|
+
"Detailed description of what needs to be done, including context and acceptance criteria"
|
|
842
|
+
),
|
|
843
|
+
activeForm: z3__default.default.string().describe(
|
|
844
|
+
'Present continuous form shown in spinner when task is in_progress (e.g., "Fixing authentication bug"). This is displayed to the user while you work on the task.'
|
|
845
|
+
),
|
|
846
|
+
metadata: z3__default.default.record(z3__default.default.string(), z3__default.default.string()).describe("Arbitrary key-value pairs for tracking")
|
|
847
|
+
})
|
|
848
|
+
};
|
|
910
849
|
function createTaskCreateHandler(stateManager) {
|
|
911
850
|
return (args) => {
|
|
912
851
|
const task = {
|
|
@@ -929,8 +868,8 @@ function createTaskCreateHandler(stateManager) {
|
|
|
929
868
|
var taskGetTool = {
|
|
930
869
|
name: "TaskGet",
|
|
931
870
|
description: `Retrieve full task details including dependencies.`,
|
|
932
|
-
schema:
|
|
933
|
-
taskId:
|
|
871
|
+
schema: z3__default.default.object({
|
|
872
|
+
taskId: z3__default.default.string().describe("The ID of the task to get")
|
|
934
873
|
})
|
|
935
874
|
};
|
|
936
875
|
|
|
@@ -953,12 +892,12 @@ function createTaskGetHandler(stateManager) {
|
|
|
953
892
|
var taskListTool = {
|
|
954
893
|
name: "TaskList",
|
|
955
894
|
description: `List all tasks with current state.`,
|
|
956
|
-
schema:
|
|
895
|
+
schema: z3__default.default.object({})
|
|
957
896
|
};
|
|
958
897
|
|
|
959
898
|
// src/tools/task-list/handler.ts
|
|
960
899
|
function createTaskListHandler(stateManager) {
|
|
961
|
-
return (
|
|
900
|
+
return () => {
|
|
962
901
|
const taskList = stateManager.getTasks();
|
|
963
902
|
return {
|
|
964
903
|
toolResponse: JSON.stringify(taskList, null, 2),
|
|
@@ -969,11 +908,11 @@ function createTaskListHandler(stateManager) {
|
|
|
969
908
|
var taskUpdateTool = {
|
|
970
909
|
name: "TaskUpdate",
|
|
971
910
|
description: `Update status, add blockers, modify details.`,
|
|
972
|
-
schema:
|
|
973
|
-
taskId:
|
|
974
|
-
status:
|
|
975
|
-
addBlockedBy:
|
|
976
|
-
addBlocks:
|
|
911
|
+
schema: z3__default.default.object({
|
|
912
|
+
taskId: z3__default.default.string().describe("The ID of the task to get"),
|
|
913
|
+
status: z3__default.default.enum(["pending", "in_progress", "completed"]).describe("The status of the task"),
|
|
914
|
+
addBlockedBy: z3__default.default.array(z3__default.default.string()).describe("The IDs of the tasks that are blocking this task"),
|
|
915
|
+
addBlocks: z3__default.default.array(z3__default.default.string()).describe("The IDs of the tasks that this task is blocking")
|
|
977
916
|
})
|
|
978
917
|
};
|
|
979
918
|
|
|
@@ -1021,6 +960,33 @@ function createTaskUpdateHandler(stateManager) {
|
|
|
1021
960
|
};
|
|
1022
961
|
};
|
|
1023
962
|
}
|
|
963
|
+
var createBashToolDescription = ({
|
|
964
|
+
fileTree
|
|
965
|
+
}) => `Execute shell commands in a bash environment.
|
|
966
|
+
|
|
967
|
+
Use this tool to:
|
|
968
|
+
- Run shell commands (ls, cat, grep, find, etc.)
|
|
969
|
+
- Execute scripts and chain commands with pipes (|) or logical operators (&&, ||)
|
|
970
|
+
- Inspect files and directories
|
|
971
|
+
|
|
972
|
+
Current file tree:
|
|
973
|
+
${fileTree}`;
|
|
974
|
+
var bashTool = {
|
|
975
|
+
name: "Bash",
|
|
976
|
+
description: `Execute shell commands in a sandboxed bash environment.
|
|
977
|
+
|
|
978
|
+
Use this tool to:
|
|
979
|
+
- Run shell commands (ls, cat, grep, find, etc.)
|
|
980
|
+
- Execute scripts and chain commands with pipes (|) or logical operators (&&, ||)
|
|
981
|
+
- Inspect files and directories
|
|
982
|
+
`,
|
|
983
|
+
schema: z3__default.default.object({
|
|
984
|
+
command: z3__default.default.string().describe(
|
|
985
|
+
"The bash command to execute. Can include pipes (|), redirects (>, >>), logical operators (&&, ||), and shell features like command substitution $(...)."
|
|
986
|
+
)
|
|
987
|
+
}),
|
|
988
|
+
strict: true
|
|
989
|
+
};
|
|
1024
990
|
|
|
1025
991
|
// node_modules/uuid/dist/esm-node/stringify.js
|
|
1026
992
|
var byteToHex = [];
|
|
@@ -1069,25 +1035,33 @@ function getThreadKey(threadId, key) {
|
|
|
1069
1035
|
return `thread:${threadId}:${key}`;
|
|
1070
1036
|
}
|
|
1071
1037
|
function createThreadManager(config) {
|
|
1072
|
-
const {
|
|
1038
|
+
const {
|
|
1039
|
+
redis,
|
|
1040
|
+
threadId,
|
|
1041
|
+
key = "messages",
|
|
1042
|
+
serialize = (m) => JSON.stringify(m),
|
|
1043
|
+
deserialize = (raw) => JSON.parse(raw)
|
|
1044
|
+
} = config;
|
|
1073
1045
|
const redisKey = getThreadKey(threadId, key);
|
|
1074
|
-
|
|
1046
|
+
const base = {
|
|
1075
1047
|
async initialize() {
|
|
1076
1048
|
await redis.del(redisKey);
|
|
1077
1049
|
},
|
|
1078
1050
|
async load() {
|
|
1079
1051
|
const data = await redis.lrange(redisKey, 0, -1);
|
|
1080
|
-
return data.map(
|
|
1052
|
+
return data.map(deserialize);
|
|
1081
1053
|
},
|
|
1082
1054
|
async append(messages) {
|
|
1083
1055
|
if (messages.length > 0) {
|
|
1084
|
-
await redis.rpush(redisKey, ...messages.map(
|
|
1056
|
+
await redis.rpush(redisKey, ...messages.map(serialize));
|
|
1085
1057
|
await redis.expire(redisKey, THREAD_TTL_SECONDS);
|
|
1086
1058
|
}
|
|
1087
1059
|
},
|
|
1088
1060
|
async delete() {
|
|
1089
1061
|
await redis.del(redisKey);
|
|
1090
|
-
}
|
|
1062
|
+
}
|
|
1063
|
+
};
|
|
1064
|
+
const helpers = {
|
|
1091
1065
|
createHumanMessage(content) {
|
|
1092
1066
|
return new messages.HumanMessage({
|
|
1093
1067
|
id: v4_default(),
|
|
@@ -1107,40 +1081,27 @@ function createThreadManager(config) {
|
|
|
1107
1081
|
},
|
|
1108
1082
|
createToolMessage(content, toolCallId) {
|
|
1109
1083
|
return new messages.ToolMessage({
|
|
1110
|
-
// Cast needed due to langchain type compatibility
|
|
1111
1084
|
content,
|
|
1112
1085
|
tool_call_id: toolCallId
|
|
1113
1086
|
}).toDict();
|
|
1114
1087
|
},
|
|
1115
|
-
createSystemMessage(content) {
|
|
1116
|
-
return new messages.SystemMessage({
|
|
1117
|
-
content
|
|
1118
|
-
}).toDict();
|
|
1119
|
-
},
|
|
1120
|
-
async appendSystemMessage(content) {
|
|
1121
|
-
const message = this.createSystemMessage(content);
|
|
1122
|
-
await this.append([message]);
|
|
1123
|
-
},
|
|
1124
1088
|
async appendHumanMessage(content) {
|
|
1125
|
-
const message =
|
|
1126
|
-
await
|
|
1089
|
+
const message = helpers.createHumanMessage(content);
|
|
1090
|
+
await base.append([message]);
|
|
1127
1091
|
},
|
|
1128
1092
|
async appendToolMessage(content, toolCallId) {
|
|
1129
|
-
const message =
|
|
1130
|
-
await
|
|
1093
|
+
const message = helpers.createToolMessage(content, toolCallId);
|
|
1094
|
+
await base.append([message]);
|
|
1131
1095
|
},
|
|
1132
1096
|
async appendAIMessage(content) {
|
|
1133
|
-
const message =
|
|
1134
|
-
await
|
|
1097
|
+
const message = helpers.createAIMessage(content);
|
|
1098
|
+
await base.append([message]);
|
|
1135
1099
|
}
|
|
1136
1100
|
};
|
|
1101
|
+
return Object.assign(base, helpers);
|
|
1137
1102
|
}
|
|
1138
1103
|
function createSharedActivities(redis) {
|
|
1139
1104
|
return {
|
|
1140
|
-
async appendSystemMessage(threadId, content) {
|
|
1141
|
-
const thread = createThreadManager({ redis, threadId });
|
|
1142
|
-
await thread.appendSystemMessage(content);
|
|
1143
|
-
},
|
|
1144
1105
|
async appendToolResult(config) {
|
|
1145
1106
|
const { threadId, toolCallId, content } = config;
|
|
1146
1107
|
const thread = createThreadManager({ redis, threadId });
|
|
@@ -1213,7 +1174,7 @@ async function invokeModel({
|
|
|
1213
1174
|
}
|
|
1214
1175
|
};
|
|
1215
1176
|
}
|
|
1216
|
-
var
|
|
1177
|
+
var createAskUserQuestionHandler = () => async (args) => {
|
|
1217
1178
|
const messages$1 = args.questions.map(
|
|
1218
1179
|
({ question, header, options, multiSelect }) => new messages.AIMessage({
|
|
1219
1180
|
content: question,
|
|
@@ -1226,99 +1187,79 @@ var handleAskUserQuestionToolResult = async (args) => {
|
|
|
1226
1187
|
);
|
|
1227
1188
|
return { toolResponse: "Question submitted", data: { chatMessages: messages$1 } };
|
|
1228
1189
|
};
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1190
|
+
function createGlobHandler(fs) {
|
|
1191
|
+
return async (_args) => {
|
|
1192
|
+
new justBash.Bash({ fs });
|
|
1193
|
+
return {
|
|
1194
|
+
toolResponse: "Hello, world!",
|
|
1195
|
+
data: { files: [] }
|
|
1196
|
+
};
|
|
1197
|
+
};
|
|
1235
1198
|
}
|
|
1236
1199
|
|
|
1237
1200
|
// src/tools/edit/handler.ts
|
|
1238
1201
|
function escapeRegExp(str) {
|
|
1239
1202
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1240
1203
|
}
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
toolResponse: `Error: old_string and new_string must be different.`,
|
|
1246
|
-
data: {
|
|
1247
|
-
path: file_path,
|
|
1248
|
-
success: false,
|
|
1249
|
-
replacements: 0
|
|
1250
|
-
}
|
|
1251
|
-
};
|
|
1252
|
-
}
|
|
1253
|
-
try {
|
|
1254
|
-
const exists = await fs.exists(file_path);
|
|
1255
|
-
if (!exists) {
|
|
1204
|
+
function createEditHandler(fs) {
|
|
1205
|
+
return async (args) => {
|
|
1206
|
+
const { file_path, old_string, new_string, replace_all = false } = args;
|
|
1207
|
+
if (old_string === new_string) {
|
|
1256
1208
|
return {
|
|
1257
|
-
toolResponse: `Error:
|
|
1258
|
-
data: {
|
|
1259
|
-
path: file_path,
|
|
1260
|
-
success: false,
|
|
1261
|
-
replacements: 0
|
|
1262
|
-
}
|
|
1209
|
+
toolResponse: `Error: old_string and new_string must be different.`,
|
|
1210
|
+
data: { path: file_path, success: false, replacements: 0 }
|
|
1263
1211
|
};
|
|
1264
1212
|
}
|
|
1265
|
-
|
|
1266
|
-
|
|
1213
|
+
try {
|
|
1214
|
+
const exists = await fs.exists(file_path);
|
|
1215
|
+
if (!exists) {
|
|
1216
|
+
return {
|
|
1217
|
+
toolResponse: `Error: File "${file_path}" does not exist.`,
|
|
1218
|
+
data: { path: file_path, success: false, replacements: 0 }
|
|
1219
|
+
};
|
|
1220
|
+
}
|
|
1221
|
+
const content = await fs.readFile(file_path);
|
|
1222
|
+
if (!content.includes(old_string)) {
|
|
1223
|
+
return {
|
|
1224
|
+
toolResponse: `Error: Could not find the specified text in "${file_path}". Make sure old_string matches exactly (whitespace-sensitive).`,
|
|
1225
|
+
data: { path: file_path, success: false, replacements: 0 }
|
|
1226
|
+
};
|
|
1227
|
+
}
|
|
1228
|
+
const escapedOldString = escapeRegExp(old_string);
|
|
1229
|
+
const globalRegex = new RegExp(escapedOldString, "g");
|
|
1230
|
+
const occurrences = (content.match(globalRegex) || []).length;
|
|
1231
|
+
if (!replace_all && occurrences > 1) {
|
|
1232
|
+
return {
|
|
1233
|
+
toolResponse: `Error: old_string appears ${occurrences} times in "${file_path}". Either provide more context to make it unique, or use replace_all: true.`,
|
|
1234
|
+
data: { path: file_path, success: false, replacements: 0 }
|
|
1235
|
+
};
|
|
1236
|
+
}
|
|
1237
|
+
let newContent;
|
|
1238
|
+
let replacements;
|
|
1239
|
+
if (replace_all) {
|
|
1240
|
+
newContent = content.split(old_string).join(new_string);
|
|
1241
|
+
replacements = occurrences;
|
|
1242
|
+
} else {
|
|
1243
|
+
const index = content.indexOf(old_string);
|
|
1244
|
+
newContent = content.slice(0, index) + new_string + content.slice(index + old_string.length);
|
|
1245
|
+
replacements = 1;
|
|
1246
|
+
}
|
|
1247
|
+
await fs.writeFile(file_path, newContent);
|
|
1248
|
+
const summary = replace_all ? `Replaced ${replacements} occurrence(s)` : `Replaced 1 occurrence`;
|
|
1267
1249
|
return {
|
|
1268
|
-
toolResponse:
|
|
1269
|
-
data: {
|
|
1270
|
-
path: file_path,
|
|
1271
|
-
success: false,
|
|
1272
|
-
replacements: 0
|
|
1273
|
-
}
|
|
1250
|
+
toolResponse: `${summary} in ${file_path}`,
|
|
1251
|
+
data: { path: file_path, success: true, replacements }
|
|
1274
1252
|
};
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
const globalRegex = new RegExp(escapedOldString, "g");
|
|
1278
|
-
const occurrences = (content.match(globalRegex) || []).length;
|
|
1279
|
-
if (!replace_all && occurrences > 1) {
|
|
1253
|
+
} catch (error) {
|
|
1254
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1280
1255
|
return {
|
|
1281
|
-
toolResponse: `Error
|
|
1282
|
-
data: {
|
|
1283
|
-
path: file_path,
|
|
1284
|
-
success: false,
|
|
1285
|
-
replacements: 0
|
|
1286
|
-
}
|
|
1256
|
+
toolResponse: `Error editing file "${file_path}": ${message}`,
|
|
1257
|
+
data: { path: file_path, success: false, replacements: 0 }
|
|
1287
1258
|
};
|
|
1288
1259
|
}
|
|
1289
|
-
|
|
1290
|
-
let replacements;
|
|
1291
|
-
if (replace_all) {
|
|
1292
|
-
newContent = content.split(old_string).join(new_string);
|
|
1293
|
-
replacements = occurrences;
|
|
1294
|
-
} else {
|
|
1295
|
-
const index = content.indexOf(old_string);
|
|
1296
|
-
newContent = content.slice(0, index) + new_string + content.slice(index + old_string.length);
|
|
1297
|
-
replacements = 1;
|
|
1298
|
-
}
|
|
1299
|
-
await fs.writeFile(file_path, newContent);
|
|
1300
|
-
const summary = replace_all ? `Replaced ${replacements} occurrence(s)` : `Replaced 1 occurrence`;
|
|
1301
|
-
return {
|
|
1302
|
-
toolResponse: `${summary} in ${file_path}`,
|
|
1303
|
-
data: {
|
|
1304
|
-
path: file_path,
|
|
1305
|
-
success: true,
|
|
1306
|
-
replacements
|
|
1307
|
-
}
|
|
1308
|
-
};
|
|
1309
|
-
} catch (error) {
|
|
1310
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1311
|
-
return {
|
|
1312
|
-
toolResponse: `Error editing file "${file_path}": ${message}`,
|
|
1313
|
-
data: {
|
|
1314
|
-
path: file_path,
|
|
1315
|
-
success: false,
|
|
1316
|
-
replacements: 0
|
|
1317
|
-
}
|
|
1318
|
-
};
|
|
1319
|
-
}
|
|
1260
|
+
};
|
|
1320
1261
|
}
|
|
1321
|
-
var
|
|
1262
|
+
var createBashHandler = (bashOptions) => async (args, _context) => {
|
|
1322
1263
|
const { command } = args;
|
|
1323
1264
|
const mergedOptions = {
|
|
1324
1265
|
...bashOptions,
|
|
@@ -1420,6 +1361,11 @@ exports.ZeitlichPlugin = ZeitlichPlugin;
|
|
|
1420
1361
|
exports.askUserQuestionTool = askUserQuestionTool;
|
|
1421
1362
|
exports.bashTool = bashTool;
|
|
1422
1363
|
exports.createAgentStateManager = createAgentStateManager;
|
|
1364
|
+
exports.createAskUserQuestionHandler = createAskUserQuestionHandler;
|
|
1365
|
+
exports.createBashHandler = createBashHandler;
|
|
1366
|
+
exports.createBashToolDescription = createBashToolDescription;
|
|
1367
|
+
exports.createEditHandler = createEditHandler;
|
|
1368
|
+
exports.createGlobHandler = createGlobHandler;
|
|
1423
1369
|
exports.createSession = createSession;
|
|
1424
1370
|
exports.createSharedActivities = createSharedActivities;
|
|
1425
1371
|
exports.createTaskCreateHandler = createTaskCreateHandler;
|
|
@@ -1431,23 +1377,21 @@ exports.createThreadManager = createThreadManager;
|
|
|
1431
1377
|
exports.createToolRouter = createToolRouter;
|
|
1432
1378
|
exports.defineSubagent = defineSubagent;
|
|
1433
1379
|
exports.defineTool = defineTool;
|
|
1434
|
-
exports.editHandler = editHandler;
|
|
1435
1380
|
exports.editTool = editTool;
|
|
1436
1381
|
exports.getStateQuery = getStateQuery;
|
|
1437
|
-
exports.globHandler = globHandler;
|
|
1438
1382
|
exports.globTool = globTool;
|
|
1439
1383
|
exports.grepTool = grepTool;
|
|
1440
|
-
exports.handleAskUserQuestionToolResult = handleAskUserQuestionToolResult;
|
|
1441
|
-
exports.handleBashTool = handleBashTool;
|
|
1442
1384
|
exports.hasNoOtherToolCalls = hasNoOtherToolCalls;
|
|
1443
1385
|
exports.invokeModel = invokeModel;
|
|
1444
1386
|
exports.isTerminalStatus = isTerminalStatus;
|
|
1387
|
+
exports.proxyDefaultThreadOps = proxyDefaultThreadOps;
|
|
1445
1388
|
exports.readTool = readTool;
|
|
1446
1389
|
exports.taskCreateTool = taskCreateTool;
|
|
1447
1390
|
exports.taskGetTool = taskGetTool;
|
|
1448
1391
|
exports.taskListTool = taskListTool;
|
|
1449
1392
|
exports.taskUpdateTool = taskUpdateTool;
|
|
1450
1393
|
exports.toTree = toTree;
|
|
1394
|
+
exports.withAutoAppend = withAutoAppend;
|
|
1451
1395
|
exports.writeTool = writeTool;
|
|
1452
1396
|
//# sourceMappingURL=index.cjs.map
|
|
1453
1397
|
//# sourceMappingURL=index.cjs.map
|