@agimon-ai/po-team 0.0.0-alpha.2 → 0.0.0-alpha.21
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/LICENSE +166 -5
- package/README.md +11 -12
- package/dist/{agentDiscovery-Whwzc4dP.cjs → agentDiscovery-DTTlM_LT.cjs} +246 -350
- package/dist/agentDiscovery-DTTlM_LT.cjs.map +1 -0
- package/dist/{agentDiscovery-ZQlFkKvB.mjs → agentDiscovery-ZNG8iZXV.mjs} +210 -279
- package/dist/agentDiscovery-ZNG8iZXV.mjs.map +1 -0
- package/dist/apiContracts.cjs +10 -3
- package/dist/apiContracts.cjs.map +1 -1
- package/dist/apiContracts.d.mts.map +1 -1
- package/dist/apiContracts.mjs +10 -3
- package/dist/apiContracts.mjs.map +1 -1
- package/dist/{externalProcessIpc-ojE0pvw0.cjs → atomicJson-DRT03Ql5.cjs} +155 -21
- package/dist/atomicJson-DRT03Ql5.cjs.map +1 -0
- package/dist/{externalProcessIpc-C-15lJrB.mjs → atomicJson-VVM1iAPu.mjs} +140 -12
- package/dist/atomicJson-VVM1iAPu.mjs.map +1 -0
- package/dist/{capabilityCeiling-CF7kAS18.mjs → capabilityCeiling-BaHT9v9S.mjs} +3 -3
- package/dist/capabilityCeiling-BaHT9v9S.mjs.map +1 -0
- package/dist/{capabilityCeiling-C-Y7H8oC.cjs → capabilityCeiling-CO3ZjYmY.cjs} +3 -3
- package/dist/capabilityCeiling-CO3ZjYmY.cjs.map +1 -0
- package/dist/capabilityCeiling.cjs +2 -2
- package/dist/capabilityCeiling.d.mts +2 -2
- package/dist/capabilityCeiling.mjs +2 -2
- package/dist/delegation.cjs +1 -1
- package/dist/delegation.cjs.map +1 -1
- package/dist/delegation.d.mts +1 -1
- package/dist/delegation.mjs +1 -1
- package/dist/delegation.mjs.map +1 -1
- package/dist/delegationApi.cjs +30 -30
- package/dist/delegationApi.d.mts +2 -2
- package/dist/delegationApi.mjs +1 -2
- package/dist/env.cjs +1 -1
- package/dist/env.d.mts +1 -1
- package/dist/env.mjs +1 -2
- package/dist/{environment-DrqhrxG_.mjs → environment-BtvJI2S-.mjs} +3 -3
- package/dist/environment-BtvJI2S-.mjs.map +1 -0
- package/dist/{environment-ma5oQ7uM.d.mts → environment-Bz1OlWIT.d.mts} +2 -2
- package/dist/{environment-ma5oQ7uM.d.mts.map → environment-Bz1OlWIT.d.mts.map} +1 -1
- package/dist/{environment-CaCW3SgT.cjs → environment-Cqs7vHJL.cjs} +3 -3
- package/dist/environment-Cqs7vHJL.cjs.map +1 -0
- package/dist/extensions/native.mjs +34 -12
- package/dist/extensions/native.mjs.map +1 -1
- package/dist/extensions/server.cjs +990 -786
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.d.mts +2 -2
- package/dist/extensions/server.d.mts.map +1 -1
- package/dist/extensions/server.mjs +975 -772
- package/dist/extensions/server.mjs.map +1 -1
- package/dist/extensions/web.mjs +994 -807
- package/dist/extensions/web.mjs.map +1 -1
- package/dist/fablePlan.cjs +3 -3
- package/dist/fablePlan.d.mts +2 -2
- package/dist/fablePlan.mjs +1 -2
- package/dist/{fablePlanApi-CZ3uUcMi.d.mts → fablePlanApi-BTNKjLni.d.mts} +6 -6
- package/dist/{fablePlanApi-CZ3uUcMi.d.mts.map → fablePlanApi-BTNKjLni.d.mts.map} +1 -1
- package/dist/{fablePlanApi-wBu9bRXU.cjs → fablePlanApi-BhI4jnDP.cjs} +12 -12
- package/dist/fablePlanApi-BhI4jnDP.cjs.map +1 -0
- package/dist/{fablePlanApi-BsHhgVFV.mjs → fablePlanApi-DuMg43Hu.mjs} +5 -5
- package/dist/fablePlanApi-DuMg43Hu.mjs.map +1 -0
- package/dist/fablePlanApi.cjs +3 -3
- package/dist/fablePlanApi.d.mts +2 -2
- package/dist/fablePlanApi.mjs +1 -2
- package/dist/index.cjs +17 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +5 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +15 -5
- package/dist/index.mjs.map +1 -1
- package/dist/rolldown-runtime-VH7oDXx4.cjs +28 -0
- package/dist/runs/background/cliRunnerEntry.cjs +26 -25
- package/dist/runs/background/cliRunnerEntry.cjs.map +1 -1
- package/dist/runs/background/cliRunnerEntry.mjs +14 -14
- package/dist/runs/background/cliRunnerEntry.mjs.map +1 -1
- package/dist/runtimeSubagentPolicy.cjs +3 -3
- package/dist/runtimeSubagentPolicy.d.mts +2 -2
- package/dist/runtimeSubagentPolicy.mjs +1 -2
- package/dist/runtimeSubagentTool.cjs +7 -2
- package/dist/runtimeSubagentTool.d.mts +1 -1
- package/dist/runtimeSubagentTool.mjs +1 -2
- package/dist/{subagentPolicy-ALJam4GN.d.mts → subagentPolicy-BE-OZoa-.d.mts} +6 -6
- package/dist/subagentPolicy-BE-OZoa-.d.mts.map +1 -0
- package/dist/{subagentPolicy-DQRyKDH-.cjs → subagentPolicy-DIpaKHO8.cjs} +8 -8
- package/dist/subagentPolicy-DIpaKHO8.cjs.map +1 -0
- package/dist/{subagentPolicy-DxjsKeyj.mjs → subagentPolicy-LfcXuqO5.mjs} +5 -5
- package/dist/subagentPolicy-LfcXuqO5.mjs.map +1 -0
- package/dist/subagentPolicy.cjs +3 -3
- package/dist/subagentPolicy.d.mts +2 -2
- package/dist/subagentPolicy.mjs +1 -2
- package/dist/{subagentTool-Ca2zQXKw.cjs → subagentTool-BueNPGHo.cjs} +5 -16
- package/dist/subagentTool-BueNPGHo.cjs.map +1 -0
- package/dist/{subagentTool-BTssGLw8.d.mts → subagentTool-UdB3s6Mn.d.mts} +2 -11
- package/dist/subagentTool-UdB3s6Mn.d.mts.map +1 -0
- package/dist/{subagentTool-WOYrjxgT.mjs → subagentTool-a2oh2v5B.mjs} +5 -16
- package/dist/subagentTool-a2oh2v5B.mjs.map +1 -0
- package/dist/subagentTool.cjs +7 -2
- package/dist/subagentTool.d.mts +1 -1
- package/dist/subagentTool.mjs +1 -2
- package/dist/teamSnapshot.d.mts +1 -0
- package/dist/teamSnapshot.d.mts.map +1 -1
- package/dist/teamSnapshot.mjs +1 -2
- package/package.json +25 -24
- package/dist/agentDiscovery-Whwzc4dP.cjs.map +0 -1
- package/dist/agentDiscovery-ZQlFkKvB.mjs.map +0 -1
- package/dist/atomicJson-D0346bt5.cjs +0 -178
- package/dist/atomicJson-D0346bt5.cjs.map +0 -1
- package/dist/atomicJson-D2t0CDh9.mjs +0 -137
- package/dist/atomicJson-D2t0CDh9.mjs.map +0 -1
- package/dist/capabilityCeiling-C-Y7H8oC.cjs.map +0 -1
- package/dist/capabilityCeiling-CF7kAS18.mjs.map +0 -1
- package/dist/environment-CaCW3SgT.cjs.map +0 -1
- package/dist/environment-DrqhrxG_.mjs.map +0 -1
- package/dist/externalProcessIpc-C-15lJrB.mjs.map +0 -1
- package/dist/externalProcessIpc-ojE0pvw0.cjs.map +0 -1
- package/dist/fablePlanApi-BsHhgVFV.mjs.map +0 -1
- package/dist/fablePlanApi-wBu9bRXU.cjs.map +0 -1
- package/dist/subagentPolicy-ALJam4GN.d.mts.map +0 -1
- package/dist/subagentPolicy-DQRyKDH-.cjs.map +0 -1
- package/dist/subagentPolicy-DxjsKeyj.mjs.map +0 -1
- package/dist/subagentTool-BTssGLw8.d.mts.map +0 -1
- package/dist/subagentTool-Ca2zQXKw.cjs.map +0 -1
- package/dist/subagentTool-WOYrjxgT.mjs.map +0 -1
package/dist/extensions/web.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineActivityGroup, defineChannelFile, defineContextAction, defineFill, defineLeaderBinding, defineSessionStore, defineSlot, defineSlotFile, defineToolRenderer, defineWebPlugin, pluginApiUrl, sessionApiAddress } from "@agimon-ai/po-core/web";
|
|
2
|
-
import { ArrowRightIcon, Badge, Button,
|
|
2
|
+
import { AgentAvatar, ArrowRightIcon, Badge, Button, ChevronDownIcon, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, Input, KebabIcon, MessageItem, MessageItemBody, MessageItemHeader, MessageItemStatus, Panel, STATUS_EDGE, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, SendIcon, Sheet, SheetBody, SheetContent, SheetHeader, SheetTitle, StatusBadge, Textarea, UsersIcon, cn, toolTone } from "@agimon-ai/po-web-components";
|
|
3
3
|
import { useStore } from "@tanstack/react-store";
|
|
4
|
-
import { useEffect, useState } from "react";
|
|
4
|
+
import { useEffect, useId, useRef, useState } from "react";
|
|
5
5
|
import { sealedTransport } from "@agimon-ai/po-web-security/browser";
|
|
6
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
//#region src/types/webSubagents.ts
|
|
@@ -124,40 +124,6 @@ function closeCatalog(sessionId) {
|
|
|
124
124
|
launch: void 0
|
|
125
125
|
}));
|
|
126
126
|
}
|
|
127
|
-
function setCatalogFilter(sessionId, filter) {
|
|
128
|
-
catalog.update(sessionId, (current) => ({
|
|
129
|
-
...current,
|
|
130
|
-
filter
|
|
131
|
-
}));
|
|
132
|
-
}
|
|
133
|
-
function selectAgent(sessionId, name) {
|
|
134
|
-
catalog.update(sessionId, (current) => ({
|
|
135
|
-
...current,
|
|
136
|
-
selected: name
|
|
137
|
-
}));
|
|
138
|
-
}
|
|
139
|
-
function toggleInspect(sessionId, name) {
|
|
140
|
-
catalog.update(sessionId, (current) => ({
|
|
141
|
-
...current,
|
|
142
|
-
inspected: current.inspected === name ? void 0 : name
|
|
143
|
-
}));
|
|
144
|
-
}
|
|
145
|
-
function openLaunch(sessionId, agent, fork) {
|
|
146
|
-
catalog.update(sessionId, (current) => ({
|
|
147
|
-
...current,
|
|
148
|
-
selected: agent,
|
|
149
|
-
launch: {
|
|
150
|
-
agent,
|
|
151
|
-
fork
|
|
152
|
-
}
|
|
153
|
-
}));
|
|
154
|
-
}
|
|
155
|
-
function closeLaunch(sessionId) {
|
|
156
|
-
catalog.update(sessionId, (current) => ({
|
|
157
|
-
...current,
|
|
158
|
-
launch: void 0
|
|
159
|
-
}));
|
|
160
|
-
}
|
|
161
127
|
/** Each drawer opening owns one request and cancels it when the drawer leaves. */
|
|
162
128
|
function loadCatalog(sessionId) {
|
|
163
129
|
const controller = new AbortController();
|
|
@@ -238,18 +204,26 @@ function abbreviateCwd(cwd) {
|
|
|
238
204
|
if (!match) return cwd;
|
|
239
205
|
return `~${cwd.slice(match[0].length)}`;
|
|
240
206
|
}
|
|
241
|
-
/**
|
|
242
|
-
* What to call a run on screen.
|
|
243
|
-
*
|
|
244
|
-
* Prefers the generated identity, because a fan-out of one agent otherwise
|
|
245
|
-
* renders as N rows reading the same word. Falls back to the agent name for a
|
|
246
|
-
* run projected before identities existed. Duplicated rather than imported
|
|
247
|
-
* from `services/agentIdentity`, which reaches for `node:fs` and so cannot be
|
|
248
|
-
* pulled into the browser bundle; that module owns minting, this owns display.
|
|
249
|
-
*/
|
|
207
|
+
/** What to call a run on screen: the identity's first name, else the agent name. Never a run id. */
|
|
250
208
|
function agentRunLabel(run) {
|
|
251
|
-
|
|
252
|
-
|
|
209
|
+
return agentDisplay(run).name;
|
|
210
|
+
}
|
|
211
|
+
function capitalize(word) {
|
|
212
|
+
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
213
|
+
}
|
|
214
|
+
/** `faris-c-6` reads "Faris"; a run without an identity reads as its agent name. */
|
|
215
|
+
function agentDisplay(run) {
|
|
216
|
+
const first = run.identity?.split("-")[0];
|
|
217
|
+
if (!run.identity || !first) return {
|
|
218
|
+
name: run.agent,
|
|
219
|
+
role: "",
|
|
220
|
+
seed: run.agent
|
|
221
|
+
};
|
|
222
|
+
return {
|
|
223
|
+
name: capitalize(first),
|
|
224
|
+
role: run.agent,
|
|
225
|
+
seed: run.identity
|
|
226
|
+
};
|
|
253
227
|
}
|
|
254
228
|
//#endregion
|
|
255
229
|
//#region src/extensions/workspaces/sessions/(frontend)/_lib/runActionsSlot.ts
|
|
@@ -376,7 +350,6 @@ const subagentRunsChannel = subagents.channel({
|
|
|
376
350
|
});
|
|
377
351
|
//#endregion
|
|
378
352
|
//#region src/extensions/workspaces/sessions/(frontend)/_lib/launchCommand.ts
|
|
379
|
-
const META_TOOL_LIMIT = 3;
|
|
380
353
|
/** Rows whose name, source, package, description or a tool contains the filter, case-insensitively. */
|
|
381
354
|
function filterCatalog(agents, filter) {
|
|
382
355
|
const needle = filter.trim().toLowerCase();
|
|
@@ -389,28 +362,6 @@ function filterCatalog(agents, filter) {
|
|
|
389
362
|
...agent.tools
|
|
390
363
|
].some((field) => field.toLowerCase().includes(needle)));
|
|
391
364
|
}
|
|
392
|
-
const SECTION_LABEL = {
|
|
393
|
-
project: "PROJECT",
|
|
394
|
-
user: "USER",
|
|
395
|
-
plugin: "PACKAGES"
|
|
396
|
-
};
|
|
397
|
-
/** The catalog's sections, nearest source first, keeping the payload's order inside each; empty ones are left out. */
|
|
398
|
-
function groupCatalog(agents) {
|
|
399
|
-
const sections = [];
|
|
400
|
-
for (const source of [
|
|
401
|
-
"project",
|
|
402
|
-
"user",
|
|
403
|
-
"plugin"
|
|
404
|
-
]) {
|
|
405
|
-
const members = agents.filter((agent) => agent.source === source);
|
|
406
|
-
if (members.length > 0) sections.push({
|
|
407
|
-
source,
|
|
408
|
-
label: SECTION_LABEL[source],
|
|
409
|
-
agents: members
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
return sections;
|
|
413
|
-
}
|
|
414
365
|
/** What the picker offers: the agent's own model and fallbacks first, then the team's, without repeats. */
|
|
415
366
|
function modelChoices(agent, models) {
|
|
416
367
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -426,255 +377,440 @@ function modelChoices(agent, models) {
|
|
|
426
377
|
}
|
|
427
378
|
return choices;
|
|
428
379
|
}
|
|
429
|
-
/** The row's one-liner: what tools it may use, how many skills, and how it starts. */
|
|
430
|
-
function agentMeta(agent) {
|
|
431
|
-
return `${agent.tools.length === 0 ? "all tools" : `tools ${agent.tools.slice(0, META_TOOL_LIMIT).join(", ")}${agent.tools.length > META_TOOL_LIMIT ? ` +${agent.tools.length - META_TOOL_LIMIT}` : ""}`}${agent.skills.length > 0 ? ` · ${agent.skills.length} skill${agent.skills.length === 1 ? "" : "s"}` : ""} · ${agent.defaultContext === "fork" ? "forks the session" : "fresh context"}`;
|
|
432
|
-
}
|
|
433
380
|
//#endregion
|
|
434
|
-
//#region src/extensions/workspaces/sessions/(frontend)/_components/
|
|
435
|
-
const
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
function
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
[
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
children: [/* @__PURE__ */ jsx("dt", {
|
|
454
|
-
className: "w-16 shrink-0 text-doom-dim",
|
|
455
|
-
children: label
|
|
456
|
-
}), /* @__PURE__ */ jsx("dd", {
|
|
457
|
-
className: "min-w-0 break-words text-doom-dim",
|
|
458
|
-
children: value
|
|
459
|
-
})]
|
|
460
|
-
}, label))
|
|
461
|
-
});
|
|
462
|
-
}
|
|
463
|
-
function AgentRow({ agent, selected, inspected, onSelect, onLaunch, onInspect }) {
|
|
464
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
465
|
-
role: "option",
|
|
466
|
-
"aria-selected": selected,
|
|
467
|
-
tabIndex: -1,
|
|
468
|
-
"data-testid": `catalog-agent-${agent.name}`,
|
|
469
|
-
"data-selected": selected,
|
|
470
|
-
onClick: onSelect,
|
|
471
|
-
onDoubleClick: () => onLaunch(false),
|
|
472
|
-
className: `flex cursor-pointer flex-col gap-1 border-l-2 px-4 py-2 ${selected ? "border-doom-blue bg-doom-panel" : "border-transparent hover:bg-doom-panel/60"}`,
|
|
473
|
-
children: [
|
|
474
|
-
/* @__PURE__ */ jsxs("div", {
|
|
475
|
-
className: "flex min-w-0 items-center gap-2",
|
|
476
|
-
children: [
|
|
477
|
-
/* @__PURE__ */ jsx("span", {
|
|
478
|
-
className: "truncate text-base font-semibold text-doom-hi",
|
|
479
|
-
children: agent.name
|
|
480
|
-
}),
|
|
481
|
-
/* @__PURE__ */ jsx(Badge, {
|
|
482
|
-
size: "xs",
|
|
483
|
-
className: "shrink-0",
|
|
484
|
-
children: agent.packageName ?? agent.source
|
|
485
|
-
}),
|
|
486
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1" }),
|
|
487
|
-
/* @__PURE__ */ jsx("span", {
|
|
488
|
-
className: `shrink-0 text-sm ${agent.model ? "text-doom-cyan" : "text-doom-dim"}`,
|
|
489
|
-
children: agent.model ? shortModel(agent.model) : "agent default"
|
|
490
|
-
})
|
|
491
|
-
]
|
|
492
|
-
}),
|
|
493
|
-
/* @__PURE__ */ jsx("span", {
|
|
494
|
-
className: "truncate text-sm text-doom-dim",
|
|
495
|
-
children: agent.description
|
|
496
|
-
}),
|
|
497
|
-
/* @__PURE__ */ jsx("span", {
|
|
498
|
-
className: "truncate text-sm text-doom-dim",
|
|
499
|
-
children: agentMeta(agent)
|
|
500
|
-
}),
|
|
501
|
-
selected ? /* @__PURE__ */ jsxs("div", {
|
|
502
|
-
className: "flex items-center gap-3 pt-0.5",
|
|
503
|
-
children: [
|
|
504
|
-
/* @__PURE__ */ jsxs(Button, {
|
|
505
|
-
variant: "link",
|
|
506
|
-
size: "xs",
|
|
507
|
-
"data-testid": `catalog-launch-${agent.name}`,
|
|
508
|
-
className: "px-0",
|
|
509
|
-
onClick: (event) => {
|
|
510
|
-
event.stopPropagation();
|
|
511
|
-
onLaunch(false);
|
|
512
|
-
},
|
|
513
|
-
children: ["launch ", /* @__PURE__ */ jsx(Kbd, { children: "↵" })]
|
|
514
|
-
}),
|
|
515
|
-
/* @__PURE__ */ jsxs(Button, {
|
|
516
|
-
variant: "link",
|
|
517
|
-
size: "xs",
|
|
518
|
-
"data-testid": `catalog-fork-${agent.name}`,
|
|
519
|
-
className: "px-0 text-doom-dim",
|
|
520
|
-
onClick: (event) => {
|
|
521
|
-
event.stopPropagation();
|
|
522
|
-
onLaunch(true);
|
|
523
|
-
},
|
|
524
|
-
children: ["fork session ", /* @__PURE__ */ jsx(Kbd, { children: "f" })]
|
|
525
|
-
}),
|
|
526
|
-
/* @__PURE__ */ jsxs(Button, {
|
|
527
|
-
variant: "link",
|
|
528
|
-
size: "xs",
|
|
529
|
-
"data-testid": `catalog-inspect-${agent.name}`,
|
|
530
|
-
className: "px-0 text-doom-dim",
|
|
531
|
-
onClick: (event) => {
|
|
532
|
-
event.stopPropagation();
|
|
533
|
-
onInspect();
|
|
534
|
-
},
|
|
535
|
-
children: ["inspect ", /* @__PURE__ */ jsx(Kbd, { children: "i" })]
|
|
536
|
-
})
|
|
537
|
-
]
|
|
538
|
-
}) : null,
|
|
539
|
-
selected && inspected ? /* @__PURE__ */ jsx(Resources, { agent }) : null
|
|
540
|
-
]
|
|
381
|
+
//#region src/extensions/workspaces/sessions/(frontend)/_components/AgentLauncherView.tsx
|
|
382
|
+
const SOURCE_LABEL = {
|
|
383
|
+
project: "Project",
|
|
384
|
+
user: "User",
|
|
385
|
+
plugin: "Package"
|
|
386
|
+
};
|
|
387
|
+
function Choice({ label, value, onChange, options, disabled }) {
|
|
388
|
+
return /* @__PURE__ */ jsxs(Select, {
|
|
389
|
+
disabled,
|
|
390
|
+
value,
|
|
391
|
+
onValueChange: onChange,
|
|
392
|
+
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
393
|
+
"aria-label": label,
|
|
394
|
+
className: "h-9 w-full",
|
|
395
|
+
children: /* @__PURE__ */ jsx(SelectValue, {})
|
|
396
|
+
}), /* @__PURE__ */ jsx(SelectContent, { children: options.map(([key, text]) => /* @__PURE__ */ jsx(SelectItem, {
|
|
397
|
+
value: key,
|
|
398
|
+
children: text
|
|
399
|
+
}, key)) })]
|
|
541
400
|
});
|
|
542
401
|
}
|
|
543
|
-
/**
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
const
|
|
550
|
-
const
|
|
551
|
-
const
|
|
552
|
-
const
|
|
553
|
-
const
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
402
|
+
/** Shared production presentation. The caller owns transport and session state. */
|
|
403
|
+
function AgentLauncherView({ agents, models, initialSearch = "", initialSelected, initialTask = "", initialFork, loading = false, warning, cwd = "", catalogNote, runNote, onClose, onLaunch, onSource }) {
|
|
404
|
+
const [search, setSearch] = useState(initialSearch);
|
|
405
|
+
const [source, setSource] = useState("all");
|
|
406
|
+
const [selected, setSelected] = useState(initialSelected);
|
|
407
|
+
const [task, setTask] = useState(initialTask);
|
|
408
|
+
const [context, setContext] = useState(initialFork === void 0 ? void 0 : initialFork ? "fork" : "fresh");
|
|
409
|
+
const [model, setModel] = useState("default");
|
|
410
|
+
const [busy, setBusy] = useState(false);
|
|
411
|
+
const pending = useRef(false);
|
|
412
|
+
const [error, setError] = useState();
|
|
413
|
+
const shown = filterCatalog(agents, search).filter((agent) => source === "all" || agent.source === source);
|
|
414
|
+
const agent = selected === void 0 ? shown[0] : shown.find((item) => item.name === selected);
|
|
415
|
+
const runContext = context ?? agent?.defaultContext ?? "fresh";
|
|
416
|
+
const choose = (item) => {
|
|
417
|
+
setSelected(item.name);
|
|
418
|
+
setContext(item.defaultContext);
|
|
419
|
+
setModel("default");
|
|
420
|
+
setError(void 0);
|
|
558
421
|
};
|
|
559
|
-
const
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
422
|
+
const launch = async () => {
|
|
423
|
+
if (!agent || loading || pending.current) return;
|
|
424
|
+
pending.current = true;
|
|
425
|
+
setBusy(true);
|
|
426
|
+
setError(void 0);
|
|
427
|
+
try {
|
|
428
|
+
await onLaunch({
|
|
429
|
+
agent: agent.name,
|
|
430
|
+
task,
|
|
431
|
+
fork: runContext === "fork",
|
|
432
|
+
...model === "default" ? {} : { model }
|
|
433
|
+
});
|
|
434
|
+
} catch (cause) {
|
|
435
|
+
setError(cause instanceof Error ? cause.message : String(cause));
|
|
436
|
+
} finally {
|
|
437
|
+
pending.current = false;
|
|
438
|
+
setBusy(false);
|
|
576
439
|
}
|
|
577
|
-
if (typing) return;
|
|
578
|
-
if (event.key === "f") onLaunch(selected, true);
|
|
579
|
-
if (event.key === "i") toggleInspect(sessionId, selected.name);
|
|
580
440
|
};
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
className: "
|
|
441
|
+
const modelLabel = model === "default" ? agent?.model ?? "Runtime default" : model;
|
|
442
|
+
const contextLabel = runContext === "fresh" ? "Fresh context" : "This conversation";
|
|
443
|
+
return /* @__PURE__ */ jsxs(DialogContent, {
|
|
444
|
+
"data-testid": "launch-dialog",
|
|
445
|
+
className: "w-6xl",
|
|
446
|
+
"aria-describedby": "launcher-description",
|
|
586
447
|
children: [
|
|
448
|
+
/* @__PURE__ */ jsx(DialogHeader, {
|
|
449
|
+
dismissible: true,
|
|
450
|
+
closeLabel: "Close new agent run",
|
|
451
|
+
className: "p-6 sm:px-6",
|
|
452
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
453
|
+
className: "space-y-1",
|
|
454
|
+
children: [/* @__PURE__ */ jsx(DialogTitle, { children: "New agent run" }), /* @__PURE__ */ jsx(DialogDescription, {
|
|
455
|
+
id: "launcher-description",
|
|
456
|
+
children: "Choose an agent, review its setup, then give it a task."
|
|
457
|
+
})]
|
|
458
|
+
})
|
|
459
|
+
}),
|
|
587
460
|
/* @__PURE__ */ jsxs("div", {
|
|
588
|
-
className: "
|
|
461
|
+
className: "grid min-h-0 overflow-y-auto md:grid-cols-3",
|
|
462
|
+
children: [/* @__PURE__ */ jsxs("aside", {
|
|
463
|
+
"aria-label": "Agent catalog",
|
|
464
|
+
onKeyDown: (event) => {
|
|
465
|
+
if (busy || event.target.getAttribute("role") === "combobox") return;
|
|
466
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
467
|
+
event.preventDefault();
|
|
468
|
+
const index = shown.findIndex((item) => item.name === agent?.name);
|
|
469
|
+
const next = shown[(index + (event.key === "ArrowDown" ? 1 : -1) + shown.length) % shown.length];
|
|
470
|
+
if (next) choose(next);
|
|
471
|
+
}
|
|
472
|
+
if (event.target.tagName === "INPUT") return;
|
|
473
|
+
if (event.key === "f") setContext("fork");
|
|
474
|
+
if (event.key === "i") {
|
|
475
|
+
const details = event.currentTarget.parentElement?.querySelector("details");
|
|
476
|
+
if (details) details.open = !details.open;
|
|
477
|
+
}
|
|
478
|
+
},
|
|
479
|
+
className: "flex flex-col gap-3 border-b border-po-border p-5 md:border-r md:border-b-0",
|
|
480
|
+
children: [
|
|
481
|
+
/* @__PURE__ */ jsx(Input, {
|
|
482
|
+
autoFocus: true,
|
|
483
|
+
"data-testid": "catalog-filter",
|
|
484
|
+
disabled: busy,
|
|
485
|
+
"aria-label": "Find an agent",
|
|
486
|
+
placeholder: "Find an agent…",
|
|
487
|
+
value: search,
|
|
488
|
+
onChange: (event) => setSearch(event.target.value)
|
|
489
|
+
}),
|
|
490
|
+
/* @__PURE__ */ jsx(Choice, {
|
|
491
|
+
disabled: busy,
|
|
492
|
+
label: "Source filter",
|
|
493
|
+
value: source,
|
|
494
|
+
onChange: setSource,
|
|
495
|
+
options: [
|
|
496
|
+
["all", "All sources"],
|
|
497
|
+
["project", "Project"],
|
|
498
|
+
["user", "User"],
|
|
499
|
+
["plugin", "Package"]
|
|
500
|
+
]
|
|
501
|
+
}),
|
|
502
|
+
/* @__PURE__ */ jsxs("div", {
|
|
503
|
+
className: "flex flex-col gap-1 py-2",
|
|
504
|
+
children: [
|
|
505
|
+
loading ? /* @__PURE__ */ jsx("p", {
|
|
506
|
+
role: "status",
|
|
507
|
+
className: "text-sm text-po-dim",
|
|
508
|
+
children: "Loading agents…"
|
|
509
|
+
}) : null,
|
|
510
|
+
warning ? /* @__PURE__ */ jsx("p", {
|
|
511
|
+
role: "alert",
|
|
512
|
+
className: "text-sm text-po-red",
|
|
513
|
+
children: warning
|
|
514
|
+
}) : null,
|
|
515
|
+
shown.map((item) => /* @__PURE__ */ jsxs(Button, {
|
|
516
|
+
variant: "ghost",
|
|
517
|
+
size: "card",
|
|
518
|
+
"aria-pressed": agent?.name === item.name,
|
|
519
|
+
className: agent?.name === item.name ? "border-l-4 border-po-green bg-po-selected/15" : "border-l-4 border-transparent",
|
|
520
|
+
disabled: busy,
|
|
521
|
+
onClick: () => {
|
|
522
|
+
choose(item);
|
|
523
|
+
},
|
|
524
|
+
children: [
|
|
525
|
+
/* @__PURE__ */ jsx("span", {
|
|
526
|
+
className: "font-semibold text-po-hi",
|
|
527
|
+
children: item.name
|
|
528
|
+
}),
|
|
529
|
+
/* @__PURE__ */ jsx("span", {
|
|
530
|
+
className: "text-sm text-po-dim",
|
|
531
|
+
children: item.description.split(".")[0]
|
|
532
|
+
}),
|
|
533
|
+
/* @__PURE__ */ jsxs("span", {
|
|
534
|
+
className: "text-sm text-po-dim",
|
|
535
|
+
children: [
|
|
536
|
+
SOURCE_LABEL[item.source],
|
|
537
|
+
" · ",
|
|
538
|
+
item.model ?? "Default model"
|
|
539
|
+
]
|
|
540
|
+
})
|
|
541
|
+
]
|
|
542
|
+
}, item.name)),
|
|
543
|
+
shown.length === 0 && !loading ? /* @__PURE__ */ jsxs("div", {
|
|
544
|
+
className: "space-y-3 py-6",
|
|
545
|
+
children: [
|
|
546
|
+
/* @__PURE__ */ jsx("p", {
|
|
547
|
+
className: "text-base text-po-hi",
|
|
548
|
+
children: "No matching agents"
|
|
549
|
+
}),
|
|
550
|
+
/* @__PURE__ */ jsx("p", {
|
|
551
|
+
className: "text-sm text-po-dim",
|
|
552
|
+
children: "Try another name or source."
|
|
553
|
+
}),
|
|
554
|
+
/* @__PURE__ */ jsx(Button, {
|
|
555
|
+
onClick: () => {
|
|
556
|
+
setSearch("");
|
|
557
|
+
setSource("all");
|
|
558
|
+
},
|
|
559
|
+
children: "Clear filters"
|
|
560
|
+
})
|
|
561
|
+
]
|
|
562
|
+
}) : null
|
|
563
|
+
]
|
|
564
|
+
}),
|
|
565
|
+
/* @__PURE__ */ jsxs("p", {
|
|
566
|
+
className: "mt-auto text-sm text-po-dim",
|
|
567
|
+
children: [
|
|
568
|
+
shown.length,
|
|
569
|
+
" agents",
|
|
570
|
+
catalogNote ? ` · ${catalogNote}` : ""
|
|
571
|
+
]
|
|
572
|
+
})
|
|
573
|
+
]
|
|
574
|
+
}), /* @__PURE__ */ jsx("section", {
|
|
575
|
+
className: "space-y-5 p-6 md:col-span-2",
|
|
576
|
+
"aria-label": "Agent definition and run",
|
|
577
|
+
children: agent ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
578
|
+
/* @__PURE__ */ jsxs("div", {
|
|
579
|
+
className: "space-y-2",
|
|
580
|
+
children: [
|
|
581
|
+
/* @__PURE__ */ jsx("p", {
|
|
582
|
+
className: "text-sm text-po-dim",
|
|
583
|
+
children: "Agent definition"
|
|
584
|
+
}),
|
|
585
|
+
/* @__PURE__ */ jsxs("div", {
|
|
586
|
+
className: "flex items-center gap-3",
|
|
587
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
588
|
+
className: "text-2xl font-semibold text-po-hi",
|
|
589
|
+
children: agent.name
|
|
590
|
+
}), /* @__PURE__ */ jsx(Badge, { children: SOURCE_LABEL[agent.source] })]
|
|
591
|
+
}),
|
|
592
|
+
/* @__PURE__ */ jsx("p", {
|
|
593
|
+
className: "text-base text-po-text",
|
|
594
|
+
children: agent.description
|
|
595
|
+
}),
|
|
596
|
+
/* @__PURE__ */ jsx("p", {
|
|
597
|
+
className: "break-all font-mono text-sm text-po-dim",
|
|
598
|
+
children: onSource?.(agent) ? /* @__PURE__ */ jsx("button", {
|
|
599
|
+
type: "button",
|
|
600
|
+
className: "text-left text-po-green underline",
|
|
601
|
+
onClick: onSource(agent),
|
|
602
|
+
children: agent.filePath
|
|
603
|
+
}) : agent.filePath
|
|
604
|
+
}),
|
|
605
|
+
agent.packageName ? /* @__PURE__ */ jsx("p", {
|
|
606
|
+
className: "text-sm text-po-dim",
|
|
607
|
+
children: agent.packageName
|
|
608
|
+
}) : null,
|
|
609
|
+
/* @__PURE__ */ jsxs("details", {
|
|
610
|
+
className: "text-base text-po-text",
|
|
611
|
+
children: [/* @__PURE__ */ jsx("summary", {
|
|
612
|
+
className: "cursor-pointer text-po-green",
|
|
613
|
+
children: "View instructions"
|
|
614
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
615
|
+
className: "mt-2 whitespace-pre-wrap rounded-md bg-po-deep p-3 text-sm",
|
|
616
|
+
children: onSource?.(agent) ? /* @__PURE__ */ jsx(Button, {
|
|
617
|
+
variant: "link",
|
|
618
|
+
onClick: onSource(agent),
|
|
619
|
+
children: "Open source instructions"
|
|
620
|
+
}) : "Instructions stay in the source definition. File viewing is not available in this host."
|
|
621
|
+
})]
|
|
622
|
+
})
|
|
623
|
+
]
|
|
624
|
+
}),
|
|
625
|
+
/* @__PURE__ */ jsx("dl", {
|
|
626
|
+
className: "grid gap-x-6 gap-y-3 text-base sm:grid-cols-2",
|
|
627
|
+
children: [
|
|
628
|
+
["Model", agent.model ?? "Runtime default"],
|
|
629
|
+
["Tools", agent.tools.length ? agent.tools.join(" · ") : "All session tools (not narrowed)"],
|
|
630
|
+
["Fallback models", agent.fallbackModels.join(" · ") || "None specified"],
|
|
631
|
+
["Skills", agent.skills.join(" · ") || "None specified"],
|
|
632
|
+
["Default context", agent.defaultContext === "fresh" ? "Fresh" : "This conversation"],
|
|
633
|
+
["Extensions", agent.extensions.join(" · ") || "None specified"]
|
|
634
|
+
].map(([label, value]) => /* @__PURE__ */ jsxs("div", {
|
|
635
|
+
className: "space-y-1",
|
|
636
|
+
children: [/* @__PURE__ */ jsx("dt", {
|
|
637
|
+
className: "text-sm text-po-dim",
|
|
638
|
+
children: label
|
|
639
|
+
}), /* @__PURE__ */ jsx("dd", {
|
|
640
|
+
className: "break-words text-po-text",
|
|
641
|
+
children: value
|
|
642
|
+
})]
|
|
643
|
+
}, label))
|
|
644
|
+
}),
|
|
645
|
+
/* @__PURE__ */ jsxs("div", {
|
|
646
|
+
className: "space-y-3 border-t border-po-border pt-4",
|
|
647
|
+
children: [
|
|
648
|
+
/* @__PURE__ */ jsx("h3", {
|
|
649
|
+
className: "text-lg font-semibold text-po-hi",
|
|
650
|
+
children: "This run"
|
|
651
|
+
}),
|
|
652
|
+
/* @__PURE__ */ jsxs("label", {
|
|
653
|
+
className: "flex flex-col gap-1 text-base text-po-text",
|
|
654
|
+
children: ["Task", /* @__PURE__ */ jsx(Textarea, {
|
|
655
|
+
"data-testid": "launch-task",
|
|
656
|
+
disabled: busy,
|
|
657
|
+
placeholder: "What should the agent do? Leave empty to use its own prompt.",
|
|
658
|
+
onKeyDown: (event) => {
|
|
659
|
+
if (event.key === "Enter" && !event.shiftKey && !event.nativeEvent.isComposing) {
|
|
660
|
+
event.preventDefault();
|
|
661
|
+
launch();
|
|
662
|
+
}
|
|
663
|
+
},
|
|
664
|
+
rows: 3,
|
|
665
|
+
value: task,
|
|
666
|
+
onChange: (event) => {
|
|
667
|
+
setTask(event.target.value);
|
|
668
|
+
setError(void 0);
|
|
669
|
+
}
|
|
670
|
+
})]
|
|
671
|
+
}),
|
|
672
|
+
/* @__PURE__ */ jsxs("div", {
|
|
673
|
+
className: "grid gap-4 sm:grid-cols-2",
|
|
674
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
675
|
+
className: "space-y-1",
|
|
676
|
+
children: [
|
|
677
|
+
/* @__PURE__ */ jsx("p", {
|
|
678
|
+
className: "text-base text-po-text",
|
|
679
|
+
children: "Context"
|
|
680
|
+
}),
|
|
681
|
+
/* @__PURE__ */ jsx(Choice, {
|
|
682
|
+
disabled: busy,
|
|
683
|
+
label: "Context",
|
|
684
|
+
value: runContext,
|
|
685
|
+
onChange: setContext,
|
|
686
|
+
options: [["fresh", "Fresh context"], ["fork", "This conversation"]]
|
|
687
|
+
}),
|
|
688
|
+
/* @__PURE__ */ jsx("p", {
|
|
689
|
+
className: "text-sm text-po-dim",
|
|
690
|
+
children: "Start clean, or include this conversation."
|
|
691
|
+
})
|
|
692
|
+
]
|
|
693
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
694
|
+
className: "space-y-1",
|
|
695
|
+
children: [
|
|
696
|
+
/* @__PURE__ */ jsx("p", {
|
|
697
|
+
className: "text-base text-po-text",
|
|
698
|
+
children: "Model override"
|
|
699
|
+
}),
|
|
700
|
+
/* @__PURE__ */ jsx(Choice, {
|
|
701
|
+
disabled: busy,
|
|
702
|
+
label: "Model override",
|
|
703
|
+
value: model,
|
|
704
|
+
onChange: setModel,
|
|
705
|
+
options: [["default", "Use agent default"], ...modelChoices(agent, models).map((choice) => [choice, choice])]
|
|
706
|
+
}),
|
|
707
|
+
/* @__PURE__ */ jsx("p", {
|
|
708
|
+
className: "text-sm text-po-dim",
|
|
709
|
+
children: "Changes apply only to this run."
|
|
710
|
+
})
|
|
711
|
+
]
|
|
712
|
+
})]
|
|
713
|
+
})
|
|
714
|
+
]
|
|
715
|
+
})
|
|
716
|
+
] }) : /* @__PURE__ */ jsx("p", {
|
|
717
|
+
className: "py-12 text-base text-po-dim",
|
|
718
|
+
children: "Choose an agent to review its definition. Clear the filters if no agents match."
|
|
719
|
+
})
|
|
720
|
+
})]
|
|
721
|
+
}),
|
|
722
|
+
/* @__PURE__ */ jsxs(DialogFooter, {
|
|
723
|
+
variant: "bar",
|
|
724
|
+
className: "gap-3 p-4 sm:px-6 sm:py-4",
|
|
589
725
|
children: [
|
|
590
|
-
/* @__PURE__ */
|
|
591
|
-
className: "
|
|
592
|
-
children: "agent catalog"
|
|
593
|
-
}),
|
|
594
|
-
/* @__PURE__ */ jsxs(Badge, {
|
|
595
|
-
size: "xs",
|
|
596
|
-
"data-testid": "catalog-count",
|
|
726
|
+
/* @__PURE__ */ jsxs("div", {
|
|
727
|
+
className: "min-w-0 flex-1 space-y-1 text-sm text-po-dim",
|
|
597
728
|
children: [
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
729
|
+
/* @__PURE__ */ jsx("p", {
|
|
730
|
+
className: "break-words",
|
|
731
|
+
children: agent ? `${agent.name} · ${contextLabel} · ${modelLabel}` : "No agent selected"
|
|
732
|
+
}),
|
|
733
|
+
/* @__PURE__ */ jsx("p", {
|
|
734
|
+
role: "status",
|
|
735
|
+
children: runNote ?? `Enter starts the run · Shift+Enter for a new line${cwd ? ` · ${cwd}` : ""}`
|
|
736
|
+
}),
|
|
737
|
+
error ? /* @__PURE__ */ jsx("p", {
|
|
738
|
+
role: "alert",
|
|
739
|
+
className: "text-po-red",
|
|
740
|
+
children: error
|
|
741
|
+
}) : null
|
|
601
742
|
]
|
|
602
743
|
}),
|
|
603
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1" }),
|
|
604
|
-
/* @__PURE__ */ jsx(Kbd, { children: "SPC a l" }),
|
|
605
744
|
/* @__PURE__ */ jsx(Button, {
|
|
606
|
-
|
|
607
|
-
size: "icon",
|
|
608
|
-
"data-testid": "catalog-close",
|
|
609
|
-
title: "close the catalog",
|
|
745
|
+
"data-testid": "launch-cancel",
|
|
610
746
|
onClick: onClose,
|
|
611
|
-
children:
|
|
747
|
+
children: "Cancel"
|
|
748
|
+
}),
|
|
749
|
+
/* @__PURE__ */ jsx(Button, {
|
|
750
|
+
"data-testid": "launch-submit",
|
|
751
|
+
variant: "primary",
|
|
752
|
+
disabled: !agent || busy || loading,
|
|
753
|
+
onClick: () => void launch(),
|
|
754
|
+
children: busy ? "Starting…" : "Start run"
|
|
612
755
|
})
|
|
613
756
|
]
|
|
614
|
-
}),
|
|
615
|
-
/* @__PURE__ */ jsx("div", {
|
|
616
|
-
className: "px-4 pt-2.5 pb-1.5",
|
|
617
|
-
children: /* @__PURE__ */ jsx(Input, {
|
|
618
|
-
"data-testid": "catalog-filter",
|
|
619
|
-
value: state.filter,
|
|
620
|
-
placeholder: "filter by name, source, or tool…",
|
|
621
|
-
autoFocus: true,
|
|
622
|
-
onChange: (event) => setCatalogFilter(sessionId, event.target.value)
|
|
623
|
-
})
|
|
624
|
-
}),
|
|
625
|
-
/* @__PURE__ */ jsxs("div", {
|
|
626
|
-
role: "listbox",
|
|
627
|
-
className: "flex min-h-0 flex-1 flex-col overflow-y-auto pb-2",
|
|
628
|
-
children: [
|
|
629
|
-
state.loading ? /* @__PURE__ */ jsx("p", {
|
|
630
|
-
role: "status",
|
|
631
|
-
className: "px-4 py-3 text-sm text-doom-dim",
|
|
632
|
-
children: "loading agents..."
|
|
633
|
-
}) : null,
|
|
634
|
-
state.warning ? /* @__PURE__ */ jsx("p", {
|
|
635
|
-
role: "alert",
|
|
636
|
-
className: "px-4 py-3 text-sm text-doom-red",
|
|
637
|
-
children: state.warning
|
|
638
|
-
}) : null,
|
|
639
|
-
shown.length === 0 && !state.loading && !state.warning ? /* @__PURE__ */ jsx("p", {
|
|
640
|
-
"data-testid": "catalog-empty",
|
|
641
|
-
className: "px-4 py-3 text-sm text-doom-dim",
|
|
642
|
-
children: state.agents.length === 0 ? "no agents found for this session; add one under .po/agents or ~/.po/agent/agents" : "nothing matches the filter"
|
|
643
|
-
}) : null,
|
|
644
|
-
sections.map((section) => /* @__PURE__ */ jsxs("div", {
|
|
645
|
-
className: "flex flex-col",
|
|
646
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
647
|
-
className: "px-4 pt-2.5 pb-1 text-lg font-semibold text-doom-hi",
|
|
648
|
-
children: section.label
|
|
649
|
-
}), section.agents.map((agent) => /* @__PURE__ */ jsx(AgentRow, {
|
|
650
|
-
agent,
|
|
651
|
-
selected: selected?.name === agent.name,
|
|
652
|
-
inspected: state.inspected === agent.name,
|
|
653
|
-
onSelect: () => selectAgent(sessionId, agent.name),
|
|
654
|
-
onLaunch: (fork) => onLaunch(agent, fork),
|
|
655
|
-
onInspect: () => toggleInspect(sessionId, agent.name)
|
|
656
|
-
}, agent.name))]
|
|
657
|
-
}, section.source))
|
|
658
|
-
]
|
|
659
|
-
}),
|
|
660
|
-
/* @__PURE__ */ jsxs("div", {
|
|
661
|
-
className: "flex h-8 shrink-0 items-center justify-between border-t border-doom-border-soft bg-doom-deep px-4",
|
|
662
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
663
|
-
className: "text-sm text-doom-dim",
|
|
664
|
-
children: "↑↓ choose · enter launch · f fork · i inspect · esc close"
|
|
665
|
-
}), /* @__PURE__ */ jsxs("span", {
|
|
666
|
-
className: "text-sm text-doom-dim",
|
|
667
|
-
children: [
|
|
668
|
-
sections.length,
|
|
669
|
-
" source",
|
|
670
|
-
sections.length === 1 ? "" : "s"
|
|
671
|
-
]
|
|
672
|
-
})]
|
|
673
757
|
})
|
|
674
758
|
]
|
|
675
759
|
});
|
|
676
760
|
}
|
|
677
761
|
//#endregion
|
|
762
|
+
//#region src/extensions/workspaces/sessions/(frontend)/_components/LaunchAgentDialog.tsx
|
|
763
|
+
function LaunchAgentDialog({ sessionId, agent, agents, loading, warning, onSource, cwd, models, fork: initialFork, initialTask, onClose, onLaunched }) {
|
|
764
|
+
return /* @__PURE__ */ jsx(Dialog, {
|
|
765
|
+
open: true,
|
|
766
|
+
onOpenChange: (open) => {
|
|
767
|
+
if (!open) onClose();
|
|
768
|
+
},
|
|
769
|
+
children: /* @__PURE__ */ jsx(AgentLauncherView, {
|
|
770
|
+
agents: agents ?? (agent ? [agent] : []),
|
|
771
|
+
models,
|
|
772
|
+
initialSelected: agent?.name,
|
|
773
|
+
initialTask,
|
|
774
|
+
initialFork,
|
|
775
|
+
loading,
|
|
776
|
+
warning,
|
|
777
|
+
cwd,
|
|
778
|
+
onSource,
|
|
779
|
+
onClose,
|
|
780
|
+
onLaunch: async (request) => {
|
|
781
|
+
requestLaunch(sessionId, request.agent);
|
|
782
|
+
try {
|
|
783
|
+
await launchAgent(sessionId, request);
|
|
784
|
+
onLaunched();
|
|
785
|
+
} catch (cause) {
|
|
786
|
+
clearPendingLaunch(sessionId);
|
|
787
|
+
throw cause;
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
})
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
//#endregion
|
|
794
|
+
//#region src/extensions/workspaces/sessions/(frontend)/_components/AgentCatalogDrawer.tsx
|
|
795
|
+
/** The catalog now opens inside the centered launcher, retaining the session store. */
|
|
796
|
+
function AgentCatalogDrawer({ sessionId, onClose, onSource }) {
|
|
797
|
+
const state = useStore(catalog.store, (current) => catalog.select(current, sessionId));
|
|
798
|
+
return /* @__PURE__ */ jsx(LaunchAgentDialog, {
|
|
799
|
+
sessionId,
|
|
800
|
+
agents: state.agents,
|
|
801
|
+
agent: state.agents.find((agent) => agent.name === (state.launch?.agent ?? state.selected)),
|
|
802
|
+
cwd: state.cwd,
|
|
803
|
+
models: state.models,
|
|
804
|
+
fork: state.launch?.fork,
|
|
805
|
+
initialTask: state.task,
|
|
806
|
+
loading: state.loading,
|
|
807
|
+
warning: state.warning,
|
|
808
|
+
onSource,
|
|
809
|
+
onClose,
|
|
810
|
+
onLaunched: onClose
|
|
811
|
+
});
|
|
812
|
+
}
|
|
813
|
+
//#endregion
|
|
678
814
|
//#region src/extensions/workspaces/sessions/(frontend)/_components/RunControl.tsx
|
|
679
815
|
/** One run state, in the host's shared outcome vocabulary. */
|
|
680
816
|
const RUN_BADGE = {
|
|
@@ -732,7 +868,7 @@ function RunControl({ sessionId, run, stopping }) {
|
|
|
732
868
|
role: "alert",
|
|
733
869
|
"data-testid": `run-stop-error-${run.runId}`,
|
|
734
870
|
title: error,
|
|
735
|
-
className: "min-w-0 truncate text-sm text-
|
|
871
|
+
className: "min-w-0 truncate text-sm text-po-red",
|
|
736
872
|
children: error
|
|
737
873
|
}) : null, /* @__PURE__ */ jsx(Button, {
|
|
738
874
|
variant: stopping ? "outline" : "danger-outline",
|
|
@@ -746,370 +882,373 @@ function RunControl({ sessionId, run, stopping }) {
|
|
|
746
882
|
})] });
|
|
747
883
|
}
|
|
748
884
|
//#endregion
|
|
749
|
-
//#region src/extensions/workspaces/sessions/(frontend)/_components/
|
|
750
|
-
const
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
885
|
+
//#region src/extensions/workspaces/sessions/(frontend)/_components/AgentThreadView.tsx
|
|
886
|
+
const NOT_REPORTED = "Not reported";
|
|
887
|
+
const END_NOTE = {
|
|
888
|
+
done: "This run has finished. Start a new run from Agents.",
|
|
889
|
+
failed: "This run failed. Start a new run from Agents.",
|
|
890
|
+
stopped: "This run was stopped. Start a new run from Agents."
|
|
891
|
+
};
|
|
892
|
+
function InfoRow({ label, children }) {
|
|
893
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
894
|
+
className: "flex gap-3",
|
|
895
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
896
|
+
className: "w-24 shrink-0 text-sm text-po-dim",
|
|
897
|
+
children: label
|
|
898
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
899
|
+
className: "min-w-0 flex-1 break-words text-base text-po-text",
|
|
900
|
+
children
|
|
901
|
+
})]
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
/** What the run is: the agent, what it was asked, and how it thinks. Only what the runtime recorded. */
|
|
905
|
+
function RunInfo({ run }) {
|
|
906
|
+
const usage = [run?.toolCount === void 0 ? void 0 : `${run.toolCount} tools`, run?.tokens === void 0 ? void 0 : `${run.tokens.toLocaleString()} tokens`].filter(Boolean).join(" · ");
|
|
907
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
908
|
+
/* @__PURE__ */ jsxs(InfoRow, {
|
|
909
|
+
label: "Agent",
|
|
910
|
+
children: [
|
|
911
|
+
/* @__PURE__ */ jsx("span", {
|
|
912
|
+
className: "font-semibold text-po-hi",
|
|
913
|
+
children: run?.agent ?? NOT_REPORTED
|
|
914
|
+
}),
|
|
915
|
+
run?.agentDescription ? /* @__PURE__ */ jsx("p", {
|
|
916
|
+
className: "text-po-dim",
|
|
917
|
+
children: run.agentDescription
|
|
918
|
+
}) : null,
|
|
919
|
+
run?.agentFilePath ? /* @__PURE__ */ jsx("p", {
|
|
920
|
+
className: "font-mono text-sm text-po-dim",
|
|
921
|
+
children: run.agentFilePath
|
|
922
|
+
}) : null
|
|
923
|
+
]
|
|
924
|
+
}),
|
|
925
|
+
/* @__PURE__ */ jsxs(InfoRow, {
|
|
926
|
+
label: "Model",
|
|
927
|
+
children: [run?.model ?? NOT_REPORTED, run?.model && run.modelSource === "configured" ? /* @__PURE__ */ jsx("span", {
|
|
928
|
+
className: "text-po-dim",
|
|
929
|
+
children: " · configured, not confirmed by the runtime"
|
|
930
|
+
}) : null]
|
|
931
|
+
}),
|
|
932
|
+
/* @__PURE__ */ jsx(InfoRow, {
|
|
933
|
+
label: "Thinking",
|
|
934
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
935
|
+
className: "capitalize",
|
|
936
|
+
children: run?.thinking ?? NOT_REPORTED
|
|
937
|
+
})
|
|
938
|
+
}),
|
|
939
|
+
/* @__PURE__ */ jsx(InfoRow, {
|
|
940
|
+
label: "Prompt",
|
|
941
|
+
children: run?.promptWithheld ? /* @__PURE__ */ jsx("span", {
|
|
942
|
+
className: "text-po-dim",
|
|
943
|
+
children: "Withheld: this task was marked sensitive."
|
|
944
|
+
}) : /* @__PURE__ */ jsx("pre", {
|
|
945
|
+
className: "max-h-40 overflow-y-auto rounded-md bg-po-deep px-3 py-2 font-sans whitespace-pre-wrap break-words",
|
|
946
|
+
children: run?.task || NOT_REPORTED
|
|
947
|
+
})
|
|
948
|
+
}),
|
|
949
|
+
run?.taskRef ? /* @__PURE__ */ jsx(InfoRow, {
|
|
950
|
+
label: "Task",
|
|
951
|
+
children: /* @__PURE__ */ jsx(Badge, {
|
|
952
|
+
tone: "violet",
|
|
953
|
+
size: "xs",
|
|
954
|
+
className: "rounded-sm bg-po-violet/10",
|
|
955
|
+
children: run.taskRef
|
|
956
|
+
})
|
|
957
|
+
}) : null,
|
|
958
|
+
/* @__PURE__ */ jsx(InfoRow, {
|
|
959
|
+
label: "Folder",
|
|
960
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
961
|
+
className: "font-mono text-sm",
|
|
962
|
+
children: run?.cwd ? abbreviateCwd(run.cwd) : NOT_REPORTED
|
|
963
|
+
})
|
|
964
|
+
}),
|
|
965
|
+
/* @__PURE__ */ jsx(InfoRow, {
|
|
966
|
+
label: "Usage",
|
|
967
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
968
|
+
className: "text-po-dim",
|
|
969
|
+
children: usage || NOT_REPORTED
|
|
970
|
+
})
|
|
762
971
|
})
|
|
763
|
-
};
|
|
972
|
+
] });
|
|
764
973
|
}
|
|
765
974
|
/**
|
|
766
|
-
*
|
|
767
|
-
*
|
|
768
|
-
*
|
|
769
|
-
* the
|
|
975
|
+
* One run's thread, read like the Conversation tab: a thin run strip, the
|
|
976
|
+
* host transcript, a guidance composer while the run can hear it, and
|
|
977
|
+
* read-only chips that all open the same run info. The container supplies
|
|
978
|
+
* the transcript, the stop control and the real actions.
|
|
770
979
|
*/
|
|
771
|
-
function
|
|
772
|
-
const
|
|
773
|
-
const
|
|
774
|
-
const
|
|
775
|
-
const
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
}, []);
|
|
783
|
-
const firstLine = run?.task.split("\n").find((line) => line.trim() !== "") ?? "";
|
|
784
|
-
const canSteer = sessionId !== null && run !== void 0 && !isTerminalRun(run);
|
|
785
|
-
const submitGuidance = async (event) => {
|
|
786
|
-
event.preventDefault();
|
|
787
|
-
const message = guidance.trim();
|
|
788
|
-
if (!canSteer || !message || sending) return;
|
|
789
|
-
setSending(true);
|
|
790
|
-
setError(void 0);
|
|
791
|
-
setNotice(void 0);
|
|
792
|
-
try {
|
|
793
|
-
const result = await steerRun(sessionId, runId, message);
|
|
794
|
-
if (result.state === "failed") {
|
|
795
|
-
setError(result.message);
|
|
796
|
-
return;
|
|
797
|
-
}
|
|
798
|
-
setGuidance("");
|
|
799
|
-
if (result.state === "pending") setNotice(result.message);
|
|
800
|
-
} catch (cause) {
|
|
801
|
-
setError(cause instanceof Error ? cause.message : String(cause));
|
|
802
|
-
} finally {
|
|
803
|
-
setSending(false);
|
|
804
|
-
}
|
|
980
|
+
function AgentThreadView({ run, gone, elapsed, stopControl, thread, canSteer, stopping, guidance, sending, error, notice, onGuidanceChange, onSubmit, initialInfoOpen = false }) {
|
|
981
|
+
const [open, setOpen] = useState(initialInfoOpen);
|
|
982
|
+
const infoId = useId();
|
|
983
|
+
const badge = run ? RUN_BADGE[run.state] : void 0;
|
|
984
|
+
const chip = {
|
|
985
|
+
variant: "outline",
|
|
986
|
+
size: "md",
|
|
987
|
+
className: "min-w-0 max-w-full gap-2",
|
|
988
|
+
"aria-expanded": open,
|
|
989
|
+
"aria-controls": infoId,
|
|
990
|
+
onClick: () => setOpen((current) => !current)
|
|
805
991
|
};
|
|
992
|
+
const endNote = run && isTerminalRun(run) ? END_NOTE[run.state] : run?.canSteer === false && !gone ? "This runtime does not take guidance while it runs." : "Guidance is unavailable for this run.";
|
|
806
993
|
return /* @__PURE__ */ jsxs("div", {
|
|
807
994
|
"data-testid": "agent-thread-panel",
|
|
808
|
-
className: "flex min-h-0 flex-1 flex-col",
|
|
995
|
+
className: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden bg-po-bg",
|
|
809
996
|
children: [
|
|
810
|
-
/* @__PURE__ */
|
|
997
|
+
/* @__PURE__ */ jsxs("div", {
|
|
811
998
|
"data-testid": "agent-thread-header",
|
|
812
|
-
className: "flex h-
|
|
813
|
-
children:
|
|
999
|
+
className: "flex h-11 shrink-0 items-center gap-2.5 border-b border-po-border-soft bg-po-rail px-[26px]",
|
|
1000
|
+
children: [
|
|
1001
|
+
run ? /* @__PURE__ */ jsx(AgentAvatar, {
|
|
1002
|
+
name: agentDisplay(run).name,
|
|
1003
|
+
seed: agentDisplay(run).seed,
|
|
1004
|
+
size: "sm"
|
|
1005
|
+
}) : null,
|
|
814
1006
|
/* @__PURE__ */ jsx("span", {
|
|
815
1007
|
"data-testid": "agent-thread-agent",
|
|
816
|
-
className: "
|
|
817
|
-
children: agentRunLabel(run)
|
|
1008
|
+
className: "min-w-0 shrink truncate text-base font-semibold text-po-hi",
|
|
1009
|
+
children: run ? agentRunLabel(run) : "Agent run"
|
|
818
1010
|
}),
|
|
819
|
-
/* @__PURE__ */ jsx(
|
|
820
|
-
|
|
1011
|
+
run && agentDisplay(run).role ? /* @__PURE__ */ jsx("span", {
|
|
1012
|
+
className: "min-w-0 shrink truncate text-sm text-po-dim",
|
|
1013
|
+
children: agentDisplay(run).role
|
|
1014
|
+
}) : null,
|
|
1015
|
+
badge ? /* @__PURE__ */ jsx(StatusBadge, {
|
|
1016
|
+
tone: badge.tone,
|
|
821
1017
|
"data-testid": "agent-thread-state",
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
/* @__PURE__ */ jsx("span", {
|
|
825
|
-
className: "shrink-0 text-sm text-doom-dim",
|
|
826
|
-
children: elapsedRun(run, now)
|
|
827
|
-
}),
|
|
828
|
-
run.model ? /* @__PURE__ */ jsx("span", {
|
|
829
|
-
className: "shrink-0 text-sm text-doom-dim",
|
|
830
|
-
children: run.model.split("/").pop() ?? run.model
|
|
1018
|
+
className: "shrink-0",
|
|
1019
|
+
children: stopping && run && !isTerminalRun(run) ? "STOPPING…" : badge.label
|
|
831
1020
|
}) : null,
|
|
832
1021
|
/* @__PURE__ */ jsx("span", {
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
children: firstLine
|
|
1022
|
+
className: "min-w-0 flex-1 truncate text-sm text-po-dim",
|
|
1023
|
+
children: elapsed
|
|
836
1024
|
}),
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
1025
|
+
stopControl
|
|
1026
|
+
]
|
|
1027
|
+
}),
|
|
1028
|
+
gone ? /* @__PURE__ */ jsx("div", {
|
|
1029
|
+
"data-testid": "agent-thread-gone",
|
|
1030
|
+
className: "shrink-0 border-b border-po-border-soft px-[26px] py-2 text-sm text-po-dim",
|
|
1031
|
+
children: "This run is no longer listed. Its thread stays readable."
|
|
1032
|
+
}) : null,
|
|
1033
|
+
/* @__PURE__ */ jsx("div", {
|
|
1034
|
+
className: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden",
|
|
1035
|
+
children: thread
|
|
1036
|
+
}),
|
|
1037
|
+
/* @__PURE__ */ jsx("section", {
|
|
1038
|
+
id: infoId,
|
|
1039
|
+
"aria-label": "Run info",
|
|
1040
|
+
"data-testid": "run-info",
|
|
1041
|
+
hidden: !open,
|
|
1042
|
+
className: "mx-[26px] mb-2 flex max-h-[40vh] shrink-0 flex-col gap-3 overflow-y-auto rounded-lg border border-po-border bg-po-panel px-4 py-3",
|
|
1043
|
+
children: /* @__PURE__ */ jsx(RunInfo, { run })
|
|
851
1044
|
}),
|
|
852
|
-
renderThread(runId),
|
|
853
1045
|
canSteer ? /* @__PURE__ */ jsx("form", {
|
|
854
1046
|
"data-testid": "agent-steer-composer",
|
|
855
|
-
className: "shrink-0
|
|
856
|
-
onSubmit: (event) =>
|
|
1047
|
+
className: "shrink-0 px-[26px] pt-2 pb-2",
|
|
1048
|
+
onSubmit: (event) => {
|
|
1049
|
+
event.preventDefault();
|
|
1050
|
+
onSubmit();
|
|
1051
|
+
},
|
|
857
1052
|
children: /* @__PURE__ */ jsxs("div", {
|
|
858
|
-
className: "rounded-lg border border-
|
|
1053
|
+
className: "rounded-lg border border-po-border bg-po-panel transition-colors focus-within:border-po-blue/60",
|
|
859
1054
|
children: [
|
|
860
|
-
/* @__PURE__ */
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
}
|
|
1055
|
+
/* @__PURE__ */ jsx(Textarea, {
|
|
1056
|
+
variant: "bare",
|
|
1057
|
+
"data-testid": "agent-steer-input",
|
|
1058
|
+
"aria-label": "Steering guidance",
|
|
1059
|
+
rows: 2,
|
|
1060
|
+
value: guidance,
|
|
1061
|
+
readOnly: sending,
|
|
1062
|
+
disabled: stopping,
|
|
1063
|
+
placeholder: stopping ? "Stopping, guidance paused" : "Guide this agent · it reads this at its next step",
|
|
1064
|
+
className: "w-full px-4 pt-3 text-lg leading-relaxed",
|
|
1065
|
+
onChange: (event) => onGuidanceChange(event.target.value),
|
|
1066
|
+
onKeyDown: (event) => {
|
|
1067
|
+
if (event.key !== "Enter" || event.shiftKey || event.nativeEvent.isComposing) return;
|
|
1068
|
+
event.preventDefault();
|
|
1069
|
+
event.currentTarget.form?.requestSubmit();
|
|
1070
|
+
}
|
|
876
1071
|
}),
|
|
877
1072
|
error ? /* @__PURE__ */ jsx("p", {
|
|
878
1073
|
role: "alert",
|
|
879
1074
|
"data-testid": "agent-steer-error",
|
|
880
|
-
className: "px-
|
|
1075
|
+
className: "px-4 pt-1 text-sm text-po-red",
|
|
881
1076
|
children: error
|
|
882
1077
|
}) : null,
|
|
883
1078
|
/* @__PURE__ */ jsxs("div", {
|
|
884
|
-
className: "flex items-center gap-
|
|
1079
|
+
className: "flex items-center gap-3 px-4 pt-1 pb-3",
|
|
885
1080
|
children: [
|
|
1081
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1" }),
|
|
886
1082
|
/* @__PURE__ */ jsx("span", {
|
|
887
1083
|
role: "status",
|
|
888
1084
|
"data-testid": "agent-steer-hint",
|
|
889
|
-
|
|
890
|
-
|
|
1085
|
+
title: notice,
|
|
1086
|
+
className: "min-w-0 truncate text-sm text-po-dim",
|
|
1087
|
+
children: notice ?? "Shift + Enter for a new line"
|
|
891
1088
|
}),
|
|
892
|
-
/* @__PURE__ */
|
|
893
|
-
/* @__PURE__ */ jsx(Button, {
|
|
1089
|
+
/* @__PURE__ */ jsxs(Button, {
|
|
894
1090
|
"data-testid": "agent-steer-submit",
|
|
895
1091
|
type: "submit",
|
|
896
1092
|
variant: "primary",
|
|
897
|
-
size: "
|
|
898
|
-
className: "
|
|
899
|
-
disabled: sending || guidance.trim() === "",
|
|
900
|
-
children: sending ? "
|
|
1093
|
+
size: "lg",
|
|
1094
|
+
className: "shrink-0 gap-2",
|
|
1095
|
+
disabled: stopping || sending || guidance.trim() === "",
|
|
1096
|
+
children: [/* @__PURE__ */ jsx(SendIcon, { className: "size-4" }), sending ? "Sending…" : "Send"]
|
|
901
1097
|
})
|
|
902
1098
|
]
|
|
903
1099
|
})
|
|
904
1100
|
]
|
|
905
1101
|
})
|
|
906
|
-
}) :
|
|
1102
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
1103
|
+
"data-testid": "agent-thread-end",
|
|
1104
|
+
className: "shrink-0 px-[26px] pt-3 pb-2 text-sm text-po-dim",
|
|
1105
|
+
children: endNote
|
|
1106
|
+
}),
|
|
1107
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1108
|
+
className: "flex shrink-0 flex-wrap items-center gap-2 px-[26px] pb-4",
|
|
1109
|
+
children: [
|
|
1110
|
+
/* @__PURE__ */ jsxs(Button, {
|
|
1111
|
+
...chip,
|
|
1112
|
+
"data-testid": "run-chip-agent",
|
|
1113
|
+
children: [
|
|
1114
|
+
/* @__PURE__ */ jsx("span", {
|
|
1115
|
+
"aria-hidden": true,
|
|
1116
|
+
className: "size-1.5 shrink-0 rounded-full bg-po-magenta"
|
|
1117
|
+
}),
|
|
1118
|
+
/* @__PURE__ */ jsx("span", {
|
|
1119
|
+
className: "truncate",
|
|
1120
|
+
children: run?.agent ?? "Agent"
|
|
1121
|
+
}),
|
|
1122
|
+
/* @__PURE__ */ jsx(ChevronDownIcon, {
|
|
1123
|
+
"aria-hidden": true,
|
|
1124
|
+
className: "size-3.5 shrink-0"
|
|
1125
|
+
})
|
|
1126
|
+
]
|
|
1127
|
+
}),
|
|
1128
|
+
/* @__PURE__ */ jsxs(Button, {
|
|
1129
|
+
...chip,
|
|
1130
|
+
"data-testid": "run-chip-model",
|
|
1131
|
+
children: [
|
|
1132
|
+
/* @__PURE__ */ jsx("span", {
|
|
1133
|
+
"aria-hidden": true,
|
|
1134
|
+
className: "size-1.5 shrink-0 rounded-full bg-po-green"
|
|
1135
|
+
}),
|
|
1136
|
+
/* @__PURE__ */ jsx("span", {
|
|
1137
|
+
className: "truncate",
|
|
1138
|
+
children: run?.model ? run.model.split("/").pop() ?? run.model : "Model not reported"
|
|
1139
|
+
}),
|
|
1140
|
+
run?.thinking ? /* @__PURE__ */ jsx("span", {
|
|
1141
|
+
className: "shrink-0 text-po-dim",
|
|
1142
|
+
children: run.thinking
|
|
1143
|
+
}) : null,
|
|
1144
|
+
/* @__PURE__ */ jsx(ChevronDownIcon, {
|
|
1145
|
+
"aria-hidden": true,
|
|
1146
|
+
className: "size-3.5 shrink-0"
|
|
1147
|
+
})
|
|
1148
|
+
]
|
|
1149
|
+
}),
|
|
1150
|
+
/* @__PURE__ */ jsxs(Button, {
|
|
1151
|
+
...chip,
|
|
1152
|
+
"data-testid": "run-chip-prompt",
|
|
1153
|
+
children: [
|
|
1154
|
+
/* @__PURE__ */ jsx("span", {
|
|
1155
|
+
"aria-hidden": true,
|
|
1156
|
+
className: "size-1.5 shrink-0 rounded-full bg-po-blue"
|
|
1157
|
+
}),
|
|
1158
|
+
"Prompt",
|
|
1159
|
+
/* @__PURE__ */ jsx(ChevronDownIcon, {
|
|
1160
|
+
"aria-hidden": true,
|
|
1161
|
+
className: "size-3.5 shrink-0"
|
|
1162
|
+
})
|
|
1163
|
+
]
|
|
1164
|
+
})
|
|
1165
|
+
]
|
|
1166
|
+
})
|
|
907
1167
|
]
|
|
908
1168
|
});
|
|
909
1169
|
}
|
|
910
1170
|
//#endregion
|
|
911
|
-
//#region src/extensions/workspaces/sessions/(frontend)/_components/
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
const
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
1171
|
+
//#region src/extensions/workspaces/sessions/(frontend)/_components/AgentThreadPanel.tsx
|
|
1172
|
+
const TICK_MS$2 = 1e4;
|
|
1173
|
+
/** The tab id doubles as the URL segment, so it stays plain and unique across plugins. */
|
|
1174
|
+
const TAB_ID_PREFIX = "subagents-run-";
|
|
1175
|
+
/** The temporary tab for one run; the host keeps this panel for as long as the tab is open. */
|
|
1176
|
+
function agentThreadTab(run) {
|
|
1177
|
+
const runId = run.runId;
|
|
1178
|
+
return {
|
|
1179
|
+
id: `${TAB_ID_PREFIX}${runId}`,
|
|
1180
|
+
label: agentRunLabel(run),
|
|
1181
|
+
panel: (props) => /* @__PURE__ */ jsx(AgentThreadPanel, {
|
|
1182
|
+
...props,
|
|
1183
|
+
runId
|
|
1184
|
+
}, `${props.sessionId}:${runId}`)
|
|
1185
|
+
};
|
|
920
1186
|
}
|
|
921
1187
|
/**
|
|
922
|
-
*
|
|
923
|
-
*
|
|
1188
|
+
* A run's own conversation on the host's transcript, with its live actions.
|
|
1189
|
+
* The run can leave the fleet feed before the reader is done; the thread and
|
|
1190
|
+
* what the run last reported stay, and the panel says so.
|
|
924
1191
|
*/
|
|
925
|
-
function
|
|
926
|
-
const
|
|
927
|
-
const
|
|
928
|
-
const [
|
|
929
|
-
|
|
1192
|
+
function AgentThreadPanel({ sessionId, runId, renderThread }) {
|
|
1193
|
+
const { runs, stopRequested } = useStore(subagents.store, (state) => subagents.select(state, sessionId));
|
|
1194
|
+
const listed = runs.find((candidate) => candidate.runId === runId);
|
|
1195
|
+
const [seen, setSeen] = useState(listed);
|
|
1196
|
+
if (listed !== void 0 && listed !== seen) setSeen(listed);
|
|
1197
|
+
const run = listed ?? seen;
|
|
1198
|
+
const gone = listed === void 0;
|
|
1199
|
+
const [now, setNow] = useState(() => Date.now());
|
|
1200
|
+
const [guidance, setGuidance] = useState("");
|
|
1201
|
+
const [sending, setSending] = useState(false);
|
|
930
1202
|
const [error, setError] = useState();
|
|
931
|
-
const
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
const
|
|
938
|
-
|
|
939
|
-
|
|
1203
|
+
const [notice, setNotice] = useState();
|
|
1204
|
+
useEffect(() => {
|
|
1205
|
+
const timer = setInterval(() => setNow(Date.now()), TICK_MS$2);
|
|
1206
|
+
return () => clearInterval(timer);
|
|
1207
|
+
}, []);
|
|
1208
|
+
const live = sessionId !== null && listed !== void 0 && !isTerminalRun(listed);
|
|
1209
|
+
const stopping = stopRequested.includes(runId);
|
|
1210
|
+
const canSteer = live && listed.canSteer !== false;
|
|
1211
|
+
const submitGuidance = async () => {
|
|
1212
|
+
const message = guidance.trim();
|
|
1213
|
+
if (!canSteer || stopping || !message || sending) return;
|
|
1214
|
+
setSending(true);
|
|
940
1215
|
setError(void 0);
|
|
941
|
-
|
|
1216
|
+
setNotice(void 0);
|
|
942
1217
|
try {
|
|
943
|
-
await
|
|
944
|
-
|
|
1218
|
+
const result = await steerRun(sessionId, runId, message);
|
|
1219
|
+
if (result.state === "failed") {
|
|
1220
|
+
setError(result.message);
|
|
1221
|
+
return;
|
|
1222
|
+
}
|
|
1223
|
+
setGuidance("");
|
|
1224
|
+
if (result.state === "pending") setNotice(result.message);
|
|
945
1225
|
} catch (cause) {
|
|
946
|
-
clearPendingLaunch(sessionId);
|
|
947
1226
|
setError(cause instanceof Error ? cause.message : String(cause));
|
|
948
1227
|
} finally {
|
|
949
|
-
|
|
950
|
-
}
|
|
951
|
-
};
|
|
952
|
-
const onTaskKeyDown = (event) => {
|
|
953
|
-
if (event.key === "Enter" && !event.shiftKey) {
|
|
954
|
-
event.preventDefault();
|
|
955
|
-
launch();
|
|
1228
|
+
setSending(false);
|
|
956
1229
|
}
|
|
957
1230
|
};
|
|
958
|
-
return /* @__PURE__ */ jsx(
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
/* @__PURE__ */ jsx(Badge, {
|
|
980
|
-
size: "xs",
|
|
981
|
-
className: "max-w-full truncate",
|
|
982
|
-
children: agent.packageName ?? agent.source
|
|
983
|
-
})
|
|
984
|
-
]
|
|
985
|
-
}) }), /* @__PURE__ */ jsxs(DialogBody, { children: [
|
|
986
|
-
/* @__PURE__ */ jsx("p", {
|
|
987
|
-
className: "text-base leading-relaxed text-doom-dim",
|
|
988
|
-
children: agent.description
|
|
989
|
-
}),
|
|
990
|
-
/* @__PURE__ */ jsxs("div", {
|
|
991
|
-
className: "flex flex-col gap-1.5",
|
|
992
|
-
children: [
|
|
993
|
-
/* @__PURE__ */ jsx(FieldLabel, { children: "TASK" }),
|
|
994
|
-
/* @__PURE__ */ jsx(Textarea, {
|
|
995
|
-
"data-testid": "launch-task",
|
|
996
|
-
autoFocus: true,
|
|
997
|
-
rows: TASK_ROWS,
|
|
998
|
-
value: task,
|
|
999
|
-
placeholder: "what should the agent do? empty runs its own prompt",
|
|
1000
|
-
onChange: (event) => setTask(event.target.value),
|
|
1001
|
-
onKeyDown: onTaskKeyDown
|
|
1002
|
-
}),
|
|
1003
|
-
/* @__PURE__ */ jsx("span", {
|
|
1004
|
-
className: "text-sm text-doom-dim",
|
|
1005
|
-
children: "enter launches · shift+enter for a new line · @ for files"
|
|
1006
|
-
})
|
|
1007
|
-
]
|
|
1008
|
-
}),
|
|
1009
|
-
/* @__PURE__ */ jsxs("div", {
|
|
1010
|
-
className: "flex flex-wrap gap-5",
|
|
1011
|
-
children: [
|
|
1012
|
-
/* @__PURE__ */ jsxs("div", {
|
|
1013
|
-
className: "flex flex-col gap-1.5",
|
|
1014
|
-
children: [
|
|
1015
|
-
/* @__PURE__ */ jsx(FieldLabel, { children: "CONTEXT" }),
|
|
1016
|
-
/* @__PURE__ */ jsxs("div", {
|
|
1017
|
-
className: "flex flex-wrap gap-1.5",
|
|
1018
|
-
children: [/* @__PURE__ */ jsx(Button, {
|
|
1019
|
-
variant: fork ? "outline" : "primary",
|
|
1020
|
-
size: "xs",
|
|
1021
|
-
"data-testid": "launch-fresh",
|
|
1022
|
-
"data-active": !fork,
|
|
1023
|
-
onClick: () => setFork(false),
|
|
1024
|
-
children: "fresh"
|
|
1025
|
-
}), /* @__PURE__ */ jsx(Button, {
|
|
1026
|
-
variant: fork ? "primary" : "outline",
|
|
1027
|
-
size: "xs",
|
|
1028
|
-
"data-testid": "launch-fork",
|
|
1029
|
-
"data-active": fork,
|
|
1030
|
-
onClick: () => setFork(true),
|
|
1031
|
-
children: "fork this session"
|
|
1032
|
-
})]
|
|
1033
|
-
}),
|
|
1034
|
-
/* @__PURE__ */ jsx("span", {
|
|
1035
|
-
className: "text-sm text-doom-dim",
|
|
1036
|
-
children: "fork shares the conversation so far"
|
|
1037
|
-
})
|
|
1038
|
-
]
|
|
1039
|
-
}),
|
|
1040
|
-
/* @__PURE__ */ jsxs("div", {
|
|
1041
|
-
className: "flex flex-col gap-1.5",
|
|
1042
|
-
children: [
|
|
1043
|
-
/* @__PURE__ */ jsx(FieldLabel, { children: "MODEL" }),
|
|
1044
|
-
/* @__PURE__ */ jsxs(Select, {
|
|
1045
|
-
value: model,
|
|
1046
|
-
onValueChange: setModel,
|
|
1047
|
-
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
1048
|
-
"data-testid": "launch-model",
|
|
1049
|
-
className: "h-7 w-full min-w-0 sm:min-w-[200px]",
|
|
1050
|
-
children: /* @__PURE__ */ jsx(SelectValue, {})
|
|
1051
|
-
}), /* @__PURE__ */ jsxs(SelectContent, { children: [/* @__PURE__ */ jsxs(SelectItem, {
|
|
1052
|
-
value: AGENT_DEFAULT,
|
|
1053
|
-
children: ["agent default", agent.model ? ` · ${agent.model}` : ""]
|
|
1054
|
-
}), modelChoices(agent, models).map((choice) => /* @__PURE__ */ jsx(SelectItem, {
|
|
1055
|
-
value: choice,
|
|
1056
|
-
children: choice
|
|
1057
|
-
}, choice))] })]
|
|
1058
|
-
}),
|
|
1059
|
-
/* @__PURE__ */ jsx("span", {
|
|
1060
|
-
className: "text-sm text-doom-dim",
|
|
1061
|
-
children: "leave unset to use the agent's default"
|
|
1062
|
-
})
|
|
1063
|
-
]
|
|
1064
|
-
}),
|
|
1065
|
-
/* @__PURE__ */ jsxs("div", {
|
|
1066
|
-
className: "flex flex-col gap-1.5",
|
|
1067
|
-
children: [
|
|
1068
|
-
/* @__PURE__ */ jsx(FieldLabel, { children: "CWD" }),
|
|
1069
|
-
/* @__PURE__ */ jsx("span", {
|
|
1070
|
-
className: "flex h-7 items-center text-sm text-doom-dim",
|
|
1071
|
-
children: abbreviateCwd(cwd)
|
|
1072
|
-
}),
|
|
1073
|
-
/* @__PURE__ */ jsx("span", {
|
|
1074
|
-
className: "text-sm text-doom-dim",
|
|
1075
|
-
children: "the session's directory"
|
|
1076
|
-
})
|
|
1077
|
-
]
|
|
1078
|
-
})
|
|
1079
|
-
]
|
|
1080
|
-
}),
|
|
1081
|
-
error ? /* @__PURE__ */ jsx("p", {
|
|
1082
|
-
role: "alert",
|
|
1083
|
-
className: "text-sm text-doom-red",
|
|
1084
|
-
children: error
|
|
1085
|
-
}) : null,
|
|
1086
|
-
/* @__PURE__ */ jsxs(DialogFooter, {
|
|
1087
|
-
className: "flex-wrap sm:flex-nowrap",
|
|
1088
|
-
children: [
|
|
1089
|
-
/* @__PURE__ */ jsx("span", {
|
|
1090
|
-
className: "w-full text-sm text-doom-dim sm:w-auto",
|
|
1091
|
-
children: "the run opens in its own tab once it starts"
|
|
1092
|
-
}),
|
|
1093
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1" }),
|
|
1094
|
-
/* @__PURE__ */ jsx(Button, {
|
|
1095
|
-
variant: "outline",
|
|
1096
|
-
size: "xs",
|
|
1097
|
-
"data-testid": "launch-cancel",
|
|
1098
|
-
onClick: onClose,
|
|
1099
|
-
children: "cancel"
|
|
1100
|
-
}),
|
|
1101
|
-
/* @__PURE__ */ jsx(Button, {
|
|
1102
|
-
variant: "primary",
|
|
1103
|
-
size: "xs",
|
|
1104
|
-
"data-testid": "launch-submit",
|
|
1105
|
-
disabled: busy,
|
|
1106
|
-
onClick: () => void launch(),
|
|
1107
|
-
children: busy ? "launching…" : "launch"
|
|
1108
|
-
})
|
|
1109
|
-
]
|
|
1110
|
-
})
|
|
1111
|
-
] })]
|
|
1112
|
-
})
|
|
1231
|
+
return /* @__PURE__ */ jsx(AgentThreadView, {
|
|
1232
|
+
run,
|
|
1233
|
+
gone,
|
|
1234
|
+
elapsed: run ? elapsedRun(gone ? {
|
|
1235
|
+
...run,
|
|
1236
|
+
endedAt: run.endedAt ?? run.lastUpdate
|
|
1237
|
+
} : run, now) : void 0,
|
|
1238
|
+
stopControl: live ? /* @__PURE__ */ jsx(RunControl, {
|
|
1239
|
+
sessionId,
|
|
1240
|
+
run: listed,
|
|
1241
|
+
stopping
|
|
1242
|
+
}) : void 0,
|
|
1243
|
+
thread: renderThread(runId),
|
|
1244
|
+
canSteer,
|
|
1245
|
+
stopping,
|
|
1246
|
+
guidance,
|
|
1247
|
+
sending,
|
|
1248
|
+
error,
|
|
1249
|
+
notice,
|
|
1250
|
+
onGuidanceChange: setGuidance,
|
|
1251
|
+
onSubmit: () => void submitGuidance()
|
|
1113
1252
|
});
|
|
1114
1253
|
}
|
|
1115
1254
|
//#endregion
|
|
@@ -1131,22 +1270,22 @@ function WorkLine({ run }) {
|
|
|
1131
1270
|
children: [/* @__PURE__ */ jsxs(Badge, {
|
|
1132
1271
|
tone: "violet",
|
|
1133
1272
|
size: "xs",
|
|
1134
|
-
className: "shrink-0 rounded-sm bg-
|
|
1273
|
+
className: "shrink-0 rounded-sm bg-po-violet/10",
|
|
1135
1274
|
children: ["TASK ", run.taskRef]
|
|
1136
1275
|
}), /* @__PURE__ */ jsx("span", {
|
|
1137
1276
|
"data-testid": "run-work",
|
|
1138
|
-
className: "min-w-0 truncate text-base text-
|
|
1277
|
+
className: "min-w-0 truncate text-base text-po-hi",
|
|
1139
1278
|
children: firstLine
|
|
1140
1279
|
})]
|
|
1141
1280
|
});
|
|
1142
1281
|
return /* @__PURE__ */ jsxs("div", {
|
|
1143
1282
|
className: "flex items-center gap-2 px-3 pb-2.5",
|
|
1144
1283
|
children: [/* @__PURE__ */ jsx("span", {
|
|
1145
|
-
className: "shrink-0 text-base font-medium text-
|
|
1284
|
+
className: "shrink-0 text-base font-medium text-po-dim",
|
|
1146
1285
|
children: "Prompt"
|
|
1147
1286
|
}), /* @__PURE__ */ jsx("span", {
|
|
1148
1287
|
"data-testid": "run-work",
|
|
1149
|
-
className: "min-w-0 truncate text-base text-
|
|
1288
|
+
className: "min-w-0 truncate text-base text-po-dim",
|
|
1150
1289
|
children: firstLine
|
|
1151
1290
|
})]
|
|
1152
1291
|
});
|
|
@@ -1168,7 +1307,7 @@ function RunMenu({ sessionId, run, stopping, onOpenThread, onOpenDetail }) {
|
|
|
1168
1307
|
role: "alert",
|
|
1169
1308
|
"data-testid": `run-menu-stop-error-${run.runId}`,
|
|
1170
1309
|
title: error,
|
|
1171
|
-
className: "min-w-0 truncate text-sm text-
|
|
1310
|
+
className: "min-w-0 truncate text-sm text-po-red",
|
|
1172
1311
|
children: error
|
|
1173
1312
|
}) : null, /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
|
|
1174
1313
|
asChild: true,
|
|
@@ -1219,6 +1358,7 @@ function RunMenu({ sessionId, run, stopping, onOpenThread, onOpenDetail }) {
|
|
|
1219
1358
|
*/
|
|
1220
1359
|
function RunCard({ sessionId, run, now, stopping, renderThread, onOpenThread, onOpenDetail }) {
|
|
1221
1360
|
const badge = RUN_BADGE[run.state];
|
|
1361
|
+
const who = agentDisplay(run);
|
|
1222
1362
|
const onKeyDown = (event) => {
|
|
1223
1363
|
if (event.target !== event.currentTarget) return;
|
|
1224
1364
|
if (event.key === "Enter" || event.key === " ") {
|
|
@@ -1228,7 +1368,7 @@ function RunCard({ sessionId, run, now, stopping, renderThread, onOpenThread, on
|
|
|
1228
1368
|
};
|
|
1229
1369
|
return /* @__PURE__ */ jsx(Panel, {
|
|
1230
1370
|
asChild: true,
|
|
1231
|
-
className: cn("flex h-[280px] min-w-0 flex-col text-left transition-colors outline-none hover:border-
|
|
1371
|
+
className: cn("flex h-[280px] min-w-0 flex-col text-left transition-colors outline-none hover:border-po-blue/50 focus-within:border-po-blue", STATUS_EDGE[badge.tone]),
|
|
1232
1372
|
children: /* @__PURE__ */ jsxs("div", {
|
|
1233
1373
|
"data-testid": `run-card-${run.runId}`,
|
|
1234
1374
|
"data-run-state": run.state,
|
|
@@ -1244,14 +1384,23 @@ function RunCard({ sessionId, run, now, stopping, renderThread, onOpenThread, on
|
|
|
1244
1384
|
/* @__PURE__ */ jsxs("div", {
|
|
1245
1385
|
className: "flex items-center gap-2 px-3 pt-2.5 pb-1.5",
|
|
1246
1386
|
children: [
|
|
1387
|
+
/* @__PURE__ */ jsx(AgentAvatar, {
|
|
1388
|
+
name: who.name,
|
|
1389
|
+
seed: who.seed,
|
|
1390
|
+
size: "sm"
|
|
1391
|
+
}),
|
|
1247
1392
|
/* @__PURE__ */ jsx("span", {
|
|
1248
1393
|
"data-testid": "run-agent",
|
|
1249
|
-
className: "truncate text-base font-semibold text-
|
|
1250
|
-
children:
|
|
1394
|
+
className: "truncate text-base font-semibold text-po-hi",
|
|
1395
|
+
children: who.name
|
|
1251
1396
|
}),
|
|
1397
|
+
who.role ? /* @__PURE__ */ jsx("span", {
|
|
1398
|
+
className: "truncate text-sm text-po-dim",
|
|
1399
|
+
children: who.role
|
|
1400
|
+
}) : null,
|
|
1252
1401
|
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1" }),
|
|
1253
1402
|
/* @__PURE__ */ jsx("span", {
|
|
1254
|
-
className: "shrink-0 text-sm text-
|
|
1403
|
+
className: "shrink-0 text-sm text-po-dim",
|
|
1255
1404
|
children: elapsedRun(run, now)
|
|
1256
1405
|
}),
|
|
1257
1406
|
/* @__PURE__ */ jsx(StatusBadge, {
|
|
@@ -1264,7 +1413,7 @@ function RunCard({ sessionId, run, now, stopping, renderThread, onOpenThread, on
|
|
|
1264
1413
|
/* @__PURE__ */ jsx(WorkLine, { run }),
|
|
1265
1414
|
/* @__PURE__ */ jsx("div", {
|
|
1266
1415
|
"data-testid": "run-stream",
|
|
1267
|
-
className: "pointer-events-none flex min-h-0 flex-1 flex-col overflow-hidden border-t border-
|
|
1416
|
+
className: "pointer-events-none flex min-h-0 flex-1 flex-col overflow-hidden border-t border-po-border-soft bg-po-deep",
|
|
1268
1417
|
children: renderThread(run.runId, {
|
|
1269
1418
|
limit: CARD_THREAD_ENTRIES,
|
|
1270
1419
|
compact: true
|
|
@@ -1272,15 +1421,15 @@ function RunCard({ sessionId, run, now, stopping, renderThread, onOpenThread, on
|
|
|
1272
1421
|
}),
|
|
1273
1422
|
run.state === "failed" && run.error ? /* @__PURE__ */ jsx("span", {
|
|
1274
1423
|
"data-testid": "run-error",
|
|
1275
|
-
className: "truncate border-t border-
|
|
1424
|
+
className: "truncate border-t border-po-border-soft px-3 py-1.5 text-sm text-po-red",
|
|
1276
1425
|
children: run.error
|
|
1277
1426
|
}) : null
|
|
1278
1427
|
]
|
|
1279
1428
|
}), /* @__PURE__ */ jsxs("div", {
|
|
1280
|
-
className: "flex shrink-0 items-center gap-3 border-t border-
|
|
1429
|
+
className: "flex shrink-0 items-center gap-3 border-t border-po-border-soft px-3 py-1.5",
|
|
1281
1430
|
children: [
|
|
1282
1431
|
/* @__PURE__ */ jsxs("span", {
|
|
1283
|
-
className: "truncate text-sm text-
|
|
1432
|
+
className: "truncate text-sm text-po-dim",
|
|
1284
1433
|
children: [
|
|
1285
1434
|
run.toolCount !== void 0 ? `${run.toolCount} tools` : "—",
|
|
1286
1435
|
run.tokens !== void 0 ? ` · ${run.tokens.toLocaleString()} tk` : "",
|
|
@@ -1300,11 +1449,11 @@ function RunCard({ sessionId, run, now, stopping, renderThread, onOpenThread, on
|
|
|
1300
1449
|
})
|
|
1301
1450
|
});
|
|
1302
1451
|
}
|
|
1303
|
-
function SheetRow({ label, value, tone = "text-
|
|
1452
|
+
function SheetRow({ label, value, tone = "text-po-dim" }) {
|
|
1304
1453
|
return /* @__PURE__ */ jsxs("div", {
|
|
1305
1454
|
className: "flex gap-2.5",
|
|
1306
1455
|
children: [/* @__PURE__ */ jsx("span", {
|
|
1307
|
-
className: "w-11 shrink-0 text-sm text-
|
|
1456
|
+
className: "w-11 shrink-0 text-sm text-po-dim",
|
|
1308
1457
|
children: label
|
|
1309
1458
|
}), /* @__PURE__ */ jsx("span", {
|
|
1310
1459
|
className: `min-w-0 break-words text-base ${tone}`,
|
|
@@ -1314,13 +1463,13 @@ function SheetRow({ label, value, tone = "text-doom-dim" }) {
|
|
|
1314
1463
|
}
|
|
1315
1464
|
function SheetBlock({ label, text, testId, tone }) {
|
|
1316
1465
|
return /* @__PURE__ */ jsxs("div", {
|
|
1317
|
-
className: "flex flex-col gap-1 rounded-md border border-
|
|
1466
|
+
className: "flex flex-col gap-1 rounded-md border border-po-border bg-po-deep px-3 py-2.5",
|
|
1318
1467
|
children: [/* @__PURE__ */ jsx("span", {
|
|
1319
|
-
className: "text-base font-medium text-
|
|
1468
|
+
className: "text-base font-medium text-po-dim",
|
|
1320
1469
|
children: label
|
|
1321
1470
|
}), /* @__PURE__ */ jsx("pre", {
|
|
1322
1471
|
"data-testid": testId,
|
|
1323
|
-
className: `overflow-x-auto whitespace-pre-wrap break-words text-base leading-relaxed ${tone ?? "text-
|
|
1472
|
+
className: `overflow-x-auto whitespace-pre-wrap break-words text-base leading-relaxed ${tone ?? "text-po-text"}`,
|
|
1324
1473
|
children: text
|
|
1325
1474
|
})]
|
|
1326
1475
|
});
|
|
@@ -1353,7 +1502,7 @@ function RunDetailSheet({ sessionId, run, now, stopping, renderSlot, onClose })
|
|
|
1353
1502
|
}),
|
|
1354
1503
|
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1" }),
|
|
1355
1504
|
/* @__PURE__ */ jsx("span", {
|
|
1356
|
-
className: "text-sm text-
|
|
1505
|
+
className: "text-sm text-po-dim",
|
|
1357
1506
|
children: elapsedRun(run, now)
|
|
1358
1507
|
}),
|
|
1359
1508
|
renderSlot(RUN_ACTIONS_SLOT.slot),
|
|
@@ -1374,7 +1523,7 @@ function RunDetailSheet({ sessionId, run, now, stopping, renderSlot, onClose })
|
|
|
1374
1523
|
run.taskRef ? /* @__PURE__ */ jsx(SheetRow, {
|
|
1375
1524
|
label: "task",
|
|
1376
1525
|
value: run.taskRef,
|
|
1377
|
-
tone: "text-
|
|
1526
|
+
tone: "text-po-violet"
|
|
1378
1527
|
}) : null,
|
|
1379
1528
|
/* @__PURE__ */ jsx(SheetRow, {
|
|
1380
1529
|
label: "model",
|
|
@@ -1404,7 +1553,7 @@ function RunDetailSheet({ sessionId, run, now, stopping, renderSlot, onClose })
|
|
|
1404
1553
|
label: "FAILURE",
|
|
1405
1554
|
testId: "sheet-error",
|
|
1406
1555
|
text: run.error,
|
|
1407
|
-
tone: "text-
|
|
1556
|
+
tone: "text-po-red"
|
|
1408
1557
|
}) : null
|
|
1409
1558
|
] })]
|
|
1410
1559
|
})
|
|
@@ -1413,14 +1562,14 @@ function RunDetailSheet({ sessionId, run, now, stopping, renderSlot, onClose })
|
|
|
1413
1562
|
/**
|
|
1414
1563
|
* The subagents tab: the focused session's fleet as a computed grid.
|
|
1415
1564
|
*
|
|
1416
|
-
*
|
|
1417
|
-
* every card is the same height with
|
|
1418
|
-
* absorbing the slack, so the grid reads as a
|
|
1565
|
+
* Two columns when the tab is wide enough, one when narrow (a container query,
|
|
1566
|
+
* so the activity rail's width counts), and every card is the same height with
|
|
1567
|
+
* the run's own live conversation absorbing the slack, so the grid reads as a
|
|
1568
|
+
* fleet rather than a ragged list.
|
|
1419
1569
|
* A card opens the run's tab; its menu opens the detail sheet over the grid.
|
|
1420
|
-
* The catalog
|
|
1421
|
-
* agent is a list beside the fleet rather than a thing about one run.
|
|
1570
|
+
* The catalog and run settings share a centered dialog over the unchanged fleet.
|
|
1422
1571
|
*/
|
|
1423
|
-
function SubagentsPanel({ sessionId, renderSlot, renderThread, openTransientTab }) {
|
|
1572
|
+
function SubagentsPanel({ sessionId, renderSlot, renderThread, openTransientTab, fileTabFor }) {
|
|
1424
1573
|
const runs = useStore(subagents.store, (state) => visibleRuns(subagents.select(state, sessionId)));
|
|
1425
1574
|
const { openRunId, stopRequested, autoOpenRunId } = useStore(subagents.store, (state) => subagents.select(state, sessionId));
|
|
1426
1575
|
const shelf = useStore(catalog.store, (state) => catalog.select(state, sessionId));
|
|
@@ -1445,7 +1594,6 @@ function SubagentsPanel({ sessionId, renderSlot, renderThread, openTransientTab
|
|
|
1445
1594
|
openTransientTab
|
|
1446
1595
|
]);
|
|
1447
1596
|
const shownRun = openRunId === void 0 ? void 0 : runs.find((run) => run.runId === openRunId);
|
|
1448
|
-
const launching = shelf.launch === void 0 ? void 0 : shelf.agents.find((agent) => agent.name === shelf.launch?.agent);
|
|
1449
1597
|
const stopping = (run) => stopRequested.includes(run.runId);
|
|
1450
1598
|
const runningTally = runs.filter((run) => run.state === "running" || run.state === "queued").length;
|
|
1451
1599
|
const doneTally = runs.filter((run) => run.state === "done").length;
|
|
@@ -1460,37 +1608,43 @@ function SubagentsPanel({ sessionId, renderSlot, renderThread, openTransientTab
|
|
|
1460
1608
|
className: "flex min-h-0 min-w-0 flex-1 overflow-hidden",
|
|
1461
1609
|
children: [
|
|
1462
1610
|
/* @__PURE__ */ jsxs("div", {
|
|
1463
|
-
className: "flex min-w-0 flex-1 flex-col overflow-y-auto px-3 py-3 sm:px-[26px] sm:py-[18px]",
|
|
1611
|
+
className: "@container flex min-w-0 flex-1 flex-col overflow-y-auto px-3 py-3 sm:px-[26px] sm:py-[18px]",
|
|
1464
1612
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
1465
1613
|
className: "flex flex-wrap items-center gap-x-3 gap-y-2 pb-3",
|
|
1466
1614
|
children: [
|
|
1467
1615
|
/* @__PURE__ */ jsx("span", {
|
|
1468
|
-
className: "text-lg font-semibold text-
|
|
1469
|
-
children: "
|
|
1616
|
+
className: "text-lg font-semibold text-po-hi",
|
|
1617
|
+
children: "Agents · this session"
|
|
1470
1618
|
}),
|
|
1471
1619
|
/* @__PURE__ */ jsx("span", { className: "hidden min-w-0 flex-1 sm:block" }),
|
|
1472
1620
|
/* @__PURE__ */ jsx("span", {
|
|
1473
1621
|
"data-testid": "subagents-tally",
|
|
1474
|
-
className: "order-3 w-full text-sm text-
|
|
1622
|
+
className: "order-3 w-full text-sm text-po-dim sm:order-none sm:w-auto",
|
|
1475
1623
|
children: runs.length === 0 ? "no runs yet" : `${runningTally} running · ${doneTally} done · ${failedTally} failed`
|
|
1476
1624
|
}),
|
|
1477
|
-
/* @__PURE__ */
|
|
1478
|
-
variant: "
|
|
1479
|
-
size: "xs",
|
|
1625
|
+
/* @__PURE__ */ jsx(Button, {
|
|
1626
|
+
variant: "primary",
|
|
1480
1627
|
className: "ml-auto sm:ml-0",
|
|
1481
1628
|
"data-testid": "subagents-launch",
|
|
1482
1629
|
title: "pick an agent from the catalog and launch it",
|
|
1483
1630
|
onClick: showCatalog,
|
|
1484
|
-
children:
|
|
1631
|
+
children: "New agent run"
|
|
1485
1632
|
})
|
|
1486
1633
|
]
|
|
1487
|
-
}), runs.length === 0 ? /* @__PURE__ */
|
|
1634
|
+
}), runs.length === 0 ? /* @__PURE__ */ jsxs("div", {
|
|
1488
1635
|
"data-testid": "subagents-empty",
|
|
1489
|
-
|
|
1490
|
-
|
|
1636
|
+
className: "text-base text-po-dim",
|
|
1637
|
+
children: [
|
|
1638
|
+
/* @__PURE__ */ jsx("p", { children: "No runs yet" }),
|
|
1639
|
+
/* @__PURE__ */ jsx("p", { children: "Start an agent run to get help with your work." }),
|
|
1640
|
+
/* @__PURE__ */ jsx("p", {
|
|
1641
|
+
className: "py-32 text-center text-sm",
|
|
1642
|
+
children: "Agent runs will appear here once you start one."
|
|
1643
|
+
})
|
|
1644
|
+
]
|
|
1491
1645
|
}) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
|
|
1492
1646
|
"data-testid": "subagents-grid",
|
|
1493
|
-
className: "grid grid-cols-
|
|
1647
|
+
className: "grid grid-cols-1 gap-4 @2xl:grid-cols-2",
|
|
1494
1648
|
children: sessionId === null ? null : runs.map((run) => /* @__PURE__ */ jsx(RunCard, {
|
|
1495
1649
|
sessionId,
|
|
1496
1650
|
run,
|
|
@@ -1507,14 +1661,20 @@ function SubagentsPanel({ sessionId, renderSlot, renderThread, openTransientTab
|
|
|
1507
1661
|
}
|
|
1508
1662
|
}, run.runId))
|
|
1509
1663
|
}), /* @__PURE__ */ jsx("span", {
|
|
1510
|
-
className: "pt-3 text-sm text-
|
|
1664
|
+
className: "pt-3 text-sm text-po-dim",
|
|
1511
1665
|
children: "click a card to open the run's thread · the card menu holds details, stop and clear · finished runs leave the grid after 10m"
|
|
1512
1666
|
})] })]
|
|
1513
1667
|
}),
|
|
1514
1668
|
sessionId !== null && shelf.open ? /* @__PURE__ */ jsx(AgentCatalogDrawer, {
|
|
1515
1669
|
sessionId,
|
|
1516
1670
|
onClose: () => closeCatalog(sessionId),
|
|
1517
|
-
|
|
1671
|
+
onSource: (agent) => {
|
|
1672
|
+
const tab = fileTabFor(agent.filePath);
|
|
1673
|
+
return tab ? () => {
|
|
1674
|
+
closeCatalog(sessionId);
|
|
1675
|
+
openTransientTab(tab);
|
|
1676
|
+
} : void 0;
|
|
1677
|
+
}
|
|
1518
1678
|
}) : null,
|
|
1519
1679
|
shownRun && sessionId !== null ? /* @__PURE__ */ jsx(RunDetailSheet, {
|
|
1520
1680
|
sessionId,
|
|
@@ -1523,17 +1683,7 @@ function SubagentsPanel({ sessionId, renderSlot, renderThread, openTransientTab
|
|
|
1523
1683
|
stopping: stopping(shownRun),
|
|
1524
1684
|
renderSlot,
|
|
1525
1685
|
onClose: () => openRun(sessionId, void 0)
|
|
1526
|
-
}) : null
|
|
1527
|
-
sessionId !== null && launching !== void 0 && shelf.launch !== void 0 ? /* @__PURE__ */ jsx(LaunchAgentDialog, {
|
|
1528
|
-
sessionId,
|
|
1529
|
-
agent: launching,
|
|
1530
|
-
cwd: shelf.cwd,
|
|
1531
|
-
models: shelf.models,
|
|
1532
|
-
fork: shelf.launch.fork,
|
|
1533
|
-
initialTask: shelf.task,
|
|
1534
|
-
onClose: () => closeLaunch(sessionId),
|
|
1535
|
-
onLaunched: () => closeCatalog(sessionId)
|
|
1536
|
-
}, launching.name) : null
|
|
1686
|
+
}) : null
|
|
1537
1687
|
]
|
|
1538
1688
|
});
|
|
1539
1689
|
}
|
|
@@ -1541,7 +1691,7 @@ function SubagentsPanel({ sessionId, renderSlot, renderThread, openTransientTab
|
|
|
1541
1691
|
function subagentsTab() {
|
|
1542
1692
|
return {
|
|
1543
1693
|
id: SUBAGENTS_TAB_ID,
|
|
1544
|
-
label: "
|
|
1694
|
+
label: "Agents",
|
|
1545
1695
|
panel: SubagentsPanel
|
|
1546
1696
|
};
|
|
1547
1697
|
}
|
|
@@ -1568,7 +1718,7 @@ var launch_agent_web_default = defineContextAction({
|
|
|
1568
1718
|
var agents_web_default = defineActivityGroup({
|
|
1569
1719
|
keys: "a r",
|
|
1570
1720
|
icon: UsersIcon,
|
|
1571
|
-
statusKey: "
|
|
1721
|
+
statusKey: "po-team-agents",
|
|
1572
1722
|
activeSource: {
|
|
1573
1723
|
subscribe(listener) {
|
|
1574
1724
|
const subscription = subagents.store.subscribe(listener);
|
|
@@ -1583,21 +1733,21 @@ var agents_web_default = defineActivityGroup({
|
|
|
1583
1733
|
});
|
|
1584
1734
|
//#endregion
|
|
1585
1735
|
//#region src/extensions/workspaces/sessions/(frontend)/channel/subagent-catalog.web.ts
|
|
1586
|
-
/** The agent catalog the session
|
|
1736
|
+
/** The agent catalog the session's server plugin publishes. The filename is the frame type. */
|
|
1587
1737
|
var subagent_catalog_web_default = defineChannelFile(subagentCatalogChannel);
|
|
1588
1738
|
//#endregion
|
|
1589
1739
|
//#region src/extensions/workspaces/sessions/(frontend)/channel/subagent-runs.web.ts
|
|
1590
|
-
/** The run graph the session
|
|
1740
|
+
/** The run graph the session's server plugin publishes. The filename is the frame type. */
|
|
1591
1741
|
var subagent_runs_web_default = defineChannelFile(subagentRunsChannel);
|
|
1592
1742
|
//#endregion
|
|
1593
1743
|
//#region src/extensions/workspaces/sessions/(frontend)/fill/_components/AgentsActivitySection.tsx
|
|
1594
1744
|
const TICK_MS = 1e4;
|
|
1595
|
-
const
|
|
1596
|
-
queued: "
|
|
1597
|
-
running: "
|
|
1598
|
-
done: "
|
|
1599
|
-
failed: "
|
|
1600
|
-
stopped: "
|
|
1745
|
+
const AVATAR_STATE = {
|
|
1746
|
+
queued: "waiting",
|
|
1747
|
+
running: "running",
|
|
1748
|
+
done: "done",
|
|
1749
|
+
failed: "failed",
|
|
1750
|
+
stopped: "done"
|
|
1601
1751
|
};
|
|
1602
1752
|
function elapsed(run, now) {
|
|
1603
1753
|
const end = run.endedAt ?? (isTerminalRun(run) ? run.lastUpdate : now);
|
|
@@ -1607,7 +1757,7 @@ function elapsed(run, now) {
|
|
|
1607
1757
|
function detail(run) {
|
|
1608
1758
|
if (run.state === "failed" && run.error) return run.error;
|
|
1609
1759
|
if (run.summary) return run.summary.split("\n").find((line) => line.trim() !== "") ?? "";
|
|
1610
|
-
return run.currentTool ?? run.tail.at(-1) ?? run.state;
|
|
1760
|
+
return run.currentTool ?? run.tail.at(-1) ?? (run.state === "running" ? "" : run.state);
|
|
1611
1761
|
}
|
|
1612
1762
|
/**
|
|
1613
1763
|
* The agents group's body in the activity dock: the session's runs, each a
|
|
@@ -1625,13 +1775,13 @@ function AgentsActivitySection({ sessionId, openTransientTab }) {
|
|
|
1625
1775
|
className: "flex flex-wrap items-center gap-x-4 gap-y-1",
|
|
1626
1776
|
children: [/* @__PURE__ */ jsx("p", {
|
|
1627
1777
|
"data-testid": "activity-summary-agents",
|
|
1628
|
-
className: "text-sm text-
|
|
1778
|
+
className: "text-sm text-po-dim",
|
|
1629
1779
|
children: "Idle"
|
|
1630
1780
|
}), /* @__PURE__ */ jsxs(Button, {
|
|
1631
1781
|
variant: "link",
|
|
1632
1782
|
size: "sm",
|
|
1633
1783
|
"data-testid": "activity-agents-launch",
|
|
1634
|
-
className: "h-auto gap-1 px-0 text-sm text-
|
|
1784
|
+
className: "h-auto gap-1 px-0 text-sm text-po-green",
|
|
1635
1785
|
onClick: () => {
|
|
1636
1786
|
if (sessionId === null) return;
|
|
1637
1787
|
openCatalog(sessionId);
|
|
@@ -1646,38 +1796,53 @@ function AgentsActivitySection({ sessionId, openTransientTab }) {
|
|
|
1646
1796
|
return /* @__PURE__ */ jsx("div", {
|
|
1647
1797
|
"data-testid": "activity-agent-runs",
|
|
1648
1798
|
className: "flex flex-col gap-0.5",
|
|
1649
|
-
children: runs.map((run) =>
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1799
|
+
children: runs.map((run) => {
|
|
1800
|
+
const who = agentDisplay(run);
|
|
1801
|
+
const description = detail(run);
|
|
1802
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
1803
|
+
variant: "ghost",
|
|
1804
|
+
size: "card",
|
|
1805
|
+
"data-testid": `activity-run-${run.runId}`,
|
|
1806
|
+
"data-run-state": run.state,
|
|
1807
|
+
title: "open this run's conversation",
|
|
1808
|
+
onClick: () => {
|
|
1809
|
+
if (sessionId === null) return;
|
|
1810
|
+
openTransientTab(agentThreadTab(run));
|
|
1811
|
+
},
|
|
1812
|
+
className: "min-w-0 gap-0.5 rounded-md px-1 py-1 hover:bg-po-panel",
|
|
1813
|
+
children: /* @__PURE__ */ jsxs("span", {
|
|
1814
|
+
className: "flex min-w-0 items-center gap-2",
|
|
1815
|
+
children: [
|
|
1816
|
+
/* @__PURE__ */ jsx(AgentAvatar, {
|
|
1817
|
+
name: who.name,
|
|
1818
|
+
seed: who.seed,
|
|
1819
|
+
state: AVATAR_STATE[run.state],
|
|
1820
|
+
size: "sm"
|
|
1821
|
+
}),
|
|
1822
|
+
/* @__PURE__ */ jsxs("span", {
|
|
1823
|
+
className: "flex min-w-0 flex-1 flex-col text-left",
|
|
1824
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
1825
|
+
className: "flex min-w-0 items-baseline gap-1.5",
|
|
1826
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
1827
|
+
className: "truncate text-base font-semibold text-po-hi",
|
|
1828
|
+
children: who.name
|
|
1829
|
+
}), who.role ? /* @__PURE__ */ jsx("span", {
|
|
1830
|
+
className: "truncate text-sm text-po-dim",
|
|
1831
|
+
children: who.role
|
|
1832
|
+
}) : null]
|
|
1833
|
+
}), description ? /* @__PURE__ */ jsx("span", {
|
|
1834
|
+
className: `truncate text-sm ${run.state === "failed" ? "text-po-red" : "text-po-dim"}`,
|
|
1835
|
+
children: description
|
|
1836
|
+
}) : null]
|
|
1837
|
+
}),
|
|
1838
|
+
/* @__PURE__ */ jsxs("span", {
|
|
1839
|
+
className: "shrink-0 text-sm text-po-dim",
|
|
1840
|
+
children: [elapsed(run, now), run.toolCount !== void 0 ? ` · ${run.toolCount} tools` : ""]
|
|
1841
|
+
})
|
|
1842
|
+
]
|
|
1843
|
+
})
|
|
1844
|
+
}, run.runId);
|
|
1845
|
+
})
|
|
1681
1846
|
});
|
|
1682
1847
|
}
|
|
1683
1848
|
//#endregion
|
|
@@ -1750,11 +1915,7 @@ function subagentCallDetail(args) {
|
|
|
1750
1915
|
const count = `${requests.length} agent${requests.length === 1 ? "" : "s"}`;
|
|
1751
1916
|
return agents.length > 0 ? `${count} · ${agents.join(", ")}` : count;
|
|
1752
1917
|
}
|
|
1753
|
-
case "status": return
|
|
1754
|
-
case "steer":
|
|
1755
|
-
case "stop":
|
|
1756
|
-
case "restore": return asString(args.id);
|
|
1757
|
-
case "suspended": return "runs";
|
|
1918
|
+
case "status": return args.id ? "run" : "fleet";
|
|
1758
1919
|
default: return "";
|
|
1759
1920
|
}
|
|
1760
1921
|
}
|
|
@@ -1808,8 +1969,11 @@ function records(value) {
|
|
|
1808
1969
|
function parts(values) {
|
|
1809
1970
|
return values.filter((value) => typeof value === "string" && value.trim() !== "").join(" · ");
|
|
1810
1971
|
}
|
|
1811
|
-
function
|
|
1812
|
-
|
|
1972
|
+
function stateAvatar(state) {
|
|
1973
|
+
if (state === "failed" || state === "error") return "failed";
|
|
1974
|
+
if (state === "running" || state === "starting") return "running";
|
|
1975
|
+
if (state === "queued") return "waiting";
|
|
1976
|
+
if (state === "complete" || state === "completed" || state === "stopped") return "done";
|
|
1813
1977
|
}
|
|
1814
1978
|
function stateTone(state) {
|
|
1815
1979
|
if (state === "failed" || state === "error") return "error";
|
|
@@ -1824,6 +1988,7 @@ function agentsView(value) {
|
|
|
1824
1988
|
const rows = records(value).map((agent, index) => ({
|
|
1825
1989
|
key: `${asString(agent.name)}-${index}`,
|
|
1826
1990
|
label: asString(agent.name),
|
|
1991
|
+
seed: asString(agent.name),
|
|
1827
1992
|
detail: preview(asString(agent.description)),
|
|
1828
1993
|
state: asString(agent.source),
|
|
1829
1994
|
tone: "idle"
|
|
@@ -1841,7 +2006,9 @@ function runView(value) {
|
|
|
1841
2006
|
return {
|
|
1842
2007
|
key: runId || `${asString(outcome.agent)}-${index}`,
|
|
1843
2008
|
label: asString(outcome.agent),
|
|
1844
|
-
|
|
2009
|
+
seed: asString(outcome.agent),
|
|
2010
|
+
avatar: runId ? "running" : "failed",
|
|
2011
|
+
detail: preview(runId ? asString(outcome.task) : asString(outcome.error)) || (runId ? "" : "unknown error"),
|
|
1845
2012
|
state: runId ? "started" : "failed",
|
|
1846
2013
|
tone: runId ? "ok" : "error"
|
|
1847
2014
|
};
|
|
@@ -1858,12 +2025,17 @@ function runView(value) {
|
|
|
1858
2025
|
function fleetView(value) {
|
|
1859
2026
|
const rows = records(value).map((job, index) => {
|
|
1860
2027
|
const state = asString(job.status) || "starting";
|
|
2028
|
+
const who = agentDisplay({
|
|
2029
|
+
agent: asString(job.agent),
|
|
2030
|
+
identity: asString(job.identity) || void 0
|
|
2031
|
+
});
|
|
1861
2032
|
return {
|
|
1862
2033
|
key: asString(job.runId) || `run-${index}`,
|
|
1863
|
-
label:
|
|
2034
|
+
label: who.name,
|
|
2035
|
+
seed: who.seed,
|
|
2036
|
+
avatar: stateAvatar(state),
|
|
1864
2037
|
detail: preview(parts([
|
|
1865
|
-
|
|
1866
|
-
job.agent,
|
|
2038
|
+
who.role,
|
|
1867
2039
|
job.currentTool,
|
|
1868
2040
|
job.activityState,
|
|
1869
2041
|
job.attentionReason,
|
|
@@ -1880,24 +2052,6 @@ function fleetView(value) {
|
|
|
1880
2052
|
tone: "idle"
|
|
1881
2053
|
};
|
|
1882
2054
|
}
|
|
1883
|
-
function suspendedView(value) {
|
|
1884
|
-
const rows = (isRecord(value) ? [value] : records(value)).map((run, index) => {
|
|
1885
|
-
const resumable = run.resumable;
|
|
1886
|
-
return {
|
|
1887
|
-
key: asString(run.runId) || `suspended-${index}`,
|
|
1888
|
-
label: asString(run.runId),
|
|
1889
|
-
detail: preview(parts([run.agent, firstLine(run.task)])),
|
|
1890
|
-
state: resumable === false ? "not resumable" : resumable === true ? "resumable" : "suspended",
|
|
1891
|
-
tone: resumable === false ? "error" : "idle"
|
|
1892
|
-
};
|
|
1893
|
-
});
|
|
1894
|
-
return {
|
|
1895
|
-
kind: "suspended",
|
|
1896
|
-
rows,
|
|
1897
|
-
summary: countSummary(rows.length, "suspended run"),
|
|
1898
|
-
tone: "idle"
|
|
1899
|
-
};
|
|
1900
|
-
}
|
|
1901
2055
|
function statusView(details) {
|
|
1902
2056
|
const runId = asString(details.runId);
|
|
1903
2057
|
const status = isRecord(details.status) ? details.status : void 0;
|
|
@@ -1905,16 +2059,22 @@ function statusView(details) {
|
|
|
1905
2059
|
if (!state) return {
|
|
1906
2060
|
kind: "status",
|
|
1907
2061
|
rows: [],
|
|
1908
|
-
summary:
|
|
2062
|
+
summary: "no status yet",
|
|
1909
2063
|
tone: "idle"
|
|
1910
2064
|
};
|
|
2065
|
+
const who = agentDisplay({
|
|
2066
|
+
agent: asString(status?.agent),
|
|
2067
|
+
identity: asString(status?.identity) || void 0
|
|
2068
|
+
});
|
|
1911
2069
|
return {
|
|
1912
2070
|
kind: "status",
|
|
1913
2071
|
rows: [{
|
|
1914
2072
|
key: runId,
|
|
1915
|
-
label:
|
|
2073
|
+
label: who.name,
|
|
2074
|
+
seed: who.seed,
|
|
2075
|
+
avatar: stateAvatar(state),
|
|
1916
2076
|
detail: preview(parts([
|
|
1917
|
-
|
|
2077
|
+
who.role,
|
|
1918
2078
|
status?.activityState,
|
|
1919
2079
|
status?.summary,
|
|
1920
2080
|
status?.error
|
|
@@ -1946,27 +2106,23 @@ function subagentResultView(details) {
|
|
|
1946
2106
|
if (isRecord(details.spawn) && Array.isArray(details.spawn.outcomes)) return runView(details.spawn.outcomes);
|
|
1947
2107
|
if (Array.isArray(details.runs)) return fleetView(details.runs);
|
|
1948
2108
|
if (Array.isArray(details.fleet)) return fleetView(details.fleet);
|
|
1949
|
-
if (details.
|
|
1950
|
-
if (isRecord(details.control)) return controlView(`stop requested for ${asString(details.runId)}`, "ok");
|
|
2109
|
+
if (isRecord(details.control)) return controlView("stop requested", "ok");
|
|
1951
2110
|
if (isRecord(details.steer)) {
|
|
1952
2111
|
const state = asString(details.steer.state);
|
|
1953
2112
|
return controlView(`steer ${state}${details.steer.message ? `: ${preview(asString(details.steer.message))}` : ""}`, state === "failed" ? "error" : "ok");
|
|
1954
2113
|
}
|
|
1955
|
-
if (isRecord(details.restore)) {
|
|
1956
|
-
const restore = details.restore;
|
|
1957
|
-
return controlView(`restored ${asString(restore.restoredFrom)} as ${asString(restore.runId)}`, "ok");
|
|
1958
|
-
}
|
|
1959
2114
|
if (typeof details.runId === "string") return statusView(details);
|
|
1960
2115
|
return null;
|
|
1961
2116
|
}
|
|
1962
|
-
/** The intercom call header: action, its target, and what is being said. */
|
|
1963
|
-
function intercomCallSummary(args) {
|
|
2117
|
+
/** The intercom call header: action, its resolved target name, and what is being said. */
|
|
2118
|
+
function intercomCallSummary(args, details) {
|
|
1964
2119
|
const action = asString(args.action);
|
|
2120
|
+
const toName = isRecord(details) ? asString(details.toName).trim() : "";
|
|
1965
2121
|
switch (action) {
|
|
1966
2122
|
case "send":
|
|
1967
2123
|
case "ask": return {
|
|
1968
2124
|
action,
|
|
1969
|
-
target: asString(args.to),
|
|
2125
|
+
target: toName || asString(args.to),
|
|
1970
2126
|
message: preview(asString(args.message))
|
|
1971
2127
|
};
|
|
1972
2128
|
case "reply": return {
|
|
@@ -1989,27 +2145,33 @@ function intercomCallSummary(args) {
|
|
|
1989
2145
|
function intercomOutcome(details) {
|
|
1990
2146
|
if (!isRecord(details)) return {
|
|
1991
2147
|
outcome: "none",
|
|
1992
|
-
who: ""
|
|
2148
|
+
who: "",
|
|
2149
|
+
reply: ""
|
|
1993
2150
|
};
|
|
1994
2151
|
if (details.delivered === true) return {
|
|
1995
2152
|
outcome: "delivered",
|
|
1996
|
-
who: asString(details.to)
|
|
2153
|
+
who: asString(details.to),
|
|
2154
|
+
reply: ""
|
|
1997
2155
|
};
|
|
1998
2156
|
if (details.state === "queued") return {
|
|
1999
2157
|
outcome: "queued",
|
|
2000
|
-
who: asString(details.to)
|
|
2158
|
+
who: asString(details.to),
|
|
2159
|
+
reply: ""
|
|
2001
2160
|
};
|
|
2002
2161
|
if (typeof details.reply === "string") return {
|
|
2003
2162
|
outcome: "answered",
|
|
2004
|
-
who: asString(details.from)
|
|
2163
|
+
who: asString(details.from),
|
|
2164
|
+
reply: details.reply
|
|
2005
2165
|
};
|
|
2006
2166
|
if (typeof details.requestId === "string" && typeof details.to === "string") return {
|
|
2007
2167
|
outcome: "replied",
|
|
2008
|
-
who: details.to
|
|
2168
|
+
who: details.to,
|
|
2169
|
+
reply: ""
|
|
2009
2170
|
};
|
|
2010
2171
|
return {
|
|
2011
2172
|
outcome: "none",
|
|
2012
|
-
who: ""
|
|
2173
|
+
who: "",
|
|
2174
|
+
reply: ""
|
|
2013
2175
|
};
|
|
2014
2176
|
}
|
|
2015
2177
|
//#endregion
|
|
@@ -2017,28 +2179,29 @@ function intercomOutcome(details) {
|
|
|
2017
2179
|
const OUTCOME_LINE = {
|
|
2018
2180
|
delivered: {
|
|
2019
2181
|
tone: "ok",
|
|
2020
|
-
text: "
|
|
2182
|
+
text: "Delivered"
|
|
2021
2183
|
},
|
|
2022
2184
|
queued: {
|
|
2023
2185
|
tone: "running",
|
|
2024
|
-
text: "
|
|
2186
|
+
text: "Queued, not yet confirmed"
|
|
2025
2187
|
},
|
|
2026
2188
|
replied: {
|
|
2027
2189
|
tone: "ok",
|
|
2028
|
-
text: "
|
|
2190
|
+
text: "Replied"
|
|
2029
2191
|
},
|
|
2030
2192
|
answered: {
|
|
2031
2193
|
tone: "ok",
|
|
2032
|
-
text: "
|
|
2194
|
+
text: "Answered"
|
|
2033
2195
|
}
|
|
2034
2196
|
};
|
|
2035
2197
|
/**
|
|
2036
|
-
* The intercom tool's timeline item
|
|
2037
|
-
*
|
|
2038
|
-
*
|
|
2198
|
+
* The intercom tool's timeline item, drawn as a conversation: what was said
|
|
2199
|
+
* as a bubble to the right, the answer as a bubble from its sender, and how
|
|
2200
|
+
* the delivery went beneath. Actions with no message (members, pending) show
|
|
2201
|
+
* the result text as before.
|
|
2039
2202
|
*/
|
|
2040
2203
|
function IntercomToolMessage({ args, result, output, running, isError }) {
|
|
2041
|
-
const summary = intercomCallSummary(args);
|
|
2204
|
+
const summary = intercomCallSummary(args, result?.details);
|
|
2042
2205
|
const collapsed = shapeResult(output, {
|
|
2043
2206
|
expanded: false,
|
|
2044
2207
|
isPartial: running,
|
|
@@ -2046,9 +2209,12 @@ function IntercomToolMessage({ args, result, output, running, isError }) {
|
|
|
2046
2209
|
});
|
|
2047
2210
|
const outcome = running || isError ? {
|
|
2048
2211
|
outcome: "none",
|
|
2049
|
-
who: ""
|
|
2212
|
+
who: "",
|
|
2213
|
+
reply: ""
|
|
2050
2214
|
} : intercomOutcome(result?.details);
|
|
2051
2215
|
const line = outcome.outcome === "none" ? null : OUTCOME_LINE[outcome.outcome];
|
|
2216
|
+
const message = typeof args.message === "string" ? args.message.trim() : "";
|
|
2217
|
+
const recipient = summary.action === "reply" ? outcome.who : summary.target;
|
|
2052
2218
|
return /* @__PURE__ */ jsx(MessageItem, {
|
|
2053
2219
|
tone: toolTone({
|
|
2054
2220
|
running,
|
|
@@ -2066,47 +2232,61 @@ function IntercomToolMessage({ args, result, output, running, isError }) {
|
|
|
2066
2232
|
children: /* @__PURE__ */ jsxs("span", {
|
|
2067
2233
|
"data-testid": "tool-call-intercom",
|
|
2068
2234
|
className: "flex min-w-0 flex-1 items-center gap-2",
|
|
2069
|
-
children: [
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
children: ["→ ", summary.target]
|
|
2077
|
-
}) : null,
|
|
2078
|
-
summary.message ? /* @__PURE__ */ jsx("span", {
|
|
2079
|
-
className: "min-w-0 truncate text-doom-dim",
|
|
2080
|
-
children: summary.message
|
|
2081
|
-
}) : null
|
|
2082
|
-
]
|
|
2235
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2236
|
+
className: "text-po-hi",
|
|
2237
|
+
children: summary.action
|
|
2238
|
+
}), recipient ? /* @__PURE__ */ jsxs("span", {
|
|
2239
|
+
className: "shrink-0 text-po-cyan",
|
|
2240
|
+
children: ["→ ", recipient]
|
|
2241
|
+
}) : null]
|
|
2083
2242
|
})
|
|
2084
2243
|
}), /* @__PURE__ */ jsxs(MessageItemBody, {
|
|
2085
2244
|
"data-testid": "tool-result-intercom",
|
|
2086
|
-
className: "flex flex-col gap-
|
|
2245
|
+
className: "flex flex-col gap-3",
|
|
2087
2246
|
children: [
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2247
|
+
message ? /* @__PURE__ */ jsxs("div", {
|
|
2248
|
+
"data-testid": "intercom-outgoing",
|
|
2249
|
+
className: "flex flex-col items-end gap-1",
|
|
2250
|
+
children: [
|
|
2251
|
+
/* @__PURE__ */ jsx("p", {
|
|
2252
|
+
className: "max-w-xl rounded-lg bg-po-tint-green px-3 py-2 text-base break-words whitespace-pre-wrap text-po-hi",
|
|
2253
|
+
children: message
|
|
2254
|
+
}),
|
|
2255
|
+
line && outcome.outcome !== "answered" ? /* @__PURE__ */ jsx(MessageItemStatus, {
|
|
2256
|
+
tone: line.tone,
|
|
2257
|
+
children: line.text
|
|
2258
|
+
}) : null,
|
|
2259
|
+
running ? /* @__PURE__ */ jsxs(MessageItemStatus, {
|
|
2260
|
+
tone: "running",
|
|
2261
|
+
children: ["Waiting for ", recipient || "a reply"]
|
|
2262
|
+
}) : null
|
|
2263
|
+
]
|
|
2091
2264
|
}) : null,
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2265
|
+
outcome.outcome === "answered" ? /* @__PURE__ */ jsxs("div", {
|
|
2266
|
+
"data-testid": "intercom-incoming",
|
|
2267
|
+
className: "flex items-start gap-2",
|
|
2268
|
+
children: [/* @__PURE__ */ jsx(AgentAvatar, {
|
|
2269
|
+
name: outcome.who,
|
|
2270
|
+
size: "sm"
|
|
2271
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
2272
|
+
className: "flex min-w-0 flex-col gap-1",
|
|
2273
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2274
|
+
className: "text-sm text-po-dim",
|
|
2275
|
+
children: outcome.who
|
|
2276
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
2277
|
+
className: "max-w-xl rounded-lg bg-po-rail px-3 py-2 text-base break-words whitespace-pre-wrap text-po-hi",
|
|
2278
|
+
children: outcome.reply
|
|
2279
|
+
})]
|
|
2280
|
+
})]
|
|
2095
2281
|
}) : null,
|
|
2096
|
-
isError ? /* @__PURE__ */ jsx(
|
|
2097
|
-
|
|
2098
|
-
|
|
2282
|
+
isError ? /* @__PURE__ */ jsx("p", {
|
|
2283
|
+
role: "alert",
|
|
2284
|
+
className: "rounded-md border border-po-edge-red bg-po-tint-red px-3 py-2 text-base text-po-red",
|
|
2285
|
+
children: shaped.lines.join("\n") || "Failed"
|
|
2099
2286
|
}) : null,
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
children:
|
|
2103
|
-
line.text,
|
|
2104
|
-
" ",
|
|
2105
|
-
/* @__PURE__ */ jsx("span", {
|
|
2106
|
-
className: "text-doom-cyan",
|
|
2107
|
-
children: outcome.who
|
|
2108
|
-
})
|
|
2109
|
-
]
|
|
2287
|
+
!message && !isError && shaped.lines.length > 0 ? /* @__PURE__ */ jsx("p", {
|
|
2288
|
+
className: `${expanded ? "whitespace-pre-wrap break-words" : "truncate"} text-po-dim`,
|
|
2289
|
+
children: shaped.lines.join("\n")
|
|
2110
2290
|
}) : null,
|
|
2111
2291
|
shaped.glyph === "more" ? /* @__PURE__ */ jsxs(MessageItemStatus, {
|
|
2112
2292
|
expands: true,
|
|
@@ -2155,18 +2335,25 @@ function SubagentRowLine({ row }) {
|
|
|
2155
2335
|
"data-testid": "tool-result-subagent-row",
|
|
2156
2336
|
className: "flex items-center gap-3 rounded-md px-2 py-1.5",
|
|
2157
2337
|
children: [
|
|
2158
|
-
/* @__PURE__ */ jsx(
|
|
2159
|
-
|
|
2160
|
-
|
|
2338
|
+
/* @__PURE__ */ jsx(AgentAvatar, {
|
|
2339
|
+
name: row.label,
|
|
2340
|
+
seed: row.seed,
|
|
2341
|
+
state: row.avatar
|
|
2161
2342
|
}),
|
|
2162
|
-
/* @__PURE__ */
|
|
2163
|
-
className: "min-w-0 flex-1
|
|
2164
|
-
children:
|
|
2343
|
+
/* @__PURE__ */ jsxs("span", {
|
|
2344
|
+
className: "flex min-w-0 flex-1 flex-col",
|
|
2345
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2346
|
+
className: "truncate text-base font-semibold text-po-hi",
|
|
2347
|
+
children: row.label
|
|
2348
|
+
}), row.detail ? /* @__PURE__ */ jsx("span", {
|
|
2349
|
+
className: "truncate text-sm text-po-dim",
|
|
2350
|
+
children: row.detail
|
|
2351
|
+
}) : null]
|
|
2165
2352
|
}),
|
|
2166
2353
|
row.state ? /* @__PURE__ */ jsx(StatusBadge, {
|
|
2167
2354
|
tone: ROW_BADGE[row.tone],
|
|
2168
2355
|
size: "md",
|
|
2169
|
-
className: ROW_BADGE[row.tone] === "neutral" ? "bg-
|
|
2356
|
+
className: ROW_BADGE[row.tone] === "neutral" ? "bg-po-rail" : void 0,
|
|
2170
2357
|
children: row.state
|
|
2171
2358
|
}) : null
|
|
2172
2359
|
]
|
|
@@ -2209,10 +2396,10 @@ function SubagentToolMessage({ args, result, output, running, isError, openTrans
|
|
|
2209
2396
|
"data-testid": "tool-call-subagent",
|
|
2210
2397
|
className: "flex min-w-0 flex-1 items-center gap-2",
|
|
2211
2398
|
children: [/* @__PURE__ */ jsx("span", {
|
|
2212
|
-
className: "text-
|
|
2399
|
+
className: "text-po-dim",
|
|
2213
2400
|
children: action
|
|
2214
2401
|
}), detail ? /* @__PURE__ */ jsx("span", {
|
|
2215
|
-
className: "min-w-0 truncate text-
|
|
2402
|
+
className: "min-w-0 truncate text-po-dim",
|
|
2216
2403
|
children: detail
|
|
2217
2404
|
}) : null]
|
|
2218
2405
|
})
|
|
@@ -2225,7 +2412,7 @@ function SubagentToolMessage({ args, result, output, running, isError, openTrans
|
|
|
2225
2412
|
children: rows.map((row) => /* @__PURE__ */ jsx(SubagentRowLine, { row }, row.key))
|
|
2226
2413
|
}) : null,
|
|
2227
2414
|
shaped && shaped.lines.length > 0 ? /* @__PURE__ */ jsx("pre", {
|
|
2228
|
-
className: `${expanded ? "whitespace-pre-wrap break-words" : "truncate"} text-
|
|
2415
|
+
className: `${expanded ? "whitespace-pre-wrap break-words" : "truncate"} text-po-dim`,
|
|
2229
2416
|
children: shaped.lines.join("\n")
|
|
2230
2417
|
}) : null,
|
|
2231
2418
|
!expanded && hiddenRows > 0 ? /* @__PURE__ */ jsxs(MessageItemStatus, {
|
|
@@ -2241,7 +2428,7 @@ function SubagentToolMessage({ args, result, output, running, isError, openTrans
|
|
|
2241
2428
|
children: [shaped.hidden, " more line(s)"]
|
|
2242
2429
|
}) : null,
|
|
2243
2430
|
/* @__PURE__ */ jsxs("div", {
|
|
2244
|
-
className: `flex flex-wrap items-center gap-x-4 gap-y-1 ${rows.length > 0 ? "mt-1 border-t border-
|
|
2431
|
+
className: `flex flex-wrap items-center gap-x-4 gap-y-1 ${rows.length > 0 ? "mt-1 border-t border-po-border-soft pt-2.5" : ""}`,
|
|
2245
2432
|
children: [view && view.summary ? /* @__PURE__ */ jsx(MessageItemStatus, {
|
|
2246
2433
|
"data-testid": "tool-result-subagent-summary",
|
|
2247
2434
|
tone: STATUS_TONE[view.tone],
|
|
@@ -2251,7 +2438,7 @@ function SubagentToolMessage({ args, result, output, running, isError, openTrans
|
|
|
2251
2438
|
size: "sm",
|
|
2252
2439
|
"data-testid": "tool-result-subagent-open",
|
|
2253
2440
|
onClick: () => openTransientTab(subagentsTab()),
|
|
2254
|
-
className: "h-auto gap-1 px-0 text-sm text-
|
|
2441
|
+
className: "h-auto gap-1 px-0 text-sm text-po-green",
|
|
2255
2442
|
children: ["Open subagents", /* @__PURE__ */ jsx(ArrowRightIcon, {
|
|
2256
2443
|
"aria-hidden": true,
|
|
2257
2444
|
className: "size-3.5"
|