@inf-minds/mindkit 0.0.1

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 (41) hide show
  1. package/dist/extensions/index.d.ts +2 -0
  2. package/dist/extensions/index.d.ts.map +1 -0
  3. package/dist/extensions/index.js +6 -0
  4. package/dist/extensions/index.js.map +1 -0
  5. package/dist/index.d.ts +5 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +9 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/mind.d.ts +15 -0
  10. package/dist/mind.d.ts.map +1 -0
  11. package/dist/mind.js +274 -0
  12. package/dist/mind.js.map +1 -0
  13. package/dist/providers/anthropic.d.ts +9 -0
  14. package/dist/providers/anthropic.d.ts.map +1 -0
  15. package/dist/providers/anthropic.js +20 -0
  16. package/dist/providers/anthropic.js.map +1 -0
  17. package/dist/providers/index.d.ts +4 -0
  18. package/dist/providers/index.d.ts.map +1 -0
  19. package/dist/providers/index.js +6 -0
  20. package/dist/providers/index.js.map +1 -0
  21. package/dist/providers/openai.d.ts +9 -0
  22. package/dist/providers/openai.d.ts.map +1 -0
  23. package/dist/providers/openai.js +20 -0
  24. package/dist/providers/openai.js.map +1 -0
  25. package/dist/providers/select.d.ts +17 -0
  26. package/dist/providers/select.d.ts.map +1 -0
  27. package/dist/providers/select.js +44 -0
  28. package/dist/providers/select.js.map +1 -0
  29. package/dist/types.d.ts +156 -0
  30. package/dist/types.d.ts.map +1 -0
  31. package/dist/types.js +4 -0
  32. package/dist/types.js.map +1 -0
  33. package/package.json +42 -0
  34. package/src/extensions/index.ts +7 -0
  35. package/src/index.ts +32 -0
  36. package/src/mind.ts +348 -0
  37. package/src/providers/anthropic.ts +22 -0
  38. package/src/providers/index.ts +6 -0
  39. package/src/providers/openai.ts +22 -0
  40. package/src/providers/select.ts +56 -0
  41. package/src/types.ts +147 -0
