agent-relay-server 0.120.1 → 0.120.3

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 (181) hide show
  1. package/docs/openapi.json +1 -1
  2. package/package.json +3 -3
  3. package/public/assets/MessageBubble-Cqi3XsZ7.js +2 -0
  4. package/public/assets/{MessageBubble-jpshgh3K.js.map → MessageBubble-Cqi3XsZ7.js.map} +1 -1
  5. package/public/assets/{PlanGraphPanel-CjVG-Jsq.js → PlanGraphPanel-D6Um05oW.js} +2 -2
  6. package/public/assets/{PlanGraphPanel-CjVG-Jsq.js.map → PlanGraphPanel-D6Um05oW.js.map} +1 -1
  7. package/public/assets/{activity-DLTFF8Dz.js → activity-B0LsQHEz.js} +2 -2
  8. package/public/assets/{activity-DLTFF8Dz.js.map → activity-B0LsQHEz.js.map} +1 -1
  9. package/public/assets/{agent-profiles-BcCLIrON.js → agent-profiles-O--pe5Ic.js} +2 -2
  10. package/public/assets/{agent-profiles-BcCLIrON.js.map → agent-profiles-O--pe5Ic.js.map} +1 -1
  11. package/public/assets/{agent-type-icon-BEz393ra.js → agent-type-icon-CeEoMouY.js} +2 -2
  12. package/public/assets/{agent-type-icon-BEz393ra.js.map → agent-type-icon-CeEoMouY.js.map} +1 -1
  13. package/public/assets/agents-Ii6XlVwR.js +2 -0
  14. package/public/assets/{agents-QemvuxKO.js.map → agents-Ii6XlVwR.js.map} +1 -1
  15. package/public/assets/{analytics-DMLoMwta.js → analytics-BCzdYWRT.js} +2 -2
  16. package/public/assets/{analytics-DMLoMwta.js.map → analytics-BCzdYWRT.js.map} +1 -1
  17. package/public/assets/{automation-DACSOffp.js → automation-Crr3Xzui.js} +2 -2
  18. package/public/assets/{automation-DACSOffp.js.map → automation-Crr3Xzui.js.map} +1 -1
  19. package/public/assets/{badge-BhUZ1cAb.js → badge-DCIT3Irj.js} +2 -2
  20. package/public/assets/{badge-BhUZ1cAb.js.map → badge-DCIT3Irj.js.map} +1 -1
  21. package/public/assets/{branch-state-badge-BYE2U_y4.js → branch-state-badge-Bhw2rloy.js} +2 -2
  22. package/public/assets/{branch-state-badge-BYE2U_y4.js.map → branch-state-badge-Bhw2rloy.js.map} +1 -1
  23. package/public/assets/{button-C-V4oij1.js → button-CzdTkRIf.js} +2 -2
  24. package/public/assets/{button-C-V4oij1.js.map → button-CzdTkRIf.js.map} +1 -1
  25. package/public/assets/{card-Br1JLjTH.js → card-C3BGuVC6.js} +2 -2
  26. package/public/assets/{card-Br1JLjTH.js.map → card-C3BGuVC6.js.map} +1 -1
  27. package/public/assets/{channels-3SlDQL3j.js → channels-CKs9rvsn.js} +2 -2
  28. package/public/assets/{channels-3SlDQL3j.js.map → channels-CKs9rvsn.js.map} +1 -1
  29. package/public/assets/chat-BCwEUj5R.js +2 -0
  30. package/public/assets/chat-BCwEUj5R.js.map +1 -0
  31. package/public/assets/{connectors-CrEW591Q.js → connectors-D_kQR_vw.js} +2 -2
  32. package/public/assets/{connectors-CrEW591Q.js.map → connectors-D_kQR_vw.js.map} +1 -1
  33. package/public/assets/{copy-button-BStzXgtd.js → copy-button-B3o1jpLu.js} +2 -2
  34. package/public/assets/{copy-button-BStzXgtd.js.map → copy-button-B3o1jpLu.js.map} +1 -1
  35. package/public/assets/{dist-ChDX_t12.js → dist-B-T7lg0a.js} +2 -2
  36. package/public/assets/{dist-ChDX_t12.js.map → dist-B-T7lg0a.js.map} +1 -1
  37. package/public/assets/{dist-DV83j9tm.js → dist-B3e4B9pg.js} +2 -2
  38. package/public/assets/{dist-DV83j9tm.js.map → dist-B3e4B9pg.js.map} +1 -1
  39. package/public/assets/{dist-y03IwOrd.js → dist-B6woQ9Tb.js} +2 -2
  40. package/public/assets/{dist-y03IwOrd.js.map → dist-B6woQ9Tb.js.map} +1 -1
  41. package/public/assets/{dist-CQ0Z-TDi.js → dist-B9G83DXv.js} +2 -2
  42. package/public/assets/{dist-CQ0Z-TDi.js.map → dist-B9G83DXv.js.map} +1 -1
  43. package/public/assets/{dist-Cs8X0P1d.js → dist-BIjlN-xB.js} +2 -2
  44. package/public/assets/{dist-Cs8X0P1d.js.map → dist-BIjlN-xB.js.map} +1 -1
  45. package/public/assets/{dist-DyNJNwpi.js → dist-BInckSJC.js} +2 -2
  46. package/public/assets/{dist-DyNJNwpi.js.map → dist-BInckSJC.js.map} +1 -1
  47. package/public/assets/{dist-CmFeEXMe.js → dist-BlzVGRhh.js} +2 -2
  48. package/public/assets/{dist-CmFeEXMe.js.map → dist-BlzVGRhh.js.map} +1 -1
  49. package/public/assets/{dist-CDZZxxJq.js → dist-C7aTlosb.js} +2 -2
  50. package/public/assets/{dist-CDZZxxJq.js.map → dist-C7aTlosb.js.map} +1 -1
  51. package/public/assets/{dist-D2jvo5oA.js → dist-DGfp5dLz.js} +2 -2
  52. package/public/assets/{dist-D2jvo5oA.js.map → dist-DGfp5dLz.js.map} +1 -1
  53. package/public/assets/{dist-mm7c7nBt.js → dist-DT-OV6sQ.js} +2 -2
  54. package/public/assets/{dist-mm7c7nBt.js.map → dist-DT-OV6sQ.js.map} +1 -1
  55. package/public/assets/{dist-CBMWGhWc.js → dist-OUPTEP6q.js} +2 -2
  56. package/public/assets/{dist-CBMWGhWc.js.map → dist-OUPTEP6q.js.map} +1 -1
  57. package/public/assets/{es2015-VnZ2kVIz.js → es2015-CnKXYKpf.js} +2 -2
  58. package/public/assets/{es2015-VnZ2kVIz.js.map → es2015-CnKXYKpf.js.map} +1 -1
  59. package/public/assets/formatted-body-impl-CSRGuMcM.js +3 -0
  60. package/public/assets/formatted-body-impl-CSRGuMcM.js.map +1 -0
  61. package/public/assets/formatted-body-q_qzt1L-.js +3 -0
  62. package/public/assets/{formatted-body-Dg9R3RD7.js.map → formatted-body-q_qzt1L-.js.map} +1 -1
  63. package/public/assets/{index-D_fNJnsI.js → index-Ceiwd02X.js} +10 -10
  64. package/public/assets/index-Ceiwd02X.js.map +1 -0
  65. package/public/assets/{input-CtLT7WXi.js → input-B6Q0NWCS.js} +2 -2
  66. package/public/assets/{input-CtLT7WXi.js.map → input-B6Q0NWCS.js.map} +1 -1
  67. package/public/assets/{insights-D48n2ojF.js → insights-DUhXqZTZ.js} +2 -2
  68. package/public/assets/{insights-D48n2ojF.js.map → insights-DUhXqZTZ.js.map} +1 -1
  69. package/public/assets/{integrations-B-bdliwU.js → integrations-lbg5CjtE.js} +2 -2
  70. package/public/assets/{integrations-B-bdliwU.js.map → integrations-lbg5CjtE.js.map} +1 -1
  71. package/public/assets/{lib-ByLQqcD1.js → lib-BHsWPMKB.js} +2 -2
  72. package/public/assets/{lib-ByLQqcD1.js.map → lib-BHsWPMKB.js.map} +1 -1
  73. package/public/assets/lucide-react-DuhlF2Sj.js +10 -0
  74. package/public/assets/lucide-react-DuhlF2Sj.js.map +1 -0
  75. package/public/assets/{maintenance-LQ_U3Nqy.js → maintenance-CQgneSVf.js} +2 -2
  76. package/public/assets/{maintenance-LQ_U3Nqy.js.map → maintenance-CQgneSVf.js.map} +1 -1
  77. package/public/assets/{managed-agents-Cfh8FvY8.js → managed-agents-DsnYf6fm.js} +4 -4
  78. package/public/assets/{managed-agents-Cfh8FvY8.js.map → managed-agents-DsnYf6fm.js.map} +1 -1
  79. package/public/assets/{markdown-preview-impl-BSa7zYx1.js → markdown-preview-impl-C1ZtGJp6.js} +2 -2
  80. package/public/assets/{markdown-preview-impl-BSa7zYx1.js.map → markdown-preview-impl-C1ZtGJp6.js.map} +1 -1
  81. package/public/assets/{memory-Dr1iYKkC.js → memory-SSLUTOI2.js} +2 -2
  82. package/public/assets/{memory-Dr1iYKkC.js.map → memory-SSLUTOI2.js.map} +1 -1
  83. package/public/assets/messages-BY26OP4K.js +2 -0
  84. package/public/assets/{messages-DRKulS-2.js.map → messages-BY26OP4K.js.map} +1 -1
  85. package/public/assets/{orchestrators-BguyeViG.js → orchestrators-OY7yPzVI.js} +2 -2
  86. package/public/assets/{orchestrators-BguyeViG.js.map → orchestrators-OY7yPzVI.js.map} +1 -1
  87. package/public/assets/overview-Dj0u1tPG.js +2 -0
  88. package/public/assets/{overview-Dbq2lr7Y.js.map → overview-Dj0u1tPG.js.map} +1 -1
  89. package/public/assets/{pairs-DD7i2scF.js → pairs-CrUR50ou.js} +2 -2
  90. package/public/assets/{pairs-DD7i2scF.js.map → pairs-CrUR50ou.js.map} +1 -1
  91. package/public/assets/{projects-DEn85LQb.js → projects-B_AtxHtH.js} +2 -2
  92. package/public/assets/{projects-DEn85LQb.js.map → projects-B_AtxHtH.js.map} +1 -1
  93. package/public/assets/{prompt-settings-DwgrPKY3.js → prompt-settings-CPtYSban.js} +2 -2
  94. package/public/assets/{prompt-settings-DwgrPKY3.js.map → prompt-settings-CPtYSban.js.map} +1 -1
  95. package/public/assets/{react-dom-cLkVFBsS.js → react-dom-DWBmcawP.js} +2 -2
  96. package/public/assets/{react-dom-cLkVFBsS.js.map → react-dom-DWBmcawP.js.map} +1 -1
  97. package/public/assets/{registry-DCR3xFpe.js → registry-BgUALWn5.js} +2 -2
  98. package/public/assets/{registry-DCR3xFpe.js.map → registry-BgUALWn5.js.map} +1 -1
  99. package/public/assets/security-5lHfGk7g.js +3 -0
  100. package/public/assets/security-5lHfGk7g.js.map +1 -0
  101. package/public/assets/{select-CpyCRBK3.js → select-Cgx4QSLj.js} +2 -2
  102. package/public/assets/{select-CpyCRBK3.js.map → select-Cgx4QSLj.js.map} +1 -1
  103. package/public/assets/settings-DFGgxyun.js +6 -0
  104. package/public/assets/{settings-DYNFGC2-.js.map → settings-DFGgxyun.js.map} +1 -1
  105. package/public/assets/store-BM4zM89B.js +9 -0
  106. package/public/assets/store-BM4zM89B.js.map +1 -0
  107. package/public/assets/{task-chip-kxk4eNm1.js → task-chip-DXfvXBDx.js} +2 -2
  108. package/public/assets/{task-chip-kxk4eNm1.js.map → task-chip-DXfvXBDx.js.map} +1 -1
  109. package/public/assets/{tasks-rdy9Nsbf.js → tasks-BvH5rluu.js} +2 -2
  110. package/public/assets/{tasks-rdy9Nsbf.js.map → tasks-BvH5rluu.js.map} +1 -1
  111. package/public/assets/{teams-DHloBagJ.js → teams-VZOIOdoE.js} +2 -2
  112. package/public/assets/{teams-DHloBagJ.js.map → teams-VZOIOdoE.js.map} +1 -1
  113. package/public/assets/{terminal-viewer-impl-DWTuNejR.js → terminal-viewer-impl-DYY3Wmoe.js} +2 -2
  114. package/public/assets/{terminal-viewer-impl-DWTuNejR.js.map → terminal-viewer-impl-DYY3Wmoe.js.map} +1 -1
  115. package/public/assets/types-uVOXgvMT.js.map +1 -1
  116. package/public/assets/{use-keyboard-viewport-B06XtRUZ.js → use-keyboard-viewport-CP109w9y.js} +2 -2
  117. package/public/assets/{use-keyboard-viewport-B06XtRUZ.js.map → use-keyboard-viewport-CP109w9y.js.map} +1 -1
  118. package/public/assets/{user-avatar-DuwCFrER.js → user-avatar-Dw6mzWhv.js} +2 -2
  119. package/public/assets/{user-avatar-DuwCFrER.js.map → user-avatar-Dw6mzWhv.js.map} +1 -1
  120. package/public/assets/{work-queue-CShT7nTC.js → work-queue-B6Xk7QNe.js} +2 -2
  121. package/public/assets/{work-queue-CShT7nTC.js.map → work-queue-B6Xk7QNe.js.map} +1 -1
  122. package/public/assets/{workspaces-DjQ6EdrZ.js → workspaces-CPIzAHAe.js} +2 -2
  123. package/public/assets/{workspaces-DjQ6EdrZ.js.map → workspaces-CPIzAHAe.js.map} +1 -1
  124. package/public/index.html +23 -23
  125. package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
  126. package/src/automations/reconcile.ts +69 -4
  127. package/src/branch-landed.ts +18 -11
  128. package/src/bus.ts +25 -18
  129. package/src/db/connection.ts +53 -1
  130. package/src/db/maintenance-worker.ts +37 -0
  131. package/src/db/message-reads.ts +86 -45
  132. package/src/db/migrations.ts +1 -0
  133. package/src/db/provider-quotas.ts +6 -7
  134. package/src/db/schema.ts +2 -1
  135. package/src/maintenance/jobs.ts +19 -13
  136. package/src/maintenance/scheduler.ts +8 -3
  137. package/src/maintenance/types.ts +5 -1
  138. package/src/mcp/index.ts +5 -5
  139. package/src/mcp/tools-workspace.ts +8 -3
  140. package/src/routes/orchestrator-proxy.ts +7 -6
  141. package/src/routes/sse.ts +2 -1
  142. package/src/routes/tasks.ts +29 -0
  143. package/src/routes/workspaces.ts +9 -2
  144. package/src/runtime-tokens.ts +4 -0
  145. package/src/security.ts +31 -7
  146. package/src/server.ts +40 -18
  147. package/src/services/git-process.ts +61 -0
  148. package/src/services/git-remote.ts +87 -7
  149. package/src/services/issue-lifecycle.ts +6 -6
  150. package/src/services/project.ts +47 -1
  151. package/src/services/send-message.ts +2 -4
  152. package/src/services/spawn-agent.ts +2 -2
  153. package/src/services/task-lifecycle.ts +6 -9
  154. package/src/settings/registry.ts +6 -4
  155. package/src/spawn-targets.ts +2 -2
  156. package/src/sse.ts +131 -46
  157. package/src/steward.ts +10 -6
  158. package/src/terminal-authz.ts +50 -0
  159. package/src/token-db.ts +3 -3
  160. package/src/validation.ts +1 -1
  161. package/src/workspace-actions.ts +46 -4
  162. package/src/workspace-auto-merge.ts +120 -13
  163. package/src/workspace-orphans.ts +1 -1
  164. package/src/workspace-probe.ts +19 -10
  165. package/public/assets/MessageBubble-jpshgh3K.js +0 -2
  166. package/public/assets/agents-QemvuxKO.js +0 -2
  167. package/public/assets/chat-xKXCafN9.js +0 -2
  168. package/public/assets/chat-xKXCafN9.js.map +0 -1
  169. package/public/assets/formatted-body-Dg9R3RD7.js +0 -3
  170. package/public/assets/formatted-body-impl-DlasTD8X.js +0 -3
  171. package/public/assets/formatted-body-impl-DlasTD8X.js.map +0 -1
  172. package/public/assets/index-D_fNJnsI.js.map +0 -1
  173. package/public/assets/lucide-react-Dc3ZwCBi.js +0 -9
  174. package/public/assets/lucide-react-Dc3ZwCBi.js.map +0 -1
  175. package/public/assets/messages-DRKulS-2.js +0 -2
  176. package/public/assets/overview-Dbq2lr7Y.js +0 -2
  177. package/public/assets/security-BH8kTdA-.js +0 -3
  178. package/public/assets/security-BH8kTdA-.js.map +0 -1
  179. package/public/assets/settings-DYNFGC2-.js +0 -6
  180. package/public/assets/store-BuuJUn70.js +0 -9
  181. package/public/assets/store-BuuJUn70.js.map +0 -1
