opencode-swarm 7.74.2 → 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 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.2",
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(normalizedUser);
47757
- const resolvedProject = path35.resolve(normalizedProject);
47758
- return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
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
- fs13.writeFileSync(backupPath, JSON.stringify(artifact, null, 2), "utf-8");
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
- fs13.writeFileSync(targetPath, artifact.content, "utf-8");
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, _config) {
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
- const hooks = value;
47983
- if (hooks) {
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
- const swarms = value;
48065
- if (swarms && typeof swarms === "object") {
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, config3, findings) {
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, config3);
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, config3);
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}]`, config3, findings);
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, config3, findings);
48568
+ walkConfigAndValidate(value, newPath, findings, visited);
48124
48569
  }
48125
48570
  }
48126
48571
  function runConfigDoctor(config3, directory) {
48127
48572
  const findings = [];
48128
- walkConfigAndValidate(config3, "", config3, findings);
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
- fs13.writeFileSync(configPath, JSON.stringify(config3, null, 2), "utf-8");
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
- fs13.writeFileSync(artifactPath, JSON.stringify(guiOutput, null, 2), "utf-8");
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 VALID_CONFIG_PATTERNS, DANGEROUS_PATH_SEGMENTS;
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
- VALID_CONFIG_PATTERNS = [
48437
- /^\.config[\\/]opencode[\\/]opencode-swarm\.json$/,
48438
- /\.opencode[\\/]opencode-swarm\.json$/
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
- output = formatDoctorMarkdown(result);
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 renameSync9 } from "fs";
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
- renameSync9(tempPath, resolvedPath);
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 renameSync10, unlinkSync as unlinkSync6 } from "fs";
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
- renameSync10(tempPath, resolvedPath);
52089
+ renameSync11(tempPath, resolvedPath);
51573
52090
  } catch (renameErr) {
51574
52091
  try {
51575
- unlinkSync6(tempPath);
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
- renameSync10(promptTempPath, promptPath);
52101
+ renameSync11(promptTempPath, promptPath);
51585
52102
  } catch (renameErr) {
51586
52103
  try {
51587
- unlinkSync6(promptTempPath);
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 levenshteinDistance(a, b) {
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 path66 = [];
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 = path66.indexOf(current);
66092
+ const cycleStart = path65.indexOf(current);
65601
66093
  const fullChain = [
65602
66094
  name,
65603
- ...path66.slice(0, cycleStart > 0 ? cycleStart : path66.length),
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
- path66.push(current);
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 fs36 from "fs";
66846
+ import * as fs35 from "fs";
66355
66847
  import * as os10 from "os";
66356
- import * as path66 from "path";
66848
+ import * as path65 from "path";
66357
66849
  var { version: version5 } = package_default;
66358
66850
  var CONFIG_DIR = getPluginConfigDir();
66359
- var OPENCODE_CONFIG_PATH = path66.join(CONFIG_DIR, "opencode.json");
66360
- var PLUGIN_CONFIG_PATH = path66.join(CONFIG_DIR, "opencode-swarm.json");
66361
- var PROMPTS_DIR = path66.join(CONFIG_DIR, "opencode-swarm");
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 = path66.resolve(p);
66366
- const home = path66.resolve(os10.homedir());
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(path66.sep).filter((s) => s.length > 0);
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 = path66.basename(resolved);
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 = path66.basename(path66.dirname(resolved));
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 = path66.basename(path66.dirname(path66.dirname(resolved)));
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 = path66.resolve(p);
66390
- const home = path66.resolve(os10.homedir());
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(path66.sep).filter((s) => s.length > 0);
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 = path66.basename(resolved);
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 = path66.basename(path66.dirname(resolved));
66894
+ const parent = path65.basename(path65.dirname(resolved));
66403
66895
  if (parent !== "opencode") {
66404
66896
  return false;
66405
66897
  }
66406
- const grandparent = path66.basename(path66.dirname(path66.dirname(resolved)));
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 (!fs36.existsSync(dir)) {
66414
- fs36.mkdirSync(dir, { recursive: true });
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 = fs36.readFileSync(filepath, "utf-8");
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
- fs36.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
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 = path66.join(cwd, ".opencode");
66433
- const projectConfigPath = path66.join(opencodeDir, "opencode-swarm.json");
66434
- if (fs36.existsSync(projectConfigPath)) {
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 = path66.join(CONFIG_DIR, "config.json");
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 (!fs36.existsSync(PLUGIN_CONFIG_PATH)) {
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 (!fs36.existsSync(cachePath))
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
- fs36.rmSync(cachePath, { recursive: true, force: true });
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 (!fs36.existsSync(lockPath))
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
- fs36.unlinkSync(lockPath);
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 (fs36.existsSync(OPENCODE_CONFIG_PATH)) {
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 (fs36.existsSync(PLUGIN_CONFIG_PATH)) {
66654
- fs36.unlinkSync(PLUGIN_CONFIG_PATH);
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 (fs36.existsSync(PROMPTS_DIR)) {
66659
- fs36.rmSync(PROMPTS_DIR, { recursive: true });
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
  }