opencode-swarm 6.86.5 → 6.86.6
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 +77 -17
- package/dist/__tests__/cli-version.adversarial.test.d.ts +1 -0
- package/dist/__tests__/cli-version.test.d.ts +1 -0
- package/dist/cli/index.js +682 -509
- package/dist/config/schema.d.ts +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1176 -1001
- package/dist/services/diagnose-service.d.ts +1 -1
- package/dist/services/warning-buffer.d.ts +9 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -17668,15 +17668,15 @@ __export(exports_config_doctor, {
|
|
|
17668
17668
|
applySafeAutoFixes: () => applySafeAutoFixes
|
|
17669
17669
|
});
|
|
17670
17670
|
import * as crypto3 from "crypto";
|
|
17671
|
-
import * as
|
|
17671
|
+
import * as fs8 from "fs";
|
|
17672
17672
|
import * as os5 from "os";
|
|
17673
|
-
import * as
|
|
17673
|
+
import * as path18 from "path";
|
|
17674
17674
|
function getUserConfigDir3() {
|
|
17675
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
17675
|
+
return process.env.XDG_CONFIG_HOME || path18.join(os5.homedir(), ".config");
|
|
17676
17676
|
}
|
|
17677
17677
|
function getConfigPaths(directory) {
|
|
17678
|
-
const userConfigPath =
|
|
17679
|
-
const projectConfigPath =
|
|
17678
|
+
const userConfigPath = path18.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
|
|
17679
|
+
const projectConfigPath = path18.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 = path18.resolve(configPath);
|
|
17705
|
+
const resolvedUser = path18.resolve(normalizedUser);
|
|
17706
|
+
const resolvedProject = path18.resolve(normalizedProject);
|
|
17707
17707
|
return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
|
|
17708
17708
|
} catch {
|
|
17709
17709
|
return false;
|
|
@@ -17713,19 +17713,19 @@ function createConfigBackup(directory) {
|
|
|
17713
17713
|
const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
|
|
17714
17714
|
let configPath = projectConfigPath;
|
|
17715
17715
|
let content = null;
|
|
17716
|
-
if (
|
|
17716
|
+
if (fs8.existsSync(projectConfigPath)) {
|
|
17717
17717
|
try {
|
|
17718
|
-
content =
|
|
17718
|
+
content = fs8.readFileSync(projectConfigPath, "utf-8");
|
|
17719
17719
|
} catch (error93) {
|
|
17720
17720
|
log("[ConfigDoctor] project config read failed", {
|
|
17721
17721
|
error: error93 instanceof Error ? error93.message : String(error93)
|
|
17722
17722
|
});
|
|
17723
17723
|
}
|
|
17724
17724
|
}
|
|
17725
|
-
if (content === null &&
|
|
17725
|
+
if (content === null && fs8.existsSync(userConfigPath)) {
|
|
17726
17726
|
configPath = userConfigPath;
|
|
17727
17727
|
try {
|
|
17728
|
-
content =
|
|
17728
|
+
content = fs8.readFileSync(userConfigPath, "utf-8");
|
|
17729
17729
|
} catch (error93) {
|
|
17730
17730
|
log("[ConfigDoctor] user config read failed", {
|
|
17731
17731
|
error: error93 instanceof Error ? error93.message : String(error93)
|
|
@@ -17743,12 +17743,12 @@ function createConfigBackup(directory) {
|
|
|
17743
17743
|
};
|
|
17744
17744
|
}
|
|
17745
17745
|
function writeBackupArtifact(directory, backup) {
|
|
17746
|
-
const swarmDir =
|
|
17747
|
-
if (!
|
|
17748
|
-
|
|
17746
|
+
const swarmDir = path18.join(directory, ".swarm");
|
|
17747
|
+
if (!fs8.existsSync(swarmDir)) {
|
|
17748
|
+
fs8.mkdirSync(swarmDir, { recursive: true });
|
|
17749
17749
|
}
|
|
17750
17750
|
const backupFilename = `config-backup-${backup.createdAt}.json`;
|
|
17751
|
-
const backupPath =
|
|
17751
|
+
const backupPath = path18.join(swarmDir, backupFilename);
|
|
17752
17752
|
const artifact = {
|
|
17753
17753
|
createdAt: backup.createdAt,
|
|
17754
17754
|
configPath: backup.configPath,
|
|
@@ -17756,15 +17756,15 @@ function writeBackupArtifact(directory, backup) {
|
|
|
17756
17756
|
content: backup.content,
|
|
17757
17757
|
preview: backup.content.substring(0, 500) + (backup.content.length > 500 ? "..." : "")
|
|
17758
17758
|
};
|
|
17759
|
-
|
|
17759
|
+
fs8.writeFileSync(backupPath, JSON.stringify(artifact, null, 2), "utf-8");
|
|
17760
17760
|
return backupPath;
|
|
17761
17761
|
}
|
|
17762
17762
|
function restoreFromBackup(backupPath, directory) {
|
|
17763
|
-
if (!
|
|
17763
|
+
if (!fs8.existsSync(backupPath)) {
|
|
17764
17764
|
return null;
|
|
17765
17765
|
}
|
|
17766
17766
|
try {
|
|
17767
|
-
const artifact = JSON.parse(
|
|
17767
|
+
const artifact = JSON.parse(fs8.readFileSync(backupPath, "utf-8"));
|
|
17768
17768
|
if (!artifact.content || !artifact.configPath || !artifact.contentHash) {
|
|
17769
17769
|
return null;
|
|
17770
17770
|
}
|
|
@@ -17778,11 +17778,11 @@ function restoreFromBackup(backupPath, directory) {
|
|
|
17778
17778
|
return null;
|
|
17779
17779
|
}
|
|
17780
17780
|
const targetPath = artifact.configPath;
|
|
17781
|
-
const targetDir =
|
|
17782
|
-
if (!
|
|
17783
|
-
|
|
17781
|
+
const targetDir = path18.dirname(targetPath);
|
|
17782
|
+
if (!fs8.existsSync(targetDir)) {
|
|
17783
|
+
fs8.mkdirSync(targetDir, { recursive: true });
|
|
17784
17784
|
}
|
|
17785
|
-
|
|
17785
|
+
fs8.writeFileSync(targetPath, artifact.content, "utf-8");
|
|
17786
17786
|
return targetPath;
|
|
17787
17787
|
} catch {
|
|
17788
17788
|
return null;
|
|
@@ -17792,12 +17792,12 @@ function readConfigFromFile(directory) {
|
|
|
17792
17792
|
const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
|
|
17793
17793
|
let configPath = projectConfigPath;
|
|
17794
17794
|
let configContent = null;
|
|
17795
|
-
if (
|
|
17795
|
+
if (fs8.existsSync(projectConfigPath)) {
|
|
17796
17796
|
configPath = projectConfigPath;
|
|
17797
|
-
configContent =
|
|
17798
|
-
} else if (
|
|
17797
|
+
configContent = fs8.readFileSync(projectConfigPath, "utf-8");
|
|
17798
|
+
} else if (fs8.existsSync(userConfigPath)) {
|
|
17799
17799
|
configPath = userConfigPath;
|
|
17800
|
-
configContent =
|
|
17800
|
+
configContent = fs8.readFileSync(userConfigPath, "utf-8");
|
|
17801
17801
|
}
|
|
17802
17802
|
if (configContent === null) {
|
|
17803
17803
|
return null;
|
|
@@ -17809,9 +17809,9 @@ function readConfigFromFile(directory) {
|
|
|
17809
17809
|
return null;
|
|
17810
17810
|
}
|
|
17811
17811
|
}
|
|
17812
|
-
function validateConfigKey(
|
|
17812
|
+
function validateConfigKey(path19, value, _config) {
|
|
17813
17813
|
const findings = [];
|
|
17814
|
-
switch (
|
|
17814
|
+
switch (path19) {
|
|
17815
17815
|
case "agents": {
|
|
17816
17816
|
if (value !== undefined) {
|
|
17817
17817
|
findings.push({
|
|
@@ -18058,27 +18058,27 @@ function validateConfigKey(path20, value, _config) {
|
|
|
18058
18058
|
}
|
|
18059
18059
|
return findings;
|
|
18060
18060
|
}
|
|
18061
|
-
function walkConfigAndValidate(obj,
|
|
18061
|
+
function walkConfigAndValidate(obj, path19, config3, findings) {
|
|
18062
18062
|
if (obj === null || obj === undefined) {
|
|
18063
18063
|
return;
|
|
18064
18064
|
}
|
|
18065
|
-
if (
|
|
18066
|
-
const keyFindings = validateConfigKey(
|
|
18065
|
+
if (path19 && typeof obj === "object" && !Array.isArray(obj)) {
|
|
18066
|
+
const keyFindings = validateConfigKey(path19, obj, config3);
|
|
18067
18067
|
findings.push(...keyFindings);
|
|
18068
18068
|
}
|
|
18069
18069
|
if (typeof obj !== "object") {
|
|
18070
|
-
const keyFindings = validateConfigKey(
|
|
18070
|
+
const keyFindings = validateConfigKey(path19, 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, `${path19}[${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 = path19 ? `${path19}.${key}` : key;
|
|
18082
18082
|
walkConfigAndValidate(value, newPath, config3, findings);
|
|
18083
18083
|
}
|
|
18084
18084
|
}
|
|
@@ -18093,9 +18093,9 @@ function runConfigDoctor(config3, directory) {
|
|
|
18093
18093
|
const hasAutoFixableIssues = findings.some((f) => f.autoFixable && f.proposedFix?.risk === "low");
|
|
18094
18094
|
const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
|
|
18095
18095
|
let configSource = "defaults";
|
|
18096
|
-
if (
|
|
18096
|
+
if (fs8.existsSync(projectConfigPath)) {
|
|
18097
18097
|
configSource = projectConfigPath;
|
|
18098
|
-
} else if (
|
|
18098
|
+
} else if (fs8.existsSync(userConfigPath)) {
|
|
18099
18099
|
configSource = userConfigPath;
|
|
18100
18100
|
}
|
|
18101
18101
|
return {
|
|
@@ -18124,12 +18124,12 @@ function applySafeAutoFixes(directory, result) {
|
|
|
18124
18124
|
const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
|
|
18125
18125
|
let configPath = projectConfigPath;
|
|
18126
18126
|
let configContent;
|
|
18127
|
-
if (
|
|
18127
|
+
if (fs8.existsSync(projectConfigPath)) {
|
|
18128
18128
|
configPath = projectConfigPath;
|
|
18129
|
-
configContent =
|
|
18130
|
-
} else if (
|
|
18129
|
+
configContent = fs8.readFileSync(projectConfigPath, "utf-8");
|
|
18130
|
+
} else if (fs8.existsSync(userConfigPath)) {
|
|
18131
18131
|
configPath = userConfigPath;
|
|
18132
|
-
configContent =
|
|
18132
|
+
configContent = fs8.readFileSync(userConfigPath, "utf-8");
|
|
18133
18133
|
} else {
|
|
18134
18134
|
return { appliedFixes, updatedConfigPath: null };
|
|
18135
18135
|
}
|
|
@@ -18198,22 +18198,22 @@ function applySafeAutoFixes(directory, result) {
|
|
|
18198
18198
|
}
|
|
18199
18199
|
}
|
|
18200
18200
|
if (appliedFixes.length > 0) {
|
|
18201
|
-
const configDir =
|
|
18202
|
-
if (!
|
|
18203
|
-
|
|
18201
|
+
const configDir = path18.dirname(configPath);
|
|
18202
|
+
if (!fs8.existsSync(configDir)) {
|
|
18203
|
+
fs8.mkdirSync(configDir, { recursive: true });
|
|
18204
18204
|
}
|
|
18205
|
-
|
|
18205
|
+
fs8.writeFileSync(configPath, JSON.stringify(config3, null, 2), "utf-8");
|
|
18206
18206
|
updatedConfigPath = configPath;
|
|
18207
18207
|
}
|
|
18208
18208
|
return { appliedFixes, updatedConfigPath };
|
|
18209
18209
|
}
|
|
18210
18210
|
function writeDoctorArtifact(directory, result) {
|
|
18211
|
-
const swarmDir =
|
|
18212
|
-
if (!
|
|
18213
|
-
|
|
18211
|
+
const swarmDir = path18.join(directory, ".swarm");
|
|
18212
|
+
if (!fs8.existsSync(swarmDir)) {
|
|
18213
|
+
fs8.mkdirSync(swarmDir, { recursive: true });
|
|
18214
18214
|
}
|
|
18215
18215
|
const artifactFilename = "config-doctor.json";
|
|
18216
|
-
const artifactPath =
|
|
18216
|
+
const artifactPath = path18.join(swarmDir, artifactFilename);
|
|
18217
18217
|
const guiOutput = {
|
|
18218
18218
|
timestamp: result.timestamp,
|
|
18219
18219
|
summary: result.summary,
|
|
@@ -18234,7 +18234,7 @@ function writeDoctorArtifact(directory, result) {
|
|
|
18234
18234
|
} : null
|
|
18235
18235
|
}))
|
|
18236
18236
|
};
|
|
18237
|
-
|
|
18237
|
+
fs8.writeFileSync(artifactPath, JSON.stringify(guiOutput, null, 2), "utf-8");
|
|
18238
18238
|
return artifactPath;
|
|
18239
18239
|
}
|
|
18240
18240
|
function shouldRunOnStartup(automationConfig) {
|
|
@@ -18574,9 +18574,78 @@ var init_evidence_summary_service = __esm(() => {
|
|
|
18574
18574
|
});
|
|
18575
18575
|
|
|
18576
18576
|
// src/cli/index.ts
|
|
18577
|
-
import * as
|
|
18577
|
+
import * as fs21 from "fs";
|
|
18578
18578
|
import * as os6 from "os";
|
|
18579
|
-
import * as
|
|
18579
|
+
import * as path32 from "path";
|
|
18580
|
+
// package.json
|
|
18581
|
+
var package_default = {
|
|
18582
|
+
name: "opencode-swarm",
|
|
18583
|
+
version: "6.86.6",
|
|
18584
|
+
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
18585
|
+
main: "dist/index.js",
|
|
18586
|
+
types: "dist/index.d.ts",
|
|
18587
|
+
bin: {
|
|
18588
|
+
"opencode-swarm": "./dist/cli/index.js"
|
|
18589
|
+
},
|
|
18590
|
+
type: "module",
|
|
18591
|
+
engines: {
|
|
18592
|
+
bun: ">=1.0.0"
|
|
18593
|
+
},
|
|
18594
|
+
license: "MIT",
|
|
18595
|
+
repository: {
|
|
18596
|
+
type: "git",
|
|
18597
|
+
url: "https://github.com/zaxbysauce/opencode-swarm.git"
|
|
18598
|
+
},
|
|
18599
|
+
publishConfig: {
|
|
18600
|
+
access: "public",
|
|
18601
|
+
registry: "https://registry.npmjs.org/"
|
|
18602
|
+
},
|
|
18603
|
+
keywords: [
|
|
18604
|
+
"opencode",
|
|
18605
|
+
"opencode-plugin",
|
|
18606
|
+
"ai",
|
|
18607
|
+
"agents",
|
|
18608
|
+
"orchestration",
|
|
18609
|
+
"swarm",
|
|
18610
|
+
"multi-agent",
|
|
18611
|
+
"llm"
|
|
18612
|
+
],
|
|
18613
|
+
files: [
|
|
18614
|
+
"dist",
|
|
18615
|
+
"dist/lang/grammars",
|
|
18616
|
+
"README.md",
|
|
18617
|
+
"LICENSE"
|
|
18618
|
+
],
|
|
18619
|
+
scripts: {
|
|
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 bun --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
|
+
typecheck: "tsc --noEmit",
|
|
18623
|
+
test: "bun test",
|
|
18624
|
+
lint: "biome lint .",
|
|
18625
|
+
format: "biome format . --write",
|
|
18626
|
+
check: "biome check --write .",
|
|
18627
|
+
dev: "bun run build && opencode",
|
|
18628
|
+
prepublishOnly: "bun run build"
|
|
18629
|
+
},
|
|
18630
|
+
dependencies: {
|
|
18631
|
+
"@opencode-ai/plugin": "^1.1.53",
|
|
18632
|
+
"@opencode-ai/sdk": "^1.1.53",
|
|
18633
|
+
"@vscode/tree-sitter-wasm": "^0.3.0",
|
|
18634
|
+
"p-limit": "^7.3.0",
|
|
18635
|
+
picomatch: "^4.0.4",
|
|
18636
|
+
"proper-lockfile": "^4.1.2",
|
|
18637
|
+
"quick-lru": "^7.3.0",
|
|
18638
|
+
"web-tree-sitter": "^0.25.0",
|
|
18639
|
+
zod: "^4.1.8"
|
|
18640
|
+
},
|
|
18641
|
+
devDependencies: {
|
|
18642
|
+
"@biomejs/biome": "2.3.14",
|
|
18643
|
+
"@types/picomatch": "^4.0.3",
|
|
18644
|
+
"bun-types": "1.3.8",
|
|
18645
|
+
"js-yaml": "^4.1.1",
|
|
18646
|
+
typescript: "^5.7.3"
|
|
18647
|
+
}
|
|
18648
|
+
};
|
|
18580
18649
|
|
|
18581
18650
|
// src/commands/acknowledge-spec-drift.ts
|
|
18582
18651
|
init_utils2();
|
|
@@ -18653,71 +18722,6 @@ ${warnings.map((w) => ` - ${w}`).join(`
|
|
|
18653
18722
|
return baseMessage + warningMessage + cautionMessage;
|
|
18654
18723
|
}
|
|
18655
18724
|
|
|
18656
|
-
// src/commands/agents.ts
|
|
18657
|
-
function handleAgentsCommand(agents, guardrails) {
|
|
18658
|
-
const entries = Object.entries(agents);
|
|
18659
|
-
if (entries.length === 0) {
|
|
18660
|
-
return "No agents registered.";
|
|
18661
|
-
}
|
|
18662
|
-
const lines = [`## Registered Agents (${entries.length} total)`, ""];
|
|
18663
|
-
for (const [key, agent] of entries) {
|
|
18664
|
-
const model = agent.config.model || "default";
|
|
18665
|
-
const temp = agent.config.temperature !== undefined ? agent.config.temperature.toString() : "default";
|
|
18666
|
-
const tools = agent.config.tools || {};
|
|
18667
|
-
const isReadOnly = tools.write === false || tools.edit === false;
|
|
18668
|
-
const access = isReadOnly ? "\uD83D\uDD12 read-only" : "\u270F\uFE0F read-write";
|
|
18669
|
-
const desc = agent.description || agent.config.description || "";
|
|
18670
|
-
const hasCustomProfile = guardrails?.profiles?.[key] !== undefined;
|
|
18671
|
-
const profileIndicator = hasCustomProfile ? " | \u26A1 custom limits" : "";
|
|
18672
|
-
lines.push(`- **${key}** | model: \`${model}\` | temp: ${temp} | ${access}${profileIndicator}`);
|
|
18673
|
-
if (desc) {
|
|
18674
|
-
lines.push(` ${desc}`);
|
|
18675
|
-
}
|
|
18676
|
-
}
|
|
18677
|
-
if (guardrails?.profiles && Object.keys(guardrails.profiles).length > 0) {
|
|
18678
|
-
lines.push("", "### Guardrail Profiles", "");
|
|
18679
|
-
for (const [profileName, profile] of Object.entries(guardrails.profiles)) {
|
|
18680
|
-
const overrides = [];
|
|
18681
|
-
if (profile.max_tool_calls !== undefined) {
|
|
18682
|
-
overrides.push(`max_tool_calls=${profile.max_tool_calls}`);
|
|
18683
|
-
}
|
|
18684
|
-
if (profile.max_duration_minutes !== undefined) {
|
|
18685
|
-
overrides.push(`max_duration_minutes=${profile.max_duration_minutes}`);
|
|
18686
|
-
}
|
|
18687
|
-
if (profile.max_repetitions !== undefined) {
|
|
18688
|
-
overrides.push(`max_repetitions=${profile.max_repetitions}`);
|
|
18689
|
-
}
|
|
18690
|
-
if (profile.max_consecutive_errors !== undefined) {
|
|
18691
|
-
overrides.push(`max_consecutive_errors=${profile.max_consecutive_errors}`);
|
|
18692
|
-
}
|
|
18693
|
-
if (profile.warning_threshold !== undefined) {
|
|
18694
|
-
overrides.push(`warning_threshold=${profile.warning_threshold}`);
|
|
18695
|
-
}
|
|
18696
|
-
const overrideStr = overrides.length > 0 ? overrides.join(", ") : "no overrides";
|
|
18697
|
-
lines.push(`- **${profileName}**: ${overrideStr}`);
|
|
18698
|
-
}
|
|
18699
|
-
}
|
|
18700
|
-
return lines.join(`
|
|
18701
|
-
`);
|
|
18702
|
-
}
|
|
18703
|
-
|
|
18704
|
-
// src/commands/analyze.ts
|
|
18705
|
-
async function handleAnalyzeCommand(_directory, args) {
|
|
18706
|
-
const description = args.join(" ").trim();
|
|
18707
|
-
if (description) {
|
|
18708
|
-
return `[MODE: ANALYZE] ${description}`;
|
|
18709
|
-
}
|
|
18710
|
-
return "[MODE: ANALYZE] Please analyze the spec against the plan using MODE: ANALYZE.";
|
|
18711
|
-
}
|
|
18712
|
-
|
|
18713
|
-
// src/config/loader.ts
|
|
18714
|
-
import * as fs2 from "fs";
|
|
18715
|
-
import * as os2 from "os";
|
|
18716
|
-
import * as path4 from "path";
|
|
18717
|
-
|
|
18718
|
-
// src/config/schema.ts
|
|
18719
|
-
init_zod();
|
|
18720
|
-
|
|
18721
18725
|
// src/tools/tool-names.ts
|
|
18722
18726
|
var TOOL_NAMES = [
|
|
18723
18727
|
"diff",
|
|
@@ -19030,6 +19034,57 @@ for (const [agentName, tools] of Object.entries(AGENT_TOOL_MAP)) {
|
|
|
19030
19034
|
}
|
|
19031
19035
|
|
|
19032
19036
|
// src/config/schema.ts
|
|
19037
|
+
init_zod();
|
|
19038
|
+
var KNOWN_SWARM_PREFIXES = [
|
|
19039
|
+
"paid",
|
|
19040
|
+
"local",
|
|
19041
|
+
"cloud",
|
|
19042
|
+
"enterprise",
|
|
19043
|
+
"mega",
|
|
19044
|
+
"default",
|
|
19045
|
+
"custom",
|
|
19046
|
+
"team",
|
|
19047
|
+
"project",
|
|
19048
|
+
"swarm",
|
|
19049
|
+
"synthetic"
|
|
19050
|
+
];
|
|
19051
|
+
var SEPARATORS = ["_", "-", " "];
|
|
19052
|
+
function stripKnownSwarmPrefix(agentName) {
|
|
19053
|
+
if (!agentName)
|
|
19054
|
+
return agentName;
|
|
19055
|
+
const normalized = agentName.toLowerCase();
|
|
19056
|
+
let stripped = normalized;
|
|
19057
|
+
let previous = "";
|
|
19058
|
+
while (stripped !== previous) {
|
|
19059
|
+
previous = stripped;
|
|
19060
|
+
for (const prefix of KNOWN_SWARM_PREFIXES) {
|
|
19061
|
+
for (const sep2 of SEPARATORS) {
|
|
19062
|
+
const prefixWithSep = prefix + sep2;
|
|
19063
|
+
if (stripped.startsWith(prefixWithSep)) {
|
|
19064
|
+
stripped = stripped.slice(prefixWithSep.length);
|
|
19065
|
+
break;
|
|
19066
|
+
}
|
|
19067
|
+
}
|
|
19068
|
+
if (stripped !== previous)
|
|
19069
|
+
break;
|
|
19070
|
+
}
|
|
19071
|
+
}
|
|
19072
|
+
if (ALL_AGENT_NAMES.includes(stripped)) {
|
|
19073
|
+
return stripped;
|
|
19074
|
+
}
|
|
19075
|
+
for (const agent of ALL_AGENT_NAMES) {
|
|
19076
|
+
for (const sep2 of SEPARATORS) {
|
|
19077
|
+
const suffix = sep2 + agent;
|
|
19078
|
+
if (normalized.endsWith(suffix)) {
|
|
19079
|
+
return agent;
|
|
19080
|
+
}
|
|
19081
|
+
}
|
|
19082
|
+
if (normalized === agent) {
|
|
19083
|
+
return agent;
|
|
19084
|
+
}
|
|
19085
|
+
}
|
|
19086
|
+
return agentName;
|
|
19087
|
+
}
|
|
19033
19088
|
var AgentOverrideConfigSchema = exports_external.object({
|
|
19034
19089
|
model: exports_external.string().optional(),
|
|
19035
19090
|
variant: exports_external.string().min(1).optional(),
|
|
@@ -19634,6 +19689,7 @@ var PluginConfigSchema = exports_external.object({
|
|
|
19634
19689
|
council: CouncilConfigSchema.optional(),
|
|
19635
19690
|
parallelization: ParallelizationConfigSchema.optional(),
|
|
19636
19691
|
turbo_mode: exports_external.boolean().default(false).optional(),
|
|
19692
|
+
quiet: exports_external.boolean().default(false).optional(),
|
|
19637
19693
|
full_auto: exports_external.object({
|
|
19638
19694
|
enabled: exports_external.boolean().default(false),
|
|
19639
19695
|
critic_model: exports_external.string().optional(),
|
|
@@ -19648,7 +19704,78 @@ var PluginConfigSchema = exports_external.object({
|
|
|
19648
19704
|
})
|
|
19649
19705
|
});
|
|
19650
19706
|
|
|
19707
|
+
// src/commands/agents.ts
|
|
19708
|
+
function handleAgentsCommand(agents, guardrails) {
|
|
19709
|
+
const entries = Object.entries(agents);
|
|
19710
|
+
if (entries.length === 0) {
|
|
19711
|
+
return "No agents registered.";
|
|
19712
|
+
}
|
|
19713
|
+
const allAgentKeys = entries.map(([key]) => key);
|
|
19714
|
+
const registeredBaseNames = allAgentKeys.map((key) => stripKnownSwarmPrefix(key)).filter((stripped) => ALL_SUBAGENT_NAMES.includes(stripped));
|
|
19715
|
+
const unregistered = ALL_SUBAGENT_NAMES.filter((name) => !registeredBaseNames.includes(name));
|
|
19716
|
+
const hasUnregistered = unregistered.length > 0;
|
|
19717
|
+
const headerLabel = hasUnregistered ? `${entries.length} registered + ${unregistered.length} unregistered` : `${entries.length} total`;
|
|
19718
|
+
const lines = [`## Registered Agents (${headerLabel})`, ""];
|
|
19719
|
+
for (const [key, agent] of entries) {
|
|
19720
|
+
const model = agent.config.model || "default";
|
|
19721
|
+
const temp = agent.config.temperature !== undefined ? agent.config.temperature.toString() : "default";
|
|
19722
|
+
const tools = agent.config.tools || {};
|
|
19723
|
+
const isReadOnly = tools.write === false || tools.edit === false;
|
|
19724
|
+
const access = isReadOnly ? "\uD83D\uDD12 read-only" : "\u270F\uFE0F read-write";
|
|
19725
|
+
const desc = agent.description || agent.config.description || "";
|
|
19726
|
+
const hasCustomProfile = guardrails?.profiles?.[key] !== undefined;
|
|
19727
|
+
const profileIndicator = hasCustomProfile ? " | \u26A1 custom limits" : "";
|
|
19728
|
+
lines.push(`- **${key}** | model: \`${model}\` | temp: ${temp} | ${access}${profileIndicator}`);
|
|
19729
|
+
if (desc) {
|
|
19730
|
+
lines.push(` ${desc}`);
|
|
19731
|
+
}
|
|
19732
|
+
}
|
|
19733
|
+
if (hasUnregistered) {
|
|
19734
|
+
lines.push("", "### Unregistered Subagents");
|
|
19735
|
+
for (const name of unregistered) {
|
|
19736
|
+
lines.push(`- **${name}** (requires configuration)`);
|
|
19737
|
+
}
|
|
19738
|
+
}
|
|
19739
|
+
if (guardrails?.profiles && Object.keys(guardrails.profiles).length > 0) {
|
|
19740
|
+
lines.push("", "### Guardrail Profiles", "");
|
|
19741
|
+
for (const [profileName, profile] of Object.entries(guardrails.profiles)) {
|
|
19742
|
+
const overrides = [];
|
|
19743
|
+
if (profile.max_tool_calls !== undefined) {
|
|
19744
|
+
overrides.push(`max_tool_calls=${profile.max_tool_calls}`);
|
|
19745
|
+
}
|
|
19746
|
+
if (profile.max_duration_minutes !== undefined) {
|
|
19747
|
+
overrides.push(`max_duration_minutes=${profile.max_duration_minutes}`);
|
|
19748
|
+
}
|
|
19749
|
+
if (profile.max_repetitions !== undefined) {
|
|
19750
|
+
overrides.push(`max_repetitions=${profile.max_repetitions}`);
|
|
19751
|
+
}
|
|
19752
|
+
if (profile.max_consecutive_errors !== undefined) {
|
|
19753
|
+
overrides.push(`max_consecutive_errors=${profile.max_consecutive_errors}`);
|
|
19754
|
+
}
|
|
19755
|
+
if (profile.warning_threshold !== undefined) {
|
|
19756
|
+
overrides.push(`warning_threshold=${profile.warning_threshold}`);
|
|
19757
|
+
}
|
|
19758
|
+
const overrideStr = overrides.length > 0 ? overrides.join(", ") : "no overrides";
|
|
19759
|
+
lines.push(`- **${profileName}**: ${overrideStr}`);
|
|
19760
|
+
}
|
|
19761
|
+
}
|
|
19762
|
+
return lines.join(`
|
|
19763
|
+
`);
|
|
19764
|
+
}
|
|
19765
|
+
|
|
19766
|
+
// src/commands/analyze.ts
|
|
19767
|
+
async function handleAnalyzeCommand(_directory, args) {
|
|
19768
|
+
const description = args.join(" ").trim();
|
|
19769
|
+
if (description) {
|
|
19770
|
+
return `[MODE: ANALYZE] ${description}`;
|
|
19771
|
+
}
|
|
19772
|
+
return "[MODE: ANALYZE] Please analyze the spec against the plan using MODE: ANALYZE.";
|
|
19773
|
+
}
|
|
19774
|
+
|
|
19651
19775
|
// src/config/loader.ts
|
|
19776
|
+
import * as fs2 from "fs";
|
|
19777
|
+
import * as os2 from "os";
|
|
19778
|
+
import * as path4 from "path";
|
|
19652
19779
|
var CONFIG_FILENAME = "opencode-swarm.json";
|
|
19653
19780
|
var MAX_CONFIG_FILE_BYTES = 102400;
|
|
19654
19781
|
function getUserConfigDir() {
|
|
@@ -20341,6 +20468,9 @@ var DeltaSpecSchema = exports_external.union([
|
|
|
20341
20468
|
SwarmSpecSchema,
|
|
20342
20469
|
SpecDeltaSchema
|
|
20343
20470
|
]);
|
|
20471
|
+
// src/services/warning-buffer.ts
|
|
20472
|
+
var deferredWarnings = [];
|
|
20473
|
+
|
|
20344
20474
|
// src/agents/index.ts
|
|
20345
20475
|
var warnedAgents = new Set;
|
|
20346
20476
|
|
|
@@ -33670,8 +33800,8 @@ async function handleClarifyCommand(_directory, args) {
|
|
|
33670
33800
|
|
|
33671
33801
|
// src/commands/close.ts
|
|
33672
33802
|
import { execFileSync } from "child_process";
|
|
33673
|
-
import { promises as
|
|
33674
|
-
import
|
|
33803
|
+
import { promises as fs7 } from "fs";
|
|
33804
|
+
import path12 from "path";
|
|
33675
33805
|
init_manager2();
|
|
33676
33806
|
|
|
33677
33807
|
// src/git/branch.ts
|
|
@@ -34360,31 +34490,10 @@ async function runAutoPromotion(directory, config3) {
|
|
|
34360
34490
|
// src/commands/close.ts
|
|
34361
34491
|
init_utils2();
|
|
34362
34492
|
|
|
34363
|
-
// src/plan/checkpoint.ts
|
|
34364
|
-
init_plan_schema();
|
|
34365
|
-
init_ledger();
|
|
34366
|
-
init_manager();
|
|
34367
|
-
import * as fs7 from "fs";
|
|
34368
|
-
import * as path11 from "path";
|
|
34369
|
-
async function writeCheckpoint(directory) {
|
|
34370
|
-
try {
|
|
34371
|
-
const plan = await loadPlan(directory);
|
|
34372
|
-
if (!plan)
|
|
34373
|
-
return;
|
|
34374
|
-
const jsonPath = path11.join(directory, "SWARM_PLAN.json");
|
|
34375
|
-
const mdPath = path11.join(directory, "SWARM_PLAN.md");
|
|
34376
|
-
fs7.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
|
|
34377
|
-
const md = derivePlanMarkdown(plan);
|
|
34378
|
-
fs7.writeFileSync(mdPath, md, "utf8");
|
|
34379
|
-
} catch (error93) {
|
|
34380
|
-
console.warn(`[checkpoint] Failed to write SWARM_PLAN checkpoint: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
34381
|
-
}
|
|
34382
|
-
}
|
|
34383
|
-
|
|
34384
34493
|
// src/session/snapshot-writer.ts
|
|
34385
34494
|
init_utils2();
|
|
34386
34495
|
import { mkdirSync as mkdirSync7, renameSync as renameSync5 } from "fs";
|
|
34387
|
-
import * as
|
|
34496
|
+
import * as path11 from "path";
|
|
34388
34497
|
init_utils();
|
|
34389
34498
|
var _writeInFlight = Promise.resolve();
|
|
34390
34499
|
function serializeAgentSession(s) {
|
|
@@ -34475,7 +34584,7 @@ async function writeSnapshot(directory, state) {
|
|
|
34475
34584
|
}
|
|
34476
34585
|
const content = JSON.stringify(snapshot, null, 2);
|
|
34477
34586
|
const resolvedPath = validateSwarmPath(directory, "session/state.json");
|
|
34478
|
-
const dir =
|
|
34587
|
+
const dir = path11.dirname(resolvedPath);
|
|
34479
34588
|
mkdirSync7(dir, { recursive: true });
|
|
34480
34589
|
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
34481
34590
|
await Bun.write(tempPath, content);
|
|
@@ -34868,21 +34977,21 @@ var ACTIVE_STATE_TO_CLEAN = [
|
|
|
34868
34977
|
];
|
|
34869
34978
|
async function handleCloseCommand(directory, args) {
|
|
34870
34979
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
34871
|
-
const swarmDir =
|
|
34980
|
+
const swarmDir = path12.join(directory, ".swarm");
|
|
34872
34981
|
let planExists = false;
|
|
34873
34982
|
let planData = {
|
|
34874
|
-
title:
|
|
34983
|
+
title: path12.basename(directory) || "Ad-hoc session",
|
|
34875
34984
|
phases: []
|
|
34876
34985
|
};
|
|
34877
34986
|
try {
|
|
34878
|
-
const content = await
|
|
34987
|
+
const content = await fs7.readFile(planPath, "utf-8");
|
|
34879
34988
|
planData = JSON.parse(content);
|
|
34880
34989
|
planExists = true;
|
|
34881
34990
|
} catch (error93) {
|
|
34882
34991
|
if (error93?.code !== "ENOENT") {
|
|
34883
34992
|
return `\u274C Failed to read plan.json: ${error93 instanceof Error ? error93.message : String(error93)}`;
|
|
34884
34993
|
}
|
|
34885
|
-
const swarmDirExists = await
|
|
34994
|
+
const swarmDirExists = await fs7.access(swarmDir).then(() => true).catch(() => false);
|
|
34886
34995
|
if (!swarmDirExists) {
|
|
34887
34996
|
return `\u274C No .swarm/ directory found in ${directory}. Run /swarm close from the project root, or run /swarm plan first.`;
|
|
34888
34997
|
}
|
|
@@ -34976,10 +35085,10 @@ async function handleCloseCommand(directory, args) {
|
|
|
34976
35085
|
warnings.push(`Session retrospective write threw: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
|
|
34977
35086
|
}
|
|
34978
35087
|
}
|
|
34979
|
-
const lessonsFilePath =
|
|
35088
|
+
const lessonsFilePath = path12.join(swarmDir, "close-lessons.md");
|
|
34980
35089
|
let explicitLessons = [];
|
|
34981
35090
|
try {
|
|
34982
|
-
const lessonsText = await
|
|
35091
|
+
const lessonsText = await fs7.readFile(lessonsFilePath, "utf-8");
|
|
34983
35092
|
explicitLessons = lessonsText.split(`
|
|
34984
35093
|
`).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
34985
35094
|
} catch {}
|
|
@@ -34993,7 +35102,7 @@ async function handleCloseCommand(directory, args) {
|
|
|
34993
35102
|
console.warn("[close-command] curateAndStoreSwarm error:", error93);
|
|
34994
35103
|
}
|
|
34995
35104
|
if (curationSucceeded && explicitLessons.length > 0) {
|
|
34996
|
-
await
|
|
35105
|
+
await fs7.unlink(lessonsFilePath).catch(() => {});
|
|
34997
35106
|
}
|
|
34998
35107
|
if (planExists && !planAlreadyDone) {
|
|
34999
35108
|
for (const phase of phases) {
|
|
@@ -35013,7 +35122,7 @@ async function handleCloseCommand(directory, args) {
|
|
|
35013
35122
|
}
|
|
35014
35123
|
}
|
|
35015
35124
|
try {
|
|
35016
|
-
await
|
|
35125
|
+
await fs7.writeFile(planPath, JSON.stringify(planData, null, 2), "utf-8");
|
|
35017
35126
|
} catch (error93) {
|
|
35018
35127
|
const msg = error93 instanceof Error ? error93.message : String(error93);
|
|
35019
35128
|
warnings.push(`Failed to persist terminal plan.json state: ${msg}`);
|
|
@@ -35022,53 +35131,53 @@ async function handleCloseCommand(directory, args) {
|
|
|
35022
35131
|
}
|
|
35023
35132
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
35024
35133
|
const suffix = Math.random().toString(36).slice(2, 8);
|
|
35025
|
-
const archiveDir =
|
|
35134
|
+
const archiveDir = path12.join(swarmDir, "archive", `swarm-${timestamp}-${suffix}`);
|
|
35026
35135
|
let archiveResult = "";
|
|
35027
35136
|
let archivedFileCount = 0;
|
|
35028
35137
|
const archivedActiveStateFiles = new Set;
|
|
35029
35138
|
try {
|
|
35030
|
-
await
|
|
35139
|
+
await fs7.mkdir(archiveDir, { recursive: true });
|
|
35031
35140
|
for (const artifact of ARCHIVE_ARTIFACTS) {
|
|
35032
|
-
const srcPath =
|
|
35033
|
-
const destPath =
|
|
35141
|
+
const srcPath = path12.join(swarmDir, artifact);
|
|
35142
|
+
const destPath = path12.join(archiveDir, artifact);
|
|
35034
35143
|
try {
|
|
35035
|
-
await
|
|
35144
|
+
await fs7.copyFile(srcPath, destPath);
|
|
35036
35145
|
archivedFileCount++;
|
|
35037
35146
|
if (ACTIVE_STATE_TO_CLEAN.includes(artifact)) {
|
|
35038
35147
|
archivedActiveStateFiles.add(artifact);
|
|
35039
35148
|
}
|
|
35040
35149
|
} catch {}
|
|
35041
35150
|
}
|
|
35042
|
-
const evidenceDir =
|
|
35043
|
-
const archiveEvidenceDir =
|
|
35151
|
+
const evidenceDir = path12.join(swarmDir, "evidence");
|
|
35152
|
+
const archiveEvidenceDir = path12.join(archiveDir, "evidence");
|
|
35044
35153
|
try {
|
|
35045
|
-
const evidenceEntries = await
|
|
35154
|
+
const evidenceEntries = await fs7.readdir(evidenceDir);
|
|
35046
35155
|
if (evidenceEntries.length > 0) {
|
|
35047
|
-
await
|
|
35156
|
+
await fs7.mkdir(archiveEvidenceDir, { recursive: true });
|
|
35048
35157
|
for (const entry of evidenceEntries) {
|
|
35049
|
-
const srcEntry =
|
|
35050
|
-
const destEntry =
|
|
35158
|
+
const srcEntry = path12.join(evidenceDir, entry);
|
|
35159
|
+
const destEntry = path12.join(archiveEvidenceDir, entry);
|
|
35051
35160
|
try {
|
|
35052
|
-
const stat = await
|
|
35161
|
+
const stat = await fs7.stat(srcEntry);
|
|
35053
35162
|
if (stat.isDirectory()) {
|
|
35054
|
-
await
|
|
35055
|
-
const subEntries = await
|
|
35163
|
+
await fs7.mkdir(destEntry, { recursive: true });
|
|
35164
|
+
const subEntries = await fs7.readdir(srcEntry);
|
|
35056
35165
|
for (const sub of subEntries) {
|
|
35057
|
-
await
|
|
35166
|
+
await fs7.copyFile(path12.join(srcEntry, sub), path12.join(destEntry, sub)).catch(() => {});
|
|
35058
35167
|
}
|
|
35059
35168
|
} else {
|
|
35060
|
-
await
|
|
35169
|
+
await fs7.copyFile(srcEntry, destEntry);
|
|
35061
35170
|
}
|
|
35062
35171
|
archivedFileCount++;
|
|
35063
35172
|
} catch {}
|
|
35064
35173
|
}
|
|
35065
35174
|
}
|
|
35066
35175
|
} catch {}
|
|
35067
|
-
const sessionStatePath =
|
|
35176
|
+
const sessionStatePath = path12.join(swarmDir, "session", "state.json");
|
|
35068
35177
|
try {
|
|
35069
|
-
const archiveSessionDir =
|
|
35070
|
-
await
|
|
35071
|
-
await
|
|
35178
|
+
const archiveSessionDir = path12.join(archiveDir, "session");
|
|
35179
|
+
await fs7.mkdir(archiveSessionDir, { recursive: true });
|
|
35180
|
+
await fs7.copyFile(sessionStatePath, path12.join(archiveSessionDir, "state.json"));
|
|
35072
35181
|
archivedFileCount++;
|
|
35073
35182
|
} catch {}
|
|
35074
35183
|
archiveResult = `Archived ${archivedFileCount} artifact(s) to .swarm/archive/swarm-${timestamp}/`;
|
|
@@ -35091,9 +35200,9 @@ async function handleCloseCommand(directory, args) {
|
|
|
35091
35200
|
warnings.push(`Preserved ${artifact} because it was not successfully archived.`);
|
|
35092
35201
|
continue;
|
|
35093
35202
|
}
|
|
35094
|
-
const filePath =
|
|
35203
|
+
const filePath = path12.join(swarmDir, artifact);
|
|
35095
35204
|
try {
|
|
35096
|
-
await
|
|
35205
|
+
await fs7.unlink(filePath);
|
|
35097
35206
|
cleanedFiles.push(artifact);
|
|
35098
35207
|
} catch {}
|
|
35099
35208
|
}
|
|
@@ -35101,23 +35210,42 @@ async function handleCloseCommand(directory, args) {
|
|
|
35101
35210
|
warnings.push("Skipped active-state cleanup because no active-state files were archived. Files preserved to prevent data loss.");
|
|
35102
35211
|
}
|
|
35103
35212
|
try {
|
|
35104
|
-
const swarmFiles = await
|
|
35213
|
+
const swarmFiles = await fs7.readdir(swarmDir);
|
|
35105
35214
|
const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
|
|
35106
35215
|
for (const backup of configBackups) {
|
|
35107
35216
|
try {
|
|
35108
|
-
await
|
|
35217
|
+
await fs7.unlink(path12.join(swarmDir, backup));
|
|
35109
35218
|
configBackupsRemoved++;
|
|
35110
35219
|
} catch {}
|
|
35111
35220
|
}
|
|
35112
35221
|
const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
|
|
35113
35222
|
for (const sibling of ledgerSiblings) {
|
|
35114
35223
|
try {
|
|
35115
|
-
await
|
|
35224
|
+
await fs7.unlink(path12.join(swarmDir, sibling));
|
|
35116
35225
|
} catch {}
|
|
35117
35226
|
}
|
|
35118
35227
|
} catch {}
|
|
35228
|
+
let swarmPlanFilesRemoved = 0;
|
|
35229
|
+
const swarmPlanJsonPath = path12.join(directory, "SWARM_PLAN.json");
|
|
35230
|
+
const swarmPlanMdPath = path12.join(directory, "SWARM_PLAN.md");
|
|
35231
|
+
try {
|
|
35232
|
+
await fs7.unlink(swarmPlanJsonPath);
|
|
35233
|
+
swarmPlanFilesRemoved++;
|
|
35234
|
+
} catch (err) {
|
|
35235
|
+
if (err?.code !== "ENOENT") {
|
|
35236
|
+
warnings.push(`Failed to remove SWARM_PLAN.json: ${err instanceof Error ? err.message : String(err)}`);
|
|
35237
|
+
}
|
|
35238
|
+
}
|
|
35239
|
+
try {
|
|
35240
|
+
await fs7.unlink(swarmPlanMdPath);
|
|
35241
|
+
swarmPlanFilesRemoved++;
|
|
35242
|
+
} catch (err) {
|
|
35243
|
+
if (err?.code !== "ENOENT") {
|
|
35244
|
+
warnings.push(`Failed to remove SWARM_PLAN.md: ${err instanceof Error ? err.message : String(err)}`);
|
|
35245
|
+
}
|
|
35246
|
+
}
|
|
35119
35247
|
clearAllScopes(directory);
|
|
35120
|
-
const contextPath =
|
|
35248
|
+
const contextPath = path12.join(swarmDir, "context.md");
|
|
35121
35249
|
const contextContent = [
|
|
35122
35250
|
"# Context",
|
|
35123
35251
|
"",
|
|
@@ -35130,7 +35258,7 @@ async function handleCloseCommand(directory, args) {
|
|
|
35130
35258
|
].join(`
|
|
35131
35259
|
`);
|
|
35132
35260
|
try {
|
|
35133
|
-
await
|
|
35261
|
+
await fs7.writeFile(contextPath, contextContent, "utf-8");
|
|
35134
35262
|
} catch (error93) {
|
|
35135
35263
|
const msg = error93 instanceof Error ? error93.message : String(error93);
|
|
35136
35264
|
warnings.push(`Failed to reset context.md: ${msg}`);
|
|
@@ -35232,6 +35360,9 @@ async function handleCloseCommand(directory, args) {
|
|
|
35232
35360
|
] : [],
|
|
35233
35361
|
"- Reset context.md for next session",
|
|
35234
35362
|
...configBackupsRemoved > 0 ? [`- Removed ${configBackupsRemoved} stale config backup file(s)`] : [],
|
|
35363
|
+
...swarmPlanFilesRemoved > 0 ? [
|
|
35364
|
+
`- Removed ${swarmPlanFilesRemoved} root-level SWARM_PLAN checkpoint artifact(s)`
|
|
35365
|
+
] : [],
|
|
35235
35366
|
...prunedBranches.length > 0 ? [
|
|
35236
35367
|
`- Pruned ${prunedBranches.length} stale local git branch(es): ${prunedBranches.join(", ")}`
|
|
35237
35368
|
] : [],
|
|
@@ -35261,7 +35392,7 @@ async function handleCloseCommand(directory, args) {
|
|
|
35261
35392
|
].join(`
|
|
35262
35393
|
`);
|
|
35263
35394
|
try {
|
|
35264
|
-
await
|
|
35395
|
+
await fs7.writeFile(closeSummaryPath, summaryContent, "utf-8");
|
|
35265
35396
|
} catch (error93) {
|
|
35266
35397
|
const msg = error93 instanceof Error ? error93.message : String(error93);
|
|
35267
35398
|
warnings.push(`Failed to write close-summary.md: ${msg}`);
|
|
@@ -35274,7 +35405,6 @@ async function handleCloseCommand(directory, args) {
|
|
|
35274
35405
|
warnings.push(`flushPendingSnapshot failed: ${msg}`);
|
|
35275
35406
|
console.warn("[close-command] flushPendingSnapshot error:", error93);
|
|
35276
35407
|
}
|
|
35277
|
-
await writeCheckpoint(directory).catch(() => {});
|
|
35278
35408
|
const preservedClient = swarmState.opencodeClient;
|
|
35279
35409
|
const preservedFullAutoFlag = swarmState.fullAutoEnabledInConfig;
|
|
35280
35410
|
const preservedCuratorInitNames = swarmState.curatorInitAgentNames;
|
|
@@ -35318,14 +35448,14 @@ ${otherWarnings.map((w) => `- ${w}`).join(`
|
|
|
35318
35448
|
|
|
35319
35449
|
// src/commands/config.ts
|
|
35320
35450
|
import * as os4 from "os";
|
|
35321
|
-
import * as
|
|
35451
|
+
import * as path13 from "path";
|
|
35322
35452
|
function getUserConfigDir2() {
|
|
35323
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
35453
|
+
return process.env.XDG_CONFIG_HOME || path13.join(os4.homedir(), ".config");
|
|
35324
35454
|
}
|
|
35325
35455
|
async function handleConfigCommand(directory, _args) {
|
|
35326
35456
|
const config3 = loadPluginConfig(directory);
|
|
35327
|
-
const userConfigPath =
|
|
35328
|
-
const projectConfigPath =
|
|
35457
|
+
const userConfigPath = path13.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
|
|
35458
|
+
const projectConfigPath = path13.join(directory, ".opencode", "opencode-swarm.json");
|
|
35329
35459
|
const lines = [
|
|
35330
35460
|
"## Swarm Configuration",
|
|
35331
35461
|
"",
|
|
@@ -35411,7 +35541,7 @@ async function handleCouncilCommand(_directory, args) {
|
|
|
35411
35541
|
}
|
|
35412
35542
|
|
|
35413
35543
|
// src/hooks/hive-promoter.ts
|
|
35414
|
-
import
|
|
35544
|
+
import path14 from "path";
|
|
35415
35545
|
|
|
35416
35546
|
// src/background/event-bus.ts
|
|
35417
35547
|
init_utils();
|
|
@@ -35666,7 +35796,7 @@ async function promoteToHive(directory, lesson, category) {
|
|
|
35666
35796
|
schema_version: 1,
|
|
35667
35797
|
created_at: new Date().toISOString(),
|
|
35668
35798
|
updated_at: new Date().toISOString(),
|
|
35669
|
-
source_project:
|
|
35799
|
+
source_project: path14.basename(directory) || "unknown",
|
|
35670
35800
|
encounter_score: 1
|
|
35671
35801
|
};
|
|
35672
35802
|
await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
|
|
@@ -35744,14 +35874,14 @@ function formatCurationSummary(summary) {
|
|
|
35744
35874
|
}
|
|
35745
35875
|
|
|
35746
35876
|
// src/commands/dark-matter.ts
|
|
35747
|
-
import
|
|
35877
|
+
import path16 from "path";
|
|
35748
35878
|
|
|
35749
35879
|
// src/tools/co-change-analyzer.ts
|
|
35750
35880
|
init_zod();
|
|
35751
35881
|
import * as child_process3 from "child_process";
|
|
35752
35882
|
import { randomUUID } from "crypto";
|
|
35753
35883
|
import { readdir, readFile as readFile3, stat } from "fs/promises";
|
|
35754
|
-
import * as
|
|
35884
|
+
import * as path15 from "path";
|
|
35755
35885
|
import { promisify } from "util";
|
|
35756
35886
|
function getExecFileAsync() {
|
|
35757
35887
|
return promisify(child_process3.execFile);
|
|
@@ -35853,7 +35983,7 @@ async function scanSourceFiles(dir) {
|
|
|
35853
35983
|
try {
|
|
35854
35984
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
35855
35985
|
for (const entry of entries) {
|
|
35856
|
-
const fullPath =
|
|
35986
|
+
const fullPath = path15.join(dir, entry.name);
|
|
35857
35987
|
if (entry.isDirectory()) {
|
|
35858
35988
|
if (skipDirs.has(entry.name)) {
|
|
35859
35989
|
continue;
|
|
@@ -35861,7 +35991,7 @@ async function scanSourceFiles(dir) {
|
|
|
35861
35991
|
const subFiles = await scanSourceFiles(fullPath);
|
|
35862
35992
|
results.push(...subFiles);
|
|
35863
35993
|
} else if (entry.isFile()) {
|
|
35864
|
-
const ext =
|
|
35994
|
+
const ext = path15.extname(entry.name);
|
|
35865
35995
|
if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
|
|
35866
35996
|
results.push(fullPath);
|
|
35867
35997
|
}
|
|
@@ -35883,8 +36013,8 @@ async function getStaticEdges(directory) {
|
|
|
35883
36013
|
continue;
|
|
35884
36014
|
}
|
|
35885
36015
|
try {
|
|
35886
|
-
const sourceDir =
|
|
35887
|
-
const resolvedPath =
|
|
36016
|
+
const sourceDir = path15.dirname(sourceFile);
|
|
36017
|
+
const resolvedPath = path15.resolve(sourceDir, importPath);
|
|
35888
36018
|
const extensions = [
|
|
35889
36019
|
"",
|
|
35890
36020
|
".ts",
|
|
@@ -35909,8 +36039,8 @@ async function getStaticEdges(directory) {
|
|
|
35909
36039
|
if (!targetFile) {
|
|
35910
36040
|
continue;
|
|
35911
36041
|
}
|
|
35912
|
-
const relSource =
|
|
35913
|
-
const relTarget =
|
|
36042
|
+
const relSource = path15.relative(directory, sourceFile).replace(/\\/g, "/");
|
|
36043
|
+
const relTarget = path15.relative(directory, targetFile).replace(/\\/g, "/");
|
|
35914
36044
|
const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
|
|
35915
36045
|
edges.add(key);
|
|
35916
36046
|
} catch {}
|
|
@@ -35922,7 +36052,7 @@ async function getStaticEdges(directory) {
|
|
|
35922
36052
|
function isTestImplementationPair(fileA, fileB) {
|
|
35923
36053
|
const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
|
|
35924
36054
|
const getBaseName = (filePath) => {
|
|
35925
|
-
const base =
|
|
36055
|
+
const base = path15.basename(filePath);
|
|
35926
36056
|
for (const pattern of testPatterns) {
|
|
35927
36057
|
if (base.endsWith(pattern)) {
|
|
35928
36058
|
return base.slice(0, -pattern.length);
|
|
@@ -35932,16 +36062,16 @@ function isTestImplementationPair(fileA, fileB) {
|
|
|
35932
36062
|
};
|
|
35933
36063
|
const baseA = getBaseName(fileA);
|
|
35934
36064
|
const baseB = getBaseName(fileB);
|
|
35935
|
-
return baseA === baseB && baseA !==
|
|
36065
|
+
return baseA === baseB && baseA !== path15.basename(fileA) && baseA !== path15.basename(fileB);
|
|
35936
36066
|
}
|
|
35937
36067
|
function hasSharedPrefix(fileA, fileB) {
|
|
35938
|
-
const dirA =
|
|
35939
|
-
const dirB =
|
|
36068
|
+
const dirA = path15.dirname(fileA);
|
|
36069
|
+
const dirB = path15.dirname(fileB);
|
|
35940
36070
|
if (dirA !== dirB) {
|
|
35941
36071
|
return false;
|
|
35942
36072
|
}
|
|
35943
|
-
const baseA =
|
|
35944
|
-
const baseB =
|
|
36073
|
+
const baseA = path15.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
36074
|
+
const baseB = path15.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
35945
36075
|
if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
|
|
35946
36076
|
return true;
|
|
35947
36077
|
}
|
|
@@ -35995,8 +36125,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
|
|
|
35995
36125
|
const entries = [];
|
|
35996
36126
|
const now = new Date().toISOString();
|
|
35997
36127
|
for (const pair of pairs.slice(0, 10)) {
|
|
35998
|
-
const baseA =
|
|
35999
|
-
const baseB =
|
|
36128
|
+
const baseA = path15.basename(pair.fileA);
|
|
36129
|
+
const baseB = path15.basename(pair.fileB);
|
|
36000
36130
|
let lesson = `Files ${pair.fileA} and ${pair.fileB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
|
|
36001
36131
|
if (lesson.length > 280) {
|
|
36002
36132
|
lesson = `Files ${baseA} and ${baseB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
|
|
@@ -36106,7 +36236,7 @@ async function handleDarkMatterCommand(directory, args) {
|
|
|
36106
36236
|
const output = formatDarkMatterOutput(pairs);
|
|
36107
36237
|
if (pairs.length > 0) {
|
|
36108
36238
|
try {
|
|
36109
|
-
const projectName =
|
|
36239
|
+
const projectName = path16.basename(path16.resolve(directory));
|
|
36110
36240
|
const entries = darkMatterToKnowledgeEntries(pairs, projectName);
|
|
36111
36241
|
if (entries.length > 0) {
|
|
36112
36242
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
@@ -36127,12 +36257,13 @@ async function handleDarkMatterCommand(directory, args) {
|
|
|
36127
36257
|
|
|
36128
36258
|
// src/services/diagnose-service.ts
|
|
36129
36259
|
import * as child_process4 from "child_process";
|
|
36130
|
-
import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as
|
|
36131
|
-
import
|
|
36260
|
+
import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync5, statSync as statSync5 } from "fs";
|
|
36261
|
+
import path17 from "path";
|
|
36132
36262
|
import { fileURLToPath } from "url";
|
|
36133
36263
|
init_manager2();
|
|
36134
36264
|
init_utils2();
|
|
36135
36265
|
init_manager();
|
|
36266
|
+
var { version: version3 } = package_default;
|
|
36136
36267
|
function validateTaskDag(plan) {
|
|
36137
36268
|
const allTaskIds = new Set;
|
|
36138
36269
|
for (const phase of plan.phases) {
|
|
@@ -36428,7 +36559,7 @@ async function checkSpecStaleness(directory, plan) {
|
|
|
36428
36559
|
};
|
|
36429
36560
|
}
|
|
36430
36561
|
async function checkConfigParseability(directory) {
|
|
36431
|
-
const configPath =
|
|
36562
|
+
const configPath = path17.join(directory, ".opencode/opencode-swarm.json");
|
|
36432
36563
|
if (!existsSync8(configPath)) {
|
|
36433
36564
|
return {
|
|
36434
36565
|
name: "Config Parseability",
|
|
@@ -36437,7 +36568,7 @@ async function checkConfigParseability(directory) {
|
|
|
36437
36568
|
};
|
|
36438
36569
|
}
|
|
36439
36570
|
try {
|
|
36440
|
-
const content =
|
|
36571
|
+
const content = readFileSync5(configPath, "utf-8");
|
|
36441
36572
|
JSON.parse(content);
|
|
36442
36573
|
return {
|
|
36443
36574
|
name: "Config Parseability",
|
|
@@ -36457,7 +36588,7 @@ function resolveGrammarDir(thisDir) {
|
|
|
36457
36588
|
const normalized = thisDir.replace(/\\/g, "/");
|
|
36458
36589
|
const isSource = normalized.endsWith("/src/services");
|
|
36459
36590
|
const isCliBundle = normalized.endsWith("/cli");
|
|
36460
|
-
return isSource || isCliBundle ?
|
|
36591
|
+
return isSource || isCliBundle ? path17.join(thisDir, "..", "lang", "grammars") : path17.join(thisDir, "lang", "grammars");
|
|
36461
36592
|
}
|
|
36462
36593
|
async function checkGrammarWasmFiles() {
|
|
36463
36594
|
const grammarFiles = [
|
|
@@ -36481,14 +36612,14 @@ async function checkGrammarWasmFiles() {
|
|
|
36481
36612
|
"tree-sitter-ini.wasm",
|
|
36482
36613
|
"tree-sitter-regex.wasm"
|
|
36483
36614
|
];
|
|
36484
|
-
const thisDir =
|
|
36615
|
+
const thisDir = path17.dirname(fileURLToPath(import.meta.url));
|
|
36485
36616
|
const grammarDir = resolveGrammarDir(thisDir);
|
|
36486
36617
|
const missing = [];
|
|
36487
|
-
if (!existsSync8(
|
|
36618
|
+
if (!existsSync8(path17.join(grammarDir, "tree-sitter.wasm"))) {
|
|
36488
36619
|
missing.push("tree-sitter.wasm (core runtime)");
|
|
36489
36620
|
}
|
|
36490
36621
|
for (const file3 of grammarFiles) {
|
|
36491
|
-
if (!existsSync8(
|
|
36622
|
+
if (!existsSync8(path17.join(grammarDir, file3))) {
|
|
36492
36623
|
missing.push(file3);
|
|
36493
36624
|
}
|
|
36494
36625
|
}
|
|
@@ -36506,7 +36637,7 @@ async function checkGrammarWasmFiles() {
|
|
|
36506
36637
|
};
|
|
36507
36638
|
}
|
|
36508
36639
|
async function checkCheckpointManifest(directory) {
|
|
36509
|
-
const manifestPath =
|
|
36640
|
+
const manifestPath = path17.join(directory, ".swarm/checkpoints.json");
|
|
36510
36641
|
if (!existsSync8(manifestPath)) {
|
|
36511
36642
|
return {
|
|
36512
36643
|
name: "Checkpoint Manifest",
|
|
@@ -36515,7 +36646,7 @@ async function checkCheckpointManifest(directory) {
|
|
|
36515
36646
|
};
|
|
36516
36647
|
}
|
|
36517
36648
|
try {
|
|
36518
|
-
const content =
|
|
36649
|
+
const content = readFileSync5(manifestPath, "utf-8");
|
|
36519
36650
|
const parsed = JSON.parse(content);
|
|
36520
36651
|
if (!parsed.checkpoints || !Array.isArray(parsed.checkpoints)) {
|
|
36521
36652
|
return {
|
|
@@ -36558,7 +36689,7 @@ async function checkCheckpointManifest(directory) {
|
|
|
36558
36689
|
}
|
|
36559
36690
|
}
|
|
36560
36691
|
async function checkEventStreamIntegrity(directory) {
|
|
36561
|
-
const eventsPath =
|
|
36692
|
+
const eventsPath = path17.join(directory, ".swarm/events.jsonl");
|
|
36562
36693
|
if (!existsSync8(eventsPath)) {
|
|
36563
36694
|
return {
|
|
36564
36695
|
name: "Event Stream",
|
|
@@ -36567,7 +36698,7 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
36567
36698
|
};
|
|
36568
36699
|
}
|
|
36569
36700
|
try {
|
|
36570
|
-
const content =
|
|
36701
|
+
const content = readFileSync5(eventsPath, "utf-8");
|
|
36571
36702
|
const lines = content.split(`
|
|
36572
36703
|
`).filter((line) => line.trim() !== "");
|
|
36573
36704
|
let malformedCount = 0;
|
|
@@ -36599,7 +36730,7 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
36599
36730
|
}
|
|
36600
36731
|
}
|
|
36601
36732
|
async function checkSteeringDirectives(directory) {
|
|
36602
|
-
const eventsPath =
|
|
36733
|
+
const eventsPath = path17.join(directory, ".swarm/events.jsonl");
|
|
36603
36734
|
if (!existsSync8(eventsPath)) {
|
|
36604
36735
|
return {
|
|
36605
36736
|
name: "Steering Directives",
|
|
@@ -36608,7 +36739,7 @@ async function checkSteeringDirectives(directory) {
|
|
|
36608
36739
|
};
|
|
36609
36740
|
}
|
|
36610
36741
|
try {
|
|
36611
|
-
const content =
|
|
36742
|
+
const content = readFileSync5(eventsPath, "utf-8");
|
|
36612
36743
|
const lines = content.split(`
|
|
36613
36744
|
`).filter((line) => line.trim() !== "");
|
|
36614
36745
|
const directivesIssued = [];
|
|
@@ -36655,7 +36786,7 @@ async function checkCurator(directory) {
|
|
|
36655
36786
|
detail: "Disabled (enable via curator.enabled)"
|
|
36656
36787
|
};
|
|
36657
36788
|
}
|
|
36658
|
-
const summaryPath =
|
|
36789
|
+
const summaryPath = path17.join(directory, ".swarm/curator-summary.json");
|
|
36659
36790
|
if (!existsSync8(summaryPath)) {
|
|
36660
36791
|
return {
|
|
36661
36792
|
name: "Curator",
|
|
@@ -36664,7 +36795,7 @@ async function checkCurator(directory) {
|
|
|
36664
36795
|
};
|
|
36665
36796
|
}
|
|
36666
36797
|
try {
|
|
36667
|
-
const content =
|
|
36798
|
+
const content = readFileSync5(summaryPath, "utf-8");
|
|
36668
36799
|
const parsed = JSON.parse(content);
|
|
36669
36800
|
if (typeof parsed.schema_version !== "number" || parsed.schema_version !== 1) {
|
|
36670
36801
|
return {
|
|
@@ -36699,6 +36830,11 @@ async function checkCurator(directory) {
|
|
|
36699
36830
|
}
|
|
36700
36831
|
async function getDiagnoseData(directory) {
|
|
36701
36832
|
const checks5 = [];
|
|
36833
|
+
checks5.push({
|
|
36834
|
+
name: "Version",
|
|
36835
|
+
status: "\u2705",
|
|
36836
|
+
detail: version3
|
|
36837
|
+
});
|
|
36702
36838
|
const plan = await loadPlanJsonOnly(directory);
|
|
36703
36839
|
if (plan) {
|
|
36704
36840
|
checks5.push({
|
|
@@ -36803,7 +36939,7 @@ async function getDiagnoseData(directory) {
|
|
|
36803
36939
|
checks5.push(await checkSteeringDirectives(directory));
|
|
36804
36940
|
checks5.push(await checkCurator(directory));
|
|
36805
36941
|
try {
|
|
36806
|
-
const evidenceDir =
|
|
36942
|
+
const evidenceDir = path17.join(directory, ".swarm", "evidence");
|
|
36807
36943
|
const snapshotFiles = existsSync8(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
|
|
36808
36944
|
if (snapshotFiles.length > 0) {
|
|
36809
36945
|
const latest = snapshotFiles.sort().pop();
|
|
@@ -36826,6 +36962,13 @@ async function getDiagnoseData(directory) {
|
|
|
36826
36962
|
detail: "No snapshots yet (snapshots written on next session start)"
|
|
36827
36963
|
});
|
|
36828
36964
|
}
|
|
36965
|
+
if (deferredWarnings.length > 0) {
|
|
36966
|
+
checks5.push({
|
|
36967
|
+
name: "Deferred Warnings",
|
|
36968
|
+
status: "\u26A0\uFE0F",
|
|
36969
|
+
detail: `${deferredWarnings.length} warning(s) deferred from init (run with verbose logs for details)`
|
|
36970
|
+
});
|
|
36971
|
+
}
|
|
36829
36972
|
const passCount = checks5.filter((c) => c.status === "\u2705").length;
|
|
36830
36973
|
const totalCount = checks5.length;
|
|
36831
36974
|
const allPassed = passCount === totalCount;
|
|
@@ -36844,6 +36987,14 @@ function formatDiagnoseMarkdown(diagnose) {
|
|
|
36844
36987
|
"",
|
|
36845
36988
|
`**Result**: ${diagnose.allPassed ? "\u2705 All checks passed" : `\u26A0\uFE0F ${diagnose.passCount}/${diagnose.totalCount} checks passed`}`
|
|
36846
36989
|
];
|
|
36990
|
+
if (deferredWarnings.length > 0) {
|
|
36991
|
+
lines.push("");
|
|
36992
|
+
lines.push("## Deferred Warnings");
|
|
36993
|
+
lines.push("");
|
|
36994
|
+
for (const warning of deferredWarnings) {
|
|
36995
|
+
lines.push(`- ${warning}`);
|
|
36996
|
+
}
|
|
36997
|
+
}
|
|
36847
36998
|
return lines.join(`
|
|
36848
36999
|
`);
|
|
36849
37000
|
}
|
|
@@ -36855,16 +37006,16 @@ async function handleDiagnoseCommand(directory, _args) {
|
|
|
36855
37006
|
init_config_doctor();
|
|
36856
37007
|
|
|
36857
37008
|
// src/services/tool-doctor.ts
|
|
36858
|
-
import * as fs11 from "fs";
|
|
36859
|
-
import * as path21 from "path";
|
|
36860
|
-
|
|
36861
|
-
// src/build/discovery.ts
|
|
36862
37009
|
import * as fs10 from "fs";
|
|
36863
37010
|
import * as path20 from "path";
|
|
36864
37011
|
|
|
37012
|
+
// src/build/discovery.ts
|
|
37013
|
+
import * as fs9 from "fs";
|
|
37014
|
+
import * as path19 from "path";
|
|
37015
|
+
|
|
36865
37016
|
// src/lang/detector.ts
|
|
36866
37017
|
import { access as access2, readdir as readdir2 } from "fs/promises";
|
|
36867
|
-
import { extname as extname2, join as
|
|
37018
|
+
import { extname as extname2, join as join15 } from "path";
|
|
36868
37019
|
|
|
36869
37020
|
// src/lang/profiles.ts
|
|
36870
37021
|
class LanguageRegistry {
|
|
@@ -37844,7 +37995,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
37844
37995
|
if (detectFile.includes("*") || detectFile.includes("?"))
|
|
37845
37996
|
continue;
|
|
37846
37997
|
try {
|
|
37847
|
-
await access2(
|
|
37998
|
+
await access2(join15(dir, detectFile));
|
|
37848
37999
|
detected.add(profile.id);
|
|
37849
38000
|
break;
|
|
37850
38001
|
} catch {}
|
|
@@ -37865,7 +38016,7 @@ async function detectProjectLanguages(projectDir) {
|
|
|
37865
38016
|
const topEntries = await readdir2(projectDir, { withFileTypes: true });
|
|
37866
38017
|
for (const entry of topEntries) {
|
|
37867
38018
|
if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
|
|
37868
|
-
await scanDir(
|
|
38019
|
+
await scanDir(join15(projectDir, entry.name));
|
|
37869
38020
|
}
|
|
37870
38021
|
}
|
|
37871
38022
|
} catch {}
|
|
@@ -38020,16 +38171,16 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
38020
38171
|
if (pattern.includes("*")) {
|
|
38021
38172
|
const dir = workingDir;
|
|
38022
38173
|
try {
|
|
38023
|
-
const files =
|
|
38174
|
+
const files = fs9.readdirSync(dir);
|
|
38024
38175
|
const regex = simpleGlobToRegex(pattern);
|
|
38025
38176
|
const matches = files.filter((f) => regex.test(f));
|
|
38026
38177
|
if (matches.length > 0) {
|
|
38027
|
-
return
|
|
38178
|
+
return path19.join(dir, matches[0]);
|
|
38028
38179
|
}
|
|
38029
38180
|
} catch {}
|
|
38030
38181
|
} else {
|
|
38031
|
-
const filePath =
|
|
38032
|
-
if (
|
|
38182
|
+
const filePath = path19.join(workingDir, pattern);
|
|
38183
|
+
if (fs9.existsSync(filePath)) {
|
|
38033
38184
|
return filePath;
|
|
38034
38185
|
}
|
|
38035
38186
|
}
|
|
@@ -38037,12 +38188,12 @@ function findBuildFiles(workingDir, patterns) {
|
|
|
38037
38188
|
return null;
|
|
38038
38189
|
}
|
|
38039
38190
|
function getRepoDefinedScripts(workingDir, scripts) {
|
|
38040
|
-
const packageJsonPath =
|
|
38041
|
-
if (!
|
|
38191
|
+
const packageJsonPath = path19.join(workingDir, "package.json");
|
|
38192
|
+
if (!fs9.existsSync(packageJsonPath)) {
|
|
38042
38193
|
return [];
|
|
38043
38194
|
}
|
|
38044
38195
|
try {
|
|
38045
|
-
const content =
|
|
38196
|
+
const content = fs9.readFileSync(packageJsonPath, "utf-8");
|
|
38046
38197
|
const pkg = JSON.parse(content);
|
|
38047
38198
|
if (!pkg.scripts || typeof pkg.scripts !== "object") {
|
|
38048
38199
|
return [];
|
|
@@ -38078,8 +38229,8 @@ function findAllBuildFiles(workingDir) {
|
|
|
38078
38229
|
const regex = simpleGlobToRegex(pattern);
|
|
38079
38230
|
findFilesRecursive(workingDir, regex, allBuildFiles);
|
|
38080
38231
|
} else {
|
|
38081
|
-
const filePath =
|
|
38082
|
-
if (
|
|
38232
|
+
const filePath = path19.join(workingDir, pattern);
|
|
38233
|
+
if (fs9.existsSync(filePath)) {
|
|
38083
38234
|
allBuildFiles.add(filePath);
|
|
38084
38235
|
}
|
|
38085
38236
|
}
|
|
@@ -38089,9 +38240,9 @@ function findAllBuildFiles(workingDir) {
|
|
|
38089
38240
|
}
|
|
38090
38241
|
function findFilesRecursive(dir, regex, results) {
|
|
38091
38242
|
try {
|
|
38092
|
-
const entries =
|
|
38243
|
+
const entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
38093
38244
|
for (const entry of entries) {
|
|
38094
|
-
const fullPath =
|
|
38245
|
+
const fullPath = path19.join(dir, entry.name);
|
|
38095
38246
|
if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
|
|
38096
38247
|
findFilesRecursive(fullPath, regex, results);
|
|
38097
38248
|
} else if (entry.isFile() && regex.test(entry.name)) {
|
|
@@ -38114,8 +38265,8 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
|
|
|
38114
38265
|
let foundCommand = false;
|
|
38115
38266
|
for (const cmd of sortedCommands) {
|
|
38116
38267
|
if (cmd.detectFile) {
|
|
38117
|
-
const detectFilePath =
|
|
38118
|
-
if (!
|
|
38268
|
+
const detectFilePath = path19.join(workingDir, cmd.detectFile);
|
|
38269
|
+
if (!fs9.existsSync(detectFilePath)) {
|
|
38119
38270
|
continue;
|
|
38120
38271
|
}
|
|
38121
38272
|
}
|
|
@@ -38238,7 +38389,7 @@ var BINARY_CHECKLIST = [
|
|
|
38238
38389
|
function extractRegisteredToolKeys(indexPath) {
|
|
38239
38390
|
const registeredKeys = new Set;
|
|
38240
38391
|
try {
|
|
38241
|
-
const content =
|
|
38392
|
+
const content = fs10.readFileSync(indexPath, "utf-8");
|
|
38242
38393
|
const toolBlockMatch = content.match(/tool:\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}/s);
|
|
38243
38394
|
if (!toolBlockMatch) {
|
|
38244
38395
|
return registeredKeys;
|
|
@@ -38289,9 +38440,9 @@ function checkBinaryReadiness() {
|
|
|
38289
38440
|
}
|
|
38290
38441
|
function runToolDoctor(_directory, pluginRoot) {
|
|
38291
38442
|
const findings = [];
|
|
38292
|
-
const resolvedPluginRoot = pluginRoot ??
|
|
38293
|
-
const indexPath =
|
|
38294
|
-
if (!
|
|
38443
|
+
const resolvedPluginRoot = pluginRoot ?? path20.resolve(import.meta.dir, "..", "..");
|
|
38444
|
+
const indexPath = path20.join(resolvedPluginRoot, "src", "index.ts");
|
|
38445
|
+
if (!fs10.existsSync(indexPath)) {
|
|
38295
38446
|
return {
|
|
38296
38447
|
findings: [
|
|
38297
38448
|
{
|
|
@@ -39211,12 +39362,12 @@ async function handleHistoryCommand(directory, _args) {
|
|
|
39211
39362
|
}
|
|
39212
39363
|
// src/hooks/knowledge-migrator.ts
|
|
39213
39364
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
39214
|
-
import { existsSync as existsSync12, readFileSync as
|
|
39365
|
+
import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
|
|
39215
39366
|
import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
39216
|
-
import * as
|
|
39367
|
+
import * as path21 from "path";
|
|
39217
39368
|
async function migrateContextToKnowledge(directory, config3) {
|
|
39218
|
-
const sentinelPath =
|
|
39219
|
-
const contextPath =
|
|
39369
|
+
const sentinelPath = path21.join(directory, ".swarm", ".knowledge-migrated");
|
|
39370
|
+
const contextPath = path21.join(directory, ".swarm", "context.md");
|
|
39220
39371
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
39221
39372
|
if (existsSync12(sentinelPath)) {
|
|
39222
39373
|
return {
|
|
@@ -39412,16 +39563,16 @@ function truncateLesson(text) {
|
|
|
39412
39563
|
return `${text.slice(0, 277)}...`;
|
|
39413
39564
|
}
|
|
39414
39565
|
function inferProjectName(directory) {
|
|
39415
|
-
const packageJsonPath =
|
|
39566
|
+
const packageJsonPath = path21.join(directory, "package.json");
|
|
39416
39567
|
if (existsSync12(packageJsonPath)) {
|
|
39417
39568
|
try {
|
|
39418
|
-
const pkg = JSON.parse(
|
|
39569
|
+
const pkg = JSON.parse(readFileSync9(packageJsonPath, "utf-8"));
|
|
39419
39570
|
if (pkg.name && typeof pkg.name === "string") {
|
|
39420
39571
|
return pkg.name;
|
|
39421
39572
|
}
|
|
39422
39573
|
} catch {}
|
|
39423
39574
|
}
|
|
39424
|
-
return
|
|
39575
|
+
return path21.basename(directory);
|
|
39425
39576
|
}
|
|
39426
39577
|
async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
39427
39578
|
const sentinel = {
|
|
@@ -39433,7 +39584,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
39433
39584
|
schema_version: 1,
|
|
39434
39585
|
migration_tool: "knowledge-migrator.ts"
|
|
39435
39586
|
};
|
|
39436
|
-
await mkdir3(
|
|
39587
|
+
await mkdir3(path21.dirname(sentinelPath), { recursive: true });
|
|
39437
39588
|
await writeFile4(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
39438
39589
|
}
|
|
39439
39590
|
|
|
@@ -39669,13 +39820,13 @@ async function handlePlanCommand(directory, args) {
|
|
|
39669
39820
|
// src/services/preflight-service.ts
|
|
39670
39821
|
init_manager2();
|
|
39671
39822
|
init_manager();
|
|
39672
|
-
import * as
|
|
39673
|
-
import * as
|
|
39823
|
+
import * as fs17 from "fs";
|
|
39824
|
+
import * as path28 from "path";
|
|
39674
39825
|
|
|
39675
39826
|
// src/tools/lint.ts
|
|
39676
39827
|
init_zod();
|
|
39677
|
-
import * as
|
|
39678
|
-
import * as
|
|
39828
|
+
import * as fs11 from "fs";
|
|
39829
|
+
import * as path22 from "path";
|
|
39679
39830
|
init_utils();
|
|
39680
39831
|
|
|
39681
39832
|
// src/utils/path-security.ts
|
|
@@ -39721,9 +39872,9 @@ function validateArgs(args) {
|
|
|
39721
39872
|
}
|
|
39722
39873
|
function getLinterCommand(linter, mode, projectDir) {
|
|
39723
39874
|
const isWindows = process.platform === "win32";
|
|
39724
|
-
const binDir =
|
|
39725
|
-
const biomeBin = isWindows ?
|
|
39726
|
-
const eslintBin = isWindows ?
|
|
39875
|
+
const binDir = path22.join(projectDir, "node_modules", ".bin");
|
|
39876
|
+
const biomeBin = isWindows ? path22.join(binDir, "biome.EXE") : path22.join(binDir, "biome");
|
|
39877
|
+
const eslintBin = isWindows ? path22.join(binDir, "eslint.cmd") : path22.join(binDir, "eslint");
|
|
39727
39878
|
switch (linter) {
|
|
39728
39879
|
case "biome":
|
|
39729
39880
|
if (mode === "fix") {
|
|
@@ -39739,7 +39890,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
39739
39890
|
}
|
|
39740
39891
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
39741
39892
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
39742
|
-
const gradlew =
|
|
39893
|
+
const gradlew = fs11.existsSync(path22.join(cwd, gradlewName)) ? path22.join(cwd, gradlewName) : null;
|
|
39743
39894
|
switch (linter) {
|
|
39744
39895
|
case "ruff":
|
|
39745
39896
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -39773,12 +39924,12 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
39773
39924
|
}
|
|
39774
39925
|
}
|
|
39775
39926
|
function detectRuff(cwd) {
|
|
39776
|
-
if (
|
|
39927
|
+
if (fs11.existsSync(path22.join(cwd, "ruff.toml")))
|
|
39777
39928
|
return isCommandAvailable("ruff");
|
|
39778
39929
|
try {
|
|
39779
|
-
const pyproject =
|
|
39780
|
-
if (
|
|
39781
|
-
const content =
|
|
39930
|
+
const pyproject = path22.join(cwd, "pyproject.toml");
|
|
39931
|
+
if (fs11.existsSync(pyproject)) {
|
|
39932
|
+
const content = fs11.readFileSync(pyproject, "utf-8");
|
|
39782
39933
|
if (content.includes("[tool.ruff]"))
|
|
39783
39934
|
return isCommandAvailable("ruff");
|
|
39784
39935
|
}
|
|
@@ -39786,21 +39937,21 @@ function detectRuff(cwd) {
|
|
|
39786
39937
|
return false;
|
|
39787
39938
|
}
|
|
39788
39939
|
function detectClippy(cwd) {
|
|
39789
|
-
return
|
|
39940
|
+
return fs11.existsSync(path22.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
39790
39941
|
}
|
|
39791
39942
|
function detectGolangciLint(cwd) {
|
|
39792
|
-
return
|
|
39943
|
+
return fs11.existsSync(path22.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
39793
39944
|
}
|
|
39794
39945
|
function detectCheckstyle(cwd) {
|
|
39795
|
-
const hasMaven =
|
|
39796
|
-
const hasGradle =
|
|
39797
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (
|
|
39946
|
+
const hasMaven = fs11.existsSync(path22.join(cwd, "pom.xml"));
|
|
39947
|
+
const hasGradle = fs11.existsSync(path22.join(cwd, "build.gradle")) || fs11.existsSync(path22.join(cwd, "build.gradle.kts"));
|
|
39948
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs11.existsSync(path22.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
39798
39949
|
return (hasMaven || hasGradle) && hasBinary;
|
|
39799
39950
|
}
|
|
39800
39951
|
function detectKtlint(cwd) {
|
|
39801
|
-
const hasKotlin =
|
|
39952
|
+
const hasKotlin = fs11.existsSync(path22.join(cwd, "build.gradle.kts")) || fs11.existsSync(path22.join(cwd, "build.gradle")) || (() => {
|
|
39802
39953
|
try {
|
|
39803
|
-
return
|
|
39954
|
+
return fs11.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
39804
39955
|
} catch {
|
|
39805
39956
|
return false;
|
|
39806
39957
|
}
|
|
@@ -39809,7 +39960,7 @@ function detectKtlint(cwd) {
|
|
|
39809
39960
|
}
|
|
39810
39961
|
function detectDotnetFormat(cwd) {
|
|
39811
39962
|
try {
|
|
39812
|
-
const files =
|
|
39963
|
+
const files = fs11.readdirSync(cwd);
|
|
39813
39964
|
const hasCsproj = files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"));
|
|
39814
39965
|
return hasCsproj && isCommandAvailable("dotnet");
|
|
39815
39966
|
} catch {
|
|
@@ -39817,14 +39968,14 @@ function detectDotnetFormat(cwd) {
|
|
|
39817
39968
|
}
|
|
39818
39969
|
}
|
|
39819
39970
|
function detectCppcheck(cwd) {
|
|
39820
|
-
if (
|
|
39971
|
+
if (fs11.existsSync(path22.join(cwd, "CMakeLists.txt"))) {
|
|
39821
39972
|
return isCommandAvailable("cppcheck");
|
|
39822
39973
|
}
|
|
39823
39974
|
try {
|
|
39824
|
-
const dirsToCheck = [cwd,
|
|
39975
|
+
const dirsToCheck = [cwd, path22.join(cwd, "src")];
|
|
39825
39976
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
39826
39977
|
try {
|
|
39827
|
-
return
|
|
39978
|
+
return fs11.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
39828
39979
|
} catch {
|
|
39829
39980
|
return false;
|
|
39830
39981
|
}
|
|
@@ -39835,13 +39986,13 @@ function detectCppcheck(cwd) {
|
|
|
39835
39986
|
}
|
|
39836
39987
|
}
|
|
39837
39988
|
function detectSwiftlint(cwd) {
|
|
39838
|
-
return
|
|
39989
|
+
return fs11.existsSync(path22.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
39839
39990
|
}
|
|
39840
39991
|
function detectDartAnalyze(cwd) {
|
|
39841
|
-
return
|
|
39992
|
+
return fs11.existsSync(path22.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
39842
39993
|
}
|
|
39843
39994
|
function detectRubocop(cwd) {
|
|
39844
|
-
return (
|
|
39995
|
+
return (fs11.existsSync(path22.join(cwd, "Gemfile")) || fs11.existsSync(path22.join(cwd, "gems.rb")) || fs11.existsSync(path22.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
|
|
39845
39996
|
}
|
|
39846
39997
|
function detectAdditionalLinter(cwd) {
|
|
39847
39998
|
if (detectRuff(cwd))
|
|
@@ -39869,10 +40020,10 @@ function detectAdditionalLinter(cwd) {
|
|
|
39869
40020
|
function findBinInAncestors(startDir, binName) {
|
|
39870
40021
|
let dir = startDir;
|
|
39871
40022
|
while (true) {
|
|
39872
|
-
const candidate =
|
|
39873
|
-
if (
|
|
40023
|
+
const candidate = path22.join(dir, "node_modules", ".bin", binName);
|
|
40024
|
+
if (fs11.existsSync(candidate))
|
|
39874
40025
|
return candidate;
|
|
39875
|
-
const parent =
|
|
40026
|
+
const parent = path22.dirname(dir);
|
|
39876
40027
|
if (parent === dir)
|
|
39877
40028
|
break;
|
|
39878
40029
|
dir = parent;
|
|
@@ -39881,11 +40032,11 @@ function findBinInAncestors(startDir, binName) {
|
|
|
39881
40032
|
}
|
|
39882
40033
|
function findBinInEnvPath(binName) {
|
|
39883
40034
|
const searchPath = process.env.PATH ?? "";
|
|
39884
|
-
for (const dir of searchPath.split(
|
|
40035
|
+
for (const dir of searchPath.split(path22.delimiter)) {
|
|
39885
40036
|
if (!dir)
|
|
39886
40037
|
continue;
|
|
39887
|
-
const candidate =
|
|
39888
|
-
if (
|
|
40038
|
+
const candidate = path22.join(dir, binName);
|
|
40039
|
+
if (fs11.existsSync(candidate))
|
|
39889
40040
|
return candidate;
|
|
39890
40041
|
}
|
|
39891
40042
|
return null;
|
|
@@ -39893,17 +40044,17 @@ function findBinInEnvPath(binName) {
|
|
|
39893
40044
|
async function detectAvailableLinter(directory) {
|
|
39894
40045
|
if (!directory)
|
|
39895
40046
|
return null;
|
|
39896
|
-
if (!
|
|
40047
|
+
if (!fs11.existsSync(directory))
|
|
39897
40048
|
return null;
|
|
39898
40049
|
const projectDir = directory;
|
|
39899
40050
|
const isWindows = process.platform === "win32";
|
|
39900
|
-
const biomeBin = isWindows ?
|
|
39901
|
-
const eslintBin = isWindows ?
|
|
40051
|
+
const biomeBin = isWindows ? path22.join(projectDir, "node_modules", ".bin", "biome.EXE") : path22.join(projectDir, "node_modules", ".bin", "biome");
|
|
40052
|
+
const eslintBin = isWindows ? path22.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path22.join(projectDir, "node_modules", ".bin", "eslint");
|
|
39902
40053
|
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
39903
40054
|
if (localResult)
|
|
39904
40055
|
return localResult;
|
|
39905
|
-
const biomeAncestor = findBinInAncestors(
|
|
39906
|
-
const eslintAncestor = findBinInAncestors(
|
|
40056
|
+
const biomeAncestor = findBinInAncestors(path22.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
40057
|
+
const eslintAncestor = findBinInAncestors(path22.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
39907
40058
|
if (biomeAncestor || eslintAncestor) {
|
|
39908
40059
|
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
39909
40060
|
}
|
|
@@ -39926,7 +40077,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
|
|
|
39926
40077
|
const result = await Promise.race([biomeExit, timeout]);
|
|
39927
40078
|
if (result === "timeout") {
|
|
39928
40079
|
biomeProc.kill();
|
|
39929
|
-
} else if (biomeProc.exitCode === 0 &&
|
|
40080
|
+
} else if (biomeProc.exitCode === 0 && fs11.existsSync(biomeBin)) {
|
|
39930
40081
|
return "biome";
|
|
39931
40082
|
}
|
|
39932
40083
|
} catch {}
|
|
@@ -39940,7 +40091,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
|
|
|
39940
40091
|
const result = await Promise.race([eslintExit, timeout]);
|
|
39941
40092
|
if (result === "timeout") {
|
|
39942
40093
|
eslintProc.kill();
|
|
39943
|
-
} else if (eslintProc.exitCode === 0 &&
|
|
40094
|
+
} else if (eslintProc.exitCode === 0 && fs11.existsSync(eslintBin)) {
|
|
39944
40095
|
return "eslint";
|
|
39945
40096
|
}
|
|
39946
40097
|
} catch {}
|
|
@@ -40111,8 +40262,8 @@ For Rust: rustup component add clippy`
|
|
|
40111
40262
|
|
|
40112
40263
|
// src/tools/secretscan.ts
|
|
40113
40264
|
init_zod();
|
|
40114
|
-
import * as
|
|
40115
|
-
import * as
|
|
40265
|
+
import * as fs12 from "fs";
|
|
40266
|
+
import * as path23 from "path";
|
|
40116
40267
|
var MAX_FILE_PATH_LENGTH = 500;
|
|
40117
40268
|
var MAX_FILE_SIZE_BYTES = 512 * 1024;
|
|
40118
40269
|
var MAX_FILES_SCANNED = 1000;
|
|
@@ -40339,11 +40490,11 @@ function isGlobOrPathPattern(pattern) {
|
|
|
40339
40490
|
return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
|
|
40340
40491
|
}
|
|
40341
40492
|
function loadSecretScanIgnore(scanDir) {
|
|
40342
|
-
const ignorePath =
|
|
40493
|
+
const ignorePath = path23.join(scanDir, ".secretscanignore");
|
|
40343
40494
|
try {
|
|
40344
|
-
if (!
|
|
40495
|
+
if (!fs12.existsSync(ignorePath))
|
|
40345
40496
|
return [];
|
|
40346
|
-
const content =
|
|
40497
|
+
const content = fs12.readFileSync(ignorePath, "utf8");
|
|
40347
40498
|
const patterns = [];
|
|
40348
40499
|
for (const rawLine of content.split(/\r?\n/)) {
|
|
40349
40500
|
const line = rawLine.trim();
|
|
@@ -40362,7 +40513,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
40362
40513
|
if (exactNames.has(entry))
|
|
40363
40514
|
return true;
|
|
40364
40515
|
for (const pattern of globPatterns) {
|
|
40365
|
-
if (
|
|
40516
|
+
if (path23.matchesGlob(relPath, pattern))
|
|
40366
40517
|
return true;
|
|
40367
40518
|
}
|
|
40368
40519
|
return false;
|
|
@@ -40383,7 +40534,7 @@ function validateDirectoryInput(dir) {
|
|
|
40383
40534
|
return null;
|
|
40384
40535
|
}
|
|
40385
40536
|
function isBinaryFile(filePath, buffer) {
|
|
40386
|
-
const ext =
|
|
40537
|
+
const ext = path23.extname(filePath).toLowerCase();
|
|
40387
40538
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
40388
40539
|
return true;
|
|
40389
40540
|
}
|
|
@@ -40458,11 +40609,11 @@ function createRedactedContext(line, findings) {
|
|
|
40458
40609
|
result += line.slice(lastEnd);
|
|
40459
40610
|
return result;
|
|
40460
40611
|
}
|
|
40461
|
-
var O_NOFOLLOW = process.platform !== "win32" ?
|
|
40612
|
+
var O_NOFOLLOW = process.platform !== "win32" ? fs12.constants.O_NOFOLLOW : undefined;
|
|
40462
40613
|
function scanFileForSecrets(filePath) {
|
|
40463
40614
|
const findings = [];
|
|
40464
40615
|
try {
|
|
40465
|
-
const lstat =
|
|
40616
|
+
const lstat = fs12.lstatSync(filePath);
|
|
40466
40617
|
if (lstat.isSymbolicLink()) {
|
|
40467
40618
|
return findings;
|
|
40468
40619
|
}
|
|
@@ -40471,14 +40622,14 @@ function scanFileForSecrets(filePath) {
|
|
|
40471
40622
|
}
|
|
40472
40623
|
let buffer;
|
|
40473
40624
|
if (O_NOFOLLOW !== undefined) {
|
|
40474
|
-
const fd =
|
|
40625
|
+
const fd = fs12.openSync(filePath, "r", O_NOFOLLOW);
|
|
40475
40626
|
try {
|
|
40476
|
-
buffer =
|
|
40627
|
+
buffer = fs12.readFileSync(fd);
|
|
40477
40628
|
} finally {
|
|
40478
|
-
|
|
40629
|
+
fs12.closeSync(fd);
|
|
40479
40630
|
}
|
|
40480
40631
|
} else {
|
|
40481
|
-
buffer =
|
|
40632
|
+
buffer = fs12.readFileSync(filePath);
|
|
40482
40633
|
}
|
|
40483
40634
|
if (isBinaryFile(filePath, buffer)) {
|
|
40484
40635
|
return findings;
|
|
@@ -40520,9 +40671,9 @@ function isSymlinkLoop(realPath, visited) {
|
|
|
40520
40671
|
return false;
|
|
40521
40672
|
}
|
|
40522
40673
|
function isPathWithinScope(realPath, scanDir) {
|
|
40523
|
-
const resolvedScanDir =
|
|
40524
|
-
const resolvedRealPath =
|
|
40525
|
-
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir +
|
|
40674
|
+
const resolvedScanDir = path23.resolve(scanDir);
|
|
40675
|
+
const resolvedRealPath = path23.resolve(realPath);
|
|
40676
|
+
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path23.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
|
|
40526
40677
|
}
|
|
40527
40678
|
function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
|
|
40528
40679
|
skippedDirs: 0,
|
|
@@ -40533,7 +40684,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
40533
40684
|
const files = [];
|
|
40534
40685
|
let entries;
|
|
40535
40686
|
try {
|
|
40536
|
-
entries =
|
|
40687
|
+
entries = fs12.readdirSync(dir);
|
|
40537
40688
|
} catch {
|
|
40538
40689
|
stats.fileErrors++;
|
|
40539
40690
|
return files;
|
|
@@ -40548,15 +40699,15 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
40548
40699
|
return a.localeCompare(b);
|
|
40549
40700
|
});
|
|
40550
40701
|
for (const entry of entries) {
|
|
40551
|
-
const fullPath =
|
|
40552
|
-
const relPath =
|
|
40702
|
+
const fullPath = path23.join(dir, entry);
|
|
40703
|
+
const relPath = path23.relative(scanDir, fullPath).replace(/\\/g, "/");
|
|
40553
40704
|
if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
|
|
40554
40705
|
stats.skippedDirs++;
|
|
40555
40706
|
continue;
|
|
40556
40707
|
}
|
|
40557
40708
|
let lstat;
|
|
40558
40709
|
try {
|
|
40559
|
-
lstat =
|
|
40710
|
+
lstat = fs12.lstatSync(fullPath);
|
|
40560
40711
|
} catch {
|
|
40561
40712
|
stats.fileErrors++;
|
|
40562
40713
|
continue;
|
|
@@ -40568,7 +40719,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
40568
40719
|
if (lstat.isDirectory()) {
|
|
40569
40720
|
let realPath;
|
|
40570
40721
|
try {
|
|
40571
|
-
realPath =
|
|
40722
|
+
realPath = fs12.realpathSync(fullPath);
|
|
40572
40723
|
} catch {
|
|
40573
40724
|
stats.fileErrors++;
|
|
40574
40725
|
continue;
|
|
@@ -40584,7 +40735,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
40584
40735
|
const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
|
|
40585
40736
|
files.push(...subFiles);
|
|
40586
40737
|
} else if (lstat.isFile()) {
|
|
40587
|
-
const ext =
|
|
40738
|
+
const ext = path23.extname(fullPath).toLowerCase();
|
|
40588
40739
|
if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
40589
40740
|
files.push(fullPath);
|
|
40590
40741
|
} else {
|
|
@@ -40650,15 +40801,15 @@ var secretscan = createSwarmTool({
|
|
|
40650
40801
|
}
|
|
40651
40802
|
}
|
|
40652
40803
|
try {
|
|
40653
|
-
const _scanDirRaw =
|
|
40804
|
+
const _scanDirRaw = path23.resolve(directory);
|
|
40654
40805
|
const scanDir = (() => {
|
|
40655
40806
|
try {
|
|
40656
|
-
return
|
|
40807
|
+
return fs12.realpathSync(_scanDirRaw);
|
|
40657
40808
|
} catch {
|
|
40658
40809
|
return _scanDirRaw;
|
|
40659
40810
|
}
|
|
40660
40811
|
})();
|
|
40661
|
-
if (!
|
|
40812
|
+
if (!fs12.existsSync(scanDir)) {
|
|
40662
40813
|
const errorResult = {
|
|
40663
40814
|
error: "directory not found",
|
|
40664
40815
|
scan_dir: directory,
|
|
@@ -40669,7 +40820,7 @@ var secretscan = createSwarmTool({
|
|
|
40669
40820
|
};
|
|
40670
40821
|
return JSON.stringify(errorResult, null, 2);
|
|
40671
40822
|
}
|
|
40672
|
-
const dirStat =
|
|
40823
|
+
const dirStat = fs12.statSync(scanDir);
|
|
40673
40824
|
if (!dirStat.isDirectory()) {
|
|
40674
40825
|
const errorResult = {
|
|
40675
40826
|
error: "target must be a directory, not a file",
|
|
@@ -40720,7 +40871,7 @@ var secretscan = createSwarmTool({
|
|
|
40720
40871
|
break;
|
|
40721
40872
|
const fileFindings = scanFileForSecrets(filePath);
|
|
40722
40873
|
try {
|
|
40723
|
-
const stat2 =
|
|
40874
|
+
const stat2 = fs12.statSync(filePath);
|
|
40724
40875
|
if (stat2.size > MAX_FILE_SIZE_BYTES) {
|
|
40725
40876
|
skippedFiles++;
|
|
40726
40877
|
continue;
|
|
@@ -40809,12 +40960,12 @@ async function runSecretscan(directory) {
|
|
|
40809
40960
|
|
|
40810
40961
|
// src/tools/test-runner.ts
|
|
40811
40962
|
init_zod();
|
|
40812
|
-
import * as
|
|
40813
|
-
import * as
|
|
40963
|
+
import * as fs16 from "fs";
|
|
40964
|
+
import * as path27 from "path";
|
|
40814
40965
|
|
|
40815
40966
|
// src/test-impact/analyzer.ts
|
|
40816
|
-
import
|
|
40817
|
-
import
|
|
40967
|
+
import fs13 from "fs";
|
|
40968
|
+
import path24 from "path";
|
|
40818
40969
|
var IMPORT_REGEX_ES = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
40819
40970
|
var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
40820
40971
|
var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
|
|
@@ -40825,7 +40976,7 @@ function normalizePath(p) {
|
|
|
40825
40976
|
function isCacheStale(impactMap, generatedAtMs) {
|
|
40826
40977
|
for (const sourcePath of Object.keys(impactMap)) {
|
|
40827
40978
|
try {
|
|
40828
|
-
const stat2 =
|
|
40979
|
+
const stat2 = fs13.statSync(sourcePath);
|
|
40829
40980
|
if (stat2.mtimeMs > generatedAtMs) {
|
|
40830
40981
|
return true;
|
|
40831
40982
|
}
|
|
@@ -40839,15 +40990,15 @@ function resolveRelativeImport(fromDir, importPath) {
|
|
|
40839
40990
|
if (!importPath.startsWith(".")) {
|
|
40840
40991
|
return null;
|
|
40841
40992
|
}
|
|
40842
|
-
const resolved =
|
|
40843
|
-
if (
|
|
40844
|
-
if (
|
|
40993
|
+
const resolved = path24.resolve(fromDir, importPath);
|
|
40994
|
+
if (path24.extname(resolved)) {
|
|
40995
|
+
if (fs13.existsSync(resolved) && fs13.statSync(resolved).isFile()) {
|
|
40845
40996
|
return normalizePath(resolved);
|
|
40846
40997
|
}
|
|
40847
40998
|
} else {
|
|
40848
40999
|
for (const ext of EXTENSIONS_TO_TRY) {
|
|
40849
41000
|
const withExt = resolved + ext;
|
|
40850
|
-
if (
|
|
41001
|
+
if (fs13.existsSync(withExt) && fs13.statSync(withExt).isFile()) {
|
|
40851
41002
|
return normalizePath(withExt);
|
|
40852
41003
|
}
|
|
40853
41004
|
}
|
|
@@ -40866,13 +41017,13 @@ function findTestFilesSync(cwd) {
|
|
|
40866
41017
|
function walk(dir, visitedInodes) {
|
|
40867
41018
|
let entries;
|
|
40868
41019
|
try {
|
|
40869
|
-
entries =
|
|
41020
|
+
entries = fs13.readdirSync(dir, { withFileTypes: true });
|
|
40870
41021
|
} catch {
|
|
40871
41022
|
return;
|
|
40872
41023
|
}
|
|
40873
41024
|
let dirInode;
|
|
40874
41025
|
try {
|
|
40875
|
-
dirInode =
|
|
41026
|
+
dirInode = fs13.statSync(dir).ino;
|
|
40876
41027
|
} catch {
|
|
40877
41028
|
return;
|
|
40878
41029
|
}
|
|
@@ -40885,12 +41036,12 @@ function findTestFilesSync(cwd) {
|
|
|
40885
41036
|
for (const entry of entries) {
|
|
40886
41037
|
if (entry.isDirectory()) {
|
|
40887
41038
|
if (!skipDirs.has(entry.name)) {
|
|
40888
|
-
walk(
|
|
41039
|
+
walk(path24.join(dir, entry.name), visitedInodes);
|
|
40889
41040
|
}
|
|
40890
41041
|
} else if (entry.isFile()) {
|
|
40891
41042
|
const name = entry.name;
|
|
40892
41043
|
if (/\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name)) {
|
|
40893
|
-
testFiles.push(normalizePath(
|
|
41044
|
+
testFiles.push(normalizePath(path24.join(dir, entry.name)));
|
|
40894
41045
|
}
|
|
40895
41046
|
}
|
|
40896
41047
|
}
|
|
@@ -40920,7 +41071,7 @@ async function buildImpactMapInternal(cwd) {
|
|
|
40920
41071
|
for (const testFile of testFiles) {
|
|
40921
41072
|
let content;
|
|
40922
41073
|
try {
|
|
40923
|
-
content =
|
|
41074
|
+
content = fs13.readFileSync(testFile, "utf-8");
|
|
40924
41075
|
} catch {
|
|
40925
41076
|
continue;
|
|
40926
41077
|
}
|
|
@@ -40928,7 +41079,7 @@ async function buildImpactMapInternal(cwd) {
|
|
|
40928
41079
|
continue;
|
|
40929
41080
|
}
|
|
40930
41081
|
const imports = extractImports(content);
|
|
40931
|
-
const testDir =
|
|
41082
|
+
const testDir = path24.dirname(testFile);
|
|
40932
41083
|
for (const importPath of imports) {
|
|
40933
41084
|
const resolvedSource = resolveRelativeImport(testDir, importPath);
|
|
40934
41085
|
if (resolvedSource === null) {
|
|
@@ -40950,10 +41101,10 @@ async function buildImpactMap(cwd) {
|
|
|
40950
41101
|
return impactMap;
|
|
40951
41102
|
}
|
|
40952
41103
|
async function loadImpactMap(cwd) {
|
|
40953
|
-
const cachePath =
|
|
40954
|
-
if (
|
|
41104
|
+
const cachePath = path24.join(cwd, ".swarm", "cache", "impact-map.json");
|
|
41105
|
+
if (fs13.existsSync(cachePath)) {
|
|
40955
41106
|
try {
|
|
40956
|
-
const content =
|
|
41107
|
+
const content = fs13.readFileSync(cachePath, "utf-8");
|
|
40957
41108
|
const data = JSON.parse(content);
|
|
40958
41109
|
const map3 = data.map;
|
|
40959
41110
|
const generatedAt = new Date(data.generatedAt).getTime();
|
|
@@ -40965,17 +41116,17 @@ async function loadImpactMap(cwd) {
|
|
|
40965
41116
|
return buildImpactMap(cwd);
|
|
40966
41117
|
}
|
|
40967
41118
|
async function saveImpactMap(cwd, impactMap) {
|
|
40968
|
-
const cacheDir =
|
|
40969
|
-
const cachePath =
|
|
40970
|
-
if (!
|
|
40971
|
-
|
|
41119
|
+
const cacheDir = path24.join(cwd, ".swarm", "cache");
|
|
41120
|
+
const cachePath = path24.join(cacheDir, "impact-map.json");
|
|
41121
|
+
if (!fs13.existsSync(cacheDir)) {
|
|
41122
|
+
fs13.mkdirSync(cacheDir, { recursive: true });
|
|
40972
41123
|
}
|
|
40973
41124
|
const data = {
|
|
40974
41125
|
generatedAt: new Date().toISOString(),
|
|
40975
41126
|
fileCount: Object.keys(impactMap).length,
|
|
40976
41127
|
map: impactMap
|
|
40977
41128
|
};
|
|
40978
|
-
|
|
41129
|
+
fs13.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
|
|
40979
41130
|
}
|
|
40980
41131
|
async function analyzeImpact(changedFiles, cwd) {
|
|
40981
41132
|
if (!Array.isArray(changedFiles)) {
|
|
@@ -40992,7 +41143,7 @@ async function analyzeImpact(changedFiles, cwd) {
|
|
|
40992
41143
|
const impactedTestsSet = new Set;
|
|
40993
41144
|
const untestedFiles = [];
|
|
40994
41145
|
for (const changedFile of validFiles) {
|
|
40995
|
-
const normalizedChanged = normalizePath(
|
|
41146
|
+
const normalizedChanged = normalizePath(path24.resolve(changedFile));
|
|
40996
41147
|
const tests = impactMap[normalizedChanged];
|
|
40997
41148
|
if (tests && tests.length > 0) {
|
|
40998
41149
|
for (const test of tests) {
|
|
@@ -41238,14 +41389,14 @@ function detectFlakyTests(allHistory) {
|
|
|
41238
41389
|
}
|
|
41239
41390
|
|
|
41240
41391
|
// src/test-impact/history-store.ts
|
|
41241
|
-
import
|
|
41242
|
-
import
|
|
41392
|
+
import fs14 from "fs";
|
|
41393
|
+
import path25 from "path";
|
|
41243
41394
|
var MAX_HISTORY_PER_TEST = 20;
|
|
41244
41395
|
var MAX_ERROR_LENGTH = 500;
|
|
41245
41396
|
var MAX_STACK_LENGTH = 200;
|
|
41246
41397
|
var MAX_CHANGED_FILES = 50;
|
|
41247
41398
|
function getHistoryPath(workingDir) {
|
|
41248
|
-
return
|
|
41399
|
+
return path25.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
|
|
41249
41400
|
}
|
|
41250
41401
|
function sanitizeErrorMessage(errorMessage) {
|
|
41251
41402
|
if (errorMessage === undefined) {
|
|
@@ -41305,9 +41456,9 @@ function appendTestRun(record3, workingDir) {
|
|
|
41305
41456
|
changedFiles: sanitizeChangedFiles(record3.changedFiles || [])
|
|
41306
41457
|
};
|
|
41307
41458
|
const historyPath = getHistoryPath(workingDir);
|
|
41308
|
-
const historyDir =
|
|
41309
|
-
if (!
|
|
41310
|
-
|
|
41459
|
+
const historyDir = path25.dirname(historyPath);
|
|
41460
|
+
if (!fs14.existsSync(historyDir)) {
|
|
41461
|
+
fs14.mkdirSync(historyDir, { recursive: true });
|
|
41311
41462
|
}
|
|
41312
41463
|
const existingRecords = readAllRecords(historyPath);
|
|
41313
41464
|
existingRecords.push(sanitizedRecord);
|
|
@@ -41332,24 +41483,24 @@ function appendTestRun(record3, workingDir) {
|
|
|
41332
41483
|
`)}
|
|
41333
41484
|
`;
|
|
41334
41485
|
const tempPath = `${historyPath}.tmp`;
|
|
41335
|
-
|
|
41336
|
-
|
|
41486
|
+
fs14.writeFileSync(tempPath, content, "utf-8");
|
|
41487
|
+
fs14.renameSync(tempPath, historyPath);
|
|
41337
41488
|
} catch (err) {
|
|
41338
41489
|
try {
|
|
41339
41490
|
const tempPath = `${historyPath}.tmp`;
|
|
41340
|
-
if (
|
|
41341
|
-
|
|
41491
|
+
if (fs14.existsSync(tempPath)) {
|
|
41492
|
+
fs14.unlinkSync(tempPath);
|
|
41342
41493
|
}
|
|
41343
41494
|
} catch {}
|
|
41344
41495
|
throw new Error(`Failed to write test history: ${err instanceof Error ? err.message : String(err)}`);
|
|
41345
41496
|
}
|
|
41346
41497
|
}
|
|
41347
41498
|
function readAllRecords(historyPath) {
|
|
41348
|
-
if (!
|
|
41499
|
+
if (!fs14.existsSync(historyPath)) {
|
|
41349
41500
|
return [];
|
|
41350
41501
|
}
|
|
41351
41502
|
try {
|
|
41352
|
-
const content =
|
|
41503
|
+
const content = fs14.readFileSync(historyPath, "utf-8");
|
|
41353
41504
|
const lines = content.split(`
|
|
41354
41505
|
`);
|
|
41355
41506
|
const records = [];
|
|
@@ -41378,8 +41529,8 @@ function getAllHistory(workingDir) {
|
|
|
41378
41529
|
}
|
|
41379
41530
|
|
|
41380
41531
|
// src/tools/resolve-working-directory.ts
|
|
41381
|
-
import * as
|
|
41382
|
-
import * as
|
|
41532
|
+
import * as fs15 from "fs";
|
|
41533
|
+
import * as path26 from "path";
|
|
41383
41534
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
41384
41535
|
if (workingDirectory == null || workingDirectory === "") {
|
|
41385
41536
|
return { success: true, directory: fallbackDirectory };
|
|
@@ -41399,18 +41550,18 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
41399
41550
|
};
|
|
41400
41551
|
}
|
|
41401
41552
|
}
|
|
41402
|
-
const normalizedDir =
|
|
41403
|
-
const pathParts = normalizedDir.split(
|
|
41553
|
+
const normalizedDir = path26.normalize(workingDirectory);
|
|
41554
|
+
const pathParts = normalizedDir.split(path26.sep);
|
|
41404
41555
|
if (pathParts.includes("..")) {
|
|
41405
41556
|
return {
|
|
41406
41557
|
success: false,
|
|
41407
41558
|
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
41408
41559
|
};
|
|
41409
41560
|
}
|
|
41410
|
-
const resolvedDir =
|
|
41561
|
+
const resolvedDir = path26.resolve(normalizedDir);
|
|
41411
41562
|
let statResult;
|
|
41412
41563
|
try {
|
|
41413
|
-
statResult =
|
|
41564
|
+
statResult = fs15.statSync(resolvedDir);
|
|
41414
41565
|
} catch {
|
|
41415
41566
|
return {
|
|
41416
41567
|
success: false,
|
|
@@ -41423,17 +41574,17 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
41423
41574
|
message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
|
|
41424
41575
|
};
|
|
41425
41576
|
}
|
|
41426
|
-
const resolvedFallback =
|
|
41577
|
+
const resolvedFallback = path26.resolve(fallbackDirectory);
|
|
41427
41578
|
let fallbackExists = false;
|
|
41428
41579
|
try {
|
|
41429
|
-
|
|
41580
|
+
fs15.statSync(resolvedFallback);
|
|
41430
41581
|
fallbackExists = true;
|
|
41431
41582
|
} catch {
|
|
41432
41583
|
fallbackExists = false;
|
|
41433
41584
|
}
|
|
41434
41585
|
if (workingDirectory != null && workingDirectory !== "") {
|
|
41435
41586
|
if (fallbackExists) {
|
|
41436
|
-
const isSubdirectory = resolvedDir.startsWith(resolvedFallback +
|
|
41587
|
+
const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path26.sep);
|
|
41437
41588
|
if (isSubdirectory) {
|
|
41438
41589
|
return {
|
|
41439
41590
|
success: false,
|
|
@@ -41523,19 +41674,19 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
41523
41674
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
41524
41675
|
}
|
|
41525
41676
|
function detectGoTest(cwd) {
|
|
41526
|
-
return
|
|
41677
|
+
return fs16.existsSync(path27.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
41527
41678
|
}
|
|
41528
41679
|
function detectJavaMaven(cwd) {
|
|
41529
|
-
return
|
|
41680
|
+
return fs16.existsSync(path27.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
41530
41681
|
}
|
|
41531
41682
|
function detectGradle(cwd) {
|
|
41532
|
-
const hasBuildFile =
|
|
41533
|
-
const hasGradlew =
|
|
41683
|
+
const hasBuildFile = fs16.existsSync(path27.join(cwd, "build.gradle")) || fs16.existsSync(path27.join(cwd, "build.gradle.kts"));
|
|
41684
|
+
const hasGradlew = fs16.existsSync(path27.join(cwd, "gradlew")) || fs16.existsSync(path27.join(cwd, "gradlew.bat"));
|
|
41534
41685
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
41535
41686
|
}
|
|
41536
41687
|
function detectDotnetTest(cwd) {
|
|
41537
41688
|
try {
|
|
41538
|
-
const files =
|
|
41689
|
+
const files = fs16.readdirSync(cwd);
|
|
41539
41690
|
const hasCsproj = files.some((f) => f.endsWith(".csproj"));
|
|
41540
41691
|
return hasCsproj && isCommandAvailable("dotnet");
|
|
41541
41692
|
} catch {
|
|
@@ -41543,32 +41694,32 @@ function detectDotnetTest(cwd) {
|
|
|
41543
41694
|
}
|
|
41544
41695
|
}
|
|
41545
41696
|
function detectCTest(cwd) {
|
|
41546
|
-
const hasSource =
|
|
41547
|
-
const hasBuildCache =
|
|
41697
|
+
const hasSource = fs16.existsSync(path27.join(cwd, "CMakeLists.txt"));
|
|
41698
|
+
const hasBuildCache = fs16.existsSync(path27.join(cwd, "CMakeCache.txt")) || fs16.existsSync(path27.join(cwd, "build", "CMakeCache.txt"));
|
|
41548
41699
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
41549
41700
|
}
|
|
41550
41701
|
function detectSwiftTest(cwd) {
|
|
41551
|
-
return
|
|
41702
|
+
return fs16.existsSync(path27.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
41552
41703
|
}
|
|
41553
41704
|
function detectDartTest(cwd) {
|
|
41554
|
-
return
|
|
41705
|
+
return fs16.existsSync(path27.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
41555
41706
|
}
|
|
41556
41707
|
function detectRSpec(cwd) {
|
|
41557
|
-
const hasRSpecFile =
|
|
41558
|
-
const hasGemfile =
|
|
41559
|
-
const hasSpecDir =
|
|
41708
|
+
const hasRSpecFile = fs16.existsSync(path27.join(cwd, ".rspec"));
|
|
41709
|
+
const hasGemfile = fs16.existsSync(path27.join(cwd, "Gemfile"));
|
|
41710
|
+
const hasSpecDir = fs16.existsSync(path27.join(cwd, "spec"));
|
|
41560
41711
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
41561
41712
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
41562
41713
|
}
|
|
41563
41714
|
function detectMinitest(cwd) {
|
|
41564
|
-
return
|
|
41715
|
+
return fs16.existsSync(path27.join(cwd, "test")) && (fs16.existsSync(path27.join(cwd, "Gemfile")) || fs16.existsSync(path27.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
41565
41716
|
}
|
|
41566
41717
|
async function detectTestFramework(cwd) {
|
|
41567
41718
|
const baseDir = cwd;
|
|
41568
41719
|
try {
|
|
41569
|
-
const packageJsonPath =
|
|
41570
|
-
if (
|
|
41571
|
-
const content =
|
|
41720
|
+
const packageJsonPath = path27.join(baseDir, "package.json");
|
|
41721
|
+
if (fs16.existsSync(packageJsonPath)) {
|
|
41722
|
+
const content = fs16.readFileSync(packageJsonPath, "utf-8");
|
|
41572
41723
|
const pkg = JSON.parse(content);
|
|
41573
41724
|
const _deps = pkg.dependencies || {};
|
|
41574
41725
|
const devDeps = pkg.devDependencies || {};
|
|
@@ -41587,38 +41738,38 @@ async function detectTestFramework(cwd) {
|
|
|
41587
41738
|
return "jest";
|
|
41588
41739
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
41589
41740
|
return "mocha";
|
|
41590
|
-
if (
|
|
41741
|
+
if (fs16.existsSync(path27.join(baseDir, "bun.lockb")) || fs16.existsSync(path27.join(baseDir, "bun.lock"))) {
|
|
41591
41742
|
if (scripts.test?.includes("bun"))
|
|
41592
41743
|
return "bun";
|
|
41593
41744
|
}
|
|
41594
41745
|
}
|
|
41595
41746
|
} catch {}
|
|
41596
41747
|
try {
|
|
41597
|
-
const pyprojectTomlPath =
|
|
41598
|
-
const setupCfgPath =
|
|
41599
|
-
const requirementsTxtPath =
|
|
41600
|
-
if (
|
|
41601
|
-
const content =
|
|
41748
|
+
const pyprojectTomlPath = path27.join(baseDir, "pyproject.toml");
|
|
41749
|
+
const setupCfgPath = path27.join(baseDir, "setup.cfg");
|
|
41750
|
+
const requirementsTxtPath = path27.join(baseDir, "requirements.txt");
|
|
41751
|
+
if (fs16.existsSync(pyprojectTomlPath)) {
|
|
41752
|
+
const content = fs16.readFileSync(pyprojectTomlPath, "utf-8");
|
|
41602
41753
|
if (content.includes("[tool.pytest"))
|
|
41603
41754
|
return "pytest";
|
|
41604
41755
|
if (content.includes("pytest"))
|
|
41605
41756
|
return "pytest";
|
|
41606
41757
|
}
|
|
41607
|
-
if (
|
|
41608
|
-
const content =
|
|
41758
|
+
if (fs16.existsSync(setupCfgPath)) {
|
|
41759
|
+
const content = fs16.readFileSync(setupCfgPath, "utf-8");
|
|
41609
41760
|
if (content.includes("[pytest]"))
|
|
41610
41761
|
return "pytest";
|
|
41611
41762
|
}
|
|
41612
|
-
if (
|
|
41613
|
-
const content =
|
|
41763
|
+
if (fs16.existsSync(requirementsTxtPath)) {
|
|
41764
|
+
const content = fs16.readFileSync(requirementsTxtPath, "utf-8");
|
|
41614
41765
|
if (content.includes("pytest"))
|
|
41615
41766
|
return "pytest";
|
|
41616
41767
|
}
|
|
41617
41768
|
} catch {}
|
|
41618
41769
|
try {
|
|
41619
|
-
const cargoTomlPath =
|
|
41620
|
-
if (
|
|
41621
|
-
const content =
|
|
41770
|
+
const cargoTomlPath = path27.join(baseDir, "Cargo.toml");
|
|
41771
|
+
if (fs16.existsSync(cargoTomlPath)) {
|
|
41772
|
+
const content = fs16.readFileSync(cargoTomlPath, "utf-8");
|
|
41622
41773
|
if (content.includes("[dev-dependencies]")) {
|
|
41623
41774
|
if (content.includes("tokio") || content.includes("mockall") || content.includes("pretty_assertions")) {
|
|
41624
41775
|
return "cargo";
|
|
@@ -41627,10 +41778,10 @@ async function detectTestFramework(cwd) {
|
|
|
41627
41778
|
}
|
|
41628
41779
|
} catch {}
|
|
41629
41780
|
try {
|
|
41630
|
-
const pesterConfigPath =
|
|
41631
|
-
const pesterConfigJsonPath =
|
|
41632
|
-
const pesterPs1Path =
|
|
41633
|
-
if (
|
|
41781
|
+
const pesterConfigPath = path27.join(baseDir, "pester.config.ps1");
|
|
41782
|
+
const pesterConfigJsonPath = path27.join(baseDir, "pester.config.ps1.json");
|
|
41783
|
+
const pesterPs1Path = path27.join(baseDir, "tests.ps1");
|
|
41784
|
+
if (fs16.existsSync(pesterConfigPath) || fs16.existsSync(pesterConfigJsonPath) || fs16.existsSync(pesterPs1Path)) {
|
|
41634
41785
|
return "pester";
|
|
41635
41786
|
}
|
|
41636
41787
|
} catch {}
|
|
@@ -41672,12 +41823,12 @@ function isTestDirectoryPath(normalizedPath) {
|
|
|
41672
41823
|
return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
|
|
41673
41824
|
}
|
|
41674
41825
|
function resolveWorkspacePath(file3, workingDir) {
|
|
41675
|
-
return
|
|
41826
|
+
return path27.isAbsolute(file3) ? path27.resolve(file3) : path27.resolve(workingDir, file3);
|
|
41676
41827
|
}
|
|
41677
41828
|
function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
|
|
41678
41829
|
if (!preferRelative)
|
|
41679
41830
|
return absolutePath;
|
|
41680
|
-
return
|
|
41831
|
+
return path27.relative(workingDir, absolutePath);
|
|
41681
41832
|
}
|
|
41682
41833
|
function dedupePush(target, value) {
|
|
41683
41834
|
if (!target.includes(value)) {
|
|
@@ -41714,18 +41865,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
|
|
|
41714
41865
|
}
|
|
41715
41866
|
}
|
|
41716
41867
|
function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
|
|
41717
|
-
const relativeDir =
|
|
41868
|
+
const relativeDir = path27.dirname(relativePath);
|
|
41718
41869
|
const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
|
|
41719
41870
|
const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
|
|
41720
|
-
const rootDir =
|
|
41721
|
-
return nestedRelativeDir ? [rootDir,
|
|
41871
|
+
const rootDir = path27.join(workingDir, dirName);
|
|
41872
|
+
return nestedRelativeDir ? [rootDir, path27.join(rootDir, nestedRelativeDir)] : [rootDir];
|
|
41722
41873
|
});
|
|
41723
41874
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
41724
41875
|
if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
|
|
41725
|
-
directories.push(
|
|
41876
|
+
directories.push(path27.join(workingDir, "src/test/java", path27.dirname(normalizedRelativePath.slice("src/main/java/".length))));
|
|
41726
41877
|
}
|
|
41727
41878
|
if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
|
|
41728
|
-
directories.push(
|
|
41879
|
+
directories.push(path27.join(workingDir, "src/test/kotlin", path27.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
|
|
41729
41880
|
}
|
|
41730
41881
|
return [...new Set(directories)];
|
|
41731
41882
|
}
|
|
@@ -41753,23 +41904,23 @@ function isLanguageSpecificTestFile(basename4) {
|
|
|
41753
41904
|
}
|
|
41754
41905
|
function isConventionTestFilePath(filePath) {
|
|
41755
41906
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
41756
|
-
const basename4 =
|
|
41907
|
+
const basename4 = path27.basename(filePath);
|
|
41757
41908
|
return hasCompoundTestExtension(basename4) || basename4.includes(".spec.") || basename4.includes(".test.") || isLanguageSpecificTestFile(basename4) || isTestDirectoryPath(normalizedPath);
|
|
41758
41909
|
}
|
|
41759
41910
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
41760
41911
|
const testFiles = [];
|
|
41761
41912
|
for (const file3 of sourceFiles) {
|
|
41762
41913
|
const absoluteFile = resolveWorkspacePath(file3, workingDir);
|
|
41763
|
-
const relativeFile =
|
|
41764
|
-
const basename4 =
|
|
41765
|
-
const dirname11 =
|
|
41766
|
-
const preferRelativeOutput = !
|
|
41914
|
+
const relativeFile = path27.relative(workingDir, absoluteFile);
|
|
41915
|
+
const basename4 = path27.basename(absoluteFile);
|
|
41916
|
+
const dirname11 = path27.dirname(absoluteFile);
|
|
41917
|
+
const preferRelativeOutput = !path27.isAbsolute(file3);
|
|
41767
41918
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
|
|
41768
41919
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
41769
41920
|
continue;
|
|
41770
41921
|
}
|
|
41771
41922
|
const nameWithoutExt = basename4.replace(/\.[^.]+$/, "");
|
|
41772
|
-
const ext =
|
|
41923
|
+
const ext = path27.extname(basename4);
|
|
41773
41924
|
const genericTestNames = [
|
|
41774
41925
|
`${nameWithoutExt}.spec${ext}`,
|
|
41775
41926
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -41778,7 +41929,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
41778
41929
|
const colocatedCandidates = [
|
|
41779
41930
|
...genericTestNames,
|
|
41780
41931
|
...languageSpecificTestNames
|
|
41781
|
-
].map((candidateName) =>
|
|
41932
|
+
].map((candidateName) => path27.join(dirname11, candidateName));
|
|
41782
41933
|
const testDirectoryNames = [
|
|
41783
41934
|
basename4,
|
|
41784
41935
|
...genericTestNames,
|
|
@@ -41787,11 +41938,11 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
41787
41938
|
const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
|
|
41788
41939
|
const possibleTestFiles = [
|
|
41789
41940
|
...colocatedCandidates,
|
|
41790
|
-
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) =>
|
|
41791
|
-
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) =>
|
|
41941
|
+
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path27.join(dirname11, dirName, candidateName))),
|
|
41942
|
+
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path27.join(candidateDir, candidateName)))
|
|
41792
41943
|
];
|
|
41793
41944
|
for (const testFile of possibleTestFiles) {
|
|
41794
|
-
if (
|
|
41945
|
+
if (fs16.existsSync(testFile)) {
|
|
41795
41946
|
dedupePush(testFiles, toWorkspaceOutputPath(testFile, workingDir, preferRelativeOutput));
|
|
41796
41947
|
}
|
|
41797
41948
|
}
|
|
@@ -41808,8 +41959,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
41808
41959
|
for (const testFile of candidateTestFiles) {
|
|
41809
41960
|
try {
|
|
41810
41961
|
const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
|
|
41811
|
-
const content =
|
|
41812
|
-
const testDir =
|
|
41962
|
+
const content = fs16.readFileSync(absoluteTestFile, "utf-8");
|
|
41963
|
+
const testDir = path27.dirname(absoluteTestFile);
|
|
41813
41964
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
41814
41965
|
let match;
|
|
41815
41966
|
match = importRegex.exec(content);
|
|
@@ -41817,8 +41968,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
41817
41968
|
const importPath = match[1];
|
|
41818
41969
|
let resolvedImport;
|
|
41819
41970
|
if (importPath.startsWith(".")) {
|
|
41820
|
-
resolvedImport =
|
|
41821
|
-
const existingExt =
|
|
41971
|
+
resolvedImport = path27.resolve(testDir, importPath);
|
|
41972
|
+
const existingExt = path27.extname(resolvedImport);
|
|
41822
41973
|
if (!existingExt) {
|
|
41823
41974
|
for (const extToTry of [
|
|
41824
41975
|
".ts",
|
|
@@ -41829,7 +41980,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
41829
41980
|
".cjs"
|
|
41830
41981
|
]) {
|
|
41831
41982
|
const withExt = resolvedImport + extToTry;
|
|
41832
|
-
if (absoluteSourceFiles.includes(withExt) ||
|
|
41983
|
+
if (absoluteSourceFiles.includes(withExt) || fs16.existsSync(withExt)) {
|
|
41833
41984
|
resolvedImport = withExt;
|
|
41834
41985
|
break;
|
|
41835
41986
|
}
|
|
@@ -41838,12 +41989,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
41838
41989
|
} else {
|
|
41839
41990
|
continue;
|
|
41840
41991
|
}
|
|
41841
|
-
const importBasename =
|
|
41842
|
-
const importDir =
|
|
41992
|
+
const importBasename = path27.basename(resolvedImport, path27.extname(resolvedImport));
|
|
41993
|
+
const importDir = path27.dirname(resolvedImport);
|
|
41843
41994
|
for (const sourceFile of absoluteSourceFiles) {
|
|
41844
|
-
const sourceDir =
|
|
41845
|
-
const sourceBasename =
|
|
41846
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
41995
|
+
const sourceDir = path27.dirname(sourceFile);
|
|
41996
|
+
const sourceBasename = path27.basename(sourceFile, path27.extname(sourceFile));
|
|
41997
|
+
const isRelatedDir = importDir === sourceDir || importDir === path27.join(sourceDir, "__tests__") || importDir === path27.join(sourceDir, "tests") || importDir === path27.join(sourceDir, "test") || importDir === path27.join(sourceDir, "spec");
|
|
41847
41998
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
41848
41999
|
dedupePush(testFiles, testFile);
|
|
41849
42000
|
break;
|
|
@@ -41856,8 +42007,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
41856
42007
|
while (match !== null) {
|
|
41857
42008
|
const importPath = match[1];
|
|
41858
42009
|
if (importPath.startsWith(".")) {
|
|
41859
|
-
let resolvedImport =
|
|
41860
|
-
const existingExt =
|
|
42010
|
+
let resolvedImport = path27.resolve(testDir, importPath);
|
|
42011
|
+
const existingExt = path27.extname(resolvedImport);
|
|
41861
42012
|
if (!existingExt) {
|
|
41862
42013
|
for (const extToTry of [
|
|
41863
42014
|
".ts",
|
|
@@ -41868,18 +42019,18 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
41868
42019
|
".cjs"
|
|
41869
42020
|
]) {
|
|
41870
42021
|
const withExt = resolvedImport + extToTry;
|
|
41871
|
-
if (absoluteSourceFiles.includes(withExt) ||
|
|
42022
|
+
if (absoluteSourceFiles.includes(withExt) || fs16.existsSync(withExt)) {
|
|
41872
42023
|
resolvedImport = withExt;
|
|
41873
42024
|
break;
|
|
41874
42025
|
}
|
|
41875
42026
|
}
|
|
41876
42027
|
}
|
|
41877
|
-
const importDir =
|
|
41878
|
-
const importBasename =
|
|
42028
|
+
const importDir = path27.dirname(resolvedImport);
|
|
42029
|
+
const importBasename = path27.basename(resolvedImport, path27.extname(resolvedImport));
|
|
41879
42030
|
for (const sourceFile of absoluteSourceFiles) {
|
|
41880
|
-
const sourceDir =
|
|
41881
|
-
const sourceBasename =
|
|
41882
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
42031
|
+
const sourceDir = path27.dirname(sourceFile);
|
|
42032
|
+
const sourceBasename = path27.basename(sourceFile, path27.extname(sourceFile));
|
|
42033
|
+
const isRelatedDir = importDir === sourceDir || importDir === path27.join(sourceDir, "__tests__") || importDir === path27.join(sourceDir, "tests") || importDir === path27.join(sourceDir, "test") || importDir === path27.join(sourceDir, "spec");
|
|
41883
42034
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
41884
42035
|
dedupePush(testFiles, testFile);
|
|
41885
42036
|
break;
|
|
@@ -41982,8 +42133,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
41982
42133
|
return ["mvn", "test"];
|
|
41983
42134
|
case "gradle": {
|
|
41984
42135
|
const isWindows = process.platform === "win32";
|
|
41985
|
-
const hasGradlewBat =
|
|
41986
|
-
const hasGradlew =
|
|
42136
|
+
const hasGradlewBat = fs16.existsSync(path27.join(baseDir, "gradlew.bat"));
|
|
42137
|
+
const hasGradlew = fs16.existsSync(path27.join(baseDir, "gradlew"));
|
|
41987
42138
|
if (hasGradlewBat && isWindows)
|
|
41988
42139
|
return ["gradlew.bat", "test"];
|
|
41989
42140
|
if (hasGradlew)
|
|
@@ -42000,7 +42151,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
|
|
|
42000
42151
|
"cmake-build-release",
|
|
42001
42152
|
"out"
|
|
42002
42153
|
];
|
|
42003
|
-
const actualBuildDir = buildDirCandidates.find((d) =>
|
|
42154
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(path27.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
42004
42155
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
42005
42156
|
}
|
|
42006
42157
|
case "swift-test":
|
|
@@ -42628,7 +42779,7 @@ var test_runner = createSwarmTool({
|
|
|
42628
42779
|
const sourceFiles = args.files.filter((file3) => {
|
|
42629
42780
|
if (directTestFiles.includes(file3))
|
|
42630
42781
|
return false;
|
|
42631
|
-
const ext =
|
|
42782
|
+
const ext = path27.extname(file3).toLowerCase();
|
|
42632
42783
|
return SOURCE_EXTENSIONS.has(ext);
|
|
42633
42784
|
});
|
|
42634
42785
|
const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
|
|
@@ -42663,7 +42814,7 @@ var test_runner = createSwarmTool({
|
|
|
42663
42814
|
if (isConventionTestFilePath(f)) {
|
|
42664
42815
|
return false;
|
|
42665
42816
|
}
|
|
42666
|
-
const ext =
|
|
42817
|
+
const ext = path27.extname(f).toLowerCase();
|
|
42667
42818
|
return SOURCE_EXTENSIONS.has(ext);
|
|
42668
42819
|
});
|
|
42669
42820
|
if (sourceFiles.length === 0) {
|
|
@@ -42690,7 +42841,7 @@ var test_runner = createSwarmTool({
|
|
|
42690
42841
|
if (isConventionTestFilePath(f)) {
|
|
42691
42842
|
return false;
|
|
42692
42843
|
}
|
|
42693
|
-
const ext =
|
|
42844
|
+
const ext = path27.extname(f).toLowerCase();
|
|
42694
42845
|
return SOURCE_EXTENSIONS.has(ext);
|
|
42695
42846
|
});
|
|
42696
42847
|
if (sourceFiles.length === 0) {
|
|
@@ -42708,8 +42859,8 @@ var test_runner = createSwarmTool({
|
|
|
42708
42859
|
const impactResult = await analyzeImpact(sourceFiles, workingDir);
|
|
42709
42860
|
if (impactResult.impactedTests.length > 0) {
|
|
42710
42861
|
testFiles = impactResult.impactedTests.map((absPath) => {
|
|
42711
|
-
const relativePath =
|
|
42712
|
-
return
|
|
42862
|
+
const relativePath = path27.relative(workingDir, absPath);
|
|
42863
|
+
return path27.isAbsolute(relativePath) ? absPath : relativePath;
|
|
42713
42864
|
});
|
|
42714
42865
|
} else {
|
|
42715
42866
|
graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
|
|
@@ -42802,8 +42953,8 @@ function validateDirectoryPath(dir) {
|
|
|
42802
42953
|
if (dir.includes("..")) {
|
|
42803
42954
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
42804
42955
|
}
|
|
42805
|
-
const normalized =
|
|
42806
|
-
const absolutePath =
|
|
42956
|
+
const normalized = path28.normalize(dir);
|
|
42957
|
+
const absolutePath = path28.isAbsolute(normalized) ? normalized : path28.resolve(normalized);
|
|
42807
42958
|
return absolutePath;
|
|
42808
42959
|
}
|
|
42809
42960
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -42826,9 +42977,9 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
42826
42977
|
}
|
|
42827
42978
|
function getPackageVersion(dir) {
|
|
42828
42979
|
try {
|
|
42829
|
-
const packagePath =
|
|
42830
|
-
if (
|
|
42831
|
-
const content =
|
|
42980
|
+
const packagePath = path28.join(dir, "package.json");
|
|
42981
|
+
if (fs17.existsSync(packagePath)) {
|
|
42982
|
+
const content = fs17.readFileSync(packagePath, "utf-8");
|
|
42832
42983
|
const pkg = JSON.parse(content);
|
|
42833
42984
|
return pkg.version ?? null;
|
|
42834
42985
|
}
|
|
@@ -42837,9 +42988,9 @@ function getPackageVersion(dir) {
|
|
|
42837
42988
|
}
|
|
42838
42989
|
function getChangelogVersion(dir) {
|
|
42839
42990
|
try {
|
|
42840
|
-
const changelogPath =
|
|
42841
|
-
if (
|
|
42842
|
-
const content =
|
|
42991
|
+
const changelogPath = path28.join(dir, "CHANGELOG.md");
|
|
42992
|
+
if (fs17.existsSync(changelogPath)) {
|
|
42993
|
+
const content = fs17.readFileSync(changelogPath, "utf-8");
|
|
42843
42994
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
42844
42995
|
if (match) {
|
|
42845
42996
|
return match[1];
|
|
@@ -42851,10 +43002,10 @@ function getChangelogVersion(dir) {
|
|
|
42851
43002
|
function getVersionFileVersion(dir) {
|
|
42852
43003
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
42853
43004
|
for (const file3 of possibleFiles) {
|
|
42854
|
-
const filePath =
|
|
42855
|
-
if (
|
|
43005
|
+
const filePath = path28.join(dir, file3);
|
|
43006
|
+
if (fs17.existsSync(filePath)) {
|
|
42856
43007
|
try {
|
|
42857
|
-
const content =
|
|
43008
|
+
const content = fs17.readFileSync(filePath, "utf-8").trim();
|
|
42858
43009
|
const match = content.match(/(\d+\.\d+\.\d+)/);
|
|
42859
43010
|
if (match) {
|
|
42860
43011
|
return match[1];
|
|
@@ -43178,8 +43329,8 @@ async function runEvidenceCheck(dir) {
|
|
|
43178
43329
|
async function runRequirementCoverageCheck(dir, currentPhase) {
|
|
43179
43330
|
const startTime = Date.now();
|
|
43180
43331
|
try {
|
|
43181
|
-
const specPath =
|
|
43182
|
-
if (!
|
|
43332
|
+
const specPath = path28.join(dir, ".swarm", "spec.md");
|
|
43333
|
+
if (!fs17.existsSync(specPath)) {
|
|
43183
43334
|
return {
|
|
43184
43335
|
type: "req_coverage",
|
|
43185
43336
|
status: "skip",
|
|
@@ -43560,7 +43711,7 @@ async function handleQaGatesCommand(directory, args, sessionID) {
|
|
|
43560
43711
|
}
|
|
43561
43712
|
|
|
43562
43713
|
// src/commands/reset.ts
|
|
43563
|
-
import * as
|
|
43714
|
+
import * as fs18 from "fs";
|
|
43564
43715
|
|
|
43565
43716
|
// src/background/manager.ts
|
|
43566
43717
|
init_utils();
|
|
@@ -44261,8 +44412,8 @@ async function handleResetCommand(directory, args) {
|
|
|
44261
44412
|
for (const filename of filesToReset) {
|
|
44262
44413
|
try {
|
|
44263
44414
|
const resolvedPath = validateSwarmPath(directory, filename);
|
|
44264
|
-
if (
|
|
44265
|
-
|
|
44415
|
+
if (fs18.existsSync(resolvedPath)) {
|
|
44416
|
+
fs18.unlinkSync(resolvedPath);
|
|
44266
44417
|
results.push(`- \u2705 Deleted ${filename}`);
|
|
44267
44418
|
} else {
|
|
44268
44419
|
results.push(`- \u23ED\uFE0F ${filename} not found (skipped)`);
|
|
@@ -44279,8 +44430,8 @@ async function handleResetCommand(directory, args) {
|
|
|
44279
44430
|
}
|
|
44280
44431
|
try {
|
|
44281
44432
|
const summariesPath = validateSwarmPath(directory, "summaries");
|
|
44282
|
-
if (
|
|
44283
|
-
|
|
44433
|
+
if (fs18.existsSync(summariesPath)) {
|
|
44434
|
+
fs18.rmSync(summariesPath, { recursive: true, force: true });
|
|
44284
44435
|
results.push("- \u2705 Deleted summaries/ directory");
|
|
44285
44436
|
} else {
|
|
44286
44437
|
results.push("- \u23ED\uFE0F summaries/ not found (skipped)");
|
|
@@ -44300,14 +44451,14 @@ async function handleResetCommand(directory, args) {
|
|
|
44300
44451
|
|
|
44301
44452
|
// src/commands/reset-session.ts
|
|
44302
44453
|
init_utils2();
|
|
44303
|
-
import * as
|
|
44304
|
-
import * as
|
|
44454
|
+
import * as fs19 from "fs";
|
|
44455
|
+
import * as path29 from "path";
|
|
44305
44456
|
async function handleResetSessionCommand(directory, _args) {
|
|
44306
44457
|
const results = [];
|
|
44307
44458
|
try {
|
|
44308
44459
|
const statePath = validateSwarmPath(directory, "session/state.json");
|
|
44309
|
-
if (
|
|
44310
|
-
|
|
44460
|
+
if (fs19.existsSync(statePath)) {
|
|
44461
|
+
fs19.unlinkSync(statePath);
|
|
44311
44462
|
results.push("\u2705 Deleted .swarm/session/state.json");
|
|
44312
44463
|
} else {
|
|
44313
44464
|
results.push("\u23ED\uFE0F state.json not found (already clean)");
|
|
@@ -44316,15 +44467,15 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
44316
44467
|
results.push("\u274C Failed to delete state.json");
|
|
44317
44468
|
}
|
|
44318
44469
|
try {
|
|
44319
|
-
const sessionDir =
|
|
44320
|
-
if (
|
|
44321
|
-
const files =
|
|
44470
|
+
const sessionDir = path29.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
44471
|
+
if (fs19.existsSync(sessionDir)) {
|
|
44472
|
+
const files = fs19.readdirSync(sessionDir);
|
|
44322
44473
|
const otherFiles = files.filter((f) => f !== "state.json");
|
|
44323
44474
|
let deletedCount = 0;
|
|
44324
44475
|
for (const file3 of otherFiles) {
|
|
44325
|
-
const filePath =
|
|
44326
|
-
if (
|
|
44327
|
-
|
|
44476
|
+
const filePath = path29.join(sessionDir, file3);
|
|
44477
|
+
if (fs19.lstatSync(filePath).isFile()) {
|
|
44478
|
+
fs19.unlinkSync(filePath);
|
|
44328
44479
|
deletedCount++;
|
|
44329
44480
|
}
|
|
44330
44481
|
}
|
|
@@ -44352,7 +44503,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
44352
44503
|
// src/summaries/manager.ts
|
|
44353
44504
|
init_utils2();
|
|
44354
44505
|
init_utils();
|
|
44355
|
-
import * as
|
|
44506
|
+
import * as path30 from "path";
|
|
44356
44507
|
var SUMMARY_ID_REGEX = /^S\d+$/;
|
|
44357
44508
|
function sanitizeSummaryId(id) {
|
|
44358
44509
|
if (!id || id.length === 0) {
|
|
@@ -44376,7 +44527,7 @@ function sanitizeSummaryId(id) {
|
|
|
44376
44527
|
}
|
|
44377
44528
|
async function loadFullOutput(directory, id) {
|
|
44378
44529
|
const sanitizedId = sanitizeSummaryId(id);
|
|
44379
|
-
const relativePath =
|
|
44530
|
+
const relativePath = path30.join("summaries", `${sanitizedId}.json`);
|
|
44380
44531
|
validateSwarmPath(directory, relativePath);
|
|
44381
44532
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
44382
44533
|
if (content === null) {
|
|
@@ -44431,18 +44582,18 @@ ${error93 instanceof Error ? error93.message : String(error93)}`;
|
|
|
44431
44582
|
init_plan_schema();
|
|
44432
44583
|
init_utils2();
|
|
44433
44584
|
init_ledger();
|
|
44434
|
-
import * as
|
|
44435
|
-
import * as
|
|
44585
|
+
import * as fs20 from "fs";
|
|
44586
|
+
import * as path31 from "path";
|
|
44436
44587
|
async function handleRollbackCommand(directory, args) {
|
|
44437
44588
|
const phaseArg = args[0];
|
|
44438
44589
|
if (!phaseArg) {
|
|
44439
44590
|
const manifestPath2 = validateSwarmPath(directory, "checkpoints/manifest.json");
|
|
44440
|
-
if (!
|
|
44591
|
+
if (!fs20.existsSync(manifestPath2)) {
|
|
44441
44592
|
return "No checkpoints found. Use `/swarm checkpoint` to create checkpoints.";
|
|
44442
44593
|
}
|
|
44443
44594
|
let manifest2;
|
|
44444
44595
|
try {
|
|
44445
|
-
manifest2 = JSON.parse(
|
|
44596
|
+
manifest2 = JSON.parse(fs20.readFileSync(manifestPath2, "utf-8"));
|
|
44446
44597
|
} catch {
|
|
44447
44598
|
return "Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.";
|
|
44448
44599
|
}
|
|
@@ -44464,12 +44615,12 @@ async function handleRollbackCommand(directory, args) {
|
|
|
44464
44615
|
return "Error: Phase number must be a positive integer.";
|
|
44465
44616
|
}
|
|
44466
44617
|
const manifestPath = validateSwarmPath(directory, "checkpoints/manifest.json");
|
|
44467
|
-
if (!
|
|
44618
|
+
if (!fs20.existsSync(manifestPath)) {
|
|
44468
44619
|
return `Error: No checkpoints found. Cannot rollback to phase ${targetPhase}.`;
|
|
44469
44620
|
}
|
|
44470
44621
|
let manifest;
|
|
44471
44622
|
try {
|
|
44472
|
-
manifest = JSON.parse(
|
|
44623
|
+
manifest = JSON.parse(fs20.readFileSync(manifestPath, "utf-8"));
|
|
44473
44624
|
} catch {
|
|
44474
44625
|
return `Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.`;
|
|
44475
44626
|
}
|
|
@@ -44479,10 +44630,10 @@ async function handleRollbackCommand(directory, args) {
|
|
|
44479
44630
|
return `Error: Checkpoint for phase ${targetPhase} not found. Available phases: ${available}`;
|
|
44480
44631
|
}
|
|
44481
44632
|
const checkpointDir = validateSwarmPath(directory, `checkpoints/phase-${targetPhase}`);
|
|
44482
|
-
if (!
|
|
44633
|
+
if (!fs20.existsSync(checkpointDir)) {
|
|
44483
44634
|
return `Error: Checkpoint directory for phase ${targetPhase} does not exist.`;
|
|
44484
44635
|
}
|
|
44485
|
-
const checkpointFiles =
|
|
44636
|
+
const checkpointFiles = fs20.readdirSync(checkpointDir);
|
|
44486
44637
|
if (checkpointFiles.length === 0) {
|
|
44487
44638
|
return `Error: Checkpoint for phase ${targetPhase} is empty. Cannot rollback.`;
|
|
44488
44639
|
}
|
|
@@ -44497,10 +44648,10 @@ async function handleRollbackCommand(directory, args) {
|
|
|
44497
44648
|
if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
|
|
44498
44649
|
continue;
|
|
44499
44650
|
}
|
|
44500
|
-
const src =
|
|
44501
|
-
const dest =
|
|
44651
|
+
const src = path31.join(checkpointDir, file3);
|
|
44652
|
+
const dest = path31.join(swarmDir, file3);
|
|
44502
44653
|
try {
|
|
44503
|
-
|
|
44654
|
+
fs20.cpSync(src, dest, { recursive: true, force: true });
|
|
44504
44655
|
successes.push(file3);
|
|
44505
44656
|
} catch (error93) {
|
|
44506
44657
|
failures.push({ file: file3, error: error93.message });
|
|
@@ -44517,14 +44668,14 @@ async function handleRollbackCommand(directory, args) {
|
|
|
44517
44668
|
].join(`
|
|
44518
44669
|
`);
|
|
44519
44670
|
}
|
|
44520
|
-
const existingLedgerPath =
|
|
44521
|
-
if (
|
|
44522
|
-
|
|
44671
|
+
const existingLedgerPath = path31.join(swarmDir, "plan-ledger.jsonl");
|
|
44672
|
+
if (fs20.existsSync(existingLedgerPath)) {
|
|
44673
|
+
fs20.unlinkSync(existingLedgerPath);
|
|
44523
44674
|
}
|
|
44524
44675
|
try {
|
|
44525
|
-
const planJsonPath =
|
|
44526
|
-
if (
|
|
44527
|
-
const planRaw =
|
|
44676
|
+
const planJsonPath = path31.join(swarmDir, "plan.json");
|
|
44677
|
+
if (fs20.existsSync(planJsonPath)) {
|
|
44678
|
+
const planRaw = fs20.readFileSync(planJsonPath, "utf-8");
|
|
44528
44679
|
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
44529
44680
|
const planId = `${plan.swarm}-${plan.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
|
|
44530
44681
|
const planHash = computePlanHash(plan);
|
|
@@ -44551,7 +44702,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
44551
44702
|
timestamp: new Date().toISOString()
|
|
44552
44703
|
};
|
|
44553
44704
|
try {
|
|
44554
|
-
|
|
44705
|
+
fs20.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
|
|
44555
44706
|
`);
|
|
44556
44707
|
} catch (error93) {
|
|
44557
44708
|
console.error("Failed to write rollback event:", error93 instanceof Error ? error93.message : String(error93));
|
|
@@ -44594,11 +44745,11 @@ async function handleSimulateCommand(directory, args) {
|
|
|
44594
44745
|
];
|
|
44595
44746
|
const report = reportLines.filter(Boolean).join(`
|
|
44596
44747
|
`);
|
|
44597
|
-
const
|
|
44598
|
-
const
|
|
44599
|
-
const reportPath =
|
|
44600
|
-
await
|
|
44601
|
-
await
|
|
44748
|
+
const fs21 = await import("fs/promises");
|
|
44749
|
+
const path32 = await import("path");
|
|
44750
|
+
const reportPath = path32.join(directory, ".swarm", "simulate-report.md");
|
|
44751
|
+
await fs21.mkdir(path32.dirname(reportPath), { recursive: true });
|
|
44752
|
+
await fs21.writeFile(reportPath, report, "utf-8");
|
|
44602
44753
|
return `${darkMatterPairs.length} hidden coupling pairs detected`;
|
|
44603
44754
|
}
|
|
44604
44755
|
|
|
@@ -45131,19 +45282,20 @@ function resolveCommand(tokens) {
|
|
|
45131
45282
|
}
|
|
45132
45283
|
|
|
45133
45284
|
// src/cli/index.ts
|
|
45134
|
-
var
|
|
45135
|
-
var
|
|
45136
|
-
var
|
|
45137
|
-
var
|
|
45138
|
-
var
|
|
45285
|
+
var { version: version4 } = package_default;
|
|
45286
|
+
var CONFIG_DIR = path32.join(process.env.XDG_CONFIG_HOME || path32.join(os6.homedir(), ".config"), "opencode");
|
|
45287
|
+
var OPENCODE_CONFIG_PATH = path32.join(CONFIG_DIR, "opencode.json");
|
|
45288
|
+
var PLUGIN_CONFIG_PATH = path32.join(CONFIG_DIR, "opencode-swarm.json");
|
|
45289
|
+
var PROMPTS_DIR = path32.join(CONFIG_DIR, "opencode-swarm");
|
|
45290
|
+
var OPENCODE_PLUGIN_CACHE_PATH = path32.join(process.env.XDG_CACHE_HOME || path32.join(os6.homedir(), ".cache"), "opencode", "packages", "opencode-swarm@latest");
|
|
45139
45291
|
function ensureDir(dir) {
|
|
45140
|
-
if (!
|
|
45141
|
-
|
|
45292
|
+
if (!fs21.existsSync(dir)) {
|
|
45293
|
+
fs21.mkdirSync(dir, { recursive: true });
|
|
45142
45294
|
}
|
|
45143
45295
|
}
|
|
45144
45296
|
function loadJson(filepath) {
|
|
45145
45297
|
try {
|
|
45146
|
-
const content =
|
|
45298
|
+
const content = fs21.readFileSync(filepath, "utf-8");
|
|
45147
45299
|
const stripped = content.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (match, comment) => comment ? "" : match).replace(/,(\s*[}\]])/g, "$1");
|
|
45148
45300
|
return JSON.parse(stripped);
|
|
45149
45301
|
} catch {
|
|
@@ -45151,15 +45303,31 @@ function loadJson(filepath) {
|
|
|
45151
45303
|
}
|
|
45152
45304
|
}
|
|
45153
45305
|
function saveJson(filepath, data) {
|
|
45154
|
-
|
|
45306
|
+
fs21.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
|
|
45155
45307
|
`, "utf-8");
|
|
45156
45308
|
}
|
|
45309
|
+
function writeProjectConfigIfMissing(cwd) {
|
|
45310
|
+
try {
|
|
45311
|
+
const opencodeDir = path32.join(cwd, ".opencode");
|
|
45312
|
+
const projectConfigPath = path32.join(opencodeDir, "opencode-swarm.json");
|
|
45313
|
+
if (fs21.existsSync(projectConfigPath)) {
|
|
45314
|
+
return;
|
|
45315
|
+
}
|
|
45316
|
+
ensureDir(opencodeDir);
|
|
45317
|
+
const starterConfig = { agents: {} };
|
|
45318
|
+
saveJson(projectConfigPath, starterConfig);
|
|
45319
|
+
console.log("\u2713 Created project config at:", projectConfigPath);
|
|
45320
|
+
} catch (error93) {
|
|
45321
|
+
console.warn("\u26A0 Could not create project config \u2014 installation will continue:");
|
|
45322
|
+
console.warn(` ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
45323
|
+
}
|
|
45324
|
+
}
|
|
45157
45325
|
async function install() {
|
|
45158
45326
|
console.log(`\uD83D\uDC1D Installing OpenCode Swarm...
|
|
45159
45327
|
`);
|
|
45160
45328
|
ensureDir(CONFIG_DIR);
|
|
45161
45329
|
ensureDir(PROMPTS_DIR);
|
|
45162
|
-
const LEGACY_CONFIG_PATH =
|
|
45330
|
+
const LEGACY_CONFIG_PATH = path32.join(CONFIG_DIR, "config.json");
|
|
45163
45331
|
let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
|
|
45164
45332
|
if (!opencodeConfig) {
|
|
45165
45333
|
const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
|
|
@@ -45191,15 +45359,15 @@ async function install() {
|
|
|
45191
45359
|
console.log("\u2713 Added opencode-swarm to OpenCode plugins");
|
|
45192
45360
|
console.log("\u2713 Disabled default OpenCode agents (explore, general)");
|
|
45193
45361
|
try {
|
|
45194
|
-
if (
|
|
45195
|
-
|
|
45362
|
+
if (fs21.existsSync(OPENCODE_PLUGIN_CACHE_PATH)) {
|
|
45363
|
+
fs21.rmSync(OPENCODE_PLUGIN_CACHE_PATH, { recursive: true, force: true });
|
|
45196
45364
|
console.log("\u2713 Cleared opencode plugin cache (next start will fetch latest)");
|
|
45197
45365
|
}
|
|
45198
45366
|
} catch {
|
|
45199
45367
|
console.warn("\u26A0 Could not clear opencode plugin cache \u2014 you may need to delete it manually:");
|
|
45200
45368
|
console.warn(` ${OPENCODE_PLUGIN_CACHE_PATH}`);
|
|
45201
45369
|
}
|
|
45202
|
-
if (!
|
|
45370
|
+
if (!fs21.existsSync(PLUGIN_CONFIG_PATH)) {
|
|
45203
45371
|
const defaultConfig = {
|
|
45204
45372
|
agents: {
|
|
45205
45373
|
coder: {
|
|
@@ -45274,6 +45442,7 @@ async function install() {
|
|
|
45274
45442
|
} else {
|
|
45275
45443
|
console.log("\u2713 Plugin config already exists at:", PLUGIN_CONFIG_PATH);
|
|
45276
45444
|
}
|
|
45445
|
+
writeProjectConfigIfMissing(process.cwd());
|
|
45277
45446
|
console.log(`
|
|
45278
45447
|
\uD83D\uDCC1 Configuration files:`);
|
|
45279
45448
|
console.log(` OpenCode config: ${OPENCODE_CONFIG_PATH}`);
|
|
@@ -45302,7 +45471,7 @@ async function uninstall() {
|
|
|
45302
45471
|
`);
|
|
45303
45472
|
const opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
|
|
45304
45473
|
if (!opencodeConfig) {
|
|
45305
|
-
if (
|
|
45474
|
+
if (fs21.existsSync(OPENCODE_CONFIG_PATH)) {
|
|
45306
45475
|
console.log(`\u2717 Could not parse opencode config at: ${OPENCODE_CONFIG_PATH}`);
|
|
45307
45476
|
return 1;
|
|
45308
45477
|
} else {
|
|
@@ -45334,13 +45503,13 @@ async function uninstall() {
|
|
|
45334
45503
|
console.log("\u2713 Re-enabled default OpenCode agents (explore, general)");
|
|
45335
45504
|
if (process.argv.includes("--clean")) {
|
|
45336
45505
|
let cleaned = false;
|
|
45337
|
-
if (
|
|
45338
|
-
|
|
45506
|
+
if (fs21.existsSync(PLUGIN_CONFIG_PATH)) {
|
|
45507
|
+
fs21.unlinkSync(PLUGIN_CONFIG_PATH);
|
|
45339
45508
|
console.log(`\u2713 Removed plugin config: ${PLUGIN_CONFIG_PATH}`);
|
|
45340
45509
|
cleaned = true;
|
|
45341
45510
|
}
|
|
45342
|
-
if (
|
|
45343
|
-
|
|
45511
|
+
if (fs21.existsSync(PROMPTS_DIR)) {
|
|
45512
|
+
fs21.rmSync(PROMPTS_DIR, { recursive: true });
|
|
45344
45513
|
console.log(`\u2713 Removed custom prompts: ${PROMPTS_DIR}`);
|
|
45345
45514
|
cleaned = true;
|
|
45346
45515
|
}
|
|
@@ -45403,6 +45572,10 @@ Examples:
|
|
|
45403
45572
|
}
|
|
45404
45573
|
async function main() {
|
|
45405
45574
|
const args = process.argv.slice(2);
|
|
45575
|
+
if (args.includes("-v") || args.includes("--version")) {
|
|
45576
|
+
console.log(`opencode-swarm ${version4}`);
|
|
45577
|
+
process.exit(0);
|
|
45578
|
+
}
|
|
45406
45579
|
if (args.includes("-h") || args.includes("--help")) {
|
|
45407
45580
|
printHelp();
|
|
45408
45581
|
process.exit(0);
|