zeitlich 0.2.7 → 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.
@@ -116,7 +116,7 @@ interface ToolWithHandler<TName extends string = string, TSchema extends z$1.Zod
116
116
  strict?: boolean;
117
117
  max_uses?: number;
118
118
  /** Whether this tool is available to the agent (default: true). Disabled tools are excluded from definitions and rejected at parse time. */
119
- enabled?: boolean;
119
+ enabled?: () => boolean;
120
120
  /** Per-tool lifecycle hooks (run in addition to global hooks) */
121
121
  hooks?: ToolHooks<z$1.infer<TSchema>, TResult>;
122
122
  }
@@ -135,7 +135,7 @@ type ToolMap = Record<string, {
135
135
  handler: ToolHandler<any, any, any>;
136
136
  strict?: boolean;
137
137
  max_uses?: number;
138
- enabled?: boolean;
138
+ enabled?: () => boolean;
139
139
  hooks?: ToolHooks<any, any>;
140
140
  }>;
141
141
  /**
@@ -187,6 +187,8 @@ interface ToolHandlerResponse<TResult = null> {
187
187
  * payloads through Temporal's activity payload limit.
188
188
  */
189
189
  resultAppended?: boolean;
190
+ /** Token usage from the tool execution (e.g. child agent invocations) */
191
+ usage?: TokenUsage;
190
192
  }
191
193
  /**
192
194
  * Context passed to tool handlers for additional data beyond tool args.
@@ -237,6 +239,7 @@ interface ToolCallResult<TName extends string = string, TResult = unknown> {
237
239
  toolCallId: string;
238
240
  name: TName;
239
241
  data: TResult;
242
+ usage?: TokenUsage;
240
243
  }
241
244
  /**
242
245
  * Options for creating a tool router.
@@ -465,6 +468,10 @@ interface BaseAgentState {
465
468
  turns: number;
466
469
  tasks: Map<string, WorkflowTask>;
467
470
  systemPrompt: string;
471
+ totalInputTokens: number;
472
+ totalOutputTokens: number;
473
+ cachedWriteTokens: number;
474
+ cachedReadtTokens: number;
468
475
  }
469
476
  /**
470
477
  * File representation for agent workflows
@@ -481,17 +488,20 @@ interface AgentFile {
481
488
  /** MIME type of the file */
482
489
  mimeType?: string;
483
490
  }
491
+ interface TokenUsage {
492
+ inputTokens?: number;
493
+ outputTokens?: number;
494
+ cachedWriteTokens?: number;
495
+ cachedReadTokens?: number;
496
+ reasonTokens?: number;
497
+ }
484
498
  /**
485
499
  * Agent response from LLM invocation
486
500
  */
487
501
  interface AgentResponse<M = StoredMessage> {
488
502
  message: M;
489
503
  rawToolCalls: RawToolCall[];
490
- usage?: {
491
- input_tokens?: number;
492
- output_tokens?: number;
493
- total_tokens?: number;
494
- };
504
+ usage?: TokenUsage;
495
505
  }
496
506
  /**
497
507
  * Thread operations required by a session.
@@ -566,9 +576,10 @@ interface SerializableToolDefinition {
566
576
  /**
567
577
  * Configuration passed to runAgent activity
568
578
  */
