@a5c-ai/adapters-gateway 5.1.1-staging.52898ebfc24f

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 (202) hide show
  1. package/README.md +20 -0
  2. package/dist/auth/bootstrap.d.ts +89 -0
  3. package/dist/auth/bootstrap.d.ts.map +1 -0
  4. package/dist/auth/bootstrap.js +222 -0
  5. package/dist/auth/bootstrap.js.map +1 -0
  6. package/dist/auth/hashing.d.ts +4 -0
  7. package/dist/auth/hashing.d.ts.map +1 -0
  8. package/dist/auth/hashing.js +27 -0
  9. package/dist/auth/hashing.js.map +1 -0
  10. package/dist/auth/middleware.d.ts +3 -0
  11. package/dist/auth/middleware.d.ts.map +1 -0
  12. package/dist/auth/middleware.js +17 -0
  13. package/dist/auth/middleware.js.map +1 -0
  14. package/dist/auth/tokens.d.ts +45 -0
  15. package/dist/auth/tokens.d.ts.map +1 -0
  16. package/dist/auth/tokens.js +186 -0
  17. package/dist/auth/tokens.js.map +1 -0
  18. package/dist/builtin-adapters.d.ts +17 -0
  19. package/dist/builtin-adapters.d.ts.map +1 -0
  20. package/dist/builtin-adapters.js +119 -0
  21. package/dist/builtin-adapters.js.map +1 -0
  22. package/dist/config.d.ts +37 -0
  23. package/dist/config.d.ts.map +1 -0
  24. package/dist/config.js +97 -0
  25. package/dist/config.js.map +1 -0
  26. package/dist/fanout/client-conn.d.ts +20 -0
  27. package/dist/fanout/client-conn.d.ts.map +1 -0
  28. package/dist/fanout/client-conn.js +53 -0
  29. package/dist/fanout/client-conn.js.map +1 -0
  30. package/dist/fanout/subscriber.d.ts +12 -0
  31. package/dist/fanout/subscriber.d.ts.map +1 -0
  32. package/dist/fanout/subscriber.js +40 -0
  33. package/dist/fanout/subscriber.js.map +1 -0
  34. package/dist/index.d.ts +30 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +52 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/kanban/lib/config-loader.d.ts +29 -0
  39. package/dist/kanban/lib/config-loader.d.ts.map +1 -0
  40. package/dist/kanban/lib/config-loader.js +166 -0
  41. package/dist/kanban/lib/config-loader.js.map +1 -0
  42. package/dist/kanban/lib/config.d.ts +3 -0
  43. package/dist/kanban/lib/config.d.ts.map +1 -0
  44. package/dist/kanban/lib/config.js +6 -0
  45. package/dist/kanban/lib/config.js.map +1 -0
  46. package/dist/kanban/lib/create-global-registry.d.ts +28 -0
  47. package/dist/kanban/lib/create-global-registry.d.ts.map +1 -0
  48. package/dist/kanban/lib/create-global-registry.js +53 -0
  49. package/dist/kanban/lib/create-global-registry.js.map +1 -0
  50. package/dist/kanban/lib/dispatch-context-audit.d.ts +12 -0
  51. package/dist/kanban/lib/dispatch-context-audit.d.ts.map +1 -0
  52. package/dist/kanban/lib/dispatch-context-audit.js +44 -0
  53. package/dist/kanban/lib/dispatch-context-audit.js.map +1 -0
  54. package/dist/kanban/lib/error-handler.d.ts +28 -0
  55. package/dist/kanban/lib/error-handler.d.ts.map +1 -0
  56. package/dist/kanban/lib/error-handler.js +61 -0
  57. package/dist/kanban/lib/error-handler.js.map +1 -0
  58. package/dist/kanban/lib/global-registry.d.ts +49 -0
  59. package/dist/kanban/lib/global-registry.d.ts.map +1 -0
  60. package/dist/kanban/lib/global-registry.js +18 -0
  61. package/dist/kanban/lib/global-registry.js.map +1 -0
  62. package/dist/kanban/lib/parser.d.ts +36 -0
  63. package/dist/kanban/lib/parser.d.ts.map +1 -0
  64. package/dist/kanban/lib/parser.js +585 -0
  65. package/dist/kanban/lib/parser.js.map +1 -0
  66. package/dist/kanban/lib/path-resolver.d.ts +2 -0
  67. package/dist/kanban/lib/path-resolver.d.ts.map +1 -0
  68. package/dist/kanban/lib/path-resolver.js +16 -0
  69. package/dist/kanban/lib/path-resolver.js.map +1 -0
  70. package/dist/kanban/lib/review-service.d.ts +63 -0
  71. package/dist/kanban/lib/review-service.d.ts.map +1 -0
  72. package/dist/kanban/lib/review-service.js +571 -0
  73. package/dist/kanban/lib/review-service.js.map +1 -0
  74. package/dist/kanban/lib/run-cache.d.ts +36 -0
  75. package/dist/kanban/lib/run-cache.d.ts.map +1 -0
  76. package/dist/kanban/lib/run-cache.js +313 -0
  77. package/dist/kanban/lib/run-cache.js.map +1 -0
  78. package/dist/kanban/lib/server-init.d.ts +26 -0
  79. package/dist/kanban/lib/server-init.d.ts.map +1 -0
  80. package/dist/kanban/lib/server-init.js +179 -0
  81. package/dist/kanban/lib/server-init.js.map +1 -0
  82. package/dist/kanban/lib/services/automation-rule-service.d.ts +97 -0
  83. package/dist/kanban/lib/services/automation-rule-service.d.ts.map +1 -0
  84. package/dist/kanban/lib/services/automation-rule-service.js +806 -0
  85. package/dist/kanban/lib/services/automation-rule-service.js.map +1 -0
  86. package/dist/kanban/lib/services/automation-webhook-service.d.ts +44 -0
  87. package/dist/kanban/lib/services/automation-webhook-service.d.ts.map +1 -0
  88. package/dist/kanban/lib/services/automation-webhook-service.js +405 -0
  89. package/dist/kanban/lib/services/automation-webhook-service.js.map +1 -0
  90. package/dist/kanban/lib/services/backlog-query-service.d.ts +130 -0
  91. package/dist/kanban/lib/services/backlog-query-service.d.ts.map +1 -0
  92. package/dist/kanban/lib/services/backlog-query-service.js +1972 -0
  93. package/dist/kanban/lib/services/backlog-query-service.js.map +1 -0
  94. package/dist/kanban/lib/services/dispatch-context-label-service.d.ts +39 -0
  95. package/dist/kanban/lib/services/dispatch-context-label-service.d.ts.map +1 -0
  96. package/dist/kanban/lib/services/dispatch-context-label-service.js +160 -0
  97. package/dist/kanban/lib/services/dispatch-context-label-service.js.map +1 -0
  98. package/dist/kanban/lib/services/kanban-storage.d.ts +36 -0
  99. package/dist/kanban/lib/services/kanban-storage.d.ts.map +1 -0
  100. package/dist/kanban/lib/services/kanban-storage.js +26 -0
  101. package/dist/kanban/lib/services/kanban-storage.js.map +1 -0
  102. package/dist/kanban/lib/services/run-query-service.d.ts +79 -0
  103. package/dist/kanban/lib/services/run-query-service.d.ts.map +1 -0
  104. package/dist/kanban/lib/services/run-query-service.js +202 -0
  105. package/dist/kanban/lib/services/run-query-service.js.map +1 -0
  106. package/dist/kanban/lib/services/task-tag-service.d.ts +39 -0
  107. package/dist/kanban/lib/services/task-tag-service.d.ts.map +1 -0
  108. package/dist/kanban/lib/services/task-tag-service.js +145 -0
  109. package/dist/kanban/lib/services/task-tag-service.js.map +1 -0
  110. package/dist/kanban/lib/settings-section-storage.d.ts +13 -0
  111. package/dist/kanban/lib/settings-section-storage.d.ts.map +1 -0
  112. package/dist/kanban/lib/settings-section-storage.js +38 -0
  113. package/dist/kanban/lib/settings-section-storage.js.map +1 -0
  114. package/dist/kanban/lib/source-discovery.d.ts +10 -0
  115. package/dist/kanban/lib/source-discovery.d.ts.map +1 -0
  116. package/dist/kanban/lib/source-discovery.js +201 -0
  117. package/dist/kanban/lib/source-discovery.js.map +1 -0
  118. package/dist/kanban/lib/utils.d.ts +8 -0
  119. package/dist/kanban/lib/utils.d.ts.map +1 -0
  120. package/dist/kanban/lib/utils.js +116 -0
  121. package/dist/kanban/lib/utils.js.map +1 -0
  122. package/dist/kanban/lib/watcher.d.ts +14 -0
  123. package/dist/kanban/lib/watcher.d.ts.map +1 -0
  124. package/dist/kanban/lib/watcher.js +221 -0
  125. package/dist/kanban/lib/watcher.js.map +1 -0
  126. package/dist/kanban/lib/workspace-lifecycle.d.ts +68 -0
  127. package/dist/kanban/lib/workspace-lifecycle.d.ts.map +1 -0
  128. package/dist/kanban/lib/workspace-lifecycle.js +1085 -0
  129. package/dist/kanban/lib/workspace-lifecycle.js.map +1 -0
  130. package/dist/kanban/routes.d.ts +2 -0
  131. package/dist/kanban/routes.d.ts.map +1 -0
  132. package/dist/kanban/routes.js +1358 -0
  133. package/dist/kanban/routes.js.map +1 -0
  134. package/dist/kanban/types/breakpoint.d.ts +13 -0
  135. package/dist/kanban/types/breakpoint.d.ts.map +1 -0
  136. package/dist/kanban/types/breakpoint.js +3 -0
  137. package/dist/kanban/types/breakpoint.js.map +1 -0
  138. package/dist/kanban/types/index.d.ts +173 -0
  139. package/dist/kanban/types/index.d.ts.map +1 -0
  140. package/dist/kanban/types/index.js +3 -0
  141. package/dist/kanban/types/index.js.map +1 -0
  142. package/dist/logging.d.ts +7 -0
  143. package/dist/logging.d.ts.map +1 -0
  144. package/dist/logging.js +22 -0
  145. package/dist/logging.js.map +1 -0
  146. package/dist/notifications/types.d.ts +18 -0
  147. package/dist/notifications/types.d.ts.map +1 -0
  148. package/dist/notifications/types.js +2 -0
  149. package/dist/notifications/types.js.map +1 -0
  150. package/dist/notifications/webhook-out.d.ts +3 -0
  151. package/dist/notifications/webhook-out.d.ts.map +1 -0
  152. package/dist/notifications/webhook-out.js +55 -0
  153. package/dist/notifications/webhook-out.js.map +1 -0
  154. package/dist/pairing/short-code.d.ts +20 -0
  155. package/dist/pairing/short-code.d.ts.map +1 -0
  156. package/dist/pairing/short-code.js +50 -0
  157. package/dist/pairing/short-code.js.map +1 -0
  158. package/dist/protocol/errors.d.ts +10 -0
  159. package/dist/protocol/errors.d.ts.map +1 -0
  160. package/dist/protocol/errors.js +15 -0
  161. package/dist/protocol/errors.js.map +1 -0
  162. package/dist/protocol/frames.d.ts +107 -0
  163. package/dist/protocol/frames.d.ts.map +1 -0
  164. package/dist/protocol/frames.js +146 -0
  165. package/dist/protocol/frames.js.map +1 -0
  166. package/dist/protocol/v1.d.ts +111 -0
  167. package/dist/protocol/v1.d.ts.map +1 -0
  168. package/dist/protocol/v1.js +2 -0
  169. package/dist/protocol/v1.js.map +1 -0
  170. package/dist/runs/event-log-index.d.ts +29 -0
  171. package/dist/runs/event-log-index.d.ts.map +1 -0
  172. package/dist/runs/event-log-index.js +210 -0
  173. package/dist/runs/event-log-index.js.map +1 -0
  174. package/dist/runs/event-log.d.ts +25 -0
  175. package/dist/runs/event-log.d.ts.map +1 -0
  176. package/dist/runs/event-log.js +104 -0
  177. package/dist/runs/event-log.js.map +1 -0
  178. package/dist/runs/hook-broker.d.ts +18 -0
  179. package/dist/runs/hook-broker.d.ts.map +1 -0
  180. package/dist/runs/hook-broker.js +110 -0
  181. package/dist/runs/hook-broker.js.map +1 -0
  182. package/dist/runs/manager.d.ts +57 -0
  183. package/dist/runs/manager.d.ts.map +1 -0
  184. package/dist/runs/manager.js +757 -0
  185. package/dist/runs/manager.js.map +1 -0
  186. package/dist/runs/session-runtime.d.ts +8 -0
  187. package/dist/runs/session-runtime.d.ts.map +1 -0
  188. package/dist/runs/session-runtime.js +291 -0
  189. package/dist/runs/session-runtime.js.map +1 -0
  190. package/dist/runs/types.d.ts +55 -0
  191. package/dist/runs/types.d.ts.map +1 -0
  192. package/dist/runs/types.js +2 -0
  193. package/dist/runs/types.js.map +1 -0
  194. package/dist/server.d.ts +15 -0
  195. package/dist/server.d.ts.map +1 -0
  196. package/dist/server.js +702 -0
  197. package/dist/server.js.map +1 -0
  198. package/dist/static/webui-server.d.ts +2 -0
  199. package/dist/static/webui-server.d.ts.map +1 -0
  200. package/dist/static/webui-server.js +97 -0
  201. package/dist/static/webui-server.js.map +1 -0
  202. package/package.json +68 -0
