opencode-swarm 6.86.7 → 6.86.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -0
- package/dist/cli/index.js +430 -234
- package/dist/config/cache-paths.d.ts +11 -0
- package/dist/config/schema.d.ts +1 -0
- package/dist/db/global-db.d.ts +1 -1
- package/dist/db/project-db.d.ts +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.js +4976 -4772
- package/dist/services/diagnose-service.d.ts +1 -1
- package/dist/services/version-check.d.ts +28 -0
- package/package.json +2 -2
- package/dist/tools/check-gate-status.prefix.test.d.ts +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -17669,14 +17669,14 @@ __export(exports_config_doctor, {
|
|
|
17669
17669
|
});
|
|
17670
17670
|
import * as crypto3 from "crypto";
|
|
17671
17671
|
import * as fs8 from "fs";
|
|
17672
|
-
import * as
|
|
17673
|
-
import * as
|
|
17672
|
+
import * as os6 from "os";
|
|
17673
|
+
import * as path19 from "path";
|
|
17674
17674
|
function getUserConfigDir3() {
|
|
17675
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
17675
|
+
return process.env.XDG_CONFIG_HOME || path19.join(os6.homedir(), ".config");
|
|
17676
17676
|
}
|
|
17677
17677
|
function getConfigPaths(directory) {
|
|
17678
|
-
const userConfigPath =
|
|
17679
|
-
const projectConfigPath =
|
|
17678
|
+
const userConfigPath = path19.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
|
|
17679
|
+
const projectConfigPath = path19.join(directory, ".opencode", "opencode-swarm.json");
|
|
17680
17680
|
return { userConfigPath, projectConfigPath };
|
|
17681
17681
|
}
|
|
17682
17682
|
function computeHash(content) {
|
|
@@ -17701,9 +17701,9 @@ function isValidConfigPath(configPath, directory) {
|
|
|
17701
17701
|
const normalizedUser = userConfigPath.replace(/\\/g, "/");
|
|
17702
17702
|
const normalizedProject = projectConfigPath.replace(/\\/g, "/");
|
|
17703
17703
|
try {
|
|
17704
|
-
const resolvedConfig =
|
|
17705
|
-
const resolvedUser =
|
|
17706
|
-
const resolvedProject =
|
|
17704
|
+
const resolvedConfig = path19.resolve(configPath);
|
|
17705
|
+
const resolvedUser = path19.resolve(normalizedUser);
|
|
17706
|
+
const resolvedProject = path19.resolve(normalizedProject);
|
|
17707
17707
|
return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
|
|
17708
17708
|
} catch {
|
|
17709
17709
|
return false;
|
|
@@ -17743,12 +17743,12 @@ function createConfigBackup(directory) {
|
|
|
17743
17743
|
};
|
|
17744
17744
|
}
|
|
17745
17745
|
function writeBackupArtifact(directory, backup) {
|
|
17746
|
-
const swarmDir =
|
|
17746
|
+
const swarmDir = path19.join(directory, ".swarm");
|
|
17747
17747
|
if (!fs8.existsSync(swarmDir)) {
|
|
17748
17748
|
fs8.mkdirSync(swarmDir, { recursive: true });
|
|
17749
17749
|
}
|
|
17750
17750
|
const backupFilename = `config-backup-${backup.createdAt}.json`;
|
|
17751
|
-
const backupPath =
|
|
17751
|
+
const backupPath = path19.join(swarmDir, backupFilename);
|
|
17752
17752
|
const artifact = {
|
|
17753
17753
|
createdAt: backup.createdAt,
|
|
17754
17754
|
configPath: backup.configPath,
|
|
@@ -17778,7 +17778,7 @@ function restoreFromBackup(backupPath, directory) {
|
|
|
17778
17778
|
return null;
|
|
17779
17779
|
}
|
|
17780
17780
|
const targetPath = artifact.configPath;
|
|
17781
|
-
const targetDir =
|
|
17781
|
+
const targetDir = path19.dirname(targetPath);
|
|
17782
17782
|
if (!fs8.existsSync(targetDir)) {
|
|
17783
17783
|
fs8.mkdirSync(targetDir, { recursive: true });
|
|
17784
17784
|
}
|
|
@@ -17809,9 +17809,9 @@ function readConfigFromFile(directory) {
|
|
|
17809
17809
|
return null;
|
|
17810
17810
|
}
|
|
17811
17811
|
}
|
|
17812
|
-
function validateConfigKey(
|
|
17812
|
+
function validateConfigKey(path20, value, _config) {
|
|
17813
17813
|
const findings = [];
|
|
17814
|
-
switch (
|
|
17814
|
+
switch (path20) {
|
|
17815
17815
|
case "agents": {
|
|
17816
17816
|
if (value !== undefined) {
|
|
17817
17817
|
findings.push({
|
|
@@ -18058,27 +18058,27 @@ function validateConfigKey(path19, value, _config) {
|
|
|
18058
18058
|
}
|
|
18059
18059
|
return findings;
|
|
18060
18060
|
}
|
|
18061
|
-
function walkConfigAndValidate(obj,
|
|
18061
|
+
function walkConfigAndValidate(obj, path20, config3, findings) {
|
|
18062
18062
|
if (obj === null || obj === undefined) {
|
|
18063
18063
|
return;
|
|
18064
18064
|
}
|
|
18065
|
-
if (
|
|
18066
|
-
const keyFindings = validateConfigKey(
|
|
18065
|
+
if (path20 && typeof obj === "object" && !Array.isArray(obj)) {
|
|
18066
|
+
const keyFindings = validateConfigKey(path20, obj, config3);
|
|
18067
18067
|
findings.push(...keyFindings);
|
|
18068
18068
|
}
|
|
18069
18069
|
if (typeof obj !== "object") {
|
|
18070
|
-
const keyFindings = validateConfigKey(
|
|
18070
|
+
const keyFindings = validateConfigKey(path20, obj, config3);
|
|
18071
18071
|
findings.push(...keyFindings);
|
|
18072
18072
|
return;
|
|
18073
18073
|
}
|
|
18074
18074
|
if (Array.isArray(obj)) {
|
|
18075
18075
|
obj.forEach((item, index) => {
|
|
18076
|
-
walkConfigAndValidate(item, `${
|
|
18076
|
+
walkConfigAndValidate(item, `${path20}[${index}]`, config3, findings);
|
|
18077
18077
|
});
|
|
18078
18078
|
return;
|
|
18079
18079
|
}
|
|
18080
18080
|
for (const [key, value] of Object.entries(obj)) {
|
|
18081
|
-
const newPath =
|
|
18081
|
+
const newPath = path20 ? `${path20}.${key}` : key;
|
|
18082
18082
|
walkConfigAndValidate(value, newPath, config3, findings);
|
|
18083
18083
|
}
|
|
18084
18084
|
}
|
|
@@ -18198,7 +18198,7 @@ function applySafeAutoFixes(directory, result) {
|
|
|
18198
18198
|
}
|
|
18199
18199
|
}
|
|
18200
18200
|
if (appliedFixes.length > 0) {
|
|
18201
|
-
const configDir =
|
|
18201
|
+
const configDir = path19.dirname(configPath);
|
|
18202
18202
|
if (!fs8.existsSync(configDir)) {
|
|
18203
18203
|
fs8.mkdirSync(configDir, { recursive: true });
|
|
18204
18204
|
}
|
|
@@ -18208,12 +18208,12 @@ function applySafeAutoFixes(directory, result) {
|
|
|
18208
18208
|
return { appliedFixes, updatedConfigPath };
|
|
18209
18209
|
}
|
|
18210
18210
|
function writeDoctorArtifact(directory, result) {
|
|
18211
|
-
const swarmDir =
|
|
18211
|
+
const swarmDir = path19.join(directory, ".swarm");
|
|
18212
18212
|
if (!fs8.existsSync(swarmDir)) {
|
|
18213
18213
|
fs8.mkdirSync(swarmDir, { recursive: true });
|
|
18214
18214
|
}
|
|
18215
18215
|
const artifactFilename = "config-doctor.json";
|
|
18216
|
-
const artifactPath =
|
|
18216
|
+
const artifactPath = path19.join(swarmDir, artifactFilename);
|
|
18217
18217
|
const guiOutput = {
|
|
18218
18218
|
timestamp: result.timestamp,
|
|
18219
18219
|
summary: result.summary,
|
|
@@ -18575,12 +18575,12 @@ var init_evidence_summary_service = __esm(() => {
|
|
|
18575
18575
|
|
|
18576
18576
|
// src/cli/index.ts
|
|
18577
18577
|
import * as fs21 from "fs";
|
|
18578
|
-
import * as
|
|
18579
|
-
import * as
|
|
18578
|
+
import * as os7 from "os";
|
|
18579
|
+
import * as path33 from "path";
|
|
18580
18580
|
// package.json
|
|
18581
18581
|
var package_default = {
|
|
18582
18582
|
name: "opencode-swarm",
|
|
18583
|
-
version: "6.86.
|
|
18583
|
+
version: "6.86.9",
|
|
18584
18584
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
18585
18585
|
main: "dist/index.js",
|
|
18586
18586
|
types: "dist/index.d.ts",
|
|
@@ -18618,7 +18618,7 @@ var package_default = {
|
|
|
18618
18618
|
],
|
|
18619
18619
|
scripts: {
|
|
18620
18620
|
clean: `bun -e "require('fs').rmSync('dist',{recursive:true,force:true})"`,
|
|
18621
|
-
build: "bun run clean && bun run scripts/copy-grammars.ts && bun build src/index.ts --outdir dist --target
|
|
18621
|
+
build: "bun run clean && bun run scripts/copy-grammars.ts && bun build src/index.ts --outdir dist --target node --format esm && bun build src/cli/index.ts --outdir dist/cli --target bun --format esm && bun run scripts/copy-grammars.ts --to-dist && tsc --emitDeclarationOnly",
|
|
18622
18622
|
typecheck: "tsc --noEmit",
|
|
18623
18623
|
test: "bun test",
|
|
18624
18624
|
lint: "biome lint .",
|
|
@@ -19691,6 +19691,7 @@ var PluginConfigSchema = exports_external.object({
|
|
|
19691
19691
|
parallelization: ParallelizationConfigSchema.optional(),
|
|
19692
19692
|
turbo_mode: exports_external.boolean().default(false).optional(),
|
|
19693
19693
|
quiet: exports_external.boolean().default(false).optional(),
|
|
19694
|
+
version_check: exports_external.boolean().default(true).optional(),
|
|
19694
19695
|
full_auto: exports_external.object({
|
|
19695
19696
|
enabled: exports_external.boolean().default(false),
|
|
19696
19697
|
critic_model: exports_external.string().optional(),
|
|
@@ -19967,9 +19968,17 @@ init_plan_schema();
|
|
|
19967
19968
|
import { createHash as createHash3 } from "crypto";
|
|
19968
19969
|
|
|
19969
19970
|
// src/db/project-db.ts
|
|
19970
|
-
import { Database } from "bun:sqlite";
|
|
19971
19971
|
import { existsSync as existsSync5, mkdirSync as mkdirSync4 } from "fs";
|
|
19972
|
+
import { createRequire } from "module";
|
|
19972
19973
|
import { join as join7, resolve as resolve5 } from "path";
|
|
19974
|
+
var _DatabaseCtor = null;
|
|
19975
|
+
function loadDatabaseCtor() {
|
|
19976
|
+
if (_DatabaseCtor)
|
|
19977
|
+
return _DatabaseCtor;
|
|
19978
|
+
const req = createRequire(import.meta.url);
|
|
19979
|
+
_DatabaseCtor = req("bun:sqlite").Database;
|
|
19980
|
+
return _DatabaseCtor;
|
|
19981
|
+
}
|
|
19973
19982
|
var MIGRATIONS = [
|
|
19974
19983
|
{
|
|
19975
19984
|
version: 1,
|
|
@@ -20040,7 +20049,8 @@ function getProjectDb(directory) {
|
|
|
20040
20049
|
return existing;
|
|
20041
20050
|
const swarmDir = join7(key, ".swarm");
|
|
20042
20051
|
mkdirSync4(swarmDir, { recursive: true });
|
|
20043
|
-
const
|
|
20052
|
+
const Db = loadDatabaseCtor();
|
|
20053
|
+
const db = new Db(join7(swarmDir, "swarm.db"));
|
|
20044
20054
|
db.run("PRAGMA journal_mode = WAL;");
|
|
20045
20055
|
db.run("PRAGMA synchronous = NORMAL;");
|
|
20046
20056
|
db.run("PRAGMA busy_timeout = 5000;");
|
|
@@ -36258,12 +36268,83 @@ async function handleDarkMatterCommand(directory, args) {
|
|
|
36258
36268
|
|
|
36259
36269
|
// src/services/diagnose-service.ts
|
|
36260
36270
|
import * as child_process4 from "child_process";
|
|
36261
|
-
import { existsSync as
|
|
36262
|
-
import
|
|
36271
|
+
import { existsSync as existsSync9, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync5 } from "fs";
|
|
36272
|
+
import path18 from "path";
|
|
36263
36273
|
import { fileURLToPath } from "url";
|
|
36274
|
+
|
|
36275
|
+
// src/config/cache-paths.ts
|
|
36276
|
+
import * as os5 from "os";
|
|
36277
|
+
import * as path17 from "path";
|
|
36278
|
+
function getPluginConfigDir() {
|
|
36279
|
+
return path17.join(process.env.XDG_CONFIG_HOME || path17.join(os5.homedir(), ".config"), "opencode");
|
|
36280
|
+
}
|
|
36281
|
+
function getPluginCachePaths() {
|
|
36282
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path17.join(os5.homedir(), ".cache");
|
|
36283
|
+
const configDir = getPluginConfigDir();
|
|
36284
|
+
return [
|
|
36285
|
+
path17.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
|
|
36286
|
+
path17.join(configDir, "node_modules", "opencode-swarm"),
|
|
36287
|
+
path17.join(cacheBase, "opencode", "node_modules", "opencode-swarm")
|
|
36288
|
+
];
|
|
36289
|
+
}
|
|
36290
|
+
|
|
36291
|
+
// src/services/diagnose-service.ts
|
|
36264
36292
|
init_manager2();
|
|
36265
36293
|
init_utils2();
|
|
36266
36294
|
init_manager();
|
|
36295
|
+
|
|
36296
|
+
// src/services/version-check.ts
|
|
36297
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync8, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
36298
|
+
import { homedir as homedir5 } from "os";
|
|
36299
|
+
import { join as join15 } from "path";
|
|
36300
|
+
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
36301
|
+
function cacheDir() {
|
|
36302
|
+
const xdg = process.env.XDG_CACHE_HOME;
|
|
36303
|
+
const base = xdg && xdg.length > 0 ? xdg : join15(homedir5(), ".cache");
|
|
36304
|
+
return join15(base, "opencode-swarm");
|
|
36305
|
+
}
|
|
36306
|
+
function cacheFile() {
|
|
36307
|
+
return join15(cacheDir(), "version-check.json");
|
|
36308
|
+
}
|
|
36309
|
+
function readVersionCache() {
|
|
36310
|
+
try {
|
|
36311
|
+
const path18 = cacheFile();
|
|
36312
|
+
if (!existsSync8(path18))
|
|
36313
|
+
return null;
|
|
36314
|
+
const raw = readFileSync5(path18, "utf-8");
|
|
36315
|
+
const parsed = JSON.parse(raw);
|
|
36316
|
+
if (typeof parsed?.checkedAt !== "number")
|
|
36317
|
+
return null;
|
|
36318
|
+
const npmLatest = typeof parsed.npmLatest === "string" ? parsed.npmLatest : null;
|
|
36319
|
+
return { checkedAt: parsed.checkedAt, npmLatest };
|
|
36320
|
+
} catch {
|
|
36321
|
+
return null;
|
|
36322
|
+
}
|
|
36323
|
+
}
|
|
36324
|
+
function compareVersions(a, b) {
|
|
36325
|
+
const [aBase, aPre] = a.split("-", 2);
|
|
36326
|
+
const [bBase, bPre] = b.split("-", 2);
|
|
36327
|
+
const aParts = aBase.split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
36328
|
+
const bParts = bBase.split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
36329
|
+
const len = Math.max(aParts.length, bParts.length);
|
|
36330
|
+
for (let i = 0;i < len; i++) {
|
|
36331
|
+
const av = aParts[i] ?? 0;
|
|
36332
|
+
const bv = bParts[i] ?? 0;
|
|
36333
|
+
if (av > bv)
|
|
36334
|
+
return 1;
|
|
36335
|
+
if (av < bv)
|
|
36336
|
+
return -1;
|
|
36337
|
+
}
|
|
36338
|
+
if (aPre && !bPre)
|
|
36339
|
+
return -1;
|
|
36340
|
+
if (!aPre && bPre)
|
|
36341
|
+
return 1;
|
|
36342
|
+
if (aPre && bPre)
|
|
36343
|
+
return aPre < bPre ? -1 : aPre > bPre ? 1 : 0;
|
|
36344
|
+
return 0;
|
|
36345
|
+
}
|
|
36346
|
+
|
|
36347
|
+
// src/services/diagnose-service.ts
|
|
36267
36348
|
var { version: version3 } = package_default;
|
|
36268
36349
|
function validateTaskDag(plan) {
|
|
36269
36350
|
const allTaskIds = new Set;
|
|
@@ -36496,7 +36577,7 @@ async function checkConfigBackups(directory) {
|
|
|
36496
36577
|
}
|
|
36497
36578
|
async function checkGitRepository(directory) {
|
|
36498
36579
|
try {
|
|
36499
|
-
if (!
|
|
36580
|
+
if (!existsSync9(directory) || !statSync5(directory).isDirectory()) {
|
|
36500
36581
|
return {
|
|
36501
36582
|
name: "Git Repository",
|
|
36502
36583
|
status: "\u274C",
|
|
@@ -36560,8 +36641,8 @@ async function checkSpecStaleness(directory, plan) {
|
|
|
36560
36641
|
};
|
|
36561
36642
|
}
|
|
36562
36643
|
async function checkConfigParseability(directory) {
|
|
36563
|
-
const configPath =
|
|
36564
|
-
if (!
|
|
36644
|
+
const configPath = path18.join(directory, ".opencode/opencode-swarm.json");
|
|
36645
|
+
if (!existsSync9(configPath)) {
|
|
36565
36646
|
return {
|
|
36566
36647
|
name: "Config Parseability",
|
|
36567
36648
|
status: "\u2705",
|
|
@@ -36569,7 +36650,7 @@ async function checkConfigParseability(directory) {
|
|
|
36569
36650
|
};
|
|
36570
36651
|
}
|
|
36571
36652
|
try {
|
|
36572
|
-
const content =
|
|
36653
|
+
const content = readFileSync6(configPath, "utf-8");
|
|
36573
36654
|
JSON.parse(content);
|
|
36574
36655
|
return {
|
|
36575
36656
|
name: "Config Parseability",
|
|
@@ -36589,7 +36670,7 @@ function resolveGrammarDir(thisDir) {
|
|
|
36589
36670
|
const normalized = thisDir.replace(/\\/g, "/");
|
|
36590
36671
|
const isSource = normalized.endsWith("/src/services");
|
|
36591
36672
|
const isCliBundle = normalized.endsWith("/cli");
|
|
36592
|
-
return isSource || isCliBundle ?
|
|
36673
|
+
return isSource || isCliBundle ? path18.join(thisDir, "..", "lang", "grammars") : path18.join(thisDir, "lang", "grammars");
|
|
36593
36674
|
}
|
|
36594
36675
|
async function checkGrammarWasmFiles() {
|
|
36595
36676
|
const grammarFiles = [
|
|
@@ -36613,14 +36694,14 @@ async function checkGrammarWasmFiles() {
|
|
|
36613
36694
|
"tree-sitter-ini.wasm",
|
|
36614
36695
|
"tree-sitter-regex.wasm"
|
|
36615
36696
|
];
|
|
36616
|
-
const thisDir =
|
|
36697
|
+
const thisDir = path18.dirname(fileURLToPath(import.meta.url));
|
|
36617
36698
|
const grammarDir = resolveGrammarDir(thisDir);
|
|
36618
36699
|
const missing = [];
|
|
36619
|
-
if (!
|
|
36700
|
+
if (!existsSync9(path18.join(grammarDir, "tree-sitter.wasm"))) {
|
|
36620
36701
|
missing.push("tree-sitter.wasm (core runtime)");
|
|
36621
36702
|
}
|
|
36622
36703
|
for (const file3 of grammarFiles) {
|
|
36623
|
-
if (!
|
|
36704
|
+
if (!existsSync9(path18.join(grammarDir, file3))) {
|
|
36624
36705
|
missing.push(file3);
|
|
36625
36706
|
}
|
|
36626
36707
|
}
|
|
@@ -36638,8 +36719,8 @@ async function checkGrammarWasmFiles() {
|
|
|
36638
36719
|
};
|
|
36639
36720
|
}
|
|
36640
36721
|
async function checkCheckpointManifest(directory) {
|
|
36641
|
-
const manifestPath =
|
|
36642
|
-
if (!
|
|
36722
|
+
const manifestPath = path18.join(directory, ".swarm/checkpoints.json");
|
|
36723
|
+
if (!existsSync9(manifestPath)) {
|
|
36643
36724
|
return {
|
|
36644
36725
|
name: "Checkpoint Manifest",
|
|
36645
36726
|
status: "\u2705",
|
|
@@ -36647,7 +36728,7 @@ async function checkCheckpointManifest(directory) {
|
|
|
36647
36728
|
};
|
|
36648
36729
|
}
|
|
36649
36730
|
try {
|
|
36650
|
-
const content =
|
|
36731
|
+
const content = readFileSync6(manifestPath, "utf-8");
|
|
36651
36732
|
const parsed = JSON.parse(content);
|
|
36652
36733
|
if (!parsed.checkpoints || !Array.isArray(parsed.checkpoints)) {
|
|
36653
36734
|
return {
|
|
@@ -36690,8 +36771,8 @@ async function checkCheckpointManifest(directory) {
|
|
|
36690
36771
|
}
|
|
36691
36772
|
}
|
|
36692
36773
|
async function checkEventStreamIntegrity(directory) {
|
|
36693
|
-
const eventsPath =
|
|
36694
|
-
if (!
|
|
36774
|
+
const eventsPath = path18.join(directory, ".swarm/events.jsonl");
|
|
36775
|
+
if (!existsSync9(eventsPath)) {
|
|
36695
36776
|
return {
|
|
36696
36777
|
name: "Event Stream",
|
|
36697
36778
|
status: "\u2705",
|
|
@@ -36699,7 +36780,7 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
36699
36780
|
};
|
|
36700
36781
|
}
|
|
36701
36782
|
try {
|
|
36702
|
-
const content =
|
|
36783
|
+
const content = readFileSync6(eventsPath, "utf-8");
|
|
36703
36784
|
const lines = content.split(`
|
|
36704
36785
|
`).filter((line) => line.trim() !== "");
|
|
36705
36786
|
let malformedCount = 0;
|
|
@@ -36731,8 +36812,8 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
36731
36812
|
}
|
|
36732
36813
|
}
|
|
36733
36814
|
async function checkSteeringDirectives(directory) {
|
|
36734
|
-
const eventsPath =
|
|
36735
|
-
if (!
|
|
36815
|
+
const eventsPath = path18.join(directory, ".swarm/events.jsonl");
|
|
36816
|
+
if (!existsSync9(eventsPath)) {
|
|
36736
36817
|
return {
|
|
36737
36818
|
name: "Steering Directives",
|
|
36738
36819
|
status: "\u2705",
|
|
@@ -36740,7 +36821,7 @@ async function checkSteeringDirectives(directory) {
|
|
|
36740
36821
|
};
|
|
36741
36822
|
}
|
|
36742
36823
|
try {
|
|
36743
|
-
const content =
|
|
36824
|
+
const content = readFileSync6(eventsPath, "utf-8");
|
|
36744
36825
|
const lines = content.split(`
|
|
36745
36826
|
`).filter((line) => line.trim() !== "");
|
|
36746
36827
|
const directivesIssued = [];
|
|
@@ -36787,8 +36868,8 @@ async function checkCurator(directory) {
|
|
|
36787
36868
|
detail: "Disabled (enable via curator.enabled)"
|
|
36788
36869
|
};
|
|
36789
36870
|
}
|
|
36790
|
-
const summaryPath =
|
|
36791
|
-
if (!
|
|
36871
|
+
const summaryPath = path18.join(directory, ".swarm/curator-summary.json");
|
|
36872
|
+
if (!existsSync9(summaryPath)) {
|
|
36792
36873
|
return {
|
|
36793
36874
|
name: "Curator",
|
|
36794
36875
|
status: "\u2705",
|
|
@@ -36796,7 +36877,7 @@ async function checkCurator(directory) {
|
|
|
36796
36877
|
};
|
|
36797
36878
|
}
|
|
36798
36879
|
try {
|
|
36799
|
-
const content =
|
|
36880
|
+
const content = readFileSync6(summaryPath, "utf-8");
|
|
36800
36881
|
const parsed = JSON.parse(content);
|
|
36801
36882
|
if (typeof parsed.schema_version !== "number" || parsed.schema_version !== 1) {
|
|
36802
36883
|
return {
|
|
@@ -36831,10 +36912,23 @@ async function checkCurator(directory) {
|
|
|
36831
36912
|
}
|
|
36832
36913
|
async function getDiagnoseData(directory) {
|
|
36833
36914
|
const checks5 = [];
|
|
36915
|
+
const versionCache = readVersionCache();
|
|
36916
|
+
let versionDetail = version3;
|
|
36917
|
+
let versionStatus = "\u2705";
|
|
36918
|
+
if (versionCache?.npmLatest) {
|
|
36919
|
+
const ageMs = Date.now() - versionCache.checkedAt;
|
|
36920
|
+
const ageMin = Math.max(0, Math.round(ageMs / 60000));
|
|
36921
|
+
if (compareVersions(versionCache.npmLatest, version3) > 0) {
|
|
36922
|
+
versionStatus = "\u26A0\uFE0F";
|
|
36923
|
+
versionDetail = `${version3} (npm latest: ${versionCache.npmLatest}, checked ${ageMin}m ago) ` + "\u2014 run `bunx opencode-swarm update` to refresh";
|
|
36924
|
+
} else {
|
|
36925
|
+
versionDetail = `${version3} (npm latest: ${versionCache.npmLatest}, checked ${ageMin}m ago)`;
|
|
36926
|
+
}
|
|
36927
|
+
}
|
|
36834
36928
|
checks5.push({
|
|
36835
36929
|
name: "Version",
|
|
36836
|
-
status:
|
|
36837
|
-
detail:
|
|
36930
|
+
status: versionStatus,
|
|
36931
|
+
detail: versionDetail
|
|
36838
36932
|
});
|
|
36839
36933
|
const plan = await loadPlanJsonOnly(directory);
|
|
36840
36934
|
if (plan) {
|
|
@@ -36940,8 +37034,8 @@ async function getDiagnoseData(directory) {
|
|
|
36940
37034
|
checks5.push(await checkSteeringDirectives(directory));
|
|
36941
37035
|
checks5.push(await checkCurator(directory));
|
|
36942
37036
|
try {
|
|
36943
|
-
const evidenceDir =
|
|
36944
|
-
const snapshotFiles =
|
|
37037
|
+
const evidenceDir = path18.join(directory, ".swarm", "evidence");
|
|
37038
|
+
const snapshotFiles = existsSync9(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
|
|
36945
37039
|
if (snapshotFiles.length > 0) {
|
|
36946
37040
|
const latest = snapshotFiles.sort().pop();
|
|
36947
37041
|
checks5.push({
|
|
@@ -36970,7 +37064,36 @@ async function getDiagnoseData(directory) {
|
|
|
36970
37064
|
detail: `${deferredWarnings.length} warning(s) deferred from init (run with verbose logs for details)`
|
|
36971
37065
|
});
|
|
36972
37066
|
}
|
|
36973
|
-
const
|
|
37067
|
+
const cachePaths = getPluginCachePaths();
|
|
37068
|
+
const cacheRows = [];
|
|
37069
|
+
for (const cachePath of cachePaths) {
|
|
37070
|
+
try {
|
|
37071
|
+
if (!existsSync9(cachePath)) {
|
|
37072
|
+
cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
|
|
37073
|
+
continue;
|
|
37074
|
+
}
|
|
37075
|
+
const pkgJsonPath = path18.join(cachePath, "package.json");
|
|
37076
|
+
try {
|
|
37077
|
+
const raw = readFileSync6(pkgJsonPath, "utf-8");
|
|
37078
|
+
const parsed = JSON.parse(raw);
|
|
37079
|
+
const installedVersion = typeof parsed.version === "string" ? parsed.version : "?";
|
|
37080
|
+
cacheRows.push(`\u2705 ${cachePath} \u2014 v${installedVersion}`);
|
|
37081
|
+
} catch {
|
|
37082
|
+
cacheRows.push(`\u26A0\uFE0F ${cachePath} \u2014 present (package.json unreadable)`);
|
|
37083
|
+
}
|
|
37084
|
+
} catch {
|
|
37085
|
+
cacheRows.push(`\u26A0\uFE0F ${cachePath} \u2014 status unknown (read error)`);
|
|
37086
|
+
}
|
|
37087
|
+
}
|
|
37088
|
+
const hasCacheEntry = cacheRows.some((r) => r.startsWith("\u2705"));
|
|
37089
|
+
const hasCacheWarning = cacheRows.some((r) => r.startsWith("\u26A0\uFE0F"));
|
|
37090
|
+
const cacheStatus = hasCacheWarning ? "\u26A0\uFE0F" : hasCacheEntry ? "\u2705" : "\u2B1C";
|
|
37091
|
+
checks5.push({
|
|
37092
|
+
name: "Plugin Caches",
|
|
37093
|
+
status: cacheStatus,
|
|
37094
|
+
detail: cacheRows.join(" | ")
|
|
37095
|
+
});
|
|
37096
|
+
const passCount = checks5.filter((c) => c.status === "\u2705" || c.status === "\u2B1C").length;
|
|
36974
37097
|
const totalCount = checks5.length;
|
|
36975
37098
|
const allPassed = passCount === totalCount;
|
|
36976
37099
|
return {
|
|
@@ -37008,15 +37131,15 @@ init_config_doctor();
|
|
|
37008
37131
|
|
|
37009
37132
|
// src/services/tool-doctor.ts
|
|
37010
37133
|
import * as fs10 from "fs";
|
|
37011
|
-
import * as
|
|
37134
|
+
import * as path21 from "path";
|
|
37012
37135
|
|
|
37013
37136
|
// src/build/discovery.ts
|
|
37014
37137
|
import * as fs9 from "fs";
|
|
37015
|
-
import * as
|
|
37138
|
+
import * as path20 from "path";
|
|
37016
37139
|
|
|
37017
37140
|
// src/lang/detector.ts
|
|
37018
37141
|
import { access as access2, readdir as readdir2 } from "fs/promises";
|
|
37019
|
-
import { extname as extname2, join as
|
|
37142
|
+
import { extname as extname2, join as join17 } from "path";
|
|
37020
37143
|
|
|
37021
37144
|
// src/lang/profiles.ts
|
|
37022
37145
|
class LanguageRegistry {
|
|
@@ -37996,7 +38119,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
37996
38119
|
if (detectFile.includes("*") || detectFile.includes("?"))
|
|
37997
38120
|
continue;
|
|
37998
38121
|
try {
|
|
37999
|
-
await access2(
|
|
38122
|
+
await access2(join17(dir, detectFile));
|
|
38000
38123
|
detected.add(profile.id);
|
|
38001
38124
|
break;
|
|
38002
38125
|
} catch {}
|
|
@@ -38017,7 +38140,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
38017
38140
|
const topEntries = await readdir2(projectDir, { withFileTypes: true });
|
|
38018
38141
|
for (const entry of topEntries) {
|
|
38019
38142
|
if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
|
|
38020
|
-
await scanDir(
|
|
38143
|
+
await scanDir(join17(projectDir, entry.name));
|
|
38021
38144
|
}
|
|
38022
38145
|
}
|
|
38023
38146
|
} catch {}
|
|
@@ -38176,11 +38299,11 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
38176
38299
|
const regex = simpleGlobToRegex(pattern);
|
|
38177
38300
|
const matches = files.filter((f) => regex.test(f));
|
|
38178
38301
|
if (matches.length > 0) {
|
|
38179
|
-
return
|
|
38302
|
+
return path20.join(dir, matches[0]);
|
|
38180
38303
|
}
|
|
38181
38304
|
} catch {}
|
|
38182
38305
|
} else {
|
|
38183
|
-
const filePath =
|
|
38306
|
+
const filePath = path20.join(workingDir, pattern);
|
|
38184
38307
|
if (fs9.existsSync(filePath)) {
|
|
38185
38308
|
return filePath;
|
|
38186
38309
|
}
|
|
@@ -38189,7 +38312,7 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
38189
38312
|
return null;
|
|
38190
38313
|
}
|
|
38191
38314
|
function getRepoDefinedScripts(workingDir, scripts) {
|
|
38192
|
-
const packageJsonPath =
|
|
38315
|
+
const packageJsonPath = path20.join(workingDir, "package.json");
|
|
38193
38316
|
if (!fs9.existsSync(packageJsonPath)) {
|
|
38194
38317
|
return [];
|
|
38195
38318
|
}
|
|
@@ -38230,7 +38353,7 @@ function findAllBuildFiles(workingDir) {
|
|
|
38230
38353
|
const regex = simpleGlobToRegex(pattern);
|
|
38231
38354
|
findFilesRecursive(workingDir, regex, allBuildFiles);
|
|
38232
38355
|
} else {
|
|
38233
|
-
const filePath =
|
|
38356
|
+
const filePath = path20.join(workingDir, pattern);
|
|
38234
38357
|
if (fs9.existsSync(filePath)) {
|
|
38235
38358
|
allBuildFiles.add(filePath);
|
|
38236
38359
|
}
|
|
@@ -38243,7 +38366,7 @@ function findFilesRecursive(dir, regex, results) {
|
|
|
38243
38366
|
try {
|
|
38244
38367
|
const entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
38245
38368
|
for (const entry of entries) {
|
|
38246
|
-
const fullPath =
|
|
38369
|
+
const fullPath = path20.join(dir, entry.name);
|
|
38247
38370
|
if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
|
|
38248
38371
|
findFilesRecursive(fullPath, regex, results);
|
|
38249
38372
|
} else if (entry.isFile() && regex.test(entry.name)) {
|
|
@@ -38266,7 +38389,7 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
|
|
|
38266
38389
|
let foundCommand = false;
|
|
38267
38390
|
for (const cmd of sortedCommands) {
|
|
38268
38391
|
if (cmd.detectFile) {
|
|
38269
|
-
const detectFilePath =
|
|
38392
|
+
const detectFilePath = path20.join(workingDir, cmd.detectFile);
|
|
38270
38393
|
if (!fs9.existsSync(detectFilePath)) {
|
|
38271
38394
|
continue;
|
|
38272
38395
|
}
|
|
@@ -38441,8 +38564,8 @@ function checkBinaryReadiness() {
|
|
|
38441
38564
|
}
|
|
38442
38565
|
function runToolDoctor(_directory, pluginRoot) {
|
|
38443
38566
|
const findings = [];
|
|
38444
|
-
const resolvedPluginRoot = pluginRoot ??
|
|
38445
|
-
const indexPath =
|
|
38567
|
+
const resolvedPluginRoot = pluginRoot ?? path21.resolve(import.meta.dir, "..", "..");
|
|
38568
|
+
const indexPath = path21.join(resolvedPluginRoot, "src", "index.ts");
|
|
38446
38569
|
if (!fs10.existsSync(indexPath)) {
|
|
38447
38570
|
return {
|
|
38448
38571
|
findings: [
|
|
@@ -39363,14 +39486,14 @@ async function handleHistoryCommand(directory, _args) {
|
|
|
39363
39486
|
}
|
|
39364
39487
|
// src/hooks/knowledge-migrator.ts
|
|
39365
39488
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
39366
|
-
import { existsSync as
|
|
39489
|
+
import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
|
|
39367
39490
|
import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
39368
|
-
import * as
|
|
39491
|
+
import * as path22 from "path";
|
|
39369
39492
|
async function migrateContextToKnowledge(directory, config3) {
|
|
39370
|
-
const sentinelPath =
|
|
39371
|
-
const contextPath =
|
|
39493
|
+
const sentinelPath = path22.join(directory, ".swarm", ".knowledge-migrated");
|
|
39494
|
+
const contextPath = path22.join(directory, ".swarm", "context.md");
|
|
39372
39495
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
39373
|
-
if (
|
|
39496
|
+
if (existsSync13(sentinelPath)) {
|
|
39374
39497
|
return {
|
|
39375
39498
|
migrated: false,
|
|
39376
39499
|
entriesMigrated: 0,
|
|
@@ -39379,7 +39502,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
39379
39502
|
skippedReason: "sentinel-exists"
|
|
39380
39503
|
};
|
|
39381
39504
|
}
|
|
39382
|
-
if (!
|
|
39505
|
+
if (!existsSync13(contextPath)) {
|
|
39383
39506
|
return {
|
|
39384
39507
|
migrated: false,
|
|
39385
39508
|
entriesMigrated: 0,
|
|
@@ -39564,16 +39687,16 @@ function truncateLesson(text) {
|
|
|
39564
39687
|
return `${text.slice(0, 277)}...`;
|
|
39565
39688
|
}
|
|
39566
39689
|
function inferProjectName(directory) {
|
|
39567
|
-
const packageJsonPath =
|
|
39568
|
-
if (
|
|
39690
|
+
const packageJsonPath = path22.join(directory, "package.json");
|
|
39691
|
+
if (existsSync13(packageJsonPath)) {
|
|
39569
39692
|
try {
|
|
39570
|
-
const pkg = JSON.parse(
|
|
39693
|
+
const pkg = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
|
|
39571
39694
|
if (pkg.name && typeof pkg.name === "string") {
|
|
39572
39695
|
return pkg.name;
|
|
39573
39696
|
}
|
|
39574
39697
|
} catch {}
|
|
39575
39698
|
}
|
|
39576
|
-
return
|
|
39699
|
+
return path22.basename(directory);
|
|
39577
39700
|
}
|
|
39578
39701
|
async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
39579
39702
|
const sentinel = {
|
|
@@ -39585,7 +39708,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
39585
39708
|
schema_version: 1,
|
|
39586
39709
|
migration_tool: "knowledge-migrator.ts"
|
|
39587
39710
|
};
|
|
39588
|
-
await mkdir3(
|
|
39711
|
+
await mkdir3(path22.dirname(sentinelPath), { recursive: true });
|
|
39589
39712
|
await writeFile4(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
39590
39713
|
}
|
|
39591
39714
|
|
|
@@ -39822,12 +39945,12 @@ async function handlePlanCommand(directory, args) {
|
|
|
39822
39945
|
init_manager2();
|
|
39823
39946
|
init_manager();
|
|
39824
39947
|
import * as fs17 from "fs";
|
|
39825
|
-
import * as
|
|
39948
|
+
import * as path29 from "path";
|
|
39826
39949
|
|
|
39827
39950
|
// src/tools/lint.ts
|
|
39828
39951
|
init_zod();
|
|
39829
39952
|
import * as fs11 from "fs";
|
|
39830
|
-
import * as
|
|
39953
|
+
import * as path23 from "path";
|
|
39831
39954
|
init_utils();
|
|
39832
39955
|
|
|
39833
39956
|
// src/utils/path-security.ts
|
|
@@ -39873,9 +39996,9 @@ function validateArgs(args) {
|
|
|
39873
39996
|
}
|
|
39874
39997
|
function getLinterCommand(linter, mode, projectDir) {
|
|
39875
39998
|
const isWindows = process.platform === "win32";
|
|
39876
|
-
const binDir =
|
|
39877
|
-
const biomeBin = isWindows ?
|
|
39878
|
-
const eslintBin = isWindows ?
|
|
39999
|
+
const binDir = path23.join(projectDir, "node_modules", ".bin");
|
|
40000
|
+
const biomeBin = isWindows ? path23.join(binDir, "biome.EXE") : path23.join(binDir, "biome");
|
|
40001
|
+
const eslintBin = isWindows ? path23.join(binDir, "eslint.cmd") : path23.join(binDir, "eslint");
|
|
39879
40002
|
switch (linter) {
|
|
39880
40003
|
case "biome":
|
|
39881
40004
|
if (mode === "fix") {
|
|
@@ -39891,7 +40014,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
39891
40014
|
}
|
|
39892
40015
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
39893
40016
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
39894
|
-
const gradlew = fs11.existsSync(
|
|
40017
|
+
const gradlew = fs11.existsSync(path23.join(cwd, gradlewName)) ? path23.join(cwd, gradlewName) : null;
|
|
39895
40018
|
switch (linter) {
|
|
39896
40019
|
case "ruff":
|
|
39897
40020
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -39925,10 +40048,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
39925
40048
|
}
|
|
39926
40049
|
}
|
|
39927
40050
|
function detectRuff(cwd) {
|
|
39928
|
-
if (fs11.existsSync(
|
|
40051
|
+
if (fs11.existsSync(path23.join(cwd, "ruff.toml")))
|
|
39929
40052
|
return isCommandAvailable("ruff");
|
|
39930
40053
|
try {
|
|
39931
|
-
const pyproject =
|
|
40054
|
+
const pyproject = path23.join(cwd, "pyproject.toml");
|
|
39932
40055
|
if (fs11.existsSync(pyproject)) {
|
|
39933
40056
|
const content = fs11.readFileSync(pyproject, "utf-8");
|
|
39934
40057
|
if (content.includes("[tool.ruff]"))
|
|
@@ -39938,19 +40061,19 @@ function detectRuff(cwd) {
|
|
|
39938
40061
|
return false;
|
|
39939
40062
|
}
|
|
39940
40063
|
function detectClippy(cwd) {
|
|
39941
|
-
return fs11.existsSync(
|
|
40064
|
+
return fs11.existsSync(path23.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
39942
40065
|
}
|
|
39943
40066
|
function detectGolangciLint(cwd) {
|
|
39944
|
-
return fs11.existsSync(
|
|
40067
|
+
return fs11.existsSync(path23.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
39945
40068
|
}
|
|
39946
40069
|
function detectCheckstyle(cwd) {
|
|
39947
|
-
const hasMaven = fs11.existsSync(
|
|
39948
|
-
const hasGradle = fs11.existsSync(
|
|
39949
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs11.existsSync(
|
|
40070
|
+
const hasMaven = fs11.existsSync(path23.join(cwd, "pom.xml"));
|
|
40071
|
+
const hasGradle = fs11.existsSync(path23.join(cwd, "build.gradle")) || fs11.existsSync(path23.join(cwd, "build.gradle.kts"));
|
|
40072
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs11.existsSync(path23.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
39950
40073
|
return (hasMaven || hasGradle) && hasBinary;
|
|
39951
40074
|
}
|
|
39952
40075
|
function detectKtlint(cwd) {
|
|
39953
|
-
const hasKotlin = fs11.existsSync(
|
|
40076
|
+
const hasKotlin = fs11.existsSync(path23.join(cwd, "build.gradle.kts")) || fs11.existsSync(path23.join(cwd, "build.gradle")) || (() => {
|
|
39954
40077
|
try {
|
|
39955
40078
|
return fs11.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
39956
40079
|
} catch {
|
|
@@ -39969,11 +40092,11 @@ function detectDotnetFormat(cwd) {
|
|
|
39969
40092
|
}
|
|
39970
40093
|
}
|
|
39971
40094
|
function detectCppcheck(cwd) {
|
|
39972
|
-
if (fs11.existsSync(
|
|
40095
|
+
if (fs11.existsSync(path23.join(cwd, "CMakeLists.txt"))) {
|
|
39973
40096
|
return isCommandAvailable("cppcheck");
|
|
39974
40097
|
}
|
|
39975
40098
|
try {
|
|
39976
|
-
const dirsToCheck = [cwd,
|
|
40099
|
+
const dirsToCheck = [cwd, path23.join(cwd, "src")];
|
|
39977
40100
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
39978
40101
|
try {
|
|
39979
40102
|
return fs11.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
@@ -39987,13 +40110,13 @@ function detectCppcheck(cwd) {
|
|
|
39987
40110
|
}
|
|
39988
40111
|
}
|
|
39989
40112
|
function detectSwiftlint(cwd) {
|
|
39990
|
-
return fs11.existsSync(
|
|
40113
|
+
return fs11.existsSync(path23.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
39991
40114
|
}
|
|
39992
40115
|
function detectDartAnalyze(cwd) {
|
|
39993
|
-
return fs11.existsSync(
|
|
40116
|
+
return fs11.existsSync(path23.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
39994
40117
|
}
|
|
39995
40118
|
function detectRubocop(cwd) {
|
|
39996
|
-
return (fs11.existsSync(
|
|
40119
|
+
return (fs11.existsSync(path23.join(cwd, "Gemfile")) || fs11.existsSync(path23.join(cwd, "gems.rb")) || fs11.existsSync(path23.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
|
|
39997
40120
|
}
|
|
39998
40121
|
function detectAdditionalLinter(cwd) {
|
|
39999
40122
|
if (detectRuff(cwd))
|
|
@@ -40021,10 +40144,10 @@ function detectAdditionalLinter(cwd) {
|
|
|
40021
40144
|
function findBinInAncestors(startDir, binName) {
|
|
40022
40145
|
let dir = startDir;
|
|
40023
40146
|
while (true) {
|
|
40024
|
-
const candidate =
|
|
40147
|
+
const candidate = path23.join(dir, "node_modules", ".bin", binName);
|
|
40025
40148
|
if (fs11.existsSync(candidate))
|
|
40026
40149
|
return candidate;
|
|
40027
|
-
const parent =
|
|
40150
|
+
const parent = path23.dirname(dir);
|
|
40028
40151
|
if (parent === dir)
|
|
40029
40152
|
break;
|
|
40030
40153
|
dir = parent;
|
|
@@ -40033,10 +40156,10 @@ function findBinInAncestors(startDir, binName) {
|
|
|
40033
40156
|
}
|
|
40034
40157
|
function findBinInEnvPath(binName) {
|
|
40035
40158
|
const searchPath = process.env.PATH ?? "";
|
|
40036
|
-
for (const dir of searchPath.split(
|
|
40159
|
+
for (const dir of searchPath.split(path23.delimiter)) {
|
|
40037
40160
|
if (!dir)
|
|
40038
40161
|
continue;
|
|
40039
|
-
const candidate =
|
|
40162
|
+
const candidate = path23.join(dir, binName);
|
|
40040
40163
|
if (fs11.existsSync(candidate))
|
|
40041
40164
|
return candidate;
|
|
40042
40165
|
}
|
|
@@ -40049,13 +40172,13 @@ async function detectAvailableLinter(directory) {
|
|
|
40049
40172
|
return null;
|
|
40050
40173
|
const projectDir = directory;
|
|
40051
40174
|
const isWindows = process.platform === "win32";
|
|
40052
|
-
const biomeBin = isWindows ?
|
|
40053
|
-
const eslintBin = isWindows ?
|
|
40175
|
+
const biomeBin = isWindows ? path23.join(projectDir, "node_modules", ".bin", "biome.EXE") : path23.join(projectDir, "node_modules", ".bin", "biome");
|
|
40176
|
+
const eslintBin = isWindows ? path23.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path23.join(projectDir, "node_modules", ".bin", "eslint");
|
|
40054
40177
|
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
40055
40178
|
if (localResult)
|
|
40056
40179
|
return localResult;
|
|
40057
|
-
const biomeAncestor = findBinInAncestors(
|
|
40058
|
-
const eslintAncestor = findBinInAncestors(
|
|
40180
|
+
const biomeAncestor = findBinInAncestors(path23.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
40181
|
+
const eslintAncestor = findBinInAncestors(path23.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
40059
40182
|
if (biomeAncestor || eslintAncestor) {
|
|
40060
40183
|
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
40061
40184
|
}
|
|
@@ -40264,7 +40387,7 @@ For Rust: rustup component add clippy`
|
|
|
40264
40387
|
// src/tools/secretscan.ts
|
|
40265
40388
|
init_zod();
|
|
40266
40389
|
import * as fs12 from "fs";
|
|
40267
|
-
import * as
|
|
40390
|
+
import * as path24 from "path";
|
|
40268
40391
|
var MAX_FILE_PATH_LENGTH = 500;
|
|
40269
40392
|
var MAX_FILE_SIZE_BYTES = 512 * 1024;
|
|
40270
40393
|
var MAX_FILES_SCANNED = 1000;
|
|
@@ -40491,7 +40614,7 @@ function isGlobOrPathPattern(pattern) {
|
|
|
40491
40614
|
return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
|
|
40492
40615
|
}
|
|
40493
40616
|
function loadSecretScanIgnore(scanDir) {
|
|
40494
|
-
const ignorePath =
|
|
40617
|
+
const ignorePath = path24.join(scanDir, ".secretscanignore");
|
|
40495
40618
|
try {
|
|
40496
40619
|
if (!fs12.existsSync(ignorePath))
|
|
40497
40620
|
return [];
|
|
@@ -40514,7 +40637,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
40514
40637
|
if (exactNames.has(entry))
|
|
40515
40638
|
return true;
|
|
40516
40639
|
for (const pattern of globPatterns) {
|
|
40517
|
-
if (
|
|
40640
|
+
if (path24.matchesGlob(relPath, pattern))
|
|
40518
40641
|
return true;
|
|
40519
40642
|
}
|
|
40520
40643
|
return false;
|
|
@@ -40535,7 +40658,7 @@ function validateDirectoryInput(dir) {
|
|
|
40535
40658
|
return null;
|
|
40536
40659
|
}
|
|
40537
40660
|
function isBinaryFile(filePath, buffer) {
|
|
40538
|
-
const ext =
|
|
40661
|
+
const ext = path24.extname(filePath).toLowerCase();
|
|
40539
40662
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
40540
40663
|
return true;
|
|
40541
40664
|
}
|
|
@@ -40672,9 +40795,9 @@ function isSymlinkLoop(realPath, visited) {
|
|
|
40672
40795
|
return false;
|
|
40673
40796
|
}
|
|
40674
40797
|
function isPathWithinScope(realPath, scanDir) {
|
|
40675
|
-
const resolvedScanDir =
|
|
40676
|
-
const resolvedRealPath =
|
|
40677
|
-
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir +
|
|
40798
|
+
const resolvedScanDir = path24.resolve(scanDir);
|
|
40799
|
+
const resolvedRealPath = path24.resolve(realPath);
|
|
40800
|
+
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path24.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
|
|
40678
40801
|
}
|
|
40679
40802
|
function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
|
|
40680
40803
|
skippedDirs: 0,
|
|
@@ -40700,8 +40823,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
40700
40823
|
return a.localeCompare(b);
|
|
40701
40824
|
});
|
|
40702
40825
|
for (const entry of entries) {
|
|
40703
|
-
const fullPath =
|
|
40704
|
-
const relPath =
|
|
40826
|
+
const fullPath = path24.join(dir, entry);
|
|
40827
|
+
const relPath = path24.relative(scanDir, fullPath).replace(/\\/g, "/");
|
|
40705
40828
|
if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
|
|
40706
40829
|
stats.skippedDirs++;
|
|
40707
40830
|
continue;
|
|
@@ -40736,7 +40859,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
40736
40859
|
const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
|
|
40737
40860
|
files.push(...subFiles);
|
|
40738
40861
|
} else if (lstat.isFile()) {
|
|
40739
|
-
const ext =
|
|
40862
|
+
const ext = path24.extname(fullPath).toLowerCase();
|
|
40740
40863
|
if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
40741
40864
|
files.push(fullPath);
|
|
40742
40865
|
} else {
|
|
@@ -40802,7 +40925,7 @@ var secretscan = createSwarmTool({
|
|
|
40802
40925
|
}
|
|
40803
40926
|
}
|
|
40804
40927
|
try {
|
|
40805
|
-
const _scanDirRaw =
|
|
40928
|
+
const _scanDirRaw = path24.resolve(directory);
|
|
40806
40929
|
const scanDir = (() => {
|
|
40807
40930
|
try {
|
|
40808
40931
|
return fs12.realpathSync(_scanDirRaw);
|
|
@@ -40962,11 +41085,11 @@ async function runSecretscan(directory) {
|
|
|
40962
41085
|
// src/tools/test-runner.ts
|
|
40963
41086
|
init_zod();
|
|
40964
41087
|
import * as fs16 from "fs";
|
|
40965
|
-
import * as
|
|
41088
|
+
import * as path28 from "path";
|
|
40966
41089
|
|
|
40967
41090
|
// src/test-impact/analyzer.ts
|
|
40968
41091
|
import fs13 from "fs";
|
|
40969
|
-
import
|
|
41092
|
+
import path25 from "path";
|
|
40970
41093
|
var IMPORT_REGEX_ES = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
40971
41094
|
var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
40972
41095
|
var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
|
|
@@ -40991,8 +41114,8 @@ function resolveRelativeImport(fromDir, importPath) {
|
|
|
40991
41114
|
if (!importPath.startsWith(".")) {
|
|
40992
41115
|
return null;
|
|
40993
41116
|
}
|
|
40994
|
-
const resolved =
|
|
40995
|
-
if (
|
|
41117
|
+
const resolved = path25.resolve(fromDir, importPath);
|
|
41118
|
+
if (path25.extname(resolved)) {
|
|
40996
41119
|
if (fs13.existsSync(resolved) && fs13.statSync(resolved).isFile()) {
|
|
40997
41120
|
return normalizePath(resolved);
|
|
40998
41121
|
}
|
|
@@ -41037,12 +41160,12 @@ function findTestFilesSync(cwd) {
|
|
|
41037
41160
|
for (const entry of entries) {
|
|
41038
41161
|
if (entry.isDirectory()) {
|
|
41039
41162
|
if (!skipDirs.has(entry.name)) {
|
|
41040
|
-
walk(
|
|
41163
|
+
walk(path25.join(dir, entry.name), visitedInodes);
|
|
41041
41164
|
}
|
|
41042
41165
|
} else if (entry.isFile()) {
|
|
41043
41166
|
const name = entry.name;
|
|
41044
41167
|
if (/\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name)) {
|
|
41045
|
-
testFiles.push(normalizePath(
|
|
41168
|
+
testFiles.push(normalizePath(path25.join(dir, entry.name)));
|
|
41046
41169
|
}
|
|
41047
41170
|
}
|
|
41048
41171
|
}
|
|
@@ -41080,7 +41203,7 @@ async function buildImpactMapInternal(cwd) {
|
|
|
41080
41203
|
continue;
|
|
41081
41204
|
}
|
|
41082
41205
|
const imports = extractImports(content);
|
|
41083
|
-
const testDir =
|
|
41206
|
+
const testDir = path25.dirname(testFile);
|
|
41084
41207
|
for (const importPath of imports) {
|
|
41085
41208
|
const resolvedSource = resolveRelativeImport(testDir, importPath);
|
|
41086
41209
|
if (resolvedSource === null) {
|
|
@@ -41102,7 +41225,7 @@ async function buildImpactMap(cwd) {
|
|
|
41102
41225
|
return impactMap;
|
|
41103
41226
|
}
|
|
41104
41227
|
async function loadImpactMap(cwd) {
|
|
41105
|
-
const cachePath =
|
|
41228
|
+
const cachePath = path25.join(cwd, ".swarm", "cache", "impact-map.json");
|
|
41106
41229
|
if (fs13.existsSync(cachePath)) {
|
|
41107
41230
|
try {
|
|
41108
41231
|
const content = fs13.readFileSync(cachePath, "utf-8");
|
|
@@ -41117,10 +41240,10 @@ async function loadImpactMap(cwd) {
|
|
|
41117
41240
|
return buildImpactMap(cwd);
|
|
41118
41241
|
}
|
|
41119
41242
|
async function saveImpactMap(cwd, impactMap) {
|
|
41120
|
-
const
|
|
41121
|
-
const cachePath =
|
|
41122
|
-
if (!fs13.existsSync(
|
|
41123
|
-
fs13.mkdirSync(
|
|
41243
|
+
const cacheDir2 = path25.join(cwd, ".swarm", "cache");
|
|
41244
|
+
const cachePath = path25.join(cacheDir2, "impact-map.json");
|
|
41245
|
+
if (!fs13.existsSync(cacheDir2)) {
|
|
41246
|
+
fs13.mkdirSync(cacheDir2, { recursive: true });
|
|
41124
41247
|
}
|
|
41125
41248
|
const data = {
|
|
41126
41249
|
generatedAt: new Date().toISOString(),
|
|
@@ -41144,7 +41267,7 @@ async function analyzeImpact(changedFiles, cwd) {
|
|
|
41144
41267
|
const impactedTestsSet = new Set;
|
|
41145
41268
|
const untestedFiles = [];
|
|
41146
41269
|
for (const changedFile of validFiles) {
|
|
41147
|
-
const normalizedChanged = normalizePath(
|
|
41270
|
+
const normalizedChanged = normalizePath(path25.resolve(changedFile));
|
|
41148
41271
|
const tests = impactMap[normalizedChanged];
|
|
41149
41272
|
if (tests && tests.length > 0) {
|
|
41150
41273
|
for (const test of tests) {
|
|
@@ -41391,13 +41514,13 @@ function detectFlakyTests(allHistory) {
|
|
|
41391
41514
|
|
|
41392
41515
|
// src/test-impact/history-store.ts
|
|
41393
41516
|
import fs14 from "fs";
|
|
41394
|
-
import
|
|
41517
|
+
import path26 from "path";
|
|
41395
41518
|
var MAX_HISTORY_PER_TEST = 20;
|
|
41396
41519
|
var MAX_ERROR_LENGTH = 500;
|
|
41397
41520
|
var MAX_STACK_LENGTH = 200;
|
|
41398
41521
|
var MAX_CHANGED_FILES = 50;
|
|
41399
41522
|
function getHistoryPath(workingDir) {
|
|
41400
|
-
return
|
|
41523
|
+
return path26.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
|
|
41401
41524
|
}
|
|
41402
41525
|
function sanitizeErrorMessage(errorMessage) {
|
|
41403
41526
|
if (errorMessage === undefined) {
|
|
@@ -41457,7 +41580,7 @@ function appendTestRun(record3, workingDir) {
|
|
|
41457
41580
|
changedFiles: sanitizeChangedFiles(record3.changedFiles || [])
|
|
41458
41581
|
};
|
|
41459
41582
|
const historyPath = getHistoryPath(workingDir);
|
|
41460
|
-
const historyDir =
|
|
41583
|
+
const historyDir = path26.dirname(historyPath);
|
|
41461
41584
|
if (!fs14.existsSync(historyDir)) {
|
|
41462
41585
|
fs14.mkdirSync(historyDir, { recursive: true });
|
|
41463
41586
|
}
|
|
@@ -41531,7 +41654,7 @@ function getAllHistory(workingDir) {
|
|
|
41531
41654
|
|
|
41532
41655
|
// src/tools/resolve-working-directory.ts
|
|
41533
41656
|
import * as fs15 from "fs";
|
|
41534
|
-
import * as
|
|
41657
|
+
import * as path27 from "path";
|
|
41535
41658
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
41536
41659
|
if (workingDirectory == null || workingDirectory === "") {
|
|
41537
41660
|
return { success: true, directory: fallbackDirectory };
|
|
@@ -41551,15 +41674,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
41551
41674
|
};
|
|
41552
41675
|
}
|
|
41553
41676
|
}
|
|
41554
|
-
const normalizedDir =
|
|
41555
|
-
const pathParts = normalizedDir.split(
|
|
41677
|
+
const normalizedDir = path27.normalize(workingDirectory);
|
|
41678
|
+
const pathParts = normalizedDir.split(path27.sep);
|
|
41556
41679
|
if (pathParts.includes("..")) {
|
|
41557
41680
|
return {
|
|
41558
41681
|
success: false,
|
|
41559
41682
|
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
41560
41683
|
};
|
|
41561
41684
|
}
|
|
41562
|
-
const resolvedDir =
|
|
41685
|
+
const resolvedDir = path27.resolve(normalizedDir);
|
|
41563
41686
|
let statResult;
|
|
41564
41687
|
try {
|
|
41565
41688
|
statResult = fs15.statSync(resolvedDir);
|
|
@@ -41575,7 +41698,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
41575
41698
|
message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
|
|
41576
41699
|
};
|
|
41577
41700
|
}
|
|
41578
|
-
const resolvedFallback =
|
|
41701
|
+
const resolvedFallback = path27.resolve(fallbackDirectory);
|
|
41579
41702
|
let fallbackExists = false;
|
|
41580
41703
|
try {
|
|
41581
41704
|
fs15.statSync(resolvedFallback);
|
|
@@ -41585,7 +41708,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
41585
41708
|
}
|
|
41586
41709
|
if (workingDirectory != null && workingDirectory !== "") {
|
|
41587
41710
|
if (fallbackExists) {
|
|
41588
|
-
const isSubdirectory = resolvedDir.startsWith(resolvedFallback +
|
|
41711
|
+
const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path27.sep);
|
|
41589
41712
|
if (isSubdirectory) {
|
|
41590
41713
|
return {
|
|
41591
41714
|
success: false,
|
|
@@ -41675,14 +41798,14 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
41675
41798
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
41676
41799
|
}
|
|
41677
41800
|
function detectGoTest(cwd) {
|
|
41678
|
-
return fs16.existsSync(
|
|
41801
|
+
return fs16.existsSync(path28.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
41679
41802
|
}
|
|
41680
41803
|
function detectJavaMaven(cwd) {
|
|
41681
|
-
return fs16.existsSync(
|
|
41804
|
+
return fs16.existsSync(path28.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
41682
41805
|
}
|
|
41683
41806
|
function detectGradle(cwd) {
|
|
41684
|
-
const hasBuildFile = fs16.existsSync(
|
|
41685
|
-
const hasGradlew = fs16.existsSync(
|
|
41807
|
+
const hasBuildFile = fs16.existsSync(path28.join(cwd, "build.gradle")) || fs16.existsSync(path28.join(cwd, "build.gradle.kts"));
|
|
41808
|
+
const hasGradlew = fs16.existsSync(path28.join(cwd, "gradlew")) || fs16.existsSync(path28.join(cwd, "gradlew.bat"));
|
|
41686
41809
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
41687
41810
|
}
|
|
41688
41811
|
function detectDotnetTest(cwd) {
|
|
@@ -41695,30 +41818,30 @@ function detectDotnetTest(cwd) {
|
|
|
41695
41818
|
}
|
|
41696
41819
|
}
|
|
41697
41820
|
function detectCTest(cwd) {
|
|
41698
|
-
const hasSource = fs16.existsSync(
|
|
41699
|
-
const hasBuildCache = fs16.existsSync(
|
|
41821
|
+
const hasSource = fs16.existsSync(path28.join(cwd, "CMakeLists.txt"));
|
|
41822
|
+
const hasBuildCache = fs16.existsSync(path28.join(cwd, "CMakeCache.txt")) || fs16.existsSync(path28.join(cwd, "build", "CMakeCache.txt"));
|
|
41700
41823
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
41701
41824
|
}
|
|
41702
41825
|
function detectSwiftTest(cwd) {
|
|
41703
|
-
return fs16.existsSync(
|
|
41826
|
+
return fs16.existsSync(path28.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
41704
41827
|
}
|
|
41705
41828
|
function detectDartTest(cwd) {
|
|
41706
|
-
return fs16.existsSync(
|
|
41829
|
+
return fs16.existsSync(path28.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
41707
41830
|
}
|
|
41708
41831
|
function detectRSpec(cwd) {
|
|
41709
|
-
const hasRSpecFile = fs16.existsSync(
|
|
41710
|
-
const hasGemfile = fs16.existsSync(
|
|
41711
|
-
const hasSpecDir = fs16.existsSync(
|
|
41832
|
+
const hasRSpecFile = fs16.existsSync(path28.join(cwd, ".rspec"));
|
|
41833
|
+
const hasGemfile = fs16.existsSync(path28.join(cwd, "Gemfile"));
|
|
41834
|
+
const hasSpecDir = fs16.existsSync(path28.join(cwd, "spec"));
|
|
41712
41835
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
41713
41836
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
41714
41837
|
}
|
|
41715
41838
|
function detectMinitest(cwd) {
|
|
41716
|
-
return fs16.existsSync(
|
|
41839
|
+
return fs16.existsSync(path28.join(cwd, "test")) && (fs16.existsSync(path28.join(cwd, "Gemfile")) || fs16.existsSync(path28.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
41717
41840
|
}
|
|
41718
41841
|
async function detectTestFramework(cwd) {
|
|
41719
41842
|
const baseDir = cwd;
|
|
41720
41843
|
try {
|
|
41721
|
-
const packageJsonPath =
|
|
41844
|
+
const packageJsonPath = path28.join(baseDir, "package.json");
|
|
41722
41845
|
if (fs16.existsSync(packageJsonPath)) {
|
|
41723
41846
|
const content = fs16.readFileSync(packageJsonPath, "utf-8");
|
|
41724
41847
|
const pkg = JSON.parse(content);
|
|
@@ -41739,16 +41862,16 @@ async function detectTestFramework(cwd) {
|
|
|
41739
41862
|
return "jest";
|
|
41740
41863
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
41741
41864
|
return "mocha";
|
|
41742
|
-
if (fs16.existsSync(
|
|
41865
|
+
if (fs16.existsSync(path28.join(baseDir, "bun.lockb")) || fs16.existsSync(path28.join(baseDir, "bun.lock"))) {
|
|
41743
41866
|
if (scripts.test?.includes("bun"))
|
|
41744
41867
|
return "bun";
|
|
41745
41868
|
}
|
|
41746
41869
|
}
|
|
41747
41870
|
} catch {}
|
|
41748
41871
|
try {
|
|
41749
|
-
const pyprojectTomlPath =
|
|
41750
|
-
const setupCfgPath =
|
|
41751
|
-
const requirementsTxtPath =
|
|
41872
|
+
const pyprojectTomlPath = path28.join(baseDir, "pyproject.toml");
|
|
41873
|
+
const setupCfgPath = path28.join(baseDir, "setup.cfg");
|
|
41874
|
+
const requirementsTxtPath = path28.join(baseDir, "requirements.txt");
|
|
41752
41875
|
if (fs16.existsSync(pyprojectTomlPath)) {
|
|
41753
41876
|
const content = fs16.readFileSync(pyprojectTomlPath, "utf-8");
|
|
41754
41877
|
if (content.includes("[tool.pytest"))
|
|
@@ -41768,7 +41891,7 @@ async function detectTestFramework(cwd) {
|
|
|
41768
41891
|
}
|
|
41769
41892
|
} catch {}
|
|
41770
41893
|
try {
|
|
41771
|
-
const cargoTomlPath =
|
|
41894
|
+
const cargoTomlPath = path28.join(baseDir, "Cargo.toml");
|
|
41772
41895
|
if (fs16.existsSync(cargoTomlPath)) {
|
|
41773
41896
|
const content = fs16.readFileSync(cargoTomlPath, "utf-8");
|
|
41774
41897
|
if (content.includes("[dev-dependencies]")) {
|
|
@@ -41779,9 +41902,9 @@ async function detectTestFramework(cwd) {
|
|
|
41779
41902
|
}
|
|
41780
41903
|
} catch {}
|
|
41781
41904
|
try {
|
|
41782
|
-
const pesterConfigPath =
|
|
41783
|
-
const pesterConfigJsonPath =
|
|
41784
|
-
const pesterPs1Path =
|
|
41905
|
+
const pesterConfigPath = path28.join(baseDir, "pester.config.ps1");
|
|
41906
|
+
const pesterConfigJsonPath = path28.join(baseDir, "pester.config.ps1.json");
|
|
41907
|
+
const pesterPs1Path = path28.join(baseDir, "tests.ps1");
|
|
41785
41908
|
if (fs16.existsSync(pesterConfigPath) || fs16.existsSync(pesterConfigJsonPath) || fs16.existsSync(pesterPs1Path)) {
|
|
41786
41909
|
return "pester";
|
|
41787
41910
|
}
|
|
@@ -41824,12 +41947,12 @@ function isTestDirectoryPath(normalizedPath) {
|
|
|
41824
41947
|
return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
|
|
41825
41948
|
}
|
|
41826
41949
|
function resolveWorkspacePath(file3, workingDir) {
|
|
41827
|
-
return
|
|
41950
|
+
return path28.isAbsolute(file3) ? path28.resolve(file3) : path28.resolve(workingDir, file3);
|
|
41828
41951
|
}
|
|
41829
41952
|
function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
|
|
41830
41953
|
if (!preferRelative)
|
|
41831
41954
|
return absolutePath;
|
|
41832
|
-
return
|
|
41955
|
+
return path28.relative(workingDir, absolutePath);
|
|
41833
41956
|
}
|
|
41834
41957
|
function dedupePush(target, value) {
|
|
41835
41958
|
if (!target.includes(value)) {
|
|
@@ -41866,18 +41989,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
|
|
|
41866
41989
|
}
|
|
41867
41990
|
}
|
|
41868
41991
|
function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
|
|
41869
|
-
const relativeDir =
|
|
41992
|
+
const relativeDir = path28.dirname(relativePath);
|
|
41870
41993
|
const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
|
|
41871
41994
|
const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
|
|
41872
|
-
const rootDir =
|
|
41873
|
-
return nestedRelativeDir ? [rootDir,
|
|
41995
|
+
const rootDir = path28.join(workingDir, dirName);
|
|
41996
|
+
return nestedRelativeDir ? [rootDir, path28.join(rootDir, nestedRelativeDir)] : [rootDir];
|
|
41874
41997
|
});
|
|
41875
41998
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
41876
41999
|
if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
|
|
41877
|
-
directories.push(
|
|
42000
|
+
directories.push(path28.join(workingDir, "src/test/java", path28.dirname(normalizedRelativePath.slice("src/main/java/".length))));
|
|
41878
42001
|
}
|
|
41879
42002
|
if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
|
|
41880
|
-
directories.push(
|
|
42003
|
+
directories.push(path28.join(workingDir, "src/test/kotlin", path28.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
|
|
41881
42004
|
}
|
|
41882
42005
|
return [...new Set(directories)];
|
|
41883
42006
|
}
|
|
@@ -41905,23 +42028,23 @@ function isLanguageSpecificTestFile(basename4) {
|
|
|
41905
42028
|
}
|
|
41906
42029
|
function isConventionTestFilePath(filePath) {
|
|
41907
42030
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
41908
|
-
const basename4 =
|
|
42031
|
+
const basename4 = path28.basename(filePath);
|
|
41909
42032
|
return hasCompoundTestExtension(basename4) || basename4.includes(".spec.") || basename4.includes(".test.") || isLanguageSpecificTestFile(basename4) || isTestDirectoryPath(normalizedPath);
|
|
41910
42033
|
}
|
|
41911
42034
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
41912
42035
|
const testFiles = [];
|
|
41913
42036
|
for (const file3 of sourceFiles) {
|
|
41914
42037
|
const absoluteFile = resolveWorkspacePath(file3, workingDir);
|
|
41915
|
-
const relativeFile =
|
|
41916
|
-
const basename4 =
|
|
41917
|
-
const dirname11 =
|
|
41918
|
-
const preferRelativeOutput = !
|
|
42038
|
+
const relativeFile = path28.relative(workingDir, absoluteFile);
|
|
42039
|
+
const basename4 = path28.basename(absoluteFile);
|
|
42040
|
+
const dirname11 = path28.dirname(absoluteFile);
|
|
42041
|
+
const preferRelativeOutput = !path28.isAbsolute(file3);
|
|
41919
42042
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
|
|
41920
42043
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
41921
42044
|
continue;
|
|
41922
42045
|
}
|
|
41923
42046
|
const nameWithoutExt = basename4.replace(/\.[^.]+$/, "");
|
|
41924
|
-
const ext =
|
|
42047
|
+
const ext = path28.extname(basename4);
|
|
41925
42048
|
const genericTestNames = [
|
|
41926
42049
|
`${nameWithoutExt}.spec${ext}`,
|
|
41927
42050
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -41930,7 +42053,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
41930
42053
|
const colocatedCandidates = [
|
|
41931
42054
|
...genericTestNames,
|
|
41932
42055
|
...languageSpecificTestNames
|
|
41933
|
-
].map((candidateName) =>
|
|
42056
|
+
].map((candidateName) => path28.join(dirname11, candidateName));
|
|
41934
42057
|
const testDirectoryNames = [
|
|
41935
42058
|
basename4,
|
|
41936
42059
|
...genericTestNames,
|
|
@@ -41939,8 +42062,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
41939
42062
|
const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
|
|
41940
42063
|
const possibleTestFiles = [
|
|
41941
42064
|
...colocatedCandidates,
|
|
41942
|
-
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) =>
|
|
41943
|
-
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) =>
|
|
42065
|
+
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path28.join(dirname11, dirName, candidateName))),
|
|
42066
|
+
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path28.join(candidateDir, candidateName)))
|
|
41944
42067
|
];
|
|
41945
42068
|
for (const testFile of possibleTestFiles) {
|
|
41946
42069
|
if (fs16.existsSync(testFile)) {
|
|
@@ -41961,7 +42084,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
41961
42084
|
try {
|
|
41962
42085
|
const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
|
|
41963
42086
|
const content = fs16.readFileSync(absoluteTestFile, "utf-8");
|
|
41964
|
-
const testDir =
|
|
42087
|
+
const testDir = path28.dirname(absoluteTestFile);
|
|
41965
42088
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
41966
42089
|
let match;
|
|
41967
42090
|
match = importRegex.exec(content);
|
|
@@ -41969,8 +42092,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
41969
42092
|
const importPath = match[1];
|
|
41970
42093
|
let resolvedImport;
|
|
41971
42094
|
if (importPath.startsWith(".")) {
|
|
41972
|
-
resolvedImport =
|
|
41973
|
-
const existingExt =
|
|
42095
|
+
resolvedImport = path28.resolve(testDir, importPath);
|
|
42096
|
+
const existingExt = path28.extname(resolvedImport);
|
|
41974
42097
|
if (!existingExt) {
|
|
41975
42098
|
for (const extToTry of [
|
|
41976
42099
|
".ts",
|
|
@@ -41990,12 +42113,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
41990
42113
|
} else {
|
|
41991
42114
|
continue;
|
|
41992
42115
|
}
|
|
41993
|
-
const importBasename =
|
|
41994
|
-
const importDir =
|
|
42116
|
+
const importBasename = path28.basename(resolvedImport, path28.extname(resolvedImport));
|
|
42117
|
+
const importDir = path28.dirname(resolvedImport);
|
|
41995
42118
|
for (const sourceFile of absoluteSourceFiles) {
|
|
41996
|
-
const sourceDir =
|
|
41997
|
-
const sourceBasename =
|
|
41998
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
42119
|
+
const sourceDir = path28.dirname(sourceFile);
|
|
42120
|
+
const sourceBasename = path28.basename(sourceFile, path28.extname(sourceFile));
|
|
42121
|
+
const isRelatedDir = importDir === sourceDir || importDir === path28.join(sourceDir, "__tests__") || importDir === path28.join(sourceDir, "tests") || importDir === path28.join(sourceDir, "test") || importDir === path28.join(sourceDir, "spec");
|
|
41999
42122
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
42000
42123
|
dedupePush(testFiles, testFile);
|
|
42001
42124
|
break;
|
|
@@ -42008,8 +42131,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
42008
42131
|
while (match !== null) {
|
|
42009
42132
|
const importPath = match[1];
|
|
42010
42133
|
if (importPath.startsWith(".")) {
|
|
42011
|
-
let resolvedImport =
|
|
42012
|
-
const existingExt =
|
|
42134
|
+
let resolvedImport = path28.resolve(testDir, importPath);
|
|
42135
|
+
const existingExt = path28.extname(resolvedImport);
|
|
42013
42136
|
if (!existingExt) {
|
|
42014
42137
|
for (const extToTry of [
|
|
42015
42138
|
".ts",
|
|
@@ -42026,12 +42149,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
42026
42149
|
}
|
|
42027
42150
|
}
|
|
42028
42151
|
}
|
|
42029
|
-
const importDir =
|
|
42030
|
-
const importBasename =
|
|
42152
|
+
const importDir = path28.dirname(resolvedImport);
|
|
42153
|
+
const importBasename = path28.basename(resolvedImport, path28.extname(resolvedImport));
|
|
42031
42154
|
for (const sourceFile of absoluteSourceFiles) {
|
|
42032
|
-
const sourceDir =
|
|
42033
|
-
const sourceBasename =
|
|
42034
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
42155
|
+
const sourceDir = path28.dirname(sourceFile);
|
|
42156
|
+
const sourceBasename = path28.basename(sourceFile, path28.extname(sourceFile));
|
|
42157
|
+
const isRelatedDir = importDir === sourceDir || importDir === path28.join(sourceDir, "__tests__") || importDir === path28.join(sourceDir, "tests") || importDir === path28.join(sourceDir, "test") || importDir === path28.join(sourceDir, "spec");
|
|
42035
42158
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
42036
42159
|
dedupePush(testFiles, testFile);
|
|
42037
42160
|
break;
|
|
@@ -42134,8 +42257,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
42134
42257
|
return ["mvn", "test"];
|
|
42135
42258
|
case "gradle": {
|
|
42136
42259
|
const isWindows = process.platform === "win32";
|
|
42137
|
-
const hasGradlewBat = fs16.existsSync(
|
|
42138
|
-
const hasGradlew = fs16.existsSync(
|
|
42260
|
+
const hasGradlewBat = fs16.existsSync(path28.join(baseDir, "gradlew.bat"));
|
|
42261
|
+
const hasGradlew = fs16.existsSync(path28.join(baseDir, "gradlew"));
|
|
42139
42262
|
if (hasGradlewBat && isWindows)
|
|
42140
42263
|
return ["gradlew.bat", "test"];
|
|
42141
42264
|
if (hasGradlew)
|
|
@@ -42152,7 +42275,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
42152
42275
|
"cmake-build-release",
|
|
42153
42276
|
"out"
|
|
42154
42277
|
];
|
|
42155
|
-
const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(
|
|
42278
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(path28.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
42156
42279
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
42157
42280
|
}
|
|
42158
42281
|
case "swift-test":
|
|
@@ -42780,7 +42903,7 @@ var test_runner = createSwarmTool({
|
|
|
42780
42903
|
const sourceFiles = args.files.filter((file3) => {
|
|
42781
42904
|
if (directTestFiles.includes(file3))
|
|
42782
42905
|
return false;
|
|
42783
|
-
const ext =
|
|
42906
|
+
const ext = path28.extname(file3).toLowerCase();
|
|
42784
42907
|
return SOURCE_EXTENSIONS.has(ext);
|
|
42785
42908
|
});
|
|
42786
42909
|
const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
|
|
@@ -42815,7 +42938,7 @@ var test_runner = createSwarmTool({
|
|
|
42815
42938
|
if (isConventionTestFilePath(f)) {
|
|
42816
42939
|
return false;
|
|
42817
42940
|
}
|
|
42818
|
-
const ext =
|
|
42941
|
+
const ext = path28.extname(f).toLowerCase();
|
|
42819
42942
|
return SOURCE_EXTENSIONS.has(ext);
|
|
42820
42943
|
});
|
|
42821
42944
|
if (sourceFiles.length === 0) {
|
|
@@ -42842,7 +42965,7 @@ var test_runner = createSwarmTool({
|
|
|
42842
42965
|
if (isConventionTestFilePath(f)) {
|
|
42843
42966
|
return false;
|
|
42844
42967
|
}
|
|
42845
|
-
const ext =
|
|
42968
|
+
const ext = path28.extname(f).toLowerCase();
|
|
42846
42969
|
return SOURCE_EXTENSIONS.has(ext);
|
|
42847
42970
|
});
|
|
42848
42971
|
if (sourceFiles.length === 0) {
|
|
@@ -42860,8 +42983,8 @@ var test_runner = createSwarmTool({
|
|
|
42860
42983
|
const impactResult = await analyzeImpact(sourceFiles, workingDir);
|
|
42861
42984
|
if (impactResult.impactedTests.length > 0) {
|
|
42862
42985
|
testFiles = impactResult.impactedTests.map((absPath) => {
|
|
42863
|
-
const relativePath =
|
|
42864
|
-
return
|
|
42986
|
+
const relativePath = path28.relative(workingDir, absPath);
|
|
42987
|
+
return path28.isAbsolute(relativePath) ? absPath : relativePath;
|
|
42865
42988
|
});
|
|
42866
42989
|
} else {
|
|
42867
42990
|
graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
|
|
@@ -42954,8 +43077,8 @@ function validateDirectoryPath(dir) {
|
|
|
42954
43077
|
if (dir.includes("..")) {
|
|
42955
43078
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
42956
43079
|
}
|
|
42957
|
-
const normalized =
|
|
42958
|
-
const absolutePath =
|
|
43080
|
+
const normalized = path29.normalize(dir);
|
|
43081
|
+
const absolutePath = path29.isAbsolute(normalized) ? normalized : path29.resolve(normalized);
|
|
42959
43082
|
return absolutePath;
|
|
42960
43083
|
}
|
|
42961
43084
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -42978,7 +43101,7 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
42978
43101
|
}
|
|
42979
43102
|
function getPackageVersion(dir) {
|
|
42980
43103
|
try {
|
|
42981
|
-
const packagePath =
|
|
43104
|
+
const packagePath = path29.join(dir, "package.json");
|
|
42982
43105
|
if (fs17.existsSync(packagePath)) {
|
|
42983
43106
|
const content = fs17.readFileSync(packagePath, "utf-8");
|
|
42984
43107
|
const pkg = JSON.parse(content);
|
|
@@ -42989,7 +43112,7 @@ function getPackageVersion(dir) {
|
|
|
42989
43112
|
}
|
|
42990
43113
|
function getChangelogVersion(dir) {
|
|
42991
43114
|
try {
|
|
42992
|
-
const changelogPath =
|
|
43115
|
+
const changelogPath = path29.join(dir, "CHANGELOG.md");
|
|
42993
43116
|
if (fs17.existsSync(changelogPath)) {
|
|
42994
43117
|
const content = fs17.readFileSync(changelogPath, "utf-8");
|
|
42995
43118
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
@@ -43003,7 +43126,7 @@ function getChangelogVersion(dir) {
|
|
|
43003
43126
|
function getVersionFileVersion(dir) {
|
|
43004
43127
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
43005
43128
|
for (const file3 of possibleFiles) {
|
|
43006
|
-
const filePath =
|
|
43129
|
+
const filePath = path29.join(dir, file3);
|
|
43007
43130
|
if (fs17.existsSync(filePath)) {
|
|
43008
43131
|
try {
|
|
43009
43132
|
const content = fs17.readFileSync(filePath, "utf-8").trim();
|
|
@@ -43330,7 +43453,7 @@ async function runEvidenceCheck(dir) {
|
|
|
43330
43453
|
async function runRequirementCoverageCheck(dir, currentPhase) {
|
|
43331
43454
|
const startTime = Date.now();
|
|
43332
43455
|
try {
|
|
43333
|
-
const specPath =
|
|
43456
|
+
const specPath = path29.join(dir, ".swarm", "spec.md");
|
|
43334
43457
|
if (!fs17.existsSync(specPath)) {
|
|
43335
43458
|
return {
|
|
43336
43459
|
type: "req_coverage",
|
|
@@ -44453,7 +44576,7 @@ async function handleResetCommand(directory, args) {
|
|
|
44453
44576
|
// src/commands/reset-session.ts
|
|
44454
44577
|
init_utils2();
|
|
44455
44578
|
import * as fs19 from "fs";
|
|
44456
|
-
import * as
|
|
44579
|
+
import * as path30 from "path";
|
|
44457
44580
|
async function handleResetSessionCommand(directory, _args) {
|
|
44458
44581
|
const results = [];
|
|
44459
44582
|
try {
|
|
@@ -44468,13 +44591,13 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
44468
44591
|
results.push("\u274C Failed to delete state.json");
|
|
44469
44592
|
}
|
|
44470
44593
|
try {
|
|
44471
|
-
const sessionDir =
|
|
44594
|
+
const sessionDir = path30.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
44472
44595
|
if (fs19.existsSync(sessionDir)) {
|
|
44473
44596
|
const files = fs19.readdirSync(sessionDir);
|
|
44474
44597
|
const otherFiles = files.filter((f) => f !== "state.json");
|
|
44475
44598
|
let deletedCount = 0;
|
|
44476
44599
|
for (const file3 of otherFiles) {
|
|
44477
|
-
const filePath =
|
|
44600
|
+
const filePath = path30.join(sessionDir, file3);
|
|
44478
44601
|
if (fs19.lstatSync(filePath).isFile()) {
|
|
44479
44602
|
fs19.unlinkSync(filePath);
|
|
44480
44603
|
deletedCount++;
|
|
@@ -44504,7 +44627,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
44504
44627
|
// src/summaries/manager.ts
|
|
44505
44628
|
init_utils2();
|
|
44506
44629
|
init_utils();
|
|
44507
|
-
import * as
|
|
44630
|
+
import * as path31 from "path";
|
|
44508
44631
|
var SUMMARY_ID_REGEX = /^S\d+$/;
|
|
44509
44632
|
function sanitizeSummaryId(id) {
|
|
44510
44633
|
if (!id || id.length === 0) {
|
|
@@ -44528,7 +44651,7 @@ function sanitizeSummaryId(id) {
|
|
|
44528
44651
|
}
|
|
44529
44652
|
async function loadFullOutput(directory, id) {
|
|
44530
44653
|
const sanitizedId = sanitizeSummaryId(id);
|
|
44531
|
-
const relativePath =
|
|
44654
|
+
const relativePath = path31.join("summaries", `${sanitizedId}.json`);
|
|
44532
44655
|
validateSwarmPath(directory, relativePath);
|
|
44533
44656
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
44534
44657
|
if (content === null) {
|
|
@@ -44584,7 +44707,7 @@ init_plan_schema();
|
|
|
44584
44707
|
init_utils2();
|
|
44585
44708
|
init_ledger();
|
|
44586
44709
|
import * as fs20 from "fs";
|
|
44587
|
-
import * as
|
|
44710
|
+
import * as path32 from "path";
|
|
44588
44711
|
async function handleRollbackCommand(directory, args) {
|
|
44589
44712
|
const phaseArg = args[0];
|
|
44590
44713
|
if (!phaseArg) {
|
|
@@ -44649,8 +44772,8 @@ async function handleRollbackCommand(directory, args) {
|
|
|
44649
44772
|
if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
|
|
44650
44773
|
continue;
|
|
44651
44774
|
}
|
|
44652
|
-
const src =
|
|
44653
|
-
const dest =
|
|
44775
|
+
const src = path32.join(checkpointDir, file3);
|
|
44776
|
+
const dest = path32.join(swarmDir, file3);
|
|
44654
44777
|
try {
|
|
44655
44778
|
fs20.cpSync(src, dest, { recursive: true, force: true });
|
|
44656
44779
|
successes.push(file3);
|
|
@@ -44669,12 +44792,12 @@ async function handleRollbackCommand(directory, args) {
|
|
|
44669
44792
|
].join(`
|
|
44670
44793
|
`);
|
|
44671
44794
|
}
|
|
44672
|
-
const existingLedgerPath =
|
|
44795
|
+
const existingLedgerPath = path32.join(swarmDir, "plan-ledger.jsonl");
|
|
44673
44796
|
if (fs20.existsSync(existingLedgerPath)) {
|
|
44674
44797
|
fs20.unlinkSync(existingLedgerPath);
|
|
44675
44798
|
}
|
|
44676
44799
|
try {
|
|
44677
|
-
const planJsonPath =
|
|
44800
|
+
const planJsonPath = path32.join(swarmDir, "plan.json");
|
|
44678
44801
|
if (fs20.existsSync(planJsonPath)) {
|
|
44679
44802
|
const planRaw = fs20.readFileSync(planJsonPath, "utf-8");
|
|
44680
44803
|
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
@@ -44747,9 +44870,9 @@ async function handleSimulateCommand(directory, args) {
|
|
|
44747
44870
|
const report = reportLines.filter(Boolean).join(`
|
|
44748
44871
|
`);
|
|
44749
44872
|
const fs21 = await import("fs/promises");
|
|
44750
|
-
const
|
|
44751
|
-
const reportPath =
|
|
44752
|
-
await fs21.mkdir(
|
|
44873
|
+
const path33 = await import("path");
|
|
44874
|
+
const reportPath = path33.join(directory, ".swarm", "simulate-report.md");
|
|
44875
|
+
await fs21.mkdir(path33.dirname(reportPath), { recursive: true });
|
|
44753
44876
|
await fs21.writeFile(reportPath, report, "utf-8");
|
|
44754
44877
|
return `${darkMatterPairs.length} hidden coupling pairs detected`;
|
|
44755
44878
|
}
|
|
@@ -45284,11 +45407,35 @@ function resolveCommand(tokens) {
|
|
|
45284
45407
|
|
|
45285
45408
|
// src/cli/index.ts
|
|
45286
45409
|
var { version: version4 } = package_default;
|
|
45287
|
-
var CONFIG_DIR =
|
|
45288
|
-
var OPENCODE_CONFIG_PATH =
|
|
45289
|
-
var PLUGIN_CONFIG_PATH =
|
|
45290
|
-
var PROMPTS_DIR =
|
|
45291
|
-
var
|
|
45410
|
+
var CONFIG_DIR = getPluginConfigDir();
|
|
45411
|
+
var OPENCODE_CONFIG_PATH = path33.join(CONFIG_DIR, "opencode.json");
|
|
45412
|
+
var PLUGIN_CONFIG_PATH = path33.join(CONFIG_DIR, "opencode-swarm.json");
|
|
45413
|
+
var PROMPTS_DIR = path33.join(CONFIG_DIR, "opencode-swarm");
|
|
45414
|
+
var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
|
|
45415
|
+
function isSafeCachePath(p) {
|
|
45416
|
+
const resolved = path33.resolve(p);
|
|
45417
|
+
const home = path33.resolve(os7.homedir());
|
|
45418
|
+
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
45419
|
+
return false;
|
|
45420
|
+
}
|
|
45421
|
+
const segments = resolved.split(path33.sep).filter((s) => s.length > 0);
|
|
45422
|
+
if (segments.length < 4) {
|
|
45423
|
+
return false;
|
|
45424
|
+
}
|
|
45425
|
+
const leaf = path33.basename(resolved);
|
|
45426
|
+
if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
|
|
45427
|
+
return false;
|
|
45428
|
+
}
|
|
45429
|
+
const parent = path33.basename(path33.dirname(resolved));
|
|
45430
|
+
if (parent !== "packages" && parent !== "node_modules") {
|
|
45431
|
+
return false;
|
|
45432
|
+
}
|
|
45433
|
+
const grandparent = path33.basename(path33.dirname(path33.dirname(resolved)));
|
|
45434
|
+
if (grandparent !== "opencode") {
|
|
45435
|
+
return false;
|
|
45436
|
+
}
|
|
45437
|
+
return true;
|
|
45438
|
+
}
|
|
45292
45439
|
function ensureDir(dir) {
|
|
45293
45440
|
if (!fs21.existsSync(dir)) {
|
|
45294
45441
|
fs21.mkdirSync(dir, { recursive: true });
|
|
@@ -45309,8 +45456,8 @@ function saveJson(filepath, data) {
|
|
|
45309
45456
|
}
|
|
45310
45457
|
function writeProjectConfigIfMissing(cwd) {
|
|
45311
45458
|
try {
|
|
45312
|
-
const opencodeDir =
|
|
45313
|
-
const projectConfigPath =
|
|
45459
|
+
const opencodeDir = path33.join(cwd, ".opencode");
|
|
45460
|
+
const projectConfigPath = path33.join(opencodeDir, "opencode-swarm.json");
|
|
45314
45461
|
if (fs21.existsSync(projectConfigPath)) {
|
|
45315
45462
|
return;
|
|
45316
45463
|
}
|
|
@@ -45328,7 +45475,7 @@ async function install() {
|
|
|
45328
45475
|
`);
|
|
45329
45476
|
ensureDir(CONFIG_DIR);
|
|
45330
45477
|
ensureDir(PROMPTS_DIR);
|
|
45331
|
-
const LEGACY_CONFIG_PATH =
|
|
45478
|
+
const LEGACY_CONFIG_PATH = path33.join(CONFIG_DIR, "config.json");
|
|
45332
45479
|
let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
|
|
45333
45480
|
if (!opencodeConfig) {
|
|
45334
45481
|
const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
|
|
@@ -45359,14 +45506,13 @@ async function install() {
|
|
|
45359
45506
|
saveJson(OPENCODE_CONFIG_PATH, opencodeConfig);
|
|
45360
45507
|
console.log("\u2713 Added opencode-swarm to OpenCode plugins");
|
|
45361
45508
|
console.log("\u2713 Disabled default OpenCode agents (explore, general)");
|
|
45362
|
-
|
|
45363
|
-
|
|
45364
|
-
|
|
45365
|
-
|
|
45366
|
-
|
|
45367
|
-
|
|
45368
|
-
|
|
45369
|
-
console.warn(` ${OPENCODE_PLUGIN_CACHE_PATH}`);
|
|
45509
|
+
const evicted = evictPluginCaches();
|
|
45510
|
+
if (evicted.cleared.length > 0) {
|
|
45511
|
+
console.log(`\u2713 Cleared opencode plugin cache (next start will fetch latest): ${evicted.cleared.join(", ")}`);
|
|
45512
|
+
}
|
|
45513
|
+
for (const failed of evicted.failed) {
|
|
45514
|
+
console.warn(`\u26A0 Could not clear opencode plugin cache \u2014 you may need to delete it manually:
|
|
45515
|
+
${failed}`);
|
|
45370
45516
|
}
|
|
45371
45517
|
if (!fs21.existsSync(PLUGIN_CONFIG_PATH)) {
|
|
45372
45518
|
const defaultConfig = {
|
|
@@ -45466,6 +45612,51 @@ Next steps:`);
|
|
|
45466
45612
|
console.log(" \u2014 use it as a reference for customizing model assignments.");
|
|
45467
45613
|
return 0;
|
|
45468
45614
|
}
|
|
45615
|
+
async function update() {
|
|
45616
|
+
console.log(`\uD83D\uDC1D Refreshing OpenCode Swarm plugin cache...
|
|
45617
|
+
`);
|
|
45618
|
+
const result = evictPluginCaches();
|
|
45619
|
+
if (result.cleared.length > 0) {
|
|
45620
|
+
for (const cleared of result.cleared) {
|
|
45621
|
+
console.log(`\u2713 Cleared: ${cleared}`);
|
|
45622
|
+
}
|
|
45623
|
+
console.log(`
|
|
45624
|
+
Restart OpenCode to fetch the latest version from npm.`);
|
|
45625
|
+
}
|
|
45626
|
+
if (result.cleared.length === 0 && result.failed.length === 0) {
|
|
45627
|
+
console.log("No cached plugin found. Restart OpenCode to fetch the latest version from npm.");
|
|
45628
|
+
console.log("Checked locations:");
|
|
45629
|
+
for (const p of OPENCODE_PLUGIN_CACHE_PATHS) {
|
|
45630
|
+
console.log(` - ${p}`);
|
|
45631
|
+
}
|
|
45632
|
+
}
|
|
45633
|
+
if (result.failed.length > 0) {
|
|
45634
|
+
for (const failed of result.failed) {
|
|
45635
|
+
console.error(`\u2717 Could not clear: ${failed}`);
|
|
45636
|
+
}
|
|
45637
|
+
return 1;
|
|
45638
|
+
}
|
|
45639
|
+
return 0;
|
|
45640
|
+
}
|
|
45641
|
+
function evictPluginCaches() {
|
|
45642
|
+
const cleared = [];
|
|
45643
|
+
const failed = [];
|
|
45644
|
+
for (const cachePath of OPENCODE_PLUGIN_CACHE_PATHS) {
|
|
45645
|
+
if (!fs21.existsSync(cachePath))
|
|
45646
|
+
continue;
|
|
45647
|
+
if (!isSafeCachePath(cachePath)) {
|
|
45648
|
+
failed.push(`${cachePath} (refused: failed safety check)`);
|
|
45649
|
+
continue;
|
|
45650
|
+
}
|
|
45651
|
+
try {
|
|
45652
|
+
fs21.rmSync(cachePath, { recursive: true, force: true });
|
|
45653
|
+
cleared.push(cachePath);
|
|
45654
|
+
} catch (err) {
|
|
45655
|
+
failed.push(`${cachePath} (${err instanceof Error ? err.message : String(err)})`);
|
|
45656
|
+
}
|
|
45657
|
+
}
|
|
45658
|
+
return { cleared, failed };
|
|
45659
|
+
}
|
|
45469
45660
|
async function uninstall() {
|
|
45470
45661
|
try {
|
|
45471
45662
|
console.log(`\uD83D\uDC1D Uninstalling OpenCode Swarm...
|
|
@@ -45536,6 +45727,7 @@ Usage: bunx opencode-swarm [command] [OPTIONS]
|
|
|
45536
45727
|
|
|
45537
45728
|
Commands:
|
|
45538
45729
|
install Install and configure the plugin (default)
|
|
45730
|
+
update Refresh OpenCode's plugin cache so the next start fetches latest from npm
|
|
45539
45731
|
uninstall Remove the plugin from OpenCode config
|
|
45540
45732
|
run Run a plugin command directly (for use outside OpenCode)
|
|
45541
45733
|
|
|
@@ -45560,6 +45752,7 @@ Custom Prompts:
|
|
|
45560
45752
|
|
|
45561
45753
|
Examples:
|
|
45562
45754
|
bunx opencode-swarm install
|
|
45755
|
+
bunx opencode-swarm update
|
|
45563
45756
|
bunx opencode-swarm uninstall
|
|
45564
45757
|
bunx opencode-swarm uninstall --clean
|
|
45565
45758
|
bunx opencode-swarm --help
|
|
@@ -45585,6 +45778,9 @@ async function main() {
|
|
|
45585
45778
|
if (command === "install") {
|
|
45586
45779
|
const exitCode = await install();
|
|
45587
45780
|
process.exit(exitCode);
|
|
45781
|
+
} else if (command === "update") {
|
|
45782
|
+
const exitCode = await update();
|
|
45783
|
+
process.exit(exitCode);
|
|
45588
45784
|
} else if (command === "uninstall") {
|
|
45589
45785
|
const exitCode = await uninstall();
|
|
45590
45786
|
process.exit(exitCode);
|