@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.
- package/README.md +20 -0
- package/dist/auth/bootstrap.d.ts +89 -0
- package/dist/auth/bootstrap.d.ts.map +1 -0
- package/dist/auth/bootstrap.js +222 -0
- package/dist/auth/bootstrap.js.map +1 -0
- package/dist/auth/hashing.d.ts +4 -0
- package/dist/auth/hashing.d.ts.map +1 -0
- package/dist/auth/hashing.js +27 -0
- package/dist/auth/hashing.js.map +1 -0
- package/dist/auth/middleware.d.ts +3 -0
- package/dist/auth/middleware.d.ts.map +1 -0
- package/dist/auth/middleware.js +17 -0
- package/dist/auth/middleware.js.map +1 -0
- package/dist/auth/tokens.d.ts +45 -0
- package/dist/auth/tokens.d.ts.map +1 -0
- package/dist/auth/tokens.js +186 -0
- package/dist/auth/tokens.js.map +1 -0
- package/dist/builtin-adapters.d.ts +17 -0
- package/dist/builtin-adapters.d.ts.map +1 -0
- package/dist/builtin-adapters.js +119 -0
- package/dist/builtin-adapters.js.map +1 -0
- package/dist/config.d.ts +37 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +97 -0
- package/dist/config.js.map +1 -0
- package/dist/fanout/client-conn.d.ts +20 -0
- package/dist/fanout/client-conn.d.ts.map +1 -0
- package/dist/fanout/client-conn.js +53 -0
- package/dist/fanout/client-conn.js.map +1 -0
- package/dist/fanout/subscriber.d.ts +12 -0
- package/dist/fanout/subscriber.d.ts.map +1 -0
- package/dist/fanout/subscriber.js +40 -0
- package/dist/fanout/subscriber.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -0
- package/dist/kanban/lib/config-loader.d.ts +29 -0
- package/dist/kanban/lib/config-loader.d.ts.map +1 -0
- package/dist/kanban/lib/config-loader.js +166 -0
- package/dist/kanban/lib/config-loader.js.map +1 -0
- package/dist/kanban/lib/config.d.ts +3 -0
- package/dist/kanban/lib/config.d.ts.map +1 -0
- package/dist/kanban/lib/config.js +6 -0
- package/dist/kanban/lib/config.js.map +1 -0
- package/dist/kanban/lib/create-global-registry.d.ts +28 -0
- package/dist/kanban/lib/create-global-registry.d.ts.map +1 -0
- package/dist/kanban/lib/create-global-registry.js +53 -0
- package/dist/kanban/lib/create-global-registry.js.map +1 -0
- package/dist/kanban/lib/dispatch-context-audit.d.ts +12 -0
- package/dist/kanban/lib/dispatch-context-audit.d.ts.map +1 -0
- package/dist/kanban/lib/dispatch-context-audit.js +44 -0
- package/dist/kanban/lib/dispatch-context-audit.js.map +1 -0
- package/dist/kanban/lib/error-handler.d.ts +28 -0
- package/dist/kanban/lib/error-handler.d.ts.map +1 -0
- package/dist/kanban/lib/error-handler.js +61 -0
- package/dist/kanban/lib/error-handler.js.map +1 -0
- package/dist/kanban/lib/global-registry.d.ts +49 -0
- package/dist/kanban/lib/global-registry.d.ts.map +1 -0
- package/dist/kanban/lib/global-registry.js +18 -0
- package/dist/kanban/lib/global-registry.js.map +1 -0
- package/dist/kanban/lib/parser.d.ts +36 -0
- package/dist/kanban/lib/parser.d.ts.map +1 -0
- package/dist/kanban/lib/parser.js +585 -0
- package/dist/kanban/lib/parser.js.map +1 -0
- package/dist/kanban/lib/path-resolver.d.ts +2 -0
- package/dist/kanban/lib/path-resolver.d.ts.map +1 -0
- package/dist/kanban/lib/path-resolver.js +16 -0
- package/dist/kanban/lib/path-resolver.js.map +1 -0
- package/dist/kanban/lib/review-service.d.ts +63 -0
- package/dist/kanban/lib/review-service.d.ts.map +1 -0
- package/dist/kanban/lib/review-service.js +571 -0
- package/dist/kanban/lib/review-service.js.map +1 -0
- package/dist/kanban/lib/run-cache.d.ts +36 -0
- package/dist/kanban/lib/run-cache.d.ts.map +1 -0
- package/dist/kanban/lib/run-cache.js +313 -0
- package/dist/kanban/lib/run-cache.js.map +1 -0
- package/dist/kanban/lib/server-init.d.ts +26 -0
- package/dist/kanban/lib/server-init.d.ts.map +1 -0
- package/dist/kanban/lib/server-init.js +179 -0
- package/dist/kanban/lib/server-init.js.map +1 -0
- package/dist/kanban/lib/services/automation-rule-service.d.ts +97 -0
- package/dist/kanban/lib/services/automation-rule-service.d.ts.map +1 -0
- package/dist/kanban/lib/services/automation-rule-service.js +806 -0
- package/dist/kanban/lib/services/automation-rule-service.js.map +1 -0
- package/dist/kanban/lib/services/automation-webhook-service.d.ts +44 -0
- package/dist/kanban/lib/services/automation-webhook-service.d.ts.map +1 -0
- package/dist/kanban/lib/services/automation-webhook-service.js +405 -0
- package/dist/kanban/lib/services/automation-webhook-service.js.map +1 -0
- package/dist/kanban/lib/services/backlog-query-service.d.ts +130 -0
- package/dist/kanban/lib/services/backlog-query-service.d.ts.map +1 -0
- package/dist/kanban/lib/services/backlog-query-service.js +1972 -0
- package/dist/kanban/lib/services/backlog-query-service.js.map +1 -0
- package/dist/kanban/lib/services/dispatch-context-label-service.d.ts +39 -0
- package/dist/kanban/lib/services/dispatch-context-label-service.d.ts.map +1 -0
- package/dist/kanban/lib/services/dispatch-context-label-service.js +160 -0
- package/dist/kanban/lib/services/dispatch-context-label-service.js.map +1 -0
- package/dist/kanban/lib/services/kanban-storage.d.ts +36 -0
- package/dist/kanban/lib/services/kanban-storage.d.ts.map +1 -0
- package/dist/kanban/lib/services/kanban-storage.js +26 -0
- package/dist/kanban/lib/services/kanban-storage.js.map +1 -0
- package/dist/kanban/lib/services/run-query-service.d.ts +79 -0
- package/dist/kanban/lib/services/run-query-service.d.ts.map +1 -0
- package/dist/kanban/lib/services/run-query-service.js +202 -0
- package/dist/kanban/lib/services/run-query-service.js.map +1 -0
- package/dist/kanban/lib/services/task-tag-service.d.ts +39 -0
- package/dist/kanban/lib/services/task-tag-service.d.ts.map +1 -0
- package/dist/kanban/lib/services/task-tag-service.js +145 -0
- package/dist/kanban/lib/services/task-tag-service.js.map +1 -0
- package/dist/kanban/lib/settings-section-storage.d.ts +13 -0
- package/dist/kanban/lib/settings-section-storage.d.ts.map +1 -0
- package/dist/kanban/lib/settings-section-storage.js +38 -0
- package/dist/kanban/lib/settings-section-storage.js.map +1 -0
- package/dist/kanban/lib/source-discovery.d.ts +10 -0
- package/dist/kanban/lib/source-discovery.d.ts.map +1 -0
- package/dist/kanban/lib/source-discovery.js +201 -0
- package/dist/kanban/lib/source-discovery.js.map +1 -0
- package/dist/kanban/lib/utils.d.ts +8 -0
- package/dist/kanban/lib/utils.d.ts.map +1 -0
- package/dist/kanban/lib/utils.js +116 -0
- package/dist/kanban/lib/utils.js.map +1 -0
- package/dist/kanban/lib/watcher.d.ts +14 -0
- package/dist/kanban/lib/watcher.d.ts.map +1 -0
- package/dist/kanban/lib/watcher.js +221 -0
- package/dist/kanban/lib/watcher.js.map +1 -0
- package/dist/kanban/lib/workspace-lifecycle.d.ts +68 -0
- package/dist/kanban/lib/workspace-lifecycle.d.ts.map +1 -0
- package/dist/kanban/lib/workspace-lifecycle.js +1085 -0
- package/dist/kanban/lib/workspace-lifecycle.js.map +1 -0
- package/dist/kanban/routes.d.ts +2 -0
- package/dist/kanban/routes.d.ts.map +1 -0
- package/dist/kanban/routes.js +1358 -0
- package/dist/kanban/routes.js.map +1 -0
- package/dist/kanban/types/breakpoint.d.ts +13 -0
- package/dist/kanban/types/breakpoint.d.ts.map +1 -0
- package/dist/kanban/types/breakpoint.js +3 -0
- package/dist/kanban/types/breakpoint.js.map +1 -0
- package/dist/kanban/types/index.d.ts +173 -0
- package/dist/kanban/types/index.d.ts.map +1 -0
- package/dist/kanban/types/index.js +3 -0
- package/dist/kanban/types/index.js.map +1 -0
- package/dist/logging.d.ts +7 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +22 -0
- package/dist/logging.js.map +1 -0
- package/dist/notifications/types.d.ts +18 -0
- package/dist/notifications/types.d.ts.map +1 -0
- package/dist/notifications/types.js +2 -0
- package/dist/notifications/types.js.map +1 -0
- package/dist/notifications/webhook-out.d.ts +3 -0
- package/dist/notifications/webhook-out.d.ts.map +1 -0
- package/dist/notifications/webhook-out.js +55 -0
- package/dist/notifications/webhook-out.js.map +1 -0
- package/dist/pairing/short-code.d.ts +20 -0
- package/dist/pairing/short-code.d.ts.map +1 -0
- package/dist/pairing/short-code.js +50 -0
- package/dist/pairing/short-code.js.map +1 -0
- package/dist/protocol/errors.d.ts +10 -0
- package/dist/protocol/errors.d.ts.map +1 -0
- package/dist/protocol/errors.js +15 -0
- package/dist/protocol/errors.js.map +1 -0
- package/dist/protocol/frames.d.ts +107 -0
- package/dist/protocol/frames.d.ts.map +1 -0
- package/dist/protocol/frames.js +146 -0
- package/dist/protocol/frames.js.map +1 -0
- package/dist/protocol/v1.d.ts +111 -0
- package/dist/protocol/v1.d.ts.map +1 -0
- package/dist/protocol/v1.js +2 -0
- package/dist/protocol/v1.js.map +1 -0
- package/dist/runs/event-log-index.d.ts +29 -0
- package/dist/runs/event-log-index.d.ts.map +1 -0
- package/dist/runs/event-log-index.js +210 -0
- package/dist/runs/event-log-index.js.map +1 -0
- package/dist/runs/event-log.d.ts +25 -0
- package/dist/runs/event-log.d.ts.map +1 -0
- package/dist/runs/event-log.js +104 -0
- package/dist/runs/event-log.js.map +1 -0
- package/dist/runs/hook-broker.d.ts +18 -0
- package/dist/runs/hook-broker.d.ts.map +1 -0
- package/dist/runs/hook-broker.js +110 -0
- package/dist/runs/hook-broker.js.map +1 -0
- package/dist/runs/manager.d.ts +57 -0
- package/dist/runs/manager.d.ts.map +1 -0
- package/dist/runs/manager.js +757 -0
- package/dist/runs/manager.js.map +1 -0
- package/dist/runs/session-runtime.d.ts +8 -0
- package/dist/runs/session-runtime.d.ts.map +1 -0
- package/dist/runs/session-runtime.js +291 -0
- package/dist/runs/session-runtime.js.map +1 -0
- package/dist/runs/types.d.ts +55 -0
- package/dist/runs/types.d.ts.map +1 -0
- package/dist/runs/types.js +2 -0
- package/dist/runs/types.js.map +1 -0
- package/dist/server.d.ts +15 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +702 -0
- package/dist/server.js.map +1 -0
- package/dist/static/webui-server.d.ts +2 -0
- package/dist/static/webui-server.d.ts.map +1 -0
- package/dist/static/webui-server.js +97 -0
- package/dist/static/webui-server.js.map +1 -0
- 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":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,SAAS,EAAoB,MAAM,oBAAoB,CAAC;AASlF,sDAAsD;AACtD,KAAK,UAAU,oBAAoB,CAAC,MAAmB;IACrD,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,UAAU,IAAI,CAAC,GAAW,EAAE,YAAoB;QACnD,IAAI,CAAC;YACH,iFAAiF;YACjF,IAAI,MAAM,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;gBACvB,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC/D,OAAO,OAAO;qBACX,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;qBAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YACxC,CAAC;YAED,qCAAqC;YACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YAChD,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACrC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;oBACvB,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACzB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,iEAAiE;YACnE,CAAC;YAED,8CAA8C;YAC9C,IAAI,YAAY,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;gBAChC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC/D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;oBAC5B,IACE,KAAK,CAAC,WAAW,EAAE;wBACnB,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;wBAC3B,KAAK,CAAC,IAAI,KAAK,cAAc,EAC7B,CAAC;wBACD,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,YAAY,GAAG,CAAC,CAAC,CAAC;oBAC3D,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,IAAI,CAAC,kCAAkC,GAAG,WAAW,YAAY,IAAI,EAAE,GAAG,CAAC,CAAC;YACtF,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;QACvB,qDAAqD;QACrD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YACvE,OAAO,OAAO;iBACX,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;iBAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,8CAA8C,MAAM,CAAC,IAAI,GAAG,EAAE,GAAG,CAAC,CAAC;YAChF,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC3B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,8CAA8C;AAC9C,SAAS,kBAAkB,CAAC,OAAe;IACzC,6CAA6C;IAC7C,kCAAkC;IAClC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO;IAC7C,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc;IACxD,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC/C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;AACtC,CAAC;AAED,gEAAgE;AAChE,IAAI,cAAc,GAAoB,EAAE,CAAC;AACzC,IAAI,kBAAkB,GAAG,CAAC,CAAC;AAC3B,MAAM,mBAAmB,GAAG,KAAK,CAAC,CAAC,0CAA0C;AAE7E,iFAAiF;AACjF,MAAM,UAAU,wBAAwB;IACtC,cAAc,GAAG,EAAE,CAAC;IACpB,kBAAkB,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,6CAA6C;AAC7C,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,GAAG,kBAAkB,GAAG,mBAAmB,EAAE,CAAC;QAChF,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;IACjC,MAAM,OAAO,GAAoB,EAAE,CAAC;IAEpC,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACpC,IAAI,MAAM,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;YACvB,0DAA0D;YAC1D,iFAAiF;YACjF,MAAM,mBAAmB,GAAG,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACvE,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;oBAC5B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;wBACxB,2EAA2E;wBAC3E,IAAI,WAAW,GAAG,mBAAmB,CAAC;wBACtC,IAAI,CAAC;4BACH,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;4BACnE,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;4BACxD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;4BACjC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gCACrB,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;4BACjC,CAAC;wBACH,CAAC;wBAAC,OAAO,GAAG,EAAE,CAAC;4BACb,kFAAkF;4BAClF,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;gCAC1B,OAAO,CAAC,IAAI,CAAC,uCAAuC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,iCAAiC,EAAE,GAAG,CAAC,CAAC;4BAChI,CAAC;wBACH,CAAC;wBACD,OAAO,CAAC,IAAI,CAAC;4BACX,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC;4BAC1C,MAAM;4BACN,WAAW;4BACX,WAAW,EAAE,MAAM,CAAC,IAAI;yBACzB,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,4CAA4C,MAAM,CAAC,IAAI,GAAG,EAAE,GAAG,CAAC,CAAC;YAChF,CAAC;QACH,CAAC;aAAM,CAAC;YACN,+CAA+C;YAC/C,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,MAAM,CAAC,CAAC;YACpD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAC/B,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;gBACjE,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;oBACnE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;wBAC5B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;4BACxB,OAAO,CAAC,IAAI,CAAC;gCACX,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC;gCACtC,MAAM;gCACN,WAAW;gCACX,WAAW;6BACZ,CAAC,CAAC;wBACL,CAAC;oBACH,CAAC;gBACH,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,IAAI,CAAC,uCAAuC,OAAO,GAAG,EAAE,GAAG,CAAC,CAAC;gBACvE,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,0EAA0E;IAC1E,0EAA0E;IAC1E,0EAA0E;IAC1E,wBAAwB;IACxB,MAAM,UAAU,GAAG,IAAI,GAAG,EAAyB,CAAC;IACpD,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,mEAAmE;YACnE,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC;YACxC,MAAM,kBAAkB,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;YACjH,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBACxB,MAAM,mBAAmB,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;gBAC7G,IAAI,mBAAmB,EAAE,CAAC;oBACxB,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBAC7B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/C,cAAc,GAAG,MAAM,CAAC;IACxB,kBAAkB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAChC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,qEAAqE;AACrE,iFAAiF;AACjF,uEAAuE;AACvE,MAAM,CAAC,KAAK,UAAU,yBAAyB;IAC7C,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;IACjC,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACpC,IAAI,MAAM,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;YACvB,kDAAkD;YAClD,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC7B,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,6CAA6C,MAAM,CAAC,IAAI,GAAG,EAAE,GAAG,CAAC,CAAC;YACjF,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,MAAM,CAAC,CAAC;YACpD,OAAO,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -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":"AAAA,MAAM,UAAU,cAAc,CAAC,EAA6B;IAC1D,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC1C,IAAI,EAAE,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3B,IAAI,EAAE,GAAG,IAAI;QAAE,OAAO,GAAG,EAAE,IAAI,CAAC;IAChC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACtC,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,GAAG,OAAO,GAAG,CAAC;IACvC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACzC,MAAM,gBAAgB,GAAG,OAAO,GAAG,EAAE,CAAC;IACtC,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,GAAG,OAAO,KAAK,gBAAgB,GAAG,CAAC;IAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACvC,MAAM,gBAAgB,GAAG,OAAO,GAAG,EAAE,CAAC;IACtC,OAAO,GAAG,KAAK,KAAK,gBAAgB,GAAG,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAuB;IACrD,IAAI,CAAC,GAAG;QAAE,OAAO,QAAQ,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QACxB,OAAO,CAAC,CAAC,kBAAkB,CAAC,OAAO,EAAE;YACnC,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,SAAS;SAClB,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAuB;IACxD,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;QAClD,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,UAAU,CAAC;QAChC,IAAI,IAAI,GAAG,IAAI;YAAE,OAAO,UAAU,CAAC;QACnC,IAAI,IAAI,GAAG,KAAK;YAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC;QAC3D,IAAI,IAAI,GAAG,OAAO;YAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC;QAC9D,IAAI,IAAI,GAAG,QAAQ;YAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;QACjE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAU,EAAE,MAAc,EAAE;IACrD,IAAI,CAAC,EAAE;QAAE,OAAO,QAAQ,CAAC;IACzB,IAAI,EAAE,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,EAAE,CAAC;IAChC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,WAAW,CAAC;QACjB,KAAK,UAAU,CAAC;QAChB,KAAK,IAAI;YACP,OAAO,cAAc,CAAC;QACxB,KAAK,QAAQ,CAAC;QACd,KAAK,OAAO;YACV,OAAO,YAAY,CAAC;QACtB,KAAK,SAAS,CAAC;QACf,KAAK,SAAS;YACZ,OAAO,cAAc,CAAC;QACxB,KAAK,SAAS,CAAC;QACf,KAAK,WAAW;YACd,OAAO,WAAW,CAAC;QACrB;YACE,OAAO,uBAAuB,CAAC;IACnC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,WAAW,CAAC;QACjB,KAAK,UAAU,CAAC;QAChB,KAAK,IAAI;YACP,OAAO,kBAAkB,CAAC;QAC5B,KAAK,QAAQ,CAAC;QACd,KAAK,OAAO;YACV,OAAO,gBAAgB,CAAC;QAC1B,KAAK,SAAS,CAAC;QACf,KAAK,SAAS;YACZ,OAAO,kBAAkB,CAAC;QAC5B,KAAK,SAAS,CAAC;QACf,KAAK,WAAW;YACd,OAAO,eAAe,CAAC;QACzB;YACE,OAAO,UAAU,CAAC;IACtB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAAU,EAAE,QAAgB,CAAC;IACzD,IAAI,CAAC,EAAE;QAAE,OAAO,GAAG,CAAC;IACpB,IAAI,EAAE,CAAC,MAAM,IAAI,KAAK;QAAE,OAAO,EAAE,CAAC;IAClC,OAAO,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,SAAiB;IACnD,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,CAAC;IAC1B,OAAO,SAAS;SACb,KAAK,CAAC,MAAM,CAAC;SACb,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;SACvE,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -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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"}
|