@bunny-agent/sdk 0.9.59-beta.3 → 0.9.59-beta.5

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/dist/index.d.ts CHANGED
@@ -25,27 +25,6 @@ interface StreamWriter {
25
25
  transient?: boolean;
26
26
  }): void;
27
27
  }
28
- /**
29
- * Context compaction progress reported by a runner.
30
- *
31
- * Runners whose agent SDK compacts the conversation automatically when the
32
- * context window fills (claude, copilot) emit a `start` event when compaction
33
- * begins and an `end` event when it finishes. Use it to render a transient
34
- * "Compacting…" indicator.
35
- */
36
- interface CompactionEvent {
37
- phase: "start" | "end";
38
- /** Only on `end`: whether compaction succeeded. */
39
- success?: boolean;
40
- /** What triggered it, when the runner reports it (e.g. "auto", "manual"). */
41
- trigger?: string;
42
- /** Context tokens before compaction. */
43
- preTokens?: number;
44
- /** Context tokens after compaction. */
45
- postTokens?: number;
46
- /** Failure detail, when compaction failed. */
47
- error?: string;
48
- }
49
28
  /**
50
29
  * Artifact Processor interface
51
30
  */
@@ -134,12 +113,6 @@ interface BunnyAgentProviderSettings extends Omit<BunnyAgentOptions, "runner" |
134
113
  logger?: Logger | false;
135
114
  /** Artifact processors for handling artifact events. */
136
115
  artifactProcessors?: ArtifactProcessor[];
137
- /**
138
- * Called when the runner reports context compaction progress. The AI SDK
139
- * stream protocol has no part type for this, so it is delivered out-of-band;
140
- * a UI typically forwards it as a transient data part.
141
- */
142
- onCompaction?: (event: CompactionEvent) => void;
143
116
  /** Limit the number of back-and-forth iterations */
144
117
  maxTurns?: number;
145
118
  /** Optional system prompt override (overrides template's default) */
@@ -341,4 +314,4 @@ declare function getBunnyAgentUsage(providerMetadata: unknown): LanguageModelV3U
341
314
 
342
315
  declare const VERSION = "0.1.0";
343
316
 
344
- export { type ArtifactProcessor, type ArtifactResult, BunnyAgentLanguageModel, type BunnyAgentLanguageModelOptions, type BunnyAgentModelId, type BunnyAgentProvider, type BunnyAgentProviderSettings, type CompactionEvent, type Logger, type Question, type StreamWriter, type SubmitAnswerOptions, type SubmitAnswerParams, VERSION, bunnyHttpTool, bunnySandboxTool, createBunnyAgent, getBunnyAgentMetadata, getBunnyAgentUsage, submitAnswer };
317
+ export { type ArtifactProcessor, type ArtifactResult, BunnyAgentLanguageModel, type BunnyAgentLanguageModelOptions, type BunnyAgentModelId, type BunnyAgentProvider, type BunnyAgentProviderSettings, type Logger, type Question, type StreamWriter, type SubmitAnswerOptions, type SubmitAnswerParams, VERSION, bunnyHttpTool, bunnySandboxTool, createBunnyAgent, getBunnyAgentMetadata, getBunnyAgentUsage, submitAnswer };
package/dist/index.js CHANGED
@@ -814,21 +814,6 @@ var BunnyAgentLanguageModel = class {
814
814
  }
815
815
  break;
816
816
  }
817
- // Context compaction progress. Delivered out-of-band via the
818
- // `onCompaction` callback: the AI SDK stream protocol has no part type
819
- // for it, and it must not become assistant content.
820
- case "compaction": {
821
- const phase = parsed.phase === "start" ? "start" : "end";
822
- this.options.onCompaction?.({
823
- phase,
824
- ...typeof parsed.success === "boolean" ? { success: parsed.success } : {},
825
- ...typeof parsed.trigger === "string" ? { trigger: parsed.trigger } : {},
826
- ...typeof parsed.preTokens === "number" ? { preTokens: parsed.preTokens } : {},
827
- ...typeof parsed.postTokens === "number" ? { postTokens: parsed.postTokens } : {},
828
- ...typeof parsed.error === "string" ? { error: parsed.error } : {}
829
- });
830
- break;
831
- }
832
817
  // Runners (claude/codex) emit reasoning as untagged deltas:
833
818
  // {type:"reasoning", text}. Wrap them in a synthesized
