agent-relay-server 0.112.0 → 0.114.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 (175) hide show
  1. package/docs/openapi.json +1 -1
  2. package/package.json +3 -3
  3. package/public/assets/MessageBubble-CxqPFLGP.js +4 -0
  4. package/public/assets/{MessageBubble-DtLlfBAK.js.map → MessageBubble-CxqPFLGP.js.map} +1 -1
  5. package/public/assets/PlanGraphPanel-gQ_lb6zP.js +2 -0
  6. package/public/assets/PlanGraphPanel-gQ_lb6zP.js.map +1 -0
  7. package/public/assets/{activity-DRAeL0Jq.js → activity-Dw15HMdi.js} +2 -2
  8. package/public/assets/{activity-DRAeL0Jq.js.map → activity-Dw15HMdi.js.map} +1 -1
  9. package/public/assets/{agent-profiles-cnWPANzx.js → agent-profiles-DNtXbS77.js} +2 -2
  10. package/public/assets/{agent-profiles-cnWPANzx.js.map → agent-profiles-DNtXbS77.js.map} +1 -1
  11. package/public/assets/agents-DOwnLE42.js +2 -0
  12. package/public/assets/{agents-DgUjmk_D.js.map → agents-DOwnLE42.js.map} +1 -1
  13. package/public/assets/{analytics-Q6Dl_CE9.js → analytics-CRwxJWuV.js} +3 -3
  14. package/public/assets/{analytics-Q6Dl_CE9.js.map → analytics-CRwxJWuV.js.map} +1 -1
  15. package/public/assets/automation-BQk8XQEj.js +2 -0
  16. package/public/assets/automation-BQk8XQEj.js.map +1 -0
  17. package/public/assets/{badge-kdQDWO6e.js → badge-oaCc6hVH.js} +2 -2
  18. package/public/assets/{badge-kdQDWO6e.js.map → badge-oaCc6hVH.js.map} +1 -1
  19. package/public/assets/branch-state-badge-JDaHO2fG.js +2 -0
  20. package/public/assets/{branch-state-badge-BRjUWyMT.js.map → branch-state-badge-JDaHO2fG.js.map} +1 -1
  21. package/public/assets/{button-BKFvNXa3.js → button-Cx0NiToX.js} +2 -2
  22. package/public/assets/{button-BKFvNXa3.js.map → button-Cx0NiToX.js.map} +1 -1
  23. package/public/assets/card-DkHdS68K.js +2 -0
  24. package/public/assets/{card-B0y1i_2D.js.map → card-DkHdS68K.js.map} +1 -1
  25. package/public/assets/{channels-DOYB1iiA.js → channels-wQha9YA6.js} +2 -2
  26. package/public/assets/{channels-DOYB1iiA.js.map → channels-wQha9YA6.js.map} +1 -1
  27. package/public/assets/chat-BTmgzO_g.js +2 -0
  28. package/public/assets/{chat-C7XCmaZz.js.map → chat-BTmgzO_g.js.map} +1 -1
  29. package/public/assets/{connectors-C5CeK-2M.js → connectors-BF-XDm0s.js} +2 -2
  30. package/public/assets/{connectors-C5CeK-2M.js.map → connectors-BF-XDm0s.js.map} +1 -1
  31. package/public/assets/copy-button-CsCBPQzj.js +2 -0
  32. package/public/assets/{copy-button-aLaiAkv2.js.map → copy-button-CsCBPQzj.js.map} +1 -1
  33. package/public/assets/{dist-BDYU37NZ.js → dist-1g1lCjVb.js} +2 -2
  34. package/public/assets/{dist-BDYU37NZ.js.map → dist-1g1lCjVb.js.map} +1 -1
  35. package/public/assets/{dist-DnyQI0qt.js → dist-AbnkNPcD.js} +2 -2
  36. package/public/assets/{dist-DnyQI0qt.js.map → dist-AbnkNPcD.js.map} +1 -1
  37. package/public/assets/{dist-EO8jbi2F.js → dist-BJnh7VkB.js} +2 -2
  38. package/public/assets/{dist-EO8jbi2F.js.map → dist-BJnh7VkB.js.map} +1 -1
  39. package/public/assets/dist-C7VlX6hz.js +2 -0
  40. package/public/assets/{dist-BnfqT2cl.js.map → dist-C7VlX6hz.js.map} +1 -1
  41. package/public/assets/{dist-DKoRwEZq.js → dist-DBti5--U.js} +2 -2
  42. package/public/assets/{dist-DKoRwEZq.js.map → dist-DBti5--U.js.map} +1 -1
  43. package/public/assets/{dist-DDh8a_SK.js → dist-DJpDTmGg.js} +2 -2
  44. package/public/assets/{dist-DDh8a_SK.js.map → dist-DJpDTmGg.js.map} +1 -1
  45. package/public/assets/{dist-D_qcpfbI.js → dist-DLOrqIs-.js} +2 -2
  46. package/public/assets/{dist-D_qcpfbI.js.map → dist-DLOrqIs-.js.map} +1 -1
  47. package/public/assets/dist-DjJMNrsj.js +2 -0
  48. package/public/assets/{dist-cyag2tir.js.map → dist-DjJMNrsj.js.map} +1 -1
  49. package/public/assets/{dist-avJPT3qF.js → dist-Pak9TL_I.js} +2 -2
  50. package/public/assets/{dist-avJPT3qF.js.map → dist-Pak9TL_I.js.map} +1 -1
  51. package/public/assets/dist-QY_EIkcd.js +2 -0
  52. package/public/assets/{dist-CF28Y5wI.js.map → dist-QY_EIkcd.js.map} +1 -1
  53. package/public/assets/{dist-DQPz52Zx.js → dist-REUlCFee.js} +2 -2
  54. package/public/assets/{dist-DQPz52Zx.js.map → dist-REUlCFee.js.map} +1 -1
  55. package/public/assets/{es2015-C9FSEGd7.js → es2015-GhJvD7eR.js} +2 -2
  56. package/public/assets/{es2015-C9FSEGd7.js.map → es2015-GhJvD7eR.js.map} +1 -1
  57. package/public/assets/formatted-body-impl-2ZWd80_S.js +3 -0
  58. package/public/assets/formatted-body-impl-2ZWd80_S.js.map +1 -0
  59. package/public/assets/index-D4mb_LKw.js +23 -0
  60. package/public/assets/index-D4mb_LKw.js.map +1 -0
  61. package/public/assets/index-DYwuv_Na.css +2 -0
  62. package/public/assets/{input-DfN6sUbX.js → input-CPfrBmej.js} +2 -2
  63. package/public/assets/{input-DfN6sUbX.js.map → input-CPfrBmej.js.map} +1 -1
  64. package/public/assets/{insights-C0dDL4El.js → insights-DwS0svZy.js} +2 -2
  65. package/public/assets/{insights-C0dDL4El.js.map → insights-DwS0svZy.js.map} +1 -1
  66. package/public/assets/{integrations-CztQfrI7.js → integrations-De1_UHQE.js} +2 -2
  67. package/public/assets/{integrations-CztQfrI7.js.map → integrations-De1_UHQE.js.map} +1 -1
  68. package/public/assets/{lib-DRRHEqRZ.js → lib-Bi-xeh6t.js} +2 -2
  69. package/public/assets/{lib-DRRHEqRZ.js.map → lib-Bi-xeh6t.js.map} +1 -1
  70. package/public/assets/{lucide-react-DmbfpRvJ.js → lucide-react-De5edQpl.js} +2 -2
  71. package/public/assets/{lucide-react-DmbfpRvJ.js.map → lucide-react-De5edQpl.js.map} +1 -1
  72. package/public/assets/{maintenance-DkOkcEkb.js → maintenance-B5qrcsDt.js} +2 -2
  73. package/public/assets/{maintenance-DkOkcEkb.js.map → maintenance-B5qrcsDt.js.map} +1 -1
  74. package/public/assets/{managed-agents-C7Czinaz.js → managed-agents-BGMWAUfG.js} +4 -4
  75. package/public/assets/{managed-agents-C7Czinaz.js.map → managed-agents-BGMWAUfG.js.map} +1 -1
  76. package/public/assets/{markdown-preview-impl-BZ7sigEc.js → markdown-preview-impl-DsZ4Ek80.js} +2 -2
  77. package/public/assets/{markdown-preview-impl-BZ7sigEc.js.map → markdown-preview-impl-DsZ4Ek80.js.map} +1 -1
  78. package/public/assets/memory-CouN7Y4r.js +2 -0
  79. package/public/assets/{memory-Bys-M7GK.js.map → memory-CouN7Y4r.js.map} +1 -1
  80. package/public/assets/messages-D9mYFxhU.js +2 -0
  81. package/public/assets/messages-D9mYFxhU.js.map +1 -0
  82. package/public/assets/{orchestrators-BjLl1Z0L.js → orchestrators-B_SD_mhI.js} +2 -2
  83. package/public/assets/{orchestrators-BjLl1Z0L.js.map → orchestrators-B_SD_mhI.js.map} +1 -1
  84. package/public/assets/overview-C8hVsCqz.js +2 -0
  85. package/public/assets/{overview-BmU7twic.js.map → overview-C8hVsCqz.js.map} +1 -1
  86. package/public/assets/{pairs-xclXjw-c.js → pairs-B6vWKXnX.js} +2 -2
  87. package/public/assets/{pairs-xclXjw-c.js.map → pairs-B6vWKXnX.js.map} +1 -1
  88. package/public/assets/{projects-cOeuiMjl.js → projects-C2gHOdEY.js} +2 -2
  89. package/public/assets/{projects-cOeuiMjl.js.map → projects-C2gHOdEY.js.map} +1 -1
  90. package/public/assets/prompt-settings-D4SXk0af.js +2 -0
  91. package/public/assets/{prompt-settings-CtQd0nz0.js.map → prompt-settings-D4SXk0af.js.map} +1 -1
  92. package/public/assets/{react-dom-jQ4Vs380.js → react-dom-FNIdlE_z.js} +2 -2
  93. package/public/assets/{react-dom-jQ4Vs380.js.map → react-dom-FNIdlE_z.js.map} +1 -1
  94. package/public/assets/registry-CMPhWcx3.js +2 -0
  95. package/public/assets/{registry-CDe6vjKI.js.map → registry-CMPhWcx3.js.map} +1 -1
  96. package/public/assets/{security-C9mBNQMZ.js → security-C1fE4DVg.js} +2 -2
  97. package/public/assets/{security-C9mBNQMZ.js.map → security-C1fE4DVg.js.map} +1 -1
  98. package/public/assets/{select-BJDKQk4q.js → select-D9j1MBVi.js} +2 -2
  99. package/public/assets/{select-BJDKQk4q.js.map → select-D9j1MBVi.js.map} +1 -1
  100. package/public/assets/settings-CduSwUr9.js +6 -0
  101. package/public/assets/{settings-BmZjWJkI.js.map → settings-CduSwUr9.js.map} +1 -1
  102. package/public/assets/{store-DDWg67Pg.js → store-Bk6Lku_S.js} +5 -5
  103. package/public/assets/store-Bk6Lku_S.js.map +1 -0
  104. package/public/assets/{tasks-DNjZKSM2.js → tasks-Bi456f7f.js} +2 -2
  105. package/public/assets/{tasks-DNjZKSM2.js.map → tasks-Bi456f7f.js.map} +1 -1
  106. package/public/assets/{teams-KNzmdolE.js → teams-ZEXvcAz_.js} +2 -2
  107. package/public/assets/{teams-KNzmdolE.js.map → teams-ZEXvcAz_.js.map} +1 -1
  108. package/public/assets/{terminal-viewer-impl-DnFJDl9N.js → terminal-viewer-impl-tktfofs3.js} +3 -3
  109. package/public/assets/{terminal-viewer-impl-DnFJDl9N.js.map → terminal-viewer-impl-tktfofs3.js.map} +1 -1
  110. package/public/assets/types-DSwhOFcJ.js.map +1 -1
  111. package/public/assets/{use-keyboard-viewport-Dw2CHZ50.js → use-keyboard-viewport-wzkGlTqU.js} +2 -2
  112. package/public/assets/{use-keyboard-viewport-Dw2CHZ50.js.map → use-keyboard-viewport-wzkGlTqU.js.map} +1 -1
  113. package/public/assets/user-avatar-_Dq16BWV.js +2 -0
  114. package/public/assets/{user-avatar-C8sbjQke.js.map → user-avatar-_Dq16BWV.js.map} +1 -1
  115. package/public/assets/work-queue-Bk8g7t9K.js +2 -0
  116. package/public/assets/work-queue-Bk8g7t9K.js.map +1 -0
  117. package/public/assets/workspaces-D2bYW3zl.js +3 -0
  118. package/public/assets/workspaces-D2bYW3zl.js.map +1 -0
  119. package/public/index.html +21 -21
  120. package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
  121. package/runner/plugins/claude/skills/task/SKILL.md +28 -0
  122. package/runner/plugins/codex/skills/task/SKILL.md +28 -0
  123. package/src/agent-lifecycle-events.ts +13 -7
  124. package/src/db/mappers.ts +2 -0
  125. package/src/db/migrations.ts +4 -1
  126. package/src/db/provisioning-registry.ts +173 -3
  127. package/src/db/schema.ts +2 -0
  128. package/src/db/task-entity.ts +39 -12
  129. package/src/db/task-memory.ts +1 -1
  130. package/src/mcp/tools-spawn.ts +3 -0
  131. package/src/mcp-dispatch-tools.ts +2 -2
  132. package/src/mcp-task-tools.ts +9 -3
  133. package/src/prompt-resolver.ts +7 -7
  134. package/src/routes/agents-spawn.ts +8 -1
  135. package/src/routes/tasks.ts +7 -2
  136. package/src/services/plan-graph.ts +1 -1
  137. package/src/services/spawn-agent.ts +82 -35
  138. package/src/services/spawn-registration-watchdog.ts +54 -18
  139. package/src/services/task-context-hydration.ts +1 -1
  140. package/src/services/task-issue-weave.ts +2 -2
  141. package/src/services/task-lifecycle.ts +2 -2
  142. package/src/services/task-semantic-events.ts +4 -4
  143. package/src/token-db.ts +1 -1
  144. package/src/validation.ts +1 -1
  145. package/public/assets/MessageBubble-DtLlfBAK.js +0 -4
  146. package/public/assets/PlanGraphPanel-pcKJ4q_4.js +0 -2
  147. package/public/assets/PlanGraphPanel-pcKJ4q_4.js.map +0 -1
  148. package/public/assets/agents-DgUjmk_D.js +0 -2
  149. package/public/assets/automation-CuTlgY1E.js +0 -2
  150. package/public/assets/automation-CuTlgY1E.js.map +0 -1
  151. package/public/assets/branch-state-badge-BRjUWyMT.js +0 -2
  152. package/public/assets/card-B0y1i_2D.js +0 -2
  153. package/public/assets/chat-C7XCmaZz.js +0 -2
  154. package/public/assets/copy-button-aLaiAkv2.js +0 -2
  155. package/public/assets/dist-BnfqT2cl.js +0 -2
  156. package/public/assets/dist-CF28Y5wI.js +0 -2
  157. package/public/assets/dist-cyag2tir.js +0 -2
  158. package/public/assets/formatted-body-impl-rLDPgdmJ.js +0 -3
  159. package/public/assets/formatted-body-impl-rLDPgdmJ.js.map +0 -1
  160. package/public/assets/index-D-Ntiy3M.css +0 -2
  161. package/public/assets/index-DGyeTLPg.js +0 -23
  162. package/public/assets/index-DGyeTLPg.js.map +0 -1
  163. package/public/assets/memory-Bys-M7GK.js +0 -2
  164. package/public/assets/messages-COSJ6trN.js +0 -2
  165. package/public/assets/messages-COSJ6trN.js.map +0 -1
  166. package/public/assets/overview-BmU7twic.js +0 -2
  167. package/public/assets/prompt-settings-CtQd0nz0.js +0 -2
  168. package/public/assets/registry-CDe6vjKI.js +0 -2
  169. package/public/assets/settings-BmZjWJkI.js +0 -6
  170. package/public/assets/store-DDWg67Pg.js.map +0 -1
  171. package/public/assets/user-avatar-C8sbjQke.js +0 -2
  172. package/public/assets/work-queue-DINvPVPn.js +0 -2
  173. package/public/assets/work-queue-DINvPVPn.js.map +0 -1
  174. package/public/assets/workspaces-CSNdUg15.js +0 -3
  175. package/public/assets/workspaces-CSNdUg15.js.map +0 -1