569
- interface RunAgentConfig {
579
+ interface RunAgentConfig extends AgentConfig {
580
+ /** The thread ID to use for the session */
570
581
  threadId: string;
571
- agentName: string;
582
+ /** Metadata for the session */
572
583
  metadata?: Record<string, unknown>;
573
584
  }
574
585
  /**
@@ -597,7 +608,7 @@ interface SubagentConfig<TResult extends z$1.ZodType = z$1.ZodType> {
597
608
  /** Description shown to the parent agent explaining what this subagent does */
598
609
  description: string;
599
610
  /** Whether this subagent is available (default: true). Disabled subagents are excluded from the Subagent tool. */
600
- enabled?: boolean;
611
+ enabled?: () => boolean;
601
612
  /** Temporal workflow function or type name (used with executeChild) */
602
613
  workflow: string | Workflow;
603
614
  /** Optional task queue - defaults to parent's queue if not specified */
@@ -927,6 +938,23 @@ interface AgentStateManager<TCustom extends JsonSerializable<TCustom>> {
927
938
  deleteTask(id: string): boolean;
928
939
  /** Set the tools (converts Zod schemas to JSON Schema for serialization) */
929
940
  setTools(newTools: ToolDefinition[]): void;
941
+ /** Update the usage */
942
+ updateUsage(usage: {
943
+ inputTokens?: number;
944
+ outputTokens?: number;
945
+ cachedWriteTokens?: number;
946
+ cachedReadTokens?: number;
947
+ reasonTokens?: number;
948
+ }): void;
949
+ /** Get the total usage */
950
+ getTotalUsage(): {
951
+ totalInputTokens: number;
952
+ totalOutputTokens: number;
953
+ totalCachedWriteTokens: number;
954
+ totalCachedReadTokens: number;
955
+ totalReasonTokens: number;
956
+ turns: number;
957
+ };
930
958
  }
931
959
  /**
932
960
  * Creates an agent state manager for tracking workflow state.
@@ -954,7 +982,11 @@ declare const AGENT_HANDLER_NAMES: {
954
982
  interface ZeitlichSession<M = unknown> {
955
983
  runSession<T extends JsonSerializable<T>>(args: {
956
984
  stateManager: AgentStateManager<T>;
957
- }): Promise<M | null>;
985
+ }): Promise<{
986
+ finalMessage: M | null;
987
+ exitReason: SessionExitReason;
988
+ usage: ReturnType<AgentStateManager<T>["getTotalUsage"]>;
989
+ }>;
958
990
  }
959
991
  /**
960
992
  * Session-level hooks for lifecycle events
@@ -965,7 +997,7 @@ interface SessionLifecycleHooks {
965
997
  /** Called when session ends */
966
998
  onSessionEnd?: SessionEndHook;
967
999
  }
968
- declare const createSession: <T extends ToolMap, M = unknown>({ threadId, agentName, maxTurns, metadata, runAgent, threadOps, buildContextMessage, subagents, tools, processToolsInParallel, hooks, appendSystemPrompt, systemPrompt, waitForInputTimeout, }: SessionConfig<T, M> & AgentConfig) => Promise<ZeitlichSession<M>>;
1000
+ declare const createSession: <T extends ToolMap, M = unknown>({ threadId, agentName, description, maxTurns, metadata, runAgent, threadOps, buildContextMessage, subagents, tools, processToolsInParallel, hooks, appendSystemPrompt, systemPrompt, waitForInputTimeout, }: SessionConfig<T, M> & AgentConfig) => Promise<ZeitlichSession<M>>;
969
1001
  /**
970
1002
  * Proxy the default ZeitlichSharedActivities as ThreadOps<StoredMessage>.
971
1003
  * Call this in workflow code for the standard LangChain/StoredMessage setup.
@@ -116,7 +116,7 @@ interface ToolWithHandler<TName extends string = string, TSchema extends z$1.Zod
116
116
  strict?: boolean;
117
117
  max_uses?: number;
118
118
  /** Whether this tool is available to the agent (default: true). Disabled tools are excluded from definitions and rejected at parse time. */
119
- enabled?: boolean;
119
+ enabled?: () => boolean;
120
120
  /** Per-tool lifecycle hooks (run in addition to global hooks) */
121
121
  hooks?: ToolHooks<z$1.infer<TSchema>, TResult>;
122
122
  }
@@ -135,7 +135,7 @@ type ToolMap = Record<string, {
135
135
  handler: ToolHandler<any, any, any>;
136
136
  strict?: boolean;
137
137
  max_uses?: number;
138
- enabled?: boolean;
138
+ enabled?: () => boolean;
139
139
  hooks?: ToolHooks<any, any>;
140
140
  }>;
141
141
  /**
@@ -187,6 +187,8 @@ interface ToolHandlerResponse<TResult = null> {
187
187
  * payloads through Temporal's activity payload limit.
188
188
  */
189
189
  resultAppended?: boolean;
190
+ /** Token usage from the tool execution (e.g. child agent invocations) */
191
+ usage?: TokenUsage;
190
192
  }