834
819
  // reasoning-start/delta/end part stream for the AI SDK.
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 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 CompactionEvent,\n // Re-exports from @ai-sdk/provider\n LanguageModelV3StreamPart,\n Logger,\n McpConfig,\n McpHttpServerConfig,\n McpLifecycle,\n McpServerConfig,\n McpServerOptions,\n McpSettings,\n McpStdioServerConfig,\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 type AgentTurnInputV1,\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 getCurrentTurnStart(messages: Message[]): number {\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role !== \"user\") return i + 1;\n }\n return 0;\n}\n\nasync function resolveImageData(\n data: string,\n declaredMediaType: string,\n): Promise<{ data: string; mediaType: string }> {\n if (!declaredMediaType.startsWith(\"image/\")) {\n throw new Error(\n `Unsupported BunnyAgent file media type: ${declaredMediaType}`,\n );\n }\n const dataUrl = /^data:([^;,]+);base64,(.+)$/s.exec(data);\n if (dataUrl) {\n if (!dataUrl[1].startsWith(\"image/\")) {\n throw new Error(\n `Unsupported BunnyAgent data URL media type: ${dataUrl[1]}`,\n );\n }\n return { mediaType: dataUrl[1], data: dataUrl[2] };\n }\n if (/^https?:\\/\\//i.test(data)) {\n const response = await fetch(data, { redirect: \"follow\" });\n if (!response.ok) {\n throw new Error(\n `Unable to fetch BunnyAgent image: HTTP ${response.status}`,\n );\n }\n const contentLength = Number(response.headers.get(\"content-length\") ?? 0);\n if (contentLength > 20 * 1024 * 1024) {\n throw new Error(\"BunnyAgent image exceeds the 20 MiB limit\");\n }\n const mediaType =\n response.headers.get(\"content-type\")?.split(\";\")[0] ?? declaredMediaType;\n if (!mediaType.startsWith(\"image/\")) {\n throw new Error(`Fetched BunnyAgent asset is not an image: ${mediaType}`);\n }\n const bytes = new Uint8Array(await response.arrayBuffer());\n if (bytes.byteLength > 20 * 1024 * 1024) {\n throw new Error(\"BunnyAgent image exceeds the 20 MiB limit\");\n }\n return { mediaType, data: Buffer.from(bytes).toString(\"base64\") };\n }\n return { mediaType: declaredMediaType, data };\n}\n\nexport async function compileMessagesToAgentInput(\n messages: Message[],\n includeHistory: boolean,\n): Promise<AgentTurnInputV1> {\n const selected = includeHistory\n ? messages\n : messages.slice(getCurrentTurnStart(messages));\n const text: string[] = [];\n const assets: AgentTurnInputV1[\"input\"] = [];\n let imageNumber = 0;\n\n for (const message of selected) {\n if (includeHistory) {\n const role = message.role[0].toUpperCase() + message.role.slice(1);\n text.push(`${role}: `);\n }\n const parts =\n typeof message.content === \"string\"\n ? [{ type: \"text\" as const, text: message.content }]\n : message.content;\n for (const part of parts) {\n if (part.type === \"text\") {\n text.push(part.text);\n continue;\n }\n imageNumber += 1;\n const label = `[Image #${imageNumber}]`;\n const resolved = await resolveImageData(part.data, part.mimeType);\n if (!text.join(\"\").endsWith(label)) text.push(label);\n assets.push({\n type: \"asset\",\n id: `image-${imageNumber}`,\n label,\n asset: resolved,\n });\n }\n text.push(\"\\n\\n\");\n }\n\n return {\n version: 1,\n input: [...assets, { type: \"text\", text: text.join(\"\").trimEnd() }],\n capabilities: [],\n execution: {\n resolvedBy: \"server\",\n skills: [],\n integrations: [],\n references: [],\n capabilityKeys: [],\n extensionVersions: {},\n },\n };\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 ...(await this.buildCodingRunBody(\n messages,\n handle.getWorkdir(),\n toolRefs,\n )),\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 input = await compileMessagesToAgentInput(\n messages,\n !(this.options.resume ?? this.options.forkFrom),\n );\n const bytesStream = await agent.stream({\n messages,\n input,\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 ...(this.options.mcpConfig\n ? { mcpConfig: this.options.mcpConfig }\n : {}),\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 async buildCodingRunBody(\n messages: Message[],\n cwdFallback: string,\n toolRefs: ToolRef[] | undefined,\n ): Promise<BunnyAgentCodingRunBody> {\n const runner = this.options.runner;\n const cwd = this.options.cwd ?? cwdFallback;\n\n const hasRuntimeHistory = Boolean(\n this.options.resume ?? this.options.forkFrom,\n );\n const input = await compileMessagesToAgentInput(\n messages,\n !hasRuntimeHistory,\n );\n\n return {\n runner: runner.runnerType ?? \"claude\",\n model: this.modelId,\n input,\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.mcpConfig ? { mcpConfig: this.options.mcpConfig } : {}),\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 // Context compaction progress. Delivered out-of-band via the\n // `onCompaction` callback: the AI SDK stream protocol has no part type\n // for it, and it must not become assistant content.\n case \"compaction\": {\n const phase = parsed.phase === \"start\" ? \"start\" : \"end\";\n this.options.onCompaction?.({\n phase,\n ...(typeof parsed.success === \"boolean\"\n ? { success: parsed.success }\n : {}),\n ...(typeof parsed.trigger === \"string\"\n ? { trigger: parsed.trigger }\n : {}),\n ...(typeof parsed.preTokens === \"number\"\n ? { preTokens: parsed.preTokens }\n : {}),\n ...(typeof parsed.postTokens === \"number\"\n ? { postTokens: parsed.postTokens }\n : {}),\n ...(typeof parsed.error === \"string\" ? { error: parsed.error } : {}),\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"]}
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 McpConfig,\n McpHttpServerConfig,\n McpLifecycle,\n McpServerConfig,\n McpServerOptions,\n McpSettings,\n McpStdioServerConfig,\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 type AgentTurnInputV1,\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 getCurrentTurnStart(messages: Message[]): number {\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role !== \"user\") return i + 1;\n }\n return 0;\n}\n\nasync function resolveImageData(\n data: string,\n declaredMediaType: string,\n): Promise<{ data: string; mediaType: string }> {\n if (!declaredMediaType.startsWith(\"image/\")) {\n throw new Error(\n `Unsupported BunnyAgent file media type: ${declaredMediaType}`,\n );\n }\n const dataUrl = /^data:([^;,]+);base64,(.+)$/s.exec(data);\n if (dataUrl) {\n if (!dataUrl[1].startsWith(\"image/\")) {\n throw new Error(\n `Unsupported BunnyAgent data URL media type: ${dataUrl[1]}`,\n );\n }\n return { mediaType: dataUrl[1], data: dataUrl[2] };\n }\n if (/^https?:\\/\\//i.test(data)) {\n const response = await fetch(data, { redirect: \"follow\" });\n if (!response.ok) {\n throw new Error(\n `Unable to fetch BunnyAgent image: HTTP ${response.status}`,\n );\n }\n const contentLength = Number(response.headers.get(\"content-length\") ?? 0);\n if (contentLength > 20 * 1024 * 1024) {\n throw new Error(\"BunnyAgent image exceeds the 20 MiB limit\");\n }\n const mediaType =\n response.headers.get(\"content-type\")?.split(\";\")[0] ?? declaredMediaType;\n if (!mediaType.startsWith(\"image/\")) {\n throw new Error(`Fetched BunnyAgent asset is not an image: ${mediaType}`);\n }\n const bytes = new Uint8Array(await response.arrayBuffer());\n if (bytes.byteLength > 20 * 1024 * 1024) {\n throw new Error(\"BunnyAgent image exceeds the 20 MiB limit\");\n }\n return { mediaType, data: Buffer.from(bytes).toString(\"base64\") };\n }\n return { mediaType: declaredMediaType, data };\n}\n\nexport async function compileMessagesToAgentInput(\n messages: Message[],\n includeHistory: boolean,\n): Promise<AgentTurnInputV1> {\n const selected = includeHistory\n ? messages\n : messages.slice(getCurrentTurnStart(messages));\n const text: string[] = [];\n const assets: AgentTurnInputV1[\"input\"] = [];\n let imageNumber = 0;\n\n for (const message of selected) {\n if (includeHistory) {\n const role = message.role[0].toUpperCase() + message.role.slice(1);\n text.push(`${role}: `);\n }\n const parts =\n typeof message.content === \"string\"\n ? [{ type: \"text\" as const, text: message.content }]\n : message.content;\n for (const part of parts) {\n if (part.type === \"text\") {\n text.push(part.text);\n continue;\n }\n imageNumber += 1;\n const label = `[Image #${imageNumber}]`;\n const resolved = await resolveImageData(part.data, part.mimeType);\n if (!text.join(\"\").endsWith(label)) text.push(label);\n assets.push({\n type: \"asset\",\n id: `image-${imageNumber}`,\n label,\n asset: resolved,\n });\n }\n text.push(\"\\n\\n\");\n }\n\n return {\n version: 1,\n input: [...assets, { type: \"text\", text: text.join(\"\").trimEnd() }],\n capabilities: [],\n execution: {\n resolvedBy: \"server\",\n skills: [],\n integrations: [],\n references: [],\n capabilityKeys: [],\n extensionVersions: {},\n },\n };\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 ...(await this.buildCodingRunBody(\n messages,\n handle.getWorkdir(),\n toolRefs,\n )),\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 input = await compileMessagesToAgentInput(\n messages,\n !(this.options.resume ?? this.options.forkFrom),\n );\n const bytesStream = await agent.stream({\n messages,\n input,\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 ...(this.options.mcpConfig\n ? { mcpConfig: this.options.mcpConfig }\n : {}),\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 async buildCodingRunBody(\n messages: Message[],\n cwdFallback: string,\n toolRefs: ToolRef[] | undefined,\n ): Promise<BunnyAgentCodingRunBody> {\n const runner = this.options.runner;\n const cwd = this.options.cwd ?? cwdFallback;\n\n const hasRuntimeHistory = Boolean(\n this.options.resume ?? this.options.forkFrom,\n );\n const input = await compileMessagesToAgentInput(\n messages,\n !hasRuntimeHistory,\n );\n\n return {\n runner: runner.runnerType ?? \"claude\",\n model: this.modelId,\n input,\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.mcpConfig ? { mcpConfig: this.options.mcpConfig } : {}),\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"]}
@@ -22,25 +22,9 @@ interface UseBunnyAgentChatOptions {
22
22
  /**
23
23
  * Return type for useBunnyAgentChat hook
24
24
  */
25
- /**
26
- * Context compaction in progress.
27
- *
28
- * Runners backed by an agent SDK that compacts automatically when the context
29
- * window fills (claude, copilot) report this; it is non-null only while
30
- * compaction is running.
31
- */
32
- interface CompactionState {
33
- phase: "start" | "end";
34
- /** What triggered it, when reported (e.g. "auto", "manual"). */
35
- trigger?: string;
36
- /** Context tokens before compaction, when reported. */
37
- preTokens?: number;
38
- }
39
25
  interface UseBunnyAgentChatReturn {
40
26
  /** All chat messages */
41
27
  messages: UIMessage[];
42
- /** Non-null while the runner is compacting the conversation context. */
43
- compaction: CompactionState | null;
44
28
  /** Current chat status */
45
29
  status: "submitted" | "streaming" | "ready" | "error";
46
30
  /** Error if any */
@@ -452,4 +436,4 @@ interface UseWriteToolReturn {
452
436
  */
453
437
  declare function useWriteTool({ part, }: UseWriteToolOptions): UseWriteToolReturn;
454
438
 
455
- export { type ArtifactData, type AskUserQuestionInput, type AskUserQuestionOutput, type CompactionState, type Question, type QuestionOption, type UseArtifactsOptions$1 as UseArtifactsOptions, type UseArtifactsReturn$1 as UseArtifactsReturn, type UseAskUserQuestionOptions, type UseAskUserQuestionReturn, type UseBunnyAgentChatOptions, type UseBunnyAgentChatReturn, type UseWriteToolOptions$1 as UseWriteToolOptions, type UseWriteToolReturn$1 as UseWriteToolReturn, type WriteToolInput, type WriteToolOutput, useArtifacts, useAskUserQuestion, useBunnyAgentChat, useWriteTool };
439
+ export { type ArtifactData, type AskUserQuestionInput, type AskUserQuestionOutput, type Question, type QuestionOption, type UseArtifactsOptions$1 as UseArtifactsOptions, type UseArtifactsReturn$1 as UseArtifactsReturn, type UseAskUserQuestionOptions, type UseAskUserQuestionReturn, type UseBunnyAgentChatOptions, type UseBunnyAgentChatReturn, type UseWriteToolOptions$1 as UseWriteToolOptions, type UseWriteToolReturn$1 as UseWriteToolReturn, type WriteToolInput, type WriteToolOutput, useArtifacts, useAskUserQuestion, useBunnyAgentChat, useWriteTool };
@@ -265,7 +265,6 @@ function useBunnyAgentChat({
265
265
  }
266
266
  return void 0;
267
267
  };
268
- const [compaction, setCompaction] = useState3(null);
269
268
  const {
270
269
  messages,
271
270
  sendMessage: sendMessageInternal,
@@ -283,12 +282,7 @@ function useBunnyAgentChat({
283
282
  ...bodyRef.current
284
283
  };
285
284
  }
286
- }),
287
- onData: (dataPart) => {
288
- if (dataPart.type !== "data-compaction") return;
289
- const event = dataPart.data;
290
- setCompaction(event.phase === "start" ? event : null);
291
- }
285
+ })
292
286
  });
