@usecrow/client 0.1.43 → 0.1.45
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 +57 -9
- package/dist/index.js +50 -790
- 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,818 +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
|
-
subdomain: e.subdomain
|
|
425
|
-
}, this.identity = new _(), this.tools = new k(), this.conversations = new C(
|
|
426
|
-
this.config.productId,
|
|
427
|
-
this.config.apiUrl
|
|
428
|
-
), this.tools.register(w), console.log("[Crow] Default tools registered:", T.join(", ")), this.identity.subscribe((t) => {
|
|
429
|
-
var s, r;
|
|
430
|
-
(r = (s = this.callbacks).onVerificationStatus) == null || r.call(s, t.isVerified);
|
|
431
|
-
});
|
|
432
|
-
}
|
|
433
|
-
// ============================================================================
|
|
434
|
-
// Configuration
|
|
435
|
-
// ============================================================================
|
|
436
|
-
/**
|
|
437
|
-
* Get current product ID
|
|
438
|
-
*/
|
|
439
|
-
get productId() {
|
|
440
|
-
return this.config.productId;
|
|
441
|
-
}
|
|
442
|
-
/**
|
|
443
|
-
* Get current API URL
|
|
444
|
-
*/
|
|
445
|
-
get apiUrl() {
|
|
446
|
-
return this.config.apiUrl;
|
|
447
|
-
}
|
|
448
|
-
/**
|
|
449
|
-
* Get/set current model
|
|
450
|
-
*/
|
|
451
|
-
get model() {
|
|
452
|
-
return this.config.model;
|
|
453
|
-
}
|
|
454
|
-
set model(e) {
|
|
455
|
-
this.config.model = e;
|
|
456
|
-
}
|
|
457
|
-
// ============================================================================
|
|
458
|
-
// Event Callbacks
|
|
459
|
-
// ============================================================================
|
|
460
|
-
/**
|
|
461
|
-
* Register event callbacks
|
|
462
|
-
*/
|
|
463
|
-
on(e) {
|
|
464
|
-
this.callbacks = { ...this.callbacks, ...e };
|
|
465
|
-
}
|
|
466
|
-
// ============================================================================
|
|
467
|
-
// Identity
|
|
468
|
-
// ============================================================================
|
|
469
|
-
/**
|
|
470
|
-
* Identify the current user with a JWT token
|
|
471
|
-
*/
|
|
472
|
-
identify(e) {
|
|
473
|
-
this.identity.identify(e);
|
|
474
|
-
}
|
|
475
|
-
/**
|
|
476
|
-
* Reset user identity (call on logout)
|
|
477
|
-
*/
|
|
478
|
-
resetUser() {
|
|
479
|
-
this.identity.reset(), this.clearMessages();
|
|
480
|
-
}
|
|
481
|
-
/**
|
|
482
|
-
* Check if user is identified
|
|
483
|
-
*/
|
|
484
|
-
isIdentified() {
|
|
485
|
-
return this.identity.isIdentified();
|
|
486
|
-
}
|
|
487
|
-
/**
|
|
488
|
-
* Check if user is verified by server
|
|
489
|
-
*/
|
|
490
|
-
isVerified() {
|
|
491
|
-
return this.identity.isVerified();
|
|
492
|
-
}
|
|
493
|
-
// ============================================================================
|
|
494
|
-
// Tools
|
|
495
|
-
// ============================================================================
|
|
496
|
-
/**
|
|
497
|
-
* Register client-side tool handlers
|
|
498
|
-
*/
|
|
499
|
-
registerTools(e) {
|
|
500
|
-
this.tools.register(e);
|
|
501
|
-
}
|
|
502
|
-
/**
|
|
503
|
-
* Unregister a tool handler
|
|
504
|
-
*/
|
|
505
|
-
unregisterTool(e) {
|
|
506
|
-
this.tools.unregister(e);
|
|
507
|
-
}
|
|
508
|
-
/**
|
|
509
|
-
* Get list of registered tool names
|
|
510
|
-
*/
|
|
511
|
-
getRegisteredTools() {
|
|
512
|
-
return this.tools.getRegisteredTools();
|
|
513
|
-
}
|
|
514
|
-
// ============================================================================
|
|
515
|
-
// Context
|
|
516
|
-
// ============================================================================
|
|
517
|
-
/**
|
|
518
|
-
* Set context data to be sent with messages
|
|
519
|
-
*/
|
|
520
|
-
setContext(e) {
|
|
521
|
-
this.context = { ...this.context, ...e };
|
|
522
|
-
}
|
|
523
|
-
/**
|
|
524
|
-
* Clear context data
|
|
525
|
-
*/
|
|
526
|
-
clearContext() {
|
|
527
|
-
this.context = {};
|
|
528
|
-
}
|
|
529
|
-
// ============================================================================
|
|
530
|
-
// Messages
|
|
531
|
-
// ============================================================================
|
|
532
|
-
/**
|
|
533
|
-
* Get current messages
|
|
534
|
-
*/
|
|
535
|
-
get messages() {
|
|
536
|
-
return [...this._messages];
|
|
537
|
-
}
|
|
538
|
-
/**
|
|
539
|
-
* Check if currently loading/streaming
|
|
540
|
-
*/
|
|
541
|
-
get isLoading() {
|
|
542
|
-
return this._isLoading;
|
|
543
|
-
}
|
|
544
|
-
/**
|
|
545
|
-
* Subscribe to message changes
|
|
546
|
-
*/
|
|
547
|
-
onMessages(e) {
|
|
548
|
-
return this.messageListeners.add(e), () => this.messageListeners.delete(e);
|
|
549
|
-
}
|
|
550
|
-
/**
|
|
551
|
-
* Subscribe to loading state changes
|
|
552
|
-
*/
|
|
553
|
-
onLoading(e) {
|
|
554
|
-
return this.loadingListeners.add(e), () => this.loadingListeners.delete(e);
|
|
555
|
-
}
|
|
556
|
-
/**
|
|
557
|
-
* Clear all messages and start new conversation
|
|
558
|
-
*/
|
|
559
|
-
clearMessages() {
|
|
560
|
-
this._messages = [], this.conversations.clear(), this.notifyMessages();
|
|
561
|
-
}
|
|
562
|
-
/**
|
|
563
|
-
* Load messages from history
|
|
564
|
-
*/
|
|
565
|
-
loadMessages(e) {
|
|
566
|
-
this._messages = e, this.notifyMessages();
|
|
567
|
-
}
|
|
568
|
-
notifyMessages() {
|
|
569
|
-
const e = this.messages;
|
|
570
|
-
for (const t of this.messageListeners)
|
|
571
|
-
t(e);
|
|
572
|
-
}
|
|
573
|
-
setLoading(e) {
|
|
574
|
-
this._isLoading = e;
|
|
575
|
-
for (const t of this.loadingListeners)
|
|
576
|
-
t(e);
|
|
577
|
-
}
|
|
578
|
-
addMessage(e) {
|
|
579
|
-
var t, s;
|
|
580
|
-
this._messages = [...this._messages, e], this.notifyMessages(), (s = (t = this.callbacks).onMessage) == null || s.call(t, e);
|
|
581
|
-
}
|
|
582
|
-
updateMessage(e, t) {
|
|
583
|
-
var s, r;
|
|
584
|
-
this._messages = this._messages.map(
|
|
585
|
-
(n) => n.id === e ? { ...n, ...t } : n
|
|
586
|
-
), this.notifyMessages(), (r = (s = this.callbacks).onMessageUpdate) == null || r.call(s, e, t);
|
|
587
|
-
}
|
|
588
|
-
generateMessageId(e) {
|
|
589
|
-
return `${e}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
590
|
-
}
|
|
591
|
-
// ============================================================================
|
|
592
|
-
// Conversations
|
|
593
|
-
// ============================================================================
|
|
594
|
-
/**
|
|
595
|
-
* Get current conversation ID
|
|
596
|
-
*/
|
|
597
|
-
get conversationId() {
|
|
598
|
-
return this.conversations.getCurrentId();
|
|
599
|
-
}
|
|
600
|
-
/**
|
|
601
|
-
* Set current conversation ID
|
|
602
|
-
*/
|
|
603
|
-
set conversationId(e) {
|
|
604
|
-
this.conversations.setCurrentId(e);
|
|
605
|
-
}
|
|
606
|
-
/**
|
|
607
|
-
* Get list of conversations for verified user
|
|
608
|
-
*/
|
|
609
|
-
async getConversations() {
|
|
610
|
-
const e = this.identity.getToken();
|
|
611
|
-
return e ? this.conversations.getConversations(e) : (console.warn("[Crow] Cannot get conversations: user not identified"), []);
|
|
612
|
-
}
|
|
613
|
-
/**
|
|
614
|
-
* Load conversation history
|
|
615
|
-
*/
|
|
616
|
-
async loadHistory(e) {
|
|
617
|
-
const t = this.identity.getToken();
|
|
618
|
-
return t ? this.conversations.loadHistory(e, t) : this.conversations.loadAnonymousHistory(e);
|
|
619
|
-
}
|
|
620
|
-
/**
|
|
621
|
-
* Switch to a different conversation
|
|
622
|
-
*/
|
|
623
|
-
async switchConversation(e) {
|
|
624
|
-
const t = await this.loadHistory(e);
|
|
625
|
-
this.conversations.setCurrentId(e), this.loadMessages(t);
|
|
626
|
-
}
|
|
627
|
-
// ============================================================================
|
|
628
|
-
// Messaging
|
|
629
|
-
// ============================================================================
|
|
630
|
-
/**
|
|
631
|
-
* Send a message and receive streaming response
|
|
632
|
-
* Returns an async generator of stream events
|
|
633
|
-
*/
|
|
634
|
-
async *sendMessage(e) {
|
|
635
|
-
var i, d, h, u, l, g, f, p, y, m;
|
|
636
|
-
if (!e.trim())
|
|
637
|
-
return;
|
|
638
|
-
const t = this.generateMessageId("user");
|
|
639
|
-
this.addMessage({
|
|
640
|
-
id: t,
|
|
641
|
-
content: e,
|
|
642
|
-
role: "user",
|
|
643
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
644
|
-
});
|
|
645
|
-
const s = this.generateMessageId("assistant");
|
|
646
|
-
this.addMessage({
|
|
647
|
-
id: s,
|
|
648
|
-
content: "",
|
|
649
|
-
role: "assistant",
|
|
650
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
651
|
-
}), this.setLoading(!0), this.abortController = new AbortController();
|
|
652
|
-
let r = "", n = "";
|
|
653
|
-
try {
|
|
654
|
-
const c = await fetch(`${this.config.apiUrl}/api/chat/message`, {
|
|
655
|
-
method: "POST",
|
|
656
|
-
headers: { "Content-Type": "application/json" },
|
|
657
|
-
body: JSON.stringify({
|
|
658
|
-
product_id: this.config.productId,
|
|
659
|
-
message: e,
|
|
660
|
-
conversation_id: this.conversations.getCurrentId(),
|
|
661
|
-
identity_token: this.identity.getToken(),
|
|
662
|
-
model: this.config.model,
|
|
663
|
-
subdomain: this.config.subdomain,
|
|
664
|
-
context: Object.keys(this.context).length > 0 ? this.context : void 0
|
|
665
|
-
}),
|
|
666
|
-
signal: this.abortController.signal
|
|
667
|
-
});
|
|
668
|
-
if (!c.ok)
|
|
669
|
-
throw new Error(`HTTP error: ${c.status}`);
|
|
670
|
-
for await (const a of M(c, this.abortController.signal)) {
|
|
671
|
-
switch (a.type) {
|
|
672
|
-
case "content":
|
|
673
|
-
r = a.accumulated, this.updateMessage(s, { content: r });
|
|
674
|
-
break;
|
|
675
|
-
case "thinking":
|
|
676
|
-
n += a.content, this.updateMessage(s, { thinking: n });
|
|
677
|
-
break;
|
|
678
|
-
case "thinking_complete":
|
|
679
|
-
this.updateMessage(s, { thinkingComplete: !0 });
|
|
680
|
-
break;
|
|
681
|
-
case "citations":
|
|
682
|
-
this.updateMessage(s, { citations: a.citations });
|
|
683
|
-
break;
|
|
684
|
-
case "verification_status":
|
|
685
|
-
this.identity.setVerified(a.isVerified);
|
|
686
|
-
break;
|
|
687
|
-
case "conversation_id":
|
|
688
|
-
this.conversations.setCurrentId(a.conversationId);
|
|
689
|
-
break;
|
|
690
|
-
case "client_tool_call":
|
|
691
|
-
await this.tools.execute(a.toolName, a.arguments), (d = (i = this.callbacks).onToolCall) == null || d.call(i, a);
|
|
692
|
-
break;
|
|
693
|
-
case "tool_call_start":
|
|
694
|
-
case "tool_call_complete":
|
|
695
|
-
(u = (h = this.callbacks).onToolCall) == null || u.call(h, a);
|
|
696
|
-
break;
|
|
697
|
-
case "workflow_started":
|
|
698
|
-
case "workflow_todo_updated":
|
|
699
|
-
case "workflow_ended":
|
|
700
|
-
case "workflow_complete_prompt":
|
|
701
|
-
(g = (l = this.callbacks).onWorkflow) == null || g.call(l, a);
|
|
702
|
-
break;
|
|
703
|
-
case "error":
|
|
704
|
-
this.updateMessage(s, { content: a.message }), (p = (f = this.callbacks).onError) == null || p.call(f, new Error(a.message));
|
|
705
|
-
break;
|
|
706
|
-
}
|
|
707
|
-
yield a;
|
|
708
|
-
}
|
|
709
|
-
} catch (c) {
|
|
710
|
-
if (c instanceof Error && c.name === "AbortError") {
|
|
711
|
-
r ? this.updateMessage(s, { content: r }) : (this._messages = this._messages.filter((a) => a.id !== s), this.notifyMessages());
|
|
712
|
-
return;
|
|
713
|
-
}
|
|
714
|
-
console.error("[Crow] Error:", c), this.updateMessage(s, {
|
|
715
|
-
content: "Sorry, I encountered an error. Please try again."
|
|
716
|
-
}), (m = (y = this.callbacks).onError) == null || m.call(y, c instanceof Error ? c : new Error(String(c)));
|
|
717
|
-
} finally {
|
|
718
|
-
this.setLoading(!1), this.abortController = null;
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
/**
|
|
722
|
-
* Send a message and wait for complete response (non-streaming)
|
|
723
|
-
*/
|
|
724
|
-
async send(e) {
|
|
725
|
-
let t = null;
|
|
726
|
-
for await (const r of this.sendMessage(e))
|
|
727
|
-
if (r.type === "done")
|
|
728
|
-
break;
|
|
729
|
-
const s = this.messages;
|
|
730
|
-
return s.length > 0 && (t = s[s.length - 1], t.role === "assistant") ? t : null;
|
|
731
|
-
}
|
|
732
|
-
/**
|
|
733
|
-
* Stop current generation
|
|
734
|
-
*/
|
|
735
|
-
stop() {
|
|
736
|
-
this.abortController && (this.abortController.abort(), this.setLoading(!1));
|
|
737
|
-
}
|
|
738
|
-
// ============================================================================
|
|
739
|
-
// Cleanup
|
|
740
|
-
// ============================================================================
|
|
741
|
-
/**
|
|
742
|
-
* Destroy the client and clean up resources
|
|
743
|
-
*/
|
|
744
|
-
destroy() {
|
|
745
|
-
this.stop(), this.messageListeners.clear(), this.loadingListeners.clear();
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
function L(o, e, t) {
|
|
749
|
-
const s = o.find(
|
|
750
|
-
(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()
|
|
751
6
|
);
|
|
752
|
-
if (!
|
|
753
|
-
let
|
|
754
|
-
if (
|
|
755
|
-
for (const [
|
|
756
|
-
|
|
757
|
-
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;
|
|
758
13
|
}
|
|
759
|
-
function
|
|
760
|
-
return async (
|
|
14
|
+
function c(n, s) {
|
|
15
|
+
return async (a) => {
|
|
761
16
|
try {
|
|
762
|
-
const
|
|
763
|
-
let
|
|
764
|
-
if (
|
|
765
|
-
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)
|
|
766
21
|
return {
|
|
767
22
|
status: "error",
|
|
768
|
-
error: `Unknown page: "${
|
|
23
|
+
error: `Unknown page: "${e}". Available pages: ${n.map((u) => u.name).join(", ")}`
|
|
769
24
|
};
|
|
770
|
-
} else if (
|
|
771
|
-
|
|
25
|
+
} else if (t)
|
|
26
|
+
r = t;
|
|
772
27
|
else
|
|
773
28
|
return {
|
|
774
29
|
status: "error",
|
|
775
30
|
error: 'Either "page" or "url" parameter is required'
|
|
776
31
|
};
|
|
777
|
-
const
|
|
778
|
-
return
|
|
32
|
+
const i = r.match(/:([a-zA-Z_][a-zA-Z0-9_]*)/g);
|
|
33
|
+
return i ? {
|
|
779
34
|
status: "error",
|
|
780
|
-
error: `Missing parameters: ${
|
|
781
|
-
} :
|
|
35
|
+
error: `Missing parameters: ${i.join(", ")}. Please provide values for these parameters.`
|
|
36
|
+
} : s ? (s(r), {
|
|
782
37
|
status: "success",
|
|
783
38
|
data: {
|
|
784
|
-
navigated_to:
|
|
785
|
-
page:
|
|
39
|
+
navigated_to: r,
|
|
40
|
+
page: e || void 0,
|
|
786
41
|
method: "spa_router"
|
|
787
42
|
}
|
|
788
|
-
}) : (window.location.href =
|
|
43
|
+
}) : typeof window < "u" ? (window.location.href = r, {
|
|
789
44
|
status: "success",
|
|
790
45
|
data: {
|
|
791
|
-
navigated_to:
|
|
792
|
-
page:
|
|
46
|
+
navigated_to: r,
|
|
47
|
+
page: e || void 0,
|
|
793
48
|
method: "full_navigation"
|
|
794
49
|
}
|
|
795
|
-
})
|
|
796
|
-
|
|
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) {
|
|
797
55
|
return {
|
|
798
56
|
status: "error",
|
|
799
|
-
error: String(
|
|
57
|
+
error: String(e)
|
|
800
58
|
};
|
|
801
59
|
}
|
|
802
60
|
};
|
|
803
61
|
}
|
|
804
62
|
export {
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
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
|
|
818
78
|
};
|