zeitlich 0.2.1 → 0.2.2

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/dist/workflow.js CHANGED
@@ -1,5 +1,5 @@
1
- import { defineQuery, proxyActivities, setHandler, workflowInfo, uuid4, executeChild } from '@temporalio/workflow';
2
- import z4, { z } from 'zod';
1
+ import { defineQuery, proxyActivities, setHandler, uuid4, workflowInfo, executeChild } from '@temporalio/workflow';
2
+ import z5, { z } from 'zod';
3
3
 
4
4
  // src/lib/session.ts
5
5
  var TASK_TOOL = "Task";
@@ -34,10 +34,10 @@ function createTaskTool(subagents) {
34
34
  return {
35
35
  name: TASK_TOOL,
36
36
  description: buildTaskDescription(subagents),
37
- schema: z4.object({
38
- subagent: z4.enum(names).describe("The type of subagent to launch"),
39
- description: z4.string().describe("A short (3-5 word) description of the task"),
40
- prompt: z4.string().describe("The task for the agent to perform")
37
+ schema: z5.object({
38
+ subagent: z5.enum(names).describe("The type of subagent to launch"),
39
+ description: z5.string().describe("A short (3-5 word) description of the task"),
40
+ prompt: z5.string().describe("The task for the agent to perform")
41
41
  })
42
42
  };
43
43
  }
@@ -51,16 +51,21 @@ function createTaskHandler(subagents) {
51
51
  );
52
52
  }
53
53
  const childWorkflowId = `${parentWorkflowId}-${args.subagent}-${uuid4()}`;
54
- const childResult = await executeChild(config.workflowType, {
54
+ const input = {
55
+ prompt: args.prompt,
56
+ ...config.context && { context: config.context }
57
+ };
58
+ const childOpts = {
55
59
  workflowId: childWorkflowId,
56
- args: [{ prompt: args.prompt }],
60
+ args: [input],
57
61
  taskQueue: config.taskQueue ?? parentTaskQueue
58
- });
62
+ };
63
+ const childResult = typeof config.workflow === "string" ? await executeChild(config.workflow, childOpts) : await executeChild(config.workflow, childOpts);
59
64
  const validated = config.resultSchema ? config.resultSchema.parse(childResult) : childResult;
60
- const content = typeof validated === "string" ? validated : JSON.stringify(validated, null, 2);
65
+ const toolResponse = typeof validated === "string" ? validated : JSON.stringify(validated, null, 2);
61
66
  return {
62
- content,
63
- result: {
67
+ toolResponse,
68
+ data: {
64
69
  result: validated,
65
70
  childWorkflowId
66
71
  }
@@ -87,8 +92,8 @@ Use this tool to:
87
92
  - Execute scripts and chain commands with pipes (|) or logical operators (&&, ||)
88
93
  - Inspect files and directories
89
94
  `,
90
- schema: z4.object({
91
- command: z4.string().describe(
95
+ schema: z5.object({
96
+ command: z5.string().describe(
92
97
  "The bash command to execute. Can include pipes (|), redirects (>, >>), logical operators (&&, ||), and shell features like command substitution $(...)."
93
98
  )
94
99
  }),
@@ -135,17 +140,17 @@ var taskCreateTool = {
135
140
  - Include enough detail in the description for another agent to understand and complete the task
136
141
  - After creating tasks, use TaskUpdate to set up dependencies (blocks/blockedBy) if needed
137
142
  - Check TaskList first to avoid creating duplicate tasks`,
138
- schema: z4.object({
139
- subject: z4.string().describe(
143
+ schema: z5.object({
144
+ subject: z5.string().describe(
140
145
  'A brief, actionable title in imperative form (e.g., "Fix authentication bug in login flow")'
141
146
  ),
142
- description: z4.string().describe(
147
+ description: z5.string().describe(
143
148
  "Detailed description of what needs to be done, including context and acceptance criteria"
144
149
  ),
145
- activeForm: z4.string().describe(
150
+ activeForm: z5.string().describe(
146
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.'
147
152
  ),
148
- metadata: z4.record(z4.string(), z4.string()).describe("Arbitrary key-value pairs for tracking")
153
+ metadata: z5.record(z5.string(), z5.string()).describe("Arbitrary key-value pairs for tracking")
149
154
  })
150
155
  };
151
156
 
@@ -169,9 +174,30 @@ function createToolRouter(options) {
169
174
  toolMap.set(tool.name, tool);
170
175
  }
171
176
  if (options.subagents) {
177
+ const subagentHooksMap = /* @__PURE__ */ new Map();
178
+ for (const s of options.subagents) {
179
+ if (s.hooks) subagentHooksMap.set(s.name, s.hooks);
180
+ }
181
+ const resolveSubagentName = (args) => args.subagent;
172
182
  toolMap.set("Task", {
173
183
  ...createTaskTool(options.subagents),
174
- handler: createTaskHandler(options.subagents)
184
+ handler: createTaskHandler(options.subagents),
185
+ ...subagentHooksMap.size > 0 && {
186
+ hooks: {
187
+ onPreToolUse: async (ctx) => {
188
+ const hooks = subagentHooksMap.get(resolveSubagentName(ctx.args));
189
+ return hooks?.onPreExecution?.(ctx) ?? {};
190
+ },
191
+ onPostToolUse: async (ctx) => {
192
+ const hooks = subagentHooksMap.get(resolveSubagentName(ctx.args));
193
+ await hooks?.onPostExecution?.(ctx);
194
+ },
195
+ onPostToolUseFailure: async (ctx) => {
196
+ const hooks = subagentHooksMap.get(resolveSubagentName(ctx.args));
197
+ return hooks?.onExecutionFailure?.(ctx) ?? {};
198
+ }
199
+ }
200
+ }
175
201
  });
176
202
  }
177
203
  if (options.buildInTools) {
@@ -194,6 +220,8 @@ function createToolRouter(options) {
194
220
  }
195
221
  async function processToolCall(toolCall, turn, handlerContext) {
196
222
  const startTime = Date.now();
223
+ const tool = toolMap.get(toolCall.name);
224
+ const toolHooks = tool?.hooks;
197
225
  let effectiveArgs = toolCall.args;
198
226
  if (options.hooks?.onPreToolUse) {
199
227
  const preResult = await options.hooks.onPreToolUse({
@@ -216,7 +244,27 @@ function createToolRouter(options) {
216
244
  effectiveArgs = preResult.modifiedArgs;
217
245
  }
218
246
  }
219
- const tool = toolMap.get(toolCall.name);
247
+ if (toolHooks?.onPreToolUse) {
248
+ const preResult = await toolHooks.onPreToolUse({
249
+ args: effectiveArgs,
250
+ threadId: options.threadId,
251
+ turn
252
+ });
253
+ if (preResult?.skip) {
254
+ await appendToolResult({
255
+ threadId: options.threadId,
256
+ toolCallId: toolCall.id,
257
+ content: JSON.stringify({
258
+ skipped: true,
259
+ reason: "Skipped by tool PreToolUse hook"
260
+ })
261
+ });
262
+ return null;
263
+ }
264
+ if (preResult?.modifiedArgs !== void 0) {
265
+ effectiveArgs = preResult.modifiedArgs;
266
+ }
267
+ }
220
268
  let result;
221
269
  let content;
222
270
  try {
@@ -225,30 +273,50 @@ function createToolRouter(options) {
225
273
  effectiveArgs,
226
274
  handlerContext ?? {}
227
275
  );
228
- result = response.result;
229
- content = response.content;
276
+ result = response.data;
277
+ content = response.toolResponse;
230
278
  } else {
231
279
  result = { error: `Unknown tool: ${toolCall.name}` };
232
280
  content = JSON.stringify(result, null, 2);
233
281
  }
234
282
  } catch (error) {
235
- if (options.hooks?.onPostToolUseFailure) {
283
+ const err = error instanceof Error ? error : new Error(String(error));
284
+ let recovered = false;
285
+ if (toolHooks?.onPostToolUseFailure) {
286
+ const failureResult = await toolHooks.onPostToolUseFailure({
287
+ args: effectiveArgs,
288
+ error: err,
289
+ threadId: options.threadId,
290
+ turn
291
+ });
292
+ if (failureResult?.fallbackContent !== void 0) {
293
+ content = failureResult.fallbackContent;
294
+ result = { error: String(error), recovered: true };
295
+ recovered = true;
296
+ } else if (failureResult?.suppress) {
297
+ content = JSON.stringify({ error: String(error), suppressed: true });
298
+ result = { error: String(error), suppressed: true };
299
+ recovered = true;
300
+ }
301
+ }
302
+ if (!recovered && options.hooks?.onPostToolUseFailure) {
236
303
  const failureResult = await options.hooks.onPostToolUseFailure({
237
304
  toolCall,
238
- error: error instanceof Error ? error : new Error(String(error)),
305
+ error: err,
239
306
  threadId: options.threadId,
240
307
  turn
241
308
  });
242
309
  if (failureResult?.fallbackContent !== void 0) {
243
310
  content = failureResult.fallbackContent;
244
311
  result = { error: String(error), recovered: true };
312
+ recovered = true;
245
313
  } else if (failureResult?.suppress) {
246
314
  content = JSON.stringify({ error: String(error), suppressed: true });
247
315
  result = { error: String(error), suppressed: true };
248
- } else {
249
- throw error;
316
+ recovered = true;
250
317
  }
251
- } else {
318
+ }
319
+ if (!recovered) {
252
320
  throw error;
253
321
  }
254
322
  }
@@ -260,10 +328,19 @@ function createToolRouter(options) {
260
328
  const toolResult = {
261
329
  toolCallId: toolCall.id,
262
330
  name: toolCall.name,
263
- result
331
+ data: result
264
332
  };
333
+ const durationMs = Date.now() - startTime;
334
+ if (toolHooks?.onPostToolUse) {
335
+ await toolHooks.onPostToolUse({
336
+ args: effectiveArgs,
337
+ result,
338
+ threadId: options.threadId,
339
+ turn,
340
+ durationMs
341
+ });
342
+ }
265
343
  if (options.hooks?.onPostToolUse) {
266
- const durationMs = Date.now() - startTime;
267
344
  await options.hooks.onPostToolUse({
268
345
  toolCall,
269
346
  result: toolResult,
@@ -344,12 +421,12 @@ function createToolRouter(options) {
344
421
  await appendToolResult({
345
422
  threadId: options.threadId,
346
423
  toolCallId: toolCall.id,
347
- content: response.content
424
+ content: response.toolResponse
348
425
  });
349
426
  return {
350
427
  toolCallId: toolCall.id,
351
428
  name: toolCall.name,
352
- result: response.result
429
+ data: response.data ?? null
353
430
  };
354
431
  };
355
432
  if (options.parallel) {
@@ -375,6 +452,12 @@ function createToolRouter(options) {
375
452
  }
376
453
  };
377
454
  }
455
+ function defineTool(tool) {
456
+ return tool;
457
+ }
458
+ function defineSubagent(config) {
459
+ return config;
460
+ }
378
461
  function hasNoOtherToolCalls(toolCalls, excludeName) {
379
462
  return toolCalls.filter((tc) => tc.name !== excludeName).length === 0;
380
463
  }
@@ -479,17 +562,47 @@ var createSession = async ({
479
562
  return message;
480
563
  }
481
564
  const rawToolCalls = await parseToolCalls(message);
482
- const parsedToolCalls = rawToolCalls.filter((tc) => tc.name !== "Task").map((tc) => toolRouter.parseToolCall(tc));
483
- const taskToolCalls = subagents && subagents.length > 0 ? rawToolCalls.filter((tc) => tc.name === "Task").map((tc) => {
484
- const parsedArgs = createTaskTool(subagents).schema.parse(
485
- tc.args
486
- );
487
- return {
488
- id: tc.id ?? "",
489
- name: tc.name,
490
- args: parsedArgs
491
- };
492
- }) : [];
565
+ const parsedToolCalls = [];
566
+ for (const tc of rawToolCalls.filter(
567
+ (tc2) => tc2.name !== "Task"
568
+ )) {
569
+ try {
570
+ parsedToolCalls.push(toolRouter.parseToolCall(tc));
571
+ } catch (error) {
572
+ await appendToolResult({
573
+ threadId,
574
+ toolCallId: tc.id ?? "",
575
+ content: JSON.stringify({
576
+ error: `Invalid tool call for "${tc.name}": ${error instanceof Error ? error.message : String(error)}`
577
+ })
578
+ });
579
+ }
580
+ }
581
+ const taskToolCalls = [];
582
+ if (subagents && subagents.length > 0) {
583
+ for (const tc of rawToolCalls.filter(
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
+ }
493
606
  await toolRouter.processToolCalls(
494
607
  [...parsedToolCalls, ...taskToolCalls],
495
608
  {
@@ -519,8 +632,6 @@ var createSession = async ({
519
632
  function isTerminalStatus(status) {
520
633
  return status === "COMPLETED" || status === "FAILED" || status === "CANCELLED";
521
634
  }
522
-
523
- // src/lib/state-manager.ts
524
635
  var getStateQuery = defineQuery("getState");
525
636
  function createAgentStateManager(initialState) {
526
637
  let status = initialState?.status ?? "RUNNING";
@@ -615,7 +726,13 @@ function createAgentStateManager(initialState) {
615
726
  version++;
616
727
  },
617
728
  setTools(newTools) {
618
- tools = newTools;
729
+ tools = newTools.map((tool) => ({
730
+ name: tool.name,
731
+ description: tool.description,
732
+ schema: z.toJSONSchema(tool.schema),
733
+ strict: tool.strict,
734
+ max_uses: tool.max_uses
735
+ }));
619
736
  },
620
737
  deleteTask(id) {
621
738
  const deleted = tasks.delete(id);
@@ -646,18 +763,18 @@ Usage notes:
646
763
  * Use multiSelect: true to allow multiple answers to be selected for a question
647
764
  * If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label
648
765
  `,
649
- schema: z4.object({
650
- questions: z4.array(
651
- z4.object({
652
- question: z4.string().describe("The full question text to display"),
653
- header: z4.string().describe("Short label for the question (max 12 characters)"),
654
- options: z4.array(
655
- z4.object({
656
- label: z4.string(),
657
- description: z4.string()
766
+ schema: z5.object({
767
+ questions: z5.array(
768
+ z5.object({
769
+ question: z5.string().describe("The full question text to display"),
770
+ header: z5.string().describe("Short label for the question (max 12 characters)"),
771
+ options: z5.array(
772
+ z5.object({
773
+ label: z5.string(),
774
+ description: z5.string()
658
775
  })
659
776
  ).min(0).max(4).describe("Array of 0-4 choices, each with label and description"),
660
- multiSelect: z4.boolean().describe("If true, users can select multiple options")
777
+ multiSelect: z5.boolean().describe("If true, users can select multiple options")
661
778
  })
662
779
  )
663
780
  }),
@@ -778,15 +895,10 @@ IMPORTANT:
778
895
  }),
779
896
  strict: true
780
897
  };
781
-
782
- // src/tools/task-create/handler.ts
783
- function createTaskCreateHandler({
784
- stateManager,
785
- idGenerator
786
- }) {
898
+ function createTaskCreateHandler(stateManager) {
787
899
  return (args) => {
788
900
  const task = {
789
- id: idGenerator(),
901
+ id: uuid4(),
790
902
  subject: args.subject,
791
903
  description: args.description,
792
904
  activeForm: args.activeForm,
@@ -797,16 +909,16 @@ function createTaskCreateHandler({
797
909
  };
798
910
  stateManager.setTask(task);
799
911
  return {
800
- content: JSON.stringify(task, null, 2),
801
- result: task
912
+ toolResponse: JSON.stringify(task, null, 2),
913
+ data: task
802
914
  };
803
915
  };
804
916
  }
805
917
  var taskGetTool = {
806
918
  name: "TaskGet",
807
919
  description: `Retrieve full task details including dependencies.`,
808
- schema: z4.object({
809
- taskId: z4.string().describe("The ID of the task to get")
920
+ schema: z5.object({
921
+ taskId: z5.string().describe("The ID of the task to get")
810
922
  })
811
923
  };
812
924
 
@@ -816,20 +928,20 @@ function createTaskGetHandler(stateManager) {
816
928
  const task = stateManager.getTask(args.taskId) ?? null;
817
929
  if (!task) {
818
930
  return {
819
- content: JSON.stringify({ error: `Task not found: ${args.taskId}` }),
820
- result: null
931
+ toolResponse: JSON.stringify({ error: `Task not found: ${args.taskId}` }),
932
+ data: null
821
933
  };
822
934
  }
823
935
  return {
824
- content: JSON.stringify(task, null, 2),
825
- result: task
936
+ toolResponse: JSON.stringify(task, null, 2),
937
+ data: task
826
938
  };
827
939
  };
828
940
  }
829
941
  var taskListTool = {
830
942
  name: "TaskList",
831
943
  description: `List all tasks with current state.`,
832
- schema: z4.object({})
944
+ schema: z5.object({})
833
945
  };
834
946
 
835
947
  // src/tools/task-list/handler.ts
@@ -837,19 +949,19 @@ function createTaskListHandler(stateManager) {
837
949
  return (_args) => {
838
950
  const taskList = stateManager.getTasks();
839
951
  return {
840
- content: JSON.stringify(taskList, null, 2),
841
- result: taskList
952
+ toolResponse: JSON.stringify(taskList, null, 2),
953
+ data: taskList
842
954
  };
843
955
  };
844
956
  }
845
957
  var taskUpdateTool = {
846
958
  name: "TaskUpdate",
847
959
  description: `Update status, add blockers, modify details.`,
848
- schema: z4.object({
849
- taskId: z4.string().describe("The ID of the task to get"),
850
- status: z4.enum(["pending", "in_progress", "completed"]).describe("The status of the task"),
851
- addBlockedBy: z4.array(z4.string()).describe("The IDs of the tasks that are blocking this task"),
852
- addBlocks: z4.array(z4.string()).describe("The IDs of the tasks that this task is blocking")
960
+ schema: z5.object({
961
+ taskId: z5.string().describe("The ID of the task to get"),
962
+ status: z5.enum(["pending", "in_progress", "completed"]).describe("The status of the task"),
963
+ addBlockedBy: z5.array(z5.string()).describe("The IDs of the tasks that are blocking this task"),
964
+ addBlocks: z5.array(z5.string()).describe("The IDs of the tasks that this task is blocking")
853
965
  })
854
966
  };
855
967
 
@@ -859,8 +971,8 @@ function createTaskUpdateHandler(stateManager) {
859
971
  const task = stateManager.getTask(args.taskId);
860
972
  if (!task) {
861
973
  return {
862
- content: JSON.stringify({ error: `Task not found: ${args.taskId}` }),
863
- result: null
974
+ toolResponse: JSON.stringify({ error: `Task not found: ${args.taskId}` }),
975
+ data: null
864
976
  };
865
977
  }
866
978
  if (args.status) {
@@ -892,12 +1004,12 @@ function createTaskUpdateHandler(stateManager) {
892
1004
  }
893
1005
  stateManager.setTask(task);
894
1006
  return {
895
- content: JSON.stringify(task, null, 2),
896
- result: task
1007
+ toolResponse: JSON.stringify(task, null, 2),
1008
+ data: task
897
1009
  };
898
1010
  };
899
1011
  }
900
1012
 
901
- export { AGENT_HANDLER_NAMES, askUserQuestionTool, bashTool, createAgentStateManager, createSession, createTaskCreateHandler, createTaskGetHandler, createTaskListHandler, createTaskTool, createTaskUpdateHandler, createToolRouter, editTool, globTool, grepTool, hasNoOtherToolCalls, isTerminalStatus, readTool, taskCreateTool, taskGetTool, taskListTool, taskUpdateTool, writeTool };
1013
+ export { AGENT_HANDLER_NAMES, askUserQuestionTool, bashTool, createAgentStateManager, createSession, createTaskCreateHandler, createTaskGetHandler, createTaskListHandler, createTaskTool, createTaskUpdateHandler, createToolRouter, defineSubagent, defineTool, editTool, globTool, grepTool, hasNoOtherToolCalls, isTerminalStatus, readTool, taskCreateTool, taskGetTool, taskListTool, taskUpdateTool, writeTool };
902
1014
  //# sourceMappingURL=workflow.js.map
903
1015
  //# sourceMappingURL=workflow.js.map