zeitlich 0.2.47 → 0.2.48

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 (50) hide show
  1. package/README.md +2 -0
  2. package/dist/{activities-CPwKoUlD.d.cts → activities-BlQR5gX4.d.cts} +3 -3
  3. package/dist/{activities-DlaBxNID.d.ts → activities-DCaIPQBT.d.ts} +3 -3
  4. package/dist/adapters/thread/anthropic/index.d.cts +5 -5
  5. package/dist/adapters/thread/anthropic/index.d.ts +5 -5
  6. package/dist/adapters/thread/anthropic/workflow.d.cts +5 -5
  7. package/dist/adapters/thread/anthropic/workflow.d.ts +5 -5
  8. package/dist/adapters/thread/google-genai/index.d.cts +5 -5
  9. package/dist/adapters/thread/google-genai/index.d.ts +5 -5
  10. package/dist/adapters/thread/google-genai/workflow.d.cts +6 -6
  11. package/dist/adapters/thread/google-genai/workflow.d.ts +6 -6
  12. package/dist/adapters/thread/langchain/index.d.cts +5 -5
  13. package/dist/adapters/thread/langchain/index.d.ts +5 -5
  14. package/dist/adapters/thread/langchain/workflow.d.cts +5 -5
  15. package/dist/adapters/thread/langchain/workflow.d.ts +5 -5
  16. package/dist/{cold-store-Z2wvK2cV.d.cts → cold-store-UL13Sstw.d.cts} +1 -1
  17. package/dist/{cold-store-BDgJpwLI.d.ts → cold-store-aD4TSKlU.d.ts} +1 -1
  18. package/dist/index.cjs +48 -10
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +8 -8
  21. package/dist/index.d.ts +8 -8
  22. package/dist/index.js +48 -10
  23. package/dist/index.js.map +1 -1
  24. package/dist/{proxy-CDh3Rsa7.d.cts → proxy-BAty3CWM.d.cts} +1 -1
  25. package/dist/{proxy-Du8ggERu.d.ts → proxy-mbnwBhHw.d.ts} +1 -1
  26. package/dist/{thread-manager-Dw96FKH1.d.ts → thread-manager-CICj68PI.d.ts} +2 -2
  27. package/dist/{thread-manager-BjoYYXgd.d.cts → thread-manager-DsXvJ5cJ.d.cts} +2 -2
  28. package/dist/{thread-manager-DtHYws2F.d.ts → thread-manager-DtEtbUkp.d.ts} +2 -2
  29. package/dist/{thread-manager-D8zKNFZ9.d.cts → thread-manager-R6c3lnJy.d.cts} +2 -2
  30. package/dist/{types-BMJrsHo0.d.cts → types-DDLPnxBh.d.cts} +1 -1
  31. package/dist/{types-CtdOquo3.d.ts → types-DF4wzWQG.d.ts} +1 -1
  32. package/dist/{types-DNEl5uxQ.d.cts → types-DWeyCTYK.d.cts} +31 -0
  33. package/dist/{types-qQVZfhoT.d.ts → types-DwBYd0ij.d.ts} +31 -0
  34. package/dist/{workflow-BH9ImDGq.d.cts → workflow-DVNPR7eX.d.cts} +1 -1
  35. package/dist/{workflow-Cdw3-RNB.d.ts → workflow-DdaU7_j4.d.ts} +1 -1
  36. package/dist/workflow.cjs +48 -10
  37. package/dist/workflow.cjs.map +1 -1
  38. package/dist/workflow.d.cts +2 -2
  39. package/dist/workflow.d.ts +2 -2
  40. package/dist/workflow.js +48 -10
  41. package/dist/workflow.js.map +1 -1
  42. package/package.json +6 -6
  43. package/src/lib/lifecycle.ts +13 -1
  44. package/src/lib/session/session-edge-cases.integration.test.ts +44 -0
  45. package/src/lib/session/session.ts +15 -0
  46. package/src/lib/subagent/handler.ts +32 -6
  47. package/src/lib/subagent/subagent.integration.test.ts +41 -2
  48. package/src/lib/tool-router/router-edge-cases.integration.test.ts +36 -0
  49. package/src/lib/tool-router/router.ts +21 -3
  50. package/src/lib/tool-router/types.ts +20 -0
