opencode-swarm 7.74.1 → 7.74.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +598 -106
- package/dist/commands/command-dispatch.d.ts +0 -3
- package/dist/index.js +1811 -1169
- package/dist/services/config-doctor.d.ts +15 -0
- package/dist/services/external-content-scanner.d.ts +67 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -52,7 +52,7 @@ var package_default;
|
|
|
52
52
|
var init_package = __esm(() => {
|
|
53
53
|
package_default = {
|
|
54
54
|
name: "opencode-swarm",
|
|
55
|
-
version: "7.74.
|
|
55
|
+
version: "7.74.3",
|
|
56
56
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
57
57
|
main: "dist/index.js",
|
|
58
58
|
types: "dist/index.d.ts",
|
|
@@ -47713,6 +47713,7 @@ __export(exports_config_doctor, {
|
|
|
47713
47713
|
runConfigDoctor: () => runConfigDoctor,
|
|
47714
47714
|
restoreFromBackup: () => restoreFromBackup,
|
|
47715
47715
|
removeStraySwarmDir: () => removeStraySwarmDir,
|
|
47716
|
+
readDoctorArtifact: () => readDoctorArtifact,
|
|
47716
47717
|
getConfigPaths: () => getConfigPaths,
|
|
47717
47718
|
detectStraySwarmDirs: () => detectStraySwarmDirs,
|
|
47718
47719
|
createConfigBackup: () => createConfigBackup,
|
|
@@ -47722,6 +47723,37 @@ import * as crypto4 from "crypto";
|
|
|
47722
47723
|
import * as fs13 from "fs";
|
|
47723
47724
|
import * as os7 from "os";
|
|
47724
47725
|
import * as path35 from "path";
|
|
47726
|
+
function levenshteinDistance(a, b) {
|
|
47727
|
+
const al = a.length;
|
|
47728
|
+
const bl = b.length;
|
|
47729
|
+
const matrix = [];
|
|
47730
|
+
for (let i = 0;i <= al; i++) {
|
|
47731
|
+
matrix[i] = [i];
|
|
47732
|
+
}
|
|
47733
|
+
for (let j = 0;j <= bl; j++) {
|
|
47734
|
+
matrix[0][j] = j;
|
|
47735
|
+
}
|
|
47736
|
+
for (let i = 1;i <= al; i++) {
|
|
47737
|
+
for (let j = 1;j <= bl; j++) {
|
|
47738
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
47739
|
+
matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost);
|
|
47740
|
+
}
|
|
47741
|
+
}
|
|
47742
|
+
return matrix[al][bl];
|
|
47743
|
+
}
|
|
47744
|
+
function emitObjectTypeMismatch(key, value, findings) {
|
|
47745
|
+
if (value !== undefined && (typeof value !== "object" || Array.isArray(value) || value === null)) {
|
|
47746
|
+
findings.push({
|
|
47747
|
+
id: `invalid-${key}-type`,
|
|
47748
|
+
title: `Invalid ${key} type`,
|
|
47749
|
+
description: `"${key}" must be an object, got ${typeof value}`,
|
|
47750
|
+
severity: "error",
|
|
47751
|
+
path: key,
|
|
47752
|
+
currentValue: value,
|
|
47753
|
+
autoFixable: false
|
|
47754
|
+
});
|
|
47755
|
+
}
|
|
47756
|
+
}
|
|
47725
47757
|
function getUserConfigDir3() {
|
|
47726
47758
|
return process.env.XDG_CONFIG_HOME || path35.join(os7.homedir(), ".config");
|
|
47727
47759
|
}
|
|
@@ -47743,23 +47775,39 @@ function isValidConfigPath(configPath, directory) {
|
|
|
47743
47775
|
}
|
|
47744
47776
|
}
|
|
47745
47777
|
}
|
|
47746
|
-
for (const pattern of VALID_CONFIG_PATTERNS) {
|
|
47747
|
-
if (pattern.test(normalizedPath)) {
|
|
47748
|
-
return true;
|
|
47749
|
-
}
|
|
47750
|
-
}
|
|
47751
47778
|
const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
|
|
47752
|
-
const normalizedUser = userConfigPath.replace(/\\/g, "/");
|
|
47753
|
-
const normalizedProject = projectConfigPath.replace(/\\/g, "/");
|
|
47754
47779
|
try {
|
|
47755
47780
|
const resolvedConfig = path35.resolve(configPath);
|
|
47756
|
-
const resolvedUser = path35.resolve(
|
|
47757
|
-
const resolvedProject = path35.resolve(
|
|
47758
|
-
|
|
47781
|
+
const resolvedUser = path35.resolve(userConfigPath);
|
|
47782
|
+
const resolvedProject = path35.resolve(projectConfigPath);
|
|
47783
|
+
if (resolvedConfig !== resolvedUser && resolvedConfig !== resolvedProject) {
|
|
47784
|
+
return false;
|
|
47785
|
+
}
|
|
47786
|
+
try {
|
|
47787
|
+
if (fs13.existsSync(resolvedConfig)) {
|
|
47788
|
+
const realConfig = fs13.realpathSync(resolvedConfig);
|
|
47789
|
+
if (realConfig !== resolvedConfig) {
|
|
47790
|
+
return false;
|
|
47791
|
+
}
|
|
47792
|
+
}
|
|
47793
|
+
} catch {}
|
|
47794
|
+
return true;
|
|
47759
47795
|
} catch {
|
|
47760
47796
|
return false;
|
|
47761
47797
|
}
|
|
47762
47798
|
}
|
|
47799
|
+
function atomicWriteFileSync(filePath, content) {
|
|
47800
|
+
const tmpPath = `${filePath}.tmp.${process.pid}`;
|
|
47801
|
+
fs13.writeFileSync(tmpPath, content, "utf-8");
|
|
47802
|
+
try {
|
|
47803
|
+
fs13.renameSync(tmpPath, filePath);
|
|
47804
|
+
} catch {
|
|
47805
|
+
try {
|
|
47806
|
+
fs13.unlinkSync(filePath);
|
|
47807
|
+
} catch {}
|
|
47808
|
+
fs13.renameSync(tmpPath, filePath);
|
|
47809
|
+
}
|
|
47810
|
+
}
|
|
47763
47811
|
function createConfigBackup(directory) {
|
|
47764
47812
|
const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
|
|
47765
47813
|
let configPath = projectConfigPath;
|
|
@@ -47807,13 +47855,18 @@ function writeBackupArtifact(directory, backup) {
|
|
|
47807
47855
|
content: backup.content,
|
|
47808
47856
|
preview: backup.content.substring(0, 500) + (backup.content.length > 500 ? "..." : "")
|
|
47809
47857
|
};
|
|
47810
|
-
|
|
47858
|
+
atomicWriteFileSync(backupPath, JSON.stringify(artifact, null, 2));
|
|
47811
47859
|
return backupPath;
|
|
47812
47860
|
}
|
|
47813
47861
|
function restoreFromBackup(backupPath, directory) {
|
|
47814
47862
|
if (!fs13.existsSync(backupPath)) {
|
|
47815
47863
|
return null;
|
|
47816
47864
|
}
|
|
47865
|
+
const swarmDir = path35.resolve(path35.join(directory, ".swarm"));
|
|
47866
|
+
const resolvedBackup = path35.resolve(backupPath);
|
|
47867
|
+
if (!resolvedBackup.startsWith(swarmDir + path35.sep) && resolvedBackup !== swarmDir) {
|
|
47868
|
+
return null;
|
|
47869
|
+
}
|
|
47817
47870
|
try {
|
|
47818
47871
|
const artifact = JSON.parse(fs13.readFileSync(backupPath, "utf-8"));
|
|
47819
47872
|
if (!artifact.content || !artifact.configPath || !artifact.contentHash) {
|
|
@@ -47828,12 +47881,13 @@ function restoreFromBackup(backupPath, directory) {
|
|
|
47828
47881
|
if (!isLegacyHash && computedHash !== storedHash) {
|
|
47829
47882
|
return null;
|
|
47830
47883
|
}
|
|
47884
|
+
log("[ConfigDoctor] Warning: restoring from backup with legacy numeric hash (pre-SHA-256). Consider re-backing up.", {});
|
|
47831
47885
|
const targetPath = artifact.configPath;
|
|
47832
47886
|
const targetDir = path35.dirname(targetPath);
|
|
47833
47887
|
if (!fs13.existsSync(targetDir)) {
|
|
47834
47888
|
fs13.mkdirSync(targetDir, { recursive: true });
|
|
47835
47889
|
}
|
|
47836
|
-
|
|
47890
|
+
atomicWriteFileSync(targetPath, artifact.content);
|
|
47837
47891
|
return targetPath;
|
|
47838
47892
|
} catch {
|
|
47839
47893
|
return null;
|
|
@@ -47856,12 +47910,28 @@ function readConfigFromFile(directory) {
|
|
|
47856
47910
|
try {
|
|
47857
47911
|
const config3 = JSON.parse(configContent);
|
|
47858
47912
|
return { config: config3, configPath };
|
|
47859
|
-
} catch {
|
|
47913
|
+
} catch (error93) {
|
|
47914
|
+
log(`[ConfigDoctor] Failed to parse config file: ${configPath}`, {
|
|
47915
|
+
error: error93 instanceof Error ? error93.message : String(error93)
|
|
47916
|
+
});
|
|
47860
47917
|
return null;
|
|
47861
47918
|
}
|
|
47862
47919
|
}
|
|
47863
|
-
function validateConfigKey(path36, value
|
|
47920
|
+
function validateConfigKey(path36, value) {
|
|
47864
47921
|
const findings = [];
|
|
47922
|
+
for (const [depPath, depInfo] of DEPRECATED_FIELDS) {
|
|
47923
|
+
if (path36 === depPath && !depInfo.isDefaultValue(value)) {
|
|
47924
|
+
findings.push({
|
|
47925
|
+
id: "deprecated-field",
|
|
47926
|
+
title: `Deprecated config field: ${depPath}`,
|
|
47927
|
+
description: `Config field "${depPath}" is deprecated. Replacement: ${depInfo.replacement}.`,
|
|
47928
|
+
severity: "info",
|
|
47929
|
+
path: depPath,
|
|
47930
|
+
currentValue: value,
|
|
47931
|
+
autoFixable: false
|
|
47932
|
+
});
|
|
47933
|
+
}
|
|
47934
|
+
}
|
|
47865
47935
|
switch (path36) {
|
|
47866
47936
|
case "agents": {
|
|
47867
47937
|
if (value !== undefined) {
|
|
@@ -47979,8 +48049,9 @@ function validateConfigKey(path36, value, _config) {
|
|
|
47979
48049
|
break;
|
|
47980
48050
|
}
|
|
47981
48051
|
case "hooks": {
|
|
47982
|
-
|
|
47983
|
-
if (
|
|
48052
|
+
emitObjectTypeMismatch("hooks", value, findings);
|
|
48053
|
+
if (value !== undefined && typeof value === "object" && !Array.isArray(value) && value !== null) {
|
|
48054
|
+
const hooks = value;
|
|
47984
48055
|
const validHooks = [
|
|
47985
48056
|
"system_enhancer",
|
|
47986
48057
|
"compaction",
|
|
@@ -48061,8 +48132,42 @@ function validateConfigKey(path36, value, _config) {
|
|
|
48061
48132
|
break;
|
|
48062
48133
|
}
|
|
48063
48134
|
case "swarms": {
|
|
48064
|
-
|
|
48065
|
-
|
|
48135
|
+
if (value !== undefined) {
|
|
48136
|
+
if (typeof value !== "object" || Array.isArray(value) || value === null) {
|
|
48137
|
+
findings.push({
|
|
48138
|
+
id: "invalid-swarms-type",
|
|
48139
|
+
title: "Invalid swarms type",
|
|
48140
|
+
description: `"swarms" must be an object, got ${typeof value}`,
|
|
48141
|
+
severity: "error",
|
|
48142
|
+
path: "swarms",
|
|
48143
|
+
currentValue: value,
|
|
48144
|
+
autoFixable: false
|
|
48145
|
+
});
|
|
48146
|
+
break;
|
|
48147
|
+
}
|
|
48148
|
+
const swarms = value;
|
|
48149
|
+
if (Object.keys(swarms).length === 0) {
|
|
48150
|
+
findings.push({
|
|
48151
|
+
id: "empty-swarms",
|
|
48152
|
+
title: "Empty swarms configuration",
|
|
48153
|
+
description: 'The "swarms" field is an empty object. No swarm configurations are defined.',
|
|
48154
|
+
severity: "info",
|
|
48155
|
+
path: "swarms",
|
|
48156
|
+
autoFixable: false
|
|
48157
|
+
});
|
|
48158
|
+
}
|
|
48159
|
+
for (const swarmId of Object.keys(swarms)) {
|
|
48160
|
+
if (swarmId.includes("..") || swarmId.includes("/") || swarmId.includes("\\") || swarmId.includes("\x00")) {
|
|
48161
|
+
findings.push({
|
|
48162
|
+
id: "swarm-id-path-traversal",
|
|
48163
|
+
title: "Path traversal in swarm ID",
|
|
48164
|
+
description: `Swarm ID "${swarmId}" contains path traversal characters.`,
|
|
48165
|
+
severity: "error",
|
|
48166
|
+
path: `swarms.${swarmId}`,
|
|
48167
|
+
autoFixable: false
|
|
48168
|
+
});
|
|
48169
|
+
}
|
|
48170
|
+
}
|
|
48066
48171
|
const validAgents = new Set(ALL_AGENT_NAMES);
|
|
48067
48172
|
for (const [swarmId, swarmConfig] of Object.entries(swarms)) {
|
|
48068
48173
|
const swarm = swarmConfig;
|
|
@@ -48096,36 +48201,376 @@ function validateConfigKey(path36, value, _config) {
|
|
|
48096
48201
|
}
|
|
48097
48202
|
break;
|
|
48098
48203
|
}
|
|
48204
|
+
case "default_agent": {
|
|
48205
|
+
if (value !== undefined && typeof value !== "string") {
|
|
48206
|
+
findings.push({
|
|
48207
|
+
id: "invalid-default_agent-type",
|
|
48208
|
+
title: "Invalid default_agent type",
|
|
48209
|
+
description: `"default_agent" must be a string, got ${typeof value}`,
|
|
48210
|
+
severity: "error",
|
|
48211
|
+
path: "default_agent",
|
|
48212
|
+
currentValue: value,
|
|
48213
|
+
autoFixable: false
|
|
48214
|
+
});
|
|
48215
|
+
}
|
|
48216
|
+
break;
|
|
48217
|
+
}
|
|
48218
|
+
case "auto_select_architect": {
|
|
48219
|
+
if (value !== undefined && typeof value !== "boolean" && typeof value !== "string") {
|
|
48220
|
+
findings.push({
|
|
48221
|
+
id: "invalid-auto_select_architect-type",
|
|
48222
|
+
title: "Invalid auto_select_architect type",
|
|
48223
|
+
description: `"auto_select_architect" must be a boolean or string, got ${typeof value}`,
|
|
48224
|
+
severity: "error",
|
|
48225
|
+
path: "auto_select_architect",
|
|
48226
|
+
currentValue: value,
|
|
48227
|
+
autoFixable: false
|
|
48228
|
+
});
|
|
48229
|
+
}
|
|
48230
|
+
break;
|
|
48231
|
+
}
|
|
48232
|
+
case "pipeline": {
|
|
48233
|
+
emitObjectTypeMismatch("pipeline", value, findings);
|
|
48234
|
+
break;
|
|
48235
|
+
}
|
|
48236
|
+
case "phase_complete": {
|
|
48237
|
+
emitObjectTypeMismatch("phase_complete", value, findings);
|
|
48238
|
+
break;
|
|
48239
|
+
}
|
|
48240
|
+
case "execution_mode": {
|
|
48241
|
+
const validModes = ["strict", "balanced", "fast"];
|
|
48242
|
+
if (value !== undefined && !validModes.includes(value)) {
|
|
48243
|
+
findings.push({
|
|
48244
|
+
id: "invalid-execution_mode-type",
|
|
48245
|
+
title: "Invalid execution_mode",
|
|
48246
|
+
description: `"execution_mode" must be one of: ${validModes.join(", ")}, got "${value}"`,
|
|
48247
|
+
severity: "error",
|
|
48248
|
+
path: "execution_mode",
|
|
48249
|
+
currentValue: value,
|
|
48250
|
+
autoFixable: false
|
|
48251
|
+
});
|
|
48252
|
+
}
|
|
48253
|
+
break;
|
|
48254
|
+
}
|
|
48255
|
+
case "inject_phase_reminders": {
|
|
48256
|
+
if (value !== undefined && typeof value !== "boolean") {
|
|
48257
|
+
findings.push({
|
|
48258
|
+
id: "invalid-inject_phase_reminders-type",
|
|
48259
|
+
title: "Invalid inject_phase_reminders type",
|
|
48260
|
+
description: `"inject_phase_reminders" must be a boolean, got ${typeof value}`,
|
|
48261
|
+
severity: "error",
|
|
48262
|
+
path: "inject_phase_reminders",
|
|
48263
|
+
currentValue: value,
|
|
48264
|
+
autoFixable: false
|
|
48265
|
+
});
|
|
48266
|
+
}
|
|
48267
|
+
break;
|
|
48268
|
+
}
|
|
48269
|
+
case "gates": {
|
|
48270
|
+
emitObjectTypeMismatch("gates", value, findings);
|
|
48271
|
+
break;
|
|
48272
|
+
}
|
|
48273
|
+
case "context_budget": {
|
|
48274
|
+
emitObjectTypeMismatch("context_budget", value, findings);
|
|
48275
|
+
break;
|
|
48276
|
+
}
|
|
48277
|
+
case "guardrails": {
|
|
48278
|
+
emitObjectTypeMismatch("guardrails", value, findings);
|
|
48279
|
+
break;
|
|
48280
|
+
}
|
|
48281
|
+
case "watchdog": {
|
|
48282
|
+
emitObjectTypeMismatch("watchdog", value, findings);
|
|
48283
|
+
break;
|
|
48284
|
+
}
|
|
48285
|
+
case "self_review": {
|
|
48286
|
+
emitObjectTypeMismatch("self_review", value, findings);
|
|
48287
|
+
break;
|
|
48288
|
+
}
|
|
48289
|
+
case "tool_filter": {
|
|
48290
|
+
emitObjectTypeMismatch("tool_filter", value, findings);
|
|
48291
|
+
break;
|
|
48292
|
+
}
|
|
48293
|
+
case "authority": {
|
|
48294
|
+
emitObjectTypeMismatch("authority", value, findings);
|
|
48295
|
+
break;
|
|
48296
|
+
}
|
|
48297
|
+
case "plan_cursor": {
|
|
48298
|
+
emitObjectTypeMismatch("plan_cursor", value, findings);
|
|
48299
|
+
break;
|
|
48300
|
+
}
|
|
48301
|
+
case "context_map": {
|
|
48302
|
+
emitObjectTypeMismatch("context_map", value, findings);
|
|
48303
|
+
break;
|
|
48304
|
+
}
|
|
48305
|
+
case "evidence": {
|
|
48306
|
+
emitObjectTypeMismatch("evidence", value, findings);
|
|
48307
|
+
break;
|
|
48308
|
+
}
|
|
48309
|
+
case "summaries": {
|
|
48310
|
+
emitObjectTypeMismatch("summaries", value, findings);
|
|
48311
|
+
break;
|
|
48312
|
+
}
|
|
48313
|
+
case "review_passes": {
|
|
48314
|
+
emitObjectTypeMismatch("review_passes", value, findings);
|
|
48315
|
+
break;
|
|
48316
|
+
}
|
|
48317
|
+
case "adversarial_detection": {
|
|
48318
|
+
emitObjectTypeMismatch("adversarial_detection", value, findings);
|
|
48319
|
+
break;
|
|
48320
|
+
}
|
|
48321
|
+
case "adversarial_testing": {
|
|
48322
|
+
emitObjectTypeMismatch("adversarial_testing", value, findings);
|
|
48323
|
+
break;
|
|
48324
|
+
}
|
|
48325
|
+
case "integration_analysis": {
|
|
48326
|
+
emitObjectTypeMismatch("integration_analysis", value, findings);
|
|
48327
|
+
break;
|
|
48328
|
+
}
|
|
48329
|
+
case "docs": {
|
|
48330
|
+
emitObjectTypeMismatch("docs", value, findings);
|
|
48331
|
+
break;
|
|
48332
|
+
}
|
|
48333
|
+
case "design_docs": {
|
|
48334
|
+
emitObjectTypeMismatch("design_docs", value, findings);
|
|
48335
|
+
break;
|
|
48336
|
+
}
|
|
48337
|
+
case "ui_review": {
|
|
48338
|
+
emitObjectTypeMismatch("ui_review", value, findings);
|
|
48339
|
+
break;
|
|
48340
|
+
}
|
|
48341
|
+
case "compaction_advisory": {
|
|
48342
|
+
emitObjectTypeMismatch("compaction_advisory", value, findings);
|
|
48343
|
+
break;
|
|
48344
|
+
}
|
|
48345
|
+
case "lint": {
|
|
48346
|
+
emitObjectTypeMismatch("lint", value, findings);
|
|
48347
|
+
break;
|
|
48348
|
+
}
|
|
48349
|
+
case "secretscan": {
|
|
48350
|
+
emitObjectTypeMismatch("secretscan", value, findings);
|
|
48351
|
+
break;
|
|
48352
|
+
}
|
|
48353
|
+
case "checkpoint": {
|
|
48354
|
+
emitObjectTypeMismatch("checkpoint", value, findings);
|
|
48355
|
+
break;
|
|
48356
|
+
}
|
|
48357
|
+
case "automation": {
|
|
48358
|
+
emitObjectTypeMismatch("automation", value, findings);
|
|
48359
|
+
break;
|
|
48360
|
+
}
|
|
48361
|
+
case "knowledge": {
|
|
48362
|
+
emitObjectTypeMismatch("knowledge", value, findings);
|
|
48363
|
+
break;
|
|
48364
|
+
}
|
|
48365
|
+
case "memory": {
|
|
48366
|
+
emitObjectTypeMismatch("memory", value, findings);
|
|
48367
|
+
break;
|
|
48368
|
+
}
|
|
48369
|
+
case "curator": {
|
|
48370
|
+
emitObjectTypeMismatch("curator", value, findings);
|
|
48371
|
+
break;
|
|
48372
|
+
}
|
|
48373
|
+
case "architectural_supervision": {
|
|
48374
|
+
emitObjectTypeMismatch("architectural_supervision", value, findings);
|
|
48375
|
+
break;
|
|
48376
|
+
}
|
|
48377
|
+
case "knowledge_application": {
|
|
48378
|
+
emitObjectTypeMismatch("knowledge_application", value, findings);
|
|
48379
|
+
break;
|
|
48380
|
+
}
|
|
48381
|
+
case "skillPropagation": {
|
|
48382
|
+
emitObjectTypeMismatch("skillPropagation", value, findings);
|
|
48383
|
+
break;
|
|
48384
|
+
}
|
|
48385
|
+
case "skill_improver": {
|
|
48386
|
+
emitObjectTypeMismatch("skill_improver", value, findings);
|
|
48387
|
+
break;
|
|
48388
|
+
}
|
|
48389
|
+
case "spec_writer": {
|
|
48390
|
+
emitObjectTypeMismatch("spec_writer", value, findings);
|
|
48391
|
+
break;
|
|
48392
|
+
}
|
|
48393
|
+
case "tool_output": {
|
|
48394
|
+
emitObjectTypeMismatch("tool_output", value, findings);
|
|
48395
|
+
break;
|
|
48396
|
+
}
|
|
48397
|
+
case "slop_detector": {
|
|
48398
|
+
emitObjectTypeMismatch("slop_detector", value, findings);
|
|
48399
|
+
break;
|
|
48400
|
+
}
|
|
48401
|
+
case "todo_gate": {
|
|
48402
|
+
emitObjectTypeMismatch("todo_gate", value, findings);
|
|
48403
|
+
break;
|
|
48404
|
+
}
|
|
48405
|
+
case "incremental_verify": {
|
|
48406
|
+
emitObjectTypeMismatch("incremental_verify", value, findings);
|
|
48407
|
+
break;
|
|
48408
|
+
}
|
|
48409
|
+
case "compaction_service": {
|
|
48410
|
+
emitObjectTypeMismatch("compaction_service", value, findings);
|
|
48411
|
+
break;
|
|
48412
|
+
}
|
|
48413
|
+
case "prm": {
|
|
48414
|
+
emitObjectTypeMismatch("prm", value, findings);
|
|
48415
|
+
break;
|
|
48416
|
+
}
|
|
48417
|
+
case "council": {
|
|
48418
|
+
emitObjectTypeMismatch("council", value, findings);
|
|
48419
|
+
break;
|
|
48420
|
+
}
|
|
48421
|
+
case "parallelization": {
|
|
48422
|
+
emitObjectTypeMismatch("parallelization", value, findings);
|
|
48423
|
+
break;
|
|
48424
|
+
}
|
|
48425
|
+
case "worktree": {
|
|
48426
|
+
emitObjectTypeMismatch("worktree", value, findings);
|
|
48427
|
+
break;
|
|
48428
|
+
}
|
|
48429
|
+
case "turbo": {
|
|
48430
|
+
emitObjectTypeMismatch("turbo", value, findings);
|
|
48431
|
+
break;
|
|
48432
|
+
}
|
|
48433
|
+
case "turbo_mode": {
|
|
48434
|
+
if (value !== undefined && typeof value !== "boolean") {
|
|
48435
|
+
findings.push({
|
|
48436
|
+
id: "invalid-turbo_mode-type",
|
|
48437
|
+
title: "Invalid turbo_mode type",
|
|
48438
|
+
description: `"turbo_mode" must be a boolean, got ${typeof value}`,
|
|
48439
|
+
severity: "error",
|
|
48440
|
+
path: "turbo_mode",
|
|
48441
|
+
currentValue: value,
|
|
48442
|
+
autoFixable: false
|
|
48443
|
+
});
|
|
48444
|
+
}
|
|
48445
|
+
break;
|
|
48446
|
+
}
|
|
48447
|
+
case "quiet": {
|
|
48448
|
+
if (value !== undefined && typeof value !== "boolean") {
|
|
48449
|
+
findings.push({
|
|
48450
|
+
id: "invalid-quiet-type",
|
|
48451
|
+
title: "Invalid quiet type",
|
|
48452
|
+
description: `"quiet" must be a boolean, got ${typeof value}`,
|
|
48453
|
+
severity: "error",
|
|
48454
|
+
path: "quiet",
|
|
48455
|
+
currentValue: value,
|
|
48456
|
+
autoFixable: false
|
|
48457
|
+
});
|
|
48458
|
+
}
|
|
48459
|
+
break;
|
|
48460
|
+
}
|
|
48461
|
+
case "version_check": {
|
|
48462
|
+
if (value !== undefined && typeof value !== "boolean") {
|
|
48463
|
+
findings.push({
|
|
48464
|
+
id: "invalid-version_check-type",
|
|
48465
|
+
title: "Invalid version_check type",
|
|
48466
|
+
description: `"version_check" must be a boolean, got ${typeof value}`,
|
|
48467
|
+
severity: "error",
|
|
48468
|
+
path: "version_check",
|
|
48469
|
+
currentValue: value,
|
|
48470
|
+
autoFixable: false
|
|
48471
|
+
});
|
|
48472
|
+
}
|
|
48473
|
+
break;
|
|
48474
|
+
}
|
|
48475
|
+
case "full_auto": {
|
|
48476
|
+
emitObjectTypeMismatch("full_auto", value, findings);
|
|
48477
|
+
break;
|
|
48478
|
+
}
|
|
48479
|
+
case "pr_monitor": {
|
|
48480
|
+
emitObjectTypeMismatch("pr_monitor", value, findings);
|
|
48481
|
+
break;
|
|
48482
|
+
}
|
|
48483
|
+
case "external_skills": {
|
|
48484
|
+
emitObjectTypeMismatch("external_skills", value, findings);
|
|
48485
|
+
break;
|
|
48486
|
+
}
|
|
48487
|
+
default: {
|
|
48488
|
+
const topLevel = path36.split(".")[0];
|
|
48489
|
+
if (KNOWN_TOP_LEVEL_KEYS.has(topLevel)) {
|
|
48490
|
+
break;
|
|
48491
|
+
}
|
|
48492
|
+
const MAX_SUGGESTION_KEY_LENGTH = 100;
|
|
48493
|
+
const lowerTopLevel = topLevel.toLowerCase();
|
|
48494
|
+
let suggestion;
|
|
48495
|
+
let matchCount = 0;
|
|
48496
|
+
if (lowerTopLevel.length <= MAX_SUGGESTION_KEY_LENGTH) {
|
|
48497
|
+
for (const knownKey of KNOWN_TOP_LEVEL_KEYS) {
|
|
48498
|
+
if (levenshteinDistance(lowerTopLevel, knownKey.toLowerCase()) <= 2) {
|
|
48499
|
+
matchCount++;
|
|
48500
|
+
if (matchCount === 1) {
|
|
48501
|
+
suggestion = knownKey;
|
|
48502
|
+
}
|
|
48503
|
+
}
|
|
48504
|
+
}
|
|
48505
|
+
}
|
|
48506
|
+
if (matchCount === 1 && suggestion) {
|
|
48507
|
+
findings.push({
|
|
48508
|
+
id: "unknown-config-key",
|
|
48509
|
+
title: `Unknown config key: ${topLevel}`,
|
|
48510
|
+
description: `Unknown config key "${path36}" is not in the schema. Did you mean "${suggestion}"?`,
|
|
48511
|
+
severity: "warn",
|
|
48512
|
+
path: path36,
|
|
48513
|
+
currentValue: value,
|
|
48514
|
+
autoFixable: false
|
|
48515
|
+
});
|
|
48516
|
+
} else {
|
|
48517
|
+
findings.push({
|
|
48518
|
+
id: "unknown-config-key",
|
|
48519
|
+
title: `Unknown config key: ${topLevel}`,
|
|
48520
|
+
description: `Unknown config key "${path36}" is not in the schema.`,
|
|
48521
|
+
severity: "warn",
|
|
48522
|
+
path: path36,
|
|
48523
|
+
currentValue: value,
|
|
48524
|
+
autoFixable: false
|
|
48525
|
+
});
|
|
48526
|
+
}
|
|
48527
|
+
break;
|
|
48528
|
+
}
|
|
48099
48529
|
}
|
|
48100
48530
|
return findings;
|
|
48101
48531
|
}
|
|
48102
|
-
function walkConfigAndValidate(obj, path36,
|
|
48532
|
+
function walkConfigAndValidate(obj, path36, findings, visited = new WeakSet) {
|
|
48103
48533
|
if (obj === null || obj === undefined) {
|
|
48104
48534
|
return;
|
|
48105
48535
|
}
|
|
48106
48536
|
if (path36 && typeof obj === "object" && !Array.isArray(obj)) {
|
|
48107
|
-
const keyFindings = validateConfigKey(path36, obj
|
|
48537
|
+
const keyFindings = validateConfigKey(path36, obj);
|
|
48108
48538
|
findings.push(...keyFindings);
|
|
48109
48539
|
}
|
|
48110
48540
|
if (typeof obj !== "object") {
|
|
48111
|
-
const keyFindings = validateConfigKey(path36, obj
|
|
48541
|
+
const keyFindings = validateConfigKey(path36, obj);
|
|
48112
48542
|
findings.push(...keyFindings);
|
|
48113
48543
|
return;
|
|
48114
48544
|
}
|
|
48545
|
+
if (visited.has(obj)) {
|
|
48546
|
+
findings.push({
|
|
48547
|
+
id: "circular-reference",
|
|
48548
|
+
title: `Circular reference detected at ${path36}`,
|
|
48549
|
+
description: `Config value at "${path36}" contains a circular reference. Validation stopped at this path to prevent stack overflow.`,
|
|
48550
|
+
severity: "error",
|
|
48551
|
+
path: path36,
|
|
48552
|
+
currentValue: "[circular]",
|
|
48553
|
+
autoFixable: false
|
|
48554
|
+
});
|
|
48555
|
+
return;
|
|
48556
|
+
}
|
|
48557
|
+
visited.add(obj);
|
|
48115
48558
|
if (Array.isArray(obj)) {
|
|
48559
|
+
const arrayFindings = validateConfigKey(path36, obj);
|
|
48560
|
+
findings.push(...arrayFindings);
|
|
48116
48561
|
obj.forEach((item, index) => {
|
|
48117
|
-
walkConfigAndValidate(item, `${path36}[${index}]`,
|
|
48562
|
+
walkConfigAndValidate(item, `${path36}[${index}]`, findings, visited);
|
|
48118
48563
|
});
|
|
48119
48564
|
return;
|
|
48120
48565
|
}
|
|
48121
48566
|
for (const [key, value] of Object.entries(obj)) {
|
|
48122
48567
|
const newPath = path36 ? `${path36}.${key}` : key;
|
|
48123
|
-
walkConfigAndValidate(value, newPath,
|
|
48568
|
+
walkConfigAndValidate(value, newPath, findings, visited);
|
|
48124
48569
|
}
|
|
48125
48570
|
}
|
|
48126
48571
|
function runConfigDoctor(config3, directory) {
|
|
48127
48572
|
const findings = [];
|
|
48128
|
-
walkConfigAndValidate(config3, "",
|
|
48573
|
+
walkConfigAndValidate(config3, "", findings);
|
|
48129
48574
|
const summary = {
|
|
48130
48575
|
info: findings.filter((f) => f.severity === "info").length,
|
|
48131
48576
|
warn: findings.filter((f) => f.severity === "warn").length,
|
|
@@ -48243,11 +48688,45 @@ function applySafeAutoFixes(directory, result) {
|
|
|
48243
48688
|
if (!fs13.existsSync(configDir)) {
|
|
48244
48689
|
fs13.mkdirSync(configDir, { recursive: true });
|
|
48245
48690
|
}
|
|
48246
|
-
|
|
48691
|
+
atomicWriteFileSync(configPath, JSON.stringify(config3, null, 2));
|
|
48247
48692
|
updatedConfigPath = configPath;
|
|
48248
48693
|
}
|
|
48249
48694
|
return { appliedFixes, updatedConfigPath };
|
|
48250
48695
|
}
|
|
48696
|
+
function readDoctorArtifact(directory) {
|
|
48697
|
+
try {
|
|
48698
|
+
const artifactPath = path35.join(directory, ".swarm", "config-doctor.json");
|
|
48699
|
+
if (!fs13.existsSync(artifactPath)) {
|
|
48700
|
+
return null;
|
|
48701
|
+
}
|
|
48702
|
+
const content = fs13.readFileSync(artifactPath, "utf-8");
|
|
48703
|
+
const artifact = JSON.parse(content);
|
|
48704
|
+
const summary = artifact.summary;
|
|
48705
|
+
if (!summary || typeof summary !== "object") {
|
|
48706
|
+
return null;
|
|
48707
|
+
}
|
|
48708
|
+
const infoVal = summary.info;
|
|
48709
|
+
const warnVal = summary.warn;
|
|
48710
|
+
const errorVal = summary.error;
|
|
48711
|
+
if (typeof infoVal !== "number" || !Number.isFinite(infoVal) || typeof warnVal !== "number" || !Number.isFinite(warnVal) || typeof errorVal !== "number" || !Number.isFinite(errorVal)) {
|
|
48712
|
+
return null;
|
|
48713
|
+
}
|
|
48714
|
+
const ts = artifact.timestamp;
|
|
48715
|
+
if (typeof ts !== "number" || !Number.isFinite(ts)) {
|
|
48716
|
+
return null;
|
|
48717
|
+
}
|
|
48718
|
+
const findingsCount = infoVal + warnVal + errorVal;
|
|
48719
|
+
const findings = artifact.findings;
|
|
48720
|
+
const autoFixableCount = Array.isArray(findings) ? findings.filter((f) => f.autoFixable === true).length : 0;
|
|
48721
|
+
return {
|
|
48722
|
+
timestamp: new Date(ts).toISOString(),
|
|
48723
|
+
findingsCount,
|
|
48724
|
+
autoFixableCount
|
|
48725
|
+
};
|
|
48726
|
+
} catch {
|
|
48727
|
+
return null;
|
|
48728
|
+
}
|
|
48729
|
+
}
|
|
48251
48730
|
function writeDoctorArtifact(directory, result) {
|
|
48252
48731
|
const swarmDir = path35.join(directory, ".swarm");
|
|
48253
48732
|
if (!fs13.existsSync(swarmDir)) {
|
|
@@ -48275,7 +48754,7 @@ function writeDoctorArtifact(directory, result) {
|
|
|
48275
48754
|
} : null
|
|
48276
48755
|
}))
|
|
48277
48756
|
};
|
|
48278
|
-
|
|
48757
|
+
atomicWriteFileSync(artifactPath, JSON.stringify(guiOutput, null, 2));
|
|
48279
48758
|
return artifactPath;
|
|
48280
48759
|
}
|
|
48281
48760
|
function shouldRunOnStartup(automationConfig) {
|
|
@@ -48428,15 +48907,46 @@ function removeStraySwarmDir(projectRoot, strayPath) {
|
|
|
48428
48907
|
};
|
|
48429
48908
|
}
|
|
48430
48909
|
}
|
|
48431
|
-
var
|
|
48910
|
+
var KNOWN_TOP_LEVEL_KEYS, DEPRECATED_FIELDS, DANGEROUS_PATH_SEGMENTS;
|
|
48432
48911
|
var init_config_doctor = __esm(() => {
|
|
48433
48912
|
init_constants();
|
|
48434
48913
|
init_schema();
|
|
48435
48914
|
init_utils();
|
|
48436
|
-
|
|
48437
|
-
|
|
48438
|
-
|
|
48439
|
-
|
|
48915
|
+
KNOWN_TOP_LEVEL_KEYS = new Set(Object.keys(PluginConfigSchema.shape));
|
|
48916
|
+
DEPRECATED_FIELDS = new Map([
|
|
48917
|
+
[
|
|
48918
|
+
"skill_improver.model",
|
|
48919
|
+
{
|
|
48920
|
+
message: "deprecated",
|
|
48921
|
+
replacement: "agents.skill_improver.model",
|
|
48922
|
+
isDefaultValue: (v) => v === null
|
|
48923
|
+
}
|
|
48924
|
+
],
|
|
48925
|
+
[
|
|
48926
|
+
"skill_improver.fallback_models",
|
|
48927
|
+
{
|
|
48928
|
+
message: "deprecated",
|
|
48929
|
+
replacement: "agents.skill_improver.fallback_models",
|
|
48930
|
+
isDefaultValue: (v) => Array.isArray(v) && v.length === 0
|
|
48931
|
+
}
|
|
48932
|
+
],
|
|
48933
|
+
[
|
|
48934
|
+
"spec_writer.model",
|
|
48935
|
+
{
|
|
48936
|
+
message: "deprecated",
|
|
48937
|
+
replacement: "agents.spec_writer.model",
|
|
48938
|
+
isDefaultValue: (v) => v === null
|
|
48939
|
+
}
|
|
48940
|
+
],
|
|
48941
|
+
[
|
|
48942
|
+
"spec_writer.fallback_models",
|
|
48943
|
+
{
|
|
48944
|
+
message: "deprecated",
|
|
48945
|
+
replacement: "agents.spec_writer.fallback_models",
|
|
48946
|
+
isDefaultValue: (v) => Array.isArray(v) && v.length === 0
|
|
48947
|
+
}
|
|
48948
|
+
]
|
|
48949
|
+
]);
|
|
48440
48950
|
DANGEROUS_PATH_SEGMENTS = new Set([
|
|
48441
48951
|
"__proto__",
|
|
48442
48952
|
"constructor",
|
|
@@ -50099,7 +50609,14 @@ async function handleDoctorCommand(directory, args) {
|
|
|
50099
50609
|
const fixResult = await runConfigDoctorWithFixes2(directory, config3, true);
|
|
50100
50610
|
output = formatDoctorMarkdown(fixResult.result);
|
|
50101
50611
|
} else {
|
|
50102
|
-
|
|
50612
|
+
const lastRun = readDoctorArtifact(directory);
|
|
50613
|
+
let markdown = formatDoctorMarkdown(result);
|
|
50614
|
+
if (lastRun) {
|
|
50615
|
+
markdown = `Last run: ${lastRun.timestamp}, ${lastRun.findingsCount} findings (${lastRun.autoFixableCount} auto-fixable)
|
|
50616
|
+
|
|
50617
|
+
` + markdown;
|
|
50618
|
+
}
|
|
50619
|
+
output = markdown;
|
|
50103
50620
|
}
|
|
50104
50621
|
const strayDirs = detectStraySwarmDirs(directory);
|
|
50105
50622
|
if (strayDirs.length > 0) {
|
|
@@ -51408,7 +51925,7 @@ var init_handoff_service = __esm(() => {
|
|
|
51408
51925
|
});
|
|
51409
51926
|
|
|
51410
51927
|
// src/session/snapshot-writer.ts
|
|
51411
|
-
import { closeSync as closeSync5, fsyncSync as fsyncSync2, mkdirSync as mkdirSync15, openSync as openSync5, renameSync as
|
|
51928
|
+
import { closeSync as closeSync5, fsyncSync as fsyncSync2, mkdirSync as mkdirSync15, openSync as openSync5, renameSync as renameSync10 } from "fs";
|
|
51412
51929
|
import * as path38 from "path";
|
|
51413
51930
|
function serializeAgentSession(s) {
|
|
51414
51931
|
const gateLog = {};
|
|
@@ -51527,7 +52044,7 @@ async function writeSnapshot(directory, state) {
|
|
|
51527
52044
|
closeSync5(fd);
|
|
51528
52045
|
}
|
|
51529
52046
|
} catch {}
|
|
51530
|
-
|
|
52047
|
+
renameSync10(tempPath, resolvedPath);
|
|
51531
52048
|
} catch (error93) {
|
|
51532
52049
|
log("[snapshot-writer] write failed", {
|
|
51533
52050
|
error: error93 instanceof Error ? error93.message : String(error93)
|
|
@@ -51560,7 +52077,7 @@ var init_snapshot_writer = __esm(() => {
|
|
|
51560
52077
|
|
|
51561
52078
|
// src/commands/handoff.ts
|
|
51562
52079
|
import crypto5 from "crypto";
|
|
51563
|
-
import { renameSync as
|
|
52080
|
+
import { renameSync as renameSync11, unlinkSync as unlinkSync7 } from "fs";
|
|
51564
52081
|
async function handleHandoffCommand(directory, _args) {
|
|
51565
52082
|
const handoffData = await getHandoffData(directory);
|
|
51566
52083
|
const markdown = formatHandoffMarkdown(handoffData);
|
|
@@ -51569,10 +52086,10 @@ async function handleHandoffCommand(directory, _args) {
|
|
|
51569
52086
|
const tempPath = `${resolvedPath}.tmp.${crypto5.randomUUID()}`;
|
|
51570
52087
|
await bunWrite(tempPath, markdown);
|
|
51571
52088
|
try {
|
|
51572
|
-
|
|
52089
|
+
renameSync11(tempPath, resolvedPath);
|
|
51573
52090
|
} catch (renameErr) {
|
|
51574
52091
|
try {
|
|
51575
|
-
|
|
52092
|
+
unlinkSync7(tempPath);
|
|
51576
52093
|
} catch {}
|
|
51577
52094
|
throw renameErr;
|
|
51578
52095
|
}
|
|
@@ -51581,10 +52098,10 @@ async function handleHandoffCommand(directory, _args) {
|
|
|
51581
52098
|
const promptTempPath = `${promptPath}.tmp.${crypto5.randomUUID()}`;
|
|
51582
52099
|
await bunWrite(promptTempPath, continuationPrompt);
|
|
51583
52100
|
try {
|
|
51584
|
-
|
|
52101
|
+
renameSync11(promptTempPath, promptPath);
|
|
51585
52102
|
} catch (renameErr) {
|
|
51586
52103
|
try {
|
|
51587
|
-
|
|
52104
|
+
unlinkSync7(promptTempPath);
|
|
51588
52105
|
} catch {}
|
|
51589
52106
|
throw renameErr;
|
|
51590
52107
|
}
|
|
@@ -64742,8 +65259,6 @@ var init_write_retro2 = __esm(() => {
|
|
|
64742
65259
|
});
|
|
64743
65260
|
|
|
64744
65261
|
// src/commands/command-dispatch.ts
|
|
64745
|
-
import fs35 from "fs";
|
|
64746
|
-
import path65 from "path";
|
|
64747
65262
|
function normalizeSwarmCommandInput(command, argumentText) {
|
|
64748
65263
|
if (command !== "swarm" && !command.startsWith("swarm-")) {
|
|
64749
65264
|
return { isSwarmCommand: false, tokens: [] };
|
|
@@ -64778,25 +65293,6 @@ ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
|
|
|
64778
65293
|
|
|
64779
65294
|
`);
|
|
64780
65295
|
}
|
|
64781
|
-
function maybeMarkFirstRun(directory) {
|
|
64782
|
-
const sentinelPath = path65.join(directory, ".swarm", ".first-run-complete");
|
|
64783
|
-
try {
|
|
64784
|
-
const swarmDir = path65.join(directory, ".swarm");
|
|
64785
|
-
fs35.mkdirSync(swarmDir, { recursive: true });
|
|
64786
|
-
fs35.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
|
|
64787
|
-
`, { flag: "wx" });
|
|
64788
|
-
return true;
|
|
64789
|
-
} catch {
|
|
64790
|
-
return false;
|
|
64791
|
-
}
|
|
64792
|
-
}
|
|
64793
|
-
function prependWelcome(text) {
|
|
64794
|
-
const welcomeMessage = `Welcome to OpenCode Swarm!
|
|
64795
|
-
` + `
|
|
64796
|
-
` + `Run \`/swarm help\` to see all available commands, or \`/swarm config\` to review your configuration.
|
|
64797
|
-
`;
|
|
64798
|
-
return welcomeMessage + text;
|
|
64799
|
-
}
|
|
64800
65296
|
async function executeSwarmCommand(args) {
|
|
64801
65297
|
const {
|
|
64802
65298
|
directory,
|
|
@@ -64804,7 +65300,6 @@ async function executeSwarmCommand(args) {
|
|
|
64804
65300
|
sessionID,
|
|
64805
65301
|
tokens,
|
|
64806
65302
|
packageRoot,
|
|
64807
|
-
includeWelcome = false,
|
|
64808
65303
|
buildHelpText,
|
|
64809
65304
|
policy
|
|
64810
65305
|
} = args;
|
|
@@ -64838,9 +65333,6 @@ ${text}`;
|
|
|
64838
65333
|
}
|
|
64839
65334
|
}
|
|
64840
65335
|
}
|
|
64841
|
-
if (includeWelcome && maybeMarkFirstRun(directory)) {
|
|
64842
|
-
text = prependWelcome(text);
|
|
64843
|
-
}
|
|
64844
65336
|
return {
|
|
64845
65337
|
text,
|
|
64846
65338
|
resolved: resolved ?? undefined,
|
|
@@ -65463,7 +65955,7 @@ var init_commands = __esm(() => {
|
|
|
65463
65955
|
});
|
|
65464
65956
|
|
|
65465
65957
|
// src/commands/registry.ts
|
|
65466
|
-
function
|
|
65958
|
+
function levenshteinDistance2(a, b) {
|
|
65467
65959
|
const matrix = [];
|
|
65468
65960
|
for (let i = 0;i <= b.length; i++) {
|
|
65469
65961
|
matrix[i] = [i];
|
|
@@ -65590,24 +66082,24 @@ function validateAliases() {
|
|
|
65590
66082
|
}
|
|
65591
66083
|
aliasTargets.get(target).push(name);
|
|
65592
66084
|
const visited = new Set;
|
|
65593
|
-
const
|
|
66085
|
+
const path65 = [];
|
|
65594
66086
|
let current = target;
|
|
65595
66087
|
while (current) {
|
|
65596
66088
|
const currentEntry = COMMAND_REGISTRY[current];
|
|
65597
66089
|
if (!currentEntry)
|
|
65598
66090
|
break;
|
|
65599
66091
|
if (visited.has(current)) {
|
|
65600
|
-
const cycleStart =
|
|
66092
|
+
const cycleStart = path65.indexOf(current);
|
|
65601
66093
|
const fullChain = [
|
|
65602
66094
|
name,
|
|
65603
|
-
...
|
|
66095
|
+
...path65.slice(0, cycleStart > 0 ? cycleStart : path65.length),
|
|
65604
66096
|
current
|
|
65605
66097
|
].join(" \u2192 ");
|
|
65606
66098
|
errors5.push(`Circular alias detected: ${fullChain}`);
|
|
65607
66099
|
break;
|
|
65608
66100
|
}
|
|
65609
66101
|
visited.add(current);
|
|
65610
|
-
|
|
66102
|
+
path65.push(current);
|
|
65611
66103
|
current = currentEntry.aliasOf || "";
|
|
65612
66104
|
}
|
|
65613
66105
|
}
|
|
@@ -66329,7 +66821,7 @@ Subcommands:
|
|
|
66329
66821
|
handleHelpCommand,
|
|
66330
66822
|
validateAliases,
|
|
66331
66823
|
resolveCommand,
|
|
66332
|
-
levenshteinDistance,
|
|
66824
|
+
levenshteinDistance: levenshteinDistance2,
|
|
66333
66825
|
findSimilarCommands,
|
|
66334
66826
|
buildDetailedHelp
|
|
66335
66827
|
};
|
|
@@ -66351,72 +66843,72 @@ init_package();
|
|
|
66351
66843
|
init_registry();
|
|
66352
66844
|
init_cache_paths();
|
|
66353
66845
|
init_constants();
|
|
66354
|
-
import * as
|
|
66846
|
+
import * as fs35 from "fs";
|
|
66355
66847
|
import * as os10 from "os";
|
|
66356
|
-
import * as
|
|
66848
|
+
import * as path65 from "path";
|
|
66357
66849
|
var { version: version5 } = package_default;
|
|
66358
66850
|
var CONFIG_DIR = getPluginConfigDir();
|
|
66359
|
-
var OPENCODE_CONFIG_PATH =
|
|
66360
|
-
var PLUGIN_CONFIG_PATH =
|
|
66361
|
-
var PROMPTS_DIR =
|
|
66851
|
+
var OPENCODE_CONFIG_PATH = path65.join(CONFIG_DIR, "opencode.json");
|
|
66852
|
+
var PLUGIN_CONFIG_PATH = path65.join(CONFIG_DIR, "opencode-swarm.json");
|
|
66853
|
+
var PROMPTS_DIR = path65.join(CONFIG_DIR, "opencode-swarm");
|
|
66362
66854
|
var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
|
|
66363
66855
|
var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
|
|
66364
66856
|
function isSafeCachePath(p) {
|
|
66365
|
-
const resolved =
|
|
66366
|
-
const home =
|
|
66857
|
+
const resolved = path65.resolve(p);
|
|
66858
|
+
const home = path65.resolve(os10.homedir());
|
|
66367
66859
|
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
66368
66860
|
return false;
|
|
66369
66861
|
}
|
|
66370
|
-
const segments = resolved.split(
|
|
66862
|
+
const segments = resolved.split(path65.sep).filter((s) => s.length > 0);
|
|
66371
66863
|
if (segments.length < 4) {
|
|
66372
66864
|
return false;
|
|
66373
66865
|
}
|
|
66374
|
-
const leaf =
|
|
66866
|
+
const leaf = path65.basename(resolved);
|
|
66375
66867
|
if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
|
|
66376
66868
|
return false;
|
|
66377
66869
|
}
|
|
66378
|
-
const parent =
|
|
66870
|
+
const parent = path65.basename(path65.dirname(resolved));
|
|
66379
66871
|
if (parent !== "packages" && parent !== "node_modules") {
|
|
66380
66872
|
return false;
|
|
66381
66873
|
}
|
|
66382
|
-
const grandparent =
|
|
66874
|
+
const grandparent = path65.basename(path65.dirname(path65.dirname(resolved)));
|
|
66383
66875
|
if (grandparent !== "opencode") {
|
|
66384
66876
|
return false;
|
|
66385
66877
|
}
|
|
66386
66878
|
return true;
|
|
66387
66879
|
}
|
|
66388
66880
|
function isSafeLockFilePath(p) {
|
|
66389
|
-
const resolved =
|
|
66390
|
-
const home =
|
|
66881
|
+
const resolved = path65.resolve(p);
|
|
66882
|
+
const home = path65.resolve(os10.homedir());
|
|
66391
66883
|
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
66392
66884
|
return false;
|
|
66393
66885
|
}
|
|
66394
|
-
const segments = resolved.split(
|
|
66886
|
+
const segments = resolved.split(path65.sep).filter((s) => s.length > 0);
|
|
66395
66887
|
if (segments.length < 4) {
|
|
66396
66888
|
return false;
|
|
66397
66889
|
}
|
|
66398
|
-
const leaf =
|
|
66890
|
+
const leaf = path65.basename(resolved);
|
|
66399
66891
|
if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
|
|
66400
66892
|
return false;
|
|
66401
66893
|
}
|
|
66402
|
-
const parent =
|
|
66894
|
+
const parent = path65.basename(path65.dirname(resolved));
|
|
66403
66895
|
if (parent !== "opencode") {
|
|
66404
66896
|
return false;
|
|
66405
66897
|
}
|
|
66406
|
-
const grandparent =
|
|
66898
|
+
const grandparent = path65.basename(path65.dirname(path65.dirname(resolved)));
|
|
66407
66899
|
if (grandparent === "opencode") {
|
|
66408
66900
|
return false;
|
|
66409
66901
|
}
|
|
66410
66902
|
return true;
|
|
66411
66903
|
}
|
|
66412
66904
|
function ensureDir(dir) {
|
|
66413
|
-
if (!
|
|
66414
|
-
|
|
66905
|
+
if (!fs35.existsSync(dir)) {
|
|
66906
|
+
fs35.mkdirSync(dir, { recursive: true });
|
|
66415
66907
|
}
|
|
66416
66908
|
}
|
|
66417
66909
|
function loadJson(filepath) {
|
|
66418
66910
|
try {
|
|
66419
|
-
const content =
|
|
66911
|
+
const content = fs35.readFileSync(filepath, "utf-8");
|
|
66420
66912
|
const stripped = content.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (match, comment) => comment ? "" : match).replace(/,(\s*[}\]])/g, "$1");
|
|
66421
66913
|
return JSON.parse(stripped);
|
|
66422
66914
|
} catch {
|
|
@@ -66424,14 +66916,14 @@ function loadJson(filepath) {
|
|
|
66424
66916
|
}
|
|
66425
66917
|
}
|
|
66426
66918
|
function saveJson(filepath, data) {
|
|
66427
|
-
|
|
66919
|
+
fs35.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
|
|
66428
66920
|
`, "utf-8");
|
|
66429
66921
|
}
|
|
66430
66922
|
function writeProjectConfigIfMissing(cwd) {
|
|
66431
66923
|
try {
|
|
66432
|
-
const opencodeDir =
|
|
66433
|
-
const projectConfigPath =
|
|
66434
|
-
if (
|
|
66924
|
+
const opencodeDir = path65.join(cwd, ".opencode");
|
|
66925
|
+
const projectConfigPath = path65.join(opencodeDir, "opencode-swarm.json");
|
|
66926
|
+
if (fs35.existsSync(projectConfigPath)) {
|
|
66435
66927
|
return;
|
|
66436
66928
|
}
|
|
66437
66929
|
ensureDir(opencodeDir);
|
|
@@ -66447,7 +66939,7 @@ async function install() {
|
|
|
66447
66939
|
`);
|
|
66448
66940
|
ensureDir(CONFIG_DIR);
|
|
66449
66941
|
ensureDir(PROMPTS_DIR);
|
|
66450
|
-
const LEGACY_CONFIG_PATH =
|
|
66942
|
+
const LEGACY_CONFIG_PATH = path65.join(CONFIG_DIR, "config.json");
|
|
66451
66943
|
let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
|
|
66452
66944
|
if (!opencodeConfig) {
|
|
66453
66945
|
const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
|
|
@@ -66494,7 +66986,7 @@ async function install() {
|
|
|
66494
66986
|
console.warn(`\u26A0 Could not clear opencode lock file \u2014 you may need to delete it manually:
|
|
66495
66987
|
${failed}`);
|
|
66496
66988
|
}
|
|
66497
|
-
if (!
|
|
66989
|
+
if (!fs35.existsSync(PLUGIN_CONFIG_PATH)) {
|
|
66498
66990
|
const defaultConfig = {
|
|
66499
66991
|
agents: { ...DEFAULT_AGENT_CONFIGS },
|
|
66500
66992
|
max_iterations: 5
|
|
@@ -66573,14 +67065,14 @@ function evictPluginCaches() {
|
|
|
66573
67065
|
const cleared = [];
|
|
66574
67066
|
const failed = [];
|
|
66575
67067
|
for (const cachePath of OPENCODE_PLUGIN_CACHE_PATHS) {
|
|
66576
|
-
if (!
|
|
67068
|
+
if (!fs35.existsSync(cachePath))
|
|
66577
67069
|
continue;
|
|
66578
67070
|
if (!isSafeCachePath(cachePath)) {
|
|
66579
67071
|
failed.push(`${cachePath} (refused: failed safety check)`);
|
|
66580
67072
|
continue;
|
|
66581
67073
|
}
|
|
66582
67074
|
try {
|
|
66583
|
-
|
|
67075
|
+
fs35.rmSync(cachePath, { recursive: true, force: true });
|
|
66584
67076
|
cleared.push(cachePath);
|
|
66585
67077
|
} catch (err) {
|
|
66586
67078
|
failed.push(`${cachePath} (${err instanceof Error ? err.message : String(err)})`);
|
|
@@ -66592,14 +67084,14 @@ function evictLockFiles() {
|
|
|
66592
67084
|
const cleared = [];
|
|
66593
67085
|
const failed = [];
|
|
66594
67086
|
for (const lockPath of OPENCODE_PLUGIN_LOCK_FILE_PATHS) {
|
|
66595
|
-
if (!
|
|
67087
|
+
if (!fs35.existsSync(lockPath))
|
|
66596
67088
|
continue;
|
|
66597
67089
|
if (!isSafeLockFilePath(lockPath)) {
|
|
66598
67090
|
failed.push(`${lockPath} (refused: failed safety check)`);
|
|
66599
67091
|
continue;
|
|
66600
67092
|
}
|
|
66601
67093
|
try {
|
|
66602
|
-
|
|
67094
|
+
fs35.unlinkSync(lockPath);
|
|
66603
67095
|
cleared.push(lockPath);
|
|
66604
67096
|
} catch (err) {
|
|
66605
67097
|
const code = err?.code;
|
|
@@ -66618,7 +67110,7 @@ async function uninstall() {
|
|
|
66618
67110
|
`);
|
|
66619
67111
|
const opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
|
|
66620
67112
|
if (!opencodeConfig) {
|
|
66621
|
-
if (
|
|
67113
|
+
if (fs35.existsSync(OPENCODE_CONFIG_PATH)) {
|
|
66622
67114
|
console.log(`\u2717 Could not parse opencode config at: ${OPENCODE_CONFIG_PATH}`);
|
|
66623
67115
|
return 1;
|
|
66624
67116
|
} else {
|
|
@@ -66650,13 +67142,13 @@ async function uninstall() {
|
|
|
66650
67142
|
console.log("\u2713 Re-enabled default OpenCode agents (explore, general)");
|
|
66651
67143
|
if (process.argv.includes("--clean")) {
|
|
66652
67144
|
let cleaned = false;
|
|
66653
|
-
if (
|
|
66654
|
-
|
|
67145
|
+
if (fs35.existsSync(PLUGIN_CONFIG_PATH)) {
|
|
67146
|
+
fs35.unlinkSync(PLUGIN_CONFIG_PATH);
|
|
66655
67147
|
console.log(`\u2713 Removed plugin config: ${PLUGIN_CONFIG_PATH}`);
|
|
66656
67148
|
cleaned = true;
|
|
66657
67149
|
}
|
|
66658
|
-
if (
|
|
66659
|
-
|
|
67150
|
+
if (fs35.existsSync(PROMPTS_DIR)) {
|
|
67151
|
+
fs35.rmSync(PROMPTS_DIR, { recursive: true });
|
|
66660
67152
|
console.log(`\u2713 Removed custom prompts: ${PROMPTS_DIR}`);
|
|
66661
67153
|
cleaned = true;
|
|
66662
67154
|
}
|