zeitlich 0.2.21 → 0.2.22

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 (117) hide show
  1. package/README.md +70 -55
  2. package/dist/adapters/sandbox/daytona/index.cjs +3 -0
  3. package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
  4. package/dist/adapters/sandbox/daytona/index.d.cts +2 -1
  5. package/dist/adapters/sandbox/daytona/index.d.ts +2 -1
  6. package/dist/adapters/sandbox/daytona/index.js +3 -0
  7. package/dist/adapters/sandbox/daytona/index.js.map +1 -1
  8. package/dist/adapters/sandbox/daytona/workflow.cjs +32 -0
  9. package/dist/adapters/sandbox/daytona/workflow.cjs.map +1 -0
  10. package/dist/adapters/sandbox/daytona/workflow.d.cts +27 -0
  11. package/dist/adapters/sandbox/daytona/workflow.d.ts +27 -0
  12. package/dist/adapters/sandbox/daytona/workflow.js +30 -0
  13. package/dist/adapters/sandbox/daytona/workflow.js.map +1 -0
  14. package/dist/adapters/sandbox/inmemory/index.cjs +4 -1
  15. package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
  16. package/dist/adapters/sandbox/inmemory/index.d.cts +3 -2
  17. package/dist/adapters/sandbox/inmemory/index.d.ts +3 -2
  18. package/dist/adapters/sandbox/inmemory/index.js +4 -1
  19. package/dist/adapters/sandbox/inmemory/index.js.map +1 -1
  20. package/dist/adapters/sandbox/inmemory/workflow.cjs +32 -0
  21. package/dist/adapters/sandbox/inmemory/workflow.cjs.map +1 -0
  22. package/dist/adapters/sandbox/inmemory/workflow.d.cts +25 -0
  23. package/dist/adapters/sandbox/inmemory/workflow.d.ts +25 -0
  24. package/dist/adapters/sandbox/inmemory/workflow.js +30 -0
  25. package/dist/adapters/sandbox/inmemory/workflow.js.map +1 -0
  26. package/dist/adapters/sandbox/virtual/index.cjs +3 -0
  27. package/dist/adapters/sandbox/virtual/index.cjs.map +1 -1
  28. package/dist/adapters/sandbox/virtual/index.d.cts +6 -4
  29. package/dist/adapters/sandbox/virtual/index.d.ts +6 -4
  30. package/dist/adapters/sandbox/virtual/index.js +3 -0
  31. package/dist/adapters/sandbox/virtual/index.js.map +1 -1
  32. package/dist/adapters/sandbox/virtual/workflow.cjs +32 -0
  33. package/dist/adapters/sandbox/virtual/workflow.cjs.map +1 -0
  34. package/dist/adapters/sandbox/virtual/workflow.d.cts +27 -0
  35. package/dist/adapters/sandbox/virtual/workflow.d.ts +27 -0
  36. package/dist/adapters/sandbox/virtual/workflow.js +30 -0
  37. package/dist/adapters/sandbox/virtual/workflow.js.map +1 -0
  38. package/dist/adapters/thread/google-genai/index.cjs +9 -1
  39. package/dist/adapters/thread/google-genai/index.cjs.map +1 -1
  40. package/dist/adapters/thread/google-genai/index.d.cts +30 -18
  41. package/dist/adapters/thread/google-genai/index.d.ts +30 -18
  42. package/dist/adapters/thread/google-genai/index.js +9 -1
  43. package/dist/adapters/thread/google-genai/index.js.map +1 -1
  44. package/dist/adapters/thread/google-genai/workflow.cjs +33 -0
  45. package/dist/adapters/thread/google-genai/workflow.cjs.map +1 -0
  46. package/dist/adapters/thread/google-genai/workflow.d.cts +32 -0
  47. package/dist/adapters/thread/google-genai/workflow.d.ts +32 -0
  48. package/dist/adapters/thread/google-genai/workflow.js +31 -0
  49. package/dist/adapters/thread/google-genai/workflow.js.map +1 -0
  50. package/dist/adapters/thread/langchain/index.cjs +9 -1
  51. package/dist/adapters/thread/langchain/index.cjs.map +1 -1
  52. package/dist/adapters/thread/langchain/index.d.cts +26 -15
  53. package/dist/adapters/thread/langchain/index.d.ts +26 -15
  54. package/dist/adapters/thread/langchain/index.js +9 -1
  55. package/dist/adapters/thread/langchain/index.js.map +1 -1
  56. package/dist/adapters/thread/langchain/workflow.cjs +33 -0
  57. package/dist/adapters/thread/langchain/workflow.cjs.map +1 -0
  58. package/dist/adapters/thread/langchain/workflow.d.cts +32 -0
  59. package/dist/adapters/thread/langchain/workflow.d.ts +32 -0
  60. package/dist/adapters/thread/langchain/workflow.js +31 -0
  61. package/dist/adapters/thread/langchain/workflow.js.map +1 -0
  62. package/dist/index.cjs +36 -34
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.d.cts +35 -14
  65. package/dist/index.d.ts +35 -14
  66. package/dist/index.js +38 -34
  67. package/dist/index.js.map +1 -1
  68. package/dist/queries-Bw6WEPMw.d.cts +44 -0
  69. package/dist/queries-C27raDaB.d.ts +44 -0
  70. package/dist/{queries-CHa2iv_I.d.cts → types-BJ8itUAl.d.cts} +2 -43
  71. package/dist/{types-BkAYmc96.d.ts → types-C5bkx6kQ.d.ts} +33 -5
  72. package/dist/{types-CES_30qx.d.cts → types-ClsHhtwL.d.cts} +33 -5
  73. package/dist/{queries-6Avfh74U.d.ts → types-ENYCKFBk.d.ts} +2 -43
  74. package/dist/{types-BMRzfELQ.d.cts → types-HBosetv3.d.cts} +15 -1
  75. package/dist/{types-BMRzfELQ.d.ts → types-HBosetv3.d.ts} +15 -1
  76. package/dist/workflow.cjs +4 -30
  77. package/dist/workflow.cjs.map +1 -1
  78. package/dist/workflow.d.cts +13 -41
  79. package/dist/workflow.d.ts +13 -41
  80. package/dist/workflow.js +6 -30
  81. package/dist/workflow.js.map +1 -1
  82. package/package.json +53 -1
  83. package/src/adapters/sandbox/daytona/index.ts +4 -0
  84. package/src/adapters/sandbox/daytona/proxy.ts +55 -0
  85. package/src/adapters/sandbox/e2b/filesystem.ts +147 -0
  86. package/src/adapters/sandbox/e2b/index.ts +159 -0
  87. package/src/adapters/sandbox/e2b/types.ts +23 -0
  88. package/src/adapters/sandbox/inmemory/index.ts +5 -1
  89. package/src/adapters/sandbox/inmemory/proxy.ts +53 -0
  90. package/src/adapters/sandbox/virtual/provider.ts +5 -1
  91. package/src/adapters/sandbox/virtual/proxy.ts +52 -0
  92. package/src/adapters/thread/google-genai/activities.ts +51 -17
  93. package/src/adapters/thread/google-genai/index.ts +1 -0
  94. package/src/adapters/thread/google-genai/proxy.ts +61 -0
  95. package/src/adapters/thread/langchain/activities.ts +47 -14
  96. package/src/adapters/thread/langchain/index.ts +1 -0
  97. package/src/adapters/thread/langchain/proxy.ts +61 -0
  98. package/src/lib/sandbox/manager.ts +40 -6
  99. package/src/lib/sandbox/sandbox.test.ts +12 -11
  100. package/src/lib/sandbox/types.ts +18 -0
  101. package/src/lib/session/index.ts +3 -5
  102. package/src/lib/session/session-edge-cases.integration.test.ts +45 -34
  103. package/src/lib/session/session.integration.test.ts +40 -48
  104. package/src/lib/session/session.ts +4 -66
  105. package/src/lib/session/types.ts +32 -1
  106. package/src/lib/subagent/define.ts +1 -1
  107. package/src/lib/subagent/handler.ts +9 -2
  108. package/src/lib/subagent/index.ts +1 -0
  109. package/src/lib/subagent/subagent.integration.test.ts +62 -0
  110. package/src/lib/subagent/types.ts +7 -2
  111. package/src/lib/tool-router/router-edge-cases.integration.test.ts +4 -1
  112. package/src/lib/tool-router/router.integration.test.ts +4 -1
  113. package/src/lib/workflow.test.ts +19 -10
  114. package/src/lib/workflow.ts +4 -1
  115. package/src/tools/bash/bash.test.ts +16 -7
  116. package/src/workflow.ts +6 -14
  117. package/tsup.config.ts +6 -0
@@ -1,5 +1,5 @@
1
1
  import Redis from 'ioredis';
2
- import { T as ThreadOps, M as ModelInvoker, a as ModelInvokerConfig, A as AgentResponse } from '../../../types-BkAYmc96.js';
2
+ import { M as ModelInvoker, P as PrefixedThreadOps, S as ScopedPrefix, a as ModelInvokerConfig, A as AgentResponse } from '../../../types-C5bkx6kQ.js';
3
3
  import { StoredMessage, MessageContent, $InferMessageContent, MessageStructure } from '@langchain/core/messages';
4
4
  import { BaseChatModel } from '@langchain/core/language_models/chat_models';