191
193
  /**
192
194
  * Context passed to tool handlers for additional data beyond tool args.
@@ -237,6 +239,7 @@ interface ToolCallResult<TName extends string = string, TResult = unknown> {
237
239
  toolCallId: string;
238
240
  name: TName;
239
241
  data: TResult;
242
+ usage?: TokenUsage;
240
243
  }
241
244
  /**
242
245
  * Options for creating a tool router.
@@ -465,6 +468,10 @@ interface BaseAgentState {
465
468
  turns: number;
466
469
  tasks: Map<string, WorkflowTask>;
467
470
  systemPrompt: string;
471
+ totalInputTokens: number;
472
+ totalOutputTokens: number;
473
+ cachedWriteTokens: number;
474
+ cachedReadtTokens: number;
468
475
  }
469
476
  /**
470
477
  * File representation for agent workflows
@@ -481,17 +488,20 @@ interface AgentFile {
481
488
  /** MIME type of the file */
482
489
  mimeType?: string;
483
490
  }
491
+ interface TokenUsage {
492
+ inputTokens?: number;
493
+ outputTokens?: number;
494
+ cachedWriteTokens?: number;
495
+ cachedReadTokens?: number;
496
+ reasonTokens?: number;
497
+ }
484
498
  /**
485
499
  * Agent response from LLM invocation
486
500
  */
487
501
  interface AgentResponse<M = StoredMessage> {
488
502
  message: M;
489
503
  rawToolCalls: RawToolCall[];
490
- usage?: {
491
- input_tokens?: number;
492
- output_tokens?: number;
493
- total_tokens?: number;
494
- };
504
+ usage?: TokenUsage;
495
505
  }
496
506
  /**
497
507
  * Thread operations required by a session.
@@ -566,9 +576,10 @@ interface SerializableToolDefinition {
566
576
  /**
567
577
  * Configuration passed to runAgent activity
568
578
  */
569
- interface RunAgentConfig {
579
+ interface RunAgentConfig extends AgentConfig {
580
+ /** The thread ID to use for the session */
570
581
  threadId: string;
571
- agentName: string;
582
+ /** Metadata for the session */
572
583
  metadata?: Record<string, unknown>;
573
584
  }
574
585
  /**
@@ -597,7 +608,7 @@ interface SubagentConfig<TResult extends z$1.ZodType = z$1.ZodType> {
597
608
  /** Description shown to the parent agent explaining what this subagent does */
598
609
  description: string;
599
610
  /** Whether this subagent is available (default: true). Disabled subagents are excluded from the Subagent tool. */
600
- enabled?: boolean;
611
+ enabled?: () => boolean;
601
612
  /** Temporal workflow function or type name (used with executeChild) */
602
613
  workflow: string | Workflow;
603
614
  /** Optional task queue - defaults to parent's queue if not specified */
@@ -927,6 +938,23 @@ interface AgentStateManager<TCustom extends JsonSerializable<TCustom>> {
927
938
  deleteTask(id: string): boolean;
928
939
  /** Set the tools (converts Zod schemas to JSON Schema for serialization) */
929
940
  setTools(newTools: ToolDefinition[]): void;
941
+ /** Update the usage */
942
+ updateUsage(usage: {
943
+ inputTokens?: number;
944
+ outputTokens?: number;
945
+ cachedWriteTokens?: number;
946
+ cachedReadTokens?: number;
947
+ reasonTokens?: number;
948
+ }): void;
949
+ /** Get the total usage */
950
+ getTotalUsage(): {
951
+ totalInputTokens: number;
952
+ totalOutputTokens: number;
953
+ totalCachedWriteTokens: number;
954
+ totalCachedReadTokens: number;
955
+ totalReasonTokens: number;
956
+ turns: number;
957
+ };
930
958
  }
931
959
  /**
932
960
  * Creates an agent state manager for tracking workflow state.
@@ -954,7 +982,11 @@ declare const AGENT_HANDLER_NAMES: {
954
982
  interface ZeitlichSession<M = unknown> {
955
983
  runSession<T extends JsonSerializable<T>>(args: {
956
984
  stateManager: AgentStateManager<T>;
957
- }): Promise<M | null>;
985
+ }): Promise<{
986
+ finalMessage: M | null;
987
+ exitReason: SessionExitReason;
988
+ usage: ReturnType<AgentStateManager<T>["getTotalUsage"]>;
989
+ }>;
958
990
  }
959
991
  /**
960
992
  * Session-level hooks for lifecycle events
@@ -965,7 +997,7 @@ interface SessionLifecycleHooks {
965
997
  /** Called when session ends */
966
998
  onSessionEnd?: SessionEndHook;
967
999
  }
