agent-relay-server 0.52.0 → 0.54.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 (135) hide show
  1. package/docs/openapi.json +1 -1
  2. package/package.json +1 -1
  3. package/public/assets/PlanGraphPanel-CQ0CH7e9.js +2 -0
  4. package/public/assets/PlanGraphPanel-CQ0CH7e9.js.map +1 -0
  5. package/public/assets/{activity-BNLuP717.js → activity-CxnH-3Zt.js} +2 -2
  6. package/public/assets/{activity-BNLuP717.js.map → activity-CxnH-3Zt.js.map} +1 -1
  7. package/public/assets/{agent-profiles-BhVEehP8.js → agent-profiles-JhWQY-pg.js} +2 -2
  8. package/public/assets/{agent-profiles-BhVEehP8.js.map → agent-profiles-JhWQY-pg.js.map} +1 -1
  9. package/public/assets/agents-Bn7CXOMZ.js +2 -0
  10. package/public/assets/{agents-CqQhC2aN.js.map → agents-Bn7CXOMZ.js.map} +1 -1
  11. package/public/assets/{analytics-44eqtAsx.js → analytics-BCVgYihk.js} +3 -3
  12. package/public/assets/{analytics-44eqtAsx.js.map → analytics-BCVgYihk.js.map} +1 -1
  13. package/public/assets/{automation-x65cxlk4.js → automation-Cu5J1Yh4.js} +2 -2
  14. package/public/assets/{automation-x65cxlk4.js.map → automation-Cu5J1Yh4.js.map} +1 -1
  15. package/public/assets/{badge-BR4bvEsy.js → badge-D6yb-Kia.js} +2 -2
  16. package/public/assets/{badge-BR4bvEsy.js.map → badge-D6yb-Kia.js.map} +1 -1
  17. package/public/assets/branch-state-badge-fOM74RDq.js +2 -0
  18. package/public/assets/{branch-state-badge-Dp6Jk4LH.js.map → branch-state-badge-fOM74RDq.js.map} +1 -1
  19. package/public/assets/{button-BwqJZS4O.js → button-B-w6a1Ng.js} +2 -2
  20. package/public/assets/{button-BwqJZS4O.js.map → button-B-w6a1Ng.js.map} +1 -1
  21. package/public/assets/card-j6bjYxys.js +2 -0
  22. package/public/assets/{card-C7JtSyuM.js.map → card-j6bjYxys.js.map} +1 -1
  23. package/public/assets/{channels-CmfUfiV0.js → channels-D4q8I1q-.js} +2 -2
  24. package/public/assets/{channels-CmfUfiV0.js.map → channels-D4q8I1q-.js.map} +1 -1
  25. package/public/assets/chat-6QaNdZGN.js +2 -0
  26. package/public/assets/{chat-nugo0m55.js.map → chat-6QaNdZGN.js.map} +1 -1
  27. package/public/assets/{connectors-Bf74bw_9.js → connectors-DuWMf8KT.js} +2 -2
  28. package/public/assets/{connectors-Bf74bw_9.js.map → connectors-DuWMf8KT.js.map} +1 -1
  29. package/public/assets/{copy-button-nbDhTE0M.js → copy-button-CJDmQ9UB.js} +2 -2
  30. package/public/assets/{copy-button-nbDhTE0M.js.map → copy-button-CJDmQ9UB.js.map} +1 -1
  31. package/public/assets/{dist-BIAvrITs.js → dist-1iqvQR2q.js} +2 -2
  32. package/public/assets/{dist-BIAvrITs.js.map → dist-1iqvQR2q.js.map} +1 -1
  33. package/public/assets/{dist-MdPDPcyo.js → dist-BNF6RqQf.js} +2 -2
  34. package/public/assets/{dist-MdPDPcyo.js.map → dist-BNF6RqQf.js.map} +1 -1
  35. package/public/assets/{dist-Dvspm7RE.js → dist-Bg5mAaEO.js} +2 -2
  36. package/public/assets/{dist-Dvspm7RE.js.map → dist-Bg5mAaEO.js.map} +1 -1
  37. package/public/assets/{dist-C7UYAwBf.js → dist-BtFzbpiK.js} +2 -2
  38. package/public/assets/{dist-C7UYAwBf.js.map → dist-BtFzbpiK.js.map} +1 -1
  39. package/public/assets/{dist-svixSeDF.js → dist-CLUvHFPE.js} +2 -2
  40. package/public/assets/{dist-svixSeDF.js.map → dist-CLUvHFPE.js.map} +1 -1
  41. package/public/assets/{dist-BiVJ8IWp.js → dist-Cl4PfJEy.js} +2 -2
  42. package/public/assets/{dist-BiVJ8IWp.js.map → dist-Cl4PfJEy.js.map} +1 -1
  43. package/public/assets/dist-D1g0W-kO.js +2 -0
  44. package/public/assets/{dist-BkDVLgYg.js.map → dist-D1g0W-kO.js.map} +1 -1
  45. package/public/assets/{dist-DvLO--_O.js → dist-DLc4vQoq.js} +2 -2
  46. package/public/assets/{dist-DvLO--_O.js.map → dist-DLc4vQoq.js.map} +1 -1
  47. package/public/assets/{dist-CSISzAHD.js → dist-HMkrkMzb.js} +2 -2
  48. package/public/assets/{dist-CSISzAHD.js.map → dist-HMkrkMzb.js.map} +1 -1
  49. package/public/assets/dist-MX7mVzej.js +2 -0
  50. package/public/assets/{dist-D5y1HX8f.js.map → dist-MX7mVzej.js.map} +1 -1
  51. package/public/assets/dist-fe-f7EIl.js +2 -0
  52. package/public/assets/{dist-tX4uIBFU.js.map → dist-fe-f7EIl.js.map} +1 -1
  53. package/public/assets/{es2015-Cu7l1536.js → es2015-4dO99MHc.js} +2 -2
  54. package/public/assets/{es2015-Cu7l1536.js.map → es2015-4dO99MHc.js.map} +1 -1
  55. package/public/assets/{formatted-body-impl-UeUBqdRz.js → formatted-body-impl-CTv-ZFNo.js} +2 -2
  56. package/public/assets/{formatted-body-impl-UeUBqdRz.js.map → formatted-body-impl-CTv-ZFNo.js.map} +1 -1
  57. package/public/assets/index-Cobj8Cqd.js +21 -0
  58. package/public/assets/index-Cobj8Cqd.js.map +1 -0
  59. package/public/assets/index-D7FDcoef.css +2 -0
  60. package/public/assets/{input-YoPXrp72.js → input-EazHb1Bc.js} +2 -2
  61. package/public/assets/{input-YoPXrp72.js.map → input-EazHb1Bc.js.map} +1 -1
  62. package/public/assets/{insights-C9k7mCoJ.js → insights-Ucwp3dHJ.js} +2 -2
  63. package/public/assets/{insights-C9k7mCoJ.js.map → insights-Ucwp3dHJ.js.map} +1 -1
  64. package/public/assets/{integrations-By3hMfqC.js → integrations-eRsF4CjO.js} +2 -2
  65. package/public/assets/{integrations-By3hMfqC.js.map → integrations-eRsF4CjO.js.map} +1 -1
  66. package/public/assets/{lib-D8ccisdr.js → lib-C7poqE0I.js} +3 -3
  67. package/public/assets/{lib-D8ccisdr.js.map → lib-C7poqE0I.js.map} +1 -1
  68. package/public/assets/{lucide-react-ChOGD4vc.js → lucide-react-Dr0-sUx6.js} +2 -2
  69. package/public/assets/{lucide-react-ChOGD4vc.js.map → lucide-react-Dr0-sUx6.js.map} +1 -1
  70. package/public/assets/{maintenance-tgb7AMTv.js → maintenance-BW56fE-T.js} +2 -2
  71. package/public/assets/{maintenance-tgb7AMTv.js.map → maintenance-BW56fE-T.js.map} +1 -1
  72. package/public/assets/{managed-agents-DJ3TfBJ5.js → managed-agents-BkFAu1Ub.js} +2 -2
  73. package/public/assets/{managed-agents-DJ3TfBJ5.js.map → managed-agents-BkFAu1Ub.js.map} +1 -1
  74. package/public/assets/{markdown-preview-impl-DcHq1Hto.js → markdown-preview-impl-BT43MQ7E.js} +2 -2
  75. package/public/assets/{markdown-preview-impl-DcHq1Hto.js.map → markdown-preview-impl-BT43MQ7E.js.map} +1 -1
  76. package/public/assets/memory-Cw279dr5.js +2 -0
  77. package/public/assets/{memory-CMdemdtb.js.map → memory-Cw279dr5.js.map} +1 -1
  78. package/public/assets/{messages-CLuLC9wC.js → messages-5InjjgUv.js} +2 -2
  79. package/public/assets/{messages-CLuLC9wC.js.map → messages-5InjjgUv.js.map} +1 -1
  80. package/public/assets/{orchestrators-d27zYyT9.js → orchestrators-B78CQxLl.js} +2 -2
  81. package/public/assets/{orchestrators-d27zYyT9.js.map → orchestrators-B78CQxLl.js.map} +1 -1
  82. package/public/assets/{overview-BY-cs5SI.js → overview-C9V2X2oo.js} +2 -2
  83. package/public/assets/{overview-BY-cs5SI.js.map → overview-C9V2X2oo.js.map} +1 -1
  84. package/public/assets/{pairs-CmyQx_4F.js → pairs-Cc3tOjXB.js} +2 -2
  85. package/public/assets/{pairs-CmyQx_4F.js.map → pairs-Cc3tOjXB.js.map} +1 -1
  86. package/public/assets/{react-dom-DgWuIw1o.js → react-dom-CQSYEHV9.js} +2 -2
  87. package/public/assets/{react-dom-DgWuIw1o.js.map → react-dom-CQSYEHV9.js.map} +1 -1
  88. package/public/assets/{security-CxCnWTlk.js → security-CpBET4KN.js} +2 -2
  89. package/public/assets/{security-CxCnWTlk.js.map → security-CpBET4KN.js.map} +1 -1
  90. package/public/assets/{select-B6iG4oYX.js → select-FNVeUxFZ.js} +2 -2
  91. package/public/assets/{select-B6iG4oYX.js.map → select-FNVeUxFZ.js.map} +1 -1
  92. package/public/assets/settings-CPto3TdF.js +10 -0
  93. package/public/assets/settings-CPto3TdF.js.map +1 -0
  94. package/public/assets/{store-BLZA3u7Y.js → store-h-egULYA.js} +4 -4
  95. package/public/assets/store-h-egULYA.js.map +1 -0
  96. package/public/assets/{tasks-BYUAWEL-.js → tasks-BPplMcnM.js} +2 -2
  97. package/public/assets/{tasks-BYUAWEL-.js.map → tasks-BPplMcnM.js.map} +1 -1
  98. package/public/assets/teams-CCeuRt7v.js +2 -0
  99. package/public/assets/{teams-gWvyw7ET.js.map → teams-CCeuRt7v.js.map} +1 -1
  100. package/public/assets/{terminal-viewer-impl-CHP0w79T.js → terminal-viewer-impl-DRlbl8Yv.js} +3 -3
  101. package/public/assets/{terminal-viewer-impl-CHP0w79T.js.map → terminal-viewer-impl-DRlbl8Yv.js.map} +1 -1
  102. package/public/assets/{use-keyboard-viewport-BY99X7eI.js → use-keyboard-viewport-Iaz6IT4p.js} +2 -2
  103. package/public/assets/{use-keyboard-viewport-BY99X7eI.js.map → use-keyboard-viewport-Iaz6IT4p.js.map} +1 -1
  104. package/public/assets/{work-queue-CBjXlNuG.js → work-queue-qtjloIIF.js} +2 -2
  105. package/public/assets/{work-queue-CBjXlNuG.js.map → work-queue-qtjloIIF.js.map} +1 -1
  106. package/public/assets/workspaces-BcnSfMmi.js +3 -0
  107. package/public/assets/{workspaces-PdCwiSQx.js.map → workspaces-BcnSfMmi.js.map} +1 -1
  108. package/public/index.html +21 -21
  109. package/src/db/message-reads.ts +60 -0
  110. package/src/mcp.ts +7 -5
  111. package/src/routes/workspaces.ts +2 -2
  112. package/src/services/register-agent.ts +4 -1
  113. package/src/services/shutdown-agent.ts +24 -7
  114. package/src/services/spawn-agent.ts +15 -0
  115. package/src/spawn-command.ts +8 -0
  116. package/src/workspace-actions.ts +2 -2
  117. package/src/workspace-merge.ts +4 -1
  118. package/public/assets/PlanGraphPanel-BnYmYHnY.js +0 -2
  119. package/public/assets/PlanGraphPanel-BnYmYHnY.js.map +0 -1
  120. package/public/assets/agents-CqQhC2aN.js +0 -2
  121. package/public/assets/branch-state-badge-Dp6Jk4LH.js +0 -2
  122. package/public/assets/card-C7JtSyuM.js +0 -2
  123. package/public/assets/chat-nugo0m55.js +0 -2
  124. package/public/assets/dist-BkDVLgYg.js +0 -2
  125. package/public/assets/dist-D5y1HX8f.js +0 -2
  126. package/public/assets/dist-tX4uIBFU.js +0 -2
  127. package/public/assets/index-C0aWKi0g.css +0 -2
  128. package/public/assets/index-D--CyG66.js +0 -21
  129. package/public/assets/index-D--CyG66.js.map +0 -1
  130. package/public/assets/memory-CMdemdtb.js +0 -2
  131. package/public/assets/settings-vSYPv8kE.js +0 -10
  132. package/public/assets/settings-vSYPv8kE.js.map +0 -1
  133. package/public/assets/store-BLZA3u7Y.js.map +0 -1
  134. package/public/assets/teams-gWvyw7ET.js +0 -2
  135. package/public/assets/workspaces-PdCwiSQx.js +0 -3
