@artooi/ag-ui-web-component 0.1.1 → 0.2.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 (109) hide show
  1. package/CHANGELOG.md +99 -1
  2. package/README.md +242 -50
  3. package/dist/ag-ui-web-component.bundle.js +451 -46
  4. package/dist/ag-ui-web-component.bundle.js.map +4 -4
  5. package/dist/constants.d.ts +34 -0
  6. package/dist/constants.d.ts.map +1 -1
  7. package/dist/{ag_ui_chat.d.ts → core/ag_ui_chat.d.ts} +63 -6
  8. package/dist/core/ag_ui_chat.d.ts.map +1 -0
  9. package/dist/{agui_client.d.ts → core/agui_client.d.ts} +13 -0
  10. package/dist/core/agui_client.d.ts.map +1 -0
  11. package/dist/core/conversation_store.d.ts.map +1 -0
  12. package/dist/core/create_http_agent.d.ts.map +1 -0
  13. package/dist/core/define_ag_ui_chat.d.ts.map +1 -0
  14. package/dist/dom/animations.d.ts +71 -0
  15. package/dist/dom/animations.d.ts.map +1 -0
  16. package/dist/{dom_driver.d.ts → dom/dom_driver.d.ts} +7 -1
  17. package/dist/dom/dom_driver.d.ts.map +1 -0
  18. package/dist/dom/native_setter.d.ts +5 -0
  19. package/dist/dom/native_setter.d.ts.map +1 -0
  20. package/dist/index.d.ts +19 -16
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +3934 -373
  23. package/dist/index.js.map +4 -4
  24. package/dist/skills/fill_template.d.ts +17 -0
  25. package/dist/skills/fill_template.d.ts.map +1 -0
  26. package/dist/skills/parse_skills.d.ts +8 -0
  27. package/dist/skills/parse_skills.d.ts.map +1 -0
  28. package/dist/skills/skill.d.ts +24 -0
  29. package/dist/skills/skill.d.ts.map +1 -0
  30. package/dist/{client_tool_registry.d.ts → tools/client_tool_registry.d.ts} +6 -1
  31. package/dist/tools/client_tool_registry.d.ts.map +1 -0
  32. package/dist/tools/is_destructive.d.ts.map +1 -0
  33. package/dist/tools/is_navigates.d.ts.map +1 -0
  34. package/dist/tools/page_map.d.ts.map +1 -0
  35. package/dist/tools/route_map.d.ts +40 -0
  36. package/dist/tools/route_map.d.ts.map +1 -0
  37. package/dist/tools/state_hook.d.ts.map +1 -0
  38. package/dist/ui/confirmation_card.d.ts +22 -0
  39. package/dist/ui/confirmation_card.d.ts.map +1 -0
  40. package/dist/ui/render_markdown.d.ts +13 -0
  41. package/dist/ui/render_markdown.d.ts.map +1 -0
  42. package/dist/ui/reveal_words.d.ts +8 -0
  43. package/dist/ui/reveal_words.d.ts.map +1 -0
  44. package/dist/ui/skills_menu.d.ts +35 -0
  45. package/dist/ui/skills_menu.d.ts.map +1 -0
  46. package/dist/ui/styles.d.ts +2 -0
  47. package/dist/ui/styles.d.ts.map +1 -0
  48. package/dist/ui/tool_call_card.d.ts +35 -0
  49. package/dist/ui/tool_call_card.d.ts.map +1 -0
  50. package/package.json +5 -3
  51. package/src/constants.ts +38 -0
  52. package/src/core/ag_ui_chat.ts +851 -0
  53. package/src/{agui_client.ts → core/agui_client.ts} +19 -1
  54. package/src/{define_ag_ui_chat.ts → core/define_ag_ui_chat.ts} +1 -1
  55. package/src/dom/animations.ts +201 -0
  56. package/src/{dom_driver.ts → dom/dom_driver.ts} +35 -2
  57. package/src/dom/native_setter.ts +42 -0
  58. package/src/index.ts +61 -32
  59. package/src/skills/fill_template.ts +32 -0
  60. package/src/skills/parse_skills.ts +26 -0
  61. package/src/skills/skill.ts +23 -0
  62. package/src/{client_tool_registry.ts → tools/client_tool_registry.ts} +6 -4
  63. package/src/{is_destructive.ts → tools/is_destructive.ts} +1 -1
  64. package/src/{is_navigates.ts → tools/is_navigates.ts} +1 -1
  65. package/src/tools/route_map.ts +140 -0
  66. package/src/{state_hook.ts → tools/state_hook.ts} +1 -1
  67. package/src/ui/confirmation_card.ts +71 -0
  68. package/src/ui/render_markdown.ts +68 -0
  69. package/src/ui/reveal_words.ts +41 -0
  70. package/src/ui/skills_menu.ts +171 -0
  71. package/src/ui/styles.ts +631 -0
  72. package/src/{tool_call_card.ts → ui/tool_call_card.ts} +50 -19
  73. package/src/version.ts +1 -1
  74. package/dist/ag_ui_chat.d.ts.map +0 -1
  75. package/dist/agui_client.d.ts.map +0 -1
  76. package/dist/animations.d.ts +0 -33
  77. package/dist/animations.d.ts.map +0 -1
  78. package/dist/client_tool_registry.d.ts.map +0 -1
  79. package/dist/confirmation_modal.d.ts +0 -14
  80. package/dist/confirmation_modal.d.ts.map +0 -1
  81. package/dist/conversation_store.d.ts.map +0 -1
  82. package/dist/create_http_agent.d.ts.map +0 -1
  83. package/dist/define_ag_ui_chat.d.ts.map +0 -1
  84. package/dist/dom_driver.d.ts.map +0 -1
  85. package/dist/is_destructive.d.ts.map +0 -1
  86. package/dist/is_navigates.d.ts.map +0 -1
  87. package/dist/page_map.d.ts.map +0 -1
  88. package/dist/route_map.d.ts +0 -27
  89. package/dist/route_map.d.ts.map +0 -1
  90. package/dist/state_hook.d.ts.map +0 -1
  91. package/dist/styles.d.ts +0 -2
  92. package/dist/styles.d.ts.map +0 -1
  93. package/dist/tool_call_card.d.ts +0 -29
  94. package/dist/tool_call_card.d.ts.map +0 -1
  95. package/src/ag_ui_chat.ts +0 -411
  96. package/src/animations.ts +0 -86
  97. package/src/confirmation_modal.ts +0 -69
  98. package/src/route_map.ts +0 -83
  99. package/src/styles.ts +0 -296
  100. /package/dist/{conversation_store.d.ts → core/conversation_store.d.ts} +0 -0
  101. /package/dist/{create_http_agent.d.ts → core/create_http_agent.d.ts} +0 -0
  102. /package/dist/{define_ag_ui_chat.d.ts → core/define_ag_ui_chat.d.ts} +0 -0
  103. /package/dist/{is_destructive.d.ts → tools/is_destructive.d.ts} +0 -0
  104. /package/dist/{is_navigates.d.ts → tools/is_navigates.d.ts} +0 -0
  105. /package/dist/{page_map.d.ts → tools/page_map.d.ts} +0 -0
  106. /package/dist/{state_hook.d.ts → tools/state_hook.d.ts} +0 -0
  107. /package/src/{conversation_store.ts → core/conversation_store.ts} +0 -0
  108. /package/src/{create_http_agent.ts → core/create_http_agent.ts} +0 -0
  109. /package/src/{page_map.ts → tools/page_map.ts} +0 -0
package/dist/index.js CHANGED
@@ -1,14 +1,14 @@
1
- // src/agui_client.ts
2
- import { randomUUID } from "@ag-ui/client";
3
-
4
1
  // src/constants.ts
5
2
  var ELEMENT_TAG = "ag-ui-chat";
6
3
  var SUBMIT_EVENT = "ag-ui-submit";
4
+ var TOGGLE_EVENT = "ag-ui-toggle";
7
5
  var MESSAGE_ROLE = {
8
6
  USER: "user",
9
7
  ASSISTANT: "assistant"
10
8
  };
11
9
  var X_DESTRUCTIVE_KEY = "x-destructive";
10
+ var X_CONFIRM_KEY = "x-confirm";
11
+ var X_SUMMARY_KEY = "x-summary";
12
12
  var X_NAVIGATES_KEY = "x-navigates";
13
13
  var MAX_TOOL_ROUNDS = 10;
14
14
  var TOOL_CALL_STATUS = {
@@ -17,137 +17,54 @@ var TOOL_CALL_STATUS = {
17
17
  ERROR: "error",
18
18
  DECLINED: "declined"
19
19
  };
20
+ var TOOL_DISPLAY = {
21
+ MINIMAL: "minimal",
22
+ COMPACT: "compact",
23
+ FULL: "full"
24
+ };
20
25
 
21
- // src/agui_client.ts
22
- var AgUiClient = class {
23
- #agent;
24
- #handlers;
25
- #getTools;
26
- #getContext;
27
- #executeTool;
28
- #onPersist;
29
- constructor(config) {
30
- this.#agent = config.agent;
31
- this.#handlers = config.handlers;
32
- this.#getTools = config.getTools ?? (() => []);
33
- this.#getContext = config.getContext ?? (() => []);
34
- this.#executeTool = config.executeTool ?? null;
35
- this.#onPersist = config.onPersist ?? (() => {
36
- });
37
- }
38
- /** Whether a run is currently in flight. */
39
- get running() {
40
- return this.#agent.isRunning;
41
- }
42
- /** The current conversation history (for persistence / rehydration). */
43
- get messages() {
44
- return this.#agent.messages;
45
- }
46
- /**
47
- * Append a user message and run the agent to completion.
48
- *
49
- * When the agent calls frontend tools, this executes them and re-runs the
50
- * agent with the results, looping until the agent stops calling frontend
51
- * tools (bounded by {@link MAX_TOOL_ROUNDS}).
52
- */
53
- async send(content) {
54
- this.#agent.addMessage({ id: randomUUID(), role: "user", content });
55
- this.#onPersist(this.#agent.messages);
56
- await this.#run();
57
- }
58
- /**
59
- * Resume the run loop after a navigating tool's result was supplied
60
- * post-reload (via {@link addToolResult}). Unlike {@link send}, adds no user
61
- * message — it simply continues the conversation already in history.
62
- */
63
- async resume() {
64
- await this.#run();
65
- }
66
- /** Append a frontend tool result to history (used by the resume path). */
67
- addToolResult(toolCallId, content) {
68
- this.#agent.addMessage({ id: randomUUID(), role: "tool", content, toolCallId });
69
- this.#onPersist(this.#agent.messages);
70
- }
71
- async #run() {
72
- try {
73
- await this.#runLoop();
74
- } catch (error) {
75
- this.#handlers.onError(error instanceof Error ? error.message : String(error));
76
- }
77
- }
78
- async #runLoop() {
79
- for (let round = 0; round < MAX_TOOL_ROUNDS; round += 1) {
80
- const pending = [];
81
- await this.#agent.runAgent(
82
- { tools: this.#getTools(), context: this.#getContext() },
83
- this.#buildSubscriber(pending)
84
- );
85
- this.#onPersist(this.#agent.messages);
86
- if (this.#executeTool === null || pending.length === 0) {
87
- return;
88
- }
89
- let executed = false;
90
- for (const call of pending) {
91
- const result = await this.#executeTool(call);
92
- if (result === null) {
93
- continue;
94
- }
95
- if (result.halt === true) {
96
- return;
97
- }
98
- this.#agent.addMessage({
99
- id: randomUUID(),
100
- role: "tool",
101
- content: result.content,
102
- toolCallId: call.id
103
- });
104
- this.#onPersist(this.#agent.messages);
105
- executed = true;
106
- }
107
- if (!executed) {
108
- return;
26
+ // src/skills/fill_template.ts
27
+ var PLACEHOLDER_RE = /\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g;
28
+ function fillTemplate(template, values) {
29
+ const missing = [];
30
+ const text2 = template.replace(PLACEHOLDER_RE, (token, key) => {
31
+ const value = values[key];
32
+ if (value === void 0 || value === null || value === "") {
33
+ if (!missing.includes(key)) {
34
+ missing.push(key);
109
35
  }
36
+ return token;
110
37
  }
38
+ return String(value);
39
+ });
40
+ return { text: text2, missing };
41
+ }
42
+
43
+ // src/skills/parse_skills.ts
44
+ function isSkill(value) {
45
+ if (typeof value !== "object" || value === null) {
46
+ return false;
111
47
  }
112
- #buildSubscriber(pending) {
113
- const h = this.#handlers;
114
- return {
115
- onRunInitialized() {
116
- h.onRunStart();
117
- },
118
- onTextMessageContentEvent({ textMessageBuffer }) {
119
- h.onTextDelta(textMessageBuffer);
120
- },
121
- onTextMessageEndEvent({ textMessageBuffer }) {
122
- h.onTextEnd(textMessageBuffer);
123
- },
124
- onToolCallEndEvent({ event, toolCallName, toolCallArgs }) {
125
- const call = {
126
- id: event.toolCallId,
127
- name: toolCallName,
128
- args: toolCallArgs
129
- };
130
- pending.push(call);
131
- h.onToolCall(call);
132
- },
133
- onRunErrorEvent({ event }) {
134
- h.onError(event.message);
135
- },
136
- onRunFinalized() {
137
- h.onRunEnd();
138
- }
139
- };
48
+ const record = value;
49
+ return typeof record["name"] === "string" && typeof record["title"] === "string" && typeof record["prompt"] === "string";
50
+ }
51
+ function parseSkills(value) {
52
+ if (!Array.isArray(value)) {
53
+ return [];
140
54
  }
141
- };
55
+ return value.filter(isSkill);
56
+ }
142
57
 