@@ -1,5 +1,5 @@
1
1
  import { ActivityOptions, ActivityInterfaceFor } from '@temporalio/workflow';
2
- import { T as ThreadOps } from './types-DNEl5uxQ.cjs';
2
+ import { T as ThreadOps } from './types-DWeyCTYK.cjs';
3
3
 
4
4
  /**
5
5
  * Shared proxy helper for thread operations.
@@ -1,5 +1,5 @@
1
1
  import { ActivityOptions, ActivityInterfaceFor } from '@temporalio/workflow';
2
- import { T as ThreadOps } from './types-qQVZfhoT.js';
2
+ import { T as ThreadOps } from './types-DwBYd0ij.js';
3
3
 
4
4
  /**
5
5
  * Shared proxy helper for thread operations.
@@ -1,7 +1,7 @@
1
1
  import Redis from 'ioredis';
2
- import { J as JsonValue } from './types-qQVZfhoT.js';
2
+ import { J as JsonValue } from './types-DwBYd0ij.js';
3
3
  import { MessageContent, StoredMessage, BaseMessage } from '@langchain/core/messages';
4
- import { T as ThreadManagerHooks, P as ProviderThreadManager } from './types-CtdOquo3.js';
4
+ import { T as ThreadManagerHooks, P as ProviderThreadManager } from './types-DF4wzWQG.js';
5
5
 
6
6
  /** SDK-native content type for LangChain human messages */
7
7
  type LangChainContent = string | MessageContent;
@@ -1,7 +1,7 @@
1
1
  import Redis from 'ioredis';
2
- import { J as JsonValue } from './types-DNEl5uxQ.cjs';
2
+ import { J as JsonValue } from './types-DWeyCTYK.cjs';
3
3
  import { MessageContent, StoredMessage, BaseMessage } from '@langchain/core/messages';
4
- import { T as ThreadManagerHooks, P as ProviderThreadManager } from './types-BMJrsHo0.cjs';
4
+ import { T as ThreadManagerHooks, P as ProviderThreadManager } from './types-DDLPnxBh.cjs';
5
5
 
6
6
  /** SDK-native content type for LangChain human messages */
7
7
  type LangChainContent = string | MessageContent;
@@ -1,7 +1,7 @@
1
1
  import Redis from 'ioredis';
2
2
  import Anthropic from '@anthropic-ai/sdk';
3
- import { J as JsonValue } from './types-qQVZfhoT.js';
4
- import { T as ThreadManagerHooks, P as ProviderThreadManager } from './types-CtdOquo3.js';
3
+ import { J as JsonValue } from './types-DwBYd0ij.js';
4
+ import { T as ThreadManagerHooks, P as ProviderThreadManager } from './types-DF4wzWQG.js';
5
5
 
6
6
  /** SDK-native content type for Anthropic human messages */
7
7
  type AnthropicContent = string | Anthropic.Messages.ContentBlockParam[];
@@ -1,7 +1,7 @@
1
1
  import Redis from 'ioredis';
2
2
  import Anthropic from '@anthropic-ai/sdk';
3
- import { J as JsonValue } from './types-DNEl5uxQ.cjs';
4
- import { T as ThreadManagerHooks, P as ProviderThreadManager } from './types-BMJrsHo0.cjs';
3
+ import { J as JsonValue } from './types-DWeyCTYK.cjs';
4
+ import { T as ThreadManagerHooks, P as ProviderThreadManager } from './types-DDLPnxBh.cjs';
5
5
 
6
6
  /** SDK-native content type for Anthropic human messages */
7
7
  type AnthropicContent = string | Anthropic.Messages.ContentBlockParam[];
@@ -1,5 +1,5 @@
1
1
  import Redis from 'ioredis';
2
- import { P as PersistedThreadState, J as JsonValue } from './types-DNEl5uxQ.cjs';
2
+ import { P as PersistedThreadState, J as JsonValue } from './types-DWeyCTYK.cjs';
3
3
 
