zidane 5.13.10 → 5.13.12

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.
Files changed (91) hide show
  1. package/dist/acp-cli.js +7 -7
  2. package/dist/acp-cli.js.map +1 -1
  3. package/dist/{acp-BRQvvdnO.js → acp-yQbtu4mo.js} +38 -9
  4. package/dist/acp-yQbtu4mo.js.map +1 -0
  5. package/dist/acp.d.ts +10 -3
  6. package/dist/acp.d.ts.map +1 -1
  7. package/dist/acp.js +2 -2
  8. package/dist/{agent-w6htlFlx.d.ts → agent-NkKgz5Dh.d.ts} +38 -2
  9. package/dist/agent-NkKgz5Dh.d.ts.map +1 -0
  10. package/dist/{auth-nA0ZMTbM.js → auth-CGTf8v1_.js} +2 -2
  11. package/dist/{auth-nA0ZMTbM.js.map → auth-CGTf8v1_.js.map} +1 -1
  12. package/dist/chat/pure.d.ts +3 -3
  13. package/dist/chat.d.ts +6 -6
  14. package/dist/chat.js +3 -3
  15. package/dist/contexts/daytona.d.ts +1 -1
  16. package/dist/contexts/e2b.d.ts +1 -1
  17. package/dist/eval.d.ts +1 -1
  18. package/dist/eval.js +2 -2
  19. package/dist/{headless-0O6HMNBQ.js → headless-CR8Giwdt.js} +6 -6
  20. package/dist/{headless-0O6HMNBQ.js.map → headless-CR8Giwdt.js.map} +1 -1
  21. package/dist/headless.d.ts +1 -1
  22. package/dist/headless.js +1 -1
  23. package/dist/{index-BH0lvT7N.d.ts → index-BFY7mcar.d.ts} +2 -2
  24. package/dist/{index-BH0lvT7N.d.ts.map → index-BFY7mcar.d.ts.map} +1 -1
  25. package/dist/{index-C4sPfyg6.d.ts → index-BgB_425D.d.ts} +43 -3
  26. package/dist/index-BgB_425D.d.ts.map +1 -0
  27. package/dist/index.d.ts +4 -4
  28. package/dist/index.js +10 -10
  29. package/dist/{logger-MCqSKpby.d.ts → logger-LQmSBfD_.d.ts} +2 -2
  30. package/dist/{logger-MCqSKpby.d.ts.map → logger-LQmSBfD_.d.ts.map} +1 -1
  31. package/dist/{login-D5rb4IG8.js → login-DE-_d045.js} +2 -2
  32. package/dist/{login-D5rb4IG8.js.map → login-DE-_d045.js.map} +1 -1
  33. package/dist/{mcp-C_TIj91j.js → mcp-2OGi_NQu.js} +2 -2
  34. package/dist/{mcp-C_TIj91j.js.map → mcp-2OGi_NQu.js.map} +1 -1
  35. package/dist/mcp.d.ts +1 -1
  36. package/dist/mcp.js +1 -1
  37. package/dist/{messages-DEsLGBB9.js → messages-U_87Z7GH.js} +2 -2
  38. package/dist/{messages-DEsLGBB9.js.map → messages-U_87Z7GH.js.map} +1 -1
  39. package/dist/output/stream-json.d.ts +2 -2
  40. package/dist/output/stream-json.js +1 -1
  41. package/dist/output/terminal.d.ts +2 -2
  42. package/dist/{presets-HDIxliiq.js → presets-ylu1ud2o.js} +2 -2
  43. package/dist/{presets-HDIxliiq.js.map → presets-ylu1ud2o.js.map} +1 -1
  44. package/dist/presets.d.ts +2 -2
  45. package/dist/presets.js +1 -1
  46. package/dist/{providers-OBIysrMe.js → providers-DyMPTo51.js} +3 -3
  47. package/dist/{providers-OBIysrMe.js.map → providers-DyMPTo51.js.map} +1 -1
  48. package/dist/providers.d.ts +1 -1
  49. package/dist/providers.js +2 -2
  50. package/dist/{read-state-DH2IuQHX.js → read-state-CLK9yVpm.js} +2 -2
  51. package/dist/{read-state-DH2IuQHX.js.map → read-state-CLK9yVpm.js.map} +1 -1
  52. package/dist/restate.d.ts +88 -3
  53. package/dist/restate.d.ts.map +1 -1
  54. package/dist/restate.js +185 -59
  55. package/dist/restate.js.map +1 -1
  56. package/dist/session/sqlite.d.ts +1 -1
  57. package/dist/{session-BDWZZaYa.js → session-DQ4bEncf.js} +2 -2
  58. package/dist/{session-BDWZZaYa.js.map → session-DQ4bEncf.js.map} +1 -1
  59. package/dist/session.d.ts +1 -1
  60. package/dist/session.js +2 -2
  61. package/dist/skills.d.ts +2 -2
  62. package/dist/{tool-formatters-C7N1Pb1q.d.ts → tool-formatters-DvtGhbJN.d.ts} +2 -2
  63. package/dist/{tool-formatters-C7N1Pb1q.d.ts.map → tool-formatters-DvtGhbJN.d.ts.map} +1 -1
  64. package/dist/tools/fetch-url.d.ts +1 -1
  65. package/dist/tools/web-search.d.ts +1 -1
  66. package/dist/{tools-DhzKzB1y.js → tools-CwwYEeHB.js} +191 -53
  67. package/dist/tools-CwwYEeHB.js.map +1 -0
  68. package/dist/tools.d.ts +3 -3
  69. package/dist/tools.js +3 -3
  70. package/dist/{transcript-anchors-BrweEBIo.js → transcript-anchors-C2UkNvZP.js} +7 -7
  71. package/dist/{transcript-anchors-BrweEBIo.js.map → transcript-anchors-C2UkNvZP.js.map} +1 -1
  72. package/dist/{transcript-anchors-CJsVfcaq.d.ts → transcript-anchors-DFmfOesU.d.ts} +4 -4
  73. package/dist/{transcript-anchors-CJsVfcaq.d.ts.map → transcript-anchors-DFmfOesU.d.ts.map} +1 -1
  74. package/dist/tui.d.ts +3 -3
  75. package/dist/tui.js +8 -8
  76. package/dist/{turn-operations-BtyfLdPi.d.ts → turn-operations-DWUN8cHo.d.ts} +3 -3
  77. package/dist/{turn-operations-BtyfLdPi.d.ts.map → turn-operations-DWUN8cHo.d.ts.map} +1 -1
  78. package/dist/{types-DxHDaqN7.js → types-CyVGdbia.js} +45 -2
  79. package/dist/{types-DxHDaqN7.js.map → types-CyVGdbia.js.map} +1 -1
  80. package/dist/types.d.ts +2 -2
  81. package/dist/types.js +1 -1
  82. package/docs/ACP.md +7 -0
  83. package/docs/ARCHITECTURE.md +1 -1
  84. package/docs/RESTATE.md +36 -11
  85. package/docs/RUN_IN_BACKGROUND.md +4 -6
  86. package/docs/SKILL.md +2 -1
  87. package/package.json +1 -1
  88. package/dist/acp-BRQvvdnO.js.map +0 -1
  89. package/dist/agent-w6htlFlx.d.ts.map +0 -1
  90. package/dist/index-C4sPfyg6.d.ts.map +0 -1
  91. package/dist/tools-DhzKzB1y.js.map +0 -1
package/dist/acp-cli.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env bun
2
- import { b as openaiCompat } from "./messages-DEsLGBB9.js";
2
+ import { b as openaiCompat } from "./messages-U_87Z7GH.js";
3
3
  import { n as createSandboxContext, r as createProcessContext } from "./contexts-DHi8LPCp.js";
4
- import { i as basic_default } from "./presets-HDIxliiq.js";
5
- import "./session-BDWZZaYa.js";
6
- import { f as arcee, i as openai, l as cerebras, p as anthropic, r as openrouter, t as xai, u as baseten } from "./providers-OBIysrMe.js";
7
- import { d as buildStartLocalOptions, f as parseStartArgValues, m as startProviderNames, p as startLocalArgOptions, t as runAcpStdioServer, u as StartUsageError } from "./acp-BRQvvdnO.js";
8
- import { a as readCredentials, b as modelsForDescriptor, i as credentialsPath, n as resolveStorageDirs, p as credKeyOf, t as detectAuth, u as BUILTIN_PROVIDERS } from "./auth-nA0ZMTbM.js";
4
+ import { i as basic_default } from "./presets-ylu1ud2o.js";
5
+ import "./session-DQ4bEncf.js";
6
+ import { f as arcee, i as openai, l as cerebras, p as anthropic, r as openrouter, t as xai, u as baseten } from "./providers-DyMPTo51.js";
7
+ import { d as StartUsageError, f as buildStartLocalOptions, h as startProviderNames, i as withAcpDefaultTools, m as startLocalArgOptions, p as parseStartArgValues, t as runAcpStdioServer } from "./acp-yQbtu4mo.js";
8
+ import { a as readCredentials, b as modelsForDescriptor, i as credentialsPath, n as resolveStorageDirs, p as credKeyOf, t as detectAuth, u as BUILTIN_PROVIDERS } from "./auth-CGTf8v1_.js";
9
9
  import { createDaytonaProvider } from "./contexts/daytona.js";
10
10
  import { createDockerContext } from "./contexts/docker.js";
11
11
  import { createE2BProvider } from "./contexts/e2b.js";
@@ -237,7 +237,7 @@ async function main() {
237
237
  ...registry.defaultModelId ? { defaultModelId: registry.defaultModelId } : {}
238
238
  } : { provider: buildBaseProvider(options) },
239
239
  model: options.model,
240
- preset: resolvePreset(options.preset),
240
+ preset: withAcpDefaultTools(resolvePreset(options.preset)),
241
241
  system: options.system,