293
287
  useEffect2(() => {
294
288
  messagesRef.current = messages;
@@ -374,7 +368,6 @@ function useBunnyAgentChat({
374
368
  );
375
369
  return {
376
370
  messages,
377
- compaction,
378
371
  status,
379
372
  error,
380
373
  isLoading,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/index.ts","../../src/react/useArtifacts.ts","../../src/react/useAskUserQuestion.ts","../../src/react/useBunnyAgentChat.ts","../../src/react/useWriteTool.ts"],"sourcesContent":["\"use client\";\n\nexport { DEFAULT_BUNNY_AGENT_DAEMON_URL } from \"@bunny-agent/manager\";\n\n// Types\nexport type {\n // Artifact types\n ArtifactData,\n AskUserQuestionInput,\n AskUserQuestionOutput,\n // Context compaction indicator\n CompactionState,\n DynamicToolUIPart,\n // useAskUserQuestion types\n Question,\n QuestionOption,\n // AI SDK types\n UIMessage,\n // useArtifacts types\n UseArtifactsOptions,\n UseArtifactsReturn,\n UseAskUserQuestionOptions,\n UseAskUserQuestionReturn,\n // useBunnyAgentChat types\n UseBunnyAgentChatOptions,\n UseBunnyAgentChatReturn,\n UseWriteToolOptions,\n UseWriteToolReturn,\n // useWriteTool types\n WriteToolInput,\n WriteToolOutput,\n} from \"./types\";\nexport { useArtifacts } from \"./useArtifacts\";\nexport { useAskUserQuestion } from \"./useAskUserQuestion\";\n// Hooks\nexport { useBunnyAgentChat } from \"./useBunnyAgentChat\";\nexport { useWriteTool } from \"./useWriteTool\";\n","\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { ArtifactData, UIMessage } from \"./types\";\n\n/**\n * Options for useArtifacts hook\n */\nexport interface UseArtifactsOptions {\n /** Messages to extract artifacts from */\n messages: UIMessage[];\n}\n\n/**\n * Return type for useArtifacts hook\n */\nexport interface UseArtifactsReturn {\n /** All extracted artifacts */\n artifacts: ArtifactData[];\n /** Currently selected artifact */\n selectedArtifact: ArtifactData | null;\n /** Set the selected artifact */\n setSelectedArtifact: (artifact: ArtifactData | null) => void;\n /** Select artifact by ID */\n selectArtifactById: (artifactId: string) => void;\n /** Whether there are any artifacts */\n hasArtifacts: boolean;\n /** Number of artifacts */\n count: number;\n /** Copy artifact content to clipboard */\n copyContent: (artifact: ArtifactData) => Promise<void>;\n /** Download artifact as file */\n downloadArtifact: (artifact: ArtifactData) => void;\n /** Get file extension from mime type */\n getFileExtension: (mimeType: string) => string;\n}\n\n/**\n * Get file extension from MIME type\n */\nfunction getFileExtensionFromMimeType(mimeType: string): string {\n const mimeToExtension: Record<string, string> = {\n \"text/plain\": \"txt\",\n \"text/html\": \"html\",\n \"text/css\": \"css\",\n \"text/javascript\": \"js\",\n \"text/markdown\": \"md\",\n \"application/json\": \"json\",\n \"application/xml\": \"xml\",\n \"application/pdf\": \"pdf\",\n \"image/png\": \"png\",\n \"image/jpeg\": \"jpg\",\n \"image/gif\": \"gif\",\n \"image/svg+xml\": \"svg\",\n };\n\n // Try exact match\n if (mimeToExtension[mimeType]) {\n return mimeToExtension[mimeType];\n }\n\n // Try partial match (e.g., \"text/x-markdown\" -> \"md\")\n if (mimeType.includes(\"markdown\")) return \"md\";\n if (mimeType.includes(\"json\")) return \"json\";\n if (mimeType.includes(\"javascript\")) return \"js\";\n if (mimeType.includes(\"typescript\")) return \"ts\";\n if (mimeType.includes(\"html\")) return \"html\";\n if (mimeType.includes(\"css\")) return \"css\";\n if (mimeType.includes(\"xml\")) return \"xml\";\n if (mimeType.includes(\"python\")) return \"py\";\n\n // Default\n return \"txt\";\n}\n\n/**\n * useArtifacts - Hook for managing artifacts from chat messages\n *\n * Extracts artifacts from messages and provides selection,\n * copy, and download functionality.\n *\n * @example\n * ```tsx\n * import { useArtifacts } from \"@bunny-agent/sdk/react\";\n *\n * function ArtifactPanel({ messages }) {\n * const {\n * artifacts,\n * selectedArtifact,\n * setSelectedArtifact,\n * hasArtifacts,\n * copyContent,\n * downloadArtifact,\n * } = useArtifacts({ messages });\n *\n * if (!hasArtifacts) return null;\n *\n * return (\n * <div>\n * {artifacts.map((artifact) => (\n * <button\n * key={artifact.artifactId}\n * onClick={() => setSelectedArtifact(artifact)}\n * >\n * {artifact.artifactId}\n * </button>\n * ))}\n *\n * {selectedArtifact && (\n * <div>\n * <pre>{selectedArtifact.content}</pre>\n * <button onClick={() => copyContent(selectedArtifact)}>Copy</button>\n * <button onClick={() => downloadArtifact(selectedArtifact)}>Download</button>\n * </div>\n * )}\n * </div>\n * );\n * }\n * ```\n */\nexport function useArtifacts({\n messages,\n}: UseArtifactsOptions): UseArtifactsReturn {\n const [selectedArtifact, setSelectedArtifact] = useState<ArtifactData | null>(\n null,\n );\n\n // Extract artifacts from messages with memoization optimization\n const prevArtifactsRef = useRef<ArtifactData[]>([]);\n const artifacts = useMemo(() => {\n const results: ArtifactData[] = [];\n for (const message of messages) {\n for (const part of message.parts) {\n if (part.type === \"data-artifact\") {\n const data = part.data as ArtifactData;\n if (!results.some((a) => a.artifactId === data.artifactId)) {\n results.push(data);\n }\n }\n }\n }\n\n // Memoization optimization - return previous reference if content unchanged\n const prev = prevArtifactsRef.current;\n if (\n prev.length === results.length &&\n prev.every((prevArt, idx) => {\n const currArt = results[idx];\n return (\n prevArt.artifactId === currArt.artifactId &&\n prevArt.content === currArt.content &&\n prevArt.mimeType === currArt.mimeType\n );\n })\n ) {\n return prev;\n }\n\n prevArtifactsRef.current = results;\n return results;\n }, [messages]);\n\n // Sync selectedArtifact when artifacts change\n useEffect(() => {\n if (artifacts.length > 0) {\n setSelectedArtifact((prev) => {\n if (!prev) return artifacts[0];\n\n const currentMatch = artifacts.find(\n (a) => a.artifactId === prev.artifactId,\n );\n\n if (!currentMatch) {\n return artifacts[0];\n }\n\n if (\n currentMatch.content === prev.content &&\n currentMatch.mimeType === prev.mimeType\n ) {\n return prev;\n }\n\n return currentMatch;\n });\n } else {\n setSelectedArtifact((prev) => (prev === null ? prev : null));\n }\n }, [artifacts]);\n\n // Select artifact by ID\n const selectArtifactById = useCallback(\n (artifactId: string) => {\n const artifact = artifacts.find((a) => a.artifactId === artifactId);\n if (artifact) {\n setSelectedArtifact(artifact);\n }\n },\n [artifacts],\n );\n\n // Copy content to clipboard\n const copyContent = useCallback(async (artifact: ArtifactData) => {\n await navigator.clipboard.writeText(artifact.content);\n }, []);\n\n // Download artifact as file\n const downloadArtifact = useCallback((artifact: ArtifactData) => {\n const blob = new Blob([artifact.content], { type: artifact.mimeType });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n const fileName =\n artifact.artifactId.split(\"/\").pop() || artifact.artifactId;\n const extension = getFileExtensionFromMimeType(artifact.mimeType);\n a.download = fileName.includes(\".\") ? fileName : `${fileName}.${extension}`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n }, []);\n\n const hasArtifacts = artifacts.length > 0;\n const count = artifacts.length;\n\n return {\n artifacts,\n selectedArtifact,\n setSelectedArtifact,\n selectArtifactById,\n hasArtifacts,\n count,\n copyContent,\n downloadArtifact,\n getFileExtension: getFileExtensionFromMimeType,\n };\n}\n","\"use client\";\n\nimport { useCallback, useMemo, useState } from \"react\";\nimport type {\n AskUserQuestionInput,\n AskUserQuestionOutput,\n Question,\n UseAskUserQuestionOptions,\n UseAskUserQuestionReturn,\n} from \"./types\";\n\n/**\n * useAskUserQuestion - Hook for handling AskUserQuestion tool interactions\n *\n * Manages the state for user question/answer interactions in chat.\n * Provides answer selection, completion detection, and formatted output.\n *\n * @example\n * ```tsx\n * import { useAskUserQuestion } from \"@bunny-agent/sdk/react\";\n *\n * function QuestionUI({ part, sessionId }) {\n * const {\n * questions,\n * answers,\n * isCompleted,\n * selectAnswer,\n * isSelected,\n * } = useAskUserQuestion({\n * part,\n * onAnswer: (data) => {\n * fetch(\"/api/answer\", {\n * method: \"POST\",\n * body: JSON.stringify(data),\n * });\n * },\n * });\n *\n * if (isCompleted) {\n * return <div>Completed</div>;\n * }\n *\n * return (\n * <div>\n * {questions.map((q) => (\n * <div key={q.question}>\n * <p>{q.question}</p>\n * {q.options?.map((opt) => (\n * <button\n * key={opt.label}\n * onClick={() => selectAnswer(q.question, opt.label, q.multiSelect)}\n * style={{ fontWeight: isSelected(q.question, opt.label, q.multiSelect) ? 'bold' : 'normal' }}\n * >\n * {opt.label}\n * </button>\n * ))}\n * </div>\n * ))}\n * </div>\n * );\n * }\n * ```\n */\nexport function useAskUserQuestion({\n part,\n answerEndpoint = \"/api/answer\",\n extraBody,\n onAnswer,\n}: UseAskUserQuestionOptions): UseAskUserQuestionReturn {\n const [answers, setAnswers] = useState<Record<string, string | string[]>>({});\n\n // Parse questions from part.input\n const questions = useMemo((): Question[] => {\n if (!part.input || typeof part.input !== \"object\") return [];\n const input = part.input as AskUserQuestionInput;\n if (!input.questions || !Array.isArray(input.questions)) return [];\n return input.questions;\n }, [part.input]);\n\n // Parse answers from part.output (for restored sessions)\n const outputAnswers = useMemo((): Record<\n string,\n string | string[]\n > | null => {\n if (part.output && typeof part.output === \"object\") {\n const output = part.output as AskUserQuestionOutput;\n if (output.answers) {\n const hasRealAnswers = Object.values(output.answers).some(\n (v) => v && v.trim() !== \"\",\n );\n if (hasRealAnswers) {\n const parsed: Record<string, string | string[]> = {};\n for (const q of questions) {\n const val = output.answers[q.question];\n if (q.multiSelect && val) {\n parsed[q.question] = val.split(\", \").filter(Boolean);\n } else {\n parsed[q.question] = val || \"\";\n }\n }\n return parsed;\n }\n }\n }\n return null;\n }, [part.output, questions]);\n\n // Determine display answers (user input or restored from output)\n const displayAnswers = useMemo(() => {\n return Object.keys(answers).length > 0 ? answers : outputAnswers || {};\n }, [answers, outputAnswers]);\n\n // Check if completed\n const isCompleted = useMemo(() => {\n return (\n part.state === \"output-available\" ||\n (Object.keys(answers).length === 0 && outputAnswers !== null)\n );\n }, [part.state, answers, outputAnswers]);\n\n // Check if waiting for input (for animation)\n const isWaitingForInput = part.state === \"input-available\";\n\n // Get formatted answers map\n const getAnswersMap = useCallback((): Record<string, string> => {\n const answersMap: Record<string, string> = {};\n for (const q of questions) {\n const answer = displayAnswers[q.question];\n if (q.multiSelect) {\n answersMap[q.question] = Array.isArray(answer) ? answer.join(\", \") : \"\";\n } else {\n answersMap[q.question] = (answer as string) || \"\";\n }\n }\n return answersMap;\n }, [questions, displayAnswers]);\n\n // Select answer handler\n const selectAnswer = useCallback(\n (question: string, value: string, multiSelect = false) => {\n const newAnswers = { ...answers };\n\n if (multiSelect) {\n const current = (newAnswers[question] as string[]) || [];\n newAnswers[question] = current.includes(value)\n ? current.filter((v) => v !== value)\n : [...current, value];\n } else {\n newAnswers[question] = value;\n }\n\n setAnswers(newAnswers);\n\n // Prepare answers map for callback and API\n const answersMap: Record<string, string> = {};\n for (const q of questions) {\n const answer = newAnswers[q.question];\n if (q.multiSelect) {\n answersMap[q.question] = Array.isArray(answer)\n ? answer.join(\", \")\n : \"\";\n } else {\n answersMap[q.question] = (answer as string) || \"\";\n }\n }\n\n // Auto-submit to answer endpoint\n fetch(answerEndpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n toolCallId: part.toolCallId,\n questions,\n answers: answersMap,\n ...extraBody,\n }),\n }).catch((err) => {\n console.error(\"[useAskUserQuestion] Submit failed:\", err);\n });\n\n // Trigger callback\n onAnswer?.({\n toolCallId: part.toolCallId,\n questions,\n answers: answersMap,\n });\n },\n [answers, questions, part.toolCallId, answerEndpoint, extraBody, onAnswer],\n );\n\n // Check if option is selected\n const isSelected = useCallback(\n (question: string, optionLabel: string, multiSelect = false): boolean => {\n const selectedValue = displayAnswers[question];\n if (multiSelect) {\n return (\n (selectedValue as string[] | undefined)?.includes(optionLabel) ??\n false\n );\n }\n return selectedValue === optionLabel;\n },\n [displayAnswers],\n );\n\n return {\n questions,\n answers: displayAnswers,\n isCompleted,\n isWaitingForInput,\n selectAnswer,\n getAnswersMap,\n isSelected,\n };\n}\n","\"use client\";\n\nimport { useChat } from \"@ai-sdk/react\";\nimport { DefaultChatTransport, type UIMessage } from \"ai\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type {\n ArtifactData,\n CompactionState,\n UseBunnyAgentChatOptions,\n UseBunnyAgentChatReturn,\n} from \"./types\";\n\n/**\n * useBunnyAgentChat - Core hook for BunnyAgent chat functionality\n *\n * Provides all the logic needed for a chat interface:\n * - Message management\n * - Artifact extraction\n * - Session management\n *\n * @example\n * ```tsx\n * import { useBunnyAgentChat } from \"@bunny-agent/sdk/react\";\n *\n * const {\n * messages,\n * sendMessage,\n * status,\n * artifacts,\n * selectedArtifact,\n * setSelectedArtifact,\n * } = useBunnyAgentChat({\n * apiEndpoint: \"/api/ai\",\n * body: { template: \"default\" },\n * });\n * ```\n */\nexport function useBunnyAgentChat({\n apiEndpoint = \"/api/ai\",\n body = {},\n}: UseBunnyAgentChatOptions = {}): UseBunnyAgentChatReturn {\n // Artifact selection state\n const [selectedArtifact, setSelectedArtifact] = useState<ArtifactData | null>(\n null,\n );\n\n // Refs for accessing latest values in callbacks\n const bodyRef = useRef(body);\n const messagesRef = useRef<UIMessage[]>([]);\n\n // Keep transport body in sync on every render (not only after useEffect) so\n // the first fetch after hydration includes the latest client config.\n bodyRef.current = body;\n\n // Helper to extract resume value (sessionId) from message parts' providerMetadata.\n const getResumeFromMessage = (\n message: UIMessage | undefined,\n ): string | undefined => {\n if (!message?.parts) return undefined;\n for (const part of message.parts) {\n if (part.type === \"text\") {\n const providerMetadata = (\n part as {\n providerMetadata?: { \"bunny-agent\"?: { sessionId?: string } };\n }\n ).providerMetadata;\n if (providerMetadata?.[\"bunny-agent\"]?.sessionId) {\n return providerMetadata[\"bunny-agent\"].sessionId;\n }\n }\n }\n return undefined;\n };\n\n // Context compaction indicator. The runner's agent SDK compacts the\n // conversation automatically when the context window fills; the server sends\n // it as a transient data part, so it arrives via onData rather than in\n // message.parts.\n const [compaction, setCompaction] = useState<CompactionState | null>(null);\n\n // Core chat hook\n const {\n messages,\n sendMessage: sendMessageInternal,\n status,\n error,\n stop,\n } = useChat({\n transport: new DefaultChatTransport({\n api: apiEndpoint,\n body: () => {\n const lastAssistantMessage = [...messagesRef.current]\n .reverse()\n .find((m) => m.role === \"assistant\");\n const resume = getResumeFromMessage(lastAssistantMessage);\n return {\n resume,\n ...bodyRef.current,\n };\n },\n }),\n onData: (dataPart) => {\n if (dataPart.type !== \"data-compaction\") return;\n const event = dataPart.data as CompactionState & {\n phase: \"start\" | \"end\";\n };\n setCompaction(event.phase === \"start\" ? event : null);\n },\n });\n\n // Keep messagesRef in sync\n useEffect(() => {\n messagesRef.current = messages;\n }, [messages]);\n\n // Extract artifacts from messages\n const prevArtifactsRef = useRef<ArtifactData[]>([]);\n const artifacts = useMemo(() => {\n const results: ArtifactData[] = [];\n for (const message of messages) {\n for (const part of message.parts) {\n if (part.type === \"data-artifact\") {\n const data = part.data as ArtifactData;\n if (!results.some((a) => a.artifactId === data.artifactId)) {\n results.push(data);\n }\n }\n }\n }\n\n // Memoization optimization\n const prev = prevArtifactsRef.current;\n if (\n prev.length === results.length &&\n prev.every((prevArt, idx) => {\n const currArt = results[idx];\n return (\n prevArt.artifactId === currArt.artifactId &&\n prevArt.content === currArt.content &&\n prevArt.mimeType === currArt.mimeType\n );\n })\n ) {\n return prev;\n }\n\n prevArtifactsRef.current = results;\n return results;\n }, [messages]);\n\n // Sync selectedArtifact when artifacts change\n useEffect(() => {\n if (artifacts.length > 0) {\n setSelectedArtifact((prev) => {\n if (!prev) return artifacts[0];\n\n const currentMatch = artifacts.find(\n (a) => a.artifactId === prev.artifactId,\n );\n\n if (!currentMatch) {\n return artifacts[0];\n }\n\n if (\n currentMatch.content === prev.content &&\n currentMatch.mimeType === prev.mimeType\n ) {\n return prev;\n }\n\n return currentMatch;\n });\n } else {\n setSelectedArtifact((prev) => (prev === null ? prev : null));\n }\n }, [artifacts]);\n\n const isLoading = status === \"streaming\" || status === \"submitted\";\n const hasError = status === \"error\" && !!error;\n\n // Send message helper\n const sendMessage = useCallback(\n (text: string) => {\n if (!isLoading && text.trim()) {\n sendMessageInternal({\n role: \"user\",\n parts: [{ type: \"text\", text: text.trim() }],\n });\n }\n },\n [isLoading, sendMessageInternal],\n );\n\n // Handle submit for PromptInput compatibility\n const handleSubmit = useCallback(\n (message: { text: string; files?: import(\"ai\").FileUIPart[] }) => {\n if (!isLoading) {\n const parts: import(\"ai\").UIMessage[\"parts\"] = [];\n if (message.text) {\n parts.push({ type: \"text\", text: message.text.trim() });\n }\n if (message.files && message.files.length > 0) {\n for (const file of message.files) {\n parts.push(file);\n }\n }\n if (parts.length > 0) {\n sendMessageInternal({\n role: \"user\",\n parts,\n });\n } else {\n sendMessageInternal();\n }\n }\n },\n [isLoading, sendMessageInternal],\n );\n\n return {\n messages,\n compaction,\n status,\n error,\n isLoading,\n hasError,\n artifacts,\n selectedArtifact,\n setSelectedArtifact,\n sendMessage,\n stop,\n handleSubmit,\n };\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport type { DynamicToolUIPart } from \"./types\";\n\n/**\n * Write tool input structure\n */\nexport interface WriteToolInput {\n file_path: string;\n content: string;\n}\n\n/**\n * Write tool output structure\n */\nexport interface WriteToolOutput {\n type: \"create\" | \"edit\";\n filePath: string;\n content: string;\n structuredPatch?: unknown[];\n originalFile?: string | null;\n}\n\n/**\n * Options for useWriteTool hook\n */\nexport interface UseWriteToolOptions {\n /** The dynamic tool UI part from the message */\n part: DynamicToolUIPart;\n}\n\n/**\n * Return type for useWriteTool hook\n */\nexport interface UseWriteToolReturn {\n /** File path being written to */\n filePath: string | null;\n /** File name (extracted from path) */\n fileName: string | null;\n /** File content */\n content: string | null;\n /** Operation type: 'create' or 'edit' */\n operationType: \"create\" | \"edit\" | null;\n /** Original file content (for edit operations) */\n originalContent: string | null;\n /** Structured patch data (for edit operations) */\n structuredPatch: unknown[] | null;\n /** Tool state */\n state: \"streaming\" | \"input-available\" | \"output-available\" | \"error\";\n /** Whether the tool is currently streaming input */\n isStreaming: boolean;\n /** Whether the write operation completed successfully */\n isCompleted: boolean;\n /** Whether there was an error */\n hasError: boolean;\n /** Error message if any */\n errorText: string | null;\n /** Whether this is a markdown file */\n isMarkdown: boolean;\n /** File extension */\n fileExtension: string | null;\n}\n\n/**\n * useWriteTool - Hook for handling Write tool interactions\n *\n * Parses the Write tool's input and output data, providing\n * easy access to file information and operation state.\n *\n * @example\n * ```tsx\n * import { useWriteTool } from \"@bunny-agent/sdk/react\";\n *\n * function WriteToolUI({ part }) {\n * const {\n * filePath,\n * fileName,\n * content,\n * operationType,\n * isStreaming,\n * isCompleted,\n * isMarkdown,\n * } = useWriteTool({ part });\n *\n * if (isStreaming) {\n * return <div>Writing {fileName}...</div>;\n * }\n *\n * return (\n * <div>\n * <h3>{fileName} ({operationType})</h3>\n * {isMarkdown ? (\n * <MarkdownRenderer content={content} />\n * ) : (\n * <pre>{content}</pre>\n * )}\n * </div>\n * );\n * }\n * ```\n */\nexport function useWriteTool({\n part,\n}: UseWriteToolOptions): UseWriteToolReturn {\n // Parse input data\n const inputData = useMemo((): WriteToolInput | null => {\n if (!part.input || typeof part.input !== \"object\") return null;\n const input = part.input as WriteToolInput;\n if (!input.file_path) return null;\n return input;\n }, [part.input]);\n\n // Parse output data\n const outputData = useMemo((): WriteToolOutput | null => {\n if (!part.output || typeof part.output !== \"object\") return null;\n const output = part.output as WriteToolOutput;\n if (!output.filePath) return null;\n return output;\n }, [part.output]);\n\n // Determine file path (prefer output, fallback to input)\n const filePath = outputData?.filePath ?? inputData?.file_path ?? null;\n\n // Extract file name\n const fileName = useMemo(() => {\n if (!filePath) return null;\n return filePath.split(\"/\").pop() || filePath;\n }, [filePath]);\n\n // Extract file extension\n const fileExtension = useMemo(() => {\n if (!fileName) return null;\n const parts = fileName.split(\".\");\n return parts.length > 1 ? parts.pop()?.toLowerCase() || null : null;\n }, [fileName]);\n\n // Determine content (prefer output, fallback to input)\n const content = outputData?.content ?? inputData?.content ?? null;\n\n // Operation type\n const operationType = outputData?.type ?? null;\n\n // Original content (for edits)\n const originalContent = outputData?.originalFile ?? null;\n\n // Structured patch\n const structuredPatch = outputData?.structuredPatch ?? null;\n\n // State parsing\n const state = useMemo((): UseWriteToolReturn[\"state\"] => {\n if (part.state === \"input-streaming\") return \"streaming\";\n if (part.state === \"output-error\") return \"error\";\n if (part.state === \"output-available\") return \"output-available\";\n return \"input-available\";\n }, [part.state]);\n\n const isStreaming = state === \"streaming\";\n const isCompleted = state === \"output-available\";\n const hasError = state === \"error\";\n const errorText = part.errorText ?? null;\n\n // Check if markdown\n const isMarkdown = useMemo(() => {\n if (!fileExtension) return false;\n return [\"md\", \"markdown\", \"mdx\"].includes(fileExtension);\n }, [fileExtension]);\n\n return {\n filePath,\n fileName,\n content,\n operationType,\n originalContent,\n structuredPatch,\n state,\n isStreaming,\n isCompleted,\n hasError,\n errorText,\n isMarkdown,\n fileExtension,\n };\n}\n"],"mappings":"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","names":["useCallback","useMemo","useState","useCallback","useEffect","useMemo","useRef","useState","useMemo"]}
1
+ {"version":3,"sources":["../../src/react/index.ts","../../src/react/useArtifacts.ts","../../src/react/useAskUserQuestion.ts","../../src/react/useBunnyAgentChat.ts","../../src/react/useWriteTool.ts"],"sourcesContent":["\"use client\";\n\nexport { DEFAULT_BUNNY_AGENT_DAEMON_URL } from \"@bunny-agent/manager\";\n\n// Types\nexport type {\n // Artifact types\n ArtifactData,\n AskUserQuestionInput,\n AskUserQuestionOutput,\n DynamicToolUIPart,\n // useAskUserQuestion types\n Question,\n QuestionOption,\n // AI SDK types\n UIMessage,\n // useArtifacts types\n UseArtifactsOptions,\n UseArtifactsReturn,\n UseAskUserQuestionOptions,\n UseAskUserQuestionReturn,\n // useBunnyAgentChat types\n UseBunnyAgentChatOptions,\n UseBunnyAgentChatReturn,\n UseWriteToolOptions,\n UseWriteToolReturn,\n // useWriteTool types\n WriteToolInput,\n WriteToolOutput,\n} from \"./types\";\nexport { useArtifacts } from \"./useArtifacts\";\nexport { useAskUserQuestion } from \"./useAskUserQuestion\";\n// Hooks\nexport { useBunnyAgentChat } from \"./useBunnyAgentChat\";\nexport { useWriteTool } from \"./useWriteTool\";\n","\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { ArtifactData, UIMessage } from \"./types\";\n\n/**\n * Options for useArtifacts hook\n */\nexport interface UseArtifactsOptions {\n /** Messages to extract artifacts from */\n messages: UIMessage[];\n}\n\n/**\n * Return type for useArtifacts hook\n */\nexport interface UseArtifactsReturn {\n /** All extracted artifacts */\n artifacts: ArtifactData[];\n /** Currently selected artifact */\n selectedArtifact: ArtifactData | null;\n /** Set the selected artifact */\n setSelectedArtifact: (artifact: ArtifactData | null) => void;\n /** Select artifact by ID */\n selectArtifactById: (artifactId: string) => void;\n /** Whether there are any artifacts */\n hasArtifacts: boolean;\n /** Number of artifacts */\n count: number;\n /** Copy artifact content to clipboard */\n copyContent: (artifact: ArtifactData) => Promise<void>;\n /** Download artifact as file */\n downloadArtifact: (artifact: ArtifactData) => void;\n /** Get file extension from mime type */\n getFileExtension: (mimeType: string) => string;\n}\n\n/**\n * Get file extension from MIME type\n */\nfunction getFileExtensionFromMimeType(mimeType: string): string {\n const mimeToExtension: Record<string, string> = {\n \"text/plain\": \"txt\",\n \"text/html\": \"html\",\n \"text/css\": \"css\",\n \"text/javascript\": \"js\",\n \"text/markdown\": \"md\",\n \"application/json\": \"json\",\n \"application/xml\": \"xml\",\n \"application/pdf\": \"pdf\",\n \"image/png\": \"png\",\n \"image/jpeg\": \"jpg\",\n \"image/gif\": \"gif\",\n \"image/svg+xml\": \"svg\",\n };\n\n // Try exact match\n if (mimeToExtension[mimeType]) {\n return mimeToExtension[mimeType];\n }\n\n // Try partial match (e.g., \"text/x-markdown\" -> \"md\")\n if (mimeType.includes(\"markdown\")) return \"md\";\n if (mimeType.includes(\"json\")) return \"json\";\n if (mimeType.includes(\"javascript\")) return \"js\";\n if (mimeType.includes(\"typescript\")) return \"ts\";\n if (mimeType.includes(\"html\")) return \"html\";\n if (mimeType.includes(\"css\")) return \"css\";\n if (mimeType.includes(\"xml\")) return \"xml\";\n if (mimeType.includes(\"python\")) return \"py\";\n\n // Default\n return \"txt\";\n}\n\n/**\n * useArtifacts - Hook for managing artifacts from chat messages\n *\n * Extracts artifacts from messages and provides selection,\n * copy, and download functionality.\n *\n * @example\n * ```tsx\n * import { useArtifacts } from \"@bunny-agent/sdk/react\";\n *\n * function ArtifactPanel({ messages }) {\n * const {\n * artifacts,\n * selectedArtifact,\n * setSelectedArtifact,\n * hasArtifacts,\n * copyContent,\n * downloadArtifact,\n * } = useArtifacts({ messages });\n *\n * if (!hasArtifacts) return null;\n *\n * return (\n * <div>\n * {artifacts.map((artifact) => (\n * <button\n * key={artifact.artifactId}\n * onClick={() => setSelectedArtifact(artifact)}\n * >\n * {artifact.artifactId}\n * </button>\n * ))}\n *\n * {selectedArtifact && (\n * <div>\n * <pre>{selectedArtifact.content}</pre>\n * <button onClick={() => copyContent(selectedArtifact)}>Copy</button>\n * <button onClick={() => downloadArtifact(selectedArtifact)}>Download</button>\n * </div>\n * )}\n * </div>\n * );\n * }\n * ```\n */\nexport function useArtifacts({\n messages,\n}: UseArtifactsOptions): UseArtifactsReturn {\n const [selectedArtifact, setSelectedArtifact] = useState<ArtifactData | null>(\n null,\n );\n\n // Extract artifacts from messages with memoization optimization\n const prevArtifactsRef = useRef<ArtifactData[]>([]);\n const artifacts = useMemo(() => {\n const results: ArtifactData[] = [];\n for (const message of messages) {\n for (const part of message.parts) {\n if (part.type === \"data-artifact\") {\n const data = part.data as ArtifactData;\n if (!results.some((a) => a.artifactId === data.artifactId)) {\n results.push(data);\n }\n }\n }\n }\n\n // Memoization optimization - return previous reference if content unchanged\n const prev = prevArtifactsRef.current;\n if (\n prev.length === results.length &&\n prev.every((prevArt, idx) => {\n const currArt = results[idx];\n return (\n prevArt.artifactId === currArt.artifactId &&\n prevArt.content === currArt.content &&\n prevArt.mimeType === currArt.mimeType\n );\n })\n ) {\n return prev;\n }\n\n prevArtifactsRef.current = results;\n return results;\n }, [messages]);\n\n // Sync selectedArtifact when artifacts change\n useEffect(() => {\n if (artifacts.length > 0) {\n setSelectedArtifact((prev) => {\n if (!prev) return artifacts[0];\n\n const currentMatch = artifacts.find(\n (a) => a.artifactId === prev.artifactId,\n );\n\n if (!currentMatch) {\n return artifacts[0];\n }\n\n if (\n currentMatch.content === prev.content &&\n currentMatch.mimeType === prev.mimeType\n ) {\n return prev;\n }\n\n return currentMatch;\n });\n } else {\n setSelectedArtifact((prev) => (prev === null ? prev : null));\n }\n }, [artifacts]);\n\n // Select artifact by ID\n const selectArtifactById = useCallback(\n (artifactId: string) => {\n const artifact = artifacts.find((a) => a.artifactId === artifactId);\n if (artifact) {\n setSelectedArtifact(artifact);\n }\n },\n [artifacts],\n );\n\n // Copy content to clipboard\n const copyContent = useCallback(async (artifact: ArtifactData) => {\n await navigator.clipboard.writeText(artifact.content);\n }, []);\n\n // Download artifact as file\n const downloadArtifact = useCallback((artifact: ArtifactData) => {\n const blob = new Blob([artifact.content], { type: artifact.mimeType });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n const fileName =\n artifact.artifactId.split(\"/\").pop() || artifact.artifactId;\n const extension = getFileExtensionFromMimeType(artifact.mimeType);\n a.download = fileName.includes(\".\") ? fileName : `${fileName}.${extension}`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n }, []);\n\n const hasArtifacts = artifacts.length > 0;\n const count = artifacts.length;\n\n return {\n artifacts,\n selectedArtifact,\n setSelectedArtifact,\n selectArtifactById,\n hasArtifacts,\n count,\n copyContent,\n downloadArtifact,\n getFileExtension: getFileExtensionFromMimeType,\n };\n}\n","\"use client\";\n\nimport { useCallback, useMemo, useState } from \"react\";\nimport type {\n AskUserQuestionInput,\n AskUserQuestionOutput,\n Question,\n UseAskUserQuestionOptions,\n UseAskUserQuestionReturn,\n} from \"./types\";\n\n/**\n * useAskUserQuestion - Hook for handling AskUserQuestion tool interactions\n *\n * Manages the state for user question/answer interactions in chat.\n * Provides answer selection, completion detection, and formatted output.\n *\n * @example\n * ```tsx\n * import { useAskUserQuestion } from \"@bunny-agent/sdk/react\";\n *\n * function QuestionUI({ part, sessionId }) {\n * const {\n * questions,\n * answers,\n * isCompleted,\n * selectAnswer,\n * isSelected,\n * } = useAskUserQuestion({\n * part,\n * onAnswer: (data) => {\n * fetch(\"/api/answer\", {\n * method: \"POST\",\n * body: JSON.stringify(data),\n * });\n * },\n * });\n *\n * if (isCompleted) {\n * return <div>Completed</div>;\n * }\n *\n * return (\n * <div>\n * {questions.map((q) => (\n * <div key={q.question}>\n * <p>{q.question}</p>\n * {q.options?.map((opt) => (\n * <button\n * key={opt.label}\n * onClick={() => selectAnswer(q.question, opt.label, q.multiSelect)}\n * style={{ fontWeight: isSelected(q.question, opt.label, q.multiSelect) ? 'bold' : 'normal' }}\n * >\n * {opt.label}\n * </button>\n * ))}\n * </div>\n * ))}\n * </div>\n * );\n * }\n * ```\n */\nexport function useAskUserQuestion({\n part,\n answerEndpoint = \"/api/answer\",\n extraBody,\n onAnswer,\n}: UseAskUserQuestionOptions): UseAskUserQuestionReturn {\n const [answers, setAnswers] = useState<Record<string, string | string[]>>({});\n\n // Parse questions from part.input\n const questions = useMemo((): Question[] => {\n if (!part.input || typeof part.input !== \"object\") return [];\n const input = part.input as AskUserQuestionInput;\n if (!input.questions || !Array.isArray(input.questions)) return [];\n return input.questions;\n }, [part.input]);\n\n // Parse answers from part.output (for restored sessions)\n const outputAnswers = useMemo((): Record<\n string,\n string | string[]\n > | null => {\n if (part.output && typeof part.output === \"object\") {\n const output = part.output as AskUserQuestionOutput;\n if (output.answers) {\n const hasRealAnswers = Object.values(output.answers).some(\n (v) => v && v.trim() !== \"\",\n );\n if (hasRealAnswers) {\n const parsed: Record<string, string | string[]> = {};\n for (const q of questions) {\n const val = output.answers[q.question];\n if (q.multiSelect && val) {\n parsed[q.question] = val.split(\", \").filter(Boolean);\n } else {\n parsed[q.question] = val || \"\";\n }\n }\n return parsed;\n }\n }\n }\n return null;\n }, [part.output, questions]);\n\n // Determine display answers (user input or restored from output)\n const displayAnswers = useMemo(() => {\n return Object.keys(answers).length > 0 ? answers : outputAnswers || {};\n }, [answers, outputAnswers]);\n\n // Check if completed\n const isCompleted = useMemo(() => {\n return (\n part.state === \"output-available\" ||\n (Object.keys(answers).length === 0 && outputAnswers !== null)\n );\n }, [part.state, answers, outputAnswers]);\n\n // Check if waiting for input (for animation)\n const isWaitingForInput = part.state === \"input-available\";\n\n // Get formatted answers map\n const getAnswersMap = useCallback((): Record<string, string> => {\n const answersMap: Record<string, string> = {};\n for (const q of questions) {\n const answer = displayAnswers[q.question];\n if (q.multiSelect) {\n answersMap[q.question] = Array.isArray(answer) ? answer.join(\", \") : \"\";\n } else {\n answersMap[q.question] = (answer as string) || \"\";\n }\n }\n return answersMap;\n }, [questions, displayAnswers]);\n\n // Select answer handler\n const selectAnswer = useCallback(\n (question: string, value: string, multiSelect = false) => {\n const newAnswers = { ...answers };\n\n if (multiSelect) {\n const current = (newAnswers[question] as string[]) || [];\n newAnswers[question] = current.includes(value)\n ? current.filter((v) => v !== value)\n : [...current, value];\n } else {\n newAnswers[question] = value;\n }\n\n setAnswers(newAnswers);\n\n // Prepare answers map for callback and API\n const answersMap: Record<string, string> = {};\n for (const q of questions) {\n const answer = newAnswers[q.question];\n if (q.multiSelect) {\n answersMap[q.question] = Array.isArray(answer)\n ? answer.join(\", \")\n : \"\";\n } else {\n answersMap[q.question] = (answer as string) || \"\";\n }\n }\n\n // Auto-submit to answer endpoint\n fetch(answerEndpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n toolCallId: part.toolCallId,\n questions,\n answers: answersMap,\n ...extraBody,\n }),\n }).catch((err) => {\n console.error(\"[useAskUserQuestion] Submit failed:\", err);\n });\n\n // Trigger callback\n onAnswer?.({\n toolCallId: part.toolCallId,\n questions,\n answers: answersMap,\n });\n },\n [answers, questions, part.toolCallId, answerEndpoint, extraBody, onAnswer],\n );\n\n // Check if option is selected\n const isSelected = useCallback(\n (question: string, optionLabel: string, multiSelect = false): boolean => {\n const selectedValue = displayAnswers[question];\n if (multiSelect) {\n return (\n (selectedValue as string[] | undefined)?.includes(optionLabel) ??\n false\n );\n }\n return selectedValue === optionLabel;\n },\n [displayAnswers],\n );\n\n return {\n questions,\n answers: displayAnswers,\n isCompleted,\n isWaitingForInput,\n selectAnswer,\n getAnswersMap,\n isSelected,\n };\n}\n","\"use client\";\n\nimport { useChat } from \"@ai-sdk/react\";\nimport { DefaultChatTransport, type UIMessage } from \"ai\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type {\n ArtifactData,\n UseBunnyAgentChatOptions,\n UseBunnyAgentChatReturn,\n} from \"./types\";\n\n/**\n * useBunnyAgentChat - Core hook for BunnyAgent chat functionality\n *\n * Provides all the logic needed for a chat interface:\n * - Message management\n * - Artifact extraction\n * - Session management\n *\n * @example\n * ```tsx\n * import { useBunnyAgentChat } from \"@bunny-agent/sdk/react\";\n *\n * const {\n * messages,\n * sendMessage,\n * status,\n * artifacts,\n * selectedArtifact,\n * setSelectedArtifact,\n * } = useBunnyAgentChat({\n * apiEndpoint: \"/api/ai\",\n * body: { template: \"default\" },\n * });\n * ```\n */\nexport function useBunnyAgentChat({\n apiEndpoint = \"/api/ai\",\n body = {},\n}: UseBunnyAgentChatOptions = {}): UseBunnyAgentChatReturn {\n // Artifact selection state\n const [selectedArtifact, setSelectedArtifact] = useState<ArtifactData | null>(\n null,\n );\n\n // Refs for accessing latest values in callbacks\n const bodyRef = useRef(body);\n const messagesRef = useRef<UIMessage[]>([]);\n\n // Keep transport body in sync on every render (not only after useEffect) so\n // the first fetch after hydration includes the latest client config.\n bodyRef.current = body;\n\n // Helper to extract resume value (sessionId) from message parts' providerMetadata.\n const getResumeFromMessage = (\n message: UIMessage | undefined,\n ): string | undefined => {\n if (!message?.parts) return undefined;\n for (const part of message.parts) {\n if (part.type === \"text\") {\n const providerMetadata = (\n part as {\n providerMetadata?: { \"bunny-agent\"?: { sessionId?: string } };\n }\n ).providerMetadata;\n if (providerMetadata?.[\"bunny-agent\"]?.sessionId) {\n return providerMetadata[\"bunny-agent\"].sessionId;\n }\n }\n }\n return undefined;\n };\n\n // Core chat hook\n const {\n messages,\n sendMessage: sendMessageInternal,\n status,\n error,\n stop,\n } = useChat({\n transport: new DefaultChatTransport({\n api: apiEndpoint,\n body: () => {\n const lastAssistantMessage = [...messagesRef.current]\n .reverse()\n .find((m) => m.role === \"assistant\");\n const resume = getResumeFromMessage(lastAssistantMessage);\n return {\n resume,\n ...bodyRef.current,\n };\n },\n }),\n });\n\n // Keep messagesRef in sync\n useEffect(() => {\n messagesRef.current = messages;\n }, [messages]);\n\n // Extract artifacts from messages\n const prevArtifactsRef = useRef<ArtifactData[]>([]);\n const artifacts = useMemo(() => {\n const results: ArtifactData[] = [];\n for (const message of messages) {\n for (const part of message.parts) {\n if (part.type === \"data-artifact\") {\n const data = part.data as ArtifactData;\n if (!results.some((a) => a.artifactId === data.artifactId)) {\n results.push(data);\n }\n }\n }\n }\n\n // Memoization optimization\n const prev = prevArtifactsRef.current;\n if (\n prev.length === results.length &&\n prev.every((prevArt, idx) => {\n const currArt = results[idx];\n return (\n prevArt.artifactId === currArt.artifactId &&\n prevArt.content === currArt.content &&\n prevArt.mimeType === currArt.mimeType\n );\n })\n ) {\n return prev;\n }\n\n prevArtifactsRef.current = results;\n return results;\n }, [messages]);\n\n // Sync selectedArtifact when artifacts change\n useEffect(() => {\n if (artifacts.length > 0) {\n setSelectedArtifact((prev) => {\n if (!prev) return artifacts[0];\n\n const currentMatch = artifacts.find(\n (a) => a.artifactId === prev.artifactId,\n );\n\n if (!currentMatch) {\n return artifacts[0];\n }\n\n if (\n currentMatch.content === prev.content &&\n currentMatch.mimeType === prev.mimeType\n ) {\n return prev;\n }\n\n return currentMatch;\n });\n } else {\n setSelectedArtifact((prev) => (prev === null ? prev : null));\n }\n }, [artifacts]);\n\n const isLoading = status === \"streaming\" || status === \"submitted\";\n const hasError = status === \"error\" && !!error;\n\n // Send message helper\n const sendMessage = useCallback(\n (text: string) => {\n if (!isLoading && text.trim()) {\n sendMessageInternal({\n role: \"user\",\n parts: [{ type: \"text\", text: text.trim() }],\n });\n }\n },\n [isLoading, sendMessageInternal],\n );\n\n // Handle submit for PromptInput compatibility\n const handleSubmit = useCallback(\n (message: { text: string; files?: import(\"ai\").FileUIPart[] }) => {\n if (!isLoading) {\n const parts: import(\"ai\").UIMessage[\"parts\"] = [];\n if (message.text) {\n parts.push({ type: \"text\", text: message.text.trim() });\n }\n if (message.files && message.files.length > 0) {\n for (const file of message.files) {\n parts.push(file);\n }\n }\n if (parts.length > 0) {\n sendMessageInternal({\n role: \"user\",\n parts,\n });\n } else {\n sendMessageInternal();\n }\n }\n },\n [isLoading, sendMessageInternal],\n );\n\n return {\n messages,\n status,\n error,\n isLoading,\n hasError,\n artifacts,\n selectedArtifact,\n setSelectedArtifact,\n sendMessage,\n stop,\n handleSubmit,\n };\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport type { DynamicToolUIPart } from \"./types\";\n\n/**\n * Write tool input structure\n */\nexport interface WriteToolInput {\n file_path: string;\n content: string;\n}\n\n/**\n * Write tool output structure\n */\nexport interface WriteToolOutput {\n type: \"create\" | \"edit\";\n filePath: string;\n content: string;\n structuredPatch?: unknown[];\n originalFile?: string | null;\n}\n\n/**\n * Options for useWriteTool hook\n */\nexport interface UseWriteToolOptions {\n /** The dynamic tool UI part from the message */\n part: DynamicToolUIPart;\n}\n\n/**\n * Return type for useWriteTool hook\n */\nexport interface UseWriteToolReturn {\n /** File path being written to */\n filePath: string | null;\n /** File name (extracted from path) */\n fileName: string | null;\n /** File content */\n content: string | null;\n /** Operation type: 'create' or 'edit' */\n operationType: \"create\" | \"edit\" | null;\n /** Original file content (for edit operations) */\n originalContent: string | null;\n /** Structured patch data (for edit operations) */\n structuredPatch: unknown[] | null;\n /** Tool state */\n state: \"streaming\" | \"input-available\" | \"output-available\" | \"error\";\n /** Whether the tool is currently streaming input */\n isStreaming: boolean;\n /** Whether the write operation completed successfully */\n isCompleted: boolean;\n /** Whether there was an error */\n hasError: boolean;\n /** Error message if any */\n errorText: string | null;\n /** Whether this is a markdown file */\n isMarkdown: boolean;\n /** File extension */\n fileExtension: string | null;\n}\n\n/**\n * useWriteTool - Hook for handling Write tool interactions\n *\n * Parses the Write tool's input and output data, providing\n * easy access to file information and operation state.\n *\n * @example\n * ```tsx\n * import { useWriteTool } from \"@bunny-agent/sdk/react\";\n *\n * function WriteToolUI({ part }) {\n * const {\n * filePath,\n * fileName,\n * content,\n * operationType,\n * isStreaming,\n * isCompleted,\n * isMarkdown,\n * } = useWriteTool({ part });\n *\n * if (isStreaming) {\n * return <div>Writing {fileName}...</div>;\n * }\n *\n * return (\n * <div>\n * <h3>{fileName} ({operationType})</h3>\n * {isMarkdown ? (\n * <MarkdownRenderer content={content} />\n * ) : (\n * <pre>{content}</pre>\n * )}\n * </div>\n * );\n * }\n * ```\n */\nexport function useWriteTool({\n part,\n}: UseWriteToolOptions): UseWriteToolReturn {\n // Parse input data\n const inputData = useMemo((): WriteToolInput | null => {\n if (!part.input || typeof part.input !== \"object\") return null;\n const input = part.input as WriteToolInput;\n if (!input.file_path) return null;\n return input;\n }, [part.input]);\n\n // Parse output data\n const outputData = useMemo((): WriteToolOutput | null => {\n if (!part.output || typeof part.output !== \"object\") return null;\n const output = part.output as WriteToolOutput;\n if (!output.filePath) return null;\n return output;\n }, [part.output]);\n\n // Determine file path (prefer output, fallback to input)\n const filePath = outputData?.filePath ?? inputData?.file_path ?? null;\n\n // Extract file name\n const fileName = useMemo(() => {\n if (!filePath) return null;\n return filePath.split(\"/\").pop() || filePath;\n }, [filePath]);\n\n // Extract file extension\n const fileExtension = useMemo(() => {\n if (!fileName) return null;\n const parts = fileName.split(\".\");\n return parts.length > 1 ? parts.pop()?.toLowerCase() || null : null;\n }, [fileName]);\n\n // Determine content (prefer output, fallback to input)\n const content = outputData?.content ?? inputData?.content ?? null;\n\n // Operation type\n const operationType = outputData?.type ?? null;\n\n // Original content (for edits)\n const originalContent = outputData?.originalFile ?? null;\n\n // Structured patch\n const structuredPatch = outputData?.structuredPatch ?? null;\n\n // State parsing\n const state = useMemo((): UseWriteToolReturn[\"state\"] => {\n if (part.state === \"input-streaming\") return \"streaming\";\n if (part.state === \"output-error\") return \"error\";\n if (part.state === \"output-available\") return \"output-available\";\n return \"input-available\";\n }, [part.state]);\n\n const isStreaming = state === \"streaming\";\n const isCompleted = state === \"output-available\";\n const hasError = state === \"error\";\n const errorText = part.errorText ?? null;\n\n // Check if markdown\n const isMarkdown = useMemo(() => {\n if (!fileExtension) return false;\n return [\"md\", \"markdown\", \"mdx\"].includes(fileExtension);\n }, [fileExtension]);\n\n return {\n filePath,\n fileName,\n content,\n operationType,\n originalContent,\n structuredPatch,\n state,\n isStreaming,\n isCompleted,\n hasError,\n errorText,\n isMarkdown,\n fileExtension,\n };\n}\n"],"mappings":"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","names":["useCallback","useMemo","useState","useCallback","useEffect","useMemo","useRef","useState","useMemo"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bunny-agent/sdk",
3
- "version": "0.9.59-beta.3",
3
+ "version": "0.9.59-beta.5",
4
4
  "description": "BunnyAgent SDK - AI Provider and React hooks for building AI agents",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -52,9 +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.59-beta.3",
56
- "@bunny-agent/sandbox-local": "0.9.59-beta.3",
57
- "@bunny-agent/sandbox-srt": "0.9.59-beta.3"
55
+ "@bunny-agent/sandbox-srt": "0.9.59-beta.5",
56
+ "@bunny-agent/sandbox-local": "0.9.59-beta.5",
57
+ "@bunny-agent/manager": "0.9.59-beta.5"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@types/node": "^20.10.0",