tmux-ide 1.2.1 → 2.0.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 (205) hide show
  1. package/bin/cli.js +4 -216
  2. package/bin/cli.ts +536 -0
  3. package/package.json +33 -14
  4. package/src/__tests__/support.ts +186 -0
  5. package/src/{attach.js → attach.ts} +7 -4
  6. package/src/cli.test.ts +314 -0
  7. package/src/command-center/discovery.test.ts +265 -0
  8. package/src/command-center/discovery.ts +296 -0
  9. package/src/command-center/index.ts +31 -0
  10. package/src/command-center/schemas.ts +57 -0
  11. package/src/command-center/server.test.ts +818 -0
  12. package/src/command-center/server.ts +1426 -0
  13. package/src/config-cli.test.ts +86 -0
  14. package/src/config.test.ts +205 -0
  15. package/src/config.ts +313 -0
  16. package/src/detect.test.ts +142 -0
  17. package/src/{detect.js → detect.ts} +31 -15
  18. package/src/dispatch.ts +102 -0
  19. package/src/doctor.test.ts +119 -0
  20. package/src/doctor.ts +167 -0
  21. package/src/init.test.ts +101 -0
  22. package/src/init.ts +144 -0
  23. package/src/inspect.test.ts +67 -0
  24. package/src/{inspect.js → inspect.ts} +95 -10
  25. package/src/integration.test.ts.skip +276 -0
  26. package/src/js-yaml.d.ts +10 -0
  27. package/src/launch.test.ts +222 -0
  28. package/src/launch.ts +494 -0
  29. package/src/lib/auth/auth-service.test.ts +178 -0
  30. package/src/lib/auth/auth-service.ts +227 -0
  31. package/src/lib/auth/middleware.test.ts +119 -0
  32. package/src/lib/auth/middleware.ts +56 -0
  33. package/src/lib/auth/types.ts +13 -0
  34. package/src/lib/authorship.test.ts +242 -0
  35. package/src/lib/authorship.ts +280 -0
  36. package/src/lib/cast/recorder.test.ts +127 -0
  37. package/src/lib/cast/recorder.ts +148 -0
  38. package/src/lib/daemon-watchdog.ts +102 -0
  39. package/src/lib/daemon.ts +417 -0
  40. package/src/lib/dot-path.test.ts +66 -0
  41. package/src/lib/dot-path.ts +17 -0
  42. package/src/lib/errors.ts +44 -0
  43. package/src/lib/event-log.test.ts +189 -0
  44. package/src/lib/event-log.ts +237 -0
  45. package/src/lib/github-pr.ts +182 -0
  46. package/src/lib/hq/client.test.ts +154 -0
  47. package/src/lib/hq/client.ts +142 -0
  48. package/src/lib/hq/mdns.test.ts +54 -0
  49. package/src/lib/hq/mdns.ts +88 -0
  50. package/src/lib/hq/registry.test.ts +237 -0
  51. package/src/lib/hq/registry.ts +145 -0
  52. package/src/lib/hq/types.ts +44 -0
  53. package/src/lib/ipc/socket-protocol.test.ts +126 -0
  54. package/src/lib/ipc/socket-protocol.ts +324 -0
  55. package/src/lib/launch-plan.test.ts +119 -0
  56. package/src/lib/launch-plan.ts +90 -0
  57. package/src/lib/log.test.ts +39 -0
  58. package/src/lib/log.ts +71 -0
  59. package/src/lib/metrics.test.ts +213 -0
  60. package/src/lib/metrics.ts +345 -0
  61. package/src/lib/orchestrator.test.ts +2358 -0
  62. package/src/lib/orchestrator.ts +1792 -0
  63. package/src/lib/{output.js → output.ts} +18 -10
  64. package/src/lib/plan-store.test.ts +148 -0
  65. package/src/lib/plan-store.ts +131 -0
  66. package/src/lib/research.test.ts +208 -0
  67. package/src/lib/research.ts +475 -0
  68. package/src/lib/round-trip.test.ts +341 -0
  69. package/src/lib/session-monitor.test.ts +152 -0
  70. package/src/lib/session-monitor.ts +282 -0
  71. package/src/lib/session-options.test.ts +146 -0
  72. package/src/lib/{session-options.js → session-options.ts} +11 -6
  73. package/src/lib/shell.test.ts +20 -0
  74. package/src/lib/shell.ts +8 -0
  75. package/src/lib/sizes.test.ts +73 -0
  76. package/src/lib/{sizes.js → sizes.ts} +4 -4
  77. package/src/lib/skill-registry.test.ts +134 -0
  78. package/src/lib/skill-registry.ts +86 -0
  79. package/src/lib/slugify.test.ts +35 -0
  80. package/src/lib/slugify.ts +10 -0
  81. package/src/lib/task-store.ts +352 -0
  82. package/src/lib/tmux.test.ts +500 -0
  83. package/src/lib/tmux.ts +372 -0
  84. package/src/lib/token-tracker.test.ts +102 -0
  85. package/src/lib/token-tracker.ts +70 -0
  86. package/src/lib/tunnels/cloudflare.test.ts +73 -0
  87. package/src/lib/tunnels/cloudflare.ts +254 -0
  88. package/src/lib/tunnels/manager.test.ts +63 -0
  89. package/src/lib/tunnels/manager.ts +132 -0
  90. package/src/lib/tunnels/ngrok.test.ts +94 -0
  91. package/src/lib/tunnels/ngrok.ts +261 -0
  92. package/src/lib/tunnels/tailscale.test.ts +103 -0
  93. package/src/lib/tunnels/tailscale.ts +1048 -0
  94. package/src/lib/tunnels/types.ts +44 -0
  95. package/src/lib/validation.test.ts +289 -0
  96. package/src/lib/validation.ts +123 -0
  97. package/src/lib/webhook.ts +51 -0
  98. package/src/lib/workflow-store.ts +209 -0
  99. package/src/lib/ws-v3/protocol.test.ts +127 -0
  100. package/src/lib/ws-v3/protocol.ts +160 -0
  101. package/src/lib/yaml-io.test.ts +125 -0
  102. package/src/lib/{yaml-io.js → yaml-io.ts} +5 -4
  103. package/src/ls.test.ts +76 -0
  104. package/src/{ls.js → ls.ts} +4 -4
  105. package/src/metrics-cli.ts +177 -0
  106. package/src/notify.ts +85 -0
  107. package/src/orchestrator-status.ts +228 -0
  108. package/src/plan.ts +117 -0
  109. package/src/postinstall.test.ts +79 -0
  110. package/src/remote.test.ts +115 -0
  111. package/src/remote.ts +148 -0
  112. package/src/restart.ts +24 -0
  113. package/src/schemas/domain.ts +422 -0
  114. package/src/schemas/ide-config.ts +148 -0
  115. package/src/schemas/index.ts +53 -0
  116. package/src/send.test.ts +70 -0
  117. package/src/send.ts +181 -0
  118. package/src/skill.test.ts +114 -0
  119. package/src/skill.ts +138 -0
  120. package/src/status.ts +66 -0
  121. package/src/stop.test.ts +176 -0
  122. package/src/stop.ts +47 -0
  123. package/src/task.test.ts +1466 -0
  124. package/src/task.ts +1143 -0
  125. package/src/tunnel.test.ts +80 -0
  126. package/src/tunnel.ts +133 -0
  127. package/src/types.ts +15 -0
  128. package/src/ui/index.ts +32 -0
  129. package/src/ui/terminal/index.ts +9 -0
  130. package/src/ui/types.ts +91 -0
  131. package/src/ui/web/base.css +80 -0
  132. package/src/ui/web/components/Box.tsx +59 -0
  133. package/src/ui/web/components/Input.tsx +32 -0
  134. package/src/ui/web/components/ScrollBox.tsx +60 -0
  135. package/src/ui/web/components/Text.tsx +28 -0
  136. package/src/ui/web/hooks.ts +106 -0
  137. package/src/ui/web/index.ts +27 -0
  138. package/src/ui/web/render.ts +77 -0
  139. package/src/ui/web/utils/color.test.ts +93 -0
  140. package/src/ui/web/utils/color.ts +27 -0
  141. package/src/validate.test.ts +385 -0
  142. package/src/validate.ts +217 -0
  143. package/src/widgets/changes/index.tsx +576 -0
  144. package/src/widgets/config/index.tsx +440 -0
  145. package/src/widgets/costs/index.tsx +216 -0
  146. package/src/widgets/explorer/breadcrumbs.tsx +77 -0
  147. package/src/widgets/explorer/footer.tsx +20 -0
  148. package/src/widgets/explorer/header.tsx +23 -0
  149. package/src/widgets/explorer/index.tsx +408 -0
  150. package/src/widgets/explorer/tree-model.test.ts +214 -0
  151. package/src/widgets/explorer/tree-model.ts +103 -0
  152. package/src/widgets/explorer/tree.tsx +156 -0
  153. package/src/widgets/lib/config-model.ts +116 -0
  154. package/src/widgets/lib/files.test.ts +103 -0
  155. package/src/widgets/lib/files.ts +88 -0
  156. package/src/widgets/lib/git.test.ts +151 -0
  157. package/src/widgets/lib/git.ts +88 -0
  158. package/src/widgets/lib/pane-comms.test.ts +178 -0
  159. package/src/widgets/lib/pane-comms.ts +192 -0
  160. package/src/widgets/lib/theme.ts +151 -0
  161. package/src/widgets/lib/watcher.ts +50 -0
  162. package/src/widgets/mission-control/activity-feed.tsx +59 -0
  163. package/src/widgets/mission-control/agent-panel.tsx +132 -0
  164. package/src/widgets/mission-control/command-bar.tsx +63 -0
  165. package/src/widgets/mission-control/index.tsx +751 -0
  166. package/src/widgets/mission-control/task-panel.tsx +238 -0
  167. package/src/widgets/preview/index.tsx +415 -0
  168. package/src/widgets/resolve.ts +40 -0
  169. package/src/widgets/setup/agent-naming.tsx +112 -0
  170. package/src/widgets/setup/config-tree.tsx +238 -0
  171. package/src/widgets/setup/detect-panel.tsx +72 -0
  172. package/src/widgets/setup/field-editor.tsx +265 -0
  173. package/src/widgets/setup/footer.tsx +107 -0
  174. package/src/widgets/setup/index.tsx +340 -0
  175. package/src/widgets/setup/layout-picker.tsx +96 -0
  176. package/src/widgets/setup/orchestrator-panel.tsx +200 -0
  177. package/src/widgets/setup/review-panel.tsx +140 -0
  178. package/src/widgets/setup/setup-model.test.ts +303 -0
  179. package/src/widgets/setup/setup-model.ts +188 -0
  180. package/src/widgets/tasks/index.tsx +129 -0
  181. package/src/widgets/tasks/task-detail.tsx +309 -0
  182. package/src/widgets/tasks/task-form.tsx +193 -0
  183. package/src/widgets/tasks/task-list.tsx +205 -0
  184. package/src/widgets/tasks/task-model.test.ts +473 -0
  185. package/src/widgets/tasks/task-model.ts +157 -0
  186. package/templates/AGENTS.md +20 -0
  187. package/templates/missions.yml +41 -0
  188. package/templates/skills/backend.md +30 -0
  189. package/templates/skills/frontend.md +30 -0
  190. package/templates/skills/general-worker.md +30 -0
  191. package/templates/skills/researcher.md +69 -0
  192. package/templates/skills/reviewer.md +30 -0
  193. package/src/config.js +0 -341
  194. package/src/doctor.js +0 -91
  195. package/src/init.js +0 -73
  196. package/src/launch.js +0 -245
  197. package/src/lib/dot-path.js +0 -16
  198. package/src/lib/errors.js +0 -35
  199. package/src/lib/launch-plan.js +0 -49
  200. package/src/lib/session-monitor.js +0 -179
  201. package/src/lib/tmux.js +0 -237
  202. package/src/restart.js +0 -16
  203. package/src/status.js +0 -35
  204. package/src/stop.js +0 -25
  205. package/src/validate.js +0 -154