@@ -0,0 +1,201 @@
1
+ import { promises as fs } from "fs";
2
+ import path from "path";
3
+ import { isNotFoundError, getConfig } from "./config-loader.js";
4
+ // Discover all .a5c/runs/ directories within a source
5
+ async function discoverRunsInSource(source) {
6
+ const results = [];
7
+ async function scan(dir, currentDepth) {
8
+ try {
9
+ // Check if this directory itself IS an .a5c/runs dir (depth=0 means direct path)
10
+ if (source.depth === 0) {
11
+ const entries = await fs.readdir(dir, { withFileTypes: true });
12
+ return entries
13
+ .filter((e) => e.isDirectory())
14
+ .map((e) => path.join(dir, e.name));
15
+ }
16
+ // Check for .a5c/runs/ at this level
17
+ const runsPath = path.join(dir, ".a5c", "runs");
18
+ try {
19
+ const stat = await fs.stat(runsPath);
20
+ if (stat.isDirectory()) {
21
+ results.push(runsPath);
22
+ }
23
+ }
24
+ catch {
25
+ // Expected: no .a5c/runs directory at this level — skip silently
26
+ }
27
+ // Recurse into subdirectories if within depth
28
+ if (currentDepth < source.depth) {
29
+ const entries = await fs.readdir(dir, { withFileTypes: true });
30
+ for (const entry of entries) {
31
+ if (entry.isDirectory() &&
32
+ !entry.name.startsWith(".") &&
33
+ entry.name !== "node_modules") {
34
+ await scan(path.join(dir, entry.name), currentDepth + 1);
35
+ }
36
+ }
37
+ }
38
+ }
39
+ catch (err) {
40
+ if (!isNotFoundError(err)) {
41
+ console.warn(`[config] Cannot scan directory ${dir} (depth=${currentDepth}):`, err);
42
+ }
43
+ }
44
+ }
45
+ if (source.depth === 0) {
46
+ // Direct .a5c/runs path — just return runs inside it
47
+ try {
48
+ const entries = await fs.readdir(source.path, { withFileTypes: true });
49
+ return entries
50
+ .filter((e) => e.isDirectory())
51
+ .map((e) => path.join(source.path, e.name));
52
+ }
53
+ catch (err) {
54
+ console.warn(`[config] Cannot list runs in direct source ${source.path}:`, err);
55
+ return [];
56
+ }
57
+ }
58
+ await scan(source.path, 0);
59
+ return results;
60
+ }
61
+ // Extract project name from a .a5c/runs/ path
62
+ function extractProjectName(runsDir) {
63
+ // runsDir is like /path/to/project/.a5c/runs
64
+ // projectPath is /path/to/project
65
+ const a5cDir = path.dirname(runsDir); // .a5c
66
+ const projectPath = path.dirname(a5cDir); // project dir
67
+ const projectName = path.basename(projectPath);
68
+ return { projectName, projectPath };
69
+ }
70
+ // Cache discovery results to avoid repeated filesystem scanning
71
+ let discoveryCache = [];
72
+ let discoveryCacheTime = 0;
73
+ const DISCOVERY_CACHE_TTL = 10000; // 10s — watcher handles real-time changes
74
+ // Force re-discovery on next call (called when new runs are detected by watcher)
75
+ export function invalidateDiscoveryCache() {
76
+ discoveryCache = [];
77
+ discoveryCacheTime = 0;
78
+ }
79
+ // Get all run directories across all sources
80
+ export async function discoverAllRunDirs() {
81
+ const now = Date.now();
82
+ if (discoveryCache.length > 0 && now - discoveryCacheTime < DISCOVERY_CACHE_TTL) {
83
+ return discoveryCache;
84
+ }
85
+ const config = await getConfig();
86
+ const allRuns = [];
87
+ for (const source of config.sources) {
88
+ if (source.depth === 0) {
89
+ // Direct runs directory — list subdirs as individual runs
90
+ // Project name: prefer run.json's projectName, fall back to source label or path
91
+ const fallbackProjectName = source.label || path.basename(source.path);
92
+ try {
93
+ const entries = await fs.readdir(source.path, { withFileTypes: true });
94
+ for (const entry of entries) {
95
+ if (entry.isDirectory()) {
96
+ // Try to read projectName from run.json for more accurate project grouping
97
+ let projectName = fallbackProjectName;
98
+ try {
99
+ const runJsonPath = path.join(source.path, entry.name, "run.json");
100
+ const content = await fs.readFile(runJsonPath, "utf-8");
101
+ const json = JSON.parse(content);
102
+ if (json.projectName) {
103
+ projectName = json.projectName;
104
+ }
105
+ }
106
+ catch (err) {
107
+ // run.json missing is expected for new runs; warn only on parse/permission errors
108
+ if (!isNotFoundError(err)) {
109
+ console.warn(`[config] Failed to read run.json in ${path.join(source.path, entry.name)} — using fallback project name:`, err);
110
+ }
111
+ }
112
+ allRuns.push({
113
+ runDir: path.join(source.path, entry.name),
114
+ source,
115
+ projectName,
116
+ projectPath: source.path,
117
+ });
118
+ }
119
+ }
120
+ }
121
+ catch (err) {
122
+ console.warn(`[config] Source directory not accessible ${source.path}:`, err);
123
+ }
124
+ }
125
+ else {
126
+ // Discover .a5c/runs/ directories within depth
127
+ const runsDirs = await discoverRunsInSource(source);
128
+ for (const runsDir of runsDirs) {
129
+ const { projectName, projectPath } = extractProjectName(runsDir);
130
+ try {
131
+ const entries = await fs.readdir(runsDir, { withFileTypes: true });
132
+ for (const entry of entries) {
133
+ if (entry.isDirectory()) {
134
+ allRuns.push({
135
+ runDir: path.join(runsDir, entry.name),
136
+ source,
137
+ projectName,
138
+ projectPath,
139
+ });
140
+ }
141
+ }
142
+ }
143
+ catch (err) {
144
+ console.warn(`[config] Cannot read runs directory ${runsDir}:`, err);
145
+ }
146
+ }
147
+ }
148
+ }
149
+ // Deduplicate by runId (basename of runDir). When the same run ID appears
150
+ // under multiple .a5c/runs/ directories (e.g. a "ghost" .a5c created by a
151
+ // task execution in a subdirectory), keep the first occurrence — which is
152
+ // the shallowest/earliest discovered and typically the one with full data
153
+ // (run.json + journal).
154
+ const seenRunIds = new Map();
155
+ for (const run of allRuns) {
156
+ const runId = path.basename(run.runDir);
157
+ if (!seenRunIds.has(runId)) {
158
+ seenRunIds.set(runId, run);
159
+ }
160
+ else {
161
+ // Prefer the run directory that has a run.json (i.e. the real one)
162
+ const existing = seenRunIds.get(runId);
163
+ const existingHasRunJson = await fs.access(path.join(existing.runDir, "run.json")).then(() => true, () => false);
164
+ if (!existingHasRunJson) {
165
+ const candidateHasRunJson = await fs.access(path.join(run.runDir, "run.json")).then(() => true, () => false);
166
+ if (candidateHasRunJson) {
167
+ seenRunIds.set(runId, run);
168
+ }
169
+ }
170
+ }
171
+ }
172
+ const result = Array.from(seenRunIds.values());
173
+ discoveryCache = result;
174
+ discoveryCacheTime = Date.now();
175
+ return result;
176
+ }
177
+ // Discover all .a5c/runs/ parent directories (including empty ones).
178
+ // Used by the watcher to set up watches on directories that don't have runs yet,
179
+ // so that the very first run in a new project is detected immediately.
180
+ export async function discoverAllRunsParentDirs() {
181
+ const config = await getConfig();
182
+ const allDirs = [];
183
+ for (const source of config.sources) {
184
+ if (source.depth === 0) {
185
+ // Direct runs path — watch the source path itself
186
+ try {
187
+ await fs.access(source.path);
188
+ allDirs.push(source.path);
189
+ }
190
+ catch (err) {
191
+ console.warn(`[config] Watch source path not accessible ${source.path}:`, err);
192
+ }
193
+ }
194
+ else {
195
+ const runsDirs = await discoverRunsInSource(source);
196
+ allDirs.push(...runsDirs);
197
+ }
198
+ }
199
+ return allDirs;
200
+ }
201
+ //# sourceMappingURL=source-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-discovery.js","sourceRoot":"","sources":["../../../src/kanban/lib/source-discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export declare function formatDuration(ms: number | undefined | null): string;
2
+ export declare function formatTimestamp(iso: string | undefined): string;
3
+ export declare function formatRelativeTime(iso: string | undefined): string;
4
+ export declare function truncateId(id: string, len?: number): string;
5
+ export declare function getStatusColor(status: string): string;
6
+ export declare function getStatusBg(status: string): string;
7
+ export declare function formatShortId(id: string, chars?: number): string;
8
+ export declare function friendlyProcessName(processId: string): string;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/kanban/lib/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAYpE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAa/D;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAalE;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,GAAE,MAAW,GAAG,MAAM,CAI/D;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAkBrD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAkBlD;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,MAAM,CAInE;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAM7D"}
@@ -0,0 +1,116 @@
1
+ export function formatDuration(ms) {
2
+ if (ms == null || ms < 0)
3
+ return "\u2014";
4
+ if (ms === 0)
5
+ return "<1s";
6
+ if (ms < 1000)
7
+ return `${ms}ms`;
8
+ const seconds = Math.floor(ms / 1000);
9
+ if (seconds < 60)
10
+ return `${seconds}s`;
11
+ const minutes = Math.floor(seconds / 60);
12
+ const remainingSeconds = seconds % 60;
13
+ if (minutes < 60)
14
+ return `${minutes}m ${remainingSeconds}s`;
15
+ const hours = Math.floor(minutes / 60);
16
+ const remainingMinutes = minutes % 60;
17
+ return `${hours}h ${remainingMinutes}m`;
18
+ }
19
+ export function formatTimestamp(iso) {
20
+ if (!iso)
21
+ return "\u2014";
22
+ try {
23
+ const d = new Date(iso);
24
+ return d.toLocaleTimeString("en-US", {
25
+ hour12: false,
26
+ hour: "2-digit",
27
+ minute: "2-digit",
28
+ second: "2-digit",
29
+ });
30
+ }
31
+ catch {
32
+ return "\u2014";
33
+ }
34
+ }
35
+ export function formatRelativeTime(iso) {
36
+ if (!iso)
37
+ return "";
38
+ try {
39
+ const diff = Date.now() - new Date(iso).getTime();
40
+ if (diff < 0)
41
+ return "just now";
42
+ if (diff < 5000)
43
+ return "just now";
44
+ if (diff < 60000)
45
+ return `${Math.floor(diff / 1000)}s ago`;
46
+ if (diff < 3600000)
47
+ return `${Math.floor(diff / 60000)}m ago`;
48
+ if (diff < 86400000)
49
+ return `${Math.floor(diff / 3600000)}h ago`;
50
+ return `${Math.floor(diff / 86400000)}d ago`;
51
+ }
52
+ catch {
53
+ return "";
54
+ }
55
+ }
56
+ export function truncateId(id, len = 12) {
57
+ if (!id)
58
+ return "\u2014";
59
+ if (id.length <= len)
60
+ return id;
61
+ return id.slice(0, len) + "...";
62
+ }
63
+ export function getStatusColor(status) {
64
+ switch (status) {
65
+ case "completed":
66
+ case "resolved":
67
+ case "ok":
68
+ return "text-success";
69
+ case "failed":
70
+ case "error":
71
+ return "text-error";
72
+ case "waiting":
73
+ case "pending":
74
+ return "text-pending";
75
+ case "running":
76
+ case "requested":
77
+ return "text-info";
78
+ default:
79
+ return "text-foreground-muted";
80
+ }
81
+ }
82
+ export function getStatusBg(status) {
83
+ switch (status) {
84
+ case "completed":
85
+ case "resolved":
86
+ case "ok":
87
+ return "bg-success-muted";
88
+ case "failed":
89
+ case "error":
90
+ return "bg-error-muted";
91
+ case "waiting":
92
+ case "pending":
93
+ return "bg-pending-muted";
94
+ case "running":
95
+ case "requested":
96
+ return "bg-info-muted";
97
+ default:
98
+ return "bg-muted";
99
+ }
100
+ }
101
+ export function formatShortId(id, chars = 4) {
102
+ if (!id)
103
+ return '—';
104
+ if (id.length <= chars)
105
+ return id;
106
+ return '...' + id.slice(-chars);
107
+ }
108
+ export function friendlyProcessName(processId) {
109
+ if (!processId)
110
+ return '';
111
+ return processId
112
+ .split(/[-/]/)
113
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
114
+ .join(' ');
115
+ }
116
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/kanban/lib/utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { EventEmitter } from "events";
2
+ export declare const watcherEvents: EventEmitter<[never]>;
3
+ export type WatcherEventType = "run-changed" | "new-run" | "error";
4
+ export interface WatcherEvent {
5
+ type: WatcherEventType;
6
+ runDir: string;
7
+ error?: Error;
8
+ }
9
+ export declare function initWatcher(): Promise<() => void>;
10
+ export declare function getWatcherStats(): {
11
+ activeWatchers: number;
12
+ watchedPaths: string[];
13
+ pendingDebounces: number;
14
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../../src/kanban/lib/watcher.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAUtC,eAAO,MAAM,aAAa,uBAAqB,CAAC;AAGhD,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG,SAAS,GAAG,OAAO,CAAC;AAEnE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,gBAAgB,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AA0LD,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,CA8CvD;AAGD,wBAAgB,eAAe;;;;EAO9B"}
@@ -0,0 +1,221 @@
1
+ import { watch } from "fs";
2
+ import { promises as fs } from "fs";
3
+ import path from "path";
4
+ import { EventEmitter } from "events";
5
+ import { discoverAllRunDirs, invalidateDiscoveryCache, discoverAllRunsParentDirs } from "./source-discovery.js";
6
+ import { invalidateRun, requestDiscovery } from "./run-cache.js";
7
+ import { getGlobal } from "./global-registry.js";
8
+ // Persist event emitter across HMR reloads via typed global registry
9
+ function getWatcherEvents() {
10
+ return getGlobal('__kanban_watcher_events__', () => new EventEmitter());
11
+ }
12
+ export const watcherEvents = getWatcherEvents();
13
+ function getWatcherState() {
14
+ return getGlobal('__kanban_watchers__', () => ({
15
+ activeWatchers: new Map(),
16
+ debounceTimers: new Map(),
17
+ rescanTimer: null,
18
+ }));
19
+ }
20
+ // WSL-optimized constants
21
+ const DEBOUNCE_MS = 500; // 500ms debounce (WSL cross-FS needs more)
22
+ const RESCAN_INTERVAL_MS = 30000; // 30s — reduced from 120s to detect new project directories faster
23
+ function debounceChange(runDir, callback) {
24
+ const state = getWatcherState();
25
+ const existing = state.debounceTimers.get(runDir);
26
+ if (existing) {
27
+ clearTimeout(existing);
28
+ }
29
+ const timer = setTimeout(() => {
30
+ state.debounceTimers.delete(runDir);
31
+ callback();
32
+ }, DEBOUNCE_MS);
33
+ state.debounceTimers.set(runDir, timer);
34
+ }
35
+ function handleJournalChange(journalDir) {
36
+ const runDir = path.dirname(journalDir);
37
+ debounceChange(runDir, () => {
38
+ invalidateRun(runDir);
39
+ requestDiscovery(); // Ensure discoverAndCacheAll() re-populates the entry
40
+ watcherEvents.emit("change", {
41
+ type: "run-changed",
42
+ runDir,
43
+ });
44
+ });
45
+ }
46
+ function handleTasksChange(tasksDir) {
47
+ const runDir = path.dirname(tasksDir);
48
+ debounceChange(runDir, () => {
49
+ invalidateRun(runDir);
50
+ requestDiscovery(); // Ensure discoverAndCacheAll() re-populates the entry
51
+ watcherEvents.emit("change", {
52
+ type: "run-changed",
53
+ runDir,
54
+ });
55
+ });
56
+ }
57
+ function handleRunsParentChange(runsDir) {
58
+ debounceChange(runsDir, () => {
59
+ // Invalidate caches so new runs are picked up on next request
60
+ invalidateDiscoveryCache();
61
+ requestDiscovery();
62
+ watcherEvents.emit("change", {
63
+ type: "new-run",
64
+ runDir: runsDir,
65
+ });
66
+ });
67
+ }
68
+ function watchDirectory(dirPath, onChange) {
69
+ try {
70
+ // Use non-recursive watch (WSL doesn't support recursive)
71
+ const watcher = watch(dirPath, { recursive: false }, (eventType, filename) => {
72
+ if (filename) {
73
+ onChange(dirPath);
74
+ }
75
+ });
76
+ watcher.on("error", (err) => {
77
+ console.error(`Watch error for ${dirPath}:`, err);
78
+ watcherEvents.emit("change", {
79
+ type: "error",
80
+ runDir: dirPath,
81
+ error: err,
82
+ });
83
+ });
84
+ return watcher;
85
+ }
86
+ catch (err) {
87
+ console.error(`Failed to watch ${dirPath}:`, err);
88
+ return null;
89
+ }
90
+ }
91
+ async function setupWatchers() {
92
+ const state = getWatcherState();
93
+ const discovered = await discoverAllRunDirs();
94
+ const runsParentDirs = new Set();
95
+ // Build the set of directories we need to watch
96
+ const neededDirs = new Set();
97
+ for (const { runDir } of discovered) {
98
+ const journalDir = path.join(runDir, "journal");
99
+ try {
100
+ await fs.access(journalDir);
101
+ neededDirs.add(journalDir);
102
+ }
103
+ catch {
104
+ // Journal dir doesn't exist yet — skip for now
105
+ }
106
+ const tasksDir = path.join(runDir, "tasks");
107
+ try {
108
+ await fs.access(tasksDir);
109
+ neededDirs.add(tasksDir);
110
+ }
111
+ catch {
112
+ // Tasks dir doesn't exist yet — skip for now
113
+ }
114
+ const runsDir = path.dirname(runDir);
115
+ runsParentDirs.add(runsDir);
116
+ }
117
+ // Also discover ALL .a5c/runs/ directories (including empty ones)
118
+ // so we detect the very first run in a new project immediately
119
+ try {
120
+ const allRunsParentDirs = await discoverAllRunsParentDirs();
121
+ for (const dir of allRunsParentDirs) {
122
+ runsParentDirs.add(dir);
123
+ }
124
+ }
125
+ catch {
126
+ // Non-critical — fall back to watching only populated runs dirs
127
+ }
128
+ for (const runsDir of runsParentDirs) {
129
+ try {
130
+ await fs.access(runsDir);
131
+ neededDirs.add(runsDir);
132
+ }
133
+ catch {
134
+ // Runs dir doesn't exist
135
+ }
136
+ }
137
+ // Incremental update: close watchers for directories no longer needed
138
+ for (const [dirPath, watcher] of state.activeWatchers.entries()) {
139
+ if (!neededDirs.has(dirPath)) {
140
+ watcher.close();
141
+ state.activeWatchers.delete(dirPath);
142
+ }
143
+ }
144
+ // Only create new watchers for newly discovered directories
145
+ for (const dirPath of neededDirs) {
146
+ if (!state.activeWatchers.has(dirPath)) {
147
+ const baseName = path.basename(dirPath);
148
+ const isJournalDir = baseName === "journal";
149
+ const isTasksDir = baseName === "tasks";
150
+ const onChange = isJournalDir
151
+ ? handleJournalChange
152
+ : isTasksDir
153
+ ? handleTasksChange
154
+ : handleRunsParentChange;
155
+ const watcher = watchDirectory(dirPath, onChange);
156
+ if (watcher) {
157
+ state.activeWatchers.set(dirPath, watcher);
158
+ }
159
+ }
160
+ }
161
+ console.log(`Watching ${state.activeWatchers.size} directories`);
162
+ }
163
+ async function periodicRescan() {
164
+ try {
165
+ // Re-discover and update watchers incrementally
166
+ await setupWatchers();
167
+ }
168
+ catch (err) {
169
+ console.error("Periodic rescan failed:", err);
170
+ }
171
+ }
172
+ export async function initWatcher() {
173
+ const state = getWatcherState();
174
+ // If watchers already exist from a previous HMR cycle, skip full re-init
175
+ if (state.activeWatchers.size > 0) {
176
+ console.log(`Reusing ${state.activeWatchers.size} existing watchers (HMR-safe)`);
177
+ // Still do an incremental rescan to pick up any new directories
178
+ await setupWatchers();
179
+ }
180
+ else {
181
+ console.log("Initializing filesystem watcher...");
182
+ await setupWatchers();
183
+ }
184
+ // Clear any existing rescan timer before setting a new one
185
+ if (state.rescanTimer) {
186
+ clearInterval(state.rescanTimer);
187
+ }
188
+ // Schedule periodic rescans
189
+ state.rescanTimer = setInterval(periodicRescan, RESCAN_INTERVAL_MS);
190
+ // Return cleanup function
191
+ return () => {
192
+ console.log("Cleaning up filesystem watcher...");
193
+ // Clear rescan timer
194
+ if (state.rescanTimer) {
195
+ clearInterval(state.rescanTimer);
196
+ state.rescanTimer = null;
197
+ }
198
+ // Clear debounce timers
199
+ for (const timer of state.debounceTimers.values()) {
200
+ clearTimeout(timer);
201
+ }
202
+ state.debounceTimers.clear();
203
+ // Close all watchers
204
+ for (const watcher of state.activeWatchers.values()) {
205
+ watcher.close();
206
+ }
207
+ state.activeWatchers.clear();
208
+ // Remove all event listeners
209
+ watcherEvents.removeAllListeners();
210
+ };
211
+ }
212
+ // Get watcher stats for debugging
213
+ export function getWatcherStats() {
214
+ const state = getWatcherState();
215
+ return {
216
+ activeWatchers: state.activeWatchers.size,
217
+ watchedPaths: Array.from(state.activeWatchers.keys()),
218
+ pendingDebounces: state.debounceTimers.size,
219
+ };
220
+ }
221
+ //# sourceMappingURL=watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../../src/kanban/lib/watcher.ts"],"names":[],"mappings":"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"}