zeitlich 0.2.51 → 0.2.53

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.
Files changed (45) hide show
  1. package/dist/adapters/thread/anthropic/index.d.cts +5 -5
  2. package/dist/adapters/thread/anthropic/index.d.ts +5 -5
  3. package/dist/adapters/thread/anthropic/workflow.d.cts +5 -5
  4. package/dist/adapters/thread/anthropic/workflow.d.ts +5 -5
  5. package/dist/adapters/thread/google-genai/index.d.cts +3 -3
  6. package/dist/adapters/thread/google-genai/index.d.ts +3 -3
  7. package/dist/adapters/thread/google-genai/workflow.d.cts +5 -5
  8. package/dist/adapters/thread/google-genai/workflow.d.ts +5 -5
  9. package/dist/adapters/thread/langchain/index.d.cts +5 -5
  10. package/dist/adapters/thread/langchain/index.d.ts +5 -5
  11. package/dist/adapters/thread/langchain/workflow.d.cts +5 -5
  12. package/dist/adapters/thread/langchain/workflow.d.ts +5 -5
  13. package/dist/{cold-store-DyHodfAB.d.ts → cold-store-BbvJLhXJ.d.ts} +1 -1
  14. package/dist/{cold-store-YOx9nmgR.d.cts → cold-store-Ki_U0jyd.d.cts} +1 -1
  15. package/dist/index.cjs +38 -3
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +8 -8
  18. package/dist/index.d.ts +8 -8
  19. package/dist/index.js +38 -3
  20. package/dist/index.js.map +1 -1
  21. package/dist/{proxy-CmiTP4pp.d.ts → proxy-CwniAm8W.d.ts} +1 -1
  22. package/dist/{proxy-2htgGQrc.d.cts → proxy-wsNrEh2u.d.cts} +1 -1
  23. package/dist/{thread-manager-CcvltOuq.d.ts → thread-manager-D1zfZnxi.d.ts} +2 -2
  24. package/dist/{thread-manager-DHAbncHX.d.ts → thread-manager-DCXkMqHH.d.ts} +2 -2
  25. package/dist/{thread-manager-BQAbrYXH.d.cts → thread-manager-DW7FqMdN.d.cts} +2 -2
  26. package/dist/{thread-manager-BJ5pz5Cx.d.cts → thread-manager-DhvA5oDL.d.cts} +2 -2
  27. package/dist/{types-DiI7mZhI.d.ts → types-DQQKF5FQ.d.ts} +24 -2
  28. package/dist/{types-BjdqxKYp.d.cts → types-DpHBKA8c.d.cts} +24 -2
  29. package/dist/{types-N_LTWe4b.d.cts → types-tJ9Or7u_.d.cts} +1 -1
  30. package/dist/{types-DEbkLA06.d.ts → types-ziu6HZPh.d.ts} +1 -1
  31. package/dist/{workflow-DBjPOKBr.d.ts → workflow-BeMiPEq4.d.ts} +2 -1
  32. package/dist/{workflow-CcgD6EUB.d.cts → workflow-CNTNwEnj.d.cts} +2 -1
  33. package/dist/workflow.cjs +38 -3
  34. package/dist/workflow.cjs.map +1 -1
  35. package/dist/workflow.d.cts +2 -2
  36. package/dist/workflow.d.ts +2 -2
  37. package/dist/workflow.js +38 -3
  38. package/dist/workflow.js.map +1 -1
  39. package/package.json +2 -2
  40. package/src/lib/hooks/index.ts +2 -0
  41. package/src/lib/hooks/types.ts +26 -1
  42. package/src/lib/observability/hooks.ts +17 -2
  43. package/src/lib/session/session.ts +31 -3
  44. package/src/lib/state/types.ts +9 -11
  45. package/src/workflow.ts +2 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zeitlich",
3
- "version": "0.2.51",
3
+ "version": "0.2.53",
4
4
  "description": "[EXPERIMENTAL] An opinionated AI agent implementation for Temporal",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -181,7 +181,7 @@
181
181
  "node": ">=18"
182
182
  },
