@runtypelabs/persona 3.17.0 → 3.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +142 -0
- package/dist/animations/glyph-cycle.d.cts +1 -1
- package/dist/animations/glyph-cycle.d.ts +1 -1
- package/dist/animations/{types-HPZY7oAI.d.cts → types-cwY5HaFD.d.cts} +25 -0
- package/dist/animations/{types-HPZY7oAI.d.ts → types-cwY5HaFD.d.ts} +25 -0
- package/dist/animations/wipe.d.cts +1 -1
- package/dist/animations/wipe.d.ts +1 -1
- package/dist/index.cjs +47 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +300 -1
- package/dist/index.d.ts +300 -1
- package/dist/index.global.js +75 -75
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +47 -47
- package/dist/index.js.map +1 -1
- package/dist/theme-editor.cjs +1432 -159
- package/dist/theme-editor.d.cts +218 -0
- package/dist/theme-editor.d.ts +218 -0
- package/dist/theme-editor.js +1432 -159
- package/dist/theme-reference.cjs +1 -1
- package/dist/theme-reference.d.cts +14 -0
- package/dist/theme-reference.d.ts +14 -0
- package/dist/widget.css +432 -0
- package/package.json +1 -1
- package/src/client.test.ts +134 -0
- package/src/client.ts +71 -0
- package/src/components/ask-user-question-bubble.test.ts +583 -0
- package/src/components/ask-user-question-bubble.ts +924 -0
- package/src/components/messages.ts +33 -1
- package/src/components/panel.ts +41 -4
- package/src/defaults.ts +21 -0
- package/src/index.ts +16 -1
- package/src/plugins/types.ts +57 -0
- package/src/session.test.ts +183 -0
- package/src/session.ts +242 -3
- package/src/styles/widget.css +432 -0
- package/src/types/theme.ts +15 -0
- package/src/types.ts +150 -0
- package/src/ui.ask-user-question-plugin.test.ts +649 -0
- package/src/ui.ts +631 -5
- package/src/utils/storage.ts +10 -2
- package/src/utils/theme.test.ts +36 -0
- package/src/utils/tokens.ts +23 -0
package/dist/theme-editor.d.cts
CHANGED
|
@@ -217,6 +217,18 @@ interface MessageTokens {
|
|
|
217
217
|
/** Border color between messages in the thread. */
|
|
218
218
|
border?: TokenReference<'color'>;
|
|
219
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Welcome / intro card rendered above the message list when no messages exist.
|
|
222
|
+
* Set `copy.showWelcomeCard: false` to hide it; use `layout.slots["body-top"]`
|
|
223
|
+
* to replace it wholesale.
|
|
224
|
+
*/
|
|
225
|
+
interface IntroCardTokens extends ComponentTokenSet {
|
|
226
|
+
background?: TokenReference<'color'>;
|
|
227
|
+
borderRadius?: TokenReference<'radius'>;
|
|
228
|
+
padding?: TokenReference<'spacing'>;
|
|
229
|
+
/** Box-shadow on the intro card (token ref or raw CSS, e.g. `none`). */
|
|
230
|
+
shadow?: string;
|
|
231
|
+
}
|
|
220
232
|
/** Collapsible widget chrome (tool bubbles, reasoning bubbles, approval bubbles). */
|
|
221
233
|
interface CollapsibleWidgetTokens {
|
|
222
234
|
/** Background for content areas. */
|
|
@@ -414,6 +426,8 @@ interface ComponentTokens {
|
|
|
414
426
|
panel: PanelTokens;
|
|
415
427
|
header: HeaderTokens;
|
|
416
428
|
message: MessageTokens;
|
|
429
|
+
/** Welcome / intro card shown above the message list. */
|
|
430
|
+
introCard?: IntroCardTokens;
|
|
417
431
|
/** Markdown surfaces (chat + artifact pane). */
|
|
418
432
|
markdown?: MarkdownTokens;
|
|
419
433
|
voice: VoiceTokens;
|
|
@@ -558,6 +572,61 @@ interface AgentWidgetPlugin {
|
|
|
558
572
|
defaultRenderer: () => HTMLElement;
|
|
559
573
|
config: AgentWidgetConfig;
|
|
560
574
|
}) => HTMLElement | null;
|
|
575
|
+
/**
|
|
576
|
+
* Custom renderer for `ask_user_question` tool calls.
|
|
577
|
+
*
|
|
578
|
+
* When a plugin returns an `HTMLElement`, it is inserted into the transcript
|
|
579
|
+
* in place of the default (which is no transcript bubble — the built-in
|
|
580
|
+
* renders a sheet over the composer). The built-in composer-overlay sheet
|
|
581
|
+
* is suppressed so the plugin's UI fully owns the interaction.
|
|
582
|
+
*
|
|
583
|
+
* Return `null` to fall through to the built-in overlay sheet.
|
|
584
|
+
*
|
|
585
|
+
* The context gives you a pre-parsed `payload` (may be partial while the
|
|
586
|
+
* tool call is still streaming — check `complete`) and two callbacks:
|
|
587
|
+
* `resolve(answer)` resumes the paused LOCAL tool with the user's answer,
|
|
588
|
+
* and `dismiss()` cancels with the sentinel `"(dismissed)"`.
|
|
589
|
+
*
|
|
590
|
+
* @example
|
|
591
|
+
* ```typescript
|
|
592
|
+
* renderAskUserQuestion: ({ payload, resolve, dismiss }) => {
|
|
593
|
+
* const prompt = payload.questions?.[0];
|
|
594
|
+
* if (!prompt) return null;
|
|
595
|
+
* const root = document.createElement("div");
|
|
596
|
+
* root.textContent = prompt.question ?? "";
|
|
597
|
+
* (prompt.options ?? []).forEach((option) => {
|
|
598
|
+
* const btn = document.createElement("button");
|
|
599
|
+
* btn.textContent = option.label;
|
|
600
|
+
* btn.addEventListener("click", () => resolve(option.label));
|
|
601
|
+
* root.appendChild(btn);
|
|
602
|
+
* });
|
|
603
|
+
* return root;
|
|
604
|
+
* }
|
|
605
|
+
* ```
|
|
606
|
+
*/
|
|
607
|
+
renderAskUserQuestion?: (context: {
|
|
608
|
+
message: AgentWidgetMessage;
|
|
609
|
+
/**
|
|
610
|
+
* Parsed `{ questions: [...] }` payload. May be partial while the tool
|
|
611
|
+
* call is still streaming; see `complete`. `null` when no payload has
|
|
612
|
+
* arrived yet.
|
|
613
|
+
*/
|
|
614
|
+
payload: Partial<AskUserQuestionPayload> | null;
|
|
615
|
+
/** `true` once the tool-call args have fully streamed in. */
|
|
616
|
+
complete: boolean;
|
|
617
|
+
/**
|
|
618
|
+
* Resume the paused LOCAL tool with the user's answer. Posts to the
|
|
619
|
+
* resume endpoint, pipes the SSE stream back into the session, and
|
|
620
|
+
* appends a user-visible answer bubble to the transcript.
|
|
621
|
+
*/
|
|
622
|
+
resolve: (answer: string) => void;
|
|
623
|
+
/**
|
|
624
|
+
* Cancel the question. Resumes with the sentinel `"(dismissed)"` so the
|
|
625
|
+
* server doesn't sit in `waiting_for_local` forever. Idempotent.
|
|
626
|
+
*/
|
|
627
|
+
dismiss: () => void;
|
|
628
|
+
config: AgentWidgetConfig;
|
|
629
|
+
}) => HTMLElement | null;
|
|
561
630
|
/**
|
|
562
631
|
* Custom renderer for approval bubbles
|
|
563
632
|
* Return null to use default renderer
|
|
@@ -778,6 +847,31 @@ type AgentMessageMetadata = {
|
|
|
778
847
|
* or `prompt` step inside the nested flow). Stable key for that step.
|
|
779
848
|
*/
|
|
780
849
|
parentStepId?: string;
|
|
850
|
+
/**
|
|
851
|
+
* Set to `true` on a tool-variant message produced from a `step_await`
|
|
852
|
+
* event (`awaitReason: "local_tool_required"`). Signals to UI code that
|
|
853
|
+
* the tool call is a LOCAL tool and the server is paused waiting for a
|
|
854
|
+
* `POST /v1/dispatch/resume` with the user's answer keyed by tool name.
|
|
855
|
+
*/
|
|
856
|
+
awaitingLocalTool?: boolean;
|
|
857
|
+
/**
|
|
858
|
+
* Set to `true` once the user has picked / typed / dismissed an answer for
|
|
859
|
+
* an `ask_user_question` tool call, so renderers stop re-mounting the
|
|
860
|
+
* answer-pill sheet for this tool call on subsequent render passes.
|
|
861
|
+
*/
|
|
862
|
+
askUserQuestionAnswered?: boolean;
|
|
863
|
+
/**
|
|
864
|
+
* In-progress answers for a multi-question `ask_user_question` payload,
|
|
865
|
+
* keyed by question text. Persisted across refresh so the user lands back
|
|
866
|
+
* where they were if the page reloads mid-flow. Cleared once
|
|
867
|
+
* `askUserQuestionAnswered` flips to `true`.
|
|
868
|
+
*/
|
|
869
|
+
askUserQuestionAnswers?: Record<string, string | string[]>;
|
|
870
|
+
/**
|
|
871
|
+
* Current page index for a multi-question `ask_user_question` payload's
|
|
872
|
+
* paginated stepper. Persists alongside `askUserQuestionAnswers`.
|
|
873
|
+
*/
|
|
874
|
+
askUserQuestionIndex?: number;
|
|
781
875
|
};
|
|
782
876
|
type AgentWidgetRequestMiddlewareContext = {
|
|
783
877
|
payload: AgentWidgetRequestPayload;
|
|
@@ -825,6 +919,8 @@ type AgentWidgetActionHandler = (action: AgentWidgetParsedAction, context: Agent
|
|
|
825
919
|
type AgentWidgetStoredState = {
|
|
826
920
|
messages?: AgentWidgetMessage[];
|
|
827
921
|
metadata?: Record<string, unknown>;
|
|
922
|
+
artifacts?: PersonaArtifactRecord[];
|
|
923
|
+
selectedArtifactId?: string | null;
|
|
828
924
|
};
|
|
829
925
|
interface AgentWidgetStorageAdapter {
|
|
830
926
|
load?: () => AgentWidgetStoredState | null | Promise<AgentWidgetStoredState | null>;
|
|
@@ -1382,6 +1478,113 @@ type AgentWidgetFeatureFlags = {
|
|
|
1382
1478
|
artifacts?: AgentWidgetArtifactsFeature;
|
|
1383
1479
|
/** Reveal animation for streaming assistant text. */
|
|
1384
1480
|
streamAnimation?: AgentWidgetStreamAnimationFeature;
|
|
1481
|
+
/**
|
|
1482
|
+
* Built-in interactive answer-pill sheet shown when the assistant invokes
|
|
1483
|
+
* the `ask_user_question` tool. Slides up over the composer with tappable
|
|
1484
|
+
* pills + optional free-text input.
|
|
1485
|
+
*/
|
|
1486
|
+
askUserQuestion?: AgentWidgetAskUserQuestionFeature;
|
|
1487
|
+
};
|
|
1488
|
+
/**
|
|
1489
|
+
* Single selectable option in an `ask_user_question` prompt.
|
|
1490
|
+
* Mirrors Anthropic's AskUserQuestion schema.
|
|
1491
|
+
*/
|
|
1492
|
+
type AskUserQuestionOption = {
|
|
1493
|
+
/** Pill label (required). */
|
|
1494
|
+
label: string;
|
|
1495
|
+
/** Optional long-form description (shown as a subtitle on tap-hover). */
|
|
1496
|
+
description?: string;
|
|
1497
|
+
/** Optional rich preview — reserved for future rendering; ignored in v1. */
|
|
1498
|
+
preview?: string;
|
|
1499
|
+
};
|
|
1500
|
+
/**
|
|
1501
|
+
* A single question in an `ask_user_question` tool call.
|
|
1502
|
+
* The tool may carry 1–8 prompts. When more than one is supplied, the built-in
|
|
1503
|
+
* renderer paginates them as a "Question N of M" stepper with Back / Next /
|
|
1504
|
+
* Submit-all controls; single-question payloads render without stepper chrome.
|
|
1505
|
+
*/
|
|
1506
|
+
type AskUserQuestionPrompt = {
|
|
1507
|
+
/** The question text shown to the user. */
|
|
1508
|
+
question: string;
|
|
1509
|
+
/** Optional short header label (≤12 chars) used as a compact group title. */
|
|
1510
|
+
header?: string;
|
|
1511
|
+
/** 2–4 selectable options. */
|
|
1512
|
+
options: AskUserQuestionOption[];
|
|
1513
|
+
/** When true, the user can pick multiple options and submit together. Default false. */
|
|
1514
|
+
multiSelect?: boolean;
|
|
1515
|
+
/** When true, a free-text "Other…" pill expands to an input. Default true. */
|
|
1516
|
+
allowFreeText?: boolean;
|
|
1517
|
+
};
|
|
1518
|
+
/** Parsed payload of an `ask_user_question` tool call. */
|
|
1519
|
+
type AskUserQuestionPayload = {
|
|
1520
|
+
/** 1–8 questions. Anything beyond the renderer's cap is truncated with a console warning. */
|
|
1521
|
+
questions: AskUserQuestionPrompt[];
|
|
1522
|
+
};
|
|
1523
|
+
/**
|
|
1524
|
+
* Style overrides for the answer-pill sheet. All values are raw CSS strings
|
|
1525
|
+
* and are plumbed through as CSS custom properties on the sheet root.
|
|
1526
|
+
*/
|
|
1527
|
+
type AgentWidgetAskUserQuestionStyles = {
|
|
1528
|
+
sheetBackground?: string;
|
|
1529
|
+
sheetBorder?: string;
|
|
1530
|
+
sheetShadow?: string;
|
|
1531
|
+
pillBackground?: string;
|
|
1532
|
+
pillBackgroundSelected?: string;
|
|
1533
|
+
pillTextColor?: string;
|
|
1534
|
+
pillTextColorSelected?: string;
|
|
1535
|
+
pillBorderRadius?: string;
|
|
1536
|
+
customInputBackground?: string;
|
|
1537
|
+
};
|
|
1538
|
+
/**
|
|
1539
|
+
* Feature config for the built-in `ask_user_question` answer-pill sheet.
|
|
1540
|
+
* When a tool call with the name `ask_user_question` arrives, the widget
|
|
1541
|
+
* renders an interactive sheet over the composer in place of the generic
|
|
1542
|
+
* tool bubble.
|
|
1543
|
+
*/
|
|
1544
|
+
type AgentWidgetAskUserQuestionFeature = {
|
|
1545
|
+
/** Enable the feature. Defaults to true. When false, `ask_user_question` renders as a regular tool bubble. */
|
|
1546
|
+
enabled?: boolean;
|
|
1547
|
+
/** Slide-in animation duration in ms. Defaults to 180. */
|
|
1548
|
+
slideInMs?: number;
|
|
1549
|
+
/** Label for the free-text pill. Defaults to "Other…". */
|
|
1550
|
+
freeTextLabel?: string;
|
|
1551
|
+
/** Placeholder text in the free-text input. Defaults to "Type your answer…". */
|
|
1552
|
+
freeTextPlaceholder?: string;
|
|
1553
|
+
/** Button label for submitting multi-select / free-text answers. Defaults to "Send". */
|
|
1554
|
+
submitLabel?: string;
|
|
1555
|
+
/** Button label advancing to the next question in grouped (paginated) payloads. Defaults to "Next". */
|
|
1556
|
+
nextLabel?: string;
|
|
1557
|
+
/** Button label moving back to the previous question in grouped payloads. Defaults to "Back". */
|
|
1558
|
+
backLabel?: string;
|
|
1559
|
+
/** Button label submitting all answers from the final page of a grouped payload. Defaults to "Submit all". */
|
|
1560
|
+
submitAllLabel?: string;
|
|
1561
|
+
/**
|
|
1562
|
+
* In grouped (multi-question) mode, auto-advance to the next page after a
|
|
1563
|
+
* single-select pill pick or free-text submit on intermediate pages.
|
|
1564
|
+
* Defaults to `true`. The final page never auto-submits — users always
|
|
1565
|
+
* confirm with an explicit "Submit all" click. Multi-select pages always
|
|
1566
|
+
* require an explicit Next regardless of this setting.
|
|
1567
|
+
*/
|
|
1568
|
+
groupedAutoAdvance?: boolean;
|
|
1569
|
+
/**
|
|
1570
|
+
* Visual layout for the option list.
|
|
1571
|
+
* - `"rows"` (default) — full-width stacked rows with always-visible
|
|
1572
|
+
* descriptions, right-edge number badges (single-select) or checkboxes
|
|
1573
|
+
* (multi-select), and an always-visible inline "Other" input.
|
|
1574
|
+
* - `"pills"` — legacy compact pill list with horizontal wrap; description
|
|
1575
|
+
* surfaces as a tooltip and the "Other…" pill expands on click.
|
|
1576
|
+
*/
|
|
1577
|
+
layout?: "rows" | "pills";
|
|
1578
|
+
/**
|
|
1579
|
+
* Button label for skipping the current question in grouped payloads.
|
|
1580
|
+
* Defaults to "Skip". On intermediate pages Skip advances without recording
|
|
1581
|
+
* an answer; on the final page Skip submits the partial answer record
|
|
1582
|
+
* (skipped questions absent from the resolved object). For single-question
|
|
1583
|
+
* payloads Skip behaves like dismiss.
|
|
1584
|
+
*/
|
|
1585
|
+
skipLabel?: string;
|
|
1586
|
+
/** Style overrides for the sheet and pills. */
|
|
1587
|
+
styles?: AgentWidgetAskUserQuestionStyles;
|
|
1385
1588
|
};
|
|
1386
1589
|
type SSEEventRecord = {
|
|
1387
1590
|
id: string;
|
|
@@ -3121,6 +3324,17 @@ type AgentWidgetConfig = {
|
|
|
3121
3324
|
autoFocusInput?: boolean;
|
|
3122
3325
|
launcher?: AgentWidgetLauncherConfig;
|
|
3123
3326
|
initialMessages?: AgentWidgetMessage[];
|
|
3327
|
+
/**
|
|
3328
|
+
* Artifacts to hydrate into the pane at init. Typically populated from
|
|
3329
|
+
* `storageAdapter.load()` alongside `initialMessages` so the artifact pane
|
|
3330
|
+
* survives a page refresh.
|
|
3331
|
+
*/
|
|
3332
|
+
initialArtifacts?: PersonaArtifactRecord[];
|
|
3333
|
+
/**
|
|
3334
|
+
* Which artifact id (if any) should be selected in the pane at init. Paired
|
|
3335
|
+
* with `initialArtifacts`.
|
|
3336
|
+
*/
|
|
3337
|
+
initialSelectedArtifactId?: string | null;
|
|
3124
3338
|
suggestionChips?: string[];
|
|
3125
3339
|
suggestionChipsConfig?: AgentWidgetSuggestionChipsConfig;
|
|
3126
3340
|
debug?: boolean;
|
|
@@ -4191,6 +4405,10 @@ type Controller = {
|
|
|
4191
4405
|
upsertArtifact: (manual: PersonaArtifactManualUpsert) => PersonaArtifactRecord | null;
|
|
4192
4406
|
selectArtifact: (id: string) => void;
|
|
4193
4407
|
clearArtifacts: () => void;
|
|
4408
|
+
/** Read current artifacts (useful on init to rebuild host-side tab state after hydration). */
|
|
4409
|
+
getArtifacts: () => PersonaArtifactRecord[];
|
|
4410
|
+
/** Read the currently selected artifact id (paired with `getArtifacts`). */
|
|
4411
|
+
getSelectedArtifactId: () => string | null;
|
|
4194
4412
|
/**
|
|
4195
4413
|
* Focus the chat input. Returns true if focus succeeded, false if panel is closed
|
|
4196
4414
|
* (launcher mode) or textarea is unavailable.
|
package/dist/theme-editor.d.ts
CHANGED
|
@@ -217,6 +217,18 @@ interface MessageTokens {
|
|
|
217
217
|
/** Border color between messages in the thread. */
|
|
218
218
|
border?: TokenReference<'color'>;
|
|
219
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Welcome / intro card rendered above the message list when no messages exist.
|
|
222
|
+
* Set `copy.showWelcomeCard: false` to hide it; use `layout.slots["body-top"]`
|
|
223
|
+
* to replace it wholesale.
|
|
224
|
+
*/
|
|
225
|
+
interface IntroCardTokens extends ComponentTokenSet {
|
|
226
|
+
background?: TokenReference<'color'>;
|
|
227
|
+
borderRadius?: TokenReference<'radius'>;
|
|
228
|
+
padding?: TokenReference<'spacing'>;
|
|
229
|
+
/** Box-shadow on the intro card (token ref or raw CSS, e.g. `none`). */
|
|
230
|
+
shadow?: string;
|
|
231
|
+
}
|
|
220
232
|
/** Collapsible widget chrome (tool bubbles, reasoning bubbles, approval bubbles). */
|
|
221
233
|
interface CollapsibleWidgetTokens {
|
|
222
234
|
/** Background for content areas. */
|
|
@@ -414,6 +426,8 @@ interface ComponentTokens {
|
|
|
414
426
|
panel: PanelTokens;
|
|
415
427
|
header: HeaderTokens;
|
|
416
428
|
message: MessageTokens;
|
|
429
|
+
/** Welcome / intro card shown above the message list. */
|
|
430
|
+
introCard?: IntroCardTokens;
|
|
417
431
|
/** Markdown surfaces (chat + artifact pane). */
|
|
418
432
|
markdown?: MarkdownTokens;
|
|
419
433
|
voice: VoiceTokens;
|
|
@@ -558,6 +572,61 @@ interface AgentWidgetPlugin {
|
|
|
558
572
|
defaultRenderer: () => HTMLElement;
|
|
559
573
|
config: AgentWidgetConfig;
|
|
560
574
|
}) => HTMLElement | null;
|
|
575
|
+
/**
|
|
576
|
+
* Custom renderer for `ask_user_question` tool calls.
|
|
577
|
+
*
|
|
578
|
+
* When a plugin returns an `HTMLElement`, it is inserted into the transcript
|
|
579
|
+
* in place of the default (which is no transcript bubble — the built-in
|
|
580
|
+
* renders a sheet over the composer). The built-in composer-overlay sheet
|
|
581
|
+
* is suppressed so the plugin's UI fully owns the interaction.
|
|
582
|
+
*
|
|
583
|
+
* Return `null` to fall through to the built-in overlay sheet.
|
|
584
|
+
*
|
|
585
|
+
* The context gives you a pre-parsed `payload` (may be partial while the
|
|
586
|
+
* tool call is still streaming — check `complete`) and two callbacks:
|
|
587
|
+
* `resolve(answer)` resumes the paused LOCAL tool with the user's answer,
|
|
588
|
+
* and `dismiss()` cancels with the sentinel `"(dismissed)"`.
|
|
589
|
+
*
|
|
590
|
+
* @example
|
|
591
|
+
* ```typescript
|
|
592
|
+
* renderAskUserQuestion: ({ payload, resolve, dismiss }) => {
|
|
593
|
+
* const prompt = payload.questions?.[0];
|
|
594
|
+
* if (!prompt) return null;
|
|
595
|
+
* const root = document.createElement("div");
|
|
596
|
+
* root.textContent = prompt.question ?? "";
|
|
597
|
+
* (prompt.options ?? []).forEach((option) => {
|
|
598
|
+
* const btn = document.createElement("button");
|
|
599
|
+
* btn.textContent = option.label;
|
|
600
|
+
* btn.addEventListener("click", () => resolve(option.label));
|
|
601
|
+
* root.appendChild(btn);
|
|
602
|
+
* });
|
|
603
|
+
* return root;
|
|
604
|
+
* }
|
|
605
|
+
* ```
|
|
606
|
+
*/
|
|
607
|
+
renderAskUserQuestion?: (context: {
|
|
608
|
+
message: AgentWidgetMessage;
|
|
609
|
+
/**
|
|
610
|
+
* Parsed `{ questions: [...] }` payload. May be partial while the tool
|
|
611
|
+
* call is still streaming; see `complete`. `null` when no payload has
|
|
612
|
+
* arrived yet.
|
|
613
|
+
*/
|
|
614
|
+
payload: Partial<AskUserQuestionPayload> | null;
|
|
615
|
+
/** `true` once the tool-call args have fully streamed in. */
|
|
616
|
+
complete: boolean;
|
|
617
|
+
/**
|
|
618
|
+
* Resume the paused LOCAL tool with the user's answer. Posts to the
|
|
619
|
+
* resume endpoint, pipes the SSE stream back into the session, and
|
|
620
|
+
* appends a user-visible answer bubble to the transcript.
|
|
621
|
+
*/
|
|
622
|
+
resolve: (answer: string) => void;
|
|
623
|
+
/**
|
|
624
|
+
* Cancel the question. Resumes with the sentinel `"(dismissed)"` so the
|
|
625
|
+
* server doesn't sit in `waiting_for_local` forever. Idempotent.
|
|
626
|
+
*/
|
|
627
|
+
dismiss: () => void;
|
|
628
|
+
config: AgentWidgetConfig;
|
|
629
|
+
}) => HTMLElement | null;
|
|
561
630
|
/**
|
|
562
631
|
* Custom renderer for approval bubbles
|
|
563
632
|
* Return null to use default renderer
|
|
@@ -778,6 +847,31 @@ type AgentMessageMetadata = {
|
|
|
778
847
|
* or `prompt` step inside the nested flow). Stable key for that step.
|
|
779
848
|
*/
|
|
780
849
|
parentStepId?: string;
|
|
850
|
+
/**
|
|
851
|
+
* Set to `true` on a tool-variant message produced from a `step_await`
|
|
852
|
+
* event (`awaitReason: "local_tool_required"`). Signals to UI code that
|
|
853
|
+
* the tool call is a LOCAL tool and the server is paused waiting for a
|
|
854
|
+
* `POST /v1/dispatch/resume` with the user's answer keyed by tool name.
|
|
855
|
+
*/
|
|
856
|
+
awaitingLocalTool?: boolean;
|
|
857
|
+
/**
|
|
858
|
+
* Set to `true` once the user has picked / typed / dismissed an answer for
|
|
859
|
+
* an `ask_user_question` tool call, so renderers stop re-mounting the
|
|
860
|
+
* answer-pill sheet for this tool call on subsequent render passes.
|
|
861
|
+
*/
|
|
862
|
+
askUserQuestionAnswered?: boolean;
|
|
863
|
+
/**
|
|
864
|
+
* In-progress answers for a multi-question `ask_user_question` payload,
|
|
865
|
+
* keyed by question text. Persisted across refresh so the user lands back
|
|
866
|
+
* where they were if the page reloads mid-flow. Cleared once
|
|
867
|
+
* `askUserQuestionAnswered` flips to `true`.
|
|
868
|
+
*/
|
|
869
|
+
askUserQuestionAnswers?: Record<string, string | string[]>;
|
|
870
|
+
/**
|
|
871
|
+
* Current page index for a multi-question `ask_user_question` payload's
|
|
872
|
+
* paginated stepper. Persists alongside `askUserQuestionAnswers`.
|
|
873
|
+
*/
|
|
874
|
+
askUserQuestionIndex?: number;
|
|
781
875
|
};
|
|
782
876
|
type AgentWidgetRequestMiddlewareContext = {
|
|
783
877
|
payload: AgentWidgetRequestPayload;
|
|
@@ -825,6 +919,8 @@ type AgentWidgetActionHandler = (action: AgentWidgetParsedAction, context: Agent
|
|
|
825
919
|
type AgentWidgetStoredState = {
|
|
826
920
|
messages?: AgentWidgetMessage[];
|
|
827
921
|
metadata?: Record<string, unknown>;
|
|
922
|
+
artifacts?: PersonaArtifactRecord[];
|
|
923
|
+
selectedArtifactId?: string | null;
|
|
828
924
|
};
|
|
829
925
|
interface AgentWidgetStorageAdapter {
|
|
830
926
|
load?: () => AgentWidgetStoredState | null | Promise<AgentWidgetStoredState | null>;
|
|
@@ -1382,6 +1478,113 @@ type AgentWidgetFeatureFlags = {
|
|
|
1382
1478
|
artifacts?: AgentWidgetArtifactsFeature;
|
|
1383
1479
|
/** Reveal animation for streaming assistant text. */
|
|
1384
1480
|
streamAnimation?: AgentWidgetStreamAnimationFeature;
|
|
1481
|
+
/**
|
|
1482
|
+
* Built-in interactive answer-pill sheet shown when the assistant invokes
|
|
1483
|
+
* the `ask_user_question` tool. Slides up over the composer with tappable
|
|
1484
|
+
* pills + optional free-text input.
|
|
1485
|
+
*/
|
|
1486
|
+
askUserQuestion?: AgentWidgetAskUserQuestionFeature;
|
|
1487
|
+
};
|
|
1488
|
+
/**
|
|
1489
|
+
* Single selectable option in an `ask_user_question` prompt.
|
|
1490
|
+
* Mirrors Anthropic's AskUserQuestion schema.
|
|
1491
|
+
*/
|
|
1492
|
+
type AskUserQuestionOption = {
|
|
1493
|
+
/** Pill label (required). */
|
|
1494
|
+
label: string;
|
|
1495
|
+
/** Optional long-form description (shown as a subtitle on tap-hover). */
|
|
1496
|
+
description?: string;
|
|
1497
|
+
/** Optional rich preview — reserved for future rendering; ignored in v1. */
|
|
1498
|
+
preview?: string;
|
|
1499
|
+
};
|
|
1500
|
+
/**
|
|
1501
|
+
* A single question in an `ask_user_question` tool call.
|
|
1502
|
+
* The tool may carry 1–8 prompts. When more than one is supplied, the built-in
|
|
1503
|
+
* renderer paginates them as a "Question N of M" stepper with Back / Next /
|
|
1504
|
+
* Submit-all controls; single-question payloads render without stepper chrome.
|
|
1505
|
+
*/
|
|
1506
|
+
type AskUserQuestionPrompt = {
|
|
1507
|
+
/** The question text shown to the user. */
|
|
1508
|
+
question: string;
|
|
1509
|
+
/** Optional short header label (≤12 chars) used as a compact group title. */
|
|
1510
|
+
header?: string;
|
|
1511
|
+
/** 2–4 selectable options. */
|
|
1512
|
+
options: AskUserQuestionOption[];
|
|
1513
|
+
/** When true, the user can pick multiple options and submit together. Default false. */
|
|
1514
|
+
multiSelect?: boolean;
|
|
1515
|
+
/** When true, a free-text "Other…" pill expands to an input. Default true. */
|
|
1516
|
+
allowFreeText?: boolean;
|
|
1517
|
+
};
|
|
1518
|
+
/** Parsed payload of an `ask_user_question` tool call. */
|
|
1519
|
+
type AskUserQuestionPayload = {
|
|
1520
|
+
/** 1–8 questions. Anything beyond the renderer's cap is truncated with a console warning. */
|
|
1521
|
+
questions: AskUserQuestionPrompt[];
|
|
1522
|
+
};
|
|
1523
|
+
/**
|
|
1524
|
+
* Style overrides for the answer-pill sheet. All values are raw CSS strings
|
|
1525
|
+
* and are plumbed through as CSS custom properties on the sheet root.
|
|
1526
|
+
*/
|
|
1527
|
+
type AgentWidgetAskUserQuestionStyles = {
|
|
1528
|
+
sheetBackground?: string;
|
|
1529
|
+
sheetBorder?: string;
|
|
1530
|
+
sheetShadow?: string;
|
|
1531
|
+
pillBackground?: string;
|
|
1532
|
+
pillBackgroundSelected?: string;
|
|
1533
|
+
pillTextColor?: string;
|
|
1534
|
+
pillTextColorSelected?: string;
|
|
1535
|
+
pillBorderRadius?: string;
|
|
1536
|
+
customInputBackground?: string;
|
|
1537
|
+
};
|
|
1538
|
+
/**
|
|
1539
|
+
* Feature config for the built-in `ask_user_question` answer-pill sheet.
|
|
1540
|
+
* When a tool call with the name `ask_user_question` arrives, the widget
|
|
1541
|
+
* renders an interactive sheet over the composer in place of the generic
|
|
1542
|
+
* tool bubble.
|
|
1543
|
+
*/
|
|
1544
|
+
type AgentWidgetAskUserQuestionFeature = {
|
|
1545
|
+
/** Enable the feature. Defaults to true. When false, `ask_user_question` renders as a regular tool bubble. */
|
|
1546
|
+
enabled?: boolean;
|
|
1547
|
+
/** Slide-in animation duration in ms. Defaults to 180. */
|
|
1548
|
+
slideInMs?: number;
|
|
1549
|
+
/** Label for the free-text pill. Defaults to "Other…". */
|
|
1550
|
+
freeTextLabel?: string;
|
|
1551
|
+
/** Placeholder text in the free-text input. Defaults to "Type your answer…". */
|
|
1552
|
+
freeTextPlaceholder?: string;
|
|
1553
|
+
/** Button label for submitting multi-select / free-text answers. Defaults to "Send". */
|
|
1554
|
+
submitLabel?: string;
|
|
1555
|
+
/** Button label advancing to the next question in grouped (paginated) payloads. Defaults to "Next". */
|
|
1556
|
+
nextLabel?: string;
|
|
1557
|
+
/** Button label moving back to the previous question in grouped payloads. Defaults to "Back". */
|
|
1558
|
+
backLabel?: string;
|
|
1559
|
+
/** Button label submitting all answers from the final page of a grouped payload. Defaults to "Submit all". */
|
|
1560
|
+
submitAllLabel?: string;
|
|
1561
|
+
/**
|
|
1562
|
+
* In grouped (multi-question) mode, auto-advance to the next page after a
|
|
1563
|
+
* single-select pill pick or free-text submit on intermediate pages.
|
|
1564
|
+
* Defaults to `true`. The final page never auto-submits — users always
|
|
1565
|
+
* confirm with an explicit "Submit all" click. Multi-select pages always
|
|
1566
|
+
* require an explicit Next regardless of this setting.
|
|
1567
|
+
*/
|
|
1568
|
+
groupedAutoAdvance?: boolean;
|
|
1569
|
+
/**
|
|
1570
|
+
* Visual layout for the option list.
|
|
1571
|
+
* - `"rows"` (default) — full-width stacked rows with always-visible
|
|
1572
|
+
* descriptions, right-edge number badges (single-select) or checkboxes
|
|
1573
|
+
* (multi-select), and an always-visible inline "Other" input.
|
|
1574
|
+
* - `"pills"` — legacy compact pill list with horizontal wrap; description
|
|
1575
|
+
* surfaces as a tooltip and the "Other…" pill expands on click.
|
|
1576
|
+
*/
|
|
1577
|
+
layout?: "rows" | "pills";
|
|
1578
|
+
/**
|
|
1579
|
+
* Button label for skipping the current question in grouped payloads.
|
|
1580
|
+
* Defaults to "Skip". On intermediate pages Skip advances without recording
|
|
1581
|
+
* an answer; on the final page Skip submits the partial answer record
|
|
1582
|
+
* (skipped questions absent from the resolved object). For single-question
|
|
1583
|
+
* payloads Skip behaves like dismiss.
|
|
1584
|
+
*/
|
|
1585
|
+
skipLabel?: string;
|
|
1586
|
+
/** Style overrides for the sheet and pills. */
|
|
1587
|
+
styles?: AgentWidgetAskUserQuestionStyles;
|
|
1385
1588
|
};
|
|
1386
1589
|
type SSEEventRecord = {
|
|
1387
1590
|
id: string;
|
|
@@ -3121,6 +3324,17 @@ type AgentWidgetConfig = {
|
|
|
3121
3324
|
autoFocusInput?: boolean;
|
|
3122
3325
|
launcher?: AgentWidgetLauncherConfig;
|
|
3123
3326
|
initialMessages?: AgentWidgetMessage[];
|
|
3327
|
+
/**
|
|
3328
|
+
* Artifacts to hydrate into the pane at init. Typically populated from
|
|
3329
|
+
* `storageAdapter.load()` alongside `initialMessages` so the artifact pane
|
|
3330
|
+
* survives a page refresh.
|
|
3331
|
+
*/
|
|
3332
|
+
initialArtifacts?: PersonaArtifactRecord[];
|
|
3333
|
+
/**
|
|
3334
|
+
* Which artifact id (if any) should be selected in the pane at init. Paired
|
|
3335
|
+
* with `initialArtifacts`.
|
|
3336
|
+
*/
|
|
3337
|
+
initialSelectedArtifactId?: string | null;
|
|
3124
3338
|
suggestionChips?: string[];
|
|
3125
3339
|
suggestionChipsConfig?: AgentWidgetSuggestionChipsConfig;
|
|
3126
3340
|
debug?: boolean;
|
|
@@ -4191,6 +4405,10 @@ type Controller = {
|
|
|
4191
4405
|
upsertArtifact: (manual: PersonaArtifactManualUpsert) => PersonaArtifactRecord | null;
|
|
4192
4406
|
selectArtifact: (id: string) => void;
|
|
4193
4407
|
clearArtifacts: () => void;
|
|
4408
|
+
/** Read current artifacts (useful on init to rebuild host-side tab state after hydration). */
|
|
4409
|
+
getArtifacts: () => PersonaArtifactRecord[];
|
|
4410
|
+
/** Read the currently selected artifact id (paired with `getArtifacts`). */
|
|
4411
|
+
getSelectedArtifactId: () => string | null;
|
|
4194
4412
|
/**
|
|
4195
4413
|
* Focus the chat input. Returns true if focus succeeded, false if panel is closed
|
|
4196
4414
|
* (launcher mode) or textarea is unavailable.
|