@invergent/agent-chat-react 2.5.8 → 2.6.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/index.cjs +1539 -421
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +160 -4
- package/dist/index.d.ts +160 -4
- package/dist/index.js +1522 -422
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -18,7 +18,7 @@ var streamdown = require('streamdown');
|
|
|
18
18
|
var reactUseControllableState = require('@radix-ui/react-use-controllable-state');
|
|
19
19
|
var shiki = require('shiki');
|
|
20
20
|
var diff = require('diff');
|
|
21
|
-
var
|
|
21
|
+
var AnsiImport = require('ansi-to-react');
|
|
22
22
|
var cmdk = require('cmdk');
|
|
23
23
|
var nanoid = require('nanoid');
|
|
24
24
|
var tokenlens = require('tokenlens');
|
|
@@ -28,7 +28,7 @@ var dateFns = require('date-fns');
|
|
|
28
28
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
29
29
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
30
30
|
|
|
31
|
-
var
|
|
31
|
+
var AnsiImport__default = /*#__PURE__*/_interopDefault(AnsiImport);
|
|
32
32
|
|
|
33
33
|
var __defProp = Object.defineProperty;
|
|
34
34
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -1025,6 +1025,11 @@ var MessageResponse = react.memo(
|
|
|
1025
1025
|
{
|
|
1026
1026
|
className: cn(
|
|
1027
1027
|
"size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0",
|
|
1028
|
+
// Streamdown emits ``list-inside`` lists and preflight strips
|
|
1029
|
+
// the UA list padding, so bullet markers hug the container
|
|
1030
|
+
// edge and wrapped lines slide under them. Hanging-indent
|
|
1031
|
+
// lists instead, everywhere markdown renders.
|
|
1032
|
+
"[&_ol]:list-outside [&_ol]:pl-5 [&_ul]:list-outside [&_ul]:pl-5",
|
|
1028
1033
|
className
|
|
1029
1034
|
),
|
|
1030
1035
|
plugins: streamdownPlugins,
|
|
@@ -1215,7 +1220,14 @@ var ReasoningContent = react.memo(
|
|
|
1215
1220
|
className
|
|
1216
1221
|
),
|
|
1217
1222
|
...props,
|
|
1218
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1223
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1224
|
+
streamdown.Streamdown,
|
|
1225
|
+
{
|
|
1226
|
+
className: "[&_ol]:list-outside [&_ol]:pl-5 [&_ul]:list-outside [&_ul]:pl-5",
|
|
1227
|
+
plugins: streamdownPlugins2,
|
|
1228
|
+
children
|
|
1229
|
+
}
|
|
1230
|
+
)
|
|
1219
1231
|
}
|
|
1220
1232
|
)
|
|
1221
1233
|
);
|
|
@@ -3309,7 +3321,7 @@ var TerminalContent = ({
|
|
|
3309
3321
|
ref: containerRef,
|
|
3310
3322
|
...props,
|
|
3311
3323
|
children: children ?? /* @__PURE__ */ jsxRuntime.jsxs("pre", { className: "whitespace-pre-wrap break-words", children: [
|
|
3312
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3324
|
+
/* @__PURE__ */ jsxRuntime.jsx(AnsiImport__default.default, { children: output }),
|
|
3313
3325
|
isStreaming && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-0.5 inline-block h-4 w-2 animate-pulse bg-foreground" })
|
|
3314
3326
|
] })
|
|
3315
3327
|
}
|
|
@@ -4573,6 +4585,108 @@ function ResearchOutlineBlock({ tc }) {
|
|
|
4573
4585
|
outline ? /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap font-mono text-[11px] leading-snug", children: outline }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "updated" })
|
|
4574
4586
|
] });
|
|
4575
4587
|
}
|
|
4588
|
+
init_utils();
|
|
4589
|
+
var Ansi2 = AnsiImport__default.default.default ?? AnsiImport__default.default;
|
|
4590
|
+
function parseCodeRun(result, args) {
|
|
4591
|
+
const fallback = {
|
|
4592
|
+
agent: "",
|
|
4593
|
+
provider: "",
|
|
4594
|
+
prompt: "",
|
|
4595
|
+
output: "",
|
|
4596
|
+
finalMessage: "",
|
|
4597
|
+
error: null,
|
|
4598
|
+
inputTokens: 0,
|
|
4599
|
+
outputTokens: 0
|
|
4600
|
+
};
|
|
4601
|
+
if (result) {
|
|
4602
|
+
try {
|
|
4603
|
+
const parsed = JSON.parse(result);
|
|
4604
|
+
return { ...fallback, ...parsed, error: parsed.error ?? null };
|
|
4605
|
+
} catch {
|
|
4606
|
+
}
|
|
4607
|
+
}
|
|
4608
|
+
try {
|
|
4609
|
+
const parsedArgs = JSON.parse(args);
|
|
4610
|
+
return { ...fallback, ...parsedArgs, error: null };
|
|
4611
|
+
} catch {
|
|
4612
|
+
return fallback;
|
|
4613
|
+
}
|
|
4614
|
+
}
|
|
4615
|
+
function agentLabel(state) {
|
|
4616
|
+
if (state.agent) return state.agent;
|
|
4617
|
+
if (state.provider === "anthropic") return "claude";
|
|
4618
|
+
if (state.provider === "openai") return "codex";
|
|
4619
|
+
return "coding agent";
|
|
4620
|
+
}
|
|
4621
|
+
function CodeRunToolBlock({
|
|
4622
|
+
tc,
|
|
4623
|
+
defaultOpen = false
|
|
4624
|
+
}) {
|
|
4625
|
+
const [isOpen, setIsOpen] = react.useState(defaultOpen);
|
|
4626
|
+
const isRunning = tc.status === "running";
|
|
4627
|
+
const state = parseCodeRun(tc.result, tc.args);
|
|
4628
|
+
const label = agentLabel(state);
|
|
4629
|
+
const hasError = tc.status === "error" || Boolean(state.error);
|
|
4630
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4631
|
+
Collapsible,
|
|
4632
|
+
{
|
|
4633
|
+
open: isOpen,
|
|
4634
|
+
onOpenChange: setIsOpen,
|
|
4635
|
+
className: "not-prose w-full",
|
|
4636
|
+
children: [
|
|
4637
|
+
/* @__PURE__ */ jsxRuntime.jsxs(CollapsibleTrigger, { className: "group/trigger flex w-fit items-center gap-2 text-sm transition-colors", children: [
|
|
4638
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-left", children: isRunning ? /* @__PURE__ */ jsxRuntime.jsx(Shimmer, { as: "span", duration: 1, children: `Running ${label}...` }) : hasError ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-destructive", children: `${label} failed` }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-foreground", children: `Ran ${label}` }) }),
|
|
4639
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4640
|
+
lucideReact.ChevronDownIcon,
|
|
4641
|
+
{
|
|
4642
|
+
className: cn(
|
|
4643
|
+
"size-4 shrink-0 transition-transform",
|
|
4644
|
+
isOpen ? "rotate-180" : "rotate-0"
|
|
4645
|
+
)
|
|
4646
|
+
}
|
|
4647
|
+
)
|
|
4648
|
+
] }),
|
|
4649
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4650
|
+
CollapsibleContent,
|
|
4651
|
+
{
|
|
4652
|
+
className: cn(
|
|
4653
|
+
"mt-2 overflow-hidden",
|
|
4654
|
+
"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 outline-none data-[state=closed]:animate-out data-[state=open]:animate-in"
|
|
4655
|
+
),
|
|
4656
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-border overflow-hidden", children: [
|
|
4657
|
+
state.prompt && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 bg-background text-muted-foreground px-3 py-2 font-mono text-sm leading-relaxed", children: [
|
|
4658
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 select-none text-emerald-600", children: "IN" }),
|
|
4659
|
+
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "whitespace-pre-wrap wrap-break-word text-foreground/90 flex-1", children: state.prompt })
|
|
4660
|
+
] }),
|
|
4661
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4662
|
+
"div",
|
|
4663
|
+
{
|
|
4664
|
+
className: cn(
|
|
4665
|
+
"px-3 py-2 bg-background font-mono text-sm leading-relaxed max-h-96 overflow-auto",
|
|
4666
|
+
state.prompt && "border-t border-border"
|
|
4667
|
+
),
|
|
4668
|
+
children: [
|
|
4669
|
+
(state.output || !isRunning) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 text-foreground/90", children: [
|
|
4670
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 select-none text-sky-600", children: "OUT" }),
|
|
4671
|
+
/* @__PURE__ */ jsxRuntime.jsxs("pre", { className: "whitespace-pre-wrap wrap-break-word flex-1", children: [
|
|
4672
|
+
state.output ? /* @__PURE__ */ jsxRuntime.jsx(Ansi2, { children: state.output }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/60", children: "(no output)" }),
|
|
4673
|
+
isRunning && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-0.5 inline-block h-3.5 w-1.5 animate-pulse bg-foreground" })
|
|
4674
|
+
] })
|
|
4675
|
+
] }),
|
|
4676
|
+
isRunning && !state.output && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-0.5 inline-block h-3.5 w-1.5 animate-pulse bg-foreground" })
|
|
4677
|
+
]
|
|
4678
|
+
}
|
|
4679
|
+
),
|
|
4680
|
+
!isRunning && hasError && state.error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border bg-destructive/5 px-3 py-2 text-sm text-destructive", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "whitespace-pre-wrap wrap-break-word", children: state.error }) }),
|
|
4681
|
+
!isRunning && !hasError && state.finalMessage && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border bg-background px-3 py-2 text-sm text-foreground/90", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "whitespace-pre-wrap wrap-break-word", children: state.finalMessage }) }),
|
|
4682
|
+
!isRunning && (state.inputTokens > 0 || state.outputTokens > 0) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border bg-background px-3 py-1.5 text-xs text-muted-foreground", children: `${state.inputTokens.toLocaleString()} in \xB7 ${state.outputTokens.toLocaleString()} out tokens` })
|
|
4683
|
+
] })
|
|
4684
|
+
}
|
|
4685
|
+
)
|
|
4686
|
+
]
|
|
4687
|
+
}
|
|
4688
|
+
);
|
|
4689
|
+
}
|
|
4576
4690
|
function ToolCallBlock({
|
|
4577
4691
|
tc,
|
|
4578
4692
|
resolvedArtifactName,
|
|
@@ -4629,6 +4743,8 @@ function ToolCallBlock({
|
|
|
4629
4743
|
return /* @__PURE__ */ jsxRuntime.jsx(ResearchOutlineBlock, { tc });
|
|
4630
4744
|
case "research_memory":
|
|
4631
4745
|
return /* @__PURE__ */ jsxRuntime.jsx(ResearchMemoryBlock, { tc });
|
|
4746
|
+
case "code_run":
|
|
4747
|
+
return /* @__PURE__ */ jsxRuntime.jsx(CodeRunToolBlock, { tc });
|
|
4632
4748
|
case "spawn_worker":
|
|
4633
4749
|
case "send_worker_message":
|
|
4634
4750
|
case "stop_worker":
|
|
@@ -6222,6 +6338,7 @@ function ChatComposerInner({
|
|
|
6222
6338
|
canShowBrowser = false,
|
|
6223
6339
|
canShowWorkspace = false,
|
|
6224
6340
|
deepResearchEnabled = false,
|
|
6341
|
+
codeAgentsEnabled = false,
|
|
6225
6342
|
viewMode = "simple",
|
|
6226
6343
|
onViewModeChange
|
|
6227
6344
|
}) {
|
|
@@ -6276,9 +6393,18 @@ function ChatComposerInner({
|
|
|
6276
6393
|
description: "Delegate a topic to the deep-research workflow"
|
|
6277
6394
|
});
|
|
6278
6395
|
}
|
|
6396
|
+
if (codeAgentsEnabled) {
|
|
6397
|
+
base.push(
|
|
6398
|
+
{ value: "/code claude ", label: "/code claude", description: "Run Claude Code on the workspace (your plan)" },
|
|
6399
|
+
{ value: "/code codex ", label: "/code codex", description: "Run Codex on the workspace (your plan)" },
|
|
6400
|
+
{ value: "/code status", label: "/code status", description: "Show connected coding agents" },
|
|
6401
|
+
{ value: "/code login claude", label: "/code login claude", description: "Connect your Claude plan" },
|
|
6402
|
+
{ value: "/code login codex", label: "/code login codex", description: "Connect your ChatGPT plan" }
|
|
6403
|
+
);
|
|
6404
|
+
}
|
|
6279
6405
|
return base;
|
|
6280
6406
|
},
|
|
6281
|
-
[deepResearchEnabled]
|
|
6407
|
+
[deepResearchEnabled, codeAgentsEnabled]
|
|
6282
6408
|
);
|
|
6283
6409
|
const scheduledExamples = react.useMemo(
|
|
6284
6410
|
() => [
|
|
@@ -7503,6 +7629,54 @@ function ArtifactSvg({ spec }) {
|
|
|
7503
7629
|
spec.caption && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: spec.caption })
|
|
7504
7630
|
] });
|
|
7505
7631
|
}
|
|
7632
|
+
init_utils();
|
|
7633
|
+
function useMediaSrc(sessionId, path) {
|
|
7634
|
+
const { adapter } = useAgentChatAdapterContext();
|
|
7635
|
+
return react.useMemo(
|
|
7636
|
+
() => adapter.getWorkspaceDownloadUrl({ sessionId, path }),
|
|
7637
|
+
[adapter, sessionId, path]
|
|
7638
|
+
);
|
|
7639
|
+
}
|
|
7640
|
+
function MediaCaption({ caption }) {
|
|
7641
|
+
if (!caption) return null;
|
|
7642
|
+
return /* @__PURE__ */ jsxRuntime.jsx("figcaption", { className: "border-t border-border px-3 py-2 text-xs leading-snug text-muted-foreground", children: caption });
|
|
7643
|
+
}
|
|
7644
|
+
function ArtifactImage({ sessionId, spec, fill = false }) {
|
|
7645
|
+
const src = useMediaSrc(sessionId, spec.path);
|
|
7646
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: "m-0", children: [
|
|
7647
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7648
|
+
"img",
|
|
7649
|
+
{
|
|
7650
|
+
src,
|
|
7651
|
+
alt: spec.caption ?? spec.path,
|
|
7652
|
+
loading: "lazy",
|
|
7653
|
+
className: cn(
|
|
7654
|
+
"block w-full bg-muted/30 object-contain",
|
|
7655
|
+
fill ? "max-h-full" : "max-h-[480px]"
|
|
7656
|
+
)
|
|
7657
|
+
}
|
|
7658
|
+
),
|
|
7659
|
+
/* @__PURE__ */ jsxRuntime.jsx(MediaCaption, { caption: spec.caption })
|
|
7660
|
+
] });
|
|
7661
|
+
}
|
|
7662
|
+
function ArtifactVideo({ sessionId, spec, fill = false }) {
|
|
7663
|
+
const src = useMediaSrc(sessionId, spec.path);
|
|
7664
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: "m-0", children: [
|
|
7665
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7666
|
+
"video",
|
|
7667
|
+
{
|
|
7668
|
+
src,
|
|
7669
|
+
controls: true,
|
|
7670
|
+
preload: "metadata",
|
|
7671
|
+
className: cn(
|
|
7672
|
+
"block w-full bg-black object-contain",
|
|
7673
|
+
fill ? "max-h-full" : "max-h-[480px]"
|
|
7674
|
+
)
|
|
7675
|
+
}
|
|
7676
|
+
),
|
|
7677
|
+
/* @__PURE__ */ jsxRuntime.jsx(MediaCaption, { caption: spec.caption })
|
|
7678
|
+
] });
|
|
7679
|
+
}
|
|
7506
7680
|
|
|
7507
7681
|
// src/components/chat/artifacts/artifact-export.ts
|
|
7508
7682
|
function exportArtifact(payload) {
|
|
@@ -7537,6 +7711,17 @@ function exportArtifact(payload) {
|
|
|
7537
7711
|
mime: "image/svg+xml",
|
|
7538
7712
|
extension: "svg"
|
|
7539
7713
|
};
|
|
7714
|
+
// Media artifacts are file references — the bytes live in the
|
|
7715
|
+
// workspace. Copy yields the path; the download action in
|
|
7716
|
+
// ArtifactBlock bypasses this serialisation and uses the
|
|
7717
|
+
// authenticated workspace download URL directly.
|
|
7718
|
+
case "image":
|
|
7719
|
+
case "video":
|
|
7720
|
+
return {
|
|
7721
|
+
text: payload.spec.path,
|
|
7722
|
+
mime: "text/plain",
|
|
7723
|
+
extension: "txt"
|
|
7724
|
+
};
|
|
7540
7725
|
}
|
|
7541
7726
|
}
|
|
7542
7727
|
function tableToCsv(columns, rows) {
|
|
@@ -7589,7 +7774,9 @@ var KIND_LABEL = {
|
|
|
7589
7774
|
table: "Table",
|
|
7590
7775
|
chart: "Chart",
|
|
7591
7776
|
html: "HTML preview",
|
|
7592
|
-
svg: "SVG"
|
|
7777
|
+
svg: "SVG",
|
|
7778
|
+
image: "Generated image",
|
|
7779
|
+
video: "Generated video"
|
|
7593
7780
|
};
|
|
7594
7781
|
var COPY_FEEDBACK_MS = 1500;
|
|
7595
7782
|
function ArtifactBlock({
|
|
@@ -7630,6 +7817,18 @@ function ArtifactBlock({
|
|
|
7630
7817
|
};
|
|
7631
7818
|
const handleDownload = () => {
|
|
7632
7819
|
if (!payload) return;
|
|
7820
|
+
if (payload.kind === "image" || payload.kind === "video") {
|
|
7821
|
+
const a = document.createElement("a");
|
|
7822
|
+
a.href = adapter.getWorkspaceDownloadUrl({
|
|
7823
|
+
sessionId,
|
|
7824
|
+
path: payload.spec.path
|
|
7825
|
+
});
|
|
7826
|
+
a.download = "";
|
|
7827
|
+
document.body.appendChild(a);
|
|
7828
|
+
a.click();
|
|
7829
|
+
document.body.removeChild(a);
|
|
7830
|
+
return;
|
|
7831
|
+
}
|
|
7633
7832
|
const { text, mime, extension } = exportArtifact(payload);
|
|
7634
7833
|
downloadText(`${safeFilename(name)}.${extension}`, text, mime);
|
|
7635
7834
|
};
|
|
@@ -7675,20 +7874,21 @@ function ArtifactBlock({
|
|
|
7675
7874
|
)
|
|
7676
7875
|
] })
|
|
7677
7876
|
] }),
|
|
7678
|
-
/* @__PURE__ */ jsxRuntime.jsx(ArtifactContent, { className: "p-0 overflow-visible", children: /* @__PURE__ */ jsxRuntime.jsx(ArtifactBody, { error, payload }) })
|
|
7877
|
+
/* @__PURE__ */ jsxRuntime.jsx(ArtifactContent, { className: "p-0 overflow-visible", children: /* @__PURE__ */ jsxRuntime.jsx(ArtifactBody, { error, payload, sessionId }) })
|
|
7679
7878
|
] }),
|
|
7680
7879
|
/* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: expanded, onOpenChange: setExpanded, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "flex h-[95vh] w-[95vw] max-w-[95vw] flex-col gap-4 overflow-hidden p-6 sm:max-w-[95vw]", children: [
|
|
7681
7880
|
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
|
|
7682
7881
|
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "truncate pr-10", children: name }),
|
|
7683
7882
|
/* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: description })
|
|
7684
7883
|
] }),
|
|
7685
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-0 flex-1 flex-col overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsx(ArtifactBody, { error, payload, fill: true }) })
|
|
7884
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-0 flex-1 flex-col overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsx(ArtifactBody, { error, payload, sessionId, fill: true }) })
|
|
7686
7885
|
] }) })
|
|
7687
7886
|
] });
|
|
7688
7887
|
}
|
|
7689
7888
|
function ArtifactBody({
|
|
7690
7889
|
error,
|
|
7691
7890
|
payload,
|
|
7891
|
+
sessionId,
|
|
7692
7892
|
fill = false
|
|
7693
7893
|
}) {
|
|
7694
7894
|
if (error) {
|
|
@@ -7714,6 +7914,10 @@ function ArtifactBody({
|
|
|
7714
7914
|
return /* @__PURE__ */ jsxRuntime.jsx(ArtifactHtml, { spec: payload.spec, fill });
|
|
7715
7915
|
case "svg":
|
|
7716
7916
|
return /* @__PURE__ */ jsxRuntime.jsx(ArtifactSvg, { spec: payload.spec });
|
|
7917
|
+
case "image":
|
|
7918
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ArtifactImage, { sessionId, spec: payload.spec, fill });
|
|
7919
|
+
case "video":
|
|
7920
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ArtifactVideo, { sessionId, spec: payload.spec, fill });
|
|
7717
7921
|
}
|
|
7718
7922
|
}
|
|
7719
7923
|
init_utils();
|
|
@@ -8820,13 +9024,17 @@ function cancelledToolLabel(toolName) {
|
|
|
8820
9024
|
ask_user_question: "Ask User Question",
|
|
8821
9025
|
process: "Process",
|
|
8822
9026
|
create_artifact: "Create artifact",
|
|
9027
|
+
run_coding_agent: "Coding agent",
|
|
9028
|
+
code_run: "Coding agent",
|
|
8823
9029
|
// ``Research memory`` reads as a noun ("memory of research") and
|
|
8824
9030
|
// makes the shimmer awkward ("Running Research memory…"). The
|
|
8825
9031
|
// one-liner renderer shows just ``Research`` as the label, so
|
|
8826
9032
|
// mirror that here so the live shimmer matches the row that
|
|
8827
9033
|
// replaces it on completion.
|
|
8828
9034
|
research_memory: "Research",
|
|
8829
|
-
research_outline: "Research"
|
|
9035
|
+
research_outline: "Research",
|
|
9036
|
+
generate_image: "image generation",
|
|
9037
|
+
generate_video: "video generation"
|
|
8830
9038
|
};
|
|
8831
9039
|
if (map[toolName]) return map[toolName];
|
|
8832
9040
|
if (toolName.startsWith("mcp__")) return formatMcpToolLabel(toolName);
|
|
@@ -9114,6 +9322,11 @@ function extractToolDetail(tc) {
|
|
|
9114
9322
|
case "consult_expert":
|
|
9115
9323
|
case "delegate_task":
|
|
9116
9324
|
return stringArg("name") ?? stringArg("task") ?? stringArg("title");
|
|
9325
|
+
case "run_coding_agent":
|
|
9326
|
+
case "code_run": {
|
|
9327
|
+
const prompt = stringArg("prompt");
|
|
9328
|
+
return prompt ? truncate3(prompt, 60) : null;
|
|
9329
|
+
}
|
|
9117
9330
|
case "memory":
|
|
9118
9331
|
return stringArg("action") ?? stringArg("key");
|
|
9119
9332
|
case "research_memory": {
|
|
@@ -9237,7 +9450,9 @@ var _TOOL_ROW_ICON = {
|
|
|
9237
9450
|
memory: lucideReact.PenLineIcon,
|
|
9238
9451
|
todo: lucideReact.ListIcon,
|
|
9239
9452
|
research_memory: lucideReact.BookOpenIcon,
|
|
9240
|
-
research_outline: lucideReact.ListIcon
|
|
9453
|
+
research_outline: lucideReact.ListIcon,
|
|
9454
|
+
run_coding_agent: lucideReact.BotIcon,
|
|
9455
|
+
code_run: lucideReact.BotIcon
|
|
9241
9456
|
};
|
|
9242
9457
|
function _toolRowIcon(toolName) {
|
|
9243
9458
|
return _TOOL_ROW_ICON[toolName] ?? lucideReact.WrenchIcon;
|
|
@@ -9283,6 +9498,13 @@ function _toolRowLabel(tc) {
|
|
|
9283
9498
|
return detail ? `Memory ${detail}` : "Updated memory";
|
|
9284
9499
|
case "todo":
|
|
9285
9500
|
return detail ? `Todo ${detail}` : "Updated todo list";
|
|
9501
|
+
case "run_coding_agent":
|
|
9502
|
+
case "code_run": {
|
|
9503
|
+
const a = parseArgs(tc.args);
|
|
9504
|
+
const agent = a?.agent ?? (a?.provider === "openai" ? "codex" : a?.provider === "anthropic" ? "claude" : void 0);
|
|
9505
|
+
const name = agent === "codex" ? "Codex" : agent === "claude" ? "Claude Code" : "coding agent";
|
|
9506
|
+
return detail ? `${name}: ${detail}` : `Ran ${name}`;
|
|
9507
|
+
}
|
|
9286
9508
|
case "research_memory": {
|
|
9287
9509
|
const args = parseArgs(tc.args);
|
|
9288
9510
|
const action = args?.action;
|
|
@@ -9366,6 +9588,9 @@ function IterationExpanded({
|
|
|
9366
9588
|
if (tc.toolName === "todo") {
|
|
9367
9589
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pr-1", children: /* @__PURE__ */ jsxRuntime.jsx(TodoToolBlock, { tc }) }, tc.id);
|
|
9368
9590
|
}
|
|
9591
|
+
if (tc.toolName === "code_run") {
|
|
9592
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pr-1", children: /* @__PURE__ */ jsxRuntime.jsx(CodeRunToolBlock, { tc, defaultOpen: true }) }, tc.id);
|
|
9593
|
+
}
|
|
9369
9594
|
return /* @__PURE__ */ jsxRuntime.jsx(SimpleDetailRow, { icon: _toolRowIcon(tc.toolName), children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: _toolRowLabel(tc) }) }, tc.id);
|
|
9370
9595
|
}),
|
|
9371
9596
|
showDone && /* @__PURE__ */ jsxRuntime.jsx(SimpleDetailRow, { icon: lucideReact.CircleCheckIcon, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground", children: "Done" }) })
|
|
@@ -9692,6 +9917,7 @@ function ChatThread({
|
|
|
9692
9917
|
viewMode = "simple",
|
|
9693
9918
|
onViewModeChange,
|
|
9694
9919
|
deepResearchEnabled = false,
|
|
9920
|
+
codeAgentsEnabled = false,
|
|
9695
9921
|
researchSources = [],
|
|
9696
9922
|
hideTurnSummary = false,
|
|
9697
9923
|
agentId,
|
|
@@ -9756,7 +9982,8 @@ function ChatThread({
|
|
|
9756
9982
|
canShowWorkspace,
|
|
9757
9983
|
viewMode,
|
|
9758
9984
|
onViewModeChange,
|
|
9759
|
-
deepResearchEnabled
|
|
9985
|
+
deepResearchEnabled,
|
|
9986
|
+
codeAgentsEnabled
|
|
9760
9987
|
}
|
|
9761
9988
|
),
|
|
9762
9989
|
onOpenIntegrations && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -10585,6 +10812,9 @@ var AGENT_CHAT_LISTENED_EVENTS = [
|
|
|
10585
10812
|
"expert.failure",
|
|
10586
10813
|
"expert.endorse",
|
|
10587
10814
|
"expert.override",
|
|
10815
|
+
"code.run_started",
|
|
10816
|
+
"code.run_progress",
|
|
10817
|
+
"code.run_result",
|
|
10588
10818
|
"user.feedback",
|
|
10589
10819
|
"artifact.created",
|
|
10590
10820
|
"artifact.updated",
|
|
@@ -10764,6 +10994,21 @@ function applyAgentChatEvent(state, event) {
|
|
|
10764
10994
|
nextState,
|
|
10765
10995
|
applyExpertFeedback(nextState.messages, event.type, event.data)
|
|
10766
10996
|
);
|
|
10997
|
+
case "code.run_started":
|
|
10998
|
+
return applyCodeRunStarted(nextState, event);
|
|
10999
|
+
case "code.run_progress":
|
|
11000
|
+
return withMessages(
|
|
11001
|
+
nextState,
|
|
11002
|
+
applyCodeRunProgress(nextState.messages, event.data)
|
|
11003
|
+
);
|
|
11004
|
+
case "code.run_result":
|
|
11005
|
+
return {
|
|
11006
|
+
...withMessages(
|
|
11007
|
+
nextState,
|
|
11008
|
+
applyCodeRunResult(nextState.messages, event.data)
|
|
11009
|
+
),
|
|
11010
|
+
isRunning: false
|
|
11011
|
+
};
|
|
10767
11012
|
case "user.feedback":
|
|
10768
11013
|
return withMessages(
|
|
10769
11014
|
nextState,
|
|
@@ -11314,6 +11559,141 @@ function applyExpertDelegation(state, event) {
|
|
|
11314
11559
|
isRunning: true
|
|
11315
11560
|
};
|
|
11316
11561
|
}
|
|
11562
|
+
var CODE_RUN_TOOL = "code_run";
|
|
11563
|
+
function codeRunFrameId(runId) {
|
|
11564
|
+
return `code-run-${runId}`;
|
|
11565
|
+
}
|
|
11566
|
+
function parseCodeRunState(raw) {
|
|
11567
|
+
if (raw) {
|
|
11568
|
+
try {
|
|
11569
|
+
const parsed = JSON.parse(raw);
|
|
11570
|
+
return {
|
|
11571
|
+
agent: parsed.agent ?? "",
|
|
11572
|
+
provider: parsed.provider ?? "",
|
|
11573
|
+
prompt: parsed.prompt ?? "",
|
|
11574
|
+
output: parsed.output ?? "",
|
|
11575
|
+
finalMessage: parsed.finalMessage ?? "",
|
|
11576
|
+
error: parsed.error ?? null,
|
|
11577
|
+
inputTokens: parsed.inputTokens ?? 0,
|
|
11578
|
+
outputTokens: parsed.outputTokens ?? 0
|
|
11579
|
+
};
|
|
11580
|
+
} catch {
|
|
11581
|
+
}
|
|
11582
|
+
}
|
|
11583
|
+
return {
|
|
11584
|
+
agent: "",
|
|
11585
|
+
provider: "",
|
|
11586
|
+
prompt: "",
|
|
11587
|
+
output: "",
|
|
11588
|
+
finalMessage: "",
|
|
11589
|
+
error: null,
|
|
11590
|
+
inputTokens: 0,
|
|
11591
|
+
outputTokens: 0
|
|
11592
|
+
};
|
|
11593
|
+
}
|
|
11594
|
+
function findCodeRunFrame(messages, runId) {
|
|
11595
|
+
const toolId = codeRunFrameId(runId);
|
|
11596
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
11597
|
+
const tc = messages[i]?.toolCalls?.find((c) => c.id === toolId);
|
|
11598
|
+
if (tc) return { msgIdx: i, toolId };
|
|
11599
|
+
}
|
|
11600
|
+
return null;
|
|
11601
|
+
}
|
|
11602
|
+
function applyCodeRunStarted(state, event) {
|
|
11603
|
+
const runId = stringValue2(event.data.run_id);
|
|
11604
|
+
if (!runId) return state;
|
|
11605
|
+
if (findCodeRunFrame(state.messages, runId)) {
|
|
11606
|
+
return { ...state, terminal: false, isRunning: true };
|
|
11607
|
+
}
|
|
11608
|
+
const agent = stringValue2(event.data.agent);
|
|
11609
|
+
const provider = stringValue2(event.data.provider);
|
|
11610
|
+
const prompt = stringValue2(event.data.prompt);
|
|
11611
|
+
const messages = [...state.messages];
|
|
11612
|
+
const assistantIdx = findLastAssistantIndex(messages);
|
|
11613
|
+
let assistant = assistantIdx >= 0 ? messages[assistantIdx] : null;
|
|
11614
|
+
const userAfterAssistant = assistantIdx >= 0 && hasUserAfterIndex(messages, assistantIdx);
|
|
11615
|
+
if (!assistant || assistant.status === "complete" || userAfterAssistant) {
|
|
11616
|
+
assistant = {
|
|
11617
|
+
id: `evt-${event.eventId}-code-run`,
|
|
11618
|
+
role: "assistant",
|
|
11619
|
+
content: "",
|
|
11620
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
11621
|
+
status: "streaming"
|
|
11622
|
+
};
|
|
11623
|
+
messages.push(assistant);
|
|
11624
|
+
} else {
|
|
11625
|
+
assistant = { ...assistant };
|
|
11626
|
+
messages[assistantIdx] = assistant;
|
|
11627
|
+
}
|
|
11628
|
+
const frameState = {
|
|
11629
|
+
agent,
|
|
11630
|
+
provider,
|
|
11631
|
+
prompt,
|
|
11632
|
+
output: "",
|
|
11633
|
+
finalMessage: "",
|
|
11634
|
+
error: null,
|
|
11635
|
+
inputTokens: 0,
|
|
11636
|
+
outputTokens: 0
|
|
11637
|
+
};
|
|
11638
|
+
const toolCall = {
|
|
11639
|
+
id: codeRunFrameId(runId),
|
|
11640
|
+
toolName: CODE_RUN_TOOL,
|
|
11641
|
+
args: JSON.stringify({ agent, provider, prompt }),
|
|
11642
|
+
status: "running",
|
|
11643
|
+
result: JSON.stringify(frameState)
|
|
11644
|
+
};
|
|
11645
|
+
assistant.toolCalls = [...assistant.toolCalls ?? [], toolCall];
|
|
11646
|
+
return { ...state, messages, terminal: false, isRunning: true };
|
|
11647
|
+
}
|
|
11648
|
+
function applyCodeRunProgress(messages, data) {
|
|
11649
|
+
const runId = stringValue2(data.run_id);
|
|
11650
|
+
if (!runId) return messages;
|
|
11651
|
+
const match = findCodeRunFrame(messages, runId);
|
|
11652
|
+
if (!match) return messages;
|
|
11653
|
+
const chunk = stringValue2(data.chunk);
|
|
11654
|
+
if (!chunk) return messages;
|
|
11655
|
+
const next = [...messages];
|
|
11656
|
+
const msg = next[match.msgIdx];
|
|
11657
|
+
next[match.msgIdx] = {
|
|
11658
|
+
...msg,
|
|
11659
|
+
toolCalls: msg.toolCalls?.map((tc) => {
|
|
11660
|
+
if (tc.id !== match.toolId) return tc;
|
|
11661
|
+
const frame = parseCodeRunState(tc.result);
|
|
11662
|
+
frame.output += chunk;
|
|
11663
|
+
return { ...tc, result: JSON.stringify(frame) };
|
|
11664
|
+
})
|
|
11665
|
+
};
|
|
11666
|
+
return next;
|
|
11667
|
+
}
|
|
11668
|
+
function applyCodeRunResult(messages, data) {
|
|
11669
|
+
const runId = stringValue2(data.run_id);
|
|
11670
|
+
if (!runId) return messages;
|
|
11671
|
+
const match = findCodeRunFrame(messages, runId);
|
|
11672
|
+
if (!match) return messages;
|
|
11673
|
+
const error = optionalStringValue(data.error) ?? null;
|
|
11674
|
+
const finalMessage = stringValue2(data.final_message);
|
|
11675
|
+
const inputTokens = numberValue(data.input_tokens);
|
|
11676
|
+
const outputTokens = numberValue(data.output_tokens);
|
|
11677
|
+
const next = [...messages];
|
|
11678
|
+
const msg = next[match.msgIdx];
|
|
11679
|
+
next[match.msgIdx] = {
|
|
11680
|
+
...msg,
|
|
11681
|
+
toolCalls: msg.toolCalls?.map((tc) => {
|
|
11682
|
+
if (tc.id !== match.toolId) return tc;
|
|
11683
|
+
const frame = parseCodeRunState(tc.result);
|
|
11684
|
+
frame.finalMessage = finalMessage;
|
|
11685
|
+
frame.error = error;
|
|
11686
|
+
frame.inputTokens = inputTokens;
|
|
11687
|
+
frame.outputTokens = outputTokens;
|
|
11688
|
+
return {
|
|
11689
|
+
...tc,
|
|
11690
|
+
status: error ? "error" : "complete",
|
|
11691
|
+
result: JSON.stringify(frame)
|
|
11692
|
+
};
|
|
11693
|
+
})
|
|
11694
|
+
};
|
|
11695
|
+
return next;
|
|
11696
|
+
}
|
|
11317
11697
|
function applyExpertFailure(messages, eventId, data) {
|
|
11318
11698
|
const match = findLatestConsultExpertCall(messages);
|
|
11319
11699
|
if (!match) return messages;
|
|
@@ -11987,6 +12367,7 @@ function AgentChat({
|
|
|
11987
12367
|
disabled,
|
|
11988
12368
|
onComposerError,
|
|
11989
12369
|
deepResearchEnabled = false,
|
|
12370
|
+
codeAgentsEnabled = false,
|
|
11990
12371
|
onOpenIntegrations
|
|
11991
12372
|
}) {
|
|
11992
12373
|
const [workspacePath, setWorkspacePath] = react.useState(null);
|
|
@@ -12136,6 +12517,7 @@ function AgentChat({
|
|
|
12136
12517
|
viewMode: runtime.viewMode,
|
|
12137
12518
|
onViewModeChange: runtime.setViewMode,
|
|
12138
12519
|
deepResearchEnabled,
|
|
12520
|
+
codeAgentsEnabled,
|
|
12139
12521
|
researchSources: runtime.researchSources,
|
|
12140
12522
|
hideTurnSummary,
|
|
12141
12523
|
agentId,
|
|
@@ -12422,74 +12804,297 @@ function ToolkitRow({
|
|
|
12422
12804
|
] })
|
|
12423
12805
|
] });
|
|
12424
12806
|
}
|
|
12425
|
-
|
|
12426
|
-
|
|
12427
|
-
|
|
12428
|
-
|
|
12429
|
-
|
|
12807
|
+
var PROVIDERS = [
|
|
12808
|
+
{
|
|
12809
|
+
key: "claude",
|
|
12810
|
+
provider: "anthropic",
|
|
12811
|
+
name: "Claude Code",
|
|
12812
|
+
oauthInstructions: "Run `claude setup-token` locally, then paste the `sk-ant-oat...` token it prints to connect your Claude subscription.",
|
|
12813
|
+
apiKeyInstructions: "Paste an Anthropic API key (`sk-ant-...`) to bill usage to your API account instead of a subscription.",
|
|
12814
|
+
oauthPlaceholder: "sk-ant-oat...",
|
|
12815
|
+
apiKeyPlaceholder: "sk-ant-...",
|
|
12816
|
+
validateOauth: (value) => value.startsWith("sk-ant-oat") ? null : "That doesn't look like a setup token \u2014 it should start with `sk-ant-oat`."
|
|
12817
|
+
},
|
|
12818
|
+
{
|
|
12819
|
+
key: "codex",
|
|
12820
|
+
provider: "openai",
|
|
12821
|
+
name: "Codex",
|
|
12822
|
+
oauthInstructions: "Run `codex login` locally, then paste the contents of `~/.codex/auth.json` to connect your ChatGPT plan.",
|
|
12823
|
+
apiKeyInstructions: "Paste an OpenAI API key (`sk-...`) to bill usage to your API account instead of a ChatGPT plan.",
|
|
12824
|
+
oauthPlaceholder: '{"OPENAI_API_KEY": ..., "tokens": { ... }}',
|
|
12825
|
+
apiKeyPlaceholder: "sk-...",
|
|
12826
|
+
validateOauth: (value) => {
|
|
12827
|
+
try {
|
|
12828
|
+
JSON.parse(value);
|
|
12829
|
+
return null;
|
|
12830
|
+
} catch {
|
|
12831
|
+
return "That doesn't look like valid JSON \u2014 paste the whole `~/.codex/auth.json` file.";
|
|
12832
|
+
}
|
|
12833
|
+
}
|
|
12430
12834
|
}
|
|
12431
|
-
|
|
12432
|
-
}
|
|
12433
|
-
|
|
12434
|
-
|
|
12435
|
-
|
|
12436
|
-
|
|
12437
|
-
|
|
12438
|
-
|
|
12439
|
-
};
|
|
12440
|
-
|
|
12441
|
-
|
|
12442
|
-
|
|
12443
|
-
|
|
12444
|
-
|
|
12445
|
-
|
|
12446
|
-
|
|
12447
|
-
|
|
12448
|
-
|
|
12449
|
-
|
|
12450
|
-
|
|
12451
|
-
|
|
12452
|
-
|
|
12453
|
-
if (kind === "action_required") return lucideReact.ExternalLinkIcon;
|
|
12454
|
-
if (kind === "task_complete") return lucideReact.ClipboardCheckIcon;
|
|
12455
|
-
if (kind === "governance_gate") return lucideReact.ShieldAlertIcon;
|
|
12456
|
-
if (kind === "progress_checkin") return lucideReact.TimerIcon;
|
|
12457
|
-
return lucideReact.CircleDotIcon;
|
|
12458
|
-
}
|
|
12459
|
-
function sortItems(items) {
|
|
12460
|
-
return [...items].sort((a, b) => {
|
|
12461
|
-
if (a.createdAt !== b.createdAt) return a.createdAt > b.createdAt ? -1 : 1;
|
|
12462
|
-
return b.id - a.id;
|
|
12463
|
-
});
|
|
12464
|
-
}
|
|
12465
|
-
function QuestionInput({
|
|
12466
|
-
prompt,
|
|
12467
|
-
choices,
|
|
12468
|
-
disabled,
|
|
12469
|
-
value,
|
|
12470
|
-
onChange
|
|
12471
|
-
}) {
|
|
12472
|
-
if (choices && choices.length > 0) {
|
|
12473
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12474
|
-
"select",
|
|
12835
|
+
];
|
|
12836
|
+
function CodingAgentsPanel({ agentId, adapter, onBack }) {
|
|
12837
|
+
const supported = !!adapter.listCodingAgentConnections && !!adapter.submitCodingAgentCredential && !!adapter.disconnectCodingAgentProvider;
|
|
12838
|
+
const [connections, setConnections] = react.useState([]);
|
|
12839
|
+
const refresh = react.useCallback(async () => {
|
|
12840
|
+
if (!adapter.listCodingAgentConnections) return;
|
|
12841
|
+
const res = await adapter.listCodingAgentConnections({ agentId });
|
|
12842
|
+
setConnections(res.connections);
|
|
12843
|
+
}, [adapter, agentId]);
|
|
12844
|
+
react.useEffect(() => {
|
|
12845
|
+
if (!supported) return;
|
|
12846
|
+
void refresh();
|
|
12847
|
+
}, [supported, refresh]);
|
|
12848
|
+
const byProvider = react.useMemo(() => {
|
|
12849
|
+
const map = /* @__PURE__ */ new Map();
|
|
12850
|
+
for (const c of connections) map.set(c.provider, c);
|
|
12851
|
+
return map;
|
|
12852
|
+
}, [connections]);
|
|
12853
|
+
if (!supported) return null;
|
|
12854
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-6 p-6", children: [
|
|
12855
|
+
onBack && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12856
|
+
"button",
|
|
12475
12857
|
{
|
|
12476
|
-
"
|
|
12477
|
-
|
|
12478
|
-
|
|
12479
|
-
value,
|
|
12480
|
-
onChange: (event) => onChange(event.target.value),
|
|
12858
|
+
type: "button",
|
|
12859
|
+
onClick: onBack,
|
|
12860
|
+
className: "flex w-fit items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground",
|
|
12481
12861
|
children: [
|
|
12482
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12483
|
-
|
|
12862
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeftIcon, { className: "h-4 w-4" }),
|
|
12863
|
+
"Back"
|
|
12484
12864
|
]
|
|
12485
12865
|
}
|
|
12486
|
-
)
|
|
12487
|
-
|
|
12488
|
-
|
|
12489
|
-
|
|
12490
|
-
|
|
12491
|
-
|
|
12492
|
-
|
|
12866
|
+
),
|
|
12867
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
12868
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-bold text-foreground", children: "Coding agents" }),
|
|
12869
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Connect your Claude or ChatGPT plan so the agent can run `/code` on your behalf without separate API billing." })
|
|
12870
|
+
] }),
|
|
12871
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4", children: PROVIDERS.map((meta) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
12872
|
+
ProviderCard,
|
|
12873
|
+
{
|
|
12874
|
+
meta,
|
|
12875
|
+
connection: byProvider.get(meta.provider) ?? null,
|
|
12876
|
+
adapter,
|
|
12877
|
+
agentId,
|
|
12878
|
+
onChanged: refresh
|
|
12879
|
+
},
|
|
12880
|
+
meta.key
|
|
12881
|
+
)) })
|
|
12882
|
+
] });
|
|
12883
|
+
}
|
|
12884
|
+
function ProviderCard({
|
|
12885
|
+
meta,
|
|
12886
|
+
connection,
|
|
12887
|
+
adapter,
|
|
12888
|
+
agentId,
|
|
12889
|
+
onChanged
|
|
12890
|
+
}) {
|
|
12891
|
+
const [mode, setMode] = react.useState("oauth");
|
|
12892
|
+
const [value, setValue] = react.useState("");
|
|
12893
|
+
const [busy, setBusy] = react.useState(false);
|
|
12894
|
+
const [error, setError] = react.useState(null);
|
|
12895
|
+
const connected = connection?.connected ?? false;
|
|
12896
|
+
const instructions = mode === "oauth" ? meta.oauthInstructions : meta.apiKeyInstructions;
|
|
12897
|
+
const placeholder = mode === "oauth" ? meta.oauthPlaceholder : meta.apiKeyPlaceholder;
|
|
12898
|
+
const submit = async () => {
|
|
12899
|
+
if (!adapter.submitCodingAgentCredential) return;
|
|
12900
|
+
const trimmed = value.trim();
|
|
12901
|
+
setError(null);
|
|
12902
|
+
if (!trimmed) {
|
|
12903
|
+
setError("Paste a value first.");
|
|
12904
|
+
return;
|
|
12905
|
+
}
|
|
12906
|
+
if (mode === "oauth") {
|
|
12907
|
+
const hint = meta.validateOauth(trimmed);
|
|
12908
|
+
if (hint) {
|
|
12909
|
+
setError(hint);
|
|
12910
|
+
return;
|
|
12911
|
+
}
|
|
12912
|
+
}
|
|
12913
|
+
setBusy(true);
|
|
12914
|
+
try {
|
|
12915
|
+
await adapter.submitCodingAgentCredential({
|
|
12916
|
+
agentId,
|
|
12917
|
+
provider: meta.provider,
|
|
12918
|
+
mode,
|
|
12919
|
+
value: trimmed
|
|
12920
|
+
});
|
|
12921
|
+
setValue("");
|
|
12922
|
+
await onChanged();
|
|
12923
|
+
} catch (e) {
|
|
12924
|
+
setError(e instanceof Error ? e.message : "Failed to save the credential");
|
|
12925
|
+
} finally {
|
|
12926
|
+
setBusy(false);
|
|
12927
|
+
}
|
|
12928
|
+
};
|
|
12929
|
+
const disconnect = async () => {
|
|
12930
|
+
if (!adapter.disconnectCodingAgentProvider) return;
|
|
12931
|
+
setBusy(true);
|
|
12932
|
+
setError(null);
|
|
12933
|
+
try {
|
|
12934
|
+
await adapter.disconnectCodingAgentProvider({ agentId, provider: meta.provider });
|
|
12935
|
+
await onChanged();
|
|
12936
|
+
} catch (e) {
|
|
12937
|
+
setError(e instanceof Error ? e.message : "Failed to disconnect");
|
|
12938
|
+
} finally {
|
|
12939
|
+
setBusy(false);
|
|
12940
|
+
}
|
|
12941
|
+
};
|
|
12942
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "flex flex-col gap-3 rounded-lg border border-border p-4", children: [
|
|
12943
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
12944
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-base font-semibold text-foreground", children: meta.name }),
|
|
12945
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12946
|
+
"span",
|
|
12947
|
+
{
|
|
12948
|
+
className: `inline-flex items-center rounded px-1.5 py-0.5 text-xs font-semibold ${connected ? "bg-primary/10 text-primary" : "bg-muted text-muted-foreground"}`,
|
|
12949
|
+
children: connected ? `Connected${connection?.auth_mode === "api_key" ? " (API key)" : ""}` : "Not connected"
|
|
12950
|
+
}
|
|
12951
|
+
)
|
|
12952
|
+
] }),
|
|
12953
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1 text-xs", children: [
|
|
12954
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12955
|
+
"button",
|
|
12956
|
+
{
|
|
12957
|
+
type: "button",
|
|
12958
|
+
onClick: () => {
|
|
12959
|
+
setMode("oauth");
|
|
12960
|
+
setError(null);
|
|
12961
|
+
},
|
|
12962
|
+
className: `rounded-md border px-2 py-1 ${mode === "oauth" ? "border-primary bg-primary/10 text-primary" : "border-border text-muted-foreground hover:bg-accent"}`,
|
|
12963
|
+
children: "Subscription"
|
|
12964
|
+
}
|
|
12965
|
+
),
|
|
12966
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12967
|
+
"button",
|
|
12968
|
+
{
|
|
12969
|
+
type: "button",
|
|
12970
|
+
onClick: () => {
|
|
12971
|
+
setMode("api_key");
|
|
12972
|
+
setError(null);
|
|
12973
|
+
},
|
|
12974
|
+
className: `rounded-md border px-2 py-1 ${mode === "api_key" ? "border-primary bg-primary/10 text-primary" : "border-border text-muted-foreground hover:bg-accent"}`,
|
|
12975
|
+
children: "API key"
|
|
12976
|
+
}
|
|
12977
|
+
)
|
|
12978
|
+
] }),
|
|
12979
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: instructions }),
|
|
12980
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12981
|
+
"textarea",
|
|
12982
|
+
{
|
|
12983
|
+
value,
|
|
12984
|
+
onChange: (e) => setValue(e.target.value),
|
|
12985
|
+
placeholder,
|
|
12986
|
+
spellCheck: false,
|
|
12987
|
+
autoComplete: "off",
|
|
12988
|
+
rows: mode === "oauth" && meta.provider === "openai" ? 4 : 2,
|
|
12989
|
+
"aria-label": `${meta.name} credential`,
|
|
12990
|
+
className: "w-full resize-y rounded-md border border-border bg-background px-3 py-2 font-mono text-xs [-webkit-text-security:disc]"
|
|
12991
|
+
}
|
|
12992
|
+
),
|
|
12993
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("div", { role: "alert", className: "text-xs text-red-500", children: error }),
|
|
12994
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
12995
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
12996
|
+
"button",
|
|
12997
|
+
{
|
|
12998
|
+
type: "button",
|
|
12999
|
+
disabled: busy,
|
|
13000
|
+
onClick: submit,
|
|
13001
|
+
className: "inline-flex items-center justify-center gap-1.5 rounded-md border border-border px-3 py-1.5 text-xs text-foreground hover:bg-accent disabled:opacity-60",
|
|
13002
|
+
children: [
|
|
13003
|
+
busy && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2Icon, { className: "h-3.5 w-3.5 animate-spin" }),
|
|
13004
|
+
connected ? "Update" : "Connect"
|
|
13005
|
+
]
|
|
13006
|
+
}
|
|
13007
|
+
),
|
|
13008
|
+
connected && /* @__PURE__ */ jsxRuntime.jsx(
|
|
13009
|
+
"button",
|
|
13010
|
+
{
|
|
13011
|
+
type: "button",
|
|
13012
|
+
disabled: busy,
|
|
13013
|
+
onClick: disconnect,
|
|
13014
|
+
className: "inline-flex items-center justify-center rounded-md border border-border px-3 py-1.5 text-xs text-muted-foreground hover:bg-accent disabled:opacity-60",
|
|
13015
|
+
children: "Disconnect"
|
|
13016
|
+
}
|
|
13017
|
+
)
|
|
13018
|
+
] })
|
|
13019
|
+
] });
|
|
13020
|
+
}
|
|
13021
|
+
init_utils();
|
|
13022
|
+
var DEFAULT_LIMIT = 50;
|
|
13023
|
+
function requireInboxAdapter(adapter) {
|
|
13024
|
+
if (!adapter.listInbox || !adapter.getInboxItem || !adapter.markInboxItemRead || !adapter.acknowledgeInboxItem || !adapter.respondGovernanceInboxItem || !adapter.openInboxStream) {
|
|
13025
|
+
throw new Error("Inbox is not supported by this adapter.");
|
|
13026
|
+
}
|
|
13027
|
+
return adapter;
|
|
13028
|
+
}
|
|
13029
|
+
var KIND_LABEL2 = {
|
|
13030
|
+
input_required: "Input needed",
|
|
13031
|
+
action_required: "Action needed",
|
|
13032
|
+
task_complete: "Task complete",
|
|
13033
|
+
governance_gate: "Approval",
|
|
13034
|
+
progress_checkin: "Progress"
|
|
13035
|
+
};
|
|
13036
|
+
function kindLabel(kind) {
|
|
13037
|
+
return KIND_LABEL2[kind] ?? kind.replace(/[_-]+/g, " ");
|
|
13038
|
+
}
|
|
13039
|
+
function statusLabel(status) {
|
|
13040
|
+
return status.split(/[_-]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
13041
|
+
}
|
|
13042
|
+
function formatRelative(value) {
|
|
13043
|
+
const date = new Date(value);
|
|
13044
|
+
if (Number.isNaN(date.getTime())) return "";
|
|
13045
|
+
return dateFns.formatDistanceToNow(date, { addSuffix: true });
|
|
13046
|
+
}
|
|
13047
|
+
function kindIcon(kind) {
|
|
13048
|
+
if (kind === "input_required") return lucideReact.MessageSquareIcon;
|
|
13049
|
+
if (kind === "action_required") return lucideReact.ExternalLinkIcon;
|
|
13050
|
+
if (kind === "task_complete") return lucideReact.ClipboardCheckIcon;
|
|
13051
|
+
if (kind === "governance_gate") return lucideReact.ShieldAlertIcon;
|
|
13052
|
+
if (kind === "progress_checkin") return lucideReact.TimerIcon;
|
|
13053
|
+
return lucideReact.CircleDotIcon;
|
|
13054
|
+
}
|
|
13055
|
+
function sortItems(items) {
|
|
13056
|
+
return [...items].sort((a, b) => {
|
|
13057
|
+
if (a.createdAt !== b.createdAt) return a.createdAt > b.createdAt ? -1 : 1;
|
|
13058
|
+
return b.id - a.id;
|
|
13059
|
+
});
|
|
13060
|
+
}
|
|
13061
|
+
function InboxBody({ body, muted }) {
|
|
13062
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13063
|
+
MessageResponse,
|
|
13064
|
+
{
|
|
13065
|
+
className: cn("text-sm", muted && "text-muted-foreground"),
|
|
13066
|
+
children: body
|
|
13067
|
+
}
|
|
13068
|
+
);
|
|
13069
|
+
}
|
|
13070
|
+
function QuestionInput({
|
|
13071
|
+
prompt,
|
|
13072
|
+
choices,
|
|
13073
|
+
disabled,
|
|
13074
|
+
value,
|
|
13075
|
+
onChange
|
|
13076
|
+
}) {
|
|
13077
|
+
if (choices && choices.length > 0) {
|
|
13078
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
13079
|
+
"select",
|
|
13080
|
+
{
|
|
13081
|
+
"aria-label": prompt,
|
|
13082
|
+
className: "h-9 w-full border border-line bg-background px-2 text-sm text-foreground outline-none focus:border-primary disabled:opacity-50",
|
|
13083
|
+
disabled,
|
|
13084
|
+
value,
|
|
13085
|
+
onChange: (event) => onChange(event.target.value),
|
|
13086
|
+
children: [
|
|
13087
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Select" }),
|
|
13088
|
+
choices.map((choice) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: choice.label, children: choice.label }, choice.label))
|
|
13089
|
+
]
|
|
13090
|
+
}
|
|
13091
|
+
);
|
|
13092
|
+
}
|
|
13093
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13094
|
+
"input",
|
|
13095
|
+
{
|
|
13096
|
+
"aria-label": prompt,
|
|
13097
|
+
className: "h-9 w-full border border-line bg-background px-2 text-sm text-foreground outline-none focus:border-primary disabled:opacity-50",
|
|
12493
13098
|
disabled,
|
|
12494
13099
|
value,
|
|
12495
13100
|
onChange: (event) => onChange(event.target.value)
|
|
@@ -12585,7 +13190,7 @@ function InputRequiredDetail({
|
|
|
12585
13190
|
}
|
|
12586
13191
|
}
|
|
12587
13192
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
12588
|
-
item.body && /* @__PURE__ */ jsxRuntime.jsx(
|
|
13193
|
+
item.body && /* @__PURE__ */ jsxRuntime.jsx(InboxBody, { body: item.body, muted: true }),
|
|
12589
13194
|
questions.map((question) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block space-y-1.5", children: [
|
|
12590
13195
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-foreground", children: question.prompt }),
|
|
12591
13196
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -12638,7 +13243,7 @@ function AckDetail({
|
|
|
12638
13243
|
const duration = typeof item.payload.duration_seconds === "number" ? item.payload.duration_seconds : null;
|
|
12639
13244
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
12640
13245
|
outcome && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "secondary", children: outcome }),
|
|
12641
|
-
item.body && /* @__PURE__ */ jsxRuntime.jsx(
|
|
13246
|
+
item.body && /* @__PURE__ */ jsxRuntime.jsx(InboxBody, { body: item.body }),
|
|
12642
13247
|
typeof item.payload.error === "string" && /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "overflow-x-auto bg-destructive/10 p-3 text-xs text-destructive", children: item.payload.error }),
|
|
12643
13248
|
duration !== null && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
12644
13249
|
"Duration: ",
|
|
@@ -12752,7 +13357,7 @@ function ActionRequiredDetail({
|
|
|
12752
13357
|
}
|
|
12753
13358
|
}
|
|
12754
13359
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
12755
|
-
item.body && /* @__PURE__ */ jsxRuntime.jsx(
|
|
13360
|
+
item.body && /* @__PURE__ */ jsxRuntime.jsx(InboxBody, { body: item.body }),
|
|
12756
13361
|
context && context !== item.body && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-wrap text-sm text-muted-foreground", children: context }),
|
|
12757
13362
|
actionType && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "secondary", children: actionType }),
|
|
12758
13363
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -12801,7 +13406,7 @@ function ProgressDetail({
|
|
|
12801
13406
|
}
|
|
12802
13407
|
}
|
|
12803
13408
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
12804
|
-
item.body && /* @__PURE__ */ jsxRuntime.jsx(
|
|
13409
|
+
item.body && /* @__PURE__ */ jsxRuntime.jsx(InboxBody, { body: item.body }),
|
|
12805
13410
|
rows.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("dl", { className: "space-y-1 text-xs text-muted-foreground", children: rows.map(([label, value]) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
12806
13411
|
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "w-20 shrink-0", children: String(label) }),
|
|
12807
13412
|
/* @__PURE__ */ jsxRuntime.jsx("dd", { className: "min-w-0", children: String(value) })
|
|
@@ -13122,6 +13727,45 @@ function Card({
|
|
|
13122
13727
|
}
|
|
13123
13728
|
);
|
|
13124
13729
|
}
|
|
13730
|
+
function CardHeader({ className, ...props }) {
|
|
13731
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13732
|
+
"div",
|
|
13733
|
+
{
|
|
13734
|
+
"data-slot": "card-header",
|
|
13735
|
+
className: cn(
|
|
13736
|
+
"group/card-header @container/card-header grid auto-rows-min items-start gap-1.5 rounded-none px-8 group-data-[size=sm]/card:px-5 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-8 group-data-[size=sm]/card:[.border-b]:pb-5",
|
|
13737
|
+
className
|
|
13738
|
+
),
|
|
13739
|
+
...props
|
|
13740
|
+
}
|
|
13741
|
+
);
|
|
13742
|
+
}
|
|
13743
|
+
function CardTitle({ className, ...props }) {
|
|
13744
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13745
|
+
"div",
|
|
13746
|
+
{
|
|
13747
|
+
"data-slot": "card-title",
|
|
13748
|
+
className: cn(
|
|
13749
|
+
"font-heading text-lg font-semibold tracking-wider uppercase",
|
|
13750
|
+
className
|
|
13751
|
+
),
|
|
13752
|
+
...props
|
|
13753
|
+
}
|
|
13754
|
+
);
|
|
13755
|
+
}
|
|
13756
|
+
function CardAction({ className, ...props }) {
|
|
13757
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13758
|
+
"div",
|
|
13759
|
+
{
|
|
13760
|
+
"data-slot": "card-action",
|
|
13761
|
+
className: cn(
|
|
13762
|
+
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
|
13763
|
+
className
|
|
13764
|
+
),
|
|
13765
|
+
...props
|
|
13766
|
+
}
|
|
13767
|
+
);
|
|
13768
|
+
}
|
|
13125
13769
|
function CardContent({ className, ...props }) {
|
|
13126
13770
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13127
13771
|
"div",
|
|
@@ -13178,111 +13822,793 @@ function truncate4(s, max) {
|
|
|
13178
13822
|
if (s.length <= max) return s;
|
|
13179
13823
|
return `${s.slice(0, max - 1)}\u2026`;
|
|
13180
13824
|
}
|
|
13181
|
-
var
|
|
13182
|
-
|
|
13183
|
-
|
|
13184
|
-
|
|
13185
|
-
|
|
13186
|
-
|
|
13187
|
-
|
|
13188
|
-
|
|
13189
|
-
|
|
13190
|
-
|
|
13191
|
-
|
|
13192
|
-
|
|
13193
|
-
|
|
13194
|
-
|
|
13195
|
-
|
|
13196
|
-
|
|
13197
|
-
|
|
13198
|
-
|
|
13199
|
-
|
|
13200
|
-
}
|
|
13201
|
-
var ACTIVITY_KIND_TONE = {
|
|
13202
|
-
"mission.defined": "bg-primary/10 text-primary border-primary/30",
|
|
13203
|
-
"mission.paused": "bg-amber-500/10 text-amber-600 border-amber-500/30",
|
|
13204
|
-
"mission.cancelled": "bg-destructive/10 text-destructive border-destructive/30",
|
|
13205
|
-
"task.spawned": "bg-foreground/5 text-foreground/80 border-foreground/20",
|
|
13206
|
-
"task.completed": "bg-emerald-500/10 text-emerald-600 border-emerald-500/30",
|
|
13207
|
-
"task.failed": "bg-destructive/10 text-destructive border-destructive/30",
|
|
13208
|
-
"task.cancelled": "bg-muted text-muted-foreground border-border",
|
|
13209
|
-
"worker.latest": "bg-foreground/5 text-foreground/70 border-foreground/15",
|
|
13210
|
-
"evaluator.verdict": "bg-primary/10 text-primary border-primary/30"
|
|
13211
|
-
};
|
|
13212
|
-
function buildMissionActivity(mission, tasks, workers) {
|
|
13213
|
-
const entries = [];
|
|
13214
|
-
entries.push({
|
|
13215
|
-
at: mission.createdAt,
|
|
13216
|
-
kind: "mission.defined",
|
|
13217
|
-
label: "Mission defined",
|
|
13218
|
-
detail: mission.description
|
|
13219
|
-
});
|
|
13220
|
-
if (mission.status === "paused" && mission.pausedReason) {
|
|
13221
|
-
entries.push({
|
|
13222
|
-
at: mission.updatedAt,
|
|
13223
|
-
kind: "mission.paused",
|
|
13224
|
-
label: "Paused",
|
|
13225
|
-
detail: mission.pausedReason
|
|
13226
|
-
});
|
|
13227
|
-
}
|
|
13228
|
-
if (mission.status === "cancelled" && mission.cancelledReason) {
|
|
13229
|
-
entries.push({
|
|
13230
|
-
at: mission.updatedAt,
|
|
13231
|
-
kind: "mission.cancelled",
|
|
13232
|
-
label: "Cancelled",
|
|
13233
|
-
detail: mission.cancelledReason
|
|
13234
|
-
});
|
|
13825
|
+
var MISSION_EVENT_CATEGORIES = [
|
|
13826
|
+
"spawn",
|
|
13827
|
+
"output",
|
|
13828
|
+
"done",
|
|
13829
|
+
"verdict",
|
|
13830
|
+
"system"
|
|
13831
|
+
];
|
|
13832
|
+
function missionEventCategory(type) {
|
|
13833
|
+
switch (type) {
|
|
13834
|
+
case "worker.spawned":
|
|
13835
|
+
return "spawn";
|
|
13836
|
+
case "iteration.summary":
|
|
13837
|
+
return "output";
|
|
13838
|
+
case "worker.complete":
|
|
13839
|
+
return "done";
|
|
13840
|
+
case "mission.evaluation.end":
|
|
13841
|
+
return "verdict";
|
|
13842
|
+
default:
|
|
13843
|
+
return "system";
|
|
13235
13844
|
}
|
|
13236
|
-
|
|
13237
|
-
|
|
13238
|
-
|
|
13239
|
-
|
|
13240
|
-
|
|
13241
|
-
|
|
13242
|
-
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
|
|
13246
|
-
|
|
13247
|
-
|
|
13248
|
-
|
|
13249
|
-
|
|
13250
|
-
|
|
13251
|
-
|
|
13252
|
-
|
|
13845
|
+
}
|
|
13846
|
+
function dataString(data, key) {
|
|
13847
|
+
const v = data?.[key];
|
|
13848
|
+
return typeof v === "string" && v.trim().length > 0 ? v.trim() : null;
|
|
13849
|
+
}
|
|
13850
|
+
var CONTROL_MARKUP_RE = /<next_action\b[^>]*(?:\/>|>[\s\S]*?<\/next_action>)/gi;
|
|
13851
|
+
function stripMissionControlMarkup(text) {
|
|
13852
|
+
return text.replace(CONTROL_MARKUP_RE, "").trim();
|
|
13853
|
+
}
|
|
13854
|
+
function missionEventSummary(event) {
|
|
13855
|
+
return stripMissionControlMarkup(rawMissionEventSummary(event));
|
|
13856
|
+
}
|
|
13857
|
+
function rawMissionEventSummary(event) {
|
|
13858
|
+
const d = event.data ?? null;
|
|
13859
|
+
switch (event.type) {
|
|
13860
|
+
case "worker.spawned":
|
|
13861
|
+
return dataString(d, "goal") ?? "Task spawned";
|
|
13862
|
+
case "worker.complete":
|
|
13863
|
+
return dataString(d, "result") ?? "Worker complete";
|
|
13864
|
+
case "iteration.summary":
|
|
13865
|
+
return dataString(d, "summary") ?? "";
|
|
13866
|
+
case "mission.evaluation.end": {
|
|
13867
|
+
const result = dataString(d, "result");
|
|
13868
|
+
const feedback = dataString(d, "feedback") ?? dataString(d, "explanation");
|
|
13869
|
+
if (result && feedback) return `${result} \u2014 ${feedback}`;
|
|
13870
|
+
return result ?? feedback ?? "Evaluation finished";
|
|
13871
|
+
}
|
|
13872
|
+
case "task.blocked":
|
|
13873
|
+
return dataString(d, "reason") ?? "Task blocked";
|
|
13874
|
+
case "task.failed":
|
|
13875
|
+
return "Task failed";
|
|
13876
|
+
default: {
|
|
13877
|
+
const text = dataString(d, "summary") ?? dataString(d, "text") ?? dataString(d, "message") ?? dataString(d, "reason");
|
|
13878
|
+
if (text) return text;
|
|
13879
|
+
if (!d) return "";
|
|
13880
|
+
try {
|
|
13881
|
+
return truncate4(JSON.stringify(d), 160);
|
|
13882
|
+
} catch {
|
|
13883
|
+
return "";
|
|
13884
|
+
}
|
|
13253
13885
|
}
|
|
13254
13886
|
}
|
|
13255
|
-
|
|
13256
|
-
|
|
13257
|
-
|
|
13258
|
-
|
|
13259
|
-
|
|
13260
|
-
|
|
13261
|
-
|
|
13262
|
-
|
|
13887
|
+
}
|
|
13888
|
+
function missionEventTaskId(event, sessions) {
|
|
13889
|
+
return dataString(event.data ?? null, "task_id") ?? sessions[event.sessionId]?.taskId ?? null;
|
|
13890
|
+
}
|
|
13891
|
+
function missionEventActorLabel(event, sessions) {
|
|
13892
|
+
const meta = sessions[event.sessionId];
|
|
13893
|
+
if (!meta) return event.sessionId.slice(0, 8);
|
|
13894
|
+
if (meta.kind === "coordinator") return "orchestrator";
|
|
13895
|
+
return meta.agentDefName ?? "worker";
|
|
13896
|
+
}
|
|
13897
|
+
function missionTaskBlocks(tasks) {
|
|
13898
|
+
const blocks = {};
|
|
13899
|
+
for (const t of tasks) {
|
|
13900
|
+
for (const parent of t.parentIds) {
|
|
13901
|
+
(blocks[parent] ?? (blocks[parent] = [])).push(t.id);
|
|
13263
13902
|
}
|
|
13264
13903
|
}
|
|
13265
|
-
|
|
13266
|
-
entries.push({
|
|
13267
|
-
at: mission.lastEvaluationAt,
|
|
13268
|
-
kind: "evaluator.verdict",
|
|
13269
|
-
label: `Verdict \xB7 ${mission.lastEvaluationResult}`,
|
|
13270
|
-
detail: mission.lastEvaluationFeedback ?? void 0
|
|
13271
|
-
});
|
|
13272
|
-
}
|
|
13273
|
-
entries.sort((a, b) => b.at.localeCompare(a.at));
|
|
13274
|
-
return entries;
|
|
13904
|
+
return blocks;
|
|
13275
13905
|
}
|
|
13276
|
-
function
|
|
13277
|
-
|
|
13278
|
-
|
|
13279
|
-
|
|
13280
|
-
|
|
13906
|
+
function missionTaskTitle(goal, max = 80) {
|
|
13907
|
+
const line = goal.split("\n").find((l) => l.trim().length > 0)?.trim() ?? goal.trim();
|
|
13908
|
+
return truncate4(line.replace(/\s+/g, " "), max);
|
|
13909
|
+
}
|
|
13910
|
+
var RAIL_GROUP_DEFS = [
|
|
13911
|
+
{ key: "running", label: "Running", match: (s) => s === "running" },
|
|
13912
|
+
{ key: "blocked", label: "Blocked", match: (s) => s === "blocked" },
|
|
13913
|
+
{
|
|
13914
|
+
key: "queued",
|
|
13915
|
+
label: "Queued",
|
|
13916
|
+
match: (s) => s === "ready" || s === "todo"
|
|
13917
|
+
},
|
|
13918
|
+
{ key: "done", label: "Done", match: (s) => s === "done" },
|
|
13919
|
+
{
|
|
13920
|
+
key: "failed",
|
|
13921
|
+
label: "Failed / cancelled",
|
|
13922
|
+
match: (s) => s === "failed" || s === "cancelled"
|
|
13923
|
+
}
|
|
13924
|
+
];
|
|
13925
|
+
function missionTaskRailGroups(tasks) {
|
|
13926
|
+
const grouped = /* @__PURE__ */ new Set();
|
|
13927
|
+
const groups = RAIL_GROUP_DEFS.map((def) => ({
|
|
13928
|
+
key: def.key,
|
|
13929
|
+
label: def.label,
|
|
13930
|
+
tasks: tasks.filter((t) => {
|
|
13931
|
+
const hit = def.match(t.status);
|
|
13932
|
+
if (hit) grouped.add(t.id);
|
|
13933
|
+
return hit;
|
|
13934
|
+
})
|
|
13935
|
+
}));
|
|
13936
|
+
const stray = tasks.filter((t) => !grouped.has(t.id));
|
|
13937
|
+
if (stray.length > 0) {
|
|
13938
|
+
const queued = groups.find((g) => g.key === "queued");
|
|
13939
|
+
if (queued) queued.tasks.push(...stray);
|
|
13281
13940
|
}
|
|
13941
|
+
return groups.filter((g) => g.tasks.length > 0);
|
|
13282
13942
|
}
|
|
13283
|
-
var
|
|
13284
|
-
|
|
13285
|
-
tasks
|
|
13943
|
+
var TERMINAL_TASK_STATUSES = /* @__PURE__ */ new Set(["done", "failed", "cancelled"]);
|
|
13944
|
+
function defaultSelectedMissionTaskId(tasks) {
|
|
13945
|
+
if (tasks.length === 0) return null;
|
|
13946
|
+
const ordered = missionTaskRailGroups(tasks).flatMap((g) => g.tasks);
|
|
13947
|
+
const firstLive = ordered.find(
|
|
13948
|
+
(t) => !TERMINAL_TASK_STATUSES.has(t.status)
|
|
13949
|
+
);
|
|
13950
|
+
return (firstLive ?? ordered[0] ?? tasks[0]).id;
|
|
13951
|
+
}
|
|
13952
|
+
function mergeMissionEvents(existing, incoming) {
|
|
13953
|
+
if (incoming.length === 0) return existing;
|
|
13954
|
+
const byId = /* @__PURE__ */ new Map();
|
|
13955
|
+
for (const e of existing) byId.set(e.id, e);
|
|
13956
|
+
for (const e of incoming) byId.set(e.id, e);
|
|
13957
|
+
return [...byId.values()].sort((a, b) => a.id - b.id);
|
|
13958
|
+
}
|
|
13959
|
+
function missionTaskStatusDotClass(status) {
|
|
13960
|
+
switch (status) {
|
|
13961
|
+
case "running":
|
|
13962
|
+
return "bg-primary";
|
|
13963
|
+
case "blocked":
|
|
13964
|
+
return "bg-amber-500";
|
|
13965
|
+
case "done":
|
|
13966
|
+
return "bg-emerald-500";
|
|
13967
|
+
case "failed":
|
|
13968
|
+
return "bg-destructive";
|
|
13969
|
+
case "cancelled":
|
|
13970
|
+
return "bg-muted-foreground";
|
|
13971
|
+
default:
|
|
13972
|
+
return "bg-foreground/30";
|
|
13973
|
+
}
|
|
13974
|
+
}
|
|
13975
|
+
function missionWorkerTaskCounts(worker, tasks) {
|
|
13976
|
+
if (worker.kind !== "task") return null;
|
|
13977
|
+
const mine = tasks.filter((t) => t.agentDefName === worker.agentDefName);
|
|
13978
|
+
return {
|
|
13979
|
+
completed: mine.filter((t) => t.status === "done").length,
|
|
13980
|
+
inFlight: mine.filter(
|
|
13981
|
+
(t) => t.status === "running" || t.status === "blocked"
|
|
13982
|
+
).length
|
|
13983
|
+
};
|
|
13984
|
+
}
|
|
13985
|
+
function formatMissionTimestamp(iso) {
|
|
13986
|
+
if (!iso) return "";
|
|
13987
|
+
const parsed = new Date(iso);
|
|
13988
|
+
if (Number.isNaN(parsed.getTime())) return iso;
|
|
13989
|
+
return parsed.toLocaleTimeString();
|
|
13990
|
+
}
|
|
13991
|
+
var CATEGORY_BADGE_CLASS = {
|
|
13992
|
+
spawn: "border-primary/30 bg-primary/10 text-primary",
|
|
13993
|
+
output: "border-foreground/20 bg-foreground/5 text-foreground/80",
|
|
13994
|
+
done: "border-emerald-500/30 bg-emerald-500/10 text-emerald-600",
|
|
13995
|
+
verdict: "border-amber-500/30 bg-amber-500/10 text-amber-600",
|
|
13996
|
+
system: "border-border bg-muted text-muted-foreground"
|
|
13997
|
+
};
|
|
13998
|
+
function MissionActivityTab({ feed }) {
|
|
13999
|
+
const [filter, setFilter] = react.useState("all");
|
|
14000
|
+
const rows = react.useMemo(() => {
|
|
14001
|
+
const newestFirst = [...feed.events].reverse();
|
|
14002
|
+
if (filter === "all") return newestFirst;
|
|
14003
|
+
return newestFirst.filter((e) => missionEventCategory(e.type) === filter);
|
|
14004
|
+
}, [feed.events, filter]);
|
|
14005
|
+
if (feed.events.length === 0) {
|
|
14006
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-8 text-center text-sm text-muted-foreground/60", children: "No mission activity yet." });
|
|
14007
|
+
}
|
|
14008
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
14009
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-1.5", children: ["all", ...MISSION_EVENT_CATEGORIES].map((cat) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
14010
|
+
"button",
|
|
14011
|
+
{
|
|
14012
|
+
type: "button",
|
|
14013
|
+
onClick: () => setFilter(cat),
|
|
14014
|
+
className: `rounded-full border px-2.5 py-0.5 font-mono text-[10px] uppercase tracking-wide transition-colors ${filter === cat ? "border-foreground bg-foreground text-background" : "border-border/60 bg-background text-muted-foreground hover:bg-muted/40"}`,
|
|
14015
|
+
children: cat
|
|
14016
|
+
},
|
|
14017
|
+
cat
|
|
14018
|
+
)) }),
|
|
14019
|
+
/* @__PURE__ */ jsxRuntime.jsx("ol", { className: "space-y-1", children: rows.map((e) => /* @__PURE__ */ jsxRuntime.jsx(ActivityRow, { event: e, feed }, e.id)) })
|
|
14020
|
+
] });
|
|
14021
|
+
}
|
|
14022
|
+
function ActivityRow({
|
|
14023
|
+
event,
|
|
14024
|
+
feed
|
|
14025
|
+
}) {
|
|
14026
|
+
const category = missionEventCategory(event.type);
|
|
14027
|
+
const taskId = missionEventTaskId(event, feed.sessions);
|
|
14028
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start gap-3 rounded px-2 py-1.5 text-sm hover:bg-muted/30", children: [
|
|
14029
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-20 shrink-0 font-mono text-[10px] text-muted-foreground/60", children: formatMissionTimestamp(event.createdAt) }),
|
|
14030
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
|
|
14031
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 items-center", children: [
|
|
14032
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14033
|
+
"span",
|
|
14034
|
+
{
|
|
14035
|
+
className: `shrink-0 rounded border px-1.5 font-mono uppercase ${CATEGORY_BADGE_CLASS[category]}`,
|
|
14036
|
+
children: category
|
|
14037
|
+
}
|
|
14038
|
+
),
|
|
14039
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "shrink-0 text-xs text-foreground font-mono", children: missionEventActorLabel(event, feed.sessions) }),
|
|
14040
|
+
taskId ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "shrink-0 rounded bg-muted px-1.5 py-0.5 font-mono text-[9px] text-muted-foreground/70", children: taskId.slice(0, 8) }) : null
|
|
14041
|
+
] }),
|
|
14042
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "min-w-0 flex-1 truncate text-foreground/80", children: missionEventSummary(event) }) })
|
|
14043
|
+
] })
|
|
14044
|
+
] });
|
|
14045
|
+
}
|
|
14046
|
+
function verdictToneClass(result) {
|
|
14047
|
+
if (result === "satisfied") {
|
|
14048
|
+
return "border-emerald-500/30 bg-emerald-500/5 text-emerald-700 dark:text-emerald-400";
|
|
14049
|
+
}
|
|
14050
|
+
if (result === "failed" || result === "blocked") {
|
|
14051
|
+
return "border-destructive/30 bg-destructive/5 text-destructive";
|
|
14052
|
+
}
|
|
14053
|
+
return "border-amber-500/30 bg-amber-500/5 text-amber-700 dark:text-amber-400";
|
|
14054
|
+
}
|
|
14055
|
+
function MissionMetadataTab({ mission }) {
|
|
14056
|
+
const rows = [
|
|
14057
|
+
{
|
|
14058
|
+
label: "Mission ID",
|
|
14059
|
+
value: /* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-[11px]", children: mission.id })
|
|
14060
|
+
},
|
|
14061
|
+
{
|
|
14062
|
+
label: "Session ID",
|
|
14063
|
+
value: /* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-[11px]", children: mission.sessionId })
|
|
14064
|
+
},
|
|
14065
|
+
{
|
|
14066
|
+
label: "Agent ID",
|
|
14067
|
+
value: /* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-[11px]", children: mission.agentId })
|
|
14068
|
+
},
|
|
14069
|
+
{ label: "Status", value: mission.status },
|
|
14070
|
+
{
|
|
14071
|
+
label: "Iteration",
|
|
14072
|
+
value: `${mission.iteration} / ${mission.maxIterations}`
|
|
14073
|
+
},
|
|
14074
|
+
{
|
|
14075
|
+
label: "Owner",
|
|
14076
|
+
value: mission.userId ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
14077
|
+
"user ",
|
|
14078
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-[11px]", children: mission.userId })
|
|
14079
|
+
] }) : mission.serviceAccountId ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
14080
|
+
"service account",
|
|
14081
|
+
" ",
|
|
14082
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-[11px]", children: mission.serviceAccountId })
|
|
14083
|
+
] }) : "\u2014"
|
|
14084
|
+
},
|
|
14085
|
+
{
|
|
14086
|
+
label: "Created",
|
|
14087
|
+
value: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[11px]", children: new Date(mission.createdAt).toLocaleString() })
|
|
14088
|
+
},
|
|
14089
|
+
{
|
|
14090
|
+
label: "Updated",
|
|
14091
|
+
value: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[11px]", children: new Date(mission.updatedAt).toLocaleString() })
|
|
14092
|
+
}
|
|
14093
|
+
];
|
|
14094
|
+
if (mission.pausedReason) {
|
|
14095
|
+
rows.push({ label: "Paused reason", value: mission.pausedReason });
|
|
14096
|
+
}
|
|
14097
|
+
if (mission.cancelledReason) {
|
|
14098
|
+
rows.push({ label: "Cancelled reason", value: mission.cancelledReason });
|
|
14099
|
+
}
|
|
14100
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
14101
|
+
mission.lastEvaluationResult ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14102
|
+
"section",
|
|
14103
|
+
{
|
|
14104
|
+
className: `space-y-2 rounded-md border p-4 ${verdictToneClass(mission.lastEvaluationResult)}`,
|
|
14105
|
+
children: [
|
|
14106
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "font-mono text-[10px] uppercase tracking-widest", children: [
|
|
14107
|
+
"Last verdict \u2014 ",
|
|
14108
|
+
mission.lastEvaluationResult
|
|
14109
|
+
] }),
|
|
14110
|
+
mission.lastEvaluationFeedback ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-wrap text-sm font-medium text-foreground/90", children: mission.lastEvaluationFeedback }) : null,
|
|
14111
|
+
mission.lastEvaluationExplanation ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-wrap text-xs text-muted-foreground/80", children: mission.lastEvaluationExplanation }) : null,
|
|
14112
|
+
mission.lastEvaluationAt ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-mono text-[10px] text-muted-foreground/60", children: new Date(mission.lastEvaluationAt).toLocaleString() }) : null
|
|
14113
|
+
]
|
|
14114
|
+
}
|
|
14115
|
+
) : null,
|
|
14116
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { children: [
|
|
14117
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2 font-mono text-[10px] uppercase tracking-widest text-muted-foreground/70", children: "Identifiers" }),
|
|
14118
|
+
/* @__PURE__ */ jsxRuntime.jsx("dl", { className: "grid grid-cols-[max-content_1fr] gap-x-4 gap-y-1 text-xs", children: rows.map((r) => /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
|
|
14119
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-muted-foreground/70", children: r.label }),
|
|
14120
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { className: "break-all text-foreground/90", children: r.value })
|
|
14121
|
+
] }, r.label)) })
|
|
14122
|
+
] })
|
|
14123
|
+
] });
|
|
14124
|
+
}
|
|
14125
|
+
var TASK_STATUS_BADGE_CLASS = {
|
|
14126
|
+
running: "border-primary/30 bg-primary/10 text-primary",
|
|
14127
|
+
blocked: "border-amber-500/30 bg-amber-500/10 text-amber-600",
|
|
14128
|
+
done: "border-emerald-500/30 bg-emerald-500/10 text-emerald-600",
|
|
14129
|
+
failed: "border-destructive/30 bg-destructive/10 text-destructive",
|
|
14130
|
+
cancelled: "border-border bg-muted text-muted-foreground"
|
|
14131
|
+
};
|
|
14132
|
+
function statusBadgeClass(status) {
|
|
14133
|
+
return TASK_STATUS_BADGE_CLASS[status] ?? "border-foreground/20 bg-foreground/5 text-foreground/70";
|
|
14134
|
+
}
|
|
14135
|
+
function TaskChip({
|
|
14136
|
+
task,
|
|
14137
|
+
onSelect
|
|
14138
|
+
}) {
|
|
14139
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14140
|
+
"button",
|
|
14141
|
+
{
|
|
14142
|
+
type: "button",
|
|
14143
|
+
"data-task-chip": true,
|
|
14144
|
+
onClick: () => onSelect(task.id),
|
|
14145
|
+
className: "inline-flex max-w-full items-center gap-1.5 rounded-full border border-border/60 bg-background px-2.5 py-1 text-xs hover:bg-muted/40",
|
|
14146
|
+
children: [
|
|
14147
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14148
|
+
"span",
|
|
14149
|
+
{
|
|
14150
|
+
className: `size-1.5 shrink-0 rounded-full ${missionTaskStatusDotClass(task.status)}`
|
|
14151
|
+
}
|
|
14152
|
+
),
|
|
14153
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-foreground/85", children: missionTaskTitle(task.goal, 40) }),
|
|
14154
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 font-mono text-[9px] text-muted-foreground/60", children: task.id.slice(0, 8) })
|
|
14155
|
+
]
|
|
14156
|
+
}
|
|
14157
|
+
);
|
|
14158
|
+
}
|
|
14159
|
+
function TaskRailRow({
|
|
14160
|
+
task,
|
|
14161
|
+
selected,
|
|
14162
|
+
onSelect
|
|
14163
|
+
}) {
|
|
14164
|
+
const preview = stripMissionControlMarkup(
|
|
14165
|
+
task.status === "done" && task.result ? task.result : task.goal
|
|
14166
|
+
);
|
|
14167
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14168
|
+
"button",
|
|
14169
|
+
{
|
|
14170
|
+
type: "button",
|
|
14171
|
+
onClick: () => onSelect(task.id),
|
|
14172
|
+
className: `w-full rounded-md border px-3 py-2 text-left text-sm transition-colors ${selected ? "border-primary/40 bg-primary/5" : "border-transparent hover:bg-muted/40"}`,
|
|
14173
|
+
children: [
|
|
14174
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
14175
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14176
|
+
"span",
|
|
14177
|
+
{
|
|
14178
|
+
className: `size-2 shrink-0 rounded-full ${missionTaskStatusDotClass(task.status)}`
|
|
14179
|
+
}
|
|
14180
|
+
),
|
|
14181
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate font-medium text-foreground/90", children: task.goal })
|
|
14182
|
+
] }),
|
|
14183
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 flex flex-col gap-2 pl-4", children: [
|
|
14184
|
+
task.agentDefName ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-xs font-mono text-muted-foreground", children: task.agentDefName }) : null,
|
|
14185
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "line-clamp-2 min-w-0 flex-1 text-xs text-muted-foreground/70", children: preview })
|
|
14186
|
+
] })
|
|
14187
|
+
]
|
|
14188
|
+
}
|
|
14189
|
+
);
|
|
14190
|
+
}
|
|
14191
|
+
function MissionTasksTab({
|
|
14192
|
+
tasks,
|
|
14193
|
+
feed,
|
|
14194
|
+
onOpenTranscript
|
|
14195
|
+
}) {
|
|
14196
|
+
const [selectedId, setSelectedId] = react.useState(null);
|
|
14197
|
+
const groups = react.useMemo(() => missionTaskRailGroups(tasks), [tasks]);
|
|
14198
|
+
const blocks = react.useMemo(() => missionTaskBlocks(tasks), [tasks]);
|
|
14199
|
+
const byId = react.useMemo(() => new Map(tasks.map((t) => [t.id, t])), [tasks]);
|
|
14200
|
+
const effectiveId = selectedId && byId.has(selectedId) ? selectedId : defaultSelectedMissionTaskId(tasks);
|
|
14201
|
+
const selected = effectiveId ? byId.get(effectiveId) ?? null : null;
|
|
14202
|
+
const taskEvents = react.useMemo(() => {
|
|
14203
|
+
if (!selected || !feed.supported) return [];
|
|
14204
|
+
return feed.events.filter(
|
|
14205
|
+
(e) => missionEventTaskId(e, feed.sessions) === selected.id
|
|
14206
|
+
);
|
|
14207
|
+
}, [selected, feed]);
|
|
14208
|
+
const liveOutput = react.useMemo(() => {
|
|
14209
|
+
if (!selected || selected.status !== "running") return null;
|
|
14210
|
+
const outputs = taskEvents.filter(
|
|
14211
|
+
(e) => missionEventCategory(e.type) === "output"
|
|
14212
|
+
);
|
|
14213
|
+
return outputs.length > 0 ? outputs[outputs.length - 1] : null;
|
|
14214
|
+
}, [selected, taskEvents]);
|
|
14215
|
+
if (tasks.length === 0) {
|
|
14216
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-8 text-center text-sm text-muted-foreground/60", children: "No tasks spawned yet." });
|
|
14217
|
+
}
|
|
14218
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full min-h-0 gap-4", children: [
|
|
14219
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-72 shrink-0 space-y-4 overflow-y-auto pr-1", children: groups.map((group) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
14220
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-1 px-1 font-mono text-[10px] uppercase tracking-widest text-muted-foreground/70", children: [
|
|
14221
|
+
group.label,
|
|
14222
|
+
" (",
|
|
14223
|
+
group.tasks.length,
|
|
14224
|
+
")"
|
|
14225
|
+
] }),
|
|
14226
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1", children: group.tasks.map((t) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
14227
|
+
TaskRailRow,
|
|
14228
|
+
{
|
|
14229
|
+
task: t,
|
|
14230
|
+
selected: t.id === effectiveId,
|
|
14231
|
+
onSelect: setSelectedId
|
|
14232
|
+
},
|
|
14233
|
+
t.id
|
|
14234
|
+
)) })
|
|
14235
|
+
] }, group.key)) }),
|
|
14236
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14237
|
+
"div",
|
|
14238
|
+
{
|
|
14239
|
+
"data-testid": "task-detail",
|
|
14240
|
+
className: "min-w-0 flex-1 space-y-4 overflow-y-auto bg-card px-8 py-5",
|
|
14241
|
+
children: selected ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
14242
|
+
TaskDetail,
|
|
14243
|
+
{
|
|
14244
|
+
task: selected,
|
|
14245
|
+
allTasks: byId,
|
|
14246
|
+
blockedTaskIds: blocks[selected.id] ?? [],
|
|
14247
|
+
taskEvents,
|
|
14248
|
+
liveOutput,
|
|
14249
|
+
eventsSupported: feed.supported,
|
|
14250
|
+
onSelect: setSelectedId,
|
|
14251
|
+
onOpenTranscript
|
|
14252
|
+
}
|
|
14253
|
+
) : null
|
|
14254
|
+
}
|
|
14255
|
+
)
|
|
14256
|
+
] });
|
|
14257
|
+
}
|
|
14258
|
+
function TaskDetail({
|
|
14259
|
+
task,
|
|
14260
|
+
allTasks,
|
|
14261
|
+
blockedTaskIds,
|
|
14262
|
+
taskEvents,
|
|
14263
|
+
liveOutput,
|
|
14264
|
+
eventsSupported,
|
|
14265
|
+
onSelect,
|
|
14266
|
+
onOpenTranscript
|
|
14267
|
+
}) {
|
|
14268
|
+
const parents = task.parentIds.map((id) => allTasks.get(id)).filter((t) => Boolean(t));
|
|
14269
|
+
const children = blockedTaskIds.map((id) => allTasks.get(id)).filter((t) => Boolean(t));
|
|
14270
|
+
const timeLabel = task.startedAt && task.completedAt ? `${formatMissionTimestamp(task.startedAt)} \u2192 ${formatMissionTimestamp(task.completedAt)}` : task.startedAt ? `started ${formatMissionTimestamp(task.startedAt)}` : "not started";
|
|
14271
|
+
const outcome = deriveTaskOutcome({ task, taskEvents, liveOutput, parents });
|
|
14272
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-5", children: [
|
|
14273
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
14274
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
|
|
14275
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "min-w-0 flex-1 truncate text-lg font-semibold text-foreground", children: missionTaskTitle(task.goal) }),
|
|
14276
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 font-mono text-[10px] text-muted-foreground/60", children: task.id.slice(0, 8) })
|
|
14277
|
+
] }),
|
|
14278
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2 text-xs", children: [
|
|
14279
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14280
|
+
Badge,
|
|
14281
|
+
{
|
|
14282
|
+
variant: "destructive",
|
|
14283
|
+
className: `font-mono text-sm uppercase tracking-wide ${statusBadgeClass(task.status)}`,
|
|
14284
|
+
children: task.status
|
|
14285
|
+
}
|
|
14286
|
+
),
|
|
14287
|
+
task.agentDefName ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: task.agentDefName }) : null,
|
|
14288
|
+
task.attemptCount > 1 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
|
|
14289
|
+
"attempts ",
|
|
14290
|
+
task.attemptCount,
|
|
14291
|
+
"/",
|
|
14292
|
+
task.maxAttempts
|
|
14293
|
+
] }) : null,
|
|
14294
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-auto inline-flex items-center gap-1 text-muted-foreground", children: [
|
|
14295
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "size-3" }),
|
|
14296
|
+
timeLabel
|
|
14297
|
+
] })
|
|
14298
|
+
] })
|
|
14299
|
+
] }),
|
|
14300
|
+
/* @__PURE__ */ jsxRuntime.jsx(OutcomeCard, { outcome }),
|
|
14301
|
+
parents.length > 0 || children.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
14302
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-mono text-[10px] uppercase tracking-widest text-muted-foreground/70", children: "Dependencies" }),
|
|
14303
|
+
parents.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [
|
|
14304
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mr-1 text-[10px] uppercase text-muted-foreground/50", children: "Depends on" }),
|
|
14305
|
+
parents.map((p) => /* @__PURE__ */ jsxRuntime.jsx(TaskChip, { task: p, onSelect }, p.id))
|
|
14306
|
+
] }) : null,
|
|
14307
|
+
children.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [
|
|
14308
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mr-1 text-[10px] uppercase text-muted-foreground/50", children: "Blocks" }),
|
|
14309
|
+
children.map((c) => /* @__PURE__ */ jsxRuntime.jsx(TaskChip, { task: c, onSelect }, c.id))
|
|
14310
|
+
] }) : null
|
|
14311
|
+
] }) : null,
|
|
14312
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
14313
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-1 font-mono text-[10px] uppercase tracking-widest text-muted-foreground/70", children: "Brief" }),
|
|
14314
|
+
/* @__PURE__ */ jsxRuntime.jsx(MessageResponse, { className: "text-sm leading-relaxed text-foreground/90", children: task.goal })
|
|
14315
|
+
] }),
|
|
14316
|
+
task.resultMetadata ? /* @__PURE__ */ jsxRuntime.jsxs("details", { children: [
|
|
14317
|
+
/* @__PURE__ */ jsxRuntime.jsx("summary", { className: "cursor-pointer font-mono text-[10px] uppercase tracking-widest text-muted-foreground/70", children: "Result metadata" }),
|
|
14318
|
+
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "mt-1 max-h-64 overflow-auto whitespace-pre-wrap rounded bg-muted/30 px-2 py-1.5 text-[11px] text-foreground/90", children: JSON.stringify(task.resultMetadata, null, 2) })
|
|
14319
|
+
] }) : null,
|
|
14320
|
+
eventsSupported && taskEvents.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
14321
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2 font-mono font-semibold uppercase text-muted-foreground", children: [
|
|
14322
|
+
"History (",
|
|
14323
|
+
taskEvents.length,
|
|
14324
|
+
")"
|
|
14325
|
+
] }),
|
|
14326
|
+
/* @__PURE__ */ jsxRuntime.jsx("ol", { className: "space-y-3", children: taskEvents.map((e) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start gap-3 text-xs", children: [
|
|
14327
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-16 shrink-0 font-mono text-[10px] text-muted-foreground/60", children: formatMissionTimestamp(e.createdAt) }),
|
|
14328
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "", children: [
|
|
14329
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "shrink-0 font-mono uppercase text-muted-foreground", children: missionEventCategory(e.type) }),
|
|
14330
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "min-w-0 flex-1 text-foreground/80", children: missionEventSummary(e) })
|
|
14331
|
+
] })
|
|
14332
|
+
] }, e.id)) })
|
|
14333
|
+
] }) : null,
|
|
14334
|
+
task.currentSessionId && onOpenTranscript ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14335
|
+
Button,
|
|
14336
|
+
{
|
|
14337
|
+
"data-testid": "view-session",
|
|
14338
|
+
variant: "outline",
|
|
14339
|
+
size: "sm",
|
|
14340
|
+
onClick: () => onOpenTranscript(task.currentSessionId),
|
|
14341
|
+
children: [
|
|
14342
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { className: "size-4" }),
|
|
14343
|
+
"View ",
|
|
14344
|
+
task.agentDefName ?? "worker",
|
|
14345
|
+
" session"
|
|
14346
|
+
]
|
|
14347
|
+
}
|
|
14348
|
+
) : null
|
|
14349
|
+
] });
|
|
14350
|
+
}
|
|
14351
|
+
function deriveTaskOutcome({
|
|
14352
|
+
task,
|
|
14353
|
+
taskEvents,
|
|
14354
|
+
liveOutput,
|
|
14355
|
+
parents
|
|
14356
|
+
}) {
|
|
14357
|
+
const result = task.result ? stripMissionControlMarkup(task.result) : "";
|
|
14358
|
+
switch (task.status) {
|
|
14359
|
+
case "done":
|
|
14360
|
+
return {
|
|
14361
|
+
label: "Result",
|
|
14362
|
+
tone: "bg-emerald-500/5 ring-emerald-500/25",
|
|
14363
|
+
labelTone: "text-emerald-600",
|
|
14364
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "size-3" }),
|
|
14365
|
+
timestamp: task.completedAt,
|
|
14366
|
+
markdown: result || void 0,
|
|
14367
|
+
text: result ? void 0 : "Completed."
|
|
14368
|
+
};
|
|
14369
|
+
case "failed":
|
|
14370
|
+
return {
|
|
14371
|
+
label: "Failed",
|
|
14372
|
+
tone: "bg-destructive/5 ring-destructive/25",
|
|
14373
|
+
labelTone: "text-destructive",
|
|
14374
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircle, { className: "size-3" }),
|
|
14375
|
+
timestamp: task.completedAt,
|
|
14376
|
+
markdown: result || void 0,
|
|
14377
|
+
text: result ? void 0 : `Failed after ${task.attemptCount}/${task.maxAttempts} attempts.`
|
|
14378
|
+
};
|
|
14379
|
+
case "cancelled":
|
|
14380
|
+
return {
|
|
14381
|
+
label: "Cancelled",
|
|
14382
|
+
tone: "bg-muted/40 ring-border",
|
|
14383
|
+
labelTone: "text-muted-foreground",
|
|
14384
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Ban, { className: "size-3" }),
|
|
14385
|
+
timestamp: task.completedAt,
|
|
14386
|
+
text: "Task cancelled."
|
|
14387
|
+
};
|
|
14388
|
+
case "running":
|
|
14389
|
+
return {
|
|
14390
|
+
label: "Live output",
|
|
14391
|
+
tone: "bg-amber-500/5 ring-amber-500/25",
|
|
14392
|
+
labelTone: "text-amber-600",
|
|
14393
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleDot, { className: "size-3 animate-pulse" }),
|
|
14394
|
+
timestamp: liveOutput?.createdAt ?? null,
|
|
14395
|
+
text: liveOutput ? missionEventSummary(liveOutput) : "Working \u2014 no output yet."
|
|
14396
|
+
};
|
|
14397
|
+
case "blocked": {
|
|
14398
|
+
const blockedEvent = [...taskEvents].reverse().find((e) => e.type === "task.blocked");
|
|
14399
|
+
return {
|
|
14400
|
+
label: "Waiting",
|
|
14401
|
+
tone: "bg-amber-500/5 ring-amber-500/20",
|
|
14402
|
+
labelTone: "text-amber-700 dark:text-amber-500",
|
|
14403
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "size-3" }),
|
|
14404
|
+
timestamp: blockedEvent?.createdAt ?? null,
|
|
14405
|
+
text: blockedEvent ? missionEventSummary(blockedEvent) : "Blocked \u2014 awaiting input."
|
|
14406
|
+
};
|
|
14407
|
+
}
|
|
14408
|
+
default: {
|
|
14409
|
+
const pending = parents.filter((p) => p.status !== "done");
|
|
14410
|
+
const text = pending.length > 0 ? `Waiting on ${pending.map((p) => missionTaskTitle(p.goal, 40)).join(" \xB7 ")} to complete.` : "Queued \u2014 waiting for a worker slot.";
|
|
14411
|
+
return {
|
|
14412
|
+
label: "Waiting",
|
|
14413
|
+
tone: "bg-muted/30 ring-border",
|
|
14414
|
+
labelTone: "text-muted-foreground",
|
|
14415
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "size-3" }),
|
|
14416
|
+
timestamp: null,
|
|
14417
|
+
text
|
|
14418
|
+
};
|
|
14419
|
+
}
|
|
14420
|
+
}
|
|
14421
|
+
}
|
|
14422
|
+
function OutcomeCard({ outcome }) {
|
|
14423
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14424
|
+
Card,
|
|
14425
|
+
{
|
|
14426
|
+
"data-testid": "task-outcome",
|
|
14427
|
+
size: "sm",
|
|
14428
|
+
className: `mx-1 gap-3 rounded-lg py-4 shadow-none ${outcome.tone}`,
|
|
14429
|
+
children: [
|
|
14430
|
+
/* @__PURE__ */ jsxRuntime.jsxs(CardHeader, { children: [
|
|
14431
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
14432
|
+
CardTitle,
|
|
14433
|
+
{
|
|
14434
|
+
className: `flex items-center gap-1.5 font-mono text-[11px] font-semibold tracking-widest ${outcome.labelTone}`,
|
|
14435
|
+
children: [
|
|
14436
|
+
outcome.icon,
|
|
14437
|
+
outcome.label
|
|
14438
|
+
]
|
|
14439
|
+
}
|
|
14440
|
+
),
|
|
14441
|
+
outcome.timestamp ? /* @__PURE__ */ jsxRuntime.jsx(CardAction, { className: "font-mono text-[10px] text-muted-foreground/60", children: formatMissionTimestamp(outcome.timestamp) }) : null
|
|
14442
|
+
] }),
|
|
14443
|
+
/* @__PURE__ */ jsxRuntime.jsx(CardContent, { children: outcome.markdown ? /* @__PURE__ */ jsxRuntime.jsx(MessageResponse, { className: "font-mono text-xs leading-relaxed text-foreground/90", children: outcome.markdown }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-wrap font-mono text-xs leading-relaxed text-foreground/90", children: outcome.text }) })
|
|
14444
|
+
]
|
|
14445
|
+
}
|
|
14446
|
+
);
|
|
14447
|
+
}
|
|
14448
|
+
var MISSION_WORKER_KIND_BADGE_CLASS = {
|
|
14449
|
+
task: "border-primary/40 bg-primary/10 text-primary uppercase tracking-wide text-[10px]",
|
|
14450
|
+
worker: "border-foreground/30 bg-foreground/5 text-foreground/80 uppercase tracking-wide text-[10px]",
|
|
14451
|
+
delegation: "border-foreground/20 bg-foreground/[0.03] text-foreground/60 uppercase tracking-wide text-[10px]"
|
|
14452
|
+
};
|
|
14453
|
+
var MISSION_WORKER_KIND_TOOLTIP = {
|
|
14454
|
+
task: "Durable Task row created by spawn_task. Retried by the dispatcher; survives across coordinator wakes.",
|
|
14455
|
+
worker: "Async one-shot session spawned by spawn_worker. Durable session, no retry/DAG.",
|
|
14456
|
+
delegation: "Sync fork-join child spawned by delegate_task. Coordinator's wake blocked until it finished."
|
|
14457
|
+
};
|
|
14458
|
+
function MissionWorkersTab({
|
|
14459
|
+
workers,
|
|
14460
|
+
tasks,
|
|
14461
|
+
onOpenTranscript
|
|
14462
|
+
}) {
|
|
14463
|
+
if (workers.length === 0) {
|
|
14464
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-8 text-center text-sm text-muted-foreground/60", children: "No workers attached to this mission right now." });
|
|
14465
|
+
}
|
|
14466
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-3 sm:grid-cols-2", children: workers.map((w) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
14467
|
+
WorkerCard,
|
|
14468
|
+
{
|
|
14469
|
+
worker: w,
|
|
14470
|
+
tasks,
|
|
14471
|
+
onOpenTranscript
|
|
14472
|
+
},
|
|
14473
|
+
w.workerSessionId
|
|
14474
|
+
)) });
|
|
14475
|
+
}
|
|
14476
|
+
function WorkerCard({
|
|
14477
|
+
worker,
|
|
14478
|
+
tasks,
|
|
14479
|
+
onOpenTranscript
|
|
14480
|
+
}) {
|
|
14481
|
+
const counts = missionWorkerTaskCounts(worker, tasks);
|
|
14482
|
+
const statusLabel2 = worker.kind === "task" ? worker.taskStatus ?? "\u2014" : worker.sessionStatus;
|
|
14483
|
+
const onTranscriptClick = (e) => {
|
|
14484
|
+
if (onOpenTranscript) {
|
|
14485
|
+
e.preventDefault();
|
|
14486
|
+
onOpenTranscript(worker.workerSessionId);
|
|
14487
|
+
}
|
|
14488
|
+
};
|
|
14489
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 rounded-md border border-border/60 bg-card p-4 shadow-sm", children: [
|
|
14490
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
14491
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
|
|
14492
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate text-sm font-semibold text-foreground", children: worker.agentDefName ?? "worker" }),
|
|
14493
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
|
|
14494
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14495
|
+
Badge,
|
|
14496
|
+
{
|
|
14497
|
+
variant: "outline",
|
|
14498
|
+
className: `mt-1 ${MISSION_WORKER_KIND_BADGE_CLASS[worker.kind]}`,
|
|
14499
|
+
children: worker.kind
|
|
14500
|
+
}
|
|
14501
|
+
) }),
|
|
14502
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { className: "max-w-xs", children: MISSION_WORKER_KIND_TOOLTIP[worker.kind] })
|
|
14503
|
+
] })
|
|
14504
|
+
] }),
|
|
14505
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 font-mono text-[10px] uppercase tracking-wider text-muted-foreground/70", children: statusLabel2 })
|
|
14506
|
+
] }),
|
|
14507
|
+
counts ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-6", children: [
|
|
14508
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
14509
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xl font-bold tabular-nums text-foreground", children: counts.completed }),
|
|
14510
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-mono text-[9px] uppercase tracking-widest text-muted-foreground/60", children: "Completed" })
|
|
14511
|
+
] }),
|
|
14512
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
14513
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14514
|
+
"div",
|
|
14515
|
+
{
|
|
14516
|
+
className: `text-xl font-bold tabular-nums ${counts.inFlight > 0 ? "text-amber-600" : "text-foreground"}`,
|
|
14517
|
+
children: counts.inFlight
|
|
14518
|
+
}
|
|
14519
|
+
),
|
|
14520
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-mono text-[9px] uppercase tracking-widest text-muted-foreground/60", children: "In flight" })
|
|
14521
|
+
] })
|
|
14522
|
+
] }) : null,
|
|
14523
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-auto space-y-1 border-t border-border/40 pt-2", children: [
|
|
14524
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
14525
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-mono text-[10px] text-muted-foreground/70", children: worker.latestEventKind ?? "no events yet" }),
|
|
14526
|
+
worker.latestEventAt ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 font-mono text-[10px] text-muted-foreground/60", children: formatMissionTimestamp(worker.latestEventAt) }) : null
|
|
14527
|
+
] }),
|
|
14528
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate text-xs text-foreground/80", children: deriveMissionWorkerActivityLabel(worker) }),
|
|
14529
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14530
|
+
"a",
|
|
14531
|
+
{
|
|
14532
|
+
href: worker.transcriptUrl,
|
|
14533
|
+
target: "_blank",
|
|
14534
|
+
rel: "noreferrer",
|
|
14535
|
+
onClick: onTranscriptClick,
|
|
14536
|
+
className: "inline-block text-xs text-primary hover:underline",
|
|
14537
|
+
children: "View session"
|
|
14538
|
+
}
|
|
14539
|
+
)
|
|
14540
|
+
] })
|
|
14541
|
+
] });
|
|
14542
|
+
}
|
|
14543
|
+
var PAGE_LIMIT = 500;
|
|
14544
|
+
var MAX_PAGES_PER_PUMP = 20;
|
|
14545
|
+
function useMissionEvents(input) {
|
|
14546
|
+
const { adapter, missionId, missionStatus, isTerminal, pollIntervalMs } = input;
|
|
14547
|
+
const supported = typeof adapter.listMissionEvents === "function";
|
|
14548
|
+
const [events, setEvents] = react.useState([]);
|
|
14549
|
+
const [sessions, setSessions] = react.useState({});
|
|
14550
|
+
const lastIdRef = react.useRef(null);
|
|
14551
|
+
const pumpingRef = react.useRef(false);
|
|
14552
|
+
const mountedRef = react.useRef(true);
|
|
14553
|
+
react.useEffect(() => {
|
|
14554
|
+
mountedRef.current = true;
|
|
14555
|
+
return () => {
|
|
14556
|
+
mountedRef.current = false;
|
|
14557
|
+
};
|
|
14558
|
+
}, []);
|
|
14559
|
+
react.useEffect(() => {
|
|
14560
|
+
lastIdRef.current = null;
|
|
14561
|
+
setEvents([]);
|
|
14562
|
+
setSessions({});
|
|
14563
|
+
}, [missionId]);
|
|
14564
|
+
const pump = react.useCallback(async () => {
|
|
14565
|
+
const fn = adapter.listMissionEvents;
|
|
14566
|
+
if (typeof fn !== "function" || pumpingRef.current) return;
|
|
14567
|
+
pumpingRef.current = true;
|
|
14568
|
+
try {
|
|
14569
|
+
for (let page = 0; page < MAX_PAGES_PER_PUMP; page += 1) {
|
|
14570
|
+
const resp = await fn.call(adapter, {
|
|
14571
|
+
missionId,
|
|
14572
|
+
afterId: lastIdRef.current ?? void 0,
|
|
14573
|
+
limit: PAGE_LIMIT
|
|
14574
|
+
});
|
|
14575
|
+
if (!mountedRef.current) return;
|
|
14576
|
+
if (resp.events.length > 0) {
|
|
14577
|
+
lastIdRef.current = resp.events[resp.events.length - 1].id;
|
|
14578
|
+
setEvents((prev) => mergeMissionEvents(prev, resp.events));
|
|
14579
|
+
}
|
|
14580
|
+
if (Object.keys(resp.sessions).length > 0) {
|
|
14581
|
+
setSessions((prev) => ({ ...prev, ...resp.sessions }));
|
|
14582
|
+
}
|
|
14583
|
+
if (resp.events.length < PAGE_LIMIT) break;
|
|
14584
|
+
}
|
|
14585
|
+
} catch {
|
|
14586
|
+
} finally {
|
|
14587
|
+
pumpingRef.current = false;
|
|
14588
|
+
}
|
|
14589
|
+
}, [adapter, missionId]);
|
|
14590
|
+
react.useEffect(() => {
|
|
14591
|
+
void pump();
|
|
14592
|
+
}, [pump]);
|
|
14593
|
+
react.useEffect(() => {
|
|
14594
|
+
if (!supported || missionStatus === null || isTerminal) return;
|
|
14595
|
+
const id = window.setInterval(() => {
|
|
14596
|
+
void pump();
|
|
14597
|
+
}, pollIntervalMs);
|
|
14598
|
+
return () => {
|
|
14599
|
+
window.clearInterval(id);
|
|
14600
|
+
};
|
|
14601
|
+
}, [supported, missionStatus, isTerminal, pollIntervalMs, pump]);
|
|
14602
|
+
return { supported, events, sessions };
|
|
14603
|
+
}
|
|
14604
|
+
var DEFAULT_POLL_INTERVAL_MS = 5e3;
|
|
14605
|
+
function CountBadge({ n }) {
|
|
14606
|
+
if (n === 0) return null;
|
|
14607
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 rounded bg-muted px-1 py-px text-[9px] text-muted-foreground/70", children: n });
|
|
14608
|
+
}
|
|
14609
|
+
var INITIAL_STATE = {
|
|
14610
|
+
mission: null,
|
|
14611
|
+
tasks: [],
|
|
13286
14612
|
workers: [],
|
|
13287
14613
|
loading: true,
|
|
13288
14614
|
error: null
|
|
@@ -13361,10 +14687,13 @@ function MissionDashboard({
|
|
|
13361
14687
|
window.clearInterval(id);
|
|
13362
14688
|
};
|
|
13363
14689
|
}, [refresh, state.mission, pollIntervalMs]);
|
|
13364
|
-
const
|
|
13365
|
-
|
|
13366
|
-
|
|
13367
|
-
|
|
14690
|
+
const feed = useMissionEvents({
|
|
14691
|
+
adapter,
|
|
14692
|
+
missionId,
|
|
14693
|
+
missionStatus: state.mission?.status ?? null,
|
|
14694
|
+
isTerminal: state.mission ? isTerminalMissionStatus(state.mission.status) : false,
|
|
14695
|
+
pollIntervalMs
|
|
14696
|
+
});
|
|
13368
14697
|
const runningWorkerCount = react.useMemo(
|
|
13369
14698
|
// "running" means the child is still consuming compute right now.
|
|
13370
14699
|
// For task-backed children that's ``taskStatus === "running"``; for
|
|
@@ -13433,7 +14762,6 @@ function MissionDashboard({
|
|
|
13433
14762
|
}
|
|
13434
14763
|
};
|
|
13435
14764
|
const statusTone = mission.status === "satisfied" ? "border-emerald-500/40 bg-emerald-500/10 text-emerald-700 dark:text-emerald-400" : mission.status === "failed" || mission.status === "cancelled" ? "border-destructive/40 bg-destructive/10 text-destructive" : mission.status === "paused" ? "border-amber-500/40 bg-amber-500/10 text-amber-700 dark:text-amber-400" : "border-primary/40 bg-primary/10 text-primary";
|
|
13436
|
-
const activity = buildMissionActivity(mission, state.tasks, state.workers);
|
|
13437
14765
|
const isActive = ACTIVE_MISSION_STATUSES.has(mission.status);
|
|
13438
14766
|
const iterationPct = mission.maxIterations > 0 ? Math.min(100, mission.iteration / mission.maxIterations * 100) : 0;
|
|
13439
14767
|
return /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { delayDuration: 300, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-1 flex-col overflow-hidden bg-muted/30", children: [
|
|
@@ -13540,18 +14868,18 @@ function MissionDashboard({
|
|
|
13540
14868
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
13541
14869
|
Tabs,
|
|
13542
14870
|
{
|
|
13543
|
-
defaultValue: "
|
|
14871
|
+
defaultValue: "tasks",
|
|
13544
14872
|
className: "mt-5 flex flex-1 flex-col overflow-hidden sm:mt-6",
|
|
13545
14873
|
children: [
|
|
13546
14874
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 border-b border-border bg-background px-5 sm:px-6", children: /* @__PURE__ */ jsxRuntime.jsxs(TabsList, { variant: "line", children: [
|
|
13547
|
-
/* @__PURE__ */ jsxRuntime.jsxs(TabsTrigger, { value: "activity", children: [
|
|
13548
|
-
"Activity",
|
|
13549
|
-
/* @__PURE__ */ jsxRuntime.jsx(CountBadge, { n: activity.length })
|
|
13550
|
-
] }),
|
|
13551
14875
|
/* @__PURE__ */ jsxRuntime.jsxs(TabsTrigger, { value: "tasks", children: [
|
|
13552
14876
|
"Tasks",
|
|
13553
14877
|
/* @__PURE__ */ jsxRuntime.jsx(CountBadge, { n: state.tasks.length })
|
|
13554
14878
|
] }),
|
|
14879
|
+
feed.supported ? /* @__PURE__ */ jsxRuntime.jsxs(TabsTrigger, { value: "activity", children: [
|
|
14880
|
+
"Activity",
|
|
14881
|
+
/* @__PURE__ */ jsxRuntime.jsx(CountBadge, { n: feed.events.length })
|
|
14882
|
+
] }) : null,
|
|
13555
14883
|
/* @__PURE__ */ jsxRuntime.jsxs(TabsTrigger, { value: "workers", children: [
|
|
13556
14884
|
"Workers",
|
|
13557
14885
|
/* @__PURE__ */ jsxRuntime.jsx(CountBadge, { n: state.workers.length })
|
|
@@ -13559,22 +14887,24 @@ function MissionDashboard({
|
|
|
13559
14887
|
/* @__PURE__ */ jsxRuntime.jsx(TabsTrigger, { value: "metadata", children: "Metadata" })
|
|
13560
14888
|
] }) }),
|
|
13561
14889
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-y-auto bg-background px-5 py-4 sm:px-6", children: [
|
|
13562
|
-
/* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: "
|
|
13563
|
-
|
|
13564
|
-
TasksList,
|
|
14890
|
+
/* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: "tasks", className: "mt-0 h-full", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14891
|
+
MissionTasksTab,
|
|
13565
14892
|
{
|
|
13566
|
-
|
|
13567
|
-
|
|
14893
|
+
tasks: state.tasks,
|
|
14894
|
+
feed,
|
|
14895
|
+
onOpenTranscript
|
|
13568
14896
|
}
|
|
13569
14897
|
) }),
|
|
14898
|
+
feed.supported ? /* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: "activity", className: "mt-0", children: /* @__PURE__ */ jsxRuntime.jsx(MissionActivityTab, { feed }) }) : null,
|
|
13570
14899
|
/* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: "workers", className: "mt-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13571
|
-
|
|
14900
|
+
MissionWorkersTab,
|
|
13572
14901
|
{
|
|
13573
14902
|
workers: state.workers,
|
|
14903
|
+
tasks: state.tasks,
|
|
13574
14904
|
onOpenTranscript
|
|
13575
14905
|
}
|
|
13576
14906
|
) }),
|
|
13577
|
-
/* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: "metadata", className: "mt-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14907
|
+
/* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: "metadata", className: "mt-0", children: /* @__PURE__ */ jsxRuntime.jsx(MissionMetadataTab, { mission }) })
|
|
13578
14908
|
] })
|
|
13579
14909
|
]
|
|
13580
14910
|
}
|
|
@@ -13638,234 +14968,6 @@ function MissionDashboard({
|
|
|
13638
14968
|
)
|
|
13639
14969
|
] }) });
|
|
13640
14970
|
}
|
|
13641
|
-
function ActivityTimeline({ entries }) {
|
|
13642
|
-
if (entries.length === 0) {
|
|
13643
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-8 text-center text-sm text-muted-foreground/60", children: "No mission activity yet." });
|
|
13644
|
-
}
|
|
13645
|
-
return /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "space-y-1", children: entries.map((e, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
13646
|
-
"li",
|
|
13647
|
-
{
|
|
13648
|
-
className: "flex items-start gap-3 rounded px-2 py-1.5 text-sm hover:bg-muted/30",
|
|
13649
|
-
children: [
|
|
13650
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-20 shrink-0 font-mono text-[10px] text-muted-foreground/60", children: formatTimestamp(e.at) }),
|
|
13651
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13652
|
-
"span",
|
|
13653
|
-
{
|
|
13654
|
-
className: `shrink-0 rounded border px-1.5 py-0.5 font-mono text-[9px] uppercase tracking-wide ${ACTIVITY_KIND_TONE[e.kind]}`,
|
|
13655
|
-
children: e.label
|
|
13656
|
-
}
|
|
13657
|
-
),
|
|
13658
|
-
e.detail ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate text-foreground/80", children: e.detail }) : null
|
|
13659
|
-
]
|
|
13660
|
-
},
|
|
13661
|
-
`${e.kind}-${e.at}-${i}`
|
|
13662
|
-
)) });
|
|
13663
|
-
}
|
|
13664
|
-
function TaskRow({ task }) {
|
|
13665
|
-
const [open, setOpen] = react.useState(false);
|
|
13666
|
-
const goalPreview = firstLine3(task.goal, 160);
|
|
13667
|
-
const hasMore = task.goal.length > 160 || Boolean(task.result) || Boolean(task.resultMetadata);
|
|
13668
|
-
const statusTone = task.status === "done" ? "border-emerald-500/30 bg-emerald-500/10 text-emerald-600" : task.status === "failed" ? "border-destructive/30 bg-destructive/10 text-destructive" : task.status === "cancelled" ? "border-border bg-muted text-muted-foreground" : task.status === "running" ? "border-primary/30 bg-primary/10 text-primary" : "border-foreground/20 bg-foreground/5 text-foreground/70";
|
|
13669
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Collapsible, { open, onOpenChange: setOpen, asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "rounded border border-border/40 text-sm", children: [
|
|
13670
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13671
|
-
CollapsibleTrigger,
|
|
13672
|
-
{
|
|
13673
|
-
asChild: true,
|
|
13674
|
-
disabled: !hasMore,
|
|
13675
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
13676
|
-
"button",
|
|
13677
|
-
{
|
|
13678
|
-
type: "button",
|
|
13679
|
-
className: "flex w-full items-start gap-3 px-3 py-2 text-left hover:bg-muted/30 disabled:hover:bg-transparent",
|
|
13680
|
-
children: [
|
|
13681
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13682
|
-
lucideReact.ChevronRight,
|
|
13683
|
-
{
|
|
13684
|
-
className: `mt-0.5 size-3.5 shrink-0 text-muted-foreground/60 transition-transform ${open ? "rotate-90" : ""} ${hasMore ? "" : "opacity-0"}`
|
|
13685
|
-
}
|
|
13686
|
-
),
|
|
13687
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13688
|
-
"span",
|
|
13689
|
-
{
|
|
13690
|
-
className: `shrink-0 rounded border px-1.5 py-0.5 font-mono text-[9px] uppercase tracking-wide ${statusTone}`,
|
|
13691
|
-
children: task.status
|
|
13692
|
-
}
|
|
13693
|
-
),
|
|
13694
|
-
task.agentDefName ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-[10px] text-muted-foreground/70", children: task.agentDefName }) : null,
|
|
13695
|
-
task.attemptCount > 1 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "shrink-0 text-[10px] text-muted-foreground/60", children: [
|
|
13696
|
-
"(",
|
|
13697
|
-
task.attemptCount,
|
|
13698
|
-
"/",
|
|
13699
|
-
task.maxAttempts,
|
|
13700
|
-
")"
|
|
13701
|
-
] }) : null,
|
|
13702
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate text-foreground/80", children: goalPreview })
|
|
13703
|
-
]
|
|
13704
|
-
}
|
|
13705
|
-
)
|
|
13706
|
-
}
|
|
13707
|
-
),
|
|
13708
|
-
/* @__PURE__ */ jsxRuntime.jsxs(CollapsibleContent, { className: "border-t border-border/40 px-3 py-2 text-xs", children: [
|
|
13709
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2", children: [
|
|
13710
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-1 font-mono text-[9px] uppercase tracking-wide text-muted-foreground/60", children: "Goal" }),
|
|
13711
|
-
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "max-h-64 overflow-auto whitespace-pre-wrap rounded bg-muted/30 px-2 py-1.5 text-[11px] text-foreground/90", children: task.goal })
|
|
13712
|
-
] }),
|
|
13713
|
-
task.parentIds.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2 text-[10px] text-muted-foreground/70", children: [
|
|
13714
|
-
"after: ",
|
|
13715
|
-
task.parentIds.map((p) => p.slice(0, 8)).join(", ")
|
|
13716
|
-
] }) : null,
|
|
13717
|
-
task.result ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2", children: [
|
|
13718
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-1 font-mono text-[9px] uppercase tracking-wide text-muted-foreground/60", children: "Result" }),
|
|
13719
|
-
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "max-h-64 overflow-auto whitespace-pre-wrap rounded bg-muted/30 px-2 py-1.5 text-[11px] text-foreground/90", children: task.result })
|
|
13720
|
-
] }) : null,
|
|
13721
|
-
task.resultMetadata ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
13722
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-1 font-mono text-[9px] uppercase tracking-wide text-muted-foreground/60", children: "Result metadata" }),
|
|
13723
|
-
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "max-h-64 overflow-auto whitespace-pre-wrap rounded bg-muted/30 px-2 py-1.5 text-[11px] text-foreground/90", children: JSON.stringify(task.resultMetadata, null, 2) })
|
|
13724
|
-
] }) : null
|
|
13725
|
-
] })
|
|
13726
|
-
] }) });
|
|
13727
|
-
}
|
|
13728
|
-
function TasksList({
|
|
13729
|
-
taskBuckets,
|
|
13730
|
-
totalTasks
|
|
13731
|
-
}) {
|
|
13732
|
-
if (totalTasks === 0) {
|
|
13733
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-8 text-center text-sm text-muted-foreground/60", children: "No tasks spawned yet." });
|
|
13734
|
-
}
|
|
13735
|
-
const headings = {
|
|
13736
|
-
in_flight: "In flight",
|
|
13737
|
-
blocked: "Blocked",
|
|
13738
|
-
done: "Done",
|
|
13739
|
-
failed_or_cancelled: "Failed / cancelled"
|
|
13740
|
-
};
|
|
13741
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children: Object.keys(headings).map((bucket) => {
|
|
13742
|
-
const rows = taskBuckets[bucket];
|
|
13743
|
-
if (rows.length === 0) return null;
|
|
13744
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
|
|
13745
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "font-mono text-[10px] uppercase tracking-widest text-muted-foreground/70", children: [
|
|
13746
|
-
headings[bucket],
|
|
13747
|
-
" (",
|
|
13748
|
-
rows.length,
|
|
13749
|
-
")"
|
|
13750
|
-
] }),
|
|
13751
|
-
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "space-y-1", children: rows.map((task) => /* @__PURE__ */ jsxRuntime.jsx(TaskRow, { task }, task.id)) })
|
|
13752
|
-
] }, bucket);
|
|
13753
|
-
}) });
|
|
13754
|
-
}
|
|
13755
|
-
function WorkersList({
|
|
13756
|
-
workers,
|
|
13757
|
-
onOpenTranscript
|
|
13758
|
-
}) {
|
|
13759
|
-
if (workers.length === 0) {
|
|
13760
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-8 text-center text-sm text-muted-foreground/60", children: "No workers attached to this mission right now." });
|
|
13761
|
-
}
|
|
13762
|
-
return /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "space-y-1", children: workers.map((w) => {
|
|
13763
|
-
const onTranscriptClick = (e) => {
|
|
13764
|
-
if (onOpenTranscript) {
|
|
13765
|
-
e.preventDefault();
|
|
13766
|
-
onOpenTranscript(w.workerSessionId);
|
|
13767
|
-
}
|
|
13768
|
-
};
|
|
13769
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
13770
|
-
"li",
|
|
13771
|
-
{
|
|
13772
|
-
className: "flex flex-col gap-2 rounded border border-border/40 px-3 py-2 text-sm sm:flex-row sm:items-start sm:justify-between",
|
|
13773
|
-
children: [
|
|
13774
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1 space-y-1", children: [
|
|
13775
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
13776
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13777
|
-
Badge,
|
|
13778
|
-
{
|
|
13779
|
-
variant: "outline",
|
|
13780
|
-
className: MISSION_WORKER_KIND_BADGE_CLASS[w.kind],
|
|
13781
|
-
title: MISSION_WORKER_KIND_TOOLTIP[w.kind],
|
|
13782
|
-
children: w.kind
|
|
13783
|
-
}
|
|
13784
|
-
),
|
|
13785
|
-
/* @__PURE__ */ jsxRuntime.jsx(Badge, { className: "text-foreground/70", children: w.kind === "task" ? w.taskStatus ?? "\u2014" : w.sessionStatus }),
|
|
13786
|
-
w.agentDefName ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground/70", children: w.agentDefName }) : null,
|
|
13787
|
-
w.latestEventAt ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto font-mono text-[10px] text-muted-foreground/60", children: formatTimestamp(w.latestEventAt) }) : null
|
|
13788
|
-
] }),
|
|
13789
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate text-sm text-foreground/80", children: deriveMissionWorkerActivityLabel(w) })
|
|
13790
|
-
] }),
|
|
13791
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13792
|
-
"a",
|
|
13793
|
-
{
|
|
13794
|
-
href: w.transcriptUrl,
|
|
13795
|
-
target: "_blank",
|
|
13796
|
-
rel: "noreferrer",
|
|
13797
|
-
onClick: onTranscriptClick,
|
|
13798
|
-
className: "self-start text-xs text-primary hover:underline",
|
|
13799
|
-
children: "View session"
|
|
13800
|
-
}
|
|
13801
|
-
)
|
|
13802
|
-
]
|
|
13803
|
-
},
|
|
13804
|
-
w.workerSessionId
|
|
13805
|
-
);
|
|
13806
|
-
}) });
|
|
13807
|
-
}
|
|
13808
|
-
function MetadataPane({ mission }) {
|
|
13809
|
-
const rows = [];
|
|
13810
|
-
rows.push({
|
|
13811
|
-
label: "Mission ID",
|
|
13812
|
-
value: /* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-[11px]", children: mission.id })
|
|
13813
|
-
});
|
|
13814
|
-
rows.push({
|
|
13815
|
-
label: "Session ID",
|
|
13816
|
-
value: /* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-[11px]", children: mission.sessionId })
|
|
13817
|
-
});
|
|
13818
|
-
rows.push({
|
|
13819
|
-
label: "Agent ID",
|
|
13820
|
-
value: /* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-[11px]", children: mission.agentId })
|
|
13821
|
-
});
|
|
13822
|
-
rows.push({ label: "Status", value: mission.status });
|
|
13823
|
-
rows.push({
|
|
13824
|
-
label: "Iteration",
|
|
13825
|
-
value: `${mission.iteration} / ${mission.maxIterations}`
|
|
13826
|
-
});
|
|
13827
|
-
rows.push({
|
|
13828
|
-
label: "Owner",
|
|
13829
|
-
value: mission.userId ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
13830
|
-
"user ",
|
|
13831
|
-
/* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-[11px]", children: mission.userId })
|
|
13832
|
-
] }) : mission.serviceAccountId ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
13833
|
-
"service account ",
|
|
13834
|
-
/* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-[11px]", children: mission.serviceAccountId })
|
|
13835
|
-
] }) : "\u2014"
|
|
13836
|
-
});
|
|
13837
|
-
rows.push({
|
|
13838
|
-
label: "Created",
|
|
13839
|
-
value: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[11px]", children: new Date(mission.createdAt).toLocaleString() })
|
|
13840
|
-
});
|
|
13841
|
-
rows.push({
|
|
13842
|
-
label: "Updated",
|
|
13843
|
-
value: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[11px]", children: new Date(mission.updatedAt).toLocaleString() })
|
|
13844
|
-
});
|
|
13845
|
-
if (mission.pausedReason) {
|
|
13846
|
-
rows.push({ label: "Paused reason", value: mission.pausedReason });
|
|
13847
|
-
}
|
|
13848
|
-
if (mission.cancelledReason) {
|
|
13849
|
-
rows.push({ label: "Cancelled reason", value: mission.cancelledReason });
|
|
13850
|
-
}
|
|
13851
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
13852
|
-
mission.lastEvaluationResult ? /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-2", children: [
|
|
13853
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "font-mono text-[10px] uppercase tracking-widest text-muted-foreground/70", children: [
|
|
13854
|
-
"Last verdict \u2014 ",
|
|
13855
|
-
mission.lastEvaluationResult
|
|
13856
|
-
] }),
|
|
13857
|
-
mission.lastEvaluationFeedback ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-wrap text-sm text-foreground/90", children: mission.lastEvaluationFeedback }) : null,
|
|
13858
|
-
mission.lastEvaluationExplanation ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-wrap text-xs text-muted-foreground/70", children: mission.lastEvaluationExplanation }) : null
|
|
13859
|
-
] }) : null,
|
|
13860
|
-
/* @__PURE__ */ jsxRuntime.jsxs("section", { children: [
|
|
13861
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2 font-mono text-[10px] uppercase tracking-widest text-muted-foreground/70", children: "Identifiers" }),
|
|
13862
|
-
/* @__PURE__ */ jsxRuntime.jsx("dl", { className: "grid grid-cols-[max-content_1fr] gap-x-4 gap-y-1 text-xs", children: rows.map((r) => /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
|
|
13863
|
-
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-muted-foreground/70", children: r.label }),
|
|
13864
|
-
/* @__PURE__ */ jsxRuntime.jsx("dd", { className: "break-all text-foreground/90", children: r.value })
|
|
13865
|
-
] }, r.label)) })
|
|
13866
|
-
] })
|
|
13867
|
-
] });
|
|
13868
|
-
}
|
|
13869
14971
|
init_utils();
|
|
13870
14972
|
var DEFAULT_POLL_INTERVAL_MS2 = 3e4;
|
|
13871
14973
|
function fingerprint(items) {
|
|
@@ -14105,7 +15207,7 @@ function MissionsPanel({
|
|
|
14105
15207
|
if (!adapter.cancelMission || busyMissionId) return;
|
|
14106
15208
|
setBusyMissionId(missionId);
|
|
14107
15209
|
try {
|
|
14108
|
-
await adapter.cancelMission({ missionId });
|
|
15210
|
+
await adapter.cancelMission({ missionId, cascadeToWorkers: true });
|
|
14109
15211
|
setItems((current) => {
|
|
14110
15212
|
const next = current.filter((m) => m.id !== missionId);
|
|
14111
15213
|
lastFingerprint.current = fingerprint(next);
|
|
@@ -14897,24 +15999,40 @@ exports.ACTIVE_MISSION_STATUSES = ACTIVE_MISSION_STATUSES;
|
|
|
14897
15999
|
exports.AgentChat = AgentChat;
|
|
14898
16000
|
exports.AgentChatAdapterProvider = AgentChatAdapterProvider;
|
|
14899
16001
|
exports.CitationText = CitationText;
|
|
16002
|
+
exports.CodingAgentsPanel = CodingAgentsPanel;
|
|
14900
16003
|
exports.ComposioConnectCard = ComposioConnectCard;
|
|
14901
16004
|
exports.InboxPanel = InboxPanel;
|
|
14902
16005
|
exports.IntegrationsBand = IntegrationsBand;
|
|
14903
16006
|
exports.IntegrationsPage = IntegrationsPage;
|
|
16007
|
+
exports.MISSION_EVENT_CATEGORIES = MISSION_EVENT_CATEGORIES;
|
|
14904
16008
|
exports.MessageResponse = MessageResponse;
|
|
14905
16009
|
exports.MissionDashboard = MissionDashboard;
|
|
14906
16010
|
exports.MissionsPanel = MissionsPanel;
|
|
14907
16011
|
exports.ResearchSourcesPanel = ResearchSourcesPanel;
|
|
14908
16012
|
exports.ScheduledWorkPanel = ScheduledWorkPanel;
|
|
14909
16013
|
exports.SessionTreePanel = SessionTreePanel;
|
|
16014
|
+
exports.defaultSelectedMissionTaskId = defaultSelectedMissionTaskId;
|
|
14910
16015
|
exports.deriveMissionWorkerActivityLabel = deriveMissionWorkerActivityLabel;
|
|
16016
|
+
exports.formatMissionTimestamp = formatMissionTimestamp;
|
|
14911
16017
|
exports.groupMissionTasksByBucket = groupMissionTasksByBucket;
|
|
14912
16018
|
exports.isTerminalMissionStatus = isTerminalMissionStatus;
|
|
16019
|
+
exports.mergeMissionEvents = mergeMissionEvents;
|
|
16020
|
+
exports.missionEventActorLabel = missionEventActorLabel;
|
|
16021
|
+
exports.missionEventCategory = missionEventCategory;
|
|
16022
|
+
exports.missionEventSummary = missionEventSummary;
|
|
16023
|
+
exports.missionEventTaskId = missionEventTaskId;
|
|
16024
|
+
exports.missionTaskBlocks = missionTaskBlocks;
|
|
14913
16025
|
exports.missionTaskBucket = missionTaskBucket;
|
|
16026
|
+
exports.missionTaskRailGroups = missionTaskRailGroups;
|
|
16027
|
+
exports.missionTaskStatusDotClass = missionTaskStatusDotClass;
|
|
16028
|
+
exports.missionTaskTitle = missionTaskTitle;
|
|
16029
|
+
exports.missionWorkerTaskCounts = missionWorkerTaskCounts;
|
|
14914
16030
|
exports.splitCitations = splitCitations;
|
|
16031
|
+
exports.stripMissionControlMarkup = stripMissionControlMarkup;
|
|
14915
16032
|
exports.useAgentChatAdapterContext = useAgentChatAdapterContext;
|
|
14916
16033
|
exports.useAgentChatRuntime = useAgentChatRuntime;
|
|
14917
16034
|
exports.useChatViewMode = useChatViewMode;
|
|
14918
16035
|
exports.useInboxUnreadCount = useInboxUnreadCount;
|
|
16036
|
+
exports.useMissionEvents = useMissionEvents;
|
|
14919
16037
|
//# sourceMappingURL=index.cjs.map
|
|
14920
16038
|
//# sourceMappingURL=index.cjs.map
|