zeitlich 0.2.11 → 0.2.13

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 (46) hide show
  1. package/README.md +313 -126
  2. package/dist/adapters/langchain/index.cjs +270 -0
  3. package/dist/adapters/langchain/index.cjs.map +1 -0
  4. package/dist/adapters/langchain/index.d.cts +132 -0
  5. package/dist/adapters/langchain/index.d.ts +132 -0
  6. package/dist/adapters/langchain/index.js +265 -0
  7. package/dist/adapters/langchain/index.js.map +1 -0
  8. package/dist/index.cjs +89 -209
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +62 -46
  11. package/dist/index.d.ts +62 -46
  12. package/dist/index.js +88 -208
  13. package/dist/index.js.map +1 -1
  14. package/dist/{workflow-BhjsEQc1.d.cts → model-invoker-y_zlyMqu.d.cts} +45 -482
  15. package/dist/{workflow-BhjsEQc1.d.ts → model-invoker-y_zlyMqu.d.ts} +45 -482
  16. package/dist/thread-manager-qc0g5Rvd.d.cts +39 -0
  17. package/dist/thread-manager-qc0g5Rvd.d.ts +39 -0
  18. package/dist/workflow.cjs +59 -27
  19. package/dist/workflow.cjs.map +1 -1
  20. package/dist/workflow.d.cts +459 -6
  21. package/dist/workflow.d.ts +459 -6
  22. package/dist/workflow.js +60 -29
  23. package/dist/workflow.js.map +1 -1
  24. package/package.json +17 -2
  25. package/src/adapters/langchain/activities.ts +120 -0
  26. package/src/adapters/langchain/index.ts +38 -0
  27. package/src/adapters/langchain/model-invoker.ts +102 -0
  28. package/src/adapters/langchain/thread-manager.ts +142 -0
  29. package/src/index.ts +24 -23
  30. package/src/lib/fs.ts +25 -0
  31. package/src/lib/model-invoker.ts +15 -75
  32. package/src/lib/session.ts +52 -21
  33. package/src/lib/state-manager.ts +23 -5
  34. package/src/lib/thread-id.ts +25 -0
  35. package/src/lib/thread-manager.ts +18 -142
  36. package/src/lib/tool-router.ts +12 -18
  37. package/src/lib/types.ts +26 -10
  38. package/src/lib/workflow-helpers.ts +50 -0
  39. package/src/tools/ask-user-question/handler.ts +25 -1
  40. package/src/tools/bash/handler.ts +13 -0
  41. package/src/tools/subagent/handler.ts +16 -5
  42. package/src/tools/subagent/tool.ts +34 -15
  43. package/src/workflow.ts +26 -7
  44. package/tsup.config.ts +1 -0
  45. package/src/activities.ts +0 -91
  46. package/src/plugin.ts +0 -28
@@ -11,6 +11,19 @@ type BashExecOut = {
11
11
  /** BashOptions with `fs` required */
12
12
  type BashToolOptions = Required<Pick<BashOptions, "fs">> & Omit<BashOptions, "fs">;
13
13
 
14
+ /**
15
+ * Creates a Bash tool handler that executes shell commands in a sandboxed environment.
16
+ *
17
+ * @param bashOptions - Options including a required `fs` (file system implementation from `just-bash`)
18
+ * @returns Activity tool handler for Bash tool calls
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * import { createBashHandler } from 'zeitlich';
23
+ *
24
+ * const bashHandlerActivity = createBashHandler({ fs: inMemoryFileSystem });
25
+ * ```
26
+ */
14
27
  export const createBashHandler: (
15
28
  bashOptions: BashToolOptions,
16
29
  ) => ActivityToolHandler<BashArgs, BashExecOut | null> =
@@ -1,5 +1,7 @@
1
- import { executeChild, workflowInfo, uuid4 } from "@temporalio/workflow";
1
+ import { executeChild, workflowInfo } from "@temporalio/workflow";
2
+ import { getShortId } from "../../lib/thread-id";
2
3
  import type { ToolHandlerResponse } from "../../lib/tool-router";
4
+ import type { ToolMessageContent } from "../../lib/types";
3
5
  import type {
4
6
  InferSubagentResult,
5
7
  SubagentConfig,
@@ -40,12 +42,13 @@ export function createSubagentHandler<
40
42
  );
41
43
  }
42
44
 
43
- const childWorkflowId = `${args.subagent}-${uuid4()}`;
45
+ const childWorkflowId = `${args.subagent}-${getShortId()}`;
44
46
 