143
- // src/client_tool_registry.ts
58
+ // src/tools/client_tool_registry.ts
144
59
  var ClientToolRegistry = class {
145
60
  #tools = /* @__PURE__ */ new Map();
146
- /** Register a tool. Throws if the name is already taken. */
61
+ /**
62
+ * Register a tool, replacing any existing one with the same name.
63
+ *
64
+ * Idempotent on the name so re-fired host refs / React StrictMode's
65
+ * double-invoke don't throw — re-registering is a replace, not an error.
66
+ */
147
67
  register(tool) {
148
- if (this.#tools.has(tool.name)) {
149
- throw new Error(`tool "${tool.name}" already registered`);
150
- }
151
68
  this.#tools.set(tool.name, tool);
152
69
  }
153
70
  has(name) {
@@ -171,131 +88,17 @@ var ClientToolRegistry = class {
171
88
  }
172
89
  };
173
90
 
174
- // src/confirmation_modal.ts
175
- function requestConfirmation(host, request) {
176
- return new Promise((resolve) => {
177
- const overlay = document.createElement("div");
178
- overlay.className = "modal-overlay";
179
- const dialog = document.createElement("div");
180
- dialog.className = "modal";
181
- const title = document.createElement("div");
182
- title.className = "modal-title";
183
- title.textContent = "Confirm action";
184
- const body = document.createElement("div");
185
- body.className = "modal-body";
186
- body.textContent = `Run \u201C${request.toolName}\u201D?`;
187
- const args = document.createElement("pre");
188
- args.className = "modal-args";
189
- args.textContent = JSON.stringify(request.args, null, 2);
190
- const actions = document.createElement("div");
191
- actions.className = "modal-actions";
192
- const cancel = document.createElement("button");
193
- cancel.className = "modal-btn modal-btn--cancel";
194
- cancel.type = "button";
195
- cancel.textContent = "Cancel";
196
- const confirm = document.createElement("button");
197
- confirm.className = "modal-btn modal-btn--confirm";
198
- confirm.type = "button";
199
- confirm.textContent = "Run";
200
- const close = (accepted) => {
201
- overlay.remove();
202
- resolve(accepted);
203
- };
204
- cancel.addEventListener("click", () => close(false));
205
- confirm.addEventListener("click", () => close(true));
206
- overlay.addEventListener("click", (event) => {
207
- if (event.target === overlay) {
208
- close(false);
209
- }
210
- });
211
- actions.append(cancel, confirm);
212
- dialog.append(title, body, args, actions);
213
- overlay.append(dialog);
214
- host.appendChild(overlay);
215
- confirm.focus();
216
- });
217
- }
218
-
219
- // src/conversation_store.ts
220
- import { randomUUID as randomUUID2 } from "@ag-ui/client";
221
- var THREAD_KEY = "ag-ui-chat:thread";
222
- var MESSAGES_PREFIX = "ag-ui-chat:messages:";
223
- var CHECKPOINT_PREFIX = "ag-ui-chat:checkpoint:";
224
- var SessionStorageStore = class {
225
- threadId() {
226
- const existing = sessionStorage.getItem(THREAD_KEY);
227
- if (existing !== null) {
228
- return existing;
229
- }
230
- const id = randomUUID2();
231
- sessionStorage.setItem(THREAD_KEY, id);
232
- return id;
233
- }
234
- loadMessages(threadId) {
235
- return Promise.resolve(this.#readJson(MESSAGES_PREFIX + threadId));
236
- }
237
- saveMessages(threadId, messages) {
238
- sessionStorage.setItem(MESSAGES_PREFIX + threadId, JSON.stringify(messages));
239
- }
240
- loadCheckpoint(threadId) {
241
- return this.#readJson(CHECKPOINT_PREFIX + threadId);
242
- }
243
- saveCheckpoint(threadId, checkpoint) {
244
- const key = CHECKPOINT_PREFIX + threadId;
245
- if (checkpoint === null) {
246
- sessionStorage.removeItem(key);
247
- return;
248
- }
249
- sessionStorage.setItem(key, JSON.stringify(checkpoint));
250
- }
251
- clear(threadId) {
252
- sessionStorage.removeItem(MESSAGES_PREFIX + threadId);
253
- sessionStorage.removeItem(CHECKPOINT_PREFIX + threadId);
254
- sessionStorage.removeItem(THREAD_KEY);
255
- }
256
- /** Parse a stored JSON value, returning `null` when absent or corrupt. */
257
- #readJson(key) {
258
- const raw = sessionStorage.getItem(key);
259
- if (raw === null) {
260
- return null;
261
- }
262
- try {
263
- return JSON.parse(raw);
264
- } catch {
265
- return null;
266
- }
267
- }
268
- };
269
-
270
- // src/create_http_agent.ts
271
- import { HttpAgent } from "@ag-ui/client";
272
- function createHttpAgent(options) {
273
- return new HttpAgent({
274
- url: options.endpoint,
275
- headers: options.headers ?? {},
276
- // HttpAgent invokes its configured fetch as a method (`this.fetch(...)`),
277
- // which would rebind the global `fetch` to the agent instance and trigger
278
- // "Illegal invocation" in browsers. Wrap it so `fetch` is always called as
279
- // a free function with the correct receiver.
280
- fetch: (url, init) => fetch(url, init),
281
- // Spread conditionally: under `exactOptionalPropertyTypes` an explicit
282
- // `undefined` is not assignable to these optional config fields.
283
- ...options.threadId !== void 0 ? { threadId: options.threadId } : {},
284
- ...options.initialMessages !== void 0 ? { initialMessages: [...options.initialMessages] } : {}
285
- });
286
- }
287
-
288
- // src/is_destructive.ts
91
+ // src/tools/is_destructive.ts
289
92
  function isDestructive(parameters) {
290
93
  return parameters[X_DESTRUCTIVE_KEY] === true;
291
94
  }
292
95
 
293
- // src/is_navigates.ts
96
+ // src/tools/is_navigates.ts
294
97
  function isNavigates(parameters) {
295
98
  return parameters[X_NAVIGATES_KEY] === true;
296
99
  }
297
100
 
298
- // src/page_map.ts
101
+ // src/tools/page_map.ts
299
102
  function createPageMapContext(getPageMap, autoInject) {
300
103
  if (!autoInject || getPageMap === null) {
301
104
  return [];
@@ -303,11 +106,31 @@ function createPageMapContext(getPageMap, autoInject) {
303
106
  return [{ description: "page_map", value: JSON.stringify(getPageMap()) }];
304
107
  }
305
108
 
306
- // src/route_map.ts
307
- function withQuery(path, params) {
308
- if (params === void 0) {
309
- return path;
109
+ // src/tools/route_map.ts
110
+ var PATH_PARAM_RE = /:([A-Za-z_][A-Za-z0-9_]*)/g;
111
+ function pathParamNames(path) {
112
+ const names = [];
113
+ for (const match of path.matchAll(PATH_PARAM_RE)) {
114
+ const name = match[1];
115
+ if (name !== void 0) {
116
+ names.push(name);
117
+ }
310
118
  }
119
+ return names;
120
+ }
121
+ function fillPath(routeId, path, params) {
122
+ const leftover = { ...params };
123
+ const filled = path.replace(PATH_PARAM_RE, (_match, name) => {
124
+ const value = params[name];
125
+ if (value === void 0 || value === null || String(value) === "") {
126
+ throw new Error(`route "${routeId}" requires path param "${name}"`);
127
+ }
128
+ delete leftover[name];
129
+ return encodeURIComponent(String(value));
130
+ });
131
+ return { path: filled, leftover };
132
+ }
133
+ function withQuery(path, params) {
311
134
  const usp = new URLSearchParams();
312
135
  for (const [key, value] of Object.entries(params)) {
313
136
  usp.set(key, String(value));
@@ -319,13 +142,13 @@ function createRouteTools(getRouteMap, getNavigate) {
319
142
  return [
320
143
  {
321
144
  name: "list_routes",
322
- description: "List the routes the app can navigate to.",
145
+ description: "List the routes the app can navigate to. Each route's `pathParams` names the dynamic segments to pass as `params` to `navigate_to_route`.",
323
146
  parameters: { type: "object", properties: {}, required: [] },
324
- handler: () => getRouteMap()
147
+ handler: () => getRouteMap().map((route) => ({ ...route, pathParams: pathParamNames(route.path) }))
325
148
  },
326
149
  {
327
150
  name: "navigate_to_route",
328
- description: "Navigate to one of the app's routes by its id.",
151
+ description: "Navigate to one of the app's routes by its id, filling any dynamic `:name` path segments (and extra query params) from `params`.",
329
152
  parameters: {
330
153
  type: "object",
331
154
  properties: {
@@ -341,7 +164,9 @@ function createRouteTools(getRouteMap, getNavigate) {
341
164
  if (route === void 0) {
342
165
  throw new Error(`unknown route "${String(routeId)}"`);
343
166
  }
344
- const path = withQuery(route.path, args["params"]);
167
+ const provided = args["params"] ?? {};
168
+ const { path: filledPath, leftover } = fillPath(route.id, route.path, provided);
169
+ const path = withQuery(filledPath, leftover);
345
170
  const navigate = getNavigate();
346
171
  if (navigate !== null) {
347
172
  navigate(path);
@@ -354,7 +179,7 @@ function createRouteTools(getRouteMap, getNavigate) {
354
179
  ];
355
180
  }
356
181
 
357
- // src/state_hook.ts
182
+ // src/tools/state_hook.ts
358
183
  function createStateHookTools(hook) {
359
184
  const tools = [
360
185
  {
@@ -376,33 +201,2744 @@ function createStateHookTools(hook) {
376
201
  return tools;
377
202
  }
378
203
 
379
- // src/styles.ts
380
- var STYLES = `
381
- :host {
382
- /* Colors */
383
- --ag-ui-bg: #ffffff;
384
- --ag-ui-fg: #1a1a2e;
385
- --ag-ui-accent: #4f46e5;
386
- --ag-ui-user-bg: #4f46e5;
387
- --ag-ui-user-fg: #ffffff;
388
- --ag-ui-assistant-bg: #f1f1f6;
389
- --ag-ui-input-bg: var(--ag-ui-bg);
390
- --ag-ui-tool-bg: var(--ag-ui-assistant-bg);
391
- --ag-ui-tool-fg: var(--ag-ui-accent);
392
- --ag-ui-header-bg: var(--ag-ui-accent);
393
- --ag-ui-header-fg: #ffffff;
394
- --ag-ui-border: #e2e2ec;
395
- --ag-ui-radius: 12px;
204
+ // src/ui/confirmation_card.ts
205
+ function actionButton(modifier, label) {
206
+ const button = document.createElement("button");
207
+ button.type = "button";
208
+ button.className = `confirm-btn confirm-btn--${modifier}`;
209
+ button.textContent = label;
210
+ return button;
211
+ }
212
+ function requestConfirmation(host, request) {
213
+ return new Promise((resolve) => {
214
+ const card = document.createElement("div");
215
+ card.className = "confirm";
216
+ card.setAttribute("data-tool-name", request.toolName);
217
+ card.setAttribute("role", "group");
218
+ card.setAttribute("aria-label", "Confirm action");
219
+ const body = document.createElement("div");
220
+ body.className = "confirm-body";
221
+ body.textContent = request.message ?? `Run \u201C${request.toolName}\u201D?`;
222
+ const args = document.createElement("pre");
223
+ args.className = "confirm-args";
224
+ args.textContent = JSON.stringify(request.args, null, 2);
225
+ const actions = document.createElement("div");
226
+ actions.className = "confirm-actions";
227
+ const cancel = actionButton("cancel", "Cancel");
228
+ const confirm = actionButton("confirm", "Confirm");
229
+ const close = (accepted) => {
230
+ cancel.disabled = true;
231
+ confirm.disabled = true;
232
+ card.setAttribute("data-resolved", accepted ? "confirmed" : "declined");
233
+ resolve(accepted);
234
+ };
235
+ cancel.addEventListener("click", () => close(false));
236
+ confirm.addEventListener("click", () => close(true));
237
+ actions.append(cancel, confirm);
238
+ card.append(body, args, actions);
239
+ host.appendChild(card);
240
+ confirm.focus();
241
+ });
242
+ }
396
243
 
397
- /* Status accents for tool-call cards. */
398
- --ag-ui-success: #15803d;
399
- --ag-ui-danger: #b91c1c;
244
+ // node_modules/.pnpm/dompurify@3.4.7/node_modules/dompurify/dist/purify.es.mjs
245
+ function _arrayLikeToArray(r, a) {
246
+ (null == a || a > r.length) && (a = r.length);
247
+ for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
248
+ return n;
249
+ }
250
+ function _arrayWithHoles(r) {
251
+ if (Array.isArray(r)) return r;
252
+ }
253
+ function _iterableToArrayLimit(r, l3) {
254
+ var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
255
+ if (null != t) {
256
+ var e, n, i, u, a = [], f = true, o = false;
257
+ try {
258
+ if (i = (t = t.call(r)).next, 0 === l3) ;
259
+ else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l3); f = true) ;
260
+ } catch (r2) {
261
+ o = true, n = r2;
262
+ } finally {
263
+ try {
264
+ if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
265
+ } finally {
266
+ if (o) throw n;
267
+ }
268
+ }
269
+ return a;
270
+ }
271
+ }
272
+ function _nonIterableRest() {
273
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
274
+ }
275
+ function _slicedToArray(r, e) {
276
+ return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
277
+ }
278
+ function _unsupportedIterableToArray(r, a) {
279
+ if (r) {
280
+ if ("string" == typeof r) return _arrayLikeToArray(r, a);
281
+ var t = {}.toString.call(r).slice(8, -1);
282
+ return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
283
+ }
284
+ }
285
+ var entries = Object.entries;
286
+ var setPrototypeOf = Object.setPrototypeOf;
287
+ var isFrozen = Object.isFrozen;
288
+ var getPrototypeOf = Object.getPrototypeOf;
289
+ var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
290
+ var freeze = Object.freeze;
291
+ var seal = Object.seal;
292
+ var create = Object.create;
293
+ var _ref = typeof Reflect !== "undefined" && Reflect;
294
+ var apply = _ref.apply;
295
+ var construct = _ref.construct;
296
+ if (!freeze) {
297
+ freeze = function freeze2(x2) {
298
+ return x2;
299
+ };
300
+ }
301
+ if (!seal) {
302
+ seal = function seal2(x2) {
303
+ return x2;
304
+ };
305
+ }
306
+ if (!apply) {
307
+ apply = function apply2(func, thisArg) {
308
+ for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
309
+ args[_key - 2] = arguments[_key];
310
+ }
311
+ return func.apply(thisArg, args);
312
+ };
313
+ }
314
+ if (!construct) {
315
+ construct = function construct2(Func) {
316
+ for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
317
+ args[_key2 - 1] = arguments[_key2];
318
+ }
319
+ return new Func(...args);
320
+ };
321
+ }
322
+ var arrayForEach = unapply(Array.prototype.forEach);
323
+ var arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);
324
+ var arrayPop = unapply(Array.prototype.pop);
325
+ var arrayPush = unapply(Array.prototype.push);
326
+ var arraySplice = unapply(Array.prototype.splice);
327
+ var arrayIsArray = Array.isArray;
328
+ var stringToLowerCase = unapply(String.prototype.toLowerCase);
329
+ var stringToString = unapply(String.prototype.toString);
330
+ var stringMatch = unapply(String.prototype.match);
331
+ var stringReplace = unapply(String.prototype.replace);
332
+ var stringIndexOf = unapply(String.prototype.indexOf);
333
+ var stringTrim = unapply(String.prototype.trim);
334
+ var numberToString = unapply(Number.prototype.toString);
335
+ var booleanToString = unapply(Boolean.prototype.toString);
336
+ var bigintToString = typeof BigInt === "undefined" ? null : unapply(BigInt.prototype.toString);
337
+ var symbolToString = typeof Symbol === "undefined" ? null : unapply(Symbol.prototype.toString);
338
+ var objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
339
+ var objectToString = unapply(Object.prototype.toString);
340
+ var regExpTest = unapply(RegExp.prototype.test);
341
+ var typeErrorCreate = unconstruct(TypeError);
342
+ function unapply(func) {
343
+ return function(thisArg) {
344
+ if (thisArg instanceof RegExp) {
345
+ thisArg.lastIndex = 0;
346
+ }
347
+ for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
348
+ args[_key3 - 1] = arguments[_key3];
349
+ }
350
+ return apply(func, thisArg, args);
351
+ };
352
+ }
353
+ function unconstruct(Func) {
354
+ return function() {
355
+ for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
356
+ args[_key4] = arguments[_key4];
357
+ }
358
+ return construct(Func, args);
359
+ };
360
+ }
361
+ function addToSet(set, array) {
362
+ let transformCaseFunc = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : stringToLowerCase;
363
+ if (setPrototypeOf) {
364
+ setPrototypeOf(set, null);
365
+ }
366
+ if (!arrayIsArray(array)) {
367
+ return set;
368
+ }
369
+ let l3 = array.length;
370
+ while (l3--) {
371
+ let element = array[l3];
372
+ if (typeof element === "string") {
373
+ const lcElement = transformCaseFunc(element);
374
+ if (lcElement !== element) {
375
+ if (!isFrozen(array)) {
376
+ array[l3] = lcElement;
377
+ }
378
+ element = lcElement;
379
+ }
380
+ }
381
+ set[element] = true;
382
+ }
383
+ return set;
384
+ }
385
+ function cleanArray(array) {
386
+ for (let index = 0; index < array.length; index++) {
387
+ const isPropertyExist = objectHasOwnProperty(array, index);
388
+ if (!isPropertyExist) {
389
+ array[index] = null;
390
+ }
391
+ }
392
+ return array;
393
+ }
394
+ function clone(object) {
395
+ const newObject = create(null);
396
+ for (const _ref2 of entries(object)) {
397
+ var _ref3 = _slicedToArray(_ref2, 2);
398
+ const property = _ref3[0];
399
+ const value = _ref3[1];
400
+ const isPropertyExist = objectHasOwnProperty(object, property);
401
+ if (isPropertyExist) {
402
+ if (arrayIsArray(value)) {
403
+ newObject[property] = cleanArray(value);
404
+ } else if (value && typeof value === "object" && value.constructor === Object) {
405
+ newObject[property] = clone(value);
406
+ } else {
407
+ newObject[property] = value;
408
+ }
409
+ }
410
+ }
411
+ return newObject;
412
+ }
413
+ function stringifyValue(value) {
414
+ switch (typeof value) {
415
+ case "string": {
416
+ return value;
417
+ }
418
+ case "number": {
419
+ return numberToString(value);
420
+ }
421
+ case "boolean": {
422
+ return booleanToString(value);
423
+ }
424
+ case "bigint": {
425
+ return bigintToString ? bigintToString(value) : "0";
426
+ }
427
+ case "symbol": {
428
+ return symbolToString ? symbolToString(value) : "Symbol()";
429
+ }
430
+ case "undefined": {
431
+ return objectToString(value);
432
+ }
433
+ case "function":
434
+ case "object": {
435
+ if (value === null) {
436
+ return objectToString(value);
437
+ }
438
+ const valueAsRecord = value;
439
+ const valueToString = lookupGetter(valueAsRecord, "toString");
440
+ if (typeof valueToString === "function") {
441
+ const stringified = valueToString(valueAsRecord);
442
+ return typeof stringified === "string" ? stringified : objectToString(stringified);
443
+ }
444
+ return objectToString(value);
445
+ }
446
+ default: {
447
+ return objectToString(value);
448
+ }
449
+ }
450
+ }
451
+ function lookupGetter(object, prop) {
452
+ while (object !== null) {
453
+ const desc = getOwnPropertyDescriptor(object, prop);
454
+ if (desc) {
455
+ if (desc.get) {
456
+ return unapply(desc.get);
457
+ }
458
+ if (typeof desc.value === "function") {
459
+ return unapply(desc.value);
460
+ }
461
+ }
462
+ object = getPrototypeOf(object);
463
+ }
464
+ function fallbackValue() {
465
+ return null;
466
+ }
467
+ return fallbackValue;
468
+ }
469
+ function isRegex(value) {
470
+ try {
471
+ regExpTest(value, "");
472
+ return true;
473
+ } catch (_unused) {
474
+ return false;
475
+ }
476
+ }
477
+ var html$1 = freeze(["a", "abbr", "acronym", "address", "area", "article", "aside", "audio", "b", "bdi", "bdo", "big", "blink", "blockquote", "body", "br", "button", "canvas", "caption", "center", "cite", "code", "col", "colgroup", "content", "data", "datalist", "dd", "decorator", "del", "details", "dfn", "dialog", "dir", "div", "dl", "dt", "element", "em", "fieldset", "figcaption", "figure", "font", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "img", "input", "ins", "kbd", "label", "legend", "li", "main", "map", "mark", "marquee", "menu", "menuitem", "meter", "nav", "nobr", "ol", "optgroup", "option", "output", "p", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "search", "section", "select", "shadow", "slot", "small", "source", "spacer", "span", "strike", "strong", "style", "sub", "summary", "sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "tr", "track", "tt", "u", "ul", "var", "video", "wbr"]);
478
+ var svg$1 = freeze(["svg", "a", "altglyph", "altglyphdef", "altglyphitem", "animatecolor", "animatemotion", "animatetransform", "circle", "clippath", "defs", "desc", "ellipse", "enterkeyhint", "exportparts", "filter", "font", "g", "glyph", "glyphref", "hkern", "image", "inputmode", "line", "lineargradient", "marker", "mask", "metadata", "mpath", "part", "path", "pattern", "polygon", "polyline", "radialgradient", "rect", "stop", "style", "switch", "symbol", "text", "textpath", "title", "tref", "tspan", "view", "vkern"]);
479
+ var svgFilters = freeze(["feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence"]);
480
+ var svgDisallowed = freeze(["animate", "color-profile", "cursor", "discard", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "foreignobject", "hatch", "hatchpath", "mesh", "meshgradient", "meshpatch", "meshrow", "missing-glyph", "script", "set", "solidcolor", "unknown", "use"]);
481
+ var mathMl$1 = freeze(["math", "menclose", "merror", "mfenced", "mfrac", "mglyph", "mi", "mlabeledtr", "mmultiscripts", "mn", "mo", "mover", "mpadded", "mphantom", "mroot", "mrow", "ms", "mspace", "msqrt", "mstyle", "msub", "msup", "msubsup", "mtable", "mtd", "mtext", "mtr", "munder", "munderover", "mprescripts"]);
482
+ var mathMlDisallowed = freeze(["maction", "maligngroup", "malignmark", "mlongdiv", "mscarries", "mscarry", "msgroup", "mstack", "msline", "msrow", "semantics", "annotation", "annotation-xml", "mprescripts", "none"]);
483
+ var text = freeze(["#text"]);
484
+ var html = freeze(["accept", "action", "align", "alt", "autocapitalize", "autocomplete", "autopictureinpicture", "autoplay", "background", "bgcolor", "border", "capture", "cellpadding", "cellspacing", "checked", "cite", "class", "clear", "color", "cols", "colspan", "command", "commandfor", "controls", "controlslist", "coords", "crossorigin", "datetime", "decoding", "default", "dir", "disabled", "disablepictureinpicture", "disableremoteplayback", "download", "draggable", "enctype", "enterkeyhint", "exportparts", "face", "for", "headers", "height", "hidden", "high", "href", "hreflang", "id", "inert", "inputmode", "integrity", "ismap", "kind", "label", "lang", "list", "loading", "loop", "low", "max", "maxlength", "media", "method", "min", "minlength", "multiple", "muted", "name", "nonce", "noshade", "novalidate", "nowrap", "open", "optimum", "part", "pattern", "placeholder", "playsinline", "popover", "popovertarget", "popovertargetaction", "poster", "preload", "pubdate", "radiogroup", "readonly", "rel", "required", "rev", "reversed", "role", "rows", "rowspan", "spellcheck", "scope", "selected", "shape", "size", "sizes", "slot", "span", "srclang", "start", "src", "srcset", "step", "style", "summary", "tabindex", "title", "translate", "type", "usemap", "valign", "value", "width", "wrap", "xmlns"]);
485
+ var svg = freeze(["accent-height", "accumulate", "additive", "alignment-baseline", "amplitude", "ascent", "attributename", "attributetype", "azimuth", "basefrequency", "baseline-shift", "begin", "bias", "by", "class", "clip", "clippathunits", "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", "color-profile", "color-rendering", "cx", "cy", "d", "dx", "dy", "diffuseconstant", "direction", "display", "divisor", "dur", "edgemode", "elevation", "end", "exponent", "fill", "fill-opacity", "fill-rule", "filter", "filterunits", "flood-color", "flood-opacity", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight", "fx", "fy", "g1", "g2", "glyph-name", "glyphref", "gradientunits", "gradienttransform", "height", "href", "id", "image-rendering", "in", "in2", "intercept", "k", "k1", "k2", "k3", "k4", "kerning", "keypoints", "keysplines", "keytimes", "lang", "lengthadjust", "letter-spacing", "kernelmatrix", "kernelunitlength", "lighting-color", "local", "marker-end", "marker-mid", "marker-start", "markerheight", "markerunits", "markerwidth", "maskcontentunits", "maskunits", "max", "mask", "mask-type", "media", "method", "mode", "min", "name", "numoctaves", "offset", "operator", "opacity", "order", "orient", "orientation", "origin", "overflow", "paint-order", "path", "pathlength", "patterncontentunits", "patterntransform", "patternunits", "points", "preservealpha", "preserveaspectratio", "primitiveunits", "r", "rx", "ry", "radius", "refx", "refy", "repeatcount", "repeatdur", "restart", "result", "rotate", "scale", "seed", "shape-rendering", "slope", "specularconstant", "specularexponent", "spreadmethod", "startoffset", "stddeviation", "stitchtiles", "stop-color", "stop-opacity", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke", "stroke-width", "style", "surfacescale", "systemlanguage", "tabindex", "tablevalues", "targetx", "targety", "transform", "transform-origin", "text-anchor", "text-decoration", "text-rendering", "textlength", "type", "u1", "u2", "unicode", "values", "viewbox", "visibility", "version", "vert-adv-y", "vert-origin-x", "vert-origin-y", "width", "word-spacing", "wrap", "writing-mode", "xchannelselector", "ychannelselector", "x", "x1", "x2", "xmlns", "y", "y1", "y2", "z", "zoomandpan"]);
486
+ var mathMl = freeze(["accent", "accentunder", "align", "bevelled", "close", "columnalign", "columnlines", "columnspacing", "columnspan", "denomalign", "depth", "dir", "display", "displaystyle", "encoding", "fence", "frame", "height", "href", "id", "largeop", "length", "linethickness", "lquote", "lspace", "mathbackground", "mathcolor", "mathsize", "mathvariant", "maxsize", "minsize", "movablelimits", "notation", "numalign", "open", "rowalign", "rowlines", "rowspacing", "rowspan", "rspace", "rquote", "scriptlevel", "scriptminsize", "scriptsizemultiplier", "selection", "separator", "separators", "stretchy", "subscriptshift", "supscriptshift", "symmetric", "voffset", "width", "xmlns"]);
487
+ var xml = freeze(["xlink:href", "xml:id", "xlink:title", "xml:space", "xmlns:xlink"]);
488
+ var MUSTACHE_EXPR = seal(/{{[\w\W]*|^[\w\W]*}}/g);
489
+ var ERB_EXPR = seal(/<%[\w\W]*|^[\w\W]*%>/g);
490
+ var TMPLIT_EXPR = seal(/\${[\w\W]*/g);
491
+ var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/);
492
+ var ARIA_ATTR = seal(/^aria-[\-\w]+$/);
493
+ var IS_ALLOWED_URI = seal(
494
+ /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i
495
+ // eslint-disable-line no-useless-escape
496
+ );
497
+ var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
498
+ var ATTR_WHITESPACE = seal(
499
+ /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g
500
+ // eslint-disable-line no-control-regex
501
+ );
502
+ var DOCTYPE_NAME = seal(/^html$/i);
503
+ var CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
504
+ var NODE_TYPE = {
505
+ element: 1,
506
+ attribute: 2,
507
+ text: 3,
508
+ cdataSection: 4,
509
+ entityReference: 5,
510
+ // Deprecated
511
+ entityNode: 6,
512
+ // Deprecated
513
+ progressingInstruction: 7,
514
+ comment: 8,
515
+ document: 9,
516
+ documentType: 10,
517
+ documentFragment: 11,
518
+ notation: 12
519
+ // Deprecated
520
+ };
521
+ var getGlobal = function getGlobal2() {
522
+ return typeof window === "undefined" ? null : window;
523
+ };
524
+ var _createTrustedTypesPolicy = function _createTrustedTypesPolicy2(trustedTypes, purifyHostElement) {
525
+ if (typeof trustedTypes !== "object" || typeof trustedTypes.createPolicy !== "function") {
526
+ return null;
527
+ }
528
+ let suffix = null;
529
+ const ATTR_NAME = "data-tt-policy-suffix";
530
+ if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {
531
+ suffix = purifyHostElement.getAttribute(ATTR_NAME);
532
+ }
533
+ const policyName = "dompurify" + (suffix ? "#" + suffix : "");
534
+ try {
535
+ return trustedTypes.createPolicy(policyName, {
536
+ createHTML(html2) {
537
+ return html2;
538
+ },
539
+ createScriptURL(scriptUrl) {
540
+ return scriptUrl;
541
+ }
542
+ });
543
+ } catch (_2) {
544
+ console.warn("TrustedTypes policy " + policyName + " could not be created.");
545
+ return null;
546
+ }
547
+ };
548
+ var _createHooksMap = function _createHooksMap2() {
549
+ return {
550
+ afterSanitizeAttributes: [],
551
+ afterSanitizeElements: [],
552
+ afterSanitizeShadowDOM: [],
553
+ beforeSanitizeAttributes: [],
554
+ beforeSanitizeElements: [],
555
+ beforeSanitizeShadowDOM: [],
556
+ uponSanitizeAttribute: [],
557
+ uponSanitizeElement: [],
558
+ uponSanitizeShadowNode: []
559
+ };
560
+ };
561
+ function createDOMPurify() {
562
+ let window2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal();
563
+ const DOMPurify = (root) => createDOMPurify(root);
564
+ DOMPurify.version = "3.4.7";
565
+ DOMPurify.removed = [];
566
+ if (!window2 || !window2.document || window2.document.nodeType !== NODE_TYPE.document || !window2.Element) {
567
+ DOMPurify.isSupported = false;
568
+ return DOMPurify;
569
+ }
570
+ let document2 = window2.document;
571
+ const originalDocument = document2;
572
+ const currentScript = originalDocument.currentScript;
573
+ window2.DocumentFragment;
574
+ const HTMLTemplateElement = window2.HTMLTemplateElement, Node2 = window2.Node, Element = window2.Element, NodeFilter = window2.NodeFilter, _window$NamedNodeMap = window2.NamedNodeMap;
575
+ _window$NamedNodeMap === void 0 ? window2.NamedNodeMap || window2.MozNamedAttrMap : _window$NamedNodeMap;
576
+ window2.HTMLFormElement;
577
+ const DOMParser = window2.DOMParser, trustedTypes = window2.trustedTypes;
578
+ const ElementPrototype = Element.prototype;
579
+ const cloneNode = lookupGetter(ElementPrototype, "cloneNode");
580
+ const remove = lookupGetter(ElementPrototype, "remove");
581
+ const getNextSibling = lookupGetter(ElementPrototype, "nextSibling");
582
+ const getChildNodes = lookupGetter(ElementPrototype, "childNodes");
583
+ const getParentNode = lookupGetter(ElementPrototype, "parentNode");
584
+ const getShadowRoot = lookupGetter(ElementPrototype, "shadowRoot");
585
+ const getAttributes = lookupGetter(ElementPrototype, "attributes");
586
+ const getNodeType = Node2 && Node2.prototype ? lookupGetter(Node2.prototype, "nodeType") : null;
587
+ const getNodeName = Node2 && Node2.prototype ? lookupGetter(Node2.prototype, "nodeName") : null;
588
+ if (typeof HTMLTemplateElement === "function") {
589
+ const template = document2.createElement("template");
590
+ if (template.content && template.content.ownerDocument) {
591
+ document2 = template.content.ownerDocument;
592
+ }
593
+ }
594
+ let trustedTypesPolicy;
595
+ let emptyHTML = "";
596
+ const _document = document2, implementation = _document.implementation, createNodeIterator = _document.createNodeIterator, createDocumentFragment = _document.createDocumentFragment, getElementsByTagName = _document.getElementsByTagName;
597
+ const importNode = originalDocument.importNode;
598
+ let hooks = _createHooksMap();
599
+ DOMPurify.isSupported = typeof entries === "function" && typeof getParentNode === "function" && implementation && implementation.createHTMLDocument !== void 0;
600
+ const MUSTACHE_EXPR$1 = MUSTACHE_EXPR, ERB_EXPR$1 = ERB_EXPR, TMPLIT_EXPR$1 = TMPLIT_EXPR, DATA_ATTR$1 = DATA_ATTR, ARIA_ATTR$1 = ARIA_ATTR, IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA, ATTR_WHITESPACE$1 = ATTR_WHITESPACE, CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT;
601
+ let IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
602
+ let ALLOWED_TAGS2 = null;
603
+ const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);
604
+ let ALLOWED_ATTR2 = null;
605
+ const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);
606
+ let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {
607
+ tagNameCheck: {
608
+ writable: true,
609
+ configurable: false,
610
+ enumerable: true,
611
+ value: null
612
+ },
613
+ attributeNameCheck: {
614
+ writable: true,
615
+ configurable: false,
616
+ enumerable: true,
617
+ value: null
618
+ },
619
+ allowCustomizedBuiltInElements: {
620
+ writable: true,
621
+ configurable: false,
622
+ enumerable: true,
623
+ value: false
624
+ }
625
+ }));
626
+ let FORBID_TAGS = null;
627
+ let FORBID_ATTR = null;
628
+ const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, {
629
+ tagCheck: {
630
+ writable: true,
631
+ configurable: false,
632
+ enumerable: true,
633
+ value: null
634
+ },
635
+ attributeCheck: {
636
+ writable: true,
637
+ configurable: false,
638
+ enumerable: true,
639
+ value: null
640
+ }
641
+ }));
642
+ let ALLOW_ARIA_ATTR = true;
643
+ let ALLOW_DATA_ATTR = true;
644
+ let ALLOW_UNKNOWN_PROTOCOLS = false;
645
+ let ALLOW_SELF_CLOSE_IN_ATTR = true;
646
+ let SAFE_FOR_TEMPLATES = false;
647
+ let SAFE_FOR_XML = true;
648
+ let WHOLE_DOCUMENT = false;
649
+ let SET_CONFIG = false;
650
+ let FORCE_BODY = false;
651
+ let RETURN_DOM = false;
652
+ let RETURN_DOM_FRAGMENT = false;
653
+ let RETURN_TRUSTED_TYPE = false;
654
+ let SANITIZE_DOM = true;
655
+ let SANITIZE_NAMED_PROPS = false;
656
+ const SANITIZE_NAMED_PROPS_PREFIX = "user-content-";
657
+ let KEEP_CONTENT = true;
658
+ let IN_PLACE = false;
659
+ let USE_PROFILES = {};
660
+ let FORBID_CONTENTS = null;
661
+ const DEFAULT_FORBID_CONTENTS = addToSet({}, ["annotation-xml", "audio", "colgroup", "desc", "foreignobject", "head", "iframe", "math", "mi", "mn", "mo", "ms", "mtext", "noembed", "noframes", "noscript", "plaintext", "script", "style", "svg", "template", "thead", "title", "video", "xmp"]);
662
+ let DATA_URI_TAGS = null;
663
+ const DEFAULT_DATA_URI_TAGS = addToSet({}, ["audio", "video", "img", "source", "image", "track"]);
664
+ let URI_SAFE_ATTRIBUTES = null;
665
+ const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ["alt", "class", "for", "id", "label", "name", "pattern", "placeholder", "role", "summary", "title", "value", "style", "xmlns"]);
666
+ const MATHML_NAMESPACE = "http://www.w3.org/1998/Math/MathML";
667
+ const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
668
+ const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
669
+ let NAMESPACE = HTML_NAMESPACE;
670
+ let IS_EMPTY_INPUT = false;
671
+ let ALLOWED_NAMESPACES = null;
672
+ const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
673
+ let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ["mi", "mo", "mn", "ms", "mtext"]);
674
+ let HTML_INTEGRATION_POINTS = addToSet({}, ["annotation-xml"]);
675
+ const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ["title", "style", "font", "a", "script"]);
676
+ let PARSER_MEDIA_TYPE = null;
677
+ const SUPPORTED_PARSER_MEDIA_TYPES = ["application/xhtml+xml", "text/html"];
678
+ const DEFAULT_PARSER_MEDIA_TYPE = "text/html";
679
+ let transformCaseFunc = null;
680
+ let CONFIG = null;
681
+ const formElement = document2.createElement("form");
682
+ const isRegexOrFunction = function isRegexOrFunction2(testValue) {
683
+ return testValue instanceof RegExp || testValue instanceof Function;
684
+ };
685
+ const _parseConfig = function _parseConfig2() {
686
+ let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
687
+ if (CONFIG && CONFIG === cfg) {
688
+ return;
689
+ }
690
+ if (!cfg || typeof cfg !== "object") {
691
+ cfg = {};
692
+ }
693
+ cfg = clone(cfg);
694
+ PARSER_MEDIA_TYPE = // eslint-disable-next-line unicorn/prefer-includes
695
+ SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;
696
+ transformCaseFunc = PARSER_MEDIA_TYPE === "application/xhtml+xml" ? stringToString : stringToLowerCase;
697
+ ALLOWED_TAGS2 = objectHasOwnProperty(cfg, "ALLOWED_TAGS") && arrayIsArray(cfg.ALLOWED_TAGS) ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
698
+ ALLOWED_ATTR2 = objectHasOwnProperty(cfg, "ALLOWED_ATTR") && arrayIsArray(cfg.ALLOWED_ATTR) ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
699
+ ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, "ALLOWED_NAMESPACES") && arrayIsArray(cfg.ALLOWED_NAMESPACES) ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
700
+ URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, "ADD_URI_SAFE_ATTR") && arrayIsArray(cfg.ADD_URI_SAFE_ATTR) ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;
701
+ DATA_URI_TAGS = objectHasOwnProperty(cfg, "ADD_DATA_URI_TAGS") && arrayIsArray(cfg.ADD_DATA_URI_TAGS) ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;
702
+ FORBID_CONTENTS = objectHasOwnProperty(cfg, "FORBID_CONTENTS") && arrayIsArray(cfg.FORBID_CONTENTS) ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
703
+ FORBID_TAGS = objectHasOwnProperty(cfg, "FORBID_TAGS") && arrayIsArray(cfg.FORBID_TAGS) ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});
704
+ FORBID_ATTR = objectHasOwnProperty(cfg, "FORBID_ATTR") && arrayIsArray(cfg.FORBID_ATTR) ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});
705
+ USE_PROFILES = objectHasOwnProperty(cfg, "USE_PROFILES") ? cfg.USE_PROFILES && typeof cfg.USE_PROFILES === "object" ? clone(cfg.USE_PROFILES) : cfg.USE_PROFILES : false;
706
+ ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false;
707
+ ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false;
708
+ ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false;
709
+ ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false;
710
+ SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false;
711
+ SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false;
712
+ WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false;
713
+ RETURN_DOM = cfg.RETURN_DOM || false;
714
+ RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false;
715
+ RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false;
716
+ FORCE_BODY = cfg.FORCE_BODY || false;
717
+ SANITIZE_DOM = cfg.SANITIZE_DOM !== false;
718
+ SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false;
719
+ KEEP_CONTENT = cfg.KEEP_CONTENT !== false;
720
+ IN_PLACE = cfg.IN_PLACE || false;
721
+ IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI;
722
+ NAMESPACE = typeof cfg.NAMESPACE === "string" ? cfg.NAMESPACE : HTML_NAMESPACE;
723
+ MATHML_TEXT_INTEGRATION_POINTS = objectHasOwnProperty(cfg, "MATHML_TEXT_INTEGRATION_POINTS") && cfg.MATHML_TEXT_INTEGRATION_POINTS && typeof cfg.MATHML_TEXT_INTEGRATION_POINTS === "object" ? clone(cfg.MATHML_TEXT_INTEGRATION_POINTS) : addToSet({}, ["mi", "mo", "mn", "ms", "mtext"]);
724
+ HTML_INTEGRATION_POINTS = objectHasOwnProperty(cfg, "HTML_INTEGRATION_POINTS") && cfg.HTML_INTEGRATION_POINTS && typeof cfg.HTML_INTEGRATION_POINTS === "object" ? clone(cfg.HTML_INTEGRATION_POINTS) : addToSet({}, ["annotation-xml"]);
725
+ const customElementHandling = objectHasOwnProperty(cfg, "CUSTOM_ELEMENT_HANDLING") && cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING === "object" ? clone(cfg.CUSTOM_ELEMENT_HANDLING) : create(null);
726
+ CUSTOM_ELEMENT_HANDLING = create(null);
727
+ if (objectHasOwnProperty(customElementHandling, "tagNameCheck") && isRegexOrFunction(customElementHandling.tagNameCheck)) {
728
+ CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck;
729
+ }
730
+ if (objectHasOwnProperty(customElementHandling, "attributeNameCheck") && isRegexOrFunction(customElementHandling.attributeNameCheck)) {
731
+ CUSTOM_ELEMENT_HANDLING.attributeNameCheck = customElementHandling.attributeNameCheck;
732
+ }
733
+ if (objectHasOwnProperty(customElementHandling, "allowCustomizedBuiltInElements") && typeof customElementHandling.allowCustomizedBuiltInElements === "boolean") {
734
+ CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = customElementHandling.allowCustomizedBuiltInElements;
735
+ }
736
+ if (SAFE_FOR_TEMPLATES) {
737
+ ALLOW_DATA_ATTR = false;
738
+ }
739
+ if (RETURN_DOM_FRAGMENT) {
740
+ RETURN_DOM = true;
741
+ }
742
+ if (USE_PROFILES) {
743
+ ALLOWED_TAGS2 = addToSet({}, text);
744
+ ALLOWED_ATTR2 = create(null);
745
+ if (USE_PROFILES.html === true) {
746
+ addToSet(ALLOWED_TAGS2, html$1);
747
+ addToSet(ALLOWED_ATTR2, html);
748
+ }
749
+ if (USE_PROFILES.svg === true) {
750
+ addToSet(ALLOWED_TAGS2, svg$1);
751
+ addToSet(ALLOWED_ATTR2, svg);
752
+ addToSet(ALLOWED_ATTR2, xml);
753
+ }
754
+ if (USE_PROFILES.svgFilters === true) {
755
+ addToSet(ALLOWED_TAGS2, svgFilters);
756
+ addToSet(ALLOWED_ATTR2, svg);
757
+ addToSet(ALLOWED_ATTR2, xml);
758
+ }
759
+ if (USE_PROFILES.mathMl === true) {
760
+ addToSet(ALLOWED_TAGS2, mathMl$1);
761
+ addToSet(ALLOWED_ATTR2, mathMl);
762
+ addToSet(ALLOWED_ATTR2, xml);
763
+ }
764
+ }
765
+ EXTRA_ELEMENT_HANDLING.tagCheck = null;
766
+ EXTRA_ELEMENT_HANDLING.attributeCheck = null;
767
+ if (objectHasOwnProperty(cfg, "ADD_TAGS")) {
768
+ if (typeof cfg.ADD_TAGS === "function") {
769
+ EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;
770
+ } else if (arrayIsArray(cfg.ADD_TAGS)) {
771
+ if (ALLOWED_TAGS2 === DEFAULT_ALLOWED_TAGS) {
772
+ ALLOWED_TAGS2 = clone(ALLOWED_TAGS2);
773
+ }
774
+ addToSet(ALLOWED_TAGS2, cfg.ADD_TAGS, transformCaseFunc);
775
+ }
776
+ }
777
+ if (objectHasOwnProperty(cfg, "ADD_ATTR")) {
778
+ if (typeof cfg.ADD_ATTR === "function") {
779
+ EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;
780
+ } else if (arrayIsArray(cfg.ADD_ATTR)) {
781
+ if (ALLOWED_ATTR2 === DEFAULT_ALLOWED_ATTR) {
782
+ ALLOWED_ATTR2 = clone(ALLOWED_ATTR2);
783
+ }
784
+ addToSet(ALLOWED_ATTR2, cfg.ADD_ATTR, transformCaseFunc);
785
+ }
786
+ }
787
+ if (objectHasOwnProperty(cfg, "ADD_URI_SAFE_ATTR") && arrayIsArray(cfg.ADD_URI_SAFE_ATTR)) {
788
+ addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
789
+ }
790
+ if (objectHasOwnProperty(cfg, "FORBID_CONTENTS") && arrayIsArray(cfg.FORBID_CONTENTS)) {
791
+ if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
792
+ FORBID_CONTENTS = clone(FORBID_CONTENTS);
793
+ }
794
+ addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
795
+ }
796
+ if (objectHasOwnProperty(cfg, "ADD_FORBID_CONTENTS") && arrayIsArray(cfg.ADD_FORBID_CONTENTS)) {
797
+ if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
798
+ FORBID_CONTENTS = clone(FORBID_CONTENTS);
799
+ }
800
+ addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);
801
+ }
802
+ if (KEEP_CONTENT) {
803
+ ALLOWED_TAGS2["#text"] = true;
804
+ }
805
+ if (WHOLE_DOCUMENT) {
806
+ addToSet(ALLOWED_TAGS2, ["html", "head", "body"]);
807
+ }
808
+ if (ALLOWED_TAGS2.table) {
809
+ addToSet(ALLOWED_TAGS2, ["tbody"]);
810
+ delete FORBID_TAGS.tbody;
811
+ }
812
+ if (cfg.TRUSTED_TYPES_POLICY) {
813
+ if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== "function") {
814
+ throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');
815
+ }
816
+ if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== "function") {
817
+ throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');
818
+ }
819
+ trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;
820
+ emptyHTML = trustedTypesPolicy.createHTML("");
821
+ } else {
822
+ if (trustedTypesPolicy === void 0) {
823
+ trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);
824
+ }
825
+ if (trustedTypesPolicy !== null && typeof emptyHTML === "string") {
826
+ emptyHTML = trustedTypesPolicy.createHTML("");
827
+ }
828
+ }
829
+ if ((hooks.uponSanitizeElement.length > 0 || hooks.uponSanitizeAttribute.length > 0) && ALLOWED_TAGS2 === DEFAULT_ALLOWED_TAGS) {
830
+ ALLOWED_TAGS2 = clone(ALLOWED_TAGS2);
831
+ }
832
+ if (hooks.uponSanitizeAttribute.length > 0 && ALLOWED_ATTR2 === DEFAULT_ALLOWED_ATTR) {
833
+ ALLOWED_ATTR2 = clone(ALLOWED_ATTR2);
834
+ }
835
+ if (freeze) {
836
+ freeze(cfg);
837
+ }
838
+ CONFIG = cfg;
839
+ };
840
+ const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);
841
+ const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);
842
+ const _checkValidNamespace = function _checkValidNamespace2(element) {
843
+ let parent = getParentNode(element);
844
+ if (!parent || !parent.tagName) {
845
+ parent = {
846
+ namespaceURI: NAMESPACE,
847
+ tagName: "template"
848
+ };
849
+ }
850
+ const tagName = stringToLowerCase(element.tagName);
851
+ const parentTagName = stringToLowerCase(parent.tagName);
852
+ if (!ALLOWED_NAMESPACES[element.namespaceURI]) {
853
+ return false;
854
+ }
855
+ if (element.namespaceURI === SVG_NAMESPACE) {
856
+ if (parent.namespaceURI === HTML_NAMESPACE) {
857
+ return tagName === "svg";
858
+ }
859
+ if (parent.namespaceURI === MATHML_NAMESPACE) {
860
+ return tagName === "svg" && (parentTagName === "annotation-xml" || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
861
+ }
862
+ return Boolean(ALL_SVG_TAGS[tagName]);
863
+ }
864
+ if (element.namespaceURI === MATHML_NAMESPACE) {
865
+ if (parent.namespaceURI === HTML_NAMESPACE) {
866
+ return tagName === "math";
867
+ }
868
+ if (parent.namespaceURI === SVG_NAMESPACE) {
869
+ return tagName === "math" && HTML_INTEGRATION_POINTS[parentTagName];
870
+ }
871
+ return Boolean(ALL_MATHML_TAGS[tagName]);
872
+ }
873
+ if (element.namespaceURI === HTML_NAMESPACE) {
874
+ if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
875
+ return false;
876
+ }
877
+ if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
878
+ return false;
879
+ }
880
+ return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
881
+ }
882
+ if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && ALLOWED_NAMESPACES[element.namespaceURI]) {
883
+ return true;
884
+ }
885
+ return false;
886
+ };
887
+ const _forceRemove = function _forceRemove2(node) {
888
+ arrayPush(DOMPurify.removed, {
889
+ element: node
890
+ });
891
+ try {
892
+ getParentNode(node).removeChild(node);
893
+ } catch (_2) {
894
+ remove(node);
895
+ }
896
+ };
897
+ const _removeAttribute = function _removeAttribute2(name, element) {
898
+ try {
899
+ arrayPush(DOMPurify.removed, {
900
+ attribute: element.getAttributeNode(name),
901
+ from: element
902
+ });
903
+ } catch (_2) {
904
+ arrayPush(DOMPurify.removed, {
905
+ attribute: null,
906
+ from: element
907
+ });
908
+ }
909
+ element.removeAttribute(name);
910
+ if (name === "is") {
911
+ if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
912
+ try {
913
+ _forceRemove(element);
914
+ } catch (_2) {
915
+ }
916
+ } else {
917
+ try {
918
+ element.setAttribute(name, "");
919
+ } catch (_2) {
920
+ }
921
+ }
922
+ }
923
+ };
924
+ const _initDocument = function _initDocument2(dirty) {
925
+ let doc = null;
926
+ let leadingWhitespace = null;
927
+ if (FORCE_BODY) {
928
+ dirty = "<remove></remove>" + dirty;
929
+ } else {
930
+ const matches = stringMatch(dirty, /^[\r\n\t ]+/);
931
+ leadingWhitespace = matches && matches[0];
932
+ }
933
+ if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && NAMESPACE === HTML_NAMESPACE) {
934
+ dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + "</body></html>";
935
+ }
936
+ const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
937
+ if (NAMESPACE === HTML_NAMESPACE) {
938
+ try {
939
+ doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
940
+ } catch (_2) {
941
+ }
942
+ }
943
+ if (!doc || !doc.documentElement) {
944
+ doc = implementation.createDocument(NAMESPACE, "template", null);
945
+ try {
946
+ doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;
947
+ } catch (_2) {
948
+ }
949
+ }
950
+ const body = doc.body || doc.documentElement;
951
+ if (dirty && leadingWhitespace) {
952
+ body.insertBefore(document2.createTextNode(leadingWhitespace), body.childNodes[0] || null);
953
+ }
954
+ if (NAMESPACE === HTML_NAMESPACE) {
955
+ return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? "html" : "body")[0];
956
+ }
957
+ return WHOLE_DOCUMENT ? doc.documentElement : body;
958
+ };
959
+ const _createNodeIterator = function _createNodeIterator2(root) {
960
+ return createNodeIterator.call(
961
+ root.ownerDocument || root,
962
+ root,
963
+ // eslint-disable-next-line no-bitwise
964
+ NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION,
965
+ null
966
+ );
967
+ };
968
+ const _scrubTemplateExpressions = function _scrubTemplateExpressions2(node) {
969
+ node.normalize();
970
+ const walker = createNodeIterator.call(
971
+ node.ownerDocument || node,
972
+ node,
973
+ // eslint-disable-next-line no-bitwise
974
+ NodeFilter.SHOW_TEXT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_CDATA_SECTION | NodeFilter.SHOW_PROCESSING_INSTRUCTION,
975
+ null
976
+ );
977
+ let currentNode = walker.nextNode();
978
+ while (currentNode) {
979
+ let data = currentNode.data;
980
+ arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], (expr) => {
981
+ data = stringReplace(data, expr, " ");
982
+ });
983
+ currentNode.data = data;
984
+ currentNode = walker.nextNode();
985
+ }
986
+ };
987
+ const _isClobbered = function _isClobbered2(element) {
988
+ const realTagName = getNodeName ? getNodeName(element) : null;
989
+ if (typeof realTagName !== "string") {
990
+ return false;
991
+ }
992
+ if (transformCaseFunc(realTagName) !== "form") {
993
+ return false;
994
+ }
995
+ return typeof element.nodeName !== "string" || typeof element.textContent !== "string" || typeof element.removeChild !== "function" || // Realm-safe NamedNodeMap detection: equality against the cached
996
+ // prototype getter. Clobbered .attributes (e.g. <input name="attributes">)
997
+ // makes the direct read diverge from the cached read; a clean form
998
+ // (same-realm OR foreign-realm) has both reads pointing at the same
999
+ // canonical NamedNodeMap.
1000
+ element.attributes !== getAttributes(element) || typeof element.removeAttribute !== "function" || typeof element.setAttribute !== "function" || typeof element.namespaceURI !== "string" || typeof element.insertBefore !== "function" || typeof element.hasChildNodes !== "function" || // NodeType clobbering probe. Cached Node.prototype.nodeType getter
1001
+ // returns the integer 1 for any Element regardless of realm; direct
1002
+ // read on a clobbered form (e.g. <input name="nodeType">) returns
1003
+ // the named child element. Cheap addition — nodeType is read from
1004
+ // an internal slot, no serialization cost — and removes a residual
1005
+ // clobbering surface used by several mXSS / PI / comment branches
1006
+ // in _sanitizeElements that compare currentNode.nodeType directly.
1007
+ element.nodeType !== getNodeType(element) || // HTMLFormElement has [LegacyOverrideBuiltIns]: a descendant named
1008
+ // "childNodes" shadows the prototype getter. Direct reads of
1009
+ // form.childNodes from a clobbered form return the named child
1010
+ // instead of the real NodeList, so any walk that reads it directly
1011
+ // skips the form's real children. Compare the direct read to the
1012
+ // cached Node.prototype getter — when the form's named-property
1013
+ // getter intercepts the read, the two values differ and we flag
1014
+ // the form. This catches every clobbering child type (input,
1015
+ // select, etc.) regardless of whether the named child happens to
1016
+ // carry a numeric .length, which a typeof-based probe would miss
1017
+ // (e.g. HTMLSelectElement.length is a defined unsigned-long).
1018
+ element.childNodes !== getChildNodes(element);
1019
+ };
1020
+ const _isDocumentFragment = function _isDocumentFragment2(value) {
1021
+ if (!getNodeType || typeof value !== "object" || value === null) {
1022
+ return false;
1023
+ }
1024
+ try {
1025
+ return getNodeType(value) === NODE_TYPE.documentFragment;
1026
+ } catch (_2) {
1027
+ return false;
1028
+ }
1029
+ };
1030
+ const _isNode = function _isNode2(value) {
1031
+ if (!getNodeType || typeof value !== "object" || value === null) {
1032
+ return false;
1033
+ }
1034
+ try {
1035
+ return typeof getNodeType(value) === "number";
1036
+ } catch (_2) {
1037
+ return false;
1038
+ }
1039
+ };
1040
+ function _executeHooks(hooks2, currentNode, data) {
1041
+ arrayForEach(hooks2, (hook) => {
1042
+ hook.call(DOMPurify, currentNode, data, CONFIG);
1043
+ });
1044
+ }
1045
+ const _sanitizeElements = function _sanitizeElements2(currentNode) {
1046
+ let content = null;
1047
+ _executeHooks(hooks.beforeSanitizeElements, currentNode, null);
1048
+ if (_isClobbered(currentNode)) {
1049
+ _forceRemove(currentNode);
1050
+ return true;
1051
+ }
1052
+ const tagName = transformCaseFunc(currentNode.nodeName);
1053
+ _executeHooks(hooks.uponSanitizeElement, currentNode, {
1054
+ tagName,
1055
+ allowedTags: ALLOWED_TAGS2
1056
+ });
1057
+ if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w!]/g, currentNode.innerHTML) && regExpTest(/<[/\w!]/g, currentNode.textContent)) {
1058
+ _forceRemove(currentNode);
1059
+ return true;
1060
+ }
1061
+ if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && tagName === "style" && _isNode(currentNode.firstElementChild)) {
1062
+ _forceRemove(currentNode);
1063
+ return true;
1064
+ }
1065
+ if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
1066
+ _forceRemove(currentNode);
1067
+ return true;
1068
+ }
1069
+ if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(/<[/\w]/g, currentNode.data)) {
1070
+ _forceRemove(currentNode);
1071
+ return true;
1072
+ }
1073
+ if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS2[tagName]) {
1074
+ if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
1075
+ if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
1076
+ return false;
1077
+ }
1078
+ if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {
1079
+ return false;
1080
+ }
1081
+ }
1082
+ if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
1083
+ const parentNode = getParentNode(currentNode);
1084
+ const childNodes = getChildNodes(currentNode);
1085
+ if (childNodes && parentNode) {
1086
+ const childCount = childNodes.length;
1087
+ for (let i = childCount - 1; i >= 0; --i) {
1088
+ const childClone = cloneNode(childNodes[i], true);
1089
+ parentNode.insertBefore(childClone, getNextSibling(currentNode));
1090
+ }
1091
+ }
1092
+ }
1093
+ _forceRemove(currentNode);
1094
+ return true;
1095
+ }
1096
+ const nt2 = getNodeType ? getNodeType(currentNode) : currentNode.nodeType;
1097
+ if (nt2 === NODE_TYPE.element && !_checkValidNamespace(currentNode)) {
1098
+ _forceRemove(currentNode);
1099
+ return true;
1100
+ }
1101
+ if ((tagName === "noscript" || tagName === "noembed" || tagName === "noframes") && regExpTest(/<\/no(script|embed|frames)/i, currentNode.innerHTML)) {
1102
+ _forceRemove(currentNode);
1103
+ return true;
1104
+ }
1105
+ if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
1106
+ content = currentNode.textContent;
1107
+ arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], (expr) => {
1108
+ content = stringReplace(content, expr, " ");
1109
+ });
1110
+ if (currentNode.textContent !== content) {
1111
+ arrayPush(DOMPurify.removed, {
1112
+ element: currentNode.cloneNode()
1113
+ });
1114
+ currentNode.textContent = content;
1115
+ }
1116
+ }
1117
+ _executeHooks(hooks.afterSanitizeElements, currentNode, null);
1118
+ return false;
1119
+ };
1120
+ const _isValidAttribute = function _isValidAttribute2(lcTag, lcName, value) {
1121
+ if (FORBID_ATTR[lcName]) {
1122
+ return false;
1123
+ }
1124
+ if (SANITIZE_DOM && (lcName === "id" || lcName === "name") && (value in document2 || value in formElement)) {
1125
+ return false;
1126
+ }
1127
+ const nameIsPermitted = ALLOWED_ATTR2[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
1128
+ if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$1, lcName)) ;
1129
+ else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) ;
1130
+ else if (!nameIsPermitted || FORBID_ATTR[lcName]) {
1131
+ if (
1132
+ // First condition does a very basic check if a) it's basically a valid custom element tagname AND
1133
+ // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
1134
+ // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
1135
+ _isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName, lcTag)) || // Alternative, second condition checks if it's an `is`-attribute, AND
1136
+ // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
1137
+ lcName === "is" && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))
1138
+ ) ;
1139
+ else {
1140
+ return false;
1141
+ }
1142
+ } else if (URI_SAFE_ATTRIBUTES[lcName]) ;
1143
+ else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) ;
1144
+ else if ((lcName === "src" || lcName === "xlink:href" || lcName === "href") && lcTag !== "script" && stringIndexOf(value, "data:") === 0 && DATA_URI_TAGS[lcTag]) ;
1145
+ else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) ;
1146
+ else if (value) {
1147
+ return false;
1148
+ } else ;
1149
+ return true;
1150
+ };
1151
+ const RESERVED_CUSTOM_ELEMENT_NAMES = addToSet({}, ["annotation-xml", "color-profile", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "missing-glyph"]);
1152
+ const _isBasicCustomElement = function _isBasicCustomElement2(tagName) {
1153
+ return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT$1, tagName);
1154
+ };
1155
+ const _sanitizeAttributes = function _sanitizeAttributes2(currentNode) {
1156
+ _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
1157
+ const attributes = currentNode.attributes;
1158
+ if (!attributes || _isClobbered(currentNode)) {
1159
+ return;
1160
+ }
1161
+ const hookEvent = {
1162
+ attrName: "",
1163
+ attrValue: "",
1164
+ keepAttr: true,
1165
+ allowedAttributes: ALLOWED_ATTR2,
1166
+ forceKeepAttr: void 0
1167
+ };
1168
+ let l3 = attributes.length;
1169
+ while (l3--) {
1170
+ const attr = attributes[l3];
1171
+ const name = attr.name, namespaceURI = attr.namespaceURI, attrValue = attr.value;
1172
+ const lcName = transformCaseFunc(name);
1173
+ const initValue = attrValue;
1174
+ let value = name === "value" ? initValue : stringTrim(initValue);
1175
+ hookEvent.attrName = lcName;
1176
+ hookEvent.attrValue = value;
1177
+ hookEvent.keepAttr = true;
1178
+ hookEvent.forceKeepAttr = void 0;
1179
+ _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);
1180
+ value = hookEvent.attrValue;
1181
+ if (SANITIZE_NAMED_PROPS && (lcName === "id" || lcName === "name") && stringIndexOf(value, SANITIZE_NAMED_PROPS_PREFIX) !== 0) {
1182
+ _removeAttribute(name, currentNode);
1183
+ value = SANITIZE_NAMED_PROPS_PREFIX + value;
1184
+ }
1185
+ if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
1186
+ _removeAttribute(name, currentNode);
1187
+ continue;
1188
+ }
1189
+ if (lcName === "attributename" && stringMatch(value, "href")) {
1190
+ _removeAttribute(name, currentNode);
1191
+ continue;
1192
+ }
1193
+ if (hookEvent.forceKeepAttr) {
1194
+ continue;
1195
+ }
1196
+ if (!hookEvent.keepAttr) {
1197
+ _removeAttribute(name, currentNode);
1198
+ continue;
1199
+ }
1200
+ if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\/>/i, value)) {
1201
+ _removeAttribute(name, currentNode);
1202
+ continue;
1203
+ }
1204
+ if (SAFE_FOR_TEMPLATES) {
1205
+ arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], (expr) => {
1206
+ value = stringReplace(value, expr, " ");
1207
+ });
1208
+ }
1209
+ const lcTag = transformCaseFunc(currentNode.nodeName);
1210
+ if (!_isValidAttribute(lcTag, lcName, value)) {
1211
+ _removeAttribute(name, currentNode);
1212
+ continue;
1213
+ }
1214
+ if (trustedTypesPolicy && typeof trustedTypes === "object" && typeof trustedTypes.getAttributeType === "function") {
1215
+ if (namespaceURI) ;
1216
+ else {
1217
+ switch (trustedTypes.getAttributeType(lcTag, lcName)) {
1218
+ case "TrustedHTML": {
1219
+ value = trustedTypesPolicy.createHTML(value);
1220
+ break;
1221
+ }
1222
+ case "TrustedScriptURL": {
1223
+ value = trustedTypesPolicy.createScriptURL(value);
1224
+ break;
1225
+ }
1226
+ }
1227
+ }
1228
+ }
1229
+ if (value !== initValue) {
1230
+ try {
1231
+ if (namespaceURI) {
1232
+ currentNode.setAttributeNS(namespaceURI, name, value);
1233
+ } else {
1234
+ currentNode.setAttribute(name, value);
1235
+ }
1236
+ if (_isClobbered(currentNode)) {
1237
+ _forceRemove(currentNode);
1238
+ } else {
1239
+ arrayPop(DOMPurify.removed);
1240
+ }
1241
+ } catch (_2) {
1242
+ _removeAttribute(name, currentNode);
1243
+ }
1244
+ }
1245
+ }
1246
+ _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);
1247
+ };
1248
+ const _sanitizeShadowDOM2 = function _sanitizeShadowDOM(fragment) {
1249
+ let shadowNode = null;
1250
+ const shadowIterator = _createNodeIterator(fragment);
1251
+ _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);
1252
+ while (shadowNode = shadowIterator.nextNode()) {
1253
+ _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);
1254
+ _sanitizeElements(shadowNode);
1255
+ _sanitizeAttributes(shadowNode);
1256
+ if (_isDocumentFragment(shadowNode.content)) {
1257
+ _sanitizeShadowDOM2(shadowNode.content);
1258
+ }
1259
+ const shadowNodeType = getNodeType ? getNodeType(shadowNode) : shadowNode.nodeType;
1260
+ if (shadowNodeType === NODE_TYPE.element) {
1261
+ const innerSr = getShadowRoot ? getShadowRoot(shadowNode) : shadowNode.shadowRoot;
1262
+ if (_isDocumentFragment(innerSr)) {
1263
+ _sanitizeAttachedShadowRoots2(innerSr);
1264
+ _sanitizeShadowDOM2(innerSr);
1265
+ }
1266
+ }
1267
+ }
1268
+ _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
1269
+ };
1270
+ const _sanitizeAttachedShadowRoots2 = function _sanitizeAttachedShadowRoots(root) {
1271
+ const nodeType = getNodeType ? getNodeType(root) : root.nodeType;
1272
+ if (nodeType === NODE_TYPE.element) {
1273
+ const sr = getShadowRoot ? getShadowRoot(root) : root.shadowRoot;
1274
+ if (_isDocumentFragment(sr)) {
1275
+ _sanitizeAttachedShadowRoots2(sr);
1276
+ _sanitizeShadowDOM2(sr);
1277
+ }
1278
+ }
1279
+ const childNodes = getChildNodes ? getChildNodes(root) : root.childNodes;
1280
+ if (!childNodes) {
1281
+ return;
1282
+ }
1283
+ const snapshot = [];
1284
+ arrayForEach(childNodes, (child) => {
1285
+ arrayPush(snapshot, child);
1286
+ });
1287
+ for (const child of snapshot) {
1288
+ _sanitizeAttachedShadowRoots2(child);
1289
+ }
1290
+ if (nodeType === NODE_TYPE.element) {
1291
+ const rootName = getNodeName ? getNodeName(root) : null;
1292
+ if (typeof rootName === "string" && transformCaseFunc(rootName) === "template") {
1293
+ const content = root.content;
1294
+ if (_isDocumentFragment(content)) {
1295
+ _sanitizeAttachedShadowRoots2(content);
1296
+ }
1297
+ }
1298
+ }
1299
+ };
1300
+ DOMPurify.sanitize = function(dirty) {
1301
+ let cfg = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
1302
+ let body = null;
1303
+ let importedNode = null;
1304
+ let currentNode = null;
1305
+ let returnNode = null;
1306
+ IS_EMPTY_INPUT = !dirty;
1307
+ if (IS_EMPTY_INPUT) {
1308
+ dirty = "<!-->";
1309
+ }
1310
+ if (typeof dirty !== "string" && !_isNode(dirty)) {
1311
+ dirty = stringifyValue(dirty);
1312
+ if (typeof dirty !== "string") {
1313
+ throw typeErrorCreate("dirty is not a string, aborting");
1314
+ }
1315
+ }
1316
+ if (!DOMPurify.isSupported) {
1317
+ return dirty;
1318
+ }
1319
+ if (!SET_CONFIG) {
1320
+ _parseConfig(cfg);
1321
+ }
1322
+ DOMPurify.removed = [];
1323
+ if (typeof dirty === "string") {
1324
+ IN_PLACE = false;
1325
+ }
1326
+ if (IN_PLACE) {
1327
+ const nn = getNodeName ? getNodeName(dirty) : dirty.nodeName;
1328
+ if (typeof nn === "string") {
1329
+ const tagName = transformCaseFunc(nn);
1330
+ if (!ALLOWED_TAGS2[tagName] || FORBID_TAGS[tagName]) {
1331
+ throw typeErrorCreate("root node is forbidden and cannot be sanitized in-place");
1332
+ }
1333
+ }
1334
+ if (_isClobbered(dirty)) {
1335
+ throw typeErrorCreate("root node is clobbered and cannot be sanitized in-place");
1336
+ }
1337
+ _sanitizeAttachedShadowRoots2(dirty);
1338
+ } else if (_isNode(dirty)) {
1339
+ body = _initDocument("<!---->");
1340
+ importedNode = body.ownerDocument.importNode(dirty, true);
1341
+ if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === "BODY") {
1342
+ body = importedNode;
1343
+ } else if (importedNode.nodeName === "HTML") {
1344
+ body = importedNode;
1345
+ } else {
1346
+ body.appendChild(importedNode);
1347
+ }
1348
+ _sanitizeAttachedShadowRoots2(importedNode);
1349
+ } else {
1350
+ if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && // eslint-disable-next-line unicorn/prefer-includes
1351
+ dirty.indexOf("<") === -1) {
1352
+ return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
1353
+ }
1354
+ body = _initDocument(dirty);
1355
+ if (!body) {
1356
+ return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : "";
1357
+ }
1358
+ }
1359
+ if (body && FORCE_BODY) {
1360
+ _forceRemove(body.firstChild);
1361
+ }
1362
+ const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);
1363
+ while (currentNode = nodeIterator.nextNode()) {
1364
+ _sanitizeElements(currentNode);
1365
+ _sanitizeAttributes(currentNode);
1366
+ if (_isDocumentFragment(currentNode.content)) {
1367
+ _sanitizeShadowDOM2(currentNode.content);
1368
+ }
1369
+ }
1370
+ if (IN_PLACE) {
1371
+ if (SAFE_FOR_TEMPLATES) {
1372
+ _scrubTemplateExpressions(dirty);
1373
+ }
1374
+ return dirty;
1375
+ }
1376
+ if (RETURN_DOM) {
1377
+ if (SAFE_FOR_TEMPLATES) {
1378
+ _scrubTemplateExpressions(body);
1379
+ }
1380
+ if (RETURN_DOM_FRAGMENT) {
1381
+ returnNode = createDocumentFragment.call(body.ownerDocument);
1382
+ while (body.firstChild) {
1383
+ returnNode.appendChild(body.firstChild);
1384
+ }
1385
+ } else {
1386
+ returnNode = body;
1387
+ }
1388
+ if (ALLOWED_ATTR2.shadowroot || ALLOWED_ATTR2.shadowrootmode) {
1389
+ returnNode = importNode.call(originalDocument, returnNode, true);
1390
+ }
1391
+ return returnNode;
1392
+ }
1393
+ let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
1394
+ if (WHOLE_DOCUMENT && ALLOWED_TAGS2["!doctype"] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
1395
+ serializedHTML = "<!DOCTYPE " + body.ownerDocument.doctype.name + ">\n" + serializedHTML;
1396
+ }
1397
+ if (SAFE_FOR_TEMPLATES) {
1398
+ arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], (expr) => {
1399
+ serializedHTML = stringReplace(serializedHTML, expr, " ");
1400
+ });
1401
+ }
1402
+ return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
1403
+ };
1404
+ DOMPurify.setConfig = function() {
1405
+ let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
1406
+ _parseConfig(cfg);
1407
+ SET_CONFIG = true;
1408
+ };
1409
+ DOMPurify.clearConfig = function() {
1410
+ CONFIG = null;
1411
+ SET_CONFIG = false;
1412
+ };
1413
+ DOMPurify.isValidAttribute = function(tag, attr, value) {
1414
+ if (!CONFIG) {
1415
+ _parseConfig({});
1416
+ }
1417
+ const lcTag = transformCaseFunc(tag);
1418
+ const lcName = transformCaseFunc(attr);
1419
+ return _isValidAttribute(lcTag, lcName, value);
1420
+ };
1421
+ DOMPurify.addHook = function(entryPoint, hookFunction) {
1422
+ if (typeof hookFunction !== "function") {
1423
+ return;
1424
+ }
1425
+ arrayPush(hooks[entryPoint], hookFunction);
1426
+ };
1427
+ DOMPurify.removeHook = function(entryPoint, hookFunction) {
1428
+ if (hookFunction !== void 0) {
1429
+ const index = arrayLastIndexOf(hooks[entryPoint], hookFunction);
1430
+ return index === -1 ? void 0 : arraySplice(hooks[entryPoint], index, 1)[0];
1431
+ }
1432
+ return arrayPop(hooks[entryPoint]);
1433
+ };
1434
+ DOMPurify.removeHooks = function(entryPoint) {
1435
+ hooks[entryPoint] = [];
1436
+ };
1437
+ DOMPurify.removeAllHooks = function() {
1438
+ hooks = _createHooksMap();
1439
+ };
1440
+ return DOMPurify;
1441
+ }
1442
+ var purify = createDOMPurify();
1443
+
1444
+ // node_modules/.pnpm/marked@18.0.4/node_modules/marked/lib/marked.esm.js
1445
+ function M() {
1446
+ return { async: false, breaks: false, extensions: null, gfm: true, hooks: null, pedantic: false, renderer: null, silent: false, tokenizer: null, walkTokens: null };
1447
+ }
1448
+ var T = M();
1449
+ function N(l3) {
1450
+ T = l3;
1451
+ }
1452
+ var _ = { exec: () => null };
1453
+ function E(l3) {
1454
+ let e = [];
1455
+ return (t) => {
1456
+ let n = Math.max(0, Math.min(3, t - 1)), s = e[n];
1457
+ return s || (s = l3(n), e[n] = s), s;
1458
+ };
1459
+ }
1460
+ function d(l3, e = "") {
1461
+ let t = typeof l3 == "string" ? l3 : l3.source, n = { replace: (s, r) => {
1462
+ let i = typeof r == "string" ? r : r.source;
1463
+ return i = i.replace(m.caret, "$1"), t = t.replace(s, i), n;
1464
+ }, getRegex: () => new RegExp(t, e) };
1465
+ return n;
1466
+ }
1467
+ var Te = ((l3 = "") => {
1468
+ try {
1469
+ return !!new RegExp("(?<=1)(?<!1)" + l3);
1470
+ } catch {
1471
+ return false;
1472
+ }
1473
+ })();
1474
+ var m = { codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm, outputLinkReplace: /\\([\[\]])/g, indentCodeCompensation: /^(\s+)(?:```)/, beginningSpace: /^\s+/, endingHash: /#$/, startingSpaceChar: /^ /, endingSpaceChar: / $/, nonSpaceChar: /[^ ]/, newLineCharGlobal: /\n/g, tabCharGlobal: /\t/g, multipleSpaceGlobal: /\s+/g, blankLine: /^[ \t]*$/, doubleBlankLine: /\n[ \t]*\n[ \t]*$/, blockquoteStart: /^ {0,3}>/, blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g, blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm, listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g, listIsTask: /^\[[ xX]\] +\S/, listReplaceTask: /^\[[ xX]\] +/, listTaskCheckbox: /\[[ xX]\]/, anyLine: /\n.*\n/, hrefBrackets: /^<(.*)>$/, tableDelimiter: /[:|]/, tableAlignChars: /^\||\| *$/g, tableRowBlankLine: /\n[ \t]*$/, tableAlignRight: /^ *-+: *$/, tableAlignCenter: /^ *:-+: *$/, tableAlignLeft: /^ *:-+ *$/, startATag: /^<a /i, endATag: /^<\/a>/i, startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i, endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i, startAngleBracket: /^</, endAngleBracket: />$/, pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/, unicodeAlphaNumeric: /[\p{L}\p{N}]/u, escapeTest: /[&<>"']/, escapeReplace: /[&<>"']/g, escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/, escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g, caret: /(^|[^\[])\^/g, percentDecode: /%25/g, findPipe: /\|/g, splitPipe: / \|/, slashPipe: /\\\|/g, carriageReturn: /\r\n|\r/g, spaceLine: /^ +$/gm, notSpaceStart: /^\S*/, endingNewline: /\n$/, listItemRegex: (l3) => new RegExp(`^( {0,3}${l3})((?:[ ][^\\n]*)?(?:\\n|$))`), nextBulletRegex: E((l3) => new RegExp(`^ {0,${l3}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`)), hrRegex: E((l3) => new RegExp(`^ {0,${l3}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`)), fencesBeginRegex: E((l3) => new RegExp(`^ {0,${l3}}(?:\`\`\`|~~~)`)), headingBeginRegex: E((l3) => new RegExp(`^ {0,${l3}}#`)), htmlBeginRegex: E((l3) => new RegExp(`^ {0,${l3}}<(?:[a-z].*>|!--)`, "i")), blockquoteBeginRegex: E((l3) => new RegExp(`^ {0,${l3}}>`)) };
1475
+ var Oe = /^(?:[ \t]*(?:\n|$))+/;
1476
+ var we = /^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/;
1477
+ var ye = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/;
1478
+ var B = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/;
1479
+ var Pe = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/;
1480
+ var j = / {0,3}(?:[*+-]|\d{1,9}[.)])/;
1481
+ var oe = /^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/;
1482
+ var ae = d(oe).replace(/bull/g, j).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/\|table/g, "").getRegex();
1483
+ var Se = d(oe).replace(/bull/g, j).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/table/g, / {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex();
1484
+ var F = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/;
1485
+ var $e = /^[^\n]+/;
1486
+ var U = /(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/;
1487
+ var Le = d(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label", U).replace("title", /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex();
1488
+ var _e = d(/^(bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g, j).getRegex();
1489
+ var H = "address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul";
1490
+ var K = /<!--(?:-?>|[\s\S]*?(?:-->|$))/;
1491
+ var ze = d("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|<![A-Z][\\s\\S]*?(?:>\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))", "i").replace("comment", K).replace("tag", H).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
1492
+ var le = d(F).replace("hr", B).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", H).getRegex();
1493
+ var Me = d(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph", le).getRegex();
1494
+ var W = { blockquote: Me, code: we, def: Le, fences: ye, heading: Pe, hr: B, html: ze, lheading: ae, list: _e, newline: Oe, paragraph: le, table: _, text: $e };
1495
+ var se = d("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr", B).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("blockquote", " {0,3}>").replace("code", "(?: {4}| {0,3} )[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", H).getRegex();
1496
+ var Ee = { ...W, lheading: Se, table: se, paragraph: d(F).replace("hr", B).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("table", se).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", H).getRegex() };
1497
+ var Ie = { ...W, html: d(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", K).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(), def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, heading: /^(#{1,6})(.*)(?:\n+|$)/, fences: _, lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, paragraph: d(F).replace("hr", B).replace("heading", ` *#{1,6} *[^
1498
+ ]`).replace("lheading", ae).replace("|table", "").replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").replace("|tag", "").getRegex() };
1499
+ var Ae = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/;
1500
+ var Ce = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/;
1501
+ var ue = /^( {2,}|\\)\n(?!\s*$)/;
1502
+ var Be = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/;
1503
+ var I = /[\p{P}\p{S}]/u;
1504
+ var Z = /[\s\p{P}\p{S}]/u;
1505
+ var X = /[^\s\p{P}\p{S}]/u;
1506
+ var De = d(/^((?![*_])punctSpace)/, "u").replace(/punctSpace/g, Z).getRegex();
1507
+ var pe = /(?!~)[\p{P}\p{S}]/u;
1508
+ var qe = /(?!~)[\s\p{P}\p{S}]/u;
1509
+ var ve = /(?:[^\s\p{P}\p{S}]|~)/u;
1510
+ var He = d(/link|precode-code|html/, "g").replace("link", /\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-", Te ? "(?<!`)()" : "(^^|[^`])").replace("code", /(?<b>`+)[^`]+\k<b>(?!`)/).replace("html", /<(?! )[^<>]*?>/).getRegex();
1511
+ var ce = /^(?:\*+(?:((?!\*)punct)|([^\s*]))?)|^_+(?:((?!_)punct)|([^\s_]))?/;
1512
+ var Ze = d(ce, "u").replace(/punct/g, I).getRegex();
1513
+ var Ge = d(ce, "u").replace(/punct/g, pe).getRegex();
1514
+ var he = "^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)";
1515
+ var Ne = d(he, "gu").replace(/notPunctSpace/g, X).replace(/punctSpace/g, Z).replace(/punct/g, I).getRegex();
1516
+ var Qe = d(he, "gu").replace(/notPunctSpace/g, ve).replace(/punctSpace/g, qe).replace(/punct/g, pe).getRegex();
1517
+ var je = d("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)", "gu").replace(/notPunctSpace/g, X).replace(/punctSpace/g, Z).replace(/punct/g, I).getRegex();
1518
+ var Fe = d(/^~~?(?:((?!~)punct)|[^\s~])/, "u").replace(/punct/g, I).getRegex();
1519
+ var Ue = "^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)";
1520
+ var Ke = d(Ue, "gu").replace(/notPunctSpace/g, X).replace(/punctSpace/g, Z).replace(/punct/g, I).getRegex();
1521
+ var We = d(/\\(punct)/, "gu").replace(/punct/g, I).getRegex();
1522
+ var Xe = d(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme", /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email", /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex();
1523
+ var Je = d(K).replace("(?:-->|$)", "-->").getRegex();
1524
+ var Ve = d("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment", Je).replace("attribute", /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex();
1525
+ var v = /(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/;
1526
+ var Ye = d(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?\s*\)/).replace("label", v).replace("href", /<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title", /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex();
1527
+ var ke = d(/^!?\[(label)\]\[(ref)\]/).replace("label", v).replace("ref", U).getRegex();
1528
+ var de = d(/^!?\[(ref)\](?:\[\])?/).replace("ref", U).getRegex();
1529
+ var et = d("reflink|nolink(?!\\()", "g").replace("reflink", ke).replace("nolink", de).getRegex();
1530
+ var ie = /[hH][tT][tT][pP][sS]?|[fF][tT][pP]/;
1531
+ var J = { _backpedal: _, anyPunctuation: We, autolink: Xe, blockSkip: He, br: ue, code: Ce, del: _, delLDelim: _, delRDelim: _, emStrongLDelim: Ze, emStrongRDelimAst: Ne, emStrongRDelimUnd: je, escape: Ae, link: Ye, nolink: de, punctuation: De, reflink: ke, reflinkSearch: et, tag: Ve, text: Be, url: _ };
1532
+ var tt = { ...J, link: d(/^!?\[(label)\]\((.*?)\)/).replace("label", v).getRegex(), reflink: d(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", v).getRegex() };
1533
+ var Q = { ...J, emStrongRDelimAst: Qe, emStrongLDelim: Ge, delLDelim: Fe, delRDelim: Ke, url: d(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol", ie).replace("email", /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(), _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, del: /^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/, text: d(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|protocol:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/).replace("protocol", ie).getRegex() };
1534
+ var nt = { ...Q, br: d(ue).replace("{2,}", "*").getRegex(), text: d(Q.text).replace("\\b_", "\\b_| {2,}\\n").replace(/\{2,\}/g, "*").getRegex() };
1535
+ var D = { normal: W, gfm: Ee, pedantic: Ie };
1536
+ var A = { normal: J, gfm: Q, breaks: nt, pedantic: tt };
1537
+ var rt = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" };
1538
+ var ge = (l3) => rt[l3];
1539
+ function O(l3, e) {
1540
+ if (e) {
1541
+ if (m.escapeTest.test(l3)) return l3.replace(m.escapeReplace, ge);
1542
+ } else if (m.escapeTestNoEncode.test(l3)) return l3.replace(m.escapeReplaceNoEncode, ge);
1543
+ return l3;
1544
+ }
1545
+ function V(l3) {
1546
+ try {
1547
+ l3 = encodeURI(l3).replace(m.percentDecode, "%");
1548
+ } catch {
1549
+ return null;
1550
+ }
1551
+ return l3;
1552
+ }
1553
+ function Y(l3, e) {
1554
+ let t = l3.replace(m.findPipe, (r, i, o) => {
1555
+ let u = false, a = i;
1556
+ for (; --a >= 0 && o[a] === "\\"; ) u = !u;
1557
+ return u ? "|" : " |";
1558
+ }), n = t.split(m.splitPipe), s = 0;
1559
+ if (n[0].trim() || n.shift(), n.length > 0 && !n.at(-1)?.trim() && n.pop(), e) if (n.length > e) n.splice(e);
1560
+ else for (; n.length < e; ) n.push("");
1561
+ for (; s < n.length; s++) n[s] = n[s].trim().replace(m.slashPipe, "|");
1562
+ return n;
1563
+ }
1564
+ function $(l3, e, t) {
1565
+ let n = l3.length;
1566
+ if (n === 0) return "";
1567
+ let s = 0;
1568
+ for (; s < n; ) {
1569
+ let r = l3.charAt(n - s - 1);
1570
+ if (r === e && !t) s++;
1571
+ else if (r !== e && t) s++;
1572
+ else break;
1573
+ }
1574
+ return l3.slice(0, n - s);
1575
+ }
1576
+ function ee(l3) {
1577
+ let e = l3.split(`
1578
+ `), t = e.length - 1;
1579
+ for (; t >= 0 && m.blankLine.test(e[t]); ) t--;
1580
+ return e.length - t <= 2 ? l3 : e.slice(0, t + 1).join(`
1581
+ `);
1582
+ }
1583
+ function fe(l3, e) {
1584
+ if (l3.indexOf(e[1]) === -1) return -1;
1585
+ let t = 0;
1586
+ for (let n = 0; n < l3.length; n++) if (l3[n] === "\\") n++;
1587
+ else if (l3[n] === e[0]) t++;
1588
+ else if (l3[n] === e[1] && (t--, t < 0)) return n;
1589
+ return t > 0 ? -2 : -1;
1590
+ }
1591
+ function me(l3, e = 0) {
1592
+ let t = e, n = "";
1593
+ for (let s of l3) if (s === " ") {
1594
+ let r = 4 - t % 4;
1595
+ n += " ".repeat(r), t += r;
1596
+ } else n += s, t++;
1597
+ return n;
1598
+ }
1599
+ function xe(l3, e, t, n, s) {
1600
+ let r = e.href, i = e.title || null, o = l3[1].replace(s.other.outputLinkReplace, "$1");
1601
+ n.state.inLink = true;
1602
+ let u = { type: l3[0].charAt(0) === "!" ? "image" : "link", raw: t, href: r, title: i, text: o, tokens: n.inlineTokens(o) };
1603
+ return n.state.inLink = false, u;
1604
+ }
1605
+ function st(l3, e, t) {
1606
+ let n = l3.match(t.other.indentCodeCompensation);
1607
+ if (n === null) return e;
1608
+ let s = n[1];
1609
+ return e.split(`
1610
+ `).map((r) => {
1611
+ let i = r.match(t.other.beginningSpace);
1612
+ if (i === null) return r;
1613
+ let [o] = i;
1614
+ return o.length >= s.length ? r.slice(s.length) : r;
1615
+ }).join(`
1616
+ `);
1617
+ }
1618
+ var w = class {
1619
+ options;
1620
+ rules;
1621
+ lexer;
1622
+ constructor(e) {
1623
+ this.options = e || T;
1624
+ }
1625
+ space(e) {
1626
+ let t = this.rules.block.newline.exec(e);
1627
+ if (t && t[0].length > 0) return { type: "space", raw: t[0] };
1628
+ }
1629
+ code(e) {
1630
+ let t = this.rules.block.code.exec(e);
1631
+ if (t) {
1632
+ let n = this.options.pedantic ? t[0] : ee(t[0]), s = n.replace(this.rules.other.codeRemoveIndent, "");
1633
+ return { type: "code", raw: n, codeBlockStyle: "indented", text: s };
1634
+ }
1635
+ }
1636
+ fences(e) {
1637
+ let t = this.rules.block.fences.exec(e);
1638
+ if (t) {
1639
+ let n = t[0], s = st(n, t[3] || "", this.rules);
1640
+ return { type: "code", raw: n, lang: t[2] ? t[2].trim().replace(this.rules.inline.anyPunctuation, "$1") : t[2], text: s };
1641
+ }
1642
+ }
1643
+ heading(e) {
1644
+ let t = this.rules.block.heading.exec(e);
1645
+ if (t) {
1646
+ let n = t[2].trim();
1647
+ if (this.rules.other.endingHash.test(n)) {
1648
+ let s = $(n, "#");
1649
+ (this.options.pedantic || !s || this.rules.other.endingSpaceChar.test(s)) && (n = s.trim());
1650
+ }
1651
+ return { type: "heading", raw: $(t[0], `
1652
+ `), depth: t[1].length, text: n, tokens: this.lexer.inline(n) };
1653
+ }
1654
+ }
1655
+ hr(e) {
1656
+ let t = this.rules.block.hr.exec(e);
1657
+ if (t) return { type: "hr", raw: $(t[0], `
1658
+ `) };
1659
+ }
1660
+ blockquote(e) {
1661
+ let t = this.rules.block.blockquote.exec(e);
1662
+ if (t) {
1663
+ let n = $(t[0], `
1664
+ `).split(`
1665
+ `), s = "", r = "", i = [];
1666
+ for (; n.length > 0; ) {
1667
+ let o = false, u = [], a;
1668
+ for (a = 0; a < n.length; a++) if (this.rules.other.blockquoteStart.test(n[a])) u.push(n[a]), o = true;
1669
+ else if (!o) u.push(n[a]);
1670
+ else break;
1671
+ n = n.slice(a);
1672
+ let c = u.join(`
1673
+ `), p = c.replace(this.rules.other.blockquoteSetextReplace, `
1674
+ $1`).replace(this.rules.other.blockquoteSetextReplace2, "");
1675
+ s = s ? `${s}
1676
+ ${c}` : c, r = r ? `${r}
1677
+ ${p}` : p;
1678
+ let k = this.lexer.state.top;
1679
+ if (this.lexer.state.top = true, this.lexer.blockTokens(p, i, true), this.lexer.state.top = k, n.length === 0) break;
1680
+ let h = i.at(-1);
1681
+ if (h?.type === "code") break;
1682
+ if (h?.type === "blockquote") {
1683
+ let R = h, f = R.raw + `
1684
+ ` + n.join(`
1685
+ `), S = this.blockquote(f);
1686
+ i[i.length - 1] = S, s = s.substring(0, s.length - R.raw.length) + S.raw, r = r.substring(0, r.length - R.text.length) + S.text;
1687
+ break;
1688
+ } else if (h?.type === "list") {
1689
+ let R = h, f = R.raw + `
1690
+ ` + n.join(`
1691
+ `), S = this.list(f);
1692
+ i[i.length - 1] = S, s = s.substring(0, s.length - h.raw.length) + S.raw, r = r.substring(0, r.length - R.raw.length) + S.raw, n = f.substring(i.at(-1).raw.length).split(`
1693
+ `);
1694
+ continue;
1695
+ }
1696
+ }
1697
+ return { type: "blockquote", raw: s, tokens: i, text: r };
1698
+ }
1699
+ }
1700
+ list(e) {
1701
+ let t = this.rules.block.list.exec(e);
1702
+ if (t) {
1703
+ let n = t[1].trim(), s = n.length > 1, r = { type: "list", raw: "", ordered: s, start: s ? +n.slice(0, -1) : "", loose: false, items: [] };
1704
+ n = s ? `\\d{1,9}\\${n.slice(-1)}` : `\\${n}`, this.options.pedantic && (n = s ? n : "[*+-]");
1705
+ let i = this.rules.other.listItemRegex(n), o = false;
1706
+ for (; e; ) {
1707
+ let a = false, c = "", p = "";
1708
+ if (!(t = i.exec(e)) || this.rules.block.hr.test(e)) break;
1709
+ c = t[0], e = e.substring(c.length);
1710
+ let k = me(t[2].split(`
1711
+ `, 1)[0], t[1].length), h = e.split(`
1712
+ `, 1)[0], R = !k.trim(), f = 0;
1713
+ if (this.options.pedantic ? (f = 2, p = k.trimStart()) : R ? f = t[1].length + 1 : (f = k.search(this.rules.other.nonSpaceChar), f = f > 4 ? 1 : f, p = k.slice(f), f += t[1].length), R && this.rules.other.blankLine.test(h) && (c += h + `
1714
+ `, e = e.substring(h.length + 1), a = true), !a) {
1715
+ let S = this.rules.other.nextBulletRegex(f), te = this.rules.other.hrRegex(f), ne = this.rules.other.fencesBeginRegex(f), re = this.rules.other.headingBeginRegex(f), be = this.rules.other.htmlBeginRegex(f), Re = this.rules.other.blockquoteBeginRegex(f);
1716
+ for (; e; ) {
1717
+ let G = e.split(`
1718
+ `, 1)[0], C;
1719
+ if (h = G, this.options.pedantic ? (h = h.replace(this.rules.other.listReplaceNesting, " "), C = h) : C = h.replace(this.rules.other.tabCharGlobal, " "), ne.test(h) || re.test(h) || be.test(h) || Re.test(h) || S.test(h) || te.test(h)) break;
1720
+ if (C.search(this.rules.other.nonSpaceChar) >= f || !h.trim()) p += `
1721
+ ` + C.slice(f);
1722
+ else {
1723
+ if (R || k.replace(this.rules.other.tabCharGlobal, " ").search(this.rules.other.nonSpaceChar) >= 4 || ne.test(k) || re.test(k) || te.test(k)) break;
1724
+ p += `
1725
+ ` + h;
1726
+ }
1727
+ R = !h.trim(), c += G + `
1728
+ `, e = e.substring(G.length + 1), k = C.slice(f);
1729
+ }
1730
+ }
1731
+ r.loose || (o ? r.loose = true : this.rules.other.doubleBlankLine.test(c) && (o = true)), r.items.push({ type: "list_item", raw: c, task: !!this.options.gfm && this.rules.other.listIsTask.test(p), loose: false, text: p, tokens: [] }), r.raw += c;
1732
+ }
1733
+ let u = r.items.at(-1);
1734
+ if (u) u.raw = u.raw.trimEnd(), u.text = u.text.trimEnd();
1735
+ else return;
1736
+ r.raw = r.raw.trimEnd();
1737
+ for (let a of r.items) {
1738
+ this.lexer.state.top = false, a.tokens = this.lexer.blockTokens(a.text, []);
1739
+ let c = a.tokens[0];
1740
+ if (a.task && (c?.type === "text" || c?.type === "paragraph")) {
1741
+ a.text = a.text.replace(this.rules.other.listReplaceTask, ""), c.raw = c.raw.replace(this.rules.other.listReplaceTask, ""), c.text = c.text.replace(this.rules.other.listReplaceTask, "");
1742
+ for (let k = this.lexer.inlineQueue.length - 1; k >= 0; k--) if (this.rules.other.listIsTask.test(this.lexer.inlineQueue[k].src)) {
1743
+ this.lexer.inlineQueue[k].src = this.lexer.inlineQueue[k].src.replace(this.rules.other.listReplaceTask, "");
1744
+ break;
1745
+ }
1746
+ let p = this.rules.other.listTaskCheckbox.exec(a.raw);
1747
+ if (p) {
1748
+ let k = { type: "checkbox", raw: p[0] + " ", checked: p[0] !== "[ ]" };
1749
+ a.checked = k.checked, r.loose ? a.tokens[0] && ["paragraph", "text"].includes(a.tokens[0].type) && "tokens" in a.tokens[0] && a.tokens[0].tokens ? (a.tokens[0].raw = k.raw + a.tokens[0].raw, a.tokens[0].text = k.raw + a.tokens[0].text, a.tokens[0].tokens.unshift(k)) : a.tokens.unshift({ type: "paragraph", raw: k.raw, text: k.raw, tokens: [k] }) : a.tokens.unshift(k);
1750
+ }
1751
+ } else a.task && (a.task = false);
1752
+ if (!r.loose) {
1753
+ let p = a.tokens.filter((h) => h.type === "space"), k = p.length > 0 && p.some((h) => this.rules.other.anyLine.test(h.raw));
1754
+ r.loose = k;
1755
+ }
1756
+ }
1757
+ if (r.loose) for (let a of r.items) {
1758
+ a.loose = true;
1759
+ for (let c of a.tokens) c.type === "text" && (c.type = "paragraph");
1760
+ }
1761
+ return r;
1762
+ }
1763
+ }
1764
+ html(e) {
1765
+ let t = this.rules.block.html.exec(e);
1766
+ if (t) {
1767
+ let n = ee(t[0]);
1768
+ return { type: "html", block: true, raw: n, pre: t[1] === "pre" || t[1] === "script" || t[1] === "style", text: n };
1769
+ }
1770
+ }
1771
+ def(e) {
1772
+ let t = this.rules.block.def.exec(e);
1773
+ if (t) {
1774
+ let n = t[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, " "), s = t[2] ? t[2].replace(this.rules.other.hrefBrackets, "$1").replace(this.rules.inline.anyPunctuation, "$1") : "", r = t[3] ? t[3].substring(1, t[3].length - 1).replace(this.rules.inline.anyPunctuation, "$1") : t[3];
1775
+ return { type: "def", tag: n, raw: $(t[0], `
1776
+ `), href: s, title: r };
1777
+ }
1778
+ }
1779
+ table(e) {
1780
+ let t = this.rules.block.table.exec(e);
1781
+ if (!t || !this.rules.other.tableDelimiter.test(t[2])) return;
1782
+ let n = Y(t[1]), s = t[2].replace(this.rules.other.tableAlignChars, "").split("|"), r = t[3]?.trim() ? t[3].replace(this.rules.other.tableRowBlankLine, "").split(`
1783
+ `) : [], i = { type: "table", raw: $(t[0], `
1784
+ `), header: [], align: [], rows: [] };
1785
+ if (n.length === s.length) {
1786
+ for (let o of s) this.rules.other.tableAlignRight.test(o) ? i.align.push("right") : this.rules.other.tableAlignCenter.test(o) ? i.align.push("center") : this.rules.other.tableAlignLeft.test(o) ? i.align.push("left") : i.align.push(null);
1787
+ for (let o = 0; o < n.length; o++) i.header.push({ text: n[o], tokens: this.lexer.inline(n[o]), header: true, align: i.align[o] });
1788
+ for (let o of r) i.rows.push(Y(o, i.header.length).map((u, a) => ({ text: u, tokens: this.lexer.inline(u), header: false, align: i.align[a] })));
1789
+ return i;
1790
+ }
1791
+ }
1792
+ lheading(e) {
1793
+ let t = this.rules.block.lheading.exec(e);
1794
+ if (t) {
1795
+ let n = t[1].trim();
1796
+ return { type: "heading", raw: $(t[0], `
1797
+ `), depth: t[2].charAt(0) === "=" ? 1 : 2, text: n, tokens: this.lexer.inline(n) };
1798
+ }
1799
+ }
1800
+ paragraph(e) {
1801
+ let t = this.rules.block.paragraph.exec(e);
1802
+ if (t) {
1803
+ let n = t[1].charAt(t[1].length - 1) === `
1804
+ ` ? t[1].slice(0, -1) : t[1];
1805
+ return { type: "paragraph", raw: t[0], text: n, tokens: this.lexer.inline(n) };
1806
+ }
1807
+ }
1808
+ text(e) {
1809
+ let t = this.rules.block.text.exec(e);
1810
+ if (t) return { type: "text", raw: t[0], text: t[0], tokens: this.lexer.inline(t[0]) };
1811
+ }
1812
+ escape(e) {
1813
+ let t = this.rules.inline.escape.exec(e);
1814
+ if (t) return { type: "escape", raw: t[0], text: t[1] };
1815
+ }
1816
+ tag(e) {
1817
+ let t = this.rules.inline.tag.exec(e);
1818
+ if (t) return !this.lexer.state.inLink && this.rules.other.startATag.test(t[0]) ? this.lexer.state.inLink = true : this.lexer.state.inLink && this.rules.other.endATag.test(t[0]) && (this.lexer.state.inLink = false), !this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(t[0]) ? this.lexer.state.inRawBlock = true : this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(t[0]) && (this.lexer.state.inRawBlock = false), { type: "html", raw: t[0], inLink: this.lexer.state.inLink, inRawBlock: this.lexer.state.inRawBlock, block: false, text: t[0] };
1819
+ }
1820
+ link(e) {
1821
+ let t = this.rules.inline.link.exec(e);
1822
+ if (t) {
1823
+ let n = t[2].trim();
1824
+ if (!this.options.pedantic && this.rules.other.startAngleBracket.test(n)) {
1825
+ if (!this.rules.other.endAngleBracket.test(n)) return;
1826
+ let i = $(n.slice(0, -1), "\\");
1827
+ if ((n.length - i.length) % 2 === 0) return;
1828
+ } else {
1829
+ let i = fe(t[2], "()");
1830
+ if (i === -2) return;
1831
+ if (i > -1) {
1832
+ let u = (t[0].indexOf("!") === 0 ? 5 : 4) + t[1].length + i;
1833
+ t[2] = t[2].substring(0, i), t[0] = t[0].substring(0, u).trim(), t[3] = "";
1834
+ }
1835
+ }
1836
+ let s = t[2], r = "";
1837
+ if (this.options.pedantic) {
1838
+ let i = this.rules.other.pedanticHrefTitle.exec(s);
1839
+ i && (s = i[1], r = i[3]);
1840
+ } else r = t[3] ? t[3].slice(1, -1) : "";
1841
+ return s = s.trim(), this.rules.other.startAngleBracket.test(s) && (this.options.pedantic && !this.rules.other.endAngleBracket.test(n) ? s = s.slice(1) : s = s.slice(1, -1)), xe(t, { href: s && s.replace(this.rules.inline.anyPunctuation, "$1"), title: r && r.replace(this.rules.inline.anyPunctuation, "$1") }, t[0], this.lexer, this.rules);
1842
+ }
1843
+ }
1844
+ reflink(e, t) {
1845
+ let n;
1846
+ if ((n = this.rules.inline.reflink.exec(e)) || (n = this.rules.inline.nolink.exec(e))) {
1847
+ let s = (n[2] || n[1]).replace(this.rules.other.multipleSpaceGlobal, " "), r = t[s.toLowerCase()];
1848
+ if (!r) {
1849
+ let i = n[0].charAt(0);
1850
+ return { type: "text", raw: i, text: i };
1851
+ }
1852
+ return xe(n, r, n[0], this.lexer, this.rules);
1853
+ }
1854
+ }
1855
+ emStrong(e, t, n = "") {
1856
+ let s = this.rules.inline.emStrongLDelim.exec(e);
1857
+ if (!s || !s[1] && !s[2] && !s[3] && !s[4] || s[4] && n.match(this.rules.other.unicodeAlphaNumeric)) return;
1858
+ if (!(s[1] || s[3] || "") || !n || this.rules.inline.punctuation.exec(n)) {
1859
+ let i = [...s[0]].length - 1, o, u, a = i, c = 0, p = s[0][0] === "*" ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;
1860
+ for (p.lastIndex = 0, t = t.slice(-1 * e.length + i); (s = p.exec(t)) !== null; ) {
1861
+ if (o = s[1] || s[2] || s[3] || s[4] || s[5] || s[6], !o) continue;
1862
+ if (u = [...o].length, s[3] || s[4]) {
1863
+ a += u;
1864
+ continue;
1865
+ } else if ((s[5] || s[6]) && i % 3 && !((i + u) % 3)) {
1866
+ c += u;
1867
+ continue;
1868
+ }
1869
+ if (a -= u, a > 0) continue;
1870
+ u = Math.min(u, u + a + c);
1871
+ let k = [...s[0]][0].length, h = e.slice(0, i + s.index + k + u);
1872
+ if (Math.min(i, u) % 2) {
1873
+ let f = h.slice(1, -1);
1874
+ return { type: "em", raw: h, text: f, tokens: this.lexer.inlineTokens(f) };
1875
+ }
1876
+ let R = h.slice(2, -2);
1877
+ return { type: "strong", raw: h, text: R, tokens: this.lexer.inlineTokens(R) };
1878
+ }
1879
+ }
1880
+ }
1881
+ codespan(e) {
1882
+ let t = this.rules.inline.code.exec(e);
1883
+ if (t) {
1884
+ let n = t[2].replace(this.rules.other.newLineCharGlobal, " "), s = this.rules.other.nonSpaceChar.test(n), r = this.rules.other.startingSpaceChar.test(n) && this.rules.other.endingSpaceChar.test(n);
1885
+ return s && r && (n = n.substring(1, n.length - 1)), { type: "codespan", raw: t[0], text: n };
1886
+ }
1887
+ }
1888
+ br(e) {
1889
+ let t = this.rules.inline.br.exec(e);
1890
+ if (t) return { type: "br", raw: t[0] };
1891
+ }
1892
+ del(e, t, n = "") {
1893
+ let s = this.rules.inline.delLDelim.exec(e);
1894
+ if (!s) return;
1895
+ if (!(s[1] || "") || !n || this.rules.inline.punctuation.exec(n)) {
1896
+ let i = [...s[0]].length - 1, o, u, a = i, c = this.rules.inline.delRDelim;
1897
+ for (c.lastIndex = 0, t = t.slice(-1 * e.length + i); (s = c.exec(t)) !== null; ) {
1898
+ if (o = s[1] || s[2] || s[3] || s[4] || s[5] || s[6], !o || (u = [...o].length, u !== i)) continue;
1899
+ if (s[3] || s[4]) {
1900
+ a += u;
1901
+ continue;
1902
+ }
1903
+ if (a -= u, a > 0) continue;
1904
+ u = Math.min(u, u + a);
1905
+ let p = [...s[0]][0].length, k = e.slice(0, i + s.index + p + u), h = k.slice(i, -i);
1906
+ return { type: "del", raw: k, text: h, tokens: this.lexer.inlineTokens(h) };
1907
+ }
1908
+ }
1909
+ }
1910
+ autolink(e) {
1911
+ let t = this.rules.inline.autolink.exec(e);
1912
+ if (t) {
1913
+ let n, s;
1914
+ return t[2] === "@" ? (n = t[1], s = "mailto:" + n) : (n = t[1], s = n), { type: "link", raw: t[0], text: n, href: s, tokens: [{ type: "text", raw: n, text: n }] };
1915
+ }
1916
+ }
1917
+ url(e) {
1918
+ let t;
1919
+ if (t = this.rules.inline.url.exec(e)) {
1920
+ let n, s;
1921
+ if (t[2] === "@") n = t[0], s = "mailto:" + n;
1922
+ else {
1923
+ let r;
1924
+ do
1925
+ r = t[0], t[0] = this.rules.inline._backpedal.exec(t[0])?.[0] ?? "";
1926
+ while (r !== t[0]);
1927
+ n = t[0], t[1] === "www." ? s = "http://" + t[0] : s = t[0];
1928
+ }
1929
+ return { type: "link", raw: t[0], text: n, href: s, tokens: [{ type: "text", raw: n, text: n }] };
1930
+ }
1931
+ }
1932
+ inlineText(e) {
1933
+ let t = this.rules.inline.text.exec(e);
1934
+ if (t) {
1935
+ let n = this.lexer.state.inRawBlock;
1936
+ return { type: "text", raw: t[0], text: t[0], escaped: n };
1937
+ }
1938
+ }
1939
+ };
1940
+ var x = class l {
1941
+ tokens;
1942
+ options;
1943
+ state;
1944
+ inlineQueue;
1945
+ tokenizer;
1946
+ constructor(e) {
1947
+ this.tokens = [], this.tokens.links = /* @__PURE__ */ Object.create(null), this.options = e || T, this.options.tokenizer = this.options.tokenizer || new w(), this.tokenizer = this.options.tokenizer, this.tokenizer.options = this.options, this.tokenizer.lexer = this, this.inlineQueue = [], this.state = { inLink: false, inRawBlock: false, top: true };
1948
+ let t = { other: m, block: D.normal, inline: A.normal };
1949
+ this.options.pedantic ? (t.block = D.pedantic, t.inline = A.pedantic) : this.options.gfm && (t.block = D.gfm, this.options.breaks ? t.inline = A.breaks : t.inline = A.gfm), this.tokenizer.rules = t;
1950
+ }
1951
+ static get rules() {
1952
+ return { block: D, inline: A };
1953
+ }
1954
+ static lex(e, t) {
1955
+ return new l(t).lex(e);
1956
+ }
1957
+ static lexInline(e, t) {
1958
+ return new l(t).inlineTokens(e);
1959
+ }
1960
+ lex(e) {
1961
+ e = e.replace(m.carriageReturn, `
1962
+ `), this.blockTokens(e, this.tokens);
1963
+ for (let t = 0; t < this.inlineQueue.length; t++) {
1964
+ let n = this.inlineQueue[t];
1965
+ this.inlineTokens(n.src, n.tokens);
1966
+ }
1967
+ return this.inlineQueue = [], this.tokens;
1968
+ }
1969
+ blockTokens(e, t = [], n = false) {
1970
+ this.tokenizer.lexer = this, this.options.pedantic && (e = e.replace(m.tabCharGlobal, " ").replace(m.spaceLine, ""));
1971
+ let s = 1 / 0;
1972
+ for (; e; ) {
1973
+ if (e.length < s) s = e.length;
1974
+ else {
1975
+ this.infiniteLoopError(e.charCodeAt(0));
1976
+ break;
1977
+ }
1978
+ let r;
1979
+ if (this.options.extensions?.block?.some((o) => (r = o.call({ lexer: this }, e, t)) ? (e = e.substring(r.raw.length), t.push(r), true) : false)) continue;
1980
+ if (r = this.tokenizer.space(e)) {
1981
+ e = e.substring(r.raw.length);
1982
+ let o = t.at(-1);
1983
+ r.raw.length === 1 && o !== void 0 ? o.raw += `
1984
+ ` : t.push(r);
1985
+ continue;
1986
+ }
1987
+ if (r = this.tokenizer.code(e)) {
1988
+ e = e.substring(r.raw.length);
1989
+ let o = t.at(-1);
1990
+ o?.type === "paragraph" || o?.type === "text" ? (o.raw += (o.raw.endsWith(`
1991
+ `) ? "" : `
1992
+ `) + r.raw, o.text += `
1993
+ ` + r.text, this.inlineQueue.at(-1).src = o.text) : t.push(r);
1994
+ continue;
1995
+ }
1996
+ if (r = this.tokenizer.fences(e)) {
1997
+ e = e.substring(r.raw.length), t.push(r);
1998
+ continue;
1999
+ }
2000
+ if (r = this.tokenizer.heading(e)) {
2001
+ e = e.substring(r.raw.length), t.push(r);
2002
+ continue;
2003
+ }
2004
+ if (r = this.tokenizer.hr(e)) {
2005
+ e = e.substring(r.raw.length), t.push(r);
2006
+ continue;
2007
+ }
2008
+ if (r = this.tokenizer.blockquote(e)) {
2009
+ e = e.substring(r.raw.length), t.push(r);
2010
+ continue;
2011
+ }
2012
+ if (r = this.tokenizer.list(e)) {
2013
+ e = e.substring(r.raw.length), t.push(r);
2014
+ continue;
2015
+ }
2016
+ if (r = this.tokenizer.html(e)) {
2017
+ e = e.substring(r.raw.length), t.push(r);
2018
+ continue;
2019
+ }
2020
+ if (r = this.tokenizer.def(e)) {
2021
+ e = e.substring(r.raw.length);
2022
+ let o = t.at(-1);
2023
+ o?.type === "paragraph" || o?.type === "text" ? (o.raw += (o.raw.endsWith(`
2024
+ `) ? "" : `
2025
+ `) + r.raw, o.text += `
2026
+ ` + r.raw, this.inlineQueue.at(-1).src = o.text) : this.tokens.links[r.tag] || (this.tokens.links[r.tag] = { href: r.href, title: r.title }, t.push(r));
2027
+ continue;
2028
+ }
2029
+ if (r = this.tokenizer.table(e)) {
2030
+ e = e.substring(r.raw.length), t.push(r);
2031
+ continue;
2032
+ }
2033
+ if (r = this.tokenizer.lheading(e)) {
2034
+ e = e.substring(r.raw.length), t.push(r);
2035
+ continue;
2036
+ }
2037
+ let i = e;
2038
+ if (this.options.extensions?.startBlock) {
2039
+ let o = 1 / 0, u = e.slice(1), a;
2040
+ this.options.extensions.startBlock.forEach((c) => {
2041
+ a = c.call({ lexer: this }, u), typeof a == "number" && a >= 0 && (o = Math.min(o, a));
2042
+ }), o < 1 / 0 && o >= 0 && (i = e.substring(0, o + 1));
2043
+ }
2044
+ if (this.state.top && (r = this.tokenizer.paragraph(i))) {
2045
+ let o = t.at(-1);
2046
+ n && o?.type === "paragraph" ? (o.raw += (o.raw.endsWith(`
2047
+ `) ? "" : `
2048
+ `) + r.raw, o.text += `
2049
+ ` + r.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src = o.text) : t.push(r), n = i.length !== e.length, e = e.substring(r.raw.length);
2050
+ continue;
2051
+ }
2052
+ if (r = this.tokenizer.text(e)) {
2053
+ e = e.substring(r.raw.length);
2054
+ let o = t.at(-1);
2055
+ o?.type === "text" ? (o.raw += (o.raw.endsWith(`
2056
+ `) ? "" : `
2057
+ `) + r.raw, o.text += `
2058
+ ` + r.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src = o.text) : t.push(r);
2059
+ continue;
2060
+ }
2061
+ if (e) {
2062
+ this.infiniteLoopError(e.charCodeAt(0));
2063
+ break;
2064
+ }
2065
+ }
2066
+ return this.state.top = true, t;
2067
+ }
2068
+ inline(e, t = []) {
2069
+ return this.inlineQueue.push({ src: e, tokens: t }), t;
2070
+ }
2071
+ inlineTokens(e, t = []) {
2072
+ this.tokenizer.lexer = this;
2073
+ let n = e, s = null;
2074
+ if (this.tokens.links) {
2075
+ let a = Object.keys(this.tokens.links);
2076
+ if (a.length > 0) for (; (s = this.tokenizer.rules.inline.reflinkSearch.exec(n)) !== null; ) a.includes(s[0].slice(s[0].lastIndexOf("[") + 1, -1)) && (n = n.slice(0, s.index) + "[" + "a".repeat(s[0].length - 2) + "]" + n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex));
2077
+ }
2078
+ for (; (s = this.tokenizer.rules.inline.anyPunctuation.exec(n)) !== null; ) n = n.slice(0, s.index) + "++" + n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);
2079
+ let r;
2080
+ for (; (s = this.tokenizer.rules.inline.blockSkip.exec(n)) !== null; ) r = s[2] ? s[2].length : 0, n = n.slice(0, s.index + r) + "[" + "a".repeat(s[0].length - r - 2) + "]" + n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
2081
+ n = this.options.hooks?.emStrongMask?.call({ lexer: this }, n) ?? n;
2082
+ let i = false, o = "", u = 1 / 0;
2083
+ for (; e; ) {
2084
+ if (e.length < u) u = e.length;
2085
+ else {
2086
+ this.infiniteLoopError(e.charCodeAt(0));
2087
+ break;
2088
+ }
2089
+ i || (o = ""), i = false;
2090
+ let a;
2091
+ if (this.options.extensions?.inline?.some((p) => (a = p.call({ lexer: this }, e, t)) ? (e = e.substring(a.raw.length), t.push(a), true) : false)) continue;
2092
+ if (a = this.tokenizer.escape(e)) {
2093
+ e = e.substring(a.raw.length), t.push(a);
2094
+ continue;
2095
+ }
2096
+ if (a = this.tokenizer.tag(e)) {
2097
+ e = e.substring(a.raw.length), t.push(a);
2098
+ continue;
2099
+ }
2100
+ if (a = this.tokenizer.link(e)) {
2101
+ e = e.substring(a.raw.length), t.push(a);
2102
+ continue;
2103
+ }
2104
+ if (a = this.tokenizer.reflink(e, this.tokens.links)) {
2105
+ e = e.substring(a.raw.length);
2106
+ let p = t.at(-1);
2107
+ a.type === "text" && p?.type === "text" ? (p.raw += a.raw, p.text += a.text) : t.push(a);
2108
+ continue;
2109
+ }
2110
+ if (a = this.tokenizer.emStrong(e, n, o)) {
2111
+ e = e.substring(a.raw.length), t.push(a);
2112
+ continue;
2113
+ }
2114
+ if (a = this.tokenizer.codespan(e)) {
2115
+ e = e.substring(a.raw.length), t.push(a);
2116
+ continue;
2117
+ }
2118
+ if (a = this.tokenizer.br(e)) {
2119
+ e = e.substring(a.raw.length), t.push(a);
2120
+ continue;
2121
+ }
2122
+ if (a = this.tokenizer.del(e, n, o)) {
2123
+ e = e.substring(a.raw.length), t.push(a);
2124
+ continue;
2125
+ }
2126
+ if (a = this.tokenizer.autolink(e)) {
2127
+ e = e.substring(a.raw.length), t.push(a);
2128
+ continue;
2129
+ }
2130
+ if (!this.state.inLink && (a = this.tokenizer.url(e))) {
2131
+ e = e.substring(a.raw.length), t.push(a);
2132
+ continue;
2133
+ }
2134
+ let c = e;
2135
+ if (this.options.extensions?.startInline) {
2136
+ let p = 1 / 0, k = e.slice(1), h;
2137
+ this.options.extensions.startInline.forEach((R) => {
2138
+ h = R.call({ lexer: this }, k), typeof h == "number" && h >= 0 && (p = Math.min(p, h));
2139
+ }), p < 1 / 0 && p >= 0 && (c = e.substring(0, p + 1));
2140
+ }
2141
+ if (a = this.tokenizer.inlineText(c)) {
2142
+ e = e.substring(a.raw.length), a.raw.slice(-1) !== "_" && (o = a.raw.slice(-1)), i = true;
2143
+ let p = t.at(-1);
2144
+ p?.type === "text" ? (p.raw += a.raw, p.text += a.text) : t.push(a);
2145
+ continue;
2146
+ }
2147
+ if (e) {
2148
+ this.infiniteLoopError(e.charCodeAt(0));
2149
+ break;
2150
+ }
2151
+ }
2152
+ return t;
2153
+ }
2154
+ infiniteLoopError(e) {
2155
+ let t = "Infinite loop on byte: " + e;
2156
+ if (this.options.silent) console.error(t);
2157
+ else throw new Error(t);
2158
+ }
2159
+ };
2160
+ var y = class {
2161
+ options;
2162
+ parser;
2163
+ constructor(e) {
2164
+ this.options = e || T;
2165
+ }
2166
+ space(e) {
2167
+ return "";
2168
+ }
2169
+ code({ text: e, lang: t, escaped: n }) {
2170
+ let s = (t || "").match(m.notSpaceStart)?.[0], r = e.replace(m.endingNewline, "") + `
2171
+ `;
2172
+ return s ? '<pre><code class="language-' + O(s) + '">' + (n ? r : O(r, true)) + `</code></pre>
2173
+ ` : "<pre><code>" + (n ? r : O(r, true)) + `</code></pre>
2174
+ `;
2175
+ }
2176
+ blockquote({ tokens: e }) {
2177
+ return `<blockquote>
2178
+ ${this.parser.parse(e)}</blockquote>
2179
+ `;
2180
+ }
2181
+ html({ text: e }) {
2182
+ return e;
2183
+ }
2184
+ def(e) {
2185
+ return "";
2186
+ }
2187
+ heading({ tokens: e, depth: t }) {
2188
+ return `<h${t}>${this.parser.parseInline(e)}</h${t}>
2189
+ `;
2190
+ }
2191
+ hr(e) {
2192
+ return `<hr>
2193
+ `;
2194
+ }
2195
+ list(e) {
2196
+ let t = e.ordered, n = e.start, s = "";
2197
+ for (let o = 0; o < e.items.length; o++) {
2198
+ let u = e.items[o];
2199
+ s += this.listitem(u);
2200
+ }
2201
+ let r = t ? "ol" : "ul", i = t && n !== 1 ? ' start="' + n + '"' : "";
2202
+ return "<" + r + i + `>
2203
+ ` + s + "</" + r + `>
2204
+ `;
2205
+ }
2206
+ listitem(e) {
2207
+ return `<li>${this.parser.parse(e.tokens)}</li>
2208
+ `;
2209
+ }
2210
+ checkbox({ checked: e }) {
2211
+ return "<input " + (e ? 'checked="" ' : "") + 'disabled="" type="checkbox"> ';
2212
+ }
2213
+ paragraph({ tokens: e }) {
2214
+ return `<p>${this.parser.parseInline(e)}</p>
2215
+ `;
2216
+ }
2217
+ table(e) {
2218
+ let t = "", n = "";
2219
+ for (let r = 0; r < e.header.length; r++) n += this.tablecell(e.header[r]);
2220
+ t += this.tablerow({ text: n });
2221
+ let s = "";
2222
+ for (let r = 0; r < e.rows.length; r++) {
2223
+ let i = e.rows[r];
2224
+ n = "";
2225
+ for (let o = 0; o < i.length; o++) n += this.tablecell(i[o]);
2226
+ s += this.tablerow({ text: n });
2227
+ }
2228
+ return s && (s = `<tbody>${s}</tbody>`), `<table>
2229
+ <thead>
2230
+ ` + t + `</thead>
2231
+ ` + s + `</table>
2232
+ `;
2233
+ }
2234
+ tablerow({ text: e }) {
2235
+ return `<tr>
2236
+ ${e}</tr>
2237
+ `;
2238
+ }
2239
+ tablecell(e) {
2240
+ let t = this.parser.parseInline(e.tokens), n = e.header ? "th" : "td";
2241
+ return (e.align ? `<${n} align="${e.align}">` : `<${n}>`) + t + `</${n}>
2242
+ `;
2243
+ }
2244
+ strong({ tokens: e }) {
2245
+ return `<strong>${this.parser.parseInline(e)}</strong>`;
2246
+ }
2247
+ em({ tokens: e }) {
2248
+ return `<em>${this.parser.parseInline(e)}</em>`;
2249
+ }
2250
+ codespan({ text: e }) {
2251
+ return `<code>${O(e, true)}</code>`;
2252
+ }
2253
+ br(e) {
2254
+ return "<br>";
2255
+ }
2256
+ del({ tokens: e }) {
2257
+ return `<del>${this.parser.parseInline(e)}</del>`;
2258
+ }
2259
+ link({ href: e, title: t, tokens: n }) {
2260
+ let s = this.parser.parseInline(n), r = V(e);
2261
+ if (r === null) return s;
2262
+ e = r;
2263
+ let i = '<a href="' + e + '"';
2264
+ return t && (i += ' title="' + O(t) + '"'), i += ">" + s + "</a>", i;
2265
+ }
2266
+ image({ href: e, title: t, text: n, tokens: s }) {
2267
+ s && (n = this.parser.parseInline(s, this.parser.textRenderer));
2268
+ let r = V(e);
2269
+ if (r === null) return O(n);
2270
+ e = r;
2271
+ let i = `<img src="${e}" alt="${O(n)}"`;
2272
+ return t && (i += ` title="${O(t)}"`), i += ">", i;
2273
+ }
2274
+ text(e) {
2275
+ return "tokens" in e && e.tokens ? this.parser.parseInline(e.tokens) : "escaped" in e && e.escaped ? e.text : O(e.text);
2276
+ }
2277
+ };
2278
+ var L = class {
2279
+ strong({ text: e }) {
2280
+ return e;
2281
+ }
2282
+ em({ text: e }) {
2283
+ return e;
2284
+ }
2285
+ codespan({ text: e }) {
2286
+ return e;
2287
+ }
2288
+ del({ text: e }) {
2289
+ return e;
2290
+ }
2291
+ html({ text: e }) {
2292
+ return e;
2293
+ }
2294
+ text({ text: e }) {
2295
+ return e;
2296
+ }
2297
+ link({ text: e }) {
2298
+ return "" + e;
2299
+ }
2300
+ image({ text: e }) {
2301
+ return "" + e;
2302
+ }
2303
+ br() {
2304
+ return "";
2305
+ }
2306
+ checkbox({ raw: e }) {
2307
+ return e;
2308
+ }
2309
+ };
2310
+ var b = class l2 {
2311
+ options;
2312
+ renderer;
2313
+ textRenderer;
2314
+ constructor(e) {
2315
+ this.options = e || T, this.options.renderer = this.options.renderer || new y(), this.renderer = this.options.renderer, this.renderer.options = this.options, this.renderer.parser = this, this.textRenderer = new L();
2316
+ }
2317
+ static parse(e, t) {
2318
+ return new l2(t).parse(e);
2319
+ }
2320
+ static parseInline(e, t) {
2321
+ return new l2(t).parseInline(e);
2322
+ }
2323
+ parse(e) {
2324
+ this.renderer.parser = this;
2325
+ let t = "";
2326
+ for (let n = 0; n < e.length; n++) {
2327
+ let s = e[n];
2328
+ if (this.options.extensions?.renderers?.[s.type]) {
2329
+ let i = s, o = this.options.extensions.renderers[i.type].call({ parser: this }, i);
2330
+ if (o !== false || !["space", "hr", "heading", "code", "table", "blockquote", "list", "html", "def", "paragraph", "text"].includes(i.type)) {
2331
+ t += o || "";
2332
+ continue;
2333
+ }
2334
+ }
2335
+ let r = s;
2336
+ switch (r.type) {
2337
+ case "space": {
2338
+ t += this.renderer.space(r);
2339
+ break;
2340
+ }
2341
+ case "hr": {
2342
+ t += this.renderer.hr(r);
2343
+ break;
2344
+ }
2345
+ case "heading": {
2346
+ t += this.renderer.heading(r);
2347
+ break;
2348
+ }
2349
+ case "code": {
2350
+ t += this.renderer.code(r);
2351
+ break;
2352
+ }
2353
+ case "table": {
2354
+ t += this.renderer.table(r);
2355
+ break;
2356
+ }
2357
+ case "blockquote": {
2358
+ t += this.renderer.blockquote(r);
2359
+ break;
2360
+ }
2361
+ case "list": {
2362
+ t += this.renderer.list(r);
2363
+ break;
2364
+ }
2365
+ case "checkbox": {
2366
+ t += this.renderer.checkbox(r);
2367
+ break;
2368
+ }
2369
+ case "html": {
2370
+ t += this.renderer.html(r);
2371
+ break;
2372
+ }
2373
+ case "def": {
2374
+ t += this.renderer.def(r);
2375
+ break;
2376
+ }
2377
+ case "paragraph": {
2378
+ t += this.renderer.paragraph(r);
2379
+ break;
2380
+ }
2381
+ case "text": {
2382
+ t += this.renderer.text(r);
2383
+ break;
2384
+ }
2385
+ default: {
2386
+ let i = 'Token with "' + r.type + '" type was not found.';
2387
+ if (this.options.silent) return console.error(i), "";
2388
+ throw new Error(i);
2389
+ }
2390
+ }
2391
+ }
2392
+ return t;
2393
+ }
2394
+ parseInline(e, t = this.renderer) {
2395
+ this.renderer.parser = this;
2396
+ let n = "";
2397
+ for (let s = 0; s < e.length; s++) {
2398
+ let r = e[s];
2399
+ if (this.options.extensions?.renderers?.[r.type]) {
2400
+ let o = this.options.extensions.renderers[r.type].call({ parser: this }, r);
2401
+ if (o !== false || !["escape", "html", "link", "image", "strong", "em", "codespan", "br", "del", "text"].includes(r.type)) {
2402
+ n += o || "";
2403
+ continue;
2404
+ }
2405
+ }
2406
+ let i = r;
2407
+ switch (i.type) {
2408
+ case "escape": {
2409
+ n += t.text(i);
2410
+ break;
2411
+ }
2412
+ case "html": {
2413
+ n += t.html(i);
2414
+ break;
2415
+ }
2416
+ case "link": {
2417
+ n += t.link(i);
2418
+ break;
2419
+ }
2420
+ case "image": {
2421
+ n += t.image(i);
2422
+ break;
2423
+ }
2424
+ case "checkbox": {
2425
+ n += t.checkbox(i);
2426
+ break;
2427
+ }
2428
+ case "strong": {
2429
+ n += t.strong(i);
2430
+ break;
2431
+ }
2432
+ case "em": {
2433
+ n += t.em(i);
2434
+ break;
2435
+ }
2436
+ case "codespan": {
2437
+ n += t.codespan(i);
2438
+ break;
2439
+ }
2440
+ case "br": {
2441
+ n += t.br(i);
2442
+ break;
2443
+ }
2444
+ case "del": {
2445
+ n += t.del(i);
2446
+ break;
2447
+ }
2448
+ case "text": {
2449
+ n += t.text(i);
2450
+ break;
2451
+ }
2452
+ default: {
2453
+ let o = 'Token with "' + i.type + '" type was not found.';
2454
+ if (this.options.silent) return console.error(o), "";
2455
+ throw new Error(o);
2456
+ }
2457
+ }
2458
+ }
2459
+ return n;
2460
+ }
2461
+ };
2462
+ var P = class {
2463
+ options;
2464
+ block;
2465
+ constructor(e) {
2466
+ this.options = e || T;
2467
+ }
2468
+ static passThroughHooks = /* @__PURE__ */ new Set(["preprocess", "postprocess", "processAllTokens", "emStrongMask"]);
2469
+ static passThroughHooksRespectAsync = /* @__PURE__ */ new Set(["preprocess", "postprocess", "processAllTokens"]);
2470
+ preprocess(e) {
2471
+ return e;
2472
+ }
2473
+ postprocess(e) {
2474
+ return e;
2475
+ }
2476
+ processAllTokens(e) {
2477
+ return e;
2478
+ }
2479
+ emStrongMask(e) {
2480
+ return e;
2481
+ }
2482
+ provideLexer(e = this.block) {
2483
+ return e ? x.lex : x.lexInline;
2484
+ }
2485
+ provideParser(e = this.block) {
2486
+ return e ? b.parse : b.parseInline;
2487
+ }
2488
+ };
2489
+ var q = class {
2490
+ defaults = M();
2491
+ options = this.setOptions;
2492
+ parse = this.parseMarkdown(true);
2493
+ parseInline = this.parseMarkdown(false);
2494
+ Parser = b;
2495
+ Renderer = y;
2496
+ TextRenderer = L;
2497
+ Lexer = x;
2498
+ Tokenizer = w;
2499
+ Hooks = P;
2500
+ constructor(...e) {
2501
+ this.use(...e);
2502
+ }
2503
+ walkTokens(e, t) {
2504
+ let n = [];
2505
+ for (let s of e) switch (n = n.concat(t.call(this, s)), s.type) {
2506
+ case "table": {
2507
+ let r = s;
2508
+ for (let i of r.header) n = n.concat(this.walkTokens(i.tokens, t));
2509
+ for (let i of r.rows) for (let o of i) n = n.concat(this.walkTokens(o.tokens, t));
2510
+ break;
2511
+ }
2512
+ case "list": {
2513
+ let r = s;
2514
+ n = n.concat(this.walkTokens(r.items, t));
2515
+ break;
2516
+ }
2517
+ default: {
2518
+ let r = s;
2519
+ this.defaults.extensions?.childTokens?.[r.type] ? this.defaults.extensions.childTokens[r.type].forEach((i) => {
2520
+ let o = r[i].flat(1 / 0);
2521
+ n = n.concat(this.walkTokens(o, t));
2522
+ }) : r.tokens && (n = n.concat(this.walkTokens(r.tokens, t)));
2523
+ }
2524
+ }
2525
+ return n;
2526
+ }
2527
+ use(...e) {
2528
+ let t = this.defaults.extensions || { renderers: {}, childTokens: {} };
2529
+ return e.forEach((n) => {
2530
+ let s = { ...n };
2531
+ if (s.async = this.defaults.async || s.async || false, n.extensions && (n.extensions.forEach((r) => {
2532
+ if (!r.name) throw new Error("extension name required");
2533
+ if ("renderer" in r) {
2534
+ let i = t.renderers[r.name];
2535
+ i ? t.renderers[r.name] = function(...o) {
2536
+ let u = r.renderer.apply(this, o);
2537
+ return u === false && (u = i.apply(this, o)), u;
2538
+ } : t.renderers[r.name] = r.renderer;
2539
+ }
2540
+ if ("tokenizer" in r) {
2541
+ if (!r.level || r.level !== "block" && r.level !== "inline") throw new Error("extension level must be 'block' or 'inline'");
2542
+ let i = t[r.level];
2543
+ i ? i.unshift(r.tokenizer) : t[r.level] = [r.tokenizer], r.start && (r.level === "block" ? t.startBlock ? t.startBlock.push(r.start) : t.startBlock = [r.start] : r.level === "inline" && (t.startInline ? t.startInline.push(r.start) : t.startInline = [r.start]));
2544
+ }
2545
+ "childTokens" in r && r.childTokens && (t.childTokens[r.name] = r.childTokens);
2546
+ }), s.extensions = t), n.renderer) {
2547
+ let r = this.defaults.renderer || new y(this.defaults);
2548
+ for (let i in n.renderer) {
2549
+ if (!(i in r)) throw new Error(`renderer '${i}' does not exist`);
2550
+ if (["options", "parser"].includes(i)) continue;
2551
+ let o = i, u = n.renderer[o], a = r[o];
2552
+ r[o] = (...c) => {
2553
+ let p = u.apply(r, c);
2554
+ return p === false && (p = a.apply(r, c)), p || "";
2555
+ };
2556
+ }
2557
+ s.renderer = r;
2558
+ }
2559
+ if (n.tokenizer) {
2560
+ let r = this.defaults.tokenizer || new w(this.defaults);
2561
+ for (let i in n.tokenizer) {
2562
+ if (!(i in r)) throw new Error(`tokenizer '${i}' does not exist`);
2563
+ if (["options", "rules", "lexer"].includes(i)) continue;
2564
+ let o = i, u = n.tokenizer[o], a = r[o];
2565
+ r[o] = (...c) => {
2566
+ let p = u.apply(r, c);
2567
+ return p === false && (p = a.apply(r, c)), p;
2568
+ };
2569
+ }
2570
+ s.tokenizer = r;
2571
+ }
2572
+ if (n.hooks) {
2573
+ let r = this.defaults.hooks || new P();
2574
+ for (let i in n.hooks) {
2575
+ if (!(i in r)) throw new Error(`hook '${i}' does not exist`);
2576
+ if (["options", "block"].includes(i)) continue;
2577
+ let o = i, u = n.hooks[o], a = r[o];
2578
+ P.passThroughHooks.has(i) ? r[o] = (c) => {
2579
+ if (this.defaults.async && P.passThroughHooksRespectAsync.has(i)) return (async () => {
2580
+ let k = await u.call(r, c);
2581
+ return a.call(r, k);
2582
+ })();
2583
+ let p = u.call(r, c);
2584
+ return a.call(r, p);
2585
+ } : r[o] = (...c) => {
2586
+ if (this.defaults.async) return (async () => {
2587
+ let k = await u.apply(r, c);
2588
+ return k === false && (k = await a.apply(r, c)), k;
2589
+ })();
2590
+ let p = u.apply(r, c);
2591
+ return p === false && (p = a.apply(r, c)), p;
2592
+ };
2593
+ }
2594
+ s.hooks = r;
2595
+ }
2596
+ if (n.walkTokens) {
2597
+ let r = this.defaults.walkTokens, i = n.walkTokens;
2598
+ s.walkTokens = function(o) {
2599
+ let u = [];
2600
+ return u.push(i.call(this, o)), r && (u = u.concat(r.call(this, o))), u;
2601
+ };
2602
+ }
2603
+ this.defaults = { ...this.defaults, ...s };
2604
+ }), this;
2605
+ }
2606
+ setOptions(e) {
2607
+ return this.defaults = { ...this.defaults, ...e }, this;
2608
+ }
2609
+ lexer(e, t) {
2610
+ return x.lex(e, t ?? this.defaults);
2611
+ }
2612
+ parser(e, t) {
2613
+ return b.parse(e, t ?? this.defaults);
2614
+ }
2615
+ parseMarkdown(e) {
2616
+ return (n, s) => {
2617
+ let r = { ...s }, i = { ...this.defaults, ...r }, o = this.onError(!!i.silent, !!i.async);
2618
+ if (this.defaults.async === true && r.async === false) return o(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));
2619
+ if (typeof n > "u" || n === null) return o(new Error("marked(): input parameter is undefined or null"));
2620
+ if (typeof n != "string") return o(new Error("marked(): input parameter is of type " + Object.prototype.toString.call(n) + ", string expected"));
2621
+ if (i.hooks && (i.hooks.options = i, i.hooks.block = e), i.async) return (async () => {
2622
+ let u = i.hooks ? await i.hooks.preprocess(n) : n, c = await (i.hooks ? await i.hooks.provideLexer(e) : e ? x.lex : x.lexInline)(u, i), p = i.hooks ? await i.hooks.processAllTokens(c) : c;
2623
+ i.walkTokens && await Promise.all(this.walkTokens(p, i.walkTokens));
2624
+ let h = await (i.hooks ? await i.hooks.provideParser(e) : e ? b.parse : b.parseInline)(p, i);
2625
+ return i.hooks ? await i.hooks.postprocess(h) : h;
2626
+ })().catch(o);
2627
+ try {
2628
+ i.hooks && (n = i.hooks.preprocess(n));
2629
+ let a = (i.hooks ? i.hooks.provideLexer(e) : e ? x.lex : x.lexInline)(n, i);
2630
+ i.hooks && (a = i.hooks.processAllTokens(a)), i.walkTokens && this.walkTokens(a, i.walkTokens);
2631
+ let p = (i.hooks ? i.hooks.provideParser(e) : e ? b.parse : b.parseInline)(a, i);
2632
+ return i.hooks && (p = i.hooks.postprocess(p)), p;
2633
+ } catch (u) {
2634
+ return o(u);
2635
+ }
2636
+ };
2637
+ }
2638
+ onError(e, t) {
2639
+ return (n) => {
2640
+ if (n.message += `
2641
+ Please report this to https://github.com/markedjs/marked.`, e) {
2642
+ let s = "<p>An error occurred:</p><pre>" + O(n.message + "", true) + "</pre>";
2643
+ return t ? Promise.resolve(s) : s;
2644
+ }
2645
+ if (t) return Promise.reject(n);
2646
+ throw n;
2647
+ };
2648
+ }
2649
+ };
2650
+ var z = new q();
2651
+ function g(l3, e) {
2652
+ return z.parse(l3, e);
2653
+ }
2654
+ g.options = g.setOptions = function(l3) {
2655
+ return z.setOptions(l3), g.defaults = z.defaults, N(g.defaults), g;
2656
+ };
2657
+ g.getDefaults = M;
2658
+ g.defaults = T;
2659
+ g.use = function(...l3) {
2660
+ return z.use(...l3), g.defaults = z.defaults, N(g.defaults), g;
2661
+ };
2662
+ g.walkTokens = function(l3, e) {
2663
+ return z.walkTokens(l3, e);
2664
+ };
2665
+ g.parseInline = z.parseInline;
2666
+ g.Parser = b;
2667
+ g.parser = b.parse;
2668
+ g.Renderer = y;
2669
+ g.TextRenderer = L;
2670
+ g.Lexer = x;
2671
+ g.lexer = x.lex;
2672
+ g.Tokenizer = w;
2673
+ g.Hooks = P;
2674
+ g.parse = g;
2675
+ var Ft = g.options;
2676
+ var Ut = g.setOptions;
2677
+ var Kt = g.use;
2678
+ var Wt = g.walkTokens;
2679
+ var Xt = g.parseInline;
2680
+ var Vt = b.parse;
2681
+ var Yt = x.lex;
2682
+
2683
+ // src/ui/render_markdown.ts
2684
+ g.setOptions({ gfm: true, breaks: true });
2685
+ var ALLOWED_TAGS = [
2686
+ "a",
2687
+ "p",
2688
+ "br",
2689
+ "strong",
2690
+ "em",
2691
+ "b",
2692
+ "i",
2693
+ "u",
2694
+ "s",
2695
+ "del",
2696
+ "code",
2697
+ "pre",
2698
+ "ul",
2699
+ "ol",
2700
+ "li",
2701
+ "blockquote",
2702
+ "h1",
2703
+ "h2",
2704
+ "h3",
2705
+ "h4",
2706
+ "h5",
2707
+ "h6",
2708
+ "hr",
2709
+ "span",
2710
+ "table",
2711
+ "thead",
2712
+ "tbody",
2713
+ "tr",
2714
+ "th",
2715
+ "td",
2716
+ "img"
2717
+ ];
2718
+ var ALLOWED_ATTR = ["href", "title", "class", "src", "alt", "width", "height"];
2719
+ function renderMarkdown(text2) {
2720
+ const rendered = g.parse(text2, { async: false });
2721
+ const clean = purify.sanitize(rendered, { ALLOWED_TAGS, ALLOWED_ATTR });
2722
+ const template = document.createElement("template");
2723
+ template.innerHTML = clean;
2724
+ for (const anchor of template.content.querySelectorAll("a[href]")) {
2725
+ anchor.setAttribute("target", "_blank");
2726
+ anchor.setAttribute("rel", "noopener noreferrer");
2727
+ }
2728
+ return template.innerHTML.trim();
2729
+ }
2730
+
2731
+ // src/ui/reveal_words.ts
2732
+ function collectTextNodes(root, out) {
2733
+ for (const child of Array.from(root.childNodes)) {
2734
+ if (child.nodeType === Node.TEXT_NODE) {
2735
+ out.push({ node: child, parent: root });
2736
+ } else {
2737
+ collectTextNodes(child, out);
2738
+ }
2739
+ }
2740
+ }
2741
+ function wrapWords(root) {
2742
+ const texts = [];
2743
+ collectTextNodes(root, texts);
2744
+ let index = 0;
2745
+ for (const { node, parent } of texts) {
2746
+ const fragment = document.createDocumentFragment();
2747
+ for (const part of node.data.split(/(\s+)/)) {
2748
+ if (part === "") {
2749
+ continue;
2750
+ }
2751
+ if (/\s/.test(part)) {
2752
+ fragment.appendChild(document.createTextNode(part));
2753
+ continue;
2754
+ }
2755
+ const span = document.createElement("span");
2756
+ span.className = "word";
2757
+ span.style.setProperty("--ag-ui-word-index", String(index));
2758
+ span.textContent = part;
2759
+ fragment.appendChild(span);
2760
+ index += 1;
2761
+ }
2762
+ parent.replaceChild(fragment, node);
2763
+ }
2764
+ }
2765
+
2766
+ // src/ui/skills_menu.ts
2767
+ var SkillsMenu = class {
2768
+ /** Chips row — append above the input. Hidden unless chips are enabled and present. */
2769
+ chips;
2770
+ /** The `/`-command dropdown — append in the input area. Hidden until opened. */
2771
+ palette;
2772
+ #onPick;
2773
+ #skills = [];
2774
+ #chipsEnabled = false;
2775
+ #slashEnabled = false;
2776
+ #filtered = [];
2777
+ #activeIndex = 0;
2778
+ constructor(onPick) {
2779
+ this.#onPick = onPick;
2780
+ this.chips = document.createElement("div");
2781
+ this.chips.className = "skill-chips";
2782
+ this.chips.hidden = true;
2783
+ this.palette = document.createElement("div");
2784
+ this.palette.className = "skill-palette";
2785
+ this.palette.setAttribute("role", "listbox");
2786
+ this.palette.hidden = true;
2787
+ }
2788
+ /** Replace the catalog (both surfaces re-derive from it). */
2789
+ setSkills(skills) {
2790
+ this.#skills = skills;
2791
+ this.#renderChips();
2792
+ }
2793
+ enableChips(enabled) {
2794
+ this.#chipsEnabled = enabled;
2795
+ this.#renderChips();
2796
+ }
2797
+ enableSlash(enabled) {
2798
+ this.#slashEnabled = enabled;
2799
+ }
2800
+ /** Whether the palette is currently open. */
2801
+ isOpen() {
2802
+ return !this.palette.hidden;
2803
+ }
2804
+ /**
2805
+ * React to an input value change: open + filter the palette when slash mode
2806
+ * is on and the value starts with `/`, otherwise close it.
2807
+ */
2808
+ onInput(value) {
2809
+ if (this.#slashEnabled && value.startsWith("/")) {
2810
+ this.#open(value.slice(1));
2811
+ } else {
2812
+ this.close();
2813
+ }
2814
+ }
2815
+ /**
2816
+ * Handle a keydown while the palette is open. Returns ``true`` when consumed
2817
+ * (the host should `preventDefault` and skip its own handling).
2818
+ */
2819
+ onKeydown(event) {
2820
+ if (!this.isOpen()) {
2821
+ return false;
2822
+ }
2823
+ if (event.key === "ArrowDown") {
2824
+ this.#move(1);
2825
+ return true;
2826
+ }
2827
+ if (event.key === "ArrowUp") {
2828
+ this.#move(-1);
2829
+ return true;
2830
+ }
2831
+ if (event.key === "Escape") {
2832
+ this.close();
2833
+ return true;
2834
+ }
2835
+ if (event.key === "Enter") {
2836
+ this.#filtered.slice(this.#activeIndex, this.#activeIndex + 1).forEach((skill) => {
2837
+ this.#pick(skill);
2838
+ });
2839
+ return true;
2840
+ }
2841
+ return false;
2842
+ }
2843
+ /** Close the palette. */
2844
+ close() {
2845
+ this.palette.hidden = true;
2846
+ this.palette.replaceChildren();
2847
+ }
2848
+ #open(query) {
2849
+ const needle = query.trim().toLowerCase();
2850
+ const matches = this.#skills.filter(
2851
+ (skill) => skill.name.toLowerCase().includes(needle) || skill.title.toLowerCase().includes(needle)
2852
+ );
2853
+ if (matches.length === 0) {
2854
+ this.close();
2855
+ return;
2856
+ }
2857
+ this.#filtered = matches;
2858
+ this.#activeIndex = 0;
2859
+ this.#renderPalette();
2860
+ this.palette.hidden = false;
2861
+ }
2862
+ #move(delta) {
2863
+ const count = this.#filtered.length;
2864
+ this.#activeIndex = (this.#activeIndex + delta + count) % count;
2865
+ this.#renderPalette();
2866
+ }
2867
+ #pick(skill) {
2868
+ this.close();
2869
+ this.#onPick(skill);
2870
+ }
2871
+ #renderChips() {
2872
+ this.chips.replaceChildren();
2873
+ const chipSkills = this.#chipsEnabled ? this.#skills.filter((skill) => skill.chip === true) : [];
2874
+ this.chips.hidden = chipSkills.length === 0;
2875
+ for (const skill of chipSkills) {
2876
+ const button = document.createElement("button");
2877
+ button.type = "button";
2878
+ button.className = "skill-chip";
2879
+ button.textContent = skill.title;
2880
+ button.addEventListener("click", () => this.#pick(skill));
2881
+ this.chips.appendChild(button);
2882
+ }
2883
+ }
2884
+ #renderPalette() {
2885
+ this.palette.replaceChildren();
2886
+ this.#filtered.forEach((skill, index) => {
2887
+ const item = document.createElement("button");
2888
+ item.type = "button";
2889
+ item.className = "skill-item";
2890
+ item.setAttribute("role", "option");
2891
+ item.setAttribute("aria-selected", index === this.#activeIndex ? "true" : "false");
2892
+ const title = document.createElement("span");
2893
+ title.className = "skill-item-title";
2894
+ title.textContent = skill.title;
2895
+ item.appendChild(title);
2896
+ if (skill.description !== void 0) {
2897
+ const desc = document.createElement("span");
2898
+ desc.className = "skill-item-desc";
2899
+ desc.textContent = skill.description;
2900
+ item.appendChild(desc);
2901
+ }
2902
+ item.addEventListener("click", () => this.#pick(skill));
2903
+ this.palette.appendChild(item);
2904
+ });
2905
+ }
2906
+ };
2907
+
2908
+ // src/ui/styles.ts
2909
+ var STYLES = `
2910
+ :host {
2911
+ /* Colors */
2912
+ --ag-ui-bg: #ffffff;
2913
+ --ag-ui-fg: #1a1a2e;
2914
+ --ag-ui-accent: #4f46e5;
2915
+ --ag-ui-user-bg: #4f46e5;
2916
+ --ag-ui-user-fg: #ffffff;
2917
+ --ag-ui-assistant-bg: #f1f1f6;
2918
+ --ag-ui-input-bg: var(--ag-ui-bg);
2919
+ --ag-ui-tool-bg: var(--ag-ui-assistant-bg);
2920
+ --ag-ui-tool-fg: var(--ag-ui-accent);
2921
+ --ag-ui-header-bg: var(--ag-ui-accent);
2922
+ --ag-ui-header-fg: #ffffff;
2923
+ --ag-ui-border: #e2e2ec;
2924
+ --ag-ui-radius: 12px;
2925
+
2926
+ /* Status accents for tool-call cards. */
2927
+ --ag-ui-success: #15803d;
2928
+ --ag-ui-danger: #b91c1c;
400
2929
  --ag-ui-muted: #6b7280;
401
2930
 
402
2931
  /* Surface \u2014 set --ag-ui-shadow: none for a flush, embedded panel. */
403
2932
  --ag-ui-shadow: 0 12px 32px rgba(20, 20, 50, 0.18);
404
2933
  --ag-ui-font: inherit;
405
2934
  --ag-ui-font-size: 14px;
2935
+ --ag-ui-code-font: ui-monospace, "SF Mono", Menlo, monospace;
2936
+
2937
+ /* Spacing \u2014 the density preset overrides these. */
2938
+ --ag-ui-space: 10px;
2939
+ --ag-ui-pad: 16px;
2940
+ --ag-ui-msg-pad: 8px 12px;
2941
+ --ag-ui-msg-radius: 14px;
406
2942
 
407
2943
  /* Layout \u2014 override from outside to dock the widget anywhere.
408
2944
  Set --ag-ui-position: static (and place this element in your own
@@ -428,6 +2964,91 @@ var STYLES = `
428
2964
  color: var(--ag-ui-fg);
429
2965
  }
430
2966
 
2967
+ /* \u2500\u2500 Themes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
2968
+ Themes only re-set the colour variables; layout/spacing are unaffected.
2969
+ theme="auto" follows the OS via prefers-color-scheme. */
2970
+ :host([theme="dark"]) {
2971
+ --ag-ui-bg: #15151f;
2972
+ --ag-ui-fg: #e8e8f2;
2973
+ --ag-ui-assistant-bg: #25253a;
2974
+ --ag-ui-header-bg: #1f1f30;
2975
+ --ag-ui-header-fg: #e8e8f2;
2976
+ --ag-ui-border: #33334a;
2977
+ --ag-ui-muted: #9aa0b4;
2978
+ --ag-ui-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
2979
+ }
2980
+
2981
+ @media (prefers-color-scheme: dark) {
2982
+ :host([theme="auto"]) {
2983
+ --ag-ui-bg: #15151f;
2984
+ --ag-ui-fg: #e8e8f2;
2985
+ --ag-ui-assistant-bg: #25253a;
2986
+ --ag-ui-header-bg: #1f1f30;
2987
+ --ag-ui-header-fg: #e8e8f2;
2988
+ --ag-ui-border: #33334a;
2989
+ --ag-ui-muted: #9aa0b4;
2990
+ --ag-ui-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
2991
+ }
2992
+ }
2993
+
2994
+ /* A terminal-flavoured "code" theme: dark, monospace, green accent. */
2995
+ :host([theme="code"]) {
2996
+ --ag-ui-bg: #0d1117;
2997
+ --ag-ui-fg: #c9d1d9;
2998
+ --ag-ui-accent: #3fb950;
2999
+ --ag-ui-user-bg: #238636;
3000
+ --ag-ui-assistant-bg: #161b22;
3001
+ --ag-ui-header-bg: #010409;
3002
+ --ag-ui-header-fg: #c9d1d9;
3003
+ --ag-ui-border: #30363d;
3004
+ --ag-ui-muted: #8b949e;
3005
+ --ag-ui-font: var(--ag-ui-code-font);
3006
+ --ag-ui-shadow: 0 12px 32px rgba(0, 0, 0, 0.6);
3007
+ }
3008
+
3009
+ /* \u2500\u2500 Density \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
3010
+ :host([density="compact"]) {
3011
+ --ag-ui-font-size: 13px;
3012
+ --ag-ui-space: 6px;
3013
+ --ag-ui-pad: 10px;
3014
+ --ag-ui-msg-pad: 5px 9px;
3015
+ --ag-ui-msg-radius: 10px;
3016
+ }
3017
+
3018
+ /* \u2500\u2500 Placement presets \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
3019
+ :host([placement="bottom-left"]) {
3020
+ --ag-ui-inset: auto auto 24px 24px;
3021
+ }
3022
+
3023
+ :host([placement="side"]) {
3024
+ --ag-ui-inset: 0 0 0 auto;
3025
+ --ag-ui-width: 420px;
3026
+ --ag-ui-height: 100vh;
3027
+ --ag-ui-max-height: 100vh;
3028
+ --ag-ui-radius: 0;
3029
+ }
3030
+
3031
+ :host([placement="full"]) {
3032
+ --ag-ui-inset: 0;
3033
+ --ag-ui-width: 100vw;
3034
+ --ag-ui-height: 100vh;
3035
+ --ag-ui-max-width: 100vw;
3036
+ --ag-ui-max-height: 100vh;
3037
+ --ag-ui-radius: 0;
3038
+ }
3039
+
3040
+ /* Embedded: drop the floating chrome and the high z-index stacking context so
3041
+ the widget lives in the host's own layout (fixes overlay/z-index clashes). */
3042
+ :host([placement="embedded"]) {
3043
+ --ag-ui-position: static;
3044
+ --ag-ui-width: 100%;
3045
+ --ag-ui-height: 100%;
3046
+ --ag-ui-max-width: 100%;
3047
+ --ag-ui-max-height: 100%;
3048
+ --ag-ui-shadow: none;
3049
+ --ag-ui-z-index: auto;
3050
+ }
3051
+
431
3052
  .chat {
432
3053
  position: relative;
433
3054
  display: flex;
@@ -442,31 +3063,114 @@ var STYLES = `
442
3063
  }
443
3064
 
444
3065
  .header {
445
- padding: 12px 16px;
446
- font-weight: 600;
3066
+ display: flex;
3067
+ align-items: center;
3068
+ justify-content: space-between;
3069
+ gap: 8px;
3070
+ padding: 10px 14px;
447
3071
  border-bottom: 1px solid var(--ag-ui-border);
448
3072
  background: var(--ag-ui-header-bg);
449
3073
  color: var(--ag-ui-header-fg);
450
3074
  }
451
3075
 
3076
+ .header-title {
3077
+ font-weight: 600;
3078
+ overflow: hidden;
3079
+ text-overflow: ellipsis;
3080
+ white-space: nowrap;
3081
+ }
3082
+
3083
+ .header-controls {
3084
+ display: flex;
3085
+ gap: 2px;
3086
+ flex: none;
3087
+ }
3088
+
3089
+ .header-btn {
3090
+ border: none;
3091
+ background: transparent;
3092
+ color: inherit;
3093
+ font: inherit;
3094
+ line-height: 1;
3095
+ padding: 4px 7px;
3096
+ border-radius: 6px;
3097
+ cursor: pointer;
3098
+ opacity: 0.85;
3099
+ }
3100
+
3101
+ .header-btn:hover {
3102
+ opacity: 1;
3103
+ background: rgba(255, 255, 255, 0.18);
3104
+ }
3105
+
3106
+ /* Collapsed: keep just the header bar \u2014 hide the whole body, and let the host
3107
+ shrink to the header. (A host can also fully hide the element itself.) */
3108
+ :host([collapsed]) {
3109
+ height: auto;
3110
+ max-height: none;
3111
+ }
3112
+
3113
+ :host([collapsed]) .messages,
3114
+ :host([collapsed]) .input-row,
3115
+ :host([collapsed]) .skill-chips,
3116
+ :host([collapsed]) .skill-palette,
3117
+ :host([collapsed]) .skill-hint {
3118
+ display: none;
3119
+ }
3120
+
3121
+ /* Edge-docked placements pin top *and* bottom, which would otherwise keep the
3122
+ panel full-height when collapsed; unpin the bottom so it shrinks to the
3123
+ header. (Floating/bottom-left pin only the bottom, so they already shrink.) */
3124
+ :host([collapsed][placement="side"]),
3125
+ :host([collapsed][placement="full"]) {
3126
+ bottom: auto;
3127
+ }
3128
+
452
3129
  .messages {
453
3130
  flex: 1;
454
3131
  overflow-y: auto;
455
- padding: 16px;
3132
+ padding: var(--ag-ui-pad);
456
3133
  display: flex;
457
3134
  flex-direction: column;
458
- gap: 10px;
3135
+ gap: var(--ag-ui-space);
459
3136
  }
460
3137
 
461
3138
  .message {
462
3139
  max-width: 80%;
463
- padding: 8px 12px;
464
- border-radius: 14px;
3140
+ padding: var(--ag-ui-msg-pad);
3141
+ border-radius: var(--ag-ui-msg-radius);
465
3142
  line-height: 1.4;
466
3143
  white-space: pre-wrap;
467
3144
  word-break: break-word;
468
3145
  }
469
3146
 
3147
+ /* \u2500\u2500 Incoming-text animations (data-text-animation) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
3148
+ :host([data-text-animation="fade"]) .message--assistant {
3149
+ animation: ag-ui-msg-fade 0.25s ease both;
3150
+ }
3151
+
3152
+ @keyframes ag-ui-msg-fade {
3153
+ from { opacity: 0; transform: translateY(4px); }
3154
+ to { opacity: 1; transform: none; }
3155
+ }
3156
+
3157
+ .message--assistant .word {
3158
+ animation: ag-ui-word-in 0.3s ease both;
3159
+ animation-delay: calc(var(--ag-ui-word-index, 0) * 35ms);
3160
+ }
3161
+
3162
+ @keyframes ag-ui-word-in {
3163
+ from { opacity: 0; }
3164
+ to { opacity: 1; }
3165
+ }
3166
+
3167
+ @media (prefers-reduced-motion: reduce) {
3168
+ :host([data-text-animation="fade"]) .message--assistant,
3169
+ .message--assistant .word {
3170
+ animation: none;
3171
+ }
3172
+ }
3173
+
470
3174
  .message--user {
471
3175
  align-self: flex-end;
472
3176
  background: var(--ag-ui-user-bg);
@@ -478,6 +3182,102 @@ var STYLES = `
478
3182
  align-self: flex-start;
479
3183
  background: var(--ag-ui-assistant-bg);
480
3184
  border-bottom-left-radius: 4px;
3185
+ /* Assistant bubbles hold rendered markdown/HTML, so collapse the source
3186
+ whitespace the renderer leaves between block tags. */
3187
+ white-space: normal;
3188
+ }
3189
+
3190
+ /* Rendered-markdown elements inside an assistant bubble. */
3191
+ .message--assistant > :first-child {
3192
+ margin-top: 0;
3193
+ }
3194
+
3195
+ .message--assistant > :last-child {
3196
+ margin-bottom: 0;
3197
+ }
3198
+
3199
+ .message--assistant p,
3200
+ .message--assistant ul,
3201
+ .message--assistant ol,
3202
+ .message--assistant blockquote,
3203
+ .message--assistant pre {
3204
+ margin: 0.5em 0;
3205
+ }
3206
+
3207
+ .message--assistant ul,
3208
+ .message--assistant ol {
3209
+ padding-left: 1.3em;
3210
+ }
3211
+
3212
+ .message--assistant a {
3213
+ color: var(--ag-ui-accent);
3214
+ text-decoration: underline;
3215
+ }
3216
+
3217
+ .message--assistant code {
3218
+ font-family: ui-monospace, "SF Mono", Menlo, monospace;
3219
+ font-size: 0.92em;
3220
+ background: rgba(127, 127, 127, 0.16);
3221
+ padding: 1px 4px;
3222
+ border-radius: 4px;
3223
+ }
3224
+
3225
+ .message--assistant pre {
3226
+ padding: 8px 10px;
3227
+ overflow: auto;
3228
+ background: var(--ag-ui-bg);
3229
+ border: 1px solid var(--ag-ui-border);
3230
+ border-radius: 6px;
3231
+ }
3232
+
3233
+ .message--assistant pre code {
3234
+ background: none;
3235
+ padding: 0;
3236
+ }
3237
+
3238
+ .message--assistant blockquote {
3239
+ padding-left: 10px;
3240
+ border-left: 3px solid var(--ag-ui-border);
3241
+ color: var(--ag-ui-muted);
3242
+ }
3243
+
3244
+ .pending {
3245
+ align-self: flex-start;
3246
+ display: inline-flex;
3247
+ gap: 4px;
3248
+ align-items: center;
3249
+ padding: 12px 14px;
3250
+ background: var(--ag-ui-assistant-bg);
3251
+ border-radius: 14px;
3252
+ border-bottom-left-radius: 4px;
3253
+ }
3254
+
3255
+ .pending-dot {
3256
+ width: 6px;
3257
+ height: 6px;
3258
+ border-radius: 50%;
3259
+ background: var(--ag-ui-muted);
3260
+ animation: ag-ui-pending 1.2s infinite ease-in-out both;
3261
+ }
3262
+
3263
+ .pending-dot:nth-child(2) {
3264
+ animation-delay: 0.16s;
3265
+ }
3266
+
3267
+ .pending-dot:nth-child(3) {
3268
+ animation-delay: 0.32s;
3269
+ }
3270
+
3271
+ @keyframes ag-ui-pending {
3272
+ 0%, 80%, 100% { opacity: 0.3; transform: translateY(0); }
3273
+ 40% { opacity: 1; transform: translateY(-3px); }
3274
+ }
3275
+
3276
+ @media (prefers-reduced-motion: reduce) {
3277
+ .pending-dot {
3278
+ animation: none;
3279
+ opacity: 0.6;
3280
+ }
481
3281
  }
482
3282
 
483
3283
  .tool-call {
@@ -602,38 +3402,30 @@ var STYLES = `
602
3402
  cursor: default;
603
3403
  }
604
3404
 
605
- .modal-overlay {
606
- position: absolute;
607
- inset: 0;
3405
+ /* Inline confirmation card \u2014 lives in the transcript, no focus-stealing overlay. */
3406
+ .confirm {
3407
+ align-self: stretch;
3408
+ box-sizing: border-box;
608
3409
  display: flex;
609
- align-items: center;
610
- justify-content: center;
611
- padding: 16px;
612
- background: rgba(20, 20, 50, 0.4);
613
- backdrop-filter: blur(2px);
614
- }
615
-
616
- .modal {
617
- width: 100%;
618
- max-width: 320px;
3410
+ flex-direction: column;
3411
+ gap: 8px;
3412
+ padding: 12px;
619
3413
  background: var(--ag-ui-bg);
620
- border-radius: 12px;
621
- box-shadow: 0 16px 40px rgba(20, 20, 50, 0.3);
622
- overflow: hidden;
3414
+ border: 1px solid var(--ag-ui-accent);
3415
+ border-radius: 10px;
623
3416
  }
624
3417
 
625
- .modal-title {
626
- padding: 12px 16px;
627
- font-weight: 600;
628
- border-bottom: 1px solid var(--ag-ui-border);
3418
+ .confirm[data-resolved] {
3419
+ opacity: 0.7;
3420
+ border-color: var(--ag-ui-border);
629
3421
  }
630
3422
 
631
- .modal-body {
632
- padding: 12px 16px 4px;
3423
+ .confirm-body {
3424
+ font-weight: 600;
633
3425
  }
634
3426
 
635
- .modal-args {
636
- margin: 0 16px 12px;
3427
+ .confirm-args {
3428
+ margin: 0;
637
3429
  padding: 8px 10px;
638
3430
  max-height: 140px;
639
3431
  overflow: auto;
@@ -645,14 +3437,13 @@ var STYLES = `
645
3437
  word-break: break-word;
646
3438
  }
647
3439
 
648
- .modal-actions {
3440
+ .confirm-actions {
649
3441
  display: flex;
650
3442
  gap: 8px;
651
- padding: 0 16px 16px;
652
3443
  justify-content: flex-end;
653
3444
  }
654
3445
 
655
- .modal-btn {
3446
+ .confirm-btn {
656
3447
  border: 1px solid var(--ag-ui-border);
657
3448
  border-radius: 8px;
658
3449
  padding: 8px 14px;
@@ -663,14 +3454,87 @@ var STYLES = `
663
3454
  color: var(--ag-ui-fg);
664
3455
  }
665
3456
 
666
- .modal-btn--confirm {
3457
+ .confirm-btn:disabled {
3458
+ cursor: default;
3459
+ opacity: 0.6;
3460
+ }
3461
+
3462
+ .confirm-btn--confirm {
667
3463
  border-color: var(--ag-ui-accent);
668
3464
  background: var(--ag-ui-accent);
669
3465
  color: #ffffff;
670
3466
  }
3467
+
3468
+ /* Skills \u2014 chips row + the /-command palette, above the input. */
3469
+ .skill-chips {
3470
+ display: flex;
3471
+ flex-wrap: wrap;
3472
+ gap: 6px;
3473
+ padding: 10px 12px;
3474
+ }
3475
+
3476
+ .skill-chip {
3477
+ border: 1px solid var(--ag-ui-border);
3478
+ border-radius: 999px;
3479
+ padding: 4px 12px;
3480
+ font: inherit;
3481
+ font-size: 0.9em;
3482
+ cursor: pointer;
3483
+ background: var(--ag-ui-assistant-bg);
3484
+ color: var(--ag-ui-fg);
3485
+ }
3486
+
3487
+ .skill-chip:hover {
3488
+ border-color: var(--ag-ui-accent);
3489
+ }
3490
+
3491
+ .skill-palette {
3492
+ margin: 8px 12px 0;
3493
+ display: flex;
3494
+ flex-direction: column;
3495
+ max-height: 220px;
3496
+ overflow: auto;
3497
+ background: var(--ag-ui-bg);
3498
+ border: 1px solid var(--ag-ui-border);
3499
+ border-radius: 8px;
3500
+ box-shadow: 0 8px 24px rgba(20, 20, 50, 0.16);
3501
+ }
3502
+
3503
+ .skill-item {
3504
+ display: flex;
3505
+ flex-direction: column;
3506
+ gap: 2px;
3507
+ align-items: flex-start;
3508
+ padding: 8px 12px;
3509
+ border: none;
3510
+ background: none;
3511
+ font: inherit;
3512
+ text-align: left;
3513
+ cursor: pointer;
3514
+ color: var(--ag-ui-fg);
3515
+ }
3516
+
3517
+ .skill-item[aria-selected="true"] {
3518
+ background: var(--ag-ui-assistant-bg);
3519
+ }
3520
+
3521
+ .skill-item-title {
3522
+ font-weight: 600;
3523
+ }
3524
+
3525
+ .skill-item-desc {
3526
+ font-size: 0.85em;
3527
+ color: var(--ag-ui-muted);
3528
+ }
3529
+
3530
+ .skill-hint {
3531
+ margin: 8px 12px 0;
3532
+ font-size: 0.85em;
3533
+ color: var(--ag-ui-danger);
3534
+ }
671
3535
  `;
672
3536
 
673
- // src/tool_call_card.ts
3537
+ // src/ui/tool_call_card.ts
674
3538
  var STATUS_LABEL = {
675
3539
  [TOOL_CALL_STATUS.PENDING]: "running\u2026",
676
3540
  [TOOL_CALL_STATUS.DONE]: "\u2713 done",
@@ -686,52 +3550,268 @@ var ToolCallCard = class {
686
3550
  /** The card's root element; append this into the message list. */
687
3551
  element;
688
3552
  #status;
689
- constructor(name, args) {
3553
+ #mode;
3554
+ #args;
3555
+ constructor(name, args, mode = TOOL_DISPLAY.FULL, summary) {
3556
+ this.#mode = mode;
3557
+ this.#args = args;
690
3558
  this.element = document.createElement("div");
691
3559
  this.element.className = "tool-call";
692
3560
  this.element.setAttribute("data-tool-name", name);
693
3561
  this.element.setAttribute("data-status", TOOL_CALL_STATUS.PENDING);
3562
+ this.element.setAttribute("data-display", mode);
694
3563
  const head = document.createElement("div");
695
3564
  head.className = "tool-call-head";
696
3565
  const label = document.createElement("span");
697
3566
  label.className = "tool-call-name";
698
- label.textContent = `\u{1F527} ${name}`;
3567
+ label.textContent = `\u{1F527} ${summary ?? name}`;
699
3568
  this.#status = document.createElement("span");
700
3569
  this.#status.className = "tool-call-status";
701
3570
  this.#status.textContent = STATUS_LABEL[TOOL_CALL_STATUS.PENDING];
702
3571
  head.append(label, this.#status);
703
- const argsEl = document.createElement("pre");
704
- argsEl.className = "tool-call-args";
705
- argsEl.textContent = JSON.stringify(args, null, 2);
706
- this.element.append(head, argsEl);
3572
+ this.element.append(head);
3573
+ if (mode === TOOL_DISPLAY.FULL) {
3574
+ const argsEl = document.createElement("pre");
3575
+ argsEl.className = "tool-call-args";
3576
+ argsEl.textContent = JSON.stringify(args, null, 2);
3577
+ this.element.append(argsEl);
3578
+ }
3579
+ }
3580
+ /**
3581
+ * Flip the status pill to ``status`` and, unless in `minimal` mode, append a
3582
+ * collapsed body behind a click-to-expand toggle: the result alone (`full`),
3583
+ * or the args + result together (`compact`).
3584
+ */
3585
+ settle(status, text2) {
3586
+ this.element.setAttribute("data-status", status);
3587
+ this.#status.textContent = STATUS_LABEL[status];
3588
+ if (this.#mode === TOOL_DISPLAY.MINIMAL) {
3589
+ return;
3590
+ }
3591
+ const toggle = document.createElement("button");
3592
+ toggle.type = "button";
3593
+ toggle.className = "tool-call-toggle";
3594
+ toggle.setAttribute("aria-expanded", "false");
3595
+ const output = document.createElement("pre");
3596
+ output.className = "tool-call-result";
3597
+ output.hidden = true;
3598
+ if (this.#mode === TOOL_DISPLAY.COMPACT) {
3599
+ toggle.textContent = "Details";
3600
+ output.textContent = `args: ${JSON.stringify(this.#args)}
3601
+
3602
+ ${text2}`;
3603
+ } else {
3604
+ toggle.textContent = RESULT_LABEL[status];
3605
+ output.textContent = text2;
3606
+ }
3607
+ toggle.addEventListener("click", () => {
3608
+ const expand = output.hidden;
3609
+ output.hidden = !expand;
3610
+ toggle.setAttribute("aria-expanded", String(expand));
3611
+ });
3612
+ this.element.append(toggle, output);
3613
+ }
3614
+ };
3615
+
3616
+ // src/core/agui_client.ts
3617
+ import { randomUUID } from "@ag-ui/client";
3618
+ var AgUiClient = class {
3619
+ #agent;
3620
+ #handlers;
3621
+ #getTools;
3622
+ #getContext;
3623
+ #executeTool;
3624
+ #onPersist;
3625
+ constructor(config) {
3626
+ this.#agent = config.agent;
3627
+ this.#handlers = config.handlers;
3628
+ this.#getTools = config.getTools ?? (() => []);
3629
+ this.#getContext = config.getContext ?? (() => []);
3630
+ this.#executeTool = config.executeTool ?? null;
3631
+ this.#onPersist = config.onPersist ?? (() => {
3632
+ });
3633
+ }
3634
+ /** Whether a run is currently in flight. */
3635
+ get running() {
3636
+ return this.#agent.isRunning;
3637
+ }
3638
+ /** The current conversation history (for persistence / rehydration). */
3639
+ get messages() {
3640
+ return this.#agent.messages;
3641
+ }
3642
+ /**
3643
+ * Append a user message and run the agent to completion.
3644
+ *
3645
+ * When the agent calls frontend tools, this executes them and re-runs the
3646
+ * agent with the results, looping until the agent stops calling frontend
3647
+ * tools (bounded by {@link MAX_TOOL_ROUNDS}).
3648
+ */
3649
+ async send(content) {
3650
+ this.#agent.addMessage({ id: randomUUID(), role: "user", content });
3651
+ this.#onPersist(this.#agent.messages);
3652
+ await this.#run();
3653
+ }
3654
+ /**
3655
+ * Resume the run loop after a navigating tool's result was supplied
3656
+ * post-reload (via {@link addToolResult}). Unlike {@link send}, adds no user
3657
+ * message — it simply continues the conversation already in history.
3658
+ */
3659
+ async resume() {
3660
+ await this.#run();
3661
+ }
3662
+ /** Append a frontend tool result to history (used by the resume path). */
3663
+ addToolResult(toolCallId, content) {
3664
+ this.#agent.addMessage({ id: randomUUID(), role: "tool", content, toolCallId });
3665
+ this.#onPersist(this.#agent.messages);
3666
+ }
3667
+ async #run() {
3668
+ try {
3669
+ await this.#runLoop();
3670
+ } catch (error) {
3671
+ this.#handlers.onError(error instanceof Error ? error.message : String(error));
3672
+ } finally {
3673
+ this.#handlers.onSettled();
3674
+ }
3675
+ }
3676
+ async #runLoop() {
3677
+ for (let round = 0; round < MAX_TOOL_ROUNDS; round += 1) {
3678
+ const pending = [];
3679
+ await this.#agent.runAgent(
3680
+ { tools: this.#getTools(), context: this.#getContext() },
3681
+ this.#buildSubscriber(pending)
3682
+ );
3683
+ this.#onPersist(this.#agent.messages);
3684
+ if (this.#executeTool === null || pending.length === 0) {
3685
+ return;
3686
+ }
3687
+ let executed = false;
3688
+ for (const call of pending) {
3689
+ const result = await this.#executeTool(call);
3690
+ if (result === null) {
3691
+ continue;
3692
+ }
3693
+ if (result.halt === true) {
3694
+ return;
3695
+ }
3696
+ this.#agent.addMessage({
3697
+ id: randomUUID(),
3698
+ role: "tool",
3699
+ content: result.content,
3700
+ toolCallId: call.id
3701
+ });
3702
+ this.#onPersist(this.#agent.messages);
3703
+ executed = true;
3704
+ }
3705
+ if (!executed) {
3706
+ return;
3707
+ }
3708
+ }
3709
+ }
3710
+ #buildSubscriber(pending) {
3711
+ const h = this.#handlers;
3712
+ return {
3713
+ onRunInitialized() {
3714
+ h.onRunStart();
3715
+ },
3716
+ onTextMessageContentEvent({ textMessageBuffer }) {
3717
+ h.onTextDelta(textMessageBuffer);
3718
+ },
3719
+ onTextMessageEndEvent({ textMessageBuffer }) {
3720
+ h.onTextEnd(textMessageBuffer);
3721
+ },
3722
+ onToolCallEndEvent({ event, toolCallName, toolCallArgs }) {
3723
+ const call = {
3724
+ id: event.toolCallId,
3725
+ name: toolCallName,
3726
+ args: toolCallArgs
3727
+ };
3728
+ pending.push(call);
3729
+ h.onToolCall(call);
3730
+ },
3731
+ onToolCallResultEvent({ event }) {
3732
+ h.onToolResult(event.toolCallId, event.content);
3733
+ },
3734
+ onRunErrorEvent({ event }) {
3735
+ h.onError(event.message);
3736
+ },
3737
+ onRunFinalized() {
3738
+ h.onRunEnd();
3739
+ }
3740
+ };
707
3741
  }
708
- /**
709
- * Flip the status pill to ``status`` and append a collapsed body holding
710
- * ``text`` (the JSON result, an error message, a decline notice, or a
711
- * server-executed note) behind a click-to-expand toggle.
712
- */
713
- settle(status, text) {
714
- this.element.setAttribute("data-status", status);
715
- this.#status.textContent = STATUS_LABEL[status];
716
- const toggle = document.createElement("button");
717
- toggle.type = "button";
718
- toggle.className = "tool-call-toggle";
719
- toggle.setAttribute("aria-expanded", "false");
720
- toggle.textContent = RESULT_LABEL[status];
721
- const output = document.createElement("pre");
722
- output.className = "tool-call-result";
723
- output.textContent = text;
724
- output.hidden = true;
725
- toggle.addEventListener("click", () => {
726
- const expand = output.hidden;
727
- output.hidden = !expand;
728
- toggle.setAttribute("aria-expanded", String(expand));
729
- });
730
- this.element.append(toggle, output);
3742
+ };
3743
+
3744
+ // src/core/conversation_store.ts
3745
+ import { randomUUID as randomUUID2 } from "@ag-ui/client";
3746
+ var THREAD_KEY = "ag-ui-chat:thread";
3747
+ var MESSAGES_PREFIX = "ag-ui-chat:messages:";
3748
+ var CHECKPOINT_PREFIX = "ag-ui-chat:checkpoint:";
3749
+ var SessionStorageStore = class {
3750
+ threadId() {
3751
+ const existing = sessionStorage.getItem(THREAD_KEY);
3752
+ if (existing !== null) {
3753
+ return existing;
3754
+ }
3755
+ const id = randomUUID2();
3756
+ sessionStorage.setItem(THREAD_KEY, id);
3757
+ return id;
3758
+ }
3759
+ loadMessages(threadId) {
3760
+ return Promise.resolve(this.#readJson(MESSAGES_PREFIX + threadId));
3761
+ }
3762
+ saveMessages(threadId, messages) {
3763
+ sessionStorage.setItem(MESSAGES_PREFIX + threadId, JSON.stringify(messages));
3764
+ }
3765
+ loadCheckpoint(threadId) {
3766
+ return this.#readJson(CHECKPOINT_PREFIX + threadId);
3767
+ }
3768
+ saveCheckpoint(threadId, checkpoint) {
3769
+ const key = CHECKPOINT_PREFIX + threadId;
3770
+ if (checkpoint === null) {
3771
+ sessionStorage.removeItem(key);
3772
+ return;
3773
+ }
3774
+ sessionStorage.setItem(key, JSON.stringify(checkpoint));
3775
+ }
3776
+ clear(threadId) {
3777
+ sessionStorage.removeItem(MESSAGES_PREFIX + threadId);
3778
+ sessionStorage.removeItem(CHECKPOINT_PREFIX + threadId);
3779
+ sessionStorage.removeItem(THREAD_KEY);
3780
+ }
3781
+ /** Parse a stored JSON value, returning `null` when absent or corrupt. */
3782
+ #readJson(key) {
3783
+ const raw = sessionStorage.getItem(key);
3784
+ if (raw === null) {
3785
+ return null;
3786
+ }
3787
+ try {
3788
+ return JSON.parse(raw);
3789
+ } catch {
3790
+ return null;
3791
+ }
731
3792
  }
732
3793
  };
733
3794
 
734
- // src/ag_ui_chat.ts
3795
+ // src/core/create_http_agent.ts
3796
+ import { HttpAgent } from "@ag-ui/client";
3797
+ function createHttpAgent(options) {
3798
+ return new HttpAgent({
3799
+ url: options.endpoint,
3800
+ headers: options.headers ?? {},
3801
+ // HttpAgent invokes its configured fetch as a method (`this.fetch(...)`),
3802
+ // which would rebind the global `fetch` to the agent instance and trigger
3803
+ // "Illegal invocation" in browsers. Wrap it so `fetch` is always called as
3804
+ // a free function with the correct receiver.
3805
+ fetch: (url, init) => fetch(url, init),
3806
+ // Spread conditionally: under `exactOptionalPropertyTypes` an explicit
3807
+ // `undefined` is not assignable to these optional config fields.
3808
+ ...options.threadId !== void 0 ? { threadId: options.threadId } : {},
3809
+ ...options.initialMessages !== void 0 ? { initialMessages: [...options.initialMessages] } : {}
3810
+ });
3811
+ }
3812
+
3813
+ // src/core/ag_ui_chat.ts
3814
+ var COLLAPSED_KEY = "ag-ui-chat:collapsed";
735
3815
  var AgUiChat = class extends HTMLElement {
736
3816
  /** Agent factory; override to inject a custom or fake agent (tests). */
737
3817
  agentFactory = createHttpAgent;
@@ -739,6 +3819,14 @@ var AgUiChat = class extends HTMLElement {
739
3819
  headers = {};
740
3820
  /** When true, destructive tools execute without a confirmation modal. */
741
3821
  autoConfirm = false;
3822
+ /**
3823
+ * Optional per-call confirmation predicate. When set, it is authoritative:
3824
+ * given a tool name + args it decides whether *this* call needs confirmation
3825
+ * (so one tool can be instant for some args and confirmed for others — what a
3826
+ * static `x-destructive` flag can't express). When unset, the `x-destructive`
3827
+ * schema flag is used. `autoConfirm` short-circuits both.
3828
+ */
3829
+ confirmPredicate = null;
742
3830
  /**
743
3831
  * Per-run frontend tool catalog provider. Defaults to the built-in
744
3832
  * `route.*` tools (when a {@link routeMap} is set) plus the tools registered
@@ -746,7 +3834,7 @@ var AgUiChat = class extends HTMLElement {
746
3834
  * fully custom catalog.
747
3835
  */
748
3836
  getTools = () => [
749
- ...this.#routeTools().map((t) => ({
3837
+ ...this.#builtinTools().map((t) => ({
750
3838
  name: t.name,
751
3839
  description: t.description,
752
3840
  parameters: t.parameters
@@ -788,18 +3876,38 @@ var AgUiChat = class extends HTMLElement {
788
3876
  navigated: true,
789
3877
  url: window.location.href
790
3878
  });
3879
+ /**
3880
+ * Named values used to fill a skill prompt's `{placeholder}`s before send
3881
+ * (e.g. `{ model: "Order", selected_ids: "1,2" }`). A host (the admin) sets
3882
+ * this from the current page; a missing placeholder blocks the send.
3883
+ */
3884
+ skillContext = () => ({});
791
3885
  #toolRegistry = new ClientToolRegistry();
792
3886
  /** Tool-call cards awaiting execution, keyed by call id. */
793
3887
  #toolCards = /* @__PURE__ */ new Map();
3888
+ /**
3889
+ * Call ids whose card was already settled from a streamed server-side result
3890
+ * (`TOOL_CALL_RESULT`), so the post-run executeTool sweep doesn't overwrite
3891
+ * the real output with the generic "executed on the server" fallback.
3892
+ */
3893
+ #serverSettled = /* @__PURE__ */ new Set();
794
3894
  #root;
795
3895
  #chat;
796
3896
  #messages;
797
3897
  #input;
798
3898
  #send;
3899
+ #title;
3900
+ #skillsMenu;
3901
+ #skillHint;
799
3902
  #client = null;
800
3903
  #streamingBubble = null;
3904
+ #pending = null;
801
3905
  #threadId = "";
802
3906
  #initialMessages = [];
3907
+ // Skill catalog by source; merged backend → embed → client (later wins).
3908
+ #backendSkills = [];
3909
+ #embedSkills = [];
3910
+ #clientSkills = [];
803
3911
  constructor() {
804
3912
  super();
805
3913
  this.#root = this.attachShadow({ mode: "open" });
@@ -807,6 +3915,16 @@ var AgUiChat = class extends HTMLElement {
807
3915
  this.#messages = document.createElement("div");
808
3916
  this.#input = document.createElement("textarea");
809
3917
  this.#send = document.createElement("button");
3918
+ this.#title = document.createElement("span");
3919
+ this.#skillHint = document.createElement("div");
3920
+ this.#skillsMenu = new SkillsMenu((skill) => this.#applySkill(skill));
3921
+ }
3922
+ /** Attributes whose late changes must reflect in already-rendered chrome. */
3923
+ static get observedAttributes() {
3924
+ return ["title-text"];
3925
+ }
3926
+ attributeChangedCallback(_name, _previous, value) {
3927
+ this.#title.textContent = value ?? "Assistant";
810
3928
  }
811
3929
  /** Declare a frontend tool the agent may call. */
812
3930
  registerTool(tool) {
@@ -828,11 +3946,34 @@ var AgUiChat = class extends HTMLElement {
828
3946
  () => this.navigate
829
3947
  );
830
3948
  }
831
- /** Resolve a tool by name: built-in route tools first, then the registry. */
3949
+ /**
3950
+ * The built-in `read_page` tool, present only when a {@link getPageMap}
3951
+ * provider is set. A *pull* the agent can call mid-turn to see the page after
3952
+ * it has acted (the auto-injected context is a send-time snapshot).
3953
+ */
3954
+ #pageTools() {
3955
+ const getPageMap = this.getPageMap;
3956
+ if (getPageMap === null) {
3957
+ return [];
3958
+ }
3959
+ return [
3960
+ {
3961
+ name: "read_page",
3962
+ description: "Read the current page's structure (fields, buttons, route). Call after acting to observe the result within the same turn.",
3963
+ parameters: { type: "object", properties: {}, required: [] },
3964
+ handler: () => getPageMap()
3965
+ }
3966
+ ];
3967
+ }
3968
+ /** All built-in (route + page) frontend tools. */
3969
+ #builtinTools() {
3970
+ return [...this.#routeTools(), ...this.#pageTools()];
3971
+ }
3972
+ /** Resolve a tool by name: built-in tools first, then the registry. */
832
3973
  #resolveTool(name) {
833
- const route = this.#routeTools().find((t) => t.name === name);
834
- if (route !== void 0) {
835
- return route;
3974
+ const builtin = this.#builtinTools().find((t) => t.name === name);
3975
+ if (builtin !== void 0) {
3976
+ return builtin;
836
3977
  }
837
3978
  return this.#toolRegistry.has(name) ? this.#toolRegistry.get(name) : null;
838
3979
  }
@@ -840,11 +3981,149 @@ var AgUiChat = class extends HTMLElement {
840
3981
  get endpoint() {
841
3982
  return this.getAttribute("endpoint") ?? "";
842
3983
  }
3984
+ // Reflecting setter so frameworks (e.g. React 19) that assign matching
3985
+ // props as element *properties* don't hit a read-only property. Read at
3986
+ // use-time, so a runtime change applies to the next run.
3987
+ set endpoint(value) {
3988
+ this.setAttribute("endpoint", value);
3989
+ }
3990
+ /**
3991
+ * How much detail tool-call cards show, from the `data-tool-display`
3992
+ * attribute (`minimal` / `compact` / `full`). Defaults to `full`.
3993
+ */
3994
+ get toolDisplay() {
3995
+ const attr = this.getAttribute("data-tool-display");
3996
+ if (attr === TOOL_DISPLAY.MINIMAL || attr === TOOL_DISPLAY.COMPACT) {
3997
+ return attr;
3998
+ }
3999
+ return TOOL_DISPLAY.FULL;
4000
+ }
4001
+ set toolDisplay(value) {
4002
+ this.setAttribute("data-tool-display", value);
4003
+ }
843
4004
  connectedCallback() {
844
4005
  this.#render();
4006
+ if (sessionStorage.getItem(COLLAPSED_KEY) === "1") {
4007
+ this.setAttribute("collapsed", "");
4008
+ }
4009
+ this.#initSkills();
845
4010
  this.#threadId = this.conversationStore.threadId();
846
4011
  void this.#rehydrate();
847
4012
  }
4013
+ /**
4014
+ * Replace the host-supplied (client) skill catalog. Merged after the embedded
4015
+ * and fetched skills (so a client skill overrides a same-named server one).
4016
+ */
4017
+ setSkills(skills) {
4018
+ this.#clientSkills = skills;
4019
+ this.#recomputeSkills();
4020
+ }
4021
+ /** Wire the skill surfaces: opt-in flags, embedded catalog, optional fetch. */
4022
+ #initSkills() {
4023
+ this.#skillsMenu.enableChips(this.getAttribute("data-prompt-chips") === "true");
4024
+ this.#skillsMenu.enableSlash(this.getAttribute("data-slash-commands") === "true");
4025
+ this.#embedSkills = this.#readEmbeddedSkills();
4026
+ this.#recomputeSkills();
4027
+ void this.#fetchSkills();
4028
+ }
4029
+ /** Parse the inline `data-skills` JSON catalog (empty when absent/malformed). */
4030
+ #readEmbeddedSkills() {
4031
+ const raw = this.getAttribute("data-skills");
4032
+ if (raw === null) {
4033
+ return [];
4034
+ }
4035
+ try {
4036
+ return parseSkills(JSON.parse(raw));
4037
+ } catch {
4038
+ return [];
4039
+ }
4040
+ }
4041
+ /** Fetch the backend skills catalog from `data-skills-url`, if set. */
4042
+ async #fetchSkills() {
4043
+ const url = this.getAttribute("data-skills-url");
4044
+ if (url === null) {
4045
+ return;
4046
+ }
4047
+ try {
4048
+ const response = await fetch(url, { headers: this.headers });
4049
+ this.#backendSkills = parseSkills(await response.json());
4050
+ this.#recomputeSkills();
4051
+ } catch {
4052
+ }
4053
+ }
4054
+ /** Merge the three sources (backend → embed → client; later wins by name). */
4055
+ #recomputeSkills() {
4056
+ const merged = /* @__PURE__ */ new Map();
4057
+ for (const skill of [...this.#backendSkills, ...this.#embedSkills, ...this.#clientSkills]) {
4058
+ merged.set(skill.name, skill);
4059
+ }
4060
+ this.#skillsMenu.setSkills([...merged.values()]);
4061
+ }
4062
+ /** Pre-fill (or send) a picked skill's prompt, filling its placeholders. */
4063
+ #applySkill(skill) {
4064
+ const { text: text2, missing } = fillTemplate(skill.prompt, this.skillContext());
4065
+ if (missing.length > 0) {
4066
+ this.#skillHint.textContent = `\u201C${skill.title}\u201D needs: ${missing.join(", ")}`;
4067
+ this.#skillHint.hidden = false;
4068
+ return;
4069
+ }
4070
+ this.#skillHint.hidden = true;
4071
+ this.#input.value = text2;
4072
+ if (skill.sendImmediately === true) {
4073
+ void this.#submit();
4074
+ } else {
4075
+ this.#input.focus();
4076
+ }
4077
+ }
4078
+ /** Whether the widget is collapsed (reflected as the `collapsed` attribute). */
4079
+ get collapsed() {
4080
+ return this.hasAttribute("collapsed");
4081
+ }
4082
+ // Property setter (framework interop) — delegates to setCollapsed so a
4083
+ // `collapsed` prop assignment persists + emits the toggle event.
4084
+ set collapsed(value) {
4085
+ this.setCollapsed(value);
4086
+ }
4087
+ /**
4088
+ * Set the collapsed state: reflect the `collapsed` attribute, persist it
4089
+ * per-tab, and emit a {@link TOGGLE_EVENT} so a host can mirror the state in
4090
+ * its own chrome.
4091
+ */
4092
+ setCollapsed(collapsed) {
4093
+ if (collapsed) {
4094
+ this.setAttribute("collapsed", "");
4095
+ } else {
4096
+ this.removeAttribute("collapsed");
4097
+ }
4098
+ sessionStorage.setItem(COLLAPSED_KEY, collapsed ? "1" : "0");
4099
+ this.dispatchEvent(
4100
+ new CustomEvent(TOGGLE_EVENT, {
4101
+ detail: { collapsed },
4102
+ bubbles: true,
4103
+ composed: true
4104
+ })
4105
+ );
4106
+ }
4107
+ /** Flip the collapsed state. Bound to the built-in header toggle. */
4108
+ toggleCollapsed() {
4109
+ this.setCollapsed(!this.collapsed);
4110
+ }
4111
+ /**
4112
+ * Start a fresh conversation: forget the persisted history, drop the
4113
+ * in-memory run state, clear the transcript, and mint a new thread id.
4114
+ */
4115
+ newChat() {
4116
+ this.conversationStore.clear(this.#threadId);
4117
+ this.#client = null;
4118
+ this.#streamingBubble = null;
4119
+ this.#hidePending();
4120
+ this.#toolCards.clear();
4121
+ this.#serverSettled.clear();
4122
+ this.#initialMessages = [];
4123
+ this.#messages.replaceChildren();
4124
+ this.#threadId = this.conversationStore.threadId();
4125
+ this.#send.disabled = false;
4126
+ }
848
4127
  /**
849
4128
  * Restore the conversation from the store on mount, then — if a navigating
850
4129
  * tool reloaded the page mid-run — resume the loop by supplying that tool's
@@ -863,15 +4142,61 @@ var AgUiChat = class extends HTMLElement {
863
4142
  await this.#resumeFrom(checkpoint);
864
4143
  }
865
4144
  }
866
- /** Render a restored message as a chat bubble (text turns only). */
4145
+ /**
4146
+ * Replay a restored message: text bubbles *and* tool activity. An assistant
4147
+ * turn may carry `toolCalls` (rendered as cards) and/or text; a `tool` turn
4148
+ * carries a result that settles the matching card. So a refreshed page shows
4149
+ * the full transcript — tool calls and their results — not just the prose.
4150
+ */
867
4151
  #renderHistoricMessage(message) {
868
- if (typeof message.content !== "string" || message.content === "") {
4152
+ const text2 = typeof message.content === "string" ? message.content : "";
4153
+ if (message.role === MESSAGE_ROLE.USER) {
4154
+ if (text2 !== "") {
4155
+ this.appendMessage(MESSAGE_ROLE.USER, text2);
4156
+ }
869
4157
  return;
870
4158
  }
871
- if (message.role === MESSAGE_ROLE.USER) {
872
- this.appendMessage(MESSAGE_ROLE.USER, message.content);
873
- } else if (message.role === MESSAGE_ROLE.ASSISTANT) {
874
- this.appendMessage(MESSAGE_ROLE.ASSISTANT, message.content);
4159
+ if (message.role === MESSAGE_ROLE.ASSISTANT) {
4160
+ if (text2 !== "") {
4161
+ this.#revealWords(this.appendMessage(MESSAGE_ROLE.ASSISTANT, text2));
4162
+ }
4163
+ const toolCalls = message.toolCalls;
4164
+ if (toolCalls !== void 0) {
4165
+ for (const call of toolCalls) {
4166
+ this.#cardFor({
4167
+ id: call.id,
4168
+ name: call.function.name,
4169
+ args: this.#parseArgs(call.function.arguments)
4170
+ });
4171
+ }
4172
+ }
4173
+ return;
4174
+ }
4175
+ if (message.role === "tool") {
4176
+ const card = this.#toolCards.get(message.toolCallId);
4177
+ if (card !== void 0) {
4178
+ card.settle(TOOL_CALL_STATUS.DONE, message.content);
4179
+ }
4180
+ }
4181
+ }
4182
+ /** Parse a tool call's JSON `arguments` string from history into an object. */
4183
+ #parseArgs(raw) {
4184
+ try {
4185
+ const parsed = JSON.parse(raw);
4186
+ if (typeof parsed === "object" && parsed !== null) {
4187
+ return parsed;
4188
+ }
4189
+ } catch {
4190
+ }
4191
+ return {};
4192
+ }
4193
+ /**
4194
+ * Word-by-word reveal for the `word` text-animation mode, applied to a
4195
+ * completed assistant bubble. `fade` is pure CSS (no JS); `none` is a no-op.
4196
+ */
4197
+ #revealWords(bubble) {
4198
+ if (this.getAttribute("data-text-animation") === "word") {
4199
+ wrapWords(bubble);
875
4200
  }
876
4201
  }
877
4202
  /** Complete the checkpointed navigating tool call and continue the run. */
@@ -881,11 +4206,21 @@ var AgUiChat = class extends HTMLElement {
881
4206
  client.addToolResult(checkpoint.toolCallId, JSON.stringify(this.navigationResult(checkpoint)));
882
4207
  await client.resume();
883
4208
  }
884
- /** Append a message bubble and return it. */
4209
+ /**
4210
+ * Append a message bubble and return it.
4211
+ *
4212
+ * Assistant content is rendered as sanitised markdown/HTML; user content
4213
+ * stays literal text (no need to parse what the user typed, and it avoids
4214
+ * rendering user-authored markup).
4215
+ */
885
4216
  appendMessage(role, content) {
886
4217
  const bubble = document.createElement("div");
887
4218
  bubble.className = `message message--${role}`;
888
- bubble.textContent = content;
4219
+ if (role === MESSAGE_ROLE.ASSISTANT) {
4220
+ bubble.innerHTML = renderMarkdown(content);
4221
+ } else {
4222
+ bubble.textContent = content;
4223
+ }
889
4224
  this.#messages.appendChild(bubble);
890
4225
  this.#messages.scrollTop = this.#messages.scrollHeight;
891
4226
  return bubble;
@@ -896,25 +4231,68 @@ var AgUiChat = class extends HTMLElement {
896
4231
  this.#chat.className = "chat";
897
4232
  const header = document.createElement("div");
898
4233
  header.className = "header";
899
- header.textContent = this.getAttribute("title-text") ?? "Assistant";
4234
+ const title = this.#title;
4235
+ title.className = "header-title";
4236
+ title.textContent = this.getAttribute("title-text") ?? "Assistant";
4237
+ const controls = document.createElement("div");
4238
+ controls.className = "header-controls";
4239
+ const newChat = document.createElement("button");
4240
+ newChat.type = "button";
4241
+ newChat.className = "header-btn header-btn--new";
4242
+ newChat.title = "New chat";
4243
+ newChat.setAttribute("aria-label", "New chat");
4244
+ newChat.textContent = "\u271A";
4245
+ newChat.addEventListener("click", () => this.newChat());
4246
+ const collapse = document.createElement("button");
4247
+ collapse.type = "button";
4248
+ collapse.className = "header-btn header-btn--collapse";
4249
+ collapse.title = "Collapse";
4250
+ collapse.setAttribute("aria-label", "Collapse");
4251
+ collapse.textContent = "\u2014";
4252
+ collapse.addEventListener("click", () => this.toggleCollapsed());
4253
+ controls.append(newChat, collapse);
4254
+ header.append(title, controls);
900
4255
  this.#messages.className = "messages";
4256
+ this.#messages.setAttribute("role", "log");
4257
+ this.#messages.setAttribute("aria-live", "polite");
4258
+ this.#messages.setAttribute("aria-label", "Conversation");
901
4259
  const inputRow = document.createElement("div");
902
4260
  inputRow.className = "input-row";
903
4261
  this.#input.className = "input";
4262
+ this.#input.setAttribute("aria-label", "Message");
904
4263
  this.#input.rows = 2;
905
4264
  this.#input.placeholder = "Ask anything\u2026";
906
4265
  this.#input.addEventListener("keydown", (event) => this.#onKeydown(event));
4266
+ this.#input.addEventListener("input", () => this.#onInput());
907
4267
  this.#send.className = "send";
908
4268
  this.#send.type = "button";
909
4269
  this.#send.textContent = "Send";
910
4270
  this.#send.addEventListener("click", () => {
911
4271
  void this.#submit();
912
4272
  });
4273
+ this.#skillHint.className = "skill-hint";
4274
+ this.#skillHint.hidden = true;
913
4275
  inputRow.append(this.#input, this.#send);
914
- this.#chat.append(header, this.#messages, inputRow);
4276
+ this.#chat.append(
4277
+ header,
4278
+ this.#messages,
4279
+ this.#skillsMenu.palette,
4280
+ this.#skillsMenu.chips,
4281
+ this.#skillHint,
4282
+ inputRow
4283
+ );
915
4284
  this.#root.append(style, this.#chat);
916
4285
  }
4286
+ /** Forward input changes to the skills palette and clear any stale hint. */
4287
+ #onInput() {
4288
+ this.#skillsMenu.onInput(this.#input.value);
4289
+ this.#skillHint.hidden = true;
4290
+ }
917
4291
  #onKeydown(event) {
4292
+ if (this.#skillsMenu.onKeydown(event)) {
4293
+ event.preventDefault();
4294
+ return;
4295
+ }
918
4296
  if (event.key === "Enter" && !event.shiftKey) {
919
4297
  event.preventDefault();
920
4298
  void this.#submit();
@@ -961,22 +4339,39 @@ var AgUiChat = class extends HTMLElement {
961
4339
  }
962
4340
  return this.#client;
963
4341
  }
4342
+ /** Whether ``call`` should be gated behind the confirmation card. */
4343
+ async #needsConfirmation(call, tool) {
4344
+ if (this.autoConfirm) {
4345
+ return false;
4346
+ }
4347
+ if (this.confirmPredicate !== null) {
4348
+ return await this.confirmPredicate(call.name, call.args) === true;
4349
+ }
4350
+ return isDestructive(tool.parameters);
4351
+ }
964
4352
  async #executeTool(call) {
965
4353
  const card = this.#cardFor(call);
966
4354
  this.#toolCards.delete(call.id);
967
4355
  const tool = this.#resolveTool(call.name);
968
4356
  if (tool === null) {
969
- card.settle(TOOL_CALL_STATUS.DONE, "Executed on the server.");
4357
+ if (!this.#serverSettled.has(call.id)) {
4358
+ card.settle(TOOL_CALL_STATUS.DONE, "Executed on the server.");
4359
+ }
970
4360
  return null;
971
4361
  }
972
- if (isDestructive(tool.parameters) && !this.autoConfirm) {
973
- const accepted = await requestConfirmation(this.#chat, {
974
- toolName: call.name,
975
- args: call.args
976
- });
4362
+ if (await this.#needsConfirmation(call, tool)) {
4363
+ const request = { toolName: call.name, args: call.args };
4364
+ const confirmText = tool.parameters[X_CONFIRM_KEY];
4365
+ if (typeof confirmText === "string") {
4366
+ request.message = confirmText;
4367
+ }
4368
+ const decision = requestConfirmation(this.#messages, request);
4369
+ this.#messages.scrollTop = this.#messages.scrollHeight;
4370
+ const accepted = await decision;
977
4371
  if (!accepted) {
978
4372
  const message = "User declined the action.";
979
4373
  card.settle(TOOL_CALL_STATUS.DECLINED, message);
4374
+ this.#showPending();
980
4375
  return { content: message };
981
4376
  }
982
4377
  }
@@ -992,6 +4387,7 @@ var AgUiChat = class extends HTMLElement {
992
4387
  }
993
4388
  const content = JSON.stringify(result ?? null);
994
4389
  card.settle(TOOL_CALL_STATUS.DONE, content);
4390
+ this.#showPending();
995
4391
  return { content };
996
4392
  } catch (error) {
997
4393
  if (navigates) {
@@ -999,6 +4395,7 @@ var AgUiChat = class extends HTMLElement {
999
4395
  }
1000
4396
  const message = error instanceof Error ? error.message : String(error);
1001
4397
  card.settle(TOOL_CALL_STATUS.ERROR, message);
4398
+ this.#showPending();
1002
4399
  return { content: `Error: ${message}`, error: message };
1003
4400
  }
1004
4401
  }
@@ -1006,34 +4403,80 @@ var AgUiChat = class extends HTMLElement {
1006
4403
  return {
1007
4404
  onRunStart: () => {
1008
4405
  this.#send.disabled = true;
4406
+ this.#showPending();
1009
4407
  },
1010
4408
  onTextDelta: (buffer) => {
4409
+ this.#hidePending();
1011
4410
  this.#streamInto(buffer);
1012
4411
  },
1013
4412
  onTextEnd: (buffer) => {
1014
- this.#streamInto(buffer);
4413
+ this.#revealWords(this.#streamInto(buffer));
1015
4414
  this.#streamingBubble = null;
1016
4415
  },
1017
4416
  onToolCall: (call) => {
4417
+ this.#hidePending();
1018
4418
  this.#cardFor(call);
1019
4419
  },
4420
+ onToolResult: (toolCallId, content) => {
4421
+ const card = this.#toolCards.get(toolCallId);
4422
+ if (card === void 0) {
4423
+ return;
4424
+ }
4425
+ card.settle(TOOL_CALL_STATUS.DONE, content);
4426
+ this.#serverSettled.add(toolCallId);
4427
+ },
1020
4428
  onRunEnd: () => {
4429
+ this.#hidePending();
1021
4430
  this.#send.disabled = false;
1022
4431
  this.#streamingBubble = null;
1023
4432
  },
1024
4433
  onError: (message) => {
1025
- this.appendMessage(MESSAGE_ROLE.ASSISTANT, `\u26A0\uFE0F ${message}`);
4434
+ this.#hidePending();
4435
+ this.#revealWords(this.appendMessage(MESSAGE_ROLE.ASSISTANT, `\u26A0\uFE0F ${message}`));
4436
+ this.#send.disabled = false;
4437
+ this.#streamingBubble = null;
4438
+ },
4439
+ onSettled: () => {
4440
+ this.#hidePending();
1026
4441
  this.#send.disabled = false;
1027
4442
  this.#streamingBubble = null;
1028
4443
  }
1029
4444
  };
1030
4445
  }
4446
+ /**
4447
+ * Show a "thinking" indicator while the agent is being awaited — both the
4448
+ * silent stretch before the first token and the gap after a tool result
4449
+ * while the next round is requested. Idempotent.
4450
+ */
4451
+ #showPending() {
4452
+ if (this.#pending !== null) {
4453
+ return;
4454
+ }
4455
+ const pending = document.createElement("div");
4456
+ pending.className = "pending";
4457
+ pending.setAttribute("role", "status");
4458
+ pending.setAttribute("aria-label", "Assistant is thinking\u2026");
4459
+ for (let i = 0; i < 3; i += 1) {
4460
+ const dot = document.createElement("span");
4461
+ dot.className = "pending-dot";
4462
+ pending.appendChild(dot);
4463
+ }
4464
+ this.#pending = pending;
4465
+ this.#messages.appendChild(pending);
4466
+ this.#messages.scrollTop = this.#messages.scrollHeight;
4467
+ }
4468
+ /** Remove the pending indicator if shown. */
4469
+ #hidePending() {
4470
+ this.#pending?.remove();
4471
+ this.#pending = null;
4472
+ }
1031
4473
  #streamInto(buffer) {
1032
4474
  if (this.#streamingBubble === null) {
1033
4475
  this.#streamingBubble = this.appendMessage(MESSAGE_ROLE.ASSISTANT, "");
1034
4476
  }
1035
- this.#streamingBubble.textContent = buffer;
4477
+ this.#streamingBubble.innerHTML = renderMarkdown(buffer);
1036
4478
  this.#messages.scrollTop = this.#messages.scrollHeight;
4479
+ return this.#streamingBubble;
1037
4480
  }
1038
4481
  /**
1039
4482
  * The card for ``call``, creating and appending it on first sight.
@@ -1046,7 +4489,13 @@ var AgUiChat = class extends HTMLElement {
1046
4489
  if (existing !== void 0) {
1047
4490
  return existing;
1048
4491
  }
1049
- const card = new ToolCallCard(call.name, call.args);
4492
+ const summary = this.#resolveTool(call.name)?.parameters[X_SUMMARY_KEY];
4493
+ const card = new ToolCallCard(
4494
+ call.name,
4495
+ call.args,
4496
+ this.toolDisplay,
4497
+ typeof summary === "string" ? summary : void 0
4498
+ );
1050
4499
  this.#toolCards.set(call.id, card);
1051
4500
  this.#messages.appendChild(card.element);
1052
4501
  this.#messages.scrollTop = this.#messages.scrollHeight;
@@ -1054,7 +4503,36 @@ var AgUiChat = class extends HTMLElement {
1054
4503
  }
1055
4504
  };
1056
4505
 
1057
- // src/animations.ts
4506
+ // src/core/define_ag_ui_chat.ts
4507
+ function defineAgUiChat() {
4508
+ if (customElements.get(ELEMENT_TAG) === void 0) {
4509
+ customElements.define(ELEMENT_TAG, AgUiChat);
4510
+ }
4511
+ }
4512
+
4513
+ // src/dom/native_setter.ts
4514
+ function prototypeSetter(proto, prop) {
4515
+ const setter = Object.getOwnPropertyDescriptor(proto, prop).set;
4516
+ return setter;
4517
+ }
4518
+ var setInputValue = prototypeSetter(HTMLInputElement.prototype, "value");
4519
+ var setTextareaValue = prototypeSetter(HTMLTextAreaElement.prototype, "value");
4520
+ var setSelectValue = prototypeSetter(HTMLSelectElement.prototype, "value");
4521
+ var setInputChecked = prototypeSetter(HTMLInputElement.prototype, "checked");
4522
+ function setNativeValue(el, value) {
4523
+ if (el instanceof HTMLTextAreaElement) {
4524
+ setTextareaValue.call(el, value);
4525
+ } else if (el instanceof HTMLSelectElement) {
4526
+ setSelectValue.call(el, value);
4527
+ } else {
4528
+ setInputValue.call(el, value);
4529
+ }
4530
+ }
4531
+ function setNativeChecked(el, checked) {
4532
+ setInputChecked.call(el, checked);
4533
+ }
4534
+
4535
+ // src/dom/animations.ts
1058
4536
  var ACCENT = "#4f46e5";
1059
4537
  function delay(ms) {
1060
4538
  return new Promise((resolve) => {
@@ -1063,10 +4541,10 @@ function delay(ms) {
1063
4541
  }
1064
4542
  async function typeInto(el, value, options = {}) {
1065
4543
  const charDelayMs = options.charDelayMs ?? 35;
1066
- el.value = "";
4544
+ setNativeValue(el, "");
1067
4545
  el.dispatchEvent(new Event("input", { bubbles: true }));
1068
4546
  for (const char of value) {
1069
- el.value += char;
4547
+ setNativeValue(el, el.value + char);
1070
4548
  el.dispatchEvent(new Event("input", { bubbles: true }));
1071
4549
  if (charDelayMs > 0) {
1072
4550
  await delay(charDelayMs);
@@ -1096,15 +4574,67 @@ async function focusWithFlash(el, options = {}) {
1096
4574
  await delay(flashMs);
1097
4575
  el.style.boxShadow = previousShadow;
1098
4576
  }
1099
-
1100
- // src/define_ag_ui_chat.ts
1101
- function defineAgUiChat() {
1102
- if (customElements.get(ELEMENT_TAG) === void 0) {
1103
- customElements.define(ELEMENT_TAG, AgUiChat);
4577
+ var RING = "0 0 0 3px rgba(79, 70, 229, 0.4)";
4578
+ function prefersReducedMotion() {
4579
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
4580
+ }
4581
+ function motionDelay(ms) {
4582
+ if (ms <= 0 || prefersReducedMotion()) {
4583
+ return Promise.resolve();
4584
+ }
4585
+ return delay(ms);
4586
+ }
4587
+ async function pressThenClick(el, options = {}) {
4588
+ const pressMs = options.pressMs ?? 140;
4589
+ const previousTransform = el.style.transform;
4590
+ const previousTransition = el.style.transition;
4591
+ const previousShadow = el.style.boxShadow;
4592
+ el.style.transition = "transform 80ms ease";
4593
+ el.style.transform = "scale(0.96)";
4594
+ el.style.boxShadow = RING;
4595
+ await motionDelay(pressMs);
4596
+ el.style.transform = previousTransform;
4597
+ el.style.transition = previousTransition;
4598
+ el.style.boxShadow = previousShadow;
4599
+ el.click();
4600
+ }
4601
+ function findOption(el, value) {
4602
+ for (const option of Array.from(el.options)) {
4603
+ if (option.value === value || option.text === value) {
4604
+ return option;
4605
+ }
4606
+ }
4607
+ return null;
4608
+ }
4609
+ async function selectOption(el, value, options = {}) {
4610
+ const option = findOption(el, value);
4611
+ if (option === null) {
4612
+ throw new Error(`no <option> matching "${value}"`);
1104
4613
  }
4614
+ const highlightMs = options.highlightMs ?? 220;
4615
+ const previousOutline = el.style.outline;
4616
+ const previousOffset = el.style.outlineOffset;
4617
+ el.style.outline = `2px solid ${ACCENT}`;
4618
+ el.style.outlineOffset = "2px";
4619
+ await motionDelay(highlightMs);
4620
+ setNativeValue(el, option.value);
4621
+ el.dispatchEvent(new Event("input", { bubbles: true }));
4622
+ el.dispatchEvent(new Event("change", { bubbles: true }));
4623
+ el.style.outline = previousOutline;
4624
+ el.style.outlineOffset = previousOffset;
4625
+ }
4626
+ async function toggleControl(el, checked, options = {}) {
4627
+ const flashMs = options.flashMs ?? 200;
4628
+ const previousShadow = el.style.boxShadow;
4629
+ el.style.boxShadow = RING;
4630
+ await motionDelay(flashMs);
4631
+ setNativeChecked(el, checked);
4632
+ el.dispatchEvent(new Event("input", { bubbles: true }));
4633
+ el.dispatchEvent(new Event("change", { bubbles: true }));
4634
+ el.style.boxShadow = previousShadow;
1105
4635
  }
1106
4636
 
1107
- // src/dom_driver.ts
4637
+ // src/dom/dom_driver.ts
1108
4638
  async function fillField(el, value, options = {}) {
1109
4639
  scrollIntoCenterView(el);
1110
4640
  await focusWithFlash(el, { flashMs: options.flashMs ?? 0 });
@@ -1114,18 +4644,30 @@ async function clickElement(el, options = {}) {
1114
4644
  scrollIntoCenterView(el);
1115
4645
  await highlightThenClick(el, options);
1116
4646
  }
4647
+ async function pressButton(el, options = {}) {
4648
+ scrollIntoCenterView(el);
4649
+ await pressThenClick(el, options);
4650
+ }
4651
+ async function selectControl(el, value, options = {}) {
4652
+ scrollIntoCenterView(el);
4653
+ await selectOption(el, value, options);
4654
+ }
4655
+ async function toggleCheckbox(el, checked, options = {}) {
4656
+ scrollIntoCenterView(el);
4657
+ await toggleControl(el, checked, options);
4658
+ }
1117
4659
  function setControlValue(el, value) {
1118
4660
  if (el instanceof HTMLInputElement && el.type === "checkbox") {
1119
- el.checked = Boolean(value);
4661
+ setNativeChecked(el, Boolean(value));
1120
4662
  } else {
1121
- el.value = String(value);
4663
+ setNativeValue(el, String(value));
1122
4664
  }
1123
4665
  el.dispatchEvent(new Event("input", { bubbles: true }));
1124
4666
  el.dispatchEvent(new Event("change", { bubbles: true }));
1125
4667
  }
1126
4668
 
1127
4669
  // src/version.ts
1128
- var VERSION = "0.1.1";
4670
+ var VERSION = "0.2.1";
1129
4671
  export {
1130
4672
  AgUiChat,
1131
4673
  AgUiClient,
@@ -1135,11 +4677,15 @@ export {
1135
4677
  MESSAGE_ROLE,
1136
4678
  SUBMIT_EVENT,
1137
4679
  SessionStorageStore,
4680
+ TOGGLE_EVENT,
1138
4681
  TOOL_CALL_STATUS,
4682
+ TOOL_DISPLAY,
1139
4683
  ToolCallCard,
1140
4684
  VERSION,
4685
+ X_CONFIRM_KEY,
1141
4686
  X_DESTRUCTIVE_KEY,
1142
4687
  X_NAVIGATES_KEY,
4688
+ X_SUMMARY_KEY,
1143
4689
  clickElement,
1144
4690
  createHttpAgent,
1145
4691
  createPageMapContext,
@@ -1151,9 +4697,24 @@ export {
1151
4697
  highlightThenClick,
1152
4698
  isDestructive,
1153
4699
  isNavigates,
4700
+ prefersReducedMotion,
4701
+ pressButton,
4702
+ pressThenClick,
4703
+ renderMarkdown,
1154
4704
  requestConfirmation,
1155
4705
  scrollIntoCenterView,
4706
+ selectControl,
4707
+ selectOption,
1156
4708
  setControlValue,
4709
+ setNativeChecked,
4710
+ setNativeValue,
4711
+ toggleCheckbox,
4712
+ toggleControl,
1157
4713
  typeInto
1158
4714
  };
4715
+ /*! Bundled license information:
4716
+
4717
+ dompurify/dist/purify.es.mjs:
4718
+ (*! @license DOMPurify 3.4.7 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.7/LICENSE *)
4719
+ */
1159
4720
  //# sourceMappingURL=index.js.map