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.js
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
1
|
import { defineQuery, proxyActivities, setHandler, uuid4, workflowInfo, executeChild } from '@temporalio/workflow';
|
|
2
|
-
import
|
|
2
|
+
import z3, { z } from 'zod';
|
|
3
3
|
|
|
4
4
|
// src/lib/session.ts
|
|
5
|
-
var
|
|
6
|
-
function
|
|
5
|
+
var SUBAGENT_TOOL = "Subagent";
|
|
6
|
+
function buildSubagentDescription(subagents) {
|
|
7
7
|
const subagentList = subagents.map((s) => `- **${s.name}**: ${s.description}`).join("\n");
|
|
8
|
-
return `Launch a new agent to handle complex
|
|
8
|
+
return `Launch a new agent to handle complex tasks autonomously.
|
|
9
9
|
|
|
10
|
-
The ${
|
|
10
|
+
The ${SUBAGENT_TOOL} tool launches specialized agents (subprocesses) that autonomously handle complex tasks. Each agent type has specific capabilities and tools available to it.
|
|
11
11
|
|
|
12
12
|
Available agent types:
|
|
13
13
|
|
|
14
14
|
${subagentList}
|
|
15
15
|
|
|
16
|
-
When using the ${
|
|
16
|
+
When using the ${SUBAGENT_TOOL} tool, you must specify a subagent parameter to select which agent type to use.
|
|
17
17
|
|
|
18
18
|
Usage notes:
|
|
19
19
|
|
|
20
20
|
- Always include a short description (3-5 words) summarizing what the agent will do
|
|
21
21
|
- Launch multiple agents concurrently whenever possible, to maximize performance; to do that, use a single message with multiple tool uses
|
|
22
|
-
- When the agent is done, it will return a single message back to you.
|
|
22
|
+
- When the agent is done, it will return a single message back to you.
|
|
23
23
|
- Each invocation starts fresh - provide a detailed task description with all necessary context.
|
|
24
24
|
- Provide clear, detailed prompts so the agent can work autonomously and return exactly the information you need.
|
|
25
25
|
- The agent's outputs should generally be trusted
|
|
26
26
|
- Clearly tell the agent what type of work you expect since it is not aware of the user's intent
|
|
27
27
|
- 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.`;
|
|
28
28
|
}
|
|
29
|
-
function
|
|
29
|
+
function createSubagentTool(subagents) {
|
|
30
30
|
if (subagents.length === 0) {
|
|
31
31
|
throw new Error("createTaskTool requires at least one subagent");
|
|
32
32
|
}
|
|
33
33
|
const names = subagents.map((s) => s.name);
|
|
34
34
|
return {
|
|
35
|
-
name:
|
|
36
|
-
description:
|
|
37
|
-
schema:
|
|
38
|
-
subagent:
|
|
39
|
-
description:
|
|
40
|
-
prompt:
|
|
35
|
+
name: SUBAGENT_TOOL,
|
|
36
|
+
description: buildSubagentDescription(subagents),
|
|
37
|
+
schema: z3.object({
|
|
38
|
+
subagent: z3.enum(names).describe("The type of subagent to launch"),
|
|
39
|
+
description: z3.string().describe("A short (3-5 word) description of the task"),
|
|
40
|
+
prompt: z3.string().describe("The task for the agent to perform")
|
|
41
41
|
})
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
|
-
function
|
|
44
|
+
function createSubagentHandler(subagents) {
|
|
45
45
|
const { workflowId: parentWorkflowId, taskQueue: parentTaskQueue } = workflowInfo();
|
|
46
46
|
return async (args) => {
|
|
47
47
|
const config = subagents.find((s) => s.name === args.subagent);
|
|
@@ -60,128 +60,32 @@ function createTaskHandler(subagents) {
|
|
|
60
60
|
args: [input],
|
|
61
61
|
taskQueue: config.taskQueue ?? parentTaskQueue
|
|
62
62
|
};
|
|
63
|
-
const
|
|
64
|
-
const validated = config.resultSchema ? config.resultSchema.parse(
|
|
65
|
-
const toolResponse = typeof validated === "string" ? validated : JSON.stringify(validated, null, 2);
|
|
63
|
+
const { toolResponse, data } = typeof config.workflow === "string" ? await executeChild(config.workflow, childOpts) : await executeChild(config.workflow, childOpts);
|
|
64
|
+
const validated = config.resultSchema ? config.resultSchema.parse(data) : null;
|
|
66
65
|
return {
|
|
67
66
|
toolResponse,
|
|
68
|
-
data:
|
|
69
|
-
result: validated,
|
|
70
|
-
childWorkflowId
|
|
71
|
-
}
|
|
67
|
+
data: validated
|
|
72
68
|
};
|
|
73
69
|
};
|
|
74
70
|
}
|
|
75
|
-
var createBashToolDescription = ({
|
|
76
|
-
fileTree
|
|
77
|
-
}) => `Execute shell commands in a bash environment.
|
|
78
|
-
|
|
79
|
-
Use this tool to:
|
|
80
|
-
- Run shell commands (ls, cat, grep, find, etc.)
|
|
81
|
-
- Execute scripts and chain commands with pipes (|) or logical operators (&&, ||)
|
|
82
|
-
- Inspect files and directories
|
|
83
|
-
|
|
84
|
-
Current file tree:
|
|
85
|
-
${fileTree}`;
|
|
86
|
-
var bashTool = {
|
|
87
|
-
name: "Bash",
|
|
88
|
-
description: `Execute shell commands in a sandboxed bash environment.
|
|
89
|
-
|
|
90
|
-
Use this tool to:
|
|
91
|
-
- Run shell commands (ls, cat, grep, find, etc.)
|
|
92
|
-
- Execute scripts and chain commands with pipes (|) or logical operators (&&, ||)
|
|
93
|
-
- Inspect files and directories
|
|
94
|
-
`,
|
|
95
|
-
schema: z5.object({
|
|
96
|
-
command: z5.string().describe(
|
|
97
|
-
"The bash command to execute. Can include pipes (|), redirects (>, >>), logical operators (&&, ||), and shell features like command substitution $(...)."
|
|
98
|
-
)
|
|
99
|
-
}),
|
|
100
|
-
strict: true
|
|
101
|
-
};
|
|
102
|
-
var taskCreateTool = {
|
|
103
|
-
name: "TaskCreate",
|
|
104
|
-
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.
|
|
105
|
-
It also helps the user understand the progress of the task and overall progress of their requests.
|
|
106
|
-
|
|
107
|
-
## When to Use This Tool
|
|
108
|
-
|
|
109
|
-
Use this tool proactively in these scenarios:
|
|
110
|
-
|
|
111
|
-
- Complex multi-step tasks - When a task requires 3 or more distinct steps or actions
|
|
112
|
-
- Non-trivial and complex tasks - Tasks that require careful planning or multiple operations
|
|
113
|
-
- User explicitly requests todo list - When the user directly asks you to use the todo list
|
|
114
|
-
- User provides multiple tasks - When users provide a list of things to be done (numbered or comma-separated)
|
|
115
|
-
- After receiving new instructions - Immediately capture user requirements as tasks
|
|
116
|
-
- When you start working on a task - Mark it as in_progress BEFORE beginning work
|
|
117
|
-
- After completing a task - Mark it as completed and add any new follow-up tasks discovered during implementation
|
|
118
|
-
|
|
119
|
-
## When NOT to Use This Tool
|
|
120
|
-
|
|
121
|
-
Skip using this tool when:
|
|
122
|
-
- There is only a single, straightforward task
|
|
123
|
-
- The task is trivial and tracking it provides no organizational benefit
|
|
124
|
-
- The task can be completed in less than 3 trivial steps
|
|
125
|
-
- The task is purely conversational or informational
|
|
126
|
-
|
|
127
|
-
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.
|
|
128
|
-
|
|
129
|
-
## Task Fields
|
|
130
|
-
|
|
131
|
-
- **subject**: A brief, actionable title in imperative form (e.g., "Fix authentication bug in login flow")
|
|
132
|
-
- **description**: Detailed description of what needs to be done, including context and acceptance criteria
|
|
133
|
-
- **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.
|
|
134
|
-
|
|
135
|
-
**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\`.
|
|
136
|
-
|
|
137
|
-
## Tips
|
|
138
|
-
|
|
139
|
-
- Create tasks with clear, specific subjects that describe the outcome
|
|
140
|
-
- Include enough detail in the description for another agent to understand and complete the task
|
|
141
|
-
- After creating tasks, use TaskUpdate to set up dependencies (blocks/blockedBy) if needed
|
|
142
|
-
- Check TaskList first to avoid creating duplicate tasks`,
|
|
143
|
-
schema: z5.object({
|
|
144
|
-
subject: z5.string().describe(
|
|
145
|
-
'A brief, actionable title in imperative form (e.g., "Fix authentication bug in login flow")'
|
|
146
|
-
),
|
|
147
|
-
description: z5.string().describe(
|
|
148
|
-
"Detailed description of what needs to be done, including context and acceptance criteria"
|
|
149
|
-
),
|
|
150
|
-
activeForm: z5.string().describe(
|
|
151
|
-
'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.'
|
|
152
|
-
),
|
|
153
|
-
metadata: z5.record(z5.string(), z5.string()).describe("Arbitrary key-value pairs for tracking")
|
|
154
|
-
})
|
|
155
|
-
};
|
|
156
71
|
|
|
157
72
|
// src/lib/tool-router.ts
|
|
158
|
-
var buildIntoolDefinitions = {
|
|
159
|
-
[bashTool.name]: bashTool,
|
|
160
|
-
[taskCreateTool.name]: taskCreateTool
|
|
161
|
-
};
|
|
162
73
|
function createToolRouter(options) {
|
|
163
|
-
const { appendToolResult } =
|
|
164
|
-
startToCloseTimeout: "2m",
|
|
165
|
-
retry: {
|
|
166
|
-
maximumAttempts: 3,
|
|
167
|
-
initialInterval: "5s",
|
|
168
|
-
maximumInterval: "15m",
|
|
169
|
-
backoffCoefficient: 4
|
|
170
|
-
}
|
|
171
|
-
});
|
|
74
|
+
const { appendToolResult } = options;
|
|
172
75
|
const toolMap = /* @__PURE__ */ new Map();
|
|
173
76
|
for (const [_key, tool] of Object.entries(options.tools)) {
|
|
174
77
|
toolMap.set(tool.name, tool);
|
|
175
78
|
}
|
|
79
|
+
const isEnabled = (tool) => tool.enabled !== false;
|
|
176
80
|
if (options.subagents) {
|
|
177
81
|
const subagentHooksMap = /* @__PURE__ */ new Map();
|
|
178
82
|
for (const s of options.subagents) {
|
|
179
83
|
if (s.hooks) subagentHooksMap.set(s.name, s.hooks);
|
|
180
84
|
}
|
|
181
85
|
const resolveSubagentName = (args) => args.subagent;
|
|
182
|
-
toolMap.set("
|
|
183
|
-
...
|
|
184
|
-
handler:
|
|
86
|
+
toolMap.set("Subagent", {
|
|
87
|
+
...createSubagentTool(options.subagents),
|
|
88
|
+
handler: createSubagentHandler(options.subagents),
|
|
185
89
|
...subagentHooksMap.size > 0 && {
|
|
186
90
|
hooks: {
|
|
187
91
|
onPreToolUse: async (ctx) => {
|
|
@@ -200,24 +104,6 @@ function createToolRouter(options) {
|
|
|
200
104
|
}
|
|
201
105
|
});
|
|
202
106
|
}
|
|
203
|
-
if (options.buildInTools) {
|
|
204
|
-
for (const [key, value] of Object.entries(options.buildInTools)) {
|
|
205
|
-
if (key === bashTool.name) {
|
|
206
|
-
toolMap.set(key, {
|
|
207
|
-
...buildIntoolDefinitions[key],
|
|
208
|
-
description: createBashToolDescription({
|
|
209
|
-
fileTree: options.fileTree
|
|
210
|
-
}),
|
|
211
|
-
handler: value
|
|
212
|
-
});
|
|
213
|
-
} else {
|
|
214
|
-
toolMap.set(key, {
|
|
215
|
-
...buildIntoolDefinitions[key],
|
|
216
|
-
handler: value
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
107
|
async function processToolCall(toolCall, turn, handlerContext) {
|
|
222
108
|
const startTime = Date.now();
|
|
223
109
|
const tool = toolMap.get(toolCall.name);
|
|
@@ -233,6 +119,7 @@ function createToolRouter(options) {
|
|
|
233
119
|
await appendToolResult({
|
|
234
120
|
threadId: options.threadId,
|
|
235
121
|
toolCallId: toolCall.id,
|
|
122
|
+
toolName: toolCall.name,
|
|
236
123
|
content: JSON.stringify({
|
|
237
124
|
skipped: true,
|
|
238
125
|
reason: "Skipped by PreToolUse hook"
|
|
@@ -254,6 +141,7 @@ function createToolRouter(options) {
|
|
|
254
141
|
await appendToolResult({
|
|
255
142
|
threadId: options.threadId,
|
|
256
143
|
toolCallId: toolCall.id,
|
|
144
|
+
toolName: toolCall.name,
|
|
257
145
|
content: JSON.stringify({
|
|
258
146
|
skipped: true,
|
|
259
147
|
reason: "Skipped by tool PreToolUse hook"
|
|
@@ -267,14 +155,22 @@ function createToolRouter(options) {
|
|
|
267
155
|
}
|
|
268
156
|
let result;
|
|
269
157
|
let content;
|
|
158
|
+
let resultAppended = false;
|
|
270
159
|
try {
|
|
271
160
|
if (tool) {
|
|
161
|
+
const enrichedContext = {
|
|
162
|
+
...handlerContext ?? {},
|
|
163
|
+
threadId: options.threadId,
|
|
164
|
+
toolCallId: toolCall.id,
|
|
165
|
+
toolName: toolCall.name
|
|
166
|
+
};
|
|
272
167
|
const response = await tool.handler(
|
|
273
168
|
effectiveArgs,
|
|
274
|
-
|
|
169
|
+
enrichedContext
|
|
275
170
|
);
|
|
276
171
|
result = response.data;
|
|
277
172
|
content = response.toolResponse;
|
|
173
|
+
resultAppended = response.resultAppended === true;
|
|
278
174
|
} else {
|
|
279
175
|
result = { error: `Unknown tool: ${toolCall.name}` };
|
|
280
176
|
content = JSON.stringify(result, null, 2);
|
|
@@ -320,11 +216,14 @@ function createToolRouter(options) {
|
|
|
320
216
|
throw error;
|
|
321
217
|
}
|
|
322
218
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
219
|
+
if (!resultAppended) {
|
|
220
|
+
await appendToolResult({
|
|
221
|
+
threadId: options.threadId,
|
|
222
|
+
toolCallId: toolCall.id,
|
|
223
|
+
toolName: toolCall.name,
|
|
224
|
+
content
|
|
225
|
+
});
|
|
226
|
+
}
|
|
328
227
|
const toolResult = {
|
|
329
228
|
toolCallId: toolCall.id,
|
|
330
229
|
name: toolCall.name,
|
|
@@ -354,11 +253,11 @@ function createToolRouter(options) {
|
|
|
354
253
|
return {
|
|
355
254
|
// --- Methods from registry ---
|
|
356
255
|
hasTools() {
|
|
357
|
-
return toolMap.
|
|
256
|
+
return Array.from(toolMap.values()).some(isEnabled);
|
|
358
257
|
},
|
|
359
258
|
parseToolCall(toolCall) {
|
|
360
259
|
const tool = toolMap.get(toolCall.name);
|
|
361
|
-
if (!tool) {
|
|
260
|
+
if (!tool || !isEnabled(tool)) {
|
|
362
261
|
throw new Error(`Tool ${toolCall.name} not found`);
|
|
363
262
|
}
|
|
364
263
|
const parsedArgs = tool.schema.parse(toolCall.args);
|
|
@@ -369,13 +268,14 @@ function createToolRouter(options) {
|
|
|
369
268
|
};
|
|
370
269
|
},
|
|
371
270
|
hasTool(name) {
|
|
372
|
-
|
|
271
|
+
const tool = toolMap.get(name);
|
|
272
|
+
return tool !== void 0 && isEnabled(tool);
|
|
373
273
|
},
|
|
374
274
|
getToolNames() {
|
|
375
|
-
return Array.from(toolMap.
|
|
275
|
+
return Array.from(toolMap.entries()).filter(([, tool]) => isEnabled(tool)).map(([name]) => name);
|
|
376
276
|
},
|
|
377
277
|
getToolDefinitions() {
|
|
378
|
-
return Array.from(toolMap).map(([name, tool]) => ({
|
|
278
|
+
return Array.from(toolMap).filter(([, tool]) => isEnabled(tool)).map(([name, tool]) => ({
|
|
379
279
|
name,
|
|
380
280
|
description: tool.description,
|
|
381
281
|
schema: tool.schema,
|
|
@@ -414,19 +314,28 @@ function createToolRouter(options) {
|
|
|
414
314
|
}
|
|
415
315
|
const handlerContext = context?.handlerContext ?? {};
|
|
416
316
|
const processOne = async (toolCall) => {
|
|
317
|
+
const enrichedContext = {
|
|
318
|
+
...handlerContext ?? {},
|
|
319
|
+
threadId: options.threadId,
|
|
320
|
+
toolCallId: toolCall.id,
|
|
321
|
+
toolName: toolCall.name
|
|
322
|
+
};
|
|
417
323
|
const response = await handler(
|
|
418
324
|
toolCall.args,
|
|
419
|
-
|
|
325
|
+
enrichedContext
|
|
420
326
|
);
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
327
|
+
if (!response.resultAppended) {
|
|
328
|
+
await appendToolResult({
|
|
329
|
+
threadId: options.threadId,
|
|
330
|
+
toolCallId: toolCall.id,
|
|
331
|
+
toolName: toolCall.name,
|
|
332
|
+
content: response.toolResponse
|
|
333
|
+
});
|
|
334
|
+
}
|
|
426
335
|
return {
|
|
427
336
|
toolCallId: toolCall.id,
|
|
428
337
|
name: toolCall.name,
|
|
429
|
-
data: response.data
|
|
338
|
+
data: response.data
|
|
430
339
|
};
|
|
431
340
|
};
|
|
432
341
|
if (options.parallel) {
|
|
@@ -463,51 +372,24 @@ function hasNoOtherToolCalls(toolCalls, excludeName) {
|
|
|
463
372
|
}
|
|
464
373
|
|
|
465
374
|
// src/lib/session.ts
|
|
466
|
-
async function resolvePrompt(prompt) {
|
|
467
|
-
if (typeof prompt === "function") {
|
|
468
|
-
return prompt();
|
|
469
|
-
}
|
|
470
|
-
return prompt;
|
|
471
|
-
}
|
|
472
375
|
var createSession = async ({
|
|
473
376
|
threadId,
|
|
474
377
|
agentName,
|
|
475
378
|
maxTurns = 50,
|
|
476
379
|
metadata = {},
|
|
477
380
|
runAgent,
|
|
478
|
-
|
|
479
|
-
instructionsPrompt,
|
|
381
|
+
threadOps,
|
|
480
382
|
buildContextMessage,
|
|
481
|
-
buildFileTree = async () => "",
|
|
482
383
|
subagents,
|
|
483
384
|
tools = {},
|
|
484
385
|
processToolsInParallel = true,
|
|
485
|
-
buildInTools = {},
|
|
486
386
|
hooks = {}
|
|
487
387
|
}) => {
|
|
488
|
-
const {
|
|
489
|
-
initializeThread,
|
|
490
|
-
appendHumanMessage,
|
|
491
|
-
parseToolCalls,
|
|
492
|
-
appendToolResult,
|
|
493
|
-
appendSystemMessage
|
|
494
|
-
} = proxyActivities({
|
|
495
|
-
startToCloseTimeout: "30m",
|
|
496
|
-
retry: {
|
|
497
|
-
maximumAttempts: 6,
|
|
498
|
-
initialInterval: "5s",
|
|
499
|
-
maximumInterval: "15m",
|
|
500
|
-
backoffCoefficient: 4
|
|
501
|
-
},
|
|
502
|
-
heartbeatTimeout: "5m"
|
|
503
|
-
});
|
|
504
|
-
const fileTree = await buildFileTree();
|
|
505
388
|
const toolRouter = createToolRouter({
|
|
506
389
|
tools,
|
|
390
|
+
appendToolResult: threadOps.appendToolResult,
|
|
507
391
|
threadId,
|
|
508
392
|
hooks,
|
|
509
|
-
buildInTools,
|
|
510
|
-
fileTree,
|
|
511
393
|
subagents,
|
|
512
394
|
parallel: processToolsInParallel
|
|
513
395
|
});
|
|
@@ -532,83 +414,41 @@ var createSession = async ({
|
|
|
532
414
|
});
|
|
533
415
|
}
|
|
534
416
|
stateManager.setTools(toolRouter.getToolDefinitions());
|
|
535
|
-
await initializeThread(threadId);
|
|
536
|
-
await
|
|
537
|
-
threadId,
|
|
538
|
-
[
|
|
539
|
-
await resolvePrompt(baseSystemPrompt),
|
|
540
|
-
await resolvePrompt(instructionsPrompt)
|
|
541
|
-
].join("\n")
|
|
542
|
-
);
|
|
543
|
-
await appendHumanMessage(threadId, await buildContextMessage());
|
|
417
|
+
await threadOps.initializeThread(threadId);
|
|
418
|
+
await threadOps.appendHumanMessage(threadId, await buildContextMessage());
|
|
544
419
|
let exitReason = "completed";
|
|
545
420
|
try {
|
|
546
421
|
while (stateManager.isRunning() && !stateManager.isTerminal() && stateManager.getTurns() < maxTurns) {
|
|
547
422
|
stateManager.incrementTurns();
|
|
548
423
|
const currentTurn = stateManager.getTurns();
|
|
549
|
-
const { message,
|
|
424
|
+
const { message, rawToolCalls } = await runAgent({
|
|
550
425
|
threadId,
|
|
551
426
|
agentName,
|
|
552
427
|
metadata
|
|
553
428
|
});
|
|
554
|
-
if (
|
|
429
|
+
if (!toolRouter.hasTools() || rawToolCalls.length === 0) {
|
|
555
430
|
stateManager.complete();
|
|
556
431
|
exitReason = "completed";
|
|
557
432
|
return message;
|
|
558
433
|
}
|
|
559
|
-
if (!toolRouter.hasTools()) {
|
|
560
|
-
stateManager.complete();
|
|
561
|
-
exitReason = "completed";
|
|
562
|
-
return message;
|
|
563
|
-
}
|
|
564
|
-
const rawToolCalls = await parseToolCalls(message);
|
|
565
434
|
const parsedToolCalls = [];
|
|
566
|
-
for (const tc of rawToolCalls
|
|
567
|
-
(tc2) => tc2.name !== "Task"
|
|
568
|
-
)) {
|
|
435
|
+
for (const tc of rawToolCalls) {
|
|
569
436
|
try {
|
|
570
437
|
parsedToolCalls.push(toolRouter.parseToolCall(tc));
|
|
571
438
|
} catch (error) {
|
|
572
|
-
await appendToolResult({
|
|
439
|
+
await threadOps.appendToolResult({
|
|
573
440
|
threadId,
|
|
574
441
|
toolCallId: tc.id ?? "",
|
|
442
|
+
toolName: tc.name,
|
|
575
443
|
content: JSON.stringify({
|
|
576
444
|
error: `Invalid tool call for "${tc.name}": ${error instanceof Error ? error.message : String(error)}`
|
|
577
445
|
})
|
|
578
446
|
});
|
|
579
447
|
}
|
|
580
448
|
}
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
(tc2) => tc2.name === "Task"
|
|
585
|
-
)) {
|
|
586
|
-
try {
|
|
587
|
-
const parsedArgs = createTaskTool(subagents).schema.parse(
|
|
588
|
-
tc.args
|
|
589
|
-
);
|
|
590
|
-
taskToolCalls.push({
|
|
591
|
-
id: tc.id ?? "",
|
|
592
|
-
name: tc.name,
|
|
593
|
-
args: parsedArgs
|
|
594
|
-
});
|
|
595
|
-
} catch (error) {
|
|
596
|
-
await appendToolResult({
|
|
597
|
-
threadId,
|
|
598
|
-
toolCallId: tc.id ?? "",
|
|
599
|
-
content: JSON.stringify({
|
|
600
|
-
error: `Invalid tool call for "Task": ${error instanceof Error ? error.message : String(error)}`
|
|
601
|
-
})
|
|
602
|
-
});
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
await toolRouter.processToolCalls(
|
|
607
|
-
[...parsedToolCalls, ...taskToolCalls],
|
|
608
|
-
{
|
|
609
|
-
turn: currentTurn
|
|
610
|
-
}
|
|
611
|
-
);
|
|
449
|
+
await toolRouter.processToolCalls(parsedToolCalls, {
|
|
450
|
+
turn: currentTurn
|
|
451
|
+
});
|
|
612
452
|
if (stateManager.getStatus() === "WAITING_FOR_INPUT") {
|
|
613
453
|
exitReason = "waiting_for_input";
|
|
614
454
|
break;
|
|
@@ -627,6 +467,25 @@ var createSession = async ({
|
|
|
627
467
|
}
|
|
628
468
|
};
|
|
629
469
|
};
|
|
470
|
+
function proxyDefaultThreadOps(options) {
|
|
471
|
+
const activities = proxyActivities(
|
|
472
|
+
options ?? {
|
|
473
|
+
startToCloseTimeout: "30m",
|
|
474
|
+
retry: {
|
|
475
|
+
maximumAttempts: 6,
|
|
476
|
+
initialInterval: "5s",
|
|
477
|
+
maximumInterval: "15m",
|
|
478
|
+
backoffCoefficient: 4
|
|
479
|
+
},
|
|
480
|
+
heartbeatTimeout: "5m"
|
|
481
|
+
}
|
|
482
|
+
);
|
|
483
|
+
return {
|
|
484
|
+
initializeThread: activities.initializeThread,
|
|
485
|
+
appendHumanMessage: activities.appendHumanMessage,
|
|
486
|
+
appendToolResult: activities.appendToolResult
|
|
487
|
+
};
|
|
488
|
+
}
|
|
630
489
|
|
|
631
490
|
// src/lib/types.ts
|
|
632
491
|
function isTerminalStatus(status) {
|
|
@@ -763,18 +622,18 @@ Usage notes:
|
|
|
763
622
|
* Use multiSelect: true to allow multiple answers to be selected for a question
|
|
764
623
|
* If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label
|
|
765
624
|
`,
|
|
766
|
-
schema:
|
|
767
|
-
questions:
|
|
768
|
-
|
|
769
|
-
question:
|
|
770
|
-
header:
|
|
771
|
-
options:
|
|
772
|
-
|
|
773
|
-
label:
|
|
774
|
-
description:
|
|
625
|
+
schema: z3.object({
|
|
626
|
+
questions: z3.array(
|
|
627
|
+
z3.object({
|
|
628
|
+
question: z3.string().describe("The full question text to display"),
|
|
629
|
+
header: z3.string().describe("Short label for the question (max 12 characters)"),
|
|
630
|
+
options: z3.array(
|
|
631
|
+
z3.object({
|
|
632
|
+
label: z3.string(),
|
|
633
|
+
description: z3.string()
|
|
775
634
|
})
|
|
776
635
|
).min(0).max(4).describe("Array of 0-4 choices, each with label and description"),
|
|
777
|
-
multiSelect:
|
|
636
|
+
multiSelect: z3.boolean().describe("If true, users can select multiple options")
|
|
778
637
|
})
|
|
779
638
|
)
|
|
780
639
|
}),
|
|
@@ -852,7 +711,7 @@ var writeTool = {
|
|
|
852
711
|
description: `Create or overwrite a file with new content.
|
|
853
712
|
|
|
854
713
|
Usage:
|
|
855
|
-
- Provide the absolute
|
|
714
|
+
- Provide the absolute path to the file
|
|
856
715
|
- The file will be created if it doesn't exist
|
|
857
716
|
- If the file exists, it will be completely overwritten
|
|
858
717
|
|
|
@@ -862,7 +721,7 @@ IMPORTANT:
|
|
|
862
721
|
- Path must be absolute (e.g., "/docs/readme.md", not "docs/readme.md")
|
|
863
722
|
`,
|
|
864
723
|
schema: z.object({
|
|
865
|
-
file_path: z.string().describe("The absolute
|
|
724
|
+
file_path: z.string().describe("The absolute path to the file to write"),
|
|
866
725
|
content: z.string().describe("The content to write to the file")
|
|
867
726
|
}),
|
|
868
727
|
strict: true
|
|
@@ -895,6 +754,60 @@ IMPORTANT:
|
|
|
895
754
|
}),
|
|
896
755
|
strict: true
|
|
897
756
|
};
|
|
757
|
+
var taskCreateTool = {
|
|
758
|
+
name: "TaskCreate",
|
|
759
|
+
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.
|
|
760
|
+
It also helps the user understand the progress of the task and overall progress of their requests.
|
|
761
|
+
|
|
762
|
+
## When to Use This Tool
|
|
763
|
+
|
|
764
|
+
Use this tool proactively in these scenarios:
|
|
765
|
+
|
|
766
|
+
- Complex multi-step tasks - When a task requires 3 or more distinct steps or actions
|
|
767
|
+
- Non-trivial and complex tasks - Tasks that require careful planning or multiple operations
|
|
768
|
+
- User explicitly requests todo list - When the user directly asks you to use the todo list
|
|
769
|
+
- User provides multiple tasks - When users provide a list of things to be done (numbered or comma-separated)
|
|
770
|
+
- After receiving new instructions - Immediately capture user requirements as tasks
|
|
771
|
+
- When you start working on a task - Mark it as in_progress BEFORE beginning work
|
|
772
|
+
- After completing a task - Mark it as completed and add any new follow-up tasks discovered during implementation
|
|
773
|
+
|
|
774
|
+
## When NOT to Use This Tool
|
|
775
|
+
|
|
776
|
+
Skip using this tool when:
|
|
777
|
+
- There is only a single, straightforward task
|
|
778
|
+
- The task is trivial and tracking it provides no organizational benefit
|
|
779
|
+
- The task can be completed in less than 3 trivial steps
|
|
780
|
+
- The task is purely conversational or informational
|
|
781
|
+
|
|
782
|
+
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.
|
|
783
|
+
|
|
784
|
+
## Task Fields
|
|
785
|
+
|
|
786
|
+
- **subject**: A brief, actionable title in imperative form (e.g., "Fix authentication bug in login flow")
|
|
787
|
+
- **description**: Detailed description of what needs to be done, including context and acceptance criteria
|
|
788
|
+
- **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.
|
|
789
|
+
|
|
790
|
+
**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\`.
|
|
791
|
+
|
|
792
|
+
## Tips
|
|
793
|
+
|
|
794
|
+
- Create tasks with clear, specific subjects that describe the outcome
|
|
795
|
+
- Include enough detail in the description for another agent to understand and complete the task
|
|
796
|
+
- After creating tasks, use TaskUpdate to set up dependencies (blocks/blockedBy) if needed
|
|
797
|
+
- Check TaskList first to avoid creating duplicate tasks`,
|
|
798
|
+
schema: z3.object({
|
|
799
|
+
subject: z3.string().describe(
|
|
800
|
+
'A brief, actionable title in imperative form (e.g., "Fix authentication bug in login flow")'
|
|
801
|
+
),
|
|
802
|
+
description: z3.string().describe(
|
|
803
|
+
"Detailed description of what needs to be done, including context and acceptance criteria"
|
|
804
|
+
),
|
|
805
|
+
activeForm: z3.string().describe(
|
|
806
|
+
'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.'
|
|
807
|
+
),
|
|
808
|
+
metadata: z3.record(z3.string(), z3.string()).describe("Arbitrary key-value pairs for tracking")
|
|
809
|
+
})
|
|
810
|
+
};
|
|
898
811
|
function createTaskCreateHandler(stateManager) {
|
|
899
812
|
return (args) => {
|
|
900
813
|
const task = {
|
|
@@ -917,8 +830,8 @@ function createTaskCreateHandler(stateManager) {
|
|
|
917
830
|
var taskGetTool = {
|
|
918
831
|
name: "TaskGet",
|
|
919
832
|
description: `Retrieve full task details including dependencies.`,
|
|
920
|
-
schema:
|
|
921
|
-
taskId:
|
|
833
|
+
schema: z3.object({
|
|
834
|
+
taskId: z3.string().describe("The ID of the task to get")
|
|
922
835
|
})
|
|
923
836
|
};
|
|
924
837
|
|
|
@@ -941,12 +854,12 @@ function createTaskGetHandler(stateManager) {
|
|
|
941
854
|
var taskListTool = {
|
|
942
855
|
name: "TaskList",
|
|
943
856
|
description: `List all tasks with current state.`,
|
|
944
|
-
schema:
|
|
857
|
+
schema: z3.object({})
|
|
945
858
|
};
|
|
946
859
|
|
|
947
860
|
// src/tools/task-list/handler.ts
|
|
948
861
|
function createTaskListHandler(stateManager) {
|
|
949
|
-
return (
|
|
862
|
+
return () => {
|
|
950
863
|
const taskList = stateManager.getTasks();
|
|
951
864
|
return {
|
|
952
865
|
toolResponse: JSON.stringify(taskList, null, 2),
|
|
@@ -957,11 +870,11 @@ function createTaskListHandler(stateManager) {
|
|
|
957
870
|
var taskUpdateTool = {
|
|
958
871
|
name: "TaskUpdate",
|
|
959
872
|
description: `Update status, add blockers, modify details.`,
|
|
960
|
-
schema:
|
|
961
|
-
taskId:
|
|
962
|
-
status:
|
|
963
|
-
addBlockedBy:
|
|
964
|
-
addBlocks:
|
|
873
|
+
schema: z3.object({
|
|
874
|
+
taskId: z3.string().describe("The ID of the task to get"),
|
|
875
|
+
status: z3.enum(["pending", "in_progress", "completed"]).describe("The status of the task"),
|
|
876
|
+
addBlockedBy: z3.array(z3.string()).describe("The IDs of the tasks that are blocking this task"),
|
|
877
|
+
addBlocks: z3.array(z3.string()).describe("The IDs of the tasks that this task is blocking")
|
|
965
878
|
})
|
|
966
879
|
};
|
|
967
880
|
|
|
@@ -1009,7 +922,34 @@ function createTaskUpdateHandler(stateManager) {
|
|
|
1009
922
|
};
|
|
1010
923
|
};
|
|
1011
924
|
}
|
|
925
|
+
var createBashToolDescription = ({
|
|
926
|
+
fileTree
|
|
927
|
+
}) => `Execute shell commands in a bash environment.
|
|
928
|
+
|
|
929
|
+
Use this tool to:
|
|
930
|
+
- Run shell commands (ls, cat, grep, find, etc.)
|
|
931
|
+
- Execute scripts and chain commands with pipes (|) or logical operators (&&, ||)
|
|
932
|
+
- Inspect files and directories
|
|
933
|
+
|
|
934
|
+
Current file tree:
|
|
935
|
+
${fileTree}`;
|
|
936
|
+
var bashTool = {
|
|
937
|
+
name: "Bash",
|
|
938
|
+
description: `Execute shell commands in a sandboxed bash environment.
|
|
939
|
+
|
|
940
|
+
Use this tool to:
|
|
941
|
+
- Run shell commands (ls, cat, grep, find, etc.)
|
|
942
|
+
- Execute scripts and chain commands with pipes (|) or logical operators (&&, ||)
|
|
943
|
+
- Inspect files and directories
|
|
944
|
+
`,
|
|
945
|
+
schema: z3.object({
|
|
946
|
+
command: z3.string().describe(
|
|
947
|
+
"The bash command to execute. Can include pipes (|), redirects (>, >>), logical operators (&&, ||), and shell features like command substitution $(...)."
|
|
948
|
+
)
|
|
949
|
+
}),
|
|
950
|
+
strict: true
|
|
951
|
+
};
|
|
1012
952
|
|
|
1013
|
-
export { AGENT_HANDLER_NAMES, askUserQuestionTool, bashTool, createAgentStateManager, createSession, createTaskCreateHandler, createTaskGetHandler, createTaskListHandler,
|
|
953
|
+
export { AGENT_HANDLER_NAMES, askUserQuestionTool, bashTool, createAgentStateManager, createBashToolDescription, createSession, createSubagentTool, createTaskCreateHandler, createTaskGetHandler, createTaskListHandler, createTaskUpdateHandler, createToolRouter, defineSubagent, defineTool, editTool, globTool, grepTool, hasNoOtherToolCalls, isTerminalStatus, proxyDefaultThreadOps, readTool, taskCreateTool, taskGetTool, taskListTool, taskUpdateTool, writeTool };
|
|
1014
954
|
//# sourceMappingURL=workflow.js.map
|
|
1015
955
|
//# sourceMappingURL=workflow.js.map
|