45
- // Execute the child workflow
46
47
  const input: SubagentInput = {
47
48
  prompt: args.prompt,
48
49
  ...(config.context && { context: config.context }),
50
+ ...(args.threadId &&
51
+ config.allowThreadContinuation && { threadId: args.threadId }),
49
52
  };
50
53
 
51
54
  const childOpts = {
@@ -54,7 +57,7 @@ export function createSubagentHandler<
54
57
  taskQueue: config.taskQueue ?? parentTaskQueue,
55
58
  };
56
59
 
57
- const { toolResponse, data, usage } =
60
+ const { toolResponse, data, usage, threadId: childThreadId } =
58
61
  typeof config.workflow === "string"
59
62
  ? await executeChild(config.workflow, childOpts)
60
63
  : await executeChild(config.workflow, childOpts);
@@ -80,8 +83,16 @@ export function createSubagentHandler<
80
83
  };
81
84
  }
82
85
 
86
+ let finalToolResponse: ToolMessageContent = toolResponse;
87
+ if (config.allowThreadContinuation && childThreadId) {
88
+ finalToolResponse =
89
+ typeof toolResponse === "string"
90
+ ? `${toolResponse}\n\n[Thread ID: ${childThreadId}]`
91
+ : toolResponse;
92
+ }
93
+
83
94
  return {
84
- toolResponse,
95
+ toolResponse: finalToolResponse,
85
96
  data: validated ? validated.data : data,
86
97
  ...(usage && { usage }),
87
98
  };
@@ -8,7 +8,12 @@ export const SUBAGENT_TOOL_NAME = "Subagent" as const;
8
8
  */
