agent-relay-server 0.108.0 → 0.110.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 (176) hide show
  1. package/docs/openapi.json +143 -1
  2. package/package.json +3 -3
  3. package/public/assets/MessageBubble-CmqJMGYF.js +4 -0
  4. package/public/assets/{MessageBubble-DYJezSjU.js.map → MessageBubble-CmqJMGYF.js.map} +1 -1
  5. package/public/assets/PlanGraphPanel-K6aFJmdd.js +2 -0
  6. package/public/assets/PlanGraphPanel-K6aFJmdd.js.map +1 -0
  7. package/public/assets/activity-DyqKrJe_.js +2 -0
  8. package/public/assets/activity-DyqKrJe_.js.map +1 -0
  9. package/public/assets/{agent-profiles-Di2w5U1o.js → agent-profiles-DRQ5vbPo.js} +2 -2
  10. package/public/assets/{agent-profiles-Di2w5U1o.js.map → agent-profiles-DRQ5vbPo.js.map} +1 -1
  11. package/public/assets/agents-BJ9sm23O.js +2 -0
  12. package/public/assets/{agents-GSJXvmU1.js.map → agents-BJ9sm23O.js.map} +1 -1
  13. package/public/assets/{analytics-B9USQLl5.js → analytics-Q6Dl_CE9.js} +3 -3
  14. package/public/assets/{analytics-B9USQLl5.js.map → analytics-Q6Dl_CE9.js.map} +1 -1
  15. package/public/assets/{automation-XRePs1dT.js → automation-CJ2-uiYt.js} +2 -2
  16. package/public/assets/{automation-XRePs1dT.js.map → automation-CJ2-uiYt.js.map} +1 -1
  17. package/public/assets/{badge-D8fABzMs.js → badge-kdQDWO6e.js} +2 -2
  18. package/public/assets/{badge-D8fABzMs.js.map → badge-kdQDWO6e.js.map} +1 -1
  19. package/public/assets/{branch-state-badge-C_VNyER3.js → branch-state-badge-BRjUWyMT.js} +2 -2
  20. package/public/assets/{branch-state-badge-C_VNyER3.js.map → branch-state-badge-BRjUWyMT.js.map} +1 -1
  21. package/public/assets/{button-KASZcscA.js → button-BKFvNXa3.js} +2 -2
  22. package/public/assets/{button-KASZcscA.js.map → button-BKFvNXa3.js.map} +1 -1
  23. package/public/assets/card-B0y1i_2D.js +2 -0
  24. package/public/assets/{card-Cds0MWME.js.map → card-B0y1i_2D.js.map} +1 -1
  25. package/public/assets/{channels-DACvNoC2.js → channels-DOYB1iiA.js} +2 -2
  26. package/public/assets/{channels-DACvNoC2.js.map → channels-DOYB1iiA.js.map} +1 -1
  27. package/public/assets/chat-D0VtHShz.js +2 -0
  28. package/public/assets/{chat-D_0uHgB6.js.map → chat-D0VtHShz.js.map} +1 -1
  29. package/public/assets/{connectors-C0B38LUK.js → connectors-C5CeK-2M.js} +2 -2
  30. package/public/assets/{connectors-C0B38LUK.js.map → connectors-C5CeK-2M.js.map} +1 -1
  31. package/public/assets/{copy-button-d9DFNX9v.js → copy-button-aLaiAkv2.js} +2 -2
  32. package/public/assets/{copy-button-d9DFNX9v.js.map → copy-button-aLaiAkv2.js.map} +1 -1
  33. package/public/assets/{display-1J__Ti1K.js → display-_5kFrHJh.js} +3 -3
  34. package/public/assets/{display-1J__Ti1K.js.map → display-_5kFrHJh.js.map} +1 -1
  35. package/public/assets/{dist-DOAjFOS4.js → dist-BDYU37NZ.js} +2 -2
  36. package/public/assets/{dist-DOAjFOS4.js.map → dist-BDYU37NZ.js.map} +1 -1
  37. package/public/assets/dist-BnfqT2cl.js +2 -0
  38. package/public/assets/{dist-DC-TqTz2.js.map → dist-BnfqT2cl.js.map} +1 -1
  39. package/public/assets/dist-CF28Y5wI.js +2 -0
  40. package/public/assets/{dist-CBVZk9U8.js.map → dist-CF28Y5wI.js.map} +1 -1
  41. package/public/assets/{dist-DTXKbk2K.js → dist-DDh8a_SK.js} +2 -2
  42. package/public/assets/{dist-DTXKbk2K.js.map → dist-DDh8a_SK.js.map} +1 -1
  43. package/public/assets/{dist-BbUJ1Vht.js → dist-DKoRwEZq.js} +2 -2
  44. package/public/assets/{dist-BbUJ1Vht.js.map → dist-DKoRwEZq.js.map} +1 -1
  45. package/public/assets/{dist-UhEAFdvZ.js → dist-DQPz52Zx.js} +2 -2
  46. package/public/assets/{dist-UhEAFdvZ.js.map → dist-DQPz52Zx.js.map} +1 -1
  47. package/public/assets/{dist-CgqfdHSt.js → dist-D_qcpfbI.js} +2 -2
  48. package/public/assets/{dist-CgqfdHSt.js.map → dist-D_qcpfbI.js.map} +1 -1
  49. package/public/assets/{dist-DybScJmm.js → dist-DnyQI0qt.js} +2 -2
  50. package/public/assets/{dist-DybScJmm.js.map → dist-DnyQI0qt.js.map} +1 -1
  51. package/public/assets/{dist-BwwlmyBq.js → dist-EO8jbi2F.js} +2 -2
  52. package/public/assets/{dist-BwwlmyBq.js.map → dist-EO8jbi2F.js.map} +1 -1
  53. package/public/assets/{dist-BlZvUZZB.js → dist-avJPT3qF.js} +2 -2
  54. package/public/assets/{dist-BlZvUZZB.js.map → dist-avJPT3qF.js.map} +1 -1
  55. package/public/assets/dist-cyag2tir.js +2 -0
  56. package/public/assets/{dist-DreO5AcZ.js.map → dist-cyag2tir.js.map} +1 -1
  57. package/public/assets/{es2015-DUjFyjDp.js → es2015-C9FSEGd7.js} +2 -2
  58. package/public/assets/{es2015-DUjFyjDp.js.map → es2015-C9FSEGd7.js.map} +1 -1
  59. package/public/assets/{formatted-body-impl-BKWCAjBd.js → formatted-body-impl-ChCxpVtI.js} +2 -2
  60. package/public/assets/{formatted-body-impl-BKWCAjBd.js.map → formatted-body-impl-ChCxpVtI.js.map} +1 -1
  61. package/public/assets/index-BIRtwnUI.js +23 -0
  62. package/public/assets/index-BIRtwnUI.js.map +1 -0
  63. package/public/assets/index-D-Ntiy3M.css +2 -0
  64. package/public/assets/{input-CtHfLn1i.js → input-DfN6sUbX.js} +2 -2
  65. package/public/assets/{input-CtHfLn1i.js.map → input-DfN6sUbX.js.map} +1 -1
  66. package/public/assets/{insights-BzNoYvDe.js → insights-BGuB8DWZ.js} +2 -2
  67. package/public/assets/{insights-BzNoYvDe.js.map → insights-BGuB8DWZ.js.map} +1 -1
  68. package/public/assets/{integrations-DLzJpt9G.js → integrations-CztQfrI7.js} +2 -2
  69. package/public/assets/{integrations-DLzJpt9G.js.map → integrations-CztQfrI7.js.map} +1 -1
  70. package/public/assets/{lib-l-JkMVR9.js → lib-DRRHEqRZ.js} +2 -2
  71. package/public/assets/{lib-l-JkMVR9.js.map → lib-DRRHEqRZ.js.map} +1 -1
  72. package/public/assets/{lucide-react-C4eXYCwx.js → lucide-react-DmbfpRvJ.js} +2 -2
  73. package/public/assets/{lucide-react-C4eXYCwx.js.map → lucide-react-DmbfpRvJ.js.map} +1 -1
  74. package/public/assets/{maintenance-B6_0-ECm.js → maintenance-BFyuZuv5.js} +2 -2
  75. package/public/assets/{maintenance-B6_0-ECm.js.map → maintenance-BFyuZuv5.js.map} +1 -1
  76. package/public/assets/managed-agents-BIXZUkrA.js +4 -0
  77. package/public/assets/{managed-agents-CpzKXDtV.js.map → managed-agents-BIXZUkrA.js.map} +1 -1
  78. package/public/assets/markdown-preview-impl-DTI--VmH.js +2 -0
  79. package/public/assets/{markdown-preview-impl-DxBnlJ2k.js.map → markdown-preview-impl-DTI--VmH.js.map} +1 -1
  80. package/public/assets/memory-OoM2E30h.js +2 -0
  81. package/public/assets/{memory-Bnm7ILWL.js.map → memory-OoM2E30h.js.map} +1 -1
  82. package/public/assets/{messages-D9LkocTc.js → messages-BHvC3SNR.js} +2 -2
  83. package/public/assets/{messages-D9LkocTc.js.map → messages-BHvC3SNR.js.map} +1 -1
  84. package/public/assets/{orchestrators-C__JfrNr.js → orchestrators-9pzQqf6-.js} +2 -2
  85. package/public/assets/{orchestrators-C__JfrNr.js.map → orchestrators-9pzQqf6-.js.map} +1 -1
  86. package/public/assets/overview-L8iYOYmR.js +2 -0
  87. package/public/assets/{overview-BQ0b0V7Q.js.map → overview-L8iYOYmR.js.map} +1 -1
  88. package/public/assets/{pairs-ChyeBs0Z.js → pairs-BCejxa6_.js} +2 -2
  89. package/public/assets/{pairs-ChyeBs0Z.js.map → pairs-BCejxa6_.js.map} +1 -1
  90. package/public/assets/projects-cOeuiMjl.js +2 -0
  91. package/public/assets/{projects-v5Kp1Oaq.js.map → projects-cOeuiMjl.js.map} +1 -1
  92. package/public/assets/prompt-settings-D9y9hhSy.js +2 -0
  93. package/public/assets/{prompt-settings-YhAOlYc6.js.map → prompt-settings-D9y9hhSy.js.map} +1 -1
  94. package/public/assets/{react-dom-BMF4hNzG.js → react-dom-jQ4Vs380.js} +2 -2
  95. package/public/assets/{react-dom-BMF4hNzG.js.map → react-dom-jQ4Vs380.js.map} +1 -1
  96. package/public/assets/registry-BwBg64Vj.js +2 -0
  97. package/public/assets/{registry-DZoAfrzx.js.map → registry-BwBg64Vj.js.map} +1 -1
  98. package/public/assets/{security-DRCj00eA.js → security-upd2zf8l.js} +2 -2
  99. package/public/assets/{security-DRCj00eA.js.map → security-upd2zf8l.js.map} +1 -1
  100. package/public/assets/{select-ZOpLw2Fd.js → select-Cu55Vi-R.js} +2 -2
  101. package/public/assets/{select-ZOpLw2Fd.js.map → select-Cu55Vi-R.js.map} +1 -1
  102. package/public/assets/settings-Dk5iNqCZ.js +6 -0
  103. package/public/assets/{settings-DGgwr9WH.js.map → settings-Dk5iNqCZ.js.map} +1 -1
  104. package/public/assets/store-DDWg67Pg.js +9 -0
  105. package/public/assets/store-DDWg67Pg.js.map +1 -0
  106. package/public/assets/tasks-BoDuvHnZ.js +2 -0
  107. package/public/assets/tasks-BoDuvHnZ.js.map +1 -0
  108. package/public/assets/teams-C6Pn-gpw.js +2 -0
  109. package/public/assets/{teams-BJpaoG2m.js.map → teams-C6Pn-gpw.js.map} +1 -1
  110. package/public/assets/{terminal-viewer-impl-CQhh6oXa.js → terminal-viewer-impl-afW96xEF.js} +3 -3
  111. package/public/assets/{terminal-viewer-impl-CQhh6oXa.js.map → terminal-viewer-impl-afW96xEF.js.map} +1 -1
  112. package/public/assets/{types-BiJFuTiL.js → types-DSwhOFcJ.js} +2 -2
  113. package/public/assets/types-DSwhOFcJ.js.map +1 -0
  114. package/public/assets/{use-keyboard-viewport-RYMALvu1.js → use-keyboard-viewport-Dw2CHZ50.js} +2 -2
  115. package/public/assets/{use-keyboard-viewport-RYMALvu1.js.map → use-keyboard-viewport-Dw2CHZ50.js.map} +1 -1
  116. package/public/assets/user-avatar-tSPnqEk5.js +2 -0
  117. package/public/assets/{user-avatar-BYGrUx1U.js.map → user-avatar-tSPnqEk5.js.map} +1 -1
  118. package/public/assets/{work-queue-BH2-mARc.js → work-queue-DP3UdDwC.js} +2 -2
  119. package/public/assets/{work-queue-BH2-mARc.js.map → work-queue-DP3UdDwC.js.map} +1 -1
  120. package/public/assets/workspaces-Dt2xndG4.js +3 -0
  121. package/public/assets/workspaces-Dt2xndG4.js.map +1 -0
  122. package/public/index.html +23 -23
  123. package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
  124. package/runner/src/config.ts +5 -0
  125. package/src/bus.ts +3 -1
  126. package/src/db/merge-lease.ts +5 -1
  127. package/src/db/migrations.ts +21 -1
  128. package/src/db/schema.ts +7 -1
  129. package/src/db/task-detail-projection.ts +66 -0
  130. package/src/db/task-entity.ts +51 -0
  131. package/src/mcp/tools-spawn.ts +1 -1
  132. package/src/mcp-dispatch-tools.ts +49 -17
  133. package/src/mcp-task-memory-tools.ts +4 -21
  134. package/src/routes/agents-spawn.ts +3 -2
  135. package/src/routes/agents.ts +2 -0
  136. package/src/routes/index.ts +5 -1
  137. package/src/routes/messages.ts +6 -6
  138. package/src/routes/tasks.ts +76 -2
  139. package/src/runtime-tokens.ts +4 -0
  140. package/src/security.ts +8 -0
  141. package/src/services/register-agent.ts +46 -2
  142. package/src/services/spawn-agent.ts +114 -30
  143. package/src/services/task-entity.ts +8 -0
  144. package/src/spawn-command.ts +3 -0
  145. package/src/task-authz.ts +52 -0
  146. package/public/assets/MessageBubble-DYJezSjU.js +0 -4
  147. package/public/assets/PlanGraphPanel-MWcVw38W.js +0 -2
  148. package/public/assets/PlanGraphPanel-MWcVw38W.js.map +0 -1
  149. package/public/assets/activity-Db3X3dg8.js +0 -2
  150. package/public/assets/activity-Db3X3dg8.js.map +0 -1
  151. package/public/assets/agents-GSJXvmU1.js +0 -2
  152. package/public/assets/card-Cds0MWME.js +0 -2
  153. package/public/assets/chat-D_0uHgB6.js +0 -2
  154. package/public/assets/dist-CBVZk9U8.js +0 -2
  155. package/public/assets/dist-DC-TqTz2.js +0 -2
  156. package/public/assets/dist-DreO5AcZ.js +0 -2
  157. package/public/assets/index-BjjzI2LT.css +0 -2
  158. package/public/assets/index-DlBSuzd2.js +0 -23
  159. package/public/assets/index-DlBSuzd2.js.map +0 -1
  160. package/public/assets/managed-agents-CpzKXDtV.js +0 -4
  161. package/public/assets/markdown-preview-impl-DxBnlJ2k.js +0 -2
  162. package/public/assets/memory-Bnm7ILWL.js +0 -2
  163. package/public/assets/overview-BQ0b0V7Q.js +0 -2
  164. package/public/assets/projects-v5Kp1Oaq.js +0 -2
  165. package/public/assets/prompt-settings-YhAOlYc6.js +0 -2
  166. package/public/assets/registry-DZoAfrzx.js +0 -2
  167. package/public/assets/settings-DGgwr9WH.js +0 -6
  168. package/public/assets/store-Bnag1kY-.js +0 -9
  169. package/public/assets/store-Bnag1kY-.js.map +0 -1
  170. package/public/assets/tasks-DUTu8ZhA.js +0 -2
  171. package/public/assets/tasks-DUTu8ZhA.js.map +0 -1
  172. package/public/assets/teams-BJpaoG2m.js +0 -2
  173. package/public/assets/types-BiJFuTiL.js.map +0 -1
  174. package/public/assets/user-avatar-BYGrUx1U.js +0 -2
  175. package/public/assets/workspaces-DldYyXZR.js +0 -3
  176. package/public/assets/workspaces-DldYyXZR.js.map +0 -1
