@tetherto/mdk-ui-agent 0.0.0 → 0.12.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.
- package/LICENSE +202 -0
- package/README.md +310 -0
- package/dist/branding.d.ts +36 -0
- package/dist/branding.d.ts.map +1 -0
- package/dist/branding.js +37 -0
- package/dist/branding.js.map +1 -0
- package/dist/components/approval-card.d.ts +46 -0
- package/dist/components/approval-card.d.ts.map +1 -0
- package/dist/components/approval-card.js +84 -0
- package/dist/components/approval-card.js.map +1 -0
- package/dist/components/assistant-message.d.ts +25 -0
- package/dist/components/assistant-message.d.ts.map +1 -0
- package/dist/components/assistant-message.js +49 -0
- package/dist/components/assistant-message.js.map +1 -0
- package/dist/components/co-pilot-panel.d.ts +17 -0
- package/dist/components/co-pilot-panel.d.ts.map +1 -0
- package/dist/components/co-pilot-panel.js +33 -0
- package/dist/components/co-pilot-panel.js.map +1 -0
- package/dist/components/code-block.d.ts +17 -0
- package/dist/components/code-block.d.ts.map +1 -0
- package/dist/components/code-block.js +40 -0
- package/dist/components/code-block.js.map +1 -0
- package/dist/components/collapsible-answer.d.ts +26 -0
- package/dist/components/collapsible-answer.d.ts.map +1 -0
- package/dist/components/collapsible-answer.js +30 -0
- package/dist/components/collapsible-answer.js.map +1 -0
- package/dist/components/composer.d.ts +31 -0
- package/dist/components/composer.d.ts.map +1 -0
- package/dist/components/composer.js +82 -0
- package/dist/components/composer.js.map +1 -0
- package/dist/components/conversation-list.d.ts +21 -0
- package/dist/components/conversation-list.d.ts.map +1 -0
- package/dist/components/conversation-list.js +42 -0
- package/dist/components/conversation-list.js.map +1 -0
- package/dist/components/icons.d.ts +88 -0
- package/dist/components/icons.d.ts.map +1 -0
- package/dist/components/icons.js +112 -0
- package/dist/components/icons.js.map +1 -0
- package/dist/components/launcher-fab.d.ts +8 -0
- package/dist/components/launcher-fab.d.ts.map +1 -0
- package/dist/components/launcher-fab.js +6 -0
- package/dist/components/launcher-fab.js.map +1 -0
- package/dist/components/leaked-tool-call-notice.d.ts +18 -0
- package/dist/components/leaked-tool-call-notice.d.ts.map +1 -0
- package/dist/components/leaked-tool-call-notice.js +14 -0
- package/dist/components/leaked-tool-call-notice.js.map +1 -0
- package/dist/components/markdown-link.d.ts +17 -0
- package/dist/components/markdown-link.d.ts.map +1 -0
- package/dist/components/markdown-link.js +18 -0
- package/dist/components/markdown-link.js.map +1 -0
- package/dist/components/markdown-text.d.ts +26 -0
- package/dist/components/markdown-text.d.ts.map +1 -0
- package/dist/components/markdown-text.js +32 -0
- package/dist/components/markdown-text.js.map +1 -0
- package/dist/components/message-list.d.ts +24 -0
- package/dist/components/message-list.d.ts.map +1 -0
- package/dist/components/message-list.js +92 -0
- package/dist/components/message-list.js.map +1 -0
- package/dist/components/no-tools-note.d.ts +26 -0
- package/dist/components/no-tools-note.d.ts.map +1 -0
- package/dist/components/no-tools-note.js +27 -0
- package/dist/components/no-tools-note.js.map +1 -0
- package/dist/components/panel-header.d.ts +26 -0
- package/dist/components/panel-header.d.ts.map +1 -0
- package/dist/components/panel-header.js +13 -0
- package/dist/components/panel-header.js.map +1 -0
- package/dist/components/rehype-highlight-subset.d.ts +17 -0
- package/dist/components/rehype-highlight-subset.d.ts.map +1 -0
- package/dist/components/rehype-highlight-subset.js +77 -0
- package/dist/components/rehype-highlight-subset.js.map +1 -0
- package/dist/components/system-message.d.ts +15 -0
- package/dist/components/system-message.d.ts.map +1 -0
- package/dist/components/system-message.js +12 -0
- package/dist/components/system-message.js.map +1 -0
- package/dist/components/tool-chip.d.ts +19 -0
- package/dist/components/tool-chip.d.ts.map +1 -0
- package/dist/components/tool-chip.js +32 -0
- package/dist/components/tool-chip.js.map +1 -0
- package/dist/components/user-message.d.ts +9 -0
- package/dist/components/user-message.d.ts.map +1 -0
- package/dist/components/user-message.js +7 -0
- package/dist/components/user-message.js.map +1 -0
- package/dist/core/conversation-store.d.ts +107 -0
- package/dist/core/conversation-store.d.ts.map +1 -0
- package/dist/core/conversation-store.js +254 -0
- package/dist/core/conversation-store.js.map +1 -0
- package/dist/core/error-text.d.ts +19 -0
- package/dist/core/error-text.d.ts.map +1 -0
- package/dist/core/error-text.js +35 -0
- package/dist/core/error-text.js.map +1 -0
- package/dist/core/events.d.ts +98 -0
- package/dist/core/events.d.ts.map +1 -0
- package/dist/core/events.js +50 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/format.d.ts +23 -0
- package/dist/core/format.d.ts.map +1 -0
- package/dist/core/format.js +49 -0
- package/dist/core/format.js.map +1 -0
- package/dist/core/index.d.ts +27 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +20 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/markdown.d.ts +26 -0
- package/dist/core/markdown.d.ts.map +1 -0
- package/dist/core/markdown.js +49 -0
- package/dist/core/markdown.js.map +1 -0
- package/dist/core/prose.d.ts +27 -0
- package/dist/core/prose.d.ts.map +1 -0
- package/dist/core/prose.js +79 -0
- package/dist/core/prose.js.map +1 -0
- package/dist/core/small-talk.d.ts +15 -0
- package/dist/core/small-talk.d.ts.map +1 -0
- package/dist/core/small-talk.js +42 -0
- package/dist/core/small-talk.js.map +1 -0
- package/dist/core/sse.d.ts +108 -0
- package/dist/core/sse.d.ts.map +1 -0
- package/dist/core/sse.js +236 -0
- package/dist/core/sse.js.map +1 -0
- package/dist/core/tool-label.d.ts +16 -0
- package/dist/core/tool-label.d.ts.map +1 -0
- package/dist/core/tool-label.js +31 -0
- package/dist/core/tool-label.js.map +1 -0
- package/dist/core/transport.d.ts +71 -0
- package/dist/core/transport.d.ts.map +1 -0
- package/dist/core/transport.js +147 -0
- package/dist/core/transport.js.map +1 -0
- package/dist/core/turn.d.ts +87 -0
- package/dist/core/turn.d.ts.map +1 -0
- package/dist/core/turn.js +232 -0
- package/dist/core/turn.js.map +1 -0
- package/dist/core/uuid.d.ts +21 -0
- package/dist/core/uuid.d.ts.map +1 -0
- package/dist/core/uuid.js +54 -0
- package/dist/core/uuid.js.map +1 -0
- package/dist/entries/chat-page.d.ts +28 -0
- package/dist/entries/chat-page.d.ts.map +1 -0
- package/dist/entries/chat-page.js +25 -0
- package/dist/entries/chat-page.js.map +1 -0
- package/dist/entries/co-pilot.d.ts +41 -0
- package/dist/entries/co-pilot.d.ts.map +1 -0
- package/dist/entries/co-pilot.js +39 -0
- package/dist/entries/co-pilot.js.map +1 -0
- package/dist/entries/lazy-panel.d.ts +15 -0
- package/dist/entries/lazy-panel.d.ts.map +1 -0
- package/dist/entries/lazy-panel.js +19 -0
- package/dist/entries/lazy-panel.js.map +1 -0
- package/dist/hooks/index.d.ts +7 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/use-agent-chat.d.ts +46 -0
- package/dist/hooks/use-agent-chat.d.ts.map +1 -0
- package/dist/hooks/use-agent-chat.js +288 -0
- package/dist/hooks/use-agent-chat.js.map +1 -0
- package/dist/hooks/use-agent-config.d.ts +29 -0
- package/dist/hooks/use-agent-config.d.ts.map +1 -0
- package/dist/hooks/use-agent-config.js +45 -0
- package/dist/hooks/use-agent-config.js.map +1 -0
- package/dist/hooks/use-conversations.d.ts +19 -0
- package/dist/hooks/use-conversations.d.ts.map +1 -0
- package/dist/hooks/use-conversations.js +19 -0
- package/dist/hooks/use-conversations.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +1 -0
- package/package.json +105 -1
- package/src/branding.ts +40 -0
- package/src/components/approval-card.tsx +141 -0
- package/src/components/assistant-message.tsx +140 -0
- package/src/components/co-pilot-panel.tsx +109 -0
- package/src/components/code-block.tsx +63 -0
- package/src/components/collapsible-answer.tsx +55 -0
- package/src/components/composer.tsx +147 -0
- package/src/components/conversation-list.tsx +141 -0
- package/src/components/icons.tsx +189 -0
- package/src/components/launcher-fab.tsx +16 -0
- package/src/components/leaked-tool-call-notice.tsx +29 -0
- package/src/components/markdown-link.tsx +30 -0
- package/src/components/markdown-text.tsx +58 -0
- package/src/components/message-list.tsx +164 -0
- package/src/components/no-tools-note.tsx +33 -0
- package/src/components/panel-header.tsx +86 -0
- package/src/components/rehype-highlight-subset.ts +84 -0
- package/src/components/system-message.tsx +19 -0
- package/src/components/tool-chip.tsx +58 -0
- package/src/components/user-message.tsx +18 -0
- package/src/core/conversation-store.ts +342 -0
- package/src/core/error-text.ts +36 -0
- package/src/core/events.ts +127 -0
- package/src/core/format.ts +59 -0
- package/src/core/index.ts +115 -0
- package/src/core/markdown.ts +52 -0
- package/src/core/prose.ts +78 -0
- package/src/core/small-talk.ts +45 -0
- package/src/core/sse.ts +269 -0
- package/src/core/tool-label.ts +33 -0
- package/src/core/transport.ts +208 -0
- package/src/core/turn.ts +299 -0
- package/src/core/uuid.ts +59 -0
- package/src/entries/chat-page.tsx +56 -0
- package/src/entries/co-pilot.tsx +84 -0
- package/src/entries/lazy-panel.tsx +19 -0
- package/src/hooks/index.ts +8 -0
- package/src/hooks/use-agent-chat.ts +387 -0
- package/src/hooks/use-agent-config.ts +70 -0
- package/src/hooks/use-conversations.ts +39 -0
- package/src/index.ts +30 -0
- package/src/styles/_approval.scss +68 -0
- package/src/styles/_composer.scss +45 -0
- package/src/styles/_conversations.scss +160 -0
- package/src/styles/_messages.scss +444 -0
- package/src/styles/_mixins.scss +27 -0
- package/src/styles/_panel.scss +147 -0
- package/src/styles/_tokens.scss +30 -0
- package/src/styles.scss +16 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button } from '@tetherto/mdk-react-devkit/primitives';
|
|
3
|
+
import { memo } from 'react';
|
|
4
|
+
import { AGENT_LABELS } from '../branding';
|
|
5
|
+
import { BackIcon, CloseIcon, ListLayoutIcon, MessagePlusIcon } from './icons';
|
|
6
|
+
export const PANEL_VIEW = { CHAT: 'chat', CONVERSATIONS: 'conversations' };
|
|
7
|
+
const PanelHeaderView = ({ view, title, status, actionsDisabled = false, onNewConversation, onToggleConversations, onClose, }) => (_jsxs("header", { className: "mdk-agent-header", children: [_jsxs("div", { className: "mdk-agent-header__titles", children: [_jsxs("h2", { className: "mdk-agent-header__title", children: [view === PANEL_VIEW.CONVERSATIONS
|
|
8
|
+
? (_jsx(Button, { variant: "icon", className: "mdk-agent-header__back", "aria-label": AGENT_LABELS.backToConversation, icon: _jsx(BackIcon, { size: 16 }), onClick: onToggleConversations }))
|
|
9
|
+
: null, title] }), status ? _jsx("p", { className: "mdk-agent-header__status", children: status }) : null] }), _jsxs("div", { className: "mdk-agent-header__actions", children: [_jsx(Button, { variant: "icon", "aria-label": AGENT_LABELS.newConversation, disabled: actionsDisabled, icon: _jsx(MessagePlusIcon, { size: 16 }), onClick: onNewConversation }), _jsx(Button, { variant: "icon", "aria-label": AGENT_LABELS.conversations, "aria-pressed": view === PANEL_VIEW.CONVERSATIONS, icon: _jsx(ListLayoutIcon, { size: 16 }), onClick: onToggleConversations }), onClose
|
|
10
|
+
? (_jsx(Button, { variant: "icon", "aria-label": AGENT_LABELS.close, icon: _jsx(CloseIcon, { size: 16 }), onClick: onClose }))
|
|
11
|
+
: null] })] }));
|
|
12
|
+
export const PanelHeader = memo(PanelHeaderView);
|
|
13
|
+
//# sourceMappingURL=panel-header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel-header.js","sourceRoot":"","sources":["../../src/components/panel-header.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAA;AAE9D,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAE5B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE9E,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,eAAe,EAAW,CAAA;AAqBnF,MAAM,eAAe,GAAG,CAAC,EACvB,IAAI,EACJ,KAAK,EACL,MAAM,EACN,eAAe,GAAG,KAAK,EACvB,iBAAiB,EACjB,qBAAqB,EACrB,OAAO,GACU,EAAe,EAAE,CAAC,CACnC,kBAAQ,SAAS,EAAC,kBAAkB,aAClC,eAAK,SAAS,EAAC,0BAA0B,aACvC,cAAI,SAAS,EAAC,yBAAyB,aACpC,IAAI,KAAK,UAAU,CAAC,aAAa;4BAChC,CAAC,CAAC,CACE,KAAC,MAAM,IACL,OAAO,EAAC,MAAM,EACd,SAAS,EAAC,wBAAwB,gBACtB,YAAY,CAAC,kBAAkB,EAC3C,IAAI,EAAE,KAAC,QAAQ,IAAC,IAAI,EAAE,EAAE,GAAI,EAC5B,OAAO,EAAE,qBAAqB,GAC9B,CACH;4BACH,CAAC,CAAC,IAAI,EACP,KAAK,IACH,EACJ,MAAM,CAAC,CAAC,CAAC,YAAG,SAAS,EAAC,0BAA0B,YAAE,MAAM,GAAK,CAAC,CAAC,CAAC,IAAI,IACjE,EAEN,eAAK,SAAS,EAAC,2BAA2B,aACxC,KAAC,MAAM,IACL,OAAO,EAAC,MAAM,gBACF,YAAY,CAAC,eAAe,EACxC,QAAQ,EAAE,eAAe,EACzB,IAAI,EAAE,KAAC,eAAe,IAAC,IAAI,EAAE,EAAE,GAAI,EACnC,OAAO,EAAE,iBAAiB,GAC1B,EACF,KAAC,MAAM,IACL,OAAO,EAAC,MAAM,gBACF,YAAY,CAAC,aAAa,kBACxB,IAAI,KAAK,UAAU,CAAC,aAAa,EAC/C,IAAI,EAAE,KAAC,cAAc,IAAC,IAAI,EAAE,EAAE,GAAI,EAClC,OAAO,EAAE,qBAAqB,GAC9B,EACD,OAAO;oBACN,CAAC,CAAC,CACE,KAAC,MAAM,IACL,OAAO,EAAC,MAAM,gBACF,YAAY,CAAC,KAAK,EAC9B,IAAI,EAAE,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,GAAI,EAC7B,OAAO,EAAE,OAAO,GAChB,CACH;oBACH,CAAC,CAAC,IAAI,IACJ,IACC,CACV,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Syntax highlighting for fenced code, restricted to the grammars this panel
|
|
3
|
+
* actually sees.
|
|
4
|
+
*
|
|
5
|
+
* `rehype-highlight` would do the same job, but it statically imports lowlight's
|
|
6
|
+
* `common` set — 37 grammars and most of highlight.js's bulk — so its
|
|
7
|
+
* `languages` option changes what gets *registered*, never what gets *bundled*.
|
|
8
|
+
* Measured against the generated shell, that was 179 kB raw / 55 kB gzip, more
|
|
9
|
+
* than doubling the panel's chunk to highlight languages a fleet co-pilot never
|
|
10
|
+
* emits. Registering three grammars directly costs a fraction of that.
|
|
11
|
+
*
|
|
12
|
+
* Anything outside the set still renders — unhighlighted, in the mono face the
|
|
13
|
+
* panel already uses.
|
|
14
|
+
*/
|
|
15
|
+
import type { Root } from 'hast';
|
|
16
|
+
export declare function rehypeHighlightSubset(): (tree: Root) => void;
|
|
17
|
+
//# sourceMappingURL=rehype-highlight-subset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rehype-highlight-subset.d.ts","sourceRoot":"","sources":["../../src/components/rehype-highlight-subset.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,KAAK,EAAyC,IAAI,EAAQ,MAAM,MAAM,CAAA;AA6D7E,wBAAgB,qBAAqB,WACrB,IAAI,KAAG,IAAI,CAG1B"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Syntax highlighting for fenced code, restricted to the grammars this panel
|
|
3
|
+
* actually sees.
|
|
4
|
+
*
|
|
5
|
+
* `rehype-highlight` would do the same job, but it statically imports lowlight's
|
|
6
|
+
* `common` set — 37 grammars and most of highlight.js's bulk — so its
|
|
7
|
+
* `languages` option changes what gets *registered*, never what gets *bundled*.
|
|
8
|
+
* Measured against the generated shell, that was 179 kB raw / 55 kB gzip, more
|
|
9
|
+
* than doubling the panel's chunk to highlight languages a fleet co-pilot never
|
|
10
|
+
* emits. Registering three grammars directly costs a fraction of that.
|
|
11
|
+
*
|
|
12
|
+
* Anything outside the set still renders — unhighlighted, in the mono face the
|
|
13
|
+
* panel already uses.
|
|
14
|
+
*/
|
|
15
|
+
import bash from 'highlight.js/lib/languages/bash';
|
|
16
|
+
import json from 'highlight.js/lib/languages/json';
|
|
17
|
+
import yaml from 'highlight.js/lib/languages/yaml';
|
|
18
|
+
import { createLowlight } from 'lowlight';
|
|
19
|
+
const lowlight = createLowlight({ bash, json, yaml });
|
|
20
|
+
const LANGUAGE_PREFIX = 'language-';
|
|
21
|
+
function isElement(node) {
|
|
22
|
+
return node.type === 'element';
|
|
23
|
+
}
|
|
24
|
+
function isParent(node) {
|
|
25
|
+
return Array.isArray(node.children);
|
|
26
|
+
}
|
|
27
|
+
/** Concatenates the text under a node, which for a code block is its source. */
|
|
28
|
+
function textOf(node) {
|
|
29
|
+
if (node.type === 'text')
|
|
30
|
+
return node.value;
|
|
31
|
+
if (!isParent(node))
|
|
32
|
+
return '';
|
|
33
|
+
return node.children.map((child) => textOf(child)).join('');
|
|
34
|
+
}
|
|
35
|
+
function languageOf(node) {
|
|
36
|
+
const className = node.properties?.className;
|
|
37
|
+
const classes = Array.isArray(className) ? className.map(String) : [];
|
|
38
|
+
const match = classes.find((name) => name.startsWith(LANGUAGE_PREFIX));
|
|
39
|
+
return match ? match.slice(LANGUAGE_PREFIX.length) : null;
|
|
40
|
+
}
|
|
41
|
+
function highlightCodeBlock(node) {
|
|
42
|
+
const language = languageOf(node);
|
|
43
|
+
if (!language || !lowlight.registered(language))
|
|
44
|
+
return;
|
|
45
|
+
try {
|
|
46
|
+
const result = lowlight.highlight(language, textOf(node));
|
|
47
|
+
// lowlight returns a Root, whose children are typed wider than a code
|
|
48
|
+
// element's. In practice it only ever emits elements and text.
|
|
49
|
+
node.children = result.children;
|
|
50
|
+
node.properties = {
|
|
51
|
+
...node.properties,
|
|
52
|
+
className: [...(Array.isArray(node.properties?.className) ? node.properties.className : []), 'hljs'],
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// A grammar that throws on odd input must not take the whole answer with it;
|
|
57
|
+
// the block simply stays unhighlighted.
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function walk(node) {
|
|
61
|
+
if (!isParent(node))
|
|
62
|
+
return;
|
|
63
|
+
for (const child of node.children) {
|
|
64
|
+
// Only `<pre><code>` — an inline `code` span is not a code block.
|
|
65
|
+
if (isElement(node) && node.tagName === 'pre' && isElement(child) && child.tagName === 'code') {
|
|
66
|
+
highlightCodeBlock(child);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
walk(child);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
export function rehypeHighlightSubset() {
|
|
73
|
+
return (tree) => {
|
|
74
|
+
walk(tree);
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=rehype-highlight-subset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rehype-highlight-subset.js","sourceRoot":"","sources":["../../src/components/rehype-highlight-subset.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { JSX } from 'react';
|
|
2
|
+
export type SystemMessageProps = {
|
|
3
|
+
text: string;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* A note from the panel itself, not from the model.
|
|
7
|
+
*
|
|
8
|
+
* Used where the transcript would otherwise imply something untrue — most of all
|
|
9
|
+
* a re-minted session, where the conversation reads as continuous but the agent
|
|
10
|
+
* remembers none of it.
|
|
11
|
+
*/
|
|
12
|
+
declare const SystemMessageView: ({ text }: SystemMessageProps) => JSX.Element;
|
|
13
|
+
export declare const SystemMessage: import("react").MemoExoticComponent<typeof SystemMessageView>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=system-message.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-message.d.ts","sourceRoot":"","sources":["../../src/components/system-message.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAGhC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED;;;;;;GAMG;AACH,QAAA,MAAM,iBAAiB,aAAc,kBAAkB,KAAG,GAAG,CAAC,OAE7D,CAAA;AAED,eAAO,MAAM,aAAa,+DAA0B,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* A note from the panel itself, not from the model.
|
|
5
|
+
*
|
|
6
|
+
* Used where the transcript would otherwise imply something untrue — most of all
|
|
7
|
+
* a re-minted session, where the conversation reads as continuous but the agent
|
|
8
|
+
* remembers none of it.
|
|
9
|
+
*/
|
|
10
|
+
const SystemMessageView = ({ text }) => (_jsx("p", { className: "mdk-agent-system", role: "note", children: text }));
|
|
11
|
+
export const SystemMessage = memo(SystemMessageView);
|
|
12
|
+
//# sourceMappingURL=system-message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-message.js","sourceRoot":"","sources":["../../src/components/system-message.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAM5B;;;;;;GAMG;AACH,MAAM,iBAAiB,GAAG,CAAC,EAAE,IAAI,EAAsB,EAAe,EAAE,CAAC,CACvE,YAAG,SAAS,EAAC,kBAAkB,EAAC,IAAI,EAAC,MAAM,YAAE,IAAI,GAAK,CACvD,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC,iBAAiB,CAAC,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { JSX } from 'react';
|
|
2
|
+
import type { ToolLabels } from '../core/tool-label';
|
|
3
|
+
import type { ToolStep } from '../core/turn';
|
|
4
|
+
export type ToolChipProps = {
|
|
5
|
+
step: ToolStep;
|
|
6
|
+
toolLabels?: ToolLabels;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* One tool call, as the small pill above an answer: `✓ Site status · 0.4s`.
|
|
10
|
+
*
|
|
11
|
+
* Showing tool activity is not decoration. Model routing is the weak point of
|
|
12
|
+
* the stack — a turn that answers without ever calling a tool is answering from
|
|
13
|
+
* the prompt, not from the fleet — so the chips are what make that visible
|
|
14
|
+
* instead of mysterious.
|
|
15
|
+
*/
|
|
16
|
+
declare const ToolChipView: ({ step, toolLabels }: ToolChipProps) => JSX.Element;
|
|
17
|
+
export declare const ToolChip: import("react").MemoExoticComponent<typeof ToolChipView>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=tool-chip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-chip.d.ts","sourceRoot":"","sources":["../../src/components/tool-chip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAGhC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAK5C,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,QAAQ,CAAA;IACd,UAAU,CAAC,EAAE,UAAU,CAAA;CACxB,CAAA;AAED;;;;;;;GAOG;AACH,QAAA,MAAM,YAAY,yBAA0B,aAAa,KAAG,GAAG,CAAC,OAiC/D,CAAA;AAED,eAAO,MAAM,QAAQ,0DAAqB,CAAA"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
import { formatDuration, toolLabel } from '../core/tool-label';
|
|
4
|
+
import { TOOL_STATUS } from '../core/turn';
|
|
5
|
+
import { CloseIcon, TickIcon, WarningIcon } from './icons';
|
|
6
|
+
/**
|
|
7
|
+
* One tool call, as the small pill above an answer: `✓ Site status · 0.4s`.
|
|
8
|
+
*
|
|
9
|
+
* Showing tool activity is not decoration. Model routing is the weak point of
|
|
10
|
+
* the stack — a turn that answers without ever calling a tool is answering from
|
|
11
|
+
* the prompt, not from the fleet — so the chips are what make that visible
|
|
12
|
+
* instead of mysterious.
|
|
13
|
+
*/
|
|
14
|
+
const ToolChipView = ({ step, toolLabels }) => {
|
|
15
|
+
const duration = formatDuration(step.durationMs);
|
|
16
|
+
const label = toolLabel(step.name, toolLabels);
|
|
17
|
+
const detail = step.status === TOOL_STATUS.AWAITING_APPROVAL
|
|
18
|
+
? 'awaiting approval'
|
|
19
|
+
: step.status === TOOL_STATUS.RUNNING
|
|
20
|
+
? 'running…'
|
|
21
|
+
: step.status === TOOL_STATUS.REJECTED
|
|
22
|
+
// Deliberately no duration: nothing ran, so there is nothing to time.
|
|
23
|
+
? 'not run'
|
|
24
|
+
// The turn ended before the result came back, so whether it ran is unknown
|
|
25
|
+
// — and the elapsed time would measure the failure, not the tool.
|
|
26
|
+
: step.status === TOOL_STATUS.INTERRUPTED
|
|
27
|
+
? 'no result'
|
|
28
|
+
: duration;
|
|
29
|
+
return (_jsxs("span", { className: `mdk-agent-tool-chip mdk-agent-tool-chip--${step.status}`, title: step.contractViolation ?? step.text ?? label, children: [_jsxs("span", { className: "mdk-agent-tool-chip__icon", "aria-hidden": "true", children: [step.status === TOOL_STATUS.OK ? _jsx(TickIcon, { size: 12 }) : null, step.status === TOOL_STATUS.ERROR ? _jsx(WarningIcon, { size: 12 }) : null, step.status === TOOL_STATUS.REJECTED ? _jsx(CloseIcon, { size: 12 }) : null, step.status === TOOL_STATUS.INTERRUPTED ? _jsx(WarningIcon, { size: 12 }) : null] }), _jsx("span", { className: "mdk-agent-tool-chip__label", children: label }), detail ? _jsx("span", { className: "mdk-agent-tool-chip__detail", children: `· ${detail}` }) : null] }));
|
|
30
|
+
};
|
|
31
|
+
export const ToolChip = memo(ToolChipView);
|
|
32
|
+
//# sourceMappingURL=tool-chip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-chip.js","sourceRoot":"","sources":["../../src/components/tool-chip.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAI5B,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAO1D;;;;;;;GAOG;AACH,MAAM,YAAY,GAAG,CAAC,EAAE,IAAI,EAAE,UAAU,EAAiB,EAAe,EAAE;IACxE,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAChD,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;IAE9C,MAAM,MAAM,GACR,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,iBAAiB;QAC7C,CAAC,CAAC,mBAAmB;QACrB,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,OAAO;YACnC,CAAC,CAAC,UAAU;YACZ,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,QAAQ;gBACpC,sEAAsE;gBACtE,CAAC,CAAC,SAAS;gBACX,2EAA2E;gBAC3E,kEAAkE;gBAClE,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,WAAW;oBACvC,CAAC,CAAC,WAAW;oBACb,CAAC,CAAC,QAAQ,CAAA;IAEpB,OAAO,CACL,gBACE,SAAS,EAAE,4CAA4C,IAAI,CAAC,MAAM,EAAE,EACpE,KAAK,EAAE,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,IAAI,IAAI,KAAK,aAEnD,gBAAM,SAAS,EAAC,2BAA2B,iBAAa,MAAM,aAC3D,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,KAAC,QAAQ,IAAC,IAAI,EAAE,EAAE,GAAI,CAAC,CAAC,CAAC,IAAI,EAC9D,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,KAAC,WAAW,IAAC,IAAI,EAAE,EAAE,GAAI,CAAC,CAAC,CAAC,IAAI,EACpE,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,GAAI,CAAC,CAAC,CAAC,IAAI,EACrE,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,KAAC,WAAW,IAAC,IAAI,EAAE,EAAE,GAAI,CAAC,CAAC,CAAC,IAAI,IACtE,EACP,eAAM,SAAS,EAAC,4BAA4B,YAAE,KAAK,GAAQ,EAC1D,MAAM,CAAC,CAAC,CAAC,eAAM,SAAS,EAAC,6BAA6B,YAAE,KAAK,MAAM,EAAE,GAAQ,CAAC,CAAC,CAAC,IAAI,IAChF,CACR,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { JSX } from 'react';
|
|
2
|
+
export type UserMessageProps = {
|
|
3
|
+
text: string;
|
|
4
|
+
};
|
|
5
|
+
/** Right-aligned operator turn: an `OPERATOR` caption above a bordered bubble. */
|
|
6
|
+
declare const UserMessageView: ({ text }: UserMessageProps) => JSX.Element;
|
|
7
|
+
export declare const UserMessage: import("react").MemoExoticComponent<typeof UserMessageView>;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=user-message.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-message.d.ts","sourceRoot":"","sources":["../../src/components/user-message.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAKhC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,kFAAkF;AAClF,QAAA,MAAM,eAAe,aAAc,gBAAgB,KAAG,GAAG,CAAC,OAKzD,CAAA;AAED,eAAO,MAAM,WAAW,6DAAwB,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
import { AGENT_LABELS } from '../branding';
|
|
4
|
+
/** Right-aligned operator turn: an `OPERATOR` caption above a bordered bubble. */
|
|
5
|
+
const UserMessageView = ({ text }) => (_jsxs("div", { className: "mdk-agent-message mdk-agent-message--user", children: [_jsx("p", { className: "mdk-agent-message__role", children: AGENT_LABELS.operator }), _jsx("div", { className: "mdk-agent-message__bubble", children: text })] }));
|
|
6
|
+
export const UserMessage = memo(UserMessageView);
|
|
7
|
+
//# sourceMappingURL=user-message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-message.js","sourceRoot":"","sources":["../../src/components/user-message.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAE5B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAM1C,kFAAkF;AAClF,MAAM,eAAe,GAAG,CAAC,EAAE,IAAI,EAAoB,EAAe,EAAE,CAAC,CACnE,eAAK,SAAS,EAAC,2CAA2C,aACxD,YAAG,SAAS,EAAC,yBAAyB,YAAE,YAAY,CAAC,QAAQ,GAAK,EAClE,cAAK,SAAS,EAAC,2BAA2B,YAAE,IAAI,GAAO,IACnD,CACP,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,CAAA"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversation history, persisted client-side.
|
|
3
|
+
*
|
|
4
|
+
* The gateway keeps sessions in an in-memory `Map` per process — no titles, no
|
|
5
|
+
* timestamps, no transcripts, and nothing survives a restart — and exposes no
|
|
6
|
+
* route to list them. So the Conversations view is backed from here instead.
|
|
7
|
+
*
|
|
8
|
+
* A stored `sessionId` is therefore a weak reference: it 404s after a gateway
|
|
9
|
+
* restart or once the agent's own 30-minute session TTL lapses. That is expected,
|
|
10
|
+
* not an error — the transcript still reads back, and the next message mints a
|
|
11
|
+
* fresh session (see `useAgentChat`).
|
|
12
|
+
*/
|
|
13
|
+
import type { StoreApi } from 'zustand/vanilla';
|
|
14
|
+
import type { ToolStep } from './turn';
|
|
15
|
+
export declare const CONVERSATION_STORAGE_KEY = "mdk-ui-agent:conversations:v1";
|
|
16
|
+
/** Keeps localStorage bounded. The oldest conversations fall off the end. */
|
|
17
|
+
export declare const MAX_CONVERSATIONS = 50;
|
|
18
|
+
/** Mirrors the agent's own per-session ceiling in `backend/core/agent/src/session-store.js`. */
|
|
19
|
+
export declare const MAX_MESSAGES_PER_CONVERSATION = 200;
|
|
20
|
+
/**
|
|
21
|
+
* How much of a tool result is kept in storage.
|
|
22
|
+
*
|
|
23
|
+
* A `list_devices` result is the whole fleet serialized, and it is written again on
|
|
24
|
+
* every subsequent change. The full text stays in memory for the session — this is
|
|
25
|
+
* only what survives a reload, where the chip's tooltip is a convenience and the
|
|
26
|
+
* quota is not. Mirrors `HISTORY_RESULT_CHARS` in the producer's own transcript.
|
|
27
|
+
*/
|
|
28
|
+
export declare const MAX_PERSISTED_TOOL_TEXT_CHARS = 400;
|
|
29
|
+
export declare const MESSAGE_ROLE: {
|
|
30
|
+
readonly USER: 'user';
|
|
31
|
+
readonly ASSISTANT: 'assistant';
|
|
32
|
+
/** Not from the model: something the panel itself has to tell the operator. */
|
|
33
|
+
readonly SYSTEM: 'system';
|
|
34
|
+
};
|
|
35
|
+
export type MessageRole = (typeof MESSAGE_ROLE)[keyof typeof MESSAGE_ROLE];
|
|
36
|
+
export type ChatMessage = {
|
|
37
|
+
id: string;
|
|
38
|
+
role: MessageRole;
|
|
39
|
+
text: string;
|
|
40
|
+
at: number;
|
|
41
|
+
/** Assistant only: the tool chips for this turn, in call order. */
|
|
42
|
+
tools?: ToolStep[];
|
|
43
|
+
/** Assistant only: set when the turn ended on an `error` event. Raw `ERR_*` codes included. */
|
|
44
|
+
error?: string | null;
|
|
45
|
+
/**
|
|
46
|
+
* Assistant only: the turn was stopped before it finished — by the operator, or
|
|
47
|
+
* by the panel unmounting. Whatever streamed is kept, but it is not the whole
|
|
48
|
+
* answer and must not read back as one.
|
|
49
|
+
*/
|
|
50
|
+
interrupted?: boolean;
|
|
51
|
+
};
|
|
52
|
+
export type Conversation = {
|
|
53
|
+
id: string;
|
|
54
|
+
title: string;
|
|
55
|
+
/** Null until the first turn creates one, or after a stale one is discarded. */
|
|
56
|
+
sessionId: string | null;
|
|
57
|
+
messages: ChatMessage[];
|
|
58
|
+
createdAt: number;
|
|
59
|
+
updatedAt: number;
|
|
60
|
+
};
|
|
61
|
+
export type ConversationState = {
|
|
62
|
+
conversations: Conversation[];
|
|
63
|
+
activeId: string | null;
|
|
64
|
+
};
|
|
65
|
+
export type ConversationActions = {
|
|
66
|
+
create: (id?: string, at?: number) => string;
|
|
67
|
+
select: (id: string) => void;
|
|
68
|
+
remove: (id: string) => void;
|
|
69
|
+
setSessionId: (id: string, sessionId: string | null) => void;
|
|
70
|
+
appendMessage: (id: string, message: ChatMessage) => void;
|
|
71
|
+
updateMessage: (id: string, messageId: string, patch: Partial<ChatMessage>) => void;
|
|
72
|
+
reset: () => void;
|
|
73
|
+
};
|
|
74
|
+
export type ConversationStore = ConversationState & ConversationActions;
|
|
75
|
+
export type ConversationStorage = Pick<Storage, 'getItem' | 'setItem'>;
|
|
76
|
+
export type ConversationStoreOptions = {
|
|
77
|
+
storageKey?: string;
|
|
78
|
+
/** Pass `null` to disable persistence entirely (tests, SSR). */
|
|
79
|
+
storage?: ConversationStorage | null;
|
|
80
|
+
};
|
|
81
|
+
/** First line of the first user message, which is what the design lists. */
|
|
82
|
+
export declare function deriveTitle(text: string, max?: number): string;
|
|
83
|
+
export declare function newConversation(id: string, at: number): Conversation;
|
|
84
|
+
/**
|
|
85
|
+
* Reconciles this tab's conversations with what another tab has just written.
|
|
86
|
+
*
|
|
87
|
+
* Union by id, newer `updatedAt` wins. Without it the last tab to act overwrites
|
|
88
|
+
* the other's turns with its own staler snapshot — and since the gateway keeps no
|
|
89
|
+
* history, that is permanent loss rather than a cache miss.
|
|
90
|
+
*
|
|
91
|
+
* The trade-off is deliberate: a conversation deleted in one tab can come back
|
|
92
|
+
* from the other tab's copy, because "absent" and "never seen" are the same thing
|
|
93
|
+
* in a union. Resurrecting a transcript is the recoverable direction; losing one
|
|
94
|
+
* is not.
|
|
95
|
+
*/
|
|
96
|
+
export declare function mergeConversations(mine: Conversation[], theirs: Conversation[]): Conversation[];
|
|
97
|
+
/**
|
|
98
|
+
* Factory for an isolated conversation store. Tests and SSR should use this;
|
|
99
|
+
* runtime code binds to the singleton {@link conversationStore}.
|
|
100
|
+
*/
|
|
101
|
+
export declare function createConversationStore(options?: ConversationStoreOptions): StoreApi<ConversationStore>;
|
|
102
|
+
/**
|
|
103
|
+
* Module-level singleton holding every conversation the operator has had in this
|
|
104
|
+
* browser. React subscribers bind to it through `useConversations`.
|
|
105
|
+
*/
|
|
106
|
+
export declare const conversationStore: StoreApi<ConversationStore>;
|
|
107
|
+
//# sourceMappingURL=conversation-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-store.d.ts","sourceRoot":"","sources":["../../src/core/conversation-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversation history, persisted client-side.
|
|
3
|
+
*
|
|
4
|
+
* The gateway keeps sessions in an in-memory `Map` per process — no titles, no
|
|
5
|
+
* timestamps, no transcripts, and nothing survives a restart — and exposes no
|
|
6
|
+
* route to list them. So the Conversations view is backed from here instead.
|
|
7
|
+
*
|
|
8
|
+
* A stored `sessionId` is therefore a weak reference: it 404s after a gateway
|
|
9
|
+
* restart or once the agent's own 30-minute session TTL lapses. That is expected,
|
|
10
|
+
* not an error — the transcript still reads back, and the next message mints a
|
|
11
|
+
* fresh session (see `useAgentChat`).
|
|
12
|
+
*/
|
|
13
|
+
import { createStore } from 'zustand/vanilla';
|
|
14
|
+
import { uuid } from './uuid';
|
|
15
|
+
export const CONVERSATION_STORAGE_KEY = 'mdk-ui-agent:conversations:v1';
|
|
16
|
+
/** Keeps localStorage bounded. The oldest conversations fall off the end. */
|
|
17
|
+
export const MAX_CONVERSATIONS = 50;
|
|
18
|
+
/** Mirrors the agent's own per-session ceiling in `backend/core/agent/src/session-store.js`. */
|
|
19
|
+
export const MAX_MESSAGES_PER_CONVERSATION = 200;
|
|
20
|
+
/**
|
|
21
|
+
* How much of a tool result is kept in storage.
|
|
22
|
+
*
|
|
23
|
+
* A `list_devices` result is the whole fleet serialized, and it is written again on
|
|
24
|
+
* every subsequent change. The full text stays in memory for the session — this is
|
|
25
|
+
* only what survives a reload, where the chip's tooltip is a convenience and the
|
|
26
|
+
* quota is not. Mirrors `HISTORY_RESULT_CHARS` in the producer's own transcript.
|
|
27
|
+
*/
|
|
28
|
+
export const MAX_PERSISTED_TOOL_TEXT_CHARS = 400;
|
|
29
|
+
export const MESSAGE_ROLE = {
|
|
30
|
+
USER: 'user',
|
|
31
|
+
ASSISTANT: 'assistant',
|
|
32
|
+
/** Not from the model: something the panel itself has to tell the operator. */
|
|
33
|
+
SYSTEM: 'system',
|
|
34
|
+
};
|
|
35
|
+
const initialState = { conversations: [], activeId: null };
|
|
36
|
+
/**
|
|
37
|
+
* `localStorage` throws on access in some privacy modes and does not exist
|
|
38
|
+
* outside the browser, so it is probed rather than assumed.
|
|
39
|
+
*/
|
|
40
|
+
function defaultStorage() {
|
|
41
|
+
try {
|
|
42
|
+
return globalThis.localStorage ?? null;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** First line of the first user message, which is what the design lists. */
|
|
49
|
+
export function deriveTitle(text, max = 48) {
|
|
50
|
+
const line = text.trim().split('\n')[0]?.trim() ?? '';
|
|
51
|
+
if (line.length === 0)
|
|
52
|
+
return 'New conversation';
|
|
53
|
+
return line.length <= max ? line : `${line.slice(0, max - 1).trimEnd()}…`;
|
|
54
|
+
}
|
|
55
|
+
export function newConversation(id, at) {
|
|
56
|
+
return { id, title: 'New conversation', sessionId: null, messages: [], createdAt: at, updatedAt: at };
|
|
57
|
+
}
|
|
58
|
+
function isConversation(value) {
|
|
59
|
+
if (typeof value !== 'object' || value === null)
|
|
60
|
+
return false;
|
|
61
|
+
const candidate = value;
|
|
62
|
+
return typeof candidate.id === 'string' && Array.isArray(candidate.messages);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Anything unreadable is discarded rather than repaired: the stored shape can
|
|
66
|
+
* predate a release, and losing local history is a far better failure than
|
|
67
|
+
* booting the panel into a broken state.
|
|
68
|
+
*/
|
|
69
|
+
function readPersisted(storage, key) {
|
|
70
|
+
if (!storage)
|
|
71
|
+
return initialState;
|
|
72
|
+
try {
|
|
73
|
+
const raw = storage.getItem(key);
|
|
74
|
+
if (!raw)
|
|
75
|
+
return initialState;
|
|
76
|
+
const parsed = JSON.parse(raw);
|
|
77
|
+
const conversations = Array.isArray(parsed.conversations)
|
|
78
|
+
? parsed.conversations.filter(isConversation)
|
|
79
|
+
: [];
|
|
80
|
+
const activeId = typeof parsed.activeId === 'string'
|
|
81
|
+
&& conversations.some((conversation) => conversation.id === parsed.activeId)
|
|
82
|
+
? parsed.activeId
|
|
83
|
+
: null;
|
|
84
|
+
return { conversations, activeId };
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return initialState;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/** Keeps a full fleet dump out of every write. The in-memory copy is untouched. */
|
|
91
|
+
function trimForStorage(conversation) {
|
|
92
|
+
if (!conversation.messages.some((message) => message.tools?.length))
|
|
93
|
+
return conversation;
|
|
94
|
+
return {
|
|
95
|
+
...conversation,
|
|
96
|
+
messages: conversation.messages.map((message) => message.tools?.length
|
|
97
|
+
? {
|
|
98
|
+
...message,
|
|
99
|
+
tools: message.tools.map((step) => step.text === undefined || step.text.length <= MAX_PERSISTED_TOOL_TEXT_CHARS
|
|
100
|
+
? step
|
|
101
|
+
: { ...step, text: `${step.text.slice(0, MAX_PERSISTED_TOOL_TEXT_CHARS)}…` }),
|
|
102
|
+
}
|
|
103
|
+
: message),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function serialize(state) {
|
|
107
|
+
return JSON.stringify({
|
|
108
|
+
conversations: state.conversations.map(trimForStorage),
|
|
109
|
+
activeId: state.activeId,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
function writePersisted(storage, key, payload) {
|
|
113
|
+
if (!storage)
|
|
114
|
+
return;
|
|
115
|
+
try {
|
|
116
|
+
storage.setItem(key, payload);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// Quota exceeded or storage disabled mid-session. History is a convenience,
|
|
120
|
+
// never a correctness requirement, so the live conversation continues.
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function touch(conversation, at) {
|
|
124
|
+
return { ...conversation, updatedAt: at };
|
|
125
|
+
}
|
|
126
|
+
/** Newest first, capped — the order the Conversations view renders. */
|
|
127
|
+
function sortAndCap(conversations) {
|
|
128
|
+
return [...conversations].sort((a, b) => b.updatedAt - a.updatedAt).slice(0, MAX_CONVERSATIONS);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Reconciles this tab's conversations with what another tab has just written.
|
|
132
|
+
*
|
|
133
|
+
* Union by id, newer `updatedAt` wins. Without it the last tab to act overwrites
|
|
134
|
+
* the other's turns with its own staler snapshot — and since the gateway keeps no
|
|
135
|
+
* history, that is permanent loss rather than a cache miss.
|
|
136
|
+
*
|
|
137
|
+
* The trade-off is deliberate: a conversation deleted in one tab can come back
|
|
138
|
+
* from the other tab's copy, because "absent" and "never seen" are the same thing
|
|
139
|
+
* in a union. Resurrecting a transcript is the recoverable direction; losing one
|
|
140
|
+
* is not.
|
|
141
|
+
*/
|
|
142
|
+
export function mergeConversations(mine, theirs) {
|
|
143
|
+
const byId = new Map(mine.map((conversation) => [conversation.id, conversation]));
|
|
144
|
+
for (const other of theirs) {
|
|
145
|
+
const own = byId.get(other.id);
|
|
146
|
+
if (!own || other.updatedAt > own.updatedAt)
|
|
147
|
+
byId.set(other.id, other);
|
|
148
|
+
}
|
|
149
|
+
return sortAndCap([...byId.values()]);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Factory for an isolated conversation store. Tests and SSR should use this;
|
|
153
|
+
* runtime code binds to the singleton {@link conversationStore}.
|
|
154
|
+
*/
|
|
155
|
+
export function createConversationStore(options = {}) {
|
|
156
|
+
const key = options.storageKey ?? CONVERSATION_STORAGE_KEY;
|
|
157
|
+
const storage = options.storage === undefined ? defaultStorage() : options.storage;
|
|
158
|
+
const store = createStore((set, get) => ({
|
|
159
|
+
...readPersisted(storage, key),
|
|
160
|
+
create: (id, at) => {
|
|
161
|
+
const conversationId = id ?? uuid();
|
|
162
|
+
const createdAt = at ?? Date.now();
|
|
163
|
+
set((state) => ({
|
|
164
|
+
conversations: sortAndCap([newConversation(conversationId, createdAt), ...state.conversations]),
|
|
165
|
+
activeId: conversationId,
|
|
166
|
+
}));
|
|
167
|
+
return conversationId;
|
|
168
|
+
},
|
|
169
|
+
select: (id) => {
|
|
170
|
+
if (!get().conversations.some((conversation) => conversation.id === id))
|
|
171
|
+
return;
|
|
172
|
+
set({ activeId: id });
|
|
173
|
+
},
|
|
174
|
+
remove: (id) => {
|
|
175
|
+
set((state) => {
|
|
176
|
+
const conversations = state.conversations.filter((conversation) => conversation.id !== id);
|
|
177
|
+
return {
|
|
178
|
+
conversations,
|
|
179
|
+
activeId: state.activeId === id ? (conversations[0]?.id ?? null) : state.activeId,
|
|
180
|
+
};
|
|
181
|
+
});
|
|
182
|
+
},
|
|
183
|
+
setSessionId: (id, sessionId) => {
|
|
184
|
+
set((state) => ({
|
|
185
|
+
conversations: state.conversations.map((conversation) => conversation.id === id ? { ...conversation, sessionId } : conversation),
|
|
186
|
+
}));
|
|
187
|
+
},
|
|
188
|
+
appendMessage: (id, message) => {
|
|
189
|
+
set((state) => ({
|
|
190
|
+
conversations: sortAndCap(state.conversations.map((conversation) => {
|
|
191
|
+
if (conversation.id !== id)
|
|
192
|
+
return conversation;
|
|
193
|
+
const messages = [...conversation.messages, message].slice(-MAX_MESSAGES_PER_CONVERSATION);
|
|
194
|
+
const title = conversation.messages.length === 0 && message.role === MESSAGE_ROLE.USER
|
|
195
|
+
? deriveTitle(message.text)
|
|
196
|
+
: conversation.title;
|
|
197
|
+
return touch({ ...conversation, messages, title }, message.at);
|
|
198
|
+
})),
|
|
199
|
+
}));
|
|
200
|
+
},
|
|
201
|
+
updateMessage: (id, messageId, patch) => {
|
|
202
|
+
set((state) => ({
|
|
203
|
+
conversations: state.conversations.map((conversation) => {
|
|
204
|
+
if (conversation.id !== id)
|
|
205
|
+
return conversation;
|
|
206
|
+
return {
|
|
207
|
+
...conversation,
|
|
208
|
+
messages: conversation.messages.map((message) => message.id === messageId ? { ...message, ...patch } : message),
|
|
209
|
+
};
|
|
210
|
+
}),
|
|
211
|
+
}));
|
|
212
|
+
},
|
|
213
|
+
reset: () => set({ ...initialState }),
|
|
214
|
+
}));
|
|
215
|
+
// The last payload written or read, so an unchanged state is not written again —
|
|
216
|
+
// and, with the cross-tab listener below, so two tabs cannot ping-pong identical
|
|
217
|
+
// writes at each other forever.
|
|
218
|
+
let persisted = serialize(store.getState());
|
|
219
|
+
store.subscribe((state) => {
|
|
220
|
+
const payload = serialize(state);
|
|
221
|
+
if (payload === persisted)
|
|
222
|
+
return;
|
|
223
|
+
persisted = payload;
|
|
224
|
+
writePersisted(storage, key, payload);
|
|
225
|
+
});
|
|
226
|
+
/**
|
|
227
|
+
* Another tab wrote the same key: merge its conversations in rather than letting
|
|
228
|
+
* whichever tab acts last overwrite the other.
|
|
229
|
+
*
|
|
230
|
+
* Only wired up for real `localStorage`, because the `storage` event describes
|
|
231
|
+
* nothing else — an injected storage (tests, SSR) has no cross-tab notion at all.
|
|
232
|
+
*/
|
|
233
|
+
if (storage && storage === globalThis.localStorage && typeof globalThis.addEventListener === 'function') {
|
|
234
|
+
globalThis.addEventListener('storage', (event) => {
|
|
235
|
+
if (event.storageArea && event.storageArea !== globalThis.localStorage)
|
|
236
|
+
return;
|
|
237
|
+
// A null key is `localStorage.clear()`, which drops ours too.
|
|
238
|
+
if (event.key !== null && event.key !== key)
|
|
239
|
+
return;
|
|
240
|
+
const external = readPersisted(storage, key);
|
|
241
|
+
const merged = mergeConversations(store.getState().conversations, external.conversations);
|
|
242
|
+
persisted = serialize({ conversations: merged, activeId: store.getState().activeId });
|
|
243
|
+
// The other tab's `activeId` is about its own window, so ours is kept.
|
|
244
|
+
store.setState({ conversations: merged });
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
return store;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Module-level singleton holding every conversation the operator has had in this
|
|
251
|
+
* browser. React subscribers bind to it through `useConversations`.
|
|
252
|
+
*/
|
|
253
|
+
export const conversationStore = createConversationStore();
|
|
254
|
+
//# sourceMappingURL=conversation-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-store.js","sourceRoot":"","sources":["../../src/core/conversation-store.ts"],"names":[],"mappings":"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"}
|