5
5
  import { B as BaseThreadManager } from '../../../types-35POpVfa.js';
@@ -7,29 +7,41 @@ import '@temporalio/common';
7
7
  import '../../../types-YbL7JpEA.js';
8
8
  import 'zod';
9
9
  import '@temporalio/workflow';
10
- import '../../../types-BMRzfELQ.js';
10
+ import '../../../types-HBosetv3.js';
11
11
  import '@temporalio/common/lib/interfaces';
12
12
 
13
+ declare const ADAPTER_PREFIX: "langChain";
14
+ type LangChainThreadOps<TScope extends string = ""> = PrefixedThreadOps<ScopedPrefix<TScope, typeof ADAPTER_PREFIX>>;
13
15
  interface LangChainAdapterConfig {
14
16
  redis: Redis;
15
17
  /** Optional default model — if omitted, use `createModelInvoker()` to create invokers later */
16
18
  model?: BaseChatModel<any>;
17
19
  }
18
20
  interface LangChainAdapter {
19
- /** Thread operations (register these as Temporal activities on the worker) */
20
- threadOps: ThreadOps;
21
21
  /** Model invoker using the default model (only available when `model` was provided) */
22
22
  invoker: ModelInvoker<StoredMessage>;
23
23
  /** Create an invoker for a specific model (for multi-model setups) */
24
24
  createModelInvoker(model: BaseChatModel<any>): ModelInvoker<StoredMessage>;
25
+ /**
26
+ * Create prefixed thread activities for registration on the worker.
27
+ *
28
+ * @param scope - Workflow name appended to the adapter prefix.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * adapter.createActivities("codingAgent")
33
+ * // → { langChainCodingAgentInitializeThread, langChainCodingAgentAppendHumanMessage, … }
34
+ * ```
35
+ */
36
+ createActivities<S extends string = "">(scope?: S): LangChainThreadOps<S>;
25
37
  }
