@harnessio/ai-chat-core 0.0.1

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.
Files changed (36) hide show
  1. package/LICENSE +201 -0
  2. package/dist/core/PluginRegistry.d.ts +12 -0
  3. package/dist/core/index.d.ts +1 -0
  4. package/dist/index.d.ts +5 -0
  5. package/dist/index.js +1051 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/react/hooks/index.d.ts +7 -0
  8. package/dist/react/hooks/useAssistantRuntime.d.ts +2 -0
  9. package/dist/react/hooks/useComposer.d.ts +3 -0
  10. package/dist/react/hooks/useContentFocus.d.ts +17 -0
  11. package/dist/react/hooks/useContentRenderer.d.ts +16 -0
  12. package/dist/react/hooks/useCurrentThread.d.ts +2 -0
  13. package/dist/react/hooks/useMessages.d.ts +2 -0
  14. package/dist/react/hooks/useThreadList.d.ts +9 -0
  15. package/dist/react/index.d.ts +2 -0
  16. package/dist/react/providers/AssistantRuntimeProvider.d.ts +8 -0
  17. package/dist/react/providers/index.d.ts +1 -0
  18. package/dist/runtime/AssistantRuntime/AssistantRuntime.d.ts +33 -0
  19. package/dist/runtime/ComposerRuntime/ComposerRuntime.d.ts +16 -0
  20. package/dist/runtime/ContentFocusRuntime/ContentFocusRuntime.d.ts +27 -0
  21. package/dist/runtime/ThreadListItemRuntime/ThreadListItemRuntime.d.ts +20 -0
  22. package/dist/runtime/ThreadListRuntime/ThreadListRuntime.d.ts +35 -0
  23. package/dist/runtime/ThreadRuntime/ThreadRuntime.d.ts +21 -0
  24. package/dist/runtime/ThreadRuntime/ThreadRuntimeCore.d.ts +32 -0
  25. package/dist/runtime/index.d.ts +10 -0
  26. package/dist/types/adapters.d.ts +48 -0
  27. package/dist/types/index.d.ts +5 -0
  28. package/dist/types/message.d.ts +56 -0
  29. package/dist/types/plugin.d.ts +55 -0
  30. package/dist/types/thread.d.ts +31 -0
  31. package/dist/utils/BaseSSEStreamAdapter.d.ts +25 -0
  32. package/dist/utils/Subscribable.d.ts +7 -0
  33. package/dist/utils/groupContentByParentId.d.ts +9 -0
  34. package/dist/utils/idGenerator.d.ts +3 -0
  35. package/dist/utils/index.d.ts +4 -0
  36. package/package.json +57 -0