4
4
  interface ThreadManagerConfig<T> {
5
5
  redis: Redis;
@@ -1,5 +1,5 @@
1
1
  import Redis from 'ioredis';
2
- import { P as PersistedThreadState, J as JsonValue } from './types-qQVZfhoT.js';
2
+ import { P as PersistedThreadState, J as JsonValue } from './types-DwBYd0ij.js';
3
3
 
4
4
  interface ThreadManagerConfig<T> {
5
5
  redis: Redis;
@@ -134,6 +134,18 @@ interface RouterContext {
134
134
  toolCallId: string;
135
135
  toolName: string;
136
136
  sandboxId?: string;
137
+ /**
138
+ * Id of the assistant message that issued this tool call (the message
139
+ * the session passed as `assistantMessageId` into `runAgent`). Present
140
+ * for any tool call processed through `processToolCalls` from a
141
+ * session; may be absent when the router is driven manually (e.g.
142
+ * tests, custom orchestrators).
143
+ *
144
+ * Subagent handlers that fork the parent's thread mid-call use this
145
+ * to truncate the orphan trailing assistant message from the forked
146
+ * thread so the child's first model call sees a well-formed history.
147
+ */
148
+ assistantMessageId?: string;
137
149
  }
138
150
  /**
139
151
  * A handler function for a specific tool.
@@ -201,6 +213,14 @@ interface ProcessToolCallsContext {
201
213
  turn?: number;
202
214
  /** Active sandbox ID (when a sandbox is configured for this session) */
203
215
  sandboxId?: string;
216
+ /**
217
+ * Id of the assistant message that produced these tool calls. The
218
+ * router forwards it into every handler's {@link RouterContext} so
219
+ * handlers can reference the message they were issued from (e.g.
220
+ * subagent forks that need to truncate the orphan assistant message
221
+ * out of a parent-forked thread).
222
+ */
223
+ assistantMessageId?: string;
204
224
  }
205
225
  /**
206
226
  * Signal that a tool handler requested a rewind. Attached to the
@@ -887,6 +907,14 @@ interface Hooks<T extends ToolMap, TResult = unknown, TContent = unknown> extend
887
907
  * continue there. When the adapter has `onForkPrepareThread` and/or
888
908
  * `onForkTransform` hooks configured, they are applied once to the forked
889
909
  * thread before the session starts.
910
+ *
911
+ * The optional `truncateAfterFork.fromMessageId` directs the session to
912
+ * call `truncateThread` on the freshly forked thread immediately after
913
+ * the fork, dropping that message and everything after. Used by
914
+ * subagents that fork their parent's thread mid-tool-call to strip the
915
+ * orphan assistant `tool_use` block (the one whose `tool_result` will
916
+ * never arrive in the child's thread) so the first model call doesn't
917
+ * reject on an unmatched tool-use/tool-result pair.
890
918
  */
891
919
  type ThreadInit = {
892
920
  mode: "new";
@@ -897,6 +925,9 @@ type ThreadInit = {
897
925
  } | {
898
926
  mode: "fork";
899
927
  threadId: string;
928
+ truncateAfterFork?: {
929
+ fromMessageId: string;
930
+ };
900
931
  };
901
932
 
902
933
  /**
@@ -134,6 +134,18 @@ interface RouterContext {
134
134
  toolCallId: string;
135
135
  toolName: string;
136
136
  sandboxId?: string;
137
+ /**
138
+ * Id of the assistant message that issued this tool call (the message
139
+ * the session passed as `assistantMessageId` into `runAgent`). Present
140
+ * for any tool call processed through `processToolCalls` from a
141
+ * session; may be absent when the router is driven manually (e.g.
142
+ * tests, custom orchestrators).
143
+ *
144
+ * Subagent handlers that fork the parent's thread mid-call use this
145
+ * to truncate the orphan trailing assistant message from the forked
146
+ * thread so the child's first model call sees a well-formed history.
147
+ */
148
+ assistantMessageId?: string;
137
149
  }
138
150
  /**
139
151
  * A handler function for a specific tool.
@@ -201,6 +213,14 @@ interface ProcessToolCallsContext {
201
213
  turn?: number;
202
214
  /** Active sandbox ID (when a sandbox is configured for this session) */
203
215
  sandboxId?: string;
216
+ /**
217
+ * Id of the assistant message that produced these tool calls. The
218
+ * router forwards it into every handler's {@link RouterContext} so
219
+ * handlers can reference the message they were issued from (e.g.
220
+ * subagent forks that need to truncate the orphan assistant message
221
+ * out of a parent-forked thread).
222
+ */
223
+ assistantMessageId?: string;
204
224
  }
