zeitlich 0.2.7 → 0.2.8
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.
- package/dist/index.cjs +68 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +68 -22
- package/dist/index.js.map +1 -1
- package/dist/{workflow-CyYHDbrr.d.cts → workflow-BdAuMMjY.d.cts} +44 -12
- package/dist/{workflow-CyYHDbrr.d.ts → workflow-BdAuMMjY.d.ts} +44 -12
- package/dist/workflow.cjs +63 -19
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +1 -1
- package/dist/workflow.d.ts +1 -1
- package/dist/workflow.js +63 -19
- package/dist/workflow.js.map +1 -1
- package/package.json +1 -1
- package/src/lib/model-invoker.ts +7 -3
- package/src/lib/session.ts +44 -10
- package/src/lib/state-manager.ts +56 -0
- package/src/lib/tool-router.ts +12 -10
- package/src/lib/types.ts +18 -8
- package/src/tools/subagent/handler.ts +2 -1
package/src/lib/session.ts
CHANGED
|
@@ -24,7 +24,11 @@ import type { MessageContent } from "@langchain/core/messages";
|
|
|
24
24
|
export interface ZeitlichSession<M = unknown> {
|
|
25
25
|
runSession<T extends JsonSerializable<T>>(args: {
|
|
26
26
|
stateManager: AgentStateManager<T>;
|
|
27
|
-
}): Promise<
|
|
27
|
+
}): Promise<{
|
|
28
|
+
finalMessage: M | null;
|
|
29
|
+
exitReason: SessionExitReason;
|
|
30
|
+
usage: ReturnType<AgentStateManager<T>["getTotalUsage"]>;
|
|
31
|
+
}>;
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
/**
|
|
@@ -40,6 +44,7 @@ export interface SessionLifecycleHooks {
|
|
|
40
44
|
export const createSession = async <T extends ToolMap, M = unknown>({
|
|
41
45
|
threadId,
|
|
42
46
|
agentName,
|
|
47
|
+
description,
|
|
43
48
|
maxTurns = 50,
|
|
44
49
|
metadata = {},
|
|
45
50
|
runAgent,
|
|
@@ -86,7 +91,13 @@ export const createSession = async <T extends ToolMap, M = unknown>({
|
|
|
86
91
|
};
|
|
87
92
|
|
|
88
93
|
return {
|
|
89
|
-
runSession: async ({
|
|
94
|
+
runSession: async ({
|
|
95
|
+
stateManager,
|
|
96
|
+
}): Promise<{
|
|
97
|
+
finalMessage: M | null;
|
|
98
|
+
exitReason: SessionExitReason;
|
|
99
|
+
usage: ReturnType<typeof stateManager.getTotalUsage>;
|
|
100
|
+
}> => {
|
|
90
101
|
setHandler(
|
|
91
102
|
defineUpdate<unknown, [MessageContent]>(`add${agentName}Message`),
|
|
92
103
|
async (message: MessageContent) => {
|
|
@@ -115,8 +126,6 @@ export const createSession = async <T extends ToolMap, M = unknown>({
|
|
|
115
126
|
});
|
|
116
127
|
}
|
|
117
128
|
|
|
118
|
-
stateManager.setTools(toolRouter.getToolDefinitions());
|
|
119
|
-
|
|
120
129
|
await initializeThread(threadId);
|
|
121
130
|
if (appendSystemPrompt && systemPrompt && systemPrompt.trim() !== "") {
|
|
122
131
|
await appendSystemMessage(threadId, systemPrompt);
|
|
@@ -134,17 +143,29 @@ export const createSession = async <T extends ToolMap, M = unknown>({
|
|
|
134
143
|
stateManager.incrementTurns();
|
|
135
144
|
const currentTurn = stateManager.getTurns();
|
|
136
145
|
|
|
137
|
-
|
|
146
|
+
stateManager.setTools(toolRouter.getToolDefinitions());
|
|
147
|
+
|
|
148
|
+
const { message, rawToolCalls, usage } = await runAgent({
|
|
138
149
|
threadId,
|
|
139
150
|
agentName,
|
|
140
151
|
metadata,
|
|
152
|
+
systemPrompt,
|
|
153
|
+
description,
|
|
141
154
|
});
|
|
142
155
|
|
|
156
|
+
if (usage) {
|
|
157
|
+
stateManager.updateUsage(usage);
|
|
158
|
+
}
|
|
159
|
+
|
|
143
160
|
// No tools configured - treat any non-end_turn as completed
|
|
144
161
|
if (!toolRouter.hasTools() || rawToolCalls.length === 0) {
|
|
145
162
|
stateManager.complete();
|
|
146
163
|
exitReason = "completed";
|
|
147
|
-
return
|
|
164
|
+
return {
|
|
165
|
+
finalMessage: message,
|
|
166
|
+
exitReason,
|
|
167
|
+
usage: stateManager.getTotalUsage(),
|
|
168
|
+
};
|
|
148
169
|
}
|
|
149
170
|
|
|
150
171
|
// Parse all tool calls uniformly through the router
|
|
@@ -165,9 +186,18 @@ export const createSession = async <T extends ToolMap, M = unknown>({
|
|
|
165
186
|
}
|
|
166
187
|
|
|
167
188
|
// Hooks can call stateManager.waitForInput() to pause the session
|
|
168
|
-
await toolRouter.processToolCalls(
|
|
169
|
-
|
|
170
|
-
|
|
189
|
+
const toolCallResults = await toolRouter.processToolCalls(
|
|
190
|
+
parsedToolCalls,
|
|
191
|
+
{
|
|
192
|
+
turn: currentTurn,
|
|
193
|
+
}
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
for (const result of toolCallResults) {
|
|
197
|
+
if (result.usage) {
|
|
198
|
+
stateManager.updateUsage(result.usage);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
171
201
|
|
|
172
202
|
if (stateManager.getStatus() === "WAITING_FOR_INPUT") {
|
|
173
203
|
const conditionMet = await condition(
|
|
@@ -195,7 +225,11 @@ export const createSession = async <T extends ToolMap, M = unknown>({
|
|
|
195
225
|
await callSessionEnd(exitReason, stateManager.getTurns());
|
|
196
226
|
}
|
|
197
227
|
|
|
198
|
-
return
|
|
228
|
+
return {
|
|
229
|
+
finalMessage: null,
|
|
230
|
+
exitReason,
|
|
231
|
+
usage: stateManager.getTotalUsage(),
|
|
232
|
+
};
|
|
199
233
|
},
|
|
200
234
|
};
|
|
201
235
|
};
|
package/src/lib/state-manager.ts
CHANGED
|
@@ -114,6 +114,25 @@ export interface AgentStateManager<TCustom extends JsonSerializable<TCustom>> {
|
|
|
114
114
|
|
|
115
115
|
/** Set the tools (converts Zod schemas to JSON Schema for serialization) */
|
|
116
116
|
setTools(newTools: ToolDefinition[]): void;
|
|
117
|
+
|
|
118
|
+
/** Update the usage */
|
|
119
|
+
updateUsage(usage: {
|
|
120
|
+
inputTokens?: number;
|
|
121
|
+
outputTokens?: number;
|
|
122
|
+
cachedWriteTokens?: number;
|
|
123
|
+
cachedReadTokens?: number;
|
|
124
|
+
reasonTokens?: number;
|
|
125
|
+
}): void;
|
|
126
|
+
|
|
127
|
+
/** Get the total usage */
|
|
128
|
+
getTotalUsage(): {
|
|
129
|
+
totalInputTokens: number;
|
|
130
|
+
totalOutputTokens: number;
|
|
131
|
+
totalCachedWriteTokens: number;
|
|
132
|
+
totalCachedReadTokens: number;
|
|
133
|
+
totalReasonTokens: number;
|
|
134
|
+
turns: number;
|
|
135
|
+
};
|
|
117
136
|
}
|
|
118
137
|
|
|
119
138
|
/**
|
|
@@ -140,6 +159,11 @@ export function createAgentStateManager<
|
|
|
140
159
|
let version = initialState?.version ?? 0;
|
|
141
160
|
let turns = initialState?.turns ?? 0;
|
|
142
161
|
let tools = initialState?.tools ?? [];
|
|
162
|
+
let totalInputTokens = 0;
|
|
163
|
+
let totalOutputTokens = 0;
|
|
164
|
+
let totalCachedWriteTokens = 0;
|
|
165
|
+
let totalCachedReadTokens = 0;
|
|
166
|
+
let totalReasonTokens = 0;
|
|
143
167
|
|
|
144
168
|
// Tasks state
|
|
145
169
|
const tasks = new Map<string, WorkflowTask>(initialState?.tasks);
|
|
@@ -283,6 +307,38 @@ export function createAgentStateManager<
|
|
|
283
307
|
}
|
|
284
308
|
return deleted;
|
|
285
309
|
},
|
|
310
|
+
|
|
311
|
+
updateUsage(usage: {
|
|
312
|
+
inputTokens?: number;
|
|
313
|
+
outputTokens?: number;
|
|
314
|
+
cachedWriteTokens?: number;
|
|
315
|
+
cachedReadTokens?: number;
|
|
316
|
+
reasonTokens?: number;
|
|
317
|
+
}): void {
|
|
318
|
+
totalInputTokens += usage.inputTokens ?? 0;
|
|
319
|
+
totalOutputTokens += usage.outputTokens ?? 0;
|
|
320
|
+
totalCachedWriteTokens += usage.cachedWriteTokens ?? 0;
|
|
321
|
+
totalCachedReadTokens += usage.cachedReadTokens ?? 0;
|
|
322
|
+
totalReasonTokens += usage.reasonTokens ?? 0;
|
|
323
|
+
},
|
|
324
|
+
|
|
325
|
+
getTotalUsage(): {
|
|
326
|
+
totalInputTokens: number;
|
|
327
|
+
totalOutputTokens: number;
|
|
328
|
+
totalCachedWriteTokens: number;
|
|
329
|
+
totalCachedReadTokens: number;
|
|
330
|
+
totalReasonTokens: number;
|
|
331
|
+
turns: number;
|
|
332
|
+
} {
|
|
333
|
+
return {
|
|
334
|
+
totalInputTokens,
|
|
335
|
+
totalOutputTokens,
|
|
336
|
+
totalCachedWriteTokens,
|
|
337
|
+
totalCachedReadTokens,
|
|
338
|
+
totalReasonTokens,
|
|
339
|
+
turns,
|
|
340
|
+
};
|
|
341
|
+
},
|
|
286
342
|
};
|
|
287
343
|
}
|
|
288
344
|
|
package/src/lib/tool-router.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
PreToolUseHookResult,
|
|
7
7
|
SubagentConfig,
|
|
8
8
|
SubagentHooks,
|
|
9
|
+
TokenUsage,
|
|
9
10
|
ToolHooks,
|
|
10
11
|
ToolResultConfig,
|
|
11
12
|
} from "./types";
|
|
@@ -53,7 +54,7 @@ export interface ToolWithHandler<
|
|
|
53
54
|
strict?: boolean;
|
|
54
55
|
max_uses?: number;
|
|
55
56
|
/** Whether this tool is available to the agent (default: true). Disabled tools are excluded from definitions and rejected at parse time. */
|
|
56
|
-
enabled?: boolean;
|
|
57
|
+
enabled?: () => boolean;
|
|
57
58
|
/** Per-tool lifecycle hooks (run in addition to global hooks) */
|
|
58
59
|
hooks?: ToolHooks<z.infer<TSchema>, TResult>;
|
|
59
60
|
}
|
|
@@ -76,7 +77,7 @@ export type ToolMap = Record<
|
|
|
76
77
|
handler: ToolHandler<any, any, any>;
|
|
77
78
|
strict?: boolean;
|
|
78
79
|
max_uses?: number;
|
|
79
|
-
enabled?: boolean;
|
|
80
|
+
enabled?: () => boolean;
|
|
80
81
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
81
82
|
hooks?: ToolHooks<any, any>;
|
|
82
83
|
}
|
|
@@ -153,6 +154,8 @@ export interface ToolHandlerResponse<TResult = null> {
|
|
|
153
154
|
* payloads through Temporal's activity payload limit.
|
|
154
155
|
*/
|
|
155
156
|
resultAppended?: boolean;
|
|
157
|
+
/** Token usage from the tool execution (e.g. child agent invocations) */
|
|
158
|
+
usage?: TokenUsage;
|
|
156
159
|
}
|
|
157
160
|
|
|
158
161
|
/**
|
|
@@ -228,6 +231,7 @@ export interface ToolCallResult<
|
|
|
228
231
|
toolCallId: string;
|
|
229
232
|
name: TName;
|
|
230
233
|
data: TResult;
|
|
234
|
+
usage?: TokenUsage;
|
|
231
235
|
}
|
|
232
236
|
|
|
233
237
|
/**
|
|
@@ -412,16 +416,14 @@ export function createToolRouter<T extends ToolMap>(
|
|
|
412
416
|
}
|
|
413
417
|
|
|
414
418
|
/** Check if a tool is enabled (defaults to true when not specified) */
|
|
415
|
-
const isEnabled = (tool: ToolMap[string]): boolean =>
|
|
419
|
+
const isEnabled = (tool: ToolMap[string]): boolean =>
|
|
420
|
+
tool.enabled?.() ?? true;
|
|
416
421
|
|
|
417
422
|
if (options.subagents) {
|
|
418
|
-
|
|
419
|
-
(s) => s.enabled !== false
|
|
420
|
-
);
|
|
421
|
-
if (enabledSubagents.length > 0) {
|
|
423
|
+
if (options.subagents.length > 0) {
|
|
422
424
|
// Build per-subagent hook dispatcher keyed by subagent name
|
|
423
425
|
const subagentHooksMap = new Map<string, SubagentHooks>();
|
|
424
|
-
for (const s of
|
|
426
|
+
for (const s of options.subagents) {
|
|
425
427
|
if (s.hooks) subagentHooksMap.set(s.agentName, s.hooks);
|
|
426
428
|
}
|
|
427
429
|
|
|
@@ -429,8 +431,8 @@ export function createToolRouter<T extends ToolMap>(
|
|
|
429
431
|
(args as SubagentArgs).subagent;
|
|
430
432
|
|
|
431
433
|
toolMap.set("Subagent", {
|
|
432
|
-
...createSubagentTool(
|
|
433
|
-
handler: createSubagentHandler(
|
|
434
|
+
...createSubagentTool(options.subagents),
|
|
435
|
+
handler: createSubagentHandler(options.subagents),
|
|
434
436
|
...(subagentHooksMap.size > 0 && {
|
|
435
437
|
hooks: {
|
|
436
438
|
onPreToolUse: async (ctx): Promise<PreToolUseHookResult> => {
|
package/src/lib/types.ts
CHANGED
|
@@ -32,6 +32,10 @@ export interface BaseAgentState {
|
|
|
32
32
|
turns: number;
|
|
33
33
|
tasks: Map<string, WorkflowTask>;
|
|
34
34
|
systemPrompt: string;
|
|
35
|
+
totalInputTokens: number;
|
|
36
|
+
totalOutputTokens: number;
|
|
37
|
+
cachedWriteTokens: number;
|
|
38
|
+
cachedReadtTokens: number;
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
/**
|
|
@@ -50,17 +54,21 @@ export interface AgentFile {
|
|
|
50
54
|
mimeType?: string;
|
|
51
55
|
}
|
|
52
56
|
|
|
57
|
+
export interface TokenUsage {
|
|
58
|
+
inputTokens?: number;
|
|
59
|
+
outputTokens?: number;
|
|
60
|
+
cachedWriteTokens?: number;
|
|
61
|
+
cachedReadTokens?: number;
|
|
62
|
+
reasonTokens?: number;
|
|
63
|
+
}
|
|
64
|
+
|
|
53
65
|
/**
|
|
54
66
|
* Agent response from LLM invocation
|
|
55
67
|
*/
|
|
56
68
|
export interface AgentResponse<M = StoredMessage> {
|
|
57
69
|
message: M;
|
|
58
70
|
rawToolCalls: RawToolCall[];
|
|
59
|
-
usage?:
|
|
60
|
-
input_tokens?: number;
|
|
61
|
-
output_tokens?: number;
|
|
62
|
-
total_tokens?: number;
|
|
63
|
-
};
|
|
71
|
+
usage?: TokenUsage;
|
|
64
72
|
}
|
|
65
73
|
|
|
66
74
|
/**
|
|
@@ -143,9 +151,10 @@ export interface SerializableToolDefinition {
|
|
|
143
151
|
/**
|
|
144
152
|
* Configuration passed to runAgent activity
|
|
145
153
|
*/
|
|
146
|
-
export interface RunAgentConfig {
|
|
154
|
+
export interface RunAgentConfig extends AgentConfig {
|
|
155
|
+
/** The thread ID to use for the session */
|
|
147
156
|
threadId: string;
|
|
148
|
-
|
|
157
|
+
/** Metadata for the session */
|
|
149
158
|
metadata?: Record<string, unknown>;
|
|
150
159
|
}
|
|
151
160
|
|
|
@@ -155,6 +164,7 @@ export interface RunAgentConfig {
|
|
|
155
164
|
export type RunAgentActivity<M = StoredMessage> = (
|
|
156
165
|
config: RunAgentConfig
|
|
157
166
|
) => Promise<AgentResponse<M>>;
|
|
167
|
+
|
|
158
168
|
/**
|
|
159
169
|
* Configuration for appending a tool result
|
|
160
170
|
*/
|
|
@@ -186,7 +196,7 @@ export interface SubagentConfig<TResult extends z.ZodType = z.ZodType> {
|
|
|
186
196
|
/** Description shown to the parent agent explaining what this subagent does */
|
|
187
197
|
description: string;
|
|
188
198
|
/** Whether this subagent is available (default: true). Disabled subagents are excluded from the Subagent tool. */
|
|
189
|
-
enabled?: boolean;
|
|
199
|
+
enabled?: () => boolean;
|
|
190
200
|
/** Temporal workflow function or type name (used with executeChild) */
|
|
191
201
|
workflow: string | Workflow;
|
|
192
202
|
/** Optional task queue - defaults to parent's queue if not specified */
|
|
@@ -53,7 +53,7 @@ export function createSubagentHandler<
|
|
|
53
53
|
taskQueue: config.taskQueue ?? parentTaskQueue,
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
-
const { toolResponse, data } =
|
|
56
|
+
const { toolResponse, data, usage } =
|
|
57
57
|
typeof config.workflow === "string"
|
|
58
58
|
? await executeChild(config.workflow, childOpts)
|
|
59
59
|
: await executeChild(config.workflow, childOpts);
|
|
@@ -66,6 +66,7 @@ export function createSubagentHandler<
|
|
|
66
66
|
return {
|
|
67
67
|
toolResponse,
|
|
68
68
|
data: validated,
|
|
69
|
+
...(usage && { usage }),
|
|
69
70
|
};
|
|
70
71
|
};
|
|
71
72
|
}
|