9
9
  function buildSubagentDescription(subagents: SubagentConfig[]): string {
10
10
  const subagentList = subagents
11
- .map((s) => `## ${s.agentName}\n${s.description}`)
11
+ .map((s) => {
12
+ const continuation = s.allowThreadContinuation
13
+ ? "\n*(Supports thread continuation — pass a threadId to resume a previous conversation)*"
14
+ : "";
15
+ return `## ${s.agentName}\n${s.description}${continuation}`;
16
+ })
12
17
  .join("\n\n");
13
18
 
14
19
  return `The ${SUBAGENT_TOOL_NAME} tool launches specialized agents (subagents) that autonomously handle complex work. Each agent type has specific capabilities and tools available to it.
@@ -37,30 +42,43 @@ ${subagentList}
37
42
  export function createSubagentTool<T extends SubagentConfig[]>(
38
43
  subagents: T
39
44
  ): {
40
- name: string;
41
- description: string;
42
- schema: z.ZodObject<{
43
- subagent: z.ZodEnum<Record<string, string>>;
44
- description: z.ZodString;
45
- prompt: z.ZodString;
46
- }>;
45
+ readonly name: typeof SUBAGENT_TOOL_NAME;
46
+ readonly description: string;
47
+ readonly schema: z.ZodObject<z.ZodRawShape>;
47
48
  } {
48
49
  if (subagents.length === 0) {
49
50
  throw new Error("createTaskTool requires at least one subagent");
50
51
  }
51
52
 
52
53
  const names = subagents.map((s) => s.agentName);
54
+ const hasThreadContinuation = subagents.some(
55
+ (s) => s.allowThreadContinuation
56
+ );
57
+
58
+ const baseFields = {
59
+ subagent: z.enum(names).describe("The type of subagent to launch"),
60
+ description: z
61
+ .string()
62
+ .describe("A short (3-5 word) description of the task"),
63
+ prompt: z.string().describe("The task for the agent to perform"),
64
+ };
65
+
66
+ const schema = hasThreadContinuation
67
+ ? z.object({
68
+ ...baseFields,
69
+ threadId: z
70
+ .string()
71
+ .nullable()
72
+ .describe(
73
+ "Thread ID to continue an existing conversation, or null to start a new one"
74
+ ),
75
+ })
76
+ : z.object(baseFields);
53
77
 
54
78
  return {
55
79
  name: SUBAGENT_TOOL_NAME,
56
80
  description: buildSubagentDescription(subagents),
57
- schema: z.object({
58
- subagent: z.enum(names).describe("The type of subagent to launch"),
59
- description: z
60
- .string()
61
- .describe("A short (3-5 word) description of the task"),
62
- prompt: z.string().describe("The task for the agent to perform"),
63
- }),
81
+ schema,
64
82
  } as const;
65
83
  }
66
84
 
@@ -71,4 +89,5 @@ export type SubagentArgs = {
71
89
  subagent: string;
72
90
  description: string;
73
91
  prompt: string;
92
+ threadId?: string;
74
93
  };
package/src/workflow.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Workflow-safe exports for use in Temporal workflow code.
3
3
  *
4
- * Import from 'zeitlich/workflow' in workflow files.
4
+ * Import from `zeitlich/workflow` in workflow files.
5
5
  * These exports have no external dependencies (no Redis, no LangChain).
6
6
  *
7
7
  * @example
@@ -10,13 +10,19 @@
10
10
  * import {
11
11
  * createSession,
12
12
  * createAgentStateManager,
13
- * createToolRouter,
13
+ * askUserQuestionTool,
14
+ * bashTool,
15
+ * defineTool,
16
+ * type SubagentWorkflow,
14
17
  * } from 'zeitlich/workflow';
15
18
  * ```
16
19
  */
17
20
 
18
21
  // Session
19
22
  export { createSession, proxyDefaultThreadOps } from "./lib/session";
23
+
24
+ // Thread utilities
25
+ export { getShortId } from "./lib/thread-id";
20
26
  export type { ZeitlichSession, SessionLifecycleHooks } from "./lib/session";
21
27
 
22
28
  // State management
@@ -59,23 +65,30 @@ export type {
59
65
  ToolCallResultUnion,
60
66
  InferToolResults,
61
67
  // Other
62
- ToolMessageContent,
63
68
  AppendToolResultFn,
64
69
  ProcessToolCallsContext,
65
70
  } from "./lib/tool-router";
66
71
 
67
72
  // Types
68
73
  export type {
74
+ // Message types (framework-agnostic)
75
+ ContentPart,
76
+ MessageContent,
77
+ ToolMessageContent,
78
+ TokenUsage,
79
+ // Agent types
69
80
  AgentStatus,
70
81
  BaseAgentState,
71
82
  AgentFile,
72
83
  AgentResponse,
73
84
  ThreadOps,
74
85
  AgentConfig,
86
+ SessionConfig,
75
87
  RunAgentConfig,
76
88
  RunAgentActivity,
77
89
  ToolResultConfig,
78
90
  SessionExitReason,
91
+ // Hook types
79
92
  PreToolUseHook,
80
93
  PreToolUseHookContext,
81
94
  PreToolUseHookResult,
@@ -84,14 +97,21 @@ export type {
84
97
  PostToolUseFailureHook,
85
98
  PostToolUseFailureHookContext,
86
99
  PostToolUseFailureHookResult,
100
+ PreHumanMessageAppendHook,
101
+ PreHumanMessageAppendHookContext,
102
+ PostHumanMessageAppendHook,
103
+ PostHumanMessageAppendHookContext,
104
+ Hooks,
87
105
  ToolHooks,
88
106
  SessionStartHook,
89
107
  SessionStartHookContext,
90
108
  SessionEndHook,
91
109
  SessionEndHookContext,
110
+ // Subagent types
92
111
  SubagentConfig,
93
112
  SubagentHooks,
94
113
  SubagentInput,
114
+ // Task types
95
115
  TaskStatus,
96
116
  WorkflowTask,
97
117
  } from "./lib/types";
@@ -101,6 +121,9 @@ export {
101
121
  agentStateChangeUpdateName,
102
122
  } from "./lib/types";
103
123
 
124
+ // Model invoker contract
125
+ export type { ModelInvoker, ModelInvokerConfig } from "./lib/model-invoker";
126
+
104
127
  // Subagent support
105
128
  export { createSubagentTool } from "./tools/subagent/tool";
106
129
  export type { SubagentArgs } from "./tools/subagent/tool";
@@ -113,10 +136,6 @@ export { createReadSkillTool } from "./tools/read-skill/tool";
113
136
  export { createReadSkillHandler } from "./tools/read-skill/handler";
114
137
  export type { ReadSkillArgs } from "./tools/read-skill/tool";
115
138
 
116
- // Activity type interfaces (types only, no runtime code)
117
- // These are safe to import in workflows for typing proxyActivities
118
- export type { ZeitlichSharedActivities } from "./activities";
119
-
120
139
  // Tool definitions (schemas only - no handlers)
121
140
  export { globTool } from "./tools/glob/tool";
122
141
  export type { GlobArgs } from "./tools/glob/tool";
package/tsup.config.ts CHANGED
@@ -4,6 +4,7 @@ export default defineConfig({
4
4
  entry: {
5
5
  index: "src/index.ts",
6
6
  workflow: "src/workflow.ts",
7
+ "adapters/langchain/index": "src/adapters/langchain/index.ts",
7
8
  },
8
9
  format: ["esm", "cjs"],
9
10
  dts: true,
package/src/activities.ts DELETED
@@ -1,91 +0,0 @@
1
- import type Redis from "ioredis";
2
- import { createThreadManager } from "./lib/thread-manager";
3
- import type { ToolResultConfig } from "./lib/types";
4
- import {
5
- type MessageContent,
6
- type StoredMessage,
7
- } from "@langchain/core/messages";
8
- /**
9
- * Shared Zeitlich activities - thread management and message handling
10
- * Note: runAgent is workflow-specific and should be created per-workflow
11
- */
12
- export interface ZeitlichSharedActivities {
13
- /**
14
- * Append a tool result to the thread.
15
- * Handles JSON serialization and optional cache points.
16
- */
17
- appendToolResult(config: ToolResultConfig): Promise<void>;
18
-
19
- /**
20
- * Initialize an empty thread.
21
- */
22
- initializeThread(threadId: string): Promise<void>;
23
-
24
- /**
25
- * Append messages to a thread.
26
- */
27
- appendThreadMessages(
28
- threadId: string,
29
- messages: StoredMessage[]
30
- ): Promise<void>;
31
-
32
- /**
33
- * Append a human message to a thread.
34
- */
35
- appendHumanMessage(
36
- threadId: string,
37
- content: string | MessageContent
38
- ): Promise<void>;
39
-
40
- /**
41
- * Append a system message to a thread.
42
- */
43
- appendSystemMessage(threadId: string, content: string): Promise<void>;
44
- }
45
-
46
- /**
47
- * Creates shared Temporal activities for thread management
48
- *
49
- * @returns An object containing the shared activity functions
50
- *
51
- * @experimental The Zeitlich integration is an experimental feature; APIs may change without notice.
52
- */
53
- export function createSharedActivities(redis: Redis): ZeitlichSharedActivities {
54
- return {
55
- async appendToolResult(config: ToolResultConfig): Promise<void> {
56
- const { threadId, toolCallId, content } = config;
57
- const thread = createThreadManager({ redis, threadId });
58
-
59
- await thread.appendToolMessage(content, toolCallId);
60
- },
61
-
62
- async initializeThread(threadId: string): Promise<void> {
63
- const thread = createThreadManager({ redis, threadId });
64
- await thread.initialize();
65
- },
66
-
67
- async appendThreadMessages(
68
- threadId: string,
69
- messages: StoredMessage[]
70
- ): Promise<void> {
71
- const thread = createThreadManager({ redis, threadId });
72
- await thread.append(messages);
73
- },
74
-
75
- async appendHumanMessage(
76
- threadId: string,
77
- content: string | MessageContent
78
- ): Promise<void> {
79
- const thread = createThreadManager({ redis, threadId });
80
- await thread.appendHumanMessage(content);
81
- },
82
-
83
- async appendSystemMessage(
84
- threadId: string,
85
- content: string
86
- ): Promise<void> {
87
- const thread = createThreadManager({ redis, threadId });
88
- await thread.appendSystemMessage(content);
89
- },
90
- };
91
- }
package/src/plugin.ts DELETED
@@ -1,28 +0,0 @@
1
- import { SimplePlugin } from "@temporalio/plugin";
2
- import { createSharedActivities } from "./activities";
3
- import type Redis from "ioredis";
4
-
5
- /**
6
- * Options for the Zeitlich plugin
7
- *
8
- * @experimental The Zeitlich plugin is an experimental feature; APIs may change without notice.
9
- */
10
- export interface ZeitlichPluginOptions {
11
- redis: Redis;
12
- }
13
-
14
- /**
15
- * A Temporal plugin that integrates Zeitlich for use in workflows.
16
- * This plugin creates shared activities for thread management.
17
- * Workflow-specific activities (like runAgent) should be created separately.
18
- *
19
- * @experimental The Zeitlich plugin is an experimental feature; APIs may change without notice.
20
- */
21
- export class ZeitlichPlugin extends SimplePlugin {
22
- constructor(options: ZeitlichPluginOptions) {
23
- super({
24
- name: "ZeitlichPlugin",
25
- activities: createSharedActivities(options.redis),
26
- });
27
- }
28
- }