zidane 1.2.0 → 1.3.1

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/README.md CHANGED
@@ -290,24 +290,40 @@ MCP connections are made lazily on the first `run()` call and reused across subs
290
290
 
291
291
  ## Sessions
292
292
 
293
- Sessions give an agent persistent identity, message history, and run metadata across multiple calls or restarts.
293
+ Sessions give an agent persistent identity, turn history, and run metadata across multiple calls or restarts. Each message exchange is a `SessionTurn` with its own UUID, enabling real-time multiplayer streaming.
294
+
295
+ ### SessionTurn
296
+
297
+ Every message in a session is a turn:
298
+
299
+ ```ts
300
+ interface SessionTurn {
301
+ id: string // UUID — generated by store or crypto.randomUUID()
302
+ role: 'user' | 'assistant' | 'system'
303
+ content: SessionContentBlock[] // same format used by providers
304
+ usage?: TurnUsage // token usage (assistant turns only)
305
+ createdAt: number // timestamp
306
+ }
307
+ ```
294
308
 
295
309
  ### Creating a session
296
310
 
311
+ `createSession` is async — stores can generate IDs server-side (e.g. Supabase).
312
+
297
313
  ```ts
298
314
  import { createSession, createMemoryStore } from 'zidane/session'
299
315
 
300
316
  // In-memory (default, no persistence)
301
- const session = createSession({ id: 'my-session', agentId: 'my-agent' })
317
+ const session = await createSession({ id: 'my-session', agentId: 'my-agent' })
302
318
 
303
319
  // With a store for persistence
304
320
  const store = createMemoryStore()
305
- const session = createSession({ id: 'my-session', store })
321
+ const session = await createSession({ id: 'my-session', store })
306
322
  ```
307
323
 
308
324
  ### Storage backends
309
325
 
310
- Three built-in stores are available:
326
+ Three built-in stores are available. All implement the full `SessionStore` interface including incremental operations.
311
327
 
312
328
  ```ts
313
329
  import { createMemoryStore, createSqliteStore, createRemoteStore } from 'zidane/session'
@@ -322,6 +338,38 @@ const sqliteStore = createSqliteStore({ path: './sessions.db' })
322
338
  const remoteStore = createRemoteStore({ url: 'https://api.example.com/sessions' })
323
339
  ```
324
340
 
341
+ ### SessionStore interface
342
+
343
+ ```ts
344
+ interface SessionStore {
345
+ // Optional: server-side ID generation
346
+ generateSessionId?: () => string | Promise<string>
347
+ generateTurnId?: () => string | Promise<string>
348
+
349
+ // Core CRUD
350
+ load: (sessionId: string) => Promise<SessionData | null>
351
+ save: (session: SessionData) => Promise<void>
352
+ delete: (sessionId: string) => Promise<void>
353
+ list: (filter?) => Promise<string[]>
354
+
355
+ // Incremental operations (avoids full re-save)
356
+ appendTurns: (sessionId: string, turns: SessionTurn[]) => Promise<void>
357
+ getTurns: (sessionId: string, from?: number, limit?: number) => Promise<SessionTurn[]>
358
+ updateRun: (sessionId: string, run: SessionRun) => Promise<void>
359
+ updateStatus: (sessionId: string, status: SessionStatus) => Promise<void>
360
+ }
361
+ ```
362
+
363
+ Custom ID generation lets external databases (e.g. Supabase) provide UUIDs server-side, keeping IDs in sync:
364
+
365
+ ```ts
366
+ const store = createRemoteStore({ url: '...' })
367
+ store.generateTurnId = async () => {
368
+ const { data } = await supabase.rpc('gen_random_uuid')
369
+ return data
370
+ }
371
+ ```
372
+
325
373
  ### Agent integration
326
374
 
327
375
  ```ts
@@ -335,6 +383,18 @@ await agent.run({ prompt: 'hello' })
335
383
  await session.save() // persist to store
336
384
  ```
337
385
 
386
+ Turns are persisted incrementally after each agent turn via `appendTurns` — not as a full document save. If the agent crashes mid-run, you still have turns up to the last completed turn.
387
+
388
+ ### Session status
389
+
390
+ Sessions track their status: `'idle' | 'running' | 'completed' | 'error'`. The agent updates it automatically during runs.
391
+
392
+ ```ts
393
+ session.status // 'idle'
394
+ await agent.run({ prompt: 'go' })
395
+ // idle → running → completed (or error)
396
+ ```
397
+
338
398
  ### Session hooks
339
399
 
340
400
  ```ts
@@ -347,9 +407,9 @@ agent.hooks.hook('session:end', (ctx) => {
347
407
  // ctx.status: 'completed' | 'aborted' | 'error'
348
408
  })
349
409
 
350
- agent.hooks.hook('session:messages', (ctx) => {
410
+ agent.hooks.hook('session:turns', (ctx) => {
351
411
  // ctx.sessionId, ctx.count
352
- // fired after each turn (live message sync)
412
+ // fired after each turn (incremental sync)
353
413
  })
354
414
 
355
415
  agent.hooks.hook('session:save', (ctx) => {
@@ -363,8 +423,6 @@ agent.hooks.hook('session:meta', (ctx) => {
363
423
  })
364
424
  ```
365
425
 
366
- Messages are synced to the session after every turn, not just at run start/end. If the agent crashes mid-run, you still have messages up to the last completed turn.
367
-
368
426
  ### Restoring a session
369
427
 
370
428
  ```ts
@@ -390,11 +448,12 @@ agent.hooks.hook('system:before', (ctx) => {
390
448
 
391
449
  agent.hooks.hook('turn:before', (ctx) => {
392
450
  // ctx.turn: turn number
451
+ // ctx.turnId: UUID for this turn (generated before LLM call)
393
452
  // ctx.options: StreamOptions being sent to provider
394
453
  })
395
454
 
396
455
  agent.hooks.hook('turn:after', (ctx) => {
397
- // ctx.turn, ctx.usage { input, output }
456
+ // ctx.turn, ctx.turnId, ctx.usage { input, output }
398
457
  })
399
458
 
400
459
  agent.hooks.hook('agent:done', (ctx) => {
@@ -412,10 +471,13 @@ agent.hooks.hook('agent:abort', () => {
412
471
  agent.hooks.hook('stream:text', (ctx) => {
413
472
  // ctx.delta: new text chunk
414
473
  // ctx.text: accumulated text so far
474
+ // ctx.turnId: UUID of the turn being streamed
475
+ // ctx.blockIndex: content block index within the turn
415
476
  })
416
477
 
417
478
  agent.hooks.hook('stream:end', (ctx) => {
418
479
  // ctx.text: final complete text
480
+ // ctx.turnId, ctx.blockIndex
419
481
  })
420
482
  ```