package/src/mcp.ts CHANGED
@@ -307,6 +307,7 @@ const TOOLS: ToolDefinition[] = [
307
307
  effort: { type: "string", enum: VALID_EFFORTS },
308
308
  approvalMode: { type: "string", enum: APPROVAL_MODES, description: "Permission posture for the worker. Defaults to YOUR OWN approval mode when omitted (a headless `guarded` worker wedges on the first approval prompt), so a coordinator running `open` spawns workers that can act autonomously. Pass an explicit value to narrow a child (e.g. `read-only` reviewer)." },
309
309
  prompt: { type: "string", description: "Initial task/message delivered to the agent on launch — spawn and hand it its first instruction in one call (no separate follow-up message needed)." },
310
+ expectReply: { type: "boolean", description: "Require the worker to report back: it gets a pending reply obligation to you and CANNOT go idle until it delivers its result (which routes to your inbox and wakes you). Defaults true when you pass a prompt — set false for a true fire-and-forget worker that needn't report (e.g. one that only lands a branch)." },
310
311
  systemPromptAppend: { type: "string" },
311
312
  profile: { type: "string", description: "Agent profile name to apply (env, instructions, permissions, MCP/skills, spawn quota)." },
312
313
  tags: { type: "array", items: { type: "string" } },
@@ -334,15 +335,15 @@ const TOOLS: ToolDefinition[] = [
334
335
  },
335
336
  {
336
337
  name: "relay_shutdown_agent",
337
- description: "Shut down an agent through Relay's orchestrator. Gated: requires the command:shutdown scope; an agent caller may only target its OWN live spawned children. Admin tokens keep full reach.",
338
+ description: "Shut down an agent through Relay's orchestrator. Gated: requires the command:shutdown scope; an agent caller may only target its OWN live spawned children, addressed by agentId or spawnRequestId (policyName/tmuxSession are admin-only broad targets). Admin tokens keep full reach.",
338
339
  requiredScopes: ["command:shutdown"],
339
340
  inputSchema: {
340
341
  type: "object",
341
342
  properties: {
342
- agentId: { type: "string" },
343
- policyName: { type: "string" },
344
- spawnRequestId: { type: "string" },
345
- tmuxSession: { type: "string" },
343
+ agentId: { type: "string", description: "Target child by agent id. For an agent caller, agentId or spawnRequestId identifies your spawned child." },
344
+ policyName: { type: "string", description: "Broad target by managed-agent policy — admin/full-reach callers only." },
345
+ spawnRequestId: { type: "string", description: "Target child by the idempotency key relay_spawn_agent returned — resolved to your spawned child server-side." },
346
+ tmuxSession: { type: "string", description: "Broad target by tmux session — admin/full-reach callers only." },
346
347
  orchestratorId: { type: "string" },
347
348
  reason: { type: "string" },
348
349
  timeoutMs: { type: "integer", minimum: 1 },
@@ -868,6 +869,7 @@ async function relaySpawnAgent(auth: McpAuthContext, args: Record<string, unknow
868
869
  policyName: optionalString(args.policyName, "policyName", 120),
869
870
  profile: optionalString(args.profile, "profile", 120),
870
871
  prompt: optionalString(args.prompt, "prompt", 16_000),
872
+ expectReply: typeof args.expectReply === "boolean" ? args.expectReply : undefined,
871
873
  systemPromptAppend: optionalString(args.systemPromptAppend, "systemPromptAppend", 64_000),
872
874
  tags: optionalStringArray(args.tags, "tags"),
873
875
  capabilities: optionalStringArray(args.capabilities, "capabilities"),
@@ -321,8 +321,8 @@ export const postWorkspaceAction: Handler = async (req, params) => {
321
321
  detail: cleanString(parsed.body.detail, "detail", { max: 4000 }),
322
322
  metadata: cleanMeta(parsed.body.metadata) ?? {},
323
323
  // No inline fallback: an absent strategy stays undefined and the shared core
324
- // (requestWorkspaceMerge) applies DEFAULT_MERGE_STRATEGY, identically to the
325
- // MCP land tool — one resolution point, no per-surface drift (#304).
324
+ // (requestWorkspaceMerge) applies the instance-aware default, identically to
325
+ // the MCP land tool — one resolution point, no per-surface drift.
326
326
  strategy: optionalEnum(parsed.body.strategy, "strategy", LAND_STRATEGIES) as WorkspaceMergeStrategy | undefined,
327
327
  deleteBranch: typeof parsed.body.deleteBranch === "boolean" ? parsed.body.deleteBranch : undefined,
328
328
  force: parsed.body.force === true,
@@ -9,7 +9,7 @@
9
9
  // managed came-up-running reconcile (delegated to managed-running.ts), the single
10
10
  // status broadcast, the single timeline note, the spawned-child parent-wake, and
11
11
  // the first-registration audit row.
12
- import { createActivityEvent, getAgent, upsertAgent } from "../db";
12
+ import { createActivityEvent, getAgent, seedSpawnReplyObligation, upsertAgent } from "../db";
13
13
  import { emitAgentStatus } from "../sse";
14
14
  import { noteAgentTimelineEvent } from "../compaction-watch";
15
15
  import { notifyAgentReady } from "../agent-lifecycle-events";
@@ -59,6 +59,9 @@ export function registerAgent(input: RegisterAgentInput, ctx: AuthContext): Agen
59
59
  if (agent.ready && !existing?.ready) notifyAgentReady(agent.id);
60
60
 
61
61
  if (!existing) {
62
+ // #413 — a spawned worker with a report-back contract gets a pending reply obligation to its
63
+ // spawner so it can't idle with its verdict undelivered (vent #121). First-registration only.
64
+ seedSpawnReplyObligation(agent.id, agent.spawnedBy, metaStr(agent.meta, "spawnRequestId"));
62
65
  createActivityEvent({
63
66
  clientId: `server-agent-${agent.id}-registered`,
64
67
  kind: "state",
@@ -30,6 +30,7 @@ import {
30
30
  createActivityEvent,
31
31
  getAgent,
32
32
  getOrchestrator,
33
+ listAgents,
33
34
  mergeAgentMeta,
34
35
  } from "../db";
35
36
  import { createCommand } from "../commands-db";
@@ -106,16 +107,32 @@ export function authorizeShutdown(ctx: AuthContext, input: ShutdownAgentInput):
106
107
  const callerId = ctx.callerAgentId;
107
108
  // Full reach: admin/server/system (no resolved caller identity) and multi-agent tokens.
108
109
  if (!callerId) return;
109
- // A scoped agent caller may target only its OWN live spawned children, addressed by
110
- // agentId. Broad targeting (policy/spawnRequestId/tmux) and cross-agent kills stay
111
- // full-reach-only otherwise spawn permission silently becomes kill-anyone permission.
112
- if (!input.agentId || input.policyName || input.spawnRequestId || input.tmuxSession) {
113
- throw new ShutdownAuthError("agents may only shut down their own spawned children, addressed by agentId");
110
+ // A scoped agent caller may target only its OWN live spawned children. Two PRECISE
111
+ // self-id keys the parent already holds resolve to a single child and pass the same
112
+ // `spawnedBy` ownership check: `agentId` and `spawnRequestId` (the idempotency key
113
+ // `relay_spawn_agent` accepts + returns; stored on the child's `meta.spawnRequestId`).
114
+ // #115: spawnRequestId was wrongly lumped with the genuinely-broad targets, forcing a
115
+ // parent to look up an agentId it didn't need. Broad targeting (`policyName`/`tmuxSession`)
116
+ // can match agents the caller never spawned, or several at once, so it stays full-reach-only
117
+ // — otherwise spawn permission silently becomes kill-anyone permission.
118
+ if (input.policyName || input.tmuxSession || (!input.agentId && !input.spawnRequestId)) {
119
+ throw new ShutdownAuthError(
120
+ "agents may only shut down their own spawned children, addressed by agentId or spawnRequestId",
121
+ );
114
122
  }
115
- const target = getAgent(input.agentId);
123
+ const target = input.agentId
124
+ ? getAgent(input.agentId)
125
+ : listAgents().find((a) => a.meta?.spawnRequestId === input.spawnRequestId);
116
126
  if (!target || target.spawnedBy !== callerId) {
117
- throw new ShutdownAuthError(`agent ${input.agentId} is not one of your spawned children`);
127
+ throw new ShutdownAuthError(
128
+ input.agentId
129
+ ? `agent ${input.agentId} is not one of your spawned children`
130
+ : `no spawned child of yours matches spawnRequestId ${input.spawnRequestId}`,
131
+ );
118
132
  }
133
+ // Normalize to the resolved agentId so the rest of the service (orchestrator resolution,
134
+ // lifecycle pill, audit row) works on a concrete agent uniformly for both key forms.
135
+ input.agentId = target.id;
119
136
  }
120
137
 
121
138
  /** Resolve the online control orchestrator for the target — the canonical resolver,
@@ -62,6 +62,15 @@ export interface SpawnAgentInput {
62
62
  profile?: string;
63
63
  prompt?: string;
64
64
  systemPromptAppend?: string;
65
+ /**
66
+ * #413 — does this spawn carry a report-back contract? When true, relay seeds a pending
67
+ * reply obligation from the spawner to the child at registration, so the child can't go
68
+ * idle until it delivers its result (vent #121). Defaults true for an agent-initiated spawn
69
+ * that hands the child a prompt (a coordinator handing a worker a task almost always wants
70
+ * the result back); off for system/dashboard/automation spawns (no caller to report to).
71
+ * Pass false to opt a fire-and-forget agent spawn out.
72
+ */
73
+ expectReply?: boolean;
65
74
  tags?: string[];
66
75
  capabilities?: string[];
67
76
  providerArgs?: string[];
@@ -204,6 +213,11 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
204
213
  ...(callerTeam ? { teamId: callerTeam.id } : {}),
205
214
  });
206
215
 
216
+ // #413 — default the report-back obligation ON for an agent coordinator handing a worker a
217
+ // task (callerId + a prompt); OFF for system/dashboard/automation spawns (no caller to report
218
+ // back to). Explicit input wins, so a coordinator can opt a fire-and-forget worker out.
219
+ const expectReply = input.expectReply ?? Boolean(callerId && input.prompt && input.prompt.trim());
220
+
207
221
  const command = createCommand({
208
222
  type: "agent.spawn",
209
223
  source: "system",
@@ -225,6 +239,7 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
225
239
  providerArgs: input.providerArgs ?? [],
226
240
  prompt: input.prompt,
227
241
  systemPromptAppend: input.systemPromptAppend,
242
+ ...(expectReply ? { expectReply } : {}),
228
243
  policyName: input.policyName,
229
244
  spawnRequestId,
230
245
  env,
@@ -91,6 +91,13 @@ interface BuildSpawnCommandOptions {
91
91
  providerArgs?: string[];
92
92
  prompt?: string;
93
93
  systemPromptAppend?: string;
94
+ /**
95
+ * #413 — when true, the child registering with this spawnRequestId gets a pending reply
96
+ * obligation back to its spawner, so the Stop hook refuses to let it idle until it delivers
97
+ * its result (closes the "spawned worker strands its verdict" gap, vent #121). Read at
98
+ * registration from the persisted spawn command params.
99
+ */
100
+ expectReply?: boolean;
94
101
  profile?: string;
95
102
  agentProfile?: unknown;
96
103
  headless?: boolean;
@@ -138,6 +145,7 @@ export function buildSpawnCommand(opts: BuildSpawnCommandOptions): Record<string
138
145
  ...def(opts.providerArgs, "providerArgs"),
139
146
  ...def(opts.prompt, "prompt"),
140
147
  ...def(opts.systemPromptAppend, "systemPromptAppend"),
148
+ ...def(opts.expectReply, "expectReply"),
141
149
  ...def(opts.headless, "headless"),
142
150
  ...def(opts.policyName, "policyName"),
143
151
  ...def(opts.automationId, "automationId"),
@@ -167,8 +167,8 @@ export function applyWorkspaceAction(workspace: WorkspaceRecord, input: ApplyWor
167
167
  const result = requestWorkspaceMerge(workspace, {
168
168
  requestedBy: agentId ?? "dashboard",
169
169
  // Pass the strategy through verbatim (undefined when unset) — the single
170
- // default lives in requestWorkspaceMerge, so both land surfaces resolve it
171
- // identically instead of each applying its own fallback (#304).
170
+ // config-aware default lives in requestWorkspaceMerge, so land surfaces
171
+ // resolve it identically instead of each applying its own fallback.
172
172
  strategy: input.strategy,
173
173
  deleteBranch: input.deleteBranch !== false,
174
174
  prTitle: input.prTitle,
@@ -176,7 +176,10 @@ export function requestWorkspaceMerge(workspace: WorkspaceRecord, opts: RequestW
176
176
  releaseMergeLease({ repoRoot: workspace.repoRoot, workspaceId: workspace.id });
177
177
  return { ok: false, status: 404, error: "workspace not found" };
178
178
  }
179
- const effectiveStrategy = opts.strategy ?? DEFAULT_MERGE_STRATEGY;
179
+ const effectiveStrategy = resolveLandStrategy({
180
+ explicit: opts.strategy,
181
+ instanceStrategy: getLandingConfig().strategy,
182
+ });
180
183
 
181
184
  // Slice 6 — issue auto-linkage: append "Closes #N" to the PR body when the
182
185
  // workspace metadata carries an issue number, WITHOUT clobbering an explicit body.
@@ -1,2 +0,0 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{Un as t,jn as n,kn as r,xt as i}from"./lucide-react-ChOGD4vc.js";import{n as a,r as o,t as s}from"./store-BLZA3u7Y.js";var c=e(t(),1),l=n(),u=196,d=68,f=52,p=16,m=14,h=[`landed`,`in-progress`,`pending`,`blocked`],g={landed:{label:`landed`,dot:`bg-emerald-400`,accent:`border-l-emerald-400`,text:`text-emerald-300`,wire:`#34d399`},"in-progress":{label:`in progress`,dot:`bg-sky-400`,accent:`border-l-sky-400`,text:`text-sky-300`,wire:`#38bdf8`},pending:{label:`pending`,dot:`bg-amber-400`,accent:`border-l-amber-400`,text:`text-amber-300`,wire:`#fbbf24`},blocked:{label:`blocked`,dot:`bg-red-400`,accent:`border-l-red-400`,text:`text-red-300`,wire:`#f87171`}};function _(e){return e?e.label||(e.policyName?`policy:${e.policyName}`:e.agentId||``):``}function v(e){let t=new Map(e.nodes.map(e=>[e.id,e])),n=new Map(e.nodes.map((e,t)=>[e.id,t])),r=new Map,i=new Map(e.nodes.map(e=>[e.id,0]));for(let n of e.edges)!t.has(n.from)||!t.has(n.to)||(r.set(n.from,[...r.get(n.from)??[],n.to]),i.set(n.to,(i.get(n.to)??0)+1));let a=new Map(e.nodes.map(e=>[e.id,0])),o=e.nodes.filter(e=>(i.get(e.id)??0)===0).map(e=>e.id),s=new Set;for(;o.length;){let e=o.shift();s.add(e);let t=a.get(e)??0;for(let n of r.get(e)??[])a.set(n,Math.max(a.get(n)??0,t+1)),i.set(n,(i.get(n)??0)-1),(i.get(n)??0)===0&&o.push(n)}let c=Math.max(0,...Array.from(a.values()))+1;for(let t of e.nodes)s.has(t.id)||a.set(t.id,c++);let l=new Map;for(let t of e.nodes){let e=a.get(t.id)??0;l.set(e,[...l.get(e)??[],t])}let h=[...l.entries()].sort(([e],[t])=>e-t),g=Math.max(1,...h.map(([,e])=>e.length)),_=d+p,v=[];h.forEach(([e,t],r)=>{let i=[...t].sort((e,t)=>(e.lane||``).localeCompare(t.lane||``)||(n.get(e.id)??0)-(n.get(t.id)??0)),a=(g-i.length)*_/2;i.forEach((t,n)=>{v.push({node:t,layer:e,x:m+r*(u+f),y:m+a+n*_})})});let y=h.length;return{nodes:v,width:Math.max(320,m*2+y*u+Math.max(0,y-1)*f),height:Math.max(d+m*2,m*2+g*d+Math.max(0,g-1)*p)}}function y(e,t){let n=e.x+u,r=e.y+d/2,i=t.x,a=t.y+d/2,o=n+Math.max(20,(i-n)/2);return`M ${n} ${r} C ${o} ${r}, ${o} ${a}, ${i} ${a}`}function b({threadId:e,teamId:t,channel:n}){let f=t?o(t,n):e?a(e,n):``,p=s(e=>t?e.plansByTeam[f]:f?e.plansByThread[f]:null),m=s(e=>e.fetchPlan);(0,c.useEffect)(()=>{if(t){m({teamId:t,channel:n});return}e&&m({threadId:e,channel:n})},[n,m,t,e]);let b=(0,c.useMemo)(()=>p?v(p):null,[p]),x=(0,c.useMemo)(()=>new Map(b?.nodes.map(e=>[e.node.id,e])??[]),[b]),S=(0,c.useMemo)(()=>{if(!p)return[];let e=new Map;for(let t of p.nodes)e.set(t.status,(e.get(t.status)??0)+1);return h.filter(t=>e.has(t)).map(t=>({status:t,count:e.get(t)??0}))},[p]);return!p||!b?null:(0,l.jsxs)(`section`,{className:`shrink-0 border-b border-border bg-card/45 px-3 py-2`,children:[(0,l.jsxs)(`div`,{className:`mb-2 flex min-w-0 items-center gap-2`,children:[(0,l.jsx)(`span`,{className:`flex h-5 w-5 shrink-0 items-center justify-center rounded bg-muted/60`,children:(0,l.jsx)(i,{className:`h-3 w-3 text-muted-foreground`})}),(0,l.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,l.jsx)(`div`,{className:`truncate text-[13px] font-semibold leading-tight text-foreground`,children:p.title||`Plan`}),p.objective&&(0,l.jsx)(`div`,{className:`truncate text-[11px] leading-tight text-muted-foreground`,children:p.objective})]}),S.length>0&&(0,l.jsx)(`div`,{className:`hidden shrink-0 items-center gap-2.5 sm:flex`,children:S.map(({status:e,count:t})=>(0,l.jsxs)(`span`,{className:`flex items-center gap-1 text-[10px] text-muted-foreground`,children:[(0,l.jsx)(`span`,{className:r(`h-1.5 w-1.5 rounded-full`,g[e].dot)}),(0,l.jsx)(`span`,{className:r(`font-medium tabular-nums`,g[e].text),children:t}),(0,l.jsx)(`span`,{children:g[e].label})]},e))}),(0,l.jsxs)(`span`,{className:`shrink-0 rounded bg-muted/60 px-1.5 py-0.5 text-[10px] font-medium tabular-nums text-muted-foreground`,children:[`v`,p.version]})]}),p.nodes.length===0?(0,l.jsx)(`div`,{className:`rounded-md border border-dashed border-border px-3 py-3 text-center text-xs text-muted-foreground`,children:`No nodes yet — the plan graph fills in as the team is composed.`}):(0,l.jsx)(`div`,{className:`max-h-[min(46vh,360px)] overflow-auto`,children:(0,l.jsxs)(`div`,{className:`relative`,style:{width:b.width,height:b.height},children:[(0,l.jsxs)(`svg`,{className:`pointer-events-none absolute inset-0`,width:b.width,height:b.height,"aria-hidden":`true`,children:[(0,l.jsx)(`defs`,{children:h.map(e=>(0,l.jsx)(`marker`,{id:`plan-arrow-${e}`,viewBox:`0 0 8 8`,refX:`6.5`,refY:`4`,markerWidth:`6`,markerHeight:`6`,orient:`auto-start-reverse`,children:(0,l.jsx)(`path`,{d:`M0 0 L8 4 L0 8 z`,fill:g[e].wire})},e))}),p.edges.map(e=>{let t=x.get(e.from),n=x.get(e.to);if(!t||!n)return null;let r=g[t.node.status];return(0,l.jsx)(`path`,{d:y(t,n),stroke:r.wire,strokeOpacity:.7,strokeWidth:2,fill:`none`,strokeLinecap:`round`,markerEnd:`url(#plan-arrow-${t.node.status})`},`${e.from}->${e.to}`)})]}),b.nodes.map(({node:e,x:t,y:n})=>{let i=g[e.status],a=_(e.ownerRef);return(0,l.jsxs)(`article`,{className:r(`group absolute flex flex-col justify-between rounded-md border border-l-[3px] bg-background/95 p-2`,`shadow-sm transition-all hover:-translate-y-px hover:border-border hover:shadow-md hover:bg-background`,i.accent),style:{left:t,top:n,width:u,height:d},title:e.scopeBlurb||e.label,children:[(0,l.jsx)(`div`,{className:`truncate text-xs font-semibold leading-tight text-foreground`,children:e.label}),(e.scopeBlurb||e.id)&&(0,l.jsx)(`div`,{className:`truncate text-[10px] leading-tight text-muted-foreground`,children:e.scopeBlurb||e.id}),(0,l.jsxs)(`div`,{className:`flex min-w-0 items-center justify-between gap-1.5`,children:[(0,l.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1.5`,children:[(0,l.jsx)(`span`,{className:r(`h-1.5 w-1.5 shrink-0 rounded-full`,i.dot)}),(0,l.jsx)(`span`,{className:r(`text-[10px] font-medium`,i.text),children:i.label})]}),(0,l.jsxs)(`div`,{className:`flex min-w-0 items-center gap-1.5`,children:[a&&(0,l.jsx)(`span`,{className:`truncate text-[10px] text-muted-foreground`,children:a}),e.lane&&(0,l.jsx)(`span`,{className:`shrink-0 rounded-sm bg-muted/70 px-1 py-px text-[9px] font-medium uppercase tracking-wide text-muted-foreground`,children:e.lane})]})]})]},e.id)})]})})]})}export{b as t};
2
- //# sourceMappingURL=PlanGraphPanel-BnYmYHnY.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PlanGraphPanel-BnYmYHnY.js","names":[],"sources":["../../dashboard/src/components/chat/PlanGraphPanel.tsx"],"sourcesContent":["import { useEffect, useMemo } from 'react'\nimport { GitBranch } from 'lucide-react'\nimport { useRelayStore } from '@/store'\nimport type { Plan, PlanNode, PlanOwnerRef, PlanStatus } from '@/types'\nimport { cn } from '@/lib/utils'\nimport { planLookupKey, planTeamLookupKey } from '@/store/slices/plans'\n\n// Left-to-right DAG: dependency depth flows along x (sequential gates), nodes\n// that share a depth stack along y (parallel lanes). This keeps the panel SHORT\n// — it's an operator overlay above the chat, not a full view — and lets the\n// gate-vs-lane structure read at a glance. Height is capped + scrollable below.\nconst NODE_W = 196\nconst NODE_H = 68\nconst COL_GAP = 52\nconst ROW_GAP = 16\nconst PAD = 14\n\nconst STATUS_ORDER: PlanStatus[] = ['landed', 'in-progress', 'pending', 'blocked']\n\nconst STATUS_STYLE: Record<\n PlanStatus,\n { label: string; dot: string; accent: string; text: string; wire: string }\n> = {\n landed: { label: 'landed', dot: 'bg-emerald-400', accent: 'border-l-emerald-400', text: 'text-emerald-300', wire: '#34d399' },\n 'in-progress': { label: 'in progress', dot: 'bg-sky-400', accent: 'border-l-sky-400', text: 'text-sky-300', wire: '#38bdf8' },\n pending: { label: 'pending', dot: 'bg-amber-400', accent: 'border-l-amber-400', text: 'text-amber-300', wire: '#fbbf24' },\n blocked: { label: 'blocked', dot: 'bg-red-400', accent: 'border-l-red-400', text: 'text-red-300', wire: '#f87171' },\n}\n\ninterface LayoutNode {\n node: PlanNode\n x: number\n y: number\n layer: number\n}\n\nfunction ownerLabel(owner?: PlanOwnerRef): string {\n if (!owner) return ''\n return owner.label || (owner.policyName ? `policy:${owner.policyName}` : owner.agentId || '')\n}\n\nfunction layerPlan(plan: Plan): { nodes: LayoutNode[]; width: number; height: number } {\n const nodeById = new Map(plan.nodes.map((node) => [node.id, node]))\n const indexById = new Map(plan.nodes.map((node, index) => [node.id, index]))\n const outgoing = new Map<string, string[]>()\n const indegree = new Map(plan.nodes.map((node) => [node.id, 0]))\n for (const edge of plan.edges) {\n if (!nodeById.has(edge.from) || !nodeById.has(edge.to)) continue\n outgoing.set(edge.from, [...(outgoing.get(edge.from) ?? []), edge.to])\n indegree.set(edge.to, (indegree.get(edge.to) ?? 0) + 1)\n }\n\n const layerById = new Map(plan.nodes.map((node) => [node.id, 0]))\n const queue = plan.nodes\n .filter((node) => (indegree.get(node.id) ?? 0) === 0)\n .map((node) => node.id)\n const visited = new Set<string>()\n\n while (queue.length) {\n const id = queue.shift()!\n visited.add(id)\n const fromLayer = layerById.get(id) ?? 0\n for (const to of outgoing.get(id) ?? []) {\n layerById.set(to, Math.max(layerById.get(to) ?? 0, fromLayer + 1))\n indegree.set(to, (indegree.get(to) ?? 0) - 1)\n if ((indegree.get(to) ?? 0) === 0) queue.push(to)\n }\n }\n\n let fallbackLayer = Math.max(0, ...Array.from(layerById.values())) + 1\n for (const node of plan.nodes) {\n if (visited.has(node.id)) continue\n layerById.set(node.id, fallbackLayer++)\n }\n\n const layers = new Map<number, PlanNode[]>()\n for (const node of plan.nodes) {\n const layer = layerById.get(node.id) ?? 0\n layers.set(layer, [...(layers.get(layer) ?? []), node])\n }\n\n const orderedLayers = [...layers.entries()].sort(([a], [b]) => a - b)\n const maxRows = Math.max(1, ...orderedLayers.map(([, nodes]) => nodes.length))\n const rowPitch = NODE_H + ROW_GAP\n\n const layoutNodes: LayoutNode[] = []\n orderedLayers.forEach(([layer, nodes], col) => {\n const ordered = [...nodes].sort((a, b) => {\n const lane = (a.lane || '').localeCompare(b.lane || '')\n return lane || ((indexById.get(a.id) ?? 0) - (indexById.get(b.id) ?? 0))\n })\n // Center each column vertically against the tallest column so the spine\n // runs through the middle and the parallel fan reads as a fan.\n const offset = ((maxRows - ordered.length) * rowPitch) / 2\n ordered.forEach((node, row) => {\n layoutNodes.push({\n node,\n layer,\n x: PAD + col * (NODE_W + COL_GAP),\n y: PAD + offset + row * rowPitch,\n })\n })\n })\n\n const cols = orderedLayers.length\n return {\n nodes: layoutNodes,\n width: Math.max(320, PAD * 2 + cols * NODE_W + Math.max(0, cols - 1) * COL_GAP),\n height: Math.max(NODE_H + PAD * 2, PAD * 2 + maxRows * NODE_H + Math.max(0, maxRows - 1) * ROW_GAP),\n }\n}\n\nfunction edgePath(from: LayoutNode, to: LayoutNode): string {\n const x1 = from.x + NODE_W\n const y1 = from.y + NODE_H / 2\n const x2 = to.x\n const y2 = to.y + NODE_H / 2\n const midX = x1 + Math.max(20, (x2 - x1) / 2)\n return `M ${x1} ${y1} C ${midX} ${y1}, ${midX} ${y2}, ${x2} ${y2}`\n}\n\nexport function PlanGraphPanel({ threadId, teamId, channel }: { threadId?: string | number | null; teamId?: string | null; channel?: string }) {\n const key = teamId ? planTeamLookupKey(teamId, channel) : threadId ? planLookupKey(threadId, channel) : ''\n const plan = useRelayStore((s) => teamId ? s.plansByTeam[key] : key ? s.plansByThread[key] : null)\n const fetchPlan = useRelayStore((s) => s.fetchPlan)\n\n useEffect(() => {\n if (teamId) {\n void fetchPlan({ teamId, channel })\n return\n }\n if (threadId) void fetchPlan({ threadId, channel })\n }, [channel, fetchPlan, teamId, threadId])\n\n const layout = useMemo(() => plan ? layerPlan(plan) : null, [plan])\n const nodeById = useMemo(() => new Map(layout?.nodes.map((node) => [node.node.id, node]) ?? []), [layout])\n\n const legend = useMemo(() => {\n if (!plan) return []\n const counts = new Map<PlanStatus, number>()\n for (const node of plan.nodes) counts.set(node.status, (counts.get(node.status) ?? 0) + 1)\n return STATUS_ORDER.filter((status) => counts.has(status)).map((status) => ({\n status,\n count: counts.get(status) ?? 0,\n }))\n }, [plan])\n\n if (!plan || !layout) return null\n\n return (\n <section className=\"shrink-0 border-b border-border bg-card/45 px-3 py-2\">\n <div className=\"mb-2 flex min-w-0 items-center gap-2\">\n <span className=\"flex h-5 w-5 shrink-0 items-center justify-center rounded bg-muted/60\">\n <GitBranch className=\"h-3 w-3 text-muted-foreground\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-[13px] font-semibold leading-tight text-foreground\">{plan.title || 'Plan'}</div>\n {plan.objective && <div className=\"truncate text-[11px] leading-tight text-muted-foreground\">{plan.objective}</div>}\n </div>\n {legend.length > 0 && (\n <div className=\"hidden shrink-0 items-center gap-2.5 sm:flex\">\n {legend.map(({ status, count }) => (\n <span key={status} className=\"flex items-center gap-1 text-[10px] text-muted-foreground\">\n <span className={cn('h-1.5 w-1.5 rounded-full', STATUS_STYLE[status].dot)} />\n <span className={cn('font-medium tabular-nums', STATUS_STYLE[status].text)}>{count}</span>\n <span>{STATUS_STYLE[status].label}</span>\n </span>\n ))}\n </div>\n )}\n <span className=\"shrink-0 rounded bg-muted/60 px-1.5 py-0.5 text-[10px] font-medium tabular-nums text-muted-foreground\">\n v{plan.version}\n </span>\n </div>\n {plan.nodes.length === 0 ? (\n <div className=\"rounded-md border border-dashed border-border px-3 py-3 text-center text-xs text-muted-foreground\">\n No nodes yet — the plan graph fills in as the team is composed.\n </div>\n ) : (\n <div className=\"max-h-[min(46vh,360px)] overflow-auto\">\n <div className=\"relative\" style={{ width: layout.width, height: layout.height }}>\n <svg className=\"pointer-events-none absolute inset-0\" width={layout.width} height={layout.height} aria-hidden=\"true\">\n <defs>\n {STATUS_ORDER.map((status) => (\n <marker\n key={status}\n id={`plan-arrow-${status}`}\n viewBox=\"0 0 8 8\"\n refX=\"6.5\"\n refY=\"4\"\n markerWidth=\"6\"\n markerHeight=\"6\"\n orient=\"auto-start-reverse\"\n >\n <path d=\"M0 0 L8 4 L0 8 z\" fill={STATUS_STYLE[status].wire} />\n </marker>\n ))}\n </defs>\n {plan.edges.map((edge) => {\n const from = nodeById.get(edge.from)\n const to = nodeById.get(edge.to)\n if (!from || !to) return null\n const wire = STATUS_STYLE[from.node.status]\n return (\n <path\n key={`${edge.from}->${edge.to}`}\n d={edgePath(from, to)}\n stroke={wire.wire}\n strokeOpacity={0.7}\n strokeWidth={2}\n fill=\"none\"\n strokeLinecap=\"round\"\n markerEnd={`url(#plan-arrow-${from.node.status})`}\n />\n )\n })}\n </svg>\n {layout.nodes.map(({ node, x, y }) => {\n const status = STATUS_STYLE[node.status]\n const owner = ownerLabel(node.ownerRef)\n return (\n <article\n key={node.id}\n className={cn(\n 'group absolute flex flex-col justify-between rounded-md border border-l-[3px] bg-background/95 p-2',\n 'shadow-sm transition-all hover:-translate-y-px hover:border-border hover:shadow-md hover:bg-background',\n status.accent,\n )}\n style={{ left: x, top: y, width: NODE_W, height: NODE_H }}\n title={node.scopeBlurb || node.label}\n >\n <div className=\"truncate text-xs font-semibold leading-tight text-foreground\">{node.label}</div>\n {(node.scopeBlurb || node.id) && (\n <div className=\"truncate text-[10px] leading-tight text-muted-foreground\">{node.scopeBlurb || node.id}</div>\n )}\n <div className=\"flex min-w-0 items-center justify-between gap-1.5\">\n <div className=\"flex shrink-0 items-center gap-1.5\">\n <span className={cn('h-1.5 w-1.5 shrink-0 rounded-full', status.dot)} />\n <span className={cn('text-[10px] font-medium', status.text)}>{status.label}</span>\n </div>\n <div className=\"flex min-w-0 items-center gap-1.5\">\n {owner && <span className=\"truncate text-[10px] text-muted-foreground\">{owner}</span>}\n {node.lane && (\n <span className=\"shrink-0 rounded-sm bg-muted/70 px-1 py-px text-[9px] font-medium uppercase tracking-wide text-muted-foreground\">\n {node.lane}\n </span>\n )}\n </div>\n </div>\n </article>\n )\n })}\n </div>\n </div>\n )}\n </section>\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,Dt as n,Ft as r,G as i,I as a,J as o,P as s,Tn as c,Un as l,bn as u,g as d,i as f,jn as p,kn as m,l as h,m as g,ot as _}from"./lucide-react-ChOGD4vc.js";import{o as v,t as y}from"./store-BLZA3u7Y.js";import{B as b,G as x,H as ee,W as te,a as S,d as C,i as ne,n as re}from"./display-CXhnBwGf.js";import{o as w,r as T}from"./dist-CSISzAHD.js";import{t as E}from"./dist-DvLO--_O.js";import{i as D,n as O}from"./dist-MdPDPcyo.js";import{t as k}from"./dist-BiVJ8IWp.js";import{t as A}from"./dist-BIAvrITs.js";import{a as j,i as M,n as N,o as P,r as ie,s as ae,t as F}from"./es2015-Cu7l1536.js";import{a as I,i as oe,n as se,r as L,t as R}from"./dist-svixSeDF.js";import{t as z}from"./badge-BR4bvEsy.js";import{t as B}from"./button-BwqJZS4O.js";import{t as ce}from"./copy-button-nbDhTE0M.js";import{B as le,H as V,P as ue,S as H,U,V as W,d as de,g as fe,h as pe,l as me,m as he,p as ge,u as _e,x as G}from"./index-D--CyG66.js";import{n as ve,t as ye}from"./card-C7JtSyuM.js";import{n as be,t as xe}from"./branch-state-badge-Dp6Jk4LH.js";var K=e(l(),1),q=p(),J=`Popover`,[Se,Ce]=D(J,[I]),Y=I(),[we,X]=Se(J),Te=e=>{let{__scopePopover:t,children:n,open:r,defaultOpen:i,onOpenChange:a,modal:o=!1}=e,s=Y(t),c=K.useRef(null),[l,u]=K.useState(!1),[d,f]=k({prop:r,defaultProp:i??!1,onChange:a,caller:J});return(0,q.jsx)(oe,{...s,children:(0,q.jsx)(we,{scope:t,contentId:ae(),triggerRef:c,open:d,onOpenChange:f,onOpenToggle:K.useCallback(()=>f(e=>!e),[f]),hasCustomAnchor:l,onCustomAnchorAdd:K.useCallback(()=>u(!0),[]),onCustomAnchorRemove:K.useCallback(()=>u(!1),[]),modal:o,children:n})})};Te.displayName=J;var Ee=`PopoverAnchor`,De=K.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=X(Ee,n),a=Y(n),{onCustomAnchorAdd:o,onCustomAnchorRemove:s}=i;return K.useEffect(()=>(o(),()=>s()),[o,s]),(0,q.jsx)(R,{...a,...r,ref:t})});De.displayName=Ee;var Oe=`PopoverTrigger`,ke=K.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=X(Oe,n),a=Y(n),o=w(t,i.triggerRef),s=(0,q.jsx)(E.button,{type:`button`,"aria-haspopup":`dialog`,"aria-expanded":i.open,"aria-controls":i.contentId,"data-state":Ve(i.open),...r,ref:o,onClick:O(e.onClick,i.onOpenToggle)});return i.hasCustomAnchor?s:(0,q.jsx)(R,{asChild:!0,...a,children:s})});ke.displayName=Oe;var Z=`PopoverPortal`,[Ae,je]=Se(Z,{forceMount:void 0}),Me=e=>{let{__scopePopover:t,forceMount:n,children:r,container:i}=e,a=X(Z,t);return(0,q.jsx)(Ae,{scope:t,forceMount:n,children:(0,q.jsx)(A,{present:n||a.open,children:(0,q.jsx)(M,{asChild:!0,container:i,children:r})})})};Me.displayName=Z;var Q=`PopoverContent`,Ne=K.forwardRef((e,t)=>{let n=je(Q,e.__scopePopover),{forceMount:r=n.forceMount,...i}=e,a=X(Q,e.__scopePopover);return(0,q.jsx)(A,{present:r||a.open,children:a.modal?(0,q.jsx)(Fe,{...i,ref:t}):(0,q.jsx)(Ie,{...i,ref:t})})});Ne.displayName=Q;var Pe=T(`PopoverContent.RemoveScroll`),Fe=K.forwardRef((e,t)=>{let n=X(Q,e.__scopePopover),r=K.useRef(null),i=w(t,r),a=K.useRef(!1);return K.useEffect(()=>{let e=r.current;if(e)return F(e)},[]),(0,q.jsx)(N,{as:Pe,allowPinchZoom:!0,children:(0,q.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=K.forwardRef((e,t)=>{let n=X(Q,e.__scopePopover),r=K.useRef(!1),i=K.useRef(!1);return(0,q.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=K.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=X(Q,n),p=Y(n);return ie(),(0,q.jsx)(j,{asChild:!0,loop:!0,trapped:r,onMountAutoFocus:i,onUnmountAutoFocus:a,children:(0,q.jsx)(P,{asChild:!0,disableOutsidePointerEvents:o,onInteractOutside:u,onEscapeKeyDown:s,onPointerDownOutside:c,onFocusOutside:l,onDismiss:()=>f.onOpenChange(!1),children:(0,q.jsx)(L,{"data-state":Ve(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)`}})})})}),$=`PopoverClose`,Re=K.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=X($,n);return(0,q.jsx)(E.button,{type:`button`,...r,ref:t,onClick:O(e.onClick,()=>i.onOpenChange(!1))})});Re.displayName=$;var ze=`PopoverArrow`,Be=K.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=Y(n);return(0,q.jsx)(se,{...i,...r,ref:t})});Be.displayName=ze;function Ve(e){return e?`open`:`closed`}var He=Te,Ue=ke,We=Me,Ge=Ne;function Ke({...e}){return(0,q.jsx)(He,{"data-slot":`popover`,...e})}function qe({...e}){return(0,q.jsx)(Ue,{"data-slot":`popover-trigger`,...e})}function Je({className:e,align:t=`center`,sideOffset:n=4,...r}){return(0,q.jsx)(We,{children:(0,q.jsx)(Ge,{"data-slot":`popover-content`,align:t,sideOffset:n,className:m(`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 Ye({className:e,...t}){return(0,q.jsx)(`div`,{"data-slot":`popover-header`,className:m(`flex flex-col gap-0.5 text-sm`,e),...t})}function Xe({className:e,...t}){return(0,q.jsx)(`div`,{"data-slot":`popover-title`,className:m(`font-medium`,e),...t})}function Ze({agent:e,childAgents:a=[],parentAgent:c}){let l=v();y(e=>e.set);let u=y(e=>e.switchView),f=y(e=>e.openInboxThread),p=y(e=>e.openAgentDetail),m=y(e=>e.openPairInvite),w=y(e=>e.openRename),T=y(e=>e.openConfirm),E=y(e=>e.doAgentAction),D=y(e=>e.doDeleteAgent),O=y(e=>e.openFilesForAgent),k=y(e=>e.workspaceAction),A=y(e=>e.openWorkspaceFocus),{terminalOpen:j,terminalTarget:M,terminalOpening:N,openTerminal:P,closeTerminal:ie}=be(e.id),ae=le(),F=ne(l,e,ue(e),ae[e.id]||null),I=S(e,`shutdown`),oe=S(e,`compact`),se=S(e,`clearContext`),L=!!(e.providerCapabilities?.terminal?.live?.read||e.providerCapabilities?.terminal?.attach?.create),R=!!(e.providerCapabilities?.terminal?.live?.write||e.providerCapabilities?.model?.provider===`claude`),V=re(e),U=c?C(c):e.spawnedBy,W=a.length>0;return(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(ye,{className:`group hover:border-zinc-600 transition-colors cursor-pointer`,onClick:()=>p(e),children:(0,q.jsxs)(ve,{className:`p-4`,children:[(0,q.jsxs)(`div`,{className:`flex items-start gap-2.5 mb-2.5`,children:[(0,q.jsx)(H,{agent:e,now:l,className:`mt-0.5`}),(0,q.jsx)(G,{agent:e}),(0,q.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,q.jsx)(`div`,{className:`text-sm font-medium truncate`,children:C(e)}),(0,q.jsx)(`div`,{className:`text-xs mt-0.5 ${te(F.tone)}`,children:F.label}),typeof e.meta?.cwd==`string`&&e.meta.cwd&&(0,q.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:b(e.meta.cwd)})]}),e.branchState&&e.branchWorkspaceId&&(0,q.jsx)(xe,{state:e.branchState,className:`mt-0.5 shrink-0`,onClick:t=>{t.stopPropagation(),A(e.branchWorkspaceId)}})]}),F.badges.length>0&&(0,q.jsx)(`div`,{className:`flex flex-wrap gap-1 mb-2`,children:F.badges.map(e=>(0,q.jsx)(`span`,{className:`text-[10px] px-1.5 py-0.5 rounded-full font-medium ${e.className}`,children:e.label},e.label))}),(W||e.spawnedBy&&U)&&(0,q.jsxs)(`div`,{className:`mb-2 flex flex-wrap gap-1.5`,onClick:e=>e.stopPropagation(),children:[W&&(0,q.jsxs)(Ke,{children:[(0,q.jsx)(qe,{asChild:!0,children:(0,q.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:`${a.length} live child ${a.length===1?`agent`:`agents`}`,children:[(0,q.jsx)(h,{className:`h-3 w-3`}),(0,q.jsx)(`span`,{children:a.length}),(0,q.jsx)(`span`,{className:`flex -space-x-1`,children:a.slice(0,4).map(e=>(0,q.jsx)(H,{agent:e,now:l,className:`h-2 w-2 ring-1 ring-background`},e.id))})]})}),(0,q.jsxs)(Je,{align:`start`,className:`w-80`,onClick:e=>e.stopPropagation(),children:[(0,q.jsx)(Ye,{children:(0,q.jsx)(Xe,{children:`Team`})}),(0,q.jsx)(`div`,{className:`space-y-1.5`,children:a.map(e=>(0,q.jsxs)(`div`,{className:`rounded-md border border-border bg-card/60 p-2`,children:[(0,q.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,q.jsx)(H,{agent:e,now:l,className:`mt-1`}),(0,q.jsx)(G,{agent:e}),(0,q.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,q.jsx)(`div`,{className:`truncate text-xs font-medium`,children:C(e)}),(0,q.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,q.jsx)(z,{variant:`outline`,className:`h-4 px-1.5 text-[9px]`,children:e.status})]}),(0,q.jsxs)(`div`,{className:`mt-2 flex gap-1`,children:[(0,q.jsx)(B,{size:`xs`,variant:`outline`,onClick:()=>p(e),children:`Open`}),(0,q.jsxs)(B,{size:`xs`,variant:`ghost`,onClick:()=>{f(e.id),u(`chat`)},children:[(0,q.jsx)(o,{className:`h-3 w-3`}),`Chat`]})]})]},e.id))})]})]}),e.spawnedBy&&U&&(0,q.jsx)(z,{variant:`outline`,className:`max-w-full text-[10px] text-muted-foreground`,children:(0,q.jsxs)(`span`,{className:`truncate`,children:[`spawned by `,U]})})]}),(e.tags.length>0||x(e.capabilities).length>0)&&(0,q.jsxs)(`div`,{className:`flex flex-wrap gap-1 mb-2`,children:[e.tags.slice(0,3).map(e=>(0,q.jsx)(z,{variant:`outline`,className:`text-[9px] px-1 py-0 h-4`,children:e},e)),x(e.capabilities).slice(0,2).map(e=>(0,q.jsx)(z,{variant:`secondary`,className:`text-[9px] px-1 py-0 h-4`,children:e},e))]}),(0,q.jsxs)(`div`,{className:`space-y-2 mb-2`,children:[(0,q.jsx)(pe,{agent:e}),(0,q.jsx)(he,{agent:e,compact:!0}),(0,q.jsx)(fe,{agent:e})]}),(0,q.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:e.id!==`user`&&e.id!==`system`&&ee(l,e.lastSeen)}),(0,q.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,q.jsx)(ce,{value:e.id,label:`Copy agent ID`,size:`icon`,className:`h-7 w-7`,iconClassName:`w-3 h-3`}),(0,q.jsx)(B,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Chat`,onClick:()=>{f(e.id),u(`chat`)},children:(0,q.jsx)(o,{className:`w-3 h-3`})}),(0,q.jsx)(B,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Pair`,onClick:()=>m(e.id),children:(0,q.jsx)(_,{className:`w-3 h-3`})}),(0,q.jsx)(B,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Rename`,onClick:()=>w(e),children:(0,q.jsx)(t,{className:`w-3 h-3`})}),L&&(0,q.jsx)(B,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Terminal`,disabled:N,onClick:()=>void P(),children:(0,q.jsx)(d,{className:`w-3 h-3`})}),(e.branchState===`changes`||e.branchState===`idle`)&&e.branchWorkspaceId&&(0,q.jsx)(B,{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,q.jsx)(n,{className:`w-3 h-3`})}),oe&&(0,q.jsx)(B,{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,q.jsx)(i,{className:`w-3 h-3`})}),se&&(0,q.jsx)(B,{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,q.jsx)(r,{className:`w-3 h-3`})}),I&&(0,q.jsx)(B,{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,q.jsx)(s,{className:`w-3 h-3`})}),V&&(0,q.jsx)(B,{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,q.jsx)(g,{className:`w-3 h-3`})})]})]})}),M&&(0,q.jsx)(ge,{open:j,onOpenChange:ie,orchestratorId:M.orchestratorId,session:M.session,interactive:M.interactive||R})]})}function Qe(){let e=y(e=>e.agentPresetFilter),t=y(e=>e.agentStatusFilter),n=y(e=>e.agentTagFilter),r=y(e=>e.agentHostFilter),i=y(e=>e.agentSort),o=y(e=>e.agentSortDir),s=y(e=>e.showOffline),l=y(e=>e.set),d=y(e=>e.openAgentSpawn),p=y(e=>e.agentsById),m=v(),h=W(),g=U(),_=V(),b=me(h,m),x=de(h,m),ee=e||t||n||r;function te(){l({agentPresetFilter:``,agentStatusFilter:``,agentTagFilter:``,agentHostFilter:``})}function S(){l({agentSortDir:o===`asc`?`desc`:`asc`})}return(0,q.jsxs)(`div`,{className:`space-y-4`,children:[(0,q.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,q.jsxs)(`select`,{value:e,onChange:e=>l({agentPresetFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,q.jsx)(`option`,{value:``,children:`All agents`}),(0,q.jsx)(`option`,{value:`active`,children:`Active`}),(0,q.jsx)(`option`,{value:`claude`,children:`Claude`}),(0,q.jsx)(`option`,{value:`codex`,children:`Codex`}),(0,q.jsx)(`option`,{value:`paired`,children:`Paired`}),(0,q.jsx)(`option`,{value:`unpaired`,children:`Unpaired`}),(0,q.jsx)(`option`,{value:`offline_stale`,children:`Offline / Stale`})]}),(0,q.jsxs)(`select`,{value:t,onChange:e=>l({agentStatusFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,q.jsx)(`option`,{value:``,children:`Any status`}),(0,q.jsx)(`option`,{value:`online`,children:`Online`}),(0,q.jsx)(`option`,{value:`idle`,children:`Idle`}),(0,q.jsx)(`option`,{value:`busy`,children:`Busy`}),(0,q.jsx)(`option`,{value:`offline`,children:`Offline`}),(0,q.jsx)(`option`,{value:`starting`,children:`Starting`})]}),g.length>0&&(0,q.jsxs)(`select`,{value:n,onChange:e=>l({agentTagFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,q.jsx)(`option`,{value:``,children:`Any tag`}),g.map(e=>(0,q.jsx)(`option`,{value:e,children:e},e))]}),_.length>1&&(0,q.jsxs)(`select`,{value:r,onChange:e=>l({agentHostFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,q.jsx)(`option`,{value:``,children:`Any host`}),_.map(e=>(0,q.jsx)(`option`,{value:e,children:e},e))]}),(0,q.jsxs)(`select`,{value:i,onChange:e=>l({agentSort:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,q.jsx)(`option`,{value:`status`,children:`Sort: Status`}),(0,q.jsx)(`option`,{value:`name`,children:`Sort: Name`}),(0,q.jsx)(`option`,{value:`lastSeen`,children:`Sort: Last seen`}),(0,q.jsx)(`option`,{value:`created`,children:`Sort: Created`})]}),(0,q.jsx)(B,{size:`icon`,variant:`outline`,className:`h-8 w-8`,title:`Toggle sort direction`,onClick:S,children:o===`asc`?(0,q.jsx)(u,{className:`w-3.5 h-3.5`}):(0,q.jsx)(c,{className:`w-3.5 h-3.5`})}),(0,q.jsxs)(`label`,{className:`flex items-center gap-1.5 text-sm text-muted-foreground cursor-pointer select-none`,children:[(0,q.jsx)(`input`,{type:`checkbox`,checked:s,onChange:e=>l({showOffline:e.target.checked}),className:`rounded`}),`Show offline`]}),ee&&(0,q.jsxs)(B,{size:`sm`,variant:`ghost`,className:`h-8 text-muted-foreground hover:text-foreground gap-1`,onClick:te,children:[(0,q.jsx)(f,{className:`w-3 h-3`}),`Clear filters`]}),(0,q.jsx)(`div`,{className:`ml-auto`,children:(0,q.jsxs)(B,{size:`sm`,onClick:d,className:`gap-1`,children:[(0,q.jsx)(a,{className:`w-3.5 h-3.5`}),`Spawn`]})})]}),x.length===0?(0,q.jsx)(`div`,{className:`text-center py-16 text-muted-foreground text-sm`,children:`No agents match the current filters.`}):(0,q.jsx)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 gap-3`,children:x.map(e=>(0,q.jsx)(Ze,{agent:e,parentAgent:e.spawnedBy?p[e.spawnedBy]??null:null,childAgents:_e(b.get(e.id)??[])},e.id))})]})}export{Qe as AgentsView};
2
- //# sourceMappingURL=agents-CqQhC2aN.js.map
@@ -1,2 +0,0 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{$t as t,Jt as n,Mn as r,Un as i,a,bt as o,jn as s,kn as c,p as l}from"./lucide-react-ChOGD4vc.js";import{t as u}from"./store-BLZA3u7Y.js";var d=e(i(),1);function f(e){let t=u(e=>e.showError),[n,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 r(`POST`,`/agents/`+encodeURIComponent(e)+`/terminal-session`)),i(!0)}catch(e){t(`Terminal Failed`,e.message)}finally{c(!1)}}}function f(t){if(t){i(!0);return}i(!1);let n=a;o(null),e&&n?.mode===`guest`&&r(`DELETE`,`/agents/`+encodeURIComponent(e)+`/terminal-session/`+encodeURIComponent(n.session)).catch(()=>{})}return{terminalOpen:n,terminalTarget:a,terminalOpening:s,openTerminal:l,closeTerminal:f}}var p=s(),m={idle:{label:`idle`,tip:`Branch worktree — nothing to land yet.`,className:`bg-zinc-500/10 text-zinc-400 border-zinc-500/20`,Icon:n},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:o},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:t},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:a},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:r}){let i=m[e],{Icon:a}=i,o=!!t,s=o?`${i.tip} Click to open this workspace.`:i.tip;return(0,p.jsxs)(`span`,{role:o?`button`:void 0,tabIndex:o?0:void 0,title:s,onClick:t,onKeyDown:o?e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),t?.(e))}:void 0,className:c(`inline-flex items-center gap-1 rounded-full border px-1.5 py-0.5 text-[10px] font-medium leading-none`,i.className,o&&`cursor-pointer hover:brightness-125 focus:outline-none focus:ring-1 focus:ring-current`,r),children:[(0,p.jsx)(a,{className:`h-2.5 w-2.5 shrink-0`}),!n&&(0,p.jsx)(`span`,{children:i.label})]})}export{f as n,h as t};
2
- //# sourceMappingURL=branch-state-badge-Dp6Jk4LH.js.map
@@ -1,2 +0,0 @@
1
- import"./chunk-CilyBKbf.js";import{Un as e,jn as t,kn as n}from"./lucide-react-ChOGD4vc.js";e();var r=t();function i({className:e,size:t=`default`,...i}){return(0,r.jsx)(`div`,{"data-slot":`card`,"data-size":t,className:n(`group/card flex flex-col gap-4 overflow-hidden rounded-xl bg-card py-4 text-sm text-card-foreground ring-1 ring-foreground/10 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl`,e),...i})}function a({className:e,...t}){return(0,r.jsx)(`div`,{"data-slot":`card-header`,className:n(`group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3`,e),...t})}function o({className:e,...t}){return(0,r.jsx)(`div`,{"data-slot":`card-title`,className:n(`font-heading text-base leading-snug font-medium group-data-[size=sm]/card:text-sm`,e),...t})}function s({className:e,...t}){return(0,r.jsx)(`div`,{"data-slot":`card-content`,className:n(`px-4 group-data-[size=sm]/card:px-3`,e),...t})}export{o as i,s as n,a as r,i as t};
2
- //# sourceMappingURL=card-C7JtSyuM.js.map