@runtypelabs/persona 4.8.0 → 4.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +14 -1
  2. package/dist/animations/glyph-cycle.d.cts +1 -1
  3. package/dist/animations/glyph-cycle.d.ts +1 -1
  4. package/dist/animations/{types-BsZtXPKK.d.cts → types-4ROVJ1gA.d.cts} +42 -0
  5. package/dist/animations/{types-BsZtXPKK.d.ts → types-4ROVJ1gA.d.ts} +42 -0
  6. package/dist/animations/wipe.d.cts +1 -1
  7. package/dist/animations/wipe.d.ts +1 -1
  8. package/dist/chunk-IO5VVUKP.js +3 -0
  9. package/dist/chunk-IPVK3KOM.js +1 -0
  10. package/dist/chunk-UPO4GUFC.js +1 -0
  11. package/dist/codegen.cjs +6 -6
  12. package/dist/codegen.js +8 -8
  13. package/dist/context-mentions-7S5KVUTG.js +169 -0
  14. package/dist/context-mentions-inline-TTCN7ZM2.js +4 -0
  15. package/dist/context-mentions-inline.cjs +4 -0
  16. package/dist/context-mentions-inline.d.cts +203 -0
  17. package/dist/context-mentions-inline.d.ts +203 -0
  18. package/dist/context-mentions-inline.js +4 -0
  19. package/dist/context-mentions.cjs +295 -0
  20. package/dist/context-mentions.d.cts +7025 -0
  21. package/dist/context-mentions.d.ts +7025 -0
  22. package/dist/context-mentions.js +295 -0
  23. package/dist/index.cjs +72 -64
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +634 -3
  26. package/dist/index.d.ts +634 -3
  27. package/dist/index.global.js +59 -51
  28. package/dist/index.global.js.map +1 -1
  29. package/dist/index.js +64 -56
  30. package/dist/index.js.map +1 -1
  31. package/dist/launcher.global.js +2 -2
  32. package/dist/launcher.global.js.map +1 -1
  33. package/dist/plugin-kit.cjs +1 -1
  34. package/dist/plugin-kit.d.cts +17 -0
  35. package/dist/plugin-kit.d.ts +17 -0
  36. package/dist/plugin-kit.js +1 -1
  37. package/dist/smart-dom-reader.cjs +17 -16
  38. package/dist/smart-dom-reader.d.cts +507 -1
  39. package/dist/smart-dom-reader.d.ts +507 -1
  40. package/dist/smart-dom-reader.js +17 -16
  41. package/dist/theme-editor-preview.cjs +236 -57
  42. package/dist/theme-editor-preview.d.cts +485 -1
  43. package/dist/theme-editor-preview.d.ts +485 -1
  44. package/dist/theme-editor-preview.js +53 -47
  45. package/dist/theme-editor.cjs +7 -7
  46. package/dist/theme-editor.d.cts +473 -0
  47. package/dist/theme-editor.d.ts +473 -0
  48. package/dist/theme-editor.js +5 -5
  49. package/dist/theme-reference.cjs +1 -1
  50. package/dist/theme-reference.d.cts +2 -0
  51. package/dist/theme-reference.d.ts +2 -0
  52. package/dist/widget.css +1 -1
  53. package/package.json +15 -3
  54. package/src/client.test.ts +69 -0
  55. package/src/client.ts +65 -51
  56. package/src/components/artifact-pane.test.ts +47 -0
  57. package/src/components/artifact-pane.ts +25 -2
  58. package/src/components/composer-parts.ts +3 -12
  59. package/src/components/context-mention-button.test.ts +70 -0
  60. package/src/components/context-mention-button.ts +82 -0
  61. package/src/components/context-mention-chip.ts +134 -0
  62. package/src/components/context-mention-menu.test.ts +508 -0
  63. package/src/components/context-mention-menu.ts +0 -0
  64. package/src/components/message-bubble.test.ts +175 -0
  65. package/src/components/message-bubble.ts +177 -19
  66. package/src/components/panel.ts +7 -10
  67. package/src/context-mentions-bundle.test.ts +163 -0
  68. package/src/context-mentions-entry.ts +185 -0
  69. package/src/context-mentions-inline-entry.test.ts +136 -0
  70. package/src/context-mentions-inline-entry.ts +226 -0
  71. package/src/context-mentions-inline-loader.test.ts +30 -0
  72. package/src/context-mentions-inline-loader.ts +36 -0
  73. package/src/context-mentions-inline.ts +15 -0
  74. package/src/context-mentions-loader.ts +32 -0
  75. package/src/context-mentions.ts +16 -0
  76. package/src/index-core.ts +27 -0
  77. package/src/index-global.ts +51 -0
  78. package/src/markdown-parsers-loader.ts +35 -44
  79. package/src/plugin-kit.test.ts +40 -0
  80. package/src/plugin-kit.ts +39 -5
  81. package/src/runtime/init-update-reset.test.ts +81 -0
  82. package/src/runtime/init.test.ts +62 -0
  83. package/src/runtime/init.ts +7 -14
  84. package/src/session.mentions.test.ts +175 -0
  85. package/src/session.test.ts +52 -4
  86. package/src/session.ts +121 -5
  87. package/src/smart-dom-reader.test.ts +129 -2
  88. package/src/smart-dom-reader.ts +127 -1
  89. package/src/styles/context-mention-menu-css.ts +176 -0
  90. package/src/styles/widget.css +243 -126
  91. package/src/theme-editor/sections.ts +3 -3
  92. package/src/types/theme.ts +2 -0
  93. package/src/types.ts +542 -0
  94. package/src/ui.artifact-pane-gating.test.ts +11 -1
  95. package/src/ui.attachments-drop.test.ts +90 -0
  96. package/src/ui.header-update-stability.test.ts +149 -0
  97. package/src/ui.launcher-update-merge.test.ts +83 -0
  98. package/src/ui.mention-submit.test.ts +235 -0
  99. package/src/ui.send-button-stream-update.test.ts +69 -0
  100. package/src/ui.ts +379 -84
  101. package/src/utils/chunk-loader.test.ts +97 -0
  102. package/src/utils/chunk-loader.ts +88 -0
  103. package/src/utils/composer-contenteditable.test.ts +507 -0
  104. package/src/utils/composer-contenteditable.ts +626 -0
  105. package/src/utils/composer-document.test.ts +280 -0
  106. package/src/utils/composer-document.ts +293 -0
  107. package/src/utils/composer-history.test.ts +35 -7
  108. package/src/utils/composer-history.ts +30 -20
  109. package/src/utils/composer-input.ts +159 -0
  110. package/src/utils/config-merge.test.ts +131 -0
  111. package/src/utils/config-merge.ts +61 -0
  112. package/src/utils/context-mention-controller.test.ts +1215 -0
  113. package/src/utils/context-mention-controller.ts +1186 -0
  114. package/src/utils/context-mention-manager.test.ts +422 -0
  115. package/src/utils/context-mention-manager.ts +410 -0
  116. package/src/utils/context-mention-orchestrator.test.ts +538 -0
  117. package/src/utils/context-mention-orchestrator.ts +348 -0
  118. package/src/utils/live-region.test.ts +108 -0
  119. package/src/utils/live-region.ts +94 -0
  120. package/src/utils/mention-channels.ts +63 -0
  121. package/src/utils/mention-llm-format.test.ts +91 -0
  122. package/src/utils/mention-llm-format.ts +79 -0
  123. package/src/utils/mention-matcher.test.ts +86 -0
  124. package/src/utils/mention-matcher.ts +221 -0
  125. package/src/utils/mention-token.ts +72 -0
  126. package/src/utils/mention-trigger.test.ts +155 -0
  127. package/src/utils/mention-trigger.ts +156 -0
  128. package/src/utils/theme.test.ts +54 -4
  129. package/src/utils/theme.ts +6 -3
  130. package/src/utils/tokens.ts +27 -11
