zeitlich 0.2.34 → 0.2.35

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 (65) hide show
  1. package/dist/{activities-JOqPfKP0.d.cts → activities-BVI2lTwr.d.ts} +6 -4
  2. package/dist/{activities-WwMsjRwm.d.ts → activities-hd4aNnZE.d.cts} +6 -4
  3. package/dist/adapters/thread/anthropic/index.cjs +7 -2
  4. package/dist/adapters/thread/anthropic/index.cjs.map +1 -1
  5. package/dist/adapters/thread/anthropic/index.d.cts +4 -4
  6. package/dist/adapters/thread/anthropic/index.d.ts +4 -4
  7. package/dist/adapters/thread/anthropic/index.js +7 -2
  8. package/dist/adapters/thread/anthropic/index.js.map +1 -1
  9. package/dist/adapters/thread/anthropic/workflow.d.cts +4 -4
  10. package/dist/adapters/thread/anthropic/workflow.d.ts +4 -4
  11. package/dist/adapters/thread/google-genai/index.cjs +4 -3
  12. package/dist/adapters/thread/google-genai/index.cjs.map +1 -1
  13. package/dist/adapters/thread/google-genai/index.d.cts +4 -4
  14. package/dist/adapters/thread/google-genai/index.d.ts +4 -4
  15. package/dist/adapters/thread/google-genai/index.js +4 -3
  16. package/dist/adapters/thread/google-genai/index.js.map +1 -1
  17. package/dist/adapters/thread/google-genai/workflow.d.cts +4 -4
  18. package/dist/adapters/thread/google-genai/workflow.d.ts +4 -4
  19. package/dist/adapters/thread/langchain/index.cjs +4 -1
  20. package/dist/adapters/thread/langchain/index.cjs.map +1 -1
  21. package/dist/adapters/thread/langchain/index.d.cts +4 -4
  22. package/dist/adapters/thread/langchain/index.d.ts +4 -4
  23. package/dist/adapters/thread/langchain/index.js +4 -1
  24. package/dist/adapters/thread/langchain/index.js.map +1 -1
  25. package/dist/adapters/thread/langchain/workflow.d.cts +4 -4
  26. package/dist/adapters/thread/langchain/workflow.d.ts +4 -4
  27. package/dist/index.cjs +1 -1
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +6 -6
  30. package/dist/index.d.ts +6 -6
  31. package/dist/index.js +1 -1
  32. package/dist/index.js.map +1 -1
  33. package/dist/{proxy-BesT2ioL.d.cts → proxy-7RnVaPdJ.d.cts} +1 -1
  34. package/dist/{proxy-Bz6wXYW-.d.ts → proxy-BjdFGPTm.d.ts} +1 -1
  35. package/dist/{thread-manager-DarJIK_b.d.ts → thread-manager-BBzNgQWH.d.cts} +5 -2
  36. package/dist/{thread-manager-Cf_34H8w.d.cts → thread-manager-CbpiGq1L.d.ts} +6 -3
  37. package/dist/{thread-manager-CCVAOK8g.d.cts → thread-manager-DjN5JYul.d.ts} +5 -2
  38. package/dist/{thread-manager-ClKAQx78.d.ts → thread-manager-DzXm9eeI.d.cts} +6 -3
  39. package/dist/{types-BGLW5Zyj.d.ts → types-CADc5V_P.d.ts} +4 -4
  40. package/dist/{types-DlLajQcu.d.cts → types-DQ1l_gXL.d.cts} +4 -4
  41. package/dist/{types-DPAZ3KCs.d.cts → types-Mc_4BCfT.d.cts} +3 -3
  42. package/dist/{types-BVUmLYpj.d.ts → types-yiXmqedU.d.ts} +3 -3
  43. package/dist/{workflow-hocXpLwg.d.cts → workflow-DhtWRovz.d.cts} +1 -1
  44. package/dist/{workflow-_ZGcacCK.d.ts → workflow-P2pTSfKu.d.ts} +1 -1
  45. package/dist/workflow.cjs +1 -1
  46. package/dist/workflow.cjs.map +1 -1
  47. package/dist/workflow.d.cts +2 -2
  48. package/dist/workflow.d.ts +2 -2
  49. package/dist/workflow.js +1 -1
  50. package/dist/workflow.js.map +1 -1
  51. package/package.json +1 -1
  52. package/src/adapters/thread/anthropic/activities.ts +2 -1
  53. package/src/adapters/thread/anthropic/thread-manager.ts +21 -9
  54. package/src/adapters/thread/google-genai/activities.ts +2 -1
  55. package/src/adapters/thread/google-genai/thread-manager.test.ts +1 -1
  56. package/src/adapters/thread/google-genai/thread-manager.ts +15 -7
  57. package/src/adapters/thread/langchain/activities.ts +2 -1
  58. package/src/adapters/thread/langchain/thread-manager.ts +12 -3
  59. package/src/lib/session/session.ts +4 -1
  60. package/src/lib/session/types.ts +5 -2
  61. package/src/lib/state/manager.ts +2 -2
  62. package/src/lib/state/types.ts +2 -2
  63. package/src/lib/thread/types.ts +2 -2
  64. package/src/lib/types.ts +1 -1
  65. package/src/workflow.ts +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zeitlich",
