@stacksjs/ai 0.70.87 → 0.70.90
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/claude/index.js +197 -0
- package/dist/agents/index.js +1 -0
- package/dist/buddy.js +393 -0
- package/dist/drivers/anthropic/index.js +276 -0
- package/dist/drivers/claude-agent-sdk/index.js +198 -0
- package/dist/drivers/index.js +4 -0
- package/dist/drivers/ollama/index.js +332 -0
- package/dist/drivers/openai/index.js +351 -0
- package/dist/image.js +375 -0
- package/dist/index.js +16 -175
- package/dist/mcp.js +361 -0
- package/dist/personalization.js +244 -0
- package/dist/search.js +316 -0
- package/dist/text.js +51 -0
- package/dist/types.js +0 -0
- package/dist/utils/client-bedrock-runtime.js +17 -0
- package/dist/utils/client-bedrock.js +20 -0
- package/dist/utils/model-access.js +21 -0
- package/dist/utils/retry.js +39 -0
- package/dist/utils/tokens.js +59 -0
- package/dist/utils/usage.js +27 -0
- package/dist/utils/vision.js +54 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,175 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
`;case"Grep":return`
|
|
18
|
-
\uD83D\uDD0E Searching for: "${Z.pattern||""}"
|
|
19
|
-
`;case"Edit":{let Y=Z.file_path||"";return`
|
|
20
|
-
\u270F\uFE0F Editing: ${Y.split("/").pop()||Y}
|
|
21
|
-
`}case"Write":{let Y=Z.file_path||"";return`
|
|
22
|
-
\uD83D\uDCDD Writing: ${Y.split("/").pop()||Y}
|
|
23
|
-
`}case"Bash":{let Y=(Z.command||"").substring(0,50);return`
|
|
24
|
-
\uD83D\uDCBB Running: ${Y}${Y.length>=50?"...":""}
|
|
25
|
-
`}case"Task":return`
|
|
26
|
-
\uD83D\uDE80 Launching agent: ${Z.description||"task"}
|
|
27
|
-
`;default:return`
|
|
28
|
-
\uD83D\uDD27 Using: ${Q}
|
|
29
|
-
`}}function $Z(Q={}){return{name:"Claude CLI (Local)",async process(Z,Y,H){let{$:X}=awaitPromise.resolve(globalThis.Bun);if((await X`which claude`.quiet().nothrow()).exitCode!==0)throw Error("Claude CLI not found. Install it with: npm install -g @anthropic-ai/claude-code");let V=Y?`Context:
|
|
30
|
-
${Y}
|
|
31
|
-
|
|
32
|
-
User request: ${Z}`:Z,J=Q.cwd||process.cwd();try{return(await X`cd ${J} && claude --print --dangerously-skip-permissions ${V}`.quiet()).text().trim()}catch{try{return(await X`cd ${J} && claude --print --allowedTools "Write,Edit,Bash" ${V}`.quiet()).text().trim()}catch($){throw Error(`Claude CLI error: ${$.message}`)}}}}}function WZ(Q){let{ec2Host:Z=process.env.BUDDY_EC2_HOST,ec2User:Y=process.env.BUDDY_EC2_USER||"ubuntu",ec2Key:H=process.env.BUDDY_EC2_KEY}=Q;return{name:"Claude CLI (EC2)",async process(X,G,V){let{$:J}=awaitPromise.resolve(globalThis.Bun);if(!Z)throw Error("BUDDY_EC2_HOST environment variable not set. Set it to your EC2 instance IP/hostname.");let W=(G?`Context:
|
|
33
|
-
${G}
|
|
34
|
-
|
|
35
|
-
User request: ${X}`:X).replace(/'/g,"'\\''"),q=H?`-i ${H}`:"",j=`${Y}@${Z}`;try{return(await J`ssh ${q} ${j} "claude --print '${W}'"`.quiet()).text().trim()}catch(B){throw Error(`EC2 Claude CLI error: ${B.message}. Make sure SSH is configured and claude CLI is installed on EC2.`)}}}}async function qZ(Q,Z){let{spawn:Y}=awaitPromise.resolve(globalThis.Bun),H=Y(["claude","--print","--verbose","--output-format","stream-json","--dangerously-skip-permissions",Q],{cwd:Z,stdout:"pipe",stderr:"pipe"}),X="",G=new TextDecoder,V=new TextEncoder,J=new ReadableStream({async start(W){try{let q=H.stdout.getReader(),j="",B="",K=await q.read();while(!K.done){j+=G.decode(K.value,{stream:!0});let O=j.split(`
|
|
36
|
-
`);j=O.pop()||"";for(let w of O){if(!w.trim())continue;try{let z=JSON.parse(w),U="";if(z.type==="system"&&z.subtype==="init")wQ++;else if(z.type==="content_block_start"&&z.content_block?.text)U=z.content_block.text;else if(z.type==="content_block_delta"&&z.delta?.text)U=z.delta.text;else if(z.type==="assistant"&&z.message?.content){for(let N of z.message.content)if(N.type==="text"&&N.text)U+=N.text;else if(N.type==="tool_use"&&N.name)U+=GZ(N.name,N.input||{})}else if(z.type==="user"&&z.message?.content){for(let N of z.message.content)if(N.type==="tool_result")U+=` \u2713 done
|
|
37
|
-
`}else if(z.type==="result"&&z.result){X=z.result;let N=z.result.substring(0,Math.min(50,z.result.length));if(!B.includes(N))U=z.result}if(U){if(z.type==="content_block_delta")B+=U,W.enqueue(V.encode(U));else if(!B.endsWith(U))B+=U,W.enqueue(V.encode(U))}}catch{if(!B.includes(w))B+=w,X+=w,W.enqueue(V.encode(w))}}K=await q.read()}if(j.trim())try{let O=JSON.parse(j);if(O.result&&!X)X=O.result}catch{if(!B.includes(j))X+=j,W.enqueue(V.encode(j))}await H.exited,W.close()}catch(q){W.error(q)}}}),$=(async()=>{return await H.exited,X.trim()})();return{stream:J,fullResponse:$}}function jZ(){wQ=0}var a={createLocal:$Z,createEC2:WZ,processStreaming:qZ,resetPromptCount:jZ};import{existsSync as x,mkdirSync as KQ,readFileSync as UQ,writeFileSync as zZ}from"fs";import{homedir as NQ}from"os";import{dirname as BZ,join as k}from"path";var v={workDir:k(NQ(),"Code",".buddy-repos"),commitMessage:"chore: wip",ollamaHost:process.env.OLLAMA_HOST||"http://localhost:11434",ollamaModel:process.env.OLLAMA_MODEL||"llama3.2"},T={anthropic:process.env.ANTHROPIC_API_KEY,openai:process.env.OPENAI_API_KEY,claudeCliHost:process.env.BUDDY_EC2_HOST},_={repo:null,conversationHistory:[],currentDriver:"claude-cli-local",github:null};if(!x(v.workDir))KQ(v.workDir,{recursive:!0});var F={getState:()=>_,setRepo:(Q)=>{_.repo=Q},setCurrentDriver:(Q)=>{_.currentDriver=Q},setGitHub:(Q)=>{_.github=Q},addToHistory:(Q)=>{_.conversationHistory.push(Q)},clearHistory:()=>{_.conversationHistory=[]}};function OZ(Q){return`You are Buddy, an AI code assistant that helps users modify codebases through voice commands.
|
|
38
|
-
|
|
39
|
-
${_.repo?`You are working on the repository: ${_.repo.name}
|
|
40
|
-
Branch: ${_.repo.branch}
|
|
41
|
-
Path: ${_.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 wZ(){return{name:"Mock",async process(Q){await new Promise((Y)=>setTimeout(Y,1000));let Z=Q.toLowerCase();if(Z.includes("readme")||Z.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(Z.includes("fix")||Z.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 UZ(Q){let Z=F.getState();switch(Q){case"claude-cli-local":return a.createLocal({cwd:Z.repo?.path});case"claude-cli-ec2":return a.createEC2({cwd:Z.repo?.path,ec2Host:T.claudeCliHost});case"claude":case"anthropic":if(!T.anthropic)throw Error("Anthropic API key not set. Configure your API key in settings.");return h({apiKey:T.anthropic});case"openai":if(!T.openai)throw Error("OpenAI API key not set. Configure your API key in settings.");return b({apiKey:T.openai});case"ollama":return g({host:v.ollamaHost,model:v.ollamaModel});case"claude-sdk":case"claude-agent-sdk":return i({cwd:Z.repo?.path,maxTurns:25,permissionMode:"bypassPermissions"});case"mock":return wZ();default:throw Error(`Unknown driver: ${Q}. Available: claude-cli-local, claude-cli-ec2, claude, claude-sdk, openai, ollama, mock`)}}function M6(){return["claude-cli-local","claude-cli-ec2","claude","claude-sdk","openai","ollama","mock"]}async function KZ(Q){let{$:Z}=awaitPromise.resolve(globalThis.Bun),H=(await Z`cd ${Q} && find . -type f -not -path "*/node_modules/*" -not -path "*/.git/*" -not -name "*.lock" | head -50`.quiet()).text().trim(),X="",G=k(Q,"README.md");if(x(G))X=UQ(G,"utf-8").slice(0,2000);let V="",J=k(Q,"package.json");if(x(J))V=UQ(J,"utf-8");return`
|
|
109
|
-
Repository Structure:
|
|
110
|
-
${H}
|
|
111
|
-
|
|
112
|
-
${X?`README.md (excerpt):
|
|
113
|
-
${X}
|
|
114
|
-
`:""}
|
|
115
|
-
${V?`package.json:
|
|
116
|
-
${V}
|
|
117
|
-
`:""}
|
|
118
|
-
`.trim()}async function _6(Q){let{$:Z}=awaitPromise.resolve(globalThis.Bun),Y,H;if(Q.includes("github.com")||Q.startsWith("git@"))if(H=Q.split("/").pop()?.replace(".git","")||"repo",Y=k(v.workDir,H),x(Y))await Z`cd ${Y} && git pull --rebase`.quiet();else await Z`git clone ${Q} ${Y}`.quiet();else{if(Y=Q.startsWith("~")?Q.replace("~",NQ()):Q,!x(Y))throw Error(`Local path does not exist: ${Y}`);if(!x(k(Y,".git")))throw Error(`Not a git repository: ${Y}`);H=Y.split("/").pop()||"repo"}let G=(await Z`cd ${Y} && git branch --show-current`.quiet()).text().trim(),J=(await Z`cd ${Y} && git status --porcelain`.quiet()).text().trim().length>0,W=(await Z`cd ${Y} && git log -1 --format="%h %s"`.quiet()).text().trim(),q={path:Y,name:H,branch:G,hasChanges:J,lastCommit:W};return F.setRepo(q),F.clearHistory(),q}async function E6(Q){let Z=F.getState();if(!Z.repo)throw Error("No repository opened");let Y=[],H=/FILE:\s*([^\n]+)\n```\w*\n([\s\S]*?)```/g;for(let X of Q.matchAll(H)){let G=X[1].trim(),V=X[2],J=k(Z.repo.path,G),$=BZ(J);if(!x($))KQ($,{recursive:!0});zZ(J,V),Y.push(G)}if(Y.length>0&&Z.repo)Z.repo.hasChanges=!0;return Y}async function NZ(){let Q=F.getState();if(!Q.repo||!Q.github)return;let{$:Z}=awaitPromise.resolve(globalThis.Bun),{name:Y,email:H}=Q.github;await Z`cd ${Q.repo.path} && git config user.name ${Y}`.quiet(),await Z`cd ${Q.repo.path} && git config user.email ${H}`.quiet()}async function I6(){let Q=F.getState();if(!Q.repo)throw Error("No repository opened");let{$:Z}=awaitPromise.resolve(globalThis.Bun);if(Q.github)await NZ();await Z`cd ${Q.repo.path} && git add -A`.quiet(),await Z`cd ${Q.repo.path} && git commit -m ${v.commitMessage}`.quiet();let H=(await Z`cd ${Q.repo.path} && git rev-parse --short HEAD`.quiet()).text().trim();return Q.repo.hasChanges=!1,Q.repo.lastCommit=H,H}async function T6(){let Q=F.getState();if(!Q.repo)throw Error("No repository opened");let{$:Z}=awaitPromise.resolve(globalThis.Bun);await Z`cd ${Q.repo.path} && git push`.quiet()}async function x6(Q,Z){let Y=F.getState();if(!Y.repo)throw Error("No repository opened");let H=Z||Y.currentDriver,X=UZ(H);if(Z)F.setCurrentDriver(Z);let G=await KZ(Y.repo.path),V=OZ(G),J=await X.process(Q,V,Y.conversationHistory);return F.addToHistory({role:"user",content:Q}),F.addToHistory({role:"assistant",content:J}),J}async function D6(Q,Z,Y){let H=F.getState();if(!H.repo)throw Error("No repository opened");let X=Z||H.currentDriver,G=["claude-cli-local","claude-sdk"];if(!G.includes(X))throw Error(`Streaming only supported for ${G.join(", ")} drivers. Current: ${X}`);if(Z)F.setCurrentDriver(Z);let V=Q;if(Y&&Y.length>0){let $=`## Previous Conversation
|
|
119
|
-
Here is our conversation so far:
|
|
120
|
-
|
|
121
|
-
`;for(let W of Y){let q=W.role==="user"?"User":"Assistant";$+=`**${q}:** ${W.content}
|
|
122
|
-
|
|
123
|
-
`}$+=`---
|
|
124
|
-
|
|
125
|
-
## Current Request
|
|
126
|
-
`,V=$+Q}let J=await a.processStreaming(V,H.repo.path);return J.fullResponse.then(($)=>{F.addToHistory({role:"user",content:Q}),F.addToHistory({role:"assistant",content:$})}),J}async function C6(Q,Z){if(!T.anthropic)throw Error("Anthropic API key not set. Configure your API key in settings.");let Y=[];if(Z&&Z.length>0)for(let W of Z)Y.push({role:W.role,content:W.content});Y.push({role:"user",content:Q});let H=`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.`,X=new TextEncoder,G="",V,J=new Promise((W)=>{V=W});return{stream:new ReadableStream({async start(W){try{let q=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json","x-api-key":T.anthropic,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:"claude-sonnet-4-20250514",max_tokens:4096,system:H,stream:!0,messages:Y})});if(!q.ok){let O=await q.text();throw Error(`Claude API error: ${O}`)}let j=q.body?.getReader();if(!j)throw Error("No response body");let B=new TextDecoder,K="";while(!0){let{done:O,value:w}=await j.read();if(O)break;K+=B.decode(w,{stream:!0});let z=K.split(`
|
|
129
|
-
`);K=z.pop()||"";for(let U of z)if(U.startsWith("data: ")){let N=U.slice(6);if(N==="[DONE]")continue;try{let L=JSON.parse(N);if(L.type==="content_block_delta"&&L.delta?.text){let R=L.delta.text;G+=R,W.enqueue(X.encode(R))}}catch{}}}F.addToHistory({role:"user",content:Q}),F.addToHistory({role:"assistant",content:G}),V(G),W.close()}catch(q){V(G),W.error(q)}}}),fullResponse:J}}import LZ from"process";var n=null;async function LQ(){if(n)return n;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 n=new Q.BedrockRuntimeClient(LZ.env.REGION||"us-east-1"),n}async function YQ(Q){return(await LQ()).invokeModel(Q)}async function k6(Q){return(await LQ()).invokeModelWithResponseStream(Q)}var RZ="amazon.titan-text-express-v1";function RQ(Q){if(Q)return Q;return globalThis.config?.ai?.bedrock?.model||process.env.BEDROCK_MODEL_ID||RZ}async function h6(Q,Z={}){let{maxTokenCount:Y=512,temperature:H=0,topP:X=0.9,modelId:G}=Z;try{let V=await YQ({modelId:RQ(G),contentType:"application/json",accept:"*/*",body:JSON.stringify({inputText:`Summarize the following text: ${Q}`,textGenerationConfig:{maxTokenCount:Y,stopSequences:[],temperature:H,topP:X}})});return JSON.parse(new TextDecoder().decode(V.body)).results[0].outputText}catch(V){throw Error(`Error summarizing text: ${V.message}`)}}async function b6(Q,Z={}){let{maxTokenCount:Y=512,temperature:H=0,topP:X=0.9,modelId:G}=Z;try{let V=await YQ({modelId:RQ(G),contentType:"application/json",accept:"*/*",body:JSON.stringify({inputText:Q,textGenerationConfig:{maxTokenCount:Y,stopSequences:[],temperature:H,topP:X}})});return JSON.parse(new TextDecoder().decode(V.body)).results[0].outputText}catch(V){throw Error(`Error asking question: ${V.message}`)}}async function FZ(Q,Z={}){let{provider:Y="openai",model:H="dall-e-3",size:X="1024x1024",quality:G="standard",n:V=1,responseFormat:J="url",style:$="vivid"}=Z;if(Y==="openai")return AZ(Q,{model:H,size:X,quality:G,n:V,responseFormat:J,style:$});throw Error(`Image generation not supported for provider: ${Y}. Use 'openai'.`)}async function AZ(Q,Z){let Y=process.env.OPENAI_API_KEY;if(!Y)throw Error("OPENAI_API_KEY environment variable is required for image generation.");let H=await fetch("https://api.openai.com/v1/images/generations",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Y}`},body:JSON.stringify({model:Z.model,prompt:Q,size:Z.size,quality:Z.quality,n:Z.n,response_format:Z.responseFormat,style:Z.style})});if(!H.ok){let G=await H.text();throw Error(`OpenAI Image API error: ${G}`)}return{images:(await H.json()).data.map((G)=>({url:G.url,b64_json:G.b64_json,revisedPrompt:G.revised_prompt})),provider:"openai",model:Z.model}}async function MZ(Q,Z,Y={}){let H=process.env.OPENAI_API_KEY;if(!H)throw Error("OPENAI_API_KEY environment variable is required for image editing.");let X=new FormData;if(X.append("image",Q),X.append("prompt",Z),X.append("model",Y.model||"dall-e-2"),Y.mask)X.append("mask",Y.mask);if(Y.n)X.append("n",String(Y.n));if(Y.size)X.append("size",Y.size);if(Y.responseFormat)X.append("response_format",Y.responseFormat);let G=await fetch("https://api.openai.com/v1/images/edits",{method:"POST",headers:{Authorization:`Bearer ${H}`},body:X});if(!G.ok){let J=await G.text();throw Error(`OpenAI Image Edit API error: ${J}`)}return{images:(await G.json()).data.map((J)=>({url:J.url,b64_json:J.b64_json})),provider:"openai",model:Y.model||"dall-e-2"}}async function _Z(Q,Z={}){let Y=process.env.OPENAI_API_KEY;if(!Y)throw Error("OPENAI_API_KEY environment variable is required for image variations.");let H=new FormData;if(H.append("image",Q),H.append("model",Z.model||"dall-e-2"),Z.n)H.append("n",String(Z.n));if(Z.size)H.append("size",Z.size);if(Z.responseFormat)H.append("response_format",Z.responseFormat);let X=await fetch("https://api.openai.com/v1/images/variations",{method:"POST",headers:{Authorization:`Bearer ${Y}`},body:H});if(!X.ok){let V=await X.text();throw Error(`OpenAI Image Variations API error: ${V}`)}return{images:(await X.json()).data.map((V)=>({url:V.url,b64_json:V.b64_json})),provider:"openai",model:Z.model||"dall-e-2"}}async function EZ(Q,Z,Y={}){let{provider:H="anthropic"}=Y;switch(H){case"anthropic":return IZ(Q,Z,Y);case"openai":return TZ(Q,Z,Y);case"ollama":return xZ(Q,Z,Y);default:throw Error(`Vision not supported for provider: ${H}`)}}async function u(Q){if(Q.type==="base64")return{data:Q.data,mediaType:Q.mediaType};if(Q.type==="url"){let Z=await fetch(Q.url);if(!Z.ok)throw Error(`Failed to fetch image from URL: ${Q.url}`);let Y=await Z.arrayBuffer(),H=Buffer.from(Y).toString("base64"),X=Z.headers.get("content-type")||"image/png";return{data:H,mediaType:X}}if(Q.type==="file"){let{readFile:Z}=await import("fs/promises"),H=(await Z(Q.path)).toString("base64"),X=Q.path.split(".").pop()?.toLowerCase()||"png";return{data:H,mediaType:{png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp"}[X]||"image/png"}}throw Error("Invalid image input type")}async function IZ(Q,Z,Y){let H=process.env.ANTHROPIC_API_KEY;if(!H)throw Error("ANTHROPIC_API_KEY environment variable is required for Claude vision.");let{data:X,mediaType:G}=await u(Q),V=Y.model||"claude-sonnet-4-20250514",J=Y.maxTokens||4096,$=[{role:"user",content:[{type:"image",source:{type:"base64",media_type:G,data:X}},{type:"text",text:Z}]}],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:V,max_tokens:J,temperature:Y.temperature,messages:$})});if(!W.ok){let j=await W.text();throw Error(`Claude Vision API error: ${j}`)}let q=await W.json();return{content:q.content[0].text,model:q.model,provider:"anthropic",usage:{promptTokens:q.usage?.input_tokens||0,completionTokens:q.usage?.output_tokens||0,totalTokens:(q.usage?.input_tokens||0)+(q.usage?.output_tokens||0)},finishReason:q.stop_reason}}async function TZ(Q,Z,Y){let H=process.env.OPENAI_API_KEY;if(!H)throw Error("OPENAI_API_KEY environment variable is required for GPT-4 vision.");let X=Y.model||"gpt-4o",G=Y.maxTokens||4096,V=Y.detail||"auto",J;if(Q.type==="url")J={type:"image_url",image_url:{url:Q.url,detail:V}};else{let{data:q,mediaType:j}=await u(Q);J={type:"image_url",image_url:{url:`data:${j};base64,${q}`,detail:V}}}let $=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${H}`},body:JSON.stringify({model:X,max_tokens:G,temperature:Y.temperature,messages:[{role:"user",content:[J,{type:"text",text:Z}]}]})});if(!$.ok){let q=await $.text();throw Error(`OpenAI Vision API error: ${q}`)}let W=await $.json();return{content:W.choices[0].message.content,model:W.model,provider:"openai",usage:{promptTokens:W.usage?.prompt_tokens||0,completionTokens:W.usage?.completion_tokens||0,totalTokens:W.usage?.total_tokens||0},finishReason:W.choices[0].finish_reason}}async function xZ(Q,Z,Y){let H=process.env.OLLAMA_HOST||"http://localhost:11434",X=Y.model||"llava",{data:G}=await u(Q),V=await fetch(`${H}/api/generate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:X,prompt:Z,images:[G],stream:!1})});if(!V.ok){let $=await V.text();throw Error(`Ollama Vision API error: ${$}`)}let J=await V.json();return{content:J.response,model:J.model,provider:"ollama",usage:{promptTokens:J.prompt_eval_count||0,completionTokens:J.eval_count||0,totalTokens:(J.prompt_eval_count||0)+(J.eval_count||0)}}}async function DZ(Q,Z,Y={}){let{provider:H="anthropic"}=Y;if(H==="anthropic"){let X=process.env.ANTHROPIC_API_KEY;if(!X)throw Error("ANTHROPIC_API_KEY required for multi-image analysis.");let G=Y.model||"claude-sonnet-4-20250514",V=[];for(let W of Q){let{data:q,mediaType:j}=await u(W);V.push({type:"image",source:{type:"base64",media_type:j,data:q}})}V.push({type:"text",text:Z});let J=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json","x-api-key":X,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:G,max_tokens:Y.maxTokens||4096,temperature:Y.temperature,messages:[{role:"user",content:V}]})});if(!J.ok){let W=await J.text();throw Error(`Claude Vision API error: ${W}`)}let $=await J.json();return{content:$.content[0].text,model:$.model,provider:"anthropic",usage:{promptTokens:$.usage?.input_tokens||0,completionTokens:$.usage?.output_tokens||0,totalTokens:($.usage?.input_tokens||0)+($.usage?.output_tokens||0)},finishReason:$.stop_reason}}if(H==="openai"){let X=process.env.OPENAI_API_KEY;if(!X)throw Error("OPENAI_API_KEY required for multi-image analysis.");let G=Y.model||"gpt-4o",V=Y.detail||"auto",J=[];for(let q of Q)if(q.type==="url")J.push({type:"image_url",image_url:{url:q.url,detail:V}});else{let{data:j,mediaType:B}=await u(q);J.push({type:"image_url",image_url:{url:`data:${B};base64,${j}`,detail:V}})}J.push({type:"text",text:Z});let $=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${X}`},body:JSON.stringify({model:G,max_tokens:Y.maxTokens||4096,temperature:Y.temperature,messages:[{role:"user",content:J}]})});if(!$.ok){let q=await $.text();throw Error(`OpenAI Vision API error: ${q}`)}let W=await $.json();return{content:W.choices[0].message.content,model:W.model,provider:"openai",usage:{promptTokens:W.usage?.prompt_tokens||0,completionTokens:W.usage?.completion_tokens||0,totalTokens:W.usage?.total_tokens||0},finishReason:W.choices[0].finish_reason}}throw Error(`Multi-image analysis not supported for provider: ${H}`)}var g6={generate:FZ,edit:MZ,variation:_Z,analyze:EZ,analyzeMultiple:DZ};async function HQ(Q,Z={}){let{provider:Y="openai"}=Z;if(Y==="openai")return CZ(Q,Z.model||"text-embedding-3-small");if(Y==="ollama")return SZ(Q,Z.model||"nomic-embed-text");throw Error(`Embedding provider not supported: ${Y}`)}async function CZ(Q,Z){let Y=process.env.OPENAI_API_KEY;if(!Y)throw Error("OPENAI_API_KEY environment variable is required for embeddings.");let H=await fetch("https://api.openai.com/v1/embeddings",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Y}`},body:JSON.stringify({model:Z,input:Q})});if(!H.ok){let V=await H.text();throw Error(`OpenAI Embeddings API error: ${V}`)}let X=await H.json();if(Array.isArray(Q))return X.data.map((V)=>V.embedding);let G=X.data[0];if(!G)throw Error("OpenAI Embeddings API returned no embedding");return G.embedding}async function SZ(Q,Z){let Y=process.env.OLLAMA_HOST||"http://localhost:11434",H=Array.isArray(Q)?Q:[Q],X=[];for(let V of H){let J=await fetch(`${Y}/api/embeddings`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:Z,prompt:V})});if(!J.ok){let W=await J.text();throw Error(`Ollama Embeddings API error: ${W}`)}let $=await J.json();X.push($.embedding)}if(Array.isArray(Q))return X;let G=X[0];if(!G)throw Error("Ollama Embeddings API returned no embedding");return G}function FQ(Q,Z){if(Q.length!==Z.length)throw Error(`Vector dimensions must match: ${Q.length} vs ${Z.length}`);let Y=0,H=0,X=0;for(let V=0;V<Q.length;V++){let J=Q[V],$=Z[V];Y+=J*$,H+=J*J,X+=$*$}let G=Math.sqrt(H)*Math.sqrt(X);if(G===0)return 0;return Y/G}function PZ(Q,Z){if(Q.length!==Z.length)throw Error(`Vector dimensions must match: ${Q.length} vs ${Z.length}`);let Y=0;for(let H=0;H<Q.length;H++)Y+=Q[H]*Z[H];return Y}function kZ(Q,Z){if(Q.length!==Z.length)throw Error(`Vector dimensions must match: ${Q.length} vs ${Z.length}`);let Y=0;for(let H=0;H<Q.length;H++){let X=Q[H]-Z[H];Y+=X*X}return Math.sqrt(Y)}class XQ{documents=[];embeddingOptions;constructor(Q={}){this.embeddingOptions=Q}async add(Q){if(Q.length===0)return;let Z=Q.map((H)=>H.content),Y=await HQ(Z,this.embeddingOptions);for(let H=0;H<Q.length;H++){let X=Q[H],G=Y[H];if(!X||!G)continue;this.documents.push({...X,embedding:G})}}addWithEmbedding(Q,Z){this.documents.push({...Q,embedding:Z})}async search(Q,Z=5){if(this.documents.length===0)return[];let Y=await HQ(Q,this.embeddingOptions);return this.searchByVector(Y,Z)}searchByVector(Q,Z=5){if(this.documents.length===0)return[];let Y=this.documents.map((H)=>({document:{id:H.id,content:H.content,metadata:H.metadata},score:FQ(Q,H.embedding)}));return Y.sort((H,X)=>X.score-H.score),Y.slice(0,Z).map((H,X)=>({...H,rank:X+1}))}remove(Q){let Z=this.documents.length;return this.documents=this.documents.filter((Y)=>Y.id!==Q),this.documents.length<Z}clear(){this.documents=[]}get size(){return this.documents.length}get ids(){return this.documents.map((Q)=>Q.id)}}async function vZ(Q,Z,Y={}){let{provider:H="anthropic",topK:X=5,maxTokens:G=4096,temperature:V,systemPrompt:J}=Y,$=await Z.search(Q,X),W=$.map((B,K)=>`[Source ${K+1}] (score: ${B.score.toFixed(3)})
|
|
130
|
-
${B.document.content}`).join(`
|
|
131
|
-
|
|
132
|
-
---
|
|
133
|
-
|
|
134
|
-
`),q=J||"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].",j=`Context:
|
|
135
|
-
${W}
|
|
136
|
-
|
|
137
|
-
Question: ${Q}`;if(H==="anthropic")return yZ(j,q,$,{maxTokens:G,temperature:V,model:Y.model});if(H==="openai")return hZ(j,q,$,{maxTokens:G,temperature:V,model:Y.model});if(H==="ollama")return bZ(j,q,$,{maxTokens:G,temperature:V,model:Y.model});throw Error(`RAG provider not supported: ${H}`)}async function yZ(Q,Z,Y,H){let X=process.env.ANTHROPIC_API_KEY;if(!X)throw Error("ANTHROPIC_API_KEY required for RAG with Anthropic.");let G=H.model||"claude-sonnet-4-20250514",V=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json","x-api-key":X,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:G,max_tokens:H.maxTokens||4096,temperature:H.temperature,system:Z,messages:[{role:"user",content:Q}]})});if(!V.ok){let $=await V.text();throw Error(`Claude API error: ${$}`)}let J=await V.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,sources:Y}}async function hZ(Q,Z,Y,H){let X=process.env.OPENAI_API_KEY;if(!X)throw Error("OPENAI_API_KEY required for RAG with OpenAI.");let G=H.model||"gpt-4o",V=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${X}`},body:JSON.stringify({model:G,max_tokens:H.maxTokens||4096,temperature:H.temperature,messages:[{role:"system",content:Z},{role:"user",content:Q}]})});if(!V.ok){let $=await V.text();throw Error(`OpenAI API error: ${$}`)}let J=await V.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,sources:Y}}async function bZ(Q,Z,Y,H){let X=process.env.OLLAMA_HOST||"http://localhost:11434",G=H.model||"llama3.2",V=await fetch(`${X}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:G,messages:[{role:"system",content:Z},{role:"user",content:Q}],stream:!1,options:{temperature:H.temperature}})});if(!V.ok){let $=await V.text();throw Error(`Ollama API error: ${$}`)}let J=await V.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",sources:Y}}function AQ(Q,Z={}){let{chunkSize:Y=1000,chunkOverlap:H=200,separator:X=`
|
|
138
|
-
`}=Z,G=Q.split(X),V=[],J="";for(let $ of G)if(J.length+$.length+1>Y&&J.length>0)if(V.push(J.trim()),H>0){let W=Math.max(0,J.length-H);J=J.slice(W)+X+$}else J=$;else J+=(J?X:"")+$;if(J.trim())V.push(J.trim());return V}async function fZ(Q,Z={}){let Y=AQ(Q,Z),H=new XQ(Z),X=Y.map((G,V)=>({id:`${Z.idPrefix||"chunk"}-${V}`,content:G,metadata:{chunkIndex:V,totalChunks:Y.length}}));return await H.add(X),H}var c6={createEmbedding:HQ,cosineSimilarity:FQ,dotProduct:PZ,euclideanDistance:kZ,VectorIndex:XQ,rag:vZ,chunkText:AQ,indexText:fZ};async function gZ(Q,Z={}){let{provider:Y="anthropic",aspects:H}=Z,X=H?`
|
|
139
|
-
Also analyze sentiment for these specific aspects: ${H.join(", ")}`:"",G=`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>${H?`,
|
|
144
|
-
"aspects": [{"aspect": "<name>", "sentiment": "positive" | "negative" | "neutral", "score": <number>}]`:""}
|
|
145
|
-
}${X}`,V=await c(Y,G,Q,Z.model);try{return JSON.parse(V.content)}catch{let J=V.content.toLowerCase(),$=J.includes("positive"),W=J.includes("negative");return{sentiment:$&&W?"mixed":$?"positive":W?"negative":"neutral",score:$?0.5:W?-0.5:0,confidence:0.5}}}async function uZ(Q,Z,Y={}){let{provider:H="anthropic",multiLabel:X=!1}=Y,G=`You are a text classification expert. Classify the given text into ${X?"one or more of":"exactly one of"} these categories: ${Z.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.`,V=await c(H,G,Q,Y.model);try{return JSON.parse(V.content)}catch{return{label:Z[0]??"",confidence:0.5,allLabels:Z.map((J)=>({label:J,confidence:1/Z.length}))}}}async function cZ(Q,Z={}){let{provider:Y="anthropic",style:H="concise",maxLength:X,language:G}=Z,V;switch(H){case"bullet-points":V="Use bullet points to organize the key points.";break;case"detailed":V="Provide a detailed summary covering all major points.";break;default:V="Be concise and focus on the most important points."}let J=X?` Keep the summary under ${X} words.`:"",$=G?` Write the summary in ${G}.`:"",W=`You are an expert summarizer. ${V}${J}${$}`;return c(Y,W,`Summarize the following text:
|
|
155
|
-
|
|
156
|
-
${Q}`,Z.model)}async function dZ(Q,Z,Y={}){let{provider:H="anthropic",limit:X=5}=Y,G=lZ(Q),V=Z.map((q)=>`ID: ${q.id} | Category: ${q.category||"none"} | Tags: ${q.tags?.join(", ")||"none"} | Content: ${q.content.slice(0,200)}`).join(`
|
|
157
|
-
`),J=`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 ${X} recommendations, sorted by relevance score descending.`,$=`User Profile:
|
|
165
|
-
${G}
|
|
166
|
-
|
|
167
|
-
Available Items:
|
|
168
|
-
${V}`,W=await c(H,J,$,Y.model);try{return{recommendations:JSON.parse(W.content).recommendations.slice(0,X),model:W.model,provider:H}}catch{return{recommendations:[],model:W.model,provider:H}}}function lZ(Q){let Z=Object.entries(Q.preferences).sort(([,H],[,X])=>X-H).slice(0,10).map(([H,X])=>`${H}: ${X.toFixed(2)}`).join(", "),Y=Q.interactions.sort((H,X)=>X.timestamp-H.timestamp).slice(0,10).map((H)=>`${H.type} on ${H.itemId}`).join(", ");return`Segments: ${Q.segments.join(", ")}
|
|
169
|
-
Top Preferences: ${Z||"none"}
|
|
170
|
-
Recent Interactions: ${Y||"none"}`}function mZ(Q,Z=[]){return{id:Q,preferences:{},interactions:[],segments:Z}}function pZ(Q,Z){Q.interactions.push(Z);let H={view:0.1,click:0.3,like:0.5,share:0.6,bookmark:0.7,purchase:1,dislike:-0.5,custom:Z.weight||0.3}[Z.type]||0.1,X=Z.itemId;return Q.preferences[X]=(Q.preferences[X]||0)+H,Q}async function iZ(Q,Z,Y={}){let{provider:H="anthropic"}=Y,X=new Set(Q.interactions.map((W)=>W.itemId)),G=Z.filter((W)=>X.has(W.id));if(G.length===0)return Q.segments;let V=G.slice(0,20).map((W)=>W.content.slice(0,200)).join(`
|
|
171
|
-
---
|
|
172
|
-
`),$=await c(H,`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.`,V,Y.model);try{return JSON.parse($.content)}catch{return Q.segments}}async function c(Q,Z,Y,H){if(Q==="anthropic"){let X=process.env.ANTHROPIC_API_KEY;if(!X)throw Error("ANTHROPIC_API_KEY required.");let G=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json","x-api-key":X,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:H||"claude-sonnet-4-20250514",max_tokens:4096,system:Z,messages:[{role:"user",content:Y}]})});if(!G.ok){let J=await G.text();throw Error(`Claude API error: ${J}`)}let V=await G.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}}if(Q==="openai"){let X=process.env.OPENAI_API_KEY;if(!X)throw Error("OPENAI_API_KEY required.");let G=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${X}`},body:JSON.stringify({model:H||"gpt-4o",max_tokens:4096,messages:[{role:"system",content:Z},{role:"user",content:Y}]})});if(!G.ok){let J=await G.text();throw Error(`OpenAI API error: ${J}`)}let V=await G.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}}if(Q==="ollama"){let X=process.env.OLLAMA_HOST||"http://localhost:11434",G=await fetch(`${X}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:H||"llama3.2",messages:[{role:"system",content:Z},{role:"user",content:Y}],stream:!1})});if(!G.ok){let J=await G.text();throw Error(`Ollama API error: ${J}`)}let V=await G.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"}}throw Error(`Provider not supported: ${Q}`)}var l6={analyzeSentiment:gZ,classifyText:uZ,summarize:cZ,recommend:dZ,createProfile:mZ,recordInteraction:pZ,extractUserInterests:iZ};class d{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:Z}=awaitPromise.resolve(globalThis.Bun);this.process=Z([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,Z=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(!Z.ok){let Y=await Z.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 Z=new TextDecoder;try{while(!0){let{done:Y,value:H}=await Q.read();if(Y)break;this.buffer+=Z.decode(H,{stream:!0}),this.processBuffer()}}catch{}}processBuffer(){let Q=this.buffer.split(`
|
|
173
|
-
`);this.buffer=Q.pop()||"";for(let Z of Q){if(!Z.trim())continue;try{let Y=JSON.parse(Z);if(Y.id!==void 0&&this.pendingRequests.has(Y.id)){let H=this.pendingRequests.get(Y.id);if(this.pendingRequests.delete(Y.id),Y.error)H.reject(Error(Y.error.message||"MCP error"));else H.resolve(Y.result)}}catch{}}}nextId(){return++this.requestId}async sendRequest(Q,Z={}){let Y=this.nextId(),H=JSON.stringify({jsonrpc:"2.0",id:Y,method:Q,params:Z})+`
|
|
174
|
-
`;if(this.config.transport.type==="stdio"&&this.process){let X=this.process.stdin?.getWriter();if(X)await X.write(new TextEncoder().encode(H)),X.releaseLock();return new Promise((G,V)=>{let J=setTimeout(()=>{this.pendingRequests.delete(Y),V(Error(`MCP request timeout: ${Q}`))},30000);this.pendingRequests.set(Y,{resolve:($)=>{clearTimeout(J),G($)},reject:($)=>{clearTimeout(J),V($)}})})}if(this.config.transport.type==="sse"||this.config.transport.type==="streamable-http"){let X=this.config.transport,G=await fetch(X.url,{method:"POST",headers:{"Content-Type":"application/json",...X.headers},body:H});if(!G.ok){let J=await G.text();throw Error(`MCP request error: ${J}`)}let V=await G.json();if(V.error)throw Error(V.error.message||"MCP error");return V.result}throw Error("No transport available")}async sendNotification(Q,Z={}){let Y=JSON.stringify({jsonrpc:"2.0",method:Q,params:Z})+`
|
|
175
|
-
`;if(this.config.transport.type==="stdio"&&this.process){let H=this.process.stdin?.getWriter();if(H)await H.write(new TextEncoder().encode(Y)),H.releaseLock()}}async discoverCapabilities(){let Q=this.config.capabilities||{tools:!0,resources:!0,prompts:!0};if(Q.tools!==!1)try{let Z=await this.sendRequest("tools/list");this.tools=Z?.tools||[]}catch{this.tools=[]}if(Q.resources!==!1)try{let Z=await this.sendRequest("resources/list");this.resources=Z?.resources||[]}catch{this.resources=[]}if(Q.prompts!==!1)try{let Z=await this.sendRequest("prompts/list");this.prompts=Z?.prompts||[]}catch{this.prompts=[]}}listTools(){return this.tools}listResources(){return this.resources}listPrompts(){return this.prompts}async callTool(Q,Z={}){if(!this.initialized)throw Error("MCP client not connected. Call connect() first.");return await this.sendRequest("tools/call",{name:Q,arguments:Z})}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,Z={}){if(!this.initialized)throw Error("MCP client not connected. Call connect() first.");return this.sendRequest("prompts/get",{name:Q,arguments:Z})}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 MQ{clients=new Map;async addServer(Q){if(this.clients.has(Q.name))throw Error(`MCP server already registered: ${Q.name}`);let Z=new d(Q);return await Z.connect(),this.clients.set(Q.name,Z),Z}async removeServer(Q){let Z=this.clients.get(Q);if(Z)await Z.disconnect(),this.clients.delete(Q)}getServer(Q){return this.clients.get(Q)}listServers(){return Array.from(this.clients.keys())}getAllTools(){let Q=[];for(let[Z,Y]of this.clients)for(let H of Y.listTools())Q.push({...H,serverName:Z});return Q}async callTool(Q,Z={}){if(Q.includes("/")){let[Y,H]=Q.split("/",2);if(!Y||!H)throw Error(`Invalid MCP tool path: ${Q}`);let X=this.clients.get(Y);if(!X)throw Error(`MCP server not found: ${Y}`);return X.callTool(H,Z)}for(let[,Y]of this.clients)if(Y.listTools().some((X)=>X.name===Q))return Y.callTool(Q,Z);throw Error(`MCP tool not found: ${Q}`)}toAnthropicTools(){let Q=[];for(let[Z,Y]of this.clients)for(let H of Y.listTools())Q.push({name:`${Z}__${H.name}`,description:`[${Z}] ${H.description}`,input_schema:H.inputSchema});return Q}toOpenAITools(){let Q=[];for(let[Z,Y]of this.clients)for(let H of Y.listTools())Q.push({type:"function",function:{name:`${Z}__${H.name}`,description:`[${Z}] ${H.description}`,parameters:H.inputSchema}});return Q}async disconnectAll(){let Q=Array.from(this.clients.values()).map((Z)=>Z.disconnect());await Promise.all(Q),this.clients.clear()}}async function aZ(Q,Z,Y,H){let X=new d({name:Q,transport:{type:"stdio",command:Z,args:Y,env:H}});return await X.connect(),X}async function nZ(Q,Z,Y){let H=new d({name:Q,transport:{type:"streamable-http",url:Z,headers:Y}});return await H.connect(),H}var p6={MCPClient:d,MCPManager:MQ,connectStdio:aZ,connectHTTP:nZ};import rZ from"process";var r=null;async function JQ(){if(r)return r;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 r=new Q.BedrockClient(rZ.env.REGION||"us-east-1"),r}async function n6(Q){return(await JQ()).createModelCustomizationJob(Q)}async function r6(Q){return(await JQ()).getModelCustomizationJob(Q)}async function s6(Q){return(await JQ()).listFoundationModels(Q)}import{log as VQ}from"@stacksjs/cli";import{ai as sZ}from"@stacksjs/config";async function tZ(){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 Q9(){let Q=await tZ(),Z=sZ.models;if(!Z)throw Error("No AI models found. Please set ./config/ai.ts values.");for(let Y of Z)try{VQ.info(`Requesting access to model ${Y}`);let H=await Q.requestModelAccess({modelId:Y});VQ.info(`Response for model ${Y}:`,H)}catch(H){VQ.error(`Error requesting access to model ${Y}:`,H)}}export{h6 as summarize,c6 as search,T9 as sanitizePrompt,jZ as resetPromptCount,Q9 as requestModelAccess,M9 as recordUsage,pZ as recordInteraction,dZ as recommend,vZ as rag,T6 as pushChanges,qZ as processCommandStreaming,x6 as processCommand,l6 as personalization,mQ as openaiDriver,pQ as openai,_6 as openRepository,A9 as onUsage,YZ as ollamaDriver,HZ as ollama,U9 as normalizeMessagesForProvider,p6 as mcp,F9 as listUsageReporters,s6 as listFoundationModels,k6 as invokeModelWithResponseStream,YQ as invokeModel,fZ as indexText,g6 as image,KZ as getRepoContext,r6 as getModelCustomizationJob,BQ as getLastSessionId,UZ as getDriver,M6 as getAvailableDrivers,FZ as generateImage,N9 as fetchWithRetry,iZ as extractUserInterests,kZ as euclideanDistance,I9 as estimateTokens,E9 as estimateMessageTokens,MZ as editImage,PZ as dotProduct,mZ as createProfile,b as createOpenAIDriver,g as createOllamaDriver,n6 as createModelCustomizationJob,_Z as createImageVariation,HQ as createEmbedding,$Z as createClaudeLocalAgent,WZ as createClaudeEC2Agent,i as createClaudeAgentSDKDriver,h as createAnthropicDriver,FQ as cosineSimilarity,aZ as connectStdio,nZ as connectHTTP,NZ as configureGitUser,I6 as commitChanges,R9 as clearUsageReporters,OQ as clearSession,VZ as claudeAgentSDK,a as claudeAgent,uZ as classifyText,AQ as chunkText,OZ as buildSystemPrompt,w9 as buildMessageWithImages,C6 as buddyStreamSimple,F as buddyState,D6 as buddyProcessStreaming,b6 as ask,E6 as applyChanges,T as apiKeys,yQ as anthropicDriver,hQ as anthropic,gZ as analyzeSentiment,DZ as analyzeImages,EZ as analyzeImage,XQ as VectorIndex,MQ as MCPManager,d as MCPClient,v as CONFIG};
|
|
1
|
+
export * from "./types";
|
|
2
|
+
export * from "./drivers";
|
|
3
|
+
export * from "./agents";
|
|
4
|
+
export * from "./buddy";
|
|
5
|
+
export * from "./text";
|
|
6
|
+
export * from "./image";
|
|
7
|
+
export * from "./search";
|
|
8
|
+
export * from "./personalization";
|
|
9
|
+
export * from "./mcp";
|
|
10
|
+
export * from "./utils/client-bedrock";
|
|
11
|
+
export * from "./utils/client-bedrock-runtime";
|
|
12
|
+
export { buildMessageWithImages, normalizeMessagesForProvider } from "./utils/vision";
|
|
13
|
+
export { fetchWithRetry } from "./utils/retry";
|
|
14
|
+
export { clearUsageReporters, listUsageReporters, onUsage, recordUsage } from "./utils/usage";
|
|
15
|
+
export { estimateMessageTokens, estimateTokens, sanitizePrompt } from "./utils/tokens";
|
|
16
|
+
export * from "./utils/model-access";
|