26
38
  /**
27
39
  * Creates a LangChain adapter that bundles thread operations and model
28
40
  * invocation using a consistent message format (StoredMessage).
29
41
  *
30
- * The returned `threadOps` should be registered as Temporal activities on
31
- * the worker. The `invoker` (or invokers created via `createModelInvoker`)
32
- * should be wrapped with `createRunAgentActivity` for per-agent activities.
42
+ * Use `createActivities(scope)` to register scoped thread operations as
43
+ * Temporal activities on the worker. The `invoker` (or invokers created via
44
+ * `createModelInvoker`) should be wrapped with `createRunAgentActivity`.
33
45
  *
34
46
  * @example
35
47
  * ```typescript
@@ -40,21 +52,20 @@ interface LangChainAdapter {
40
52
  *
41
53
  * export function createActivities(client: WorkflowClient) {
42
54
  * return {
43
- * ...adapter.threadOps,
44
- * runAgent: createRunAgentActivity(client, adapter.invoker),
55
+ * ...adapter.createActivities("codingAgent"),
56
+ * runCodingAgent: createRunAgentActivity(client, adapter.invoker),
45
57
  * };
46
58
  * }
47
59
  * ```
48
60
  *
49
- * @example Multi-model setup
61
+ * @example Multi-agent worker
50
62
  * ```typescript
51
- * const adapter = createLangChainAdapter({ redis });
52
- *
53
63
  * export function createActivities(client: WorkflowClient) {
54
64
  * return {
55
- * ...adapter.threadOps,
65
+ * ...adapter.createActivities("codingAgent"),
66
+ * ...adapter.createActivities("researchAgent"),
67
+ * runCodingAgent: createRunAgentActivity(client, adapter.invoker),
56
68
  * runResearchAgent: createRunAgentActivity(client, adapter.createModelInvoker(claude)),
57
- * runWriterAgent: createRunAgentActivity(client, adapter.createModelInvoker(gpt4)),
58
69
  * };
59
70
  * }
60
71
  * ```
@@ -125,4 +136,4 @@ declare function invokeLangChainModel<TModel extends BaseChatModel<any> = BaseCh
125
136
  model: TModel;
126
137
  }): Promise<AgentResponse<StoredMessage>>;
127
138
 
128
- export { type LangChainAdapter, type LangChainAdapterConfig, type LangChainModelInvokerConfig, type LangChainThreadManager, type LangChainThreadManagerConfig, type LangChainToolMessageContent, createLangChainAdapter, createLangChainModelInvoker, createLangChainThreadManager, invokeLangChainModel };
139
+ export { type LangChainAdapter, type LangChainAdapterConfig, type LangChainModelInvokerConfig, type LangChainThreadManager, type LangChainThreadManagerConfig, type LangChainThreadOps, type LangChainToolMessageContent, createLangChainAdapter, createLangChainModelInvoker, createLangChainThreadManager, invokeLangChainModel };
@@ -246,6 +246,7 @@ async function invokeLangChainModel({
246
246
  }
247
247
 
248
248
  // src/adapters/thread/langchain/activities.ts
249
+ var ADAPTER_PREFIX = "langChain";
249
250
  function createLangChainAdapter(config) {
250
251
  const { redis } = config;
251
252
  const threadOps = {
@@ -274,6 +275,13 @@ function createLangChainAdapter(config) {
274
275
  await thread.fork(targetThreadId);
275
276
  }
276
277
  };
278
+ function createActivities(scope) {
279
+ const prefix = scope ? `${ADAPTER_PREFIX}${scope.charAt(0).toUpperCase()}${scope.slice(1)}` : ADAPTER_PREFIX;
280
+ const cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
281
+ return Object.fromEntries(
282
+ Object.entries(threadOps).map(([k, v]) => [`${prefix}${cap(k)}`, v])
283
+ );
284
+ }
277
285
  const makeInvoker = (model) => createLangChainModelInvoker({ redis, model });
278
286
  const invoker = config.model ? makeInvoker(config.model) : () => {
279
287
  throw new Error(
@@ -281,7 +289,7 @@ function createLangChainAdapter(config) {
281
289
  );
282
290
  };
283
291
  return {
284
- threadOps,
292
+ createActivities,
285
293
  invoker,
286
294
  createModelInvoker: makeInvoker
287
295
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/thread/manager.ts","../../../../src/adapters/thread/langchain/thread-manager.ts","../../../../node_modules/uuid/dist/esm/stringify.js","../../../../node_modules/uuid/dist/esm/rng.js","../../../../node_modules/uuid/dist/esm/native.js","../../../../node_modules/uuid/dist/esm/v4.js","../../../../src/adapters/thread/langchain/model-invoker.ts","../../../../src/adapters/thread/langchain/activities.ts"],"names":["invokeLangChainModel"],"mappings":"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","file":"index.js","sourcesContent":["import type {\n ThreadManagerConfig,\n BaseThreadManager,\n} from \"./types\";\n\nconst THREAD_TTL_SECONDS = 60 * 60 * 24 * 90; // 90 days\n\n/**\n * Lua script for atomic idempotent append.\n * Checks a dedup key; if it exists the message was already appended and we\n * return 0. Otherwise appends all messages to the list, sets TTL on both\n * the list and the dedup key, and returns 1.\n *\n * KEYS[1] = dedup key, KEYS[2] = list key\n * ARGV[1] = TTL seconds, ARGV[2..N] = serialised messages\n */\nconst APPEND_IDEMPOTENT_SCRIPT = `\nif redis.call('EXISTS', KEYS[1]) == 1 then\n return 0\nend\nfor i = 2, #ARGV do\n redis.call('RPUSH', KEYS[2], ARGV[i])\nend\nredis.call('EXPIRE', KEYS[2], tonumber(ARGV[1]))\nredis.call('SET', KEYS[1], '1', 'EX', tonumber(ARGV[1]))\nreturn 1\n`;\n\nfunction getThreadKey(threadId: string, key: string): string {\n return `thread:${threadId}:${key}`;\n}\n\n/**\n * Creates a generic thread manager for handling conversation state in Redis.\n * Framework-agnostic — works with any serializable message type.\n */\nexport function createThreadManager<T>(\n config: ThreadManagerConfig<T>,\n): BaseThreadManager<T> {\n const {\n redis,\n threadId,\n key = \"messages\",\n serialize = (m: T): string => JSON.stringify(m),\n deserialize = (raw: string): T => JSON.parse(raw) as T,\n idOf,\n } = config;\n const redisKey = getThreadKey(threadId, key);\n const metaKey = getThreadKey(threadId, `${key}:meta`);\n\n async function assertThreadExists(): Promise<void> {\n const exists = await redis.exists(metaKey);\n if (!exists) {\n throw new Error(`Thread \"${threadId}\" (key: ${key}) does not exist`);\n }\n }\n\n return {\n async initialize(): Promise<void> {\n await redis.del(redisKey);\n await redis.set(metaKey, \"1\", \"EX\", THREAD_TTL_SECONDS);\n },\n\n async load(): Promise<T[]> {\n await assertThreadExists();\n const data = await redis.lrange(redisKey, 0, -1);\n return data.map(deserialize);\n },\n\n async append(messages: T[]): Promise<void> {\n if (messages.length === 0) return;\n await assertThreadExists();\n\n if (idOf) {\n const dedupId = messages.map(idOf).join(\":\");\n const dedupKey = getThreadKey(threadId, `dedup:${dedupId}`);\n await redis.eval(\n APPEND_IDEMPOTENT_SCRIPT,\n 2,\n dedupKey,\n redisKey,\n String(THREAD_TTL_SECONDS),\n ...messages.map(serialize),\n );\n } else {\n await redis.rpush(redisKey, ...messages.map(serialize));\n await redis.expire(redisKey, THREAD_TTL_SECONDS);\n }\n },\n\n async fork(newThreadId: string): Promise<BaseThreadManager<T>> {\n await assertThreadExists();\n const data = await redis.lrange(redisKey, 0, -1);\n const forked = createThreadManager({\n ...config,\n threadId: newThreadId,\n });\n await forked.initialize();\n if (data.length > 0) {\n const newKey = getThreadKey(newThreadId, key);\n await redis.rpush(newKey, ...data);\n await redis.expire(newKey, THREAD_TTL_SECONDS);\n }\n return forked;\n },\n\n async delete(): Promise<void> {\n await redis.del(redisKey, metaKey);\n },\n };\n}\n","import type Redis from \"ioredis\";\nimport {\n type $InferMessageContent,\n AIMessage,\n HumanMessage,\n type MessageContent,\n type MessageStructure,\n type StoredMessage,\n SystemMessage,\n ToolMessage,\n} from \"@langchain/core/messages\";\nimport {\n createThreadManager,\n type BaseThreadManager,\n type ThreadManagerConfig,\n} from \"../../../lib/thread\";\n\nexport type LangChainToolMessageContent = $InferMessageContent<\n MessageStructure,\n \"tool\"\n>;\n\nexport interface LangChainThreadManagerConfig {\n redis: Redis;\n threadId: string;\n /** Thread key, defaults to 'messages' */\n key?: string;\n}\n\n/** Thread manager with LangChain StoredMessage convenience helpers */\nexport interface LangChainThreadManager extends BaseThreadManager<StoredMessage> {\n createHumanMessage(\n id: string,\n content: string | MessageContent\n ): StoredMessage;\n createSystemMessage(id: string, content: string): StoredMessage;\n createAIMessage(\n id: string,\n content: string | MessageContent,\n kwargs?: { header?: string; options?: string[]; multiSelect?: boolean }\n ): StoredMessage;\n createToolMessage(\n id: string,\n content: LangChainToolMessageContent,\n toolCallId: string\n ): StoredMessage;\n appendHumanMessage(\n id: string,\n content: string | MessageContent\n ): Promise<void>;\n appendSystemMessage(id: string, content: string): Promise<void>;\n appendToolMessage(\n id: string,\n content: LangChainToolMessageContent,\n toolCallId: string\n ): Promise<void>;\n appendAIMessage(id: string, content: string | MessageContent): Promise<void>;\n}\n\nfunction storedMessageId(msg: StoredMessage): string {\n if (msg.type === \"tool\" && msg.data.tool_call_id) {\n return msg.data.tool_call_id;\n }\n\n if (msg.data.id) {\n return msg.data.id;\n }\n\n throw new Error(\"No id found for message\");\n}\n\n/**\n * Creates a LangChain-specific thread manager that stores StoredMessage\n * instances in Redis and provides convenience helpers for creating and\n * appending typed LangChain messages.\n */\nexport function createLangChainThreadManager(\n config: LangChainThreadManagerConfig\n): LangChainThreadManager {\n const baseConfig: ThreadManagerConfig<StoredMessage> = {\n redis: config.redis,\n threadId: config.threadId,\n key: config.key,\n idOf: storedMessageId,\n };\n\n const base = createThreadManager(baseConfig);\n\n const helpers = {\n createHumanMessage(\n id: string,\n content: string | MessageContent\n ): StoredMessage {\n return new HumanMessage({\n id,\n content: content as string,\n }).toDict();\n },\n\n createSystemMessage(id: string, content: string): StoredMessage {\n return new SystemMessage({\n id,\n content: content as string,\n }).toDict();\n },\n\n createAIMessage(\n id: string,\n content: string,\n kwargs?: { header?: string; options?: string[]; multiSelect?: boolean }\n ): StoredMessage {\n return new AIMessage({\n id,\n content,\n additional_kwargs: kwargs\n ? {\n header: kwargs.header,\n options: kwargs.options,\n multiSelect: kwargs.multiSelect,\n }\n : undefined,\n }).toDict();\n },\n\n createToolMessage(\n id: string,\n content: LangChainToolMessageContent,\n toolCallId: string\n ): StoredMessage {\n return new ToolMessage({\n id,\n content: content as MessageContent,\n tool_call_id: toolCallId,\n }).toDict();\n },\n\n async appendHumanMessage(\n id: string,\n content: string | MessageContent\n ): Promise<void> {\n const message = helpers.createHumanMessage(id, content);\n await base.append([message]);\n },\n\n async appendToolMessage(\n id: string,\n content: LangChainToolMessageContent,\n toolCallId: string\n ): Promise<void> {\n const message = helpers.createToolMessage(id, content, toolCallId);\n await base.append([message]);\n },\n\n async appendAIMessage(\n id: string,\n content: string | MessageContent\n ): Promise<void> {\n const message = helpers.createAIMessage(id, content as string);\n await base.append([message]);\n },\n\n async appendSystemMessage(id: string, content: string): Promise<void> {\n const message = helpers.createSystemMessage(id, content);\n await base.initialize();\n await base.append([message]);\n },\n };\n\n return Object.assign(base, helpers);\n}\n","import validate from './validate.js';\nconst byteToHex = [];\nfor (let i = 0; i < 256; ++i) {\n byteToHex.push((i + 0x100).toString(16).slice(1));\n}\nexport function unsafeStringify(arr, offset = 0) {\n return (byteToHex[arr[offset + 0]] +\n byteToHex[arr[offset + 1]] +\n byteToHex[arr[offset + 2]] +\n byteToHex[arr[offset + 3]] +\n '-' +\n byteToHex[arr[offset + 4]] +\n byteToHex[arr[offset + 5]] +\n '-' +\n byteToHex[arr[offset + 6]] +\n byteToHex[arr[offset + 7]] +\n '-' +\n byteToHex[arr[offset + 8]] +\n byteToHex[arr[offset + 9]] +\n '-' +\n byteToHex[arr[offset + 10]] +\n byteToHex[arr[offset + 11]] +\n byteToHex[arr[offset + 12]] +\n byteToHex[arr[offset + 13]] +\n byteToHex[arr[offset + 14]] +\n byteToHex[arr[offset + 15]]).toLowerCase();\n}\nfunction stringify(arr, offset = 0) {\n const uuid = unsafeStringify(arr, offset);\n if (!validate(uuid)) {\n throw TypeError('Stringified UUID is invalid');\n }\n return uuid;\n}\nexport default stringify;\n","import { randomFillSync } from 'crypto';\nconst rnds8Pool = new Uint8Array(256);\nlet poolPtr = rnds8Pool.length;\nexport default function rng() {\n if (poolPtr > rnds8Pool.length - 16) {\n randomFillSync(rnds8Pool);\n poolPtr = 0;\n }\n return rnds8Pool.slice(poolPtr, (poolPtr += 16));\n}\n","import { randomUUID } from 'crypto';\nexport default { randomUUID };\n","import native from './native.js';\nimport rng from './rng.js';\nimport { unsafeStringify } from './stringify.js';\nfunction v4(options, buf, offset) {\n if (native.randomUUID && !buf && !options) {\n return native.randomUUID();\n }\n options = options || {};\n const rnds = options.random ?? options.rng?.() ?? rng();\n if (rnds.length < 16) {\n throw new Error('Random bytes length must be >= 16');\n }\n rnds[6] = (rnds[6] & 0x0f) | 0x40;\n rnds[8] = (rnds[8] & 0x3f) | 0x80;\n if (buf) {\n offset = offset || 0;\n if (offset < 0 || offset + 16 > buf.length) {\n throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);\n }\n for (let i = 0; i < 16; ++i) {\n buf[offset + i] = rnds[i];\n }\n return buf;\n }\n return unsafeStringify(rnds);\n}\nexport default v4;\n","import type Redis from \"ioredis\";\nimport type { AgentResponse } from \"../../../lib/model\";\nimport type { ModelInvokerConfig } from \"../../../lib/model\";\nimport { mapStoredMessagesToChatMessages } from \"@langchain/core/messages\";\nimport type { StoredMessage } from \"@langchain/core/messages\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport { createLangChainThreadManager } from \"./thread-manager\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface LangChainModelInvokerConfig<TModel extends BaseChatModel<any> = BaseChatModel<any>> {\n redis: Redis;\n model: TModel;\n}\n\n/**\n * Creates a LangChain-based model invoker that satisfies the generic\n * `ModelInvoker<StoredMessage>` contract.\n *\n * Loads the conversation thread from Redis, invokes a LangChain chat model,\n * appends the AI response, and returns a normalised AgentResponse.\n *\n * @example\n * ```typescript\n * import { createLangChainModelInvoker } from 'zeitlich/adapters/thread/langchain';\n * import { createRunAgentActivity } from 'zeitlich';\n * import { ChatAnthropic } from '@langchain/anthropic';\n *\n * const model = new ChatAnthropic({ model: \"claude-sonnet-4-6\" });\n * const invoker = createLangChainModelInvoker({ redis, model });\n *\n * return { runAgent: createRunAgentActivity(client, invoker) };\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function createLangChainModelInvoker<TModel extends BaseChatModel<any> = BaseChatModel<any>>(\n { redis, model }: LangChainModelInvokerConfig<TModel>,\n) {\n return async function invokeLangChainModel(\n config: ModelInvokerConfig\n ): Promise<AgentResponse<StoredMessage>> {\n const { threadId, agentName, state, metadata } = config;\n\n const thread = createLangChainThreadManager({ redis, threadId });\n const runId = uuidv4();\n\n const messages = await thread.load();\n const response = await model.invoke(\n [...mapStoredMessagesToChatMessages(messages)],\n {\n runName: agentName,\n runId,\n metadata: { thread_id: `${agentName}-${threadId}`, ...metadata },\n tools: state.tools,\n }\n );\n\n await thread.append([response.toDict()]);\n\n const toolCalls = response.tool_calls ?? [];\n\n return {\n message: response.toDict(),\n rawToolCalls: toolCalls.map((tc) => ({\n id: tc.id,\n name: tc.name,\n args: tc.args,\n })),\n usage: {\n inputTokens: response.usage_metadata?.input_tokens,\n outputTokens: response.usage_metadata?.output_tokens,\n reasonTokens: response.usage_metadata?.output_token_details?.reasoning,\n cachedWriteTokens:\n response.usage_metadata?.input_token_details?.cache_creation,\n cachedReadTokens:\n response.usage_metadata?.input_token_details?.cache_read,\n },\n };\n };\n}\n\n/**\n * Standalone function for one-shot LangChain model invocation.\n * Convenience wrapper around createLangChainModelInvoker for cases where\n * you don't need to reuse the invoker.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function invokeLangChainModel<TModel extends BaseChatModel<any> = BaseChatModel<any>>({\n redis,\n model,\n config,\n}: {\n redis: Redis;\n config: ModelInvokerConfig;\n model: TModel;\n}): Promise<AgentResponse<StoredMessage>> {\n const invoker = createLangChainModelInvoker({ redis, model });\n return invoker(config);\n}\n","import type Redis from \"ioredis\";\nimport type { ToolResultConfig } from \"../../../lib/types\";\nimport type { MessageContent } from \"@langchain/core/messages\";\nimport type { ThreadOps } from \"../../../lib/session/types\";\nimport type { ModelInvoker } from \"../../../lib/model\";\nimport type { StoredMessage } from \"@langchain/core/messages\";\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport { createLangChainThreadManager } from \"./thread-manager\";\nimport { createLangChainModelInvoker } from \"./model-invoker\";\n\nexport interface LangChainAdapterConfig {\n redis: Redis;\n /** Optional default model — if omitted, use `createModelInvoker()` to create invokers later */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n model?: BaseChatModel<any>;\n}\n\nexport interface LangChainAdapter {\n /** Thread operations (register these as Temporal activities on the worker) */\n threadOps: ThreadOps;\n /** Model invoker using the default model (only available when `model` was provided) */\n invoker: ModelInvoker<StoredMessage>;\n /** Create an invoker for a specific model (for multi-model setups) */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n createModelInvoker(model: BaseChatModel<any>): ModelInvoker<StoredMessage>;\n}\n\n/**\n * Creates a LangChain adapter that bundles thread operations and model\n * invocation using a consistent message format (StoredMessage).\n *\n * The returned `threadOps` should be registered as Temporal activities on\n * the worker. The `invoker` (or invokers created via `createModelInvoker`)\n * should be wrapped with `createRunAgentActivity` for per-agent activities.\n *\n * @example\n * ```typescript\n * import { createLangChainAdapter } from 'zeitlich/adapters/thread/langchain';\n * import { createRunAgentActivity } from 'zeitlich';\n *\n * const adapter = createLangChainAdapter({ redis, model });\n *\n * export function createActivities(client: WorkflowClient) {\n * return {\n * ...adapter.threadOps,\n * runAgent: createRunAgentActivity(client, adapter.invoker),\n * };\n * }\n * ```\n *\n * @example Multi-model setup\n * ```typescript\n * const adapter = createLangChainAdapter({ redis });\n *\n * export function createActivities(client: WorkflowClient) {\n * return {\n * ...adapter.threadOps,\n * runResearchAgent: createRunAgentActivity(client, adapter.createModelInvoker(claude)),\n * runWriterAgent: createRunAgentActivity(client, adapter.createModelInvoker(gpt4)),\n * };\n * }\n * ```\n */\nexport function createLangChainAdapter(\n config: LangChainAdapterConfig\n): LangChainAdapter {\n const { redis } = config;\n\n const threadOps: ThreadOps = {\n async initializeThread(threadId: string): Promise<void> {\n const thread = createLangChainThreadManager({ redis, threadId });\n await thread.initialize();\n },\n\n async appendHumanMessage(\n threadId: string,\n id: string,\n content: string | MessageContent\n ): Promise<void> {\n const thread = createLangChainThreadManager({ redis, threadId });\n await thread.appendHumanMessage(id, content);\n },\n\n async appendSystemMessage(\n threadId: string,\n id: string,\n content: string\n ): Promise<void> {\n const thread = createLangChainThreadManager({ redis, threadId });\n await thread.appendSystemMessage(id, content);\n },\n\n async appendToolResult(id: string, cfg: ToolResultConfig): Promise<void> {\n const { threadId, toolCallId, content } = cfg;\n const thread = createLangChainThreadManager({ redis, threadId });\n await thread.appendToolMessage(id, content, toolCallId);\n },\n\n async forkThread(\n sourceThreadId: string,\n targetThreadId: string\n ): Promise<void> {\n const thread = createLangChainThreadManager({\n redis,\n threadId: sourceThreadId,\n });\n await thread.fork(targetThreadId);\n },\n };\n\n const makeInvoker = (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n model: BaseChatModel<any>\n ): ModelInvoker<StoredMessage> =>\n createLangChainModelInvoker({ redis, model });\n\n const invoker: ModelInvoker<StoredMessage> = config.model\n ? makeInvoker(config.model)\n : () => {\n throw new Error(\n \"No default model provided to createLangChainAdapter. \" +\n \"Either pass `model` in the config or use `createModelInvoker(model)` instead.\"\n );\n };\n\n return {\n threadOps,\n invoker,\n createModelInvoker: makeInvoker,\n };\n}\n"]}
1
+ {"version":3,"sources":["../../../../src/lib/thread/manager.ts","../../../../src/adapters/thread/langchain/thread-manager.ts","../../../../node_modules/uuid/dist/esm/stringify.js","../../../../node_modules/uuid/dist/esm/rng.js","../../../../node_modules/uuid/dist/esm/native.js","../../../../node_modules/uuid/dist/esm/v4.js","../../../../src/adapters/thread/langchain/model-invoker.ts","../../../../src/adapters/thread/langchain/activities.ts"],"names":["invokeLangChainModel"],"mappings":"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","file":"index.js","sourcesContent":["import type {\n ThreadManagerConfig,\n BaseThreadManager,\n} from \"./types\";\n\nconst THREAD_TTL_SECONDS = 60 * 60 * 24 * 90; // 90 days\n\n/**\n * Lua script for atomic idempotent append.\n * Checks a dedup key; if it exists the message was already appended and we\n * return 0. Otherwise appends all messages to the list, sets TTL on both\n * the list and the dedup key, and returns 1.\n *\n * KEYS[1] = dedup key, KEYS[2] = list key\n * ARGV[1] = TTL seconds, ARGV[2..N] = serialised messages\n */\nconst APPEND_IDEMPOTENT_SCRIPT = `\nif redis.call('EXISTS', KEYS[1]) == 1 then\n return 0\nend\nfor i = 2, #ARGV do\n redis.call('RPUSH', KEYS[2], ARGV[i])\nend\nredis.call('EXPIRE', KEYS[2], tonumber(ARGV[1]))\nredis.call('SET', KEYS[1], '1', 'EX', tonumber(ARGV[1]))\nreturn 1\n`;\n\nfunction getThreadKey(threadId: string, key: string): string {\n return `thread:${threadId}:${key}`;\n}\n\n/**\n * Creates a generic thread manager for handling conversation state in Redis.\n * Framework-agnostic — works with any serializable message type.\n */\nexport function createThreadManager<T>(\n config: ThreadManagerConfig<T>,\n): BaseThreadManager<T> {\n const {\n redis,\n threadId,\n key = \"messages\",\n serialize = (m: T): string => JSON.stringify(m),\n deserialize = (raw: string): T => JSON.parse(raw) as T,\n idOf,\n } = config;\n const redisKey = getThreadKey(threadId, key);\n const metaKey = getThreadKey(threadId, `${key}:meta`);\n\n async function assertThreadExists(): Promise<void> {\n const exists = await redis.exists(metaKey);\n if (!exists) {\n throw new Error(`Thread \"${threadId}\" (key: ${key}) does not exist`);\n }\n }\n\n return {\n async initialize(): Promise<void> {\n await redis.del(redisKey);\n await redis.set(metaKey, \"1\", \"EX\", THREAD_TTL_SECONDS);\n },\n\n async load(): Promise<T[]> {\n await assertThreadExists();\n const data = await redis.lrange(redisKey, 0, -1);\n return data.map(deserialize);\n },\n\n async append(messages: T[]): Promise<void> {\n if (messages.length === 0) return;\n await assertThreadExists();\n\n if (idOf) {\n const dedupId = messages.map(idOf).join(\":\");\n const dedupKey = getThreadKey(threadId, `dedup:${dedupId}`);\n await redis.eval(\n APPEND_IDEMPOTENT_SCRIPT,\n 2,\n dedupKey,\n redisKey,\n String(THREAD_TTL_SECONDS),\n ...messages.map(serialize),\n );\n } else {\n await redis.rpush(redisKey, ...messages.map(serialize));\n await redis.expire(redisKey, THREAD_TTL_SECONDS);\n }\n },\n\n async fork(newThreadId: string): Promise<BaseThreadManager<T>> {\n await assertThreadExists();\n const data = await redis.lrange(redisKey, 0, -1);\n const forked = createThreadManager({\n ...config,\n threadId: newThreadId,\n });\n await forked.initialize();\n if (data.length > 0) {\n const newKey = getThreadKey(newThreadId, key);\n await redis.rpush(newKey, ...data);\n await redis.expire(newKey, THREAD_TTL_SECONDS);\n }\n return forked;\n },\n\n async delete(): Promise<void> {\n await redis.del(redisKey, metaKey);\n },\n };\n}\n","import type Redis from \"ioredis\";\nimport {\n type $InferMessageContent,\n AIMessage,\n HumanMessage,\n type MessageContent,\n type MessageStructure,\n type StoredMessage,\n SystemMessage,\n ToolMessage,\n} from \"@langchain/core/messages\";\nimport {\n createThreadManager,\n type BaseThreadManager,\n type ThreadManagerConfig,\n} from \"../../../lib/thread\";\n\nexport type LangChainToolMessageContent = $InferMessageContent<\n MessageStructure,\n \"tool\"\n>;\n\nexport interface LangChainThreadManagerConfig {\n redis: Redis;\n threadId: string;\n /** Thread key, defaults to 'messages' */\n key?: string;\n}\n\n/** Thread manager with LangChain StoredMessage convenience helpers */\nexport interface LangChainThreadManager extends BaseThreadManager<StoredMessage> {\n createHumanMessage(\n id: string,\n content: string | MessageContent\n ): StoredMessage;\n createSystemMessage(id: string, content: string): StoredMessage;\n createAIMessage(\n id: string,\n content: string | MessageContent,\n kwargs?: { header?: string; options?: string[]; multiSelect?: boolean }\n ): StoredMessage;\n createToolMessage(\n id: string,\n content: LangChainToolMessageContent,\n toolCallId: string\n ): StoredMessage;\n appendHumanMessage(\n id: string,\n content: string | MessageContent\n ): Promise<void>;\n appendSystemMessage(id: string, content: string): Promise<void>;\n appendToolMessage(\n id: string,\n content: LangChainToolMessageContent,\n toolCallId: string\n ): Promise<void>;\n appendAIMessage(id: string, content: string | MessageContent): Promise<void>;\n}\n\nfunction storedMessageId(msg: StoredMessage): string {\n if (msg.type === \"tool\" && msg.data.tool_call_id) {\n return msg.data.tool_call_id;\n }\n\n if (msg.data.id) {\n return msg.data.id;\n }\n\n throw new Error(\"No id found for message\");\n}\n\n/**\n * Creates a LangChain-specific thread manager that stores StoredMessage\n * instances in Redis and provides convenience helpers for creating and\n * appending typed LangChain messages.\n */\nexport function createLangChainThreadManager(\n config: LangChainThreadManagerConfig\n): LangChainThreadManager {\n const baseConfig: ThreadManagerConfig<StoredMessage> = {\n redis: config.redis,\n threadId: config.threadId,\n key: config.key,\n idOf: storedMessageId,\n };\n\n const base = createThreadManager(baseConfig);\n\n const helpers = {\n createHumanMessage(\n id: string,\n content: string | MessageContent\n ): StoredMessage {\n return new HumanMessage({\n id,\n content: content as string,\n }).toDict();\n },\n\n createSystemMessage(id: string, content: string): StoredMessage {\n return new SystemMessage({\n id,\n content: content as string,\n }).toDict();\n },\n\n createAIMessage(\n id: string,\n content: string,\n kwargs?: { header?: string; options?: string[]; multiSelect?: boolean }\n ): StoredMessage {\n return new AIMessage({\n id,\n content,\n additional_kwargs: kwargs\n ? {\n header: kwargs.header,\n options: kwargs.options,\n multiSelect: kwargs.multiSelect,\n }\n : undefined,\n }).toDict();\n },\n\n createToolMessage(\n id: string,\n content: LangChainToolMessageContent,\n toolCallId: string\n ): StoredMessage {\n return new ToolMessage({\n id,\n content: content as MessageContent,\n tool_call_id: toolCallId,\n }).toDict();\n },\n\n async appendHumanMessage(\n id: string,\n content: string | MessageContent\n ): Promise<void> {\n const message = helpers.createHumanMessage(id, content);\n await base.append([message]);\n },\n\n async appendToolMessage(\n id: string,\n content: LangChainToolMessageContent,\n toolCallId: string\n ): Promise<void> {\n const message = helpers.createToolMessage(id, content, toolCallId);\n await base.append([message]);\n },\n\n async appendAIMessage(\n id: string,\n content: string | MessageContent\n ): Promise<void> {\n const message = helpers.createAIMessage(id, content as string);\n await base.append([message]);\n },\n\n async appendSystemMessage(id: string, content: string): Promise<void> {\n const message = helpers.createSystemMessage(id, content);\n await base.initialize();\n await base.append([message]);\n },\n };\n\n return Object.assign(base, helpers);\n}\n","import validate from './validate.js';\nconst byteToHex = [];\nfor (let i = 0; i < 256; ++i) {\n byteToHex.push((i + 0x100).toString(16).slice(1));\n}\nexport function unsafeStringify(arr, offset = 0) {\n return (byteToHex[arr[offset + 0]] +\n byteToHex[arr[offset + 1]] +\n byteToHex[arr[offset + 2]] +\n byteToHex[arr[offset + 3]] +\n '-' +\n byteToHex[arr[offset + 4]] +\n byteToHex[arr[offset + 5]] +\n '-' +\n byteToHex[arr[offset + 6]] +\n byteToHex[arr[offset + 7]] +\n '-' +\n byteToHex[arr[offset + 8]] +\n byteToHex[arr[offset + 9]] +\n '-' +\n byteToHex[arr[offset + 10]] +\n byteToHex[arr[offset + 11]] +\n byteToHex[arr[offset + 12]] +\n byteToHex[arr[offset + 13]] +\n byteToHex[arr[offset + 14]] +\n byteToHex[arr[offset + 15]]).toLowerCase();\n}\nfunction stringify(arr, offset = 0) {\n const uuid = unsafeStringify(arr, offset);\n if (!validate(uuid)) {\n throw TypeError('Stringified UUID is invalid');\n }\n return uuid;\n}\nexport default stringify;\n","import { randomFillSync } from 'crypto';\nconst rnds8Pool = new Uint8Array(256);\nlet poolPtr = rnds8Pool.length;\nexport default function rng() {\n if (poolPtr > rnds8Pool.length - 16) {\n randomFillSync(rnds8Pool);\n poolPtr = 0;\n }\n return rnds8Pool.slice(poolPtr, (poolPtr += 16));\n}\n","import { randomUUID } from 'crypto';\nexport default { randomUUID };\n","import native from './native.js';\nimport rng from './rng.js';\nimport { unsafeStringify } from './stringify.js';\nfunction v4(options, buf, offset) {\n if (native.randomUUID && !buf && !options) {\n return native.randomUUID();\n }\n options = options || {};\n const rnds = options.random ?? options.rng?.() ?? rng();\n if (rnds.length < 16) {\n throw new Error('Random bytes length must be >= 16');\n }\n rnds[6] = (rnds[6] & 0x0f) | 0x40;\n rnds[8] = (rnds[8] & 0x3f) | 0x80;\n if (buf) {\n offset = offset || 0;\n if (offset < 0 || offset + 16 > buf.length) {\n throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);\n }\n for (let i = 0; i < 16; ++i) {\n buf[offset + i] = rnds[i];\n }\n return buf;\n }\n return unsafeStringify(rnds);\n}\nexport default v4;\n","import type Redis from \"ioredis\";\nimport type { AgentResponse } from \"../../../lib/model\";\nimport type { ModelInvokerConfig } from \"../../../lib/model\";\nimport { mapStoredMessagesToChatMessages } from \"@langchain/core/messages\";\nimport type { StoredMessage } from \"@langchain/core/messages\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport { createLangChainThreadManager } from \"./thread-manager\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface LangChainModelInvokerConfig<TModel extends BaseChatModel<any> = BaseChatModel<any>> {\n redis: Redis;\n model: TModel;\n}\n\n/**\n * Creates a LangChain-based model invoker that satisfies the generic\n * `ModelInvoker<StoredMessage>` contract.\n *\n * Loads the conversation thread from Redis, invokes a LangChain chat model,\n * appends the AI response, and returns a normalised AgentResponse.\n *\n * @example\n * ```typescript\n * import { createLangChainModelInvoker } from 'zeitlich/adapters/thread/langchain';\n * import { createRunAgentActivity } from 'zeitlich';\n * import { ChatAnthropic } from '@langchain/anthropic';\n *\n * const model = new ChatAnthropic({ model: \"claude-sonnet-4-6\" });\n * const invoker = createLangChainModelInvoker({ redis, model });\n *\n * return { runAgent: createRunAgentActivity(client, invoker) };\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function createLangChainModelInvoker<TModel extends BaseChatModel<any> = BaseChatModel<any>>(\n { redis, model }: LangChainModelInvokerConfig<TModel>,\n) {\n return async function invokeLangChainModel(\n config: ModelInvokerConfig\n ): Promise<AgentResponse<StoredMessage>> {\n const { threadId, agentName, state, metadata } = config;\n\n const thread = createLangChainThreadManager({ redis, threadId });\n const runId = uuidv4();\n\n const messages = await thread.load();\n const response = await model.invoke(\n [...mapStoredMessagesToChatMessages(messages)],\n {\n runName: agentName,\n runId,\n metadata: { thread_id: `${agentName}-${threadId}`, ...metadata },\n tools: state.tools,\n }\n );\n\n await thread.append([response.toDict()]);\n\n const toolCalls = response.tool_calls ?? [];\n\n return {\n message: response.toDict(),\n rawToolCalls: toolCalls.map((tc) => ({\n id: tc.id,\n name: tc.name,\n args: tc.args,\n })),\n usage: {\n inputTokens: response.usage_metadata?.input_tokens,\n outputTokens: response.usage_metadata?.output_tokens,\n reasonTokens: response.usage_metadata?.output_token_details?.reasoning,\n cachedWriteTokens:\n response.usage_metadata?.input_token_details?.cache_creation,\n cachedReadTokens:\n response.usage_metadata?.input_token_details?.cache_read,\n },\n };\n };\n}\n\n/**\n * Standalone function for one-shot LangChain model invocation.\n * Convenience wrapper around createLangChainModelInvoker for cases where\n * you don't need to reuse the invoker.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function invokeLangChainModel<TModel extends BaseChatModel<any> = BaseChatModel<any>>({\n redis,\n model,\n config,\n}: {\n redis: Redis;\n config: ModelInvokerConfig;\n model: TModel;\n}): Promise<AgentResponse<StoredMessage>> {\n const invoker = createLangChainModelInvoker({ redis, model });\n return invoker(config);\n}\n","import type Redis from \"ioredis\";\nimport type { ToolResultConfig } from \"../../../lib/types\";\nimport type { MessageContent } from \"@langchain/core/messages\";\nimport type {\n ThreadOps,\n PrefixedThreadOps,\n ScopedPrefix,\n} from \"../../../lib/session/types\";\nimport type { ModelInvoker } from \"../../../lib/model\";\nimport type { StoredMessage } from \"@langchain/core/messages\";\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport { createLangChainThreadManager } from \"./thread-manager\";\nimport { createLangChainModelInvoker } from \"./model-invoker\";\n\nconst ADAPTER_PREFIX = \"langChain\" as const;\n\nexport type LangChainThreadOps<TScope extends string = \"\"> =\n PrefixedThreadOps<ScopedPrefix<TScope, typeof ADAPTER_PREFIX>>;\n\nexport interface LangChainAdapterConfig {\n redis: Redis;\n /** Optional default model — if omitted, use `createModelInvoker()` to create invokers later */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n model?: BaseChatModel<any>;\n}\n\nexport interface LangChainAdapter {\n /** Model invoker using the default model (only available when `model` was provided) */\n invoker: ModelInvoker<StoredMessage>;\n /** Create an invoker for a specific model (for multi-model setups) */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n createModelInvoker(model: BaseChatModel<any>): ModelInvoker<StoredMessage>;\n /**\n * Create prefixed thread activities for registration on the worker.\n *\n * @param scope - Workflow name appended to the adapter prefix.\n *\n * @example\n * ```typescript\n * adapter.createActivities(\"codingAgent\")\n * // → { langChainCodingAgentInitializeThread, langChainCodingAgentAppendHumanMessage, … }\n * ```\n */\n createActivities<S extends string = \"\">(\n scope?: S\n ): LangChainThreadOps<S>;\n}\n\n/**\n * Creates a LangChain adapter that bundles thread operations and model\n * invocation using a consistent message format (StoredMessage).\n *\n * Use `createActivities(scope)` to register scoped thread operations as\n * Temporal activities on the worker. The `invoker` (or invokers created via\n * `createModelInvoker`) should be wrapped with `createRunAgentActivity`.\n *\n * @example\n * ```typescript\n * import { createLangChainAdapter } from 'zeitlich/adapters/thread/langchain';\n * import { createRunAgentActivity } from 'zeitlich';\n *\n * const adapter = createLangChainAdapter({ redis, model });\n *\n * export function createActivities(client: WorkflowClient) {\n * return {\n * ...adapter.createActivities(\"codingAgent\"),\n * runCodingAgent: createRunAgentActivity(client, adapter.invoker),\n * };\n * }\n * ```\n *\n * @example Multi-agent worker\n * ```typescript\n * export function createActivities(client: WorkflowClient) {\n * return {\n * ...adapter.createActivities(\"codingAgent\"),\n * ...adapter.createActivities(\"researchAgent\"),\n * runCodingAgent: createRunAgentActivity(client, adapter.invoker),\n * runResearchAgent: createRunAgentActivity(client, adapter.createModelInvoker(claude)),\n * };\n * }\n * ```\n */\nexport function createLangChainAdapter(\n config: LangChainAdapterConfig\n): LangChainAdapter {\n const { redis } = config;\n\n const threadOps: ThreadOps = {\n async initializeThread(threadId: string): Promise<void> {\n const thread = createLangChainThreadManager({ redis, threadId });\n await thread.initialize();\n },\n\n async appendHumanMessage(\n threadId: string,\n id: string,\n content: string | MessageContent\n ): Promise<void> {\n const thread = createLangChainThreadManager({ redis, threadId });\n await thread.appendHumanMessage(id, content);\n },\n\n async appendSystemMessage(\n threadId: string,\n id: string,\n content: string\n ): Promise<void> {\n const thread = createLangChainThreadManager({ redis, threadId });\n await thread.appendSystemMessage(id, content);\n },\n\n async appendToolResult(id: string, cfg: ToolResultConfig): Promise<void> {\n const { threadId, toolCallId, content } = cfg;\n const thread = createLangChainThreadManager({ redis, threadId });\n await thread.appendToolMessage(id, content, toolCallId);\n },\n\n async forkThread(\n sourceThreadId: string,\n targetThreadId: string\n ): Promise<void> {\n const thread = createLangChainThreadManager({\n redis,\n threadId: sourceThreadId,\n });\n await thread.fork(targetThreadId);\n },\n };\n\n function createActivities<S extends string = \"\">(\n scope?: S\n ): LangChainThreadOps<S> {\n const prefix = scope\n ? `${ADAPTER_PREFIX}${scope.charAt(0).toUpperCase()}${scope.slice(1)}`\n : ADAPTER_PREFIX;\n const cap = (s: string): string =>\n s.charAt(0).toUpperCase() + s.slice(1);\n return Object.fromEntries(\n Object.entries(threadOps).map(([k, v]) => [`${prefix}${cap(k)}`, v])\n ) as LangChainThreadOps<S>;\n }\n\n const makeInvoker = (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n model: BaseChatModel<any>\n ): ModelInvoker<StoredMessage> =>\n createLangChainModelInvoker({ redis, model });\n\n const invoker: ModelInvoker<StoredMessage> = config.model\n ? makeInvoker(config.model)\n : () => {\n throw new Error(\n \"No default model provided to createLangChainAdapter. \" +\n \"Either pass `model` in the config or use `createModelInvoker(model)` instead.\"\n );\n };\n\n return {\n createActivities,\n invoker,\n createModelInvoker: makeInvoker,\n };\n}\n"]}
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ var workflow = require('@temporalio/workflow');
4
+
5
+ // src/adapters/thread/langchain/proxy.ts
6
+ var ADAPTER_PREFIX = "langChain";
7
+ function proxyLangChainThreadOps(scope, options) {
8
+ const resolvedScope = scope ?? workflow.workflowInfo().workflowType;
9
+ const acts = workflow.proxyActivities(
10
+ options ?? {
11
+ startToCloseTimeout: "10s",
12
+ retry: {
13
+ maximumAttempts: 6,
14
+ initialInterval: "5s",
15
+ maximumInterval: "15m",
16
+ backoffCoefficient: 4
17
+ }
18
+ }
19
+ );
20
+ const prefix = `${ADAPTER_PREFIX}${resolvedScope.charAt(0).toUpperCase()}${resolvedScope.slice(1)}`;
21
+ const p = (key) => `${prefix}${key.charAt(0).toUpperCase()}${key.slice(1)}`;
22
+ return {
23
+ initializeThread: acts[p("initializeThread")],
24
+ appendHumanMessage: acts[p("appendHumanMessage")],
25
+ appendToolResult: acts[p("appendToolResult")],
26
+ appendSystemMessage: acts[p("appendSystemMessage")],
27
+ forkThread: acts[p("forkThread")]
28
+ };
29
+ }
30
+
31
+ exports.proxyLangChainThreadOps = proxyLangChainThreadOps;
32
+ //# sourceMappingURL=workflow.cjs.map
33
+ //# sourceMappingURL=workflow.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/adapters/thread/langchain/proxy.ts"],"names":["workflowInfo","proxyActivities"],"mappings":";;;;;AA2BA,IAAM,cAAA,GAAiB,WAAA;AAEhB,SAAS,uBAAA,CACd,OACA,OAAA,EACiC;AACjC,EAAA,MAAM,aAAA,GAAgB,KAAA,IAASA,qBAAA,EAAa,CAAE,YAAA;AAG9C,EAAA,MAAM,IAAA,GAAOC,wBAAA;AAAA,IACX,OAAA,IAAW;AAAA,MACT,mBAAA,EAAqB,KAAA;AAAA,MACrB,KAAA,EAAO;AAAA,QACL,eAAA,EAAiB,CAAA;AAAA,QACjB,eAAA,EAAiB,IAAA;AAAA,QACjB,eAAA,EAAiB,KAAA;AAAA,QACjB,kBAAA,EAAoB;AAAA;AACtB;AACF,GACF;AAEA,EAAA,MAAM,MAAA,GACJ,CAAA,EAAG,cAAc,CAAA,EAAG,cAAc,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,EAAa,CAAA,EAAG,aAAA,CAAc,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AACpF,EAAA,MAAM,IAAI,CAAC,GAAA,KACT,CAAA,EAAG,MAAM,GAAG,GAAA,CAAI,MAAA,CAAO,CAAC,CAAA,CAAE,aAAa,CAAA,EAAG,GAAA,CAAI,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AAExD,EAAA,OAAO;AAAA,IACL,gBAAA,EAAkB,IAAA,CAAK,CAAA,CAAE,kBAAkB,CAAC,CAAA;AAAA,IAC5C,kBAAA,EAAoB,IAAA,CAAK,CAAA,CAAE,oBAAoB,CAAC,CAAA;AAAA,IAChD,gBAAA,EAAkB,IAAA,CAAK,CAAA,CAAE,kBAAkB,CAAC,CAAA;AAAA,IAC5C,mBAAA,EAAqB,IAAA,CAAK,CAAA,CAAE,qBAAqB,CAAC,CAAA;AAAA,IAClD,UAAA,EAAY,IAAA,CAAK,CAAA,CAAE,YAAY,CAAC;AAAA,GAClC;AACF","file":"workflow.cjs","sourcesContent":["/**\n * Workflow-safe proxy for LangChain thread operations.\n *\n * Import this from `zeitlich/adapters/thread/langchain/workflow`\n * in your Temporal workflow files.\n *\n * By default the scope is derived from `workflowInfo().workflowType`,\n * so activities are automatically namespaced per workflow.\n *\n * @example\n * ```typescript\n * import { proxyLangChainThreadOps } from 'zeitlich/adapters/thread/langchain/workflow';\n *\n * // Auto-scoped to the current workflow name\n * const threadOps = proxyLangChainThreadOps();\n *\n * // Explicit scope override\n * const threadOps = proxyLangChainThreadOps(\"customScope\");\n * ```\n */\nimport {\n proxyActivities,\n workflowInfo,\n type ActivityInterfaceFor,\n} from \"@temporalio/workflow\";\nimport type { ThreadOps } from \"../../../lib/session/types\";\n\nconst ADAPTER_PREFIX = \"langChain\";\n\nexport function proxyLangChainThreadOps(\n scope?: string,\n options?: Parameters<typeof proxyActivities>[0]\n): ActivityInterfaceFor<ThreadOps> {\n const resolvedScope = scope ?? workflowInfo().workflowType;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const acts = proxyActivities<Record<string, (...args: any[]) => any>>(\n options ?? {\n startToCloseTimeout: \"10s\",\n retry: {\n maximumAttempts: 6,\n initialInterval: \"5s\",\n maximumInterval: \"15m\",\n backoffCoefficient: 4,\n },\n }\n );\n\n const prefix =\n `${ADAPTER_PREFIX}${resolvedScope.charAt(0).toUpperCase()}${resolvedScope.slice(1)}`;\n const p = (key: string): string =>\n `${prefix}${key.charAt(0).toUpperCase()}${key.slice(1)}`;\n\n return {\n initializeThread: acts[p(\"initializeThread\")],\n appendHumanMessage: acts[p(\"appendHumanMessage\")],\n appendToolResult: acts[p(\"appendToolResult\")],\n appendSystemMessage: acts[p(\"appendSystemMessage\")],\n forkThread: acts[p(\"forkThread\")],\n } as ActivityInterfaceFor<ThreadOps>;\n}\n"]}
@@ -0,0 +1,32 @@
1
+ import { proxyActivities, ActivityInterfaceFor } from '@temporalio/workflow';
2
+ import { T as ThreadOps } from '../../../types-ClsHhtwL.cjs';
3
+ import '@temporalio/common';
4
+ import '../../../types-YbL7JpEA.cjs';
5
+ import 'zod';
6
+ import '../../../types-HBosetv3.cjs';
7
+ import '@temporalio/common/lib/interfaces';
8
+
9
+ /**
10
+ * Workflow-safe proxy for LangChain thread operations.
11
+ *
12
+ * Import this from `zeitlich/adapters/thread/langchain/workflow`
13
+ * in your Temporal workflow files.
14
+ *
15
+ * By default the scope is derived from `workflowInfo().workflowType`,
16
+ * so activities are automatically namespaced per workflow.
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import { proxyLangChainThreadOps } from 'zeitlich/adapters/thread/langchain/workflow';
21
+ *
22
+ * // Auto-scoped to the current workflow name
23
+ * const threadOps = proxyLangChainThreadOps();
24
+ *
25
+ * // Explicit scope override
26
+ * const threadOps = proxyLangChainThreadOps("customScope");
27
+ * ```
28
+ */
29
+
30
+ declare function proxyLangChainThreadOps(scope?: string, options?: Parameters<typeof proxyActivities>[0]): ActivityInterfaceFor<ThreadOps>;
31
+
32
+ export { proxyLangChainThreadOps };
@@ -0,0 +1,32 @@
1
+ import { proxyActivities, ActivityInterfaceFor } from '@temporalio/workflow';
2
+ import { T as ThreadOps } from '../../../types-C5bkx6kQ.js';
3
+ import '@temporalio/common';
4
+ import '../../../types-YbL7JpEA.js';
5
+ import 'zod';
6
+ import '../../../types-HBosetv3.js';
7
+ import '@temporalio/common/lib/interfaces';
8
+
9
+ /**
10
+ * Workflow-safe proxy for LangChain thread operations.
11
+ *
12
+ * Import this from `zeitlich/adapters/thread/langchain/workflow`
13
+ * in your Temporal workflow files.
14
+ *
15
+ * By default the scope is derived from `workflowInfo().workflowType`,
16
+ * so activities are automatically namespaced per workflow.
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import { proxyLangChainThreadOps } from 'zeitlich/adapters/thread/langchain/workflow';
21
+ *
22
+ * // Auto-scoped to the current workflow name
23
+ * const threadOps = proxyLangChainThreadOps();
24
+ *
25
+ * // Explicit scope override
26
+ * const threadOps = proxyLangChainThreadOps("customScope");
27
+ * ```
28
+ */
29
+
30
+ declare function proxyLangChainThreadOps(scope?: string, options?: Parameters<typeof proxyActivities>[0]): ActivityInterfaceFor<ThreadOps>;
31
+
32
+ export { proxyLangChainThreadOps };
@@ -0,0 +1,31 @@
1
+ import { workflowInfo, proxyActivities } from '@temporalio/workflow';
2
+
3
+ // src/adapters/thread/langchain/proxy.ts
4
+ var ADAPTER_PREFIX = "langChain";
5
+ function proxyLangChainThreadOps(scope, options) {
6
+ const resolvedScope = scope ?? workflowInfo().workflowType;
7
+ const acts = proxyActivities(
8
+ options ?? {
9
+ startToCloseTimeout: "10s",
10
+ retry: {
11
+ maximumAttempts: 6,
12
+ initialInterval: "5s",
13
+ maximumInterval: "15m",
14
+ backoffCoefficient: 4
15
+ }
16
+ }
17
+ );
18
+ const prefix = `${ADAPTER_PREFIX}${resolvedScope.charAt(0).toUpperCase()}${resolvedScope.slice(1)}`;
19
+ const p = (key) => `${prefix}${key.charAt(0).toUpperCase()}${key.slice(1)}`;
20
+ return {
21
+ initializeThread: acts[p("initializeThread")],
22
+ appendHumanMessage: acts[p("appendHumanMessage")],
23
+ appendToolResult: acts[p("appendToolResult")],
24
+ appendSystemMessage: acts[p("appendSystemMessage")],
25
+ forkThread: acts[p("forkThread")]
26
+ };
27
+ }
28
+
29
+ export { proxyLangChainThreadOps };
30
+ //# sourceMappingURL=workflow.js.map
31
+ //# sourceMappingURL=workflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/adapters/thread/langchain/proxy.ts"],"names":[],"mappings":";;;AA2BA,IAAM,cAAA,GAAiB,WAAA;AAEhB,SAAS,uBAAA,CACd,OACA,OAAA,EACiC;AACjC,EAAA,MAAM,aAAA,GAAgB,KAAA,IAAS,YAAA,EAAa,CAAE,YAAA;AAG9C,EAAA,MAAM,IAAA,GAAO,eAAA;AAAA,IACX,OAAA,IAAW;AAAA,MACT,mBAAA,EAAqB,KAAA;AAAA,MACrB,KAAA,EAAO;AAAA,QACL,eAAA,EAAiB,CAAA;AAAA,QACjB,eAAA,EAAiB,IAAA;AAAA,QACjB,eAAA,EAAiB,KAAA;AAAA,QACjB,kBAAA,EAAoB;AAAA;AACtB;AACF,GACF;AAEA,EAAA,MAAM,MAAA,GACJ,CAAA,EAAG,cAAc,CAAA,EAAG,cAAc,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,EAAa,CAAA,EAAG,aAAA,CAAc,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AACpF,EAAA,MAAM,IAAI,CAAC,GAAA,KACT,CAAA,EAAG,MAAM,GAAG,GAAA,CAAI,MAAA,CAAO,CAAC,CAAA,CAAE,aAAa,CAAA,EAAG,GAAA,CAAI,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AAExD,EAAA,OAAO;AAAA,IACL,gBAAA,EAAkB,IAAA,CAAK,CAAA,CAAE,kBAAkB,CAAC,CAAA;AAAA,IAC5C,kBAAA,EAAoB,IAAA,CAAK,CAAA,CAAE,oBAAoB,CAAC,CAAA;AAAA,IAChD,gBAAA,EAAkB,IAAA,CAAK,CAAA,CAAE,kBAAkB,CAAC,CAAA;AAAA,IAC5C,mBAAA,EAAqB,IAAA,CAAK,CAAA,CAAE,qBAAqB,CAAC,CAAA;AAAA,IAClD,UAAA,EAAY,IAAA,CAAK,CAAA,CAAE,YAAY,CAAC;AAAA,GAClC;AACF","file":"workflow.js","sourcesContent":["/**\n * Workflow-safe proxy for LangChain thread operations.\n *\n * Import this from `zeitlich/adapters/thread/langchain/workflow`\n * in your Temporal workflow files.\n *\n * By default the scope is derived from `workflowInfo().workflowType`,\n * so activities are automatically namespaced per workflow.\n *\n * @example\n * ```typescript\n * import { proxyLangChainThreadOps } from 'zeitlich/adapters/thread/langchain/workflow';\n *\n * // Auto-scoped to the current workflow name\n * const threadOps = proxyLangChainThreadOps();\n *\n * // Explicit scope override\n * const threadOps = proxyLangChainThreadOps(\"customScope\");\n * ```\n */\nimport {\n proxyActivities,\n workflowInfo,\n type ActivityInterfaceFor,\n} from \"@temporalio/workflow\";\nimport type { ThreadOps } from \"../../../lib/session/types\";\n\nconst ADAPTER_PREFIX = \"langChain\";\n\nexport function proxyLangChainThreadOps(\n scope?: string,\n options?: Parameters<typeof proxyActivities>[0]\n): ActivityInterfaceFor<ThreadOps> {\n const resolvedScope = scope ?? workflowInfo().workflowType;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const acts = proxyActivities<Record<string, (...args: any[]) => any>>(\n options ?? {\n startToCloseTimeout: \"10s\",\n retry: {\n maximumAttempts: 6,\n initialInterval: \"5s\",\n maximumInterval: \"15m\",\n backoffCoefficient: 4,\n },\n }\n );\n\n const prefix =\n `${ADAPTER_PREFIX}${resolvedScope.charAt(0).toUpperCase()}${resolvedScope.slice(1)}`;\n const p = (key: string): string =>\n `${prefix}${key.charAt(0).toUpperCase()}${key.slice(1)}`;\n\n return {\n initializeThread: acts[p(\"initializeThread\")],\n appendHumanMessage: acts[p(\"appendHumanMessage\")],\n appendToolResult: acts[p(\"appendToolResult\")],\n appendSystemMessage: acts[p(\"appendSystemMessage\")],\n forkThread: acts[p(\"forkThread\")],\n } as ActivityInterfaceFor<ThreadOps>;\n}\n"]}
package/dist/index.cjs CHANGED
@@ -378,9 +378,10 @@ function createSubagentHandler(subagents) {
378
378
  },