421
483
 
@@ -1,6 +1,6 @@
1
1
  import { Hookable } from 'hookable';
2
2
  import Anthropic from '@anthropic-ai/sdk';
3
- import { M as McpServerConfig, d as TurnUsage, b as SessionMessage, C as ChildRunStats, a as AgentStats, A as AgentRunOptions, c as ToolExecutionMode } from './types-4CFQ-6Qu.js';
3
+ import { M as McpServerConfig, e as TurnUsage, b as SessionMessage, C as ChildRunStats, a as AgentStats, A as AgentRunOptions, c as SessionTurn, d as ToolExecutionMode } from './types-CLRMCak3.js';
4
4
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
5
5
  import { Provider, StreamOptions } from './providers.js';
6
6
  import { Session } from './session.js';
@@ -168,18 +168,24 @@ interface AgentHooks {
168
168
  }) => void;
169
169
  'turn:before': (ctx: {
170
170
  turn: number;
171
+ turnId: string;
171
172
  options: StreamOptions;
172
173
  }) => void;
173
174
  'turn:after': (ctx: {
174
175
  turn: number;
176
+ turnId: string;
175
177
  usage: TurnUsage;
176
178
  }) => void;
177
179
  'stream:text': (ctx: {
178
180
  delta: string;
179
181
  text: string;
182
+ turnId: string;
183
+ blockIndex: number;
180
184
  }) => void;
181
185
  'stream:end': (ctx: {
182
186
  text: string;
187
+ turnId: string;
188
+ blockIndex: number;
183
189
  }) => void;
184
190
  'tool:before': (ctx: {
185
191
  name: string;
@@ -264,7 +270,7 @@ interface AgentHooks {
264
270
  runId: string;
265
271
  status: 'completed' | 'aborted' | 'error';
266
272
  }) => void;
267
- 'session:messages': (ctx: {
273
+ 'session:turns': (ctx: {
268
274
  sessionId: string;
269
275
  count: number;
270
276
  }) => void;
@@ -286,7 +292,7 @@ interface AgentOptions {
286
292
  execution?: ExecutionContext;
287
293
  /** MCP servers to connect and expose as tools */
288
294
  mcpServers?: McpServerConfig[];
289
- /** Session for identity, message persistence, and run tracking */
295
+ /** Session for identity, turn persistence, and run tracking */
290
296
  session?: Session;
291
297
  /** @internal */
292
298
  _mcpConnector?: (configs: McpServerConfig[]) => Promise<McpConnection>;
@@ -302,7 +308,7 @@ interface Agent {
302
308
  /** Destroy the execution context and clean up resources */
303
309
  destroy: () => Promise<void>;
304
310
  readonly isRunning: boolean;
305
- readonly messages: SessionMessage[];
311
+ readonly turns: SessionTurn[];
306
312
  readonly execution: ExecutionContext;
307
313
  readonly handle: ExecutionHandle | null;
308
314
  readonly session: Session | null;
@@ -21,6 +21,37 @@ function createMemoryStore() {
21
21
  ids = ids.slice(0, filter.limit);
22
22
  }
23
23
  return ids;
24
+ },
25
+ async appendTurns(sessionId, turns) {
26
+ const data = sessions.get(sessionId);
27
+ if (data) {
28
+ data.turns.push(...JSON.parse(JSON.stringify(turns)));
29
+ data.updatedAt = Date.now();
30
+ }
31
+ },
32
+ async getTurns(sessionId, from = 0, limit) {
33
+ const data = sessions.get(sessionId);
34
+ if (!data)
35
+ return [];
36
+ const sliced = data.turns.slice(from, limit !== void 0 ? from + limit : void 0);
37
+ return JSON.parse(JSON.stringify(sliced));
38
+ },
39
+ async updateRun(sessionId, run) {
40
+ const data = sessions.get(sessionId);
41
+ if (data) {
42
+ const idx = data.runs.findIndex((r) => r.id === run.id);
43
+ if (idx >= 0) {
44
+ data.runs[idx] = JSON.parse(JSON.stringify(run));
45
+ }
46
+ data.updatedAt = Date.now();
47
+ }
48
+ },
49
+ async updateStatus(sessionId, status) {
50
+ const data = sessions.get(sessionId);
51
+ if (data) {
52
+ data.status = status;
53
+ data.updatedAt = Date.now();
54
+ }
24
55
  }
25
56
  };
26
57
  }
@@ -82,6 +113,50 @@ function createRemoteStore(options) {
82
113
  }
83
114
  const body = await res.json();
84
115
  return body.ids;
116
+ },
117
+ async appendTurns(sessionId, turns) {
118
+ const res = await request(`/sessions/${encodeURIComponent(sessionId)}/turns`, {
119
+ method: "POST",
120
+ body: JSON.stringify(turns)
121
+ });
122
+ if (!res.ok) {
123
+ throw new Error(`Remote appendTurns failed: ${res.status} ${res.statusText}`);
124
+ }
125
+ },
126
+ async getTurns(sessionId, from = 0, limit) {
127
+ const params = new URLSearchParams();
128
+ if (from)
129
+ params.set("from", String(from));
130
+ if (limit !== void 0)
131
+ params.set("limit", String(limit));
132
+ const query = params.toString();
133
+ const path = `/sessions/${encodeURIComponent(sessionId)}/turns${query ? `?${query}` : ""}`;
134
+ const res = await request(path);
135
+ if (!res.ok) {
136
+ throw new Error(`Remote getTurns failed: ${res.status} ${res.statusText}`);
137
+ }
138
+ return await res.json();
139
+ },
140
+ async updateRun(sessionId, run) {
141
+ const res = await request(
142
+ `/sessions/${encodeURIComponent(sessionId)}/runs/${encodeURIComponent(run.id)}`,
143
+ {
144
+ method: "PUT",
145
+ body: JSON.stringify(run)
146
+ }
147
+ );
148
+ if (!res.ok) {
149
+ throw new Error(`Remote updateRun failed: ${res.status} ${res.statusText}`);
150
+ }
151
+ },
152
+ async updateStatus(sessionId, status) {
153
+ const res = await request(`/sessions/${encodeURIComponent(sessionId)}`, {
154
+ method: "PATCH",
155
+ body: JSON.stringify({ status })
156
+ });
157
+ if (!res.ok) {
158
+ throw new Error(`Remote updateStatus failed: ${res.status} ${res.statusText}`);
159
+ }
85
160
  }
86
161
  };
