@invergent/agent-chat-react 2.7.0 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +477 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +101 -2
- package/dist/index.d.ts +101 -2
- package/dist/index.js +478 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4922,6 +4922,74 @@ function AttachmentChip({
|
|
|
4922
4922
|
}
|
|
4923
4923
|
);
|
|
4924
4924
|
}
|
|
4925
|
+
function tokenizeInline(text) {
|
|
4926
|
+
const tokens = [];
|
|
4927
|
+
let buf = "";
|
|
4928
|
+
let i = 0;
|
|
4929
|
+
const flush = () => {
|
|
4930
|
+
if (buf) {
|
|
4931
|
+
tokens.push({ kind: "text", value: buf });
|
|
4932
|
+
buf = "";
|
|
4933
|
+
}
|
|
4934
|
+
};
|
|
4935
|
+
while (i < text.length) {
|
|
4936
|
+
const ch = text[i];
|
|
4937
|
+
if (ch === "`") {
|
|
4938
|
+
const end = text.indexOf("`", i + 1);
|
|
4939
|
+
if (end > i) {
|
|
4940
|
+
flush();
|
|
4941
|
+
tokens.push({ kind: "code", value: text.slice(i + 1, end) });
|
|
4942
|
+
i = end + 1;
|
|
4943
|
+
continue;
|
|
4944
|
+
}
|
|
4945
|
+
}
|
|
4946
|
+
if (ch === "*" && text[i + 1] === "*") {
|
|
4947
|
+
const end = text.indexOf("**", i + 2);
|
|
4948
|
+
if (end > i + 1) {
|
|
4949
|
+
flush();
|
|
4950
|
+
tokens.push({ kind: "strong", value: text.slice(i + 2, end) });
|
|
4951
|
+
i = end + 2;
|
|
4952
|
+
continue;
|
|
4953
|
+
}
|
|
4954
|
+
}
|
|
4955
|
+
if (ch === "*") {
|
|
4956
|
+
const end = text.indexOf("*", i + 1);
|
|
4957
|
+
if (end > i + 1) {
|
|
4958
|
+
flush();
|
|
4959
|
+
tokens.push({ kind: "em", value: text.slice(i + 1, end) });
|
|
4960
|
+
i = end + 1;
|
|
4961
|
+
continue;
|
|
4962
|
+
}
|
|
4963
|
+
}
|
|
4964
|
+
buf += ch;
|
|
4965
|
+
i += 1;
|
|
4966
|
+
}
|
|
4967
|
+
flush();
|
|
4968
|
+
return tokens;
|
|
4969
|
+
}
|
|
4970
|
+
function renderInlineMarkdown(text) {
|
|
4971
|
+
if (!text || !/[*`]/.test(text)) return text ?? null;
|
|
4972
|
+
const tokens = tokenizeInline(text);
|
|
4973
|
+
return tokens.map((tok, idx) => {
|
|
4974
|
+
switch (tok.kind) {
|
|
4975
|
+
case "strong":
|
|
4976
|
+
return /* @__PURE__ */ jsxRuntime.jsx("strong", { className: "font-semibold", children: tok.value }, idx);
|
|
4977
|
+
case "em":
|
|
4978
|
+
return /* @__PURE__ */ jsxRuntime.jsx("em", { children: tok.value }, idx);
|
|
4979
|
+
case "code":
|
|
4980
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4981
|
+
"code",
|
|
4982
|
+
{
|
|
4983
|
+
className: "rounded bg-muted px-1 py-0.5 font-mono text-[0.9em]",
|
|
4984
|
+
children: tok.value
|
|
4985
|
+
},
|
|
4986
|
+
idx
|
|
4987
|
+
);
|
|
4988
|
+
default:
|
|
4989
|
+
return /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: tok.value }, idx);
|
|
4990
|
+
}
|
|
4991
|
+
});
|
|
4992
|
+
}
|
|
4925
4993
|
|
|
4926
4994
|
// src/components/ui/command.tsx
|
|
4927
4995
|
init_utils();
|
|
@@ -6352,6 +6420,7 @@ function ChatComposerInner({
|
|
|
6352
6420
|
canShowBrowser = false,
|
|
6353
6421
|
canShowWorkspace = false,
|
|
6354
6422
|
deepResearchEnabled = false,
|
|
6423
|
+
researchEnabled = false,
|
|
6355
6424
|
codeAgentsEnabled = false,
|
|
6356
6425
|
viewMode = "simple",
|
|
6357
6426
|
onViewModeChange
|
|
@@ -6422,6 +6491,13 @@ function ChatComposerInner({
|
|
|
6422
6491
|
description: "Delegate a topic to the deep-research workflow"
|
|
6423
6492
|
});
|
|
6424
6493
|
}
|
|
6494
|
+
if (researchEnabled) {
|
|
6495
|
+
base.push({
|
|
6496
|
+
value: "/auto-research ",
|
|
6497
|
+
label: "/auto-research",
|
|
6498
|
+
description: "Launch an autonomous research mission (Arbor)"
|
|
6499
|
+
});
|
|
6500
|
+
}
|
|
6425
6501
|
if (codeAgentsEnabled) {
|
|
6426
6502
|
base.push(
|
|
6427
6503
|
{ value: "/code claude ", label: "/code claude", description: "Run Claude Code on the workspace (your plan)" },
|
|
@@ -6433,7 +6509,7 @@ function ChatComposerInner({
|
|
|
6433
6509
|
}
|
|
6434
6510
|
return base;
|
|
6435
6511
|
},
|
|
6436
|
-
[deepResearchEnabled, codeAgentsEnabled]
|
|
6512
|
+
[deepResearchEnabled, researchEnabled, codeAgentsEnabled]
|
|
6437
6513
|
);
|
|
6438
6514
|
const scheduledExamples = react.useMemo(
|
|
6439
6515
|
() => [
|
|
@@ -7971,6 +8047,16 @@ var ErrorMessage = react.memo(function ErrorMessage2({
|
|
|
7971
8047
|
const [detailOpen, setDetailOpen] = react.useState(false);
|
|
7972
8048
|
const [retryPending, setRetryPending] = react.useState(false);
|
|
7973
8049
|
const [retryError, setRetryError] = react.useState(null);
|
|
8050
|
+
if (errorInfo.insufficientCredits) {
|
|
8051
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8052
|
+
InsufficientCreditsCard,
|
|
8053
|
+
{
|
|
8054
|
+
detail: errorInfo.detail,
|
|
8055
|
+
onDismiss,
|
|
8056
|
+
className
|
|
8057
|
+
}
|
|
8058
|
+
);
|
|
8059
|
+
}
|
|
7974
8060
|
const showRetry = errorInfo.retryable && !!onRetry;
|
|
7975
8061
|
const handleRetry = async () => {
|
|
7976
8062
|
if (!onRetry) return;
|
|
@@ -8042,6 +8128,46 @@ var ErrorMessage = react.memo(function ErrorMessage2({
|
|
|
8042
8128
|
}
|
|
8043
8129
|
);
|
|
8044
8130
|
});
|
|
8131
|
+
function parseRequestedTokens(detail) {
|
|
8132
|
+
const m = detail.match(/["']?requested["']?\s*[:=]\s*(\d+)/);
|
|
8133
|
+
return m ? Number(m[1]) : null;
|
|
8134
|
+
}
|
|
8135
|
+
var InsufficientCreditsCard = react.memo(function InsufficientCreditsCard2({
|
|
8136
|
+
detail,
|
|
8137
|
+
onDismiss,
|
|
8138
|
+
className
|
|
8139
|
+
}) {
|
|
8140
|
+
const { onOpenBilling } = useAgentChatAdapterContext();
|
|
8141
|
+
const requested = parseRequestedTokens(detail);
|
|
8142
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8143
|
+
"div",
|
|
8144
|
+
{
|
|
8145
|
+
role: "alert",
|
|
8146
|
+
className: cn(
|
|
8147
|
+
"flex w-full gap-3 rounded-md border border-amber-500/30 bg-amber-500/5 p-4",
|
|
8148
|
+
className
|
|
8149
|
+
),
|
|
8150
|
+
children: [
|
|
8151
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCard, { className: "mt-0.5 size-5 shrink-0 text-amber-600 dark:text-amber-400" }),
|
|
8152
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-2", children: [
|
|
8153
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-semibold text-foreground", children: "You're out of credits" }),
|
|
8154
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
8155
|
+
"This run was blocked by the token-credit limit",
|
|
8156
|
+
requested ? ` (it needed ~${requested.toLocaleString()} tokens)` : "",
|
|
8157
|
+
". Buy additional credits or upgrade your plan to keep your agents running."
|
|
8158
|
+
] }),
|
|
8159
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2 pt-1", children: [
|
|
8160
|
+
onOpenBilling && /* @__PURE__ */ jsxRuntime.jsxs(Button, { size: "sm", onClick: onOpenBilling, children: [
|
|
8161
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCard, { className: "size-4" }),
|
|
8162
|
+
"Go to Billing"
|
|
8163
|
+
] }),
|
|
8164
|
+
onDismiss && /* @__PURE__ */ jsxRuntime.jsx(Button, { size: "sm", variant: "ghost", onClick: onDismiss, children: "Dismiss" })
|
|
8165
|
+
] })
|
|
8166
|
+
] })
|
|
8167
|
+
]
|
|
8168
|
+
}
|
|
8169
|
+
);
|
|
8170
|
+
});
|
|
8045
8171
|
init_utils();
|
|
8046
8172
|
var SKELETON_WIDTHS = [70, 85, 55, 90, 60, 78, 45, 82, 65, 72];
|
|
8047
8173
|
var PDF_WORKER_SRC = new URL(
|
|
@@ -9063,7 +9189,11 @@ function cancelledToolLabel(toolName) {
|
|
|
9063
9189
|
research_memory: "Research",
|
|
9064
9190
|
research_outline: "Research",
|
|
9065
9191
|
generate_image: "image generation",
|
|
9066
|
-
generate_video: "video generation"
|
|
9192
|
+
generate_video: "video generation",
|
|
9193
|
+
// Arbor research-mission tools (the /auto-research coordinator loop).
|
|
9194
|
+
idea_tree: "Idea tree",
|
|
9195
|
+
dispatch_experiments: "Dispatch experiments",
|
|
9196
|
+
merge_experiment: "Merge experiment"
|
|
9067
9197
|
};
|
|
9068
9198
|
if (map[toolName]) return map[toolName];
|
|
9069
9199
|
if (toolName.startsWith("mcp__")) return formatMcpToolLabel(toolName);
|
|
@@ -9240,7 +9370,7 @@ function NarrationEntry({
|
|
|
9240
9370
|
/* @__PURE__ */ jsxRuntime.jsx(TimelineSeparator, { style: { backgroundColor: "var(--color-border)" } }),
|
|
9241
9371
|
/* @__PURE__ */ jsxRuntime.jsx(TimelineIndicator, { className: "size-2 border-none bg-foreground/30" })
|
|
9242
9372
|
] }),
|
|
9243
|
-
/* @__PURE__ */ jsxRuntime.jsx(TimelineContent, { children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: line }) })
|
|
9373
|
+
/* @__PURE__ */ jsxRuntime.jsx(TimelineContent, { children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: renderInlineMarkdown(line) }) })
|
|
9244
9374
|
] });
|
|
9245
9375
|
}
|
|
9246
9376
|
function TextEntry({
|
|
@@ -9356,6 +9486,17 @@ function extractToolDetail(tc) {
|
|
|
9356
9486
|
const prompt = stringArg("prompt");
|
|
9357
9487
|
return prompt ? truncate3(prompt, 60) : null;
|
|
9358
9488
|
}
|
|
9489
|
+
case "idea_tree":
|
|
9490
|
+
return stringArg("action");
|
|
9491
|
+
case "dispatch_experiments": {
|
|
9492
|
+
const keys = args.node_keys;
|
|
9493
|
+
if (Array.isArray(keys) && keys.length > 0) {
|
|
9494
|
+
return truncate3(keys.map((k) => String(k)).join(", "), 40);
|
|
9495
|
+
}
|
|
9496
|
+
return stringArg("action");
|
|
9497
|
+
}
|
|
9498
|
+
case "merge_experiment":
|
|
9499
|
+
return stringArg("node_key") ?? stringArg("action");
|
|
9359
9500
|
case "memory":
|
|
9360
9501
|
return stringArg("action") ?? stringArg("key");
|
|
9361
9502
|
case "research_memory": {
|
|
@@ -9657,7 +9798,7 @@ function IterationGroup({
|
|
|
9657
9798
|
"aria-expanded": open,
|
|
9658
9799
|
className: "flex w-full items-center gap-2 rounded py-0.5 text-left text-sm hover:bg-muted/40",
|
|
9659
9800
|
children: [
|
|
9660
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex-1 truncate", labelTone), children: label }),
|
|
9801
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex-1 truncate", labelTone), children: renderInlineMarkdown(label) }),
|
|
9661
9802
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9662
9803
|
lucideReact.ChevronDown,
|
|
9663
9804
|
{
|
|
@@ -9784,7 +9925,7 @@ function SimpleAssistantGroup({
|
|
|
9784
9925
|
const narrationLine = action ? action.body.trim().toLowerCase() === "done" ? null : action.body : inferredNarration;
|
|
9785
9926
|
const askBody = hasUserFacingAskContent(message) ? cleaned : null;
|
|
9786
9927
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
9787
|
-
askBody ? /* @__PURE__ */ jsxRuntime.jsx(MessageResponse, { children: askBody }) : narrationLine ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground", children: narrationLine }) : null,
|
|
9928
|
+
askBody ? /* @__PURE__ */ jsxRuntime.jsx(MessageResponse, { children: askBody }) : narrationLine ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground", children: renderInlineMarkdown(narrationLine) }) : null,
|
|
9788
9929
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9789
9930
|
IterationGroup,
|
|
9790
9931
|
{
|
|
@@ -9946,6 +10087,7 @@ function ChatThread({
|
|
|
9946
10087
|
viewMode = "simple",
|
|
9947
10088
|
onViewModeChange,
|
|
9948
10089
|
deepResearchEnabled = false,
|
|
10090
|
+
researchEnabled = false,
|
|
9949
10091
|
codeAgentsEnabled = false,
|
|
9950
10092
|
researchSources = [],
|
|
9951
10093
|
hideTurnSummary = false,
|
|
@@ -10012,6 +10154,7 @@ function ChatThread({
|
|
|
10012
10154
|
viewMode,
|
|
10013
10155
|
onViewModeChange,
|
|
10014
10156
|
deepResearchEnabled,
|
|
10157
|
+
researchEnabled,
|
|
10015
10158
|
codeAgentsEnabled
|
|
10016
10159
|
}
|
|
10017
10160
|
),
|
|
@@ -10855,6 +10998,9 @@ var AGENT_CHAT_LISTENED_EVENTS = [
|
|
|
10855
10998
|
"iteration.summary",
|
|
10856
10999
|
"turn.summary"
|
|
10857
11000
|
];
|
|
11001
|
+
var AGENT_CHAT_LISTENED_EVENT_SET = new Set(
|
|
11002
|
+
AGENT_CHAT_LISTENED_EVENTS
|
|
11003
|
+
);
|
|
10858
11004
|
|
|
10859
11005
|
// src/runtime/reducer.ts
|
|
10860
11006
|
var EMPTY_TOKEN_USAGE = {
|
|
@@ -10877,6 +11023,7 @@ function createInitialAgentChatState(options = {}) {
|
|
|
10877
11023
|
sessionDone: false,
|
|
10878
11024
|
hadDeltas: false,
|
|
10879
11025
|
terminal: false,
|
|
11026
|
+
stopped: false,
|
|
10880
11027
|
workspaceRefreshKey: 0,
|
|
10881
11028
|
browser: null,
|
|
10882
11029
|
viewMode: options.viewMode ?? "simple",
|
|
@@ -10891,13 +11038,13 @@ function applyAgentChatEvent(state, event) {
|
|
|
10891
11038
|
sessionDone: state.sessionDone || event.type === "session.done"
|
|
10892
11039
|
};
|
|
10893
11040
|
nextState = applyRetryIndicator(nextState, event);
|
|
10894
|
-
if (state.
|
|
11041
|
+
if (state.stopped && isPostTerminalLiveEvent(event.type)) {
|
|
10895
11042
|
return nextState;
|
|
10896
11043
|
}
|
|
10897
11044
|
switch (event.type) {
|
|
10898
11045
|
case "user.message":
|
|
10899
11046
|
return withMessages(
|
|
10900
|
-
{ ...nextState, terminal: false, isRunning: true },
|
|
11047
|
+
{ ...nextState, terminal: false, stopped: false, isRunning: true },
|
|
10901
11048
|
applyUserMessage(nextState.messages, event.eventId, event.data)
|
|
10902
11049
|
);
|
|
10903
11050
|
case "skill.invoked":
|
|
@@ -11520,13 +11667,21 @@ function buildErrorInfo(event) {
|
|
|
11520
11667
|
if (event.type !== "session.fail" || typeof event.data.error_category !== "string") {
|
|
11521
11668
|
return void 0;
|
|
11522
11669
|
}
|
|
11670
|
+
const detail = stringValue2(event.data.error_detail) || stringValue2(event.data.error);
|
|
11671
|
+
const insufficientCredits = isInsufficientCreditsError(detail);
|
|
11523
11672
|
return {
|
|
11524
11673
|
category: event.data.error_category,
|
|
11525
|
-
title: stringValue2(event.data.error_title) || "The session failed due to an internal error.",
|
|
11526
|
-
detail
|
|
11527
|
-
|
|
11674
|
+
title: insufficientCredits ? "You're out of credits" : stringValue2(event.data.error_title) || "The session failed due to an internal error.",
|
|
11675
|
+
detail,
|
|
11676
|
+
// A credit shortfall is not a transient failure — retrying just hits
|
|
11677
|
+
// the same 402. The billing CTA replaces Retry.
|
|
11678
|
+
retryable: insufficientCredits ? false : Boolean(event.data.retryable),
|
|
11679
|
+
insufficientCredits
|
|
11528
11680
|
};
|
|
11529
11681
|
}
|
|
11682
|
+
function isInsufficientCreditsError(text) {
|
|
11683
|
+
return typeof text === "string" && text.includes("insufficient_credits");
|
|
11684
|
+
}
|
|
11530
11685
|
function applyExpertResult(messages, eventId, data) {
|
|
11531
11686
|
const match = findLatestConsultExpertCall(messages);
|
|
11532
11687
|
if (!match) return messages;
|
|
@@ -11926,6 +12081,15 @@ function readTurnMeta(data) {
|
|
|
11926
12081
|
}
|
|
11927
12082
|
|
|
11928
12083
|
// src/runtime/use-agent-chat-runtime.ts
|
|
12084
|
+
var RECONCILE_FIRST_DELAY = 4e3;
|
|
12085
|
+
var RECONCILE_FAST = 1500;
|
|
12086
|
+
var RECONCILE_ACTIVE = 4e3;
|
|
12087
|
+
var RECONCILE_MISSION_IDLE = 5e3;
|
|
12088
|
+
var RECONCILE_IDLE = 15e3;
|
|
12089
|
+
function applyRuntimeEvent(prev, event) {
|
|
12090
|
+
if (event.eventId > 0 && event.eventId <= prev.lastEventId) return prev;
|
|
12091
|
+
return applyAgentChatEvent(prev, event);
|
|
12092
|
+
}
|
|
11929
12093
|
var VIEW_MODE_KEY = "@invergent/agent-chat-react:viewMode";
|
|
11930
12094
|
var VIEW_MODE_EVENT = "@invergent/agent-chat-react:viewMode:change";
|
|
11931
12095
|
function readPersistedViewMode() {
|
|
@@ -11993,6 +12157,7 @@ function useAgentChatRuntime({
|
|
|
11993
12157
|
const stateRef = react.useRef(state);
|
|
11994
12158
|
const streamRef = react.useRef(null);
|
|
11995
12159
|
const reconnectTimerRef = react.useRef(null);
|
|
12160
|
+
const reconcileTimerRef = react.useRef(null);
|
|
11996
12161
|
const previousSessionIdRef = react.useRef(sessionId);
|
|
11997
12162
|
const sessionIdRef = react.useRef(sessionId);
|
|
11998
12163
|
react.useEffect(() => {
|
|
@@ -12025,7 +12190,7 @@ function useAgentChatRuntime({
|
|
|
12025
12190
|
const data = parseEventData(messageEvent.data);
|
|
12026
12191
|
const eventId = messageEvent.lastEventId ? Number(messageEvent.lastEventId) : 0;
|
|
12027
12192
|
setState(
|
|
12028
|
-
(prev) =>
|
|
12193
|
+
(prev) => applyRuntimeEvent(prev, {
|
|
12029
12194
|
type: eventType,
|
|
12030
12195
|
eventId,
|
|
12031
12196
|
data
|
|
@@ -12057,12 +12222,110 @@ function useAgentChatRuntime({
|
|
|
12057
12222
|
stateRef.current = {
|
|
12058
12223
|
...stateRef.current,
|
|
12059
12224
|
sessionDone: false,
|
|
12060
|
-
terminal: false
|
|
12225
|
+
terminal: false,
|
|
12226
|
+
stopped: false
|
|
12061
12227
|
};
|
|
12062
12228
|
openStream(targetSessionId, after);
|
|
12063
12229
|
},
|
|
12064
12230
|
[clearReconnectTimer, closeStream, openStream]
|
|
12065
12231
|
);
|
|
12232
|
+
const reviveStreamIfNeeded = react.useCallback(
|
|
12233
|
+
(targetSessionId) => {
|
|
12234
|
+
if (streamRef.current) return;
|
|
12235
|
+
if (reconnectTimerRef.current) return;
|
|
12236
|
+
stateRef.current = { ...stateRef.current, sessionDone: false };
|
|
12237
|
+
setState(
|
|
12238
|
+
(prev) => prev.sessionDone ? { ...prev, sessionDone: false } : prev
|
|
12239
|
+
);
|
|
12240
|
+
openStream(targetSessionId, stateRef.current.lastEventId);
|
|
12241
|
+
},
|
|
12242
|
+
[openStream]
|
|
12243
|
+
);
|
|
12244
|
+
const applyPolledEvents = react.useCallback((events) => {
|
|
12245
|
+
if (events.length === 0) return;
|
|
12246
|
+
setState((prev) => {
|
|
12247
|
+
let next = prev;
|
|
12248
|
+
for (const event of events) {
|
|
12249
|
+
if (!AGENT_CHAT_LISTENED_EVENT_SET.has(event.type)) continue;
|
|
12250
|
+
next = applyRuntimeEvent(next, {
|
|
12251
|
+
type: event.type,
|
|
12252
|
+
eventId: event.id,
|
|
12253
|
+
data: event.data ?? {}
|
|
12254
|
+
});
|
|
12255
|
+
}
|
|
12256
|
+
return next;
|
|
12257
|
+
});
|
|
12258
|
+
}, []);
|
|
12259
|
+
const reconcileTick = react.useCallback(async () => {
|
|
12260
|
+
const targetSessionId = sessionIdRef.current;
|
|
12261
|
+
if (!targetSessionId) return RECONCILE_IDLE;
|
|
12262
|
+
let appliedNew = false;
|
|
12263
|
+
if (adapter.pollEvents) {
|
|
12264
|
+
let cursor = stateRef.current.lastEventId;
|
|
12265
|
+
try {
|
|
12266
|
+
for (let page = 0; page < 5; page++) {
|
|
12267
|
+
const res = await adapter.pollEvents({
|
|
12268
|
+
sessionId: targetSessionId,
|
|
12269
|
+
after: cursor,
|
|
12270
|
+
limit: 200
|
|
12271
|
+
});
|
|
12272
|
+
if (sessionIdRef.current !== targetSessionId) return RECONCILE_IDLE;
|
|
12273
|
+
const events = res.events ?? [];
|
|
12274
|
+
if (events.length === 0) break;
|
|
12275
|
+
const fresh = events.filter((event) => event.id > cursor);
|
|
12276
|
+
const known = fresh.filter(
|
|
12277
|
+
(event) => AGENT_CHAT_LISTENED_EVENT_SET.has(event.type)
|
|
12278
|
+
);
|
|
12279
|
+
if (known.length > 0) {
|
|
12280
|
+
applyPolledEvents(known);
|
|
12281
|
+
appliedNew = true;
|
|
12282
|
+
}
|
|
12283
|
+
for (const event of events) cursor = Math.max(cursor, event.id);
|
|
12284
|
+
if (!res.hasMore) break;
|
|
12285
|
+
}
|
|
12286
|
+
} catch {
|
|
12287
|
+
}
|
|
12288
|
+
}
|
|
12289
|
+
let live = false;
|
|
12290
|
+
let isMission = false;
|
|
12291
|
+
let statusKnown = false;
|
|
12292
|
+
try {
|
|
12293
|
+
const session2 = await adapter.getSession({ sessionId: targetSessionId });
|
|
12294
|
+
if (sessionIdRef.current !== targetSessionId) return RECONCILE_IDLE;
|
|
12295
|
+
statusKnown = true;
|
|
12296
|
+
live = session2.status === "active";
|
|
12297
|
+
isMission = Boolean(
|
|
12298
|
+
session2.config?.active_mission_id
|
|
12299
|
+
);
|
|
12300
|
+
} catch {
|
|
12301
|
+
}
|
|
12302
|
+
if (live) reviveStreamIfNeeded(targetSessionId);
|
|
12303
|
+
if (appliedNew) return RECONCILE_FAST;
|
|
12304
|
+
if (live || !statusKnown) return RECONCILE_ACTIVE;
|
|
12305
|
+
return isMission || stateRef.current.isRunning ? RECONCILE_MISSION_IDLE : RECONCILE_IDLE;
|
|
12306
|
+
}, [adapter, applyPolledEvents, reviveStreamIfNeeded]);
|
|
12307
|
+
react.useEffect(() => {
|
|
12308
|
+
if (!sessionId) return;
|
|
12309
|
+
let cancelled = false;
|
|
12310
|
+
const schedule = (delay) => {
|
|
12311
|
+
if (cancelled) return;
|
|
12312
|
+
reconcileTimerRef.current = setTimeout(() => {
|
|
12313
|
+
if (cancelled) return;
|
|
12314
|
+
void reconcileTick().catch(() => RECONCILE_ACTIVE).then((next) => {
|
|
12315
|
+
if (cancelled) return;
|
|
12316
|
+
schedule(next);
|
|
12317
|
+
});
|
|
12318
|
+
}, delay);
|
|
12319
|
+
};
|
|
12320
|
+
schedule(RECONCILE_FIRST_DELAY);
|
|
12321
|
+
return () => {
|
|
12322
|
+
cancelled = true;
|
|
12323
|
+
if (reconcileTimerRef.current) {
|
|
12324
|
+
clearTimeout(reconcileTimerRef.current);
|
|
12325
|
+
reconcileTimerRef.current = null;
|
|
12326
|
+
}
|
|
12327
|
+
};
|
|
12328
|
+
}, [sessionId, reconcileTick]);
|
|
12066
12329
|
react.useEffect(() => {
|
|
12067
12330
|
const previousSessionId = previousSessionIdRef.current;
|
|
12068
12331
|
previousSessionIdRef.current = sessionId;
|
|
@@ -12187,6 +12450,10 @@ function useAgentChatRuntime({
|
|
|
12187
12450
|
return {
|
|
12188
12451
|
...prev,
|
|
12189
12452
|
terminal: true,
|
|
12453
|
+
// User-initiated stop: gate the aborted turn's late in-flight
|
|
12454
|
+
// events (a natural session.complete leaves this false so an
|
|
12455
|
+
// autonomous mission resume still streams).
|
|
12456
|
+
stopped: true,
|
|
12190
12457
|
isRunning: false,
|
|
12191
12458
|
messages
|
|
12192
12459
|
};
|
|
@@ -12269,6 +12536,7 @@ function useAgentChatRuntime({
|
|
|
12269
12536
|
setState((prev) => ({
|
|
12270
12537
|
...prev,
|
|
12271
12538
|
terminal: false,
|
|
12539
|
+
stopped: false,
|
|
12272
12540
|
retryIndicator: null,
|
|
12273
12541
|
isRunning: true
|
|
12274
12542
|
}));
|
|
@@ -12396,8 +12664,10 @@ function AgentChat({
|
|
|
12396
12664
|
disabled,
|
|
12397
12665
|
onComposerError,
|
|
12398
12666
|
deepResearchEnabled = false,
|
|
12667
|
+
researchEnabled = false,
|
|
12399
12668
|
codeAgentsEnabled = false,
|
|
12400
|
-
onOpenIntegrations
|
|
12669
|
+
onOpenIntegrations,
|
|
12670
|
+
onOpenBilling
|
|
12401
12671
|
}) {
|
|
12402
12672
|
const [workspacePath, setWorkspacePath] = react.useState(null);
|
|
12403
12673
|
const [mobileView, setMobileView] = react.useState("chat");
|
|
@@ -12456,7 +12726,8 @@ function AgentChat({
|
|
|
12456
12726
|
value: {
|
|
12457
12727
|
adapter,
|
|
12458
12728
|
sessionId,
|
|
12459
|
-
onFileSelect: handleFileSelect
|
|
12729
|
+
onFileSelect: handleFileSelect,
|
|
12730
|
+
onOpenBilling
|
|
12460
12731
|
},
|
|
12461
12732
|
children: /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12462
12733
|
"section",
|
|
@@ -12546,6 +12817,7 @@ function AgentChat({
|
|
|
12546
12817
|
viewMode: runtime.viewMode,
|
|
12547
12818
|
onViewModeChange: runtime.setViewMode,
|
|
12548
12819
|
deepResearchEnabled,
|
|
12820
|
+
researchEnabled,
|
|
12549
12821
|
codeAgentsEnabled,
|
|
12550
12822
|
researchSources: runtime.researchSources,
|
|
12551
12823
|
hideTurnSummary,
|
|
@@ -14222,7 +14494,7 @@ function ActivityRow({
|
|
|
14222
14494
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "shrink-0 text-xs text-foreground font-mono", children: missionEventActorLabel(event, feed.sessions) }),
|
|
14223
14495
|
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
|
|
14224
14496
|
] }),
|
|
14225
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "min-w-0 flex-1 truncate text-foreground/80", children: missionEventSummary(event) }) })
|
|
14497
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "min-w-0 flex-1 truncate text-foreground/80", children: renderInlineMarkdown(missionEventSummary(event)) }) })
|
|
14226
14498
|
] })
|
|
14227
14499
|
] });
|
|
14228
14500
|
}
|
|
@@ -14305,6 +14577,182 @@ function MissionMetadataTab({ mission }) {
|
|
|
14305
14577
|
] })
|
|
14306
14578
|
] });
|
|
14307
14579
|
}
|
|
14580
|
+
function compareNodes(a, b) {
|
|
14581
|
+
if (a.nodeKey === b.nodeKey) return 0;
|
|
14582
|
+
if (a.nodeKey === "ROOT") return -1;
|
|
14583
|
+
if (b.nodeKey === "ROOT") return 1;
|
|
14584
|
+
const pa = a.nodeKey.split(".").map((p) => Number.parseInt(p, 10));
|
|
14585
|
+
const pb = b.nodeKey.split(".").map((p) => Number.parseInt(p, 10));
|
|
14586
|
+
const n = Math.min(pa.length, pb.length);
|
|
14587
|
+
for (let i = 0; i < n; i += 1) {
|
|
14588
|
+
if (pa[i] !== pb[i]) return pa[i] - pb[i];
|
|
14589
|
+
}
|
|
14590
|
+
return pa.length - pb.length;
|
|
14591
|
+
}
|
|
14592
|
+
function statusToneClass(status) {
|
|
14593
|
+
switch (status) {
|
|
14594
|
+
case "merged":
|
|
14595
|
+
return "border-emerald-500/30 bg-emerald-500/10 text-emerald-700 dark:text-emerald-400";
|
|
14596
|
+
case "done":
|
|
14597
|
+
return "border-sky-500/30 bg-sky-500/10 text-sky-700 dark:text-sky-400";
|
|
14598
|
+
case "running":
|
|
14599
|
+
return "border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-400";
|
|
14600
|
+
case "failed":
|
|
14601
|
+
return "border-destructive/30 bg-destructive/10 text-destructive";
|
|
14602
|
+
case "pruned":
|
|
14603
|
+
return "border-border bg-muted/40 text-muted-foreground/70 line-through";
|
|
14604
|
+
default:
|
|
14605
|
+
return "border-border bg-muted/30 text-muted-foreground/80";
|
|
14606
|
+
}
|
|
14607
|
+
}
|
|
14608
|
+
function fmtScore(n) {
|
|
14609
|
+
if (n === null || n === void 0) return "\u2014";
|
|
14610
|
+
return n.toFixed(3).replace(/\.?0+$/, "") || "0";
|
|
14611
|
+
}
|
|
14612
|
+
function deltaLabel(score, ref, direction) {
|
|
14613
|
+
if (score === null || score === void 0 || ref === null || ref === void 0) {
|
|
14614
|
+
return null;
|
|
14615
|
+
}
|
|
14616
|
+
const raw = score - ref;
|
|
14617
|
+
const good = direction === "minimize" ? raw < 0 : raw > 0;
|
|
14618
|
+
const sign = raw > 0 ? "+" : raw < 0 ? "\u2212" : "\xB1";
|
|
14619
|
+
return { text: `${sign}${fmtScore(Math.abs(raw))}`, good };
|
|
14620
|
+
}
|
|
14621
|
+
function ScorePair({
|
|
14622
|
+
label,
|
|
14623
|
+
from,
|
|
14624
|
+
to,
|
|
14625
|
+
direction
|
|
14626
|
+
}) {
|
|
14627
|
+
const delta = deltaLabel(to, from, direction);
|
|
14628
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
14629
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-mono text-[10px] uppercase tracking-widest text-muted-foreground/60", children: label }),
|
|
14630
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-1.5 tabular-nums", children: [
|
|
14631
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/70", children: fmtScore(from) }),
|
|
14632
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/40", children: "\u2192" }),
|
|
14633
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg font-semibold text-foreground", children: fmtScore(to) }),
|
|
14634
|
+
delta ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
14635
|
+
"span",
|
|
14636
|
+
{
|
|
14637
|
+
className: delta.good ? "text-xs font-medium text-emerald-600 dark:text-emerald-400" : "text-xs font-medium text-muted-foreground/60",
|
|
14638
|
+
children: delta.text
|
|
14639
|
+
}
|
|
14640
|
+
) : null
|
|
14641
|
+
] })
|
|
14642
|
+
] });
|
|
14643
|
+
}
|
|
14644
|
+
function RunHeader({ run }) {
|
|
14645
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4 rounded-md border bg-card/40 p-4", children: [
|
|
14646
|
+
run.objective ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-foreground/90", children: run.objective }) : null,
|
|
14647
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
14648
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14649
|
+
ScorePair,
|
|
14650
|
+
{
|
|
14651
|
+
label: "Dev (working)",
|
|
14652
|
+
from: run.baselineScore,
|
|
14653
|
+
to: run.trunkScore ?? run.baselineScore,
|
|
14654
|
+
direction: run.metricDirection
|
|
14655
|
+
}
|
|
14656
|
+
),
|
|
14657
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14658
|
+
ScorePair,
|
|
14659
|
+
{
|
|
14660
|
+
label: "Held-out test (authoritative)",
|
|
14661
|
+
from: run.testBaselineScore,
|
|
14662
|
+
to: run.testTrunkScore ?? run.testBaselineScore,
|
|
14663
|
+
direction: run.metricDirection
|
|
14664
|
+
}
|
|
14665
|
+
)
|
|
14666
|
+
] }),
|
|
14667
|
+
/* @__PURE__ */ jsxRuntime.jsxs("dl", { className: "grid grid-cols-[max-content_1fr] gap-x-4 gap-y-1 text-[11px]", children: [
|
|
14668
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-muted-foreground/60", children: "Status" }),
|
|
14669
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { className: "text-foreground/80", children: run.status }),
|
|
14670
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-muted-foreground/60", children: "Repo" }),
|
|
14671
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { children: /* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-[11px]", children: run.repoPath }) }),
|
|
14672
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-muted-foreground/60", children: "Trunk" }),
|
|
14673
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { children: /* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-[11px]", children: run.trunkBranch }) }),
|
|
14674
|
+
run.evalCmd ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
14675
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-muted-foreground/60", children: "Dev eval" }),
|
|
14676
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { children: /* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-[11px]", children: run.evalCmd }) })
|
|
14677
|
+
] }) : null,
|
|
14678
|
+
run.evalCmdTest ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
14679
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-muted-foreground/60", children: "Held-out eval" }),
|
|
14680
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { children: /* @__PURE__ */ jsxRuntime.jsx("code", { className: "text-[11px]", children: run.evalCmdTest }) })
|
|
14681
|
+
] }) : null
|
|
14682
|
+
] })
|
|
14683
|
+
] });
|
|
14684
|
+
}
|
|
14685
|
+
function IdeaRow({
|
|
14686
|
+
node,
|
|
14687
|
+
baseline,
|
|
14688
|
+
direction
|
|
14689
|
+
}) {
|
|
14690
|
+
const indent = node.nodeKey === "ROOT" ? 0 : node.depth;
|
|
14691
|
+
const delta = deltaLabel(node.score, baseline, direction);
|
|
14692
|
+
const headline = (node.hypothesis || "").split("\n")[0];
|
|
14693
|
+
const insight = node.insight ? node.insight.split("\n").slice(-1)[0] : null;
|
|
14694
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14695
|
+
"li",
|
|
14696
|
+
{
|
|
14697
|
+
className: "flex flex-col gap-0.5 border-b border-border/40 py-2 last:border-b-0",
|
|
14698
|
+
style: { paddingLeft: `${indent * 16}px` },
|
|
14699
|
+
children: [
|
|
14700
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
14701
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { className: "shrink-0 text-[11px] text-muted-foreground/60", children: node.nodeKey }),
|
|
14702
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14703
|
+
"span",
|
|
14704
|
+
{
|
|
14705
|
+
className: `shrink-0 rounded border px-1.5 py-0.5 font-mono text-[9px] uppercase tracking-wider ${statusToneClass(node.status)}`,
|
|
14706
|
+
children: node.status
|
|
14707
|
+
}
|
|
14708
|
+
),
|
|
14709
|
+
node.score !== null && node.score !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "shrink-0 tabular-nums text-xs font-medium text-foreground/90", children: [
|
|
14710
|
+
fmtScore(node.score),
|
|
14711
|
+
delta ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14712
|
+
"span",
|
|
14713
|
+
{
|
|
14714
|
+
className: delta.good ? " text-emerald-600 dark:text-emerald-400" : " text-muted-foreground/50",
|
|
14715
|
+
children: [
|
|
14716
|
+
" ",
|
|
14717
|
+
delta.text
|
|
14718
|
+
]
|
|
14719
|
+
}
|
|
14720
|
+
) : null
|
|
14721
|
+
] }) : null,
|
|
14722
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs text-foreground/80", title: headline, children: headline })
|
|
14723
|
+
] }),
|
|
14724
|
+
insight ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate pl-[calc(1.5rem)] text-[11px] text-muted-foreground/60", title: node.insight ?? void 0, children: insight }) : null
|
|
14725
|
+
]
|
|
14726
|
+
}
|
|
14727
|
+
);
|
|
14728
|
+
}
|
|
14729
|
+
function MissionResearchTab({ research }) {
|
|
14730
|
+
const sorted = react.useMemo(
|
|
14731
|
+
() => [...research.nodes].sort(compareNodes),
|
|
14732
|
+
[research.nodes]
|
|
14733
|
+
);
|
|
14734
|
+
const { run } = research;
|
|
14735
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
14736
|
+
/* @__PURE__ */ jsxRuntime.jsx(RunHeader, { run }),
|
|
14737
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { children: [
|
|
14738
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2 font-mono text-[10px] uppercase tracking-widest text-muted-foreground/70", children: [
|
|
14739
|
+
"Idea Tree \xB7 ",
|
|
14740
|
+
sorted.length,
|
|
14741
|
+
" node",
|
|
14742
|
+
sorted.length === 1 ? "" : "s"
|
|
14743
|
+
] }),
|
|
14744
|
+
sorted.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground/60", children: "No hypotheses yet." }) : /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "rounded-md border", children: sorted.map((n) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
14745
|
+
IdeaRow,
|
|
14746
|
+
{
|
|
14747
|
+
node: n,
|
|
14748
|
+
baseline: run.baselineScore,
|
|
14749
|
+
direction: run.metricDirection
|
|
14750
|
+
},
|
|
14751
|
+
n.nodeKey
|
|
14752
|
+
)) })
|
|
14753
|
+
] })
|
|
14754
|
+
] });
|
|
14755
|
+
}
|
|
14308
14756
|
var TASK_STATUS_BADGE_CLASS = {
|
|
14309
14757
|
running: "border-primary/30 bg-primary/10 text-primary",
|
|
14310
14758
|
blocked: "border-amber-500/30 bg-amber-500/10 text-amber-600",
|
|
@@ -14510,7 +14958,7 @@ function TaskDetail({
|
|
|
14510
14958
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-16 shrink-0 font-mono text-[10px] text-muted-foreground/60", children: formatMissionTimestamp(e.createdAt) }),
|
|
14511
14959
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "", children: [
|
|
14512
14960
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "shrink-0 font-mono uppercase text-muted-foreground", children: missionEventCategory(e.type) }),
|
|
14513
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "min-w-0 flex-1 text-foreground/80", children: missionEventSummary(e) })
|
|
14961
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "min-w-0 flex-1 text-foreground/80", children: renderInlineMarkdown(missionEventSummary(e)) })
|
|
14514
14962
|
] })
|
|
14515
14963
|
] }, e.id)) })
|
|
14516
14964
|
] }) : null,
|
|
@@ -14623,7 +15071,7 @@ function OutcomeCard({ outcome }) {
|
|
|
14623
15071
|
),
|
|
14624
15072
|
outcome.timestamp ? /* @__PURE__ */ jsxRuntime.jsx(CardAction, { className: "font-mono text-[10px] text-muted-foreground/60", children: formatMissionTimestamp(outcome.timestamp) }) : null
|
|
14625
15073
|
] }),
|
|
14626
|
-
/* @__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 }) })
|
|
15074
|
+
/* @__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: renderInlineMarkdown(outcome.text) }) })
|
|
14627
15075
|
]
|
|
14628
15076
|
}
|
|
14629
15077
|
);
|
|
@@ -14793,6 +15241,7 @@ var INITIAL_STATE = {
|
|
|
14793
15241
|
mission: null,
|
|
14794
15242
|
tasks: [],
|
|
14795
15243
|
workers: [],
|
|
15244
|
+
research: null,
|
|
14796
15245
|
loading: true,
|
|
14797
15246
|
error: null
|
|
14798
15247
|
};
|
|
@@ -14835,16 +15284,19 @@ function MissionDashboard({
|
|
|
14835
15284
|
}, []);
|
|
14836
15285
|
const refresh = react.useCallback(async () => {
|
|
14837
15286
|
try {
|
|
14838
|
-
const
|
|
15287
|
+
const researchFn = adapter.getMissionResearch;
|
|
15288
|
+
const [mission2, tasksResp, workersResp, research] = await Promise.all([
|
|
14839
15289
|
api.getMission({ missionId }),
|
|
14840
15290
|
api.getMissionTasks({ missionId }),
|
|
14841
|
-
api.getMissionWorkers({ missionId })
|
|
15291
|
+
api.getMissionWorkers({ missionId }),
|
|
15292
|
+
researchFn ? researchFn({ missionId }).catch(() => null) : Promise.resolve(null)
|
|
14842
15293
|
]);
|
|
14843
15294
|
if (!isMounted.current) return;
|
|
14844
15295
|
setState({
|
|
14845
15296
|
mission: mission2,
|
|
14846
15297
|
tasks: tasksResp.tasks,
|
|
14847
15298
|
workers: workersResp.workers,
|
|
15299
|
+
research,
|
|
14848
15300
|
loading: false,
|
|
14849
15301
|
error: null
|
|
14850
15302
|
});
|
|
@@ -14856,7 +15308,7 @@ function MissionDashboard({
|
|
|
14856
15308
|
error: err instanceof Error ? err.message : String(err)
|
|
14857
15309
|
}));
|
|
14858
15310
|
}
|
|
14859
|
-
}, [api, missionId]);
|
|
15311
|
+
}, [adapter, api, missionId]);
|
|
14860
15312
|
react.useEffect(() => {
|
|
14861
15313
|
void refresh();
|
|
14862
15314
|
}, [refresh]);
|
|
@@ -15055,6 +15507,10 @@ function MissionDashboard({
|
|
|
15055
15507
|
className: "mt-5 flex flex-1 flex-col overflow-hidden sm:mt-6",
|
|
15056
15508
|
children: [
|
|
15057
15509
|
/* @__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: [
|
|
15510
|
+
state.research ? /* @__PURE__ */ jsxRuntime.jsxs(TabsTrigger, { value: "research", children: [
|
|
15511
|
+
"Research",
|
|
15512
|
+
/* @__PURE__ */ jsxRuntime.jsx(CountBadge, { n: state.research.nodes.length })
|
|
15513
|
+
] }) : null,
|
|
15058
15514
|
/* @__PURE__ */ jsxRuntime.jsxs(TabsTrigger, { value: "tasks", children: [
|
|
15059
15515
|
"Tasks",
|
|
15060
15516
|
/* @__PURE__ */ jsxRuntime.jsx(CountBadge, { n: state.tasks.length })
|
|
@@ -15070,6 +15526,7 @@ function MissionDashboard({
|
|
|
15070
15526
|
/* @__PURE__ */ jsxRuntime.jsx(TabsTrigger, { value: "metadata", children: "Metadata" })
|
|
15071
15527
|
] }) }),
|
|
15072
15528
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-y-auto bg-background px-5 py-4 sm:px-6", children: [
|
|
15529
|
+
state.research ? /* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: "research", className: "mt-0", children: /* @__PURE__ */ jsxRuntime.jsx(MissionResearchTab, { research: state.research }) }) : null,
|
|
15073
15530
|
/* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: "tasks", className: "mt-0 h-full", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
15074
15531
|
MissionTasksTab,
|
|
15075
15532
|
{
|