zeitlich 0.2.6 → 0.2.8

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, uuid4, workflowInfo, executeChild } from '@temporalio/workflow';
2
- import z3, { z } from 'zod';
1
+ import { setHandler, defineUpdate, condition, proxyActivities, defineQuery, uuid4, workflowInfo, executeChild } from '@temporalio/workflow';
2
+ import z13, { z } from 'zod';
3
3
 
4
4
  // src/lib/session.ts
5
5
  var SUBAGENT_TOOL = "Subagent";
@@ -34,10 +34,10 @@ function createSubagentTool(subagents) {
34
34
  return {
35
35
  name: SUBAGENT_TOOL,
36
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")
37
+ schema: z13.object({
38
+ subagent: z13.enum(names).describe("The type of subagent to launch"),
39
+ description: z13.string().describe("A short (3-5 word) description of the task"),
40
+ prompt: z13.string().describe("The task for the agent to perform")
41
41
  })
42
42
  };
43
43
  }
@@ -60,11 +60,12 @@ function createSubagentHandler(subagents) {
60
60
  args: [input],
61
61
  taskQueue: config.taskQueue ?? parentTaskQueue
62
62
  };
63
- const { toolResponse, data } = typeof config.workflow === "string" ? await executeChild(config.workflow, childOpts) : await executeChild(config.workflow, childOpts);
63
+ const { toolResponse, data, usage } = typeof config.workflow === "string" ? await executeChild(config.workflow, childOpts) : await executeChild(config.workflow, childOpts);
64
64
  const validated = config.resultSchema ? config.resultSchema.parse(data) : null;
65
65
  return {
66
66
  toolResponse,
67
- data: validated
67
+ data: validated,
68
+ ...usage && { usage }
68
69
  };
69
70
  };
70
71
  }