87
162
  }
@@ -113,7 +188,7 @@ function createSqliteStore(options) {
113
188
  const stmtDelete = db.prepare("DELETE FROM sessions WHERE id = ?");
114
189
  const stmtList = db.prepare("SELECT id FROM sessions ORDER BY updated_at DESC");
115
190
  const stmtListByAgent = db.prepare("SELECT id FROM sessions WHERE agent_id = ? ORDER BY updated_at DESC");
116
- return {
191
+ const store = {
117
192
  async load(sessionId) {
118
193
  const row = stmtLoad.get(sessionId);
119
194
  if (!row)
@@ -144,19 +219,61 @@ function createSqliteStore(options) {
144
219
  return ids.slice(0, filter.limit);
145
220
  }
146
221
  return ids;
222
+ },
223
+ async appendTurns(sessionId, turns) {
224
+ const data = await store.load(sessionId);
225
+ if (data) {
226
+ data.turns.push(...turns);
227
+ data.updatedAt = Date.now();
228
+ await store.save(data);
229
+ }
230
+ },
231
+ async getTurns(sessionId, from = 0, limit) {
232
+ const data = await store.load(sessionId);
233
+ if (!data)
234
+ return [];
235
+ return data.turns.slice(from, limit !== void 0 ? from + limit : void 0);
236
+ },
237
+ async updateRun(sessionId, run) {
238
+ const data = await store.load(sessionId);
239
+ if (data) {
240
+ const idx = data.runs.findIndex((r) => r.id === run.id);
241
+ if (idx >= 0) {
242
+ data.runs[idx] = run;
243
+ }
244
+ data.updatedAt = Date.now();
245
+ await store.save(data);
246
+ }
247
+ },
248
+ async updateStatus(sessionId, status) {
249
+ const data = await store.load(sessionId);
250
+ if (data) {
251
+ data.status = status;
252
+ data.updatedAt = Date.now();
253
+ await store.save(data);
254
+ }
147
255
  }
148
256
  };
257
+ return store;
149
258
  }
150
259
 
151
260
  // src/session/index.ts
152
- function createSession(options = {}) {
261
+ async function createSession(options = {}) {
153
262
  const store = options.store;
154
263
  const now = Date.now();
264
+ let sessionId = options.id;
265
+ if (!sessionId && store?.generateSessionId) {
266
+ sessionId = await store.generateSessionId();
267
+ }
268
+ if (!sessionId) {
269
+ sessionId = generateId();
270
+ }
155
271
  const data = options._data ?? {
156
- id: options.id ?? generateId(),
272
+ id: sessionId,
157
273
  agentId: options.agentId,
158
- messages: [],
274
+ turns: [],
159
275
  runs: [],
276
+ status: "idle",
160
277
  metadata: options.metadata ?? {},
161
278
  createdAt: now,
162
279
  updatedAt: now
@@ -167,15 +284,18 @@ function createSession(options = {}) {
167
284
  function findRun(runId) {
168
285
  return data.runs.find((r) => r.id === runId);
169
286
  }
170
- return {
287
+ const session = {
171
288
  get id() {
172
289
  return data.id;
173
290
  },
174
291
  get agentId() {
175
292
  return data.agentId;
176
293
  },
177
- get messages() {
178
- return data.messages;
294
+ get turns() {
295
+ return data.turns;
296
+ },
297
+ get status() {
298
+ return data.status;
179
299
  },
180
300
  get runs() {
181
301
  return data.runs;
@@ -232,14 +352,35 @@ function createSession(options = {}) {
232
352
  }
233
353
  touch();
234
354
  },
235
- pushMessages(messages) {
236
- data.messages.push(...messages);
355
+ async appendTurns(turns) {
356
+ data.turns.push(...turns);
237
357
  touch();
358
+ if (store) {
359
+ await store.appendTurns(data.id, turns);
360
+ }
238
361
  },
239
- setMessages(messages) {
240
- data.messages = messages;
362
+ setTurns(turns) {
363
+ data.turns = turns;
241
364
  touch();
242
365
  },
366
+ async updateStatus(status) {
367
+ data.status = status;
368
+ touch();
369
+ if (store) {
370
+ await store.updateStatus(data.id, status);
371
+ }
372
+ },
373
+ async updateRun(run) {
374
+ if (store) {
375
+ await store.updateRun(data.id, run);
376
+ }
377
+ },
378
+ generateTurnId() {
379
+ if (store?.generateTurnId) {
380
+ return store.generateTurnId();
381
+ }
382
+ return crypto.randomUUID();
383
+ },
243
384
  setMeta(key, value) {
244
385
  data.metadata[key] = value;
245
386
  touch();
@@ -254,6 +395,7 @@ function createSession(options = {}) {
254
395
  return JSON.parse(JSON.stringify(data));
255
396
  }
256
397
  };
398
+ return session;
257
399
  }
258
400
  async function loadSession(store, sessionId) {
259
401
  const loaded = await store.load(sessionId);
@@ -5,7 +5,7 @@ import {
5
5
  shell,
6
6
  spawn_exports,
7
7
  writeFile
8
- } from "./chunk-27EP7HB3.js";
8
+ } from "./chunk-SWS5624X.js";
9
9
  import {
10
10
  __toCommonJS
11
11
  } from "./chunk-PNKVD2UK.js";
@@ -287,6 +287,9 @@ var init_validation = __esm({
287
287
  });
288
288
 
289
289
  // src/loop.ts
290
+ function turnsToMessages(turns) {
291
+ return turns.map((t) => ({ role: t.role, content: t.content }));
292
+ }
290
293
  async function runLoop(ctx) {
291
294
  let totalIn = 0;
292
295
  let totalOut = 0;
@@ -309,14 +312,26 @@ async function runLoop(ctx) {
309
312
  if (ctx.steeringQueue.length > 0) {
310
313
  const steerMsg = ctx.steeringQueue.shift();
311
314
  await ctx.hooks.callHook("steer:inject", { message: steerMsg });
312
- ctx.messages.push(ctx.provider.userMessage(steerMsg));
315
+ const steerUserMsg = ctx.provider.userMessage(steerMsg);
316
+ ctx.turns.push({
317
+ id: await ctx.generateTurnId(),
318
+ role: steerUserMsg.role,
319
+ content: steerUserMsg.content,
320
+ createdAt: Date.now()
321
+ });
313
322
  continue;
314
323
  }
315
324
  if (result.ended) {
316
325
  if (ctx.followUpQueue.length > 0) {
317
326
  const followUp = ctx.followUpQueue.shift();
318
327
  await ctx.hooks.callHook("steer:inject", { message: followUp });
319
- ctx.messages.push(ctx.provider.userMessage(followUp));
328
+ const followUpMsg = ctx.provider.userMessage(followUp);
329
+ ctx.turns.push({
330
+ id: await ctx.generateTurnId(),
331
+ role: followUpMsg.role,
332
+ content: followUpMsg.content,
333
+ createdAt: Date.now()
334
+ });
320
335
  continue;
321
336
  }
322
337
  return { totalIn, totalOut, turns: turn + 1, elapsed: Date.now() - startTime, turnUsage: turnUsages };
@@ -327,37 +342,59 @@ async function runLoop(ctx) {
327
342
  return stats;
328
343
  }
329
344
  async function executeTurn(ctx, turn) {
345
+ const turnId = await ctx.generateTurnId();
346
+ const messages = turnsToMessages(ctx.turns);
330
347
  const streamOptions = {
331
348
  model: ctx.model,
332
349
  system: ctx.system,
333
350
  tools: ctx.formattedTools,
334
- messages: ctx.messages,
351
+ messages,
335
352
  maxTokens: 16384,
336
353
  thinking: ctx.thinking,
337
354
  signal: ctx.signal
338
355
  };
339
- await ctx.hooks.callHook("context:transform", { messages: ctx.messages });
340
- await ctx.hooks.callHook("turn:before", { turn, options: streamOptions });
356
+ await ctx.hooks.callHook("context:transform", { messages });
357
+ await ctx.hooks.callHook("turn:before", { turn, turnId, options: streamOptions });
341
358
  let currentText = "";
359
+ const blockIndex = 0;
342
360
  const result = await ctx.provider.stream(
343
361
  streamOptions,
344
362
  {
345
363
  onText(delta) {
346
364
  currentText += delta;
347
- ctx.hooks.callHook("stream:text", { delta, text: currentText });
365
+ ctx.hooks.callHook("stream:text", { delta, text: currentText, turnId, blockIndex });
348
366
  }
349
367
  }
350
368
  );
351
369
  if (currentText) {
352
- await ctx.hooks.callHook("stream:end", { text: currentText });
370
+ await ctx.hooks.callHook("stream:end", { text: currentText, turnId, blockIndex });
353
371
  }
354
- await ctx.hooks.callHook("turn:after", { turn, usage: result.usage });
372
+ await ctx.hooks.callHook("turn:after", { turn, turnId, usage: result.usage });
355
373
  if (result.done) {
374
+ ctx.turns.push({
375
+ id: turnId,
376
+ role: "assistant",
377
+ content: result.assistantMessage?.content ?? [{ type: "text", text: currentText }],
378
+ usage: result.usage,
379
+ createdAt: Date.now()
380
+ });
356
381
  return { ended: true, usage: result.usage };
357
382
  }
358
- ctx.messages.push(result.assistantMessage);
383
+ ctx.turns.push({
384
+ id: turnId,
385
+ role: "assistant",
386
+ content: result.assistantMessage.content,
387
+ usage: result.usage,
388
+ createdAt: Date.now()
389
+ });
359
390
  const toolResults = ctx.toolExecution === "parallel" ? await executeToolsParallel(ctx, result.toolCalls) : await executeToolsSequential(ctx, result.toolCalls);
360
- ctx.messages.push(ctx.provider.toolResultsMessage(toolResults));
391
+ const toolResultMsg = ctx.provider.toolResultsMessage(toolResults);
392
+ ctx.turns.push({
393
+ id: await ctx.generateTurnId(),
394
+ role: toolResultMsg.role,
395
+ content: toolResultMsg.content,
396
+ createdAt: Date.now()
397
+ });
361
398
  return { ended: false, usage: result.usage };
362
399
  }
363
400
  async function executeSingleTool(ctx, call) {
@@ -412,8 +449,20 @@ async function executeToolsSequential(ctx, toolCalls) {
412
449
  for (const skipped of toolCalls.slice(toolCalls.indexOf(call))) {
413
450
  results.push({ id: skipped.id, content: "Skipped: steering message received" });
414
451
  }
415
- ctx.messages.push(ctx.provider.toolResultsMessage(results));
416
- ctx.messages.push(ctx.provider.userMessage(steerMsg));
452
+ const toolResultMsg = ctx.provider.toolResultsMessage(results);
453
+ ctx.turns.push({
454
+ id: await ctx.generateTurnId(),
455
+ role: toolResultMsg.role,
456
+ content: toolResultMsg.content,
457
+ createdAt: Date.now()
458
+ });
459
+ const steerUserMsg = ctx.provider.userMessage(steerMsg);
460
+ ctx.turns.push({
461
+ id: await ctx.generateTurnId(),
462
+ role: steerUserMsg.role,
463
+ content: steerUserMsg.content,
464
+ createdAt: Date.now()
465
+ });
417
466
  return [];
418
467
  }
419
468
  const { result } = await executeSingleTool(ctx, call);
@@ -447,8 +496,8 @@ function createAgent({ harness, provider, toolExecution = "sequential", executio
447
496
  const allMcpServers = [...harness.mcpServers ?? [], ...mcpServers ?? []];
448
497
  const steeringQueue = [];
449
498
  const followUpQueue = [];
450
- let conversationMessages = session?.messages ?? [];
451
- let runCounter = 0;
499
+ let conversationTurns = session?.turns.slice() ?? [];
500
+ let runCounter = session?.runs.length ?? 0;
452
501
  async function run(options) {
453
502
  if (running) {
454
503
  throw new Error("Agent is already running. Use steer() or followUp() to queue messages, or waitForIdle().");
@@ -457,8 +506,10 @@ function createAgent({ harness, provider, toolExecution = "sequential", executio
457
506
  abortController = new AbortController();
458
507
  const runId = `run_${++runCounter}`;
459
508
  session?.startRun(runId, options.prompt);
460
- if (session)
509
+ if (session) {
510
+ await session.updateStatus("running");
461
511
  await hooks.callHook("session:start", { sessionId: session.id, runId, prompt: options.prompt });
512
+ }
462
513
  if (options.signal) {
463
514
  if (options.signal.aborted) {
464
515
  abortController.abort();
@@ -496,18 +547,44 @@ function createAgent({ harness, provider, toolExecution = "sequential", executio
496
547
  })
497
548
  );
498
549
  const formattedTools = provider.formatTools(toolSpecs);
499
- const messages = [];
550
+ const turns = [];
551
+ const isResume = session && session.turns.length > 0 && session.runs.length > 0;
552
+ if (isResume) {
553
+ turns.push(...session.turns);
554
+ }
500
555
  if (options.system) {
501
556
  await hooks.callHook("system:before", { system: options.system });
502
- messages.push(provider.userMessage(options.system));
503
- messages.push(provider.assistantMessage("Understood. I will proceed with these instructions above the rest of my system prompt."));
557
+ const systemUserMsg = provider.userMessage(options.system);
558
+ turns.push({
559
+ id: crypto.randomUUID(),
560
+ role: systemUserMsg.role,
561
+ content: systemUserMsg.content,
562
+ createdAt: Date.now()
563
+ });
564
+ const systemAckMsg = provider.assistantMessage("Understood. I will proceed with these instructions above the rest of my system prompt.");
565
+ turns.push({
566
+ id: crypto.randomUUID(),
567
+ role: systemAckMsg.role,
568
+ content: systemAckMsg.content,
569
+ createdAt: Date.now()
570
+ });
504
571
  }
505
- messages.push(provider.userMessage(options.prompt, options.images));
506
- conversationMessages = messages;
507
- session?.setMessages(messages);
508
- const unregisterSessionSync = session ? hooks.hook("turn:after", () => {
509
- session.setMessages(messages);
510
- hooks.callHook("session:messages", { sessionId: session.id, count: messages.length });
572
+ const promptMsg = provider.userMessage(options.prompt, options.images);
573
+ turns.push({
574
+ id: crypto.randomUUID(),
575
+ role: promptMsg.role,
576
+ content: promptMsg.content,
577
+ createdAt: Date.now()
578
+ });
579
+ conversationTurns = turns;
580
+ let lastPersistedTurnCount = isResume ? session.turns.length : 0;
581
+ const unregisterSessionSync = session ? hooks.hook("turn:after", async () => {
582
+ const newTurns = turns.slice(lastPersistedTurnCount);
583
+ if (newTurns.length > 0) {
584
+ await session.appendTurns(newTurns);
585
+ lastPersistedTurnCount = turns.length;
586
+ hooks.callHook("session:turns", { sessionId: session.id, count: turns.length });
587
+ }
511
588
  }) : void 0;
512
589
  try {
513
590
  const stats = await runLoop({
@@ -526,7 +603,8 @@ function createAgent({ harness, provider, toolExecution = "sequential", executio
526
603
  handle: executionHandle,
527
604
  steeringQueue,
528
605
  followUpQueue,
529
- messages
606
+ turns,
607
+ generateTurnId: () => session?.generateTurnId() ?? crypto.randomUUID()
530
608
  });
531
609
  const finalStats = {
532
610
  ...stats,
@@ -534,15 +612,24 @@ function createAgent({ harness, provider, toolExecution = "sequential", executio
534
612
  };
535
613
  if (abortController.signal.aborted) {
536
614
  session?.abortRun(runId);
537
- if (session)
615
+ if (session) {
616
+ const run2 = session.runs.find((r) => r.id === runId);
617
+ if (run2)
618
+ await session.updateRun(run2);
619
+ await session.updateStatus("idle");
538
620
  await hooks.callHook("session:end", { sessionId: session.id, runId, status: "aborted" });
621
+ }
539
622
  await hooks.callHook("agent:done", finalStats);
540
623
  return finalStats;
541
624
  }
542
625
  const totalCost = finalStats.turnUsage?.reduce((sum, t) => sum + (t.cost ?? 0), 0) || void 0;
543
626
  if (totalCost)
544
627
  finalStats.cost = totalCost;
545
- session?.setMessages(messages);
628
+ const finalNewTurns = turns.slice(lastPersistedTurnCount);
629
+ if (session && finalNewTurns.length > 0) {
630
+ await session.appendTurns(finalNewTurns);
631
+ lastPersistedTurnCount = turns.length;
632
+ }
546
633
  session?.completeRun(runId, {
547
634
  turns: finalStats.turns,
548
635
  tokensIn: finalStats.totalIn,
@@ -550,22 +637,37 @@ function createAgent({ harness, provider, toolExecution = "sequential", executio
550
637
  turnUsage: finalStats.turnUsage,
551
638
  cost: totalCost
552
639
  });
553
- if (session)
640
+ if (session) {
641
+ const run2 = session.runs.find((r) => r.id === runId);
642
+ if (run2)
643
+ await session.updateRun(run2);
644
+ await session.updateStatus("completed");
554
645
  await hooks.callHook("session:end", { sessionId: session.id, runId, status: "completed" });
646
+ }
555
647
  await hooks.callHook("agent:done", finalStats);
556
648
  return finalStats;
557
649
  } catch (err) {
558
650
  if (abortController.signal.aborted) {
559
651
  session?.abortRun(runId);
560
- if (session)
652
+ if (session) {
653
+ const run2 = session.runs.find((r) => r.id === runId);
654
+ if (run2)
655
+ await session.updateRun(run2);
656
+ await session.updateStatus("idle");
561
657
  await hooks.callHook("session:end", { sessionId: session.id, runId, status: "aborted" });
658
+ }
562
659
  const stats = { totalIn: 0, totalOut: 0, turns: 0, elapsed: 0 };
563
660
  await hooks.callHook("agent:done", stats);
564
661
  return stats;
565
662
  }
566
663
  session?.errorRun(runId, err.message);
567
- if (session)
664
+ if (session) {
665
+ const run2 = session.runs.find((r) => r.id === runId);
666
+ if (run2)
667
+ await session.updateRun(run2);
668
+ await session.updateStatus("error");
568
669
  await hooks.callHook("session:end", { sessionId: session.id, runId, status: "error" });
670
+ }
569
671
  throw err;
570
672
  } finally {
571
673
  unregisterSpawnHook();
@@ -592,7 +694,7 @@ function createAgent({ harness, provider, toolExecution = "sequential", executio
592
694
  return idlePromise ?? Promise.resolve();
593
695
  }
594
696
  function reset() {
595
- conversationMessages = [];
697
+ conversationTurns = [];
596
698
  steeringQueue.length = 0;
597
699
  followUpQueue.length = 0;
598
700
  }
@@ -630,8 +732,8 @@ function createAgent({ harness, provider, toolExecution = "sequential", executio
630
732
  get isRunning() {
631
733
  return running;
632
734
  },
633
- get messages() {
634
- return conversationMessages;
735
+ get turns() {
736
+ return conversationTurns;
635
737
  },
636
738
  get execution() {
637
739
  return executionContext;
@@ -731,7 +833,7 @@ function createSpawnTool(options = {}) {
731
833
  task,
732
834
  stats
733
835
  });
734
- const response = extractText(agent.messages.at(-1));
836
+ const response = extractText(agent.turns.at(-1));
735
837
  return [
736
838
  `[sub-agent ${id}] Completed in ${stats.turns} turns (${stats.elapsed}ms)`,
737
839
  `Tokens: ${stats.totalIn} in / ${stats.totalOut} out`,
@@ -831,7 +933,7 @@ var init_spawn = __esm({
831
933
  task,
832
934
  stats
833
935
  });
834
- const response = extractText(agent.messages.at(-1));
936
+ const response = extractText(agent.turns.at(-1));
835
937
  return [
836
938
  `[sub-agent ${id}] Completed in ${stats.turns} turns (${stats.elapsed}ms)`,
837
939
  `Tokens: ${stats.totalIn} in / ${stats.totalOut} out`,
@@ -1,7 +1,7 @@
1
1
  import '@anthropic-ai/sdk';
2
2
  import 'hookable';
3
- export { H as Harness, f as HarnessConfig, T as ToolContext, g as ToolDef, h as ToolMap, _ as basic, l as basicTools, k as defineHarness } from './agent-DvZm8U14.js';
3
+ export { H as Harness, f as HarnessConfig, T as ToolContext, g as ToolDef, h as ToolMap, _ as basic, l as basicTools, k as defineHarness } from './agent-DxIUxou4.js';
4
4
  import './providers.js';
5
- import './types-4CFQ-6Qu.js';
5
+ import './types-CLRMCak3.js';
6
6
  import '@modelcontextprotocol/sdk/client/index.js';
7
7
  import './session.js';
package/dist/harnesses.js CHANGED
@@ -2,8 +2,8 @@ import {
2
2
  basicTools,
3
3
  basic_default,
4
4
  defineHarness
5
- } from "./chunk-34KXKPNN.js";
6
- import "./chunk-27EP7HB3.js";
5
+ } from "./chunk-N523NBO2.js";
6
+ import "./chunk-SWS5624X.js";
7
7
  import "./chunk-26LIQARN.js";
8
8
  import "./chunk-PNKVD2UK.js";
9
9
  export {
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { S as SpawnConfig, E as ExecutionContext, a as ExecResult } from './agent-DvZm8U14.js';
2
- export { A as Agent, b as AgentHooks, c as AgentOptions, C as ContextCapabilities, d as ContextType, e as ExecutionHandle, H as Harness, f as HarnessConfig, M as McpConnection, T as ToolContext, g as ToolDef, h as ToolMap, i as connectMcpServers, j as createAgent, k as defineHarness } from './agent-DvZm8U14.js';
1
+ import { S as SpawnConfig, E as ExecutionContext, a as ExecResult } from './agent-DxIUxou4.js';
2
+ export { A as Agent, b as AgentHooks, c as AgentOptions, C as ContextCapabilities, d as ContextType, e as ExecutionHandle, H as Harness, f as HarnessConfig, M as McpConnection, T as ToolContext, g as ToolDef, h as ToolMap, i as connectMcpServers, j as createAgent, k as defineHarness } from './agent-DxIUxou4.js';
3
3
  export { CreateSessionOptions, RemoteStoreOptions, Session, SessionData, SessionRun, SessionStore, SqliteStoreOptions, autoDetectAndConvert, createMemoryStore, createRemoteStore, createSession, createSqliteStore, fromAnthropic, fromOpenAI, loadSession, toAnthropic, toOpenAI } from './session.js';
4
- export { C as ChildAgent, S as SpawnToolOptions, a as SpawnToolState, c as createSpawnTool, s as spawn } from './spawn-pP2grsVp.js';
5
- export { A as AgentRunOptions, a as AgentStats, I as ImageContent, M as McpServerConfig, S as SessionContentBlock, b as SessionMessage, T as ThinkingLevel, c as ToolExecutionMode, d as TurnUsage } from './types-4CFQ-6Qu.js';
4
+ export { C as ChildAgent, S as SpawnToolOptions, a as SpawnToolState, c as createSpawnTool, s as spawn } from './spawn-bEqlGUVT.js';
5
+ export { A as AgentRunOptions, a as AgentStats, I as ImageContent, M as McpServerConfig, S as SessionContentBlock, b as SessionMessage, c as SessionTurn, T as ThinkingLevel, d as ToolExecutionMode, e as TurnUsage } from './types-CLRMCak3.js';
6
6
  import 'hookable';
7
7
  import '@anthropic-ai/sdk';
8
8
  import '@modelcontextprotocol/sdk/client/index.js';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  defineHarness
3
- } from "./chunk-34KXKPNN.js";
3
+ } from "./chunk-N523NBO2.js";
4
4
  import {
5
5
  createAgent,
6
6
  createDockerContext,
@@ -10,7 +10,7 @@ import {
10
10
  init_agent,
11
11
  init_contexts,
12
12
  spawn
13
- } from "./chunk-27EP7HB3.js";
13
+ } from "./chunk-SWS5624X.js";
14
14
  import {
15
15
  connectMcpServers,
16
16
  init_mcp
@@ -21,7 +21,7 @@ import {
21
21
  createSession,
22
22
  createSqliteStore,
23
23
  loadSession
24
- } from "./chunk-LMSOIIAT.js";
24
+ } from "./chunk-IC2WAUBZ.js";
25
25
  import {
26
26
  autoDetectAndConvert,
27
27
  fromAnthropic,
package/dist/mcp.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import 'hookable';
2
- export { M as McpConnection, i as connectMcpServers, r as resultToString } from './agent-DvZm8U14.js';
3
- export { M as McpServerConfig } from './types-4CFQ-6Qu.js';
2
+ export { M as McpConnection, i as connectMcpServers, r as resultToString } from './agent-DxIUxou4.js';
3
+ export { M as McpServerConfig } from './types-CLRMCak3.js';
4
4
  import '@modelcontextprotocol/sdk/client/index.js';
5
5
  import '@anthropic-ai/sdk';
6
6
  import './providers.js';
@@ -1,4 +1,4 @@
1
- import { b as SessionMessage, T as ThinkingLevel, I as ImageContent, d as TurnUsage } from './types-4CFQ-6Qu.js';
1
+ import { b as SessionMessage, T as ThinkingLevel, I as ImageContent, e as TurnUsage } from './types-CLRMCak3.js';
2
2
 
3
3
  declare function anthropic(): Provider;
4
4
 
package/dist/session.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { b as SessionMessage, d as TurnUsage } from './types-4CFQ-6Qu.js';
2
- export { S as SessionContentBlock } from './types-4CFQ-6Qu.js';
1
+ import { b as SessionMessage, c as SessionTurn, e as TurnUsage } from './types-CLRMCak3.js';
2
+ export { S as SessionContentBlock } from './types-CLRMCak3.js';
3
3
 
4
4
  /**
5
5
  * In-memory session store.
@@ -37,10 +37,14 @@ declare function autoDetectAndConvert(msg: {
37
37
  * Remote session store via HTTP API.
38
38
  *
39
39
  * Expects a REST API with:
40
- * GET {url}/sessions/{id} -> SessionData | 404
41
- * PUT {url}/sessions/{id} -> save SessionData
42
- * DELETE {url}/sessions/{id} -> delete
43
- * GET {url}/sessions?agentId=&limit= -> { ids: string[] }
40
+ * GET {url}/sessions/{id} -> SessionData | 404
41
+ * PUT {url}/sessions/{id} -> save SessionData
42
+ * DELETE {url}/sessions/{id} -> delete
43
+ * GET {url}/sessions?agentId=&limit= -> { ids: string[] }
44
+ * POST {url}/sessions/{id}/turns -> append turns
45
+ * GET {url}/sessions/{id}/turns?from=&limit= -> SessionTurn[]
46
+ * PUT {url}/sessions/{id}/runs/{runId} -> update run
47
+ * PATCH {url}/sessions/{id} -> { status }
44
48
  */
45
49
 
46
50
  interface RemoteStoreOptions {
@@ -64,7 +68,7 @@ declare function createSqliteStore(options: SqliteStoreOptions): SessionStore;
64
68
  /**
65
69
  * Session management for agents.
66
70
  *
67
- * A session tracks identity, message history, and run metadata.
71
+ * A session tracks identity, turn history, and run metadata.
68
72
  * Plug in any storage backend by implementing the SessionStore interface,
69
73
  * or use one of the built-in stores: memory, sqlite, remote.
70
74
  */
@@ -89,32 +93,47 @@ interface SessionRun {
89
93
  interface SessionData {
90
94
  id: string;
91
95
  agentId?: string;
92
- messages: SessionMessage[];
96
+ turns: SessionTurn[];
93
97
  runs: SessionRun[];
98
+ status: 'idle' | 'running' | 'completed' | 'error';
94
99
  metadata: Record<string, unknown>;
95
100
  createdAt: number;
96
101
  updatedAt: number;
97
102
  }
98
103
  interface SessionStore {
104
+ /** Optional: generate a session ID server-side (e.g. Supabase UUID). */
105
+ generateSessionId?: () => string | Promise<string>;
106
+ /** Optional: generate a turn ID server-side. */
107
+ generateTurnId?: () => string | Promise<string>;
99
108
  /** Load a session by ID. Returns null if not found. */
100
109
  load: (sessionId: string) => Promise<SessionData | null>;
101
- /** Save a session (create or update). */
110
+ /** Save a session (create or update, full document). */
102
111
  save: (session: SessionData) => Promise<void>;
103
112
  /** Delete a session. */
104
113
  delete: (sessionId: string) => Promise<void>;
105
- /** List session IDs, optionally filtered by agentId. */
114
+ /** List session IDs, optionally filtered. */
106
115
  list: (filter?: {
107
116
  agentId?: string;
108
117
  limit?: number;
109
118
  }) => Promise<string[]>;
119
+ /** Append new turns to a session (incremental, avoids full re-save). */
120
+ appendTurns: (sessionId: string, turns: SessionTurn[]) => Promise<void>;
121
+ /** Return a slice of turns for a session. */
122
+ getTurns: (sessionId: string, from?: number, limit?: number) => Promise<SessionTurn[]>;
123
+ /** Persist an updated run record (called after completeRun / abortRun / errorRun). */
124
+ updateRun: (sessionId: string, run: SessionRun) => Promise<void>;
125
+ /** Update the top-level status of a session. */
126
+ updateStatus: (sessionId: string, status: SessionData['status']) => Promise<void>;
110
127
  }
111
128
  interface Session {
112
129
  /** Session ID */
113
130
  readonly id: string;
114
131
  /** Agent ID (optional label) */
115
132
  readonly agentId?: string;
116
- /** Current message history */
117
- readonly messages: SessionMessage[];
133
+ /** Current turn history */
134
+ readonly turns: SessionTurn[];
135
+ /** Top-level session status */
136
+ readonly status: SessionData['status'];
118
137
  /** All runs in this session */
119
138
  readonly runs: SessionRun[];
120
139
  /** Arbitrary metadata */
@@ -133,19 +152,25 @@ interface Session {
133
152
  abortRun: (runId: string) => void;
134
153
  /** Mark a run as errored */
135
154
  errorRun: (runId: string, error: string) => void;
136
- /** Append messages to the session history */
137
- pushMessages: (messages: SessionMessage[]) => void;
138
- /** Replace all messages (e.g. after context:transform) */
139
- setMessages: (messages: SessionMessage[]) => void;
155
+ /** Append turns to in-memory history AND persist via store.appendTurns (if store present) */
156
+ appendTurns: (turns: SessionTurn[]) => Promise<void>;
157
+ /** Replace all turns in-memory (does not persist — use save() for that) */
158
+ setTurns: (turns: SessionTurn[]) => void;
159
+ /** Update the session status in memory AND via store.updateStatus (if store present) */
160
+ updateStatus: (status: SessionData['status']) => Promise<void>;
161
+ /** Persist an updated run record via store.updateRun (if store present) */
162
+ updateRun: (run: SessionRun) => Promise<void>;
163
+ /** Generate a turn ID using store.generateTurnId if available, else crypto.randomUUID() */
164
+ generateTurnId: () => string | Promise<string>;
140
165
  /** Set metadata key */
141
166
  setMeta: (key: string, value: unknown) => void;
142
- /** Persist the session to the store */
167
+ /** Persist the full session document to the store */
143
168
  save: () => Promise<void>;
144
169
  /** Serialize to SessionData */
145
170
  toJSON: () => SessionData;
146
171
  }
147
172
  interface CreateSessionOptions {
148
- /** Session ID (auto-generated if not provided) */
173
+ /** Session ID. If omitted and store provides generateSessionId, that is used. */
149
174
  id?: string;
150
175
  /** Agent ID label */
151
176
  agentId?: string;
@@ -157,11 +182,12 @@ interface CreateSessionOptions {
157
182
  }
158
183
  /**
159
184
  * Create a new session.
185
+ * Async so stores that generate IDs server-side (e.g. Supabase) can be supported.
160
186
  */
161
- declare function createSession(options?: CreateSessionOptions): Session;
187
+ declare function createSession(options?: CreateSessionOptions): Promise<Session>;
162
188
  /**
163
189
  * Load an existing session from a store.
164
190
  */
165
191
  declare function loadSession(store: SessionStore, sessionId: string): Promise<Session | null>;
166
192
 
167
- export { type CreateSessionOptions, type RemoteStoreOptions, type Session, type SessionData, SessionMessage, type SessionRun, type SessionStore, type SqliteStoreOptions, autoDetectAndConvert, createMemoryStore, createRemoteStore, createSession, createSqliteStore, fromAnthropic, fromOpenAI, loadSession, toAnthropic, toOpenAI };
193
+ export { type CreateSessionOptions, type RemoteStoreOptions, type Session, type SessionData, SessionMessage, type SessionRun, type SessionStore, SessionTurn, type SqliteStoreOptions, autoDetectAndConvert, createMemoryStore, createRemoteStore, createSession, createSqliteStore, fromAnthropic, fromOpenAI, loadSession, toAnthropic, toOpenAI };
package/dist/session.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  createSession,
5
5
  createSqliteStore,
6
6
  loadSession
7
- } from "./chunk-LMSOIIAT.js";
7
+ } from "./chunk-IC2WAUBZ.js";
8
8
  import {
9
9
  autoDetectAndConvert,
10
10
  fromAnthropic,
@@ -1,5 +1,5 @@
1
- import { f as HarnessConfig, g as ToolDef } from './agent-DvZm8U14.js';
2
- import { a as AgentStats } from './types-4CFQ-6Qu.js';
1
+ import { f as HarnessConfig, g as ToolDef } from './agent-DxIUxou4.js';
2
+ import { a as AgentStats } from './types-CLRMCak3.js';
3
3
 
4
4
  /**
5
5
  * Spawn tool — create sub-agents from a parent agent.
package/dist/tools.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { g as ToolDef } from './agent-DvZm8U14.js';
2
- export { C as ChildAgent, S as SpawnToolOptions, a as SpawnToolState, c as createSpawnTool, s as spawn } from './spawn-pP2grsVp.js';
1
+ import { g as ToolDef } from './agent-DxIUxou4.js';
2
+ export { C as ChildAgent, S as SpawnToolOptions, a as SpawnToolState, c as createSpawnTool, s as spawn } from './spawn-bEqlGUVT.js';
3
3
  import 'hookable';
4
4
  import '@anthropic-ai/sdk';
5
- import './types-4CFQ-6Qu.js';
5
+ import './types-CLRMCak3.js';
6
6
  import '@modelcontextprotocol/sdk/client/index.js';
7
7
  import './providers.js';
8
8
  import './session.js';
package/dist/tools.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  spawn,
7
7
  validateToolArgs,
8
8
  writeFile
9
- } from "./chunk-27EP7HB3.js";
9
+ } from "./chunk-SWS5624X.js";
10
10
  import "./chunk-26LIQARN.js";
11
11
  import "./chunk-PNKVD2UK.js";
12
12
  export {
@@ -52,6 +52,16 @@ interface SessionMessage {
52
52
  role: 'user' | 'assistant';
53
53
  content: SessionContentBlock[];
54
54
  }
55
+ interface SessionTurn {
56
+ /** UUID — generated by the store if it provides generateTurnId, else crypto.randomUUID() */
57
+ id: string;
58
+ role: 'user' | 'assistant' | 'system';
59
+ content: SessionContentBlock[];
60
+ /** Token usage — only present on assistant turns */
61
+ usage?: TurnUsage;
62
+ /** Unix timestamp (Date.now()) when the turn was created */
63
+ createdAt: number;
64
+ }
55
65
  interface AgentRunOptions {
56
66
  model?: string;
57
67
  prompt: string;
@@ -91,4 +101,4 @@ interface ChildRunStats {
91
101
  stats: AgentStats;
92
102
  }
93
103
 
94
- export type { AgentRunOptions as A, ChildRunStats as C, ImageContent as I, McpServerConfig as M, SessionContentBlock as S, ThinkingLevel as T, AgentStats as a, SessionMessage as b, ToolExecutionMode as c, TurnUsage as d };
104
+ export type { AgentRunOptions as A, ChildRunStats as C, ImageContent as I, McpServerConfig as M, SessionContentBlock as S, ThinkingLevel as T, AgentStats as a, SessionMessage as b, SessionTurn as c, ToolExecutionMode as d, TurnUsage as e };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zidane",
3
- "version": "1.2.0",
3
+ "version": "1.3.1",
4
4
  "description": "an agent that goes straight to the goal",
5
5
  "type": "module",
6
6
  "private": false,