@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.
Files changed (45) hide show
  1. package/dist/agents/claude/index.d.ts +29 -0
  2. package/dist/agents/claude/index.js +197 -0
  3. package/dist/agents/index.d.ts +6 -0
  4. package/dist/agents/index.js +1 -0
  5. package/dist/buddy.d.ts +67 -0
  6. package/dist/buddy.js +393 -0
  7. package/dist/drivers/anthropic/index.d.ts +40 -0
  8. package/dist/drivers/anthropic/index.js +276 -0
  9. package/dist/drivers/claude-agent-sdk/index.d.ts +40 -0
  10. package/dist/drivers/claude-agent-sdk/index.js +198 -0
  11. package/dist/drivers/index.d.ts +13 -0
  12. package/dist/drivers/index.js +4 -0
  13. package/dist/drivers/ollama/index.d.ts +93 -0
  14. package/dist/drivers/ollama/index.js +332 -0
  15. package/dist/drivers/openai/index.d.ts +66 -0
  16. package/dist/drivers/openai/index.js +351 -0
  17. package/dist/image.d.ts +83 -0
  18. package/dist/image.js +375 -0
  19. package/dist/index.d.ts +39 -0
  20. package/dist/index.js +16 -0
  21. package/dist/mcp.d.ts +115 -0
  22. package/dist/mcp.js +361 -0
  23. package/dist/personalization.d.ts +118 -0
  24. package/dist/personalization.js +244 -0
  25. package/dist/search.d.ts +101 -0
  26. package/dist/search.js +316 -0
  27. package/dist/text.d.ts +10 -0
  28. package/dist/text.js +51 -0
  29. package/dist/types.d.ts +185 -0
  30. package/dist/types.js +0 -0
  31. package/dist/utils/client-bedrock-runtime.d.ts +16 -0
  32. package/dist/utils/client-bedrock-runtime.js +17 -0
  33. package/dist/utils/client-bedrock.d.ts +27 -0
  34. package/dist/utils/client-bedrock.js +20 -0
  35. package/dist/utils/model-access.d.ts +1 -0
  36. package/dist/utils/model-access.js +21 -0
  37. package/dist/utils/retry.d.ts +38 -0
  38. package/dist/utils/retry.js +39 -0
  39. package/dist/utils/tokens.d.ts +50 -0
  40. package/dist/utils/tokens.js +59 -0
  41. package/dist/utils/usage.d.ts +56 -0
  42. package/dist/utils/usage.js +27 -0
  43. package/dist/utils/vision.d.ts +22 -0
  44. package/dist/utils/vision.js +54 -0
  45. package/package.json +1 -1
