zidane 1.6.1 → 1.6.4

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
@@ -34,16 +34,16 @@ All options on `createAgent`:
34
34
  ```ts
35
35
  createAgent({
36
36
  provider, // required: LLM provider
37
+ session, // session for persistence
37
38
  harness: basic, // tool set (default: noTools)
38
39
  behavior: { // agent-level defaults
39
- toolExecution: 'sequential', // or 'parallel'
40
+ toolExecution: 'parallel', // or 'sequential' (default: parallel)
40
41
  maxTurns: 50, // max loop iterations
41
- maxTokens: 16384, // max tokens per LLM response
42
- thinkingBudget: 10240, // exact thinking token budget
42
+ maxTokens: 16384, // max tokens per LLM response
43
+ thinkingBudget: 10240, // exact thinking token budget
43
44
  },
44
45
  execution: createProcessContext(), // where tools run
45
46
  mcpServers: [], // MCP tool servers
46
- session, // session for persistence
47
47
  skills: {}, // skills configuration
48
48
  })
49
49
  ```
@@ -52,7 +52,7 @@ All options on `agent.run()`:
52
52
 
53
53
  ```ts
54
54
  await agent.run({
55
- prompt: 'your task', // required
55
+ prompt: 'your task', // optional when session has existing turns
56
56
  model: 'claude-opus-4-6',
57
57
  system: 'be concise',
58
58
  thinking: 'medium', // off | minimal | low | medium | high
@@ -67,6 +67,8 @@ await agent.run({
67
67
  })
68
68
  ```
69
69
 
70
+ `prompt` is optional when a session with existing turns is provided — the agent resumes from the last turn. This supports apps where the user message is persisted to the session before the agent runs (e.g. WebSocket → session → queue → agent).
71
+
70
72
  Precedence: `run.behavior` > `agent.behavior` > `harness.behavior` > hardcoded defaults.
71
73
 
72
74
  ## CLI
