@absolutejs/absolute 0.19.0-beta.226 → 0.19.0-beta.228
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/.absolutejs/eslint-cache +1 -0
- package/.absolutejs/prettier.cache.json +42 -19
- package/.absolutejs/vue-tsc.tsbuildinfo +1 -1
- package/.claude/settings.local.json +2 -1
- package/ROADMAP.md +0 -25
- package/dist/{Image-y5bdvj57.vue → Image-b3r6hxqk.vue} +6 -1
- package/dist/ai/index.js +529 -0
- package/dist/ai/index.js.map +13 -0
- package/dist/ai/providers/anthropic.js +396 -0
- package/dist/ai/providers/anthropic.js.map +10 -0
- package/dist/ai/providers/ollama.js +233 -0
- package/dist/ai/providers/ollama.js.map +10 -0
- package/dist/ai/providers/openai.js +355 -0
- package/dist/ai/providers/openai.js.map +10 -0
- package/dist/ai-client/angular/ai/index.js +532 -0
- package/dist/ai-client/react/ai/index.js +499 -0
- package/dist/ai-client/vue/ai/index.js +460 -0
- package/dist/angular/ai/index.js +668 -0
- package/dist/angular/ai/index.js.map +15 -0
- package/dist/angular/components/image.component.js +1 -1
- package/dist/angular/index.js +11 -1
- package/dist/angular/index.js.map +3 -3
- package/dist/build.js +48 -2
- package/dist/build.js.map +4 -4
- package/dist/index.js +50 -2
- package/dist/index.js.map +6 -6
- package/dist/react/ai/index.js +635 -0
- package/dist/react/ai/index.js.map +16 -0
- package/dist/react/components/index.js +11 -1
- package/dist/react/components/index.js.map +2 -2
- package/dist/react/hooks/index.js +11 -1
- package/dist/react/hooks/index.js.map +2 -2
- package/dist/react/index.js +11 -1
- package/dist/react/index.js.map +3 -3
- package/dist/src/ai/client/actions.d.ts +46 -0
- package/dist/src/ai/client/connection.d.ts +9 -0
- package/dist/src/ai/client/messageStore.d.ts +12 -0
- package/dist/src/ai/conversationManager.d.ts +11 -0
- package/dist/src/ai/index.d.ts +3 -0
- package/dist/src/ai/protocol.d.ts +4 -0
- package/dist/src/ai/providers/anthropic.d.ts +3 -0
- package/dist/src/ai/providers/ollama.d.ts +6 -0
- package/dist/src/ai/providers/openai.d.ts +7 -0
- package/dist/src/ai/streamAI.d.ts +2 -0
- package/dist/src/angular/ai/ai-stream.service.d.ts +15 -0
- package/dist/src/angular/ai/index.d.ts +1 -0
- package/dist/src/react/ai/AIStreamProvider.d.ts +13 -0
- package/dist/src/react/ai/index.d.ts +2 -0
- package/dist/src/react/ai/useAIStream.d.ts +8 -0
- package/dist/src/svelte/ai/createAIStream.d.ts +10 -0
- package/dist/src/svelte/ai/index.d.ts +1 -0
- package/dist/src/vue/ai/index.d.ts +1 -0
- package/dist/src/vue/ai/useAIStream.d.ts +22 -0
- package/dist/svelte/ai/index.js +590 -0
- package/dist/svelte/ai/index.js.map +15 -0
- package/dist/svelte/components/Image.svelte +6 -1
- package/dist/svelte/index.js +11 -1
- package/dist/svelte/index.js.map +3 -3
- package/dist/types/ai.d.ts +188 -0
- package/dist/types/anthropic.d.ts +18 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/typeGuards.d.ts +3 -0
- package/dist/vue/ai/index.js +596 -0
- package/dist/vue/ai/index.js.map +15 -0
- package/dist/vue/components/Image.vue +6 -1
- package/dist/vue/components/index.js +12 -2
- package/dist/vue/components/index.js.map +1 -1
- package/dist/vue/index.js +11 -1
- package/dist/vue/index.js.map +3 -3
- package/package.json +36 -1
- package/scripts/build.ts +33 -0
- package/types/ai.ts +235 -0
- package/types/anthropic.ts +17 -0
- package/types/index.ts +1 -0
- package/types/typeGuards.ts +72 -1
|
@@ -256,7 +256,8 @@
|
|
|
256
256
|
"Bash(git status:*)",
|
|
257
257
|
"Bash(find /home/alexkahn/abs/docs -path */src/frontend/* -type f \\\\\\(-name *.ts -o -name *.tsx \\\\\\))",
|
|
258
258
|
"Bash(find /home/alexkahn/abs/absolutejs/example -path */generated/* -name *.js -type f)",
|
|
259
|
-
"mcp__playwright__browser_take_screenshot"
|
|
259
|
+
"mcp__playwright__browser_take_screenshot",
|
|
260
|
+
"Bash(xargs -r kill -9)"
|
|
260
261
|
]
|
|
261
262
|
}
|
|
262
263
|
}
|
package/ROADMAP.md
CHANGED
|
@@ -4,31 +4,6 @@ Features missing from AbsoluteJS that Next.js provides, ordered by priority. Eac
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## 2. P1 — Loading / Error / Not-Found States
|
|
8
|
-
|
|
9
|
-
**What Next.js does:**
|
|
10
|
-
Per-route-segment `loading.tsx` (shows during async data fetch), `error.tsx` (catches runtime errors with React error boundary), and `not-found.tsx` (404 page). These are automatic — drop the file in and it works.
|
|
11
|
-
|
|
12
|
-
**What AbsoluteJS has today:**
|
|
13
|
-
- Dev error overlay (`src/dev/client/errorOverlay.ts`) for compilation/runtime errors in development
|
|
14
|
-
- SSR error page (`src/utils/ssrErrorPage.ts`) that returns a styled error page when server rendering fails
|
|
15
|
-
- No production error boundaries, no loading states, no 404 handling
|
|
16
|
-
|
|
17
|
-
**What needs to be built:**
|
|
18
|
-
- A documented pattern for error boundaries per framework (React has `ErrorBoundary`, Vue has `onErrorCaptured`, Svelte has `<svelte:boundary>`, Angular has `ErrorHandler`)
|
|
19
|
-
- A helper or wrapper that each page handler can use to catch SSR errors and render a user-defined error page instead of the generic one
|
|
20
|
-
- A loading state pattern — for React this means Suspense boundaries with fallback UI; for streaming SSR, sending the shell immediately and streaming content as it resolves
|
|
21
|
-
- A 404 handler — an Elysia catch-all route that renders a user-defined not-found page
|
|
22
|
-
- Framework-specific examples showing how to wire each of these up
|
|
23
|
-
|
|
24
|
-
**Files likely involved:**
|
|
25
|
-
- `src/utils/ssrErrorPage.ts` — make it accept a user-defined error component
|
|
26
|
-
- Each framework's `pageHandler.ts` — add error/loading handling to the streaming pipeline
|
|
27
|
-
- New: `src/utils/notFoundPage.ts` or a convention for 404 pages
|
|
28
|
-
- Example directory — add error/loading/not-found examples
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
7
|
## 3. P1 — Client-Side Navigation / SPA Mode with `<Link>`
|
|
33
8
|
|
|
34
9
|
**What Next.js does:**
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, ref } from 'vue';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
DEFAULT_QUALITY,
|
|
5
|
+
buildOptimizedUrl,
|
|
6
|
+
generateBlurSvg,
|
|
7
|
+
generateSrcSet
|
|
8
|
+
} from '@absolutejs/absolute/image';
|
|
4
9
|
|
|
5
10
|
type ImageLoader = (params: {
|
|
6
11
|
src: string;
|
package/dist/ai/index.js
ADDED
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
function __accessProp(key) {
|
|
9
|
+
return this[key];
|
|
10
|
+
}
|
|
11
|
+
var __toESMCache_node;
|
|
12
|
+
var __toESMCache_esm;
|
|
13
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
14
|
+
var canCache = mod != null && typeof mod === "object";
|
|
15
|
+
if (canCache) {
|
|
16
|
+
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
17
|
+
var cached = cache.get(mod);
|
|
18
|
+
if (cached)
|
|
19
|
+
return cached;
|
|
20
|
+
}
|
|
21
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
22
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
23
|
+
for (let key of __getOwnPropNames(mod))
|
|
24
|
+
if (!__hasOwnProp.call(to, key))
|
|
25
|
+
__defProp(to, key, {
|
|
26
|
+
get: __accessProp.bind(mod, key),
|
|
27
|
+
enumerable: true
|
|
28
|
+
});
|
|
29
|
+
if (canCache)
|
|
30
|
+
cache.set(mod, to);
|
|
31
|
+
return to;
|
|
32
|
+
};
|
|
33
|
+
var __toCommonJS = (from) => {
|
|
34
|
+
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
35
|
+
if (entry)
|
|
36
|
+
return entry;
|
|
37
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
38
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
39
|
+
for (var key of __getOwnPropNames(from))
|
|
40
|
+
if (!__hasOwnProp.call(entry, key))
|
|
41
|
+
__defProp(entry, key, {
|
|
42
|
+
get: __accessProp.bind(from, key),
|
|
43
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
__moduleCache.set(from, entry);
|
|
47
|
+
return entry;
|
|
48
|
+
};
|
|
49
|
+
var __moduleCache;
|
|
50
|
+
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
51
|
+
var __returnValue = (v) => v;
|
|
52
|
+
function __exportSetter(name, newValue) {
|
|
53
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
54
|
+
}
|
|
55
|
+
var __export = (target, all) => {
|
|
56
|
+
for (var name in all)
|
|
57
|
+
__defProp(target, name, {
|
|
58
|
+
get: all[name],
|
|
59
|
+
enumerable: true,
|
|
60
|
+
configurable: true,
|
|
61
|
+
set: __exportSetter.bind(all, name)
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
var __legacyDecorateClassTS = function(decorators, target, key, desc) {
|
|
65
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
66
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
67
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
68
|
+
else
|
|
69
|
+
for (var i = decorators.length - 1;i >= 0; i--)
|
|
70
|
+
if (d = decorators[i])
|
|
71
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
72
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
73
|
+
};
|
|
74
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
75
|
+
var __require = import.meta.require;
|
|
76
|
+
|
|
77
|
+
// types/typeGuards.ts
|
|
78
|
+
var isValidAIClientMessage = (data) => {
|
|
79
|
+
if (!data || typeof data !== "object") {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
if (!("type" in data) || typeof data.type !== "string") {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
switch (data.type) {
|
|
86
|
+
case "message":
|
|
87
|
+
return "content" in data && typeof data.content === "string";
|
|
88
|
+
case "cancel":
|
|
89
|
+
return "conversationId" in data && typeof data.conversationId === "string";
|
|
90
|
+
case "branch":
|
|
91
|
+
return "messageId" in data && typeof data.messageId === "string" && "content" in data && typeof data.content === "string" && "conversationId" in data && typeof data.conversationId === "string";
|
|
92
|
+
default:
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}, isValidAIServerMessage = (data) => {
|
|
96
|
+
if (!data || typeof data !== "object") {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
if (!("type" in data) || typeof data.type !== "string") {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
switch (data.type) {
|
|
103
|
+
case "chunk":
|
|
104
|
+
return "content" in data && typeof data.content === "string" && "messageId" in data && "conversationId" in data;
|
|
105
|
+
case "tool_status":
|
|
106
|
+
return "name" in data && "status" in data && "messageId" in data && "conversationId" in data;
|
|
107
|
+
case "complete":
|
|
108
|
+
return "messageId" in data && "conversationId" in data;
|
|
109
|
+
case "error":
|
|
110
|
+
return "message" in data && typeof data.message === "string";
|
|
111
|
+
default:
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}, isValidHMRClientMessage = (data) => {
|
|
115
|
+
if (!data || typeof data !== "object") {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
if (!("type" in data) || typeof data.type !== "string") {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
switch (data.type) {
|
|
122
|
+
case "ping":
|
|
123
|
+
return true;
|
|
124
|
+
case "ready":
|
|
125
|
+
return true;
|
|
126
|
+
case "request-rebuild":
|
|
127
|
+
return true;
|
|
128
|
+
case "hydration-error":
|
|
129
|
+
return true;
|
|
130
|
+
case "hmr-timing":
|
|
131
|
+
return true;
|
|
132
|
+
default:
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// src/ai/protocol.ts
|
|
138
|
+
var generateId = () => crypto.randomUUID();
|
|
139
|
+
var parseAIMessage = (raw) => {
|
|
140
|
+
if (raw === null || raw === undefined) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
let text;
|
|
144
|
+
if (typeof raw === "string") {
|
|
145
|
+
text = raw;
|
|
146
|
+
} else if (raw instanceof ArrayBuffer) {
|
|
147
|
+
text = new TextDecoder().decode(raw);
|
|
148
|
+
} else if (ArrayBuffer.isView(raw)) {
|
|
149
|
+
text = new TextDecoder().decode(raw);
|
|
150
|
+
} else if (typeof raw === "object") {
|
|
151
|
+
if (isValidAIClientMessage(raw)) {
|
|
152
|
+
return raw;
|
|
153
|
+
}
|
|
154
|
+
return null;
|
|
155
|
+
} else {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
const parsed = JSON.parse(text);
|
|
160
|
+
if (isValidAIClientMessage(parsed)) {
|
|
161
|
+
return parsed;
|
|
162
|
+
}
|
|
163
|
+
return null;
|
|
164
|
+
} catch {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
var serializeAIMessage = (msg) => JSON.stringify(msg);
|
|
169
|
+
|
|
170
|
+
// src/ai/streamAI.ts
|
|
171
|
+
var WS_OPEN = 1;
|
|
172
|
+
var BACKPRESSURE_THRESHOLD = 1048576;
|
|
173
|
+
var BACKPRESSURE_DELAY = 10;
|
|
174
|
+
var DEFAULT_MAX_TURNS = 10;
|
|
175
|
+
var INITIAL_TURN = 0;
|
|
176
|
+
var delay = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
177
|
+
var checkBackpressure = async (socket) => {
|
|
178
|
+
if (!("raw" in socket)) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const { raw } = socket;
|
|
182
|
+
if (raw && typeof raw === "object" && "bufferedAmount" in raw && typeof raw.bufferedAmount === "number" && raw.bufferedAmount > BACKPRESSURE_THRESHOLD) {
|
|
183
|
+
await delay(BACKPRESSURE_DELAY);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
var sendMessage = async (socket, msg) => {
|
|
187
|
+
if (socket.readyState !== WS_OPEN) {
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
await checkBackpressure(socket);
|
|
191
|
+
socket.send(serializeAIMessage(msg));
|
|
192
|
+
return true;
|
|
193
|
+
};
|
|
194
|
+
var buildToolDefinitions = (tools) => Object.entries(tools).map(([name, def]) => ({
|
|
195
|
+
description: def.description,
|
|
196
|
+
input_schema: def.input,
|
|
197
|
+
name
|
|
198
|
+
}));
|
|
199
|
+
var extractTextContent = (chunk, onChunk) => {
|
|
200
|
+
if (!onChunk) {
|
|
201
|
+
return chunk.content;
|
|
202
|
+
}
|
|
203
|
+
const transformed = onChunk(chunk);
|
|
204
|
+
if (transformed && typeof transformed === "object" && "content" in transformed) {
|
|
205
|
+
return transformed.content;
|
|
206
|
+
}
|
|
207
|
+
return chunk.content;
|
|
208
|
+
};
|
|
209
|
+
var sendToolRunning = async (socket, toolName, toolInput, messageId, conversationId) => sendMessage(socket, {
|
|
210
|
+
conversationId,
|
|
211
|
+
input: toolInput,
|
|
212
|
+
messageId,
|
|
213
|
+
name: toolName,
|
|
214
|
+
status: "running",
|
|
215
|
+
type: "tool_status"
|
|
216
|
+
});
|
|
217
|
+
var sendToolComplete = async (socket, toolName, result, messageId, conversationId) => sendMessage(socket, {
|
|
218
|
+
conversationId,
|
|
219
|
+
messageId,
|
|
220
|
+
name: toolName,
|
|
221
|
+
result,
|
|
222
|
+
status: "complete",
|
|
223
|
+
type: "tool_status"
|
|
224
|
+
});
|
|
225
|
+
var executeTool = async (options, toolName, toolInput) => {
|
|
226
|
+
const toolDef = options.tools?.[toolName];
|
|
227
|
+
if (!toolDef) {
|
|
228
|
+
return `Error: unknown tool "${toolName}"`;
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
return await toolDef.handler(toolInput);
|
|
232
|
+
} catch (err) {
|
|
233
|
+
return `Error: ${err instanceof Error ? err.message : String(err)}`;
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
var buildToolUseBlock = (toolUseId, toolName, toolInput) => [
|
|
237
|
+
{
|
|
238
|
+
id: toolUseId,
|
|
239
|
+
input: toolInput,
|
|
240
|
+
name: toolName,
|
|
241
|
+
type: "tool_use"
|
|
242
|
+
}
|
|
243
|
+
];
|
|
244
|
+
var buildToolResultBlock = (toolUseId, result) => [
|
|
245
|
+
{
|
|
246
|
+
content: result,
|
|
247
|
+
tool_use_id: toolUseId,
|
|
248
|
+
type: "tool_result"
|
|
249
|
+
}
|
|
250
|
+
];
|
|
251
|
+
var handleToolChunkText = (chunk, state, options, socket, messageId, conversationId) => {
|
|
252
|
+
const textContent = extractTextContent(chunk, options.onChunk);
|
|
253
|
+
state.currentFullResponse += textContent;
|
|
254
|
+
sendMessage(socket, {
|
|
255
|
+
content: textContent,
|
|
256
|
+
conversationId,
|
|
257
|
+
messageId,
|
|
258
|
+
type: "chunk"
|
|
259
|
+
});
|
|
260
|
+
};
|
|
261
|
+
var handleToolChunkToolUse = (chunk, state) => {
|
|
262
|
+
state.currentToolUseId = chunk.id;
|
|
263
|
+
state.currentToolName = chunk.name;
|
|
264
|
+
state.currentToolInput = chunk.input;
|
|
265
|
+
};
|
|
266
|
+
var processToolChunk = (chunk, state, options, socket, messageId, conversationId) => {
|
|
267
|
+
let hitAnotherTool = false;
|
|
268
|
+
switch (chunk.type) {
|
|
269
|
+
case "text":
|
|
270
|
+
handleToolChunkText(chunk, state, options, socket, messageId, conversationId);
|
|
271
|
+
break;
|
|
272
|
+
case "tool_use":
|
|
273
|
+
handleToolChunkToolUse(chunk, state);
|
|
274
|
+
hitAnotherTool = true;
|
|
275
|
+
break;
|
|
276
|
+
case "done":
|
|
277
|
+
state.currentUsage = chunk.usage;
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
return hitAnotherTool;
|
|
281
|
+
};
|
|
282
|
+
var processToolTurn = async (socket, options, state, messageId, conversationId, signal) => {
|
|
283
|
+
await sendToolRunning(socket, state.currentToolName, state.currentToolInput, messageId, conversationId);
|
|
284
|
+
const result = await executeTool(options, state.currentToolName, state.currentToolInput);
|
|
285
|
+
await sendToolComplete(socket, state.currentToolName, result, messageId, conversationId);
|
|
286
|
+
options.onToolUse?.(state.currentToolName, state.currentToolInput, result);
|
|
287
|
+
state.currentMessages.push({
|
|
288
|
+
content: buildToolUseBlock(state.currentToolUseId, state.currentToolName, state.currentToolInput),
|
|
289
|
+
role: "assistant"
|
|
290
|
+
});
|
|
291
|
+
state.currentMessages.push({
|
|
292
|
+
content: buildToolResultBlock(state.currentToolUseId, result),
|
|
293
|
+
role: "user"
|
|
294
|
+
});
|
|
295
|
+
const toolDefs = options.tools ? buildToolDefinitions(options.tools) : undefined;
|
|
296
|
+
const stream = options.provider.stream({
|
|
297
|
+
messages: state.currentMessages,
|
|
298
|
+
model: options.model,
|
|
299
|
+
signal,
|
|
300
|
+
systemPrompt: options.systemPrompt,
|
|
301
|
+
tools: toolDefs
|
|
302
|
+
});
|
|
303
|
+
return consumeToolStream(stream, state, options, socket, messageId, conversationId, signal);
|
|
304
|
+
};
|
|
305
|
+
var consumeToolStream = async (stream, state, options, socket, messageId, conversationId, signal) => {
|
|
306
|
+
for await (const chunk of stream) {
|
|
307
|
+
if (signal.aborted)
|
|
308
|
+
break;
|
|
309
|
+
const isToolHit = processToolChunk(chunk, state, options, socket, messageId, conversationId);
|
|
310
|
+
if (isToolHit)
|
|
311
|
+
return true;
|
|
312
|
+
}
|
|
313
|
+
return false;
|
|
314
|
+
};
|
|
315
|
+
var shouldContinueToolLoop = (state, maxTurns, signal) => state.currentTurn < maxTurns && !signal.aborted;
|
|
316
|
+
var executeToolLoop = async (socket, options, messages, toolUseId, toolName, toolInput, messageId, conversationId, signal, fullResponse, turn) => {
|
|
317
|
+
const maxTurns = options.maxTurns ?? DEFAULT_MAX_TURNS;
|
|
318
|
+
const state = {
|
|
319
|
+
currentFullResponse: fullResponse,
|
|
320
|
+
currentMessages: [...messages],
|
|
321
|
+
currentToolInput: toolInput,
|
|
322
|
+
currentToolName: toolName,
|
|
323
|
+
currentToolUseId: toolUseId,
|
|
324
|
+
currentTurn: turn,
|
|
325
|
+
currentUsage: undefined
|
|
326
|
+
};
|
|
327
|
+
while (shouldContinueToolLoop(state, maxTurns, signal)) {
|
|
328
|
+
const hitAnotherTool = await processToolTurn(socket, options, state, messageId, conversationId, signal);
|
|
329
|
+
if (!hitAnotherTool) {
|
|
330
|
+
return {
|
|
331
|
+
fullResponse: state.currentFullResponse,
|
|
332
|
+
usage: state.currentUsage
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
state.currentTurn++;
|
|
336
|
+
}
|
|
337
|
+
return {
|
|
338
|
+
fullResponse: state.currentFullResponse,
|
|
339
|
+
usage: state.currentUsage
|
|
340
|
+
};
|
|
341
|
+
};
|
|
342
|
+
var sendComplete = async (socket, messageId, conversationId, usage) => sendMessage(socket, {
|
|
343
|
+
conversationId,
|
|
344
|
+
messageId,
|
|
345
|
+
type: "complete",
|
|
346
|
+
usage
|
|
347
|
+
});
|
|
348
|
+
var sendError = async (socket, err, messageId, conversationId) => sendMessage(socket, {
|
|
349
|
+
conversationId,
|
|
350
|
+
message: err instanceof Error ? err.message : String(err),
|
|
351
|
+
messageId,
|
|
352
|
+
type: "error"
|
|
353
|
+
});
|
|
354
|
+
var handleTextChunk = async (chunk, options, socket, messageId, conversationId) => {
|
|
355
|
+
const textContent = extractTextContent(chunk, options.onChunk);
|
|
356
|
+
await sendMessage(socket, {
|
|
357
|
+
content: textContent,
|
|
358
|
+
conversationId,
|
|
359
|
+
messageId,
|
|
360
|
+
type: "chunk"
|
|
361
|
+
});
|
|
362
|
+
return textContent;
|
|
363
|
+
};
|
|
364
|
+
var handleToolUseChunk = async (socket, options, messages, chunkId, chunkName, chunkInput, messageId, conversationId, signal, fullResponse) => {
|
|
365
|
+
const toolResult = await executeToolLoop(socket, options, messages, chunkId, chunkName, chunkInput, messageId, conversationId, signal, fullResponse, INITIAL_TURN);
|
|
366
|
+
await sendComplete(socket, messageId, conversationId, toolResult.usage);
|
|
367
|
+
options.onComplete?.(toolResult.fullResponse, toolResult.usage);
|
|
368
|
+
return toolResult;
|
|
369
|
+
};
|
|
370
|
+
var processStreamTextChunk = async (chunk, options, socket, messageId, conversationId) => {
|
|
371
|
+
const textContent = await handleTextChunk(chunk, options, socket, messageId, conversationId);
|
|
372
|
+
return textContent;
|
|
373
|
+
};
|
|
374
|
+
var processStreamToolUseChunk = async (chunk, socket, options, messages, messageId, conversationId, signal, fullResponse) => {
|
|
375
|
+
await handleToolUseChunk(socket, options, messages, chunk.id, chunk.name, chunk.input, messageId, conversationId, signal, fullResponse);
|
|
376
|
+
};
|
|
377
|
+
var processStream = async (socket, options, messages, messageId, conversationId, signal) => {
|
|
378
|
+
const toolDefs = options.tools ? buildToolDefinitions(options.tools) : undefined;
|
|
379
|
+
const stream = options.provider.stream({
|
|
380
|
+
messages,
|
|
381
|
+
model: options.model,
|
|
382
|
+
signal,
|
|
383
|
+
systemPrompt: options.systemPrompt,
|
|
384
|
+
tools: toolDefs
|
|
385
|
+
});
|
|
386
|
+
const result = await consumeStream(stream, options, socket, messages, messageId, conversationId, signal);
|
|
387
|
+
if (!result.earlyReturn) {
|
|
388
|
+
await sendComplete(socket, messageId, conversationId, result.usage);
|
|
389
|
+
options.onComplete?.(result.fullResponse, result.usage);
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
var consumeStreamChunk = async (chunk, options, socket, messages, messageId, conversationId, signal, fullResponse) => {
|
|
393
|
+
switch (chunk.type) {
|
|
394
|
+
case "text":
|
|
395
|
+
return processStreamTextChunk(chunk, options, socket, messageId, conversationId);
|
|
396
|
+
case "tool_use":
|
|
397
|
+
await processStreamToolUseChunk(chunk, socket, options, messages, messageId, conversationId, signal, fullResponse);
|
|
398
|
+
return { earlyReturn: true, fullResponse, usage: undefined };
|
|
399
|
+
case "done":
|
|
400
|
+
return { earlyReturn: false, fullResponse, usage: chunk.usage };
|
|
401
|
+
}
|
|
402
|
+
return "";
|
|
403
|
+
};
|
|
404
|
+
var applyStreamChunkResult = (result, state) => {
|
|
405
|
+
if (typeof result === "string") {
|
|
406
|
+
state.fullResponse += result;
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
if (result.earlyReturn)
|
|
410
|
+
return result;
|
|
411
|
+
state.usage = result.usage;
|
|
412
|
+
return;
|
|
413
|
+
};
|
|
414
|
+
var consumeStream = async (stream, options, socket, messages, messageId, conversationId, signal) => {
|
|
415
|
+
const state = { fullResponse: "", usage: undefined };
|
|
416
|
+
for await (const chunk of stream) {
|
|
417
|
+
if (signal.aborted)
|
|
418
|
+
break;
|
|
419
|
+
const result = await consumeStreamChunk(chunk, options, socket, messages, messageId, conversationId, signal, state.fullResponse);
|
|
420
|
+
const earlyExit = applyStreamChunkResult(result, state);
|
|
421
|
+
if (earlyExit)
|
|
422
|
+
return earlyExit;
|
|
423
|
+
}
|
|
424
|
+
const finalResult = {
|
|
425
|
+
earlyReturn: false,
|
|
426
|
+
fullResponse: state.fullResponse,
|
|
427
|
+
usage: state.usage
|
|
428
|
+
};
|
|
429
|
+
return finalResult;
|
|
430
|
+
};
|
|
431
|
+
var streamAI = async (socket, conversationId, messageId, options) => {
|
|
432
|
+
const signal = options.signal ?? new AbortController().signal;
|
|
433
|
+
const messages = options.messages ? [...options.messages] : [];
|
|
434
|
+
try {
|
|
435
|
+
await processStream(socket, options, messages, messageId, conversationId, signal);
|
|
436
|
+
} catch (err) {
|
|
437
|
+
await handleStreamError(socket, err, messageId, conversationId, signal);
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
var handleStreamError = async (socket, err, messageId, conversationId, signal) => {
|
|
441
|
+
if (signal.aborted) {
|
|
442
|
+
await sendComplete(socket, messageId, conversationId);
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
await sendError(socket, err, messageId, conversationId);
|
|
446
|
+
};
|
|
447
|
+
// src/ai/conversationManager.ts
|
|
448
|
+
var NOT_FOUND = -1;
|
|
449
|
+
var createConversationManager = () => {
|
|
450
|
+
const conversations = new Map;
|
|
451
|
+
const getOrCreate = (conversationId) => {
|
|
452
|
+
const id = conversationId ?? generateId();
|
|
453
|
+
let conversation = conversations.get(id);
|
|
454
|
+
if (!conversation) {
|
|
455
|
+
conversation = { id, messages: [] };
|
|
456
|
+
conversations.set(id, conversation);
|
|
457
|
+
}
|
|
458
|
+
return conversation;
|
|
459
|
+
};
|
|
460
|
+
const appendMessage = (conversationId, message) => {
|
|
461
|
+
const conversation = getOrCreate(conversationId);
|
|
462
|
+
conversation.messages.push(message);
|
|
463
|
+
};
|
|
464
|
+
const branch = (fromMessageId, sourceConversationId) => {
|
|
465
|
+
const source = conversations.get(sourceConversationId);
|
|
466
|
+
if (!source) {
|
|
467
|
+
return null;
|
|
468
|
+
}
|
|
469
|
+
const cutoffIndex = source.messages.findIndex((msg) => msg.id === fromMessageId);
|
|
470
|
+
if (cutoffIndex === NOT_FOUND) {
|
|
471
|
+
return null;
|
|
472
|
+
}
|
|
473
|
+
const newId = generateId();
|
|
474
|
+
const branchedMessages = source.messages.slice(0, cutoffIndex + 1).map((msg) => ({ ...msg, conversationId: newId }));
|
|
475
|
+
const newConversation = {
|
|
476
|
+
id: newId,
|
|
477
|
+
messages: branchedMessages
|
|
478
|
+
};
|
|
479
|
+
conversations.set(newId, newConversation);
|
|
480
|
+
return newId;
|
|
481
|
+
};
|
|
482
|
+
const emptyHistory = [];
|
|
483
|
+
const getHistory = (conversationId) => {
|
|
484
|
+
const conversation = conversations.get(conversationId);
|
|
485
|
+
if (!conversation) {
|
|
486
|
+
return emptyHistory;
|
|
487
|
+
}
|
|
488
|
+
const history = conversation.messages.map((msg) => ({
|
|
489
|
+
content: msg.content,
|
|
490
|
+
role: msg.role
|
|
491
|
+
}));
|
|
492
|
+
return history;
|
|
493
|
+
};
|
|
494
|
+
const getAbortController = (conversationId) => {
|
|
495
|
+
const conversation = getOrCreate(conversationId);
|
|
496
|
+
const controller = new AbortController;
|
|
497
|
+
conversation.activeStreamAbort = controller;
|
|
498
|
+
return controller;
|
|
499
|
+
};
|
|
500
|
+
const abort = (conversationId) => {
|
|
501
|
+
const conversation = conversations.get(conversationId);
|
|
502
|
+
if (conversation?.activeStreamAbort) {
|
|
503
|
+
conversation.activeStreamAbort.abort();
|
|
504
|
+
conversation.activeStreamAbort = undefined;
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
const get = (conversationId) => conversations.get(conversationId);
|
|
508
|
+
const remove = (conversationId) => conversations.delete(conversationId);
|
|
509
|
+
return {
|
|
510
|
+
abort,
|
|
511
|
+
appendMessage,
|
|
512
|
+
branch,
|
|
513
|
+
get,
|
|
514
|
+
getAbortController,
|
|
515
|
+
getHistory,
|
|
516
|
+
getOrCreate,
|
|
517
|
+
remove
|
|
518
|
+
};
|
|
519
|
+
};
|
|
520
|
+
export {
|
|
521
|
+
streamAI,
|
|
522
|
+
serializeAIMessage,
|
|
523
|
+
parseAIMessage,
|
|
524
|
+
generateId,
|
|
525
|
+
createConversationManager
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
//# debugId=522D65A44B1E30AF64756E2164756E21
|
|
529
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../types/typeGuards.ts", "../src/ai/protocol.ts", "../src/ai/streamAI.ts", "../src/ai/conversationManager.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { AIClientMessage, AIServerMessage } from './ai';\nimport type { HMRClientMessage } from './messages';\n\n/* Type guard for AI client messages */\nexport const isValidAIClientMessage = (\n\tdata: unknown\n): data is AIClientMessage => {\n\tif (!data || typeof data !== 'object') {\n\t\treturn false;\n\t}\n\n\tif (!('type' in data) || typeof data.type !== 'string') {\n\t\treturn false;\n\t}\n\n\tswitch (data.type) {\n\t\tcase 'message':\n\t\t\treturn 'content' in data && typeof data.content === 'string';\n\t\tcase 'cancel':\n\t\t\treturn (\n\t\t\t\t'conversationId' in data &&\n\t\t\t\ttypeof data.conversationId === 'string'\n\t\t\t);\n\t\tcase 'branch':\n\t\t\treturn (\n\t\t\t\t'messageId' in data &&\n\t\t\t\ttypeof data.messageId === 'string' &&\n\t\t\t\t'content' in data &&\n\t\t\t\ttypeof data.content === 'string' &&\n\t\t\t\t'conversationId' in data &&\n\t\t\t\ttypeof data.conversationId === 'string'\n\t\t\t);\n\t\tdefault:\n\t\t\treturn false;\n\t}\n};\n\n/* Type guard for AI server messages */\nexport const isValidAIServerMessage = (\n\tdata: unknown\n): data is AIServerMessage => {\n\tif (!data || typeof data !== 'object') {\n\t\treturn false;\n\t}\n\n\tif (!('type' in data) || typeof data.type !== 'string') {\n\t\treturn false;\n\t}\n\n\tswitch (data.type) {\n\t\tcase 'chunk':\n\t\t\treturn (\n\t\t\t\t'content' in data &&\n\t\t\t\ttypeof data.content === 'string' &&\n\t\t\t\t'messageId' in data &&\n\t\t\t\t'conversationId' in data\n\t\t\t);\n\t\tcase 'tool_status':\n\t\t\treturn (\n\t\t\t\t'name' in data &&\n\t\t\t\t'status' in data &&\n\t\t\t\t'messageId' in data &&\n\t\t\t\t'conversationId' in data\n\t\t\t);\n\t\tcase 'complete':\n\t\t\treturn 'messageId' in data && 'conversationId' in data;\n\t\tcase 'error':\n\t\t\treturn 'message' in data && typeof data.message === 'string';\n\t\tdefault:\n\t\t\treturn false;\n\t}\n};\n\n/* Type guard for HMR client messages */\nexport const isValidHMRClientMessage = (\n\tdata: unknown\n): data is HMRClientMessage => {\n\tif (!data || typeof data !== 'object') {\n\t\treturn false;\n\t}\n\n\tif (!('type' in data) || typeof data.type !== 'string') {\n\t\treturn false;\n\t}\n\n\tswitch (data.type) {\n\t\tcase 'ping':\n\t\t\treturn true;\n\t\tcase 'ready':\n\t\t\treturn true;\n\t\tcase 'request-rebuild':\n\t\t\treturn true;\n\t\tcase 'hydration-error':\n\t\t\treturn true;\n\t\tcase 'hmr-timing':\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n};\n",
|
|
6
|
+
"import type { AIServerMessage } from '../../types/ai';\nimport { isValidAIClientMessage } from '../../types/typeGuards';\n\nexport const generateId = () => crypto.randomUUID();\n\nexport const parseAIMessage = (raw: unknown) => {\n\tif (raw === null || raw === undefined) {\n\t\treturn null;\n\t}\n\n\tlet text: string;\n\n\tif (typeof raw === 'string') {\n\t\ttext = raw;\n\t} else if (raw instanceof ArrayBuffer) {\n\t\ttext = new TextDecoder().decode(raw);\n\t} else if (ArrayBuffer.isView(raw)) {\n\t\ttext = new TextDecoder().decode(raw);\n\t} else if (typeof raw === 'object') {\n\t\tif (isValidAIClientMessage(raw)) {\n\t\t\treturn raw;\n\t\t}\n\n\t\treturn null;\n\t} else {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(text);\n\n\t\tif (isValidAIClientMessage(parsed)) {\n\t\t\treturn parsed;\n\t\t}\n\n\t\treturn null;\n\t} catch {\n\t\treturn null;\n\t}\n};\n\nexport const serializeAIMessage = (msg: AIServerMessage) => JSON.stringify(msg);\n",
|
|
7
|
+
"import type {\n\tAIChunk,\n\tAIProviderMessage,\n\tAIServerMessage,\n\tAITextChunk,\n\tAIToolMap,\n\tAIUsage,\n\tAIWebSocket,\n\tStreamAIOptions\n} from '../../types/ai';\nimport { serializeAIMessage } from './protocol';\n\nconst WS_OPEN = 1;\nconst BACKPRESSURE_THRESHOLD = 1_048_576;\nconst BACKPRESSURE_DELAY = 10;\nconst DEFAULT_MAX_TURNS = 10;\nconst INITIAL_TURN = 0;\n\nconst delay = (milliseconds: number) =>\n\t// eslint-disable-next-line promise/avoid-new\n\tnew Promise<void>((resolve) => setTimeout(resolve, milliseconds));\n\nconst checkBackpressure = async (socket: AIWebSocket) => {\n\tif (!('raw' in socket)) {\n\t\treturn;\n\t}\n\n\tconst { raw } = socket;\n\n\tif (\n\t\traw &&\n\t\ttypeof raw === 'object' &&\n\t\t'bufferedAmount' in raw &&\n\t\ttypeof raw.bufferedAmount === 'number' &&\n\t\traw.bufferedAmount > BACKPRESSURE_THRESHOLD\n\t) {\n\t\tawait delay(BACKPRESSURE_DELAY);\n\t}\n};\n\nconst sendMessage = async (socket: AIWebSocket, msg: AIServerMessage) => {\n\tif (socket.readyState !== WS_OPEN) {\n\t\treturn false;\n\t}\n\n\tawait checkBackpressure(socket);\n\n\tsocket.send(serializeAIMessage(msg));\n\n\treturn true;\n};\n\nconst buildToolDefinitions = (tools: AIToolMap) =>\n\tObject.entries(tools).map(([name, def]) => ({\n\t\tdescription: def.description,\n\t\tinput_schema: def.input,\n\t\tname\n\t}));\n\nconst extractTextContent = (\n\tchunk: AITextChunk,\n\tonChunk?: (chunk: AITextChunk) => AITextChunk | void\n) => {\n\tif (!onChunk) {\n\t\treturn chunk.content;\n\t}\n\n\tconst transformed = onChunk(chunk);\n\n\tif (\n\t\ttransformed &&\n\t\ttypeof transformed === 'object' &&\n\t\t'content' in transformed\n\t) {\n\t\treturn transformed.content;\n\t}\n\n\treturn chunk.content;\n};\n\nconst sendToolRunning = async (\n\tsocket: AIWebSocket,\n\ttoolName: string,\n\ttoolInput: unknown,\n\tmessageId: string,\n\tconversationId: string\n) =>\n\tsendMessage(socket, {\n\t\tconversationId,\n\t\tinput: toolInput,\n\t\tmessageId,\n\t\tname: toolName,\n\t\tstatus: 'running',\n\t\ttype: 'tool_status'\n\t});\n\nconst sendToolComplete = async (\n\tsocket: AIWebSocket,\n\ttoolName: string,\n\tresult: string,\n\tmessageId: string,\n\tconversationId: string\n) =>\n\tsendMessage(socket, {\n\t\tconversationId,\n\t\tmessageId,\n\t\tname: toolName,\n\t\tresult,\n\t\tstatus: 'complete',\n\t\ttype: 'tool_status'\n\t});\n\nconst executeTool = async (\n\toptions: StreamAIOptions,\n\ttoolName: string,\n\ttoolInput: unknown\n) => {\n\tconst toolDef = options.tools?.[toolName];\n\n\tif (!toolDef) {\n\t\treturn `Error: unknown tool \"${toolName}\"`;\n\t}\n\n\ttry {\n\t\treturn await toolDef.handler(toolInput);\n\t} catch (err) {\n\t\treturn `Error: ${err instanceof Error ? err.message : String(err)}`;\n\t}\n};\n\nconst buildToolUseBlock = (\n\ttoolUseId: string,\n\ttoolName: string,\n\ttoolInput: unknown\n) => [\n\t{\n\t\tid: toolUseId,\n\t\tinput: toolInput,\n\t\tname: toolName,\n\t\ttype: 'tool_use' as const\n\t}\n];\n\nconst buildToolResultBlock = (toolUseId: string, result: string) => [\n\t{\n\t\tcontent: result,\n\t\ttool_use_id: toolUseId,\n\t\ttype: 'tool_result' as const\n\t}\n];\n\ntype ToolLoopState = {\n\tcurrentFullResponse: string;\n\tcurrentMessages: AIProviderMessage[];\n\tcurrentToolInput: unknown;\n\tcurrentToolName: string;\n\tcurrentToolUseId: string;\n\tcurrentTurn: number;\n\tcurrentUsage: AIUsage | undefined;\n};\n\ntype ToolLoopResult = {\n\tfullResponse: string;\n\tusage: AIUsage | undefined;\n};\n\nconst handleToolChunkText = (\n\tchunk: AITextChunk,\n\tstate: ToolLoopState,\n\toptions: StreamAIOptions,\n\tsocket: AIWebSocket,\n\tmessageId: string,\n\tconversationId: string\n) => {\n\tconst textContent = extractTextContent(chunk, options.onChunk);\n\tstate.currentFullResponse += textContent;\n\tsendMessage(socket, {\n\t\tcontent: textContent,\n\t\tconversationId,\n\t\tmessageId,\n\t\ttype: 'chunk'\n\t});\n};\n\nconst handleToolChunkToolUse = (\n\tchunk: AIChunk & { type: 'tool_use' },\n\tstate: ToolLoopState\n) => {\n\tstate.currentToolUseId = chunk.id;\n\tstate.currentToolName = chunk.name;\n\tstate.currentToolInput = chunk.input;\n};\n\nconst processToolChunk = (\n\tchunk: AIChunk,\n\tstate: ToolLoopState,\n\toptions: StreamAIOptions,\n\tsocket: AIWebSocket,\n\tmessageId: string,\n\tconversationId: string\n) => {\n\tlet hitAnotherTool = false;\n\n\tswitch (chunk.type) {\n\t\tcase 'text':\n\t\t\thandleToolChunkText(\n\t\t\t\tchunk,\n\t\t\t\tstate,\n\t\t\t\toptions,\n\t\t\t\tsocket,\n\t\t\t\tmessageId,\n\t\t\t\tconversationId\n\t\t\t);\n\t\t\tbreak;\n\n\t\tcase 'tool_use':\n\t\t\thandleToolChunkToolUse(chunk, state);\n\t\t\thitAnotherTool = true;\n\t\t\tbreak;\n\n\t\tcase 'done':\n\t\t\tstate.currentUsage = chunk.usage;\n\t\t\tbreak;\n\t}\n\n\treturn hitAnotherTool;\n};\n\nconst processToolTurn = async (\n\tsocket: AIWebSocket,\n\toptions: StreamAIOptions,\n\tstate: ToolLoopState,\n\tmessageId: string,\n\tconversationId: string,\n\tsignal: AbortSignal\n) => {\n\tawait sendToolRunning(\n\t\tsocket,\n\t\tstate.currentToolName,\n\t\tstate.currentToolInput,\n\t\tmessageId,\n\t\tconversationId\n\t);\n\n\tconst result = await executeTool(\n\t\toptions,\n\t\tstate.currentToolName,\n\t\tstate.currentToolInput\n\t);\n\n\tawait sendToolComplete(\n\t\tsocket,\n\t\tstate.currentToolName,\n\t\tresult,\n\t\tmessageId,\n\t\tconversationId\n\t);\n\n\toptions.onToolUse?.(state.currentToolName, state.currentToolInput, result);\n\n\tstate.currentMessages.push({\n\t\tcontent: buildToolUseBlock(\n\t\t\tstate.currentToolUseId,\n\t\t\tstate.currentToolName,\n\t\t\tstate.currentToolInput\n\t\t),\n\t\trole: 'assistant'\n\t});\n\n\tstate.currentMessages.push({\n\t\tcontent: buildToolResultBlock(state.currentToolUseId, result),\n\t\trole: 'user'\n\t});\n\n\tconst toolDefs = options.tools\n\t\t? buildToolDefinitions(options.tools)\n\t\t: undefined;\n\n\tconst stream = options.provider.stream({\n\t\tmessages: state.currentMessages,\n\t\tmodel: options.model,\n\t\tsignal,\n\t\tsystemPrompt: options.systemPrompt,\n\t\ttools: toolDefs\n\t});\n\n\treturn consumeToolStream(\n\t\tstream,\n\t\tstate,\n\t\toptions,\n\t\tsocket,\n\t\tmessageId,\n\t\tconversationId,\n\t\tsignal\n\t);\n};\n\nconst consumeToolStream = async (\n\tstream: AsyncIterable<AIChunk>,\n\tstate: ToolLoopState,\n\toptions: StreamAIOptions,\n\tsocket: AIWebSocket,\n\tmessageId: string,\n\tconversationId: string,\n\tsignal: AbortSignal\n) => {\n\tfor await (const chunk of stream) {\n\t\tif (signal.aborted) break;\n\n\t\tconst isToolHit = processToolChunk(\n\t\t\tchunk,\n\t\t\tstate,\n\t\t\toptions,\n\t\t\tsocket,\n\t\t\tmessageId,\n\t\t\tconversationId\n\t\t);\n\n\t\tif (isToolHit) return true;\n\t}\n\n\treturn false;\n};\n\nconst shouldContinueToolLoop = (\n\tstate: ToolLoopState,\n\tmaxTurns: number,\n\tsignal: AbortSignal\n) => state.currentTurn < maxTurns && !signal.aborted;\n\nconst executeToolLoop = async (\n\tsocket: AIWebSocket,\n\toptions: StreamAIOptions,\n\tmessages: AIProviderMessage[],\n\ttoolUseId: string,\n\ttoolName: string,\n\ttoolInput: unknown,\n\tmessageId: string,\n\tconversationId: string,\n\tsignal: AbortSignal,\n\tfullResponse: string,\n\tturn: number\n): Promise<ToolLoopResult> => {\n\tconst maxTurns = options.maxTurns ?? DEFAULT_MAX_TURNS;\n\n\tconst state: ToolLoopState = {\n\t\tcurrentFullResponse: fullResponse,\n\t\tcurrentMessages: [...messages],\n\t\tcurrentToolInput: toolInput,\n\t\tcurrentToolName: toolName,\n\t\tcurrentToolUseId: toolUseId,\n\t\tcurrentTurn: turn,\n\t\tcurrentUsage: undefined\n\t};\n\n\twhile (shouldContinueToolLoop(state, maxTurns, signal)) {\n\t\t// eslint-disable-next-line no-await-in-loop\n\t\tconst hitAnotherTool = await processToolTurn(\n\t\t\tsocket,\n\t\t\toptions,\n\t\t\tstate,\n\t\t\tmessageId,\n\t\t\tconversationId,\n\t\t\tsignal\n\t\t);\n\n\t\tif (!hitAnotherTool) {\n\t\t\treturn {\n\t\t\t\tfullResponse: state.currentFullResponse,\n\t\t\t\tusage: state.currentUsage\n\t\t\t};\n\t\t}\n\n\t\tstate.currentTurn++;\n\t}\n\n\treturn {\n\t\tfullResponse: state.currentFullResponse,\n\t\tusage: state.currentUsage\n\t};\n};\n\nconst sendComplete = async (\n\tsocket: AIWebSocket,\n\tmessageId: string,\n\tconversationId: string,\n\tusage?: AIUsage\n) =>\n\tsendMessage(socket, {\n\t\tconversationId,\n\t\tmessageId,\n\t\ttype: 'complete',\n\t\tusage\n\t});\n\nconst sendError = async (\n\tsocket: AIWebSocket,\n\terr: unknown,\n\tmessageId: string,\n\tconversationId: string\n) =>\n\tsendMessage(socket, {\n\t\tconversationId,\n\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\tmessageId,\n\t\ttype: 'error'\n\t});\n\nconst handleTextChunk = async (\n\tchunk: AITextChunk,\n\toptions: StreamAIOptions,\n\tsocket: AIWebSocket,\n\tmessageId: string,\n\tconversationId: string\n) => {\n\tconst textContent = extractTextContent(chunk, options.onChunk);\n\n\tawait sendMessage(socket, {\n\t\tcontent: textContent,\n\t\tconversationId,\n\t\tmessageId,\n\t\ttype: 'chunk'\n\t});\n\n\treturn textContent;\n};\n\nconst handleToolUseChunk = async (\n\tsocket: AIWebSocket,\n\toptions: StreamAIOptions,\n\tmessages: AIProviderMessage[],\n\tchunkId: string,\n\tchunkName: string,\n\tchunkInput: unknown,\n\tmessageId: string,\n\tconversationId: string,\n\tsignal: AbortSignal,\n\tfullResponse: string\n) => {\n\tconst toolResult = await executeToolLoop(\n\t\tsocket,\n\t\toptions,\n\t\tmessages,\n\t\tchunkId,\n\t\tchunkName,\n\t\tchunkInput,\n\t\tmessageId,\n\t\tconversationId,\n\t\tsignal,\n\t\tfullResponse,\n\t\tINITIAL_TURN\n\t);\n\n\tawait sendComplete(socket, messageId, conversationId, toolResult.usage);\n\toptions.onComplete?.(toolResult.fullResponse, toolResult.usage);\n\n\treturn toolResult;\n};\n\nconst processStreamTextChunk = async (\n\tchunk: AITextChunk,\n\toptions: StreamAIOptions,\n\tsocket: AIWebSocket,\n\tmessageId: string,\n\tconversationId: string\n) => {\n\tconst textContent = await handleTextChunk(\n\t\tchunk,\n\t\toptions,\n\t\tsocket,\n\t\tmessageId,\n\t\tconversationId\n\t);\n\n\treturn textContent;\n};\n\nconst processStreamToolUseChunk = async (\n\tchunk: AIChunk & { type: 'tool_use' },\n\tsocket: AIWebSocket,\n\toptions: StreamAIOptions,\n\tmessages: AIProviderMessage[],\n\tmessageId: string,\n\tconversationId: string,\n\tsignal: AbortSignal,\n\tfullResponse: string\n) => {\n\tawait handleToolUseChunk(\n\t\tsocket,\n\t\toptions,\n\t\tmessages,\n\t\tchunk.id,\n\t\tchunk.name,\n\t\tchunk.input,\n\t\tmessageId,\n\t\tconversationId,\n\t\tsignal,\n\t\tfullResponse\n\t);\n};\n\nconst processStream = async (\n\tsocket: AIWebSocket,\n\toptions: StreamAIOptions,\n\tmessages: AIProviderMessage[],\n\tmessageId: string,\n\tconversationId: string,\n\tsignal: AbortSignal\n) => {\n\tconst toolDefs = options.tools\n\t\t? buildToolDefinitions(options.tools)\n\t\t: undefined;\n\n\tconst stream = options.provider.stream({\n\t\tmessages,\n\t\tmodel: options.model,\n\t\tsignal,\n\t\tsystemPrompt: options.systemPrompt,\n\t\ttools: toolDefs\n\t});\n\n\tconst result = await consumeStream(\n\t\tstream,\n\t\toptions,\n\t\tsocket,\n\t\tmessages,\n\t\tmessageId,\n\t\tconversationId,\n\t\tsignal\n\t);\n\n\tif (!result.earlyReturn) {\n\t\tawait sendComplete(socket, messageId, conversationId, result.usage);\n\t\toptions.onComplete?.(result.fullResponse, result.usage);\n\t}\n};\n\ntype ConsumeStreamResult = {\n\tearlyReturn: boolean;\n\tfullResponse: string;\n\tusage: AIUsage | undefined;\n};\n\nconst consumeStreamChunk = async (\n\tchunk: AIChunk,\n\toptions: StreamAIOptions,\n\tsocket: AIWebSocket,\n\tmessages: AIProviderMessage[],\n\tmessageId: string,\n\tconversationId: string,\n\tsignal: AbortSignal,\n\tfullResponse: string\n) => {\n\tswitch (chunk.type) {\n\t\tcase 'text':\n\t\t\treturn processStreamTextChunk(\n\t\t\t\tchunk,\n\t\t\t\toptions,\n\t\t\t\tsocket,\n\t\t\t\tmessageId,\n\t\t\t\tconversationId\n\t\t\t);\n\n\t\tcase 'tool_use':\n\t\t\tawait processStreamToolUseChunk(\n\t\t\t\tchunk,\n\t\t\t\tsocket,\n\t\t\t\toptions,\n\t\t\t\tmessages,\n\t\t\t\tmessageId,\n\t\t\t\tconversationId,\n\t\t\t\tsignal,\n\t\t\t\tfullResponse\n\t\t\t);\n\n\t\t\treturn { earlyReturn: true, fullResponse, usage: undefined };\n\n\t\tcase 'done':\n\t\t\treturn { earlyReturn: false, fullResponse, usage: chunk.usage };\n\t}\n\n\treturn '';\n};\n\ntype ConsumeStreamState = {\n\tfullResponse: string;\n\tusage: AIUsage | undefined;\n};\n\nconst applyStreamChunkResult = (\n\tresult: ConsumeStreamResult | string,\n\tstate: ConsumeStreamState\n) => {\n\tif (typeof result === 'string') {\n\t\tstate.fullResponse += result;\n\n\t\treturn undefined;\n\t}\n\n\tif (result.earlyReturn) return result;\n\n\tstate.usage = result.usage;\n\n\treturn undefined;\n};\n\nconst consumeStream = async (\n\tstream: AsyncIterable<AIChunk>,\n\toptions: StreamAIOptions,\n\tsocket: AIWebSocket,\n\tmessages: AIProviderMessage[],\n\tmessageId: string,\n\tconversationId: string,\n\tsignal: AbortSignal\n) => {\n\tconst state: ConsumeStreamState = { fullResponse: '', usage: undefined };\n\n\tfor await (const chunk of stream) {\n\t\tif (signal.aborted) break;\n\n\t\tconst result = await consumeStreamChunk(\n\t\t\tchunk,\n\t\t\toptions,\n\t\t\tsocket,\n\t\t\tmessages,\n\t\t\tmessageId,\n\t\t\tconversationId,\n\t\t\tsignal,\n\t\t\tstate.fullResponse\n\t\t);\n\t\tconst earlyExit = applyStreamChunkResult(result, state);\n\n\t\tif (earlyExit) return earlyExit;\n\t}\n\n\tconst finalResult: ConsumeStreamResult = {\n\t\tearlyReturn: false,\n\t\tfullResponse: state.fullResponse,\n\t\tusage: state.usage\n\t};\n\n\treturn finalResult;\n};\n\nexport const streamAI = async (\n\tsocket: AIWebSocket,\n\tconversationId: string,\n\tmessageId: string,\n\toptions: StreamAIOptions\n) => {\n\tconst signal = options.signal ?? new AbortController().signal;\n\n\tconst messages: AIProviderMessage[] = options.messages\n\t\t? [...options.messages]\n\t\t: [];\n\n\ttry {\n\t\tawait processStream(\n\t\t\tsocket,\n\t\t\toptions,\n\t\t\tmessages,\n\t\t\tmessageId,\n\t\t\tconversationId,\n\t\t\tsignal\n\t\t);\n\t} catch (err) {\n\t\tawait handleStreamError(socket, err, messageId, conversationId, signal);\n\t}\n};\n\nconst handleStreamError = async (\n\tsocket: AIWebSocket,\n\terr: unknown,\n\tmessageId: string,\n\tconversationId: string,\n\tsignal: AbortSignal\n) => {\n\tif (signal.aborted) {\n\t\tawait sendComplete(socket, messageId, conversationId);\n\n\t\treturn;\n\t}\n\n\tawait sendError(socket, err, messageId, conversationId);\n};\n",
|
|
8
|
+
"import type {\n\tAIConversation,\n\tAIMessage,\n\tAIProviderMessage\n} from '../../types/ai';\nimport { generateId } from './protocol';\n\nconst NOT_FOUND = -1;\n\nexport const createConversationManager = () => {\n\tconst conversations = new Map<string, AIConversation>();\n\n\tconst getOrCreate = (conversationId?: string) => {\n\t\tconst id = conversationId ?? generateId();\n\t\tlet conversation = conversations.get(id);\n\n\t\tif (!conversation) {\n\t\t\tconversation = { id, messages: [] };\n\t\t\tconversations.set(id, conversation);\n\t\t}\n\n\t\treturn conversation;\n\t};\n\n\tconst appendMessage = (conversationId: string, message: AIMessage) => {\n\t\tconst conversation = getOrCreate(conversationId);\n\t\tconversation.messages.push(message);\n\t};\n\n\tconst branch = (fromMessageId: string, sourceConversationId: string) => {\n\t\tconst source = conversations.get(sourceConversationId);\n\n\t\tif (!source) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst cutoffIndex = source.messages.findIndex(\n\t\t\t(msg) => msg.id === fromMessageId\n\t\t);\n\n\t\tif (cutoffIndex === NOT_FOUND) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst newId = generateId();\n\t\tconst branchedMessages = source.messages\n\t\t\t.slice(0, cutoffIndex + 1)\n\t\t\t.map((msg) => ({ ...msg, conversationId: newId }));\n\n\t\tconst newConversation: AIConversation = {\n\t\t\tid: newId,\n\t\t\tmessages: branchedMessages\n\t\t};\n\t\tconversations.set(newId, newConversation);\n\n\t\treturn newId;\n\t};\n\n\tconst emptyHistory: AIProviderMessage[] = [];\n\n\tconst getHistory = (conversationId: string) => {\n\t\tconst conversation = conversations.get(conversationId);\n\n\t\tif (!conversation) {\n\t\t\treturn emptyHistory;\n\t\t}\n\n\t\tconst history: AIProviderMessage[] = conversation.messages.map(\n\t\t\t(msg) => ({\n\t\t\t\tcontent: msg.content,\n\t\t\t\trole: msg.role\n\t\t\t})\n\t\t);\n\n\t\treturn history;\n\t};\n\n\tconst getAbortController = (conversationId: string) => {\n\t\tconst conversation = getOrCreate(conversationId);\n\t\tconst controller = new AbortController();\n\t\tconversation.activeStreamAbort = controller;\n\n\t\treturn controller;\n\t};\n\n\tconst abort = (conversationId: string) => {\n\t\tconst conversation = conversations.get(conversationId);\n\n\t\tif (conversation?.activeStreamAbort) {\n\t\t\tconversation.activeStreamAbort.abort();\n\t\t\tconversation.activeStreamAbort = undefined;\n\t\t}\n\t};\n\n\tconst get = (conversationId: string) => conversations.get(conversationId);\n\n\tconst remove = (conversationId: string) =>\n\t\tconversations.delete(conversationId);\n\n\treturn {\n\t\tabort,\n\t\tappendMessage,\n\t\tbranch,\n\t\tget,\n\t\tgetAbortController,\n\t\tgetHistory,\n\t\tgetOrCreate,\n\t\tremove\n\t};\n};\n"
|
|
9
|
+
],
|
|
10
|
+
"mappings": "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",
|
|
11
|
+
"debugId": "522D65A44B1E30AF64756E2164756E21",
|
|
12
|
+
"names": []
|
|
13
|
+
}
|