242
242
  store,
243
243
  framing: "newline",
@@ -1 +1 @@
1
- {"version":3,"file":"acp-cli.js","names":[],"sources":["../src/acp/credential-bridge.ts","../src/cli-shared.ts","../src/start/options.ts","../src/acp-cli.ts"],"sourcesContent":["/**\n * Bridge the user's existing zidane credential store into the process\n * environment so the ACP agent authenticates with the SAME login the TUI /\n * `zidane auth` already set up — no secrets in the editor's `settings.json`.\n *\n * ACP gives the client (e.g. Zed) no way to forward its own provider API keys\n * to an external agent: provider/auth is agent-owned. The only client-driven\n * channel is the `agent_servers.<name>.env` block, i.e. literal secrets in\n * settings. This bridge removes that need by reading the on-disk store the rest\n * of zidane manages:\n *\n * - OAuth providers (Anthropic / OpenAI Codex / xAI): point\n * `ZIDANE_CREDENTIALS_PATH` at the store so the harness providers read and\n * refresh from it.\n * - API-key providers (OpenRouter / Cerebras / Baseten / Arcee / …): inject\n * the stored key into the provider's env var.\n *\n * Precedence is \"explicit env wins\": an env var already set (e.g. by the\n * editor's `env` block) is never overwritten — the store only FILLS GAPS. The\n * whole bridge no-ops when `ZIDANE_CREDENTIALS_PATH` is already set (the caller\n * is managing credentials explicitly) or when no store file exists (so\n * `~/.credentials.json` from a legacy `bun run auth` keeps working untouched).\n */\n\nimport { existsSync } from 'node:fs'\nimport { credentialsPath, readCredentials } from '../chat/credentials'\nimport { BUILTIN_PROVIDERS, credKeyOf } from '../chat/providers'\nimport { resolveStorageDirs } from '../chat/xdg'\n\nexport interface CredentialBridgeOptions {\n /** Environment to read/mutate. Defaults to `process.env`. */\n env?: Record<string, string | undefined>\n /** Storage dir holding `credentials.json`. Defaults to the resolved zidane data dir. */\n dataDir?: string\n}\n\n/**\n * Apply the stored credentials to `env`. Returns the bridged file path, or\n * `null` when nothing was applied (no store, or an explicit path override).\n */\nexport function bridgeStoredCredentials(options: CredentialBridgeOptions = {}): string | null {\n const env = options.env ?? process.env\n // An explicit path means the caller owns credential resolution — don't\n // second-guess it.\n if (env.ZIDANE_CREDENTIALS_PATH)\n return null\n\n const dataDir = options.dataDir ?? resolveStorageDirs({ env }).configDir\n const path = credentialsPath(dataDir)\n if (!existsSync(path))\n return null\n\n // OAuth providers resolve + refresh from this file.\n env.ZIDANE_CREDENTIALS_PATH = path\n\n const creds = readCredentials(dataDir)\n for (const descriptor of Object.values(BUILTIN_PROVIDERS)) {\n const cred = creds[credKeyOf(descriptor)]\n if (cred?.kind !== 'apikey')\n continue\n if (descriptor.envKey && cred.value && !env[descriptor.envKey])\n env[descriptor.envKey] = cred.value\n for (const field of descriptor.customFields ?? []) {\n const value = cred.customFields?.[field.key]\n if (value && !env[field.envVar])\n env[field.envVar] = value\n }\n }\n return path\n}\n","/**\n * Shared glue for the CLI entrypoints (`start.ts` — human renderer,\n * `headless-cli.ts` — machine contract). Both build an execution context,\n * resolve a session (memory or sqlite), and parse `--mcp` config the same way;\n * this module is the single source of truth for that wiring so the two CLIs\n * stay in lockstep without duplicating it.\n */\n\nimport type { ExecutionContext } from './contexts'\nimport type { Session } from './session'\nimport { createProcessContext, createSandboxContext } from './contexts'\nimport { createDaytonaProvider } from './contexts/daytona'\nimport { createDockerContext } from './contexts/docker'\nimport { createE2BProvider } from './contexts/e2b'\nimport { createMemoryStore, createSession, loadSession } from './session'\nimport { createSqliteStore } from './session/sqlite'\n\nexport { parseMcpConfig } from './start/shared-options'\n\n/**\n * Build the execution context for a CLI run: `process` (default), `docker`,\n * `e2b`, or `daytona`.\n *\n * The `e2b` backend reads its `E2B_API_KEY` / `E2B_DOMAIN` / `E2B_TEMPLATE`\n * from the environment (point `E2B_DOMAIN` at a self-hosted cluster, and set\n * `E2B_TEMPLATE` to a template that exists there — the default `base` does\n * not); `--cwd` becomes the sandbox working directory.\n *\n * The Daytona backend reads `DAYTONA_API_KEY` / `DAYTONA_API_URL` /\n * `DAYTONA_TARGET` from the environment. `--cwd` becomes the sandbox working\n * directory.\n *\n * `env` (from `--env` / `--pass-env`) is forwarded to whichever context is\n * selected: baked into remote sandboxes at create time, set on the Docker\n * container, or merged into the in-process command environment.\n *\n * `pregame` (from `--pregame`) is supported by the remote sandbox providers:\n * a setup script uploaded and run in the sandbox once it's ready, before\n * prompting begins.\n *\n * `sandboxId` (from `--sandbox`) attaches to a pre-existing remote sandbox\n * instead of creating a fresh one.\n */\nexport function createCliExecution(type: string, opts: { image?: string, cwd?: string, env?: Record<string, string>, pregame?: { name: string, content: string }, sandboxId?: string, sandboxOnDestroy?: 'kill' | 'pause' | 'leave' }): ExecutionContext {\n switch (type) {\n case 'docker':\n return createDockerContext({ image: opts.image, cwd: opts.cwd, env: opts.env })\n case 'e2b':\n return createSandboxContext(createE2BProvider({ cwd: opts.cwd, env: opts.env, ...(opts.pregame ? { pregame: opts.pregame } : {}), ...(opts.sandboxId ? { sandboxId: opts.sandboxId } : {}), ...(opts.sandboxOnDestroy ? { onDestroy: opts.sandboxOnDestroy } : {}) }))\n case 'daytona':\n return createSandboxContext(createDaytonaProvider({ cwd: opts.cwd, env: opts.env, ...(opts.pregame ? { pregame: opts.pregame } : {}), ...(opts.sandboxId ? { sandboxId: opts.sandboxId } : {}), ...(opts.sandboxOnDestroy ? { onDestroy: opts.sandboxOnDestroy } : {}) }))\n case 'process':\n default:\n return createProcessContext({ cwd: opts.cwd, env: opts.env })\n }\n}\n\n/**\n * Resolve the session for a CLI run.\n * - `sessionDb` set → sqlite-backed; resume `sessionId` if it exists, else\n * create it (or a fresh id when `sessionId` is omitted).\n * - `sessionDb` absent → in-memory store.\n *\n * Fresh sessions are saved immediately so the store has a header row from\n * the start — incremental `appendTurns` against a header-less sqlite store\n * would otherwise be silent no-ops, and an error / Ctrl+C before the final\n * save would lose the whole run.\n */\nexport async function createCliSession(sessionDb?: string, sessionId?: string): Promise<Session> {\n if (sessionDb) {\n const store = createSqliteStore({ path: sessionDb })\n if (sessionId) {\n const existing = await loadSession(store, sessionId)\n if (existing)\n return existing\n const session = await createSession({ store, id: sessionId })\n await session.save()\n return session\n }\n const session = await createSession({ store })\n await session.save()\n return session\n }\n return await createSession({ store: createMemoryStore() })\n}\n\n/**\n * Install SIGINT/SIGTERM handlers for a CLI run. The first signal aborts the\n * returned `AbortSignal` so the running agent can unwind cleanly (persist the\n * session, destroy execution contexts) and the process exits through the\n * normal path — which is what fires the `process.on('exit')` orphan reaper\n * for detached background process groups. A second signal force-exits\n * immediately (the synchronous 'exit' reaper still runs, but async cleanup\n * such as Docker container teardown is skipped).\n */\nexport function installCliSignalHandlers(): AbortSignal {\n const controller = new AbortController()\n const onSignal = (name: NodeJS.Signals): void => {\n if (controller.signal.aborted)\n process.exit(name === 'SIGTERM' ? 143 : 130) // 128 + signal number\n controller.abort(new Error(`Received ${name} — aborting run`))\n }\n process.on('SIGINT', () => onSignal('SIGINT'))\n process.on('SIGTERM', () => onSignal('SIGTERM'))\n return controller.signal\n}\n","import type { ParseArgsConfig } from 'node:util'\nimport type { Preset } from '../presets'\nimport type { Provider } from '../providers'\nimport type { StartLocalOptions, StartProviderName } from './shared-options'\nimport { basic } from '../presets'\nimport { anthropic, arcee, baseten, cerebras, openai, openaiCompat, openrouter, xai } from '../providers'\nimport {\n buildStartLocalOptions,\n parseStartArgValues,\n startLocalArgOptions,\n startLocalUsage,\n StartUsageError,\n} from './shared-options'\n\nexport const startProviders = {\n anthropic,\n openai,\n openrouter,\n cerebras,\n xai,\n arcee,\n baseten,\n}\n\nexport const startPresets = {\n basic,\n} as const\n\ninterface StartProviderConfig {\n provider: StartProviderName\n model?: string\n baseURL?: string\n apiKeyEnv?: string\n headersEnv?: string\n extraHeaders?: Record<string, string>\n vision?: boolean\n imageInToolResult?: boolean\n temperature?: number\n seed?: number\n}\n\ntype StartProviderInput = StartProviderName | StartProviderConfig\n\nexport interface StartOptions extends StartLocalOptions {\n restate: boolean\n restateAdminUrl: string\n restateIngressUrl: string\n restateServicePort: number\n restateDeploymentUri: string\n restateVerbose: boolean\n restateKeepAlive: boolean\n restateRandomFailure: boolean\n restateInvocationTimeoutMs?: number\n restateProviderRetryAttempts?: number\n restateToolRetryAttempts?: number\n}\n\nexport { StartUsageError }\n\nconst restateArgOptions = {\n 'restate': { type: 'boolean', default: false },\n 'restate-admin-url': { type: 'string', default: 'http://localhost:19070' },\n 'restate-ingress-url': { type: 'string', default: 'http://localhost:18080' },\n 'restate-service-port': { type: 'string', default: '19081' },\n 'restate-deployment-uri': { type: 'string' },\n 'restate-verbose': { type: 'boolean', default: false },\n 'restate-keep-alive': { type: 'boolean', default: false },\n 'restate-random-failure': { type: 'boolean', default: false },\n 'restate-invocation-timeout-ms': { type: 'string' },\n 'restate-provider-retry-attempts': { type: 'string' },\n 'restate-tool-retry-attempts': { type: 'string' },\n} as const satisfies ParseArgsConfig['options']\n\nexport function parseStartArgs(argv: readonly string[] = Bun.argv.slice(2)): StartOptions {\n // Single parse over the composed table — the shared local options plus the\n // Restate-only flags — so a flag added to one surface can't silently drift\n // out of the other.\n const values = parseStartArgValues(argv, { ...startLocalArgOptions, ...restateArgOptions })\n const local = buildStartLocalOptions(values, { usage: startUsage })\n const servicePort = parsePort(values['restate-service-port'] as string | undefined)\n const deploymentUri = values['restate-deployment-uri'] as string | undefined\n\n return {\n ...local,\n restate: values.restate === true,\n restateAdminUrl: stripTrailingSlash((values['restate-admin-url'] as string | undefined) || 'http://localhost:19070'),\n restateIngressUrl: stripTrailingSlash((values['restate-ingress-url'] as string | undefined) || 'http://localhost:18080'),\n restateServicePort: servicePort,\n restateDeploymentUri: stripTrailingSlash(deploymentUri || `http://host.docker.internal:${servicePort}`),\n restateVerbose: values['restate-verbose'] === true,\n restateKeepAlive: values['restate-keep-alive'] === true,\n restateRandomFailure: values['restate-random-failure'] === true,\n restateInvocationTimeoutMs: parseOptionalPositiveInteger(\n values['restate-invocation-timeout-ms'] as string | undefined,\n '--restate-invocation-timeout-ms',\n ),\n restateProviderRetryAttempts: parseOptionalNonNegativeInteger(\n values['restate-provider-retry-attempts'] as string | undefined,\n '--restate-provider-retry-attempts',\n ),\n restateToolRetryAttempts: parseOptionalNonNegativeInteger(\n values['restate-tool-retry-attempts'] as string | undefined,\n '--restate-tool-retry-attempts',\n ),\n }\n}\n\nexport function resolvePreset(name: string): Preset {\n const preset = startPresets[name as keyof typeof startPresets]\n if (!preset)\n throw new Error(`Unknown preset: ${name}. Available: ${Object.keys(startPresets).join(', ')}`)\n return preset\n}\n\nexport function createStartProvider(input: StartProviderInput): Provider {\n const options = typeof input === 'string' ? { provider: input } : input\n const name = options.provider\n if (name === 'local' || name === 'openai-compat')\n return createLocalCompatProvider(options, name)\n\n const providerFactory = startProviders[name]\n if (!providerFactory)\n throw new Error(`Unknown provider: ${name}. Available: ${Object.keys(startProviders).join(', ')}, local, openai-compat`)\n warnIgnoredLocalProviderOptions(options, name)\n return providerFactory()\n}\n\nexport function startUsage(): string {\n return [\n startLocalUsage(),\n ` [--restate] [--restate-admin-url <url>] [--restate-ingress-url <url>]`,\n ` [--restate-service-port <port>] [--restate-deployment-uri <url>]`,\n ` [--restate-invocation-timeout-ms <ms>] [--restate-provider-retry-attempts <n>] [--restate-tool-retry-attempts <n>]`,\n ` [--restate-keep-alive] [--restate-random-failure] [--restate-verbose]`,\n '',\n 'Subagents:',\n ' The default `basic` preset ships with the `spawn` tool — prompt the model to delegate, e.g.',\n ' bun start --prompt \"Spawn one subagent to count files in src/, another to count files in test/, then sum them\"',\n ' Subagent stream/tool/spawn events are rendered live, indented per depth.',\n ].join('\\n')\n}\n\nfunction parsePort(raw: string | undefined): number {\n const port = Number(raw || 19081)\n if (!Number.isInteger(port) || port <= 0 || port > 65_535)\n throw new Error(`Invalid --restate-service-port: ${raw}`)\n return port\n}\n\nfunction parseOptionalPositiveInteger(raw: string | undefined, name: string): number | undefined {\n if (raw === undefined)\n return undefined\n const value = Number(raw)\n if (!Number.isInteger(value) || value <= 0)\n throw new Error(`Invalid ${name}: ${raw}`)\n return value\n}\n\nfunction parseOptionalNonNegativeInteger(raw: string | undefined, name: string): number | undefined {\n if (raw === undefined)\n return undefined\n const value = Number(raw)\n if (!Number.isInteger(value) || value < 0)\n throw new Error(`Invalid ${name}: ${raw}`)\n return value\n}\n\nfunction stripTrailingSlash(value: string): string {\n return value.replace(/\\/+$/, '')\n}\n\nfunction createLocalCompatProvider(options: Partial<StartLocalOptions>, name: 'local' | 'openai-compat'): Provider {\n const baseURL = options.baseURL ?? process.env.LOCAL_LLM_BASE_URL\n if (!baseURL) {\n throw new Error(\n 'No base URL for the local provider. Pass --base-url or set LOCAL_LLM_BASE_URL '\n + '(e.g. http://localhost:11434/v1 for Ollama, http://localhost:8000/v1 for vLLM).',\n )\n }\n\n const apiKey = (options.apiKeyEnv ? process.env[options.apiKeyEnv] : undefined)\n ?? process.env.LOCAL_LLM_API_KEY\n ?? 'no-key'\n const capabilities = {\n vision: options.vision ?? false,\n imageInToolResult: options.imageInToolResult ?? false,\n }\n if (capabilities.imageInToolResult)\n capabilities.vision = true\n\n const extraBodyParams: Record<string, unknown> = {\n stream_options: { include_usage: true },\n }\n if (options.temperature !== undefined)\n extraBodyParams.temperature = options.temperature\n if (options.seed !== undefined)\n extraBodyParams.seed = options.seed\n\n return openaiCompat({\n name,\n baseURL,\n apiKey,\n extraHeaders: resolveLocalExtraHeaders(options),\n capabilities,\n ...(options.model\n ? { defaultModel: options.model }\n : process.env.LOCAL_LLM_DEFAULT_MODEL\n ? { defaultModel: process.env.LOCAL_LLM_DEFAULT_MODEL }\n : {}),\n extraBodyParams,\n })\n}\n\nfunction warnIgnoredLocalProviderOptions(options: Partial<StartLocalOptions>, provider: string): void {\n const ignored = [\n options.baseURL !== undefined ? '--base-url' : null,\n options.apiKeyEnv !== undefined ? '--api-key-env' : null,\n options.headersEnv !== undefined ? '--headers-env' : null,\n options.extraHeaders !== undefined ? '--header' : null,\n options.vision !== undefined ? '--vision' : null,\n options.imageInToolResult !== undefined ? '--image-in-tool-result' : null,\n options.temperature !== undefined ? '--temperature' : null,\n options.seed !== undefined ? '--seed' : null,\n ].filter((flag): flag is string => flag !== null)\n\n if (ignored.length > 0)\n console.error(`[start] ${ignored.join(', ')} only apply to --provider local|openai-compat; ignored for '${provider}'.`)\n}\n\nfunction resolveLocalExtraHeaders(options: Partial<StartLocalOptions>): Record<string, string> {\n return {\n ...(process.env.LOCAL_LLM_AUTHORIZATION ? { Authorization: process.env.LOCAL_LLM_AUTHORIZATION } : {}),\n ...readHeadersEnv(options.headersEnv ?? 'LOCAL_LLM_HEADERS'),\n ...(options.extraHeaders ?? {}),\n }\n}\n\nfunction readHeadersEnv(envName: string): Record<string, string> {\n const raw = process.env[envName]\n if (!raw)\n return {}\n\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n }\n catch {\n throw new Error(`${envName} must contain a JSON object of string headers.`)\n }\n\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))\n throw new Error(`${envName} must contain a JSON object of string headers.`)\n\n const headers: Record<string, string> = {}\n for (const [name, value] of Object.entries(parsed)) {\n if (typeof value !== 'string')\n throw new Error(`${envName} header \"${name}\" must be a string.`)\n headers[name] = value\n }\n return headers\n}\n","#!/usr/bin/env bun\n\nimport type { ParseArgsConfig } from 'node:util'\nimport type { AcpModelChoice } from './acp'\nimport type { Provider } from './providers'\nimport type { StartLocalOptions, StartProviderName } from './start/shared-options'\nimport { resolve } from 'node:path'\nimport { runAcpStdioServer } from './acp'\nimport { bridgeStoredCredentials } from './acp/credential-bridge'\nimport { detectAuth } from './chat/auth'\nimport { BUILTIN_PROVIDERS, modelsForDescriptor } from './chat/providers'\nimport { resolveStorageDirs } from './chat/xdg'\nimport { createCliExecution } from './cli-shared'\nimport { createStartProvider, resolvePreset } from './start/options'\nimport { buildStartLocalOptions, parseStartArgValues, startLocalArgOptions, startProviderNames, StartUsageError } from './start/shared-options'\n\n// ACP-only flags layered on top of the shared start option table. Parsed with\n// the strict shared parser so a typo still fails loudly.\nconst acpArgOptions = {\n 'models': { type: 'string' },\n 'model-option': { type: 'string', multiple: true },\n 'no-credential-store': { type: 'boolean', default: false },\n} as const satisfies ParseArgsConfig['options']\n\nasync function main(): Promise<void> {\n const argv = Bun.argv.slice(2)\n if (isHelp(argv)) {\n process.stdout.write(`${usage()}\\n`)\n return\n }\n\n const values = parseStartArgValues(argv, { ...startLocalArgOptions, ...acpArgOptions })\n const options = buildStartLocalOptions(values, { requirePrompt: false, usage })\n\n // Pull credentials from the existing zidane store (the same login the TUI /\n // `zidane auth` use) so editors like Zed need no secrets in settings.json.\n // Runs before any provider is constructed. Explicit env still wins.\n if (values['no-credential-store'] !== true) {\n const bridged = bridgeStoredCredentials()\n if (bridged)\n process.stderr.write(`[zidane-acp] using stored credentials from ${bridged}\\n`)\n }\n\n const registry = buildModelRegistry(options, values)\n ?? buildAutoModelRegistry(options, argv)\n const sessionDb = options.sessionDb ?? defaultAcpSessionDbPath()\n const store = (await import('./session/sqlite')).createTuiStore(sessionDb)\n\n const handle = runAcpStdioServer({\n // Registry mode lets ACP clients (e.g. Zed) switch models; each model\n // resolves its own provider + credentials lazily. Otherwise a single\n // provider backs every run.\n ...(registry\n ? { models: registry.models, ...(registry.defaultModelId ? { defaultModelId: registry.defaultModelId } : {}) }\n : { provider: buildBaseProvider(options) }),\n model: options.model,\n preset: resolvePreset(options.preset),\n system: options.system,\n store,\n // ACP mandates newline-delimited JSON over stdio. Be explicit so the\n // shipped binary stays correct regardless of library defaults.\n framing: 'newline',\n agentOptions: {\n ...(options.mcp ? { mcpServers: options.mcp } : {}),\n },\n execution: request => createCliExecution(options.context, {\n image: options.image,\n cwd: request.cwd || options.cwd,\n env: options.env,\n pregame: options.pregame,\n sandboxId: options.sandboxId,\n sandboxOnDestroy: options.sandboxOnDestroy,\n }),\n agentInfo: {\n name: 'zidane',\n title: 'Zidane',\n version: process.env.npm_package_version ?? '1',\n },\n permission: { enabled: true },\n })\n\n const shutdown = async () => {\n await handle.close()\n store?.close?.()\n }\n process.once('SIGINT', () => {\n void shutdown().finally(() => process.exit(130))\n })\n process.once('SIGTERM', () => {\n void shutdown().finally(() => process.exit(143))\n })\n}\n\nfunction usage(): string {\n return [\n 'Usage: zidane-acp [provider/context options]',\n '',\n 'Runs Zidane as an ACP v1 agent over stdio. Prompts are received through ACP session/prompt.',\n '',\n 'Common options:',\n ' --provider anthropic|openai|openrouter|cerebras|xai|arcee|baseten|local|openai-compat',\n ' --model <id>',\n ' --models <id,id,...> advertise a model selector (all on --provider)',\n ' --model-option provider:model[:label] add a cross-provider selectable model (repeatable)',\n ' --context process|docker|e2b|daytona',\n ' --cwd <path>',\n ` --session-db <path> default: ${defaultAcpSessionDbPath()}`,\n ' --mcp <json>',\n ' --no-credential-store ignore ~/.zidane credentials; use only env',\n '',\n 'Without --provider / --model / --models / --model-option, zidane-acp',\n 'auto-advertises models for every configured provider. Explicit flags keep',\n 'the old deterministic single-provider or curated-picker behavior.',\n '',\n 'Credentials: by default zidane-acp reads Zidane\\'s app credential store',\n '(~/.zidane/credentials.json), so no API keys are needed in the editor config.',\n 'Explicit env vars always win.',\n ].join('\\n')\n}\n\nfunction isHelp(argv: readonly string[]): boolean {\n return argv.includes('--help') || argv.includes('-h')\n}\n\n/** Build a `createStartProvider` config from the parsed CLI options. */\nfunction providerConfig(options: StartLocalOptions, provider: StartProviderName, model: string | undefined) {\n return {\n provider,\n model,\n baseURL: options.baseURL,\n apiKeyEnv: options.apiKeyEnv,\n headersEnv: options.headersEnv,\n extraHeaders: options.extraHeaders,\n vision: options.vision,\n imageInToolResult: options.imageInToolResult,\n temperature: options.temperature,\n seed: options.seed,\n }\n}\n\nfunction buildBaseProvider(options: StartLocalOptions): Provider {\n return createStartProvider(providerConfig(options, options.provider, options.model))\n}\n\n/**\n * Assemble the selectable-model registry from `--model-option` (cross-provider,\n * each lazily building its own provider) and `--models` (same `--provider`,\n * sharing one provider instance). Returns `undefined` when neither flag is set\n * so the caller falls back to a single provider.\n */\nfunction buildModelRegistry(\n options: StartLocalOptions,\n values: Record<string, unknown>,\n): { models: AcpModelChoice[], defaultModelId?: string } | undefined {\n const modelsFlag = (values.models as string | undefined)?.trim()\n const modelOptionFlags = (values['model-option'] as string[] | undefined) ?? []\n if (!modelsFlag && modelOptionFlags.length === 0)\n return undefined\n\n const choices: AcpModelChoice[] = []\n\n for (const raw of modelOptionFlags)\n choices.push(parseModelOption(raw, options))\n\n if (modelsFlag) {\n const models = modelsFlag.split(',').map(model => model.trim()).filter(Boolean)\n if (models.length === 0)\n throw new StartUsageError('--models must list at least one model id.')\n // Same provider serves every entry: build it once and share the instance.\n const baseProvider = buildBaseProvider(options)\n for (const model of models)\n choices.push({ id: model, name: model, model, ...modelChoiceMetadata(options.provider, model), provider: baseProvider })\n }\n\n const seen = new Set<string>()\n for (const choice of choices) {\n if (seen.has(choice.id))\n throw new StartUsageError(`Duplicate model id \"${choice.id}\" across --models / --model-option.`)\n seen.add(choice.id)\n }\n\n const defaultModelId = (options.model\n && choices.find(choice => choice.id === options.model || choice.model === options.model)?.id)\n || choices[0]!.id\n return { models: choices, defaultModelId }\n}\n\nfunction buildAutoModelRegistry(\n options: StartLocalOptions,\n argv: readonly string[],\n): { models: AcpModelChoice[], defaultModelId?: string } | undefined {\n if (hasExplicitProviderTarget(argv))\n return undefined\n\n const dataDir = resolveStorageDirs({ env: process.env }).configDir\n const available = detectAuth(dataDir, BUILTIN_PROVIDERS, process.env)\n .filter(provider => provider.available)\n if (available.length === 0)\n return undefined\n\n const choices: AcpModelChoice[] = []\n const providers = new Map<string, Provider>()\n const providerFor = (key: string): Provider => {\n let provider = providers.get(key)\n if (!provider) {\n const descriptor = BUILTIN_PROVIDERS[key]\n if (!descriptor)\n throw new StartUsageError(`Unknown configured provider: ${key}`)\n provider = descriptor.factory()\n providers.set(key, provider)\n }\n return provider\n }\n\n for (const auth of available) {\n const descriptor = BUILTIN_PROVIDERS[auth.key]\n if (!descriptor)\n continue\n const models = promoteDefaultModel(modelsForDescriptor(descriptor), descriptor.defaultModel)\n for (const model of models) {\n choices.push({\n id: `${descriptor.key}:${model.id}`,\n name: `${model.name ?? model.id} (${descriptor.label})`,\n model: model.id,\n ...(model.reasoning === true ? { reasoning: true } : {}),\n ...(model.options?.length\n ? { options: model.options.map(option => ({ id: option.id, label: option.label, ...(option.description ? { description: option.description } : {}) })) }\n : {}),\n provider: () => providerFor(descriptor.key),\n })\n }\n }\n\n if (choices.length === 0)\n return undefined\n const defaultModelId = choices.find(choice => choice.id === `${options.provider}:${options.model}` || choice.model === options.model)?.id\n ?? choices[0]!.id\n return { models: choices, defaultModelId }\n}\n\nfunction promoteDefaultModel<T extends { id: string }>(models: readonly T[], defaultModel: string | undefined): readonly T[] {\n if (!defaultModel)\n return models\n const index = models.findIndex(model => model.id === defaultModel)\n if (index <= 0)\n return models\n const next = models.slice()\n const [selected] = next.splice(index, 1)\n next.unshift(selected)\n return next\n}\n\nfunction hasExplicitProviderTarget(argv: readonly string[]): boolean {\n return hasArg(argv, 'provider')\n || hasArg(argv, 'model', 'm')\n || hasArg(argv, 'models')\n || hasArg(argv, 'model-option')\n}\n\nfunction hasArg(argv: readonly string[], long: string, short?: string): boolean {\n const longFlag = `--${long}`\n const shortFlag = short ? `-${short}` : undefined\n return argv.some(arg =>\n arg === longFlag\n || arg.startsWith(`${longFlag}=`)\n || (shortFlag !== undefined && (arg === shortFlag || arg.startsWith(`${shortFlag}=`))),\n )\n}\n\nfunction defaultAcpSessionDbPath(): string {\n return resolve(resolveStorageDirs({ env: process.env }).dataDir, 'acp-sessions.db')\n}\n\nfunction parseModelOption(raw: string, options: StartLocalOptions): AcpModelChoice {\n const parts = raw.split(':')\n if (parts.length < 2 || !parts[0] || !parts[1])\n throw new StartUsageError(`--model-option must be \"provider:model[:label]\", got '${raw}'.`)\n const providerName = parts[0] as StartProviderName\n if (!startProviderNames.includes(providerName))\n throw new StartUsageError(`--model-option provider must be one of ${startProviderNames.join('|')}, got '${providerName}'.`)\n const model = parts[1]\n const label = parts.slice(2).join(':').trim() || undefined\n const isLocal = providerName === 'local' || providerName === 'openai-compat'\n // Lazy: a model the user never selects never builds its provider, so its\n // credentials are never required. local/openai-compat carry the endpoint\n // flags; hosted providers read their own standard env credentials.\n const provider = (): Provider => createStartProvider(\n isLocal ? providerConfig(options, providerName, model) : { provider: providerName, model },\n )\n // Stable `provider:model` key so the value the client echoes back is\n // unambiguous; the optional label is display-only.\n return { id: `${providerName}:${model}`, name: label ?? model, model, ...modelChoiceMetadata(providerName, model), provider }\n}\n\nfunction modelChoiceMetadata(providerName: StartProviderName, modelId: string): Pick<AcpModelChoice, 'reasoning' | 'options'> {\n const descriptor = BUILTIN_PROVIDERS[providerName]\n if (!descriptor)\n return {}\n const model = modelsForDescriptor(descriptor).find(candidate => candidate.id === modelId)\n return {\n ...(model?.reasoning === true ? { reasoning: true } : {}),\n ...(model?.options?.length\n ? { options: model.options.map(option => ({ id: option.id, label: option.label, ...(option.description ? { description: option.description } : {}) })) }\n : {}),\n }\n}\n\nmain().catch((err) => {\n if (err instanceof StartUsageError)\n process.stderr.write(`${err.message}\\n`)\n else\n process.stderr.write(`ACP server error: ${err instanceof Error ? err.message : String(err)}\\n`)\n process.exit(1)\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"acp-cli.js","names":[],"sources":["../src/acp/credential-bridge.ts","../src/cli-shared.ts","../src/start/options.ts","../src/acp-cli.ts"],"sourcesContent":["/**\n * Bridge the user's existing zidane credential store into the process\n * environment so the ACP agent authenticates with the SAME login the TUI /\n * `zidane auth` already set up — no secrets in the editor's `settings.json`.\n *\n * ACP gives the client (e.g. Zed) no way to forward its own provider API keys\n * to an external agent: provider/auth is agent-owned. The only client-driven\n * channel is the `agent_servers.<name>.env` block, i.e. literal secrets in\n * settings. This bridge removes that need by reading the on-disk store the rest\n * of zidane manages:\n *\n * - OAuth providers (Anthropic / OpenAI Codex / xAI): point\n * `ZIDANE_CREDENTIALS_PATH` at the store so the harness providers read and\n * refresh from it.\n * - API-key providers (OpenRouter / Cerebras / Baseten / Arcee / …): inject\n * the stored key into the provider's env var.\n *\n * Precedence is \"explicit env wins\": an env var already set (e.g. by the\n * editor's `env` block) is never overwritten — the store only FILLS GAPS. The\n * whole bridge no-ops when `ZIDANE_CREDENTIALS_PATH` is already set (the caller\n * is managing credentials explicitly) or when no store file exists (so\n * `~/.credentials.json` from a legacy `bun run auth` keeps working untouched).\n */\n\nimport { existsSync } from 'node:fs'\nimport { credentialsPath, readCredentials } from '../chat/credentials'\nimport { BUILTIN_PROVIDERS, credKeyOf } from '../chat/providers'\nimport { resolveStorageDirs } from '../chat/xdg'\n\nexport interface CredentialBridgeOptions {\n /** Environment to read/mutate. Defaults to `process.env`. */\n env?: Record<string, string | undefined>\n /** Storage dir holding `credentials.json`. Defaults to the resolved zidane data dir. */\n dataDir?: string\n}\n\n/**\n * Apply the stored credentials to `env`. Returns the bridged file path, or\n * `null` when nothing was applied (no store, or an explicit path override).\n */\nexport function bridgeStoredCredentials(options: CredentialBridgeOptions = {}): string | null {\n const env = options.env ?? process.env\n // An explicit path means the caller owns credential resolution — don't\n // second-guess it.\n if (env.ZIDANE_CREDENTIALS_PATH)\n return null\n\n const dataDir = options.dataDir ?? resolveStorageDirs({ env }).configDir\n const path = credentialsPath(dataDir)\n if (!existsSync(path))\n return null\n\n // OAuth providers resolve + refresh from this file.\n env.ZIDANE_CREDENTIALS_PATH = path\n\n const creds = readCredentials(dataDir)\n for (const descriptor of Object.values(BUILTIN_PROVIDERS)) {\n const cred = creds[credKeyOf(descriptor)]\n if (cred?.kind !== 'apikey')\n continue\n if (descriptor.envKey && cred.value && !env[descriptor.envKey])\n env[descriptor.envKey] = cred.value\n for (const field of descriptor.customFields ?? []) {\n const value = cred.customFields?.[field.key]\n if (value && !env[field.envVar])\n env[field.envVar] = value\n }\n }\n return path\n}\n","/**\n * Shared glue for the CLI entrypoints (`start.ts` — human renderer,\n * `headless-cli.ts` — machine contract). Both build an execution context,\n * resolve a session (memory or sqlite), and parse `--mcp` config the same way;\n * this module is the single source of truth for that wiring so the two CLIs\n * stay in lockstep without duplicating it.\n */\n\nimport type { ExecutionContext } from './contexts'\nimport type { Session } from './session'\nimport { createProcessContext, createSandboxContext } from './contexts'\nimport { createDaytonaProvider } from './contexts/daytona'\nimport { createDockerContext } from './contexts/docker'\nimport { createE2BProvider } from './contexts/e2b'\nimport { createMemoryStore, createSession, loadSession } from './session'\nimport { createSqliteStore } from './session/sqlite'\n\nexport { parseMcpConfig } from './start/shared-options'\n\n/**\n * Build the execution context for a CLI run: `process` (default), `docker`,\n * `e2b`, or `daytona`.\n *\n * The `e2b` backend reads its `E2B_API_KEY` / `E2B_DOMAIN` / `E2B_TEMPLATE`\n * from the environment (point `E2B_DOMAIN` at a self-hosted cluster, and set\n * `E2B_TEMPLATE` to a template that exists there — the default `base` does\n * not); `--cwd` becomes the sandbox working directory.\n *\n * The Daytona backend reads `DAYTONA_API_KEY` / `DAYTONA_API_URL` /\n * `DAYTONA_TARGET` from the environment. `--cwd` becomes the sandbox working\n * directory.\n *\n * `env` (from `--env` / `--pass-env`) is forwarded to whichever context is\n * selected: baked into remote sandboxes at create time, set on the Docker\n * container, or merged into the in-process command environment.\n *\n * `pregame` (from `--pregame`) is supported by the remote sandbox providers:\n * a setup script uploaded and run in the sandbox once it's ready, before\n * prompting begins.\n *\n * `sandboxId` (from `--sandbox`) attaches to a pre-existing remote sandbox\n * instead of creating a fresh one.\n */\nexport function createCliExecution(type: string, opts: { image?: string, cwd?: string, env?: Record<string, string>, pregame?: { name: string, content: string }, sandboxId?: string, sandboxOnDestroy?: 'kill' | 'pause' | 'leave' }): ExecutionContext {\n switch (type) {\n case 'docker':\n return createDockerContext({ image: opts.image, cwd: opts.cwd, env: opts.env })\n case 'e2b':\n return createSandboxContext(createE2BProvider({ cwd: opts.cwd, env: opts.env, ...(opts.pregame ? { pregame: opts.pregame } : {}), ...(opts.sandboxId ? { sandboxId: opts.sandboxId } : {}), ...(opts.sandboxOnDestroy ? { onDestroy: opts.sandboxOnDestroy } : {}) }))\n case 'daytona':\n return createSandboxContext(createDaytonaProvider({ cwd: opts.cwd, env: opts.env, ...(opts.pregame ? { pregame: opts.pregame } : {}), ...(opts.sandboxId ? { sandboxId: opts.sandboxId } : {}), ...(opts.sandboxOnDestroy ? { onDestroy: opts.sandboxOnDestroy } : {}) }))\n case 'process':\n default:\n return createProcessContext({ cwd: opts.cwd, env: opts.env })\n }\n}\n\n/**\n * Resolve the session for a CLI run.\n * - `sessionDb` set → sqlite-backed; resume `sessionId` if it exists, else\n * create it (or a fresh id when `sessionId` is omitted).\n * - `sessionDb` absent → in-memory store.\n *\n * Fresh sessions are saved immediately so the store has a header row from\n * the start — incremental `appendTurns` against a header-less sqlite store\n * would otherwise be silent no-ops, and an error / Ctrl+C before the final\n * save would lose the whole run.\n */\nexport async function createCliSession(sessionDb?: string, sessionId?: string): Promise<Session> {\n if (sessionDb) {\n const store = createSqliteStore({ path: sessionDb })\n if (sessionId) {\n const existing = await loadSession(store, sessionId)\n if (existing)\n return existing\n const session = await createSession({ store, id: sessionId })\n await session.save()\n return session\n }\n const session = await createSession({ store })\n await session.save()\n return session\n }\n return await createSession({ store: createMemoryStore() })\n}\n\n/**\n * Install SIGINT/SIGTERM handlers for a CLI run. The first signal aborts the\n * returned `AbortSignal` so the running agent can unwind cleanly (persist the\n * session, destroy execution contexts) and the process exits through the\n * normal path — which is what fires the `process.on('exit')` orphan reaper\n * for detached background process groups. A second signal force-exits\n * immediately (the synchronous 'exit' reaper still runs, but async cleanup\n * such as Docker container teardown is skipped).\n */\nexport function installCliSignalHandlers(): AbortSignal {\n const controller = new AbortController()\n const onSignal = (name: NodeJS.Signals): void => {\n if (controller.signal.aborted)\n process.exit(name === 'SIGTERM' ? 143 : 130) // 128 + signal number\n controller.abort(new Error(`Received ${name} — aborting run`))\n }\n process.on('SIGINT', () => onSignal('SIGINT'))\n process.on('SIGTERM', () => onSignal('SIGTERM'))\n return controller.signal\n}\n","import type { ParseArgsConfig } from 'node:util'\nimport type { Preset } from '../presets'\nimport type { Provider } from '../providers'\nimport type { StartLocalOptions, StartProviderName } from './shared-options'\nimport { basic } from '../presets'\nimport { anthropic, arcee, baseten, cerebras, openai, openaiCompat, openrouter, xai } from '../providers'\nimport {\n buildStartLocalOptions,\n parseStartArgValues,\n startLocalArgOptions,\n startLocalUsage,\n StartUsageError,\n} from './shared-options'\n\nexport const startProviders = {\n anthropic,\n openai,\n openrouter,\n cerebras,\n xai,\n arcee,\n baseten,\n}\n\nexport const startPresets = {\n basic,\n} as const\n\ninterface StartProviderConfig {\n provider: StartProviderName\n model?: string\n baseURL?: string\n apiKeyEnv?: string\n headersEnv?: string\n extraHeaders?: Record<string, string>\n vision?: boolean\n imageInToolResult?: boolean\n temperature?: number\n seed?: number\n}\n\ntype StartProviderInput = StartProviderName | StartProviderConfig\n\nexport interface StartOptions extends StartLocalOptions {\n restate: boolean\n restateAdminUrl: string\n restateIngressUrl: string\n restateServicePort: number\n restateDeploymentUri: string\n restateVerbose: boolean\n restateKeepAlive: boolean\n restateRandomFailure: boolean\n restateInvocationTimeoutMs?: number\n restateProviderRetryAttempts?: number\n restateToolRetryAttempts?: number\n}\n\nexport { StartUsageError }\n\nconst restateArgOptions = {\n 'restate': { type: 'boolean', default: false },\n 'restate-admin-url': { type: 'string', default: 'http://localhost:19070' },\n 'restate-ingress-url': { type: 'string', default: 'http://localhost:18080' },\n 'restate-service-port': { type: 'string', default: '19081' },\n 'restate-deployment-uri': { type: 'string' },\n 'restate-verbose': { type: 'boolean', default: false },\n 'restate-keep-alive': { type: 'boolean', default: false },\n 'restate-random-failure': { type: 'boolean', default: false },\n 'restate-invocation-timeout-ms': { type: 'string' },\n 'restate-provider-retry-attempts': { type: 'string' },\n 'restate-tool-retry-attempts': { type: 'string' },\n} as const satisfies ParseArgsConfig['options']\n\nexport function parseStartArgs(argv: readonly string[] = Bun.argv.slice(2)): StartOptions {\n // Single parse over the composed table — the shared local options plus the\n // Restate-only flags — so a flag added to one surface can't silently drift\n // out of the other.\n const values = parseStartArgValues(argv, { ...startLocalArgOptions, ...restateArgOptions })\n const local = buildStartLocalOptions(values, { usage: startUsage })\n const servicePort = parsePort(values['restate-service-port'] as string | undefined)\n const deploymentUri = values['restate-deployment-uri'] as string | undefined\n\n return {\n ...local,\n restate: values.restate === true,\n restateAdminUrl: stripTrailingSlash((values['restate-admin-url'] as string | undefined) || 'http://localhost:19070'),\n restateIngressUrl: stripTrailingSlash((values['restate-ingress-url'] as string | undefined) || 'http://localhost:18080'),\n restateServicePort: servicePort,\n restateDeploymentUri: stripTrailingSlash(deploymentUri || `http://host.docker.internal:${servicePort}`),\n restateVerbose: values['restate-verbose'] === true,\n restateKeepAlive: values['restate-keep-alive'] === true,\n restateRandomFailure: values['restate-random-failure'] === true,\n restateInvocationTimeoutMs: parseOptionalPositiveInteger(\n values['restate-invocation-timeout-ms'] as string | undefined,\n '--restate-invocation-timeout-ms',\n ),\n restateProviderRetryAttempts: parseOptionalNonNegativeInteger(\n values['restate-provider-retry-attempts'] as string | undefined,\n '--restate-provider-retry-attempts',\n ),\n restateToolRetryAttempts: parseOptionalNonNegativeInteger(\n values['restate-tool-retry-attempts'] as string | undefined,\n '--restate-tool-retry-attempts',\n ),\n }\n}\n\nexport function resolvePreset(name: string): Preset {\n const preset = startPresets[name as keyof typeof startPresets]\n if (!preset)\n throw new Error(`Unknown preset: ${name}. Available: ${Object.keys(startPresets).join(', ')}`)\n return preset\n}\n\nexport function createStartProvider(input: StartProviderInput): Provider {\n const options = typeof input === 'string' ? { provider: input } : input\n const name = options.provider\n if (name === 'local' || name === 'openai-compat')\n return createLocalCompatProvider(options, name)\n\n const providerFactory = startProviders[name]\n if (!providerFactory)\n throw new Error(`Unknown provider: ${name}. Available: ${Object.keys(startProviders).join(', ')}, local, openai-compat`)\n warnIgnoredLocalProviderOptions(options, name)\n return providerFactory()\n}\n\nexport function startUsage(): string {\n return [\n startLocalUsage(),\n ` [--restate] [--restate-admin-url <url>] [--restate-ingress-url <url>]`,\n ` [--restate-service-port <port>] [--restate-deployment-uri <url>]`,\n ` [--restate-invocation-timeout-ms <ms>] [--restate-provider-retry-attempts <n>] [--restate-tool-retry-attempts <n>]`,\n ` [--restate-keep-alive] [--restate-random-failure] [--restate-verbose]`,\n '',\n 'Subagents:',\n ' The default `basic` preset ships with the `spawn` tool — prompt the model to delegate, e.g.',\n ' bun start --prompt \"Spawn one subagent to count files in src/, another to count files in test/, then sum them\"',\n ' Subagent stream/tool/spawn events are rendered live, indented per depth.',\n ].join('\\n')\n}\n\nfunction parsePort(raw: string | undefined): number {\n const port = Number(raw || 19081)\n if (!Number.isInteger(port) || port <= 0 || port > 65_535)\n throw new Error(`Invalid --restate-service-port: ${raw}`)\n return port\n}\n\nfunction parseOptionalPositiveInteger(raw: string | undefined, name: string): number | undefined {\n if (raw === undefined)\n return undefined\n const value = Number(raw)\n if (!Number.isInteger(value) || value <= 0)\n throw new Error(`Invalid ${name}: ${raw}`)\n return value\n}\n\nfunction parseOptionalNonNegativeInteger(raw: string | undefined, name: string): number | undefined {\n if (raw === undefined)\n return undefined\n const value = Number(raw)\n if (!Number.isInteger(value) || value < 0)\n throw new Error(`Invalid ${name}: ${raw}`)\n return value\n}\n\nfunction stripTrailingSlash(value: string): string {\n return value.replace(/\\/+$/, '')\n}\n\nfunction createLocalCompatProvider(options: Partial<StartLocalOptions>, name: 'local' | 'openai-compat'): Provider {\n const baseURL = options.baseURL ?? process.env.LOCAL_LLM_BASE_URL\n if (!baseURL) {\n throw new Error(\n 'No base URL for the local provider. Pass --base-url or set LOCAL_LLM_BASE_URL '\n + '(e.g. http://localhost:11434/v1 for Ollama, http://localhost:8000/v1 for vLLM).',\n )\n }\n\n const apiKey = (options.apiKeyEnv ? process.env[options.apiKeyEnv] : undefined)\n ?? process.env.LOCAL_LLM_API_KEY\n ?? 'no-key'\n const capabilities = {\n vision: options.vision ?? false,\n imageInToolResult: options.imageInToolResult ?? false,\n }\n if (capabilities.imageInToolResult)\n capabilities.vision = true\n\n const extraBodyParams: Record<string, unknown> = {\n stream_options: { include_usage: true },\n }\n if (options.temperature !== undefined)\n extraBodyParams.temperature = options.temperature\n if (options.seed !== undefined)\n extraBodyParams.seed = options.seed\n\n return openaiCompat({\n name,\n baseURL,\n apiKey,\n extraHeaders: resolveLocalExtraHeaders(options),\n capabilities,\n ...(options.model\n ? { defaultModel: options.model }\n : process.env.LOCAL_LLM_DEFAULT_MODEL\n ? { defaultModel: process.env.LOCAL_LLM_DEFAULT_MODEL }\n : {}),\n extraBodyParams,\n })\n}\n\nfunction warnIgnoredLocalProviderOptions(options: Partial<StartLocalOptions>, provider: string): void {\n const ignored = [\n options.baseURL !== undefined ? '--base-url' : null,\n options.apiKeyEnv !== undefined ? '--api-key-env' : null,\n options.headersEnv !== undefined ? '--headers-env' : null,\n options.extraHeaders !== undefined ? '--header' : null,\n options.vision !== undefined ? '--vision' : null,\n options.imageInToolResult !== undefined ? '--image-in-tool-result' : null,\n options.temperature !== undefined ? '--temperature' : null,\n options.seed !== undefined ? '--seed' : null,\n ].filter((flag): flag is string => flag !== null)\n\n if (ignored.length > 0)\n console.error(`[start] ${ignored.join(', ')} only apply to --provider local|openai-compat; ignored for '${provider}'.`)\n}\n\nfunction resolveLocalExtraHeaders(options: Partial<StartLocalOptions>): Record<string, string> {\n return {\n ...(process.env.LOCAL_LLM_AUTHORIZATION ? { Authorization: process.env.LOCAL_LLM_AUTHORIZATION } : {}),\n ...readHeadersEnv(options.headersEnv ?? 'LOCAL_LLM_HEADERS'),\n ...(options.extraHeaders ?? {}),\n }\n}\n\nfunction readHeadersEnv(envName: string): Record<string, string> {\n const raw = process.env[envName]\n if (!raw)\n return {}\n\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n }\n catch {\n throw new Error(`${envName} must contain a JSON object of string headers.`)\n }\n\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))\n throw new Error(`${envName} must contain a JSON object of string headers.`)\n\n const headers: Record<string, string> = {}\n for (const [name, value] of Object.entries(parsed)) {\n if (typeof value !== 'string')\n throw new Error(`${envName} header \"${name}\" must be a string.`)\n headers[name] = value\n }\n return headers\n}\n","#!/usr/bin/env bun\n\nimport type { ParseArgsConfig } from 'node:util'\nimport type { AcpModelChoice } from './acp'\nimport type { Provider } from './providers'\nimport type { StartLocalOptions, StartProviderName } from './start/shared-options'\nimport { resolve } from 'node:path'\nimport { runAcpStdioServer, withAcpDefaultTools } from './acp'\nimport { bridgeStoredCredentials } from './acp/credential-bridge'\nimport { detectAuth } from './chat/auth'\nimport { BUILTIN_PROVIDERS, modelsForDescriptor } from './chat/providers'\nimport { resolveStorageDirs } from './chat/xdg'\nimport { createCliExecution } from './cli-shared'\nimport { createStartProvider, resolvePreset } from './start/options'\nimport { buildStartLocalOptions, parseStartArgValues, startLocalArgOptions, startProviderNames, StartUsageError } from './start/shared-options'\n\n// ACP-only flags layered on top of the shared start option table. Parsed with\n// the strict shared parser so a typo still fails loudly.\nconst acpArgOptions = {\n 'models': { type: 'string' },\n 'model-option': { type: 'string', multiple: true },\n 'no-credential-store': { type: 'boolean', default: false },\n} as const satisfies ParseArgsConfig['options']\n\nasync function main(): Promise<void> {\n const argv = Bun.argv.slice(2)\n if (isHelp(argv)) {\n process.stdout.write(`${usage()}\\n`)\n return\n }\n\n const values = parseStartArgValues(argv, { ...startLocalArgOptions, ...acpArgOptions })\n const options = buildStartLocalOptions(values, { requirePrompt: false, usage })\n\n // Pull credentials from the existing zidane store (the same login the TUI /\n // `zidane auth` use) so editors like Zed need no secrets in settings.json.\n // Runs before any provider is constructed. Explicit env still wins.\n if (values['no-credential-store'] !== true) {\n const bridged = bridgeStoredCredentials()\n if (bridged)\n process.stderr.write(`[zidane-acp] using stored credentials from ${bridged}\\n`)\n }\n\n const registry = buildModelRegistry(options, values)\n ?? buildAutoModelRegistry(options, argv)\n const sessionDb = options.sessionDb ?? defaultAcpSessionDbPath()\n const store = (await import('./session/sqlite')).createTuiStore(sessionDb)\n\n const handle = runAcpStdioServer({\n // Registry mode lets ACP clients (e.g. Zed) switch models; each model\n // resolves its own provider + credentials lazily. Otherwise a single\n // provider backs every run.\n ...(registry\n ? { models: registry.models, ...(registry.defaultModelId ? { defaultModelId: registry.defaultModelId } : {}) }\n : { provider: buildBaseProvider(options) }),\n model: options.model,\n // `basic` ships no web_search/fetch_url; fill them in so editor sessions\n // match the TUI (and Anthropic gets native server-side web search).\n preset: withAcpDefaultTools(resolvePreset(options.preset)),\n system: options.system,\n store,\n // ACP mandates newline-delimited JSON over stdio. Be explicit so the\n // shipped binary stays correct regardless of library defaults.\n framing: 'newline',\n agentOptions: {\n ...(options.mcp ? { mcpServers: options.mcp } : {}),\n },\n execution: request => createCliExecution(options.context, {\n image: options.image,\n cwd: request.cwd || options.cwd,\n env: options.env,\n pregame: options.pregame,\n sandboxId: options.sandboxId,\n sandboxOnDestroy: options.sandboxOnDestroy,\n }),\n agentInfo: {\n name: 'zidane',\n title: 'Zidane',\n version: process.env.npm_package_version ?? '1',\n },\n permission: { enabled: true },\n })\n\n const shutdown = async () => {\n await handle.close()\n store?.close?.()\n }\n process.once('SIGINT', () => {\n void shutdown().finally(() => process.exit(130))\n })\n process.once('SIGTERM', () => {\n void shutdown().finally(() => process.exit(143))\n })\n}\n\nfunction usage(): string {\n return [\n 'Usage: zidane-acp [provider/context options]',\n '',\n 'Runs Zidane as an ACP v1 agent over stdio. Prompts are received through ACP session/prompt.',\n '',\n 'Common options:',\n ' --provider anthropic|openai|openrouter|cerebras|xai|arcee|baseten|local|openai-compat',\n ' --model <id>',\n ' --models <id,id,...> advertise a model selector (all on --provider)',\n ' --model-option provider:model[:label] add a cross-provider selectable model (repeatable)',\n ' --context process|docker|e2b|daytona',\n ' --cwd <path>',\n ` --session-db <path> default: ${defaultAcpSessionDbPath()}`,\n ' --mcp <json>',\n ' --no-credential-store ignore ~/.zidane credentials; use only env',\n '',\n 'Without --provider / --model / --models / --model-option, zidane-acp',\n 'auto-advertises models for every configured provider. Explicit flags keep',\n 'the old deterministic single-provider or curated-picker behavior.',\n '',\n 'Credentials: by default zidane-acp reads Zidane\\'s app credential store',\n '(~/.zidane/credentials.json), so no API keys are needed in the editor config.',\n 'Explicit env vars always win.',\n ].join('\\n')\n}\n\nfunction isHelp(argv: readonly string[]): boolean {\n return argv.includes('--help') || argv.includes('-h')\n}\n\n/** Build a `createStartProvider` config from the parsed CLI options. */\nfunction providerConfig(options: StartLocalOptions, provider: StartProviderName, model: string | undefined) {\n return {\n provider,\n model,\n baseURL: options.baseURL,\n apiKeyEnv: options.apiKeyEnv,\n headersEnv: options.headersEnv,\n extraHeaders: options.extraHeaders,\n vision: options.vision,\n imageInToolResult: options.imageInToolResult,\n temperature: options.temperature,\n seed: options.seed,\n }\n}\n\nfunction buildBaseProvider(options: StartLocalOptions): Provider {\n return createStartProvider(providerConfig(options, options.provider, options.model))\n}\n\n/**\n * Assemble the selectable-model registry from `--model-option` (cross-provider,\n * each lazily building its own provider) and `--models` (same `--provider`,\n * sharing one provider instance). Returns `undefined` when neither flag is set\n * so the caller falls back to a single provider.\n */\nfunction buildModelRegistry(\n options: StartLocalOptions,\n values: Record<string, unknown>,\n): { models: AcpModelChoice[], defaultModelId?: string } | undefined {\n const modelsFlag = (values.models as string | undefined)?.trim()\n const modelOptionFlags = (values['model-option'] as string[] | undefined) ?? []\n if (!modelsFlag && modelOptionFlags.length === 0)\n return undefined\n\n const choices: AcpModelChoice[] = []\n\n for (const raw of modelOptionFlags)\n choices.push(parseModelOption(raw, options))\n\n if (modelsFlag) {\n const models = modelsFlag.split(',').map(model => model.trim()).filter(Boolean)\n if (models.length === 0)\n throw new StartUsageError('--models must list at least one model id.')\n // Same provider serves every entry: build it once and share the instance.\n const baseProvider = buildBaseProvider(options)\n for (const model of models)\n choices.push({ id: model, name: model, model, ...modelChoiceMetadata(options.provider, model), provider: baseProvider })\n }\n\n const seen = new Set<string>()\n for (const choice of choices) {\n if (seen.has(choice.id))\n throw new StartUsageError(`Duplicate model id \"${choice.id}\" across --models / --model-option.`)\n seen.add(choice.id)\n }\n\n const defaultModelId = (options.model\n && choices.find(choice => choice.id === options.model || choice.model === options.model)?.id)\n || choices[0]!.id\n return { models: choices, defaultModelId }\n}\n\nfunction buildAutoModelRegistry(\n options: StartLocalOptions,\n argv: readonly string[],\n): { models: AcpModelChoice[], defaultModelId?: string } | undefined {\n if (hasExplicitProviderTarget(argv))\n return undefined\n\n const dataDir = resolveStorageDirs({ env: process.env }).configDir\n const available = detectAuth(dataDir, BUILTIN_PROVIDERS, process.env)\n .filter(provider => provider.available)\n if (available.length === 0)\n return undefined\n\n const choices: AcpModelChoice[] = []\n const providers = new Map<string, Provider>()\n const providerFor = (key: string): Provider => {\n let provider = providers.get(key)\n if (!provider) {\n const descriptor = BUILTIN_PROVIDERS[key]\n if (!descriptor)\n throw new StartUsageError(`Unknown configured provider: ${key}`)\n provider = descriptor.factory()\n providers.set(key, provider)\n }\n return provider\n }\n\n for (const auth of available) {\n const descriptor = BUILTIN_PROVIDERS[auth.key]\n if (!descriptor)\n continue\n const models = promoteDefaultModel(modelsForDescriptor(descriptor), descriptor.defaultModel)\n for (const model of models) {\n choices.push({\n id: `${descriptor.key}:${model.id}`,\n name: `${model.name ?? model.id} (${descriptor.label})`,\n model: model.id,\n ...(model.reasoning === true ? { reasoning: true } : {}),\n ...(model.options?.length\n ? { options: model.options.map(option => ({ id: option.id, label: option.label, ...(option.description ? { description: option.description } : {}) })) }\n : {}),\n provider: () => providerFor(descriptor.key),\n })\n }\n }\n\n if (choices.length === 0)\n return undefined\n const defaultModelId = choices.find(choice => choice.id === `${options.provider}:${options.model}` || choice.model === options.model)?.id\n ?? choices[0]!.id\n return { models: choices, defaultModelId }\n}\n\nfunction promoteDefaultModel<T extends { id: string }>(models: readonly T[], defaultModel: string | undefined): readonly T[] {\n if (!defaultModel)\n return models\n const index = models.findIndex(model => model.id === defaultModel)\n if (index <= 0)\n return models\n const next = models.slice()\n const [selected] = next.splice(index, 1)\n next.unshift(selected)\n return next\n}\n\nfunction hasExplicitProviderTarget(argv: readonly string[]): boolean {\n return hasArg(argv, 'provider')\n || hasArg(argv, 'model', 'm')\n || hasArg(argv, 'models')\n || hasArg(argv, 'model-option')\n}\n\nfunction hasArg(argv: readonly string[], long: string, short?: string): boolean {\n const longFlag = `--${long}`\n const shortFlag = short ? `-${short}` : undefined\n return argv.some(arg =>\n arg === longFlag\n || arg.startsWith(`${longFlag}=`)\n || (shortFlag !== undefined && (arg === shortFlag || arg.startsWith(`${shortFlag}=`))),\n )\n}\n\nfunction defaultAcpSessionDbPath(): string {\n return resolve(resolveStorageDirs({ env: process.env }).dataDir, 'acp-sessions.db')\n}\n\nfunction parseModelOption(raw: string, options: StartLocalOptions): AcpModelChoice {\n const parts = raw.split(':')\n if (parts.length < 2 || !parts[0] || !parts[1])\n throw new StartUsageError(`--model-option must be \"provider:model[:label]\", got '${raw}'.`)\n const providerName = parts[0] as StartProviderName\n if (!startProviderNames.includes(providerName))\n throw new StartUsageError(`--model-option provider must be one of ${startProviderNames.join('|')}, got '${providerName}'.`)\n const model = parts[1]\n const label = parts.slice(2).join(':').trim() || undefined\n const isLocal = providerName === 'local' || providerName === 'openai-compat'\n // Lazy: a model the user never selects never builds its provider, so its\n // credentials are never required. local/openai-compat carry the endpoint\n // flags; hosted providers read their own standard env credentials.\n const provider = (): Provider => createStartProvider(\n isLocal ? providerConfig(options, providerName, model) : { provider: providerName, model },\n )\n // Stable `provider:model` key so the value the client echoes back is\n // unambiguous; the optional label is display-only.\n return { id: `${providerName}:${model}`, name: label ?? model, model, ...modelChoiceMetadata(providerName, model), provider }\n}\n\nfunction modelChoiceMetadata(providerName: StartProviderName, modelId: string): Pick<AcpModelChoice, 'reasoning' | 'options'> {\n const descriptor = BUILTIN_PROVIDERS[providerName]\n if (!descriptor)\n return {}\n const model = modelsForDescriptor(descriptor).find(candidate => candidate.id === modelId)\n return {\n ...(model?.reasoning === true ? { reasoning: true } : {}),\n ...(model?.options?.length\n ? { options: model.options.map(option => ({ id: option.id, label: option.label, ...(option.description ? { description: option.description } : {}) })) }\n : {}),\n }\n}\n\nmain().catch((err) => {\n if (err instanceof StartUsageError)\n process.stderr.write(`${err.message}\\n`)\n else\n process.stderr.write(`ACP server error: ${err instanceof Error ? err.message : String(err)}\\n`)\n process.exit(1)\n})\n"],"mappings":"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"}
@@ -1,12 +1,14 @@
1
- import { I as defaultPromptMessage } from "./messages-DEsLGBB9.js";
2
- import { d as createAgent } from "./tools-DhzKzB1y.js";
1
+ import { I as defaultPromptMessage } from "./messages-U_87Z7GH.js";
2
+ import { d as createAgent } from "./tools-CwwYEeHB.js";
3
3
  import { r as createProcessContext } from "./contexts-DHi8LPCp.js";
4
- import { o as toolResultToText } from "./types-DxHDaqN7.js";
5
- import { o as readStateKey, r as hashContent, s as resolveReadStateMap } from "./read-state-DH2IuQHX.js";
4
+ import { s as toolResultToText } from "./types-CyVGdbia.js";
5
+ import { o as readStateKey, r as hashContent, s as resolveReadStateMap } from "./read-state-CLK9yVpm.js";
6
6
  import { l as errorMessage } from "./errors-BpPfMo_4.js";
7
7
  import { t as effectiveInputFromTurn } from "./stats-DAKBEKjc.js";
8
- import { i as basic_default } from "./presets-HDIxliiq.js";
9
- import { r as loadSession, t as createSession } from "./session-BDWZZaYa.js";
8
+ import { i as basic_default } from "./presets-ylu1ud2o.js";
9
+ import { r as loadSession, t as createSession } from "./session-DQ4bEncf.js";
10
+ import { r as fetchUrl } from "./fetch-url-Cgbq-HYx.js";
11
+ import { webSearch } from "./tools/web-search.js";
10
12
  import { basename, resolve } from "node:path";
11
13
  import { readFileSync } from "node:fs";
12
14
  import { Buffer } from "node:buffer";
@@ -986,6 +988,33 @@ const PLAN_READ_ONLY_TOOLS = new Set([
986
988
  "fetch_url",
987
989
  "skills_read"
988
990
  ]);
991
+ /**
992
+ * Search/fetch tools layered onto the DEFAULT ACP session (i.e. only when the
993
+ * host passes no `preset` of its own). The `basic` preset ships neither — they
994
+ * are opt-in at the SDK layer — but an editor-facing ACP agent should match the
995
+ * TUI. `web_search` in particular is the trigger that makes Anthropic-backed
996
+ * sessions use the native server-side `web_search_20250305` tool: without a
997
+ * registered `web_search` ToolDef the provider has nothing to upgrade.
998
+ */
999
+ const ACP_DEFAULT_EXTRA_TOOLS = {
1000
+ webSearch,
1001
+ fetchUrl
1002
+ };
1003
+ /**
1004
+ * Return `preset` with the default ACP search/fetch tools filled in. The
1005
+ * preset's own tools win on name collision, so this only adds what's missing.
1006
+ * Applied to the default base and by the `zidane-acp` CLI — never to a
1007
+ * host-provided `AcpServerOptions.preset`, which is honored verbatim.
1008
+ */
1009
+ function withAcpDefaultTools(preset) {
1010
+ return {
1011
+ ...preset,
1012
+ tools: {
1013
+ ...ACP_DEFAULT_EXTRA_TOOLS,
1014
+ ...preset.tools
1015
+ }
1016
+ };
1017
+ }
989
1018
  const DEFAULT_PERMISSION_OPTIONS = [
990
1019
  {
991
1020
  optionId: "allow_once",
@@ -1455,7 +1484,7 @@ var AcpServerImpl = class {
1455
1484
  const provider = router ? router.provider : this.resolveProvider();
1456
1485
  const runModel = initialChoiceId !== void 0 ? this.modelChoices.find((choice) => choice.id === initialChoiceId).model : this.options.model;
1457
1486
  const sessionId = session.id;
1458
- const base = this.options.preset ?? basic_default;
1487
+ const base = this.options.preset ?? withAcpDefaultTools(basic_default);
1459
1488
  const agentOptions = this.options.agentOptions ?? {};
1460
1489
  const wrappedTools = wrapToolsForAcpClient(mergeTools(base.tools, agentOptions.tools, this.options.tools), {
1461
1490
  client: this.requirePeer(),
@@ -1890,6 +1919,6 @@ function runAcpStdioServer(options) {
1890
1919
  };
1891
1920
  }
1892
1921
  //#endregion
1893
- export { acpMcpServersToZidane as a, stopReasonFromRun as c, buildStartLocalOptions as d, parseStartArgValues as f, createJsonRpcConnection as g, JsonRpcRemoteError as h, wrapToolsForAcpClient as i, toolResultToAcpContent as l, startProviderNames as m, AcpProtocolError as n, acpPromptToPromptParts as o, startLocalArgOptions as p, createAcpServer as r, sessionBlocksToAcp as s, runAcpStdioServer as t, StartUsageError as u };
1922
+ export { createJsonRpcConnection as _, wrapToolsForAcpClient as a, sessionBlocksToAcp as c, StartUsageError as d, buildStartLocalOptions as f, JsonRpcRemoteError as g, startProviderNames as h, withAcpDefaultTools as i, stopReasonFromRun as l, startLocalArgOptions as m, AcpProtocolError as n, acpMcpServersToZidane as o, parseStartArgValues as p, createAcpServer as r, acpPromptToPromptParts as s, runAcpStdioServer as t, toolResultToAcpContent as u };
1894
1923
 
1895
- //# sourceMappingURL=acp-BRQvvdnO.js.map
1924
+ //# sourceMappingURL=acp-yQbtu4mo.js.map