@directive-run/ai 1.11.0 → 1.13.0

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.
@@ -1,3 +1,3 @@
1
- 'use strict';var chunkKP3G32S7_cjs=require('./chunk-KP3G32S7.cjs'),chunkW6MVJKWN_cjs=require('./chunk-W6MVJKWN.cjs');var K={"claude-sonnet-4-5-20250929":{input:3,output:15},"claude-sonnet-4-20250514":{input:3,output:15},"claude-haiku-4-5-20250514":{input:.8,output:4},"claude-haiku-3-5-20241022":{input:.8,output:4},"claude-opus-4-20250514":{input:15,output:75}};function L(h){let{apiKey:i,model:k="claude-sonnet-4-5-20250929",maxTokens:d=4096,baseURL:u="https://api.anthropic.com/v1",fetch:f=globalThis.fetch,timeoutMs:r,hooks:m,temperature:p,topP:c,stopSequences:o}=h;return chunkW6MVJKWN_cjs.d(u),chunkKP3G32S7_cjs.c(i,"createAnthropicRunner"),chunkW6MVJKWN_cjs.e({fetch:f,hooks:m,buildRequest:(n,s,a)=>({url:`${u}/messages`,init:{method:"POST",headers:{"Content-Type":"application/json","x-api-key":i,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:n.model??k,max_tokens:d,...p!=null?{temperature:p}:{},...c!=null?{top_p:c}:{},...o!=null?{stop_sequences:o}:{},system:n.instructions??"",messages:a.map(e=>({role:e.role,content:e.content}))}),...r!=null?{signal:AbortSignal.timeout(r)}:{}}}),parseResponse:async n=>{let s=await n.json(),a=s.content?.[0]?.text??"",e=s.usage?.input_tokens??0,l=s.usage?.output_tokens??0;return {text:a,totalTokens:e+l,inputTokens:e,outputTokens:l}}})}function N(h){let{apiKey:i,model:k="claude-sonnet-4-5-20250929",maxTokens:d=4096,baseURL:u="https://api.anthropic.com/v1",fetch:f=globalThis.fetch,hooks:r,temperature:m,topP:p,stopSequences:c}=h;return chunkW6MVJKWN_cjs.d(u),chunkKP3G32S7_cjs.c(i,"createAnthropicStreamingRunner"),async(o,n,s)=>{let a=chunkKP3G32S7_cjs.e(r,o,n);try{let e=await f(`${u}/messages`,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":i,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:o.model??k,max_tokens:d,...m!=null?{temperature:m}:{},...p!=null?{top_p:p}:{},...c!=null?{stop_sequences:c}:{},system:o.instructions??"",messages:[{role:"user",content:n}],stream:!0}),signal:s.signal});e.ok||await chunkKP3G32S7_cjs.a(e,"Anthropic");let l=chunkKP3G32S7_cjs.b(e),{fullText:R,inputTokens:b,outputTokens:S}=await chunkKP3G32S7_cjs.d(l,s.onToken,t=>{if(t.type==="error")throw new Error(`[Directive] Anthropic stream error: ${t.error?.message??JSON.stringify(t.error)}`);let g={};return t.type==="content_block_delta"&&t.delta?.type==="text_delta"&&(g.text=t.delta.text),t.type==="message_delta"&&t.usage&&(g.outputTokens=t.usage.output_tokens??0),t.type==="message_start"&&t.message?.usage&&(g.inputTokens=t.message.usage.input_tokens??0),g},"Anthropic"),x={inputTokens:b,outputTokens:S},A=b+S;return s.onMessage?.({role:"assistant",content:R}),chunkKP3G32S7_cjs.f(r,o,n,R,A,x,a),chunkKP3G32S7_cjs.h(n,R,A,x)}catch(e){throw chunkKP3G32S7_cjs.g(r,o,n,e,a),e}}}
1
+ 'use strict';var chunkKP3G32S7_cjs=require('./chunk-KP3G32S7.cjs'),chunk3WO4MWJM_cjs=require('./chunk-3WO4MWJM.cjs');var K={"claude-sonnet-4-5-20250929":{input:3,output:15},"claude-sonnet-4-20250514":{input:3,output:15},"claude-haiku-4-5-20250514":{input:.8,output:4},"claude-haiku-3-5-20241022":{input:.8,output:4},"claude-opus-4-20250514":{input:15,output:75}};function L(h){let{apiKey:i,model:k="claude-sonnet-4-5-20250929",maxTokens:d=4096,baseURL:u="https://api.anthropic.com/v1",fetch:f=globalThis.fetch,timeoutMs:r,hooks:m,temperature:p,topP:c,stopSequences:o}=h;return chunk3WO4MWJM_cjs.d(u),chunkKP3G32S7_cjs.c(i,"createAnthropicRunner"),chunk3WO4MWJM_cjs.f({fetch:f,hooks:m,buildRequest:(n,s,a)=>({url:`${u}/messages`,init:{method:"POST",headers:{"Content-Type":"application/json","x-api-key":i,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:n.model??k,max_tokens:d,...p!=null?{temperature:p}:{},...c!=null?{top_p:c}:{},...o!=null?{stop_sequences:o}:{},system:n.instructions??"",messages:a.map(e=>({role:e.role,content:e.content}))}),...r!=null?{signal:AbortSignal.timeout(r)}:{}}}),parseResponse:async n=>{let s=await n.json(),a=s.content?.[0]?.text??"",e=s.usage?.input_tokens??0,l=s.usage?.output_tokens??0;return {text:a,totalTokens:e+l,inputTokens:e,outputTokens:l}}})}function N(h){let{apiKey:i,model:k="claude-sonnet-4-5-20250929",maxTokens:d=4096,baseURL:u="https://api.anthropic.com/v1",fetch:f=globalThis.fetch,hooks:r,temperature:m,topP:p,stopSequences:c}=h;return chunk3WO4MWJM_cjs.d(u),chunkKP3G32S7_cjs.c(i,"createAnthropicStreamingRunner"),async(o,n,s)=>{let a=chunkKP3G32S7_cjs.e(r,o,n);try{let e=await f(`${u}/messages`,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":i,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:o.model??k,max_tokens:d,...m!=null?{temperature:m}:{},...p!=null?{top_p:p}:{},...c!=null?{stop_sequences:c}:{},system:o.instructions??"",messages:[{role:"user",content:n}],stream:!0}),signal:s.signal});e.ok||await chunkKP3G32S7_cjs.a(e,"Anthropic");let l=chunkKP3G32S7_cjs.b(e),{fullText:R,inputTokens:b,outputTokens:S}=await chunkKP3G32S7_cjs.d(l,s.onToken,t=>{if(t.type==="error")throw new Error(`[Directive] Anthropic stream error: ${t.error?.message??JSON.stringify(t.error)}`);let g={};return t.type==="content_block_delta"&&t.delta?.type==="text_delta"&&(g.text=t.delta.text),t.type==="message_delta"&&t.usage&&(g.outputTokens=t.usage.output_tokens??0),t.type==="message_start"&&t.message?.usage&&(g.inputTokens=t.message.usage.input_tokens??0),g},"Anthropic"),x={inputTokens:b,outputTokens:S},A=b+S;return s.onMessage?.({role:"assistant",content:R}),chunkKP3G32S7_cjs.f(r,o,n,R,A,x,a),chunkKP3G32S7_cjs.h(n,R,A,x)}catch(e){throw chunkKP3G32S7_cjs.g(r,o,n,e,a),e}}}
2
2
  exports.ANTHROPIC_PRICING=K;exports.createAnthropicRunner=L;exports.createAnthropicStreamingRunner=N;//# sourceMappingURL=anthropic.cjs.map
3
3
  //# sourceMappingURL=anthropic.cjs.map
package/dist/anthropic.js CHANGED
@@ -1,3 +1,3 @@
1
- import {c,e as e$1,a,b,d as d$1,f,h,g}from'./chunk-3PGRBK4E.js';import {d,e}from'./chunk-W6WZBQER.js';var K={"claude-sonnet-4-5-20250929":{input:3,output:15},"claude-sonnet-4-20250514":{input:3,output:15},"claude-haiku-4-5-20250514":{input:.8,output:4},"claude-haiku-3-5-20241022":{input:.8,output:4},"claude-opus-4-20250514":{input:15,output:75}};function L(h){let{apiKey:i,model:k="claude-sonnet-4-5-20250929",maxTokens:d$1=4096,baseURL:u="https://api.anthropic.com/v1",fetch:f=globalThis.fetch,timeoutMs:r,hooks:m,temperature:p,topP:c$1,stopSequences:o}=h;return d(u),c(i,"createAnthropicRunner"),e({fetch:f,hooks:m,buildRequest:(n,s,a)=>({url:`${u}/messages`,init:{method:"POST",headers:{"Content-Type":"application/json","x-api-key":i,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:n.model??k,max_tokens:d$1,...p!=null?{temperature:p}:{},...c$1!=null?{top_p:c$1}:{},...o!=null?{stop_sequences:o}:{},system:n.instructions??"",messages:a.map(e=>({role:e.role,content:e.content}))}),...r!=null?{signal:AbortSignal.timeout(r)}:{}}}),parseResponse:async n=>{let s=await n.json(),a=s.content?.[0]?.text??"",e=s.usage?.input_tokens??0,l=s.usage?.output_tokens??0;return {text:a,totalTokens:e+l,inputTokens:e,outputTokens:l}}})}function N(h$1){let{apiKey:i,model:k="claude-sonnet-4-5-20250929",maxTokens:d$2=4096,baseURL:u="https://api.anthropic.com/v1",fetch:f$1=globalThis.fetch,hooks:r,temperature:m,topP:p,stopSequences:c$1}=h$1;return d(u),c(i,"createAnthropicStreamingRunner"),async(o,n,s)=>{let a$1=e$1(r,o,n);try{let e=await f$1(`${u}/messages`,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":i,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:o.model??k,max_tokens:d$2,...m!=null?{temperature:m}:{},...p!=null?{top_p:p}:{},...c$1!=null?{stop_sequences:c$1}:{},system:o.instructions??"",messages:[{role:"user",content:n}],stream:!0}),signal:s.signal});e.ok||await a(e,"Anthropic");let l=b(e),{fullText:R,inputTokens:b$1,outputTokens:S}=await d$1(l,s.onToken,t=>{if(t.type==="error")throw new Error(`[Directive] Anthropic stream error: ${t.error?.message??JSON.stringify(t.error)}`);let g={};return t.type==="content_block_delta"&&t.delta?.type==="text_delta"&&(g.text=t.delta.text),t.type==="message_delta"&&t.usage&&(g.outputTokens=t.usage.output_tokens??0),t.type==="message_start"&&t.message?.usage&&(g.inputTokens=t.message.usage.input_tokens??0),g},"Anthropic"),x={inputTokens:b$1,outputTokens:S},A=b$1+S;return s.onMessage?.({role:"assistant",content:R}),f(r,o,n,R,A,x,a$1),h(n,R,A,x)}catch(e){throw g(r,o,n,e,a$1),e}}}
1
+ import {c,e,a,b,d as d$1,f as f$1,h,g}from'./chunk-3PGRBK4E.js';import {d,f}from'./chunk-ZFLHWJ56.js';var K={"claude-sonnet-4-5-20250929":{input:3,output:15},"claude-sonnet-4-20250514":{input:3,output:15},"claude-haiku-4-5-20250514":{input:.8,output:4},"claude-haiku-3-5-20241022":{input:.8,output:4},"claude-opus-4-20250514":{input:15,output:75}};function L(h){let{apiKey:i,model:k="claude-sonnet-4-5-20250929",maxTokens:d$1=4096,baseURL:u="https://api.anthropic.com/v1",fetch:f$1=globalThis.fetch,timeoutMs:r,hooks:m,temperature:p,topP:c$1,stopSequences:o}=h;return d(u),c(i,"createAnthropicRunner"),f({fetch:f$1,hooks:m,buildRequest:(n,s,a)=>({url:`${u}/messages`,init:{method:"POST",headers:{"Content-Type":"application/json","x-api-key":i,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:n.model??k,max_tokens:d$1,...p!=null?{temperature:p}:{},...c$1!=null?{top_p:c$1}:{},...o!=null?{stop_sequences:o}:{},system:n.instructions??"",messages:a.map(e=>({role:e.role,content:e.content}))}),...r!=null?{signal:AbortSignal.timeout(r)}:{}}}),parseResponse:async n=>{let s=await n.json(),a=s.content?.[0]?.text??"",e=s.usage?.input_tokens??0,l=s.usage?.output_tokens??0;return {text:a,totalTokens:e+l,inputTokens:e,outputTokens:l}}})}function N(h$1){let{apiKey:i,model:k="claude-sonnet-4-5-20250929",maxTokens:d$2=4096,baseURL:u="https://api.anthropic.com/v1",fetch:f=globalThis.fetch,hooks:r,temperature:m,topP:p,stopSequences:c$1}=h$1;return d(u),c(i,"createAnthropicStreamingRunner"),async(o,n,s)=>{let a$1=e(r,o,n);try{let e=await f(`${u}/messages`,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":i,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:o.model??k,max_tokens:d$2,...m!=null?{temperature:m}:{},...p!=null?{top_p:p}:{},...c$1!=null?{stop_sequences:c$1}:{},system:o.instructions??"",messages:[{role:"user",content:n}],stream:!0}),signal:s.signal});e.ok||await a(e,"Anthropic");let l=b(e),{fullText:R,inputTokens:b$1,outputTokens:S}=await d$1(l,s.onToken,t=>{if(t.type==="error")throw new Error(`[Directive] Anthropic stream error: ${t.error?.message??JSON.stringify(t.error)}`);let g={};return t.type==="content_block_delta"&&t.delta?.type==="text_delta"&&(g.text=t.delta.text),t.type==="message_delta"&&t.usage&&(g.outputTokens=t.usage.output_tokens??0),t.type==="message_start"&&t.message?.usage&&(g.inputTokens=t.message.usage.input_tokens??0),g},"Anthropic"),x={inputTokens:b$1,outputTokens:S},A=b$1+S;return s.onMessage?.({role:"assistant",content:R}),f$1(r,o,n,R,A,x,a$1),h(n,R,A,x)}catch(e){throw g(r,o,n,e,a$1),e}}}
2
2
  export{K as ANTHROPIC_PRICING,L as createAnthropicRunner,N as createAnthropicStreamingRunner};//# sourceMappingURL=anthropic.js.map
3
3
  //# sourceMappingURL=anthropic.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/adapters/anthropic.ts"],"names":["ANTHROPIC_PRICING","createAnthropicRunner","options","apiKey","model","maxTokens","baseURL","fetchFn","timeoutMs","hooks","temperature","topP","stopSequences","validateBaseURL","warnIfMissingApiKey","createRunner","agent","_input","messages","m","res","data","text","inputTokens","outputTokens","createAnthropicStreamingRunner","input","callbacks","startTime","fireBeforeCallHook","response","throwStreamingHTTPError","reader","getSSEReader","fullText","parseSSEStream","event","result","tokenUsage","totalTokens","fireAfterCallHook","buildStreamingResult","err","fireErrorHook"],"mappings":"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","file":"anthropic.js","sourcesContent":["/**\n * @directive-run/ai/anthropic\n *\n * Anthropic adapter for Directive AI. Provides runners for the\n * Anthropic Messages API, including streaming support.\n *\n * @example\n * ```typescript\n * import { createAnthropicRunner, createAnthropicStreamingRunner } from '@directive-run/ai/anthropic';\n *\n * const runner = createAnthropicRunner({ apiKey: process.env.ANTHROPIC_API_KEY! });\n * ```\n */\n\nimport { createRunner, validateBaseURL } from \"../agent-utils.js\";\nimport type { AdapterHooks, AgentRunner } from \"../types.js\";\nimport type { StreamingCallbackRunner } from \"../types.js\";\nimport {\n buildStreamingResult,\n fireAfterCallHook,\n fireBeforeCallHook,\n fireErrorHook,\n getSSEReader,\n parseSSEStream,\n throwStreamingHTTPError,\n warnIfMissingApiKey,\n} from \"./shared.js\";\n\n// ============================================================================\n// Pricing Constants\n// ============================================================================\n\n/**\n * Anthropic model pricing (USD per million tokens).\n *\n * Use with `estimateCost()` for per-call cost tracking:\n * ```typescript\n * import { estimateCost } from '@directive-run/ai';\n * import { ANTHROPIC_PRICING } from '@directive-run/ai/anthropic';\n *\n * const cost =\n * estimateCost(result.tokenUsage!.inputTokens, ANTHROPIC_PRICING[\"claude-sonnet-4-5-20250929\"].input) +\n * estimateCost(result.tokenUsage!.outputTokens, ANTHROPIC_PRICING[\"claude-sonnet-4-5-20250929\"].output);\n * ```\n *\n * **Note:** Pricing changes over time. These values are provided as a convenience\n * and may not reflect the latest rates. Always verify at https://anthropic.com/pricing\n */\nexport const ANTHROPIC_PRICING: Record<\n string,\n { input: number; output: number }\n> = {\n \"claude-sonnet-4-5-20250929\": { input: 3, output: 15 },\n \"claude-sonnet-4-20250514\": { input: 3, output: 15 },\n \"claude-haiku-4-5-20250514\": { input: 0.8, output: 4 },\n \"claude-haiku-3-5-20241022\": { input: 0.8, output: 4 },\n \"claude-opus-4-20250514\": { input: 15, output: 75 },\n};\n\n// ============================================================================\n// Anthropic Runner\n// ============================================================================\n\n/** Options for createAnthropicRunner */\nexport interface AnthropicRunnerOptions {\n apiKey: string;\n model?: string;\n /** @default 4096 */\n maxTokens?: number;\n baseURL?: string;\n fetch?: typeof globalThis.fetch;\n /** @default undefined */\n timeoutMs?: number;\n /** Lifecycle hooks for tracing, logging, and metrics */\n hooks?: AdapterHooks;\n /** Sampling temperature (0–1). Higher = more random. */\n temperature?: number;\n /** Nucleus sampling: top-P probability mass (0–1). */\n topP?: number;\n /** Custom stop sequences. The model will stop generating when it encounters one. */\n stopSequences?: string[];\n}\n\n/**\n * Create an AgentRunner for the Anthropic Messages API.\n *\n * Returns `tokenUsage` with input/output breakdown for cost tracking.\n *\n * @example\n * ```typescript\n * const runner = createAnthropicRunner({\n * apiKey: process.env.ANTHROPIC_API_KEY!,\n * hooks: {\n * onAfterCall: ({ durationMs, tokenUsage }) => {\n * console.log(`${durationMs}ms – ${tokenUsage.inputTokens}in/${tokenUsage.outputTokens}out`);\n * },\n * },\n * });\n * const orchestrator = createAgentOrchestrator({ runner });\n * const result = await orchestrator.run(agent, input);\n * ```\n */\nexport function createAnthropicRunner(\n options: AnthropicRunnerOptions,\n): AgentRunner {\n const {\n apiKey,\n model = \"claude-sonnet-4-5-20250929\",\n maxTokens = 4096,\n baseURL = \"https://api.anthropic.com/v1\",\n fetch: fetchFn = globalThis.fetch,\n timeoutMs,\n hooks,\n temperature,\n topP,\n stopSequences,\n } = options;\n\n validateBaseURL(baseURL);\n warnIfMissingApiKey(apiKey, \"createAnthropicRunner\");\n\n return createRunner({\n fetch: fetchFn,\n hooks,\n buildRequest: (agent, _input, messages) => ({\n url: `${baseURL}/messages`,\n init: {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": apiKey,\n \"anthropic-version\": \"2023-06-01\",\n },\n body: JSON.stringify({\n model: agent.model ?? model,\n max_tokens: maxTokens,\n ...(temperature != null ? { temperature } : {}),\n ...(topP != null ? { top_p: topP } : {}),\n ...(stopSequences != null ? { stop_sequences: stopSequences } : {}),\n system: agent.instructions ?? \"\",\n messages: messages.map((m) => ({\n role: m.role,\n content: m.content,\n })),\n }),\n ...(timeoutMs != null\n ? { signal: AbortSignal.timeout(timeoutMs) }\n : {}),\n },\n }),\n parseResponse: async (res) => {\n const data = await res.json();\n const text = data.content?.[0]?.text ?? \"\";\n const inputTokens = data.usage?.input_tokens ?? 0;\n const outputTokens = data.usage?.output_tokens ?? 0;\n\n return {\n text,\n totalTokens: inputTokens + outputTokens,\n inputTokens,\n outputTokens,\n };\n },\n });\n}\n\n// ============================================================================\n// Anthropic Streaming Runner\n// ============================================================================\n\n/** Options for createAnthropicStreamingRunner */\nexport interface AnthropicStreamingRunnerOptions {\n apiKey: string;\n model?: string;\n /** @default 4096 */\n maxTokens?: number;\n baseURL?: string;\n fetch?: typeof globalThis.fetch;\n /** Lifecycle hooks for tracing, logging, and metrics */\n hooks?: AdapterHooks;\n /** Sampling temperature (0–1). Higher = more random. */\n temperature?: number;\n /** Nucleus sampling: top-P probability mass (0–1). */\n topP?: number;\n /** Custom stop sequences. The model will stop generating when it encounters one. */\n stopSequences?: string[];\n}\n\n/**\n * Create a StreamingCallbackRunner for the Anthropic Messages API with\n * server-sent events. Can be used standalone or paired with `createAnthropicRunner`.\n *\n * Returns `tokenUsage` with input/output breakdown for cost tracking.\n *\n * @example\n * ```typescript\n * const streamingRunner = createAnthropicStreamingRunner({\n * apiKey: process.env.ANTHROPIC_API_KEY!,\n * });\n * const streamRunner = createStreamingRunner(streamingRunner);\n * const { stream, result } = streamRunner(agent, input);\n * ```\n */\nexport function createAnthropicStreamingRunner(\n options: AnthropicStreamingRunnerOptions,\n): StreamingCallbackRunner {\n const {\n apiKey,\n model = \"claude-sonnet-4-5-20250929\",\n maxTokens = 4096,\n baseURL = \"https://api.anthropic.com/v1\",\n fetch: fetchFn = globalThis.fetch,\n hooks,\n temperature,\n topP,\n stopSequences,\n } = options;\n\n validateBaseURL(baseURL);\n warnIfMissingApiKey(apiKey, \"createAnthropicStreamingRunner\");\n\n return async (agent, input, callbacks) => {\n const startTime = fireBeforeCallHook(hooks, agent, input);\n\n try {\n const response = await fetchFn(`${baseURL}/messages`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": apiKey,\n \"anthropic-version\": \"2023-06-01\",\n },\n body: JSON.stringify({\n model: agent.model ?? model,\n max_tokens: maxTokens,\n ...(temperature != null ? { temperature } : {}),\n ...(topP != null ? { top_p: topP } : {}),\n ...(stopSequences != null ? { stop_sequences: stopSequences } : {}),\n system: agent.instructions ?? \"\",\n messages: [{ role: \"user\", content: input }],\n stream: true,\n }),\n signal: callbacks.signal,\n });\n\n if (!response.ok) {\n await throwStreamingHTTPError(response, \"Anthropic\");\n }\n\n const reader = getSSEReader(response);\n\n const { fullText, inputTokens, outputTokens } = await parseSSEStream(\n reader,\n callbacks.onToken,\n (event) => {\n if (event.type === \"error\") {\n throw new Error(\n `[Directive] Anthropic stream error: ${(event.error as Record<string, unknown>)?.message ?? JSON.stringify(event.error)}`,\n );\n }\n\n const result: {\n text?: string;\n inputTokens?: number;\n outputTokens?: number;\n } = {};\n if (\n event.type === \"content_block_delta\" &&\n (event.delta as Record<string, unknown>)?.type === \"text_delta\"\n ) {\n result.text = (event.delta as Record<string, unknown>)\n .text as string;\n }\n if (event.type === \"message_delta\" && event.usage) {\n result.outputTokens =\n ((event.usage as Record<string, unknown>)\n .output_tokens as number) ?? 0;\n }\n if (\n event.type === \"message_start\" &&\n (event.message as Record<string, unknown>)?.usage\n ) {\n result.inputTokens =\n ((\n (event.message as Record<string, unknown>).usage as Record<\n string,\n unknown\n >\n ).input_tokens as number) ?? 0;\n }\n\n return result;\n },\n \"Anthropic\",\n );\n\n const tokenUsage = { inputTokens, outputTokens };\n const totalTokens = inputTokens + outputTokens;\n\n callbacks.onMessage?.({ role: \"assistant\", content: fullText });\n fireAfterCallHook(\n hooks,\n agent,\n input,\n fullText,\n totalTokens,\n tokenUsage,\n startTime,\n );\n\n return buildStreamingResult(input, fullText, totalTokens, tokenUsage);\n } catch (err) {\n fireErrorHook(hooks, agent, input, err, startTime);\n\n throw err;\n }\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/adapters/anthropic.ts"],"names":["ANTHROPIC_PRICING","createAnthropicRunner","options","apiKey","model","maxTokens","baseURL","fetchFn","timeoutMs","hooks","temperature","topP","stopSequences","validateBaseURL","warnIfMissingApiKey","createRunner","agent","_input","messages","m","res","data","text","inputTokens","outputTokens","createAnthropicStreamingRunner","input","callbacks","startTime","fireBeforeCallHook","response","throwStreamingHTTPError","reader","getSSEReader","fullText","parseSSEStream","event","result","tokenUsage","totalTokens","fireAfterCallHook","buildStreamingResult","err","fireErrorHook"],"mappings":"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","file":"anthropic.js","sourcesContent":["/**\n * @directive-run/ai/anthropic\n *\n * Anthropic adapter for Directive AI. Provides runners for the\n * Anthropic Messages API, including streaming support.\n *\n * @example\n * ```typescript\n * import { createAnthropicRunner, createAnthropicStreamingRunner } from '@directive-run/ai/anthropic';\n *\n * const runner = createAnthropicRunner({ apiKey: process.env.ANTHROPIC_API_KEY! });\n * ```\n */\n\nimport { createRunner, validateBaseURL } from \"../agent-utils.js\";\nimport type { AdapterHooks, AgentRunner } from \"../types.js\";\nimport type { StreamingCallbackRunner } from \"../types.js\";\nimport {\n buildStreamingResult,\n fireAfterCallHook,\n fireBeforeCallHook,\n fireErrorHook,\n getSSEReader,\n parseSSEStream,\n throwStreamingHTTPError,\n warnIfMissingApiKey,\n} from \"./shared.js\";\n\n// ============================================================================\n// Pricing Constants\n// ============================================================================\n\n/**\n * Anthropic model pricing (USD per million tokens).\n *\n * Use with `estimateCost()` for per-call cost tracking:\n * ```typescript\n * import { estimateCost } from '@directive-run/ai';\n * import { ANTHROPIC_PRICING } from '@directive-run/ai/anthropic';\n *\n * const cost =\n * estimateCost(result.tokenUsage!.inputTokens, ANTHROPIC_PRICING[\"claude-sonnet-4-5-20250929\"].input) +\n * estimateCost(result.tokenUsage!.outputTokens, ANTHROPIC_PRICING[\"claude-sonnet-4-5-20250929\"].output);\n * ```\n *\n * **Note:** Pricing changes over time. These values are provided as a convenience\n * and may not reflect the latest rates. Always verify at https://anthropic.com/pricing\n */\nexport const ANTHROPIC_PRICING: Record<\n string,\n { input: number; output: number }\n> = {\n \"claude-sonnet-4-5-20250929\": { input: 3, output: 15 },\n \"claude-sonnet-4-20250514\": { input: 3, output: 15 },\n \"claude-haiku-4-5-20250514\": { input: 0.8, output: 4 },\n \"claude-haiku-3-5-20241022\": { input: 0.8, output: 4 },\n \"claude-opus-4-20250514\": { input: 15, output: 75 },\n};\n\n// ============================================================================\n// Anthropic Runner\n// ============================================================================\n\n/** Options for createAnthropicRunner */\nexport interface AnthropicRunnerOptions {\n apiKey: string;\n model?: string;\n /** @default 4096 */\n maxTokens?: number;\n baseURL?: string;\n fetch?: typeof globalThis.fetch;\n /** @default undefined */\n timeoutMs?: number;\n /** Lifecycle hooks for tracing, logging, and metrics */\n hooks?: AdapterHooks;\n /** Sampling temperature (0–1). Higher = more random. */\n temperature?: number;\n /** Nucleus sampling: top-P probability mass (0–1). */\n topP?: number;\n /** Custom stop sequences. The model will stop generating when it encounters one. */\n stopSequences?: string[];\n}\n\n/**\n * Create an AgentRunner for the Anthropic Messages API.\n *\n * Returns `tokenUsage` with input/output breakdown for cost tracking.\n *\n * @example\n * ```typescript\n * const runner = createAnthropicRunner({\n * apiKey: process.env.ANTHROPIC_API_KEY!,\n * hooks: {\n * onAfterCall: ({ durationMs, tokenUsage }) => {\n * console.log(`${durationMs}ms – ${tokenUsage.inputTokens}in/${tokenUsage.outputTokens}out`);\n * },\n * },\n * });\n * const orchestrator = createAgentOrchestrator({ runner });\n * const result = await orchestrator.run(agent, input);\n * ```\n */\nexport function createAnthropicRunner(\n options: AnthropicRunnerOptions,\n): AgentRunner {\n const {\n apiKey,\n model = \"claude-sonnet-4-5-20250929\",\n maxTokens = 4096,\n baseURL = \"https://api.anthropic.com/v1\",\n fetch: fetchFn = globalThis.fetch,\n timeoutMs,\n hooks,\n temperature,\n topP,\n stopSequences,\n } = options;\n\n validateBaseURL(baseURL);\n warnIfMissingApiKey(apiKey, \"createAnthropicRunner\");\n\n return createRunner({\n fetch: fetchFn,\n hooks,\n buildRequest: (agent, _input, messages) => ({\n url: `${baseURL}/messages`,\n init: {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": apiKey,\n \"anthropic-version\": \"2023-06-01\",\n },\n body: JSON.stringify({\n model: agent.model ?? model,\n max_tokens: maxTokens,\n ...(temperature != null ? { temperature } : {}),\n ...(topP != null ? { top_p: topP } : {}),\n ...(stopSequences != null ? { stop_sequences: stopSequences } : {}),\n system: agent.instructions ?? \"\",\n messages: messages.map((m) => ({\n role: m.role,\n content: m.content,\n })),\n }),\n ...(timeoutMs != null\n ? { signal: AbortSignal.timeout(timeoutMs) }\n : {}),\n },\n }),\n parseResponse: async (res) => {\n const data = await res.json();\n const text = data.content?.[0]?.text ?? \"\";\n const inputTokens = data.usage?.input_tokens ?? 0;\n const outputTokens = data.usage?.output_tokens ?? 0;\n\n return {\n text,\n totalTokens: inputTokens + outputTokens,\n inputTokens,\n outputTokens,\n };\n },\n });\n}\n\n// ============================================================================\n// Anthropic Streaming Runner\n// ============================================================================\n\n/** Options for createAnthropicStreamingRunner */\nexport interface AnthropicStreamingRunnerOptions {\n apiKey: string;\n model?: string;\n /** @default 4096 */\n maxTokens?: number;\n baseURL?: string;\n fetch?: typeof globalThis.fetch;\n /** Lifecycle hooks for tracing, logging, and metrics */\n hooks?: AdapterHooks;\n /** Sampling temperature (0–1). Higher = more random. */\n temperature?: number;\n /** Nucleus sampling: top-P probability mass (0–1). */\n topP?: number;\n /** Custom stop sequences. The model will stop generating when it encounters one. */\n stopSequences?: string[];\n}\n\n/**\n * Create a StreamingCallbackRunner for the Anthropic Messages API with\n * server-sent events. Can be used standalone or paired with `createAnthropicRunner`.\n *\n * Returns `tokenUsage` with input/output breakdown for cost tracking.\n *\n * @example\n * ```typescript\n * const streamingRunner = createAnthropicStreamingRunner({\n * apiKey: process.env.ANTHROPIC_API_KEY!,\n * });\n * const streamRunner = createStreamingRunner(streamingRunner);\n * const { stream, result } = streamRunner(agent, input);\n * ```\n */\nexport function createAnthropicStreamingRunner(\n options: AnthropicStreamingRunnerOptions,\n): StreamingCallbackRunner {\n const {\n apiKey,\n model = \"claude-sonnet-4-5-20250929\",\n maxTokens = 4096,\n baseURL = \"https://api.anthropic.com/v1\",\n fetch: fetchFn = globalThis.fetch,\n hooks,\n temperature,\n topP,\n stopSequences,\n } = options;\n\n validateBaseURL(baseURL);\n warnIfMissingApiKey(apiKey, \"createAnthropicStreamingRunner\");\n\n return async (agent, input, callbacks) => {\n const startTime = fireBeforeCallHook(hooks, agent, input);\n\n try {\n const response = await fetchFn(`${baseURL}/messages`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": apiKey,\n \"anthropic-version\": \"2023-06-01\",\n },\n body: JSON.stringify({\n model: agent.model ?? model,\n max_tokens: maxTokens,\n ...(temperature != null ? { temperature } : {}),\n ...(topP != null ? { top_p: topP } : {}),\n ...(stopSequences != null ? { stop_sequences: stopSequences } : {}),\n system: agent.instructions ?? \"\",\n messages: [{ role: \"user\", content: input }],\n stream: true,\n }),\n signal: callbacks.signal,\n });\n\n if (!response.ok) {\n await throwStreamingHTTPError(response, \"Anthropic\");\n }\n\n const reader = getSSEReader(response);\n\n const { fullText, inputTokens, outputTokens } = await parseSSEStream(\n reader,\n callbacks.onToken,\n (event) => {\n if (event.type === \"error\") {\n throw new Error(\n `[Directive] Anthropic stream error: ${(event.error as Record<string, unknown>)?.message ?? JSON.stringify(event.error)}`,\n );\n }\n\n const result: {\n text?: string;\n inputTokens?: number;\n outputTokens?: number;\n } = {};\n if (\n event.type === \"content_block_delta\" &&\n (event.delta as Record<string, unknown>)?.type === \"text_delta\"\n ) {\n result.text = (event.delta as Record<string, unknown>)\n .text as string;\n }\n if (event.type === \"message_delta\" && event.usage) {\n result.outputTokens =\n ((event.usage as Record<string, unknown>)\n .output_tokens as number) ?? 0;\n }\n if (\n event.type === \"message_start\" &&\n (event.message as Record<string, unknown>)?.usage\n ) {\n result.inputTokens =\n ((\n (event.message as Record<string, unknown>).usage as Record<\n string,\n unknown\n >\n ).input_tokens as number) ?? 0;\n }\n\n return result;\n },\n \"Anthropic\",\n );\n\n const tokenUsage = { inputTokens, outputTokens };\n const totalTokens = inputTokens + outputTokens;\n\n callbacks.onMessage?.({ role: \"assistant\", content: fullText });\n fireAfterCallHook(\n hooks,\n agent,\n input,\n fullText,\n totalTokens,\n tokenUsage,\n startTime,\n );\n\n return buildStreamingResult(input, fullText, totalTokens, tokenUsage);\n } catch (err) {\n fireErrorHook(hooks, agent, input, err, startTime);\n\n throw err;\n }\n };\n}\n"]}
@@ -0,0 +1,3 @@
1
+ 'use strict';function x(t){return t.status==="running"}function O(t){return t.pending.length>0}function L(t,e){return t/1e6*e}var y=new Set(["http:","https:"]);function M(t){try{let e=new URL(t);if(!y.has(e.protocol))throw new Error(`[Directive] Invalid baseURL protocol "${e.protocol}" \u2013 only http: and https: are allowed`)}catch(e){throw e instanceof Error&&e.message.startsWith("[Directive]")?e:new Error(`[Directive] Invalid baseURL "${t}" \u2013 must be a valid URL (e.g. "https://api.openai.com/v1")`)}}function S(t){let e=t.filter(n=>n!==void 0);if(e.length===0)return;if(e.length===1)return e[0];let c=AbortSignal.any;if(typeof c=="function")return c(e);let r=new AbortController,p=e.find(n=>n.aborted);if(p)return r.abort(p.reason??void 0),r.signal;for(let n of e)n.addEventListener("abort",()=>{r.abort(n.reason??void 0);},{once:true});return r.signal}function D(t){let{fetch:e=globalThis.fetch,buildRequest:c,parseResponse:r,parseOutput:p,hooks:n}=t,m=p??(s=>{try{return JSON.parse(s)}catch{return s}});return async(s,a,f)=>{let g=Date.now();n?.onBeforeCall?.({agent:s,input:a,timestamp:g});let d=[{role:"user",content:a}];try{let{url:i,init:u}=c(s,a,d),h=S([u.signal??void 0,f?.signal]),T=h?{...u,signal:h}:u,l=await e(i,T);if(!l.ok){let k=await l.text().catch(()=>"");throw new Error(`[Directive] AgentRunner request failed: ${l.status} ${l.statusText}${k?` \u2013 ${k.slice(0,300)}`:""}`)}let o=await r(l,d),b={inputTokens:o.inputTokens??0,outputTokens:o.outputTokens??0},R={role:"assistant",content:o.text},A=[...d,R];f?.onMessage?.(R);let w=Date.now()-g;return n?.onAfterCall?.({agent:s,input:a,output:o.text,totalTokens:o.totalTokens,tokenUsage:b,durationMs:w,timestamp:Date.now()}),{output:m(o.text),messages:A,toolCalls:[],totalTokens:o.totalTokens,tokenUsage:b}}catch(i){let u=Date.now()-g;throw i instanceof Error&&n?.onError?.({agent:s,input:a,error:i,durationMs:u,timestamp:Date.now()}),i}}}
2
+ exports.a=x;exports.b=O;exports.c=L;exports.d=M;exports.e=S;exports.f=D;//# sourceMappingURL=chunk-3WO4MWJM.cjs.map
3
+ //# sourceMappingURL=chunk-3WO4MWJM.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/agent-utils.ts"],"names":["isAgentRunning","state","hasPendingApprovals","estimateCost","tokenUsage","ratePerMillionTokens","ALLOWED_PROTOCOLS","validateBaseURL","baseURL","url","err","combineSignals","signals","live","s","anyFn","controller","already","createRunner","options","fetchFn","buildRequest","parseResponse","parseOutput","hooks","parse","text","agent","input","runOptions","startTime","messages","init","combined","fetchInit","response","errBody","parsed","assistantMessage","allMessages","durationMs"],"mappings":"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","file":"chunk-3WO4MWJM.cjs","sourcesContent":["/**\n * Agent utilities — createRunner, estimateCost, state queries, URL validation.\n */\n\nimport type {\n AdapterHooks,\n AgentLike,\n AgentRunner,\n AgentState,\n ApprovalState,\n Message,\n RunOptions,\n RunResult,\n TokenUsage,\n} from \"./types.js\";\n\n// ============================================================================\n// State Query Helpers\n// ============================================================================\n\n/**\n * Check whether an agent is currently executing a run.\n *\n * @param state - The current {@link AgentState} to inspect.\n * @returns `true` when the agent status is `\"running\"`.\n */\nexport function isAgentRunning(state: AgentState): boolean {\n return state.status === \"running\";\n}\n\n/**\n * Check whether there are tool-call approvals waiting for user confirmation.\n *\n * @param state - The current {@link ApprovalState} to inspect.\n * @returns `true` when one or more approvals are pending.\n */\nexport function hasPendingApprovals(state: ApprovalState): boolean {\n return state.pending.length > 0;\n}\n\n// ============================================================================\n// Cost Estimation\n// ============================================================================\n\n/**\n * Estimate the dollar cost of an agent run based on total token usage.\n *\n * @remarks\n * No default rate is provided — callers must supply the current per-million-token\n * price to avoid silently using stale pricing.\n *\n * @param tokenUsage - Total number of tokens consumed (input + output).\n * @param ratePerMillionTokens - Cost in dollars per one million tokens.\n * @returns Estimated cost in dollars.\n */\nexport function estimateCost(\n tokenUsage: number,\n ratePerMillionTokens: number,\n): number {\n return (tokenUsage / 1_000_000) * ratePerMillionTokens;\n}\n\n// ============================================================================\n// Validation Helpers\n// ============================================================================\n\nconst ALLOWED_PROTOCOLS = new Set([\"http:\", \"https:\"]);\n\n/**\n * Validate that a base URL uses the `http:` or `https:` protocol.\n * Throws immediately at adapter creation time (not at call time) to surface\n * configuration errors before any LLM requests are made.\n *\n * @param baseURL - The base URL string to validate.\n * @throws When the URL is malformed or uses a protocol other than `http:` or `https:`.\n */\nexport function validateBaseURL(baseURL: string): void {\n try {\n const url = new URL(baseURL);\n if (!ALLOWED_PROTOCOLS.has(url.protocol)) {\n throw new Error(\n `[Directive] Invalid baseURL protocol \"${url.protocol}\" – only http: and https: are allowed`,\n );\n }\n } catch (err) {\n if (err instanceof Error && err.message.startsWith(\"[Directive]\")) {\n throw err;\n }\n\n throw new Error(\n `[Directive] Invalid baseURL \"${baseURL}\" – must be a valid URL (e.g. \"https://api.openai.com/v1\")`,\n );\n }\n}\n\n// ============================================================================\n// AbortSignal combination helper\n// ============================================================================\n\n/**\n * Combine multiple `AbortSignal`s into one — the resulting signal aborts\n * as soon as ANY input signal aborts. Falls back to a manual controller\n * wiring on runtimes without `AbortSignal.any` (Node < 20).\n *\n * @internal\n */\nexport function combineSignals(\n signals: ReadonlyArray<AbortSignal | undefined>,\n): AbortSignal | undefined {\n const live = signals.filter((s): s is AbortSignal => s !== undefined);\n if (live.length === 0) return undefined;\n if (live.length === 1) return live[0];\n\n // Prefer the standard helper when available (Node 20.3+, modern browsers).\n const anyFn = (\n AbortSignal as unknown as {\n any?: (signals: readonly AbortSignal[]) => AbortSignal;\n }\n ).any;\n if (typeof anyFn === \"function\") {\n return anyFn(live);\n }\n\n // Fallback: manual controller. If any input is already aborted, the\n // result is too — wire listeners for the rest.\n const controller = new AbortController();\n const already = live.find((s) => s.aborted);\n if (already) {\n controller.abort(\n (already as AbortSignal & { reason?: unknown }).reason ?? undefined,\n );\n\n return controller.signal;\n }\n for (const s of live) {\n s.addEventListener(\n \"abort\",\n () => {\n controller.abort(\n (s as AbortSignal & { reason?: unknown }).reason ?? undefined,\n );\n },\n { once: true },\n );\n }\n\n return controller.signal;\n}\n\n// ============================================================================\n// createRunner Helper\n// ============================================================================\n\n/** Parsed response from an LLM provider */\nexport interface ParsedResponse {\n text: string;\n totalTokens: number;\n /** Input token count, when available from the provider */\n inputTokens?: number;\n /** Output token count, when available from the provider */\n outputTokens?: number;\n}\n\n/** Options for creating an AgentRunner from buildRequest/parseResponse */\nexport interface CreateRunnerOptions {\n fetch?: typeof globalThis.fetch;\n buildRequest: (\n agent: AgentLike,\n input: string,\n messages: Message[],\n ) => { url: string; init: RequestInit };\n parseResponse: (\n response: Response,\n messages: Message[],\n ) => Promise<ParsedResponse>;\n parseOutput?: <T>(text: string) => T;\n /** Lifecycle hooks for tracing, logging, and metrics */\n hooks?: AdapterHooks;\n}\n\n/**\n * Create an {@link AgentRunner} from `buildRequest`/`parseResponse` helpers, reducing\n * ~50 lines of fetch boilerplate to ~20 lines of configuration.\n *\n * @remarks\n * Supports lifecycle hooks for observability:\n * - `onBeforeCall` fires before each API request\n * - `onAfterCall` fires after a successful response (includes token breakdown)\n * - `onError` fires when the request fails\n *\n * Output parsing defaults to `JSON.parse` with a string fallback. Supply a custom\n * `parseOutput` to override (e.g. for structured output schemas).\n *\n * @param options - Configuration for the runner, including request building, response parsing, and hooks.\n * @returns An {@link AgentRunner} function that performs LLM calls via fetch.\n *\n * @example\n * ```typescript\n * const runClaude = createRunner({\n * buildRequest: (agent, input) => ({\n * url: \"/api/claude\",\n * init: {\n * method: \"POST\",\n * headers: { \"Content-Type\": \"application/json\" },\n * body: JSON.stringify({\n * model: agent.model ?? \"claude-haiku-4-5-20251001\",\n * system: agent.instructions ?? \"\",\n * messages: [{ role: \"user\", content: input }],\n * }),\n * },\n * }),\n * parseResponse: async (res) => {\n * const data = await res.json();\n * const inputTokens = data.usage?.input_tokens ?? 0;\n * const outputTokens = data.usage?.output_tokens ?? 0;\n * return {\n * text: data.content?.[0]?.text ?? \"\",\n * totalTokens: inputTokens + outputTokens,\n * inputTokens,\n * outputTokens,\n * };\n * },\n * hooks: {\n * onAfterCall: ({ durationMs, tokenUsage }) => {\n * console.log(`LLM call: ${durationMs}ms, ${tokenUsage.inputTokens}in/${tokenUsage.outputTokens}out`);\n * },\n * },\n * });\n * ```\n *\n * @public\n */\nexport function createRunner(options: CreateRunnerOptions): AgentRunner {\n const {\n fetch: fetchFn = globalThis.fetch,\n buildRequest,\n parseResponse,\n parseOutput,\n hooks,\n } = options;\n\n const defaultParseOutput = <T>(text: string): T => {\n try {\n return JSON.parse(text) as T;\n } catch {\n return text as unknown as T;\n }\n };\n\n const parse = parseOutput ?? defaultParseOutput;\n\n return async <T = unknown>(\n agent: AgentLike,\n input: string,\n runOptions?: RunOptions,\n ): Promise<RunResult<T>> => {\n const startTime = Date.now();\n hooks?.onBeforeCall?.({ agent, input, timestamp: startTime });\n\n const messages: Message[] = [{ role: \"user\", content: input }];\n\n try {\n const { url, init } = buildRequest(agent, input, messages);\n\n // (Sec MAJOR) Combine signals — `buildRequest` may set\n // `init.signal` (e.g. `AbortSignal.timeout(timeoutMs)`) and the\n // caller may pass their own via `runOptions.signal`. Naively\n // overwriting one with the other silently disables whichever was\n // dropped. `combineSignals` aborts as soon as either fires.\n const combined = combineSignals([\n init.signal ?? undefined,\n runOptions?.signal,\n ]);\n const fetchInit: RequestInit = combined\n ? { ...init, signal: combined }\n : init;\n\n const response = await fetchFn(url, fetchInit);\n\n if (!response.ok) {\n const errBody = await response.text().catch(() => \"\");\n\n throw new Error(\n `[Directive] AgentRunner request failed: ${response.status} ${response.statusText}${errBody ? ` – ${errBody.slice(0, 300)}` : \"\"}`,\n );\n }\n\n const parsed = await parseResponse(response, messages);\n const tokenUsage: TokenUsage = {\n inputTokens: parsed.inputTokens ?? 0,\n outputTokens: parsed.outputTokens ?? 0,\n };\n\n const assistantMessage: Message = {\n role: \"assistant\",\n content: parsed.text,\n };\n const allMessages: Message[] = [...messages, assistantMessage];\n\n runOptions?.onMessage?.(assistantMessage);\n\n const durationMs = Date.now() - startTime;\n hooks?.onAfterCall?.({\n agent,\n input,\n output: parsed.text,\n totalTokens: parsed.totalTokens,\n tokenUsage,\n durationMs,\n timestamp: Date.now(),\n });\n\n return {\n output: parse<T>(parsed.text),\n messages: allMessages,\n toolCalls: [],\n totalTokens: parsed.totalTokens,\n tokenUsage,\n };\n } catch (err) {\n const durationMs = Date.now() - startTime;\n if (err instanceof Error) {\n hooks?.onError?.({\n agent,\n input,\n error: err,\n durationMs,\n timestamp: Date.now(),\n });\n }\n\n throw err;\n }\n };\n}\n"]}
@@ -0,0 +1,3 @@
1
+ function x(t){return t.status==="running"}function O(t){return t.pending.length>0}function L(t,e){return t/1e6*e}var y=new Set(["http:","https:"]);function M(t){try{let e=new URL(t);if(!y.has(e.protocol))throw new Error(`[Directive] Invalid baseURL protocol "${e.protocol}" \u2013 only http: and https: are allowed`)}catch(e){throw e instanceof Error&&e.message.startsWith("[Directive]")?e:new Error(`[Directive] Invalid baseURL "${t}" \u2013 must be a valid URL (e.g. "https://api.openai.com/v1")`)}}function S(t){let e=t.filter(n=>n!==void 0);if(e.length===0)return;if(e.length===1)return e[0];let c=AbortSignal.any;if(typeof c=="function")return c(e);let r=new AbortController,p=e.find(n=>n.aborted);if(p)return r.abort(p.reason??void 0),r.signal;for(let n of e)n.addEventListener("abort",()=>{r.abort(n.reason??void 0);},{once:true});return r.signal}function D(t){let{fetch:e=globalThis.fetch,buildRequest:c,parseResponse:r,parseOutput:p,hooks:n}=t,m=p??(s=>{try{return JSON.parse(s)}catch{return s}});return async(s,a,f)=>{let g=Date.now();n?.onBeforeCall?.({agent:s,input:a,timestamp:g});let d=[{role:"user",content:a}];try{let{url:i,init:u}=c(s,a,d),h=S([u.signal??void 0,f?.signal]),T=h?{...u,signal:h}:u,l=await e(i,T);if(!l.ok){let k=await l.text().catch(()=>"");throw new Error(`[Directive] AgentRunner request failed: ${l.status} ${l.statusText}${k?` \u2013 ${k.slice(0,300)}`:""}`)}let o=await r(l,d),b={inputTokens:o.inputTokens??0,outputTokens:o.outputTokens??0},R={role:"assistant",content:o.text},A=[...d,R];f?.onMessage?.(R);let w=Date.now()-g;return n?.onAfterCall?.({agent:s,input:a,output:o.text,totalTokens:o.totalTokens,tokenUsage:b,durationMs:w,timestamp:Date.now()}),{output:m(o.text),messages:A,toolCalls:[],totalTokens:o.totalTokens,tokenUsage:b}}catch(i){let u=Date.now()-g;throw i instanceof Error&&n?.onError?.({agent:s,input:a,error:i,durationMs:u,timestamp:Date.now()}),i}}}
2
+ export{x as a,O as b,L as c,M as d,S as e,D as f};//# sourceMappingURL=chunk-ZFLHWJ56.js.map
3
+ //# sourceMappingURL=chunk-ZFLHWJ56.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/agent-utils.ts"],"names":["isAgentRunning","state","hasPendingApprovals","estimateCost","tokenUsage","ratePerMillionTokens","ALLOWED_PROTOCOLS","validateBaseURL","baseURL","url","err","combineSignals","signals","live","s","anyFn","controller","already","createRunner","options","fetchFn","buildRequest","parseResponse","parseOutput","hooks","parse","text","agent","input","runOptions","startTime","messages","init","combined","fetchInit","response","errBody","parsed","assistantMessage","allMessages","durationMs"],"mappings":"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","file":"chunk-ZFLHWJ56.js","sourcesContent":["/**\n * Agent utilities — createRunner, estimateCost, state queries, URL validation.\n */\n\nimport type {\n AdapterHooks,\n AgentLike,\n AgentRunner,\n AgentState,\n ApprovalState,\n Message,\n RunOptions,\n RunResult,\n TokenUsage,\n} from \"./types.js\";\n\n// ============================================================================\n// State Query Helpers\n// ============================================================================\n\n/**\n * Check whether an agent is currently executing a run.\n *\n * @param state - The current {@link AgentState} to inspect.\n * @returns `true` when the agent status is `\"running\"`.\n */\nexport function isAgentRunning(state: AgentState): boolean {\n return state.status === \"running\";\n}\n\n/**\n * Check whether there are tool-call approvals waiting for user confirmation.\n *\n * @param state - The current {@link ApprovalState} to inspect.\n * @returns `true` when one or more approvals are pending.\n */\nexport function hasPendingApprovals(state: ApprovalState): boolean {\n return state.pending.length > 0;\n}\n\n// ============================================================================\n// Cost Estimation\n// ============================================================================\n\n/**\n * Estimate the dollar cost of an agent run based on total token usage.\n *\n * @remarks\n * No default rate is provided — callers must supply the current per-million-token\n * price to avoid silently using stale pricing.\n *\n * @param tokenUsage - Total number of tokens consumed (input + output).\n * @param ratePerMillionTokens - Cost in dollars per one million tokens.\n * @returns Estimated cost in dollars.\n */\nexport function estimateCost(\n tokenUsage: number,\n ratePerMillionTokens: number,\n): number {\n return (tokenUsage / 1_000_000) * ratePerMillionTokens;\n}\n\n// ============================================================================\n// Validation Helpers\n// ============================================================================\n\nconst ALLOWED_PROTOCOLS = new Set([\"http:\", \"https:\"]);\n\n/**\n * Validate that a base URL uses the `http:` or `https:` protocol.\n * Throws immediately at adapter creation time (not at call time) to surface\n * configuration errors before any LLM requests are made.\n *\n * @param baseURL - The base URL string to validate.\n * @throws When the URL is malformed or uses a protocol other than `http:` or `https:`.\n */\nexport function validateBaseURL(baseURL: string): void {\n try {\n const url = new URL(baseURL);\n if (!ALLOWED_PROTOCOLS.has(url.protocol)) {\n throw new Error(\n `[Directive] Invalid baseURL protocol \"${url.protocol}\" – only http: and https: are allowed`,\n );\n }\n } catch (err) {\n if (err instanceof Error && err.message.startsWith(\"[Directive]\")) {\n throw err;\n }\n\n throw new Error(\n `[Directive] Invalid baseURL \"${baseURL}\" – must be a valid URL (e.g. \"https://api.openai.com/v1\")`,\n );\n }\n}\n\n// ============================================================================\n// AbortSignal combination helper\n// ============================================================================\n\n/**\n * Combine multiple `AbortSignal`s into one — the resulting signal aborts\n * as soon as ANY input signal aborts. Falls back to a manual controller\n * wiring on runtimes without `AbortSignal.any` (Node < 20).\n *\n * @internal\n */\nexport function combineSignals(\n signals: ReadonlyArray<AbortSignal | undefined>,\n): AbortSignal | undefined {\n const live = signals.filter((s): s is AbortSignal => s !== undefined);\n if (live.length === 0) return undefined;\n if (live.length === 1) return live[0];\n\n // Prefer the standard helper when available (Node 20.3+, modern browsers).\n const anyFn = (\n AbortSignal as unknown as {\n any?: (signals: readonly AbortSignal[]) => AbortSignal;\n }\n ).any;\n if (typeof anyFn === \"function\") {\n return anyFn(live);\n }\n\n // Fallback: manual controller. If any input is already aborted, the\n // result is too — wire listeners for the rest.\n const controller = new AbortController();\n const already = live.find((s) => s.aborted);\n if (already) {\n controller.abort(\n (already as AbortSignal & { reason?: unknown }).reason ?? undefined,\n );\n\n return controller.signal;\n }\n for (const s of live) {\n s.addEventListener(\n \"abort\",\n () => {\n controller.abort(\n (s as AbortSignal & { reason?: unknown }).reason ?? undefined,\n );\n },\n { once: true },\n );\n }\n\n return controller.signal;\n}\n\n// ============================================================================\n// createRunner Helper\n// ============================================================================\n\n/** Parsed response from an LLM provider */\nexport interface ParsedResponse {\n text: string;\n totalTokens: number;\n /** Input token count, when available from the provider */\n inputTokens?: number;\n /** Output token count, when available from the provider */\n outputTokens?: number;\n}\n\n/** Options for creating an AgentRunner from buildRequest/parseResponse */\nexport interface CreateRunnerOptions {\n fetch?: typeof globalThis.fetch;\n buildRequest: (\n agent: AgentLike,\n input: string,\n messages: Message[],\n ) => { url: string; init: RequestInit };\n parseResponse: (\n response: Response,\n messages: Message[],\n ) => Promise<ParsedResponse>;\n parseOutput?: <T>(text: string) => T;\n /** Lifecycle hooks for tracing, logging, and metrics */\n hooks?: AdapterHooks;\n}\n\n/**\n * Create an {@link AgentRunner} from `buildRequest`/`parseResponse` helpers, reducing\n * ~50 lines of fetch boilerplate to ~20 lines of configuration.\n *\n * @remarks\n * Supports lifecycle hooks for observability:\n * - `onBeforeCall` fires before each API request\n * - `onAfterCall` fires after a successful response (includes token breakdown)\n * - `onError` fires when the request fails\n *\n * Output parsing defaults to `JSON.parse` with a string fallback. Supply a custom\n * `parseOutput` to override (e.g. for structured output schemas).\n *\n * @param options - Configuration for the runner, including request building, response parsing, and hooks.\n * @returns An {@link AgentRunner} function that performs LLM calls via fetch.\n *\n * @example\n * ```typescript\n * const runClaude = createRunner({\n * buildRequest: (agent, input) => ({\n * url: \"/api/claude\",\n * init: {\n * method: \"POST\",\n * headers: { \"Content-Type\": \"application/json\" },\n * body: JSON.stringify({\n * model: agent.model ?? \"claude-haiku-4-5-20251001\",\n * system: agent.instructions ?? \"\",\n * messages: [{ role: \"user\", content: input }],\n * }),\n * },\n * }),\n * parseResponse: async (res) => {\n * const data = await res.json();\n * const inputTokens = data.usage?.input_tokens ?? 0;\n * const outputTokens = data.usage?.output_tokens ?? 0;\n * return {\n * text: data.content?.[0]?.text ?? \"\",\n * totalTokens: inputTokens + outputTokens,\n * inputTokens,\n * outputTokens,\n * };\n * },\n * hooks: {\n * onAfterCall: ({ durationMs, tokenUsage }) => {\n * console.log(`LLM call: ${durationMs}ms, ${tokenUsage.inputTokens}in/${tokenUsage.outputTokens}out`);\n * },\n * },\n * });\n * ```\n *\n * @public\n */\nexport function createRunner(options: CreateRunnerOptions): AgentRunner {\n const {\n fetch: fetchFn = globalThis.fetch,\n buildRequest,\n parseResponse,\n parseOutput,\n hooks,\n } = options;\n\n const defaultParseOutput = <T>(text: string): T => {\n try {\n return JSON.parse(text) as T;\n } catch {\n return text as unknown as T;\n }\n };\n\n const parse = parseOutput ?? defaultParseOutput;\n\n return async <T = unknown>(\n agent: AgentLike,\n input: string,\n runOptions?: RunOptions,\n ): Promise<RunResult<T>> => {\n const startTime = Date.now();\n hooks?.onBeforeCall?.({ agent, input, timestamp: startTime });\n\n const messages: Message[] = [{ role: \"user\", content: input }];\n\n try {\n const { url, init } = buildRequest(agent, input, messages);\n\n // (Sec MAJOR) Combine signals — `buildRequest` may set\n // `init.signal` (e.g. `AbortSignal.timeout(timeoutMs)`) and the\n // caller may pass their own via `runOptions.signal`. Naively\n // overwriting one with the other silently disables whichever was\n // dropped. `combineSignals` aborts as soon as either fires.\n const combined = combineSignals([\n init.signal ?? undefined,\n runOptions?.signal,\n ]);\n const fetchInit: RequestInit = combined\n ? { ...init, signal: combined }\n : init;\n\n const response = await fetchFn(url, fetchInit);\n\n if (!response.ok) {\n const errBody = await response.text().catch(() => \"\");\n\n throw new Error(\n `[Directive] AgentRunner request failed: ${response.status} ${response.statusText}${errBody ? ` – ${errBody.slice(0, 300)}` : \"\"}`,\n );\n }\n\n const parsed = await parseResponse(response, messages);\n const tokenUsage: TokenUsage = {\n inputTokens: parsed.inputTokens ?? 0,\n outputTokens: parsed.outputTokens ?? 0,\n };\n\n const assistantMessage: Message = {\n role: \"assistant\",\n content: parsed.text,\n };\n const allMessages: Message[] = [...messages, assistantMessage];\n\n runOptions?.onMessage?.(assistantMessage);\n\n const durationMs = Date.now() - startTime;\n hooks?.onAfterCall?.({\n agent,\n input,\n output: parsed.text,\n totalTokens: parsed.totalTokens,\n tokenUsage,\n durationMs,\n timestamp: Date.now(),\n });\n\n return {\n output: parse<T>(parsed.text),\n messages: allMessages,\n toolCalls: [],\n totalTokens: parsed.totalTokens,\n tokenUsage,\n };\n } catch (err) {\n const durationMs = Date.now() - startTime;\n if (err instanceof Error) {\n hooks?.onError?.({\n agent,\n input,\n error: err,\n durationMs,\n timestamp: Date.now(),\n });\n }\n\n throw err;\n }\n };\n}\n"]}
package/dist/gemini.cjs CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';var chunkKP3G32S7_cjs=require('./chunk-KP3G32S7.cjs'),chunkW6MVJKWN_cjs=require('./chunk-W6MVJKWN.cjs');var $={"gemini-2.5-pro":{input:1.25,output:10},"gemini-2.5-flash":{input:.15,output:.6},"gemini-2.0-flash":{input:.1,output:.4},"gemini-2.0-flash-lite":{input:.025,output:.1}};function v(h){let{apiKey:u,model:T="gemini-2.0-flash",maxOutputTokens:p,baseURL:m="https://generativelanguage.googleapis.com/v1beta",fetch:b=globalThis.fetch,timeoutMs:i,hooks:g,temperature:c,topP:l,stopSequences:n}=h;chunkW6MVJKWN_cjs.d(m),chunkKP3G32S7_cjs.c(u,"createGeminiRunner");let o={};p!=null&&(o.maxOutputTokens=p),c!=null&&(o.temperature=c),l!=null&&(o.topP=l),n!=null&&(o.stopSequences=n);let s=Object.keys(o).length>0;return chunkW6MVJKWN_cjs.e({fetch:b,hooks:g,buildRequest:(t,r,a)=>({url:`${m}/models/${t.model??T}:generateContent`,init:{method:"POST",headers:{"Content-Type":"application/json","x-goog-api-key":u},body:JSON.stringify({...t.instructions?{systemInstruction:{parts:[{text:t.instructions}]}}:{},contents:a.map(e=>({role:e.role==="assistant"?"model":"user",parts:[{text:e.content}]})),...s?{generationConfig:o}:{}}),...i!=null?{signal:AbortSignal.timeout(i)}:{}}}),parseResponse:async t=>{let r=await t.json(),a=r.candidates?.[0]?.content?.parts?.[0]?.text??"",e=r.usageMetadata?.promptTokenCount??0,f=r.usageMetadata?.candidatesTokenCount??0;return {text:a,totalTokens:e+f,inputTokens:e,outputTokens:f}}})}function B(h){let{apiKey:u,model:T="gemini-2.0-flash",maxOutputTokens:p,baseURL:m="https://generativelanguage.googleapis.com/v1beta",fetch:b=globalThis.fetch,hooks:i,temperature:g,topP:c,stopSequences:l}=h;chunkW6MVJKWN_cjs.d(m),chunkKP3G32S7_cjs.c(u,"createGeminiStreamingRunner");let n={};p!=null&&(n.maxOutputTokens=p),g!=null&&(n.temperature=g),c!=null&&(n.topP=c),l!=null&&(n.stopSequences=l);let o=Object.keys(n).length>0;return async(s,t,r)=>{let a=chunkKP3G32S7_cjs.e(i,s,t);try{let e=await b(`${m}/models/${s.model??T}:streamGenerateContent?alt=sse`,{method:"POST",headers:{"Content-Type":"application/json","x-goog-api-key":u},body:JSON.stringify({...s.instructions?{systemInstruction:{parts:[{text:s.instructions}]}}:{},contents:[{role:"user",parts:[{text:t}]}],...o?{generationConfig:n}:{}}),signal:r.signal});e.ok||await chunkKP3G32S7_cjs.a(e,"Gemini");let f=chunkKP3G32S7_cjs.b(e),{fullText:R,inputTokens:C,outputTokens:O}=await chunkKP3G32S7_cjs.d(f,r.onToken,y=>{let d={},A=y.candidates?.[0]?.content?.parts?.[0]?.text;if(A&&(d.text=A),y.usageMetadata){let k=y.usageMetadata;k.promptTokenCount!==void 0&&(d.inputTokens=k.promptTokenCount),k.candidatesTokenCount!==void 0&&(d.outputTokens=k.candidatesTokenCount);}return d},"Gemini"),G={inputTokens:C,outputTokens:O},w=C+O;return r.onMessage?.({role:"assistant",content:R}),chunkKP3G32S7_cjs.f(i,s,t,R,w,G,a),chunkKP3G32S7_cjs.h(t,R,w,G)}catch(e){throw chunkKP3G32S7_cjs.g(i,s,t,e,a),e}}}
1
+ 'use strict';var chunkKP3G32S7_cjs=require('./chunk-KP3G32S7.cjs'),chunk3WO4MWJM_cjs=require('./chunk-3WO4MWJM.cjs');var $={"gemini-2.5-pro":{input:1.25,output:10},"gemini-2.5-flash":{input:.15,output:.6},"gemini-2.0-flash":{input:.1,output:.4},"gemini-2.0-flash-lite":{input:.025,output:.1}};function v(h){let{apiKey:u,model:T="gemini-2.0-flash",maxOutputTokens:p,baseURL:m="https://generativelanguage.googleapis.com/v1beta",fetch:b=globalThis.fetch,timeoutMs:i,hooks:g,temperature:c,topP:l,stopSequences:n}=h;chunk3WO4MWJM_cjs.d(m),chunkKP3G32S7_cjs.c(u,"createGeminiRunner");let o={};p!=null&&(o.maxOutputTokens=p),c!=null&&(o.temperature=c),l!=null&&(o.topP=l),n!=null&&(o.stopSequences=n);let s=Object.keys(o).length>0;return chunk3WO4MWJM_cjs.f({fetch:b,hooks:g,buildRequest:(t,r,a)=>({url:`${m}/models/${t.model??T}:generateContent`,init:{method:"POST",headers:{"Content-Type":"application/json","x-goog-api-key":u},body:JSON.stringify({...t.instructions?{systemInstruction:{parts:[{text:t.instructions}]}}:{},contents:a.map(e=>({role:e.role==="assistant"?"model":"user",parts:[{text:e.content}]})),...s?{generationConfig:o}:{}}),...i!=null?{signal:AbortSignal.timeout(i)}:{}}}),parseResponse:async t=>{let r=await t.json(),a=r.candidates?.[0]?.content?.parts?.[0]?.text??"",e=r.usageMetadata?.promptTokenCount??0,f=r.usageMetadata?.candidatesTokenCount??0;return {text:a,totalTokens:e+f,inputTokens:e,outputTokens:f}}})}function B(h){let{apiKey:u,model:T="gemini-2.0-flash",maxOutputTokens:p,baseURL:m="https://generativelanguage.googleapis.com/v1beta",fetch:b=globalThis.fetch,hooks:i,temperature:g,topP:c,stopSequences:l}=h;chunk3WO4MWJM_cjs.d(m),chunkKP3G32S7_cjs.c(u,"createGeminiStreamingRunner");let n={};p!=null&&(n.maxOutputTokens=p),g!=null&&(n.temperature=g),c!=null&&(n.topP=c),l!=null&&(n.stopSequences=l);let o=Object.keys(n).length>0;return async(s,t,r)=>{let a=chunkKP3G32S7_cjs.e(i,s,t);try{let e=await b(`${m}/models/${s.model??T}:streamGenerateContent?alt=sse`,{method:"POST",headers:{"Content-Type":"application/json","x-goog-api-key":u},body:JSON.stringify({...s.instructions?{systemInstruction:{parts:[{text:s.instructions}]}}:{},contents:[{role:"user",parts:[{text:t}]}],...o?{generationConfig:n}:{}}),signal:r.signal});e.ok||await chunkKP3G32S7_cjs.a(e,"Gemini");let f=chunkKP3G32S7_cjs.b(e),{fullText:R,inputTokens:C,outputTokens:O}=await chunkKP3G32S7_cjs.d(f,r.onToken,y=>{let d={},A=y.candidates?.[0]?.content?.parts?.[0]?.text;if(A&&(d.text=A),y.usageMetadata){let k=y.usageMetadata;k.promptTokenCount!==void 0&&(d.inputTokens=k.promptTokenCount),k.candidatesTokenCount!==void 0&&(d.outputTokens=k.candidatesTokenCount);}return d},"Gemini"),G={inputTokens:C,outputTokens:O},w=C+O;return r.onMessage?.({role:"assistant",content:R}),chunkKP3G32S7_cjs.f(i,s,t,R,w,G,a),chunkKP3G32S7_cjs.h(t,R,w,G)}catch(e){throw chunkKP3G32S7_cjs.g(i,s,t,e,a),e}}}
2
2
  exports.GEMINI_PRICING=$;exports.createGeminiRunner=v;exports.createGeminiStreamingRunner=B;//# sourceMappingURL=gemini.cjs.map
3
3
  //# sourceMappingURL=gemini.cjs.map
package/dist/gemini.js CHANGED
@@ -1,3 +1,3 @@
1
- import {c,e as e$1,a,b,d as d$1,f,h,g}from'./chunk-3PGRBK4E.js';import {d,e}from'./chunk-W6WZBQER.js';var $={"gemini-2.5-pro":{input:1.25,output:10},"gemini-2.5-flash":{input:.15,output:.6},"gemini-2.0-flash":{input:.1,output:.4},"gemini-2.0-flash-lite":{input:.025,output:.1}};function v(h){let{apiKey:u,model:T="gemini-2.0-flash",maxOutputTokens:p,baseURL:m="https://generativelanguage.googleapis.com/v1beta",fetch:b=globalThis.fetch,timeoutMs:i,hooks:g,temperature:c$1,topP:l,stopSequences:n}=h;d(m),c(u,"createGeminiRunner");let o={};p!=null&&(o.maxOutputTokens=p),c$1!=null&&(o.temperature=c$1),l!=null&&(o.topP=l),n!=null&&(o.stopSequences=n);let s=Object.keys(o).length>0;return e({fetch:b,hooks:g,buildRequest:(t,r,a)=>({url:`${m}/models/${t.model??T}:generateContent`,init:{method:"POST",headers:{"Content-Type":"application/json","x-goog-api-key":u},body:JSON.stringify({...t.instructions?{systemInstruction:{parts:[{text:t.instructions}]}}:{},contents:a.map(e=>({role:e.role==="assistant"?"model":"user",parts:[{text:e.content}]})),...s?{generationConfig:o}:{}}),...i!=null?{signal:AbortSignal.timeout(i)}:{}}}),parseResponse:async t=>{let r=await t.json(),a=r.candidates?.[0]?.content?.parts?.[0]?.text??"",e=r.usageMetadata?.promptTokenCount??0,f=r.usageMetadata?.candidatesTokenCount??0;return {text:a,totalTokens:e+f,inputTokens:e,outputTokens:f}}})}function B(h$1){let{apiKey:u,model:T="gemini-2.0-flash",maxOutputTokens:p,baseURL:m="https://generativelanguage.googleapis.com/v1beta",fetch:b$1=globalThis.fetch,hooks:i,temperature:g$1,topP:c$1,stopSequences:l}=h$1;d(m),c(u,"createGeminiStreamingRunner");let n={};p!=null&&(n.maxOutputTokens=p),g$1!=null&&(n.temperature=g$1),c$1!=null&&(n.topP=c$1),l!=null&&(n.stopSequences=l);let o=Object.keys(n).length>0;return async(s,t,r)=>{let a$1=e$1(i,s,t);try{let e=await b$1(`${m}/models/${s.model??T}:streamGenerateContent?alt=sse`,{method:"POST",headers:{"Content-Type":"application/json","x-goog-api-key":u},body:JSON.stringify({...s.instructions?{systemInstruction:{parts:[{text:s.instructions}]}}:{},contents:[{role:"user",parts:[{text:t}]}],...o?{generationConfig:n}:{}}),signal:r.signal});e.ok||await a(e,"Gemini");let f$1=b(e),{fullText:R,inputTokens:C,outputTokens:O}=await d$1(f$1,r.onToken,y=>{let d={},A=y.candidates?.[0]?.content?.parts?.[0]?.text;if(A&&(d.text=A),y.usageMetadata){let k=y.usageMetadata;k.promptTokenCount!==void 0&&(d.inputTokens=k.promptTokenCount),k.candidatesTokenCount!==void 0&&(d.outputTokens=k.candidatesTokenCount);}return d},"Gemini"),G={inputTokens:C,outputTokens:O},w=C+O;return r.onMessage?.({role:"assistant",content:R}),f(i,s,t,R,w,G,a$1),h(t,R,w,G)}catch(e){throw g(i,s,t,e,a$1),e}}}
1
+ import {c,e,a,b,d as d$1,f as f$1,h,g}from'./chunk-3PGRBK4E.js';import {d,f}from'./chunk-ZFLHWJ56.js';var $={"gemini-2.5-pro":{input:1.25,output:10},"gemini-2.5-flash":{input:.15,output:.6},"gemini-2.0-flash":{input:.1,output:.4},"gemini-2.0-flash-lite":{input:.025,output:.1}};function v(h){let{apiKey:u,model:T="gemini-2.0-flash",maxOutputTokens:p,baseURL:m="https://generativelanguage.googleapis.com/v1beta",fetch:b=globalThis.fetch,timeoutMs:i,hooks:g,temperature:c$1,topP:l,stopSequences:n}=h;d(m),c(u,"createGeminiRunner");let o={};p!=null&&(o.maxOutputTokens=p),c$1!=null&&(o.temperature=c$1),l!=null&&(o.topP=l),n!=null&&(o.stopSequences=n);let s=Object.keys(o).length>0;return f({fetch:b,hooks:g,buildRequest:(t,r,a)=>({url:`${m}/models/${t.model??T}:generateContent`,init:{method:"POST",headers:{"Content-Type":"application/json","x-goog-api-key":u},body:JSON.stringify({...t.instructions?{systemInstruction:{parts:[{text:t.instructions}]}}:{},contents:a.map(e=>({role:e.role==="assistant"?"model":"user",parts:[{text:e.content}]})),...s?{generationConfig:o}:{}}),...i!=null?{signal:AbortSignal.timeout(i)}:{}}}),parseResponse:async t=>{let r=await t.json(),a=r.candidates?.[0]?.content?.parts?.[0]?.text??"",e=r.usageMetadata?.promptTokenCount??0,f=r.usageMetadata?.candidatesTokenCount??0;return {text:a,totalTokens:e+f,inputTokens:e,outputTokens:f}}})}function B(h$1){let{apiKey:u,model:T="gemini-2.0-flash",maxOutputTokens:p,baseURL:m="https://generativelanguage.googleapis.com/v1beta",fetch:b$1=globalThis.fetch,hooks:i,temperature:g$1,topP:c$1,stopSequences:l}=h$1;d(m),c(u,"createGeminiStreamingRunner");let n={};p!=null&&(n.maxOutputTokens=p),g$1!=null&&(n.temperature=g$1),c$1!=null&&(n.topP=c$1),l!=null&&(n.stopSequences=l);let o=Object.keys(n).length>0;return async(s,t,r)=>{let a$1=e(i,s,t);try{let e=await b$1(`${m}/models/${s.model??T}:streamGenerateContent?alt=sse`,{method:"POST",headers:{"Content-Type":"application/json","x-goog-api-key":u},body:JSON.stringify({...s.instructions?{systemInstruction:{parts:[{text:s.instructions}]}}:{},contents:[{role:"user",parts:[{text:t}]}],...o?{generationConfig:n}:{}}),signal:r.signal});e.ok||await a(e,"Gemini");let f=b(e),{fullText:R,inputTokens:C,outputTokens:O}=await d$1(f,r.onToken,y=>{let d={},A=y.candidates?.[0]?.content?.parts?.[0]?.text;if(A&&(d.text=A),y.usageMetadata){let k=y.usageMetadata;k.promptTokenCount!==void 0&&(d.inputTokens=k.promptTokenCount),k.candidatesTokenCount!==void 0&&(d.outputTokens=k.candidatesTokenCount);}return d},"Gemini"),G={inputTokens:C,outputTokens:O},w=C+O;return r.onMessage?.({role:"assistant",content:R}),f$1(i,s,t,R,w,G,a$1),h(t,R,w,G)}catch(e){throw g(i,s,t,e,a$1),e}}}
2
2
  export{$ as GEMINI_PRICING,v as createGeminiRunner,B as createGeminiStreamingRunner};//# sourceMappingURL=gemini.js.map
3
3
  //# sourceMappingURL=gemini.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/adapters/gemini.ts"],"names":["GEMINI_PRICING","createGeminiRunner","options","apiKey","model","maxOutputTokens","baseURL","fetchFn","timeoutMs","hooks","temperature","topP","stopSequences","validateBaseURL","warnIfMissingApiKey","genConfig","hasGenConfig","createRunner","agent","_input","messages","m","res","data","text","inputTokens","outputTokens","createGeminiStreamingRunner","input","callbacks","startTime","fireBeforeCallHook","response","throwStreamingHTTPError","reader","getSSEReader","fullText","parseSSEStream","event","result","textVal","meta","tokenUsage","totalTokens","fireAfterCallHook","buildStreamingResult","err","fireErrorHook"],"mappings":"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","file":"gemini.js","sourcesContent":["/**\n * @directive-run/ai/gemini\n *\n * Google Gemini adapter for Directive AI. Provides runners for the\n * Gemini generateContent API, including streaming support.\n *\n * @example\n * ```typescript\n * import { createGeminiRunner, createGeminiStreamingRunner } from '@directive-run/ai/gemini';\n *\n * const runner = createGeminiRunner({ apiKey: process.env.GEMINI_API_KEY! });\n * ```\n */\n\nimport { createRunner, validateBaseURL } from \"../agent-utils.js\";\nimport type { AdapterHooks, AgentRunner } from \"../types.js\";\nimport type { StreamingCallbackRunner } from \"../types.js\";\nimport {\n buildStreamingResult,\n fireAfterCallHook,\n fireBeforeCallHook,\n fireErrorHook,\n getSSEReader,\n parseSSEStream,\n throwStreamingHTTPError,\n warnIfMissingApiKey,\n} from \"./shared.js\";\n\n// ============================================================================\n// Pricing Constants\n// ============================================================================\n\n/**\n * Gemini model pricing (USD per million tokens).\n *\n * Use with `estimateCost()` for per-call cost tracking:\n * ```typescript\n * import { estimateCost } from '@directive-run/ai';\n * import { GEMINI_PRICING } from '@directive-run/ai/gemini';\n *\n * const cost =\n * estimateCost(result.tokenUsage!.inputTokens, GEMINI_PRICING[\"gemini-2.0-flash\"].input) +\n * estimateCost(result.tokenUsage!.outputTokens, GEMINI_PRICING[\"gemini-2.0-flash\"].output);\n * ```\n *\n * **Note:** Pricing changes over time. These values are provided as a convenience\n * and may not reflect the latest rates. Always verify at https://ai.google.dev/pricing\n */\nexport const GEMINI_PRICING: Record<string, { input: number; output: number }> =\n {\n \"gemini-2.5-pro\": { input: 1.25, output: 10 },\n \"gemini-2.5-flash\": { input: 0.15, output: 0.6 },\n \"gemini-2.0-flash\": { input: 0.1, output: 0.4 },\n \"gemini-2.0-flash-lite\": { input: 0.025, output: 0.1 },\n };\n\n// ============================================================================\n// Gemini Runner\n// ============================================================================\n\n/** Options for createGeminiRunner */\nexport interface GeminiRunnerOptions {\n apiKey: string;\n model?: string;\n maxOutputTokens?: number;\n baseURL?: string;\n fetch?: typeof globalThis.fetch;\n /** @default undefined */\n timeoutMs?: number;\n /** Lifecycle hooks for tracing, logging, and metrics */\n hooks?: AdapterHooks;\n /** Sampling temperature. Higher = more random. */\n temperature?: number;\n /** Nucleus sampling: top-P probability mass (0–1). */\n topP?: number;\n /** Stop sequences. The model will stop generating when it encounters one. */\n stopSequences?: string[];\n}\n\n/**\n * Create an AgentRunner for the Google Gemini generateContent API.\n *\n * Returns `tokenUsage` with input/output breakdown for cost tracking.\n *\n * @example\n * ```typescript\n * const runner = createGeminiRunner({\n * apiKey: process.env.GEMINI_API_KEY!,\n * model: 'gemini-2.0-flash',\n * });\n * const orchestrator = createAgentOrchestrator({ runner });\n * const result = await orchestrator.run(agent, input);\n * ```\n */\nexport function createGeminiRunner(options: GeminiRunnerOptions): AgentRunner {\n const {\n apiKey,\n model = \"gemini-2.0-flash\",\n maxOutputTokens,\n baseURL = \"https://generativelanguage.googleapis.com/v1beta\",\n fetch: fetchFn = globalThis.fetch,\n timeoutMs,\n hooks,\n temperature,\n topP,\n stopSequences,\n } = options;\n\n validateBaseURL(baseURL);\n warnIfMissingApiKey(apiKey, \"createGeminiRunner\");\n\n const genConfig: Record<string, unknown> = {};\n if (maxOutputTokens != null) {\n genConfig.maxOutputTokens = maxOutputTokens;\n }\n if (temperature != null) {\n genConfig.temperature = temperature;\n }\n if (topP != null) {\n genConfig.topP = topP;\n }\n if (stopSequences != null) {\n genConfig.stopSequences = stopSequences;\n }\n const hasGenConfig = Object.keys(genConfig).length > 0;\n\n return createRunner({\n fetch: fetchFn,\n hooks,\n buildRequest: (agent, _input, messages) => ({\n url: `${baseURL}/models/${agent.model ?? model}:generateContent`,\n init: {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-goog-api-key\": apiKey,\n },\n body: JSON.stringify({\n ...(agent.instructions\n ? { systemInstruction: { parts: [{ text: agent.instructions }] } }\n : {}),\n contents: messages.map((m) => ({\n role: m.role === \"assistant\" ? \"model\" : \"user\",\n parts: [{ text: m.content }],\n })),\n ...(hasGenConfig ? { generationConfig: genConfig } : {}),\n }),\n ...(timeoutMs != null\n ? { signal: AbortSignal.timeout(timeoutMs) }\n : {}),\n },\n }),\n parseResponse: async (res) => {\n const data = await res.json();\n const text = data.candidates?.[0]?.content?.parts?.[0]?.text ?? \"\";\n const inputTokens = data.usageMetadata?.promptTokenCount ?? 0;\n const outputTokens = data.usageMetadata?.candidatesTokenCount ?? 0;\n\n return {\n text,\n totalTokens: inputTokens + outputTokens,\n inputTokens,\n outputTokens,\n };\n },\n });\n}\n\n// ============================================================================\n// Gemini Streaming Runner\n// ============================================================================\n\n/** Options for createGeminiStreamingRunner */\nexport interface GeminiStreamingRunnerOptions {\n apiKey: string;\n model?: string;\n maxOutputTokens?: number;\n baseURL?: string;\n fetch?: typeof globalThis.fetch;\n /** Lifecycle hooks for tracing, logging, and metrics */\n hooks?: AdapterHooks;\n /** Sampling temperature. Higher = more random. */\n temperature?: number;\n /** Nucleus sampling: top-P probability mass (0–1). */\n topP?: number;\n /** Stop sequences. The model will stop generating when it encounters one. */\n stopSequences?: string[];\n}\n\n/**\n * Create a StreamingCallbackRunner for the Gemini streamGenerateContent API\n * with server-sent events. Can be used standalone or paired with `createGeminiRunner`.\n *\n * Returns `tokenUsage` with input/output breakdown for cost tracking.\n *\n * @example\n * ```typescript\n * const streamingRunner = createGeminiStreamingRunner({\n * apiKey: process.env.GEMINI_API_KEY!,\n * });\n * const streamRunner = createStreamingRunner(streamingRunner);\n * const { stream, result } = streamRunner(agent, input);\n * ```\n */\nexport function createGeminiStreamingRunner(\n options: GeminiStreamingRunnerOptions,\n): StreamingCallbackRunner {\n const {\n apiKey,\n model = \"gemini-2.0-flash\",\n maxOutputTokens,\n baseURL = \"https://generativelanguage.googleapis.com/v1beta\",\n fetch: fetchFn = globalThis.fetch,\n hooks,\n temperature,\n topP,\n stopSequences,\n } = options;\n\n validateBaseURL(baseURL);\n warnIfMissingApiKey(apiKey, \"createGeminiStreamingRunner\");\n\n const genConfig: Record<string, unknown> = {};\n if (maxOutputTokens != null) {\n genConfig.maxOutputTokens = maxOutputTokens;\n }\n if (temperature != null) {\n genConfig.temperature = temperature;\n }\n if (topP != null) {\n genConfig.topP = topP;\n }\n if (stopSequences != null) {\n genConfig.stopSequences = stopSequences;\n }\n const hasGenConfig = Object.keys(genConfig).length > 0;\n\n return async (agent, input, callbacks) => {\n const startTime = fireBeforeCallHook(hooks, agent, input);\n\n try {\n const response = await fetchFn(\n `${baseURL}/models/${agent.model ?? model}:streamGenerateContent?alt=sse`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-goog-api-key\": apiKey,\n },\n body: JSON.stringify({\n ...(agent.instructions\n ? { systemInstruction: { parts: [{ text: agent.instructions }] } }\n : {}),\n contents: [{ role: \"user\", parts: [{ text: input }] }],\n ...(hasGenConfig ? { generationConfig: genConfig } : {}),\n }),\n signal: callbacks.signal,\n },\n );\n\n if (!response.ok) {\n await throwStreamingHTTPError(response, \"Gemini\");\n }\n\n const reader = getSSEReader(response);\n\n const { fullText, inputTokens, outputTokens } = await parseSSEStream(\n reader,\n callbacks.onToken,\n (event) => {\n const result: {\n text?: string;\n inputTokens?: number;\n outputTokens?: number;\n } = {};\n\n const text = (\n (event.candidates as Array<Record<string, unknown>>)?.[0]\n ?.content as Record<string, unknown>\n )?.parts as Array<Record<string, unknown>> | undefined;\n const textVal = text?.[0]?.text;\n if (textVal) {\n result.text = textVal as string;\n }\n\n if (event.usageMetadata) {\n const meta = event.usageMetadata as Record<string, unknown>;\n if (meta.promptTokenCount !== undefined) {\n result.inputTokens = meta.promptTokenCount as number;\n }\n if (meta.candidatesTokenCount !== undefined) {\n result.outputTokens = meta.candidatesTokenCount as number;\n }\n }\n\n return result;\n },\n \"Gemini\",\n );\n\n const tokenUsage = { inputTokens, outputTokens };\n const totalTokens = inputTokens + outputTokens;\n\n callbacks.onMessage?.({ role: \"assistant\", content: fullText });\n fireAfterCallHook(\n hooks,\n agent,\n input,\n fullText,\n totalTokens,\n tokenUsage,\n startTime,\n );\n\n return buildStreamingResult(input, fullText, totalTokens, tokenUsage);\n } catch (err) {\n fireErrorHook(hooks, agent, input, err, startTime);\n\n throw err;\n }\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/adapters/gemini.ts"],"names":["GEMINI_PRICING","createGeminiRunner","options","apiKey","model","maxOutputTokens","baseURL","fetchFn","timeoutMs","hooks","temperature","topP","stopSequences","validateBaseURL","warnIfMissingApiKey","genConfig","hasGenConfig","createRunner","agent","_input","messages","m","res","data","text","inputTokens","outputTokens","createGeminiStreamingRunner","input","callbacks","startTime","fireBeforeCallHook","response","throwStreamingHTTPError","reader","getSSEReader","fullText","parseSSEStream","event","result","textVal","meta","tokenUsage","totalTokens","fireAfterCallHook","buildStreamingResult","err","fireErrorHook"],"mappings":"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","file":"gemini.js","sourcesContent":["/**\n * @directive-run/ai/gemini\n *\n * Google Gemini adapter for Directive AI. Provides runners for the\n * Gemini generateContent API, including streaming support.\n *\n * @example\n * ```typescript\n * import { createGeminiRunner, createGeminiStreamingRunner } from '@directive-run/ai/gemini';\n *\n * const runner = createGeminiRunner({ apiKey: process.env.GEMINI_API_KEY! });\n * ```\n */\n\nimport { createRunner, validateBaseURL } from \"../agent-utils.js\";\nimport type { AdapterHooks, AgentRunner } from \"../types.js\";\nimport type { StreamingCallbackRunner } from \"../types.js\";\nimport {\n buildStreamingResult,\n fireAfterCallHook,\n fireBeforeCallHook,\n fireErrorHook,\n getSSEReader,\n parseSSEStream,\n throwStreamingHTTPError,\n warnIfMissingApiKey,\n} from \"./shared.js\";\n\n// ============================================================================\n// Pricing Constants\n// ============================================================================\n\n/**\n * Gemini model pricing (USD per million tokens).\n *\n * Use with `estimateCost()` for per-call cost tracking:\n * ```typescript\n * import { estimateCost } from '@directive-run/ai';\n * import { GEMINI_PRICING } from '@directive-run/ai/gemini';\n *\n * const cost =\n * estimateCost(result.tokenUsage!.inputTokens, GEMINI_PRICING[\"gemini-2.0-flash\"].input) +\n * estimateCost(result.tokenUsage!.outputTokens, GEMINI_PRICING[\"gemini-2.0-flash\"].output);\n * ```\n *\n * **Note:** Pricing changes over time. These values are provided as a convenience\n * and may not reflect the latest rates. Always verify at https://ai.google.dev/pricing\n */\nexport const GEMINI_PRICING: Record<string, { input: number; output: number }> =\n {\n \"gemini-2.5-pro\": { input: 1.25, output: 10 },\n \"gemini-2.5-flash\": { input: 0.15, output: 0.6 },\n \"gemini-2.0-flash\": { input: 0.1, output: 0.4 },\n \"gemini-2.0-flash-lite\": { input: 0.025, output: 0.1 },\n };\n\n// ============================================================================\n// Gemini Runner\n// ============================================================================\n\n/** Options for createGeminiRunner */\nexport interface GeminiRunnerOptions {\n apiKey: string;\n model?: string;\n maxOutputTokens?: number;\n baseURL?: string;\n fetch?: typeof globalThis.fetch;\n /** @default undefined */\n timeoutMs?: number;\n /** Lifecycle hooks for tracing, logging, and metrics */\n hooks?: AdapterHooks;\n /** Sampling temperature. Higher = more random. */\n temperature?: number;\n /** Nucleus sampling: top-P probability mass (0–1). */\n topP?: number;\n /** Stop sequences. The model will stop generating when it encounters one. */\n stopSequences?: string[];\n}\n\n/**\n * Create an AgentRunner for the Google Gemini generateContent API.\n *\n * Returns `tokenUsage` with input/output breakdown for cost tracking.\n *\n * @example\n * ```typescript\n * const runner = createGeminiRunner({\n * apiKey: process.env.GEMINI_API_KEY!,\n * model: 'gemini-2.0-flash',\n * });\n * const orchestrator = createAgentOrchestrator({ runner });\n * const result = await orchestrator.run(agent, input);\n * ```\n */\nexport function createGeminiRunner(options: GeminiRunnerOptions): AgentRunner {\n const {\n apiKey,\n model = \"gemini-2.0-flash\",\n maxOutputTokens,\n baseURL = \"https://generativelanguage.googleapis.com/v1beta\",\n fetch: fetchFn = globalThis.fetch,\n timeoutMs,\n hooks,\n temperature,\n topP,\n stopSequences,\n } = options;\n\n validateBaseURL(baseURL);\n warnIfMissingApiKey(apiKey, \"createGeminiRunner\");\n\n const genConfig: Record<string, unknown> = {};\n if (maxOutputTokens != null) {\n genConfig.maxOutputTokens = maxOutputTokens;\n }\n if (temperature != null) {\n genConfig.temperature = temperature;\n }\n if (topP != null) {\n genConfig.topP = topP;\n }\n if (stopSequences != null) {\n genConfig.stopSequences = stopSequences;\n }\n const hasGenConfig = Object.keys(genConfig).length > 0;\n\n return createRunner({\n fetch: fetchFn,\n hooks,\n buildRequest: (agent, _input, messages) => ({\n url: `${baseURL}/models/${agent.model ?? model}:generateContent`,\n init: {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-goog-api-key\": apiKey,\n },\n body: JSON.stringify({\n ...(agent.instructions\n ? { systemInstruction: { parts: [{ text: agent.instructions }] } }\n : {}),\n contents: messages.map((m) => ({\n role: m.role === \"assistant\" ? \"model\" : \"user\",\n parts: [{ text: m.content }],\n })),\n ...(hasGenConfig ? { generationConfig: genConfig } : {}),\n }),\n ...(timeoutMs != null\n ? { signal: AbortSignal.timeout(timeoutMs) }\n : {}),\n },\n }),\n parseResponse: async (res) => {\n const data = await res.json();\n const text = data.candidates?.[0]?.content?.parts?.[0]?.text ?? \"\";\n const inputTokens = data.usageMetadata?.promptTokenCount ?? 0;\n const outputTokens = data.usageMetadata?.candidatesTokenCount ?? 0;\n\n return {\n text,\n totalTokens: inputTokens + outputTokens,\n inputTokens,\n outputTokens,\n };\n },\n });\n}\n\n// ============================================================================\n// Gemini Streaming Runner\n// ============================================================================\n\n/** Options for createGeminiStreamingRunner */\nexport interface GeminiStreamingRunnerOptions {\n apiKey: string;\n model?: string;\n maxOutputTokens?: number;\n baseURL?: string;\n fetch?: typeof globalThis.fetch;\n /** Lifecycle hooks for tracing, logging, and metrics */\n hooks?: AdapterHooks;\n /** Sampling temperature. Higher = more random. */\n temperature?: number;\n /** Nucleus sampling: top-P probability mass (0–1). */\n topP?: number;\n /** Stop sequences. The model will stop generating when it encounters one. */\n stopSequences?: string[];\n}\n\n/**\n * Create a StreamingCallbackRunner for the Gemini streamGenerateContent API\n * with server-sent events. Can be used standalone or paired with `createGeminiRunner`.\n *\n * Returns `tokenUsage` with input/output breakdown for cost tracking.\n *\n * @example\n * ```typescript\n * const streamingRunner = createGeminiStreamingRunner({\n * apiKey: process.env.GEMINI_API_KEY!,\n * });\n * const streamRunner = createStreamingRunner(streamingRunner);\n * const { stream, result } = streamRunner(agent, input);\n * ```\n */\nexport function createGeminiStreamingRunner(\n options: GeminiStreamingRunnerOptions,\n): StreamingCallbackRunner {\n const {\n apiKey,\n model = \"gemini-2.0-flash\",\n maxOutputTokens,\n baseURL = \"https://generativelanguage.googleapis.com/v1beta\",\n fetch: fetchFn = globalThis.fetch,\n hooks,\n temperature,\n topP,\n stopSequences,\n } = options;\n\n validateBaseURL(baseURL);\n warnIfMissingApiKey(apiKey, \"createGeminiStreamingRunner\");\n\n const genConfig: Record<string, unknown> = {};\n if (maxOutputTokens != null) {\n genConfig.maxOutputTokens = maxOutputTokens;\n }\n if (temperature != null) {\n genConfig.temperature = temperature;\n }\n if (topP != null) {\n genConfig.topP = topP;\n }\n if (stopSequences != null) {\n genConfig.stopSequences = stopSequences;\n }\n const hasGenConfig = Object.keys(genConfig).length > 0;\n\n return async (agent, input, callbacks) => {\n const startTime = fireBeforeCallHook(hooks, agent, input);\n\n try {\n const response = await fetchFn(\n `${baseURL}/models/${agent.model ?? model}:streamGenerateContent?alt=sse`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-goog-api-key\": apiKey,\n },\n body: JSON.stringify({\n ...(agent.instructions\n ? { systemInstruction: { parts: [{ text: agent.instructions }] } }\n : {}),\n contents: [{ role: \"user\", parts: [{ text: input }] }],\n ...(hasGenConfig ? { generationConfig: genConfig } : {}),\n }),\n signal: callbacks.signal,\n },\n );\n\n if (!response.ok) {\n await throwStreamingHTTPError(response, \"Gemini\");\n }\n\n const reader = getSSEReader(response);\n\n const { fullText, inputTokens, outputTokens } = await parseSSEStream(\n reader,\n callbacks.onToken,\n (event) => {\n const result: {\n text?: string;\n inputTokens?: number;\n outputTokens?: number;\n } = {};\n\n const text = (\n (event.candidates as Array<Record<string, unknown>>)?.[0]\n ?.content as Record<string, unknown>\n )?.parts as Array<Record<string, unknown>> | undefined;\n const textVal = text?.[0]?.text;\n if (textVal) {\n result.text = textVal as string;\n }\n\n if (event.usageMetadata) {\n const meta = event.usageMetadata as Record<string, unknown>;\n if (meta.promptTokenCount !== undefined) {\n result.inputTokens = meta.promptTokenCount as number;\n }\n if (meta.candidatesTokenCount !== undefined) {\n result.outputTokens = meta.candidatesTokenCount as number;\n }\n }\n\n return result;\n },\n \"Gemini\",\n );\n\n const tokenUsage = { inputTokens, outputTokens };\n const totalTokens = inputTokens + outputTokens;\n\n callbacks.onMessage?.({ role: \"assistant\", content: fullText });\n fireAfterCallHook(\n hooks,\n agent,\n input,\n fullText,\n totalTokens,\n tokenUsage,\n startTime,\n );\n\n return buildStreamingResult(input, fullText, totalTokens, tokenUsage);\n } catch (err) {\n fireErrorHook(hooks, agent, input, err, startTime);\n\n throw err;\n }\n };\n}\n"]}