@@ -25,7 +25,9 @@
25
25
  // deliberately out of scope here — this slice converges the two external TRANSPORTS.
26
26
  import type { SpawnProvider } from "agent-relay-sdk";
27
27
  import { DEFAULT_USER_ID, errMessage, isRecord, stringValue } from "agent-relay-sdk";
28
- import { assignTaskAgent, countLiveSpawnedAgents, createActivityEvent, ensureTeam, getAgent, listAgents, listWorkspaces, recordTaskSpawnRequested, resolveAgentOwnership, resolveProjectForCwd, resolveScopedAnchor, setAgentTeam, ValidationError, withResolvedProvisioning } from "../db";
28
+ import { statSync } from "node:fs";
29
+ import { dirname, resolve } from "node:path";
30
+ import { countLiveSpawnedAgents, createActivityEvent, ensureTeam, getAgent, getTaskDetail, listAgents, listProjects, listWorkspaces, recordTaskSpawnRequested, resolveAgentOwnership, resolveProjectForCwd, resolveScopedAnchor, rootsForProject, setAgentTeam, ValidationError, withResolvedProvisioning } from "../db";
29
31
  import { createCommand } from "../commands-db";
30
32
  import { emitCommandEvent } from "../command-events";
31
33
  import { buildSpawnCommand, generateSpawnRequestId, resolveSpawnModelParams } from "../spawn-command";
