opencode-swarm 7.0.2 → 7.0.3
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/dist/cli/index.js +890 -548
- package/dist/config/index.d.ts +1 -1
- package/dist/config/loader.d.ts +8 -0
- package/dist/hooks/__tests__/repo-graph-builder.test.d.ts +12 -0
- package/dist/hooks/repo-graph-builder.d.ts +13 -1
- package/dist/index.js +1828 -1331
- package/dist/tools/__tests__/repo-graph-walk.test.d.ts +16 -0
- package/dist/tools/repo-graph.d.ts +16 -2
- package/dist/utils/__tests__/bun-compat.test.d.ts +11 -0
- package/dist/utils/__tests__/timeout.test.d.ts +12 -0
- package/dist/utils/bun-compat.d.ts +106 -0
- package/dist/utils/timeout.d.ts +23 -0
- package/package.json +3 -2
package/dist/cli/index.js
CHANGED
|
@@ -99,8 +99,335 @@ var init_utils = __esm(() => {
|
|
|
99
99
|
init_logger();
|
|
100
100
|
});
|
|
101
101
|
|
|
102
|
-
// src/
|
|
102
|
+
// src/utils/bun-compat.ts
|
|
103
|
+
import {
|
|
104
|
+
spawn as nodeSpawn,
|
|
105
|
+
spawnSync as nodeSpawnSync
|
|
106
|
+
} from "child_process";
|
|
107
|
+
import * as fsSync from "fs";
|
|
108
|
+
import * as fsPromises from "fs/promises";
|
|
103
109
|
import * as path from "path";
|
|
110
|
+
function getBun() {
|
|
111
|
+
const g = globalThis;
|
|
112
|
+
return g.Bun;
|
|
113
|
+
}
|
|
114
|
+
function bunFile(filePath) {
|
|
115
|
+
const bun = getBun();
|
|
116
|
+
if (bun?.file) {
|
|
117
|
+
return bun.file(filePath);
|
|
118
|
+
}
|
|
119
|
+
let cachedSize;
|
|
120
|
+
return {
|
|
121
|
+
async text() {
|
|
122
|
+
return fsPromises.readFile(filePath, "utf-8");
|
|
123
|
+
},
|
|
124
|
+
async arrayBuffer() {
|
|
125
|
+
const buf = await fsPromises.readFile(filePath);
|
|
126
|
+
const ab = new ArrayBuffer(buf.byteLength);
|
|
127
|
+
new Uint8Array(ab).set(buf);
|
|
128
|
+
return ab;
|
|
129
|
+
},
|
|
130
|
+
async exists() {
|
|
131
|
+
try {
|
|
132
|
+
await fsPromises.access(filePath, fsSync.constants.F_OK);
|
|
133
|
+
return true;
|
|
134
|
+
} catch {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
get size() {
|
|
139
|
+
if (cachedSize !== undefined)
|
|
140
|
+
return cachedSize;
|
|
141
|
+
try {
|
|
142
|
+
cachedSize = fsSync.statSync(filePath).size;
|
|
143
|
+
} catch {
|
|
144
|
+
cachedSize = 0;
|
|
145
|
+
}
|
|
146
|
+
return cachedSize;
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
async function bunWrite(filePath, data) {
|
|
151
|
+
const bun = getBun();
|
|
152
|
+
if (bun?.write) {
|
|
153
|
+
return bun.write(filePath, data);
|
|
154
|
+
}
|
|
155
|
+
const dir = path.dirname(filePath);
|
|
156
|
+
const tempName = `.${path.basename(filePath)}.${process.pid}.${Date.now()}.${tempCounter++}.${Math.random().toString(36).slice(2, 10)}.tmp`;
|
|
157
|
+
const tempPath = path.join(dir, tempName);
|
|
158
|
+
let buffer;
|
|
159
|
+
if (typeof data === "string") {
|
|
160
|
+
buffer = data;
|
|
161
|
+
} else if (data instanceof ArrayBuffer) {
|
|
162
|
+
buffer = new Uint8Array(data);
|
|
163
|
+
} else if (ArrayBuffer.isView(data)) {
|
|
164
|
+
buffer = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
165
|
+
} else {
|
|
166
|
+
buffer = new Uint8Array(0);
|
|
167
|
+
}
|
|
168
|
+
try {
|
|
169
|
+
await fsPromises.mkdir(dir, { recursive: true });
|
|
170
|
+
} catch {}
|
|
171
|
+
await fsPromises.writeFile(tempPath, buffer);
|
|
172
|
+
let lastError;
|
|
173
|
+
for (let attempt = 0;attempt < WINDOWS_RENAME_MAX_RETRIES; attempt++) {
|
|
174
|
+
try {
|
|
175
|
+
await fsPromises.rename(tempPath, filePath);
|
|
176
|
+
lastError = undefined;
|
|
177
|
+
break;
|
|
178
|
+
} catch (err) {
|
|
179
|
+
lastError = err;
|
|
180
|
+
const code = err.code;
|
|
181
|
+
if (code !== "EEXIST" && code !== "EBUSY" && code !== "EPERM") {
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
await new Promise((r) => setTimeout(r, WINDOWS_RENAME_RETRY_DELAY_MS));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (lastError) {
|
|
188
|
+
try {
|
|
189
|
+
await fsPromises.unlink(tempPath);
|
|
190
|
+
} catch {}
|
|
191
|
+
throw lastError;
|
|
192
|
+
}
|
|
193
|
+
const stats = await fsPromises.stat(filePath);
|
|
194
|
+
return stats.size;
|
|
195
|
+
}
|
|
196
|
+
function bunHash(input) {
|
|
197
|
+
const bun = getBun();
|
|
198
|
+
if (bun?.hash) {
|
|
199
|
+
const r = bun.hash(input);
|
|
200
|
+
return typeof r === "bigint" ? r : BigInt(r);
|
|
201
|
+
}
|
|
202
|
+
let bytes;
|
|
203
|
+
if (typeof input === "string") {
|
|
204
|
+
bytes = new TextEncoder().encode(input);
|
|
205
|
+
} else if (input instanceof ArrayBuffer) {
|
|
206
|
+
bytes = new Uint8Array(input);
|
|
207
|
+
} else {
|
|
208
|
+
bytes = new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
|
|
209
|
+
}
|
|
210
|
+
let hash = 5381n;
|
|
211
|
+
for (const b of bytes) {
|
|
212
|
+
hash = hash * 33n + BigInt(b) & 0xffffffffffffffffn;
|
|
213
|
+
}
|
|
214
|
+
return hash;
|
|
215
|
+
}
|
|
216
|
+
function streamFromNode(pipe) {
|
|
217
|
+
const collected = new Promise((resolve) => {
|
|
218
|
+
if (!pipe) {
|
|
219
|
+
resolve(Buffer.alloc(0));
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
const chunks = [];
|
|
223
|
+
pipe.on("data", (chunk) => {
|
|
224
|
+
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
225
|
+
});
|
|
226
|
+
pipe.on("end", () => resolve(Buffer.concat(chunks)));
|
|
227
|
+
pipe.on("error", () => resolve(Buffer.concat(chunks)));
|
|
228
|
+
});
|
|
229
|
+
const toWebReadable = () => {
|
|
230
|
+
if (!pipe) {
|
|
231
|
+
return new ReadableStream({
|
|
232
|
+
start(controller) {
|
|
233
|
+
controller.close();
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
const r = pipe;
|
|
238
|
+
if (typeof r.toWeb === "function") {
|
|
239
|
+
return r.toWeb();
|
|
240
|
+
}
|
|
241
|
+
return new ReadableStream({
|
|
242
|
+
start(controller) {
|
|
243
|
+
pipe.on("data", (chunk) => {
|
|
244
|
+
controller.enqueue(typeof chunk === "string" ? new TextEncoder().encode(chunk) : new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength));
|
|
245
|
+
});
|
|
246
|
+
pipe.on("end", () => controller.close());
|
|
247
|
+
pipe.on("error", (err) => controller.error(err));
|
|
248
|
+
},
|
|
249
|
+
cancel() {
|
|
250
|
+
const destroyable = pipe;
|
|
251
|
+
if (typeof destroyable.destroy === "function") {
|
|
252
|
+
try {
|
|
253
|
+
destroyable.destroy();
|
|
254
|
+
} catch {}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
};
|
|
259
|
+
return {
|
|
260
|
+
async text() {
|
|
261
|
+
return (await collected).toString("utf-8");
|
|
262
|
+
},
|
|
263
|
+
async bytes() {
|
|
264
|
+
const b = await collected;
|
|
265
|
+
return new Uint8Array(b.buffer, b.byteOffset, b.byteLength);
|
|
266
|
+
},
|
|
267
|
+
getReader() {
|
|
268
|
+
return toWebReadable().getReader();
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
function mapStdio(v) {
|
|
273
|
+
return v ?? "pipe";
|
|
274
|
+
}
|
|
275
|
+
function streamFromBun(stream) {
|
|
276
|
+
if (!stream || typeof stream !== "object") {
|
|
277
|
+
const empty = {
|
|
278
|
+
async text() {
|
|
279
|
+
return "";
|
|
280
|
+
},
|
|
281
|
+
async bytes() {
|
|
282
|
+
return new Uint8Array(0);
|
|
283
|
+
},
|
|
284
|
+
getReader() {
|
|
285
|
+
return new ReadableStream({
|
|
286
|
+
start(controller) {
|
|
287
|
+
controller.close();
|
|
288
|
+
}
|
|
289
|
+
}).getReader();
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
return empty;
|
|
293
|
+
}
|
|
294
|
+
const candidate = stream;
|
|
295
|
+
const collect = async () => {
|
|
296
|
+
if (typeof candidate.getReader !== "function") {
|
|
297
|
+
return new Uint8Array(0);
|
|
298
|
+
}
|
|
299
|
+
const reader = candidate.getReader();
|
|
300
|
+
const chunks = [];
|
|
301
|
+
for (;; ) {
|
|
302
|
+
const { done, value } = await reader.read();
|
|
303
|
+
if (done)
|
|
304
|
+
break;
|
|
305
|
+
if (value)
|
|
306
|
+
chunks.push(value);
|
|
307
|
+
}
|
|
308
|
+
const total = chunks.reduce((acc, c) => acc + c.byteLength, 0);
|
|
309
|
+
const out = new Uint8Array(total);
|
|
310
|
+
let off = 0;
|
|
311
|
+
for (const c of chunks) {
|
|
312
|
+
out.set(c, off);
|
|
313
|
+
off += c.byteLength;
|
|
314
|
+
}
|
|
315
|
+
return out;
|
|
316
|
+
};
|
|
317
|
+
const text = typeof candidate.text === "function" ? () => candidate.text() : async () => new TextDecoder().decode(await collect());
|
|
318
|
+
const bytes = typeof candidate.bytes === "function" ? () => candidate.bytes() : collect;
|
|
319
|
+
const getReader = typeof candidate.getReader === "function" ? () => candidate.getReader() : () => new ReadableStream({
|
|
320
|
+
start(controller) {
|
|
321
|
+
controller.close();
|
|
322
|
+
}
|
|
323
|
+
}).getReader();
|
|
324
|
+
return { text, bytes, getReader };
|
|
325
|
+
}
|
|
326
|
+
function bunSpawn(cmd, options) {
|
|
327
|
+
const bun = getBun();
|
|
328
|
+
if (bun?.spawn) {
|
|
329
|
+
const proc2 = bun.spawn(cmd, options);
|
|
330
|
+
return {
|
|
331
|
+
stdout: streamFromBun(proc2.stdout),
|
|
332
|
+
stderr: streamFromBun(proc2.stderr),
|
|
333
|
+
exited: proc2.exited,
|
|
334
|
+
get exitCode() {
|
|
335
|
+
return proc2.exitCode;
|
|
336
|
+
},
|
|
337
|
+
kill(sig) {
|
|
338
|
+
proc2.kill(sig);
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
const [file, ...args] = cmd;
|
|
343
|
+
const proc = nodeSpawn(file, args, {
|
|
344
|
+
cwd: options?.cwd,
|
|
345
|
+
env: options?.env,
|
|
346
|
+
stdio: [
|
|
347
|
+
mapStdio(options?.stdin),
|
|
348
|
+
mapStdio(options?.stdout),
|
|
349
|
+
mapStdio(options?.stderr)
|
|
350
|
+
]
|
|
351
|
+
});
|
|
352
|
+
let timeoutHandle;
|
|
353
|
+
const exited = new Promise((resolve) => {
|
|
354
|
+
proc.on("exit", (code) => resolve(code ?? 0));
|
|
355
|
+
proc.on("error", () => resolve(1));
|
|
356
|
+
if (options?.timeout && options.timeout > 0) {
|
|
357
|
+
timeoutHandle = setTimeout(() => {
|
|
358
|
+
try {
|
|
359
|
+
proc.kill("SIGKILL");
|
|
360
|
+
} catch {}
|
|
361
|
+
}, options.timeout);
|
|
362
|
+
if (typeof timeoutHandle.unref === "function") {
|
|
363
|
+
timeoutHandle.unref();
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}).finally(() => {
|
|
367
|
+
if (timeoutHandle !== undefined)
|
|
368
|
+
clearTimeout(timeoutHandle);
|
|
369
|
+
});
|
|
370
|
+
return {
|
|
371
|
+
stdout: streamFromNode(proc.stdout),
|
|
372
|
+
stderr: streamFromNode(proc.stderr),
|
|
373
|
+
exited,
|
|
374
|
+
get exitCode() {
|
|
375
|
+
return proc.exitCode;
|
|
376
|
+
},
|
|
377
|
+
kill(signal) {
|
|
378
|
+
try {
|
|
379
|
+
proc.kill(signal);
|
|
380
|
+
} catch {}
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
function bunSpawnSync(cmd, options) {
|
|
385
|
+
const bun = getBun();
|
|
386
|
+
if (bun?.spawnSync) {
|
|
387
|
+
const result2 = bun.spawnSync(cmd, options);
|
|
388
|
+
return result2;
|
|
389
|
+
}
|
|
390
|
+
let argv;
|
|
391
|
+
let mergedOptions;
|
|
392
|
+
if (Array.isArray(cmd)) {
|
|
393
|
+
argv = cmd;
|
|
394
|
+
mergedOptions = { ...options ?? {} };
|
|
395
|
+
} else {
|
|
396
|
+
argv = cmd.cmd;
|
|
397
|
+
mergedOptions = {
|
|
398
|
+
cwd: cmd.cwd,
|
|
399
|
+
env: cmd.env,
|
|
400
|
+
stdin: "pipe",
|
|
401
|
+
timeout: cmd.timeout,
|
|
402
|
+
...options ?? {}
|
|
403
|
+
};
|
|
404
|
+
if (cmd.stdin !== undefined) {
|
|
405
|
+
mergedOptions.stdin = cmd.stdin;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
const [file, ...args] = argv;
|
|
409
|
+
const result = nodeSpawnSync(file, args, {
|
|
410
|
+
cwd: mergedOptions.cwd,
|
|
411
|
+
env: mergedOptions.env,
|
|
412
|
+
input: mergedOptions.stdin instanceof Uint8Array || typeof mergedOptions.stdin === "string" ? mergedOptions.stdin : undefined,
|
|
413
|
+
timeout: mergedOptions.timeout,
|
|
414
|
+
windowsHide: true
|
|
415
|
+
});
|
|
416
|
+
const stdout = result.stdout instanceof Buffer ? new Uint8Array(result.stdout.buffer, result.stdout.byteOffset, result.stdout.byteLength) : typeof result.stdout === "string" ? new TextEncoder().encode(result.stdout) : new Uint8Array(0);
|
|
417
|
+
const stderr = result.stderr instanceof Buffer ? new Uint8Array(result.stderr.buffer, result.stderr.byteOffset, result.stderr.byteLength) : typeof result.stderr === "string" ? new TextEncoder().encode(result.stderr) : new Uint8Array(0);
|
|
418
|
+
const exitCode = result.status ?? (result.signal ? 128 : 1);
|
|
419
|
+
return {
|
|
420
|
+
stdout,
|
|
421
|
+
stderr,
|
|
422
|
+
exitCode,
|
|
423
|
+
success: exitCode === 0 && !result.error
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
var WINDOWS_RENAME_MAX_RETRIES = 3, WINDOWS_RENAME_RETRY_DELAY_MS = 50, tempCounter = 0;
|
|
427
|
+
var init_bun_compat = () => {};
|
|
428
|
+
|
|
429
|
+
// src/hooks/utils.ts
|
|
430
|
+
import * as path2 from "path";
|
|
104
431
|
function validateSwarmPath(directory, filename) {
|
|
105
432
|
if (/[\0]/.test(filename)) {
|
|
106
433
|
throw new Error("Invalid filename: contains null bytes");
|
|
@@ -114,14 +441,14 @@ function validateSwarmPath(directory, filename) {
|
|
|
114
441
|
if (filename.startsWith("/")) {
|
|
115
442
|
throw new Error("Invalid filename: path escapes .swarm directory");
|
|
116
443
|
}
|
|
117
|
-
const baseDir =
|
|
118
|
-
const resolved =
|
|
444
|
+
const baseDir = path2.normalize(path2.resolve(directory, ".swarm"));
|
|
445
|
+
const resolved = path2.normalize(path2.resolve(baseDir, filename));
|
|
119
446
|
if (process.platform === "win32") {
|
|
120
|
-
if (!resolved.toLowerCase().startsWith((baseDir +
|
|
447
|
+
if (!resolved.toLowerCase().startsWith((baseDir + path2.sep).toLowerCase())) {
|
|
121
448
|
throw new Error("Invalid filename: path escapes .swarm directory");
|
|
122
449
|
}
|
|
123
450
|
} else {
|
|
124
|
-
if (!resolved.startsWith(baseDir +
|
|
451
|
+
if (!resolved.startsWith(baseDir + path2.sep)) {
|
|
125
452
|
throw new Error("Invalid filename: path escapes .swarm directory");
|
|
126
453
|
}
|
|
127
454
|
}
|
|
@@ -130,7 +457,7 @@ function validateSwarmPath(directory, filename) {
|
|
|
130
457
|
async function readSwarmFileAsync(directory, filename) {
|
|
131
458
|
try {
|
|
132
459
|
const resolvedPath = validateSwarmPath(directory, filename);
|
|
133
|
-
const file =
|
|
460
|
+
const file = bunFile(resolvedPath);
|
|
134
461
|
const content = await file.text();
|
|
135
462
|
return content;
|
|
136
463
|
} catch {
|
|
@@ -139,6 +466,7 @@ async function readSwarmFileAsync(directory, filename) {
|
|
|
139
466
|
}
|
|
140
467
|
var init_utils2 = __esm(() => {
|
|
141
468
|
init_utils();
|
|
469
|
+
init_bun_compat();
|
|
142
470
|
});
|
|
143
471
|
|
|
144
472
|
// node_modules/zod/v4/core/core.js
|
|
@@ -388,10 +716,10 @@ function mergeDefs(...defs) {
|
|
|
388
716
|
function cloneDef(schema) {
|
|
389
717
|
return mergeDefs(schema._zod.def);
|
|
390
718
|
}
|
|
391
|
-
function getElementAtPath(obj,
|
|
392
|
-
if (!
|
|
719
|
+
function getElementAtPath(obj, path3) {
|
|
720
|
+
if (!path3)
|
|
393
721
|
return obj;
|
|
394
|
-
return
|
|
722
|
+
return path3.reduce((acc, key) => acc?.[key], obj);
|
|
395
723
|
}
|
|
396
724
|
function promiseAllObject(promisesObj) {
|
|
397
725
|
const keys = Object.keys(promisesObj);
|
|
@@ -702,11 +1030,11 @@ function aborted(x, startIndex = 0) {
|
|
|
702
1030
|
}
|
|
703
1031
|
return false;
|
|
704
1032
|
}
|
|
705
|
-
function prefixIssues(
|
|
1033
|
+
function prefixIssues(path3, issues) {
|
|
706
1034
|
return issues.map((iss) => {
|
|
707
1035
|
var _a;
|
|
708
1036
|
(_a = iss).path ?? (_a.path = []);
|
|
709
|
-
iss.path.unshift(
|
|
1037
|
+
iss.path.unshift(path3);
|
|
710
1038
|
return iss;
|
|
711
1039
|
});
|
|
712
1040
|
}
|
|
@@ -944,7 +1272,7 @@ function formatError(error2, mapper = (issue2) => issue2.message) {
|
|
|
944
1272
|
}
|
|
945
1273
|
function treeifyError(error2, mapper = (issue2) => issue2.message) {
|
|
946
1274
|
const result = { errors: [] };
|
|
947
|
-
const processError = (error3,
|
|
1275
|
+
const processError = (error3, path3 = []) => {
|
|
948
1276
|
var _a, _b;
|
|
949
1277
|
for (const issue2 of error3.issues) {
|
|
950
1278
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -954,7 +1282,7 @@ function treeifyError(error2, mapper = (issue2) => issue2.message) {
|
|
|
954
1282
|
} else if (issue2.code === "invalid_element") {
|
|
955
1283
|
processError({ issues: issue2.issues }, issue2.path);
|
|
956
1284
|
} else {
|
|
957
|
-
const fullpath = [...
|
|
1285
|
+
const fullpath = [...path3, ...issue2.path];
|
|
958
1286
|
if (fullpath.length === 0) {
|
|
959
1287
|
result.errors.push(mapper(issue2));
|
|
960
1288
|
continue;
|
|
@@ -986,8 +1314,8 @@ function treeifyError(error2, mapper = (issue2) => issue2.message) {
|
|
|
986
1314
|
}
|
|
987
1315
|
function toDotPath(_path) {
|
|
988
1316
|
const segs = [];
|
|
989
|
-
const
|
|
990
|
-
for (const seg of
|
|
1317
|
+
const path3 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
1318
|
+
for (const seg of path3) {
|
|
991
1319
|
if (typeof seg === "number")
|
|
992
1320
|
segs.push(`[${seg}]`);
|
|
993
1321
|
else if (typeof seg === "symbol")
|
|
@@ -13262,13 +13590,13 @@ function resolveRef(ref, ctx) {
|
|
|
13262
13590
|
if (!ref.startsWith("#")) {
|
|
13263
13591
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
13264
13592
|
}
|
|
13265
|
-
const
|
|
13266
|
-
if (
|
|
13593
|
+
const path3 = ref.slice(1).split("/").filter(Boolean);
|
|
13594
|
+
if (path3.length === 0) {
|
|
13267
13595
|
return ctx.rootSchema;
|
|
13268
13596
|
}
|
|
13269
13597
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
13270
|
-
if (
|
|
13271
|
-
const key =
|
|
13598
|
+
if (path3[0] === defsKey) {
|
|
13599
|
+
const key = path3[1];
|
|
13272
13600
|
if (!key || !ctx.defs[key]) {
|
|
13273
13601
|
throw new Error(`Reference not found: ${ref}`);
|
|
13274
13602
|
}
|
|
@@ -14103,13 +14431,13 @@ var init_telemetry = __esm(() => {
|
|
|
14103
14431
|
|
|
14104
14432
|
// src/utils/spec-hash.ts
|
|
14105
14433
|
import { createHash } from "crypto";
|
|
14106
|
-
import { readFile } from "fs/promises";
|
|
14107
|
-
import { join } from "path";
|
|
14434
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
14435
|
+
import { join as join2 } from "path";
|
|
14108
14436
|
async function computeSpecHash(directory) {
|
|
14109
|
-
const specPath =
|
|
14437
|
+
const specPath = join2(directory, ".swarm", "spec.md");
|
|
14110
14438
|
let hash2 = null;
|
|
14111
14439
|
try {
|
|
14112
|
-
const content = await
|
|
14440
|
+
const content = await readFile2(specPath, "utf-8");
|
|
14113
14441
|
hash2 = createHash("sha256").update(content, "utf-8").digest("hex");
|
|
14114
14442
|
} catch (error49) {
|
|
14115
14443
|
if (error49.code !== "ENOENT") {
|
|
@@ -14144,12 +14472,12 @@ var init_spec_hash = () => {};
|
|
|
14144
14472
|
// src/plan/ledger.ts
|
|
14145
14473
|
import * as crypto2 from "crypto";
|
|
14146
14474
|
import * as fs from "fs";
|
|
14147
|
-
import * as
|
|
14475
|
+
import * as path3 from "path";
|
|
14148
14476
|
function getLedgerPath(directory) {
|
|
14149
|
-
return
|
|
14477
|
+
return path3.join(directory, ".swarm", LEDGER_FILENAME);
|
|
14150
14478
|
}
|
|
14151
14479
|
function getPlanJsonPath(directory) {
|
|
14152
|
-
return
|
|
14480
|
+
return path3.join(directory, ".swarm", PLAN_JSON_FILENAME);
|
|
14153
14481
|
}
|
|
14154
14482
|
function computePlanHash(plan) {
|
|
14155
14483
|
const normalized = {
|
|
@@ -14280,7 +14608,7 @@ async function initLedger(directory, planId, initialPlanHash, initialPlan) {
|
|
|
14280
14608
|
schema_version: LEDGER_SCHEMA_VERSION,
|
|
14281
14609
|
...payload ? { payload } : {}
|
|
14282
14610
|
};
|
|
14283
|
-
fs.mkdirSync(
|
|
14611
|
+
fs.mkdirSync(path3.join(directory, ".swarm"), { recursive: true });
|
|
14284
14612
|
const tempPath = `${ledgerPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
|
|
14285
14613
|
const line = `${JSON.stringify(event)}
|
|
14286
14614
|
`;
|
|
@@ -14307,7 +14635,7 @@ async function appendLedgerEvent(directory, eventInput, options) {
|
|
|
14307
14635
|
plan_hash_after: planHashAfter,
|
|
14308
14636
|
schema_version: LEDGER_SCHEMA_VERSION
|
|
14309
14637
|
};
|
|
14310
|
-
fs.mkdirSync(
|
|
14638
|
+
fs.mkdirSync(path3.join(directory, ".swarm"), { recursive: true });
|
|
14311
14639
|
const tempPath = `${ledgerPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
|
|
14312
14640
|
const line = `${JSON.stringify(event)}
|
|
14313
14641
|
`;
|
|
@@ -14500,9 +14828,9 @@ async function readLedgerEventsWithIntegrity(directory) {
|
|
|
14500
14828
|
}
|
|
14501
14829
|
async function quarantineLedgerSuffix(directory, badSuffix) {
|
|
14502
14830
|
try {
|
|
14503
|
-
const quarantinePath =
|
|
14831
|
+
const quarantinePath = path3.join(directory, ".swarm", "plan-ledger.quarantine");
|
|
14504
14832
|
fs.writeFileSync(quarantinePath, badSuffix, "utf8");
|
|
14505
|
-
console.warn(`[ledger] Corrupted suffix quarantined to ${
|
|
14833
|
+
console.warn(`[ledger] Corrupted suffix quarantined to ${path3.relative(directory, quarantinePath)}`);
|
|
14506
14834
|
} catch {}
|
|
14507
14835
|
}
|
|
14508
14836
|
async function loadLastApprovedPlan(directory, expectedPlanId) {
|
|
@@ -14558,8 +14886,8 @@ import {
|
|
|
14558
14886
|
renameSync as renameSync2,
|
|
14559
14887
|
unlinkSync
|
|
14560
14888
|
} from "fs";
|
|
14561
|
-
import * as
|
|
14562
|
-
import * as
|
|
14889
|
+
import * as fsPromises2 from "fs/promises";
|
|
14890
|
+
import * as path4 from "path";
|
|
14563
14891
|
async function retryCasWithBackoff(directory, eventInput, options) {
|
|
14564
14892
|
const maxRetries = options.maxRetries ?? CAS_MAX_RETRIES;
|
|
14565
14893
|
let currentExpected = options.expectedHash;
|
|
@@ -14660,7 +14988,7 @@ function computePlanContentHash(plan) {
|
|
|
14660
14988
|
})).sort((a, b) => a.id - b.id)
|
|
14661
14989
|
};
|
|
14662
14990
|
const jsonString = JSON.stringify(content);
|
|
14663
|
-
return
|
|
14991
|
+
return bunHash(jsonString).toString(36);
|
|
14664
14992
|
}
|
|
14665
14993
|
function extractPlanHashFromMarkdown(markdown) {
|
|
14666
14994
|
const match = markdown.match(/<!--\s*PLAN_HASH:\s*(\S+)\s*-->/);
|
|
@@ -14685,15 +15013,15 @@ async function isPlanMdInSync(directory, plan) {
|
|
|
14685
15013
|
return normalizedActual.includes(normalizedExpected) || normalizedExpected.includes(normalizedActual.replace(/^#.*$/gm, "").trim());
|
|
14686
15014
|
}
|
|
14687
15015
|
async function regeneratePlanMarkdown(directory, plan) {
|
|
14688
|
-
const swarmDir =
|
|
15016
|
+
const swarmDir = path4.resolve(directory, ".swarm");
|
|
14689
15017
|
const contentHash = computePlanContentHash(plan);
|
|
14690
15018
|
const markdown = derivePlanMarkdown(plan);
|
|
14691
15019
|
const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
|
|
14692
15020
|
${markdown}`;
|
|
14693
|
-
const mdPath =
|
|
14694
|
-
const mdTempPath =
|
|
15021
|
+
const mdPath = path4.join(swarmDir, "plan.md");
|
|
15022
|
+
const mdTempPath = path4.join(swarmDir, `plan.md.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
14695
15023
|
try {
|
|
14696
|
-
await
|
|
15024
|
+
await bunWrite(mdTempPath, markdownWithHash);
|
|
14697
15025
|
renameSync2(mdTempPath, mdPath);
|
|
14698
15026
|
} finally {
|
|
14699
15027
|
try {
|
|
@@ -14721,7 +15049,7 @@ async function loadPlan(directory) {
|
|
|
14721
15049
|
if (await ledgerExists(directory)) {
|
|
14722
15050
|
const planHash = computePlanHash(validated);
|
|
14723
15051
|
const ledgerHash = await getLatestLedgerHash(directory);
|
|
14724
|
-
const resolvedWorkspace =
|
|
15052
|
+
const resolvedWorkspace = path4.resolve(directory);
|
|
14725
15053
|
if (!startupLedgerCheckedWorkspaces.has(resolvedWorkspace)) {
|
|
14726
15054
|
startupLedgerCheckedWorkspaces.add(resolvedWorkspace);
|
|
14727
15055
|
if (ledgerHash !== "" && planHash !== ledgerHash) {
|
|
@@ -14774,8 +15102,8 @@ async function loadPlan(directory) {
|
|
|
14774
15102
|
runtimePlan._specStale = true;
|
|
14775
15103
|
runtimePlan._specStaleReason = staleResult.reason;
|
|
14776
15104
|
try {
|
|
14777
|
-
const specStalenessPath =
|
|
14778
|
-
await
|
|
15105
|
+
const specStalenessPath = path4.join(directory, ".swarm", "spec-staleness.json");
|
|
15106
|
+
await fsPromises2.writeFile(specStalenessPath, JSON.stringify({
|
|
14779
15107
|
type: "spec_stale_detected",
|
|
14780
15108
|
timestamp: new Date().toISOString(),
|
|
14781
15109
|
phase: validated.current_phase ?? 1,
|
|
@@ -14786,7 +15114,7 @@ async function loadPlan(directory) {
|
|
|
14786
15114
|
}, null, 2), "utf-8");
|
|
14787
15115
|
} catch {}
|
|
14788
15116
|
try {
|
|
14789
|
-
const eventsPath =
|
|
15117
|
+
const eventsPath = path4.join(directory, ".swarm", "events.jsonl");
|
|
14790
15118
|
const event = {
|
|
14791
15119
|
type: "spec_stale_detected",
|
|
14792
15120
|
timestamp: new Date().toISOString(),
|
|
@@ -14796,7 +15124,7 @@ async function loadPlan(directory) {
|
|
|
14796
15124
|
reason: staleResult.reason ?? "unknown",
|
|
14797
15125
|
planTitle: validated.title
|
|
14798
15126
|
};
|
|
14799
|
-
await
|
|
15127
|
+
await fsPromises2.appendFile(eventsPath, `${JSON.stringify(event)}
|
|
14800
15128
|
`, "utf-8");
|
|
14801
15129
|
} catch {}
|
|
14802
15130
|
}
|
|
@@ -14842,7 +15170,7 @@ async function loadPlan(directory) {
|
|
|
14842
15170
|
return migrated;
|
|
14843
15171
|
}
|
|
14844
15172
|
if (await ledgerExists(directory)) {
|
|
14845
|
-
const resolvedDir =
|
|
15173
|
+
const resolvedDir = path4.resolve(directory);
|
|
14846
15174
|
const existingMutex = recoveryMutexes.get(resolvedDir);
|
|
14847
15175
|
if (existingMutex) {
|
|
14848
15176
|
await existingMutex;
|
|
@@ -14948,9 +15276,9 @@ async function savePlan(directory, plan, options) {
|
|
|
14948
15276
|
} else {
|
|
14949
15277
|
const existingEvents = await readLedgerEvents(directory);
|
|
14950
15278
|
if (existingEvents.length > 0 && existingEvents[0].plan_id !== planId) {
|
|
14951
|
-
const swarmDir2 =
|
|
14952
|
-
const oldLedgerPath =
|
|
14953
|
-
const oldLedgerBackupPath =
|
|
15279
|
+
const swarmDir2 = path4.resolve(directory, ".swarm");
|
|
15280
|
+
const oldLedgerPath = path4.join(swarmDir2, "plan-ledger.jsonl");
|
|
15281
|
+
const oldLedgerBackupPath = path4.join(swarmDir2, `plan-ledger.backup-${Date.now()}-${Math.floor(Math.random() * 1e9)}.jsonl`);
|
|
14954
15282
|
let backupExists = false;
|
|
14955
15283
|
if (existsSync2(oldLedgerPath)) {
|
|
14956
15284
|
try {
|
|
@@ -14988,7 +15316,7 @@ async function savePlan(directory, plan, options) {
|
|
|
14988
15316
|
}
|
|
14989
15317
|
}
|
|
14990
15318
|
if (initSucceeded && backupExists) {
|
|
14991
|
-
const archivePath =
|
|
15319
|
+
const archivePath = path4.join(swarmDir2, `plan-ledger.archived-${Date.now()}-${Math.floor(Math.random() * 1e9)}.jsonl`);
|
|
14992
15320
|
try {
|
|
14993
15321
|
renameSync2(oldLedgerBackupPath, archivePath);
|
|
14994
15322
|
warn(`[savePlan] Ledger identity mismatch (was "${existingEvents[0].plan_id}", now "${planId}") \u2014 archived old ledger to ${archivePath} and reinitializing.`);
|
|
@@ -15013,7 +15341,7 @@ async function savePlan(directory, plan, options) {
|
|
|
15013
15341
|
const toRemove = archivedSiblings.slice(0, archivedSiblings.length - MAX_ARCHIVED_SIBLINGS);
|
|
15014
15342
|
for (const file2 of toRemove) {
|
|
15015
15343
|
try {
|
|
15016
|
-
unlinkSync(
|
|
15344
|
+
unlinkSync(path4.join(swarmDir2, file2));
|
|
15017
15345
|
} catch {}
|
|
15018
15346
|
}
|
|
15019
15347
|
}
|
|
@@ -15082,11 +15410,11 @@ async function savePlan(directory, plan, options) {
|
|
|
15082
15410
|
}
|
|
15083
15411
|
});
|
|
15084
15412
|
}
|
|
15085
|
-
const swarmDir =
|
|
15086
|
-
const planPath =
|
|
15087
|
-
const tempPath =
|
|
15413
|
+
const swarmDir = path4.resolve(directory, ".swarm");
|
|
15414
|
+
const planPath = path4.join(swarmDir, "plan.json");
|
|
15415
|
+
const tempPath = path4.join(swarmDir, `plan.json.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
15088
15416
|
try {
|
|
15089
|
-
await
|
|
15417
|
+
await bunWrite(tempPath, JSON.stringify(validated, null, 2));
|
|
15090
15418
|
renameSync2(tempPath, planPath);
|
|
15091
15419
|
} finally {
|
|
15092
15420
|
try {
|
|
@@ -15098,10 +15426,10 @@ async function savePlan(directory, plan, options) {
|
|
|
15098
15426
|
const markdown = derivePlanMarkdown(validated);
|
|
15099
15427
|
const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
|
|
15100
15428
|
${markdown}`;
|
|
15101
|
-
const mdPath =
|
|
15102
|
-
const mdTempPath =
|
|
15429
|
+
const mdPath = path4.join(swarmDir, "plan.md");
|
|
15430
|
+
const mdTempPath = path4.join(swarmDir, `plan.md.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
15103
15431
|
try {
|
|
15104
|
-
await
|
|
15432
|
+
await bunWrite(mdTempPath, markdownWithHash);
|
|
15105
15433
|
renameSync2(mdTempPath, mdPath);
|
|
15106
15434
|
} finally {
|
|
15107
15435
|
try {
|
|
@@ -15120,7 +15448,7 @@ ${markdown}`;
|
|
|
15120
15448
|
} catch {}
|
|
15121
15449
|
}
|
|
15122
15450
|
try {
|
|
15123
|
-
const markerPath =
|
|
15451
|
+
const markerPath = path4.join(swarmDir, ".plan-write-marker");
|
|
15124
15452
|
const tasksCount = validated.phases.reduce((sum, phase) => sum + phase.tasks.length, 0);
|
|
15125
15453
|
const marker = JSON.stringify({
|
|
15126
15454
|
source: "plan_manager",
|
|
@@ -15128,28 +15456,28 @@ ${markdown}`;
|
|
|
15128
15456
|
phases_count: validated.phases.length,
|
|
15129
15457
|
tasks_count: tasksCount
|
|
15130
15458
|
});
|
|
15131
|
-
await
|
|
15459
|
+
await bunWrite(markerPath, marker);
|
|
15132
15460
|
} catch {}
|
|
15133
15461
|
}
|
|
15134
15462
|
async function rebuildPlan(directory, plan) {
|
|
15135
15463
|
const targetPlan = plan ?? await replayFromLedger(directory);
|
|
15136
15464
|
if (!targetPlan)
|
|
15137
15465
|
return null;
|
|
15138
|
-
const swarmDir =
|
|
15139
|
-
const planPath =
|
|
15140
|
-
const mdPath =
|
|
15141
|
-
const tempPlanPath =
|
|
15142
|
-
await
|
|
15466
|
+
const swarmDir = path4.join(directory, ".swarm");
|
|
15467
|
+
const planPath = path4.join(swarmDir, "plan.json");
|
|
15468
|
+
const mdPath = path4.join(swarmDir, "plan.md");
|
|
15469
|
+
const tempPlanPath = path4.join(swarmDir, `plan.json.rebuild.${Date.now()}`);
|
|
15470
|
+
await bunWrite(tempPlanPath, JSON.stringify(targetPlan, null, 2));
|
|
15143
15471
|
renameSync2(tempPlanPath, planPath);
|
|
15144
15472
|
const contentHash = computePlanContentHash(targetPlan);
|
|
15145
15473
|
const markdown = derivePlanMarkdown(targetPlan);
|
|
15146
15474
|
const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
|
|
15147
15475
|
${markdown}`;
|
|
15148
|
-
const tempMdPath =
|
|
15149
|
-
await
|
|
15476
|
+
const tempMdPath = path4.join(swarmDir, `plan.md.rebuild.${Date.now()}`);
|
|
15477
|
+
await bunWrite(tempMdPath, markdownWithHash);
|
|
15150
15478
|
renameSync2(tempMdPath, mdPath);
|
|
15151
15479
|
try {
|
|
15152
|
-
const markerPath =
|
|
15480
|
+
const markerPath = path4.join(swarmDir, ".plan-write-marker");
|
|
15153
15481
|
const tasksCount = targetPlan.phases.reduce((sum, phase) => sum + phase.tasks.length, 0);
|
|
15154
15482
|
const marker = JSON.stringify({
|
|
15155
15483
|
source: "plan_manager",
|
|
@@ -15157,7 +15485,7 @@ ${markdown}`;
|
|
|
15157
15485
|
phases_count: targetPlan.phases.length,
|
|
15158
15486
|
tasks_count: tasksCount
|
|
15159
15487
|
});
|
|
15160
|
-
await
|
|
15488
|
+
await bunWrite(markerPath, marker);
|
|
15161
15489
|
} catch {}
|
|
15162
15490
|
return targetPlan;
|
|
15163
15491
|
}
|
|
@@ -15435,6 +15763,7 @@ var init_manager = __esm(() => {
|
|
|
15435
15763
|
init_utils2();
|
|
15436
15764
|
init_telemetry();
|
|
15437
15765
|
init_utils();
|
|
15766
|
+
init_bun_compat();
|
|
15438
15767
|
init_spec_hash();
|
|
15439
15768
|
init_ledger();
|
|
15440
15769
|
PlanConcurrentModificationError = class PlanConcurrentModificationError extends Error {
|
|
@@ -15703,7 +16032,7 @@ var init_evidence_schema = __esm(() => {
|
|
|
15703
16032
|
|
|
15704
16033
|
// node_modules/graceful-fs/polyfills.js
|
|
15705
16034
|
var require_polyfills = __commonJS((exports, module) => {
|
|
15706
|
-
var
|
|
16035
|
+
var constants2 = __require("constants");
|
|
15707
16036
|
var origCwd = process.cwd;
|
|
15708
16037
|
var cwd = null;
|
|
15709
16038
|
var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform;
|
|
@@ -15727,7 +16056,7 @@ var require_polyfills = __commonJS((exports, module) => {
|
|
|
15727
16056
|
var chdir;
|
|
15728
16057
|
module.exports = patch;
|
|
15729
16058
|
function patch(fs3) {
|
|
15730
|
-
if (
|
|
16059
|
+
if (constants2.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
|
|
15731
16060
|
patchLchmod(fs3);
|
|
15732
16061
|
}
|
|
15733
16062
|
if (!fs3.lutimes) {
|
|
@@ -15752,14 +16081,14 @@ var require_polyfills = __commonJS((exports, module) => {
|
|
|
15752
16081
|
fs3.fstatSync = statFixSync(fs3.fstatSync);
|
|
15753
16082
|
fs3.lstatSync = statFixSync(fs3.lstatSync);
|
|
15754
16083
|
if (fs3.chmod && !fs3.lchmod) {
|
|
15755
|
-
fs3.lchmod = function(
|
|
16084
|
+
fs3.lchmod = function(path6, mode, cb) {
|
|
15756
16085
|
if (cb)
|
|
15757
16086
|
process.nextTick(cb);
|
|
15758
16087
|
};
|
|
15759
16088
|
fs3.lchmodSync = function() {};
|
|
15760
16089
|
}
|
|
15761
16090
|
if (fs3.chown && !fs3.lchown) {
|
|
15762
|
-
fs3.lchown = function(
|
|
16091
|
+
fs3.lchown = function(path6, uid, gid, cb) {
|
|
15763
16092
|
if (cb)
|
|
15764
16093
|
process.nextTick(cb);
|
|
15765
16094
|
};
|
|
@@ -15767,7 +16096,7 @@ var require_polyfills = __commonJS((exports, module) => {
|
|
|
15767
16096
|
}
|
|
15768
16097
|
if (platform === "win32") {
|
|
15769
16098
|
fs3.rename = typeof fs3.rename !== "function" ? fs3.rename : function(fs$rename) {
|
|
15770
|
-
function
|
|
16099
|
+
function rename2(from, to, cb) {
|
|
15771
16100
|
var start = Date.now();
|
|
15772
16101
|
var backoff = 0;
|
|
15773
16102
|
fs$rename(from, to, function CB(er) {
|
|
@@ -15789,8 +16118,8 @@ var require_polyfills = __commonJS((exports, module) => {
|
|
|
15789
16118
|
});
|
|
15790
16119
|
}
|
|
15791
16120
|
if (Object.setPrototypeOf)
|
|
15792
|
-
Object.setPrototypeOf(
|
|
15793
|
-
return
|
|
16121
|
+
Object.setPrototypeOf(rename2, fs$rename);
|
|
16122
|
+
return rename2;
|
|
15794
16123
|
}(fs3.rename);
|
|
15795
16124
|
}
|
|
15796
16125
|
fs3.read = typeof fs3.read !== "function" ? fs3.read : function(fs$read) {
|
|
@@ -15829,8 +16158,8 @@ var require_polyfills = __commonJS((exports, module) => {
|
|
|
15829
16158
|
};
|
|
15830
16159
|
}(fs3.readSync);
|
|
15831
16160
|
function patchLchmod(fs4) {
|
|
15832
|
-
fs4.lchmod = function(
|
|
15833
|
-
fs4.open(
|
|
16161
|
+
fs4.lchmod = function(path6, mode, callback) {
|
|
16162
|
+
fs4.open(path6, constants2.O_WRONLY | constants2.O_SYMLINK, mode, function(err, fd) {
|
|
15834
16163
|
if (err) {
|
|
15835
16164
|
if (callback)
|
|
15836
16165
|
callback(err);
|
|
@@ -15844,8 +16173,8 @@ var require_polyfills = __commonJS((exports, module) => {
|
|
|
15844
16173
|
});
|
|
15845
16174
|
});
|
|
15846
16175
|
};
|
|
15847
|
-
fs4.lchmodSync = function(
|
|
15848
|
-
var fd = fs4.openSync(
|
|
16176
|
+
fs4.lchmodSync = function(path6, mode) {
|
|
16177
|
+
var fd = fs4.openSync(path6, constants2.O_WRONLY | constants2.O_SYMLINK, mode);
|
|
15849
16178
|
var threw = true;
|
|
15850
16179
|
var ret;
|
|
15851
16180
|
try {
|
|
@@ -15864,9 +16193,9 @@ var require_polyfills = __commonJS((exports, module) => {
|
|
|
15864
16193
|
};
|
|
15865
16194
|
}
|
|
15866
16195
|
function patchLutimes(fs4) {
|
|
15867
|
-
if (
|
|
15868
|
-
fs4.lutimes = function(
|
|
15869
|
-
fs4.open(
|
|
16196
|
+
if (constants2.hasOwnProperty("O_SYMLINK") && fs4.futimes) {
|
|
16197
|
+
fs4.lutimes = function(path6, at, mt, cb) {
|
|
16198
|
+
fs4.open(path6, constants2.O_SYMLINK, function(er, fd) {
|
|
15870
16199
|
if (er) {
|
|
15871
16200
|
if (cb)
|
|
15872
16201
|
cb(er);
|
|
@@ -15880,8 +16209,8 @@ var require_polyfills = __commonJS((exports, module) => {
|
|
|
15880
16209
|
});
|
|
15881
16210
|
});
|
|
15882
16211
|
};
|
|
15883
|
-
fs4.lutimesSync = function(
|
|
15884
|
-
var fd = fs4.openSync(
|
|
16212
|
+
fs4.lutimesSync = function(path6, at, mt) {
|
|
16213
|
+
var fd = fs4.openSync(path6, constants2.O_SYMLINK);
|
|
15885
16214
|
var ret;
|
|
15886
16215
|
var threw = true;
|
|
15887
16216
|
try {
|
|
@@ -16013,12 +16342,12 @@ var require_legacy_streams = __commonJS((exports, module) => {
|
|
|
16013
16342
|
ReadStream,
|
|
16014
16343
|
WriteStream
|
|
16015
16344
|
};
|
|
16016
|
-
function ReadStream(
|
|
16345
|
+
function ReadStream(path6, options) {
|
|
16017
16346
|
if (!(this instanceof ReadStream))
|
|
16018
|
-
return new ReadStream(
|
|
16347
|
+
return new ReadStream(path6, options);
|
|
16019
16348
|
Stream.call(this);
|
|
16020
16349
|
var self = this;
|
|
16021
|
-
this.path =
|
|
16350
|
+
this.path = path6;
|
|
16022
16351
|
this.fd = null;
|
|
16023
16352
|
this.readable = true;
|
|
16024
16353
|
this.paused = false;
|
|
@@ -16064,11 +16393,11 @@ var require_legacy_streams = __commonJS((exports, module) => {
|
|
|
16064
16393
|
self._read();
|
|
16065
16394
|
});
|
|
16066
16395
|
}
|
|
16067
|
-
function WriteStream(
|
|
16396
|
+
function WriteStream(path6, options) {
|
|
16068
16397
|
if (!(this instanceof WriteStream))
|
|
16069
|
-
return new WriteStream(
|
|
16398
|
+
return new WriteStream(path6, options);
|
|
16070
16399
|
Stream.call(this);
|
|
16071
|
-
this.path =
|
|
16400
|
+
this.path = path6;
|
|
16072
16401
|
this.fd = null;
|
|
16073
16402
|
this.writable = true;
|
|
16074
16403
|
this.flags = "w";
|
|
@@ -16205,15 +16534,15 @@ GFS4: `);
|
|
|
16205
16534
|
fs4.createReadStream = createReadStream;
|
|
16206
16535
|
fs4.createWriteStream = createWriteStream;
|
|
16207
16536
|
var fs$readFile = fs4.readFile;
|
|
16208
|
-
fs4.readFile =
|
|
16209
|
-
function
|
|
16537
|
+
fs4.readFile = readFile3;
|
|
16538
|
+
function readFile3(path6, options, cb) {
|
|
16210
16539
|
if (typeof options === "function")
|
|
16211
16540
|
cb = options, options = null;
|
|
16212
|
-
return go$readFile(
|
|
16213
|
-
function go$readFile(
|
|
16214
|
-
return fs$readFile(
|
|
16541
|
+
return go$readFile(path6, options, cb);
|
|
16542
|
+
function go$readFile(path7, options2, cb2, startTime) {
|
|
16543
|
+
return fs$readFile(path7, options2, function(err) {
|
|
16215
16544
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
16216
|
-
enqueue([go$readFile, [
|
|
16545
|
+
enqueue([go$readFile, [path7, options2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
16217
16546
|
else {
|
|
16218
16547
|
if (typeof cb2 === "function")
|
|
16219
16548
|
cb2.apply(this, arguments);
|
|
@@ -16222,15 +16551,15 @@ GFS4: `);
|
|
|
16222
16551
|
}
|
|
16223
16552
|
}
|
|
16224
16553
|
var fs$writeFile = fs4.writeFile;
|
|
16225
|
-
fs4.writeFile =
|
|
16226
|
-
function
|
|
16554
|
+
fs4.writeFile = writeFile3;
|
|
16555
|
+
function writeFile3(path6, data, options, cb) {
|
|
16227
16556
|
if (typeof options === "function")
|
|
16228
16557
|
cb = options, options = null;
|
|
16229
|
-
return go$writeFile(
|
|
16230
|
-
function go$writeFile(
|
|
16231
|
-
return fs$writeFile(
|
|
16558
|
+
return go$writeFile(path6, data, options, cb);
|
|
16559
|
+
function go$writeFile(path7, data2, options2, cb2, startTime) {
|
|
16560
|
+
return fs$writeFile(path7, data2, options2, function(err) {
|
|
16232
16561
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
16233
|
-
enqueue([go$writeFile, [
|
|
16562
|
+
enqueue([go$writeFile, [path7, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
16234
16563
|
else {
|
|
16235
16564
|
if (typeof cb2 === "function")
|
|
16236
16565
|
cb2.apply(this, arguments);
|
|
@@ -16241,14 +16570,14 @@ GFS4: `);
|
|
|
16241
16570
|
var fs$appendFile = fs4.appendFile;
|
|
16242
16571
|
if (fs$appendFile)
|
|
16243
16572
|
fs4.appendFile = appendFile2;
|
|
16244
|
-
function appendFile2(
|
|
16573
|
+
function appendFile2(path6, data, options, cb) {
|
|
16245
16574
|
if (typeof options === "function")
|
|
16246
16575
|
cb = options, options = null;
|
|
16247
|
-
return go$appendFile(
|
|
16248
|
-
function go$appendFile(
|
|
16249
|
-
return fs$appendFile(
|
|
16576
|
+
return go$appendFile(path6, data, options, cb);
|
|
16577
|
+
function go$appendFile(path7, data2, options2, cb2, startTime) {
|
|
16578
|
+
return fs$appendFile(path7, data2, options2, function(err) {
|
|
16250
16579
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
16251
|
-
enqueue([go$appendFile, [
|
|
16580
|
+
enqueue([go$appendFile, [path7, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
16252
16581
|
else {
|
|
16253
16582
|
if (typeof cb2 === "function")
|
|
16254
16583
|
cb2.apply(this, arguments);
|
|
@@ -16279,21 +16608,21 @@ GFS4: `);
|
|
|
16279
16608
|
var fs$readdir = fs4.readdir;
|
|
16280
16609
|
fs4.readdir = readdir;
|
|
16281
16610
|
var noReaddirOptionVersions = /^v[0-5]\./;
|
|
16282
|
-
function readdir(
|
|
16611
|
+
function readdir(path6, options, cb) {
|
|
16283
16612
|
if (typeof options === "function")
|
|
16284
16613
|
cb = options, options = null;
|
|
16285
|
-
var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(
|
|
16286
|
-
return fs$readdir(
|
|
16287
|
-
} : function go$readdir2(
|
|
16288
|
-
return fs$readdir(
|
|
16614
|
+
var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path7, options2, cb2, startTime) {
|
|
16615
|
+
return fs$readdir(path7, fs$readdirCallback(path7, options2, cb2, startTime));
|
|
16616
|
+
} : function go$readdir2(path7, options2, cb2, startTime) {
|
|
16617
|
+
return fs$readdir(path7, options2, fs$readdirCallback(path7, options2, cb2, startTime));
|
|
16289
16618
|
};
|
|
16290
|
-
return go$readdir(
|
|
16291
|
-
function fs$readdirCallback(
|
|
16619
|
+
return go$readdir(path6, options, cb);
|
|
16620
|
+
function fs$readdirCallback(path7, options2, cb2, startTime) {
|
|
16292
16621
|
return function(err, files) {
|
|
16293
16622
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
16294
16623
|
enqueue([
|
|
16295
16624
|
go$readdir,
|
|
16296
|
-
[
|
|
16625
|
+
[path7, options2, cb2],
|
|
16297
16626
|
err,
|
|
16298
16627
|
startTime || Date.now(),
|
|
16299
16628
|
Date.now()
|
|
@@ -16364,7 +16693,7 @@ GFS4: `);
|
|
|
16364
16693
|
enumerable: true,
|
|
16365
16694
|
configurable: true
|
|
16366
16695
|
});
|
|
16367
|
-
function ReadStream(
|
|
16696
|
+
function ReadStream(path6, options) {
|
|
16368
16697
|
if (this instanceof ReadStream)
|
|
16369
16698
|
return fs$ReadStream.apply(this, arguments), this;
|
|
16370
16699
|
else
|
|
@@ -16384,7 +16713,7 @@ GFS4: `);
|
|
|
16384
16713
|
}
|
|
16385
16714
|
});
|
|
16386
16715
|
}
|
|
16387
|
-
function WriteStream(
|
|
16716
|
+
function WriteStream(path6, options) {
|
|
16388
16717
|
if (this instanceof WriteStream)
|
|
16389
16718
|
return fs$WriteStream.apply(this, arguments), this;
|
|
16390
16719
|
else
|
|
@@ -16402,22 +16731,22 @@ GFS4: `);
|
|
|
16402
16731
|
}
|
|
16403
16732
|
});
|
|
16404
16733
|
}
|
|
16405
|
-
function createReadStream(
|
|
16406
|
-
return new fs4.ReadStream(
|
|
16734
|
+
function createReadStream(path6, options) {
|
|
16735
|
+
return new fs4.ReadStream(path6, options);
|
|
16407
16736
|
}
|
|
16408
|
-
function createWriteStream(
|
|
16409
|
-
return new fs4.WriteStream(
|
|
16737
|
+
function createWriteStream(path6, options) {
|
|
16738
|
+
return new fs4.WriteStream(path6, options);
|
|
16410
16739
|
}
|
|
16411
16740
|
var fs$open = fs4.open;
|
|
16412
16741
|
fs4.open = open;
|
|
16413
|
-
function open(
|
|
16742
|
+
function open(path6, flags, mode, cb) {
|
|
16414
16743
|
if (typeof mode === "function")
|
|
16415
16744
|
cb = mode, mode = null;
|
|
16416
|
-
return go$open(
|
|
16417
|
-
function go$open(
|
|
16418
|
-
return fs$open(
|
|
16745
|
+
return go$open(path6, flags, mode, cb);
|
|
16746
|
+
function go$open(path7, flags2, mode2, cb2, startTime) {
|
|
16747
|
+
return fs$open(path7, flags2, mode2, function(err, fd) {
|
|
16419
16748
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
16420
|
-
enqueue([go$open, [
|
|
16749
|
+
enqueue([go$open, [path7, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
16421
16750
|
else {
|
|
16422
16751
|
if (typeof cb2 === "function")
|
|
16423
16752
|
cb2.apply(this, arguments);
|
|
@@ -16868,11 +17197,11 @@ var require_mtime_precision = __commonJS((exports, module) => {
|
|
|
16868
17197
|
function probe(file2, fs3, callback) {
|
|
16869
17198
|
const cachedPrecision = fs3[cacheSymbol];
|
|
16870
17199
|
if (cachedPrecision) {
|
|
16871
|
-
return fs3.stat(file2, (err,
|
|
17200
|
+
return fs3.stat(file2, (err, stat2) => {
|
|
16872
17201
|
if (err) {
|
|
16873
17202
|
return callback(err);
|
|
16874
17203
|
}
|
|
16875
|
-
callback(null,
|
|
17204
|
+
callback(null, stat2.mtime, cachedPrecision);
|
|
16876
17205
|
});
|
|
16877
17206
|
}
|
|
16878
17207
|
const mtime = new Date(Math.ceil(Date.now() / 1000) * 1000 + 5);
|
|
@@ -16880,13 +17209,13 @@ var require_mtime_precision = __commonJS((exports, module) => {
|
|
|
16880
17209
|
if (err) {
|
|
16881
17210
|
return callback(err);
|
|
16882
17211
|
}
|
|
16883
|
-
fs3.stat(file2, (err2,
|
|
17212
|
+
fs3.stat(file2, (err2, stat2) => {
|
|
16884
17213
|
if (err2) {
|
|
16885
17214
|
return callback(err2);
|
|
16886
17215
|
}
|
|
16887
|
-
const precision =
|
|
17216
|
+
const precision = stat2.mtime.getTime() % 1000 === 0 ? "s" : "ms";
|
|
16888
17217
|
Object.defineProperty(fs3, cacheSymbol, { value: precision });
|
|
16889
|
-
callback(null,
|
|
17218
|
+
callback(null, stat2.mtime, precision);
|
|
16890
17219
|
});
|
|
16891
17220
|
});
|
|
16892
17221
|
}
|
|
@@ -16903,7 +17232,7 @@ var require_mtime_precision = __commonJS((exports, module) => {
|
|
|
16903
17232
|
|
|
16904
17233
|
// node_modules/proper-lockfile/lib/lockfile.js
|
|
16905
17234
|
var require_lockfile = __commonJS((exports, module) => {
|
|
16906
|
-
var
|
|
17235
|
+
var path6 = __require("path");
|
|
16907
17236
|
var fs3 = require_graceful_fs();
|
|
16908
17237
|
var retry = require_retry();
|
|
16909
17238
|
var onExit = require_signal_exit();
|
|
@@ -16914,7 +17243,7 @@ var require_lockfile = __commonJS((exports, module) => {
|
|
|
16914
17243
|
}
|
|
16915
17244
|
function resolveCanonicalPath(file2, options, callback) {
|
|
16916
17245
|
if (!options.realpath) {
|
|
16917
|
-
return callback(null,
|
|
17246
|
+
return callback(null, path6.resolve(file2));
|
|
16918
17247
|
}
|
|
16919
17248
|
options.fs.realpath(file2, callback);
|
|
16920
17249
|
}
|
|
@@ -16936,14 +17265,14 @@ var require_lockfile = __commonJS((exports, module) => {
|
|
|
16936
17265
|
if (options.stale <= 0) {
|
|
16937
17266
|
return callback(Object.assign(new Error("Lock file is already being held"), { code: "ELOCKED", file: file2 }));
|
|
16938
17267
|
}
|
|
16939
|
-
options.fs.stat(lockfilePath, (err2,
|
|
17268
|
+
options.fs.stat(lockfilePath, (err2, stat2) => {
|
|
16940
17269
|
if (err2) {
|
|
16941
17270
|
if (err2.code === "ENOENT") {
|
|
16942
17271
|
return acquireLock(file2, { ...options, stale: 0 }, callback);
|
|
16943
17272
|
}
|
|
16944
17273
|
return callback(err2);
|
|
16945
17274
|
}
|
|
16946
|
-
if (!isLockStale(
|
|
17275
|
+
if (!isLockStale(stat2, options)) {
|
|
16947
17276
|
return callback(Object.assign(new Error("Lock file is already being held"), { code: "ELOCKED", file: file2 }));
|
|
16948
17277
|
}
|
|
16949
17278
|
removeLock(file2, options, (err3) => {
|
|
@@ -16955,8 +17284,8 @@ var require_lockfile = __commonJS((exports, module) => {
|
|
|
16955
17284
|
});
|
|
16956
17285
|
});
|
|
16957
17286
|
}
|
|
16958
|
-
function isLockStale(
|
|
16959
|
-
return
|
|
17287
|
+
function isLockStale(stat2, options) {
|
|
17288
|
+
return stat2.mtime.getTime() < Date.now() - options.stale;
|
|
16960
17289
|
}
|
|
16961
17290
|
function removeLock(file2, options, callback) {
|
|
16962
17291
|
options.fs.rmdir(getLockFile(file2, options), (err) => {
|
|
@@ -16974,7 +17303,7 @@ var require_lockfile = __commonJS((exports, module) => {
|
|
|
16974
17303
|
lock2.updateDelay = lock2.updateDelay || options.update;
|
|
16975
17304
|
lock2.updateTimeout = setTimeout(() => {
|
|
16976
17305
|
lock2.updateTimeout = null;
|
|
16977
|
-
options.fs.stat(lock2.lockfilePath, (err,
|
|
17306
|
+
options.fs.stat(lock2.lockfilePath, (err, stat2) => {
|
|
16978
17307
|
const isOverThreshold = lock2.lastUpdate + options.stale < Date.now();
|
|
16979
17308
|
if (err) {
|
|
16980
17309
|
if (err.code === "ENOENT" || isOverThreshold) {
|
|
@@ -16983,7 +17312,7 @@ var require_lockfile = __commonJS((exports, module) => {
|
|
|
16983
17312
|
lock2.updateDelay = 1000;
|
|
16984
17313
|
return updateLock(file2, options);
|
|
16985
17314
|
}
|
|
16986
|
-
const isMtimeOurs = lock2.mtime.getTime() ===
|
|
17315
|
+
const isMtimeOurs = lock2.mtime.getTime() === stat2.mtime.getTime();
|
|
16987
17316
|
if (!isMtimeOurs) {
|
|
16988
17317
|
return setLockAsCompromised(file2, lock2, Object.assign(new Error("Unable to update lock within the stale threshold"), { code: "ECOMPROMISED" }));
|
|
16989
17318
|
}
|
|
@@ -17101,11 +17430,11 @@ var require_lockfile = __commonJS((exports, module) => {
|
|
|
17101
17430
|
if (err) {
|
|
17102
17431
|
return callback(err);
|
|
17103
17432
|
}
|
|
17104
|
-
options.fs.stat(getLockFile(file3, options), (err2,
|
|
17433
|
+
options.fs.stat(getLockFile(file3, options), (err2, stat2) => {
|
|
17105
17434
|
if (err2) {
|
|
17106
17435
|
return err2.code === "ENOENT" ? callback(null, false) : callback(err2);
|
|
17107
17436
|
}
|
|
17108
|
-
return callback(null, !isLockStale(
|
|
17437
|
+
return callback(null, !isLockStale(stat2, options));
|
|
17109
17438
|
});
|
|
17110
17439
|
});
|
|
17111
17440
|
}
|
|
@@ -17223,20 +17552,20 @@ var require_proper_lockfile = __commonJS((exports, module) => {
|
|
|
17223
17552
|
|
|
17224
17553
|
// src/parallel/file-locks.ts
|
|
17225
17554
|
import * as fs3 from "fs";
|
|
17226
|
-
import * as
|
|
17555
|
+
import * as path6 from "path";
|
|
17227
17556
|
function getLockFilePath(directory, filePath) {
|
|
17228
|
-
const normalized =
|
|
17229
|
-
const baseDir =
|
|
17557
|
+
const normalized = path6.resolve(directory, filePath);
|
|
17558
|
+
const baseDir = path6.resolve(directory) + path6.sep;
|
|
17230
17559
|
const pathOk = process.platform === "win32" ? normalized.toLowerCase().startsWith(baseDir.toLowerCase()) : normalized.startsWith(baseDir);
|
|
17231
17560
|
if (!pathOk) {
|
|
17232
17561
|
throw new Error("Invalid file path: path traversal not allowed");
|
|
17233
17562
|
}
|
|
17234
17563
|
const hash2 = Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
|
|
17235
|
-
return
|
|
17564
|
+
return path6.join(directory, LOCKS_DIR, `${hash2}.lock`);
|
|
17236
17565
|
}
|
|
17237
17566
|
async function tryAcquireLock(directory, filePath, agent, taskId) {
|
|
17238
17567
|
const lockPath = getLockFilePath(directory, filePath);
|
|
17239
|
-
const locksDir =
|
|
17568
|
+
const locksDir = path6.dirname(lockPath);
|
|
17240
17569
|
if (!fs3.existsSync(locksDir)) {
|
|
17241
17570
|
fs3.mkdirSync(locksDir, { recursive: true });
|
|
17242
17571
|
}
|
|
@@ -17386,19 +17715,19 @@ var init_task_id = __esm(() => {
|
|
|
17386
17715
|
});
|
|
17387
17716
|
|
|
17388
17717
|
// src/evidence/manager.ts
|
|
17389
|
-
import { mkdirSync as mkdirSync3, readdirSync as readdirSync3, rmSync, statSync as
|
|
17718
|
+
import { mkdirSync as mkdirSync3, readdirSync as readdirSync3, rmSync, statSync as statSync4 } from "fs";
|
|
17390
17719
|
import * as fs4 from "fs/promises";
|
|
17391
|
-
import * as
|
|
17720
|
+
import * as path7 from "path";
|
|
17392
17721
|
function isValidEvidenceType(type) {
|
|
17393
17722
|
return VALID_EVIDENCE_TYPES.includes(type);
|
|
17394
17723
|
}
|
|
17395
17724
|
async function saveEvidence(directory, taskId, evidence) {
|
|
17396
17725
|
const sanitizedTaskId = sanitizeTaskId2(taskId);
|
|
17397
|
-
const relativePath =
|
|
17726
|
+
const relativePath = path7.join("evidence", sanitizedTaskId, "evidence.json");
|
|
17398
17727
|
validateSwarmPath(directory, relativePath);
|
|
17399
17728
|
return withEvidenceLock(directory, relativePath, "evidence-manager", sanitizedTaskId, async () => {
|
|
17400
17729
|
const evidencePath = validateSwarmPath(directory, relativePath);
|
|
17401
|
-
const evidenceDir =
|
|
17730
|
+
const evidenceDir = path7.dirname(evidencePath);
|
|
17402
17731
|
let bundle;
|
|
17403
17732
|
const existingContent = await readSwarmFileAsync(directory, relativePath);
|
|
17404
17733
|
if (existingContent !== null) {
|
|
@@ -17441,9 +17770,9 @@ async function saveEvidence(directory, taskId, evidence) {
|
|
|
17441
17770
|
throw new Error(`Evidence bundle size (${bundleJson.length} bytes) exceeds maximum (${EVIDENCE_MAX_JSON_BYTES} bytes)`);
|
|
17442
17771
|
}
|
|
17443
17772
|
mkdirSync3(evidenceDir, { recursive: true });
|
|
17444
|
-
const tempPath =
|
|
17773
|
+
const tempPath = path7.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
|
|
17445
17774
|
try {
|
|
17446
|
-
await
|
|
17775
|
+
await bunWrite(tempPath, bundleJson);
|
|
17447
17776
|
await fs4.rename(tempPath, evidencePath);
|
|
17448
17777
|
} catch (error49) {
|
|
17449
17778
|
try {
|
|
@@ -17480,7 +17809,7 @@ function wrapFlatRetrospective(flatEntry, taskId) {
|
|
|
17480
17809
|
}
|
|
17481
17810
|
async function loadEvidence(directory, taskId) {
|
|
17482
17811
|
const sanitizedTaskId = sanitizeTaskId2(taskId);
|
|
17483
|
-
const relativePath =
|
|
17812
|
+
const relativePath = path7.join("evidence", sanitizedTaskId, "evidence.json");
|
|
17484
17813
|
const evidencePath = validateSwarmPath(directory, relativePath);
|
|
17485
17814
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
17486
17815
|
if (content === null) {
|
|
@@ -17498,11 +17827,11 @@ async function loadEvidence(directory, taskId) {
|
|
|
17498
17827
|
const validated = EvidenceBundleSchema.parse(wrappedBundle);
|
|
17499
17828
|
try {
|
|
17500
17829
|
await withEvidenceLock(directory, relativePath, "evidence-loader", sanitizedTaskId, async () => {
|
|
17501
|
-
const evidenceDir =
|
|
17830
|
+
const evidenceDir = path7.dirname(evidencePath);
|
|
17502
17831
|
const bundleJson = JSON.stringify(validated);
|
|
17503
|
-
const tempPath =
|
|
17832
|
+
const tempPath = path7.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
|
|
17504
17833
|
try {
|
|
17505
|
-
await
|
|
17834
|
+
await bunWrite(tempPath, bundleJson);
|
|
17506
17835
|
await fs4.rename(tempPath, evidencePath);
|
|
17507
17836
|
} catch (writeError) {
|
|
17508
17837
|
try {
|
|
@@ -17533,7 +17862,7 @@ async function loadEvidence(directory, taskId) {
|
|
|
17533
17862
|
async function listEvidenceTaskIds(directory) {
|
|
17534
17863
|
const evidenceBasePath = validateSwarmPath(directory, "evidence");
|
|
17535
17864
|
try {
|
|
17536
|
-
|
|
17865
|
+
statSync4(evidenceBasePath);
|
|
17537
17866
|
} catch {
|
|
17538
17867
|
return [];
|
|
17539
17868
|
}
|
|
@@ -17545,9 +17874,9 @@ async function listEvidenceTaskIds(directory) {
|
|
|
17545
17874
|
}
|
|
17546
17875
|
const taskIds = [];
|
|
17547
17876
|
for (const entry of entries) {
|
|
17548
|
-
const entryPath =
|
|
17877
|
+
const entryPath = path7.join(evidenceBasePath, entry);
|
|
17549
17878
|
try {
|
|
17550
|
-
const stats =
|
|
17879
|
+
const stats = statSync4(entryPath);
|
|
17551
17880
|
if (!stats.isDirectory()) {
|
|
17552
17881
|
continue;
|
|
17553
17882
|
}
|
|
@@ -17563,10 +17892,10 @@ async function listEvidenceTaskIds(directory) {
|
|
|
17563
17892
|
}
|
|
17564
17893
|
async function deleteEvidence(directory, taskId) {
|
|
17565
17894
|
const sanitizedTaskId = sanitizeTaskId2(taskId);
|
|
17566
|
-
const relativePath =
|
|
17895
|
+
const relativePath = path7.join("evidence", sanitizedTaskId);
|
|
17567
17896
|
const evidenceDir = validateSwarmPath(directory, relativePath);
|
|
17568
17897
|
try {
|
|
17569
|
-
|
|
17898
|
+
statSync4(evidenceDir);
|
|
17570
17899
|
} catch {
|
|
17571
17900
|
return false;
|
|
17572
17901
|
}
|
|
@@ -17579,8 +17908,8 @@ async function deleteEvidence(directory, taskId) {
|
|
|
17579
17908
|
}
|
|
17580
17909
|
}
|
|
17581
17910
|
async function checkRequirementCoverage(phase, directory) {
|
|
17582
|
-
const relativePath =
|
|
17583
|
-
const absolutePath =
|
|
17911
|
+
const relativePath = path7.join("evidence", `req-coverage-phase-${phase}.json`);
|
|
17912
|
+
const absolutePath = path7.resolve(directory, ".swarm", relativePath);
|
|
17584
17913
|
try {
|
|
17585
17914
|
await fs4.access(absolutePath);
|
|
17586
17915
|
return { exists: true, path: absolutePath };
|
|
@@ -17630,6 +17959,7 @@ var init_manager2 = __esm(() => {
|
|
|
17630
17959
|
init_evidence_schema();
|
|
17631
17960
|
init_utils2();
|
|
17632
17961
|
init_utils();
|
|
17962
|
+
init_bun_compat();
|
|
17633
17963
|
init_lock();
|
|
17634
17964
|
init_task_id();
|
|
17635
17965
|
VALID_EVIDENCE_TYPES = [
|
|
@@ -17671,13 +18001,13 @@ __export(exports_config_doctor, {
|
|
|
17671
18001
|
import * as crypto3 from "crypto";
|
|
17672
18002
|
import * as fs8 from "fs";
|
|
17673
18003
|
import * as os6 from "os";
|
|
17674
|
-
import * as
|
|
18004
|
+
import * as path20 from "path";
|
|
17675
18005
|
function getUserConfigDir3() {
|
|
17676
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
18006
|
+
return process.env.XDG_CONFIG_HOME || path20.join(os6.homedir(), ".config");
|
|
17677
18007
|
}
|
|
17678
18008
|
function getConfigPaths(directory) {
|
|
17679
|
-
const userConfigPath =
|
|
17680
|
-
const projectConfigPath =
|
|
18009
|
+
const userConfigPath = path20.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
|
|
18010
|
+
const projectConfigPath = path20.join(directory, ".opencode", "opencode-swarm.json");
|
|
17681
18011
|
return { userConfigPath, projectConfigPath };
|
|
17682
18012
|
}
|
|
17683
18013
|
function computeHash(content) {
|
|
@@ -17702,9 +18032,9 @@ function isValidConfigPath(configPath, directory) {
|
|
|
17702
18032
|
const normalizedUser = userConfigPath.replace(/\\/g, "/");
|
|
17703
18033
|
const normalizedProject = projectConfigPath.replace(/\\/g, "/");
|
|
17704
18034
|
try {
|
|
17705
|
-
const resolvedConfig =
|
|
17706
|
-
const resolvedUser =
|
|
17707
|
-
const resolvedProject =
|
|
18035
|
+
const resolvedConfig = path20.resolve(configPath);
|
|
18036
|
+
const resolvedUser = path20.resolve(normalizedUser);
|
|
18037
|
+
const resolvedProject = path20.resolve(normalizedProject);
|
|
17708
18038
|
return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
|
|
17709
18039
|
} catch {
|
|
17710
18040
|
return false;
|
|
@@ -17744,12 +18074,12 @@ function createConfigBackup(directory) {
|
|
|
17744
18074
|
};
|
|
17745
18075
|
}
|
|
17746
18076
|
function writeBackupArtifact(directory, backup) {
|
|
17747
|
-
const swarmDir =
|
|
18077
|
+
const swarmDir = path20.join(directory, ".swarm");
|
|
17748
18078
|
if (!fs8.existsSync(swarmDir)) {
|
|
17749
18079
|
fs8.mkdirSync(swarmDir, { recursive: true });
|
|
17750
18080
|
}
|
|
17751
18081
|
const backupFilename = `config-backup-${backup.createdAt}.json`;
|
|
17752
|
-
const backupPath =
|
|
18082
|
+
const backupPath = path20.join(swarmDir, backupFilename);
|
|
17753
18083
|
const artifact = {
|
|
17754
18084
|
createdAt: backup.createdAt,
|
|
17755
18085
|
configPath: backup.configPath,
|
|
@@ -17779,7 +18109,7 @@ function restoreFromBackup(backupPath, directory) {
|
|
|
17779
18109
|
return null;
|
|
17780
18110
|
}
|
|
17781
18111
|
const targetPath = artifact.configPath;
|
|
17782
|
-
const targetDir =
|
|
18112
|
+
const targetDir = path20.dirname(targetPath);
|
|
17783
18113
|
if (!fs8.existsSync(targetDir)) {
|
|
17784
18114
|
fs8.mkdirSync(targetDir, { recursive: true });
|
|
17785
18115
|
}
|
|
@@ -17810,9 +18140,9 @@ function readConfigFromFile(directory) {
|
|
|
17810
18140
|
return null;
|
|
17811
18141
|
}
|
|
17812
18142
|
}
|
|
17813
|
-
function validateConfigKey(
|
|
18143
|
+
function validateConfigKey(path21, value, _config) {
|
|
17814
18144
|
const findings = [];
|
|
17815
|
-
switch (
|
|
18145
|
+
switch (path21) {
|
|
17816
18146
|
case "agents": {
|
|
17817
18147
|
if (value !== undefined) {
|
|
17818
18148
|
findings.push({
|
|
@@ -18059,27 +18389,27 @@ function validateConfigKey(path20, value, _config) {
|
|
|
18059
18389
|
}
|
|
18060
18390
|
return findings;
|
|
18061
18391
|
}
|
|
18062
|
-
function walkConfigAndValidate(obj,
|
|
18392
|
+
function walkConfigAndValidate(obj, path21, config3, findings) {
|
|
18063
18393
|
if (obj === null || obj === undefined) {
|
|
18064
18394
|
return;
|
|
18065
18395
|
}
|
|
18066
|
-
if (
|
|
18067
|
-
const keyFindings = validateConfigKey(
|
|
18396
|
+
if (path21 && typeof obj === "object" && !Array.isArray(obj)) {
|
|
18397
|
+
const keyFindings = validateConfigKey(path21, obj, config3);
|
|
18068
18398
|
findings.push(...keyFindings);
|
|
18069
18399
|
}
|
|
18070
18400
|
if (typeof obj !== "object") {
|
|
18071
|
-
const keyFindings = validateConfigKey(
|
|
18401
|
+
const keyFindings = validateConfigKey(path21, obj, config3);
|
|
18072
18402
|
findings.push(...keyFindings);
|
|
18073
18403
|
return;
|
|
18074
18404
|
}
|
|
18075
18405
|
if (Array.isArray(obj)) {
|
|
18076
18406
|
obj.forEach((item, index) => {
|
|
18077
|
-
walkConfigAndValidate(item, `${
|
|
18407
|
+
walkConfigAndValidate(item, `${path21}[${index}]`, config3, findings);
|
|
18078
18408
|
});
|
|
18079
18409
|
return;
|
|
18080
18410
|
}
|
|
18081
18411
|
for (const [key, value] of Object.entries(obj)) {
|
|
18082
|
-
const newPath =
|
|
18412
|
+
const newPath = path21 ? `${path21}.${key}` : key;
|
|
18083
18413
|
walkConfigAndValidate(value, newPath, config3, findings);
|
|
18084
18414
|
}
|
|
18085
18415
|
}
|
|
@@ -18199,7 +18529,7 @@ function applySafeAutoFixes(directory, result) {
|
|
|
18199
18529
|
}
|
|
18200
18530
|
}
|
|
18201
18531
|
if (appliedFixes.length > 0) {
|
|
18202
|
-
const configDir =
|
|
18532
|
+
const configDir = path20.dirname(configPath);
|
|
18203
18533
|
if (!fs8.existsSync(configDir)) {
|
|
18204
18534
|
fs8.mkdirSync(configDir, { recursive: true });
|
|
18205
18535
|
}
|
|
@@ -18209,12 +18539,12 @@ function applySafeAutoFixes(directory, result) {
|
|
|
18209
18539
|
return { appliedFixes, updatedConfigPath };
|
|
18210
18540
|
}
|
|
18211
18541
|
function writeDoctorArtifact(directory, result) {
|
|
18212
|
-
const swarmDir =
|
|
18542
|
+
const swarmDir = path20.join(directory, ".swarm");
|
|
18213
18543
|
if (!fs8.existsSync(swarmDir)) {
|
|
18214
18544
|
fs8.mkdirSync(swarmDir, { recursive: true });
|
|
18215
18545
|
}
|
|
18216
18546
|
const artifactFilename = "config-doctor.json";
|
|
18217
|
-
const artifactPath =
|
|
18547
|
+
const artifactPath = path20.join(swarmDir, artifactFilename);
|
|
18218
18548
|
const guiOutput = {
|
|
18219
18549
|
timestamp: result.timestamp,
|
|
18220
18550
|
summary: result.summary,
|
|
@@ -18577,11 +18907,11 @@ var init_evidence_summary_service = __esm(() => {
|
|
|
18577
18907
|
// src/cli/index.ts
|
|
18578
18908
|
import * as fs21 from "fs";
|
|
18579
18909
|
import * as os7 from "os";
|
|
18580
|
-
import * as
|
|
18910
|
+
import * as path35 from "path";
|
|
18581
18911
|
// package.json
|
|
18582
18912
|
var package_default = {
|
|
18583
18913
|
name: "opencode-swarm",
|
|
18584
|
-
version: "7.0.
|
|
18914
|
+
version: "7.0.3",
|
|
18585
18915
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
18586
18916
|
main: "dist/index.js",
|
|
18587
18917
|
types: "dist/index.d.ts",
|
|
@@ -18626,7 +18956,8 @@ var package_default = {
|
|
|
18626
18956
|
format: "biome format . --write",
|
|
18627
18957
|
check: "biome check --write .",
|
|
18628
18958
|
dev: "bun run build && opencode",
|
|
18629
|
-
prepublishOnly: "bun run build"
|
|
18959
|
+
prepublishOnly: "bun run build",
|
|
18960
|
+
"repro:704": "node scripts/repro-704.mjs"
|
|
18630
18961
|
},
|
|
18631
18962
|
dependencies: {
|
|
18632
18963
|
"@opencode-ai/plugin": "^1.1.53",
|
|
@@ -18652,12 +18983,12 @@ var package_default = {
|
|
|
18652
18983
|
init_utils2();
|
|
18653
18984
|
init_manager();
|
|
18654
18985
|
init_spec_hash();
|
|
18655
|
-
import { promises as
|
|
18986
|
+
import { promises as fsPromises3 } from "fs";
|
|
18656
18987
|
async function handleAcknowledgeSpecDriftCommand(directory, _args) {
|
|
18657
18988
|
const specStalenessPath = validateSwarmPath(directory, "spec-staleness.json");
|
|
18658
18989
|
let stalenessContent;
|
|
18659
18990
|
try {
|
|
18660
|
-
stalenessContent = await
|
|
18991
|
+
stalenessContent = await fsPromises3.readFile(specStalenessPath, "utf-8");
|
|
18661
18992
|
} catch (error49) {
|
|
18662
18993
|
if (error49?.code === "ENOENT") {
|
|
18663
18994
|
return "No spec drift detected.";
|
|
@@ -18668,11 +18999,11 @@ async function handleAcknowledgeSpecDriftCommand(directory, _args) {
|
|
|
18668
18999
|
try {
|
|
18669
19000
|
stalenessData = JSON.parse(stalenessContent);
|
|
18670
19001
|
} catch {
|
|
18671
|
-
await
|
|
19002
|
+
await fsPromises3.unlink(specStalenessPath).catch(() => {});
|
|
18672
19003
|
return "Spec staleness file was corrupted. It has been removed.";
|
|
18673
19004
|
}
|
|
18674
19005
|
const { planTitle, phase } = stalenessData;
|
|
18675
|
-
await
|
|
19006
|
+
await fsPromises3.unlink(specStalenessPath);
|
|
18676
19007
|
let currentHash = null;
|
|
18677
19008
|
let planUpdateSkipped = false;
|
|
18678
19009
|
try {
|
|
@@ -18698,7 +19029,7 @@ async function handleAcknowledgeSpecDriftCommand(directory, _args) {
|
|
|
18698
19029
|
};
|
|
18699
19030
|
let eventWriteFailed = false;
|
|
18700
19031
|
try {
|
|
18701
|
-
await
|
|
19032
|
+
await fsPromises3.appendFile(eventsPath, `${JSON.stringify(acknowledgmentEvent)}
|
|
18702
19033
|
`, "utf-8");
|
|
18703
19034
|
} catch (appendError) {
|
|
18704
19035
|
console.error("[acknowledge-spec-drift] Failed to write acknowledgment event:", appendError instanceof Error ? appendError.message : String(appendError));
|
|
@@ -19726,11 +20057,11 @@ function handleAgentsCommand(agents, guardrails) {
|
|
|
19726
20057
|
const temp = agent.config.temperature !== undefined ? agent.config.temperature.toString() : "default";
|
|
19727
20058
|
const tools = agent.config.tools || {};
|
|
19728
20059
|
const isReadOnly = tools.write === false || tools.edit === false;
|
|
19729
|
-
const
|
|
20060
|
+
const access2 = isReadOnly ? "\uD83D\uDD12 read-only" : "\u270F\uFE0F read-write";
|
|
19730
20061
|
const desc = agent.description || agent.config.description || "";
|
|
19731
20062
|
const hasCustomProfile = guardrails?.profiles?.[key] !== undefined;
|
|
19732
20063
|
const profileIndicator = hasCustomProfile ? " | \u26A1 custom limits" : "";
|
|
19733
|
-
lines.push(`- **${key}** | model: \`${model}\` | temp: ${temp} | ${
|
|
20064
|
+
lines.push(`- **${key}** | model: \`${model}\` | temp: ${temp} | ${access2}${profileIndicator}`);
|
|
19734
20065
|
if (desc) {
|
|
19735
20066
|
lines.push(` ${desc}`);
|
|
19736
20067
|
}
|
|
@@ -19780,11 +20111,11 @@ async function handleAnalyzeCommand(_directory, args) {
|
|
|
19780
20111
|
// src/config/loader.ts
|
|
19781
20112
|
import * as fs2 from "fs";
|
|
19782
20113
|
import * as os2 from "os";
|
|
19783
|
-
import * as
|
|
20114
|
+
import * as path5 from "path";
|
|
19784
20115
|
var CONFIG_FILENAME = "opencode-swarm.json";
|
|
19785
20116
|
var MAX_CONFIG_FILE_BYTES = 102400;
|
|
19786
20117
|
function getUserConfigDir() {
|
|
19787
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
20118
|
+
return process.env.XDG_CONFIG_HOME || path5.join(os2.homedir(), ".config");
|
|
19788
20119
|
}
|
|
19789
20120
|
function loadRawConfigFromPath(configPath) {
|
|
19790
20121
|
try {
|
|
@@ -19843,8 +20174,8 @@ function migratePresetsConfig(raw) {
|
|
|
19843
20174
|
return raw;
|
|
19844
20175
|
}
|
|
19845
20176
|
function loadPluginConfig(directory) {
|
|
19846
|
-
const userConfigPath =
|
|
19847
|
-
const projectConfigPath =
|
|
20177
|
+
const userConfigPath = path5.join(getUserConfigDir(), "opencode", CONFIG_FILENAME);
|
|
20178
|
+
const projectConfigPath = path5.join(directory, ".opencode", CONFIG_FILENAME);
|
|
19848
20179
|
const userResult = loadRawConfigFromPath(userConfigPath);
|
|
19849
20180
|
const projectResult = loadRawConfigFromPath(projectConfigPath);
|
|
19850
20181
|
const rawUserConfig = userResult.config;
|
|
@@ -19881,8 +20212,8 @@ function loadPluginConfig(directory) {
|
|
|
19881
20212
|
return result.data;
|
|
19882
20213
|
}
|
|
19883
20214
|
function loadPluginConfigWithMeta(directory) {
|
|
19884
|
-
const userConfigPath =
|
|
19885
|
-
const projectConfigPath =
|
|
20215
|
+
const userConfigPath = path5.join(getUserConfigDir(), "opencode", CONFIG_FILENAME);
|
|
20216
|
+
const projectConfigPath = path5.join(directory, ".opencode", CONFIG_FILENAME);
|
|
19886
20217
|
const userResult = loadRawConfigFromPath(userConfigPath);
|
|
19887
20218
|
const projectResult = loadRawConfigFromPath(projectConfigPath);
|
|
19888
20219
|
const loadedFromFile = userResult.fileExisted || projectResult.fileExisted;
|
|
@@ -19973,7 +20304,7 @@ import { createHash as createHash3 } from "crypto";
|
|
|
19973
20304
|
// src/db/project-db.ts
|
|
19974
20305
|
import { existsSync as existsSync5, mkdirSync as mkdirSync4 } from "fs";
|
|
19975
20306
|
import { createRequire } from "module";
|
|
19976
|
-
import { join as
|
|
20307
|
+
import { join as join8, resolve as resolve5 } from "path";
|
|
19977
20308
|
var _DatabaseCtor = null;
|
|
19978
20309
|
function loadDatabaseCtor() {
|
|
19979
20310
|
if (_DatabaseCtor)
|
|
@@ -20040,7 +20371,7 @@ function runProjectMigrations(db) {
|
|
|
20040
20371
|
}
|
|
20041
20372
|
}
|
|
20042
20373
|
function projectDbPath(directory) {
|
|
20043
|
-
return
|
|
20374
|
+
return join8(resolve5(directory), ".swarm", "swarm.db");
|
|
20044
20375
|
}
|
|
20045
20376
|
function projectDbExists(directory) {
|
|
20046
20377
|
return existsSync5(projectDbPath(directory));
|
|
@@ -20050,10 +20381,10 @@ function getProjectDb(directory) {
|
|
|
20050
20381
|
const existing = _projectDbs.get(key);
|
|
20051
20382
|
if (existing)
|
|
20052
20383
|
return existing;
|
|
20053
|
-
const swarmDir =
|
|
20384
|
+
const swarmDir = join8(key, ".swarm");
|
|
20054
20385
|
mkdirSync4(swarmDir, { recursive: true });
|
|
20055
20386
|
const Db = loadDatabaseCtor();
|
|
20056
|
-
const db = new Db(
|
|
20387
|
+
const db = new Db(join8(swarmDir, "swarm.db"));
|
|
20057
20388
|
db.run("PRAGMA journal_mode = WAL;");
|
|
20058
20389
|
db.run("PRAGMA synchronous = NORMAL;");
|
|
20059
20390
|
db.run("PRAGMA busy_timeout = 5000;");
|
|
@@ -20603,9 +20934,10 @@ var warnedAgents = new Set;
|
|
|
20603
20934
|
init_manager();
|
|
20604
20935
|
|
|
20605
20936
|
// src/scope/scope-persistence.ts
|
|
20937
|
+
init_bun_compat();
|
|
20606
20938
|
var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
|
|
20607
20939
|
import * as fs5 from "fs";
|
|
20608
|
-
import * as
|
|
20940
|
+
import * as path8 from "path";
|
|
20609
20941
|
var DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;
|
|
20610
20942
|
var LOCK_STALE_MS = 30 * 1000;
|
|
20611
20943
|
var SCOPES_DIR = ".swarm/scopes";
|
|
@@ -20636,7 +20968,7 @@ var WINDOWS_RESERVED = new Set([
|
|
|
20636
20968
|
"LPT9"
|
|
20637
20969
|
]);
|
|
20638
20970
|
function getScopesDir(directory) {
|
|
20639
|
-
return
|
|
20971
|
+
return path8.join(directory, SCOPES_DIR);
|
|
20640
20972
|
}
|
|
20641
20973
|
function clearAllScopes(directory) {
|
|
20642
20974
|
try {
|
|
@@ -20647,6 +20979,7 @@ function clearAllScopes(directory) {
|
|
|
20647
20979
|
// src/hooks/guardrails.ts
|
|
20648
20980
|
init_telemetry();
|
|
20649
20981
|
init_utils();
|
|
20982
|
+
init_bun_compat();
|
|
20650
20983
|
init_logger();
|
|
20651
20984
|
|
|
20652
20985
|
// src/hooks/conflict-resolution.ts
|
|
@@ -21161,7 +21494,7 @@ init_zod();
|
|
|
21161
21494
|
init_zod();
|
|
21162
21495
|
import * as child_process from "child_process";
|
|
21163
21496
|
import * as fs6 from "fs";
|
|
21164
|
-
import * as
|
|
21497
|
+
import * as path9 from "path";
|
|
21165
21498
|
|
|
21166
21499
|
// node_modules/@opencode-ai/plugin/node_modules/zod/v4/classic/external.js
|
|
21167
21500
|
var exports_external2 = {};
|
|
@@ -21892,10 +22225,10 @@ function mergeDefs2(...defs) {
|
|
|
21892
22225
|
function cloneDef2(schema) {
|
|
21893
22226
|
return mergeDefs2(schema._zod.def);
|
|
21894
22227
|
}
|
|
21895
|
-
function getElementAtPath2(obj,
|
|
21896
|
-
if (!
|
|
22228
|
+
function getElementAtPath2(obj, path9) {
|
|
22229
|
+
if (!path9)
|
|
21897
22230
|
return obj;
|
|
21898
|
-
return
|
|
22231
|
+
return path9.reduce((acc, key) => acc?.[key], obj);
|
|
21899
22232
|
}
|
|
21900
22233
|
function promiseAllObject2(promisesObj) {
|
|
21901
22234
|
const keys = Object.keys(promisesObj);
|
|
@@ -22254,11 +22587,11 @@ function aborted2(x, startIndex = 0) {
|
|
|
22254
22587
|
}
|
|
22255
22588
|
return false;
|
|
22256
22589
|
}
|
|
22257
|
-
function prefixIssues2(
|
|
22590
|
+
function prefixIssues2(path9, issues) {
|
|
22258
22591
|
return issues.map((iss) => {
|
|
22259
22592
|
var _a2;
|
|
22260
22593
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
22261
|
-
iss.path.unshift(
|
|
22594
|
+
iss.path.unshift(path9);
|
|
22262
22595
|
return iss;
|
|
22263
22596
|
});
|
|
22264
22597
|
}
|
|
@@ -22426,7 +22759,7 @@ function treeifyError2(error49, _mapper) {
|
|
|
22426
22759
|
return issue3.message;
|
|
22427
22760
|
};
|
|
22428
22761
|
const result = { errors: [] };
|
|
22429
|
-
const processError = (error50,
|
|
22762
|
+
const processError = (error50, path9 = []) => {
|
|
22430
22763
|
var _a2, _b;
|
|
22431
22764
|
for (const issue3 of error50.issues) {
|
|
22432
22765
|
if (issue3.code === "invalid_union" && issue3.errors.length) {
|
|
@@ -22436,7 +22769,7 @@ function treeifyError2(error49, _mapper) {
|
|
|
22436
22769
|
} else if (issue3.code === "invalid_element") {
|
|
22437
22770
|
processError({ issues: issue3.issues }, issue3.path);
|
|
22438
22771
|
} else {
|
|
22439
|
-
const fullpath = [...
|
|
22772
|
+
const fullpath = [...path9, ...issue3.path];
|
|
22440
22773
|
if (fullpath.length === 0) {
|
|
22441
22774
|
result.errors.push(mapper(issue3));
|
|
22442
22775
|
continue;
|
|
@@ -22468,8 +22801,8 @@ function treeifyError2(error49, _mapper) {
|
|
|
22468
22801
|
}
|
|
22469
22802
|
function toDotPath2(_path) {
|
|
22470
22803
|
const segs = [];
|
|
22471
|
-
const
|
|
22472
|
-
for (const seg of
|
|
22804
|
+
const path9 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
22805
|
+
for (const seg of path9) {
|
|
22473
22806
|
if (typeof seg === "number")
|
|
22474
22807
|
segs.push(`[${seg}]`);
|
|
22475
22808
|
else if (typeof seg === "symbol")
|
|
@@ -33567,7 +33900,7 @@ function validateLabel(label) {
|
|
|
33567
33900
|
return null;
|
|
33568
33901
|
}
|
|
33569
33902
|
function getCheckpointLogPath(directory) {
|
|
33570
|
-
return
|
|
33903
|
+
return path9.join(directory, CHECKPOINT_LOG_PATH);
|
|
33571
33904
|
}
|
|
33572
33905
|
function readCheckpointLog(directory) {
|
|
33573
33906
|
const logPath = getCheckpointLogPath(directory);
|
|
@@ -33585,7 +33918,7 @@ function readCheckpointLog(directory) {
|
|
|
33585
33918
|
}
|
|
33586
33919
|
function writeCheckpointLog(log2, directory) {
|
|
33587
33920
|
const logPath = getCheckpointLogPath(directory);
|
|
33588
|
-
const dir =
|
|
33921
|
+
const dir = path9.dirname(logPath);
|
|
33589
33922
|
if (!fs6.existsSync(dir)) {
|
|
33590
33923
|
fs6.mkdirSync(dir, { recursive: true });
|
|
33591
33924
|
}
|
|
@@ -33940,7 +34273,7 @@ async function handleClarifyCommand(_directory, args) {
|
|
|
33940
34273
|
|
|
33941
34274
|
// src/commands/close.ts
|
|
33942
34275
|
import { promises as fs7 } from "fs";
|
|
33943
|
-
import
|
|
34276
|
+
import path13 from "path";
|
|
33944
34277
|
init_manager2();
|
|
33945
34278
|
|
|
33946
34279
|
// src/git/branch.ts
|
|
@@ -34189,36 +34522,36 @@ function resetToRemoteBranch(cwd, options) {
|
|
|
34189
34522
|
// src/hooks/knowledge-store.ts
|
|
34190
34523
|
var import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
|
|
34191
34524
|
import { existsSync as existsSync7 } from "fs";
|
|
34192
|
-
import { appendFile as appendFile2, mkdir, readFile as
|
|
34525
|
+
import { appendFile as appendFile2, mkdir as mkdir2, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
34193
34526
|
import * as os3 from "os";
|
|
34194
|
-
import * as
|
|
34527
|
+
import * as path10 from "path";
|
|
34195
34528
|
function resolveSwarmKnowledgePath(directory) {
|
|
34196
|
-
return
|
|
34529
|
+
return path10.join(directory, ".swarm", "knowledge.jsonl");
|
|
34197
34530
|
}
|
|
34198
34531
|
function resolveSwarmRejectedPath(directory) {
|
|
34199
|
-
return
|
|
34532
|
+
return path10.join(directory, ".swarm", "knowledge-rejected.jsonl");
|
|
34200
34533
|
}
|
|
34201
34534
|
function resolveHiveKnowledgePath() {
|
|
34202
34535
|
const platform = process.platform;
|
|
34203
34536
|
const home = process.env.HOME || os3.homedir();
|
|
34204
34537
|
let dataDir;
|
|
34205
34538
|
if (platform === "win32") {
|
|
34206
|
-
dataDir =
|
|
34539
|
+
dataDir = path10.join(process.env.LOCALAPPDATA || path10.join(home, "AppData", "Local"), "opencode-swarm", "Data");
|
|
34207
34540
|
} else if (platform === "darwin") {
|
|
34208
|
-
dataDir =
|
|
34541
|
+
dataDir = path10.join(home, "Library", "Application Support", "opencode-swarm");
|
|
34209
34542
|
} else {
|
|
34210
|
-
dataDir =
|
|
34543
|
+
dataDir = path10.join(process.env.XDG_DATA_HOME || path10.join(home, ".local", "share"), "opencode-swarm");
|
|
34211
34544
|
}
|
|
34212
|
-
return
|
|
34545
|
+
return path10.join(dataDir, "shared-learnings.jsonl");
|
|
34213
34546
|
}
|
|
34214
34547
|
function resolveHiveRejectedPath() {
|
|
34215
34548
|
const hivePath = resolveHiveKnowledgePath();
|
|
34216
|
-
return
|
|
34549
|
+
return path10.join(path10.dirname(hivePath), "shared-learnings-rejected.jsonl");
|
|
34217
34550
|
}
|
|
34218
34551
|
async function readKnowledge(filePath) {
|
|
34219
34552
|
if (!existsSync7(filePath))
|
|
34220
34553
|
return [];
|
|
34221
|
-
const content = await
|
|
34554
|
+
const content = await readFile3(filePath, "utf-8");
|
|
34222
34555
|
const results = [];
|
|
34223
34556
|
for (const line of content.split(`
|
|
34224
34557
|
`)) {
|
|
@@ -34237,13 +34570,13 @@ async function readRejectedLessons(directory) {
|
|
|
34237
34570
|
return readKnowledge(resolveSwarmRejectedPath(directory));
|
|
34238
34571
|
}
|
|
34239
34572
|
async function appendKnowledge(filePath, entry) {
|
|
34240
|
-
await
|
|
34573
|
+
await mkdir2(path10.dirname(filePath), { recursive: true });
|
|
34241
34574
|
await appendFile2(filePath, `${JSON.stringify(entry)}
|
|
34242
34575
|
`, "utf-8");
|
|
34243
34576
|
}
|
|
34244
34577
|
async function rewriteKnowledge(filePath, entries) {
|
|
34245
|
-
const dir =
|
|
34246
|
-
await
|
|
34578
|
+
const dir = path10.dirname(filePath);
|
|
34579
|
+
await mkdir2(dir, { recursive: true });
|
|
34247
34580
|
let release = null;
|
|
34248
34581
|
try {
|
|
34249
34582
|
release = await import_proper_lockfile3.default.lock(dir, {
|
|
@@ -34253,7 +34586,7 @@ async function rewriteKnowledge(filePath, entries) {
|
|
|
34253
34586
|
const content = entries.map((e) => JSON.stringify(e)).join(`
|
|
34254
34587
|
`) + (entries.length > 0 ? `
|
|
34255
34588
|
` : "");
|
|
34256
|
-
await
|
|
34589
|
+
await writeFile3(filePath, content, "utf-8");
|
|
34257
34590
|
} finally {
|
|
34258
34591
|
if (release) {
|
|
34259
34592
|
try {
|
|
@@ -34352,8 +34685,8 @@ function inferTags(lesson) {
|
|
|
34352
34685
|
|
|
34353
34686
|
// src/hooks/knowledge-validator.ts
|
|
34354
34687
|
var import_proper_lockfile4 = __toESM(require_proper_lockfile(), 1);
|
|
34355
|
-
import { appendFile as appendFile3, mkdir as
|
|
34356
|
-
import * as
|
|
34688
|
+
import { appendFile as appendFile3, mkdir as mkdir3, writeFile as writeFile4 } from "fs/promises";
|
|
34689
|
+
import * as path11 from "path";
|
|
34357
34690
|
var DANGEROUS_COMMAND_PATTERNS = [
|
|
34358
34691
|
/\brm\s+-rf\b/,
|
|
34359
34692
|
/\bsudo\s+rm\b/,
|
|
@@ -34608,11 +34941,11 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
|
|
|
34608
34941
|
return;
|
|
34609
34942
|
}
|
|
34610
34943
|
const sanitizedReason = reason.slice(0, 500).replace(/[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f\x0d]/g, "");
|
|
34611
|
-
const knowledgePath =
|
|
34612
|
-
const quarantinePath =
|
|
34613
|
-
const rejectedPath =
|
|
34614
|
-
const swarmDir =
|
|
34615
|
-
await
|
|
34944
|
+
const knowledgePath = path11.join(directory, ".swarm", "knowledge.jsonl");
|
|
34945
|
+
const quarantinePath = path11.join(directory, ".swarm", "knowledge-quarantined.jsonl");
|
|
34946
|
+
const rejectedPath = path11.join(directory, ".swarm", "knowledge-rejected.jsonl");
|
|
34947
|
+
const swarmDir = path11.join(directory, ".swarm");
|
|
34948
|
+
await mkdir3(swarmDir, { recursive: true });
|
|
34616
34949
|
let release;
|
|
34617
34950
|
try {
|
|
34618
34951
|
release = await import_proper_lockfile4.default.lock(swarmDir, {
|
|
@@ -34633,7 +34966,7 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
|
|
|
34633
34966
|
const jsonlContent = remaining.length > 0 ? `${remaining.map((e) => JSON.stringify(e)).join(`
|
|
34634
34967
|
`)}
|
|
34635
34968
|
` : "";
|
|
34636
|
-
await
|
|
34969
|
+
await writeFile4(knowledgePath, jsonlContent, "utf-8");
|
|
34637
34970
|
await appendFile3(quarantinePath, `${JSON.stringify(quarantined)}
|
|
34638
34971
|
`, "utf-8");
|
|
34639
34972
|
const quarantinedEntries = await readKnowledge(quarantinePath);
|
|
@@ -34642,7 +34975,7 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
|
|
|
34642
34975
|
const capContent = trimmed.length > 0 ? `${trimmed.map((e) => JSON.stringify(e)).join(`
|
|
34643
34976
|
`)}
|
|
34644
34977
|
` : "";
|
|
34645
|
-
await
|
|
34978
|
+
await writeFile4(quarantinePath, capContent, "utf-8");
|
|
34646
34979
|
}
|
|
34647
34980
|
const rejectedRecord = {
|
|
34648
34981
|
id: entryId,
|
|
@@ -34668,11 +35001,11 @@ async function restoreEntry(directory, entryId) {
|
|
|
34668
35001
|
console.warn("[knowledge-validator] restoreEntry: invalid entryId rejected");
|
|
34669
35002
|
return;
|
|
34670
35003
|
}
|
|
34671
|
-
const knowledgePath =
|
|
34672
|
-
const quarantinePath =
|
|
34673
|
-
const rejectedPath =
|
|
34674
|
-
const swarmDir =
|
|
34675
|
-
await
|
|
35004
|
+
const knowledgePath = path11.join(directory, ".swarm", "knowledge.jsonl");
|
|
35005
|
+
const quarantinePath = path11.join(directory, ".swarm", "knowledge-quarantined.jsonl");
|
|
35006
|
+
const rejectedPath = path11.join(directory, ".swarm", "knowledge-rejected.jsonl");
|
|
35007
|
+
const swarmDir = path11.join(directory, ".swarm");
|
|
35008
|
+
await mkdir3(swarmDir, { recursive: true });
|
|
34676
35009
|
let release;
|
|
34677
35010
|
try {
|
|
34678
35011
|
release = await import_proper_lockfile4.default.lock(swarmDir, {
|
|
@@ -34688,7 +35021,7 @@ async function restoreEntry(directory, entryId) {
|
|
|
34688
35021
|
const jsonlContent = remaining.length > 0 ? `${remaining.map((e) => JSON.stringify(e)).join(`
|
|
34689
35022
|
`)}
|
|
34690
35023
|
` : "";
|
|
34691
|
-
await
|
|
35024
|
+
await writeFile4(quarantinePath, jsonlContent, "utf-8");
|
|
34692
35025
|
await appendFile3(knowledgePath, `${JSON.stringify(original)}
|
|
34693
35026
|
`, "utf-8");
|
|
34694
35027
|
const rejectedEntries = await readKnowledge(rejectedPath);
|
|
@@ -34696,7 +35029,7 @@ async function restoreEntry(directory, entryId) {
|
|
|
34696
35029
|
const rejectedContent = filtered.length > 0 ? `${filtered.map((e) => JSON.stringify(e)).join(`
|
|
34697
35030
|
`)}
|
|
34698
35031
|
` : "";
|
|
34699
|
-
await
|
|
35032
|
+
await writeFile4(rejectedPath, rejectedContent, "utf-8");
|
|
34700
35033
|
} finally {
|
|
34701
35034
|
if (release) {
|
|
34702
35035
|
await release();
|
|
@@ -34829,8 +35162,9 @@ init_utils2();
|
|
|
34829
35162
|
// src/session/snapshot-writer.ts
|
|
34830
35163
|
init_utils2();
|
|
34831
35164
|
import { mkdirSync as mkdirSync7, renameSync as renameSync5 } from "fs";
|
|
34832
|
-
import * as
|
|
35165
|
+
import * as path12 from "path";
|
|
34833
35166
|
init_utils();
|
|
35167
|
+
init_bun_compat();
|
|
34834
35168
|
var _writeInFlight = Promise.resolve();
|
|
34835
35169
|
function serializeAgentSession(s) {
|
|
34836
35170
|
const gateLog = {};
|
|
@@ -34921,10 +35255,10 @@ async function writeSnapshot(directory, state) {
|
|
|
34921
35255
|
}
|
|
34922
35256
|
const content = JSON.stringify(snapshot, null, 2);
|
|
34923
35257
|
const resolvedPath = validateSwarmPath(directory, "session/state.json");
|
|
34924
|
-
const dir =
|
|
35258
|
+
const dir = path12.dirname(resolvedPath);
|
|
34925
35259
|
mkdirSync7(dir, { recursive: true });
|
|
34926
35260
|
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
34927
|
-
await
|
|
35261
|
+
await bunWrite(tempPath, content);
|
|
34928
35262
|
renameSync5(tempPath, resolvedPath);
|
|
34929
35263
|
} catch (error93) {
|
|
34930
35264
|
log("[snapshot-writer] write failed", {
|
|
@@ -35334,10 +35668,10 @@ function guaranteeAllPlansComplete(planData) {
|
|
|
35334
35668
|
}
|
|
35335
35669
|
async function handleCloseCommand(directory, args) {
|
|
35336
35670
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
35337
|
-
const swarmDir =
|
|
35671
|
+
const swarmDir = path13.join(directory, ".swarm");
|
|
35338
35672
|
let planExists = false;
|
|
35339
35673
|
let planData = {
|
|
35340
|
-
title:
|
|
35674
|
+
title: path13.basename(directory) || "Ad-hoc session",
|
|
35341
35675
|
phases: []
|
|
35342
35676
|
};
|
|
35343
35677
|
try {
|
|
@@ -35442,7 +35776,7 @@ async function handleCloseCommand(directory, args) {
|
|
|
35442
35776
|
warnings.push(`Session retrospective write threw: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
|
|
35443
35777
|
}
|
|
35444
35778
|
}
|
|
35445
|
-
const lessonsFilePath =
|
|
35779
|
+
const lessonsFilePath = path13.join(swarmDir, "close-lessons.md");
|
|
35446
35780
|
let explicitLessons = [];
|
|
35447
35781
|
try {
|
|
35448
35782
|
const lessonsText = await fs7.readFile(lessonsFilePath, "utf-8");
|
|
@@ -35451,11 +35785,11 @@ async function handleCloseCommand(directory, args) {
|
|
|
35451
35785
|
} catch {}
|
|
35452
35786
|
const retroLessons = [];
|
|
35453
35787
|
try {
|
|
35454
|
-
const evidenceDir =
|
|
35788
|
+
const evidenceDir = path13.join(swarmDir, "evidence");
|
|
35455
35789
|
const evidenceEntries = await fs7.readdir(evidenceDir);
|
|
35456
35790
|
const retroDirs = evidenceEntries.filter((e) => e.startsWith("retro-")).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
|
|
35457
35791
|
for (const retroDir of retroDirs) {
|
|
35458
|
-
const evidencePath =
|
|
35792
|
+
const evidencePath = path13.join(evidenceDir, retroDir, "evidence.json");
|
|
35459
35793
|
try {
|
|
35460
35794
|
const content = await fs7.readFile(evidencePath, "utf-8");
|
|
35461
35795
|
const parsed = JSON.parse(content);
|
|
@@ -35509,15 +35843,15 @@ async function handleCloseCommand(directory, args) {
|
|
|
35509
35843
|
}
|
|
35510
35844
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
35511
35845
|
const suffix = Math.random().toString(36).slice(2, 8);
|
|
35512
|
-
const archiveDir =
|
|
35846
|
+
const archiveDir = path13.join(swarmDir, "archive", `swarm-${timestamp}-${suffix}`);
|
|
35513
35847
|
let archiveResult = "";
|
|
35514
35848
|
let archivedFileCount = 0;
|
|
35515
35849
|
const archivedActiveStateFiles = new Set;
|
|
35516
35850
|
try {
|
|
35517
35851
|
await fs7.mkdir(archiveDir, { recursive: true });
|
|
35518
35852
|
for (const artifact of ARCHIVE_ARTIFACTS) {
|
|
35519
|
-
const srcPath =
|
|
35520
|
-
const destPath =
|
|
35853
|
+
const srcPath = path13.join(swarmDir, artifact);
|
|
35854
|
+
const destPath = path13.join(archiveDir, artifact);
|
|
35521
35855
|
try {
|
|
35522
35856
|
await fs7.copyFile(srcPath, destPath);
|
|
35523
35857
|
archivedFileCount++;
|
|
@@ -35526,22 +35860,22 @@ async function handleCloseCommand(directory, args) {
|
|
|
35526
35860
|
}
|
|
35527
35861
|
} catch {}
|
|
35528
35862
|
}
|
|
35529
|
-
const evidenceDir =
|
|
35530
|
-
const archiveEvidenceDir =
|
|
35863
|
+
const evidenceDir = path13.join(swarmDir, "evidence");
|
|
35864
|
+
const archiveEvidenceDir = path13.join(archiveDir, "evidence");
|
|
35531
35865
|
try {
|
|
35532
35866
|
const evidenceEntries = await fs7.readdir(evidenceDir);
|
|
35533
35867
|
if (evidenceEntries.length > 0) {
|
|
35534
35868
|
await fs7.mkdir(archiveEvidenceDir, { recursive: true });
|
|
35535
35869
|
for (const entry of evidenceEntries) {
|
|
35536
|
-
const srcEntry =
|
|
35537
|
-
const destEntry =
|
|
35870
|
+
const srcEntry = path13.join(evidenceDir, entry);
|
|
35871
|
+
const destEntry = path13.join(archiveEvidenceDir, entry);
|
|
35538
35872
|
try {
|
|
35539
|
-
const
|
|
35540
|
-
if (
|
|
35873
|
+
const stat2 = await fs7.stat(srcEntry);
|
|
35874
|
+
if (stat2.isDirectory()) {
|
|
35541
35875
|
await fs7.mkdir(destEntry, { recursive: true });
|
|
35542
35876
|
const subEntries = await fs7.readdir(srcEntry);
|
|
35543
35877
|
for (const sub of subEntries) {
|
|
35544
|
-
await fs7.copyFile(
|
|
35878
|
+
await fs7.copyFile(path13.join(srcEntry, sub), path13.join(destEntry, sub)).catch(() => {});
|
|
35545
35879
|
}
|
|
35546
35880
|
} else {
|
|
35547
35881
|
await fs7.copyFile(srcEntry, destEntry);
|
|
@@ -35551,11 +35885,11 @@ async function handleCloseCommand(directory, args) {
|
|
|
35551
35885
|
}
|
|
35552
35886
|
}
|
|
35553
35887
|
} catch {}
|
|
35554
|
-
const sessionStatePath =
|
|
35888
|
+
const sessionStatePath = path13.join(swarmDir, "session", "state.json");
|
|
35555
35889
|
try {
|
|
35556
|
-
const archiveSessionDir =
|
|
35890
|
+
const archiveSessionDir = path13.join(archiveDir, "session");
|
|
35557
35891
|
await fs7.mkdir(archiveSessionDir, { recursive: true });
|
|
35558
|
-
await fs7.copyFile(sessionStatePath,
|
|
35892
|
+
await fs7.copyFile(sessionStatePath, path13.join(archiveSessionDir, "state.json"));
|
|
35559
35893
|
archivedFileCount++;
|
|
35560
35894
|
} catch {}
|
|
35561
35895
|
archiveResult = `Archived ${archivedFileCount} artifact(s) to .swarm/archive/swarm-${timestamp}/`;
|
|
@@ -35578,7 +35912,7 @@ async function handleCloseCommand(directory, args) {
|
|
|
35578
35912
|
warnings.push(`Preserved ${artifact} because it was not successfully archived.`);
|
|
35579
35913
|
continue;
|
|
35580
35914
|
}
|
|
35581
|
-
const filePath =
|
|
35915
|
+
const filePath = path13.join(swarmDir, artifact);
|
|
35582
35916
|
try {
|
|
35583
35917
|
await fs7.unlink(filePath);
|
|
35584
35918
|
cleanedFiles.push(artifact);
|
|
@@ -35592,23 +35926,23 @@ async function handleCloseCommand(directory, args) {
|
|
|
35592
35926
|
const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
|
|
35593
35927
|
for (const backup of configBackups) {
|
|
35594
35928
|
try {
|
|
35595
|
-
await fs7.unlink(
|
|
35929
|
+
await fs7.unlink(path13.join(swarmDir, backup));
|
|
35596
35930
|
configBackupsRemoved++;
|
|
35597
35931
|
} catch {}
|
|
35598
35932
|
}
|
|
35599
35933
|
const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
|
|
35600
35934
|
for (const sibling of ledgerSiblings) {
|
|
35601
35935
|
try {
|
|
35602
|
-
await fs7.unlink(
|
|
35936
|
+
await fs7.unlink(path13.join(swarmDir, sibling));
|
|
35603
35937
|
} catch {}
|
|
35604
35938
|
}
|
|
35605
35939
|
} catch {}
|
|
35606
35940
|
let swarmPlanFilesRemoved = 0;
|
|
35607
35941
|
const candidates = [
|
|
35608
|
-
|
|
35609
|
-
|
|
35610
|
-
|
|
35611
|
-
|
|
35942
|
+
path13.join(directory, ".swarm", "SWARM_PLAN.json"),
|
|
35943
|
+
path13.join(directory, ".swarm", "SWARM_PLAN.md"),
|
|
35944
|
+
path13.join(directory, "SWARM_PLAN.json"),
|
|
35945
|
+
path13.join(directory, "SWARM_PLAN.md")
|
|
35612
35946
|
];
|
|
35613
35947
|
for (const candidate of candidates) {
|
|
35614
35948
|
try {
|
|
@@ -35616,12 +35950,12 @@ async function handleCloseCommand(directory, args) {
|
|
|
35616
35950
|
swarmPlanFilesRemoved++;
|
|
35617
35951
|
} catch (err) {
|
|
35618
35952
|
if (err?.code !== "ENOENT") {
|
|
35619
|
-
warnings.push(`Failed to remove ${
|
|
35953
|
+
warnings.push(`Failed to remove ${path13.basename(candidate)}: ${err instanceof Error ? err.message : String(err)}`);
|
|
35620
35954
|
}
|
|
35621
35955
|
}
|
|
35622
35956
|
}
|
|
35623
35957
|
clearAllScopes(directory);
|
|
35624
|
-
const contextPath =
|
|
35958
|
+
const contextPath = path13.join(swarmDir, "context.md");
|
|
35625
35959
|
const contextContent = [
|
|
35626
35960
|
"# Context",
|
|
35627
35961
|
"",
|
|
@@ -35756,14 +36090,14 @@ ${otherWarnings.map((w) => `- ${w}`).join(`
|
|
|
35756
36090
|
|
|
35757
36091
|
// src/commands/config.ts
|
|
35758
36092
|
import * as os4 from "os";
|
|
35759
|
-
import * as
|
|
36093
|
+
import * as path14 from "path";
|
|
35760
36094
|
function getUserConfigDir2() {
|
|
35761
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
36095
|
+
return process.env.XDG_CONFIG_HOME || path14.join(os4.homedir(), ".config");
|
|
35762
36096
|
}
|
|
35763
36097
|
async function handleConfigCommand(directory, _args) {
|
|
35764
36098
|
const config3 = loadPluginConfig(directory);
|
|
35765
|
-
const userConfigPath =
|
|
35766
|
-
const projectConfigPath =
|
|
36099
|
+
const userConfigPath = path14.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
|
|
36100
|
+
const projectConfigPath = path14.join(directory, ".opencode", "opencode-swarm.json");
|
|
35767
36101
|
const lines = [
|
|
35768
36102
|
"## Swarm Configuration",
|
|
35769
36103
|
"",
|
|
@@ -35849,7 +36183,7 @@ async function handleCouncilCommand(_directory, args) {
|
|
|
35849
36183
|
}
|
|
35850
36184
|
|
|
35851
36185
|
// src/hooks/hive-promoter.ts
|
|
35852
|
-
import
|
|
36186
|
+
import path15 from "path";
|
|
35853
36187
|
|
|
35854
36188
|
// src/background/event-bus.ts
|
|
35855
36189
|
init_utils();
|
|
@@ -35922,6 +36256,7 @@ function getGlobalEventBus() {
|
|
|
35922
36256
|
|
|
35923
36257
|
// src/hooks/curator.ts
|
|
35924
36258
|
init_manager();
|
|
36259
|
+
init_bun_compat();
|
|
35925
36260
|
init_logger();
|
|
35926
36261
|
init_utils2();
|
|
35927
36262
|
|
|
@@ -36105,7 +36440,7 @@ async function promoteToHive(directory, lesson, category) {
|
|
|
36105
36440
|
schema_version: 1,
|
|
36106
36441
|
created_at: new Date().toISOString(),
|
|
36107
36442
|
updated_at: new Date().toISOString(),
|
|
36108
|
-
source_project:
|
|
36443
|
+
source_project: path15.basename(directory) || "unknown",
|
|
36109
36444
|
encounter_score: 1
|
|
36110
36445
|
};
|
|
36111
36446
|
await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
|
|
@@ -36183,14 +36518,14 @@ function formatCurationSummary(summary) {
|
|
|
36183
36518
|
}
|
|
36184
36519
|
|
|
36185
36520
|
// src/commands/dark-matter.ts
|
|
36186
|
-
import
|
|
36521
|
+
import path17 from "path";
|
|
36187
36522
|
|
|
36188
36523
|
// src/tools/co-change-analyzer.ts
|
|
36189
36524
|
init_zod();
|
|
36190
36525
|
import * as child_process3 from "child_process";
|
|
36191
36526
|
import { randomUUID } from "crypto";
|
|
36192
|
-
import { readdir, readFile as
|
|
36193
|
-
import * as
|
|
36527
|
+
import { readdir, readFile as readFile4, stat as stat2 } from "fs/promises";
|
|
36528
|
+
import * as path16 from "path";
|
|
36194
36529
|
import { promisify } from "util";
|
|
36195
36530
|
function getExecFileAsync() {
|
|
36196
36531
|
return promisify(child_process3.execFile);
|
|
@@ -36292,7 +36627,7 @@ async function scanSourceFiles(dir) {
|
|
|
36292
36627
|
try {
|
|
36293
36628
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
36294
36629
|
for (const entry of entries) {
|
|
36295
|
-
const fullPath =
|
|
36630
|
+
const fullPath = path16.join(dir, entry.name);
|
|
36296
36631
|
if (entry.isDirectory()) {
|
|
36297
36632
|
if (skipDirs.has(entry.name)) {
|
|
36298
36633
|
continue;
|
|
@@ -36300,7 +36635,7 @@ async function scanSourceFiles(dir) {
|
|
|
36300
36635
|
const subFiles = await scanSourceFiles(fullPath);
|
|
36301
36636
|
results.push(...subFiles);
|
|
36302
36637
|
} else if (entry.isFile()) {
|
|
36303
|
-
const ext =
|
|
36638
|
+
const ext = path16.extname(entry.name);
|
|
36304
36639
|
if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
|
|
36305
36640
|
results.push(fullPath);
|
|
36306
36641
|
}
|
|
@@ -36314,7 +36649,7 @@ async function getStaticEdges(directory) {
|
|
|
36314
36649
|
const sourceFiles = await scanSourceFiles(directory);
|
|
36315
36650
|
for (const sourceFile of sourceFiles) {
|
|
36316
36651
|
try {
|
|
36317
|
-
const content = await
|
|
36652
|
+
const content = await readFile4(sourceFile, "utf-8");
|
|
36318
36653
|
const importRegex = /(?:import|require)\s*(?:\(?\s*['"`]|.*?from\s+['"`])([^'"`]+)['"`]/g;
|
|
36319
36654
|
for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
|
|
36320
36655
|
const importPath = match[1].trim();
|
|
@@ -36322,8 +36657,8 @@ async function getStaticEdges(directory) {
|
|
|
36322
36657
|
continue;
|
|
36323
36658
|
}
|
|
36324
36659
|
try {
|
|
36325
|
-
const sourceDir =
|
|
36326
|
-
const resolvedPath =
|
|
36660
|
+
const sourceDir = path16.dirname(sourceFile);
|
|
36661
|
+
const resolvedPath = path16.resolve(sourceDir, importPath);
|
|
36327
36662
|
const extensions = [
|
|
36328
36663
|
"",
|
|
36329
36664
|
".ts",
|
|
@@ -36338,7 +36673,7 @@ async function getStaticEdges(directory) {
|
|
|
36338
36673
|
for (const ext of extensions) {
|
|
36339
36674
|
const testPath = resolvedPath + ext;
|
|
36340
36675
|
try {
|
|
36341
|
-
const testStat = await
|
|
36676
|
+
const testStat = await stat2(testPath);
|
|
36342
36677
|
if (testStat.isFile()) {
|
|
36343
36678
|
targetFile = testPath;
|
|
36344
36679
|
break;
|
|
@@ -36348,8 +36683,8 @@ async function getStaticEdges(directory) {
|
|
|
36348
36683
|
if (!targetFile) {
|
|
36349
36684
|
continue;
|
|
36350
36685
|
}
|
|
36351
|
-
const relSource =
|
|
36352
|
-
const relTarget =
|
|
36686
|
+
const relSource = path16.relative(directory, sourceFile).replace(/\\/g, "/");
|
|
36687
|
+
const relTarget = path16.relative(directory, targetFile).replace(/\\/g, "/");
|
|
36353
36688
|
const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
|
|
36354
36689
|
edges.add(key);
|
|
36355
36690
|
} catch {}
|
|
@@ -36361,7 +36696,7 @@ async function getStaticEdges(directory) {
|
|
|
36361
36696
|
function isTestImplementationPair(fileA, fileB) {
|
|
36362
36697
|
const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
|
|
36363
36698
|
const getBaseName = (filePath) => {
|
|
36364
|
-
const base =
|
|
36699
|
+
const base = path16.basename(filePath);
|
|
36365
36700
|
for (const pattern of testPatterns) {
|
|
36366
36701
|
if (base.endsWith(pattern)) {
|
|
36367
36702
|
return base.slice(0, -pattern.length);
|
|
@@ -36371,16 +36706,16 @@ function isTestImplementationPair(fileA, fileB) {
|
|
|
36371
36706
|
};
|
|
36372
36707
|
const baseA = getBaseName(fileA);
|
|
36373
36708
|
const baseB = getBaseName(fileB);
|
|
36374
|
-
return baseA === baseB && baseA !==
|
|
36709
|
+
return baseA === baseB && baseA !== path16.basename(fileA) && baseA !== path16.basename(fileB);
|
|
36375
36710
|
}
|
|
36376
36711
|
function hasSharedPrefix(fileA, fileB) {
|
|
36377
|
-
const dirA =
|
|
36378
|
-
const dirB =
|
|
36712
|
+
const dirA = path16.dirname(fileA);
|
|
36713
|
+
const dirB = path16.dirname(fileB);
|
|
36379
36714
|
if (dirA !== dirB) {
|
|
36380
36715
|
return false;
|
|
36381
36716
|
}
|
|
36382
|
-
const baseA =
|
|
36383
|
-
const baseB =
|
|
36717
|
+
const baseA = path16.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
36718
|
+
const baseB = path16.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
36384
36719
|
if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
|
|
36385
36720
|
return true;
|
|
36386
36721
|
}
|
|
@@ -36434,8 +36769,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
|
|
|
36434
36769
|
const entries = [];
|
|
36435
36770
|
const now = new Date().toISOString();
|
|
36436
36771
|
for (const pair of pairs.slice(0, 10)) {
|
|
36437
|
-
const baseA =
|
|
36438
|
-
const baseB =
|
|
36772
|
+
const baseA = path16.basename(pair.fileA);
|
|
36773
|
+
const baseB = path16.basename(pair.fileB);
|
|
36439
36774
|
let lesson = `Files ${pair.fileA} and ${pair.fileB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
|
|
36440
36775
|
if (lesson.length > 280) {
|
|
36441
36776
|
lesson = `Files ${baseA} and ${baseB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
|
|
@@ -36545,7 +36880,7 @@ async function handleDarkMatterCommand(directory, args) {
|
|
|
36545
36880
|
const output = formatDarkMatterOutput(pairs);
|
|
36546
36881
|
if (pairs.length > 0) {
|
|
36547
36882
|
try {
|
|
36548
|
-
const projectName =
|
|
36883
|
+
const projectName = path17.basename(path17.resolve(directory));
|
|
36549
36884
|
const entries = darkMatterToKnowledgeEntries(pairs, projectName);
|
|
36550
36885
|
if (entries.length > 0) {
|
|
36551
36886
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
@@ -36566,50 +36901,50 @@ async function handleDarkMatterCommand(directory, args) {
|
|
|
36566
36901
|
|
|
36567
36902
|
// src/services/diagnose-service.ts
|
|
36568
36903
|
import * as child_process4 from "child_process";
|
|
36569
|
-
import { existsSync as existsSync9, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as
|
|
36570
|
-
import
|
|
36904
|
+
import { existsSync as existsSync9, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync6 } from "fs";
|
|
36905
|
+
import path19 from "path";
|
|
36571
36906
|
import { fileURLToPath } from "url";
|
|
36572
36907
|
|
|
36573
36908
|
// src/config/cache-paths.ts
|
|
36574
36909
|
import * as os5 from "os";
|
|
36575
|
-
import * as
|
|
36910
|
+
import * as path18 from "path";
|
|
36576
36911
|
function getPluginConfigDir() {
|
|
36577
|
-
return
|
|
36912
|
+
return path18.join(process.env.XDG_CONFIG_HOME || path18.join(os5.homedir(), ".config"), "opencode");
|
|
36578
36913
|
}
|
|
36579
36914
|
function getPluginCachePaths() {
|
|
36580
|
-
const cacheBase = process.env.XDG_CACHE_HOME ||
|
|
36915
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path18.join(os5.homedir(), ".cache");
|
|
36581
36916
|
const configDir = getPluginConfigDir();
|
|
36582
36917
|
const paths = [
|
|
36583
|
-
|
|
36584
|
-
|
|
36585
|
-
|
|
36918
|
+
path18.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
|
|
36919
|
+
path18.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
|
|
36920
|
+
path18.join(configDir, "node_modules", "opencode-swarm")
|
|
36586
36921
|
];
|
|
36587
36922
|
if (process.platform === "darwin") {
|
|
36588
|
-
const libCaches =
|
|
36589
|
-
paths.push(
|
|
36923
|
+
const libCaches = path18.join(os5.homedir(), "Library", "Caches");
|
|
36924
|
+
paths.push(path18.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path18.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
|
|
36590
36925
|
}
|
|
36591
36926
|
if (process.platform === "win32") {
|
|
36592
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
36593
|
-
const appData = process.env.APPDATA ||
|
|
36594
|
-
paths.push(
|
|
36927
|
+
const localAppData = process.env.LOCALAPPDATA || path18.join(os5.homedir(), "AppData", "Local");
|
|
36928
|
+
const appData = process.env.APPDATA || path18.join(os5.homedir(), "AppData", "Roaming");
|
|
36929
|
+
paths.push(path18.join(localAppData, "opencode", "node_modules", "opencode-swarm"), path18.join(localAppData, "opencode", "packages", "opencode-swarm@latest"), path18.join(appData, "opencode", "node_modules", "opencode-swarm"));
|
|
36595
36930
|
}
|
|
36596
36931
|
return paths;
|
|
36597
36932
|
}
|
|
36598
36933
|
function getPluginLockFilePaths() {
|
|
36599
|
-
const cacheBase = process.env.XDG_CACHE_HOME ||
|
|
36934
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path18.join(os5.homedir(), ".cache");
|
|
36600
36935
|
const configDir = getPluginConfigDir();
|
|
36601
36936
|
const paths = [
|
|
36602
|
-
|
|
36603
|
-
|
|
36604
|
-
|
|
36937
|
+
path18.join(cacheBase, "opencode", "bun.lock"),
|
|
36938
|
+
path18.join(cacheBase, "opencode", "bun.lockb"),
|
|
36939
|
+
path18.join(configDir, "package-lock.json")
|
|
36605
36940
|
];
|
|
36606
36941
|
if (process.platform === "darwin") {
|
|
36607
|
-
const libCaches =
|
|
36608
|
-
paths.push(
|
|
36942
|
+
const libCaches = path18.join(os5.homedir(), "Library", "Caches");
|
|
36943
|
+
paths.push(path18.join(libCaches, "opencode", "bun.lock"), path18.join(libCaches, "opencode", "bun.lockb"));
|
|
36609
36944
|
}
|
|
36610
36945
|
if (process.platform === "win32") {
|
|
36611
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
36612
|
-
paths.push(
|
|
36946
|
+
const localAppData = process.env.LOCALAPPDATA || path18.join(os5.homedir(), "AppData", "Local");
|
|
36947
|
+
paths.push(path18.join(localAppData, "opencode", "bun.lock"), path18.join(localAppData, "opencode", "bun.lockb"));
|
|
36613
36948
|
}
|
|
36614
36949
|
return paths;
|
|
36615
36950
|
}
|
|
@@ -36622,22 +36957,22 @@ init_manager();
|
|
|
36622
36957
|
// src/services/version-check.ts
|
|
36623
36958
|
import { existsSync as existsSync8, mkdirSync as mkdirSync8, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
36624
36959
|
import { homedir as homedir5 } from "os";
|
|
36625
|
-
import { join as
|
|
36960
|
+
import { join as join16 } from "path";
|
|
36626
36961
|
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
36627
36962
|
function cacheDir() {
|
|
36628
36963
|
const xdg = process.env.XDG_CACHE_HOME;
|
|
36629
|
-
const base = xdg && xdg.length > 0 ? xdg :
|
|
36630
|
-
return
|
|
36964
|
+
const base = xdg && xdg.length > 0 ? xdg : join16(homedir5(), ".cache");
|
|
36965
|
+
return join16(base, "opencode-swarm");
|
|
36631
36966
|
}
|
|
36632
36967
|
function cacheFile() {
|
|
36633
|
-
return
|
|
36968
|
+
return join16(cacheDir(), "version-check.json");
|
|
36634
36969
|
}
|
|
36635
36970
|
function readVersionCache() {
|
|
36636
36971
|
try {
|
|
36637
|
-
const
|
|
36638
|
-
if (!existsSync8(
|
|
36972
|
+
const path19 = cacheFile();
|
|
36973
|
+
if (!existsSync8(path19))
|
|
36639
36974
|
return null;
|
|
36640
|
-
const raw = readFileSync5(
|
|
36975
|
+
const raw = readFileSync5(path19, "utf-8");
|
|
36641
36976
|
const parsed = JSON.parse(raw);
|
|
36642
36977
|
if (typeof parsed?.checkedAt !== "number")
|
|
36643
36978
|
return null;
|
|
@@ -36903,7 +37238,7 @@ async function checkConfigBackups(directory) {
|
|
|
36903
37238
|
}
|
|
36904
37239
|
async function checkGitRepository(directory) {
|
|
36905
37240
|
try {
|
|
36906
|
-
if (!existsSync9(directory) || !
|
|
37241
|
+
if (!existsSync9(directory) || !statSync6(directory).isDirectory()) {
|
|
36907
37242
|
return {
|
|
36908
37243
|
name: "Git Repository",
|
|
36909
37244
|
status: "\u274C",
|
|
@@ -36967,7 +37302,7 @@ async function checkSpecStaleness(directory, plan) {
|
|
|
36967
37302
|
};
|
|
36968
37303
|
}
|
|
36969
37304
|
async function checkConfigParseability(directory) {
|
|
36970
|
-
const configPath =
|
|
37305
|
+
const configPath = path19.join(directory, ".opencode/opencode-swarm.json");
|
|
36971
37306
|
if (!existsSync9(configPath)) {
|
|
36972
37307
|
return {
|
|
36973
37308
|
name: "Config Parseability",
|
|
@@ -36996,7 +37331,7 @@ function resolveGrammarDir(thisDir) {
|
|
|
36996
37331
|
const normalized = thisDir.replace(/\\/g, "/");
|
|
36997
37332
|
const isSource = normalized.endsWith("/src/services");
|
|
36998
37333
|
const isCliBundle = normalized.endsWith("/cli");
|
|
36999
|
-
return isSource || isCliBundle ?
|
|
37334
|
+
return isSource || isCliBundle ? path19.join(thisDir, "..", "lang", "grammars") : path19.join(thisDir, "lang", "grammars");
|
|
37000
37335
|
}
|
|
37001
37336
|
async function checkGrammarWasmFiles() {
|
|
37002
37337
|
const grammarFiles = [
|
|
@@ -37020,14 +37355,14 @@ async function checkGrammarWasmFiles() {
|
|
|
37020
37355
|
"tree-sitter-ini.wasm",
|
|
37021
37356
|
"tree-sitter-regex.wasm"
|
|
37022
37357
|
];
|
|
37023
|
-
const thisDir =
|
|
37358
|
+
const thisDir = path19.dirname(fileURLToPath(import.meta.url));
|
|
37024
37359
|
const grammarDir = resolveGrammarDir(thisDir);
|
|
37025
37360
|
const missing = [];
|
|
37026
|
-
if (!existsSync9(
|
|
37361
|
+
if (!existsSync9(path19.join(grammarDir, "tree-sitter.wasm"))) {
|
|
37027
37362
|
missing.push("tree-sitter.wasm (core runtime)");
|
|
37028
37363
|
}
|
|
37029
37364
|
for (const file3 of grammarFiles) {
|
|
37030
|
-
if (!existsSync9(
|
|
37365
|
+
if (!existsSync9(path19.join(grammarDir, file3))) {
|
|
37031
37366
|
missing.push(file3);
|
|
37032
37367
|
}
|
|
37033
37368
|
}
|
|
@@ -37045,7 +37380,7 @@ async function checkGrammarWasmFiles() {
|
|
|
37045
37380
|
};
|
|
37046
37381
|
}
|
|
37047
37382
|
async function checkCheckpointManifest(directory) {
|
|
37048
|
-
const manifestPath =
|
|
37383
|
+
const manifestPath = path19.join(directory, ".swarm/checkpoints.json");
|
|
37049
37384
|
if (!existsSync9(manifestPath)) {
|
|
37050
37385
|
return {
|
|
37051
37386
|
name: "Checkpoint Manifest",
|
|
@@ -37097,7 +37432,7 @@ async function checkCheckpointManifest(directory) {
|
|
|
37097
37432
|
}
|
|
37098
37433
|
}
|
|
37099
37434
|
async function checkEventStreamIntegrity(directory) {
|
|
37100
|
-
const eventsPath =
|
|
37435
|
+
const eventsPath = path19.join(directory, ".swarm/events.jsonl");
|
|
37101
37436
|
if (!existsSync9(eventsPath)) {
|
|
37102
37437
|
return {
|
|
37103
37438
|
name: "Event Stream",
|
|
@@ -37138,7 +37473,7 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
37138
37473
|
}
|
|
37139
37474
|
}
|
|
37140
37475
|
async function checkSteeringDirectives(directory) {
|
|
37141
|
-
const eventsPath =
|
|
37476
|
+
const eventsPath = path19.join(directory, ".swarm/events.jsonl");
|
|
37142
37477
|
if (!existsSync9(eventsPath)) {
|
|
37143
37478
|
return {
|
|
37144
37479
|
name: "Steering Directives",
|
|
@@ -37194,7 +37529,7 @@ async function checkCurator(directory) {
|
|
|
37194
37529
|
detail: "Disabled (enable via curator.enabled)"
|
|
37195
37530
|
};
|
|
37196
37531
|
}
|
|
37197
|
-
const summaryPath =
|
|
37532
|
+
const summaryPath = path19.join(directory, ".swarm/curator-summary.json");
|
|
37198
37533
|
if (!existsSync9(summaryPath)) {
|
|
37199
37534
|
return {
|
|
37200
37535
|
name: "Curator",
|
|
@@ -37360,7 +37695,7 @@ async function getDiagnoseData(directory) {
|
|
|
37360
37695
|
checks5.push(await checkSteeringDirectives(directory));
|
|
37361
37696
|
checks5.push(await checkCurator(directory));
|
|
37362
37697
|
try {
|
|
37363
|
-
const evidenceDir =
|
|
37698
|
+
const evidenceDir = path19.join(directory, ".swarm", "evidence");
|
|
37364
37699
|
const snapshotFiles = existsSync9(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
|
|
37365
37700
|
if (snapshotFiles.length > 0) {
|
|
37366
37701
|
const latest = snapshotFiles.sort().pop();
|
|
@@ -37398,7 +37733,7 @@ async function getDiagnoseData(directory) {
|
|
|
37398
37733
|
cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
|
|
37399
37734
|
continue;
|
|
37400
37735
|
}
|
|
37401
|
-
const pkgJsonPath =
|
|
37736
|
+
const pkgJsonPath = path19.join(cachePath, "package.json");
|
|
37402
37737
|
try {
|
|
37403
37738
|
const raw = readFileSync6(pkgJsonPath, "utf-8");
|
|
37404
37739
|
const parsed = JSON.parse(raw);
|
|
@@ -37457,15 +37792,15 @@ init_config_doctor();
|
|
|
37457
37792
|
|
|
37458
37793
|
// src/services/tool-doctor.ts
|
|
37459
37794
|
import * as fs10 from "fs";
|
|
37460
|
-
import * as
|
|
37795
|
+
import * as path22 from "path";
|
|
37461
37796
|
|
|
37462
37797
|
// src/build/discovery.ts
|
|
37463
37798
|
import * as fs9 from "fs";
|
|
37464
|
-
import * as
|
|
37799
|
+
import * as path21 from "path";
|
|
37465
37800
|
|
|
37466
37801
|
// src/lang/detector.ts
|
|
37467
|
-
import { access as
|
|
37468
|
-
import { extname as extname2, join as
|
|
37802
|
+
import { access as access3, readdir as readdir2 } from "fs/promises";
|
|
37803
|
+
import { extname as extname2, join as join18 } from "path";
|
|
37469
37804
|
|
|
37470
37805
|
// src/lang/profiles.ts
|
|
37471
37806
|
class LanguageRegistry {
|
|
@@ -38445,7 +38780,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
38445
38780
|
if (detectFile.includes("*") || detectFile.includes("?"))
|
|
38446
38781
|
continue;
|
|
38447
38782
|
try {
|
|
38448
|
-
await
|
|
38783
|
+
await access3(join18(dir, detectFile));
|
|
38449
38784
|
detected.add(profile.id);
|
|
38450
38785
|
break;
|
|
38451
38786
|
} catch {}
|
|
@@ -38466,7 +38801,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
38466
38801
|
const topEntries = await readdir2(projectDir, { withFileTypes: true });
|
|
38467
38802
|
for (const entry of topEntries) {
|
|
38468
38803
|
if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
|
|
38469
|
-
await scanDir(
|
|
38804
|
+
await scanDir(join18(projectDir, entry.name));
|
|
38470
38805
|
}
|
|
38471
38806
|
}
|
|
38472
38807
|
} catch {}
|
|
@@ -38482,6 +38817,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
38482
38817
|
|
|
38483
38818
|
// src/build/discovery.ts
|
|
38484
38819
|
init_utils();
|
|
38820
|
+
init_bun_compat();
|
|
38485
38821
|
var ECOSYSTEMS = [
|
|
38486
38822
|
{
|
|
38487
38823
|
ecosystem: "node",
|
|
@@ -38600,8 +38936,7 @@ function isCommandAvailable(command) {
|
|
|
38600
38936
|
const isWindows = process.platform === "win32";
|
|
38601
38937
|
const cmd = isWindows ? `${command}.exe` : command;
|
|
38602
38938
|
try {
|
|
38603
|
-
const result =
|
|
38604
|
-
cmd: isWindows ? ["where", cmd] : ["which", cmd],
|
|
38939
|
+
const result = bunSpawnSync(isWindows ? ["where", cmd] : ["which", cmd], {
|
|
38605
38940
|
stdout: "pipe",
|
|
38606
38941
|
stderr: "pipe"
|
|
38607
38942
|
});
|
|
@@ -38625,11 +38960,11 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
38625
38960
|
const regex = simpleGlobToRegex(pattern);
|
|
38626
38961
|
const matches = files.filter((f) => regex.test(f));
|
|
38627
38962
|
if (matches.length > 0) {
|
|
38628
|
-
return
|
|
38963
|
+
return path21.join(dir, matches[0]);
|
|
38629
38964
|
}
|
|
38630
38965
|
} catch {}
|
|
38631
38966
|
} else {
|
|
38632
|
-
const filePath =
|
|
38967
|
+
const filePath = path21.join(workingDir, pattern);
|
|
38633
38968
|
if (fs9.existsSync(filePath)) {
|
|
38634
38969
|
return filePath;
|
|
38635
38970
|
}
|
|
@@ -38638,7 +38973,7 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
38638
38973
|
return null;
|
|
38639
38974
|
}
|
|
38640
38975
|
function getRepoDefinedScripts(workingDir, scripts) {
|
|
38641
|
-
const packageJsonPath =
|
|
38976
|
+
const packageJsonPath = path21.join(workingDir, "package.json");
|
|
38642
38977
|
if (!fs9.existsSync(packageJsonPath)) {
|
|
38643
38978
|
return [];
|
|
38644
38979
|
}
|
|
@@ -38679,7 +39014,7 @@ function findAllBuildFiles(workingDir) {
|
|
|
38679
39014
|
const regex = simpleGlobToRegex(pattern);
|
|
38680
39015
|
findFilesRecursive(workingDir, regex, allBuildFiles);
|
|
38681
39016
|
} else {
|
|
38682
|
-
const filePath =
|
|
39017
|
+
const filePath = path21.join(workingDir, pattern);
|
|
38683
39018
|
if (fs9.existsSync(filePath)) {
|
|
38684
39019
|
allBuildFiles.add(filePath);
|
|
38685
39020
|
}
|
|
@@ -38692,7 +39027,7 @@ function findFilesRecursive(dir, regex, results) {
|
|
|
38692
39027
|
try {
|
|
38693
39028
|
const entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
38694
39029
|
for (const entry of entries) {
|
|
38695
|
-
const fullPath =
|
|
39030
|
+
const fullPath = path21.join(dir, entry.name);
|
|
38696
39031
|
if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
|
|
38697
39032
|
findFilesRecursive(fullPath, regex, results);
|
|
38698
39033
|
} else if (entry.isFile() && regex.test(entry.name)) {
|
|
@@ -38715,7 +39050,7 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
|
|
|
38715
39050
|
let foundCommand = false;
|
|
38716
39051
|
for (const cmd of sortedCommands) {
|
|
38717
39052
|
if (cmd.detectFile) {
|
|
38718
|
-
const detectFilePath =
|
|
39053
|
+
const detectFilePath = path21.join(workingDir, cmd.detectFile);
|
|
38719
39054
|
if (!fs9.existsSync(detectFilePath)) {
|
|
38720
39055
|
continue;
|
|
38721
39056
|
}
|
|
@@ -38890,8 +39225,8 @@ function checkBinaryReadiness() {
|
|
|
38890
39225
|
}
|
|
38891
39226
|
function runToolDoctor(_directory, pluginRoot) {
|
|
38892
39227
|
const findings = [];
|
|
38893
|
-
const resolvedPluginRoot = pluginRoot ??
|
|
38894
|
-
const indexPath =
|
|
39228
|
+
const resolvedPluginRoot = pluginRoot ?? path22.resolve(import.meta.dir, "..", "..");
|
|
39229
|
+
const indexPath = path22.join(resolvedPluginRoot, "src", "index.ts");
|
|
38895
39230
|
if (!fs10.existsSync(indexPath)) {
|
|
38896
39231
|
return {
|
|
38897
39232
|
findings: [
|
|
@@ -39651,17 +39986,18 @@ ${lines.join(`
|
|
|
39651
39986
|
}
|
|
39652
39987
|
|
|
39653
39988
|
// src/commands/handoff.ts
|
|
39989
|
+
init_bun_compat();
|
|
39654
39990
|
async function handleHandoffCommand(directory, _args) {
|
|
39655
39991
|
const handoffData = await getHandoffData(directory);
|
|
39656
39992
|
const markdown = formatHandoffMarkdown(handoffData);
|
|
39657
39993
|
const resolvedPath = validateSwarmPath(directory, "handoff.md");
|
|
39658
39994
|
const tempPath = `${resolvedPath}.tmp.${crypto4.randomUUID()}`;
|
|
39659
|
-
await
|
|
39995
|
+
await bunWrite(tempPath, markdown);
|
|
39660
39996
|
renameSync6(tempPath, resolvedPath);
|
|
39661
39997
|
const continuationPrompt = formatContinuationPrompt(handoffData);
|
|
39662
39998
|
const promptPath = validateSwarmPath(directory, "handoff-prompt.md");
|
|
39663
39999
|
const promptTempPath = `${promptPath}.tmp.${crypto4.randomUUID()}`;
|
|
39664
|
-
await
|
|
40000
|
+
await bunWrite(promptTempPath, continuationPrompt);
|
|
39665
40001
|
renameSync6(promptTempPath, promptPath);
|
|
39666
40002
|
await writeSnapshot(directory, swarmState);
|
|
39667
40003
|
await flushPendingSnapshot(directory);
|
|
@@ -40019,17 +40355,17 @@ ${USAGE2}`;
|
|
|
40019
40355
|
}
|
|
40020
40356
|
|
|
40021
40357
|
// src/commands/knowledge.ts
|
|
40022
|
-
import { join as
|
|
40358
|
+
import { join as join22 } from "path";
|
|
40023
40359
|
|
|
40024
40360
|
// src/hooks/knowledge-migrator.ts
|
|
40025
40361
|
init_logger();
|
|
40026
40362
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
40027
40363
|
import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
|
|
40028
|
-
import { mkdir as
|
|
40029
|
-
import * as
|
|
40364
|
+
import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
40365
|
+
import * as path23 from "path";
|
|
40030
40366
|
async function migrateContextToKnowledge(directory, config3) {
|
|
40031
|
-
const sentinelPath =
|
|
40032
|
-
const contextPath =
|
|
40367
|
+
const sentinelPath = path23.join(directory, ".swarm", ".knowledge-migrated");
|
|
40368
|
+
const contextPath = path23.join(directory, ".swarm", "context.md");
|
|
40033
40369
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
40034
40370
|
if (existsSync13(sentinelPath)) {
|
|
40035
40371
|
return {
|
|
@@ -40049,7 +40385,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
40049
40385
|
skippedReason: "no-context-file"
|
|
40050
40386
|
};
|
|
40051
40387
|
}
|
|
40052
|
-
const contextContent = await
|
|
40388
|
+
const contextContent = await readFile5(contextPath, "utf-8");
|
|
40053
40389
|
if (contextContent.trim().length === 0) {
|
|
40054
40390
|
return {
|
|
40055
40391
|
migrated: false,
|
|
@@ -40225,7 +40561,7 @@ function truncateLesson(text) {
|
|
|
40225
40561
|
return `${text.slice(0, 277)}...`;
|
|
40226
40562
|
}
|
|
40227
40563
|
function inferProjectName(directory) {
|
|
40228
|
-
const packageJsonPath =
|
|
40564
|
+
const packageJsonPath = path23.join(directory, "package.json");
|
|
40229
40565
|
if (existsSync13(packageJsonPath)) {
|
|
40230
40566
|
try {
|
|
40231
40567
|
const pkg = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
|
|
@@ -40234,7 +40570,7 @@ function inferProjectName(directory) {
|
|
|
40234
40570
|
}
|
|
40235
40571
|
} catch {}
|
|
40236
40572
|
}
|
|
40237
|
-
return
|
|
40573
|
+
return path23.basename(directory);
|
|
40238
40574
|
}
|
|
40239
40575
|
async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
40240
40576
|
const sentinel = {
|
|
@@ -40246,8 +40582,8 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
40246
40582
|
schema_version: 1,
|
|
40247
40583
|
migration_tool: "knowledge-migrator.ts"
|
|
40248
40584
|
};
|
|
40249
|
-
await
|
|
40250
|
-
await
|
|
40585
|
+
await mkdir4(path23.dirname(sentinelPath), { recursive: true });
|
|
40586
|
+
await writeFile5(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
40251
40587
|
}
|
|
40252
40588
|
|
|
40253
40589
|
// src/commands/knowledge.ts
|
|
@@ -40301,7 +40637,7 @@ async function handleKnowledgeRestoreCommand(directory, args) {
|
|
|
40301
40637
|
return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
|
|
40302
40638
|
}
|
|
40303
40639
|
try {
|
|
40304
|
-
const quarantinePath =
|
|
40640
|
+
const quarantinePath = join22(directory, ".swarm", "knowledge-quarantined.jsonl");
|
|
40305
40641
|
const entries = await readKnowledge(quarantinePath);
|
|
40306
40642
|
const resolved = resolveEntryByPrefix(entries, inputId);
|
|
40307
40643
|
if ("error" in resolved) {
|
|
@@ -40705,13 +41041,14 @@ ${USAGE3}`;
|
|
|
40705
41041
|
init_manager2();
|
|
40706
41042
|
init_manager();
|
|
40707
41043
|
import * as fs17 from "fs";
|
|
40708
|
-
import * as
|
|
41044
|
+
import * as path30 from "path";
|
|
40709
41045
|
|
|
40710
41046
|
// src/tools/lint.ts
|
|
40711
41047
|
init_zod();
|
|
40712
41048
|
import * as fs11 from "fs";
|
|
40713
|
-
import * as
|
|
41049
|
+
import * as path24 from "path";
|
|
40714
41050
|
init_utils();
|
|
41051
|
+
init_bun_compat();
|
|
40715
41052
|
|
|
40716
41053
|
// src/utils/path-security.ts
|
|
40717
41054
|
function containsPathTraversal(str) {
|
|
@@ -40756,9 +41093,9 @@ function validateArgs(args) {
|
|
|
40756
41093
|
}
|
|
40757
41094
|
function getLinterCommand(linter, mode, projectDir) {
|
|
40758
41095
|
const isWindows = process.platform === "win32";
|
|
40759
|
-
const binDir =
|
|
40760
|
-
const biomeBin = isWindows ?
|
|
40761
|
-
const eslintBin = isWindows ?
|
|
41096
|
+
const binDir = path24.join(projectDir, "node_modules", ".bin");
|
|
41097
|
+
const biomeBin = isWindows ? path24.join(binDir, "biome.EXE") : path24.join(binDir, "biome");
|
|
41098
|
+
const eslintBin = isWindows ? path24.join(binDir, "eslint.cmd") : path24.join(binDir, "eslint");
|
|
40762
41099
|
switch (linter) {
|
|
40763
41100
|
case "biome":
|
|
40764
41101
|
if (mode === "fix") {
|
|
@@ -40774,7 +41111,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
40774
41111
|
}
|
|
40775
41112
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
40776
41113
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
40777
|
-
const gradlew = fs11.existsSync(
|
|
41114
|
+
const gradlew = fs11.existsSync(path24.join(cwd, gradlewName)) ? path24.join(cwd, gradlewName) : null;
|
|
40778
41115
|
switch (linter) {
|
|
40779
41116
|
case "ruff":
|
|
40780
41117
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -40808,10 +41145,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
40808
41145
|
}
|
|
40809
41146
|
}
|
|
40810
41147
|
function detectRuff(cwd) {
|
|
40811
|
-
if (fs11.existsSync(
|
|
41148
|
+
if (fs11.existsSync(path24.join(cwd, "ruff.toml")))
|
|
40812
41149
|
return isCommandAvailable("ruff");
|
|
40813
41150
|
try {
|
|
40814
|
-
const pyproject =
|
|
41151
|
+
const pyproject = path24.join(cwd, "pyproject.toml");
|
|
40815
41152
|
if (fs11.existsSync(pyproject)) {
|
|
40816
41153
|
const content = fs11.readFileSync(pyproject, "utf-8");
|
|
40817
41154
|
if (content.includes("[tool.ruff]"))
|
|
@@ -40821,19 +41158,19 @@ function detectRuff(cwd) {
|
|
|
40821
41158
|
return false;
|
|
40822
41159
|
}
|
|
40823
41160
|
function detectClippy(cwd) {
|
|
40824
|
-
return fs11.existsSync(
|
|
41161
|
+
return fs11.existsSync(path24.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
40825
41162
|
}
|
|
40826
41163
|
function detectGolangciLint(cwd) {
|
|
40827
|
-
return fs11.existsSync(
|
|
41164
|
+
return fs11.existsSync(path24.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
40828
41165
|
}
|
|
40829
41166
|
function detectCheckstyle(cwd) {
|
|
40830
|
-
const hasMaven = fs11.existsSync(
|
|
40831
|
-
const hasGradle = fs11.existsSync(
|
|
40832
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs11.existsSync(
|
|
41167
|
+
const hasMaven = fs11.existsSync(path24.join(cwd, "pom.xml"));
|
|
41168
|
+
const hasGradle = fs11.existsSync(path24.join(cwd, "build.gradle")) || fs11.existsSync(path24.join(cwd, "build.gradle.kts"));
|
|
41169
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs11.existsSync(path24.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
40833
41170
|
return (hasMaven || hasGradle) && hasBinary;
|
|
40834
41171
|
}
|
|
40835
41172
|
function detectKtlint(cwd) {
|
|
40836
|
-
const hasKotlin = fs11.existsSync(
|
|
41173
|
+
const hasKotlin = fs11.existsSync(path24.join(cwd, "build.gradle.kts")) || fs11.existsSync(path24.join(cwd, "build.gradle")) || (() => {
|
|
40837
41174
|
try {
|
|
40838
41175
|
return fs11.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
40839
41176
|
} catch {
|
|
@@ -40852,11 +41189,11 @@ function detectDotnetFormat(cwd) {
|
|
|
40852
41189
|
}
|
|
40853
41190
|
}
|
|
40854
41191
|
function detectCppcheck(cwd) {
|
|
40855
|
-
if (fs11.existsSync(
|
|
41192
|
+
if (fs11.existsSync(path24.join(cwd, "CMakeLists.txt"))) {
|
|
40856
41193
|
return isCommandAvailable("cppcheck");
|
|
40857
41194
|
}
|
|
40858
41195
|
try {
|
|
40859
|
-
const dirsToCheck = [cwd,
|
|
41196
|
+
const dirsToCheck = [cwd, path24.join(cwd, "src")];
|
|
40860
41197
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
40861
41198
|
try {
|
|
40862
41199
|
return fs11.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
@@ -40870,13 +41207,13 @@ function detectCppcheck(cwd) {
|
|
|
40870
41207
|
}
|
|
40871
41208
|
}
|
|
40872
41209
|
function detectSwiftlint(cwd) {
|
|
40873
|
-
return fs11.existsSync(
|
|
41210
|
+
return fs11.existsSync(path24.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
40874
41211
|
}
|
|
40875
41212
|
function detectDartAnalyze(cwd) {
|
|
40876
|
-
return fs11.existsSync(
|
|
41213
|
+
return fs11.existsSync(path24.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
40877
41214
|
}
|
|
40878
41215
|
function detectRubocop(cwd) {
|
|
40879
|
-
return (fs11.existsSync(
|
|
41216
|
+
return (fs11.existsSync(path24.join(cwd, "Gemfile")) || fs11.existsSync(path24.join(cwd, "gems.rb")) || fs11.existsSync(path24.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
|
|
40880
41217
|
}
|
|
40881
41218
|
function detectAdditionalLinter(cwd) {
|
|
40882
41219
|
if (detectRuff(cwd))
|
|
@@ -40904,10 +41241,10 @@ function detectAdditionalLinter(cwd) {
|
|
|
40904
41241
|
function findBinInAncestors(startDir, binName) {
|
|
40905
41242
|
let dir = startDir;
|
|
40906
41243
|
while (true) {
|
|
40907
|
-
const candidate =
|
|
41244
|
+
const candidate = path24.join(dir, "node_modules", ".bin", binName);
|
|
40908
41245
|
if (fs11.existsSync(candidate))
|
|
40909
41246
|
return candidate;
|
|
40910
|
-
const parent =
|
|
41247
|
+
const parent = path24.dirname(dir);
|
|
40911
41248
|
if (parent === dir)
|
|
40912
41249
|
break;
|
|
40913
41250
|
dir = parent;
|
|
@@ -40916,10 +41253,10 @@ function findBinInAncestors(startDir, binName) {
|
|
|
40916
41253
|
}
|
|
40917
41254
|
function findBinInEnvPath(binName) {
|
|
40918
41255
|
const searchPath = process.env.PATH ?? "";
|
|
40919
|
-
for (const dir of searchPath.split(
|
|
41256
|
+
for (const dir of searchPath.split(path24.delimiter)) {
|
|
40920
41257
|
if (!dir)
|
|
40921
41258
|
continue;
|
|
40922
|
-
const candidate =
|
|
41259
|
+
const candidate = path24.join(dir, binName);
|
|
40923
41260
|
if (fs11.existsSync(candidate))
|
|
40924
41261
|
return candidate;
|
|
40925
41262
|
}
|
|
@@ -40932,13 +41269,13 @@ async function detectAvailableLinter(directory) {
|
|
|
40932
41269
|
return null;
|
|
40933
41270
|
const projectDir = directory;
|
|
40934
41271
|
const isWindows = process.platform === "win32";
|
|
40935
|
-
const biomeBin = isWindows ?
|
|
40936
|
-
const eslintBin = isWindows ?
|
|
41272
|
+
const biomeBin = isWindows ? path24.join(projectDir, "node_modules", ".bin", "biome.EXE") : path24.join(projectDir, "node_modules", ".bin", "biome");
|
|
41273
|
+
const eslintBin = isWindows ? path24.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path24.join(projectDir, "node_modules", ".bin", "eslint");
|
|
40937
41274
|
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
40938
41275
|
if (localResult)
|
|
40939
41276
|
return localResult;
|
|
40940
|
-
const biomeAncestor = findBinInAncestors(
|
|
40941
|
-
const eslintAncestor = findBinInAncestors(
|
|
41277
|
+
const biomeAncestor = findBinInAncestors(path24.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
41278
|
+
const eslintAncestor = findBinInAncestors(path24.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
40942
41279
|
if (biomeAncestor || eslintAncestor) {
|
|
40943
41280
|
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
40944
41281
|
}
|
|
@@ -40952,7 +41289,7 @@ async function detectAvailableLinter(directory) {
|
|
|
40952
41289
|
async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
|
|
40953
41290
|
const DETECT_TIMEOUT = 2000;
|
|
40954
41291
|
try {
|
|
40955
|
-
const biomeProc =
|
|
41292
|
+
const biomeProc = bunSpawn([biomeBin, "--version"], {
|
|
40956
41293
|
stdout: "pipe",
|
|
40957
41294
|
stderr: "pipe"
|
|
40958
41295
|
});
|
|
@@ -40966,7 +41303,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
|
|
|
40966
41303
|
}
|
|
40967
41304
|
} catch {}
|
|
40968
41305
|
try {
|
|
40969
|
-
const eslintProc =
|
|
41306
|
+
const eslintProc = bunSpawn([eslintBin, "--version"], {
|
|
40970
41307
|
stdout: "pipe",
|
|
40971
41308
|
stderr: "pipe"
|
|
40972
41309
|
});
|
|
@@ -40994,14 +41331,14 @@ async function runLint(linter, mode, directory) {
|
|
|
40994
41331
|
};
|
|
40995
41332
|
}
|
|
40996
41333
|
try {
|
|
40997
|
-
const proc =
|
|
41334
|
+
const proc = bunSpawn(command, {
|
|
40998
41335
|
stdout: "pipe",
|
|
40999
41336
|
stderr: "pipe",
|
|
41000
41337
|
cwd: directory
|
|
41001
41338
|
});
|
|
41002
41339
|
const [stdout, stderr] = await Promise.all([
|
|
41003
|
-
|
|
41004
|
-
|
|
41340
|
+
proc.stdout.text(),
|
|
41341
|
+
proc.stderr.text()
|
|
41005
41342
|
]);
|
|
41006
41343
|
const exitCode = await proc.exited;
|
|
41007
41344
|
let output = stdout;
|
|
@@ -41052,14 +41389,14 @@ async function runAdditionalLint(linter, mode, cwd) {
|
|
|
41052
41389
|
};
|
|
41053
41390
|
}
|
|
41054
41391
|
try {
|
|
41055
|
-
const proc =
|
|
41392
|
+
const proc = bunSpawn(command, {
|
|
41056
41393
|
stdout: "pipe",
|
|
41057
41394
|
stderr: "pipe",
|
|
41058
41395
|
cwd
|
|
41059
41396
|
});
|
|
41060
41397
|
const [stdout, stderr] = await Promise.all([
|
|
41061
|
-
|
|
41062
|
-
|
|
41398
|
+
proc.stdout.text(),
|
|
41399
|
+
proc.stderr.text()
|
|
41063
41400
|
]);
|
|
41064
41401
|
const exitCode = await proc.exited;
|
|
41065
41402
|
let output = stdout;
|
|
@@ -41147,7 +41484,7 @@ For Rust: rustup component add clippy`
|
|
|
41147
41484
|
// src/tools/secretscan.ts
|
|
41148
41485
|
init_zod();
|
|
41149
41486
|
import * as fs12 from "fs";
|
|
41150
|
-
import * as
|
|
41487
|
+
import * as path25 from "path";
|
|
41151
41488
|
var MAX_FILE_PATH_LENGTH = 500;
|
|
41152
41489
|
var MAX_FILE_SIZE_BYTES = 512 * 1024;
|
|
41153
41490
|
var MAX_FILES_SCANNED = 1000;
|
|
@@ -41374,7 +41711,7 @@ function isGlobOrPathPattern(pattern) {
|
|
|
41374
41711
|
return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
|
|
41375
41712
|
}
|
|
41376
41713
|
function loadSecretScanIgnore(scanDir) {
|
|
41377
|
-
const ignorePath =
|
|
41714
|
+
const ignorePath = path25.join(scanDir, ".secretscanignore");
|
|
41378
41715
|
try {
|
|
41379
41716
|
if (!fs12.existsSync(ignorePath))
|
|
41380
41717
|
return [];
|
|
@@ -41397,7 +41734,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
41397
41734
|
if (exactNames.has(entry))
|
|
41398
41735
|
return true;
|
|
41399
41736
|
for (const pattern of globPatterns) {
|
|
41400
|
-
if (
|
|
41737
|
+
if (path25.matchesGlob(relPath, pattern))
|
|
41401
41738
|
return true;
|
|
41402
41739
|
}
|
|
41403
41740
|
return false;
|
|
@@ -41418,7 +41755,7 @@ function validateDirectoryInput(dir) {
|
|
|
41418
41755
|
return null;
|
|
41419
41756
|
}
|
|
41420
41757
|
function isBinaryFile(filePath, buffer) {
|
|
41421
|
-
const ext =
|
|
41758
|
+
const ext = path25.extname(filePath).toLowerCase();
|
|
41422
41759
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
41423
41760
|
return true;
|
|
41424
41761
|
}
|
|
@@ -41555,9 +41892,9 @@ function isSymlinkLoop(realPath, visited) {
|
|
|
41555
41892
|
return false;
|
|
41556
41893
|
}
|
|
41557
41894
|
function isPathWithinScope(realPath, scanDir) {
|
|
41558
|
-
const resolvedScanDir =
|
|
41559
|
-
const resolvedRealPath =
|
|
41560
|
-
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir +
|
|
41895
|
+
const resolvedScanDir = path25.resolve(scanDir);
|
|
41896
|
+
const resolvedRealPath = path25.resolve(realPath);
|
|
41897
|
+
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path25.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
|
|
41561
41898
|
}
|
|
41562
41899
|
function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
|
|
41563
41900
|
skippedDirs: 0,
|
|
@@ -41583,8 +41920,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
41583
41920
|
return a.localeCompare(b);
|
|
41584
41921
|
});
|
|
41585
41922
|
for (const entry of entries) {
|
|
41586
|
-
const fullPath =
|
|
41587
|
-
const relPath =
|
|
41923
|
+
const fullPath = path25.join(dir, entry);
|
|
41924
|
+
const relPath = path25.relative(scanDir, fullPath).replace(/\\/g, "/");
|
|
41588
41925
|
if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
|
|
41589
41926
|
stats.skippedDirs++;
|
|
41590
41927
|
continue;
|
|
@@ -41619,7 +41956,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
41619
41956
|
const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
|
|
41620
41957
|
files.push(...subFiles);
|
|
41621
41958
|
} else if (lstat.isFile()) {
|
|
41622
|
-
const ext =
|
|
41959
|
+
const ext = path25.extname(fullPath).toLowerCase();
|
|
41623
41960
|
if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
41624
41961
|
files.push(fullPath);
|
|
41625
41962
|
} else {
|
|
@@ -41685,7 +42022,7 @@ var secretscan = createSwarmTool({
|
|
|
41685
42022
|
}
|
|
41686
42023
|
}
|
|
41687
42024
|
try {
|
|
41688
|
-
const _scanDirRaw =
|
|
42025
|
+
const _scanDirRaw = path25.resolve(directory);
|
|
41689
42026
|
const scanDir = (() => {
|
|
41690
42027
|
try {
|
|
41691
42028
|
return fs12.realpathSync(_scanDirRaw);
|
|
@@ -41755,8 +42092,8 @@ var secretscan = createSwarmTool({
|
|
|
41755
42092
|
break;
|
|
41756
42093
|
const fileFindings = scanFileForSecrets(filePath);
|
|
41757
42094
|
try {
|
|
41758
|
-
const
|
|
41759
|
-
if (
|
|
42095
|
+
const stat3 = fs12.statSync(filePath);
|
|
42096
|
+
if (stat3.size > MAX_FILE_SIZE_BYTES) {
|
|
41760
42097
|
skippedFiles++;
|
|
41761
42098
|
continue;
|
|
41762
42099
|
}
|
|
@@ -41845,11 +42182,11 @@ async function runSecretscan(directory) {
|
|
|
41845
42182
|
// src/tools/test-runner.ts
|
|
41846
42183
|
init_zod();
|
|
41847
42184
|
import * as fs16 from "fs";
|
|
41848
|
-
import * as
|
|
42185
|
+
import * as path29 from "path";
|
|
41849
42186
|
|
|
41850
42187
|
// src/test-impact/analyzer.ts
|
|
41851
42188
|
import fs13 from "fs";
|
|
41852
|
-
import
|
|
42189
|
+
import path26 from "path";
|
|
41853
42190
|
var IMPORT_REGEX_ES = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
41854
42191
|
var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
41855
42192
|
var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
|
|
@@ -41860,8 +42197,8 @@ function normalizePath(p) {
|
|
|
41860
42197
|
function isCacheStale(impactMap, generatedAtMs) {
|
|
41861
42198
|
for (const sourcePath of Object.keys(impactMap)) {
|
|
41862
42199
|
try {
|
|
41863
|
-
const
|
|
41864
|
-
if (
|
|
42200
|
+
const stat3 = fs13.statSync(sourcePath);
|
|
42201
|
+
if (stat3.mtimeMs > generatedAtMs) {
|
|
41865
42202
|
return true;
|
|
41866
42203
|
}
|
|
41867
42204
|
} catch {
|
|
@@ -41874,8 +42211,8 @@ function resolveRelativeImport(fromDir, importPath) {
|
|
|
41874
42211
|
if (!importPath.startsWith(".")) {
|
|
41875
42212
|
return null;
|
|
41876
42213
|
}
|
|
41877
|
-
const resolved =
|
|
41878
|
-
if (
|
|
42214
|
+
const resolved = path26.resolve(fromDir, importPath);
|
|
42215
|
+
if (path26.extname(resolved)) {
|
|
41879
42216
|
if (fs13.existsSync(resolved) && fs13.statSync(resolved).isFile()) {
|
|
41880
42217
|
return normalizePath(resolved);
|
|
41881
42218
|
}
|
|
@@ -41920,12 +42257,12 @@ function findTestFilesSync(cwd) {
|
|
|
41920
42257
|
for (const entry of entries) {
|
|
41921
42258
|
if (entry.isDirectory()) {
|
|
41922
42259
|
if (!skipDirs.has(entry.name)) {
|
|
41923
|
-
walk(
|
|
42260
|
+
walk(path26.join(dir, entry.name), visitedInodes);
|
|
41924
42261
|
}
|
|
41925
42262
|
} else if (entry.isFile()) {
|
|
41926
42263
|
const name = entry.name;
|
|
41927
42264
|
if (/\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name)) {
|
|
41928
|
-
testFiles.push(normalizePath(
|
|
42265
|
+
testFiles.push(normalizePath(path26.join(dir, entry.name)));
|
|
41929
42266
|
}
|
|
41930
42267
|
}
|
|
41931
42268
|
}
|
|
@@ -41963,7 +42300,7 @@ async function buildImpactMapInternal(cwd) {
|
|
|
41963
42300
|
continue;
|
|
41964
42301
|
}
|
|
41965
42302
|
const imports = extractImports(content);
|
|
41966
|
-
const testDir =
|
|
42303
|
+
const testDir = path26.dirname(testFile);
|
|
41967
42304
|
for (const importPath of imports) {
|
|
41968
42305
|
const resolvedSource = resolveRelativeImport(testDir, importPath);
|
|
41969
42306
|
if (resolvedSource === null) {
|
|
@@ -41985,7 +42322,7 @@ async function buildImpactMap(cwd) {
|
|
|
41985
42322
|
return impactMap;
|
|
41986
42323
|
}
|
|
41987
42324
|
async function loadImpactMap(cwd) {
|
|
41988
|
-
const cachePath =
|
|
42325
|
+
const cachePath = path26.join(cwd, ".swarm", "cache", "impact-map.json");
|
|
41989
42326
|
if (fs13.existsSync(cachePath)) {
|
|
41990
42327
|
try {
|
|
41991
42328
|
const content = fs13.readFileSync(cachePath, "utf-8");
|
|
@@ -42000,8 +42337,8 @@ async function loadImpactMap(cwd) {
|
|
|
42000
42337
|
return buildImpactMap(cwd);
|
|
42001
42338
|
}
|
|
42002
42339
|
async function saveImpactMap(cwd, impactMap) {
|
|
42003
|
-
const cacheDir2 =
|
|
42004
|
-
const cachePath =
|
|
42340
|
+
const cacheDir2 = path26.join(cwd, ".swarm", "cache");
|
|
42341
|
+
const cachePath = path26.join(cacheDir2, "impact-map.json");
|
|
42005
42342
|
if (!fs13.existsSync(cacheDir2)) {
|
|
42006
42343
|
fs13.mkdirSync(cacheDir2, { recursive: true });
|
|
42007
42344
|
}
|
|
@@ -42027,7 +42364,7 @@ async function analyzeImpact(changedFiles, cwd) {
|
|
|
42027
42364
|
const impactedTestsSet = new Set;
|
|
42028
42365
|
const untestedFiles = [];
|
|
42029
42366
|
for (const changedFile of validFiles) {
|
|
42030
|
-
const normalizedChanged = normalizePath(
|
|
42367
|
+
const normalizedChanged = normalizePath(path26.resolve(changedFile));
|
|
42031
42368
|
const tests = impactMap[normalizedChanged];
|
|
42032
42369
|
if (tests && tests.length > 0) {
|
|
42033
42370
|
for (const test of tests) {
|
|
@@ -42274,13 +42611,13 @@ function detectFlakyTests(allHistory) {
|
|
|
42274
42611
|
|
|
42275
42612
|
// src/test-impact/history-store.ts
|
|
42276
42613
|
import fs14 from "fs";
|
|
42277
|
-
import
|
|
42614
|
+
import path27 from "path";
|
|
42278
42615
|
var MAX_HISTORY_PER_TEST = 20;
|
|
42279
42616
|
var MAX_ERROR_LENGTH = 500;
|
|
42280
42617
|
var MAX_STACK_LENGTH = 200;
|
|
42281
42618
|
var MAX_CHANGED_FILES = 50;
|
|
42282
42619
|
function getHistoryPath(workingDir) {
|
|
42283
|
-
return
|
|
42620
|
+
return path27.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
|
|
42284
42621
|
}
|
|
42285
42622
|
function sanitizeErrorMessage(errorMessage) {
|
|
42286
42623
|
if (errorMessage === undefined) {
|
|
@@ -42340,7 +42677,7 @@ function appendTestRun(record3, workingDir) {
|
|
|
42340
42677
|
changedFiles: sanitizeChangedFiles(record3.changedFiles || [])
|
|
42341
42678
|
};
|
|
42342
42679
|
const historyPath = getHistoryPath(workingDir);
|
|
42343
|
-
const historyDir =
|
|
42680
|
+
const historyDir = path27.dirname(historyPath);
|
|
42344
42681
|
if (!fs14.existsSync(historyDir)) {
|
|
42345
42682
|
fs14.mkdirSync(historyDir, { recursive: true });
|
|
42346
42683
|
}
|
|
@@ -42412,9 +42749,12 @@ function getAllHistory(workingDir) {
|
|
|
42412
42749
|
return records;
|
|
42413
42750
|
}
|
|
42414
42751
|
|
|
42752
|
+
// src/tools/test-runner.ts
|
|
42753
|
+
init_bun_compat();
|
|
42754
|
+
|
|
42415
42755
|
// src/tools/resolve-working-directory.ts
|
|
42416
42756
|
import * as fs15 from "fs";
|
|
42417
|
-
import * as
|
|
42757
|
+
import * as path28 from "path";
|
|
42418
42758
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
42419
42759
|
if (workingDirectory == null || workingDirectory === "") {
|
|
42420
42760
|
return { success: true, directory: fallbackDirectory };
|
|
@@ -42434,15 +42774,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
42434
42774
|
};
|
|
42435
42775
|
}
|
|
42436
42776
|
}
|
|
42437
|
-
const normalizedDir =
|
|
42438
|
-
const pathParts = normalizedDir.split(
|
|
42777
|
+
const normalizedDir = path28.normalize(workingDirectory);
|
|
42778
|
+
const pathParts = normalizedDir.split(path28.sep);
|
|
42439
42779
|
if (pathParts.includes("..")) {
|
|
42440
42780
|
return {
|
|
42441
42781
|
success: false,
|
|
42442
42782
|
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
42443
42783
|
};
|
|
42444
42784
|
}
|
|
42445
|
-
const resolvedDir =
|
|
42785
|
+
const resolvedDir = path28.resolve(normalizedDir);
|
|
42446
42786
|
let statResult;
|
|
42447
42787
|
try {
|
|
42448
42788
|
statResult = fs15.statSync(resolvedDir);
|
|
@@ -42458,7 +42798,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
42458
42798
|
message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
|
|
42459
42799
|
};
|
|
42460
42800
|
}
|
|
42461
|
-
const resolvedFallback =
|
|
42801
|
+
const resolvedFallback = path28.resolve(fallbackDirectory);
|
|
42462
42802
|
let fallbackExists = false;
|
|
42463
42803
|
try {
|
|
42464
42804
|
fs15.statSync(resolvedFallback);
|
|
@@ -42468,7 +42808,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
42468
42808
|
}
|
|
42469
42809
|
if (workingDirectory != null && workingDirectory !== "") {
|
|
42470
42810
|
if (fallbackExists) {
|
|
42471
|
-
const isSubdirectory = resolvedDir.startsWith(resolvedFallback +
|
|
42811
|
+
const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path28.sep);
|
|
42472
42812
|
if (isSubdirectory) {
|
|
42473
42813
|
return {
|
|
42474
42814
|
success: false,
|
|
@@ -42558,14 +42898,14 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
42558
42898
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
42559
42899
|
}
|
|
42560
42900
|
function detectGoTest(cwd) {
|
|
42561
|
-
return fs16.existsSync(
|
|
42901
|
+
return fs16.existsSync(path29.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
42562
42902
|
}
|
|
42563
42903
|
function detectJavaMaven(cwd) {
|
|
42564
|
-
return fs16.existsSync(
|
|
42904
|
+
return fs16.existsSync(path29.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
42565
42905
|
}
|
|
42566
42906
|
function detectGradle(cwd) {
|
|
42567
|
-
const hasBuildFile = fs16.existsSync(
|
|
42568
|
-
const hasGradlew = fs16.existsSync(
|
|
42907
|
+
const hasBuildFile = fs16.existsSync(path29.join(cwd, "build.gradle")) || fs16.existsSync(path29.join(cwd, "build.gradle.kts"));
|
|
42908
|
+
const hasGradlew = fs16.existsSync(path29.join(cwd, "gradlew")) || fs16.existsSync(path29.join(cwd, "gradlew.bat"));
|
|
42569
42909
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
42570
42910
|
}
|
|
42571
42911
|
function detectDotnetTest(cwd) {
|
|
@@ -42578,30 +42918,30 @@ function detectDotnetTest(cwd) {
|
|
|
42578
42918
|
}
|
|
42579
42919
|
}
|
|
42580
42920
|
function detectCTest(cwd) {
|
|
42581
|
-
const hasSource = fs16.existsSync(
|
|
42582
|
-
const hasBuildCache = fs16.existsSync(
|
|
42921
|
+
const hasSource = fs16.existsSync(path29.join(cwd, "CMakeLists.txt"));
|
|
42922
|
+
const hasBuildCache = fs16.existsSync(path29.join(cwd, "CMakeCache.txt")) || fs16.existsSync(path29.join(cwd, "build", "CMakeCache.txt"));
|
|
42583
42923
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
42584
42924
|
}
|
|
42585
42925
|
function detectSwiftTest(cwd) {
|
|
42586
|
-
return fs16.existsSync(
|
|
42926
|
+
return fs16.existsSync(path29.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
42587
42927
|
}
|
|
42588
42928
|
function detectDartTest(cwd) {
|
|
42589
|
-
return fs16.existsSync(
|
|
42929
|
+
return fs16.existsSync(path29.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
42590
42930
|
}
|
|
42591
42931
|
function detectRSpec(cwd) {
|
|
42592
|
-
const hasRSpecFile = fs16.existsSync(
|
|
42593
|
-
const hasGemfile = fs16.existsSync(
|
|
42594
|
-
const hasSpecDir = fs16.existsSync(
|
|
42932
|
+
const hasRSpecFile = fs16.existsSync(path29.join(cwd, ".rspec"));
|
|
42933
|
+
const hasGemfile = fs16.existsSync(path29.join(cwd, "Gemfile"));
|
|
42934
|
+
const hasSpecDir = fs16.existsSync(path29.join(cwd, "spec"));
|
|
42595
42935
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
42596
42936
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
42597
42937
|
}
|
|
42598
42938
|
function detectMinitest(cwd) {
|
|
42599
|
-
return fs16.existsSync(
|
|
42939
|
+
return fs16.existsSync(path29.join(cwd, "test")) && (fs16.existsSync(path29.join(cwd, "Gemfile")) || fs16.existsSync(path29.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
42600
42940
|
}
|
|
42601
42941
|
async function detectTestFramework(cwd) {
|
|
42602
42942
|
const baseDir = cwd;
|
|
42603
42943
|
try {
|
|
42604
|
-
const packageJsonPath =
|
|
42944
|
+
const packageJsonPath = path29.join(baseDir, "package.json");
|
|
42605
42945
|
if (fs16.existsSync(packageJsonPath)) {
|
|
42606
42946
|
const content = fs16.readFileSync(packageJsonPath, "utf-8");
|
|
42607
42947
|
const pkg = JSON.parse(content);
|
|
@@ -42622,16 +42962,16 @@ async function detectTestFramework(cwd) {
|
|
|
42622
42962
|
return "jest";
|
|
42623
42963
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
42624
42964
|
return "mocha";
|
|
42625
|
-
if (fs16.existsSync(
|
|
42965
|
+
if (fs16.existsSync(path29.join(baseDir, "bun.lockb")) || fs16.existsSync(path29.join(baseDir, "bun.lock"))) {
|
|
42626
42966
|
if (scripts.test?.includes("bun"))
|
|
42627
42967
|
return "bun";
|
|
42628
42968
|
}
|
|
42629
42969
|
}
|
|
42630
42970
|
} catch {}
|
|
42631
42971
|
try {
|
|
42632
|
-
const pyprojectTomlPath =
|
|
42633
|
-
const setupCfgPath =
|
|
42634
|
-
const requirementsTxtPath =
|
|
42972
|
+
const pyprojectTomlPath = path29.join(baseDir, "pyproject.toml");
|
|
42973
|
+
const setupCfgPath = path29.join(baseDir, "setup.cfg");
|
|
42974
|
+
const requirementsTxtPath = path29.join(baseDir, "requirements.txt");
|
|
42635
42975
|
if (fs16.existsSync(pyprojectTomlPath)) {
|
|
42636
42976
|
const content = fs16.readFileSync(pyprojectTomlPath, "utf-8");
|
|
42637
42977
|
if (content.includes("[tool.pytest"))
|
|
@@ -42651,7 +42991,7 @@ async function detectTestFramework(cwd) {
|
|
|
42651
42991
|
}
|
|
42652
42992
|
} catch {}
|
|
42653
42993
|
try {
|
|
42654
|
-
const cargoTomlPath =
|
|
42994
|
+
const cargoTomlPath = path29.join(baseDir, "Cargo.toml");
|
|
42655
42995
|
if (fs16.existsSync(cargoTomlPath)) {
|
|
42656
42996
|
const content = fs16.readFileSync(cargoTomlPath, "utf-8");
|
|
42657
42997
|
if (content.includes("[dev-dependencies]")) {
|
|
@@ -42662,9 +43002,9 @@ async function detectTestFramework(cwd) {
|
|
|
42662
43002
|
}
|
|
42663
43003
|
} catch {}
|
|
42664
43004
|
try {
|
|
42665
|
-
const pesterConfigPath =
|
|
42666
|
-
const pesterConfigJsonPath =
|
|
42667
|
-
const pesterPs1Path =
|
|
43005
|
+
const pesterConfigPath = path29.join(baseDir, "pester.config.ps1");
|
|
43006
|
+
const pesterConfigJsonPath = path29.join(baseDir, "pester.config.ps1.json");
|
|
43007
|
+
const pesterPs1Path = path29.join(baseDir, "tests.ps1");
|
|
42668
43008
|
if (fs16.existsSync(pesterConfigPath) || fs16.existsSync(pesterConfigJsonPath) || fs16.existsSync(pesterPs1Path)) {
|
|
42669
43009
|
return "pester";
|
|
42670
43010
|
}
|
|
@@ -42707,12 +43047,12 @@ function isTestDirectoryPath(normalizedPath) {
|
|
|
42707
43047
|
return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
|
|
42708
43048
|
}
|
|
42709
43049
|
function resolveWorkspacePath(file3, workingDir) {
|
|
42710
|
-
return
|
|
43050
|
+
return path29.isAbsolute(file3) ? path29.resolve(file3) : path29.resolve(workingDir, file3);
|
|
42711
43051
|
}
|
|
42712
43052
|
function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
|
|
42713
43053
|
if (!preferRelative)
|
|
42714
43054
|
return absolutePath;
|
|
42715
|
-
return
|
|
43055
|
+
return path29.relative(workingDir, absolutePath);
|
|
42716
43056
|
}
|
|
42717
43057
|
function dedupePush(target, value) {
|
|
42718
43058
|
if (!target.includes(value)) {
|
|
@@ -42749,18 +43089,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
|
|
|
42749
43089
|
}
|
|
42750
43090
|
}
|
|
42751
43091
|
function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
|
|
42752
|
-
const relativeDir =
|
|
43092
|
+
const relativeDir = path29.dirname(relativePath);
|
|
42753
43093
|
const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
|
|
42754
43094
|
const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
|
|
42755
|
-
const rootDir =
|
|
42756
|
-
return nestedRelativeDir ? [rootDir,
|
|
43095
|
+
const rootDir = path29.join(workingDir, dirName);
|
|
43096
|
+
return nestedRelativeDir ? [rootDir, path29.join(rootDir, nestedRelativeDir)] : [rootDir];
|
|
42757
43097
|
});
|
|
42758
43098
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
42759
43099
|
if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
|
|
42760
|
-
directories.push(
|
|
43100
|
+
directories.push(path29.join(workingDir, "src/test/java", path29.dirname(normalizedRelativePath.slice("src/main/java/".length))));
|
|
42761
43101
|
}
|
|
42762
43102
|
if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
|
|
42763
|
-
directories.push(
|
|
43103
|
+
directories.push(path29.join(workingDir, "src/test/kotlin", path29.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
|
|
42764
43104
|
}
|
|
42765
43105
|
return [...new Set(directories)];
|
|
42766
43106
|
}
|
|
@@ -42768,19 +43108,19 @@ function hasCompoundTestExtension(filename) {
|
|
|
42768
43108
|
const lower = filename.toLowerCase();
|
|
42769
43109
|
return COMPOUND_TEST_EXTENSIONS.some((ext) => lower.endsWith(ext));
|
|
42770
43110
|
}
|
|
42771
|
-
function isLanguageSpecificTestFile(
|
|
42772
|
-
const lower =
|
|
43111
|
+
function isLanguageSpecificTestFile(basename5) {
|
|
43112
|
+
const lower = basename5.toLowerCase();
|
|
42773
43113
|
if (lower.endsWith("_test.go"))
|
|
42774
43114
|
return true;
|
|
42775
43115
|
if (lower.endsWith(".py") && (lower.startsWith("test_") || lower.endsWith("_test.py")))
|
|
42776
43116
|
return true;
|
|
42777
43117
|
if (lower.endsWith("_spec.rb"))
|
|
42778
43118
|
return true;
|
|
42779
|
-
if (lower.endsWith(".java") && (/^Test[A-Z]/.test(
|
|
43119
|
+
if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename5) || basename5.endsWith("Test.java") || basename5.endsWith("Tests.java") || lower.endsWith("it.java")))
|
|
42780
43120
|
return true;
|
|
42781
43121
|
if (lower.endsWith(".cs") && (lower.endsWith("test.cs") || lower.endsWith("tests.cs")))
|
|
42782
43122
|
return true;
|
|
42783
|
-
if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(
|
|
43123
|
+
if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename5) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
|
|
42784
43124
|
return true;
|
|
42785
43125
|
if (lower.endsWith(".tests.ps1"))
|
|
42786
43126
|
return true;
|
|
@@ -42788,23 +43128,23 @@ function isLanguageSpecificTestFile(basename4) {
|
|
|
42788
43128
|
}
|
|
42789
43129
|
function isConventionTestFilePath(filePath) {
|
|
42790
43130
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
42791
|
-
const
|
|
42792
|
-
return hasCompoundTestExtension(
|
|
43131
|
+
const basename5 = path29.basename(filePath);
|
|
43132
|
+
return hasCompoundTestExtension(basename5) || basename5.includes(".spec.") || basename5.includes(".test.") || isLanguageSpecificTestFile(basename5) || isTestDirectoryPath(normalizedPath);
|
|
42793
43133
|
}
|
|
42794
43134
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
42795
43135
|
const testFiles = [];
|
|
42796
43136
|
for (const file3 of sourceFiles) {
|
|
42797
43137
|
const absoluteFile = resolveWorkspacePath(file3, workingDir);
|
|
42798
|
-
const relativeFile =
|
|
42799
|
-
const
|
|
42800
|
-
const
|
|
42801
|
-
const preferRelativeOutput = !
|
|
43138
|
+
const relativeFile = path29.relative(workingDir, absoluteFile);
|
|
43139
|
+
const basename5 = path29.basename(absoluteFile);
|
|
43140
|
+
const dirname12 = path29.dirname(absoluteFile);
|
|
43141
|
+
const preferRelativeOutput = !path29.isAbsolute(file3);
|
|
42802
43142
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
|
|
42803
43143
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
42804
43144
|
continue;
|
|
42805
43145
|
}
|
|
42806
|
-
const nameWithoutExt =
|
|
42807
|
-
const ext =
|
|
43146
|
+
const nameWithoutExt = basename5.replace(/\.[^.]+$/, "");
|
|
43147
|
+
const ext = path29.extname(basename5);
|
|
42808
43148
|
const genericTestNames = [
|
|
42809
43149
|
`${nameWithoutExt}.spec${ext}`,
|
|
42810
43150
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -42813,17 +43153,17 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
42813
43153
|
const colocatedCandidates = [
|
|
42814
43154
|
...genericTestNames,
|
|
42815
43155
|
...languageSpecificTestNames
|
|
42816
|
-
].map((candidateName) =>
|
|
43156
|
+
].map((candidateName) => path29.join(dirname12, candidateName));
|
|
42817
43157
|
const testDirectoryNames = [
|
|
42818
|
-
|
|
43158
|
+
basename5,
|
|
42819
43159
|
...genericTestNames,
|
|
42820
43160
|
...languageSpecificTestNames
|
|
42821
43161
|
];
|
|
42822
43162
|
const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
|
|
42823
43163
|
const possibleTestFiles = [
|
|
42824
43164
|
...colocatedCandidates,
|
|
42825
|
-
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) =>
|
|
42826
|
-
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) =>
|
|
43165
|
+
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path29.join(dirname12, dirName, candidateName))),
|
|
43166
|
+
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path29.join(candidateDir, candidateName)))
|
|
42827
43167
|
];
|
|
42828
43168
|
for (const testFile of possibleTestFiles) {
|
|
42829
43169
|
if (fs16.existsSync(testFile)) {
|
|
@@ -42844,7 +43184,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
42844
43184
|
try {
|
|
42845
43185
|
const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
|
|
42846
43186
|
const content = fs16.readFileSync(absoluteTestFile, "utf-8");
|
|
42847
|
-
const testDir =
|
|
43187
|
+
const testDir = path29.dirname(absoluteTestFile);
|
|
42848
43188
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
42849
43189
|
let match;
|
|
42850
43190
|
match = importRegex.exec(content);
|
|
@@ -42852,8 +43192,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
42852
43192
|
const importPath = match[1];
|
|
42853
43193
|
let resolvedImport;
|
|
42854
43194
|
if (importPath.startsWith(".")) {
|
|
42855
|
-
resolvedImport =
|
|
42856
|
-
const existingExt =
|
|
43195
|
+
resolvedImport = path29.resolve(testDir, importPath);
|
|
43196
|
+
const existingExt = path29.extname(resolvedImport);
|
|
42857
43197
|
if (!existingExt) {
|
|
42858
43198
|
for (const extToTry of [
|
|
42859
43199
|
".ts",
|
|
@@ -42873,12 +43213,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
42873
43213
|
} else {
|
|
42874
43214
|
continue;
|
|
42875
43215
|
}
|
|
42876
|
-
const importBasename =
|
|
42877
|
-
const importDir =
|
|
43216
|
+
const importBasename = path29.basename(resolvedImport, path29.extname(resolvedImport));
|
|
43217
|
+
const importDir = path29.dirname(resolvedImport);
|
|
42878
43218
|
for (const sourceFile of absoluteSourceFiles) {
|
|
42879
|
-
const sourceDir =
|
|
42880
|
-
const sourceBasename =
|
|
42881
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
43219
|
+
const sourceDir = path29.dirname(sourceFile);
|
|
43220
|
+
const sourceBasename = path29.basename(sourceFile, path29.extname(sourceFile));
|
|
43221
|
+
const isRelatedDir = importDir === sourceDir || importDir === path29.join(sourceDir, "__tests__") || importDir === path29.join(sourceDir, "tests") || importDir === path29.join(sourceDir, "test") || importDir === path29.join(sourceDir, "spec");
|
|
42882
43222
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
42883
43223
|
dedupePush(testFiles, testFile);
|
|
42884
43224
|
break;
|
|
@@ -42891,8 +43231,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
42891
43231
|
while (match !== null) {
|
|
42892
43232
|
const importPath = match[1];
|
|
42893
43233
|
if (importPath.startsWith(".")) {
|
|
42894
|
-
let resolvedImport =
|
|
42895
|
-
const existingExt =
|
|
43234
|
+
let resolvedImport = path29.resolve(testDir, importPath);
|
|
43235
|
+
const existingExt = path29.extname(resolvedImport);
|
|
42896
43236
|
if (!existingExt) {
|
|
42897
43237
|
for (const extToTry of [
|
|
42898
43238
|
".ts",
|
|
@@ -42909,12 +43249,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
42909
43249
|
}
|
|
42910
43250
|
}
|
|
42911
43251
|
}
|
|
42912
|
-
const importDir =
|
|
42913
|
-
const importBasename =
|
|
43252
|
+
const importDir = path29.dirname(resolvedImport);
|
|
43253
|
+
const importBasename = path29.basename(resolvedImport, path29.extname(resolvedImport));
|
|
42914
43254
|
for (const sourceFile of absoluteSourceFiles) {
|
|
42915
|
-
const sourceDir =
|
|
42916
|
-
const sourceBasename =
|
|
42917
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
43255
|
+
const sourceDir = path29.dirname(sourceFile);
|
|
43256
|
+
const sourceBasename = path29.basename(sourceFile, path29.extname(sourceFile));
|
|
43257
|
+
const isRelatedDir = importDir === sourceDir || importDir === path29.join(sourceDir, "__tests__") || importDir === path29.join(sourceDir, "tests") || importDir === path29.join(sourceDir, "test") || importDir === path29.join(sourceDir, "spec");
|
|
42918
43258
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
42919
43259
|
dedupePush(testFiles, testFile);
|
|
42920
43260
|
break;
|
|
@@ -43017,8 +43357,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
43017
43357
|
return ["mvn", "test"];
|
|
43018
43358
|
case "gradle": {
|
|
43019
43359
|
const isWindows = process.platform === "win32";
|
|
43020
|
-
const hasGradlewBat = fs16.existsSync(
|
|
43021
|
-
const hasGradlew = fs16.existsSync(
|
|
43360
|
+
const hasGradlewBat = fs16.existsSync(path29.join(baseDir, "gradlew.bat"));
|
|
43361
|
+
const hasGradlew = fs16.existsSync(path29.join(baseDir, "gradlew"));
|
|
43022
43362
|
if (hasGradlewBat && isWindows)
|
|
43023
43363
|
return ["gradlew.bat", "test"];
|
|
43024
43364
|
if (hasGradlew)
|
|
@@ -43035,7 +43375,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
43035
43375
|
"cmake-build-release",
|
|
43036
43376
|
"out"
|
|
43037
43377
|
];
|
|
43038
|
-
const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(
|
|
43378
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(path29.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
43039
43379
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
43040
43380
|
}
|
|
43041
43381
|
case "swift-test":
|
|
@@ -43351,7 +43691,7 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
43351
43691
|
}
|
|
43352
43692
|
const startTime = Date.now();
|
|
43353
43693
|
try {
|
|
43354
|
-
const proc =
|
|
43694
|
+
const proc = bunSpawn(command, {
|
|
43355
43695
|
stdout: "pipe",
|
|
43356
43696
|
stderr: "pipe",
|
|
43357
43697
|
cwd
|
|
@@ -43663,7 +44003,7 @@ var test_runner = createSwarmTool({
|
|
|
43663
44003
|
const sourceFiles = args.files.filter((file3) => {
|
|
43664
44004
|
if (directTestFiles.includes(file3))
|
|
43665
44005
|
return false;
|
|
43666
|
-
const ext =
|
|
44006
|
+
const ext = path29.extname(file3).toLowerCase();
|
|
43667
44007
|
return SOURCE_EXTENSIONS.has(ext);
|
|
43668
44008
|
});
|
|
43669
44009
|
const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
|
|
@@ -43698,7 +44038,7 @@ var test_runner = createSwarmTool({
|
|
|
43698
44038
|
if (isConventionTestFilePath(f)) {
|
|
43699
44039
|
return false;
|
|
43700
44040
|
}
|
|
43701
|
-
const ext =
|
|
44041
|
+
const ext = path29.extname(f).toLowerCase();
|
|
43702
44042
|
return SOURCE_EXTENSIONS.has(ext);
|
|
43703
44043
|
});
|
|
43704
44044
|
if (sourceFiles.length === 0) {
|
|
@@ -43725,7 +44065,7 @@ var test_runner = createSwarmTool({
|
|
|
43725
44065
|
if (isConventionTestFilePath(f)) {
|
|
43726
44066
|
return false;
|
|
43727
44067
|
}
|
|
43728
|
-
const ext =
|
|
44068
|
+
const ext = path29.extname(f).toLowerCase();
|
|
43729
44069
|
return SOURCE_EXTENSIONS.has(ext);
|
|
43730
44070
|
});
|
|
43731
44071
|
if (sourceFiles.length === 0) {
|
|
@@ -43743,8 +44083,8 @@ var test_runner = createSwarmTool({
|
|
|
43743
44083
|
const impactResult = await analyzeImpact(sourceFiles, workingDir);
|
|
43744
44084
|
if (impactResult.impactedTests.length > 0) {
|
|
43745
44085
|
testFiles = impactResult.impactedTests.map((absPath) => {
|
|
43746
|
-
const relativePath =
|
|
43747
|
-
return
|
|
44086
|
+
const relativePath = path29.relative(workingDir, absPath);
|
|
44087
|
+
return path29.isAbsolute(relativePath) ? absPath : relativePath;
|
|
43748
44088
|
});
|
|
43749
44089
|
} else {
|
|
43750
44090
|
graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
|
|
@@ -43837,8 +44177,8 @@ function validateDirectoryPath(dir) {
|
|
|
43837
44177
|
if (dir.includes("..")) {
|
|
43838
44178
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
43839
44179
|
}
|
|
43840
|
-
const normalized =
|
|
43841
|
-
const absolutePath =
|
|
44180
|
+
const normalized = path30.normalize(dir);
|
|
44181
|
+
const absolutePath = path30.isAbsolute(normalized) ? normalized : path30.resolve(normalized);
|
|
43842
44182
|
return absolutePath;
|
|
43843
44183
|
}
|
|
43844
44184
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -43861,7 +44201,7 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
43861
44201
|
}
|
|
43862
44202
|
function getPackageVersion(dir) {
|
|
43863
44203
|
try {
|
|
43864
|
-
const packagePath =
|
|
44204
|
+
const packagePath = path30.join(dir, "package.json");
|
|
43865
44205
|
if (fs17.existsSync(packagePath)) {
|
|
43866
44206
|
const content = fs17.readFileSync(packagePath, "utf-8");
|
|
43867
44207
|
const pkg = JSON.parse(content);
|
|
@@ -43872,7 +44212,7 @@ function getPackageVersion(dir) {
|
|
|
43872
44212
|
}
|
|
43873
44213
|
function getChangelogVersion(dir) {
|
|
43874
44214
|
try {
|
|
43875
|
-
const changelogPath =
|
|
44215
|
+
const changelogPath = path30.join(dir, "CHANGELOG.md");
|
|
43876
44216
|
if (fs17.existsSync(changelogPath)) {
|
|
43877
44217
|
const content = fs17.readFileSync(changelogPath, "utf-8");
|
|
43878
44218
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
@@ -43886,7 +44226,7 @@ function getChangelogVersion(dir) {
|
|
|
43886
44226
|
function getVersionFileVersion(dir) {
|
|
43887
44227
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
43888
44228
|
for (const file3 of possibleFiles) {
|
|
43889
|
-
const filePath =
|
|
44229
|
+
const filePath = path30.join(dir, file3);
|
|
43890
44230
|
if (fs17.existsSync(filePath)) {
|
|
43891
44231
|
try {
|
|
43892
44232
|
const content = fs17.readFileSync(filePath, "utf-8").trim();
|
|
@@ -44213,7 +44553,7 @@ async function runEvidenceCheck(dir) {
|
|
|
44213
44553
|
async function runRequirementCoverageCheck(dir, currentPhase) {
|
|
44214
44554
|
const startTime = Date.now();
|
|
44215
44555
|
try {
|
|
44216
|
-
const specPath =
|
|
44556
|
+
const specPath = path30.join(dir, ".swarm", "spec.md");
|
|
44217
44557
|
if (!fs17.existsSync(specPath)) {
|
|
44218
44558
|
return {
|
|
44219
44559
|
type: "req_coverage",
|
|
@@ -44597,7 +44937,7 @@ async function handleQaGatesCommand(directory, args, sessionID) {
|
|
|
44597
44937
|
|
|
44598
44938
|
// src/commands/reset.ts
|
|
44599
44939
|
import * as fs18 from "fs";
|
|
44600
|
-
import * as
|
|
44940
|
+
import * as path31 from "path";
|
|
44601
44941
|
|
|
44602
44942
|
// src/background/manager.ts
|
|
44603
44943
|
init_utils();
|
|
@@ -45318,7 +45658,7 @@ async function handleResetCommand(directory, args) {
|
|
|
45318
45658
|
}
|
|
45319
45659
|
for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
|
|
45320
45660
|
try {
|
|
45321
|
-
const rootPath =
|
|
45661
|
+
const rootPath = path31.join(directory, filename);
|
|
45322
45662
|
if (fs18.existsSync(rootPath)) {
|
|
45323
45663
|
fs18.unlinkSync(rootPath);
|
|
45324
45664
|
results.push(`- \u2705 Deleted ${filename} (root)`);
|
|
@@ -45355,7 +45695,7 @@ async function handleResetCommand(directory, args) {
|
|
|
45355
45695
|
// src/commands/reset-session.ts
|
|
45356
45696
|
init_utils2();
|
|
45357
45697
|
import * as fs19 from "fs";
|
|
45358
|
-
import * as
|
|
45698
|
+
import * as path32 from "path";
|
|
45359
45699
|
async function handleResetSessionCommand(directory, _args) {
|
|
45360
45700
|
const results = [];
|
|
45361
45701
|
try {
|
|
@@ -45370,13 +45710,13 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
45370
45710
|
results.push("\u274C Failed to delete state.json");
|
|
45371
45711
|
}
|
|
45372
45712
|
try {
|
|
45373
|
-
const sessionDir =
|
|
45713
|
+
const sessionDir = path32.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
45374
45714
|
if (fs19.existsSync(sessionDir)) {
|
|
45375
45715
|
const files = fs19.readdirSync(sessionDir);
|
|
45376
45716
|
const otherFiles = files.filter((f) => f !== "state.json");
|
|
45377
45717
|
let deletedCount = 0;
|
|
45378
45718
|
for (const file3 of otherFiles) {
|
|
45379
|
-
const filePath =
|
|
45719
|
+
const filePath = path32.join(sessionDir, file3);
|
|
45380
45720
|
if (fs19.lstatSync(filePath).isFile()) {
|
|
45381
45721
|
fs19.unlinkSync(filePath);
|
|
45382
45722
|
deletedCount++;
|
|
@@ -45406,7 +45746,8 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
45406
45746
|
// src/summaries/manager.ts
|
|
45407
45747
|
init_utils2();
|
|
45408
45748
|
init_utils();
|
|
45409
|
-
|
|
45749
|
+
init_bun_compat();
|
|
45750
|
+
import * as path33 from "path";
|
|
45410
45751
|
var SUMMARY_ID_REGEX = /^S\d+$/;
|
|
45411
45752
|
function sanitizeSummaryId(id) {
|
|
45412
45753
|
if (!id || id.length === 0) {
|
|
@@ -45430,7 +45771,7 @@ function sanitizeSummaryId(id) {
|
|
|
45430
45771
|
}
|
|
45431
45772
|
async function loadFullOutput(directory, id) {
|
|
45432
45773
|
const sanitizedId = sanitizeSummaryId(id);
|
|
45433
|
-
const relativePath =
|
|
45774
|
+
const relativePath = path33.join("summaries", `${sanitizedId}.json`);
|
|
45434
45775
|
validateSwarmPath(directory, relativePath);
|
|
45435
45776
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
45436
45777
|
if (content === null) {
|
|
@@ -45486,7 +45827,7 @@ init_plan_schema();
|
|
|
45486
45827
|
init_utils2();
|
|
45487
45828
|
init_ledger();
|
|
45488
45829
|
import * as fs20 from "fs";
|
|
45489
|
-
import * as
|
|
45830
|
+
import * as path34 from "path";
|
|
45490
45831
|
async function handleRollbackCommand(directory, args) {
|
|
45491
45832
|
const phaseArg = args[0];
|
|
45492
45833
|
if (!phaseArg) {
|
|
@@ -45551,8 +45892,8 @@ async function handleRollbackCommand(directory, args) {
|
|
|
45551
45892
|
if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
|
|
45552
45893
|
continue;
|
|
45553
45894
|
}
|
|
45554
|
-
const src =
|
|
45555
|
-
const dest =
|
|
45895
|
+
const src = path34.join(checkpointDir, file3);
|
|
45896
|
+
const dest = path34.join(swarmDir, file3);
|
|
45556
45897
|
try {
|
|
45557
45898
|
fs20.cpSync(src, dest, { recursive: true, force: true });
|
|
45558
45899
|
successes.push(file3);
|
|
@@ -45571,12 +45912,12 @@ async function handleRollbackCommand(directory, args) {
|
|
|
45571
45912
|
].join(`
|
|
45572
45913
|
`);
|
|
45573
45914
|
}
|
|
45574
|
-
const existingLedgerPath =
|
|
45915
|
+
const existingLedgerPath = path34.join(swarmDir, "plan-ledger.jsonl");
|
|
45575
45916
|
if (fs20.existsSync(existingLedgerPath)) {
|
|
45576
45917
|
fs20.unlinkSync(existingLedgerPath);
|
|
45577
45918
|
}
|
|
45578
45919
|
try {
|
|
45579
|
-
const planJsonPath =
|
|
45920
|
+
const planJsonPath = path34.join(swarmDir, "plan.json");
|
|
45580
45921
|
if (fs20.existsSync(planJsonPath)) {
|
|
45581
45922
|
const planRaw = fs20.readFileSync(planJsonPath, "utf-8");
|
|
45582
45923
|
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
@@ -45649,9 +45990,9 @@ async function handleSimulateCommand(directory, args) {
|
|
|
45649
45990
|
const report = reportLines.filter(Boolean).join(`
|
|
45650
45991
|
`);
|
|
45651
45992
|
const fs21 = await import("fs/promises");
|
|
45652
|
-
const
|
|
45653
|
-
const reportPath =
|
|
45654
|
-
await fs21.mkdir(
|
|
45993
|
+
const path35 = await import("path");
|
|
45994
|
+
const reportPath = path35.join(directory, ".swarm", "simulate-report.md");
|
|
45995
|
+
await fs21.mkdir(path35.dirname(reportPath), { recursive: true });
|
|
45655
45996
|
await fs21.writeFile(reportPath, report, "utf-8");
|
|
45656
45997
|
return `${darkMatterPairs.length} hidden coupling pairs detected`;
|
|
45657
45998
|
}
|
|
@@ -45711,6 +46052,7 @@ function getCompactionMetrics(sessionId) {
|
|
|
45711
46052
|
|
|
45712
46053
|
// src/services/context-budget-service.ts
|
|
45713
46054
|
init_utils2();
|
|
46055
|
+
init_bun_compat();
|
|
45714
46056
|
var DEFAULT_CONTEXT_BUDGET_CONFIG = {
|
|
45715
46057
|
enabled: true,
|
|
45716
46058
|
budgetTokens: 40000,
|
|
@@ -46199,50 +46541,50 @@ function resolveCommand(tokens) {
|
|
|
46199
46541
|
// src/cli/index.ts
|
|
46200
46542
|
var { version: version4 } = package_default;
|
|
46201
46543
|
var CONFIG_DIR = getPluginConfigDir();
|
|
46202
|
-
var OPENCODE_CONFIG_PATH =
|
|
46203
|
-
var PLUGIN_CONFIG_PATH =
|
|
46204
|
-
var PROMPTS_DIR =
|
|
46544
|
+
var OPENCODE_CONFIG_PATH = path35.join(CONFIG_DIR, "opencode.json");
|
|
46545
|
+
var PLUGIN_CONFIG_PATH = path35.join(CONFIG_DIR, "opencode-swarm.json");
|
|
46546
|
+
var PROMPTS_DIR = path35.join(CONFIG_DIR, "opencode-swarm");
|
|
46205
46547
|
var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
|
|
46206
46548
|
var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
|
|
46207
46549
|
function isSafeCachePath(p) {
|
|
46208
|
-
const resolved =
|
|
46209
|
-
const home =
|
|
46550
|
+
const resolved = path35.resolve(p);
|
|
46551
|
+
const home = path35.resolve(os7.homedir());
|
|
46210
46552
|
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
46211
46553
|
return false;
|
|
46212
46554
|
}
|
|
46213
|
-
const segments = resolved.split(
|
|
46555
|
+
const segments = resolved.split(path35.sep).filter((s) => s.length > 0);
|
|
46214
46556
|
if (segments.length < 4) {
|
|
46215
46557
|
return false;
|
|
46216
46558
|
}
|
|
46217
|
-
const leaf =
|
|
46559
|
+
const leaf = path35.basename(resolved);
|
|
46218
46560
|
if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
|
|
46219
46561
|
return false;
|
|
46220
46562
|
}
|
|
46221
|
-
const parent =
|
|
46563
|
+
const parent = path35.basename(path35.dirname(resolved));
|
|
46222
46564
|
if (parent !== "packages" && parent !== "node_modules") {
|
|
46223
46565
|
return false;
|
|
46224
46566
|
}
|
|
46225
|
-
const grandparent =
|
|
46567
|
+
const grandparent = path35.basename(path35.dirname(path35.dirname(resolved)));
|
|
46226
46568
|
if (grandparent !== "opencode") {
|
|
46227
46569
|
return false;
|
|
46228
46570
|
}
|
|
46229
46571
|
return true;
|
|
46230
46572
|
}
|
|
46231
46573
|
function isSafeLockFilePath(p) {
|
|
46232
|
-
const resolved =
|
|
46233
|
-
const home =
|
|
46574
|
+
const resolved = path35.resolve(p);
|
|
46575
|
+
const home = path35.resolve(os7.homedir());
|
|
46234
46576
|
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
46235
46577
|
return false;
|
|
46236
46578
|
}
|
|
46237
|
-
const segments = resolved.split(
|
|
46579
|
+
const segments = resolved.split(path35.sep).filter((s) => s.length > 0);
|
|
46238
46580
|
if (segments.length < 4) {
|
|
46239
46581
|
return false;
|
|
46240
46582
|
}
|
|
46241
|
-
const leaf =
|
|
46583
|
+
const leaf = path35.basename(resolved);
|
|
46242
46584
|
if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
|
|
46243
46585
|
return false;
|
|
46244
46586
|
}
|
|
46245
|
-
const parent =
|
|
46587
|
+
const parent = path35.basename(path35.dirname(resolved));
|
|
46246
46588
|
if (parent !== "opencode") {
|
|
46247
46589
|
return false;
|
|
46248
46590
|
}
|
|
@@ -46268,8 +46610,8 @@ function saveJson(filepath, data) {
|
|
|
46268
46610
|
}
|
|
46269
46611
|
function writeProjectConfigIfMissing(cwd) {
|
|
46270
46612
|
try {
|
|
46271
|
-
const opencodeDir =
|
|
46272
|
-
const projectConfigPath =
|
|
46613
|
+
const opencodeDir = path35.join(cwd, ".opencode");
|
|
46614
|
+
const projectConfigPath = path35.join(opencodeDir, "opencode-swarm.json");
|
|
46273
46615
|
if (fs21.existsSync(projectConfigPath)) {
|
|
46274
46616
|
return;
|
|
46275
46617
|
}
|
|
@@ -46287,7 +46629,7 @@ async function install() {
|
|
|
46287
46629
|
`);
|
|
46288
46630
|
ensureDir(CONFIG_DIR);
|
|
46289
46631
|
ensureDir(PROMPTS_DIR);
|
|
46290
|
-
const LEGACY_CONFIG_PATH =
|
|
46632
|
+
const LEGACY_CONFIG_PATH = path35.join(CONFIG_DIR, "config.json");
|
|
46291
46633
|
let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
|
|
46292
46634
|
if (!opencodeConfig) {
|
|
46293
46635
|
const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
|