@runtypelabs/persona 4.17.1 → 4.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/dist/chunk-3I2S3I5P.js +1 -0
- package/dist/chunk-76IELU7F.js +1 -0
- package/dist/chunk-EFJBUH5F.js +1 -0
- package/dist/chunk-PDPVORUF.js +1 -0
- package/dist/chunk-Q735PSZL.js +1 -0
- package/dist/chunk-VK6JOIYJ.js +1 -0
- package/dist/codegen.cjs +4 -4
- package/dist/codegen.js +4 -4
- package/dist/{context-mentions-BTSTIBFC.js → context-mentions-MJL6S6P2.js} +1 -1
- package/dist/context-mentions.cjs +9 -8
- package/dist/context-mentions.d.cts +1212 -14
- package/dist/context-mentions.d.ts +1212 -14
- package/dist/context-mentions.js +9 -8
- package/dist/event-stream-view-4EZ7BGFK.js +1 -0
- package/dist/event-stream-view.cjs +129 -0
- package/dist/event-stream-view.d.cts +8384 -0
- package/dist/event-stream-view.d.ts +8384 -0
- package/dist/event-stream-view.js +129 -0
- package/dist/history-view-BD6OXLNA.js +898 -0
- package/dist/history-view.cjs +898 -0
- package/dist/history-view.d.cts +1461 -0
- package/dist/history-view.d.ts +1461 -0
- package/dist/history-view.js +898 -0
- package/dist/index.cjs +77 -77
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1987 -17
- package/dist/index.d.ts +1987 -17
- package/dist/index.global.js +67 -66
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +77 -77
- package/dist/index.js.map +1 -1
- package/dist/launcher.global.js +5 -4
- package/dist/launcher.global.js.map +1 -1
- package/dist/plugin-kit.cjs +1 -1
- package/dist/plugin-kit.d.cts +0 -8
- package/dist/plugin-kit.d.ts +0 -8
- package/dist/plugin-kit.js +1 -1
- package/dist/smart-dom-reader.d.cts +1212 -14
- package/dist/smart-dom-reader.d.ts +1212 -14
- package/dist/theme-editor-preview.cjs +970 -73
- package/dist/theme-editor-preview.d.cts +1331 -15
- package/dist/theme-editor-preview.d.ts +1331 -15
- package/dist/theme-editor-preview.js +81 -81
- package/dist/theme-editor.cjs +7 -7
- package/dist/theme-editor.d.cts +1215 -15
- package/dist/theme-editor.d.ts +1215 -15
- package/dist/theme-editor.js +9 -9
- package/dist/theme-reference.cjs +1 -1
- package/dist/theme-reference.d.cts +226 -7
- package/dist/theme-reference.d.ts +226 -7
- package/dist/theme-reference.js +1 -1
- package/dist/widget.css +1 -1
- package/package.json +16 -4
- package/src/client-history-rest.test.ts +1034 -0
- package/src/client-visitor-history.test.ts +596 -0
- package/src/client.ts +1040 -24
- package/src/components/artifact-inline.ts +8 -1
- package/src/components/artifact-pane.test.ts +278 -1
- package/src/components/artifact-pane.ts +135 -67
- package/src/components/artifact-preview.test.ts +14 -1
- package/src/components/artifact-preview.ts +9 -0
- package/src/components/header-builder.ts +3 -0
- package/src/components/header-layouts.test.ts +171 -7
- package/src/components/header-layouts.ts +83 -53
- package/src/components/header-parts.test.ts +154 -1
- package/src/components/header-parts.ts +266 -138
- package/src/components/history-confirm-dialog.ts +177 -0
- package/src/components/history-shell-copy.ts +99 -0
- package/src/components/history-view/announcer.ts +40 -0
- package/src/components/history-view/copy.ts +105 -0
- package/src/components/history-view/css.ts +1078 -0
- package/src/components/history-view/grouping.test.ts +142 -0
- package/src/components/history-view/grouping.ts +142 -0
- package/src/components/history-view/icons.ts +73 -0
- package/src/components/history-view/rows.ts +341 -0
- package/src/components/history-view/state.ts +309 -0
- package/src/components/history-view.test.ts +2660 -0
- package/src/components/history-view.ts +1891 -0
- package/src/components/launcher-surface.test.ts +133 -0
- package/src/components/launcher.test.ts +18 -0
- package/src/components/launcher.ts +7 -7
- package/src/components/panel.ts +17 -7
- package/src/components/welcome.ts +72 -2
- package/src/defaults.ts +36 -3
- package/src/event-stream-view-bundle.test.ts +69 -0
- package/src/event-stream-view-entry.ts +19 -0
- package/src/event-stream-view-loader.ts +31 -0
- package/src/event-stream-view.ts +19 -0
- package/src/generated/runtype-openapi-contract.ts +1 -0
- package/src/history-render.ts +325 -0
- package/src/history-view-bundle.test.ts +78 -0
- package/src/history-view-entry.ts +41 -0
- package/src/history-view-loader.test.ts +30 -0
- package/src/history-view-loader.ts +32 -0
- package/src/history-view.ts +28 -0
- package/src/index-core.ts +50 -2
- package/src/index-global.ts +55 -0
- package/src/internal/demo-history-provider.test.ts +402 -0
- package/src/internal/demo-history-provider.ts +689 -0
- package/src/internal/history-provider-registry.ts +25 -0
- package/src/internal/history-provider.ts +150 -0
- package/src/internal/runtype-history-provider.test.ts +313 -0
- package/src/internal/runtype-history-provider.ts +240 -0
- package/src/plugin-kit.test.ts +16 -0
- package/src/plugin-kit.ts +13 -5
- package/src/plugins/types.ts +177 -1
- package/src/session-history.test.ts +1397 -0
- package/src/session.ts +1200 -26
- package/src/styles/widget-styles.test.ts +133 -0
- package/src/styles/widget.css +227 -8
- package/src/theme-editor/preview-utils.test.ts +19 -0
- package/src/theme-editor/preview-utils.ts +15 -1
- package/src/theme-editor/preview.ts +7 -1
- package/src/theme-editor/role-mappings.ts +4 -1
- package/src/theme-editor/sections.test.ts +168 -1
- package/src/theme-editor/sections.ts +136 -7
- package/src/theme-editor/webmcp/summary.ts +16 -2
- package/src/theme-reference.ts +20 -6
- package/src/types/theme.ts +213 -7
- package/src/types.ts +927 -7
- package/src/ui.artifact-rail-resize.test.ts +235 -0
- package/src/ui.attachments-drop.test.ts +1 -0
- package/src/ui.header-update-stability.test.ts +2 -2
- package/src/ui.history-chunk.test.ts +72 -0
- package/src/ui.history-config-provider.test.ts +318 -0
- package/src/ui.history-controller.test.ts +711 -0
- package/src/ui.history-lifecycle.test.ts +456 -0
- package/src/ui.history-render-hooks.test.ts +904 -0
- package/src/ui.history-shell.test.ts +1887 -0
- package/src/ui.rail-overlay.test.ts +573 -0
- package/src/ui.rail-resize.test.ts +284 -0
- package/src/ui.rebuild-composer.test.ts +21 -0
- package/src/ui.render-welcome.test.ts +42 -0
- package/src/ui.shortcuts.test.ts +166 -0
- package/src/ui.ts +3071 -240
- package/src/utils/__fixtures__/client-conversation-history-wire.json +108 -0
- package/src/utils/artifact-file.ts +15 -0
- package/src/utils/artifact-gate.test.ts +4 -0
- package/src/utils/artifact-gate.ts +13 -17
- package/src/utils/artifact-resize.test.ts +28 -0
- package/src/utils/artifact-resize.ts +9 -2
- package/src/utils/buttons.ts +188 -1
- package/src/utils/config-merge.test.ts +91 -0
- package/src/utils/dropdown.ts +10 -1
- package/src/utils/history-messages.test.ts +284 -0
- package/src/utils/history-messages.ts +284 -0
- package/src/utils/icons.ts +3 -0
- package/src/utils/shortcuts.test.ts +288 -0
- package/src/utils/shortcuts.ts +221 -0
- package/src/utils/theme.test.ts +501 -4
- package/src/utils/theme.ts +42 -3
- package/src/utils/tokens.ts +153 -15
- package/src/utils/tooltip-timing.ts +4 -0
- package/src/utils/tooltip.test.ts +249 -7
- package/src/utils/tooltip.ts +146 -4
- package/src/utils/visitor-store.test.ts +425 -0
- package/src/utils/visitor-store.ts +337 -0
- package/dist/chunk-QJ4LV2KW.js +0 -1
package/src/plugin-kit.test.ts
CHANGED
|
@@ -78,6 +78,22 @@ describe("injectStyles / getStyleRoot", () => {
|
|
|
78
78
|
expect(shadow.querySelector('style[data-persona-plugin-style="kit-deferred"]')).not.toBeNull();
|
|
79
79
|
});
|
|
80
80
|
|
|
81
|
+
it("re-injects into a foreign document's head for a node adopted after the call", async () => {
|
|
82
|
+
// Mirrors the theme-editor preview: nodes built against the outer document
|
|
83
|
+
// and mounted into an iframe's. The branch must resolve by nodeType, since
|
|
84
|
+
// a real iframe document fails cross-realm instanceof checks.
|
|
85
|
+
const foreignDoc = document.implementation.createHTMLDocument("frame");
|
|
86
|
+
const el = document.createElement("div");
|
|
87
|
+
injectStyles(el, "kit-foreign", ".f {}");
|
|
88
|
+
foreignDoc.body.appendChild(el);
|
|
89
|
+
|
|
90
|
+
await flushMicrotasks();
|
|
91
|
+
|
|
92
|
+
expect(
|
|
93
|
+
foreignDoc.head.querySelector('style[data-persona-plugin-style="kit-foreign"]')
|
|
94
|
+
).not.toBeNull();
|
|
95
|
+
});
|
|
96
|
+
|
|
81
97
|
it("accepts an explicit Document or ShadowRoot target", () => {
|
|
82
98
|
const host = document.createElement("div");
|
|
83
99
|
document.body.appendChild(host);
|
package/src/plugin-kit.ts
CHANGED
|
@@ -30,21 +30,29 @@
|
|
|
30
30
|
* regardless of whether the widget runs in light or shadow DOM. For a detached
|
|
31
31
|
* node (one not yet mounted) this falls back to the owning document.
|
|
32
32
|
*/
|
|
33
|
+
// nodeType checks, not instanceof: an iframe's Document/ShadowRoot fail
|
|
34
|
+
// cross-realm instanceof against this realm's constructors.
|
|
35
|
+
const isDocumentNode = (node: Node): node is Document =>
|
|
36
|
+
node.nodeType === Node.DOCUMENT_NODE;
|
|
37
|
+
const isShadowRootNode = (node: Node): node is ShadowRoot =>
|
|
38
|
+
node.nodeType === Node.DOCUMENT_FRAGMENT_NODE &&
|
|
39
|
+
(node as ShadowRoot).host !== undefined;
|
|
40
|
+
|
|
33
41
|
export function getStyleRoot(node: Node): Document | ShadowRoot {
|
|
34
42
|
const root = node.getRootNode?.();
|
|
35
|
-
if (root
|
|
36
|
-
if (root
|
|
43
|
+
if (root && isShadowRootNode(root)) return root;
|
|
44
|
+
if (root && isDocumentNode(root)) return root;
|
|
37
45
|
return node.ownerDocument ?? document;
|
|
38
46
|
}
|
|
39
47
|
|
|
40
48
|
function injectInto(root: Document | ShadowRoot, id: string, css: string): void {
|
|
41
49
|
const container: Document | ShadowRoot | HTMLHeadElement =
|
|
42
|
-
root
|
|
50
|
+
isDocumentNode(root) ? root.head : root;
|
|
43
51
|
const escaped = id.replace(/["\\]/g, "\\$&");
|
|
44
52
|
if (container.querySelector(`style[data-persona-plugin-style="${escaped}"]`)) {
|
|
45
53
|
return; // Already present in this root: idempotent.
|
|
46
54
|
}
|
|
47
|
-
const doc = root
|
|
55
|
+
const doc = isDocumentNode(root) ? root : root.ownerDocument ?? document;
|
|
48
56
|
const style = doc.createElement("style");
|
|
49
57
|
style.setAttribute("data-persona-plugin-style", id);
|
|
50
58
|
style.textContent = css;
|
|
@@ -77,7 +85,7 @@ export function injectStyles(
|
|
|
77
85
|
id: string,
|
|
78
86
|
css: string
|
|
79
87
|
): void {
|
|
80
|
-
if (target
|
|
88
|
+
if (isDocumentNode(target) || isShadowRootNode(target)) {
|
|
81
89
|
injectInto(target, id, css);
|
|
82
90
|
return;
|
|
83
91
|
}
|
package/src/plugins/types.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ResolvedWelcomeConfig } from "../welcome";
|
|
2
2
|
import type { AgentWidgetPluginStorage } from "../utils/plugin-storage";
|
|
3
|
+
import type { ShortcutScope } from "../utils/shortcuts";
|
|
3
4
|
import {
|
|
4
5
|
AgentWidgetMessage,
|
|
5
6
|
AgentWidgetConfig,
|
|
@@ -16,7 +17,15 @@ import {
|
|
|
16
17
|
AgentWidgetSuggestionSource,
|
|
17
18
|
AgentWidgetSuggestionSurface,
|
|
18
19
|
AgentWidgetSuggestionVariant,
|
|
19
|
-
AgentWidgetWelcomeVariant
|
|
20
|
+
AgentWidgetWelcomeVariant,
|
|
21
|
+
AgentWidgetRenderHistoryViewContext,
|
|
22
|
+
AgentWidgetRenderHistoryHeaderContext,
|
|
23
|
+
AgentWidgetRenderHistoryConversationContext,
|
|
24
|
+
AgentWidgetRenderHistoryOpenErrorContext,
|
|
25
|
+
AgentWidgetRenderHistoryStateContext,
|
|
26
|
+
AgentWidgetHistoryRailSection,
|
|
27
|
+
AgentWidgetHistoryRenderActions,
|
|
28
|
+
ResolvedHistoryPresentation
|
|
20
29
|
} from "../types";
|
|
21
30
|
|
|
22
31
|
export type AgentWidgetTransformSuggestionsContext = {
|
|
@@ -70,6 +79,40 @@ export type AgentWidgetRenderWelcomeContext = {
|
|
|
70
79
|
onCleanup: (fn: () => void) => void;
|
|
71
80
|
};
|
|
72
81
|
|
|
82
|
+
/** Context for one `railSections` entry. Frozen per invocation. */
|
|
83
|
+
export type AgentWidgetRailSectionContext = {
|
|
84
|
+
/** Current rail width state. The section re-renders whenever this flips. */
|
|
85
|
+
collapsed: boolean;
|
|
86
|
+
presentation: ResolvedHistoryPresentation;
|
|
87
|
+
/** The same frozen action path the default rows and `renderHistoryView` use. */
|
|
88
|
+
actions: AgentWidgetHistoryRenderActions;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/** A plugin-contributed navigation section in the history rail. */
|
|
92
|
+
export type AgentWidgetRailSection = {
|
|
93
|
+
/** Stable identity, stamped as `data-persona-rail-section`. */
|
|
94
|
+
id: string;
|
|
95
|
+
/** Default `"above-conversations"`. */
|
|
96
|
+
placement?: AgentWidgetHistoryRailSection["placement"];
|
|
97
|
+
/** Optional heading, styled like a conversation date-group heading. */
|
|
98
|
+
title?: string;
|
|
99
|
+
/** Section body. Null renders nothing for the current state. */
|
|
100
|
+
render: (context: AgentWidgetRailSectionContext) => Element | null;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/** A plugin-contributed keyboard shortcut, bound per widget instance. */
|
|
104
|
+
export type AgentWidgetPluginShortcut = {
|
|
105
|
+
/** Stable identity, used in duplicate/throw warnings. */
|
|
106
|
+
id: string;
|
|
107
|
+
/** e.g. `"mod+b"`. "mod" is Command on Apple platforms, Control elsewhere. */
|
|
108
|
+
combo: string;
|
|
109
|
+
/** Default `"widget"`: fires only from inside the widget mount. */
|
|
110
|
+
scope?: ShortcutScope;
|
|
111
|
+
/** Returning false skips the binding for this keypress. */
|
|
112
|
+
when?: () => boolean;
|
|
113
|
+
run: () => void;
|
|
114
|
+
};
|
|
115
|
+
|
|
73
116
|
export type AgentWidgetSuggestionSelectContext = {
|
|
74
117
|
suggestion: AgentWidgetResolvedSuggestion;
|
|
75
118
|
surface: AgentWidgetSuggestionSurface;
|
|
@@ -360,6 +403,10 @@ export interface AgentWidgetPlugin {
|
|
|
360
403
|
* Custom renderer for loading indicator
|
|
361
404
|
* Return null to use default renderer (or config-based renderer)
|
|
362
405
|
*
|
|
406
|
+
* Covers the streaming indicator ('inline', 'standalone') and the transcript
|
|
407
|
+
* skeleton shown while a conversation opened from the Messages list loads
|
|
408
|
+
* ('conversation-open').
|
|
409
|
+
*
|
|
363
410
|
* @example
|
|
364
411
|
* ```typescript
|
|
365
412
|
* renderLoadingIndicator: ({ location, defaultRenderer }) => {
|
|
@@ -417,6 +464,135 @@ export interface AgentWidgetPlugin {
|
|
|
417
464
|
*/
|
|
418
465
|
renderEventStreamPayload?: (context: EventStreamPayloadRenderContext) => HTMLElement | null;
|
|
419
466
|
|
|
467
|
+
/**
|
|
468
|
+
* Replace the complete history ("Messages") navigation contents in either
|
|
469
|
+
* host. Plugins run by priority and the first non-null element wins; null
|
|
470
|
+
* falls through to the default full view, which then applies the first
|
|
471
|
+
* non-null header/row/state hook at each slot.
|
|
472
|
+
*
|
|
473
|
+
* Calling `defaultRenderer()` bypasses this hook only: the default view is
|
|
474
|
+
* built and its lower-level slots still arbitrate, including this plugin's.
|
|
475
|
+
* Return it (or an element containing it) to compose rather than replace.
|
|
476
|
+
*
|
|
477
|
+
* The hook replaces contents, not orchestration. Persona keeps placement,
|
|
478
|
+
* open/close, responsive rail <-> panel movement, inertness, Escape, the
|
|
479
|
+
* confirmation dialogs, live announcements, and focus fallback. Fetch nothing
|
|
480
|
+
* directly: `actions.refresh()` is the only way to reload the list.
|
|
481
|
+
*
|
|
482
|
+
* @example
|
|
483
|
+
* ```typescript
|
|
484
|
+
* renderHistoryView: ({ conversations, actions, presentation, onCleanup }) => {
|
|
485
|
+
* const rail = document.createElement("nav");
|
|
486
|
+
* rail.dataset.presentation = presentation;
|
|
487
|
+
* for (const conversation of conversations) {
|
|
488
|
+
* const row = document.createElement("button");
|
|
489
|
+
* row.textContent = conversation.title;
|
|
490
|
+
* row.addEventListener("click", () => void actions.openConversation(conversation.id));
|
|
491
|
+
* rail.appendChild(row);
|
|
492
|
+
* }
|
|
493
|
+
* const timer = setInterval(() => void actions.refresh(), 60_000);
|
|
494
|
+
* onCleanup(() => clearInterval(timer));
|
|
495
|
+
* return rail;
|
|
496
|
+
* }
|
|
497
|
+
* ```
|
|
498
|
+
*/
|
|
499
|
+
renderHistoryView?: (
|
|
500
|
+
context: AgentWidgetRenderHistoryViewContext
|
|
501
|
+
) => HTMLElement | null;
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Replace the standard Messages header while retaining its list/state UI.
|
|
505
|
+
* Return null to use the default top bar. A custom header may not remove the
|
|
506
|
+
* keyboard close path or falsify the resolved open state.
|
|
507
|
+
*/
|
|
508
|
+
renderHistoryHeader?: (
|
|
509
|
+
context: AgentWidgetRenderHistoryHeaderContext
|
|
510
|
+
) => HTMLElement | null;
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Replace one conversation row while retaining standard paging/grouping.
|
|
514
|
+
* Return null to use the default row.
|
|
515
|
+
*/
|
|
516
|
+
renderHistoryConversation?: (
|
|
517
|
+
context: AgentWidgetRenderHistoryConversationContext
|
|
518
|
+
) => HTMLElement | null;
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* Replace loading, empty, error, authentication, rate-limit, or recovery
|
|
522
|
+
* content in the list region. Return null to use the default block.
|
|
523
|
+
*/
|
|
524
|
+
renderHistoryState?: (
|
|
525
|
+
context: AgentWidgetRenderHistoryStateContext
|
|
526
|
+
) => HTMLElement | null;
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Replace the transcript-level error surface shown when opening a
|
|
530
|
+
* conversation from the Messages list fails. Plugins run by priority and
|
|
531
|
+
* the first non-null element wins; null falls through to the default block.
|
|
532
|
+
*
|
|
533
|
+
* Persona keeps the centered transcript column, the alert role, and the
|
|
534
|
+
* composer gate around the returned element. `retry`/`back` are the only
|
|
535
|
+
* exits: both route through the token-guarded open flow, so do not fetch
|
|
536
|
+
* directly. `back` is absent when there is no Messages surface to return
|
|
537
|
+
* to; do not render a back affordance without it.
|
|
538
|
+
*/
|
|
539
|
+
renderHistoryOpenError?: (
|
|
540
|
+
context: AgentWidgetRenderHistoryOpenErrorContext
|
|
541
|
+
) => HTMLElement | null;
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Contribute navigation sections to the history rail, stacked around the
|
|
545
|
+
* conversation list in `placement` order. Rail only: the panel presentation
|
|
546
|
+
* renders none of them, and `features.history.rail.sections` (config) comes
|
|
547
|
+
* first inside each bucket, then plugins in plugin order.
|
|
548
|
+
*
|
|
549
|
+
* `render` is re-invoked with the new `collapsed` value whenever the rail
|
|
550
|
+
* collapses or expands, and its return replaces the previous content;
|
|
551
|
+
* returning null renders nothing for that state. A throwing `render` warns
|
|
552
|
+
* once and drops that section only, leaving the rest of the rail alone. An id
|
|
553
|
+
* a config section already owns is dropped with a warning.
|
|
554
|
+
*
|
|
555
|
+
* Keep heavy UI in the host bundle: `render` may return a skeleton and
|
|
556
|
+
* hydrate it after the host's own dynamic import resolves.
|
|
557
|
+
*
|
|
558
|
+
* @example
|
|
559
|
+
* ```typescript
|
|
560
|
+
* railSections: [
|
|
561
|
+
* {
|
|
562
|
+
* id: "pinned",
|
|
563
|
+
* title: "Pinned",
|
|
564
|
+
* render: ({ collapsed, actions }) => {
|
|
565
|
+
* if (collapsed) return null;
|
|
566
|
+
* const list = document.createElement("div");
|
|
567
|
+
* const row = document.createElement("button");
|
|
568
|
+
* row.textContent = "Weekly report";
|
|
569
|
+
* row.addEventListener("click", () => void actions.openConversation("c1"));
|
|
570
|
+
* list.appendChild(row);
|
|
571
|
+
* return list;
|
|
572
|
+
* }
|
|
573
|
+
* }
|
|
574
|
+
* ]
|
|
575
|
+
* ```
|
|
576
|
+
*/
|
|
577
|
+
railSections?: AgentWidgetRailSection[];
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* Keyboard shortcuts registered for the lifetime of each widget instance the
|
|
581
|
+
* plugin is active in, and unregistered on its teardown. `combo` is written
|
|
582
|
+
* as `"mod+b"` / `"mod+shift+k"`, where "mod" is Command on Apple platforms
|
|
583
|
+
* and Control elsewhere. `scope` defaults to `"widget"` (only while focus is
|
|
584
|
+
* inside the mount); `when` returning false skips the keypress. A combo
|
|
585
|
+
* another binding already owns warns and is ignored, first registration wins.
|
|
586
|
+
*
|
|
587
|
+
* @example
|
|
588
|
+
* ```typescript
|
|
589
|
+
* shortcuts: [
|
|
590
|
+
* { id: "open-inbox", combo: "mod+shift+i", run: () => openInbox() }
|
|
591
|
+
* ]
|
|
592
|
+
* ```
|
|
593
|
+
*/
|
|
594
|
+
shortcuts?: AgentWidgetPluginShortcut[];
|
|
595
|
+
|
|
420
596
|
/**
|
|
421
597
|
* Called when plugin is registered
|
|
422
598
|
*/
|