@@ -205,11 +207,11 @@ agent.hooks.hook('agent:done', (ctx) => {
205
207
 
206
208
  ```ts
207
209
  agent.hooks.hook('stream:text', (ctx) => {
208
- // ctx.delta, ctx.text, ctx.turnId, ctx.blockIndex
210
+ // ctx.delta, ctx.text, ctx.turnId
209
211
  })
210
212
 
211
213
  agent.hooks.hook('stream:end', (ctx) => {
212
- // ctx.text (final), ctx.turnId, ctx.blockIndex
214
+ // ctx.text (final), ctx.turnId
213
215
  // Only fires when there is text content (not on tool-only turns)
214
216
  })
215
217
  ```
@@ -297,6 +299,34 @@ const harness = defineHarness({
297
299
 
298
300
  Children inherit the parent's harness and can spawn their own children.
299
301
 
302
+ ## Interaction Tool
303
+
304
+ Let the agent pause and request structured input from the outside world. Not included in any harness by default.
305
+
306
+ ```ts
307
+ import { createInteractionTool, defineHarness, basicTools } from 'zidane'
308
+
309
+ const askUser = createInteractionTool({
310
+ name: 'ask_user',
311
+ schema: {
312
+ type: 'object',
313
+ properties: { question: { type: 'string' } },
314
+ required: ['question'],
315
+ },
316
+ onRequest: async (payload) => {
317
+ const answer = await promptUser(payload.question)
318
+ return { answer }
319
+ },
320
+ })
321
+
322
+ const harness = defineHarness({
323
+ name: 'interactive',
324
+ tools: { ...basicTools, ask_user: askUser },
325
+ })
326
+ ```
327
+
328
+ `onRequest` can be async — the agent waits for the response. Return a string or object (objects are JSON-stringified).
329
+
300
330
  ## Sessions
301
331
 
302
332
  Sessions give an agent persistent turn history and run metadata across calls.
@@ -552,7 +582,7 @@ import type { Agent, SessionTurn, TurnUsage, Provider, ToolDef } from 'zidane/ty
552
582
  bun test
553
583
  ```
554
584
 
555
- 460+ tests with mock provider and execution context. No API keys or Docker needed.
585
+ 474+ tests with mock provider and execution context. No API keys or Docker needed.
556
586
 
557
587
  ## License
558
588
 
@@ -83,7 +83,8 @@ interface SessionTurn {
83
83
  }
84
84
  interface AgentRunOptions {
85
85
  model?: string;
86
- prompt: string;
86
+ /** User prompt. Optional when resuming a session with existing turns. */
87
+ prompt?: string;
87
88
  system?: string;
88
89
  thinking?: ThinkingLevel;
89
90
  images?: ImageContent[];
@@ -150,7 +151,7 @@ declare function openrouter(params?: OpenRouterParams): Provider;
150
151
  interface ToolSpec {
151
152
  name: string;
152
153
  description: string;
153
- input_schema: Record<string, unknown>;
154
+ inputSchema: Record<string, unknown>;
154
155
  }
155
156
  interface ToolCall {
156
157
  id: string;
@@ -433,7 +434,7 @@ interface Session {
433
434
  /** Arbitrary metadata */
434
435
  readonly metadata: Record<string, unknown>;
435
436
  /** Start tracking a new run */
436
- startRun: (runId: string, prompt: string) => void;
437
+ startRun: (runId: string, prompt?: string) => void;
437
438
  /** Mark a run as completed */
438
439
  completeRun: (runId: string, stats: {
439
440
  turns: number;
@@ -507,12 +508,10 @@ interface AgentHooks {
507
508
  delta: string;
508
509
  text: string;
509
510
  turnId: string;
510
- blockIndex: number;
511
511
  }) => void;
512
512
  'stream:end': (ctx: {
513
513
  text: string;
514
514
  turnId: string;
515
- blockIndex: number;
516
515
  }) => void;
517
516
  'tool:before': (ctx: {
518
517
  name: string;
@@ -4,7 +4,7 @@ import {
4
4
  shell,
5
5
  spawn,
6
6
  writeFile
7
- } from "./chunk-SKLAWY7O.js";
7
+ } from "./chunk-KWNFSVVE.js";
8
8
 
9
9
  // src/harnesses/basic.ts
10
10
  var basicTools = { shell, readFile, writeFile, listFiles };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  connectMcpServers
3
- } from "./chunk-YTZOORAP.js";
3
+ } from "./chunk-NNMWWSBY.js";
4
4
  import {
5
5
  buildCatalog,
6
6
  interpolateShellCommands,
@@ -8,12 +8,29 @@ import {
8
8
  resolveSkills
9
9
  } from "./chunk-4C6Y56CC.js";
10
10
 
11
+ // src/tools/interaction.ts
12
+ function createInteractionTool(options) {
13
+ const name = options.name ?? "interaction";
14
+ const description = options.description ?? "Request structured input from the user or external system.";
15
+ return {
16
+ spec: {
17
+ name,
18
+ description,
19
+ inputSchema: options.schema
20
+ },
21
+ async execute(input) {
22
+ const result = await options.onRequest(input);
23
+ return typeof result === "string" ? result : JSON.stringify(result);
24
+ }
25
+ };
26
+ }
27
+
11
28
  // src/tools/list-files.ts
12
29
  var listFiles = {
13
30
  spec: {
14
31
  name: "list_files",
15
32
  description: "List files and directories at the given path (relative to project root).",
16
- input_schema: {
33
+ inputSchema: {
17
34
  type: "object",
18
35
  properties: {
19
36
  path: { type: "string", description: 'Relative directory path (default: ".")' }
@@ -36,7 +53,7 @@ var readFile = {
36
53
  spec: {
37
54
  name: "read_file",
38
55
  description: "Read the contents of a file at the given path (relative to project root).",
39
- input_schema: {
56
+ inputSchema: {
40
57
  type: "object",
41
58
  properties: {
42
59
  path: { type: "string", description: "Relative file path" }
@@ -58,7 +75,7 @@ var shell = {
58
75
  spec: {
59
76
  name: "shell",
60
77
  description: "Execute a shell command and return stdout+stderr. Runs in the project root.",
61
- input_schema: {
78
+ inputSchema: {
62
79
  type: "object",
63
80
  properties: {
64
81
  command: { type: "string", description: "The shell command to run" }
@@ -403,7 +420,6 @@ async function executeTurn(ctx, turn) {
403
420
  await ctx.hooks.callHook("context:transform", { messages });
404
421
  await ctx.hooks.callHook("turn:before", { turn, turnId, options: streamOptions });
405
422
  let currentText = "";
406
- let blockIndex = 0;
407
423
  let result;
408
424
  try {
409
425
  result = await ctx.provider.stream(
@@ -411,26 +427,26 @@ async function executeTurn(ctx, turn) {
411
427
  {
412
428
  onText(delta) {
413
429
  currentText += delta;
414
- ctx.hooks.callHook("stream:text", { delta, text: currentText, turnId, blockIndex });
430
+ ctx.hooks.callHook("stream:text", { delta, text: currentText, turnId });
415
431
  }
416
432
  }
417
433
  );
418
434
  } catch (err) {
435
+ const errorUsage = { input: 0, output: 0 };
419
436
  const errorTurn = {
420
437
  id: turnId,
421
438
  runId: ctx.runId,
422
439
  role: "assistant",
423
440
  content: currentText ? [{ type: "text", text: currentText }] : [],
424
- usage: { input: 0, output: 0 },
441
+ usage: errorUsage,
425
442
  createdAt: Date.now()
426
443
  };
427
444
  ctx.turns.push(errorTurn);
428
- await ctx.hooks.callHook("turn:after", { turn, turnId, usage: errorTurn.usage, message: errorTurn });
445
+ await ctx.hooks.callHook("turn:after", { turn, turnId, usage: errorUsage, message: errorTurn });
429
446
  throw err;
430
447
  }
431
448
  if (currentText) {
432
- await ctx.hooks.callHook("stream:end", { text: currentText, turnId, blockIndex });
433
- blockIndex++;
449
+ await ctx.hooks.callHook("stream:end", { text: currentText, turnId });
434
450
  }
435
451
  const assistantTurn = {
436
452
  id: turnId,
@@ -447,7 +463,7 @@ async function executeTurn(ctx, turn) {
447
463
  const outputSpec = {
448
464
  name: "__output__",
449
465
  description: "Return the final structured output matching the required schema.",
450
- input_schema: ctx.schema
466
+ inputSchema: ctx.schema
451
467
  };
452
468
  const schemaResult = await ctx.provider.stream(
453
469
  {
@@ -503,16 +519,16 @@ async function executeSingleTool(ctx, call) {
503
519
  const gateCtx = { name: call.name, input: call.input, block: false, reason: "Tool execution was blocked" };
504
520
  await ctx.hooks.callHook("tool:gate", gateCtx);
505
521
  if (gateCtx.block) {
506
- return { result: { id: call.id, content: `Blocked: ${gateCtx.reason}` }, steered: false };
522
+ return { result: { id: call.id, content: `Blocked: ${gateCtx.reason}` } };
507
523
  }
508
524
  if (!toolDef) {
509
525
  const err = new Error(`Unknown tool: ${call.name}`);
510
526
  await ctx.hooks.callHook("tool:error", { name: call.name, input: call.input, error: err });
511
- return { result: { id: call.id, content: `Tool error: ${err.message}` }, steered: false };
527
+ return { result: { id: call.id, content: `Tool error: ${err.message}` } };
512
528
  }
513
- const validation = validateToolArgs(call.input, toolDef.spec.input_schema);
529
+ const validation = validateToolArgs(call.input, toolDef.spec.inputSchema);
514
530
  if (!validation.valid) {
515
- return { result: { id: call.id, content: `Validation error: ${validation.error}` }, steered: false };
531
+ return { result: { id: call.id, content: `Validation error: ${validation.error}` } };
516
532
  }
517
533
  await ctx.hooks.callHook("tool:before", { name: call.name, input: call.input });
518
534
  let output;
@@ -537,7 +553,7 @@ async function executeSingleTool(ctx, call) {
537
553
  output = transformCtx.result;
538
554
  isError = transformCtx.isError;
539
555
  await ctx.hooks.callHook("tool:after", { name: call.name, input: call.input, result: output });
540
- return { result: { id: call.id, content: output }, steered: false };
556
+ return { result: { id: call.id, content: output } };
541
557
  }
542
558
  async function executeToolsSequential(ctx, toolCalls) {
543
559
  const results = [];
@@ -583,7 +599,7 @@ async function executeToolsParallel(ctx, toolCalls) {
583
599
  var noTools = { name: "none", system: "You are a helpful assistant.", tools: {} };
584
600
  function resolveBehavior(harnessBehavior, agentBehavior, runBehavior) {
585
601
  return {
586
- toolExecution: runBehavior?.toolExecution ?? agentBehavior?.toolExecution ?? harnessBehavior?.toolExecution ?? "sequential",
602
+ toolExecution: runBehavior?.toolExecution ?? agentBehavior?.toolExecution ?? harnessBehavior?.toolExecution ?? "parallel",
587
603
  maxTurns: runBehavior?.maxTurns ?? agentBehavior?.maxTurns ?? harnessBehavior?.maxTurns,
588
604
  maxTokens: runBehavior?.maxTokens ?? agentBehavior?.maxTokens ?? harnessBehavior?.maxTokens,
589
605
  thinkingBudget: runBehavior?.thinkingBudget ?? agentBehavior?.thinkingBudget ?? harnessBehavior?.thinkingBudget,
@@ -614,13 +630,23 @@ function createAgent({ harness: harnessOption, provider, behavior: agentBehavior
614
630
  if (running) {
615
631
  throw new Error("Agent is already running. Use steer() or followUp() to queue messages, or waitForIdle().");
616
632
  }
633
+ const hasSessionTurns = session && session.turns.length > 0;
634
+ if (!options.prompt && !hasSessionTurns) {
635
+ throw new Error("prompt is required when no session with existing turns is provided");
636
+ }
637
+ if (!options.prompt && hasSessionTurns) {
638
+ const lastTurn = session.turns.at(-1);
639
+ if (lastTurn && lastTurn.role !== "user") {
640
+ throw new Error("cannot resume without prompt: last session turn must be a user message");
641
+ }
642
+ }
617
643
  running = true;
618
644
  abortController = new AbortController();
619
645
  const runId = `run_${++runCounter}`;
620
646
  session?.startRun(runId, options.prompt);
621
647
  if (session) {
622
648
  await session.updateStatus("running");
623
- await hooks.callHook("session:start", { sessionId: session.id, runId, prompt: options.prompt });
649
+ await hooks.callHook("session:start", { sessionId: session.id, runId, prompt: options.prompt ?? "" });
624
650
  }
625
651
  if (options.signal) {
626
652
  if (options.signal.aborted) {
@@ -698,12 +724,12 @@ ${skillsCatalog}`;
698
724
  (t) => ({
699
725
  name: t.spec.name,
700
726
  description: t.spec.description || "",
701
- input_schema: t.spec.input_schema
727
+ inputSchema: t.spec.inputSchema
702
728
  })
703
729
  );
704
730
  const formattedTools = toolSpecs.length > 0 ? provider.formatTools(toolSpecs) : [];
705
731
  const turns = [];
706
- const isResume = session && session.turns.length > 0 && session.runs.length > 0;
732
+ const isResume = session && session.turns.length > 0 && (session.runs.length > 0 || !options.prompt);
707
733
  if (isResume) {
708
734
  turns.push(...session.turns);
709
735
  }
@@ -727,14 +753,16 @@ ${skillsCatalog}`;
727
753
  createdAt: Date.now()
728
754
  });
729
755
  }
730
- const promptMsg = provider.userMessage(options.prompt, options.images);
731
- turns.push({
732
- id: crypto.randomUUID(),
733
- runId,
734
- role: promptMsg.role,
735
- content: promptMsg.content,
736
- createdAt: Date.now()
737
- });
756
+ if (options.prompt) {
757
+ const promptMsg = provider.userMessage(options.prompt, options.images);
758
+ turns.push({
759
+ id: crypto.randomUUID(),
760
+ runId,
761
+ role: promptMsg.role,
762
+ content: promptMsg.content,
763
+ createdAt: Date.now()
764
+ });
765
+ }
738
766
  conversationTurns = turns;
739
767
  let lastPersistedTurnCount = isResume ? session.turns.length : 0;
740
768
  const unregisterSessionSync = session ? hooks.hook("turn:after", async () => {
@@ -945,7 +973,7 @@ function createSpawnTool(options = {}) {
945
973
  spec: {
946
974
  name: "spawn",
947
975
  description: "Spawn a sub-agent to work on a specific task. The sub-agent runs independently with its own tool access and returns its final response. Use this to delegate work, parallelize tasks, or isolate concerns.",
948
- input_schema: {
976
+ inputSchema: {
949
977
  type: "object",
950
978
  properties: {
951
979
  task: {
@@ -1020,7 +1048,7 @@ var writeFile2 = {
1020
1048
  spec: {
1021
1049
  name: "write_file",
1022
1050
  description: "Write content to a file. Creates parent directories if needed.",
1023
- input_schema: {
1051
+ inputSchema: {
1024
1052
  type: "object",
1025
1053
  properties: {
1026
1054
  path: { type: "string", description: "Relative file path" },
@@ -1041,6 +1069,7 @@ export {
1041
1069
  createSandboxContext,
1042
1070
  validateToolArgs,
1043
1071
  createAgent,
1072
+ createInteractionTool,
1044
1073
  listFiles,
1045
1074
  readFile,
1046
1075
  shell,
@@ -51,7 +51,7 @@ async function connectMcpServers(configs, _clientFactory, hooks) {
51
51
  spec: {
52
52
  name: namespacedName,
53
53
  description: tool.description || "",
54
- input_schema: tool.inputSchema ?? { type: "object", properties: {} }
54
+ inputSchema: tool.inputSchema ?? { type: "object", properties: {} }
55
55
  },
56
56
  execute: async (input, _ctx) => {
57
57
  await hooks?.callHook("mcp:tool:before", { server: config.name, tool: tool.name, input });
@@ -124,7 +124,7 @@ function toOAIMessages(system, messages) {
124
124
  function formatTools(tools) {
125
125
  return tools.map((t) => ({
126
126
  type: "function",
127
- function: { name: t.name, description: t.description, parameters: t.input_schema }
127
+ function: { name: t.name, description: t.description, parameters: t.inputSchema }
128
128
  }));
129
129
  }
130
130
  function userMessage(content, images) {
@@ -307,7 +307,7 @@ async function createSession(options = {}) {
307
307
  data.runs.push({
308
308
  id: runId,
309
309
  startedAt: Date.now(),
310
- prompt,
310
+ prompt: prompt ?? "",
311
311
  status: "running"
312
312
  });
313
313
  touch();
@@ -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-C7X6yygt.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-CPOBJlcn.js';
3
3
  import './types-CKXAp41h.js';
4
4
  import '@modelcontextprotocol/sdk/client/index.js';
package/dist/harnesses.js CHANGED
@@ -3,9 +3,9 @@ import {
3
3
  basic_default,
4
4
  defineHarness,
5
5
  noTools
6
- } from "./chunk-JR4QNFMD.js";
7
- import "./chunk-SKLAWY7O.js";
8
- import "./chunk-YTZOORAP.js";
6
+ } from "./chunk-BDBQ5MIB.js";
7
+ import "./chunk-KWNFSVVE.js";
8
+ import "./chunk-NNMWWSBY.js";
9
9
  import "./chunk-4C6Y56CC.js";
10
10
  export {
11
11
  basic_default as basic,
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-C7X6yygt.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-CPOBJlcn.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, S as SpawnToolOptions, a as SpawnToolState, c as createSpawnTool, s as spawn } from './spawn-CIxEFPrs.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';
7
7
  import 'hookable';
8
8
  import '@modelcontextprotocol/sdk/client/index.js';
9
9
 
@@ -30,7 +30,7 @@ declare function createProcessContext(config?: SpawnConfig): ExecutionContext;
30
30
  /**
31
31
  * Zod v4 integration helper.
32
32
  *
33
- * Normalizes the output of z.toJsonSchema() for use as ToolSpec.input_schema.
33
+ * Normalizes the output of z.toJsonSchema() for use as ToolSpec.inputSchema.
34
34
  * Zod is an optional peer dependency — consumers call z.toJsonSchema() themselves.
35
35
  *
36
36
  * Usage:
@@ -40,7 +40,7 @@ declare function createProcessContext(config?: SpawnConfig): ExecutionContext;
40
40
  */
41
41
  /**
42
42
  * Normalize a JSON Schema (e.g. from zod v4's z.toJsonSchema()) for use
43
- * as a ToolSpec.input_schema.
43
+ * as a ToolSpec.inputSchema.
44
44
  *
45
45
  * Strips the $schema key that some providers reject.
46
46
  */
package/dist/index.js CHANGED
@@ -1,32 +1,33 @@
1
1
  import {
2
2
  defineHarness,
3
3
  noTools
4
- } from "./chunk-JR4QNFMD.js";
4
+ } from "./chunk-BDBQ5MIB.js";
5
5
  import {
6
6
  createAgent,
7
7
  createDockerContext,
8
+ createInteractionTool,
8
9
  createProcessContext,
9
10
  createSandboxContext,
10
11
  createSpawnTool,
11
12
  spawn
12
- } from "./chunk-SKLAWY7O.js";
13
+ } from "./chunk-KWNFSVVE.js";
13
14
  import {
14
15
  connectMcpServers
15
- } from "./chunk-YTZOORAP.js";
16
+ } from "./chunk-NNMWWSBY.js";
16
17
  import {
17
18
  createMemoryStore,
18
19
  createRemoteStore,
19
20
  createSession,
20
21
  createSqliteStore,
21
22
  loadSession
22
- } from "./chunk-XT7QBZ47.js";
23
+ } from "./chunk-V4PBD7LE.js";
23
24
  import {
24
25
  autoDetectAndConvert,
25
26
  fromAnthropic,
26
27
  fromOpenAI,
27
28
  toAnthropic,
28
29
  toOpenAI
29
- } from "./chunk-LS57GDAV.js";
30
+ } from "./chunk-UHCWNQGG.js";
30
31
  import {
31
32
  defineSkill
32
33
  } from "./chunk-CFLC2I7D.js";
@@ -53,6 +54,7 @@ export {
53
54
  connectMcpServers,
54
55
  createAgent,
55
56
  createDockerContext,
57
+ createInteractionTool,
56
58
  createMemoryStore,
57
59
  createProcessContext,
58
60
  createRemoteStore,
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-C7X6yygt.js';
2
+ export { M as McpConnection, j as McpServerConfig, F as connectMcpServers, a3 as resultToString } from './agent-CPOBJlcn.js';
3
3
  import '@modelcontextprotocol/sdk/client/index.js';
4
4
  import './types-CKXAp41h.js';
package/dist/mcp.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  connectMcpServers,
3
3
  resultToString
4
- } from "./chunk-YTZOORAP.js";
4
+ } from "./chunk-NNMWWSBY.js";
5
5
  export {
6
6
  connectMcpServers,
7
7
  resultToString
@@ -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-C7X6yygt.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-CPOBJlcn.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-LS57GDAV.js";
11
+ } from "./chunk-UHCWNQGG.js";
12
12
 
13
13
  // src/providers/anthropic.ts
14
14
  import { existsSync, readFileSync } from "fs";
@@ -59,7 +59,7 @@ function anthropic(anthropicParams) {
59
59
  return tools.map((t) => ({
60
60
  name: t.name,
61
61
  description: t.description,
62
- input_schema: t.input_schema
62
+ input_schema: t.inputSchema
63
63
  }));
64
64
  },
65
65
  userMessage(content, images) {
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-C7X6yygt.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-CPOBJlcn.js';
2
2
  import 'hookable';
3
3
  import './types-CKXAp41h.js';
4
4
  import '@modelcontextprotocol/sdk/client/index.js';
package/dist/session.js CHANGED
@@ -4,14 +4,14 @@ import {
4
4
  createSession,
5
5
  createSqliteStore,
6
6
  loadSession
7
- } from "./chunk-XT7QBZ47.js";
7
+ } from "./chunk-V4PBD7LE.js";
8
8
  import {
9
9
  autoDetectAndConvert,
10
10
  fromAnthropic,
11
11
  fromOpenAI,
12
12
  toAnthropic,
13
13
  toOpenAI
14
- } from "./chunk-LS57GDAV.js";
14
+ } from "./chunk-UHCWNQGG.js";
15
15
  export {
16
16
  autoDetectAndConvert,
17
17
  createMemoryStore,
@@ -1,4 +1,41 @@
1
- import { i as HarnessConfig, e as AgentStats, v as ToolDef } from './agent-C7X6yygt.js';
1
+ import { v as ToolDef, i as HarnessConfig, e as AgentStats } from './agent-CPOBJlcn.js';
2
+
3
+ /**
4
+ * Interaction tool — lets the agent request structured input from the outside world.
5
+ *
6
+ * Not included in any harness by default. Add it explicitly:
7
+ *
8
+ * import { createInteractionTool } from 'zidane'
9
+ *
10
+ * const askUser = createInteractionTool({
11
+ * schema: { type: 'object', properties: { question: { type: 'string' } }, required: ['question'] },
12
+ * onRequest: async (payload) => {
13
+ * const answer = await promptUser(payload.question)
14
+ * return { answer }
15
+ * },
16
+ * })
17
+ *
18
+ * const harness = defineHarness({ name: 'interactive', tools: { ...basicTools, ask_user: askUser } })
19
+ */
20
+
21
+ interface InteractionToolOptions {
22
+ /** JSON Schema for the request payload the model sends */
23
+ schema: Record<string, unknown>;
24
+ /** Tool name (default: 'interaction') */
25
+ name?: string;
26
+ /** Tool description shown to the model */
27
+ description?: string;
28
+ /** Called when the model invokes this tool. Receives the validated payload, returns data for the model. */
29
+ onRequest: (payload: Record<string, unknown>) => Promise<Record<string, unknown> | string>;
30
+ }
31
+ /**
32
+ * Create an interaction tool that lets the agent request structured input.
33
+ *
34
+ * The model calls this tool with a payload matching the schema.
35
+ * `onRequest` is called with the payload and should return the response
36
+ * (string or object) that gets sent back to the model as the tool result.
37
+ */
38
+ declare function createInteractionTool(options: InteractionToolOptions): ToolDef;
2
39
 
3
40
  /**
4
41
  * Spawn tool — create sub-agents from a parent agent.
@@ -59,4 +96,4 @@ declare function createSpawnTool(options?: SpawnToolOptions): ToolDef & SpawnToo
59
96
  */
60
97
  declare const spawn: ToolDef & SpawnToolState;
61
98
 
62
- export { type ChildAgent as C, type SpawnToolOptions as S, type SpawnToolState as a, createSpawnTool as c, spawn as s };
99
+ export { type ChildAgent as C, type InteractionToolOptions as I, type SpawnToolOptions as S, type SpawnToolState as a, createSpawnTool as b, createInteractionTool as c, spawn as s };
package/dist/tools.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { v as ToolDef } from './agent-C7X6yygt.js';
2
- export { C as ChildAgent, S as SpawnToolOptions, a as SpawnToolState, c as createSpawnTool, s as spawn } from './spawn-CIxEFPrs.js';
3
- export { V as ValidationResult, v as validateToolArgs } from './validation-CwSuvOKf.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-CK08YMPC.js';
2
+ import { v as ToolDef } from './agent-CPOBJlcn.js';
3
+ export { V as ValidationResult, v as validateToolArgs } from './validation-DOY_k7lW.js';
4
4
  import 'hookable';
5
5
  import './types-CKXAp41h.js';
6
6
  import '@modelcontextprotocol/sdk/client/index.js';
package/dist/tools.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import {
2
+ createInteractionTool,
2
3
  createSpawnTool,
3
4
  listFiles,
4
5
  readFile,
@@ -6,10 +7,11 @@ import {
6
7
  spawn,
7
8
  validateToolArgs,
8
9
  writeFile
9
- } from "./chunk-SKLAWY7O.js";
10
- import "./chunk-YTZOORAP.js";
10
+ } from "./chunk-KWNFSVVE.js";
11
+ import "./chunk-NNMWWSBY.js";
11
12
  import "./chunk-4C6Y56CC.js";
12
13
  export {
14
+ createInteractionTool,
13
15
  createSpawnTool,
14
16
  listFiles,
15
17
  readFile,
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-C7X6yygt.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-CPOBJlcn.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, S as SpawnToolOptions, a as SpawnToolState } from './spawn-CIxEFPrs.js';
5
- export { V as ValidationResult } from './validation-CwSuvOKf.js';
4
+ export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState } from './spawn-CK08YMPC.js';
5
+ export { V as ValidationResult } from './validation-DOY_k7lW.js';
6
6
  import 'hookable';
7
7
  import '@modelcontextprotocol/sdk/client/index.js';
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Simple tool argument validation against JSON Schema-style input_schema.
2
+ * Simple tool argument validation against JSON Schema-style inputSchema.
3
3
  * Checks required fields are present; type coercion is left to the tools themselves.
4
4
  */
5
5
  interface ValidationResult {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zidane",
3
- "version": "1.6.1",
3
+ "version": "1.6.4",
4
4
  "description": "an agent that goes straight to the goal",
5
5
  "type": "module",
6
6
  "private": false,
@@ -59,7 +59,8 @@
59
59
  "lint": "eslint .",
60
60
  "lint:fix": "eslint . --fix",
61
61
  "test": "bun test",
62
- "release": "bumpp"
62
+ "release": "bumpp",
63
+ "typecheck": "tsc --noEmit"
63
64
  },
64
65
  "dependencies": {
65
66
  "@anthropic-ai/sdk": "^0.80.0",
@@ -84,6 +85,7 @@
84
85
  "bumpp": "^11.0.1",
85
86
  "eslint": "^10.0.3",
86
87
  "jiti": "^2.6.1",
87
- "tsup": "^8.5.1"
88
+ "tsup": "^8.5.1",
89
+ "typescript": "~5.9.3"
88
90
  }
89
91
  }