opencode-swarm 6.44.0 → 6.44.1
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 +44 -8
- package/dist/index.js +70 -24
- package/dist/tools/lint.d.ts +8 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -37327,8 +37327,31 @@ function detectAdditionalLinter(cwd) {
|
|
|
37327
37327
|
return "rubocop";
|
|
37328
37328
|
return null;
|
|
37329
37329
|
}
|
|
37330
|
+
function findBinInAncestors(startDir, binName) {
|
|
37331
|
+
let dir = startDir;
|
|
37332
|
+
while (true) {
|
|
37333
|
+
const candidate = path19.join(dir, "node_modules", ".bin", binName);
|
|
37334
|
+
if (fs9.existsSync(candidate))
|
|
37335
|
+
return candidate;
|
|
37336
|
+
const parent = path19.dirname(dir);
|
|
37337
|
+
if (parent === dir)
|
|
37338
|
+
break;
|
|
37339
|
+
dir = parent;
|
|
37340
|
+
}
|
|
37341
|
+
return null;
|
|
37342
|
+
}
|
|
37343
|
+
function findBinInEnvPath(binName) {
|
|
37344
|
+
const searchPath = process.env.PATH ?? "";
|
|
37345
|
+
for (const dir of searchPath.split(path19.delimiter)) {
|
|
37346
|
+
if (!dir)
|
|
37347
|
+
continue;
|
|
37348
|
+
const candidate = path19.join(dir, binName);
|
|
37349
|
+
if (fs9.existsSync(candidate))
|
|
37350
|
+
return candidate;
|
|
37351
|
+
}
|
|
37352
|
+
return null;
|
|
37353
|
+
}
|
|
37330
37354
|
async function detectAvailableLinter(directory) {
|
|
37331
|
-
const _DETECT_TIMEOUT = 2000;
|
|
37332
37355
|
if (!directory)
|
|
37333
37356
|
return null;
|
|
37334
37357
|
if (!fs9.existsSync(directory))
|
|
@@ -37337,7 +37360,20 @@ async function detectAvailableLinter(directory) {
|
|
|
37337
37360
|
const isWindows = process.platform === "win32";
|
|
37338
37361
|
const biomeBin = isWindows ? path19.join(projectDir, "node_modules", ".bin", "biome.EXE") : path19.join(projectDir, "node_modules", ".bin", "biome");
|
|
37339
37362
|
const eslintBin = isWindows ? path19.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path19.join(projectDir, "node_modules", ".bin", "eslint");
|
|
37340
|
-
|
|
37363
|
+
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
37364
|
+
if (localResult)
|
|
37365
|
+
return localResult;
|
|
37366
|
+
const biomeAncestor = findBinInAncestors(path19.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
37367
|
+
const eslintAncestor = findBinInAncestors(path19.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
37368
|
+
if (biomeAncestor || eslintAncestor) {
|
|
37369
|
+
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
37370
|
+
}
|
|
37371
|
+
const pathBiome = findBinInEnvPath(isWindows ? "biome.EXE" : "biome");
|
|
37372
|
+
const pathEslint = findBinInEnvPath(isWindows ? "eslint.cmd" : "eslint");
|
|
37373
|
+
if (pathBiome || pathEslint) {
|
|
37374
|
+
return _detectAvailableLinter(projectDir, pathBiome ?? biomeBin, pathEslint ?? eslintBin);
|
|
37375
|
+
}
|
|
37376
|
+
return null;
|
|
37341
37377
|
}
|
|
37342
37378
|
async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
|
|
37343
37379
|
const DETECT_TIMEOUT = 2000;
|
|
@@ -38499,7 +38535,7 @@ function getTestFilesFromConvention(sourceFiles) {
|
|
|
38499
38535
|
for (const file3 of sourceFiles) {
|
|
38500
38536
|
const normalizedPath = file3.replace(/\\/g, "/");
|
|
38501
38537
|
const basename4 = path22.basename(file3);
|
|
38502
|
-
const
|
|
38538
|
+
const dirname10 = path22.dirname(file3);
|
|
38503
38539
|
if (hasCompoundTestExtension(basename4) || basename4.includes(".spec.") || basename4.includes(".test.") || normalizedPath.includes("/__tests__/") || normalizedPath.includes("/tests/") || normalizedPath.includes("/test/")) {
|
|
38504
38540
|
if (!testFiles.includes(file3)) {
|
|
38505
38541
|
testFiles.push(file3);
|
|
@@ -38510,11 +38546,11 @@ function getTestFilesFromConvention(sourceFiles) {
|
|
|
38510
38546
|
const nameWithoutExt = basename4.replace(/\.[^.]+$/, "");
|
|
38511
38547
|
const ext = path22.extname(basename4);
|
|
38512
38548
|
const possibleTestFiles = [
|
|
38513
|
-
path22.join(
|
|
38514
|
-
path22.join(
|
|
38515
|
-
path22.join(
|
|
38516
|
-
path22.join(
|
|
38517
|
-
path22.join(
|
|
38549
|
+
path22.join(dirname10, `${nameWithoutExt}.spec${ext}`),
|
|
38550
|
+
path22.join(dirname10, `${nameWithoutExt}.test${ext}`),
|
|
38551
|
+
path22.join(dirname10, "__tests__", `${nameWithoutExt}${ext}`),
|
|
38552
|
+
path22.join(dirname10, "tests", `${nameWithoutExt}${ext}`),
|
|
38553
|
+
path22.join(dirname10, "test", `${nameWithoutExt}${ext}`)
|
|
38518
38554
|
];
|
|
38519
38555
|
for (const testFile of possibleTestFiles) {
|
|
38520
38556
|
if (fs12.existsSync(testFile) && !testFiles.includes(testFile)) {
|
package/dist/index.js
CHANGED
|
@@ -35010,8 +35010,45 @@ function detectAdditionalLinter(cwd) {
|
|
|
35010
35010
|
return "rubocop";
|
|
35011
35011
|
return null;
|
|
35012
35012
|
}
|
|
35013
|
+
function resolveLinterBinPath(linter, projectDir) {
|
|
35014
|
+
const isWindows = process.platform === "win32";
|
|
35015
|
+
const binName = linter === "biome" ? isWindows ? "biome.EXE" : "biome" : isWindows ? "eslint.cmd" : "eslint";
|
|
35016
|
+
const localBin = path26.join(projectDir, "node_modules", ".bin", binName);
|
|
35017
|
+
if (fs15.existsSync(localBin))
|
|
35018
|
+
return localBin;
|
|
35019
|
+
const ancestor = findBinInAncestors(path26.dirname(projectDir), binName);
|
|
35020
|
+
if (ancestor)
|
|
35021
|
+
return ancestor;
|
|
35022
|
+
const fromPath = findBinInEnvPath(binName);
|
|
35023
|
+
if (fromPath)
|
|
35024
|
+
return fromPath;
|
|
35025
|
+
return localBin;
|
|
35026
|
+
}
|
|
35027
|
+
function findBinInAncestors(startDir, binName) {
|
|
35028
|
+
let dir = startDir;
|
|
35029
|
+
while (true) {
|
|
35030
|
+
const candidate = path26.join(dir, "node_modules", ".bin", binName);
|
|
35031
|
+
if (fs15.existsSync(candidate))
|
|
35032
|
+
return candidate;
|
|
35033
|
+
const parent = path26.dirname(dir);
|
|
35034
|
+
if (parent === dir)
|
|
35035
|
+
break;
|
|
35036
|
+
dir = parent;
|
|
35037
|
+
}
|
|
35038
|
+
return null;
|
|
35039
|
+
}
|
|
35040
|
+
function findBinInEnvPath(binName) {
|
|
35041
|
+
const searchPath = process.env.PATH ?? "";
|
|
35042
|
+
for (const dir of searchPath.split(path26.delimiter)) {
|
|
35043
|
+
if (!dir)
|
|
35044
|
+
continue;
|
|
35045
|
+
const candidate = path26.join(dir, binName);
|
|
35046
|
+
if (fs15.existsSync(candidate))
|
|
35047
|
+
return candidate;
|
|
35048
|
+
}
|
|
35049
|
+
return null;
|
|
35050
|
+
}
|
|
35013
35051
|
async function detectAvailableLinter(directory) {
|
|
35014
|
-
const _DETECT_TIMEOUT = 2000;
|
|
35015
35052
|
if (!directory)
|
|
35016
35053
|
return null;
|
|
35017
35054
|
if (!fs15.existsSync(directory))
|
|
@@ -35020,7 +35057,20 @@ async function detectAvailableLinter(directory) {
|
|
|
35020
35057
|
const isWindows = process.platform === "win32";
|
|
35021
35058
|
const biomeBin = isWindows ? path26.join(projectDir, "node_modules", ".bin", "biome.EXE") : path26.join(projectDir, "node_modules", ".bin", "biome");
|
|
35022
35059
|
const eslintBin = isWindows ? path26.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path26.join(projectDir, "node_modules", ".bin", "eslint");
|
|
35023
|
-
|
|
35060
|
+
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
35061
|
+
if (localResult)
|
|
35062
|
+
return localResult;
|
|
35063
|
+
const biomeAncestor = findBinInAncestors(path26.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
35064
|
+
const eslintAncestor = findBinInAncestors(path26.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
35065
|
+
if (biomeAncestor || eslintAncestor) {
|
|
35066
|
+
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
35067
|
+
}
|
|
35068
|
+
const pathBiome = findBinInEnvPath(isWindows ? "biome.EXE" : "biome");
|
|
35069
|
+
const pathEslint = findBinInEnvPath(isWindows ? "eslint.cmd" : "eslint");
|
|
35070
|
+
if (pathBiome || pathEslint) {
|
|
35071
|
+
return _detectAvailableLinter(projectDir, pathBiome ?? biomeBin, pathEslint ?? eslintBin);
|
|
35072
|
+
}
|
|
35073
|
+
return null;
|
|
35024
35074
|
}
|
|
35025
35075
|
async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
|
|
35026
35076
|
const DETECT_TIMEOUT = 2000;
|
|
@@ -36160,7 +36210,7 @@ function getTestFilesFromConvention(sourceFiles) {
|
|
|
36160
36210
|
for (const file3 of sourceFiles) {
|
|
36161
36211
|
const normalizedPath = file3.replace(/\\/g, "/");
|
|
36162
36212
|
const basename4 = path29.basename(file3);
|
|
36163
|
-
const
|
|
36213
|
+
const dirname12 = path29.dirname(file3);
|
|
36164
36214
|
if (hasCompoundTestExtension(basename4) || basename4.includes(".spec.") || basename4.includes(".test.") || normalizedPath.includes("/__tests__/") || normalizedPath.includes("/tests/") || normalizedPath.includes("/test/")) {
|
|
36165
36215
|
if (!testFiles.includes(file3)) {
|
|
36166
36216
|
testFiles.push(file3);
|
|
@@ -36171,11 +36221,11 @@ function getTestFilesFromConvention(sourceFiles) {
|
|
|
36171
36221
|
const nameWithoutExt = basename4.replace(/\.[^.]+$/, "");
|
|
36172
36222
|
const ext = path29.extname(basename4);
|
|
36173
36223
|
const possibleTestFiles = [
|
|
36174
|
-
path29.join(
|
|
36175
|
-
path29.join(
|
|
36176
|
-
path29.join(
|
|
36177
|
-
path29.join(
|
|
36178
|
-
path29.join(
|
|
36224
|
+
path29.join(dirname12, `${nameWithoutExt}.spec${ext}`),
|
|
36225
|
+
path29.join(dirname12, `${nameWithoutExt}.test${ext}`),
|
|
36226
|
+
path29.join(dirname12, "__tests__", `${nameWithoutExt}${ext}`),
|
|
36227
|
+
path29.join(dirname12, "tests", `${nameWithoutExt}${ext}`),
|
|
36228
|
+
path29.join(dirname12, "test", `${nameWithoutExt}${ext}`)
|
|
36179
36229
|
];
|
|
36180
36230
|
for (const testFile of possibleTestFiles) {
|
|
36181
36231
|
if (fs18.existsSync(testFile) && !testFiles.includes(testFile)) {
|
|
@@ -45688,10 +45738,7 @@ class PlanSyncWorker {
|
|
|
45688
45738
|
lastStat = null;
|
|
45689
45739
|
disposed = false;
|
|
45690
45740
|
constructor(options = {}) {
|
|
45691
|
-
|
|
45692
|
-
throw new Error("[plan-sync-worker] No directory provided - options.directory is required");
|
|
45693
|
-
}
|
|
45694
|
-
this.directory = options.directory;
|
|
45741
|
+
this.directory = options.directory ?? "";
|
|
45695
45742
|
this.debounceMs = options.debounceMs ?? 300;
|
|
45696
45743
|
this.pollIntervalMs = options.pollIntervalMs ?? 2000;
|
|
45697
45744
|
this.syncTimeoutMs = options.syncTimeoutMs ?? 30000;
|
|
@@ -45708,6 +45755,10 @@ class PlanSyncWorker {
|
|
|
45708
45755
|
log("[PlanSyncWorker] Cannot start - worker has been disposed");
|
|
45709
45756
|
return;
|
|
45710
45757
|
}
|
|
45758
|
+
if (!this.directory) {
|
|
45759
|
+
log("[PlanSyncWorker] Cannot start - no directory provided");
|
|
45760
|
+
return;
|
|
45761
|
+
}
|
|
45711
45762
|
if (this.status === "running" || this.status === "starting") {
|
|
45712
45763
|
log("[PlanSyncWorker] Already running or starting");
|
|
45713
45764
|
return;
|
|
@@ -45715,10 +45766,8 @@ class PlanSyncWorker {
|
|
|
45715
45766
|
this.status = "starting";
|
|
45716
45767
|
log("[PlanSyncWorker] Starting...");
|
|
45717
45768
|
this.initializeStat();
|
|
45718
|
-
|
|
45719
|
-
|
|
45720
|
-
this.setupPolling();
|
|
45721
|
-
}
|
|
45769
|
+
this.setupPolling();
|
|
45770
|
+
this.setupNativeWatcher();
|
|
45722
45771
|
this.status = "running";
|
|
45723
45772
|
log("[PlanSyncWorker] Started watching for plan.json changes");
|
|
45724
45773
|
}
|
|
@@ -53417,7 +53466,7 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
|
53417
53466
|
const delegTargetPath = delegArgs?.filePath ?? delegArgs?.path ?? delegArgs?.file ?? delegArgs?.target;
|
|
53418
53467
|
if (typeof delegTargetPath === "string" && delegTargetPath.length > 0) {
|
|
53419
53468
|
const agentName = swarmState.activeAgent.get(sessionID) ?? "unknown";
|
|
53420
|
-
const cwd =
|
|
53469
|
+
const cwd = effectiveDirectory;
|
|
53421
53470
|
const authorityCheck = checkFileAuthority(agentName, delegTargetPath, cwd);
|
|
53422
53471
|
if (!authorityCheck.allowed) {
|
|
53423
53472
|
throw new Error(`WRITE BLOCKED: Agent "${agentName}" is not authorised to write "${delegTargetPath}". Reason: ${authorityCheck.reason}`);
|
|
@@ -65217,8 +65266,6 @@ async function runLintWrapped(files, directory, _config) {
|
|
|
65217
65266
|
}
|
|
65218
65267
|
}
|
|
65219
65268
|
async function runLintOnFiles(linter, files, workspaceDir) {
|
|
65220
|
-
const isWindows = process.platform === "win32";
|
|
65221
|
-
const binDir = path60.join(workspaceDir, "node_modules", ".bin");
|
|
65222
65269
|
const validatedFiles = [];
|
|
65223
65270
|
for (const file3 of files) {
|
|
65224
65271
|
if (typeof file3 !== "string") {
|
|
@@ -65240,13 +65287,12 @@ async function runLintOnFiles(linter, files, workspaceDir) {
|
|
|
65240
65287
|
error: "No valid files after security validation"
|
|
65241
65288
|
};
|
|
65242
65289
|
}
|
|
65290
|
+
const resolvedBin = resolveLinterBinPath(linter, workspaceDir);
|
|
65243
65291
|
let command;
|
|
65244
65292
|
if (linter === "biome") {
|
|
65245
|
-
|
|
65246
|
-
command = [biomeBin, "check", ...validatedFiles];
|
|
65293
|
+
command = [resolvedBin, "check", ...validatedFiles];
|
|
65247
65294
|
} else {
|
|
65248
|
-
|
|
65249
|
-
command = [eslintBin, ...validatedFiles];
|
|
65295
|
+
command = [resolvedBin, ...validatedFiles];
|
|
65250
65296
|
}
|
|
65251
65297
|
try {
|
|
65252
65298
|
const proc = Bun.spawn(command, {
|
|
@@ -68339,7 +68385,7 @@ function checkReviewerGate(taskId, workingDirectory) {
|
|
|
68339
68385
|
}
|
|
68340
68386
|
} catch {}
|
|
68341
68387
|
}
|
|
68342
|
-
const resolvedDir = workingDirectory;
|
|
68388
|
+
const resolvedDir = workingDirectory ?? process.cwd();
|
|
68343
68389
|
try {
|
|
68344
68390
|
const evidence = readTaskEvidenceRaw(resolvedDir, taskId);
|
|
68345
68391
|
if (evidence === null) {} else if (evidence.required_gates && Array.isArray(evidence.required_gates) && evidence.gates) {
|
package/dist/tools/lint.d.ts
CHANGED
|
@@ -41,6 +41,14 @@ export declare function getAdditionalLinterCommand(linter: AdditionalLinter, mod
|
|
|
41
41
|
export declare function detectAdditionalLinter(cwd: string): 'ruff' | 'clippy' | 'golangci-lint' | 'checkstyle' | 'ktlint' | 'dotnet-format' | 'cppcheck' | 'swiftlint' | 'dart-analyze' | 'rubocop' | null;
|
|
42
42
|
/** Compute the local biome binary path for a given project directory. */
|
|
43
43
|
export declare function getBiomeBinPath(directory: string): string;
|
|
44
|
+
/**
|
|
45
|
+
* Resolve the binary path for a linter, using the same hierarchy as detectAvailableLinter:
|
|
46
|
+
* 1. Local node_modules/.bin
|
|
47
|
+
* 2. Ancestor node_modules/.bin (monorepo)
|
|
48
|
+
* 3. process.env.PATH scan
|
|
49
|
+
* 4. Local path as fallback (may not exist)
|
|
50
|
+
*/
|
|
51
|
+
export declare function resolveLinterBinPath(linter: SupportedLinter, projectDir: string): string;
|
|
44
52
|
/** Compute the local eslint binary path for a given project directory. */
|
|
45
53
|
export declare function getEslintBinPath(directory: string): string;
|
|
46
54
|
export declare function detectAvailableLinter(directory?: string): Promise<SupportedLinter | null>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "6.44.
|
|
3
|
+
"version": "6.44.1",
|
|
4
4
|
"description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|