zidane 1.5.2 → 1.6.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
@@ -35,11 +35,12 @@ All options on `createAgent`:
35
35
  createAgent({
36
36
  provider, // required: LLM provider
37
37
  harness: basic, // tool set (default: noTools)
38
- enableTools: true, // false for pure chat mode
39
- toolExecution: 'sequential', // or 'parallel'
40
- maxTurns: 50, // max loop iterations
41
- maxTokens: 16384, // max tokens per LLM response
42
- thinkingBudget: 10240, // exact thinking token budget
38
+ behavior: { // agent-level defaults
39
+ toolExecution: 'sequential', // or 'parallel'
40
+ maxTurns: 50, // max loop iterations
41
+ maxTokens: 16384, // max tokens per LLM response
42
+ thinkingBudget: 10240, // exact thinking token budget
43
+ },
43
44
  execution: createProcessContext(), // where tools run
44
45
  mcpServers: [], // MCP tool servers
45
46
  session, // session for persistence
@@ -51,19 +52,22 @@ All options on `agent.run()`:
51
52
 
52
53
  ```ts
53
54
  await agent.run({
54
- prompt: 'your task', // required
55
+ prompt: 'your task', // required
55
56
  model: 'claude-opus-4-6',
56
57
  system: 'be concise',
57
- thinking: 'medium', // off | minimal | low | medium | high
58
- thinkingBudget: 8192, // overrides level-based default
59
- maxTurns: 10, // overrides agent-level default
60
- maxTokens: 4096, // overrides agent-level default
61
- images: [], // base64 images
58
+ thinking: 'medium', // off | minimal | low | medium | high
59
+ behavior: { // per-run overrides
60
+ maxTurns: 10,
61
+ maxTokens: 4096,
62
+ thinkingBudget: 8192,
63
+ },
64
+ tools: {}, // override tools for this run ({} = no tools)
65
+ images: [], // base64 images
62
66
  signal: abortController.signal,
63
67
  })
64
68
  ```
65
69
 
66
- Per-run options override agent-level defaults. Agent-level defaults override hardcoded defaults.
70
+ Precedence: `run.behavior` > `agent.behavior` > `harness.behavior` > hardcoded defaults.
67
71
 
68
72
  ## CLI
69
73
 
@@ -139,10 +143,10 @@ const harness = defineHarness({
139
143
  })
140
144
  ```
141
145
 
142
- For pure chat with no tools:
146
+ For pure chat with no tools, pass `tools: {}` on a specific run or use the `noTools` harness:
143
147
 
144
148
  ```ts
145
- const agent = createAgent({ provider, enableTools: false })
149
+ await agent.run({ prompt: 'just chat', tools: {} })
146
150
  ```
147
151
 
148
152
  ## Thinking
@@ -162,10 +166,10 @@ Extended reasoning with named levels or exact token budgets.
162
166
  await agent.run({ prompt: 'solve this', thinking: 'high' })
163
167
 
164
168
  // Exact budget (overrides level default)
165
- await agent.run({ prompt: 'solve this', thinking: 'high', thinkingBudget: 50000 })
169
+ await agent.run({ prompt: 'solve this', thinking: 'high', behavior: { thinkingBudget: 50000 } })
166
170
 
167
171
  // Agent-level default
168
- const agent = createAgent({ provider, harness, thinkingBudget: 16384 })
172
+ const agent = createAgent({ provider, harness, behavior: { thinkingBudget: 16384 } })
169
173
  ```
170
174
 
171
175
  ## Hooks
@@ -180,12 +184,19 @@ agent.hooks.hook('turn:before', (ctx) => {
180
184
  })
181
185
 
182
186
  agent.hooks.hook('turn:after', (ctx) => {
183
- // ctx.turn, ctx.turnId, ctx.usage { input, output }
187
+ // ctx.turn, ctx.turnId, ctx.usage, ctx.message (full SessionTurn)
184
188
  // Always fires — even if the provider throws mid-stream
189
+ // Turn is guaranteed to be in agent.turns before this fires
190
+ })
191
+
192
+ agent.hooks.hook('usage', (ctx) => {
193
+ // ctx.turn, ctx.turnId, ctx.usage (per-turn)
194
+ // ctx.totalIn, ctx.totalOut (running totals)
185
195
  })
186
196
 
187
197
  agent.hooks.hook('agent:done', (ctx) => {
188
198
  // ctx.totalIn, ctx.totalOut, ctx.turns, ctx.elapsed, ctx.children?
199
+ // ctx.output — structured output (when behavior.schema is set)
189
200
  // Fires on all exit paths: completion, maxTurns, and abort
190
201
  })
191
202
  ```
@@ -329,7 +340,7 @@ if (session) {
329
340
 
330
341
  ```ts
331
342
  agent.hooks.hook('session:start', (ctx) => { /* ctx.sessionId, ctx.runId, ctx.prompt */ })
332
- agent.hooks.hook('session:end', (ctx) => { /* ctx.sessionId, ctx.runId, ctx.status */ })
343
+ agent.hooks.hook('session:end', (ctx) => { /* ctx.sessionId, ctx.runId, ctx.status, ctx.turnRange */ })
333
344
  agent.hooks.hook('session:turns', (ctx) => { /* ctx.sessionId, ctx.count */ })
334
345
  ```
335
346
 
@@ -449,7 +460,7 @@ const agent = createAgent({
449
460
 
450
461
  ```ts
451
462
  agent.isRunning // is a run in progress?
452
- agent.messages // conversation history
463
+ agent.turns // conversation history (SessionTurn[])
453
464
  agent.abort() // cancel the current run
454
465
  agent.reset() // clear messages and queues
455
466
  await agent.destroy() // clean up context + MCP connections
@@ -480,6 +491,45 @@ Converters for external interop:
480
491
  import { fromAnthropic, toAnthropic, fromOpenAI, toOpenAI, autoDetectAndConvert } from 'zidane'
481
492
  ```
482
493
 
494
+ ## Structured Output
495
+
496
+ Force the agent's final response to match a JSON Schema via provider-level tool forcing.
497
+
498
+ ```ts
499
+ const stats = await agent.run({
500
+ prompt: 'Extract the entities',
501
+ behavior: {
502
+ schema: {
503
+ type: 'object',
504
+ properties: { name: { type: 'string' }, age: { type: 'number' } },
505
+ required: ['name', 'age'],
506
+ },
507
+ },
508
+ })
509
+
510
+ console.log(stats.output) // { name: 'Alice', age: 30 }
511
+ ```
512
+
513
+ The `output` hook fires when structured output is extracted:
514
+
515
+ ```ts
516
+ agent.hooks.hook('output', (ctx) => {
517
+ // ctx.output — the parsed JSON matching the schema
518
+ // ctx.schema — the schema that was enforced
519
+ })
520
+ ```
521
+
522
+ ### Zod v4 integration
523
+
524
+ Use `zodToJsonSchema` to normalize `z.toJsonSchema()` output for tool schemas:
525
+
526
+ ```ts
527
+ import { z } from 'zod'
528
+ import { zodToJsonSchema } from 'zidane'
529
+
530
+ const schema = zodToJsonSchema(z.toJsonSchema(z.object({ name: z.string() })))
531
+ ```
532
+
483
533
  ## Usage Tracking
484
534
 
485
535
  ```ts
@@ -488,13 +538,21 @@ stats.turnUsage // TurnUsage[] — per-turn { input, output, cacheCreation?, c
488
538
  stats.cost // total USD cost (if reported by provider)
489
539
  ```
490
540
 
541
+ ## Types
542
+
543
+ All types are available from `zidane/types`:
544
+
545
+ ```ts
546
+ import type { Agent, SessionTurn, TurnUsage, Provider, ToolDef } from 'zidane/types'
547
+ ```
548
+
491
549
  ## Testing
492
550
 
493
551
  ```bash
494
552
  bun test
495
553
  ```
496
554
 
497
- 430+ tests with mock provider and execution context. No API keys or Docker needed.
555
+ 460+ tests with mock provider and execution context. No API keys or Docker needed.
498
556
 
499
557
  ## License
500
558