@stacksjs/ai 0.70.23 → 0.70.26

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.
@@ -0,0 +1,175 @@
1
+ // @bun
2
+ var F=import.meta.require;var t=null;function zQ(Q){t=Q}function o(Q){let X={...t,...Q};if(!X.apiKey)X.apiKey=process.env.ANTHROPIC_API_KEY||"";return X}function S(Q){let{apiKey:X,model:Y="claude-sonnet-4-20250514",maxTokens:Z=4096,anthropicVersion:H="2023-06-01"}=Q;return{name:"Claude API",async process(W,J,V){if(!X)throw Error("Anthropic API key not set. Configure your API key in settings.");let G=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json","x-api-key":X,"anthropic-version":H},body:JSON.stringify({model:Y,max_tokens:Z,system:J,messages:[...V,{role:"user",content:W}]})});if(!G.ok){let j=await G.text();throw Error(`Claude API error: ${j}`)}let U=await G.json();if(!U.content||U.content.length===0)throw Error("Claude API returned empty content");return U.content[0].text},async*stream(W,J,V){if(!X)throw Error("Anthropic API key not set. Configure your API key in settings.");let G=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json","x-api-key":X,"anthropic-version":H},body:JSON.stringify({model:Y,max_tokens:Z,system:J,stream:!0,messages:[...V,{role:"user",content:W}]})});if(!G.ok){let q=await G.text();throw Error(`Claude API error: ${q}`)}let U=G.body?.getReader();if(!U)throw Error("No response body");let j=new TextDecoder,$="";while(!0){let{done:q,value:L}=await U.read();if(q)break;$+=j.decode(L,{stream:!0});let A=$.split(`
3
+ `);$=A.pop()||"";for(let B of A)if(B.startsWith("data: ")){let z=B.slice(6);if(z==="[DONE]")continue;try{let E=JSON.parse(z);if(E.type==="content_block_delta"&&E.delta?.text)yield E.delta.text}catch{}}}if($.startsWith("data: ")){let q=$.slice(6);if(q!=="[DONE]")try{let L=JSON.parse(q);if(L.type==="content_block_delta"&&L.delta?.text)yield L.delta.text}catch{}}}}}async function e(Q,X={}){let Y=o(),{model:Z="claude-sonnet-4-20250514",maxTokens:H=4096,temperature:W,topP:J,stop:V,system:G}=X,U=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json","x-api-key":Y.apiKey,"anthropic-version":Y.anthropicVersion||"2023-06-01"},body:JSON.stringify({model:Z,max_tokens:H,temperature:W,top_p:J,stop_sequences:V?Array.isArray(V)?V:[V]:void 0,system:G,messages:Q})});if(!U.ok){let $=await U.text();throw Error(`Claude API error: ${$}`)}let j=await U.json();if(!j.content||j.content.length===0)throw Error("Claude API returned empty content");return{content:j.content[0].text,model:j.model,usage:{promptTokens:j.usage?.input_tokens||0,completionTokens:j.usage?.output_tokens||0,totalTokens:(j.usage?.input_tokens||0)+(j.usage?.output_tokens||0)},finishReason:j.stop_reason}}async function*BQ(Q,X={}){let Y=o(),{model:Z="claude-sonnet-4-20250514",maxTokens:H=4096,temperature:W,topP:J,stop:V,system:G}=X,U=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json","x-api-key":Y.apiKey,"anthropic-version":Y.anthropicVersion||"2023-06-01"},body:JSON.stringify({model:Z,max_tokens:H,temperature:W,top_p:J,stop_sequences:V?Array.isArray(V)?V:[V]:void 0,system:G,stream:!0,messages:Q})});if(!U.ok){let L=await U.text();throw Error(`Claude API error: ${L}`)}let j=U.body?.getReader();if(!j)throw Error("No response body");let $=new TextDecoder,q="";while(!0){let{done:L,value:A}=await j.read();if(L)break;q+=$.decode(A,{stream:!0});let B=q.split(`
4
+ `);q=B.pop()||"";for(let z of B)if(z.startsWith("data: ")){let E=z.slice(6);if(E==="[DONE]")continue;try{let O=JSON.parse(E);if(O.type==="content_block_delta"&&O.delta?.text)yield O.delta.text}catch{}}}}async function EQ(Q,X={}){return(await e([{role:"user",content:Q}],X)).content}function QQ(Q){return Math.ceil(Q.length/4)}var LQ={create:S},AQ={configure:zQ,chat:e,streamChat:BQ,prompt:EQ,estimateTokens:QQ,createDriver:S};var XQ=null;function OQ(Q){XQ=Q}function D(Q){let X={...XQ,...Q};if(!X.apiKey)X.apiKey=process.env.OPENAI_API_KEY||"";return X}function P(Q){let{apiKey:X,model:Y="gpt-4o",maxTokens:Z=4096,baseUrl:H="https://api.openai.com/v1",embeddingModel:W="text-embedding-3-small"}=Q;return{name:"OpenAI",async process(J,V,G){if(!X)throw Error("OpenAI API key not set. Configure your API key in settings.");let U=await fetch(`${H}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${X}`},body:JSON.stringify({model:Y,max_tokens:Z,messages:[{role:"system",content:V},...G,{role:"user",content:J}]})});if(!U.ok){let $=await U.text();throw Error(`OpenAI API error: ${$}`)}let j=await U.json();if(!j.choices||j.choices.length===0)throw Error("OpenAI API returned empty choices");return j.choices[0].message.content},async*stream(J,V,G){if(!X)throw Error("OpenAI API key not set. Configure your API key in settings.");let U=await fetch(`${H}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${X}`},body:JSON.stringify({model:Y,max_tokens:Z,stream:!0,messages:[{role:"system",content:V},...G,{role:"user",content:J}]})});if(!U.ok){let L=await U.text();throw Error(`OpenAI API error: ${L}`)}let j=U.body?.getReader();if(!j)throw Error("No response body");let $=new TextDecoder,q="";while(!0){let{done:L,value:A}=await j.read();if(L)break;q+=$.decode(A,{stream:!0});let B=q.split(`
5
+ `);q=B.pop()||"";for(let z of B)if(z.startsWith("data: ")){let E=z.slice(6);if(E==="[DONE]")continue;try{let _=JSON.parse(E).choices[0]?.delta?.content;if(_)yield _}catch{}}}if(q.startsWith("data: ")){let L=q.slice(6);if(L!=="[DONE]")try{let B=JSON.parse(L).choices[0]?.delta?.content;if(B)yield B}catch{}}},async embed(J){if(!X)throw Error("OpenAI API key not set. Configure your API key in settings.");let V=await fetch(`${H}/embeddings`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${X}`},body:JSON.stringify({model:W,input:J})});if(!V.ok){let U=await V.text();throw Error(`OpenAI Embeddings API error: ${U}`)}let G=await V.json();if(Array.isArray(J))return G.data.map((U)=>U.embedding);return G.data[0].embedding}}}async function _Q(Q,X={}){let Y=D(),{model:Z="gpt-4o",maxTokens:H=4096,temperature:W,topP:J,stop:V}=X,G=await fetch(`${Y.baseUrl||"https://api.openai.com/v1"}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Y.apiKey}`},body:JSON.stringify({model:Z,max_tokens:H,temperature:W,top_p:J,stop:V,messages:Q})});if(!G.ok){let j=await G.text();throw Error(`OpenAI API error: ${j}`)}let U=await G.json();if(!U.choices||U.choices.length===0)throw Error("OpenAI API returned empty choices");return{content:U.choices[0].message.content,model:U.model,usage:{promptTokens:U.usage?.prompt_tokens||0,completionTokens:U.usage?.completion_tokens||0,totalTokens:U.usage?.total_tokens||0},finishReason:U.choices[0].finish_reason}}async function*RQ(Q,X={}){let Y=D(),{model:Z="gpt-4o",maxTokens:H=4096,temperature:W,topP:J,stop:V}=X,G=await fetch(`${Y.baseUrl||"https://api.openai.com/v1"}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Y.apiKey}`},body:JSON.stringify({model:Z,max_tokens:H,temperature:W,top_p:J,stop:V,stream:!0,messages:Q})});if(!G.ok){let q=await G.text();throw Error(`OpenAI API error: ${q}`)}let U=G.body?.getReader();if(!U)throw Error("No response body");let j=new TextDecoder,$="";while(!0){let{done:q,value:L}=await U.read();if(q)break;$+=j.decode(L,{stream:!0});let A=$.split(`
6
+ `);$=A.pop()||"";for(let B of A)if(B.startsWith("data: ")){let z=B.slice(6);if(z==="[DONE]")continue;try{let O=JSON.parse(z).choices[0]?.delta?.content;if(O)yield O}catch{}}}}async function FQ(Q,X="text-embedding-3-small"){let Y=D(),Z=await fetch(`${Y.baseUrl||"https://api.openai.com/v1"}/embeddings`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Y.apiKey}`},body:JSON.stringify({model:X,input:Q})});if(!Z.ok){let W=await Z.text();throw Error(`OpenAI Embeddings API error: ${W}`)}let H=await Z.json();if(Array.isArray(Q))return H.data.map((W)=>W.embedding);return H.data[0].embedding}async function NQ(Q,X={}){let Y=D(),{model:Z="dall-e-3",size:H="1024x1024",quality:W="standard",n:J=1,responseFormat:V="url"}=X,G=await fetch(`${Y.baseUrl||"https://api.openai.com/v1"}/images/generations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Y.apiKey}`},body:JSON.stringify({model:Z,prompt:Q,size:H,quality:W,n:J,response_format:V})});if(!G.ok){let j=await G.text();throw Error(`OpenAI Image API error: ${j}`)}return(await G.json()).data}async function wQ(Q,X={}){let Y=D(),Z=new FormData;if(Z.append("file",Q),Z.append("model",X.model||"whisper-1"),X.language)Z.append("language",X.language);if(X.prompt)Z.append("prompt",X.prompt);if(X.responseFormat)Z.append("response_format",X.responseFormat);if(X.temperature!==void 0)Z.append("temperature",String(X.temperature));let H=await fetch(`${Y.baseUrl||"https://api.openai.com/v1"}/audio/transcriptions`,{method:"POST",headers:{Authorization:`Bearer ${Y.apiKey}`},body:Z});if(!H.ok){let W=await H.text();throw Error(`OpenAI Whisper API error: ${W}`)}return H.json()}async function MQ(Q,X={}){let Y=D(),{model:Z="tts-1",voice:H="alloy",responseFormat:W="mp3",speed:J=1}=X,V=await fetch(`${Y.baseUrl||"https://api.openai.com/v1"}/audio/speech`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Y.apiKey}`},body:JSON.stringify({model:Z,input:Q,voice:H,response_format:W,speed:J})});if(!V.ok){let G=await V.text();throw Error(`OpenAI TTS API error: ${G}`)}return V.arrayBuffer()}var KQ={create:P},TQ={configure:OQ,chat:_Q,streamChat:RQ,embed:FQ,generateImage:NQ,transcribe:wQ,textToSpeech:MQ,createDriver:P};var v={};function DQ(Q){v={...v,...Q}}function M(Q){return{host:Q?.host||v.host||process.env.OLLAMA_HOST||"http://localhost:11434",model:Q?.model||v.model||process.env.OLLAMA_MODEL||"llama3.2",embeddingModel:Q?.embeddingModel||v.embeddingModel||"nomic-embed-text"}}function b(Q={}){let{host:X=process.env.OLLAMA_HOST||"http://localhost:11434",model:Y=process.env.OLLAMA_MODEL||"llama3.2",embeddingModel:Z="nomic-embed-text"}=Q;return{name:"Ollama",async process(H,W,J){let V=await fetch(`${X}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:Y,messages:[{role:"system",content:W},...J,{role:"user",content:H}],stream:!1})});if(!V.ok){let U=await V.text();throw Error(`Ollama API error: ${U}`)}return(await V.json()).message.content},async*stream(H,W,J){let V=await fetch(`${X}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:Y,messages:[{role:"system",content:W},...J,{role:"user",content:H}],stream:!0})});if(!V.ok){let $=await V.text();throw Error(`Ollama API error: ${$}`)}let G=V.body?.getReader();if(!G)throw Error("No response body");let U=new TextDecoder,j="";while(!0){let{done:$,value:q}=await G.read();if($)break;j+=U.decode(q,{stream:!0});let L=j.split(`
7
+ `);j=L.pop()||"";for(let A of L){if(!A.trim())continue;try{let B=JSON.parse(A);if(B.message?.content)yield B.message.content}catch{}}}},async embed(H){let W=Array.isArray(H)?H:[H],J=[];for(let V of W){let G=await fetch(`${X}/api/embeddings`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:Z,prompt:V})});if(!G.ok){let j=await G.text();throw Error(`Ollama Embeddings API error: ${j}`)}let U=await G.json();J.push(U.embedding)}return Array.isArray(H)?J:J[0]}}}async function IQ(Q,X={}){let Y=M(),{model:Z=Y.model,temperature:H,topP:W,stop:J}=X,V=await fetch(`${Y.host}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:Z,messages:Q,stream:!1,options:{temperature:H,top_p:W,stop:J}})});if(!V.ok){let U=await V.text();throw Error(`Ollama API error: ${U}`)}let G=await V.json();return{content:G.message.content,model:G.model,usage:{promptTokens:G.prompt_eval_count||0,completionTokens:G.eval_count||0,totalTokens:(G.prompt_eval_count||0)+(G.eval_count||0)},finishReason:G.done_reason||"stop"}}async function*xQ(Q,X={}){let Y=M(),{model:Z=Y.model,temperature:H,topP:W,stop:J}=X,V=await fetch(`${Y.host}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:Z,messages:Q,stream:!0,options:{temperature:H,top_p:W,stop:J}})});if(!V.ok){let $=await V.text();throw Error(`Ollama API error: ${$}`)}let G=V.body?.getReader();if(!G)throw Error("No response body");let U=new TextDecoder,j="";while(!0){let{done:$,value:q}=await G.read();if($)break;j+=U.decode(q,{stream:!0});let L=j.split(`
8
+ `);j=L.pop()||"";for(let A of L){if(!A.trim())continue;try{let B=JSON.parse(A);if(B.message?.content)yield B.message.content}catch{}}}}async function kQ(Q,X={}){let Y=M(),Z=await fetch(`${Y.host}/api/generate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:X.model||Y.model,prompt:Q,system:X.system,template:X.template,context:X.context,raw:X.raw,format:X.format,images:X.images,stream:!1})});if(!Z.ok){let W=await Z.text();throw Error(`Ollama API error: ${W}`)}let H=await Z.json();return{content:H.response,model:H.model,usage:{promptTokens:H.prompt_eval_count||0,completionTokens:H.eval_count||0,totalTokens:(H.prompt_eval_count||0)+(H.eval_count||0)}}}async function CQ(Q,X){let Y=M(),Z=X||Y.embeddingModel,H=Array.isArray(Q)?Q:[Q],W=[];for(let J of H){let V=await fetch(`${Y.host}/api/embeddings`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:Z,prompt:J})});if(!V.ok){let U=await V.text();throw Error(`Ollama Embeddings API error: ${U}`)}let G=await V.json();W.push(G.embedding)}return Array.isArray(Q)?W:W[0]}async function SQ(){let Q=M(),X=await fetch(`${Q.host}/api/tags`,{method:"GET"});if(!X.ok){let Z=await X.text();throw Error(`Ollama API error: ${Z}`)}return(await X.json()).models}async function PQ(Q,X){let Y=M(),Z=await fetch(`${Y.host}/api/pull`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:Q,stream:!0})});if(!Z.ok){let V=await Z.text();throw Error(`Ollama API error: ${V}`)}let H=Z.body?.getReader();if(!H)return;let W=new TextDecoder,J="";while(!0){let{done:V,value:G}=await H.read();if(V)break;J+=W.decode(G,{stream:!0});let U=J.split(`
9
+ `);J=U.pop()||"";for(let j of U){if(!j.trim())continue;try{let $=JSON.parse(j);if(X)X($.status,$.completed,$.total)}catch{}}}}async function vQ(Q){let X=M(),Y=await fetch(`${X.host}/api/delete`,{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:Q})});if(!Y.ok){let Z=await Y.text();throw Error(`Ollama API error: ${Z}`)}}async function bQ(Q){let X=M(),Y=await fetch(`${X.host}/api/show`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:Q})});if(!Y.ok){let Z=await Y.text();throw Error(`Ollama API error: ${Z}`)}return Y.json()}async function hQ(){let Q=M();try{return(await fetch(`${Q.host}/api/tags`,{method:"GET"})).ok}catch{return!1}}var yQ={create:b},fQ={configure:DQ,chat:IQ,streamChat:xQ,generate:kQ,embed:CQ,listModels:SQ,pullModel:PQ,deleteModel:vQ,showModel:bQ,isRunning:hQ,createDriver:b};var p=null;async function u(){if(!p)try{p=await import("@anthropic-ai/claude-agent-sdk")}catch{throw Error("Claude Agent SDK not installed. Run: bun add @anthropic-ai/claude-agent-sdk")}return p}var N={lastSessionId:void 0},I={maxTurns:25,allowedTools:["Read","Write","Edit","Bash","Glob","Grep"],permissionMode:"bypassPermissions"};function c(Q={}){let{maxTurns:X=I.maxTurns,cwd:Y,allowedTools:Z=I.allowedTools,disallowedTools:H,permissionMode:W=I.permissionMode,customSystemPrompt:J,appendSystemPrompt:V,resumeSessionId:G}=Q;return{name:"Claude Agent SDK",async process(U,j,$){let q=await u(),{query:L}=q,A=j?`${j}
10
+
11
+ User request: ${U}`:U,B={allowedTools:Z,permissionMode:W,maxTurns:X};if(H)B.disallowedTools=H;if(J)B.customSystemPrompt=J;if(V)B.appendSystemPrompt=V;if(Y)B.cwd=Y;if(G||N.lastSessionId)B.resume=G||N.lastSessionId;let z="";try{for await(let E of L({prompt:A,options:B})){if(E.type==="system"&&E.subtype==="init")N.lastSessionId=E.session_id;if("result"in E&&typeof E.result==="string")z=E.result}return z||"No response from Claude Agent SDK"}catch(E){let O=E;if(O.message.includes("ANTHROPIC_API_KEY"))throw Error("Claude Agent SDK requires ANTHROPIC_API_KEY environment variable or Claude Code authentication.");throw Error(`Claude Agent SDK error: ${O.message}`)}},async*stream(U,j,$){let q=await u(),{query:L}=q,A=j?`${j}
12
+
13
+ User request: ${U}`:U,B={allowedTools:Z,permissionMode:W,maxTurns:X};if(H)B.disallowedTools=H;if(J)B.customSystemPrompt=J;if(V)B.appendSystemPrompt=V;if(Y)B.cwd=Y;if(G||N.lastSessionId)B.resume=G||N.lastSessionId;try{for await(let z of L({prompt:A,options:B})){if(z.type==="system"&&z.subtype==="init")N.lastSessionId=z.session_id;if(z.type==="assistant"){let E=z;if(E.message?.content){for(let O of E.message.content)if(O.type==="text"&&O.text)yield O.text}}if("result"in z&&typeof z.result==="string")yield z.result}}catch(z){let E=z;if(E.message.includes("ANTHROPIC_API_KEY"))throw Error("Claude Agent SDK requires ANTHROPIC_API_KEY environment variable or Claude Code authentication.");throw Error(`Claude Agent SDK error: ${E.message}`)}}}}async function gQ(Q,X,Y={}){let Z=await u(),{query:H}=Z,{maxTurns:W=I.maxTurns,allowedTools:J=I.allowedTools,disallowedTools:V,permissionMode:G=I.permissionMode,customSystemPrompt:U,appendSystemPrompt:j,resumeSessionId:$}=Y,q={allowedTools:J,permissionMode:G,maxTurns:W};if(V)q.disallowedTools=V;if(U)q.customSystemPrompt=U;if(j)q.appendSystemPrompt=j;if(X)q.cwd=X;if($||N.lastSessionId)q.resume=$||N.lastSessionId;let L=new TextEncoder,A="",B,z=new Promise((O)=>{B=O});return{stream:new ReadableStream({async start(O){try{for await(let _ of H({prompt:Q,options:q})){if(_.type==="system"&&_.subtype==="init")N.lastSessionId=_.session_id;if(_.type==="assistant"){let C=_;if(C.message?.content){for(let g of C.message.content)if(g.type==="text"&&g.text)A+=g.text,O.enqueue(L.encode(g.text))}}if("result"in _&&typeof _.result==="string"){if(!A)A=_.result,O.enqueue(L.encode(_.result))}}B(A),O.close()}catch(_){B(A),O.error(_)}}}),fullResponse:z}}async function uQ(Q,X){let Y=await u(),{query:Z}=Y,H="";for await(let W of Z({prompt:X,options:{resume:Q,permissionMode:"bypassPermissions"}}))if("result"in W&&typeof W.result==="string")H=W.result;return H||"No response from resumed session"}function YQ(){return N.lastSessionId}function ZQ(){N.lastSessionId=void 0}var cQ={createDriver:c,processStreaming:gQ,resumeSession:uQ,getLastSessionId:YQ,clearSession:ZQ};var HQ=0;function lQ(Q,X){switch(Q){case"Read":{let Y=X.file_path||"";return`
14
+ \uD83D\uDCD6 Reading: ${Y.split("/").pop()||Y}
15
+ `}case"Glob":return`
16
+ \uD83D\uDD0D Searching files: ${X.pattern||""}
17
+ `;case"Grep":return`
18
+ \uD83D\uDD0E Searching for: "${X.pattern||""}"
19
+ `;case"Edit":{let Y=X.file_path||"";return`
20
+ \u270F\uFE0F Editing: ${Y.split("/").pop()||Y}
21
+ `}case"Write":{let Y=X.file_path||"";return`
22
+ \uD83D\uDCDD Writing: ${Y.split("/").pop()||Y}
23
+ `}case"Bash":{let Y=(X.command||"").substring(0,50);return`
24
+ \uD83D\uDCBB Running: ${Y}${Y.length>=50?"...":""}
25
+ `}case"Task":return`
26
+ \uD83D\uDE80 Launching agent: ${X.description||"task"}
27
+ `;default:return`
28
+ \uD83D\uDD27 Using: ${Q}
29
+ `}}function dQ(Q={}){return{name:"Claude CLI (Local)",async process(X,Y,Z){let{$:H}=awaitPromise.resolve(globalThis.Bun);if((await H`which claude`.quiet().nothrow()).exitCode!==0)throw Error("Claude CLI not found. Install it with: npm install -g @anthropic-ai/claude-code");let J=Y?`Context:
30
+ ${Y}
31
+
32
+ User request: ${X}`:X,V=Q.cwd||process.cwd();try{return(await H`cd ${V} && claude --print --dangerously-skip-permissions ${J}`.quiet()).text().trim()}catch{try{return(await H`cd ${V} && claude --print --allowedTools "Write,Edit,Bash" ${J}`.quiet()).text().trim()}catch(G){throw Error(`Claude CLI error: ${G.message}`)}}}}}function mQ(Q){let{ec2Host:X=process.env.BUDDY_EC2_HOST,ec2User:Y=process.env.BUDDY_EC2_USER||"ubuntu",ec2Key:Z=process.env.BUDDY_EC2_KEY}=Q;return{name:"Claude CLI (EC2)",async process(H,W,J){let{$:V}=awaitPromise.resolve(globalThis.Bun);if(!X)throw Error("BUDDY_EC2_HOST environment variable not set. Set it to your EC2 instance IP/hostname.");let U=(W?`Context:
33
+ ${W}
34
+
35
+ User request: ${H}`:H).replace(/'/g,"'\\''"),j=Z?`-i ${Z}`:"",$=`${Y}@${X}`;try{return(await V`ssh ${j} ${$} "claude --print '${U}'"`.quiet()).text().trim()}catch(q){throw Error(`EC2 Claude CLI error: ${q.message}. Make sure SSH is configured and claude CLI is installed on EC2.`)}}}}async function pQ(Q,X){let{spawn:Y}=awaitPromise.resolve(globalThis.Bun),Z=Y(["claude","--print","--verbose","--output-format","stream-json","--dangerously-skip-permissions",Q],{cwd:X,stdout:"pipe",stderr:"pipe"}),H="",W=new TextDecoder,J=new TextEncoder,V=new ReadableStream({async start(U){try{let j=Z.stdout.getReader(),$="",q="",L=await j.read();while(!L.done){$+=W.decode(L.value,{stream:!0});let A=$.split(`
36
+ `);$=A.pop()||"";for(let B of A){if(!B.trim())continue;try{let z=JSON.parse(B),E="";if(z.type==="system"&&z.subtype==="init")HQ++;else if(z.type==="content_block_start"&&z.content_block?.text)E=z.content_block.text;else if(z.type==="content_block_delta"&&z.delta?.text)E=z.delta.text;else if(z.type==="assistant"&&z.message?.content){for(let O of z.message.content)if(O.type==="text"&&O.text)E+=O.text;else if(O.type==="tool_use"&&O.name)E+=lQ(O.name,O.input||{})}else if(z.type==="user"&&z.message?.content){for(let O of z.message.content)if(O.type==="tool_result")E+=` \u2713 done
37
+ `}else if(z.type==="result"&&z.result){H=z.result;let O=z.result.substring(0,Math.min(50,z.result.length));if(!q.includes(O))E=z.result}if(E){if(z.type==="content_block_delta")q+=E,U.enqueue(J.encode(E));else if(!q.endsWith(E))q+=E,U.enqueue(J.encode(E))}}catch{if(!q.includes(B))q+=B,H+=B,U.enqueue(J.encode(B))}}L=await j.read()}if($.trim())try{let A=JSON.parse($);if(A.result&&!H)H=A.result}catch{if(!q.includes($))H+=$,U.enqueue(J.encode($))}await Z.exited,U.close()}catch(j){U.error(j)}}}),G=(async()=>{return await Z.exited,H.trim()})();return{stream:V,fullResponse:G}}function iQ(){HQ=0}var l={createLocal:dQ,createEC2:mQ,processStreaming:pQ,resetPromptCount:iQ};import{existsSync as T,mkdirSync as VQ,readFileSync as JQ,writeFileSync as aQ}from"fs";import{homedir as WQ}from"os";import{dirname as rQ,join as x}from"path";var k={workDir:x(WQ(),"Code",".buddy-repos"),commitMessage:"chore: wip",ollamaHost:process.env.OLLAMA_HOST||"http://localhost:11434",ollamaModel:process.env.OLLAMA_MODEL||"llama3.2"},K={anthropic:process.env.ANTHROPIC_API_KEY,openai:process.env.OPENAI_API_KEY,claudeCliHost:process.env.BUDDY_EC2_HOST},w={repo:null,conversationHistory:[],currentDriver:"claude-cli-local",github:null};if(!T(k.workDir))VQ(k.workDir,{recursive:!0});var R={getState:()=>w,setRepo:(Q)=>{w.repo=Q},setCurrentDriver:(Q)=>{w.currentDriver=Q},setGitHub:(Q)=>{w.github=Q},addToHistory:(Q)=>{w.conversationHistory.push(Q)},clearHistory:()=>{w.conversationHistory=[]}};function nQ(Q){return`You are Buddy, an AI code assistant that helps users modify codebases through voice commands.
38
+
39
+ ${w.repo?`You are working on the repository: ${w.repo.name}
40
+ Branch: ${w.repo.branch}
41
+ Path: ${w.repo.path}
42
+
43
+ ${Q}`:"No repository is currently open."}
44
+
45
+ When the user gives you a command:
46
+ 1. Analyze what they want to do
47
+ 2. Identify the files that need to be modified
48
+ 3. Generate the exact code changes needed
49
+ 4. Respond with a structured format showing:
50
+ - Summary of changes
51
+ - Files to modify/create with full content
52
+ - Any additional notes
53
+
54
+ Format file changes as:
55
+ FILE: path/to/file.ts
56
+ \`\`\`typescript
57
+ // Full file content
58
+ \`\`\`
59
+
60
+ Be concise but thorough. The user will review and commit your changes.`}function sQ(){return{name:"Mock",async process(Q){await new Promise((Y)=>setTimeout(Y,1000));let X=Q.toLowerCase();if(X.includes("readme")||X.includes("documentation"))return`I'll update the README.md file for you.
61
+
62
+ Analyzing the repository structure...
63
+
64
+ FILE: README.md
65
+ \`\`\`markdown
66
+ # Project Name
67
+
68
+ ## Installation
69
+
70
+ \`\`\`bash
71
+ npm install
72
+ # or
73
+ bun install
74
+ \`\`\`
75
+
76
+ ## Usage
77
+
78
+ \`\`\`bash
79
+ npm run start
80
+ \`\`\`
81
+ \`\`\`
82
+
83
+ File modified: README.md
84
+ Lines added: 12`;if(X.includes("fix")||X.includes("bug"))return`I'll analyze and fix the issue.
85
+
86
+ Scanning for potential bugs...
87
+
88
+ FILE: src/utils.ts
89
+ \`\`\`typescript
90
+ export function getData(data: { value?: string }) {
91
+ return data?.value ?? 'default';
92
+ }
93
+ \`\`\`
94
+
95
+ Files modified: src/utils.ts
96
+ Lines changed: 4`;return`I understand you want to: "${Q}"
97
+
98
+ I'll analyze the repository and implement this change.
99
+
100
+ FILE: src/main.ts
101
+ \`\`\`typescript
102
+ // Updated based on your request
103
+ export function main() {
104
+ console.log('Changes applied');
105
+ }
106
+ \`\`\`
107
+
108
+ Files modified: 1`}}}function tQ(Q){let X=R.getState();switch(Q){case"claude-cli-local":return l.createLocal({cwd:X.repo?.path});case"claude-cli-ec2":return l.createEC2({cwd:X.repo?.path,ec2Host:K.claudeCliHost});case"claude":case"anthropic":if(!K.anthropic)throw Error("Anthropic API key not set. Configure your API key in settings.");return S({apiKey:K.anthropic});case"openai":if(!K.openai)throw Error("OpenAI API key not set. Configure your API key in settings.");return P({apiKey:K.openai});case"ollama":return b({host:k.ollamaHost,model:k.ollamaModel});case"claude-sdk":case"claude-agent-sdk":return c({cwd:X.repo?.path,maxTurns:25,permissionMode:"bypassPermissions"});case"mock":return sQ();default:throw Error(`Unknown driver: ${Q}. Available: claude-cli-local, claude-cli-ec2, claude, claude-sdk, openai, ollama, mock`)}}function tX(){return["claude-cli-local","claude-cli-ec2","claude","claude-sdk","openai","ollama","mock"]}async function oQ(Q){let{$:X}=awaitPromise.resolve(globalThis.Bun),Z=(await X`cd ${Q} && find . -type f -not -path "*/node_modules/*" -not -path "*/.git/*" -not -name "*.lock" | head -50`.quiet()).text().trim(),H="",W=x(Q,"README.md");if(T(W))H=JQ(W,"utf-8").slice(0,2000);let J="",V=x(Q,"package.json");if(T(V))J=JQ(V,"utf-8");return`
109
+ Repository Structure:
110
+ ${Z}
111
+
112
+ ${H?`README.md (excerpt):
113
+ ${H}
114
+ `:""}
115
+ ${J?`package.json:
116
+ ${J}
117
+ `:""}
118
+ `.trim()}async function oX(Q){let{$:X}=awaitPromise.resolve(globalThis.Bun),Y,Z;if(Q.includes("github.com")||Q.startsWith("git@"))if(Z=Q.split("/").pop()?.replace(".git","")||"repo",Y=x(k.workDir,Z),T(Y))await X`cd ${Y} && git pull --rebase`.quiet();else await X`git clone ${Q} ${Y}`.quiet();else{if(Y=Q.startsWith("~")?Q.replace("~",WQ()):Q,!T(Y))throw Error(`Local path does not exist: ${Y}`);if(!T(x(Y,".git")))throw Error(`Not a git repository: ${Y}`);Z=Y.split("/").pop()||"repo"}let W=(await X`cd ${Y} && git branch --show-current`.quiet()).text().trim(),V=(await X`cd ${Y} && git status --porcelain`.quiet()).text().trim().length>0,U=(await X`cd ${Y} && git log -1 --format="%h %s"`.quiet()).text().trim(),j={path:Y,name:Z,branch:W,hasChanges:V,lastCommit:U};return R.setRepo(j),R.clearHistory(),j}async function eX(Q){let X=R.getState();if(!X.repo)throw Error("No repository opened");let Y=[],Z=/FILE:\s*([^\n]+)\n```\w*\n([\s\S]*?)```/g;for(let H of Q.matchAll(Z)){let W=H[1].trim(),J=H[2],V=x(X.repo.path,W),G=rQ(V);if(!T(G))VQ(G,{recursive:!0});aQ(V,J),Y.push(W)}if(Y.length>0&&X.repo)X.repo.hasChanges=!0;return Y}async function eQ(){let Q=R.getState();if(!Q.repo||!Q.github)return;let{$:X}=awaitPromise.resolve(globalThis.Bun),{name:Y,email:Z}=Q.github;await X`cd ${Q.repo.path} && git config user.name ${Y}`.quiet(),await X`cd ${Q.repo.path} && git config user.email ${Z}`.quiet()}async function QY(){let Q=R.getState();if(!Q.repo)throw Error("No repository opened");let{$:X}=awaitPromise.resolve(globalThis.Bun);if(Q.github)await eQ();await X`cd ${Q.repo.path} && git add -A`.quiet(),await X`cd ${Q.repo.path} && git commit -m ${k.commitMessage}`.quiet();let Z=(await X`cd ${Q.repo.path} && git rev-parse --short HEAD`.quiet()).text().trim();return Q.repo.hasChanges=!1,Q.repo.lastCommit=Z,Z}async function XY(){let Q=R.getState();if(!Q.repo)throw Error("No repository opened");let{$:X}=awaitPromise.resolve(globalThis.Bun);await X`cd ${Q.repo.path} && git push`.quiet()}async function YY(Q,X){let Y=R.getState();if(!Y.repo)throw Error("No repository opened");let Z=X||Y.currentDriver,H=tQ(Z);if(X)R.setCurrentDriver(X);let W=await oQ(Y.repo.path),J=nQ(W),V=await H.process(Q,J,Y.conversationHistory);return R.addToHistory({role:"user",content:Q}),R.addToHistory({role:"assistant",content:V}),V}async function ZY(Q,X,Y){let Z=R.getState();if(!Z.repo)throw Error("No repository opened");let H=X||Z.currentDriver,W=["claude-cli-local","claude-sdk"];if(!W.includes(H))throw Error(`Streaming only supported for ${W.join(", ")} drivers. Current: ${H}`);if(X)R.setCurrentDriver(X);let J=Q;if(Y&&Y.length>0){let G=`## Previous Conversation
119
+ Here is our conversation so far:
120
+
121
+ `;for(let U of Y){let j=U.role==="user"?"User":"Assistant";G+=`**${j}:** ${U.content}
122
+
123
+ `}G+=`---
124
+
125
+ ## Current Request
126
+ `,J=G+Q}let V=await l.processStreaming(J,Z.repo.path);return V.fullResponse.then((G)=>{R.addToHistory({role:"user",content:Q}),R.addToHistory({role:"assistant",content:G})}),V}async function HY(Q,X){if(!K.anthropic)throw Error("Anthropic API key not set. Configure your API key in settings.");let Y=[];if(X&&X.length>0)for(let U of X)Y.push({role:U.role,content:U.content});Y.push({role:"user",content:Q});let Z=`You are a helpful AI assistant. Answer questions naturally and conversationally.
127
+ You can discuss any topic - technology, science, philosophy, everyday questions, or anything else the user asks about.
128
+ Be concise but thorough. If the user asks about coding or their project specifically, help with that too.`,H=new TextEncoder,W="",J,V=new Promise((U)=>{J=U});return{stream:new ReadableStream({async start(U){try{let j=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json","x-api-key":K.anthropic,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:"claude-sonnet-4-20250514",max_tokens:4096,system:Z,stream:!0,messages:Y})});if(!j.ok){let A=await j.text();throw Error(`Claude API error: ${A}`)}let $=j.body?.getReader();if(!$)throw Error("No response body");let q=new TextDecoder,L="";while(!0){let{done:A,value:B}=await $.read();if(A)break;L+=q.decode(B,{stream:!0});let z=L.split(`
129
+ `);L=z.pop()||"";for(let E of z)if(E.startsWith("data: ")){let O=E.slice(6);if(O==="[DONE]")continue;try{let _=JSON.parse(O);if(_.type==="content_block_delta"&&_.delta?.text){let C=_.delta.text;W+=C,U.enqueue(H.encode(C))}}catch{}}}R.addToHistory({role:"user",content:Q}),R.addToHistory({role:"assistant",content:W}),J(W),U.close()}catch(j){J(W),U.error(j)}}}),fullResponse:V}}import QX from"process";var d=null;async function GQ(){if(d)return d;let Q=await import("@stacksjs/ts-cloud/aws");if(!Q?.BedrockRuntimeClient)throw Error("@stacksjs/ts-cloud/aws does not export BedrockRuntimeClient \u2014 rebuild ts-cloud or remove the AI dependency.");return d=new Q.BedrockRuntimeClient(QX.env.REGION||"us-east-1"),d}async function i(Q){return(await GQ()).invokeModel(Q)}async function WY(Q){return(await GQ()).invokeModelWithResponseStream(Q)}var XX="amazon.titan-text-express-v1";function UQ(Q){if(Q)return Q;return globalThis.config?.ai?.bedrock?.model||process.env.BEDROCK_MODEL_ID||XX}async function jY(Q,X={}){let{maxTokenCount:Y=512,temperature:Z=0,topP:H=0.9,modelId:W}=X;try{let J=await i({modelId:UQ(W),contentType:"application/json",accept:"*/*",body:JSON.stringify({inputText:`Summarize the following text: ${Q}`,textGenerationConfig:{maxTokenCount:Y,stopSequences:[],temperature:Z,topP:H}})});return JSON.parse(new TextDecoder().decode(J.body)).results[0].outputText}catch(J){throw Error(`Error summarizing text: ${J.message}`)}}async function $Y(Q,X={}){let{maxTokenCount:Y=512,temperature:Z=0,topP:H=0.9,modelId:W}=X;try{let J=await i({modelId:UQ(W),contentType:"application/json",accept:"*/*",body:JSON.stringify({inputText:Q,textGenerationConfig:{maxTokenCount:Y,stopSequences:[],temperature:Z,topP:H}})});return JSON.parse(new TextDecoder().decode(J.body)).results[0].outputText}catch(J){throw Error(`Error asking question: ${J.message}`)}}async function YX(Q,X={}){let{provider:Y="openai",model:Z="dall-e-3",size:H="1024x1024",quality:W="standard",n:J=1,responseFormat:V="url",style:G="vivid"}=X;if(Y==="openai")return ZX(Q,{model:Z,size:H,quality:W,n:J,responseFormat:V,style:G});throw Error(`Image generation not supported for provider: ${Y}. Use 'openai'.`)}async function ZX(Q,X){let Y=process.env.OPENAI_API_KEY;if(!Y)throw Error("OPENAI_API_KEY environment variable is required for image generation.");let Z=await fetch("https://api.openai.com/v1/images/generations",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Y}`},body:JSON.stringify({model:X.model,prompt:Q,size:X.size,quality:X.quality,n:X.n,response_format:X.responseFormat,style:X.style})});if(!Z.ok){let W=await Z.text();throw Error(`OpenAI Image API error: ${W}`)}return{images:(await Z.json()).data.map((W)=>({url:W.url,b64_json:W.b64_json,revisedPrompt:W.revised_prompt})),provider:"openai",model:X.model}}async function HX(Q,X,Y={}){let Z=process.env.OPENAI_API_KEY;if(!Z)throw Error("OPENAI_API_KEY environment variable is required for image editing.");let H=new FormData;if(H.append("image",Q),H.append("prompt",X),H.append("model",Y.model||"dall-e-2"),Y.mask)H.append("mask",Y.mask);if(Y.n)H.append("n",String(Y.n));if(Y.size)H.append("size",Y.size);if(Y.responseFormat)H.append("response_format",Y.responseFormat);let W=await fetch("https://api.openai.com/v1/images/edits",{method:"POST",headers:{Authorization:`Bearer ${Z}`},body:H});if(!W.ok){let V=await W.text();throw Error(`OpenAI Image Edit API error: ${V}`)}return{images:(await W.json()).data.map((V)=>({url:V.url,b64_json:V.b64_json})),provider:"openai",model:Y.model||"dall-e-2"}}async function JX(Q,X={}){let Y=process.env.OPENAI_API_KEY;if(!Y)throw Error("OPENAI_API_KEY environment variable is required for image variations.");let Z=new FormData;if(Z.append("image",Q),Z.append("model",X.model||"dall-e-2"),X.n)Z.append("n",String(X.n));if(X.size)Z.append("size",X.size);if(X.responseFormat)Z.append("response_format",X.responseFormat);let H=await fetch("https://api.openai.com/v1/images/variations",{method:"POST",headers:{Authorization:`Bearer ${Y}`},body:Z});if(!H.ok){let J=await H.text();throw Error(`OpenAI Image Variations API error: ${J}`)}return{images:(await H.json()).data.map((J)=>({url:J.url,b64_json:J.b64_json})),provider:"openai",model:X.model||"dall-e-2"}}async function VX(Q,X,Y={}){let{provider:Z="anthropic"}=Y;switch(Z){case"anthropic":return WX(Q,X,Y);case"openai":return GX(Q,X,Y);case"ollama":return UX(Q,X,Y);default:throw Error(`Vision not supported for provider: ${Z}`)}}async function h(Q){if(Q.type==="base64")return{data:Q.data,mediaType:Q.mediaType};if(Q.type==="url"){let X=await fetch(Q.url);if(!X.ok)throw Error(`Failed to fetch image from URL: ${Q.url}`);let Y=await X.arrayBuffer(),Z=Buffer.from(Y).toString("base64"),H=X.headers.get("content-type")||"image/png";return{data:Z,mediaType:H}}if(Q.type==="file"){let{readFile:X}=await import("fs/promises"),Z=(await X(Q.path)).toString("base64"),H=Q.path.split(".").pop()?.toLowerCase()||"png";return{data:Z,mediaType:{png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp"}[H]||"image/png"}}throw Error("Invalid image input type")}async function WX(Q,X,Y){let Z=process.env.ANTHROPIC_API_KEY;if(!Z)throw Error("ANTHROPIC_API_KEY environment variable is required for Claude vision.");let{data:H,mediaType:W}=await h(Q),J=Y.model||"claude-sonnet-4-20250514",V=Y.maxTokens||4096,G=[{role:"user",content:[{type:"image",source:{type:"base64",media_type:W,data:H}},{type:"text",text:X}]}],U=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json","x-api-key":Z,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:J,max_tokens:V,temperature:Y.temperature,messages:G})});if(!U.ok){let $=await U.text();throw Error(`Claude Vision API error: ${$}`)}let j=await U.json();return{content:j.content[0].text,model:j.model,provider:"anthropic",usage:{promptTokens:j.usage?.input_tokens||0,completionTokens:j.usage?.output_tokens||0,totalTokens:(j.usage?.input_tokens||0)+(j.usage?.output_tokens||0)},finishReason:j.stop_reason}}async function GX(Q,X,Y){let Z=process.env.OPENAI_API_KEY;if(!Z)throw Error("OPENAI_API_KEY environment variable is required for GPT-4 vision.");let H=Y.model||"gpt-4o",W=Y.maxTokens||4096,J=Y.detail||"auto",V;if(Q.type==="url")V={type:"image_url",image_url:{url:Q.url,detail:J}};else{let{data:j,mediaType:$}=await h(Q);V={type:"image_url",image_url:{url:`data:${$};base64,${j}`,detail:J}}}let G=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Z}`},body:JSON.stringify({model:H,max_tokens:W,temperature:Y.temperature,messages:[{role:"user",content:[V,{type:"text",text:X}]}]})});if(!G.ok){let j=await G.text();throw Error(`OpenAI Vision API error: ${j}`)}let U=await G.json();return{content:U.choices[0].message.content,model:U.model,provider:"openai",usage:{promptTokens:U.usage?.prompt_tokens||0,completionTokens:U.usage?.completion_tokens||0,totalTokens:U.usage?.total_tokens||0},finishReason:U.choices[0].finish_reason}}async function UX(Q,X,Y){let Z=process.env.OLLAMA_HOST||"http://localhost:11434",H=Y.model||"llava",{data:W}=await h(Q),J=await fetch(`${Z}/api/generate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:H,prompt:X,images:[W],stream:!1})});if(!J.ok){let G=await J.text();throw Error(`Ollama Vision API error: ${G}`)}let V=await J.json();return{content:V.response,model:V.model,provider:"ollama",usage:{promptTokens:V.prompt_eval_count||0,completionTokens:V.eval_count||0,totalTokens:(V.prompt_eval_count||0)+(V.eval_count||0)}}}async function jX(Q,X,Y={}){let{provider:Z="anthropic"}=Y;if(Z==="anthropic"){let H=process.env.ANTHROPIC_API_KEY;if(!H)throw Error("ANTHROPIC_API_KEY required for multi-image analysis.");let W=Y.model||"claude-sonnet-4-20250514",J=[];for(let U of Q){let{data:j,mediaType:$}=await h(U);J.push({type:"image",source:{type:"base64",media_type:$,data:j}})}J.push({type:"text",text:X});let V=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json","x-api-key":H,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:W,max_tokens:Y.maxTokens||4096,temperature:Y.temperature,messages:[{role:"user",content:J}]})});if(!V.ok){let U=await V.text();throw Error(`Claude Vision API error: ${U}`)}let G=await V.json();return{content:G.content[0].text,model:G.model,provider:"anthropic",usage:{promptTokens:G.usage?.input_tokens||0,completionTokens:G.usage?.output_tokens||0,totalTokens:(G.usage?.input_tokens||0)+(G.usage?.output_tokens||0)},finishReason:G.stop_reason}}if(Z==="openai"){let H=process.env.OPENAI_API_KEY;if(!H)throw Error("OPENAI_API_KEY required for multi-image analysis.");let W=Y.model||"gpt-4o",J=Y.detail||"auto",V=[];for(let j of Q)if(j.type==="url")V.push({type:"image_url",image_url:{url:j.url,detail:J}});else{let{data:$,mediaType:q}=await h(j);V.push({type:"image_url",image_url:{url:`data:${q};base64,${$}`,detail:J}})}V.push({type:"text",text:X});let G=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${H}`},body:JSON.stringify({model:W,max_tokens:Y.maxTokens||4096,temperature:Y.temperature,messages:[{role:"user",content:V}]})});if(!G.ok){let j=await G.text();throw Error(`OpenAI Vision API error: ${j}`)}let U=await G.json();return{content:U.choices[0].message.content,model:U.model,provider:"openai",usage:{promptTokens:U.usage?.prompt_tokens||0,completionTokens:U.usage?.completion_tokens||0,totalTokens:U.usage?.total_tokens||0},finishReason:U.choices[0].finish_reason}}throw Error(`Multi-image analysis not supported for provider: ${Z}`)}var zY={generate:YX,edit:HX,variation:JX,analyze:VX,analyzeMultiple:jX};async function a(Q,X={}){let{provider:Y="openai"}=X;if(Y==="openai")return $X(Q,X.model||"text-embedding-3-small");if(Y==="ollama")return qX(Q,X.model||"nomic-embed-text");throw Error(`Embedding provider not supported: ${Y}`)}async function $X(Q,X){let Y=process.env.OPENAI_API_KEY;if(!Y)throw Error("OPENAI_API_KEY environment variable is required for embeddings.");let Z=await fetch("https://api.openai.com/v1/embeddings",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Y}`},body:JSON.stringify({model:X,input:Q})});if(!Z.ok){let W=await Z.text();throw Error(`OpenAI Embeddings API error: ${W}`)}let H=await Z.json();if(Array.isArray(Q))return H.data.map((W)=>W.embedding);return H.data[0].embedding}async function qX(Q,X){let Y=process.env.OLLAMA_HOST||"http://localhost:11434",Z=Array.isArray(Q)?Q:[Q],H=[];for(let W of Z){let J=await fetch(`${Y}/api/embeddings`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:X,prompt:W})});if(!J.ok){let G=await J.text();throw Error(`Ollama Embeddings API error: ${G}`)}let V=await J.json();H.push(V.embedding)}return Array.isArray(Q)?H:H[0]}function jQ(Q,X){if(Q.length!==X.length)throw Error(`Vector dimensions must match: ${Q.length} vs ${X.length}`);let Y=0,Z=0,H=0;for(let J=0;J<Q.length;J++)Y+=Q[J]*X[J],Z+=Q[J]*Q[J],H+=X[J]*X[J];let W=Math.sqrt(Z)*Math.sqrt(H);if(W===0)return 0;return Y/W}function zX(Q,X){if(Q.length!==X.length)throw Error(`Vector dimensions must match: ${Q.length} vs ${X.length}`);let Y=0;for(let Z=0;Z<Q.length;Z++)Y+=Q[Z]*X[Z];return Y}function BX(Q,X){if(Q.length!==X.length)throw Error(`Vector dimensions must match: ${Q.length} vs ${X.length}`);let Y=0;for(let Z=0;Z<Q.length;Z++){let H=Q[Z]-X[Z];Y+=H*H}return Math.sqrt(Y)}class r{documents=[];embeddingOptions;constructor(Q={}){this.embeddingOptions=Q}async add(Q){if(Q.length===0)return;let X=Q.map((H)=>H.content),Y=await a(X,this.embeddingOptions),Z=X.length===1?[Y]:Y;for(let H=0;H<Q.length;H++)this.documents.push({...Q[H],embedding:Z[H]})}addWithEmbedding(Q,X){this.documents.push({...Q,embedding:X})}async search(Q,X=5){if(this.documents.length===0)return[];let Y=await a(Q,this.embeddingOptions);return this.searchByVector(Y,X)}searchByVector(Q,X=5){if(this.documents.length===0)return[];let Y=this.documents.map((Z)=>({document:{id:Z.id,content:Z.content,metadata:Z.metadata},score:jQ(Q,Z.embedding)}));return Y.sort((Z,H)=>H.score-Z.score),Y.slice(0,X).map((Z,H)=>({...Z,rank:H+1}))}remove(Q){let X=this.documents.length;return this.documents=this.documents.filter((Y)=>Y.id!==Q),this.documents.length<X}clear(){this.documents=[]}get size(){return this.documents.length}get ids(){return this.documents.map((Q)=>Q.id)}}async function EX(Q,X,Y={}){let{provider:Z="anthropic",topK:H=5,maxTokens:W=4096,temperature:J,systemPrompt:V}=Y,G=await X.search(Q,H),U=G.map((q,L)=>`[Source ${L+1}] (score: ${q.score.toFixed(3)})
130
+ ${q.document.content}`).join(`
131
+
132
+ ---
133
+
134
+ `),j=V||"You are a helpful assistant. Answer the user's question based on the provided context. If the context doesn't contain relevant information, say so. Always cite your sources by referencing [Source N].",$=`Context:
135
+ ${U}
136
+
137
+ Question: ${Q}`;if(Z==="anthropic")return LX($,j,G,{maxTokens:W,temperature:J,model:Y.model});if(Z==="openai")return AX($,j,G,{maxTokens:W,temperature:J,model:Y.model});if(Z==="ollama")return OX($,j,G,{maxTokens:W,temperature:J,model:Y.model});throw Error(`RAG provider not supported: ${Z}`)}async function LX(Q,X,Y,Z){let H=process.env.ANTHROPIC_API_KEY;if(!H)throw Error("ANTHROPIC_API_KEY required for RAG with Anthropic.");let W=Z.model||"claude-sonnet-4-20250514",J=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json","x-api-key":H,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:W,max_tokens:Z.maxTokens||4096,temperature:Z.temperature,system:X,messages:[{role:"user",content:Q}]})});if(!J.ok){let G=await J.text();throw Error(`Claude API error: ${G}`)}let V=await J.json();return{content:V.content[0].text,model:V.model,usage:{promptTokens:V.usage?.input_tokens||0,completionTokens:V.usage?.output_tokens||0,totalTokens:(V.usage?.input_tokens||0)+(V.usage?.output_tokens||0)},finishReason:V.stop_reason,sources:Y}}async function AX(Q,X,Y,Z){let H=process.env.OPENAI_API_KEY;if(!H)throw Error("OPENAI_API_KEY required for RAG with OpenAI.");let W=Z.model||"gpt-4o",J=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${H}`},body:JSON.stringify({model:W,max_tokens:Z.maxTokens||4096,temperature:Z.temperature,messages:[{role:"system",content:X},{role:"user",content:Q}]})});if(!J.ok){let G=await J.text();throw Error(`OpenAI API error: ${G}`)}let V=await J.json();return{content:V.choices[0].message.content,model:V.model,usage:{promptTokens:V.usage?.prompt_tokens||0,completionTokens:V.usage?.completion_tokens||0,totalTokens:V.usage?.total_tokens||0},finishReason:V.choices[0].finish_reason,sources:Y}}async function OX(Q,X,Y,Z){let H=process.env.OLLAMA_HOST||"http://localhost:11434",W=Z.model||"llama3.2",J=await fetch(`${H}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:W,messages:[{role:"system",content:X},{role:"user",content:Q}],stream:!1,options:{temperature:Z.temperature}})});if(!J.ok){let G=await J.text();throw Error(`Ollama API error: ${G}`)}let V=await J.json();return{content:V.message.content,model:V.model,usage:{promptTokens:V.prompt_eval_count||0,completionTokens:V.eval_count||0,totalTokens:(V.prompt_eval_count||0)+(V.eval_count||0)},finishReason:V.done_reason||"stop",sources:Y}}function $Q(Q,X={}){let{chunkSize:Y=1000,chunkOverlap:Z=200,separator:H=`
138
+ `}=X,W=Q.split(H),J=[],V="";for(let G of W)if(V.length+G.length+1>Y&&V.length>0)if(J.push(V.trim()),Z>0){let U=Math.max(0,V.length-Z);V=V.slice(U)+H+G}else V=G;else V+=(V?H:"")+G;if(V.trim())J.push(V.trim());return J}async function _X(Q,X={}){let Y=$Q(Q,X),Z=new r(X),H=Y.map((W,J)=>({id:`${X.idPrefix||"chunk"}-${J}`,content:W,metadata:{chunkIndex:J,totalChunks:Y.length}}));return await Z.add(H),Z}var EY={createEmbedding:a,cosineSimilarity:jQ,dotProduct:zX,euclideanDistance:BX,VectorIndex:r,rag:EX,chunkText:$Q,indexText:_X};async function RX(Q,X={}){let{provider:Y="anthropic",aspects:Z}=X,H=Z?`
139
+ Also analyze sentiment for these specific aspects: ${Z.join(", ")}`:"",W=`You are a sentiment analysis expert. Analyze the sentiment of the given text and respond with ONLY valid JSON in this exact format:
140
+ {
141
+ "sentiment": "positive" | "negative" | "neutral" | "mixed",
142
+ "score": <number from -1.0 to 1.0>,
143
+ "confidence": <number from 0.0 to 1.0>${Z?`,
144
+ "aspects": [{"aspect": "<name>", "sentiment": "positive" | "negative" | "neutral", "score": <number>}]`:""}
145
+ }${H}`,J=await y(Y,W,Q,X.model);try{return JSON.parse(J.content)}catch{let V=J.content.toLowerCase(),G=V.includes("positive"),U=V.includes("negative");return{sentiment:G&&U?"mixed":G?"positive":U?"negative":"neutral",score:G?0.5:U?-0.5:0,confidence:0.5}}}async function FX(Q,X,Y={}){let{provider:Z="anthropic",multiLabel:H=!1}=Y,W=`You are a text classification expert. Classify the given text into ${H?"one or more of":"exactly one of"} these categories: ${X.join(", ")}.
146
+
147
+ Respond with ONLY valid JSON in this exact format:
148
+ {
149
+ "label": "<primary label>",
150
+ "confidence": <number from 0.0 to 1.0>,
151
+ "allLabels": [{"label": "<label>", "confidence": <number>}]
152
+ }
153
+
154
+ Include ALL provided labels in allLabels with their confidence scores, sorted by confidence descending.`,J=await y(Z,W,Q,Y.model);try{return JSON.parse(J.content)}catch{return{label:X[0],confidence:0.5,allLabels:X.map((V)=>({label:V,confidence:1/X.length}))}}}async function NX(Q,X={}){let{provider:Y="anthropic",style:Z="concise",maxLength:H,language:W}=X,J;switch(Z){case"bullet-points":J="Use bullet points to organize the key points.";break;case"detailed":J="Provide a detailed summary covering all major points.";break;default:J="Be concise and focus on the most important points."}let V=H?` Keep the summary under ${H} words.`:"",G=W?` Write the summary in ${W}.`:"",U=`You are an expert summarizer. ${J}${V}${G}`;return y(Y,U,`Summarize the following text:
155
+
156
+ ${Q}`,X.model)}async function wX(Q,X,Y={}){let{provider:Z="anthropic",limit:H=5}=Y,W=MX(Q),J=X.map((j)=>`ID: ${j.id} | Category: ${j.category||"none"} | Tags: ${j.tags?.join(", ")||"none"} | Content: ${j.content.slice(0,200)}`).join(`
157
+ `),V=`You are a recommendation engine. Based on the user profile, recommend the most relevant items. Respond with ONLY valid JSON:
158
+ {
159
+ "recommendations": [
160
+ {"itemId": "<id>", "score": <0.0-1.0>, "reason": "<brief reason>"}
161
+ ]
162
+ }
163
+
164
+ Return at most ${H} recommendations, sorted by relevance score descending.`,G=`User Profile:
165
+ ${W}
166
+
167
+ Available Items:
168
+ ${J}`,U=await y(Z,V,G,Y.model);try{return{recommendations:JSON.parse(U.content).recommendations.slice(0,H),model:U.model,provider:Z}}catch{return{recommendations:[],model:U.model,provider:Z}}}function MX(Q){let X=Object.entries(Q.preferences).sort(([,Z],[,H])=>H-Z).slice(0,10).map(([Z,H])=>`${Z}: ${H.toFixed(2)}`).join(", "),Y=Q.interactions.sort((Z,H)=>H.timestamp-Z.timestamp).slice(0,10).map((Z)=>`${Z.type} on ${Z.itemId}`).join(", ");return`Segments: ${Q.segments.join(", ")}
169
+ Top Preferences: ${X||"none"}
170
+ Recent Interactions: ${Y||"none"}`}function KX(Q,X=[]){return{id:Q,preferences:{},interactions:[],segments:X}}function TX(Q,X){Q.interactions.push(X);let Z={view:0.1,click:0.3,like:0.5,share:0.6,bookmark:0.7,purchase:1,dislike:-0.5,custom:X.weight||0.3}[X.type]||0.1,H=X.itemId;return Q.preferences[H]=(Q.preferences[H]||0)+Z,Q}async function DX(Q,X,Y={}){let{provider:Z="anthropic"}=Y,H=new Set(Q.interactions.map((U)=>U.itemId)),W=X.filter((U)=>H.has(U.id));if(W.length===0)return Q.segments;let J=W.slice(0,20).map((U)=>U.content.slice(0,200)).join(`
171
+ ---
172
+ `),G=await y(Z,`Extract the main interests/topics from the user's interaction history. Return ONLY a JSON array of strings, e.g. ["technology", "cooking", "travel"]. Maximum 10 interests.`,J,Y.model);try{return JSON.parse(G.content)}catch{return Q.segments}}async function y(Q,X,Y,Z){if(Q==="anthropic"){let H=process.env.ANTHROPIC_API_KEY;if(!H)throw Error("ANTHROPIC_API_KEY required.");let W=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json","x-api-key":H,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:Z||"claude-sonnet-4-20250514",max_tokens:4096,system:X,messages:[{role:"user",content:Y}]})});if(!W.ok){let V=await W.text();throw Error(`Claude API error: ${V}`)}let J=await W.json();return{content:J.content[0].text,model:J.model,usage:{promptTokens:J.usage?.input_tokens||0,completionTokens:J.usage?.output_tokens||0,totalTokens:(J.usage?.input_tokens||0)+(J.usage?.output_tokens||0)},finishReason:J.stop_reason}}if(Q==="openai"){let H=process.env.OPENAI_API_KEY;if(!H)throw Error("OPENAI_API_KEY required.");let W=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${H}`},body:JSON.stringify({model:Z||"gpt-4o",max_tokens:4096,messages:[{role:"system",content:X},{role:"user",content:Y}]})});if(!W.ok){let V=await W.text();throw Error(`OpenAI API error: ${V}`)}let J=await W.json();return{content:J.choices[0].message.content,model:J.model,usage:{promptTokens:J.usage?.prompt_tokens||0,completionTokens:J.usage?.completion_tokens||0,totalTokens:J.usage?.total_tokens||0},finishReason:J.choices[0].finish_reason}}if(Q==="ollama"){let H=process.env.OLLAMA_HOST||"http://localhost:11434",W=await fetch(`${H}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:Z||"llama3.2",messages:[{role:"system",content:X},{role:"user",content:Y}],stream:!1})});if(!W.ok){let V=await W.text();throw Error(`Ollama API error: ${V}`)}let J=await W.json();return{content:J.message.content,model:J.model,usage:{promptTokens:J.prompt_eval_count||0,completionTokens:J.eval_count||0,totalTokens:(J.prompt_eval_count||0)+(J.eval_count||0)},finishReason:J.done_reason||"stop"}}throw Error(`Provider not supported: ${Q}`)}var AY={analyzeSentiment:RX,classifyText:FX,summarize:NX,recommend:wX,createProfile:KX,recordInteraction:TX,extractUserInterests:DX};class f{config;process=null;requestId=0;pendingRequests=new Map;tools=[];resources=[];prompts=[];initialized=!1;buffer="";constructor(Q){this.config=Q}async connect(){if(this.config.transport.type==="stdio")await this.connectStdio();else if(this.config.transport.type==="sse"||this.config.transport.type==="streamable-http")await this.connectHTTP();else throw Error(`Unsupported transport type: ${this.config.transport.type}`);this.initialized=!0}async connectStdio(){let Q=this.config.transport,{spawn:X}=awaitPromise.resolve(globalThis.Bun);this.process=X([Q.command,...Q.args||[]],{stdin:"pipe",stdout:"pipe",stderr:"pipe",env:{...process.env,...Q.env}}),this.readStdout(),await this.sendRequest("initialize",{protocolVersion:"2024-11-05",capabilities:{},clientInfo:{name:"stacks-ai",version:"1.0.0"}}),await this.sendNotification("notifications/initialized",{}),await this.discoverCapabilities()}async connectHTTP(){let Q=this.config.transport,X=await fetch(Q.url,{method:"POST",headers:{"Content-Type":"application/json",...Q.headers},body:JSON.stringify({jsonrpc:"2.0",id:this.nextId(),method:"initialize",params:{protocolVersion:"2024-11-05",capabilities:{},clientInfo:{name:"stacks-ai",version:"1.0.0"}}})});if(!X.ok){let Y=await X.text();throw Error(`MCP HTTP connection error: ${Y}`)}await this.discoverCapabilities()}async readStdout(){if(!this.process)return;let Q=this.process.stdout?.getReader();if(!Q)return;let X=new TextDecoder;try{while(!0){let{done:Y,value:Z}=await Q.read();if(Y)break;this.buffer+=X.decode(Z,{stream:!0}),this.processBuffer()}}catch{}}processBuffer(){let Q=this.buffer.split(`
173
+ `);this.buffer=Q.pop()||"";for(let X of Q){if(!X.trim())continue;try{let Y=JSON.parse(X);if(Y.id!==void 0&&this.pendingRequests.has(Y.id)){let Z=this.pendingRequests.get(Y.id);if(this.pendingRequests.delete(Y.id),Y.error)Z.reject(Error(Y.error.message||"MCP error"));else Z.resolve(Y.result)}}catch{}}}nextId(){return++this.requestId}async sendRequest(Q,X={}){let Y=this.nextId(),Z=JSON.stringify({jsonrpc:"2.0",id:Y,method:Q,params:X})+`
174
+ `;if(this.config.transport.type==="stdio"&&this.process){let H=this.process.stdin?.getWriter();if(H)await H.write(new TextEncoder().encode(Z)),H.releaseLock();return new Promise((W,J)=>{let V=setTimeout(()=>{this.pendingRequests.delete(Y),J(Error(`MCP request timeout: ${Q}`))},30000);this.pendingRequests.set(Y,{resolve:(G)=>{clearTimeout(V),W(G)},reject:(G)=>{clearTimeout(V),J(G)}})})}if(this.config.transport.type==="sse"||this.config.transport.type==="streamable-http"){let H=this.config.transport,W=await fetch(H.url,{method:"POST",headers:{"Content-Type":"application/json",...H.headers},body:Z});if(!W.ok){let V=await W.text();throw Error(`MCP request error: ${V}`)}let J=await W.json();if(J.error)throw Error(J.error.message||"MCP error");return J.result}throw Error("No transport available")}async sendNotification(Q,X={}){let Y=JSON.stringify({jsonrpc:"2.0",method:Q,params:X})+`
175
+ `;if(this.config.transport.type==="stdio"&&this.process){let Z=this.process.stdin?.getWriter();if(Z)await Z.write(new TextEncoder().encode(Y)),Z.releaseLock()}}async discoverCapabilities(){let Q=this.config.capabilities||{tools:!0,resources:!0,prompts:!0};if(Q.tools!==!1)try{let X=await this.sendRequest("tools/list");this.tools=X?.tools||[]}catch{this.tools=[]}if(Q.resources!==!1)try{let X=await this.sendRequest("resources/list");this.resources=X?.resources||[]}catch{this.resources=[]}if(Q.prompts!==!1)try{let X=await this.sendRequest("prompts/list");this.prompts=X?.prompts||[]}catch{this.prompts=[]}}listTools(){return this.tools}listResources(){return this.resources}listPrompts(){return this.prompts}async callTool(Q,X={}){if(!this.initialized)throw Error("MCP client not connected. Call connect() first.");return await this.sendRequest("tools/call",{name:Q,arguments:X})}async readResource(Q){if(!this.initialized)throw Error("MCP client not connected. Call connect() first.");let Y=(await this.sendRequest("resources/read",{uri:Q}))?.contents?.[0];return{uri:Y?.uri||Q,mimeType:Y?.mimeType,text:Y?.text,blob:Y?.blob}}async getPrompt(Q,X={}){if(!this.initialized)throw Error("MCP client not connected. Call connect() first.");return this.sendRequest("prompts/get",{name:Q,arguments:X})}toAnthropicTools(){return this.tools.map((Q)=>({name:Q.name,description:Q.description,input_schema:Q.inputSchema}))}toOpenAITools(){return this.tools.map((Q)=>({type:"function",function:{name:Q.name,description:Q.description,parameters:Q.inputSchema}}))}async disconnect(){if(this.process)this.process.kill(),this.process=null;for(let Q of this.pendingRequests.values())try{Q.reject(Error("MCP client disconnected"))}catch{}this.pendingRequests.clear(),this.initialized=!1,this.tools=[],this.resources=[],this.prompts=[]}get isConnected(){return this.initialized}get serverName(){return this.config.name}}class qQ{clients=new Map;async addServer(Q){if(this.clients.has(Q.name))throw Error(`MCP server already registered: ${Q.name}`);let X=new f(Q);return await X.connect(),this.clients.set(Q.name,X),X}async removeServer(Q){let X=this.clients.get(Q);if(X)await X.disconnect(),this.clients.delete(Q)}getServer(Q){return this.clients.get(Q)}listServers(){return Array.from(this.clients.keys())}getAllTools(){let Q=[];for(let[X,Y]of this.clients)for(let Z of Y.listTools())Q.push({...Z,serverName:X});return Q}async callTool(Q,X={}){if(Q.includes("/")){let[Y,Z]=Q.split("/",2),H=this.clients.get(Y);if(!H)throw Error(`MCP server not found: ${Y}`);return H.callTool(Z,X)}for(let[,Y]of this.clients)if(Y.listTools().some((H)=>H.name===Q))return Y.callTool(Q,X);throw Error(`MCP tool not found: ${Q}`)}toAnthropicTools(){let Q=[];for(let[X,Y]of this.clients)for(let Z of Y.listTools())Q.push({name:`${X}__${Z.name}`,description:`[${X}] ${Z.description}`,input_schema:Z.inputSchema});return Q}toOpenAITools(){let Q=[];for(let[X,Y]of this.clients)for(let Z of Y.listTools())Q.push({type:"function",function:{name:`${X}__${Z.name}`,description:`[${X}] ${Z.description}`,parameters:Z.inputSchema}});return Q}async disconnectAll(){let Q=Array.from(this.clients.values()).map((X)=>X.disconnect());await Promise.all(Q),this.clients.clear()}}async function IX(Q,X,Y,Z){let H=new f({name:Q,transport:{type:"stdio",command:X,args:Y,env:Z}});return await H.connect(),H}async function xX(Q,X,Y){let Z=new f({name:Q,transport:{type:"streamable-http",url:X,headers:Y}});return await Z.connect(),Z}var _Y={MCPClient:f,MCPManager:qQ,connectStdio:IX,connectHTTP:xX};import kX from"process";var m=null;async function n(){if(m)return m;let Q=await import("@stacksjs/ts-cloud/aws");if(!Q?.BedrockClient)throw Error("@stacksjs/ts-cloud/aws does not export BedrockClient \u2014 rebuild ts-cloud or remove the AI dependency.");return m=new Q.BedrockClient(kX.env.REGION||"us-east-1"),m}async function NY(Q){return(await n()).createModelCustomizationJob(Q)}async function wY(Q){return(await n()).getModelCustomizationJob(Q)}async function MY(Q){return(await n()).listFoundationModels(Q)}import{log as s}from"@stacksjs/cli";import{ai as CX}from"@stacksjs/config";async function SX(){let Q=await import("@stacksjs/ts-cloud/aws");if(!Q?.BedrockClient)throw Error("@stacksjs/ts-cloud/aws does not export BedrockClient \u2014 rebuild ts-cloud or remove the AI dependency.");return new Q.BedrockClient("us-east-1")}async function IY(){let Q=await SX(),X=CX.models;if(!X)throw Error("No AI models found. Please set ./config/ai.ts values.");for(let Y of X)try{s.info(`Requesting access to model ${Y}`);let Z=await Q.requestModelAccess({modelId:Y});s.info(`Response for model ${Y}:`,Z)}catch(Z){s.error(`Error requesting access to model ${Y}:`,Z)}}export{jY as summarize,EY as search,iQ as resetPromptCount,IY as requestModelAccess,TX as recordInteraction,wX as recommend,EX as rag,XY as pushChanges,pQ as processCommandStreaming,YY as processCommand,AY as personalization,KQ as openaiDriver,TQ as openai,oX as openRepository,yQ as ollamaDriver,fQ as ollama,_Y as mcp,MY as listFoundationModels,WY as invokeModelWithResponseStream,i as invokeModel,_X as indexText,zY as image,oQ as getRepoContext,wY as getModelCustomizationJob,YQ as getLastSessionId,tQ as getDriver,tX as getAvailableDrivers,YX as generateImage,DX as extractUserInterests,BX as euclideanDistance,QQ as estimateTokens,HX as editImage,zX as dotProduct,KX as createProfile,P as createOpenAIDriver,b as createOllamaDriver,NY as createModelCustomizationJob,JX as createImageVariation,a as createEmbedding,dQ as createClaudeLocalAgent,mQ as createClaudeEC2Agent,c as createClaudeAgentSDKDriver,S as createAnthropicDriver,jQ as cosineSimilarity,IX as connectStdio,xX as connectHTTP,eQ as configureGitUser,QY as commitChanges,ZQ as clearSession,cQ as claudeAgentSDK,l as claudeAgent,FX as classifyText,$Q as chunkText,nQ as buildSystemPrompt,HY as buddyStreamSimple,R as buddyState,ZY as buddyProcessStreaming,$Y as ask,eX as applyChanges,K as apiKeys,LQ as anthropicDriver,AQ as anthropic,RX as analyzeSentiment,jX as analyzeImages,VX as analyzeImage,r as VectorIndex,qQ as MCPManager,f as MCPClient,k as CONFIG};
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Create and connect to an MCP server using stdio transport.
3
+ */
4
+ export declare function connectStdio(name: string, command: string, args?: string[], env?: Record<string, string>): Promise<MCPClient>;
5
+ /**
6
+ * Create and connect to an MCP server using HTTP transport.
7
+ */
8
+ export declare function connectHTTP(name: string, url: string, headers?: Record<string, string>): Promise<MCPClient>;
9
+ // ============================================================================
10
+ // Exports
11
+ // ============================================================================
12
+ export declare const mcp: {
13
+
14
+ };
15
+ /**
16
+ * MCP (Model Context Protocol) Module
17
+ *
18
+ * Implements an MCP client for connecting to MCP servers, discovering tools,
19
+ * and invoking them through AI providers. This enables AI models to interact
20
+ * with external services via a standardized protocol.
21
+ *
22
+ * @see https://modelcontextprotocol.io
23
+ */
24
+ // ============================================================================
25
+ // Types
26
+ // ============================================================================
27
+ export declare interface MCPServerConfig {
28
+ name: string
29
+ transport: MCPTransport
30
+ capabilities?: MCPCapabilities
31
+ }
32
+ export declare interface MCPCapabilities {
33
+ tools?: boolean
34
+ resources?: boolean
35
+ prompts?: boolean
36
+ }
37
+ export declare interface MCPTool {
38
+ name: string
39
+ description: string
40
+ inputSchema: Record<string, unknown>
41
+ }
42
+ export declare interface MCPResource {
43
+ uri: string
44
+ name: string
45
+ description?: string
46
+ mimeType?: string
47
+ }
48
+ export declare interface MCPPrompt {
49
+ name: string
50
+ description?: string
51
+ arguments?: Array<{
52
+ name: string
53
+ description?: string
54
+ required?: boolean
55
+ }>
56
+ }
57
+ export declare interface MCPToolCallResult {
58
+ content: Array<{
59
+ type: 'text' | 'image' | 'resource'
60
+ text?: string
61
+ data?: string
62
+ mimeType?: string
63
+ }>
64
+ isError?: boolean
65
+ }
66
+ export declare interface MCPResourceContent {
67
+ uri: string
68
+ mimeType?: string
69
+ text?: string
70
+ blob?: string
71
+ }
72
+ export type MCPTransport = | { type: 'stdio'; command: string; args?: string[]; env?: Record<string, string> }
73
+ | { type: 'sse'; url: string; headers?: Record<string, string> }
74
+ | { type: 'streamable-http'; url: string; headers?: Record<string, string> }
75
+ /**
76
+ * MCP Client for connecting to Model Context Protocol servers.
77
+ *
78
+ * Supports stdio and SSE/streamable-http transports.
79
+ * Provides tool discovery, invocation, resource reading, and prompt listing.
80
+ */
81
+ export declare class MCPClient {
82
+ constructor(config: MCPServerConfig);
83
+ connect(): Promise<void>;
84
+ listTools(): MCPTool[];
85
+ listResources(): MCPResource[];
86
+ listPrompts(): MCPPrompt[];
87
+ callTool(name: string, args?: Record<string, unknown>): Promise<MCPToolCallResult>;
88
+ readResource(uri: string): Promise<MCPResourceContent>;
89
+ getPrompt(name: string, args?: Record<string, string>): Promise<{
90
+ description?: string
91
+ messages: Array<{ role: string; content: { type: string; text: string } }>
92
+ }>;
93
+ toAnthropicTools(): Array<{ name: string; description: string; input_schema: Record<string, unknown> }>;
94
+ toOpenAITools(): Array<{ type: 'function'; function: { name: string; description: string; parameters: Record<string, unknown> } }>;
95
+ disconnect(): Promise<void>;
96
+ get isConnected(): boolean;
97
+ get serverName(): string;
98
+ }
99
+ /**
100
+ * Manages connections to multiple MCP servers.
101
+ */
102
+ export declare class MCPManager {
103
+ addServer(config: MCPServerConfig): Promise<MCPClient>;
104
+ removeServer(name: string): Promise<void>;
105
+ getServer(name: string): MCPClient | undefined;
106
+ listServers(): string[];
107
+ getAllTools(): Array<MCPTool & { serverName: string }>;
108
+ callTool(toolPath: string, args?: Record<string, unknown>): Promise<MCPToolCallResult>;
109
+ toAnthropicTools(): Array<{ name: string; description: string; input_schema: Record<string, unknown> }>;
110
+ toOpenAITools(): Array<{ type: 'function'; function: { name: string; description: string; parameters: Record<string, unknown> } }>;
111
+ disconnectAll(): Promise<void>;
112
+ }
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Analyze the sentiment of text using AI.
3
+ */
4
+ export declare function analyzeSentiment(text: string, options?: {
5
+ provider?: 'anthropic' | 'openai' | 'ollama'
6
+ model?: string
7
+ aspects?: string[]
8
+ }): Promise<SentimentResult>;
9
+ /**
10
+ * Classify text into one of the provided labels.
11
+ */
12
+ export declare function classifyText(text: string, labels: string[], options?: {
13
+ provider?: 'anthropic' | 'openai' | 'ollama'
14
+ model?: string
15
+ multiLabel?: boolean
16
+ }): Promise<ClassificationResult>;
17
+ /**
18
+ * Generate personalized content recommendations based on user profile and available items.
19
+ */
20
+ export declare function recommend(profile: UserProfile, items: ContentItem[], options?: RecommendationOptions): Promise<RecommendationResult>;
21
+ /**
22
+ * Create a new empty user profile.
23
+ */
24
+ export declare function createProfile(id: string, segments?: string[]): UserProfile;
25
+ /**
26
+ * Record a user interaction and update preferences.
27
+ */
28
+ export declare function recordInteraction(profile: UserProfile, interaction: Interaction): UserProfile;
29
+ /**
30
+ * Extract keywords/topics from user interactions using AI.
31
+ */
32
+ export declare function extractUserInterests(profile: UserProfile, items: ContentItem[], options?: { provider?: 'anthropic' | 'openai' | 'ollama'; model?: string }): Promise<string[]>;
33
+ // ============================================================================
34
+ // Exports
35
+ // ============================================================================
36
+ export declare const personalization: {
37
+
38
+ };
39
+ // ============================================================================
40
+ // Types
41
+ // ============================================================================
42
+ export declare interface UserProfile {
43
+ id: string
44
+ preferences: Record<string, number>
45
+ interactions: Interaction[]
46
+ segments: string[]
47
+ metadata?: Record<string, unknown>
48
+ }
49
+ export declare interface Interaction {
50
+ type: 'view' | 'click' | 'purchase' | 'like' | 'dislike' | 'share' | 'bookmark' | 'custom'
51
+ itemId: string
52
+ timestamp: number
53
+ weight?: number
54
+ metadata?: Record<string, unknown>
55
+ }
56
+ export declare interface ContentItem {
57
+ id: string
58
+ content: string
59
+ category?: string
60
+ tags?: string[]
61
+ metadata?: Record<string, unknown>
62
+ }
63
+ export declare interface RecommendationOptions {
64
+ provider?: 'anthropic' | 'openai' | 'ollama'
65
+ model?: string
66
+ maxTokens?: number
67
+ temperature?: number
68
+ limit?: number
69
+ }
70
+ export declare interface RecommendationResult {
71
+ recommendations: Array<{
72
+ itemId: string
73
+ score: number
74
+ reason: string
75
+ }>
76
+ model: string
77
+ provider: string
78
+ }
79
+ export declare interface SentimentResult {
80
+ sentiment: 'positive' | 'negative' | 'neutral' | 'mixed'
81
+ score: number
82
+ confidence: number
83
+ aspects?: Array<{
84
+ aspect: string
85
+ sentiment: 'positive' | 'negative' | 'neutral'
86
+ score: number
87
+ }>
88
+ }
89
+ export declare interface ClassificationResult {
90
+ label: string
91
+ confidence: number
92
+ allLabels: Array<{
93
+ label: string
94
+ confidence: number
95
+ }>
96
+ }
97
+ export declare interface SummaryOptions {
98
+ provider?: 'anthropic' | 'openai' | 'ollama'
99
+ model?: string
100
+ maxLength?: number
101
+ style?: 'concise' | 'detailed' | 'bullet-points'
102
+ language?: string
103
+ }
@@ -0,0 +1,91 @@
1
+ import type { AIResult } from './types';
2
+ /**
3
+ * Generate embeddings for text input.
4
+ */
5
+ export declare function createEmbedding(input: string | string[], options?: EmbeddingOptions): Promise<number[] | number[][]>;
6
+ /**
7
+ * Calculate cosine similarity between two vectors.
8
+ */
9
+ export declare function cosineSimilarity(a: number[], b: number[]): number;
10
+ /**
11
+ * Calculate dot product similarity between two vectors.
12
+ */
13
+ export declare function dotProduct(a: number[], b: number[]): number;
14
+ /**
15
+ * Calculate Euclidean distance between two vectors.
16
+ */
17
+ export declare function euclideanDistance(a: number[], b: number[]): number;
18
+ /**
19
+ * Perform RAG: search for relevant documents and use them as context for generation.
20
+ */
21
+ export declare function rag(query: string, index: VectorIndex, options?: RAGOptions): Promise<RAGResult>;
22
+ /**
23
+ * Split text into overlapping chunks for embedding.
24
+ */
25
+ export declare function chunkText(text: string, options?: ChunkOptions): string[];
26
+ /**
27
+ * Create a searchable index from a long text by chunking and embedding.
28
+ */
29
+ export declare function indexText(text: string, options?: ChunkOptions & EmbeddingOptions & { idPrefix?: string }): Promise<VectorIndex>;
30
+ // ============================================================================
31
+ // Exports
32
+ // ============================================================================
33
+ export declare const search: {
34
+
35
+ };
36
+ // ============================================================================
37
+ // Types
38
+ // ============================================================================
39
+ export declare interface EmbeddingOptions {
40
+ provider?: 'openai' | 'ollama'
41
+ model?: string
42
+ }
43
+ export declare interface SearchDocument {
44
+ id: string
45
+ content: string
46
+ metadata?: Record<string, unknown>
47
+ }
48
+ export declare interface IndexedDocument extends SearchDocument {
49
+ embedding: number[]
50
+ }
51
+ export declare interface SearchResult {
52
+ document: SearchDocument
53
+ score: number
54
+ rank: number
55
+ }
56
+ export declare interface RAGOptions {
57
+ provider?: 'anthropic' | 'openai' | 'ollama'
58
+ embeddingProvider?: 'openai' | 'ollama'
59
+ embeddingModel?: string
60
+ model?: string
61
+ maxTokens?: number
62
+ temperature?: number
63
+ topK?: number
64
+ systemPrompt?: string
65
+ }
66
+ export declare interface RAGResult extends AIResult {
67
+ sources: SearchResult[]
68
+ }
69
+ // ============================================================================
70
+ // Text Chunking Utilities
71
+ // ============================================================================
72
+ export declare interface ChunkOptions {
73
+ chunkSize?: number
74
+ chunkOverlap?: number
75
+ separator?: string
76
+ }
77
+ /**
78
+ * Simple in-memory vector search index.
79
+ * For production, use a dedicated vector database.
80
+ */
81
+ export declare class VectorIndex {
82
+ constructor(options?: EmbeddingOptions);
83
+ add(documents: SearchDocument[]): Promise<void>;
84
+ addWithEmbedding(document: SearchDocument, embedding: number[]): void;
85
+ search(query: string, topK?: number): Promise<SearchResult[]>;
86
+ searchByVector(queryEmbedding: number[], topK?: number): SearchResult[];
87
+ remove(id: string): boolean;
88
+ clear(): void;
89
+ get size(): number;
90
+ get ids(): string[];
91
+ }
@@ -0,0 +1,10 @@
1
+ export declare function summarize(text: string, options?: SummarizeOptions): Promise<string>;
2
+ export declare function ask(question: string, options?: AskOptions): Promise<string>;
3
+ declare interface AiOptions {
4
+ maxTokenCount?: number
5
+ temperature?: number
6
+ topP?: number
7
+ modelId?: string
8
+ }
9
+ export declare interface SummarizeOptions extends AiOptions {}
10
+ export declare interface AskOptions extends AiOptions {}