@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
|
@@ -0,0 +1,590 @@
|
|
|
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/client/actions.ts
|
|
138
|
+
var serverMessageToAction = (msg) => {
|
|
139
|
+
switch (msg.type) {
|
|
140
|
+
case "chunk":
|
|
141
|
+
return {
|
|
142
|
+
content: msg.content,
|
|
143
|
+
conversationId: msg.conversationId,
|
|
144
|
+
messageId: msg.messageId,
|
|
145
|
+
type: "chunk"
|
|
146
|
+
};
|
|
147
|
+
case "tool_status":
|
|
148
|
+
return {
|
|
149
|
+
conversationId: msg.conversationId,
|
|
150
|
+
input: msg.input,
|
|
151
|
+
messageId: msg.messageId,
|
|
152
|
+
name: msg.name,
|
|
153
|
+
result: msg.result,
|
|
154
|
+
status: msg.status,
|
|
155
|
+
type: "tool_status"
|
|
156
|
+
};
|
|
157
|
+
case "complete":
|
|
158
|
+
return {
|
|
159
|
+
conversationId: msg.conversationId,
|
|
160
|
+
messageId: msg.messageId,
|
|
161
|
+
type: "complete",
|
|
162
|
+
usage: msg.usage
|
|
163
|
+
};
|
|
164
|
+
case "error":
|
|
165
|
+
return { message: msg.message, type: "error" };
|
|
166
|
+
default:
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// src/ai/client/connection.ts
|
|
172
|
+
var WS_OPEN = 1;
|
|
173
|
+
var WS_NORMAL_CLOSURE = 1000;
|
|
174
|
+
var WS_CLOSED = 3;
|
|
175
|
+
var DEFAULT_PING_INTERVAL = 30000;
|
|
176
|
+
var RECONNECT_INITIAL_DELAY = 500;
|
|
177
|
+
var RECONNECT_POLL_INTERVAL = 300;
|
|
178
|
+
var DEFAULT_MAX_RECONNECT_ATTEMPTS = 60;
|
|
179
|
+
var noop = () => {};
|
|
180
|
+
var noopUnsubscribe = () => noop;
|
|
181
|
+
var NOOP_CONNECTION = {
|
|
182
|
+
close: noop,
|
|
183
|
+
send: noop,
|
|
184
|
+
subscribe: noopUnsubscribe,
|
|
185
|
+
getReadyState: () => WS_CLOSED
|
|
186
|
+
};
|
|
187
|
+
var buildWsUrl = (path) => {
|
|
188
|
+
const { hostname, port, protocol } = window.location;
|
|
189
|
+
const wsProtocol = protocol === "https:" ? "wss:" : "ws:";
|
|
190
|
+
const portSuffix = port ? `:${port}` : "";
|
|
191
|
+
return `${wsProtocol}//${hostname}${portSuffix}${path}`;
|
|
192
|
+
};
|
|
193
|
+
var parseServerMessage = (event) => {
|
|
194
|
+
let data;
|
|
195
|
+
try {
|
|
196
|
+
data = JSON.parse(String(event.data));
|
|
197
|
+
} catch {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
if (data && typeof data === "object" && "type" in data && data.type === "pong") {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
if (!isValidAIServerMessage(data)) {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
return data;
|
|
207
|
+
};
|
|
208
|
+
var createAIConnection = (path, options = {}) => {
|
|
209
|
+
if (typeof window === "undefined") {
|
|
210
|
+
return NOOP_CONNECTION;
|
|
211
|
+
}
|
|
212
|
+
const shouldReconnect = options.reconnect !== false;
|
|
213
|
+
const pingInterval = options.pingInterval ?? DEFAULT_PING_INTERVAL;
|
|
214
|
+
const maxReconnectAttempts = options.maxReconnectAttempts ?? DEFAULT_MAX_RECONNECT_ATTEMPTS;
|
|
215
|
+
const listeners = new Set;
|
|
216
|
+
const connState = {
|
|
217
|
+
isConnected: false,
|
|
218
|
+
pingInterval: null,
|
|
219
|
+
reconnectAttempts: 0,
|
|
220
|
+
reconnectTimeout: null,
|
|
221
|
+
ws: null
|
|
222
|
+
};
|
|
223
|
+
const clearTimers = () => {
|
|
224
|
+
if (connState.pingInterval) {
|
|
225
|
+
clearInterval(connState.pingInterval);
|
|
226
|
+
connState.pingInterval = null;
|
|
227
|
+
}
|
|
228
|
+
if (connState.reconnectTimeout) {
|
|
229
|
+
clearTimeout(connState.reconnectTimeout);
|
|
230
|
+
connState.reconnectTimeout = null;
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
const scheduleReconnect = () => {
|
|
234
|
+
connState.reconnectAttempts++;
|
|
235
|
+
const delay = connState.reconnectAttempts === 1 ? RECONNECT_INITIAL_DELAY : RECONNECT_POLL_INTERVAL;
|
|
236
|
+
connState.reconnectTimeout = setTimeout(() => {
|
|
237
|
+
if (connState.reconnectAttempts > maxReconnectAttempts) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
connect();
|
|
241
|
+
}, delay);
|
|
242
|
+
};
|
|
243
|
+
const connect = () => {
|
|
244
|
+
const url = buildWsUrl(path);
|
|
245
|
+
const wsInstance = new WebSocket(url, options.protocols);
|
|
246
|
+
wsInstance.onopen = () => {
|
|
247
|
+
connState.isConnected = true;
|
|
248
|
+
connState.reconnectAttempts = 0;
|
|
249
|
+
connState.pingInterval = setInterval(() => {
|
|
250
|
+
if (wsInstance.readyState === WS_OPEN && connState.isConnected) {
|
|
251
|
+
wsInstance.send(JSON.stringify({ type: "ping" }));
|
|
252
|
+
}
|
|
253
|
+
}, pingInterval);
|
|
254
|
+
};
|
|
255
|
+
wsInstance.onmessage = (event) => {
|
|
256
|
+
const message = parseServerMessage(event);
|
|
257
|
+
if (!message) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
listeners.forEach((listener) => listener(message));
|
|
261
|
+
};
|
|
262
|
+
wsInstance.onclose = (event) => {
|
|
263
|
+
connState.isConnected = false;
|
|
264
|
+
clearTimers();
|
|
265
|
+
const shouldAttemptReconnect = shouldReconnect && event.code !== WS_NORMAL_CLOSURE && connState.reconnectAttempts < maxReconnectAttempts;
|
|
266
|
+
if (shouldAttemptReconnect) {
|
|
267
|
+
scheduleReconnect();
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
wsInstance.onerror = () => {};
|
|
271
|
+
connState.ws = wsInstance;
|
|
272
|
+
};
|
|
273
|
+
const send = (msg) => {
|
|
274
|
+
if (connState.ws?.readyState === WS_OPEN) {
|
|
275
|
+
connState.ws.send(JSON.stringify(msg));
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
const subscribe = (callback) => {
|
|
279
|
+
listeners.add(callback);
|
|
280
|
+
return () => {
|
|
281
|
+
listeners.delete(callback);
|
|
282
|
+
};
|
|
283
|
+
};
|
|
284
|
+
const close = () => {
|
|
285
|
+
clearTimers();
|
|
286
|
+
if (connState.ws) {
|
|
287
|
+
connState.ws.close(WS_NORMAL_CLOSURE);
|
|
288
|
+
connState.ws = null;
|
|
289
|
+
}
|
|
290
|
+
connState.isConnected = false;
|
|
291
|
+
listeners.clear();
|
|
292
|
+
};
|
|
293
|
+
const getReadyState = () => connState.ws?.readyState ?? WS_CLOSED;
|
|
294
|
+
connect();
|
|
295
|
+
return { close, getReadyState, send, subscribe };
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
// src/ai/client/messageStore.ts
|
|
299
|
+
var EMPTY_STATE = {
|
|
300
|
+
activeConversationId: null,
|
|
301
|
+
conversations: new Map,
|
|
302
|
+
error: null,
|
|
303
|
+
isStreaming: false
|
|
304
|
+
};
|
|
305
|
+
var initialActiveConversationId = null;
|
|
306
|
+
var initialError = null;
|
|
307
|
+
var freshState = () => ({
|
|
308
|
+
activeConversationId: initialActiveConversationId,
|
|
309
|
+
conversations: new Map,
|
|
310
|
+
error: initialError,
|
|
311
|
+
isStreaming: false
|
|
312
|
+
});
|
|
313
|
+
var findAssistantMessage = (conversation, messageId) => conversation.messages.find((msg) => msg.id === messageId && msg.role === "assistant");
|
|
314
|
+
var getOrCreate = (state, conversationId) => {
|
|
315
|
+
let conversation = state.conversations.get(conversationId);
|
|
316
|
+
if (!conversation) {
|
|
317
|
+
conversation = { id: conversationId, messages: [] };
|
|
318
|
+
state.conversations.set(conversationId, conversation);
|
|
319
|
+
}
|
|
320
|
+
return conversation;
|
|
321
|
+
};
|
|
322
|
+
var handleSend = (state, action) => {
|
|
323
|
+
const conversation = getOrCreate(state, action.conversationId);
|
|
324
|
+
const message = {
|
|
325
|
+
content: action.content,
|
|
326
|
+
conversationId: action.conversationId,
|
|
327
|
+
id: action.messageId,
|
|
328
|
+
role: "user",
|
|
329
|
+
timestamp: Date.now()
|
|
330
|
+
};
|
|
331
|
+
conversation.messages = [...conversation.messages, message];
|
|
332
|
+
state.activeConversationId = action.conversationId;
|
|
333
|
+
state.error = null;
|
|
334
|
+
state.isStreaming = true;
|
|
335
|
+
};
|
|
336
|
+
var handleChunk = (state, action) => {
|
|
337
|
+
const conversation = getOrCreate(state, action.conversationId);
|
|
338
|
+
const existing = findAssistantMessage(conversation, action.messageId);
|
|
339
|
+
if (existing) {
|
|
340
|
+
existing.content += action.content;
|
|
341
|
+
conversation.messages = [...conversation.messages];
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
const message = {
|
|
345
|
+
content: action.content,
|
|
346
|
+
conversationId: action.conversationId,
|
|
347
|
+
id: action.messageId,
|
|
348
|
+
isStreaming: true,
|
|
349
|
+
role: "assistant",
|
|
350
|
+
timestamp: Date.now()
|
|
351
|
+
};
|
|
352
|
+
conversation.messages = [...conversation.messages, message];
|
|
353
|
+
};
|
|
354
|
+
var upsertToolCall = (message, toolCall) => {
|
|
355
|
+
if (!message.toolCalls) {
|
|
356
|
+
message.toolCalls = [toolCall];
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
const existingIdx = message.toolCalls.findIndex((existing) => existing.name === toolCall.name);
|
|
360
|
+
if (existingIdx >= 0) {
|
|
361
|
+
message.toolCalls[existingIdx] = toolCall;
|
|
362
|
+
} else {
|
|
363
|
+
message.toolCalls = [...message.toolCalls, toolCall];
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
var handleToolStatus = (state, action) => {
|
|
367
|
+
const conversation = getOrCreate(state, action.conversationId);
|
|
368
|
+
const message = findAssistantMessage(conversation, action.messageId);
|
|
369
|
+
if (!message) {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
const toolCall = {
|
|
373
|
+
id: action.messageId,
|
|
374
|
+
input: action.input,
|
|
375
|
+
name: action.name,
|
|
376
|
+
result: action.status === "complete" ? action.result ?? "" : undefined
|
|
377
|
+
};
|
|
378
|
+
upsertToolCall(message, toolCall);
|
|
379
|
+
conversation.messages = [...conversation.messages];
|
|
380
|
+
};
|
|
381
|
+
var markMessageComplete = (conversation, messageId) => {
|
|
382
|
+
const message = findAssistantMessage(conversation, messageId);
|
|
383
|
+
if (message) {
|
|
384
|
+
message.isStreaming = false;
|
|
385
|
+
}
|
|
386
|
+
conversation.messages = [...conversation.messages];
|
|
387
|
+
};
|
|
388
|
+
var handleComplete = (state, action) => {
|
|
389
|
+
const conversation = state.conversations.get(action.conversationId);
|
|
390
|
+
if (conversation) {
|
|
391
|
+
markMessageComplete(conversation, action.messageId);
|
|
392
|
+
}
|
|
393
|
+
state.isStreaming = false;
|
|
394
|
+
};
|
|
395
|
+
var markConversationStreamsComplete = (conversation) => {
|
|
396
|
+
const streamingMessages = conversation.messages.filter((msg) => msg.isStreaming);
|
|
397
|
+
if (streamingMessages.length === 0) {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
for (const msg of streamingMessages) {
|
|
401
|
+
msg.isStreaming = false;
|
|
402
|
+
}
|
|
403
|
+
conversation.messages = [...conversation.messages];
|
|
404
|
+
};
|
|
405
|
+
var markAllStreamsComplete = (state) => {
|
|
406
|
+
for (const [, conversation] of state.conversations) {
|
|
407
|
+
markConversationStreamsComplete(conversation);
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
var handleBranch = (state, action) => {
|
|
411
|
+
const source = state.conversations.get(action.oldConversationId);
|
|
412
|
+
if (!source) {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
const cutoffIndex = source.messages.findIndex((msg) => msg.id === action.fromMessageId);
|
|
416
|
+
if (cutoffIndex < 0) {
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
const branchedMessages = source.messages.slice(0, cutoffIndex + 1).map((msg) => ({ ...msg, conversationId: action.newConversationId }));
|
|
420
|
+
const newConversation = {
|
|
421
|
+
id: action.newConversationId,
|
|
422
|
+
messages: branchedMessages
|
|
423
|
+
};
|
|
424
|
+
state.conversations.set(action.newConversationId, newConversation);
|
|
425
|
+
state.activeConversationId = action.newConversationId;
|
|
426
|
+
};
|
|
427
|
+
var dispatch = (state, subscribers, action) => {
|
|
428
|
+
switch (action.type) {
|
|
429
|
+
case "send":
|
|
430
|
+
handleSend(state, action);
|
|
431
|
+
break;
|
|
432
|
+
case "chunk":
|
|
433
|
+
handleChunk(state, action);
|
|
434
|
+
break;
|
|
435
|
+
case "tool_status":
|
|
436
|
+
handleToolStatus(state, action);
|
|
437
|
+
break;
|
|
438
|
+
case "complete":
|
|
439
|
+
handleComplete(state, action);
|
|
440
|
+
break;
|
|
441
|
+
case "error":
|
|
442
|
+
state.error = action.message;
|
|
443
|
+
state.isStreaming = false;
|
|
444
|
+
break;
|
|
445
|
+
case "cancel":
|
|
446
|
+
state.isStreaming = false;
|
|
447
|
+
markAllStreamsComplete(state);
|
|
448
|
+
break;
|
|
449
|
+
case "branch":
|
|
450
|
+
handleBranch(state, action);
|
|
451
|
+
break;
|
|
452
|
+
case "set_conversation":
|
|
453
|
+
state.activeConversationId = action.conversationId;
|
|
454
|
+
break;
|
|
455
|
+
}
|
|
456
|
+
Object.assign(state, { conversations: new Map(state.conversations) });
|
|
457
|
+
subscribers.forEach((callback) => callback());
|
|
458
|
+
};
|
|
459
|
+
var createAIMessageStore = () => {
|
|
460
|
+
const state = freshState();
|
|
461
|
+
const subscribers = new Set;
|
|
462
|
+
return {
|
|
463
|
+
dispatch: (action) => dispatch(state, subscribers, action),
|
|
464
|
+
getServerSnapshot: () => EMPTY_STATE,
|
|
465
|
+
getSnapshot: () => state,
|
|
466
|
+
subscribe: (callback) => {
|
|
467
|
+
subscribers.add(callback);
|
|
468
|
+
return () => {
|
|
469
|
+
subscribers.delete(callback);
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
// src/ai/protocol.ts
|
|
476
|
+
var generateId = () => crypto.randomUUID();
|
|
477
|
+
var parseAIMessage = (raw) => {
|
|
478
|
+
if (raw === null || raw === undefined) {
|
|
479
|
+
return null;
|
|
480
|
+
}
|
|
481
|
+
let text;
|
|
482
|
+
if (typeof raw === "string") {
|
|
483
|
+
text = raw;
|
|
484
|
+
} else if (raw instanceof ArrayBuffer) {
|
|
485
|
+
text = new TextDecoder().decode(raw);
|
|
486
|
+
} else if (ArrayBuffer.isView(raw)) {
|
|
487
|
+
text = new TextDecoder().decode(raw);
|
|
488
|
+
} else if (typeof raw === "object") {
|
|
489
|
+
if (isValidAIClientMessage(raw)) {
|
|
490
|
+
return raw;
|
|
491
|
+
}
|
|
492
|
+
return null;
|
|
493
|
+
} else {
|
|
494
|
+
return null;
|
|
495
|
+
}
|
|
496
|
+
try {
|
|
497
|
+
const parsed = JSON.parse(text);
|
|
498
|
+
if (isValidAIClientMessage(parsed)) {
|
|
499
|
+
return parsed;
|
|
500
|
+
}
|
|
501
|
+
return null;
|
|
502
|
+
} catch {
|
|
503
|
+
return null;
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
var serializeAIMessage = (msg) => JSON.stringify(msg);
|
|
507
|
+
|
|
508
|
+
// src/svelte/ai/createAIStream.ts
|
|
509
|
+
var createAIStream = (path, conversationId) => {
|
|
510
|
+
const connection = createAIConnection(path);
|
|
511
|
+
const store = createAIMessageStore();
|
|
512
|
+
let currentError = null;
|
|
513
|
+
let currentIsStreaming = false;
|
|
514
|
+
let currentMessages = [];
|
|
515
|
+
let activeConversationId = conversationId ?? null;
|
|
516
|
+
const syncState = () => {
|
|
517
|
+
const snapshot = store.getSnapshot();
|
|
518
|
+
const convId = activeConversationId ?? snapshot.activeConversationId;
|
|
519
|
+
const conversation = convId ? snapshot.conversations.get(convId) : undefined;
|
|
520
|
+
activeConversationId = convId ?? snapshot.activeConversationId;
|
|
521
|
+
currentError = snapshot.error;
|
|
522
|
+
currentIsStreaming = snapshot.isStreaming;
|
|
523
|
+
currentMessages = conversation?.messages ?? [];
|
|
524
|
+
};
|
|
525
|
+
store.subscribe(syncState);
|
|
526
|
+
connection.subscribe((msg) => {
|
|
527
|
+
const action = serverMessageToAction(msg);
|
|
528
|
+
if (action) {
|
|
529
|
+
store.dispatch(action);
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
const branch = (messageId, content) => {
|
|
533
|
+
if (activeConversationId) {
|
|
534
|
+
connection.send({
|
|
535
|
+
content,
|
|
536
|
+
conversationId: activeConversationId,
|
|
537
|
+
messageId,
|
|
538
|
+
type: "branch"
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
const cancel = () => {
|
|
543
|
+
if (activeConversationId) {
|
|
544
|
+
store.dispatch({ type: "cancel" });
|
|
545
|
+
connection.send({
|
|
546
|
+
conversationId: activeConversationId,
|
|
547
|
+
type: "cancel"
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
const destroy = () => {
|
|
552
|
+
connection.close();
|
|
553
|
+
};
|
|
554
|
+
const send = (content) => {
|
|
555
|
+
const convId = activeConversationId ?? generateId();
|
|
556
|
+
const msgId = generateId();
|
|
557
|
+
store.dispatch({
|
|
558
|
+
content,
|
|
559
|
+
conversationId: convId,
|
|
560
|
+
messageId: msgId,
|
|
561
|
+
type: "send"
|
|
562
|
+
});
|
|
563
|
+
connection.send({
|
|
564
|
+
content,
|
|
565
|
+
conversationId: convId,
|
|
566
|
+
type: "message"
|
|
567
|
+
});
|
|
568
|
+
};
|
|
569
|
+
return {
|
|
570
|
+
branch,
|
|
571
|
+
cancel,
|
|
572
|
+
destroy,
|
|
573
|
+
send,
|
|
574
|
+
get error() {
|
|
575
|
+
return currentError;
|
|
576
|
+
},
|
|
577
|
+
get isStreaming() {
|
|
578
|
+
return currentIsStreaming;
|
|
579
|
+
},
|
|
580
|
+
get messages() {
|
|
581
|
+
return currentMessages;
|
|
582
|
+
}
|
|
583
|
+
};
|
|
584
|
+
};
|
|
585
|
+
export {
|
|
586
|
+
createAIStream
|
|
587
|
+
};
|
|
588
|
+
|
|
589
|
+
//# debugId=316F5CA69826AEA964756E2164756E21
|
|
590
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../types/typeGuards.ts", "../src/ai/client/actions.ts", "../src/ai/client/connection.ts", "../src/ai/client/messageStore.ts", "../src/ai/protocol.ts", "../src/svelte/ai/createAIStream.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';\n\nexport const serverMessageToAction = (msg: AIServerMessage) => {\n\tswitch (msg.type) {\n\t\tcase 'chunk':\n\t\t\treturn {\n\t\t\t\tcontent: msg.content,\n\t\t\t\tconversationId: msg.conversationId,\n\t\t\t\tmessageId: msg.messageId,\n\t\t\t\ttype: 'chunk' as const\n\t\t\t};\n\t\tcase 'tool_status':\n\t\t\treturn {\n\t\t\t\tconversationId: msg.conversationId,\n\t\t\t\tinput: msg.input,\n\t\t\t\tmessageId: msg.messageId,\n\t\t\t\tname: msg.name,\n\t\t\t\tresult: msg.result,\n\t\t\t\tstatus: msg.status,\n\t\t\t\ttype: 'tool_status' as const\n\t\t\t};\n\t\tcase 'complete':\n\t\t\treturn {\n\t\t\t\tconversationId: msg.conversationId,\n\t\t\t\tmessageId: msg.messageId,\n\t\t\t\ttype: 'complete' as const,\n\t\t\t\tusage: msg.usage\n\t\t\t};\n\t\tcase 'error':\n\t\t\treturn { message: msg.message, type: 'error' as const };\n\t\tdefault:\n\t\t\treturn null;\n\t}\n};\n",
|
|
7
|
+
"import type {\n\tAIClientMessage,\n\tAIConnectionOptions,\n\tAIServerMessage\n} from '../../../types/ai';\nimport { isValidAIServerMessage } from '../../../types/typeGuards';\n\nconst WS_OPEN = 1;\nconst WS_NORMAL_CLOSURE = 1000;\nconst WS_CLOSED = 3;\nconst DEFAULT_PING_INTERVAL = 30_000;\nconst RECONNECT_INITIAL_DELAY = 500;\nconst RECONNECT_POLL_INTERVAL = 300;\nconst DEFAULT_MAX_RECONNECT_ATTEMPTS = 60;\n\ntype AIConnectionState = {\n\tisConnected: boolean;\n\tpingInterval: ReturnType<typeof setInterval> | null;\n\treconnectAttempts: number;\n\treconnectTimeout: ReturnType<typeof setTimeout> | null;\n\tws: WebSocket | null;\n};\n\ntype AIConnectionHandle = {\n\tclose: () => void;\n\tgetReadyState: () => number;\n\tsend: (msg: AIClientMessage) => void;\n\tsubscribe: (callback: (msg: AIServerMessage) => void) => () => void;\n};\n\n// eslint-disable-next-line no-empty-function\nconst noop = () => {};\nconst noopUnsubscribe = () => noop;\n\nconst NOOP_CONNECTION: AIConnectionHandle = {\n\tclose: noop,\n\tsend: noop,\n\tsubscribe: noopUnsubscribe,\n\tgetReadyState: () => WS_CLOSED\n};\n\nconst buildWsUrl = (path: string) => {\n\tconst { hostname, port, protocol } = window.location;\n\tconst wsProtocol = protocol === 'https:' ? 'wss:' : 'ws:';\n\tconst portSuffix = port ? `:${port}` : '';\n\n\treturn `${wsProtocol}//${hostname}${portSuffix}${path}`;\n};\n\nconst parseServerMessage = (event: MessageEvent) => {\n\tlet data: unknown;\n\n\ttry {\n\t\tdata = JSON.parse(String(event.data));\n\t} catch {\n\t\treturn null;\n\t}\n\n\tif (\n\t\tdata &&\n\t\ttypeof data === 'object' &&\n\t\t'type' in data &&\n\t\tdata.type === 'pong'\n\t) {\n\t\treturn null;\n\t}\n\n\tif (!isValidAIServerMessage(data)) {\n\t\treturn null;\n\t}\n\n\treturn data;\n};\n\nexport const createAIConnection = (\n\tpath: string,\n\toptions: AIConnectionOptions = {}\n) => {\n\tif (typeof window === 'undefined') {\n\t\treturn NOOP_CONNECTION;\n\t}\n\n\tconst shouldReconnect = options.reconnect !== false;\n\tconst pingInterval = options.pingInterval ?? DEFAULT_PING_INTERVAL;\n\tconst maxReconnectAttempts =\n\t\toptions.maxReconnectAttempts ?? DEFAULT_MAX_RECONNECT_ATTEMPTS;\n\n\tconst listeners = new Set<(msg: AIServerMessage) => void>();\n\n\tconst connState: AIConnectionState = {\n\t\tisConnected: false,\n\t\tpingInterval: null,\n\t\treconnectAttempts: 0,\n\t\treconnectTimeout: null,\n\t\tws: null\n\t};\n\n\tconst clearTimers = () => {\n\t\tif (connState.pingInterval) {\n\t\t\tclearInterval(connState.pingInterval);\n\t\t\tconnState.pingInterval = null;\n\t\t}\n\n\t\tif (connState.reconnectTimeout) {\n\t\t\tclearTimeout(connState.reconnectTimeout);\n\t\t\tconnState.reconnectTimeout = null;\n\t\t}\n\t};\n\n\tconst scheduleReconnect = () => {\n\t\tconnState.reconnectAttempts++;\n\t\tconst delay =\n\t\t\tconnState.reconnectAttempts === 1\n\t\t\t\t? RECONNECT_INITIAL_DELAY\n\t\t\t\t: RECONNECT_POLL_INTERVAL;\n\n\t\tconnState.reconnectTimeout = setTimeout(() => {\n\t\t\tif (connState.reconnectAttempts > maxReconnectAttempts) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconnect();\n\t\t}, delay);\n\t};\n\n\tconst connect = () => {\n\t\tconst url = buildWsUrl(path);\n\t\tconst wsInstance = new WebSocket(url, options.protocols);\n\n\t\twsInstance.onopen = () => {\n\t\t\tconnState.isConnected = true;\n\t\t\tconnState.reconnectAttempts = 0;\n\n\t\t\tconnState.pingInterval = setInterval(() => {\n\t\t\t\tif (\n\t\t\t\t\twsInstance.readyState === WS_OPEN &&\n\t\t\t\t\tconnState.isConnected\n\t\t\t\t) {\n\t\t\t\t\twsInstance.send(JSON.stringify({ type: 'ping' }));\n\t\t\t\t}\n\t\t\t}, pingInterval);\n\t\t};\n\n\t\twsInstance.onmessage = (event: MessageEvent) => {\n\t\t\tconst message = parseServerMessage(event);\n\n\t\t\tif (!message) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlisteners.forEach((listener) => listener(message));\n\t\t};\n\n\t\twsInstance.onclose = (event: CloseEvent) => {\n\t\t\tconnState.isConnected = false;\n\t\t\tclearTimers();\n\n\t\t\tconst shouldAttemptReconnect =\n\t\t\t\tshouldReconnect &&\n\t\t\t\tevent.code !== WS_NORMAL_CLOSURE &&\n\t\t\t\tconnState.reconnectAttempts < maxReconnectAttempts;\n\n\t\t\tif (shouldAttemptReconnect) {\n\t\t\t\tscheduleReconnect();\n\t\t\t}\n\t\t};\n\n\t\twsInstance.onerror = () => {\n\t\t\t// Error is followed by close event, reconnection handled there\n\t\t};\n\n\t\tconnState.ws = wsInstance;\n\t};\n\n\tconst send = (msg: AIClientMessage) => {\n\t\tif (connState.ws?.readyState === WS_OPEN) {\n\t\t\tconnState.ws.send(JSON.stringify(msg));\n\t\t}\n\t};\n\n\tconst subscribe = (callback: (msg: AIServerMessage) => void) => {\n\t\tlisteners.add(callback);\n\n\t\treturn () => {\n\t\t\tlisteners.delete(callback);\n\t\t};\n\t};\n\n\tconst close = () => {\n\t\tclearTimers();\n\n\t\tif (connState.ws) {\n\t\t\tconnState.ws.close(WS_NORMAL_CLOSURE);\n\t\t\tconnState.ws = null;\n\t\t}\n\n\t\tconnState.isConnected = false;\n\t\tlisteners.clear();\n\t};\n\n\tconst getReadyState = () => connState.ws?.readyState ?? WS_CLOSED;\n\n\tconnect();\n\n\treturn { close, getReadyState, send, subscribe };\n};\n",
|
|
8
|
+
"import type {\n\tAIConversation,\n\tAIMessage,\n\tAIStreamState,\n\tAIStoreAction,\n\tAIToolCall\n} from '../../../types/ai';\n\nconst EMPTY_STATE: AIStreamState = {\n\tactiveConversationId: null,\n\tconversations: new Map(),\n\terror: null,\n\tisStreaming: false\n};\n\nconst initialActiveConversationId: string | null = null;\nconst initialError: string | null = null;\n\n// eslint-disable-next-line absolute/no-useless-function -- returns a new instance each call\nconst freshState = () => ({\n\tactiveConversationId: initialActiveConversationId,\n\tconversations: new Map<string, AIConversation>(),\n\terror: initialError,\n\tisStreaming: false\n});\n\nconst findAssistantMessage = (\n\tconversation: AIConversation,\n\tmessageId: string\n) =>\n\tconversation.messages.find(\n\t\t(msg) => msg.id === messageId && msg.role === 'assistant'\n\t);\n\nconst getOrCreate = (state: AIStreamState, conversationId: string) => {\n\tlet conversation = state.conversations.get(conversationId);\n\n\tif (!conversation) {\n\t\tconversation = { id: conversationId, messages: [] };\n\t\tstate.conversations.set(conversationId, conversation);\n\t}\n\n\treturn conversation;\n};\n\nconst handleSend = (\n\tstate: AIStreamState,\n\taction: AIStoreAction & { type: 'send' }\n) => {\n\tconst conversation = getOrCreate(state, action.conversationId);\n\tconst message: AIMessage = {\n\t\tcontent: action.content,\n\t\tconversationId: action.conversationId,\n\t\tid: action.messageId,\n\t\trole: 'user',\n\t\ttimestamp: Date.now()\n\t};\n\n\tconversation.messages = [...conversation.messages, message];\n\tstate.activeConversationId = action.conversationId;\n\tstate.error = null;\n\tstate.isStreaming = true;\n};\n\nconst handleChunk = (\n\tstate: AIStreamState,\n\taction: AIStoreAction & { type: 'chunk' }\n) => {\n\tconst conversation = getOrCreate(state, action.conversationId);\n\tconst existing = findAssistantMessage(conversation, action.messageId);\n\n\tif (existing) {\n\t\texisting.content += action.content;\n\t\tconversation.messages = [...conversation.messages];\n\n\t\treturn;\n\t}\n\n\tconst message: AIMessage = {\n\t\tcontent: action.content,\n\t\tconversationId: action.conversationId,\n\t\tid: action.messageId,\n\t\tisStreaming: true,\n\t\trole: 'assistant',\n\t\ttimestamp: Date.now()\n\t};\n\n\tconversation.messages = [...conversation.messages, message];\n};\n\nconst upsertToolCall = (message: AIMessage, toolCall: AIToolCall) => {\n\tif (!message.toolCalls) {\n\t\tmessage.toolCalls = [toolCall];\n\n\t\treturn;\n\t}\n\n\tconst existingIdx = message.toolCalls.findIndex(\n\t\t(existing) => existing.name === toolCall.name\n\t);\n\n\tif (existingIdx >= 0) {\n\t\tmessage.toolCalls[existingIdx] = toolCall;\n\t} else {\n\t\tmessage.toolCalls = [...message.toolCalls, toolCall];\n\t}\n};\n\nconst handleToolStatus = (\n\tstate: AIStreamState,\n\taction: AIStoreAction & { type: 'tool_status' }\n) => {\n\tconst conversation = getOrCreate(state, action.conversationId);\n\tconst message = findAssistantMessage(conversation, action.messageId);\n\n\tif (!message) {\n\t\treturn;\n\t}\n\n\tconst toolCall: AIToolCall = {\n\t\tid: action.messageId,\n\t\tinput: action.input,\n\t\tname: action.name,\n\t\tresult: action.status === 'complete' ? (action.result ?? '') : undefined\n\t};\n\n\tupsertToolCall(message, toolCall);\n\tconversation.messages = [...conversation.messages];\n};\n\nconst markMessageComplete = (\n\tconversation: AIConversation,\n\tmessageId: string\n) => {\n\tconst message = findAssistantMessage(conversation, messageId);\n\n\tif (message) {\n\t\tmessage.isStreaming = false;\n\t}\n\n\tconversation.messages = [...conversation.messages];\n};\n\nconst handleComplete = (\n\tstate: AIStreamState,\n\taction: AIStoreAction & { type: 'complete' }\n) => {\n\tconst conversation = state.conversations.get(action.conversationId);\n\n\tif (conversation) {\n\t\tmarkMessageComplete(conversation, action.messageId);\n\t}\n\n\tstate.isStreaming = false;\n};\n\nconst markConversationStreamsComplete = (conversation: AIConversation) => {\n\tconst streamingMessages = conversation.messages.filter(\n\t\t(msg) => msg.isStreaming\n\t);\n\n\tif (streamingMessages.length === 0) {\n\t\treturn;\n\t}\n\n\tfor (const msg of streamingMessages) {\n\t\tmsg.isStreaming = false;\n\t}\n\n\tconversation.messages = [...conversation.messages];\n};\n\nconst markAllStreamsComplete = (state: AIStreamState) => {\n\tfor (const [, conversation] of state.conversations) {\n\t\tmarkConversationStreamsComplete(conversation);\n\t}\n};\n\nconst handleBranch = (\n\tstate: AIStreamState,\n\taction: AIStoreAction & { type: 'branch' }\n) => {\n\tconst source = state.conversations.get(action.oldConversationId);\n\n\tif (!source) {\n\t\treturn;\n\t}\n\n\tconst cutoffIndex = source.messages.findIndex(\n\t\t(msg) => msg.id === action.fromMessageId\n\t);\n\n\tif (cutoffIndex < 0) {\n\t\treturn;\n\t}\n\n\tconst branchedMessages = source.messages\n\t\t.slice(0, cutoffIndex + 1)\n\t\t.map((msg) => ({ ...msg, conversationId: action.newConversationId }));\n\n\tconst newConversation: AIConversation = {\n\t\tid: action.newConversationId,\n\t\tmessages: branchedMessages\n\t};\n\n\tstate.conversations.set(action.newConversationId, newConversation);\n\tstate.activeConversationId = action.newConversationId;\n};\n\nconst dispatch = (\n\tstate: AIStreamState,\n\tsubscribers: Set<() => void>,\n\taction: AIStoreAction\n) => {\n\tswitch (action.type) {\n\t\tcase 'send':\n\t\t\thandleSend(state, action);\n\t\t\tbreak;\n\t\tcase 'chunk':\n\t\t\thandleChunk(state, action);\n\t\t\tbreak;\n\t\tcase 'tool_status':\n\t\t\thandleToolStatus(state, action);\n\t\t\tbreak;\n\t\tcase 'complete':\n\t\t\thandleComplete(state, action);\n\t\t\tbreak;\n\t\tcase 'error':\n\t\t\tstate.error = action.message;\n\t\t\tstate.isStreaming = false;\n\t\t\tbreak;\n\t\tcase 'cancel':\n\t\t\tstate.isStreaming = false;\n\t\t\tmarkAllStreamsComplete(state);\n\t\t\tbreak;\n\t\tcase 'branch':\n\t\t\thandleBranch(state, action);\n\t\t\tbreak;\n\t\tcase 'set_conversation':\n\t\t\tstate.activeConversationId = action.conversationId;\n\t\t\tbreak;\n\t}\n\n\t// Create new reference for React's Object.is check\n\tObject.assign(state, { conversations: new Map(state.conversations) });\n\tsubscribers.forEach((callback) => callback());\n};\n\nexport const createAIMessageStore = () => {\n\tconst state = freshState();\n\tconst subscribers = new Set<() => void>();\n\n\treturn {\n\t\tdispatch: (action: AIStoreAction) =>\n\t\t\tdispatch(state, subscribers, action),\n\t\tgetServerSnapshot: () => EMPTY_STATE,\n\t\tgetSnapshot: () => state,\n\t\tsubscribe: (callback: () => void) => {\n\t\t\tsubscribers.add(callback);\n\n\t\t\treturn () => {\n\t\t\t\tsubscribers.delete(callback);\n\t\t\t};\n\t\t}\n\t};\n};\n",
|
|
9
|
+
"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",
|
|
10
|
+
"import type { AIMessage, AIServerMessage } from '../../../types/ai';\nimport { serverMessageToAction } from '../../ai/client/actions';\nimport { createAIConnection } from '../../ai/client/connection';\nimport { createAIMessageStore } from '../../ai/client/messageStore';\nimport { generateId } from '../../ai/protocol';\n\nexport const createAIStream = (path: string, conversationId?: string) => {\n\tconst connection = createAIConnection(path);\n\tconst store = createAIMessageStore();\n\n\tlet currentError: string | null = null;\n\tlet currentIsStreaming = false;\n\tlet currentMessages: AIMessage[] = [];\n\tlet activeConversationId: string | null = conversationId ?? null;\n\n\tconst syncState = () => {\n\t\tconst snapshot = store.getSnapshot();\n\t\tconst convId = activeConversationId ?? snapshot.activeConversationId;\n\t\tconst conversation = convId\n\t\t\t? snapshot.conversations.get(convId)\n\t\t\t: undefined;\n\t\tactiveConversationId = convId ?? snapshot.activeConversationId;\n\t\tcurrentError = snapshot.error;\n\t\tcurrentIsStreaming = snapshot.isStreaming;\n\t\tcurrentMessages = conversation?.messages ?? [];\n\t};\n\n\tstore.subscribe(syncState);\n\n\tconnection.subscribe((msg: AIServerMessage) => {\n\t\tconst action = serverMessageToAction(msg);\n\t\tif (action) {\n\t\t\tstore.dispatch(action);\n\t\t}\n\t});\n\n\tconst branch = (messageId: string, content: string) => {\n\t\tif (activeConversationId) {\n\t\t\tconnection.send({\n\t\t\t\tcontent,\n\t\t\t\tconversationId: activeConversationId,\n\t\t\t\tmessageId,\n\t\t\t\ttype: 'branch'\n\t\t\t});\n\t\t}\n\t};\n\n\tconst cancel = () => {\n\t\tif (activeConversationId) {\n\t\t\tstore.dispatch({ type: 'cancel' });\n\t\t\tconnection.send({\n\t\t\t\tconversationId: activeConversationId,\n\t\t\t\ttype: 'cancel'\n\t\t\t});\n\t\t}\n\t};\n\n\tconst destroy = () => {\n\t\tconnection.close();\n\t};\n\n\tconst send = (content: string) => {\n\t\tconst convId = activeConversationId ?? generateId();\n\t\tconst msgId = generateId();\n\n\t\tstore.dispatch({\n\t\t\tcontent,\n\t\t\tconversationId: convId,\n\t\t\tmessageId: msgId,\n\t\t\ttype: 'send'\n\t\t});\n\n\t\tconnection.send({\n\t\t\tcontent,\n\t\t\tconversationId: convId,\n\t\t\ttype: 'message'\n\t\t});\n\t};\n\n\treturn {\n\t\tbranch,\n\t\tcancel,\n\t\tdestroy,\n\t\tsend,\n\t\tget error() {\n\t\t\treturn currentError;\n\t\t},\n\t\tget isStreaming() {\n\t\t\treturn currentIsStreaming;\n\t\t},\n\t\tget messages() {\n\t\t\treturn currentMessages;\n\t\t}\n\t};\n};\n"
|
|
11
|
+
],
|
|
12
|
+
"mappings": "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",
|
|
13
|
+
"debugId": "316F5CA69826AEA964756E2164756E21",
|
|
14
|
+
"names": []
|
|
15
|
+
}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { ImageProps } from '@absolutejs/absolute/image';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
DEFAULT_QUALITY,
|
|
5
|
+
buildOptimizedUrl,
|
|
6
|
+
generateBlurSvg,
|
|
7
|
+
generateSrcSet
|
|
8
|
+
} from '@absolutejs/absolute/image';
|
|
4
9
|
|
|
5
10
|
let {
|
|
6
11
|
src,
|