@@ -0,0 +1,422 @@
1
+ import { z } from "zod";
2
+
3
+ // ---------------------------------------------------------------------------
4
+ // ProofSchema (from src/types.ts)
5
+ // ---------------------------------------------------------------------------
6
+
7
+ export const ProofSchemaZ = z.object({
8
+ tests: z.object({ passed: z.number(), total: z.number() }).optional(),
9
+ pr: z
10
+ .object({
11
+ number: z.number(),
12
+ url: z.string().optional(),
13
+ status: z.string().optional(),
14
+ })
15
+ .optional(),
16
+ ci: z.object({ status: z.string(), url: z.string().optional() }).optional(),
17
+ notes: z.string().optional(),
18
+ });
19
+
20
+ export type ProofSchema = z.infer<typeof ProofSchemaZ>;
21
+
22
+ // ---------------------------------------------------------------------------
23
+ // Task / Goal / Mission (from src/lib/task-store.ts)
24
+ // ---------------------------------------------------------------------------
25
+
26
+ export const MilestoneSchemaZ = z.object({
27
+ id: z.string(),
28
+ title: z.string(),
29
+ description: z.string(),
30
+ status: z.enum(["locked", "active", "done", "validating"]),
31
+ order: z.number(),
32
+ created: z.string(),
33
+ updated: z.string(),
34
+ });
35
+
36
+ export const MissionSchemaZ = z.object({
37
+ title: z.string(),
38
+ description: z.string(),
39
+ status: z.enum(["planning", "active", "validating", "complete"]),
40
+ branch: z.string().nullable(),
41
+ milestones: z.array(MilestoneSchemaZ),
42
+ created: z.string(),
43
+ updated: z.string(),
44
+ });
45
+
46
+ export const GoalSchemaZ = z.object({
47
+ id: z.string(),
48
+ title: z.string(),
49
+ description: z.string(),
50
+ status: z.enum(["todo", "in-progress", "done"]),
51
+ acceptance: z.string(),
52
+ priority: z.number(),
53
+ created: z.string(),
54
+ updated: z.string(),
55
+ assignee: z.string().nullable(),
56
+ specialty: z.string().nullable(),
57
+ milestone: z.string().nullable(),
58
+ });
59
+
60
+ export const TaskSchemaZ = z.object({
61
+ id: z.string(),
62
+ title: z.string(),
63
+ description: z.string(),
64
+ goal: z.string().nullable(),
65
+ status: z.enum(["todo", "in-progress", "review", "done"]),
66
+ assignee: z.string().nullable(),
67
+ priority: z.number(),
68
+ created: z.string(),
69
+ updated: z.string(),
70
+ tags: z.array(z.string()),
71
+ proof: ProofSchemaZ.nullable(),
72
+ retryCount: z.number(),
73
+ maxRetries: z.number(),
74
+ lastError: z.string().nullable(),
75
+ nextRetryAt: z.string().nullable(),
76
+ depends_on: z.array(z.string()),
77
+ milestone: z.string().nullable(),
78
+ specialty: z.string().nullable(),
79
+ fulfills: z.array(z.string()),
80
+ discoveredIssues: z.array(z.string()),
81
+ salientSummary: z.string().nullable(),
82
+ });
83
+
84
+ // ---------------------------------------------------------------------------
85
+ // EventType / OrchestratorEvent (from src/lib/event-log.ts)
86
+ // ---------------------------------------------------------------------------
87
+
88
+ export const EventTypeSchemaZ = z.enum([
89
+ "dispatch",
90
+ "stall",
91
+ "completion",
92
+ "retry",
93
+ "reconcile",
94
+ "error",
95
+ "task_created",
96
+ "status_change",
97
+ "send",
98
+ "notify",
99
+ "milestone_validating",
100
+ "milestone_complete",
101
+ "validation_dispatch",
102
+ "remediation",
103
+ "validation_failed",
104
+ "planning",
105
+ "mission_complete",
106
+ "discovered_issue",
107
+ "research_dispatch",
108
+ "research_finding",
109
+ "agent_heartbeat",
110
+ "session_start",
111
+ "session_end",
112
+ ]);
113
+
114
+ export const OrchestratorEventSchemaZ = z.object({
115
+ timestamp: z.string(),
116
+ type: EventTypeSchemaZ,
117
+ taskId: z.string().optional(),
118
+ agent: z.string().optional(),
119
+ message: z.string(),
120
+ });
121
+
122
+ // ---------------------------------------------------------------------------
123
+ // StructuredEvent — discriminated union on "type" with typed payloads
124
+ // ---------------------------------------------------------------------------
125
+
126
+ const DispatchEventZ = z.object({
127
+ timestamp: z.string(),
128
+ type: z.literal("dispatch"),
129
+ taskId: z.string(),
130
+ agent: z.string(),
131
+ });
132
+
133
+ const CompletionEventZ = z.object({
134
+ timestamp: z.string(),
135
+ type: z.literal("completion"),
136
+ taskId: z.string(),
137
+ agent: z.string(),
138
+ durationMs: z.number().optional(),
139
+ });
140
+
141
+ const StallEventZ = z.object({
142
+ timestamp: z.string(),
143
+ type: z.literal("stall"),
144
+ taskId: z.string(),
145
+ agent: z.string(),
146
+ elapsedMs: z.number(),
147
+ });
148
+
149
+ const RetryEventZ = z.object({
150
+ timestamp: z.string(),
151
+ type: z.literal("retry"),
152
+ taskId: z.string(),
153
+ attempt: z.number(),
154
+ maxRetries: z.number(),
155
+ reason: z.string(),
156
+ });
157
+
158
+ const ReconcileEventZ = z.object({
159
+ timestamp: z.string(),
160
+ type: z.literal("reconcile"),
161
+ taskId: z.string(),
162
+ previousAgent: z.string(),
163
+ action: z.string(),
164
+ });
165
+
166
+ const ErrorEventZ = z.object({
167
+ timestamp: z.string(),
168
+ type: z.literal("error"),
169
+ taskId: z.string().optional(),
170
+ agent: z.string().optional(),
171
+ message: z.string(),
172
+ code: z.string().optional(),
173
+ });
174
+
175
+ const TaskCreatedEventZ = z.object({
176
+ timestamp: z.string(),
177
+ type: z.literal("task_created"),
178
+ taskId: z.string(),
179
+ title: z.string(),
180
+ });
181
+
182
+ const StatusChangeEventZ = z.object({
183
+ timestamp: z.string(),
184
+ type: z.literal("status_change"),
185
+ taskId: z.string(),
186
+ from: z.string(),
187
+ to: z.string(),
188
+ });
189
+
190
+ const SendEventZ = z.object({
191
+ timestamp: z.string(),
192
+ type: z.literal("send"),
193
+ target: z.string(),
194
+ paneId: z.string(),
195
+ message: z.string(),
196
+ });
197
+
198
+ const NotifyEventZ = z.object({
199
+ timestamp: z.string(),
200
+ type: z.literal("notify"),
201
+ target: z.string(),
202
+ paneId: z.string(),
203
+ message: z.string(),
204
+ });
205
+
206
+ const MilestoneValidatingEventZ = z.object({
207
+ timestamp: z.string(),
208
+ type: z.literal("milestone_validating"),
209
+ milestoneId: z.string().optional(),
210
+ title: z.string().optional(),
211
+ });
212
+
213
+ const MilestoneCompleteEventZ = z.object({
214
+ timestamp: z.string(),
215
+ type: z.literal("milestone_complete"),
216
+ milestoneId: z.string().optional(),
217
+ title: z.string().optional(),
218
+ });
219
+
220
+ const ValidationDispatchEventZ = z.object({
221
+ timestamp: z.string(),
222
+ type: z.literal("validation_dispatch"),
223
+ milestoneId: z.string().optional(),
224
+ title: z.string().optional(),
225
+ target: z.string().optional(),
226
+ });
227
+
228
+ const RemediationEventZ = z.object({
229
+ timestamp: z.string(),
230
+ type: z.literal("remediation"),
231
+ taskId: z.string(),
232
+ assertionId: z.string().optional(),
233
+ });
234
+
235
+ const ValidationFailedEventZ = z.object({
236
+ timestamp: z.string(),
237
+ type: z.literal("validation_failed"),
238
+ milestoneId: z.string().optional(),
239
+ title: z.string().optional(),
240
+ failedCount: z.number().optional(),
241
+ });
242
+
243
+ const PlanningEventZ = z.object({
244
+ timestamp: z.string(),
245
+ type: z.literal("planning"),
246
+ target: z.string().optional(),
247
+ });
248
+
249
+ const MissionCompleteEventZ = z.object({
250
+ timestamp: z.string(),
251
+ type: z.literal("mission_complete"),
252
+ title: z.string().optional(),
253
+ milestoneCount: z.number().optional(),
254
+ taskCount: z.number().optional(),
255
+ prNumber: z.number().optional(),
256
+ });
257
+
258
+ const DiscoveredIssueEventZ = z.object({
259
+ timestamp: z.string(),
260
+ type: z.literal("discovered_issue"),
261
+ taskId: z.string(),
262
+ sourceTaskId: z.string().optional(),
263
+ issue: z.string().optional(),
264
+ });
265
+
266
+ const ResearchDispatchEventZ = z.object({
267
+ timestamp: z.string(),
268
+ type: z.literal("research_dispatch"),
269
+ taskId: z.string(),
270
+ target: z.string().optional(),
271
+ researchType: z.string().optional(),
272
+ });
273
+
274
+ const ResearchFindingEventZ = z.object({
275
+ timestamp: z.string(),
276
+ type: z.literal("research_finding"),
277
+ taskId: z.string(),
278
+ researchType: z.string().optional(),
279
+ summary: z.string().optional(),
280
+ });
281
+
282
+ export const StructuredEventSchemaZ = z.union([
283
+ DispatchEventZ,
284
+ CompletionEventZ,
285
+ StallEventZ,
286
+ RetryEventZ,
287
+ ReconcileEventZ,
288
+ ErrorEventZ,
289
+ TaskCreatedEventZ,
290
+ StatusChangeEventZ,
291
+ SendEventZ,
292
+ NotifyEventZ,
293
+ MilestoneValidatingEventZ,
294
+ MilestoneCompleteEventZ,
295
+ ValidationDispatchEventZ,
296
+ RemediationEventZ,
297
+ ValidationFailedEventZ,
298
+ PlanningEventZ,
299
+ MissionCompleteEventZ,
300
+ DiscoveredIssueEventZ,
301
+ ResearchDispatchEventZ,
302
+ ResearchFindingEventZ,
303
+ ]);
304
+
305
+ // ---------------------------------------------------------------------------
306
+ // MarkRange / Mark / AuthorshipStats (from src/lib/authorship.ts)
307
+ // ---------------------------------------------------------------------------
308
+
309
+ export const MarkRangeSchemaZ = z.object({
310
+ from: z.number(),
311
+ to: z.number(),
312
+ });
313
+
314
+ export const MarkSchemaZ = z.object({
315
+ id: z.string(),
316
+ kind: z.enum(["authored", "approved", "flagged", "comment", "insert", "delete", "replace"]),
317
+ by: z.string(),
318
+ at: z.string(),
319
+ range: MarkRangeSchemaZ,
320
+ quote: z.string(),
321
+ orphaned: z.boolean().optional(),
322
+ });
323
+
324
+ export const AuthorshipStatsSchemaZ = z.object({
325
+ aiPercent: z.number(),
326
+ humanPercent: z.number(),
327
+ totalChars: z.number(),
328
+ });
329
+
330
+ // ---------------------------------------------------------------------------
331
+ // PlanStatus / PlanMeta (from src/lib/plan-store.ts)
332
+ // ---------------------------------------------------------------------------
333
+
334
+ export const PlanStatusSchemaZ = z.enum(["pending", "in-progress", "done", "archived"]);
335
+
336
+ export const PlanMetaSchemaZ = z.object({
337
+ name: z.string(),
338
+ path: z.string(),
339
+ title: z.string(),
340
+ status: PlanStatusSchemaZ,
341
+ effort: z.string().optional(),
342
+ gate: z.string().optional(),
343
+ completed: z.string().optional(),
344
+ });
345
+
346
+ // ---------------------------------------------------------------------------
347
+ // PaneInfo (from src/widgets/lib/pane-comms.ts)
348
+ // ---------------------------------------------------------------------------
349
+
350
+ export const PaneInfoSchemaZ = z.object({
351
+ id: z.string(),
352
+ index: z.number(),
353
+ title: z.string(),
354
+ currentCommand: z.string(),
355
+ width: z.number(),
356
+ height: z.number(),
357
+ active: z.boolean(),
358
+ role: z
359
+ .enum(["lead", "teammate", "planner", "validator", "researcher", "widget", "shell"])
360
+ .nullable(),
361
+ name: z.string().nullable(),
362
+ type: z.string().nullable(),
363
+ });
364
+
365
+ // ---------------------------------------------------------------------------
366
+ // AgentDetail / SessionStats / SessionOverview / ProjectDetail
367
+ // (from src/command-center/discovery.ts)
368
+ // ---------------------------------------------------------------------------
369
+
370
+ export const AgentDetailSchemaZ = z.object({
371
+ paneTitle: z.string(),
372
+ paneId: z.string(),
373
+ isBusy: z.boolean(),
374
+ taskTitle: z.string().nullable(),
375
+ taskId: z.string().nullable(),
376
+ elapsed: z.string(),
377
+ });
378
+
379
+ export const SessionStatsSchemaZ = z.object({
380
+ totalTasks: z.number(),
381
+ doneTasks: z.number(),
382
+ agents: z.number(),
383
+ activeAgents: z.number(),
384
+ });
385
+
386
+ export const SessionOverviewSchemaZ = z.object({
387
+ name: z.string(),
388
+ dir: z.string(),
389
+ mission: MissionSchemaZ.nullable(),
390
+ stats: SessionStatsSchemaZ,
391
+ goals: z.array(
392
+ z.object({
393
+ id: z.string(),
394
+ title: z.string(),
395
+ progress: z.number(),
396
+ }),
397
+ ),
398
+ });
399
+
400
+ export const ProjectDetailSchemaZ = z.object({
401
+ session: z.string(),
402
+ dir: z.string(),
403
+ mission: MissionSchemaZ.nullable(),
404
+ goals: z.array(GoalSchemaZ),
405
+ tasks: z.array(TaskSchemaZ),
406
+ agents: z.array(AgentDetailSchemaZ),
407
+ });
408
+
409
+ // ---------------------------------------------------------------------------
410
+ // Inferred types
411
+ // ---------------------------------------------------------------------------
412
+
413
+ export type Mission = z.infer<typeof MissionSchemaZ>;
414
+ export type Goal = z.infer<typeof GoalSchemaZ>;
415
+ export type Task = z.infer<typeof TaskSchemaZ>;
416
+ export type EventType = z.infer<typeof EventTypeSchemaZ>;
417
+ export type Mark = z.infer<typeof MarkSchemaZ>;
418
+ export type MarkRange = z.infer<typeof MarkRangeSchemaZ>;
419
+ export type AuthorshipStats = z.infer<typeof AuthorshipStatsSchemaZ>;
420
+ export type AgentDetail = z.infer<typeof AgentDetailSchemaZ>;
421
+ export type SessionOverview = z.infer<typeof SessionOverviewSchemaZ>;
422
+ export type ProjectDetail = z.infer<typeof ProjectDetailSchemaZ>;
@@ -0,0 +1,148 @@
1
+ import { z } from "zod";
2
+ import { AuthConfigSchema } from "../lib/auth/types.ts";
3
+ import { HQConfigSchema } from "../lib/hq/types.ts";
4
+
5
+ const sizeField = z
6
+ .string()
7
+ .regex(/^[1-9]\d*%$/)
8
+ .refine((v) => parseInt(v) <= 100);
9
+
10
+ export const ThemeConfigSchema = z.object({
11
+ accent: z.string().optional(),
12
+ border: z.string().optional(),
13
+ bg: z.string().optional(),
14
+ fg: z.string().optional(),
15
+ });
16
+
17
+ export const PaneSchema = z.object({
18
+ title: z.string().optional(),
19
+ command: z.string().optional(),
20
+ type: z
21
+ .enum(["explorer", "changes", "preview", "tasks", "costs", "config", "mission-control"])
22
+ .optional(),
23
+ target: z.string().optional(),
24
+ dir: z.string().optional(),
25
+ size: sizeField.optional(),
26
+ focus: z.boolean().optional(),
27
+ env: z.record(z.string(), z.union([z.string(), z.number()])).optional(),
28
+ role: z.enum(["lead", "teammate", "planner", "validator", "researcher"]).optional(),
29
+ task: z.string().optional(),
30
+ specialty: z.string().optional(),
31
+ skill: z.string().optional(),
32
+ });
33
+
34
+ export const RowSchema = z.object({
35
+ size: sizeField.optional(),
36
+ panes: z.array(PaneSchema).min(1),
37
+ });
38
+
39
+ export const WebhookConfigSchema = z.object({
40
+ url: z.string(),
41
+ events: z.array(z.string()).optional(),
42
+ secret: z.string().optional(),
43
+ });
44
+
45
+ export const OrchestratorYamlConfigSchema = z.object({
46
+ enabled: z.boolean().optional(),
47
+ port: z.number().int().positive().optional(),
48
+ auto_dispatch: z.boolean().optional(),
49
+ stall_timeout: z.number().optional(),
50
+ poll_interval: z.number().min(100).optional(),
51
+ master_pane: z.string().optional(),
52
+ before_run: z.string().optional(),
53
+ after_run: z.string().optional(),
54
+ dispatch_mode: z.enum(["tasks", "goals", "missions"]).optional(),
55
+ max_concurrent_agents: z.number().min(1).max(50).optional(),
56
+ widgets: z.boolean().optional(),
57
+ webhooks: z.array(WebhookConfigSchema).optional(),
58
+ services: z
59
+ .record(
60
+ z.string(),
61
+ z.object({
62
+ command: z.string(),
63
+ port: z.number().optional(),
64
+ healthcheck: z.string().optional(),
65
+ }),
66
+ )
67
+ .optional(),
68
+ research: z
69
+ .object({
70
+ enabled: z.boolean().optional(),
71
+ triggers: z
72
+ .object({
73
+ mission_start: z.boolean().optional(),
74
+ milestone_progress: z.number().min(0).optional(),
75
+ milestone_complete: z.boolean().optional(),
76
+ periodic_minutes: z.number().min(0).optional(),
77
+ retry_cluster: z.boolean().optional(),
78
+ stall_detected: z.boolean().optional(),
79
+ discovered_issue: z.boolean().optional(),
80
+ })
81
+ .optional(),
82
+ })
83
+ .optional(),
84
+ });
85
+
86
+ export const TunnelConfigSchema = z.object({
87
+ provider: z.enum(["tailscale", "ngrok", "cloudflare"]),
88
+ auto_start: z.boolean().optional(),
89
+ port: z.number().int().positive().optional(),
90
+ domain: z.string().optional(),
91
+ authtoken: z.string().optional(),
92
+ });
93
+
94
+ export const CommandCenterConfigSchema = z.object({
95
+ port: z.number().optional(),
96
+ enabled: z.boolean().optional(),
97
+ });
98
+
99
+ export const DashboardConfigSchema = z.object({
100
+ port: z.number().int().positive().optional(),
101
+ });
102
+
103
+ export const IdeConfigSchema = z.object({
104
+ name: z.string().optional(),
105
+ before: z.string().optional(),
106
+ team: z
107
+ .object({
108
+ name: z.string(),
109
+ model: z.string().optional(),
110
+ permissions: z.array(z.string()).optional(),
111
+ })
112
+ .optional(),
113
+ rows: z.array(RowSchema).min(1),
114
+ theme: ThemeConfigSchema.optional(),
115
+ orchestrator: OrchestratorYamlConfigSchema.optional(),
116
+ command_center: CommandCenterConfigSchema.optional(),
117
+ dashboard: DashboardConfigSchema.optional(),
118
+ auth: AuthConfigSchema.optional(),
119
+ tunnel: TunnelConfigSchema.optional(),
120
+ hq: HQConfigSchema.optional(),
121
+ });
122
+
123
+ export const PaneActionSchema = z.object({
124
+ targetPane: z.string(),
125
+ title: z.string().nullable(),
126
+ chdir: z.string().nullable(),
127
+ exports: z.array(z.string()),
128
+ command: z.string().nullable(),
129
+ widgetType: z.string().nullable(),
130
+ widgetTarget: z.string().nullable(),
131
+ paneRole: z.string().nullable(),
132
+ paneType: z.string().nullable(),
133
+ });
134
+
135
+ export const SessionStateSchema = z.object({
136
+ running: z.boolean(),
137
+ reason: z.string().nullable(),
138
+ });
139
+
140
+ export type ThemeConfig = z.infer<typeof ThemeConfigSchema>;
141
+ export type Pane = z.infer<typeof PaneSchema>;
142
+ export type Row = z.infer<typeof RowSchema>;
143
+ export type OrchestratorYamlConfig = z.infer<typeof OrchestratorYamlConfigSchema>;
144
+ export type CommandCenterConfig = z.infer<typeof CommandCenterConfigSchema>;
145
+ export type DashboardConfig = z.infer<typeof DashboardConfigSchema>;
146
+ export type IdeConfig = z.infer<typeof IdeConfigSchema>;
147
+ export type PaneAction = z.infer<typeof PaneActionSchema>;
148
+ export type SessionState = z.infer<typeof SessionStateSchema>;
@@ -0,0 +1,53 @@
1
+ export {
2
+ PaneSchema,
3
+ RowSchema,
4
+ ThemeConfigSchema,
5
+ OrchestratorYamlConfigSchema,
6
+ IdeConfigSchema,
7
+ PaneActionSchema,
8
+ SessionStateSchema,
9
+ } from "./ide-config.ts";
10
+
11
+ export type {
12
+ Pane,
13
+ Row,
14
+ ThemeConfig,
15
+ OrchestratorYamlConfig,
16
+ IdeConfig,
17
+ PaneAction,
18
+ SessionState,
19
+ } from "./ide-config.ts";
20
+
21
+ export {
22
+ ProofSchemaZ,
23
+ TaskSchemaZ,
24
+ GoalSchemaZ,
25
+ MissionSchemaZ,
26
+ EventTypeSchemaZ,
27
+ OrchestratorEventSchemaZ,
28
+ MarkRangeSchemaZ,
29
+ MarkSchemaZ,
30
+ AuthorshipStatsSchemaZ,
31
+ PlanStatusSchemaZ,
32
+ PlanMetaSchemaZ,
33
+ AgentDetailSchemaZ,
34
+ SessionOverviewSchemaZ,
35
+ ProjectDetailSchemaZ,
36
+ SessionStatsSchemaZ,
37
+ PaneInfoSchemaZ,
38
+ StructuredEventSchemaZ,
39
+ } from "./domain.ts";
40
+
41
+ export type {
42
+ ProofSchema,
43
+ Mission,
44
+ Goal,
45
+ Task,
46
+ EventType,
47
+ Mark,
48
+ MarkRange,
49
+ AuthorshipStats,
50
+ AgentDetail,
51
+ SessionOverview,
52
+ ProjectDetail,
53
+ } from "./domain.ts";
@@ -0,0 +1,70 @@
1
+ import { describe, it, beforeEach, afterEach, expect } from "bun:test";
2
+ import { mkdtempSync, rmSync, existsSync, readFileSync, mkdirSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { writeDispatchFile, LONG_MESSAGE_THRESHOLD } from "./send.ts";
6
+
7
+ let tmpDir: string;
8
+
9
+ beforeEach(() => {
10
+ tmpDir = mkdtempSync(join(tmpdir(), "tmux-ide-send-test-"));
11
+ mkdirSync(join(tmpDir, ".tasks"), { recursive: true });
12
+ });
13
+
14
+ afterEach(() => {
15
+ rmSync(tmpDir, { recursive: true, force: true });
16
+ });
17
+
18
+ describe("writeDispatchFile", () => {
19
+ it("writes long message to dispatch file and returns trigger command", () => {
20
+ const longMessage = "x".repeat(200);
21
+ const result = writeDispatchFile(tmpDir, "%1", longMessage);
22
+
23
+ expect(result).not.toBeNull();
24
+ expect(result!.triggerCmd).toContain(".tasks/dispatch/");
25
+ expect(result!.triggerCmd).toContain("send-1-");
26
+ expect(existsSync(result!.filePath)).toBe(true);
27
+ expect(readFileSync(result!.filePath, "utf-8")).toBe(longMessage);
28
+ });
29
+
30
+ it("returns null for short messages", () => {
31
+ const result = writeDispatchFile(tmpDir, "%1", "hello");
32
+ expect(result).toBeNull();
33
+ });
34
+
35
+ it("returns null for messages exactly at threshold", () => {
36
+ const result = writeDispatchFile(tmpDir, "%1", "x".repeat(LONG_MESSAGE_THRESHOLD));
37
+ expect(result).toBeNull();
38
+ });
39
+
40
+ it("creates dispatch directory if it does not exist", () => {
41
+ const longMessage = "y".repeat(200);
42
+ const result = writeDispatchFile(tmpDir, "%2", longMessage);
43
+ expect(result).not.toBeNull();
44
+ expect(existsSync(join(tmpDir, ".tasks", "dispatch"))).toBe(true);
45
+ });
46
+
47
+ it("creates unique filenames for different panes", () => {
48
+ const msg = "z".repeat(200);
49
+ const r1 = writeDispatchFile(tmpDir, "%1", msg);
50
+ const r2 = writeDispatchFile(tmpDir, "%2", msg);
51
+ expect(r1).not.toBeNull();
52
+ expect(r2).not.toBeNull();
53
+ expect(r1!.filePath).not.toBe(r2!.filePath);
54
+ });
55
+
56
+ it("adds a random suffix so same-pane writes stay unique in the same millisecond", () => {
57
+ const originalNow = Date.now;
58
+ Date.now = () => 1234567890;
59
+ try {
60
+ const msg = "z".repeat(200);
61
+ const r1 = writeDispatchFile(tmpDir, "%1", msg);
62
+ const r2 = writeDispatchFile(tmpDir, "%1", msg);
63
+ expect(r1).not.toBeNull();
64
+ expect(r2).not.toBeNull();
65
+ expect(r1!.filePath).not.toBe(r2!.filePath);
66
+ } finally {
67
+ Date.now = originalNow;
68
+ }
69
+ });
70
+ });