@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.
- package/dist/extensions/index.d.ts +2 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +6 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/mind.d.ts +15 -0
- package/dist/mind.d.ts.map +1 -0
- package/dist/mind.js +274 -0
- package/dist/mind.js.map +1 -0
- package/dist/providers/anthropic.d.ts +9 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +20 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/index.d.ts +4 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +6 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/openai.d.ts +9 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +20 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/select.d.ts +17 -0
- package/dist/providers/select.d.ts.map +1 -0
- package/dist/providers/select.js +44 -0
- package/dist/providers/select.js.map +1 -0
- package/dist/types.d.ts +156 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/package.json +42 -0
- package/src/extensions/index.ts +7 -0
- package/src/index.ts +32 -0
- package/src/mind.ts +348 -0
- package/src/providers/anthropic.ts +22 -0
- package/src/providers/index.ts +6 -0
- package/src/providers/openai.ts +22 -0
- package/src/providers/select.ts +56 -0
- package/src/types.ts +147 -0
package/dist/types.d.ts
ADDED
|
@@ -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":"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"}
|
package/dist/types.js
ADDED
|
@@ -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
|
+
}
|
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
|
+
}
|