968
- declare const createSession: <T extends ToolMap, M = unknown>({ threadId, agentName, maxTurns, metadata, runAgent, threadOps, buildContextMessage, subagents, tools, processToolsInParallel, hooks, appendSystemPrompt, systemPrompt, waitForInputTimeout, }: SessionConfig<T, M> & AgentConfig) => Promise<ZeitlichSession<M>>;
1000
+ declare const createSession: <T extends ToolMap, M = unknown>({ threadId, agentName, description, maxTurns, metadata, runAgent, threadOps, buildContextMessage, subagents, tools, processToolsInParallel, hooks, appendSystemPrompt, systemPrompt, waitForInputTimeout, }: SessionConfig<T, M> & AgentConfig) => Promise<ZeitlichSession<M>>;
969
1001
  /**
970
1002
  * Proxy the default ZeitlichSharedActivities as ThreadOps<StoredMessage>.
971
1003
  * Call this in workflow code for the standard LangChain/StoredMessage setup.
package/dist/workflow.cjs CHANGED
@@ -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,
@@ -425,7 +424,9 @@ var createSession = async ({
425
424
  }
426
425
  };
427
426
  return {
428
- runSession: async ({ stateManager }) => {
427
+ runSession: async ({
428
+ stateManager
429
+ }) => {
429
430
  workflow.setHandler(
430
431
  workflow.defineUpdate(`add${agentName}Message`),
431
432
  async (message) => {
@@ -452,7 +453,6 @@ var createSession = async ({
452
453
  metadata
453
454
  });
454
455
  }
455
- stateManager.setTools(toolRouter.getToolDefinitions());
456
456
  await initializeThread(threadId);
457
457
  if (appendSystemPrompt && systemPrompt && systemPrompt.trim() !== "") {
458
458
  await appendSystemMessage(threadId, systemPrompt);
@@ -463,15 +463,25 @@ var createSession = async ({
463
463
  while (stateManager.isRunning() && !stateManager.isTerminal() && stateManager.getTurns() < maxTurns) {
464
464
  stateManager.incrementTurns();
465
465
  const currentTurn = stateManager.getTurns();
466
- const { message, rawToolCalls } = await runAgent({
466
+ stateManager.setTools(toolRouter.getToolDefinitions());
467
+ const { message, rawToolCalls, usage } = await runAgent({
467
468
  threadId,
468
469
  agentName,
469
- metadata
470
+ metadata,
471
+ systemPrompt,
472
+ description
470
473
  });
474
+ if (usage) {
475
+ stateManager.updateUsage(usage);
476
+ }
471
477
  if (!toolRouter.hasTools() || rawToolCalls.length === 0) {
472
478
  stateManager.complete();
473
479
  exitReason = "completed";
474
- return message;
480
+ return {
481
+ finalMessage: message,
482
+ exitReason,
483
+ usage: stateManager.getTotalUsage()
484
+ };
475
485
  }
476
486
  const parsedToolCalls = [];
477
487
  for (const tc of rawToolCalls) {
@@ -488,9 +498,17 @@ var createSession = async ({
488
498
  });
489
499
  }
490
500
  }
491
- await toolRouter.processToolCalls(parsedToolCalls, {
492
- turn: currentTurn
493
- });
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
+ }
494
512
  if (stateManager.getStatus() === "WAITING_FOR_INPUT") {
495
513
  const conditionMet = await workflow.condition(
496
514
  () => stateManager.getStatus() === "RUNNING",
@@ -512,7 +530,11 @@ var createSession = async ({
512
530
  } finally {
513
531
  await callSessionEnd(exitReason, stateManager.getTurns());
514
532
  }
515
- return null;
533
+ return {
534
+ finalMessage: null,
535
+ exitReason,
536
+ usage: stateManager.getTotalUsage()
537
+ };
516
538
  }
517
539
  };
518
540
  };
@@ -549,6 +571,11 @@ function createAgentStateManager({
549
571
  let version = initialState?.version ?? 0;
550
572
  let turns = initialState?.turns ?? 0;
551
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;
552
579
  const tasks = new Map(initialState?.tasks);
553
580
  const {
554
581
  status: _,
@@ -663,6 +690,23 @@ function createAgentStateManager({
663
690
  version++;
664
691
  }
665
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
+ };
666
710
  }
667
711
  };
668
712
  }