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.cjs CHANGED
@@ -1,11 +1,11 @@
1
1
  'use strict';
2
2
 
3
3
  var workflow = require('@temporalio/workflow');
4
- var z3 = require('zod');
4
+ var z13 = require('zod');
5
5
 
6
6
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
7
 
8
- var z3__default = /*#__PURE__*/_interopDefault(z3);
8
+ var z13__default = /*#__PURE__*/_interopDefault(z13);
9
9
 
10
10
  // src/lib/session.ts
11
11
  var SUBAGENT_TOOL = "Subagent";
@@ -40,10 +40,10 @@ function createSubagentTool(subagents) {
40
40
  return {
41
41
  name: SUBAGENT_TOOL,
42
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")
43
+ schema: z13__default.default.object({
44
+ subagent: z13__default.default.enum(names).describe("The type of subagent to launch"),
45
+ description: z13__default.default.string().describe("A short (3-5 word) description of the task"),
46
+ prompt: z13__default.default.string().describe("The task for the agent to perform")
47
47
  })
48
48
  };
49
49
  }
@@ -66,11 +66,12 @@ function createSubagentHandler(subagents) {
66
66
  args: [input],
67
67
  taskQueue: config.taskQueue ?? parentTaskQueue
68
68
  };
69
- const { toolResponse, data } = typeof config.workflow === "string" ? await workflow.executeChild(config.workflow, childOpts) : await workflow.executeChild(config.workflow, childOpts);
69
+ const { toolResponse, data, usage } = typeof config.workflow === "string" ? await workflow.executeChild(config.workflow, childOpts) : await workflow.executeChild(config.workflow, childOpts);
70
70
  const validated = config.resultSchema ? config.resultSchema.parse(data) : null;
71
71
  return {
72
72
  toolResponse,
73
- data: validated
73
+ data: validated,
74
+ ...usage && { usage }
74
75
  };
75
76
  };
76
77
  }
