@smooai/chat-widget 0.12.0 → 0.13.0
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/README.md +1 -0
- package/dist/chat-widget.global.js +205 -12
- package/dist/chat-widget.global.js.map +1 -1
- package/dist/index.d.ts +72 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +205 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/config.ts +11 -0
- package/src/conversation.ts +93 -1
- package/src/element.ts +138 -14
- package/src/index.ts +2 -0
- package/src/styles.ts +42 -0
package/dist/index.d.ts
CHANGED
|
@@ -134,6 +134,16 @@ interface ChatWidgetConfig {
|
|
|
134
134
|
* `require*` flags are ignored and the pre-chat form is skipped.
|
|
135
135
|
*/
|
|
136
136
|
allowAnonymous?: boolean;
|
|
137
|
+
/**
|
|
138
|
+
* Show the agent's tool activity (grep / read_file / bash / knowledge_search…)
|
|
139
|
+
* as inline chips interleaved with its prose, mirroring the smooth daemon SPA.
|
|
140
|
+
*
|
|
141
|
+
* Defaults to **`false`**: for a customer-facing support widget, surfacing raw
|
|
142
|
+
* tool calls to an end-user is usually undesirable, so tool activity is hidden
|
|
143
|
+
* and only the assistant's prose renders. Enable it for internal / power-user
|
|
144
|
+
* surfaces where seeing what the agent did mid-turn is valuable.
|
|
145
|
+
*/
|
|
146
|
+
showToolActivity?: boolean;
|
|
137
147
|
/** Theme overrides. */
|
|
138
148
|
theme?: ChatWidgetTheme;
|
|
139
149
|
}
|
|
@@ -219,6 +229,36 @@ declare function createWidgetStore(agentId: string): StoreApi<WidgetStore>;
|
|
|
219
229
|
*/
|
|
220
230
|
declare function httpBaseFromWsEndpoint(endpoint: string): string | null;
|
|
221
231
|
type Role = 'user' | 'assistant';
|
|
232
|
+
/**
|
|
233
|
+
* One tool invocation within an assistant turn. Mirrors the smooth daemon SPA's
|
|
234
|
+
* `ToolCall` (`crates/smooth-web/web/src/operator.ts`): opens `done: false` on the
|
|
235
|
+
* tool call and resolves on the tool result.
|
|
236
|
+
*/
|
|
237
|
+
interface ToolCall {
|
|
238
|
+
/** Stable id for keyed rendering (assigned when the call opens). */
|
|
239
|
+
id: string;
|
|
240
|
+
name: string;
|
|
241
|
+
/** Raw arguments, JSON-stringified. */
|
|
242
|
+
args: string;
|
|
243
|
+
/** Present once the tool resolves. */
|
|
244
|
+
result?: string;
|
|
245
|
+
isError?: boolean;
|
|
246
|
+
done: boolean;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* One ordered segment of an assistant turn: a run of prose, or a tool call.
|
|
250
|
+
* Preserves the interleave order the model produced (say a bit → call a tool →
|
|
251
|
+
* say a bit → …) so the UI can render tool chips INLINE where the model called
|
|
252
|
+
* them. Mirrors the daemon SPA's `MessageBlock`. Only populated when the widget
|
|
253
|
+
* is configured with `showToolActivity: true`.
|
|
254
|
+
*/
|
|
255
|
+
type MessageBlock = {
|
|
256
|
+
kind: 'text';
|
|
257
|
+
text: string;
|
|
258
|
+
} | {
|
|
259
|
+
kind: 'tool';
|
|
260
|
+
tool: ToolCall;
|
|
261
|
+
};
|
|
222
262
|
interface ChatMessage {
|
|
223
263
|
id: string;
|
|
224
264
|
role: Role;
|
|
@@ -226,6 +266,12 @@ interface ChatMessage {
|
|
|
226
266
|
text: string;
|
|
227
267
|
/** True while an assistant message is still streaming. */
|
|
228
268
|
streaming: boolean;
|
|
269
|
+
/**
|
|
270
|
+
* Ordered text + tool segments, interleaved as the model produced them. Present
|
|
271
|
+
* only on assistant messages when `showToolActivity` is enabled (absent
|
|
272
|
+
* otherwise — the default popover renders `text` alone, byte-for-byte unchanged).
|
|
273
|
+
*/
|
|
274
|
+
blocks?: MessageBlock[];
|
|
229
275
|
/**
|
|
230
276
|
* Sources that grounded an assistant answer, when the terminal
|
|
231
277
|
* `eventual_response` carried any. Optional + back-compatible: absent when
|
|
@@ -542,6 +588,10 @@ declare class SmoothAgentChatElement extends HTMLElement {
|
|
|
542
588
|
/** How many chars of {@link streamTarget} are currently shown. */
|
|
543
589
|
private displayedLength;
|
|
544
590
|
private rafId;
|
|
591
|
+
/** Block structure signature of the last-rendered streaming message (tool chips
|
|
592
|
+
* only — text growth doesn't change it), so a chip add/resolve forces a rebuild
|
|
593
|
+
* while plain trailing-text growth stays on the fast reveal path. */
|
|
594
|
+
private prevBlockSig;
|
|
545
595
|
constructor();
|
|
546
596
|
connectedCallback(): void;
|
|
547
597
|
disconnectedCallback(): void;
|
|
@@ -605,6 +655,14 @@ declare class SmoothAgentChatElement extends HTMLElement {
|
|
|
605
655
|
* rebuild via {@link renderMessages}.
|
|
606
656
|
*/
|
|
607
657
|
private handleMessages;
|
|
658
|
+
/** True when an assistant message's turn invoked at least one tool. */
|
|
659
|
+
private hasToolBlocks;
|
|
660
|
+
/** Signature that changes only when a tool chip is added or resolved (text growth is 'x'). */
|
|
661
|
+
private blockSig;
|
|
662
|
+
/** The live (last) text block for a tool turn, else the whole message text. */
|
|
663
|
+
private tailText;
|
|
664
|
+
/** Reveal-binding key — composite for a tool-turn tail (so a new trailing block rebinds), else msg id. */
|
|
665
|
+
private tailKey;
|
|
608
666
|
private renderMessages;
|
|
609
667
|
/**
|
|
610
668
|
* Render (or clear) the mid-conversation suggested-reply chips under the
|
|
@@ -624,6 +682,19 @@ declare class SmoothAgentChatElement extends HTMLElement {
|
|
|
624
682
|
* doesn't restart the reveal from zero), then resumes the loop.
|
|
625
683
|
*/
|
|
626
684
|
private bindReveal;
|
|
685
|
+
/**
|
|
686
|
+
* Render a tool-activity assistant turn as an ordered strip: prose bubbles and
|
|
687
|
+
* inline tool chips in the order the model produced them (mirrors the daemon
|
|
688
|
+
* SPA's `blocks`). The live trailing text block (while streaming) binds to the
|
|
689
|
+
* rAF reveal; earlier/finalized text blocks render as sanitized markdown.
|
|
690
|
+
*/
|
|
691
|
+
private renderAssistantBlocks;
|
|
692
|
+
/**
|
|
693
|
+
* A single tool-activity chip: icon + tool name + status (running… / done / error),
|
|
694
|
+
* with a truncated args preview. Tool name/args are set via `textContent` so a
|
|
695
|
+
* tool payload can never inject markup.
|
|
696
|
+
*/
|
|
697
|
+
private buildToolChip;
|
|
627
698
|
/** Start the rAF loop if it isn't already running. */
|
|
628
699
|
private ensureRevealLoop;
|
|
629
700
|
/**
|
|
@@ -778,5 +849,5 @@ declare function computeFingerprint(): string;
|
|
|
778
849
|
*/
|
|
779
850
|
declare function getOrCreateFingerprint(get: () => string | null, set: (fp: string) => void): string;
|
|
780
851
|
//#endregion
|
|
781
|
-
export { type ChatMessage, type ChatWidgetConfig, type ChatWidgetMode, type ChatWidgetTheme, type Citation, type ConnectionStatus, type ConsentState, ConversationController, type ConversationEvents, ELEMENT_TAG, type IdentityRestore, type IdentityState, PERSIST_VERSION, type PersistedWidgetState, type RestorableConversation, type Role, SmoothAgentChatElement, type UserInfo, type WidgetStore, computeFingerprint, createWidgetStore, defineChatWidget, getOrCreateFingerprint, httpBaseFromWsEndpoint, initChatWidgetLoader, mountChatWidget, mountFullPageChat, storageKey };
|
|
852
|
+
export { type ChatMessage, type ChatWidgetConfig, type ChatWidgetMode, type ChatWidgetTheme, type Citation, type ConnectionStatus, type ConsentState, ConversationController, type ConversationEvents, ELEMENT_TAG, type IdentityRestore, type IdentityState, type MessageBlock, PERSIST_VERSION, type PersistedWidgetState, type RestorableConversation, type Role, SmoothAgentChatElement, type ToolCall, type UserInfo, type WidgetStore, computeFingerprint, createWidgetStore, defineChatWidget, getOrCreateFingerprint, httpBaseFromWsEndpoint, initChatWidgetLoader, mountChatWidget, mountFullPageChat, storageKey };
|
|
782
853
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/config.ts","../src/persistence.ts","../src/conversation.ts","../src/element.ts","../src/loader-core.ts","../src/fingerprint.ts"],"mappings":";;;;UASiB,eAAA;;EAEb,IAAA;;EAEA,UAAA;EAJ4B;EAM5B,OAAA;EAN4B;EAQ5B,WAAA;EAJA;EAMA,SAAA;EAFA;EAIA,eAAA;EAAA;EAEA,mBAAA;EAEA;EAAA,UAAA;EAIA;EAFA,cAAA;EAUA;EARA,MAAA;EAYA;EANA,iBAAA;EAMsB;EAJtB,qBAAA;EAesB;EAbtB,kBAAA;EAasB;EAXtB,sBAAA;AAAA;;;;;;;;;KAWQ,cAAA;AAAA,UAEK,gBAAA;EAyBb;;;;EApBA,QAAA;EA6BmD;;;;EAxBnD,IAAA,GAAO,cAAA;EAsCP;EApCA,OAAA;EA+CA;EA7CA,SAAA;EAiDA;;;;;;EA1CA,OAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/config.ts","../src/persistence.ts","../src/conversation.ts","../src/element.ts","../src/loader-core.ts","../src/fingerprint.ts"],"mappings":";;;;UASiB,eAAA;;EAEb,IAAA;;EAEA,UAAA;EAJ4B;EAM5B,OAAA;EAN4B;EAQ5B,WAAA;EAJA;EAMA,SAAA;EAFA;EAIA,eAAA;EAAA;EAEA,mBAAA;EAEA;EAAA,UAAA;EAIA;EAFA,cAAA;EAUA;EARA,MAAA;EAYA;EANA,iBAAA;EAMsB;EAJtB,qBAAA;EAesB;EAbtB,kBAAA;EAasB;EAXtB,sBAAA;AAAA;;;;;;;;;KAWQ,cAAA;AAAA,UAEK,gBAAA;EAyBb;;;;EApBA,QAAA;EA6BmD;;;;EAxBnD,IAAA,GAAO,cAAA;EAsCP;EApCA,OAAA;EA+CA;EA7CA,SAAA;EAiDA;;;;;;EA1CA,OAAA;EA+EA;EA7EA,QAAA;EA6EuB;EA3EvB,SAAA;;EAEA,SAAA;;ACxDJ;;;;AAAyC;ED+DrC,WAAA;IAAgB,MAAA;IAAgB,SAAA;IAAmB,SAAA;EAAA;EC1DnD;ED4DA,WAAA;ECxDA;ED0DA,QAAA;EC1DS;ED4DT,sBAAA;ECxD0B;ED0D1B,SAAA;EC1D0B;;;;;EDgE1B,YAAA;ECtDa;;;;ED2Db,cAAA;ECtDS;;;;;ED4DT,oBAAA;EC7DA;ED+DA,WAAA;EC9DA;EDgEA,YAAA;ECxDA;ED0DA,YAAA;ECtDA;;AAAkB;AAItB;;EDwDI,YAAA;ECnDkC;;;;;;ED0DlC,cAAA;EC1DsB;;;;ED+DtB,gBAAA;EC5DA;;;;EDiEA,cAAA;ECrDQ;;;;AAAuD;AAiBnE;;;;ED8CI,gBAAA;ECwEY;EDtEZ,KAAA,GAAQ,eAAe;AAAA;;;;cCjId,eAAA;AD2Bb;AAAA,UCxBiB,YAAA;EACb,UAAA;EACA,QAAA;EDsBsB;ECpBtB,aAAA;EDsB6B;ECpB7B,SAAA;AAAA;;UAIa,aAAA;EACb,IAAA;EACA,KAAA;EACA,KAAA;AAAA;;;;;UAOa,oBAAA;EACb,OAAA,SAAgB,eAAA;EDuCmC;ECrCnD,SAAA;EACA,QAAA,EAAU,aAAA;EACV,OAAA,EAAS,YAAA;ED2CT;;;;;;;ECnCA,aAAA;EDuEA;ECrEA,sBAAA;ED+EA;EC7EA,kBAAA;AAAA;;UAIa,kBAAA;EACb,YAAA,GAAe,SAAA;;EAEf,aAAA,GAAgB,QAAA,EAAU,aAAA;;EAE1B,UAAA,GAAa,OAAA,EAAS,YAAY;EAjDG;EAmDrC,gBAAA,GAAmB,KAAA,iBAAsB,SAAA;EACzC,qBAAA,GAAwB,EAAA;EApDa;AAGzC;;;;;;;EA0DI,YAAA;AAAA;AAAA,KAGQ,WAAA,GAAc,oBAAA,GAAuB,kBAAkB;AAnDnE;AAAA,iBAoEgB,UAAA,CAAW,OAAe;;;;;;iBAsH1B,iBAAA,CAAkB,OAAA,WAAkB,QAAQ,CAAC,WAAA;;;;;;;;;;iBCtL7C,sBAAA,CAAuB,QAAgB;AAAA,KAmB3C,IAAA;;;;;;UAOK,QAAA;EF4Bb;EE1BA,EAAA;EACA,IAAA;EF0CA;EExCA,IAAA;EF4CA;EE1CA,MAAA;EACA,OAAA;EACA,IAAA;AAAA;;;;;;AF6EuB;;KEnEf,YAAA;EAAiB,IAAA;EAAc,IAAA;AAAA;EAAmB,IAAA;EAAc,IAAA,EAAM,QAAQ;AAAA;AAAA,UAEzE,WAAA;EACb,EAAA;EACA,IAAA,EAAM,IAAA;ED/DmB;ECiEzB,IAAA;ED/DA;ECiEA,SAAA;ED7DA;;AAAS;AAIb;;EC+DI,MAAA,GAAS,YAAA;ED/DiB;;;;;AAGrB;ECmEL,SAAA,GAAY,QAAA;ED5DqB;;;;;;ECmEjC,WAAA;AAAA;AAAA,KAGQ,gBAAA;;;;;;;;;;ADrDU;AAItB;KC8DY,SAAA;EAEF,IAAA;EACA,MAAA;EACA,iBAAA;EACA,iBAAA,uBDhEN;ECkEM,IAAA;IAAS,OAAA;IAAkB,iBAAA;EAAA,GDhEpB;ECkEP,KAAA;EACA,iBAAA;AAAA;EAEF,IAAA;EAAiB,MAAA;EAAiB,iBAAA;AAAA;EAEhC,IAAA,iBDxDE;EC0DF,aAAA;EAEA,eAAA,UD5DyD;EC8DzD,IAAA,EAAM,MAAM,mBD7CI;EC+ChB,MAAA,WD/CgC;ECiDhC,MAAA;IAAW,KAAA;IAAe,OAAA;EAAA;AAAA;AAAA,UAWnB,QAAA;EACb,IAAA;EACA,KAAA;EACA,KAAA;EA/HmD;EAiInD,OAAA;IAAY,UAAA;IAAqB,QAAA;EAAA;AAAA;AA9GrB;AAAA,UAkHC,sBAAA;EACb,cAAA;EACA,SAAA;EACA,cAAA;EACA,OAAA;AAAA;;;;;;AAtGI;KA+GI,eAAA;EACJ,KAAA;AAAA;EAEA,KAAA;EAAyB,KAAA;AAAA;EACzB,KAAA;EAAqB,KAAA;EAAe,OAAA;AAAA;EACpC,KAAA;EAAwB,KAAA;EAAe,OAAA;EAA0B,iBAAA;EAA4B,KAAA;EAAgB,iBAAA;AAAA;EAC7G,KAAA;EAAoB,KAAA;EAAe,OAAA;AAAA;EACnC,KAAA;EAAoB,KAAA;AAAA;EACpB,KAAA;EAAmB,KAAA;EAAe,aAAA,EAAe,sBAAsB;AAAA;EACvE,KAAA;EAAgB,OAAA;AAAA;AAAA,UAEP,kBAAA;EAjFW;EAmFxB,UAAA,GAAa,QAAA,EAAU,WAAA;EAtEf;EAwER,QAAA,GAAW,MAAA,EAAQ,gBAAA,EAAkB,MAAA;;EAErC,WAAA,IAAe,SAAA,EAAW,SAAA;EAxEpB;EA0EN,iBAAA,IAAqB,KAAA,EAAO,eAAA;AAAA;AAAA,cAqHnB,sBAAA;EAAA,iBACQ,MAAA;EAAA,iBACA,MAAA;EAAA,iBACA,KAAA;EAAA,QACT,MAAA;EAAA,QACA,SAAA;EAAA,iBACS,QAAA;EAAA,QACT,MAAA;EAAA,QACA,GAAA;EA3LF;EAAA,QA6LE,eAAA;EAAA,QACA,SAAA;EAxLF;;EAAA,QA2LE,wBAAA;EAAA,QACA,eAAA;EAxLS;;;AAAsB;AAW3C;;;;EAXqB,QAiMT,eAAA;EApLR;;;;;;EAAA,iBA2LiB,QAAA;cAEL,MAAA,EAAQ,gBAAA,EAAkB,MAAA,EAAQ,kBAAA,EAAoB,KAAA,GAAQ,QAAA,CAAS,WAAA;EAAA,IAyB/E,gBAAA,IAAoB,gBAAA;;EAKxB,QAAA,IAAY,QAAA,CAAS,WAAA;EAnNrB;EAwNA,mBAAA;EAtNA;EA2NA,oBAAA;EA1NO;EAgOP,WAAA,CAAY,IAAA,EAAM,QAAA;EAAA,QAcV,YAAA;EAAA,QAKA,kBAAA;EAAA,IAKJ,sBAAA,IAA0B,eAAA;EAvO6C;EA4O3E,SAAA,CAAU,IAAA;EAjPN;EAuPJ,WAAA,CAAY,QAAA;EAtPR;;;;;;;EAmQJ,iBAAA,CAAkB,MAAA,EAAQ,MAAA;EAlQuF;EAiRjH,kBAAA;EAAA,QAaQ,MAAA;EAAA,QAKA,SAAA;EAAA,QAKA,YAAA;EAtSgB;EAAA,QA4ShB,WAAA;EA3Se;;;;;;AACI;AAE/B;;;;;;EAH2B,QAgUf,eAAA;EArTmC;;;;;;EAAA,QA4UnC,uBAAA;EAhVG;EAAA,QAyVG,YAAA;EAvVd;;;;;;;AAE2C;AAqH/C;;;;EAkPU,OAAA,IAAW,OAAA;EAjNkE;;;;;;EAAA,QAqQ3E,QAAA;EAvKkB;EAAA,QA+KZ,YAAA;EAkHY;;;;;EAAA,QA7EZ,mBAAA;EAlVG;EAAA,QA+VH,aAAA;EA7VG;;;;EAAA,QAoXH,SAAA;EA/WN;EAAA,QA+XM,cAAA;EA5XN;;;;EAqZF,IAAA,CAAK,IAAA,WAAe,OAAA;;UAuFlB,eAAA;EAtdI;;;;EAqjBN,kBAAA,CAAmB,KAAA,UAAe,OAAA,qBAAqC,OAAA;EArjBX;EAulB5D,iBAAA,CAAkB,IAAA,WAAe,OAAA;EA9jBf;EAAA,QA2lBV,eAAA;EAtlBF;;;;;EA4nBN,mBAAA,CAAoB,SAAA,WAAoB,OAAA;EA5mBlC;EAkoBZ,qBAAA;EA/mBQ;EAonBR,UAAA;AAAA;;;cCz/BS,WAAA;AAAA,cAuNA,sBAAA,SAA+B,WAAA;EAAA,WAC7B,kBAAA;EAAA,iBAIM,IAAA;EAAA,QACT,UAAA;EAAA,QACA,SAAA;EAAA,QACA,IAAA;EAAA,QACA,QAAA;EAAA,QACA,MAAA;EAAA,QACA,OAAA;EHlJR;EAAA,QGoJQ,iBAAA;EHhJR;EAAA,QGkJQ,OAAA;EH1IR;EAAA,QG4IQ,cAAA;EHhIR;EAAA,QGkIQ,oBAAA;EHnHR;EAAA,QGqHQ,QAAA;EHnHA;EAAA,QGqHA,SAAA;EAAA,QACA,WAAA;;UAEA,eAAA;;UAEA,gBAAA;EF3P6B;EAAA,QE6P7B,MAAA;EAAA,QAGA,OAAA;EAAA,QACA,UAAA;EAAA,QACA,UAAA;EAAA,QACA,QAAA;EAAA,QACA,KAAA;EAAA,QACA,OAAA;EAAA,QACA,OAAA;EAAA,QACA,aAAA;EFhQR;EAAA,QEyQQ,cAAA;EFvQC;EAAA,QEyQD,WAAA;EFrQK;EAAA,QEuQL,YAAA;;UAEA,eAAA;EAAA,QACA,KAAA;EFxQR;;;EAAA,QE4QQ,YAAA;;EAOR,iBAAA;EAKA,oBAAA;EAOA,wBAAA;EFnRU;;;;EE2RV,SAAA,CAAU,MAAA,EAAQ,OAAA,CAAQ,gBAAA;EF9RV;EEuShB,QAAA;EFpSA;EE8SA,SAAA;EAAA,QAOQ,UAAA;EAAA,QAuCA,MAAA;EFnVR;;;;AAIkB;EAJlB,QEwjBQ,eAAA;EFhjBuB;;;;;;;EAAA,QE0qBvB,gBAAA;EFrqBR;EAAA,QE+zBQ,UAAA;EF/zBK;;;;;;;;AAYD;AAGhB;;;;EAfiB,QEs1BL,cAAA;EFtzBI;EAAA,QEu2BJ,mBAAA;;UAqCA,YAAA;EAAA,QAMA,aAAA;EF5xBI;EAAA,QEwyBJ,QAAA;;;;;;;AFxyB4D;;;;UEyzB5D,cAAA;ED/+B0B;EAAA,QCmhC1B,aAAA;EDnhC2C;EAAA,QCwhC3C,QAAA;EDrgCA;EAAA,QC2gCA,QAAA;;UASA,OAAA;EAAA,QAKA,cAAA;EDlhCK;;;;;;;;;EAAA,QCmmCL,iBAAA;ED1lCJ;EAAA,QConCI,oBAAA;ED1mCA;;;;;EAAA,QCmnCA,UAAA;EDnnCkD;;;;AAA4B;AAE1F;EAF8D,QC+oClD,qBAAA;;;;;;UA+BA,aAAA;ED3qCR;EAAA,QCqsCQ,gBAAA;EDpsCF;;;;;;EAAA,QCotCE,UAAA;ED5rCR;EAAA,QCwtCQ,UAAA;EDxtCG;AAGf;;;;AAA4B;AAa5B;;;EAhBe,QCwuCH,oBAAA;EDttCF;EAAA,QCiuCE,WAAA;ED/tCF;;;;;;EAAA,QC8uCE,cAAA;EDtuCJ;EAAA,QCkvCI,QAAA;EAAA,QAaA,cAAA;EAAA,QAOA,SAAA;EDlwCF;;;;;;EAAA,QC4wCE,aAAA;EAAA,QAkEA,YAAA;EAAA,QAgBA,mBAAA;EAAA,QAMA,MAAA;AAAA;;iBAYI,gBAAA;;;;;iBAUA,eAAA,CAAgB,MAAA,EAAQ,gBAAA,EAAkB,MAAA,GAAQ,WAAA,GAA8B,sBAAA;;;;ADl2CnD;AAI7C;;;;;;;;;AAIW;iBCg3CK,iBAAA,CAAkB,MAAA,EAAQ,IAAA,CAAK,gBAAA,WAA2B,MAAA,GAAQ,WAAA,GAA8B,sBAAA;;;;;;;AH1hDhH;;;;;;;;;;;;;;;;;;;AAgC0B;AAW1B;;;;AAA0B;AAE1B;;;;;;;iBImCgB,oBAAA;;;;;;;AJhFhB;;;;;;;;;;;;;;;;;;;AAgC0B;AAW1B;;;;AAA0B;AAE1B;;;;;;;;;iBKmDgB,kBAAA;;;;;;iBAUA,sBAAA,CAAuB,GAAA,uBAA0B,GAAA,GAAM,EAAA"}
|
package/dist/index.js
CHANGED
|
@@ -342,6 +342,7 @@ function resolveConfig(config) {
|
|
|
342
342
|
collectConsent: config.collectConsent ?? true,
|
|
343
343
|
allowChatRestore: config.allowChatRestore ?? true,
|
|
344
344
|
allowAnonymous: config.allowAnonymous ?? false,
|
|
345
|
+
showToolActivity: config.showToolActivity ?? false,
|
|
345
346
|
theme: {
|
|
346
347
|
text: theme.text ?? "#f8fafc",
|
|
347
348
|
background: theme.background ?? "#040d30",
|
|
@@ -807,6 +808,59 @@ function wireMessageToChat(m, idx) {
|
|
|
807
808
|
streaming: false
|
|
808
809
|
};
|
|
809
810
|
}
|
|
811
|
+
let toolSeq = 0;
|
|
812
|
+
const nextToolId = () => `tool-${++toolSeq}`;
|
|
813
|
+
/** Grow the trailing text block, or open a new one if the last block was a tool. */
|
|
814
|
+
function growTextBlock(blocks, text) {
|
|
815
|
+
if (!text) return;
|
|
816
|
+
const last = blocks[blocks.length - 1];
|
|
817
|
+
if (last && last.kind === "text") last.text += text;
|
|
818
|
+
else blocks.push({
|
|
819
|
+
kind: "text",
|
|
820
|
+
text
|
|
821
|
+
});
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Fold a `stream_chunk` node-state into the ordered block list, returning `true`
|
|
825
|
+
* when the chunk carried tool activity.
|
|
826
|
+
*
|
|
827
|
+
* Tool activity rides `state.rawResponse.toolCall` / `state.rawResponse.toolResult`
|
|
828
|
+
* — **NOT** `state.toolResult`. Reading the wrong path leaves every chip stuck on
|
|
829
|
+
* "running…" forever (the exact bug the daemon SPA hit and this mirror avoids).
|
|
830
|
+
*/
|
|
831
|
+
function applyToolChunk(blocks, state) {
|
|
832
|
+
const raw = state?.rawResponse;
|
|
833
|
+
if (!raw || typeof raw !== "object") return false;
|
|
834
|
+
const call = raw.toolCall;
|
|
835
|
+
const res = raw.toolResult;
|
|
836
|
+
if (call) {
|
|
837
|
+
const args = typeof call.arguments === "string" ? call.arguments : JSON.stringify(call.arguments ?? {});
|
|
838
|
+
blocks.push({
|
|
839
|
+
kind: "tool",
|
|
840
|
+
tool: {
|
|
841
|
+
id: nextToolId(),
|
|
842
|
+
name: call.name ?? "",
|
|
843
|
+
args,
|
|
844
|
+
done: false
|
|
845
|
+
}
|
|
846
|
+
});
|
|
847
|
+
return true;
|
|
848
|
+
}
|
|
849
|
+
if (res) {
|
|
850
|
+
const result = typeof res.result === "string" ? res.result : JSON.stringify(res.result ?? "");
|
|
851
|
+
for (let i = blocks.length - 1; i >= 0; i--) {
|
|
852
|
+
const b = blocks[i];
|
|
853
|
+
if (b && b.kind === "tool" && b.tool.name === (res.name ?? "") && !b.tool.done) {
|
|
854
|
+
b.tool.done = true;
|
|
855
|
+
b.tool.isError = !!res.isError;
|
|
856
|
+
b.tool.result = result;
|
|
857
|
+
break;
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
return true;
|
|
861
|
+
}
|
|
862
|
+
return false;
|
|
863
|
+
}
|
|
810
864
|
var ConversationController = class {
|
|
811
865
|
constructor(config, events, store) {
|
|
812
866
|
_defineProperty(this, "config", void 0);
|
|
@@ -1153,11 +1207,13 @@ var ConversationController = class {
|
|
|
1153
1207
|
text: trimmed,
|
|
1154
1208
|
streaming: false
|
|
1155
1209
|
});
|
|
1210
|
+
const showTools = this.config.showToolActivity === true;
|
|
1156
1211
|
const assistant = {
|
|
1157
1212
|
id: this.nextId("a"),
|
|
1158
1213
|
role: "assistant",
|
|
1159
1214
|
text: "",
|
|
1160
|
-
streaming: true
|
|
1215
|
+
streaming: true,
|
|
1216
|
+
blocks: showTools ? [] : void 0
|
|
1161
1217
|
};
|
|
1162
1218
|
this.messages.push(assistant);
|
|
1163
1219
|
this.emitMessages();
|
|
@@ -1172,8 +1228,11 @@ var ConversationController = class {
|
|
|
1172
1228
|
const token = event.token ?? event.data?.token ?? "";
|
|
1173
1229
|
if (token) {
|
|
1174
1230
|
assistant.text += token;
|
|
1231
|
+
if (showTools && assistant.blocks) growTextBlock(assistant.blocks, token);
|
|
1175
1232
|
this.emitMessages();
|
|
1176
1233
|
}
|
|
1234
|
+
} else if (showTools && event.type === "stream_chunk") {
|
|
1235
|
+
if (assistant.blocks && applyToolChunk(assistant.blocks, event.data?.state)) this.emitMessages();
|
|
1177
1236
|
} else this.handleTurnEvent(event);
|
|
1178
1237
|
const inner = (await turn).data?.data;
|
|
1179
1238
|
const finalText = extractFinalText(inner?.response);
|
|
@@ -1183,6 +1242,7 @@ var ConversationController = class {
|
|
|
1183
1242
|
if (citations.length > 0) assistant.citations = citations;
|
|
1184
1243
|
const suggestions = extractSuggestions(inner?.response);
|
|
1185
1244
|
if (suggestions.length > 0) assistant.suggestions = suggestions;
|
|
1245
|
+
if (assistant.blocks && !assistant.blocks.some((b) => b.kind === "tool")) assistant.blocks = void 0;
|
|
1186
1246
|
assistant.streaming = false;
|
|
1187
1247
|
this.emitMessages();
|
|
1188
1248
|
} catch (err) {
|
|
@@ -1494,6 +1554,7 @@ function buildStyles(theme, mode = "popover") {
|
|
|
1494
1554
|
--sac-bg: ${theme.background};
|
|
1495
1555
|
--sac-primary: ${theme.primary};
|
|
1496
1556
|
--sac-primary-text: ${theme.primaryText};
|
|
1557
|
+
--sac-secondary: ${theme.secondary};
|
|
1497
1558
|
--sac-assistant-bubble: ${theme.assistantBubble};
|
|
1498
1559
|
--sac-assistant-bubble-text: ${theme.assistantBubbleText};
|
|
1499
1560
|
--sac-user-bubble: ${theme.userBubble};
|
|
@@ -1806,6 +1867,47 @@ ${mode === "fullpage" ? `
|
|
|
1806
1867
|
}
|
|
1807
1868
|
@keyframes sac-blink { to { opacity: 0 } }
|
|
1808
1869
|
|
|
1870
|
+
/* Interleaved tool-activity strip (gated by showToolActivity): prose bubbles
|
|
1871
|
+
and inline tool chips stacked in the order the model produced them. */
|
|
1872
|
+
.blocks { display: flex; flex-direction: column; align-items: flex-start; gap: 7px; }
|
|
1873
|
+
.blocks .bubble { align-self: flex-start; }
|
|
1874
|
+
.toolchip {
|
|
1875
|
+
display: inline-flex;
|
|
1876
|
+
align-items: center;
|
|
1877
|
+
gap: 6px;
|
|
1878
|
+
max-width: 100%;
|
|
1879
|
+
padding: 5px 10px;
|
|
1880
|
+
border-radius: 99px;
|
|
1881
|
+
font-size: 12px;
|
|
1882
|
+
line-height: 1.3;
|
|
1883
|
+
color: color-mix(in srgb, var(--sac-text) 78%, transparent);
|
|
1884
|
+
background: color-mix(in srgb, var(--sac-text) 6%, transparent);
|
|
1885
|
+
border: 1px solid color-mix(in srgb, var(--sac-text) 12%, transparent);
|
|
1886
|
+
animation: sac-msg-in .3s var(--sac-ease) both;
|
|
1887
|
+
}
|
|
1888
|
+
.toolchip .ti { display: inline-flex; flex: none; opacity: .8; }
|
|
1889
|
+
.toolchip .ti svg { width: 13px; height: 13px; }
|
|
1890
|
+
.toolchip .tn { font-weight: 600; letter-spacing: .01em; }
|
|
1891
|
+
.toolchip .ts { opacity: .7; }
|
|
1892
|
+
.toolchip .ta {
|
|
1893
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
1894
|
+
font-size: 11px;
|
|
1895
|
+
opacity: .6;
|
|
1896
|
+
overflow: hidden;
|
|
1897
|
+
text-overflow: ellipsis;
|
|
1898
|
+
white-space: nowrap;
|
|
1899
|
+
min-width: 0;
|
|
1900
|
+
}
|
|
1901
|
+
.toolchip.running { border-color: color-mix(in srgb, var(--sac-primary) 45%, transparent); }
|
|
1902
|
+
.toolchip.running .ts { color: var(--sac-primary); opacity: 1; animation: sac-typing 1.3s ease-in-out infinite; }
|
|
1903
|
+
.toolchip.done .ts::before { content: '✓ '; }
|
|
1904
|
+
.toolchip.error {
|
|
1905
|
+
color: var(--sac-secondary);
|
|
1906
|
+
border-color: color-mix(in srgb, var(--sac-secondary) 50%, transparent);
|
|
1907
|
+
background: color-mix(in srgb, var(--sac-secondary) 10%, transparent);
|
|
1908
|
+
}
|
|
1909
|
+
.toolchip.error .ts::before { content: '! '; }
|
|
1910
|
+
|
|
1809
1911
|
/* ─────────────── Rendered markdown (assistant bubbles / snippets) ─────────── */
|
|
1810
1912
|
/* The renderer (markdown.ts) emits a small allowlisted set of tags; these rules
|
|
1811
1913
|
keep them legible inside the tight Aurora-Glass bubble + citation card. */
|
|
@@ -2248,7 +2350,8 @@ const OBSERVED = [
|
|
|
2248
2350
|
"greeting",
|
|
2249
2351
|
"start-open",
|
|
2250
2352
|
"mode",
|
|
2251
|
-
"hide-branding"
|
|
2353
|
+
"hide-branding",
|
|
2354
|
+
"show-tool-activity"
|
|
2252
2355
|
];
|
|
2253
2356
|
/**
|
|
2254
2357
|
* Inline SVG icons (static, trusted strings — never interpolated with user data).
|
|
@@ -2270,7 +2373,9 @@ const ICON = {
|
|
|
2270
2373
|
/** Identity-intake interrupt — a person. */
|
|
2271
2374
|
user: `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="8.2" r="3.4" stroke="currentColor" stroke-width="1.7"/><path d="M5.5 19.5c.8-3.1 3.4-4.8 6.5-4.8s5.7 1.7 6.5 4.8" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/></svg>`,
|
|
2272
2375
|
/** Tool-confirmation interrupt — a shield. */
|
|
2273
|
-
shield: `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 3 5 6v5c0 4.4 3 7.2 7 8.5 4-1.3 7-4.1 7-8.5V6l-7-3Z" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/><path d="m9 11.5 2 2 4-4" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/></svg
|
|
2376
|
+
shield: `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 3 5 6v5c0 4.4 3 7.2 7 8.5 4-1.3 7-4.1 7-8.5V6l-7-3Z" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/><path d="m9 11.5 2 2 4-4" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/></svg>`,
|
|
2377
|
+
/** Tool-activity chip — a wrench. */
|
|
2378
|
+
tool: `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M14.7 6.3a3.5 3.5 0 0 0-4.6 4.3l-5 5a1.6 1.6 0 0 0 2.3 2.3l5-5a3.5 3.5 0 0 0 4.3-4.6l-2 2-1.7-.3-.3-1.7 2-2Z" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/></svg>`
|
|
2274
2379
|
};
|
|
2275
2380
|
/**
|
|
2276
2381
|
* The identity_intake card: the fields the agent requested (pre-chat form field
|
|
@@ -2436,6 +2541,7 @@ var SmoothAgentChatElement = class extends HTMLElement {
|
|
|
2436
2541
|
_defineProperty(this, "streamTarget", "");
|
|
2437
2542
|
_defineProperty(this, "displayedLength", 0);
|
|
2438
2543
|
_defineProperty(this, "rafId", 0);
|
|
2544
|
+
_defineProperty(this, "prevBlockSig", "");
|
|
2439
2545
|
this.root = this.attachShadow({ mode: "open" });
|
|
2440
2546
|
}
|
|
2441
2547
|
connectedCallback() {
|
|
@@ -2507,6 +2613,7 @@ var SmoothAgentChatElement = class extends HTMLElement {
|
|
|
2507
2613
|
collectConsent: this.overrides.collectConsent,
|
|
2508
2614
|
allowChatRestore: this.overrides.allowChatRestore,
|
|
2509
2615
|
allowAnonymous: this.overrides.allowAnonymous,
|
|
2616
|
+
showToolActivity: this.overrides.showToolActivity ?? this.hasAttribute("show-tool-activity"),
|
|
2510
2617
|
theme
|
|
2511
2618
|
};
|
|
2512
2619
|
}
|
|
@@ -3046,15 +3153,38 @@ var SmoothAgentChatElement = class extends HTMLElement {
|
|
|
3046
3153
|
const prev = this.messages;
|
|
3047
3154
|
const last = messages[messages.length - 1];
|
|
3048
3155
|
const prevLast = prev[prev.length - 1];
|
|
3049
|
-
const structural = messages.length !== prev.length || !last || !prevLast || last.id !== prevLast.id || last.role !== prevLast.role || last.streaming !== prevLast.streaming || !!last.streaming && !prevLast.text && !!last.text;
|
|
3156
|
+
const structural = messages.length !== prev.length || !last || !prevLast || last.id !== prevLast.id || last.role !== prevLast.role || last.streaming !== prevLast.streaming || !!last.streaming && !prevLast.text && !!last.text || this.blockSig(last) !== this.prevBlockSig;
|
|
3050
3157
|
this.messages = messages;
|
|
3051
|
-
|
|
3052
|
-
|
|
3158
|
+
this.prevBlockSig = this.blockSig(last);
|
|
3159
|
+
if (!structural && last && last.streaming && this.tailKey(last) === this.streamMsgId) {
|
|
3160
|
+
this.streamTarget = this.tailText(last);
|
|
3053
3161
|
this.ensureRevealLoop();
|
|
3054
3162
|
return;
|
|
3055
3163
|
}
|
|
3056
3164
|
this.renderMessages();
|
|
3057
3165
|
}
|
|
3166
|
+
/** True when an assistant message's turn invoked at least one tool. */
|
|
3167
|
+
hasToolBlocks(m) {
|
|
3168
|
+
return !!m?.blocks?.some((b) => b.kind === "tool");
|
|
3169
|
+
}
|
|
3170
|
+
/** Signature that changes only when a tool chip is added or resolved (text growth is 'x'). */
|
|
3171
|
+
blockSig(m) {
|
|
3172
|
+
if (!m?.blocks) return "";
|
|
3173
|
+
return m.blocks.map((b) => b.kind === "tool" ? `t:${b.tool.id}:${b.tool.done ? 1 : 0}` : "x").join("|");
|
|
3174
|
+
}
|
|
3175
|
+
/** The live (last) text block for a tool turn, else the whole message text. */
|
|
3176
|
+
tailText(m) {
|
|
3177
|
+
if (this.hasToolBlocks(m) && m.blocks) {
|
|
3178
|
+
const last = m.blocks[m.blocks.length - 1];
|
|
3179
|
+
return last?.kind === "text" ? last.text : "";
|
|
3180
|
+
}
|
|
3181
|
+
return m.text;
|
|
3182
|
+
}
|
|
3183
|
+
/** Reveal-binding key — composite for a tool-turn tail (so a new trailing block rebinds), else msg id. */
|
|
3184
|
+
tailKey(m) {
|
|
3185
|
+
if (this.hasToolBlocks(m) && m.blocks) return `${m.id}#${m.blocks.length - 1}`;
|
|
3186
|
+
return m.id;
|
|
3187
|
+
}
|
|
3058
3188
|
renderMessages() {
|
|
3059
3189
|
if (!this.messagesEl) return;
|
|
3060
3190
|
this.resetReveal();
|
|
@@ -3075,6 +3205,11 @@ var SmoothAgentChatElement = class extends HTMLElement {
|
|
|
3075
3205
|
this.messagesEl.appendChild(chips);
|
|
3076
3206
|
}
|
|
3077
3207
|
for (const msg of this.messages) {
|
|
3208
|
+
if (msg.role === "assistant" && this.hasToolBlocks(msg)) {
|
|
3209
|
+
this.messagesEl.appendChild(this.buildRow("assistant", this.renderAssistantBlocks(msg)));
|
|
3210
|
+
if (!msg.streaming && msg.citations && msg.citations.length > 0) this.messagesEl.appendChild(this.renderSources(msg.citations));
|
|
3211
|
+
continue;
|
|
3212
|
+
}
|
|
3078
3213
|
const bubble = document.createElement("div");
|
|
3079
3214
|
bubble.className = `bubble ${msg.role}`;
|
|
3080
3215
|
if (msg.role === "assistant" && msg.streaming && !msg.text) {
|
|
@@ -3132,19 +3267,77 @@ var SmoothAgentChatElement = class extends HTMLElement {
|
|
|
3132
3267
|
* doesn't restart the reveal from zero), then resumes the loop.
|
|
3133
3268
|
*/
|
|
3134
3269
|
bindReveal(msg, bubble) {
|
|
3135
|
-
const
|
|
3270
|
+
const key = this.tailKey(msg);
|
|
3271
|
+
const target = this.tailText(msg);
|
|
3272
|
+
const carryOver = key === this.streamMsgId ? Math.min(this.displayedLength, target.length) : 0;
|
|
3136
3273
|
this.streamBubbleEl = bubble;
|
|
3137
|
-
this.streamMsgId =
|
|
3138
|
-
this.streamTarget =
|
|
3274
|
+
this.streamMsgId = key;
|
|
3275
|
+
this.streamTarget = target;
|
|
3139
3276
|
this.displayedLength = carryOver;
|
|
3140
3277
|
if (this.prefersReducedMotion()) {
|
|
3141
|
-
this.displayedLength =
|
|
3142
|
-
bubble.textContent =
|
|
3278
|
+
this.displayedLength = target.length;
|
|
3279
|
+
bubble.textContent = target;
|
|
3143
3280
|
return;
|
|
3144
3281
|
}
|
|
3145
|
-
bubble.textContent =
|
|
3282
|
+
bubble.textContent = target.slice(0, this.displayedLength);
|
|
3146
3283
|
this.ensureRevealLoop();
|
|
3147
3284
|
}
|
|
3285
|
+
/**
|
|
3286
|
+
* Render a tool-activity assistant turn as an ordered strip: prose bubbles and
|
|
3287
|
+
* inline tool chips in the order the model produced them (mirrors the daemon
|
|
3288
|
+
* SPA's `blocks`). The live trailing text block (while streaming) binds to the
|
|
3289
|
+
* rAF reveal; earlier/finalized text blocks render as sanitized markdown.
|
|
3290
|
+
*/
|
|
3291
|
+
renderAssistantBlocks(msg) {
|
|
3292
|
+
const wrap = document.createElement("div");
|
|
3293
|
+
wrap.className = "blocks";
|
|
3294
|
+
const blocks = msg.blocks ?? [];
|
|
3295
|
+
const lastIdx = blocks.length - 1;
|
|
3296
|
+
blocks.forEach((block, i) => {
|
|
3297
|
+
if (block.kind === "tool") {
|
|
3298
|
+
wrap.appendChild(this.buildToolChip(block.tool));
|
|
3299
|
+
return;
|
|
3300
|
+
}
|
|
3301
|
+
const bubble = document.createElement("div");
|
|
3302
|
+
bubble.className = "bubble assistant";
|
|
3303
|
+
if (msg.streaming && i === lastIdx) {
|
|
3304
|
+
bubble.classList.add("cursor");
|
|
3305
|
+
this.bindReveal(msg, bubble);
|
|
3306
|
+
} else {
|
|
3307
|
+
bubble.classList.add("md");
|
|
3308
|
+
bubble.innerHTML = renderMarkdown(block.text);
|
|
3309
|
+
}
|
|
3310
|
+
wrap.appendChild(bubble);
|
|
3311
|
+
});
|
|
3312
|
+
return wrap;
|
|
3313
|
+
}
|
|
3314
|
+
/**
|
|
3315
|
+
* A single tool-activity chip: icon + tool name + status (running… / done / error),
|
|
3316
|
+
* with a truncated args preview. Tool name/args are set via `textContent` so a
|
|
3317
|
+
* tool payload can never inject markup.
|
|
3318
|
+
*/
|
|
3319
|
+
buildToolChip(tool) {
|
|
3320
|
+
const chip = document.createElement("div");
|
|
3321
|
+
chip.className = `toolchip ${tool.done ? tool.isError ? "error" : "done" : "running"}`;
|
|
3322
|
+
chip.setAttribute("part", "tool-chip");
|
|
3323
|
+
const icon = document.createElement("span");
|
|
3324
|
+
icon.className = "ti";
|
|
3325
|
+
icon.innerHTML = ICON.tool;
|
|
3326
|
+
const name = document.createElement("span");
|
|
3327
|
+
name.className = "tn";
|
|
3328
|
+
name.textContent = tool.name || "tool";
|
|
3329
|
+
const status = document.createElement("span");
|
|
3330
|
+
status.className = "ts";
|
|
3331
|
+
status.textContent = tool.done ? tool.isError ? "error" : "done" : "running…";
|
|
3332
|
+
chip.append(icon, name, status);
|
|
3333
|
+
if (tool.args && tool.args !== "{}" && tool.args !== "\"\"") {
|
|
3334
|
+
const args = document.createElement("span");
|
|
3335
|
+
args.className = "ta";
|
|
3336
|
+
args.textContent = tool.args.length > 80 ? `${tool.args.slice(0, 80)}…` : tool.args;
|
|
3337
|
+
chip.appendChild(args);
|
|
3338
|
+
}
|
|
3339
|
+
return chip;
|
|
3340
|
+
}
|
|
3148
3341
|
/** Start the rAF loop if it isn't already running. */
|
|
3149
3342
|
ensureRevealLoop() {
|
|
3150
3343
|
if (this.prefersReducedMotion() || typeof requestAnimationFrame !== "function") {
|