@artooi/ag-ui-web-component 0.3.0 → 0.4.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/CHANGELOG.md +81 -1
- package/README.md +34 -6
- package/dist/ag-ui-web-component.bundle.js +36 -23
- package/dist/ag-ui-web-component.bundle.js.map +4 -4
- package/dist/core/ag_ui_chat.d.ts +7 -0
- package/dist/core/ag_ui_chat.d.ts.map +1 -1
- package/dist/core/agui_client.d.ts +18 -2
- package/dist/core/agui_client.d.ts.map +1 -1
- package/dist/core/create_http_agent.d.ts +9 -0
- package/dist/core/create_http_agent.d.ts.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +170 -21
- package/dist/index.js.map +3 -3
- package/dist/ui/confirmation_card.d.ts +10 -1
- package/dist/ui/confirmation_card.d.ts.map +1 -1
- package/dist/ui/prettify_tool_name.d.ts +11 -0
- package/dist/ui/prettify_tool_name.d.ts.map +1 -0
- package/dist/ui/render_markdown.d.ts +10 -1
- package/dist/ui/render_markdown.d.ts.map +1 -1
- package/dist/ui/styles.d.ts +1 -1
- package/dist/ui/styles.d.ts.map +1 -1
- package/package.json +2 -3
- package/src/core/ag_ui_chat.ts +92 -9
- package/src/core/agui_client.ts +63 -3
- package/src/core/create_http_agent.ts +23 -2
- package/src/index.ts +7 -2
- package/src/ui/confirmation_card.ts +22 -0
- package/src/ui/prettify_tool_name.ts +16 -0
- package/src/ui/render_markdown.ts +37 -11
- package/src/ui/styles.ts +13 -0
- package/src/version.ts +1 -1
|
@@ -36,6 +36,13 @@ export declare class AgUiChat extends HTMLElement {
|
|
|
36
36
|
agentFactory: AgentFactory;
|
|
37
37
|
/** Extra HTTP headers for the AG-UI endpoint (e.g. CSRF). */
|
|
38
38
|
headers: Record<string, string>;
|
|
39
|
+
/**
|
|
40
|
+
* Permit `<img>` in rendered assistant markdown. **Off by default**: a
|
|
41
|
+
* model-controlled image URL is fetched with no user interaction, which
|
|
42
|
+
* makes it a zero-click exfiltration channel for prompt-injected page
|
|
43
|
+
* data. Enable only when the content source is trusted.
|
|
44
|
+
*/
|
|
45
|
+
allowImages: boolean;
|
|
39
46
|
/** When true, destructive tools execute without a confirmation modal. */
|
|
40
47
|
autoConfirm: boolean;
|
|
41
48
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ag_ui_chat.d.ts","sourceRoot":"","sources":["../../src/core/ag_ui_chat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAW,IAAI,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EACL,YAAY,EAOb,MAAM,iBAAiB,CAAC;AAGzB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,KAAK,UAAU,EAAsB,MAAM,kCAAkC,CAAC;AAGvF,OAAO,EAAwB,KAAK,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,EAAoB,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAwB,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"ag_ui_chat.d.ts","sourceRoot":"","sources":["../../src/core/ag_ui_chat.ts"],"names":[],"mappings":"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"}
|
|
@@ -48,11 +48,19 @@ export interface AgUiClientHandlers {
|
|
|
48
48
|
onToolResult(toolCallId: string, content: string): void;
|
|
49
49
|
onRunEnd(): void;
|
|
50
50
|
onError(message: string): void;
|
|
51
|
+
/**
|
|
52
|
+
* Fired when the user cancelled the run ({@link AgUiClient.cancel}) — the
|
|
53
|
+
* deliberate-stop sibling of `onError`. Any partial assistant text already
|
|
54
|
+
* streamed stays valid; the host should keep the bubble and show a muted
|
|
55
|
+
* "stopped" affordance rather than an error. `onSettled` still follows.
|
|
56
|
+
*/
|
|
57
|
+
onCancelled(): void;
|
|
51
58
|
/**
|
|
52
59
|
* Fired exactly once when the whole interaction settles — after the run loop
|
|
53
60
|
* ends for any reason (a server-only round, frontend-tool rounds exhausted,
|
|
54
|
-
* or an error). The terminal guarantee that the UI returns
|
|
55
|
-
* indicator cleared, input re-enabled) no matter how the
|
|
61
|
+
* a cancellation, or an error). The terminal guarantee that the UI returns
|
|
62
|
+
* to rest (pending indicator cleared, input re-enabled) no matter how the
|
|
63
|
+
* run finished.
|
|
56
64
|
*/
|
|
57
65
|
onSettled(): void;
|
|
58
66
|
}
|
|
@@ -108,5 +116,13 @@ export declare class AgUiClient {
|
|
|
108
116
|
resume(): Promise<void>;
|
|
109
117
|
/** Append a frontend tool result to history (used by the resume path). */
|
|
110
118
|
addToolResult(toolCallId: string, content: string): void;
|
|
119
|
+
/**
|
|
120
|
+
* Cancel the in-flight run (AG-UI has no server cancel route — aborting the
|
|
121
|
+
* streaming request is the protocol's cancel; the server observes the
|
|
122
|
+
* disconnect). Safe to call with no run in flight. Partial text already
|
|
123
|
+
* streamed stays in history; {@link AgUiClientHandlers.onCancelled} fires
|
|
124
|
+
* instead of `onError`, and `onSettled` still follows.
|
|
125
|
+
*/
|
|
126
|
+
cancel(): void;
|
|
111
127
|
}
|
|
112
128
|
//# sourceMappingURL=agui_client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agui_client.d.ts","sourceRoot":"","sources":["../../src/core/agui_client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAoC,MAAM,eAAe,CAAC;AACrF,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAG1D,8DAA8D;AAC9D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxC;AAED,mFAAmF;AACnF,MAAM,WAAW,aAAa;IAC5B,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;AAEhF;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,IAAI,IAAI,CAAC;IACnB,yEAAyE;IACzE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,gFAAgF;IAChF,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,+EAA+E;IAC/E,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IACrC;;;;OAIG;IACH,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACxD,QAAQ,IAAI,IAAI,CAAC;IACjB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;;OAKG;IACH,SAAS,IAAI,IAAI,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,IAAI,EAAE,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,OAAO,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACrD,sEAAsE;IACtE,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,oEAAoE;IACpE,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,KAAK,IAAI,CAAC;CACpD;AAED;;;;;;GAMG;AACH,qBAAa,UAAU;;
|
|
1
|
+
{"version":3,"file":"agui_client.d.ts","sourceRoot":"","sources":["../../src/core/agui_client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAoC,MAAM,eAAe,CAAC;AACrF,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAG1D,8DAA8D;AAC9D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxC;AAED,mFAAmF;AACnF,MAAM,WAAW,aAAa;IAC5B,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;AAEhF;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,IAAI,IAAI,CAAC;IACnB,yEAAyE;IACzE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,gFAAgF;IAChF,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,+EAA+E;IAC/E,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IACrC;;;;OAIG;IACH,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACxD,QAAQ,IAAI,IAAI,CAAC;IACjB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;;OAKG;IACH,WAAW,IAAI,IAAI,CAAC;IACpB;;;;;;OAMG;IACH,SAAS,IAAI,IAAI,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,IAAI,EAAE,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,OAAO,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACrD,sEAAsE;IACtE,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,oEAAoE;IACpE,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,KAAK,IAAI,CAAC;CACpD;AAED;;;;;;GAMG;AACH,qBAAa,UAAU;;gBAWT,MAAM,EAAE,gBAAgB;IASpC,4CAA4C;IAC5C,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,wEAAwE;IACxE,IAAI,QAAQ,IAAI,SAAS,OAAO,EAAE,CAEjC;IAED;;;;;;OAMG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM1C;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,0EAA0E;IAC1E,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAKxD;;;;;;OAMG;IACH,MAAM,IAAI,IAAI;CAgHf"}
|
|
@@ -4,6 +4,15 @@ import type { Message } from "@ag-ui/core";
|
|
|
4
4
|
export interface HttpAgentOptions {
|
|
5
5
|
endpoint: string;
|
|
6
6
|
headers?: Record<string, string>;
|
|
7
|
+
/**
|
|
8
|
+
* Live header source, re-read on **every** request. `HttpAgent` bakes the
|
|
9
|
+
* static `headers` into its constructor and the element caches the agent
|
|
10
|
+
* for the whole conversation — so a rotated token (CSRF, short-lived JWT)
|
|
11
|
+
* would otherwise never reach the agent endpoint and a long session 401s
|
|
12
|
+
* mid-conversation. When set, the fetch wrapper overlays these values on
|
|
13
|
+
* each call; `headers` still seeds the initial/static configuration.
|
|
14
|
+
*/
|
|
15
|
+
getHeaders?: () => Record<string, string>;
|
|
7
16
|
/** Stable conversation id, so the agent's runs share a thread. */
|
|
8
17
|
threadId?: string;
|
|
9
18
|
/** Rehydrated history to seed the agent with (durable conversation). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create_http_agent.d.ts","sourceRoot":"","sources":["../../src/core/create_http_agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAa,MAAM,eAAe,CAAC;AAC9D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,0CAA0C;AAC1C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,eAAe,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;CACtC;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"create_http_agent.d.ts","sourceRoot":"","sources":["../../src/core/create_http_agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAa,MAAM,eAAe,CAAC;AAC9D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,0CAA0C;AAC1C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,eAAe,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;CACtC;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,aAAa,CA4BxE;AAED,2EAA2E;AAC3E,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,aAAa,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -15,8 +15,9 @@ export { createPageMapContext, type PageMap } from "./tools/page_map.js";
|
|
|
15
15
|
export { parseToolCatalog, type ToolCatalogEntry } from "./tools/parse_tool_catalog.js";
|
|
16
16
|
export { createRouteTools, type Route, type RouteMap, type RouteWithParams, } from "./tools/route_map.js";
|
|
17
17
|
export { createStateHookTools, type StateHook } from "./tools/state_hook.js";
|
|
18
|
-
export { type ConfirmationRequest, requestConfirmation } from "./ui/confirmation_card.js";
|
|
19
|
-
export {
|
|
18
|
+
export { type ConfirmationOptions, type ConfirmationRequest, requestConfirmation, } from "./ui/confirmation_card.js";
|
|
19
|
+
export { prettifyToolName } from "./ui/prettify_tool_name.js";
|
|
20
|
+
export { type RenderMarkdownOptions, renderMarkdown } from "./ui/render_markdown.js";
|
|
20
21
|
export { type SettledStatus, ToolCallCard, type ToolCallStatus, type ToolDisplayMode, } from "./ui/tool_call_card.js";
|
|
21
22
|
export { VERSION } from "./version.js";
|
|
22
23
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,WAAW,EACX,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,aAAa,GACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,QAAQ,EACR,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,YAAY,GAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,UAAU,EACV,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,aAAa,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,mBAAmB,GACpB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,KAAK,YAAY,EACjB,eAAe,EACf,KAAK,gBAAgB,GACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EACL,KAAK,YAAY,EACjB,cAAc,EACd,KAAK,qBAAqB,EAC1B,kBAAkB,EAClB,KAAK,YAAY,EACjB,oBAAoB,EACpB,cAAc,EACd,KAAK,aAAa,EAClB,oBAAoB,EACpB,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,aAAa,EACb,QAAQ,GACT,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,YAAY,EACZ,KAAK,gBAAgB,EACrB,SAAS,EACT,WAAW,EACX,aAAa,EACb,eAAe,EACf,cAAc,GACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC1E,YAAY,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,KAAK,UAAU,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,KAAK,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACxF,OAAO,EACL,gBAAgB,EAChB,KAAK,KAAK,EACV,KAAK,QAAQ,EACb,KAAK,eAAe,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,oBAAoB,EAAE,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,WAAW,EACX,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,aAAa,GACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,QAAQ,EACR,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,YAAY,GAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,UAAU,EACV,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,aAAa,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,mBAAmB,GACpB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,KAAK,YAAY,EACjB,eAAe,EACf,KAAK,gBAAgB,GACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EACL,KAAK,YAAY,EACjB,cAAc,EACd,KAAK,qBAAqB,EAC1B,kBAAkB,EAClB,KAAK,YAAY,EACjB,oBAAoB,EACpB,cAAc,EACd,KAAK,aAAa,EAClB,oBAAoB,EACpB,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,aAAa,EACb,QAAQ,GACT,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,YAAY,EACZ,KAAK,gBAAgB,EACrB,SAAS,EACT,WAAW,EACX,aAAa,EACb,eAAe,EACf,cAAc,GACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC1E,YAAY,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,KAAK,UAAU,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,KAAK,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACxF,OAAO,EACL,gBAAgB,EAChB,KAAK,KAAK,EACV,KAAK,QAAQ,EACb,KAAK,eAAe,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,oBAAoB,EAAE,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,mBAAmB,GACpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,KAAK,qBAAqB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACrF,OAAO,EACL,KAAK,aAAa,EAClB,YAAY,EACZ,KAAK,cAAc,EACnB,KAAK,eAAe,GACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -239,7 +239,7 @@ function actionButton(modifier, label) {
|
|
|
239
239
|
button.textContent = label;
|
|
240
240
|
return button;
|
|
241
241
|
}
|
|
242
|
-
function requestConfirmation(host, request) {
|
|
242
|
+
function requestConfirmation(host, request, options = {}) {
|
|
243
243
|
return new Promise((resolve) => {
|
|
244
244
|
const card = document.createElement("div");
|
|
245
245
|
card.className = "confirm";
|
|
@@ -256,7 +256,12 @@ function requestConfirmation(host, request) {
|
|
|
256
256
|
actions.className = "confirm-actions";
|
|
257
257
|
const cancel = actionButton("cancel", "Cancel");
|
|
258
258
|
const confirm = actionButton("confirm", "Confirm");
|
|
259
|
+
let settled = false;
|
|
259
260
|
const close = (accepted) => {
|
|
261
|
+
if (settled) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
settled = true;
|
|
260
265
|
cancel.disabled = true;
|
|
261
266
|
confirm.disabled = true;
|
|
262
267
|
card.setAttribute("data-resolved", accepted ? "confirmed" : "declined");
|
|
@@ -264,13 +269,27 @@ function requestConfirmation(host, request) {
|
|
|
264
269
|
};
|
|
265
270
|
cancel.addEventListener("click", () => close(false));
|
|
266
271
|
confirm.addEventListener("click", () => close(true));
|
|
272
|
+
options.signal?.addEventListener("abort", () => close(false), { once: true });
|
|
267
273
|
actions.append(cancel, confirm);
|
|
268
274
|
card.append(body, args, actions);
|
|
269
275
|
host.appendChild(card);
|
|
276
|
+
if (options.signal?.aborted === true) {
|
|
277
|
+
close(false);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
270
280
|
confirm.focus();
|
|
271
281
|
});
|
|
272
282
|
}
|
|
273
283
|
|
|
284
|
+
// src/ui/prettify_tool_name.ts
|
|
285
|
+
function prettifyToolName(name) {
|
|
286
|
+
const spaced = name.replace(/[._-]+/g, " ").trim();
|
|
287
|
+
if (spaced === "") {
|
|
288
|
+
return name;
|
|
289
|
+
}
|
|
290
|
+
return spaced.charAt(0).toUpperCase() + spaced.slice(1);
|
|
291
|
+
}
|
|
292
|
+
|
|
274
293
|
// node_modules/.pnpm/dompurify@3.4.7/node_modules/dompurify/dist/purify.es.mjs
|
|
275
294
|
function _arrayLikeToArray(r, a) {
|
|
276
295
|
(null == a || a > r.length) && (a = r.length);
|
|
@@ -2711,7 +2730,7 @@ var Vt = b.parse;
|
|
|
2711
2730
|
var Yt = x.lex;
|
|
2712
2731
|
|
|
2713
2732
|
// src/ui/render_markdown.ts
|
|
2714
|
-
|
|
2733
|
+
var parser = new q({ gfm: true, breaks: true });
|
|
2715
2734
|
var ALLOWED_TAGS = [
|
|
2716
2735
|
"a",
|
|
2717
2736
|
"p",
|
|
@@ -2742,13 +2761,18 @@ var ALLOWED_TAGS = [
|
|
|
2742
2761
|
"tbody",
|
|
2743
2762
|
"tr",
|
|
2744
2763
|
"th",
|
|
2745
|
-
"td"
|
|
2746
|
-
"img"
|
|
2764
|
+
"td"
|
|
2747
2765
|
];
|
|
2748
|
-
var ALLOWED_ATTR = ["href", "title", "class"
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2766
|
+
var ALLOWED_ATTR = ["href", "title", "class"];
|
|
2767
|
+
var ALLOWED_TAGS_WITH_IMAGES = [...ALLOWED_TAGS, "img"];
|
|
2768
|
+
var ALLOWED_ATTR_WITH_IMAGES = [...ALLOWED_ATTR, "src", "alt", "width", "height"];
|
|
2769
|
+
function renderMarkdown(text2, options) {
|
|
2770
|
+
const allowImages = options?.allowImages === true;
|
|
2771
|
+
const rendered = parser.parse(text2, { async: false });
|
|
2772
|
+
const clean = purify.sanitize(rendered, {
|
|
2773
|
+
ALLOWED_TAGS: allowImages ? ALLOWED_TAGS_WITH_IMAGES : ALLOWED_TAGS,
|
|
2774
|
+
ALLOWED_ATTR: allowImages ? ALLOWED_ATTR_WITH_IMAGES : ALLOWED_ATTR
|
|
2775
|
+
});
|
|
2752
2776
|
const template = document.createElement("template");
|
|
2753
2777
|
template.innerHTML = clean;
|
|
2754
2778
|
for (const anchor of template.content.querySelectorAll("a[href]")) {
|
|
@@ -3435,6 +3459,19 @@ var STYLES = `
|
|
|
3435
3459
|
cursor: default;
|
|
3436
3460
|
}
|
|
3437
3461
|
|
|
3462
|
+
/* The composer button doubles as the Stop control while a run is in flight. */
|
|
3463
|
+
.send[data-state="running"] {
|
|
3464
|
+
background: var(--ag-ui-muted);
|
|
3465
|
+
}
|
|
3466
|
+
|
|
3467
|
+
/* Muted "\u23F9 Stopped" line after a cancelled run \u2014 a note, not an error bubble. */
|
|
3468
|
+
.stopped-note {
|
|
3469
|
+
align-self: flex-start;
|
|
3470
|
+
color: var(--ag-ui-muted);
|
|
3471
|
+
font-size: 12px;
|
|
3472
|
+
padding: 2px 4px;
|
|
3473
|
+
}
|
|
3474
|
+
|
|
3438
3475
|
/* Inline confirmation card \u2014 lives in the transcript, no focus-stealing overlay. */
|
|
3439
3476
|
.confirm {
|
|
3440
3477
|
align-self: stretch;
|
|
@@ -3655,6 +3692,9 @@ var AgUiClient = class {
|
|
|
3655
3692
|
#getContext;
|
|
3656
3693
|
#executeTool;
|
|
3657
3694
|
#onPersist;
|
|
3695
|
+
// Set by cancel(); reset at the top of each #run(). Checked by the loop so
|
|
3696
|
+
// a cancel between frontend-tool rounds doesn't start another round.
|
|
3697
|
+
#cancelled = false;
|
|
3658
3698
|
constructor(config) {
|
|
3659
3699
|
this.#agent = config.agent;
|
|
3660
3700
|
this.#handlers = config.handlers;
|
|
@@ -3697,23 +3737,52 @@ var AgUiClient = class {
|
|
|
3697
3737
|
this.#agent.addMessage({ id: randomUUID(), role: "tool", content, toolCallId });
|
|
3698
3738
|
this.#onPersist(this.#agent.messages);
|
|
3699
3739
|
}
|
|
3740
|
+
/**
|
|
3741
|
+
* Cancel the in-flight run (AG-UI has no server cancel route — aborting the
|
|
3742
|
+
* streaming request is the protocol's cancel; the server observes the
|
|
3743
|
+
* disconnect). Safe to call with no run in flight. Partial text already
|
|
3744
|
+
* streamed stays in history; {@link AgUiClientHandlers.onCancelled} fires
|
|
3745
|
+
* instead of `onError`, and `onSettled` still follows.
|
|
3746
|
+
*/
|
|
3747
|
+
cancel() {
|
|
3748
|
+
this.#cancelled = true;
|
|
3749
|
+
this.#agent.abortRun();
|
|
3750
|
+
}
|
|
3700
3751
|
async #run() {
|
|
3752
|
+
this.#cancelled = false;
|
|
3701
3753
|
try {
|
|
3702
3754
|
await this.#runLoop();
|
|
3755
|
+
if (this.#cancelled) {
|
|
3756
|
+
this.#onCancelled();
|
|
3757
|
+
}
|
|
3703
3758
|
} catch (error) {
|
|
3704
|
-
this.#
|
|
3759
|
+
if (this.#cancelled || isAbortError(error)) {
|
|
3760
|
+
this.#onCancelled();
|
|
3761
|
+
} else {
|
|
3762
|
+
this.#handlers.onError(error instanceof Error ? error.message : String(error));
|
|
3763
|
+
}
|
|
3705
3764
|
} finally {
|
|
3706
3765
|
this.#handlers.onSettled();
|
|
3707
3766
|
}
|
|
3708
3767
|
}
|
|
3768
|
+
#onCancelled() {
|
|
3769
|
+
this.#onPersist(this.#agent.messages);
|
|
3770
|
+
this.#handlers.onCancelled();
|
|
3771
|
+
}
|
|
3709
3772
|
async #runLoop() {
|
|
3710
3773
|
for (let round = 0; round < MAX_TOOL_ROUNDS; round += 1) {
|
|
3774
|
+
if (this.#cancelled) {
|
|
3775
|
+
return;
|
|
3776
|
+
}
|
|
3711
3777
|
const pending = [];
|
|
3712
3778
|
await this.#agent.runAgent(
|
|
3713
3779
|
{ tools: this.#getTools(), context: this.#getContext() },
|
|
3714
3780
|
this.#buildSubscriber(pending)
|
|
3715
3781
|
);
|
|
3716
3782
|
this.#onPersist(this.#agent.messages);
|
|
3783
|
+
if (this.#cancelled) {
|
|
3784
|
+
return;
|
|
3785
|
+
}
|
|
3717
3786
|
if (this.#executeTool === null || pending.length === 0) {
|
|
3718
3787
|
return;
|
|
3719
3788
|
}
|
|
@@ -3773,6 +3842,9 @@ var AgUiClient = class {
|
|
|
3773
3842
|
};
|
|
3774
3843
|
}
|
|
3775
3844
|
};
|
|
3845
|
+
function isAbortError(error) {
|
|
3846
|
+
return error instanceof Error && error.name === "AbortError";
|
|
3847
|
+
}
|
|
3776
3848
|
|
|
3777
3849
|
// src/core/conversation_store.ts
|
|
3778
3850
|
import { randomUUID as randomUUID2 } from "@ag-ui/client";
|
|
@@ -3834,8 +3906,20 @@ function createHttpAgent(options) {
|
|
|
3834
3906
|
// HttpAgent invokes its configured fetch as a method (`this.fetch(...)`),
|
|
3835
3907
|
// which would rebind the global `fetch` to the agent instance and trigger
|
|
3836
3908
|
// "Illegal invocation" in browsers. Wrap it so `fetch` is always called as
|
|
3837
|
-
// a free function with the correct receiver.
|
|
3838
|
-
|
|
3909
|
+
// a free function with the correct receiver. The wrapper also overlays
|
|
3910
|
+
// `getHeaders()` per request, so header rotation (CSRF, short-lived JWT)
|
|
3911
|
+
// reaches the stream even though the agent instance is cached.
|
|
3912
|
+
fetch: (url, init) => {
|
|
3913
|
+
const fresh = options.getHeaders?.();
|
|
3914
|
+
if (fresh === void 0) {
|
|
3915
|
+
return fetch(url, init);
|
|
3916
|
+
}
|
|
3917
|
+
const headers = new Headers(init?.headers);
|
|
3918
|
+
for (const [name, value] of Object.entries(fresh)) {
|
|
3919
|
+
headers.set(name, value);
|
|
3920
|
+
}
|
|
3921
|
+
return fetch(url, { ...init, headers });
|
|
3922
|
+
},
|
|
3839
3923
|
// Spread conditionally: under `exactOptionalPropertyTypes` an explicit
|
|
3840
3924
|
// `undefined` is not assignable to these optional config fields.
|
|
3841
3925
|
...options.threadId !== void 0 ? { threadId: options.threadId } : {},
|
|
@@ -3850,6 +3934,13 @@ var AgUiChat = class extends HTMLElement {
|
|
|
3850
3934
|
agentFactory = createHttpAgent;
|
|
3851
3935
|
/** Extra HTTP headers for the AG-UI endpoint (e.g. CSRF). */
|
|
3852
3936
|
headers = {};
|
|
3937
|
+
/**
|
|
3938
|
+
* Permit `<img>` in rendered assistant markdown. **Off by default**: a
|
|
3939
|
+
* model-controlled image URL is fetched with no user interaction, which
|
|
3940
|
+
* makes it a zero-click exfiltration channel for prompt-injected page
|
|
3941
|
+
* data. Enable only when the content source is trusted.
|
|
3942
|
+
*/
|
|
3943
|
+
allowImages = false;
|
|
3853
3944
|
/** When true, destructive tools execute without a confirmation modal. */
|
|
3854
3945
|
autoConfirm = false;
|
|
3855
3946
|
/**
|
|
@@ -3948,6 +4039,13 @@ var AgUiChat = class extends HTMLElement {
|
|
|
3948
4039
|
#skillsMenu;
|
|
3949
4040
|
#skillHint;
|
|
3950
4041
|
#client = null;
|
|
4042
|
+
// Whether an interaction is in flight (first onRunStart → onSettled). Drives
|
|
4043
|
+
// the Send⇄Stop button: `agent.isRunning` is false between frontend-tool
|
|
4044
|
+
// rounds, but the user must still be able to stop there.
|
|
4045
|
+
#running = false;
|
|
4046
|
+
// Aborting this dismisses (declines) an open confirmation card when the run
|
|
4047
|
+
// is cancelled while the card awaits a decision. One controller per card.
|
|
4048
|
+
#confirmAbort = null;
|
|
3951
4049
|
#streamingBubble = null;
|
|
3952
4050
|
// Text deltas applied to the current streaming bubble. >1 ⇒ the message
|
|
3953
4051
|
// revealed progressively as it streamed, so the word reveal must not re-animate
|
|
@@ -4183,6 +4281,7 @@ var AgUiChat = class extends HTMLElement {
|
|
|
4183
4281
|
* in-memory run state, clear the transcript, and mint a new thread id.
|
|
4184
4282
|
*/
|
|
4185
4283
|
newChat() {
|
|
4284
|
+
this.#cancelRun();
|
|
4186
4285
|
this.conversationStore.clear(this.#threadId);
|
|
4187
4286
|
this.#client = null;
|
|
4188
4287
|
this.#streamingBubble = null;
|
|
@@ -4192,7 +4291,7 @@ var AgUiChat = class extends HTMLElement {
|
|
|
4192
4291
|
this.#initialMessages = [];
|
|
4193
4292
|
this.#messages.replaceChildren();
|
|
4194
4293
|
this.#threadId = this.conversationStore.threadId();
|
|
4195
|
-
this.#
|
|
4294
|
+
this.#setRunning(false);
|
|
4196
4295
|
}
|
|
4197
4296
|
/**
|
|
4198
4297
|
* Restore the conversation from the store on mount, then — if a navigating
|
|
@@ -4287,7 +4386,7 @@ var AgUiChat = class extends HTMLElement {
|
|
|
4287
4386
|
const bubble = document.createElement("div");
|
|
4288
4387
|
bubble.className = `message message--${role}`;
|
|
4289
4388
|
if (role === MESSAGE_ROLE.ASSISTANT) {
|
|
4290
|
-
bubble.innerHTML = renderMarkdown(content);
|
|
4389
|
+
bubble.innerHTML = renderMarkdown(content, { allowImages: this.allowImages });
|
|
4291
4390
|
} else {
|
|
4292
4391
|
bubble.textContent = content;
|
|
4293
4392
|
}
|
|
@@ -4337,7 +4436,13 @@ var AgUiChat = class extends HTMLElement {
|
|
|
4337
4436
|
this.#send.className = "send";
|
|
4338
4437
|
this.#send.type = "button";
|
|
4339
4438
|
this.#send.textContent = "Send";
|
|
4439
|
+
this.#send.setAttribute("aria-label", "Send");
|
|
4440
|
+
this.#send.dataset["state"] = "idle";
|
|
4340
4441
|
this.#send.addEventListener("click", () => {
|
|
4442
|
+
if (this.#running) {
|
|
4443
|
+
this.#cancelRun();
|
|
4444
|
+
return;
|
|
4445
|
+
}
|
|
4341
4446
|
void this.#submit();
|
|
4342
4447
|
});
|
|
4343
4448
|
this.#skillHint.className = "skill-hint";
|
|
@@ -4363,11 +4468,34 @@ var AgUiChat = class extends HTMLElement {
|
|
|
4363
4468
|
event.preventDefault();
|
|
4364
4469
|
return;
|
|
4365
4470
|
}
|
|
4471
|
+
if (event.key === "Escape" && this.#running) {
|
|
4472
|
+
event.preventDefault();
|
|
4473
|
+
this.#cancelRun();
|
|
4474
|
+
return;
|
|
4475
|
+
}
|
|
4366
4476
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
4367
4477
|
event.preventDefault();
|
|
4368
4478
|
void this.#submit();
|
|
4369
4479
|
}
|
|
4370
4480
|
}
|
|
4481
|
+
/**
|
|
4482
|
+
* Stop the in-flight run: decline any confirmation card awaiting a decision
|
|
4483
|
+
* (the loop is suspended on it), then cancel the client run — the abort
|
|
4484
|
+
* closes the streaming request, which is AG-UI's cancel (the server
|
|
4485
|
+
* observes the disconnect).
|
|
4486
|
+
*/
|
|
4487
|
+
#cancelRun() {
|
|
4488
|
+
this.#confirmAbort?.abort();
|
|
4489
|
+
this.#client?.cancel();
|
|
4490
|
+
}
|
|
4491
|
+
/** Swap the composer button between Send (idle) and Stop (running). */
|
|
4492
|
+
#setRunning(running) {
|
|
4493
|
+
this.#running = running;
|
|
4494
|
+
const label = running ? "Stop" : "Send";
|
|
4495
|
+
this.#send.textContent = label;
|
|
4496
|
+
this.#send.setAttribute("aria-label", label);
|
|
4497
|
+
this.#send.dataset["state"] = running ? "running" : "idle";
|
|
4498
|
+
}
|
|
4371
4499
|
async #submit() {
|
|
4372
4500
|
const content = this.#input.value.trim();
|
|
4373
4501
|
if (content === "") {
|
|
@@ -4395,6 +4523,10 @@ var AgUiChat = class extends HTMLElement {
|
|
|
4395
4523
|
const agent = this.agentFactory({
|
|
4396
4524
|
endpoint: this.endpoint,
|
|
4397
4525
|
headers: this.headers,
|
|
4526
|
+
// Live getter: the client is built once and cached, but a rotated
|
|
4527
|
+
// token must still reach every request — the factory's fetch wrapper
|
|
4528
|
+
// re-reads this on each call.
|
|
4529
|
+
getHeaders: () => this.headers,
|
|
4398
4530
|
threadId: this.#threadId,
|
|
4399
4531
|
initialMessages: this.#initialMessages
|
|
4400
4532
|
});
|
|
@@ -4435,9 +4567,13 @@ var AgUiChat = class extends HTMLElement {
|
|
|
4435
4567
|
if (typeof confirmText === "string") {
|
|
4436
4568
|
request.message = confirmText;
|
|
4437
4569
|
}
|
|
4438
|
-
|
|
4570
|
+
this.#confirmAbort = new AbortController();
|
|
4571
|
+
const decision = requestConfirmation(this.#messages, request, {
|
|
4572
|
+
signal: this.#confirmAbort.signal
|
|
4573
|
+
});
|
|
4439
4574
|
this.#messages.scrollTop = this.#messages.scrollHeight;
|
|
4440
4575
|
const accepted = await decision;
|
|
4576
|
+
this.#confirmAbort = null;
|
|
4441
4577
|
if (!accepted) {
|
|
4442
4578
|
const message = "User declined the action.";
|
|
4443
4579
|
card.settle(TOOL_CALL_STATUS.DECLINED, message);
|
|
@@ -4472,7 +4608,7 @@ var AgUiChat = class extends HTMLElement {
|
|
|
4472
4608
|
#handlers() {
|
|
4473
4609
|
return {
|
|
4474
4610
|
onRunStart: () => {
|
|
4475
|
-
this.#
|
|
4611
|
+
this.#setRunning(true);
|
|
4476
4612
|
this.#showPending();
|
|
4477
4613
|
},
|
|
4478
4614
|
onTextDelta: (buffer) => {
|
|
@@ -4501,22 +4637,34 @@ var AgUiChat = class extends HTMLElement {
|
|
|
4501
4637
|
},
|
|
4502
4638
|
onRunEnd: () => {
|
|
4503
4639
|
this.#hidePending();
|
|
4504
|
-
this.#send.disabled = false;
|
|
4505
4640
|
this.#streamingBubble = null;
|
|
4506
4641
|
},
|
|
4507
4642
|
onError: (message) => {
|
|
4508
4643
|
this.#hidePending();
|
|
4509
4644
|
this.#revealWords(this.appendMessage(MESSAGE_ROLE.ASSISTANT, `\u26A0\uFE0F ${message}`));
|
|
4510
|
-
this.#
|
|
4645
|
+
this.#streamingBubble = null;
|
|
4646
|
+
},
|
|
4647
|
+
onCancelled: () => {
|
|
4648
|
+
this.#hidePending();
|
|
4649
|
+
this.#appendStoppedNote();
|
|
4511
4650
|
this.#streamingBubble = null;
|
|
4512
4651
|
},
|
|
4513
4652
|
onSettled: () => {
|
|
4514
4653
|
this.#hidePending();
|
|
4515
|
-
this.#
|
|
4654
|
+
this.#setRunning(false);
|
|
4516
4655
|
this.#streamingBubble = null;
|
|
4517
4656
|
}
|
|
4518
4657
|
};
|
|
4519
4658
|
}
|
|
4659
|
+
/** A muted "⏹ Stopped" line in the transcript (distinct from the ⚠️ error bubble). */
|
|
4660
|
+
#appendStoppedNote() {
|
|
4661
|
+
const note = document.createElement("div");
|
|
4662
|
+
note.className = "stopped-note";
|
|
4663
|
+
note.setAttribute("role", "status");
|
|
4664
|
+
note.textContent = "\u23F9 Stopped";
|
|
4665
|
+
this.#messages.appendChild(note);
|
|
4666
|
+
this.#messages.scrollTop = this.#messages.scrollHeight;
|
|
4667
|
+
}
|
|
4520
4668
|
/**
|
|
4521
4669
|
* Show a "thinking" indicator while the agent is being awaited — both the
|
|
4522
4670
|
* silent stretch before the first token and the gap after a tool result
|
|
@@ -4549,7 +4697,7 @@ var AgUiChat = class extends HTMLElement {
|
|
|
4549
4697
|
this.#streamingBubble = this.appendMessage(MESSAGE_ROLE.ASSISTANT, "");
|
|
4550
4698
|
this.#streamDeltas = 0;
|
|
4551
4699
|
}
|
|
4552
|
-
this.#streamingBubble.innerHTML = renderMarkdown(buffer);
|
|
4700
|
+
this.#streamingBubble.innerHTML = renderMarkdown(buffer, { allowImages: this.allowImages });
|
|
4553
4701
|
this.#messages.scrollTop = this.#messages.scrollHeight;
|
|
4554
4702
|
return this.#streamingBubble;
|
|
4555
4703
|
}
|
|
@@ -4565,7 +4713,7 @@ var AgUiChat = class extends HTMLElement {
|
|
|
4565
4713
|
return existing;
|
|
4566
4714
|
}
|
|
4567
4715
|
const labelled = this.#resolveTool(call.name)?.parameters[X_SUMMARY_KEY];
|
|
4568
|
-
const summary = typeof labelled === "string" ? labelled : this.toolSummaries[call.name] ?? this.#toolCatalog[call.name];
|
|
4716
|
+
const summary = typeof labelled === "string" ? labelled : this.toolSummaries[call.name] ?? this.#toolCatalog[call.name] ?? prettifyToolName(call.name);
|
|
4569
4717
|
const card = new ToolCallCard(call.name, call.args, this.toolDisplay, summary);
|
|
4570
4718
|
this.#toolCards.set(call.id, card);
|
|
4571
4719
|
this.#messages.appendChild(card.element);
|
|
@@ -4738,7 +4886,7 @@ function setControlValue(el, value) {
|
|
|
4738
4886
|
}
|
|
4739
4887
|
|
|
4740
4888
|
// src/version.ts
|
|
4741
|
-
var VERSION = "0.
|
|
4889
|
+
var VERSION = "0.4.0";
|
|
4742
4890
|
export {
|
|
4743
4891
|
AgUiChat,
|
|
4744
4892
|
AgUiClient,
|
|
@@ -4772,6 +4920,7 @@ export {
|
|
|
4772
4920
|
prefersReducedMotion,
|
|
4773
4921
|
pressButton,
|
|
4774
4922
|
pressThenClick,
|
|
4923
|
+
prettifyToolName,
|
|
4775
4924
|
renderMarkdown,
|
|
4776
4925
|
requestConfirmation,
|
|
4777
4926
|
scrollIntoCenterView,
|