@@ -39,6 +41,7 @@ import type { ProjectSkillsPolicy } from "../project-skills";
39
41
  import { applyDefaultSharedMcp, type SharedMcpSpawnOverride } from "../shared-mcp";
40
42
  import { autoSeedProjectForCwd } from "./project";
41
43
  import { hydrateTaskContext, projectTaskHydration } from "./task-context-hydration";
44
+ import { recordTaskEntityDispatchDecision } from "./task-entity";
42
45
  import { dispatchTask } from "../task-dispatcher";
43
46
  import { hasComponentScope, isComponentAuthorizedFor } from "../security";
44
47
  import { isPathWithinBase } from "../utils";
@@ -51,6 +54,60 @@ import { TERMINAL_WORKSPACE_STATUSES } from "../workspace-phase";
51
54
  /** The spawn scope every transport must hold (admin `*` / `admin:*` pass; `system` bypasses). */
52
55
  const SPAWN_SCOPE = "command:spawn";
53
56
 
57
+ function hasGitMarker(dir: string): boolean {
58
+ try {
59
+ const marker = statSync(`${dir}/.git`);
60
+ return marker.isDirectory() || marker.isFile();
61
+ } catch {
62
+ return false;
63
+ }
64
+ }
65
+
66
+ function findGitRepoRoot(cwd: string): string | null {
67
+ if (!cwd.trim()) return null;
68
+ let current = resolve(cwd);
69
+ try {
70
+ const stat = statSync(current);
71
+ if (!stat.isDirectory()) current = dirname(current);
72
+ } catch {
73
+ return null;
74
+ }
75
+ for (;;) {
76
+ if (hasGitMarker(current)) return current;
77
+ const parent = dirname(current);
78
+ if (parent === current) return null;
79
+ current = parent;
80
+ }
81
+ }
82
+
83
+ function assertIsolatedSpawnHasGitRepo(cwd: string): void {
84
+ if (findGitRepoRoot(cwd)) return;
85
+ throw new ValidationError(`workspaceMode "isolated" requires a git repo, but ${cwd} is not one. Pass an explicit cwd under a repo, or use workspaceMode "shared"/"inherit".`);
86
+ }
87
+
88
+ function taskLinkedRepoCwd(taskId: number, callerCwd?: string): string {
89
+ const task = getTaskDetail(taskId);
90
+ if (!task) throw new ValidationError(`task ${taskId} not found or not a deliverable task`);
91
+ const repos = [...new Set(task.issues.map((issue) => issue.repo).filter((repo): repo is string => Boolean(repo)))];
92
+ if (repos.length === 0) {
93
+ throw new ValidationError(`task ${taskId} has no linked issue repo; pass cwd/orchestratorId explicitly`);
94
+ }
95
+ const candidates = listProjects()
96
+ .filter((project) => project.issueRepo && repos.includes(project.issueRepo))
97
+ .flatMap((project) => rootsForProject(project.id).map((root) => ({ project, root })));
98
+ if (candidates.length === 0) {
99
+ throw new ValidationError(`task ${taskId} links repo ${repos.join(", ")} but no Relay project root is registered for it; pass cwd/orchestratorId explicitly or add a project root`);
100
+ }
101
+ const matchingCallerRoot = callerCwd
102
+ ? candidates
103
+ .filter((candidate) => isPathWithinBase(callerCwd, candidate.root.rootPath))
104
+ .sort((a, b) => b.root.rootPath.length - a.root.rootPath.length)[0]
105
+ : undefined;
106
+ if (matchingCallerRoot) return matchingCallerRoot.root.rootPath;
107
+ if (candidates.length === 1) return candidates[0]!.root.rootPath;
108
+ throw new ValidationError(`task ${taskId} links repo ${repos.join(", ")} with multiple registered roots; pass cwd explicitly`);
109
+ }
110
+
54
111
  /**
55
112
  * A normalized spawn request — every transport validates its own wire shape (enums,
56
113
  * lengths) and hands the service this. Caller-context defaults (cwd, approvalMode,
@@ -177,6 +234,19 @@ function canSpawn(ctx: AuthContext): boolean {
177
234
  return ctx.scopes.includes(SPAWN_SCOPE);
178
235
  }
179
236
 
237
+ function agentIdFromTaskCreator(createdBy: string | undefined): string | undefined {
238
+ const raw = createdBy?.trim();
239
+ if (!raw) return undefined;
240
+ const candidates = [raw, raw.startsWith("agent:") ? raw.slice("agent:".length) : undefined].filter((value): value is string => Boolean(value));
241
+ return candidates.find((candidate) => getAgent(candidate)) ?? undefined;
242
+ }
243
+
244
+ function taskSpawnLabel(task: { id: number; title: string } | undefined, fallback?: string): string | undefined {
245
+ if (fallback || !task) return fallback;
246
+ const label = `task-${task.id}: ${task.title.trim() || "untitled"}`;
247
+ return label.length <= 120 ? label : `${label.slice(0, 117)}...`;
248
+ }
249
+
180
250
  /**
181
251
  * Spawn a provider agent. Transport-agnostic: every gate + side effect lives here so the
182
252
  * MCP and HTTP paths cannot drift. Throws `McpAuthError` (→403) on a gate denial,
@@ -189,22 +259,30 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
189
259
  // the #221 gate AND the #328/#331/#324 caller-context inheritance — one lookup, reused.
190
260
  const callerId = ctx.callerAgentId;
191
261
  const caller: AgentCard | undefined = (callerId ? getAgent(callerId) : undefined) ?? undefined;
262
+ const linkedTask = input.taskId !== undefined ? getTaskDetail(input.taskId) ?? undefined : undefined;
263
+ const taskCreatorAgentId = !callerId ? agentIdFromTaskCreator(linkedTask?.createdBy) : undefined;
264
+ const lineageAgentId = callerId ?? taskCreatorAgentId;
265
+ const lineageAgent: AgentCard | undefined = (lineageAgentId ? getAgent(lineageAgentId) : undefined) ?? undefined;
266
+ const callerCwd = stringValue(caller?.meta?.cwd) ?? stringValue(lineageAgent?.meta?.cwd);
267
+ const taskDefaultCwd = input.taskId !== undefined && !input.orchestratorId && !input.cwd
268
+ ? taskLinkedRepoCwd(input.taskId, callerCwd)
269
+ : undefined;
270
+ const requestedCwd = input.cwd ?? taskDefaultCwd;
192
271
 
193
272
  // #255/#328 — bias the host to the caller's own machine when neither an explicit
194
273
  // orchestratorId nor a cwd pins it, so an agent spawning a helper lands on its own host.
195
- const orchestrator = selectSpawnOrchestrator(input.provider, input.orchestratorId, input.cwd, caller?.machine);
274
+ const orchestrator = selectSpawnOrchestrator(input.provider, input.orchestratorId, requestedCwd, caller?.machine ?? lineageAgent?.machine);
196
275
 
197
276
  // #308 §3 — an explicit cwd must resolve within the TARGET host's base dir (a path valid on
198
277
  // your host may not exist on a different orchestrator).
199
- if (input.cwd && !isPathWithinBase(input.cwd, orchestrator.baseDir)) {
200
- throw new ValidationError(`cwd '${input.cwd}' is not within ${orchestrator.id} (host ${orchestrator.hostname})'s base dir '${orchestrator.baseDir}' — a path valid on your host may not exist on the target. Pass a cwd under that base dir, or omit cwd to default to it.`);
278
+ if (requestedCwd && !isPathWithinBase(requestedCwd, orchestrator.baseDir)) {
279
+ throw new ValidationError(`cwd '${requestedCwd}' is not within ${orchestrator.id} (host ${orchestrator.hostname})'s base dir '${orchestrator.baseDir}' — a path valid on your host may not exist on the target. Pass a cwd under that base dir, or omit cwd to default to it.`);
201
280
  }
202
281
  // #328 — default cwd to the caller's OWN repo (so "spawn a helper for my current task" Just
203
282
  // Works, esp. isolated mode which needs a git repo), but only when it resolves within the
204
283
  // target host's base. Precedence: explicit cwd > caller cwd > base dir.
205
- const callerCwd = stringValue(caller?.meta?.cwd);
206
284
  const inheritedCwd = callerCwd && isPathWithinBase(callerCwd, orchestrator.baseDir) ? callerCwd : undefined;
207
- const resolvedCwd = input.cwd || inheritedCwd || orchestrator.baseDir;
285
+ const resolvedCwd = requestedCwd || inheritedCwd || orchestrator.baseDir;
208
286
 
209
287
  // #838 — spawn-with-task hydration. When a taskId is given, relay assembles the worker's
210
288
  // first-turn context FROM the durable Task (intent + linked-issue spec/acceptance + recorded
@@ -234,9 +312,11 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
234
312
  // and a no-taskId spawn is untouched — the coupling is opt-in, not hard-wired.
235
313
  let dispatchModel = input.model;
236
314
  let dispatchEffort = input.effort;
315
+ let taskDispatchDecision: ReturnType<typeof dispatchTask> | undefined;
237
316
  if (hydratedTask && !input.model && !input.effort && hydratedTask.task.dispatch) {
238
317
  try {
239
318
  const decision = dispatchTask(hydratedTask.task.dispatch, { provider: input.provider });
319
+ taskDispatchDecision = decision;
240
320
  dispatchModel = decision.target.model ?? dispatchModel;
241
321
  dispatchEffort = decision.target.effort ?? dispatchEffort;
242
322
  } catch (err) {
@@ -245,18 +325,23 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
245
325
  }
246
326
 
247
327
  const modelParams = resolveSpawnModelParams(input.provider, dispatchModel, dispatchEffort);
328
+ const resolvedLabel = taskSpawnLabel(linkedTask, input.label);
248
329
 
249
330
  // #331 — default the child's approval mode to the CALLER's, not a hardcoded `guarded` (a
250
331
  // headless `guarded` child wedges on its first tool-call approval prompt). Explicit always
251
332
  // wins and can NARROW a child; non-agent callers keep the safe `guarded` default.
252
- const callerApprovalMode = caller?.meta?.approvalMode as SpawnApprovalMode | undefined;
253
- const approvalMode = input.approvalMode ?? callerApprovalMode ?? "guarded";
333
+ const callerApprovalMode = (caller?.meta?.approvalMode ?? lineageAgent?.meta?.approvalMode) as SpawnApprovalMode | undefined;
334
+ const approvalMode = input.approvalMode ?? callerApprovalMode ?? (input.taskId !== undefined ? "open" : "guarded");
254
335
 
255
336
  // #324 — agent-initiated spawns (a real caller behind the token) default to `isolated` (a
256
337
  // branch worker that auto-lands); non-agent callers (admin/dashboard) keep the orchestrator's
257
- // `inherit` fallback. Explicit wins.
258
- const workspaceMode = input.workspaceMode ?? (callerId ? ("isolated" as WorkspaceMode) : undefined);
338
+ // `inherit` fallback. Task-triggered spawns are coordinator work and should get an isolated
339
+ // branch unless explicitly narrowed.
340
+ const workspaceMode = input.workspaceMode ?? (callerId || input.taskId !== undefined ? ("isolated" as WorkspaceMode) : undefined);
259
341
  const lifecycle = input.lifecycle ?? "persistent";
342
+ if (workspaceMode === "isolated" && (input.taskId !== undefined || input.workspaceMode === "isolated")) {
343
+ assertIsolatedSpawnHasGitRepo(resolvedCwd);
344
+ }
260
345
 
261
346
  const spawnRequestId = input.spawnRequestId ?? generateSpawnRequestId();
262
347
 
@@ -344,9 +429,9 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
344
429
 
345
430
  // Provenance actor: the resolved caller agent when known, else the transport's label, else
346
431
  // the raw token actor. Recorded in the command payload, the token mint, and the audit row.
347
- const requestedBy = callerId ?? input.requestedBy ?? ctx.actor.id;
348
- const callerTeam = callerId ? (caller?.teamId ? { id: caller.teamId } : ensureTeam(callerId)) : undefined;
349
- if (callerId && callerTeam && !caller?.teamId) setAgentTeam(callerId, callerTeam.id);
432
+ const requestedBy = callerId ?? taskCreatorAgentId ?? input.requestedBy ?? ctx.actor.id;
433
+ const callerTeam = lineageAgentId ? (lineageAgent?.teamId ? { id: lineageAgent.teamId } : ensureTeam(lineageAgentId)) : undefined;
434
+ if (lineageAgentId && callerTeam && !lineageAgent?.teamId) setAgentTeam(lineageAgentId, callerTeam.id);
350
435
 
351
436
  // #405 — durable project binding: the project whose registered root contains the spawn cwd.
352
437
  // Stamped on the child token's constraints (identity-only, like teamId) so callerProject(auth)
@@ -374,7 +459,7 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
374
459
  // Both resolve null until someone has actually written to them, so a fresh deployment stays
375
460
  // byte-identical. Injection of their active (promoted) entries happens in the composer.
376
461
  const profileAnchor = resolveScopedAnchor("profile", profileName);
377
- const operatorId = callerId ? resolveAgentOwnership(callerId).ownerUserId : DEFAULT_USER_ID;
462
+ const operatorId = lineageAgentId ? resolveAgentOwnership(lineageAgentId).ownerUserId : DEFAULT_USER_ID;
378
463
  const userAnchor = resolveScopedAnchor("user", operatorId);
379
464
  const composedInstructions = composeSpawnInstructionsWithEvents({
380
465
  ...(callerProject ? { callerProject } : {}),
@@ -382,7 +467,7 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
382
467
  ...(profileAnchor ? { profileAnchor } : {}),
383
468
  ...(userAnchor ? { userAnchor } : {}),
384
469
  ...(agentProfile ? { profile: agentProfile } : {}),
385
- ...(callerId ? { spawnedBy: callerId } : {}),
470
+ ...(lineageAgentId ? { spawnedBy: lineageAgentId } : {}),
386
471
  ...(resolvedSystemPromptAppend ? { callerSystemPromptAppend: resolvedSystemPromptAppend } : {}),
387
472
  });
388
473
  const systemPromptAppend = composedInstructions.systemPromptAppend;
@@ -395,9 +480,10 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
395
480
  orchestratorId: orchestrator.id,
396
481
  cwd: resolvedCwd,
397
482
  provider: input.provider,
398
- label: input.label,
483
+ label: resolvedLabel,
399
484
  policyName: input.policyName,
400
485
  spawnRequestId,
486
+ taskId: input.taskId,
401
487
  createdBy: requestedBy,
402
488
  // Thread the resolved profile into the mint so the spawn grant (command:spawn/shutdown +
403
489
  // maxSpawnedAgents quota) is honored — parity with the HTTP path (agent-sessions.ts). #349
@@ -405,7 +491,7 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
405
491
  // (P0 regression #364). For an agent caller, agentInitiated still forces a non-spawn-capable
406
492
  // child regardless of profile (no grandchildren).
407
493
  profile: profileName,
408
- ...(callerId ? { agentInitiated: true, spawnedBy: callerId } : {}),
494
+ ...(lineageAgentId ? { agentInitiated: true, spawnedBy: lineageAgentId } : {}),
409
495
  ...(callerTeam ? { teamId: callerTeam.id } : {}),
410
496
  ...(callerProject ? { projectId: callerProject.id } : {}),
411
497
  });
@@ -426,7 +512,7 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
426
512
  cwd: resolvedCwd,
427
513
  ...(workspaceMode ? { workspaceMode } : {}),
428
514
  lifecycle,
429
- label: input.label,
515
+ label: resolvedLabel,
430
516
  profile: profileName,
431
517
  agentProfile,
432
518
  tags: input.tags ?? [],
@@ -440,6 +526,7 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
440
526
  landStrategy: input.landStrategy,
441
527
  autoMerge: input.autoMerge,
442
528
  reviewer: input.reviewer,
529
+ taskId: input.taskId,
443
530
  resumeWorkspace: input.resumeWorkspace,
444
531
  ...(expectReply ? { expectReply } : {}),
445
532
  policyName: input.policyName,
@@ -451,7 +538,7 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
451
538
  orchestratorId: orchestrator.id,
452
539
  // #308 — stamp the spawning parent so a FAILED agent.spawn command (child never registers,
453
540
  // so there's no agent row to resolve `spawnedBy` from) can be routed back to it.
454
- ...(callerId ? { extra: { spawnedBy: callerId } } : {}),
541
+ ...(lineageAgentId ? { extra: { spawnedBy: lineageAgentId } } : {}),
455
542
  }),
456
543
  });
457
544
  emitCommandEvent(command, "command.requested");
@@ -472,7 +559,7 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
472
559
  approvalMode,
473
560
  lifecycle,
474
561
  workspaceMode: workspaceMode ?? null,
475
- label: input.label ?? null,
562
+ label: resolvedLabel ?? null,
476
563
  commandId: command.id,
477
564
  spawnRequestId,
478
565
  requestedVia: input.requestedVia ?? null,
@@ -486,6 +573,13 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
486
573
  // drive one-shot reap. Best-effort: an attribution write never fails the spawn.
487
574
  if (input.taskId !== undefined) {
488
575
  try {
576
+ if (taskDispatchDecision) {
577
+ recordTaskEntityDispatchDecision(input.taskId, {
578
+ decision: taskDispatchDecision,
579
+ source: "spawn",
580
+ actor: requestedBy,
581
+ });
582
+ }
489
583
  recordTaskSpawnRequested(input.taskId, {
490
584
  spawnRequestId,
491
585
  provider: input.provider,
@@ -502,16 +596,6 @@ export async function spawnAgent(input: SpawnAgentInput, ctx: AuthContext): Prom
502
596
  const waitMs = Math.min(input.waitForRegistrationMs ?? 0, 30_000);
503
597
  const agentId = waitMs > 0 ? await waitForSpawnedAgent(spawnRequestId, waitMs) : null;
504
598
 
505
- // #838 — once the child's id is known (waitForRegistrationMs > 0), stamp it as the Task owner
506
- // via the #834 attribution API. Fire-and-forget spawns resolve the id later; #831 closes that
507
- // gap by reading the spawn_requested event above. Best-effort, never fails the spawn.
508
- if (input.taskId !== undefined && agentId) {
509
- try {
510
- assignTaskAgent(input.taskId, agentId, "worker", requestedBy);
511
- } catch (err) {
512
- console.warn(`task ${input.taskId} owner attribution skipped: ${errMessage(err)}`);
513
- }
514
- }
515
599
  return {
516
600
  ok: true,
517
601
  spawnRequestId,
@@ -11,6 +11,7 @@ import {
11
11
  listDeliverableTasks,
12
12
  listTaskEvents,
13
13
  recordGate,
14
+ recordTaskDispatchDecision,
14
15
  removeTaskDependency,
15
16
  removeTaskRef,
16
17
  setTaskStage,
@@ -19,6 +20,7 @@ import {
19
20
  type AddTaskRefInput,
20
21
  type CreateDeliverableTaskInput,
21
22
  type ListDeliverableTasksFilter,
23
+ type RecordTaskDispatchDecisionInput,
22
24
  type RecordGateInput,
23
25
  type RemoveTaskRefInput,
24
26
  type SetTaskStageInput,
@@ -144,6 +146,12 @@ export function assignTaskEntityAgent(id: number, agentId: string, role?: string
144
146
  return detail;
145
147
  }
146
148
 
149
+ export function recordTaskEntityDispatchDecision(id: number, input: RecordTaskDispatchDecisionInput): TaskDetail {
150
+ const detail = recordTaskDispatchDecision(id, input);
151
+ emitTaskChanged(detail, "task.dispatch");
152
+ return detail;
153
+ }
154
+
147
155
  export function taskEntityHistory(id: number): TaskEvent[] {
148
156
  return listTaskEvents(id);
149
157
  }
@@ -100,6 +100,8 @@ interface BuildSpawnCommandOptions {
100
100
  landStrategy?: WorkspaceLandingPolicy;
101
101
  autoMerge?: WorkspaceAutoMergePolicy;
102
102
  reviewer?: string;
103
+ /** #838 — durable Task this worker was spawned to execute. */
104
+ taskId?: number;
103
105
  /**
104
106
  * #413 — when true, the child registering with this spawnRequestId gets a pending reply
105
107
  * obligation back to its spawner, so the Stop hook refuses to let it idle until it delivers
@@ -160,6 +162,7 @@ export function buildSpawnCommand(opts: BuildSpawnCommandOptions): Record<string
160
162
  ...def(opts.landStrategy, "landStrategy"),
161
163
  ...def(opts.autoMerge, "autoMerge"),
162
164
  ...def(opts.reviewer, "reviewer"),
165
+ ...def(opts.taskId, "taskId"),
163
166
  ...def(opts.expectReply, "expectReply"),
164
167
  ...def(opts.headless, "headless"),
165
168
  ...def(opts.policyName, "policyName"),
@@ -0,0 +1,52 @@
1
+ // Shared per-task authorization gate used by both MCP (mcp-task-memory-tools.ts) and
2
+ // HTTP (routes/tasks.ts) paths. Keeping the logic here ensures neither transport forks
3
+ // the bound-task or admin-scope check (#843).
4
+ import { stringValue } from "agent-relay-sdk";
5
+ import { deliverableTaskIdsByOwnerAgent, deliverableTaskIdsBySpawnRequestId, getAgent, listAgents } from "./db";
6
+ import { resolveCallerAgentId } from "./agent-ref";
7
+ import type { ComponentToken } from "agent-relay-sdk/types";
8
+
9
+ /** Scopes that bypass the per-task binding check (privileged escape hatch). */
10
+ export function hasTaskReadAdminScope(scopes: string[]): boolean {
11
+ return scopes.includes("*") || scopes.includes("admin:*") || scopes.includes("system:admin") || scopes.includes("task:admin");
12
+ }
13
+
14
+ /**
15
+ * Resolve the set of deliverable Task ids the given agent is bound to.
16
+ * Covers both the direct ownerAgentId link and the spawnRequestId fallback (#838).
17
+ */
18
+ export function agentBoundTaskIds(agentId: string): Set<number> {
19
+ const ids = new Set<number>(deliverableTaskIdsByOwnerAgent(agentId));
20
+ const spawnRequestId = stringValue(getAgent(agentId)?.meta?.spawnRequestId);
21
+ if (spawnRequestId) {
22
+ for (const id of deliverableTaskIdsBySpawnRequestId(spawnRequestId)) ids.add(id);
23
+ }
24
+ return ids;
25
+ }
26
+
27
+ /** Resolve the agent ID from an HTTP ComponentToken using the same constraint-resolution as the MCP path. */
28
+ export function agentIdFromComponent(component: ComponentToken): string | undefined {
29
+ return resolveCallerAgentId(component.constraints, listAgents);
30
+ }
31
+
32
+ /**
33
+ * Returns true when the caller may read task-sensitive data (memory / history) for `taskId`.
34
+ * Admin scopes bypass binding; otherwise the agentId must be bound to the task.
35
+ */
36
+ export function isTaskReadAuthorized(taskId: number, agentId: string | undefined, scopes: string[]): boolean {
37
+ if (hasTaskReadAdminScope(scopes)) return true;
38
+ if (!agentId) return false;
39
+ return agentBoundTaskIds(agentId).has(taskId);
40
+ }
41
+
42
+ /**
43
+ * Returns true when the caller may issue dispatch decisions (command:spawn-class) for `taskId`.
44
+ * Admin scopes bypass binding (dashboard token carries admin scope); otherwise the calling
45
+ * agent must be directly bound to the task. Dispatch is spawn-class — restrict to binding,
46
+ * not any reader (#848 gap: scope-only gates must not widen here).
47
+ */
48
+ export function isTaskDispatchAuthorized(taskId: number, agentId: string | undefined, scopes: string[]): boolean {
49
+ if (hasTaskReadAdminScope(scopes)) return true;
50
+ if (!agentId) return false;
51
+ return agentBoundTaskIds(agentId).has(taskId);
52
+ }
@@ -1,4 +0,0 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{$n as t,$t as n,An as r,B as i,Cn as a,Dt as o,Fn as s,Hn as c,L as l,Ot as u,Qt as d,Sn as f,Un as p,V as m,Vt as h,Yn as g,Zn as _,_n as v,a as y,b,c as ee,ft as x,g as S,hn as C,i as te,ln as ne,lt as w,m as T,on as E,r as D,un as re,ur as O,vn as k,x as A,xn as ie,yn as j}from"./lucide-react-C4eXYCwx.js";import{r as M,t as N,y as P}from"./store-Bnag1kY-.js";import{t as F}from"./types-BiJFuTiL.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-1J__Ti1K.js";import{D as H,a as pe,i as me,l as he,t as U}from"./index-DlBSuzd2.js";import{t as ge}from"./user-avatar-BYGrUx1U.js";var W=e(O(),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,o=n.some(e=>e!==V);if(i||o){let e=i?r:n.find(e=>e!==V);return{label:`read`,title:e?`Read by ${e}`:`Read by agent`,tone:`ok`,icon:a}}if(e.deliveryStatus===`delivered`)return{label:`delivered`,title:`Delivered to agent inbox`,tone:`ok`,icon:a};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:v}}return{label:`sent`,title:`Accepted by Relay`,tone:`muted`,icon:f}}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=_(),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)(ne,{className:g(`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":o,"context.warning":T,"agent.context_threshold":T,"agent.resume_budget_exhausted":T,"agent.rate_limit_resume":m},$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:g(`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:``,s=typeof t.branch==`string`?t.branch:``,c=typeof t.base==`string`?t.base:``,l=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)(o,{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`}),s&&c&&(0,Y.jsxs)(`span`,{className:`font-mono text-emerald-700/80 dark:text-emerald-200/70`,title:`${s} → ${c}`,children:[s,(0,Y.jsx)(`span`,{className:`opacity-50`,children:` → `}),c]}),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`})]}),l===!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]??l,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":i,"spawned-child-exited":w,"spawned-child-failed":v,"spawned-by-ready":p,"spawned-by-exited":p,"spawned-by-failed":p},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]??l,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:g(`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:g(`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:r,instructions:h,tools:y,comms:l,knowledge:s,context:n},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]??b;return(0,Y.jsx)(`div`,{className:`flex justify-center py-2 my-1`,children:(0,Y.jsxs)(`div`,{className:g(`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)(j,{className:g(`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)(v,{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)(re,{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[i,a]=pt(),o=t?e:e.filter(e=>e.kind!==`reasoning`);if(!o.length)return null;let s=o.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:[o.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)(r,{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):i?null:(0,Y.jsxs)(`div`,{className:`flex items-start gap-1.5 text-xs leading-relaxed text-muted-foreground`,children:[(0,Y.jsx)(S,{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)),s>0&&(0,Y.jsxs)(`button`,{onClick:a,className:`flex items-center gap-1 text-[11px] text-muted-foreground/50 hover:text-muted-foreground transition-colors text-left`,children:[(0,Y.jsx)(j,{className:g(`w-3 h-3 shrink-0 transition-transform`,!i&&`rotate-90`)}),(0,Y.jsx)(`span`,{children:i?`show ${s} tool step${s===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)(C,{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)(u,{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:g(`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:g(`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:g(`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:g(`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)(b,{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,r]=(0,W.useState)(!0),[i,a]=(0,W.useState)(null),[o,s]=(0,W.useState)(null),[c,l]=(0,W.useState)(!1),u=(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(!u||!e){r(!0);return}let t=null,n=null,i=()=>{let i=e.querySelector(`[data-msg-id="${u.id}"]`);if(!i){t?.disconnect(),t=null,n=null,r(!1);return}let a=i.getBoundingClientRect(),o=e.getBoundingClientRect();l(a.top<o.top),i!==n&&(t?.disconnect(),n=i,t=new IntersectionObserver(([e])=>{e&&r(e.isIntersecting)},{root:e,threshold:0}),t.observe(i))};return i(),e.addEventListener(`scroll`,i,{passive:!0}),()=>{t?.disconnect(),e.removeEventListener(`scroll`,i)}},[u?.id,e]),n||!u||!u.body.trim())return null;let d=i?.id===u.id?i.value:!1,f=o?.id===u.id?o.value:!1;function p(){!e||!u||e.querySelector(`[data-msg-id="${u.id}"]`)?.scrollIntoView({behavior:`smooth`,block:`center`})}let m=c?`↑`:`↓`;return f?(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:()=>s({id:u.id,value:!1}),children:[(0,Y.jsx)(`span`,{children:`Your prompt`}),(0,Y.jsx)(ie,{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:p,children:[m,` scroll to original`]}),(0,Y.jsx)(`button`,{type:`button`,className:`hover:text-foreground transition-colors`,onClick:()=>s({id:u.id,value:!0}),title:`Minimize`,children:(0,Y.jsx)(k,{className:`w-3 h-3`})})]}),(0,Y.jsx)(`p`,{className:g(`text-sm text-foreground leading-snug cursor-pointer`,!d&&`line-clamp-2`),onClick:()=>a({id:u.id,value:!d}),children:u.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:g(`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:n}){let r=e.kind===`image`,i=e.title||e.artifactId,[a,o]=(0,W.useState)(null),[s,c]=(0,W.useState)(null),[l,u]=(0,W.useState)(!1),[f,p]=(0,W.useState)(!1);(0,W.useEffect)(()=>{let n=!1,r=null;async function i(){u(!0),c(null),o(null);try{let i=await t(`/artifacts/${encodeURIComponent(e.artifactId)}/content`);if(n)return;r=URL.createObjectURL(i),o(r)}catch(e){n||c(e.message)}finally{n||u(!1)}}return i(),()=>{n=!0,r&&URL.revokeObjectURL(r)}},[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)(D,{className:`w-6 h-6 text-white opacity-0 group-hover/img:opacity-100 transition-opacity drop-shadow-md`})})]}):(0,Y.jsxs)(`span`,{className:g(`flex min-h-20 items-center gap-2 px-3 py-2 text-xs`,s?`text-red-400`:`text-muted-foreground`),children:[l?(0,Y.jsx)(x,{className:`h-4 w-4 animate-spin`}):(0,Y.jsx)(v,{className:`h-4 w-4`}),s||`Loading image`]})}),a&&(0,Y.jsx)(me,{open:f,onOpenChange:p,children:(0,Y.jsxs)(pe,{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)(d,{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)(te,{className:`w-4 h-4`})})]})]})]})})]}):(0,Y.jsxs)(`button`,{type:`button`,onClick:m,disabled:!a,className:g(`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`,n?`border-primary-foreground/20 bg-primary-foreground/10 hover:bg-primary-foreground/15`:`border-border bg-background hover:bg-muted`),children:[l?(0,Y.jsx)(x,{className:`h-4 w-4 shrink-0 animate-spin`}):s?(0,Y.jsx)(v,{className:`h-4 w-4 shrink-0 text-red-400`}):(0,Y.jsx)(h,{className:`h-4 w-4 shrink-0`}),(0,Y.jsx)(`span`,{className:g(`min-w-0 flex-1 truncate`,s&&`text-red-400`),children:s||i}),(0,Y.jsx)(d,{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:g(`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)(A,{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),i=N(e=>e.agentsById),a=N(e=>e.openAgentDetail),o=e.from===t,s=(o?e.to:e.from)||``,l=i[o?t:s]?.issueRepo??i[t]?.issueRepo,u=!s||s===`broadcast`||s.includes(`:`),d=z(e),f=J(e.occurredAt??e.createdAt),m=o?c:p,h=i[e.from??``]??null;function _(e){e.stopPropagation(),h&&a(h)}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)(j,{className:g(`h-3 w-3 shrink-0 text-muted-foreground/60 transition-transform`,n&&`rotate-90`)}),(0,Y.jsx)(`button`,{type:`button`,title:h?h.label||h.name||h.id:void 0,disabled:!h,onClick:_,className:g(`shrink-0 transition-opacity`,h?`cursor-pointer hover:opacity-80`:`cursor-default opacity-60`),children:(0,Y.jsx)(H,{agent:h,className:`!w-4 !h-4 !rounded-sm opacity-70`})}),(0,Y.jsx)(m,{className:`h-3 w-3 shrink-0 text-muted-foreground/70`}),(0,Y.jsxs)(`span`,{className:`shrink-0 text-muted-foreground`,children:[`Message `,o?`to`:`from`]}),u?(0,Y.jsx)(`span`,{className:`shrink-0 font-medium text-muted-foreground`,children:de(s,i)}):(0,Y.jsx)(X,{agentId:s,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),h=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),te=J(e.occurredAt??e.createdAt),ne=ze(e),w=Ve(e),T=s?He(e,t):null,E=T?.icon,D=u===String(e.id),O=l&&!s&&!q(e)&&C.trim().length>0;function k(t){t.stopPropagation(),D?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 A(e){return Pe(d||`/`,e)}function ie(e,t){let n=A(e);r?.(n,t)}function j(e,t,n){let r=A(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:g(`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:g(`relative`,R?`max-w-[calc(85%-2rem)] md:max-w-[calc(75%-2rem)]`:`max-w-[85%] md:max-w-[75%]`),children:[O&&(0,Y.jsx)(`button`,{type:`button`,title:D?`Stop playback`:`Play aloud`,onClick:k,className:g(`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`,D?`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:D?(0,Y.jsx)(re,{className:`h-3.5 w-3.5 animate-pulse`}):(0,Y.jsx)(ee,{className:`h-3.5 w-3.5`})}),(0,Y.jsxs)(`div`,{className:g(`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:g(`text-[11px] font-semibold mb-0.5 text-right`,le(e.from)),children:fe(e.from,p)}),e.subject&&(0,Y.jsx)(`p`,{className:g(`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:ie,onPreviewPath:j,onPreviewPathEnd:a,resolvePathTitle:(e,t)=>`${A(e)}${t?`:${t}`:``}`}),ne.map(t=>(0,Y.jsx)(Tt,{attachment:t,outbound:s},`${e.id}-${t.artifactId}-${t.role||``}`)),(0,Y.jsxs)(`p`,{className:g(`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:te}),T&&E&&(0,Y.jsxs)(`span`,{className:g(`inline-flex items-center gap-1`,T.tone===`ok`&&`text-emerald-300`,T.tone===`warn`&&`text-amber-200`,T.tone===`danger`&&`text-red-200`),title:T.title,children:[(0,Y.jsx)(E,{className:`h-3 w-3`}),T.label]})]})]}),!q(e)&&w.length>0&&(0,Y.jsxs)(`div`,{className:g(`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}),w.map(e=>(0,Y.jsxs)(`button`,{type:`button`,title:e.actors.join(`, `),onClick:()=>M(e.emoji),className:g(`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&&w.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:h,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-DYJezSjU.js.map
@@ -1,2 +0,0 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{At as t,Yn as n,Zn as r,ur as i,vn as a,xn as o}from"./lucide-react-C4eXYCwx.js";import{i as s,r as c,t as l}from"./store-Bnag1kY-.js";import{h as u}from"./index-DlBSuzd2.js";var d=e(i(),1),f=`(max-width: 767px)`;function p(e){if(typeof window>`u`)return()=>{};let t=window.matchMedia(f);return t.addEventListener(`change`,e),()=>t.removeEventListener(`change`,e)}function m(){return(0,d.useSyncExternalStore)(p,()=>typeof window<`u`?window.matchMedia(f).matches:!1,()=>!1)}var h=r(),g=196,_=84,v=52,y=16,b=14,x=[`landed`,`in-progress`,`pending`,`blocked`],S={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 C(e){return e?e.label||(e.policyName?`policy:${e.policyName}`:e.agentId||``):``}function w(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,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:b+r*(g+v),y:b+a+n*f})})});let m=u.length;return{nodes:p,width:Math.max(320,b*2+m*g+Math.max(0,m-1)*v),height:Math.max(_+b*2,b*2+d*_+Math.max(0,d-1)*y)}}function T(e,t){let n=e.x+g,r=e.y+_/2,i=t.x,a=t.y+_/2,o=n+Math.max(20,(i-n)/2);return`M ${n} ${r} C ${o} ${r}, ${o} ${a}, ${i} ${a}`}function E({threadId:e,teamId:r,channel:i}){let f=r?s(r,i):e?c(e,i):``,p=l(e=>r?e.plansByTeam[f]:f?e.plansByThread[f]:null),v=l(e=>e.fetchPlan),y=l(e=>e.planCollapsed),b=l(e=>e.setPlanCollapsed),E=l(e=>e.issueRefsById),D=m(),O=y??D;(0,d.useEffect)(()=>{if(r){v({teamId:r,channel:i});return}e&&v({threadId:e,channel:i})},[i,v,r,e]);let k=(0,d.useMemo)(()=>p?w(p):null,[p]),A=(0,d.useMemo)(()=>new Map(k?.nodes.map(e=>[e.node.id,e])??[]),[k]),j=(0,d.useMemo)(()=>{if(!p)return[];let e=new Map;for(let t of p.nodes)e.set(t.status,(e.get(t.status)??0)+1);return x.filter(t=>e.has(t)).map(t=>({status:t,count:e.get(t)??0}))},[p]);if(!p||!k)return null;let M=p.nodes.length,N=j.find(e=>e.status===`landed`)?.count??0,P=`${M} node${M===1?``:`s`}${N>0?` · ${N} landed`:``}`;return(0,h.jsxs)(`section`,{className:`shrink-0 border-b border-border bg-card/45 px-3 py-2`,children:[(0,h.jsxs)(`button`,{type:`button`,onClick:()=>b(!O),"aria-expanded":!O,"aria-label":O?`Expand plan graph`:`Collapse plan graph`,className:n(`flex w-full min-w-0 items-center gap-2 text-left`,!O&&`mb-2`),children:[(0,h.jsx)(`span`,{className:`flex h-5 w-5 shrink-0 items-center justify-center rounded bg-muted/60`,children:(0,h.jsx)(t,{className:`h-3 w-3 text-muted-foreground`})}),(0,h.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,h.jsx)(`div`,{className:`truncate text-[13px] font-semibold leading-tight text-foreground`,children:p.title||`Plan`}),(0,h.jsx)(`div`,{className:`truncate text-[11px] leading-tight text-muted-foreground`,children:O?P:p.objective||P})]}),j.length>0&&(0,h.jsx)(`div`,{className:`hidden shrink-0 items-center gap-2.5 sm:flex`,children:j.map(({status:e,count:t})=>(0,h.jsxs)(`span`,{className:`flex items-center gap-1 text-[10px] text-muted-foreground`,children:[(0,h.jsx)(`span`,{className:n(`h-1.5 w-1.5 rounded-full`,S[e].dot)}),(0,h.jsx)(`span`,{className:n(`font-medium tabular-nums`,S[e].text),children:t}),(0,h.jsx)(`span`,{children:S[e].label})]},e))}),(0,h.jsxs)(`span`,{className:`shrink-0 rounded bg-muted/60 px-1.5 py-0.5 text-[10px] font-medium tabular-nums text-muted-foreground`,children:[`v`,p.version]}),(0,h.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:O?(0,h.jsx)(o,{className:`h-3.5 w-3.5`}):(0,h.jsx)(a,{className:`h-3.5 w-3.5`})})]}),O?null:p.nodes.length===0?(0,h.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,h.jsx)(`div`,{className:`max-h-[min(46vh,360px)] overflow-auto`,children:(0,h.jsxs)(`div`,{className:`relative`,style:{width:k.width,height:k.height},children:[(0,h.jsxs)(`svg`,{className:`pointer-events-none absolute inset-0`,width:k.width,height:k.height,"aria-hidden":`true`,children:[(0,h.jsx)(`defs`,{children:x.map(e=>(0,h.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,h.jsx)(`path`,{d:`M0 0 L8 4 L0 8 z`,fill:S[e].wire})},e))}),p.edges.map(e=>{let t=A.get(e.from),n=A.get(e.to);if(!t||!n)return null;let r=S[t.node.status];return(0,h.jsx)(`path`,{d:T(t,n),stroke:r.wire,strokeOpacity:.7,strokeWidth:2,fill:`none`,strokeLinecap:`round`,markerEnd:`url(#plan-arrow-${t.node.status})`},`${e.from}->${e.to}`)})]}),k.nodes.map(({node:e,x:t,y:r})=>{let i=S[e.status],a=C(e.ownerRef),o=e.refs?.issueId?E[e.refs.issueId]:null;return(0,h.jsxs)(`article`,{className:n(`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:r,width:g,height:_},title:e.scopeBlurb||e.label,children:[(0,h.jsx)(`div`,{className:`truncate text-xs font-semibold leading-tight text-foreground`,children:e.label}),(e.scopeBlurb||e.id)&&(0,h.jsx)(`div`,{className:`truncate text-[10px] leading-tight text-muted-foreground`,children:e.scopeBlurb||e.id}),o&&(0,h.jsx)(`div`,{className:`min-w-0`,children:(0,h.jsx)(u,{issueRef:o,compact:!0,className:`max-w-full`})}),(0,h.jsxs)(`div`,{className:`flex min-w-0 items-center justify-between gap-1.5`,children:[(0,h.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1.5`,children:[(0,h.jsx)(`span`,{className:n(`h-1.5 w-1.5 shrink-0 rounded-full`,i.dot)}),(0,h.jsx)(`span`,{className:n(`text-[10px] font-medium`,i.text),children:i.label})]}),(0,h.jsxs)(`div`,{className:`flex min-w-0 items-center gap-1.5`,children:[a&&(0,h.jsx)(`span`,{className:`truncate text-[10px] text-muted-foreground`,children:a}),e.lane&&(0,h.jsx)(`span`,{className:`shrink-0 rounded-sm bg-muted/70 px-1 py-px text-[9px] font-medium uppercase tracking-wide text-muted-foreground`,children:e.lane})]})]})]},e.id)})]})})]})}export{E as t};
2
- //# sourceMappingURL=PlanGraphPanel-MWcVw38W.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PlanGraphPanel-MWcVw38W.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 } from 'react'\nimport { ChevronDown, ChevronUp, GitBranch } from 'lucide-react'\nimport { useRelayStore } from '@/store'\nimport type { Plan, PlanNode, PlanOwnerRef, PlanStatus } from '@/types'\nimport { cn } from '@/lib/utils'\nimport { planLookupKey, planTeamLookupKey } from '@/store/slices/plans'\nimport { IssueRefChip } from '@/components/shared/issue-ref-chip'\nimport { useIsMobile } from './hooks/useIsMobile'\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 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 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 && (\n <div className=\"min-w-0\">\n <IssueRefChip issueRef={issueRef} compact className=\"max-w-full\" />\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"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{Jn as t,L as n,Mn as r,Rt as i,Ut as a,Yn as o,Zn as s,cn as c,dn as l,mt as u,nt as d,rt as f,u as p,ur as m}from"./lucide-react-C4eXYCwx.js";import{f as h,t as g}from"./store-Bnag1kY-.js";import{K as _,f as v,h as y,rt as b}from"./display-1J__Ti1K.js";import{t as x}from"./badge-D8fABzMs.js";import{t as S}from"./button-KASZcscA.js";import{u as C}from"./index-DlBSuzd2.js";import{r as w,t as T}from"./card-Cds0MWME.js";import{n as E,o as D,p as O,r as k,t as A,u as j,w as M}from"./MessageBubble-DYJezSjU.js";var N=e(m(),1),P=s(),F={question:l,reply:d,message:f,operator:p,pair:u,task:c,state:n},I={question:`bg-blue-500/10 text-blue-400 border-blue-500/20`,reply:`bg-emerald-500/10 text-emerald-400 border-emerald-500/20`,message:`bg-zinc-500/10 text-zinc-400 border-zinc-500/20`,operator:`bg-purple-500/10 text-purple-400 border-purple-500/20`,pair:`bg-yellow-500/10 text-yellow-400 border-yellow-500/20`,task:`bg-orange-500/10 text-orange-400 border-orange-500/20`,state:`bg-cyan-500/10 text-cyan-400 border-cyan-500/20`},L=[`question`,`reply`,`message`,`operator`,`pair`,`task`,`state`],R=[`chat`,`session`,`system`,`task`];function z(e){let t=e?.surface;if(!t||typeof t!=`object`)return null;let n=t,r=[];return typeof n.component==`string`&&r.push(n.component),typeof n.view==`string`&&n.view!==n.component&&r.push(n.view),typeof n.session==`string`&&r.push(`tab ${n.session.slice(0,6)}`),typeof n.client==`string`&&r.push(`client ${n.client.slice(0,6)}`),r.length?r.join(` · `):null}function B({entry:e,agentsById:t}){if(e.type===`notice`)return(0,P.jsx)(`div`,{className:`px-1`,children:(0,P.jsx)(j,{msg:e.msg})});if(e.type===`agent-action`)return(0,P.jsx)(`div`,{className:`px-1`,children:(0,P.jsx)(k,{entry:e})});if(e.type===`activity`)return(0,P.jsx)(`div`,{className:`px-1 opacity-60`,children:(0,P.jsx)(E,{steps:e.steps,showReasoning:!1})});if(e.type===`status`)return(0,P.jsx)(`div`,{className:`px-1`,children:(0,P.jsx)(O,{event:e.event})});if(e.type===`date`)return(0,P.jsx)(`div`,{className:`px-1`,children:(0,P.jsx)(D,{date:e.date})});if(e.type===`created`||e.type===`import-boundary`||e.type===`imported-message`||e.type!==`message`)return null;let{msg:n}=e,r=v(n.from,t),i=v(n.to,t);return(0,P.jsxs)(`div`,{children:[(0,P.jsxs)(`div`,{className:`flex items-center gap-1.5 px-3 mb-0.5`,children:[(0,P.jsx)(`span`,{className:`text-xs font-mono text-muted-foreground truncate max-w-[140px]`,title:n.from,children:r}),(0,P.jsx)(`span`,{className:`text-xs text-muted-foreground shrink-0`,children:`→`}),(0,P.jsx)(`span`,{className:`text-xs font-mono text-muted-foreground truncate max-w-[140px]`,title:n.to,children:i}),(0,P.jsx)(x,{variant:`outline`,className:`text-[10px] px-1 py-0 shrink-0 ml-1`,children:n.kind})]}),(0,P.jsx)(A,{msg:n,peer:b})]})}function V(){let e=g(e=>e.messages),t=g(e=>e.agentsById),[n,r]=(0,N.useState)(``),[i,a]=(0,N.useState)(``),o=(0,N.useMemo)(()=>{let t=e;if(n){let e=n.toLowerCase();t=t.filter(t=>t.from.toLowerCase().includes(e)||t.to.toLowerCase().includes(e))}return i&&(t=t.filter(e=>e.kind===i)),t},[e,n,i]),s=(0,N.useMemo)(()=>M(o,[]),[o]);return(0,P.jsxs)(P.Fragment,{children:[(0,P.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,P.jsx)(`input`,{type:`text`,className:`rounded-md border border-input bg-background px-3 py-1.5 text-sm w-44`,placeholder:`Filter by agent…`,value:n,onChange:e=>r(e.target.value)}),(0,P.jsxs)(`select`,{className:`rounded-md border border-input bg-background px-3 py-1.5 text-sm`,value:i,onChange:e=>a(e.target.value),children:[(0,P.jsx)(`option`,{value:``,children:`All kinds`}),R.map(e=>(0,P.jsx)(`option`,{value:e,children:e},e))]}),(0,P.jsx)(x,{variant:`secondary`,className:`ml-auto`,children:o.length})]}),(0,P.jsx)(C,{className:`h-[calc(100dvh-13rem)]`,children:(0,P.jsxs)(`div`,{className:`space-y-1 pr-2`,children:[s.length===0&&(0,P.jsx)(`div`,{className:`text-center text-muted-foreground py-16 text-sm`,children:`No messages yet`}),s.map((e,n)=>(0,P.jsx)(B,{entry:e,agentsById:t},n))]})})]})}function H(){let e=h(),n=g(e=>e.activityFilter),i=g(e=>e.activityEvents),o=g(e=>e.operatorActivity),s=g(e=>e.set),c=g(e=>e.openActivityItem),l=g(e=>e.exportActivity),u=(0,N.useMemo)(()=>{let e=[...i,...o],t=new Set,n=[];for(let r of e){let e=r.clientId||String(r.id);t.has(e)||(t.add(e),n.push(r))}return n.map(e=>({...e,ts:e.ts??new Date(e.createdAt).getTime()})).sort((e,t)=>(t.ts??0)-(e.ts??0))},[i,o]),d=(0,N.useMemo)(()=>n?u.filter(e=>e.kind===n):u,[u,n]);return(0,P.jsxs)(P.Fragment,{children:[(0,P.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,P.jsxs)(`select`,{className:`rounded-md border border-input bg-background px-3 py-1.5 text-sm`,value:n,onChange:e=>s({activityFilter:e.target.value}),children:[(0,P.jsx)(`option`,{value:``,children:`All types`}),L.map(e=>(0,P.jsx)(`option`,{value:e,children:e},e))]}),(0,P.jsxs)(S,{size:`sm`,variant:`outline`,onClick:()=>l(`markdown`),children:[(0,P.jsx)(a,{className:`w-4 h-4 mr-1`}),` Markdown`]}),(0,P.jsxs)(S,{size:`sm`,variant:`outline`,onClick:()=>l(`json`),children:[(0,P.jsx)(r,{className:`w-4 h-4 mr-1`}),` JSON`]}),(0,P.jsx)(x,{variant:`secondary`,className:`ml-auto`,children:d.length})]}),(0,P.jsx)(C,{className:`h-[calc(100dvh-13rem)]`,children:(0,P.jsxs)(`div`,{className:`space-y-2 pr-2`,children:[d.length===0&&(0,P.jsx)(`div`,{className:`text-center text-muted-foreground py-16 text-sm`,children:`No activity yet`}),d.map(n=>{let r=F[n.kind]||t,i=I[n.kind]||I.message,a=z(n.metadata);return(0,P.jsx)(T,{className:`cursor-pointer hover:bg-accent/40 transition-colors`,onClick:()=>c(n),children:(0,P.jsxs)(w,{className:`p-3 flex gap-3`,children:[(0,P.jsx)(`span`,{className:`inline-flex items-center justify-center w-7 h-7 rounded-md border shrink-0 mt-0.5 ${i}`,children:(0,P.jsx)(r,{className:`w-3.5 h-3.5`})}),(0,P.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,P.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,P.jsx)(`span`,{className:`font-medium text-sm truncate`,children:n.title}),(0,P.jsx)(x,{variant:`outline`,className:`text-xs px-1.5 py-0 border ${i}`,children:n.kind}),(0,P.jsx)(`span`,{className:`text-xs text-muted-foreground ml-auto shrink-0`,title:y(n.ts??n.createdAt),children:_(e,n.ts??n.createdAt)})]}),n.body&&(0,P.jsx)(`p`,{className:`text-xs text-muted-foreground mt-0.5 line-clamp-2`,children:n.body}),n.meta&&(0,P.jsx)(`p`,{className:`text-xs text-muted-foreground/60 mt-0.5 font-mono truncate`,children:n.meta}),a&&(0,P.jsxs)(`p`,{className:`text-xs text-muted-foreground/60 mt-0.5 truncate`,title:a,children:[(0,P.jsx)(`span`,{className:`opacity-70`,children:`via`}),` `,a]})]})]})},n.clientId||n.id)})]})})]})}function U(){let[e,n]=(0,N.useState)(`firehose`);return(0,P.jsxs)(`div`,{className:`space-y-4`,children:[(0,P.jsxs)(`div`,{className:`flex items-center justify-between flex-wrap gap-2`,children:[(0,P.jsxs)(`div`,{className:`flex items-center gap-2`,children:[e===`firehose`?(0,P.jsx)(i,{className:`w-5 h-5 text-muted-foreground`}):(0,P.jsx)(t,{className:`w-5 h-5 text-muted-foreground`}),(0,P.jsx)(`h2`,{className:`text-lg font-semibold`,children:e===`firehose`?`Firehose`:`Events`})]}),(0,P.jsxs)(`div`,{className:`flex items-center gap-1 rounded-md border border-input overflow-hidden`,children:[(0,P.jsx)(`button`,{className:o(`px-3 py-1.5 text-sm transition-colors`,e===`firehose`?`bg-primary text-primary-foreground`:`hover:bg-accent`),onClick:()=>n(`firehose`),children:`Firehose`}),(0,P.jsx)(`button`,{className:o(`px-3 py-1.5 text-sm transition-colors`,e===`events`?`bg-primary text-primary-foreground`:`hover:bg-accent`),onClick:()=>n(`events`),children:`Events`})]})]}),e===`firehose`?(0,P.jsx)(V,{}):(0,P.jsx)(H,{})]})}export{U as ActivityView};
2
- //# sourceMappingURL=activity-Db3X3dg8.js.map