agent-relay-server 0.99.1 → 0.100.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.
Files changed (89) hide show
  1. package/docs/openapi.json +1 -1
  2. package/package.json +5 -2
  3. package/public/assets/{MessageBubble-DiorZXyB.js → MessageBubble-DZ3cUoHO.js} +2 -2
  4. package/public/assets/{MessageBubble-DiorZXyB.js.map → MessageBubble-DZ3cUoHO.js.map} +1 -1
  5. package/public/assets/{PlanGraphPanel-DY1p8v4p.js → PlanGraphPanel-B6G_RSZ3.js} +2 -2
  6. package/public/assets/{PlanGraphPanel-DY1p8v4p.js.map → PlanGraphPanel-B6G_RSZ3.js.map} +1 -1
  7. package/public/assets/{activity-rIxqUtFC.js → activity-BefDMYiE.js} +2 -2
  8. package/public/assets/{activity-rIxqUtFC.js.map → activity-BefDMYiE.js.map} +1 -1
  9. package/public/assets/{agent-profiles-Cu-VkJm4.js → agent-profiles-D5VW943m.js} +2 -2
  10. package/public/assets/agent-profiles-D5VW943m.js.map +1 -0
  11. package/public/assets/agents-CtsNY05B.js +2 -0
  12. package/public/assets/agents-CtsNY05B.js.map +1 -0
  13. package/public/assets/{automation-B0cyCT5l.js → automation-B5TFhCGs.js} +2 -2
  14. package/public/assets/{automation-B0cyCT5l.js.map → automation-B5TFhCGs.js.map} +1 -1
  15. package/public/assets/branch-state-badge-BLF9LPtu.js +2 -0
  16. package/public/assets/branch-state-badge-BLF9LPtu.js.map +1 -0
  17. package/public/assets/chat-CoZcF6dA.js +2 -0
  18. package/public/assets/chat-CoZcF6dA.js.map +1 -0
  19. package/public/assets/{formatted-body-impl-ZwgTH3jh.js → formatted-body-impl-Zk5WjWS7.js} +2 -2
  20. package/public/assets/{formatted-body-impl-ZwgTH3jh.js.map → formatted-body-impl-Zk5WjWS7.js.map} +1 -1
  21. package/public/assets/{index-GoC6YrKn.js → index-B4cTW4A9.js} +5 -5
  22. package/public/assets/index-B4cTW4A9.js.map +1 -0
  23. package/public/assets/{insights-C3mlXZdd.js → insights-C8iC-IB1.js} +2 -2
  24. package/public/assets/{insights-C3mlXZdd.js.map → insights-C8iC-IB1.js.map} +1 -1
  25. package/public/assets/{maintenance-DL1lnqmG.js → maintenance-pl6U2a_y.js} +2 -2
  26. package/public/assets/{maintenance-DL1lnqmG.js.map → maintenance-pl6U2a_y.js.map} +1 -1
  27. package/public/assets/{managed-agents-7A6WH4Rn.js → managed-agents-1CynkXEy.js} +2 -2
  28. package/public/assets/{managed-agents-7A6WH4Rn.js.map → managed-agents-1CynkXEy.js.map} +1 -1
  29. package/public/assets/{markdown-preview-impl-THat8xv0.js → markdown-preview-impl-Dj6MExTR.js} +2 -2
  30. package/public/assets/{markdown-preview-impl-THat8xv0.js.map → markdown-preview-impl-Dj6MExTR.js.map} +1 -1
  31. package/public/assets/{memory-C349UJe9.js → memory-DyWT5mwx.js} +2 -2
  32. package/public/assets/{memory-C349UJe9.js.map → memory-DyWT5mwx.js.map} +1 -1
  33. package/public/assets/{messages-DXoLFj2P.js → messages-LqXFX2yc.js} +2 -2
  34. package/public/assets/{messages-DXoLFj2P.js.map → messages-LqXFX2yc.js.map} +1 -1
  35. package/public/assets/{orchestrators-CTXu4jAn.js → orchestrators-xdpBJOt1.js} +2 -2
  36. package/public/assets/{orchestrators-CTXu4jAn.js.map → orchestrators-xdpBJOt1.js.map} +1 -1
  37. package/public/assets/{overview-dWiN6TyN.js → overview-BDetOVf7.js} +2 -2
  38. package/public/assets/{overview-dWiN6TyN.js.map → overview-BDetOVf7.js.map} +1 -1
  39. package/public/assets/{pairs-KIXektDv.js → pairs-BxVd-YVM.js} +2 -2
  40. package/public/assets/{pairs-KIXektDv.js.map → pairs-BxVd-YVM.js.map} +1 -1
  41. package/public/assets/{registry-C-Y41yGB.js → registry-BeoPmyhz.js} +2 -2
  42. package/public/assets/{registry-C-Y41yGB.js.map → registry-BeoPmyhz.js.map} +1 -1
  43. package/public/assets/{security-BUymkwuj.js → security-DKDgxf96.js} +2 -2
  44. package/public/assets/{security-BUymkwuj.js.map → security-DKDgxf96.js.map} +1 -1
  45. package/public/assets/{select-DV25WRP5.js → select-DpRN9C_1.js} +2 -2
  46. package/public/assets/{select-DV25WRP5.js.map → select-DpRN9C_1.js.map} +1 -1
  47. package/public/assets/{settings-C1En58bx.js → settings-D_mLzA5O.js} +2 -2
  48. package/public/assets/{settings-C1En58bx.js.map → settings-D_mLzA5O.js.map} +1 -1
  49. package/public/assets/{tasks-BkpnKA63.js → tasks-D5OVfd-K.js} +2 -2
  50. package/public/assets/{tasks-BkpnKA63.js.map → tasks-D5OVfd-K.js.map} +1 -1
  51. package/public/assets/{teams-D-UYp7yH.js → teams-CFJM0XlG.js} +2 -2
  52. package/public/assets/{teams-D-UYp7yH.js.map → teams-CFJM0XlG.js.map} +1 -1
  53. package/public/assets/{terminal-viewer-impl-Bif-tkvD.js → terminal-viewer-impl-B-2tqoEB.js} +2 -2
  54. package/public/assets/{terminal-viewer-impl-Bif-tkvD.js.map → terminal-viewer-impl-B-2tqoEB.js.map} +1 -1
  55. package/public/assets/{user-avatar--czLv_AJ.js → user-avatar-BGXTBaME.js} +2 -2
  56. package/public/assets/{user-avatar--czLv_AJ.js.map → user-avatar-BGXTBaME.js.map} +1 -1
  57. package/public/assets/{work-queue-DN4oTe7w.js → work-queue-DMwtDbBg.js} +2 -2
  58. package/public/assets/{work-queue-DN4oTe7w.js.map → work-queue-DMwtDbBg.js.map} +1 -1
  59. package/public/index.html +1 -1
  60. package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
  61. package/runner/plugins/claude/hooks/kill-guard.sh +300 -0
  62. package/runner/plugins/claude/hooks/read-only-bash-guard.sh +38 -140
  63. package/runner/src/adapter.ts +2 -2
  64. package/src/agent-death-diagnosis.ts +12 -3
  65. package/src/bus.ts +6 -45
  66. package/src/config-store.ts +13 -9
  67. package/src/db/provider-quota-burn.ts +2 -1
  68. package/src/issue-tracker/adapter.ts +11 -1
  69. package/src/issue-tracker/github.ts +83 -2
  70. package/src/issue-tracker/index.ts +1 -0
  71. package/src/lifecycle-manager.ts +9 -22
  72. package/src/provider-state.ts +9 -18
  73. package/src/provider-timeline-event.ts +70 -0
  74. package/src/quota-advisory.ts +4 -7
  75. package/src/routes/agent-sessions.ts +4 -2
  76. package/src/services/issue-lifecycle.ts +54 -8
  77. package/src/services/provider-state-audit.ts +3 -3
  78. package/src/services/rate-limit-resume.ts +6 -4
  79. package/src/services/register-agent.ts +2 -1
  80. package/src/spawn-targets.ts +1 -0
  81. package/src/sse.ts +5 -4
  82. package/public/assets/agent-profiles-Cu-VkJm4.js.map +0 -1
  83. package/public/assets/agents-dRHOBDUe.js +0 -2
  84. package/public/assets/agents-dRHOBDUe.js.map +0 -1
  85. package/public/assets/branch-state-badge-CNko2_BL.js +0 -2
  86. package/public/assets/branch-state-badge-CNko2_BL.js.map +0 -1
  87. package/public/assets/chat-jit-e6S_.js +0 -2
  88. package/public/assets/chat-jit-e6S_.js.map +0 -1
  89. package/public/assets/index-GoC6YrKn.js.map +0 -1
@@ -15,7 +15,7 @@ import { defaultIssueRepo } from "../config";
15
15
  // existing importers and tests keep their entry point.
16
16
  import { parseOwnerRepoFromRemote, repoFromGitRemote, __resetRemoteRepoCacheForTests } from "./git-remote";
17
17
  export { parseOwnerRepoFromRemote, repoFromGitRemote, __resetRemoteRepoCacheForTests };
18
- import type { IssueTrackerAdapter } from "../issue-tracker";
18
+ import type { IssueTrackerAdapter, IssueTrackerIssueSummary } from "../issue-tracker";
19
19
  import { recordAndEmitIssueActivity } from "./issue-activity";
20
20
  import type { IssueAssociationEntityType, IssueProvider, IssueRef, WorkspaceRecord } from "../types";
21
21
 
@@ -208,14 +208,41 @@ function closeAuditComment(input: LandedIssueLifecycleInput): string {
208
208
  return `Closed by \`${commit}\` on merge to \`main\` - reopen if release surfaces more work.`;
209
209
  }
210
210
 
