zeitlich 0.2.2 → 0.2.4

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.
Files changed (46) hide show
  1. package/README.md +34 -31
  2. package/dist/index.cjs +330 -399
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +24 -43
  5. package/dist/index.d.ts +24 -43
  6. package/dist/index.js +301 -373
  7. package/dist/index.js.map +1 -1
  8. package/dist/{workflow-BQf5EfNN.d.cts → workflow-PjeURKw4.d.cts} +265 -258
  9. package/dist/{workflow-BQf5EfNN.d.ts → workflow-PjeURKw4.d.ts} +265 -258
  10. package/dist/workflow.cjs +223 -281
  11. package/dist/workflow.cjs.map +1 -1
  12. package/dist/workflow.d.cts +2 -3
  13. package/dist/workflow.d.ts +2 -3
  14. package/dist/workflow.js +198 -258
  15. package/dist/workflow.js.map +1 -1
  16. package/package.json +3 -2
  17. package/src/activities.ts +0 -32
  18. package/src/index.ts +14 -11
  19. package/src/lib/model-invoker.ts +7 -1
  20. package/src/lib/session.ts +54 -109
  21. package/src/lib/thread-manager.ts +45 -37
  22. package/src/lib/tool-router.ts +148 -108
  23. package/src/lib/types.ts +35 -26
  24. package/src/tools/ask-user-question/handler.ts +5 -5
  25. package/src/tools/ask-user-question/tool.ts +3 -2
  26. package/src/tools/bash/bash.test.ts +12 -12
  27. package/src/tools/bash/handler.ts +5 -5
  28. package/src/tools/bash/tool.ts +3 -2
  29. package/src/tools/edit/handler.ts +78 -123
  30. package/src/tools/edit/tool.ts +3 -2
  31. package/src/tools/glob/handler.ts +17 -48
  32. package/src/tools/glob/tool.ts +3 -2
  33. package/src/tools/grep/tool.ts +3 -2
  34. package/src/tools/{read → read-file}/tool.ts +3 -2
  35. package/src/tools/{task → subagent}/handler.ts +18 -31
  36. package/src/tools/{task → subagent}/tool.ts +13 -20
  37. package/src/tools/task-create/handler.ts +5 -11
  38. package/src/tools/task-create/tool.ts +3 -2
  39. package/src/tools/task-get/handler.ts +5 -10
  40. package/src/tools/task-get/tool.ts +3 -2
  41. package/src/tools/task-list/handler.ts +5 -10
  42. package/src/tools/task-list/tool.ts +3 -2
  43. package/src/tools/task-update/handler.ts +5 -12
  44. package/src/tools/task-update/tool.ts +3 -2
  45. package/src/tools/{write → write-file}/tool.ts +5 -6
  46. package/src/workflow.ts +24 -21
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var workflow = require('@temporalio/workflow');
4
- var z5 = require('zod');
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,50 +10,50 @@ var justBash = require('just-bash');
10
10
 
11
11
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
12
12
 
13
- var z5__default = /*#__PURE__*/_interopDefault(z5);
13
+ var z3__default = /*#__PURE__*/_interopDefault(z3);
14
14
  var crypto__default = /*#__PURE__*/_interopDefault(crypto);
15
15
 
16
16
  // src/lib/session.ts
