@stacksjs/ai 0.70.88 → 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.d.ts +29 -0
- package/dist/agents/claude/index.js +197 -0
- package/dist/agents/index.d.ts +6 -0
- package/dist/agents/index.js +1 -0
- package/dist/buddy.d.ts +67 -0
- package/dist/buddy.js +393 -0
- package/dist/drivers/anthropic/index.d.ts +40 -0
- package/dist/drivers/anthropic/index.js +276 -0
- package/dist/drivers/claude-agent-sdk/index.d.ts +40 -0
- package/dist/drivers/claude-agent-sdk/index.js +198 -0
- package/dist/drivers/index.d.ts +13 -0
- package/dist/drivers/index.js +4 -0
- package/dist/drivers/ollama/index.d.ts +93 -0
- package/dist/drivers/ollama/index.js +332 -0
- package/dist/drivers/openai/index.d.ts +66 -0
- package/dist/drivers/openai/index.js +351 -0
- package/dist/image.d.ts +83 -0
- package/dist/image.js +375 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.js +16 -0
- package/dist/mcp.d.ts +115 -0
- package/dist/mcp.js +361 -0
- package/dist/personalization.d.ts +118 -0
- package/dist/personalization.js +244 -0
- package/dist/search.d.ts +101 -0
- package/dist/search.js +316 -0
- package/dist/text.d.ts +10 -0
- package/dist/text.js +51 -0
- package/dist/types.d.ts +185 -0
- package/dist/types.js +0 -0
- package/dist/utils/client-bedrock-runtime.d.ts +16 -0
- package/dist/utils/client-bedrock-runtime.js +17 -0
- package/dist/utils/client-bedrock.d.ts +27 -0
- package/dist/utils/client-bedrock.js +20 -0
- package/dist/utils/model-access.d.ts +1 -0
- package/dist/utils/model-access.js +21 -0
- package/dist/utils/retry.d.ts +38 -0
- package/dist/utils/retry.js +39 -0
- package/dist/utils/tokens.d.ts +50 -0
- package/dist/utils/tokens.js +59 -0
- package/dist/utils/usage.d.ts +56 -0
- package/dist/utils/usage.js +27 -0
- package/dist/utils/vision.d.ts +22 -0
- package/dist/utils/vision.js +54 -0
- package/package.json +1 -1
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { AIDriver, AIDriverConfig, AIMessage, AIResult, ChatCompletionOptions } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Configure Anthropic globally
|
|
4
|
+
*/
|
|
5
|
+
export declare function configure(config: AnthropicDriverConfig): void;
|
|
6
|
+
export declare function createAnthropicDriver(config: AnthropicDriverConfig): AIDriver;
|
|
7
|
+
/**
|
|
8
|
+
* Chat completion with full options. Supports tools + structured
|
|
9
|
+
* output via `responseFormat` (stacksjs/stacks#1878 A-1).
|
|
10
|
+
*/
|
|
11
|
+
export declare function chat(messages: AIMessage[], options?: ChatCompletionOptions & { system?: string }): Promise<AIResult>;
|
|
12
|
+
/**
|
|
13
|
+
* Stream chat completion
|
|
14
|
+
*/
|
|
15
|
+
export declare function streamChat(messages: AIMessage[], options?: ChatCompletionOptions & { system?: string }): AsyncGenerator<string>;
|
|
16
|
+
/**
|
|
17
|
+
* Simple prompt helper
|
|
18
|
+
*/
|
|
19
|
+
export declare function prompt(text: string, options?: ChatCompletionOptions & { system?: string }): Promise<string>;
|
|
20
|
+
/**
|
|
21
|
+
* Count tokens (approximate)
|
|
22
|
+
* Note: This is a rough estimate. For accurate counts, use the tokenizer.
|
|
23
|
+
*/
|
|
24
|
+
export declare function estimateTokens(text: string): number;
|
|
25
|
+
export declare const anthropicDriver: { create: typeof createAnthropicDriver };
|
|
26
|
+
export declare const anthropic: {
|
|
27
|
+
configure: typeof configure;
|
|
28
|
+
chat: typeof chat;
|
|
29
|
+
streamChat: typeof streamChat;
|
|
30
|
+
prompt: typeof prompt;
|
|
31
|
+
estimateTokens: typeof estimateTokens;
|
|
32
|
+
createDriver: unknown
|
|
33
|
+
};
|
|
34
|
+
export declare interface AnthropicDriverConfig extends AIDriverConfig {
|
|
35
|
+
apiKey: string
|
|
36
|
+
model?: string
|
|
37
|
+
maxTokens?: number
|
|
38
|
+
anthropicVersion?: string
|
|
39
|
+
}
|
|
40
|
+
export default anthropic;
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { fetchWithRetry } from "../../utils/retry";
|
|
2
|
+
import { recordUsage } from "../../utils/usage";
|
|
3
|
+
import { normalizeMessagesForProvider } from "../../utils/vision";
|
|
4
|
+
const DEFAULT_MODEL = "claude-sonnet-4-20250514", DEFAULT_MAX_TOKENS = 4096, DEFAULT_VERSION = "2023-06-01", BASE_URL = "https://api.anthropic.com/v1";
|
|
5
|
+
let globalConfig = null;
|
|
6
|
+
export function configure(config) {
|
|
7
|
+
globalConfig = config;
|
|
8
|
+
}
|
|
9
|
+
function getConfig(config) {
|
|
10
|
+
const merged = { ...globalConfig, ...config };
|
|
11
|
+
if (!merged.apiKey)
|
|
12
|
+
merged.apiKey = process.env.ANTHROPIC_API_KEY || "";
|
|
13
|
+
return merged;
|
|
14
|
+
}
|
|
15
|
+
export function createAnthropicDriver(config) {
|
|
16
|
+
const {
|
|
17
|
+
apiKey,
|
|
18
|
+
model = DEFAULT_MODEL,
|
|
19
|
+
maxTokens = DEFAULT_MAX_TOKENS,
|
|
20
|
+
anthropicVersion = DEFAULT_VERSION
|
|
21
|
+
} = config;
|
|
22
|
+
return {
|
|
23
|
+
name: "Claude API",
|
|
24
|
+
async process(command, systemPrompt, history) {
|
|
25
|
+
if (!apiKey)
|
|
26
|
+
throw Error("Anthropic API key not set. Configure your API key in settings.");
|
|
27
|
+
const response = await fetchWithRetry(`${BASE_URL}/messages`, {
|
|
28
|
+
method: "POST",
|
|
29
|
+
headers: {
|
|
30
|
+
"Content-Type": "application/json",
|
|
31
|
+
"x-api-key": apiKey,
|
|
32
|
+
"anthropic-version": anthropicVersion
|
|
33
|
+
},
|
|
34
|
+
body: JSON.stringify({
|
|
35
|
+
model,
|
|
36
|
+
max_tokens: maxTokens,
|
|
37
|
+
system: systemPrompt,
|
|
38
|
+
messages: [...history, { role: "user", content: command }]
|
|
39
|
+
})
|
|
40
|
+
});
|
|
41
|
+
if (!response.ok) {
|
|
42
|
+
const error = await response.text();
|
|
43
|
+
throw Error(`Claude API error: ${error}`);
|
|
44
|
+
}
|
|
45
|
+
const data = await response.json();
|
|
46
|
+
if (!data.content || data.content.length === 0)
|
|
47
|
+
throw Error("Claude API returned empty content");
|
|
48
|
+
return data.content[0].text;
|
|
49
|
+
},
|
|
50
|
+
async* stream(command, systemPrompt, history) {
|
|
51
|
+
if (!apiKey)
|
|
52
|
+
throw Error("Anthropic API key not set. Configure your API key in settings.");
|
|
53
|
+
const response = await fetch(`${BASE_URL}/messages`, {
|
|
54
|
+
method: "POST",
|
|
55
|
+
headers: {
|
|
56
|
+
"Content-Type": "application/json",
|
|
57
|
+
"x-api-key": apiKey,
|
|
58
|
+
"anthropic-version": anthropicVersion
|
|
59
|
+
},
|
|
60
|
+
body: JSON.stringify({
|
|
61
|
+
model,
|
|
62
|
+
max_tokens: maxTokens,
|
|
63
|
+
system: systemPrompt,
|
|
64
|
+
stream: !0,
|
|
65
|
+
messages: [...history, { role: "user", content: command }]
|
|
66
|
+
})
|
|
67
|
+
});
|
|
68
|
+
if (!response.ok) {
|
|
69
|
+
const error = await response.text();
|
|
70
|
+
throw Error(`Claude API error: ${error}`);
|
|
71
|
+
}
|
|
72
|
+
const reader = response.body?.getReader();
|
|
73
|
+
if (!reader)
|
|
74
|
+
throw Error("No response body");
|
|
75
|
+
const decoder = new TextDecoder;
|
|
76
|
+
let buffer = "";
|
|
77
|
+
const handlePayload = function* (data) {
|
|
78
|
+
if (data === "[DONE]")
|
|
79
|
+
return;
|
|
80
|
+
let event;
|
|
81
|
+
try {
|
|
82
|
+
event = JSON.parse(data);
|
|
83
|
+
} catch {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (event.type === "error") {
|
|
87
|
+
const msg = event.error?.message ?? JSON.stringify(event.error ?? event);
|
|
88
|
+
throw Error(`[anthropic/stream] mid-stream error: ${msg}`);
|
|
89
|
+
}
|
|
90
|
+
if (event.type === "content_block_delta" && event.delta?.text)
|
|
91
|
+
yield event.delta.text;
|
|
92
|
+
};
|
|
93
|
+
while (!0) {
|
|
94
|
+
const { done, value } = await reader.read();
|
|
95
|
+
if (done)
|
|
96
|
+
break;
|
|
97
|
+
buffer += decoder.decode(value, { stream: !0 });
|
|
98
|
+
const lines = buffer.split(`
|
|
99
|
+
`);
|
|
100
|
+
buffer = lines.pop() || "";
|
|
101
|
+
for (const line of lines)
|
|
102
|
+
if (line.startsWith("data: "))
|
|
103
|
+
yield* handlePayload(line.slice(6));
|
|
104
|
+
}
|
|
105
|
+
if (buffer.startsWith("data: "))
|
|
106
|
+
yield* handlePayload(buffer.slice(6));
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
export async function chat(messages, options = {}) {
|
|
111
|
+
const config = getConfig(), {
|
|
112
|
+
model = DEFAULT_MODEL,
|
|
113
|
+
maxTokens = DEFAULT_MAX_TOKENS,
|
|
114
|
+
temperature,
|
|
115
|
+
topP,
|
|
116
|
+
stop,
|
|
117
|
+
system,
|
|
118
|
+
tools,
|
|
119
|
+
toolChoice,
|
|
120
|
+
responseFormat
|
|
121
|
+
} = options, normalizedMessages = normalizeMessagesForProvider(messages, "anthropic"), startedAt = Date.now(), body = {
|
|
122
|
+
model,
|
|
123
|
+
max_tokens: maxTokens,
|
|
124
|
+
temperature,
|
|
125
|
+
top_p: topP,
|
|
126
|
+
stop_sequences: stop ? Array.isArray(stop) ? stop : [stop] : void 0,
|
|
127
|
+
system,
|
|
128
|
+
messages: normalizedMessages
|
|
129
|
+
};
|
|
130
|
+
if (tools && tools.length > 0) {
|
|
131
|
+
body.tools = tools.map((t) => ({
|
|
132
|
+
name: t.name,
|
|
133
|
+
description: t.description,
|
|
134
|
+
input_schema: t.parameters ?? { type: "object", properties: {} }
|
|
135
|
+
}));
|
|
136
|
+
if (toolChoice !== void 0)
|
|
137
|
+
body.tool_choice = mapAnthropicToolChoice(toolChoice);
|
|
138
|
+
}
|
|
139
|
+
if (responseFormat && responseFormat.type !== "text") {
|
|
140
|
+
const outputTool = buildAnthropicJsonTool(responseFormat), existing = Array.isArray(body.tools) ? body.tools : [];
|
|
141
|
+
body.tools = [...existing, outputTool];
|
|
142
|
+
if (toolChoice === void 0)
|
|
143
|
+
body.tool_choice = { type: "tool", name: outputTool.name };
|
|
144
|
+
}
|
|
145
|
+
const response = await fetch(`${BASE_URL}/messages`, {
|
|
146
|
+
method: "POST",
|
|
147
|
+
headers: {
|
|
148
|
+
"Content-Type": "application/json",
|
|
149
|
+
"x-api-key": config.apiKey,
|
|
150
|
+
"anthropic-version": config.anthropicVersion || DEFAULT_VERSION
|
|
151
|
+
},
|
|
152
|
+
body: JSON.stringify(body)
|
|
153
|
+
});
|
|
154
|
+
if (!response.ok) {
|
|
155
|
+
const error = await response.text();
|
|
156
|
+
throw Error(`Claude API error: ${error}`);
|
|
157
|
+
}
|
|
158
|
+
const data = await response.json();
|
|
159
|
+
if (!data.content || data.content.length === 0)
|
|
160
|
+
throw Error("Claude API returned empty content");
|
|
161
|
+
const block = data.content.find((b) => b.type === "tool_use") ?? data.content.find((b) => b.type === "text") ?? data.content[0], result = {
|
|
162
|
+
content: block?.type === "tool_use" ? JSON.stringify(block.input) : block?.text ?? "",
|
|
163
|
+
model: data.model,
|
|
164
|
+
usage: {
|
|
165
|
+
promptTokens: data.usage?.input_tokens || 0,
|
|
166
|
+
completionTokens: data.usage?.output_tokens || 0,
|
|
167
|
+
totalTokens: (data.usage?.input_tokens || 0) + (data.usage?.output_tokens || 0)
|
|
168
|
+
},
|
|
169
|
+
finishReason: data.stop_reason
|
|
170
|
+
};
|
|
171
|
+
recordUsage({
|
|
172
|
+
provider: "anthropic",
|
|
173
|
+
model: data.model,
|
|
174
|
+
promptTokens: result.usage.promptTokens,
|
|
175
|
+
completionTokens: result.usage.completionTokens,
|
|
176
|
+
totalTokens: result.usage.totalTokens,
|
|
177
|
+
durationMs: Date.now() - startedAt,
|
|
178
|
+
timestamp: Date.now()
|
|
179
|
+
});
|
|
180
|
+
return result;
|
|
181
|
+
}
|
|
182
|
+
function mapAnthropicToolChoice(choice) {
|
|
183
|
+
if (choice === "auto")
|
|
184
|
+
return { type: "auto" };
|
|
185
|
+
if (choice === "required")
|
|
186
|
+
return { type: "any" };
|
|
187
|
+
if (choice === "none")
|
|
188
|
+
return { type: "auto", disable_parallel_tool_use: !0 };
|
|
189
|
+
return { type: "tool", name: choice.name };
|
|
190
|
+
}
|
|
191
|
+
function buildAnthropicJsonTool(format) {
|
|
192
|
+
if (format.type === "json_schema")
|
|
193
|
+
return {
|
|
194
|
+
name: format.json_schema.name,
|
|
195
|
+
description: `Returns the result as JSON matching the '${format.json_schema.name}' schema.`,
|
|
196
|
+
input_schema: format.json_schema.schema
|
|
197
|
+
};
|
|
198
|
+
return {
|
|
199
|
+
name: "structured_output",
|
|
200
|
+
description: "Returns the result as a JSON object.",
|
|
201
|
+
input_schema: { type: "object", additionalProperties: !0 }
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
export async function* streamChat(messages, options = {}) {
|
|
205
|
+
const config = getConfig(), {
|
|
206
|
+
model = DEFAULT_MODEL,
|
|
207
|
+
maxTokens = DEFAULT_MAX_TOKENS,
|
|
208
|
+
temperature,
|
|
209
|
+
topP,
|
|
210
|
+
stop,
|
|
211
|
+
system
|
|
212
|
+
} = options, response = await fetch(`${BASE_URL}/messages`, {
|
|
213
|
+
method: "POST",
|
|
214
|
+
headers: {
|
|
215
|
+
"Content-Type": "application/json",
|
|
216
|
+
"x-api-key": config.apiKey,
|
|
217
|
+
"anthropic-version": config.anthropicVersion || DEFAULT_VERSION
|
|
218
|
+
},
|
|
219
|
+
body: JSON.stringify({
|
|
220
|
+
model,
|
|
221
|
+
max_tokens: maxTokens,
|
|
222
|
+
temperature,
|
|
223
|
+
top_p: topP,
|
|
224
|
+
stop_sequences: stop ? Array.isArray(stop) ? stop : [stop] : void 0,
|
|
225
|
+
system,
|
|
226
|
+
stream: !0,
|
|
227
|
+
messages: normalizeMessagesForProvider(messages, "anthropic")
|
|
228
|
+
})
|
|
229
|
+
});
|
|
230
|
+
if (!response.ok) {
|
|
231
|
+
const error = await response.text();
|
|
232
|
+
throw Error(`Claude API error: ${error}`);
|
|
233
|
+
}
|
|
234
|
+
const reader = response.body?.getReader();
|
|
235
|
+
if (!reader)
|
|
236
|
+
throw Error("No response body");
|
|
237
|
+
const decoder = new TextDecoder;
|
|
238
|
+
let buffer = "";
|
|
239
|
+
while (!0) {
|
|
240
|
+
const { done, value } = await reader.read();
|
|
241
|
+
if (done)
|
|
242
|
+
break;
|
|
243
|
+
buffer += decoder.decode(value, { stream: !0 });
|
|
244
|
+
const lines = buffer.split(`
|
|
245
|
+
`);
|
|
246
|
+
buffer = lines.pop() || "";
|
|
247
|
+
for (const line of lines)
|
|
248
|
+
if (line.startsWith("data: ")) {
|
|
249
|
+
const data = line.slice(6);
|
|
250
|
+
if (data === "[DONE]")
|
|
251
|
+
continue;
|
|
252
|
+
try {
|
|
253
|
+
const event = JSON.parse(data);
|
|
254
|
+
if (event.type === "content_block_delta" && event.delta?.text)
|
|
255
|
+
yield event.delta.text;
|
|
256
|
+
} catch {}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
export async function prompt(text, options = {}) {
|
|
261
|
+
return (await chat([{ role: "user", content: text }], options)).content;
|
|
262
|
+
}
|
|
263
|
+
export function estimateTokens(text) {
|
|
264
|
+
return Math.ceil(text.length / 4);
|
|
265
|
+
}
|
|
266
|
+
export const anthropicDriver = {
|
|
267
|
+
create: createAnthropicDriver
|
|
268
|
+
}, anthropic = {
|
|
269
|
+
configure,
|
|
270
|
+
chat,
|
|
271
|
+
streamChat,
|
|
272
|
+
prompt,
|
|
273
|
+
estimateTokens,
|
|
274
|
+
createDriver: createAnthropicDriver
|
|
275
|
+
};
|
|
276
|
+
export default anthropic;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { AIDriver, AIDriverConfig, StreamingResult } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Create a Claude Agent SDK driver instance
|
|
4
|
+
*/
|
|
5
|
+
export declare function createClaudeAgentSDKDriver(config?: ClaudeAgentSDKConfig): AIDriver;
|
|
6
|
+
/**
|
|
7
|
+
* Process a command with streaming and return a StreamingResult
|
|
8
|
+
*/
|
|
9
|
+
export declare function processStreaming(command: string, cwd?: string, config?: Omit<ClaudeAgentSDKConfig, 'cwd'>): Promise<StreamingResult>;
|
|
10
|
+
/**
|
|
11
|
+
* Resume a previous SDK session
|
|
12
|
+
*/
|
|
13
|
+
export declare function resumeSession(sessionId: string, prompt: string): Promise<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Get the last session ID for potential resume
|
|
16
|
+
*/
|
|
17
|
+
export declare function getLastSessionId(): string | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Clear the stored session ID
|
|
20
|
+
*/
|
|
21
|
+
export declare function clearSession(): void;
|
|
22
|
+
// Export the driver creator and utilities
|
|
23
|
+
export declare const claudeAgentSDK: {
|
|
24
|
+
createDriver: unknown;
|
|
25
|
+
processStreaming: typeof processStreaming;
|
|
26
|
+
resumeSession: typeof resumeSession;
|
|
27
|
+
getLastSessionId: typeof getLastSessionId;
|
|
28
|
+
clearSession: typeof clearSession
|
|
29
|
+
};
|
|
30
|
+
export declare interface ClaudeAgentSDKConfig extends AIDriverConfig {
|
|
31
|
+
maxTurns?: number
|
|
32
|
+
cwd?: string
|
|
33
|
+
allowedTools?: string[]
|
|
34
|
+
disallowedTools?: string[]
|
|
35
|
+
permissionMode?: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan'
|
|
36
|
+
customSystemPrompt?: string
|
|
37
|
+
appendSystemPrompt?: string
|
|
38
|
+
resumeSessionId?: string
|
|
39
|
+
}
|
|
40
|
+
export default claudeAgentSDK;
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
let sdkModule = null;
|
|
2
|
+
async function getSDK() {
|
|
3
|
+
if (!sdkModule)
|
|
4
|
+
try {
|
|
5
|
+
sdkModule = await import("@anthropic-ai/claude-agent-sdk");
|
|
6
|
+
} catch {
|
|
7
|
+
throw Error("Claude Agent SDK not installed. Run: bun add @anthropic-ai/claude-agent-sdk");
|
|
8
|
+
}
|
|
9
|
+
return sdkModule;
|
|
10
|
+
}
|
|
11
|
+
const sdkState = {
|
|
12
|
+
lastSessionId: void 0
|
|
13
|
+
}, DEFAULT_CONFIG = {
|
|
14
|
+
maxTurns: 25,
|
|
15
|
+
allowedTools: ["Read", "Write", "Edit", "Bash", "Glob", "Grep"],
|
|
16
|
+
permissionMode: "bypassPermissions"
|
|
17
|
+
};
|
|
18
|
+
export function createClaudeAgentSDKDriver(config = {}) {
|
|
19
|
+
const {
|
|
20
|
+
maxTurns = DEFAULT_CONFIG.maxTurns,
|
|
21
|
+
cwd,
|
|
22
|
+
allowedTools = DEFAULT_CONFIG.allowedTools,
|
|
23
|
+
disallowedTools,
|
|
24
|
+
permissionMode = DEFAULT_CONFIG.permissionMode,
|
|
25
|
+
customSystemPrompt,
|
|
26
|
+
appendSystemPrompt,
|
|
27
|
+
resumeSessionId
|
|
28
|
+
} = config;
|
|
29
|
+
return {
|
|
30
|
+
name: "Claude Agent SDK",
|
|
31
|
+
async process(command, systemPrompt, _history) {
|
|
32
|
+
const sdk = await getSDK(), { query } = sdk, fullPrompt = systemPrompt ? `${systemPrompt}
|
|
33
|
+
|
|
34
|
+
User request: ${command}` : command, options = {
|
|
35
|
+
allowedTools,
|
|
36
|
+
permissionMode,
|
|
37
|
+
maxTurns
|
|
38
|
+
};
|
|
39
|
+
if (disallowedTools)
|
|
40
|
+
options.disallowedTools = disallowedTools;
|
|
41
|
+
if (customSystemPrompt)
|
|
42
|
+
options.customSystemPrompt = customSystemPrompt;
|
|
43
|
+
if (appendSystemPrompt)
|
|
44
|
+
options.appendSystemPrompt = appendSystemPrompt;
|
|
45
|
+
if (cwd)
|
|
46
|
+
options.cwd = cwd;
|
|
47
|
+
if (resumeSessionId || sdkState.lastSessionId)
|
|
48
|
+
options.resume = resumeSessionId || sdkState.lastSessionId;
|
|
49
|
+
let result = "";
|
|
50
|
+
try {
|
|
51
|
+
for await (const message of query({ prompt: fullPrompt, options })) {
|
|
52
|
+
if (message.type === "system" && message.subtype === "init")
|
|
53
|
+
sdkState.lastSessionId = message.session_id;
|
|
54
|
+
if ("result" in message && typeof message.result === "string")
|
|
55
|
+
result = message.result;
|
|
56
|
+
}
|
|
57
|
+
return result || "No response from Claude Agent SDK";
|
|
58
|
+
} catch (error) {
|
|
59
|
+
const err = error;
|
|
60
|
+
if (err.message.includes("ANTHROPIC_API_KEY"))
|
|
61
|
+
throw Error("Claude Agent SDK requires ANTHROPIC_API_KEY environment variable or Claude Code authentication.");
|
|
62
|
+
throw Error(`Claude Agent SDK error: ${err.message}`);
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
async* stream(command, systemPrompt, _history) {
|
|
66
|
+
const sdk = await getSDK(), { query } = sdk, fullPrompt = systemPrompt ? `${systemPrompt}
|
|
67
|
+
|
|
68
|
+
User request: ${command}` : command, options = {
|
|
69
|
+
allowedTools,
|
|
70
|
+
permissionMode,
|
|
71
|
+
maxTurns
|
|
72
|
+
};
|
|
73
|
+
if (disallowedTools)
|
|
74
|
+
options.disallowedTools = disallowedTools;
|
|
75
|
+
if (customSystemPrompt)
|
|
76
|
+
options.customSystemPrompt = customSystemPrompt;
|
|
77
|
+
if (appendSystemPrompt)
|
|
78
|
+
options.appendSystemPrompt = appendSystemPrompt;
|
|
79
|
+
if (cwd)
|
|
80
|
+
options.cwd = cwd;
|
|
81
|
+
if (resumeSessionId || sdkState.lastSessionId)
|
|
82
|
+
options.resume = resumeSessionId || sdkState.lastSessionId;
|
|
83
|
+
try {
|
|
84
|
+
for await (const message of query({ prompt: fullPrompt, options })) {
|
|
85
|
+
if (message.type === "system" && message.subtype === "init")
|
|
86
|
+
sdkState.lastSessionId = message.session_id;
|
|
87
|
+
if (message.type === "assistant") {
|
|
88
|
+
const assistantMsg = message;
|
|
89
|
+
if (assistantMsg.message?.content) {
|
|
90
|
+
for (const block of assistantMsg.message.content)
|
|
91
|
+
if (block.type === "text" && block.text)
|
|
92
|
+
yield block.text;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if ("result" in message && typeof message.result === "string")
|
|
96
|
+
yield message.result;
|
|
97
|
+
}
|
|
98
|
+
} catch (error) {
|
|
99
|
+
const err = error;
|
|
100
|
+
if (err.message.includes("ANTHROPIC_API_KEY"))
|
|
101
|
+
throw Error("Claude Agent SDK requires ANTHROPIC_API_KEY environment variable or Claude Code authentication.");
|
|
102
|
+
throw Error(`Claude Agent SDK error: ${err.message}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
export async function processStreaming(command, cwd, config = {}) {
|
|
108
|
+
const sdk = await getSDK(), { query } = sdk, {
|
|
109
|
+
maxTurns = DEFAULT_CONFIG.maxTurns,
|
|
110
|
+
allowedTools = DEFAULT_CONFIG.allowedTools,
|
|
111
|
+
disallowedTools,
|
|
112
|
+
permissionMode = DEFAULT_CONFIG.permissionMode,
|
|
113
|
+
customSystemPrompt,
|
|
114
|
+
appendSystemPrompt,
|
|
115
|
+
resumeSessionId
|
|
116
|
+
} = config, options = {
|
|
117
|
+
allowedTools,
|
|
118
|
+
permissionMode,
|
|
119
|
+
maxTurns
|
|
120
|
+
};
|
|
121
|
+
if (disallowedTools)
|
|
122
|
+
options.disallowedTools = disallowedTools;
|
|
123
|
+
if (customSystemPrompt)
|
|
124
|
+
options.customSystemPrompt = customSystemPrompt;
|
|
125
|
+
if (appendSystemPrompt)
|
|
126
|
+
options.appendSystemPrompt = appendSystemPrompt;
|
|
127
|
+
if (cwd)
|
|
128
|
+
options.cwd = cwd;
|
|
129
|
+
if (resumeSessionId || sdkState.lastSessionId)
|
|
130
|
+
options.resume = resumeSessionId || sdkState.lastSessionId;
|
|
131
|
+
const encoder = new TextEncoder;
|
|
132
|
+
let fullResponse = "", resolveFullResponse;
|
|
133
|
+
const fullResponsePromise = new Promise((resolve) => {
|
|
134
|
+
resolveFullResponse = resolve;
|
|
135
|
+
});
|
|
136
|
+
return {
|
|
137
|
+
stream: new ReadableStream({
|
|
138
|
+
async start(controller) {
|
|
139
|
+
try {
|
|
140
|
+
for await (const message of query({ prompt: command, options })) {
|
|
141
|
+
if (message.type === "system" && message.subtype === "init")
|
|
142
|
+
sdkState.lastSessionId = message.session_id;
|
|
143
|
+
if (message.type === "assistant") {
|
|
144
|
+
const assistantMsg = message;
|
|
145
|
+
if (assistantMsg.message?.content) {
|
|
146
|
+
for (const block of assistantMsg.message.content)
|
|
147
|
+
if (block.type === "text" && block.text) {
|
|
148
|
+
fullResponse += block.text;
|
|
149
|
+
controller.enqueue(encoder.encode(block.text));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if ("result" in message && typeof message.result === "string") {
|
|
154
|
+
if (!fullResponse) {
|
|
155
|
+
fullResponse = message.result;
|
|
156
|
+
controller.enqueue(encoder.encode(message.result));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
resolveFullResponse(fullResponse);
|
|
161
|
+
controller.close();
|
|
162
|
+
} catch (error) {
|
|
163
|
+
resolveFullResponse(fullResponse);
|
|
164
|
+
controller.error(error);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}),
|
|
168
|
+
fullResponse: fullResponsePromise
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
export async function resumeSession(sessionId, prompt) {
|
|
172
|
+
const sdk = await getSDK(), { query } = sdk;
|
|
173
|
+
let result = "";
|
|
174
|
+
for await (const message of query({
|
|
175
|
+
prompt,
|
|
176
|
+
options: {
|
|
177
|
+
resume: sessionId,
|
|
178
|
+
permissionMode: "bypassPermissions"
|
|
179
|
+
}
|
|
180
|
+
}))
|
|
181
|
+
if ("result" in message && typeof message.result === "string")
|
|
182
|
+
result = message.result;
|
|
183
|
+
return result || "No response from resumed session";
|
|
184
|
+
}
|
|
185
|
+
export function getLastSessionId() {
|
|
186
|
+
return sdkState.lastSessionId;
|
|
187
|
+
}
|
|
188
|
+
export function clearSession() {
|
|
189
|
+
sdkState.lastSessionId = void 0;
|
|
190
|
+
}
|
|
191
|
+
export const claudeAgentSDK = {
|
|
192
|
+
createDriver: createClaudeAgentSDKDriver,
|
|
193
|
+
processStreaming,
|
|
194
|
+
resumeSession,
|
|
195
|
+
getLastSessionId,
|
|
196
|
+
clearSession
|
|
197
|
+
};
|
|
198
|
+
export default claudeAgentSDK;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type { AnthropicDriverConfig } from './anthropic/index';
|
|
2
|
+
export type { OpenAIDriverConfig } from './openai/index';
|
|
3
|
+
export type { OllamaDriverConfig } from './ollama/index';
|
|
4
|
+
export type { ClaudeAgentSDKConfig } from './claude-agent-sdk/index';
|
|
5
|
+
/**
|
|
6
|
+
* AI Drivers
|
|
7
|
+
*
|
|
8
|
+
* Export all available AI drivers.
|
|
9
|
+
*/
|
|
10
|
+
export { createAnthropicDriver, anthropicDriver, anthropic, estimateTokens } from './anthropic/index';
|
|
11
|
+
export { createOpenAIDriver, openaiDriver, openai } from './openai/index';
|
|
12
|
+
export { createOllamaDriver, ollamaDriver, ollama } from './ollama/index';
|
|
13
|
+
export { createClaudeAgentSDKDriver, claudeAgentSDK, getLastSessionId, clearSession } from './claude-agent-sdk/index';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { createAnthropicDriver, anthropicDriver, anthropic, estimateTokens } from "./anthropic";
|
|
2
|
+
export { createOpenAIDriver, openaiDriver, openai } from "./openai";
|
|
3
|
+
export { createOllamaDriver, ollamaDriver, ollama } from "./ollama";
|
|
4
|
+
export { createClaudeAgentSDKDriver, claudeAgentSDK, getLastSessionId, clearSession } from "./claude-agent-sdk";
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { AIDriver, AIDriverConfig, AIMessage, AIResult, ChatCompletionOptions } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Configure Ollama globally
|
|
4
|
+
*/
|
|
5
|
+
export declare function configure(config: OllamaDriverConfig): void;
|
|
6
|
+
export declare function createOllamaDriver(config?: OllamaDriverConfig): AIDriver;
|
|
7
|
+
/**
|
|
8
|
+
* Chat completion with full options
|
|
9
|
+
*/
|
|
10
|
+
export declare function chat(messages: AIMessage[], options?: ChatCompletionOptions): Promise<AIResult>;
|
|
11
|
+
/**
|
|
12
|
+
* Stream chat completion
|
|
13
|
+
*/
|
|
14
|
+
export declare function streamChat(messages: AIMessage[], options?: ChatCompletionOptions): AsyncGenerator<string>;
|
|
15
|
+
/**
|
|
16
|
+
* Generate text completion (non-chat)
|
|
17
|
+
*/
|
|
18
|
+
export declare function generate(prompt: string, options?: {
|
|
19
|
+
model?: string
|
|
20
|
+
system?: string
|
|
21
|
+
template?: string
|
|
22
|
+
context?: number[]
|
|
23
|
+
raw?: boolean
|
|
24
|
+
format?: 'json'
|
|
25
|
+
images?: string[]
|
|
26
|
+
}): Promise<AIResult>;
|
|
27
|
+
/**
|
|
28
|
+
* Create embeddings
|
|
29
|
+
*/
|
|
30
|
+
export declare function embed(input: string | string[], model?: string): Promise<number[] | number[][]>;
|
|
31
|
+
/**
|
|
32
|
+
* List available models
|
|
33
|
+
*/
|
|
34
|
+
export declare function listModels(): Promise<Array<{
|
|
35
|
+
name: string
|
|
36
|
+
modified_at: string
|
|
37
|
+
size: number
|
|
38
|
+
digest: string
|
|
39
|
+
details: {
|
|
40
|
+
format: string
|
|
41
|
+
family: string
|
|
42
|
+
families: string[]
|
|
43
|
+
parameter_size: string
|
|
44
|
+
quantization_level: string
|
|
45
|
+
}
|
|
46
|
+
}>>;
|
|
47
|
+
/**
|
|
48
|
+
* Pull a model from the library
|
|
49
|
+
*/
|
|
50
|
+
export declare function pullModel(name: string, onProgress?: (status: string, completed?: number, total?: number) => void): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Delete a model
|
|
53
|
+
*/
|
|
54
|
+
export declare function deleteModel(name: string): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Show model information
|
|
57
|
+
*/
|
|
58
|
+
export declare function showModel(_name: string): Promise<{
|
|
59
|
+
modelfile: string
|
|
60
|
+
parameters: string
|
|
61
|
+
template: string
|
|
62
|
+
details: {
|
|
63
|
+
format: string
|
|
64
|
+
family: string
|
|
65
|
+
families: string[]
|
|
66
|
+
parameter_size: string
|
|
67
|
+
quantization_level: string
|
|
68
|
+
}
|
|
69
|
+
}>;
|
|
70
|
+
/**
|
|
71
|
+
* Check if Ollama is running
|
|
72
|
+
*/
|
|
73
|
+
export declare function isRunning(): Promise<boolean>;
|
|
74
|
+
export declare const ollamaDriver: { create: typeof createOllamaDriver };
|
|
75
|
+
export declare const ollama: {
|
|
76
|
+
configure: typeof configure;
|
|
77
|
+
chat: typeof chat;
|
|
78
|
+
streamChat: typeof streamChat;
|
|
79
|
+
generate: typeof generate;
|
|
80
|
+
embed: typeof embed;
|
|
81
|
+
listModels: typeof listModels;
|
|
82
|
+
pullModel: typeof pullModel;
|
|
83
|
+
deleteModel: typeof deleteModel;
|
|
84
|
+
showModel: typeof showModel;
|
|
85
|
+
isRunning: typeof isRunning;
|
|
86
|
+
createDriver: unknown
|
|
87
|
+
};
|
|
88
|
+
export declare interface OllamaDriverConfig extends AIDriverConfig {
|
|
89
|
+
host?: string
|
|
90
|
+
model?: string
|
|
91
|
+
embeddingModel?: string
|
|
92
|
+
}
|
|
93
|
+
export default ollama;
|