@@ -0,0 +1,156 @@
1
+ import type { ArtifactRef, VisibilityHints } from '@inf-minds/jobs';
2
+ /**
3
+ * Unique ID generator type
4
+ */
5
+ export type GenerateId = () => string;
6
+ /**
7
+ * Unsubscribe function returned by subscribe methods
8
+ */
9
+ export type Unsubscribe = () => void;
10
+ /**
11
+ * Token usage statistics from LLM calls
12
+ */
13
+ export interface TokenUsage {
14
+ promptTokens: number;
15
+ completionTokens: number;
16
+ totalTokens: number;
17
+ }
18
+ /**
19
+ * Tool definition for minds
20
+ */
21
+ export interface ToolDefinition {
22
+ name: string;
23
+ description: string;
24
+ parameters: Record<string, unknown>;
25
+ execute: (args: unknown) => Promise<unknown>;
26
+ }
27
+ /**
28
+ * Mind configuration
29
+ */
30
+ export interface MindConfig {
31
+ /** Model identifier (e.g., 'claude-sonnet-4-20250514', 'gpt-4o') */
32
+ model: string;
33
+ /** LLM provider - auto-detected from model if not specified */
34
+ provider?: 'anthropic' | 'openai';
35
+ /** API key for the provider (required for edge runtimes like Cloudflare Workers) */
36
+ apiKey?: string;
37
+ /** System prompt for the mind */
38
+ systemPrompt?: string;
39
+ /** Tools available to the mind */
40
+ tools?: ToolDefinition[];
41
+ /** Maximum tokens for completion */
42
+ maxTokens?: number;
43
+ /** Temperature for sampling */
44
+ temperature?: number;
45
+ /** Extensions to compose into the mind */
46
+ extensions?: MindExtension[];
47
+ }
48
+ /**
49
+ * Input to a mind execution
50
+ */
51
+ export interface MindInput {
52
+ /** The task or prompt for the mind */
53
+ task: string;
54
+ /** Additional context data */
55
+ context?: Record<string, unknown>;
56
+ /** Artifact references available to the mind */
57
+ artifacts?: ArtifactRef[];
58
+ /** Artifact paths to load */
59
+ artifactPaths?: string[];
60
+ }
61
+ /**
62
+ * Artifact with visibility hints from mind output
63
+ */
64
+ export interface ArtifactWithHints {
65
+ ref: ArtifactRef;
66
+ hints: VisibilityHints;
67
+ }
68
+ /**
69
+ * Output from a mind execution
70
+ */
71
+ export interface MindOutput {
72
+ /** The result from the mind */
73
+ result: unknown;
74
+ /** Artifacts created by the mind with visibility hints */
75
+ artifacts?: ArtifactWithHints[];
76
+ /** Token usage statistics */
77
+ usage?: TokenUsage;
78
+ }
79
+ /**
80
+ * Mind extension for composable functionality
81
+ */
82
+ export interface MindExtension {
83
+ /** Extension name */
84
+ name: string;
85
+ /** Additional system prompt content */
86
+ systemPromptAddition?: string;
87
+ /** Additional tools provided by the extension */
88
+ tools?: ToolDefinition[];
89
+ /** Preprocess input before execution */
90
+ preprocessInput?: (input: MindInput) => MindInput;
91
+ /** Postprocess output after execution */
92
+ postprocessOutput?: (output: MindOutput) => MindOutput;
93
+ }
94
+ /**
95
+ * Events emitted during mind execution
96
+ */
97
+ export type MindEvent = {
98
+ type: 'started';
99
+ timestamp: Date;
100
+ } | {
101
+ type: 'thinking';
102
+ content: string;
103
+ } | {
104
+ type: 'tool_call';
105
+ tool: string;
106
+ args: unknown;
107
+ } | {
108
+ type: 'tool_result';
109
+ tool: string;
110
+ result: unknown;
111
+ } | {
112
+ type: 'text_delta';
113
+ delta: string;
114
+ } | {
115
+ type: 'artifact_created';
116
+ ref: ArtifactRef;
117
+ hints: VisibilityHints;
118
+ } | {
119
+ type: 'progress';
120
+ percent: number;
121
+ message?: string;
122
+ } | {
123
+ type: 'completed';
124
+ output: MindOutput;
125
+ } | {
126
+ type: 'failed';
127
+ error: string;
128
+ };
129
+ /**
130
+ * Mind runtime interface
131
+ */
132
+ export interface Mind {
133
+ /** Unique mind instance ID */
134
+ readonly id: string;
135
+ /** Mind configuration */
136
+ readonly config: MindConfig;
137
+ /**
138
+ * Execute the mind with the given input
139
+ * @param input - Task and context for execution
140
+ * @returns Mind output with result and artifacts
141
+ */
142
+ run(input: MindInput): Promise<MindOutput>;
143
+ /**
144
+ * Execute the mind with streaming events
145
+ * @param input - Task and context for execution
146
+ * @returns Async iterable of mind events
147
+ */
148
+ stream(input: MindInput): AsyncIterable<MindEvent>;
149
+ /**
150
+ * Subscribe to mind events during execution
151
+ * @param handler - Event handler function
152
+ * @returns Unsubscribe function
153
+ */
154
+ subscribe(handler: (event: MindEvent) => void): Unsubscribe;
155
+ }
156
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEpE;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC;AAEtC;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9C;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,WAAW,GAAG,QAAQ,CAAC;IAClC,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+BAA+B;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,gDAAgD;IAChD,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC;IAC1B,6BAA6B;IAC7B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,WAAW,CAAC;IACjB,KAAK,EAAE,eAAe,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,+BAA+B;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAChC,6BAA6B;IAC7B,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,iDAAiD;IACjD,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,wCAAwC;IACxC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,SAAS,CAAC;IAClD,yCAAyC;IACzC,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,UAAU,CAAC;CACxD;AAED;;GAEG;AACH,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,IAAI,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,GAAG,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,eAAe,CAAA;CAAE,GACtE;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B;;;;OAIG;IACH,GAAG,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;IACnD;;;;OAIG;IACH,SAAS,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,GAAG,WAAW,CAAC;CAC7D"}
package/dist/types.js ADDED
@@ -0,0 +1,4 @@
1
+ // ABOUTME: Core types for mindkit - Mind, MindConfig, MindExtension, MindEvent
2
+ // ABOUTME: Defines the interface for single mind runtime using Mastra
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,sEAAsE"}
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@inf-minds/mindkit",
3
+ "version": "0.0.1",
4
+ "description": "Single mind runtime using Mastra for LLM orchestration",
5
+ "license": "Apache-2.0",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "src"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsc",
22
+ "test": "vitest run",
23
+ "test:watch": "vitest",
24
+ "typecheck": "tsc --noEmit",
25
+ "lint": "echo 'No linter configured yet'"
26
+ },
27
+ "dependencies": {
28
+ "ai": "^3.4.0",
29
+ "zod": "^3.23.8",
30
+ "@ai-sdk/anthropic": "^1.0.0",
31
+ "@ai-sdk/openai": "^1.0.0",
32
+ "@inf-minds/jobs": "workspace:*"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^20.0.0",
36
+ "typescript": "^5.3.0",
37
+ "vitest": "^2.0.0"
38
+ },
39
+ "peerDependencies": {
40
+ "ai": ">=3.0.0"
41
+ }
42
+ }
@@ -0,0 +1,7 @@
1
+ // ABOUTME: Built-in extensions for mindkit
2
+ // ABOUTME: Exports composable functionality extensions
3
+
4
+ // Extensions will be implemented in future phases
5
+ // This file serves as the extension export point
6
+
7
+ export {};
package/src/index.ts ADDED
@@ -0,0 +1,32 @@
1
+ // ABOUTME: Mindkit package entry point
2
+ // ABOUTME: Exports Mind types, createMind factory, and provider adapters
3
+
4
+ // Type exports
5
+ export type {
6
+ Mind,
7
+ MindConfig,
8
+ MindInput,
9
+ MindOutput,
10
+ MindEvent,
11
+ MindExtension,
12
+ ToolDefinition,
13
+ TokenUsage,
14
+ ArtifactWithHints,
15
+ Unsubscribe,
16
+ GenerateId,
17
+ } from './types.js';
18
+
19
+ // Factory exports
20
+ export { createMind, type CreateMindOptions } from './mind.js';
21
+
22
+ // Provider exports
23
+ export {
24
+ createAnthropicModel,
25
+ createOpenAIModel,
26
+ selectModel,
27
+ detectProvider,
28
+ type ModelProvider,
29
+ } from './providers/index.js';
30
+
31
+ // Extension exports (placeholder for future extensions)
32
+ export * from './extensions/index.js';
package/src/mind.ts ADDED
@@ -0,0 +1,348 @@
1
+ // ABOUTME: Mind factory for creating mind instances
2
+ // ABOUTME: Uses Vercel AI SDK for LLM orchestration
3
+
4
+ import { generateText, streamText, tool, type CoreMessage, type LanguageModel } from 'ai';
5
+ import { z } from 'zod';
6
+ import { selectModel } from './providers/index.js';
7
+ import type {
8
+ Mind,
9
+ MindConfig,
10
+ MindInput,
11
+ MindOutput,
12
+ MindEvent,
13
+ MindExtension,
14
+ ToolDefinition,
15
+ Unsubscribe,
16
+ GenerateId,
17
+ } from './types.js';
18
+
19
+ /**
20
+ * Default ID generator using crypto.randomUUID
21
+ */
22
+ const defaultGenerateId: GenerateId = () => crypto.randomUUID();
23
+
24
+ /**
25
+ * Options for creating a mind
26
+ */
27
+ export interface CreateMindOptions extends MindConfig {
28
+ /** Custom ID generator */
29
+ generateId?: GenerateId;
30
+ }
31
+
32
+ /**
33
+ * Build the final system prompt from base config and extensions
34
+ */
35
+ function buildSystemPrompt(config: MindConfig): string {
36
+ const parts: string[] = [];
37
+
38
+ // Base system prompt
39
+ if (config.systemPrompt) {
40
+ parts.push(config.systemPrompt);
41
+ }
42
+
43
+ // Extension additions
44
+ if (config.extensions) {
45
+ for (const ext of config.extensions) {
46
+ if (ext.systemPromptAddition) {
47
+ parts.push(ext.systemPromptAddition);
48
+ }
49
+ }
50
+ }
51
+
52
+ return parts.join('\n\n');
53
+ }
54
+
55
+ /**
56
+ * Collect tools from config and extensions
57
+ */
58
+ function collectTools(config: MindConfig): ToolDefinition[] {
59
+ const tools: ToolDefinition[] = [];
60
+
61
+ // Base tools
62
+ if (config.tools) {
63
+ tools.push(...config.tools);
64
+ }
65
+
66
+ // Extension tools
67
+ if (config.extensions) {
68
+ for (const ext of config.extensions) {
69
+ if (ext.tools) {
70
+ tools.push(...ext.tools);
71
+ }
72
+ }
73
+ }
74
+
75
+ return tools;
76
+ }
77
+
78
+ /**
79
+ * Apply extension preprocessors to input
80
+ */
81
+ function preprocessInput(input: MindInput, extensions?: MindExtension[]): MindInput {
82
+ let processed = input;
83
+
84
+ if (extensions) {
85
+ for (const ext of extensions) {
86
+ if (ext.preprocessInput) {
87
+ processed = ext.preprocessInput(processed);
88
+ }
89
+ }
90
+ }
91
+
92
+ return processed;
93
+ }
94
+
95
+ /**
96
+ * Apply extension postprocessors to output
97
+ */
98
+ function postprocessOutput(output: MindOutput, extensions?: MindExtension[]): MindOutput {
99
+ let processed = output;
100
+
101
+ if (extensions) {
102
+ for (const ext of extensions) {
103
+ if (ext.postprocessOutput) {
104
+ processed = ext.postprocessOutput(processed);
105
+ }
106
+ }
107
+ }
108
+
109
+ return processed;
110
+ }
111
+
112
+ /**
113
+ * Convert tool definitions to Vercel AI SDK tool format
114
+ */
115
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
116
+ function convertToolsToAI(tools: ToolDefinition[]): Record<string, any> {
117
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
118
+ const aiTools: Record<string, any> = {};
119
+
120
+ for (const toolDef of tools) {
121
+ // Convert parameters to zod schema if it's a plain object
122
+ const parametersSchema =
123
+ toolDef.parameters instanceof z.ZodType
124
+ ? toolDef.parameters
125
+ : z.object(toolDef.parameters as Record<string, z.ZodTypeAny>);
126
+
127
+ aiTools[toolDef.name] = tool({
128
+ description: toolDef.description,
129
+ parameters: parametersSchema,
130
+ execute: toolDef.execute as (args: unknown) => Promise<unknown>,
131
+ });
132
+ }
133
+
134
+ return aiTools;
135
+ }
136
+
137
+ /**
138
+ * Build messages array from input
139
+ */
140
+ function buildMessages(systemPrompt: string, input: MindInput): CoreMessage[] {
141
+ const messages: CoreMessage[] = [];
142
+
143
+ // Add system message if provided
144
+ if (systemPrompt) {
145
+ messages.push({ role: 'system', content: systemPrompt });
146
+ }
147
+
148
+ // Build user message with context
149
+ let userContent = input.task;
150
+ if (input.context) {
151
+ userContent = `Context:\n${JSON.stringify(input.context, null, 2)}\n\nTask:\n${input.task}`;
152
+ }
153
+
154
+ messages.push({ role: 'user', content: userContent });
155
+
156
+ return messages;
157
+ }
158
+
159
+ /**
160
+ * Mind implementation using Vercel AI SDK
161
+ */
162
+ class MindImpl implements Mind {
163
+ readonly id: string;
164
+ readonly config: MindConfig;
165
+ private systemPrompt: string;
166
+ private toolDefs: ToolDefinition[];
167
+ private model: LanguageModel;
168
+ private subscribers: Set<(event: MindEvent) => void> = new Set();
169
+
170
+ constructor(
171
+ id: string,
172
+ config: MindConfig,
173
+ systemPrompt: string,
174
+ toolDefs: ToolDefinition[],
175
+ model: LanguageModel
176
+ ) {
177
+ this.id = id;
178
+ this.config = config;
179
+ this.systemPrompt = systemPrompt;
180
+ this.toolDefs = toolDefs;
181
+ this.model = model;
182
+ }
183
+
184
+ private emit(event: MindEvent): void {
185
+ for (const handler of this.subscribers) {
186
+ try {
187
+ handler(event);
188
+ } catch {
189
+ // Ignore subscriber errors
190
+ }
191
+ }
192
+ }
193
+
194
+ async run(input: MindInput): Promise<MindOutput> {
195
+ // Preprocess input
196
+ const processedInput = preprocessInput(input, this.config.extensions);
197
+
198
+ // Emit started event
199
+ this.emit({ type: 'started', timestamp: new Date() });
200
+
201
+ try {
202
+ // Build messages
203
+ const messages = buildMessages(this.systemPrompt, processedInput);
204
+
205
+ // Convert tools
206
+ const tools = this.toolDefs.length > 0 ? convertToolsToAI(this.toolDefs) : undefined;
207
+
208
+ // Execute via Vercel AI SDK
209
+ const result = await generateText({
210
+ model: this.model,
211
+ messages,
212
+ tools,
213
+ maxSteps: 10,
214
+ maxTokens: this.config.maxTokens,
215
+ temperature: this.config.temperature,
216
+ });
217
+
218
+ // Build output
219
+ const output: MindOutput = {
220
+ result: result.text,
221
+ usage: result.usage
222
+ ? {
223
+ promptTokens: result.usage.promptTokens ?? 0,
224
+ completionTokens: result.usage.completionTokens ?? 0,
225
+ totalTokens: (result.usage.promptTokens ?? 0) + (result.usage.completionTokens ?? 0),
226
+ }
227
+ : undefined,
228
+ };
229
+
230
+ // Postprocess output
231
+ const processedOutput = postprocessOutput(output, this.config.extensions);
232
+
233
+ // Emit completed event
234
+ this.emit({ type: 'completed', output: processedOutput });
235
+
236
+ return processedOutput;
237
+ } catch (error) {
238
+ const errorMessage = error instanceof Error ? error.message : String(error);
239
+ this.emit({ type: 'failed', error: errorMessage });
240
+ throw error;
241
+ }
242
+ }
243
+
244
+ async *stream(input: MindInput): AsyncIterable<MindEvent> {
245
+ // Preprocess input
246
+ const processedInput = preprocessInput(input, this.config.extensions);
247
+
248
+ // Emit started event
249
+ const startedEvent: MindEvent = { type: 'started', timestamp: new Date() };
250
+ this.emit(startedEvent);
251
+ yield startedEvent;
252
+
253
+ try {
254
+ // Build messages
255
+ const messages = buildMessages(this.systemPrompt, processedInput);
256
+
257
+ // Convert tools
258
+ const tools = this.toolDefs.length > 0 ? convertToolsToAI(this.toolDefs) : undefined;
259
+
260
+ // Stream via Vercel AI SDK - streamText returns a Promise
261
+ const streamResult = await streamText({
262
+ model: this.model,
263
+ messages,
264
+ tools,
265
+ maxSteps: 10,
266
+ maxTokens: this.config.maxTokens,
267
+ temperature: this.config.temperature,
268
+ });
269
+
270
+ let fullText = '';
271
+
272
+ // Process stream chunks - fullStream is an AsyncIterable
273
+ for await (const chunk of streamResult.fullStream) {
274
+ if (chunk.type === 'text-delta') {
275
+ const event: MindEvent = { type: 'text_delta', delta: chunk.textDelta };
276
+ fullText += chunk.textDelta;
277
+ this.emit(event);
278
+ yield event;
279
+ } else if (chunk.type === 'tool-call') {
280
+ const event: MindEvent = { type: 'tool_call', tool: chunk.toolName, args: chunk.args };
281
+ this.emit(event);
282
+ yield event;
283
+ } else if (chunk.type === 'tool-result') {
284
+ const event: MindEvent = { type: 'tool_result', tool: chunk.toolName, result: chunk.result };
285
+ this.emit(event);
286
+ yield event;
287
+ }
288
+ }
289
+
290
+ // Get final usage - usage is a promise that resolves after stream completes
291
+ const usage = await streamResult.usage;
292
+
293
+ // Build output
294
+ const output: MindOutput = {
295
+ result: fullText,
296
+ usage: usage
297
+ ? {
298
+ promptTokens: usage.promptTokens ?? 0,
299
+ completionTokens: usage.completionTokens ?? 0,
300
+ totalTokens: (usage.promptTokens ?? 0) + (usage.completionTokens ?? 0),
301
+ }
302
+ : undefined,
303
+ };
304
+
305
+ // Postprocess output
306
+ const processedOutput = postprocessOutput(output, this.config.extensions);
307
+
308
+ // Emit completed event
309
+ const completedEvent: MindEvent = { type: 'completed', output: processedOutput };
310
+ this.emit(completedEvent);
311
+ yield completedEvent;
312
+ } catch (error) {
313
+ const errorMessage = error instanceof Error ? error.message : String(error);
314
+ const failedEvent: MindEvent = { type: 'failed', error: errorMessage };
315
+ this.emit(failedEvent);
316
+ yield failedEvent;
317
+ throw error;
318
+ }
319
+ }
320
+
321
+ subscribe(handler: (event: MindEvent) => void): Unsubscribe {
322
+ this.subscribers.add(handler);
323
+ return () => {
324
+ this.subscribers.delete(handler);
325
+ };
326
+ }
327
+ }
328
+
329
+ /**
330
+ * Create a mind instance
331
+ * @param options - Mind configuration and options
332
+ * @returns Mind instance
333
+ */
334
+ export function createMind(options: CreateMindOptions): Mind {
335
+ const generateId = options.generateId ?? defaultGenerateId;
336
+ const id = generateId();
337
+
338
+ // Build system prompt
339
+ const systemPrompt = buildSystemPrompt(options);
340
+
341
+ // Collect tools (keep as definitions, convert at runtime)
342
+ const toolDefs = collectTools(options);
343
+
344
+ // Select model based on config
345
+ const model = selectModel(options.model, options.provider, options.apiKey);
346
+
347
+ return new MindImpl(id, options, systemPrompt, toolDefs, model);
348
+ }
@@ -0,0 +1,22 @@
1
+ // ABOUTME: Anthropic provider adapter for mindkit
2
+ // ABOUTME: Creates Anthropic model instances using @ai-sdk/anthropic
3
+
4
+ import { createAnthropic, anthropic } from '@ai-sdk/anthropic';
5
+ import type { LanguageModel } from 'ai';
6
+
7
+ /**
8
+ * Create an Anthropic model instance
9
+ * @param modelId - Model identifier (e.g., 'claude-sonnet-4-20250514')
10
+ * @param apiKey - Optional API key (required for edge runtimes like Cloudflare Workers)
11
+ * @returns Anthropic model instance
12
+ */
13
+ export function createAnthropicModel(modelId: string, apiKey?: string): LanguageModel {
14
+ // Cast needed due to version differences between @ai-sdk/anthropic and ai package
15
+ if (apiKey) {
16
+ // Use explicit API key for edge runtimes that don't have process.env
17
+ const anthropicClient = createAnthropic({ apiKey });
18
+ return anthropicClient(modelId) as unknown as LanguageModel;
19
+ }
20
+ // Fallback to env var for Node.js environments
21
+ return anthropic(modelId) as unknown as LanguageModel;
22
+ }
@@ -0,0 +1,6 @@
1
+ // ABOUTME: LLM provider adapters for mindkit
2
+ // ABOUTME: Exports provider creation functions for Anthropic and OpenAI
3
+
4
+ export { createAnthropicModel } from './anthropic.js';
5
+ export { createOpenAIModel } from './openai.js';
6
+ export { selectModel, detectProvider, type ModelProvider } from './select.js';
@@ -0,0 +1,22 @@
1
+ // ABOUTME: OpenAI provider adapter for mindkit
2
+ // ABOUTME: Creates OpenAI model instances using @ai-sdk/openai
3
+
4
+ import { createOpenAI, openai } from '@ai-sdk/openai';
5
+ import type { LanguageModel } from 'ai';
6
+
7
+ /**
8
+ * Create an OpenAI model instance
9
+ * @param modelId - Model identifier (e.g., 'gpt-4o')
10
+ * @param apiKey - Optional API key (required for edge runtimes like Cloudflare Workers)
11
+ * @returns OpenAI model instance
12
+ */
13
+ export function createOpenAIModel(modelId: string, apiKey?: string): LanguageModel {
14
+ // Cast needed due to version differences between @ai-sdk/openai and ai package
15
+ if (apiKey) {
16
+ // Use explicit API key for edge runtimes that don't have process.env
17
+ const openaiClient = createOpenAI({ apiKey });
18
+ return openaiClient(modelId) as unknown as LanguageModel;
19
+ }
20
+ // Fallback to env var for Node.js environments
21
+ return openai(modelId) as unknown as LanguageModel;
22
+ }