@vistagenic/vista 0.2.16 → 0.3.2
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/bin/vista.js +184 -177
- package/dist/ai/agent.d.ts +37 -0
- package/dist/ai/agent.js +385 -0
- package/dist/ai/embeddings.d.ts +11 -0
- package/dist/ai/embeddings.js +71 -0
- package/dist/ai/index.d.ts +10 -0
- package/dist/ai/index.js +26 -0
- package/dist/ai/memory.d.ts +16 -0
- package/dist/ai/memory.js +39 -0
- package/dist/ai/observability.d.ts +21 -0
- package/dist/ai/observability.js +69 -0
- package/dist/ai/providers/anthropic.d.ts +2 -0
- package/dist/ai/providers/anthropic.js +190 -0
- package/dist/ai/providers/base.d.ts +7 -0
- package/dist/ai/providers/base.js +85 -0
- package/dist/ai/providers/gemini.d.ts +2 -0
- package/dist/ai/providers/gemini.js +194 -0
- package/dist/ai/providers/index.d.ts +5 -0
- package/dist/ai/providers/index.js +21 -0
- package/dist/ai/providers/mock.d.ts +8 -0
- package/dist/ai/providers/mock.js +77 -0
- package/dist/ai/providers/openai.d.ts +2 -0
- package/dist/ai/providers/openai.js +211 -0
- package/dist/ai/rag.d.ts +35 -0
- package/dist/ai/rag.js +110 -0
- package/dist/ai/react/index.d.ts +1 -0
- package/dist/ai/react/index.js +17 -0
- package/dist/ai/react/react-server.d.ts +1 -0
- package/dist/ai/react/react-server.js +17 -0
- package/dist/ai/react/use-agent.d.ts +23 -0
- package/dist/ai/react/use-agent.js +138 -0
- package/dist/ai/stream.d.ts +24 -0
- package/dist/ai/stream.js +109 -0
- package/dist/ai/tool.d.ts +11 -0
- package/dist/ai/tool.js +47 -0
- package/dist/ai/types.d.ts +117 -0
- package/dist/ai/types.js +5 -0
- package/dist/auth/core.d.ts +140 -0
- package/dist/auth/core.js +165 -0
- package/dist/auth/index.d.ts +20 -8
- package/dist/auth/index.js +369 -16
- package/dist/auth/react-server.d.ts +1 -0
- package/dist/auth/react-server.js +10 -0
- package/dist/auth/react.d.ts +18 -0
- package/dist/auth/react.js +71 -0
- package/dist/bin/build-rsc.js +602 -604
- package/dist/bin/build.js +389 -388
- package/dist/bin/deploy-output.d.ts +2 -7
- package/dist/bin/deploy-output.js +3 -76
- package/dist/bin/deploy.d.ts +7 -0
- package/dist/bin/deploy.js +102 -0
- package/dist/bin/dev-error-overlay-snippet.js +778 -552
- package/dist/bin/devtools-indicator-snippet.js +387 -387
- package/dist/bin/generate.js +510 -248
- package/dist/build/manifest.d.ts +169 -139
- package/dist/build/manifest.js +423 -367
- package/dist/build/rsc/client-manifest.d.ts +62 -52
- package/dist/build/rsc/client-manifest.js +295 -193
- package/dist/build/rsc/client-reference-plugin.d.ts +37 -37
- package/dist/build/rsc/client-reference-plugin.js +160 -160
- package/dist/build/rsc/native-scanner.d.ts +135 -123
- package/dist/build/rsc/native-scanner.js +203 -170
- package/dist/build/rsc/react-client-reference-manifest.d.ts +28 -22
- package/dist/build/rsc/react-client-reference-manifest.js +240 -219
- package/dist/build/rsc/rsc-renderer.d.ts +99 -99
- package/dist/build/rsc/rsc-renderer.js +263 -263
- package/dist/build/rsc/server-component-loader.d.ts +19 -19
- package/dist/build/rsc/server-component-loader.js +91 -91
- package/dist/build/rsc/server-manifest.d.ts +17 -0
- package/dist/build/rsc/server-manifest.js +20 -0
- package/dist/build/standalone.js +337 -334
- package/dist/build/webpack/plugins/vista-flight-plugin.js +5 -5
- package/dist/client/dynamic.react-server.d.ts +2 -0
- package/dist/client/dynamic.react-server.js +23 -0
- package/dist/client/link.react-server.d.ts +2 -0
- package/dist/client/link.react-server.js +11 -0
- package/dist/client/navigation.react-server.d.ts +1 -0
- package/dist/client/navigation.react-server.js +17 -0
- package/dist/client/router.react-server.d.ts +1 -0
- package/dist/client/router.react-server.js +17 -0
- package/dist/client/rsc-router.react-server.d.ts +1 -0
- package/dist/client/rsc-router.react-server.js +17 -0
- package/dist/client/script.react-server.d.ts +2 -0
- package/dist/client/script.react-server.js +23 -0
- package/dist/components/client-island.d.ts +34 -34
- package/dist/components/client-island.js +75 -75
- package/dist/config.d.ts +17 -0
- package/dist/config.js +60 -1
- package/dist/deploy/adapters/cloudflare.d.ts +2 -0
- package/dist/deploy/adapters/cloudflare.js +124 -0
- package/dist/deploy/adapters/docker.d.ts +2 -0
- package/dist/deploy/adapters/docker.js +112 -0
- package/dist/deploy/adapters/index.d.ts +15 -0
- package/dist/deploy/adapters/index.js +24 -0
- package/dist/deploy/adapters/netlify.d.ts +2 -0
- package/dist/deploy/adapters/netlify.js +115 -0
- package/dist/deploy/adapters/render.d.ts +2 -0
- package/dist/deploy/adapters/render.js +95 -0
- package/dist/deploy/adapters/vercel.d.ts +7 -0
- package/dist/deploy/adapters/vercel.js +164 -0
- package/dist/deploy/cli-runner.d.ts +8 -0
- package/dist/deploy/cli-runner.js +58 -0
- package/dist/deploy/detect.d.ts +6 -0
- package/dist/deploy/detect.js +77 -0
- package/dist/deploy/index.d.ts +24 -0
- package/dist/deploy/index.js +112 -0
- package/dist/deploy/preflight.d.ts +8 -0
- package/dist/deploy/preflight.js +80 -0
- package/dist/deploy/types.d.ts +48 -0
- package/dist/deploy/types.js +2 -0
- package/dist/deploy/utils.d.ts +18 -0
- package/dist/deploy/utils.js +70 -0
- package/dist/dev-error.d.ts +14 -0
- package/dist/dev-error.js +1763 -705
- package/dist/index.d.ts +23 -21
- package/dist/index.js +61 -57
- package/dist/server/cookie-parse.d.ts +4 -0
- package/dist/server/cookie-parse.js +14 -0
- package/dist/server/engine.js +7 -26
- package/dist/server/index.d.ts +109 -102
- package/dist/server/index.js +315 -286
- package/dist/server/middleware-runner.d.ts +125 -57
- package/dist/server/middleware-runner.js +615 -218
- package/dist/server/middleware-security.d.ts +36 -0
- package/dist/server/middleware-security.js +183 -0
- package/dist/server/module-compile-hook.js +695 -662
- package/dist/server/route-handler-registry.d.ts +65 -0
- package/dist/server/route-handler-registry.js +195 -0
- package/dist/server/route-patterns.d.ts +67 -0
- package/dist/server/route-patterns.js +186 -0
- package/dist/server/rsc-engine.js +75 -92
- package/dist/server/rsc-module-system.d.ts +33 -33
- package/dist/server/rsc-module-system.js +87 -87
- package/dist/server/rsc-upstream.js +892 -888
- package/dist/server/static-generator.js +10 -10
- package/dist/server/typed-api-runtime.d.ts +18 -0
- package/dist/server/typed-api-runtime.js +635 -507
- package/dist/server/vista-import-map.js +134 -123
- package/dist/stack/index.d.ts +34 -32
- package/dist/stack/index.js +49 -45
- package/dist/stack/server/caller.d.ts +13 -0
- package/dist/stack/server/caller.js +42 -0
- package/dist/stack/server/executor.d.ts +40 -36
- package/dist/stack/server/executor.js +222 -174
- package/dist/stack/server/index.d.ts +11 -10
- package/dist/stack/server/index.js +24 -23
- package/dist/stack/server/procedure.d.ts +20 -18
- package/dist/stack/server/procedure.js +66 -58
- package/dist/stack/server/types.d.ts +113 -100
- package/dist/theme/react-server.d.ts +10 -0
- package/dist/theme/react-server.js +16 -0
- package/package.json +28 -3
- package/LICENSE +0 -21
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createOpenAIModel = createOpenAIModel;
|
|
4
|
+
const tool_1 = require("../tool");
|
|
5
|
+
function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
6
|
+
const result = [];
|
|
7
|
+
if (systemPrompt) {
|
|
8
|
+
result.push({ role: 'system', content: systemPrompt });
|
|
9
|
+
}
|
|
10
|
+
for (const msg of messages) {
|
|
11
|
+
if (msg.role === 'tool') {
|
|
12
|
+
result.push({
|
|
13
|
+
role: 'tool',
|
|
14
|
+
tool_call_id: msg.toolCallId || 'call_default',
|
|
15
|
+
content: msg.content,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
else if (msg.role === 'assistant' && msg.toolCalls && msg.toolCalls.length > 0) {
|
|
19
|
+
result.push({
|
|
20
|
+
role: 'assistant',
|
|
21
|
+
content: msg.content || null,
|
|
22
|
+
tool_calls: msg.toolCalls.map((tc) => ({
|
|
23
|
+
id: tc.id,
|
|
24
|
+
type: 'function',
|
|
25
|
+
function: {
|
|
26
|
+
name: tc.name,
|
|
27
|
+
arguments: typeof tc.arguments === 'string' ? tc.arguments : JSON.stringify(tc.arguments),
|
|
28
|
+
},
|
|
29
|
+
})),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
result.push({
|
|
34
|
+
role: msg.role,
|
|
35
|
+
content: msg.content,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
function createOpenAIModel(options) {
|
|
42
|
+
const baseURL = (options.baseURL ||
|
|
43
|
+
process.env.OPENAI_BASE_URL ||
|
|
44
|
+
'https://api.openai.com/v1').replace(/\/+$/, '');
|
|
45
|
+
const apiKey = options.apiKey || process.env.OPENAI_API_KEY || '';
|
|
46
|
+
const modelName = options.model || 'gpt-4o';
|
|
47
|
+
return {
|
|
48
|
+
provider: 'openai',
|
|
49
|
+
modelName,
|
|
50
|
+
async generateText(genOptions) {
|
|
51
|
+
const url = `${baseURL}/chat/completions`;
|
|
52
|
+
const messages = formatMessagesForOpenAI(genOptions.messages, genOptions.systemPrompt);
|
|
53
|
+
const body = {
|
|
54
|
+
model: modelName,
|
|
55
|
+
messages,
|
|
56
|
+
temperature: genOptions.temperature ?? options.temperature ?? 0.7,
|
|
57
|
+
};
|
|
58
|
+
if (genOptions.maxTokens || options.maxTokens) {
|
|
59
|
+
body.max_tokens = genOptions.maxTokens || options.maxTokens;
|
|
60
|
+
}
|
|
61
|
+
if (genOptions.tools && genOptions.tools.length > 0) {
|
|
62
|
+
body.tools = genOptions.tools.map(tool_1.formatToolForOpenAI);
|
|
63
|
+
body.tool_choice = 'auto';
|
|
64
|
+
}
|
|
65
|
+
const headers = {
|
|
66
|
+
'Content-Type': 'application/json',
|
|
67
|
+
...(options.headers || {}),
|
|
68
|
+
};
|
|
69
|
+
if (apiKey) {
|
|
70
|
+
headers['Authorization'] = `Bearer ${apiKey}`;
|
|
71
|
+
}
|
|
72
|
+
const res = await fetch(url, {
|
|
73
|
+
method: 'POST',
|
|
74
|
+
headers,
|
|
75
|
+
body: JSON.stringify(body),
|
|
76
|
+
signal: genOptions.abortSignal,
|
|
77
|
+
});
|
|
78
|
+
if (!res.ok) {
|
|
79
|
+
const errText = await res.text().catch(() => '');
|
|
80
|
+
throw new Error(`OpenAI API request failed [${res.status}]: ${errText}`);
|
|
81
|
+
}
|
|
82
|
+
const data = await res.json();
|
|
83
|
+
const choice = data.choices?.[0];
|
|
84
|
+
const message = choice?.message;
|
|
85
|
+
let toolCalls;
|
|
86
|
+
if (message?.tool_calls && message.tool_calls.length > 0) {
|
|
87
|
+
toolCalls = message.tool_calls.map((tc) => {
|
|
88
|
+
let parsedArgs = {};
|
|
89
|
+
try {
|
|
90
|
+
parsedArgs = JSON.parse(tc.function?.arguments || '{}');
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
parsedArgs = { raw: tc.function?.arguments };
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
id: tc.id,
|
|
97
|
+
name: tc.function?.name,
|
|
98
|
+
arguments: parsedArgs,
|
|
99
|
+
};
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
text: message?.content || '',
|
|
104
|
+
toolCalls,
|
|
105
|
+
finishReason: choice?.finish_reason || 'stop',
|
|
106
|
+
usage: data.usage
|
|
107
|
+
? {
|
|
108
|
+
promptTokens: data.usage.prompt_tokens || 0,
|
|
109
|
+
completionTokens: data.usage.completion_tokens || 0,
|
|
110
|
+
totalTokens: data.usage.total_tokens || 0,
|
|
111
|
+
}
|
|
112
|
+
: undefined,
|
|
113
|
+
raw: data,
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
async *streamText(genOptions) {
|
|
117
|
+
const url = `${baseURL}/chat/completions`;
|
|
118
|
+
const messages = formatMessagesForOpenAI(genOptions.messages, genOptions.systemPrompt);
|
|
119
|
+
const body = {
|
|
120
|
+
model: modelName,
|
|
121
|
+
messages,
|
|
122
|
+
temperature: genOptions.temperature ?? options.temperature ?? 0.7,
|
|
123
|
+
stream: true,
|
|
124
|
+
};
|
|
125
|
+
if (genOptions.maxTokens || options.maxTokens) {
|
|
126
|
+
body.max_tokens = genOptions.maxTokens || options.maxTokens;
|
|
127
|
+
}
|
|
128
|
+
if (genOptions.tools && genOptions.tools.length > 0) {
|
|
129
|
+
body.tools = genOptions.tools.map(tool_1.formatToolForOpenAI);
|
|
130
|
+
body.tool_choice = 'auto';
|
|
131
|
+
}
|
|
132
|
+
const headers = {
|
|
133
|
+
'Content-Type': 'application/json',
|
|
134
|
+
...(options.headers || {}),
|
|
135
|
+
};
|
|
136
|
+
if (apiKey) {
|
|
137
|
+
headers['Authorization'] = `Bearer ${apiKey}`;
|
|
138
|
+
}
|
|
139
|
+
const res = await fetch(url, {
|
|
140
|
+
method: 'POST',
|
|
141
|
+
headers,
|
|
142
|
+
body: JSON.stringify(body),
|
|
143
|
+
signal: genOptions.abortSignal,
|
|
144
|
+
});
|
|
145
|
+
if (!res.ok) {
|
|
146
|
+
const errText = await res.text().catch(() => '');
|
|
147
|
+
throw new Error(`OpenAI API stream request failed [${res.status}]: ${errText}`);
|
|
148
|
+
}
|
|
149
|
+
if (!res.body) {
|
|
150
|
+
throw new Error('ReadableStream not supported on fetch response');
|
|
151
|
+
}
|
|
152
|
+
const reader = res.body.getReader();
|
|
153
|
+
const decoder = new TextDecoder();
|
|
154
|
+
let buffer = '';
|
|
155
|
+
try {
|
|
156
|
+
while (true) {
|
|
157
|
+
const { done, value } = await reader.read();
|
|
158
|
+
if (done)
|
|
159
|
+
break;
|
|
160
|
+
buffer += decoder.decode(value, { stream: true });
|
|
161
|
+
const lines = buffer.split('\n');
|
|
162
|
+
buffer = lines.pop() || '';
|
|
163
|
+
for (const line of lines) {
|
|
164
|
+
const trimmed = line.trim();
|
|
165
|
+
if (!trimmed || trimmed.startsWith(':'))
|
|
166
|
+
continue;
|
|
167
|
+
if (trimmed === 'data: [DONE]') {
|
|
168
|
+
yield { type: 'done' };
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (trimmed.startsWith('data: ')) {
|
|
172
|
+
try {
|
|
173
|
+
const parsed = JSON.parse(trimmed.slice(6));
|
|
174
|
+
const delta = parsed.choices?.[0]?.delta;
|
|
175
|
+
if (delta?.content) {
|
|
176
|
+
yield { type: 'text-delta', textDelta: delta.content };
|
|
177
|
+
}
|
|
178
|
+
if (delta?.tool_calls) {
|
|
179
|
+
for (const tc of delta.tool_calls) {
|
|
180
|
+
let parsedArgs = {};
|
|
181
|
+
try {
|
|
182
|
+
parsedArgs = JSON.parse(tc.function?.arguments || '{}');
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
parsedArgs = { raw: tc.function?.arguments };
|
|
186
|
+
}
|
|
187
|
+
yield {
|
|
188
|
+
type: 'tool-call',
|
|
189
|
+
toolCall: {
|
|
190
|
+
id: tc.id || `call_${Date.now()}`,
|
|
191
|
+
name: tc.function?.name || '',
|
|
192
|
+
arguments: parsedArgs,
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
// Ignore parse errors on partial chunks
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
finally {
|
|
206
|
+
reader.releaseLock();
|
|
207
|
+
}
|
|
208
|
+
yield { type: 'done' };
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
}
|
package/dist/ai/rag.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ToolDefinition } from './types';
|
|
2
|
+
export interface DocumentEntry<TMetadata = any> {
|
|
3
|
+
id: string;
|
|
4
|
+
text: string;
|
|
5
|
+
vector?: number[];
|
|
6
|
+
metadata?: TMetadata;
|
|
7
|
+
}
|
|
8
|
+
export interface DocumentMatch<TMetadata = any> {
|
|
9
|
+
id: string;
|
|
10
|
+
text: string;
|
|
11
|
+
score: number;
|
|
12
|
+
metadata?: TMetadata;
|
|
13
|
+
}
|
|
14
|
+
export declare function cosineSimilarity(a: number[], b: number[]): number;
|
|
15
|
+
export declare class InMemoryVectorStore<TMetadata = any> {
|
|
16
|
+
private documents;
|
|
17
|
+
addDocument(doc: DocumentEntry<TMetadata>): void;
|
|
18
|
+
addDocuments(docs: DocumentEntry<TMetadata>[]): void;
|
|
19
|
+
search(queryVector: number[], topK?: number): DocumentMatch<TMetadata>[];
|
|
20
|
+
searchByKeyword(query: string, topK?: number): DocumentMatch<TMetadata>[];
|
|
21
|
+
clear(): void;
|
|
22
|
+
}
|
|
23
|
+
export interface RetrieverOptions<TMetadata = any> {
|
|
24
|
+
name?: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
store: InMemoryVectorStore<TMetadata>;
|
|
27
|
+
embed?: (text: string) => Promise<number[]> | number[];
|
|
28
|
+
topK?: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Creates a knowledge retriever tool that can be provided directly to an AI agent.
|
|
32
|
+
*/
|
|
33
|
+
export declare function createRetrieverTool<TMetadata = any>(options: RetrieverOptions<TMetadata>): ToolDefinition<{
|
|
34
|
+
query: string;
|
|
35
|
+
}>;
|
package/dist/ai/rag.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InMemoryVectorStore = void 0;
|
|
4
|
+
exports.cosineSimilarity = cosineSimilarity;
|
|
5
|
+
exports.createRetrieverTool = createRetrieverTool;
|
|
6
|
+
const tool_1 = require("./tool");
|
|
7
|
+
function cosineSimilarity(a, b) {
|
|
8
|
+
if (a.length !== b.length || a.length === 0)
|
|
9
|
+
return 0;
|
|
10
|
+
let dotProduct = 0;
|
|
11
|
+
let normA = 0;
|
|
12
|
+
let normB = 0;
|
|
13
|
+
for (let i = 0; i < a.length; i++) {
|
|
14
|
+
dotProduct += a[i] * b[i];
|
|
15
|
+
normA += a[i] * a[i];
|
|
16
|
+
normB += b[i] * b[i];
|
|
17
|
+
}
|
|
18
|
+
const denominator = Math.sqrt(normA) * Math.sqrt(normB);
|
|
19
|
+
if (denominator === 0)
|
|
20
|
+
return 0;
|
|
21
|
+
return dotProduct / denominator;
|
|
22
|
+
}
|
|
23
|
+
class InMemoryVectorStore {
|
|
24
|
+
documents = [];
|
|
25
|
+
addDocument(doc) {
|
|
26
|
+
this.documents.push(doc);
|
|
27
|
+
}
|
|
28
|
+
addDocuments(docs) {
|
|
29
|
+
this.documents.push(...docs);
|
|
30
|
+
}
|
|
31
|
+
search(queryVector, topK = 3) {
|
|
32
|
+
const scored = [];
|
|
33
|
+
for (const doc of this.documents) {
|
|
34
|
+
if (!doc.vector)
|
|
35
|
+
continue;
|
|
36
|
+
const score = cosineSimilarity(queryVector, doc.vector);
|
|
37
|
+
scored.push({
|
|
38
|
+
id: doc.id,
|
|
39
|
+
text: doc.text,
|
|
40
|
+
score,
|
|
41
|
+
metadata: doc.metadata,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
scored.sort((a, b) => b.score - a.score);
|
|
45
|
+
return scored.slice(0, topK);
|
|
46
|
+
}
|
|
47
|
+
searchByKeyword(query, topK = 3) {
|
|
48
|
+
const lowerQuery = query.toLowerCase();
|
|
49
|
+
const scored = [];
|
|
50
|
+
for (const doc of this.documents) {
|
|
51
|
+
const lowerText = doc.text.toLowerCase();
|
|
52
|
+
let matchCount = 0;
|
|
53
|
+
const terms = lowerQuery.split(/\s+/).filter(Boolean);
|
|
54
|
+
for (const term of terms) {
|
|
55
|
+
if (lowerText.includes(term))
|
|
56
|
+
matchCount++;
|
|
57
|
+
}
|
|
58
|
+
if (matchCount > 0) {
|
|
59
|
+
scored.push({
|
|
60
|
+
id: doc.id,
|
|
61
|
+
text: doc.text,
|
|
62
|
+
score: matchCount / terms.length,
|
|
63
|
+
metadata: doc.metadata,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
scored.sort((a, b) => b.score - a.score);
|
|
68
|
+
return scored.slice(0, topK);
|
|
69
|
+
}
|
|
70
|
+
clear() {
|
|
71
|
+
this.documents = [];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.InMemoryVectorStore = InMemoryVectorStore;
|
|
75
|
+
/**
|
|
76
|
+
* Creates a knowledge retriever tool that can be provided directly to an AI agent.
|
|
77
|
+
*/
|
|
78
|
+
function createRetrieverTool(options) {
|
|
79
|
+
const { name = 'search_knowledge_base', description = 'Search the knowledge base for relevant context, documentation, or domain facts.', store, embed, topK = 3, } = options;
|
|
80
|
+
return (0, tool_1.tool)({
|
|
81
|
+
name,
|
|
82
|
+
description,
|
|
83
|
+
parameters: {
|
|
84
|
+
type: 'object',
|
|
85
|
+
properties: {
|
|
86
|
+
query: {
|
|
87
|
+
type: 'string',
|
|
88
|
+
description: 'The search query or keyword phrase to find context for',
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
required: ['query'],
|
|
92
|
+
},
|
|
93
|
+
execute: async ({ query }) => {
|
|
94
|
+
let matches = [];
|
|
95
|
+
if (embed) {
|
|
96
|
+
const queryVector = await embed(query);
|
|
97
|
+
matches = store.search(queryVector, topK);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
matches = store.searchByKeyword(query, topK);
|
|
101
|
+
}
|
|
102
|
+
return matches.map((m) => ({
|
|
103
|
+
id: m.id,
|
|
104
|
+
content: m.text,
|
|
105
|
+
score: Math.round(m.score * 100) / 100,
|
|
106
|
+
metadata: m.metadata,
|
|
107
|
+
}));
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './use-agent';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./use-agent"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './index';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./index"), exports);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Message } from '../types';
|
|
2
|
+
export interface UseAgentOptions {
|
|
3
|
+
api?: string;
|
|
4
|
+
initialMessages?: Message[];
|
|
5
|
+
sessionId?: string;
|
|
6
|
+
onResponse?: (response: Response) => void;
|
|
7
|
+
onFinish?: (message: Message) => void;
|
|
8
|
+
onError?: (error: Error) => void;
|
|
9
|
+
}
|
|
10
|
+
export interface UseAgentResult {
|
|
11
|
+
messages: Message[];
|
|
12
|
+
input: string;
|
|
13
|
+
setInput: (value: string) => void;
|
|
14
|
+
handleInputChange: (e: any) => void;
|
|
15
|
+
handleSubmit: (e?: any, options?: {
|
|
16
|
+
prompt?: string;
|
|
17
|
+
}) => Promise<void>;
|
|
18
|
+
isLoading: boolean;
|
|
19
|
+
error: Error | null;
|
|
20
|
+
stop: () => void;
|
|
21
|
+
reload: () => Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
export declare function useAgent(options?: UseAgentOptions): UseAgentResult;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.useAgent = useAgent;
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
function useAgent(options = {}) {
|
|
7
|
+
const { api = '/api/chat', initialMessages = [], sessionId, onResponse, onFinish, onError, } = options;
|
|
8
|
+
const [messages, setMessages] = (0, react_1.useState)(initialMessages);
|
|
9
|
+
const [input, setInput] = (0, react_1.useState)('');
|
|
10
|
+
const [isLoading, setIsLoading] = (0, react_1.useState)(false);
|
|
11
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
12
|
+
const abortControllerRef = (0, react_1.useRef)(null);
|
|
13
|
+
const handleInputChange = (0, react_1.useCallback)((e) => {
|
|
14
|
+
setInput(e?.target?.value ?? e);
|
|
15
|
+
}, []);
|
|
16
|
+
const stop = (0, react_1.useCallback)(() => {
|
|
17
|
+
if (abortControllerRef.current) {
|
|
18
|
+
abortControllerRef.current.abort();
|
|
19
|
+
abortControllerRef.current = null;
|
|
20
|
+
setIsLoading(false);
|
|
21
|
+
}
|
|
22
|
+
}, []);
|
|
23
|
+
const sendPrompt = (0, react_1.useCallback)(async (promptToSend) => {
|
|
24
|
+
if (!promptToSend.trim())
|
|
25
|
+
return;
|
|
26
|
+
const userMessage = { role: 'user', content: promptToSend };
|
|
27
|
+
const newMessages = [...messages, userMessage];
|
|
28
|
+
setMessages(newMessages);
|
|
29
|
+
setInput('');
|
|
30
|
+
setIsLoading(true);
|
|
31
|
+
setError(null);
|
|
32
|
+
const abortController = new AbortController();
|
|
33
|
+
abortControllerRef.current = abortController;
|
|
34
|
+
try {
|
|
35
|
+
const response = await fetch(api, {
|
|
36
|
+
method: 'POST',
|
|
37
|
+
headers: { 'Content-Type': 'application/json' },
|
|
38
|
+
body: JSON.stringify({
|
|
39
|
+
prompt: promptToSend,
|
|
40
|
+
messages: newMessages,
|
|
41
|
+
sessionId,
|
|
42
|
+
}),
|
|
43
|
+
signal: abortController.signal,
|
|
44
|
+
});
|
|
45
|
+
onResponse?.(response);
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
const errText = await response.text().catch(() => '');
|
|
48
|
+
throw new Error(errText || `Request failed with status ${response.status}`);
|
|
49
|
+
}
|
|
50
|
+
if (!response.body) {
|
|
51
|
+
throw new Error('Response body is empty or not streamable');
|
|
52
|
+
}
|
|
53
|
+
const reader = response.body.getReader();
|
|
54
|
+
const decoder = new TextDecoder();
|
|
55
|
+
let buffer = '';
|
|
56
|
+
let assistantText = '';
|
|
57
|
+
// Add empty assistant message that will stream
|
|
58
|
+
setMessages((prev) => [...prev, { role: 'assistant', content: '' }]);
|
|
59
|
+
while (true) {
|
|
60
|
+
const { done, value } = await reader.read();
|
|
61
|
+
if (done)
|
|
62
|
+
break;
|
|
63
|
+
buffer += decoder.decode(value, { stream: true });
|
|
64
|
+
const lines = buffer.split('\n');
|
|
65
|
+
buffer = lines.pop() || '';
|
|
66
|
+
for (const line of lines) {
|
|
67
|
+
const trimmed = line.trim();
|
|
68
|
+
if (!trimmed.startsWith('data: '))
|
|
69
|
+
continue;
|
|
70
|
+
const payload = trimmed.slice(6);
|
|
71
|
+
if (payload === '[DONE]')
|
|
72
|
+
break;
|
|
73
|
+
try {
|
|
74
|
+
const chunk = JSON.parse(payload);
|
|
75
|
+
if (chunk.type === 'text-delta' && chunk.textDelta) {
|
|
76
|
+
assistantText += chunk.textDelta;
|
|
77
|
+
setMessages((prev) => {
|
|
78
|
+
const updated = [...prev];
|
|
79
|
+
const lastIdx = updated.length - 1;
|
|
80
|
+
if (lastIdx >= 0 && updated[lastIdx].role === 'assistant') {
|
|
81
|
+
updated[lastIdx] = {
|
|
82
|
+
...updated[lastIdx],
|
|
83
|
+
content: assistantText,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return updated;
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
else if (chunk.type === 'error' && chunk.error) {
|
|
90
|
+
throw new Error(chunk.error);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Ignore partial JSON chunks
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const finalAssistantMessage = {
|
|
99
|
+
role: 'assistant',
|
|
100
|
+
content: assistantText,
|
|
101
|
+
};
|
|
102
|
+
onFinish?.(finalAssistantMessage);
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
if (err?.name === 'AbortError')
|
|
106
|
+
return;
|
|
107
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
108
|
+
setError(e);
|
|
109
|
+
onError?.(e);
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
setIsLoading(false);
|
|
113
|
+
abortControllerRef.current = null;
|
|
114
|
+
}
|
|
115
|
+
}, [api, messages, sessionId, onResponse, onFinish, onError]);
|
|
116
|
+
const handleSubmit = (0, react_1.useCallback)(async (e, submitOptions) => {
|
|
117
|
+
e?.preventDefault?.();
|
|
118
|
+
const promptToSend = submitOptions?.prompt ?? input;
|
|
119
|
+
await sendPrompt(promptToSend);
|
|
120
|
+
}, [input, sendPrompt]);
|
|
121
|
+
const reload = (0, react_1.useCallback)(async () => {
|
|
122
|
+
const lastUserMessage = [...messages].reverse().find((m) => m.role === 'user');
|
|
123
|
+
if (lastUserMessage) {
|
|
124
|
+
await sendPrompt(lastUserMessage.content);
|
|
125
|
+
}
|
|
126
|
+
}, [messages, sendPrompt]);
|
|
127
|
+
return {
|
|
128
|
+
messages,
|
|
129
|
+
input,
|
|
130
|
+
setInput,
|
|
131
|
+
handleInputChange,
|
|
132
|
+
handleSubmit,
|
|
133
|
+
isLoading,
|
|
134
|
+
error,
|
|
135
|
+
stop,
|
|
136
|
+
reload,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { StreamChunk, TokenUsage, ToolCall } from './types';
|
|
2
|
+
export declare class AgentStream implements AsyncIterable<StreamChunk> {
|
|
3
|
+
private source;
|
|
4
|
+
constructor(source: AsyncIterable<StreamChunk>);
|
|
5
|
+
[Symbol.asyncIterator](): AsyncIterator<StreamChunk>;
|
|
6
|
+
/**
|
|
7
|
+
* Converts the stream into a Server-Sent Events (SSE) Response.
|
|
8
|
+
* Format is compatible with UI clients and standard EventSource.
|
|
9
|
+
*/
|
|
10
|
+
toDataStreamResponse(init?: ResponseInit): Response;
|
|
11
|
+
/**
|
|
12
|
+
* Converts the stream into a simple text-only Response stream.
|
|
13
|
+
*/
|
|
14
|
+
toTextStreamResponse(init?: ResponseInit): Response;
|
|
15
|
+
/**
|
|
16
|
+
* Collects all text and events from the stream into a single result.
|
|
17
|
+
*/
|
|
18
|
+
collect(): Promise<{
|
|
19
|
+
text: string;
|
|
20
|
+
toolCalls: ToolCall[];
|
|
21
|
+
usage?: TokenUsage;
|
|
22
|
+
}>;
|
|
23
|
+
}
|
|
24
|
+
export declare function createAIStreamResponse(stream: AsyncIterable<StreamChunk> | AgentStream, init?: ResponseInit): Response;
|