@corenel/web-ui 0.13.3 → 0.14.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/Composer.d.ts +30 -1
- package/dist/Composer.d.ts.map +1 -1
- package/dist/Composer.js +111 -19
- package/dist/Composer.js.map +1 -1
- package/dist/ContextBar.d.ts +9 -3
- package/dist/ContextBar.d.ts.map +1 -1
- package/dist/ContextBar.js +14 -7
- package/dist/ContextBar.js.map +1 -1
- package/dist/ContextManager.d.ts +10 -2
- package/dist/ContextManager.d.ts.map +1 -1
- package/dist/ContextManager.js +14 -10
- package/dist/ContextManager.js.map +1 -1
- package/dist/DictateButton.d.ts +21 -1
- package/dist/DictateButton.d.ts.map +1 -1
- package/dist/DictateButton.js +73 -10
- package/dist/DictateButton.js.map +1 -1
- package/dist/PickChips.d.ts +6 -0
- package/dist/PickChips.d.ts.map +1 -0
- package/dist/PickChips.js +55 -0
- package/dist/PickChips.js.map +1 -0
- package/dist/ProcessDock.d.ts +10 -0
- package/dist/ProcessDock.d.ts.map +1 -1
- package/dist/ProcessDock.js +24 -1
- package/dist/ProcessDock.js.map +1 -1
- package/dist/RichContent.d.ts.map +1 -1
- package/dist/RichContent.js +102 -24
- package/dist/RichContent.js.map +1 -1
- package/dist/SummaryTranscript.d.ts +5 -1
- package/dist/SummaryTranscript.d.ts.map +1 -1
- package/dist/SummaryTranscript.js +5 -3
- package/dist/SummaryTranscript.js.map +1 -1
- package/dist/TodoBar.d.ts +2 -0
- package/dist/TodoBar.d.ts.map +1 -1
- package/dist/TodoBar.js +8 -0
- package/dist/TodoBar.js.map +1 -1
- package/dist/TodoLine.d.ts +11 -0
- package/dist/TodoLine.d.ts.map +1 -0
- package/dist/TodoLine.js +55 -0
- package/dist/TodoLine.js.map +1 -0
- package/dist/ToolFold.js +1 -1
- package/dist/ToolFold.js.map +1 -1
- package/dist/Transcript.d.ts +19 -1
- package/dist/Transcript.d.ts.map +1 -1
- package/dist/Transcript.js +127 -58
- package/dist/Transcript.js.map +1 -1
- package/dist/agentChat/AgentChat.d.ts +42 -0
- package/dist/agentChat/AgentChat.d.ts.map +1 -1
- package/dist/agentChat/AgentChat.js +573 -100
- package/dist/agentChat/AgentChat.js.map +1 -1
- package/dist/agentChat/ChatSettingsSheet.d.ts +9 -0
- package/dist/agentChat/ChatSettingsSheet.d.ts.map +1 -0
- package/dist/agentChat/ChatSettingsSheet.js +103 -0
- package/dist/agentChat/ChatSettingsSheet.js.map +1 -0
- package/dist/agentChat/OptionsDrawer.d.ts +8 -0
- package/dist/agentChat/OptionsDrawer.d.ts.map +1 -1
- package/dist/agentChat/OptionsDrawer.js +24 -215
- package/dist/agentChat/OptionsDrawer.js.map +1 -1
- package/dist/agentChat/PlanReview.d.ts +1 -1
- package/dist/agentChat/PlanReview.d.ts.map +1 -1
- package/dist/agentChat/PlanReview.js +1 -1
- package/dist/agentChat/PlanReview.js.map +1 -1
- package/dist/agentChat/SourceGroups.d.ts +24 -0
- package/dist/agentChat/SourceGroups.d.ts.map +1 -0
- package/dist/agentChat/SourceGroups.js +117 -0
- package/dist/agentChat/SourceGroups.js.map +1 -0
- package/dist/agentChat/controller.d.ts +30 -1
- package/dist/agentChat/controller.d.ts.map +1 -1
- package/dist/agentChat/controller.js.map +1 -1
- package/dist/agentChat/pendingQueue.d.ts +4 -0
- package/dist/agentChat/pendingQueue.d.ts.map +1 -1
- package/dist/agentChat/pendingQueue.js +7 -0
- package/dist/agentChat/pendingQueue.js.map +1 -1
- package/dist/agentChat/planTool.d.ts +4 -0
- package/dist/agentChat/planTool.d.ts.map +1 -0
- package/dist/agentChat/planTool.js +4 -0
- package/dist/agentChat/planTool.js.map +1 -0
- package/dist/agentChat/testSheetHost.d.ts +3 -0
- package/dist/agentChat/testSheetHost.d.ts.map +1 -0
- package/dist/agentChat/testSheetHost.js +9 -0
- package/dist/agentChat/testSheetHost.js.map +1 -0
- package/dist/agentChat/useChatOptions.d.ts +63 -0
- package/dist/agentChat/useChatOptions.d.ts.map +1 -0
- package/dist/agentChat/useChatOptions.js +156 -0
- package/dist/agentChat/useChatOptions.js.map +1 -0
- package/dist/chatRefreshContext.d.ts +8 -0
- package/dist/chatRefreshContext.d.ts.map +1 -0
- package/dist/chatRefreshContext.js +14 -0
- package/dist/chatRefreshContext.js.map +1 -0
- package/dist/chatSkinContext.d.ts +13 -6
- package/dist/chatSkinContext.d.ts.map +1 -1
- package/dist/chatSkinContext.js +18 -4
- package/dist/chatSkinContext.js.map +1 -1
- package/dist/chatSkinCss.d.ts.map +1 -1
- package/dist/chatSkinCss.js +108 -22
- package/dist/chatSkinCss.js.map +1 -1
- package/dist/composerAction.d.ts +16 -0
- package/dist/composerAction.d.ts.map +1 -0
- package/dist/composerAction.js +20 -0
- package/dist/composerAction.js.map +1 -0
- package/dist/composerHistory.d.ts.map +1 -1
- package/dist/composerHistory.js +4 -1
- package/dist/composerHistory.js.map +1 -1
- package/dist/fx/LiveAnswer.d.ts.map +1 -1
- package/dist/fx/LiveAnswer.js +324 -59
- package/dist/fx/LiveAnswer.js.map +1 -1
- package/dist/fx/arrivalModes.d.ts +17 -2
- package/dist/fx/arrivalModes.d.ts.map +1 -1
- package/dist/fx/arrivalModes.js +46 -4
- package/dist/fx/arrivalModes.js.map +1 -1
- package/dist/fx/pacer.d.ts +41 -0
- package/dist/fx/pacer.d.ts.map +1 -0
- package/dist/fx/pacer.js +66 -0
- package/dist/fx/pacer.js.map +1 -0
- package/dist/fx/useReveal.d.ts +16 -1
- package/dist/fx/useReveal.d.ts.map +1 -1
- package/dist/fx/useReveal.js +101 -41
- package/dist/fx/useReveal.js.map +1 -1
- package/dist/localAddress.d.ts +2 -0
- package/dist/localAddress.d.ts.map +1 -0
- package/dist/localAddress.js +56 -0
- package/dist/localAddress.js.map +1 -0
- package/dist/steps/AfterReply.d.ts +67 -0
- package/dist/steps/AfterReply.d.ts.map +1 -0
- package/dist/steps/AfterReply.js +217 -0
- package/dist/steps/AfterReply.js.map +1 -0
- package/dist/steps/ChatApproval.d.ts +18 -0
- package/dist/steps/ChatApproval.d.ts.map +1 -0
- package/dist/steps/ChatApproval.js +35 -0
- package/dist/steps/ChatApproval.js.map +1 -0
- package/dist/steps/Delegation.d.ts +77 -0
- package/dist/steps/Delegation.d.ts.map +1 -0
- package/dist/steps/Delegation.js +188 -0
- package/dist/steps/Delegation.js.map +1 -0
- package/dist/steps/LiveRail.d.ts +14 -0
- package/dist/steps/LiveRail.d.ts.map +1 -0
- package/dist/steps/LiveRail.js +16 -0
- package/dist/steps/LiveRail.js.map +1 -0
- package/dist/steps/StepDetail.d.ts +23 -0
- package/dist/steps/StepDetail.d.ts.map +1 -0
- package/dist/steps/StepDetail.js +195 -0
- package/dist/steps/StepDetail.js.map +1 -0
- package/dist/steps/StepDetailHost.d.ts +54 -0
- package/dist/steps/StepDetailHost.d.ts.map +1 -0
- package/dist/steps/StepDetailHost.js +175 -0
- package/dist/steps/StepDetailHost.js.map +1 -0
- package/dist/steps/StepRail.d.ts +38 -0
- package/dist/steps/StepRail.d.ts.map +1 -0
- package/dist/steps/StepRail.js +238 -0
- package/dist/steps/StepRail.js.map +1 -0
- package/dist/steps/approval.d.ts +73 -0
- package/dist/steps/approval.d.ts.map +1 -0
- package/dist/steps/approval.js +81 -0
- package/dist/steps/approval.js.map +1 -0
- package/dist/steps/model.d.ts +140 -0
- package/dist/steps/model.d.ts.map +1 -0
- package/dist/steps/model.js +433 -0
- package/dist/steps/model.js.map +1 -0
- package/dist/steps/outcome.d.ts +5 -0
- package/dist/steps/outcome.d.ts.map +1 -0
- package/dist/steps/outcome.js +34 -0
- package/dist/steps/outcome.js.map +1 -0
- package/dist/steps/peek.d.ts +35 -0
- package/dist/steps/peek.d.ts.map +1 -0
- package/dist/steps/peek.js +219 -0
- package/dist/steps/peek.js.map +1 -0
- package/dist/steps/plan.d.ts +50 -0
- package/dist/steps/plan.d.ts.map +1 -0
- package/dist/steps/plan.js +242 -0
- package/dist/steps/plan.js.map +1 -0
- package/dist/steps/useRailDetail.d.ts +25 -0
- package/dist/steps/useRailDetail.d.ts.map +1 -0
- package/dist/steps/useRailDetail.js +108 -0
- package/dist/steps/useRailDetail.js.map +1 -0
- package/dist/steps/words.d.ts +40 -0
- package/dist/steps/words.d.ts.map +1 -0
- package/dist/steps/words.js +247 -0
- package/dist/steps/words.js.map +1 -0
- package/dist/toolRender.d.ts +27 -1
- package/dist/toolRender.d.ts.map +1 -1
- package/dist/toolRender.js +72 -4
- package/dist/toolRender.js.map +1 -1
- package/dist/transcriptSkin.d.ts.map +1 -1
- package/dist/transcriptSkin.js +66 -0
- package/dist/transcriptSkin.js.map +1 -1
- package/dist/transcriptSkinCss.d.ts +35 -0
- package/dist/transcriptSkinCss.d.ts.map +1 -1
- package/dist/transcriptSkinCss.js +360 -19
- package/dist/transcriptSkinCss.js.map +1 -1
- package/dist/useHoldPress.d.ts +24 -0
- package/dist/useHoldPress.d.ts.map +1 -0
- package/dist/useHoldPress.js +85 -0
- package/dist/useHoldPress.js.map +1 -0
- package/package.json +5 -5
package/dist/DictateButton.js
CHANGED
|
@@ -14,7 +14,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
14
14
|
* this feature's entire claim ("nothing leaves your device") false in the only
|
|
15
15
|
* way the user cannot see. */
|
|
16
16
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
17
|
-
import { IcMic, IcStop } from '@corenel/ui-kit/icons';
|
|
17
|
+
import { IcMic, IcStop, Spinner } from '@corenel/ui-kit/icons';
|
|
18
18
|
import { createDictation as realCreateDictation } from '@corenel/tools-web/speech/session';
|
|
19
19
|
/** What enabling voice input actually costs on the wire, for the prompt.
|
|
20
20
|
*
|
|
@@ -37,7 +37,7 @@ const DOWNLOAD_SIZE = '~40 MB';
|
|
|
37
37
|
function canDictate() {
|
|
38
38
|
return typeof navigator !== 'undefined' && !!navigator.mediaDevices?.getUserMedia;
|
|
39
39
|
}
|
|
40
|
-
export function DictateButton({ host, onInterim, onFinal, createDictation = realCreateDictation, supported, onListeningChange, hideWhenIdle = false, controlRef, backend, }) {
|
|
40
|
+
export function DictateButton({ host, onInterim, onFinal, createDictation = realCreateDictation, supported, onListeningChange, hideWhenIdle = false, controlRef, backend, onNotice, }) {
|
|
41
41
|
const [state, setState] = useState('idle');
|
|
42
42
|
const [error, setError] = useState(null);
|
|
43
43
|
const [progress, setProgress] = useState(null);
|
|
@@ -56,10 +56,17 @@ export function DictateButton({ host, onInterim, onFinal, createDictation = real
|
|
|
56
56
|
* stop, and `begin` then resumes and opens the microphone on behalf of a
|
|
57
57
|
* component that is gone, with nothing left to close it. */
|
|
58
58
|
const cancelled = useRef(false);
|
|
59
|
+
/* Bumped by every begin and by Cancel. A begin whose number is no longer the
|
|
60
|
+
* current one was cancelled while it waited on the model, and stops there.
|
|
61
|
+
* The download itself is not aborted: it finishes in the background and is
|
|
62
|
+
* cached, so the next dictation starts without it. */
|
|
63
|
+
const attempt = useRef(0);
|
|
59
64
|
/* Read through a ref so the unmount cleanup (empty deps, by design) can reach
|
|
60
65
|
* the CURRENT callback rather than the one captured at first mount. */
|
|
61
66
|
const report = useRef(onListeningChange);
|
|
62
67
|
report.current = onListeningChange;
|
|
68
|
+
const notice = useRef(onNotice);
|
|
69
|
+
notice.current = onNotice;
|
|
63
70
|
/* Release on unmount. Empty deps on purpose: this must run exactly once, at
|
|
64
71
|
* teardown, reading the ref -- a dependency that re-ran it would stop a live
|
|
65
72
|
* dictation every time the parent re-rendered.
|
|
@@ -87,8 +94,14 @@ export function DictateButton({ host, onInterim, onFinal, createDictation = real
|
|
|
87
94
|
// The composer must come out of dictation mode even when this disappears
|
|
88
95
|
// from under it.
|
|
89
96
|
report.current?.(false);
|
|
97
|
+
notice.current?.(null);
|
|
90
98
|
};
|
|
91
99
|
}, []);
|
|
100
|
+
const cancel = useCallback(() => {
|
|
101
|
+
attempt.current += 1;
|
|
102
|
+
setState('idle');
|
|
103
|
+
setProgress(null);
|
|
104
|
+
}, []);
|
|
92
105
|
const teardown = useCallback(() => {
|
|
93
106
|
void session.current?.stop();
|
|
94
107
|
session.current = null;
|
|
@@ -100,6 +113,8 @@ export function DictateButton({ host, onInterim, onFinal, createDictation = real
|
|
|
100
113
|
onInterim('');
|
|
101
114
|
}, [onInterim]);
|
|
102
115
|
const begin = useCallback(async () => {
|
|
116
|
+
const mine = ++attempt.current;
|
|
117
|
+
const gone = () => cancelled.current || mine !== attempt.current;
|
|
103
118
|
setError(null);
|
|
104
119
|
setState('preparing');
|
|
105
120
|
/* A WARM-UP IS NOT A DOWNLOAD.
|
|
@@ -123,12 +138,15 @@ export function DictateButton({ host, onInterim, onFinal, createDictation = real
|
|
|
123
138
|
catch {
|
|
124
139
|
cached = false;
|
|
125
140
|
}
|
|
126
|
-
if (
|
|
141
|
+
if (gone())
|
|
127
142
|
return;
|
|
128
143
|
try {
|
|
129
|
-
await h.ensureModel(cached ? undefined : (p) =>
|
|
144
|
+
await h.ensureModel(cached ? undefined : (p) => { if (!gone())
|
|
145
|
+
setProgress(p); });
|
|
130
146
|
}
|
|
131
147
|
catch (e) {
|
|
148
|
+
if (gone())
|
|
149
|
+
return;
|
|
132
150
|
// Intent stays on (model.ts keeps it), so the next click retries the
|
|
133
151
|
// download rather than re-asking a question already answered.
|
|
134
152
|
setError(e.message || 'The download failed.');
|
|
@@ -136,9 +154,9 @@ export function DictateButton({ host, onInterim, onFinal, createDictation = real
|
|
|
136
154
|
setProgress(null);
|
|
137
155
|
return;
|
|
138
156
|
}
|
|
139
|
-
// Gone while the model was downloading: do not acquire a
|
|
140
|
-
//
|
|
141
|
-
if (
|
|
157
|
+
// Gone while the model was downloading, or cancelled: do not acquire a
|
|
158
|
+
// microphone nobody is waiting for.
|
|
159
|
+
if (gone())
|
|
142
160
|
return;
|
|
143
161
|
const d = make({
|
|
144
162
|
onInterim,
|
|
@@ -170,7 +188,12 @@ export function DictateButton({ host, onInterim, onFinal, createDictation = real
|
|
|
170
188
|
onInterim('');
|
|
171
189
|
return;
|
|
172
190
|
}
|
|
173
|
-
|
|
191
|
+
// A tap on the spinner gives up waiting, the same as the notice's Cancel.
|
|
192
|
+
if (state === 'preparing') {
|
|
193
|
+
cancel();
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (state === 'asking')
|
|
174
197
|
return;
|
|
175
198
|
const b = backend ? backend() : { host, createDictation, supported: ok };
|
|
176
199
|
if (!b.supported)
|
|
@@ -186,19 +209,51 @@ export function DictateButton({ host, onInterim, onFinal, createDictation = real
|
|
|
186
209
|
b.host.setEnabled(true);
|
|
187
210
|
}
|
|
188
211
|
await begin();
|
|
189
|
-
}, [state, host, createDictation, backend, ok, begin, onInterim]);
|
|
212
|
+
}, [state, host, createDictation, backend, ok, begin, onInterim, cancel]);
|
|
190
213
|
const accept = useCallback(async () => {
|
|
191
214
|
(active.current?.host ?? host).setEnabled(true);
|
|
192
215
|
setState('idle');
|
|
193
216
|
await begin();
|
|
194
217
|
}, [host, begin]);
|
|
218
|
+
/* Always the latest accept, so the consent notice (published once per state
|
|
219
|
+
* change) never goes stale and never needs to be re-published when the host
|
|
220
|
+
* hands in fresh callbacks. */
|
|
221
|
+
const acceptRef = useRef(accept);
|
|
222
|
+
acceptRef.current = accept;
|
|
223
|
+
useEffect(() => {
|
|
224
|
+
const report = notice.current;
|
|
225
|
+
if (!report)
|
|
226
|
+
return;
|
|
227
|
+
if (state === 'asking') {
|
|
228
|
+
report({
|
|
229
|
+
kind: 'consent', size: DOWNLOAD_SIZE,
|
|
230
|
+
accept: () => { void acceptRef.current(); },
|
|
231
|
+
decline: () => setState('idle'),
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
else if (state === 'preparing') {
|
|
235
|
+
report({ kind: 'preparing', progress, cancel });
|
|
236
|
+
}
|
|
237
|
+
else if (error) {
|
|
238
|
+
report({ kind: 'error', message: error, dismiss: () => setError(null) });
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
report(null);
|
|
242
|
+
}
|
|
243
|
+
}, [state, error, progress, cancel]);
|
|
195
244
|
const listening = state === 'listening';
|
|
196
245
|
// Refreshed every render, so the menu always drives the CURRENT click logic.
|
|
197
246
|
if (controlRef)
|
|
198
247
|
controlRef.current = { toggle: onClick, supported: ok, listening };
|
|
199
248
|
if (hideWhenIdle && state === 'idle' && !error)
|
|
200
249
|
return null;
|
|
201
|
-
const label = listening ? 'Stop dictating' : 'Dictate';
|
|
250
|
+
const label = listening ? 'Stop dictating' : state === 'preparing' ? 'Cancel voice input' : 'Dictate';
|
|
251
|
+
if (onNotice) {
|
|
252
|
+
if (!ok && state === 'idle' && !error)
|
|
253
|
+
return null;
|
|
254
|
+
const busy = state === 'preparing' || state === 'asking';
|
|
255
|
+
return (_jsx("button", { style: S.round(listening), onClick: () => void onClick(), "aria-label": label, "aria-busy": busy ? true : undefined, title: `Dictate into the composer (${DOWNLOAD_SIZE} one-time download)`, children: listening ? _jsx(IcStop, { size: 18 }) : busy ? _jsx(Spinner, { size: 18, title: "Preparing voice input" }) : _jsx(IcMic, { size: 18 }) }));
|
|
256
|
+
}
|
|
202
257
|
const title = !ok
|
|
203
258
|
? 'Voice input needs a microphone and a browser that supports one.'
|
|
204
259
|
: listening ? 'Stop dictating' : `Dictate into the composer (${DOWNLOAD_SIZE} one-time download)`;
|
|
@@ -221,6 +276,14 @@ const S = {
|
|
|
221
276
|
* press-to-talk target you reach for mid-thought, often on a phone, and the
|
|
222
277
|
* 22px chip height that suits a passive status chip is a poor hit target for
|
|
223
278
|
* something you aim at while composing a sentence. */
|
|
279
|
+
round: (on) => ({
|
|
280
|
+
display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
|
|
281
|
+
height: '40px', width: '40px', padding: 0, borderRadius: '50%',
|
|
282
|
+
background: on ? 'var(--accent-soft)' : 'transparent',
|
|
283
|
+
border: `1px solid ${on ? 'var(--accent)' : 'var(--border-default)'}`,
|
|
284
|
+
color: on ? 'var(--accent)' : 'var(--text-secondary)',
|
|
285
|
+
cursor: 'pointer',
|
|
286
|
+
}),
|
|
224
287
|
btn: (on) => ({
|
|
225
288
|
display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 5,
|
|
226
289
|
height: 30, minWidth: 34, padding: '0 9px',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DictateButton.js","sourceRoot":"","sources":["../DictateButton.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;8BAa8B;AAC9B,OAAc,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"DictateButton.js","sourceRoot":"","sources":["../DictateButton.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PickChips.d.ts","sourceRoot":"","sources":["../PickChips.tsx"],"names":[],"mappings":"AAQA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAEnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAkDpE,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,SAAS,WAAW,EAAE,CAAA;CAAE,4BASrE"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/* The chips a sent message shows for the page elements picked with it.
|
|
3
|
+
*
|
|
4
|
+
* NOTHING THE MODEL GOT IS HIDDEN, ONLY FOLDED. Any user-role message can carry
|
|
5
|
+
* the pick marker (a room participant, a delegating model, a daemon prompt),
|
|
6
|
+
* so a chip that showed only its label would let a writer show a harmless
|
|
7
|
+
* selector while the model read something else. Each chip is a disclosure:
|
|
8
|
+
* collapsed by default, and opening it shows the exact text the model
|
|
9
|
+
* received for that block, as plain text in a pre, never as HTML. */
|
|
10
|
+
import { useEffect, useState } from 'react';
|
|
11
|
+
import { IcTarget } from '@corenel/ui-kit/icons';
|
|
12
|
+
const PHONE_QUERY = '(max-width: 640px)';
|
|
13
|
+
function usePhone() {
|
|
14
|
+
const read = () => typeof matchMedia === 'function' && matchMedia(PHONE_QUERY).matches;
|
|
15
|
+
const [phone, setPhone] = useState(read);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
if (typeof matchMedia !== 'function')
|
|
18
|
+
return;
|
|
19
|
+
const mq = matchMedia(PHONE_QUERY);
|
|
20
|
+
const on = () => setPhone(mq.matches);
|
|
21
|
+
mq.addEventListener?.('change', on);
|
|
22
|
+
on();
|
|
23
|
+
return () => mq.removeEventListener?.('change', on);
|
|
24
|
+
}, []);
|
|
25
|
+
return phone;
|
|
26
|
+
}
|
|
27
|
+
/* Keys from the content, numbered only among equal picks. */
|
|
28
|
+
function keysFor(picks) {
|
|
29
|
+
const seen = new Map();
|
|
30
|
+
return picks.map((p) => {
|
|
31
|
+
const base = `${p.label}\n${p.text}`;
|
|
32
|
+
const n = seen.get(base) ?? 0;
|
|
33
|
+
seen.set(base, n + 1);
|
|
34
|
+
return `${base}\n${n}`;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function PickChip({ pick, phone }) {
|
|
38
|
+
const [open, setOpen] = useState(false);
|
|
39
|
+
return (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", "data-testid": "user-pick", style: phone ? { ...S.chip, ...S.chipPhone } : S.chip, title: pick.label, "aria-expanded": open, "aria-label": `${pick.label}, ${open ? 'hide' : 'show'} what was sent`, onClick: () => setOpen((o) => !o), children: [_jsx(IcTarget, { size: phone ? 14 : 11 }), _jsx("span", { style: S.label, children: pick.label })] }), open && _jsx("pre", { "data-testid": "user-pick-body", style: S.body, children: _jsx("code", { children: pick.text }) })] }));
|
|
40
|
+
}
|
|
41
|
+
export function PickChips({ picks }) {
|
|
42
|
+
const phone = usePhone();
|
|
43
|
+
if (picks.length === 0)
|
|
44
|
+
return null;
|
|
45
|
+
const keys = keysFor(picks);
|
|
46
|
+
return (_jsx("span", { style: S.row, children: picks.map((p, i) => _jsx(PickChip, { pick: p, phone: phone }, keys[i])) }));
|
|
47
|
+
}
|
|
48
|
+
const S = {
|
|
49
|
+
row: { display: 'flex', flexWrap: 'wrap', gap: 6, minWidth: 0, flex: '1 1 auto' },
|
|
50
|
+
chip: { display: 'inline-flex', alignItems: 'center', gap: 5, height: 22, padding: '0 8px', borderRadius: 'var(--radius-pill)', background: 'var(--surface-3)', border: '1px solid var(--border-subtle)', color: 'var(--text-secondary)', fontSize: 11.5, fontFamily: 'var(--font-mono)', fontStyle: 'normal', maxWidth: '100%', minWidth: 0, boxSizing: 'border-box', cursor: 'pointer' },
|
|
51
|
+
chipPhone: { height: 44, padding: '0 14px', fontSize: 13 },
|
|
52
|
+
label: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', minWidth: 0 },
|
|
53
|
+
body: { flexBasis: '100%', margin: 0, padding: '8px 10px', maxHeight: 320, overflow: 'auto', borderRadius: 'var(--radius-sm)', background: 'var(--surface-2)', border: '1px solid var(--border-subtle)', color: 'var(--text-secondary)', fontSize: 12, fontFamily: 'var(--font-mono)', fontStyle: 'normal', whiteSpace: 'pre-wrap', wordBreak: 'break-word', textAlign: 'left' },
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=PickChips.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PickChips.js","sourceRoot":"","sources":["../PickChips.tsx"],"names":[],"mappings":"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"}
|
package/dist/ProcessDock.d.ts
CHANGED
|
@@ -16,6 +16,16 @@ export interface DockProcess {
|
|
|
16
16
|
code: number | null;
|
|
17
17
|
signal?: string;
|
|
18
18
|
};
|
|
19
|
+
/** The agent started it (through its proc_start tool), not the person. The
|
|
20
|
+
* card says so, since it is still a process on their machine that they may
|
|
21
|
+
* want to stop. */
|
|
22
|
+
byAgent?: boolean;
|
|
23
|
+
/** A local web address the process printed, when this browser is on the
|
|
24
|
+
* sidecar's machine: the card offers to open it. */
|
|
25
|
+
openUrl?: string;
|
|
26
|
+
/** The same kind of address when this browser is NOT on that machine: shown
|
|
27
|
+
* as text, since it would point at the wrong computer. */
|
|
28
|
+
remoteUrl?: string;
|
|
19
29
|
}
|
|
20
30
|
export interface ProcessDockProps {
|
|
21
31
|
processes: DockProcess[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProcessDock.d.ts","sourceRoot":"","sources":["../ProcessDock.tsx"],"names":[],"mappings":"AAyBA,OAAO,EAA+B,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAGvE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,mBAAmB;IACnB,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,KAAK,GAAG,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC9D,0DAA0D;IAC1D,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"ProcessDock.d.ts","sourceRoot":"","sources":["../ProcessDock.tsx"],"names":[],"mappings":"AAyBA,OAAO,EAA+B,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAGvE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,mBAAmB;IACnB,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,KAAK,GAAG,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC9D,0DAA0D;IAC1D,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD;;uBAEmB;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;wDACoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;8DAC0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,WAAW,EAAE,CAAC;IACzB,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,+EAA+E;IAC/E,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,wCAAwC;IACxC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAkBD;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,WAAW,EAAE,EAAE,GAAG,SAAY,GAAG;IAAE,KAAK,EAAE,WAAW,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAWpH;AAED,wBAAgB,WAAW,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,gBAAgB,GAAG,YAAY,GAAG,IAAI,CAsC3G"}
|
package/dist/ProcessDock.js
CHANGED
|
@@ -92,7 +92,7 @@ function ProcessCard({ proc, open, onToggle, onStop, onKeep, onDismiss }) {
|
|
|
92
92
|
const tail = proc.lines.slice(-200);
|
|
93
93
|
return (_jsxs("div", { style: S.card, children: [_jsxs("div", { style: S.head, children: [_jsx("button", { style: S.disclose, onClick: onToggle, "aria-expanded": open, "aria-label": open ? 'hide output' : 'show output', children: _jsx("span", { style: { ...S.caret, transform: open ? 'rotate(90deg)' : 'none' }, children: _jsx(IcChevronRight, { size: 12 }) }) }), _jsx("span", { style: { ...S.dot, background: st.tone === 'live' ? 'var(--accent)' : st.tone === 'bad' ? 'var(--danger)' : 'var(--success)' } }), _jsx("code", { style: S.cmd, title: proc.command, children: proc.label || proc.command }), _jsx("span", { style: { ...S.status, color: st.tone === 'bad' ? 'var(--danger)' : 'var(--text-tertiary)' }, children: st.text }), _jsx("div", { style: S.spacer }), proc.running
|
|
94
94
|
? _jsx("button", { style: S.btn, onClick: () => onStop(proc.procId), children: "Stop" })
|
|
95
|
-
: (_jsxs(_Fragment, { children: [_jsxs("button", { style: S.btn, onClick: () => onKeep(proc.procId), title: "Add this output to the conversation and the agent's context", children: [_jsx(IcCheck, { size: 12 }), " Keep in context"] }), _jsx("button", { style: S.icon, onClick: () => onDismiss(proc.procId), "aria-label": "dismiss", children: _jsx(IcX, { size: 13 }) })] }))] }), open && (_jsxs(_Fragment, { children: [proc.truncated && (_jsxs("div", { style: S.gap, children: [_jsx(IcAlert, { size: 12 }), _jsx("span", { children: "Earlier output is no longer held - this is the tail, not the whole run." })] })), _jsx("pre", { style: S.out, children: tail.length
|
|
95
|
+
: (_jsxs(_Fragment, { children: [_jsxs("button", { style: S.btn, onClick: () => onKeep(proc.procId), title: "Add this output to the conversation and the agent's context", children: [_jsx(IcCheck, { size: 12 }), " Keep in context"] }), _jsx("button", { style: S.icon, onClick: () => onDismiss(proc.procId), "aria-label": "dismiss", children: _jsx(IcX, { size: 13 }) })] }))] }), proc.byAgent && _jsx("div", { style: S.who, children: "Started by the agent" }), proc.running && proc.openUrl && (_jsxs("div", { style: S.addr, children: [_jsx("code", { style: S.addrText, children: proc.openUrl }), _jsx("button", { style: S.open, onClick: () => { window.open(proc.openUrl, '_blank', 'noopener,noreferrer'); }, title: `Open ${proc.openUrl}`, "aria-label": `Open ${proc.openUrl}`, children: "Open" })] })), proc.running && !proc.openUrl && proc.remoteUrl && (_jsxs("div", { style: S.addr, children: [_jsx("code", { style: S.addrText, children: proc.remoteUrl }), _jsx("span", { style: S.hint, children: "Open it on the sidecar's computer." })] })), open && (_jsxs(_Fragment, { children: [proc.truncated && (_jsxs("div", { style: S.gap, children: [_jsx(IcAlert, { size: 12 }), _jsx("span", { children: "Earlier output is no longer held - this is the tail, not the whole run." })] })), _jsx("pre", { style: S.out, children: tail.length
|
|
96
96
|
? tail.map((l) => (_jsx("span", { style: l.stream === 'err' ? S.errLine : undefined, children: l.text }, l.seq)))
|
|
97
97
|
: _jsx("span", { style: S.hint, children: "No output yet." }) })] }))] }));
|
|
98
98
|
}
|
|
@@ -146,5 +146,28 @@ const S = {
|
|
|
146
146
|
errLine: { color: 'var(--danger)' },
|
|
147
147
|
hint: { color: 'var(--text-tertiary)' },
|
|
148
148
|
more: { padding: '2px 4px', fontSize: 11, color: 'var(--text-tertiary)' },
|
|
149
|
+
// Wraps rather than scrolls: a long address must not widen the card at 390px.
|
|
150
|
+
addr: {
|
|
151
|
+
display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: '4px 8px',
|
|
152
|
+
padding: '0 10px 6px 43px', minWidth: 0, fontSize: 11,
|
|
153
|
+
},
|
|
154
|
+
addrText: {
|
|
155
|
+
fontFamily: 'var(--font-mono, monospace)', fontSize: 11.5, color: 'var(--text-secondary)',
|
|
156
|
+
minWidth: 0, overflowWrap: 'anywhere',
|
|
157
|
+
},
|
|
158
|
+
// 44px square minimum for touch, matching the other card buttons' pill look.
|
|
159
|
+
open: {
|
|
160
|
+
display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flex: 'none',
|
|
161
|
+
minHeight: 44, minWidth: 44, padding: '0 14px', borderRadius: 999,
|
|
162
|
+
border: '1px solid var(--accent)', background: 'transparent', color: 'var(--accent)',
|
|
163
|
+
font: 'inherit', fontSize: 12, cursor: 'pointer',
|
|
164
|
+
},
|
|
165
|
+
// Under the one-line head rather than in it: at phone width the head has no
|
|
166
|
+
// room left, and squeezing this in would cut the command down to nothing.
|
|
167
|
+
// Indented to sit under the command (4 + 18 + 7 + 7 + 7 px of head before it).
|
|
168
|
+
who: {
|
|
169
|
+
padding: '0 10px 5px 43px', fontSize: 11, color: 'var(--text-tertiary)', minWidth: 0,
|
|
170
|
+
overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
|
|
171
|
+
},
|
|
149
172
|
};
|
|
150
173
|
//# sourceMappingURL=ProcessDock.js.map
|
package/dist/ProcessDock.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProcessDock.js","sourceRoot":"","sources":["../ProcessDock.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAqB,MAAM,OAAO,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"ProcessDock.js","sourceRoot":"","sources":["../ProcessDock.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RichContent.d.ts","sourceRoot":"","sources":["../RichContent.tsx"],"names":[],"mappings":"AAWA,OAAO,
|
|
1
|
+
{"version":3,"file":"RichContent.d.ts","sourceRoot":"","sources":["../RichContent.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAgE,MAAM,OAAO,CAAC;AAErF,OAAO,EAA2B,KAAK,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAuEvF,wBAAgB,OAAO,CAAC,EAAE,IAAI,EAAE,KAAc,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,qBAUjF;AAqID,wBAAgB,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,qBA2BvE;AAyJD,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;IACrE;kFAC8E;IAC9E,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IACrD,kFAAkF;IAClF,EAAE,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvB;+EAC2E;IAC3E,QAAQ,CAAC,EAAE,WAAW,CAAC;CACxB,qBAyCA;AAaD;;;;4DAI4D;AAC5D,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;IACrE;;;4CAGwC;IACxC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;CACtD,4BASA;AAKD,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,qBAkBjH;AAiED,yEAAyE;AACzE,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,KAAK,CAAC,SAAS,CAiCzG"}
|
package/dist/RichContent.js
CHANGED
|
@@ -10,7 +10,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
10
10
|
* - DiagramBlock: lazy-loads mermaid (kept out of the main bundle) and renders the
|
|
11
11
|
* SVG, falling back to the source on a parse error.
|
|
12
12
|
* - RichResult: picks the right renderer for a tool result from the tool + path. */
|
|
13
|
-
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
13
|
+
import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
14
14
|
import { isToolErrorResult } from '@corenel/harness/core/recovery';
|
|
15
15
|
import { mdToHtml, highlightPrmd } from '@corenel/ui-kit/ui-helpers';
|
|
16
16
|
import { getTheme } from '@corenel/ui-kit/theme';
|
|
@@ -264,30 +264,65 @@ function splitFences(text) {
|
|
|
264
264
|
}
|
|
265
265
|
/** Resolve the `data-opfs` images in a rendered prose block to object URLs.
|
|
266
266
|
*
|
|
267
|
-
* Prose is
|
|
267
|
+
* Prose is raw html (mdToHtml returns a string), so there is no React node for
|
|
268
268
|
* an image -- the swap happens against the container after mount. That is also
|
|
269
269
|
* the only place that can own the revoke: nothing else will clean these up, and
|
|
270
270
|
* one leaked object URL pins its whole blob for the life of the tab.
|
|
271
271
|
*
|
|
272
|
+
* Prose is morphed, not replaced, as text grows (see Prose), so an image node
|
|
273
|
+
* persists across deltas and keeps its resolved URL: a node whose opfs id is
|
|
274
|
+
* unchanged is neither re-resolved nor revoked. A URL is revoked only when its
|
|
275
|
+
* node is gone or now holds a different id, and all of them on unmount (or when
|
|
276
|
+
* the resolver changes).
|
|
277
|
+
*
|
|
272
278
|
* The resolver is injected because readImage lives in the app, not this
|
|
273
279
|
* package; a surface that passes none is byte-for-byte unchanged. */
|
|
274
280
|
function useOpfsImages(ref, text, resolveImage) {
|
|
281
|
+
const store = useRef(new Map());
|
|
282
|
+
const inflight = useRef(new Map());
|
|
283
|
+
const generation = useRef(0);
|
|
284
|
+
// Owns teardown: declared first so on a resolver change it runs before the pass below.
|
|
285
|
+
useEffect(() => {
|
|
286
|
+
const urls = store.current;
|
|
287
|
+
const pending = inflight.current;
|
|
288
|
+
return () => {
|
|
289
|
+
generation.current++;
|
|
290
|
+
for (const e of urls.values())
|
|
291
|
+
URL.revokeObjectURL(e.url);
|
|
292
|
+
urls.clear();
|
|
293
|
+
pending.clear();
|
|
294
|
+
};
|
|
295
|
+
}, [ref, resolveImage]);
|
|
275
296
|
useEffect(() => {
|
|
276
297
|
if (!resolveImage || !ref.current)
|
|
277
298
|
return;
|
|
278
299
|
const nodes = Array.from(ref.current.querySelectorAll('img[data-opfs]'));
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
300
|
+
for (const [node, e] of store.current) {
|
|
301
|
+
if (nodes.includes(node) && node.getAttribute('data-opfs') === e.id)
|
|
302
|
+
continue;
|
|
303
|
+
URL.revokeObjectURL(e.url);
|
|
304
|
+
store.current.delete(node);
|
|
305
|
+
}
|
|
306
|
+
const gen = generation.current;
|
|
283
307
|
void Promise.all(nodes.map(async (node) => {
|
|
284
308
|
const id = node.getAttribute('data-opfs');
|
|
285
|
-
if (!id)
|
|
309
|
+
if (!id || store.current.has(node) || inflight.current.get(node) === id)
|
|
286
310
|
return;
|
|
311
|
+
inflight.current.set(node, id);
|
|
287
312
|
const blob = await resolveImage(id).catch(() => null);
|
|
288
313
|
// Teardown and missing bytes are DIFFERENT cases, and collapsing them is
|
|
289
314
|
// what produced the bug below. On teardown, touch nothing.
|
|
290
|
-
if (
|
|
315
|
+
if (generation.current !== gen)
|
|
316
|
+
return;
|
|
317
|
+
if (inflight.current.get(node) === id)
|
|
318
|
+
inflight.current.delete(node);
|
|
319
|
+
// The node went away (or took another id) while the bytes loaded.
|
|
320
|
+
if (!node.isConnected || node.getAttribute('data-opfs') !== id)
|
|
321
|
+
return;
|
|
322
|
+
/* An id flip A -> B -> A leaves two resolves for A in flight on one node:
|
|
323
|
+
* the first already minted its URL, so a second must not overwrite it in
|
|
324
|
+
* the store (leaking it until the tab closes) or replace it with a notice. */
|
|
325
|
+
if (store.current.get(node)?.id === id)
|
|
291
326
|
return;
|
|
292
327
|
/* A document outlives its bytes routinely: OPFS is partitioned by browser
|
|
293
328
|
* profile AND origin, so an image generated in Chrome on a laptop has no
|
|
@@ -303,13 +338,6 @@ function useOpfsImages(ref, text, resolveImage) {
|
|
|
303
338
|
* Same sentence as ArtifactImage's missing branch: one condition must not
|
|
304
339
|
* read two different ways depending on which pane you are looking at. */
|
|
305
340
|
if (!blob) {
|
|
306
|
-
/* Belt and braces, and NOT tested behaviour: `cancelled` above already
|
|
307
|
-
* returns on teardown, so nothing can reach this line with a detached
|
|
308
|
-
* node -- a mutation deleting it survives the whole suite. Kept in case
|
|
309
|
-
* that check is ever moved or removed, stated plainly rather than
|
|
310
|
-
* dressed up as something the tests pin. */
|
|
311
|
-
if (!node.isConnected)
|
|
312
|
-
return;
|
|
313
341
|
const note = node.ownerDocument.createElement('span');
|
|
314
342
|
note.className = 'md-img-missing';
|
|
315
343
|
note.textContent = 'This image is not available any more.';
|
|
@@ -323,17 +351,67 @@ function useOpfsImages(ref, text, resolveImage) {
|
|
|
323
351
|
return;
|
|
324
352
|
}
|
|
325
353
|
const url = URL.createObjectURL(blob);
|
|
326
|
-
|
|
354
|
+
store.current.set(node, { id, url });
|
|
327
355
|
node.setAttribute('src', url);
|
|
328
356
|
}));
|
|
329
|
-
return () => {
|
|
330
|
-
cancelled = true;
|
|
331
|
-
for (const u of urls)
|
|
332
|
-
URL.revokeObjectURL(u);
|
|
333
|
-
};
|
|
334
|
-
// Re-runs when the prose changes, which is when the nodes are replaced.
|
|
335
357
|
}, [ref, text, resolveImage]);
|
|
336
358
|
}
|
|
359
|
+
/** Bring `live`'s children to match `next`'s, keeping every node that can stay.
|
|
360
|
+
* Assigning innerHTML replaces every node, which cancels any animation a
|
|
361
|
+
* caller is running on a block the moment the text grows. Elements with the
|
|
362
|
+
* same tag are updated in place (attributes, then children, recursively);
|
|
363
|
+
* only a node that cannot match is replaced. */
|
|
364
|
+
function morphChildren(live, next) {
|
|
365
|
+
const want = Array.from(next.childNodes);
|
|
366
|
+
const have = Array.from(live.childNodes);
|
|
367
|
+
want.forEach((n, i) => {
|
|
368
|
+
const cur = have[i];
|
|
369
|
+
if (!cur) {
|
|
370
|
+
live.appendChild(n);
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
if (cur.isEqualNode(n))
|
|
374
|
+
return;
|
|
375
|
+
if (cur instanceof Element && n instanceof Element && cur.tagName === n.tagName) {
|
|
376
|
+
// An opfs image's src is the object URL useOpfsImages swapped in; the same
|
|
377
|
+
// image keeps it (re-resolving would flicker), a different one takes the new.
|
|
378
|
+
const keepSrc = cur.hasAttribute('data-opfs') && cur.getAttribute('data-opfs') === n.getAttribute('data-opfs');
|
|
379
|
+
for (const a of Array.from(cur.attributes))
|
|
380
|
+
if (!n.hasAttribute(a.name) && !(keepSrc && a.name === 'src'))
|
|
381
|
+
cur.removeAttribute(a.name);
|
|
382
|
+
for (const a of Array.from(n.attributes))
|
|
383
|
+
if (!(keepSrc && a.name === 'src') && cur.getAttribute(a.name) !== a.value)
|
|
384
|
+
cur.setAttribute(a.name, a.value);
|
|
385
|
+
morphChildren(cur, n);
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
if (cur.nodeType === Node.TEXT_NODE && n.nodeType === Node.TEXT_NODE) {
|
|
389
|
+
cur.nodeValue = n.nodeValue;
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
live.replaceChild(n, cur);
|
|
393
|
+
});
|
|
394
|
+
for (let i = want.length; i < have.length; i++)
|
|
395
|
+
live.removeChild(have[i]);
|
|
396
|
+
}
|
|
397
|
+
/** A prose run. The first html is rendered by React; every later one is
|
|
398
|
+
* morphed into the live DOM so blocks that persist keep their identity (and
|
|
399
|
+
* their running animations). */
|
|
400
|
+
function Prose({ html }) {
|
|
401
|
+
const first = useRef(html);
|
|
402
|
+
const host = useRef(null);
|
|
403
|
+
const applied = useRef(html);
|
|
404
|
+
useLayoutEffect(() => {
|
|
405
|
+
const el = host.current;
|
|
406
|
+
if (!el || applied.current === html)
|
|
407
|
+
return;
|
|
408
|
+
applied.current = html;
|
|
409
|
+
const t = document.createElement('template');
|
|
410
|
+
t.innerHTML = html;
|
|
411
|
+
morphChildren(el, t.content);
|
|
412
|
+
}, [html]);
|
|
413
|
+
return _jsx("div", { ref: host, dangerouslySetInnerHTML: { __html: first.current } });
|
|
414
|
+
}
|
|
337
415
|
export function Markdown({ text, renderFence, mentions, me, resolveImage }) {
|
|
338
416
|
const blocks = useMemo(() => splitFences(text), [text]);
|
|
339
417
|
const host = useRef(null);
|
|
@@ -342,7 +420,7 @@ export function Markdown({ text, renderFence, mentions, me, resolveImage }) {
|
|
|
342
420
|
const [zoomSrc, setZoomSrc] = useState(null);
|
|
343
421
|
return (_jsxs("div", { className: "agent-md", style: S.md, ref: host,
|
|
344
422
|
/* Click-to-expand for markdown images, by DELEGATION: prose is written
|
|
345
|
-
*
|
|
423
|
+
* as raw html (Prose), so there is no React node to put an
|
|
346
424
|
* onClick on -- the same reason useOpfsImages works against the container
|
|
347
425
|
* after mount.
|
|
348
426
|
*
|
|
@@ -362,7 +440,7 @@ export function Markdown({ text, renderFence, mentions, me, resolveImage }) {
|
|
|
362
440
|
setZoomSrc(src);
|
|
363
441
|
}, children: [zoomSrc && _jsx(Lightbox, { src: zoomSrc, onClose: () => setZoomSrc(null) }), blocks.map((b, i) => {
|
|
364
442
|
if (b.type === 'md')
|
|
365
|
-
return _jsx(
|
|
443
|
+
return _jsx(Prose, { html: mdToHtml(b.text, mentions ? { mentions, me } : undefined) }, i);
|
|
366
444
|
const custom = renderFence?.(b.lang, b.code);
|
|
367
445
|
return custom != null
|
|
368
446
|
? _jsx(React.Fragment, { children: custom }, i)
|