@agentshouse/mdruntime 0.1.0-cd3486bd400ed → 0.1.0-cde2b99d2fcbc
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/AGENTS.md +70 -42
- package/README.md +11 -2
- package/dist/adapter.d.ts +34 -11
- package/dist/adapter.d.ts.map +1 -1
- package/dist/binary.d.ts +23 -0
- package/dist/binary.d.ts.map +1 -0
- package/dist/binary.js +8 -0
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +5 -8
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +8 -7
- package/dist/change.d.ts +11 -0
- package/dist/change.d.ts.map +1 -1
- package/dist/change.js +26 -1
- package/dist/chat/context.d.ts +3 -0
- package/dist/chat/context.d.ts.map +1 -0
- package/dist/chat/context.js +10 -0
- package/dist/chat/input.d.ts +9 -0
- package/dist/chat/input.d.ts.map +1 -0
- package/dist/chat/input.js +99 -0
- package/dist/chat/kit.d.ts +60 -0
- package/dist/chat/kit.d.ts.map +1 -0
- package/dist/chat/kit.js +123 -0
- package/dist/chat/lasting.d.ts +6 -0
- package/dist/chat/lasting.d.ts.map +1 -0
- package/dist/chat/lasting.js +19 -0
- package/dist/chat/list.d.ts +20 -0
- package/dist/chat/list.d.ts.map +1 -0
- package/dist/chat/list.js +59 -0
- package/dist/chat/markdown.d.ts +19 -0
- package/dist/chat/markdown.d.ts.map +1 -0
- package/dist/chat/markdown.js +187 -0
- package/dist/chat/message.d.ts +6 -0
- package/dist/chat/message.d.ts.map +1 -0
- package/dist/chat/message.js +192 -0
- package/dist/chat/name.d.ts +6 -0
- package/dist/chat/name.d.ts.map +1 -0
- package/dist/chat/name.js +37 -0
- package/dist/chat/opened.d.ts +11 -0
- package/dist/chat/opened.d.ts.map +1 -0
- package/dist/chat/opened.js +17 -0
- package/dist/chat/provider.d.ts +6 -0
- package/dist/chat/provider.d.ts.map +1 -1
- package/dist/chat/provider.js +9 -1
- package/dist/chat/question.d.ts +9 -0
- package/dist/chat/question.d.ts.map +1 -0
- package/dist/chat/question.js +80 -0
- package/dist/chat/ready.d.ts +33 -0
- package/dist/chat/ready.d.ts.map +1 -0
- package/dist/chat/ready.js +91 -0
- package/dist/chat/style.d.ts +4 -0
- package/dist/chat/style.d.ts.map +1 -0
- package/dist/chat/style.js +302 -0
- package/dist/chat.d.ts +7 -0
- package/dist/chat.d.ts.map +1 -1
- package/dist/chat.js +6 -0
- package/dist/client.d.ts +7 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +10 -0
- package/dist/connection.d.ts +9 -4
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +184 -15
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +4 -0
- package/dist/identity.d.ts +1 -0
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +3 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/memory.d.ts +3 -3
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +31 -11
- package/dist/outcome.d.ts +7 -1
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +6 -0
- package/dist/overlay.d.ts +13 -2
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +56 -22
- package/dist/query.d.ts +2 -0
- package/dist/query.d.ts.map +1 -1
- package/dist/reach.d.ts +2 -0
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +23 -1
- package/dist/read-side.d.ts.map +1 -1
- package/dist/read-side.js +9 -2
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +12 -17
- package/dist/replica.d.ts +5 -2
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +43 -27
- package/dist/room-draft.d.ts +19 -2
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +119 -1
- package/dist/rows.d.ts +3 -1
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +3 -1
- package/dist/save.d.ts +24 -0
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +304 -14
- package/dist/store.d.ts +6 -7
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +79 -91
- package/dist/wire.d.ts +2 -0
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +2 -0
- package/package.json +11 -3
- package/dist/attachment.d.ts +0 -3
- package/dist/attachment.d.ts.map +0 -1
- package/dist/attachment.js +0 -8
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, } from 'react';
|
|
3
|
+
import { ActionBarPrimitive, AuiIf, ErrorPrimitive, MessagePartPrimitive, MessagePrimitive, groupPartByType, useAuiState, } from '@assistant-ui/react';
|
|
4
|
+
import { MarkdownTextPrimitive } from '@assistant-ui/react-markdown';
|
|
5
|
+
import { Collapsible } from 'radix-ui';
|
|
6
|
+
import remarkGfm from 'remark-gfm';
|
|
7
|
+
import Bot from 'lucide-react/dist/esm/icons/bot.mjs';
|
|
8
|
+
import Brain from 'lucide-react/dist/esm/icons/brain.mjs';
|
|
9
|
+
import CalendarClock from 'lucide-react/dist/esm/icons/calendar-clock.mjs';
|
|
10
|
+
import Check from 'lucide-react/dist/esm/icons/check.mjs';
|
|
11
|
+
import ChevronRight from 'lucide-react/dist/esm/icons/chevron-right.mjs';
|
|
12
|
+
import Copy from 'lucide-react/dist/esm/icons/copy.mjs';
|
|
13
|
+
import Cpu from 'lucide-react/dist/esm/icons/cpu.mjs';
|
|
14
|
+
import ImageGlyph from 'lucide-react/dist/esm/icons/image.mjs';
|
|
15
|
+
import Layers from 'lucide-react/dist/esm/icons/layers.mjs';
|
|
16
|
+
import ListChecks from 'lucide-react/dist/esm/icons/list-checks.mjs';
|
|
17
|
+
import ListTodo from 'lucide-react/dist/esm/icons/list-todo.mjs';
|
|
18
|
+
import Paperclip from 'lucide-react/dist/esm/icons/paperclip.mjs';
|
|
19
|
+
import RotateCw from 'lucide-react/dist/esm/icons/rotate-cw.mjs';
|
|
20
|
+
import Send from 'lucide-react/dist/esm/icons/send.mjs';
|
|
21
|
+
import SlidersHorizontal from 'lucide-react/dist/esm/icons/sliders-horizontal.mjs';
|
|
22
|
+
import Terminal from 'lucide-react/dist/esm/icons/terminal.mjs';
|
|
23
|
+
import { buttonClass, Name, Working } from './kit.js';
|
|
24
|
+
import { StillRunning } from './lasting.js';
|
|
25
|
+
import { list, record, text } from './read.js';
|
|
26
|
+
export const Linked = createContext(null);
|
|
27
|
+
const groupBy = groupPartByType({
|
|
28
|
+
reasoning: ['group-thought', 'group-reasoning'],
|
|
29
|
+
'tool-call': ['group-thought'],
|
|
30
|
+
});
|
|
31
|
+
const GFM = [remarkGfm];
|
|
32
|
+
const STARTED = 'Session started';
|
|
33
|
+
const SENT = {
|
|
34
|
+
send_routine_request: 'Sent a request',
|
|
35
|
+
cancel_routine_request: 'Cancelled a request',
|
|
36
|
+
};
|
|
37
|
+
const MARKED = {
|
|
38
|
+
mode: { title: 'Mode', Icon: SlidersHorizontal },
|
|
39
|
+
compaction: { title: 'Context compacted', Icon: Layers },
|
|
40
|
+
retry: { title: 'Retrying', Icon: RotateCw },
|
|
41
|
+
model: { title: 'Model', Icon: Cpu },
|
|
42
|
+
};
|
|
43
|
+
const STEP = { completed: '✓', in_progress: '→' };
|
|
44
|
+
function counted(count) {
|
|
45
|
+
return count === 1 ? '1 command' : `${count} commands`;
|
|
46
|
+
}
|
|
47
|
+
function jobShown(said) {
|
|
48
|
+
const icon = _jsx(CalendarClock, { "aria-hidden": "true" });
|
|
49
|
+
const shown = { icon, input: '', output: '' };
|
|
50
|
+
const label = said('label');
|
|
51
|
+
const state = said('state');
|
|
52
|
+
if (said('job') === 'started') {
|
|
53
|
+
return { ...shown, title: 'Background job started', detail: label };
|
|
54
|
+
}
|
|
55
|
+
if (said('job') === 'scheduled') {
|
|
56
|
+
const detail = said('next') === '' ? label : `${label} · ${state}`;
|
|
57
|
+
return { ...shown, title: 'Schedule set', detail };
|
|
58
|
+
}
|
|
59
|
+
const detail = state === '' ? label : `${label} · ${state}`;
|
|
60
|
+
return { ...shown, title: 'Background job ended', detail };
|
|
61
|
+
}
|
|
62
|
+
function shownOf({ toolName, args, result }) {
|
|
63
|
+
const said = (key) => text(args, key) ?? '';
|
|
64
|
+
const plain = { detail: '', input: '', output: '' };
|
|
65
|
+
switch (toolName) {
|
|
66
|
+
case 'subagent':
|
|
67
|
+
return {
|
|
68
|
+
icon: _jsx(Bot, { "aria-hidden": "true" }),
|
|
69
|
+
title: 'Sub-agent',
|
|
70
|
+
detail: said('description'),
|
|
71
|
+
input: said('description'),
|
|
72
|
+
output: typeof result === 'string' ? result : '',
|
|
73
|
+
};
|
|
74
|
+
case 'message':
|
|
75
|
+
return {
|
|
76
|
+
...plain,
|
|
77
|
+
icon: _jsx(Send, { "aria-hidden": "true" }),
|
|
78
|
+
title: SENT[said('command')] ?? said('command'),
|
|
79
|
+
detail: said('target'),
|
|
80
|
+
};
|
|
81
|
+
case 'plan': {
|
|
82
|
+
const steps = list(args, 'steps').map(record);
|
|
83
|
+
return {
|
|
84
|
+
...plain,
|
|
85
|
+
icon: _jsx(ListTodo, { "aria-hidden": "true" }),
|
|
86
|
+
title: 'Plan',
|
|
87
|
+
detail: text(steps.find((one) => one.status === 'in_progress') ?? {}, 'content') ?? '',
|
|
88
|
+
input: steps
|
|
89
|
+
.map((one) => `${STEP[text(one, 'status') ?? ''] ?? '○'} ${text(one, 'content') ?? ''}`)
|
|
90
|
+
.join('\n'),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
case 'marker': {
|
|
94
|
+
const marked = MARKED[said('marker')];
|
|
95
|
+
if (marked === undefined)
|
|
96
|
+
return jobShown(said);
|
|
97
|
+
return {
|
|
98
|
+
...plain,
|
|
99
|
+
icon: _jsx(marked.Icon, { "aria-hidden": "true" }),
|
|
100
|
+
title: marked.title,
|
|
101
|
+
detail: said('text'),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
default:
|
|
105
|
+
return {
|
|
106
|
+
...plain,
|
|
107
|
+
icon: _jsx(Terminal, { "aria-hidden": "true" }),
|
|
108
|
+
title: counted(Number(args.count)),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function workedOf(calls) {
|
|
113
|
+
const commands = calls.reduce((sum, one) => (one.toolName === 'commands' ? sum + Number(one.args.count) : sum), 0);
|
|
114
|
+
return commands === 0 ? 'Worked' : `Worked · ${counted(commands)}`;
|
|
115
|
+
}
|
|
116
|
+
function Toggle({ icon, label, detail = '', active, children, }) {
|
|
117
|
+
return (_jsxs(Collapsible.Root, { children: [_jsxs(Collapsible.Trigger, { className: "ahc-row ahc-toggle", children: [icon, _jsx("span", { className: active ? 'ahc-clipped ahc-shimmer' : 'ahc-clipped', children: label }), detail === '' ? null : _jsx("span", { className: "ahc-clipped", children: detail }), _jsx("span", { className: "ahc-chevron", children: _jsx(ChevronRight, { "aria-hidden": "true" }) })] }), _jsx(Collapsible.Content, { children: children })] }));
|
|
118
|
+
}
|
|
119
|
+
function ToolCall({ call, active }) {
|
|
120
|
+
const shown = shownOf(call);
|
|
121
|
+
if (shown.input === '' && shown.output === '') {
|
|
122
|
+
return (_jsxs("div", { className: "ahc-toolline ahc-quiet", children: [shown.icon, _jsx("span", { className: active ? 'ahc-shimmer' : undefined, children: shown.title }), shown.detail === '' ? null : _jsx("span", { className: "ahc-clipped", children: shown.detail })] }));
|
|
123
|
+
}
|
|
124
|
+
return (_jsx(Toggle, { icon: shown.icon, label: shown.title, detail: shown.detail, active: active, children: _jsxs("div", { className: "ahc-quiet ahc-wells", children: [shown.input === '' ? null : _jsx("div", { className: "ahc-well", children: shown.input }), shown.output === '' ? null : _jsx("div", { className: "ahc-well", children: shown.output })] }) }));
|
|
125
|
+
}
|
|
126
|
+
function Thought({ indices, active, children, }) {
|
|
127
|
+
const parts = useAuiState((s) => s.message.parts);
|
|
128
|
+
const held = indices.flatMap((at) => parts[at] ?? []);
|
|
129
|
+
const calls = held.flatMap((part) => (part.type === 'tool-call' ? [part] : []));
|
|
130
|
+
if (calls.length === 0 || held.length === 1)
|
|
131
|
+
return _jsx(_Fragment, { children: children });
|
|
132
|
+
const last = held.at(-1);
|
|
133
|
+
const now = last?.type === 'tool-call'
|
|
134
|
+
? shownOf(last)
|
|
135
|
+
: { icon: _jsx(Brain, { "aria-hidden": "true" }), title: 'Thinking', detail: '' };
|
|
136
|
+
return (_jsx(Toggle, { icon: active ? now.icon : _jsx(ListChecks, { "aria-hidden": "true" }), label: active ? now.title : workedOf(calls), detail: active ? now.detail : '', active: active, children: children }));
|
|
137
|
+
}
|
|
138
|
+
const SCHEME = /^[a-z][a-z0-9+.-]*:/i;
|
|
139
|
+
function Anchor({ node: _node, href = '', ...rest }) {
|
|
140
|
+
const onLink = useContext(Linked);
|
|
141
|
+
if (SCHEME.test(href) || onLink === null)
|
|
142
|
+
return _jsx("a", { ...rest, href: href, rel: "noreferrer" });
|
|
143
|
+
return (_jsx("a", { ...rest, href: href, onClick: (event) => {
|
|
144
|
+
event.preventDefault();
|
|
145
|
+
onLink(href);
|
|
146
|
+
} }));
|
|
147
|
+
}
|
|
148
|
+
const LINKED = { a: Anchor };
|
|
149
|
+
const THOUGHT = { className: 'ahc-thought' };
|
|
150
|
+
function Said({ thought = false }) {
|
|
151
|
+
return (_jsx(MarkdownTextPrimitive, { className: "ahc-text ahc-markdown", containerProps: thought ? THOUGHT : undefined, remarkPlugins: GFM, components: LINKED }));
|
|
152
|
+
}
|
|
153
|
+
function UserText() {
|
|
154
|
+
return _jsx(MessagePartPrimitive.Text, { className: "ahc-said" });
|
|
155
|
+
}
|
|
156
|
+
export function UserMessage() {
|
|
157
|
+
const said = useAuiState((s) => s.message.parts.some((one) => one.type === 'text' && one.text !== ''));
|
|
158
|
+
const attached = useAuiState((s) => (s.message.attachments?.length ?? 0) > 0);
|
|
159
|
+
const undelivered = useAuiState((s) => s.message.metadata.custom.undelivered === true);
|
|
160
|
+
return (_jsxs(MessagePrimitive.Root, { role: "group", "aria-label": "You", className: "ahc-you", children: [said ? (_jsx("div", { className: "ahc-bubble", children: _jsx(MessagePrimitive.Parts, { components: { Text: UserText } }) })) : null, attached ? (_jsx("div", { className: "ahc-chips", children: _jsx(MessagePrimitive.Attachments, { children: ({ attachment }) => (_jsxs("span", { className: "ahc-chip", children: [_jsx(Paperclip, { "aria-hidden": "true" }), _jsx(Name, { text: attachment.name })] })) }) })) : null, undelivered ? _jsx(Undelivered, {}) : null] }));
|
|
161
|
+
}
|
|
162
|
+
export function Undelivered() {
|
|
163
|
+
return _jsx("span", { className: "ahc-meta", children: "Telegram didn't receive this" });
|
|
164
|
+
}
|
|
165
|
+
export function AssistantMessage() {
|
|
166
|
+
const running = useAuiState((s) => s.message.status?.type === 'running');
|
|
167
|
+
const started = useAuiState((s) => s.message.metadata.isOptimistic !== true);
|
|
168
|
+
const said = useAuiState((s) => s.message.parts.some((one) => one.type === 'text'));
|
|
169
|
+
const last = useAuiState((s) => s.message.isLast);
|
|
170
|
+
const custom = useAuiState((s) => s.message.metadata.custom);
|
|
171
|
+
const lasting = Array.isArray(custom.lasting) ? custom.lasting : [];
|
|
172
|
+
return (_jsxs(MessagePrimitive.Root, { role: "group", "aria-label": running ? 'Turn, running' : 'Turn', className: "ahc-turn", children: [_jsx(MessagePrimitive.GroupedParts, { groupBy: groupBy, indicator: "empty", children: ({ part, children }) => {
|
|
173
|
+
switch (part.type) {
|
|
174
|
+
case 'group-thought':
|
|
175
|
+
return (_jsx(Thought, { indices: part.indices, active: part.status.type === 'running', children: children }));
|
|
176
|
+
case 'group-reasoning':
|
|
177
|
+
return (_jsx(Toggle, { icon: _jsx(Brain, { "aria-hidden": "true" }), label: "Thinking", active: part.status.type === 'running', children: children }));
|
|
178
|
+
case 'text':
|
|
179
|
+
return _jsx(Said, {});
|
|
180
|
+
case 'reasoning':
|
|
181
|
+
return _jsx(Said, { thought: true });
|
|
182
|
+
case 'tool-call':
|
|
183
|
+
return _jsx(ToolCall, { call: part, active: part.status.type === 'running' });
|
|
184
|
+
case 'file':
|
|
185
|
+
return (_jsxs("div", { className: "ahc-toolline ahc-quiet", children: [_jsx(ImageGlyph, { "aria-hidden": "true" }), _jsx("span", { className: "ahc-clipped", children: part.filename })] }));
|
|
186
|
+
case 'indicator':
|
|
187
|
+
return _jsx(Working, { step: started ? STARTED : undefined });
|
|
188
|
+
default:
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
} }), _jsx(MessagePrimitive.Error, { children: _jsxs(ErrorPrimitive.Root, { className: "ahc-failure", children: [_jsx(ErrorPrimitive.Message, {}), _jsx(AuiIf, { condition: (s) => s.thread.capabilities.reload && s.message.metadata.custom.again === true, children: _jsx(ActionBarPrimitive.Reload, { className: buttonClass('outline', true, false), children: "Try again" }) })] }) }), custom.undelivered === true ? _jsx(Undelivered, {}) : null, said ? (_jsx(ActionBarPrimitive.Root, { hideWhenRunning: true, autohide: "not-last", autohideFloat: "always", className: last ? 'ahc-actions' : 'ahc-actions ahc-actions--floating', children: _jsxs(ActionBarPrimitive.Copy, { className: `${buttonClass('quiet', true, true)} ahc-secondary`, "aria-label": "Copy", children: [_jsx(AuiIf, { condition: (s) => s.message.isCopied, children: _jsx(Check, { "aria-hidden": "true" }) }), _jsx(AuiIf, { condition: (s) => !s.message.isCopied, children: _jsx(Copy, { "aria-hidden": "true" }) })] }) })) : null, lasting.length === 0 ? null : _jsx(StillRunning, { lasting: lasting })] }));
|
|
192
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"name.d.ts","sourceRoot":"","sources":["../../src/chat/name.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAgC1C,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI7C;AAED,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAc1E"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
const INSTANT = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:\d{2})/g;
|
|
3
|
+
function stamp(at) {
|
|
4
|
+
const time = new Date(at);
|
|
5
|
+
return Number.isNaN(time.getTime())
|
|
6
|
+
? ''
|
|
7
|
+
: time.toLocaleString('en-US', {
|
|
8
|
+
month: 'short',
|
|
9
|
+
day: 'numeric',
|
|
10
|
+
hour: '2-digit',
|
|
11
|
+
minute: '2-digit',
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
function partsOf(name) {
|
|
15
|
+
const parts = [];
|
|
16
|
+
let from = 0;
|
|
17
|
+
for (const found of name.matchAll(INSTANT)) {
|
|
18
|
+
const shown = stamp(found[0]);
|
|
19
|
+
if (shown === '')
|
|
20
|
+
continue;
|
|
21
|
+
if (found.index > from)
|
|
22
|
+
parts.push({ text: name.slice(from, found.index), at: null });
|
|
23
|
+
parts.push({ text: shown, at: found[0] });
|
|
24
|
+
from = found.index + found[0].length;
|
|
25
|
+
}
|
|
26
|
+
if (from < name.length)
|
|
27
|
+
parts.push({ text: name.slice(from), at: null });
|
|
28
|
+
return parts;
|
|
29
|
+
}
|
|
30
|
+
export function readable(name) {
|
|
31
|
+
return partsOf(name)
|
|
32
|
+
.map((part) => part.text)
|
|
33
|
+
.join('');
|
|
34
|
+
}
|
|
35
|
+
export function ChatName({ name }) {
|
|
36
|
+
return (_jsx(_Fragment, { children: partsOf(name).map((part, at) => part.at === null ? (part.text) : (_jsx("time", { dateTime: part.at, children: part.text }, at))) }));
|
|
37
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ConversationEntry } from '../conversation.js';
|
|
2
|
+
import { type ChatState } from './provider.js';
|
|
3
|
+
export type Opened = ChatState & {
|
|
4
|
+
readonly entry: ConversationEntry | undefined;
|
|
5
|
+
readonly by: string | null;
|
|
6
|
+
readonly name: string;
|
|
7
|
+
readonly deleted: boolean;
|
|
8
|
+
readonly busy: boolean;
|
|
9
|
+
};
|
|
10
|
+
export declare function useOpened(): Opened;
|
|
11
|
+
//# sourceMappingURL=opened.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opened.d.ts","sourceRoot":"","sources":["../../src/chat/opened.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAyB,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAEtE,MAAM,MAAM,MAAM,GAAG,SAAS,GAAG;IAC/B,QAAQ,CAAC,KAAK,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,wBAAgB,SAAS,IAAI,MAAM,CAelC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useChat, useChatScope } from './provider.js';
|
|
2
|
+
export function useOpened() {
|
|
3
|
+
const chat = useChat();
|
|
4
|
+
const { known } = useChatScope();
|
|
5
|
+
const entry = chat.conversations.find((one) => one.conversation === chat.conversation);
|
|
6
|
+
const by = entry?.agent.identity ?? chat.agent;
|
|
7
|
+
const live = chat.agents.find((one) => one.identity === by);
|
|
8
|
+
const asks = chat.view?.process?.running === true && chat.questions.length > 0;
|
|
9
|
+
return {
|
|
10
|
+
...chat,
|
|
11
|
+
entry,
|
|
12
|
+
by,
|
|
13
|
+
name: live?.name ?? entry?.agent.name ?? '',
|
|
14
|
+
deleted: known && chat.conversation !== null && by !== null && live === undefined,
|
|
15
|
+
busy: chat.running || asks,
|
|
16
|
+
};
|
|
17
|
+
}
|
package/dist/chat/provider.d.ts
CHANGED
|
@@ -52,6 +52,12 @@ export type ChatProviderProps = {
|
|
|
52
52
|
readonly onOpen?: (opened: ChatOpened) => void;
|
|
53
53
|
readonly children?: ReactNode;
|
|
54
54
|
};
|
|
55
|
+
type Scope = {
|
|
56
|
+
readonly client: MdRuntimeClient;
|
|
57
|
+
readonly known: boolean;
|
|
58
|
+
};
|
|
59
|
+
export declare function useChatScope(): Scope;
|
|
55
60
|
export declare function useChat(): ChatState;
|
|
56
61
|
export declare function ChatProvider({ client, conversation, agent, onOpen, children, }: ChatProviderProps): ReactElement;
|
|
62
|
+
export {};
|
|
57
63
|
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/chat/provider.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/chat/provider.ts"],"names":[],"mappings":"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"}
|
package/dist/chat/provider.js
CHANGED
|
@@ -173,6 +173,13 @@ function composed(state) {
|
|
|
173
173
|
return JSON.stringify([state.text, state.attachments.map((one) => one.id)]);
|
|
174
174
|
}
|
|
175
175
|
const ChatContext = createContext(null);
|
|
176
|
+
const ScopeContext = createContext(null);
|
|
177
|
+
export function useChatScope() {
|
|
178
|
+
const scope = useContext(ScopeContext);
|
|
179
|
+
if (scope === null)
|
|
180
|
+
throw new Error('useChat is called outside a ChatProvider');
|
|
181
|
+
return scope;
|
|
182
|
+
}
|
|
176
183
|
export function useChat() {
|
|
177
184
|
const chat = useContext(ChatContext);
|
|
178
185
|
if (chat === null)
|
|
@@ -633,5 +640,6 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
633
640
|
unqueue(id);
|
|
634
641
|
},
|
|
635
642
|
};
|
|
636
|
-
|
|
643
|
+
const scope = useMemo(() => ({ client, known: agentsHeld !== null }), [client, agentsHeld]);
|
|
644
|
+
return createElement(AssistantRuntimeProvider, { runtime: aui }, createElement(ScopeContext.Provider, { value: scope }, createElement(ChatContext.Provider, { value: chat }, children)));
|
|
637
645
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ReactElement } from 'react';
|
|
2
|
+
import { type MdRuntimeClient } from '../client.js';
|
|
3
|
+
import type { ChatQuestion } from './questions.js';
|
|
4
|
+
export declare function forgetAnswers(client: MdRuntimeClient, conversation: string, interaction?: string): Promise<void>;
|
|
5
|
+
export type ChatQuestionCardProps = {
|
|
6
|
+
readonly question: ChatQuestion;
|
|
7
|
+
};
|
|
8
|
+
export declare function ChatQuestionCard({ question }: ChatQuestionCardProps): ReactElement;
|
|
9
|
+
//# sourceMappingURL=question.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"question.d.ts","sourceRoot":"","sources":["../../src/chat/question.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAGhE,OAAO,EAAU,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAM5D,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAoB9D,wBAAgB,aAAa,CAC3B,MAAM,EAAE,eAAe,EACvB,YAAY,EAAE,MAAM,EACpB,WAAW,SAAK,GACf,OAAO,CAAC,IAAI,CAAC,CAQf;AAeD,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;CACjC,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,EAAE,qBAAqB,GAAG,YAAY,CAmHlF"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useContext, useState } from 'react';
|
|
3
|
+
import Check from 'lucide-react/dist/esm/icons/check.mjs';
|
|
4
|
+
import CircleHelp from 'lucide-react/dist/esm/icons/circle-help.mjs';
|
|
5
|
+
import { inTurn } from '../client.js';
|
|
6
|
+
import { useObserve } from '../react.js';
|
|
7
|
+
import { Button, Scoped } from './kit.js';
|
|
8
|
+
import { Markdown } from './markdown.js';
|
|
9
|
+
import { Linked, Undelivered } from './message.js';
|
|
10
|
+
import { useChat, useChatScope } from './provider.js';
|
|
11
|
+
import { record, text } from './read.js';
|
|
12
|
+
const TYPED = 'typed';
|
|
13
|
+
function answerKey(conversation, interaction) {
|
|
14
|
+
return `answer:${conversation}:${interaction}`;
|
|
15
|
+
}
|
|
16
|
+
function changeTyped(client, update) {
|
|
17
|
+
return inTurn(client, async () => {
|
|
18
|
+
const held = record(await client.presentation.read());
|
|
19
|
+
const typed = update(record(held[TYPED]));
|
|
20
|
+
if (typed !== null)
|
|
21
|
+
await client.presentation.write({ ...held, [TYPED]: typed });
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
export function forgetAnswers(client, conversation, interaction = '') {
|
|
25
|
+
const at = answerKey(conversation, interaction);
|
|
26
|
+
return changeTyped(client, (typed) => {
|
|
27
|
+
const kept = Object.entries(typed).filter(([key]) => interaction === '' ? !key.startsWith(at) : key !== at);
|
|
28
|
+
return kept.length === Object.keys(typed).length ? null : Object.fromEntries(kept);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function useTyped(client, key) {
|
|
32
|
+
const held = useObserve(client, 'presentation');
|
|
33
|
+
const kept = record(record(record(held.state === 'ready' ? held.value : null)[TYPED])[key]);
|
|
34
|
+
const [local, setLocal] = useState(null);
|
|
35
|
+
return [
|
|
36
|
+
local !== null && local.key === key ? local.value : kept,
|
|
37
|
+
(next) => {
|
|
38
|
+
setLocal({ key, value: next });
|
|
39
|
+
void changeTyped(client, (typed) => ({ ...typed, [key]: next }));
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
}
|
|
43
|
+
export function ChatQuestionCard({ question }) {
|
|
44
|
+
const chat = useChat();
|
|
45
|
+
const { client } = useChatScope();
|
|
46
|
+
const onLink = useContext(Linked);
|
|
47
|
+
const conversation = chat.conversation ?? '';
|
|
48
|
+
const [values, setValues] = useTyped(client, answerKey(conversation, question.interaction));
|
|
49
|
+
const lone = chat.lone?.question.interaction === question.interaction;
|
|
50
|
+
const reply = (response) => void chat.answer(question, response).then((answered) => {
|
|
51
|
+
if (answered)
|
|
52
|
+
void forgetAnswers(client, conversation, question.interaction);
|
|
53
|
+
});
|
|
54
|
+
const single = question.fields.length === 1;
|
|
55
|
+
const answers = !question.secret && !(single && question.fields[0]?.kind !== 'multi-select');
|
|
56
|
+
const declines = !question.secret && question.decline !== null;
|
|
57
|
+
const pick = (field, value) => {
|
|
58
|
+
if (single && field.kind !== 'multi-select') {
|
|
59
|
+
reply(question.accept({ [field.name]: value }));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (field.kind !== 'multi-select') {
|
|
63
|
+
setValues({ ...values, [field.name]: value });
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const held = Array.isArray(values[field.name]) ? values[field.name] : [];
|
|
67
|
+
setValues({
|
|
68
|
+
...values,
|
|
69
|
+
[field.name]: held.includes(value) ? held.filter((one) => one !== value) : [...held, value],
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
const chosen = (field, value) => {
|
|
73
|
+
const held = values[field.name];
|
|
74
|
+
return Array.isArray(held) ? held.includes(value) : held === value;
|
|
75
|
+
};
|
|
76
|
+
const option = (field, value, label, about, at) => (_jsxs("button", { type: "button", className: "ahc-option", "aria-pressed": chosen(field, value), onClick: () => pick(field, value), children: [_jsx("span", { className: "ahc-option__key", "aria-hidden": "true", children: at + 1 }), _jsxs("span", { className: "ahc-option__body", children: [_jsx("span", { className: "ahc-option__label", children: label }), about === null ? null : _jsx("span", { className: "ahc-option__note", children: about })] }), chosen(field, value) ? _jsx(Check, { size: 20, "aria-hidden": "true" }) : null] }, label));
|
|
77
|
+
return (_jsx(Scoped, { children: _jsxs("section", { className: "ahc-question", "aria-label": "Question", children: [_jsxs("div", { className: "ahc-question__head", children: [_jsxs("span", { className: "ahc-chip ahc-chip--attention", children: [_jsx(CircleHelp, { "aria-hidden": "true" }), "Needs your answer"] }), question.message === '' ? null : (_jsx(Markdown, { text: question.message, className: "ahc-question__text ahc-markdown", ...(onLink === null ? {} : { onLink }) }))] }), question.secret
|
|
78
|
+
? null
|
|
79
|
+
: question.fields.map((field) => (_jsxs("div", { className: "ahc-field", children: [_jsx("p", { className: "ahc-question__text", children: field.prompt }), field.about === null ? null : (_jsx("span", { className: "ahc-option__note", children: field.about })), field.kind === 'boolean' ? (_jsxs(_Fragment, { children: [option(field, true, 'Yes', null, 0), option(field, false, 'No', null, 1)] })) : field.choices.length > 0 ? (field.choices.map((one, at) => option(field, one.value, one.label, one.about, at))) : lone ? (_jsx("span", { className: "ahc-option__note", children: "Answer it below." })) : (_jsx("input", { className: "ahc-input", "aria-label": field.prompt, inputMode: field.kind === 'string' ? 'text' : 'numeric', value: text(values, field.name) ?? '', onChange: (event) => setValues({ ...values, [field.name]: event.target.value }) }))] }, field.name))), question.undelivered ? _jsx(Undelivered, {}) : null, answers || declines ? (_jsxs("div", { className: "ahc-row-of", children: [answers ? (_jsx(Button, { variant: "ink", onClick: () => reply(question.accept(values)), children: "Answer" })) : null, declines ? _jsx(Button, { onClick: () => reply(question.decline), children: "Decline" }) : null] })) : null] }) }));
|
|
80
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type CSSProperties, type ReactElement, type ReactNode } from 'react';
|
|
2
|
+
import type { MdRuntimeClient } from '../client.js';
|
|
3
|
+
import { type ChatNoteProps } from './kit.js';
|
|
4
|
+
import { type AgentLook } from './list.js';
|
|
5
|
+
import { type ChatOpened, type ChatState } from './provider.js';
|
|
6
|
+
export type ChatWidth = 'full' | '3/4' | '1/2' | '1/3';
|
|
7
|
+
export type ChatProps = AgentLook & {
|
|
8
|
+
readonly client?: MdRuntimeClient;
|
|
9
|
+
readonly conversation?: string | null;
|
|
10
|
+
readonly agent?: string | null;
|
|
11
|
+
readonly onOpen?: (opened: ChatOpened) => void;
|
|
12
|
+
readonly width?: ChatWidth;
|
|
13
|
+
readonly showChats?: boolean;
|
|
14
|
+
readonly className?: string;
|
|
15
|
+
readonly style?: CSSProperties;
|
|
16
|
+
readonly onLink?: (href: string) => void;
|
|
17
|
+
readonly about?: (chat: ChatState) => ReactNode;
|
|
18
|
+
readonly actions?: ReactNode;
|
|
19
|
+
readonly note?: (note: ChatNoteProps) => ReactNode;
|
|
20
|
+
readonly messageLength?: number;
|
|
21
|
+
readonly autoFocus?: boolean;
|
|
22
|
+
};
|
|
23
|
+
export declare function Chat({ client, conversation, agent, onOpen, ...look }: ChatProps): ReactElement;
|
|
24
|
+
export type MountedChat = {
|
|
25
|
+
update(props: ChatProps & {
|
|
26
|
+
readonly client: MdRuntimeClient;
|
|
27
|
+
}): void;
|
|
28
|
+
unmount(): void;
|
|
29
|
+
};
|
|
30
|
+
export declare function mountChat(element: Element, props: ChatProps & {
|
|
31
|
+
readonly client: MdRuntimeClient;
|
|
32
|
+
}): MountedChat;
|
|
33
|
+
//# sourceMappingURL=ready.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ready.d.ts","sourceRoot":"","sources":["../../src/chat/ready.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAUf,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGpD,OAAO,EASL,KAAK,aAAa,EACnB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAwC,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAGjF,OAAO,EAA8B,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAI5F,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAEvD,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAC/C,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,SAAS,CAAC;IAChD,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,SAAS,CAAC;IACnD,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAgQF,wBAAgB,IAAI,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,EAAE,SAAS,GAAG,YAAY,CAY9F;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG;QAAE,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAA;KAAE,GAAG,IAAI,CAAC;IACtE,OAAO,IAAI,IAAI,CAAC;CACjB,CAAC;AAEF,wBAAgB,SAAS,CACvB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,SAAS,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAA;CAAE,GACtD,WAAW,CAOb"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useContext, useEffect, useState, } from 'react';
|
|
3
|
+
import { createRoot } from 'react-dom/client';
|
|
4
|
+
import Check from 'lucide-react/dist/esm/icons/check.mjs';
|
|
5
|
+
import CircleStop from 'lucide-react/dist/esm/icons/circle-stop.mjs';
|
|
6
|
+
import Ellipsis from 'lucide-react/dist/esm/icons/ellipsis.mjs';
|
|
7
|
+
import Info from 'lucide-react/dist/esm/icons/info.mjs';
|
|
8
|
+
import MessagesSquare from 'lucide-react/dist/esm/icons/messages-square.mjs';
|
|
9
|
+
import OctagonX from 'lucide-react/dist/esm/icons/octagon-x.mjs';
|
|
10
|
+
import Pencil from 'lucide-react/dist/esm/icons/pencil.mjs';
|
|
11
|
+
import Trash2 from 'lucide-react/dist/esm/icons/trash-2.mjs';
|
|
12
|
+
import { ChatInput } from './input.js';
|
|
13
|
+
import { Button, Confirm, IconButton, Menu, MenuGap, MenuItem, Name, Within, } from './kit.js';
|
|
14
|
+
import { ChatList, ChatMessageList, Described } from './list.js';
|
|
15
|
+
import { readable } from './name.js';
|
|
16
|
+
import { useOpened } from './opened.js';
|
|
17
|
+
import { ChatProvider, useChatScope } from './provider.js';
|
|
18
|
+
import { forgetAnswers } from './question.js';
|
|
19
|
+
import { adopted } from './style.js';
|
|
20
|
+
function Title({ name, renaming, onRename, onDone, }) {
|
|
21
|
+
const [next, setNext] = useState(name);
|
|
22
|
+
if (!renaming)
|
|
23
|
+
return _jsx("h1", { className: "ahc-title", children: name });
|
|
24
|
+
const finish = () => {
|
|
25
|
+
const kept = next.trim();
|
|
26
|
+
onDone();
|
|
27
|
+
if (kept !== '' && kept !== name)
|
|
28
|
+
onRename(kept);
|
|
29
|
+
};
|
|
30
|
+
return (_jsx("input", { className: "ahc-input ahc-rename", "aria-label": "Chat name", autoFocus: true, value: next, onFocus: (event) => event.currentTarget.select(), onChange: (event) => setNext(event.target.value), onBlur: finish, onKeyDown: (event) => {
|
|
31
|
+
if (event.key === 'Enter')
|
|
32
|
+
event.currentTarget.blur();
|
|
33
|
+
if (event.key === 'Escape')
|
|
34
|
+
onDone();
|
|
35
|
+
} }));
|
|
36
|
+
}
|
|
37
|
+
function Head({ about, actions, listing, }) {
|
|
38
|
+
const chat = useOpened();
|
|
39
|
+
const { client } = useChatScope();
|
|
40
|
+
const { agentMark } = useContext(Described);
|
|
41
|
+
const fresh = chat.conversation === null;
|
|
42
|
+
const [named, setNamed] = useState(chat.entry);
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
if (chat.entry !== undefined)
|
|
45
|
+
setNamed(chat.entry);
|
|
46
|
+
}, [chat.entry]);
|
|
47
|
+
const entry = chat.entry ?? named;
|
|
48
|
+
const name = fresh ? 'New chat' : readable(entry?.name ?? chat.name);
|
|
49
|
+
const [asking, setAsking] = useState(null);
|
|
50
|
+
const [renaming, setRenaming] = useState(false);
|
|
51
|
+
const forgotten = (ended) => {
|
|
52
|
+
if (ended && chat.conversation !== null)
|
|
53
|
+
void forgetAnswers(client, chat.conversation);
|
|
54
|
+
};
|
|
55
|
+
const line = about?.(chat) ??
|
|
56
|
+
(chat.deleted ? (_jsx(Name, { text: `${chat.name}, deleted · read only`, className: "ahc-head__line" })) : (_jsx(Name, { text: [chat.name, chat.view?.process?.running === false ? 'not running' : null]
|
|
57
|
+
.filter(Boolean)
|
|
58
|
+
.join(' · '), className: "ahc-head__line" })));
|
|
59
|
+
return (_jsxs("div", { className: "ahc-head", children: [_jsxs("div", { className: "ahc-head__column", children: [listing === null ? null : (_jsx("span", { className: "ahc-list-toggle", children: _jsx(IconButton, { label: "Chats", onClick: listing, children: _jsx(MessagesSquare, { size: 20, "aria-hidden": "true" }) }) })), chat.by === null ? null : agentMark?.(chat.by, 20), _jsxs("div", { className: "ahc-head__names", children: [_jsx(Title, { name: name, renaming: renaming, onRename: (next) => void chat.rename(next), onDone: () => setRenaming(false) }, name), line] }), fresh ? null : chat.deleted ? (_jsx(Button, { variant: "danger-outline", onClick: () => setAsking('delete'), children: "Delete chat\u2026" })) : (_jsxs(_Fragment, { children: [actions, _jsxs(Menu, { trigger: _jsx(IconButton, { label: "Conversation options", children: _jsx(Ellipsis, { size: 20, "aria-hidden": "true" }) }), children: [_jsx(MenuItem, { icon: _jsx(Check, { "aria-hidden": "true" }), onSelect: () => void chat.done(), children: "Done" }), _jsx(MenuItem, { icon: _jsx(Pencil, { "aria-hidden": "true" }), onSelect: () => setRenaming(true), children: "Rename" }), chat.busy ? (_jsxs(_Fragment, { children: [_jsx(MenuItem, { icon: _jsx(CircleStop, { "aria-hidden": "true" }), onSelect: () => void chat.stop().then(forgotten), children: "Stop" }), _jsx(MenuItem, { icon: _jsx(OctagonX, { "aria-hidden": "true" }), onSelect: () => setAsking('kill'), children: "Kill\u2026" })] })) : null, _jsx(MenuGap, {}), _jsx(MenuItem, { icon: _jsx(Trash2, { "aria-hidden": "true" }), danger: true, onSelect: () => setAsking('delete'), children: "Delete chat\u2026" })] })] }))] }), asking === 'delete' ? (_jsx(Confirm, { title: "Delete this chat?", text: `“${name}” is deleted from House with its history. Files ${chat.name} wrote stay in their Rooms.`, action: "Delete chat", onConfirm: () => void chat.remove(), onClose: () => setAsking(null) })) : null, asking === 'kill' ? (_jsx(Confirm, { title: `Kill ${chat.name}’s process?`, text: "Stop asks the turn to end. Kill ends the process at once, and nothing after its last saved step is kept.", action: "Kill", onConfirm: () => void chat.kill().then(forgotten), onClose: () => setAsking(null) })) : null] }));
|
|
60
|
+
}
|
|
61
|
+
function Deleted() {
|
|
62
|
+
const chat = useOpened();
|
|
63
|
+
return (_jsx("div", { className: "ahc-deleted", children: _jsxs("div", { role: "note", className: "ahc-column ahc-deleted__note", children: [_jsx("span", { className: "ahc-deleted__icon", children: _jsx(Info, { "aria-hidden": "true" }) }), _jsx("span", { children: `${chat.name} was deleted. Its chats stay here for you to read or delete.` })] }) }));
|
|
64
|
+
}
|
|
65
|
+
function Frame({ showChats, onLink, about, actions, note, messageLength, autoFocus, }) {
|
|
66
|
+
const chat = useOpened();
|
|
67
|
+
const [listed, setListed] = useState(false);
|
|
68
|
+
const thread = chat.conversation ?? `new:${chat.agent ?? ''}`;
|
|
69
|
+
return (_jsxs("div", { className: "ahc-frame", children: [showChats === true ? (_jsx("div", { className: "ahc-side", "data-open": listed ? '' : undefined, children: _jsx(ChatList, { onChoose: () => setListed(false) }) })) : null, _jsxs("div", { className: "ahc-pane", children: [_jsx(Head, { about: about, actions: actions, listing: showChats === true ? () => setListed((open) => !open) : null }, thread), chat.deleted ? _jsx(Deleted, {}) : null, _jsx(ChatMessageList, { ...(onLink === undefined ? {} : { onLink }), footer: _jsx(ChatInput, { ...(messageLength === undefined ? {} : { messageLength }), ...(note === undefined ? {} : { note }), autoFocus: autoFocus === true }) })] })] }));
|
|
70
|
+
}
|
|
71
|
+
function Ready({ width = 'full', className, style, agentMark, agentDetail, ...rest }) {
|
|
72
|
+
const [root, setRoot] = useState(null);
|
|
73
|
+
const attach = useCallback((element) => {
|
|
74
|
+
adopted(element);
|
|
75
|
+
setRoot(element);
|
|
76
|
+
}, []);
|
|
77
|
+
return (_jsx("div", { ref: attach, className: className === undefined ? 'ahc ahc-chat' : `ahc ahc-chat ${className}`, "data-width": width, style: style, children: root === null ? null : (_jsx(Within, { root: root, children: _jsx(Described.Provider, { value: { agentMark, agentDetail }, children: _jsx(Frame, { ...rest }) }) })) }));
|
|
78
|
+
}
|
|
79
|
+
export function Chat({ client, conversation, agent, onOpen, ...look }) {
|
|
80
|
+
if (client === undefined)
|
|
81
|
+
return _jsx(Ready, { ...look });
|
|
82
|
+
return (_jsx(ChatProvider, { client: client, ...(conversation === undefined ? {} : { conversation }), ...(agent === undefined ? {} : { agent }), ...(onOpen === undefined ? {} : { onOpen }), children: _jsx(Ready, { ...look }) }));
|
|
83
|
+
}
|
|
84
|
+
export function mountChat(element, props) {
|
|
85
|
+
const root = createRoot(element);
|
|
86
|
+
root.render(_jsx(Chat, { ...props }));
|
|
87
|
+
return {
|
|
88
|
+
update: (next) => root.render(_jsx(Chat, { ...next })),
|
|
89
|
+
unmount: () => root.unmount(),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../src/chat/style.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,MAAM,CAAC;AAEnC,eAAO,MAAM,kBAAkB,QAAsB,CAAC;AA2StD,wBAAgB,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CASrD"}
|