379
379
  ...inheritSandbox && { sandboxId: parentSandboxId }
380
380
  };
381
+ const resolvedContext = config.context === void 0 ? void 0 : typeof config.context === "function" ? config.context() : config.context;
381
382
  const childOpts = {
382
383
  workflowId: childWorkflowId,
383
- args: config.context === void 0 ? [args.prompt, workflowInput] : [args.prompt, workflowInput, config.context],
384
+ args: resolvedContext === void 0 ? [args.prompt, workflowInput] : [args.prompt, workflowInput, resolvedContext],
384
385
  taskQueue: config.taskQueue ?? parentTaskQueue
385
386
  };
386
387
  const {
@@ -531,7 +532,7 @@ var createSession = async ({
531
532
  initializeThread,
532
533
  appendSystemMessage,
533
534
  forkThread
534
- } = threadOps ?? proxyDefaultThreadOps();
535
+ } = threadOps;
535
536
  const plugins = [];
536
537
  if (subagents) {
537
538
  const reg = buildSubagentRegistration(subagents);
@@ -701,37 +702,12 @@ var createSession = async ({
701
702
  }
702
703
  };
703
704
  };
704
- function proxyDefaultThreadOps(options) {
705
- return workflow.proxyActivities(
706
- options ?? {
707
- startToCloseTimeout: "10s",
708
- retry: {
709
- maximumAttempts: 6,
710
- initialInterval: "5s",
711
- maximumInterval: "15m",
712
- backoffCoefficient: 4
713
- }
714
- }
715
- );
716
- }
717
- function proxySandboxOps(options) {
718
- return workflow.proxyActivities(
719
- options ?? {
720
- startToCloseTimeout: "30s",
721
- retry: {
722
- maximumAttempts: 3,
723
- initialInterval: "2s",
724
- maximumInterval: "30s",
725
- backoffCoefficient: 2
726
- }
727
- }
728
- );
729
- }
730
705
 
731
706
  // src/lib/workflow.ts
732
707
  function defineWorkflow(config, fn) {
733
708
  const workflow = async (input, workflowInput = {}) => {
734
709
  const sessionInput = {
710
+ agentName: config.name,
735
711
  ...workflowInput.previousThreadId && {
736
712
  threadId: workflowInput.previousThreadId,
737
713
  continueThread: true
@@ -1748,12 +1724,33 @@ var SandboxManager = class {
1748
1724
  const sandbox = await this.provider.restore(snapshot);
1749
1725
  return sandbox.id;
1750
1726
  }
1727
+ async fork(sandboxId) {
1728
+ const sandbox = await this.provider.fork(sandboxId);
1729
+ return sandbox.id;
1730
+ }
1751
1731
  /**
1752
- * Returns Temporal activity functions matching {@link SandboxOps}.
1753
- * Spread these into your worker's activity map.
1732
+ * Returns Temporal activity functions with prefixed names.
1733
+ *
1734
+ * The provider's `id` is automatically prepended, so you only need
1735
+ * to pass the workflow/scope name. Use the matching `proxy*SandboxOps()`
1736
+ * helper from the adapter's `/workflow` entrypoint on the workflow side.
1737
+ *
1738
+ * @param scope - Workflow name (appended to the provider id)
1739
+ *
1740
+ * @example
1741
+ * ```typescript
1742
+ * const manager = new SandboxManager(new InMemorySandboxProvider());
1743
+ * manager.createActivities("CodingAgent");
1744
+ * // registers: inMemoryCodingAgentCreateSandbox, inMemoryCodingAgentDestroySandbox, …
1745
+ *
1746
+ * const vmgr = new SandboxManager(new VirtualSandboxProvider(resolver));
1747
+ * vmgr.createActivities("CodingAgent");
1748
+ * // registers: virtualCodingAgentCreateSandbox, …
1749
+ * ```
1754
1750
  */
1755
- createActivities() {
1756
- return {
1751
+ createActivities(scope) {
1752
+ const prefix = `${this.provider.id}${scope.charAt(0).toUpperCase()}${scope.slice(1)}`;
1753
+ const ops = {
1757
1754
  createSandbox: async (options) => {
1758
1755
  return this.create(options);
1759
1756
  },
@@ -1762,8 +1759,15 @@ var SandboxManager = class {
1762
1759
  },
1763
1760
  snapshotSandbox: async (sandboxId) => {
1764
1761
  return this.snapshot(sandboxId);
1762
+ },
1763
+ forkSandbox: async (sandboxId) => {
1764
+ return this.fork(sandboxId);
1765
1765
  }
1766
1766
  };
1767
+ const cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
1768
+ return Object.fromEntries(
1769
+ Object.entries(ops).map(([k, v]) => [`${prefix}${cap(k)}`, v])
1770
+ );
1767
1771
  }
1768
1772
  };
1769
1773
 
@@ -2059,8 +2063,6 @@ exports.hasFileWithMimeType = hasFileWithMimeType;
2059
2063
  exports.hasNoOtherToolCalls = hasNoOtherToolCalls;
2060
2064
  exports.isTerminalStatus = isTerminalStatus;
2061
2065
  exports.parseSkillFile = parseSkillFile;
2062
- exports.proxyDefaultThreadOps = proxyDefaultThreadOps;
2063
- exports.proxySandboxOps = proxySandboxOps;
2064
2066
  exports.queryParentWorkflowState = queryParentWorkflowState;
2065
2067
  exports.readFileHandler = readFileHandler;
2066
2068
  exports.readFileTool = readFileTool;