package/dist/index.js ADDED
@@ -0,0 +1,1051 @@
1
+ var $ = Object.defineProperty;
2
+ var q = (n, i, t) => i in n ? $(n, i, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[i] = t;
3
+ var d = (n, i, t) => q(n, typeof i != "symbol" ? i + "" : i, t);
4
+ import j, { createContext as U, useContext as J, useState as D, useEffect as k } from "react";
5
+ class W {
6
+ constructor() {
7
+ d(this, "plugins", /* @__PURE__ */ new Map());
8
+ d(this, "renderersByType", /* @__PURE__ */ new Map());
9
+ }
10
+ registerPlugin(i) {
11
+ this.plugins.has(i.id), this.plugins.set(i.id, i), i.renderers.forEach((t) => {
12
+ const e = this.renderersByType.get(t.type) || [];
13
+ e.push(t), e.sort((r, s) => ((s == null ? void 0 : s.priority) ?? 0) - ((r == null ? void 0 : r.priority) ?? 0)), this.renderersByType.set(t.type, e);
14
+ });
15
+ }
16
+ unregisterPlugin(i) {
17
+ const t = this.plugins.get(i);
18
+ return t ? (t.renderers.forEach((e) => {
19
+ const s = (this.renderersByType.get(e.type) || []).filter((a) => !t.renderers.includes(a));
20
+ s.length === 0 ? this.renderersByType.delete(e.type) : this.renderersByType.set(e.type, s);
21
+ }), this.plugins.delete(i)) : !1;
22
+ }
23
+ getPlugin(i) {
24
+ return this.plugins.get(i);
25
+ }
26
+ getAllPlugins() {
27
+ return Array.from(this.plugins.values());
28
+ }
29
+ getRenderersByType(i) {
30
+ return this.renderersByType.get(i) || [];
31
+ }
32
+ getBestRendererForType(i) {
33
+ return this.getRenderersByType(i)[0];
34
+ }
35
+ clear() {
36
+ this.plugins.clear(), this.renderersByType.clear();
37
+ }
38
+ }
39
+ class m {
40
+ constructor() {
41
+ d(this, "_subscriptions", /* @__PURE__ */ new Set());
42
+ }
43
+ subscribe(i) {
44
+ return this._subscriptions.add(i), () => {
45
+ this._subscriptions.delete(i);
46
+ };
47
+ }
48
+ notifySubscribers() {
49
+ for (const i of this._subscriptions)
50
+ i();
51
+ }
52
+ getSubscriberCount() {
53
+ return this._subscriptions.size;
54
+ }
55
+ }
56
+ class z extends m {
57
+ constructor() {
58
+ super(...arguments);
59
+ d(this, "_state", {
60
+ isActive: !1,
61
+ context: null,
62
+ focusedContent: null,
63
+ focusedMessage: null,
64
+ focusedMessageId: null,
65
+ focusedContentIndex: null
66
+ });
67
+ }
68
+ get state() {
69
+ return this._state;
70
+ }
71
+ get isActive() {
72
+ return this._state.isActive;
73
+ }
74
+ get context() {
75
+ return this._state.context;
76
+ }
77
+ get focusedContent() {
78
+ return this._state.focusedContent;
79
+ }
80
+ get focusedMessage() {
81
+ return this._state.focusedMessage;
82
+ }
83
+ get focusedMessageId() {
84
+ return this._state.focusedMessageId;
85
+ }
86
+ get focusedContentIndex() {
87
+ return this._state.focusedContentIndex;
88
+ }
89
+ focus(t, e, r, s = "detail") {
90
+ this._state = {
91
+ isActive: !0,
92
+ context: s,
93
+ focusedContent: t,
94
+ focusedMessage: e,
95
+ focusedMessageId: e.id,
96
+ focusedContentIndex: r
97
+ }, this.notifySubscribers();
98
+ }
99
+ blur() {
100
+ this._state = {
101
+ isActive: !1,
102
+ context: null,
103
+ focusedContent: null,
104
+ focusedMessage: null,
105
+ focusedMessageId: null,
106
+ focusedContentIndex: null
107
+ }, this.notifySubscribers();
108
+ }
109
+ toggle(t, e, r, s = "detail") {
110
+ this._state.isActive && this._state.focusedMessageId === e.id && this._state.focusedContentIndex === r && this._state.context === s ? this.blur() : this.focus(t, e, r, s);
111
+ }
112
+ switchContext(t) {
113
+ this._state.isActive && this._state.focusedContent && (this._state = {
114
+ ...this._state,
115
+ context: t
116
+ }, this.notifySubscribers());
117
+ }
118
+ focusNext(t) {
119
+ if (!this._state.focusedMessageId || !t.length) return;
120
+ const e = t.findIndex((a) => a.id === this._state.focusedMessageId);
121
+ if (e === -1) return;
122
+ const r = t[e], s = this._state.focusedContentIndex ?? 0;
123
+ if (s + 1 < r.content.length) {
124
+ const a = r.content[s + 1];
125
+ this.focus(a, r, s + 1, this._state.context || "detail");
126
+ return;
127
+ }
128
+ if (e + 1 < t.length) {
129
+ const a = t[e + 1];
130
+ a.content.length > 0 && this.focus(a.content[0], a, 0, this._state.context || "detail");
131
+ }
132
+ }
133
+ focusPrevious(t) {
134
+ if (!this._state.focusedMessageId || !t.length) return;
135
+ const e = t.findIndex((a) => a.id === this._state.focusedMessageId);
136
+ if (e === -1) return;
137
+ const r = t[e], s = this._state.focusedContentIndex ?? 0;
138
+ if (s > 0) {
139
+ const a = r.content[s - 1];
140
+ this.focus(a, r, s - 1, this._state.context || "detail");
141
+ return;
142
+ }
143
+ if (e > 0) {
144
+ const a = t[e - 1];
145
+ if (a.content.length > 0) {
146
+ const o = a.content.length - 1;
147
+ this.focus(a.content[o], a, o, this._state.context || "detail");
148
+ }
149
+ }
150
+ }
151
+ }
152
+ let G = 0, V = 0;
153
+ function E() {
154
+ return `msg-${Date.now()}-${++G}`;
155
+ }
156
+ function M() {
157
+ return `thread-${Date.now()}-${++V}`;
158
+ }
159
+ function ct(n = "id") {
160
+ return `${n}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
161
+ }
162
+ class w extends m {
163
+ constructor(t) {
164
+ super();
165
+ d(this, "_state");
166
+ this.config = t, this._state = t.state;
167
+ }
168
+ get state() {
169
+ return this._state;
170
+ }
171
+ getState() {
172
+ return this._state;
173
+ }
174
+ updateState(t) {
175
+ this._state = t, this.notifySubscribers();
176
+ }
177
+ async switchTo() {
178
+ await this.config.onSwitchTo(this._state.id);
179
+ }
180
+ async rename(t) {
181
+ await this.config.onRename(this._state.id, t);
182
+ }
183
+ async delete() {
184
+ await this.config.onDelete(this._state.id);
185
+ }
186
+ subscribe(t) {
187
+ return super.subscribe(t);
188
+ }
189
+ }
190
+ class H extends m {
191
+ constructor() {
192
+ super(...arguments);
193
+ d(this, "_text", "");
194
+ d(this, "_isSubmitting", !1);
195
+ }
196
+ get text() {
197
+ return this._text;
198
+ }
199
+ get isSubmitting() {
200
+ return this._isSubmitting;
201
+ }
202
+ getState() {
203
+ return {
204
+ text: this._text,
205
+ isSubmitting: this._isSubmitting
206
+ };
207
+ }
208
+ setText(t) {
209
+ this._text = t, this.notifySubscribers();
210
+ }
211
+ clear() {
212
+ this._text = "", this.notifySubscribers();
213
+ }
214
+ setSubmitting(t) {
215
+ this._isSubmitting = t, this.notifySubscribers();
216
+ }
217
+ }
218
+ class T extends m {
219
+ constructor(t) {
220
+ super();
221
+ d(this, "composer");
222
+ this._core = t, this.composer = new H(), this._core.subscribe(() => {
223
+ this.notifySubscribers();
224
+ });
225
+ }
226
+ get messages() {
227
+ return this._core.messages;
228
+ }
229
+ get isRunning() {
230
+ return this._core.isRunning;
231
+ }
232
+ get isDisabled() {
233
+ return this._core.isDisabled;
234
+ }
235
+ get capabilities() {
236
+ return this._core.capabilities;
237
+ }
238
+ getState() {
239
+ return {
240
+ threadId: "main",
241
+ // Will be set by ThreadListRuntime
242
+ isDisabled: this._core.isDisabled,
243
+ isRunning: this._core.isRunning,
244
+ capabilities: this._core.capabilities
245
+ };
246
+ }
247
+ append(t) {
248
+ this._core.append(t);
249
+ }
250
+ async send(t) {
251
+ if (t.trim()) {
252
+ this.composer.setSubmitting(!0);
253
+ try {
254
+ this.composer.clear(), await this._core.startRun({
255
+ role: "user",
256
+ content: [{ type: "text", data: t }]
257
+ });
258
+ } catch {
259
+ } finally {
260
+ this.composer.setSubmitting(!1);
261
+ }
262
+ }
263
+ }
264
+ cancelRun() {
265
+ this._core.cancelRun();
266
+ }
267
+ clear() {
268
+ this._core.clear();
269
+ }
270
+ reset(t = []) {
271
+ this._core.reset(t);
272
+ }
273
+ subscribe(t) {
274
+ return super.subscribe(t);
275
+ }
276
+ }
277
+ class x extends m {
278
+ constructor(t) {
279
+ super();
280
+ d(this, "_messages", []);
281
+ d(this, "_isRunning", !1);
282
+ d(this, "_isDisabled", !1);
283
+ d(this, "_abortController", null);
284
+ // Track current part being accumulated
285
+ d(this, "_currentPart", null);
286
+ this.config = t, t.initialMessages && (this._messages = [...t.initialMessages]);
287
+ }
288
+ get messages() {
289
+ return this._messages;
290
+ }
291
+ get isRunning() {
292
+ return this._isRunning;
293
+ }
294
+ get isDisabled() {
295
+ return this._isDisabled;
296
+ }
297
+ get capabilities() {
298
+ return {
299
+ cancel: !0,
300
+ edit: !1,
301
+ reload: !1,
302
+ speech: !1,
303
+ attachments: !1,
304
+ feedback: !1
305
+ };
306
+ }
307
+ append(t) {
308
+ var r, s;
309
+ const e = {
310
+ id: t.id || E(),
311
+ parentId: t.parentId,
312
+ role: t.role,
313
+ content: t.content,
314
+ status: t.status || { type: "complete" },
315
+ timestamp: t.timestamp || Date.now(),
316
+ metadata: t.metadata
317
+ };
318
+ this._messages.push(e), (s = (r = this.config).onMessagesChange) == null || s.call(r, this._messages), this.notifySubscribers();
319
+ }
320
+ async startRun(t) {
321
+ var s, a;
322
+ if (this._isRunning)
323
+ throw new Error("A run is already in progress");
324
+ this.append(t), this._isRunning = !0, this._abortController = new AbortController(), this._currentPart = null, this.notifySubscribers();
325
+ const e = E(), r = {
326
+ id: e,
327
+ role: "assistant",
328
+ content: [],
329
+ status: { type: "running" },
330
+ timestamp: Date.now()
331
+ };
332
+ this._messages.push(r), (a = (s = this.config).onMessagesChange) == null || a.call(s, this._messages), this.notifySubscribers();
333
+ try {
334
+ const o = this.config.streamAdapter.stream({
335
+ messages: this._messages,
336
+ signal: this._abortController.signal
337
+ });
338
+ for await (const u of o) {
339
+ if (this._abortController.signal.aborted)
340
+ break;
341
+ this.handleStreamEvent(e, u.event);
342
+ }
343
+ this.updateMessageStatus(e, { type: "complete" });
344
+ } catch (o) {
345
+ if (o instanceof Error && o.name === "AbortError")
346
+ this.updateMessageStatus(e, { type: "cancelled" });
347
+ else {
348
+ const u = o instanceof Error ? o.message : "Unknown error";
349
+ this.updateMessageStatus(e, {
350
+ type: "error",
351
+ error: u
352
+ });
353
+ }
354
+ } finally {
355
+ this._isRunning = !1, this._abortController = null, this._currentPart = null, this.notifySubscribers();
356
+ }
357
+ }
358
+ handleStreamEvent(t, e) {
359
+ var a, o;
360
+ const r = this._messages.findIndex((u) => u.id === t);
361
+ if (r === -1) return;
362
+ const s = this._messages[r];
363
+ if (e.type === "part-start")
364
+ this.handlePartStart(s, e);
365
+ else if (e.type === "text-delta")
366
+ this.handleTextDelta(s, e);
367
+ else if (e.type === "part-finish")
368
+ this.handlePartFinish();
369
+ else if (e.type === "metadata") {
370
+ const u = e;
371
+ s.metadata = {
372
+ ...s.metadata,
373
+ conversationId: u.conversationId,
374
+ interactionId: u.interactionId
375
+ };
376
+ } else if (e.type === "error") {
377
+ const u = e;
378
+ s.content.push({
379
+ type: "error",
380
+ data: u.error
381
+ });
382
+ } else {
383
+ const u = e;
384
+ s.content.push({
385
+ type: u.type,
386
+ data: u.data,
387
+ parentId: u.parentId
388
+ });
389
+ }
390
+ this._messages = [
391
+ ...this._messages.slice(0, r),
392
+ { ...s, timestamp: Date.now() },
393
+ ...this._messages.slice(r + 1)
394
+ ], (o = (a = this.config).onMessagesChange) == null || o.call(a, this._messages), this.notifySubscribers();
395
+ }
396
+ handlePartStart(t, e) {
397
+ const r = t.content.length;
398
+ let s;
399
+ switch (e.part.type) {
400
+ case "assistant_thought":
401
+ s = {
402
+ type: e.part.type,
403
+ data: [],
404
+ parentId: e.part.parentId
405
+ };
406
+ break;
407
+ case "text":
408
+ s = {
409
+ type: e.part.type,
410
+ data: "",
411
+ parentId: e.part.parentId
412
+ };
413
+ break;
414
+ default:
415
+ s = {
416
+ type: e.part.type,
417
+ parentId: e.part.parentId
418
+ };
419
+ }
420
+ t.content.push(s), this._currentPart = {
421
+ messageId: t.id,
422
+ contentIndex: r,
423
+ type: e.part.type,
424
+ parentId: e.part.parentId
425
+ };
426
+ }
427
+ handleTextDelta(t, e) {
428
+ if (!this._currentPart) {
429
+ console.warn("Received text-delta without part-start");
430
+ return;
431
+ }
432
+ const r = t.content[this._currentPart.contentIndex];
433
+ r.type === "assistant_thought" ? (Array.isArray(r.data) || (r.data = []), e.delta.trim() && r.data.push(e.delta.trim())) : r.data = (r.data || "") + e.delta;
434
+ }
435
+ handlePartFinish() {
436
+ if (!this._currentPart) {
437
+ console.warn("Received part-finish without part-start");
438
+ return;
439
+ }
440
+ this._currentPart = null;
441
+ }
442
+ updateMessageStatus(t, e) {
443
+ var s, a;
444
+ const r = this._messages.findIndex((o) => o.id === t);
445
+ r !== -1 && (this._messages[r] = {
446
+ ...this._messages[r],
447
+ status: e
448
+ }, (a = (s = this.config).onMessagesChange) == null || a.call(s, this._messages), this.notifySubscribers());
449
+ }
450
+ clear() {
451
+ var t, e;
452
+ this._messages = [], (e = (t = this.config).onMessagesChange) == null || e.call(t, this._messages), this.notifySubscribers();
453
+ }
454
+ cancelRun() {
455
+ !this._isRunning || !this._abortController || this._abortController.abort();
456
+ }
457
+ reset(t = []) {
458
+ var e, r;
459
+ this._messages = [...t], (r = (e = this.config).onMessagesChange) == null || r.call(e, this._messages), this.notifySubscribers();
460
+ }
461
+ }
462
+ class K extends m {
463
+ constructor(t) {
464
+ super();
465
+ d(this, "_mainThreadId");
466
+ d(this, "_threads", /* @__PURE__ */ new Map());
467
+ d(this, "_threadItems", /* @__PURE__ */ new Map());
468
+ d(this, "_threadStates", /* @__PURE__ */ new Map());
469
+ d(this, "_isLoading", !1);
470
+ d(this, "main");
471
+ this.config = t, this._mainThreadId = M();
472
+ const e = new x({
473
+ streamAdapter: t.streamAdapter
474
+ });
475
+ this.main = new T(e), this._threads.set(this._mainThreadId, this.main);
476
+ const r = {
477
+ id: this._mainThreadId,
478
+ title: "New Chat",
479
+ status: { type: "regular" },
480
+ isMain: !0,
481
+ createdAt: Date.now(),
482
+ updatedAt: Date.now()
483
+ };
484
+ this._threadStates.set(this._mainThreadId, r);
485
+ const s = new w({
486
+ state: r,
487
+ onSwitchTo: this.switchToThread.bind(this),
488
+ onRename: this.renameThread.bind(this),
489
+ onDelete: this.deleteThread.bind(this)
490
+ });
491
+ this._threadItems.set(this._mainThreadId, s);
492
+ }
493
+ get isLoading() {
494
+ return this._isLoading;
495
+ }
496
+ /**
497
+ * Get the currently active main thread
498
+ */
499
+ getMainThread() {
500
+ const t = this._threads.get(this._mainThreadId);
501
+ return t || this.main;
502
+ }
503
+ getState() {
504
+ const t = [], e = {};
505
+ for (const [r, s] of this._threadStates)
506
+ e[r] = s, s.status.type === "regular" && t.push(r);
507
+ return {
508
+ mainThreadId: this._mainThreadId,
509
+ threads: t,
510
+ isLoading: this._isLoading,
511
+ threadItems: e
512
+ };
513
+ }
514
+ async switchToThread(t) {
515
+ var a, o;
516
+ const e = this._threads.get(t);
517
+ if (!e)
518
+ throw new Error(`Thread ${t} not found`);
519
+ const r = this._threadStates.get(this._mainThreadId);
520
+ r && (r.isMain = !1, this._threadStates.set(this._mainThreadId, r), (a = this._threadItems.get(this._mainThreadId)) == null || a.updateState(r)), this._mainThreadId = t;
521
+ const s = this._threadStates.get(t);
522
+ if (s && (s.isMain = !0, this._threadStates.set(t, s), (o = this._threadItems.get(t)) == null || o.updateState(s)), this.config.threadListAdapter && (s != null && s.conversationId)) {
523
+ this._isLoading = !0, this.notifySubscribers();
524
+ try {
525
+ const u = await this.config.threadListAdapter.loadThread(t);
526
+ e.reset(u);
527
+ } catch (u) {
528
+ console.error("Failed to load thread:", u);
529
+ } finally {
530
+ this._isLoading = !1;
531
+ }
532
+ }
533
+ this.notifySubscribers();
534
+ }
535
+ async switchToNewThread() {
536
+ const t = M(), e = new x({
537
+ streamAdapter: this.config.streamAdapter
538
+ }), r = new T(e);
539
+ this._threads.set(t, r);
540
+ const s = {
541
+ id: t,
542
+ title: "New Chat",
543
+ status: { type: "regular" },
544
+ isMain: !1,
545
+ createdAt: Date.now(),
546
+ updatedAt: Date.now()
547
+ };
548
+ this._threadStates.set(t, s);
549
+ const a = new w({
550
+ state: s,
551
+ onSwitchTo: this.switchToThread.bind(this),
552
+ onRename: this.renameThread.bind(this),
553
+ onDelete: this.deleteThread.bind(this)
554
+ });
555
+ if (this._threadItems.set(t, a), r.subscribe(() => {
556
+ this.notifySubscribers();
557
+ }), this.config.threadListAdapter)
558
+ try {
559
+ const o = await this.config.threadListAdapter.createThread();
560
+ s.conversationId = o.conversationId, this._threadStates.set(t, s), a.updateState(s);
561
+ } catch (o) {
562
+ console.error("Failed to create thread:", o);
563
+ }
564
+ await this.switchToThread(t);
565
+ }
566
+ async loadThreads() {
567
+ if (!this.config.threadListAdapter) {
568
+ console.warn("No threadListAdapter configured");
569
+ return;
570
+ }
571
+ this._isLoading = !0, this.notifySubscribers();
572
+ try {
573
+ const t = await this.config.threadListAdapter.loadThreads();
574
+ for (const e of t) {
575
+ if (this._threadStates.has(e.id))
576
+ continue;
577
+ const r = new x({
578
+ streamAdapter: this.config.streamAdapter
579
+ }), s = new T(r);
580
+ this._threads.set(e.id, s), this._threadStates.set(e.id, e);
581
+ const a = new w({
582
+ state: e,
583
+ onSwitchTo: this.switchToThread.bind(this),
584
+ onRename: this.renameThread.bind(this),
585
+ onDelete: this.deleteThread.bind(this)
586
+ });
587
+ this._threadItems.set(e.id, a), s.subscribe(() => {
588
+ this.notifySubscribers();
589
+ });
590
+ }
591
+ } catch (t) {
592
+ console.error("Failed to load threads:", t);
593
+ } finally {
594
+ this._isLoading = !1, this.notifySubscribers();
595
+ }
596
+ }
597
+ async renameThread(t, e) {
598
+ var s;
599
+ const r = this._threadStates.get(t);
600
+ if (r) {
601
+ if (r.title = e, r.updatedAt = Date.now(), this._threadStates.set(t, r), (s = this._threadItems.get(t)) == null || s.updateState(r), this.config.threadListAdapter)
602
+ try {
603
+ await this.config.threadListAdapter.updateThread(t, { title: e });
604
+ } catch (a) {
605
+ console.error("Failed to rename thread:", a);
606
+ }
607
+ this.notifySubscribers();
608
+ }
609
+ }
610
+ async deleteThread(t) {
611
+ if (t === this._mainThreadId && this._threads.size === 1)
612
+ throw new Error("Cannot delete the last thread");
613
+ if (t === this._mainThreadId) {
614
+ const e = Array.from(this._threads.keys()).find((r) => r !== t);
615
+ e && await this.switchToThread(e);
616
+ }
617
+ if (this._threads.delete(t), this._threadItems.delete(t), this._threadStates.delete(t), this.config.threadListAdapter)
618
+ try {
619
+ await this.config.threadListAdapter.deleteThread(t);
620
+ } catch (e) {
621
+ console.error("Failed to delete thread:", e);
622
+ }
623
+ this.notifySubscribers();
624
+ }
625
+ }
626
+ class ht extends m {
627
+ constructor(t) {
628
+ super();
629
+ d(this, "threads");
630
+ d(this, "pluginRegistry");
631
+ d(this, "_contentFocusRuntime");
632
+ d(this, "_currentThreadUnsubscribe");
633
+ this.pluginRegistry = new W(), t.plugins && t.plugins.forEach((e) => {
634
+ this.pluginRegistry.registerPlugin(e);
635
+ }), this.threads = new K({
636
+ streamAdapter: t.streamAdapter,
637
+ threadListAdapter: t.threadListAdapter
638
+ }), this._contentFocusRuntime = new z(), this._contentFocusRuntime.subscribe(() => {
639
+ this.notifySubscribers();
640
+ }), this.threads.subscribe(() => {
641
+ this.subscribeToCurrentThread(), this.notifySubscribers();
642
+ }), this.subscribeToCurrentThread();
643
+ }
644
+ get thread() {
645
+ return this.threads.getMainThread();
646
+ }
647
+ get contentFocus() {
648
+ return this._contentFocusRuntime;
649
+ }
650
+ /**
651
+ * Register a plugin
652
+ */
653
+ registerPlugin(t) {
654
+ var e;
655
+ this.pluginRegistry.registerPlugin(t), (e = t.init) == null || e.call(t, {
656
+ streamingEnabled: !0,
657
+ feedbackEnabled: !1,
658
+ detailPanelEnabled: !0
659
+ });
660
+ }
661
+ /**
662
+ * Unregister a plugin
663
+ */
664
+ unregisterPlugin(t) {
665
+ return this.pluginRegistry.unregisterPlugin(t);
666
+ }
667
+ /**
668
+ * Subscribe to the current main thread
669
+ * Called when thread switches to ensure we listen to the right thread
670
+ */
671
+ subscribeToCurrentThread() {
672
+ this._currentThreadUnsubscribe && this._currentThreadUnsubscribe(), this._currentThreadUnsubscribe = this.thread.subscribe(() => {
673
+ this.handleMessagesChange(this.thread.messages), this.notifySubscribers();
674
+ });
675
+ }
676
+ handleMessagesChange(t) {
677
+ if (t.length === 0) return;
678
+ const e = t[t.length - 1];
679
+ e.role === "assistant" && e.status.type === "complete" && this.autoFocusLastContent(t);
680
+ }
681
+ autoFocusLastContent(t) {
682
+ var e;
683
+ if (t.length !== 0 && !this._contentFocusRuntime.isActive)
684
+ for (let r = t.length - 1; r >= 0; r--) {
685
+ const s = t[r];
686
+ if (s.role === "assistant")
687
+ for (let a = s.content.length - 1; a >= 0; a--) {
688
+ const o = s.content[a], u = this.pluginRegistry.getRenderersByType(o.type);
689
+ if (u.length > 0 && ((e = u[0].capabilities) != null && e.supportsFocus)) {
690
+ this._contentFocusRuntime.focus(o, s, a, "detail");
691
+ return;
692
+ }
693
+ }
694
+ }
695
+ }
696
+ }
697
+ var I = { exports: {} }, _ = {};
698
+ /*
699
+ object-assign
700
+ (c) Sindre Sorhus
701
+ @license MIT
702
+ */
703
+ var R, A;
704
+ function Y() {
705
+ if (A) return R;
706
+ A = 1;
707
+ var n = Object.getOwnPropertySymbols, i = Object.prototype.hasOwnProperty, t = Object.prototype.propertyIsEnumerable;
708
+ function e(s) {
709
+ if (s == null)
710
+ throw new TypeError("Object.assign cannot be called with null or undefined");
711
+ return Object(s);
712
+ }
713
+ function r() {
714
+ try {
715
+ if (!Object.assign)
716
+ return !1;
717
+ var s = new String("abc");
718
+ if (s[5] = "de", Object.getOwnPropertyNames(s)[0] === "5")
719
+ return !1;
720
+ for (var a = {}, o = 0; o < 10; o++)
721
+ a["_" + String.fromCharCode(o)] = o;
722
+ var u = Object.getOwnPropertyNames(a).map(function(l) {
723
+ return a[l];
724
+ });
725
+ if (u.join("") !== "0123456789")
726
+ return !1;
727
+ var f = {};
728
+ return "abcdefghijklmnopqrst".split("").forEach(function(l) {
729
+ f[l] = l;
730
+ }), Object.keys(Object.assign({}, f)).join("") === "abcdefghijklmnopqrst";
731
+ } catch {
732
+ return !1;
733
+ }
734
+ }
735
+ return R = r() ? Object.assign : function(s, a) {
736
+ for (var o, u = e(s), f, l = 1; l < arguments.length; l++) {
737
+ o = Object(arguments[l]);
738
+ for (var c in o)
739
+ i.call(o, c) && (u[c] = o[c]);
740
+ if (n) {
741
+ f = n(o);
742
+ for (var h = 0; h < f.length; h++)
743
+ t.call(o, f[h]) && (u[f[h]] = o[f[h]]);
744
+ }
745
+ }
746
+ return u;
747
+ }, R;
748
+ }
749
+ /** @license React v17.0.2
750
+ * react-jsx-runtime.production.min.js
751
+ *
752
+ * Copyright (c) Facebook, Inc. and its affiliates.
753
+ *
754
+ * This source code is licensed under the MIT license found in the
755
+ * LICENSE file in the root directory of this source tree.
756
+ */
757
+ var P;
758
+ function Q() {
759
+ if (P) return _;
760
+ P = 1, Y();
761
+ var n = j, i = 60103;
762
+ if (_.Fragment = 60107, typeof Symbol == "function" && Symbol.for) {
763
+ var t = Symbol.for;
764
+ i = t("react.element"), _.Fragment = t("react.fragment");
765
+ }
766
+ var e = n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner, r = Object.prototype.hasOwnProperty, s = { key: !0, ref: !0, __self: !0, __source: !0 };
767
+ function a(o, u, f) {
768
+ var l, c = {}, h = null, p = null;
769
+ f !== void 0 && (h = "" + f), u.key !== void 0 && (h = "" + u.key), u.ref !== void 0 && (p = u.ref);
770
+ for (l in u) r.call(u, l) && !s.hasOwnProperty(l) && (c[l] = u[l]);
771
+ if (o && o.defaultProps) for (l in u = o.defaultProps, u) c[l] === void 0 && (c[l] = u[l]);
772
+ return { $$typeof: i, type: o, key: h, ref: p, props: c, _owner: e.current };
773
+ }
774
+ return _.jsx = a, _.jsxs = a, _;
775
+ }
776
+ var F;
777
+ function X() {
778
+ return F || (F = 1, I.exports = Q()), I.exports;
779
+ }
780
+ var Z = X();
781
+ const B = U(null);
782
+ function dt({ runtime: n, children: i }) {
783
+ return /* @__PURE__ */ Z.jsx(B.Provider, { value: n, children: i });
784
+ }
785
+ function tt() {
786
+ const n = J(B);
787
+ if (!n)
788
+ throw new Error("useAssistantRuntimeContext must be used within AssistantRuntimeProvider");
789
+ return n;
790
+ }
791
+ function y() {
792
+ return tt();
793
+ }
794
+ function lt() {
795
+ const n = y();
796
+ return {
797
+ switchToThread: (i) => n.threads.switchToThread(i),
798
+ switchToNewThread: () => n.threads.switchToNewThread(),
799
+ loadThreads: () => {
800
+ var i, t;
801
+ return (t = (i = n.threads).loadThreads) == null ? void 0 : t.call(i);
802
+ },
803
+ renameThread: (i, t) => {
804
+ var e, r;
805
+ return (r = (e = n.threads).renameThread) == null ? void 0 : r.call(e, i, t);
806
+ },
807
+ deleteThread: (i) => {
808
+ var t, e;
809
+ return (e = (t = n.threads).deleteThread) == null ? void 0 : e.call(t, i);
810
+ }
811
+ };
812
+ }
813
+ function ft() {
814
+ const n = y(), [i, t] = D(n.threads.getState());
815
+ return k(() => n.threads.subscribe(() => {
816
+ t(n.threads.getState());
817
+ }), [n]), i;
818
+ }
819
+ function et() {
820
+ return y().threads.getMainThread();
821
+ }
822
+ var C = { exports: {} }, v = {};
823
+ /**
824
+ * @license React
825
+ * use-sync-external-store-shim.production.js
826
+ *
827
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
828
+ *
829
+ * This source code is licensed under the MIT license found in the
830
+ * LICENSE file in the root directory of this source tree.
831
+ */
832
+ var L;
833
+ function st() {
834
+ if (L) return v;
835
+ L = 1;
836
+ var n = j;
837
+ function i(c, h) {
838
+ return c === h && (c !== 0 || 1 / c === 1 / h) || c !== c && h !== h;
839
+ }
840
+ var t = typeof Object.is == "function" ? Object.is : i, e = n.useState, r = n.useEffect, s = n.useLayoutEffect, a = n.useDebugValue;
841
+ function o(c, h) {
842
+ var p = h(), b = e({ inst: { value: p, getSnapshot: h } }), g = b[0].inst, S = b[1];
843
+ return s(
844
+ function() {
845
+ g.value = p, g.getSnapshot = h, u(g) && S({ inst: g });
846
+ },
847
+ [c, p, h]
848
+ ), r(
849
+ function() {
850
+ return u(g) && S({ inst: g }), c(function() {
851
+ u(g) && S({ inst: g });
852
+ });
853
+ },
854
+ [c]
855
+ ), a(p), p;
856
+ }
857
+ function u(c) {
858
+ var h = c.getSnapshot;
859
+ c = c.value;
860
+ try {
861
+ var p = h();
862
+ return !t(c, p);
863
+ } catch {
864
+ return !0;
865
+ }
866
+ }
867
+ function f(c, h) {
868
+ return h();
869
+ }
870
+ var l = typeof window > "u" || typeof window.document > "u" || typeof window.document.createElement > "u" ? f : o;
871
+ return v.useSyncExternalStore = n.useSyncExternalStore !== void 0 ? n.useSyncExternalStore : l, v;
872
+ }
873
+ var O;
874
+ function rt() {
875
+ return O || (O = 1, C.exports = st()), C.exports;
876
+ }
877
+ var N = rt();
878
+ function pt() {
879
+ const n = y();
880
+ return N.useSyncExternalStore(
881
+ (i) => n.subscribe(() => {
882
+ i();
883
+ }),
884
+ () => n.thread.messages,
885
+ () => n.thread.messages
886
+ );
887
+ }
888
+ function nt() {
889
+ return et().composer;
890
+ }
891
+ function gt() {
892
+ const n = nt();
893
+ return N.useSyncExternalStore(
894
+ (i) => n.subscribe(i),
895
+ () => n.getState(),
896
+ () => n.getState()
897
+ );
898
+ }
899
+ function mt(n, i) {
900
+ var s, a, o, u;
901
+ const e = y().pluginRegistry.getBestRendererForType(n);
902
+ if (!e)
903
+ return {
904
+ component: null,
905
+ auxiliaryComponent: null,
906
+ supportsFocus: !1,
907
+ supportsPreview: !1,
908
+ supportsFullscreen: !1
909
+ };
910
+ const r = i ? (s = e.auxiliary) == null ? void 0 : s[i] : null;
911
+ return {
912
+ component: e.component,
913
+ auxiliaryComponent: r,
914
+ supportsFocus: ((a = e.capabilities) == null ? void 0 : a.supportsFocus) ?? !1,
915
+ supportsPreview: ((o = e.capabilities) == null ? void 0 : o.supportsPreview) ?? !1,
916
+ supportsFullscreen: ((u = e.capabilities) == null ? void 0 : u.supportsFullscreen) ?? !1
917
+ };
918
+ }
919
+ function bt() {
920
+ const n = y(), [i, t] = D(n.contentFocus.state);
921
+ return k(() => n.contentFocus.subscribe(() => {
922
+ t(n.contentFocus.state);
923
+ }), [n]), {
924
+ ...i,
925
+ focus: (e, r, s, a) => n.contentFocus.focus(e, r, s, a),
926
+ blur: () => n.contentFocus.blur(),
927
+ toggle: (e, r, s, a) => n.contentFocus.toggle(e, r, s, a),
928
+ switchContext: (e) => n.contentFocus.switchContext(e),
929
+ focusNext: () => n.contentFocus.focusNext(n.thread.messages),
930
+ focusPrevious: () => n.contentFocus.focusPrevious(n.thread.messages)
931
+ };
932
+ }
933
+ function _t(n) {
934
+ const i = /* @__PURE__ */ new Map();
935
+ for (let e = 0; e < n.length; e++) {
936
+ const a = n[e].parentId ?? `__ungrouped_${e}`, o = i.get(a) ?? [];
937
+ o.push(e), i.set(a, o);
938
+ }
939
+ const t = [];
940
+ for (const [e, r] of i) {
941
+ const s = e.startsWith("__ungrouped_") ? void 0 : e, a = r.map((f) => n[f]), o = it(a), u = at(a);
942
+ t.push({ groupKey: s, indices: r, items: a, groupType: o, primaryType: u });
943
+ }
944
+ return t;
945
+ }
946
+ function it(n) {
947
+ if (n.length === 1) return "single-type";
948
+ if (new Set(n.map((t) => t.type)).size === 1) {
949
+ const t = n[0].type;
950
+ return t === "tool_call" ? "tool-calls" : t === "assistant_thought" ? "reasoning" : "single-type";
951
+ }
952
+ return "mixed";
953
+ }
954
+ function at(n) {
955
+ const i = /* @__PURE__ */ new Map();
956
+ for (const r of n)
957
+ i.set(r.type, (i.get(r.type) || 0) + 1);
958
+ let t = 0, e = n[0].type;
959
+ for (const [r, s] of i)
960
+ s > t && (t = s, e = r);
961
+ return e;
962
+ }
963
+ class yt {
964
+ getAllowedEvents() {
965
+ return null;
966
+ }
967
+ shouldProcessEvent(i) {
968
+ const t = this.getAllowedEvents();
969
+ return t ? t.includes(i) : !0;
970
+ }
971
+ async *stream(i) {
972
+ const { signal: t } = i, { url: e, options: r } = this.prepareRequest(i), s = await fetch(e, { ...r, signal: t });
973
+ if (!s.ok)
974
+ throw new Error(`HTTP error! status: ${s.status}`);
975
+ if (!s.body)
976
+ throw new Error("Response body is null");
977
+ yield* this.parseSSEStream(s.body, t);
978
+ }
979
+ async *parseSSEStream(i, t) {
980
+ const e = i.getReader(), r = new TextDecoder();
981
+ let s = "", a = null;
982
+ try {
983
+ for (; ; ) {
984
+ const { done: o, value: u } = await e.read();
985
+ if (o || t != null && t.aborted) break;
986
+ s += r.decode(u, { stream: !0 });
987
+ const f = s.split(`
988
+ `);
989
+ s = f.pop() || "";
990
+ for (const l of f) {
991
+ const c = l.trim();
992
+ if (!c) {
993
+ a = null;
994
+ continue;
995
+ }
996
+ if (c !== ": ping") {
997
+ if (c.startsWith("event:")) {
998
+ a = c.substring(6).trim();
999
+ continue;
1000
+ }
1001
+ if (c.startsWith("data:")) {
1002
+ const h = c.substring(5).trim();
1003
+ if (h === "eof" || c === "eof")
1004
+ break;
1005
+ try {
1006
+ const p = JSON.parse(h);
1007
+ if (a && this.shouldProcessEvent(a)) {
1008
+ const b = this.convertEvent({
1009
+ event: a,
1010
+ data: p
1011
+ });
1012
+ b && (yield b);
1013
+ }
1014
+ } catch {
1015
+ }
1016
+ a = null;
1017
+ }
1018
+ }
1019
+ }
1020
+ }
1021
+ } finally {
1022
+ e.releaseLock();
1023
+ }
1024
+ }
1025
+ }
1026
+ export {
1027
+ ht as AssistantRuntime,
1028
+ dt as AssistantRuntimeProvider,
1029
+ yt as BaseSSEStreamAdapter,
1030
+ m as BaseSubscribable,
1031
+ H as ComposerRuntime,
1032
+ W as PluginRegistry,
1033
+ w as ThreadListItemRuntime,
1034
+ K as ThreadListRuntime,
1035
+ T as ThreadRuntime,
1036
+ x as ThreadRuntimeCore,
1037
+ ct as generateId,
1038
+ E as generateMessageId,
1039
+ M as generateThreadId,
1040
+ _t as groupContentByParentId,
1041
+ y as useAssistantRuntime,
1042
+ nt as useComposer,
1043
+ gt as useComposerState,
1044
+ bt as useContentFocus,
1045
+ mt as useContentRenderer,
1046
+ et as useCurrentThread,
1047
+ pt as useMessages,
1048
+ lt as useThreadList,
1049
+ ft as useThreadListState
1050
+ };
1051
+ //# sourceMappingURL=index.js.map