17
- var TASK_TOOL = "Task";
18
- function buildTaskDescription(subagents) {
17
+ var SUBAGENT_TOOL = "Subagent";
18
+ function buildSubagentDescription(subagents) {
19
19
  const subagentList = subagents.map((s) => `- **${s.name}**: ${s.description}`).join("\n");
20
- return `Launch a new agent to handle complex, multi-step tasks autonomously.
20
+ return `Launch a new agent to handle complex tasks autonomously.
21
21
 
22
- The ${TASK_TOOL} tool launches specialized agents (subprocesses) that autonomously handle complex tasks. Each agent type has specific capabilities and tools available to it.
22
+ The ${SUBAGENT_TOOL} tool launches specialized agents (subprocesses) that autonomously handle complex tasks. Each agent type has specific capabilities and tools available to it.
23
23
 
24
24
  Available agent types:
25
25
 
26
26
  ${subagentList}
27
27
 
28
- When using the ${TASK_TOOL} tool, you must specify a subagent parameter to select which agent type to use.
28
+ When using the ${SUBAGENT_TOOL} tool, you must specify a subagent parameter to select which agent type to use.
29
29
 
30
30
  Usage notes:
31
31
 
32
32
  - Always include a short description (3-5 words) summarizing what the agent will do
33
33
  - Launch multiple agents concurrently whenever possible, to maximize performance; to do that, use a single message with multiple tool uses
34
- - When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result.
34
+ - When the agent is done, it will return a single message back to you.
35
35
  - Each invocation starts fresh - provide a detailed task description with all necessary context.
36
36
  - Provide clear, detailed prompts so the agent can work autonomously and return exactly the information you need.
37
37
  - The agent's outputs should generally be trusted
38
38
  - Clearly tell the agent what type of work you expect since it is not aware of the user's intent
39
39
  - If the agent description mentions that it should be used proactively, then you should try your best to use it without the user having to ask for it first. Use your judgement.`;
40
40
  }
41
- function createTaskTool(subagents) {
41
+ function createSubagentTool(subagents) {
42
42
  if (subagents.length === 0) {
43
43
  throw new Error("createTaskTool requires at least one subagent");
44
44
  }
45
45
  const names = subagents.map((s) => s.name);
46
46
  return {
47
- name: TASK_TOOL,
48
- description: buildTaskDescription(subagents),
49
- schema: z5__default.default.object({
50
- subagent: z5__default.default.enum(names).describe("The type of subagent to launch"),
51
- description: z5__default.default.string().describe("A short (3-5 word) description of the task"),
52
- prompt: z5__default.default.string().describe("The task for the agent to perform")
47
+ name: SUBAGENT_TOOL,
48
+ description: buildSubagentDescription(subagents),
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
  }
56
- function createTaskHandler(subagents) {
56
+ function createSubagentHandler(subagents) {
57
57
  const { workflowId: parentWorkflowId, taskQueue: parentTaskQueue } = workflow.workflowInfo();
58
58
  return async (args) => {
59
59
  const config = subagents.find((s) => s.name === args.subagent);
@@ -72,128 +72,32 @@ function createTaskHandler(subagents) {
72
72
  args: [input],
73
73
  taskQueue: config.taskQueue ?? parentTaskQueue
74
74
  };
75
- const childResult = typeof config.workflow === "string" ? await workflow.executeChild(config.workflow, childOpts) : await workflow.executeChild(config.workflow, childOpts);
76
- const validated = config.resultSchema ? config.resultSchema.parse(childResult) : childResult;
77
- const toolResponse = typeof validated === "string" ? validated : JSON.stringify(validated, null, 2);
75
+ const { toolResponse, data } = typeof config.workflow === "string" ? await workflow.executeChild(config.workflow, childOpts) : await workflow.executeChild(config.workflow, childOpts);
76
+ const validated = config.resultSchema ? config.resultSchema.parse(data) : null;
78
77
  return {
79
78
  toolResponse,
80
- data: {
81
- result: validated,
82
- childWorkflowId
83
- }
79
+ data: validated
84
80
  };
85
81
  };
86
82
  }
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
83
 
169
84
  // src/lib/tool-router.ts
170
- var buildIntoolDefinitions = {
171
- [bashTool.name]: bashTool,
172
- [taskCreateTool.name]: taskCreateTool
173
- };
174
85
  function createToolRouter(options) {
175
- const { appendToolResult } = workflow.proxyActivities({
176
- startToCloseTimeout: "2m",
177
- retry: {
178
- maximumAttempts: 3,
179
- initialInterval: "5s",
180
- maximumInterval: "15m",
181
- backoffCoefficient: 4
182
- }
183
- });
86
+ const { appendToolResult } = options;
184
87
  const toolMap = /* @__PURE__ */ new Map();
185
88
  for (const [_key, tool] of Object.entries(options.tools)) {
186
89
  toolMap.set(tool.name, tool);
187
90
  }
91
+ const isEnabled = (tool) => tool.enabled !== false;
188
92
  if (options.subagents) {
189
93
  const subagentHooksMap = /* @__PURE__ */ new Map();
190
94
  for (const s of options.subagents) {
191
95
  if (s.hooks) subagentHooksMap.set(s.name, s.hooks);
192
96
  }
193
97
  const resolveSubagentName = (args) => args.subagent;
194
- toolMap.set("Task", {
195
- ...createTaskTool(options.subagents),
196
- handler: createTaskHandler(options.subagents),
98
+ toolMap.set("Subagent", {
99
+ ...createSubagentTool(options.subagents),
100
+ handler: createSubagentHandler(options.subagents),
197
101
  ...subagentHooksMap.size > 0 && {
198
102
  hooks: {
199
103
  onPreToolUse: async (ctx) => {
@@ -212,24 +116,6 @@ function createToolRouter(options) {
212
116
  }
213
117
  });
214
118
  }
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
119
  async function processToolCall(toolCall, turn, handlerContext) {
234
120
  const startTime = Date.now();
235
121
  const tool = toolMap.get(toolCall.name);
@@ -245,6 +131,7 @@ function createToolRouter(options) {
245
131
  await appendToolResult({
246
132
  threadId: options.threadId,
247
133
  toolCallId: toolCall.id,
134
+ toolName: toolCall.name,
248
135
  content: JSON.stringify({
249
136
  skipped: true,
250
137
  reason: "Skipped by PreToolUse hook"
@@ -266,6 +153,7 @@ function createToolRouter(options) {
266
153
  await appendToolResult({
267
154
  threadId: options.threadId,
268
155
  toolCallId: toolCall.id,
156
+ toolName: toolCall.name,
269
157
  content: JSON.stringify({
270
158
  skipped: true,
271
159
  reason: "Skipped by tool PreToolUse hook"
@@ -279,14 +167,22 @@ function createToolRouter(options) {
279
167
  }
280
168
  let result;
281
169
  let content;
170
+ let resultAppended = false;
282
171
  try {
283
172
  if (tool) {
173
+ const enrichedContext = {
174
+ ...handlerContext ?? {},
175
+ threadId: options.threadId,
176
+ toolCallId: toolCall.id,
177
+ toolName: toolCall.name
178
+ };
284
179
  const response = await tool.handler(
285
180
  effectiveArgs,
286
- handlerContext ?? {}
181
+ enrichedContext
287
182
  );
288
183
  result = response.data;
289
184
  content = response.toolResponse;
185
+ resultAppended = response.resultAppended === true;
290
186
  } else {
291
187
  result = { error: `Unknown tool: ${toolCall.name}` };
292
188
  content = JSON.stringify(result, null, 2);
@@ -332,11 +228,14 @@ function createToolRouter(options) {
332
228
  throw error;
333
229
  }
334
230
  }
335
- await appendToolResult({
336
- threadId: options.threadId,
337
- toolCallId: toolCall.id,
338
- content
339
- });
231
+ if (!resultAppended) {
232
+ await appendToolResult({
233
+ threadId: options.threadId,
234
+ toolCallId: toolCall.id,
235
+ toolName: toolCall.name,
236
+ content
237
+ });
238
+ }
340
239
  const toolResult = {
341
240
  toolCallId: toolCall.id,
342
241
  name: toolCall.name,
@@ -366,11 +265,11 @@ function createToolRouter(options) {
366
265
  return {
367
266
  // --- Methods from registry ---
368
267
  hasTools() {
369
- return toolMap.size > 0;
268
+ return Array.from(toolMap.values()).some(isEnabled);
370
269
  },
371
270
  parseToolCall(toolCall) {
372
271
  const tool = toolMap.get(toolCall.name);
373
- if (!tool) {
272
+ if (!tool || !isEnabled(tool)) {
374
273
  throw new Error(`Tool ${toolCall.name} not found`);
375
274
  }
376
275
  const parsedArgs = tool.schema.parse(toolCall.args);
@@ -381,13 +280,14 @@ function createToolRouter(options) {
381
280
  };
382
281
  },
383
282
  hasTool(name) {
384
- return toolMap.has(name);
283
+ const tool = toolMap.get(name);
284
+ return tool !== void 0 && isEnabled(tool);
385
285
  },
386
286
  getToolNames() {
387
- return Array.from(toolMap.keys());
287
+ return Array.from(toolMap.entries()).filter(([, tool]) => isEnabled(tool)).map(([name]) => name);
388
288
  },
389
289
  getToolDefinitions() {
390
- return Array.from(toolMap).map(([name, tool]) => ({
290
+ return Array.from(toolMap).filter(([, tool]) => isEnabled(tool)).map(([name, tool]) => ({
391
291
  name,
392
292
  description: tool.description,
393
293
  schema: tool.schema,
@@ -426,19 +326,28 @@ function createToolRouter(options) {
426
326
  }
427
327
  const handlerContext = context?.handlerContext ?? {};
428
328
  const processOne = async (toolCall) => {
329
+ const enrichedContext = {
330
+ ...handlerContext ?? {},
331
+ threadId: options.threadId,
332
+ toolCallId: toolCall.id,
333
+ toolName: toolCall.name
334
+ };
429
335
  const response = await handler(
430
336
  toolCall.args,
431
- handlerContext
337
+ enrichedContext
432
338
  );
433
- await appendToolResult({
434
- threadId: options.threadId,
435
- toolCallId: toolCall.id,
436
- content: response.toolResponse
437
- });
339
+ if (!response.resultAppended) {
340
+ await appendToolResult({
341
+ threadId: options.threadId,
342
+ toolCallId: toolCall.id,
343
+ toolName: toolCall.name,
344
+ content: response.toolResponse
345
+ });
346
+ }
438
347
  return {
439
348
  toolCallId: toolCall.id,
440
349
  name: toolCall.name,
441
- data: response.data ?? null
350
+ data: response.data
442
351
  };
443
352
  };
444
353
  if (options.parallel) {
@@ -464,6 +373,21 @@ function createToolRouter(options) {
464
373
  }
465
374
  };
466
375
  }
376
+ function withAutoAppend(threadHandler, handler) {
377
+ return async (args, context) => {
378
+ const response = await handler(args, context);
379
+ const threadId = context.threadId;
380
+ const toolCallId = context.toolCallId;
381
+ const toolName = context.toolName;
382
+ await threadHandler({
383
+ threadId,
384
+ toolCallId,
385
+ toolName,
386
+ content: response.toolResponse
387
+ });
388
+ return { toolResponse: "", data: response.data, resultAppended: true };
389
+ };
390
+ }
467
391
  function defineTool(tool) {
468
392
  return tool;
469
393
  }
@@ -475,51 +399,24 @@ function hasNoOtherToolCalls(toolCalls, excludeName) {
475
399
  }
476
400
 
477
401
  // src/lib/session.ts
478
- async function resolvePrompt(prompt) {
479
- if (typeof prompt === "function") {
480
- return prompt();
481
- }
482
- return prompt;
483
- }
484
402
  var createSession = async ({
485
403
  threadId,
486
404
  agentName,
487
405
  maxTurns = 50,
488
406
  metadata = {},
489
407
  runAgent,
490
- baseSystemPrompt,
491
- instructionsPrompt,
408
+ threadOps,
492
409
  buildContextMessage,
493
- buildFileTree = async () => "",
494
410
  subagents,
495
411
  tools = {},
496
412
  processToolsInParallel = true,
497
- buildInTools = {},
498
413
  hooks = {}
499
414
  }) => {
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
415
  const toolRouter = createToolRouter({
518
416
  tools,
417
+ appendToolResult: threadOps.appendToolResult,
519
418
  threadId,
520
419
  hooks,
521
- buildInTools,
522
- fileTree,
523
420
  subagents,
524
421
  parallel: processToolsInParallel
525
422
  });
@@ -544,83 +441,41 @@ var createSession = async ({
544
441
  });
545
442
  }
546
443
  stateManager.setTools(toolRouter.getToolDefinitions());
547
- await initializeThread(threadId);
548
- await appendSystemMessage(
549
- threadId,
550
- [
551
- await resolvePrompt(baseSystemPrompt),
552
- await resolvePrompt(instructionsPrompt)
553
- ].join("\n")
554
- );
555
- await appendHumanMessage(threadId, await buildContextMessage());
444
+ await threadOps.initializeThread(threadId);
445
+ await threadOps.appendHumanMessage(threadId, await buildContextMessage());
556
446
  let exitReason = "completed";
557
447
  try {
558
448
  while (stateManager.isRunning() && !stateManager.isTerminal() && stateManager.getTurns() < maxTurns) {
559
449
  stateManager.incrementTurns();
560
450
  const currentTurn = stateManager.getTurns();
561
- const { message, stopReason } = await runAgent({
451
+ const { message, rawToolCalls } = await runAgent({
562
452
  threadId,
563
453
  agentName,
564
454
  metadata
565
455
  });
566
- if (stopReason === "end_turn") {
567
- stateManager.complete();
568
- exitReason = "completed";
569
- return message;
570
- }
571
- if (!toolRouter.hasTools()) {
456
+ if (!toolRouter.hasTools() || rawToolCalls.length === 0) {
572
457
  stateManager.complete();
573
458
  exitReason = "completed";
574
459
  return message;
575
460
  }
576
- const rawToolCalls = await parseToolCalls(message);
577
461
  const parsedToolCalls = [];
578
- for (const tc of rawToolCalls.filter(
579
- (tc2) => tc2.name !== "Task"
580
- )) {
462
+ for (const tc of rawToolCalls) {
581
463
  try {
582
464
  parsedToolCalls.push(toolRouter.parseToolCall(tc));
583
465
  } catch (error) {
584
- await appendToolResult({
466
+ await threadOps.appendToolResult({
585
467
  threadId,
586
468
  toolCallId: tc.id ?? "",
469
+ toolName: tc.name,
587
470
  content: JSON.stringify({
588
471
  error: `Invalid tool call for "${tc.name}": ${error instanceof Error ? error.message : String(error)}`
589
472
  })
590
473
  });
591
474
  }
592
475
  }
593
- const taskToolCalls = [];
594
- if (subagents && subagents.length > 0) {
595
- for (const tc of rawToolCalls.filter(
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
- );
476
+ await toolRouter.processToolCalls(parsedToolCalls, {
477
+ turn: currentTurn
478
+ });
624
479
  if (stateManager.getStatus() === "WAITING_FOR_INPUT") {
625
480
  exitReason = "waiting_for_input";
626
481
  break;
@@ -639,6 +494,25 @@ var createSession = async ({
639
494
  }
640
495
  };
641
496
  };
497
+ function proxyDefaultThreadOps(options) {
498
+ const activities = workflow.proxyActivities(
499
+ options ?? {
500
+ startToCloseTimeout: "30m",
501
+ retry: {
502
+ maximumAttempts: 6,
503
+ initialInterval: "5s",
504
+ maximumInterval: "15m",
505
+ backoffCoefficient: 4
506
+ },
507
+ heartbeatTimeout: "5m"
508
+ }
509
+ );
510
+ return {
511
+ initializeThread: activities.initializeThread,
512
+ appendHumanMessage: activities.appendHumanMessage,
513
+ appendToolResult: activities.appendToolResult
514
+ };
515
+ }
642
516
 
643
517
  // src/lib/types.ts
644
518
  function isTerminalStatus(status) {
@@ -741,7 +615,7 @@ function createAgentStateManager(initialState) {
741
615
  tools = newTools.map((tool) => ({
742
616
  name: tool.name,
743
617
  description: tool.description,
744
- schema: z5.z.toJSONSchema(tool.schema),
618
+ schema: z3.z.toJSONSchema(tool.schema),
745
619
  strict: tool.strict,
746
620
  max_uses: tool.max_uses
747
621
  }));
@@ -775,18 +649,18 @@ Usage notes:
775
649
  * Use multiSelect: true to allow multiple answers to be selected for a question
776
650
  * If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label
777
651
  `,
778
- schema: z5__default.default.object({
779
- questions: z5__default.default.array(
780
- z5__default.default.object({
781
- question: z5__default.default.string().describe("The full question text to display"),
782
- header: z5__default.default.string().describe("Short label for the question (max 12 characters)"),
783
- options: z5__default.default.array(
784
- z5__default.default.object({
785
- label: z5__default.default.string(),
786
- description: z5__default.default.string()
652
+ schema: z3__default.default.object({
653
+ questions: z3__default.default.array(
654
+ z3__default.default.object({
655
+ question: z3__default.default.string().describe("The full question text to display"),
656
+ header: z3__default.default.string().describe("Short label for the question (max 12 characters)"),
657
+ options: z3__default.default.array(
658
+ z3__default.default.object({
659
+ label: z3__default.default.string(),
660
+ description: z3__default.default.string()
787
661
  })
788
662
  ).min(0).max(4).describe("Array of 0-4 choices, each with label and description"),
789
- multiSelect: z5__default.default.boolean().describe("If true, users can select multiple options")
663
+ multiSelect: z3__default.default.boolean().describe("If true, users can select multiple options")
790
664
  })
791
665
  )
792
666
  }),
@@ -806,9 +680,9 @@ Examples:
806
680
  - "**/*.test.ts" - Find all test files recursively
807
681
  - "src/**/*.ts" - Find all TypeScript files in src directory
808
682
  `,
809
- schema: z5.z.object({
810
- pattern: z5.z.string().describe("Glob pattern to match files against"),
811
- root: z5.z.string().optional().describe("Optional root directory to search from")
683
+ schema: z3.z.object({
684
+ pattern: z3.z.string().describe("Glob pattern to match files against"),
685
+ root: z3.z.string().optional().describe("Optional root directory to search from")
812
686
  }),
813
687
  strict: true
814
688
  };
@@ -826,13 +700,13 @@ Examples:
826
700
  - Search for function definitions with "function.*handleClick"
827
701
  - Search case-insensitively with ignoreCase: true
828
702
  `,
829
- schema: z5.z.object({
830
- pattern: z5.z.string().describe("Regex pattern to search for in file contents"),
831
- ignoreCase: z5.z.boolean().optional().describe("Case-insensitive search (default: false)"),
832
- maxMatches: z5.z.number().optional().describe("Maximum number of matches to return (default: 50)"),
833
- includePatterns: z5.z.array(z5.z.string()).optional().describe("Glob patterns to include (e.g., ['*.ts', '*.js'])"),
834
- excludePatterns: z5.z.array(z5.z.string()).optional().describe("Glob patterns to exclude (e.g., ['*.test.ts'])"),
835
- contextLines: z5.z.number().optional().describe("Number of context lines to show around matches")
703
+ schema: z3.z.object({
704
+ pattern: z3.z.string().describe("Regex pattern to search for in file contents"),
705
+ ignoreCase: z3.z.boolean().optional().describe("Case-insensitive search (default: false)"),
706
+ maxMatches: z3.z.number().optional().describe("Maximum number of matches to return (default: 50)"),
707
+ includePatterns: z3.z.array(z3.z.string()).optional().describe("Glob patterns to include (e.g., ['*.ts', '*.js'])"),
708
+ excludePatterns: z3.z.array(z3.z.string()).optional().describe("Glob patterns to exclude (e.g., ['*.test.ts'])"),
709
+ contextLines: z3.z.number().optional().describe("Number of context lines to show around matches")
836
710
  }),
837
711
  strict: true
838
712
  };
@@ -850,12 +724,12 @@ The tool returns the file content in an appropriate format:
850
724
  - Images: Base64-encoded image data
851
725
  - PDFs: Extracted text content
852
726
  `,
853
- schema: z5.z.object({
854
- path: z5.z.string().describe("Virtual path to the file to read"),
855
- offset: z5.z.number().optional().describe(
727
+ schema: z3.z.object({
728
+ path: z3.z.string().describe("Virtual path to the file to read"),
729
+ offset: z3.z.number().optional().describe(
856
730
  "Line number to start reading from (1-indexed, for text files)"
857
731
  ),
858
- limit: z5.z.number().optional().describe("Maximum number of lines to read (for text files)")
732
+ limit: z3.z.number().optional().describe("Maximum number of lines to read (for text files)")
859
733
  }),
860
734
  strict: true
861
735
  };
@@ -864,7 +738,7 @@ var writeTool = {
864
738
  description: `Create or overwrite a file with new content.
865
739
 
866
740
  Usage:
867
- - Provide the absolute virtual path to the file
741
+ - Provide the absolute path to the file
868
742
  - The file will be created if it doesn't exist
869
743
  - If the file exists, it will be completely overwritten
870
744
 
@@ -873,9 +747,9 @@ IMPORTANT:
873
747
  - This is an atomic write operation - the entire file is replaced
874
748
  - Path must be absolute (e.g., "/docs/readme.md", not "docs/readme.md")
875
749
  `,
876
- schema: z5.z.object({
877
- file_path: z5.z.string().describe("The absolute virtual path to the file to write"),
878
- content: z5.z.string().describe("The content to write to the file")
750
+ schema: z3.z.object({
751
+ file_path: z3.z.string().describe("The absolute path to the file to write"),
752
+ content: z3.z.string().describe("The content to write to the file")
879
753
  }),
880
754
  strict: true
881
755
  };
@@ -895,18 +769,72 @@ IMPORTANT:
895
769
  - The operation fails if old_string is not found
896
770
  - old_string and new_string must be different
897
771
  `,
898
- schema: z5.z.object({
899
- file_path: z5.z.string().describe("The absolute virtual path to the file to modify"),
900
- old_string: z5.z.string().describe("The exact text to replace"),
901
- new_string: z5.z.string().describe(
772
+ schema: z3.z.object({
773
+ file_path: z3.z.string().describe("The absolute virtual path to the file to modify"),
774
+ old_string: z3.z.string().describe("The exact text to replace"),
775
+ new_string: z3.z.string().describe(
902
776
  "The text to replace it with (must be different from old_string)"
903
777
  ),
904
- replace_all: z5.z.boolean().optional().describe(
778
+ replace_all: z3.z.boolean().optional().describe(
905
779
  "If true, replace all occurrences of old_string (default: false)"
906
780
  )
907
781
  }),
908
782
  strict: true
909
783
  };
784
+ var taskCreateTool = {
785
+ name: "TaskCreate",
786
+ 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.
787
+ It also helps the user understand the progress of the task and overall progress of their requests.
788
+
789
+ ## When to Use This Tool
790
+
791
+ Use this tool proactively in these scenarios:
792
+
793
+ - Complex multi-step tasks - When a task requires 3 or more distinct steps or actions
794
+ - Non-trivial and complex tasks - Tasks that require careful planning or multiple operations
795
+ - User explicitly requests todo list - When the user directly asks you to use the todo list
796
+ - User provides multiple tasks - When users provide a list of things to be done (numbered or comma-separated)
797
+ - After receiving new instructions - Immediately capture user requirements as tasks
798
+ - When you start working on a task - Mark it as in_progress BEFORE beginning work
799
+ - After completing a task - Mark it as completed and add any new follow-up tasks discovered during implementation
800
+
801
+ ## When NOT to Use This Tool
802
+
803
+ Skip using this tool when:
804
+ - There is only a single, straightforward task
805
+ - The task is trivial and tracking it provides no organizational benefit
806
+ - The task can be completed in less than 3 trivial steps
807
+ - The task is purely conversational or informational
808
+
809
+ 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.
810
+
811
+ ## Task Fields
812
+
813
+ - **subject**: A brief, actionable title in imperative form (e.g., "Fix authentication bug in login flow")
814
+ - **description**: Detailed description of what needs to be done, including context and acceptance criteria
815
+ - **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.
816
+
817
+ **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\`.
818
+
819
+ ## Tips
820
+
821
+ - Create tasks with clear, specific subjects that describe the outcome
822
+ - Include enough detail in the description for another agent to understand and complete the task
823
+ - After creating tasks, use TaskUpdate to set up dependencies (blocks/blockedBy) if needed
824
+ - Check TaskList first to avoid creating duplicate tasks`,
825
+ schema: z3__default.default.object({
826
+ subject: z3__default.default.string().describe(
827
+ 'A brief, actionable title in imperative form (e.g., "Fix authentication bug in login flow")'
828
+ ),
829
+ description: z3__default.default.string().describe(
830
+ "Detailed description of what needs to be done, including context and acceptance criteria"
831
+ ),
832
+ activeForm: z3__default.default.string().describe(
833
+ '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.'
834
+ ),
835
+ metadata: z3__default.default.record(z3__default.default.string(), z3__default.default.string()).describe("Arbitrary key-value pairs for tracking")
836
+ })
837
+ };
910
838
  function createTaskCreateHandler(stateManager) {
911
839
  return (args) => {
912
840
  const task = {
@@ -929,8 +857,8 @@ function createTaskCreateHandler(stateManager) {
929
857
  var taskGetTool = {
930
858
  name: "TaskGet",
931
859
  description: `Retrieve full task details including dependencies.`,
932
- schema: z5__default.default.object({
933
- taskId: z5__default.default.string().describe("The ID of the task to get")
860
+ schema: z3__default.default.object({
861
+ taskId: z3__default.default.string().describe("The ID of the task to get")
934
862
  })
935
863
  };
936
864
 
@@ -953,12 +881,12 @@ function createTaskGetHandler(stateManager) {
953
881
  var taskListTool = {
954
882
  name: "TaskList",
955
883
  description: `List all tasks with current state.`,
956
- schema: z5__default.default.object({})
884
+ schema: z3__default.default.object({})
957
885
  };
958
886
 
959
887
  // src/tools/task-list/handler.ts
960
888
  function createTaskListHandler(stateManager) {
961
- return (_args) => {
889
+ return () => {
962
890
  const taskList = stateManager.getTasks();
963
891
  return {
964
892
  toolResponse: JSON.stringify(taskList, null, 2),
@@ -969,11 +897,11 @@ function createTaskListHandler(stateManager) {
969
897
  var taskUpdateTool = {
970
898
  name: "TaskUpdate",
971
899
  description: `Update status, add blockers, modify details.`,
972
- schema: z5__default.default.object({
973
- taskId: z5__default.default.string().describe("The ID of the task to get"),
974
- status: z5__default.default.enum(["pending", "in_progress", "completed"]).describe("The status of the task"),
975
- addBlockedBy: z5__default.default.array(z5__default.default.string()).describe("The IDs of the tasks that are blocking this task"),
976
- addBlocks: z5__default.default.array(z5__default.default.string()).describe("The IDs of the tasks that this task is blocking")
900
+ schema: z3__default.default.object({
901
+ taskId: z3__default.default.string().describe("The ID of the task to get"),
902
+ status: z3__default.default.enum(["pending", "in_progress", "completed"]).describe("The status of the task"),
903
+ addBlockedBy: z3__default.default.array(z3__default.default.string()).describe("The IDs of the tasks that are blocking this task"),
904
+ addBlocks: z3__default.default.array(z3__default.default.string()).describe("The IDs of the tasks that this task is blocking")
977
905
  })
978
906
  };
979
907
 
@@ -1021,6 +949,33 @@ function createTaskUpdateHandler(stateManager) {
1021
949
  };
1022
950
  };
1023
951
  }
952
+ var createBashToolDescription = ({
953
+ fileTree
954
+ }) => `Execute shell commands in a bash environment.
955
+
956
+ Use this tool to:
957
+ - Run shell commands (ls, cat, grep, find, etc.)
958
+ - Execute scripts and chain commands with pipes (|) or logical operators (&&, ||)
959
+ - Inspect files and directories
960
+
961
+ Current file tree:
962
+ ${fileTree}`;
963
+ var bashTool = {
964
+ name: "Bash",
965
+ description: `Execute shell commands in a sandboxed 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
+ schema: z3__default.default.object({
973
+ command: z3__default.default.string().describe(
974
+ "The bash command to execute. Can include pipes (|), redirects (>, >>), logical operators (&&, ||), and shell features like command substitution $(...)."
975
+ )
976
+ }),
977
+ strict: true
978
+ };
1024
979
 
1025
980
  // node_modules/uuid/dist/esm-node/stringify.js
1026
981
  var byteToHex = [];
@@ -1069,25 +1024,33 @@ function getThreadKey(threadId, key) {
1069
1024
  return `thread:${threadId}:${key}`;
1070
1025
  }
1071
1026
  function createThreadManager(config) {
1072
- const { redis, threadId, key = "messages" } = config;
1027
+ const {
1028
+ redis,
1029
+ threadId,
1030
+ key = "messages",
1031
+ serialize = (m) => JSON.stringify(m),
1032
+ deserialize = (raw) => JSON.parse(raw)
1033
+ } = config;
1073
1034
  const redisKey = getThreadKey(threadId, key);
1074
- return {
1035
+ const base = {
1075
1036
  async initialize() {
1076
1037
  await redis.del(redisKey);
1077
1038
  },
1078
1039
  async load() {
1079
1040
  const data = await redis.lrange(redisKey, 0, -1);
1080
- return data.map((item) => JSON.parse(item));
1041
+ return data.map(deserialize);
1081
1042
  },
1082
1043
  async append(messages) {
1083
1044
  if (messages.length > 0) {
1084
- await redis.rpush(redisKey, ...messages.map((m) => JSON.stringify(m)));
1045
+ await redis.rpush(redisKey, ...messages.map(serialize));
1085
1046
  await redis.expire(redisKey, THREAD_TTL_SECONDS);
1086
1047
  }
1087
1048
  },
1088
1049
  async delete() {
1089
1050
  await redis.del(redisKey);
1090
- },
1051
+ }
1052
+ };
1053
+ const helpers = {
1091
1054
  createHumanMessage(content) {
1092
1055
  return new messages.HumanMessage({
1093
1056
  id: v4_default(),
@@ -1107,40 +1070,29 @@ function createThreadManager(config) {
1107
1070
  },
1108
1071
  createToolMessage(content, toolCallId) {
1109
1072
  return new messages.ToolMessage({
1110
- // Cast needed due to langchain type compatibility
1111
1073
  content,
1112
1074
  tool_call_id: toolCallId
1113
1075
  }).toDict();
1114
1076
  },
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
1077
  async appendHumanMessage(content) {
1125
- const message = this.createHumanMessage(content);
1126
- await this.append([message]);
1078
+ const message = helpers.createHumanMessage(content);
1079
+ await base.append([message]);
1127
1080
  },
1128
1081
  async appendToolMessage(content, toolCallId) {
1129
- const message = this.createToolMessage(content, toolCallId);
1130
- await this.append([message]);
1082
+ const message = helpers.createToolMessage(content, toolCallId);
1083
+ await base.append([message]);
1131
1084
  },
1132
1085
  async appendAIMessage(content) {
1133
- const message = this.createAIMessage(content);
1134
- await this.append([message]);
1086
+ const message = helpers.createAIMessage(content);
1087
+ await base.append([message]);
1135
1088
  }
1136
1089
  };
1090
+ return Object.assign(base, helpers);
1137
1091
  }
1092
+
1093
+ // src/activities.ts
1138
1094
  function createSharedActivities(redis) {
1139
1095
  return {
1140
- async appendSystemMessage(threadId, content) {
1141
- const thread = createThreadManager({ redis, threadId });
1142
- await thread.appendSystemMessage(content);
1143
- },
1144
1096
  async appendToolResult(config) {
1145
1097
  const { threadId, toolCallId, content } = config;
1146
1098
  const thread = createThreadManager({ redis, threadId });
@@ -1157,15 +1109,6 @@ function createSharedActivities(redis) {
1157
1109
  async appendHumanMessage(threadId, content) {
1158
1110
  const thread = createThreadManager({ redis, threadId });
1159
1111
  await thread.appendHumanMessage(content);
1160
- },
1161
- async parseToolCalls(storedMessage) {
1162
- const message = messages.mapStoredMessageToChatMessage(storedMessage);
1163
- const toolCalls = message.tool_calls ?? [];
1164
- return toolCalls.map((toolCall) => ({
1165
- id: toolCall.id,
1166
- name: toolCall.name,
1167
- args: toolCall.args
1168
- }));
1169
1112
  }
1170
1113
  };
1171
1114
  }
@@ -1203,9 +1146,14 @@ async function invokeModel({
1203
1146
  }
1204
1147
  );
1205
1148
  await thread.append([response.toDict()]);
1149
+ const toolCalls = response.tool_calls ?? [];
1206
1150
  return {
1207
1151
  message: response.toDict(),
1208
- stopReason: response.response_metadata?.stop_reason ?? null,
1152
+ rawToolCalls: toolCalls.map((tc) => ({
1153
+ id: tc.id,
1154
+ name: tc.name,
1155
+ args: tc.args
1156
+ })),
1209
1157
  usage: {
1210
1158
  input_tokens: response.usage_metadata?.input_tokens,
1211
1159
  output_tokens: response.usage_metadata?.output_tokens,
@@ -1213,7 +1161,7 @@ async function invokeModel({
1213
1161
  }
1214
1162
  };
1215
1163
  }
1216
- var handleAskUserQuestionToolResult = async (args) => {
1164
+ var createAskUserQuestionHandler = () => async (args) => {
1217
1165
  const messages$1 = args.questions.map(
1218
1166
  ({ question, header, options, multiSelect }) => new messages.AIMessage({
1219
1167
  content: question,
@@ -1226,99 +1174,79 @@ var handleAskUserQuestionToolResult = async (args) => {
1226
1174
  );
1227
1175
  return { toolResponse: "Question submitted", data: { chatMessages: messages$1 } };
1228
1176
  };
1229
- async function globHandler(_args, fs) {
1230
- new justBash.Bash({ fs });
1231
- return Promise.resolve({
1232
- toolResponse: "Hello, world!",
1233
- data: { files: [] }
1234
- });
1177
+ function createGlobHandler(fs) {
1178
+ return async (_args) => {
1179
+ new justBash.Bash({ fs });
1180
+ return {
1181
+ toolResponse: "Hello, world!",
1182
+ data: { files: [] }
1183
+ };
1184
+ };
1235
1185
  }
1236
1186
 
1237
1187
  // src/tools/edit/handler.ts
1238
1188
  function escapeRegExp(str) {
1239
1189
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1240
1190
  }
1241
- async function editHandler(args, fs) {
1242
- const { file_path, old_string, new_string, replace_all = false } = args;
1243
- if (old_string === new_string) {
1244
- return {
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) {
1191
+ function createEditHandler(fs) {
1192
+ return async (args) => {
1193
+ const { file_path, old_string, new_string, replace_all = false } = args;
1194
+ if (old_string === new_string) {
1256
1195
  return {
1257
- toolResponse: `Error: File "${file_path}" does not exist.`,
1258
- data: {
1259
- path: file_path,
1260
- success: false,
1261
- replacements: 0
1262
- }
1196
+ toolResponse: `Error: old_string and new_string must be different.`,
1197
+ data: { path: file_path, success: false, replacements: 0 }
1263
1198
  };
1264
1199
  }
1265
- const content = await fs.readFile(file_path);
1266
- if (!content.includes(old_string)) {
1200
+ try {
1201
+ const exists = await fs.exists(file_path);
1202
+ if (!exists) {
1203
+ return {
1204
+ toolResponse: `Error: File "${file_path}" does not exist.`,
1205
+ data: { path: file_path, success: false, replacements: 0 }
1206
+ };
1207
+ }
1208
+ const content = await fs.readFile(file_path);
1209
+ if (!content.includes(old_string)) {
1210
+ return {
1211
+ toolResponse: `Error: Could not find the specified text in "${file_path}". Make sure old_string matches exactly (whitespace-sensitive).`,
1212
+ data: { path: file_path, success: false, replacements: 0 }
1213
+ };
1214
+ }
1215
+ const escapedOldString = escapeRegExp(old_string);
1216
+ const globalRegex = new RegExp(escapedOldString, "g");
1217
+ const occurrences = (content.match(globalRegex) || []).length;
1218
+ if (!replace_all && occurrences > 1) {
1219
+ return {
1220
+ toolResponse: `Error: old_string appears ${occurrences} times in "${file_path}". Either provide more context to make it unique, or use replace_all: true.`,
1221
+ data: { path: file_path, success: false, replacements: 0 }
1222
+ };
1223
+ }
1224
+ let newContent;
1225
+ let replacements;
1226
+ if (replace_all) {
1227
+ newContent = content.split(old_string).join(new_string);
1228
+ replacements = occurrences;
1229
+ } else {
1230
+ const index = content.indexOf(old_string);
1231
+ newContent = content.slice(0, index) + new_string + content.slice(index + old_string.length);
1232
+ replacements = 1;
1233
+ }
1234
+ await fs.writeFile(file_path, newContent);
1235
+ const summary = replace_all ? `Replaced ${replacements} occurrence(s)` : `Replaced 1 occurrence`;
1267
1236
  return {
1268
- toolResponse: `Error: Could not find the specified text in "${file_path}". Make sure old_string matches exactly (whitespace-sensitive).`,
1269
- data: {
1270
- path: file_path,
1271
- success: false,
1272
- replacements: 0
1273
- }
1237
+ toolResponse: `${summary} in ${file_path}`,
1238
+ data: { path: file_path, success: true, replacements }
1274
1239
  };
1275
- }
1276
- const escapedOldString = escapeRegExp(old_string);
1277
- const globalRegex = new RegExp(escapedOldString, "g");
1278
- const occurrences = (content.match(globalRegex) || []).length;
1279
- if (!replace_all && occurrences > 1) {
1240
+ } catch (error) {
1241
+ const message = error instanceof Error ? error.message : "Unknown error";
1280
1242
  return {
1281
- toolResponse: `Error: old_string appears ${occurrences} times in "${file_path}". Either provide more context to make it unique, or use replace_all: true.`,
1282
- data: {
1283
- path: file_path,
1284
- success: false,
1285
- replacements: 0
1286
- }
1243
+ toolResponse: `Error editing file "${file_path}": ${message}`,
1244
+ data: { path: file_path, success: false, replacements: 0 }
1287
1245
  };
1288
1246
  }
1289
- let newContent;
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
- }
1247
+ };
1320
1248
  }
1321
- var handleBashTool = (bashOptions) => async (args, _context) => {
1249
+ var createBashHandler = (bashOptions) => async (args, _context) => {
1322
1250
  const { command } = args;
1323
1251
  const mergedOptions = {
1324
1252
  ...bashOptions,
@@ -1420,34 +1348,37 @@ exports.ZeitlichPlugin = ZeitlichPlugin;
1420
1348
  exports.askUserQuestionTool = askUserQuestionTool;
1421
1349
  exports.bashTool = bashTool;
1422
1350
  exports.createAgentStateManager = createAgentStateManager;
1351
+ exports.createAskUserQuestionHandler = createAskUserQuestionHandler;
1352
+ exports.createBashHandler = createBashHandler;
1353
+ exports.createBashToolDescription = createBashToolDescription;
1354
+ exports.createEditHandler = createEditHandler;
1355
+ exports.createGlobHandler = createGlobHandler;
1423
1356
  exports.createSession = createSession;
1424
1357
  exports.createSharedActivities = createSharedActivities;
1358
+ exports.createSubagentTool = createSubagentTool;
1425
1359
  exports.createTaskCreateHandler = createTaskCreateHandler;
1426
1360
  exports.createTaskGetHandler = createTaskGetHandler;
1427
1361
  exports.createTaskListHandler = createTaskListHandler;
1428
- exports.createTaskTool = createTaskTool;
1429
1362
  exports.createTaskUpdateHandler = createTaskUpdateHandler;
1430
1363
  exports.createThreadManager = createThreadManager;
1431
1364
  exports.createToolRouter = createToolRouter;
1432
1365
  exports.defineSubagent = defineSubagent;
1433
1366
  exports.defineTool = defineTool;
1434
- exports.editHandler = editHandler;
1435
1367
  exports.editTool = editTool;
1436
1368
  exports.getStateQuery = getStateQuery;
1437
- exports.globHandler = globHandler;
1438
1369
  exports.globTool = globTool;
1439
1370
  exports.grepTool = grepTool;
1440
- exports.handleAskUserQuestionToolResult = handleAskUserQuestionToolResult;
1441
- exports.handleBashTool = handleBashTool;
1442
1371
  exports.hasNoOtherToolCalls = hasNoOtherToolCalls;
1443
1372
  exports.invokeModel = invokeModel;
1444
1373
  exports.isTerminalStatus = isTerminalStatus;
1374
+ exports.proxyDefaultThreadOps = proxyDefaultThreadOps;
1445
1375
  exports.readTool = readTool;
1446
1376
  exports.taskCreateTool = taskCreateTool;
1447
1377
  exports.taskGetTool = taskGetTool;
1448
1378
  exports.taskListTool = taskListTool;
1449
1379
  exports.taskUpdateTool = taskUpdateTool;
1450
1380
  exports.toTree = toTree;
1381
+ exports.withAutoAppend = withAutoAppend;
1451
1382
  exports.writeTool = writeTool;
1452
1383
  //# sourceMappingURL=index.cjs.map
1453
1384
  //# sourceMappingURL=index.cjs.map