@@ -692,6 +692,8 @@ interface ComponentTokenSet {
692
692
  margin?: TokenReference<'spacing'>;
693
693
  shadow?: TokenReference<'shadow'>;
694
694
  opacity?: number;
695
+ /** Hover background — used by transparent variants like `button.ghost`. */
696
+ hoverBackground?: TokenReference<'color'>;
695
697
  }
696
698
  interface ButtonTokens extends ComponentTokenSet {
697
699
  primary: ComponentTokenSet;
@@ -2008,6 +2010,446 @@ type AgentWidgetContextProviderContext = {
2008
2010
  config: AgentWidgetConfig;
2009
2011
  };
2010
2012
  type AgentWidgetContextProvider = (context: AgentWidgetContextProviderContext) => Record<string, unknown> | void | Promise<Record<string, unknown> | void>;
2013
+ /** A single selectable item in the mention menu (host-provided). */
2014
+ type AgentWidgetContextMentionItem = {
2015
+ /** Stable key within its source. */
2016
+ id: string;
2017
+ /** Shown in the menu and on the chip (e.g. "App.tsx"). */
2018
+ label: string;
2019
+ /** Subtitle line in the menu. */
2020
+ description?: string;
2021
+ /** Lucide icon name. */
2022
+ iconName?: string;
2023
+ /**
2024
+ * Accent color for this item's inline token (`display: "inline"`), any CSS
2025
+ * color. Sets `--persona-mention-token-accent` on the token, tinting its pill
2026
+ * background + icon/label — the per-item/per-type color knob (Slack/Linear
2027
+ * style). Prefer setting the same color across a source's items for a "color
2028
+ * per type" look, or theme by `[data-mention-source]` in CSS instead. Ignored
2029
+ * in chip mode.
2030
+ */
2031
+ color?: string;
2032
+ /** Group header override; defaults to the source's `label`. */
2033
+ group?: string;
2034
+ /** Optional recency/popularity hint the default matcher boosts on. */
2035
+ recencyScore?: number;
2036
+ /**
2037
+ * SKILLS / SLASH-COMMANDS. When set, this item is a COMMAND (a verb) rather
2038
+ * than a context mention (a noun), so selecting it dispatches a behavior
2039
+ * instead of adding a context chip. Absent for ordinary mentions.
2040
+ *
2041
+ * - `"prompt"`: a prompt macro. `resolve()` returns `insertText` (or
2042
+ * `llmAppend`) which is written into the composer (see `insertMode`);
2043
+ * `submitOnSelect` optionally sends it immediately. No chip.
2044
+ * - `"action"`: a client action. `action()` runs in the browser; no resolve,
2045
+ * no chip, no message sent (e.g. `/clear`, `/theme dark`).
2046
+ * - `"server"`: a server-invoked skill. Routed like a `resolveOn:"submit"`
2047
+ * mention whose `resolve().context` reaches the backend via request
2048
+ * `context.mentions.<sourceId>.<itemId>` (a flow/agent reads it).
2049
+ */
2050
+ command?: "prompt" | "action" | "server";
2051
+ /**
2052
+ * `command:"action"` handler. Receives the parsed `args` (text after the
2053
+ * command name), plus a small `composer` capability + `config`/`messages`.
2054
+ * Short-circuits the mention flow (no chip, no send). Ignored otherwise.
2055
+ */
2056
+ action?: (ctx: AgentWidgetContextMentionCommandContext) => void | Promise<void>;
2057
+ /**
2058
+ * `command:"prompt"` insertion mode. `"replace"` (default) swaps the whole
2059
+ * composer value for the resolved text; `"insert-at-caret"` replaces only the
2060
+ * `/token` span, keeping surrounding prose. Ignored otherwise.
2061
+ */
2062
+ insertMode?: "replace" | "insert-at-caret";
2063
+ /**
2064
+ * When true, a `command:"prompt"` submits the composer immediately after
2065
+ * inserting its text (a one-shot macro). Ignored for other kinds.
2066
+ */
2067
+ submitOnSelect?: boolean;
2068
+ /**
2069
+ * COMMANDS only. Ghost hint for a free-text argument (e.g. "order id" →
2070
+ * `/lookup ‹order id›` in the menu). Its presence switches the command to
2071
+ * INLINE COMPLETION (Slack-style): selecting it fills `/name ` into the
2072
+ * composer for inline arg entry instead of dispatching on select, and the
2073
+ * command is executed at SUBMIT with the typed args. `command:"server"` items
2074
+ * always use inline completion (their chip had no way to add an argument);
2075
+ * for `"prompt"`/`"action"` items this is opt-in. Ignored for non-commands.
2076
+ */
2077
+ commandArgsPlaceholder?: string;
2078
+ };
2079
+ /**
2080
+ * Capability object handed to a `command:"action"` handler. The widget exposes
2081
+ * only composer-local operations; broader actions (clear the transcript, change
2082
+ * theme) are wired by the host via closures over its own controller.
2083
+ */
2084
+ type AgentWidgetContextMentionComposerCapability = {
2085
+ /** Current composer text. */
2086
+ getValue: () => string;
2087
+ /** Replace composer text (fires `input`, moves caret to end, refocuses). */
2088
+ setValue: (value: string) => void;
2089
+ /** Submit the composer (same path as pressing send). */
2090
+ submit: () => void;
2091
+ };
2092
+ /** Context passed to a `command:"action"` handler. */
2093
+ type AgentWidgetContextMentionCommandContext = {
2094
+ /** Text typed after the command name (e.g. `staging` for `/deploy staging`). */
2095
+ args: string;
2096
+ config: AgentWidgetConfig;
2097
+ messages: AgentWidgetMessage[];
2098
+ composer: AgentWidgetContextMentionComposerCapability;
2099
+ };
2100
+ /** Reference stored on a sent message for transcript fidelity + chip rendering. */
2101
+ type AgentWidgetContextMentionRef = {
2102
+ sourceId: string;
2103
+ itemId: string;
2104
+ label: string;
2105
+ iconName?: string;
2106
+ /** Accent color for the inline token (see `AgentWidgetContextMentionItem.color`). */
2107
+ color?: string;
2108
+ };
2109
+ /**
2110
+ * One ordered segment of a sent message's prose, for inline mention rendering
2111
+ * (`contextMentions.display: "inline"`). Text runs and atomic mention tokens
2112
+ * interleave in document order so the sent bubble re-renders `@tokens` in place
2113
+ * and composer history can round-trip them. Display/transcript concern only —
2114
+ * the model still sees resolved bodies via `llmContent`/`contentParts`.
2115
+ */
2116
+ type AgentWidgetContentSegment = {
2117
+ kind: "text";
2118
+ text: string;
2119
+ } | {
2120
+ kind: "mention";
2121
+ ref: AgentWidgetContextMentionRef;
2122
+ };
2123
+ /**
2124
+ * The payload a source returns from `resolve()` for one selected item.
2125
+ * Lead with `llmAppend` — it is the only channel guaranteed to reach the model
2126
+ * with no backend changes.
2127
+ */
2128
+ type AgentWidgetContextMentionPayload = {
2129
+ /**
2130
+ * PRIMARY, model-visible channel. Appended to this user message's LLM content
2131
+ * so the model actually sees the context with no backend changes.
2132
+ */
2133
+ llmAppend?: string;
2134
+ /**
2135
+ * `command:"prompt"` macros only. Text written into the COMPOSER on select
2136
+ * (see `AgentWidgetContextMentionItem.insertMode`) — distinct from the hidden
2137
+ * `llmAppend` context channel. Falls back to `llmAppend` when omitted.
2138
+ */
2139
+ insertText?: string;
2140
+ /** Extra content parts (e.g. file text / image) via the multi-modal path. */
2141
+ contentParts?: ContentPart[];
2142
+ /**
2143
+ * OPT-IN structured channel. Merged into request `context` under
2144
+ * `mentions.<sourceId>.<itemId>` for flows/agents that read it. NOTE: ambient
2145
+ * `context` is NOT guaranteed to reach the model — use `llmAppend` if you need
2146
+ * the model to see it.
2147
+ */
2148
+ context?: Record<string, unknown>;
2149
+ };
2150
+ /**
2151
+ * One resolved mention, handed to `contextMentions.llmFormat` to build the
2152
+ * model-visible block. `text` is the source's `llmAppend`; `ref`/`item` carry
2153
+ * the selection identity/metadata for a custom formatter (e.g. a source-specific
2154
+ * wrapper or a path from `item`).
2155
+ */
2156
+ type AgentWidgetMentionLlmEntry = {
2157
+ /** The mention's display label (from `ref.label`). */
2158
+ label: string;
2159
+ /** The resolved model-visible body (the source's `llmAppend`). */
2160
+ text: string;
2161
+ ref: AgentWidgetContextMentionRef;
2162
+ item: AgentWidgetContextMentionItem;
2163
+ };
2164
+ type AgentWidgetContextMentionSearchContext = {
2165
+ messages: AgentWidgetMessage[];
2166
+ config: AgentWidgetConfig;
2167
+ /** Aborts when the next keystroke supersedes this in-flight search. */
2168
+ signal: AbortSignal;
2169
+ };
2170
+ type AgentWidgetContextMentionResolveContext = AgentWidgetContextMentionSearchContext & {
2171
+ /** Plain-text composer value at resolve time. */
2172
+ composerText: string;
2173
+ /**
2174
+ * For `command` items: the text typed after the command name (e.g.
2175
+ * `"123"` for `/lookup 123`). Empty string for ordinary mentions.
2176
+ */
2177
+ args: string;
2178
+ };
2179
+ type AgentWidgetContextMentionSource = {
2180
+ id: string;
2181
+ /** Group header shown in the menu. */
2182
+ label: string;
2183
+ /**
2184
+ * Filter items for the current `@query` (empty query → recent/popular).
2185
+ * Implement server-side search for large/remote sets, or return all items and
2186
+ * let the widget rank them with `defaultMentionFilter`
2187
+ * (see `createStaticMentionSource` for the common case).
2188
+ */
2189
+ search: (query: string, ctx: AgentWidgetContextMentionSearchContext) => AgentWidgetContextMentionItem[] | Promise<AgentWidgetContextMentionItem[]>;
2190
+ /**
2191
+ * Fetch the payload for dispatch. Called once when the user SELECTS the item
2192
+ * (eagerly, cached on the chip, abortable on removal) unless `resolveOn` is
2193
+ * `"submit"`. A throw/abort drops the mention via `onMentionResolveError`.
2194
+ */
2195
+ resolve: (item: AgentWidgetContextMentionItem, ctx: AgentWidgetContextMentionResolveContext) => AgentWidgetContextMentionPayload | Promise<AgentWidgetContextMentionPayload>;
2196
+ /**
2197
+ * When to call `resolve()`:
2198
+ * - `"select"` (default): eager on pick; parallelizes the fetch with the user
2199
+ * finishing their sentence so submit stays instant.
2200
+ * - `"submit"`: defer to send time, for time-sensitive sources (e.g. current
2201
+ * page state that may change between select and send).
2202
+ * @default "select"
2203
+ */
2204
+ resolveOn?: "select" | "submit";
2205
+ /**
2206
+ * COMMAND sources only. Resolve a `/name` (the first token of a command line)
2207
+ * to its menu item, for submit-time inline-command dispatch and the menu's
2208
+ * "typing args now" suppression. `createSlashCommandsSource` sets this; plain
2209
+ * `@`-mention sources leave it undefined.
2210
+ */
2211
+ matchCommand?: (name: string) => AgentWidgetContextMentionItem | undefined;
2212
+ };
2213
+ /** Context passed to the optional `renderMentionMenu` override. */
2214
+ type AgentWidgetContextMentionMenuRenderContext = {
2215
+ /** Current trigger query ("" when freshly opened). */
2216
+ query: string;
2217
+ /** Grouped, ranked, capped results ready to paint. */
2218
+ groups: {
2219
+ source: AgentWidgetContextMentionSource;
2220
+ items: AgentWidgetContextMentionItem[];
2221
+ }[];
2222
+ /** Per-source async state for loading/empty/error rendering, keyed by source id. */
2223
+ status: Record<string, "loading" | "ready" | "empty" | "error">;
2224
+ /** Index into the flat keyboard-traversal order. */
2225
+ activeIndex: number;
2226
+ /** Commit a selection (strips `@query`, adds chip, resolves on select). */
2227
+ select: (item: AgentWidgetContextMentionItem) => void;
2228
+ /** Close the menu, keeping a literal `@`. */
2229
+ close: () => void;
2230
+ };
2231
+ /** Context passed to the optional `renderMentionItem` per-row override. */
2232
+ type AgentWidgetContextMentionItemRenderContext = {
2233
+ /** The item to render. */
2234
+ item: AgentWidgetContextMentionItem;
2235
+ /** The source this item came from (its group). */
2236
+ source: AgentWidgetContextMentionSource;
2237
+ /** Current trigger query, for highlighting matches. */
2238
+ query: string;
2239
+ /** True when this row is the keyboard-highlighted one at render time. */
2240
+ active: boolean;
2241
+ /** Position in the flat keyboard-traversal order. */
2242
+ index: number;
2243
+ };
2244
+ /** Context passed to the optional `renderMentionChip` override. */
2245
+ type AgentWidgetContextMentionChipRenderContext = {
2246
+ ref: AgentWidgetContextMentionRef;
2247
+ /** Resolve-on-select lifecycle for spinner→ready→error UI. */
2248
+ status: "resolving" | "ready" | "error";
2249
+ /**
2250
+ * The resolved payload, once available (select-resolved sources only). Use it
2251
+ * to preview already-fetched content on hover. Undefined while `status` is
2252
+ * `"resolving"`, on `"error"`, and for `resolveOn:"submit"` sources (which
2253
+ * resolve at send time, not while the chip sits in the composer — for those,
2254
+ * `ref.itemId` carries the source key you can re-read on demand, e.g. a CSS
2255
+ * selector for the smart-dom source).
2256
+ */
2257
+ payload?: AgentWidgetContextMentionPayload;
2258
+ /** Remove the chip; aborts any in-flight resolve. */
2259
+ remove: () => void;
2260
+ };
2261
+ /**
2262
+ * Where a trigger char is allowed to open the menu:
2263
+ * - `"anywhere"` (default): after any whitespace or start (the `@` rule).
2264
+ * - `"line-start"`: only when the char before the trigger is a newline or the
2265
+ * start of input — the natural rule for `/` slash-commands.
2266
+ * - `"input-start"`: only at index 0 of the composer.
2267
+ */
2268
+ type AgentWidgetMentionTriggerPosition = "anywhere" | "line-start" | "input-start";
2269
+ /**
2270
+ * A SECOND (or Nth) trigger channel sharing the same menu engine — e.g. `/` for
2271
+ * slash-commands alongside `@` for context. The legacy `trigger`/`sources`
2272
+ * fields form the implicit first channel; `triggers[]` adds more. At any caret
2273
+ * at most one channel is active, so all channels drive one menu/controller.
2274
+ */
2275
+ type AgentWidgetMentionTriggerChannel = {
2276
+ /** Trigger character (e.g. "/"). */
2277
+ trigger: string;
2278
+ /** Sources for this channel (searched only when this trigger is active). */
2279
+ sources: AgentWidgetContextMentionSource[];
2280
+ /** Where the trigger may open. @default "anywhere" */
2281
+ triggerPosition?: AgentWidgetMentionTriggerPosition;
2282
+ /**
2283
+ * Let the query span spaces so a command can take ARGS (`/deploy staging`).
2284
+ * A newline still ends it. Pair with `triggerPosition: "line-start"` for
2285
+ * slash-commands. @default false
2286
+ */
2287
+ allowSpaces?: boolean;
2288
+ /** Show a composer affordance button for this channel. @default false */
2289
+ showButton?: boolean;
2290
+ /** Icon for this channel's affordance button. */
2291
+ buttonIconName?: string;
2292
+ /** Tooltip / aria-label for this channel's affordance button. */
2293
+ buttonTooltipText?: string;
2294
+ /** Placeholder for this channel's picker search field. */
2295
+ searchPlaceholder?: string;
2296
+ };
2297
+ type AgentWidgetContextMentionConfig = {
2298
+ /** @default false */
2299
+ enabled?: boolean;
2300
+ /**
2301
+ * Show the visible composer affordance button (the discoverable entry point).
2302
+ * Strongly recommended; the bare `@` trigger alone is hard to discover for
2303
+ * non-technical users. @default true
2304
+ */
2305
+ showButton?: boolean;
2306
+ /**
2307
+ * Icon for the affordance button (any registered Lucide name). Defaults to a
2308
+ * "+" signifier — the consumer-recognized "add context" affordance — rather
2309
+ * than an "@" glyph, which reads as power-user. Use `"at-sign"` on a
2310
+ * developer/power-user surface. @default "plus"
2311
+ */
2312
+ buttonIconName?: string;
2313
+ /** Tooltip / aria-label for the affordance button. @default "Add context" */
2314
+ buttonTooltipText?: string;
2315
+ /**
2316
+ * Placeholder for the picker's search field, shown when the menu is opened
2317
+ * from the affordance button (a Cursor/Copilot-style picker that inserts no
2318
+ * trigger character). The typed-trigger path keeps its query in the textarea
2319
+ * and never shows this field. @default "Search context…"
2320
+ */
2321
+ searchPlaceholder?: string;
2322
+ /** Trigger character. @default "@" */
2323
+ trigger?: string;
2324
+ /**
2325
+ * Where the primary `trigger` may open the menu. @default "anywhere"
2326
+ */
2327
+ triggerPosition?: AgentWidgetMentionTriggerPosition;
2328
+ /**
2329
+ * ADDITIONAL trigger channels sharing this engine — e.g. a `/` slash-command
2330
+ * channel next to `@` context. Each channel has its own trigger char,
2331
+ * sources, and position rule. See `AgentWidgetMentionTriggerChannel`.
2332
+ */
2333
+ triggers?: AgentWidgetMentionTriggerChannel[];
2334
+ /** Max mentions per message. @default 8 */
2335
+ maxMentions?: number;
2336
+ /** Max items shown per source group before "keep typing to narrow". @default 6 */
2337
+ maxItemsPerGroup?: number;
2338
+ /**
2339
+ * Debounce for ASYNC source search only (ms). Synchronous sources and the
2340
+ * menu's first paint are never debounced. @default 150
2341
+ */
2342
+ searchDebounceMs?: number;
2343
+ /** Registered mention sources (search + resolve). */
2344
+ sources: AgentWidgetContextMentionSource[];
2345
+ /** Chip icon fallback when a source/item omits one. @default "at-sign" */
2346
+ chipIconName?: string;
2347
+ /**
2348
+ * How each resolved mention's `llmAppend` text is wrapped into a delimited
2349
+ * block before it is prepended to the model-visible message content. Blocks
2350
+ * are joined with a blank line and the typed prose follows last.
2351
+ *
2352
+ * - `"fenced"` (default): a fenced code block with the label in the info
2353
+ * string, e.g. selecting `App.tsx` emits:
2354
+ * ```text
2355
+ * ```App.tsx
2356
+ * <file body>
2357
+ * ```
2358
+ * ```
2359
+ * The fence auto-escalates (four+ backticks) when the body itself contains a
2360
+ * fence, so a body can never terminate its own wrapper.
2361
+ * - `"document"`: Anthropic's long-context document shape, e.g.:
2362
+ * ```text
2363
+ * <document index="1">
2364
+ * <source>App.tsx</source>
2365
+ * <document_content>
2366
+ * <file body>
2367
+ * </document_content>
2368
+ * </document>
2369
+ * ```
2370
+ * Prefer this for prose/document-shaped sources per Anthropic's long-context
2371
+ * guidance (indexed `<document>` blocks improve grounding and citation). A
2372
+ * body containing the literal `</document_content>` closing tag falls back to
2373
+ * the fenced block for that entry to avoid a broken XML boundary.
2374
+ * - function form: fully owns the block for one mention — its return string is
2375
+ * used verbatim (no extra wrapping), joined with the other blocks. `index` is
2376
+ * the 0-based position among the message's mention blocks.
2377
+ *
2378
+ * @default "fenced"
2379
+ */
2380
+ llmFormat?: "fenced" | "document" | ((entry: AgentWidgetMentionLlmEntry, index: number) => string);
2381
+ /**
2382
+ * How `@` selections appear in the composer and sent user bubble.
2383
+ *
2384
+ * - `"chip"` (default): strip `@query` on select; show a compact pill in the
2385
+ * composer context row; `content` is prose-only.
2386
+ * - `"inline"`: insert an atomic styled token in the sentence (Slack/Linear/
2387
+ * Cursor style), backed by a contenteditable composer. Slash-command channels
2388
+ * (`triggers[]` with `/`) stay inline-text regardless — they already use the
2389
+ * `/name args` model, not chips. `renderMentionChip` is ignored for `@`
2390
+ * mentions in this mode.
2391
+ *
2392
+ * The resolved-context channel (`llmContent`/`contentParts`) is unchanged
2393
+ * across both modes — inline tokens are a display concern.
2394
+ *
2395
+ * @default "chip"
2396
+ */
2397
+ display?: "chip" | "inline";
2398
+ /**
2399
+ * Fired when a pick is rejected: it duplicates an existing chip in chip display
2400
+ * (`"duplicate"` — inline display allows the same item as multiple tokens, so it
2401
+ * never rejects for this reason), hits `maxMentions` (`"limit"`), or (inline
2402
+ * display) the composer text changed between parse and commit so the token could
2403
+ * not be inserted (`"stale"`).
2404
+ */
2405
+ onMentionRejected?: (item: AgentWidgetContextMentionItem, reason: "duplicate" | "limit" | "stale") => void;
2406
+ /**
2407
+ * A `resolve()` that throws/aborts: the mention is dropped and the message
2408
+ * still sends. Surface a non-blocking notice here if desired.
2409
+ */
2410
+ onMentionResolveError?: (item: AgentWidgetContextMentionItem, error: unknown) => void;
2411
+ /**
2412
+ * MID-LEVEL render override for the autocomplete menu. The widget still owns
2413
+ * trigger detection, search, debounce/abort, keyboard nav, and positioning;
2414
+ * you only supply the menu markup and drive selection through `ctx`. Omit to
2415
+ * use the built-in grouped menu. @default built-in
2416
+ */
2417
+ renderMentionMenu?: (ctx: AgentWidgetContextMentionMenuRenderContext) => HTMLElement;
2418
+ /**
2419
+ * NARROW render override for a single result row's INNER content, keeping the
2420
+ * built-in menu chrome (group headers, loading/empty/error, keyboard nav, the
2421
+ * "keep typing" hint). The widget keeps the `role="option"` wrapper and its
2422
+ * click/hover wiring; you return only the row's contents. For full menu
2423
+ * control use `renderMentionMenu` instead. Highlight is CSS-driven via the
2424
+ * wrapper's `[data-active]` attribute, so this is called once per render, not
2425
+ * on every arrow key. Ignored when `renderMentionMenu` is set. @default built-in
2426
+ */
2427
+ renderMentionItem?: (ctx: AgentWidgetContextMentionItemRenderContext) => HTMLElement;
2428
+ /**
2429
+ * MID-LEVEL render override for a single context chip. Return your own pill
2430
+ * (must include an accessible remove control wired to `ctx.remove`); reflect
2431
+ * `ctx.status` for resolve-on-select. Omit to use the built-in compact pill.
2432
+ * @default built-in
2433
+ */
2434
+ renderMentionChip?: (ctx: AgentWidgetContextMentionChipRenderContext) => HTMLElement;
2435
+ /**
2436
+ * INLINE display only (`display: "inline"`). Render override for a single inline
2437
+ * mention TOKEN — the atomic styled node that sits in the sentence, in both the
2438
+ * contenteditable composer and the read-only sent bubble. Return your own
2439
+ * element (e.g. a fully custom colored pill); the composer marks it
2440
+ * `contenteditable="false"` and stamps `data-mention-id` so it stays atomic.
2441
+ * Omit to use the built-in pill (icon + `@label`, tinted by
2442
+ * `--persona-mention-token-accent` / `ref.color`, themeable per source via the
2443
+ * `[data-mention-source]` attribute). Ignored in chip mode.
2444
+ * @default built-in
2445
+ */
2446
+ renderMentionToken?: (ctx: AgentWidgetContextMentionTokenRenderContext) => HTMLElement;
2447
+ };
2448
+ /** Render context for `renderMentionToken`. `readonly` is true in the sent bubble. */
2449
+ type AgentWidgetContextMentionTokenRenderContext = {
2450
+ ref: AgentWidgetContextMentionRef;
2451
+ readonly: boolean;
2452
+ };
2011
2453
  type AgentWidgetRequestPayloadMessage = {
2012
2454
  role: AgentWidgetMessageRole;
2013
2455
  content: MessageContent;
@@ -5927,6 +6369,18 @@ type AgentWidgetConfig = {
5927
6369
  }) => string;
5928
6370
  plugins?: AgentWidgetPlugin[];
5929
6371
  contextProviders?: AgentWidgetContextProvider[];
6372
+ /**
6373
+ * Context mentions: let users explicitly pull external context into a turn by
6374
+ * typing `@` or clicking a visible composer button, both opening one shared
6375
+ * searchable menu of host-provided sources. Selecting a mention adds a
6376
+ * removable pill chip; resolved content reaches the model via `llmAppend`
6377
+ * (default) or the opt-in structured `context` channel.
6378
+ *
6379
+ * Disabled by default. When enabled, the mention runtime is lazy-loaded from a
6380
+ * sibling chunk on first use, so sites that leave it off pay no bundle cost.
6381
+ * See `docs/context-mentions-plan.md`.
6382
+ */
6383
+ contextMentions?: AgentWidgetContextMentionConfig;
5930
6384
  requestMiddleware?: AgentWidgetRequestMiddleware;
5931
6385
  actionParsers?: AgentWidgetActionParser[];
5932
6386
  actionHandlers?: AgentWidgetActionHandler[];
@@ -6469,6 +6923,25 @@ type AgentWidgetMessage = {
6469
6923
  * The `content` field contains the text-only representation for display.
6470
6924
  */
6471
6925
  contentParts?: ContentPart[];
6926
+ /**
6927
+ * Context mentions attached to this (user) message, for transcript fidelity +
6928
+ * chip rendering in the sent bubble. Refs only — the resolved payloads are
6929
+ * merged into `llmContent`/`contentParts` (model-visible) at send time.
6930
+ */
6931
+ contextMentions?: AgentWidgetContextMentionRef[];
6932
+ /**
6933
+ * Ordered prose + mention blocks for inline-mode rendering and composer history
6934
+ * recall (`contextMentions.display: "inline"`). Present only on inline-mode user
6935
+ * messages; when omitted the sent bubble falls back to the chip row derived from
6936
+ * `contextMentions`. Display/transcript concern only — not the model channel.
6937
+ */
6938
+ contentSegments?: AgentWidgetContentSegment[];
6939
+ /**
6940
+ * Resolved opt-in structured mention context for this (user) message, merged
6941
+ * into the request `context` under `mentions.<sourceId>.<itemId>` by the
6942
+ * client. Internal: set at send time from each source's `resolve().context`.
6943
+ */
6944
+ mentionContext?: Record<string, unknown>;
6472
6945
  streaming?: boolean;
6473
6946
  variant?: AgentWidgetMessageVariant;
6474
6947
  sequence?: number;
@@ -6648,5 +7121,38 @@ interface SmartDomReaderProviderOptions extends SmartDomContextOptions {
6648
7121
  * `payload.context` on every agent request.
6649
7122
  */
6650
7123
  declare function createSmartDomReaderContextProvider(opts?: SmartDomReaderProviderOptions): AgentWidgetContextProvider;
7124
+ /** Options for {@link createSmartDomMentionSource}. */
7125
+ interface SmartDomMentionSourceOptions extends SmartDomContextOptions {
7126
+ /** Source id. Default: "page". */
7127
+ id?: string;
7128
+ /** Group header shown in the menu. Default: "Page". */
7129
+ label?: string;
7130
+ /**
7131
+ * Reshape each surfaced element into a mention item. Receives the raw
7132
+ * {@link EnrichedPageElement} and the default-mapped item, so you can tweak
7133
+ * one field (`{ ...defaultItem, iconName: "star" }`) or build from scratch.
7134
+ * The returned item's `id` MUST stay a selector `resolve()` can read at submit
7135
+ * (default: `el.selector`) unless you also override resolution. @default built-in mapping
7136
+ */
7137
+ mapItem?: (el: EnrichedPageElement, defaultItem: AgentWidgetContextMentionItem) => AgentWidgetContextMentionItem;
7138
+ }
7139
+ /**
7140
+ * First-class **supported** mention source backed by smart-dom-reader: surfaces
7141
+ * visible page elements (Shadow-DOM-piercing) as mentionable items, resolving a
7142
+ * fresh snapshot of the chosen element's text at SUBMIT (`resolveOn: "submit"`),
7143
+ * since the page is time-sensitive. The element list is snapshotted when the
7144
+ * menu opens (empty query) and filtered client-side with `defaultMentionFilter`
7145
+ * as the user types.
7146
+ *
7147
+ * @example
7148
+ * ```ts
7149
+ * import { createSmartDomMentionSource } from "@runtypelabs/persona/smart-dom-reader";
7150
+ *
7151
+ * initAgentWidget({
7152
+ * contextMentions: { enabled: true, sources: [createSmartDomMentionSource()] },
7153
+ * });
7154
+ * ```
7155
+ */
7156
+ declare function createSmartDomMentionSource(opts?: SmartDomMentionSourceOptions): AgentWidgetContextMentionSource;
6651
7157
 
6652
- export { type SmartDomAdapterOptions, type SmartDomContextOptions, type SmartDomReaderProviderOptions, collectSmartDomContext, createSmartDomReaderContextProvider, smartDomResultToEnriched };
7158
+ export { type EnrichedPageElement, type SmartDomAdapterOptions, type SmartDomContextOptions, type SmartDomMentionSourceOptions, type SmartDomReaderProviderOptions, collectSmartDomContext, createSmartDomMentionSource, createSmartDomReaderContextProvider, smartDomResultToEnriched };