@@ -82,20 +83,17 @@ function createToolRouter(options) {
82
83
  for (const [_key, tool] of Object.entries(options.tools)) {
83
84
  toolMap.set(tool.name, tool);
84
85
  }
85
- const isEnabled = (tool) => tool.enabled !== false;
86
+ const isEnabled = (tool) => tool.enabled?.() ?? true;
86
87
  if (options.subagents) {
87
- const enabledSubagents = options.subagents.filter(
88
- (s) => s.enabled !== false
89
- );
90
- if (enabledSubagents.length > 0) {
88
+ if (options.subagents.length > 0) {
91
89
  const subagentHooksMap = /* @__PURE__ */ new Map();
92
- for (const s of enabledSubagents) {
90
+ for (const s of options.subagents) {
93
91
  if (s.hooks) subagentHooksMap.set(s.agentName, s.hooks);
94
92
  }
95
93
  const resolveSubagentName = (args) => args.subagent;
96
94
  toolMap.set("Subagent", {
97
- ...createSubagentTool(enabledSubagents),
98
- handler: createSubagentHandler(enabledSubagents),
95
+ ...createSubagentTool(options.subagents),
96
+ handler: createSubagentHandler(options.subagents),
99
97
  ...subagentHooksMap.size > 0 && {
100
98
  hooks: {
101
99
  onPreToolUse: async (ctx) => {
@@ -386,6 +384,7 @@ function hasNoOtherToolCalls(toolCalls, excludeName) {
386
384
  var createSession = async ({
387
385
  threadId,
388
386
  agentName,
387
+ description,
389
388
  maxTurns = 50,
390
389
  metadata = {},
391
390
  runAgent,
@@ -396,7 +395,8 @@ var createSession = async ({
396
395
  processToolsInParallel = true,
397
396
  hooks = {},
398
397
  appendSystemPrompt = true,
399
- systemPrompt
398
+ systemPrompt,
399
+ waitForInputTimeout = "48h"
400
400
  }) => {
401
401
  const {
402
402
  appendToolResult,
@@ -424,7 +424,28 @@ var createSession = async ({
424
424
  }
425
425
  };
426
426
  return {
427
- runSession: async ({ stateManager }) => {
427
+ runSession: async ({
428
+ stateManager
429
+ }) => {
430
+ workflow.setHandler(
431
+ workflow.defineUpdate(`add${agentName}Message`),
432
+ async (message) => {
433
+ if (hooks.onPreHumanMessageAppend) {
434
+ await hooks.onPreHumanMessageAppend({
435
+ message,
436
+ threadId
437
+ });
438
+ }
439
+ await appendHumanMessage(threadId, message);
440
+ if (hooks.onPostHumanMessageAppend) {
441
+ await hooks.onPostHumanMessageAppend({
442
+ message,
443
+ threadId
444
+ });
445
+ }
446
+ stateManager.run();
447
+ }
448
+ );
428
449
  if (hooks.onSessionStart) {
429
450
  await hooks.onSessionStart({
430
451
  threadId,
@@ -432,7 +453,6 @@ var createSession = async ({
432
453
  metadata
433
454
  });
434
455
  }
435
- stateManager.setTools(toolRouter.getToolDefinitions());
436
456
  await initializeThread(threadId);
437
457
  if (appendSystemPrompt && systemPrompt && systemPrompt.trim() !== "") {
438
458
  await appendSystemMessage(threadId, systemPrompt);
@@ -443,15 +463,25 @@ var createSession = async ({
443
463
  while (stateManager.isRunning() && !stateManager.isTerminal() && stateManager.getTurns() < maxTurns) {
444
464
  stateManager.incrementTurns();
445
465
  const currentTurn = stateManager.getTurns();
446
- const { message, rawToolCalls } = await runAgent({
466
+ stateManager.setTools(toolRouter.getToolDefinitions());
467
+ const { message, rawToolCalls, usage } = await runAgent({
447
468
  threadId,
448
469
  agentName,
449
- metadata
470
+ metadata,
471
+ systemPrompt,
472
+ description
450
473
  });
474
+ if (usage) {
475
+ stateManager.updateUsage(usage);
476
+ }
451
477
  if (!toolRouter.hasTools() || rawToolCalls.length === 0) {
452
478
  stateManager.complete();
453
479
  exitReason = "completed";
454
- return message;
480
+ return {
481
+ finalMessage: message,
482
+ exitReason,
483
+ usage: stateManager.getTotalUsage()
484
+ };
455
485
  }
456
486
  const parsedToolCalls = [];
457
487
  for (const tc of rawToolCalls) {
@@ -468,12 +498,27 @@ var createSession = async ({
468
498
  });
469
499
  }
470
500
  }
471
- await toolRouter.processToolCalls(parsedToolCalls, {
472
- turn: currentTurn
473
- });
501
+ const toolCallResults = await toolRouter.processToolCalls(
502
+ parsedToolCalls,
503
+ {
504
+ turn: currentTurn
505
+ }
506
+ );
507
+ for (const result of toolCallResults) {
508
+ if (result.usage) {
509
+ stateManager.updateUsage(result.usage);
510
+ }
511
+ }
474
512
  if (stateManager.getStatus() === "WAITING_FOR_INPUT") {
475
- exitReason = "waiting_for_input";
476
- break;
513
+ const conditionMet = await workflow.condition(
514
+ () => stateManager.getStatus() === "RUNNING",
515
+ waitForInputTimeout
516
+ );
517
+ if (!conditionMet) {
518
+ stateManager.cancel();
519
+ await workflow.condition(() => false, "2s");
520
+ break;
521
+ }
477
522
  }
478
523
  }
479
524
  if (stateManager.getTurns() >= maxTurns && stateManager.isRunning()) {
@@ -485,7 +530,11 @@ var createSession = async ({
485
530
  } finally {
486
531
  await callSessionEnd(exitReason, stateManager.getTurns());
487
532
  }
488
- return null;
533
+ return {
534
+ finalMessage: null,
535
+ exitReason,
536
+ usage: stateManager.getTotalUsage()
537
+ };
489
538
  }
490
539
  };
491
540
  };
@@ -514,12 +563,19 @@ function proxyDefaultThreadOps(options) {
514
563
  function isTerminalStatus(status) {
515
564
  return status === "COMPLETED" || status === "FAILED" || status === "CANCELLED";
516
565
  }
517
- var getStateQuery = workflow.defineQuery("getState");
518
- function createAgentStateManager(initialState) {
566
+ function createAgentStateManager({
567
+ initialState,
568
+ agentConfig
569
+ }) {
519
570
  let status = initialState?.status ?? "RUNNING";
520
571
  let version = initialState?.version ?? 0;
521
572
  let turns = initialState?.turns ?? 0;
522
573
  let tools = initialState?.tools ?? [];
574
+ let totalInputTokens = 0;
575
+ let totalOutputTokens = 0;
576
+ let totalCachedWriteTokens = 0;
577
+ let totalCachedReadTokens = 0;
578
+ let totalReasonTokens = 0;
523
579
  const tasks = new Map(initialState?.tasks);
524
580
  const {
525
581
  status: _,
@@ -539,9 +595,21 @@ function createAgentStateManager(initialState) {
539
595
  ...customState
540
596
  };
541
597
  }
542
- workflow.setHandler(getStateQuery, () => {
598
+ workflow.setHandler(workflow.defineQuery(`get${agentConfig.agentName}State`), () => {
543
599
  return buildState();
544
600
  });
601
+ workflow.setHandler(
602
+ workflow.defineUpdate(
603
+ `waitFor${agentConfig.agentName}StateChange`
604
+ ),
605
+ async (lastKnownVersion) => {
606
+ await workflow.condition(
607
+ () => version > lastKnownVersion || isTerminalStatus(status),
608
+ "55s"
609
+ );
610
+ return buildState();
611
+ }
612
+ );
545
613
  return {
546
614
  getStatus() {
547
615
  return status;
@@ -611,7 +679,7 @@ function createAgentStateManager(initialState) {
611
679
  tools = newTools.map((tool) => ({
612
680
  name: tool.name,
613
681
  description: tool.description,
614
- schema: z3.z.toJSONSchema(tool.schema),
682
+ schema: z13.z.toJSONSchema(tool.schema),
615
683
  strict: tool.strict,
616
684
  max_uses: tool.max_uses
617
685
  }));
@@ -622,6 +690,23 @@ function createAgentStateManager(initialState) {
622
690
  version++;
623
691
  }
624
692
  return deleted;
693
+ },
694
+ updateUsage(usage) {
695
+ totalInputTokens += usage.inputTokens ?? 0;
696
+ totalOutputTokens += usage.outputTokens ?? 0;
697
+ totalCachedWriteTokens += usage.cachedWriteTokens ?? 0;
698
+ totalCachedReadTokens += usage.cachedReadTokens ?? 0;
699
+ totalReasonTokens += usage.reasonTokens ?? 0;
700
+ },
701
+ getTotalUsage() {
702
+ return {
703
+ totalInputTokens,
704
+ totalOutputTokens,
705
+ totalCachedWriteTokens,
706
+ totalCachedReadTokens,
707
+ totalReasonTokens,
708
+ turns
709
+ };
625
710
  }
626
711
  };
627
712
  }
@@ -630,38 +715,6 @@ var AGENT_HANDLER_NAMES = {
630
715
  waitForStateChange: "waitForStateChange",
631
716
  addMessage: "addMessage"
632
717
  };
633
- var askUserQuestionTool = {
634
- name: "AskUserQuestion",
635
- description: `Use this tool when you need to ask the user questions during execution. This allows you to:
636
-
637
- 1. Gather user preferences or requirements
638
- 2. Clarify ambiguous instructions
639
- 3. Get decisions on implementation choices as you work
640
- 4. Offer choices to the user about what direction to take.
641
-
642
- Usage notes:
643
-
644
- * Users will always be able to select "Other" to provide custom text input
645
- * Use multiSelect: true to allow multiple answers to be selected for a question
646
- * If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label
647
- `,
648
- schema: z3__default.default.object({
649
- questions: z3__default.default.array(
650
- z3__default.default.object({
651
- question: z3__default.default.string().describe("The full question text to display"),
652
- header: z3__default.default.string().describe("Short label for the question (max 12 characters)"),
653
- options: z3__default.default.array(
654
- z3__default.default.object({
655
- label: z3__default.default.string(),
656
- description: z3__default.default.string()
657
- })
658
- ).min(0).max(4).describe("Array of 0-4 choices, each with label and description"),
659
- multiSelect: z3__default.default.boolean().describe("If true, users can select multiple options")
660
- })
661
- )
662
- }),
663
- strict: true
664
- };
665
718
  var globTool = {
666
719
  name: "Glob",
667
720
  description: `Search for files matching a glob pattern within the available file system.
@@ -676,9 +729,9 @@ Examples:
676
729
  - "**/*.test.ts" - Find all test files recursively
677
730
  - "src/**/*.ts" - Find all TypeScript files in src directory
678
731
  `,
679
- schema: z3.z.object({
680
- pattern: z3.z.string().describe("Glob pattern to match files against"),
681
- root: z3.z.string().optional().describe("Optional root directory to search from")
732
+ schema: z13.z.object({
733
+ pattern: z13.z.string().describe("Glob pattern to match files against"),
734
+ root: z13.z.string().optional().describe("Optional root directory to search from")
682
735
  }),
683
736
  strict: true
684
737
  };
@@ -696,13 +749,13 @@ Examples:
696
749
  - Search for function definitions with "function.*handleClick"
697
750
  - Search case-insensitively with ignoreCase: true
698
751
  `,
699
- schema: z3.z.object({
700
- pattern: z3.z.string().describe("Regex pattern to search for in file contents"),
701
- ignoreCase: z3.z.boolean().optional().describe("Case-insensitive search (default: false)"),
702
- maxMatches: z3.z.number().optional().describe("Maximum number of matches to return (default: 50)"),
703
- includePatterns: z3.z.array(z3.z.string()).optional().describe("Glob patterns to include (e.g., ['*.ts', '*.js'])"),
704
- excludePatterns: z3.z.array(z3.z.string()).optional().describe("Glob patterns to exclude (e.g., ['*.test.ts'])"),
705
- contextLines: z3.z.number().optional().describe("Number of context lines to show around matches")
752
+ schema: z13.z.object({
753
+ pattern: z13.z.string().describe("Regex pattern to search for in file contents"),
754
+ ignoreCase: z13.z.boolean().optional().describe("Case-insensitive search (default: false)"),
755
+ maxMatches: z13.z.number().optional().describe("Maximum number of matches to return (default: 50)"),
756
+ includePatterns: z13.z.array(z13.z.string()).optional().describe("Glob patterns to include (e.g., ['*.ts', '*.js'])"),
757
+ excludePatterns: z13.z.array(z13.z.string()).optional().describe("Glob patterns to exclude (e.g., ['*.test.ts'])"),
758
+ contextLines: z13.z.number().optional().describe("Number of context lines to show around matches")
706
759
  }),
707
760
  strict: true
708
761
  };
@@ -720,12 +773,12 @@ The tool returns the file content in an appropriate format:
720
773
  - Images: Base64-encoded image data
721
774
  - PDFs: Extracted text content
722
775
  `,
723
- schema: z3.z.object({
724
- path: z3.z.string().describe("Virtual path to the file to read"),
725
- offset: z3.z.number().optional().describe(
776
+ schema: z13.z.object({
777
+ path: z13.z.string().describe("Virtual path to the file to read"),
778
+ offset: z13.z.number().optional().describe(
726
779
  "Line number to start reading from (1-indexed, for text files)"
727
780
  ),
728
- limit: z3.z.number().optional().describe("Maximum number of lines to read (for text files)")
781
+ limit: z13.z.number().optional().describe("Maximum number of lines to read (for text files)")
729
782
  }),
730
783
  strict: true
731
784
  };
@@ -743,9 +796,9 @@ IMPORTANT:
743
796
  - This is an atomic write operation - the entire file is replaced
744
797
  - Path must be absolute (e.g., "/docs/readme.md", not "docs/readme.md")
745
798
  `,
746
- schema: z3.z.object({
747
- file_path: z3.z.string().describe("The absolute path to the file to write"),
748
- content: z3.z.string().describe("The content to write to the file")
799
+ schema: z13.z.object({
800
+ file_path: z13.z.string().describe("The absolute path to the file to write"),
801
+ content: z13.z.string().describe("The content to write to the file")
749
802
  }),
750
803
  strict: true
751
804
  };
@@ -765,13 +818,13 @@ IMPORTANT:
765
818
  - The operation fails if old_string is not found
766
819
  - old_string and new_string must be different
767
820
  `,
768
- schema: z3.z.object({
769
- file_path: z3.z.string().describe("The absolute virtual path to the file to modify"),
770
- old_string: z3.z.string().describe("The exact text to replace"),
771
- new_string: z3.z.string().describe(
821
+ schema: z13.z.object({
822
+ file_path: z13.z.string().describe("The absolute virtual path to the file to modify"),
823
+ old_string: z13.z.string().describe("The exact text to replace"),
824
+ new_string: z13.z.string().describe(
772
825
  "The text to replace it with (must be different from old_string)"
773
826
  ),
774
- replace_all: z3.z.boolean().optional().describe(
827
+ replace_all: z13.z.boolean().optional().describe(
775
828
  "If true, replace all occurrences of old_string (default: false)"
776
829
  )
777
830
  }),
@@ -818,17 +871,17 @@ var taskCreateTool = {
818
871
  - Include enough detail in the description for another agent to understand and complete the task
819
872
  - After creating tasks, use TaskUpdate to set up dependencies (blocks/blockedBy) if needed
820
873
  - Check TaskList first to avoid creating duplicate tasks`,
821
- schema: z3__default.default.object({
822
- subject: z3__default.default.string().describe(
874
+ schema: z13__default.default.object({
875
+ subject: z13__default.default.string().describe(
823
876
  'A brief, actionable title in imperative form (e.g., "Fix authentication bug in login flow")'
824
877
  ),
825
- description: z3__default.default.string().describe(
878
+ description: z13__default.default.string().describe(
826
879
  "Detailed description of what needs to be done, including context and acceptance criteria"
827
880
  ),
828
- activeForm: z3__default.default.string().describe(
881
+ activeForm: z13__default.default.string().describe(
829
882
  '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.'
830
883
  ),
831
- metadata: z3__default.default.record(z3__default.default.string(), z3__default.default.string()).describe("Arbitrary key-value pairs for tracking")
884
+ metadata: z13__default.default.record(z13__default.default.string(), z13__default.default.string()).describe("Arbitrary key-value pairs for tracking")
832
885
  })
833
886
  };
834
887
  function createTaskCreateHandler(stateManager) {
@@ -853,8 +906,8 @@ function createTaskCreateHandler(stateManager) {
853
906
  var taskGetTool = {
854
907
  name: "TaskGet",
855
908
  description: `Retrieve full task details including dependencies.`,
856
- schema: z3__default.default.object({
857
- taskId: z3__default.default.string().describe("The ID of the task to get")
909
+ schema: z13__default.default.object({
910
+ taskId: z13__default.default.string().describe("The ID of the task to get")
858
911
  })
859
912
  };
860
913
 
@@ -877,7 +930,7 @@ function createTaskGetHandler(stateManager) {
877
930
  var taskListTool = {
878
931
  name: "TaskList",
879
932
  description: `List all tasks with current state.`,
880
- schema: z3__default.default.object({})
933
+ schema: z13__default.default.object({})
881
934
  };
882
935
 
883
936
  // src/tools/task-list/handler.ts
@@ -893,11 +946,11 @@ function createTaskListHandler(stateManager) {
893
946
  var taskUpdateTool = {
894
947
  name: "TaskUpdate",
895
948
  description: `Update status, add blockers, modify details.`,
896
- schema: z3__default.default.object({
897
- taskId: z3__default.default.string().describe("The ID of the task to get"),
898
- status: z3__default.default.enum(["pending", "in_progress", "completed"]).describe("The status of the task"),
899
- addBlockedBy: z3__default.default.array(z3__default.default.string()).describe("The IDs of the tasks that are blocking this task"),
900
- addBlocks: z3__default.default.array(z3__default.default.string()).describe("The IDs of the tasks that this task is blocking")
949
+ schema: z13__default.default.object({
950
+ taskId: z13__default.default.string().describe("The ID of the task to get"),
951
+ status: z13__default.default.enum(["pending", "in_progress", "completed"]).describe("The status of the task"),
952
+ addBlockedBy: z13__default.default.array(z13__default.default.string()).describe("The IDs of the tasks that are blocking this task"),
953
+ addBlocks: z13__default.default.array(z13__default.default.string()).describe("The IDs of the tasks that this task is blocking")
901
954
  })
902
955
  };
903
956
 
@@ -965,18 +1018,59 @@ Use this tool to:
965
1018
  - Execute scripts and chain commands with pipes (|) or logical operators (&&, ||)
966
1019
  - Inspect files and directories
967
1020
  `,
968
- schema: z3__default.default.object({
969
- command: z3__default.default.string().describe(
1021
+ schema: z13__default.default.object({
1022
+ command: z13__default.default.string().describe(
970
1023
  "The bash command to execute. Can include pipes (|), redirects (>, >>), logical operators (&&, ||), and shell features like command substitution $(...)."
971
1024
  )
972
1025
  }),
973
1026
  strict: true
974
1027
  };
1028
+ var askUserQuestionTool = {
1029
+ name: "AskUserQuestion",
1030
+ description: `Use this tool when you need to ask the user questions during execution. This allows you to:
1031
+
1032
+ 1. Gather user preferences or requirements
1033
+ 2. Clarify ambiguous instructions
1034
+ 3. Get decisions on implementation choices as you work
1035
+ 4. Offer choices to the user about what direction to take.
1036
+
1037
+ Usage notes:
1038
+
1039
+ * Users will always be able to select "Other" to provide custom text input
1040
+ * Use multiSelect: true to allow multiple answers to be selected for a question
1041
+ * If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label
1042
+ `,
1043
+ schema: z13__default.default.object({
1044
+ questions: z13__default.default.array(
1045
+ z13__default.default.object({
1046
+ question: z13__default.default.string().describe("The full question text to display"),
1047
+ header: z13__default.default.string().describe("Short label for the question (max 12 characters)"),
1048
+ options: z13__default.default.array(
1049
+ z13__default.default.object({
1050
+ label: z13__default.default.string(),
1051
+ description: z13__default.default.string()
1052
+ })
1053
+ ).min(0).max(4).describe("Array of 0-4 choices, each with label and description"),
1054
+ multiSelect: z13__default.default.boolean().describe("If true, users can select multiple options")
1055
+ })
1056
+ )
1057
+ }),
1058
+ strict: true
1059
+ };
1060
+
1061
+ // src/tools/ask-user-question/handler.ts
1062
+ var createAskUserQuestionHandler = () => (args) => {
1063
+ return {
1064
+ toolResponse: "Question submitted",
1065
+ data: { questions: args.questions }
1066
+ };
1067
+ };
975
1068
 
976
1069
  exports.AGENT_HANDLER_NAMES = AGENT_HANDLER_NAMES;
977
1070
  exports.askUserQuestionTool = askUserQuestionTool;
978
1071
  exports.bashTool = bashTool;
979
1072
  exports.createAgentStateManager = createAgentStateManager;
1073
+ exports.createAskUserQuestionHandler = createAskUserQuestionHandler;
980
1074
  exports.createBashToolDescription = createBashToolDescription;
981
1075
  exports.createSession = createSession;
982
1076
  exports.createSubagentTool = createSubagentTool;