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.
- package/README.md +34 -31
- package/dist/index.cjs +330 -399
- 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 +301 -373
- package/dist/index.js.map +1 -1
- package/dist/{workflow-BQf5EfNN.d.cts → workflow-PjeURKw4.d.cts} +265 -258
- package/dist/{workflow-BQf5EfNN.d.ts → workflow-PjeURKw4.d.ts} +265 -258
- package/dist/workflow.cjs +223 -281
- 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 +198 -258
- package/dist/workflow.js.map +1 -1
- package/package.json +3 -2
- package/src/activities.ts +0 -32
- package/src/index.ts +14 -11
- package/src/lib/model-invoker.ts +7 -1
- package/src/lib/session.ts +54 -109
- package/src/lib/thread-manager.ts +45 -37
- package/src/lib/tool-router.ts +148 -108
- package/src/lib/types.ts +35 -26
- 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 → subagent}/handler.ts +18 -31
- package/src/tools/{task → subagent}/tool.ts +13 -20
- 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 +24 -21
package/dist/workflow.cjs
CHANGED
|
@@ -1,53 +1,53 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var workflow = require('@temporalio/workflow');
|
|
4
|
-
var
|
|
4
|
+
var z3 = require('zod');
|
|
5
5
|
|
|
6
6
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
7
|
|
|
8
|
-
var
|
|
8
|
+
var z3__default = /*#__PURE__*/_interopDefault(z3);
|
|
9
9
|
|
|
10
10
|
// src/lib/session.ts
|
|
11
|
-
var
|
|
12
|
-
function
|
|
11
|
+
var SUBAGENT_TOOL = "Subagent";
|
|
12
|
+
function buildSubagentDescription(subagents) {
|
|
13
13
|
const subagentList = subagents.map((s) => `- **${s.name}**: ${s.description}`).join("\n");
|
|
14
|
-
return `Launch a new agent to handle complex
|
|
14
|
+
return `Launch a new agent to handle complex tasks autonomously.
|
|
15
15
|
|
|
16
|
-
The ${
|
|
16
|
+
The ${SUBAGENT_TOOL} tool launches specialized agents (subprocesses) that autonomously handle complex tasks. Each agent type has specific capabilities and tools available to it.
|
|
17
17
|
|
|
18
18
|
Available agent types:
|
|
19
19
|
|
|
20
20
|
${subagentList}
|
|
21
21
|
|
|
22
|
-
When using the ${
|
|
22
|
+
When using the ${SUBAGENT_TOOL} tool, you must specify a subagent parameter to select which agent type to use.
|
|
23
23
|
|
|
24
24
|
Usage notes:
|
|
25
25
|
|
|
26
26
|
- Always include a short description (3-5 words) summarizing what the agent will do
|
|
27
27
|
- Launch multiple agents concurrently whenever possible, to maximize performance; to do that, use a single message with multiple tool uses
|
|
28
|
-
- When the agent is done, it will return a single message back to you.
|
|
28
|
+
- When the agent is done, it will return a single message back to you.
|
|
29
29
|
- Each invocation starts fresh - provide a detailed task description with all necessary context.
|
|
30
30
|
- Provide clear, detailed prompts so the agent can work autonomously and return exactly the information you need.
|
|
31
31
|
- The agent's outputs should generally be trusted
|
|
32
32
|
- Clearly tell the agent what type of work you expect since it is not aware of the user's intent
|
|
33
33
|
- 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.`;
|
|
34
34
|
}
|
|
35
|
-
function
|
|
35
|
+
function createSubagentTool(subagents) {
|
|
36
36
|
if (subagents.length === 0) {
|
|
37
37
|
throw new Error("createTaskTool requires at least one subagent");
|
|
38
38
|
}
|
|
39
39
|
const names = subagents.map((s) => s.name);
|
|
40
40
|
return {
|
|
41
|
-
name:
|
|
42
|
-
description:
|
|
43
|
-
schema:
|
|
44
|
-
subagent:
|
|
45
|
-
description:
|
|
46
|
-
prompt:
|
|
41
|
+
name: SUBAGENT_TOOL,
|
|
42
|
+
description: buildSubagentDescription(subagents),
|
|
43
|
+
schema: z3__default.default.object({
|
|
44
|
+
subagent: z3__default.default.enum(names).describe("The type of subagent to launch"),
|
|
45
|
+
description: z3__default.default.string().describe("A short (3-5 word) description of the task"),
|
|
46
|
+
prompt: z3__default.default.string().describe("The task for the agent to perform")
|
|
47
47
|
})
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
|
-
function
|
|
50
|
+
function createSubagentHandler(subagents) {
|
|
51
51
|
const { workflowId: parentWorkflowId, taskQueue: parentTaskQueue } = workflow.workflowInfo();
|
|
52
52
|
return async (args) => {
|
|
53
53
|
const config = subagents.find((s) => s.name === args.subagent);
|
|
@@ -66,128 +66,32 @@ function createTaskHandler(subagents) {
|
|
|
66
66
|
args: [input],
|
|
67
67
|
taskQueue: config.taskQueue ?? parentTaskQueue
|
|
68
68
|
};
|
|
69
|
-
const
|
|
70
|
-
const validated = config.resultSchema ? config.resultSchema.parse(
|
|
71
|
-
const toolResponse = typeof validated === "string" ? validated : JSON.stringify(validated, null, 2);
|
|
69
|
+
const { toolResponse, data } = typeof config.workflow === "string" ? await workflow.executeChild(config.workflow, childOpts) : await workflow.executeChild(config.workflow, childOpts);
|
|
70
|
+
const validated = config.resultSchema ? config.resultSchema.parse(data) : null;
|
|
72
71
|
return {
|
|
73
72
|
toolResponse,
|
|
74
|
-
data:
|
|
75
|
-
result: validated,
|
|
76
|
-
childWorkflowId
|
|
77
|
-
}
|
|
73
|
+
data: validated
|
|
78
74
|
};
|
|
79
75
|
};
|
|
80
76
|
}
|
|
81
|
-
var createBashToolDescription = ({
|
|
82
|
-
fileTree
|
|
83
|
-
}) => `Execute shell commands in a bash environment.
|
|
84
|
-
|
|
85
|
-
Use this tool to:
|
|
86
|
-
- Run shell commands (ls, cat, grep, find, etc.)
|
|
87
|
-
- Execute scripts and chain commands with pipes (|) or logical operators (&&, ||)
|
|
88
|
-
- Inspect files and directories
|
|
89
|
-
|
|
90
|
-
Current file tree:
|
|
91
|
-
${fileTree}`;
|
|
92
|
-
var bashTool = {
|
|
93
|
-
name: "Bash",
|
|
94
|
-
description: `Execute shell commands in a sandboxed bash environment.
|
|
95
|
-
|
|
96
|
-
Use this tool to:
|
|
97
|
-
- Run shell commands (ls, cat, grep, find, etc.)
|
|
98
|
-
- Execute scripts and chain commands with pipes (|) or logical operators (&&, ||)
|
|
99
|
-
- Inspect files and directories
|
|
100
|
-
`,
|
|
101
|
-
schema: z5__default.default.object({
|
|
102
|
-
command: z5__default.default.string().describe(
|
|
103
|
-
"The bash command to execute. Can include pipes (|), redirects (>, >>), logical operators (&&, ||), and shell features like command substitution $(...)."
|
|
104
|
-
)
|
|
105
|
-
}),
|
|
106
|
-
strict: true
|
|
107
|
-
};
|
|
108
|
-
var taskCreateTool = {
|
|
109
|
-
name: "TaskCreate",
|
|
110
|
-
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.
|
|
111
|
-
It also helps the user understand the progress of the task and overall progress of their requests.
|
|
112
|
-
|
|
113
|
-
## When to Use This Tool
|
|
114
|
-
|
|
115
|
-
Use this tool proactively in these scenarios:
|
|
116
|
-
|
|
117
|
-
- Complex multi-step tasks - When a task requires 3 or more distinct steps or actions
|
|
118
|
-
- Non-trivial and complex tasks - Tasks that require careful planning or multiple operations
|
|
119
|
-
- User explicitly requests todo list - When the user directly asks you to use the todo list
|
|
120
|
-
- User provides multiple tasks - When users provide a list of things to be done (numbered or comma-separated)
|
|
121
|
-
- After receiving new instructions - Immediately capture user requirements as tasks
|
|
122
|
-
- When you start working on a task - Mark it as in_progress BEFORE beginning work
|
|
123
|
-
- After completing a task - Mark it as completed and add any new follow-up tasks discovered during implementation
|
|
124
|
-
|
|
125
|
-
## When NOT to Use This Tool
|
|
126
|
-
|
|
127
|
-
Skip using this tool when:
|
|
128
|
-
- There is only a single, straightforward task
|
|
129
|
-
- The task is trivial and tracking it provides no organizational benefit
|
|
130
|
-
- The task can be completed in less than 3 trivial steps
|
|
131
|
-
- The task is purely conversational or informational
|
|
132
|
-
|
|
133
|
-
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.
|
|
134
|
-
|
|
135
|
-
## Task Fields
|
|
136
|
-
|
|
137
|
-
- **subject**: A brief, actionable title in imperative form (e.g., "Fix authentication bug in login flow")
|
|
138
|
-
- **description**: Detailed description of what needs to be done, including context and acceptance criteria
|
|
139
|
-
- **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.
|
|
140
|
-
|
|
141
|
-
**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\`.
|
|
142
|
-
|
|
143
|
-
## Tips
|
|
144
|
-
|
|
145
|
-
- Create tasks with clear, specific subjects that describe the outcome
|
|
146
|
-
- Include enough detail in the description for another agent to understand and complete the task
|
|
147
|
-
- After creating tasks, use TaskUpdate to set up dependencies (blocks/blockedBy) if needed
|
|
148
|
-
- Check TaskList first to avoid creating duplicate tasks`,
|
|
149
|
-
schema: z5__default.default.object({
|
|
150
|
-
subject: z5__default.default.string().describe(
|
|
151
|
-
'A brief, actionable title in imperative form (e.g., "Fix authentication bug in login flow")'
|
|
152
|
-
),
|
|
153
|
-
description: z5__default.default.string().describe(
|
|
154
|
-
"Detailed description of what needs to be done, including context and acceptance criteria"
|
|
155
|
-
),
|
|
156
|
-
activeForm: z5__default.default.string().describe(
|
|
157
|
-
'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.'
|
|
158
|
-
),
|
|
159
|
-
metadata: z5__default.default.record(z5__default.default.string(), z5__default.default.string()).describe("Arbitrary key-value pairs for tracking")
|
|
160
|
-
})
|
|
161
|
-
};
|
|
162
77
|
|
|
163
78
|
// src/lib/tool-router.ts
|
|
164
|
-
var buildIntoolDefinitions = {
|
|
165
|
-
[bashTool.name]: bashTool,
|
|
166
|
-
[taskCreateTool.name]: taskCreateTool
|
|
167
|
-
};
|
|
168
79
|
function createToolRouter(options) {
|
|
169
|
-
const { appendToolResult } =
|
|
170
|
-
startToCloseTimeout: "2m",
|
|
171
|
-
retry: {
|
|
172
|
-
maximumAttempts: 3,
|
|
173
|
-
initialInterval: "5s",
|
|
174
|
-
maximumInterval: "15m",
|
|
175
|
-
backoffCoefficient: 4
|
|
176
|
-
}
|
|
177
|
-
});
|
|
80
|
+
const { appendToolResult } = options;
|
|
178
81
|
const toolMap = /* @__PURE__ */ new Map();
|
|
179
82
|
for (const [_key, tool] of Object.entries(options.tools)) {
|
|
180
83
|
toolMap.set(tool.name, tool);
|
|
181
84
|
}
|
|
85
|
+
const isEnabled = (tool) => tool.enabled !== false;
|
|
182
86
|
if (options.subagents) {
|
|
183
87
|
const subagentHooksMap = /* @__PURE__ */ new Map();
|
|
184
88
|
for (const s of options.subagents) {
|
|
185
89
|
if (s.hooks) subagentHooksMap.set(s.name, s.hooks);
|
|
186
90
|
}
|
|
187
91
|
const resolveSubagentName = (args) => args.subagent;
|
|
188
|
-
toolMap.set("
|
|
189
|
-
...
|
|
190
|
-
handler:
|
|
92
|
+
toolMap.set("Subagent", {
|
|
93
|
+
...createSubagentTool(options.subagents),
|
|
94
|
+
handler: createSubagentHandler(options.subagents),
|
|
191
95
|
...subagentHooksMap.size > 0 && {
|
|
192
96
|
hooks: {
|
|
193
97
|
onPreToolUse: async (ctx) => {
|
|
@@ -206,24 +110,6 @@ function createToolRouter(options) {
|
|
|
206
110
|
}
|
|
207
111
|
});
|
|
208
112
|
}
|
|
209
|
-
if (options.buildInTools) {
|
|
210
|
-
for (const [key, value] of Object.entries(options.buildInTools)) {
|
|
211
|
-
if (key === bashTool.name) {
|
|
212
|
-
toolMap.set(key, {
|
|
213
|
-
...buildIntoolDefinitions[key],
|
|
214
|
-
description: createBashToolDescription({
|
|
215
|
-
fileTree: options.fileTree
|
|
216
|
-
}),
|
|
217
|
-
handler: value
|
|
218
|
-
});
|
|
219
|
-
} else {
|
|
220
|
-
toolMap.set(key, {
|
|
221
|
-
...buildIntoolDefinitions[key],
|
|
222
|
-
handler: value
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
113
|
async function processToolCall(toolCall, turn, handlerContext) {
|
|
228
114
|
const startTime = Date.now();
|
|
229
115
|
const tool = toolMap.get(toolCall.name);
|
|
@@ -239,6 +125,7 @@ function createToolRouter(options) {
|
|
|
239
125
|
await appendToolResult({
|
|
240
126
|
threadId: options.threadId,
|
|
241
127
|
toolCallId: toolCall.id,
|
|
128
|
+
toolName: toolCall.name,
|
|
242
129
|
content: JSON.stringify({
|
|
243
130
|
skipped: true,
|
|
244
131
|
reason: "Skipped by PreToolUse hook"
|
|
@@ -260,6 +147,7 @@ function createToolRouter(options) {
|
|
|
260
147
|
await appendToolResult({
|
|
261
148
|
threadId: options.threadId,
|
|
262
149
|
toolCallId: toolCall.id,
|
|
150
|
+
toolName: toolCall.name,
|
|
263
151
|
content: JSON.stringify({
|
|
264
152
|
skipped: true,
|
|
265
153
|
reason: "Skipped by tool PreToolUse hook"
|
|
@@ -273,14 +161,22 @@ function createToolRouter(options) {
|
|
|
273
161
|
}
|
|
274
162
|
let result;
|
|
275
163
|
let content;
|
|
164
|
+
let resultAppended = false;
|
|
276
165
|
try {
|
|
277
166
|
if (tool) {
|
|
167
|
+
const enrichedContext = {
|
|
168
|
+
...handlerContext ?? {},
|
|
169
|
+
threadId: options.threadId,
|
|
170
|
+
toolCallId: toolCall.id,
|
|
171
|
+
toolName: toolCall.name
|
|
172
|
+
};
|
|
278
173
|
const response = await tool.handler(
|
|
279
174
|
effectiveArgs,
|
|
280
|
-
|
|
175
|
+
enrichedContext
|
|
281
176
|
);
|
|
282
177
|
result = response.data;
|
|
283
178
|
content = response.toolResponse;
|
|
179
|
+
resultAppended = response.resultAppended === true;
|
|
284
180
|
} else {
|
|
285
181
|
result = { error: `Unknown tool: ${toolCall.name}` };
|
|
286
182
|
content = JSON.stringify(result, null, 2);
|
|
@@ -326,11 +222,14 @@ function createToolRouter(options) {
|
|
|
326
222
|
throw error;
|
|
327
223
|
}
|
|
328
224
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
225
|
+
if (!resultAppended) {
|
|
226
|
+
await appendToolResult({
|
|
227
|
+
threadId: options.threadId,
|
|
228
|
+
toolCallId: toolCall.id,
|
|
229
|
+
toolName: toolCall.name,
|
|
230
|
+
content
|
|
231
|
+
});
|
|
232
|
+
}
|
|
334
233
|
const toolResult = {
|
|
335
234
|
toolCallId: toolCall.id,
|
|
336
235
|
name: toolCall.name,
|
|
@@ -360,11 +259,11 @@ function createToolRouter(options) {
|
|
|
360
259
|
return {
|
|
361
260
|
// --- Methods from registry ---
|
|
362
261
|
hasTools() {
|
|
363
|
-
return toolMap.
|
|
262
|
+
return Array.from(toolMap.values()).some(isEnabled);
|
|
364
263
|
},
|
|
365
264
|
parseToolCall(toolCall) {
|
|
366
265
|
const tool = toolMap.get(toolCall.name);
|
|
367
|
-
if (!tool) {
|
|
266
|
+
if (!tool || !isEnabled(tool)) {
|
|
368
267
|
throw new Error(`Tool ${toolCall.name} not found`);
|
|
369
268
|
}
|
|
370
269
|
const parsedArgs = tool.schema.parse(toolCall.args);
|
|
@@ -375,13 +274,14 @@ function createToolRouter(options) {
|
|
|
375
274
|
};
|
|
376
275
|
},
|
|
377
276
|
hasTool(name) {
|
|
378
|
-
|
|
277
|
+
const tool = toolMap.get(name);
|
|
278
|
+
return tool !== void 0 && isEnabled(tool);
|
|
379
279
|
},
|
|
380
280
|
getToolNames() {
|
|
381
|
-
return Array.from(toolMap.
|
|
281
|
+
return Array.from(toolMap.entries()).filter(([, tool]) => isEnabled(tool)).map(([name]) => name);
|
|
382
282
|
},
|
|
383
283
|
getToolDefinitions() {
|
|
384
|
-
return Array.from(toolMap).map(([name, tool]) => ({
|
|
284
|
+
return Array.from(toolMap).filter(([, tool]) => isEnabled(tool)).map(([name, tool]) => ({
|
|
385
285
|
name,
|
|
386
286
|
description: tool.description,
|
|
387
287
|
schema: tool.schema,
|
|
@@ -420,19 +320,28 @@ function createToolRouter(options) {
|
|
|
420
320
|
}
|
|
421
321
|
const handlerContext = context?.handlerContext ?? {};
|
|
422
322
|
const processOne = async (toolCall) => {
|
|
323
|
+
const enrichedContext = {
|
|
324
|
+
...handlerContext ?? {},
|
|
325
|
+
threadId: options.threadId,
|
|
326
|
+
toolCallId: toolCall.id,
|
|
327
|
+
toolName: toolCall.name
|
|
328
|
+
};
|
|
423
329
|
const response = await handler(
|
|
424
330
|
toolCall.args,
|
|
425
|
-
|
|
331
|
+
enrichedContext
|
|
426
332
|
);
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
333
|
+
if (!response.resultAppended) {
|
|
334
|
+
await appendToolResult({
|
|
335
|
+
threadId: options.threadId,
|
|
336
|
+
toolCallId: toolCall.id,
|
|
337
|
+
toolName: toolCall.name,
|
|
338
|
+
content: response.toolResponse
|
|
339
|
+
});
|
|
340
|
+
}
|
|
432
341
|
return {
|
|
433
342
|
toolCallId: toolCall.id,
|
|
434
343
|
name: toolCall.name,
|
|
435
|
-
data: response.data
|
|
344
|
+
data: response.data
|
|
436
345
|
};
|
|
437
346
|
};
|
|
438
347
|
if (options.parallel) {
|
|
@@ -469,51 +378,24 @@ function hasNoOtherToolCalls(toolCalls, excludeName) {
|
|
|
469
378
|
}
|
|
470
379
|
|
|
471
380
|
// src/lib/session.ts
|
|
472
|
-
async function resolvePrompt(prompt) {
|
|
473
|
-
if (typeof prompt === "function") {
|
|
474
|
-
return prompt();
|
|
475
|
-
}
|
|
476
|
-
return prompt;
|
|
477
|
-
}
|
|
478
381
|
var createSession = async ({
|
|
479
382
|
threadId,
|
|
480
383
|
agentName,
|
|
481
384
|
maxTurns = 50,
|
|
482
385
|
metadata = {},
|
|
483
386
|
runAgent,
|
|
484
|
-
|
|
485
|
-
instructionsPrompt,
|
|
387
|
+
threadOps,
|
|
486
388
|
buildContextMessage,
|
|
487
|
-
buildFileTree = async () => "",
|
|
488
389
|
subagents,
|
|
489
390
|
tools = {},
|
|
490
391
|
processToolsInParallel = true,
|
|
491
|
-
buildInTools = {},
|
|
492
392
|
hooks = {}
|
|
493
393
|
}) => {
|
|
494
|
-
const {
|
|
495
|
-
initializeThread,
|
|
496
|
-
appendHumanMessage,
|
|
497
|
-
parseToolCalls,
|
|
498
|
-
appendToolResult,
|
|
499
|
-
appendSystemMessage
|
|
500
|
-
} = workflow.proxyActivities({
|
|
501
|
-
startToCloseTimeout: "30m",
|
|
502
|
-
retry: {
|
|
503
|
-
maximumAttempts: 6,
|
|
504
|
-
initialInterval: "5s",
|
|
505
|
-
maximumInterval: "15m",
|
|
506
|
-
backoffCoefficient: 4
|
|
507
|
-
},
|
|
508
|
-
heartbeatTimeout: "5m"
|
|
509
|
-
});
|
|
510
|
-
const fileTree = await buildFileTree();
|
|
511
394
|
const toolRouter = createToolRouter({
|
|
512
395
|
tools,
|
|
396
|
+
appendToolResult: threadOps.appendToolResult,
|
|
513
397
|
threadId,
|
|
514
398
|
hooks,
|
|
515
|
-
buildInTools,
|
|
516
|
-
fileTree,
|
|
517
399
|
subagents,
|
|
518
400
|
parallel: processToolsInParallel
|
|
519
401
|
});
|
|
@@ -538,83 +420,41 @@ var createSession = async ({
|
|
|
538
420
|
});
|
|
539
421
|
}
|
|
540
422
|
stateManager.setTools(toolRouter.getToolDefinitions());
|
|
541
|
-
await initializeThread(threadId);
|
|
542
|
-
await
|
|
543
|
-
threadId,
|
|
544
|
-
[
|
|
545
|
-
await resolvePrompt(baseSystemPrompt),
|
|
546
|
-
await resolvePrompt(instructionsPrompt)
|
|
547
|
-
].join("\n")
|
|
548
|
-
);
|
|
549
|
-
await appendHumanMessage(threadId, await buildContextMessage());
|
|
423
|
+
await threadOps.initializeThread(threadId);
|
|
424
|
+
await threadOps.appendHumanMessage(threadId, await buildContextMessage());
|
|
550
425
|
let exitReason = "completed";
|
|
551
426
|
try {
|
|
552
427
|
while (stateManager.isRunning() && !stateManager.isTerminal() && stateManager.getTurns() < maxTurns) {
|
|
553
428
|
stateManager.incrementTurns();
|
|
554
429
|
const currentTurn = stateManager.getTurns();
|
|
555
|
-
const { message,
|
|
430
|
+
const { message, rawToolCalls } = await runAgent({
|
|
556
431
|
threadId,
|
|
557
432
|
agentName,
|
|
558
433
|
metadata
|
|
559
434
|
});
|
|
560
|
-
if (
|
|
435
|
+
if (!toolRouter.hasTools() || rawToolCalls.length === 0) {
|
|
561
436
|
stateManager.complete();
|
|
562
437
|
exitReason = "completed";
|
|
563
438
|
return message;
|
|
564
439
|
}
|
|
565
|
-
if (!toolRouter.hasTools()) {
|
|
566
|
-
stateManager.complete();
|
|
567
|
-
exitReason = "completed";
|
|
568
|
-
return message;
|
|
569
|
-
}
|
|
570
|
-
const rawToolCalls = await parseToolCalls(message);
|
|
571
440
|
const parsedToolCalls = [];
|
|
572
|
-
for (const tc of rawToolCalls
|
|
573
|
-
(tc2) => tc2.name !== "Task"
|
|
574
|
-
)) {
|
|
441
|
+
for (const tc of rawToolCalls) {
|
|
575
442
|
try {
|
|
576
443
|
parsedToolCalls.push(toolRouter.parseToolCall(tc));
|
|
577
444
|
} catch (error) {
|
|
578
|
-
await appendToolResult({
|
|
445
|
+
await threadOps.appendToolResult({
|
|
579
446
|
threadId,
|
|
580
447
|
toolCallId: tc.id ?? "",
|
|
448
|
+
toolName: tc.name,
|
|
581
449
|
content: JSON.stringify({
|
|
582
450
|
error: `Invalid tool call for "${tc.name}": ${error instanceof Error ? error.message : String(error)}`
|
|
583
451
|
})
|
|
584
452
|
});
|
|
585
453
|
}
|
|
586
454
|
}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
(tc2) => tc2.name === "Task"
|
|
591
|
-
)) {
|
|
592
|
-
try {
|
|
593
|
-
const parsedArgs = createTaskTool(subagents).schema.parse(
|
|
594
|
-
tc.args
|
|
595
|
-
);
|
|
596
|
-
taskToolCalls.push({
|
|
597
|
-
id: tc.id ?? "",
|
|
598
|
-
name: tc.name,
|
|
599
|
-
args: parsedArgs
|
|
600
|
-
});
|
|
601
|
-
} catch (error) {
|
|
602
|
-
await appendToolResult({
|
|
603
|
-
threadId,
|
|
604
|
-
toolCallId: tc.id ?? "",
|
|
605
|
-
content: JSON.stringify({
|
|
606
|
-
error: `Invalid tool call for "Task": ${error instanceof Error ? error.message : String(error)}`
|
|
607
|
-
})
|
|
608
|
-
});
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
await toolRouter.processToolCalls(
|
|
613
|
-
[...parsedToolCalls, ...taskToolCalls],
|
|
614
|
-
{
|
|
615
|
-
turn: currentTurn
|
|
616
|
-
}
|
|
617
|
-
);
|
|
455
|
+
await toolRouter.processToolCalls(parsedToolCalls, {
|
|
456
|
+
turn: currentTurn
|
|
457
|
+
});
|
|
618
458
|
if (stateManager.getStatus() === "WAITING_FOR_INPUT") {
|
|
619
459
|
exitReason = "waiting_for_input";
|
|
620
460
|
break;
|
|
@@ -633,6 +473,25 @@ var createSession = async ({
|
|
|
633
473
|
}
|
|
634
474
|
};
|
|
635
475
|
};
|
|
476
|
+
function proxyDefaultThreadOps(options) {
|
|
477
|
+
const activities = workflow.proxyActivities(
|
|
478
|
+
options ?? {
|
|
479
|
+
startToCloseTimeout: "30m",
|
|
480
|
+
retry: {
|
|
481
|
+
maximumAttempts: 6,
|
|
482
|
+
initialInterval: "5s",
|
|
483
|
+
maximumInterval: "15m",
|
|
484
|
+
backoffCoefficient: 4
|
|
485
|
+
},
|
|
486
|
+
heartbeatTimeout: "5m"
|
|
487
|
+
}
|
|
488
|
+
);
|
|
489
|
+
return {
|
|
490
|
+
initializeThread: activities.initializeThread,
|
|
491
|
+
appendHumanMessage: activities.appendHumanMessage,
|
|
492
|
+
appendToolResult: activities.appendToolResult
|
|
493
|
+
};
|
|
494
|
+
}
|
|
636
495
|
|
|
637
496
|
// src/lib/types.ts
|
|
638
497
|
function isTerminalStatus(status) {
|
|
@@ -735,7 +594,7 @@ function createAgentStateManager(initialState) {
|
|
|
735
594
|
tools = newTools.map((tool) => ({
|
|
736
595
|
name: tool.name,
|
|
737
596
|
description: tool.description,
|
|
738
|
-
schema:
|
|
597
|
+
schema: z3.z.toJSONSchema(tool.schema),
|
|
739
598
|
strict: tool.strict,
|
|
740
599
|
max_uses: tool.max_uses
|
|
741
600
|
}));
|
|
@@ -769,18 +628,18 @@ Usage notes:
|
|
|
769
628
|
* Use multiSelect: true to allow multiple answers to be selected for a question
|
|
770
629
|
* If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label
|
|
771
630
|
`,
|
|
772
|
-
schema:
|
|
773
|
-
questions:
|
|
774
|
-
|
|
775
|
-
question:
|
|
776
|
-
header:
|
|
777
|
-
options:
|
|
778
|
-
|
|
779
|
-
label:
|
|
780
|
-
description:
|
|
631
|
+
schema: z3__default.default.object({
|
|
632
|
+
questions: z3__default.default.array(
|
|
633
|
+
z3__default.default.object({
|
|
634
|
+
question: z3__default.default.string().describe("The full question text to display"),
|
|
635
|
+
header: z3__default.default.string().describe("Short label for the question (max 12 characters)"),
|
|
636
|
+
options: z3__default.default.array(
|
|
637
|
+
z3__default.default.object({
|
|
638
|
+
label: z3__default.default.string(),
|
|
639
|
+
description: z3__default.default.string()
|
|
781
640
|
})
|
|
782
641
|
).min(0).max(4).describe("Array of 0-4 choices, each with label and description"),
|
|
783
|
-
multiSelect:
|
|
642
|
+
multiSelect: z3__default.default.boolean().describe("If true, users can select multiple options")
|
|
784
643
|
})
|
|
785
644
|
)
|
|
786
645
|
}),
|
|
@@ -800,9 +659,9 @@ Examples:
|
|
|
800
659
|
- "**/*.test.ts" - Find all test files recursively
|
|
801
660
|
- "src/**/*.ts" - Find all TypeScript files in src directory
|
|
802
661
|
`,
|
|
803
|
-
schema:
|
|
804
|
-
pattern:
|
|
805
|
-
root:
|
|
662
|
+
schema: z3.z.object({
|
|
663
|
+
pattern: z3.z.string().describe("Glob pattern to match files against"),
|
|
664
|
+
root: z3.z.string().optional().describe("Optional root directory to search from")
|
|
806
665
|
}),
|
|
807
666
|
strict: true
|
|
808
667
|
};
|
|
@@ -820,13 +679,13 @@ Examples:
|
|
|
820
679
|
- Search for function definitions with "function.*handleClick"
|
|
821
680
|
- Search case-insensitively with ignoreCase: true
|
|
822
681
|
`,
|
|
823
|
-
schema:
|
|
824
|
-
pattern:
|
|
825
|
-
ignoreCase:
|
|
826
|
-
maxMatches:
|
|
827
|
-
includePatterns:
|
|
828
|
-
excludePatterns:
|
|
829
|
-
contextLines:
|
|
682
|
+
schema: z3.z.object({
|
|
683
|
+
pattern: z3.z.string().describe("Regex pattern to search for in file contents"),
|
|
684
|
+
ignoreCase: z3.z.boolean().optional().describe("Case-insensitive search (default: false)"),
|
|
685
|
+
maxMatches: z3.z.number().optional().describe("Maximum number of matches to return (default: 50)"),
|
|
686
|
+
includePatterns: z3.z.array(z3.z.string()).optional().describe("Glob patterns to include (e.g., ['*.ts', '*.js'])"),
|
|
687
|
+
excludePatterns: z3.z.array(z3.z.string()).optional().describe("Glob patterns to exclude (e.g., ['*.test.ts'])"),
|
|
688
|
+
contextLines: z3.z.number().optional().describe("Number of context lines to show around matches")
|
|
830
689
|
}),
|
|
831
690
|
strict: true
|
|
832
691
|
};
|
|
@@ -844,12 +703,12 @@ The tool returns the file content in an appropriate format:
|
|
|
844
703
|
- Images: Base64-encoded image data
|
|
845
704
|
- PDFs: Extracted text content
|
|
846
705
|
`,
|
|
847
|
-
schema:
|
|
848
|
-
path:
|
|
849
|
-
offset:
|
|
706
|
+
schema: z3.z.object({
|
|
707
|
+
path: z3.z.string().describe("Virtual path to the file to read"),
|
|
708
|
+
offset: z3.z.number().optional().describe(
|
|
850
709
|
"Line number to start reading from (1-indexed, for text files)"
|
|
851
710
|
),
|
|
852
|
-
limit:
|
|
711
|
+
limit: z3.z.number().optional().describe("Maximum number of lines to read (for text files)")
|
|
853
712
|
}),
|
|
854
713
|
strict: true
|
|
855
714
|
};
|
|
@@ -858,7 +717,7 @@ var writeTool = {
|
|
|
858
717
|
description: `Create or overwrite a file with new content.
|
|
859
718
|
|
|
860
719
|
Usage:
|
|
861
|
-
- Provide the absolute
|
|
720
|
+
- Provide the absolute path to the file
|
|
862
721
|
- The file will be created if it doesn't exist
|
|
863
722
|
- If the file exists, it will be completely overwritten
|
|
864
723
|
|
|
@@ -867,9 +726,9 @@ IMPORTANT:
|
|
|
867
726
|
- This is an atomic write operation - the entire file is replaced
|
|
868
727
|
- Path must be absolute (e.g., "/docs/readme.md", not "docs/readme.md")
|
|
869
728
|
`,
|
|
870
|
-
schema:
|
|
871
|
-
file_path:
|
|
872
|
-
content:
|
|
729
|
+
schema: z3.z.object({
|
|
730
|
+
file_path: z3.z.string().describe("The absolute path to the file to write"),
|
|
731
|
+
content: z3.z.string().describe("The content to write to the file")
|
|
873
732
|
}),
|
|
874
733
|
strict: true
|
|
875
734
|
};
|
|
@@ -889,18 +748,72 @@ IMPORTANT:
|
|
|
889
748
|
- The operation fails if old_string is not found
|
|
890
749
|
- old_string and new_string must be different
|
|
891
750
|
`,
|
|
892
|
-
schema:
|
|
893
|
-
file_path:
|
|
894
|
-
old_string:
|
|
895
|
-
new_string:
|
|
751
|
+
schema: z3.z.object({
|
|
752
|
+
file_path: z3.z.string().describe("The absolute virtual path to the file to modify"),
|
|
753
|
+
old_string: z3.z.string().describe("The exact text to replace"),
|
|
754
|
+
new_string: z3.z.string().describe(
|
|
896
755
|
"The text to replace it with (must be different from old_string)"
|
|
897
756
|
),
|
|
898
|
-
replace_all:
|
|
757
|
+
replace_all: z3.z.boolean().optional().describe(
|
|
899
758
|
"If true, replace all occurrences of old_string (default: false)"
|
|
900
759
|
)
|
|
901
760
|
}),
|
|
902
761
|
strict: true
|
|
903
762
|
};
|
|
763
|
+
var taskCreateTool = {
|
|
764
|
+
name: "TaskCreate",
|
|
765
|
+
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.
|
|
766
|
+
It also helps the user understand the progress of the task and overall progress of their requests.
|
|
767
|
+
|
|
768
|
+
## When to Use This Tool
|
|
769
|
+
|
|
770
|
+
Use this tool proactively in these scenarios:
|
|
771
|
+
|
|
772
|
+
- Complex multi-step tasks - When a task requires 3 or more distinct steps or actions
|
|
773
|
+
- Non-trivial and complex tasks - Tasks that require careful planning or multiple operations
|
|
774
|
+
- User explicitly requests todo list - When the user directly asks you to use the todo list
|
|
775
|
+
- User provides multiple tasks - When users provide a list of things to be done (numbered or comma-separated)
|
|
776
|
+
- After receiving new instructions - Immediately capture user requirements as tasks
|
|
777
|
+
- When you start working on a task - Mark it as in_progress BEFORE beginning work
|
|
778
|
+
- After completing a task - Mark it as completed and add any new follow-up tasks discovered during implementation
|
|
779
|
+
|
|
780
|
+
## When NOT to Use This Tool
|
|
781
|
+
|
|
782
|
+
Skip using this tool when:
|
|
783
|
+
- There is only a single, straightforward task
|
|
784
|
+
- The task is trivial and tracking it provides no organizational benefit
|
|
785
|
+
- The task can be completed in less than 3 trivial steps
|
|
786
|
+
- The task is purely conversational or informational
|
|
787
|
+
|
|
788
|
+
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.
|
|
789
|
+
|
|
790
|
+
## Task Fields
|
|
791
|
+
|
|
792
|
+
- **subject**: A brief, actionable title in imperative form (e.g., "Fix authentication bug in login flow")
|
|
793
|
+
- **description**: Detailed description of what needs to be done, including context and acceptance criteria
|
|
794
|
+
- **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.
|
|
795
|
+
|
|
796
|
+
**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\`.
|
|
797
|
+
|
|
798
|
+
## Tips
|
|
799
|
+
|
|
800
|
+
- Create tasks with clear, specific subjects that describe the outcome
|
|
801
|
+
- Include enough detail in the description for another agent to understand and complete the task
|
|
802
|
+
- After creating tasks, use TaskUpdate to set up dependencies (blocks/blockedBy) if needed
|
|
803
|
+
- Check TaskList first to avoid creating duplicate tasks`,
|
|
804
|
+
schema: z3__default.default.object({
|
|
805
|
+
subject: z3__default.default.string().describe(
|
|
806
|
+
'A brief, actionable title in imperative form (e.g., "Fix authentication bug in login flow")'
|
|
807
|
+
),
|
|
808
|
+
description: z3__default.default.string().describe(
|
|
809
|
+
"Detailed description of what needs to be done, including context and acceptance criteria"
|
|
810
|
+
),
|
|
811
|
+
activeForm: z3__default.default.string().describe(
|
|
812
|
+
'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.'
|
|
813
|
+
),
|
|
814
|
+
metadata: z3__default.default.record(z3__default.default.string(), z3__default.default.string()).describe("Arbitrary key-value pairs for tracking")
|
|
815
|
+
})
|
|
816
|
+
};
|
|
904
817
|
function createTaskCreateHandler(stateManager) {
|
|
905
818
|
return (args) => {
|
|
906
819
|
const task = {
|
|
@@ -923,8 +836,8 @@ function createTaskCreateHandler(stateManager) {
|
|
|
923
836
|
var taskGetTool = {
|
|
924
837
|
name: "TaskGet",
|
|
925
838
|
description: `Retrieve full task details including dependencies.`,
|
|
926
|
-
schema:
|
|
927
|
-
taskId:
|
|
839
|
+
schema: z3__default.default.object({
|
|
840
|
+
taskId: z3__default.default.string().describe("The ID of the task to get")
|
|
928
841
|
})
|
|
929
842
|
};
|
|
930
843
|
|
|
@@ -947,12 +860,12 @@ function createTaskGetHandler(stateManager) {
|
|
|
947
860
|
var taskListTool = {
|
|
948
861
|
name: "TaskList",
|
|
949
862
|
description: `List all tasks with current state.`,
|
|
950
|
-
schema:
|
|
863
|
+
schema: z3__default.default.object({})
|
|
951
864
|
};
|
|
952
865
|
|
|
953
866
|
// src/tools/task-list/handler.ts
|
|
954
867
|
function createTaskListHandler(stateManager) {
|
|
955
|
-
return (
|
|
868
|
+
return () => {
|
|
956
869
|
const taskList = stateManager.getTasks();
|
|
957
870
|
return {
|
|
958
871
|
toolResponse: JSON.stringify(taskList, null, 2),
|
|
@@ -963,11 +876,11 @@ function createTaskListHandler(stateManager) {
|
|
|
963
876
|
var taskUpdateTool = {
|
|
964
877
|
name: "TaskUpdate",
|
|
965
878
|
description: `Update status, add blockers, modify details.`,
|
|
966
|
-
schema:
|
|
967
|
-
taskId:
|
|
968
|
-
status:
|
|
969
|
-
addBlockedBy:
|
|
970
|
-
addBlocks:
|
|
879
|
+
schema: z3__default.default.object({
|
|
880
|
+
taskId: z3__default.default.string().describe("The ID of the task to get"),
|
|
881
|
+
status: z3__default.default.enum(["pending", "in_progress", "completed"]).describe("The status of the task"),
|
|
882
|
+
addBlockedBy: z3__default.default.array(z3__default.default.string()).describe("The IDs of the tasks that are blocking this task"),
|
|
883
|
+
addBlocks: z3__default.default.array(z3__default.default.string()).describe("The IDs of the tasks that this task is blocking")
|
|
971
884
|
})
|
|
972
885
|
};
|
|
973
886
|
|
|
@@ -1015,16 +928,44 @@ function createTaskUpdateHandler(stateManager) {
|
|
|
1015
928
|
};
|
|
1016
929
|
};
|
|
1017
930
|
}
|
|
931
|
+
var createBashToolDescription = ({
|
|
932
|
+
fileTree
|
|
933
|
+
}) => `Execute shell commands in a bash environment.
|
|
934
|
+
|
|
935
|
+
Use this tool to:
|
|
936
|
+
- Run shell commands (ls, cat, grep, find, etc.)
|
|
937
|
+
- Execute scripts and chain commands with pipes (|) or logical operators (&&, ||)
|
|
938
|
+
- Inspect files and directories
|
|
939
|
+
|
|
940
|
+
Current file tree:
|
|
941
|
+
${fileTree}`;
|
|
942
|
+
var bashTool = {
|
|
943
|
+
name: "Bash",
|
|
944
|
+
description: `Execute shell commands in a sandboxed bash environment.
|
|
945
|
+
|
|
946
|
+
Use this tool to:
|
|
947
|
+
- Run shell commands (ls, cat, grep, find, etc.)
|
|
948
|
+
- Execute scripts and chain commands with pipes (|) or logical operators (&&, ||)
|
|
949
|
+
- Inspect files and directories
|
|
950
|
+
`,
|
|
951
|
+
schema: z3__default.default.object({
|
|
952
|
+
command: z3__default.default.string().describe(
|
|
953
|
+
"The bash command to execute. Can include pipes (|), redirects (>, >>), logical operators (&&, ||), and shell features like command substitution $(...)."
|
|
954
|
+
)
|
|
955
|
+
}),
|
|
956
|
+
strict: true
|
|
957
|
+
};
|
|
1018
958
|
|
|
1019
959
|
exports.AGENT_HANDLER_NAMES = AGENT_HANDLER_NAMES;
|
|
1020
960
|
exports.askUserQuestionTool = askUserQuestionTool;
|
|
1021
961
|
exports.bashTool = bashTool;
|
|
1022
962
|
exports.createAgentStateManager = createAgentStateManager;
|
|
963
|
+
exports.createBashToolDescription = createBashToolDescription;
|
|
1023
964
|
exports.createSession = createSession;
|
|
965
|
+
exports.createSubagentTool = createSubagentTool;
|
|
1024
966
|
exports.createTaskCreateHandler = createTaskCreateHandler;
|
|
1025
967
|
exports.createTaskGetHandler = createTaskGetHandler;
|
|
1026
968
|
exports.createTaskListHandler = createTaskListHandler;
|
|
1027
|
-
exports.createTaskTool = createTaskTool;
|
|
1028
969
|
exports.createTaskUpdateHandler = createTaskUpdateHandler;
|
|
1029
970
|
exports.createToolRouter = createToolRouter;
|
|
1030
971
|
exports.defineSubagent = defineSubagent;
|
|
@@ -1034,6 +975,7 @@ exports.globTool = globTool;
|
|
|
1034
975
|
exports.grepTool = grepTool;
|
|
1035
976
|
exports.hasNoOtherToolCalls = hasNoOtherToolCalls;
|
|
1036
977
|
exports.isTerminalStatus = isTerminalStatus;
|
|
978
|
+
exports.proxyDefaultThreadOps = proxyDefaultThreadOps;
|
|
1037
979
|
exports.readTool = readTool;
|
|
1038
980
|
exports.taskCreateTool = taskCreateTool;
|
|
1039
981
|
exports.taskGetTool = taskGetTool;
|