3
- "version": "0.2.34",
3
+ "version": "0.2.35",
4
4
  "description": "[EXPERIMENTAL] An opinionated AI agent implementation for Temporal",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -15,6 +15,7 @@ import type { ModelInvoker } from "../../../lib/model";
15
15
  import {
16
16
  createAnthropicThreadManager,
17
17
  type AnthropicContent,
18
+ type AnthropicSystemContent,
18
19
  type AnthropicThreadManagerHooks,
19
20
  } from "./thread-manager";
20
21
  import {
@@ -152,7 +153,7 @@ export function createAnthropicAdapter(
152
153
  async appendSystemMessage(
153
154
  threadId: string,
154
155
  id: string,
155
- content: string,
156
+ content: AnthropicSystemContent,
156
157
  threadKey?: string,
157
158
  ): Promise<void> {
158
159
  const thread = createAnthropicThreadManager({ redis, threadId, key: threadKey });
@@ -13,6 +13,11 @@ export type AnthropicContent =
13
13
  | string
14
14
  | Anthropic.Messages.ContentBlockParam[];
15
15
 
16
+ /** SDK-native content type for Anthropic system prompts (supports cache_control blocks) */
17
+ export type AnthropicSystemContent =
18
+ | string
19
+ | Anthropic.Messages.TextBlockParam[];
20
+
16
21
  /** A MessageParam with a unique ID for idempotent Redis storage */
17
22
  export interface StoredMessage {
18
23
  id: string;
@@ -34,12 +39,12 @@ export interface AnthropicThreadManagerConfig {
34
39
  /** Prepared payload ready to send to the Anthropic API */
35
40
  export interface AnthropicInvocationPayload {
36
41
  messages: Anthropic.Messages.MessageParam[];
37
- system?: string;
42
+ system?: string | Anthropic.Messages.TextBlockParam[];
38
43
  }
39
44
 
40
45
  /** Thread manager with Anthropic MessageParam convenience helpers */
41
46
  export interface AnthropicThreadManager
42
- extends ProviderThreadManager<StoredMessage, AnthropicContent> {
47
+ extends ProviderThreadManager<StoredMessage, AnthropicContent, JsonValue, AnthropicSystemContent> {
43
48
  appendAssistantMessage(
44
49
  id: string,
45
50
  content: Anthropic.Messages.ContentBlock[],
@@ -120,11 +125,19 @@ export function createAnthropicThreadManager(
120
125
  }]);
121
126
  },
122
127
 
123
- async appendSystemMessage(id: string, content: string): Promise<void> {
128
+ async appendSystemMessage(
129
+ id: string,
130
+ content: AnthropicSystemContent,
131
+ ): Promise<void> {
124
132
  await base.initialize();
125
133
  await base.append([{
126
134
  id,
127
- message: { role: "user", content },
135
+ // Stored under a user-role placeholder to satisfy the MessageParam
136
+ // shape; the `isSystem` flag steers extraction in prepareForInvocation.
137
+ message: {
138
+ role: "user",
139
+ content: content as Anthropic.Messages.MessageParam["content"],
140
+ },
128
141
  isSystem: true,
129
142
  }]);
130
143
  },
@@ -174,15 +187,14 @@ export function createAnthropicThreadManager(
174
187
  ? stored.map((msg, i) => onPrepareMessage(msg, i, stored))
175
188
  : stored;
176
189
 
177
- let system: string | undefined;
190
+ let system: string | Anthropic.Messages.TextBlockParam[] | undefined;
178
191
  const conversationMessages: Anthropic.Messages.MessageParam[] = [];
179
192
 
180
193
  for (const item of mapped) {
181
194
  if (item.isSystem) {
182
- system =
183
- typeof item.message.content === "string"
184
- ? item.message.content
185
- : undefined;
195
+ system = item.message.content as
196
+ | string
197
+ | Anthropic.Messages.TextBlockParam[];
186
198
  } else {
187
199
  conversationMessages.push(item.message);
188
200
  }
@@ -15,6 +15,7 @@ import type { ModelInvoker } from "../../../lib/model";
15
15
  import {
16
16
  createGoogleGenAIThreadManager,
17
17
  type GoogleGenAIContent,
18
+ type GoogleGenAISystemContent,
18
19
  type GoogleGenAIThreadManagerHooks,
19
20
  } from "./thread-manager";
20
21
  import { createGoogleGenAIModelInvoker } from "./model-invoker";
@@ -169,7 +170,7 @@ export function createGoogleGenAIAdapter(
169
170
  async appendSystemMessage(
170
171
  threadId: string,
171
172
  id: string,
172
- content: string,
173
+ content: GoogleGenAISystemContent,
173
174
  threadKey?: string
174
175
  ): Promise<void> {
175
176
  const thread = createGoogleGenAIThreadManager({
@@ -55,7 +55,7 @@ describe("Google GenAI thread manager hooks", () => {
55
55
 
56
56
  expect(hook).toHaveBeenCalledTimes(3);
57
57
  expect(hook).toHaveBeenCalledWith(systemContent, 0, [systemContent, userContent, modelContent]);
58
- expect(systemInstruction).toBe("You are helpful.");
58
+ expect(systemInstruction).toEqual([{ text: "You are helpful." }]);
59
59
  expect(contents[0]?.parts?.[0]?.text).toBe("[modified] Hello");
60
60
  expect(contents[1]?.parts?.[0]?.text).toBe("[modified] Hi there!");
61
61
  });
@@ -11,6 +11,9 @@ import type { GoogleGenAIToolResponse } from "./activities";
11
11
  /** SDK-native content type for Google GenAI human messages */
12
12
  export type GoogleGenAIContent = string | Part[];
13
13
 
14
+ /** SDK-native content type for Google GenAI system instructions */
15
+ export type GoogleGenAISystemContent = string | Part[];
16
+
14
17
  /** A Content with a unique ID for idempotent Redis storage */
15
18
  export interface StoredContent {
16
19
  id: string;
@@ -30,12 +33,12 @@ export interface GoogleGenAIThreadManagerConfig {
30
33
  /** Prepared payload ready to send to the Google GenAI API */
31
34
  export interface GoogleGenAIInvocationPayload {
32
35
  contents: Content[];
33
- systemInstruction?: string;
36
+ systemInstruction?: Part[];
34
37
  }
35
38
 
36
39
  /** Thread manager with Google GenAI Content convenience helpers */
37
40
  export interface GoogleGenAIThreadManager
38
- extends ProviderThreadManager<StoredContent, GoogleGenAIContent, GoogleGenAIToolResponse> {
41
+ extends ProviderThreadManager<StoredContent, GoogleGenAIContent, GoogleGenAIToolResponse, GoogleGenAISystemContent> {
39
42
  appendModelContent(id: string, parts: Part[]): Promise<void>;
40
43
  prepareForInvocation(): Promise<GoogleGenAIInvocationPayload>;
41
44
  }
@@ -106,11 +109,16 @@ export function createGoogleGenAIThreadManager(
106
109
  }]);
107
110
  },
108
111
 
109
- async appendSystemMessage(id: string, content: string): Promise<void> {
112
+ async appendSystemMessage(
113
+ id: string,
114
+ content: GoogleGenAISystemContent,
115
+ ): Promise<void> {
116
+ const parts: Part[] =
117
+ typeof content === "string" ? [{ text: content }] : content;
110
118
  await base.initialize();
111
119
  await base.append([{
112
120
  id,
113
- content: { role: "system", parts: [{ text: content }] },
121
+ content: { role: "system", parts },
114
122
  }]);
115
123
  },
116
124
 
@@ -150,12 +158,12 @@ export function createGoogleGenAIThreadManager(
150
158
  ? stored.map((msg, i) => onPrepareMessage(msg, i, stored))
151
159
  : stored;
152
160
 
153
- let systemInstruction: string | undefined;
161
+ let systemInstruction: Part[] | undefined;
154
162
  const conversationContents: Content[] = [];
155
163
 
156
164
  for (const item of mapped) {
157
165
  if (item.content.role === "system") {
158
- systemInstruction = item.content.parts?.[0]?.text;
166
+ systemInstruction = item.content.parts ?? [];
159
167
  } else {
160
168
  conversationContents.push(item.content);
161
169
  }
@@ -166,7 +174,7 @@ export function createGoogleGenAIThreadManager(
166
174
  contents: onPreparedMessage
167
175
  ? contents.map((msg, i) => onPreparedMessage(msg, i, contents))
168
176
  : contents,
169
- ...(systemInstruction ? { systemInstruction } : {}),
177
+ ...(systemInstruction && systemInstruction.length > 0 ? { systemInstruction } : {}),
170
178
  };
171
179
  },
172
180
  };
@@ -17,6 +17,7 @@ import type { BaseChatModel } from "@langchain/core/language_models/chat_models"
17
17
  import {
18
18
  createLangChainThreadManager,
19
19
  type LangChainContent,
20
+ type LangChainSystemContent,
20
21
  type LangChainThreadManagerHooks,
21
22
  } from "./thread-manager";
22
23
  import { createLangChainModelInvoker } from "./model-invoker";
@@ -135,7 +136,7 @@ export function createLangChainAdapter(
135
136
  async appendSystemMessage(
136
137
  threadId: string,
137
138
  id: string,
138
- content: string,
139
+ content: LangChainSystemContent,
139
140
  threadKey?: string,
140
141
  ): Promise<void> {
141
142
  const thread = createLangChainThreadManager({ redis, threadId, key: threadKey });
@@ -20,6 +20,9 @@ import type {
20
20
  /** SDK-native content type for LangChain human messages */
21
21
  export type LangChainContent = string | MessageContent;
22
22
 
23
+ /** SDK-native content type for LangChain system messages */
24
+ export type LangChainSystemContent = string | MessageContent;
25
+
23
26
  export type LangChainThreadManagerHooks = ThreadManagerHooks<StoredMessage, BaseMessage>;
24
27
 
25
28
  export interface LangChainThreadManagerConfig {
@@ -37,7 +40,7 @@ export interface LangChainInvocationPayload {
37
40
 
38
41
  /** Thread manager with LangChain StoredMessage convenience helpers */
39
42
  export interface LangChainThreadManager
40
- extends ProviderThreadManager<StoredMessage, LangChainContent> {
43
+ extends ProviderThreadManager<StoredMessage, LangChainContent, JsonValue, LangChainSystemContent> {
41
44
  appendAIMessage(id: string, content: string | MessageContent): Promise<void>;
42
45
  prepareForInvocation(): Promise<LangChainInvocationPayload>;
43
46
  }
@@ -81,10 +84,16 @@ export function createLangChainThreadManager(
81
84
  ]);
82
85
  },
83
86
 
84
- async appendSystemMessage(id: string, content: string): Promise<void> {
87
+ async appendSystemMessage(
88
+ id: string,
89
+ content: LangChainSystemContent,
90
+ ): Promise<void> {
85
91
  await base.initialize();
86
92
  await base.append([
87
- new SystemMessage({ id, content }).toDict(),
93
+ new SystemMessage({
94
+ id,
95
+ content: content as MessageContent,
96
+ }).toDict(),
88
97
  ]);
89
98
  },
90
99
 
@@ -325,7 +325,10 @@ export async function createSession<
325
325
  // "continue" — thread already exists, just append the new message
326
326
  } else {
327
327
  if (appendSystemPrompt) {
328
- if (!systemPrompt || systemPrompt.trim() === "") {
328
+ if (
329
+ systemPrompt == null ||
330
+ (typeof systemPrompt === "string" && systemPrompt.trim() === "")
331
+ ) {
329
332
  throw ApplicationFailure.create({
330
333
  message: "No system prompt in state",
331
334
  nonRetryable: true,
@@ -1,5 +1,8 @@
1
1
  import type { Duration } from "@temporalio/common";
2
- import type { ToolResultConfig, SessionExitReason } from "../types";
2
+ import type {
3
+ SessionExitReason,
4
+ ToolResultConfig,
5
+ } from "../types";
3
6
  import type {
4
7
  ToolMap,
5
8
  ToolCallResultUnion,
@@ -50,7 +53,7 @@ export interface ThreadOps<TContent = string> {
50
53
  appendSystemMessage(
51
54
  threadId: string,
52
55
  id: string,
53
- content: string,
56
+ content: unknown,
54
57
  threadKey?: string
55
58
  ): Promise<void>;
56
59
  /** Copy all messages from sourceThreadId into a new thread at targetThreadId */
@@ -108,7 +108,7 @@ export function createAgentStateManager<
108
108
  return status === "RUNNING";
109
109
  },
110
110
 
111
- getSystemPrompt(): string | undefined {
111
+ getSystemPrompt(): unknown {
112
112
  return systemPrompt;
113
113
  },
114
114
 
@@ -202,7 +202,7 @@ export function createAgentStateManager<
202
202
  }));
203
203
  },
204
204
 
205
- setSystemPrompt(newSystemPrompt: string): void {
205
+ setSystemPrompt(newSystemPrompt: unknown): void {
206
206
  systemPrompt = newSystemPrompt;
207
207
  },
208
208
 
@@ -90,10 +90,10 @@ export interface AgentStateManager<TCustom extends JsonSerializable<TCustom>> {
90
90
  getTurns(): number;
91
91
 
92
92
  /** Get the system prompt */
93
- getSystemPrompt(): string | undefined;
93
+ getSystemPrompt(): unknown;
94
94
 
95
95
  /** Set the system prompt */
96
- setSystemPrompt(newSystemPrompt: string): void;
96
+ setSystemPrompt(newSystemPrompt: unknown): void;
97
97
 
98
98
  /** Get a custom state value by key */
99
99
  get<K extends keyof TCustom>(key: K): TCustom[K];
@@ -1,6 +1,5 @@
1
1
  import type Redis from "ioredis";
2
2
  import type { JsonValue } from "../state/types";
3
-
4
3
  export interface ThreadManagerConfig<T> {
5
4
  redis: Redis;
6
5
  threadId: string;
@@ -71,9 +70,10 @@ export interface ProviderThreadManager<
71
70
  TStored,
72
71
  TContent = string,
73
72
  TToolContent = JsonValue,
73
+ TSystemContent = string,
74
74
  > extends BaseThreadManager<TStored> {
75
75
  appendUserMessage(id: string, content: TContent): Promise<void>;
76
- appendSystemMessage(id: string, content: string): Promise<void>;
76
+ appendSystemMessage(id: string, content: TSystemContent): Promise<void>;
77
77
  appendToolResult(
78
78
  id: string,
79
79
  toolCallId: string,
package/src/lib/types.ts CHANGED
@@ -28,7 +28,7 @@ export interface BaseAgentState {
28
28
  /** In-memory file contents keyed by path, bypassing the resolver (e.g. skill resources). */
29
29
  inlineFiles?: Record<string, string>;
30
30
  virtualFsCtx?: unknown;
31
- systemPrompt?: string;
31
+ systemPrompt?: unknown;
32
32
  totalInputTokens: number;
33
33
  totalOutputTokens: number;
34
34
  cachedWriteTokens: number;
package/src/workflow.ts CHANGED
@@ -119,7 +119,6 @@ export type {
119
119
  ToolResultConfig,
120
120
  SessionExitReason,
121
121
  SerializableToolDefinition,
122
- // Task types
123
122
  TaskStatus,
124
123
  WorkflowTask,
125
124
  } from "./lib/types";