agent-relay-server 0.10.20 → 0.10.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/docs/openapi.json +369 -70
- package/package.json +2 -2
- package/public/index.html +1188 -463
- package/src/db.ts +95 -19
- package/src/lifecycle-manager.ts +56 -1
- package/src/maintenance.ts +117 -0
- package/src/routes.ts +362 -24
package/public/index.html
CHANGED
|
@@ -11610,6 +11610,10 @@ var useRelayStore = create$1()(persist((set, get) => ({
|
|
|
11610
11610
|
health: null,
|
|
11611
11611
|
maintenanceJobs: [],
|
|
11612
11612
|
workspaces: [],
|
|
11613
|
+
workspaceGitState: {},
|
|
11614
|
+
workspaceMergePreview: {},
|
|
11615
|
+
workspaceDiff: {},
|
|
11616
|
+
workspaceOrphans: [],
|
|
11613
11617
|
taskEvents: [],
|
|
11614
11618
|
taskEventCache: {},
|
|
11615
11619
|
activityEvents: [],
|
|
@@ -12003,12 +12007,83 @@ var useRelayStore = create$1()(persist((set, get) => ({
|
|
|
12003
12007
|
set({ workspaces: await api("GET", "/workspaces") });
|
|
12004
12008
|
} catch {}
|
|
12005
12009
|
},
|
|
12010
|
+
async fetchWorkspaceGitState(workspaceId) {
|
|
12011
|
+
try {
|
|
12012
|
+
const state = await api("GET", "/workspaces/" + encodeURIComponent(workspaceId) + "/git-state");
|
|
12013
|
+
set((s) => ({ workspaceGitState: {
|
|
12014
|
+
...s.workspaceGitState,
|
|
12015
|
+
[workspaceId]: state
|
|
12016
|
+
} }));
|
|
12017
|
+
} catch (e) {
|
|
12018
|
+
set((s) => ({ workspaceGitState: {
|
|
12019
|
+
...s.workspaceGitState,
|
|
12020
|
+
[workspaceId]: {
|
|
12021
|
+
available: false,
|
|
12022
|
+
reason: e.message
|
|
12023
|
+
}
|
|
12024
|
+
} }));
|
|
12025
|
+
}
|
|
12026
|
+
},
|
|
12027
|
+
async fetchWorkspaceMergePreview(workspaceId) {
|
|
12028
|
+
try {
|
|
12029
|
+
const preview = await api("GET", "/workspaces/" + encodeURIComponent(workspaceId) + "/merge-preview");
|
|
12030
|
+
set((s) => ({ workspaceMergePreview: {
|
|
12031
|
+
...s.workspaceMergePreview,
|
|
12032
|
+
[workspaceId]: preview
|
|
12033
|
+
} }));
|
|
12034
|
+
} catch (e) {
|
|
12035
|
+
set((s) => ({ workspaceMergePreview: {
|
|
12036
|
+
...s.workspaceMergePreview,
|
|
12037
|
+
[workspaceId]: {
|
|
12038
|
+
available: false,
|
|
12039
|
+
reason: e.message
|
|
12040
|
+
}
|
|
12041
|
+
} }));
|
|
12042
|
+
}
|
|
12043
|
+
},
|
|
12044
|
+
async fetchWorkspaceDiff(workspaceId) {
|
|
12045
|
+
try {
|
|
12046
|
+
const diff = await api("GET", "/workspaces/" + encodeURIComponent(workspaceId) + "/diff");
|
|
12047
|
+
set((s) => ({ workspaceDiff: {
|
|
12048
|
+
...s.workspaceDiff,
|
|
12049
|
+
[workspaceId]: diff
|
|
12050
|
+
} }));
|
|
12051
|
+
} catch (e) {
|
|
12052
|
+
set((s) => ({ workspaceDiff: {
|
|
12053
|
+
...s.workspaceDiff,
|
|
12054
|
+
[workspaceId]: {
|
|
12055
|
+
available: false,
|
|
12056
|
+
reason: e.message
|
|
12057
|
+
}
|
|
12058
|
+
} }));
|
|
12059
|
+
}
|
|
12060
|
+
},
|
|
12061
|
+
async fetchWorkspaceOrphans() {
|
|
12062
|
+
try {
|
|
12063
|
+
set({ workspaceOrphans: (await api("GET", "/workspaces/orphans")).orphans ?? [] });
|
|
12064
|
+
} catch {}
|
|
12065
|
+
},
|
|
12066
|
+
async reclaimWorkspaceOrphan(orphan) {
|
|
12067
|
+
get().openConfirm("Reclaim Orphan Worktree", `Remove the orphaned worktree "${orphan.branch || orphan.worktreePath}" from disk? It has no live agent.`, async () => {
|
|
12068
|
+
try {
|
|
12069
|
+
await api("POST", "/workspaces/orphans/reclaim", {
|
|
12070
|
+
worktreePath: orphan.worktreePath,
|
|
12071
|
+
repoRoot: orphan.repoRoot,
|
|
12072
|
+
branch: orphan.branch
|
|
12073
|
+
});
|
|
12074
|
+
get().showNotification("Orphan reclaim dispatched");
|
|
12075
|
+
await Promise.all([get().fetchWorkspaceOrphans(), get().fetchActivityEvents()]);
|
|
12076
|
+
} catch (e) {
|
|
12077
|
+
get().showError("Reclaim Failed", e.message);
|
|
12078
|
+
}
|
|
12079
|
+
});
|
|
12080
|
+
},
|
|
12006
12081
|
async workspaceAction(workspaceId, action) {
|
|
12007
|
-
const label = action === "ready" ? "Mark ready" : action === "request-review" ? "Request review" : action === "merge-plan" ? "Mark merge planned" : action === "abandon" ? "Abandon" : "Cleanup";
|
|
12082
|
+
const label = action === "ready" ? "Mark ready" : action === "request-review" ? "Request review" : action === "merge-plan" ? "Mark merge planned" : action === "merge" ? "Merge" : action === "abandon" ? "Abandon" : "Cleanup";
|
|
12008
12083
|
const run = async () => {
|
|
12009
12084
|
try {
|
|
12010
12085
|
await api("POST", "/workspaces/" + encodeURIComponent(workspaceId) + "/actions", { action });
|
|
12011
|
-
get().showNotification(action === "cleanup" ? "Workspace cleanup requested" : `Workspace updated: ${label}`);
|
|
12086
|
+
get().showNotification(action === "cleanup" ? "Workspace cleanup requested" : action === "merge" ? "Workspace merge dispatched" : `Workspace updated: ${label}`);
|
|
12012
12087
|
await Promise.all([
|
|
12013
12088
|
get().fetchWorkspaces(),
|
|
12014
12089
|
get().fetchOrchestrators(),
|
|
@@ -12018,14 +12093,45 @@ var useRelayStore = create$1()(persist((set, get) => ({
|
|
|
12018
12093
|
get().showError("Workspace Action Failed", e.message);
|
|
12019
12094
|
}
|
|
12020
12095
|
};
|
|
12021
|
-
if (action === "cleanup" || action === "abandon") {
|
|
12096
|
+
if (action === "cleanup" || action === "abandon" || action === "merge") {
|
|
12022
12097
|
const workspace = get().workspaces.find((item) => item.id === workspaceId);
|
|
12023
12098
|
const target = workspace?.branch || workspace?.worktreePath || workspaceId;
|
|
12024
|
-
|
|
12099
|
+
if (action === "merge") {
|
|
12100
|
+
const preview = get().workspaceMergePreview[workspaceId];
|
|
12101
|
+
const mergeDetail = preview && preview.available !== false ? ` — ${preview.strategy === "pr" ? "opens a PR" : `rebases & fast-forwards into ${preview.baseRef || "base"}, then deletes the branch`}.` : " — lands the work and deletes the branch.";
|
|
12102
|
+
get().openConfirm("Merge Workspace", `Merge workspace "${target}"?${mergeDetail}`, run);
|
|
12103
|
+
return;
|
|
12104
|
+
}
|
|
12105
|
+
if (action === "cleanup") {
|
|
12106
|
+
await get().fetchWorkspaceGitState(workspaceId);
|
|
12107
|
+
const gs = get().workspaceGitState[workspaceId];
|
|
12108
|
+
let warn = "";
|
|
12109
|
+
if (gs && gs.available !== false && !gs.missing) {
|
|
12110
|
+
const ahead = gs.ahead ?? 0;
|
|
12111
|
+
const dirty = gs.dirtyCount ?? 0;
|
|
12112
|
+
if (ahead > 0 || dirty > 0) warn = ` ⚠ This destroys ${[ahead > 0 ? `${ahead} unmerged commit(s)` : "", dirty > 0 ? `${dirty} uncommitted change(s)` : ""].filter(Boolean).join(" and ")}.`;
|
|
12113
|
+
}
|
|
12114
|
+
get().openConfirm("Cleanup Workspace", `Remove the worktree for "${target}" on the host?${warn}`, run);
|
|
12115
|
+
return;
|
|
12116
|
+
}
|
|
12117
|
+
get().openConfirm("Abandon Workspace", `Abandon workspace "${target}"?`, run);
|
|
12025
12118
|
return;
|
|
12026
12119
|
}
|
|
12027
12120
|
await run();
|
|
12028
12121
|
},
|
|
12122
|
+
async purgeWorkspace(workspaceId) {
|
|
12123
|
+
const workspace = get().workspaces.find((item) => item.id === workspaceId);
|
|
12124
|
+
const target = workspace?.branch || workspace?.worktreePath || workspaceId;
|
|
12125
|
+
get().openConfirm("Purge Workspace Record", `Permanently remove the record for "${target}"? This only clears the dashboard row — it does not touch disk.`, async () => {
|
|
12126
|
+
try {
|
|
12127
|
+
await api("DELETE", "/workspaces/" + encodeURIComponent(workspaceId));
|
|
12128
|
+
get().showNotification("Workspace record purged");
|
|
12129
|
+
await Promise.all([get().fetchWorkspaces(), get().fetchActivityEvents()]);
|
|
12130
|
+
} catch (e) {
|
|
12131
|
+
get().showError("Purge Failed", e.message);
|
|
12132
|
+
}
|
|
12133
|
+
});
|
|
12134
|
+
},
|
|
12029
12135
|
async fetchAgentProfiles() {
|
|
12030
12136
|
try {
|
|
12031
12137
|
set({ agentProfiles: (await api("GET", "/agent-profiles")).map((entry) => entry.value) });
|
|
@@ -12227,6 +12333,8 @@ var useRelayStore = create$1()(persist((set, get) => ({
|
|
|
12227
12333
|
const msgs = [...s.messages, msg];
|
|
12228
12334
|
if (msgs.length > 500) msgs.splice(0, msgs.length - 500);
|
|
12229
12335
|
set({ messages: msgs });
|
|
12336
|
+
const peer = inboxPeer(msg);
|
|
12337
|
+
if (isHumanInboundMessage(msg) && peer && s.view === "chat" && s.selectedInboxThread === peer && !isDashboardHidden()) get().markInboxThreadReadTo(peer, msg.id);
|
|
12230
12338
|
return;
|
|
12231
12339
|
}
|
|
12232
12340
|
if (event === "message.queued" || event === "message.expired" || event === "message.delivery_updated" || event === "message.reaction_updated") {
|
|
@@ -13209,6 +13317,20 @@ var useRelayStore = create$1()(persist((set, get) => ({
|
|
|
13209
13317
|
}
|
|
13210
13318
|
});
|
|
13211
13319
|
},
|
|
13320
|
+
upgradeOrchestrator(orchId, targetVersion) {
|
|
13321
|
+
const to = targetVersion ? ` to v${targetVersion}` : " to match the relay";
|
|
13322
|
+
get().openConfirm("Upgrade Orchestrator", `Upgrade "${orchId}"${to}? It will install the new version and restart itself.`, async () => {
|
|
13323
|
+
try {
|
|
13324
|
+
await api("POST", "/orchestrators/" + encodeURIComponent(orchId) + "/actions", {
|
|
13325
|
+
action: "upgrade",
|
|
13326
|
+
...targetVersion ? { targetVersion } : {}
|
|
13327
|
+
});
|
|
13328
|
+
await Promise.all([get().fetchOrchestrators(), get().fetchActivityEvents()]);
|
|
13329
|
+
} catch (e) {
|
|
13330
|
+
get().showError("Upgrade Failed", e.message);
|
|
13331
|
+
}
|
|
13332
|
+
});
|
|
13333
|
+
},
|
|
13212
13334
|
deleteOrchestrator(orchId) {
|
|
13213
13335
|
get().openConfirm("Remove Orchestrator", `Remove orchestrator "${orchId}"?`, async () => {
|
|
13214
13336
|
try {
|
|
@@ -106939,8 +107061,8 @@ function TextWithLinks({ text, onOpenPath, onPreviewPath, onPreviewPathEnd, isPa
|
|
|
106939
107061
|
e.stopPropagation();
|
|
106940
107062
|
onOpenPath(part.path, part.line);
|
|
106941
107063
|
},
|
|
106942
|
-
onMouseEnter: () => onPreviewPath?.(part.path, part.line),
|
|
106943
|
-
onFocus: () => onPreviewPath?.(part.path, part.line),
|
|
107064
|
+
onMouseEnter: (e) => onPreviewPath?.(part.path, part.line, e.currentTarget.getBoundingClientRect()),
|
|
107065
|
+
onFocus: (e) => onPreviewPath?.(part.path, part.line, e.currentTarget.getBoundingClientRect()),
|
|
106944
107066
|
onMouseLeave: () => onPreviewPathEnd?.(),
|
|
106945
107067
|
onBlur: () => onPreviewPathEnd?.(),
|
|
106946
107068
|
title: resolvedTitle ? `Open ${resolvedTitle}` : "Open file",
|
|
@@ -117489,15 +117611,21 @@ var h$1 = 2, _$1 = 1, o$1 = class {
|
|
|
117489
117611
|
};
|
|
117490
117612
|
//#endregion
|
|
117491
117613
|
//#region src/components/ui/dialog.tsx
|
|
117614
|
+
var suppressGuardPop = false;
|
|
117492
117615
|
function useBackClose$1(open, onOpenChange) {
|
|
117493
117616
|
const pushedRef = import_react.useRef(false);
|
|
117494
117617
|
const cbRef = import_react.useRef(onOpenChange);
|
|
117495
117618
|
cbRef.current = onOpenChange;
|
|
117496
117619
|
import_react.useEffect(() => {
|
|
117497
117620
|
if (!open || !cbRef.current) return;
|
|
117621
|
+
suppressGuardPop = false;
|
|
117498
117622
|
window.history.pushState({ dialogGuard: true }, "");
|
|
117499
117623
|
pushedRef.current = true;
|
|
117500
117624
|
function onPop() {
|
|
117625
|
+
if (suppressGuardPop) {
|
|
117626
|
+
suppressGuardPop = false;
|
|
117627
|
+
return;
|
|
117628
|
+
}
|
|
117501
117629
|
if (pushedRef.current) {
|
|
117502
117630
|
pushedRef.current = false;
|
|
117503
117631
|
cbRef.current?.(false);
|
|
@@ -117508,6 +117636,7 @@ function useBackClose$1(open, onOpenChange) {
|
|
|
117508
117636
|
window.removeEventListener("popstate", onPop);
|
|
117509
117637
|
if (pushedRef.current) {
|
|
117510
117638
|
pushedRef.current = false;
|
|
117639
|
+
suppressGuardPop = true;
|
|
117511
117640
|
window.history.back();
|
|
117512
117641
|
}
|
|
117513
117642
|
};
|
|
@@ -119670,6 +119799,74 @@ function PendingAttachmentPreview({ item, onRemove }) {
|
|
|
119670
119799
|
})
|
|
119671
119800
|
})] });
|
|
119672
119801
|
}
|
|
119802
|
+
function FloatingFilePreview({ preview, error, onReadError, onMouseEnter, onMouseLeave }) {
|
|
119803
|
+
const { anchor } = preview;
|
|
119804
|
+
const gap = 8;
|
|
119805
|
+
const width = Math.min(560, window.innerWidth - 24);
|
|
119806
|
+
const height = Math.min(380, window.innerHeight - 24);
|
|
119807
|
+
const left = Math.max(12, Math.min(anchor.left, window.innerWidth - width - 12));
|
|
119808
|
+
return (0, import_react_dom.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
119809
|
+
className: "fixed z-50 flex flex-col overflow-hidden rounded-lg border border-border bg-background shadow-xl",
|
|
119810
|
+
style: {
|
|
119811
|
+
top: window.innerHeight - anchor.bottom >= height + gap ? anchor.bottom + gap : anchor.top - gap - height >= 12 ? anchor.top - gap - height : Math.max(12, window.innerHeight - height - 12),
|
|
119812
|
+
left,
|
|
119813
|
+
width,
|
|
119814
|
+
height
|
|
119815
|
+
},
|
|
119816
|
+
onMouseEnter,
|
|
119817
|
+
onMouseLeave,
|
|
119818
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
119819
|
+
className: "flex h-8 shrink-0 items-center gap-2 border-b border-border px-2.5",
|
|
119820
|
+
children: [
|
|
119821
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
119822
|
+
className: "min-w-0 flex-1 truncate text-[11px] font-medium text-muted-foreground",
|
|
119823
|
+
children: preview.path
|
|
119824
|
+
}),
|
|
119825
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
119826
|
+
className: "max-w-[12rem] truncate text-[11px] text-red-400",
|
|
119827
|
+
children: error
|
|
119828
|
+
}),
|
|
119829
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
119830
|
+
className: "shrink-0 text-[10px] text-muted-foreground/70",
|
|
119831
|
+
children: "click to pin"
|
|
119832
|
+
})
|
|
119833
|
+
]
|
|
119834
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
119835
|
+
className: "min-h-0 flex-1",
|
|
119836
|
+
children: preview.type === "directory" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DirectoryContent, {
|
|
119837
|
+
orchestratorId: preview.orchestratorId,
|
|
119838
|
+
selectedPath: preview.path,
|
|
119839
|
+
onReadError
|
|
119840
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileContent, {
|
|
119841
|
+
orchestratorId: preview.orchestratorId,
|
|
119842
|
+
selectedPath: preview.path,
|
|
119843
|
+
line: preview.line,
|
|
119844
|
+
onReadError
|
|
119845
|
+
})
|
|
119846
|
+
})]
|
|
119847
|
+
}), document.body);
|
|
119848
|
+
}
|
|
119849
|
+
function AddReaction({ open, onToggle, onReact }) {
|
|
119850
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
119851
|
+
className: "relative shrink-0",
|
|
119852
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
119853
|
+
type: "button",
|
|
119854
|
+
title: "Add reaction",
|
|
119855
|
+
onClick: onToggle,
|
|
119856
|
+
className: cn$1("inline-flex h-5 w-6 items-center justify-center rounded-full border border-border bg-popover text-muted-foreground shadow-sm transition hover:bg-muted hover:text-foreground", open ? "opacity-100" : "opacity-0 pointer-events-none md:group-hover/msg:opacity-100 md:group-hover/msg:pointer-events-auto"),
|
|
119857
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SmilePlus, { className: "h-3 w-3" })
|
|
119858
|
+
}), open && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
119859
|
+
className: "absolute bottom-full left-0 z-30 mb-1 flex gap-0.5 rounded-full border border-border bg-popover p-0.5 shadow-md",
|
|
119860
|
+
children: QUICK_REACTIONS.map((emoji) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
119861
|
+
type: "button",
|
|
119862
|
+
title: `React ${emoji}`,
|
|
119863
|
+
onClick: () => onReact(emoji),
|
|
119864
|
+
className: "inline-flex h-6 w-7 items-center justify-center rounded-full text-xs transition-colors hover:bg-muted",
|
|
119865
|
+
children: emoji
|
|
119866
|
+
}, emoji))
|
|
119867
|
+
})]
|
|
119868
|
+
});
|
|
119869
|
+
}
|
|
119673
119870
|
var MessageBubble = (0, import_react.memo)(function MessageBubble({ msg, peer, onOpenReferencedPath, onPreviewReferencedPath, onPreviewReferencedPathEnd }) {
|
|
119674
119871
|
const isOutbound = msg.from === HUMAN_AGENT_ID;
|
|
119675
119872
|
const reactToMessage = useRelayStore((s) => s.reactToMessage);
|
|
@@ -119707,9 +119904,9 @@ var MessageBubble = (0, import_react.memo)(function MessageBubble({ msg, peer, o
|
|
|
119707
119904
|
const absolute = resolvedReferencedPath(path);
|
|
119708
119905
|
onOpenReferencedPath?.(absolute, line);
|
|
119709
119906
|
}
|
|
119710
|
-
function previewReferencedPath(path, line) {
|
|
119907
|
+
function previewReferencedPath(path, line, anchor) {
|
|
119711
119908
|
const absolute = resolvedReferencedPath(path);
|
|
119712
|
-
onPreviewReferencedPath?.(absolute, line);
|
|
119909
|
+
onPreviewReferencedPath?.(absolute, line, anchor);
|
|
119713
119910
|
}
|
|
119714
119911
|
function handleReact(emoji) {
|
|
119715
119912
|
reactToMessage(msg, emoji);
|
|
@@ -119783,25 +119980,27 @@ var MessageBubble = (0, import_react.memo)(function MessageBubble({ msg, peer, o
|
|
|
119783
119980
|
})
|
|
119784
119981
|
]
|
|
119785
119982
|
}),
|
|
119786
|
-
!isReactionEvent(msg) && reactions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.
|
|
119787
|
-
className: cn$1("flex flex-wrap gap-0.5 -mt-1 relative z-10", isOutbound ? "justify-end pr-2" : "justify-start pl-2"),
|
|
119788
|
-
children:
|
|
119983
|
+
!isReactionEvent(msg) && reactions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
119984
|
+
className: cn$1("flex flex-wrap items-center gap-0.5 -mt-1 relative z-10", isOutbound ? "justify-end pr-2" : "justify-start pl-2"),
|
|
119985
|
+
children: [!isOutbound && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AddReaction, {
|
|
119986
|
+
open: showQuickReact,
|
|
119987
|
+
onToggle: () => setShowQuickReact((v) => !v),
|
|
119988
|
+
onReact: handleReact
|
|
119989
|
+
}), reactions.map((reaction) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
|
|
119789
119990
|
type: "button",
|
|
119790
119991
|
title: reaction.actors.join(", "),
|
|
119791
119992
|
onClick: () => handleReact(reaction.emoji),
|
|
119792
119993
|
className: cn$1("inline-flex h-5 items-center gap-0.5 rounded-full border px-1.5 text-[11px] shadow-sm transition-colors", reaction.mine ? "border-primary/40 bg-primary/10 text-primary" : "border-border bg-background hover:bg-muted text-foreground"),
|
|
119793
119994
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: reaction.emoji }), reaction.count > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: reaction.count })]
|
|
119794
|
-
}, reaction.emoji))
|
|
119995
|
+
}, reaction.emoji))]
|
|
119795
119996
|
}),
|
|
119796
|
-
!isReactionEvent(msg) && !isOutbound && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
119797
|
-
className:
|
|
119798
|
-
children:
|
|
119799
|
-
|
|
119800
|
-
|
|
119801
|
-
|
|
119802
|
-
|
|
119803
|
-
children: emoji
|
|
119804
|
-
}, emoji))
|
|
119997
|
+
!isReactionEvent(msg) && !isOutbound && reactions.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
119998
|
+
className: "absolute -bottom-2.5 left-1 z-20",
|
|
119999
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AddReaction, {
|
|
120000
|
+
open: showQuickReact,
|
|
120001
|
+
onToggle: () => setShowQuickReact((v) => !v),
|
|
120002
|
+
onReact: handleReact
|
|
120003
|
+
})
|
|
119805
120004
|
})
|
|
119806
120005
|
]
|
|
119807
120006
|
})
|
|
@@ -119961,6 +120160,7 @@ function ChatPanel({ threads, onBack, showBackButton }) {
|
|
|
119961
120160
|
const [terminalTarget, setTerminalTarget] = (0, import_react.useState)(null);
|
|
119962
120161
|
const [terminalOpening, setTerminalOpening] = (0, import_react.useState)(false);
|
|
119963
120162
|
const [filePreview, setFilePreview] = (0, import_react.useState)(null);
|
|
120163
|
+
const [floatingPreview, setFloatingPreview] = (0, import_react.useState)(null);
|
|
119964
120164
|
const [filePreviewError, setFilePreviewError] = (0, import_react.useState)("");
|
|
119965
120165
|
const filePreviewCloseTimer = (0, import_react.useRef)(null);
|
|
119966
120166
|
const filePreviewRequest = (0, import_react.useRef)(0);
|
|
@@ -120059,17 +120259,17 @@ function ChatPanel({ threads, onBack, showBackButton }) {
|
|
|
120059
120259
|
return null;
|
|
120060
120260
|
}
|
|
120061
120261
|
}, [orchestrators]);
|
|
120062
|
-
const previewReferencedFile = (0, import_react.useCallback)((path, line) => {
|
|
120063
|
-
if (!supportsSideFilePreview()) return;
|
|
120262
|
+
const previewReferencedFile = (0, import_react.useCallback)((path, line, anchor) => {
|
|
120263
|
+
if (!supportsSideFilePreview() || !anchor) return;
|
|
120064
120264
|
const request = ++filePreviewRequest.current;
|
|
120065
120265
|
resolveReferencedFile(path).then((info) => {
|
|
120066
120266
|
if (filePreviewRequest.current !== request) return;
|
|
120067
120267
|
if (!info) return;
|
|
120068
120268
|
clearFilePreviewCloseTimer();
|
|
120069
|
-
|
|
120269
|
+
setFloatingPreview({
|
|
120070
120270
|
...info,
|
|
120071
120271
|
line: line || 0,
|
|
120072
|
-
|
|
120272
|
+
anchor
|
|
120073
120273
|
});
|
|
120074
120274
|
setFilePreviewError("");
|
|
120075
120275
|
});
|
|
@@ -120078,7 +120278,7 @@ function ChatPanel({ threads, onBack, showBackButton }) {
|
|
|
120078
120278
|
filePreviewRequest.current += 1;
|
|
120079
120279
|
clearFilePreviewCloseTimer();
|
|
120080
120280
|
filePreviewCloseTimer.current = window.setTimeout(() => {
|
|
120081
|
-
|
|
120281
|
+
setFloatingPreview(null);
|
|
120082
120282
|
}, 250);
|
|
120083
120283
|
}, [clearFilePreviewCloseTimer]);
|
|
120084
120284
|
const openReferencedFile = (0, import_react.useCallback)((path, line) => {
|
|
@@ -120088,11 +120288,12 @@ function ChatPanel({ threads, onBack, showBackButton }) {
|
|
|
120088
120288
|
return;
|
|
120089
120289
|
}
|
|
120090
120290
|
if (supportsSideFilePreview()) {
|
|
120291
|
+
filePreviewRequest.current += 1;
|
|
120091
120292
|
clearFilePreviewCloseTimer();
|
|
120293
|
+
setFloatingPreview(null);
|
|
120092
120294
|
setFilePreview({
|
|
120093
120295
|
...info,
|
|
120094
|
-
line: line || 0
|
|
120095
|
-
pinned: true
|
|
120296
|
+
line: line || 0
|
|
120096
120297
|
});
|
|
120097
120298
|
setFilePreviewError("");
|
|
120098
120299
|
return;
|
|
@@ -120117,8 +120318,6 @@ function ChatPanel({ threads, onBack, showBackButton }) {
|
|
|
120117
120318
|
showError
|
|
120118
120319
|
]);
|
|
120119
120320
|
function closeFilePreview() {
|
|
120120
|
-
filePreviewRequest.current += 1;
|
|
120121
|
-
clearFilePreviewCloseTimer();
|
|
120122
120321
|
setFilePreview(null);
|
|
120123
120322
|
setFilePreviewError("");
|
|
120124
120323
|
}
|
|
@@ -120209,372 +120408,380 @@ function ChatPanel({ threads, onBack, showBackButton }) {
|
|
|
120209
120408
|
children: "Select an agent to start chatting"
|
|
120210
120409
|
})]
|
|
120211
120410
|
});
|
|
120212
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
120213
|
-
|
|
120214
|
-
|
|
120215
|
-
|
|
120216
|
-
|
|
120217
|
-
|
|
120218
|
-
|
|
120219
|
-
|
|
120220
|
-
|
|
120221
|
-
|
|
120222
|
-
|
|
120223
|
-
|
|
120224
|
-
|
|
120225
|
-
|
|
120226
|
-
|
|
120227
|
-
|
|
120228
|
-
|
|
120229
|
-
|
|
120230
|
-
|
|
120231
|
-
|
|
120232
|
-
|
|
120233
|
-
|
|
120234
|
-
|
|
120235
|
-
|
|
120236
|
-
|
|
120237
|
-
agent,
|
|
120238
|
-
|
|
120239
|
-
|
|
120240
|
-
|
|
120241
|
-
|
|
120242
|
-
|
|
120243
|
-
|
|
120244
|
-
|
|
120245
|
-
|
|
120246
|
-
|
|
120247
|
-
|
|
120248
|
-
|
|
120249
|
-
|
|
120250
|
-
|
|
120251
|
-
|
|
120252
|
-
|
|
120411
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
120412
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
120413
|
+
className: "flex h-full min-w-0",
|
|
120414
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
120415
|
+
className: "flex h-full min-w-0 flex-1 flex-col",
|
|
120416
|
+
children: [
|
|
120417
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
120418
|
+
className: "flex items-center justify-between px-3 md:px-4 py-2.5 md:py-3 border-b border-border shrink-0",
|
|
120419
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
120420
|
+
className: "flex items-center gap-2 md:gap-2.5 min-w-0",
|
|
120421
|
+
children: [
|
|
120422
|
+
showBackButton && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120423
|
+
variant: "ghost",
|
|
120424
|
+
size: "icon-sm",
|
|
120425
|
+
onClick: onBack,
|
|
120426
|
+
className: "shrink-0 -ml-1",
|
|
120427
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArrowLeft, { className: "w-4 h-4" })
|
|
120428
|
+
}),
|
|
120429
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
|
|
120430
|
+
type: "button",
|
|
120431
|
+
className: "flex items-center gap-2 md:gap-2.5 min-w-0 hover:opacity-80 transition-opacity",
|
|
120432
|
+
onClick: () => agent && openAgentDetail(agent),
|
|
120433
|
+
disabled: !agent,
|
|
120434
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
120435
|
+
className: "relative shrink-0",
|
|
120436
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AgentTypeIcon, { agent }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusDot, {
|
|
120437
|
+
agent,
|
|
120438
|
+
now,
|
|
120439
|
+
className: "absolute -bottom-0.5 -right-0.5 w-2 h-2"
|
|
120440
|
+
})]
|
|
120441
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
120442
|
+
className: "min-w-0 text-left",
|
|
120443
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
120444
|
+
className: "text-sm font-medium truncate",
|
|
120445
|
+
children: agent ? displayName(agent) : selectedInboxThread
|
|
120446
|
+
}), agent && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
|
|
120447
|
+
className: "text-xs text-muted-foreground truncate",
|
|
120448
|
+
children: [
|
|
120449
|
+
blockedState ? `blocked: ${blockedState.label}` : agent.status,
|
|
120450
|
+
agent.machine && ` · ${agent.machine}`,
|
|
120451
|
+
typeof agent.meta?.cwd === "string" && agent.meta.cwd && ` · ${shortPath$1(agent.meta.cwd, 1)}`
|
|
120452
|
+
]
|
|
120453
|
+
})]
|
|
120253
120454
|
})]
|
|
120254
|
-
})
|
|
120255
|
-
|
|
120256
|
-
|
|
120257
|
-
|
|
120258
|
-
|
|
120259
|
-
|
|
120260
|
-
|
|
120261
|
-
|
|
120262
|
-
|
|
120263
|
-
|
|
120264
|
-
|
|
120265
|
-
|
|
120266
|
-
|
|
120267
|
-
|
|
120268
|
-
|
|
120269
|
-
|
|
120270
|
-
|
|
120271
|
-
|
|
120272
|
-
|
|
120273
|
-
|
|
120274
|
-
|
|
120275
|
-
|
|
120276
|
-
|
|
120277
|
-
|
|
120278
|
-
|
|
120279
|
-
|
|
120280
|
-
|
|
120281
|
-
|
|
120282
|
-
|
|
120283
|
-
|
|
120284
|
-
|
|
120285
|
-
|
|
120286
|
-
|
|
120287
|
-
|
|
120288
|
-
|
|
120289
|
-
|
|
120290
|
-
|
|
120291
|
-
|
|
120292
|
-
|
|
120293
|
-
|
|
120294
|
-
|
|
120295
|
-
|
|
120296
|
-
|
|
120297
|
-
|
|
120298
|
-
|
|
120299
|
-
|
|
120300
|
-
|
|
120301
|
-
|
|
120302
|
-
|
|
120303
|
-
|
|
120304
|
-
|
|
120305
|
-
|
|
120306
|
-
|
|
120307
|
-
|
|
120308
|
-
|
|
120309
|
-
|
|
120310
|
-
|
|
120311
|
-
|
|
120312
|
-
|
|
120313
|
-
|
|
120314
|
-
|
|
120315
|
-
|
|
120316
|
-
|
|
120317
|
-
|
|
120455
|
+
}),
|
|
120456
|
+
agent && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AgentRuntimeChips, {
|
|
120457
|
+
agent,
|
|
120458
|
+
compact: true,
|
|
120459
|
+
className: "hidden md:flex shrink-0"
|
|
120460
|
+
}),
|
|
120461
|
+
agent?.context && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextRing, { utilization: agent.context.utilization }),
|
|
120462
|
+
thread?.attention.unread ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Badge$1, {
|
|
120463
|
+
className: "bg-red-500/20 text-red-400 text-xs shrink-0 hidden sm:flex",
|
|
120464
|
+
children: [thread.attention.unread, " unread"]
|
|
120465
|
+
}) : null
|
|
120466
|
+
]
|
|
120467
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
120468
|
+
className: "flex items-center gap-0.5 md:gap-1 shrink-0",
|
|
120469
|
+
children: agent && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
120470
|
+
canOpenTerminal && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120471
|
+
variant: "ghost",
|
|
120472
|
+
size: "icon-sm",
|
|
120473
|
+
className: "hidden sm:inline-flex",
|
|
120474
|
+
disabled: terminalOpening,
|
|
120475
|
+
title: "Terminal",
|
|
120476
|
+
onClick: () => void handleOpenTerminal(),
|
|
120477
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Terminal, { className: "w-3.5 h-3.5" })
|
|
120478
|
+
}),
|
|
120479
|
+
canCompact && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120480
|
+
variant: "ghost",
|
|
120481
|
+
size: "icon-sm",
|
|
120482
|
+
className: "hidden sm:inline-flex",
|
|
120483
|
+
title: "Compact",
|
|
120484
|
+
onClick: () => openConfirm("Compact Agent", `Compact context for ${displayName(agent)}?`, () => doAgentAction(agent, "compact")),
|
|
120485
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Minimize2, { className: "w-3.5 h-3.5" })
|
|
120486
|
+
}),
|
|
120487
|
+
canClearContext && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120488
|
+
variant: "ghost",
|
|
120489
|
+
size: "icon-sm",
|
|
120490
|
+
className: "hidden sm:inline-flex",
|
|
120491
|
+
title: "Clear context",
|
|
120492
|
+
onClick: () => openConfirm("Clear Context", `Clear context for ${displayName(agent)}?`, () => doAgentAction(agent, "clearContext")),
|
|
120493
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Eraser, { className: "w-3.5 h-3.5" })
|
|
120494
|
+
}),
|
|
120495
|
+
canShutdown && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120496
|
+
variant: "ghost",
|
|
120497
|
+
size: "icon-sm",
|
|
120498
|
+
className: "hidden sm:inline-flex",
|
|
120499
|
+
title: "Shutdown",
|
|
120500
|
+
onClick: () => openConfirm("Shutdown Agent", `Shutdown ${displayName(agent)}?`, () => doAgentAction(agent, "shutdown")),
|
|
120501
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Power, { className: "w-3.5 h-3.5" })
|
|
120502
|
+
}),
|
|
120503
|
+
agent && typeof agent.meta?.cwd === "string" && agent.meta.cwd && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120504
|
+
variant: "ghost",
|
|
120505
|
+
size: "icon-sm",
|
|
120506
|
+
className: "hidden sm:inline-flex",
|
|
120507
|
+
title: `Open ${agent.meta.cwd} in Files`,
|
|
120508
|
+
onClick: () => void openFilesForAgent(agent),
|
|
120509
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FolderOpen, { className: "w-3.5 h-3.5" })
|
|
120510
|
+
}),
|
|
120511
|
+
agent && thread && thread.messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120512
|
+
variant: "ghost",
|
|
120513
|
+
size: "icon-sm",
|
|
120514
|
+
className: "hidden sm:inline-flex",
|
|
120515
|
+
title: "Fork — spawn new agent with this chat history",
|
|
120516
|
+
onClick: () => forkFromAgent(agent.id, thread.messages),
|
|
120517
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitFork, { className: "w-3.5 h-3.5" })
|
|
120518
|
+
}),
|
|
120519
|
+
thread && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120520
|
+
variant: "ghost",
|
|
120521
|
+
size: "icon-sm",
|
|
120522
|
+
className: "hidden sm:inline-flex",
|
|
120523
|
+
title: "Mark unread",
|
|
120524
|
+
onClick: () => markInboxThreadUnread(selectedInboxThread),
|
|
120525
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MailX, { className: "w-3.5 h-3.5" })
|
|
120526
|
+
}),
|
|
120527
|
+
thread && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120528
|
+
variant: "ghost",
|
|
120529
|
+
size: "icon-sm",
|
|
120530
|
+
className: "hidden sm:inline-flex",
|
|
120531
|
+
title: "Mark read",
|
|
120532
|
+
onClick: () => markInboxThreadRead(thread.peer, thread.messages),
|
|
120533
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MailOpen, { className: "w-3.5 h-3.5" })
|
|
120534
|
+
}),
|
|
120535
|
+
exportableThread && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120536
|
+
variant: "ghost",
|
|
120537
|
+
size: "icon-sm",
|
|
120538
|
+
className: "hidden sm:inline-flex",
|
|
120539
|
+
title: "Export thread",
|
|
120540
|
+
onClick: () => exportThread({
|
|
120541
|
+
...exportableThread,
|
|
120542
|
+
importedHistory
|
|
120543
|
+
}, "json"),
|
|
120544
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Download, { className: "w-3.5 h-3.5" })
|
|
120545
|
+
}),
|
|
120546
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenu, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DropdownMenuTrigger, {
|
|
120547
|
+
asChild: true,
|
|
120548
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120549
|
+
variant: "ghost",
|
|
120550
|
+
size: "icon-sm",
|
|
120551
|
+
className: "sm:hidden",
|
|
120552
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Ellipsis, { className: "w-3.5 h-3.5" })
|
|
120553
|
+
})
|
|
120554
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuContent, {
|
|
120555
|
+
align: "end",
|
|
120556
|
+
children: [
|
|
120557
|
+
canOpenTerminal && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuItem, {
|
|
120558
|
+
disabled: terminalOpening,
|
|
120559
|
+
onClick: () => void handleOpenTerminal(),
|
|
120560
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Terminal, { className: "w-3.5 h-3.5" }), "Terminal"]
|
|
120561
|
+
}),
|
|
120562
|
+
canCompact && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuItem, {
|
|
120563
|
+
onClick: () => openConfirm("Compact Agent", `Compact context for ${displayName(agent)}?`, () => doAgentAction(agent, "compact")),
|
|
120564
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Minimize2, { className: "w-3.5 h-3.5" }), "Compact"]
|
|
120565
|
+
}),
|
|
120566
|
+
canClearContext && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuItem, {
|
|
120567
|
+
onClick: () => openConfirm("Clear Context", `Clear context for ${displayName(agent)}?`, () => doAgentAction(agent, "clearContext")),
|
|
120568
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Eraser, { className: "w-3.5 h-3.5" }), "Clear Context"]
|
|
120569
|
+
}),
|
|
120570
|
+
canShutdown && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuItem, {
|
|
120571
|
+
onClick: () => openConfirm("Shutdown Agent", `Shutdown ${displayName(agent)}?`, () => doAgentAction(agent, "shutdown")),
|
|
120572
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Power, { className: "w-3.5 h-3.5" }), "Shutdown"]
|
|
120573
|
+
}),
|
|
120574
|
+
agent && typeof agent.meta?.cwd === "string" && agent.meta.cwd && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuItem, {
|
|
120575
|
+
onClick: () => void openFilesForAgent(agent),
|
|
120576
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FolderOpen, { className: "w-3.5 h-3.5" }), "Open Files"]
|
|
120577
|
+
}),
|
|
120578
|
+
agent && thread && thread.messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuItem, {
|
|
120579
|
+
onClick: () => forkFromAgent(agent.id, thread.messages),
|
|
120580
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitFork, { className: "w-3.5 h-3.5" }), "Fork"]
|
|
120581
|
+
}),
|
|
120582
|
+
(canOpenTerminal || canCompact || canClearContext || canShutdown) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DropdownMenuSeparator, {}),
|
|
120583
|
+
thread && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuItem, {
|
|
120584
|
+
onClick: () => markInboxThreadUnread(selectedInboxThread),
|
|
120585
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MailX, { className: "w-3.5 h-3.5" }), "Mark Unread"]
|
|
120586
|
+
}),
|
|
120587
|
+
thread && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuItem, {
|
|
120588
|
+
onClick: () => markInboxThreadRead(thread.peer, thread.messages),
|
|
120589
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MailOpen, { className: "w-3.5 h-3.5" }), "Mark Read"]
|
|
120590
|
+
}),
|
|
120591
|
+
exportableThread && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuItem, {
|
|
120592
|
+
onClick: () => exportThread({
|
|
120593
|
+
...exportableThread,
|
|
120594
|
+
importedHistory
|
|
120595
|
+
}, "json"),
|
|
120596
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Download, { className: "w-3.5 h-3.5" }), "Download"]
|
|
120597
|
+
})
|
|
120598
|
+
]
|
|
120599
|
+
})] })
|
|
120600
|
+
] })
|
|
120601
|
+
})]
|
|
120602
|
+
}),
|
|
120603
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
120604
|
+
ref: pinnedScroll.ref,
|
|
120605
|
+
onScroll: pinnedScroll.onScroll,
|
|
120606
|
+
className: "flex-1 overflow-y-auto px-3 md:px-4 py-3 md:py-4",
|
|
120607
|
+
style: { minHeight: 0 },
|
|
120608
|
+
children: timeline.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
120609
|
+
className: "flex flex-col items-center justify-center h-full text-center",
|
|
120610
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessageSquare, { className: "w-8 h-8 text-zinc-600 mb-2" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
120611
|
+
className: "text-xs text-muted-foreground",
|
|
120612
|
+
children: "No messages yet"
|
|
120613
|
+
})]
|
|
120614
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
120615
|
+
timeline.map((entry) => {
|
|
120616
|
+
if (entry.type === "message") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessageBubble, {
|
|
120617
|
+
msg: entry.msg,
|
|
120618
|
+
peer: selectedInboxThread,
|
|
120619
|
+
onOpenReferencedPath: openReferencedFile,
|
|
120620
|
+
onPreviewReferencedPath: previewReferencedFile,
|
|
120621
|
+
onPreviewReferencedPathEnd: scheduleCloseReferencedFilePreview
|
|
120622
|
+
}, entry.msg.id);
|
|
120623
|
+
if (entry.type === "import-boundary") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImportedHistoryMarker, { history: entry.history }, `import-${entry.history.id}`);
|
|
120624
|
+
if (entry.type === "imported-message") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImportedMessageBubble, {
|
|
120625
|
+
entry: entry.entry,
|
|
120626
|
+
sourceLabel: entry.history.sourceAgentLabel || entry.history.sourcePeerId
|
|
120627
|
+
}, `import-${entry.history.id}-${entry.entry.originalMessageId}-${entry.entry.position}`);
|
|
120628
|
+
if (entry.type === "status") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusMarker, { event: entry.event }, entry.event.id);
|
|
120629
|
+
if (entry.type === "date") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DateSeparator, { date: entry.date }, `d-${entry.date}`);
|
|
120630
|
+
if (entry.type === "created") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CreatedMarker, { timestamp: entry.timestamp }, "created");
|
|
120631
|
+
return null;
|
|
120318
120632
|
}),
|
|
120319
|
-
|
|
120320
|
-
|
|
120321
|
-
|
|
120322
|
-
className: "hidden sm:inline-flex",
|
|
120323
|
-
title: "Mark unread",
|
|
120324
|
-
onClick: () => markInboxThreadUnread(selectedInboxThread),
|
|
120325
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MailX, { className: "w-3.5 h-3.5" })
|
|
120633
|
+
pendingApproval && agent && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PermissionRequestBubble, {
|
|
120634
|
+
agentId: agent.id,
|
|
120635
|
+
approval: pendingApproval
|
|
120326
120636
|
}),
|
|
120327
|
-
|
|
120328
|
-
|
|
120329
|
-
|
|
120330
|
-
|
|
120331
|
-
|
|
120332
|
-
|
|
120333
|
-
|
|
120637
|
+
agent?.status === "busy" && !pendingApproval && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BusyIndicator, { blockedLabel: blockedState?.label })
|
|
120638
|
+
] })
|
|
120639
|
+
}),
|
|
120640
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
120641
|
+
className: cn$1("shrink-0 border-t border-border px-3 md:px-4 py-2.5 md:py-3 safe-area-bottom", dragActive && "bg-primary/5 ring-1 ring-primary/40"),
|
|
120642
|
+
onDragOver: (e) => {
|
|
120643
|
+
e.preventDefault();
|
|
120644
|
+
setDragActive(true);
|
|
120645
|
+
},
|
|
120646
|
+
onDragLeave: () => setDragActive(false),
|
|
120647
|
+
onDrop: (e) => {
|
|
120648
|
+
e.preventDefault();
|
|
120649
|
+
setDragActive(false);
|
|
120650
|
+
uploadFiles(e.dataTransfer.files);
|
|
120651
|
+
},
|
|
120652
|
+
children: [
|
|
120653
|
+
pendingAttachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
120654
|
+
className: "mb-2 grid gap-2 sm:grid-cols-2",
|
|
120655
|
+
children: pendingAttachments.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PendingAttachmentPreview, {
|
|
120656
|
+
item,
|
|
120657
|
+
onRemove: () => removePendingAttachment(item.id)
|
|
120658
|
+
}, item.id))
|
|
120334
120659
|
}),
|
|
120335
|
-
|
|
120336
|
-
|
|
120337
|
-
|
|
120338
|
-
|
|
120339
|
-
|
|
120340
|
-
|
|
120341
|
-
|
|
120342
|
-
|
|
120343
|
-
}
|
|
120344
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Download, { className: "w-3.5 h-3.5" })
|
|
120660
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", {
|
|
120661
|
+
ref: fileInputRef,
|
|
120662
|
+
type: "file",
|
|
120663
|
+
multiple: true,
|
|
120664
|
+
className: "hidden",
|
|
120665
|
+
onChange: (e) => {
|
|
120666
|
+
if (e.target.files) uploadFiles(e.target.files);
|
|
120667
|
+
e.currentTarget.value = "";
|
|
120668
|
+
}
|
|
120345
120669
|
}),
|
|
120346
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
120347
|
-
|
|
120348
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120349
|
-
variant: "ghost",
|
|
120350
|
-
size: "icon-sm",
|
|
120351
|
-
className: "sm:hidden",
|
|
120352
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Ellipsis, { className: "w-3.5 h-3.5" })
|
|
120353
|
-
})
|
|
120354
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuContent, {
|
|
120355
|
-
align: "end",
|
|
120670
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
120671
|
+
className: "hidden md:flex items-end gap-2",
|
|
120356
120672
|
children: [
|
|
120357
|
-
|
|
120358
|
-
|
|
120359
|
-
|
|
120360
|
-
|
|
120361
|
-
|
|
120362
|
-
|
|
120363
|
-
|
|
120364
|
-
children:
|
|
120365
|
-
}),
|
|
120366
|
-
canClearContext && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuItem, {
|
|
120367
|
-
onClick: () => openConfirm("Clear Context", `Clear context for ${displayName(agent)}?`, () => doAgentAction(agent, "clearContext")),
|
|
120368
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Eraser, { className: "w-3.5 h-3.5" }), "Clear Context"]
|
|
120369
|
-
}),
|
|
120370
|
-
canShutdown && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuItem, {
|
|
120371
|
-
onClick: () => openConfirm("Shutdown Agent", `Shutdown ${displayName(agent)}?`, () => doAgentAction(agent, "shutdown")),
|
|
120372
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Power, { className: "w-3.5 h-3.5" }), "Shutdown"]
|
|
120373
|
-
}),
|
|
120374
|
-
agent && typeof agent.meta?.cwd === "string" && agent.meta.cwd && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuItem, {
|
|
120375
|
-
onClick: () => void openFilesForAgent(agent),
|
|
120376
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FolderOpen, { className: "w-3.5 h-3.5" }), "Open Files"]
|
|
120377
|
-
}),
|
|
120378
|
-
agent && thread && thread.messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuItem, {
|
|
120379
|
-
onClick: () => forkFromAgent(agent.id, thread.messages),
|
|
120380
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitFork, { className: "w-3.5 h-3.5" }), "Fork"]
|
|
120381
|
-
}),
|
|
120382
|
-
(canOpenTerminal || canCompact || canClearContext || canShutdown) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DropdownMenuSeparator, {}),
|
|
120383
|
-
thread && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuItem, {
|
|
120384
|
-
onClick: () => markInboxThreadUnread(selectedInboxThread),
|
|
120385
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MailX, { className: "w-3.5 h-3.5" }), "Mark Unread"]
|
|
120673
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120674
|
+
variant: "ghost",
|
|
120675
|
+
size: "icon",
|
|
120676
|
+
title: "Attach files",
|
|
120677
|
+
disabled: chatSending,
|
|
120678
|
+
onClick: () => fileInputRef.current?.click(),
|
|
120679
|
+
className: "shrink-0 mb-0.5 rounded-xl h-[42px] w-[42px]",
|
|
120680
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Paperclip, { className: "w-4 h-4" })
|
|
120386
120681
|
}),
|
|
120387
|
-
|
|
120388
|
-
|
|
120389
|
-
|
|
120682
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AutoGrowTextarea, {
|
|
120683
|
+
value: draft,
|
|
120684
|
+
onChange: (e) => setReplyDraft(selectedInboxThread, e.target.value),
|
|
120685
|
+
onKeyDown: handleKeyDown,
|
|
120686
|
+
onPaste: handlePaste,
|
|
120687
|
+
placeholder: `Message ${agent ? displayName(agent) : selectedInboxThread}…`,
|
|
120688
|
+
className: "flex-1"
|
|
120390
120689
|
}),
|
|
120391
|
-
|
|
120392
|
-
|
|
120393
|
-
|
|
120394
|
-
|
|
120395
|
-
|
|
120396
|
-
children:
|
|
120690
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120691
|
+
size: "icon",
|
|
120692
|
+
disabled: !draft.trim() && readyAttachments.length === 0 || hasPendingUploads || chatSending,
|
|
120693
|
+
onClick: handleSend,
|
|
120694
|
+
className: "shrink-0 mb-0.5 rounded-xl h-[42px] w-[42px]",
|
|
120695
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Send, { className: "w-4 h-4" })
|
|
120397
120696
|
})
|
|
120398
120697
|
]
|
|
120399
|
-
})
|
|
120400
|
-
|
|
120401
|
-
|
|
120402
|
-
|
|
120403
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
120404
|
-
ref: pinnedScroll.ref,
|
|
120405
|
-
onScroll: pinnedScroll.onScroll,
|
|
120406
|
-
className: "flex-1 overflow-y-auto px-3 md:px-4 py-3 md:py-4",
|
|
120407
|
-
style: { minHeight: 0 },
|
|
120408
|
-
children: timeline.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
120409
|
-
className: "flex flex-col items-center justify-center h-full text-center",
|
|
120410
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessageSquare, { className: "w-8 h-8 text-zinc-600 mb-2" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
120411
|
-
className: "text-xs text-muted-foreground",
|
|
120412
|
-
children: "No messages yet"
|
|
120413
|
-
})]
|
|
120414
|
-
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
120415
|
-
timeline.map((entry) => {
|
|
120416
|
-
if (entry.type === "message") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessageBubble, {
|
|
120417
|
-
msg: entry.msg,
|
|
120418
|
-
peer: selectedInboxThread,
|
|
120419
|
-
onOpenReferencedPath: openReferencedFile,
|
|
120420
|
-
onPreviewReferencedPath: previewReferencedFile,
|
|
120421
|
-
onPreviewReferencedPathEnd: scheduleCloseReferencedFilePreview
|
|
120422
|
-
}, entry.msg.id);
|
|
120423
|
-
if (entry.type === "import-boundary") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImportedHistoryMarker, { history: entry.history }, `import-${entry.history.id}`);
|
|
120424
|
-
if (entry.type === "imported-message") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImportedMessageBubble, {
|
|
120425
|
-
entry: entry.entry,
|
|
120426
|
-
sourceLabel: entry.history.sourceAgentLabel || entry.history.sourcePeerId
|
|
120427
|
-
}, `import-${entry.history.id}-${entry.entry.originalMessageId}-${entry.entry.position}`);
|
|
120428
|
-
if (entry.type === "status") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusMarker, { event: entry.event }, entry.event.id);
|
|
120429
|
-
if (entry.type === "date") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DateSeparator, { date: entry.date }, `d-${entry.date}`);
|
|
120430
|
-
if (entry.type === "created") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CreatedMarker, { timestamp: entry.timestamp }, "created");
|
|
120431
|
-
return null;
|
|
120432
|
-
}),
|
|
120433
|
-
pendingApproval && agent && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PermissionRequestBubble, {
|
|
120434
|
-
agentId: agent.id,
|
|
120435
|
-
approval: pendingApproval
|
|
120436
|
-
}),
|
|
120437
|
-
agent?.status === "busy" && !pendingApproval && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BusyIndicator, { blockedLabel: blockedState?.label })
|
|
120438
|
-
] })
|
|
120439
|
-
}),
|
|
120440
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
120441
|
-
className: cn$1("shrink-0 border-t border-border px-3 md:px-4 py-2.5 md:py-3 safe-area-bottom", dragActive && "bg-primary/5 ring-1 ring-primary/40"),
|
|
120442
|
-
onDragOver: (e) => {
|
|
120443
|
-
e.preventDefault();
|
|
120444
|
-
setDragActive(true);
|
|
120445
|
-
},
|
|
120446
|
-
onDragLeave: () => setDragActive(false),
|
|
120447
|
-
onDrop: (e) => {
|
|
120448
|
-
e.preventDefault();
|
|
120449
|
-
setDragActive(false);
|
|
120450
|
-
uploadFiles(e.dataTransfer.files);
|
|
120451
|
-
},
|
|
120452
|
-
children: [
|
|
120453
|
-
pendingAttachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
120454
|
-
className: "mb-2 grid gap-2 sm:grid-cols-2",
|
|
120455
|
-
children: pendingAttachments.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PendingAttachmentPreview, {
|
|
120456
|
-
item,
|
|
120457
|
-
onRemove: () => removePendingAttachment(item.id)
|
|
120458
|
-
}, item.id))
|
|
120459
|
-
}),
|
|
120460
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", {
|
|
120461
|
-
ref: fileInputRef,
|
|
120462
|
-
type: "file",
|
|
120463
|
-
multiple: true,
|
|
120464
|
-
className: "hidden",
|
|
120465
|
-
onChange: (e) => {
|
|
120466
|
-
if (e.target.files) uploadFiles(e.target.files);
|
|
120467
|
-
e.currentTarget.value = "";
|
|
120468
|
-
}
|
|
120469
|
-
}),
|
|
120470
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
120471
|
-
className: "hidden md:flex items-end gap-2",
|
|
120472
|
-
children: [
|
|
120473
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120474
|
-
variant: "ghost",
|
|
120475
|
-
size: "icon",
|
|
120476
|
-
title: "Attach files",
|
|
120477
|
-
disabled: chatSending,
|
|
120478
|
-
onClick: () => fileInputRef.current?.click(),
|
|
120479
|
-
className: "shrink-0 mb-0.5 rounded-xl h-[42px] w-[42px]",
|
|
120480
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Paperclip, { className: "w-4 h-4" })
|
|
120481
|
-
}),
|
|
120482
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AutoGrowTextarea, {
|
|
120698
|
+
}),
|
|
120699
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
120700
|
+
className: "md:hidden space-y-2",
|
|
120701
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AutoGrowTextarea, {
|
|
120483
120702
|
value: draft,
|
|
120484
120703
|
onChange: (e) => setReplyDraft(selectedInboxThread, e.target.value),
|
|
120485
120704
|
onKeyDown: handleKeyDown,
|
|
120486
120705
|
onPaste: handlePaste,
|
|
120487
120706
|
placeholder: `Message ${agent ? displayName(agent) : selectedInboxThread}…`,
|
|
120488
|
-
className: "
|
|
120489
|
-
}),
|
|
120490
|
-
|
|
120491
|
-
|
|
120492
|
-
|
|
120493
|
-
|
|
120494
|
-
|
|
120495
|
-
|
|
120496
|
-
|
|
120497
|
-
|
|
120498
|
-
|
|
120499
|
-
|
|
120500
|
-
|
|
120501
|
-
|
|
120502
|
-
|
|
120503
|
-
|
|
120504
|
-
|
|
120505
|
-
|
|
120506
|
-
placeholder: `Message ${agent ? displayName(agent) : selectedInboxThread}…`,
|
|
120507
|
-
className: "w-full"
|
|
120508
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
120509
|
-
className: "flex items-center justify-between",
|
|
120510
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120511
|
-
variant: "ghost",
|
|
120512
|
-
size: "icon",
|
|
120513
|
-
title: "Attach files",
|
|
120514
|
-
disabled: chatSending,
|
|
120515
|
-
onClick: () => fileInputRef.current?.click(),
|
|
120516
|
-
className: "rounded-xl h-9 w-9",
|
|
120517
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Paperclip, { className: "w-4 h-4" })
|
|
120518
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120519
|
-
size: "icon",
|
|
120520
|
-
disabled: !draft.trim() && readyAttachments.length === 0 || hasPendingUploads || chatSending,
|
|
120521
|
-
onClick: handleSend,
|
|
120522
|
-
className: "rounded-xl h-9 w-9",
|
|
120523
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Send, { className: "w-4 h-4" })
|
|
120707
|
+
className: "w-full"
|
|
120708
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
120709
|
+
className: "flex items-center justify-between",
|
|
120710
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120711
|
+
variant: "ghost",
|
|
120712
|
+
size: "icon",
|
|
120713
|
+
title: "Attach files",
|
|
120714
|
+
disabled: chatSending,
|
|
120715
|
+
onClick: () => fileInputRef.current?.click(),
|
|
120716
|
+
className: "rounded-xl h-9 w-9",
|
|
120717
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Paperclip, { className: "w-4 h-4" })
|
|
120718
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120719
|
+
size: "icon",
|
|
120720
|
+
disabled: !draft.trim() && readyAttachments.length === 0 || hasPendingUploads || chatSending,
|
|
120721
|
+
onClick: handleSend,
|
|
120722
|
+
className: "rounded-xl h-9 w-9",
|
|
120723
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Send, { className: "w-4 h-4" })
|
|
120724
|
+
})]
|
|
120524
120725
|
})]
|
|
120525
|
-
})
|
|
120726
|
+
}),
|
|
120727
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
120728
|
+
className: "text-xs text-muted-foreground mt-1.5 hidden md:block",
|
|
120729
|
+
children: "Enter to send · Shift+Enter for newline"
|
|
120730
|
+
})
|
|
120731
|
+
]
|
|
120732
|
+
})
|
|
120733
|
+
]
|
|
120734
|
+
}), filePreview && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("aside", {
|
|
120735
|
+
className: "hidden h-full w-[min(44vw,720px)] min-w-[360px] shrink-0 flex-col border-l border-border bg-background xl:flex",
|
|
120736
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
120737
|
+
className: "flex h-10 shrink-0 items-center gap-2 border-b border-border px-3",
|
|
120738
|
+
children: [
|
|
120739
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
120740
|
+
className: "min-w-0 flex-1 text-xs font-medium text-muted-foreground",
|
|
120741
|
+
children: "File preview"
|
|
120526
120742
|
}),
|
|
120527
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("
|
|
120528
|
-
className: "text-xs text-
|
|
120529
|
-
children:
|
|
120743
|
+
filePreviewError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
120744
|
+
className: "max-w-[18rem] truncate text-xs text-red-400",
|
|
120745
|
+
children: filePreviewError
|
|
120746
|
+
}),
|
|
120747
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120748
|
+
variant: "ghost",
|
|
120749
|
+
size: "icon-sm",
|
|
120750
|
+
title: "Close preview",
|
|
120751
|
+
onClick: closeFilePreview,
|
|
120752
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(X$2, { className: "h-3.5 w-3.5" })
|
|
120530
120753
|
})
|
|
120531
120754
|
]
|
|
120532
|
-
})
|
|
120533
|
-
|
|
120534
|
-
|
|
120535
|
-
|
|
120536
|
-
|
|
120537
|
-
|
|
120538
|
-
|
|
120539
|
-
|
|
120540
|
-
|
|
120541
|
-
|
|
120542
|
-
|
|
120543
|
-
children: "File preview"
|
|
120544
|
-
}),
|
|
120545
|
-
filePreviewError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
120546
|
-
className: "max-w-[18rem] truncate text-xs text-red-400",
|
|
120547
|
-
children: filePreviewError
|
|
120548
|
-
}),
|
|
120549
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
120550
|
-
variant: "ghost",
|
|
120551
|
-
size: "icon-sm",
|
|
120552
|
-
title: "Close preview",
|
|
120553
|
-
onClick: closeFilePreview,
|
|
120554
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(X$2, { className: "h-3.5 w-3.5" })
|
|
120755
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
120756
|
+
className: "min-h-0 flex-1",
|
|
120757
|
+
children: filePreview.type === "directory" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DirectoryContent, {
|
|
120758
|
+
orchestratorId: filePreview.orchestratorId,
|
|
120759
|
+
selectedPath: filePreview.path,
|
|
120760
|
+
onReadError: setFilePreviewError
|
|
120761
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileContent, {
|
|
120762
|
+
orchestratorId: filePreview.orchestratorId,
|
|
120763
|
+
selectedPath: filePreview.path,
|
|
120764
|
+
line: filePreview.line,
|
|
120765
|
+
onReadError: setFilePreviewError
|
|
120555
120766
|
})
|
|
120556
|
-
]
|
|
120557
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
120558
|
-
className: "min-h-0 flex-1",
|
|
120559
|
-
children: filePreview.type === "directory" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DirectoryContent, {
|
|
120560
|
-
orchestratorId: filePreview.orchestratorId,
|
|
120561
|
-
selectedPath: filePreview.path,
|
|
120562
|
-
onReadError: setFilePreviewError
|
|
120563
|
-
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileContent, {
|
|
120564
|
-
orchestratorId: filePreview.orchestratorId,
|
|
120565
|
-
selectedPath: filePreview.path,
|
|
120566
|
-
line: filePreview.line,
|
|
120567
|
-
onReadError: setFilePreviewError
|
|
120568
|
-
})
|
|
120767
|
+
})]
|
|
120569
120768
|
})]
|
|
120570
|
-
})
|
|
120571
|
-
|
|
120572
|
-
|
|
120573
|
-
|
|
120574
|
-
|
|
120575
|
-
|
|
120576
|
-
|
|
120577
|
-
|
|
120769
|
+
}),
|
|
120770
|
+
floatingPreview && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FloatingFilePreview, {
|
|
120771
|
+
preview: floatingPreview,
|
|
120772
|
+
error: filePreviewError,
|
|
120773
|
+
onReadError: setFilePreviewError,
|
|
120774
|
+
onMouseEnter: clearFilePreviewCloseTimer,
|
|
120775
|
+
onMouseLeave: scheduleCloseReferencedFilePreview
|
|
120776
|
+
}),
|
|
120777
|
+
terminalTarget && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TerminalDialog, {
|
|
120778
|
+
open: terminalOpen,
|
|
120779
|
+
onOpenChange: handleCloseTerminal,
|
|
120780
|
+
orchestratorId: terminalTarget.orchestratorId,
|
|
120781
|
+
session: terminalTarget.session,
|
|
120782
|
+
interactive: terminalTarget.interactive || canWriteTerminal
|
|
120783
|
+
})
|
|
120784
|
+
] });
|
|
120578
120785
|
}
|
|
120579
120786
|
function ChatView() {
|
|
120580
120787
|
const threads = useAllInboxThreads();
|
|
@@ -121582,6 +121789,8 @@ function ManagedAgentRow({ agent, orch }) {
|
|
|
121582
121789
|
function OrchestratorCard({ orch }) {
|
|
121583
121790
|
const now = useNow();
|
|
121584
121791
|
const orchestratorAction = useRelayStore((s) => s.orchestratorAction);
|
|
121792
|
+
const upgradeOrchestrator = useRelayStore((s) => s.upgradeOrchestrator);
|
|
121793
|
+
const fleetTarget = useRelayStore((s) => s.stats.version);
|
|
121585
121794
|
const openOrchestratorSpawnFor = useRelayStore((s) => s.openOrchestratorSpawnFor);
|
|
121586
121795
|
const openFilesAt = useRelayStore((s) => s.openFilesAt);
|
|
121587
121796
|
const deleteOrchestrator = useRelayStore((s) => s.deleteOrchestrator);
|
|
@@ -121590,6 +121799,10 @@ function OrchestratorCard({ orch }) {
|
|
|
121590
121799
|
const healthClass = orchestratorHealthClass(orch);
|
|
121591
121800
|
const online = orch.status === "online";
|
|
121592
121801
|
const packageVersion = orch.package?.version || orch.version;
|
|
121802
|
+
const upgrade = orch.upgrade;
|
|
121803
|
+
const upgrading = upgrade?.status === "pending";
|
|
121804
|
+
const driftAvailable = online && !!orch.version && !!fleetTarget && orch.version !== fleetTarget;
|
|
121805
|
+
const canUpgrade = online && !upgrading && (driftAvailable || upgrade?.status === "failed");
|
|
121593
121806
|
const contractEntries = Object.entries(orch.contracts || {}).filter(([, value]) => typeof value === "number");
|
|
121594
121807
|
const providerStatus = orch.providerStatus || orch.providers.map((provider) => ({
|
|
121595
121808
|
name: provider,
|
|
@@ -121642,6 +121855,27 @@ function OrchestratorCard({ orch }) {
|
|
|
121642
121855
|
" v",
|
|
121643
121856
|
packageVersion
|
|
121644
121857
|
] }),
|
|
121858
|
+
upgrading && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Badge$1, {
|
|
121859
|
+
className: "text-[10px] bg-amber-500/10 text-amber-400 border-amber-500/20 gap-1",
|
|
121860
|
+
children: [
|
|
121861
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CircleArrowUp, { className: "w-3 h-3 animate-pulse" }),
|
|
121862
|
+
"upgrading → v",
|
|
121863
|
+
upgrade.desiredVersion
|
|
121864
|
+
]
|
|
121865
|
+
}),
|
|
121866
|
+
!upgrading && upgrade?.status === "failed" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Badge$1, {
|
|
121867
|
+
className: "text-[10px] bg-red-500/10 text-red-400 border-red-500/20 gap-1",
|
|
121868
|
+
title: upgrade.error,
|
|
121869
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TriangleAlert, { className: "w-3 h-3" }), "upgrade failed"]
|
|
121870
|
+
}),
|
|
121871
|
+
!upgrading && driftAvailable && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Badge$1, {
|
|
121872
|
+
className: "text-[10px] bg-blue-500/10 text-blue-400 border-blue-500/20",
|
|
121873
|
+
children: [
|
|
121874
|
+
"→ v",
|
|
121875
|
+
fleetTarget,
|
|
121876
|
+
" available"
|
|
121877
|
+
]
|
|
121878
|
+
}),
|
|
121645
121879
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
121646
121880
|
className: "ml-auto",
|
|
121647
121881
|
children: timeAgo(now, orch.lastSeen)
|
|
@@ -121733,6 +121967,15 @@ function OrchestratorCard({ orch }) {
|
|
|
121733
121967
|
onClick: () => refreshOrchestratorProviders(orch.id),
|
|
121734
121968
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RotateCw, { className: "w-3 h-3" }), "Refresh providers"]
|
|
121735
121969
|
}),
|
|
121970
|
+
(canUpgrade || upgrading) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, {
|
|
121971
|
+
size: "sm",
|
|
121972
|
+
variant: "outline",
|
|
121973
|
+
disabled: upgrading,
|
|
121974
|
+
className: "h-7 text-xs gap-1 text-blue-400 hover:text-blue-300 border-blue-500/30 disabled:opacity-60",
|
|
121975
|
+
title: upgrading ? `Upgrading to v${upgrade.desiredVersion}…` : `Upgrade to v${fleetTarget}`,
|
|
121976
|
+
onClick: () => upgradeOrchestrator(orch.id),
|
|
121977
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CircleArrowUp, { className: `w-3 h-3 ${upgrading ? "animate-pulse" : ""}` }), upgrading ? "Upgrading…" : "Upgrade"]
|
|
121978
|
+
}),
|
|
121736
121979
|
online && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, {
|
|
121737
121980
|
size: "sm",
|
|
121738
121981
|
variant: "outline",
|
|
@@ -121817,12 +122060,27 @@ var LIVE_STATUSES = new Set([
|
|
|
121817
122060
|
"merge_planned",
|
|
121818
122061
|
"cleanup_requested"
|
|
121819
122062
|
]);
|
|
122063
|
+
var GIT_STATE_STATUSES = new Set([
|
|
122064
|
+
"active",
|
|
122065
|
+
"ready",
|
|
122066
|
+
"conflict",
|
|
122067
|
+
"review_requested",
|
|
122068
|
+
"merge_planned"
|
|
122069
|
+
]);
|
|
122070
|
+
var MERGEABLE_STATUSES = new Set([
|
|
122071
|
+
"active",
|
|
122072
|
+
"ready",
|
|
122073
|
+
"review_requested",
|
|
122074
|
+
"merge_planned",
|
|
122075
|
+
"conflict"
|
|
122076
|
+
]);
|
|
121820
122077
|
var STATUS_CLASS$1 = {
|
|
121821
122078
|
active: "bg-blue-500/10 text-blue-400 border-blue-500/20",
|
|
121822
122079
|
ready: "bg-emerald-500/10 text-emerald-400 border-emerald-500/20",
|
|
121823
122080
|
conflict: "bg-red-500/10 text-red-400 border-red-500/20",
|
|
121824
122081
|
review_requested: "bg-yellow-500/10 text-yellow-400 border-yellow-500/20",
|
|
121825
122082
|
merge_planned: "bg-indigo-500/10 text-indigo-400 border-indigo-500/20",
|
|
122083
|
+
merged: "bg-violet-500/10 text-violet-400 border-violet-500/20",
|
|
121826
122084
|
abandoned: "bg-zinc-500/10 text-zinc-400 border-zinc-500/20",
|
|
121827
122085
|
cleanup_requested: "bg-orange-500/10 text-orange-400 border-orange-500/20",
|
|
121828
122086
|
cleaned: "bg-zinc-500/10 text-zinc-400 border-zinc-500/20"
|
|
@@ -121833,6 +122091,7 @@ var STATUS_LABEL = {
|
|
|
121833
122091
|
conflict: "conflict",
|
|
121834
122092
|
review_requested: "review",
|
|
121835
122093
|
merge_planned: "merge planned",
|
|
122094
|
+
merged: "merged",
|
|
121836
122095
|
abandoned: "abandoned",
|
|
121837
122096
|
cleanup_requested: "cleanup",
|
|
121838
122097
|
cleaned: "cleaned"
|
|
@@ -121844,9 +122103,11 @@ var STATUS_ORDER = {
|
|
|
121844
122103
|
merge_planned: 3,
|
|
121845
122104
|
active: 4,
|
|
121846
122105
|
cleanup_requested: 5,
|
|
121847
|
-
|
|
121848
|
-
|
|
122106
|
+
merged: 6,
|
|
122107
|
+
abandoned: 7,
|
|
122108
|
+
cleaned: 8
|
|
121849
122109
|
};
|
|
122110
|
+
var TERMINAL_STATUSES = new Set(["cleaned", "merged"]);
|
|
121850
122111
|
function shortPath(path) {
|
|
121851
122112
|
const parts = path.split("/").filter(Boolean);
|
|
121852
122113
|
if (parts.length <= 3) return path || "-";
|
|
@@ -121881,20 +122142,35 @@ function groupWorkspaces(workspaces) {
|
|
|
121881
122142
|
}
|
|
121882
122143
|
function filterWorkspaces(workspaces, filter) {
|
|
121883
122144
|
if (filter === "all") return workspaces;
|
|
121884
|
-
if (filter === "cleaned") return workspaces.filter((workspace) => workspace.status
|
|
121885
|
-
return workspaces.filter((workspace) => workspace.status
|
|
122145
|
+
if (filter === "cleaned") return workspaces.filter((workspace) => TERMINAL_STATUSES.has(workspace.status));
|
|
122146
|
+
return workspaces.filter((workspace) => !TERMINAL_STATUSES.has(workspace.status));
|
|
121886
122147
|
}
|
|
121887
|
-
function WorkspaceActions({ workspace }) {
|
|
122148
|
+
function WorkspaceActions({ workspace, expanded, onToggleDetails }) {
|
|
121888
122149
|
const workspaceAction = useRelayStore((s) => s.workspaceAction);
|
|
122150
|
+
const purgeWorkspace = useRelayStore((s) => s.purgeWorkspace);
|
|
122151
|
+
const fetchWorkspaceMergePreview = useRelayStore((s) => s.fetchWorkspaceMergePreview);
|
|
121889
122152
|
const openFilesAt = useRelayStore((s) => s.openFilesAt);
|
|
121890
|
-
const
|
|
122153
|
+
const terminal = workspace.status === "cleaned" || workspace.status === "merged" || workspace.status === "abandoned";
|
|
122154
|
+
const disabled = terminal || workspace.status === "cleanup_requested";
|
|
121891
122155
|
const openPath = workspace.worktreePath || workspace.sourceCwd || workspace.repoRoot;
|
|
122156
|
+
const mergeable = workspace.mode === "isolated" && Boolean(workspace.worktreePath) && MERGEABLE_STATUSES.has(workspace.status);
|
|
121892
122157
|
async function copyPath() {
|
|
121893
122158
|
await navigator.clipboard?.writeText(openPath);
|
|
121894
122159
|
}
|
|
122160
|
+
async function merge() {
|
|
122161
|
+
await fetchWorkspaceMergePreview(workspace.id);
|
|
122162
|
+
await workspaceAction(workspace.id, "merge");
|
|
122163
|
+
}
|
|
121895
122164
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
121896
122165
|
className: "flex flex-wrap justify-end gap-1.5",
|
|
121897
122166
|
children: [
|
|
122167
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
122168
|
+
size: "icon-sm",
|
|
122169
|
+
variant: "ghost",
|
|
122170
|
+
title: expanded ? "Hide details" : "Show diff & timeline",
|
|
122171
|
+
onClick: onToggleDetails,
|
|
122172
|
+
children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronDown, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronRight, { className: "h-3.5 w-3.5" })
|
|
122173
|
+
}),
|
|
121898
122174
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
121899
122175
|
size: "icon-sm",
|
|
121900
122176
|
variant: "ghost",
|
|
@@ -121933,108 +122209,477 @@ function WorkspaceActions({ workspace }) {
|
|
|
121933
122209
|
title: "Mark merge planned",
|
|
121934
122210
|
disabled: disabled || workspace.status === "merge_planned",
|
|
121935
122211
|
onClick: () => void workspaceAction(workspace.id, "merge-plan"),
|
|
122212
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Flag, { className: "h-3.5 w-3.5" })
|
|
122213
|
+
}),
|
|
122214
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
122215
|
+
size: "icon-sm",
|
|
122216
|
+
variant: "default",
|
|
122217
|
+
title: "Merge & land work",
|
|
122218
|
+
disabled: !mergeable,
|
|
122219
|
+
onClick: () => void merge(),
|
|
121936
122220
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitMerge, { className: "h-3.5 w-3.5" })
|
|
121937
122221
|
}),
|
|
121938
122222
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
121939
122223
|
size: "icon-sm",
|
|
121940
122224
|
variant: "outline",
|
|
121941
|
-
title: "Request cleanup",
|
|
122225
|
+
title: "Request cleanup (removes the worktree on the host)",
|
|
121942
122226
|
disabled: workspace.status === "cleaned" || workspace.status === "cleanup_requested",
|
|
121943
122227
|
onClick: () => void workspaceAction(workspace.id, "cleanup"),
|
|
121944
122228
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Trash2, { className: "h-3.5 w-3.5" })
|
|
122229
|
+
}),
|
|
122230
|
+
terminal && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
122231
|
+
size: "icon-sm",
|
|
122232
|
+
variant: "ghost",
|
|
122233
|
+
title: "Purge record (clears the row, does not touch disk)",
|
|
122234
|
+
onClick: () => void purgeWorkspace(workspace.id),
|
|
122235
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(X$2, { className: "h-3.5 w-3.5" })
|
|
121945
122236
|
})
|
|
121946
122237
|
]
|
|
121947
122238
|
});
|
|
121948
122239
|
}
|
|
121949
|
-
function
|
|
122240
|
+
function MergePreviewHint({ workspace, ahead }) {
|
|
122241
|
+
const preview = useRelayStore((s) => s.workspaceMergePreview[workspace.id]);
|
|
122242
|
+
const fetchWorkspaceMergePreview = useRelayStore((s) => s.fetchWorkspaceMergePreview);
|
|
122243
|
+
const eligible = ahead > 0 && MERGEABLE_STATUSES.has(workspace.status);
|
|
122244
|
+
(0, import_react.useEffect)(() => {
|
|
122245
|
+
if (eligible && preview === void 0) fetchWorkspaceMergePreview(workspace.id);
|
|
122246
|
+
}, [
|
|
122247
|
+
eligible,
|
|
122248
|
+
preview,
|
|
122249
|
+
workspace.id,
|
|
122250
|
+
fetchWorkspaceMergePreview
|
|
122251
|
+
]);
|
|
122252
|
+
if (!eligible || preview === void 0 || preview.available === false) return null;
|
|
122253
|
+
if (preview.conflict) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
122254
|
+
className: "flex items-center gap-0.5 text-amber-400",
|
|
122255
|
+
title: `Merging into ${preview.baseRef || "base"} would conflict — resolve before merging`,
|
|
122256
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TriangleAlert, { className: "h-3 w-3" }), "conflict"]
|
|
122257
|
+
});
|
|
122258
|
+
if (preview.conflict === false) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
122259
|
+
className: "flex items-center gap-0.5 text-emerald-400",
|
|
122260
|
+
title: `Clean to merge via ${preview.strategy === "pr" ? "PR" : "rebase + fast-forward"} into ${preview.baseRef || "base"}`,
|
|
122261
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Check, { className: "h-3 w-3" }), preview.strategy === "pr" ? "PR ready" : "clean"]
|
|
122262
|
+
});
|
|
122263
|
+
return null;
|
|
122264
|
+
}
|
|
122265
|
+
function GitState({ workspace }) {
|
|
121950
122266
|
const now = useNow();
|
|
121951
|
-
const
|
|
121952
|
-
const
|
|
121953
|
-
const
|
|
121954
|
-
|
|
122267
|
+
const gitState = useRelayStore((s) => s.workspaceGitState[workspace.id]);
|
|
122268
|
+
const fetchWorkspaceGitState = useRelayStore((s) => s.fetchWorkspaceGitState);
|
|
122269
|
+
const eligible = workspace.mode === "isolated" && Boolean(workspace.worktreePath) && GIT_STATE_STATUSES.has(workspace.status);
|
|
122270
|
+
(0, import_react.useEffect)(() => {
|
|
122271
|
+
if (eligible && gitState === void 0) fetchWorkspaceGitState(workspace.id);
|
|
122272
|
+
}, [
|
|
122273
|
+
eligible,
|
|
122274
|
+
gitState,
|
|
122275
|
+
workspace.id,
|
|
122276
|
+
fetchWorkspaceGitState
|
|
122277
|
+
]);
|
|
122278
|
+
if (!eligible) return null;
|
|
122279
|
+
const refresh = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
122280
|
+
size: "icon-sm",
|
|
122281
|
+
variant: "ghost",
|
|
122282
|
+
className: "h-5 w-5",
|
|
122283
|
+
title: "Refresh git state",
|
|
122284
|
+
onClick: () => void fetchWorkspaceGitState(workspace.id),
|
|
122285
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshCw, { className: "h-3 w-3" })
|
|
122286
|
+
});
|
|
122287
|
+
if (gitState === void 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
122288
|
+
className: "flex items-center gap-1 text-[11px] text-muted-foreground",
|
|
122289
|
+
children: "Loading git state…"
|
|
122290
|
+
});
|
|
122291
|
+
if (gitState.available === false) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122292
|
+
className: "flex items-center gap-1 text-[11px] text-muted-foreground",
|
|
122293
|
+
title: gitState.reason,
|
|
122294
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "git state unavailable" }), refresh]
|
|
122295
|
+
});
|
|
122296
|
+
if (gitState.missing) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122297
|
+
className: "flex items-center gap-1 text-[11px] text-muted-foreground",
|
|
122298
|
+
children: ["worktree gone ", refresh]
|
|
122299
|
+
});
|
|
122300
|
+
if (gitState.error) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122301
|
+
className: "flex items-center gap-1 text-[11px] text-red-400",
|
|
122302
|
+
title: gitState.error,
|
|
122303
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "git error" }), refresh]
|
|
122304
|
+
});
|
|
122305
|
+
const ahead = gitState.ahead ?? 0;
|
|
122306
|
+
const behind = gitState.behind ?? 0;
|
|
122307
|
+
const dirty = gitState.dirtyCount ?? 0;
|
|
122308
|
+
const clean = ahead === 0 && dirty === 0;
|
|
122309
|
+
const commit = gitState.lastCommit;
|
|
121955
122310
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
121956
|
-
className: "
|
|
122311
|
+
className: "space-y-0.5",
|
|
122312
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122313
|
+
className: "flex flex-wrap items-center gap-x-2 gap-y-0.5 text-[11px]",
|
|
122314
|
+
children: [clean ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
122315
|
+
className: "text-muted-foreground",
|
|
122316
|
+
children: "no unmerged work"
|
|
122317
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
122318
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
122319
|
+
className: ahead > 0 ? "flex items-center text-emerald-400" : "flex items-center text-muted-foreground",
|
|
122320
|
+
title: `${ahead} commit(s) ahead of base`,
|
|
122321
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArrowUp, { className: "h-3 w-3" }), ahead]
|
|
122322
|
+
}),
|
|
122323
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
122324
|
+
className: behind > 0 ? "flex items-center text-amber-400" : "flex items-center text-muted-foreground",
|
|
122325
|
+
title: `${behind} commit(s) behind base`,
|
|
122326
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArrowDown, { className: "h-3 w-3" }), behind]
|
|
122327
|
+
}),
|
|
122328
|
+
dirty > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
122329
|
+
className: "flex items-center text-orange-400",
|
|
122330
|
+
title: `${dirty} uncommitted change(s)`,
|
|
122331
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FilePen, { className: "h-3 w-3" }), dirty]
|
|
122332
|
+
}),
|
|
122333
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MergePreviewHint, {
|
|
122334
|
+
workspace,
|
|
122335
|
+
ahead
|
|
122336
|
+
})
|
|
122337
|
+
] }), refresh]
|
|
122338
|
+
}), commit && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122339
|
+
className: "flex min-w-0 items-center gap-1 text-[11px] text-muted-foreground",
|
|
122340
|
+
title: `${commit.sha.slice(0, 8)} — ${commit.message}`,
|
|
122341
|
+
children: [
|
|
122342
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitCommitHorizontal, { className: "h-3 w-3 shrink-0" }),
|
|
122343
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
122344
|
+
className: "truncate",
|
|
122345
|
+
children: commit.message || commit.sha.slice(0, 8)
|
|
122346
|
+
}),
|
|
122347
|
+
commit.at ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
122348
|
+
className: "shrink-0 opacity-70",
|
|
122349
|
+
children: ["· ", timeAgo(now, commit.at)]
|
|
122350
|
+
}) : null
|
|
122351
|
+
]
|
|
122352
|
+
})]
|
|
122353
|
+
});
|
|
122354
|
+
}
|
|
122355
|
+
function WorkspaceTimeline({ workspace }) {
|
|
122356
|
+
const now = useNow();
|
|
122357
|
+
const mergedAt = typeof workspace.metadata?.mergedAt === "number" ? workspace.metadata.mergedAt : void 0;
|
|
122358
|
+
const steps = [
|
|
122359
|
+
{
|
|
122360
|
+
label: "created",
|
|
122361
|
+
at: workspace.createdAt
|
|
122362
|
+
},
|
|
122363
|
+
{
|
|
122364
|
+
label: "ready",
|
|
122365
|
+
at: workspace.readyAt
|
|
122366
|
+
},
|
|
122367
|
+
{
|
|
122368
|
+
label: "merged",
|
|
122369
|
+
at: mergedAt
|
|
122370
|
+
},
|
|
122371
|
+
{
|
|
122372
|
+
label: "cleaned",
|
|
122373
|
+
at: workspace.cleanedAt
|
|
122374
|
+
}
|
|
122375
|
+
].filter((step) => typeof step.at === "number" && step.at > 0);
|
|
122376
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122377
|
+
className: "flex flex-wrap items-center gap-x-3 gap-y-1 text-[11px] text-muted-foreground",
|
|
122378
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
122379
|
+
className: "flex items-center gap-1 font-medium text-foreground",
|
|
122380
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Clock, { className: "h-3 w-3" }), "Timeline"]
|
|
122381
|
+
}), steps.map((step, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
122382
|
+
className: "flex items-center gap-1",
|
|
122383
|
+
children: [
|
|
122384
|
+
i > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
122385
|
+
className: "opacity-40",
|
|
122386
|
+
children: "→"
|
|
122387
|
+
}),
|
|
122388
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
122389
|
+
className: "text-foreground",
|
|
122390
|
+
children: step.label
|
|
122391
|
+
}),
|
|
122392
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
122393
|
+
title: new Date(step.at).toLocaleString(),
|
|
122394
|
+
children: timeAgo(now, step.at)
|
|
122395
|
+
})
|
|
122396
|
+
]
|
|
122397
|
+
}, step.label))]
|
|
122398
|
+
});
|
|
122399
|
+
}
|
|
122400
|
+
function diffLineClass(line) {
|
|
122401
|
+
if (line.startsWith("+") && !line.startsWith("+++")) return "text-emerald-400";
|
|
122402
|
+
if (line.startsWith("-") && !line.startsWith("---")) return "text-red-400";
|
|
122403
|
+
if (line.startsWith("@@")) return "text-cyan-400";
|
|
122404
|
+
if (line.startsWith("diff ") || line.startsWith("index ") || line.startsWith("+++") || line.startsWith("---")) return "text-muted-foreground";
|
|
122405
|
+
return "";
|
|
122406
|
+
}
|
|
122407
|
+
function WorkspaceDiffView({ workspace }) {
|
|
122408
|
+
const diff = useRelayStore((s) => s.workspaceDiff[workspace.id]);
|
|
122409
|
+
const fetchWorkspaceDiff = useRelayStore((s) => s.fetchWorkspaceDiff);
|
|
122410
|
+
const eligible = workspace.mode === "isolated" && Boolean(workspace.worktreePath);
|
|
122411
|
+
(0, import_react.useEffect)(() => {
|
|
122412
|
+
if (eligible && diff === void 0) fetchWorkspaceDiff(workspace.id);
|
|
122413
|
+
}, [
|
|
122414
|
+
eligible,
|
|
122415
|
+
diff,
|
|
122416
|
+
workspace.id,
|
|
122417
|
+
fetchWorkspaceDiff
|
|
122418
|
+
]);
|
|
122419
|
+
if (!eligible) return null;
|
|
122420
|
+
if (diff === void 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
122421
|
+
className: "text-[11px] text-muted-foreground",
|
|
122422
|
+
children: "Loading diff…"
|
|
122423
|
+
});
|
|
122424
|
+
if (diff.available === false) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122425
|
+
className: "text-[11px] text-muted-foreground",
|
|
122426
|
+
children: ["Diff unavailable", diff.reason ? `: ${diff.reason}` : ""]
|
|
122427
|
+
});
|
|
122428
|
+
if (diff.missing) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
122429
|
+
className: "text-[11px] text-muted-foreground",
|
|
122430
|
+
children: "Worktree no longer on disk"
|
|
122431
|
+
});
|
|
122432
|
+
if (diff.error) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122433
|
+
className: "text-[11px] text-red-400",
|
|
122434
|
+
children: ["Diff error: ", diff.error]
|
|
122435
|
+
});
|
|
122436
|
+
if (!diff.files.length) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122437
|
+
className: "text-[11px] text-muted-foreground",
|
|
122438
|
+
children: ["No committed changes against ", diff.baseRef || "base"]
|
|
122439
|
+
});
|
|
122440
|
+
const refresh = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
122441
|
+
size: "icon-sm",
|
|
122442
|
+
variant: "ghost",
|
|
122443
|
+
className: "h-5 w-5",
|
|
122444
|
+
title: "Refresh diff",
|
|
122445
|
+
onClick: () => void fetchWorkspaceDiff(workspace.id),
|
|
122446
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshCw, { className: "h-3 w-3" })
|
|
122447
|
+
});
|
|
122448
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122449
|
+
className: "space-y-1",
|
|
121957
122450
|
children: [
|
|
121958
122451
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
121959
|
-
className: "
|
|
121960
|
-
children: [
|
|
121961
|
-
className: "
|
|
121962
|
-
|
|
121963
|
-
|
|
121964
|
-
|
|
121965
|
-
|
|
122452
|
+
className: "flex items-center gap-2 text-[11px] font-medium",
|
|
122453
|
+
children: [
|
|
122454
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileDiff, { className: "h-3 w-3" }),
|
|
122455
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
122456
|
+
diff.files.length,
|
|
122457
|
+
" file",
|
|
122458
|
+
diff.files.length === 1 ? "" : "s",
|
|
122459
|
+
" vs ",
|
|
122460
|
+
diff.baseRef || "base"
|
|
122461
|
+
] }),
|
|
122462
|
+
refresh
|
|
122463
|
+
]
|
|
122464
|
+
}),
|
|
122465
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", {
|
|
122466
|
+
className: "space-y-0.5 text-[11px]",
|
|
122467
|
+
children: diff.files.map((file) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", {
|
|
122468
|
+
className: "flex items-center gap-2 font-mono",
|
|
122469
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
122470
|
+
className: "truncate",
|
|
122471
|
+
title: file.path,
|
|
122472
|
+
children: file.path
|
|
122473
|
+
}), file.binary ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
122474
|
+
className: "shrink-0 text-muted-foreground",
|
|
122475
|
+
children: "binary"
|
|
122476
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
122477
|
+
className: "shrink-0",
|
|
122478
|
+
children: [
|
|
122479
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
122480
|
+
className: "text-emerald-400",
|
|
122481
|
+
children: ["+", file.additions ?? 0]
|
|
122482
|
+
}),
|
|
122483
|
+
" ",
|
|
122484
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
122485
|
+
className: "text-red-400",
|
|
122486
|
+
children: ["−", file.deletions ?? 0]
|
|
122487
|
+
})
|
|
122488
|
+
]
|
|
121966
122489
|
})]
|
|
121967
|
-
}
|
|
121968
|
-
className: "flex flex-wrap gap-1",
|
|
121969
|
-
children: [
|
|
121970
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge$1, {
|
|
121971
|
-
variant: "outline",
|
|
121972
|
-
className: `text-[10px] ${workspace.mode === "isolated" ? "border-sky-500/30 text-sky-400" : "border-zinc-500/30 text-zinc-400"}`,
|
|
121973
|
-
children: workspace.mode
|
|
121974
|
-
}),
|
|
121975
|
-
workspace.requestedMode && workspace.requestedMode !== workspace.mode && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Badge$1, {
|
|
121976
|
-
variant: "outline",
|
|
121977
|
-
className: "text-[10px]",
|
|
121978
|
-
children: ["requested ", workspace.requestedMode]
|
|
121979
|
-
}),
|
|
121980
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge$1, {
|
|
121981
|
-
variant: "outline",
|
|
121982
|
-
className: `text-[10px] ${statusTone(workspace.status)}`,
|
|
121983
|
-
children: STATUS_LABEL[workspace.status] || workspace.status
|
|
121984
|
-
})
|
|
121985
|
-
]
|
|
121986
|
-
})]
|
|
122490
|
+
}, file.path))
|
|
121987
122491
|
}),
|
|
121988
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("
|
|
121989
|
-
className: "
|
|
121990
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
121991
|
-
className:
|
|
121992
|
-
|
|
121993
|
-
|
|
121994
|
-
|
|
121995
|
-
|
|
121996
|
-
title: workspace.sourceCwd,
|
|
121997
|
-
children: workspace.sourceCwd
|
|
122492
|
+
diff.patch && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("pre", {
|
|
122493
|
+
className: "max-h-80 overflow-auto rounded border border-border bg-muted/30 p-2 text-[10.5px] leading-relaxed",
|
|
122494
|
+
children: [diff.patch.split("\n").map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
122495
|
+
className: diffLineClass(line),
|
|
122496
|
+
children: line || " "
|
|
122497
|
+
}, i)), diff.truncated && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
122498
|
+
className: "mt-1 text-muted-foreground",
|
|
122499
|
+
children: "… patch truncated"
|
|
121998
122500
|
})]
|
|
121999
|
-
})
|
|
122000
|
-
|
|
122001
|
-
|
|
122501
|
+
})
|
|
122502
|
+
]
|
|
122503
|
+
});
|
|
122504
|
+
}
|
|
122505
|
+
function WorkspaceDetails({ workspace }) {
|
|
122506
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122507
|
+
className: "space-y-3 border-t border-dashed border-border bg-muted/20 px-3 py-3",
|
|
122508
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(WorkspaceTimeline, { workspace }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WorkspaceDiffView, { workspace })]
|
|
122509
|
+
});
|
|
122510
|
+
}
|
|
122511
|
+
function OrphanPanel() {
|
|
122512
|
+
const orphans = useRelayStore((s) => s.workspaceOrphans);
|
|
122513
|
+
const fetchWorkspaceOrphans = useRelayStore((s) => s.fetchWorkspaceOrphans);
|
|
122514
|
+
const reclaimWorkspaceOrphan = useRelayStore((s) => s.reclaimWorkspaceOrphan);
|
|
122515
|
+
(0, import_react.useEffect)(() => {
|
|
122516
|
+
fetchWorkspaceOrphans();
|
|
122517
|
+
}, [fetchWorkspaceOrphans]);
|
|
122518
|
+
if (!orphans.length) return null;
|
|
122519
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, {
|
|
122520
|
+
className: "border-amber-500/30",
|
|
122521
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardHeader, {
|
|
122522
|
+
className: "px-4 py-3",
|
|
122523
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122524
|
+
className: "flex items-center gap-2",
|
|
122002
122525
|
children: [
|
|
122003
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("
|
|
122004
|
-
|
|
122005
|
-
|
|
122526
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(PackageOpen, { className: "h-4 w-4 text-amber-400" }),
|
|
122527
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, {
|
|
122528
|
+
className: "text-sm font-medium",
|
|
122529
|
+
children: "Orphaned worktrees"
|
|
122006
122530
|
}),
|
|
122007
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
122008
|
-
|
|
122009
|
-
|
|
122010
|
-
children:
|
|
122531
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge$1, {
|
|
122532
|
+
variant: "outline",
|
|
122533
|
+
className: "border-amber-500/30 text-amber-400 text-[10px]",
|
|
122534
|
+
children: orphans.length
|
|
122011
122535
|
}),
|
|
122536
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
122537
|
+
size: "icon-sm",
|
|
122538
|
+
variant: "ghost",
|
|
122539
|
+
className: "ml-auto h-6 w-6",
|
|
122540
|
+
title: "Rescan",
|
|
122541
|
+
onClick: () => void fetchWorkspaceOrphans(),
|
|
122542
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshCw, { className: "h-3.5 w-3.5" })
|
|
122543
|
+
})
|
|
122544
|
+
]
|
|
122545
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
122546
|
+
className: "mt-1 text-xs text-muted-foreground",
|
|
122547
|
+
children: "Agent worktrees on disk with no live workspace. Reclaim removes them from the host."
|
|
122548
|
+
})]
|
|
122549
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardContent, {
|
|
122550
|
+
className: "p-0",
|
|
122551
|
+
children: orphans.map((orphan) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122552
|
+
className: "flex items-center gap-3 border-t border-border px-4 py-2 text-xs",
|
|
122553
|
+
children: [
|
|
122554
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitBranch, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
|
|
122012
122555
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
122013
|
-
className: "
|
|
122014
|
-
|
|
122556
|
+
className: "truncate font-medium",
|
|
122557
|
+
title: orphan.branch,
|
|
122558
|
+
children: orphan.branch || "(detached)"
|
|
122015
122559
|
}),
|
|
122016
122560
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
122017
|
-
className: "truncate",
|
|
122018
|
-
title:
|
|
122019
|
-
children:
|
|
122561
|
+
className: "truncate font-mono text-muted-foreground",
|
|
122562
|
+
title: orphan.worktreePath,
|
|
122563
|
+
children: shortPath(orphan.worktreePath)
|
|
122020
122564
|
}),
|
|
122021
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
122022
|
-
|
|
122023
|
-
|
|
122565
|
+
orphan.hadTerminalRow && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge$1, {
|
|
122566
|
+
variant: "outline",
|
|
122567
|
+
className: "text-[10px]",
|
|
122568
|
+
children: "cleanup failed"
|
|
122024
122569
|
}),
|
|
122025
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
122026
|
-
|
|
122027
|
-
|
|
122028
|
-
|
|
122029
|
-
|
|
122030
|
-
className: "
|
|
122031
|
-
|
|
122032
|
-
children: workspace.baseRef
|
|
122033
|
-
})] })
|
|
122570
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, {
|
|
122571
|
+
size: "sm",
|
|
122572
|
+
variant: "outline",
|
|
122573
|
+
className: "ml-auto h-7 text-xs",
|
|
122574
|
+
onClick: () => void reclaimWorkspaceOrphan(orphan),
|
|
122575
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArchiveRestore, { className: "mr-1 h-3.5 w-3.5" }), "Reclaim"]
|
|
122576
|
+
})
|
|
122034
122577
|
]
|
|
122035
|
-
})
|
|
122036
|
-
|
|
122037
|
-
|
|
122578
|
+
}, orphan.worktreePath))
|
|
122579
|
+
})]
|
|
122580
|
+
});
|
|
122581
|
+
}
|
|
122582
|
+
function WorkspaceRow({ workspace }) {
|
|
122583
|
+
const now = useNow();
|
|
122584
|
+
const [expanded, setExpanded] = (0, import_react.useState)(false);
|
|
122585
|
+
const agentsById = useRelayStore((s) => s.agentsById);
|
|
122586
|
+
const owner = workspace.ownerAgentId ? agentsById[workspace.ownerAgentId] : void 0;
|
|
122587
|
+
const steward = workspace.stewardAgentId ? agentsById[workspace.stewardAgentId] : void 0;
|
|
122588
|
+
const path = workspace.worktreePath || workspace.sourceCwd || workspace.repoRoot;
|
|
122589
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122590
|
+
className: "border-t border-border",
|
|
122591
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122592
|
+
className: "grid gap-3 px-3 py-3 text-sm lg:grid-cols-[minmax(180px,1.2fr)_minmax(220px,1.5fr)_minmax(160px,1fr)_minmax(170px,auto)]",
|
|
122593
|
+
children: [
|
|
122594
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122595
|
+
className: "min-w-0 space-y-1",
|
|
122596
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122597
|
+
className: "flex min-w-0 items-center gap-2",
|
|
122598
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitBranch, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
122599
|
+
className: "truncate font-medium",
|
|
122600
|
+
title: workspace.branch || workspace.id,
|
|
122601
|
+
children: workspace.branch || workspace.id
|
|
122602
|
+
})]
|
|
122603
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122604
|
+
className: "flex flex-wrap gap-1",
|
|
122605
|
+
children: [
|
|
122606
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge$1, {
|
|
122607
|
+
variant: "outline",
|
|
122608
|
+
className: `text-[10px] ${workspace.mode === "isolated" ? "border-sky-500/30 text-sky-400" : "border-zinc-500/30 text-zinc-400"}`,
|
|
122609
|
+
children: workspace.mode
|
|
122610
|
+
}),
|
|
122611
|
+
workspace.requestedMode && workspace.requestedMode !== workspace.mode && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Badge$1, {
|
|
122612
|
+
variant: "outline",
|
|
122613
|
+
className: "text-[10px]",
|
|
122614
|
+
children: ["requested ", workspace.requestedMode]
|
|
122615
|
+
}),
|
|
122616
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge$1, {
|
|
122617
|
+
variant: "outline",
|
|
122618
|
+
className: `text-[10px] ${statusTone(workspace.status)}`,
|
|
122619
|
+
children: STATUS_LABEL[workspace.status] || workspace.status
|
|
122620
|
+
})
|
|
122621
|
+
]
|
|
122622
|
+
})]
|
|
122623
|
+
}),
|
|
122624
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122625
|
+
className: "min-w-0 space-y-1",
|
|
122626
|
+
children: [
|
|
122627
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
122628
|
+
className: "truncate font-mono text-xs",
|
|
122629
|
+
title: path,
|
|
122630
|
+
children: shortPath(path)
|
|
122631
|
+
}),
|
|
122632
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
122633
|
+
className: "truncate text-xs text-muted-foreground",
|
|
122634
|
+
title: workspace.sourceCwd,
|
|
122635
|
+
children: workspace.sourceCwd
|
|
122636
|
+
}),
|
|
122637
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitState, { workspace })
|
|
122638
|
+
]
|
|
122639
|
+
}),
|
|
122640
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
122641
|
+
className: "grid grid-cols-[4.5rem_minmax(0,1fr)] gap-x-2 gap-y-1 text-xs",
|
|
122642
|
+
children: [
|
|
122643
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
122644
|
+
className: "text-muted-foreground",
|
|
122645
|
+
children: "Owner"
|
|
122646
|
+
}),
|
|
122647
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
122648
|
+
className: "truncate",
|
|
122649
|
+
title: workspace.ownerAgentId,
|
|
122650
|
+
children: agentLabel(owner, workspace.ownerPolicyName || workspace.ownerAgentId)
|
|
122651
|
+
}),
|
|
122652
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
122653
|
+
className: "text-muted-foreground",
|
|
122654
|
+
children: "Steward"
|
|
122655
|
+
}),
|
|
122656
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
122657
|
+
className: "truncate",
|
|
122658
|
+
title: workspace.stewardAgentId,
|
|
122659
|
+
children: agentLabel(steward, workspace.stewardAgentId)
|
|
122660
|
+
}),
|
|
122661
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
122662
|
+
className: "text-muted-foreground",
|
|
122663
|
+
children: "Updated"
|
|
122664
|
+
}),
|
|
122665
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: timeAgo(now, workspace.updatedAt) }),
|
|
122666
|
+
workspace.baseRef && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
122667
|
+
className: "text-muted-foreground",
|
|
122668
|
+
children: "Base"
|
|
122669
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
122670
|
+
className: "truncate",
|
|
122671
|
+
title: workspace.baseSha,
|
|
122672
|
+
children: workspace.baseRef
|
|
122673
|
+
})] })
|
|
122674
|
+
]
|
|
122675
|
+
}),
|
|
122676
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(WorkspaceActions, {
|
|
122677
|
+
workspace,
|
|
122678
|
+
expanded,
|
|
122679
|
+
onToggleDetails: () => setExpanded((value) => !value)
|
|
122680
|
+
})
|
|
122681
|
+
]
|
|
122682
|
+
}), expanded && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WorkspaceDetails, { workspace })]
|
|
122038
122683
|
});
|
|
122039
122684
|
}
|
|
122040
122685
|
function RepoGroup({ repoRoot, workspaces }) {
|
|
@@ -122092,17 +122737,17 @@ function WorkspacesView() {
|
|
|
122092
122737
|
const isolatedCount = workspaces.filter((item) => item.mode === "isolated").length;
|
|
122093
122738
|
const readyCount = workspaces.filter((item) => item.status === "ready" || item.status === "review_requested" || item.status === "merge_planned").length;
|
|
122094
122739
|
const conflictCount = workspaces.filter((item) => item.status === "conflict").length;
|
|
122095
|
-
const
|
|
122740
|
+
const doneCount = workspaces.filter((item) => TERMINAL_STATUSES.has(item.status)).length;
|
|
122096
122741
|
const filters = [
|
|
122097
122742
|
{
|
|
122098
122743
|
key: "active",
|
|
122099
122744
|
label: "Active",
|
|
122100
|
-
count: workspaces.length -
|
|
122745
|
+
count: workspaces.length - doneCount
|
|
122101
122746
|
},
|
|
122102
122747
|
{
|
|
122103
122748
|
key: "cleaned",
|
|
122104
|
-
label: "
|
|
122105
|
-
count:
|
|
122749
|
+
label: "Done",
|
|
122750
|
+
count: doneCount
|
|
122106
122751
|
},
|
|
122107
122752
|
{
|
|
122108
122753
|
key: "all",
|
|
@@ -122144,6 +122789,7 @@ function WorkspacesView() {
|
|
|
122144
122789
|
]
|
|
122145
122790
|
})]
|
|
122146
122791
|
}),
|
|
122792
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(OrphanPanel, {}),
|
|
122147
122793
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
122148
122794
|
className: "flex flex-wrap items-center gap-2",
|
|
122149
122795
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
@@ -125120,6 +125766,7 @@ function blankForm(orchestratorId = "") {
|
|
|
125120
125766
|
ifNoMatch: "fail",
|
|
125121
125767
|
cwd: "",
|
|
125122
125768
|
approvalMode: "guarded",
|
|
125769
|
+
workspaceMode: "inherit",
|
|
125123
125770
|
keepAlive: false,
|
|
125124
125771
|
budgetMinutes: "",
|
|
125125
125772
|
warningMinutes: "",
|
|
@@ -125158,6 +125805,7 @@ function automationToForm(automation) {
|
|
|
125158
125805
|
ifNoMatch: policy.mode === "existing_agent" ? policy.ifNoMatch || "fail" : "fail",
|
|
125159
125806
|
cwd: policy.mode === "on_demand_agent" ? policy.cwd || "" : "",
|
|
125160
125807
|
approvalMode: policy.mode === "on_demand_agent" ? policy.approvalMode || "guarded" : "guarded",
|
|
125808
|
+
workspaceMode: policy.mode === "on_demand_agent" ? policy.workspaceMode || "inherit" : "inherit",
|
|
125161
125809
|
keepAlive: policy.mode === "on_demand_agent" ? Boolean(policy.keepAlive) : false,
|
|
125162
125810
|
budgetMinutes: policy.mode === "on_demand_agent" && policy.runtimeBudget ? String(Math.round(policy.runtimeBudget.maxRuntimeMs / 6e4)) : "",
|
|
125163
125811
|
warningMinutes: policy.mode === "on_demand_agent" && policy.runtimeBudget?.warnAtMs !== void 0 ? String(Math.round(policy.runtimeBudget.warnAtMs / 6e4)) : "",
|
|
@@ -125195,6 +125843,7 @@ function formToInput(form) {
|
|
|
125195
125843
|
profile: form.profile || void 0,
|
|
125196
125844
|
cwd: form.cwd.trim() || void 0,
|
|
125197
125845
|
approvalMode: form.approvalMode,
|
|
125846
|
+
workspaceMode: form.workspaceMode,
|
|
125198
125847
|
keepAlive: form.keepAlive,
|
|
125199
125848
|
runtimeBudget
|
|
125200
125849
|
};
|
|
@@ -125799,6 +126448,28 @@ function AutomationEditor({ form, selected, saving, orchestrators, agentProfiles
|
|
|
125799
126448
|
children: profile.name
|
|
125800
126449
|
}, profile.name))]
|
|
125801
126450
|
})
|
|
126451
|
+
}),
|
|
126452
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field$1, {
|
|
126453
|
+
label: "Workspace",
|
|
126454
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", {
|
|
126455
|
+
className: "h-9 w-full rounded-md border border-input bg-background px-3 text-sm",
|
|
126456
|
+
value: form.workspaceMode,
|
|
126457
|
+
onChange: (e) => onChange({ workspaceMode: e.target.value }),
|
|
126458
|
+
children: [
|
|
126459
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
126460
|
+
value: "inherit",
|
|
126461
|
+
children: "inherit (default → isolated worktree)"
|
|
126462
|
+
}),
|
|
126463
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
126464
|
+
value: "shared",
|
|
126465
|
+
children: "shared (run in the repo, commit to its branch)"
|
|
126466
|
+
}),
|
|
126467
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
126468
|
+
value: "isolated",
|
|
126469
|
+
children: "isolated (fresh git worktree per run)"
|
|
126470
|
+
})
|
|
126471
|
+
]
|
|
126472
|
+
})
|
|
125802
126473
|
})
|
|
125803
126474
|
]
|
|
125804
126475
|
}),
|
|
@@ -150319,10 +150990,6 @@ if ("serviceWorker" in navigator) {
|
|
|
150319
150990
|
inset-block: calc(var(--spacing) * 0);
|
|
150320
150991
|
}
|
|
150321
150992
|
|
|
150322
|
-
.-top-3 {
|
|
150323
|
-
top: calc(var(--spacing) * -3);
|
|
150324
|
-
}
|
|
150325
|
-
|
|
150326
150993
|
.top-0 {
|
|
150327
150994
|
top: calc(var(--spacing) * 0);
|
|
150328
150995
|
}
|
|
@@ -150363,6 +151030,14 @@ if ("serviceWorker" in navigator) {
|
|
|
150363
151030
|
bottom: calc(var(--spacing) * -.5);
|
|
150364
151031
|
}
|
|
150365
151032
|
|
|
151033
|
+
.-bottom-2\.5 {
|
|
151034
|
+
bottom: calc(var(--spacing) * -2.5);
|
|
151035
|
+
}
|
|
151036
|
+
|
|
151037
|
+
.bottom-full {
|
|
151038
|
+
bottom: 100%;
|
|
151039
|
+
}
|
|
151040
|
+
|
|
150366
151041
|
.left-0 {
|
|
150367
151042
|
left: calc(var(--spacing) * 0);
|
|
150368
151043
|
}
|
|
@@ -150998,6 +151673,10 @@ if ("serviceWorker" in navigator) {
|
|
|
150998
151673
|
max-width: var(--container-2xl);
|
|
150999
151674
|
}
|
|
151000
151675
|
|
|
151676
|
+
.max-w-\[12rem\] {
|
|
151677
|
+
max-width: 12rem;
|
|
151678
|
+
}
|
|
151679
|
+
|
|
151001
151680
|
.max-w-\[18rem\] {
|
|
151002
151681
|
max-width: 18rem;
|
|
151003
151682
|
}
|
|
@@ -151406,6 +152085,10 @@ if ("serviceWorker" in navigator) {
|
|
|
151406
152085
|
column-gap: calc(var(--spacing) * 4);
|
|
151407
152086
|
}
|
|
151408
152087
|
|
|
152088
|
+
.gap-y-0\.5 {
|
|
152089
|
+
row-gap: calc(var(--spacing) * .5);
|
|
152090
|
+
}
|
|
152091
|
+
|
|
151409
152092
|
.gap-y-1 {
|
|
151410
152093
|
row-gap: calc(var(--spacing) * 1);
|
|
151411
152094
|
}
|
|
@@ -151590,6 +152273,16 @@ if ("serviceWorker" in navigator) {
|
|
|
151590
152273
|
}
|
|
151591
152274
|
}
|
|
151592
152275
|
|
|
152276
|
+
.border-amber-500\/20 {
|
|
152277
|
+
border-color: #f99c0033;
|
|
152278
|
+
}
|
|
152279
|
+
|
|
152280
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
152281
|
+
.border-amber-500\/20 {
|
|
152282
|
+
border-color: color-mix(in oklab, var(--color-amber-500) 20%, transparent);
|
|
152283
|
+
}
|
|
152284
|
+
}
|
|
152285
|
+
|
|
151593
152286
|
.border-amber-500\/25 {
|
|
151594
152287
|
border-color: #f99c0040;
|
|
151595
152288
|
}
|
|
@@ -151912,6 +152605,16 @@ if ("serviceWorker" in navigator) {
|
|
|
151912
152605
|
border-color: #0000;
|
|
151913
152606
|
}
|
|
151914
152607
|
|
|
152608
|
+
.border-violet-500\/20 {
|
|
152609
|
+
border-color: #8d54ff33;
|
|
152610
|
+
}
|
|
152611
|
+
|
|
152612
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
152613
|
+
.border-violet-500\/20 {
|
|
152614
|
+
border-color: color-mix(in oklab, var(--color-violet-500) 20%, transparent);
|
|
152615
|
+
}
|
|
152616
|
+
}
|
|
152617
|
+
|
|
151915
152618
|
.border-violet-500\/30 {
|
|
151916
152619
|
border-color: #8d54ff4d;
|
|
151917
152620
|
}
|
|
@@ -152890,6 +153593,10 @@ if ("serviceWorker" in navigator) {
|
|
|
152890
153593
|
font-size: 9px;
|
|
152891
153594
|
}
|
|
152892
153595
|
|
|
153596
|
+
.text-\[10\.5px\] {
|
|
153597
|
+
font-size: 10.5px;
|
|
153598
|
+
}
|
|
153599
|
+
|
|
152893
153600
|
.text-\[10px\] {
|
|
152894
153601
|
font-size: 10px;
|
|
152895
153602
|
}
|
|
@@ -153124,6 +153831,16 @@ if ("serviceWorker" in navigator) {
|
|
|
153124
153831
|
}
|
|
153125
153832
|
}
|
|
153126
153833
|
|
|
153834
|
+
.text-muted-foreground\/70 {
|
|
153835
|
+
color: var(--muted-foreground);
|
|
153836
|
+
}
|
|
153837
|
+
|
|
153838
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
153839
|
+
.text-muted-foreground\/70 {
|
|
153840
|
+
color: color-mix(in oklab, var(--muted-foreground) 70%, transparent);
|
|
153841
|
+
}
|
|
153842
|
+
}
|
|
153843
|
+
|
|
153127
153844
|
.text-muted-foreground\/80 {
|
|
153128
153845
|
color: var(--muted-foreground);
|
|
153129
153846
|
}
|
|
@@ -153330,6 +154047,10 @@ if ("serviceWorker" in navigator) {
|
|
|
153330
154047
|
opacity: .6;
|
|
153331
154048
|
}
|
|
153332
154049
|
|
|
154050
|
+
.opacity-70 {
|
|
154051
|
+
opacity: .7;
|
|
154052
|
+
}
|
|
154053
|
+
|
|
153333
154054
|
.opacity-80 {
|
|
153334
154055
|
opacity: .8;
|
|
153335
154056
|
}
|
|
@@ -154029,6 +154750,10 @@ if ("serviceWorker" in navigator) {
|
|
|
154029
154750
|
opacity: .5;
|
|
154030
154751
|
}
|
|
154031
154752
|
|
|
154753
|
+
.disabled\:opacity-60:disabled {
|
|
154754
|
+
opacity: .6;
|
|
154755
|
+
}
|
|
154756
|
+
|
|
154032
154757
|
.disabled\:opacity-70:disabled {
|
|
154033
154758
|
opacity: .7;
|
|
154034
154759
|
}
|