@@ -36,11 +36,14 @@ import { isAwaitingReviewerApproval } from "./reviewer-pipeline";
36
36
  import { emitWorkspaceTaskSemanticNotifications } from "./services/task-lifecycle";
37
37
  import { ensureRepoSteward } from "./steward";
38
38
  import { requestWorkspaceMerge, workspaceMergeOrchestrators } from "./workspace-merge";
39
+ import { workspaceOwnerOrchestrator } from "./workspace-host";
39
40
  import { workspaceActiveClaim } from "./workspace-claim";
40
41
  import { DIRTY_WORKTREE_LAND_SKIP_REASON, READY_TO_LAND_STATUSES } from "./workspace-phase";
41
42
  import { fetchHostMergePreview } from "./workspace-probe";
42
43
  import type { WorkspaceAutoMergePolicy, WorkspaceLandingPolicy, WorkspaceMergePreview, WorkspaceMergeStrategy, WorkspaceRecord } from "./types";
43
44
  import { STEWARD_WAKE_COOLDOWN_MS, stewardFallbackTarget, workspaceAutoMergeEnabled } from "./config";
45
+ import { isPathWithinBase } from "./utils";
46
+ import type { Orchestrator } from "./types";
44
47
 
45
48
  const WORKSPACE_LAND_STRATEGIES = ["direct", "pr"] as const;