183
183
  "devDependencies": {
184
- "@anthropic-ai/sdk": "^0.100.1",
184
+ "@anthropic-ai/sdk": "^0.102.0",
185
185
  "@aws-sdk/client-s3": "^3.1000.0",
186
186
  "@aws-sdk/lib-storage": "^3.1000.0",
187
187
  "@daytonaio/sdk": "^0.184.0",
@@ -3,6 +3,8 @@ export type {
3
3
  SessionStartHook,
4
4
  SessionEndHookContext,
5
5
  SessionEndHook,
6
+ TurnCompleteHookContext,
7
+ TurnCompleteHook,
6
8
  PreHumanMessageAppendHookContext,
7
9
  PreHumanMessageAppendHook,
8
10
  PostHumanMessageAppendHookContext,
@@ -1,4 +1,4 @@
1
- import type { SessionExitReason } from "../types";
1
+ import type { SessionExitReason, TokenUsage } from "../types";
2
2
  import type { ToolMap, ToolRouterHooks } from "../tool-router/types";
3
3
 
4
4
  // ============================================================================
@@ -29,6 +29,7 @@ export interface SessionEndHookContext {
29
29
  agentName: string;
30
30
  exitReason: SessionExitReason;
31
31
  turns: number;
32
+ usage: TokenUsage;
32
33
  metadata: Record<string, unknown>;
33
34
  }
34
35
 
@@ -39,6 +40,28 @@ export type SessionEndHook = (
39
40
  ctx: SessionEndHookContext
40
41
  ) => void | Promise<void>;
41
42
 
43
+ /**
44
+ * Context for TurnComplete hook - called after each agent turn commits
45
+ * (i.e. once per model invocation, excluding rewound turns)
46
+ */
47
+ export interface TurnCompleteHookContext {
48
+ threadId: string;
49
+ agentName: string;
50
+ /** 1-based turn number that just completed */
51
+ turn: number;
52
+ /** Number of tool calls the model requested this turn */
53
+ toolCallCount: number;
54
+ /** Token usage reported by the model for this turn, if available */
55
+ usage?: TokenUsage;
56
+ }
57
+
58
+ /**
59
+ * TurnComplete hook - called after each agent turn commits
60
+ */
61
+ export type TurnCompleteHook = (
62
+ ctx: TurnCompleteHookContext
63
+ ) => void | Promise<void>;
64
+
42
65
  // ============================================================================
43
66
  // Message Lifecycle Hooks
44
67
  // ============================================================================
@@ -95,4 +118,6 @@ export interface Hooks<
95
118
  onSessionStart?: SessionStartHook;
96
119
  /** Called when session ends */
97
120
  onSessionEnd?: SessionEndHook;
121
+ /** Called after each agent turn commits (excludes rewound turns) */
122
+ onTurnComplete?: TurnCompleteHook;
98
123
  }
@@ -1,6 +1,10 @@
1
1
  import { proxySinks } from "@temporalio/workflow";
2
2
  import type { ZeitlichObservabilitySinks } from "./sinks";
3
- import type { SessionStartHook, SessionEndHook } from "../hooks/types";
3
+ import type {
4
+ SessionStartHook,
5
+ SessionEndHook,
6
+ TurnCompleteHook,
7
+ } from "../hooks/types";
4
8
  import type {
5
9
  PostToolUseHook,
6
10
  PostToolUseFailureHook,
@@ -9,6 +13,7 @@ import type {
9
13
  export interface ObservabilityHooks {
10
14
  onSessionStart: SessionStartHook;
11
15
  onSessionEnd: SessionEndHook;
16
+ onTurnComplete: TurnCompleteHook;
12
17
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
18
  onPostToolUse: PostToolUseHook<any, any>;
14
19
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -58,11 +63,21 @@ export function createObservabilityHooks(
58
63
  threadId: ctx.threadId,
59
64
  exitReason: ctx.exitReason,
60
65
  turns: ctx.turns,
61
- usage: {},
66
+ usage: ctx.usage,
62
67
  durationMs: Date.now() - sessionStartMs,
63
68
  });
64
69
  },
65
70
 
71
+ onTurnComplete: (ctx) => {
72
+ zeitlichMetrics.turnCompleted({
73
+ agentName,
74
+ threadId: ctx.threadId,
75
+ turn: ctx.turn,
76
+ toolCallCount: ctx.toolCallCount,
77
+ ...(ctx.usage && { usage: ctx.usage }),
78
+ });
79
+ },
80
+
66
81
  onPostToolUse: (ctx) => {
67
82
  zeitlichMetrics.toolExecuted({
68
83
  agentName,
@@ -4,7 +4,7 @@ import {
4
4
  ApplicationFailure,
5
5
  log,
6
6
  } from "@temporalio/workflow";
7
- import type { SessionExitReason } from "../types";
7
+ import type { SessionExitReason, TokenUsage } from "../types";
8
8
  import type { SessionConfig, ZeitlichSession } from "./types";
9
9
  import { resolveSessionLifecycle } from "./types";
10
10
  import type {
@@ -232,7 +232,8 @@ export async function createSession<
232
232
 
233
233
  const callSessionEnd = async (
234
234
  exitReason: SessionExitReason,
235
- turns: number
235
+ turns: number,
236
+ usage: TokenUsage
236
237
  ): Promise<void> => {
237
238
  if (hooks.onSessionEnd) {
238
239
  await hooks.onSessionEnd({
@@ -240,6 +241,7 @@ export async function createSession<
240
241
  agentName,
241
242
  exitReason,
242
243
  turns,
244
+ usage,
243
245
  metadata,
244
246
  });
245
247
  }
@@ -554,6 +556,15 @@ export async function createSession<
554
556
  });
555
557
 
556
558
  if (!toolRouter.hasTools() || rawToolCalls.length === 0) {
559
+ if (hooks.onTurnComplete) {
560
+ await hooks.onTurnComplete({
561
+ threadId,
562
+ agentName,
563
+ turn: currentTurn,
564
+ toolCallCount: rawToolCalls.length,
565
+ ...(usage && { usage }),
566
+ });
567
+ }
557
568
  stateManager.complete();
558
569
  exitReason = "completed";
559
570
  finalMessage = message;
@@ -638,6 +649,16 @@ export async function createSession<
638
649
 
639
650
  // Turn committed: fresh id for the next turn.
640
651
  assistantId = undefined;
652
+
653
+ if (hooks.onTurnComplete) {
654
+ await hooks.onTurnComplete({
655
+ threadId,
656
+ agentName,
657
+ turn: currentTurn,
658
+ toolCallCount: rawToolCalls.length,
659
+ ...(usage && { usage }),
660
+ });
661
+ }
641
662
  }
642
663
 
643
664
  if (stateManager.getTurns() >= maxTurns && stateManager.isRunning()) {
@@ -707,7 +728,14 @@ export async function createSession<
707
728
  });
708
729
  }
709
730
 
710
- await callSessionEnd(exitReason, stateManager.getTurns());
731
+ const totals = stateManager.getTotalUsage();
732
+ await callSessionEnd(exitReason, totals.turns, {
733
+ inputTokens: totals.totalInputTokens,
734
+ outputTokens: totals.totalOutputTokens,
735
+ cachedWriteTokens: totals.totalCachedWriteTokens,
736
+ cachedReadTokens: totals.totalCachedReadTokens,
737
+ reasonTokens: totals.totalReasonTokens,
738
+ });
711
739
 
712
740
  if (sandboxOwned && sandboxId && sandboxOps) {
713
741
  switch (resolvedShutdown) {
@@ -29,19 +29,17 @@ export type JsonValue =
29
29
  * Rejects: functions, symbols, undefined, class instances with methods
30
30
  */
31
31
  export type JsonSerializable<T> = {
32
- [K in keyof T]: T[K] extends JsonValue
33
- ? T[K]
34
- : T[K] extends JsonPrimitive
35
- ? T[K]
36
- : T[K] extends (infer U)[]
37
- ? U extends JsonValue
38
- ? T[K]
39
- : JsonSerializable<U>[]
40
- : T[K] extends object
41
- ? JsonSerializable<T[K]>
42
- : never;
32
+ [K in keyof T]: JsonSerializableValue<T[K]>;
43
33
  };
44
34
 
35
+ type JsonSerializableValue<V> = V extends JsonValue
36
+ ? V
37
+ : V extends (infer U)[]
38
+ ? JsonSerializableValue<U>[]
39
+ : V extends object
40
+ ? JsonSerializable<V>
41
+ : never;
42
+
45
43
  /**
46
44
  * Full state type combining base state with custom state
47
45
  */
package/src/workflow.ts CHANGED
@@ -116,6 +116,8 @@ export type {
116
116
  SessionStartHookContext,
117
117
  SessionEndHook,
118
118
  SessionEndHookContext,
119
+ TurnCompleteHook,
120
+ TurnCompleteHookContext,
119
121
  PreHumanMessageAppendHook,
120
122
  PreHumanMessageAppendHookContext,
121
123
  PostHumanMessageAppendHook,