205
225
  /**
206
226
  * Signal that a tool handler requested a rewind. Attached to the
@@ -887,6 +907,14 @@ interface Hooks<T extends ToolMap, TResult = unknown, TContent = unknown> extend
887
907
  * continue there. When the adapter has `onForkPrepareThread` and/or
888
908
  * `onForkTransform` hooks configured, they are applied once to the forked
889
909
  * thread before the session starts.
910
+ *
911
+ * The optional `truncateAfterFork.fromMessageId` directs the session to
912
+ * call `truncateThread` on the freshly forked thread immediately after
913
+ * the fork, dropping that message and everything after. Used by
914
+ * subagents that fork their parent's thread mid-tool-call to strip the
915
+ * orphan assistant `tool_use` block (the one whose `tool_result` will
916
+ * never arrive in the child's thread) so the first model call doesn't
917
+ * reject on an unmatched tool-use/tool-result pair.
890
918
  */
891
919
  type ThreadInit = {
892
920
  mode: "new";
@@ -897,6 +925,9 @@ type ThreadInit = {
897
925
  } | {
898
926
  mode: "fork";
899
927
  threadId: string;
928
+ truncateAfterFork?: {
929
+ fromMessageId: string;
930
+ };
900
931
  };
901
932
 
902
933
  /**
@@ -1,4 +1,4 @@
1
- import { au as ToolMap, _ as SandboxInit, ah as SubagentSandboxShutdown, a1 as SessionConfig, aF as ZeitlichSession, $ as SandboxShutdown, am as ThreadInit, u as JsonSerializable, B as BaseAgentState, p as AgentStateManager, aH as ToolRouterOptions, ax as ToolRouter, R as RouterContext, J as JsonValue, az as ToolWithHandler, w as ParsedToolCallUnion, av as ToolNames, ac as SubagentDefinition, af as SubagentHooks, ag as SubagentSandboxConfig, aa as SubagentConfig, ai as SubagentSessionInput, ad as SubagentFnResult, a7 as SessionStartHook, a2 as SessionEndHook, E as PostToolUseHook, z as PostToolUseFailureHook, a4 as SessionExitReason, an as TokenUsage, f as RunAgentConfig, A as AgentResponse, F as FileEntryMetadata, aB as VirtualFileTree, k as TreeMutation, s as FileEntry, aC as VirtualFsOps, h as SkillMetadata, i as Skill, c as ToolHandlerResponse, as as ToolHandler, aE as WorkflowTask, d as ActivityToolHandler } from './types-DNEl5uxQ.cjs';
1
+ import { au as ToolMap, _ as SandboxInit, ah as SubagentSandboxShutdown, a1 as SessionConfig, aF as ZeitlichSession, $ as SandboxShutdown, am as ThreadInit, u as JsonSerializable, B as BaseAgentState, p as AgentStateManager, aH as ToolRouterOptions, ax as ToolRouter, R as RouterContext, J as JsonValue, az as ToolWithHandler, w as ParsedToolCallUnion, av as ToolNames, ac as SubagentDefinition, af as SubagentHooks, ag as SubagentSandboxConfig, aa as SubagentConfig, ai as SubagentSessionInput, ad as SubagentFnResult, a7 as SessionStartHook, a2 as SessionEndHook, E as PostToolUseHook, z as PostToolUseFailureHook, a4 as SessionExitReason, an as TokenUsage, f as RunAgentConfig, A as AgentResponse, F as FileEntryMetadata, aB as VirtualFileTree, k as TreeMutation, s as FileEntry, aC as VirtualFsOps, h as SkillMetadata, i as Skill, c as ToolHandlerResponse, as as ToolHandler, aE as WorkflowTask, d as ActivityToolHandler } from './types-DWeyCTYK.cjs';
2
2
  import z$1, { z } from 'zod';
3
3
  import './types-CJ7tCdl6.cjs';
4
4
  import { Duration } from '@temporalio/common';
@@ -1,4 +1,4 @@
1
- import { au as ToolMap, _ as SandboxInit, ah as SubagentSandboxShutdown, a1 as SessionConfig, aF as ZeitlichSession, $ as SandboxShutdown, am as ThreadInit, u as JsonSerializable, B as BaseAgentState, p as AgentStateManager, aH as ToolRouterOptions, ax as ToolRouter, R as RouterContext, J as JsonValue, az as ToolWithHandler, w as ParsedToolCallUnion, av as ToolNames, ac as SubagentDefinition, af as SubagentHooks, ag as SubagentSandboxConfig, aa as SubagentConfig, ai as SubagentSessionInput, ad as SubagentFnResult, a7 as SessionStartHook, a2 as SessionEndHook, E as PostToolUseHook, z as PostToolUseFailureHook, a4 as SessionExitReason, an as TokenUsage, f as RunAgentConfig, A as AgentResponse, F as FileEntryMetadata, aB as VirtualFileTree, k as TreeMutation, s as FileEntry, aC as VirtualFsOps, h as SkillMetadata, i as Skill, c as ToolHandlerResponse, as as ToolHandler, aE as WorkflowTask, d as ActivityToolHandler } from './types-qQVZfhoT.js';
1
+ import { au as ToolMap, _ as SandboxInit, ah as SubagentSandboxShutdown, a1 as SessionConfig, aF as ZeitlichSession, $ as SandboxShutdown, am as ThreadInit, u as JsonSerializable, B as BaseAgentState, p as AgentStateManager, aH as ToolRouterOptions, ax as ToolRouter, R as RouterContext, J as JsonValue, az as ToolWithHandler, w as ParsedToolCallUnion, av as ToolNames, ac as SubagentDefinition, af as SubagentHooks, ag as SubagentSandboxConfig, aa as SubagentConfig, ai as SubagentSessionInput, ad as SubagentFnResult, a7 as SessionStartHook, a2 as SessionEndHook, E as PostToolUseHook, z as PostToolUseFailureHook, a4 as SessionExitReason, an as TokenUsage, f as RunAgentConfig, A as AgentResponse, F as FileEntryMetadata, aB as VirtualFileTree, k as TreeMutation, s as FileEntry, aC as VirtualFsOps, h as SkillMetadata, i as Skill, c as ToolHandlerResponse, as as ToolHandler, aE as WorkflowTask, d as ActivityToolHandler } from './types-DwBYd0ij.js';
2
2
  import z$1, { z } from 'zod';
3
3
  import './types-CJ7tCdl6.js';
4
4
  import { Duration } from '@temporalio/common';
package/dist/workflow.cjs CHANGED
@@ -123,7 +123,7 @@ function createToolRouter(options) {
123
123
  });
124
124
  }
125
125
  }
126
- async function processToolCall(toolCall, turn, sandboxId, onRewindRequested) {
126
+ async function processToolCall(toolCall, turn, sandboxId, onRewindRequested, assistantMessageId) {
127
127
  const startTime = Date.now();
128
128
  const tool = toolMap.get(toolCall.name);
129
129
  const preResult = await runPreHooks(toolCall, tool, turn);
@@ -158,7 +158,8 @@ function createToolRouter(options) {
158
158
  ...options.threadKey && { threadKey: options.threadKey },
159
159
  toolCallId: toolCall.id,
160
160
  toolName: toolCall.name,
161
- ...sandboxId !== void 0 && { sandboxId }
161
+ ...sandboxId !== void 0 && { sandboxId },
162
+ ...assistantMessageId !== void 0 && { assistantMessageId }
162
163
  };
163
164
  const response = await tool.handler(
164
165
  effectiveArgs,
@@ -285,6 +286,7 @@ function createToolRouter(options) {
285
286
  }
286
287
  const turn = context?.turn ?? 0;
287
288
  const sandboxId = context?.sandboxId;
289
+ const assistantMessageId = context?.assistantMessageId;
288
290
  let rewindSignal;
289
291
  if (options.parallel) {
290
292
  const scope = new workflow.CancellationScope({ cancellable: true });
@@ -297,7 +299,13 @@ function createToolRouter(options) {
297
299
  const outcomes = await scope.run(
298
300
  async () => Promise.allSettled(
299
301
  toolCalls.map(
300
- (tc) => processToolCall(tc, turn, sandboxId, onRewindRequested)
302
+ (tc) => processToolCall(
303
+ tc,
304
+ turn,
305
+ sandboxId,
306
+ onRewindRequested,
307
+ assistantMessageId
308
+ )
301
309
  )
302
310
  )
303
311
  );
@@ -317,7 +325,13 @@ function createToolRouter(options) {
317
325
  }
318
326
  const results = [];
319
327
  for (const toolCall of toolCalls) {
320
- const outcome = await processToolCall(toolCall, turn, sandboxId);
328
+ const outcome = await processToolCall(
329
+ toolCall,
330
+ turn,
331
+ sandboxId,
332
+ void 0,
333
+ assistantMessageId
334
+ );
321
335
  if (outcome.kind === "rewind") {
322
336
  rewindSignal = outcome.signal;
323
337
  break;
@@ -341,6 +355,9 @@ function createToolRouter(options) {
341
355
  toolName: toolCall.name,
342
356
  ...context?.sandboxId !== void 0 && {
343
357
  sandboxId: context.sandboxId
358
+ },
359
+ ...context?.assistantMessageId !== void 0 && {
360
+ assistantMessageId: context.assistantMessageId
344
361
  }
345
362
  };
346
363
  const response = await handler(
@@ -567,13 +584,26 @@ function createSubagentHandler(subagents) {
567
584
  const threadMode = config.thread ?? "new";
568
585
  const allowsContinuation = threadMode !== "new";
569
586
  const newThreadSource = config.newThreadSource ?? "new";
570
- const continuationThreadId = !allowsContinuation ? void 0 : args.threadId ?? (newThreadSource === "from-parent" ? context.threadId : void 0);
587
+ const usingParentFallback = allowsContinuation && !args.threadId && newThreadSource === "from-parent";
588
+ const continuationThreadId = !allowsContinuation ? void 0 : args.threadId ?? (usingParentFallback ? context.threadId : void 0);
571
589
  let thread;
572
590
  if (continuationThreadId) {
573
- thread = {
574
- mode: threadMode,
575
- threadId: continuationThreadId
576
- };
591
+ if (threadMode === "fork") {
592
+ thread = {
593
+ mode: "fork",
594
+ threadId: continuationThreadId,
595
+ ...usingParentFallback && context.assistantMessageId ? {
596
+ truncateAfterFork: {
597
+ fromMessageId: context.assistantMessageId
598
+ }
599
+ } : {}
600
+ };
601
+ } else {
602
+ thread = {
603
+ mode: "continue",
604
+ threadId: continuationThreadId
605
+ };
606
+ }
577
607
  }
578
608
  let sandbox;
579
609
  let sandboxShutdownOverride;
@@ -1034,6 +1064,7 @@ async function createSession(config) {
1034
1064
  appendSystemMessage,
1035
1065
  appendAgentMessage,
1036
1066
  forkThread,
1067
+ truncateThread,
1037
1068
  loadThreadState,
1038
1069
  saveThreadState,
1039
1070
  hydrateThread,
@@ -1183,6 +1214,10 @@ async function createSession(config) {
1183
1214
  if (threadMode === "fork" && sourceThreadId) {
1184
1215
  await hydrateThread(sourceThreadId, threadKey);
1185
1216
  await forkThread(sourceThreadId, threadId, threadKey);
1217
+ const truncate = threadInit.truncateAfterFork;
1218
+ if (truncate?.fromMessageId) {
1219
+ await truncateThread(threadId, truncate.fromMessageId, threadKey);
1220
+ }
1186
1221
  const forkedSlice = await loadThreadState(threadId, threadKey);
1187
1222
  if (forkedSlice) rehydrateFromSlice(forkedSlice);
1188
1223
  } else if (threadMode === "continue") {
@@ -1312,7 +1347,10 @@ async function createSession(config) {
1312
1347
  parsedToolCalls,
1313
1348
  {
1314
1349
  turn: currentTurn,
1315
- ...sandboxId !== void 0 && { sandboxId }
1350
+ ...sandboxId !== void 0 && { sandboxId },
1351
+ ...assistantId !== void 0 && {
1352
+ assistantMessageId: assistantId
1353
+ }
1316
1354
  }
1317
1355
  );
1318
1356
  for (const result of toolCallResults) {