@volter-ai-dev/supercode-ui 0.1.13 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/components.d.ts +1 -0
- package/components.mjs +711 -361
- package/composer.mjs +77 -19
- package/controller.mjs +5 -2
- package/conversation.mjs +364 -196
- package/core.mjs +3 -2
- package/embed.mjs +712 -363
- package/icon.d.ts +2 -0
- package/icon.mjs +45 -0
- package/index.d.ts +9 -3
- package/messenger.mjs +710 -361
- package/package.json +8 -2
- package/sessions.mjs +160 -48
- package/styles.css +35 -18
package/conversation.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/conversation.jsx
|
|
2
|
-
import {
|
|
2
|
+
import { Fragment as Fragment2 } from "preact";
|
|
3
|
+
import { useEffect as useEffect2, useId, useLayoutEffect, useRef as useRef2, useState } from "preact/hooks";
|
|
3
4
|
|
|
4
5
|
// core.mjs
|
|
5
6
|
var HARNESS_NAMES = Object.freeze({
|
|
@@ -283,18 +284,95 @@ function activitySummary(entries) {
|
|
|
283
284
|
|
|
284
285
|
// src/markdown.jsx
|
|
285
286
|
import MarkdownIt from "markdown-it";
|
|
286
|
-
import { useMemo } from "preact/hooks";
|
|
287
|
+
import { useEffect, useMemo, useRef } from "preact/hooks";
|
|
287
288
|
import { jsx } from "preact/jsx-runtime";
|
|
288
289
|
var markdown = new MarkdownIt({ html: false, linkify: true, breaks: false });
|
|
290
|
+
var LANGUAGE_LABELS = {
|
|
291
|
+
bash: "Shell",
|
|
292
|
+
css: "CSS",
|
|
293
|
+
html: "HTML",
|
|
294
|
+
js: "JavaScript",
|
|
295
|
+
javascript: "JavaScript",
|
|
296
|
+
jsx: "JSX",
|
|
297
|
+
md: "Markdown",
|
|
298
|
+
markdown: "Markdown",
|
|
299
|
+
py: "Python",
|
|
300
|
+
python: "Python",
|
|
301
|
+
rs: "Rust",
|
|
302
|
+
rust: "Rust",
|
|
303
|
+
sh: "Shell",
|
|
304
|
+
shell: "Shell",
|
|
305
|
+
ts: "TypeScript",
|
|
306
|
+
tsx: "TSX",
|
|
307
|
+
yaml: "YAML",
|
|
308
|
+
yml: "YAML",
|
|
309
|
+
json: "JSON",
|
|
310
|
+
jsonc: "JSONC",
|
|
311
|
+
sql: "SQL",
|
|
312
|
+
xml: "XML"
|
|
313
|
+
};
|
|
314
|
+
var COPY_ICON = '<svg viewBox="0 0 18 18" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="5" y="5" width="8" height="8" rx="1.5"></rect><path d="M3 10.5V4.25C3 3.56 3.56 3 4.25 3h6.25"></path></svg>';
|
|
315
|
+
function languageLabel(info) {
|
|
316
|
+
const language = info.trim().split(/\s+/, 1)[0]?.toLocaleLowerCase() ?? "";
|
|
317
|
+
if (!language) return "Code";
|
|
318
|
+
return LANGUAGE_LABELS[language] ?? language.toLocaleUpperCase();
|
|
319
|
+
}
|
|
320
|
+
function frameCode(render, tokens, index, options, env, self) {
|
|
321
|
+
const label = markdown.utils.escapeHtml(languageLabel(tokens[index]?.info ?? ""));
|
|
322
|
+
return `<div class="scui-code-block"><div class="scui-code-head"><span>${label}</span><button class="scui-code-copy" type="button" aria-label="Copy code" title="Copy code">${COPY_ICON}<span>Copy</span></button></div>${render(tokens, index, options, env, self)}</div>`;
|
|
323
|
+
}
|
|
324
|
+
for (const kind of ["fence", "code_block"]) {
|
|
325
|
+
const render = markdown.renderer.rules[kind];
|
|
326
|
+
markdown.renderer.rules[kind] = (tokens, index, options, env, self) => frameCode(render, tokens, index, options, env, self);
|
|
327
|
+
}
|
|
289
328
|
var defaultLinkOpen = markdown.renderer.rules.link_open;
|
|
290
329
|
markdown.renderer.rules.link_open = (tokens, index, options, env, self) => {
|
|
291
330
|
tokens[index]?.attrSet("target", "_blank");
|
|
292
331
|
tokens[index]?.attrSet("rel", "noreferrer noopener");
|
|
293
332
|
return defaultLinkOpen ? defaultLinkOpen(tokens, index, options, env, self) : self.renderToken(tokens, index, options);
|
|
294
333
|
};
|
|
295
|
-
function
|
|
334
|
+
function setCopyState(button, status) {
|
|
335
|
+
const labels = {
|
|
336
|
+
idle: ["Copy code", "Copy"],
|
|
337
|
+
copied: ["Code copied", "Copied"],
|
|
338
|
+
failed: ["Copy failed \xB7 retry", "Retry"]
|
|
339
|
+
};
|
|
340
|
+
const [label, visible] = labels[status];
|
|
341
|
+
button.dataset.status = status;
|
|
342
|
+
button.setAttribute("aria-label", label);
|
|
343
|
+
button.setAttribute("title", label);
|
|
344
|
+
const text = button.querySelector("span");
|
|
345
|
+
if (text) text.textContent = visible;
|
|
346
|
+
}
|
|
347
|
+
function Markdown({ value, copyText }) {
|
|
296
348
|
const html = useMemo(() => markdown.render(value), [value]);
|
|
297
|
-
|
|
349
|
+
const resets = useRef(/* @__PURE__ */ new Map());
|
|
350
|
+
useEffect(() => () => {
|
|
351
|
+
for (const timer of resets.current.values()) clearTimeout(timer);
|
|
352
|
+
resets.current.clear();
|
|
353
|
+
}, []);
|
|
354
|
+
const copyCode = async (event) => {
|
|
355
|
+
const button = event.target.closest?.(".scui-code-copy");
|
|
356
|
+
if (!button || !event.currentTarget.contains(button) || !copyText) return;
|
|
357
|
+
const code = button.closest(".scui-code-block")?.querySelector("pre code");
|
|
358
|
+
if (!code) return;
|
|
359
|
+
button.disabled = true;
|
|
360
|
+
try {
|
|
361
|
+
await copyText(code.textContent ?? "");
|
|
362
|
+
setCopyState(button, "copied");
|
|
363
|
+
} catch {
|
|
364
|
+
setCopyState(button, "failed");
|
|
365
|
+
} finally {
|
|
366
|
+
button.disabled = false;
|
|
367
|
+
}
|
|
368
|
+
clearTimeout(resets.current.get(button));
|
|
369
|
+
const timer = setTimeout(() => {
|
|
370
|
+
if (button.isConnected) setCopyState(button, "idle");
|
|
371
|
+
resets.current.delete(button);
|
|
372
|
+
}, 1500);
|
|
373
|
+
resets.current.set(button, timer);
|
|
374
|
+
};
|
|
375
|
+
return /* @__PURE__ */ jsx("div", { class: "scui-markdown", "data-copyable": Boolean(copyText), onClick: copyCode, dangerouslySetInnerHTML: { __html: html } });
|
|
298
376
|
}
|
|
299
377
|
|
|
300
378
|
// src/memory.js
|
|
@@ -305,8 +383,51 @@ function boundedSet(map, key, value) {
|
|
|
305
383
|
while (map.size > MEMORY_LIMIT) map.delete(map.keys().next().value);
|
|
306
384
|
}
|
|
307
385
|
|
|
308
|
-
// src/
|
|
386
|
+
// src/icon.jsx
|
|
309
387
|
import { Fragment, jsx as jsx2, jsxs } from "preact/jsx-runtime";
|
|
388
|
+
var ICONS = {
|
|
389
|
+
back: () => /* @__PURE__ */ jsx2("path", { d: "m11.5 4.5-4.5 4.5 4.5 4.5" }),
|
|
390
|
+
check: () => /* @__PURE__ */ jsx2("path", { d: "m4 9 3.25 3.25L14 5.5" }),
|
|
391
|
+
chevron: () => /* @__PURE__ */ jsx2("path", { d: "m7 4.5 4.5 4.5L7 13.5" }),
|
|
392
|
+
close: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
393
|
+
/* @__PURE__ */ jsx2("path", { d: "m4.75 4.75 8.5 8.5" }),
|
|
394
|
+
/* @__PURE__ */ jsx2("path", { d: "m13.25 4.75-8.5 8.5" })
|
|
395
|
+
] }),
|
|
396
|
+
copy: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
397
|
+
/* @__PURE__ */ jsx2("rect", { x: "5", y: "5", width: "8", height: "8", rx: "1.5" }),
|
|
398
|
+
/* @__PURE__ */ jsx2("path", { d: "M3 10.5V4.25C3 3.56 3.56 3 4.25 3h6.25" })
|
|
399
|
+
] }),
|
|
400
|
+
down: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
401
|
+
/* @__PURE__ */ jsx2("path", { d: "M9 3.5v10" }),
|
|
402
|
+
/* @__PURE__ */ jsx2("path", { d: "m4.75 9.5 4.25 4 4.25-4" })
|
|
403
|
+
] }),
|
|
404
|
+
menu: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
405
|
+
/* @__PURE__ */ jsx2("circle", { cx: "4", cy: "9", r: "1.25", fill: "currentColor", stroke: "none" }),
|
|
406
|
+
/* @__PURE__ */ jsx2("circle", { cx: "9", cy: "9", r: "1.25", fill: "currentColor", stroke: "none" }),
|
|
407
|
+
/* @__PURE__ */ jsx2("circle", { cx: "14", cy: "9", r: "1.25", fill: "currentColor", stroke: "none" })
|
|
408
|
+
] }),
|
|
409
|
+
plus: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
410
|
+
/* @__PURE__ */ jsx2("path", { d: "M9 3.5v11" }),
|
|
411
|
+
/* @__PURE__ */ jsx2("path", { d: "M3.5 9h11" })
|
|
412
|
+
] }),
|
|
413
|
+
search: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
414
|
+
/* @__PURE__ */ jsx2("circle", { cx: "7.75", cy: "7.75", r: "4.25" }),
|
|
415
|
+
/* @__PURE__ */ jsx2("path", { d: "m11 11 3.5 3.5" })
|
|
416
|
+
] }),
|
|
417
|
+
send: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
418
|
+
/* @__PURE__ */ jsx2("path", { d: "M9 14.5v-11" }),
|
|
419
|
+
/* @__PURE__ */ jsx2("path", { d: "m4.75 7.75 4.25-4.25 4.25 4.25" })
|
|
420
|
+
] }),
|
|
421
|
+
stop: () => /* @__PURE__ */ jsx2("rect", { x: "4.5", y: "4.5", width: "9", height: "9", rx: "1.5", fill: "currentColor", stroke: "none" })
|
|
422
|
+
};
|
|
423
|
+
function UiIcon({ name, size = 16, class: className = "" }) {
|
|
424
|
+
const Glyph = ICONS[name];
|
|
425
|
+
if (!Glyph) return null;
|
|
426
|
+
return /* @__PURE__ */ jsx2("svg", { class: `scui-icon ${className}`, style: { "--scui-icon-size": `${size}px` }, viewBox: "0 0 18 18", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx2(Glyph, {}) });
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// src/conversation.jsx
|
|
430
|
+
import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs2 } from "preact/jsx-runtime";
|
|
310
431
|
function LoadingStatus({ state, compact = false }) {
|
|
311
432
|
const copy = {
|
|
312
433
|
connecting: ["Connecting to coding agents", "Checking installed harnesses and capabilities.", 0],
|
|
@@ -314,81 +435,104 @@ function LoadingStatus({ state, compact = false }) {
|
|
|
314
435
|
discovering: ["Loading recent sessions", "Scanning native session stores without loading full transcripts.", 2],
|
|
315
436
|
ready: ["Ready", "Coding sessions are up to date.", 3]
|
|
316
437
|
}[state.startup];
|
|
317
|
-
return /* @__PURE__ */
|
|
318
|
-
/* @__PURE__ */
|
|
319
|
-
/* @__PURE__ */
|
|
320
|
-
/* @__PURE__ */
|
|
321
|
-
/* @__PURE__ */
|
|
438
|
+
return /* @__PURE__ */ jsxs2("div", { class: `scui-loading${compact ? " scui-loading-compact" : ""}`, role: "status", "aria-busy": state.startup !== "ready", children: [
|
|
439
|
+
/* @__PURE__ */ jsx3("span", { class: "scui-orbit", "aria-hidden": "true", children: /* @__PURE__ */ jsx3("i", {}) }),
|
|
440
|
+
/* @__PURE__ */ jsxs2("span", { class: "scui-loading-copy", children: [
|
|
441
|
+
/* @__PURE__ */ jsx3("strong", { children: copy[0] }),
|
|
442
|
+
/* @__PURE__ */ jsx3("small", { children: copy[1] })
|
|
322
443
|
] }),
|
|
323
|
-
/* @__PURE__ */
|
|
444
|
+
/* @__PURE__ */ jsx3("span", { class: "scui-progress", "aria-hidden": "true", children: [1, 2, 3].map((step) => /* @__PURE__ */ jsx3("i", { "data-progress": step <= copy[2] ? "done" : step === copy[2] + 1 ? "current" : "waiting" }, step)) })
|
|
324
445
|
] });
|
|
325
446
|
}
|
|
326
447
|
function RequestCard({ entry, adapter, canRespond }) {
|
|
327
448
|
const request = entry.request;
|
|
328
449
|
if (!request) return null;
|
|
329
450
|
if (request.status === "responded") {
|
|
330
|
-
return /* @__PURE__ */
|
|
451
|
+
return /* @__PURE__ */ jsxs2("div", { class: "scui-request-done", children: [
|
|
331
452
|
"\u2713 Request answered \xB7 ",
|
|
332
453
|
request.resolution?.name ?? request.requestKind
|
|
333
454
|
] });
|
|
334
455
|
}
|
|
335
|
-
return /* @__PURE__ */
|
|
336
|
-
/* @__PURE__ */
|
|
337
|
-
/* @__PURE__ */
|
|
338
|
-
/* @__PURE__ */
|
|
339
|
-
request.options.map((option) => /* @__PURE__ */
|
|
340
|
-
request.cancellable ? /* @__PURE__ */
|
|
456
|
+
return /* @__PURE__ */ jsxs2("section", { class: "scui-request", role: "alert", "aria-label": `${request.requestKind} needs input`, children: [
|
|
457
|
+
/* @__PURE__ */ jsx3("strong", { children: "Agent needs input" }),
|
|
458
|
+
/* @__PURE__ */ jsx3(Markdown, { value: request.payloadText || entry.text, copyText: adapter?.copyText }),
|
|
459
|
+
/* @__PURE__ */ jsxs2("div", { class: "scui-request-actions", children: [
|
|
460
|
+
request.options.map((option) => /* @__PURE__ */ jsx3("button", { type: "button", disabled: !canRespond, onClick: () => adapter.onIntent({ action: "respond", requestId: request.requestId, optionId: option.optionId }), children: option.name }, option.optionId)),
|
|
461
|
+
request.cancellable ? /* @__PURE__ */ jsx3("button", { type: "button", disabled: !canRespond, onClick: () => adapter.onIntent({ action: "respond", requestId: request.requestId, optionId: null }), children: "Cancel" }) : null
|
|
341
462
|
] })
|
|
342
463
|
] });
|
|
343
464
|
}
|
|
344
465
|
function ContextDisclosure({ context }) {
|
|
345
466
|
if (!context?.length) return null;
|
|
346
|
-
return /* @__PURE__ */
|
|
347
|
-
/* @__PURE__ */
|
|
467
|
+
return /* @__PURE__ */ jsxs2("details", { class: "scui-context", children: [
|
|
468
|
+
/* @__PURE__ */ jsxs2("summary", { children: [
|
|
348
469
|
"Context \xB7 ",
|
|
349
470
|
context.length
|
|
350
471
|
] }),
|
|
351
|
-
/* @__PURE__ */
|
|
352
|
-
/* @__PURE__ */
|
|
353
|
-
/* @__PURE__ */
|
|
472
|
+
/* @__PURE__ */ jsx3("div", { children: context.map((item, index) => /* @__PURE__ */ jsxs2("p", { children: [
|
|
473
|
+
/* @__PURE__ */ jsx3("strong", { children: item.label }),
|
|
474
|
+
/* @__PURE__ */ jsx3("span", { children: item.detail })
|
|
354
475
|
] }, item.id ?? index)) })
|
|
355
476
|
] });
|
|
356
477
|
}
|
|
478
|
+
function MessageMeta({ entry, adapter }) {
|
|
479
|
+
const [copyState, setCopyState2] = useState("idle");
|
|
480
|
+
const reset = useRef2(null);
|
|
481
|
+
useEffect2(() => () => clearTimeout(reset.current), []);
|
|
482
|
+
const date = entry.ts === null ? null : new Date(entry.ts);
|
|
483
|
+
const validDate = date && Number.isFinite(date.valueOf()) ? date : null;
|
|
484
|
+
if (!validDate && (!adapter?.copyText || !entry.text)) return null;
|
|
485
|
+
const copy = async () => {
|
|
486
|
+
try {
|
|
487
|
+
await adapter.copyText(entry.text);
|
|
488
|
+
setCopyState2("copied");
|
|
489
|
+
} catch {
|
|
490
|
+
setCopyState2("failed");
|
|
491
|
+
}
|
|
492
|
+
clearTimeout(reset.current);
|
|
493
|
+
reset.current = setTimeout(() => setCopyState2("idle"), 1500);
|
|
494
|
+
};
|
|
495
|
+
const copyLabel = copyState === "copied" ? "Message copied" : copyState === "failed" ? "Copy failed \xB7 retry" : "Copy message";
|
|
496
|
+
return /* @__PURE__ */ jsxs2("footer", { class: "scui-message-meta", children: [
|
|
497
|
+
validDate ? /* @__PURE__ */ jsx3("time", { dateTime: validDate.toISOString(), title: validDate.toLocaleString(), children: validDate.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) }) : null,
|
|
498
|
+
adapter?.copyText && entry.text ? /* @__PURE__ */ jsx3("button", { type: "button", "aria-label": copyLabel, title: copyLabel, onClick: copy, "data-status": copyState, children: /* @__PURE__ */ jsx3(UiIcon, { name: "copy", size: 13 }) }) : null
|
|
499
|
+
] });
|
|
500
|
+
}
|
|
357
501
|
var TOOL_ICONS = {
|
|
358
|
-
read: () => /* @__PURE__ */
|
|
359
|
-
/* @__PURE__ */
|
|
360
|
-
/* @__PURE__ */
|
|
502
|
+
read: () => /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
503
|
+
/* @__PURE__ */ jsx3("path", { d: "M5 2.75h7.25L15 5.5v7.75A1.75 1.75 0 0 1 13.25 15h-8.5A1.75 1.75 0 0 1 3 13.25v-8.5A2 2 0 0 1 5 2.75Z" }),
|
|
504
|
+
/* @__PURE__ */ jsx3("path", { d: "M12 2.9v3h2.85M6 9h6M6 12h4" })
|
|
361
505
|
] }),
|
|
362
|
-
search: () => /* @__PURE__ */
|
|
363
|
-
/* @__PURE__ */
|
|
364
|
-
/* @__PURE__ */
|
|
506
|
+
search: () => /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
507
|
+
/* @__PURE__ */ jsx3("circle", { cx: "8", cy: "8", r: "4.5" }),
|
|
508
|
+
/* @__PURE__ */ jsx3("path", { d: "m11.5 11.5 3 3" })
|
|
365
509
|
] }),
|
|
366
|
-
edit: () => /* @__PURE__ */
|
|
367
|
-
/* @__PURE__ */
|
|
368
|
-
/* @__PURE__ */
|
|
510
|
+
edit: () => /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
511
|
+
/* @__PURE__ */ jsx3("path", { d: "m11.75 3.25 3 3-8.5 8.5-3.75.75.75-3.75 8.5-8.5Z" }),
|
|
512
|
+
/* @__PURE__ */ jsx3("path", { d: "m10 5 3 3" })
|
|
369
513
|
] }),
|
|
370
|
-
command: () => /* @__PURE__ */
|
|
371
|
-
test: () => /* @__PURE__ */
|
|
372
|
-
/* @__PURE__ */
|
|
373
|
-
/* @__PURE__ */
|
|
514
|
+
command: () => /* @__PURE__ */ jsx3(Fragment3, { children: /* @__PURE__ */ jsx3("path", { d: "m3 5 3 3-3 3M8 12h6" }) }),
|
|
515
|
+
test: () => /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
516
|
+
/* @__PURE__ */ jsx3("path", { d: "M6 2.5v3L3 12a2 2 0 0 0 1.8 3h8.4a2 2 0 0 0 1.8-3l-3-6.5v-3M5 9h8" }),
|
|
517
|
+
/* @__PURE__ */ jsx3("path", { d: "M5 2.5h8" })
|
|
374
518
|
] }),
|
|
375
|
-
web: () => /* @__PURE__ */
|
|
376
|
-
/* @__PURE__ */
|
|
377
|
-
/* @__PURE__ */
|
|
519
|
+
web: () => /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
520
|
+
/* @__PURE__ */ jsx3("circle", { cx: "9", cy: "9", r: "6.5" }),
|
|
521
|
+
/* @__PURE__ */ jsx3("path", { d: "M2.75 9h12.5M9 2.5c2 1.8 3 4 3 6.5s-1 4.7-3 6.5c-2-1.8-3-4-3-6.5s1-4.7 3-6.5Z" })
|
|
378
522
|
] }),
|
|
379
|
-
agent: () => /* @__PURE__ */
|
|
380
|
-
/* @__PURE__ */
|
|
381
|
-
/* @__PURE__ */
|
|
523
|
+
agent: () => /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
524
|
+
/* @__PURE__ */ jsx3("circle", { cx: "9", cy: "6", r: "2.5" }),
|
|
525
|
+
/* @__PURE__ */ jsx3("path", { d: "M4 15c.4-3 2-4.5 5-4.5s4.6 1.5 5 4.5" })
|
|
382
526
|
] }),
|
|
383
|
-
plan: () => /* @__PURE__ */
|
|
384
|
-
other: () => /* @__PURE__ */
|
|
385
|
-
/* @__PURE__ */
|
|
386
|
-
/* @__PURE__ */
|
|
527
|
+
plan: () => /* @__PURE__ */ jsx3(Fragment3, { children: /* @__PURE__ */ jsx3("path", { d: "m3 5 1 1 2-2M3 9l1 1 2-2M3 13l1 1 2-2M8 5h7M8 9h7M8 13h7" }) }),
|
|
528
|
+
other: () => /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
529
|
+
/* @__PURE__ */ jsx3("path", { d: "M9 2.5v3M9 12.5v3M2.5 9h3M12.5 9h3" }),
|
|
530
|
+
/* @__PURE__ */ jsx3("circle", { cx: "9", cy: "9", r: "3.5" })
|
|
387
531
|
] })
|
|
388
532
|
};
|
|
389
533
|
function ToolIcon({ category }) {
|
|
390
534
|
const Glyph = TOOL_ICONS[category] ?? TOOL_ICONS.other;
|
|
391
|
-
return /* @__PURE__ */
|
|
535
|
+
return /* @__PURE__ */ jsx3("svg", { class: "scui-tool-icon", viewBox: "0 0 18 18", fill: "none", stroke: "currentColor", "stroke-width": "1.35", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx3(Glyph, {}) });
|
|
392
536
|
}
|
|
393
537
|
function toolAction2(entry, category, presentation) {
|
|
394
538
|
if (presentation?.action) return presentation.action;
|
|
@@ -443,86 +587,86 @@ function ToolMetrics({ presentation }) {
|
|
|
443
587
|
presentation.exitCode === null ? "" : `exit ${presentation.exitCode}`,
|
|
444
588
|
formatDuration(presentation.durationMs)
|
|
445
589
|
].filter(Boolean);
|
|
446
|
-
return metrics.length ? /* @__PURE__ */
|
|
590
|
+
return metrics.length ? /* @__PURE__ */ jsx3("div", { class: "scui-tool-metrics", children: metrics.map((metric) => /* @__PURE__ */ jsx3("span", { children: metric }, metric)) }) : null;
|
|
447
591
|
}
|
|
448
592
|
function PendingElapsed({ now }) {
|
|
449
593
|
const clock = now ?? Date.now;
|
|
450
|
-
const started =
|
|
594
|
+
const started = useRef2(clock());
|
|
451
595
|
const [elapsed, setElapsed] = useState(0);
|
|
452
|
-
|
|
596
|
+
useEffect2(() => {
|
|
453
597
|
const timer = setInterval(() => setElapsed(Math.max(0, clock() - started.current)), 1e3);
|
|
454
598
|
return () => clearInterval(timer);
|
|
455
599
|
}, [clock]);
|
|
456
|
-
return /* @__PURE__ */
|
|
600
|
+
return /* @__PURE__ */ jsx3("small", { class: "scui-tool-elapsed", children: elapsed < 1e3 ? "now" : formatDuration(elapsed) });
|
|
457
601
|
}
|
|
458
602
|
function LinePreview({ value, kind }) {
|
|
459
603
|
if (!value) return null;
|
|
460
|
-
return /* @__PURE__ */
|
|
604
|
+
return /* @__PURE__ */ jsx3("ol", { class: "scui-code-preview", "data-kind": kind, children: stripAnsi(value).split("\n").map((line, index) => {
|
|
461
605
|
const tone = kind === "diff" ? line.startsWith("+") && !line.startsWith("+++") ? "add" : line.startsWith("-") && !line.startsWith("---") ? "remove" : line.startsWith("@@") ? "hunk" : "plain" : "plain";
|
|
462
|
-
return /* @__PURE__ */
|
|
463
|
-
/* @__PURE__ */
|
|
464
|
-
/* @__PURE__ */
|
|
606
|
+
return /* @__PURE__ */ jsxs2("li", { "data-tone": tone, children: [
|
|
607
|
+
/* @__PURE__ */ jsx3("span", { children: index + 1 }),
|
|
608
|
+
/* @__PURE__ */ jsx3("code", { children: line || " " })
|
|
465
609
|
] }, index);
|
|
466
610
|
}) });
|
|
467
611
|
}
|
|
468
612
|
function TerminalPreview({ presentation, pending, failed }) {
|
|
469
|
-
return /* @__PURE__ */
|
|
470
|
-
/* @__PURE__ */
|
|
471
|
-
/* @__PURE__ */
|
|
472
|
-
/* @__PURE__ */
|
|
473
|
-
/* @__PURE__ */
|
|
474
|
-
/* @__PURE__ */
|
|
613
|
+
return /* @__PURE__ */ jsxs2("section", { class: "scui-terminal", children: [
|
|
614
|
+
/* @__PURE__ */ jsxs2("header", { children: [
|
|
615
|
+
/* @__PURE__ */ jsxs2("span", { "aria-hidden": "true", children: [
|
|
616
|
+
/* @__PURE__ */ jsx3("i", {}),
|
|
617
|
+
/* @__PURE__ */ jsx3("i", {}),
|
|
618
|
+
/* @__PURE__ */ jsx3("i", {})
|
|
475
619
|
] }),
|
|
476
|
-
/* @__PURE__ */
|
|
620
|
+
/* @__PURE__ */ jsx3("code", { children: presentation.command ? `$ ${presentation.command}` : "Terminal" })
|
|
477
621
|
] }),
|
|
478
|
-
presentation.preview ? /* @__PURE__ */
|
|
479
|
-
/* @__PURE__ */
|
|
622
|
+
presentation.preview ? /* @__PURE__ */ jsx3("pre", { "data-error": failed, children: stripAnsi(presentation.preview) }) : pending ? /* @__PURE__ */ jsxs2("div", { class: "scui-terminal-wait", children: [
|
|
623
|
+
/* @__PURE__ */ jsx3("i", {}),
|
|
480
624
|
" Waiting for output"
|
|
481
|
-
] }) : /* @__PURE__ */
|
|
625
|
+
] }) : /* @__PURE__ */ jsx3("div", { class: "scui-terminal-empty", children: "No output" })
|
|
482
626
|
] });
|
|
483
627
|
}
|
|
484
628
|
function SearchPreview({ presentation }) {
|
|
485
629
|
const lines = stripAnsi(presentation.preview).split("\n").filter(Boolean);
|
|
486
|
-
return /* @__PURE__ */
|
|
487
|
-
presentation.query ? /* @__PURE__ */
|
|
488
|
-
/* @__PURE__ */
|
|
489
|
-
/* @__PURE__ */
|
|
630
|
+
return /* @__PURE__ */ jsxs2("section", { class: "scui-search-preview", children: [
|
|
631
|
+
presentation.query ? /* @__PURE__ */ jsxs2("header", { children: [
|
|
632
|
+
/* @__PURE__ */ jsx3("span", { children: "Search" }),
|
|
633
|
+
/* @__PURE__ */ jsx3("code", { children: presentation.query })
|
|
490
634
|
] }) : null,
|
|
491
|
-
lines.length ? /* @__PURE__ */
|
|
635
|
+
lines.length ? /* @__PURE__ */ jsx3("ol", { children: lines.map((line, index) => {
|
|
492
636
|
const match = /^(.*?):(\d+)(?::(\d+))?:(.*)$/.exec(line);
|
|
493
|
-
return /* @__PURE__ */
|
|
494
|
-
/* @__PURE__ */
|
|
495
|
-
/* @__PURE__ */
|
|
637
|
+
return /* @__PURE__ */ jsx3("li", { children: match ? /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
638
|
+
/* @__PURE__ */ jsx3("code", { children: match[1] }),
|
|
639
|
+
/* @__PURE__ */ jsxs2("small", { children: [
|
|
496
640
|
match[2],
|
|
497
641
|
match[3] ? `:${match[3]}` : ""
|
|
498
642
|
] }),
|
|
499
|
-
/* @__PURE__ */
|
|
500
|
-
] }) : /* @__PURE__ */
|
|
501
|
-
}) }) : /* @__PURE__ */
|
|
643
|
+
/* @__PURE__ */ jsx3("span", { children: match[4] })
|
|
644
|
+
] }) : /* @__PURE__ */ jsx3("span", { children: line }) }, index);
|
|
645
|
+
}) }) : /* @__PURE__ */ jsx3("p", { children: "No textual results" })
|
|
502
646
|
] });
|
|
503
647
|
}
|
|
504
648
|
function ToolPreview({ presentation, entry }) {
|
|
505
649
|
const pending = entry.status === "pending";
|
|
506
650
|
const failed = entry.status === "error";
|
|
507
|
-
if (presentation.detail === "terminal") return /* @__PURE__ */
|
|
508
|
-
if (presentation.detail === "diff") return presentation.preview ? /* @__PURE__ */
|
|
509
|
-
if (presentation.detail === "file") return presentation.preview ? /* @__PURE__ */
|
|
510
|
-
if (presentation.detail === "matches") return /* @__PURE__ */
|
|
511
|
-
if (presentation.detail === "web") return /* @__PURE__ */
|
|
512
|
-
presentation.url ? /* @__PURE__ */
|
|
513
|
-
presentation.preview ? /* @__PURE__ */
|
|
651
|
+
if (presentation.detail === "terminal") return /* @__PURE__ */ jsx3(TerminalPreview, { presentation, pending, failed });
|
|
652
|
+
if (presentation.detail === "diff") return presentation.preview ? /* @__PURE__ */ jsx3(LinePreview, { value: presentation.preview, kind: "diff" }) : /* @__PURE__ */ jsx3("div", { class: "scui-tool-empty", children: "Edit completed without a textual diff" });
|
|
653
|
+
if (presentation.detail === "file") return presentation.preview ? /* @__PURE__ */ jsx3(LinePreview, { value: presentation.preview, kind: "file" }) : /* @__PURE__ */ jsx3("div", { class: "scui-tool-empty", children: "File contents were not included in this event" });
|
|
654
|
+
if (presentation.detail === "matches") return /* @__PURE__ */ jsx3(SearchPreview, { presentation });
|
|
655
|
+
if (presentation.detail === "web") return /* @__PURE__ */ jsxs2("section", { class: "scui-web-preview", children: [
|
|
656
|
+
presentation.url ? /* @__PURE__ */ jsx3("code", { children: presentation.url }) : null,
|
|
657
|
+
presentation.preview ? /* @__PURE__ */ jsx3("p", { children: stripAnsi(presentation.preview) }) : /* @__PURE__ */ jsx3("small", { children: pending ? "Waiting for the page" : "No page summary returned" })
|
|
514
658
|
] });
|
|
515
|
-
if (presentation.detail === "agent") return /* @__PURE__ */
|
|
516
|
-
if (presentation.detail === "plan") return /* @__PURE__ */
|
|
517
|
-
/* @__PURE__ */
|
|
518
|
-
/* @__PURE__ */
|
|
659
|
+
if (presentation.detail === "agent") return /* @__PURE__ */ jsx3("section", { class: "scui-agent-preview", children: presentation.preview ? /* @__PURE__ */ jsx3("pre", { children: stripAnsi(presentation.preview) }) : /* @__PURE__ */ jsx3("small", { children: pending ? "Agent is working" : "No textual handoff returned" }) });
|
|
660
|
+
if (presentation.detail === "plan") return /* @__PURE__ */ jsx3("ol", { class: "scui-plan-preview", children: presentation.items?.map((item, index) => /* @__PURE__ */ jsxs2("li", { "data-status": item.status, children: [
|
|
661
|
+
/* @__PURE__ */ jsx3("i", { "aria-hidden": "true" }),
|
|
662
|
+
/* @__PURE__ */ jsx3("span", { children: item.label })
|
|
519
663
|
] }, `${item.label}:${index}`)) });
|
|
520
|
-
return presentation.preview ? /* @__PURE__ */
|
|
664
|
+
return presentation.preview ? /* @__PURE__ */ jsx3("pre", { class: "scui-tool-output", "data-error": failed, children: stripAnsi(presentation.preview) }) : null;
|
|
521
665
|
}
|
|
522
666
|
function ToolActions({ presentation, adapter }) {
|
|
523
667
|
const [copied, setCopied] = useState(false);
|
|
524
|
-
const reset =
|
|
525
|
-
|
|
668
|
+
const reset = useRef2(null);
|
|
669
|
+
useEffect2(() => () => clearTimeout(reset.current), []);
|
|
526
670
|
if (!adapter?.copyText) return null;
|
|
527
671
|
const action = presentation.command ? ["Copy command", presentation.command] : presentation.path ? ["Copy path", presentation.path] : presentation.url ? ["Copy URL", presentation.url] : presentation.query ? ["Copy query", presentation.query] : null;
|
|
528
672
|
const copy = async () => {
|
|
@@ -531,27 +675,27 @@ function ToolActions({ presentation, adapter }) {
|
|
|
531
675
|
clearTimeout(reset.current);
|
|
532
676
|
reset.current = setTimeout(() => setCopied(false), 1500);
|
|
533
677
|
};
|
|
534
|
-
return action ? /* @__PURE__ */
|
|
678
|
+
return action ? /* @__PURE__ */ jsx3("div", { class: "scui-tool-actions", children: /* @__PURE__ */ jsx3("button", { type: "button", onClick: copy, children: copied ? "Copied" : action[0] }) }) : null;
|
|
535
679
|
}
|
|
536
680
|
function ToolStack({ tools }) {
|
|
537
681
|
if (tools.length < 2) return null;
|
|
538
|
-
return /* @__PURE__ */
|
|
682
|
+
return /* @__PURE__ */ jsx3("div", { class: "scui-tool-stack", "aria-label": "Coordinated tools", children: tools.map((tool) => /* @__PURE__ */ jsx3("span", { children: tool.replaceAll("__", " \xB7 ").replaceAll("_", " ") }, tool)) });
|
|
539
683
|
}
|
|
540
684
|
function TechnicalDetails({ entry }) {
|
|
541
685
|
if (!entry.arguments && !entry.resultText) return null;
|
|
542
|
-
return /* @__PURE__ */
|
|
543
|
-
/* @__PURE__ */
|
|
544
|
-
/* @__PURE__ */
|
|
545
|
-
entry.arguments ? /* @__PURE__ */
|
|
546
|
-
/* @__PURE__ */
|
|
547
|
-
/* @__PURE__ */
|
|
548
|
-
/* @__PURE__ */
|
|
549
|
-
/* @__PURE__ */
|
|
686
|
+
return /* @__PURE__ */ jsxs2("details", { class: "scui-tool-technical", children: [
|
|
687
|
+
/* @__PURE__ */ jsx3("summary", { children: "Technical details" }),
|
|
688
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
689
|
+
entry.arguments ? /* @__PURE__ */ jsxs2("section", { children: [
|
|
690
|
+
/* @__PURE__ */ jsx3("strong", { children: "Native arguments" }),
|
|
691
|
+
/* @__PURE__ */ jsx3("dl", { children: argumentRows(entry.arguments).map((row) => /* @__PURE__ */ jsxs2("div", { children: [
|
|
692
|
+
/* @__PURE__ */ jsx3("dt", { children: row.label }),
|
|
693
|
+
/* @__PURE__ */ jsx3("dd", { children: /* @__PURE__ */ jsx3("pre", { children: row.value }) })
|
|
550
694
|
] }, row.key)) })
|
|
551
695
|
] }) : null,
|
|
552
|
-
entry.resultText ? /* @__PURE__ */
|
|
553
|
-
/* @__PURE__ */
|
|
554
|
-
/* @__PURE__ */
|
|
696
|
+
entry.resultText ? /* @__PURE__ */ jsxs2("section", { children: [
|
|
697
|
+
/* @__PURE__ */ jsx3("strong", { children: "Native result" }),
|
|
698
|
+
/* @__PURE__ */ jsxs2("pre", { "data-error": entry.status === "error", children: [
|
|
555
699
|
entry.resultText,
|
|
556
700
|
entry.truncated ? "\n[truncated]" : ""
|
|
557
701
|
] })
|
|
@@ -560,125 +704,126 @@ function TechnicalDetails({ entry }) {
|
|
|
560
704
|
] });
|
|
561
705
|
}
|
|
562
706
|
function TranscriptEntry({ entry, state, adapter }) {
|
|
563
|
-
if (entry.role === "request") return /* @__PURE__ */
|
|
707
|
+
if (entry.role === "request") return /* @__PURE__ */ jsx3(RequestCard, { entry, adapter, canRespond: state.canRespond });
|
|
564
708
|
if (entry.role === "reasoning") {
|
|
565
|
-
return /* @__PURE__ */
|
|
566
|
-
/* @__PURE__ */
|
|
567
|
-
/* @__PURE__ */
|
|
709
|
+
return /* @__PURE__ */ jsxs2("details", { class: "scui-reasoning", open: entry.streaming, children: [
|
|
710
|
+
/* @__PURE__ */ jsx3("summary", { children: entry.streaming ? "Reasoning\u2026" : "Reasoning" }),
|
|
711
|
+
/* @__PURE__ */ jsx3(Markdown, { value: entry.text, copyText: adapter?.copyText })
|
|
568
712
|
] });
|
|
569
713
|
}
|
|
570
|
-
if (entry.role === "notice" || entry.role === "system") return /* @__PURE__ */
|
|
571
|
-
return /* @__PURE__ */
|
|
572
|
-
/* @__PURE__ */
|
|
573
|
-
/* @__PURE__ */
|
|
574
|
-
entry.truncated ? /* @__PURE__ */
|
|
714
|
+
if (entry.role === "notice" || entry.role === "system") return /* @__PURE__ */ jsx3("div", { class: "scui-notice", "data-code": entry.code, children: entry.text });
|
|
715
|
+
return /* @__PURE__ */ jsxs2("article", { class: "scui-message", "data-role": entry.role, "aria-label": `${entry.role === "user" ? "Your" : "Assistant"} message`, children: [
|
|
716
|
+
/* @__PURE__ */ jsx3(Markdown, { value: entry.text, copyText: adapter?.copyText }),
|
|
717
|
+
/* @__PURE__ */ jsx3(ContextDisclosure, { context: entry.context }),
|
|
718
|
+
entry.truncated ? /* @__PURE__ */ jsx3("small", { class: "scui-truncated", children: "Entry truncated by host \xB7 load native session for the complete value" }) : null,
|
|
719
|
+
/* @__PURE__ */ jsx3(MessageMeta, { entry, adapter })
|
|
575
720
|
] });
|
|
576
721
|
}
|
|
577
722
|
function ToolRow({ entry, workspace, open = false, adapter }) {
|
|
578
723
|
const presentation = entry.presentation ?? createToolPresentation(entry);
|
|
579
724
|
const [expanded, setExpanded] = useState(open || entry.status === "pending");
|
|
580
|
-
|
|
725
|
+
useEffect2(() => {
|
|
581
726
|
if (entry.status === "pending") setExpanded(true);
|
|
582
727
|
}, [entry.status]);
|
|
583
728
|
const target = compactToolTarget(presentation.target, workspace);
|
|
584
729
|
const hasDetail = Boolean(entry.arguments || entry.resultText || presentation.preview || presentation.fields.length);
|
|
585
730
|
const category = presentation.category ?? toolCategory(entry);
|
|
586
|
-
const summary = /* @__PURE__ */
|
|
587
|
-
/* @__PURE__ */
|
|
588
|
-
/* @__PURE__ */
|
|
589
|
-
target ? /* @__PURE__ */
|
|
590
|
-
/* @__PURE__ */
|
|
591
|
-
entry.status === "pending" ? /* @__PURE__ */
|
|
592
|
-
/* @__PURE__ */
|
|
593
|
-
hasDetail ? /* @__PURE__ */
|
|
731
|
+
const summary = /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
732
|
+
/* @__PURE__ */ jsx3(ToolIcon, { category }),
|
|
733
|
+
/* @__PURE__ */ jsx3("strong", { children: toolAction2(entry, category, presentation) }),
|
|
734
|
+
target ? /* @__PURE__ */ jsx3("code", { class: "scui-tool-target", title: presentation.target, children: target }) : null,
|
|
735
|
+
/* @__PURE__ */ jsx3("span", { class: "scui-spacer" }),
|
|
736
|
+
entry.status === "pending" ? /* @__PURE__ */ jsx3(PendingElapsed, { now: adapter?.now }) : null,
|
|
737
|
+
/* @__PURE__ */ jsx3("span", { class: "scui-tool-status", role: "status", "data-status": entry.status ?? "completed", "aria-label": entry.status ?? "completed", children: entry.status === "pending" ? /* @__PURE__ */ jsx3("i", {}) : /* @__PURE__ */ jsx3(UiIcon, { name: entry.status === "error" ? "close" : "check", size: 12 }) }),
|
|
738
|
+
hasDetail ? /* @__PURE__ */ jsx3(UiIcon, { name: "chevron", size: 14, class: "scui-tool-chevron" }) : null
|
|
594
739
|
] });
|
|
595
|
-
if (!hasDetail) return /* @__PURE__ */
|
|
596
|
-
return /* @__PURE__ */
|
|
597
|
-
/* @__PURE__ */
|
|
598
|
-
/* @__PURE__ */
|
|
599
|
-
/* @__PURE__ */
|
|
600
|
-
/* @__PURE__ */
|
|
601
|
-
/* @__PURE__ */
|
|
602
|
-
presentation.fields.length ? /* @__PURE__ */
|
|
603
|
-
/* @__PURE__ */
|
|
604
|
-
/* @__PURE__ */
|
|
740
|
+
if (!hasDetail) return /* @__PURE__ */ jsx3("div", { class: "scui-tool", "data-status": entry.status ?? "completed", "data-category": category, children: /* @__PURE__ */ jsx3("div", { class: "scui-tool-head", children: summary }) });
|
|
741
|
+
return /* @__PURE__ */ jsxs2("details", { class: "scui-tool", "data-status": entry.status ?? "completed", "data-category": category, open: expanded, onToggle: (event) => setExpanded(event.currentTarget.open), children: [
|
|
742
|
+
/* @__PURE__ */ jsx3("summary", { class: "scui-tool-head", children: summary }),
|
|
743
|
+
/* @__PURE__ */ jsxs2("div", { class: "scui-tool-detail", children: [
|
|
744
|
+
/* @__PURE__ */ jsx3(ToolMetrics, { presentation }),
|
|
745
|
+
/* @__PURE__ */ jsx3(ToolStack, { tools: presentation.tools ?? [] }),
|
|
746
|
+
/* @__PURE__ */ jsx3(ToolPreview, { presentation, entry }),
|
|
747
|
+
presentation.fields.length ? /* @__PURE__ */ jsx3("dl", { class: "scui-tool-fields", children: presentation.fields.map((field) => /* @__PURE__ */ jsxs2("div", { children: [
|
|
748
|
+
/* @__PURE__ */ jsx3("dt", { children: field.label }),
|
|
749
|
+
/* @__PURE__ */ jsx3("dd", { children: field.value })
|
|
605
750
|
] }, field.label)) }) : null,
|
|
606
|
-
/* @__PURE__ */
|
|
607
|
-
/* @__PURE__ */
|
|
751
|
+
/* @__PURE__ */ jsx3(ToolActions, { presentation, adapter }),
|
|
752
|
+
/* @__PURE__ */ jsx3(TechnicalDetails, { entry })
|
|
608
753
|
] })
|
|
609
754
|
] });
|
|
610
755
|
}
|
|
611
756
|
function ActivityGroup({ entries, state, adapter }) {
|
|
612
|
-
if (entries.length === 1) return /* @__PURE__ */
|
|
757
|
+
if (entries.length === 1) return /* @__PURE__ */ jsx3("section", { class: "scui-activity", "data-single": "true", children: /* @__PURE__ */ jsx3(ToolRow, { entry: entries[0], workspace: state.workspace, adapter }) });
|
|
613
758
|
const active = entries.some((entry) => entry.status === "pending");
|
|
614
759
|
const [open, setOpen] = useState(active);
|
|
615
760
|
const id = useId();
|
|
616
|
-
|
|
761
|
+
useEffect2(() => {
|
|
617
762
|
if (active) setOpen(true);
|
|
618
763
|
}, [active]);
|
|
619
|
-
return /* @__PURE__ */
|
|
620
|
-
/* @__PURE__ */
|
|
621
|
-
/* @__PURE__ */
|
|
622
|
-
/* @__PURE__ */
|
|
623
|
-
/* @__PURE__ */
|
|
624
|
-
/* @__PURE__ */
|
|
764
|
+
return /* @__PURE__ */ jsxs2("section", { class: "scui-activity", children: [
|
|
765
|
+
/* @__PURE__ */ jsxs2("button", { class: "scui-activity-head", type: "button", "aria-expanded": open, "aria-controls": id, onClick: () => setOpen((value) => !value), children: [
|
|
766
|
+
/* @__PURE__ */ jsx3("span", { class: "scui-fold", "data-open": open, children: /* @__PURE__ */ jsx3(UiIcon, { name: "chevron", size: 14 }) }),
|
|
767
|
+
/* @__PURE__ */ jsx3("strong", { children: activitySummary(entries) }),
|
|
768
|
+
/* @__PURE__ */ jsx3("span", { class: "scui-spacer" }),
|
|
769
|
+
/* @__PURE__ */ jsxs2("small", { children: [
|
|
625
770
|
entries.filter((entry) => entry.status !== "pending").length,
|
|
626
771
|
"/",
|
|
627
772
|
entries.length
|
|
628
773
|
] })
|
|
629
774
|
] }),
|
|
630
|
-
open ? /* @__PURE__ */
|
|
775
|
+
open ? /* @__PURE__ */ jsx3("div", { id, children: entries.map((entry) => /* @__PURE__ */ jsx3(ToolRow, { entry, workspace: state.workspace, adapter }, entry.id)) }) : null
|
|
631
776
|
] });
|
|
632
777
|
}
|
|
633
778
|
function TaskPlan({ plan }) {
|
|
634
779
|
if (!plan.items.length) return null;
|
|
635
780
|
const complete = plan.items.filter((item) => item.status === "completed" || item.status === "cancelled").length;
|
|
636
|
-
return /* @__PURE__ */
|
|
637
|
-
/* @__PURE__ */
|
|
638
|
-
/* @__PURE__ */
|
|
639
|
-
/* @__PURE__ */
|
|
781
|
+
return /* @__PURE__ */ jsxs2("details", { class: "scui-plan", children: [
|
|
782
|
+
/* @__PURE__ */ jsxs2("summary", { children: [
|
|
783
|
+
/* @__PURE__ */ jsx3("span", { children: "Plan" }),
|
|
784
|
+
/* @__PURE__ */ jsxs2("small", { children: [
|
|
640
785
|
complete,
|
|
641
786
|
"/",
|
|
642
787
|
plan.items.length
|
|
643
788
|
] })
|
|
644
789
|
] }),
|
|
645
|
-
/* @__PURE__ */
|
|
646
|
-
/* @__PURE__ */
|
|
790
|
+
/* @__PURE__ */ jsx3("ol", { tabIndex: 0, "aria-label": "Task plan steps", children: plan.items.map((item) => /* @__PURE__ */ jsxs2("li", { "data-status": item.status, children: [
|
|
791
|
+
/* @__PURE__ */ jsx3("i", { "aria-hidden": "true" }),
|
|
647
792
|
" ",
|
|
648
|
-
/* @__PURE__ */
|
|
793
|
+
/* @__PURE__ */ jsx3("span", { children: item.title })
|
|
649
794
|
] }, item.id)) })
|
|
650
795
|
] });
|
|
651
796
|
}
|
|
652
797
|
function SessionDetails({ semantics }) {
|
|
653
798
|
if (!semantics.fidelity && !semantics.residueCount && !semantics.parseErrors && !semantics.subagents.length) return null;
|
|
654
|
-
return /* @__PURE__ */
|
|
655
|
-
/* @__PURE__ */
|
|
656
|
-
/* @__PURE__ */
|
|
657
|
-
semantics.fidelity ? /* @__PURE__ */
|
|
658
|
-
/* @__PURE__ */
|
|
659
|
-
/* @__PURE__ */
|
|
799
|
+
return /* @__PURE__ */ jsxs2("details", { class: "scui-details", children: [
|
|
800
|
+
/* @__PURE__ */ jsx3("summary", { children: "Session details" }),
|
|
801
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
802
|
+
semantics.fidelity ? /* @__PURE__ */ jsxs2("p", { children: [
|
|
803
|
+
/* @__PURE__ */ jsx3("strong", { children: "Fidelity" }),
|
|
804
|
+
/* @__PURE__ */ jsx3("span", { children: semantics.fidelity.replaceAll("_", " ") })
|
|
660
805
|
] }) : null,
|
|
661
|
-
/* @__PURE__ */
|
|
662
|
-
/* @__PURE__ */
|
|
663
|
-
/* @__PURE__ */
|
|
806
|
+
/* @__PURE__ */ jsxs2("p", { children: [
|
|
807
|
+
/* @__PURE__ */ jsx3("strong", { children: "Native records" }),
|
|
808
|
+
/* @__PURE__ */ jsx3("span", { children: semantics.rawRecords })
|
|
664
809
|
] }),
|
|
665
|
-
semantics.residueCount ? /* @__PURE__ */
|
|
666
|
-
/* @__PURE__ */
|
|
667
|
-
/* @__PURE__ */
|
|
810
|
+
semantics.residueCount ? /* @__PURE__ */ jsxs2("p", { children: [
|
|
811
|
+
/* @__PURE__ */ jsx3("strong", { children: "Residue" }),
|
|
812
|
+
/* @__PURE__ */ jsxs2("span", { children: [
|
|
668
813
|
semantics.residueCount,
|
|
669
814
|
" retained"
|
|
670
815
|
] })
|
|
671
816
|
] }) : null,
|
|
672
|
-
semantics.parseErrors ? /* @__PURE__ */
|
|
673
|
-
/* @__PURE__ */
|
|
674
|
-
/* @__PURE__ */
|
|
817
|
+
semantics.parseErrors ? /* @__PURE__ */ jsxs2("p", { children: [
|
|
818
|
+
/* @__PURE__ */ jsx3("strong", { children: "Parse diagnostics" }),
|
|
819
|
+
/* @__PURE__ */ jsx3("span", { children: semantics.parseErrors })
|
|
675
820
|
] }) : null,
|
|
676
|
-
semantics.subagents.map((agent) => /* @__PURE__ */
|
|
677
|
-
/* @__PURE__ */
|
|
821
|
+
semantics.subagents.map((agent) => /* @__PURE__ */ jsxs2("p", { children: [
|
|
822
|
+
/* @__PURE__ */ jsxs2("strong", { children: [
|
|
678
823
|
agent.source,
|
|
679
824
|
" subagent"
|
|
680
825
|
] }),
|
|
681
|
-
/* @__PURE__ */
|
|
826
|
+
/* @__PURE__ */ jsxs2("span", { children: [
|
|
682
827
|
agent.messages,
|
|
683
828
|
" messages \xB7 ",
|
|
684
829
|
agent.fidelity.replaceAll("_", " ")
|
|
@@ -688,13 +833,29 @@ function SessionDetails({ semantics }) {
|
|
|
688
833
|
] });
|
|
689
834
|
}
|
|
690
835
|
var conversationMemory = /* @__PURE__ */ new Map();
|
|
691
|
-
function
|
|
692
|
-
const
|
|
836
|
+
function ConversationAnnouncements({ state }) {
|
|
837
|
+
const previousBusy = useRef2(state.busy);
|
|
838
|
+
const [announcement, setAnnouncement] = useState("");
|
|
839
|
+
useEffect2(() => {
|
|
840
|
+
if (previousBusy.current && !state.busy && !state.error) {
|
|
841
|
+
setAnnouncement(`${harnessDisplayName(state.harness) || "Coding agent"} finished working`);
|
|
842
|
+
}
|
|
843
|
+
previousBusy.current = state.busy;
|
|
844
|
+
}, [state.busy, state.error, state.harness]);
|
|
845
|
+
return /* @__PURE__ */ jsx3("span", { class: "scui-sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement });
|
|
846
|
+
}
|
|
847
|
+
function Conversation({ state, adapter, components = {}, slots = {}, memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`, pending = null, unreadAfterMessages = null }) {
|
|
848
|
+
const scroller = useRef2(null);
|
|
693
849
|
const remembered = conversationMemory.get(memoryKey) ?? { top: null, atBottom: true };
|
|
694
850
|
const [atBottom, setAtBottom] = useState(remembered.atBottom);
|
|
695
|
-
const earlierAnchor =
|
|
696
|
-
const restored =
|
|
851
|
+
const earlierAnchor = useRef2(null);
|
|
852
|
+
const restored = useRef2(false);
|
|
697
853
|
const blocks = groupConversation(state.transcript);
|
|
854
|
+
const unreadBoundary = useRef2(Number.isSafeInteger(unreadAfterMessages) && unreadAfterMessages >= 0 ? unreadAfterMessages : null);
|
|
855
|
+
const unreadBlock = unreadBoundary.current === null ? -1 : blocks.findIndex((block) => {
|
|
856
|
+
const entries = block.kind === "activity" ? block.entries : [block.entry];
|
|
857
|
+
return entries.some((entry) => Number.isSafeInteger(entry.messageIndex) && entry.messageIndex > unreadBoundary.current);
|
|
858
|
+
});
|
|
698
859
|
const Entry = components.TranscriptEntry ?? TranscriptEntry;
|
|
699
860
|
const Group = components.ActivityGroup ?? ActivityGroup;
|
|
700
861
|
const Plan = components.TaskPlan ?? TaskPlan;
|
|
@@ -725,48 +886,55 @@ function Conversation({ state, adapter, components = {}, slots = {}, memoryKey =
|
|
|
725
886
|
else pin();
|
|
726
887
|
} else if (atBottom) pin();
|
|
727
888
|
}, [memoryKey, state.transcript, state.busy, state.operation, pendingMessage?.text, pendingMessage?.status]);
|
|
728
|
-
return /* @__PURE__ */
|
|
729
|
-
/* @__PURE__ */
|
|
889
|
+
return /* @__PURE__ */ jsxs2("div", { class: "scui-conversation-wrap", children: [
|
|
890
|
+
/* @__PURE__ */ jsx3(ConversationAnnouncements, { state }),
|
|
891
|
+
/* @__PURE__ */ jsx3("div", { class: "scui-conversation", ref: scroller, tabIndex: 0, "aria-label": "Conversation", onScroll: (event) => {
|
|
730
892
|
const element = event.currentTarget;
|
|
731
893
|
const bottom = element.scrollHeight - element.scrollTop - element.clientHeight <= 64;
|
|
732
894
|
setAtBottom(bottom);
|
|
733
895
|
remember({ top: element.scrollTop, atBottom: bottom });
|
|
734
|
-
}, children: /* @__PURE__ */
|
|
735
|
-
Before ? /* @__PURE__ */
|
|
736
|
-
/* @__PURE__ */
|
|
737
|
-
/* @__PURE__ */
|
|
738
|
-
state.history.hasEarlier ? /* @__PURE__ */
|
|
896
|
+
}, children: /* @__PURE__ */ jsxs2("div", { children: [
|
|
897
|
+
Before ? /* @__PURE__ */ jsx3(Before, { state, adapter, value: null }) : null,
|
|
898
|
+
/* @__PURE__ */ jsx3(Plan, { plan: state.taskPlan, value: state.taskPlan, state, adapter }),
|
|
899
|
+
/* @__PURE__ */ jsx3(SessionDetails, { semantics: state.semantics }),
|
|
900
|
+
state.history.hasEarlier ? /* @__PURE__ */ jsx3("button", { class: "scui-load", type: "button", disabled: Boolean(state.operation), onClick: () => {
|
|
739
901
|
const element = scroller.current;
|
|
740
902
|
if (element) earlierAnchor.current = { height: element.scrollHeight, top: element.scrollTop, entries: state.transcript.length };
|
|
741
903
|
setAtBottom(false);
|
|
742
904
|
adapter.onIntent({ action: "loadEarlier" });
|
|
743
905
|
}, children: "Load earlier messages" }) : null,
|
|
744
|
-
!blocks.length && state.startup !== "ready" ? /* @__PURE__ */
|
|
745
|
-
!blocks.length && state.startup === "ready" ? Empty ? /* @__PURE__ */
|
|
746
|
-
blocks.map((block
|
|
747
|
-
|
|
748
|
-
/* @__PURE__ */
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
906
|
+
!blocks.length && state.startup !== "ready" ? /* @__PURE__ */ jsx3(LoadingStatus, { state }) : null,
|
|
907
|
+
!blocks.length && state.startup === "ready" ? Empty ? /* @__PURE__ */ jsx3(Empty, { state, adapter, value: null }) : /* @__PURE__ */ jsx3("div", { class: "scui-empty", children: state.error ?? (state.harness ? `${harnessDisplayName(state.harness)} is listening. Say something.` : "No transcript yet.") }) : null,
|
|
908
|
+
blocks.map((block, index) => /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
909
|
+
index === unreadBlock ? /* @__PURE__ */ jsx3("div", { class: "scui-unread-divider", role: "separator", "aria-label": "New messages", children: /* @__PURE__ */ jsx3("span", { children: "New" }) }) : null,
|
|
910
|
+
block.kind === "activity" ? /* @__PURE__ */ jsx3(Group, { value: block.entries, entries: block.entries, state, adapter }) : /* @__PURE__ */ jsx3(Entry, { value: block.entry, entry: block.entry, state, adapter })
|
|
911
|
+
] }, block.id)),
|
|
912
|
+
pendingMessage ? /* @__PURE__ */ jsxs2("article", { class: "scui-message scui-pending", "data-role": "user", "data-status": pendingMessage.status, "aria-label": "Your pending message", children: [
|
|
913
|
+
/* @__PURE__ */ jsx3(Markdown, { value: pendingMessage.text, copyText: adapter?.copyText }),
|
|
914
|
+
/* @__PURE__ */ jsxs2("footer", { children: [
|
|
915
|
+
/* @__PURE__ */ jsx3("small", { children: pendingMessage.status === "failed" ? "Not sent" : "Sending\u2026" }),
|
|
916
|
+
pendingMessage.status === "failed" ? /* @__PURE__ */ jsxs2("span", { children: [
|
|
917
|
+
/* @__PURE__ */ jsx3("button", { type: "button", onClick: pendingMessage.onRetry, children: "Retry" }),
|
|
918
|
+
/* @__PURE__ */ jsx3("button", { type: "button", onClick: pendingMessage.onEdit, children: "Edit" })
|
|
754
919
|
] }) : null
|
|
755
920
|
] })
|
|
756
921
|
] }) : null,
|
|
757
|
-
state.busy ? /* @__PURE__ */
|
|
758
|
-
/* @__PURE__ */
|
|
759
|
-
/* @__PURE__ */
|
|
760
|
-
/* @__PURE__ */
|
|
761
|
-
/* @__PURE__ */
|
|
762
|
-
/* @__PURE__ */
|
|
922
|
+
state.busy ? /* @__PURE__ */ jsxs2("div", { class: "scui-working", role: "status", children: [
|
|
923
|
+
/* @__PURE__ */ jsx3("span", { "aria-hidden": "true", children: "\u2726" }),
|
|
924
|
+
/* @__PURE__ */ jsx3("i", {}),
|
|
925
|
+
/* @__PURE__ */ jsx3("i", {}),
|
|
926
|
+
/* @__PURE__ */ jsx3("i", {}),
|
|
927
|
+
/* @__PURE__ */ jsxs2("small", { children: [
|
|
763
928
|
harnessDisplayName(state.harness),
|
|
764
929
|
" is working"
|
|
765
930
|
] })
|
|
766
931
|
] }) : null,
|
|
767
|
-
After ? /* @__PURE__ */
|
|
932
|
+
After ? /* @__PURE__ */ jsx3(After, { state, adapter, value: null }) : null
|
|
768
933
|
] }) }),
|
|
769
|
-
!atBottom ? /* @__PURE__ */
|
|
934
|
+
!atBottom ? /* @__PURE__ */ jsxs2("button", { class: "scui-latest", type: "button", onClick: pin, children: [
|
|
935
|
+
/* @__PURE__ */ jsx3(UiIcon, { name: "down", size: 13 }),
|
|
936
|
+
" Latest"
|
|
937
|
+
] }) : null
|
|
770
938
|
] });
|
|
771
939
|
}
|
|
772
940
|
export {
|