@@ -76,20 +77,17 @@ function createToolRouter(options) {
76
77
  for (const [_key, tool] of Object.entries(options.tools)) {
77
78
  toolMap.set(tool.name, tool);
78
79
  }
79
- const isEnabled = (tool) => tool.enabled !== false;
80
+ const isEnabled = (tool) => tool.enabled?.() ?? true;
80
81
  if (options.subagents) {
81
- const enabledSubagents = options.subagents.filter(
82
- (s) => s.enabled !== false
83
- );
84
- if (enabledSubagents.length > 0) {
82
+ if (options.subagents.length > 0) {
85
83
  const subagentHooksMap = /* @__PURE__ */ new Map();
86
- for (const s of enabledSubagents) {
84
+ for (const s of options.subagents) {
87
85
  if (s.hooks) subagentHooksMap.set(s.agentName, s.hooks);
88
86
  }
89
87
  const resolveSubagentName = (args) => args.subagent;
90
88
  toolMap.set("Subagent", {
91
- ...createSubagentTool(enabledSubagents),
92
- handler: createSubagentHandler(enabledSubagents),
89
+ ...createSubagentTool(options.subagents),
90
+ handler: createSubagentHandler(options.subagents),
93
91
  ...subagentHooksMap.size > 0 && {
94
92
  hooks: {
95
93
  onPreToolUse: async (ctx) => {
@@ -380,6 +378,7 @@ function hasNoOtherToolCalls(toolCalls, excludeName) {
380
378
  var createSession = async ({
381
379
  threadId,
382
380
  agentName,
381
+ description,
383
382
  maxTurns = 50,
384
383
  metadata = {},
385
384
  runAgent,
@@ -390,7 +389,8 @@ var createSession = async ({
390
389
  processToolsInParallel = true,
391
390
  hooks = {},
392
391
  appendSystemPrompt = true,
393
- systemPrompt
392
+ systemPrompt,
393
+ waitForInputTimeout = "48h"
394
394
  }) => {
395
395
  const {
396
396
  appendToolResult,
@@ -418,7 +418,28 @@ var createSession = async ({
418
418
  }
419
419
  };
420
420
  return {
421
- runSession: async ({ stateManager }) => {
421
+ runSession: async ({
422
+ stateManager
423
+ }) => {
424
+ setHandler(
425
+ defineUpdate(`add${agentName}Message`),
426
+ async (message) => {
427
+ if (hooks.onPreHumanMessageAppend) {
428
+ await hooks.onPreHumanMessageAppend({
429
+ message,
430
+ threadId
431
+ });
432
+ }
433
+ await appendHumanMessage(threadId, message);
434
+ if (hooks.onPostHumanMessageAppend) {
435
+ await hooks.onPostHumanMessageAppend({
436
+ message,
437
+ threadId
438
+ });
439
+ }
440
+ stateManager.run();
441
+ }
442
+ );
422
443
  if (hooks.onSessionStart) {
423
444
  await hooks.onSessionStart({
424
445
  threadId,
@@ -426,7 +447,6 @@ var createSession = async ({
426
447
  metadata
427
448
  });
428
449
  }
429
- stateManager.setTools(toolRouter.getToolDefinitions());
430
450
  await initializeThread(threadId);
431
451
  if (appendSystemPrompt && systemPrompt && systemPrompt.trim() !== "") {
432
452
  await appendSystemMessage(threadId, systemPrompt);
@@ -437,15 +457,25 @@ var createSession = async ({
437
457
  while (stateManager.isRunning() && !stateManager.isTerminal() && stateManager.getTurns() < maxTurns) {
438
458
  stateManager.incrementTurns();
439
459
  const currentTurn = stateManager.getTurns();
440
- const { message, rawToolCalls } = await runAgent({
460
+ stateManager.setTools(toolRouter.getToolDefinitions());
461
+ const { message, rawToolCalls, usage } = await runAgent({
441
462
  threadId,
442
463
  agentName,
443
- metadata
464
+ metadata,
465
+ systemPrompt,
466
+ description
444
467
  });
468
+ if (usage) {
469
+ stateManager.updateUsage(usage);
470
+ }
445
471
  if (!toolRouter.hasTools() || rawToolCalls.length === 0) {
446
472
  stateManager.complete();
447
473
  exitReason = "completed";
448
- return message;
474
+ return {
475
+ finalMessage: message,
476
+ exitReason,
477
+ usage: stateManager.getTotalUsage()
478
+ };
449
479
  }
450
480
  const parsedToolCalls = [];
451
481
  for (const tc of rawToolCalls) {
@@ -462,12 +492,27 @@ var createSession = async ({
462
492
  });
463
493
  }
464
494
  }
465
- await toolRouter.processToolCalls(parsedToolCalls, {
466
- turn: currentTurn
467
- });
495
+ const toolCallResults = await toolRouter.processToolCalls(
496
+ parsedToolCalls,
497
+ {
498
+ turn: currentTurn
499
+ }
500
+ );
501
+ for (const result of toolCallResults) {
502
+ if (result.usage) {
503
+ stateManager.updateUsage(result.usage);
504
+ }
505
+ }
468
506
  if (stateManager.getStatus() === "WAITING_FOR_INPUT") {
469
- exitReason = "waiting_for_input";
470
- break;
507
+ const conditionMet = await condition(
508
+ () => stateManager.getStatus() === "RUNNING",
509
+ waitForInputTimeout
510
+ );
511
+ if (!conditionMet) {
512
+ stateManager.cancel();
513
+ await condition(() => false, "2s");
514
+ break;
515
+ }
471
516
  }
472
517
  }
473
518
  if (stateManager.getTurns() >= maxTurns && stateManager.isRunning()) {
@@ -479,7 +524,11 @@ var createSession = async ({
479
524
  } finally {
480
525
  await callSessionEnd(exitReason, stateManager.getTurns());
481
526
  }
482
- return null;
527
+ return {
528
+ finalMessage: null,
529
+ exitReason,
530
+ usage: stateManager.getTotalUsage()
531
+ };
483
532
  }
484
533
  };
485
534
  };
@@ -508,12 +557,19 @@ function proxyDefaultThreadOps(options) {
508
557
  function isTerminalStatus(status) {
509
558
  return status === "COMPLETED" || status === "FAILED" || status === "CANCELLED";
510
559
  }
511
- var getStateQuery = defineQuery("getState");
512
- function createAgentStateManager(initialState) {
560
+ function createAgentStateManager({
561
+ initialState,
562
+ agentConfig
563
+ }) {
513
564
  let status = initialState?.status ?? "RUNNING";
514
565
  let version = initialState?.version ?? 0;
515
566
  let turns = initialState?.turns ?? 0;
516
567
  let tools = initialState?.tools ?? [];
568
+ let totalInputTokens = 0;
569
+ let totalOutputTokens = 0;
570
+ let totalCachedWriteTokens = 0;
571
+ let totalCachedReadTokens = 0;
572
+ let totalReasonTokens = 0;
517
573
  const tasks = new Map(initialState?.tasks);
518
574
  const {
519
575
  status: _,
@@ -533,9 +589,21 @@ function createAgentStateManager(initialState) {
533
589
  ...customState
534
590
  };
535
591
  }
536
- setHandler(getStateQuery, () => {
592
+ setHandler(defineQuery(`get${agentConfig.agentName}State`), () => {
537
593
  return buildState();
538
594
  });
595
+ setHandler(
596
+ defineUpdate(
597
+ `waitFor${agentConfig.agentName}StateChange`
598
+ ),
599
+ async (lastKnownVersion) => {
600
+ await condition(
601
+ () => version > lastKnownVersion || isTerminalStatus(status),
602
+ "55s"
603
+ );
604
+ return buildState();
605
+ }
606
+ );
539
607
  return {
540
608
  getStatus() {
541
609
  return status;
@@ -616,6 +684,23 @@ function createAgentStateManager(initialState) {
616
684
  version++;
617
685
  }
618
686
  return deleted;
687
+ },
688
+ updateUsage(usage) {
689
+ totalInputTokens += usage.inputTokens ?? 0;
690
+ totalOutputTokens += usage.outputTokens ?? 0;
691
+ totalCachedWriteTokens += usage.cachedWriteTokens ?? 0;
692
+ totalCachedReadTokens += usage.cachedReadTokens ?? 0;
693
+ totalReasonTokens += usage.reasonTokens ?? 0;
694
+ },
695
+ getTotalUsage() {
696
+ return {
697
+ totalInputTokens,
698
+ totalOutputTokens,
699
+ totalCachedWriteTokens,
700
+ totalCachedReadTokens,
701
+ totalReasonTokens,
702
+ turns
703
+ };
619
704
  }
620
705
  };
621
706
  }
@@ -624,38 +709,6 @@ var AGENT_HANDLER_NAMES = {
624
709
  waitForStateChange: "waitForStateChange",
625
710
  addMessage: "addMessage"
626
711
  };
627
- var askUserQuestionTool = {
628
- name: "AskUserQuestion",
629
- description: `Use this tool when you need to ask the user questions during execution. This allows you to:
630
-
631
- 1. Gather user preferences or requirements
632
- 2. Clarify ambiguous instructions
633
- 3. Get decisions on implementation choices as you work
634
- 4. Offer choices to the user about what direction to take.
635
-
636
- Usage notes:
637
-
638
- * Users will always be able to select "Other" to provide custom text input
639
- * Use multiSelect: true to allow multiple answers to be selected for a question
640
- * If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label
641
- `,
642
- schema: z3.object({
643
- questions: z3.array(
644
- z3.object({
645
- question: z3.string().describe("The full question text to display"),
646
- header: z3.string().describe("Short label for the question (max 12 characters)"),
647
- options: z3.array(
648
- z3.object({
649
- label: z3.string(),
650
- description: z3.string()
651
- })
652
- ).min(0).max(4).describe("Array of 0-4 choices, each with label and description"),
653
- multiSelect: z3.boolean().describe("If true, users can select multiple options")
654
- })
655
- )
656
- }),
657
- strict: true
658
- };
659
712
  var globTool = {
660
713
  name: "Glob",
661
714
  description: `Search for files matching a glob pattern within the available file system.
@@ -812,17 +865,17 @@ var taskCreateTool = {
812
865
  - Include enough detail in the description for another agent to understand and complete the task
813
866
  - After creating tasks, use TaskUpdate to set up dependencies (blocks/blockedBy) if needed
814
867
  - Check TaskList first to avoid creating duplicate tasks`,
815
- schema: z3.object({
816
- subject: z3.string().describe(
868
+ schema: z13.object({
869
+ subject: z13.string().describe(
817
870
  'A brief, actionable title in imperative form (e.g., "Fix authentication bug in login flow")'
818
871
  ),
819
- description: z3.string().describe(
872
+ description: z13.string().describe(
820
873
  "Detailed description of what needs to be done, including context and acceptance criteria"
821
874
  ),
822
- activeForm: z3.string().describe(
875
+ activeForm: z13.string().describe(
823
876
  '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.'
824
877
  ),
825
- metadata: z3.record(z3.string(), z3.string()).describe("Arbitrary key-value pairs for tracking")
878
+ metadata: z13.record(z13.string(), z13.string()).describe("Arbitrary key-value pairs for tracking")
826
879
  })
827
880
  };
828
881
  function createTaskCreateHandler(stateManager) {
@@ -847,8 +900,8 @@ function createTaskCreateHandler(stateManager) {
847
900
  var taskGetTool = {
848
901
  name: "TaskGet",
849
902
  description: `Retrieve full task details including dependencies.`,
850
- schema: z3.object({
851
- taskId: z3.string().describe("The ID of the task to get")
903
+ schema: z13.object({
904
+ taskId: z13.string().describe("The ID of the task to get")
852
905
  })
853
906
  };
854
907
 
@@ -871,7 +924,7 @@ function createTaskGetHandler(stateManager) {
871
924
  var taskListTool = {
872
925
  name: "TaskList",
873
926
  description: `List all tasks with current state.`,
874
- schema: z3.object({})
927
+ schema: z13.object({})
875
928
  };
876
929
 
877
930
  // src/tools/task-list/handler.ts
@@ -887,11 +940,11 @@ function createTaskListHandler(stateManager) {
887
940
  var taskUpdateTool = {
888
941
  name: "TaskUpdate",
889
942
  description: `Update status, add blockers, modify details.`,
890
- schema: z3.object({
891
- taskId: z3.string().describe("The ID of the task to get"),
892
- status: z3.enum(["pending", "in_progress", "completed"]).describe("The status of the task"),
893
- addBlockedBy: z3.array(z3.string()).describe("The IDs of the tasks that are blocking this task"),
894
- addBlocks: z3.array(z3.string()).describe("The IDs of the tasks that this task is blocking")
943
+ schema: z13.object({
944
+ taskId: z13.string().describe("The ID of the task to get"),
945
+ status: z13.enum(["pending", "in_progress", "completed"]).describe("The status of the task"),
946
+ addBlockedBy: z13.array(z13.string()).describe("The IDs of the tasks that are blocking this task"),
947
+ addBlocks: z13.array(z13.string()).describe("The IDs of the tasks that this task is blocking")
895
948
  })
896
949
  };
897
950
 
@@ -959,14 +1012,54 @@ Use this tool to:
959
1012
  - Execute scripts and chain commands with pipes (|) or logical operators (&&, ||)
960
1013
  - Inspect files and directories
961
1014
  `,
962
- schema: z3.object({
963
- command: z3.string().describe(
1015
+ schema: z13.object({
1016
+ command: z13.string().describe(
964
1017
  "The bash command to execute. Can include pipes (|), redirects (>, >>), logical operators (&&, ||), and shell features like command substitution $(...)."
965
1018
  )
966
1019
  }),
967
1020
  strict: true
968
1021
  };
1022
+ var askUserQuestionTool = {
1023
+ name: "AskUserQuestion",
1024
+ description: `Use this tool when you need to ask the user questions during execution. This allows you to:
1025
+
1026
+ 1. Gather user preferences or requirements
1027
+ 2. Clarify ambiguous instructions
1028
+ 3. Get decisions on implementation choices as you work
1029
+ 4. Offer choices to the user about what direction to take.
1030
+
1031
+ Usage notes:
1032
+
1033
+ * Users will always be able to select "Other" to provide custom text input
1034
+ * Use multiSelect: true to allow multiple answers to be selected for a question
1035
+ * If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label
1036
+ `,
1037
+ schema: z13.object({
1038
+ questions: z13.array(
1039
+ z13.object({
1040
+ question: z13.string().describe("The full question text to display"),
1041
+ header: z13.string().describe("Short label for the question (max 12 characters)"),
1042
+ options: z13.array(
1043
+ z13.object({
1044
+ label: z13.string(),
1045
+ description: z13.string()
1046
+ })
1047
+ ).min(0).max(4).describe("Array of 0-4 choices, each with label and description"),
1048
+ multiSelect: z13.boolean().describe("If true, users can select multiple options")
1049
+ })
1050
+ )
1051
+ }),
1052
+ strict: true
1053
+ };
1054
+
1055
+ // src/tools/ask-user-question/handler.ts
1056
+ var createAskUserQuestionHandler = () => (args) => {
1057
+ return {
1058
+ toolResponse: "Question submitted",
1059
+ data: { questions: args.questions }
1060
+ };
1061
+ };
969
1062
 
970
- 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 };
1063
+ export { AGENT_HANDLER_NAMES, askUserQuestionTool, bashTool, createAgentStateManager, createAskUserQuestionHandler, createBashToolDescription, createSession, createSubagentTool, createTaskCreateHandler, createTaskGetHandler, createTaskListHandler, createTaskUpdateHandler, createToolRouter, defineSubagent, defineTool, editTool, globTool, grepTool, hasNoOtherToolCalls, isTerminalStatus, proxyDefaultThreadOps, readTool, taskCreateTool, taskGetTool, taskListTool, taskUpdateTool, writeTool };
971
1064
  //# sourceMappingURL=workflow.js.map
972
1065
  //# sourceMappingURL=workflow.js.map