@bunny-agent/sdk 0.9.51 → 0.9.52

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
@@ -39,7 +39,7 @@ Your App → @bunny-agent/sdk → Coding Agent (Claude / Codex / …)
39
39
  |---------|-------------|
40
40
  | 🔌 **AI SDK Provider** | `createBunnyAgent()` returns a model you pass to `streamText` / `generateText` |
41
41
  | ⚛️ **React Hooks** | `useBunnyAgentChat`, `useArtifacts`, `useWriteTool`, `useAskUserQuestion` |
42
- | 🖥️ **Local Mode** | Built-in `LocalSandbox` — run on your machine for Desktop apps & debugging |
42
+ | 🖥️ **Local Mode** | Built-in `LocalMachine` (no isolation) and `SrtSandbox` (OS-level isolation) — run on your machine for Desktop apps & debugging |
43
43
  | ☁️ **Cloud Sandboxes** | Plug in [Sandock](https://sandock.ai), E2B, or Daytona for isolated cloud execution |
44
44
  | 🎨 **Agent Templates** | Markdown-based templates turn a generic agent into a domain expert |
45
45
  | 🔄 **Multi-turn Sessions** | Resume conversations with full filesystem continuity |
@@ -58,7 +58,7 @@ npm install @bunny-agent/sdk ai
58
58
 
59
59
  ```typescript
60
60
  // app/api/ai/route.ts
61
- import { createBunnyAgent, LocalSandbox } from "@bunny-agent/sdk";
61
+ import { createBunnyAgent, LocalMachine } from "@bunny-agent/sdk";
62
62
  import {
63
63
  convertToModelMessages,
64
64
  createUIMessageStream,
@@ -69,7 +69,7 @@ import {
69
69
  export async function POST(request: Request) {
70
70
  const { messages } = await request.json();
71
71
 
72
- const sandbox = new LocalSandbox({
72
+ const sandbox = new LocalMachine({
73
73
  workdir: process.cwd(),
74
74
  templatesPath: process.cwd(),
75
75
  runnerCommand: ["npx", "-y", "@bunny-agent/runner-cli@latest", "run"],
@@ -138,12 +138,27 @@ That's it — you now have a full Coding Agent streaming into your app.
138
138
 
139
139
  ### Local Mode (Desktop apps & debugging)
140
140
 
141
- `LocalSandbox` is built-in — no extra packages needed. The agent runs directly on your machine's filesystem.
141
+ `LocalMachine` is built-in — no extra packages needed. The agent runs directly on your machine's filesystem, with your user's permissions and **no isolation** (it was previously named `LocalSandbox`; that alias still works but is deprecated). When you want actual OS-level isolation on the local machine, use `SrtSandbox` instead — same API, but every command is wrapped with [Anthropic's sandbox runtime](https://www.npmjs.com/package/@anthropic-ai/sandbox-runtime) (bubblewrap on Linux, Seatbelt on macOS): writes are restricted to the workdir, network access is blocked unless you allowlist domains.
142
142
 
143
143
  ```typescript
144
- import { createBunnyAgent, LocalSandbox } from "@bunny-agent/sdk";
144
+ import { createBunnyAgent, SrtSandbox } from "@bunny-agent/sdk";
145
145
 
146
- const sandbox = new LocalSandbox({
146
+ const sandbox = new SrtSandbox({
147
+ workdir: "/path/to/project",
148
+ isolation: {
149
+ allowedDomains: ["api.anthropic.com", "*.npmjs.org"],
150
+ denyRead: ["~/.ssh", "~/.aws"],
151
+ allowWrite: ["~/.npm"], // runners that write to the home dir need this
152
+ },
153
+ });
154
+ ```
155
+
156
+ Linux needs `bubblewrap` + `socat` installed (and on Ubuntu 24.04+, an AppArmor profile that grants `userns` to bwrap). macOS works out of the box.
157
+
158
+ ```typescript
159
+ import { createBunnyAgent, LocalMachine } from "@bunny-agent/sdk";
160
+
161
+ const sandbox = new LocalMachine({
147
162
  workdir: "/path/to/project",
148
163
  templatesPath: "./my-agent-template",
149
164
  env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! },
@@ -224,7 +239,7 @@ my-agent/
224
239
  ```
225
240
 
226
241
  ```typescript
227
- const sandbox = new LocalSandbox({
242
+ const sandbox = new LocalMachine({
228
243
  workdir: process.cwd(),
229
244
  templatesPath: "./templates/analyst", // Point to your template
230
245
  });
@@ -256,10 +271,10 @@ import {
256
271
  #### `createBunnyAgent` — sandbox transport (cloud / local filesystem)
257
272
 
258
273
  ```typescript
259
- import { createBunnyAgent, LocalSandbox } from "@bunny-agent/sdk";
274
+ import { createBunnyAgent, LocalMachine } from "@bunny-agent/sdk";
260
275
 
261
276
  const bunnyAgent = createBunnyAgent({
262
- sandbox: SandboxAdapter, // LocalSandbox, SandockSandbox, E2BSandbox, etc.
277
+ sandbox: SandboxAdapter, // LocalMachine, SrtSandbox, SandockSandbox, E2BSandbox, etc.
263
278
  cwd?: string, // Working directory inside sandbox
264
279
  env?: Record<string, string>, // Environment variables
265
280
  template?: string, // Template name
@@ -272,7 +287,7 @@ const model = bunnyAgent("claude-sonnet-4-20250514");
272
287
 
273
288
  #### Daemon HTTP transport (same provider)
274
289
 
275
- **With any sandbox adapter** (E2B, Sandock, `LocalSandbox`, etc.): pass **`sandbox` + `daemonUrl`**. The URL is resolved **inside** the sandbox (the `vikadata/bunny-agent` image starts `bunny-agent-daemon` on port 3080). The SDK streams via `streamCodingRunFromSandbox` (`curl -N` in the sandbox, including `LocalSandbox`), not `fetch` from your server. It does **not** call `/healthz` for you — use `isBunnyAgentDaemonHealthy` from `@bunny-agent/sdk` when you want a probe before setting `daemonUrl` (e.g. to fall back to the CLI runner).
290
+ **With any sandbox adapter** (E2B, Sandock, `LocalMachine`, etc.): pass **`sandbox` + `daemonUrl`**. The URL is resolved **inside** the sandbox (the `vikadata/bunny-agent` image starts `bunny-agent-daemon` on port 3080). The SDK streams via `streamCodingRunFromSandbox` (`curl -N` in the sandbox, including `LocalMachine`), not `fetch` from your server. It does **not** call `/healthz` for you — use `isBunnyAgentDaemonHealthy` from `@bunny-agent/sdk` when you want a probe before setting `daemonUrl` (e.g. to fall back to the CLI runner).
276
291
 
277
292
  ```typescript
278
293
  import { createBunnyAgent, DEFAULT_BUNNY_AGENT_DAEMON_URL } from "@bunny-agent/sdk";
@@ -291,7 +306,7 @@ Omit `daemonUrl` to use the **CLI runner** in the same sandbox. `createBunnyAgen
291
306
 
292
307
  | Entry Point | Exports |
293
308
  |-------------|---------|
294
- | `@bunny-agent/sdk` | `createBunnyAgent`, `LocalSandbox`, `BunnyAgentLanguageModel`, `submitAnswer`, `DEFAULT_BUNNY_AGENT_DAEMON_URL` (re-exported from `@bunny-agent/manager`) |
309
+ | `@bunny-agent/sdk` | `createBunnyAgent`, `BunnyAgentLanguageModel`, `submitAnswer`, `DEFAULT_BUNNY_AGENT_DAEMON_URL`; re-exports `LocalMachine` (from `@bunny-agent/sandbox-local`) and `SrtSandbox` (from `@bunny-agent/sandbox-srt`) |
295
310
  | `@bunny-agent/sdk/react` | `useBunnyAgentChat`, `useArtifacts`, `useWriteTool`, `useAskUserQuestion`, `DEFAULT_BUNNY_AGENT_DAEMON_URL` (re-exported from `@bunny-agent/manager`) |
296
311
 
297
312
  ---
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { BunnyAgentOptions, SandboxAdapter, ToolRef, RunnerSpec } from '@bunny-agent/manager';
2
- export { DEFAULT_BUNNY_AGENT_DAEMON_URL, IsBunnyAgentDaemonHealthyOptions, LocalSandbox, LocalSandboxOptions, Message, RunnerEnvParams, RunnerType, SandboxAdapter, SandboxHandle, ToolRuntime, TranscriptEntry, buildRunnerEnv, isBunnyAgentDaemonHealthy } from '@bunny-agent/manager';
2
+ export { DEFAULT_BUNNY_AGENT_DAEMON_URL, IsBunnyAgentDaemonHealthyOptions, Message, RunnerEnvParams, RunnerType, SandboxAdapter, SandboxHandle, ToolRuntime, TranscriptEntry, buildRunnerEnv, isBunnyAgentDaemonHealthy } from '@bunny-agent/manager';
3
+ export { LocalMachine, LocalMachineOptions, LocalSandbox, LocalSandboxOptions } from '@bunny-agent/sandbox-local';
4
+ export { SrtIsolationOptions, SrtSandbox, SrtSandboxOptions } from '@bunny-agent/sandbox-srt';
3
5
  import { LanguageModelV3StreamPart, LanguageModelV3, LanguageModelV3CallOptions, LanguageModelV3GenerateResult, LanguageModelV3StreamResult, ProviderV3, EmbeddingModelV3, ImageModelV3, JSONValue, LanguageModelV3Usage } from '@ai-sdk/provider';
4
6
  export { LanguageModelV3StreamPart } from '@ai-sdk/provider';
5
7
  import { Tool } from 'ai';
@@ -165,11 +167,17 @@ declare class BunnyAgentLanguageModel implements LanguageModelV3 {
165
167
  private sessionId;
166
168
  private toolNameMap;
167
169
  private legacyTextPartCounter;
170
+ private receivedFinish;
171
+ private activeReasoningPartId;
168
172
  private logUnparsedStreamLine;
169
173
  constructor(modelOptions: BunnyAgentLanguageModelOptions);
170
174
  doGenerate(options: LanguageModelV3CallOptions): Promise<LanguageModelV3GenerateResult>;
171
175
  doStream(options: LanguageModelV3CallOptions): Promise<LanguageModelV3StreamResult>;
172
176
  private resetStreamState;
177
+ /** Close the open reasoning part, if any (returns the end part to emit). */
178
+ private closeReasoningPart;
179
+ /** Synthesize a terminal error+finish pair for streams that end (EOF or `[DONE]`) without ever emitting a "finish" part, so the UI shows an error instead of silently stalling. */
180
+ private buildUnexpectedEndParts;
173
181
  private buildCodingRunBody;
174
182
  private buildStreamResult;
175
183
  private createLanguageModelStreamFromSseReader;
package/dist/index.js CHANGED
@@ -2,9 +2,10 @@
2
2
  import {
3
3
  buildRunnerEnv,
4
4
  DEFAULT_BUNNY_AGENT_DAEMON_URL,
5
- isBunnyAgentDaemonHealthy,
6
- LocalSandbox
5
+ isBunnyAgentDaemonHealthy
7
6
  } from "@bunny-agent/manager";
7
+ import { LocalMachine, LocalSandbox } from "@bunny-agent/sandbox-local";
8
+ import { SrtSandbox } from "@bunny-agent/sandbox-srt";
8
9
 
9
10
  // src/provider/bunny-agent-language-model.ts
10
11
  import {
@@ -332,18 +333,24 @@ var BunnyAgentLanguageModel = class {
332
333
  sessionId;
333
334
  toolNameMap = /* @__PURE__ */ new Map();
334
335
  legacyTextPartCounter = 0;
336
+ receivedFinish = false;
337
+ activeReasoningPartId;
335
338
  logUnparsedStreamLine(candidate, error) {
336
339
  const trimmed = candidate.trim();
337
340
  if (!trimmed) return;
338
341
  const looksLikeError = /\b(error|failed|exception|traceback|fatal)\b/i.test(
339
342
  trimmed
340
343
  );
344
+ const snippet = trimmed.slice(0, 500);
345
+ const msg = error instanceof Error ? error.message : String(error);
341
346
  if (looksLikeError) {
342
- const snippet = trimmed.slice(0, 500);
343
- const msg = error instanceof Error ? error.message : String(error);
344
347
  this.logger.error(
345
348
  `[bunny-agent] Unparsed stream line (likely runner error): ${snippet} | parser: ${msg}`
346
349
  );
350
+ } else {
351
+ this.logger.debug(
352
+ `[bunny-agent] Unparsed stream line: ${snippet} | parser: ${msg}`
353
+ );
347
354
  }
348
355
  }
349
356
  constructor(modelOptions) {
@@ -365,6 +372,7 @@ var BunnyAgentLanguageModel = class {
365
372
  let usage = createEmptyUsage();
366
373
  let providerMetadata;
367
374
  const textParts = /* @__PURE__ */ new Map();
375
+ const reasoningParts = /* @__PURE__ */ new Map();
368
376
  const toolInputs = /* @__PURE__ */ new Map();
369
377
  try {
370
378
  while (true) {
@@ -392,6 +400,27 @@ var BunnyAgentLanguageModel = class {
392
400
  }
393
401
  break;
394
402
  }
403
+ case "reasoning-start": {
404
+ reasoningParts.set(value.id, { text: "" });
405
+ break;
406
+ }
407
+ case "reasoning-delta": {
408
+ const part = reasoningParts.get(value.id);
409
+ if (part) {
410
+ part.text += value.delta;
411
+ }
412
+ break;
413
+ }
414
+ case "reasoning-end": {
415
+ const part = reasoningParts.get(value.id);
416
+ if (part && part.text.length > 0) {
417
+ content.push({
418
+ type: "reasoning",
419
+ text: part.text
420
+ });
421
+ }
422
+ break;
423
+ }
395
424
  case "tool-input-start": {
396
425
  toolInputs.set(value.id, { toolName: value.toolName, input: "" });
397
426
  break;
@@ -517,6 +546,36 @@ var BunnyAgentLanguageModel = class {
517
546
  this.sessionId = void 0;
518
547
  this.toolNameMap = /* @__PURE__ */ new Map();
519
548
  this.legacyTextPartCounter = 0;
549
+ this.receivedFinish = false;
550
+ this.activeReasoningPartId = void 0;
551
+ }
552
+ /** Close the open reasoning part, if any (returns the end part to emit). */
553
+ closeReasoningPart() {
554
+ if (this.activeReasoningPartId == null) return [];
555
+ const id = this.activeReasoningPartId;
556
+ this.activeReasoningPartId = void 0;
557
+ return [{ type: "reasoning-end", id }];
558
+ }
559
+ /** Synthesize a terminal error+finish pair for streams that end (EOF or `[DONE]`) without ever emitting a "finish" part, so the UI shows an error instead of silently stalling. */
560
+ buildUnexpectedEndParts() {
561
+ return [
562
+ {
563
+ type: "error",
564
+ error: new Error(
565
+ "The agent stream ended unexpectedly before completing."
566
+ )
567
+ },
568
+ {
569
+ type: "finish",
570
+ finishReason: { unified: "error", raw: "unexpected-stream-end" },
571
+ usage: createEmptyUsage(),
572
+ providerMetadata: {
573
+ "bunny-agent": {
574
+ sessionId: this.sessionId
575
+ }
576
+ }
577
+ }
578
+ ];
520
579
  }
521
580
  buildCodingRunBody(messages, cwdFallback, toolRefs) {
522
581
  const runner = this.options.runner;
@@ -565,6 +624,11 @@ var BunnyAgentLanguageModel = class {
565
624
  controller.enqueue(part);
566
625
  }
567
626
  }
627
+ if (!self.receivedFinish) {
628
+ for (const part of self.buildUnexpectedEndParts()) {
629
+ controller.enqueue(part);
630
+ }
631
+ }
568
632
  controller.close();
569
633
  break;
570
634
  }
@@ -602,6 +666,11 @@ var BunnyAgentLanguageModel = class {
602
666
  }
603
667
  }
604
668
  if (foundDone) {
669
+ if (!self.receivedFinish) {
670
+ for (const part of self.buildUnexpectedEndParts()) {
671
+ controller.enqueue(part);
672
+ }
673
+ }
605
674
  controller.close();
606
675
  return;
607
676
  }
@@ -644,6 +713,7 @@ var BunnyAgentLanguageModel = class {
644
713
  const parsed = JSON.parse(data);
645
714
  const parsedType = typeof parsed.type === "string" ? parsed.type : void 0;
646
715
  if (!parsedType && typeof parsed.error === "string") {
716
+ this.receivedFinish = true;
647
717
  return [
648
718
  {
649
719
  type: "error",
@@ -690,7 +760,29 @@ var BunnyAgentLanguageModel = class {
690
760
  }
691
761
  break;
692
762
  }
763
+ // Runners (claude/codex) emit reasoning as untagged deltas:
764
+ // {type:"reasoning", text}. Wrap them in a synthesized
765
+ // reasoning-start/delta/end part stream for the AI SDK.
766
+ case "reasoning": {
767
+ const text = typeof parsed.text === "string" ? parsed.text : typeof parsed.delta === "string" ? parsed.delta : "";
768
+ if (text.length > 0) {
769
+ if (this.activeReasoningPartId == null) {
770
+ this.activeReasoningPartId = `reasoning-${++this.legacyTextPartCounter}`;
771
+ parts.push({
772
+ type: "reasoning-start",
773
+ id: this.activeReasoningPartId
774
+ });
775
+ }
776
+ parts.push({
777
+ type: "reasoning-delta",
778
+ id: this.activeReasoningPartId,
779
+ delta: text
780
+ });
781
+ }
782
+ break;
783
+ }
693
784
  case "text-start": {
785
+ parts.push(...this.closeReasoningPart());
694
786
  parts.push({
695
787
  type: "text-start",
696
788
  id: parsed.id,
@@ -718,6 +810,7 @@ var BunnyAgentLanguageModel = class {
718
810
  break;
719
811
  }
720
812
  case "tool-input-start": {
813
+ parts.push(...this.closeReasoningPart());
721
814
  parts.push({
722
815
  type: "tool-input-start",
723
816
  id: parsed.toolCallId,
@@ -775,6 +868,7 @@ var BunnyAgentLanguageModel = class {
775
868
  break;
776
869
  }
777
870
  case "error": {
871
+ this.receivedFinish = true;
778
872
  parts.push({
779
873
  type: "error",
780
874
  error: new Error(
@@ -784,6 +878,8 @@ var BunnyAgentLanguageModel = class {
784
878
  break;
785
879
  }
786
880
  case "finish": {
881
+ this.receivedFinish = true;
882
+ parts.push(...this.closeReasoningPart());
787
883
  const rawFinishReason = parsed.finishReason;
788
884
  let finishReason;
789
885
  if (typeof rawFinishReason === "object" && rawFinishReason !== null && "unified" in rawFinishReason) {
@@ -899,7 +995,7 @@ function createBunnyAgent(defaultOptions) {
899
995
  const logger = getProviderLogger(defaultOptions);
900
996
  if (!defaultOptions.sandbox) {
901
997
  throw new Error(
902
- "Provide a `sandbox` adapter (e.g. E2BSandbox, LocalSandbox). Optional `daemonUrl` uses in-sandbox HTTP to bunny-agent-daemon (no automatic `/healthz` probe). Use `isBunnyAgentDaemonHealthy` from `@bunny-agent/sdk` if you want to probe and omit `daemonUrl` for CLI fallback. Omit `daemonUrl` to always use CLI."
998
+ "Provide a `sandbox` adapter (e.g. E2BSandbox, LocalMachine). Optional `daemonUrl` uses in-sandbox HTTP to bunny-agent-daemon (no automatic `/healthz` probe). Use `isBunnyAgentDaemonHealthy` from `@bunny-agent/sdk` if you want to probe and omit `daemonUrl` for CLI fallback. Omit `daemonUrl` to always use CLI."
903
999
  );
904
1000
  }
905
1001
  const createModel = (modelId, options = {}) => {
@@ -1006,7 +1102,9 @@ var VERSION = "0.1.0";
1006
1102
  export {
1007
1103
  BunnyAgentLanguageModel,
1008
1104
  DEFAULT_BUNNY_AGENT_DAEMON_URL,
1105
+ LocalMachine,
1009
1106
  LocalSandbox,
1107
+ SrtSandbox,
1010
1108
  VERSION,
1011
1109
  buildRunnerEnv,
1012
1110
  bunnyHttpTool,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/provider/bunny-agent-language-model.ts","../src/provider/logging.ts","../src/provider/tool-refs.ts","../src/provider/usage.ts","../src/provider/bunny-agent-provider.ts","../src/provider/question-processor.ts"],"sourcesContent":["/**\n * @bunny-agent/sdk\n *\n * BunnyAgent SDK - AI Provider and React hooks for building AI chat interfaces.\n *\n * Main entry point exports the AI provider (backend).\n * React hooks are available via \"@bunny-agent/sdk/react\".\n *\n * @example\n * ```typescript\n * // Backend - Provider\n * import { createBunnyAgent } from \"@bunny-agent/sdk\";\n * const bunnyAgent = createBunnyAgent({ sandbox, env });\n * const model = bunnyAgent(\"sonnet\");\n *\n * // Frontend - React hooks\n * import { useBunnyAgentChat } from \"@bunny-agent/sdk/react\";\n * const { messages, sendMessage } = useBunnyAgentChat({ apiEndpoint: \"/api/ai\" });\n * ```\n */\n\nexport type {\n IsBunnyAgentDaemonHealthyOptions,\n LocalSandboxOptions,\n RunnerEnvParams,\n RunnerType,\n} from \"@bunny-agent/manager\";\n// Re-export LocalSandbox for convenience\n// Re-export env helpers\nexport {\n buildRunnerEnv,\n DEFAULT_BUNNY_AGENT_DAEMON_URL,\n isBunnyAgentDaemonHealthy,\n LocalSandbox,\n} from \"@bunny-agent/manager\";\nexport type {\n ArtifactProcessor,\n ArtifactResult,\n BunnyAgentLanguageModelOptions,\n BunnyAgentModelId,\n BunnyAgentProvider,\n BunnyAgentProviderSettings,\n // Re-exports from @ai-sdk/provider\n LanguageModelV3StreamPart,\n Logger,\n Message,\n Question,\n // Re-exports from @bunny-agent/manager\n SandboxAdapter,\n SandboxHandle,\n StreamWriter,\n SubmitAnswerOptions,\n SubmitAnswerParams,\n ToolRuntime,\n TranscriptEntry,\n} from \"./provider\";\n// Provider exports\nexport {\n BunnyAgentLanguageModel,\n bunnyHttpTool,\n bunnySandboxTool,\n createBunnyAgent,\n getBunnyAgentMetadata,\n getBunnyAgentUsage,\n submitAnswer,\n} from \"./provider\";\n\nexport const VERSION = \"0.1.0\";\n","import type {\n JSONValue,\n LanguageModelV3,\n LanguageModelV3CallOptions,\n LanguageModelV3Content,\n LanguageModelV3FinishReason,\n LanguageModelV3GenerateResult,\n LanguageModelV3Prompt,\n LanguageModelV3StreamPart,\n LanguageModelV3StreamResult,\n LanguageModelV3Usage,\n SharedV3ProviderMetadata,\n SharedV3Warning,\n} from \"@ai-sdk/provider\";\nimport {\n BunnyAgent,\n type BunnyAgentCodingRunBody,\n type Message,\n type RunnerSpec,\n streamCodingRunFromSandbox,\n type ToolRef,\n} from \"@bunny-agent/manager\";\nimport { getProviderLogger } from \"./logging\";\nimport { compileToolRefsFromLanguageModelTools } from \"./tool-refs\";\nimport type {\n BunnyAgentModelId,\n BunnyAgentProviderSettings,\n Logger,\n} from \"./types\";\nimport { normalizeBunnyAgentUsage } from \"./usage\";\n\n/**\n * Options for creating a BunnyAgent language model instance.\n */\nexport interface BunnyAgentLanguageModelOptions {\n id: BunnyAgentModelId;\n options: BunnyAgentProviderSettings & { runner: RunnerSpec };\n}\n\n/** Format error so message and cause chain are visible (e.g. includes \"Fatal error: ...\" from runner). */\nfunction formatErrorForLog(error: unknown): string {\n if (error instanceof Error) {\n const parts = [error.message];\n let cause: unknown = error.cause;\n while (cause instanceof Error) {\n parts.push(cause.message);\n cause = cause.cause;\n }\n return parts.join(\" | cause: \");\n }\n return String(error);\n}\n\n/** Bridge async iterable (sandbox exec / curl) to Web ReadableStream for SSE parsing. */\nfunction asyncIterableToReadableStream(\n iterable: AsyncIterable<Uint8Array>,\n): ReadableStream<Uint8Array> {\n const iterator = iterable[Symbol.asyncIterator]();\n return new ReadableStream<Uint8Array>({\n async pull(controller) {\n try {\n while (true) {\n const { done, value } = await iterator.next();\n if (done) {\n controller.close();\n return;\n }\n if (value.byteLength > 0) {\n controller.enqueue(value);\n return;\n }\n }\n } catch (error) {\n const isAbort =\n (error instanceof Error && error.name === \"AbortError\") ||\n (typeof DOMException !== \"undefined\" &&\n error instanceof DOMException &&\n error.name === \"AbortError\") ||\n (error instanceof Error && /abort/i.test(error.message));\n if (isAbort) {\n controller.close();\n } else {\n controller.error(error);\n }\n }\n },\n async cancel(reason) {\n await iterator.return?.(reason);\n },\n });\n}\n\nfunction mergeToolRefs(\n staticToolRefs: ToolRef[] | undefined,\n callToolRefs: ToolRef[] | undefined,\n): ToolRef[] | undefined {\n const merged = [...(staticToolRefs ?? []), ...(callToolRefs ?? [])];\n return merged.length > 0 ? merged : undefined;\n}\n\nfunction extractTextContent(content: Message[\"content\"]): string {\n if (typeof content === \"string\") return content;\n return content\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text)\n .join(\"\\n\");\n}\n\nfunction getLastUserTextFromMessages(messages: Message[]): string {\n // Collect all trailing user messages (handles batched/queued messages)\n const trailingUserMessages: Message[] = [];\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === \"user\") {\n trailingUserMessages.unshift(messages[i]);\n } else {\n break;\n }\n }\n if (trailingUserMessages.length === 0) return \"\";\n return trailingUserMessages\n .map((msg) => extractTextContent(msg.content))\n .join(\"\\n\\n\");\n}\n\n/**\n * Serialize the full transcript into a single userInput string.\n *\n * Used when the runtime has no session context to hydrate from — i.e. neither\n * `resume` (existing runner session id) nor `forkFrom` (parent session to\n * snapshot-clone) is set. In that case the runner starts a brand-new session\n * whose only visible input is the `userInput` payload; if we passed only the\n * last user turn the runner would lose all prior conversation, which is what\n * happened when share-continued fallback sessions arrived at pi with just\n * the current question instead of the copied `agent_messages` history.\n *\n * Format: prior turns labeled by role, then the current user message under\n * a \"Current message\" header so the runner treats it as the actual prompt.\n */\nfunction serializeMessagesToUserInput(messages: Message[]): string {\n // Split trailing consecutive user messages (the \"current\" turn) from history.\n let currentStart = messages.length;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === \"user\") {\n currentStart = i;\n } else {\n break;\n }\n }\n\n const history = messages.slice(0, currentStart);\n const current = messages.slice(currentStart);\n\n const currentText = current\n .map((msg) => extractTextContent(msg.content))\n .filter((t) => t.length > 0)\n .join(\"\\n\\n\");\n\n if (history.length === 0) return currentText;\n\n const historyLines: string[] = [];\n for (const msg of history) {\n const text = extractTextContent(msg.content);\n if (text.length === 0) continue;\n const label =\n msg.role === \"user\"\n ? \"User\"\n : msg.role === \"assistant\"\n ? \"Assistant\"\n : \"System\";\n historyLines.push(`${label}: ${text}`);\n }\n\n if (historyLines.length === 0) return currentText;\n\n const historyBlock = `Previous conversation:\\n\\n${historyLines.join(\"\\n\\n\")}`;\n if (currentText.length === 0) return historyBlock;\n return `${historyBlock}\\n\\nCurrent message:\\n\\n${currentText}`;\n}\n\nfunction createEmptyUsage(): LanguageModelV3Usage {\n return {\n inputTokens: {\n total: 0,\n noCache: 0,\n cacheRead: 0,\n cacheWrite: 0,\n },\n outputTokens: {\n total: 0,\n text: undefined,\n reasoning: undefined,\n },\n raw: undefined,\n };\n}\n\nfunction readToolDynamicFlag(parsed: Record<string, unknown>): boolean {\n if (typeof parsed.dynamic === \"boolean\") {\n return parsed.dynamic;\n }\n return parsed.providerExecuted === true;\n}\n\n/**\n * BunnyAgent Language Model implementation for AI SDK.\n */\nexport class BunnyAgentLanguageModel implements LanguageModelV3 {\n readonly specificationVersion = \"v3\" as const;\n readonly provider: string;\n readonly modelId: string;\n readonly supportedUrls: Record<string, RegExp[]> = {\n \"image/*\": [/.*/],\n };\n\n readonly settings: BunnyAgentProviderSettings & { runner: RunnerSpec };\n private readonly options: BunnyAgentProviderSettings & { runner: RunnerSpec };\n private readonly logger: Logger;\n private sessionId: string | undefined;\n private toolNameMap: Map<string, string> = new Map();\n private legacyTextPartCounter = 0;\n\n private logUnparsedStreamLine(candidate: string, error: unknown): void {\n const trimmed = candidate.trim();\n if (!trimmed) return;\n const looksLikeError = /\\b(error|failed|exception|traceback|fatal)\\b/i.test(\n trimmed,\n );\n if (looksLikeError) {\n const snippet = trimmed.slice(0, 500);\n const msg = error instanceof Error ? error.message : String(error);\n this.logger.error(\n `[bunny-agent] Unparsed stream line (likely runner error): ${snippet} | parser: ${msg}`,\n );\n }\n }\n\n constructor(modelOptions: BunnyAgentLanguageModelOptions) {\n this.modelId = modelOptions.id;\n this.settings = modelOptions.options;\n this.options = modelOptions.options;\n this.logger = getProviderLogger(modelOptions.options);\n this.provider = \"bunny-agent\";\n }\n\n async doGenerate(\n options: LanguageModelV3CallOptions,\n ): Promise<LanguageModelV3GenerateResult> {\n const { stream, request } = await this.doStream(options);\n const reader = stream.getReader();\n\n const content: LanguageModelV3Content[] = [];\n const warnings: SharedV3Warning[] = [];\n let finishReason: LanguageModelV3FinishReason = {\n unified: \"other\",\n raw: undefined,\n };\n let usage: LanguageModelV3Usage = createEmptyUsage();\n let providerMetadata: SharedV3ProviderMetadata | undefined;\n\n const textParts: Map<string, { text: string }> = new Map();\n const toolInputs: Map<string, { toolName: string; input: string }> =\n new Map();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n switch (value.type) {\n case \"text-start\": {\n textParts.set(value.id, { text: \"\" });\n break;\n }\n case \"text-delta\": {\n const part = textParts.get(value.id);\n if (part) {\n part.text += value.delta;\n }\n break;\n }\n case \"text-end\": {\n const part = textParts.get(value.id);\n if (part) {\n content.push({\n type: \"text\",\n text: part.text,\n });\n }\n break;\n }\n case \"tool-input-start\": {\n toolInputs.set(value.id, { toolName: value.toolName, input: \"\" });\n break;\n }\n case \"tool-input-delta\": {\n const tool = toolInputs.get(value.id);\n if (tool) {\n tool.input += value.delta;\n }\n break;\n }\n case \"tool-input-end\": {\n break;\n }\n case \"tool-call\": {\n content.push({\n type: \"tool-call\",\n toolCallId: value.toolCallId,\n toolName: value.toolName,\n input: value.input,\n providerExecuted: value.providerExecuted,\n });\n break;\n }\n case \"stream-start\": {\n warnings.push(...value.warnings);\n break;\n }\n case \"error\": {\n // `value.error` type comes from AI SDK and can be `{}`-shaped.\n // Convert it to a readable string safely.\n const message =\n value.error instanceof Error\n ? value.error.message\n : typeof value.error === \"string\"\n ? value.error\n : value.error\n ? String(value.error)\n : \"Unknown error\";\n\n // Surface errors as assistant text + mark finishReason=error.\n content.push({ type: \"text\", text: message });\n finishReason = { unified: \"error\", raw: \"error\" };\n break;\n }\n case \"finish\": {\n finishReason = value.finishReason;\n usage = value.usage;\n providerMetadata = value.providerMetadata;\n break;\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n return {\n content,\n finishReason,\n usage,\n providerMetadata,\n request,\n warnings,\n };\n }\n\n async doStream(\n options: LanguageModelV3CallOptions,\n ): Promise<LanguageModelV3StreamResult> {\n const { prompt, abortSignal } = options;\n const messages = this.convertPromptToMessages(prompt);\n\n this.resetStreamState();\n\n this.logger.debug(\n `[bunny-agent] Starting stream with ${messages.length} messages`,\n );\n\n const sandbox = this.options.sandbox;\n if (!sandbox) {\n throw new Error(\n \"BunnyAgent language model requires a sandbox adapter (set `sandbox` on the provider).\",\n );\n }\n\n const callToolRefs = compileToolRefsFromLanguageModelTools(options.tools);\n const toolRefs = mergeToolRefs(this.options.toolRefs, callToolRefs);\n\n const daemonUrl = this.options.daemonUrl;\n\n if (daemonUrl) {\n const handle = await sandbox.attach();\n const sandboxEnv = sandbox.getEnv?.() ?? {};\n const runnerEnv = { ...sandboxEnv, ...this.options.env };\n const body: BunnyAgentCodingRunBody = {\n ...this.buildCodingRunBody(messages, handle.getWorkdir(), toolRefs),\n ...(Object.keys(runnerEnv).length > 0 ? { env: runnerEnv } : {}),\n ...(this.options.systemEnv &&\n Object.keys(this.options.systemEnv).length > 0\n ? { systemEnv: this.options.systemEnv }\n : {}),\n };\n const execOpts = {\n cwd: this.options.cwd ?? handle.getWorkdir(),\n signal: abortSignal,\n };\n const iterable = streamCodingRunFromSandbox(\n handle,\n daemonUrl,\n body,\n execOpts,\n );\n const bytesStream = asyncIterableToReadableStream(iterable);\n return this.buildStreamResult(bytesStream, messages);\n }\n\n const sandboxEnv = sandbox.getEnv?.() ?? {};\n const sandboxWorkdir =\n this.options.cwd ?? sandbox.getWorkdir?.() ?? \"/workspace\";\n\n // CLI fallback path: each `bunny-agent run` invocation is single-request /\n // single-tenant, so the runner's `process.env` IS the expected bash\n // environment. We therefore merge env + systemEnv into one map and let\n // sandbox.exec inject everything. Pi's bash tool inherits this via its\n // default `ctx.env`, so no JSON-payload channel is needed.\n const agent = new BunnyAgent({\n sandbox,\n runner: this.options.runner,\n env: {\n ...sandboxEnv,\n ...this.options.env,\n ...(this.options.systemEnv ?? {}),\n },\n });\n\n try {\n const bytesStream = await agent.stream({\n messages,\n workspace: {\n path: sandboxWorkdir,\n },\n resume: this.options.resume,\n forkFrom: this.options.forkFrom,\n signal: abortSignal,\n ...(toolRefs && toolRefs.length > 0 ? { toolRefs } : {}),\n });\n return this.buildStreamResult(bytesStream, messages);\n } catch (error) {\n await agent.destroy().catch(() => {});\n throw error;\n }\n }\n\n private resetStreamState(): void {\n this.sessionId = undefined;\n this.toolNameMap = new Map();\n this.legacyTextPartCounter = 0;\n }\n\n private buildCodingRunBody(\n messages: Message[],\n cwdFallback: string,\n toolRefs: ToolRef[] | undefined,\n ): BunnyAgentCodingRunBody {\n const runner = this.options.runner;\n const cwd = this.options.cwd ?? cwdFallback;\n\n // When the runner has session context to hydrate from (resume points at\n // an existing runner session, or forkFrom snapshot-clones a parent), send\n // only the last user turn — history lives in the runner's session file.\n // Otherwise it's a fresh session with no server-side history, so serialize\n // the full transcript into userInput so the runner sees prior turns.\n const hasRuntimeHistory = Boolean(\n this.options.resume ?? this.options.forkFrom,\n );\n const userInput = hasRuntimeHistory\n ? getLastUserTextFromMessages(messages)\n : serializeMessagesToUserInput(messages);\n\n return {\n runner: runner.runnerType ?? \"claude\",\n model: this.modelId,\n userInput,\n cwd,\n resume: this.options.resume,\n forkFrom: this.options.forkFrom,\n systemPrompt: this.options.systemPrompt ?? runner.systemPrompt,\n maxTurns: this.options.maxTurns ?? runner.maxTurns,\n allowedTools: runner.allowedTools ?? this.options.allowedTools,\n skillPaths: runner.skillPaths ?? this.options.skillPaths,\n yolo: this.options.yolo,\n ...(toolRefs && toolRefs.length > 0 ? { toolRefs } : {}),\n ...(this.options.effort ? { effort: this.options.effort } : {}),\n };\n }\n\n private buildStreamResult(\n bytesStream: ReadableStream<Uint8Array>,\n messages: Message[],\n ): LanguageModelV3StreamResult {\n const reader = bytesStream.getReader();\n\n return {\n stream: this.createLanguageModelStreamFromSseReader(reader),\n request: {\n body: JSON.stringify({ messages }),\n },\n };\n }\n\n private createLanguageModelStreamFromSseReader(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n ): ReadableStream<LanguageModelV3StreamPart> {\n const self = this;\n\n return new ReadableStream<LanguageModelV3StreamPart>({\n async start(controller) {\n try {\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) {\n if (buffer.trim()) {\n const parts = self.parseSSEBuffer(buffer);\n for (const part of parts) {\n controller.enqueue(part);\n }\n }\n controller.close();\n break;\n }\n\n const text = new TextDecoder().decode(value);\n buffer += text;\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n let foundDone = false;\n for (const line of lines) {\n const candidate = line.startsWith(\"data: \")\n ? line.slice(6)\n : line.trim();\n if (!candidate) continue;\n if (candidate === \"[DONE]\") {\n foundDone = true;\n continue;\n }\n\n try {\n const parts = self.parseSSEData(candidate);\n for (const part of parts) {\n controller.enqueue(part);\n\n if (self.sessionId) {\n const sessionId: string = self.sessionId;\n\n if (self.options.artifactProcessors?.length) {\n for (const processor of self.options.artifactProcessors) {\n Promise.resolve()\n .then(() => processor.onChange(part, sessionId))\n .catch((e) => {\n self.logger.error(\n `[bunny-agent] Artifact processor error: ${e}`,\n );\n });\n }\n }\n }\n }\n } catch (e) {\n // daemon /api/coding/run or CLI runner may emit plain text lines.\n self.logUnparsedStreamLine(candidate, e);\n }\n }\n\n if (foundDone) {\n controller.close();\n return;\n }\n }\n } catch (error) {\n const isAbort =\n (error instanceof Error && error.name === \"AbortError\") ||\n (typeof DOMException !== \"undefined\" &&\n error instanceof DOMException &&\n error.name === \"AbortError\") ||\n (error instanceof Error && /abort/i.test(error.message));\n if (isAbort) {\n self.logger.info(\"[bunny-agent] Stream aborted by user\");\n controller.close();\n } else {\n self.logger.error(\n `[bunny-agent] Stream error: ${formatErrorForLog(error)}`,\n );\n controller.error(error);\n }\n }\n },\n\n cancel() {\n reader.cancel();\n },\n });\n }\n\n private parseSSEBuffer(buffer: string): LanguageModelV3StreamPart[] {\n const parts: LanguageModelV3StreamPart[] = [];\n const lines = buffer.split(\"\\n\");\n\n for (const line of lines) {\n const candidate = line.startsWith(\"data: \") ? line.slice(6) : line.trim();\n if (!candidate || candidate === \"[DONE]\") continue;\n try {\n const parsedParts = this.parseSSEData(candidate);\n parts.push(...parsedParts);\n } catch (e) {\n this.logUnparsedStreamLine(candidate, e);\n }\n }\n\n return parts;\n }\n\n private parseSSEData(data: string): LanguageModelV3StreamPart[] {\n const parts: LanguageModelV3StreamPart[] = [];\n const parsed = JSON.parse(data) as Record<string, unknown>;\n const parsedType =\n typeof parsed.type === \"string\" ? parsed.type : undefined;\n\n // daemon NDJSON errors may arrive as: {\"error\":\"...\"} (without type)\n if (!parsedType && typeof parsed.error === \"string\") {\n return [\n {\n type: \"error\",\n error: new Error(parsed.error),\n },\n ];\n }\n\n switch (parsedType) {\n case \"start\": {\n break;\n }\n\n // Backward-compatible NDJSON chunk from daemon tests/mock runners.\n case \"text\": {\n const text = typeof parsed.text === \"string\" ? parsed.text : \"\";\n if (text.length > 0) {\n const id = `legacy-text-${++this.legacyTextPartCounter}`;\n parts.push(\n {\n type: \"text-start\",\n id,\n providerMetadata: {\n \"bunny-agent\": {\n sessionId: this.sessionId,\n } as unknown as SharedV3ProviderMetadata,\n },\n },\n { type: \"text-delta\", id, delta: text },\n { type: \"text-end\", id },\n );\n }\n break;\n }\n\n case \"message-metadata\": {\n const metadata = parsed.messageMetadata as Record<string, unknown>;\n if (metadata?.sessionId && typeof metadata.sessionId === \"string\") {\n this.sessionId = metadata.sessionId;\n this.logger.debug(\n `[bunny-agent] Session ID extracted: ${this.sessionId}`,\n );\n parts.push({\n type: \"raw\",\n rawValue: this.sessionId,\n });\n }\n break;\n }\n\n case \"text-start\": {\n parts.push({\n type: \"text-start\",\n id: parsed.id as string,\n providerMetadata: {\n \"bunny-agent\": {\n sessionId: this.sessionId,\n } as unknown as SharedV3ProviderMetadata,\n },\n });\n break;\n }\n\n case \"text-delta\": {\n parts.push({\n type: \"text-delta\",\n id: parsed.id as string,\n delta: parsed.delta as string,\n });\n break;\n }\n\n case \"text-end\": {\n parts.push({\n type: \"text-end\",\n id: parsed.id as string,\n });\n break;\n }\n\n case \"tool-input-start\": {\n parts.push({\n type: \"tool-input-start\",\n id: parsed.toolCallId as string,\n toolName: parsed.toolName as string,\n dynamic: readToolDynamicFlag(parsed),\n providerExecuted: parsed.providerExecuted as boolean,\n });\n break;\n }\n\n case \"tool-input-delta\": {\n parts.push({\n type: \"tool-input-delta\",\n id: parsed.toolCallId as string,\n delta: parsed.inputTextDelta as string,\n });\n break;\n }\n case \"tool-input-available\": {\n const toolCallId = parsed.toolCallId as string;\n const toolName = parsed.toolName as string;\n const input = parsed.input as Record<string, unknown>;\n this.toolNameMap.set(toolCallId, toolName);\n parts.push({\n type: \"tool-call\",\n toolCallId,\n toolName,\n input: JSON.stringify(input),\n dynamic: readToolDynamicFlag(parsed),\n providerExecuted: parsed.providerExecuted as boolean,\n });\n break;\n }\n\n case \"tool-output-available\": {\n const toolName = this.toolNameMap.get(parsed.toolCallId as string);\n parts.push({\n type: \"tool-result\",\n toolCallId: parsed.toolCallId as string,\n toolName: toolName ?? \"\",\n result: parsed.output as NonNullable<JSONValue>,\n isError: parsed.isError as boolean,\n dynamic: readToolDynamicFlag(parsed),\n });\n break;\n }\n case \"tool-output-error\": {\n const toolName = this.toolNameMap.get(parsed.toolCallId as string);\n parts.push({\n type: \"tool-result\",\n toolCallId: parsed.toolCallId as string,\n toolName: toolName ?? \"\",\n result: (parsed.errorText as string) ?? \"Tool execution failed\",\n isError: true,\n dynamic: readToolDynamicFlag(parsed),\n });\n break;\n }\n case \"error\": {\n parts.push({\n type: \"error\",\n error: new Error(\n (parsed.errorText as string) ||\n (parsed.error as string) ||\n \"Unknown stream error\",\n ),\n });\n break;\n }\n\n case \"finish\": {\n const rawFinishReason = parsed.finishReason;\n let finishReason: LanguageModelV3FinishReason;\n\n if (\n typeof rawFinishReason === \"object\" &&\n rawFinishReason !== null &&\n \"unified\" in rawFinishReason\n ) {\n finishReason = rawFinishReason as LanguageModelV3FinishReason;\n } else {\n finishReason = this.mapFinishReason(rawFinishReason as string);\n }\n\n const usage =\n normalizeBunnyAgentUsage(\n (parsed.messageMetadata as Record<string, unknown>) ?? undefined,\n ) ?? createEmptyUsage();\n\n parts.push({\n type: \"finish\",\n finishReason,\n usage,\n providerMetadata: {\n \"bunny-agent\": {\n ...((parsed.messageMetadata as Record<string, unknown>) ?? {}),\n sessionId: this.sessionId,\n } as unknown as SharedV3ProviderMetadata,\n },\n });\n break;\n }\n }\n\n return parts;\n }\n\n private convertPromptToMessages(prompt: LanguageModelV3Prompt): Message[] {\n const messages: Message[] = [];\n\n for (const message of prompt) {\n switch (message.role) {\n case \"system\": {\n messages.push({\n role: \"system\",\n content: message.content,\n });\n break;\n }\n\n case \"user\": {\n const parts = message.content\n .map((part) => {\n if (part.type === \"text\") {\n return { type: \"text\" as const, text: part.text };\n }\n if (part.type === \"file\") {\n // LanguageModelV3FilePart: data is Uint8Array | string | URL, mediaType is IANA type\n let dataStr = \"\";\n if (part.data instanceof Uint8Array) {\n dataStr = `data:${part.mediaType};base64,${Buffer.from(part.data).toString(\"base64\")}`;\n } else if (part.data instanceof URL) {\n dataStr = part.data.toString();\n } else if (typeof part.data === \"string\") {\n // Already a data URL or base64 string\n dataStr = part.data;\n }\n return {\n type: \"image\" as const,\n mimeType: part.mediaType || \"image/png\",\n data: dataStr,\n };\n }\n return null;\n })\n .filter(\n (\n p,\n ): p is\n | { type: \"text\"; text: string }\n | { type: \"image\"; mimeType: string; data: string } =>\n p !== null,\n );\n\n if (parts.length > 0) {\n // If only text parts, combine them into a string for cleaner payload, else pass array\n const isAllText = parts.every((p) => p.type === \"text\");\n messages.push({\n role: \"user\",\n content: isAllText\n ? parts\n .map((p) => (p as { type: \"text\"; text: string }).text)\n .join(\"\\n\")\n : parts,\n });\n }\n break;\n }\n\n case \"assistant\": {\n const textParts = message.content\n .filter(\n (part): part is { type: \"text\"; text: string } =>\n part.type === \"text\",\n )\n .map((part) => part.text);\n\n if (textParts.length > 0) {\n messages.push({\n role: \"assistant\",\n content: textParts.join(\"\\n\"),\n });\n }\n break;\n }\n\n case \"tool\": {\n break;\n }\n }\n }\n\n return messages;\n }\n\n private mapFinishReason(\n reason: string | undefined,\n ): LanguageModelV3FinishReason {\n switch (reason) {\n case \"stop\":\n return { unified: \"stop\", raw: reason };\n case \"length\":\n return { unified: \"length\", raw: reason };\n case \"tool_calls\":\n case \"tool-calls\":\n return { unified: \"tool-calls\", raw: reason };\n case \"content_filter\":\n case \"content-filter\":\n return { unified: \"content-filter\", raw: reason };\n case \"error\":\n return { unified: \"error\", raw: reason };\n default:\n return { unified: \"other\", raw: reason ?? \"unknown\" };\n }\n }\n}\n","import type { BunnyAgentProviderSettings, Logger } from \"./types\";\n\n/** Shared logger factory for provider and language model. */\nexport function getProviderLogger(\n settings: Partial<BunnyAgentProviderSettings>,\n): Logger {\n if (settings.logger === false) {\n return {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n };\n }\n\n if (settings.logger) {\n return settings.logger;\n }\n\n const isVerbose = settings.verbose ?? false;\n return {\n debug: (msg) => isVerbose && console.debug(msg),\n info: (msg) => isVerbose && console.info(msg),\n warn: (msg) => console.warn(msg),\n error: (msg) => console.error(msg),\n };\n}\n","import type {\n JSONObject,\n LanguageModelV3FunctionTool,\n LanguageModelV3ProviderTool,\n SharedV3ProviderOptions,\n} from \"@ai-sdk/provider\";\nimport type { ToolRef } from \"@bunny-agent/manager\";\nimport type { Tool } from \"ai\";\n\nconst BUNNY_PROVIDER_OPTIONS_KEY = \"bunny-agent\";\n\ntype BunnyProviderOptions = {\n runtime?: JSONObject;\n};\n\ntype BunnyToolRuntime = Extract<\n ToolRef[\"runtime\"],\n { type: \"http\" | \"module\" }\n>;\n\ntype BunnyDynamicTool<INPUT> = Tool<INPUT, unknown> & { type: \"dynamic\" };\n\n/**\n * AI SDK helper for tools that the sandbox runner should call by HTTP.\n *\n * This is still used with the standard AI SDK `streamText`:\n * `import { streamText } from \"ai\"`.\n */\nexport function bunnyHttpTool<INPUT, OUTPUT>(\n input: Omit<Tool<INPUT, OUTPUT>, \"execute\" | \"outputSchema\"> & {\n endpoint: {\n url: string;\n headers?: Record<string, string>;\n };\n },\n): BunnyDynamicTool<INPUT> {\n return {\n type: \"dynamic\" as const,\n description: input.description,\n title: input.title,\n providerOptions: withBunnyProviderOptions(input.providerOptions, {\n runtime: {\n type: \"http\",\n url: input.endpoint.url,\n ...(input.endpoint.headers ? { headers: input.endpoint.headers } : {}),\n },\n }),\n inputSchema: input.inputSchema,\n inputExamples: input.inputExamples,\n needsApproval: input.needsApproval,\n strict: input.strict,\n onInputStart: input.onInputStart,\n onInputDelta: input.onInputDelta,\n onInputAvailable: input.onInputAvailable,\n async execute() {\n throw new Error(\n \"bunnyHttpTool is provider-executed by the sandbox runner.\",\n );\n },\n } satisfies BunnyDynamicTool<INPUT>;\n}\n\n/**\n * AI SDK helper for tools implemented by a module already present in the\n * sandbox filesystem.\n */\nexport function bunnySandboxTool<INPUT, OUTPUT>(\n input: Omit<Tool<INPUT, OUTPUT>, \"execute\" | \"outputSchema\"> & {\n module: string;\n exportName?: string;\n },\n): BunnyDynamicTool<INPUT> {\n return {\n type: \"dynamic\" as const,\n description: input.description,\n title: input.title,\n providerOptions: withBunnyProviderOptions(input.providerOptions, {\n runtime: {\n type: \"module\",\n module: input.module,\n ...(input.exportName ? { exportName: input.exportName } : {}),\n },\n }),\n inputSchema: input.inputSchema,\n inputExamples: input.inputExamples,\n needsApproval: input.needsApproval,\n strict: input.strict,\n onInputStart: input.onInputStart,\n onInputDelta: input.onInputDelta,\n onInputAvailable: input.onInputAvailable,\n async execute() {\n throw new Error(\n \"bunnySandboxTool is provider-executed by the sandbox runner.\",\n );\n },\n } satisfies BunnyDynamicTool<INPUT>;\n}\n\nexport function compileToolRefsFromLanguageModelTools(\n tools:\n | Array<LanguageModelV3FunctionTool | LanguageModelV3ProviderTool>\n | undefined,\n): ToolRef[] | undefined {\n if (!tools || tools.length === 0) return undefined;\n\n const toolRefs: ToolRef[] = [];\n\n for (const tool of tools) {\n if (tool.type !== \"function\") {\n continue;\n }\n\n const runtime = getBunnyRuntime(tool);\n if (!runtime) {\n throw new Error(\n `[bunny-agent] Tool \"${tool.name}\" was passed through AI SDK streamText, ` +\n \"but Bunny cannot access host-side tool({ execute }) callbacks at the provider boundary. \" +\n \"Use bunnyHttpTool(...) for an endpoint tool or bunnySandboxTool(...) for a sandbox-local module.\",\n );\n }\n\n toolRefs.push({\n name: tool.name,\n description: tool.description ?? \"\",\n inputSchema: tool.inputSchema as Record<string, unknown>,\n runtime,\n });\n }\n\n return toolRefs.length > 0 ? toolRefs : undefined;\n}\n\nfunction getBunnyRuntime(\n tool: LanguageModelV3FunctionTool,\n): BunnyToolRuntime | undefined {\n const options = tool.providerOptions?.[BUNNY_PROVIDER_OPTIONS_KEY] as\n | BunnyProviderOptions\n | undefined;\n const runtime = options?.runtime;\n if (!isRecord(runtime) || typeof runtime.type !== \"string\") {\n return undefined;\n }\n if (runtime.type === \"http\" && typeof runtime.url === \"string\") {\n return {\n type: \"http\",\n url: runtime.url,\n ...(isStringRecord(runtime.headers) ? { headers: runtime.headers } : {}),\n };\n }\n if (runtime.type === \"module\" && typeof runtime.module === \"string\") {\n return {\n type: \"module\",\n module: runtime.module,\n ...(typeof runtime.exportName === \"string\"\n ? { exportName: runtime.exportName }\n : {}),\n };\n }\n return undefined;\n}\n\nfunction withBunnyProviderOptions(\n providerOptions: SharedV3ProviderOptions | undefined,\n bunnyOptions: BunnyProviderOptions,\n): SharedV3ProviderOptions {\n return {\n ...(providerOptions ?? {}),\n [BUNNY_PROVIDER_OPTIONS_KEY]: {\n ...((providerOptions?.[BUNNY_PROVIDER_OPTIONS_KEY] as\n | object\n | undefined) ?? {}),\n ...bunnyOptions,\n },\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction isStringRecord(value: unknown): value is Record<string, string> {\n if (!isRecord(value)) return false;\n return Object.values(value).every((entry) => typeof entry === \"string\");\n}\n","import type { JSONValue, LanguageModelV3Usage } from \"@ai-sdk/provider\";\n\ntype JsonRecord = Record<string, JSONValue | undefined>;\n\nfunction asRecord(value: unknown): JsonRecord | undefined {\n if (value == null || typeof value !== \"object\" || Array.isArray(value)) {\n return undefined;\n }\n return value as JsonRecord;\n}\n\n/**\n * Extract `providerMetadata[\"bunny-agent\"]` from an AI SDK providerMetadata object.\n */\nexport function getBunnyAgentMetadata(\n providerMetadata: unknown,\n): JsonRecord | undefined {\n const providerMeta = asRecord(providerMetadata);\n if (providerMeta == null) return undefined;\n return asRecord(providerMeta[\"bunny-agent\"]);\n}\n\n/**\n * Extract Bunny Agent usage payload from an AI SDK providerMetadata object.\n *\n * This returns the raw usage object emitted by Bunny Agent stream metadata,\n * e.g. `{ input_tokens, output_tokens, cache_read_input_tokens, ... }`.\n */\nexport function getBunnyAgentUsage(\n providerMetadata: unknown,\n): LanguageModelV3Usage | undefined {\n const bunnyMeta = getBunnyAgentMetadata(providerMetadata);\n if (bunnyMeta == null) return undefined;\n return normalizeBunnyAgentUsage(bunnyMeta);\n}\n\n/**\n * Convert Bunny Agent usage metadata to AI SDK standard usage shape.\n *\n * Accepts either:\n * - a metadata object that contains `usage` plus extra fields (model/cost/image/search)\n * - or a direct usage payload in snake_case token fields.\n *\n * `raw` preserves usage fields and includes extra metadata fields when available.\n */\nexport function normalizeBunnyAgentUsage(\n data: unknown,\n): LanguageModelV3Usage | undefined {\n const dataRecord = asRecord(data);\n if (dataRecord == null) return undefined;\n\n const usageSource = asRecord(dataRecord.usage ?? dataRecord);\n if (usageSource == null) return undefined;\n const hasTokenFields =\n \"input_tokens\" in usageSource ||\n \"output_tokens\" in usageSource ||\n \"cache_read_input_tokens\" in usageSource ||\n \"cache_creation_input_tokens\" in usageSource;\n if (!hasTokenFields) return undefined;\n\n const inputTokens =\n typeof usageSource.input_tokens === \"number\" ? usageSource.input_tokens : 0;\n const outputTokens =\n typeof usageSource.output_tokens === \"number\"\n ? usageSource.output_tokens\n : 0;\n const cacheRead =\n typeof usageSource.cache_read_input_tokens === \"number\"\n ? usageSource.cache_read_input_tokens\n : 0;\n const cacheWrite =\n typeof usageSource.cache_creation_input_tokens === \"number\"\n ? usageSource.cache_creation_input_tokens\n : 0;\n const textTokens =\n typeof usageSource.text_tokens === \"number\"\n ? usageSource.text_tokens\n : undefined;\n const reasoningTokens =\n typeof usageSource.reasoning_tokens === \"number\"\n ? usageSource.reasoning_tokens\n : undefined;\n const extraMetadata = Object.fromEntries(\n Object.entries(dataRecord).filter(([key]) => key !== \"usage\"),\n ) as JsonRecord;\n const raw =\n Object.keys(extraMetadata).length > 0\n ? { ...usageSource, ...extraMetadata }\n : usageSource;\n\n return {\n inputTokens: {\n total: inputTokens + cacheRead + cacheWrite,\n noCache: inputTokens,\n cacheRead,\n cacheWrite,\n },\n outputTokens: {\n total: outputTokens,\n text: textTokens,\n reasoning: reasoningTokens,\n },\n raw,\n };\n}\n","import type {\n EmbeddingModelV3,\n ImageModelV3,\n LanguageModelV3,\n ProviderV3,\n} from \"@ai-sdk/provider\";\nimport { NoSuchModelError } from \"@ai-sdk/provider\";\nimport type { RunnerSpec } from \"@bunny-agent/manager\";\nimport { BunnyAgentLanguageModel } from \"./bunny-agent-language-model\";\nimport { getProviderLogger } from \"./logging\";\nimport type { BunnyAgentModelId, BunnyAgentProviderSettings } from \"./types\";\n\nexport type { BunnyAgentProviderSettings } from \"./types\";\n\n/**\n * BunnyAgent provider interface that extends the AI SDK's ProviderV3.\n */\nexport interface BunnyAgentProvider extends ProviderV3 {\n (\n modelId: BunnyAgentModelId,\n options?: Partial<BunnyAgentProviderSettings>,\n ): LanguageModelV3;\n\n languageModel(\n modelId: BunnyAgentModelId,\n options?: Partial<BunnyAgentProviderSettings>,\n ): LanguageModelV3;\n\n chat(\n modelId: BunnyAgentModelId,\n options?: Partial<BunnyAgentProviderSettings>,\n ): LanguageModelV3;\n\n embeddingModel(modelId: string): EmbeddingModelV3;\n textEmbeddingModel(modelId: string): EmbeddingModelV3;\n imageModel(modelId: string): ImageModelV3;\n}\n\n/**\n * Creates a BunnyAgent provider instance with the specified configuration.\n *\n * @example\n * ```typescript\n * import { createBunnyAgent } from '@bunny-agent/sdk';\n * import { E2BSandbox } from '@bunny-agent/sandbox-e2b';\n * import { generateText } from 'ai';\n *\n * const bunnyAgent = createBunnyAgent({\n * sandbox: new E2BSandbox({ apiKey: process.env.E2B_API_KEY! }),\n * env: {\n * ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY!,\n * },\n * });\n *\n * const { text } = await generateText({\n * model: bunnyAgent('sonnet'),\n * prompt: 'Create a hello world program',\n * });\n * ```\n */\nexport function createBunnyAgent(\n defaultOptions: BunnyAgentProviderSettings,\n): BunnyAgentProvider {\n const logger = getProviderLogger(defaultOptions);\n\n if (!defaultOptions.sandbox) {\n throw new Error(\n \"Provide a `sandbox` adapter (e.g. E2BSandbox, LocalSandbox). \" +\n \"Optional `daemonUrl` uses in-sandbox HTTP to bunny-agent-daemon (no automatic `/healthz` probe). Use `isBunnyAgentDaemonHealthy` from `@bunny-agent/sdk` if you want to probe and omit `daemonUrl` for CLI fallback. Omit `daemonUrl` to always use CLI.\",\n );\n }\n\n const createModel = (\n modelId: BunnyAgentModelId,\n options: Partial<BunnyAgentProviderSettings> = {},\n ): LanguageModelV3 => {\n const mergedSkillPaths =\n options.skillPaths !== undefined\n ? options.skillPaths\n : defaultOptions.skillPaths;\n\n const mergedAllowedTools =\n options.allowedTools !== undefined\n ? options.allowedTools\n : defaultOptions.allowedTools;\n\n const runner: RunnerSpec = {\n model: modelId,\n runnerType: options.runnerType ?? defaultOptions.runnerType,\n outputFormat: \"stream\",\n maxTurns: options.maxTurns ?? defaultOptions.maxTurns,\n ...((options.systemPrompt ?? defaultOptions.systemPrompt)\n ? { systemPrompt: options.systemPrompt ?? defaultOptions.systemPrompt }\n : {}),\n ...(mergedSkillPaths && mergedSkillPaths.length > 0\n ? { skillPaths: mergedSkillPaths }\n : {}),\n ...(mergedAllowedTools !== undefined\n ? { allowedTools: mergedAllowedTools }\n : {}),\n ...((options.effort ?? defaultOptions.effort)\n ? {\n effort: options.effort ?? defaultOptions.effort,\n }\n : {}),\n };\n\n const mergedOptions = {\n ...defaultOptions,\n ...options,\n runner,\n env: {\n ...defaultOptions.env,\n ...options.env,\n },\n systemEnv:\n defaultOptions.systemEnv || options.systemEnv\n ? {\n ...(defaultOptions.systemEnv ?? {}),\n ...(options.systemEnv ?? {}),\n }\n : undefined,\n artifactProcessors: [\n ...(defaultOptions.artifactProcessors ?? []),\n ...(options.artifactProcessors ?? []),\n ],\n toolRefs:\n options.toolRefs !== undefined\n ? options.toolRefs\n : defaultOptions.toolRefs,\n } as BunnyAgentProviderSettings & { runner: RunnerSpec };\n\n logger.debug(\n `[bunny-agent] Creating model: ${modelId}${runner.runnerType ? ` (runnerType: ${runner.runnerType})` : \"\"}${runner.skillPaths?.length ? ` skillPaths=${runner.skillPaths.length}` : \"\"}`,\n );\n\n return new BunnyAgentLanguageModel({\n id: modelId,\n options: mergedOptions,\n });\n };\n\n const provider = function (\n modelId: BunnyAgentModelId,\n options?: Partial<BunnyAgentProviderSettings>,\n ) {\n if (new.target) {\n throw new Error(\n \"The BunnyAgent model function cannot be called with the new keyword.\",\n );\n }\n\n return createModel(modelId, options);\n };\n\n provider.languageModel = createModel;\n provider.chat = createModel;\n provider.specificationVersion = \"v3\" as const;\n\n provider.embeddingModel = (modelId: string): EmbeddingModelV3 => {\n throw new NoSuchModelError({\n modelId,\n modelType: \"embeddingModel\",\n });\n };\n\n provider.textEmbeddingModel = (modelId: string): EmbeddingModelV3 => {\n throw new NoSuchModelError({\n modelId,\n modelType: \"embeddingModel\",\n });\n };\n\n provider.imageModel = (modelId: string): ImageModelV3 => {\n throw new NoSuchModelError({\n modelId,\n modelType: \"imageModel\",\n });\n };\n\n return provider as BunnyAgentProvider;\n}\n","import type { SandboxAdapter } from \"@bunny-agent/manager\";\nimport type { SubmitAnswerParams } from \"./types\";\n\n/**\n * Options for submitAnswer\n */\nexport interface SubmitAnswerOptions {\n /**\n * Optional base path prefix for approval files\n * @default \".bunny-agent/approvals\"\n */\n basePath?: string;\n}\n\n/**\n * Submit user's answer for an AskUserQuestion tool call.\n * Writes the answer file to `.bunny-agent/approvals/{toolCallId}.json` in the sandbox workdir.\n *\n * @example\n * ```typescript\n * import { submitAnswer } from \"@bunny-agent/sdk\";\n *\n * await submitAnswer(sandbox, {\n * toolCallId: \"tool-456\",\n * questions: [...],\n * answers: { \"Question 1\": \"Answer 1\" },\n * });\n * ```\n */\nexport async function submitAnswer(\n sandbox: SandboxAdapter,\n params: SubmitAnswerParams,\n options?: SubmitAnswerOptions,\n): Promise<void> {\n const { toolCallId, questions, answers } = params;\n const basePath = options?.basePath ?? \".bunny-agent/approvals\";\n\n const allAnswered = questions.every(\n (q) => answers[q.question] !== undefined && answers[q.question] !== \"\",\n );\n\n const answerData = {\n questions,\n answers,\n status: allAnswered ? \"completed\" : \"pending\",\n timestamp: new Date().toISOString(),\n };\n\n const filename = `${toolCallId}.json`;\n const handle = sandbox.getHandle() ?? (await sandbox.attach());\n // Absolute path so remote sandboxes (Sandock) write to the same path the runner reads (/workspace/.bunny-agent/approvals).\n const workdir = handle.getWorkdir();\n const targetDir = workdir\n ? `${workdir.replace(/\\/$/, \"\")}/${basePath}`\n : basePath;\n\n await handle.upload(\n [{ path: filename, content: JSON.stringify(answerData, null, 2) }],\n targetDir,\n );\n\n console.log(\n `[submitAnswer] Answer submitted: ${targetDir}/${filename} (status: ${answerData.status}, workdir: ${workdir ?? \"(none)\"})`,\n );\n}\n"],"mappings":"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","names":["sandboxEnv"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/provider/bunny-agent-language-model.ts","../src/provider/logging.ts","../src/provider/tool-refs.ts","../src/provider/usage.ts","../src/provider/bunny-agent-provider.ts","../src/provider/question-processor.ts"],"sourcesContent":["/**\n * @bunny-agent/sdk\n *\n * BunnyAgent SDK - AI Provider and React hooks for building AI chat interfaces.\n *\n * Main entry point exports the AI provider (backend).\n * React hooks are available via \"@bunny-agent/sdk/react\".\n *\n * @example\n * ```typescript\n * // Backend - Provider\n * import { createBunnyAgent } from \"@bunny-agent/sdk\";\n * const bunnyAgent = createBunnyAgent({ sandbox, env });\n * const model = bunnyAgent(\"sonnet\");\n *\n * // Frontend - React hooks\n * import { useBunnyAgentChat } from \"@bunny-agent/sdk/react\";\n * const { messages, sendMessage } = useBunnyAgentChat({ apiEndpoint: \"/api/ai\" });\n * ```\n */\n\nexport type {\n IsBunnyAgentDaemonHealthyOptions,\n RunnerEnvParams,\n RunnerType,\n} from \"@bunny-agent/manager\";\n// Re-export env helpers\nexport {\n buildRunnerEnv,\n DEFAULT_BUNNY_AGENT_DAEMON_URL,\n isBunnyAgentDaemonHealthy,\n} from \"@bunny-agent/manager\";\nexport type {\n LocalMachineOptions,\n LocalSandboxOptions,\n} from \"@bunny-agent/sandbox-local\";\n// Re-export the local adapters for convenience (LocalSandbox is the\n// deprecated pre-rename alias of LocalMachine)\nexport { LocalMachine, LocalSandbox } from \"@bunny-agent/sandbox-local\";\nexport type {\n SrtIsolationOptions,\n SrtSandboxOptions,\n} from \"@bunny-agent/sandbox-srt\";\nexport { SrtSandbox } from \"@bunny-agent/sandbox-srt\";\nexport type {\n ArtifactProcessor,\n ArtifactResult,\n BunnyAgentLanguageModelOptions,\n BunnyAgentModelId,\n BunnyAgentProvider,\n BunnyAgentProviderSettings,\n // Re-exports from @ai-sdk/provider\n LanguageModelV3StreamPart,\n Logger,\n Message,\n Question,\n // Re-exports from @bunny-agent/manager\n SandboxAdapter,\n SandboxHandle,\n StreamWriter,\n SubmitAnswerOptions,\n SubmitAnswerParams,\n ToolRuntime,\n TranscriptEntry,\n} from \"./provider\";\n// Provider exports\nexport {\n BunnyAgentLanguageModel,\n bunnyHttpTool,\n bunnySandboxTool,\n createBunnyAgent,\n getBunnyAgentMetadata,\n getBunnyAgentUsage,\n submitAnswer,\n} from \"./provider\";\n\nexport const VERSION = \"0.1.0\";\n","import type {\n JSONValue,\n LanguageModelV3,\n LanguageModelV3CallOptions,\n LanguageModelV3Content,\n LanguageModelV3FinishReason,\n LanguageModelV3GenerateResult,\n LanguageModelV3Prompt,\n LanguageModelV3StreamPart,\n LanguageModelV3StreamResult,\n LanguageModelV3Usage,\n SharedV3ProviderMetadata,\n SharedV3Warning,\n} from \"@ai-sdk/provider\";\nimport {\n BunnyAgent,\n type BunnyAgentCodingRunBody,\n type Message,\n type RunnerSpec,\n streamCodingRunFromSandbox,\n type ToolRef,\n} from \"@bunny-agent/manager\";\nimport { getProviderLogger } from \"./logging\";\nimport { compileToolRefsFromLanguageModelTools } from \"./tool-refs\";\nimport type {\n BunnyAgentModelId,\n BunnyAgentProviderSettings,\n Logger,\n} from \"./types\";\nimport { normalizeBunnyAgentUsage } from \"./usage\";\n\n/**\n * Options for creating a BunnyAgent language model instance.\n */\nexport interface BunnyAgentLanguageModelOptions {\n id: BunnyAgentModelId;\n options: BunnyAgentProviderSettings & { runner: RunnerSpec };\n}\n\n/** Format error so message and cause chain are visible (e.g. includes \"Fatal error: ...\" from runner). */\nfunction formatErrorForLog(error: unknown): string {\n if (error instanceof Error) {\n const parts = [error.message];\n let cause: unknown = error.cause;\n while (cause instanceof Error) {\n parts.push(cause.message);\n cause = cause.cause;\n }\n return parts.join(\" | cause: \");\n }\n return String(error);\n}\n\n/** Bridge async iterable (sandbox exec / curl) to Web ReadableStream for SSE parsing. */\nfunction asyncIterableToReadableStream(\n iterable: AsyncIterable<Uint8Array>,\n): ReadableStream<Uint8Array> {\n const iterator = iterable[Symbol.asyncIterator]();\n return new ReadableStream<Uint8Array>({\n async pull(controller) {\n try {\n while (true) {\n const { done, value } = await iterator.next();\n if (done) {\n controller.close();\n return;\n }\n if (value.byteLength > 0) {\n controller.enqueue(value);\n return;\n }\n }\n } catch (error) {\n const isAbort =\n (error instanceof Error && error.name === \"AbortError\") ||\n (typeof DOMException !== \"undefined\" &&\n error instanceof DOMException &&\n error.name === \"AbortError\") ||\n (error instanceof Error && /abort/i.test(error.message));\n if (isAbort) {\n controller.close();\n } else {\n controller.error(error);\n }\n }\n },\n async cancel(reason) {\n await iterator.return?.(reason);\n },\n });\n}\n\nfunction mergeToolRefs(\n staticToolRefs: ToolRef[] | undefined,\n callToolRefs: ToolRef[] | undefined,\n): ToolRef[] | undefined {\n const merged = [...(staticToolRefs ?? []), ...(callToolRefs ?? [])];\n return merged.length > 0 ? merged : undefined;\n}\n\nfunction extractTextContent(content: Message[\"content\"]): string {\n if (typeof content === \"string\") return content;\n return content\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text)\n .join(\"\\n\");\n}\n\nfunction getLastUserTextFromMessages(messages: Message[]): string {\n // Collect all trailing user messages (handles batched/queued messages)\n const trailingUserMessages: Message[] = [];\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === \"user\") {\n trailingUserMessages.unshift(messages[i]);\n } else {\n break;\n }\n }\n if (trailingUserMessages.length === 0) return \"\";\n return trailingUserMessages\n .map((msg) => extractTextContent(msg.content))\n .join(\"\\n\\n\");\n}\n\n/**\n * Serialize the full transcript into a single userInput string.\n *\n * Used when the runtime has no session context to hydrate from — i.e. neither\n * `resume` (existing runner session id) nor `forkFrom` (parent session to\n * snapshot-clone) is set. In that case the runner starts a brand-new session\n * whose only visible input is the `userInput` payload; if we passed only the\n * last user turn the runner would lose all prior conversation, which is what\n * happened when share-continued fallback sessions arrived at pi with just\n * the current question instead of the copied `agent_messages` history.\n *\n * Format: prior turns labeled by role, then the current user message under\n * a \"Current message\" header so the runner treats it as the actual prompt.\n */\nfunction serializeMessagesToUserInput(messages: Message[]): string {\n // Split trailing consecutive user messages (the \"current\" turn) from history.\n let currentStart = messages.length;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === \"user\") {\n currentStart = i;\n } else {\n break;\n }\n }\n\n const history = messages.slice(0, currentStart);\n const current = messages.slice(currentStart);\n\n const currentText = current\n .map((msg) => extractTextContent(msg.content))\n .filter((t) => t.length > 0)\n .join(\"\\n\\n\");\n\n if (history.length === 0) return currentText;\n\n const historyLines: string[] = [];\n for (const msg of history) {\n const text = extractTextContent(msg.content);\n if (text.length === 0) continue;\n const label =\n msg.role === \"user\"\n ? \"User\"\n : msg.role === \"assistant\"\n ? \"Assistant\"\n : \"System\";\n historyLines.push(`${label}: ${text}`);\n }\n\n if (historyLines.length === 0) return currentText;\n\n const historyBlock = `Previous conversation:\\n\\n${historyLines.join(\"\\n\\n\")}`;\n if (currentText.length === 0) return historyBlock;\n return `${historyBlock}\\n\\nCurrent message:\\n\\n${currentText}`;\n}\n\nfunction createEmptyUsage(): LanguageModelV3Usage {\n return {\n inputTokens: {\n total: 0,\n noCache: 0,\n cacheRead: 0,\n cacheWrite: 0,\n },\n outputTokens: {\n total: 0,\n text: undefined,\n reasoning: undefined,\n },\n raw: undefined,\n };\n}\n\nfunction readToolDynamicFlag(parsed: Record<string, unknown>): boolean {\n if (typeof parsed.dynamic === \"boolean\") {\n return parsed.dynamic;\n }\n return parsed.providerExecuted === true;\n}\n\n/**\n * BunnyAgent Language Model implementation for AI SDK.\n */\nexport class BunnyAgentLanguageModel implements LanguageModelV3 {\n readonly specificationVersion = \"v3\" as const;\n readonly provider: string;\n readonly modelId: string;\n readonly supportedUrls: Record<string, RegExp[]> = {\n \"image/*\": [/.*/],\n };\n\n readonly settings: BunnyAgentProviderSettings & { runner: RunnerSpec };\n private readonly options: BunnyAgentProviderSettings & { runner: RunnerSpec };\n private readonly logger: Logger;\n private sessionId: string | undefined;\n private toolNameMap: Map<string, string> = new Map();\n private legacyTextPartCounter = 0;\n private receivedFinish = false;\n private activeReasoningPartId: string | undefined;\n\n private logUnparsedStreamLine(candidate: string, error: unknown): void {\n const trimmed = candidate.trim();\n if (!trimmed) return;\n const looksLikeError = /\\b(error|failed|exception|traceback|fatal)\\b/i.test(\n trimmed,\n );\n const snippet = trimmed.slice(0, 500);\n const msg = error instanceof Error ? error.message : String(error);\n if (looksLikeError) {\n this.logger.error(\n `[bunny-agent] Unparsed stream line (likely runner error): ${snippet} | parser: ${msg}`,\n );\n } else {\n // Not obviously an error, but still worth surfacing — a silently\n // dropped line here is exactly how a stream can stall with no\n // \"finish\"/\"error\" part and no visible feedback to the user.\n this.logger.debug(\n `[bunny-agent] Unparsed stream line: ${snippet} | parser: ${msg}`,\n );\n }\n }\n\n constructor(modelOptions: BunnyAgentLanguageModelOptions) {\n this.modelId = modelOptions.id;\n this.settings = modelOptions.options;\n this.options = modelOptions.options;\n this.logger = getProviderLogger(modelOptions.options);\n this.provider = \"bunny-agent\";\n }\n\n async doGenerate(\n options: LanguageModelV3CallOptions,\n ): Promise<LanguageModelV3GenerateResult> {\n const { stream, request } = await this.doStream(options);\n const reader = stream.getReader();\n\n const content: LanguageModelV3Content[] = [];\n const warnings: SharedV3Warning[] = [];\n let finishReason: LanguageModelV3FinishReason = {\n unified: \"other\",\n raw: undefined,\n };\n let usage: LanguageModelV3Usage = createEmptyUsage();\n let providerMetadata: SharedV3ProviderMetadata | undefined;\n\n const textParts: Map<string, { text: string }> = new Map();\n const reasoningParts: Map<string, { text: string }> = new Map();\n const toolInputs: Map<string, { toolName: string; input: string }> =\n new Map();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n switch (value.type) {\n case \"text-start\": {\n textParts.set(value.id, { text: \"\" });\n break;\n }\n case \"text-delta\": {\n const part = textParts.get(value.id);\n if (part) {\n part.text += value.delta;\n }\n break;\n }\n case \"text-end\": {\n const part = textParts.get(value.id);\n if (part) {\n content.push({\n type: \"text\",\n text: part.text,\n });\n }\n break;\n }\n case \"reasoning-start\": {\n reasoningParts.set(value.id, { text: \"\" });\n break;\n }\n case \"reasoning-delta\": {\n const part = reasoningParts.get(value.id);\n if (part) {\n part.text += value.delta;\n }\n break;\n }\n case \"reasoning-end\": {\n const part = reasoningParts.get(value.id);\n if (part && part.text.length > 0) {\n content.push({\n type: \"reasoning\",\n text: part.text,\n });\n }\n break;\n }\n case \"tool-input-start\": {\n toolInputs.set(value.id, { toolName: value.toolName, input: \"\" });\n break;\n }\n case \"tool-input-delta\": {\n const tool = toolInputs.get(value.id);\n if (tool) {\n tool.input += value.delta;\n }\n break;\n }\n case \"tool-input-end\": {\n break;\n }\n case \"tool-call\": {\n content.push({\n type: \"tool-call\",\n toolCallId: value.toolCallId,\n toolName: value.toolName,\n input: value.input,\n providerExecuted: value.providerExecuted,\n });\n break;\n }\n case \"stream-start\": {\n warnings.push(...value.warnings);\n break;\n }\n case \"error\": {\n // `value.error` type comes from AI SDK and can be `{}`-shaped.\n // Convert it to a readable string safely.\n const message =\n value.error instanceof Error\n ? value.error.message\n : typeof value.error === \"string\"\n ? value.error\n : value.error\n ? String(value.error)\n : \"Unknown error\";\n\n // Surface errors as assistant text + mark finishReason=error.\n content.push({ type: \"text\", text: message });\n finishReason = { unified: \"error\", raw: \"error\" };\n break;\n }\n case \"finish\": {\n finishReason = value.finishReason;\n usage = value.usage;\n providerMetadata = value.providerMetadata;\n break;\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n return {\n content,\n finishReason,\n usage,\n providerMetadata,\n request,\n warnings,\n };\n }\n\n async doStream(\n options: LanguageModelV3CallOptions,\n ): Promise<LanguageModelV3StreamResult> {\n const { prompt, abortSignal } = options;\n const messages = this.convertPromptToMessages(prompt);\n\n this.resetStreamState();\n\n this.logger.debug(\n `[bunny-agent] Starting stream with ${messages.length} messages`,\n );\n\n const sandbox = this.options.sandbox;\n if (!sandbox) {\n throw new Error(\n \"BunnyAgent language model requires a sandbox adapter (set `sandbox` on the provider).\",\n );\n }\n\n const callToolRefs = compileToolRefsFromLanguageModelTools(options.tools);\n const toolRefs = mergeToolRefs(this.options.toolRefs, callToolRefs);\n\n const daemonUrl = this.options.daemonUrl;\n\n if (daemonUrl) {\n const handle = await sandbox.attach();\n const sandboxEnv = sandbox.getEnv?.() ?? {};\n const runnerEnv = { ...sandboxEnv, ...this.options.env };\n const body: BunnyAgentCodingRunBody = {\n ...this.buildCodingRunBody(messages, handle.getWorkdir(), toolRefs),\n ...(Object.keys(runnerEnv).length > 0 ? { env: runnerEnv } : {}),\n ...(this.options.systemEnv &&\n Object.keys(this.options.systemEnv).length > 0\n ? { systemEnv: this.options.systemEnv }\n : {}),\n };\n const execOpts = {\n cwd: this.options.cwd ?? handle.getWorkdir(),\n signal: abortSignal,\n };\n const iterable = streamCodingRunFromSandbox(\n handle,\n daemonUrl,\n body,\n execOpts,\n );\n const bytesStream = asyncIterableToReadableStream(iterable);\n return this.buildStreamResult(bytesStream, messages);\n }\n\n const sandboxEnv = sandbox.getEnv?.() ?? {};\n const sandboxWorkdir =\n this.options.cwd ?? sandbox.getWorkdir?.() ?? \"/workspace\";\n\n // CLI fallback path: each `bunny-agent run` invocation is single-request /\n // single-tenant, so the runner's `process.env` IS the expected bash\n // environment. We therefore merge env + systemEnv into one map and let\n // sandbox.exec inject everything. Pi's bash tool inherits this via its\n // default `ctx.env`, so no JSON-payload channel is needed.\n const agent = new BunnyAgent({\n sandbox,\n runner: this.options.runner,\n env: {\n ...sandboxEnv,\n ...this.options.env,\n ...(this.options.systemEnv ?? {}),\n },\n });\n\n try {\n const bytesStream = await agent.stream({\n messages,\n workspace: {\n path: sandboxWorkdir,\n },\n resume: this.options.resume,\n forkFrom: this.options.forkFrom,\n signal: abortSignal,\n ...(toolRefs && toolRefs.length > 0 ? { toolRefs } : {}),\n });\n return this.buildStreamResult(bytesStream, messages);\n } catch (error) {\n await agent.destroy().catch(() => {});\n throw error;\n }\n }\n\n private resetStreamState(): void {\n this.sessionId = undefined;\n this.toolNameMap = new Map();\n this.legacyTextPartCounter = 0;\n this.receivedFinish = false;\n this.activeReasoningPartId = undefined;\n }\n\n /** Close the open reasoning part, if any (returns the end part to emit). */\n private closeReasoningPart(): LanguageModelV3StreamPart[] {\n if (this.activeReasoningPartId == null) return [];\n const id = this.activeReasoningPartId;\n this.activeReasoningPartId = undefined;\n return [{ type: \"reasoning-end\", id }];\n }\n\n /** Synthesize a terminal error+finish pair for streams that end (EOF or `[DONE]`) without ever emitting a \"finish\" part, so the UI shows an error instead of silently stalling. */\n private buildUnexpectedEndParts(): LanguageModelV3StreamPart[] {\n return [\n {\n type: \"error\",\n error: new Error(\n \"The agent stream ended unexpectedly before completing.\",\n ),\n },\n {\n type: \"finish\",\n finishReason: { unified: \"error\", raw: \"unexpected-stream-end\" },\n usage: createEmptyUsage(),\n providerMetadata: {\n \"bunny-agent\": {\n sessionId: this.sessionId,\n } as unknown as SharedV3ProviderMetadata,\n },\n },\n ];\n }\n\n private buildCodingRunBody(\n messages: Message[],\n cwdFallback: string,\n toolRefs: ToolRef[] | undefined,\n ): BunnyAgentCodingRunBody {\n const runner = this.options.runner;\n const cwd = this.options.cwd ?? cwdFallback;\n\n // When the runner has session context to hydrate from (resume points at\n // an existing runner session, or forkFrom snapshot-clones a parent), send\n // only the last user turn — history lives in the runner's session file.\n // Otherwise it's a fresh session with no server-side history, so serialize\n // the full transcript into userInput so the runner sees prior turns.\n const hasRuntimeHistory = Boolean(\n this.options.resume ?? this.options.forkFrom,\n );\n const userInput = hasRuntimeHistory\n ? getLastUserTextFromMessages(messages)\n : serializeMessagesToUserInput(messages);\n\n return {\n runner: runner.runnerType ?? \"claude\",\n model: this.modelId,\n userInput,\n cwd,\n resume: this.options.resume,\n forkFrom: this.options.forkFrom,\n systemPrompt: this.options.systemPrompt ?? runner.systemPrompt,\n maxTurns: this.options.maxTurns ?? runner.maxTurns,\n allowedTools: runner.allowedTools ?? this.options.allowedTools,\n skillPaths: runner.skillPaths ?? this.options.skillPaths,\n yolo: this.options.yolo,\n ...(toolRefs && toolRefs.length > 0 ? { toolRefs } : {}),\n ...(this.options.effort ? { effort: this.options.effort } : {}),\n };\n }\n\n private buildStreamResult(\n bytesStream: ReadableStream<Uint8Array>,\n messages: Message[],\n ): LanguageModelV3StreamResult {\n const reader = bytesStream.getReader();\n\n return {\n stream: this.createLanguageModelStreamFromSseReader(reader),\n request: {\n body: JSON.stringify({ messages }),\n },\n };\n }\n\n private createLanguageModelStreamFromSseReader(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n ): ReadableStream<LanguageModelV3StreamPart> {\n const self = this;\n\n return new ReadableStream<LanguageModelV3StreamPart>({\n async start(controller) {\n try {\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) {\n if (buffer.trim()) {\n const parts = self.parseSSEBuffer(buffer);\n for (const part of parts) {\n controller.enqueue(part);\n }\n }\n if (!self.receivedFinish) {\n for (const part of self.buildUnexpectedEndParts()) {\n controller.enqueue(part);\n }\n }\n controller.close();\n break;\n }\n\n const text = new TextDecoder().decode(value);\n buffer += text;\n\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n let foundDone = false;\n for (const line of lines) {\n const candidate = line.startsWith(\"data: \")\n ? line.slice(6)\n : line.trim();\n if (!candidate) continue;\n if (candidate === \"[DONE]\") {\n foundDone = true;\n continue;\n }\n\n try {\n const parts = self.parseSSEData(candidate);\n for (const part of parts) {\n controller.enqueue(part);\n\n if (self.sessionId) {\n const sessionId: string = self.sessionId;\n\n if (self.options.artifactProcessors?.length) {\n for (const processor of self.options.artifactProcessors) {\n Promise.resolve()\n .then(() => processor.onChange(part, sessionId))\n .catch((e) => {\n self.logger.error(\n `[bunny-agent] Artifact processor error: ${e}`,\n );\n });\n }\n }\n }\n }\n } catch (e) {\n // daemon /api/coding/run or CLI runner may emit plain text lines.\n self.logUnparsedStreamLine(candidate, e);\n }\n }\n\n if (foundDone) {\n if (!self.receivedFinish) {\n for (const part of self.buildUnexpectedEndParts()) {\n controller.enqueue(part);\n }\n }\n controller.close();\n return;\n }\n }\n } catch (error) {\n const isAbort =\n (error instanceof Error && error.name === \"AbortError\") ||\n (typeof DOMException !== \"undefined\" &&\n error instanceof DOMException &&\n error.name === \"AbortError\") ||\n (error instanceof Error && /abort/i.test(error.message));\n if (isAbort) {\n self.logger.info(\"[bunny-agent] Stream aborted by user\");\n controller.close();\n } else {\n self.logger.error(\n `[bunny-agent] Stream error: ${formatErrorForLog(error)}`,\n );\n controller.error(error);\n }\n }\n },\n\n cancel() {\n reader.cancel();\n },\n });\n }\n\n private parseSSEBuffer(buffer: string): LanguageModelV3StreamPart[] {\n const parts: LanguageModelV3StreamPart[] = [];\n const lines = buffer.split(\"\\n\");\n\n for (const line of lines) {\n const candidate = line.startsWith(\"data: \") ? line.slice(6) : line.trim();\n if (!candidate || candidate === \"[DONE]\") continue;\n try {\n const parsedParts = this.parseSSEData(candidate);\n parts.push(...parsedParts);\n } catch (e) {\n this.logUnparsedStreamLine(candidate, e);\n }\n }\n\n return parts;\n }\n\n private parseSSEData(data: string): LanguageModelV3StreamPart[] {\n const parts: LanguageModelV3StreamPart[] = [];\n const parsed = JSON.parse(data) as Record<string, unknown>;\n const parsedType =\n typeof parsed.type === \"string\" ? parsed.type : undefined;\n\n // daemon NDJSON errors may arrive as: {\"error\":\"...\"} (without type)\n if (!parsedType && typeof parsed.error === \"string\") {\n this.receivedFinish = true;\n return [\n {\n type: \"error\",\n error: new Error(parsed.error),\n },\n ];\n }\n\n switch (parsedType) {\n case \"start\": {\n break;\n }\n\n // Backward-compatible NDJSON chunk from daemon tests/mock runners.\n case \"text\": {\n const text = typeof parsed.text === \"string\" ? parsed.text : \"\";\n if (text.length > 0) {\n const id = `legacy-text-${++this.legacyTextPartCounter}`;\n parts.push(\n {\n type: \"text-start\",\n id,\n providerMetadata: {\n \"bunny-agent\": {\n sessionId: this.sessionId,\n } as unknown as SharedV3ProviderMetadata,\n },\n },\n { type: \"text-delta\", id, delta: text },\n { type: \"text-end\", id },\n );\n }\n break;\n }\n\n case \"message-metadata\": {\n const metadata = parsed.messageMetadata as Record<string, unknown>;\n if (metadata?.sessionId && typeof metadata.sessionId === \"string\") {\n this.sessionId = metadata.sessionId;\n this.logger.debug(\n `[bunny-agent] Session ID extracted: ${this.sessionId}`,\n );\n parts.push({\n type: \"raw\",\n rawValue: this.sessionId,\n });\n }\n break;\n }\n\n // Runners (claude/codex) emit reasoning as untagged deltas:\n // {type:\"reasoning\", text}. Wrap them in a synthesized\n // reasoning-start/delta/end part stream for the AI SDK.\n case \"reasoning\": {\n const text =\n typeof parsed.text === \"string\"\n ? parsed.text\n : typeof parsed.delta === \"string\"\n ? parsed.delta\n : \"\";\n if (text.length > 0) {\n if (this.activeReasoningPartId == null) {\n this.activeReasoningPartId = `reasoning-${++this.legacyTextPartCounter}`;\n parts.push({\n type: \"reasoning-start\",\n id: this.activeReasoningPartId,\n });\n }\n parts.push({\n type: \"reasoning-delta\",\n id: this.activeReasoningPartId,\n delta: text,\n });\n }\n break;\n }\n\n case \"text-start\": {\n parts.push(...this.closeReasoningPart());\n parts.push({\n type: \"text-start\",\n id: parsed.id as string,\n providerMetadata: {\n \"bunny-agent\": {\n sessionId: this.sessionId,\n } as unknown as SharedV3ProviderMetadata,\n },\n });\n break;\n }\n\n case \"text-delta\": {\n parts.push({\n type: \"text-delta\",\n id: parsed.id as string,\n delta: parsed.delta as string,\n });\n break;\n }\n\n case \"text-end\": {\n parts.push({\n type: \"text-end\",\n id: parsed.id as string,\n });\n break;\n }\n\n case \"tool-input-start\": {\n parts.push(...this.closeReasoningPart());\n parts.push({\n type: \"tool-input-start\",\n id: parsed.toolCallId as string,\n toolName: parsed.toolName as string,\n dynamic: readToolDynamicFlag(parsed),\n providerExecuted: parsed.providerExecuted as boolean,\n });\n break;\n }\n\n case \"tool-input-delta\": {\n parts.push({\n type: \"tool-input-delta\",\n id: parsed.toolCallId as string,\n delta: parsed.inputTextDelta as string,\n });\n break;\n }\n case \"tool-input-available\": {\n const toolCallId = parsed.toolCallId as string;\n const toolName = parsed.toolName as string;\n const input = parsed.input as Record<string, unknown>;\n this.toolNameMap.set(toolCallId, toolName);\n parts.push({\n type: \"tool-call\",\n toolCallId,\n toolName,\n input: JSON.stringify(input),\n dynamic: readToolDynamicFlag(parsed),\n providerExecuted: parsed.providerExecuted as boolean,\n });\n break;\n }\n\n case \"tool-output-available\": {\n const toolName = this.toolNameMap.get(parsed.toolCallId as string);\n parts.push({\n type: \"tool-result\",\n toolCallId: parsed.toolCallId as string,\n toolName: toolName ?? \"\",\n result: parsed.output as NonNullable<JSONValue>,\n isError: parsed.isError as boolean,\n dynamic: readToolDynamicFlag(parsed),\n });\n break;\n }\n case \"tool-output-error\": {\n const toolName = this.toolNameMap.get(parsed.toolCallId as string);\n parts.push({\n type: \"tool-result\",\n toolCallId: parsed.toolCallId as string,\n toolName: toolName ?? \"\",\n result: (parsed.errorText as string) ?? \"Tool execution failed\",\n isError: true,\n dynamic: readToolDynamicFlag(parsed),\n });\n break;\n }\n case \"error\": {\n this.receivedFinish = true;\n parts.push({\n type: \"error\",\n error: new Error(\n (parsed.errorText as string) ||\n (parsed.error as string) ||\n \"Unknown stream error\",\n ),\n });\n break;\n }\n\n case \"finish\": {\n this.receivedFinish = true;\n parts.push(...this.closeReasoningPart());\n const rawFinishReason = parsed.finishReason;\n let finishReason: LanguageModelV3FinishReason;\n\n if (\n typeof rawFinishReason === \"object\" &&\n rawFinishReason !== null &&\n \"unified\" in rawFinishReason\n ) {\n finishReason = rawFinishReason as LanguageModelV3FinishReason;\n } else {\n finishReason = this.mapFinishReason(rawFinishReason as string);\n }\n\n const usage =\n normalizeBunnyAgentUsage(\n (parsed.messageMetadata as Record<string, unknown>) ?? undefined,\n ) ?? createEmptyUsage();\n\n parts.push({\n type: \"finish\",\n finishReason,\n usage,\n providerMetadata: {\n \"bunny-agent\": {\n ...((parsed.messageMetadata as Record<string, unknown>) ?? {}),\n sessionId: this.sessionId,\n } as unknown as SharedV3ProviderMetadata,\n },\n });\n break;\n }\n }\n\n return parts;\n }\n\n private convertPromptToMessages(prompt: LanguageModelV3Prompt): Message[] {\n const messages: Message[] = [];\n\n for (const message of prompt) {\n switch (message.role) {\n case \"system\": {\n messages.push({\n role: \"system\",\n content: message.content,\n });\n break;\n }\n\n case \"user\": {\n const parts = message.content\n .map((part) => {\n if (part.type === \"text\") {\n return { type: \"text\" as const, text: part.text };\n }\n if (part.type === \"file\") {\n // LanguageModelV3FilePart: data is Uint8Array | string | URL, mediaType is IANA type\n let dataStr = \"\";\n if (part.data instanceof Uint8Array) {\n dataStr = `data:${part.mediaType};base64,${Buffer.from(part.data).toString(\"base64\")}`;\n } else if (part.data instanceof URL) {\n dataStr = part.data.toString();\n } else if (typeof part.data === \"string\") {\n // Already a data URL or base64 string\n dataStr = part.data;\n }\n return {\n type: \"image\" as const,\n mimeType: part.mediaType || \"image/png\",\n data: dataStr,\n };\n }\n return null;\n })\n .filter(\n (\n p,\n ): p is\n | { type: \"text\"; text: string }\n | { type: \"image\"; mimeType: string; data: string } =>\n p !== null,\n );\n\n if (parts.length > 0) {\n // If only text parts, combine them into a string for cleaner payload, else pass array\n const isAllText = parts.every((p) => p.type === \"text\");\n messages.push({\n role: \"user\",\n content: isAllText\n ? parts\n .map((p) => (p as { type: \"text\"; text: string }).text)\n .join(\"\\n\")\n : parts,\n });\n }\n break;\n }\n\n case \"assistant\": {\n const textParts = message.content\n .filter(\n (part): part is { type: \"text\"; text: string } =>\n part.type === \"text\",\n )\n .map((part) => part.text);\n\n if (textParts.length > 0) {\n messages.push({\n role: \"assistant\",\n content: textParts.join(\"\\n\"),\n });\n }\n break;\n }\n\n case \"tool\": {\n break;\n }\n }\n }\n\n return messages;\n }\n\n private mapFinishReason(\n reason: string | undefined,\n ): LanguageModelV3FinishReason {\n switch (reason) {\n case \"stop\":\n return { unified: \"stop\", raw: reason };\n case \"length\":\n return { unified: \"length\", raw: reason };\n case \"tool_calls\":\n case \"tool-calls\":\n return { unified: \"tool-calls\", raw: reason };\n case \"content_filter\":\n case \"content-filter\":\n return { unified: \"content-filter\", raw: reason };\n case \"error\":\n return { unified: \"error\", raw: reason };\n default:\n return { unified: \"other\", raw: reason ?? \"unknown\" };\n }\n }\n}\n","import type { BunnyAgentProviderSettings, Logger } from \"./types\";\n\n/** Shared logger factory for provider and language model. */\nexport function getProviderLogger(\n settings: Partial<BunnyAgentProviderSettings>,\n): Logger {\n if (settings.logger === false) {\n return {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n };\n }\n\n if (settings.logger) {\n return settings.logger;\n }\n\n const isVerbose = settings.verbose ?? false;\n return {\n debug: (msg) => isVerbose && console.debug(msg),\n info: (msg) => isVerbose && console.info(msg),\n warn: (msg) => console.warn(msg),\n error: (msg) => console.error(msg),\n };\n}\n","import type {\n JSONObject,\n LanguageModelV3FunctionTool,\n LanguageModelV3ProviderTool,\n SharedV3ProviderOptions,\n} from \"@ai-sdk/provider\";\nimport type { ToolRef } from \"@bunny-agent/manager\";\nimport type { Tool } from \"ai\";\n\nconst BUNNY_PROVIDER_OPTIONS_KEY = \"bunny-agent\";\n\ntype BunnyProviderOptions = {\n runtime?: JSONObject;\n};\n\ntype BunnyToolRuntime = Extract<\n ToolRef[\"runtime\"],\n { type: \"http\" | \"module\" }\n>;\n\ntype BunnyDynamicTool<INPUT> = Tool<INPUT, unknown> & { type: \"dynamic\" };\n\n/**\n * AI SDK helper for tools that the sandbox runner should call by HTTP.\n *\n * This is still used with the standard AI SDK `streamText`:\n * `import { streamText } from \"ai\"`.\n */\nexport function bunnyHttpTool<INPUT, OUTPUT>(\n input: Omit<Tool<INPUT, OUTPUT>, \"execute\" | \"outputSchema\"> & {\n endpoint: {\n url: string;\n headers?: Record<string, string>;\n };\n },\n): BunnyDynamicTool<INPUT> {\n return {\n type: \"dynamic\" as const,\n description: input.description,\n title: input.title,\n providerOptions: withBunnyProviderOptions(input.providerOptions, {\n runtime: {\n type: \"http\",\n url: input.endpoint.url,\n ...(input.endpoint.headers ? { headers: input.endpoint.headers } : {}),\n },\n }),\n inputSchema: input.inputSchema,\n inputExamples: input.inputExamples,\n needsApproval: input.needsApproval,\n strict: input.strict,\n onInputStart: input.onInputStart,\n onInputDelta: input.onInputDelta,\n onInputAvailable: input.onInputAvailable,\n async execute() {\n throw new Error(\n \"bunnyHttpTool is provider-executed by the sandbox runner.\",\n );\n },\n } satisfies BunnyDynamicTool<INPUT>;\n}\n\n/**\n * AI SDK helper for tools implemented by a module already present in the\n * sandbox filesystem.\n */\nexport function bunnySandboxTool<INPUT, OUTPUT>(\n input: Omit<Tool<INPUT, OUTPUT>, \"execute\" | \"outputSchema\"> & {\n module: string;\n exportName?: string;\n },\n): BunnyDynamicTool<INPUT> {\n return {\n type: \"dynamic\" as const,\n description: input.description,\n title: input.title,\n providerOptions: withBunnyProviderOptions(input.providerOptions, {\n runtime: {\n type: \"module\",\n module: input.module,\n ...(input.exportName ? { exportName: input.exportName } : {}),\n },\n }),\n inputSchema: input.inputSchema,\n inputExamples: input.inputExamples,\n needsApproval: input.needsApproval,\n strict: input.strict,\n onInputStart: input.onInputStart,\n onInputDelta: input.onInputDelta,\n onInputAvailable: input.onInputAvailable,\n async execute() {\n throw new Error(\n \"bunnySandboxTool is provider-executed by the sandbox runner.\",\n );\n },\n } satisfies BunnyDynamicTool<INPUT>;\n}\n\nexport function compileToolRefsFromLanguageModelTools(\n tools:\n | Array<LanguageModelV3FunctionTool | LanguageModelV3ProviderTool>\n | undefined,\n): ToolRef[] | undefined {\n if (!tools || tools.length === 0) return undefined;\n\n const toolRefs: ToolRef[] = [];\n\n for (const tool of tools) {\n if (tool.type !== \"function\") {\n continue;\n }\n\n const runtime = getBunnyRuntime(tool);\n if (!runtime) {\n throw new Error(\n `[bunny-agent] Tool \"${tool.name}\" was passed through AI SDK streamText, ` +\n \"but Bunny cannot access host-side tool({ execute }) callbacks at the provider boundary. \" +\n \"Use bunnyHttpTool(...) for an endpoint tool or bunnySandboxTool(...) for a sandbox-local module.\",\n );\n }\n\n toolRefs.push({\n name: tool.name,\n description: tool.description ?? \"\",\n inputSchema: tool.inputSchema as Record<string, unknown>,\n runtime,\n });\n }\n\n return toolRefs.length > 0 ? toolRefs : undefined;\n}\n\nfunction getBunnyRuntime(\n tool: LanguageModelV3FunctionTool,\n): BunnyToolRuntime | undefined {\n const options = tool.providerOptions?.[BUNNY_PROVIDER_OPTIONS_KEY] as\n | BunnyProviderOptions\n | undefined;\n const runtime = options?.runtime;\n if (!isRecord(runtime) || typeof runtime.type !== \"string\") {\n return undefined;\n }\n if (runtime.type === \"http\" && typeof runtime.url === \"string\") {\n return {\n type: \"http\",\n url: runtime.url,\n ...(isStringRecord(runtime.headers) ? { headers: runtime.headers } : {}),\n };\n }\n if (runtime.type === \"module\" && typeof runtime.module === \"string\") {\n return {\n type: \"module\",\n module: runtime.module,\n ...(typeof runtime.exportName === \"string\"\n ? { exportName: runtime.exportName }\n : {}),\n };\n }\n return undefined;\n}\n\nfunction withBunnyProviderOptions(\n providerOptions: SharedV3ProviderOptions | undefined,\n bunnyOptions: BunnyProviderOptions,\n): SharedV3ProviderOptions {\n return {\n ...(providerOptions ?? {}),\n [BUNNY_PROVIDER_OPTIONS_KEY]: {\n ...((providerOptions?.[BUNNY_PROVIDER_OPTIONS_KEY] as\n | object\n | undefined) ?? {}),\n ...bunnyOptions,\n },\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction isStringRecord(value: unknown): value is Record<string, string> {\n if (!isRecord(value)) return false;\n return Object.values(value).every((entry) => typeof entry === \"string\");\n}\n","import type { JSONValue, LanguageModelV3Usage } from \"@ai-sdk/provider\";\n\ntype JsonRecord = Record<string, JSONValue | undefined>;\n\nfunction asRecord(value: unknown): JsonRecord | undefined {\n if (value == null || typeof value !== \"object\" || Array.isArray(value)) {\n return undefined;\n }\n return value as JsonRecord;\n}\n\n/**\n * Extract `providerMetadata[\"bunny-agent\"]` from an AI SDK providerMetadata object.\n */\nexport function getBunnyAgentMetadata(\n providerMetadata: unknown,\n): JsonRecord | undefined {\n const providerMeta = asRecord(providerMetadata);\n if (providerMeta == null) return undefined;\n return asRecord(providerMeta[\"bunny-agent\"]);\n}\n\n/**\n * Extract Bunny Agent usage payload from an AI SDK providerMetadata object.\n *\n * This returns the raw usage object emitted by Bunny Agent stream metadata,\n * e.g. `{ input_tokens, output_tokens, cache_read_input_tokens, ... }`.\n */\nexport function getBunnyAgentUsage(\n providerMetadata: unknown,\n): LanguageModelV3Usage | undefined {\n const bunnyMeta = getBunnyAgentMetadata(providerMetadata);\n if (bunnyMeta == null) return undefined;\n return normalizeBunnyAgentUsage(bunnyMeta);\n}\n\n/**\n * Convert Bunny Agent usage metadata to AI SDK standard usage shape.\n *\n * Accepts either:\n * - a metadata object that contains `usage` plus extra fields (model/cost/image/search)\n * - or a direct usage payload in snake_case token fields.\n *\n * `raw` preserves usage fields and includes extra metadata fields when available.\n */\nexport function normalizeBunnyAgentUsage(\n data: unknown,\n): LanguageModelV3Usage | undefined {\n const dataRecord = asRecord(data);\n if (dataRecord == null) return undefined;\n\n const usageSource = asRecord(dataRecord.usage ?? dataRecord);\n if (usageSource == null) return undefined;\n const hasTokenFields =\n \"input_tokens\" in usageSource ||\n \"output_tokens\" in usageSource ||\n \"cache_read_input_tokens\" in usageSource ||\n \"cache_creation_input_tokens\" in usageSource;\n if (!hasTokenFields) return undefined;\n\n const inputTokens =\n typeof usageSource.input_tokens === \"number\" ? usageSource.input_tokens : 0;\n const outputTokens =\n typeof usageSource.output_tokens === \"number\"\n ? usageSource.output_tokens\n : 0;\n const cacheRead =\n typeof usageSource.cache_read_input_tokens === \"number\"\n ? usageSource.cache_read_input_tokens\n : 0;\n const cacheWrite =\n typeof usageSource.cache_creation_input_tokens === \"number\"\n ? usageSource.cache_creation_input_tokens\n : 0;\n const textTokens =\n typeof usageSource.text_tokens === \"number\"\n ? usageSource.text_tokens\n : undefined;\n const reasoningTokens =\n typeof usageSource.reasoning_tokens === \"number\"\n ? usageSource.reasoning_tokens\n : undefined;\n const extraMetadata = Object.fromEntries(\n Object.entries(dataRecord).filter(([key]) => key !== \"usage\"),\n ) as JsonRecord;\n const raw =\n Object.keys(extraMetadata).length > 0\n ? { ...usageSource, ...extraMetadata }\n : usageSource;\n\n return {\n inputTokens: {\n total: inputTokens + cacheRead + cacheWrite,\n noCache: inputTokens,\n cacheRead,\n cacheWrite,\n },\n outputTokens: {\n total: outputTokens,\n text: textTokens,\n reasoning: reasoningTokens,\n },\n raw,\n };\n}\n","import type {\n EmbeddingModelV3,\n ImageModelV3,\n LanguageModelV3,\n ProviderV3,\n} from \"@ai-sdk/provider\";\nimport { NoSuchModelError } from \"@ai-sdk/provider\";\nimport type { RunnerSpec } from \"@bunny-agent/manager\";\nimport { BunnyAgentLanguageModel } from \"./bunny-agent-language-model\";\nimport { getProviderLogger } from \"./logging\";\nimport type { BunnyAgentModelId, BunnyAgentProviderSettings } from \"./types\";\n\nexport type { BunnyAgentProviderSettings } from \"./types\";\n\n/**\n * BunnyAgent provider interface that extends the AI SDK's ProviderV3.\n */\nexport interface BunnyAgentProvider extends ProviderV3 {\n (\n modelId: BunnyAgentModelId,\n options?: Partial<BunnyAgentProviderSettings>,\n ): LanguageModelV3;\n\n languageModel(\n modelId: BunnyAgentModelId,\n options?: Partial<BunnyAgentProviderSettings>,\n ): LanguageModelV3;\n\n chat(\n modelId: BunnyAgentModelId,\n options?: Partial<BunnyAgentProviderSettings>,\n ): LanguageModelV3;\n\n embeddingModel(modelId: string): EmbeddingModelV3;\n textEmbeddingModel(modelId: string): EmbeddingModelV3;\n imageModel(modelId: string): ImageModelV3;\n}\n\n/**\n * Creates a BunnyAgent provider instance with the specified configuration.\n *\n * @example\n * ```typescript\n * import { createBunnyAgent } from '@bunny-agent/sdk';\n * import { E2BSandbox } from '@bunny-agent/sandbox-e2b';\n * import { generateText } from 'ai';\n *\n * const bunnyAgent = createBunnyAgent({\n * sandbox: new E2BSandbox({ apiKey: process.env.E2B_API_KEY! }),\n * env: {\n * ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY!,\n * },\n * });\n *\n * const { text } = await generateText({\n * model: bunnyAgent('sonnet'),\n * prompt: 'Create a hello world program',\n * });\n * ```\n */\nexport function createBunnyAgent(\n defaultOptions: BunnyAgentProviderSettings,\n): BunnyAgentProvider {\n const logger = getProviderLogger(defaultOptions);\n\n if (!defaultOptions.sandbox) {\n throw new Error(\n \"Provide a `sandbox` adapter (e.g. E2BSandbox, LocalMachine). \" +\n \"Optional `daemonUrl` uses in-sandbox HTTP to bunny-agent-daemon (no automatic `/healthz` probe). Use `isBunnyAgentDaemonHealthy` from `@bunny-agent/sdk` if you want to probe and omit `daemonUrl` for CLI fallback. Omit `daemonUrl` to always use CLI.\",\n );\n }\n\n const createModel = (\n modelId: BunnyAgentModelId,\n options: Partial<BunnyAgentProviderSettings> = {},\n ): LanguageModelV3 => {\n const mergedSkillPaths =\n options.skillPaths !== undefined\n ? options.skillPaths\n : defaultOptions.skillPaths;\n\n const mergedAllowedTools =\n options.allowedTools !== undefined\n ? options.allowedTools\n : defaultOptions.allowedTools;\n\n const runner: RunnerSpec = {\n model: modelId,\n runnerType: options.runnerType ?? defaultOptions.runnerType,\n outputFormat: \"stream\",\n maxTurns: options.maxTurns ?? defaultOptions.maxTurns,\n ...((options.systemPrompt ?? defaultOptions.systemPrompt)\n ? { systemPrompt: options.systemPrompt ?? defaultOptions.systemPrompt }\n : {}),\n ...(mergedSkillPaths && mergedSkillPaths.length > 0\n ? { skillPaths: mergedSkillPaths }\n : {}),\n ...(mergedAllowedTools !== undefined\n ? { allowedTools: mergedAllowedTools }\n : {}),\n ...((options.effort ?? defaultOptions.effort)\n ? {\n effort: options.effort ?? defaultOptions.effort,\n }\n : {}),\n };\n\n const mergedOptions = {\n ...defaultOptions,\n ...options,\n runner,\n env: {\n ...defaultOptions.env,\n ...options.env,\n },\n systemEnv:\n defaultOptions.systemEnv || options.systemEnv\n ? {\n ...(defaultOptions.systemEnv ?? {}),\n ...(options.systemEnv ?? {}),\n }\n : undefined,\n artifactProcessors: [\n ...(defaultOptions.artifactProcessors ?? []),\n ...(options.artifactProcessors ?? []),\n ],\n toolRefs:\n options.toolRefs !== undefined\n ? options.toolRefs\n : defaultOptions.toolRefs,\n } as BunnyAgentProviderSettings & { runner: RunnerSpec };\n\n logger.debug(\n `[bunny-agent] Creating model: ${modelId}${runner.runnerType ? ` (runnerType: ${runner.runnerType})` : \"\"}${runner.skillPaths?.length ? ` skillPaths=${runner.skillPaths.length}` : \"\"}`,\n );\n\n return new BunnyAgentLanguageModel({\n id: modelId,\n options: mergedOptions,\n });\n };\n\n const provider = function (\n modelId: BunnyAgentModelId,\n options?: Partial<BunnyAgentProviderSettings>,\n ) {\n if (new.target) {\n throw new Error(\n \"The BunnyAgent model function cannot be called with the new keyword.\",\n );\n }\n\n return createModel(modelId, options);\n };\n\n provider.languageModel = createModel;\n provider.chat = createModel;\n provider.specificationVersion = \"v3\" as const;\n\n provider.embeddingModel = (modelId: string): EmbeddingModelV3 => {\n throw new NoSuchModelError({\n modelId,\n modelType: \"embeddingModel\",\n });\n };\n\n provider.textEmbeddingModel = (modelId: string): EmbeddingModelV3 => {\n throw new NoSuchModelError({\n modelId,\n modelType: \"embeddingModel\",\n });\n };\n\n provider.imageModel = (modelId: string): ImageModelV3 => {\n throw new NoSuchModelError({\n modelId,\n modelType: \"imageModel\",\n });\n };\n\n return provider as BunnyAgentProvider;\n}\n","import type { SandboxAdapter } from \"@bunny-agent/manager\";\nimport type { SubmitAnswerParams } from \"./types\";\n\n/**\n * Options for submitAnswer\n */\nexport interface SubmitAnswerOptions {\n /**\n * Optional base path prefix for approval files\n * @default \".bunny-agent/approvals\"\n */\n basePath?: string;\n}\n\n/**\n * Submit user's answer for an AskUserQuestion tool call.\n * Writes the answer file to `.bunny-agent/approvals/{toolCallId}.json` in the sandbox workdir.\n *\n * @example\n * ```typescript\n * import { submitAnswer } from \"@bunny-agent/sdk\";\n *\n * await submitAnswer(sandbox, {\n * toolCallId: \"tool-456\",\n * questions: [...],\n * answers: { \"Question 1\": \"Answer 1\" },\n * });\n * ```\n */\nexport async function submitAnswer(\n sandbox: SandboxAdapter,\n params: SubmitAnswerParams,\n options?: SubmitAnswerOptions,\n): Promise<void> {\n const { toolCallId, questions, answers } = params;\n const basePath = options?.basePath ?? \".bunny-agent/approvals\";\n\n const allAnswered = questions.every(\n (q) => answers[q.question] !== undefined && answers[q.question] !== \"\",\n );\n\n const answerData = {\n questions,\n answers,\n status: allAnswered ? \"completed\" : \"pending\",\n timestamp: new Date().toISOString(),\n };\n\n const filename = `${toolCallId}.json`;\n const handle = sandbox.getHandle() ?? (await sandbox.attach());\n // Absolute path so remote sandboxes (Sandock) write to the same path the runner reads (/workspace/.bunny-agent/approvals).\n const workdir = handle.getWorkdir();\n const targetDir = workdir\n ? `${workdir.replace(/\\/$/, \"\")}/${basePath}`\n : basePath;\n\n await handle.upload(\n [{ path: filename, content: JSON.stringify(answerData, null, 2) }],\n targetDir,\n );\n\n console.log(\n `[submitAnswer] Answer submitted: ${targetDir}/${filename} (status: ${answerData.status}, workdir: ${workdir ?? \"(none)\"})`,\n );\n}\n"],"mappings":"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","names":["sandboxEnv"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bunny-agent/sdk",
3
- "version": "0.9.51",
3
+ "version": "0.9.52",
4
4
  "description": "BunnyAgent SDK - AI Provider and React hooks for building AI agents",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -52,7 +52,9 @@
52
52
  "dependencies": {
53
53
  "@ai-sdk/provider": "^3.0.8",
54
54
  "@ai-sdk/react": "^3.0.105",
55
- "@bunny-agent/manager": "0.9.51"
55
+ "@bunny-agent/manager": "0.9.52",
56
+ "@bunny-agent/sandbox-srt": "0.9.51-release.1",
57
+ "@bunny-agent/sandbox-local": "0.9.51-release.1"
56
58
  },
57
59
  "devDependencies": {
58
60
  "@types/node": "^20.10.0",