211
- function issueLabel(ref: IssueRef, parent: IssueRef): string {
211
+ function issueLabel(ref: Pick<IssueRef, "repo" | "externalKey">, parent: IssueRef): string {
212
212
  return ref.repo === parent.repo ? `#${ref.externalKey}` : `${ref.repo}#${ref.externalKey}`;
213
213
  }
214
214
 
215
- function backlinkProgressComment(input: LandedIssueLifecycleInput, parent: IssueRef, openSubIssues: IssueRef[]): string {
215
+ function openSubIssuesComment(input: LandedIssueLifecycleInput, parent: IssueRef, openSubIssues: IssueTrackerIssueSummary[]): string {
216
216
  const commit = input.mergedSha ? input.mergedSha.slice(0, 12) : input.workspace.branch ?? input.workspace.id;
217
217
  const childList = openSubIssues.map((ref) => issueLabel(ref, parent)).join(", ");
218
- return `Linked landed slice \`${commit}\` to this parent issue, but Agent Relay left it open because these sub-issues are still open: ${childList}.`;
218
+ return `Referenced by landed commit \`${commit}\`; left open because these sub-issues are still open: ${childList}.`;
219
+ }
220
+
221
+ function issueSummaryKey(ref: Pick<IssueTrackerIssueSummary, "provider" | "repo" | "externalKey">): string {
222
+ return `${ref.provider}:${ref.repo}#${ref.externalKey}`;
223
+ }
224
+
225
+ async function listOpenSubIssuesForLand(issueRef: IssueRef, opts: IssueLifecycleOptions): Promise<IssueTrackerIssueSummary[]> {
226
+ const open = new Map<string, IssueTrackerIssueSummary>();
227
+ const adapter = adapterFor(issueRef, opts);
228
+ if (adapter.listOpenSubIssues) {
229
+ for (const ref of await adapter.listOpenSubIssues(issueRef)) {
230
+ if (ref.status === "open") open.set(issueSummaryKey(ref), ref);
231
+ }
232
+ }
233
+ for (const item of listIssuesForEntity("epic", issueRef.id)) {
234
+ const ref = item.issueRef;
235
+ if (ref.status !== "open") continue;
236
+ open.set(issueSummaryKey(ref), {
237
+ provider: ref.provider,
238
+ repo: ref.repo,
239
+ externalKey: ref.externalKey,
240
+ url: ref.url,
241
+ title: ref.title,
242
+ status: "open",
243
+ });
244
+ }
245
+ return [...open.values()];
219
246
  }
220
247
 
221
248
  async function reconcileClosedIssueRefBeforeSkip(issueRef: IssueRef, opts: IssueLifecycleOptions): Promise<{
@@ -250,11 +277,30 @@ async function closeIssueRefForLand(
250
277
  if (reconciled.liveStatus !== "open") return { issueRef: latest, action: "skipped", reason: "already-closed", landKey: key };
251
278
  }
252
279
 
253
- const openSubIssues = source === "backlink"
254
- ? listIssuesForEntity("epic", latest.id).map((item) => item.issueRef).filter((ref) => ref.status === "open")
255
- : [];
280
+ let openSubIssues: IssueTrackerIssueSummary[];
281
+ try {
282
+ openSubIssues = await listOpenSubIssuesForLand(latest, opts);
283
+ } catch (error) {
284
+ const message = `sub-issue lookup failed: ${errMessage(error)}`;
285
+ upsertIssueLifecycleAction({
286
+ issueRefId: latest.id,
287
+ action: "close",
288
+ landKey: key,
289
+ workspaceId: input.workspace.id,
290
+ branch: input.workspace.branch,
291
+ baseRef: input.workspace.baseRef ?? "main",
292
+ commitSha: input.mergedSha,
293
+ commitSubject: input.subject,
294
+ agentId: input.workspace.ownerAgentId,
295
+ source,
296
+ status: "failed",
297
+ error: message,
298
+ });
299
+ logFailure(opts, `issue lifecycle sub-issue lookup failed for ${latest.id} on ${key}: ${errMessage(error)}`);
300
+ return { issueRef: latest, action: "failed", error: message, landKey: key };
301
+ }
256
302
  if (openSubIssues.length > 0) {
257
- const comment = backlinkProgressComment(input, latest, openSubIssues);
303
+ const comment = openSubIssuesComment(input, latest, openSubIssues);
258
304
  try {
259
305
  await adapterFor(latest, opts).comment(latest, comment);
260
306
  } catch (error) {
@@ -1,6 +1,6 @@
1
1
  import { createActivityEvent } from "../db";
2
2
  import { routeNotification } from "../notification-router";
3
- import { agentProviderState } from "../provider-state";
3
+ import { agentProviderState, type ProviderState } from "../provider-state";
4
4
  import type { AgentCard } from "../types";
5
5
 
6
6
  export function auditProviderStateTransition(agentId: string, before: AgentCard | null | undefined, after: AgentCard | null | undefined): void {
@@ -46,7 +46,7 @@ export function auditProviderStateTransition(agentId: string, before: AgentCard
46
46
  }
47
47
  }
48
48
 
49
- function providerStateKey(state: Record<string, unknown> | null): string | null {
49
+ function providerStateKey(state: ProviderState | null): string | null {
50
50
  if (!state) return null;
51
- return [state.state, typeof state.reason === "string" ? state.reason : ""].join(":");
51
+ return [state.state, state.reason ?? ""].join(":");
52
52
  }
@@ -6,6 +6,7 @@ import {
6
6
  agentProviderState,
7
7
  isRateLimitHold,
8
8
  isTransientRateLimitHold,
9
+ type ProviderState,
9
10
  rateLimitResumeAt,
10
11
  transientRateLimitAttempt,
11
12
  transientRateLimitExhausted,
@@ -46,7 +47,7 @@ export function resetRateLimitResumeTrackerForTests(): void {
46
47
  const RESUME_BODY =
47
48
  "Your provider limit/overload hold is ready to retry — resuming. Continue the task you were working on when the provider interrupted you. If you had already finished, no action is needed.";
48
49
 
49
- function nextTransientState(state: Record<string, unknown>, now: number, attempts: number): Record<string, unknown> {
50
+ function nextTransientState(state: ProviderState, now: number, attempts: number): ProviderState {
50
51
  const nextAttempts = attempts + 1;
51
52
  const nextDelay = TRANSIENT_RATE_LIMIT_BACKOFF_MS[nextAttempts];
52
53
  return {
@@ -58,7 +59,7 @@ function nextTransientState(state: Record<string, unknown>, now: number, attempt
58
59
  };
59
60
  }
60
61
 
61
- function notifyTransientExhausted(agent: { id: string; label?: string | null; spawnedBy?: string | null }, state: Record<string, unknown>, now: number): void {
62
+ function notifyTransientExhausted(agent: { id: string; label?: string | null; spawnedBy?: string | null }, state: ProviderState, now: number): void {
62
63
  mergeAgentMeta(agent.id, { providerState: { ...state, exhaustedAt: now, updatedAt: now } });
63
64
  if (!agent.spawnedBy) return;
64
65
  routeNotification({
@@ -88,6 +89,7 @@ export function resumeRateLimitedAgents(): Record<string, unknown> {
88
89
  seen.add(agent.id);
89
90
 
90
91
  const state = agentProviderState(agent);
92
+ if (!state) continue;
91
93
  const resumeAt = rateLimitResumeAt(state);
92
94
  if (resumeAt !== null && now < resumeAt) { waiting.push(agent.id); continue; }
93
95
 
@@ -96,7 +98,7 @@ export function resumeRateLimitedAgents(): Record<string, unknown> {
96
98
  const attempts = transient ? Math.max(transientRateLimitAttempt(state), tracked.attempts ?? 0) : 0;
97
99
  if (transient && (attempts >= TRANSIENT_RATE_LIMIT_BACKOFF_MS.length || transientRateLimitExhausted(state))) {
98
100
  if (!tracked.exhaustedNotified) {
99
- notifyTransientExhausted(agent, state as Record<string, unknown>, now);
101
+ notifyTransientExhausted(agent, state, now);
100
102
  resumeTracker.set(agent.id, { ...tracked, attempts, exhaustedNotified: true });
101
103
  }
102
104
  waiting.push(agent.id);
@@ -133,7 +135,7 @@ export function resumeRateLimitedAgents(): Record<string, unknown> {
133
135
  continue;
134
136
  }
135
137
 
136
- if (transient) mergeAgentMeta(agent.id, { providerState: nextTransientState(state as Record<string, unknown>, now, attempts) });
138
+ if (transient) mergeAgentMeta(agent.id, { providerState: nextTransientState(state, now, attempts) });
137
139
 
138
140
  // #416 — flush messages queued while the agent was rate-limited.
139
141
  flushQueuedDirectMessages(agent.id);
@@ -13,6 +13,7 @@ import { isReservedAgentId } from "agent-relay-sdk";
13
13
  import { ValidationError, createActivityEvent, getAgent, seedSpawnPromptMirror, seedSpawnReplyObligation, upsertAgent } from "../db";
14
14
  import { emitAgentStatus, emitNewMessage } from "../sse";
15
15
  import { noteAgentTimelineEvent } from "../compaction-watch";
16
+ import { agentProviderTimelineEvent } from "../provider-timeline-event";
16
17
  import { notifyAgentReady } from "../agent-lifecycle-events";
17
18
  import { resolveSpawnLineage, resolveTeamLineage } from "../security";
18
19
  import { flushQueuedDirectMessages, markManagedAgentRunning } from "./managed-running";
@@ -65,7 +66,7 @@ export function registerAgent(input: RegisterAgentInput, ctx: AuthContext): Agen
65
66
  // PreCompact/SessionStart hook arrives as a latched meta.timelineEvent — clears any
66
67
  // pending stall watch; the timestamp guard inside ignores stale latched events.
67
68
  emitAgentStatus(agent.id);
68
- noteAgentTimelineEvent(agent.id, agent.meta?.timelineEvent);
69
+ noteAgentTimelineEvent(agent.id, agentProviderTimelineEvent(agent));
69
70
 
70
71
  // #308/#351 — a spawned child registering already-ready (the common isolated-worktree
71
72
  // case) wakes its block-polling parent. Fire on the first-ever ready, regardless of
@@ -306,6 +306,7 @@ function spawnProfilesSummary(): Array<Record<string, unknown>> {
306
306
  return listAgentProfiles().map(({ key, value }) => ({
307
307
  name: value.name ?? key,
308
308
  description: value.description,
309
+ ...(value.icon ? { icon: value.icon } : {}),
309
310
  provider: value.provider,
310
311
  approvalMode: value.permissions?.mode,
311
312
  ...(value.maxSpawnedAgents !== undefined ? { maxSpawnedAgents: value.maxSpawnedAgents } : {}),
package/src/sse.ts CHANGED
@@ -4,6 +4,7 @@ import { emitRelayEvent, subscribeRelayEvents, type RelayEvent } from "./events"
4
4
  import { messageMatchesAgent, targetMatchesAgent } from "./agent-ref";
5
5
  import type { ActivityEvent, AgentCard, Message, RelayInjectionCategory, RelayNotification, Task } from "./types";
6
6
  import { isRecord } from "agent-relay-sdk";
7
+ import { agentProviderState } from "./provider-state";
7
8
 
8
9
  interface Connection {
9
10
  id: string;
@@ -333,11 +334,11 @@ function notificationForDelivery(msg: Message): RelayNotification | undefined {
333
334
  }
334
335
 
335
336
  function notificationForAgentStatus(agent: AgentCard): RelayNotification | undefined {
336
- const providerState = isRecord(agent.meta?.providerState) ? agent.meta.providerState : undefined;
337
- const state = typeof providerState?.state === "string" ? providerState.state : "";
337
+ const providerState = agentProviderState(agent);
338
+ const state = providerState?.state ?? "";
338
339
  if (!state || (state !== "error" && !state.includes("blocked") && !state.includes("waiting"))) return undefined;
339
- const label = typeof providerState?.label === "string" && providerState.label ? providerState.label : state;
340
- const reason = typeof providerState?.reason === "string" ? providerState.reason : label;
340
+ const label = providerState?.label || state;
341
+ const reason = providerState?.reason ?? label;
341
342
  return {
342
343
  id: `agent:${agent.id}:${state}`,
343
344
  kind: "agent.blocked",
@@ -1 +0,0 @@
1
- {"version":3,"file":"agent-profiles-Cu-VkJm4.js","names":[],"sources":["../../dashboard/src/components/views/agent-profile-resolved-dialog.tsx","../../dashboard/src/components/views/agent-profiles.tsx"],"sourcesContent":["import { useCallback, useEffect, useState } from 'react'\nimport { errMessage } from 'agent-relay-sdk/types'\nimport { Download, Loader2 } from 'lucide-react'\nimport { useRelayStore } from '@/store'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/dialog'\nimport { Button } from '@/components/ui/button'\nimport type { AgentProfile } from '@/types'\n\ntype ResolveProvider = 'claude' | 'codex'\n\ninterface ResolvedResponse {\n provider: ResolveProvider\n profile: AgentProfile\n}\n\ninterface AgentProfileResolvedDialogProps {\n profile: AgentProfile\n open: boolean\n onOpenChange: (open: boolean) => void\n}\n\nfunction defaultProvider(profile: AgentProfile): ResolveProvider {\n return profile.provider === 'claude' || profile.provider === 'codex' ? profile.provider : 'codex'\n}\n\n// Deep-clone the projection, replacing every `provisioning.*.files[].content` blob with a\n// `<N chars elided>` marker so the inline view stays legible without dumping plugin/skill\n// source. The full content remains available via the JSON download.\nfunction elideFileContents(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(elideFileContents)\n if (value && typeof value === 'object') {\n const out: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(value as Record<string, unknown>)) {\n if (key === 'files' && Array.isArray(val)) {\n out[key] = val.map((file) => {\n if (file && typeof file === 'object' && typeof (file as Record<string, unknown>).content === 'string') {\n const content = (file as Record<string, unknown>).content as string\n return { ...(file as Record<string, unknown>), content: `<${content.length} chars elided>` }\n }\n return elideFileContents(file)\n })\n } else {\n out[key] = elideFileContents(val)\n }\n }\n return out\n }\n return value\n}\n\nexport function AgentProfileResolvedDialog({ profile, open, onOpenChange }: AgentProfileResolvedDialogProps) {\n const apiCall = useRelayStore((s) => s.apiCall)\n const [provider, setProvider] = useState<ResolveProvider>(() => defaultProvider(profile))\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [resolved, setResolved] = useState<AgentProfile | null>(null)\n\n const load = useCallback(async (p: ResolveProvider) => {\n setLoading(true)\n setError(null)\n try {\n const result = await apiCall<ResolvedResponse>('GET', `/agent-profiles/${encodeURIComponent(profile.name)}/resolved?provider=${p}`)\n setResolved(result.profile)\n } catch (e) {\n setResolved(null)\n setError(errMessage(e))\n } finally {\n setLoading(false)\n }\n }, [apiCall, profile.name])\n\n useEffect(() => {\n if (open) {\n const p = defaultProvider(profile)\n setProvider(p)\n void load(p)\n }\n }, [open, profile, load])\n\n function selectProvider(p: ResolveProvider) {\n if (p === provider) return\n setProvider(p)\n void load(p)\n }\n\n function downloadFullJson() {\n if (!resolved) return\n const blob = new Blob([JSON.stringify(resolved, null, 2)], { type: 'application/json' })\n const url = URL.createObjectURL(blob)\n const link = document.createElement('a')\n link.href = url\n link.download = `${profile.name}.${provider}.resolved.json`\n document.body.appendChild(link)\n link.click()\n link.remove()\n URL.revokeObjectURL(url)\n }\n\n const elided = resolved ? JSON.stringify(elideFileContents(resolved), null, 2) : ''\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"max-w-3xl\">\n <DialogHeader>\n <DialogTitle className=\"font-mono text-sm\">{profile.name} — resolved projection</DialogTitle>\n <DialogDescription>\n The fully-resolved agent-profile projection (<code>withResolvedProvisioning</code>) for the selected provider.\n File contents are elided below; download the full JSON for the complete bundle.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-xs text-muted-foreground\">Provider</span>\n <div className=\"flex items-center gap-1\">\n {(['claude', 'codex'] as ResolveProvider[]).map((p) => (\n <Button\n key={p}\n variant={p === provider ? 'default' : 'outline'}\n size=\"sm\"\n className=\"h-7 px-3 text-xs\"\n disabled={loading}\n onClick={() => selectProvider(p)}\n >\n {p}\n </Button>\n ))}\n </div>\n <div className=\"flex-1\" />\n <Button size=\"sm\" className=\"h-7 gap-1 text-xs\" disabled={loading || !resolved} onClick={downloadFullJson}>\n <Download className=\"h-3.5 w-3.5\" />\n Download full JSON\n </Button>\n </div>\n\n <div className=\"min-h-[16rem] overflow-auto rounded-md border border-border bg-muted/30 p-3\">\n {loading ? (\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n Resolving projection…\n </div>\n ) : error ? (\n <div className=\"text-xs text-destructive\">{error}</div>\n ) : resolved ? (\n <pre className=\"max-h-[60vh] overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed\">{elided}</pre>\n ) : (\n <div className=\"text-xs text-muted-foreground\">No projection available.</div>\n )}\n </div>\n\n <DialogFooter>\n <Button variant=\"outline\" size=\"sm\" onClick={() => onOpenChange(false)}>Close</Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n","import { useState } from 'react'\nimport { useRelayStore } from '@/store'\nimport { Button } from '@/components/ui/button'\nimport { Badge } from '@/components/ui/badge'\nimport { Copy, Eye, FileJson, Pencil, Plus, Trash2, UserCog } from 'lucide-react'\nimport type { AgentProfile } from '@/types'\nimport { AgentProfileResolvedDialog } from './agent-profile-resolved-dialog'\n\nconst BASE_COLORS: Record<string, string> = {\n host: 'text-emerald-400 bg-emerald-500/10',\n minimal: 'text-amber-400 bg-amber-500/10',\n isolated: 'text-red-400 bg-red-500/10',\n vanilla: 'text-fuchsia-400 bg-fuchsia-500/10',\n}\n\nfunction RelayDots({ relay }: { relay: AgentProfile['relay'] }) {\n const items = [\n { key: 'ctx', on: relay.context },\n { key: 'skl', on: relay.skills },\n { key: 'plg', on: relay.plugins },\n { key: 'stl', on: relay.statusLine },\n ]\n return (\n <div className=\"flex items-center gap-1\">\n {items.map((item) => (\n <span key={item.key} className={`inline-block h-1.5 w-1.5 rounded-full ${item.on ? 'bg-emerald-400' : 'bg-muted-foreground/30'}`} title={`${item.key}: ${item.on ? 'on' : 'off'}`} />\n ))}\n </div>\n )\n}\n\nfunction ProfileCard({ profile }: { profile: AgentProfile }) {\n const openProfileModal = useRelayStore((s) => s.openProfileModal)\n const deleteProfile = useRelayStore((s) => s.deleteProfile)\n const isBuiltIn = profile.builtIn === true\n const [resolvedOpen, setResolvedOpen] = useState(false)\n\n return (\n <div className=\"group flex flex-col gap-3 rounded-lg border border-border bg-card p-4\">\n <div className=\"flex items-start gap-2\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-mono text-sm font-medium\">{profile.name}</span>\n {isBuiltIn && <Badge variant=\"secondary\" className=\"text-[10px]\">Built-in</Badge>}\n {profile.overridden && <Badge variant=\"outline\" className=\"text-[10px] border-amber-500/30 bg-amber-500/10 text-amber-400\">Overridden</Badge>}\n </div>\n {profile.description && (\n <p className=\"mt-0.5 text-xs text-muted-foreground line-clamp-2\">{profile.description}</p>\n )}\n </div>\n <div className=\"flex shrink-0 items-center gap-0.5 opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity\">\n <Button variant=\"ghost\" size=\"icon-sm\" className=\"h-7 w-7\" title=\"View\" onClick={() => openProfileModal('view', profile)}>\n <Eye className=\"h-3.5 w-3.5\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" className=\"h-7 w-7\" title=\"Edit\" onClick={() => openProfileModal('edit', profile)}>\n <Pencil className=\"h-3.5 w-3.5\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" className=\"h-7 w-7\" title=\"Duplicate\" onClick={() => openProfileModal('duplicate', profile)}>\n <Copy className=\"h-3.5 w-3.5\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" className=\"h-7 w-7\" title=\"Resolved projection\" onClick={() => setResolvedOpen(true)}>\n <FileJson className=\"h-3.5 w-3.5\" />\n </Button>\n {(!isBuiltIn || profile.overridden) && (\n <Button variant=\"ghost\" size=\"icon-sm\" className=\"h-7 w-7 text-destructive\" title={isBuiltIn ? 'Reset to default' : 'Delete'} onClick={() => deleteProfile(profile)}>\n <Trash2 className=\"h-3.5 w-3.5\" />\n </Button>\n )}\n </div>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-1.5 text-[10px]\">\n <Badge variant=\"outline\" className={BASE_COLORS[profile.base] || ''}>{profile.base}</Badge>\n <Badge variant=\"outline\">{profile.provider || 'any'}</Badge>\n <Badge variant=\"outline\">fs: {profile.permissions.filesystem}</Badge>\n {profile.permissions.mode && <Badge variant=\"outline\">{profile.permissions.mode}</Badge>}\n </div>\n\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-1 text-[10px] text-muted-foreground\">\n <span className=\"flex items-center gap-1\">\n Relay <RelayDots relay={profile.relay} />\n </span>\n <span>MCP: {profile.mcp.mode}</span>\n <span>Hooks: {profile.hooks.mode}</span>\n {profile.instructions.globalInstructions === 'ignore' && <span className=\"text-amber-400\">global: ignore</span>}\n {Object.keys(profile.env || {}).length > 0 && <span>{Object.keys(profile.env).length} env vars</span>}\n </div>\n\n <AgentProfileResolvedDialog profile={profile} open={resolvedOpen} onOpenChange={setResolvedOpen} />\n </div>\n )\n}\n\nexport function AgentProfilesView() {\n const profiles = useRelayStore((s) => s.agentProfiles)\n const openProfileModal = useRelayStore((s) => s.openProfileModal)\n\n const builtIn = profiles.filter((p) => p.builtIn)\n const custom = profiles.filter((p) => !p.builtIn)\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <div className=\"flex items-center gap-2 text-lg font-semibold\">\n <UserCog className=\"h-5 w-5 text-primary\" />\n Agent Profiles\n </div>\n <Badge variant=\"outline\">{profiles.length}</Badge>\n <div className=\"flex-1\" />\n <Button size=\"sm\" className=\"gap-1\" onClick={() => openProfileModal('create')}>\n <Plus className=\"h-3.5 w-3.5\" />\n Create Profile\n </Button>\n </div>\n\n {builtIn.length > 0 && (\n <div>\n <h3 className=\"mb-2 text-xs font-medium text-muted-foreground uppercase tracking-wider\">Built-in</h3>\n <div className=\"grid gap-3 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3\">\n {builtIn.map((p) => <ProfileCard key={p.name} profile={p} />)}\n </div>\n </div>\n )}\n\n {custom.length > 0 && (\n <div>\n <h3 className=\"mb-2 text-xs font-medium text-muted-foreground uppercase tracking-wider\">Custom</h3>\n <div className=\"grid gap-3 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3\">\n {custom.map((p) => <ProfileCard key={p.name} profile={p} />)}\n </div>\n </div>\n )}\n\n {profiles.length === 0 && (\n <div className=\"py-12 text-center text-sm text-muted-foreground\">\n No agent profiles found. Create one to configure agent behavior.\n </div>\n )}\n </div>\n )\n}\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{B as t,G as n,Kn as r,Q as i,Qn as a,R as o,Vn as s,Xn as c,Yt as l,dr as u,g as d,h as f,i as p,l as m,mt as h,tt as g,zt as _}from"./lucide-react-BYZuAhQs.js";import{l as ee,t as v}from"./store-pKbf_WYd.js";import{J as y,K as b,W as te,Y as x,a as S,d as C,i as ne,n as re}from"./display-DRiGi1zj.js";import{o as w,r as T}from"./dist-BnbGIUmi.js";import{t as E}from"./dist-CQF3Jiqg.js";import{i as D,n as O}from"./dist-DAl28ejX.js";import{t as k}from"./dist-DDUGmmoi.js";import{t as A}from"./dist-B5VvlkhI.js";import{a as j,i as M,n as N,o as P,r as F,s as I,t as L}from"./es2015-B8Z9p8oQ.js";import{a as R,i as ie,n as ae,r as oe,t as z}from"./dist-DZ97OosY.js";import{t as B}from"./badge-BLar6FjP.js";import{t as V}from"./button-BrIB69qd.js";import{t as se}from"./copy-button-Cd-LbSbg.js";import{B as ce,D as H,J as U,K as le,O as W,S as ue,Y as G,b as de,f as K,g as fe,m as pe,p as me,q as he,x as ge,y as _e}from"./index-GoC6YrKn.js";import{r as ve,t as ye}from"./card-lhnFnBoz.js";import{n as be,t as xe}from"./branch-state-badge-CNko2_BL.js";var q=e(u(),1),J=a(),Y=`Popover`,[Se,Ce]=D(Y,[R]),X=R(),[we,Z]=Se(Y),Te=e=>{let{__scopePopover:t,children:n,open:r,defaultOpen:i,onOpenChange:a,modal:o=!1}=e,s=X(t),c=q.useRef(null),[l,u]=q.useState(!1),[d,f]=k({prop:r,defaultProp:i??!1,onChange:a,caller:Y});return(0,J.jsx)(ie,{...s,children:(0,J.jsx)(we,{scope:t,contentId:I(),triggerRef:c,open:d,onOpenChange:f,onOpenToggle:q.useCallback(()=>f(e=>!e),[f]),hasCustomAnchor:l,onCustomAnchorAdd:q.useCallback(()=>u(!0),[]),onCustomAnchorRemove:q.useCallback(()=>u(!1),[]),modal:o,children:n})})};Te.displayName=Y;var Ee=`PopoverAnchor`,De=q.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=Z(Ee,n),a=X(n),{onCustomAnchorAdd:o,onCustomAnchorRemove:s}=i;return q.useEffect(()=>(o(),()=>s()),[o,s]),(0,J.jsx)(z,{...a,...r,ref:t})});De.displayName=Ee;var Oe=`PopoverTrigger`,ke=q.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=Z(Oe,n),a=X(n),o=w(t,i.triggerRef),s=(0,J.jsx)(E.button,{type:`button`,"aria-haspopup":`dialog`,"aria-expanded":i.open,"aria-controls":i.contentId,"data-state":He(i.open),...r,ref:o,onClick:O(e.onClick,i.onOpenToggle)});return i.hasCustomAnchor?s:(0,J.jsx)(z,{asChild:!0,...a,children:s})});ke.displayName=Oe;var Q=`PopoverPortal`,[Ae,je]=Se(Q,{forceMount:void 0}),Me=e=>{let{__scopePopover:t,forceMount:n,children:r,container:i}=e,a=Z(Q,t);return(0,J.jsx)(Ae,{scope:t,forceMount:n,children:(0,J.jsx)(A,{present:n||a.open,children:(0,J.jsx)(M,{asChild:!0,container:i,children:r})})})};Me.displayName=Q;var $=`PopoverContent`,Ne=q.forwardRef((e,t)=>{let n=je($,e.__scopePopover),{forceMount:r=n.forceMount,...i}=e,a=Z($,e.__scopePopover);return(0,J.jsx)(A,{present:r||a.open,children:a.modal?(0,J.jsx)(Fe,{...i,ref:t}):(0,J.jsx)(Ie,{...i,ref:t})})});Ne.displayName=$;var Pe=T(`PopoverContent.RemoveScroll`),Fe=q.forwardRef((e,t)=>{let n=Z($,e.__scopePopover),r=q.useRef(null),i=w(t,r),a=q.useRef(!1);return q.useEffect(()=>{let e=r.current;if(e)return L(e)},[]),(0,J.jsx)(N,{as:Pe,allowPinchZoom:!0,children:(0,J.jsx)(Le,{...e,ref:i,trapFocus:n.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:O(e.onCloseAutoFocus,e=>{e.preventDefault(),a.current||n.triggerRef.current?.focus()}),onPointerDownOutside:O(e.onPointerDownOutside,e=>{let t=e.detail.originalEvent,n=t.button===0&&t.ctrlKey===!0;a.current=t.button===2||n},{checkForDefaultPrevented:!1}),onFocusOutside:O(e.onFocusOutside,e=>e.preventDefault(),{checkForDefaultPrevented:!1})})})}),Ie=q.forwardRef((e,t)=>{let n=Z($,e.__scopePopover),r=q.useRef(!1),i=q.useRef(!1);return(0,J.jsx)(Le,{...e,ref:t,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:t=>{e.onCloseAutoFocus?.(t),t.defaultPrevented||(r.current||n.triggerRef.current?.focus(),t.preventDefault()),r.current=!1,i.current=!1},onInteractOutside:t=>{e.onInteractOutside?.(t),t.defaultPrevented||(r.current=!0,t.detail.originalEvent.type===`pointerdown`&&(i.current=!0));let a=t.target;n.triggerRef.current?.contains(a)&&t.preventDefault(),t.detail.originalEvent.type===`focusin`&&i.current&&t.preventDefault()}})}),Le=q.forwardRef((e,t)=>{let{__scopePopover:n,trapFocus:r,onOpenAutoFocus:i,onCloseAutoFocus:a,disableOutsidePointerEvents:o,onEscapeKeyDown:s,onPointerDownOutside:c,onFocusOutside:l,onInteractOutside:u,...d}=e,f=Z($,n),p=X(n);return F(),(0,J.jsx)(j,{asChild:!0,loop:!0,trapped:r,onMountAutoFocus:i,onUnmountAutoFocus:a,children:(0,J.jsx)(P,{asChild:!0,disableOutsidePointerEvents:o,onInteractOutside:u,onEscapeKeyDown:s,onPointerDownOutside:c,onFocusOutside:l,onDismiss:()=>f.onOpenChange(!1),children:(0,J.jsx)(oe,{"data-state":He(f.open),role:`dialog`,id:f.contentId,...p,...d,ref:t,style:{...d.style,"--radix-popover-content-transform-origin":`var(--radix-popper-transform-origin)`,"--radix-popover-content-available-width":`var(--radix-popper-available-width)`,"--radix-popover-content-available-height":`var(--radix-popper-available-height)`,"--radix-popover-trigger-width":`var(--radix-popper-anchor-width)`,"--radix-popover-trigger-height":`var(--radix-popper-anchor-height)`}})})})}),Re=`PopoverClose`,ze=q.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=Z(Re,n);return(0,J.jsx)(E.button,{type:`button`,...r,ref:t,onClick:O(e.onClick,()=>i.onOpenChange(!1))})});ze.displayName=Re;var Be=`PopoverArrow`,Ve=q.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=X(n);return(0,J.jsx)(ae,{...i,...r,ref:t})});Ve.displayName=Be;function He(e){return e?`open`:`closed`}var Ue=Te,We=ke,Ge=Me,Ke=Ne;function qe({...e}){return(0,J.jsx)(Ue,{"data-slot":`popover`,...e})}function Je({...e}){return(0,J.jsx)(We,{"data-slot":`popover-trigger`,...e})}function Ye({className:e,align:t=`center`,sideOffset:n=4,...r}){return(0,J.jsx)(Ge,{children:(0,J.jsx)(Ke,{"data-slot":`popover-content`,align:t,sideOffset:n,className:c(`z-50 flex w-72 origin-(--radix-popover-content-transform-origin) flex-col gap-2.5 rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95`,e),...r})})}function Xe({className:e,...t}){return(0,J.jsx)(`div`,{"data-slot":`popover-header`,className:c(`flex flex-col gap-0.5 text-sm`,e),...t})}function Ze({className:e,...t}){return(0,J.jsx)(`div`,{"data-slot":`popover-title`,className:c(`font-medium`,e),...t})}function Qe({agent:e,childAgents:t=[],parentAgent:r}){let a=ee();v(e=>e.set);let s=v(e=>e.switchView),c=v(e=>e.openInboxThread),u=v(e=>e.openAgentDetail),p=v(e=>e.openPairInvite),w=v(e=>e.openRename),T=v(e=>e.openConfirm),E=v(e=>e.doAgentAction),D=v(e=>e.doDeleteAgent),O=v(e=>e.openFilesForAgent),k=v(e=>e.workspaceAction),A=v(e=>e.openWorkspaceFocus),{terminalOpen:j,terminalTarget:M,terminalOpening:N,openTerminal:P,closeTerminal:F}=be(e.id),I=le(),L=ne(a,e,ce(e),I[e.id]||null),R=S(e,`shutdown`),ie=S(e,`compact`),ae=S(e,`clearContext`),oe=!!(e.providerCapabilities?.terminal?.live?.read||e.providerCapabilities?.terminal?.attach?.create),z=!!(e.providerCapabilities?.terminal?.live?.write||e.providerCapabilities?.model?.provider===`claude`),U=re(e),G=r?C(r):e.spawnedBy,K=t.length>0;return(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(ye,{className:`group hover:border-zinc-600 transition-colors cursor-pointer`,onClick:()=>u(e),children:(0,J.jsxs)(ve,{className:`p-4`,children:[(0,J.jsxs)(`div`,{className:`flex items-start gap-2.5 mb-2.5`,children:[(0,J.jsx)(W,{agent:e,now:a,className:`mt-0.5`}),(0,J.jsx)(H,{agent:e}),(0,J.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,J.jsx)(`div`,{className:`text-sm font-medium truncate`,children:C(e)}),(0,J.jsx)(`div`,{className:`text-xs mt-0.5 ${y(L.tone)}`,children:L.label}),typeof e.meta?.cwd==`string`&&e.meta.cwd&&(0,J.jsx)(`button`,{type:`button`,className:`mt-0.5 block max-w-full truncate font-mono text-[10px] text-muted-foreground hover:text-foreground`,title:`Open ${e.meta.cwd} in Files`,onClick:t=>{t.stopPropagation(),O(e)},children:te(e.meta.cwd)}),(0,J.jsx)(fe,{agent:e,className:`mt-1`})]}),e.branchState&&e.branchWorkspaceId&&(0,J.jsx)(xe,{state:e.branchState,className:`mt-0.5 shrink-0`,onClick:t=>{t.stopPropagation(),A(e.branchWorkspaceId)}})]}),L.badges.length>0&&(0,J.jsx)(`div`,{className:`flex flex-wrap gap-1 mb-2`,children:L.badges.map(e=>(0,J.jsx)(`span`,{className:`text-[10px] px-1.5 py-0.5 rounded-full font-medium ${e.className}`,children:e.label},e.label))}),(K||e.spawnedBy&&G)&&(0,J.jsxs)(`div`,{className:`mb-2 flex flex-wrap gap-1.5`,onClick:e=>e.stopPropagation(),children:[K&&(0,J.jsxs)(qe,{children:[(0,J.jsx)(Je,{asChild:!0,children:(0,J.jsxs)(`button`,{type:`button`,className:`inline-flex h-6 max-w-full items-center gap-1.5 rounded-full border border-sky-500/30 bg-sky-500/10 px-2 text-[10px] font-medium text-sky-300 transition-colors hover:bg-sky-500/15`,title:`${t.length} live child ${t.length===1?`agent`:`agents`}`,children:[(0,J.jsx)(m,{className:`h-3 w-3`}),(0,J.jsx)(`span`,{children:t.length}),(0,J.jsx)(`span`,{className:`flex -space-x-1`,children:t.slice(0,4).map(e=>(0,J.jsx)(W,{agent:e,now:a,className:`h-2 w-2 ring-1 ring-background`},e.id))})]})}),(0,J.jsxs)(Ye,{align:`start`,className:`w-80`,onClick:e=>e.stopPropagation(),children:[(0,J.jsx)(Xe,{children:(0,J.jsx)(Ze,{children:`Team`})}),(0,J.jsx)(`div`,{className:`space-y-1.5`,children:t.map(e=>(0,J.jsxs)(`div`,{className:`rounded-md border border-border bg-card/60 p-2`,children:[(0,J.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,J.jsx)(W,{agent:e,now:a,className:`mt-1`}),(0,J.jsx)(H,{agent:e}),(0,J.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,J.jsx)(`div`,{className:`truncate text-xs font-medium`,children:C(e)}),(0,J.jsx)(`div`,{className:`truncate text-[10px] text-muted-foreground`,children:e.providerCapabilities?.model?.alias||e.providerCapabilities?.model?.id||e.providerCapabilities?.model?.provider||e.status})]}),(0,J.jsx)(B,{variant:`outline`,className:`h-4 px-1.5 text-[9px]`,children:e.status})]}),(0,J.jsxs)(`div`,{className:`mt-2 flex gap-1`,children:[(0,J.jsx)(V,{size:`xs`,variant:`outline`,onClick:()=>u(e),children:`Open`}),(0,J.jsxs)(V,{size:`xs`,variant:`ghost`,onClick:()=>{c(e.id),s(`chat`)},children:[(0,J.jsx)(g,{className:`h-3 w-3`}),`Chat`]})]})]},e.id))})]})]}),e.spawnedBy&&G&&(0,J.jsx)(B,{variant:`outline`,className:`max-w-full text-[10px] text-muted-foreground`,children:(0,J.jsxs)(`span`,{className:`truncate`,children:[`spawned by `,G]})})]}),(e.tags.length>0||x(e.capabilities).length>0)&&(0,J.jsxs)(`div`,{className:`flex flex-wrap gap-1 mb-2`,children:[e.tags.slice(0,3).map(e=>(0,J.jsx)(B,{variant:`outline`,className:`text-[9px] px-1 py-0 h-4`,children:e},e)),x(e.capabilities).slice(0,2).map(e=>(0,J.jsx)(B,{variant:`secondary`,className:`text-[9px] px-1 py-0 h-4`,children:e},e))]}),(0,J.jsxs)(`div`,{className:`space-y-2 mb-2`,children:[(0,J.jsx)(ge,{agent:e}),(0,J.jsx)(de,{agent:e,compact:!0}),(0,J.jsx)(ue,{agent:e})]}),(0,J.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:e.id!==`user`&&e.id!==`system`&&b(a,e.lastSeen)}),(0,J.jsxs)(`div`,{className:`flex gap-1 mt-2.5 opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity`,onClick:e=>e.stopPropagation(),children:[(0,J.jsx)(se,{value:e.id,label:`Copy agent ID`,size:`icon`,className:`h-7 w-7`,iconClassName:`w-3 h-3`}),(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Chat`,onClick:()=>{c(e.id),s(`chat`)},children:(0,J.jsx)(g,{className:`w-3 h-3`})}),(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Pair`,onClick:()=>p(e.id),children:(0,J.jsx)(h,{className:`w-3 h-3`})}),(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Rename`,onClick:()=>w(e),children:(0,J.jsx)(n,{className:`w-3 h-3`})}),oe&&(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Terminal`,disabled:N,onClick:()=>void P(),children:(0,J.jsx)(d,{className:`w-3 h-3`})}),(e.branchState===`changes`||e.branchState===`idle`)&&e.branchWorkspaceId&&(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7 text-amber-400 hover:text-amber-300`,title:`Mark workspace ready — hand off to the auto-merge`,onClick:()=>T(`Mark Workspace Ready`,`Mark ${C(e)}'s branch ready to land? The relay auto-merge will rebase and land it.`,()=>k(e.branchWorkspaceId,`ready`)),children:(0,J.jsx)(_,{className:`w-3 h-3`})}),ie&&(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Compact`,onClick:()=>T(`Compact Agent`,`Compact context for ${C(e)}?`,()=>E(e,`compact`,`agents-grid`)),children:(0,J.jsx)(i,{className:`w-3 h-3`})}),ae&&(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Clear Context`,onClick:()=>T(`Clear Context`,`Clear context for ${C(e)}?`,()=>E(e,`clearContext`,`agents-grid`)),children:(0,J.jsx)(l,{className:`w-3 h-3`})}),R&&(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7 text-red-400 hover:text-red-300`,title:`Shutdown`,onClick:()=>T(`Shutdown Agent`,`Shutdown ${C(e)}?`,()=>E(e,`shutdown`,`agents-grid`)),children:(0,J.jsx)(o,{className:`w-3 h-3`})}),U&&(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7 text-red-400 hover:text-red-300`,title:`Forget stale agent`,onClick:()=>T(`Forget Agent`,`Forget ${C(e)}?`,()=>D(e.id)),children:(0,J.jsx)(f,{className:`w-3 h-3`})})]})]})}),M&&(0,J.jsx)(_e,{open:j,onOpenChange:F,orchestratorId:M.orchestratorId,session:M.session,interactive:M.interactive||z})]})}function $e(){let e=v(e=>e.agentPresetFilter),n=v(e=>e.agentStatusFilter),i=v(e=>e.agentTagFilter),a=v(e=>e.agentHostFilter),o=v(e=>e.agentSort),c=v(e=>e.agentSortDir),l=v(e=>e.showOffline),u=v(e=>e.set),d=v(e=>e.openAgentSpawn),f=v(e=>e.agentsById),m=ee(),h=he(),g=G(),_=U(),y=K(h,m),b=pe(h,m),te=e||n||i||a;function x(){u({agentPresetFilter:``,agentStatusFilter:``,agentTagFilter:``,agentHostFilter:``})}function S(){u({agentSortDir:c===`asc`?`desc`:`asc`})}return(0,J.jsxs)(`div`,{className:`space-y-4`,children:[(0,J.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,J.jsxs)(`select`,{value:e,onChange:e=>u({agentPresetFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,J.jsx)(`option`,{value:``,children:`All agents`}),(0,J.jsx)(`option`,{value:`active`,children:`Active`}),(0,J.jsx)(`option`,{value:`claude`,children:`Claude`}),(0,J.jsx)(`option`,{value:`codex`,children:`Codex`}),(0,J.jsx)(`option`,{value:`paired`,children:`Paired`}),(0,J.jsx)(`option`,{value:`unpaired`,children:`Unpaired`}),(0,J.jsx)(`option`,{value:`offline_stale`,children:`Offline / Stale`})]}),(0,J.jsxs)(`select`,{value:n,onChange:e=>u({agentStatusFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,J.jsx)(`option`,{value:``,children:`Any status`}),(0,J.jsx)(`option`,{value:`online`,children:`Online`}),(0,J.jsx)(`option`,{value:`idle`,children:`Idle`}),(0,J.jsx)(`option`,{value:`busy`,children:`Busy`}),(0,J.jsx)(`option`,{value:`offline`,children:`Offline`}),(0,J.jsx)(`option`,{value:`starting`,children:`Starting`})]}),g.length>0&&(0,J.jsxs)(`select`,{value:i,onChange:e=>u({agentTagFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,J.jsx)(`option`,{value:``,children:`Any tag`}),g.map(e=>(0,J.jsx)(`option`,{value:e,children:e},e))]}),_.length>1&&(0,J.jsxs)(`select`,{value:a,onChange:e=>u({agentHostFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,J.jsx)(`option`,{value:``,children:`Any host`}),_.map(e=>(0,J.jsx)(`option`,{value:e,children:e},e))]}),(0,J.jsxs)(`select`,{value:o,onChange:e=>u({agentSort:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,J.jsx)(`option`,{value:`status`,children:`Sort: Status`}),(0,J.jsx)(`option`,{value:`name`,children:`Sort: Name`}),(0,J.jsx)(`option`,{value:`lastSeen`,children:`Sort: Last seen`}),(0,J.jsx)(`option`,{value:`created`,children:`Sort: Created`})]}),(0,J.jsx)(V,{size:`icon`,variant:`outline`,className:`h-8 w-8`,title:`Toggle sort direction`,onClick:S,children:c===`asc`?(0,J.jsx)(s,{className:`w-3.5 h-3.5`}):(0,J.jsx)(r,{className:`w-3.5 h-3.5`})}),(0,J.jsxs)(`label`,{className:`flex items-center gap-1.5 text-sm text-muted-foreground cursor-pointer select-none`,children:[(0,J.jsx)(`input`,{type:`checkbox`,checked:l,onChange:e=>u({showOffline:e.target.checked}),className:`rounded`}),`Show offline`]}),te&&(0,J.jsxs)(V,{size:`sm`,variant:`ghost`,className:`h-8 text-muted-foreground hover:text-foreground gap-1`,onClick:x,children:[(0,J.jsx)(p,{className:`w-3 h-3`}),`Clear filters`]}),(0,J.jsx)(`div`,{className:`ml-auto`,children:(0,J.jsxs)(V,{size:`sm`,onClick:d,className:`gap-1`,children:[(0,J.jsx)(t,{className:`w-3.5 h-3.5`}),`Spawn`]})})]}),b.length===0?(0,J.jsx)(`div`,{className:`text-center py-16 text-muted-foreground text-sm`,children:`No agents match the current filters.`}):(0,J.jsx)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 gap-3`,children:b.map(e=>(0,J.jsx)(Qe,{agent:e,parentAgent:e.spawnedBy?f[e.spawnedBy]??null:null,childAgents:me(y.get(e.id)??[])},e.id))})]})}export{$e as AgentsView};
2
- //# sourceMappingURL=agents-dRHOBDUe.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"agents-dRHOBDUe.js","names":["Popover","PopperPrimitive.Root","PopperPrimitive.Anchor","PopoverTrigger","PortalPrimitive","PopoverContent","RemoveScroll","PopperPrimitive.Content","PopperPrimitive.Arrow"],"sources":["../../dashboard/node_modules/@radix-ui/react-popover/dist/index.mjs","../../dashboard/src/components/ui/popover.tsx","../../dashboard/src/components/views/agents.tsx"],"sourcesContent":["\"use client\";\n\n// src/popover.tsx\nimport * as React from \"react\";\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport { createContextScope } from \"@radix-ui/react-context\";\nimport { DismissableLayer } from \"@radix-ui/react-dismissable-layer\";\nimport { useFocusGuards } from \"@radix-ui/react-focus-guards\";\nimport { FocusScope } from \"@radix-ui/react-focus-scope\";\nimport { useId } from \"@radix-ui/react-id\";\nimport * as PopperPrimitive from \"@radix-ui/react-popper\";\nimport { createPopperScope } from \"@radix-ui/react-popper\";\nimport { Portal as PortalPrimitive } from \"@radix-ui/react-portal\";\nimport { Presence } from \"@radix-ui/react-presence\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { createSlot } from \"@radix-ui/react-slot\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { hideOthers } from \"aria-hidden\";\nimport { RemoveScroll } from \"react-remove-scroll\";\nimport { jsx } from \"react/jsx-runtime\";\nvar POPOVER_NAME = \"Popover\";\nvar [createPopoverContext, createPopoverScope] = createContextScope(POPOVER_NAME, [\n createPopperScope\n]);\nvar usePopperScope = createPopperScope();\nvar [PopoverProvider, usePopoverContext] = createPopoverContext(POPOVER_NAME);\nvar Popover = (props) => {\n const {\n __scopePopover,\n children,\n open: openProp,\n defaultOpen,\n onOpenChange,\n modal = false\n } = props;\n const popperScope = usePopperScope(__scopePopover);\n const triggerRef = React.useRef(null);\n const [hasCustomAnchor, setHasCustomAnchor] = React.useState(false);\n const [open, setOpen] = useControllableState({\n prop: openProp,\n defaultProp: defaultOpen ?? false,\n onChange: onOpenChange,\n caller: POPOVER_NAME\n });\n return /* @__PURE__ */ jsx(PopperPrimitive.Root, { ...popperScope, children: /* @__PURE__ */ jsx(\n PopoverProvider,\n {\n scope: __scopePopover,\n contentId: useId(),\n triggerRef,\n open,\n onOpenChange: setOpen,\n onOpenToggle: React.useCallback(() => setOpen((prevOpen) => !prevOpen), [setOpen]),\n hasCustomAnchor,\n onCustomAnchorAdd: React.useCallback(() => setHasCustomAnchor(true), []),\n onCustomAnchorRemove: React.useCallback(() => setHasCustomAnchor(false), []),\n modal,\n children\n }\n ) });\n};\nPopover.displayName = POPOVER_NAME;\nvar ANCHOR_NAME = \"PopoverAnchor\";\nvar PopoverAnchor = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopePopover, ...anchorProps } = props;\n const context = usePopoverContext(ANCHOR_NAME, __scopePopover);\n const popperScope = usePopperScope(__scopePopover);\n const { onCustomAnchorAdd, onCustomAnchorRemove } = context;\n React.useEffect(() => {\n onCustomAnchorAdd();\n return () => onCustomAnchorRemove();\n }, [onCustomAnchorAdd, onCustomAnchorRemove]);\n return /* @__PURE__ */ jsx(PopperPrimitive.Anchor, { ...popperScope, ...anchorProps, ref: forwardedRef });\n }\n);\nPopoverAnchor.displayName = ANCHOR_NAME;\nvar TRIGGER_NAME = \"PopoverTrigger\";\nvar PopoverTrigger = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopePopover, ...triggerProps } = props;\n const context = usePopoverContext(TRIGGER_NAME, __scopePopover);\n const popperScope = usePopperScope(__scopePopover);\n const composedTriggerRef = useComposedRefs(forwardedRef, context.triggerRef);\n const trigger = /* @__PURE__ */ jsx(\n Primitive.button,\n {\n type: \"button\",\n \"aria-haspopup\": \"dialog\",\n \"aria-expanded\": context.open,\n \"aria-controls\": context.contentId,\n \"data-state\": getState(context.open),\n ...triggerProps,\n ref: composedTriggerRef,\n onClick: composeEventHandlers(props.onClick, context.onOpenToggle)\n }\n );\n return context.hasCustomAnchor ? trigger : /* @__PURE__ */ jsx(PopperPrimitive.Anchor, { asChild: true, ...popperScope, children: trigger });\n }\n);\nPopoverTrigger.displayName = TRIGGER_NAME;\nvar PORTAL_NAME = \"PopoverPortal\";\nvar [PortalProvider, usePortalContext] = createPopoverContext(PORTAL_NAME, {\n forceMount: void 0\n});\nvar PopoverPortal = (props) => {\n const { __scopePopover, forceMount, children, container } = props;\n const context = usePopoverContext(PORTAL_NAME, __scopePopover);\n return /* @__PURE__ */ jsx(PortalProvider, { scope: __scopePopover, forceMount, children: /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx(PortalPrimitive, { asChild: true, container, children }) }) });\n};\nPopoverPortal.displayName = PORTAL_NAME;\nvar CONTENT_NAME = \"PopoverContent\";\nvar PopoverContent = React.forwardRef(\n (props, forwardedRef) => {\n const portalContext = usePortalContext(CONTENT_NAME, props.__scopePopover);\n const { forceMount = portalContext.forceMount, ...contentProps } = props;\n const context = usePopoverContext(CONTENT_NAME, props.__scopePopover);\n return /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: context.modal ? /* @__PURE__ */ jsx(PopoverContentModal, { ...contentProps, ref: forwardedRef }) : /* @__PURE__ */ jsx(PopoverContentNonModal, { ...contentProps, ref: forwardedRef }) });\n }\n);\nPopoverContent.displayName = CONTENT_NAME;\nvar Slot = createSlot(\"PopoverContent.RemoveScroll\");\nvar PopoverContentModal = React.forwardRef(\n (props, forwardedRef) => {\n const context = usePopoverContext(CONTENT_NAME, props.__scopePopover);\n const contentRef = React.useRef(null);\n const composedRefs = useComposedRefs(forwardedRef, contentRef);\n const isRightClickOutsideRef = React.useRef(false);\n React.useEffect(() => {\n const content = contentRef.current;\n if (content) return hideOthers(content);\n }, []);\n return /* @__PURE__ */ jsx(RemoveScroll, { as: Slot, allowPinchZoom: true, children: /* @__PURE__ */ jsx(\n PopoverContentImpl,\n {\n ...props,\n ref: composedRefs,\n trapFocus: context.open,\n disableOutsidePointerEvents: true,\n onCloseAutoFocus: composeEventHandlers(props.onCloseAutoFocus, (event) => {\n event.preventDefault();\n if (!isRightClickOutsideRef.current) context.triggerRef.current?.focus();\n }),\n onPointerDownOutside: composeEventHandlers(\n props.onPointerDownOutside,\n (event) => {\n const originalEvent = event.detail.originalEvent;\n const ctrlLeftClick = originalEvent.button === 0 && originalEvent.ctrlKey === true;\n const isRightClick = originalEvent.button === 2 || ctrlLeftClick;\n isRightClickOutsideRef.current = isRightClick;\n },\n { checkForDefaultPrevented: false }\n ),\n onFocusOutside: composeEventHandlers(\n props.onFocusOutside,\n (event) => event.preventDefault(),\n { checkForDefaultPrevented: false }\n )\n }\n ) });\n }\n);\nvar PopoverContentNonModal = React.forwardRef(\n (props, forwardedRef) => {\n const context = usePopoverContext(CONTENT_NAME, props.__scopePopover);\n const hasInteractedOutsideRef = React.useRef(false);\n const hasPointerDownOutsideRef = React.useRef(false);\n return /* @__PURE__ */ jsx(\n PopoverContentImpl,\n {\n ...props,\n ref: forwardedRef,\n trapFocus: false,\n disableOutsidePointerEvents: false,\n onCloseAutoFocus: (event) => {\n props.onCloseAutoFocus?.(event);\n if (!event.defaultPrevented) {\n if (!hasInteractedOutsideRef.current) context.triggerRef.current?.focus();\n event.preventDefault();\n }\n hasInteractedOutsideRef.current = false;\n hasPointerDownOutsideRef.current = false;\n },\n onInteractOutside: (event) => {\n props.onInteractOutside?.(event);\n if (!event.defaultPrevented) {\n hasInteractedOutsideRef.current = true;\n if (event.detail.originalEvent.type === \"pointerdown\") {\n hasPointerDownOutsideRef.current = true;\n }\n }\n const target = event.target;\n const targetIsTrigger = context.triggerRef.current?.contains(target);\n if (targetIsTrigger) event.preventDefault();\n if (event.detail.originalEvent.type === \"focusin\" && hasPointerDownOutsideRef.current) {\n event.preventDefault();\n }\n }\n }\n );\n }\n);\nvar PopoverContentImpl = React.forwardRef(\n (props, forwardedRef) => {\n const {\n __scopePopover,\n trapFocus,\n onOpenAutoFocus,\n onCloseAutoFocus,\n disableOutsidePointerEvents,\n onEscapeKeyDown,\n onPointerDownOutside,\n onFocusOutside,\n onInteractOutside,\n ...contentProps\n } = props;\n const context = usePopoverContext(CONTENT_NAME, __scopePopover);\n const popperScope = usePopperScope(__scopePopover);\n useFocusGuards();\n return /* @__PURE__ */ jsx(\n FocusScope,\n {\n asChild: true,\n loop: true,\n trapped: trapFocus,\n onMountAutoFocus: onOpenAutoFocus,\n onUnmountAutoFocus: onCloseAutoFocus,\n children: /* @__PURE__ */ jsx(\n DismissableLayer,\n {\n asChild: true,\n disableOutsidePointerEvents,\n onInteractOutside,\n onEscapeKeyDown,\n onPointerDownOutside,\n onFocusOutside,\n onDismiss: () => context.onOpenChange(false),\n children: /* @__PURE__ */ jsx(\n PopperPrimitive.Content,\n {\n \"data-state\": getState(context.open),\n role: \"dialog\",\n id: context.contentId,\n ...popperScope,\n ...contentProps,\n ref: forwardedRef,\n style: {\n ...contentProps.style,\n // re-namespace exposed content custom properties\n ...{\n \"--radix-popover-content-transform-origin\": \"var(--radix-popper-transform-origin)\",\n \"--radix-popover-content-available-width\": \"var(--radix-popper-available-width)\",\n \"--radix-popover-content-available-height\": \"var(--radix-popper-available-height)\",\n \"--radix-popover-trigger-width\": \"var(--radix-popper-anchor-width)\",\n \"--radix-popover-trigger-height\": \"var(--radix-popper-anchor-height)\"\n }\n }\n }\n )\n }\n )\n }\n );\n }\n);\nvar CLOSE_NAME = \"PopoverClose\";\nvar PopoverClose = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopePopover, ...closeProps } = props;\n const context = usePopoverContext(CLOSE_NAME, __scopePopover);\n return /* @__PURE__ */ jsx(\n Primitive.button,\n {\n type: \"button\",\n ...closeProps,\n ref: forwardedRef,\n onClick: composeEventHandlers(props.onClick, () => context.onOpenChange(false))\n }\n );\n }\n);\nPopoverClose.displayName = CLOSE_NAME;\nvar ARROW_NAME = \"PopoverArrow\";\nvar PopoverArrow = React.forwardRef(\n (props, forwardedRef) => {\n const { __scopePopover, ...arrowProps } = props;\n const popperScope = usePopperScope(__scopePopover);\n return /* @__PURE__ */ jsx(PopperPrimitive.Arrow, { ...popperScope, ...arrowProps, ref: forwardedRef });\n }\n);\nPopoverArrow.displayName = ARROW_NAME;\nfunction getState(open) {\n return open ? \"open\" : \"closed\";\n}\nvar Root2 = Popover;\nvar Anchor2 = PopoverAnchor;\nvar Trigger = PopoverTrigger;\nvar Portal = PopoverPortal;\nvar Content2 = PopoverContent;\nvar Close = PopoverClose;\nvar Arrow2 = PopoverArrow;\nexport {\n Anchor2 as Anchor,\n Arrow2 as Arrow,\n Close,\n Content2 as Content,\n Popover,\n PopoverAnchor,\n PopoverArrow,\n PopoverClose,\n PopoverContent,\n PopoverPortal,\n PopoverTrigger,\n Portal,\n Root2 as Root,\n Trigger,\n createPopoverScope\n};\n//# sourceMappingURL=index.mjs.map\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Popover as PopoverPrimitive } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Popover({\n ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Root>) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />\n}\n\nfunction PopoverTrigger({\n ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />\n}\n\nfunction PopoverContent({\n className,\n align = \"center\",\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Content>) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n data-slot=\"popover-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 flex w-72 origin-(--radix-popover-content-transform-origin) flex-col gap-2.5 rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n )\n}\n\nfunction PopoverAnchor({\n ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {\n return <PopoverPrimitive.Anchor data-slot=\"popover-anchor\" {...props} />\n}\n\nfunction PopoverHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"popover-header\"\n className={cn(\"flex flex-col gap-0.5 text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction PopoverTitle({ className, ...props }: React.ComponentProps<\"h2\">) {\n return (\n <div\n data-slot=\"popover-title\"\n className={cn(\"font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction PopoverDescription({\n className,\n ...props\n}: React.ComponentProps<\"p\">) {\n return (\n <p\n data-slot=\"popover-description\"\n className={cn(\"text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Popover,\n PopoverAnchor,\n PopoverContent,\n PopoverDescription,\n PopoverHeader,\n PopoverTitle,\n PopoverTrigger,\n}\n","import { useAgentTerminal } from '@/hooks/use-agent-terminal'\nimport { useRelayStore, useNow } from '@/store'\nimport {\n useSortedAgents, useUniqueTags, useUniqueHosts, usePairsByAgentId, useAgentAttention,\n} from '@/hooks/use-selectors'\nimport { Card, CardContent } from '@/components/ui/card'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Popover, PopoverContent, PopoverHeader, PopoverTitle, PopoverTrigger } from '@/components/ui/popover'\nimport { StatusDot } from '@/components/shared/status-dot'\nimport { AgentTypeIcon } from '@/components/shared/agent-type-icon'\nimport { BranchStateBadge } from '@/components/shared/branch-state-badge'\nimport { AgentRuntimeBadges, AgentRuntimeChips, ContextMeter } from '@/components/shared/agent-runtime-summary'\nimport { TerminalDialog } from '@/components/shared/terminal-viewer'\nimport { CopyButton } from '@/components/shared/copy-button'\nimport { AgentProjectBadge } from '@/components/shared/agent-project-badge'\nimport {\n displayName, timeAgo, agentPresence, toneToColor, agentSupportsControlAction, agentCanBeForgotten, userFacingCapabilities, shortPath,\n} from '@/lib/display'\nimport { liveChildrenByParent, sortedLiveChildren, topLevelAgentsForTeamView } from '@/lib/agent-lineage'\nimport {\n MessageSquare, Link, Edit3, Power, Terminal, Minimize2, Eraser, Trash2, Plus, SortAsc, SortDesc, X, Flag, Users,\n} from 'lucide-react'\nimport type { Agent } from '@/types'\n\nfunction AgentCard({ agent, childAgents = [], parentAgent }: { agent: Agent; childAgents?: Agent[]; parentAgent?: Agent | null }) {\n const now = useNow()\n const set = useRelayStore((s) => s.set)\n const switchView = useRelayStore((s) => s.switchView)\n const openInboxThread = useRelayStore((s) => s.openInboxThread)\n const openAgentDetail = useRelayStore((s) => s.openAgentDetail)\n const openPairInvite = useRelayStore((s) => s.openPairInvite)\n const openRename = useRelayStore((s) => s.openRename)\n const openConfirm = useRelayStore((s) => s.openConfirm)\n const doAgentAction = useRelayStore((s) => s.doAgentAction)\n const doDeleteAgent = useRelayStore((s) => s.doDeleteAgent)\n const openFilesForAgent = useRelayStore((s) => s.openFilesForAgent)\n const workspaceAction = useRelayStore((s) => s.workspaceAction)\n const openWorkspaceFocus = useRelayStore((s) => s.openWorkspaceFocus)\n\n const { terminalOpen, terminalTarget, terminalOpening, openTerminal: handleOpenTerminal, closeTerminal: handleCloseTerminal } = useAgentTerminal(agent.id)\n\n const pairsMap = usePairsByAgentId()\n const attention = useAgentAttention(agent)\n const pair = pairsMap[agent.id] || null\n const presence = agentPresence(now, agent, attention, pair)\n\n const canShutdown = agentSupportsControlAction(agent, 'shutdown')\n const canCompact = agentSupportsControlAction(agent, 'compact')\n const canClearContext = agentSupportsControlAction(agent, 'clearContext')\n const canOpenTerminal = Boolean(agent.providerCapabilities?.terminal?.live?.read || agent.providerCapabilities?.terminal?.attach?.create)\n const canWriteTerminal = Boolean(agent.providerCapabilities?.terminal?.live?.write || agent.providerCapabilities?.model?.provider === 'claude')\n const canForget = agentCanBeForgotten(agent)\n const parentLabel = parentAgent ? displayName(parentAgent) : agent.spawnedBy\n const hasTeam = childAgents.length > 0\n\n return (\n <>\n <Card\n className=\"group hover:border-zinc-600 transition-colors cursor-pointer\"\n onClick={() => openAgentDetail(agent)}\n >\n <CardContent className=\"p-4\">\n <div className=\"flex items-start gap-2.5 mb-2.5\">\n <StatusDot agent={agent} now={now} className=\"mt-0.5\" />\n <AgentTypeIcon agent={agent} />\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm font-medium truncate\">{displayName(agent)}</div>\n <div className={`text-xs mt-0.5 ${toneToColor(presence.tone)}`}>{presence.label}</div>\n {typeof agent.meta?.cwd === 'string' && agent.meta.cwd && (\n <button\n type=\"button\"\n className=\"mt-0.5 block max-w-full truncate font-mono text-[10px] text-muted-foreground hover:text-foreground\"\n title={`Open ${agent.meta.cwd as string} in Files`}\n onClick={(e) => { e.stopPropagation(); void openFilesForAgent(agent) }}\n >\n {shortPath(agent.meta.cwd as string)}\n </button>\n )}\n <AgentProjectBadge agent={agent} className=\"mt-1\" />\n </div>\n {agent.branchState && agent.branchWorkspaceId && (\n <BranchStateBadge\n state={agent.branchState}\n className=\"mt-0.5 shrink-0\"\n onClick={(e) => { e.stopPropagation(); void openWorkspaceFocus(agent.branchWorkspaceId!) }}\n />\n )}\n </div>\n\n {/* Presence badges */}\n {presence.badges.length > 0 && (\n <div className=\"flex flex-wrap gap-1 mb-2\">\n {presence.badges.map((b) => (\n <span key={b.label} className={`text-[10px] px-1.5 py-0.5 rounded-full font-medium ${b.className}`}>\n {b.label}\n </span>\n ))}\n </div>\n )}\n\n {(hasTeam || (agent.spawnedBy && parentLabel)) && (\n <div className=\"mb-2 flex flex-wrap gap-1.5\" onClick={(e) => e.stopPropagation()}>\n {hasTeam && (\n <Popover>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex h-6 max-w-full items-center gap-1.5 rounded-full border border-sky-500/30 bg-sky-500/10 px-2 text-[10px] font-medium text-sky-300 transition-colors hover:bg-sky-500/15\"\n title={`${childAgents.length} live child ${childAgents.length === 1 ? 'agent' : 'agents'}`}\n >\n <Users className=\"h-3 w-3\" />\n <span>{childAgents.length}</span>\n <span className=\"flex -space-x-1\">\n {childAgents.slice(0, 4).map((child) => (\n <StatusDot key={child.id} agent={child} now={now} className=\"h-2 w-2 ring-1 ring-background\" />\n ))}\n </span>\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-80\" onClick={(e) => e.stopPropagation()}>\n <PopoverHeader>\n <PopoverTitle>Team</PopoverTitle>\n </PopoverHeader>\n <div className=\"space-y-1.5\">\n {childAgents.map((child) => (\n <div key={child.id} className=\"rounded-md border border-border bg-card/60 p-2\">\n <div className=\"flex items-start gap-2\">\n <StatusDot agent={child} now={now} className=\"mt-1\" />\n <AgentTypeIcon agent={child} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-xs font-medium\">{displayName(child)}</div>\n <div className=\"truncate text-[10px] text-muted-foreground\">\n {child.providerCapabilities?.model?.alias || child.providerCapabilities?.model?.id || child.providerCapabilities?.model?.provider || child.status}\n </div>\n </div>\n <Badge variant=\"outline\" className=\"h-4 px-1.5 text-[9px]\">{child.status}</Badge>\n </div>\n <div className=\"mt-2 flex gap-1\">\n <Button size=\"xs\" variant=\"outline\" onClick={() => openAgentDetail(child)}>Open</Button>\n <Button size=\"xs\" variant=\"ghost\" onClick={() => { openInboxThread(child.id); switchView('chat') }}>\n <MessageSquare className=\"h-3 w-3\" />\n Chat\n </Button>\n </div>\n </div>\n ))}\n </div>\n </PopoverContent>\n </Popover>\n )}\n {agent.spawnedBy && parentLabel && (\n <Badge variant=\"outline\" className=\"max-w-full text-[10px] text-muted-foreground\">\n <span className=\"truncate\">spawned by {parentLabel}</span>\n </Badge>\n )}\n </div>\n )}\n\n {/* Tags + caps */}\n {(agent.tags.length > 0 || userFacingCapabilities(agent.capabilities).length > 0) && (\n <div className=\"flex flex-wrap gap-1 mb-2\">\n {agent.tags.slice(0, 3).map((t) => (\n <Badge key={t} variant=\"outline\" className=\"text-[9px] px-1 py-0 h-4\">{t}</Badge>\n ))}\n {userFacingCapabilities(agent.capabilities).slice(0, 2).map((c) => (\n <Badge key={c} variant=\"secondary\" className=\"text-[9px] px-1 py-0 h-4\">{c}</Badge>\n ))}\n </div>\n )}\n\n <div className=\"space-y-2 mb-2\">\n <AgentRuntimeChips agent={agent} />\n <AgentRuntimeBadges agent={agent} compact />\n <ContextMeter agent={agent} />\n </div>\n\n <div className=\"text-xs text-muted-foreground\">\n {agent.id !== 'user' && agent.id !== 'system' && timeAgo(now, agent.lastSeen)}\n </div>\n\n {/* Action buttons – always visible on mobile, hover on desktop */}\n <div\n className=\"flex gap-1 mt-2.5 opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity\"\n onClick={(e) => e.stopPropagation()}\n >\n <CopyButton value={agent.id} label=\"Copy agent ID\" size=\"icon\" className=\"h-7 w-7\" iconClassName=\"w-3 h-3\" />\n <Button size=\"icon\" variant=\"ghost\" className=\"h-7 w-7\" title=\"Chat\" onClick={() => { openInboxThread(agent.id); switchView('chat') }}>\n <MessageSquare className=\"w-3 h-3\" />\n </Button>\n <Button size=\"icon\" variant=\"ghost\" className=\"h-7 w-7\" title=\"Pair\" onClick={() => openPairInvite(agent.id)}>\n <Link className=\"w-3 h-3\" />\n </Button>\n <Button size=\"icon\" variant=\"ghost\" className=\"h-7 w-7\" title=\"Rename\" onClick={() => openRename(agent)}>\n <Edit3 className=\"w-3 h-3\" />\n </Button>\n {canOpenTerminal && (\n <Button size=\"icon\" variant=\"ghost\" className=\"h-7 w-7\" title=\"Terminal\" disabled={terminalOpening} onClick={() => void handleOpenTerminal()}>\n <Terminal className=\"w-3 h-3\" />\n </Button>\n )}\n {(agent.branchState === 'changes' || agent.branchState === 'idle') && agent.branchWorkspaceId && (\n <Button size=\"icon\" variant=\"ghost\" className=\"h-7 w-7 text-amber-400 hover:text-amber-300\" title=\"Mark workspace ready — hand off to the auto-merge\" onClick={() => openConfirm('Mark Workspace Ready', `Mark ${displayName(agent)}'s branch ready to land? The relay auto-merge will rebase and land it.`, () => workspaceAction(agent.branchWorkspaceId!, 'ready'))}>\n <Flag className=\"w-3 h-3\" />\n </Button>\n )}\n {canCompact && (\n <Button size=\"icon\" variant=\"ghost\" className=\"h-7 w-7\" title=\"Compact\" onClick={() => openConfirm('Compact Agent', `Compact context for ${displayName(agent)}?`, () => doAgentAction(agent, 'compact', 'agents-grid'))}>\n <Minimize2 className=\"w-3 h-3\" />\n </Button>\n )}\n {canClearContext && (\n <Button size=\"icon\" variant=\"ghost\" className=\"h-7 w-7\" title=\"Clear Context\" onClick={() => openConfirm('Clear Context', `Clear context for ${displayName(agent)}?`, () => doAgentAction(agent, 'clearContext', 'agents-grid'))}>\n <Eraser className=\"w-3 h-3\" />\n </Button>\n )}\n {canShutdown && (\n <Button size=\"icon\" variant=\"ghost\" className=\"h-7 w-7 text-red-400 hover:text-red-300\" title=\"Shutdown\" onClick={() => openConfirm('Shutdown Agent', `Shutdown ${displayName(agent)}?`, () => doAgentAction(agent, 'shutdown', 'agents-grid'))}>\n <Power className=\"w-3 h-3\" />\n </Button>\n )}\n {canForget && (\n <Button size=\"icon\" variant=\"ghost\" className=\"h-7 w-7 text-red-400 hover:text-red-300\" title=\"Forget stale agent\" onClick={() => openConfirm('Forget Agent', `Forget ${displayName(agent)}?`, () => doDeleteAgent(agent.id))}>\n <Trash2 className=\"w-3 h-3\" />\n </Button>\n )}\n </div>\n </CardContent>\n </Card>\n {terminalTarget && (\n <TerminalDialog open={terminalOpen} onOpenChange={handleCloseTerminal} orchestratorId={terminalTarget.orchestratorId} session={terminalTarget.session} interactive={terminalTarget.interactive || canWriteTerminal} />\n )}\n </>\n )\n}\n\nexport function AgentsView() {\n const agentPresetFilter = useRelayStore((s) => s.agentPresetFilter)\n const agentStatusFilter = useRelayStore((s) => s.agentStatusFilter)\n const agentTagFilter = useRelayStore((s) => s.agentTagFilter)\n const agentHostFilter = useRelayStore((s) => s.agentHostFilter)\n const agentSort = useRelayStore((s) => s.agentSort)\n const agentSortDir = useRelayStore((s) => s.agentSortDir)\n const showOffline = useRelayStore((s) => s.showOffline)\n const set = useRelayStore((s) => s.set)\n const openAgentSpawn = useRelayStore((s) => s.openAgentSpawn)\n const agentsById = useRelayStore((s) => s.agentsById)\n const now = useNow()\n\n const sortedAgents = useSortedAgents()\n const uniqueTags = useUniqueTags()\n const uniqueHosts = useUniqueHosts()\n const childrenByParent = liveChildrenByParent(sortedAgents, now)\n const topLevelAgents = topLevelAgentsForTeamView(sortedAgents, now)\n\n const hasFilters = agentPresetFilter || agentStatusFilter || agentTagFilter || agentHostFilter\n\n function clearFilters() {\n set({ agentPresetFilter: '', agentStatusFilter: '', agentTagFilter: '', agentHostFilter: '' })\n }\n\n function toggleSortDir() {\n set({ agentSortDir: agentSortDir === 'asc' ? 'desc' : 'asc' })\n }\n\n return (\n <div className=\"space-y-4\">\n {/* Toolbar */}\n <div className=\"flex flex-wrap items-center gap-2\">\n <select\n value={agentPresetFilter}\n onChange={(e) => set({ agentPresetFilter: e.target.value })}\n className=\"h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground\"\n >\n <option value=\"\">All agents</option>\n <option value=\"active\">Active</option>\n <option value=\"claude\">Claude</option>\n <option value=\"codex\">Codex</option>\n <option value=\"paired\">Paired</option>\n <option value=\"unpaired\">Unpaired</option>\n <option value=\"offline_stale\">Offline / Stale</option>\n </select>\n\n <select\n value={agentStatusFilter}\n onChange={(e) => set({ agentStatusFilter: e.target.value })}\n className=\"h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground\"\n >\n <option value=\"\">Any status</option>\n <option value=\"online\">Online</option>\n <option value=\"idle\">Idle</option>\n <option value=\"busy\">Busy</option>\n <option value=\"offline\">Offline</option>\n <option value=\"starting\">Starting</option>\n </select>\n\n {uniqueTags.length > 0 && (\n <select\n value={agentTagFilter}\n onChange={(e) => set({ agentTagFilter: e.target.value })}\n className=\"h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground\"\n >\n <option value=\"\">Any tag</option>\n {uniqueTags.map((t) => <option key={t} value={t}>{t}</option>)}\n </select>\n )}\n\n {uniqueHosts.length > 1 && (\n <select\n value={agentHostFilter}\n onChange={(e) => set({ agentHostFilter: e.target.value })}\n className=\"h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground\"\n >\n <option value=\"\">Any host</option>\n {uniqueHosts.map((h) => <option key={h} value={h}>{h}</option>)}\n </select>\n )}\n\n <select\n value={agentSort}\n onChange={(e) => set({ agentSort: e.target.value })}\n className=\"h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground\"\n >\n <option value=\"status\">Sort: Status</option>\n <option value=\"name\">Sort: Name</option>\n <option value=\"lastSeen\">Sort: Last seen</option>\n <option value=\"created\">Sort: Created</option>\n </select>\n\n <Button size=\"icon\" variant=\"outline\" className=\"h-8 w-8\" title=\"Toggle sort direction\" onClick={toggleSortDir}>\n {agentSortDir === 'asc' ? <SortAsc className=\"w-3.5 h-3.5\" /> : <SortDesc className=\"w-3.5 h-3.5\" />}\n </Button>\n\n <label className=\"flex items-center gap-1.5 text-sm text-muted-foreground cursor-pointer select-none\">\n <input\n type=\"checkbox\"\n checked={showOffline}\n onChange={(e) => set({ showOffline: e.target.checked })}\n className=\"rounded\"\n />\n Show offline\n </label>\n\n {hasFilters && (\n <Button size=\"sm\" variant=\"ghost\" className=\"h-8 text-muted-foreground hover:text-foreground gap-1\" onClick={clearFilters}>\n <X className=\"w-3 h-3\" />\n Clear filters\n </Button>\n )}\n\n <div className=\"ml-auto\">\n <Button size=\"sm\" onClick={openAgentSpawn} className=\"gap-1\">\n <Plus className=\"w-3.5 h-3.5\" />\n Spawn\n </Button>\n </div>\n </div>\n\n {/* Agent grid */}\n {topLevelAgents.length === 0 ? (\n <div className=\"text-center py-16 text-muted-foreground text-sm\">\n No agents match the current filters.\n </div>\n ) : (\n <div className=\"grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 gap-3\">\n {topLevelAgents.map((agent) => (\n <AgentCard\n key={agent.id}\n agent={agent}\n parentAgent={agent.spawnedBy ? agentsById[agent.spawnedBy] ?? null : null}\n childAgents={sortedLiveChildren(childrenByParent.get(agent.id) ?? [])}\n />\n ))}\n </div>\n )}\n </div>\n )\n}\n"],"x_google_ignoreList":[0],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{$n as t,Qn as n,Xn as r,a as i,dr as a,gn as o,kt as s,ln as c,m as l}from"./lucide-react-BYZuAhQs.js";import{t as u}from"./store-pKbf_WYd.js";var d=e(a(),1);function f(e){let n=u(e=>e.showError),[r,i]=(0,d.useState)(!1),[a,o]=(0,d.useState)(null),[s,c]=(0,d.useState)(!1);async function l(){if(!(!e||s)){c(!0);try{o(await t(`POST`,`/agents/`+encodeURIComponent(e)+`/terminal-session`)),i(!0)}catch(e){n(`Terminal Failed`,e.message)}finally{c(!1)}}}function f(n){if(n){i(!0);return}i(!1);let r=a;o(null),e&&r?.mode===`guest`&&t(`DELETE`,`/agents/`+encodeURIComponent(e)+`/terminal-session/`+encodeURIComponent(r.session)).catch(()=>{})}return{terminalOpen:r,terminalTarget:a,terminalOpening:s,openTerminal:l,closeTerminal:f}}var p=n(),m={idle:{label:`idle`,tip:`Branch worktree — nothing to land yet.`,className:`bg-zinc-500/10 text-zinc-400 border-zinc-500/20`,Icon:c},changes:{label:`changes`,tip:`Unlanded work in this branch — use "Mark workspace ready" to land it.`,className:`bg-amber-500/10 text-amber-400 border-amber-500/20`,Icon:s},ready:{label:`ready`,tip:`Handed off — the relay auto-merge will land it (~2 min sweep).`,className:`bg-blue-500/10 text-blue-400 border-blue-500/20`,Icon:o},steward:{label:`steward`,tip:`Under reconciliation — a steward is landing it. No action needed.`,className:`bg-orange-500/10 text-orange-400 border-orange-500/20`,Icon:i},blocked:{label:`blocked`,tip:`Escalated — the auto-merge/steward path is stuck. Needs human attention.`,className:`bg-red-500/10 text-red-400 border-red-500/20`,Icon:l}};function h({state:e,onClick:t,iconOnly:n=!1,className:i}){let a=m[e],{Icon:o}=a,s=!!t,c=s?`${a.tip} Click to open this workspace.`:a.tip;return(0,p.jsxs)(`span`,{role:s?`button`:void 0,tabIndex:s?0:void 0,title:c,onClick:t,onKeyDown:s?e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),t?.(e))}:void 0,className:r(`inline-flex items-center gap-1 rounded-full border px-1.5 py-0.5 text-[10px] font-medium leading-none`,a.className,s&&`cursor-pointer hover:brightness-125 focus:outline-none focus:ring-1 focus:ring-current`,i),children:[(0,p.jsx)(o,{className:`h-2.5 w-2.5 shrink-0`}),!n&&(0,p.jsx)(`span`,{children:a.label})]})}export{f as n,h as t};
2
- //# sourceMappingURL=branch-state-badge-CNko2_BL.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"branch-state-badge-CNko2_BL.js","names":[],"sources":["../../dashboard/src/hooks/use-agent-terminal.ts","../../dashboard/src/components/shared/branch-state-badge.tsx"],"sourcesContent":["import { useState } from 'react'\nimport { api } from '@/lib/api'\nimport { useRelayStore } from '@/store'\n\ninterface TerminalTarget {\n mode: string\n orchestratorId: string\n session: string\n interactive: boolean\n}\n\n/**\n * Open/close lifecycle for an agent's terminal session. Shared by the agent\n * card and the chat header — both POST a terminal-session, track the target,\n * and DELETE guest sessions on close. Pass null/undefined to no-op (e.g. when\n * no agent is selected).\n */\nexport function useAgentTerminal(agentId: string | null | undefined) {\n const showError = useRelayStore((s) => s.showError)\n const [terminalOpen, setTerminalOpen] = useState(false)\n const [terminalTarget, setTerminalTarget] = useState<TerminalTarget | null>(null)\n const [terminalOpening, setTerminalOpening] = useState(false)\n\n async function openTerminal() {\n if (!agentId || terminalOpening) return\n setTerminalOpening(true)\n try {\n const session = await api<TerminalTarget>('POST', '/agents/' + encodeURIComponent(agentId) + '/terminal-session')\n setTerminalTarget(session)\n setTerminalOpen(true)\n } catch (e) {\n showError('Terminal Failed', (e as Error).message)\n } finally {\n setTerminalOpening(false)\n }\n }\n\n function closeTerminal(open: boolean) {\n if (open) { setTerminalOpen(true); return }\n setTerminalOpen(false)\n const target = terminalTarget\n setTerminalTarget(null)\n if (agentId && target?.mode === 'guest') {\n void api('DELETE', '/agents/' + encodeURIComponent(agentId) + '/terminal-session/' + encodeURIComponent(target.session)).catch(() => {})\n }\n }\n\n return { terminalOpen, terminalTarget, terminalOpening, openTerminal, closeTerminal }\n}\n","import type { MouseEvent } from 'react'\nimport { Circle, CircleArrowUp, GitCommitHorizontal, TriangleAlert, Wrench, type LucideIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport type { BranchState } from '@/types'\n\n// Visual model for the #236 branch-state badge — one row per BranchState. The\n// server (deriveBranchState) is the single source of truth for the value; this map\n// is purely how the human reads it. `tip` doubles as the next-step hint.\nconst BRANCH_STATE_META: Record<BranchState, { label: string; tip: string; className: string; Icon: LucideIcon }> = {\n idle: {\n label: 'idle',\n tip: 'Branch worktree — nothing to land yet.',\n className: 'bg-zinc-500/10 text-zinc-400 border-zinc-500/20',\n Icon: Circle,\n },\n changes: {\n label: 'changes',\n tip: 'Unlanded work in this branch — use \"Mark workspace ready\" to land it.',\n className: 'bg-amber-500/10 text-amber-400 border-amber-500/20',\n Icon: GitCommitHorizontal,\n },\n ready: {\n label: 'ready',\n tip: 'Handed off — the relay auto-merge will land it (~2 min sweep).',\n className: 'bg-blue-500/10 text-blue-400 border-blue-500/20',\n Icon: CircleArrowUp,\n },\n steward: {\n label: 'steward',\n tip: 'Under reconciliation — a steward is landing it. No action needed.',\n className: 'bg-orange-500/10 text-orange-400 border-orange-500/20',\n Icon: Wrench,\n },\n blocked: {\n label: 'blocked',\n tip: 'Escalated — the auto-merge/steward path is stuck. Needs human attention.',\n className: 'bg-red-500/10 text-red-400 border-red-500/20',\n Icon: TriangleAlert,\n },\n}\n\ninterface BranchStateBadgeProps {\n state: BranchState\n /** Click-through (opens the Workspaces panel focused on this workspace). */\n onClick?: (event: MouseEvent) => void\n /** Hide the text label, leaving just the icon (tight headers). */\n iconOnly?: boolean\n className?: string\n}\n\nexport function BranchStateBadge({ state, onClick, iconOnly = false, className }: BranchStateBadgeProps) {\n const meta = BRANCH_STATE_META[state]\n const { Icon } = meta\n const interactive = Boolean(onClick)\n const tip = interactive ? `${meta.tip} Click to open this workspace.` : meta.tip\n return (\n <span\n role={interactive ? 'button' : undefined}\n tabIndex={interactive ? 0 : undefined}\n title={tip}\n onClick={onClick}\n onKeyDown={interactive ? (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onClick?.(e as unknown as MouseEvent) } } : undefined}\n className={cn(\n 'inline-flex items-center gap-1 rounded-full border px-1.5 py-0.5 text-[10px] font-medium leading-none',\n meta.className,\n interactive && 'cursor-pointer hover:brightness-125 focus:outline-none focus:ring-1 focus:ring-current',\n className,\n )}\n >\n <Icon className=\"h-2.5 w-2.5 shrink-0\" />\n {!iconOnly && <span>{meta.label}</span>}\n </span>\n )\n}\n"],"mappings":"6MAiBA,SAAgB,EAAiB,EAAoC,CACnE,IAAM,EAAY,EAAe,GAAM,EAAE,UAAU,CAC7C,CAAC,EAAc,IAAA,EAAA,EAAA,UAA4B,GAAM,CACjD,CAAC,EAAgB,IAAA,EAAA,EAAA,UAAqD,KAAK,CAC3E,CAAC,EAAiB,IAAA,EAAA,EAAA,UAA+B,GAAM,CAE7D,eAAe,GAAe,CACxB,MAAC,GAAW,GAChB,GAAmB,GAAK,CACxB,GAAI,CAEF,EAAkB,MADI,EAAoB,OAAQ,WAAa,mBAAmB,EAAQ,CAAG,oBAAoB,CACvF,CAC1B,EAAgB,GAAK,OACd,EAAG,CACV,EAAU,kBAAoB,EAAY,QAAQ,QAC1C,CACR,EAAmB,GAAM,GAI7B,SAAS,EAAc,EAAe,CACpC,GAAI,EAAM,CAAE,EAAgB,GAAK,CAAE,OACnC,EAAgB,GAAM,CACtB,IAAM,EAAS,EACf,EAAkB,KAAK,CACnB,GAAW,GAAQ,OAAS,SAC9B,EAAS,SAAU,WAAa,mBAAmB,EAAQ,CAAG,qBAAuB,mBAAmB,EAAO,QAAQ,CAAC,CAAC,UAAY,GAAG,CAI5I,MAAO,CAAE,eAAc,iBAAgB,kBAAiB,eAAc,gBAAe,WCvCjF,EAA8G,CAClH,KAAM,CACJ,MAAO,OACP,IAAK,yCACL,UAAW,kDACX,KAAM,EACP,CACD,QAAS,CACP,MAAO,UACP,IAAK,wEACL,UAAW,qDACX,KAAM,EACP,CACD,MAAO,CACL,MAAO,QACP,IAAK,iEACL,UAAW,kDACX,KAAM,EACP,CACD,QAAS,CACP,MAAO,UACP,IAAK,oEACL,UAAW,wDACX,KAAM,EACP,CACD,QAAS,CACP,MAAO,UACP,IAAK,2EACL,UAAW,+CACX,KAAM,EACP,CACF,CAWD,SAAgB,EAAiB,CAAE,QAAO,UAAS,WAAW,GAAO,aAAoC,CACvG,IAAM,EAAO,EAAkB,GACzB,CAAE,QAAS,EACX,EAAc,EAAQ,EACtB,EAAM,EAAc,GAAG,EAAK,IAAI,gCAAkC,EAAK,IAC7E,OACE,EAAA,EAAA,MAAC,OAAD,CACE,KAAM,EAAc,SAAW,IAAA,GAC/B,SAAU,EAAc,EAAI,IAAA,GAC5B,MAAO,EACE,UACT,UAAW,EAAe,GAAM,EAAM,EAAE,MAAQ,SAAW,EAAE,MAAQ,OAAO,EAAE,gBAAgB,CAAE,IAAU,EAA2B,GAAO,IAAA,GAC5I,UAAW,EACT,wGACA,EAAK,UACL,GAAe,yFACf,EACD,UAXH,EAaE,EAAA,EAAA,KAAC,EAAD,CAAM,UAAU,uBAAyB,CAAA,CACxC,CAAC,IAAY,EAAA,EAAA,KAAC,OAAD,CAAA,SAAO,EAAK,MAAa,CAAA,CAClC"}