agent-relay-server 0.21.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/openapi.json +4 -1
- package/package.json +2 -2
- package/public/index.html +716 -426
- package/runner/src/adapter.ts +3 -0
- package/src/cli.ts +62 -8
- package/src/maintenance.ts +9 -4
- package/src/mcp.ts +244 -2
- package/src/routes.ts +79 -167
- package/src/workspace-actions.ts +336 -0
- package/src/workspace-phase.ts +181 -0
package/public/index.html
CHANGED
|
@@ -10510,6 +10510,40 @@ function prepareForSpeech(markdown) {
|
|
|
10510
10510
|
}
|
|
10511
10511
|
//#endregion
|
|
10512
10512
|
//#region src/lib/voice.ts
|
|
10513
|
+
var KOKORO_VOICES = [
|
|
10514
|
+
{
|
|
10515
|
+
id: "am_michael",
|
|
10516
|
+
label: "Michael (US ♂)"
|
|
10517
|
+
},
|
|
10518
|
+
{
|
|
10519
|
+
id: "am_adam",
|
|
10520
|
+
label: "Adam (US ♂)"
|
|
10521
|
+
},
|
|
10522
|
+
{
|
|
10523
|
+
id: "af_heart",
|
|
10524
|
+
label: "Heart (US ♀)"
|
|
10525
|
+
},
|
|
10526
|
+
{
|
|
10527
|
+
id: "af_bella",
|
|
10528
|
+
label: "Bella (US ♀)"
|
|
10529
|
+
},
|
|
10530
|
+
{
|
|
10531
|
+
id: "af_nicole",
|
|
10532
|
+
label: "Nicole (US ♀)"
|
|
10533
|
+
},
|
|
10534
|
+
{
|
|
10535
|
+
id: "af_sarah",
|
|
10536
|
+
label: "Sarah (US ♀)"
|
|
10537
|
+
},
|
|
10538
|
+
{
|
|
10539
|
+
id: "bm_george",
|
|
10540
|
+
label: "George (UK ♂)"
|
|
10541
|
+
},
|
|
10542
|
+
{
|
|
10543
|
+
id: "bf_emma",
|
|
10544
|
+
label: "Emma (UK ♀)"
|
|
10545
|
+
}
|
|
10546
|
+
];
|
|
10513
10547
|
var MAX_CHUNK = 220;
|
|
10514
10548
|
/** Split into utterance-sized chunks (sentence boundaries; hard-split very long runs). */
|
|
10515
10549
|
function chunkForSpeech(text) {
|
|
@@ -10537,6 +10571,7 @@ var VoiceTts = class {
|
|
|
10537
10571
|
lang = "en-US";
|
|
10538
10572
|
mode = "kokoro";
|
|
10539
10573
|
kokoroVoice = "am_michael";
|
|
10574
|
+
browserVoice = "";
|
|
10540
10575
|
active = null;
|
|
10541
10576
|
queue = [];
|
|
10542
10577
|
currentChat = null;
|
|
@@ -10586,6 +10621,10 @@ var VoiceTts = class {
|
|
|
10586
10621
|
setKokoroVoice(voice) {
|
|
10587
10622
|
this.kokoroVoice = voice;
|
|
10588
10623
|
}
|
|
10624
|
+
/** Set the browser engine's voice by voiceURI. Empty = default for the language. */
|
|
10625
|
+
setBrowserVoice(uri) {
|
|
10626
|
+
this.browserVoice = uri;
|
|
10627
|
+
}
|
|
10589
10628
|
setActiveChat(chatId) {
|
|
10590
10629
|
if (chatId === this.active) return;
|
|
10591
10630
|
this.active = chatId;
|
|
@@ -10683,7 +10722,11 @@ var VoiceTts = class {
|
|
|
10683
10722
|
if (gen !== this.gen) return;
|
|
10684
10723
|
if (!synthAvailable || i >= chunks.length) return done();
|
|
10685
10724
|
const u = new SpeechSynthesisUtterance(chunks[i]);
|
|
10686
|
-
|
|
10725
|
+
const picked = this.browserVoice ? window.speechSynthesis.getVoices().find((v) => v.voiceURI === this.browserVoice) : void 0;
|
|
10726
|
+
if (picked) {
|
|
10727
|
+
u.voice = picked;
|
|
10728
|
+
u.lang = picked.lang;
|
|
10729
|
+
} else u.lang = this.lang || navigator.language || "en-US";
|
|
10687
10730
|
u.onend = () => this.speakBrowser(chunks, i + 1, gen, done);
|
|
10688
10731
|
u.onerror = () => this.speakBrowser(chunks, i + 1, gen, done);
|
|
10689
10732
|
window.speechSynthesis.speak(u);
|
|
@@ -10732,12 +10775,16 @@ var VoiceTts = class {
|
|
|
10732
10775
|
}
|
|
10733
10776
|
};
|
|
10734
10777
|
var voiceTts = new VoiceTts();
|
|
10735
|
-
/**
|
|
10736
|
-
* until the engine
|
|
10737
|
-
function
|
|
10778
|
+
/** The browser's individual speech voices ({uri, label, lang}), sorted by language
|
|
10779
|
+
* then name. May be empty until the engine loads (listen for `voiceschanged`). */
|
|
10780
|
+
function availableSpeechVoices() {
|
|
10738
10781
|
if (!synthAvailable) return [];
|
|
10739
10782
|
try {
|
|
10740
|
-
return
|
|
10783
|
+
return window.speechSynthesis.getVoices().map((v) => ({
|
|
10784
|
+
uri: v.voiceURI,
|
|
10785
|
+
label: `${v.name} (${v.lang})`,
|
|
10786
|
+
lang: v.lang
|
|
10787
|
+
})).sort((a, b) => a.lang.localeCompare(b.lang) || a.label.localeCompare(b.label));
|
|
10741
10788
|
} catch {
|
|
10742
10789
|
return [];
|
|
10743
10790
|
}
|
|
@@ -12099,9 +12146,11 @@ function isDashboardHidden() {
|
|
|
12099
12146
|
function notificationPeer(notification) {
|
|
12100
12147
|
return notification.threadPeer || notification.agentId || "";
|
|
12101
12148
|
}
|
|
12149
|
+
function isActiveVisibleChat(peer, state) {
|
|
12150
|
+
return Boolean(peer && state.view === "chat" && state.selectedInboxThread === peer && !isDashboardHidden());
|
|
12151
|
+
}
|
|
12102
12152
|
function notificationTargetsActiveChat(notification, state) {
|
|
12103
|
-
|
|
12104
|
-
return Boolean(state.view === "chat" && peer && state.selectedInboxThread === peer && !isDashboardHidden());
|
|
12153
|
+
return isActiveVisibleChat(notificationPeer(notification), state);
|
|
12105
12154
|
}
|
|
12106
12155
|
function lastInboundMessageId(messages) {
|
|
12107
12156
|
return messages.filter((m) => m.to === "user" && m.from !== "user").reduce((max, m) => Math.max(max, m.id), 0);
|
|
@@ -12174,6 +12223,7 @@ var useRelayStore = create$1()(persist((set, get) => ({
|
|
|
12174
12223
|
voiceTtsLang: "en-US",
|
|
12175
12224
|
voiceTtsMode: "kokoro",
|
|
12176
12225
|
voiceTtsKokoroVoice: "am_michael",
|
|
12226
|
+
voiceTtsBrowserVoice: "",
|
|
12177
12227
|
voiceInputMode: "compose",
|
|
12178
12228
|
agentSort: "status",
|
|
12179
12229
|
agentSortDir: "asc",
|
|
@@ -12218,6 +12268,8 @@ var useRelayStore = create$1()(persist((set, get) => ({
|
|
|
12218
12268
|
chatAgentHostFilter: "",
|
|
12219
12269
|
chatAgentSort: "status",
|
|
12220
12270
|
chatAgentSortDir: "asc",
|
|
12271
|
+
chatAgentGroupBy: "",
|
|
12272
|
+
chatAgentFiltersCollapsed: true,
|
|
12221
12273
|
chatStatusEvents: {},
|
|
12222
12274
|
chatStickToBottom: true,
|
|
12223
12275
|
chatHasNewItems: false,
|
|
@@ -12380,6 +12432,10 @@ var useRelayStore = create$1()(persist((set, get) => ({
|
|
|
12380
12432
|
voiceTts.setKokoroVoice(voice);
|
|
12381
12433
|
set({ voiceTtsKokoroVoice: voice });
|
|
12382
12434
|
},
|
|
12435
|
+
setVoiceTtsBrowserVoice(uri) {
|
|
12436
|
+
voiceTts.setBrowserVoice(uri);
|
|
12437
|
+
set({ voiceTtsBrowserVoice: uri });
|
|
12438
|
+
},
|
|
12383
12439
|
setVoiceInputMode(mode) {
|
|
12384
12440
|
set({ voiceInputMode: mode });
|
|
12385
12441
|
},
|
|
@@ -12396,6 +12452,7 @@ var useRelayStore = create$1()(persist((set, get) => ({
|
|
|
12396
12452
|
voiceTts.setLang(get().voiceTtsLang);
|
|
12397
12453
|
voiceTts.setMode(get().voiceTtsMode);
|
|
12398
12454
|
voiceTts.setKokoroVoice(get().voiceTtsKokoroVoice);
|
|
12455
|
+
voiceTts.setBrowserVoice(get().voiceTtsBrowserVoice);
|
|
12399
12456
|
syncVoiceActiveChat(get());
|
|
12400
12457
|
setUnauthorizedHandler(() => {
|
|
12401
12458
|
if (!get().authNeeded) set({
|
|
@@ -12835,7 +12892,15 @@ var useRelayStore = create$1()(persist((set, get) => ({
|
|
|
12835
12892
|
if (s.view === "messages" && s.selectedAgent) path += "&for=" + encodeURIComponent(s.selectedAgent);
|
|
12836
12893
|
if (s.view === "messages" && s.channelFilter) path += "&channel=" + encodeURIComponent(s.channelFilter);
|
|
12837
12894
|
const messages = await api("GET", path);
|
|
12838
|
-
|
|
12895
|
+
const merged = mergeFetchedMessages(get().messages, messages);
|
|
12896
|
+
set({ messages: merged });
|
|
12897
|
+
const after = get();
|
|
12898
|
+
const peer = after.selectedInboxThread;
|
|
12899
|
+
if (isActiveVisibleChat(peer, after)) {
|
|
12900
|
+
let lastId = 0;
|
|
12901
|
+
for (const m of merged) if (m.id > lastId && inboxPeer(m) === peer && isHumanInboundMessage(m) && !isSessionActivityStep(m)) lastId = m.id;
|
|
12902
|
+
if (lastId) get().markInboxThreadReadTo(peer, lastId);
|
|
12903
|
+
}
|
|
12839
12904
|
} catch {}
|
|
12840
12905
|
},
|
|
12841
12906
|
async fetchThreadHistory(peer) {
|
|
@@ -12936,7 +13001,7 @@ var useRelayStore = create$1()(persist((set, get) => ({
|
|
|
12936
13001
|
if (msgs.length > 500) msgs.splice(0, msgs.length - 500);
|
|
12937
13002
|
set({ messages: msgs });
|
|
12938
13003
|
const peer = inboxPeer(msg);
|
|
12939
|
-
if (isHumanInboundMessage(msg) && peer
|
|
13004
|
+
if (isHumanInboundMessage(msg) && isActiveVisibleChat(peer, s)) get().markInboxThreadReadTo(peer, msg.id);
|
|
12940
13005
|
return;
|
|
12941
13006
|
}
|
|
12942
13007
|
if (event === "message.queued" || event === "message.expired" || event === "message.delivery_updated" || event === "message.reaction_updated") {
|
|
@@ -14510,6 +14575,7 @@ var useRelayStore = create$1()(persist((set, get) => ({
|
|
|
14510
14575
|
voiceTtsLang: state.voiceTtsLang,
|
|
14511
14576
|
voiceTtsMode: state.voiceTtsMode,
|
|
14512
14577
|
voiceTtsKokoroVoice: state.voiceTtsKokoroVoice,
|
|
14578
|
+
voiceTtsBrowserVoice: state.voiceTtsBrowserVoice,
|
|
14513
14579
|
voiceInputMode: state.voiceInputMode,
|
|
14514
14580
|
agentSort: state.agentSort,
|
|
14515
14581
|
agentSortDir: state.agentSortDir,
|
|
@@ -14528,6 +14594,8 @@ var useRelayStore = create$1()(persist((set, get) => ({
|
|
|
14528
14594
|
chatAgentHostFilter: state.chatAgentHostFilter,
|
|
14529
14595
|
chatAgentSort: state.chatAgentSort,
|
|
14530
14596
|
chatAgentSortDir: state.chatAgentSortDir,
|
|
14597
|
+
chatAgentGroupBy: state.chatAgentGroupBy,
|
|
14598
|
+
chatAgentFiltersCollapsed: state.chatAgentFiltersCollapsed,
|
|
14531
14599
|
activityFilter: state.activityFilter,
|
|
14532
14600
|
analyticsPeriod: state.analyticsPeriod,
|
|
14533
14601
|
memoryFilters: state.memoryFilters,
|
|
@@ -99801,6 +99869,45 @@ function Button({ className, variant = "default", size = "default", asChild = fa
|
|
|
99801
99869
|
});
|
|
99802
99870
|
}
|
|
99803
99871
|
//#endregion
|
|
99872
|
+
//#region src/components/shared/copy-button.tsx
|
|
99873
|
+
/**
|
|
99874
|
+
* Shared copy-to-clipboard button with a transient "copied" check state.
|
|
99875
|
+
* Consolidates the duplicated clipboard + timeout pattern used across views.
|
|
99876
|
+
*/
|
|
99877
|
+
function CopyButton({ value, label = "Copy", copiedLabel = "Copied", showText = false, size, variant = "ghost", className, iconClassName, disabled, onCopied }) {
|
|
99878
|
+
const [copied, setCopied] = (0, import_react.useState)(false);
|
|
99879
|
+
const timer = (0, import_react.useRef)(null);
|
|
99880
|
+
(0, import_react.useEffect)(() => () => {
|
|
99881
|
+
if (timer.current) clearTimeout(timer.current);
|
|
99882
|
+
}, []);
|
|
99883
|
+
async function copy(e) {
|
|
99884
|
+
e.preventDefault();
|
|
99885
|
+
e.stopPropagation();
|
|
99886
|
+
try {
|
|
99887
|
+
await navigator.clipboard?.writeText(typeof value === "function" ? value() : value);
|
|
99888
|
+
setCopied(true);
|
|
99889
|
+
onCopied?.();
|
|
99890
|
+
if (timer.current) clearTimeout(timer.current);
|
|
99891
|
+
timer.current = setTimeout(() => setCopied(false), 1400);
|
|
99892
|
+
} catch {
|
|
99893
|
+
setCopied(false);
|
|
99894
|
+
}
|
|
99895
|
+
}
|
|
99896
|
+
const resolvedSize = size ?? (showText ? "sm" : "icon-sm");
|
|
99897
|
+
const iconCls = cn$2("h-3.5 w-3.5", iconClassName);
|
|
99898
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, {
|
|
99899
|
+
type: "button",
|
|
99900
|
+
size: resolvedSize,
|
|
99901
|
+
variant,
|
|
99902
|
+
className,
|
|
99903
|
+
disabled,
|
|
99904
|
+
title: copied ? copiedLabel : label,
|
|
99905
|
+
"aria-label": copied ? copiedLabel : label,
|
|
99906
|
+
onClick: (e) => void copy(e),
|
|
99907
|
+
children: [copied ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Check, { className: iconCls }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Copy, { className: iconCls }), showText && (copied ? copiedLabel : label)]
|
|
99908
|
+
});
|
|
99909
|
+
}
|
|
99910
|
+
//#endregion
|
|
99804
99911
|
//#region \0vite/preload-helper.js
|
|
99805
99912
|
var scriptRel, assetsURL, seen, __vitePreload;
|
|
99806
99913
|
var init_preload_helper = __esmMin((() => {
|
|
@@ -108465,25 +108572,14 @@ var CodePreview = (0, import_react.memo)(function CodePreview({ content, path, m
|
|
|
108465
108572
|
const [html, setHtml] = (0, import_react.useState)("");
|
|
108466
108573
|
const [loading, setLoading] = (0, import_react.useState)(false);
|
|
108467
108574
|
const [failed, setFailed] = (0, import_react.useState)(false);
|
|
108468
|
-
const [copied, setCopied] = (0, import_react.useState)(false);
|
|
108469
|
-
async function copyCode() {
|
|
108470
|
-
try {
|
|
108471
|
-
await navigator.clipboard?.writeText(content);
|
|
108472
|
-
setCopied(true);
|
|
108473
|
-
window.setTimeout(() => setCopied(false), 1400);
|
|
108474
|
-
} catch {
|
|
108475
|
-
setCopied(false);
|
|
108476
|
-
}
|
|
108477
|
-
}
|
|
108478
108575
|
function copyButton() {
|
|
108479
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
108480
|
-
|
|
108576
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CopyButton, {
|
|
108577
|
+
value: content,
|
|
108578
|
+
label: "Copy code",
|
|
108579
|
+
copiedLabel: "Copied code",
|
|
108481
108580
|
size: "icon",
|
|
108482
108581
|
variant: "ghost",
|
|
108483
|
-
className: "absolute right-2 top-2 h-7 w-7 bg-background/80 opacity-0 shadow-sm backdrop-blur transition-opacity hover:bg-muted group-hover/code:opacity-100 focus-visible:opacity-100"
|
|
108484
|
-
onClick: copyCode,
|
|
108485
|
-
title: copied ? "Copied code" : "Copy code",
|
|
108486
|
-
children: copied ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Check, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Copy, { className: "h-3.5 w-3.5" })
|
|
108582
|
+
className: "absolute right-2 top-2 h-7 w-7 bg-background/80 opacity-0 shadow-sm backdrop-blur transition-opacity hover:bg-muted group-hover/code:opacity-100 focus-visible:opacity-100"
|
|
108487
108583
|
});
|
|
108488
108584
|
}
|
|
108489
108585
|
(0, import_react.useEffect)(() => {
|
|
@@ -108780,7 +108876,7 @@ function ContextMeter({ agent }) {
|
|
|
108780
108876
|
function runtimeChips(agent) {
|
|
108781
108877
|
const spawned = isRelaySpawned(agent);
|
|
108782
108878
|
const approval = approvalMode(agent);
|
|
108783
|
-
const workspace =
|
|
108879
|
+
const workspace = agentWorkspaceMeta(agent);
|
|
108784
108880
|
return [
|
|
108785
108881
|
{
|
|
108786
108882
|
key: "origin",
|
|
@@ -108820,7 +108916,7 @@ function approvalMode(agent) {
|
|
|
108820
108916
|
className: "border-amber-500/30 bg-amber-500/10 text-amber-300"
|
|
108821
108917
|
};
|
|
108822
108918
|
}
|
|
108823
|
-
function
|
|
108919
|
+
function agentWorkspaceMeta(agent) {
|
|
108824
108920
|
const workspace = recordValue(agent.meta?.workspace);
|
|
108825
108921
|
const requested = stringValue(workspace.requestedMode) || stringValue(agent.meta?.workspaceMode);
|
|
108826
108922
|
const effective = stringValue(workspace.mode);
|
|
@@ -108830,6 +108926,7 @@ function workspaceMode(agent) {
|
|
|
108830
108926
|
label: "Isolated",
|
|
108831
108927
|
title: "Workspace: isolated worktree",
|
|
108832
108928
|
Icon: GitBranch,
|
|
108929
|
+
iconColor: "text-violet-300",
|
|
108833
108930
|
className: "border-violet-500/30 bg-violet-500/10 text-violet-300"
|
|
108834
108931
|
};
|
|
108835
108932
|
if (mode === "shared") return {
|
|
@@ -108837,6 +108934,7 @@ function workspaceMode(agent) {
|
|
|
108837
108934
|
label: "Shared",
|
|
108838
108935
|
title: "Workspace: shared repo checkout",
|
|
108839
108936
|
Icon: Share2,
|
|
108937
|
+
iconColor: "text-cyan-300",
|
|
108840
108938
|
className: "border-cyan-500/30 bg-cyan-500/10 text-cyan-300"
|
|
108841
108939
|
};
|
|
108842
108940
|
return {
|
|
@@ -108844,12 +108942,18 @@ function workspaceMode(agent) {
|
|
|
108844
108942
|
label: "Default",
|
|
108845
108943
|
title: effective ? `Workspace: default/inherit, resolved to ${effective}` : "Workspace: default/inherit",
|
|
108846
108944
|
Icon: Layers,
|
|
108945
|
+
iconColor: "text-zinc-400",
|
|
108847
108946
|
className: "border-zinc-500/30 bg-zinc-500/10 text-zinc-300"
|
|
108848
108947
|
};
|
|
108849
108948
|
}
|
|
108850
108949
|
function recordValue(value) {
|
|
108851
108950
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
108852
108951
|
}
|
|
108952
|
+
function agentProjectName(agent) {
|
|
108953
|
+
const workspace = recordValue(agent.meta?.workspace);
|
|
108954
|
+
const root = stringValue(workspace.repoRoot) || stringValue(workspace.sourceCwd) || stringValue(agent.meta?.cwd);
|
|
108955
|
+
return root ? shortPath$1(root, 2) : "";
|
|
108956
|
+
}
|
|
108853
108957
|
function runtimeBadges(agent) {
|
|
108854
108958
|
const caps = agent.providerCapabilities;
|
|
108855
108959
|
const context = agent.context;
|
|
@@ -108865,40 +108969,47 @@ function runtimeBadges(agent) {
|
|
|
108865
108969
|
if (context) badges.push(`${Math.round(context.utilization * 100)}% ctx`);
|
|
108866
108970
|
return badges;
|
|
108867
108971
|
}
|
|
108868
|
-
function ContextRing({ utilization, className }) {
|
|
108972
|
+
function ContextRing({ utilization, size = 26, className }) {
|
|
108869
108973
|
const pct = Math.round(Math.min(1, Math.max(0, utilization)) * 100);
|
|
108870
|
-
const
|
|
108974
|
+
const stroke = size >= 24 ? 3 : 2.5;
|
|
108975
|
+
const c = size / 2;
|
|
108976
|
+
const r = c - stroke;
|
|
108871
108977
|
const circumference = 2 * Math.PI * r;
|
|
108872
108978
|
const offset = circumference * (1 - Math.min(1, Math.max(0, utilization)));
|
|
108873
108979
|
const color = utilization > .8 ? "text-red-400" : utilization > .5 ? "text-yellow-400" : "text-emerald-400";
|
|
108874
108980
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
108875
108981
|
className: `relative shrink-0 ${className ?? ""}`,
|
|
108982
|
+
style: {
|
|
108983
|
+
width: size,
|
|
108984
|
+
height: size
|
|
108985
|
+
},
|
|
108876
108986
|
title: `Context: ${pct}%`,
|
|
108877
108987
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
|
|
108878
|
-
width:
|
|
108879
|
-
height:
|
|
108880
|
-
viewBox:
|
|
108988
|
+
width: size,
|
|
108989
|
+
height: size,
|
|
108990
|
+
viewBox: `0 0 ${size} ${size}`,
|
|
108881
108991
|
className: "rotate-[-90deg]",
|
|
108882
108992
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", {
|
|
108883
|
-
cx:
|
|
108884
|
-
cy:
|
|
108993
|
+
cx: c,
|
|
108994
|
+
cy: c,
|
|
108885
108995
|
r,
|
|
108886
108996
|
fill: "none",
|
|
108887
|
-
strokeWidth:
|
|
108997
|
+
strokeWidth: stroke,
|
|
108888
108998
|
className: "stroke-muted-foreground/20"
|
|
108889
108999
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", {
|
|
108890
|
-
cx:
|
|
108891
|
-
cy:
|
|
109000
|
+
cx: c,
|
|
109001
|
+
cy: c,
|
|
108892
109002
|
r,
|
|
108893
109003
|
fill: "none",
|
|
108894
|
-
strokeWidth:
|
|
109004
|
+
strokeWidth: stroke,
|
|
108895
109005
|
strokeDasharray: circumference,
|
|
108896
109006
|
strokeDashoffset: offset,
|
|
108897
109007
|
strokeLinecap: "round",
|
|
108898
109008
|
className: `${color} stroke-current transition-all duration-500`
|
|
108899
109009
|
})]
|
|
108900
109010
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
108901
|
-
className: `absolute inset-0 flex items-center justify-center
|
|
109011
|
+
className: `absolute inset-0 flex items-center justify-center font-semibold leading-none ${color}`,
|
|
109012
|
+
style: { fontSize: size >= 24 ? 8 : 7 },
|
|
108902
109013
|
children: pct
|
|
108903
109014
|
})]
|
|
108904
109015
|
});
|
|
@@ -124794,7 +124905,6 @@ function FileContent({ orchestratorId, selectedPath, line, onReadError }) {
|
|
|
124794
124905
|
const { file, loading, error } = useFileRead(orchestratorId, selectedPath);
|
|
124795
124906
|
const lineRef = (0, import_react.useRef)(null);
|
|
124796
124907
|
const [mode, setMode] = (0, import_react.useState)("raw");
|
|
124797
|
-
const [copiedPath, setCopiedPath] = (0, import_react.useState)(false);
|
|
124798
124908
|
(0, import_react.useEffect)(() => {
|
|
124799
124909
|
onReadError(error);
|
|
124800
124910
|
}, [error, onReadError]);
|
|
@@ -124816,15 +124926,6 @@ function FileContent({ orchestratorId, selectedPath, line, onReadError }) {
|
|
|
124816
124926
|
file?.content,
|
|
124817
124927
|
line
|
|
124818
124928
|
]);
|
|
124819
|
-
async function copyPath(path) {
|
|
124820
|
-
try {
|
|
124821
|
-
await navigator.clipboard?.writeText(path);
|
|
124822
|
-
setCopiedPath(true);
|
|
124823
|
-
window.setTimeout(() => setCopiedPath(false), 1400);
|
|
124824
|
-
} catch {
|
|
124825
|
-
setCopiedPath(false);
|
|
124826
|
-
}
|
|
124827
|
-
}
|
|
124828
124929
|
function selectMode(nextMode, kind) {
|
|
124829
124930
|
setMode(nextMode);
|
|
124830
124931
|
if (kind) writeModePreference(kind, nextMode);
|
|
@@ -124849,14 +124950,13 @@ function FileContent({ orchestratorId, selectedPath, line, onReadError }) {
|
|
|
124849
124950
|
className: "min-w-0 flex-1 truncate font-mono",
|
|
124850
124951
|
children: file.path
|
|
124851
124952
|
}),
|
|
124852
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
124853
|
-
|
|
124953
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CopyButton, {
|
|
124954
|
+
value: file.path,
|
|
124955
|
+
label: "Copy path",
|
|
124956
|
+
copiedLabel: "Copied path",
|
|
124854
124957
|
size: "icon",
|
|
124855
124958
|
variant: "ghost",
|
|
124856
|
-
className: "h-7 w-7 shrink-0"
|
|
124857
|
-
onClick: () => copyPath(file.path),
|
|
124858
|
-
title: copiedPath ? "Copied path" : "Copy path",
|
|
124859
|
-
children: copiedPath ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Check, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Copy, { className: "h-3.5 w-3.5" })
|
|
124959
|
+
className: "h-7 w-7 shrink-0"
|
|
124860
124960
|
}),
|
|
124861
124961
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge$1, {
|
|
124862
124962
|
variant: "outline",
|
|
@@ -124913,14 +125013,13 @@ function FileContent({ orchestratorId, selectedPath, line, onReadError }) {
|
|
|
124913
125013
|
className: "min-w-0 flex-1 truncate font-mono",
|
|
124914
125014
|
children: file.path
|
|
124915
125015
|
}),
|
|
124916
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
124917
|
-
|
|
125016
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CopyButton, {
|
|
125017
|
+
value: file.path,
|
|
125018
|
+
label: "Copy path",
|
|
125019
|
+
copiedLabel: "Copied path",
|
|
124918
125020
|
size: "icon",
|
|
124919
125021
|
variant: "ghost",
|
|
124920
|
-
className: "h-7 w-7 shrink-0"
|
|
124921
|
-
onClick: () => copyPath(file.path),
|
|
124922
|
-
title: copiedPath ? "Copied path" : "Copy path",
|
|
124923
|
-
children: copiedPath ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Check, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Copy, { className: "h-3.5 w-3.5" })
|
|
125022
|
+
className: "h-7 w-7 shrink-0"
|
|
124924
125023
|
}),
|
|
124925
125024
|
file.truncated && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge$1, {
|
|
124926
125025
|
variant: "secondary",
|
|
@@ -125617,6 +125716,8 @@ function AgentListPanel({ threads, onSelectAgent }) {
|
|
|
125617
125716
|
const chatAgentTagFilter = useRelayStore((s) => s.chatAgentTagFilter);
|
|
125618
125717
|
const chatAgentCapFilter = useRelayStore((s) => s.chatAgentCapFilter);
|
|
125619
125718
|
const chatAgentHostFilter = useRelayStore((s) => s.chatAgentHostFilter);
|
|
125719
|
+
const chatAgentGroupBy = useRelayStore((s) => s.chatAgentGroupBy);
|
|
125720
|
+
const chatAgentFiltersCollapsed = useRelayStore((s) => s.chatAgentFiltersCollapsed);
|
|
125620
125721
|
const now = useNow();
|
|
125621
125722
|
const chatAgents = useChatAgents();
|
|
125622
125723
|
const threadByPeer = (0, import_react.useMemo)(() => {
|
|
@@ -125640,161 +125741,287 @@ function AgentListPanel({ threads, onSelectAgent }) {
|
|
|
125640
125741
|
const uniqueTags = (0, import_react.useMemo)(() => [...new Set(chatAgents.flatMap((a) => a.tags || []))], [chatAgents]);
|
|
125641
125742
|
const uniqueCaps = (0, import_react.useMemo)(() => [...new Set(chatAgents.flatMap((a) => userFacingCapabilities(a.capabilities || [])))], [chatAgents]);
|
|
125642
125743
|
const uniqueHosts = useUniqueHosts();
|
|
125744
|
+
const groupedAgents = (0, import_react.useMemo)(() => {
|
|
125745
|
+
if (chatAgentGroupBy !== "project") return null;
|
|
125746
|
+
const groups = /* @__PURE__ */ new Map();
|
|
125747
|
+
for (const a of sortedAgents) {
|
|
125748
|
+
const key = agentProjectName(a) || "No project";
|
|
125749
|
+
const bucket = groups.get(key);
|
|
125750
|
+
if (bucket) bucket.push(a);
|
|
125751
|
+
else groups.set(key, [a]);
|
|
125752
|
+
}
|
|
125753
|
+
return [...groups.entries()].sort((a, b) => a[0].localeCompare(b[0]));
|
|
125754
|
+
}, [sortedAgents, chatAgentGroupBy]);
|
|
125755
|
+
const activeFilterCount = [
|
|
125756
|
+
chatAgentProviderFilter,
|
|
125757
|
+
chatAgentStatusFilter,
|
|
125758
|
+
chatAgentTagFilter,
|
|
125759
|
+
chatAgentCapFilter,
|
|
125760
|
+
chatAgentHostFilter
|
|
125761
|
+
].filter(Boolean).length;
|
|
125643
125762
|
function handleSelect(id) {
|
|
125644
125763
|
openInboxThread(id, threadByPeer.get(id)?.messages);
|
|
125645
125764
|
onSelectAgent?.(id);
|
|
125646
125765
|
}
|
|
125647
|
-
|
|
125648
|
-
|
|
125649
|
-
|
|
125650
|
-
|
|
125651
|
-
|
|
125652
|
-
|
|
125653
|
-
|
|
125654
|
-
|
|
125655
|
-
|
|
125656
|
-
|
|
125657
|
-
|
|
125658
|
-
|
|
125659
|
-
|
|
125660
|
-
|
|
125661
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
125662
|
-
|
|
125663
|
-
|
|
125664
|
-
|
|
125665
|
-
|
|
125666
|
-
|
|
125766
|
+
function renderAgentRow(agent) {
|
|
125767
|
+
const thread = threadByPeer.get(agent.id);
|
|
125768
|
+
const unread = thread?.attention.unread || 0;
|
|
125769
|
+
const lastMsg = thread?.previewMessage;
|
|
125770
|
+
const lastActivityAt = threadActivityTimestamp(thread);
|
|
125771
|
+
const isSelected = selectedInboxThread === agent.id;
|
|
125772
|
+
const ws = agentWorkspaceMeta(agent);
|
|
125773
|
+
const project = agentProjectName(agent);
|
|
125774
|
+
const WsIcon = ws.Icon;
|
|
125775
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
|
|
125776
|
+
className: cn$2("w-full text-left px-3 py-2.5 flex items-start gap-2.5 hover:bg-muted/50 transition-colors border-b border-border/50", isSelected && "bg-muted/60"),
|
|
125777
|
+
onClick: () => handleSelect(agent.id),
|
|
125778
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
125779
|
+
className: "relative shrink-0 mt-0.5",
|
|
125780
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AgentTypeIcon, { agent }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusDot, {
|
|
125781
|
+
agent,
|
|
125782
|
+
now,
|
|
125783
|
+
className: "absolute -bottom-0.5 -right-0.5 w-2 h-2"
|
|
125784
|
+
})]
|
|
125785
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
125786
|
+
className: "flex-1 min-w-0",
|
|
125787
|
+
children: [
|
|
125788
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
125789
|
+
className: "flex items-center justify-between gap-1 mb-0.5",
|
|
125790
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
125791
|
+
className: "text-xs font-medium truncate",
|
|
125792
|
+
children: displayName(agent)
|
|
125793
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
125794
|
+
className: "flex items-center gap-1 shrink-0",
|
|
125795
|
+
children: [lastActivityAt > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
125796
|
+
className: "text-[10px] text-muted-foreground",
|
|
125797
|
+
title: fmtTime$1(lastActivityAt),
|
|
125798
|
+
children: timeAgo(now, lastActivityAt)
|
|
125799
|
+
}), unread > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge$1, {
|
|
125800
|
+
className: "bg-red-500 text-white text-xs min-w-[18px] h-[18px] flex items-center justify-center shrink-0 px-1",
|
|
125801
|
+
children: unread
|
|
125802
|
+
})]
|
|
125803
|
+
})]
|
|
125804
|
+
}),
|
|
125805
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
125806
|
+
className: "flex items-center gap-1.5 mb-0.5 text-[10px] text-muted-foreground",
|
|
125667
125807
|
children: [
|
|
125668
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("
|
|
125669
|
-
|
|
125670
|
-
|
|
125671
|
-
|
|
125672
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125673
|
-
value: "name",
|
|
125674
|
-
children: "By name"
|
|
125808
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
125809
|
+
title: ws.title,
|
|
125810
|
+
className: "inline-flex shrink-0",
|
|
125811
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WsIcon, { className: cn$2("h-3 w-3", ws.iconColor) })
|
|
125675
125812
|
}),
|
|
125676
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("
|
|
125677
|
-
|
|
125678
|
-
children:
|
|
125813
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
125814
|
+
className: "truncate",
|
|
125815
|
+
children: project || ws.label
|
|
125679
125816
|
}),
|
|
125680
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("
|
|
125681
|
-
|
|
125682
|
-
children:
|
|
125817
|
+
agent.context && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
125818
|
+
className: "ml-auto shrink-0",
|
|
125819
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextRing, {
|
|
125820
|
+
utilization: agent.context.utilization,
|
|
125821
|
+
size: 18
|
|
125822
|
+
})
|
|
125683
125823
|
})
|
|
125684
125824
|
]
|
|
125685
|
-
}),
|
|
125686
|
-
|
|
125687
|
-
|
|
125688
|
-
|
|
125689
|
-
|
|
125690
|
-
|
|
125691
|
-
|
|
125692
|
-
|
|
125693
|
-
|
|
125694
|
-
|
|
125695
|
-
|
|
125696
|
-
|
|
125697
|
-
|
|
125698
|
-
|
|
125825
|
+
}),
|
|
125826
|
+
lastMsg && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
|
|
125827
|
+
className: "text-xs text-muted-foreground truncate leading-tight",
|
|
125828
|
+
children: [lastMsg.from === "user" ? "You: " : "", messagePreview(lastMsg)]
|
|
125829
|
+
}),
|
|
125830
|
+
agent.status !== "offline" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
125831
|
+
className: "mt-1",
|
|
125832
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
125833
|
+
className: cn$2("text-xs", agent.status === "busy" ? "text-yellow-400" : "text-emerald-400"),
|
|
125834
|
+
children: agent.status
|
|
125835
|
+
})
|
|
125836
|
+
})
|
|
125837
|
+
]
|
|
125838
|
+
})]
|
|
125839
|
+
}) }, agent.id);
|
|
125840
|
+
}
|
|
125841
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
125842
|
+
className: "flex flex-col h-full border-r border-border min-w-0",
|
|
125843
|
+
children: [
|
|
125844
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
125845
|
+
className: "p-3 border-b border-border space-y-2",
|
|
125846
|
+
children: [
|
|
125847
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
125848
|
+
className: "relative",
|
|
125849
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Search, { className: "absolute left-2.5 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground pointer-events-none" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Input, {
|
|
125850
|
+
placeholder: "Search agents...",
|
|
125851
|
+
value: chatAgentSearch,
|
|
125852
|
+
onChange: (e) => set({ chatAgentSearch: e.target.value }),
|
|
125853
|
+
className: "pl-8 h-7 text-xs"
|
|
125854
|
+
})]
|
|
125855
|
+
}),
|
|
125856
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
|
|
125857
|
+
type: "button",
|
|
125858
|
+
onClick: () => set({ chatAgentFiltersCollapsed: !chatAgentFiltersCollapsed }),
|
|
125859
|
+
className: "sm:hidden flex w-full items-center justify-between h-6 px-1.5 text-xs rounded-md border border-border bg-background text-muted-foreground",
|
|
125860
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
125861
|
+
className: "inline-flex items-center gap-1.5",
|
|
125699
125862
|
children: [
|
|
125700
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("
|
|
125701
|
-
|
|
125702
|
-
|
|
125703
|
-
|
|
125704
|
-
|
|
125705
|
-
value: "claude",
|
|
125706
|
-
children: "Claude"
|
|
125707
|
-
}),
|
|
125708
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125709
|
-
value: "codex",
|
|
125710
|
-
children: "Codex"
|
|
125711
|
-
}),
|
|
125712
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125713
|
-
value: "agent",
|
|
125714
|
-
children: "Agent"
|
|
125715
|
-
}),
|
|
125716
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125717
|
-
value: "user",
|
|
125718
|
-
children: "User"
|
|
125863
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SlidersHorizontal, { className: "w-3.5 h-3.5" }),
|
|
125864
|
+
"Filters & sort",
|
|
125865
|
+
activeFilterCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge$1, {
|
|
125866
|
+
className: "bg-primary/20 text-primary text-[10px] h-4 min-w-4 px-1 flex items-center justify-center",
|
|
125867
|
+
children: activeFilterCount
|
|
125719
125868
|
})
|
|
125720
125869
|
]
|
|
125721
|
-
}),
|
|
125722
|
-
|
|
125723
|
-
|
|
125724
|
-
|
|
125725
|
-
|
|
125726
|
-
|
|
125727
|
-
|
|
125870
|
+
}), chatAgentFiltersCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronDown, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronUp, { className: "w-3.5 h-3.5" })]
|
|
125871
|
+
}),
|
|
125872
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
125873
|
+
className: cn$2("space-y-2", chatAgentFiltersCollapsed ? "hidden" : "block", "sm:block"),
|
|
125874
|
+
children: [
|
|
125875
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
125876
|
+
className: "flex items-center gap-1.5",
|
|
125877
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", {
|
|
125878
|
+
value: chatAgentSort,
|
|
125879
|
+
onChange: (e) => set({ chatAgentSort: e.target.value }),
|
|
125880
|
+
className: "flex-1 h-6 text-xs rounded-md border border-border bg-background px-1.5 text-foreground",
|
|
125881
|
+
children: [
|
|
125882
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125883
|
+
value: "status",
|
|
125884
|
+
children: "By status"
|
|
125885
|
+
}),
|
|
125886
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125887
|
+
value: "name",
|
|
125888
|
+
children: "By name"
|
|
125889
|
+
}),
|
|
125890
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125891
|
+
value: "lastSeen",
|
|
125892
|
+
children: "By last seen"
|
|
125893
|
+
}),
|
|
125894
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125895
|
+
value: "lastMessage",
|
|
125896
|
+
children: "By last activity"
|
|
125897
|
+
})
|
|
125898
|
+
]
|
|
125899
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
125900
|
+
variant: "ghost",
|
|
125901
|
+
size: "icon-xs",
|
|
125902
|
+
onClick: () => set({ chatAgentSortDir: chatAgentSortDir === "asc" ? "desc" : "asc" }),
|
|
125903
|
+
children: chatAgentSortDir === "asc" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArrowUpNarrowWide, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArrowDownWideNarrow, { className: "w-3.5 h-3.5" })
|
|
125904
|
+
})]
|
|
125905
|
+
}),
|
|
125906
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", {
|
|
125907
|
+
value: chatAgentGroupBy,
|
|
125908
|
+
onChange: (e) => set({ chatAgentGroupBy: e.target.value }),
|
|
125909
|
+
className: "w-full h-6 text-xs rounded-md border border-border bg-background px-1.5 text-foreground",
|
|
125910
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125728
125911
|
value: "",
|
|
125729
|
-
children: "
|
|
125730
|
-
}),
|
|
125731
|
-
|
|
125732
|
-
|
|
125733
|
-
|
|
125734
|
-
|
|
125735
|
-
|
|
125736
|
-
|
|
125737
|
-
|
|
125738
|
-
|
|
125739
|
-
|
|
125740
|
-
|
|
125741
|
-
|
|
125742
|
-
|
|
125743
|
-
|
|
125744
|
-
|
|
125745
|
-
|
|
125746
|
-
|
|
125747
|
-
|
|
125748
|
-
|
|
125749
|
-
|
|
125750
|
-
|
|
125751
|
-
|
|
125752
|
-
|
|
125753
|
-
|
|
125754
|
-
|
|
125755
|
-
|
|
125756
|
-
|
|
125757
|
-
|
|
125758
|
-
|
|
125759
|
-
|
|
125760
|
-
|
|
125761
|
-
|
|
125762
|
-
|
|
125763
|
-
|
|
125764
|
-
|
|
125765
|
-
|
|
125766
|
-
|
|
125767
|
-
|
|
125768
|
-
|
|
125769
|
-
|
|
125770
|
-
|
|
125771
|
-
|
|
125772
|
-
|
|
125773
|
-
|
|
125774
|
-
|
|
125775
|
-
|
|
125776
|
-
|
|
125777
|
-
|
|
125778
|
-
|
|
125779
|
-
|
|
125780
|
-
|
|
125781
|
-
|
|
125782
|
-
|
|
125783
|
-
|
|
125784
|
-
|
|
125785
|
-
|
|
125786
|
-
|
|
125787
|
-
|
|
125788
|
-
|
|
125789
|
-
|
|
125790
|
-
|
|
125791
|
-
|
|
125792
|
-
|
|
125912
|
+
children: "No grouping"
|
|
125913
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125914
|
+
value: "project",
|
|
125915
|
+
children: "Group by project"
|
|
125916
|
+
})]
|
|
125917
|
+
}),
|
|
125918
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
125919
|
+
className: "flex gap-1",
|
|
125920
|
+
children: [
|
|
125921
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", {
|
|
125922
|
+
value: chatAgentProviderFilter,
|
|
125923
|
+
onChange: (e) => set({ chatAgentProviderFilter: e.target.value }),
|
|
125924
|
+
className: "flex-1 h-6 text-xs rounded-md border border-border bg-background px-1.5 text-foreground",
|
|
125925
|
+
children: [
|
|
125926
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125927
|
+
value: "",
|
|
125928
|
+
children: "All types"
|
|
125929
|
+
}),
|
|
125930
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125931
|
+
value: "claude",
|
|
125932
|
+
children: "Claude"
|
|
125933
|
+
}),
|
|
125934
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125935
|
+
value: "codex",
|
|
125936
|
+
children: "Codex"
|
|
125937
|
+
}),
|
|
125938
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125939
|
+
value: "agent",
|
|
125940
|
+
children: "Agent"
|
|
125941
|
+
}),
|
|
125942
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125943
|
+
value: "user",
|
|
125944
|
+
children: "User"
|
|
125945
|
+
})
|
|
125946
|
+
]
|
|
125947
|
+
}),
|
|
125948
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", {
|
|
125949
|
+
value: chatAgentStatusFilter,
|
|
125950
|
+
onChange: (e) => set({ chatAgentStatusFilter: e.target.value }),
|
|
125951
|
+
className: "flex-1 h-6 text-xs rounded-md border border-border bg-background px-1.5 text-foreground",
|
|
125952
|
+
children: [
|
|
125953
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125954
|
+
value: "",
|
|
125955
|
+
children: "All status"
|
|
125956
|
+
}),
|
|
125957
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125958
|
+
value: "online",
|
|
125959
|
+
children: "Online"
|
|
125960
|
+
}),
|
|
125961
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125962
|
+
value: "idle",
|
|
125963
|
+
children: "Idle"
|
|
125964
|
+
}),
|
|
125965
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125966
|
+
value: "busy",
|
|
125967
|
+
children: "Busy"
|
|
125968
|
+
}),
|
|
125969
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125970
|
+
value: "offline",
|
|
125971
|
+
children: "Offline"
|
|
125972
|
+
})
|
|
125973
|
+
]
|
|
125974
|
+
}),
|
|
125975
|
+
uniqueHosts.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", {
|
|
125976
|
+
value: chatAgentHostFilter,
|
|
125977
|
+
onChange: (e) => set({ chatAgentHostFilter: e.target.value }),
|
|
125978
|
+
className: "flex-1 h-6 text-xs rounded-md border border-border bg-background px-1.5 text-foreground",
|
|
125979
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125980
|
+
value: "",
|
|
125981
|
+
children: "All hosts"
|
|
125982
|
+
}), uniqueHosts.map((h) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125983
|
+
value: h,
|
|
125984
|
+
children: h
|
|
125985
|
+
}, h))]
|
|
125986
|
+
})
|
|
125987
|
+
]
|
|
125988
|
+
}),
|
|
125989
|
+
(uniqueTags.length > 0 || uniqueCaps.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
125990
|
+
className: "flex gap-1",
|
|
125991
|
+
children: [uniqueTags.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", {
|
|
125992
|
+
value: chatAgentTagFilter,
|
|
125993
|
+
onChange: (e) => set({ chatAgentTagFilter: e.target.value }),
|
|
125994
|
+
className: "flex-1 h-6 text-xs rounded-md border border-border bg-background px-1.5 text-foreground",
|
|
125995
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
125996
|
+
value: "",
|
|
125997
|
+
children: "All tags"
|
|
125998
|
+
}), uniqueTags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("option", {
|
|
125999
|
+
value: t,
|
|
126000
|
+
children: ["#", t]
|
|
126001
|
+
}, t))]
|
|
126002
|
+
}), uniqueCaps.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", {
|
|
126003
|
+
value: chatAgentCapFilter,
|
|
126004
|
+
onChange: (e) => set({ chatAgentCapFilter: e.target.value }),
|
|
126005
|
+
className: "flex-1 h-6 text-xs rounded-md border border-border bg-background px-1.5 text-foreground",
|
|
126006
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
126007
|
+
value: "",
|
|
126008
|
+
children: "All caps"
|
|
126009
|
+
}), uniqueCaps.map((c) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
126010
|
+
value: c,
|
|
126011
|
+
children: c
|
|
126012
|
+
}, c))]
|
|
126013
|
+
})]
|
|
126014
|
+
})
|
|
126015
|
+
]
|
|
126016
|
+
})
|
|
126017
|
+
]
|
|
126018
|
+
}),
|
|
126019
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
|
|
125793
126020
|
type: "button",
|
|
125794
|
-
className: "flex w-full items-
|
|
126021
|
+
className: "flex w-full shrink-0 items-center gap-2.5 border-b border-border px-3 py-2 text-left transition-colors hover:bg-muted/50",
|
|
125795
126022
|
onClick: openAgentSpawn,
|
|
125796
126023
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
125797
|
-
className: "
|
|
126024
|
+
className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full border border-dashed border-primary/50 bg-primary/10 text-primary",
|
|
125798
126025
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Plus, { className: "h-3.5 w-3.5" })
|
|
125799
126026
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
125800
126027
|
className: "min-w-0 flex-1",
|
|
@@ -125802,71 +126029,31 @@ function AgentListPanel({ threads, onSelectAgent }) {
|
|
|
125802
126029
|
className: "text-xs font-medium",
|
|
125803
126030
|
children: "New Agent"
|
|
125804
126031
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
125805
|
-
className: "
|
|
126032
|
+
className: "truncate text-[10px] text-muted-foreground",
|
|
125806
126033
|
children: "Spawn a fresh chat agent"
|
|
125807
126034
|
})]
|
|
125808
126035
|
})]
|
|
125809
|
-
}),
|
|
125810
|
-
|
|
125811
|
-
|
|
125812
|
-
|
|
125813
|
-
|
|
125814
|
-
|
|
125815
|
-
|
|
125816
|
-
|
|
125817
|
-
const unread = thread?.attention.unread || 0;
|
|
125818
|
-
const lastMsg = thread?.previewMessage;
|
|
125819
|
-
const lastActivityAt = threadActivityTimestamp(thread);
|
|
125820
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
|
|
125821
|
-
className: cn$2("w-full text-left px-3 py-2.5 flex items-start gap-2.5 hover:bg-muted/50 transition-colors border-b border-border/50", selectedInboxThread === agent.id && "bg-muted/60"),
|
|
125822
|
-
onClick: () => handleSelect(agent.id),
|
|
125823
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
125824
|
-
className: "relative shrink-0 mt-0.5",
|
|
125825
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AgentTypeIcon, { agent }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusDot, {
|
|
125826
|
-
agent,
|
|
125827
|
-
now,
|
|
125828
|
-
className: "absolute -bottom-0.5 -right-0.5 w-2 h-2"
|
|
125829
|
-
})]
|
|
125830
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
125831
|
-
className: "flex-1 min-w-0",
|
|
125832
|
-
children: [
|
|
125833
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
125834
|
-
className: "flex items-center justify-between gap-1 mb-0.5",
|
|
125835
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
125836
|
-
className: "text-xs font-medium truncate",
|
|
125837
|
-
children: displayName(agent)
|
|
125838
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
125839
|
-
className: "flex items-center gap-1 shrink-0",
|
|
125840
|
-
children: [lastActivityAt > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
125841
|
-
className: "text-[10px] text-muted-foreground",
|
|
125842
|
-
title: fmtTime$1(lastActivityAt),
|
|
125843
|
-
children: timeAgo(now, lastActivityAt)
|
|
125844
|
-
}), unread > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge$1, {
|
|
125845
|
-
className: "bg-red-500 text-white text-xs min-w-[18px] h-[18px] flex items-center justify-center shrink-0 px-1",
|
|
125846
|
-
children: unread
|
|
125847
|
-
})]
|
|
125848
|
-
})]
|
|
125849
|
-
}),
|
|
125850
|
-
typeof agent.meta?.cwd === "string" && agent.meta.cwd && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
125851
|
-
className: "font-mono text-[10px] text-muted-foreground/60 truncate",
|
|
125852
|
-
children: shortPath$1(agent.meta.cwd)
|
|
125853
|
-
}),
|
|
125854
|
-
lastMsg && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
|
|
125855
|
-
className: "text-xs text-muted-foreground truncate leading-tight",
|
|
125856
|
-
children: [lastMsg.from === "user" ? "You: " : "", messagePreview(lastMsg)]
|
|
125857
|
-
}),
|
|
125858
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
125859
|
-
className: "flex flex-wrap gap-1 mt-1",
|
|
125860
|
-
children: agent.status !== "offline" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
125861
|
-
className: cn$2("text-xs", agent.status === "busy" ? "text-yellow-400" : agent.status === "idle" ? "text-emerald-400" : "text-emerald-400"),
|
|
125862
|
-
children: agent.status
|
|
125863
|
-
})
|
|
125864
|
-
})
|
|
125865
|
-
]
|
|
126036
|
+
}),
|
|
126037
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
126038
|
+
className: "flex-1 overflow-y-auto",
|
|
126039
|
+
children: sortedAgents.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
126040
|
+
className: "flex flex-col items-center justify-center py-10 text-center px-4",
|
|
126041
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Bot, { className: "w-8 h-8 text-zinc-600 mb-2" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
126042
|
+
className: "text-xs text-muted-foreground",
|
|
126043
|
+
children: "No agents match filters"
|
|
125866
126044
|
})]
|
|
125867
|
-
})
|
|
125868
|
-
|
|
125869
|
-
|
|
126045
|
+
}) : groupedAgents ? groupedAgents.map(([project, agents]) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
126046
|
+
className: "sticky top-0 z-10 flex items-center gap-1.5 border-b border-border/50 bg-background/95 px-3 py-1 text-[10px] font-medium uppercase tracking-wide text-muted-foreground backdrop-blur",
|
|
126047
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
126048
|
+
className: "truncate",
|
|
126049
|
+
children: project
|
|
126050
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
126051
|
+
className: "text-muted-foreground/50",
|
|
126052
|
+
children: agents.length
|
|
126053
|
+
})]
|
|
126054
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { children: agents.map(renderAgentRow) })] }, project)) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { children: sortedAgents.map(renderAgentRow) })
|
|
126055
|
+
})
|
|
126056
|
+
]
|
|
125870
126057
|
});
|
|
125871
126058
|
}
|
|
125872
126059
|
function chatTimestamp(iso) {
|
|
@@ -125926,40 +126113,6 @@ var TIMELINE_STATUS_LABELS = {
|
|
|
125926
126113
|
var TIMELINE_STATUSES = new Set(Object.keys(TIMELINE_STATUS_LABELS));
|
|
125927
126114
|
var STATUS_DEDUPE_WINDOW_MS = 3e3;
|
|
125928
126115
|
var CHAT_BOTTOM_THRESHOLD_PX = 96;
|
|
125929
|
-
var KOKORO_VOICES = [
|
|
125930
|
-
{
|
|
125931
|
-
id: "am_michael",
|
|
125932
|
-
label: "Michael (US ♂)"
|
|
125933
|
-
},
|
|
125934
|
-
{
|
|
125935
|
-
id: "am_adam",
|
|
125936
|
-
label: "Adam (US ♂)"
|
|
125937
|
-
},
|
|
125938
|
-
{
|
|
125939
|
-
id: "af_heart",
|
|
125940
|
-
label: "Heart (US ♀)"
|
|
125941
|
-
},
|
|
125942
|
-
{
|
|
125943
|
-
id: "af_bella",
|
|
125944
|
-
label: "Bella (US ♀)"
|
|
125945
|
-
},
|
|
125946
|
-
{
|
|
125947
|
-
id: "af_nicole",
|
|
125948
|
-
label: "Nicole (US ♀)"
|
|
125949
|
-
},
|
|
125950
|
-
{
|
|
125951
|
-
id: "af_sarah",
|
|
125952
|
-
label: "Sarah (US ♀)"
|
|
125953
|
-
},
|
|
125954
|
-
{
|
|
125955
|
-
id: "bm_george",
|
|
125956
|
-
label: "George (UK ♂)"
|
|
125957
|
-
},
|
|
125958
|
-
{
|
|
125959
|
-
id: "bf_emma",
|
|
125960
|
-
label: "Emma (UK ♀)"
|
|
125961
|
-
}
|
|
125962
|
-
];
|
|
125963
126116
|
function StatusMarker({ event }) {
|
|
125964
126117
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
125965
126118
|
className: "flex items-center justify-center gap-2 py-2 my-1",
|
|
@@ -127119,21 +127272,7 @@ function ChatPanel({ threads, onBack, showBackButton }) {
|
|
|
127119
127272
|
const fetchOrchestrators = useRelayStore((s) => s.fetchOrchestrators);
|
|
127120
127273
|
const voiceTtsEnabled = useRelayStore((s) => s.voiceTtsEnabled);
|
|
127121
127274
|
const setVoiceTtsEnabled = useRelayStore((s) => s.setVoiceTtsEnabled);
|
|
127122
|
-
const voiceTtsLang = useRelayStore((s) => s.voiceTtsLang);
|
|
127123
|
-
const setVoiceTtsLang = useRelayStore((s) => s.setVoiceTtsLang);
|
|
127124
|
-
const voiceTtsMode = useRelayStore((s) => s.voiceTtsMode);
|
|
127125
|
-
const setVoiceTtsMode = useRelayStore((s) => s.setVoiceTtsMode);
|
|
127126
|
-
const voiceTtsKokoroVoice = useRelayStore((s) => s.voiceTtsKokoroVoice);
|
|
127127
|
-
const setVoiceTtsKokoroVoice = useRelayStore((s) => s.setVoiceTtsKokoroVoice);
|
|
127128
127275
|
const voiceInputMode = useRelayStore((s) => s.voiceInputMode);
|
|
127129
|
-
const [speechLangs, setSpeechLangs] = (0, import_react.useState)(() => availableSpeechLangs());
|
|
127130
|
-
(0, import_react.useEffect)(() => {
|
|
127131
|
-
if (!voiceTts.available) return;
|
|
127132
|
-
const refresh = () => setSpeechLangs(availableSpeechLangs());
|
|
127133
|
-
refresh();
|
|
127134
|
-
window.speechSynthesis.addEventListener?.("voiceschanged", refresh);
|
|
127135
|
-
return () => window.speechSynthesis.removeEventListener?.("voiceschanged", refresh);
|
|
127136
|
-
}, []);
|
|
127137
127276
|
const fileInputRef = (0, import_react.useRef)(null);
|
|
127138
127277
|
const pttRecorderRef = (0, import_react.useRef)(null);
|
|
127139
127278
|
const [micState, setMicState] = (0, import_react.useState)("idle");
|
|
@@ -127549,55 +127688,19 @@ function ChatPanel({ threads, onBack, showBackButton }) {
|
|
|
127549
127688
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
127550
127689
|
className: "flex items-center gap-0.5 md:gap-1 shrink-0",
|
|
127551
127690
|
children: agent && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
127691
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CopyButton, {
|
|
127692
|
+
value: agent.id,
|
|
127693
|
+
label: "Copy agent ID",
|
|
127694
|
+
size: "icon-sm"
|
|
127695
|
+
}),
|
|
127552
127696
|
voiceTts.available && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
127553
127697
|
variant: "ghost",
|
|
127554
127698
|
size: "icon-sm",
|
|
127555
|
-
title: voiceTtsEnabled ? "Speaking agent responses aloud — click to mute" : "Speak agent responses aloud (active chat)",
|
|
127699
|
+
title: voiceTtsEnabled ? "Speaking agent responses aloud — click to mute (engine & voice in Settings)" : "Speak agent responses aloud (active chat) — engine & voice in Settings",
|
|
127556
127700
|
className: voiceTtsEnabled ? "text-primary" : "",
|
|
127557
127701
|
onClick: () => setVoiceTtsEnabled(!voiceTtsEnabled),
|
|
127558
127702
|
children: voiceTtsEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Volume2, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VolumeX, { className: "w-3.5 h-3.5" })
|
|
127559
127703
|
}),
|
|
127560
|
-
voiceTts.available && voiceTtsEnabled && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", {
|
|
127561
|
-
value: voiceTtsMode,
|
|
127562
|
-
onChange: (e) => setVoiceTtsMode(e.target.value),
|
|
127563
|
-
title: "Voice engine — Kokoro (server, natural) falls back to browser automatically",
|
|
127564
|
-
className: "h-7 rounded border border-border bg-background px-1 text-xs",
|
|
127565
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
127566
|
-
value: "kokoro",
|
|
127567
|
-
children: "Kokoro"
|
|
127568
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
127569
|
-
value: "browser",
|
|
127570
|
-
children: "Browser"
|
|
127571
|
-
})]
|
|
127572
|
-
}), voiceTtsMode === "kokoro" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", {
|
|
127573
|
-
value: voiceTtsKokoroVoice,
|
|
127574
|
-
onChange: (e) => setVoiceTtsKokoroVoice(e.target.value),
|
|
127575
|
-
title: "Kokoro voice",
|
|
127576
|
-
className: "h-7 rounded border border-border bg-background px-1 text-xs",
|
|
127577
|
-
children: [...KOKORO_VOICES, ...KOKORO_VOICES.some((v) => v.id === voiceTtsKokoroVoice) ? [] : [{
|
|
127578
|
-
id: voiceTtsKokoroVoice,
|
|
127579
|
-
label: voiceTtsKokoroVoice
|
|
127580
|
-
}]].map((v) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
127581
|
-
value: v.id,
|
|
127582
|
-
children: v.label
|
|
127583
|
-
}, v.id))
|
|
127584
|
-
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", {
|
|
127585
|
-
value: voiceTtsLang,
|
|
127586
|
-
onChange: (e) => setVoiceTtsLang(e.target.value),
|
|
127587
|
-
title: "Voice language",
|
|
127588
|
-
className: "h-7 rounded border border-border bg-background px-1 text-xs",
|
|
127589
|
-
children: [[...new Set([
|
|
127590
|
-
"en-US",
|
|
127591
|
-
...speechLangs,
|
|
127592
|
-
...voiceTtsLang ? [voiceTtsLang] : []
|
|
127593
|
-
])].sort().map((l) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
127594
|
-
value: l,
|
|
127595
|
-
children: l
|
|
127596
|
-
}, l)), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
127597
|
-
value: "",
|
|
127598
|
-
children: "Browser default"
|
|
127599
|
-
})]
|
|
127600
|
-
})] }),
|
|
127601
127704
|
canOpenTerminal && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
127602
127705
|
variant: "ghost",
|
|
127603
127706
|
size: "icon-sm",
|
|
@@ -128193,6 +128296,13 @@ function AgentCard({ agent }) {
|
|
|
128193
128296
|
className: "flex gap-1 mt-2.5 opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity",
|
|
128194
128297
|
onClick: (e) => e.stopPropagation(),
|
|
128195
128298
|
children: [
|
|
128299
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CopyButton, {
|
|
128300
|
+
value: agent.id,
|
|
128301
|
+
label: "Copy agent ID",
|
|
128302
|
+
size: "icon",
|
|
128303
|
+
className: "h-7 w-7",
|
|
128304
|
+
iconClassName: "w-3 h-3"
|
|
128305
|
+
}),
|
|
128196
128306
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
128197
128307
|
size: "icon",
|
|
128198
128308
|
variant: "ghost",
|
|
@@ -129392,9 +129502,6 @@ function WorkspaceActions({ workspace, expanded, onToggleDetails }) {
|
|
|
129392
129502
|
const gitState = useRelayStore((s) => s.workspaceGitState[workspace.id]);
|
|
129393
129503
|
const landed = !!gitState && gitState.available !== false && gitState.landed === true;
|
|
129394
129504
|
const mergeable = workspace.mode === "isolated" && Boolean(workspace.worktreePath) && MERGEABLE_STATUSES.has(workspace.status) && !landed;
|
|
129395
|
-
async function copyPath() {
|
|
129396
|
-
await navigator.clipboard?.writeText(openPath);
|
|
129397
|
-
}
|
|
129398
129505
|
async function merge() {
|
|
129399
129506
|
await fetchWorkspaceMergePreview(workspace.id);
|
|
129400
129507
|
await workspaceAction(workspace.id, "merge");
|
|
@@ -129417,13 +129524,13 @@ function WorkspaceActions({ workspace, expanded, onToggleDetails }) {
|
|
|
129417
129524
|
onClick: () => void openFilesAt({ path: openPath }),
|
|
129418
129525
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FolderOpen, { className: "h-3.5 w-3.5" })
|
|
129419
129526
|
}),
|
|
129420
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
129527
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CopyButton, {
|
|
129528
|
+
value: openPath,
|
|
129529
|
+
label: "Copy path",
|
|
129530
|
+
copiedLabel: "Copied path",
|
|
129421
129531
|
size: "icon-sm",
|
|
129422
129532
|
variant: "ghost",
|
|
129423
|
-
|
|
129424
|
-
disabled: !openPath,
|
|
129425
|
-
onClick: () => void copyPath(),
|
|
129426
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Copy, { className: "h-3.5 w-3.5" })
|
|
129533
|
+
disabled: !openPath
|
|
129427
129534
|
}),
|
|
129428
129535
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
|
|
129429
129536
|
size: "icon-sm",
|
|
@@ -130703,10 +130810,6 @@ function SecurityView() {
|
|
|
130703
130810
|
await api("POST", `/tokens/${encodeURIComponent(token.jti)}/revoke`);
|
|
130704
130811
|
await refresh();
|
|
130705
130812
|
}
|
|
130706
|
-
async function copy(value) {
|
|
130707
|
-
await navigator.clipboard?.writeText(value);
|
|
130708
|
-
setStatus("Copied");
|
|
130709
|
-
}
|
|
130710
130813
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
130711
130814
|
className: "space-y-4",
|
|
130712
130815
|
children: [
|
|
@@ -130936,11 +131039,12 @@ function SecurityView() {
|
|
|
130936
131039
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
130937
131040
|
className: "text-xs text-muted-foreground",
|
|
130938
131041
|
children: "New token"
|
|
130939
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
130940
|
-
|
|
131042
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CopyButton, {
|
|
131043
|
+
value: issuedToken,
|
|
131044
|
+
label: "Copy token",
|
|
130941
131045
|
size: "sm",
|
|
130942
|
-
|
|
130943
|
-
|
|
131046
|
+
variant: "ghost",
|
|
131047
|
+
onCopied: () => setStatus("Copied")
|
|
130944
131048
|
})]
|
|
130945
131049
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", {
|
|
130946
131050
|
className: "block max-h-24 overflow-auto break-all text-xs",
|
|
@@ -153632,8 +153736,11 @@ function MaintenanceView() {
|
|
|
153632
153736
|
})]
|
|
153633
153737
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollArea, {
|
|
153634
153738
|
className: "h-[calc(100dvh-10rem)]",
|
|
153635
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
153636
|
-
className: "
|
|
153739
|
+
children: jobs.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
153740
|
+
className: "rounded-md border border-border px-3 py-12 text-center text-sm text-muted-foreground",
|
|
153741
|
+
children: "No maintenance jobs registered"
|
|
153742
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
153743
|
+
className: "hidden overflow-x-auto rounded-md border border-border md:block",
|
|
153637
153744
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", {
|
|
153638
153745
|
className: "w-full min-w-[980px] text-sm",
|
|
153639
153746
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", {
|
|
@@ -153668,22 +153775,117 @@ function MaintenanceView() {
|
|
|
153668
153775
|
children: "Action"
|
|
153669
153776
|
})
|
|
153670
153777
|
] })
|
|
153671
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: jobs.
|
|
153672
|
-
colSpan: 7,
|
|
153673
|
-
className: "px-3 py-12 text-center text-sm text-muted-foreground",
|
|
153674
|
-
children: "No maintenance jobs registered"
|
|
153675
|
-
}) }) : jobs.map((job) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MaintenanceRow, {
|
|
153778
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: jobs.map((job) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MaintenanceRow, {
|
|
153676
153779
|
job,
|
|
153677
153780
|
now,
|
|
153678
153781
|
onRun: () => void runMaintenanceJob(job.id)
|
|
153679
153782
|
}, job.id)) })]
|
|
153680
153783
|
})
|
|
153681
|
-
})
|
|
153784
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
153785
|
+
className: "space-y-3 md:hidden",
|
|
153786
|
+
children: jobs.map((job) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MaintenanceCard, {
|
|
153787
|
+
job,
|
|
153788
|
+
now,
|
|
153789
|
+
onRun: () => void runMaintenanceJob(job.id)
|
|
153790
|
+
}, job.id))
|
|
153791
|
+
})] })
|
|
153682
153792
|
})]
|
|
153683
153793
|
});
|
|
153684
153794
|
}
|
|
153795
|
+
function jobStatus(job) {
|
|
153796
|
+
return job.running ? "running" : job.enabled ? job.lastStatus : "disabled";
|
|
153797
|
+
}
|
|
153798
|
+
function StatusBadge({ status }) {
|
|
153799
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Badge$1, {
|
|
153800
|
+
variant: "outline",
|
|
153801
|
+
className: cn$2("border", STATUS_CLASS[status] || STATUS_CLASS.idle),
|
|
153802
|
+
children: [statusIcon(status), status]
|
|
153803
|
+
});
|
|
153804
|
+
}
|
|
153805
|
+
function MaintenanceCard({ job, now, onRun }) {
|
|
153806
|
+
const status = jobStatus(job);
|
|
153807
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
153808
|
+
className: "rounded-md border border-border p-3",
|
|
153809
|
+
children: [
|
|
153810
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
153811
|
+
className: "flex items-start justify-between gap-2",
|
|
153812
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
153813
|
+
className: "min-w-0",
|
|
153814
|
+
children: [
|
|
153815
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
153816
|
+
className: "font-medium",
|
|
153817
|
+
children: job.title
|
|
153818
|
+
}),
|
|
153819
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
153820
|
+
className: "mt-0.5 text-xs text-muted-foreground",
|
|
153821
|
+
children: job.description
|
|
153822
|
+
}),
|
|
153823
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
153824
|
+
className: "mt-1 font-mono text-[11px] text-muted-foreground/80",
|
|
153825
|
+
children: job.id
|
|
153826
|
+
})
|
|
153827
|
+
]
|
|
153828
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusBadge, { status })]
|
|
153829
|
+
}),
|
|
153830
|
+
job.consecutiveFailures > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
153831
|
+
className: "mt-2 text-xs text-red-400",
|
|
153832
|
+
children: [
|
|
153833
|
+
job.consecutiveFailures,
|
|
153834
|
+
" failure",
|
|
153835
|
+
job.consecutiveFailures === 1 ? "" : "s"
|
|
153836
|
+
]
|
|
153837
|
+
}),
|
|
153838
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dl", {
|
|
153839
|
+
className: "mt-3 grid grid-cols-3 gap-2 text-xs",
|
|
153840
|
+
children: [
|
|
153841
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
|
|
153842
|
+
className: "text-muted-foreground",
|
|
153843
|
+
children: "Last run"
|
|
153844
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: job.lastRunAt ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
153845
|
+
title: fmtTime$1(job.lastRunAt),
|
|
153846
|
+
children: timeAgo(now, job.lastRunAt)
|
|
153847
|
+
}) : "never" })] }),
|
|
153848
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
|
|
153849
|
+
className: "text-muted-foreground",
|
|
153850
|
+
children: "Next run"
|
|
153851
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: job.nextRunAt ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
153852
|
+
title: fmtTime$1(job.nextRunAt),
|
|
153853
|
+
children: nextRunText(now, job.nextRunAt)
|
|
153854
|
+
}) : "-" })] }),
|
|
153855
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
|
|
153856
|
+
className: "text-muted-foreground",
|
|
153857
|
+
children: "Duration"
|
|
153858
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: job.lastDurationMs !== void 0 ? `${job.lastDurationMs}ms` : "-" })] })
|
|
153859
|
+
]
|
|
153860
|
+
}),
|
|
153861
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
153862
|
+
className: "mt-3",
|
|
153863
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
153864
|
+
className: "text-xs text-muted-foreground",
|
|
153865
|
+
children: "Result"
|
|
153866
|
+
}), job.lastError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
153867
|
+
className: "mt-0.5 text-xs text-red-400 line-clamp-3",
|
|
153868
|
+
children: job.lastError
|
|
153869
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
153870
|
+
className: "mt-0.5 font-mono text-[11px] text-muted-foreground line-clamp-3",
|
|
153871
|
+
children: resultSummary(job)
|
|
153872
|
+
})]
|
|
153873
|
+
}),
|
|
153874
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
153875
|
+
className: "mt-3 flex justify-end",
|
|
153876
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, {
|
|
153877
|
+
size: "sm",
|
|
153878
|
+
variant: "outline",
|
|
153879
|
+
disabled: !job.enabled || job.running,
|
|
153880
|
+
onClick: onRun,
|
|
153881
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Play, { className: "h-3.5 w-3.5" }), " Run"]
|
|
153882
|
+
})
|
|
153883
|
+
})
|
|
153884
|
+
]
|
|
153885
|
+
});
|
|
153886
|
+
}
|
|
153685
153887
|
function MaintenanceRow({ job, now, onRun }) {
|
|
153686
|
-
const status = job
|
|
153888
|
+
const status = jobStatus(job);
|
|
153687
153889
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", {
|
|
153688
153890
|
className: "border-t border-border align-top",
|
|
153689
153891
|
children: [
|
|
@@ -153706,11 +153908,7 @@ function MaintenanceRow({ job, now, onRun }) {
|
|
|
153706
153908
|
}),
|
|
153707
153909
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", {
|
|
153708
153910
|
className: "px-3 py-3",
|
|
153709
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
153710
|
-
variant: "outline",
|
|
153711
|
-
className: cn$2("border", STATUS_CLASS[status] || STATUS_CLASS.idle),
|
|
153712
|
-
children: [statusIcon(status), status]
|
|
153713
|
-
}), job.consecutiveFailures > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
153911
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusBadge, { status }), job.consecutiveFailures > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
153714
153912
|
className: "mt-1 text-xs text-red-400",
|
|
153715
153913
|
children: [
|
|
153716
153914
|
job.consecutiveFailures,
|
|
@@ -154096,30 +154294,101 @@ function WorkspaceSettings() {
|
|
|
154096
154294
|
});
|
|
154097
154295
|
}
|
|
154098
154296
|
function VoiceSettings() {
|
|
154297
|
+
const voiceTtsEnabled = useRelayStore((s) => s.voiceTtsEnabled);
|
|
154298
|
+
const setVoiceTtsEnabled = useRelayStore((s) => s.setVoiceTtsEnabled);
|
|
154299
|
+
const voiceTtsMode = useRelayStore((s) => s.voiceTtsMode);
|
|
154300
|
+
const setVoiceTtsMode = useRelayStore((s) => s.setVoiceTtsMode);
|
|
154301
|
+
const voiceTtsKokoroVoice = useRelayStore((s) => s.voiceTtsKokoroVoice);
|
|
154302
|
+
const setVoiceTtsKokoroVoice = useRelayStore((s) => s.setVoiceTtsKokoroVoice);
|
|
154303
|
+
const voiceTtsBrowserVoice = useRelayStore((s) => s.voiceTtsBrowserVoice);
|
|
154304
|
+
const setVoiceTtsBrowserVoice = useRelayStore((s) => s.setVoiceTtsBrowserVoice);
|
|
154099
154305
|
const voiceInputMode = useRelayStore((s) => s.voiceInputMode);
|
|
154100
154306
|
const setVoiceInputMode = useRelayStore((s) => s.setVoiceInputMode);
|
|
154307
|
+
const [browserVoices, setBrowserVoices] = (0, import_react.useState)(() => availableSpeechVoices());
|
|
154308
|
+
(0, import_react.useEffect)(() => {
|
|
154309
|
+
if (typeof window === "undefined" || !("speechSynthesis" in window)) return;
|
|
154310
|
+
const refresh = () => setBrowserVoices(availableSpeechVoices());
|
|
154311
|
+
refresh();
|
|
154312
|
+
window.speechSynthesis.addEventListener?.("voiceschanged", refresh);
|
|
154313
|
+
return () => window.speechSynthesis.removeEventListener?.("voiceschanged", refresh);
|
|
154314
|
+
}, []);
|
|
154315
|
+
const kokoroOptions = KOKORO_VOICES.some((v) => v.id === voiceTtsKokoroVoice) ? KOKORO_VOICES : [...KOKORO_VOICES, {
|
|
154316
|
+
id: voiceTtsKokoroVoice,
|
|
154317
|
+
label: voiceTtsKokoroVoice
|
|
154318
|
+
}];
|
|
154101
154319
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
|
|
154102
154320
|
className: "space-y-3 rounded-lg border p-4",
|
|
154103
|
-
children: [
|
|
154104
|
-
|
|
154105
|
-
|
|
154106
|
-
|
|
154107
|
-
|
|
154108
|
-
|
|
154109
|
-
|
|
154110
|
-
|
|
154111
|
-
|
|
154112
|
-
|
|
154113
|
-
|
|
154114
|
-
|
|
154115
|
-
|
|
154116
|
-
|
|
154117
|
-
|
|
154118
|
-
|
|
154119
|
-
|
|
154120
|
-
|
|
154321
|
+
children: [
|
|
154322
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
154323
|
+
className: "flex items-center justify-between gap-2",
|
|
154324
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
154325
|
+
className: "flex items-center gap-2",
|
|
154326
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Volume2, { className: "w-4 h-4" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", {
|
|
154327
|
+
className: "text-sm font-semibold",
|
|
154328
|
+
children: "Voice"
|
|
154329
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
154330
|
+
className: "text-xs text-muted-foreground",
|
|
154331
|
+
children: "Speak agent responses aloud in the active chat, and how push-to-talk behaves."
|
|
154332
|
+
})] })]
|
|
154333
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Switch, {
|
|
154334
|
+
checked: voiceTtsEnabled,
|
|
154335
|
+
onCheckedChange: setVoiceTtsEnabled
|
|
154336
|
+
})]
|
|
154337
|
+
}),
|
|
154338
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, {
|
|
154339
|
+
label: "Speech engine",
|
|
154340
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Select$1, {
|
|
154341
|
+
value: voiceTtsMode,
|
|
154342
|
+
onValueChange: (v) => setVoiceTtsMode(v),
|
|
154343
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectTrigger, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectValue, {}) }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectContent, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
|
|
154344
|
+
value: "kokoro",
|
|
154345
|
+
children: "Kokoro (server, natural — falls back to browser)"
|
|
154346
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
|
|
154347
|
+
value: "browser",
|
|
154348
|
+
children: "Browser (Web Speech API)"
|
|
154349
|
+
})] })]
|
|
154350
|
+
})
|
|
154351
|
+
}),
|
|
154352
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, {
|
|
154353
|
+
label: "Kokoro voice",
|
|
154354
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Select$1, {
|
|
154355
|
+
value: voiceTtsKokoroVoice,
|
|
154356
|
+
onValueChange: setVoiceTtsKokoroVoice,
|
|
154357
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectTrigger, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectValue, {}) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectContent, { children: kokoroOptions.map((v) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
|
|
154358
|
+
value: v.id,
|
|
154359
|
+
children: v.label
|
|
154360
|
+
}, v.id)) })]
|
|
154361
|
+
})
|
|
154362
|
+
}),
|
|
154363
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, {
|
|
154364
|
+
label: "Browser voice",
|
|
154365
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Select$1, {
|
|
154366
|
+
value: voiceTtsBrowserVoice || "__default__",
|
|
154367
|
+
onValueChange: (v) => setVoiceTtsBrowserVoice(v === "__default__" ? "" : v),
|
|
154368
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectTrigger, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectValue, {}) }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectContent, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
|
|
154369
|
+
value: "__default__",
|
|
154370
|
+
children: "System default"
|
|
154371
|
+
}), browserVoices.map((v) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
|
|
154372
|
+
value: v.uri,
|
|
154373
|
+
children: v.label
|
|
154374
|
+
}, v.uri))] })]
|
|
154375
|
+
})
|
|
154376
|
+
}),
|
|
154377
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, {
|
|
154378
|
+
label: "Push-to-talk input",
|
|
154379
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Select$1, {
|
|
154380
|
+
value: voiceInputMode,
|
|
154381
|
+
onValueChange: (v) => setVoiceInputMode(v),
|
|
154382
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectTrigger, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectValue, {}) }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectContent, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
|
|
154383
|
+
value: "compose",
|
|
154384
|
+
children: "Fill the message box (review, then Enter)"
|
|
154385
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
|
|
154386
|
+
value: "autosend",
|
|
154387
|
+
children: "Send immediately (speak-and-send)"
|
|
154388
|
+
})] })]
|
|
154389
|
+
})
|
|
154121
154390
|
})
|
|
154122
|
-
|
|
154391
|
+
]
|
|
154123
154392
|
});
|
|
154124
154393
|
}
|
|
154125
154394
|
var EFFORTS = [
|
|
@@ -154392,7 +154661,6 @@ function AgentDiagnostics({ agent, orchestrators }) {
|
|
|
154392
154661
|
const now = useNow();
|
|
154393
154662
|
const [policyHealth, setPolicyHealth] = (0, import_react.useState)(null);
|
|
154394
154663
|
const [agentEvents, setAgentEvents] = (0, import_react.useState)([]);
|
|
154395
|
-
const [copied, setCopied] = (0, import_react.useState)(false);
|
|
154396
154664
|
const [expandedSections, setExpandedSections] = (0, import_react.useState)({
|
|
154397
154665
|
spawn: true,
|
|
154398
154666
|
workspace: true,
|
|
@@ -154436,7 +154704,7 @@ function AgentDiagnostics({ agent, orchestrators }) {
|
|
|
154436
154704
|
[key]: !s[key]
|
|
154437
154705
|
}));
|
|
154438
154706
|
}
|
|
154439
|
-
|
|
154707
|
+
function buildDiagnosticBundle() {
|
|
154440
154708
|
const policy = policyHealth?.policy;
|
|
154441
154709
|
const state = policyHealth?.state;
|
|
154442
154710
|
const lines = [
|
|
@@ -154513,11 +154781,7 @@ function AgentDiagnostics({ agent, orchestrators }) {
|
|
|
154513
154781
|
}
|
|
154514
154782
|
const contracts = agent.meta?.contracts;
|
|
154515
154783
|
if (contracts) for (const [k, v] of Object.entries(contracts)) lines.push(`Contract ${k}: ${v}`);
|
|
154516
|
-
|
|
154517
|
-
await navigator.clipboard.writeText(lines.join("\n"));
|
|
154518
|
-
setCopied(true);
|
|
154519
|
-
setTimeout(() => setCopied(false), 2e3);
|
|
154520
|
-
} catch {}
|
|
154784
|
+
return lines.join("\n");
|
|
154521
154785
|
}
|
|
154522
154786
|
const policy = policyHealth?.policy;
|
|
154523
154787
|
const state = policyHealth?.state;
|
|
@@ -154529,12 +154793,14 @@ function AgentDiagnostics({ agent, orchestrators }) {
|
|
|
154529
154793
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h3", {
|
|
154530
154794
|
className: "text-sm font-medium flex items-center gap-1.5",
|
|
154531
154795
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Stethoscope, { className: "w-3.5 h-3.5 text-muted-foreground" }), "Diagnostics"]
|
|
154532
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.
|
|
154796
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CopyButton, {
|
|
154797
|
+
value: buildDiagnosticBundle,
|
|
154798
|
+
label: "Copy Bundle",
|
|
154799
|
+
showText: true,
|
|
154533
154800
|
size: "sm",
|
|
154534
154801
|
variant: "outline",
|
|
154535
154802
|
className: "h-7 text-xs gap-1",
|
|
154536
|
-
|
|
154537
|
-
children: [copied ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Check, { className: "w-3 h-3" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Copy, { className: "w-3 h-3" }), copied ? "Copied" : "Copy Bundle"]
|
|
154803
|
+
iconClassName: "w-3 h-3"
|
|
154538
154804
|
})]
|
|
154539
154805
|
}),
|
|
154540
154806
|
policy && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CollapsibleSection, {
|
|
@@ -155727,13 +155993,21 @@ function AgentDetailDrawer() {
|
|
|
155727
155993
|
className: "space-y-1 text-sm",
|
|
155728
155994
|
children: [
|
|
155729
155995
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
155730
|
-
className: "flex justify-between gap-2 min-w-0",
|
|
155996
|
+
className: "flex items-center justify-between gap-2 min-w-0",
|
|
155731
155997
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
155732
155998
|
className: "text-muted-foreground shrink-0",
|
|
155733
155999
|
children: "ID"
|
|
155734
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.
|
|
155735
|
-
className: "
|
|
155736
|
-
children:
|
|
156000
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
156001
|
+
className: "flex min-w-0 items-center gap-1",
|
|
156002
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
156003
|
+
className: "font-mono text-xs truncate",
|
|
156004
|
+
children: agent.id
|
|
156005
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CopyButton, {
|
|
156006
|
+
value: agent.id,
|
|
156007
|
+
label: "Copy agent ID",
|
|
156008
|
+
size: "icon-xs",
|
|
156009
|
+
className: "shrink-0 text-muted-foreground"
|
|
156010
|
+
})]
|
|
155737
156011
|
})]
|
|
155738
156012
|
}),
|
|
155739
156013
|
runtimePackage && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
@@ -157317,11 +157591,6 @@ function OrchestratorInstallModal() {
|
|
|
157317
157591
|
setLoading(false);
|
|
157318
157592
|
}
|
|
157319
157593
|
}
|
|
157320
|
-
async function copy() {
|
|
157321
|
-
if (!command) return;
|
|
157322
|
-
await navigator.clipboard.writeText(command);
|
|
157323
|
-
showNotification("Install command copied");
|
|
157324
|
-
}
|
|
157325
157594
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Dialog, {
|
|
157326
157595
|
open,
|
|
157327
157596
|
onOpenChange: (o) => !o && set({ orchestratorInstallOpen: false }),
|
|
@@ -157390,11 +157659,14 @@ function OrchestratorInstallModal() {
|
|
|
157390
157659
|
onClick: () => set({ orchestratorInstallOpen: false }),
|
|
157391
157660
|
children: "Close"
|
|
157392
157661
|
}),
|
|
157393
|
-
command && /* @__PURE__ */ (0, import_jsx_runtime.
|
|
157662
|
+
command && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CopyButton, {
|
|
157663
|
+
value: command,
|
|
157664
|
+
label: "Copy",
|
|
157665
|
+
showText: true,
|
|
157666
|
+
size: "default",
|
|
157394
157667
|
variant: "outline",
|
|
157395
157668
|
className: "gap-1",
|
|
157396
|
-
|
|
157397
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Copy, { className: "w-3.5 h-3.5" }), "Copy"]
|
|
157669
|
+
onCopied: () => showNotification("Install command copied")
|
|
157398
157670
|
}),
|
|
157399
157671
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button, {
|
|
157400
157672
|
className: "gap-1",
|
|
@@ -159322,6 +159594,10 @@ if ("serviceWorker" in navigator) {
|
|
|
159322
159594
|
display: inline-flex;
|
|
159323
159595
|
}
|
|
159324
159596
|
|
|
159597
|
+
.table {
|
|
159598
|
+
display: table;
|
|
159599
|
+
}
|
|
159600
|
+
|
|
159325
159601
|
.field-sizing-content {
|
|
159326
159602
|
field-sizing: content;
|
|
159327
159603
|
}
|
|
@@ -159794,6 +160070,10 @@ if ("serviceWorker" in navigator) {
|
|
|
159794
160070
|
min-width: calc(var(--spacing) * 0);
|
|
159795
160071
|
}
|
|
159796
160072
|
|
|
160073
|
+
.min-w-4 {
|
|
160074
|
+
min-width: calc(var(--spacing) * 4);
|
|
160075
|
+
}
|
|
160076
|
+
|
|
159797
160077
|
.min-w-5 {
|
|
159798
160078
|
min-width: calc(var(--spacing) * 5);
|
|
159799
160079
|
}
|
|
@@ -160848,6 +161128,16 @@ if ("serviceWorker" in navigator) {
|
|
|
160848
161128
|
}
|
|
160849
161129
|
}
|
|
160850
161130
|
|
|
161131
|
+
.bg-background\/95 {
|
|
161132
|
+
background-color: var(--background);
|
|
161133
|
+
}
|
|
161134
|
+
|
|
161135
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
161136
|
+
.bg-background\/95 {
|
|
161137
|
+
background-color: color-mix(in oklab, var(--background) 95%, transparent);
|
|
161138
|
+
}
|
|
161139
|
+
}
|
|
161140
|
+
|
|
160851
161141
|
.bg-black\/0 {
|
|
160852
161142
|
background-color: #0000;
|
|
160853
161143
|
}
|
|
@@ -161718,10 +162008,6 @@ if ("serviceWorker" in navigator) {
|
|
|
161718
162008
|
font-size: .8rem;
|
|
161719
162009
|
}
|
|
161720
162010
|
|
|
161721
|
-
.text-\[8px\] {
|
|
161722
|
-
font-size: 8px;
|
|
161723
|
-
}
|
|
161724
|
-
|
|
161725
162011
|
.text-\[9px\] {
|
|
161726
162012
|
font-size: 9px;
|
|
161727
162013
|
}
|
|
@@ -163336,6 +163622,10 @@ if ("serviceWorker" in navigator) {
|
|
|
163336
163622
|
}
|
|
163337
163623
|
|
|
163338
163624
|
@media (min-width: 40rem) {
|
|
163625
|
+
.sm\:block {
|
|
163626
|
+
display: block;
|
|
163627
|
+
}
|
|
163628
|
+
|
|
163339
163629
|
.sm\:flex {
|
|
163340
163630
|
display: flex;
|
|
163341
163631
|
}
|