@@ -41,7 +41,7 @@ import type { ProjectSkillsPolicy } from "../project-skills";
41
41
  import { applyDefaultSharedMcp, type SharedMcpSpawnOverride } from "../shared-mcp";
42
42
  import { autoSeedProjectForCwd } from "./project";
43
43
  import { hydrateTaskContext, projectTaskHydration } from "./task-context-hydration";
44
- import { recordTaskEntityDispatchDecision } from "./task-entity";
44
+ import { createTaskEntity, recordTaskEntityDispatchDecision } from "./task-entity";
45
45
  import { autoSubscribeTaskCoordinator } from "./task-semantic-events";
46
46
  import { dispatchTask } from "../task-dispatcher";
47
47
  import { hasComponentScope, isComponentAuthorizedFor } from "../security";
@@ -138,6 +138,11 @@ export interface SpawnAgentInput {
138
138
  * work-shape (#839). Absent = today's behavior, byte-identical.
139
139
  */
140
140
  taskId?: number;
141
+ /**
142
+ * #867 — explicit escape hatch for utility/standby spawns that carry a prompt but are not
143
+ * dispatching deliverable work. Known utility profiles are also exempt by default.
144
+ */
145
+ taskless?: boolean;
141
146
  /** #838 — the latest one-line steer; the actionable instruction layered over the hydrated Task context. */
142
147
  steer?: string;
143
148
  /**
@@ -218,6 +223,7 @@ export interface SpawnAgentResult {
218
223
  agentId: string | null;
219
224
  registered: boolean;
220
225
  command: Command;
226
+ task?: { id: number; autoScaffolded: boolean; nudge: string };
221
227
  }
222
228
 
223
229
  /** Reject when a component token's signed resource constraints disallow the target (#323). */
@@ -248,6 +254,30 @@ function taskSpawnLabel(task: { id: number; title: string } | undefined, fallbac
248
254
  return label.length <= 120 ? label : `${label.slice(0, 117)}...`;
249
255
  }
250
256
 
257
+ const WORK_DISPATCH_PROFILES = new Set(["default-relay", "lean-worker", "worker"]);
258
+ const TASKLESS_PROFILES = new Set(["coordinator", "isolated-research", "minimal", "ops-assistant", "reviewer", "vanilla"]);
259
+ const AUTO_SCAFFOLD_TASK_NUDGE = "No taskId was provided, so Relay auto-scaffolded a Task from the spawn brief and bound this spawn to it. Pass taskId for intentional task reuse, or taskless:true for utility/standby spawns.";
260
+
261
+ function spawnBrief(input: SpawnAgentInput): string | undefined {
262
+ const candidates = [input.steer, input.prompt];
263
+ for (const value of candidates) {
264
+ const cleaned = value?.trim();
265
+ if (cleaned) return cleaned;
266
+ }
267
+ return undefined;
268
+ }
269
+
270
+ function taskTitleFromBrief(brief: string): string {
271
+ const firstLine = brief.split(/\r?\n/).map((line) => line.trim()).find(Boolean) ?? "Spawned work";
272
+ return firstLine.length <= 500 ? firstLine : `${firstLine.slice(0, 497)}...`;
273
+ }
274
+
275
+ function shouldAutoScaffoldTask(input: SpawnAgentInput, profileName: string): boolean {
276
+ if (input.taskId !== undefined || input.taskless === true) return false;
277
+ if (TASKLESS_PROFILES.has(profileName)) return false;
278
+ return WORK_DISPATCH_PROFILES.has(profileName) && spawnBrief(input) !== undefined;
279
+ }
280
+
251
281
  /**
252
282
  * Spawn a provider agent. Transport-agnostic: every gate + side effect lives here so the
253
283
  * MCP and HTTP paths cannot drift. Throws `McpAuthError` (→403) on a gate denial,
@@ -260,7 +290,9 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
260
290
  // the #221 gate AND the #328/#331/#324 caller-context inheritance — one lookup, reused.
261
291
  const callerId = ctx.callerAgentId;
262
292
  const caller: AgentCard | undefined = (callerId ? getAgent(callerId) : undefined) ?? undefined;
263
- const linkedTask = input.taskId !== undefined ? getTaskDetail(input.taskId) ?? undefined : undefined;
293
+ const profileName = input.profile ?? DEFAULT_SPAWN_PROFILE_NAME;
294
+ let autoScaffoldedTask: SpawnAgentResult["task"] | undefined;
295
+ let linkedTask = input.taskId !== undefined ? getTaskDetail(input.taskId) ?? undefined : undefined;
264
296
  const taskCreatorAgentId = !callerId ? agentIdFromTaskCreator(linkedTask?.createdBy) : undefined;
265
297
  const lineageAgentId = callerId ?? taskCreatorAgentId;
266
298
  const lineageAgent: AgentCard | undefined = (lineageAgentId ? getAgent(lineageAgentId) : undefined) ?? undefined;
@@ -285,6 +317,53 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
285
317
  const inheritedCwd = callerCwd && isPathWithinBase(callerCwd, orchestrator.baseDir) ? callerCwd : undefined;
286
318
  const resolvedCwd = requestedCwd || inheritedCwd || orchestrator.baseDir;
287
319
 
320
+ // Resolve + validate the named agent profile server-side (was HTTP-only; the MCP path passed
321
+ // the name through unvalidated). Omitted profile uses Relay's spawn default so coordinator
322
+ // spawns still get the bundled Relay context/affordances. Explicit profile always wins.
323
+ let agentProfile = withResolvedProvisioning(getAgentProfile(profileName)?.value, input.provider);
324
+ if (!agentProfile) throw new McpNotFoundError(input.profile ? "agent profile not found" : `default agent profile ${DEFAULT_SPAWN_PROFILE_NAME} not found`);
325
+
326
+ // --- THE GATE (uniform across transports) ---------------------------------
327
+ // Coarse capability: spawning requires command:spawn. The MCP dispatcher already enforced
328
+ // this; the HTTP route did not — asserting here makes it transport-invariant.
329
+ if (!canSpawn(ctx)) {
330
+ throw new McpAuthError(`spawn requires the ${SPAWN_SCOPE} scope`);
331
+ }
332
+ // #221 — a real spawning agent: no grandchildren, and within its maxSpawnedAgents quota.
333
+ // Server/admin/dashboard tokens carry no caller identity → unrestricted by design.
334
+ if (callerId) {
335
+ if (caller?.spawnedBy) {
336
+ throw new McpAuthError("spawned agents cannot spawn further agents (no grandchildren)");
337
+ }
338
+ const quota = ctx.constraints?.maxSpawnedAgents ?? 0;
339
+ const live = countLiveSpawnedAgents(callerId);
340
+ if (live >= quota) {
341
+ throw new ValidationError(`spawn quota reached (${live}/${quota} live children) — shut one down or wait for one to exit`);
342
+ }
343
+ }
344
+ // Gate the child spawn on the token's legit bounds: the target orchestrator AND the spawn cwd
345
+ // (`cwdPrefixes`/`cwd` constraint). Excludes the #323 footguns (spawnRequestIds/policies) — those
346
+ // are self-scoping per-spawn ids the CHILD gets fresh, so gating on them makes the quota
347
+ // unreachable. The cwd bound was enforced by the old HTTP route (resource.cwd) but NOT by the MCP
348
+ // path; unifying here converges UP to the strict union — a scoped dashboard token still can't spawn
349
+ // outside its cwd prefix, and MCP now honors the same bound.
350
+ assertResourceAllowed(ctx, { scope: "agent:write", resource: { orchestratorId: orchestrator.id, cwd: resolvedCwd } });
351
+
352
+ if (shouldAutoScaffoldTask(input, profileName)) {
353
+ const brief = spawnBrief(input)!;
354
+ const taskRequestedBy = callerId ?? input.requestedBy ?? ctx.actor.id;
355
+ linkedTask = createTaskEntity({
356
+ title: taskTitleFromBrief(brief),
357
+ intent: brief,
358
+ latestSteer: input.steer,
359
+ createdBy: taskRequestedBy,
360
+ source: "spawn",
361
+ target: taskRequestedBy,
362
+ });
363
+ input = { ...input, taskId: linkedTask.id };
364
+ autoScaffoldedTask = { id: linkedTask.id, autoScaffolded: true, nudge: AUTO_SCAFFOLD_TASK_NUDGE };
365
+ }
366
+
288
367
  // #838 — spawn-with-task hydration. When a taskId is given, relay assembles the worker's
289
368
  // first-turn context FROM the durable Task (intent + linked-issue spec/acceptance + recorded
290
369
  // decisions + history + latest steer), resolved server-side ONCE, and projects it onto the
@@ -346,13 +425,6 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
346
425
 
347
426
  const spawnRequestId = input.spawnRequestId ?? generateSpawnRequestId();
348
427
 
349
- // Resolve + validate the named agent profile server-side (was HTTP-only; the MCP path passed
350
- // the name through unvalidated). Omitted profile uses Relay's spawn default so coordinator
351
- // spawns still get the bundled Relay context/affordances. Explicit profile always wins.
352
- const profileName = input.profile ?? DEFAULT_SPAWN_PROFILE_NAME;
353
- let agentProfile = withResolvedProvisioning(getAgentProfile(profileName)?.value, input.provider);
354
- if (!agentProfile) throw new McpNotFoundError(input.profile ? "agent profile not found" : `default agent profile ${DEFAULT_SPAWN_PROFILE_NAME} not found`);
355
-
356
428
  // #667 — project `.mcp.json` projection: a per-spawn `projectMcp` overrides the profile
357
429
  // default. The runner does the filesystem read + injection from `agentProfile.projectMcp`
358
430
  // (it owns the spawn cwd), so thread the resolved decision onto the in-flight profile copy
@@ -368,32 +440,6 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
368
440
  // Explicit opt-in still works for zero-host profiles.
369
441
  agentProfile = applyDefaultSharedMcp(agentProfile, input.sharedMcp);
370
442
 
371
- // --- THE GATE (uniform across transports) ---------------------------------
372
- // Coarse capability: spawning requires command:spawn. The MCP dispatcher already enforced
373
- // this; the HTTP route did not — asserting here makes it transport-invariant.
374
- if (!canSpawn(ctx)) {
375
- throw new McpAuthError(`spawn requires the ${SPAWN_SCOPE} scope`);
376
- }
377
- // #221 — a real spawning agent: no grandchildren, and within its maxSpawnedAgents quota.
378
- // Server/admin/dashboard tokens carry no caller identity → unrestricted by design.
379
- if (callerId) {
380
- if (caller?.spawnedBy) {
381
- throw new McpAuthError("spawned agents cannot spawn further agents (no grandchildren)");
382
- }
383
- const quota = ctx.constraints?.maxSpawnedAgents ?? 0;
384
- const live = countLiveSpawnedAgents(callerId);
385
- if (live >= quota) {
386
- throw new ValidationError(`spawn quota reached (${live}/${quota} live children) — shut one down or wait for one to exit`);
387
- }
388
- }
389
- // Gate the child spawn on the token's legit bounds: the target orchestrator AND the spawn cwd
390
- // (`cwdPrefixes`/`cwd` constraint). Excludes the #323 footguns (spawnRequestIds/policies) — those
391
- // are self-scoping per-spawn ids the CHILD gets fresh, so gating on them makes the quota
392
- // unreachable. The cwd bound was enforced by the old HTTP route (resource.cwd) but NOT by the MCP
393
- // path; unifying here converges UP to the strict union — a scoped dashboard token still can't spawn
394
- // outside its cwd prefix, and MCP now honors the same bound.
395
- assertResourceAllowed(ctx, { scope: "agent:write", resource: { orchestratorId: orchestrator.id, cwd: resolvedCwd } });
396
-
397
443
  // #635 — validate and enrich resumeWorkspace before dispatching to the orchestrator.
398
444
  // The relay has the workspace DB records; the orchestrator has disk access. We do the
399
445
  // "is this a real managed workspace and is it free?" check here, the orchestrator
@@ -606,6 +652,7 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
606
652
  agentId,
607
653
  registered: agentId !== null,
608
654
  command,
655
+ ...(autoScaffoldedTask ? { task: autoScaffoldedTask } : {}),
609
656
  };
610
657
  }
611
658
 
@@ -12,6 +12,14 @@ interface SpawnCommandRow {
12
12
  updated_at: number;
13
13
  }
14
14
 
15
+ interface SpawnCommandGroup {
16
+ spawnRequestId: string;
17
+ parent: string;
18
+ provider?: string;
19
+ latestUpdatedAt: number;
20
+ rows: SpawnCommandRow[];
21
+ }
22
+
15
23
  interface SpawnRegistrationWatchdogResult extends Record<string, unknown> {
16
24
  failedSpawnCommandIds: string[];
17
25
  notifiedSpawnCommandIds: string[];
@@ -30,41 +38,69 @@ export function reapUnregisteredSpawnCommands(
30
38
  FROM commands
31
39
  WHERE type = 'agent.spawn'
32
40
  AND status = 'succeeded'
33
- AND updated_at <= ?
34
41
  ORDER BY updated_at ASC
35
- `).all(cutoff) as SpawnCommandRow[];
42
+ `).all() as SpawnCommandRow[];
36
43
 
37
44
  const failedSpawnCommandIds: string[] = [];
38
45
  const notifiedSpawnCommandIds: string[] = [];
39
46
  const silencedSpawnCommandIds: string[] = [];
40
- for (const row of rows) {
41
- const params = parseParams(row.params);
42
- const spawnRequestId = stringParam(params, "spawnRequestId") ?? row.correlation_id ?? undefined;
43
- const parent = stringParam(params, "spawnedBy");
44
- if (!spawnRequestId || !parent) continue;
45
- if (hasEverRegisteredAgent(spawnRequestId)) continue;
47
+ for (const group of groupSpawnCommands(rows)) {
48
+ if (group.latestUpdatedAt > cutoff) continue;
49
+ if (hasEverRegisteredAgent(group.spawnRequestId)) continue;
46
50
 
47
51
  const reason = `spawned agent did not register within ${deadlineMs}ms`;
48
- const failed = updateCommand(row.id, { status: "failed", error: reason });
49
- if (!failed || failed.status !== "failed") continue;
50
- failedSpawnCommandIds.push(failed.id);
51
- if (row.updated_at >= notifyCutoff) {
52
- notifiedSpawnCommandIds.push(failed.id);
52
+ const failedCommands = group.rows
53
+ .map((row) => updateCommand(row.id, { status: "failed", error: reason }))
54
+ .filter((command): command is NonNullable<typeof command> => Boolean(command && command.status === "failed"));
55
+ if (failedCommands.length === 0) continue;
56
+ failedSpawnCommandIds.push(...failedCommands.map((command) => command.id));
57
+ if (group.latestUpdatedAt >= notifyCutoff) {
58
+ notifiedSpawnCommandIds.push(failedCommands[failedCommands.length - 1]!.id);
53
59
  notifyAgentSpawnFailed({
54
- parent,
55
- spawnRequestId,
56
- provider: stringParam(params, "provider"),
60
+ parent: group.parent,
61
+ spawnRequestId: group.spawnRequestId,
62
+ provider: group.provider,
57
63
  reason,
58
64
  });
59
65
  } else {
60
- silencedSpawnCommandIds.push(failed.id);
66
+ silencedSpawnCommandIds.push(...failedCommands.map((command) => command.id));
67
+ }
68
+ for (const failed of failedCommands) {
69
+ emitCommandEvent(failed, "command.failed");
61
70
  }
62
- emitCommandEvent(failed, "command.failed");
63
71
  }
64
72
 
65
73
  return { failedSpawnCommandIds, notifiedSpawnCommandIds, silencedSpawnCommandIds };
66
74
  }
67
75
 
76
+ function groupSpawnCommands(rows: SpawnCommandRow[]): SpawnCommandGroup[] {
77
+ const groups = new Map<string, SpawnCommandGroup>();
78
+ for (const row of rows) {
79
+ const params = parseParams(row.params);
80
+ const spawnRequestId = stringParam(params, "spawnRequestId") ?? row.correlation_id ?? undefined;
81
+ const parent = stringParam(params, "spawnedBy");
82
+ if (!spawnRequestId || !parent) continue;
83
+ const existing = groups.get(spawnRequestId);
84
+ if (existing) {
85
+ existing.rows.push(row);
86
+ if (row.updated_at >= existing.latestUpdatedAt) {
87
+ existing.parent = parent;
88
+ existing.provider = stringParam(params, "provider");
89
+ existing.latestUpdatedAt = row.updated_at;
90
+ }
91
+ continue;
92
+ }
93
+ groups.set(spawnRequestId, {
94
+ spawnRequestId,
95
+ parent,
96
+ provider: stringParam(params, "provider"),
97
+ latestUpdatedAt: row.updated_at,
98
+ rows: [row],
99
+ });
100
+ }
101
+ return [...groups.values()];
102
+ }
103
+
68
104
  function hasEverRegisteredAgent(spawnRequestId: string): boolean {
69
105
  const row = getDb().query(`
70
106
  SELECT 1
@@ -170,7 +170,7 @@ function hasTaskMemory(envelope: TaskMemoryEnvelope): boolean {
170
170
  function renderTaskMemory(envelope: TaskMemoryEnvelope): string | undefined {
171
171
  if (!hasTaskMemory(envelope)) return undefined;
172
172
  const rendered = renderContinuation(boundedTaskMemoryEnvelope(envelope), {
173
- intro: `Task-bound memory — generation ${envelope.generation}. This is Relay-owned memory bound to Task #${envelope.taskId}; carry these dead ends, decisions, and working state forward.`,
173
+ intro: `Task-bound memory — generation ${envelope.generation}. This is Relay-owned memory bound to Task T${envelope.taskId}; carry these dead ends, decisions, and working state forward.`,
174
174
  });
175
175
  return truncateTaskMemorySection(rendered, TASK_MEMORY_SECTION_LIMIT);
176
176
  }
@@ -112,8 +112,8 @@ interface TaskCommentPayload {
112
112
  }
113
113
 
114
114
  const HEADINGS: Record<TaskCommentKind, (p: TaskCommentPayload) => string> = {
115
- discussion: (p) => `💬 **Comment on Task #${p.taskId}**${p.author ? ` — _${p.author}_` : ""}`,
116
- milestone: (p) => `🏁 **Task #${p.taskId} — ${p.milestone ?? "milestone"}**`,
115
+ discussion: (p) => `💬 **Comment on T${p.taskId}**${p.author ? ` — _${p.author}_` : ""}`,
116
+ milestone: (p) => `🏁 **T${p.taskId} — ${p.milestone ?? "milestone"}**`,
117
117
  };
118
118
 
119
119
  // The payload is base64url-encoded inside the marker, NOT raw JSON: a user/route-supplied
@@ -410,8 +410,8 @@ function emitDeliverableErrorReceipt(input: LandedTaskLifecycleInput, outcome: T
410
410
  recipients: [{ agentId: coordinator, matchedRule: "task-stakeholder" }],
411
411
  ttlMs: null,
412
412
  message: {
413
- subject: `Task #${outcome.taskId} land lifecycle failed`,
414
- body: `Task #${outcome.taskId} landed, but Relay could not complete the task lifecycle automation: ${outcome.error}`,
413
+ subject: `Task T${outcome.taskId} land lifecycle failed`,
414
+ body: `Task T${outcome.taskId} landed, but Relay could not complete the task lifecycle automation: ${outcome.error}`,
415
415
  payload: {
416
416
  kind: "task.lifecycle-error",
417
417
  notification: "task-lifecycle-error",
@@ -271,7 +271,7 @@ function compactStatusPulseItems(items: StatusPulseDigestItem[]): StatusPulseDig
271
271
  function taskStatusPulseBody(items: StatusPulseDigestItem[]): string {
272
272
  const lines = ["Task status pulse:"];
273
273
  for (const item of items) {
274
- const bits = [`#${item.taskId}`, item.transition, item.title];
274
+ const bits = [`T${item.taskId}`, item.transition, item.title];
275
275
  const issue = issueLabel(item.issue);
276
276
  if (issue) bits.push(issue);
277
277
  if (item.branch) bits.push(`branch ${item.branch}`);
@@ -303,13 +303,13 @@ function taskNotificationScope(input: TaskSemanticNotificationInput): Notificati
303
303
  }
304
304
 
305
305
  function taskNotificationSubject(input: TaskSemanticNotificationInput): string {
306
- return `Task #${input.task.id} ${input.transition}`;
306
+ return `Task T${input.task.id} ${input.transition}`;
307
307
  }
308
308
 
309
309
  function taskNotificationBody(input: TaskSemanticNotificationInput): string {
310
310
  const issue = issueLabel(primaryIssue(input.task));
311
311
  if (input.transition === "landed-on-main") {
312
- const bits = [`Task #${input.task.id} landed on main: ${input.task.title}`];
312
+ const bits = [`Task T${input.task.id} landed on main: ${input.task.title}`];
313
313
  if (input.sha) bits.push(`sha ${input.sha.slice(0, 12)}`);
314
314
  const gatesPassed = input.outcome?.gatesPassed;
315
315
  if (typeof gatesPassed === "boolean") bits.push(gatesPassed ? "gates passed" : "gates not verified");
@@ -318,7 +318,7 @@ function taskNotificationBody(input: TaskSemanticNotificationInput): string {
318
318
  return bits.join("; ");
319
319
  }
320
320
  const needed = taskNotificationNeeded(input);
321
- return `Task #${input.task.id} ${input.transition}: ${input.task.title}${issue ? ` (${issue})` : ""}${needed ? `\nNeeded: ${needed}` : ""}`;
321
+ return `Task T${input.task.id} ${input.transition}: ${input.task.title}${issue ? ` (${issue})` : ""}${needed ? `\nNeeded: ${needed}` : ""}`;
322
322
  }
323
323
 
324
324
  function taskNotificationNeeded(input: TaskSemanticNotificationInput): string {
package/src/token-db.ts CHANGED
@@ -67,7 +67,7 @@ const BUILT_IN_PROFILES: Array<Omit<TokenProfile, "createdAt" | "updatedAt">> =
67
67
  name: "Orchestrator Host",
68
68
  description: "Host supervisor access for spawn, command, log, and terminal operations.",
69
69
  role: "orchestrator",
70
- scope: ["agent:read", "agent:write", "command:read", "command:write", "task:read", "task:write", "logs:read", "terminal:attach", "quota:write"],
70
+ scope: ["agent:read", "agent:write", "command:read", "command:write", "task:read", "task:write", "logs:read", "terminal:attach", "quota:write", "provisioning:read"],
71
71
  constraints: { logsRead: true, terminalAttach: true },
72
72
  ttlSeconds: 30 * 24 * 60 * 60,
73
73
  builtIn: true,
package/src/validation.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ValidationError } from "./db";
1
+ import { ValidationError } from "./db/connection.ts";
2
2
  import { type TokenConstraints, type WorkspaceAutoMergePolicy, type WorkspaceLandingPolicy, type WorkspaceMetadata, type WorkspaceMode, type WorkspaceProbe, type WorkspaceStatus } from "./types";
3
3
  import { AUTO_MERGE_POLICIES, VALID_WORKSPACE_MODES, isRecord } from "agent-relay-sdk";
4
4
 
@@ -1,4 +0,0 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{$n as t,$t as n,Cn as r,Gn as i,H as a,Ht as o,Ln as s,Mn as c,Ot as l,R as u,S as d,Tn as f,V as p,Wn as m,Zn as h,_ as g,_n as _,a as v,bn as y,en as b,fn as ee,fr as x,h as S,kt as C,l as te,o as ne,pt as w,r as T,sn as E,tr as D,un as O,ut as re,wn as ie,x as k,xn as A,yn as j}from"./lucide-react-DmbfpRvJ.js";import{r as M,t as N,y as P}from"./store-DDWg67Pg.js";import{o as F}from"./types-DSwhOFcJ.js";import{E as I,H as ae,N as L,P as R,R as oe,S as se,V as ce,_ as le,d as ue,f as de,k as z,q as B,rt as V,v as fe}from"./display-_5kFrHJh.js";import{k as H,n as pe,r as me,s as he,t as U}from"./index-DGyeTLPg.js";import{t as ge}from"./user-avatar-C8sbjQke.js";var W=e(x(),1),_e={online:`came online`,offline:`went offline`,shutdown:`shut down`,restarted:`restarted`,"compaction-requested":`compaction requested`,compacting:`compaction started`,compacted:`context compacted`,"compaction-stalled":`compaction stalled — may need manual intervention`,"clear-requested":`clear requested`,"clearing-context":`clear started`,"context-cleared":`context cleared`,"clear-stalled":`context clear stalled — may need manual intervention`,"shutting-down":`shutting down`},ve=new Set(Object.keys(_e)),ye=3e3;function G(e){return new Date(e.occurredAt??e.createdAt).getTime()}function be(e){if(e.kind!==`session`)return null;let t=e.payload?.session;return!t||t.type!==`narration`&&t.type!==`reasoning`&&t.type!==`tool`?null:{id:e.id,kind:t.type,label:typeof t.label==`string`?t.label:void 0,text:e.body,ts:G(e),turnId:typeof t.turnId==`string`?t.turnId:void 0}}function xe(e){if(e.kind!==`session`)return null;let t=e.payload?.session;if(t?.type!==`notice`)return null;let n=typeof t.label==`string`&&t.label?t.label:`compacted`;return{id:`notice-${e.id}`,status:n,timestamp:G(e)}}function Se(e){if(e.kind!==`session`)return null;let t=e.payload?.session;if(t?.type!==`relay-injection`)return null;let n=t.relayInjection&&typeof t.relayInjection==`object`&&!Array.isArray(t.relayInjection)?t.relayInjection:{},r=typeof n.category==`string`&&[`memory`,`instructions`,`tools`,`comms`,`knowledge`,`context`].includes(n.category)?n.category:`context`,i=typeof n.timestamp==`number`&&Number.isFinite(n.timestamp)?n.timestamp:G(e),a=n.detail&&typeof n.detail==`object`&&!Array.isArray(n.detail)?n.detail:{};return{id:e.id,category:r,summary:typeof n.summary==`string`&&n.summary.trim()?n.summary:e.body,detail:a,agentId:typeof n.agentId==`string`&&n.agentId?n.agentId:e.from,timestamp:i}}function Ce(e){if(e.kind!==`session`)return null;let t=e.payload?.session;if(t?.type!==`prompt-resolution`)return null;let n=t.promptResolution&&typeof t.promptResolution==`object`&&!Array.isArray(t.promptResolution)?t.promptResolution:{},r=n.kind===`questions`||n.kind===`plan`||n.kind===`command`||n.kind===`tool`?n.kind:`tool`,i=typeof n.title==`string`&&n.title.trim()?n.title:`Prompt resolved`,a=typeof n.decisionLabel==`string`&&n.decisionLabel.trim()?n.decisionLabel:typeof t.label==`string`&&t.label.trim()?t.label:`Resolved`,o=n.answers&&typeof n.answers==`object`&&!Array.isArray(n.answers)?n.answers:{};return{id:e.id,title:i,kind:r,body:typeof n.promptBody==`string`?n.promptBody:typeof n.body==`string`?n.body:e.body,toolName:typeof n.toolName==`string`&&n.toolName.trim()?n.toolName:i,decisionLabel:a,questions:we(n.questions,o,a),timestamp:G(e)}}function we(e,t,n){let r=(Array.isArray(e)?e:[]).map((e,r)=>{let i=e&&typeof e==`object`&&!Array.isArray(e)?e:{},a=typeof i.question==`string`&&i.question.trim()?i.question.trim():typeof i.header==`string`&&i.header.trim()?i.header.trim():`Question ${r+1}`,o=t[a]??t[String(i.question??``)]??t[String(i.header??``)];return{question:a,answer:typeof o==`string`&&o.trim()?o.trim():n}});return r.length?r:Object.entries(t).map(([e,t])=>({question:e,answer:t}))}function Te(e,t){let n=e.trim();for(let e of t){let t=e.trim();if(t){if(n===t)break;n.startsWith(`${t}\n\n`)&&(n=n.slice(t.length+2).trimStart())}}return n.trim()||e.trim()}function Ee(e){return e.kind===`system`&&e.from===`system`}var De=new Set([`agent.ready`,`agent.exited`,`agent.spawn_failed`]);function K(e){let t=new Date(e);return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,`0`)}-${String(t.getDate()).padStart(2,`0`)}`}function Oe(e){let t=e.filter(e=>ve.has(e.status)).slice().sort((e,t)=>e.timestamp-t.timestamp),n=[];for(let e of t)n.some(t=>t.id===e.id)||n.some(t=>t.status===e.status&&Math.abs(t.timestamp-e.timestamp)<=ye)||n.push(e);return n}function ke(e,t,n,r=[],i){let a=[];for(let e of r){let t=e.entries.reduce((e,t)=>Math.min(e,B(t.originalCreatedAt)),1/0),n=Number.isFinite(t)?t-1:e.importedAt;a.push({ts:n,entry:{type:`import-boundary`,history:e,timestamp:n}});for(let t of e.entries)a.push({ts:B(t.originalCreatedAt),entry:{type:`imported-message`,history:e,entry:t}})}if(n){let e=new Date(n).getTime();Number.isFinite(e)&&a.push({ts:e,entry:{type:`created`,timestamp:e}})}if(i?.spawnedBy){let e=n?new Date(n).getTime():0,t=Number.isFinite(e)?e:0;a.push({ts:t,entry:{type:`agent-action`,direction:`spawned-by`,agentId:i.spawnedBy.agentId,provider:i.spawnedBy.provider,status:`ready`,timestamp:t}})}let o=i?.spawnedBy?.agentId,s=null,c=1/0;for(let t of e){if(t.kind===`session`||Ee(t)||I(t)||!(t.from===`user`||o!==void 0&&t.from===o)||!z(t).trim())continue;let e=G(t);e<c&&(c=e,s=t.id)}let l=new Map,u=new Map,d=new Map;for(let t of e){if(t.kind!==`session`)continue;let e=t.payload?.session;if(e?.type===`narration`&&typeof e.turnId==`string`){let n=u.get(e.turnId)??[];n.push({id:t.id,body:t.body.trim()}),u.set(e.turnId,n)}else if(e?.type===`response`&&typeof e.turnId==`string`){let n=l.get(e.turnId)??[];n.push(t.body.trim()),l.set(e.turnId,n)}}let f=new Map;for(let[e,t]of l){let n=(u.get(e)??[]).map(e=>e.body);f.set(e,t.map(e=>Te(e,n)))}for(let t of e){if(t.kind!==`session`)continue;let e=t.payload?.session;if(e?.type!==`response`||typeof e.turnId!=`string`)continue;let n=Te(t.body,(u.get(e.turnId)??[]).map(e=>e.body));n&&n!==t.body&&d.set(t.id,n)}let p=new Set;for(let[e,t]of f){let n=u.get(e)??[];for(let e of t)for(let t=n.length-1;t>=0;t--){let r=n[t];if(!p.has(r.id)&&ae(e,r.body)){p.add(r.id);break}}}let m=new Map,h=[];for(let t of e){if(Ee(t)){let e=typeof t.payload?.kind==`string`?t.payload.kind:``;if(De.has(e)){let n=t.payload,r=typeof n.agentId==`string`?n.agentId:``,i=G(t);if(!r){a.push({ts:i,entry:{type:`notice`,msg:t}});continue}let o=e===`agent.ready`?`ready`:e===`agent.exited`?`exited`:`failed`,s=m.get(r);if(s)s.entry.status=o,typeof n.reason==`string`&&(s.entry.reason=n.reason),s.entry.timestamp=i,s.ts=i;else{let e={ts:i,entry:{type:`agent-action`,direction:`spawned-child`,agentId:r,provider:typeof n.provider==`string`?n.provider:void 0,status:o,reason:typeof n.reason==`string`?n.reason:void 0,timestamp:i}};m.set(r,e),a.push(e)}continue}a.push({ts:G(t),entry:{type:`notice`,msg:t}});continue}let e=xe(t);if(e){h.push(e);continue}let n=be(t);if(n){if(n.kind===`narration`&&p.has(n.id))continue;a.push({ts:n.ts,entry:{type:`activity`,steps:[n],timestamp:n.ts}});continue}let r=Se(t);if(r){a.push({ts:r.timestamp,entry:{type:`relay-injection`,event:r}});continue}let i=Ce(t);if(i){a.push({ts:i.timestamp,entry:{type:`prompt-resolution`,event:i}});continue}if(t.kind===`session`){let e=t.payload?.session;if(e?.type===`response`&&typeof e.turnId==`string`){let e=d.get(t.id);if(e&&e!==t.body){a.push({ts:G(t),entry:{type:`message`,msg:{...t,body:e}}});continue}}}let o=t.id===s?`initial-prompt`:`message`;a.push({ts:G(t),entry:{type:o,msg:t}})}for(let e of Oe([...t,...h]))a.push({ts:e.timestamp,entry:{type:`status`,event:e}});let g={created:0,date:1,"import-boundary":2,"imported-message":3,"initial-prompt":4,message:4,activity:4,notice:4,"agent-action":4,"relay-injection":4,"prompt-resolution":4,status:5};a.sort((e,t)=>{let n=e.ts-t.ts;return Math.abs(n)<3e3&&g[e.entry.type]-g[t.entry.type]||n});let _=[],v=``;for(let{ts:e,entry:t}of a){if(t.type===`created`){_.push(t);continue}let n=K(e);if(n!==v&&(_.push({type:`date`,date:n,timestamp:e}),v=n),t.type===`activity`){let e=_[_.length-1];if(e&&e.type===`activity`&&Me(e,t)){e.steps.push(...t.steps);continue}}_.push(t)}return _}function Ae(e){return e.type===`message`?`msg-${e.msg.id}`:e.type===`initial-prompt`?`initprompt-${e.msg.id}`:e.type===`notice`?`notice-${e.msg.id}`:e.type===`relay-injection`?`relay-injection-${e.event.id}`:e.type===`prompt-resolution`?`prompt-resolution-${e.event.id}`:e.type===`agent-action`?`agent-action-${e.direction}-${e.agentId}`:e.type===`activity`?`act-${e.steps[0]?.id??e.timestamp}`:e.type===`import-boundary`?`import-${e.history.id}`:e.type===`imported-message`?`import-msg-${e.history.id}-${e.entry.originalMessageId}-${e.entry.position}`:e.type===`status`?`status-${e.event.id}`:e.type===`date`?`date-${e.date}`:`created-${e.timestamp}`}function je(e){return e.type===`message`||e.type===`initial-prompt`||e.type===`notice`?(e.msg.subject?`${e.msg.subject} `:``)+z(e.msg):e.type===`imported-message`?z(e.entry.message):e.type===`activity`?e.steps.map(e=>[e.label,e.text].filter(Boolean).join(` `)).join(`
2
- `):e.type===`relay-injection`?`${e.event.category} ${e.event.summary}\n${JSON.stringify(e.event.detail)}`:e.type===`prompt-resolution`?[e.event.title,e.event.decisionLabel,e.event.body,...e.event.questions.map(e=>`${e.question} ${e.answer}`)].filter(Boolean).join(`
3
- `):``}function Me(e,t){let n=e.steps[e.steps.length-1]?.turnId,r=t.steps[0]?.turnId;return n&&r?n===r:!n&&!r}function Ne(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/1024/1024).toFixed(1)} MB`}function Pe(e,t){if(t.startsWith(`/`))return t;let n=`${e.replace(/\/+$/,``)}/${t}`.split(`/`),r=[];for(let e of n)!e||e===`.`||(e===`..`?r.pop():r.push(e));return`/`+r.join(`/`)}function Fe(e){let t=e.replace(/\/+$/,``),n=t.lastIndexOf(`/`);return n>0?t.slice(0,n):`/`}function Ie(e,t){return e.filter(e=>e.status===`online`&&oe(t,e.baseDir)).sort((e,t)=>L(t.baseDir).length-L(e.baseDir).length)[0]||e.find(e=>e.status===`online`)}function Le(){return typeof window<`u`&&window.matchMedia(`(min-width: 1280px)`).matches}function Re(){return typeof window<`u`&&!!window.getSelection()?.toString()}function ze(e){let t=e.payload?.attachments;return Array.isArray(t)?t.filter(e=>!!(e&&typeof e==`object`&&typeof e.artifactId==`string`)):[]}var Be=[`👍`,`❤️`,`✅`,`👀`];function Ve(e){let t=new Map;for(let n of e.reactions||[]){let e=R(n.emoji),r=t.get(e)??{emoji:e,count:0,mine:!1,actors:[]};r.count+=1,r.mine=r.mine||n.actorId===`user`,r.actors.push(n.actorId),t.set(e,r)}return[...t.values()].sort((e,t)=>t.count-e.count||e.emoji.localeCompare(t.emoji))}function q(e){return I(e)}function He(e,t){let n=e.readBy||[],r=e.resolvedToAgent||t||e.to,i=r?n.includes(r):!1,a=n.some(e=>e!==V);if(i||a){let e=i?r:n.find(e=>e!==V);return{label:`read`,title:e?`Read by ${e}`:`Read by agent`,tone:`ok`,icon:f}}if(e.deliveryStatus===`delivered`)return{label:`delivered`,title:`Delivered to agent inbox`,tone:`ok`,icon:f};if(e.deliveryStatus===`queued`)return{label:`queued`,title:`Queued until the target agent is available`,tone:`warn`,icon:E};if(e.deliveryStatus===`failed`||e.deliveryStatus===`dead`){let t=e.deliveryPoisonReason||e.deliveryLastError||e.deliveryStatus;return{label:e.deliveryStatus,title:t,tone:`danger`,icon:j}}return{label:`sent`,title:`Accepted by Relay`,tone:`muted`,icon:ie}}function Ue(e){let t=B(e.createdAt);return(e.reactions||[]).reduce((e,t)=>Math.max(e,B(t.updatedAt||t.createdAt)),t)}function We(e){return e?e.messages.reduce((e,t)=>Math.max(e,Ue(t)),0):0}function Ge(e,t,n){return(e-t)*n}function Ke(e){if(!e)return 0;let t=0;for(let n of e.messages)se(n)&&(t=Math.max(t,B(n.createdAt)));return t}function J(e){return new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`})}function qe(e){for(let t of e)t.previewUrl&&URL.revokeObjectURL(t.previewUrl)}function Je(e,t,n,r){if(e?.teamId)return{teamId:e.teamId};let i=[...t];n&&!i.some(e=>e.id===n.id)&&i.push(n);let a=i.filter(e=>e.threadId).reverse(),o=a.find(e=>!!r[M(e.threadId,e.channel)])??a[0];return o?.threadId?{threadId:o.threadId,...o.channel?{channel:o.channel}:{}}:null}var Y=t(),Ye={online:`text-emerald-400`,offline:`text-zinc-400`,shutdown:`text-zinc-400`,restarted:`text-blue-400`,"compaction-requested":`text-zinc-400`,compacting:`text-amber-400`,compacted:`text-amber-400`,"compaction-stalled":`text-red-400`,"clear-requested":`text-zinc-400`,"clearing-context":`text-amber-400`,"context-cleared":`text-amber-400`,"clear-stalled":`text-red-400`,"shutting-down":`text-zinc-400`};function Xe(e){let t=new Date,[n,r,i]=e.split(`-`).map(Number),a=new Date(n,r-1,i);if(e===K(t.getTime()))return`Today`;let o=new Date(t);return o.setDate(o.getDate()-1),e===K(o.getTime())?`Yesterday`:a.toLocaleDateString(void 0,{weekday:`short`,month:`short`,day:`numeric`,year:a.getFullYear()===t.getFullYear()?void 0:`numeric`})}function Ze({event:e}){return(0,Y.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-2 my-1`,children:[(0,Y.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,Y.jsxs)(`div`,{className:`flex items-center gap-1.5 text-xs text-muted-foreground`,children:[(0,Y.jsx)(O,{className:h(`w-2 h-2 fill-current`,Ye[e.status]||`text-zinc-400`)}),(0,Y.jsx)(`span`,{children:_e[e.status]||e.status}),(0,Y.jsx)(`span`,{className:`text-muted-foreground/60`,children:J(e.timestamp)})]}),(0,Y.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}var Qe={"branch.landed":l,"context.warning":S,"agent.context_threshold":S,"agent.resume_budget_exhausted":S,"agent.rate_limit_resume":a},$e={"branch.landed":`branch landed`,"context.warning":`context warning`,"agent.context_threshold":`context threshold reached`};function et(e){return e&&(e.includes(`.`)?e.slice(e.indexOf(`.`)+1):e).replace(/[._-]+/g,` `).trim()||`system signal`}function X({agentId:e,fallbackLabel:t,className:n,noIcon:r}){let i=N(t=>t.agentsById[e])||null,a=N(e=>e.openInboxThread),o=N(e=>e.switchView),s=i?ue(i):t||e;return(0,Y.jsxs)(`button`,{type:`button`,className:h(`inline-flex max-w-full items-center gap-1 rounded px-1 text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground`,n),onClick:t=>{t.stopPropagation(),a(e),o(`chat`)},title:`Open chat for ${s}`,children:[!r&&(0,Y.jsx)(H,{agent:i,className:`w-4 h-4 text-[10px]`}),(0,Y.jsx)(`span`,{className:`max-w-[160px] truncate`,children:s})]})}function tt({msg:e}){let t=e.payload??{},n=rt(e),r=typeof t.sha==`string`?t.sha:``,i=r?r.slice(0,7):``,a=typeof t.author==`string`?t.author:``,o=typeof t.branch==`string`?t.branch:``,s=typeof t.base==`string`?t.base:``,c=t.pushed;return(0,Y.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-2 my-1`,children:[(0,Y.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,Y.jsxs)(`div`,{className:`flex max-w-full flex-wrap items-center justify-center gap-x-1.5 gap-y-0.5 rounded-full border border-emerald-600/35 bg-emerald-500/10 px-2.5 py-1 text-xs text-emerald-700 dark:border-emerald-500/25 dark:text-emerald-300/90`,children:[(0,Y.jsx)(l,{className:`h-3 w-3 shrink-0 text-emerald-600 dark:text-emerald-400`}),(0,Y.jsx)(`span`,{className:`text-emerald-700 dark:text-emerald-300`,children:`branch landed`}),o&&s&&(0,Y.jsxs)(`span`,{className:`font-mono text-emerald-700/80 dark:text-emerald-200/70`,title:`${o} → ${s}`,children:[o,(0,Y.jsx)(`span`,{className:`opacity-50`,children:` → `}),s]}),i&&(0,Y.jsx)(`span`,{className:`rounded bg-emerald-500/15 px-1 font-mono text-emerald-800 dark:text-emerald-200`,title:r,children:i}),a&&(0,Y.jsxs)(`span`,{className:`inline-flex items-center gap-1 text-emerald-700/80 dark:text-emerald-300/80`,children:[(0,Y.jsx)(`span`,{className:`opacity-70`,children:`by`}),(0,Y.jsx)(X,{agentId:a,className:`text-emerald-700 hover:text-emerald-900 dark:text-emerald-300/90 dark:hover:text-emerald-100`})]}),c===!1&&(0,Y.jsx)(`span`,{className:`text-amber-600 dark:text-amber-300/80`,title:`Local-only land — not pushed to origin`,children:`· local only`}),n&&(0,Y.jsxs)(`span`,{className:`max-w-[220px] truncate text-emerald-700/70 dark:text-emerald-300/70`,title:n,children:[`· because `,n]}),(0,Y.jsx)(`span`,{className:`text-emerald-700/60 dark:text-emerald-300/50`,children:J(e.occurredAt??e.createdAt)})]}),(0,Y.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}function nt({msg:e}){let t=typeof e.payload?.kind==`string`?e.payload.kind:``;if(t===`branch.landed`)return(0,Y.jsx)(tt,{msg:e});let n=Qe[t]??u,r=$e[t]??et(t),i=rt(e);return(0,Y.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-2 my-1`,children:[(0,Y.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,Y.jsxs)(`div`,{className:`flex items-center gap-1.5 rounded-full border border-border bg-muted/30 px-2.5 py-1 text-xs text-muted-foreground`,children:[(0,Y.jsx)(n,{className:`h-3 w-3`}),(0,Y.jsx)(`span`,{children:r}),i&&(0,Y.jsxs)(`span`,{className:`max-w-[220px] truncate text-muted-foreground/80`,title:i,children:[`· because `,i]}),(0,Y.jsx)(`span`,{className:`text-muted-foreground/60`,children:J(e.occurredAt??e.createdAt)})]}),(0,Y.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}function rt(e){let t=e.payload?.routing;if(!t||typeof t!=`object`||Array.isArray(t))return``;let n=t.reason;return typeof n==`string`?n:``}var it={"spawned-child":{ready:`spawned`,exited:`spawned · exited`,failed:`spawn failed`},"spawned-by":{ready:`spawned by`,exited:`spawned by`,failed:`spawned by`}},at={"spawned-child-ready":p,"spawned-child-exited":re,"spawned-child-failed":j,"spawned-by-ready":i,"spawned-by-exited":i,"spawned-by-failed":i},ot={"spawned-child-ready":`text-emerald-400`,"spawned-child-exited":`text-zinc-400`,"spawned-child-failed":`text-red-400`,"spawned-by-ready":`text-blue-400`,"spawned-by-exited":`text-blue-400`,"spawned-by-failed":`text-blue-400`};function st({entry:e}){let t=`${e.direction}-${e.status}`,n=it[e.direction]?.[e.status]??e.direction,r=at[t]??u,i=ot[t]??`text-muted-foreground`,a=e.status===`failed`;return(0,Y.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-2 my-1`,children:[(0,Y.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,Y.jsxs)(`div`,{className:h(`flex items-center gap-1.5 rounded-full border bg-muted/30 px-2.5 py-1 text-xs`,a?`border-red-500/30`:`border-border`),children:[(0,Y.jsx)(r,{className:h(`h-3 w-3 shrink-0`,i)}),(0,Y.jsx)(`span`,{className:`text-muted-foreground`,children:n}),(0,Y.jsx)(X,{agentId:e.agentId}),e.reason&&a&&(0,Y.jsxs)(`span`,{className:`text-red-400/80 max-w-[120px] truncate`,title:e.reason,children:[`— `,e.reason]}),(0,Y.jsx)(`span`,{className:`text-muted-foreground/60 shrink-0`,children:J(e.timestamp)})]}),(0,Y.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}var ct={memory:c,instructions:o,tools:ne,comms:u,knowledge:s,context:b},lt={memory:`border-emerald-500/25 bg-emerald-500/10 text-emerald-300`,instructions:`border-sky-500/25 bg-sky-500/10 text-sky-300`,tools:`border-amber-500/25 bg-amber-500/10 text-amber-300`,comms:`border-violet-500/25 bg-violet-500/10 text-violet-300`,knowledge:`border-cyan-500/25 bg-cyan-500/10 text-cyan-300`,context:`border-zinc-500/25 bg-zinc-500/10 text-zinc-300`};function ut(e){try{return JSON.stringify(e,null,2)}catch{return String(e)}}function dt({entry:e}){let[t,n]=(0,W.useState)(!1),r=e.event,i=ct[r.category]??k;return(0,Y.jsx)(`div`,{className:`flex justify-center py-2 my-1`,children:(0,Y.jsxs)(`div`,{className:h(`w-full max-w-[85%] md:max-w-[75%] rounded-lg border px-2.5 py-1.5 text-xs shadow-sm`,lt[r.category]??lt.context),children:[(0,Y.jsxs)(`button`,{type:`button`,className:`flex w-full min-w-0 items-center gap-1.5 text-left`,onClick:()=>n(e=>!e),children:[(0,Y.jsx)(i,{className:`h-3.5 w-3.5 shrink-0`}),(0,Y.jsx)(`span`,{className:`shrink-0 font-medium`,children:r.category}),(0,Y.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-foreground/80`,children:r.summary}),(0,Y.jsx)(`span`,{className:`shrink-0 text-muted-foreground/60`,children:J(r.timestamp)}),(0,Y.jsx)(A,{className:h(`h-3.5 w-3.5 shrink-0 transition-transform`,t&&`rotate-90`)})]}),t&&(0,Y.jsx)(`pre`,{className:`mt-2 max-h-72 overflow-auto rounded-md border border-border/60 bg-background/75 p-2 font-mono text-[11px] leading-relaxed text-muted-foreground whitespace-pre-wrap break-words`,children:ut(r.detail)})]})})}function ft({blockedLabel:e,onInterrupt:t}){return e?(0,Y.jsx)(`div`,{className:`flex justify-start mb-3 animate-in fade-in slide-in-from-bottom-1 duration-150`,children:(0,Y.jsxs)(`div`,{className:`flex h-9 items-center gap-2 rounded-2xl rounded-bl-sm bg-card ring-1 ring-red-500/30 px-4`,children:[(0,Y.jsx)(j,{className:`w-3.5 h-3.5 text-red-400`}),(0,Y.jsxs)(`span`,{className:`text-xs text-red-300`,children:[`blocked: `,e]})]})}):(0,Y.jsx)(`div`,{className:`flex justify-start mb-3 animate-in fade-in slide-in-from-bottom-1 duration-150`,children:(0,Y.jsxs)(`div`,{className:`flex h-9 items-center gap-2 rounded-2xl rounded-bl-sm bg-card ring-1 ring-foreground/10 px-4`,children:[(0,Y.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,Y.jsx)(`span`,{className:`w-1.5 h-1.5 rounded-full bg-yellow-400 animate-[pulse_1.4s_ease-in-out_infinite]`}),(0,Y.jsx)(`span`,{className:`w-1.5 h-1.5 rounded-full bg-yellow-400 animate-[pulse_1.4s_ease-in-out_0.2s_infinite]`}),(0,Y.jsx)(`span`,{className:`w-1.5 h-1.5 rounded-full bg-yellow-400 animate-[pulse_1.4s_ease-in-out_0.4s_infinite]`})]}),(0,Y.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`working`}),t&&(0,Y.jsxs)(`button`,{onClick:t,title:`Interrupt`,className:`ml-1 flex items-center gap-1 rounded-full px-1.5 py-0.5 text-xs text-muted-foreground hover:text-red-300 hover:bg-red-500/10 transition-colors`,children:[(0,Y.jsx)(ee,{className:`w-3.5 h-3.5`}),`Stop`]})]})})}var Z=`agent-relay:chat-hide-tools`,Q=(()=>{let e=new Set,t=(()=>{try{return window.localStorage.getItem(Z)===`on`}catch{return!1}})(),n=()=>e.forEach(e=>e());return typeof window<`u`&&window.addEventListener(`storage`,e=>{e.key===Z&&(t=e.newValue===`on`,n())}),{subscribe(t){return e.add(t),()=>e.delete(t)},get:()=>t,toggle(){t=!t;try{window.localStorage.setItem(Z,t?`on`:`off`)}catch{}n()}}})();function pt(){return[(0,W.useSyncExternalStore)(Q.subscribe,Q.get,()=>!1),Q.toggle]}function mt({steps:e,showReasoning:t,issueRepo:n}){let[r,i]=pt(),a=t?e:e.filter(e=>e.kind!==`reasoning`);if(!a.length)return null;let o=a.filter(e=>e.kind===`tool`).length;return(0,Y.jsx)(`div`,{className:`flex justify-start mb-2`,children:(0,Y.jsxs)(`div`,{className:`max-w-[85%] md:max-w-[75%] min-w-0 space-y-1.5`,children:[a.map(e=>e.kind===`narration`?(0,Y.jsx)(U,{text:e.text,issueRepo:n,className:`text-sm leading-relaxed break-words text-foreground/90 min-w-0`},e.id):e.kind===`reasoning`?(0,Y.jsxs)(`div`,{className:`flex items-start gap-1.5 text-xs leading-relaxed text-muted-foreground/80`,children:[(0,Y.jsx)(c,{className:`w-3.5 h-3.5 mt-0.5 shrink-0 opacity-70`}),(0,Y.jsx)(U,{text:e.text,issueRepo:n,className:`italic break-words min-w-0`})]},e.id):r?null:(0,Y.jsxs)(`div`,{className:`flex items-start gap-1.5 text-xs leading-relaxed text-muted-foreground`,children:[(0,Y.jsx)(g,{className:`w-3 h-3 mt-0.5 shrink-0 opacity-70`}),(0,Y.jsxs)(`span`,{className:`min-w-0 break-words`,children:[(0,Y.jsx)(`span`,{className:`font-medium`,children:e.label||`tool`}),e.text&&e.text.trim()&&e.text.trim()!==(e.label??``).trim()?(0,Y.jsxs)(`span`,{className:`opacity-70`,children:[` — `,e.text]}):null]})]},e.id)),o>0&&(0,Y.jsxs)(`button`,{onClick:i,className:`flex items-center gap-1 text-[11px] text-muted-foreground/50 hover:text-muted-foreground transition-colors text-left`,children:[(0,Y.jsx)(A,{className:h(`w-3 h-3 shrink-0 transition-transform`,!r&&`rotate-90`)}),(0,Y.jsx)(`span`,{children:r?`show ${o} tool step${o===1?``:`s`}`:`hide tool steps`})]})]})})}function ht({entry:e}){let{event:t}=e,n=t.kind===`questions`,r=n?t.title:t.kind===`plan`?`Plan prompt`:`${t.toolName} permission`;return(0,Y.jsx)(`div`,{className:`flex justify-center py-1.5`,children:(0,Y.jsxs)(`div`,{className:`w-full max-w-2xl rounded-md border border-border bg-muted/20 px-3 py-2 text-sm`,children:[(0,Y.jsxs)(`div`,{className:`flex items-center gap-2 text-xs text-muted-foreground`,children:[(0,Y.jsx)(_,{className:`h-3.5 w-3.5 text-emerald-500`}),(0,Y.jsx)(`span`,{className:`font-medium text-foreground`,children:r}),(0,Y.jsx)(`span`,{children:t.decisionLabel}),(0,Y.jsx)(`span`,{className:`ml-auto shrink-0 text-muted-foreground/60`,children:J(t.timestamp)})]}),n&&t.questions.length>0?(0,Y.jsx)(`div`,{className:`mt-2 space-y-1.5`,children:t.questions.map((e,t)=>(0,Y.jsxs)(`div`,{className:`grid gap-0.5`,children:[(0,Y.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:e.question}),(0,Y.jsx)(`div`,{className:`text-sm text-foreground`,children:e.answer})]},`${e.question}-${t}`))}):t.body.trim()?(0,Y.jsx)(`div`,{className:`mt-2 max-h-48 overflow-auto rounded border border-border/70 bg-background/40 px-2 py-1.5 text-sm`,children:(0,Y.jsx)(U,{text:t.body})}):null]})})}function gt({date:e}){return(0,Y.jsxs)(`div`,{className:`flex items-center justify-center gap-3 py-3 my-1`,children:[(0,Y.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,Y.jsx)(`span`,{className:`text-xs font-medium text-muted-foreground`,children:Xe(e)}),(0,Y.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}function _t({timestamp:e}){let t=new Date(e).toLocaleString(void 0,{month:`short`,day:`numeric`,year:`numeric`,hour:`2-digit`,minute:`2-digit`});return(0,Y.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-2 my-1`,children:[(0,Y.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,Y.jsxs)(`span`,{className:`text-xs text-muted-foreground/60`,children:[`created `,t]}),(0,Y.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}function vt({history:e}){let t=e.sourceAgentLabel||e.sourcePeerId,n=e.entries.length;return(0,Y.jsxs)(`div`,{className:`flex items-center justify-center gap-2 py-2 my-1`,children:[(0,Y.jsx)(`div`,{className:`h-px flex-1 bg-border`}),(0,Y.jsxs)(`div`,{className:`flex items-center gap-1.5 rounded-full border border-dashed border-border bg-muted/30 px-2 py-1 text-[11px] text-muted-foreground`,children:[(0,Y.jsx)(C,{className:`h-3 w-3`}),(0,Y.jsxs)(`span`,{children:[`forked history from `,t]}),(0,Y.jsxs)(`span`,{className:`text-muted-foreground/60`,children:[n,` `,n===1?`entry`:`entries`]})]}),(0,Y.jsx)(`div`,{className:`h-px flex-1 bg-border`})]})}function yt({entry:e,sourceLabel:t,issueRepo:n}){let r=e.message,i=z(r),a=e.originalFrom===V;return(0,Y.jsx)(`div`,{className:h(`flex mb-3 opacity-80`,a?`justify-end`:`justify-start`),children:(0,Y.jsx)(`div`,{className:`max-w-[85%] md:max-w-[75%]`,children:(0,Y.jsxs)(`div`,{className:h(`rounded-2xl border border-dashed px-3.5 py-2 text-sm select-text`,a?`border-primary/25 bg-primary/10 text-foreground rounded-br-sm`:`border-border bg-card/70 rounded-bl-sm`),children:[(0,Y.jsxs)(`div`,{className:h(`mb-1 text-[10px] uppercase tracking-normal`,a?`text-primary/70`:`text-muted-foreground`),children:[`forked history · `,a?`you`:t||e.originalFrom]}),(0,Y.jsx)(U,{text:i,rawBody:r.body,issueRepo:n,className:`leading-relaxed`}),(0,Y.jsxs)(`p`,{className:h(`mt-1 flex items-center justify-end gap-1.5 text-xs`,a?`text-primary/60`:`text-muted-foreground`),children:[(0,Y.jsxs)(`span`,{className:`opacity-40`,children:[`#`,e.originalMessageId]}),(0,Y.jsx)(`span`,{children:J(e.originalCreatedAt)})]})]})})})}function $({msg:e,issueRepo:t}){let n=z(e),r=J(e.occurredAt??e.createdAt);return(0,Y.jsx)(`div`,{"data-msg-id":e.id,className:`mb-3`,children:(0,Y.jsxs)(`div`,{className:`rounded-xl border border-primary/30 bg-primary/[0.06] px-3.5 py-2.5 shadow-sm`,children:[(0,Y.jsxs)(`div`,{className:`mb-1.5 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-primary/80`,children:[(0,Y.jsx)(k,{className:`h-3.5 w-3.5`}),(0,Y.jsx)(`span`,{children:`Initial prompt`}),(0,Y.jsx)(`span`,{className:`ml-auto text-[10px] font-normal normal-case text-muted-foreground/60`,children:r})]}),(0,Y.jsx)(U,{text:n,rawBody:e.body,issueRepo:t,className:`text-sm leading-relaxed text-foreground`})]})})}function bt({scrollEl:e,timeline:t}){let[n,i]=(0,W.useState)(!0),[a,o]=(0,W.useState)(null),[s,c]=(0,W.useState)(null),[l,u]=(0,W.useState)(!1),d=(0,W.useMemo)(()=>{for(let e=t.length-1;e>=0;e--){let n=t[e];if(!(!n||n.type!==`message`&&n.type!==`initial-prompt`)&&n.msg.from===`user`)return{id:n.msg.id,body:z(n.msg)}}return null},[t]);if((0,W.useEffect)(()=>{if(!d||!e){i(!0);return}let t=null,n=null,r=()=>{let r=e.querySelector(`[data-msg-id="${d.id}"]`);if(!r){t?.disconnect(),t=null,n=null,i(!1);return}let a=r.getBoundingClientRect(),o=e.getBoundingClientRect();u(a.top<o.top),r!==n&&(t?.disconnect(),n=r,t=new IntersectionObserver(([e])=>{e&&i(e.isIntersecting)},{root:e,threshold:0}),t.observe(r))};return r(),e.addEventListener(`scroll`,r,{passive:!0}),()=>{t?.disconnect(),e.removeEventListener(`scroll`,r)}},[d?.id,e]),n||!d||!d.body.trim())return null;let f=a?.id===d.id?a.value:!1,p=s?.id===d.id?s.value:!1;function m(){!e||!d||e.querySelector(`[data-msg-id="${d.id}"]`)?.scrollIntoView({behavior:`smooth`,block:`center`})}let g=l?`↑`:`↓`;return p?(0,Y.jsx)(`div`,{className:`flex shrink-0 bg-card/45 border-b border-border`,children:(0,Y.jsxs)(`button`,{type:`button`,className:`w-full flex items-center justify-center gap-1.5 py-1 text-[11px] text-primary/60 hover:text-primary transition-colors`,onClick:()=>c({id:d.id,value:!1}),children:[(0,Y.jsx)(`span`,{children:`Your prompt`}),(0,Y.jsx)(r,{className:`w-3 h-3`})]})}):(0,Y.jsxs)(`section`,{className:`flex shrink-0 flex-col border-b border-border bg-card/45 px-3 py-2`,children:[(0,Y.jsxs)(`div`,{className:`flex items-center gap-2 text-[11px] text-muted-foreground mb-0.5`,children:[(0,Y.jsx)(`span`,{className:`font-medium text-primary/70`,children:`Your prompt`}),(0,Y.jsxs)(`button`,{type:`button`,className:`ml-auto hover:text-foreground transition-colors`,onClick:m,children:[g,` scroll to original`]}),(0,Y.jsx)(`button`,{type:`button`,className:`hover:text-foreground transition-colors`,onClick:()=>c({id:d.id,value:!0}),title:`Minimize`,children:(0,Y.jsx)(y,{className:`w-3 h-3`})})]}),(0,Y.jsx)(`p`,{className:h(`text-sm text-foreground leading-snug cursor-pointer`,!f&&`line-clamp-2`),onClick:()=>o({id:d.id,value:!f}),children:d.body})]})}function xt(){return(0,W.useSyncExternalStore)(e=>P.subscribe(e),()=>P.getPlayingKey(),()=>null)}function St({msg:e,peer:t}){return(0,Y.jsx)($,{msg:e,issueRepo:N(e=>e.agentsById[t]?.issueRepo)})}function Ct({agent:e,onClick:t}){let n=!!(t&&e);return(0,Y.jsx)(`button`,{type:`button`,title:e?e.label||e.name||e.id:void 0,onClick:t,disabled:!n,className:h(`shrink-0 self-end transition-opacity`,n?`cursor-pointer hover:opacity-80`:`cursor-default opacity-60`),children:(0,Y.jsx)(H,{agent:e})})}function wt({agentId:e,onOpen:t}){let n=N(t=>t.agentsById[e]??null);return(0,Y.jsx)(Ct,{agent:n,onClick:n?()=>t(n):void 0})}function Tt({attachment:e,outbound:t}){let r=e.kind===`image`,i=e.title||e.artifactId,[a,s]=(0,W.useState)(null),[c,l]=(0,W.useState)(null),[u,d]=(0,W.useState)(!1),[f,p]=(0,W.useState)(!1);(0,W.useEffect)(()=>{let t=!1,n=null;async function r(){d(!0),l(null),s(null);try{let r=await D(`/artifacts/${encodeURIComponent(e.artifactId)}/content`);if(t)return;n=URL.createObjectURL(r),s(n)}catch(e){t||l(e.message)}finally{t||d(!1)}}return r(),()=>{t=!0,n&&URL.revokeObjectURL(n)}},[e.artifactId]);function m(){if(!a)return;let e=document.createElement(`a`);e.href=a,e.download=i,document.body.appendChild(e),e.click(),e.remove()}return r?(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(`button`,{type:`button`,onClick:()=>a&&p(!0),disabled:!a,className:`group/img mt-2 block overflow-hidden rounded-md border border-foreground/10 bg-black/10 text-left disabled:cursor-default relative`,children:a?(0,Y.jsxs)(Y.Fragment,{children:[(0,Y.jsx)(`img`,{src:a,alt:i,loading:`lazy`,className:`block max-h-72 max-w-full object-contain`}),(0,Y.jsx)(`span`,{className:`absolute inset-0 flex items-center justify-center bg-black/0 group-hover/img:bg-black/30 transition-colors`,children:(0,Y.jsx)(T,{className:`w-6 h-6 text-white opacity-0 group-hover/img:opacity-100 transition-opacity drop-shadow-md`})})]}):(0,Y.jsxs)(`span`,{className:h(`flex min-h-20 items-center gap-2 px-3 py-2 text-xs`,c?`text-red-400`:`text-muted-foreground`),children:[u?(0,Y.jsx)(w,{className:`h-4 w-4 animate-spin`}):(0,Y.jsx)(j,{className:`h-4 w-4`}),c||`Loading image`]})}),a&&(0,Y.jsx)(pe,{open:f,onOpenChange:p,children:(0,Y.jsxs)(me,{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,Y.jsx)(he,{className:`sr-only`,children:i}),(0,Y.jsxs)(`div`,{className:`relative flex items-center justify-center min-h-[200px]`,children:[(0,Y.jsx)(`img`,{src:a,alt:i,className:`max-w-[93vw] max-h-[90vh] object-contain`}),(0,Y.jsxs)(`div`,{className:`absolute top-2 right-2 flex gap-1`,children:[(0,Y.jsx)(`button`,{type:`button`,onClick:m,className:`rounded-md bg-black/60 hover:bg-black/80 p-2 text-white transition-colors`,title:`Download`,children:(0,Y.jsx)(n,{className:`w-4 h-4`})}),(0,Y.jsx)(`button`,{type:`button`,onClick:()=>p(!1),className:`rounded-md bg-black/60 hover:bg-black/80 p-2 text-white transition-colors`,title:`Close`,children:(0,Y.jsx)(v,{className:`w-4 h-4`})})]})]})]})})]}):(0,Y.jsxs)(`button`,{type:`button`,onClick:m,disabled:!a,className:h(`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:[u?(0,Y.jsx)(w,{className:`h-4 w-4 shrink-0 animate-spin`}):c?(0,Y.jsx)(j,{className:`h-4 w-4 shrink-0 text-red-400`}):(0,Y.jsx)(o,{className:`h-4 w-4 shrink-0`}),(0,Y.jsx)(`span`,{className:h(`min-w-0 flex-1 truncate`,c&&`text-red-400`),children:c||i}),(0,Y.jsx)(n,{className:`h-3.5 w-3.5 shrink-0`})]})}function Et({open:e,onToggle:t,onReact:n}){return(0,Y.jsxs)(`div`,{className:`relative shrink-0`,children:[(0,Y.jsx)(`button`,{type:`button`,title:`Add reaction`,onClick:t,className:h(`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,Y.jsx)(d,{className:`h-3 w-3`})}),e&&(0,Y.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:Be.map(e=>(0,Y.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 Dt({msg:e,peer:t}){let[n,r]=(0,W.useState)(!1),a=N(e=>e.agentsById),o=N(e=>e.openAgentDetail),s=e.from===t,c=(s?e.to:e.from)||``,l=a[s?t:c]?.issueRepo??a[t]?.issueRepo,u=!c||c===`broadcast`||c.includes(`:`),d=z(e),f=J(e.occurredAt??e.createdAt),p=s?m:i,g=a[e.from??``]??null;function _(e){e.stopPropagation(),g&&o(g)}return(0,Y.jsx)(`div`,{"data-msg-id":e.id,className:`flex justify-center mb-1.5`,children:(0,Y.jsxs)(`div`,{className:`w-full max-w-[94%] rounded-md border border-border/50 bg-muted/15 px-2.5 py-1`,children:[(0,Y.jsxs)(`div`,{className:`flex items-center gap-1.5 text-xs cursor-pointer select-none`,onClick:()=>r(e=>!e),children:[(0,Y.jsx)(A,{className:h(`h-3 w-3 shrink-0 text-muted-foreground/60 transition-transform`,n&&`rotate-90`)}),(0,Y.jsx)(`button`,{type:`button`,title:g?g.label||g.name||g.id:void 0,disabled:!g,onClick:_,className:h(`shrink-0 transition-opacity`,g?`cursor-pointer hover:opacity-80`:`cursor-default opacity-60`),children:(0,Y.jsx)(H,{agent:g,className:`!w-4 !h-4 !rounded-sm opacity-70`})}),(0,Y.jsx)(p,{className:`h-3 w-3 shrink-0 text-muted-foreground/70`}),(0,Y.jsxs)(`span`,{className:`shrink-0 text-muted-foreground`,children:[`Message `,s?`to`:`from`]}),u?(0,Y.jsx)(`span`,{className:`shrink-0 font-medium text-muted-foreground`,children:de(c,a)}):(0,Y.jsx)(X,{agentId:c,className:`shrink-0 px-0.5 text-foreground/80`,noIcon:!0}),!n&&(0,Y.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-muted-foreground/50`,children:d}),(0,Y.jsx)(`span`,{className:`ml-auto shrink-0 text-muted-foreground/40`,children:f})]}),n&&(0,Y.jsx)(`div`,{className:`mt-1.5 pl-5`,children:(0,Y.jsx)(U,{text:d,rawBody:e.body,issueRepo:l,className:`text-sm leading-relaxed text-foreground/90`})})]})})}var Ot=(0,W.memo)(function({msg:e,peer:t,showAvatar:n=!1,onOpenReferencedPath:r,onPreviewReferencedPath:i,onPreviewReferencedPathEnd:a}){if(!F(e.from)&&!F(e.to))return(0,Y.jsx)(Dt,{msg:e,peer:t});let o=e.kind===`session`?e.payload?.session:void 0;if(o?.type===`prompt`&&o?.origin===`provider`)return(0,Y.jsx)(St,{msg:e,peer:t});let s=F(e.from),c=N(e=>e.reactToMessage),l=N(e=>e.voiceTtsEnabled),u=xt(),d=N(e=>{let n=e.agentsById[t]?.meta?.cwd;return typeof n==`string`?n:``}),f=N(e=>e.agentsById[t]?.issueRepo),p=N(e=>e.usersById),m=N(e=>e.users.length>1),g=s?ce(e.from,p):void 0,_=N(e=>e.openAgentDetail),[v,y]=(0,W.useState)(!1),b=(0,W.useRef)(null),x=(0,W.useRef)(null),S=(0,W.useRef)(!1),C=z(e),ne=J(e.occurredAt??e.createdAt),w=ze(e),T=Ve(e),E=s?He(e,t):null,D=E?.icon,O=u===String(e.id),re=l&&!s&&!q(e)&&C.trim().length>0;function ie(t){t.stopPropagation(),O?P.bargeIn():P.speak(e.body,String(e.id))}(0,W.useEffect)(()=>{if(!v)return;function e(e){Re()||b.current&&!b.current.contains(e.target)&&y(!1)}return document.addEventListener(`mousedown`,e),document.addEventListener(`touchstart`,e),()=>{document.removeEventListener(`mousedown`,e),document.removeEventListener(`touchstart`,e)}},[v]);function k(e){return Pe(d||`/`,e)}function A(e,t){let n=k(e);r?.(n,t)}function j(e,t,n){let r=k(e);i?.(r,t,n)}function M(t){c(e,t),y(!1)}function I(e){e.button===0&&(x.current={x:e.clientX,y:e.clientY},S.current=!1)}function ae(e){let t=x.current;t&&(Math.abs(e.clientX-t.x)>3||Math.abs(e.clientY-t.y)>3)&&(S.current=!0)}function L(t){if(!(q(e)||s)&&!t.target.closest(`a,button,input,textarea,select,[role="button"]`)){if(S.current||Re()){S.current=!1;return}y(e=>!e)}}let R=n&&!q(e);return(0,Y.jsxs)(`div`,{"data-msg-id":e.id,className:h(`group/msg flex mb-3 items-end`,s?`justify-end`:`justify-start`,R&&`gap-1.5`),children:[!s&&R&&(0,Y.jsx)(wt,{agentId:t,onOpen:_}),(0,Y.jsxs)(`div`,{ref:b,className:h(`relative`,R?`max-w-[calc(85%-2rem)] md:max-w-[calc(75%-2rem)]`:`max-w-[85%] md:max-w-[75%]`),children:[re&&(0,Y.jsx)(`button`,{type:`button`,title:O?`Stop playback`:`Play aloud`,onClick:ie,className:h(`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`,O?`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:O?(0,Y.jsx)(ee,{className:`h-3.5 w-3.5 animate-pulse`}):(0,Y.jsx)(te,{className:`h-3.5 w-3.5`})}),(0,Y.jsxs)(`div`,{className:h(`rounded-2xl px-3.5 py-2 text-sm select-text`,!s&&!q(e)&&`cursor-pointer`,s?`bg-primary text-primary-foreground rounded-br-sm`:`bg-card ring-1 ring-foreground/10 rounded-bl-sm`),onPointerDown:I,onPointerMove:ae,onClick:L,children:[s&&m&&(0,Y.jsx)(`p`,{className:h(`text-[11px] font-semibold mb-0.5 text-right`,le(e.from)),children:fe(e.from,p)}),e.subject&&(0,Y.jsx)(`p`,{className:h(`text-xs font-semibold mb-1`,s?`text-primary-foreground/70`:`text-muted-foreground`),children:e.subject}),(0,Y.jsx)(U,{text:C,rawBody:e.body,issueRepo:f,className:`leading-relaxed`,onPrimary:s,onOpenPath:A,onPreviewPath:j,onPreviewPathEnd:a,resolvePathTitle:(e,t)=>`${k(e)}${t?`:${t}`:``}`}),w.map(t=>(0,Y.jsx)(Tt,{attachment:t,outbound:s},`${e.id}-${t.artifactId}-${t.role||``}`)),(0,Y.jsxs)(`p`,{className:h(`text-xs mt-1 flex items-center gap-1.5`,s?`justify-end text-primary-foreground/60`:`justify-end text-muted-foreground`),children:[(0,Y.jsxs)(`span`,{className:`opacity-40`,children:[`#`,e.id]}),(0,Y.jsx)(`span`,{children:ne}),E&&D&&(0,Y.jsxs)(`span`,{className:h(`inline-flex items-center gap-1`,E.tone===`ok`&&`text-emerald-300`,E.tone===`warn`&&`text-amber-200`,E.tone===`danger`&&`text-red-200`),title:E.title,children:[(0,Y.jsx)(D,{className:`h-3 w-3`}),E.label]})]})]}),!q(e)&&T.length>0&&(0,Y.jsxs)(`div`,{className:h(`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,Y.jsx)(Et,{open:v,onToggle:()=>y(e=>!e),onReact:M}),T.map(e=>(0,Y.jsxs)(`button`,{type:`button`,title:e.actors.join(`, `),onClick:()=>M(e.emoji),className:h(`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,Y.jsx)(`span`,{children:e.emoji}),e.count>1&&(0,Y.jsx)(`span`,{children:e.count})]},e.emoji))]}),!q(e)&&!s&&T.length===0&&(0,Y.jsx)(`div`,{className:`absolute -bottom-2.5 left-1 z-20`,children:(0,Y.jsx)(Et,{open:v,onToggle:()=>y(e=>!e),onReact:M})})]}),s&&R&&(0,Y.jsx)(`span`,{className:`shrink-0 self-end opacity-60`,children:(0,Y.jsx)(ge,{user:g,address:e.from,distinct:m})})]})});export{We as C,je as E,Le as S,Ae as T,Ke as _,_t as a,Je as b,yt as c,ht as d,dt as f,Ne as g,Ge as h,ft as i,$ as l,bt as m,mt as n,gt as o,Ze as p,st as r,vt as s,Ot as t,nt as u,Ie as v,ke as w,qe as x,Fe as y};
4
- //# sourceMappingURL=MessageBubble-DtLlfBAK.js.map
@@ -1,2 +0,0 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{$n as t,Cn as n,Zn as r,bn as i,er as a,fr as o,jt as s}from"./lucide-react-DmbfpRvJ.js";import{i as c,r as l,t as u}from"./store-DDWg67Pg.js";import{_ as d,f}from"./index-DGyeTLPg.js";var p=e(o(),1),m=`(max-width: 767px)`;function h(e){if(typeof window>`u`)return()=>{};let t=window.matchMedia(m);return t.addEventListener(`change`,e),()=>t.removeEventListener(`change`,e)}function g(){return(0,p.useSyncExternalStore)(h,()=>typeof window<`u`?window.matchMedia(m).matches:!1,()=>!1)}var _=t(),v=196,y=84,b=52,x=16,S=14,C=[`landed`,`in-progress`,`pending`,`blocked`],w={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 T(e){return e?e.label||(e.policyName?`policy:${e.policyName}`:e.agentId||``):``}function E(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 u=[...l.entries()].sort(([e],[t])=>e-t),d=Math.max(1,...u.map(([,e])=>e.length)),f=y+x,p=[];u.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=(d-i.length)*f/2;i.forEach((t,n)=>{p.push({node:t,layer:e,x:S+r*(v+b),y:S+a+n*f})})});let m=u.length;return{nodes:p,width:Math.max(320,S*2+m*v+Math.max(0,m-1)*b),height:Math.max(y+S*2,S*2+d*y+Math.max(0,d-1)*x)}}function D(e,t){let n=e.x+v,r=e.y+y/2,i=t.x,a=t.y+y/2,o=n+Math.max(20,(i-n)/2);return`M ${n} ${r} C ${o} ${r}, ${o} ${a}, ${i} ${a}`}function O({threadId:e,teamId:t,channel:a}){let o=t?c(t,a):e?l(e,a):``,m=u(e=>t?e.plansByTeam[o]:o?e.plansByThread[o]:null),h=u(e=>e.fetchPlan),b=u(e=>e.planCollapsed),x=u(e=>e.setPlanCollapsed),S=u(e=>e.issueRefsById),O=u(e=>e.deliverableTasks),k=u(e=>e.openTaskDetailById),A=g(),j=b??A;(0,p.useEffect)(()=>{if(t){h({teamId:t,channel:a});return}e&&h({threadId:e,channel:a})},[a,h,t,e]);let M=(0,p.useMemo)(()=>m?E(m):null,[m]),N=(0,p.useMemo)(()=>new Map(M?.nodes.map(e=>[e.node.id,e])??[]),[M]),P=(0,p.useMemo)(()=>{if(!m)return[];let e=new Map;for(let t of m.nodes)e.set(t.status,(e.get(t.status)??0)+1);return C.filter(t=>e.has(t)).map(t=>({status:t,count:e.get(t)??0}))},[m]);if(!m||!M)return null;let F=m.nodes.length,I=P.find(e=>e.status===`landed`)?.count??0,L=`${F} node${F===1?``:`s`}${I>0?` · ${I} landed`:``}`;return(0,_.jsxs)(`section`,{className:`shrink-0 border-b border-border bg-card/45 px-3 py-2`,children:[(0,_.jsxs)(`button`,{type:`button`,onClick:()=>x(!j),"aria-expanded":!j,"aria-label":j?`Expand plan graph`:`Collapse plan graph`,className:r(`flex w-full min-w-0 items-center gap-2 text-left`,!j&&`mb-2`),children:[(0,_.jsx)(`span`,{className:`flex h-5 w-5 shrink-0 items-center justify-center rounded bg-muted/60`,children:(0,_.jsx)(s,{className:`h-3 w-3 text-muted-foreground`})}),(0,_.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,_.jsx)(`div`,{className:`truncate text-[13px] font-semibold leading-tight text-foreground`,children:m.title||`Plan`}),(0,_.jsx)(`div`,{className:`truncate text-[11px] leading-tight text-muted-foreground`,children:j?L:m.objective||L})]}),P.length>0&&(0,_.jsx)(`div`,{className:`hidden shrink-0 items-center gap-2.5 sm:flex`,children:P.map(({status:e,count:t})=>(0,_.jsxs)(`span`,{className:`flex items-center gap-1 text-[10px] text-muted-foreground`,children:[(0,_.jsx)(`span`,{className:r(`h-1.5 w-1.5 rounded-full`,w[e].dot)}),(0,_.jsx)(`span`,{className:r(`font-medium tabular-nums`,w[e].text),children:t}),(0,_.jsx)(`span`,{children:w[e].label})]},e))}),(0,_.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`,m.version]}),(0,_.jsx)(`span`,{className:`flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-muted/60 hover:text-foreground`,children:j?(0,_.jsx)(n,{className:`h-3.5 w-3.5`}):(0,_.jsx)(i,{className:`h-3.5 w-3.5`})})]}),j?null:m.nodes.length===0?(0,_.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,_.jsx)(`div`,{className:`max-h-[min(46vh,360px)] overflow-auto`,children:(0,_.jsxs)(`div`,{className:`relative`,style:{width:M.width,height:M.height},children:[(0,_.jsxs)(`svg`,{className:`pointer-events-none absolute inset-0`,width:M.width,height:M.height,"aria-hidden":`true`,children:[(0,_.jsx)(`defs`,{children:C.map(e=>(0,_.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,_.jsx)(`path`,{d:`M0 0 L8 4 L0 8 z`,fill:w[e].wire})},e))}),m.edges.map(e=>{let t=N.get(e.from),n=N.get(e.to);if(!t||!n)return null;let r=w[t.node.status];return(0,_.jsx)(`path`,{d:D(t,n),stroke:r.wire,strokeOpacity:.7,strokeWidth:2,fill:`none`,strokeLinecap:`round`,markerEnd:`url(#plan-arrow-${t.node.status})`},`${e.from}->${e.to}`)})]}),M.nodes.map(({node:e,x:t,y:n})=>{let i=w[e.status],a=T(e.ownerRef),o=e.refs?.issueId?S[e.refs.issueId]:null,s=e.refs?.taskId?parseInt(e.refs.taskId,10):null,c=s==null?void 0:O.find(e=>e.id===s)?.title;return(0,_.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:v,height:y},title:e.scopeBlurb||e.label,children:[(0,_.jsx)(`div`,{className:`truncate text-xs font-semibold leading-tight text-foreground`,children:e.label}),(e.scopeBlurb||e.id)&&(0,_.jsx)(`div`,{className:`truncate text-[10px] leading-tight text-muted-foreground`,children:e.scopeBlurb||e.id}),(o||s!=null)&&(0,_.jsxs)(`div`,{className:`flex min-w-0 flex-wrap gap-1`,children:[o&&(0,_.jsx)(d,{issueRef:o,compact:!0,className:`max-w-full`}),s!=null&&(0,_.jsx)(f,{id:s,title:c,onClick:()=>k(s),className:`max-w-full`})]}),(0,_.jsxs)(`div`,{className:`flex min-w-0 items-center justify-between gap-1.5`,children:[(0,_.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1.5`,children:[(0,_.jsx)(`span`,{className:r(`h-1.5 w-1.5 shrink-0 rounded-full`,i.dot)}),(0,_.jsx)(`span`,{className:r(`text-[10px] font-medium`,i.text),children:i.label})]}),(0,_.jsxs)(`div`,{className:`flex min-w-0 items-center gap-1.5`,children:[a&&(0,_.jsx)(`span`,{className:`truncate text-[10px] text-muted-foreground`,children:a}),e.lane&&(0,_.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)})]})})]})}function k({agentId:e}){let t=u(e=>e.openTaskDetailById),[n,r]=(0,p.useState)([]);return(0,p.useEffect)(()=>{a(`GET`,`/task-entities?createdBy=`+encodeURIComponent(e)).then(e=>r(e)).catch(()=>{})},[e]),n.length===0?null:(0,_.jsxs)(`section`,{className:`shrink-0 border-b border-border bg-card/45 px-3 py-2`,children:[(0,_.jsxs)(`div`,{className:`mb-1.5 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground`,children:[`Tasks from this session (`,n.length,`)`]}),(0,_.jsx)(`div`,{className:`flex flex-wrap gap-1.5`,children:n.map(e=>(0,_.jsx)(f,{id:e.id,title:e.title,status:e.status,onClick:()=>t(e.id)},e.id))})]})}export{k as n,O as t};
2
- //# sourceMappingURL=PlanGraphPanel-pcKJ4q_4.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PlanGraphPanel-pcKJ4q_4.js","names":[],"sources":["../../dashboard/src/components/chat/hooks/useIsMobile.ts","../../dashboard/src/components/chat/PlanGraphPanel.tsx"],"sourcesContent":["import { useSyncExternalStore } from 'react'\n\n// Reactive narrow-viewport flag. Subscribes to the same `max-width: 767px`\n// breakpoint the chat single-pane layout uses, via useSyncExternalStore — an\n// external-store subscription, not effect-driven derived state — so it stays\n// correct across resize/rotate without a useEffect.\nconst QUERY = '(max-width: 767px)'\n\nfunction subscribe(cb: () => void): () => void {\n if (typeof window === 'undefined') return () => {}\n const mql = window.matchMedia(QUERY)\n mql.addEventListener('change', cb)\n return () => mql.removeEventListener('change', cb)\n}\n\nexport function useIsMobile(): boolean {\n return useSyncExternalStore(\n subscribe,\n () => (typeof window !== 'undefined' ? window.matchMedia(QUERY).matches : false),\n () => false,\n )\n}\n","import { useEffect, useMemo, useState } from 'react'\nimport { ChevronDown, ChevronUp, GitBranch } from 'lucide-react'\nimport { useRelayStore } from '@/store'\nimport type { Plan, PlanNode, PlanOwnerRef, PlanStatus, Task } from '@/types'\nimport { cn } from '@/lib/utils'\nimport { planLookupKey, planTeamLookupKey } from '@/store/slices/plans'\nimport { IssueRefChip } from '@/components/shared/issue-ref-chip'\nimport { TaskChip } from '@/components/shared/task-chip'\nimport { useIsMobile } from './hooks/useIsMobile'\nimport { api } from '@/lib/api'\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 = 84\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 const planCollapsed = useRelayStore((s) => s.planCollapsed)\n const setPlanCollapsed = useRelayStore((s) => s.setPlanCollapsed)\n const issueRefsById = useRelayStore((s) => s.issueRefsById)\n const deliverableTasks = useRelayStore((s) => s.deliverableTasks)\n const openTaskDetailById = useRelayStore((s) => s.openTaskDetailById)\n const isMobile = useIsMobile()\n // null = no manual toggle yet → follow the viewport default. The graph\n // dominates a phone screen, so it starts collapsed there and expanded on\n // desktop; an explicit user toggle (persisted) overrides the default.\n const collapsed = planCollapsed ?? isMobile\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 const nodeCount = plan.nodes.length\n const landedCount = legend.find((entry) => entry.status === 'landed')?.count ?? 0\n // Thin summary for the collapsed bar (the legend dots are hidden on mobile),\n // e.g. \"5 nodes · 4 landed\".\n const summary = `${nodeCount} node${nodeCount === 1 ? '' : 's'}${landedCount > 0 ? ` · ${landedCount} landed` : ''}`\n\n return (\n <section className=\"shrink-0 border-b border-border bg-card/45 px-3 py-2\">\n <button\n type=\"button\"\n onClick={() => setPlanCollapsed(!collapsed)}\n aria-expanded={!collapsed}\n aria-label={collapsed ? 'Expand plan graph' : 'Collapse plan graph'}\n className={cn(\n 'flex w-full min-w-0 items-center gap-2 text-left',\n !collapsed && 'mb-2',\n )}\n >\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 <div className=\"truncate text-[11px] leading-tight text-muted-foreground\">\n {collapsed ? summary : (plan.objective || summary)}\n </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 <span className=\"flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-muted/60 hover:text-foreground\">\n {collapsed ? <ChevronDown className=\"h-3.5 w-3.5\" /> : <ChevronUp className=\"h-3.5 w-3.5\" />}\n </span>\n </button>\n {collapsed ? null : 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 const issueRef = node.refs?.issueId ? issueRefsById[node.refs.issueId] : null\n const taskNumId = node.refs?.taskId ? parseInt(node.refs.taskId, 10) : null\n const taskTitle = taskNumId != null ? deliverableTasks.find((t) => t.id === taskNumId)?.title : undefined\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 {(issueRef || taskNumId != null) && (\n <div className=\"flex min-w-0 flex-wrap gap-1\">\n {issueRef && <IssueRefChip issueRef={issueRef} compact className=\"max-w-full\" />}\n {taskNumId != null && (\n <TaskChip id={taskNumId} title={taskTitle} onClick={() => openTaskDetailById(taskNumId)} className=\"max-w-full\" />\n )}\n </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\n// Tasks created/triggered from a session (#856, #860). Fetches server-side via createdBy filter.\nexport function SessionTasksPanel({ agentId }: { agentId: string }) {\n const openTaskDetailById = useRelayStore((s) => s.openTaskDetailById)\n const [sessionTasks, setSessionTasks] = useState<Task[]>([])\n useEffect(() => {\n void api<import('@/types').Task[]>('GET', '/task-entities?createdBy=' + encodeURIComponent(agentId))\n .then((tasks) => setSessionTasks(tasks))\n .catch(() => {})\n }, [agentId])\n if (sessionTasks.length === 0) return null\n return (\n <section className=\"shrink-0 border-b border-border bg-card/45 px-3 py-2\">\n <div className=\"mb-1.5 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground\">\n Tasks from this session ({sessionTasks.length})\n </div>\n <div className=\"flex flex-wrap gap-1.5\">\n {sessionTasks.map((task) => (\n <TaskChip\n key={task.id}\n id={task.id}\n title={task.title}\n status={task.status}\n onClick={() => openTaskDetailById(task.id)}\n />\n ))}\n </div>\n </section>\n )\n}\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{$ as t,$n as n,Bt as r,Jn as i,K as a,Un as o,V as s,Xt as c,Zn as l,_ as u,a as d,fr as f,g as p,ht as m,nt as h,u as g,z as _}from"./lucide-react-DmbfpRvJ.js";import{f as ee,t as v}from"./store-DDWg67Pg.js";import{h as y,p as b}from"./types-DSwhOFcJ.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-_5kFrHJh.js";import{o as D,r as O}from"./dist-DKoRwEZq.js";import{t as k}from"./dist-DnyQI0qt.js";import{i as re,n as A}from"./dist-DQPz52Zx.js";import{t as j}from"./dist-EO8jbi2F.js";import{t as M}from"./dist-D_qcpfbI.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-C9FSEGd7.js";import{a as R,i as oe,n as se,r as z,t as B}from"./dist-BDYU37NZ.js";import{t as V}from"./badge-kdQDWO6e.js";import{t as H}from"./button-BKFvNXa3.js";import{t as ce}from"./copy-button-aLaiAkv2.js";import{A as U,C as le,H as ue,J as de,S as fe,X as W,Y as pe,Z as me,g as he,h as ge,k as G,m as _e,v as ve,w as ye,x as be}from"./index-DGyeTLPg.js";import{r as xe,t as Se}from"./card-B0y1i_2D.js";import{i as Ce,n as we,r as Te,t as Ee}from"./branch-state-badge-BRjUWyMT.js";var K=e(f(),1),q=n(),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:l(`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:l(`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:l(`font-medium`,e),...t})}function nt({agent:e,childAgents:n=[],parentAgent:i}){let o=ee();v(e=>e.set);let s=v(e=>e.switchView),l=v(e=>e.openInboxThread),d=v(e=>e.openAgentDetail),f=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=de(),L=te(o,e,ue(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=i?E(i):e.spawnedBy,W=n.length>0;return(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(Se,{className:`group hover:border-zinc-600 transition-colors cursor-pointer`,onClick:()=>d(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)(U,{agent:e,now:o,className:`mt-0.5`}),(0,q.jsx)(G,{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)(ve,{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:`${n.length} live child ${n.length===1?`agent`:`agents`}`,children:[(0,q.jsx)(g,{className:`h-3 w-3`}),(0,q.jsx)(`span`,{children:n.length}),(0,q.jsx)(`span`,{className:`flex -space-x-1`,children:n.slice(0,4).map(e=>(0,q.jsx)(U,{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:n.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)(U,{agent:e,now:o,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: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:()=>d(e),children:`Open`}),(0,q.jsxs)(H,{size:`xs`,variant:`ghost`,onClick:()=>{l(e.id),s(`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)(le,{agent:e}),(0,q.jsx)(fe,{agent:e,compact:!0}),(0,q.jsx)(ye,{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:()=>{l(e.id),s(`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:()=>f(e.id),children:(0,q.jsx)(m,{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)(a,{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)(u,{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)(r,{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)(c,{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)(p,{className:`w-3 h-3`})})]})]})}),M&&(0,q.jsx)(be,{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),r=v(e=>e.agentHostFilter),a=v(e=>e.agentSort),c=v(e=>e.agentSortDir),l=v(e=>e.showOffline),u=v(e=>e.set),f=v(e=>e.openAgentSpawn),p=v(e=>e.agentsById),m=ee(),h=pe(),g=me(),_=W(),x=_e(h,m),S=he(h,m),C=e||t||n||r;function w(){u({agentPresetFilter:``,agentStatusFilter:``,agentTagFilter:``,agentHostFilter:``})}function T(){u({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=>u({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=>u({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=>u({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=>u({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:a,onChange:e=>u({agentSort:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,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)(o,{className:`w-3.5 h-3.5`}):(0,q.jsx)(i,{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:l,onChange:e=>u({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)(d,{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)(s,{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:ge(x.get(e.id)??[])},e.id))})]})}export{rt as AgentsView};
2
- //# sourceMappingURL=agents-DgUjmk_D.js.map