@agimon-ai/po-template-elegant 0.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1264 @@
1
+ import { defineWebPlugin, defineWebTemplate } from "@agimon-ai/po-core/web";
2
+ import { DEFAULT_REPOSITORY_SETTINGS_SECTION, DEFAULT_SETTINGS_SECTION, DashboardRendererProvider, HOST_SLOTS, findTransientTab, pluginActivityGroups, refreshWebPluginCompositions, sessionsStore, setDockOpen, settingsSection, transientTabsStore, uiStore, updateWorkspaceAdmission, useActiveSession, useActiveSessionMeta, useDashboardRoute, useDashboardState, useNoSessions, usePluginSlotProps, useSessionMcp, useWebPluginRegistry, watchDashboardTranscript, webTabs, workspaceAdmissionStore, workspacesStore } from "@agimon-ai/po-web-dashboard";
3
+ import { ActivityDock, AppearanceSettings, CommandPalette, Composer, ContributedSettings, DialogOverlay, ImageSettings, NotificationSettings, PairingApprovalDialog, PluginSettings, PluginSurface, ProviderSettings, RefusedCard, RemoteAccessDialog, RemoteControlSettings, RepositoryWorkspace, SelectionBar, SessionActivity, SessionMcp, SessionRailDialogs, SessionTranscriptView, SettingsMenu, SettingsPanelHost, ThreadView, Timeline, TopBar, WelcomePanel, useSessionRail } from "@agimon-ai/po-web-dashboard/views";
4
+ import { useStore } from "@tanstack/react-store";
5
+ import { useEffect, useRef, useState } from "react";
6
+ import { ActivityIcon, AlertIcon, Avatar, AvatarFallback, AvatarImage, BranchIcon, Button, ChevronUpIcon, CloseIcon, Dialog, DialogBody, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, Dot, Drawer, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, FolderIcon, ForkIcon, GearIcon, Input, Kbd, KebabIcon, LoaderIcon, NavTab, OptionRow, PlusIcon, ShieldIcon, cn } from "@agimon-ai/po-web-components";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
+ import { Link, useNavigate } from "@tanstack/react-router";
9
+ //#region src/extensions/(frontend)/template/_components/ElegantFolderBrowser.tsx
10
+ function folderName$1(path) {
11
+ return path.slice(path.lastIndexOf("/") + 1) || path;
12
+ }
13
+ /** Walks the server's folders inline: up, into a child, or pick the current folder. */
14
+ function ElegantFolderBrowser({ start, listDirectory, onSelect }) {
15
+ const [target, setTarget] = useState(start);
16
+ const [listing, setListing] = useState(null);
17
+ const [error, setError] = useState("");
18
+ useEffect(() => {
19
+ let stale = false;
20
+ listDirectory(target).then((result) => {
21
+ if (stale) return;
22
+ if ("error" in result) setError(result.error);
23
+ else {
24
+ setError("");
25
+ setListing(result);
26
+ }
27
+ });
28
+ return () => {
29
+ stale = true;
30
+ };
31
+ }, [target, listDirectory]);
32
+ return /* @__PURE__ */ jsxs("div", {
33
+ "data-testid": "folder-browser",
34
+ className: "flex flex-col gap-1 rounded-lg border border-doom-border-soft bg-doom-panel/40 p-1.5",
35
+ children: [
36
+ /* @__PURE__ */ jsxs("div", {
37
+ className: "flex items-center gap-1 px-1",
38
+ children: [
39
+ /* @__PURE__ */ jsx(Button, {
40
+ variant: "ghost",
41
+ size: "icon",
42
+ "data-testid": "folder-browser-up",
43
+ title: "parent folder",
44
+ "aria-label": "parent folder",
45
+ disabled: listing?.parent === void 0,
46
+ onClick: () => listing?.parent !== void 0 && setTarget(listing.parent),
47
+ children: /* @__PURE__ */ jsx(ChevronUpIcon, { className: "h-3 w-3" })
48
+ }),
49
+ /* @__PURE__ */ jsx("span", {
50
+ className: "min-w-0 flex-1 truncate text-sm text-doom-dim",
51
+ title: listing?.path,
52
+ children: listing?.path ?? "loading…"
53
+ }),
54
+ /* @__PURE__ */ jsx(Button, {
55
+ variant: "outline",
56
+ size: "xs",
57
+ "data-testid": "folder-browser-select",
58
+ disabled: listing === null,
59
+ onClick: () => listing !== null && onSelect(listing.path),
60
+ children: "use this folder"
61
+ })
62
+ ]
63
+ }),
64
+ error ? /* @__PURE__ */ jsx("p", {
65
+ className: "px-2 py-1 text-sm text-doom-red",
66
+ children: error
67
+ }) : null,
68
+ /* @__PURE__ */ jsxs("div", {
69
+ role: "listbox",
70
+ "aria-label": "folders",
71
+ className: "max-h-40 overflow-y-auto",
72
+ children: [listing !== null && listing.directories.length === 0 ? /* @__PURE__ */ jsx("p", {
73
+ className: "px-2 py-1 text-sm text-doom-dim",
74
+ children: "no folders here"
75
+ }) : null, listing?.directories.map((directory) => /* @__PURE__ */ jsx(OptionRow, {
76
+ density: "compact",
77
+ "data-testid": "folder-browser-entry",
78
+ onClick: () => setTarget(directory),
79
+ className: "w-full px-2.5 py-1 ",
80
+ children: folderName$1(directory)
81
+ }, directory))]
82
+ })
83
+ ]
84
+ });
85
+ }
86
+ //#endregion
87
+ //#region src/extensions/(frontend)/template/_components/ElegantAddWorkspaceDialog.tsx
88
+ const SUGGESTION_DEBOUNCE_MS = 120;
89
+ const NO_HIGHLIGHT = -1;
90
+ const TRAILING_SEPARATORS = /\/+$/u;
91
+ function folderName(path) {
92
+ const trimmed = path.trim().replace(TRAILING_SEPARATORS, "");
93
+ return trimmed.slice(trimmed.lastIndexOf("/") + 1);
94
+ }
95
+ /** Adds a workspace by name, by folder, or both; a name alone gets a new default folder. */
96
+ function ElegantAddWorkspaceDialog({ suggestedPaths, actions }) {
97
+ const draft = useStore(workspaceAdmissionStore, (state) => state);
98
+ const { name, nameEdited, pending: busy, error } = draft;
99
+ const path = draft.path ?? suggestedPaths[0] ?? "";
100
+ const setName = (name) => updateWorkspaceAdmission({ name });
101
+ const setNameEdited = (nameEdited) => updateWorkspaceAdmission({ nameEdited });
102
+ const setPath = (path) => updateWorkspaceAdmission({ path });
103
+ const [browsing, setBrowsing] = useState(false);
104
+ const [suggestions, setSuggestions] = useState([]);
105
+ const [highlight, setHighlight] = useState(NO_HIGHLIGHT);
106
+ const pathInput = useRef(null);
107
+ const shownName = nameEdited ? name : folderName(path);
108
+ useEffect(() => {
109
+ const typed = path.trim();
110
+ if (typed === "") return;
111
+ let stale = false;
112
+ const timer = setTimeout(async () => {
113
+ const found = await actions.searchDirectories(typed);
114
+ if (stale) return;
115
+ setSuggestions(found.filter((directory) => directory !== typed));
116
+ setHighlight(NO_HIGHLIGHT);
117
+ }, SUGGESTION_DEBOUNCE_MS);
118
+ return () => {
119
+ stale = true;
120
+ clearTimeout(timer);
121
+ };
122
+ }, [path, actions]);
123
+ const changePath = (next) => {
124
+ setPath(next);
125
+ if (next.trim() === "") setSuggestions([]);
126
+ };
127
+ const pick = (directory) => {
128
+ changePath(`${directory}/`);
129
+ pathInput.current?.focus();
130
+ };
131
+ const trimmedPath = path.trim().replace(TRAILING_SEPARATORS, "") || (path.trim() === "" ? "" : "/");
132
+ const canSubmit = !busy && (trimmedPath !== "" || shownName.trim() !== "");
133
+ const submit = async () => {
134
+ if (!canSubmit) return;
135
+ await actions.addWorkspace({
136
+ name: shownName.trim(),
137
+ ...trimmedPath === "" ? {} : { path: trimmedPath }
138
+ });
139
+ };
140
+ return /* @__PURE__ */ jsx(Dialog, {
141
+ open: true,
142
+ onOpenChange: (next) => !next && !busy && actions.closeAddWorkspace(),
143
+ children: /* @__PURE__ */ jsxs(DialogContent, {
144
+ width: "md",
145
+ "data-testid": "add-workspace-dialog",
146
+ "aria-describedby": void 0,
147
+ children: [/* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: "add workspace" }) }), /* @__PURE__ */ jsxs(DialogBody, { children: [
148
+ /* @__PURE__ */ jsxs("label", {
149
+ htmlFor: "add-workspace-name",
150
+ className: "flex flex-col gap-1",
151
+ children: [/* @__PURE__ */ jsx("span", {
152
+ className: "text-base font-medium text-doom-dim",
153
+ children: "name"
154
+ }), /* @__PURE__ */ jsx(Input, {
155
+ id: "add-workspace-name",
156
+ "data-testid": "add-workspace-name",
157
+ value: shownName,
158
+ autoFocus: true,
159
+ onChange: (event) => {
160
+ setNameEdited(true);
161
+ setName(event.target.value);
162
+ },
163
+ onKeyDown: (event) => {
164
+ if (event.key === "Enter") submit();
165
+ },
166
+ placeholder: "my-project"
167
+ })]
168
+ }),
169
+ /* @__PURE__ */ jsxs("label", {
170
+ htmlFor: "add-workspace-root",
171
+ className: "flex flex-col gap-1",
172
+ children: [/* @__PURE__ */ jsxs("span", {
173
+ className: "text-base font-medium text-doom-dim",
174
+ children: ["folder ", /* @__PURE__ */ jsx("span", {
175
+ className: "text-doom-dim",
176
+ children: "(optional; type a path or browse)"
177
+ })]
178
+ }), /* @__PURE__ */ jsxs("span", {
179
+ className: "flex items-center gap-1.5",
180
+ children: [/* @__PURE__ */ jsx(Input, {
181
+ id: "add-workspace-root",
182
+ ref: pathInput,
183
+ "data-testid": "add-workspace-root",
184
+ value: path,
185
+ onChange: (event) => changePath(event.target.value),
186
+ onKeyDown: (event) => {
187
+ if (event.key === "ArrowDown" && suggestions.length > 0) {
188
+ event.preventDefault();
189
+ setHighlight((current) => (current + 1) % suggestions.length);
190
+ } else if (event.key === "ArrowUp" && suggestions.length > 0) {
191
+ event.preventDefault();
192
+ setHighlight((current) => current <= 0 ? suggestions.length - 1 : current - 1);
193
+ } else if (event.key === "Enter") {
194
+ const chosen = highlight === NO_HIGHLIGHT ? void 0 : suggestions[highlight];
195
+ if (chosen === void 0) submit();
196
+ else pick(chosen);
197
+ }
198
+ },
199
+ placeholder: "~/workspace/my-project",
200
+ className: "min-w-0 flex-1"
201
+ }), /* @__PURE__ */ jsx(Button, {
202
+ variant: browsing ? "subtle" : "outline",
203
+ size: "md",
204
+ "data-testid": "add-workspace-browse",
205
+ "aria-pressed": browsing,
206
+ onClick: () => setBrowsing((open) => !open),
207
+ children: "browse"
208
+ })]
209
+ })]
210
+ }),
211
+ browsing ? /* @__PURE__ */ jsx(ElegantFolderBrowser, {
212
+ ...trimmedPath.startsWith("/") ? { start: trimmedPath } : {},
213
+ listDirectory: actions.listDirectory,
214
+ onSelect: (selected) => {
215
+ changePath(selected);
216
+ setBrowsing(false);
217
+ }
218
+ }) : suggestions.length > 0 ? /* @__PURE__ */ jsx("div", {
219
+ role: "listbox",
220
+ "aria-label": "matching directories",
221
+ "data-testid": "add-workspace-suggestions",
222
+ className: "max-h-40 overflow-y-auto rounded-lg border border-doom-border-soft bg-doom-panel/40 p-1.5",
223
+ children: suggestions.map((directory, index) => /* @__PURE__ */ jsx(OptionRow, {
224
+ density: "compact",
225
+ active: index === highlight,
226
+ "data-testid": "add-workspace-suggestion",
227
+ onMouseDown: (event) => event.preventDefault(),
228
+ onMouseEnter: () => setHighlight(index),
229
+ onClick: () => pick(directory),
230
+ className: "w-full px-2.5 py-1 ",
231
+ children: directory
232
+ }, directory))
233
+ }) : null,
234
+ suggestedPaths.length > 0 ? /* @__PURE__ */ jsx("div", {
235
+ className: "flex flex-wrap gap-1",
236
+ children: suggestedPaths.slice(0, 4).map((suggested) => /* @__PURE__ */ jsx(Button, {
237
+ variant: "outline",
238
+ size: "xs",
239
+ onClick: () => changePath(suggested),
240
+ children: suggested
241
+ }, suggested))
242
+ }) : null,
243
+ trimmedPath === "" && shownName.trim() !== "" ? /* @__PURE__ */ jsxs("p", {
244
+ "data-testid": "add-workspace-default-hint",
245
+ className: "text-sm text-doom-dim",
246
+ children: ["creates ~/.po/workspace/", shownName.trim()]
247
+ }) : null,
248
+ error ? /* @__PURE__ */ jsx("pre", {
249
+ className: "max-h-28 overflow-y-auto rounded border border-doom-edge-red bg-doom-tint-red/40 px-2.5 py-2 text-sm whitespace-pre-wrap text-doom-red",
250
+ children: error
251
+ }) : null,
252
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [/* @__PURE__ */ jsx(Button, {
253
+ variant: "outline",
254
+ onClick: () => actions.closeAddWorkspace(),
255
+ disabled: busy,
256
+ children: "cancel"
257
+ }), /* @__PURE__ */ jsx(Button, {
258
+ variant: "primary",
259
+ "data-testid": "add-workspace-confirm",
260
+ onClick: () => void submit(),
261
+ disabled: !canSubmit,
262
+ children: busy ? "adding…" : "add workspace"
263
+ })] })
264
+ ] })]
265
+ })
266
+ });
267
+ }
268
+ //#endregion
269
+ //#region src/extensions/(frontend)/template/_components/ElegantPendingSetup.tsx
270
+ /** A setup-only reservation: no runtime, so it offers removal and nothing else. */
271
+ function ElegantPendingSetup({ sessionId, setup, actions }) {
272
+ const key = JSON.stringify([
273
+ "rail/setup",
274
+ sessionId,
275
+ setup.id
276
+ ]);
277
+ const [busy, setBusy, busyState] = useDashboardState(`${key}/busy`, false);
278
+ const [error, setError] = useDashboardState(`${key}/error`, "");
279
+ const remove = async () => {
280
+ if (busyState.state) return;
281
+ setBusy(true);
282
+ setError("");
283
+ const result = await actions.removePendingSetup(sessionId, setup.id);
284
+ setBusy(false);
285
+ if (result !== void 0) setError(result.error);
286
+ };
287
+ return /* @__PURE__ */ jsxs("div", {
288
+ "data-testid": `pending-session-${setup.id}`,
289
+ className: "ml-9 flex flex-col gap-0.5 rounded-lg border border-dashed border-doom-border-soft px-3 py-2",
290
+ children: [
291
+ /* @__PURE__ */ jsxs("div", {
292
+ className: "flex items-center justify-between gap-2",
293
+ children: [/* @__PURE__ */ jsx("span", {
294
+ className: "truncate text-base font-semibold text-doom-hi",
295
+ children: setup.name
296
+ }), /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
297
+ asChild: true,
298
+ children: /* @__PURE__ */ jsx(Button, {
299
+ variant: "ghost",
300
+ size: "icon",
301
+ title: "session setup actions",
302
+ disabled: busy,
303
+ "data-testid": `pending-session-menu-${setup.id}`,
304
+ children: /* @__PURE__ */ jsx(KebabIcon, { className: "h-3 w-3" })
305
+ })
306
+ }), /* @__PURE__ */ jsx(DropdownMenuContent, { children: /* @__PURE__ */ jsx(DropdownMenuItem, {
307
+ variant: "destructive",
308
+ onSelect: () => void remove(),
309
+ children: "remove setup"
310
+ }) })] })]
311
+ }),
312
+ /* @__PURE__ */ jsx("p", {
313
+ className: setup.failed ? "text-sm text-doom-red" : "text-sm text-doom-dim",
314
+ children: setup.status
315
+ }),
316
+ setup.recovery ? /* @__PURE__ */ jsx("p", {
317
+ role: setup.failed ? "alert" : void 0,
318
+ className: "text-sm text-doom-dim",
319
+ children: setup.recovery
320
+ }) : null,
321
+ error ? /* @__PURE__ */ jsx("p", {
322
+ role: "alert",
323
+ className: "text-sm text-doom-red",
324
+ children: error
325
+ }) : null
326
+ ]
327
+ });
328
+ }
329
+ //#endregion
330
+ //#region src/extensions/(frontend)/template/_components/ElegantSessionCard.tsx
331
+ /** A soft tile led by the persona avatar, with the branch as a quiet caption. */
332
+ function ElegantSessionCard({ session, actions }) {
333
+ const key = `rail/session/${session.id}`;
334
+ const [mode, setMode] = useDashboardState(`${key}/mode`, "view");
335
+ const [draft, setDraft] = useDashboardState(`${key}/draft`, "");
336
+ const [removeError, setRemoveError] = useDashboardState(`${key}/error`, "");
337
+ const [, setRemoving, removingState] = useDashboardState(`${key}/removing`, false);
338
+ const modeRef = useRef(mode);
339
+ const enterMode = (next) => {
340
+ modeRef.current = next;
341
+ setMode(next);
342
+ };
343
+ const { active } = session;
344
+ const error = removeError || session.error;
345
+ const tileClass = active ? "rounded-lg border border-doom-edge-green bg-doom-tint-green px-3 hover:bg-doom-tint-green" : "rounded-lg border border-transparent px-3 hover:bg-doom-panel";
346
+ const failed = session.status.startsWith("failed") || session.status.includes(" failed");
347
+ const running = session.status.startsWith("running");
348
+ const commitRename = () => {
349
+ actions.renameSession(session.id, draft);
350
+ enterMode("view");
351
+ };
352
+ const remove = async () => {
353
+ if (removingState.state) return;
354
+ setRemoving(true);
355
+ enterMode("view");
356
+ setRemoveError("");
357
+ const result = await actions.removeSession(session.id);
358
+ setRemoving(false);
359
+ if (result !== void 0) setRemoveError(result.error);
360
+ };
361
+ const body = /* @__PURE__ */ jsxs(Fragment, { children: [
362
+ /* @__PURE__ */ jsxs("span", {
363
+ className: "flex w-full min-w-0 items-start gap-2.5",
364
+ children: [/* @__PURE__ */ jsxs(Avatar, {
365
+ "data-testid": session.profile ? "session-avatar" : void 0,
366
+ "aria-label": session.profile?.label ?? "Po",
367
+ title: session.profile?.label,
368
+ className: "size-8 shrink-0 rounded-full",
369
+ children: [session.profile?.avatarUrl ? /* @__PURE__ */ jsx(AvatarImage, {
370
+ src: session.profile.avatarUrl,
371
+ alt: ""
372
+ }) : null, /* @__PURE__ */ jsx(AvatarFallback, {
373
+ className: "bg-doom-tint-green text-xs font-semibold text-doom-green",
374
+ children: session.profile?.initials ?? "PO"
375
+ })]
376
+ }), /* @__PURE__ */ jsxs("span", {
377
+ className: "flex min-w-0 flex-1 flex-col gap-0.5",
378
+ children: [/* @__PURE__ */ jsxs("span", {
379
+ className: "flex min-w-0 items-start gap-2",
380
+ children: [
381
+ session.nested && session.provenance === "workflow-session" ? /* @__PURE__ */ jsx(ActivityIcon, {
382
+ "aria-label": "workflow session",
383
+ className: `mt-1 size-3 shrink-0 ${active ? "text-doom-green" : "text-doom-faint"}`
384
+ }) : session.nested && session.provenance ? /* @__PURE__ */ jsx(ForkIcon, {
385
+ "aria-label": session.provenance === "worktree" ? "automatic per-conversation worktree" : session.provenance,
386
+ className: `mt-1 size-3 shrink-0 ${active ? "text-doom-green" : "text-doom-faint"}`
387
+ }) : null,
388
+ /* @__PURE__ */ jsx("span", {
389
+ className: "min-w-0 flex-1 text-base font-semibold break-words text-doom-hi",
390
+ children: session.name || "Untitled"
391
+ }),
392
+ session.ordinal <= 9 ? /* @__PURE__ */ jsx("span", {
393
+ title: `press ${String(session.ordinal)} to focus`,
394
+ className: "grid size-5 shrink-0 place-items-center rounded-full bg-doom-panel text-2xs text-doom-dim transition-opacity group-focus-within:opacity-0 group-hover:opacity-0",
395
+ children: session.ordinal
396
+ }) : null
397
+ ]
398
+ }), /* @__PURE__ */ jsxs("span", {
399
+ className: `flex min-w-0 items-start gap-1.5 text-sm leading-snug ${failed ? "text-doom-red" : running ? "text-doom-yellow" : active ? "text-doom-text" : "text-doom-dim"}`,
400
+ children: [session.awaitingInput ? /* @__PURE__ */ jsx(AlertIcon, {
401
+ "data-testid": "session-awaiting-input",
402
+ "aria-label": "Waiting for your input",
403
+ className: "mt-0.5 size-3 shrink-0 text-doom-magenta"
404
+ }) : running ? /* @__PURE__ */ jsx(LoaderIcon, {
405
+ "aria-hidden": true,
406
+ className: "mt-0.5 size-3 shrink-0 animate-spin"
407
+ }) : failed ? /* @__PURE__ */ jsx(AlertIcon, {
408
+ "aria-hidden": true,
409
+ className: "mt-0.5 size-3 shrink-0"
410
+ }) : null, /* @__PURE__ */ jsx("span", {
411
+ "data-testid": "session-status",
412
+ className: active ? "line-clamp-2" : "truncate",
413
+ children: session.status
414
+ })]
415
+ })]
416
+ })]
417
+ }),
418
+ session.git ? /* @__PURE__ */ jsxs("span", {
419
+ "data-testid": "session-branch",
420
+ className: "flex min-w-0 items-center gap-1.5 pl-10.5 text-sm text-doom-dim",
421
+ children: [
422
+ /* @__PURE__ */ jsx(BranchIcon, { className: `size-3 shrink-0 ${active ? "text-doom-green" : ""}` }),
423
+ /* @__PURE__ */ jsx("span", {
424
+ className: "truncate font-mono",
425
+ children: session.git.branch
426
+ }),
427
+ session.git.dirty ? /* @__PURE__ */ jsx("span", {
428
+ className: "shrink-0 text-doom-yellow",
429
+ children: "modified"
430
+ }) : null
431
+ ]
432
+ }) : null,
433
+ error ? /* @__PURE__ */ jsx("span", {
434
+ "data-testid": "session-error",
435
+ className: "line-clamp-3 text-sm break-words text-doom-red",
436
+ children: error
437
+ }) : null
438
+ ] });
439
+ const menuOpen = mode === "menu";
440
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
441
+ className: cn("group relative", session.nested && "pl-5"),
442
+ "data-testid": `session-card-${session.id}`,
443
+ "data-active": active,
444
+ "data-nested": session.nested,
445
+ children: [
446
+ /* @__PURE__ */ jsx(Button, {
447
+ variant: "ghost",
448
+ size: "card",
449
+ "data-testid": `session-open-${session.id}`,
450
+ onClick: () => actions.openSession(session.id),
451
+ className: tileClass,
452
+ children: body
453
+ }),
454
+ mode === "view" || menuOpen ? /* @__PURE__ */ jsx("div", {
455
+ className: `absolute top-2 right-2 transition-opacity ${menuOpen ? "opacity-100" : "opacity-0 group-focus-within:opacity-100 group-hover:opacity-100"}`,
456
+ children: /* @__PURE__ */ jsxs(DropdownMenu, {
457
+ open: menuOpen,
458
+ onOpenChange: (next) => {
459
+ const current = modeRef.current;
460
+ enterMode(next ? "menu" : current === "menu" ? "view" : current);
461
+ },
462
+ children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
463
+ asChild: true,
464
+ children: /* @__PURE__ */ jsx(Button, {
465
+ variant: "ghost",
466
+ size: "icon",
467
+ "data-testid": `session-menu-${session.id}`,
468
+ title: "session actions",
469
+ className: "text-doom-dim hover:text-doom-hi",
470
+ children: /* @__PURE__ */ jsx(KebabIcon, { className: "h-3 w-3" })
471
+ })
472
+ }), /* @__PURE__ */ jsxs(DropdownMenuContent, {
473
+ "data-testid": `session-menu-list-${session.id}`,
474
+ onCloseAutoFocus: (event) => {
475
+ if (modeRef.current !== "view") event.preventDefault();
476
+ },
477
+ children: [
478
+ actions.renderSessionMenuItems(session.id),
479
+ /* @__PURE__ */ jsx(DropdownMenuItem, {
480
+ "data-testid": `session-rename-${session.id}`,
481
+ onSelect: () => {
482
+ setDraft(session.name);
483
+ enterMode("rename");
484
+ },
485
+ children: "rename"
486
+ }),
487
+ /* @__PURE__ */ jsx(DropdownMenuItem, {
488
+ "data-testid": `session-resume-${session.id}`,
489
+ onSelect: () => actions.resumeSession(session.id),
490
+ children: "resume"
491
+ }),
492
+ /* @__PURE__ */ jsx(DropdownMenuItem, {
493
+ "data-testid": `session-restart-${session.id}`,
494
+ disabled: session.restarting || session.restartBlocked === true,
495
+ onSelect: () => actions.restartSession(session.id),
496
+ children: "restart"
497
+ }),
498
+ /* @__PURE__ */ jsx(DropdownMenuItem, {
499
+ variant: "destructive",
500
+ "data-testid": `session-stop-${session.id}`,
501
+ onSelect: () => enterMode("confirm"),
502
+ children: "remove"
503
+ })
504
+ ]
505
+ })]
506
+ })
507
+ }) : null,
508
+ /* @__PURE__ */ jsx(Dialog, {
509
+ open: mode === "rename",
510
+ onOpenChange: (next) => !next && enterMode("view"),
511
+ children: /* @__PURE__ */ jsxs(DialogContent, {
512
+ width: "sm",
513
+ "data-testid": `session-rename-dialog-${session.id}`,
514
+ "aria-describedby": void 0,
515
+ children: [/* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: "rename session" }) }), /* @__PURE__ */ jsx(DialogBody, { children: /* @__PURE__ */ jsxs("form", {
516
+ className: "flex flex-col gap-3",
517
+ onSubmit: (event) => {
518
+ event.preventDefault();
519
+ commitRename();
520
+ },
521
+ children: [/* @__PURE__ */ jsx(Input, {
522
+ "data-testid": `session-name-input-${session.id}`,
523
+ "aria-label": "session name",
524
+ value: draft,
525
+ autoFocus: true,
526
+ onChange: (event) => setDraft(event.target.value)
527
+ }), /* @__PURE__ */ jsxs(DialogFooter, { children: [/* @__PURE__ */ jsx(Button, {
528
+ type: "button",
529
+ variant: "outline",
530
+ size: "md",
531
+ "data-testid": `session-rename-cancel-${session.id}`,
532
+ onClick: () => enterMode("view"),
533
+ children: "cancel"
534
+ }), /* @__PURE__ */ jsx(Button, {
535
+ type: "submit",
536
+ variant: "primary",
537
+ size: "md",
538
+ "data-testid": `session-rename-confirm-${session.id}`,
539
+ disabled: draft.trim() === "",
540
+ children: "rename"
541
+ })] })]
542
+ }) })]
543
+ })
544
+ }),
545
+ /* @__PURE__ */ jsx(Dialog, {
546
+ open: mode === "confirm",
547
+ onOpenChange: (next) => !next && enterMode("view"),
548
+ children: /* @__PURE__ */ jsxs(DialogContent, {
549
+ width: "sm",
550
+ "data-testid": `session-stop-dialog-${session.id}`,
551
+ "aria-describedby": void 0,
552
+ children: [/* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: "remove session" }) }), /* @__PURE__ */ jsxs(DialogBody, { children: [/* @__PURE__ */ jsxs(DialogDescription, { children: [
553
+ "this stops ",
554
+ /* @__PURE__ */ jsx("span", {
555
+ className: "font-semibold text-doom-hi",
556
+ children: session.name || "untitled"
557
+ }),
558
+ " and removes it from the list. anything it is running ends now, but its saved history remains available to resume."
559
+ ] }), /* @__PURE__ */ jsxs(DialogFooter, { children: [/* @__PURE__ */ jsx(Button, {
560
+ variant: "outline",
561
+ size: "md",
562
+ "data-testid": `session-stop-cancel-${session.id}`,
563
+ autoFocus: true,
564
+ onClick: () => enterMode("view"),
565
+ children: "cancel"
566
+ }), /* @__PURE__ */ jsx(Button, {
567
+ variant: "danger",
568
+ size: "md",
569
+ "data-testid": `session-stop-confirm-${session.id}`,
570
+ onClick: () => void remove(),
571
+ children: "remove"
572
+ })] })] })]
573
+ })
574
+ })
575
+ ]
576
+ }), session.pendingSetups.map((setup) => /* @__PURE__ */ jsx(ElegantPendingSetup, {
577
+ sessionId: session.id,
578
+ setup,
579
+ actions
580
+ }, `setup:${setup.id}`))] });
581
+ }
582
+ //#endregion
583
+ //#region src/extensions/(frontend)/template/_components/ElegantWorkspaceGroup.tsx
584
+ /** A folder heading over its sessions; only a hover tint marks the row. */
585
+ function ElegantWorkspaceGroup({ workspace, actions }) {
586
+ const key = `rail/workspace/${workspace.id}`;
587
+ const [removeOpen, setRemoveOpen] = useDashboardState(`${key}/open`, false);
588
+ const [removeError, setRemoveError] = useDashboardState(`${key}/error`, "");
589
+ const [removing, setRemoving, removingState] = useDashboardState(`${key}/removing`, false);
590
+ const { id, name, root, available, legacy } = workspace;
591
+ const unregister = async () => {
592
+ if (removingState.state) return;
593
+ setRemoving(true);
594
+ setRemoveError("");
595
+ const result = await actions.deleteWorkspace(id);
596
+ setRemoving(false);
597
+ if (result !== void 0) setRemoveError(result.error);
598
+ else setRemoveOpen(false);
599
+ };
600
+ return /* @__PURE__ */ jsxs("section", {
601
+ "data-testid": `workspace-group-${id}`,
602
+ "data-available": available,
603
+ className: "flex flex-col gap-1.5",
604
+ children: [
605
+ /* @__PURE__ */ jsxs("div", {
606
+ className: "flex min-w-0 items-start gap-2.5 rounded-md px-2 py-1 transition-colors hover:bg-doom-panel/60",
607
+ children: [
608
+ /* @__PURE__ */ jsx(FolderIcon, {
609
+ "aria-hidden": true,
610
+ className: "mt-0.5 size-4 shrink-0 text-doom-dim"
611
+ }),
612
+ /* @__PURE__ */ jsxs("div", {
613
+ className: "flex min-w-0 flex-1 flex-col",
614
+ children: [/* @__PURE__ */ jsx("p", {
615
+ className: "truncate text-base font-semibold text-doom-hi",
616
+ children: name
617
+ }), /* @__PURE__ */ jsx("p", {
618
+ className: "truncate font-mono text-sm text-doom-dim",
619
+ title: root,
620
+ children: root
621
+ })]
622
+ }),
623
+ legacy ? null : /* @__PURE__ */ jsxs("span", {
624
+ className: "flex items-center gap-0.5",
625
+ children: [/* @__PURE__ */ jsx(Button, {
626
+ variant: "ghost",
627
+ size: "icon",
628
+ "data-testid": `workspace-new-session-${id}`,
629
+ title: "New session",
630
+ "aria-label": `New session in ${name}`,
631
+ disabled: !available,
632
+ onClick: () => actions.createSession(id),
633
+ className: "text-doom-faint hover:text-doom-hi",
634
+ children: /* @__PURE__ */ jsx(PlusIcon, { className: "size-3.5" })
635
+ }), /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
636
+ asChild: true,
637
+ children: /* @__PURE__ */ jsx(Button, {
638
+ variant: "ghost",
639
+ size: "icon",
640
+ "data-testid": `workspace-menu-${id}`,
641
+ title: "Workspace actions",
642
+ "aria-label": `${name} actions`,
643
+ className: "text-doom-faint hover:text-doom-hi",
644
+ children: /* @__PURE__ */ jsx(KebabIcon, { className: "size-3.5" })
645
+ })
646
+ }), /* @__PURE__ */ jsxs(DropdownMenuContent, { children: [
647
+ /* @__PURE__ */ jsx(DropdownMenuItem, {
648
+ disabled: !available,
649
+ onSelect: () => actions.resumeInWorkspace(id),
650
+ children: "resume session"
651
+ }),
652
+ /* @__PURE__ */ jsx(DropdownMenuItem, {
653
+ disabled: !available,
654
+ onSelect: () => actions.openWorkspaceSettings(id),
655
+ children: "workspace settings"
656
+ }),
657
+ /* @__PURE__ */ jsx(DropdownMenuItem, {
658
+ variant: "destructive",
659
+ "data-testid": `workspace-delete-${id}`,
660
+ onSelect: () => {
661
+ setRemoveError("");
662
+ setRemoveOpen(true);
663
+ },
664
+ children: "delete workspace"
665
+ })
666
+ ] })] })]
667
+ })
668
+ ]
669
+ }),
670
+ !available ? /* @__PURE__ */ jsx("p", {
671
+ className: "px-9 text-sm text-doom-red",
672
+ children: "Workspace unavailable"
673
+ }) : null,
674
+ workspace.sessions.length > 0 ? /* @__PURE__ */ jsx("div", {
675
+ className: "flex flex-col gap-1",
676
+ children: workspace.sessions.map((session) => /* @__PURE__ */ jsx(ElegantSessionCard, {
677
+ session,
678
+ actions
679
+ }, session.id))
680
+ }) : available ? /* @__PURE__ */ jsx("p", {
681
+ className: "px-9 pb-1 text-sm text-doom-dim",
682
+ children: "No sessions yet. Start or resume one."
683
+ }) : null,
684
+ /* @__PURE__ */ jsx(Dialog, {
685
+ open: removeOpen,
686
+ onOpenChange: (next) => !next && !removing && setRemoveOpen(false),
687
+ children: /* @__PURE__ */ jsxs(DialogContent, {
688
+ width: "sm",
689
+ "data-testid": `workspace-delete-dialog-${id}`,
690
+ "aria-describedby": void 0,
691
+ children: [/* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: "delete workspace" }) }), /* @__PURE__ */ jsxs(DialogBody, { children: [
692
+ /* @__PURE__ */ jsxs(DialogDescription, { children: [
693
+ "this unregisters ",
694
+ /* @__PURE__ */ jsx("span", {
695
+ className: "font-semibold text-doom-hi",
696
+ children: name
697
+ }),
698
+ " from Po only. files at",
699
+ " ",
700
+ /* @__PURE__ */ jsx("code", { children: root }),
701
+ " stay on disk. its sessions must be removed first."
702
+ ] }),
703
+ removeError ? /* @__PURE__ */ jsx("p", {
704
+ "data-testid": `workspace-delete-error-${id}`,
705
+ className: "text-sm text-doom-red",
706
+ children: removeError
707
+ }) : null,
708
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [/* @__PURE__ */ jsx(Button, {
709
+ variant: "outline",
710
+ size: "md",
711
+ "data-testid": `workspace-delete-cancel-${id}`,
712
+ disabled: removing,
713
+ autoFocus: true,
714
+ onClick: () => setRemoveOpen(false),
715
+ children: "cancel"
716
+ }), /* @__PURE__ */ jsx(Button, {
717
+ variant: "danger",
718
+ size: "md",
719
+ "data-testid": `workspace-delete-confirm-${id}`,
720
+ disabled: removing,
721
+ onClick: () => void unregister(),
722
+ children: removing ? "deleting…" : "delete"
723
+ })] })
724
+ ] })]
725
+ })
726
+ })
727
+ ]
728
+ });
729
+ }
730
+ //#endregion
731
+ //#region src/extensions/(frontend)/template/_components/ElegantRail.tsx
732
+ /** The drawer's session list: brand, workspaces with their sessions, remote access, and settings. */
733
+ function ElegantRail({ rail, onClose }) {
734
+ const { remote, actions } = rail;
735
+ const live = remote.status === "on" || remote.status === "starting";
736
+ return /* @__PURE__ */ jsxs("div", {
737
+ className: "flex min-h-full flex-col",
738
+ children: [
739
+ /* @__PURE__ */ jsxs("div", {
740
+ className: "flex items-center justify-between gap-2 px-5 pt-4 pb-3",
741
+ children: [/* @__PURE__ */ jsxs("span", {
742
+ className: "flex items-center gap-2.5",
743
+ "aria-label": "Po",
744
+ children: [/* @__PURE__ */ jsx("img", {
745
+ src: "/favicon.svg",
746
+ alt: "",
747
+ "aria-hidden": "true",
748
+ className: "size-9 rounded-lg"
749
+ }), /* @__PURE__ */ jsx("span", {
750
+ "aria-hidden": "true",
751
+ className: "text-2xl font-semibold text-doom-hi",
752
+ children: "Po"
753
+ })]
754
+ }), /* @__PURE__ */ jsxs("span", {
755
+ className: "flex items-center gap-1",
756
+ children: [/* @__PURE__ */ jsxs(Button, {
757
+ variant: remote.status === "failed" ? "danger-outline" : "outline",
758
+ size: "sm",
759
+ "data-testid": "remote-access-open",
760
+ "aria-label": `Remote access is ${remote.status}`,
761
+ onClick: actions.openRemoteAccess,
762
+ className: `gap-1.5 rounded-md ${remote.status === "failed" ? "" : "bg-doom-panel"}`,
763
+ children: [live ? /* @__PURE__ */ jsx(Dot, {
764
+ tone: "yellow",
765
+ pulse: true,
766
+ "data-testid": "remote-access-live"
767
+ }) : /* @__PURE__ */ jsx(ShieldIcon, { className: "size-3.5" }), "Remote access"]
768
+ }), /* @__PURE__ */ jsx(Button, {
769
+ variant: "ghost",
770
+ size: "icon",
771
+ "data-testid": "mobile-sessions-close",
772
+ title: "Hide sessions",
773
+ "aria-label": "Hide sessions",
774
+ onClick: onClose,
775
+ className: "text-doom-dim",
776
+ children: /* @__PURE__ */ jsx(CloseIcon, { className: "size-3.5" })
777
+ })]
778
+ })]
779
+ }),
780
+ /* @__PURE__ */ jsxs("div", {
781
+ className: "flex items-center justify-between px-5 pt-3 pb-2",
782
+ children: [/* @__PURE__ */ jsx("h2", {
783
+ className: "text-lg font-semibold text-doom-hi",
784
+ children: "Workspaces"
785
+ }), /* @__PURE__ */ jsx(Button, {
786
+ variant: "ghost",
787
+ size: "icon",
788
+ "data-testid": "add-workspace-open",
789
+ title: "Add workspace",
790
+ "aria-label": "Add workspace",
791
+ onClick: actions.openAddWorkspace,
792
+ className: "text-doom-faint hover:text-doom-hi",
793
+ children: /* @__PURE__ */ jsx(PlusIcon, { className: "size-3.5" })
794
+ })]
795
+ }),
796
+ /* @__PURE__ */ jsxs("div", {
797
+ className: "flex flex-col gap-4 px-3 pb-3",
798
+ children: [rail.workspaces.map((workspace) => /* @__PURE__ */ jsx(ElegantWorkspaceGroup, {
799
+ workspace,
800
+ actions
801
+ }, workspace.id)), rail.workspaces.length === 0 ? /* @__PURE__ */ jsxs("div", {
802
+ className: "flex flex-col gap-3 rounded-lg border border-dashed border-doom-border px-4 py-5",
803
+ children: [/* @__PURE__ */ jsx("p", {
804
+ className: "text-sm text-doom-dim",
805
+ children: "Add a folder to start working with Po."
806
+ }), /* @__PURE__ */ jsxs(Button, {
807
+ variant: "outline",
808
+ size: "md",
809
+ "data-testid": "add-workspace-empty",
810
+ onClick: actions.openAddWorkspace,
811
+ className: "justify-start gap-2 bg-doom-panel",
812
+ children: [/* @__PURE__ */ jsx(PlusIcon, { className: "size-3.5" }), "Add workspace"]
813
+ })]
814
+ }) : null]
815
+ }),
816
+ rail.pluginContent,
817
+ /* @__PURE__ */ jsx("div", { className: "flex-1" }),
818
+ /* @__PURE__ */ jsxs("div", {
819
+ className: "sticky bottom-0 mt-auto shrink-0 bg-doom-rail",
820
+ children: [remote.status === "off" ? null : /* @__PURE__ */ jsxs("div", {
821
+ "data-testid": "remote-banner",
822
+ className: `flex items-center gap-2 border-t border-doom-border-soft px-4 py-2 text-sm ${remote.status === "failed" ? "bg-doom-tint-red text-doom-red" : "bg-doom-tint-yellow text-doom-yellow"}`,
823
+ children: [
824
+ /* @__PURE__ */ jsx(Dot, { tone: remote.status === "failed" ? "red" : "yellow" }),
825
+ /* @__PURE__ */ jsx("span", {
826
+ className: "min-w-0 flex-1 truncate",
827
+ children: remote.status === "failed" ? `Remote access failed: ${remote.error ?? "the tunnel stopped"}` : `Remote access ${remote.status === "starting" ? "starting" : "on"}${remote.host === void 0 ? "" : ` · ${remote.host}`} · ${String(remote.deviceCount)} device${remote.deviceCount === 1 ? "" : "s"}`
828
+ }),
829
+ /* @__PURE__ */ jsx(Button, {
830
+ variant: "ghost",
831
+ size: "xs",
832
+ "data-testid": "remote-banner-open",
833
+ onClick: actions.openRemoteAccess,
834
+ children: "Manage"
835
+ }),
836
+ /* @__PURE__ */ jsx(Button, {
837
+ variant: "ghost",
838
+ size: "xs",
839
+ "data-testid": "remote-banner-off",
840
+ onClick: actions.turnRemoteAccessOff,
841
+ children: "Turn off"
842
+ })
843
+ ]
844
+ }), /* @__PURE__ */ jsxs("div", {
845
+ className: "flex flex-col gap-1 border-t border-doom-border-soft px-3 py-3",
846
+ children: [/* @__PURE__ */ jsxs(Button, {
847
+ variant: "ghost",
848
+ size: "md",
849
+ "data-testid": "settings-open",
850
+ onClick: actions.openSettings,
851
+ className: "justify-start gap-2.5 px-2 text-doom-text",
852
+ children: [/* @__PURE__ */ jsx(GearIcon, { className: "size-4 text-doom-dim" }), "Settings"]
853
+ }), /* @__PURE__ */ jsxs("span", {
854
+ className: "px-2 text-sm text-doom-dim max-sm:hidden",
855
+ children: [
856
+ /* @__PURE__ */ jsx(Kbd, {
857
+ className: "bg-doom-panel",
858
+ children: "ctrl+k"
859
+ }),
860
+ " commands · ",
861
+ /* @__PURE__ */ jsx(Kbd, {
862
+ className: "bg-doom-panel",
863
+ children: "ctrl+t"
864
+ }),
865
+ " new session"
866
+ ]
867
+ })]
868
+ })]
869
+ })
870
+ ]
871
+ });
872
+ }
873
+ //#endregion
874
+ //#region src/extensions/(frontend)/template/_components/ElegantLayout.tsx
875
+ /** A conversation-first frame, with the same host capabilities available on demand. */
876
+ function ElegantLayout({ view, slots, rail, navigationOpen, mobileActivityOpen, onNavigationOpenChange, onMobileActivityOpenChange }) {
877
+ const conversation = view === "conversation" || view === "welcome";
878
+ return /* @__PURE__ */ jsxs("div", {
879
+ className: "relative flex h-full min-w-0 flex-col overflow-hidden bg-doom-bg",
880
+ children: [
881
+ /* @__PURE__ */ jsx(Drawer, {
882
+ open: navigationOpen,
883
+ onOpenChange: onNavigationOpenChange,
884
+ side: "left",
885
+ title: "Sessions",
886
+ showHeader: false,
887
+ "data-testid": "session-rail-panel",
888
+ backdropTestId: "mobile-drawer-backdrop",
889
+ className: "w-[min(340px,calc(100vw-48px))] border-doom-border-soft",
890
+ children: /* @__PURE__ */ jsx(ElegantRail, {
891
+ rail,
892
+ onClose: () => onNavigationOpenChange(false)
893
+ })
894
+ }),
895
+ slots.notices,
896
+ slots.header({
897
+ navigationToggle: "always",
898
+ activityToggle: "always"
899
+ }),
900
+ /* @__PURE__ */ jsx("main", {
901
+ className: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden",
902
+ children: /* @__PURE__ */ jsxs("div", {
903
+ "data-testid": "template-content",
904
+ className: conversation ? "mx-auto flex min-h-0 w-full max-w-[960px] flex-1 flex-col overflow-hidden px-2 sm:px-6" : "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden",
905
+ children: [
906
+ slots.content,
907
+ slots.composer == null ? null : /* @__PURE__ */ jsx("div", {
908
+ className: "mb-2 shrink-0 sm:mb-4",
909
+ children: slots.composer
910
+ }),
911
+ slots.controls == null ? null : /* @__PURE__ */ jsxs("details", {
912
+ className: "shrink-0 px-3 pb-3 text-sm text-doom-dim",
913
+ children: [/* @__PURE__ */ jsx("summary", {
914
+ "data-testid": "template-controls-toggle",
915
+ className: "cursor-pointer rounded-sm px-1 py-1 focus-visible:outline focus-visible:outline-doom-blue",
916
+ children: "Session controls"
917
+ }), slots.controls]
918
+ })
919
+ ]
920
+ })
921
+ }),
922
+ slots.activity == null ? null : /* @__PURE__ */ jsx(Drawer, {
923
+ open: mobileActivityOpen,
924
+ onOpenChange: onMobileActivityOpenChange,
925
+ side: "right",
926
+ title: "Activity",
927
+ showHeader: false,
928
+ backdropTestId: "mobile-activity-backdrop",
929
+ className: "w-auto max-w-[calc(100vw-48px)]",
930
+ children: slots.activity
931
+ }),
932
+ rail.addWorkspace ? /* @__PURE__ */ jsx(ElegantAddWorkspaceDialog, {
933
+ suggestedPaths: rail.addWorkspace.suggestedPaths,
934
+ actions: rail.actions
935
+ }) : null
936
+ ]
937
+ });
938
+ }
939
+ //#endregion
940
+ //#region src/extensions/(frontend)/template/_components/ElegantConversation.tsx
941
+ function ElegantConversation() {
942
+ useWebPluginRegistry();
943
+ const dockOpen = useStore(uiStore, (state) => state.dockOpen);
944
+ const [railOpen, setRailOpen] = useState(false);
945
+ const [mobileActivityOpen, setMobileActivityOpen] = useState(false);
946
+ const { sessionId, tabId } = useDashboardRoute();
947
+ const slotProps = usePluginSlotProps(sessionId ?? null);
948
+ const sessionWorkspaceId = useStore(sessionsStore, (state) => sessionId === void 0 ? void 0 : state.byId[sessionId]?.summary.workspaceId);
949
+ const selectedWorkspaceId = useStore(workspacesStore, (state) => state.selectedId);
950
+ const mcp = useSessionMcp(sessionId === void 0 ? selectedWorkspaceId ?? void 0 : sessionWorkspaceId, sessionId);
951
+ const mcpView = tabId === "mcp";
952
+ const mcpEnabled = mcp.snapshot?.enabled === true || mcpView;
953
+ const transferLabel = useStore(sessionsStore, (state) => {
954
+ if (state.transferringToId === null) return null;
955
+ return state.byId[state.transferringToId]?.summary.name ?? "destination session";
956
+ });
957
+ const noSessions = useNoSessions();
958
+ const activeMeta = useActiveSessionMeta();
959
+ const dormantMeta = activeMeta?.summary.dormant === true ? activeMeta : null;
960
+ const dialogId = useActiveSession((state) => state.dialog?.id ?? null);
961
+ const storedTransientTab = useStore(transientTabsStore, (state) => findTransientTab(state, sessionId, tabId));
962
+ const transientTab = storedTransientTab === void 0 ? void 0 : pluginActivityGroups().map((group) => group.transientTab?.()).find((candidate) => candidate?.id === storedTransientTab.id) ?? storedTransientTab;
963
+ const tab = (tabId === void 0 ? void 0 : webTabs().find((entry) => entry.id === tabId)) ?? transientTab;
964
+ const composerContext = tab === transientTab ? transientTab?.composerContext : void 0;
965
+ const routeKey = `${sessionId ?? ""}\u0000${tabId ?? ""}`;
966
+ const [lastRouteKey, setLastRouteKey] = useState(routeKey);
967
+ if (lastRouteKey !== routeKey) {
968
+ setLastRouteKey(routeKey);
969
+ setRailOpen(false);
970
+ setMobileActivityOpen(false);
971
+ }
972
+ const [lastDialogId, setLastDialogId] = useState(dialogId);
973
+ if (lastDialogId !== dialogId) {
974
+ setLastDialogId(dialogId);
975
+ if (dialogId !== null) {
976
+ setMobileActivityOpen(false);
977
+ setRailOpen(false);
978
+ }
979
+ }
980
+ const rail = useSessionRail({ onDismiss: () => setRailOpen(false) });
981
+ const closeActivity = () => {
982
+ if (mobileActivityOpen) setMobileActivityOpen(false);
983
+ else setDockOpen(false);
984
+ };
985
+ return /* @__PURE__ */ jsxs("div", {
986
+ "data-testid": "cockpit",
987
+ className: "h-full min-w-0 overflow-hidden",
988
+ children: [/* @__PURE__ */ jsx(ElegantLayout, {
989
+ view: mcpView || tab ? "panel" : noSessions ? "welcome" : "conversation",
990
+ navigationOpen: railOpen,
991
+ desktopActivityOpen: dockOpen,
992
+ mobileActivityOpen,
993
+ onNavigationOpenChange: setRailOpen,
994
+ onDesktopActivityOpenChange: setDockOpen,
995
+ onMobileActivityOpenChange: setMobileActivityOpen,
996
+ rail,
997
+ slots: {
998
+ header: (options) => /* @__PURE__ */ jsx(TopBar, {
999
+ ...options,
1000
+ view: mcpView ? "mcp" : tab?.id ?? "conversation",
1001
+ mcpEnabled,
1002
+ onShowSessions: () => {
1003
+ setMobileActivityOpen(false);
1004
+ setRailOpen(true);
1005
+ },
1006
+ onShowActivity: () => {
1007
+ setRailOpen(false);
1008
+ setMobileActivityOpen(true);
1009
+ }
1010
+ }),
1011
+ notices: transferLabel === null ? null : /* @__PURE__ */ jsxs("output", {
1012
+ "data-testid": "voice-transfer-transition",
1013
+ className: "border-b border-doom-cyan/30 bg-doom-cyan/10 px-4 py-2 text-center text-base font-medium text-doom-cyan",
1014
+ children: [
1015
+ "Transferring voice to ",
1016
+ transferLabel,
1017
+ "..."
1018
+ ]
1019
+ }),
1020
+ content: mcpView ? /* @__PURE__ */ jsx(SessionMcp, { state: mcp }, sessionId) : tab ? /* @__PURE__ */ jsx(tab.panel, { ...slotProps }) : noSessions ? /* @__PURE__ */ jsx(WelcomePanel, {}) : /* @__PURE__ */ jsx(Timeline, {}),
1021
+ composer: mcpView ? null : tab ? tab.retainComposer === true ? /* @__PURE__ */ jsx(Composer, { composerContext }) : null : noSessions ? null : /* @__PURE__ */ jsx(Composer, {}),
1022
+ controls: !mcpView && !tab && !noSessions && dormantMeta === null ? /* @__PURE__ */ jsx(SelectionBar, {}) : null,
1023
+ activity: /* @__PURE__ */ jsx(ActivityDock, {
1024
+ mcp,
1025
+ onClose: closeActivity,
1026
+ onOpenContent: () => setMobileActivityOpen(false)
1027
+ })
1028
+ }
1029
+ }), /* @__PURE__ */ jsx(SessionRailDialogs, {})]
1030
+ });
1031
+ }
1032
+ //#endregion
1033
+ //#region src/extensions/(frontend)/template/_components/ElegantSettings.tsx
1034
+ /** Settings have their own page frame, independent of session navigation. */
1035
+ function ElegantSettings() {
1036
+ useWebPluginRegistry();
1037
+ const { section, workspaceId } = useDashboardRoute();
1038
+ const navigate = useNavigate();
1039
+ const activeId = useStore(sessionsStore, (state) => state.activeId);
1040
+ const [loadError, setLoadError] = useState();
1041
+ const [repositoryReady, setRepositoryReady] = useState(false);
1042
+ const [templateTarget, setTemplateTarget] = useDashboardState("settings/template-target", "global");
1043
+ const current = settingsSection(section);
1044
+ const workspace = current?.workspace ?? (section?.startsWith("repository-") ? "repository" : "general");
1045
+ useEffect(() => {
1046
+ if (current) return;
1047
+ if (workspace === "repository" && !repositoryReady) return;
1048
+ let cancelled = false;
1049
+ refreshWebPluginCompositions().then(() => {
1050
+ if (cancelled || settingsSection(section)) return;
1051
+ navigate({
1052
+ to: "/settings/$section",
1053
+ params: { section: DEFAULT_SETTINGS_SECTION },
1054
+ search: { workspace: workspaceId },
1055
+ replace: true
1056
+ });
1057
+ }).catch((error) => {
1058
+ if (!cancelled) setLoadError(error instanceof Error ? error.message : String(error));
1059
+ });
1060
+ return () => {
1061
+ cancelled = true;
1062
+ };
1063
+ }, [
1064
+ current,
1065
+ section,
1066
+ navigate,
1067
+ workspace,
1068
+ workspaceId,
1069
+ repositoryReady
1070
+ ]);
1071
+ return /* @__PURE__ */ jsxs("div", {
1072
+ "data-testid": "settings",
1073
+ className: "flex h-full min-h-0 min-w-0 flex-col overflow-hidden bg-doom-bg",
1074
+ children: [/* @__PURE__ */ jsxs("header", {
1075
+ className: "grid shrink-0 grid-cols-[minmax(0,1fr)_auto] items-center gap-x-2 gap-y-2 border-b border-doom-border px-3 py-2 sm:h-14 sm:grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] sm:px-6 sm:py-0",
1076
+ children: [
1077
+ /* @__PURE__ */ jsx("h1", {
1078
+ className: "order-1 min-w-0 truncate text-xl font-semibold text-doom-hi sm:order-none",
1079
+ children: "Settings"
1080
+ }),
1081
+ /* @__PURE__ */ jsxs("nav", {
1082
+ className: "order-3 col-span-2 flex w-full items-center gap-1 rounded-lg bg-doom-panel p-1 sm:order-none sm:col-span-1 sm:w-auto",
1083
+ "aria-label": "settings workspace",
1084
+ children: [/* @__PURE__ */ jsx(NavTab, {
1085
+ asChild: true,
1086
+ active: workspace === "general",
1087
+ className: "min-h-8 flex-1 justify-center rounded-md px-4 focus-visible:ring-2 focus-visible:ring-doom-green sm:flex-none",
1088
+ "aria-current": workspace === "general" ? "true" : void 0,
1089
+ children: /* @__PURE__ */ jsx(Link, {
1090
+ to: "/settings/$section",
1091
+ params: { section: DEFAULT_SETTINGS_SECTION },
1092
+ search: { workspace: workspaceId },
1093
+ "data-testid": "settings-workspace-general",
1094
+ children: "General"
1095
+ })
1096
+ }), /* @__PURE__ */ jsx(NavTab, {
1097
+ asChild: true,
1098
+ active: workspace === "repository",
1099
+ className: "min-h-8 flex-1 justify-center rounded-md px-4 focus-visible:ring-2 focus-visible:ring-doom-green sm:flex-none",
1100
+ "aria-current": workspace === "repository" ? "true" : void 0,
1101
+ children: /* @__PURE__ */ jsx(Link, {
1102
+ to: "/settings/$section",
1103
+ params: { section: DEFAULT_REPOSITORY_SETTINGS_SECTION },
1104
+ search: { workspace: workspaceId },
1105
+ "data-testid": "settings-workspace-repository",
1106
+ children: "Workspaces"
1107
+ })
1108
+ })]
1109
+ }),
1110
+ /* @__PURE__ */ jsx(Button, {
1111
+ asChild: true,
1112
+ variant: "ghost",
1113
+ size: "sm",
1114
+ className: "order-2 sm:order-none sm:justify-self-end",
1115
+ children: activeId !== null ? /* @__PURE__ */ jsxs(Link, {
1116
+ to: "/session/$sessionId",
1117
+ params: { sessionId: activeId },
1118
+ "data-testid": "settings-close",
1119
+ children: [/* @__PURE__ */ jsx("span", {
1120
+ className: "sm:hidden",
1121
+ children: "Back"
1122
+ }), /* @__PURE__ */ jsx("span", {
1123
+ className: "hidden sm:inline",
1124
+ children: "Back to session"
1125
+ })]
1126
+ }) : /* @__PURE__ */ jsx(Link, {
1127
+ to: "/",
1128
+ "data-testid": "settings-close",
1129
+ children: "Back"
1130
+ })
1131
+ })
1132
+ ]
1133
+ }), /* @__PURE__ */ jsx("main", {
1134
+ className: "flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden",
1135
+ children: workspace === "repository" ? /* @__PURE__ */ jsx(RepositoryWorkspace, {
1136
+ current: current ?? {
1137
+ id: section ?? "",
1138
+ label: "",
1139
+ detail: "",
1140
+ workspace: "repository"
1141
+ },
1142
+ initialRepositoryId: workspaceId,
1143
+ onRepositoryChange: (nextWorkspaceId) => {
1144
+ navigate({
1145
+ to: "/settings/$section",
1146
+ params: { section: current?.id ?? section ?? DEFAULT_REPOSITORY_SETTINGS_SECTION },
1147
+ search: { workspace: nextWorkspaceId },
1148
+ replace: true
1149
+ });
1150
+ },
1151
+ onReady: setRepositoryReady
1152
+ }, workspaceId ?? "remembered-workspace") : /* @__PURE__ */ jsxs("div", {
1153
+ className: "flex min-h-0 flex-1 flex-col lg:flex-row",
1154
+ children: [/* @__PURE__ */ jsx(SettingsMenu, {
1155
+ active: current?.id,
1156
+ workspace: "general",
1157
+ repositoryId: workspaceId
1158
+ }), /* @__PURE__ */ jsx("section", {
1159
+ "data-testid": "settings-content",
1160
+ className: "min-w-0 flex-1 overflow-y-auto px-4 py-6 sm:px-6 sm:py-8 lg:px-8 lg:py-10",
1161
+ children: /* @__PURE__ */ jsxs("div", {
1162
+ className: "mx-auto flex w-full max-w-[720px] flex-col gap-8",
1163
+ children: [
1164
+ !current && loadError ? /* @__PURE__ */ jsx("p", {
1165
+ role: "alert",
1166
+ children: loadError
1167
+ }) : null,
1168
+ current?.id === "providers" ? /* @__PURE__ */ jsx(ProviderSettings, {}) : null,
1169
+ current?.id === "appearance" ? /* @__PURE__ */ jsx(AppearanceSettings, {
1170
+ templateTarget,
1171
+ onTemplateTargetChange: setTemplateTarget
1172
+ }) : null,
1173
+ current?.id === "notifications" ? /* @__PURE__ */ jsx(NotificationSettings, {}) : null,
1174
+ current?.id === "images" ? /* @__PURE__ */ jsx(ImageSettings, {}) : null,
1175
+ current?.id === "remote" ? /* @__PURE__ */ jsx(RemoteControlSettings, {}) : null,
1176
+ current?.id === "plugins" ? /* @__PURE__ */ jsx(PluginSettings, {}) : null,
1177
+ current?.contribution === void 0 ? null : /* @__PURE__ */ jsx(ContributedSettings, {
1178
+ section: current.contribution,
1179
+ scope: "global"
1180
+ }),
1181
+ current?.panel === void 0 ? null : /* @__PURE__ */ jsx(SettingsPanelHost, { panel: current.panel })
1182
+ ]
1183
+ })
1184
+ })]
1185
+ })
1186
+ })]
1187
+ });
1188
+ }
1189
+ //#endregion
1190
+ //#region src/extensions/(frontend)/template/_components/ElegantDashboard.tsx
1191
+ const renderers = {
1192
+ thread: (id, threadId, options) => /* @__PURE__ */ jsx(ThreadView, {
1193
+ sessionId: id,
1194
+ threadId,
1195
+ options
1196
+ }),
1197
+ activity: (id, open) => /* @__PURE__ */ jsx(SessionActivity, {
1198
+ sessionId: id,
1199
+ onOpenConversation: open
1200
+ }),
1201
+ transcript: (id, options) => /* @__PURE__ */ jsx(SessionTranscriptView, {
1202
+ sessionId: id,
1203
+ options,
1204
+ watch: watchDashboardTranscript
1205
+ })
1206
+ };
1207
+ function ElegantDashboard() {
1208
+ const route = useDashboardRoute();
1209
+ const sessionId = useStore(sessionsStore, (state) => state.activeId);
1210
+ return /* @__PURE__ */ jsxs(DashboardRendererProvider, {
1211
+ value: renderers,
1212
+ children: [
1213
+ route.kind === "settings" ? /* @__PURE__ */ jsx(ElegantSettings, {}) : /* @__PURE__ */ jsx(ElegantConversation, {}),
1214
+ /* @__PURE__ */ jsx(DialogOverlay, {}),
1215
+ /* @__PURE__ */ jsx(RefusedCard, {}),
1216
+ /* @__PURE__ */ jsx(CommandPalette, {}),
1217
+ /* @__PURE__ */ jsx(PluginSurface, {
1218
+ slot: HOST_SLOTS.overlay,
1219
+ sessionId
1220
+ }),
1221
+ /* @__PURE__ */ jsx(RemoteAccessDialog, {}),
1222
+ /* @__PURE__ */ jsx(PairingApprovalDialog, {})
1223
+ ]
1224
+ });
1225
+ }
1226
+ //#endregion
1227
+ //#region src/extensions/(frontend)/template/_lib/definition.ts
1228
+ const elegantTemplate = {
1229
+ label: "Elegant",
1230
+ description: "A focused conversation with collapsible navigation, session controls, and activity.",
1231
+ contractVersion: 2,
1232
+ app: ElegantDashboard
1233
+ };
1234
+ //#endregion
1235
+ //#region src/extensions/(frontend)/template/po-template-elegant.web.ts
1236
+ var po_template_elegant_web_default$2 = defineWebTemplate(elegantTemplate);
1237
+ //#endregion
1238
+ //#region src/extensions/workspaces/(frontend)/template/po-template-elegant.web.ts
1239
+ var po_template_elegant_web_default$1 = defineWebTemplate(elegantTemplate);
1240
+ //#endregion
1241
+ //#region src/extensions/workspaces/sessions/(frontend)/template/po-template-elegant.web.ts
1242
+ var po_template_elegant_web_default = defineWebTemplate(elegantTemplate);
1243
+ //#endregion
1244
+ //#region generated/web.ts
1245
+ const via = (identity, value) => value === void 0 ? void 0 : {
1246
+ ...identity,
1247
+ ...value
1248
+ };
1249
+ const webPlugin = defineWebPlugin({
1250
+ id: "template-elegant",
1251
+ global: { get templates() {
1252
+ return [via({ id: "po-template-elegant" }, po_template_elegant_web_default$2)];
1253
+ } },
1254
+ workspace: { get templates() {
1255
+ return [via({ id: "po-template-elegant" }, po_template_elegant_web_default$1)];
1256
+ } },
1257
+ session: { get templates() {
1258
+ return [via({ id: "po-template-elegant" }, po_template_elegant_web_default)];
1259
+ } }
1260
+ });
1261
+ //#endregion
1262
+ export { webPlugin };
1263
+
1264
+ //# sourceMappingURL=web.mjs.map