@usecrow/client 0.1.42 → 0.1.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -3
- package/dist/index.d.ts +59 -9
- package/dist/index.js +50 -788
- package/dist/index.native.cjs +3 -0
- package/dist/index.native.d.ts +517 -0
- package/dist/index.native.js +788 -0
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -1,816 +1,78 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
metadata: {},
|
|
7
|
-
isVerified: !1
|
|
8
|
-
}, this.listeners = /* @__PURE__ */ new Set();
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Identify the current user with a JWT token
|
|
12
|
-
*/
|
|
13
|
-
identify(e) {
|
|
14
|
-
const { token: t, ...s } = e;
|
|
15
|
-
this.state = {
|
|
16
|
-
token: t,
|
|
17
|
-
metadata: s,
|
|
18
|
-
isVerified: !1
|
|
19
|
-
// Will be set when server confirms
|
|
20
|
-
}, this.notify(), console.log("[Crow] User identified");
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Update verification status (called when server confirms)
|
|
24
|
-
*/
|
|
25
|
-
setVerified(e) {
|
|
26
|
-
this.state = { ...this.state, isVerified: e }, this.notify();
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Reset user identity (call on logout)
|
|
30
|
-
*/
|
|
31
|
-
reset() {
|
|
32
|
-
this.state = {
|
|
33
|
-
token: null,
|
|
34
|
-
metadata: {},
|
|
35
|
-
isVerified: !1
|
|
36
|
-
}, this.notify(), console.log("[Crow] User reset");
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Get current identity token
|
|
40
|
-
*/
|
|
41
|
-
getToken() {
|
|
42
|
-
return this.state.token;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Get current identity state
|
|
46
|
-
*/
|
|
47
|
-
getState() {
|
|
48
|
-
return { ...this.state };
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Check if user is identified
|
|
52
|
-
*/
|
|
53
|
-
isIdentified() {
|
|
54
|
-
return this.state.token !== null;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Check if user is verified
|
|
58
|
-
*/
|
|
59
|
-
isVerified() {
|
|
60
|
-
return this.state.isVerified;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Subscribe to identity changes
|
|
64
|
-
*/
|
|
65
|
-
subscribe(e) {
|
|
66
|
-
return this.listeners.add(e), () => this.listeners.delete(e);
|
|
67
|
-
}
|
|
68
|
-
notify() {
|
|
69
|
-
const e = this.getState();
|
|
70
|
-
for (const t of this.listeners)
|
|
71
|
-
t(e);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
class k {
|
|
75
|
-
constructor() {
|
|
76
|
-
this.handlers = {};
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Register client-side tool handlers
|
|
80
|
-
*/
|
|
81
|
-
register(e) {
|
|
82
|
-
for (const [t, s] of Object.entries(e))
|
|
83
|
-
typeof s == "function" ? (this.handlers[t] = s, console.log(`[Crow] Registered client tool: ${t}`)) : console.warn(`[Crow] Skipping ${t}: handler is not a function`);
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Unregister a tool handler
|
|
87
|
-
*/
|
|
88
|
-
unregister(e) {
|
|
89
|
-
delete this.handlers[e], console.log(`[Crow] Unregistered client tool: ${e}`);
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Check if a tool is registered
|
|
93
|
-
*/
|
|
94
|
-
has(e) {
|
|
95
|
-
return e in this.handlers;
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Get all registered tool names
|
|
99
|
-
*/
|
|
100
|
-
getRegisteredTools() {
|
|
101
|
-
return Object.keys(this.handlers);
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Execute a client-side tool
|
|
105
|
-
*/
|
|
106
|
-
async execute(e, t) {
|
|
107
|
-
const s = this.handlers[e];
|
|
108
|
-
if (!s)
|
|
109
|
-
return console.warn(`[Crow] No handler registered for tool: ${e}`), {
|
|
110
|
-
status: "error",
|
|
111
|
-
error: `No handler registered for tool: ${e}`
|
|
112
|
-
};
|
|
113
|
-
try {
|
|
114
|
-
console.log(`[Crow] Executing client tool: ${e}`, t);
|
|
115
|
-
const r = await s(t);
|
|
116
|
-
return console.log(`[Crow] Tool ${e} completed:`, r), r;
|
|
117
|
-
} catch (r) {
|
|
118
|
-
const n = r instanceof Error ? r.message : String(r);
|
|
119
|
-
return console.error(`[Crow] Tool ${e} failed:`, r), {
|
|
120
|
-
status: "error",
|
|
121
|
-
error: n
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
const v = "crow_conv_";
|
|
127
|
-
class C {
|
|
128
|
-
constructor(e, t) {
|
|
129
|
-
this.currentId = null, this.productId = e, this.apiUrl = t, this.currentId = this.loadFromStorage();
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Get localStorage key for this product
|
|
133
|
-
*/
|
|
134
|
-
getStorageKey() {
|
|
135
|
-
return `${v}${this.productId}`;
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Load conversation ID from localStorage
|
|
139
|
-
*/
|
|
140
|
-
loadFromStorage() {
|
|
141
|
-
try {
|
|
142
|
-
return localStorage.getItem(this.getStorageKey());
|
|
143
|
-
} catch {
|
|
144
|
-
return null;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Save conversation ID to localStorage
|
|
149
|
-
*/
|
|
150
|
-
saveToStorage(e) {
|
|
151
|
-
try {
|
|
152
|
-
localStorage.setItem(this.getStorageKey(), e);
|
|
153
|
-
} catch {
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Clear conversation ID from localStorage
|
|
158
|
-
*/
|
|
159
|
-
clearStorage() {
|
|
160
|
-
try {
|
|
161
|
-
localStorage.removeItem(this.getStorageKey());
|
|
162
|
-
} catch {
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Get current conversation ID
|
|
167
|
-
*/
|
|
168
|
-
getCurrentId() {
|
|
169
|
-
return this.currentId;
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Set current conversation ID
|
|
173
|
-
*/
|
|
174
|
-
setCurrentId(e) {
|
|
175
|
-
this.currentId = e, e ? this.saveToStorage(e) : this.clearStorage();
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Check if there's a restored conversation
|
|
179
|
-
*/
|
|
180
|
-
hasRestoredConversation() {
|
|
181
|
-
return this.currentId !== null;
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Clear current conversation (start new)
|
|
185
|
-
*/
|
|
186
|
-
clear() {
|
|
187
|
-
this.currentId = null, this.clearStorage();
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Fetch list of conversations for verified user
|
|
191
|
-
*/
|
|
192
|
-
async getConversations(e) {
|
|
193
|
-
try {
|
|
194
|
-
const t = await fetch(
|
|
195
|
-
`${this.apiUrl}/api/chat/conversations?product_id=${this.productId}&identity_token=${encodeURIComponent(e)}`
|
|
196
|
-
);
|
|
197
|
-
if (!t.ok)
|
|
198
|
-
throw new Error(`HTTP error: ${t.status}`);
|
|
199
|
-
return (await t.json()).conversations || [];
|
|
200
|
-
} catch (t) {
|
|
201
|
-
return console.error("[Crow] Failed to load conversations:", t), [];
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
/**
|
|
205
|
-
* Load conversation history for verified user
|
|
206
|
-
*/
|
|
207
|
-
async loadHistory(e, t) {
|
|
208
|
-
try {
|
|
209
|
-
const s = await fetch(
|
|
210
|
-
`${this.apiUrl}/api/chat/conversations/${e}/history?product_id=${this.productId}&identity_token=${encodeURIComponent(t)}`
|
|
211
|
-
);
|
|
212
|
-
if (!s.ok)
|
|
213
|
-
throw new Error(`HTTP error: ${s.status}`);
|
|
214
|
-
const r = await s.json();
|
|
215
|
-
return this.parseHistoryMessages(r.messages || []);
|
|
216
|
-
} catch (s) {
|
|
217
|
-
return console.error("[Crow] Failed to load conversation history:", s), [];
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Load conversation history for anonymous user
|
|
222
|
-
*/
|
|
223
|
-
async loadAnonymousHistory(e) {
|
|
224
|
-
try {
|
|
225
|
-
const t = await fetch(
|
|
226
|
-
`${this.apiUrl}/api/chat/conversations/${e}/history/anonymous?product_id=${this.productId}`
|
|
227
|
-
);
|
|
228
|
-
if (!t.ok)
|
|
229
|
-
throw new Error(`HTTP error: ${t.status}`);
|
|
230
|
-
const s = await t.json();
|
|
231
|
-
return this.parseHistoryMessages(s.messages || []);
|
|
232
|
-
} catch (t) {
|
|
233
|
-
return console.error("[Crow] Failed to load anonymous conversation history:", t), [];
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Parse history messages from API format
|
|
238
|
-
*/
|
|
239
|
-
parseHistoryMessages(e) {
|
|
240
|
-
return e.filter((t) => t.role !== "tool" && !t.content.startsWith("[Client Tool Result:")).map((t, s) => ({
|
|
241
|
-
id: `history-${s}`,
|
|
242
|
-
content: this.parseContent(t.content),
|
|
243
|
-
role: t.role === "assistant" ? "assistant" : "user",
|
|
244
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
245
|
-
}));
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Parse structured content (with thinking/text blocks) and extract just text
|
|
249
|
-
*/
|
|
250
|
-
parseContent(e) {
|
|
251
|
-
try {
|
|
252
|
-
const t = JSON.parse(e);
|
|
253
|
-
if (Array.isArray(t)) {
|
|
254
|
-
const s = t.find(
|
|
255
|
-
(r) => r.type === "text"
|
|
256
|
-
);
|
|
257
|
-
return (s == null ? void 0 : s.text) || e;
|
|
258
|
-
}
|
|
259
|
-
} catch {
|
|
260
|
-
}
|
|
261
|
-
if (e.includes("'type': 'text'")) {
|
|
262
|
-
const t = e.match(
|
|
263
|
-
/\{'text':\s*'((?:[^'\\]|\\.)*)'\s*,\s*'type':\s*'text'/
|
|
264
|
-
);
|
|
265
|
-
if (t)
|
|
266
|
-
return t[1].replace(/\\n/g, `
|
|
267
|
-
`).replace(/\\'/g, "'");
|
|
268
|
-
}
|
|
269
|
-
return e;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
function b(o) {
|
|
273
|
-
if (o === "[DONE]")
|
|
274
|
-
return { type: "done" };
|
|
275
|
-
try {
|
|
276
|
-
const e = JSON.parse(o);
|
|
277
|
-
switch (e.type) {
|
|
278
|
-
case "verification_status":
|
|
279
|
-
return {
|
|
280
|
-
type: "verification_status",
|
|
281
|
-
isVerified: e.is_verified === !0
|
|
282
|
-
};
|
|
283
|
-
case "conversation_id":
|
|
284
|
-
return {
|
|
285
|
-
type: "conversation_id",
|
|
286
|
-
conversationId: e.conversation_id
|
|
287
|
-
};
|
|
288
|
-
case "thinking":
|
|
289
|
-
return e.status === "complete" ? { type: "thinking_complete" } : null;
|
|
290
|
-
case "thinking_token":
|
|
291
|
-
return {
|
|
292
|
-
type: "thinking",
|
|
293
|
-
content: e.content || ""
|
|
294
|
-
};
|
|
295
|
-
case "content":
|
|
296
|
-
return {
|
|
297
|
-
type: "content",
|
|
298
|
-
text: e.content || "",
|
|
299
|
-
accumulated: ""
|
|
300
|
-
// Will be set by caller
|
|
301
|
-
};
|
|
302
|
-
case "citations":
|
|
303
|
-
return {
|
|
304
|
-
type: "citations",
|
|
305
|
-
citations: e.citations
|
|
306
|
-
};
|
|
307
|
-
case "error":
|
|
308
|
-
return {
|
|
309
|
-
type: "error",
|
|
310
|
-
message: e.message || "Unknown error"
|
|
311
|
-
};
|
|
312
|
-
case "tool_call_start":
|
|
313
|
-
return {
|
|
314
|
-
type: "tool_call_start",
|
|
315
|
-
toolName: e.tool_name,
|
|
316
|
-
displayName: e.display_name || void 0,
|
|
317
|
-
arguments: e.arguments || {}
|
|
318
|
-
};
|
|
319
|
-
case "tool_call_complete":
|
|
320
|
-
return {
|
|
321
|
-
type: "tool_call_complete",
|
|
322
|
-
toolName: e.tool_name,
|
|
323
|
-
displayName: e.display_name || void 0,
|
|
324
|
-
success: e.success
|
|
325
|
-
};
|
|
326
|
-
case "client_tool_call":
|
|
327
|
-
return {
|
|
328
|
-
type: "client_tool_call",
|
|
329
|
-
toolName: e.tool_name,
|
|
330
|
-
displayName: e.display_name || void 0,
|
|
331
|
-
arguments: e.arguments || {}
|
|
332
|
-
};
|
|
333
|
-
case "tool_consent_required":
|
|
334
|
-
return {
|
|
335
|
-
type: "tool_consent_required",
|
|
336
|
-
toolName: e.tool_name,
|
|
337
|
-
displayName: e.display_name || void 0,
|
|
338
|
-
arguments: e.arguments || {}
|
|
339
|
-
};
|
|
340
|
-
case "workflow_started":
|
|
341
|
-
return {
|
|
342
|
-
type: "workflow_started",
|
|
343
|
-
name: e.name,
|
|
344
|
-
todos: e.todos
|
|
345
|
-
};
|
|
346
|
-
case "todo_updated":
|
|
347
|
-
return {
|
|
348
|
-
type: "workflow_todo_updated",
|
|
349
|
-
todoId: e.id,
|
|
350
|
-
status: e.status
|
|
351
|
-
};
|
|
352
|
-
case "workflow_ended":
|
|
353
|
-
return { type: "workflow_ended" };
|
|
354
|
-
case "workflow_complete_prompt":
|
|
355
|
-
return { type: "workflow_complete_prompt" };
|
|
356
|
-
default:
|
|
357
|
-
return null;
|
|
358
|
-
}
|
|
359
|
-
} catch {
|
|
360
|
-
return console.error("[Crow] Failed to parse SSE data:", o), null;
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
function* I(o) {
|
|
364
|
-
const e = o.split(`
|
|
365
|
-
`);
|
|
366
|
-
for (const t of e)
|
|
367
|
-
t.startsWith("data: ") && (yield t.slice(6).trim());
|
|
368
|
-
}
|
|
369
|
-
async function* M(o, e) {
|
|
370
|
-
var n;
|
|
371
|
-
const t = (n = o.body) == null ? void 0 : n.getReader();
|
|
372
|
-
if (!t)
|
|
373
|
-
throw new Error("Response body is not readable");
|
|
374
|
-
const s = new TextDecoder();
|
|
375
|
-
let r = "";
|
|
376
|
-
try {
|
|
377
|
-
for (; ; ) {
|
|
378
|
-
if (e != null && e.aborted) {
|
|
379
|
-
t.cancel();
|
|
380
|
-
return;
|
|
381
|
-
}
|
|
382
|
-
const { done: i, value: d } = await t.read();
|
|
383
|
-
if (i) break;
|
|
384
|
-
const h = s.decode(d);
|
|
385
|
-
for (const u of I(h)) {
|
|
386
|
-
const l = b(u);
|
|
387
|
-
if (l && (l.type === "content" ? (r += l.text, yield { ...l, accumulated: r }) : yield l, l.type === "done"))
|
|
388
|
-
return;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
} finally {
|
|
392
|
-
t.releaseLock();
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
async function S() {
|
|
396
|
-
var o;
|
|
397
|
-
try {
|
|
398
|
-
const e = document.title, t = window.location.href, s = window.location.pathname, r = (((o = document.body) == null ? void 0 : o.innerText) || "").slice(0, 2e3).trim();
|
|
399
|
-
return {
|
|
400
|
-
status: "success",
|
|
401
|
-
data: {
|
|
402
|
-
title: e,
|
|
403
|
-
url: t,
|
|
404
|
-
pathname: s,
|
|
405
|
-
visibleText: r
|
|
406
|
-
}
|
|
407
|
-
};
|
|
408
|
-
} catch (e) {
|
|
409
|
-
return {
|
|
410
|
-
status: "error",
|
|
411
|
-
error: e instanceof Error ? e.message : "Failed to read screen"
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
const w = {
|
|
416
|
-
whatsOnScreen: S
|
|
417
|
-
}, T = Object.keys(w), $ = "https://api.usecrow.org", E = "claude-sonnet-4-20250514";
|
|
418
|
-
class x {
|
|
419
|
-
constructor(e) {
|
|
420
|
-
this.context = {}, this.abortController = null, this.callbacks = {}, this._messages = [], this.messageListeners = /* @__PURE__ */ new Set(), this._isLoading = !1, this.loadingListeners = /* @__PURE__ */ new Set(), this.config = {
|
|
421
|
-
productId: e.productId,
|
|
422
|
-
apiUrl: e.apiUrl || $,
|
|
423
|
-
model: e.model || E
|
|
424
|
-
}, this.identity = new _(), this.tools = new k(), this.conversations = new C(
|
|
425
|
-
this.config.productId,
|
|
426
|
-
this.config.apiUrl
|
|
427
|
-
), this.tools.register(w), console.log("[Crow] Default tools registered:", T.join(", ")), this.identity.subscribe((t) => {
|
|
428
|
-
var s, r;
|
|
429
|
-
(r = (s = this.callbacks).onVerificationStatus) == null || r.call(s, t.isVerified);
|
|
430
|
-
});
|
|
431
|
-
}
|
|
432
|
-
// ============================================================================
|
|
433
|
-
// Configuration
|
|
434
|
-
// ============================================================================
|
|
435
|
-
/**
|
|
436
|
-
* Get current product ID
|
|
437
|
-
*/
|
|
438
|
-
get productId() {
|
|
439
|
-
return this.config.productId;
|
|
440
|
-
}
|
|
441
|
-
/**
|
|
442
|
-
* Get current API URL
|
|
443
|
-
*/
|
|
444
|
-
get apiUrl() {
|
|
445
|
-
return this.config.apiUrl;
|
|
446
|
-
}
|
|
447
|
-
/**
|
|
448
|
-
* Get/set current model
|
|
449
|
-
*/
|
|
450
|
-
get model() {
|
|
451
|
-
return this.config.model;
|
|
452
|
-
}
|
|
453
|
-
set model(e) {
|
|
454
|
-
this.config.model = e;
|
|
455
|
-
}
|
|
456
|
-
// ============================================================================
|
|
457
|
-
// Event Callbacks
|
|
458
|
-
// ============================================================================
|
|
459
|
-
/**
|
|
460
|
-
* Register event callbacks
|
|
461
|
-
*/
|
|
462
|
-
on(e) {
|
|
463
|
-
this.callbacks = { ...this.callbacks, ...e };
|
|
464
|
-
}
|
|
465
|
-
// ============================================================================
|
|
466
|
-
// Identity
|
|
467
|
-
// ============================================================================
|
|
468
|
-
/**
|
|
469
|
-
* Identify the current user with a JWT token
|
|
470
|
-
*/
|
|
471
|
-
identify(e) {
|
|
472
|
-
this.identity.identify(e);
|
|
473
|
-
}
|
|
474
|
-
/**
|
|
475
|
-
* Reset user identity (call on logout)
|
|
476
|
-
*/
|
|
477
|
-
resetUser() {
|
|
478
|
-
this.identity.reset(), this.clearMessages();
|
|
479
|
-
}
|
|
480
|
-
/**
|
|
481
|
-
* Check if user is identified
|
|
482
|
-
*/
|
|
483
|
-
isIdentified() {
|
|
484
|
-
return this.identity.isIdentified();
|
|
485
|
-
}
|
|
486
|
-
/**
|
|
487
|
-
* Check if user is verified by server
|
|
488
|
-
*/
|
|
489
|
-
isVerified() {
|
|
490
|
-
return this.identity.isVerified();
|
|
491
|
-
}
|
|
492
|
-
// ============================================================================
|
|
493
|
-
// Tools
|
|
494
|
-
// ============================================================================
|
|
495
|
-
/**
|
|
496
|
-
* Register client-side tool handlers
|
|
497
|
-
*/
|
|
498
|
-
registerTools(e) {
|
|
499
|
-
this.tools.register(e);
|
|
500
|
-
}
|
|
501
|
-
/**
|
|
502
|
-
* Unregister a tool handler
|
|
503
|
-
*/
|
|
504
|
-
unregisterTool(e) {
|
|
505
|
-
this.tools.unregister(e);
|
|
506
|
-
}
|
|
507
|
-
/**
|
|
508
|
-
* Get list of registered tool names
|
|
509
|
-
*/
|
|
510
|
-
getRegisteredTools() {
|
|
511
|
-
return this.tools.getRegisteredTools();
|
|
512
|
-
}
|
|
513
|
-
// ============================================================================
|
|
514
|
-
// Context
|
|
515
|
-
// ============================================================================
|
|
516
|
-
/**
|
|
517
|
-
* Set context data to be sent with messages
|
|
518
|
-
*/
|
|
519
|
-
setContext(e) {
|
|
520
|
-
this.context = { ...this.context, ...e };
|
|
521
|
-
}
|
|
522
|
-
/**
|
|
523
|
-
* Clear context data
|
|
524
|
-
*/
|
|
525
|
-
clearContext() {
|
|
526
|
-
this.context = {};
|
|
527
|
-
}
|
|
528
|
-
// ============================================================================
|
|
529
|
-
// Messages
|
|
530
|
-
// ============================================================================
|
|
531
|
-
/**
|
|
532
|
-
* Get current messages
|
|
533
|
-
*/
|
|
534
|
-
get messages() {
|
|
535
|
-
return [...this._messages];
|
|
536
|
-
}
|
|
537
|
-
/**
|
|
538
|
-
* Check if currently loading/streaming
|
|
539
|
-
*/
|
|
540
|
-
get isLoading() {
|
|
541
|
-
return this._isLoading;
|
|
542
|
-
}
|
|
543
|
-
/**
|
|
544
|
-
* Subscribe to message changes
|
|
545
|
-
*/
|
|
546
|
-
onMessages(e) {
|
|
547
|
-
return this.messageListeners.add(e), () => this.messageListeners.delete(e);
|
|
548
|
-
}
|
|
549
|
-
/**
|
|
550
|
-
* Subscribe to loading state changes
|
|
551
|
-
*/
|
|
552
|
-
onLoading(e) {
|
|
553
|
-
return this.loadingListeners.add(e), () => this.loadingListeners.delete(e);
|
|
554
|
-
}
|
|
555
|
-
/**
|
|
556
|
-
* Clear all messages and start new conversation
|
|
557
|
-
*/
|
|
558
|
-
clearMessages() {
|
|
559
|
-
this._messages = [], this.conversations.clear(), this.notifyMessages();
|
|
560
|
-
}
|
|
561
|
-
/**
|
|
562
|
-
* Load messages from history
|
|
563
|
-
*/
|
|
564
|
-
loadMessages(e) {
|
|
565
|
-
this._messages = e, this.notifyMessages();
|
|
566
|
-
}
|
|
567
|
-
notifyMessages() {
|
|
568
|
-
const e = this.messages;
|
|
569
|
-
for (const t of this.messageListeners)
|
|
570
|
-
t(e);
|
|
571
|
-
}
|
|
572
|
-
setLoading(e) {
|
|
573
|
-
this._isLoading = e;
|
|
574
|
-
for (const t of this.loadingListeners)
|
|
575
|
-
t(e);
|
|
576
|
-
}
|
|
577
|
-
addMessage(e) {
|
|
578
|
-
var t, s;
|
|
579
|
-
this._messages = [...this._messages, e], this.notifyMessages(), (s = (t = this.callbacks).onMessage) == null || s.call(t, e);
|
|
580
|
-
}
|
|
581
|
-
updateMessage(e, t) {
|
|
582
|
-
var s, r;
|
|
583
|
-
this._messages = this._messages.map(
|
|
584
|
-
(n) => n.id === e ? { ...n, ...t } : n
|
|
585
|
-
), this.notifyMessages(), (r = (s = this.callbacks).onMessageUpdate) == null || r.call(s, e, t);
|
|
586
|
-
}
|
|
587
|
-
generateMessageId(e) {
|
|
588
|
-
return `${e}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
589
|
-
}
|
|
590
|
-
// ============================================================================
|
|
591
|
-
// Conversations
|
|
592
|
-
// ============================================================================
|
|
593
|
-
/**
|
|
594
|
-
* Get current conversation ID
|
|
595
|
-
*/
|
|
596
|
-
get conversationId() {
|
|
597
|
-
return this.conversations.getCurrentId();
|
|
598
|
-
}
|
|
599
|
-
/**
|
|
600
|
-
* Set current conversation ID
|
|
601
|
-
*/
|
|
602
|
-
set conversationId(e) {
|
|
603
|
-
this.conversations.setCurrentId(e);
|
|
604
|
-
}
|
|
605
|
-
/**
|
|
606
|
-
* Get list of conversations for verified user
|
|
607
|
-
*/
|
|
608
|
-
async getConversations() {
|
|
609
|
-
const e = this.identity.getToken();
|
|
610
|
-
return e ? this.conversations.getConversations(e) : (console.warn("[Crow] Cannot get conversations: user not identified"), []);
|
|
611
|
-
}
|
|
612
|
-
/**
|
|
613
|
-
* Load conversation history
|
|
614
|
-
*/
|
|
615
|
-
async loadHistory(e) {
|
|
616
|
-
const t = this.identity.getToken();
|
|
617
|
-
return t ? this.conversations.loadHistory(e, t) : this.conversations.loadAnonymousHistory(e);
|
|
618
|
-
}
|
|
619
|
-
/**
|
|
620
|
-
* Switch to a different conversation
|
|
621
|
-
*/
|
|
622
|
-
async switchConversation(e) {
|
|
623
|
-
const t = await this.loadHistory(e);
|
|
624
|
-
this.conversations.setCurrentId(e), this.loadMessages(t);
|
|
625
|
-
}
|
|
626
|
-
// ============================================================================
|
|
627
|
-
// Messaging
|
|
628
|
-
// ============================================================================
|
|
629
|
-
/**
|
|
630
|
-
* Send a message and receive streaming response
|
|
631
|
-
* Returns an async generator of stream events
|
|
632
|
-
*/
|
|
633
|
-
async *sendMessage(e) {
|
|
634
|
-
var i, d, h, u, l, g, f, p, y, m;
|
|
635
|
-
if (!e.trim())
|
|
636
|
-
return;
|
|
637
|
-
const t = this.generateMessageId("user");
|
|
638
|
-
this.addMessage({
|
|
639
|
-
id: t,
|
|
640
|
-
content: e,
|
|
641
|
-
role: "user",
|
|
642
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
643
|
-
});
|
|
644
|
-
const s = this.generateMessageId("assistant");
|
|
645
|
-
this.addMessage({
|
|
646
|
-
id: s,
|
|
647
|
-
content: "",
|
|
648
|
-
role: "assistant",
|
|
649
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
650
|
-
}), this.setLoading(!0), this.abortController = new AbortController();
|
|
651
|
-
let r = "", n = "";
|
|
652
|
-
try {
|
|
653
|
-
const c = await fetch(`${this.config.apiUrl}/api/chat/message`, {
|
|
654
|
-
method: "POST",
|
|
655
|
-
headers: { "Content-Type": "application/json" },
|
|
656
|
-
body: JSON.stringify({
|
|
657
|
-
product_id: this.config.productId,
|
|
658
|
-
message: e,
|
|
659
|
-
conversation_id: this.conversations.getCurrentId(),
|
|
660
|
-
identity_token: this.identity.getToken(),
|
|
661
|
-
model: this.config.model,
|
|
662
|
-
context: Object.keys(this.context).length > 0 ? this.context : void 0
|
|
663
|
-
}),
|
|
664
|
-
signal: this.abortController.signal
|
|
665
|
-
});
|
|
666
|
-
if (!c.ok)
|
|
667
|
-
throw new Error(`HTTP error: ${c.status}`);
|
|
668
|
-
for await (const a of M(c, this.abortController.signal)) {
|
|
669
|
-
switch (a.type) {
|
|
670
|
-
case "content":
|
|
671
|
-
r = a.accumulated, this.updateMessage(s, { content: r });
|
|
672
|
-
break;
|
|
673
|
-
case "thinking":
|
|
674
|
-
n += a.content, this.updateMessage(s, { thinking: n });
|
|
675
|
-
break;
|
|
676
|
-
case "thinking_complete":
|
|
677
|
-
this.updateMessage(s, { thinkingComplete: !0 });
|
|
678
|
-
break;
|
|
679
|
-
case "citations":
|
|
680
|
-
this.updateMessage(s, { citations: a.citations });
|
|
681
|
-
break;
|
|
682
|
-
case "verification_status":
|
|
683
|
-
this.identity.setVerified(a.isVerified);
|
|
684
|
-
break;
|
|
685
|
-
case "conversation_id":
|
|
686
|
-
this.conversations.setCurrentId(a.conversationId);
|
|
687
|
-
break;
|
|
688
|
-
case "client_tool_call":
|
|
689
|
-
await this.tools.execute(a.toolName, a.arguments), (d = (i = this.callbacks).onToolCall) == null || d.call(i, a);
|
|
690
|
-
break;
|
|
691
|
-
case "tool_call_start":
|
|
692
|
-
case "tool_call_complete":
|
|
693
|
-
(u = (h = this.callbacks).onToolCall) == null || u.call(h, a);
|
|
694
|
-
break;
|
|
695
|
-
case "workflow_started":
|
|
696
|
-
case "workflow_todo_updated":
|
|
697
|
-
case "workflow_ended":
|
|
698
|
-
case "workflow_complete_prompt":
|
|
699
|
-
(g = (l = this.callbacks).onWorkflow) == null || g.call(l, a);
|
|
700
|
-
break;
|
|
701
|
-
case "error":
|
|
702
|
-
this.updateMessage(s, { content: a.message }), (p = (f = this.callbacks).onError) == null || p.call(f, new Error(a.message));
|
|
703
|
-
break;
|
|
704
|
-
}
|
|
705
|
-
yield a;
|
|
706
|
-
}
|
|
707
|
-
} catch (c) {
|
|
708
|
-
if (c instanceof Error && c.name === "AbortError") {
|
|
709
|
-
r ? this.updateMessage(s, { content: r }) : (this._messages = this._messages.filter((a) => a.id !== s), this.notifyMessages());
|
|
710
|
-
return;
|
|
711
|
-
}
|
|
712
|
-
console.error("[Crow] Error:", c), this.updateMessage(s, {
|
|
713
|
-
content: "Sorry, I encountered an error. Please try again."
|
|
714
|
-
}), (m = (y = this.callbacks).onError) == null || m.call(y, c instanceof Error ? c : new Error(String(c)));
|
|
715
|
-
} finally {
|
|
716
|
-
this.setLoading(!1), this.abortController = null;
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
/**
|
|
720
|
-
* Send a message and wait for complete response (non-streaming)
|
|
721
|
-
*/
|
|
722
|
-
async send(e) {
|
|
723
|
-
let t = null;
|
|
724
|
-
for await (const r of this.sendMessage(e))
|
|
725
|
-
if (r.type === "done")
|
|
726
|
-
break;
|
|
727
|
-
const s = this.messages;
|
|
728
|
-
return s.length > 0 && (t = s[s.length - 1], t.role === "assistant") ? t : null;
|
|
729
|
-
}
|
|
730
|
-
/**
|
|
731
|
-
* Stop current generation
|
|
732
|
-
*/
|
|
733
|
-
stop() {
|
|
734
|
-
this.abortController && (this.abortController.abort(), this.setLoading(!1));
|
|
735
|
-
}
|
|
736
|
-
// ============================================================================
|
|
737
|
-
// Cleanup
|
|
738
|
-
// ============================================================================
|
|
739
|
-
/**
|
|
740
|
-
* Destroy the client and clean up resources
|
|
741
|
-
*/
|
|
742
|
-
destroy() {
|
|
743
|
-
this.stop(), this.messageListeners.clear(), this.loadingListeners.clear();
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
function L(o, e, t) {
|
|
747
|
-
const s = o.find(
|
|
748
|
-
(n) => n.name.toLowerCase() === e.toLowerCase()
|
|
1
|
+
import { ConversationManager as g, CrowClient as f, DEFAULT_TOOLS as m, DEFAULT_TOOL_NAMES as v, IdentityManager as w, ToolManager as h, createLocalStorageAdapter as S, createMemoryStorageAdapter as T, parseSSEChunk as _, parseSSEData as A, streamResponse as C } from "./index.native.js";
|
|
2
|
+
import { C as L, W as y } from "./workflowExecutor-ijFlX3nx.js";
|
|
3
|
+
function l(n, s, a) {
|
|
4
|
+
const e = n.find(
|
|
5
|
+
(t) => t.name.toLowerCase() === s.toLowerCase()
|
|
749
6
|
);
|
|
750
|
-
if (!
|
|
751
|
-
let
|
|
752
|
-
if (
|
|
753
|
-
for (const [
|
|
754
|
-
|
|
755
|
-
return
|
|
7
|
+
if (!e) return null;
|
|
8
|
+
let o = e.path;
|
|
9
|
+
if (a)
|
|
10
|
+
for (const [t, r] of Object.entries(a))
|
|
11
|
+
o = o.replace(`:${t}`, String(r));
|
|
12
|
+
return o;
|
|
756
13
|
}
|
|
757
|
-
function
|
|
758
|
-
return async (
|
|
14
|
+
function c(n, s) {
|
|
15
|
+
return async (a) => {
|
|
759
16
|
try {
|
|
760
|
-
const
|
|
761
|
-
let
|
|
762
|
-
if (
|
|
763
|
-
if (
|
|
17
|
+
const e = a.page, o = a.params, t = a.url;
|
|
18
|
+
let r = null;
|
|
19
|
+
if (e) {
|
|
20
|
+
if (r = l(n, e, o), !r)
|
|
764
21
|
return {
|
|
765
22
|
status: "error",
|
|
766
|
-
error: `Unknown page: "${
|
|
23
|
+
error: `Unknown page: "${e}". Available pages: ${n.map((u) => u.name).join(", ")}`
|
|
767
24
|
};
|
|
768
|
-
} else if (
|
|
769
|
-
|
|
25
|
+
} else if (t)
|
|
26
|
+
r = t;
|
|
770
27
|
else
|
|
771
28
|
return {
|
|
772
29
|
status: "error",
|
|
773
30
|
error: 'Either "page" or "url" parameter is required'
|
|
774
31
|
};
|
|
775
|
-
const
|
|
776
|
-
return
|
|
32
|
+
const i = r.match(/:([a-zA-Z_][a-zA-Z0-9_]*)/g);
|
|
33
|
+
return i ? {
|
|
777
34
|
status: "error",
|
|
778
|
-
error: `Missing parameters: ${
|
|
779
|
-
} :
|
|
35
|
+
error: `Missing parameters: ${i.join(", ")}. Please provide values for these parameters.`
|
|
36
|
+
} : s ? (s(r), {
|
|
780
37
|
status: "success",
|
|
781
38
|
data: {
|
|
782
|
-
navigated_to:
|
|
783
|
-
page:
|
|
39
|
+
navigated_to: r,
|
|
40
|
+
page: e || void 0,
|
|
784
41
|
method: "spa_router"
|
|
785
42
|
}
|
|
786
|
-
}) : (window.location.href =
|
|
43
|
+
}) : typeof window < "u" ? (window.location.href = r, {
|
|
787
44
|
status: "success",
|
|
788
45
|
data: {
|
|
789
|
-
navigated_to:
|
|
790
|
-
page:
|
|
46
|
+
navigated_to: r,
|
|
47
|
+
page: e || void 0,
|
|
791
48
|
method: "full_navigation"
|
|
792
49
|
}
|
|
793
|
-
})
|
|
794
|
-
|
|
50
|
+
}) : {
|
|
51
|
+
status: "error",
|
|
52
|
+
error: "No navigateFn provided and window.location is unavailable (non-browser runtime). Pass a navigateFn to createNavigateToPageTool."
|
|
53
|
+
};
|
|
54
|
+
} catch (e) {
|
|
795
55
|
return {
|
|
796
56
|
status: "error",
|
|
797
|
-
error: String(
|
|
57
|
+
error: String(e)
|
|
798
58
|
};
|
|
799
59
|
}
|
|
800
60
|
};
|
|
801
61
|
}
|
|
802
62
|
export {
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
63
|
+
g as ConversationManager,
|
|
64
|
+
L as CrowBrowserUse,
|
|
65
|
+
f as CrowClient,
|
|
66
|
+
m as DEFAULT_TOOLS,
|
|
67
|
+
v as DEFAULT_TOOL_NAMES,
|
|
68
|
+
w as IdentityManager,
|
|
69
|
+
h as ToolManager,
|
|
70
|
+
y as WorkflowExecutor,
|
|
71
|
+
S as createLocalStorageAdapter,
|
|
72
|
+
T as createMemoryStorageAdapter,
|
|
73
|
+
c as createNavigateToPageTool,
|
|
74
|
+
_ as parseSSEChunk,
|
|
75
|
+
A as parseSSEData,
|
|
76
|
+
l as resolveRoute,
|
|
77
|
+
C as streamResponse
|
|
816
78
|
};
|