zidane 5.9.12 → 5.9.13

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
@@ -18,7 +18,7 @@ Small, hookable core with sensible defaults. Three principles guide the design:
18
18
 
19
19
  Everything below is in service of those:
20
20
 
21
- - 🧠 **Providers** — Anthropic, OpenAI Codex, OpenRouter, Cerebras, plus `openaiCompat` (Baseten, Fireworks, Groq, local). OAuth + API key with auto-refresh.
21
+ - 🧠 **Providers** — Anthropic, OpenAI Codex, OpenRouter, Cerebras, Arcee, local LLMs, plus `openaiCompat` (Baseten, Fireworks, Groq). OAuth + API key with auto-refresh.
22
22
  - 🪝 **Hookable turn loop** — every text/thinking delta, tool call, MCP, session, skill, spawn, OAuth, validation, and budget event is observable and (mostly) mutable.
23
23
  - 🛠️ **First-class tools** — `shell`, `read_file`, `write_file`, `edit`, `multi_edit`, `glob`, `grep`, `spawn`, human-in-the-loop, plus any [MCP](https://modelcontextprotocol.io) server. Per-call gates, arg auto-coerce, hallucinated-tool fallback, error rewriting. Lazy MCP disclosure via `tool_search`. Optional `todowrite` / `todoread` for persistent task checkpointing across prompts.
24
24
  - 🧮 **Per-tool concurrency** — every `ToolDef` carries `isConcurrencySafe` (default `false`); the dispatcher fans safe siblings out in parallel and barriers unsafe ones. Order is preserved at yield time. Cap via `behavior.maxConcurrentTools`.
@@ -121,7 +121,9 @@ Precedence: `run.behavior` > `agent.behavior` > defaults.
121
121
  bun start \
122
122
  --prompt "your task" \ # required
123
123
  --model claude-opus-4-7 \ # model id
124
- --provider anthropic \ # anthropic | openai | openrouter | cerebras
124
+ --provider anthropic \ # anthropic | openai | openrouter | cerebras | arcee | local | openai-compat
125
+ --base-url http://localhost:8000/v1 \ # local/openai-compat endpoint
126
+ --header "X-Route: dev" \ # extra header for local/openai-compat
125
127
  --preset basic \ # preset name
126
128
  --system "be concise" \ # system prompt
127
129
  --thinking off \ # off | minimal | low | medium | high
@@ -129,6 +131,8 @@ bun start \
129
131
  --mcp '{"name":"fs","transport":"stdio","command":"npx","args":["-y","@modelcontextprotocol/server-filesystem","."]}'
130
132
  ```
131
133
 
134
+ For `local` / `openai-compat`, `--base-url`, `--api-key-env`, `--headers-env`, `--header`, `--vision`, `--image-in-tool-result`, `--temperature`, and `--seed` apply; hosted providers ignore them.
135
+
132
136
  `bun start --restate` runs the same start flow through a local Restate endpoint for durable-execution demos and fixture testing. It starts the service, probes readiness, registers the deployment, invokes `zidane-start-agent`, and exposes `run` / `status` / `history` handlers. See [docs/RESTATE.md](./docs/RESTATE.md) for production wiring and the advanced ReState flags.
133
137
 
134
138
  ## Providers
@@ -164,20 +168,22 @@ anthropic({
164
168
 
165
169
  Fallback: `params.apiKey` > `params.access` > `ANTHROPIC_API_KEY` env > `.credentials.json`. `extraBetas` merge with OAuth defaults and de-dupe. `contextManagement` is sent as `context_management`; pair with the matching beta. Non-Anthropic equivalent: `behavior.compactStrategy: 'tail'`. Declares `capabilities.nativeWebSearch`: when the `web_search` tool is registered, the provider swaps in Anthropic's server-side `web_search_20250305` and streams results via `onServerToolUse` / `onServerToolResult`.
166
170
 
167
- `extraBodyParams` passes un-typed Messages API fields through (factory options win on collision). Use when Anthropic ships a beta before zidane has a knob. `openaiCompat` accepts the same field (e.g. `reasoning_effort`, `metadata`, OpenRouter `provider` routing).
171
+ `extraHeaders` merges request headers for proxies/gateways; reserved Anthropic headers still win on collision. `extraBodyParams` passes un-typed Messages API fields through (factory options win on collision). Use when Anthropic ships a beta before zidane has a knob. `openaiCompat` accepts the same field (e.g. `reasoning_effort`, `metadata`, OpenRouter `provider` routing).
168
172
 
169
- ### OpenRouter / OpenAI / Cerebras
173
+ ### OpenRouter / OpenAI / Cerebras / Arcee / Local
170
174
 
171
175
  ```ts
172
- import { openrouter, openai, cerebras } from 'zidane/providers'
176
+ import { openrouter, openai, cerebras, arcee, local } from 'zidane/providers'
173
177
 
174
178
  openrouter({ apiKey: 'sk-or-...', defaultModel: 'google/gemini-pro' })
175
179
  openai() // OpenAI Codex OAuth
176
180
  openai({ access: 'eyJ...', refresh: '...', expires: Date.now() + 3600_000, accountId: 'acct_123' })
177
181
  cerebras({ apiKey: 'csk-...', defaultModel: 'zai-glm-4.7' })
182
+ arcee({ apiKey: 'arcee-...', defaultModel: 'trinity-large-thinking' })
183
+ local({ baseURL: 'http://localhost:8000/v1', defaultModel: 'qwen3-coder' })
178
184
  ```
179
185
 
180
- Fallbacks: `params.apiKey` > `params.access` (Codex) > `<PROVIDER>_API_KEY` env > `.credentials.json` (Codex). Pass full OAuth fields on `openai()` to auto-refresh without reading `.credentials.json`.
186
+ Fallbacks: `params.apiKey` > `params.access` (Codex) > `<PROVIDER>_API_KEY` env > `.credentials.json` (Codex). `local` uses `LOCAL_LLM_BASE_URL`, `LOCAL_LLM_API_KEY`, and `LOCAL_LLM_DEFAULT_MODEL`. Pass full OAuth fields on `openai()` to auto-refresh without reading `.credentials.json`.
181
187
 
182
188
  ### OpenAI-compatible (custom endpoints)
183
189
 
@@ -196,7 +202,7 @@ openaiCompat({
196
202
  })
197
203
  ```
198
204
 
199
- `openrouter` and `cerebras` are thin wrappers with vendor defaults pinned. Use `openaiCompat` directly for new backends.
205
+ `openrouter`, `cerebras`, `arcee`, and `local` are thin wrappers with vendor/runtime defaults pinned. Use `openaiCompat` directly for new backends.
200
206
 
201
207
  ### Prompt caching
202
208
 
@@ -206,7 +212,7 @@ openaiCompat({
206
212
  |---|---|
207
213
  | `anthropic` | Honored natively. |
208
214
  | `openrouter` | Forwarded; Anthropic + Gemini honor; OpenAI / DeepSeek / Grok / Groq / Moonshot cache automatically and ignore the markers. |
209
- | `openaiCompat` | Opt-in via `cacheBreakpoints: true`. Off by default. |
215
+ | `arcee` / `local` / `openaiCompat` | Off by default for strict OpenAI-compatible schemas; use `openaiCompat({ cacheBreakpoints: true })` only for endpoints that honor `cache_control`. |
210
216
  | `cerebras` | Off. |
211
217
  | `openai` (Codex) | Not affected (pi-ai wire format). |
212
218
 
@@ -238,7 +244,7 @@ await agent.run({ prompt: 'just chat', tools: {} }) // no tools for one run
238
244
 
239
245
  ## Thinking
240
246
 
241
- Named levels or exact budgets. Traces persist as `{ type: 'thinking', text }` blocks and stream via `stream:thinking`. Supported by Anthropic (native) and OpenRouter/Cerebras (`reasoning_content`/`reasoning` SSE fields).
247
+ Named levels or exact budgets. Traces persist as `{ type: 'thinking', text }` blocks and stream via `stream:thinking`. Supported by Anthropic (native) and OpenRouter/Arcee (`reasoning_content`/`reasoning` SSE fields).
242
248
 
243
249
  | Level | Default budget |
244
250
  |---|---|
@@ -312,7 +312,7 @@ Provider semantics:
312
312
  |---|---|
313
313
  | `anthropic` | Breakpoints honored natively. |
314
314
  | `openrouter` | Breakpoints forwarded; Anthropic + Gemini routes honor them, others ignore. |
315
- | `openaiCompat` | Factory-gated via `cacheBreakpoints: boolean` (default **off**). `openrouter` flips it on; bare `openaiCompat` stays off so OpenAI-direct doesn't reject unknown fields. |
315
+ | `arcee` / `local` / `openaiCompat` | Factory-gated via `cacheBreakpoints: boolean` (default **off**). `openrouter` flips it on; Arcee/local/bare `openaiCompat` stay off so strict OpenAI-compatible endpoints don't reject unknown fields. |
316
316
  | `cerebras` | Off (factory doesn't enable breakpoints). |
317
317
  | `openai` (Codex) | Not affected — separate wire format (pi-ai). |
318
318
 
@@ -352,7 +352,7 @@ The built-in profiles (`buildBuildSystem` / `buildPlanSystem` in `zidane/chat`)
352
352
 
353
353
  - `anthropic` — `applyAnthropicCacheBreakpoints(params, originalSystem)` splits string system prompts on the marker. The OAuth path skips the split (the canonical CC prompt occupies `params.system`; the user doctrine lives in an injected user message).
354
354
  - `openaiCompat` — `toOAIMessages` strips the marker; `applyOAICacheBreakpoints(messages, originalSystem)` splits the leading system message into static + dynamic content parts when caching is on.
355
- - `openai` (Codex), `cerebras`, and any cache-disabled route — marker is collapsed via `renderSystemForWire` so it never reaches the model.
355
+ - `openai` (Codex), `cerebras`, `arcee`, `local`, and any cache-disabled route — marker is collapsed via `renderSystemForWire` so it never reaches the model.
356
356
 
357
357
  ### Cache-break diagnosis
358
358
 
package/docs/CHAT.md CHANGED
@@ -151,7 +151,7 @@ The table below indexes every named export; sections further down dive into the
151
151
  | `project-root` | `findGitRoot(cwd)` — walks upward looking for `.git`, returns absolute path or `null`. Used for session scope tagging + export anchors. |
152
152
  | `prompt-segments` | `splitPromptSegments(text, refs)` → `PromptSegment[]`. GUI maps the same segments to inline-block chip pills. |
153
153
  | `project-user-paths` | `projectUserPaths({ subPath, cwd, home, prefix })` — shared search-order builder for project + user config discovery. Powers `defaultSkillScanPaths` (`'skills'`) and `defaultMcpsConfigPaths` (calls it twice, once per `mcps.json` / `mcp.json`); the same convention extends to any new discovery surface. |
154
- | `providers` | `ProviderDescriptor` registry + helpers — `BUILTIN_PROVIDERS` (`anthropicDescriptor`, `openaiDescriptor`, `openrouterDescriptor`, `cerebrasDescriptor`, `localDescriptor`), `modelsForDescriptor`, `getModelInfo`, `getContextWindow`, `effectiveContextWindow`, `modelSupportsReasoning`, `OUTPUT_RESERVE_TOKENS`, `credKeyOf`, `piIdOf`. `cursorDescriptor` is exported but NOT in `BUILTIN_PROVIDERS` (OAuth works, inference not wired). See **Local provider**. |
154
+ | `providers` | `ProviderDescriptor` registry + helpers — `BUILTIN_PROVIDERS` (`anthropicDescriptor`, `openaiDescriptor`, `openrouterDescriptor`, `cerebrasDescriptor`, `arceeDescriptor`, `localDescriptor`), `modelsForDescriptor`, `getModelInfo`, `getContextWindow`, `effectiveContextWindow`, `modelSupportsReasoning`, `OUTPUT_RESERVE_TOKENS`, `credKeyOf`, `piIdOf`. `cursorDescriptor` is exported but NOT in `BUILTIN_PROVIDERS` (OAuth works, inference not wired). See **Local provider**. |
155
155
  | `safe-mode` | Per-project safelist + matchers — `IMPLICITLY_SAFE_TOOLS`, `suggestSafelistEntry`, `addToSafelist`, `getSafelist`, `isOnSafelist`, `matchesSafelistEntry`, `readProjects`, `writeProjects`, `projectsFilePath`. |
156
156
  | `safe-mode-context` | `SafeModeProvider` owns a FIFO approval queue. `useSafeModeQueue()` returns the live array; `useSafeModeActions()` returns stable `{ requestApproval, resolveHead, denyAll }`. |
157
157
  | `session-export` | `renderSession`, `resolveSessionExportTarget`, `writeSessionExport`, `SessionExportFormat`, `SessionExportAnchor`, `SessionExportTarget`. |
@@ -186,7 +186,7 @@ resolveConfig({
186
186
  projectDb: false,
187
187
  cwd: process.cwd(), // override the project-root walk root
188
188
 
189
- // Provider registry — defaults to BUILTIN_PROVIDERS (Anthropic + OpenAI + OpenRouter + Cerebras).
189
+ // Provider registry — defaults to BUILTIN_PROVIDERS (Anthropic + OpenAI + OpenRouter + Cerebras + Arcee + Local).
190
190
  providers: { ...BUILTIN_PROVIDERS, mine: myDescriptor },
191
191
 
192
192
  // Agent registry — defaults to BUILTIN_AGENTS (Build + Plan).
package/docs/SKILL.md CHANGED
@@ -11,7 +11,7 @@ Minimal TypeScript agent loop built with Bun. Streams from an LLM, executes tool
11
11
 
12
12
  ## Core Concepts
13
13
 
14
- - **Provider** — LLM backend (Anthropic, OpenAI Codex, OpenRouter, Cerebras). Streaming, format conversion, tool wiring. Anthropic + Codex support OAuth.
14
+ - **Provider** — LLM backend (Anthropic, OpenAI Codex, OpenRouter, Cerebras, Arcee, local LLMs). Streaming, format conversion, tool wiring. Anthropic + Codex support OAuth.
15
15
  - **Preset** — `Partial<AgentOptions>` (tools, system, aliases, mcpServers, skills, behavior, hooks). `basicTools` ships `shell`, `readFile`, `writeFile`, `listFiles`, `edit`, `multiEdit`; the `basic` preset adds `spawn`. Override `tools: {}` for untrusted prompts.
16
16
  - **Agent** — `createAgent()` returns one. Turn loop: prompt → LLM → tool calls → tool results → … until done or `maxTurns`.
17
17
  - **Session** — Optional persistent turn history. Written incrementally.
@@ -85,11 +85,12 @@ Precedence: `run.behavior` > `agent.behavior` > defaults. `prompt` is required u
85
85
  All providers accept runtime keys via params. Env vars are fallbacks. OAuth credentials are read from `.credentials.json` and auto-refreshed (populate via `bun run auth`).
86
86
 
87
87
  ```ts
88
- import { anthropic, openai, openrouter, cerebras, openaiCompat } from 'zidane'
88
+ import { anthropic, openai, openrouter, cerebras, arcee, local, openaiCompat } from 'zidane'
89
89
 
90
90
  anthropic({ apiKey: 'sk-ant-...', defaultModel: 'claude-opus-4-8' })
91
91
  anthropic({ access: 'sk-ant-oat-...', refresh: '...', expires: 1234567890 }) // OAuth
92
92
  anthropic({ apiKey: 'sk-ant-...', baseURL: 'https://gateway.corp/anthropic' }) // full proxy
93
+ anthropic({ apiKey: 'sk-ant-...', extraHeaders: { 'X-Route': 'claude-prod' } }) // proxy headers
93
94
  anthropic({ // first-party betas
94
95
  apiKey: 'sk-ant-...',
95
96
  extraBetas: ['context-management-2025-06-27', 'token-efficient-tools-2026-03-28'],
@@ -105,6 +106,8 @@ anthropic({ /
105
106
  openai({ apiKey: 'sk-...', defaultModel: 'gpt-5.5' }) // OpenAI Codex (OAuth too)
106
107
  openrouter({ apiKey: 'sk-or-...', defaultModel: 'google/gemini-pro' })
107
108
  cerebras({ apiKey: 'csk-...', defaultModel: 'zai-glm-4.7' })
109
+ arcee({ apiKey: 'arcee-...', defaultModel: 'trinity-large-thinking' })
110
+ local({ baseURL: 'http://localhost:8000/v1', defaultModel: 'qwen3-coder' })
108
111
 
109
112
  // Public factory for any OpenAI-compatible endpoint:
110
113
  openaiCompat({
@@ -115,9 +118,9 @@ openaiCompat({
115
118
  })
116
119
  ```
117
120
 
118
- Provider params types: `AnthropicParams`, `OpenAIParams`, `OpenRouterParams`, `CerebrasParams`, `OpenAICompatParams` — exported from `zidane`.
121
+ Provider params types: `AnthropicParams`, `OpenAIParams`, `OpenRouterParams`, `CerebrasParams`, `ArceeParams`, `LocalParams`, `OpenAICompatParams` — exported from `zidane`.
119
122
 
120
- `openrouter` and `cerebras` are thin wrappers over `openaiCompat` with vendor defaults pinned. For new OAI-compatible backends (Baseten, Fireworks, Groq, local LM servers), use `openaiCompat` directly.
123
+ `openrouter`, `cerebras`, `arcee`, and `local` are thin wrappers over `openaiCompat` with vendor/runtime defaults pinned. For new OAI-compatible backends (Baseten, Fireworks, Groq), use `openaiCompat` directly.
121
124
 
122
125
  ### Vision + image tool results
123
126
 
@@ -152,7 +155,7 @@ Flatten via `toolResultToText(result)`. MCP image blocks are auto-normalized via
152
155
  |---|---|
153
156
  | `anthropic` | Honored natively. |
154
157
  | `openrouter` | Forwarded to Anthropic + Gemini routes; ignored by OpenAI / DeepSeek / Grok / Groq / Moonshot (those cache automatically). |
155
- | `openaiCompat` | Opt-in via `cacheBreakpoints: true`. Off by default so strict-schema endpoints don't reject unknown fields. |
158
+ | `arcee` / `local` / `openaiCompat` | Off by default so strict-schema endpoints don't reject unknown fields. Use `openaiCompat({ cacheBreakpoints: true })` only for hosts that honor `cache_control`. |
156
159
  | `cerebras` | Off. |
157
160
  | `openai` (Codex) | Not affected (pi-ai wire format). |
158
161
 
@@ -857,6 +860,7 @@ createSandboxContext(myProvider) // implement SandboxProvider (E2B, Rivet, …)
857
860
  | `FileMapAdapter` | `{ get, save, delete }` — host-SDK seam for `createFileMapStore`. |
858
861
  | `TracingHooksOptions` | `createTracingHooks` config (`startSpan`, `namespace?`). |
859
862
  | `OpenAICompatParams` | `openaiCompat()` config (apiKey, baseURL, authHeader, extraHeaders, capabilities, cacheBreakpoints). |
863
+ | `ArceeParams` / `LocalParams` | OpenAI-compatible wrapper configs for Arcee Platform and self-hosted local endpoints. |
860
864
  | `ValidationResult` | `{ valid, error?, coercedInput?, coercions?, droppedItems? }` — `validateToolArgs` output. `droppedItems` is keyed by field name and reports the original indexes of items dropped during recursive array validation. |
861
865
  | `AgentHookMap` | `{ [event]: handler \| handler[] }` — agent-lifetime hooks on `AgentOptions.hooks`. |
862
866
  | `RunHookMap` | Same shape, per-run scope (`agent.run({ hooks })`); handlers auto-detach. |
@@ -885,7 +889,7 @@ src/
885
889
  zod.ts zodToJsonSchema (v4)
886
890
  auth.ts OAuth login CLI
887
891
  start.ts CLI entrypoint
888
- providers/ anthropic, openai (Codex), openrouter, cerebras, openaiCompat + oauth helpers
892
+ providers/ anthropic, openai (Codex), openrouter, cerebras, arcee, local, openaiCompat + oauth helpers
889
893
  presets/ basic, basicTools, definePreset, composePresets
890
894
  tools/ Built-ins + skills tools + validation (auto-coerce)
891
895
  session/ memory, sqlite, remote, file-map + converters
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zidane",
3
- "version": "5.9.12",
3
+ "version": "5.9.13",
4
4
  "description": "an agent that goes straight to the goal",
5
5
  "type": "module",
6
6
  "private": false,