46
49
  const WORKSPACE_AUTO_MERGE_POLICIES = ["on-green", "on-approval", "manual"] as const;
@@ -52,6 +55,21 @@ type AutoMergeRequestOptions = {
52
55
  reviewer?: string;
53
56
  };
54
57
 
58
+ function stewardOwnerForWorkspace(ws: WorkspaceRecord): { owner: Orchestrator } | { error: string } {
59
+ const orchestrators = listOrchestrators();
60
+ if (ws.orchestratorId) {
61
+ const owner = orchestrators.find((orch) => orch.id === ws.orchestratorId);
62
+ if (!owner) return { error: `cannot spawn steward: owning host ${ws.orchestratorId} is not registered` };
63
+ if (owner.status !== "online") return { error: `cannot spawn steward: owning host ${owner.id} is ${owner.status}` };
64
+ if (!isPathWithinBase(ws.worktreePath, owner.baseDir)) {
65
+ return { error: `cannot spawn steward: worktree is not on owning host ${owner.id}` };
66
+ }
67
+ return { owner };
68
+ }
69
+ const owner = workspaceOwnerOrchestrator(ws, orchestrators, { requireApiUrl: true });
70
+ return owner ? { owner } : { error: "cannot spawn steward: no online owner for workspace host path" };
71
+ }
72
+
55
73
  function workspaceLandStrategy(metadata: Record<string, unknown>): WorkspaceLandingPolicy | undefined {
56
74
  const value = metadata.landStrategy;
57
75
  return typeof value === "string" && (WORKSPACE_LAND_STRATEGIES as readonly string[]).includes(value)
@@ -91,8 +109,8 @@ function autoMergeRequestOptions(ws: WorkspaceRecord): AutoMergeRequestOptions {
91
109
 
92
110
  // Don't re-wake the managed steward for the same workspace more than once per this
93
111
  // window — a persistent conflict/behind row would otherwise re-ping every sweep.
94
- // Wake the managed per-repo steward (issue #167) for a workspace it should handle:
95
- // auto-provision the policy from global steward config, then queue a `policy:` wake
112
+ // Wake the managed per-host/repo steward (issue #167/#977) for a workspace it should handle:
113
+ // auto-provision the policy on the workspace-owning host, then queue a `policy:` wake
96
114
  // message (which also spawns the on-demand agent now via onMessageForPolicy). Honors a
97
115
  // per-workspace cooldown so a persistent conflict/behind row isn't re-pinged every sweep.
98
116
  // Returns the steward policy name on a fresh wake, or null (disabled / no owner / cooled down).
@@ -100,8 +118,16 @@ export function wakeRepoSteward(ws: WorkspaceRecord, reason: string): string | n
100
118
  const meta = ws.metadata as Record<string, unknown>;
101
119
  const lastWoke = typeof meta.stewardWokenAt === "number" ? meta.stewardWokenAt : 0;
102
120
  if (lastWoke && Date.now() - lastWoke < STEWARD_WAKE_COOLDOWN_MS) return null;
103
- const policyName = ensureRepoSteward(ws.repoRoot);
104
- if (!policyName) return null;
121
+ const ownerResult = stewardOwnerForWorkspace(ws);
122
+ if ("error" in ownerResult) {
123
+ patchWorkspaceMetadata(ws.id, { stewardWakeError: ownerResult.error, stewardWakeErrorAt: Date.now() });
124
+ return null;
125
+ }
126
+ const policyName = ensureRepoSteward(ws.repoRoot, ownerResult.owner);
127
+ if (!policyName) {
128
+ patchWorkspaceMetadata(ws.id, { stewardWakeError: "cannot spawn steward: steward policy could not be provisioned", stewardWakeErrorAt: Date.now() });
129
+ return null;
130
+ }
105
131
  // #640 — resolve the identity triangle so the steward isn't blind to the people-graph:
106
132
  // the workspace's branch agent (owner) and that agent's coordinator (owner's `spawnedBy`).
107
133
  const { ownerAgentId, coordinatorAgentId } = resolveStewardIdentity(ws);
@@ -132,11 +158,18 @@ export function wakeRepoSteward(ws: WorkspaceRecord, reason: string): string | n
132
158
  },
133
159
  });
134
160
  getLifecycleManager().onMessageForPolicy(policyName);
135
- patchWorkspaceMetadata(ws.id, { stewardWokenAt: Date.now(), stewardPolicy: policyName, coordinatorAgentId: coordinatorAgentId ?? undefined });
161
+ patchWorkspaceMetadata(ws.id, {
162
+ stewardWokenAt: Date.now(),
163
+ stewardPolicy: policyName,
164
+ coordinatorAgentId: coordinatorAgentId ?? undefined,
165
+ stewardWakeError: undefined,
166
+ stewardWakeErrorAt: undefined,
167
+ });
136
168
  // #641/#642 — tell the owner which steward took over and proactively loop in its coordinator.
137
169
  notifyStewardHandoff({ workspace: ws, stewardId: policyName, coordinatorAgentId, reason });
138
170
  return policyName;
139
- } catch {
171
+ } catch (e) {
172
+ patchWorkspaceMetadata(ws.id, { stewardWakeError: e instanceof Error ? e.message : "failed to wake steward", stewardWakeErrorAt: Date.now() });
140
173
  return null;
141
174
  }
142
175
  }
@@ -247,6 +280,36 @@ function escalateNoProgressMerge(ws: WorkspaceRecord): void {
247
280
  });
248
281
  }
249
282
 