package/dist/mcp.js ADDED
@@ -0,0 +1,361 @@
1
+ export class MCPClient {
2
+ config;
3
+ process = null;
4
+ requestId = 0;
5
+ pendingRequests = new Map;
6
+ tools = [];
7
+ resources = [];
8
+ prompts = [];
9
+ initialized = !1;
10
+ buffer = "";
11
+ constructor(config) {
12
+ this.config = config;
13
+ }
14
+ async connect() {
15
+ if (this.config.transport.type === "stdio")
16
+ await this.connectStdio();
17
+ else if (this.config.transport.type === "sse" || this.config.transport.type === "streamable-http")
18
+ await this.connectHTTP();
19
+ else
20
+ throw Error(`Unsupported transport type: ${this.config.transport.type}`);
21
+ this.initialized = !0;
22
+ }
23
+ async connectStdio() {
24
+ const transport = this.config.transport, { spawn } = await import("bun");
25
+ this.process = spawn([transport.command, ...transport.args || []], {
26
+ stdin: "pipe",
27
+ stdout: "pipe",
28
+ stderr: "pipe",
29
+ env: { ...process.env, ...transport.env }
30
+ });
31
+ this.readStdout();
32
+ await this.sendRequest("initialize", {
33
+ protocolVersion: "2024-11-05",
34
+ capabilities: {},
35
+ clientInfo: { name: "stacks-ai", version: "1.0.0" }
36
+ });
37
+ await this.sendNotification("notifications/initialized", {});
38
+ await this.discoverCapabilities();
39
+ }
40
+ async connectHTTP() {
41
+ const transport = this.config.transport, response = await fetch(transport.url, {
42
+ method: "POST",
43
+ headers: {
44
+ "Content-Type": "application/json",
45
+ ...transport.headers
46
+ },
47
+ body: JSON.stringify({
48
+ jsonrpc: "2.0",
49
+ id: this.nextId(),
50
+ method: "initialize",
51
+ params: {
52
+ protocolVersion: "2024-11-05",
53
+ capabilities: {},
54
+ clientInfo: { name: "stacks-ai", version: "1.0.0" }
55
+ }
56
+ })
57
+ });
58
+ if (!response.ok) {
59
+ const error = await response.text();
60
+ throw Error(`MCP HTTP connection error: ${error}`);
61
+ }
62
+ await this.discoverCapabilities();
63
+ }
64
+ async readStdout() {
65
+ if (!this.process)
66
+ return;
67
+ const reader = this.process.stdout?.getReader();
68
+ if (!reader)
69
+ return;
70
+ const decoder = new TextDecoder;
71
+ try {
72
+ while (!0) {
73
+ const { done, value } = await reader.read();
74
+ if (done)
75
+ break;
76
+ this.buffer += decoder.decode(value, { stream: !0 });
77
+ this.processBuffer();
78
+ }
79
+ } catch {}
80
+ }
81
+ processBuffer() {
82
+ const lines = this.buffer.split(`
83
+ `);
84
+ this.buffer = lines.pop() || "";
85
+ for (const line of lines) {
86
+ if (!line.trim())
87
+ continue;
88
+ try {
89
+ const message = JSON.parse(line);
90
+ if (message.id !== void 0 && this.pendingRequests.has(message.id)) {
91
+ const pending = this.pendingRequests.get(message.id);
92
+ this.pendingRequests.delete(message.id);
93
+ if (message.error)
94
+ pending.reject(Error(message.error.message || "MCP error"));
95
+ else
96
+ pending.resolve(message.result);
97
+ }
98
+ } catch {}
99
+ }
100
+ }
101
+ nextId() {
102
+ return ++this.requestId;
103
+ }
104
+ async sendRequest(method, params = {}) {
105
+ const id = this.nextId(), message = JSON.stringify({
106
+ jsonrpc: "2.0",
107
+ id,
108
+ method,
109
+ params
110
+ }) + `
111
+ `;
112
+ if (this.config.transport.type === "stdio" && this.process) {
113
+ const writer = this.process.stdin?.getWriter();
114
+ if (writer) {
115
+ await writer.write(new TextEncoder().encode(message));
116
+ writer.releaseLock();
117
+ }
118
+ return new Promise((resolve, reject) => {
119
+ const timeout = setTimeout(() => {
120
+ this.pendingRequests.delete(id);
121
+ reject(Error(`MCP request timeout: ${method}`));
122
+ }, 30000);
123
+ this.pendingRequests.set(id, {
124
+ resolve: (value) => {
125
+ clearTimeout(timeout);
126
+ resolve(value);
127
+ },
128
+ reject: (error) => {
129
+ clearTimeout(timeout);
130
+ reject(error);
131
+ }
132
+ });
133
+ });
134
+ }
135
+ if (this.config.transport.type === "sse" || this.config.transport.type === "streamable-http") {
136
+ const transport = this.config.transport, response = await fetch(transport.url, {
137
+ method: "POST",
138
+ headers: {
139
+ "Content-Type": "application/json",
140
+ ...transport.headers
141
+ },
142
+ body: message
143
+ });
144
+ if (!response.ok) {
145
+ const error = await response.text();
146
+ throw Error(`MCP request error: ${error}`);
147
+ }
148
+ const result = await response.json();
149
+ if (result.error)
150
+ throw Error(result.error.message || "MCP error");
151
+ return result.result;
152
+ }
153
+ throw Error("No transport available");
154
+ }
155
+ async sendNotification(method, params = {}) {
156
+ const message = JSON.stringify({
157
+ jsonrpc: "2.0",
158
+ method,
159
+ params
160
+ }) + `
161
+ `;
162
+ if (this.config.transport.type === "stdio" && this.process) {
163
+ const writer = this.process.stdin?.getWriter();
164
+ if (writer) {
165
+ await writer.write(new TextEncoder().encode(message));
166
+ writer.releaseLock();
167
+ }
168
+ }
169
+ }
170
+ async discoverCapabilities() {
171
+ const capabilities = this.config.capabilities || { tools: !0, resources: !0, prompts: !0 };
172
+ if (capabilities.tools !== !1)
173
+ try {
174
+ const result = await this.sendRequest("tools/list");
175
+ this.tools = result?.tools || [];
176
+ } catch {
177
+ this.tools = [];
178
+ }
179
+ if (capabilities.resources !== !1)
180
+ try {
181
+ const result = await this.sendRequest("resources/list");
182
+ this.resources = result?.resources || [];
183
+ } catch {
184
+ this.resources = [];
185
+ }
186
+ if (capabilities.prompts !== !1)
187
+ try {
188
+ const result = await this.sendRequest("prompts/list");
189
+ this.prompts = result?.prompts || [];
190
+ } catch {
191
+ this.prompts = [];
192
+ }
193
+ }
194
+ listTools() {
195
+ return this.tools;
196
+ }
197
+ listResources() {
198
+ return this.resources;
199
+ }
200
+ listPrompts() {
201
+ return this.prompts;
202
+ }
203
+ async callTool(name, args = {}) {
204
+ if (!this.initialized)
205
+ throw Error("MCP client not connected. Call connect() first.");
206
+ return await this.sendRequest("tools/call", { name, arguments: args });
207
+ }
208
+ async readResource(uri) {
209
+ if (!this.initialized)
210
+ throw Error("MCP client not connected. Call connect() first.");
211
+ const contents = (await this.sendRequest("resources/read", { uri }))?.contents?.[0];
212
+ return {
213
+ uri: contents?.uri || uri,
214
+ mimeType: contents?.mimeType,
215
+ text: contents?.text,
216
+ blob: contents?.blob
217
+ };
218
+ }
219
+ async getPrompt(name, args = {}) {
220
+ if (!this.initialized)
221
+ throw Error("MCP client not connected. Call connect() first.");
222
+ return this.sendRequest("prompts/get", { name, arguments: args });
223
+ }
224
+ toAnthropicTools() {
225
+ return this.tools.map((tool) => ({
226
+ name: tool.name,
227
+ description: tool.description,
228
+ input_schema: tool.inputSchema
229
+ }));
230
+ }
231
+ toOpenAITools() {
232
+ return this.tools.map((tool) => ({
233
+ type: "function",
234
+ function: {
235
+ name: tool.name,
236
+ description: tool.description,
237
+ parameters: tool.inputSchema
238
+ }
239
+ }));
240
+ }
241
+ async disconnect() {
242
+ if (this.process) {
243
+ this.process.kill();
244
+ this.process = null;
245
+ }
246
+ for (const pending of this.pendingRequests.values())
247
+ try {
248
+ pending.reject(Error("MCP client disconnected"));
249
+ } catch {}
250
+ this.pendingRequests.clear();
251
+ this.initialized = !1;
252
+ this.tools = [];
253
+ this.resources = [];
254
+ this.prompts = [];
255
+ }
256
+ get isConnected() {
257
+ return this.initialized;
258
+ }
259
+ get serverName() {
260
+ return this.config.name;
261
+ }
262
+ }
263
+
264
+ export class MCPManager {
265
+ clients = new Map;
266
+ async addServer(config) {
267
+ if (this.clients.has(config.name))
268
+ throw Error(`MCP server already registered: ${config.name}`);
269
+ const client = new MCPClient(config);
270
+ await client.connect();
271
+ this.clients.set(config.name, client);
272
+ return client;
273
+ }
274
+ async removeServer(name) {
275
+ const client = this.clients.get(name);
276
+ if (client) {
277
+ await client.disconnect();
278
+ this.clients.delete(name);
279
+ }
280
+ }
281
+ getServer(name) {
282
+ return this.clients.get(name);
283
+ }
284
+ listServers() {
285
+ return Array.from(this.clients.keys());
286
+ }
287
+ getAllTools() {
288
+ const allTools = [];
289
+ for (const [name, client] of this.clients)
290
+ for (const tool of client.listTools())
291
+ allTools.push({ ...tool, serverName: name });
292
+ return allTools;
293
+ }
294
+ async callTool(toolPath, args = {}) {
295
+ if (toolPath.includes("/")) {
296
+ const [serverName, toolName] = toolPath.split("/", 2);
297
+ if (!serverName || !toolName)
298
+ throw Error(`Invalid MCP tool path: ${toolPath}`);
299
+ const client = this.clients.get(serverName);
300
+ if (!client)
301
+ throw Error(`MCP server not found: ${serverName}`);
302
+ return client.callTool(toolName, args);
303
+ }
304
+ for (const [, client] of this.clients)
305
+ if (client.listTools().some((t) => t.name === toolPath))
306
+ return client.callTool(toolPath, args);
307
+ throw Error(`MCP tool not found: ${toolPath}`);
308
+ }
309
+ toAnthropicTools() {
310
+ const tools = [];
311
+ for (const [serverName, client] of this.clients)
312
+ for (const tool of client.listTools())
313
+ tools.push({
314
+ name: `${serverName}__${tool.name}`,
315
+ description: `[${serverName}] ${tool.description}`,
316
+ input_schema: tool.inputSchema
317
+ });
318
+ return tools;
319
+ }
320
+ toOpenAITools() {
321
+ const tools = [];
322
+ for (const [serverName, client] of this.clients)
323
+ for (const tool of client.listTools())
324
+ tools.push({
325
+ type: "function",
326
+ function: {
327
+ name: `${serverName}__${tool.name}`,
328
+ description: `[${serverName}] ${tool.description}`,
329
+ parameters: tool.inputSchema
330
+ }
331
+ });
332
+ return tools;
333
+ }
334
+ async disconnectAll() {
335
+ const disconnects = Array.from(this.clients.values()).map((c) => c.disconnect());
336
+ await Promise.all(disconnects);
337
+ this.clients.clear();
338
+ }
339
+ }
340
+ export async function connectStdio(name, command, args, env) {
341
+ const client = new MCPClient({
342
+ name,
343
+ transport: { type: "stdio", command, args, env }
344
+ });
345
+ await client.connect();
346
+ return client;
347
+ }
348
+ export async function connectHTTP(name, url, headers) {
349
+ const client = new MCPClient({
350
+ name,
351
+ transport: { type: "streamable-http", url, headers }
352
+ });
353
+ await client.connect();
354
+ return client;
355
+ }
356
+ export const mcp = {
357
+ MCPClient,
358
+ MCPManager,
359
+ connectStdio,
360
+ connectHTTP
361
+ };
@@ -0,0 +1,118 @@
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 an intelligent summary of text.
19
+ *
20
+ * Not exported as a bare top-level identifier because `text.ts` already
21
+ * exposes `summarize`, and `index.ts` re-exports both via `export *`.
22
+ * Reach this multi-provider variant through the `personalization`
23
+ * namespace export below: `personalization.summarize(...)`.
24
+ */
25
+ declare function summarize(text: string, options?: SummaryOptions): Promise<AIResult>;
26
+ /**
27
+ * Generate personalized content recommendations based on user profile and available items.
28
+ */
29
+ export declare function recommend(profile: UserProfile, items: ContentItem[], options?: RecommendationOptions): Promise<RecommendationResult>;
30
+ /**
31
+ * Create a new empty user profile.
32
+ */
33
+ export declare function createProfile(id: string, segments?: string[]): UserProfile;
34
+ /**
35
+ * Record a user interaction and update preferences.
36
+ */
37
+ export declare function recordInteraction(profile: UserProfile, interaction: Interaction): UserProfile;
38
+ /**
39
+ * Extract keywords/topics from user interactions using AI.
40
+ */
41
+ export declare function extractUserInterests(profile: UserProfile, items: ContentItem[], options?: { provider?: 'anthropic' | 'openai' | 'ollama'; model?: string }): Promise<string[]>;
42
+ // ============================================================================
43
+ // Exports
44
+ // ============================================================================
45
+ export declare const personalization: {
46
+ analyzeSentiment: typeof analyzeSentiment;
47
+ classifyText: typeof classifyText;
48
+ summarize: typeof summarize;
49
+ recommend: typeof recommend;
50
+ createProfile: typeof createProfile;
51
+ recordInteraction: typeof recordInteraction;
52
+ extractUserInterests: typeof extractUserInterests
53
+ };
54
+ // ============================================================================
55
+ // Types
56
+ // ============================================================================
57
+ export declare interface UserProfile {
58
+ id: string
59
+ preferences: Record<string, number>
60
+ interactions: Interaction[]
61
+ segments: string[]
62
+ metadata?: Record<string, unknown>
63
+ }
64
+ export declare interface Interaction {
65
+ type: 'view' | 'click' | 'purchase' | 'like' | 'dislike' | 'share' | 'bookmark' | 'custom'
66
+ itemId: string
67
+ timestamp: number
68
+ weight?: number
69
+ metadata?: Record<string, unknown>
70
+ }
71
+ export declare interface ContentItem {
72
+ id: string
73
+ content: string
74
+ category?: string
75
+ tags?: string[]
76
+ metadata?: Record<string, unknown>
77
+ }
78
+ export declare interface RecommendationOptions {
79
+ provider?: 'anthropic' | 'openai' | 'ollama'
80
+ model?: string
81
+ maxTokens?: number
82
+ temperature?: number
83
+ limit?: number
84
+ }
85
+ export declare interface RecommendationResult {
86
+ recommendations: Array<{
87
+ itemId: string
88
+ score: number
89
+ reason: string
90
+ }>
91
+ model: string
92
+ provider: string
93
+ }
94
+ export declare interface SentimentResult {
95
+ sentiment: 'positive' | 'negative' | 'neutral' | 'mixed'
96
+ score: number
97
+ confidence: number
98
+ aspects?: Array<{
99
+ aspect: string
100
+ sentiment: 'positive' | 'negative' | 'neutral'
101
+ score: number
102
+ }>
103
+ }
104
+ export declare interface ClassificationResult {
105
+ label: string
106
+ confidence: number
107
+ allLabels: Array<{
108
+ label: string
109
+ confidence: number
110
+ }>
111
+ }
112
+ export declare interface SummaryOptions {
113
+ provider?: 'anthropic' | 'openai' | 'ollama'
114
+ model?: string
115
+ maxLength?: number
116
+ style?: 'concise' | 'detailed' | 'bullet-points'
117
+ language?: string
118
+ }