zidane 1.6.4 → 1.6.6

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
@@ -174,6 +174,8 @@ await agent.run({ prompt: 'solve this', thinking: 'high', behavior: { thinkingBu
174
174
  const agent = createAgent({ provider, harness, behavior: { thinkingBudget: 16384 } })
175
175
  ```
176
176
 
177
+ Thinking traces are stored in session turns as `{ type: 'thinking', text }` content blocks and streamed live via the `stream:thinking` hook. Supported by Anthropic (native) and OpenRouter/Cerebras (`reasoning_content`/`reasoning` SSE fields).
178
+
177
179
  ## Hooks
178
180
 
179
181
  Every hook receives a mutable context object.
@@ -214,6 +216,11 @@ agent.hooks.hook('stream:end', (ctx) => {
214
216
  // ctx.text (final), ctx.turnId
215
217
  // Only fires when there is text content (not on tool-only turns)
216
218
  })
219
+
220
+ agent.hooks.hook('stream:thinking', (ctx) => {
221
+ // ctx.delta, ctx.thinking (accumulated), ctx.turnId
222
+ // Fires when the model streams reasoning traces (Anthropic, OpenRouter)
223
+ })
217
224
  ```
218
225
 
219
226
  ### Tool execution
@@ -582,7 +589,7 @@ import type { Agent, SessionTurn, TurnUsage, Provider, ToolDef } from 'zidane/ty
582
589
  bun test
583
590
  ```
584
591
 
585
- 474+ tests with mock provider and execution context. No API keys or Docker needed.
592
+ 484+ tests with mock provider and execution context. No API keys or Docker needed.
586
593
 
587
594
  ## License
588
595
 
@@ -64,6 +64,7 @@ type SessionContentBlock = {
64
64
  } | {
65
65
  type: 'thinking';
66
66
  text: string;
67
+ signature?: string;
67
68
  };
68
69
  interface SessionMessage {
69
70
  role: 'user' | 'assistant';
@@ -164,6 +165,7 @@ interface ToolResult {
164
165
  }
165
166
  interface StreamCallbacks {
166
167
  onText: (delta: string) => void;
168
+ onThinking?: (delta: string) => void;
167
169
  }
168
170
  interface TurnResult {
169
171
  /** Full assistant turn as a SessionMessage */
@@ -513,6 +515,11 @@ interface AgentHooks {
513
515
  text: string;
514
516
  turnId: string;
515
517
  }) => void;
518
+ 'stream:thinking': (ctx: {
519
+ delta: string;
520
+ thinking: string;
521
+ turnId: string;
522
+ }) => void;
516
523
  'tool:before': (ctx: {
517
524
  name: string;
518
525
  input: Record<string, unknown>;
@@ -395,14 +395,10 @@ async function runLoop(ctx) {
395
395
  });
396
396
  continue;
397
397
  }
398
- const stats2 = { totalIn, totalOut, turns: turn + 1, elapsed: Date.now() - startTime, turnUsage: turnUsages, output: result.output };
399
- await ctx.hooks.callHook("agent:done", stats2);
400
- return stats2;
398
+ return { totalIn, totalOut, turns: turn + 1, elapsed: Date.now() - startTime, turnUsage: turnUsages, output: result.output };
401
399
  }
402
400
  }
403
- const stats = { totalIn, totalOut, turns: maxTurns, elapsed: Date.now() - startTime, turnUsage: turnUsages };
404
- await ctx.hooks.callHook("agent:done", stats);
405
- return stats;
401
+ return { totalIn, totalOut, turns: maxTurns, elapsed: Date.now() - startTime, turnUsage: turnUsages };
406
402
  }
407
403
  async function executeTurn(ctx, turn) {
408
404
  const turnId = await ctx.generateTurnId();
@@ -420,6 +416,7 @@ async function executeTurn(ctx, turn) {
420
416
  await ctx.hooks.callHook("context:transform", { messages });
421
417
  await ctx.hooks.callHook("turn:before", { turn, turnId, options: streamOptions });
422
418
  let currentText = "";
419
+ let currentThinking = "";
423
420
  let result;
424
421
  try {
425
422
  result = await ctx.provider.stream(
@@ -428,6 +425,10 @@ async function executeTurn(ctx, turn) {
428
425
  onText(delta) {
429
426
  currentText += delta;
430
427
  ctx.hooks.callHook("stream:text", { delta, text: currentText, turnId });
428
+ },
429
+ onThinking(delta) {
430
+ currentThinking += delta;
431
+ ctx.hooks.callHook("stream:thinking", { delta, thinking: currentThinking, turnId });
431
432
  }
432
433
  }
433
434
  );
@@ -4,7 +4,7 @@ import {
4
4
  shell,
5
5
  spawn,
6
6
  writeFile
7
- } from "./chunk-KWNFSVVE.js";
7
+ } from "./chunk-F4BVVP67.js";
8
8
 
9
9
  // src/harnesses/basic.ts
10
10
  var basicTools = { shell, readFile, writeFile, listFiles };
@@ -6,6 +6,7 @@ async function consumeSSE(response, callbacks, signal) {
6
6
  const decoder = new TextDecoder();
7
7
  let buffer = "";
8
8
  let text = "";
9
+ let thinking = "";
9
10
  let finishReason = "stop";
10
11
  let usage = { input: 0, output: 0 };
11
12
  const tcMap = /* @__PURE__ */ new Map();
@@ -36,6 +37,11 @@ async function consumeSSE(response, callbacks, signal) {
36
37
  continue;
37
38
  if (choice.finish_reason)
38
39
  finishReason = choice.finish_reason;
40
+ const thinkingDelta = choice.delta?.reasoning_content ?? choice.delta?.reasoning;
41
+ if (thinkingDelta) {
42
+ thinking += thinkingDelta;
43
+ callbacks.onThinking?.(thinkingDelta);
44
+ }
39
45
  if (choice.delta?.content) {
40
46
  text += choice.delta.content;
41
47
  callbacks.onText(choice.delta.content);
@@ -72,7 +78,7 @@ async function consumeSSE(response, callbacks, signal) {
72
78
  name: tc.name,
73
79
  input: tc.args ? JSON.parse(tc.args) : {}
74
80
  }));
75
- return { text, toolCalls, finishReason, usage };
81
+ return { text, thinking, toolCalls, finishReason, usage };
76
82
  }
77
83
  function toOAIMessages(system, messages) {
78
84
  const out = [{ role: "system", content: system }];
@@ -156,8 +162,10 @@ function toolResultsMessage(results) {
156
162
  }))
157
163
  };
158
164
  }
159
- function buildAssistantContent(text, toolCalls) {
165
+ function buildAssistantContent(text, toolCalls, thinking) {
160
166
  const content = [];
167
+ if (thinking)
168
+ content.push({ type: "thinking", text: thinking });
161
169
  if (text)
162
170
  content.push({ type: "text", text });
163
171
  for (const tc of toolCalls) {
@@ -192,7 +200,7 @@ function fromAnthropic(msg) {
192
200
  const output = typeof b.content === "string" ? b.content : JSON.stringify(b.content);
193
201
  content.push({ type: "tool_result", callId: b.tool_use_id, output });
194
202
  } else if (b.type === "thinking") {
195
- content.push({ type: "thinking", text: b.thinking });
203
+ content.push({ type: "thinking", text: b.thinking, signature: b.signature });
196
204
  }
197
205
  }
198
206
  }
@@ -261,7 +269,7 @@ function toAnthropic(msg) {
261
269
  case "tool_result":
262
270
  return { type: "tool_result", tool_use_id: block.callId, content: block.output };
263
271
  case "thinking":
264
- return { type: "thinking", thinking: block.text };
272
+ return { type: "thinking", thinking: block.text, signature: block.signature };
265
273
  default:
266
274
  return { type: "text", text: "" };
267
275
  }
@@ -1,4 +1,4 @@
1
1
  import 'hookable';
2
- export { H as Harness, i as HarnessConfig, u as ToolContext, v as ToolDef, x as ToolMap, a1 as basic, a2 as basicTools, Q as defineHarness, X as noTools } from './agent-CPOBJlcn.js';
2
+ export { H as Harness, i as HarnessConfig, u as ToolContext, v as ToolDef, x as ToolMap, a1 as basic, a2 as basicTools, Q as defineHarness, X as noTools } from './agent-0Tafyla0.js';
3
3
  import './types-CKXAp41h.js';
4
4
  import '@modelcontextprotocol/sdk/client/index.js';
package/dist/harnesses.js CHANGED
@@ -3,8 +3,8 @@ import {
3
3
  basic_default,
4
4
  defineHarness,
5
5
  noTools
6
- } from "./chunk-BDBQ5MIB.js";
7
- import "./chunk-KWNFSVVE.js";
6
+ } from "./chunk-KG63Q5KF.js";
7
+ import "./chunk-F4BVVP67.js";
8
8
  import "./chunk-NNMWWSBY.js";
9
9
  import "./chunk-4C6Y56CC.js";
10
10
  export {
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- export { A as Agent, a as AgentBehavior, b as AgentHooks, c as AgentOptions, d as AgentRunOptions, e as AgentStats, h as CreateSessionOptions, H as Harness, i as HarnessConfig, I as ImageContent, M as McpConnection, j as McpServerConfig, R as RemoteStoreOptions, S as Session, k as SessionContentBlock, l as SessionData, m as SessionMessage, n as SessionRun, o as SessionStore, p as SessionTurn, q as SqliteStoreOptions, T as ThinkingLevel, u as ToolContext, v as ToolDef, w as ToolExecutionMode, x as ToolMap, D as TurnUsage, E as autoDetectAndConvert, F as connectMcpServers, G as createAgent, J as createMemoryStore, K as createRemoteStore, L as createSession, N as createSqliteStore, Q as defineHarness, U as fromAnthropic, V as fromOpenAI, W as loadSession, X as noTools, Y as toAnthropic, Z as toOpenAI } from './agent-CPOBJlcn.js';
1
+ export { A as Agent, a as AgentBehavior, b as AgentHooks, c as AgentOptions, d as AgentRunOptions, e as AgentStats, h as CreateSessionOptions, H as Harness, i as HarnessConfig, I as ImageContent, M as McpConnection, j as McpServerConfig, R as RemoteStoreOptions, S as Session, k as SessionContentBlock, l as SessionData, m as SessionMessage, n as SessionRun, o as SessionStore, p as SessionTurn, q as SqliteStoreOptions, T as ThinkingLevel, u as ToolContext, v as ToolDef, w as ToolExecutionMode, x as ToolMap, D as TurnUsage, E as autoDetectAndConvert, F as connectMcpServers, G as createAgent, J as createMemoryStore, K as createRemoteStore, L as createSession, N as createSqliteStore, Q as defineHarness, U as fromAnthropic, V as fromOpenAI, W as loadSession, X as noTools, Y as toAnthropic, Z as toOpenAI } from './agent-0Tafyla0.js';
2
2
  import { f as SpawnConfig, b as ExecutionContext } from './types-CKXAp41h.js';
3
3
  export { C as ContextCapabilities, a as ContextType, E as ExecResult, c as ExecutionHandle, S as SkillConfig, d as SkillResource, e as SkillsConfig } from './types-CKXAp41h.js';
4
4
  export { S as SandboxProvider, c as createSandboxContext } from './sandbox-DZn3ybp_.js';
5
5
  export { buildCatalog, defineSkill, discoverSkills, interpolateShellCommands, mergeSkillsConfig, parseSkillFile, resolveSkills, validateSkillName, writeSkillToDisk, writeSkillsToDisk } from './skills.js';
6
- export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState, c as createInteractionTool, b as createSpawnTool, s as spawn } from './spawn-CK08YMPC.js';
6
+ export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState, c as createInteractionTool, b as createSpawnTool, s as spawn } from './spawn-Bm1ihQ_K.js';
7
7
  import 'hookable';
8
8
  import '@modelcontextprotocol/sdk/client/index.js';
9
9
 
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  defineHarness,
3
3
  noTools
4
- } from "./chunk-BDBQ5MIB.js";
4
+ } from "./chunk-KG63Q5KF.js";
5
5
  import {
6
6
  createAgent,
7
7
  createDockerContext,
@@ -10,7 +10,7 @@ import {
10
10
  createSandboxContext,
11
11
  createSpawnTool,
12
12
  spawn
13
- } from "./chunk-KWNFSVVE.js";
13
+ } from "./chunk-F4BVVP67.js";
14
14
  import {
15
15
  connectMcpServers
16
16
  } from "./chunk-NNMWWSBY.js";
@@ -27,7 +27,7 @@ import {
27
27
  fromOpenAI,
28
28
  toAnthropic,
29
29
  toOpenAI
30
- } from "./chunk-UHCWNQGG.js";
30
+ } from "./chunk-QCJKUQTQ.js";
31
31
  import {
32
32
  defineSkill
33
33
  } from "./chunk-CFLC2I7D.js";
package/dist/mcp.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import 'hookable';
2
- export { M as McpConnection, j as McpServerConfig, F as connectMcpServers, a3 as resultToString } from './agent-CPOBJlcn.js';
2
+ export { M as McpConnection, j as McpServerConfig, F as connectMcpServers, a3 as resultToString } from './agent-0Tafyla0.js';
3
3
  import '@modelcontextprotocol/sdk/client/index.js';
4
4
  import './types-CKXAp41h.js';
@@ -1,4 +1,4 @@
1
- export { f as AnthropicParams, C as CerebrasParams, O as OpenRouterParams, P as Provider, r as StreamCallbacks, s as StreamOptions, t as ToolCall, y as ToolResult, z as ToolSpec, B as TurnResult, _ as anthropic, $ as cerebras, a0 as openrouter } from './agent-CPOBJlcn.js';
1
+ export { f as AnthropicParams, C as CerebrasParams, O as OpenRouterParams, P as Provider, r as StreamCallbacks, s as StreamOptions, t as ToolCall, y as ToolResult, z as ToolSpec, B as TurnResult, _ as anthropic, $ as cerebras, a0 as openrouter } from './agent-0Tafyla0.js';
2
2
  import 'hookable';
3
3
  import './types-CKXAp41h.js';
4
4
  import '@modelcontextprotocol/sdk/client/index.js';
package/dist/providers.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  toOAIMessages,
9
9
  toolResultsMessage,
10
10
  userMessage
11
- } from "./chunk-UHCWNQGG.js";
11
+ } from "./chunk-QCJKUQTQ.js";
12
12
 
13
13
  // src/providers/anthropic.ts
14
14
  import { existsSync, readFileSync } from "fs";
@@ -109,6 +109,7 @@ function anthropic(anthropicParams) {
109
109
  type: "enabled",
110
110
  budget_tokens: budgetTokens
111
111
  };
112
+ params.max_tokens = budgetTokens + params.max_tokens;
112
113
  params.temperature = 1;
113
114
  }
114
115
  if (options.toolChoice) {
@@ -127,6 +128,11 @@ function anthropic(anthropicParams) {
127
128
  text += delta;
128
129
  callbacks.onText(delta);
129
130
  });
131
+ if (callbacks.onThinking) {
132
+ s.on("thinking", (delta) => {
133
+ callbacks.onThinking(delta);
134
+ });
135
+ }
130
136
  const response = await s.finalMessage();
131
137
  const toolCalls = response.content.filter((b) => b.type === "tool_use").map((b) => ({ id: b.id, name: b.name, input: b.input }));
132
138
  return {
@@ -167,10 +173,11 @@ function cerebras(params) {
167
173
  async stream(options, callbacks) {
168
174
  const modelId = options.model || defaultModel;
169
175
  const messages = toOAIMessages(options.system, options.messages);
176
+ const maxTokens = options.thinkingBudget ? options.thinkingBudget + options.maxTokens : options.maxTokens;
170
177
  const body = {
171
178
  model: modelId,
172
179
  messages,
173
- max_tokens: options.maxTokens,
180
+ max_tokens: maxTokens,
174
181
  stream: true
175
182
  };
176
183
  if (options.tools && options.tools.length > 0)
@@ -198,7 +205,7 @@ function cerebras(params) {
198
205
  }
199
206
  const result = await consumeSSE(response, callbacks, options.signal);
200
207
  return {
201
- assistantMessage: buildAssistantContent(result.text, result.toolCalls),
208
+ assistantMessage: buildAssistantContent(result.text, result.toolCalls, result.thinking),
202
209
  text: result.text,
203
210
  toolCalls: result.toolCalls,
204
211
  done: result.finishReason === "stop" || result.toolCalls.length === 0,
@@ -233,10 +240,11 @@ function openrouter(params) {
233
240
  if (thinking !== "off" && !modelId.includes(":thinking"))
234
241
  modelId = `${modelId}:thinking`;
235
242
  const messages = toOAIMessages(options.system, options.messages);
243
+ const maxTokens = options.thinkingBudget ? options.thinkingBudget + options.maxTokens : options.maxTokens;
236
244
  const body = {
237
245
  model: modelId,
238
246
  messages,
239
- max_tokens: options.maxTokens,
247
+ max_tokens: maxTokens,
240
248
  stream: true
241
249
  };
242
250
  if (options.tools && options.tools.length > 0)
@@ -266,7 +274,7 @@ function openrouter(params) {
266
274
  }
267
275
  const result = await consumeSSE(response, callbacks, options.signal);
268
276
  return {
269
- assistantMessage: buildAssistantContent(result.text, result.toolCalls),
277
+ assistantMessage: buildAssistantContent(result.text, result.toolCalls, result.thinking),
270
278
  text: result.text,
271
279
  toolCalls: result.toolCalls,
272
280
  done: result.finishReason === "stop" || result.toolCalls.length === 0,
package/dist/session.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { h as CreateSessionOptions, R as RemoteStoreOptions, S as Session, k as SessionContentBlock, l as SessionData, m as SessionMessage, n as SessionRun, o as SessionStore, p as SessionTurn, q as SqliteStoreOptions, E as autoDetectAndConvert, J as createMemoryStore, K as createRemoteStore, L as createSession, N as createSqliteStore, U as fromAnthropic, V as fromOpenAI, W as loadSession, Y as toAnthropic, Z as toOpenAI } from './agent-CPOBJlcn.js';
1
+ export { h as CreateSessionOptions, R as RemoteStoreOptions, S as Session, k as SessionContentBlock, l as SessionData, m as SessionMessage, n as SessionRun, o as SessionStore, p as SessionTurn, q as SqliteStoreOptions, E as autoDetectAndConvert, J as createMemoryStore, K as createRemoteStore, L as createSession, N as createSqliteStore, U as fromAnthropic, V as fromOpenAI, W as loadSession, Y as toAnthropic, Z as toOpenAI } from './agent-0Tafyla0.js';
2
2
  import 'hookable';
3
3
  import './types-CKXAp41h.js';
4
4
  import '@modelcontextprotocol/sdk/client/index.js';
package/dist/session.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  fromOpenAI,
12
12
  toAnthropic,
13
13
  toOpenAI
14
- } from "./chunk-UHCWNQGG.js";
14
+ } from "./chunk-QCJKUQTQ.js";
15
15
  export {
16
16
  autoDetectAndConvert,
17
17
  createMemoryStore,
@@ -1,4 +1,4 @@
1
- import { v as ToolDef, i as HarnessConfig, e as AgentStats } from './agent-CPOBJlcn.js';
1
+ import { v as ToolDef, i as HarnessConfig, e as AgentStats } from './agent-0Tafyla0.js';
2
2
 
3
3
  /**
4
4
  * Interaction tool — lets the agent request structured input from the outside world.
package/dist/tools.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState, c as createInteractionTool, b as createSpawnTool, s as spawn } from './spawn-CK08YMPC.js';
2
- import { v as ToolDef } from './agent-CPOBJlcn.js';
1
+ export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState, c as createInteractionTool, b as createSpawnTool, s as spawn } from './spawn-Bm1ihQ_K.js';
2
+ import { v as ToolDef } from './agent-0Tafyla0.js';
3
3
  export { V as ValidationResult, v as validateToolArgs } from './validation-DOY_k7lW.js';
4
4
  import 'hookable';
5
5
  import './types-CKXAp41h.js';
package/dist/tools.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  spawn,
8
8
  validateToolArgs,
9
9
  writeFile
10
- } from "./chunk-KWNFSVVE.js";
10
+ } from "./chunk-F4BVVP67.js";
11
11
  import "./chunk-NNMWWSBY.js";
12
12
  import "./chunk-4C6Y56CC.js";
13
13
  export {
package/dist/types.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export { A as Agent, a as AgentBehavior, b as AgentHooks, c as AgentOptions, d as AgentRunOptions, e as AgentStats, f as AnthropicParams, C as CerebrasParams, g as ChildRunStats, h as CreateSessionOptions, H as Harness, i as HarnessConfig, I as ImageContent, M as McpConnection, j as McpServerConfig, O as OpenRouterParams, P as Provider, R as RemoteStoreOptions, S as Session, k as SessionContentBlock, l as SessionData, m as SessionMessage, n as SessionRun, o as SessionStore, p as SessionTurn, q as SqliteStoreOptions, r as StreamCallbacks, s as StreamOptions, T as ThinkingLevel, t as ToolCall, u as ToolContext, v as ToolDef, w as ToolExecutionMode, x as ToolMap, y as ToolResult, z as ToolSpec, B as TurnResult, D as TurnUsage } from './agent-CPOBJlcn.js';
1
+ export { A as Agent, a as AgentBehavior, b as AgentHooks, c as AgentOptions, d as AgentRunOptions, e as AgentStats, f as AnthropicParams, C as CerebrasParams, g as ChildRunStats, h as CreateSessionOptions, H as Harness, i as HarnessConfig, I as ImageContent, M as McpConnection, j as McpServerConfig, O as OpenRouterParams, P as Provider, R as RemoteStoreOptions, S as Session, k as SessionContentBlock, l as SessionData, m as SessionMessage, n as SessionRun, o as SessionStore, p as SessionTurn, q as SqliteStoreOptions, r as StreamCallbacks, s as StreamOptions, T as ThinkingLevel, t as ToolCall, u as ToolContext, v as ToolDef, w as ToolExecutionMode, x as ToolMap, y as ToolResult, z as ToolSpec, B as TurnResult, D as TurnUsage } from './agent-0Tafyla0.js';
2
2
  export { C as ContextCapabilities, a as ContextType, E as ExecResult, b as ExecutionContext, c as ExecutionHandle, S as SkillConfig, d as SkillResource, e as SkillsConfig, f as SpawnConfig } from './types-CKXAp41h.js';
3
3
  export { S as SandboxProvider } from './sandbox-DZn3ybp_.js';
4
- export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState } from './spawn-CK08YMPC.js';
4
+ export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState } from './spawn-Bm1ihQ_K.js';
5
5
  export { V as ValidationResult } from './validation-DOY_k7lW.js';
6
6
  import 'hookable';
7
7
  import '@modelcontextprotocol/sdk/client/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zidane",
3
- "version": "1.6.4",
3
+ "version": "1.6.6",
4
4
  "description": "an agent that goes straight to the goal",
5
5
  "type": "module",
6
6
  "private": false,