283
+ function notifyProtectedTipRestore(ws: WorkspaceRecord, preview: WorkspaceMergePreview): void {
284
+ const discardedRef = preview.protectedTipDiscardedRef;
285
+ const discardedHead = preview.protectedTipDiscardedHead;
286
+ if (!discardedRef || !discardedHead) return;
287
+ const { coordinatorAgentId } = resolveStewardIdentity(ws);
288
+ const recipients = [...new Set([coordinatorAgentId, ws.ownerAgentId].filter((r): r is string => Boolean(r)))];
289
+ const body = `Workspace \`${ws.branch ?? ws.id}\` restored protected tip \`${preview.protectedTip?.slice(0, 12) ?? "unknown"}\`; discarded HEAD \`${discardedHead.slice(0, 12)}\` was preserved at \`${discardedRef}\`.`;
290
+ createActivityEvent({
291
+ clientId: `workspace-protected-tip-restore-${ws.id}-${Date.now()}`,
292
+ kind: "state",
293
+ title: "Protected workspace tip restored",
294
+ body,
295
+ meta: ws.branch ?? ws.id,
296
+ icon: "ti-shield",
297
+ view: "orchestrators",
298
+ metadata: { source: "server", maintenanceJobId: "workspace-auto-merge", workspaceId: ws.id, protectedTip: preview.protectedTip, discardedHead, discardedRef },
299
+ });
300
+ if (!recipients.length) return;
301
+ routeNotification({
302
+ type: "workspace.land_gate_warning",
303
+ scope: { workspaceId: ws.id, repoRoot: ws.repoRoot, author: ws.ownerAgentId, parent: coordinatorAgentId ?? undefined },
304
+ recipients,
305
+ message: {
306
+ subject: "Workspace protected tip restored",
307
+ body,
308
+ payload: { kind: "workspace.protected-tip-restore", workspaceId: ws.id, repoRoot: ws.repoRoot, branch: ws.branch, protectedTip: preview.protectedTip, discardedHead, discardedRef },
309
+ },
310
+ });
311
+ }
312
+
250
313
  interface LandSweepResult {
251
314
  scanned: number;
252
315
  merged: string[];
@@ -255,13 +318,14 @@ interface LandSweepResult {
255
318
  heldByPause: string[];
256
319
  heldAwaitingApproval: string[];
257
320
  previewUnavailable: string[];
321
+ dirtyWorktree: string[];
258
322
  backedOff: string[];
259
323
  leftForSteward: string[];
260
324
  wokeStewards: string[];
261
325
  }
262
326
 
263
327
  function emptyLandSweep(): LandSweepResult {
264
- return { scanned: 0, merged: [], heldByLease: [], heldByClaim: [], heldByPause: [], heldAwaitingApproval: [], previewUnavailable: [], backedOff: [], leftForSteward: [], wokeStewards: [] };
328
+ return { scanned: 0, merged: [], heldByLease: [], heldByClaim: [], heldByPause: [], heldAwaitingApproval: [], previewUnavailable: [], dirtyWorktree: [], backedOff: [], leftForSteward: [], wokeStewards: [] };
265
329
  }
266
330
 
267
331
  async function fetchFirstUsableMergePreview(
@@ -270,7 +334,7 @@ async function fetchFirstUsableMergePreview(
270
334
  ): Promise<WorkspaceMergePreview | { available: false } | null> {
271
335
  for (const orch of workspaceMergeOrchestrators(ws, orchestrators)) {
272
336
  if (!orch.apiUrl) continue;
273
- const preview = await fetchHostMergePreview(orch.apiUrl, ws);
337
+ const preview = await fetchHostMergePreview(orch.apiUrl, ws, { protectTip: true });
274
338
  if (!preview || (preview as { available?: false }).available === false) continue;
275
339
  const p = preview as WorkspaceMergePreview;
276
340
  if (p.error || p.missing) continue;
@@ -288,7 +352,7 @@ async function landCandidates(
288
352
  ): Promise<LandSweepResult> {
289
353
  const stewardEnabled = getStewardConfig().enabled;
290
354
  const merged: string[] = [], previewUnavailable: string[] = [];
291
- const heldByLease: string[] = [], heldByClaim: string[] = [], heldByPause: string[] = [], heldAwaitingApproval: string[] = [], backedOff: string[] = [], leftForSteward: string[] = [], wokeStewards: string[] = [];
355
+ const heldByLease: string[] = [], heldByClaim: string[] = [], heldByPause: string[] = [], heldAwaitingApproval: string[] = [], dirtyWorktree: string[] = [], backedOff: string[] = [], leftForSteward: string[] = [], wokeStewards: string[] = [];
292
356
 
293
357
  for (const ws of candidates) {
294
358
  if (isAwaitingReviewerApproval(ws)) { heldAwaitingApproval.push(ws.id); continue; }
@@ -310,8 +374,22 @@ async function landCandidates(
310
374
  continue;
311
375
  }
312
376
  const p = preview as WorkspaceMergePreview;
313
- if (p.reason === DIRTY_WORKTREE_LAND_SKIP_REASON) {
314
- patchWorkspaceMetadata(ws.id, { lastLandSkipReason: p.reason, lastLandSkipAt: Date.now() });
377
+ if (p.protectedTipRestored) notifyProtectedTipRestore(ws, p);
378
+ const dirtyCount = p.dirtyCount ?? 0;
379
+ if (p.reason === DIRTY_WORKTREE_LAND_SKIP_REASON || dirtyCount > 0) {
380
+ const mergeError = p.reason ?? DIRTY_WORKTREE_LAND_SKIP_REASON;
381
+ const heldDirty = patchWorkspaceMetadata(ws.id, {
382
+ ...noteMergeNoProgress(ws.metadata),
383
+ mergeError,
384
+ lastLandSkipReason: DIRTY_WORKTREE_LAND_SKIP_REASON,
385
+ lastLandSkipAt: Date.now(),
386
+ }) ?? ws;
387
+ dirtyWorktree.push(ws.id);
388
+ if (mergeNoProgressCount(heldDirty.metadata) >= MAX_NO_PROGRESS_MERGE_ATTEMPTS) {
389
+ backedOff.push(ws.id);
390
+ escalateNoProgressMerge(heldDirty);
391
+ }
392
+ continue;
315
393
  } else if (ws.metadata.lastLandSkipReason === DIRTY_WORKTREE_LAND_SKIP_REASON) {
316
394
  patchWorkspaceMetadata(ws.id, { lastLandSkipReason: undefined, lastLandSkipAt: undefined });
317
395
  }
@@ -328,11 +406,40 @@ async function landCandidates(
328
406
  // the steward every sweep for a workspace with no work.
329
407
  const canLand = p.noop === true || (p.conflict === false && ahead > 0);
330
408
  if (!canLand) {
409
+ let handoffWorkspace = ws;
410
+ if (p.conflict !== true) {
411
+ const mergeError = p.protectedTipReachable === false
412
+ ? p.protectedTipError ?? "protected worker tip is no longer reachable"
413
+ : p.reason ?? p.error ?? "merge state unknown";
414
+ handoffWorkspace = patchWorkspaceMetadata(ws.id, {
415
+ ...noteMergeNoProgress(ws.metadata),
416
+ mergeError,
417
+ lastMergeStateUnknownAt: Date.now(),
418
+ }) ?? ws;
419
+ if (mergeNoProgressCount(handoffWorkspace.metadata) >= MAX_NO_PROGRESS_MERGE_ATTEMPTS) {
420
+ backedOff.push(ws.id);
421
+ escalateNoProgressMerge(handoffWorkspace);
422
+ continue;
423
+ }
424
+ }
331
425
  leftForSteward.push(ws.id);
426
+ let woke: string | null = null;
332
427
  if (stewardEnabled) {
333
- const woke = wakeRepoSteward(ws, p.conflict === true ? "conflict" : "merge state unknown");
428
+ woke = wakeRepoSteward(handoffWorkspace, p.conflict === true ? "conflict" : "merge state unknown");
334
429
  if (woke) wokeStewards.push(woke);
335
430
  }
431
+ if (stewardEnabled && !woke && p.conflict === true) {
432
+ const failedHandoff = patchWorkspaceMetadata(ws.id, {
433
+ ...noteMergeNoProgress(ws.metadata),
434
+ mergeError: "cannot spawn steward on the workspace owning host",
435
+ lastStewardWakeFailedAt: Date.now(),
436
+ }) ?? ws;
437
+ if (mergeNoProgressCount(failedHandoff.metadata) >= MAX_NO_PROGRESS_MERGE_ATTEMPTS) {
438
+ backedOff.push(ws.id);
439
+ escalateNoProgressMerge(failedHandoff);
440
+ continue;
441
+ }
442
+ }
336
443
  if (p.conflict === true) {
337
444
  emitWorkspaceTaskSemanticNotifications({
338
445
  workspace: ws,
@@ -372,7 +479,7 @@ async function landCandidates(
372
479
  });
373
480
  }
374
481
 
375
- return { scanned: candidates.length, merged, heldByLease, heldByClaim, heldByPause, heldAwaitingApproval, previewUnavailable, backedOff, leftForSteward, wokeStewards };
482
+ return { scanned: candidates.length, merged, heldByLease, heldByClaim, heldByPause, heldAwaitingApproval, previewUnavailable, dirtyWorktree, backedOff, leftForSteward, wokeStewards };
376
483
  }
377
484
 
378
485
  // Coalesced, fire-and-forget per-repo land trigger (see module header). A run already
@@ -556,7 +556,7 @@ export async function reapOrphanedWorktrees(): Promise<Record<string, unknown>>
556
556
  // Route through the guarded action (#279): no `force`, so a flipped-alive owner
557
557
  // is rejected (409) — our safety net. Also does the cleanup_requested transition
558
558
  // + audit. Attributed to a distinct requester so incidents are traceable.
559
- const result = applyWorkspaceAction(workspace, {
559
+ const result = await applyWorkspaceAction(workspace, {
560
560
  action: "cleanup",
561
561
  agentId: "workspace-dead-owner-reaper",
562
562
  auditMetadata: { source: "server", maintenanceJobId: "workspace-orphan-reaper", requestedBy: "workspace-dead-owner-reaper", deadOwner: workspace.ownerAgentId },
@@ -32,12 +32,16 @@ export const workspacePathWithinBase = isPathWithinBase;
32
32
  export async function fetchHostMergePreview(
33
33
  apiUrl: string,
34
34
  workspace: WorkspaceRecord,
35
- opts: { checkPr?: boolean } = {},
35
+ opts: { checkPr?: boolean; protectTip?: boolean } = {},
36
36
  ): Promise<WorkspaceMergePreview | { available: false } | null> {
37
37
  const checkPr = opts.checkPr !== false;
38
38
  const query = new URLSearchParams({ path: workspace.worktreePath, ...(checkPr ? { checkPr: "1" } : {}) });
39
39
  if (workspace.baseRef) query.set("baseRef", workspace.baseRef);
40
40
  if (workspace.baseSha) query.set("baseSha", workspace.baseSha);
41
+ if (opts.protectTip) {
42
+ query.set("workspaceId", workspace.id);
43
+ query.set("protectTip", "1");
44
+ }
41
45
  const headers: Record<string, string> = {};
42
46
  const token = relayToken();
43
47
  if (token) headers[RELAY_TOKEN_HEADER] = token;
@@ -84,6 +88,18 @@ interface ProbeResult {
84
88
  skipped?: string;
85
89
  }
86
90
 
91
+ export async function refreshWorkspaceGitState(ws: WorkspaceRecord): Promise<ProbeResult> {
92
+ if (!ws.worktreePath) return { probed: false, workspaceId: ws.id, skipped: "workspace has no worktree" };
93
+ const orch = workspaceOwnerOrchestrator(ws, listOrchestrators(), { requireApiUrl: true });
94
+ if (!orch?.apiUrl) return { probed: false, workspaceId: ws.id, skipped: "no online orchestrator owns this path" };
95
+ const preview = await fetchHostMergePreview(orch.apiUrl, ws, { checkPr: false });
96
+ if (!preview || (preview as { available?: false }).available === false) return { probed: false, workspaceId: ws.id, skipped: "host preview unavailable" };
97
+ const p = preview as WorkspaceMergePreview;
98
+ if (p.error || p.missing) return { probed: false, workspaceId: ws.id, skipped: "host preview error" };
99
+ const flipped = applyBranchFreshness(ws, p);
100
+ return { probed: true, flipped, workspaceId: ws.id };
101
+ }
102
+
87
103
  /**
88
104
  * Probe THIS agent's branch worktree on turn-end (#237). Single scoped host round-trip
89
105
  * (not the full fan-out scan) so the changes badge flips at the exact moment work
@@ -96,15 +112,8 @@ export async function probeWorkspaceState(agentId: string): Promise<ProbeResult>
96
112
  const ws = ownedIsolatedWorkspace(agentId);
97
113
  if (!ws || !ws.worktreePath) return { probed: false, skipped: "no live isolated workspace" };
98
114
  if (ws.status !== "active") return { probed: false, workspaceId: ws.id, skipped: `status ${ws.status} derives badge without git counts` };
99
- const orch = workspaceOwnerOrchestrator(ws, listOrchestrators(), { requireApiUrl: true });
100
- if (!orch?.apiUrl) return { probed: false, workspaceId: ws.id, skipped: "no online orchestrator owns this path" };
101
- // checkPr:false — a badge probe never needs the gh round-trip (#304).
102
- const preview = await fetchHostMergePreview(orch.apiUrl, ws, { checkPr: false });
103
- if (!preview || (preview as { available?: false }).available === false) return { probed: false, workspaceId: ws.id, skipped: "host preview unavailable" };
104
- const p = preview as WorkspaceMergePreview;
105
- if (p.error || p.missing) return { probed: false, workspaceId: ws.id, skipped: "host preview error" };
106
- const flipped = applyBranchFreshness(ws, p);
107
- return { probed: true, flipped, workspaceId: ws.id };
115
+ // checkPr:false a badge/readiness probe never needs the gh round-trip (#304).
116
+ return refreshWorkspaceGitState(ws);
108
117
  }
109
118
 
110
119
  /**
@@ -1,2 +0,0 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{Gn as t,Kn as n,S as r,Sn as i,Ut as a,a as o,bn as s,en as c,er as l,hr as u,ir as d,l as f,nr as p,pn as m,pt as h,r as g}from"./lucide-react-Dc3ZwCBi.js";import{t as _,y as v}from"./store-BuuJUn70.js";import{o as y}from"./types-uVOXgvMT.js";import{V as b,_ as x,f as S,k as C,v as ee}from"./display-exQDWum3.js";import{t as w}from"./agent-type-icon-BEz393ra.js";import{t as T}from"./formatted-body-Dg9R3RD7.js";import{A as E,L as D,M as O,O as te,P as ne,T as k,h as A,k as j,l as M,n as N,o as P,t as F,w as I}from"./index-D_fNJnsI.js";import{t as L}from"./user-avatar-DuwCFrER.js";var R=e(u(),1);function re(){return(0,R.useSyncExternalStore)(e=>v.subscribe(e),()=>v.getPlayingKey(),()=>null)}var z=p();function ie({msg:e,peer:t}){return(0,z.jsx)(A,{msg:e,issueRepo:_(e=>e.agentsById[t]?.issueRepo)})}function B({agent:e,onClick:t}){let n=!!(t&&e);return(0,z.jsx)(`button`,{type:`button`,title:e?e.label||e.name||e.id:void 0,onClick:t,disabled:!n,className:l(`shrink-0 self-end transition-opacity`,n?`cursor-pointer hover:opacity-80`:`cursor-default opacity-60`),children:(0,z.jsx)(w,{agent:e})})}function ae({agentId:e,onOpen:t}){let n=_(t=>t.agentsById[e]??null);return(0,z.jsx)(B,{agent:n,onClick:n?()=>t(n):void 0})}function V({attachment:e,outbound:t}){let n=e.kind===`image`,r=e.title||e.artifactId,[i,u]=(0,R.useState)(null),[f,p]=(0,R.useState)(null),[m,_]=(0,R.useState)(!1),[v,y]=(0,R.useState)(!1);(0,R.useEffect)(()=>{let t=!1,n=null;async function r(){_(!0),p(null),u(null);try{let r=await d(`/artifacts/${encodeURIComponent(e.artifactId)}/content`);if(t)return;n=URL.createObjectURL(r),u(n)}catch(e){t||p(e.message)}finally{t||_(!1)}}return r(),()=>{t=!0,n&&URL.revokeObjectURL(n)}},[e.artifactId]);function b(){if(!i)return;let e=document.createElement(`a`);e.href=i,e.download=r,document.body.appendChild(e),e.click(),e.remove()}return n?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`button`,{type:`button`,onClick:()=>i&&y(!0),disabled:!i,className:`group/img mt-2 block overflow-hidden rounded-md border border-foreground/10 bg-black/10 text-left disabled:cursor-default relative`,children:i?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`img`,{src:i,alt:r,loading:`lazy`,className:`block max-h-72 max-w-full object-contain`}),(0,z.jsx)(`span`,{className:`absolute inset-0 flex items-center justify-center bg-black/0 group-hover/img:bg-black/30 transition-colors`,children:(0,z.jsx)(g,{className:`w-6 h-6 text-white opacity-0 group-hover/img:opacity-100 transition-opacity drop-shadow-md`})})]}):(0,z.jsxs)(`span`,{className:l(`flex min-h-20 items-center gap-2 px-3 py-2 text-xs`,f?`text-red-400`:`text-muted-foreground`),children:[m?(0,z.jsx)(h,{className:`h-4 w-4 animate-spin`}):(0,z.jsx)(s,{className:`h-4 w-4`}),f||`Loading image`]})}),i&&(0,z.jsx)(F,{open:v,onOpenChange:y,children:(0,z.jsxs)(N,{className:`max-w-[95vw] max-h-[95vh] w-auto p-0 bg-black/95 border-zinc-800 gap-0 overflow-hidden`,showCloseButton:!1,children:[(0,z.jsx)(P,{className:`sr-only`,children:r}),(0,z.jsxs)(`div`,{className:`relative flex items-center justify-center min-h-[200px]`,children:[(0,z.jsx)(`img`,{src:i,alt:r,className:`max-w-[93vw] max-h-[90vh] object-contain`}),(0,z.jsxs)(`div`,{className:`absolute top-2 right-2 flex gap-1`,children:[(0,z.jsx)(`button`,{type:`button`,onClick:b,className:`rounded-md bg-black/60 hover:bg-black/80 p-2 text-white transition-colors`,title:`Download`,children:(0,z.jsx)(c,{className:`w-4 h-4`})}),(0,z.jsx)(`button`,{type:`button`,onClick:()=>y(!1),className:`rounded-md bg-black/60 hover:bg-black/80 p-2 text-white transition-colors`,title:`Close`,children:(0,z.jsx)(o,{className:`w-4 h-4`})})]})]})]})})]}):(0,z.jsxs)(`button`,{type:`button`,onClick:b,disabled:!i,className:l(`mt-2 flex w-full items-center gap-2 rounded-md border px-2.5 py-2 text-left text-xs transition-colors disabled:cursor-default disabled:opacity-70`,t?`border-primary-foreground/20 bg-primary-foreground/10 hover:bg-primary-foreground/15`:`border-border bg-background hover:bg-muted`),children:[m?(0,z.jsx)(h,{className:`h-4 w-4 shrink-0 animate-spin`}):f?(0,z.jsx)(s,{className:`h-4 w-4 shrink-0 text-red-400`}):(0,z.jsx)(a,{className:`h-4 w-4 shrink-0`}),(0,z.jsx)(`span`,{className:l(`min-w-0 flex-1 truncate`,f&&`text-red-400`),children:f||r}),(0,z.jsx)(c,{className:`h-3.5 w-3.5 shrink-0`})]})}function H({open:e,onToggle:t,onReact:n}){return(0,z.jsxs)(`div`,{className:`relative shrink-0`,children:[(0,z.jsx)(`button`,{type:`button`,title:`Add reaction`,onClick:t,className:l(`inline-flex h-5 w-6 items-center justify-center rounded-full border border-border bg-popover text-muted-foreground shadow-sm transition hover:bg-muted hover:text-foreground`,e?`opacity-100`:`opacity-0 pointer-events-none md:group-hover/msg:opacity-100 md:group-hover/msg:pointer-events-auto`),children:(0,z.jsx)(r,{className:`h-3 w-3`})}),e&&(0,z.jsx)(`div`,{className:`absolute bottom-full left-0 z-30 mb-1 flex gap-0.5 rounded-full border border-border bg-popover p-0.5 shadow-md`,children:I.map(e=>(0,z.jsx)(`button`,{type:`button`,title:`React ${e}`,onClick:()=>n(e),className:`inline-flex h-6 w-7 items-center justify-center rounded-full text-xs transition-colors hover:bg-muted`,children:e},e))})]})}function U({msg:e,peer:r}){let[a,o]=(0,R.useState)(!1),s=_(e=>e.agentsById),c=_(e=>e.openAgentDetail),u=e.from===r,d=(u?e.to:e.from)||``,f=s[u?r:d]?.issueRepo??s[r]?.issueRepo,p=!d||d===`broadcast`||d.includes(`:`),m=C(e),h=k(e.occurredAt??e.createdAt),g=u?t:n,v=s[e.from??``]??null;function y(e){e.stopPropagation(),v&&c(v)}return(0,z.jsx)(`div`,{"data-msg-id":e.id,className:`flex justify-center mb-1.5`,children:(0,z.jsxs)(`div`,{className:`w-full max-w-[94%] rounded-md border border-border/50 bg-muted/15 px-2.5 py-1`,children:[(0,z.jsxs)(`div`,{className:`flex items-center gap-1.5 text-xs cursor-pointer select-none`,onClick:()=>o(e=>!e),children:[(0,z.jsx)(i,{className:l(`h-3 w-3 shrink-0 text-muted-foreground/60 transition-transform`,a&&`rotate-90`)}),(0,z.jsx)(`button`,{type:`button`,title:v?v.label||v.name||v.id:void 0,disabled:!v,onClick:y,className:l(`shrink-0 transition-opacity`,v?`cursor-pointer hover:opacity-80`:`cursor-default opacity-60`),children:(0,z.jsx)(w,{agent:v,className:`!w-4 !h-4 !rounded-sm opacity-70`})}),(0,z.jsx)(g,{className:`h-3 w-3 shrink-0 text-muted-foreground/70`}),(0,z.jsxs)(`span`,{className:`shrink-0 text-muted-foreground`,children:[`Message `,u?`to`:`from`]}),p?(0,z.jsx)(`span`,{className:`shrink-0 font-medium text-muted-foreground`,children:S(d,s)}):(0,z.jsx)(M,{agentId:d,className:`shrink-0 px-0.5 text-foreground/80`,noIcon:!0}),!a&&(0,z.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-muted-foreground/50`,children:m}),(0,z.jsx)(`span`,{className:`ml-auto shrink-0 text-muted-foreground/40`,children:h})]}),a&&(0,z.jsx)(`div`,{className:`mt-1.5 pl-5`,children:(0,z.jsx)(T,{text:m,rawBody:e.body,issueRepo:f,className:`text-sm leading-relaxed text-foreground/90`})})]})})}var W=(0,R.memo)(function({msg:e,peer:t,showAvatar:n=!1,onOpenReferencedPath:r,onPreviewReferencedPath:i,onPreviewReferencedPathEnd:a}){if(!y(e.from)&&!y(e.to))return(0,z.jsx)(U,{msg:e,peer:t});let o=e.kind===`session`?e.payload?.session:void 0;if(o?.type===`prompt`&&o?.origin===`provider`)return(0,z.jsx)(ie,{msg:e,peer:t});let s=y(e.from),c=_(e=>e.reactToMessage),u=_(e=>e.voiceTtsEnabled),d=re(),p=_(e=>{let n=e.agentsById[t]?.meta?.cwd;return typeof n==`string`?n:``}),h=_(e=>e.agentsById[t]?.issueRepo),g=_(e=>e.usersById),S=_(e=>e.users.length>1),w=s?b(e.from,g):void 0,A=_(e=>e.openAgentDetail);_(e=>e.openTaskDetailById);let[M,N]=(0,R.useState)(!1),P=(0,R.useRef)(null),F=(0,R.useRef)(null),I=(0,R.useRef)(!1),B=C(e),W=k(e.occurredAt??e.createdAt),G=O(e),K=te(e),q=s?ne(e,t):null,J=q?.icon,Y=d===String(e.id),oe=u&&!s&&!E(e)&&B.trim().length>0;function se(t){t.stopPropagation(),Y?v.bargeIn():v.speak(e.body,String(e.id))}(0,R.useEffect)(()=>{if(!M)return;function e(e){j()||P.current&&!P.current.contains(e.target)&&N(!1)}return document.addEventListener(`mousedown`,e),document.addEventListener(`touchstart`,e),()=>{document.removeEventListener(`mousedown`,e),document.removeEventListener(`touchstart`,e)}},[M]);function X(e){return D(p||`/`,e)}function Z(e,t){let n=X(e);r?.(n,t)}function ce(e,t,n){let r=X(e);i?.(r,t,n)}function Q(t){c(e,t),N(!1)}function le(e){e.button===0&&(F.current={x:e.clientX,y:e.clientY},I.current=!1)}function ue(e){let t=F.current;t&&(Math.abs(e.clientX-t.x)>3||Math.abs(e.clientY-t.y)>3)&&(I.current=!0)}function de(t){if(!(E(e)||s)&&!t.target.closest(`a,button,input,textarea,select,[role="button"]`)){if(I.current||j()){I.current=!1;return}N(e=>!e)}}let $=n&&!E(e);return(0,z.jsxs)(`div`,{"data-msg-id":e.id,className:l(`group/msg flex mb-3 items-end`,s?`justify-end`:`justify-start`,$&&`gap-1.5`),children:[!s&&$&&(0,z.jsx)(ae,{agentId:t,onOpen:A}),(0,z.jsxs)(`div`,{ref:P,className:l(`relative`,$?`max-w-[calc(85%-2rem)] md:max-w-[calc(75%-2rem)]`:`max-w-[85%] md:max-w-[75%]`),children:[oe&&(0,z.jsx)(`button`,{type:`button`,title:Y?`Stop playback`:`Play aloud`,onClick:se,className:l(`absolute -top-2 -right-2 z-20 inline-flex h-6 w-6 items-center justify-center rounded-full border bg-popover shadow-sm transition`,Y?`border-primary/50 text-primary opacity-100`:`border-border text-muted-foreground opacity-70 hover:bg-muted hover:text-foreground hover:opacity-100 [@media(hover:hover)]:md:opacity-0 [@media(hover:hover)]:md:group-hover/msg:opacity-100`),children:Y?(0,z.jsx)(m,{className:`h-3.5 w-3.5 animate-pulse`}):(0,z.jsx)(f,{className:`h-3.5 w-3.5`})}),(0,z.jsxs)(`div`,{className:l(`rounded-2xl px-3.5 py-2 text-sm select-text`,!s&&!E(e)&&`cursor-pointer`,s?`bg-primary text-primary-foreground rounded-br-sm`:`bg-card ring-1 ring-foreground/10 rounded-bl-sm`),onPointerDown:le,onPointerMove:ue,onClick:de,children:[s&&S&&(0,z.jsx)(`p`,{className:l(`text-[11px] font-semibold mb-0.5 text-right`,x(e.from)),children:ee(e.from,g)}),e.subject&&(0,z.jsx)(`p`,{className:l(`text-xs font-semibold mb-1`,s?`text-primary-foreground/70`:`text-muted-foreground`),children:e.subject}),(0,z.jsx)(T,{text:B,rawBody:e.body,issueRepo:h,className:`leading-relaxed`,onPrimary:s,onOpenPath:Z,onPreviewPath:ce,onPreviewPathEnd:a,resolvePathTitle:(e,t)=>`${X(e)}${t?`:${t}`:``}`}),G.map(t=>(0,z.jsx)(V,{attachment:t,outbound:s},`${e.id}-${t.artifactId}-${t.role||``}`)),(0,z.jsxs)(`p`,{className:l(`text-xs mt-1 flex items-center gap-1.5`,s?`justify-end text-primary-foreground/60`:`justify-end text-muted-foreground`),children:[(0,z.jsxs)(`span`,{className:`opacity-40`,children:[`#`,e.id]}),(0,z.jsx)(`span`,{children:W}),q&&J&&(0,z.jsxs)(`span`,{className:l(`inline-flex items-center gap-1`,q.tone===`ok`&&`text-emerald-300`,q.tone===`warn`&&`text-amber-200`,q.tone===`danger`&&`text-red-200`),title:q.title,children:[(0,z.jsx)(J,{className:`h-3 w-3`}),q.label]})]})]}),!E(e)&&K.length>0&&(0,z.jsxs)(`div`,{className:l(`flex flex-wrap items-center gap-0.5 -mt-1 relative z-10`,s?`justify-end pr-2`:`justify-start pl-2`),children:[!s&&(0,z.jsx)(H,{open:M,onToggle:()=>N(e=>!e),onReact:Q}),K.map(e=>(0,z.jsxs)(`button`,{type:`button`,title:e.actors.join(`, `),onClick:()=>Q(e.emoji),className:l(`inline-flex h-5 items-center gap-0.5 rounded-full border px-1.5 text-[11px] shadow-sm transition-colors`,e.mine?`border-primary/40 bg-primary/10 text-primary`:`border-border bg-background hover:bg-muted text-foreground`),children:[(0,z.jsx)(`span`,{children:e.emoji}),e.count>1&&(0,z.jsx)(`span`,{children:e.count})]},e.emoji))]}),!E(e)&&!s&&K.length===0&&(0,z.jsx)(`div`,{className:`absolute -bottom-2.5 left-1 z-20`,children:(0,z.jsx)(H,{open:M,onToggle:()=>N(e=>!e),onReact:Q})})]}),s&&$&&(0,z.jsx)(`span`,{className:`shrink-0 self-end opacity-60`,children:(0,z.jsx)(L,{user:w,address:e.from,distinct:S})})]})});export{W as t};
2
- //# sourceMappingURL=MessageBubble-jpshgh3K.js.map
@@ -1,2 +0,0 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{$ as t,K as n,V as r,Vt as i,Wn as a,Yn as o,Zt as s,_ as c,a as l,er as u,g as d,gt as f,hr as p,nr as m,nt as h,u as g,z as _}from"./lucide-react-Dc3ZwCBi.js";import{f as ee,t as v}from"./store-BuuJUn70.js";import{h as y,p as b}from"./types-uVOXgvMT.js";import{J as x,K as S,W as C,Y as w,a as T,d as E,i as te,n as ne}from"./display-exQDWum3.js";import{o as D,r as O}from"./dist-Cs8X0P1d.js";import{t as k}from"./dist-CQ0Z-TDi.js";import{i as re,n as A}from"./dist-ChDX_t12.js";import{t as j}from"./dist-CBMWGhWc.js";import{t as M}from"./dist-CmFeEXMe.js";import{a as N,i as P,n as F,o as I,r as L,s as ie,t as ae}from"./es2015-VnZ2kVIz.js";import{a as R,i as oe,n as se,r as z,t as B}from"./dist-DV83j9tm.js";import{t as V}from"./badge-BhUZ1cAb.js";import{t as H}from"./button-C-V4oij1.js";import{t as ce}from"./copy-button-BStzXgtd.js";import{t as U}from"./agent-type-icon-BEz393ra.js";import{$ as le,Dt as W,Et as ue,G as de,K as fe,Q as pe,Tt as me,Y as he,et as ge,ot as G,q as _e,tt as ve,vt as ye,wt as be}from"./index-D_fNJnsI.js";import{r as xe,t as Se}from"./card-Br1JLjTH.js";import{i as Ce,n as we,r as Te,t as Ee}from"./branch-state-badge-BYE2U_y4.js";var K=e(p(),1),q=m(),J=`Popover`,[De,Oe]=re(J,[R]),Y=R(),[ke,X]=De(J),Ae=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]=j({prop:r,defaultProp:i??!1,onChange:a,caller:J});return(0,q.jsx)(oe,{...s,children:(0,q.jsx)(ke,{scope:t,contentId:ie(),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})})};Ae.displayName=J;var je=`PopoverAnchor`,Me=K.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=X(je,n),a=Y(n),{onCustomAnchorAdd:o,onCustomAnchorRemove:s}=i;return K.useEffect(()=>(o(),()=>s()),[o,s]),(0,q.jsx)(B,{...a,...r,ref:t})});Me.displayName=je;var Ne=`PopoverTrigger`,Z=K.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=X(Ne,n),a=Y(n),o=D(t,i.triggerRef),s=(0,q.jsx)(k.button,{type:`button`,"aria-haspopup":`dialog`,"aria-expanded":i.open,"aria-controls":i.contentId,"data-state":Ke(i.open),...r,ref:o,onClick:A(e.onClick,i.onOpenToggle)});return i.hasCustomAnchor?s:(0,q.jsx)(B,{asChild:!0,...a,children:s})});Z.displayName=Ne;var Q=`PopoverPortal`,[Pe,Fe]=De(Q,{forceMount:void 0}),Ie=e=>{let{__scopePopover:t,forceMount:n,children:r,container:i}=e,a=X(Q,t);return(0,q.jsx)(Pe,{scope:t,forceMount:n,children:(0,q.jsx)(M,{present:n||a.open,children:(0,q.jsx)(P,{asChild:!0,container:i,children:r})})})};Ie.displayName=Q;var $=`PopoverContent`,Le=K.forwardRef((e,t)=>{let n=Fe($,e.__scopePopover),{forceMount:r=n.forceMount,...i}=e,a=X($,e.__scopePopover);return(0,q.jsx)(M,{present:r||a.open,children:a.modal?(0,q.jsx)(ze,{...i,ref:t}):(0,q.jsx)(Be,{...i,ref:t})})});Le.displayName=$;var Re=O(`PopoverContent.RemoveScroll`),ze=K.forwardRef((e,t)=>{let n=X($,e.__scopePopover),r=K.useRef(null),i=D(t,r),a=K.useRef(!1);return K.useEffect(()=>{let e=r.current;if(e)return ae(e)},[]),(0,q.jsx)(F,{as:Re,allowPinchZoom:!0,children:(0,q.jsx)(Ve,{...e,ref:i,trapFocus:n.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:A(e.onCloseAutoFocus,e=>{e.preventDefault(),a.current||n.triggerRef.current?.focus()}),onPointerDownOutside:A(e.onPointerDownOutside,e=>{let t=e.detail.originalEvent,n=t.button===0&&t.ctrlKey===!0;a.current=t.button===2||n},{checkForDefaultPrevented:!1}),onFocusOutside:A(e.onFocusOutside,e=>e.preventDefault(),{checkForDefaultPrevented:!1})})})}),Be=K.forwardRef((e,t)=>{let n=X($,e.__scopePopover),r=K.useRef(!1),i=K.useRef(!1);return(0,q.jsx)(Ve,{...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()}})}),Ve=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($,n),p=Y(n);return L(),(0,q.jsx)(N,{asChild:!0,loop:!0,trapped:r,onMountAutoFocus:i,onUnmountAutoFocus:a,children:(0,q.jsx)(I,{asChild:!0,disableOutsidePointerEvents:o,onInteractOutside:u,onEscapeKeyDown:s,onPointerDownOutside:c,onFocusOutside:l,onDismiss:()=>f.onOpenChange(!1),children:(0,q.jsx)(z,{"data-state":Ke(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)`}})})})}),He=`PopoverClose`,Ue=K.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=X(He,n);return(0,q.jsx)(k.button,{type:`button`,...r,ref:t,onClick:A(e.onClick,()=>i.onOpenChange(!1))})});Ue.displayName=He;var We=`PopoverArrow`,Ge=K.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=Y(n);return(0,q.jsx)(se,{...i,...r,ref:t})});Ge.displayName=We;function Ke(e){return e?`open`:`closed`}var qe=Ae,Je=Z,Ye=Ie,Xe=Le;function Ze({...e}){return(0,q.jsx)(qe,{"data-slot":`popover`,...e})}function Qe({...e}){return(0,q.jsx)(Je,{"data-slot":`popover-trigger`,...e})}function $e({className:e,align:t=`center`,sideOffset:n=4,...r}){return(0,q.jsx)(Ye,{children:(0,q.jsx)(Xe,{"data-slot":`popover-content`,align:t,sideOffset:n,className:u(`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 et({className:e,...t}){return(0,q.jsx)(`div`,{"data-slot":`popover-header`,className:u(`flex flex-col gap-0.5 text-sm`,e),...t})}function tt({className:e,...t}){return(0,q.jsx)(`div`,{"data-slot":`popover-title`,className:u(`font-medium`,e),...t})}function nt({agent:e,childAgents:r=[],parentAgent:a}){let o=ee();v(e=>e.set);let l=v(e=>e.switchView),u=v(e=>e.openInboxThread),p=v(e=>e.openAgentDetail),m=v(e=>e.openPairInvite),y=v(e=>e.openRename),b=v(e=>e.openConfirm),D=v(e=>e.doAgentAction),O=v(e=>e.doDeleteAgent),k=v(e=>e.openFilesForAgent),re=v(e=>e.workspaceAction),A=v(e=>e.openWorkspaceFocus),{terminalOpen:j,terminalTarget:M,terminalOpening:N,openTerminal:P,closeTerminal:F}=Ce(e.id),I=be(),L=te(o,e,ye(e),I[e.id]||null),ie=T(e,`shutdown`),ae=T(e,`compact`),R=T(e,`clearContext`),oe=!!(e.providerCapabilities?.terminal?.live?.read||e.providerCapabilities?.terminal?.attach?.create),se=!!e.providerCapabilities?.terminal?.live?.write,z=ne(e),B=a?E(a):e.spawnedBy,W=r.length>0;return(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(Se,{className:`group hover:border-zinc-600 transition-colors cursor-pointer`,onClick:()=>p(e),children:(0,q.jsxs)(xe,{className:`p-4`,children:[(0,q.jsxs)(`div`,{className:`flex items-start gap-2.5 mb-2.5`,children:[(0,q.jsx)(G,{agent:e,now:o,className:`mt-0.5`}),(0,q.jsx)(U,{agent:e}),(0,q.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,q.jsxs)(`div`,{className:`flex items-center gap-1 min-w-0`,children:[(0,q.jsx)(we,{profile:Te(e),className:`text-sm shrink-0`}),(0,q.jsx)(`span`,{className:`text-sm font-medium truncate`,children:E(e)})]}),(0,q.jsx)(`div`,{className:`text-xs mt-0.5 ${x(L.tone)}`,children:L.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(),k(e)},children:C(e.meta.cwd)}),(0,q.jsx)(he,{agent:e,className:`mt-1`})]}),e.branchState&&e.branchWorkspaceId&&(0,q.jsx)(Ee,{state:e.branchState,className:`mt-0.5 shrink-0`,onClick:t=>{t.stopPropagation(),A(e.branchWorkspaceId)}})]}),L.badges.length>0&&(0,q.jsx)(`div`,{className:`flex flex-wrap gap-1 mb-2`,children:L.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&&B)&&(0,q.jsxs)(`div`,{className:`mb-2 flex flex-wrap gap-1.5`,onClick:e=>e.stopPropagation(),children:[W&&(0,q.jsxs)(Ze,{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:`${r.length} live child ${r.length===1?`agent`:`agents`}`,children:[(0,q.jsx)(g,{className:`h-3 w-3`}),(0,q.jsx)(`span`,{children:r.length}),(0,q.jsx)(`span`,{className:`flex -space-x-1`,children:r.slice(0,4).map(e=>(0,q.jsx)(G,{agent:e,now:o,className:`h-2 w-2 ring-1 ring-background`},e.id))})]})}),(0,q.jsxs)($e,{align:`start`,className:`w-80`,onClick:e=>e.stopPropagation(),children:[(0,q.jsx)(et,{children:(0,q.jsx)(tt,{children:`Team`})}),(0,q.jsx)(`div`,{className:`space-y-1.5`,children:r.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)(G,{agent:e,now:o,className:`mt-1`}),(0,q.jsx)(U,{agent:e}),(0,q.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,q.jsx)(`div`,{className:`truncate text-xs font-medium`,children:E(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)(V,{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)(H,{size:`xs`,variant:`outline`,onClick:()=>p(e),children:`Open`}),(0,q.jsxs)(H,{size:`xs`,variant:`ghost`,onClick:()=>{u(e.id),l(`chat`)},children:[(0,q.jsx)(h,{className:`h-3 w-3`}),`Chat`]})]})]},e.id))})]})]}),e.spawnedBy&&B&&(0,q.jsx)(V,{variant:`outline`,className:`max-w-full text-[10px] text-muted-foreground`,children:(0,q.jsxs)(`span`,{className:`truncate`,children:[`spawned by `,B]})})]}),(e.tags.length>0||w(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)(V,{variant:`outline`,className:`text-[9px] px-1 py-0 h-4`,children:e},e)),w(e.capabilities).slice(0,2).map(e=>(0,q.jsx)(V,{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)(ge,{agent:e}),(0,q.jsx)(le,{agent:e,compact:!0}),(0,q.jsx)(ve,{agent:e})]}),(0,q.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:e.id!==`user`&&e.id!==`system`&&S(o,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)(H,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Chat`,onClick:()=>{u(e.id),l(`chat`)},children:(0,q.jsx)(h,{className:`w-3 h-3`})}),(0,q.jsx)(H,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Pair`,onClick:()=>m(e.id),children:(0,q.jsx)(f,{className:`w-3 h-3`})}),(0,q.jsx)(H,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Rename`,onClick:()=>y(e),children:(0,q.jsx)(n,{className:`w-3 h-3`})}),oe&&(0,q.jsx)(H,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Terminal`,disabled:N,onClick:()=>void P(),children:(0,q.jsx)(c,{className:`w-3 h-3`})}),(e.branchState===`changes`||e.branchState===`idle`)&&e.branchWorkspaceId&&(0,q.jsx)(H,{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:()=>b(`Mark Workspace Ready`,`Mark ${E(e)}'s branch ready to land? The relay auto-merge will rebase and land it.`,()=>re(e.branchWorkspaceId,`ready`)),children:(0,q.jsx)(i,{className:`w-3 h-3`})}),ae&&(0,q.jsx)(H,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Compact`,onClick:()=>b(`Compact Agent`,`Compact context for ${E(e)}?`,()=>D(e,`compact`,`agents-grid`)),children:(0,q.jsx)(t,{className:`w-3 h-3`})}),R&&(0,q.jsx)(H,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Clear Context`,onClick:()=>b(`Clear Context`,`Clear context for ${E(e)}?`,()=>D(e,`clearContext`,`agents-grid`)),children:(0,q.jsx)(s,{className:`w-3 h-3`})}),ie&&(0,q.jsx)(H,{size:`icon`,variant:`ghost`,className:`h-7 w-7 text-red-400 hover:text-red-300`,title:`Shutdown`,onClick:()=>b(`Shutdown Agent`,`Shutdown ${E(e)}?`,()=>D(e,`shutdown`,`agents-grid`)),children:(0,q.jsx)(_,{className:`w-3 h-3`})}),z&&(0,q.jsx)(H,{size:`icon`,variant:`ghost`,className:`h-7 w-7 text-red-400 hover:text-red-300`,title:`Forget stale agent`,onClick:()=>b(`Forget Agent`,`Forget ${E(e)}?`,()=>O(e.id)),children:(0,q.jsx)(d,{className:`w-3 h-3`})})]})]})}),M&&(0,q.jsx)(pe,{open:j,onOpenChange:F,orchestratorId:M.orchestratorId,session:M.session,interactive:M.interactive||se})]})}function rt(){let e=v(e=>e.agentPresetFilter),t=v(e=>e.agentStatusFilter),n=v(e=>e.agentTagFilter),i=v(e=>e.agentHostFilter),s=v(e=>e.agentSort),c=v(e=>e.agentSortDir),u=v(e=>e.showOffline),d=v(e=>e.set),f=v(e=>e.openAgentSpawn),p=v(e=>e.agentsById),m=ee(),h=me(),g=W(),_=ue(),x=de(h,m),S=_e(h,m),C=e||t||n||i;function w(){d({agentPresetFilter:``,agentStatusFilter:``,agentTagFilter:``,agentHostFilter:``})}function T(){d({agentSortDir:c===`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=>d({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`}),b().map(e=>(0,q.jsx)(`option`,{value:e,children:y(e)},e)),(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=>d({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=>d({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:i,onChange:e=>d({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:s,onChange:e=>d({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)(H,{size:`icon`,variant:`outline`,className:`h-8 w-8`,title:`Toggle sort direction`,onClick:T,children:c===`asc`?(0,q.jsx)(a,{className:`w-3.5 h-3.5`}):(0,q.jsx)(o,{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:u,onChange:e=>d({showOffline:e.target.checked}),className:`rounded`}),`Show offline`]}),C&&(0,q.jsxs)(H,{size:`sm`,variant:`ghost`,className:`h-8 text-muted-foreground hover:text-foreground gap-1`,onClick:w,children:[(0,q.jsx)(l,{className:`w-3 h-3`}),`Clear filters`]}),(0,q.jsx)(`div`,{className:`ml-auto`,children:(0,q.jsxs)(H,{size:`sm`,onClick:f,className:`gap-1`,children:[(0,q.jsx)(r,{className:`w-3.5 h-3.5`}),`Spawn`]})})]}),S.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:S.map(e=>(0,q.jsx)(nt,{agent:e,parentAgent:e.spawnedBy?p[e.spawnedBy]??null:null,childAgents:fe(x.get(e.id)??[])},e.id))})]})}export{rt as AgentsView};
2
- //# sourceMappingURL=agents-QemvuxKO.js.map