opencode-swarm 7.18.2 → 7.19.0

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
@@ -34,7 +34,7 @@ var package_default;
34
34
  var init_package = __esm(() => {
35
35
  package_default = {
36
36
  name: "opencode-swarm",
37
- version: "7.18.2",
37
+ version: "7.19.0",
38
38
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
39
39
  main: "dist/index.js",
40
40
  types: "dist/index.d.ts",
@@ -16064,6 +16064,7 @@ var init_tool_names = __esm(() => {
16064
16064
  "skill_improve",
16065
16065
  "spec_write",
16066
16066
  "knowledge_ack",
16067
+ "swarm_command",
16067
16068
  "lean_turbo_plan_lanes",
16068
16069
  "lean_turbo_acquire_locks",
16069
16070
  "lean_turbo_runner_status",
@@ -16316,6 +16317,7 @@ var init_constants = __esm(() => {
16316
16317
  "skill_inspect",
16317
16318
  "skill_improve",
16318
16319
  "knowledge_ack",
16320
+ "swarm_command",
16319
16321
  "lean_turbo_plan_lanes",
16320
16322
  "lean_turbo_acquire_locks",
16321
16323
  "lean_turbo_runner_status",
@@ -16337,7 +16339,8 @@ var init_constants = __esm(() => {
16337
16339
  "todo_extract",
16338
16340
  "doc_scan",
16339
16341
  "knowledge_recall",
16340
- "repo_map"
16342
+ "repo_map",
16343
+ "swarm_command"
16341
16344
  ],
16342
16345
  coder: [
16343
16346
  "diff",
@@ -16351,7 +16354,8 @@ var init_constants = __esm(() => {
16351
16354
  "syntax_check",
16352
16355
  "knowledge_add",
16353
16356
  "knowledge_recall",
16354
- "repo_map"
16357
+ "repo_map",
16358
+ "swarm_command"
16355
16359
  ],
16356
16360
  test_engineer: [
16357
16361
  "test_runner",
@@ -16366,7 +16370,8 @@ var init_constants = __esm(() => {
16366
16370
  "pkg_audit",
16367
16371
  "build_check",
16368
16372
  "syntax_check",
16369
- "search"
16373
+ "search",
16374
+ "swarm_command"
16370
16375
  ],
16371
16376
  sme: [
16372
16377
  "complexity_hotspots",
@@ -16377,7 +16382,8 @@ var init_constants = __esm(() => {
16377
16382
  "schema_drift",
16378
16383
  "search",
16379
16384
  "symbols",
16380
- "knowledge_recall"
16385
+ "knowledge_recall",
16386
+ "swarm_command"
16381
16387
  ],
16382
16388
  reviewer: [
16383
16389
  "diff",
@@ -16399,7 +16405,8 @@ var init_constants = __esm(() => {
16399
16405
  "search",
16400
16406
  "batch_symbols",
16401
16407
  "suggest_patch",
16402
- "repo_map"
16408
+ "repo_map",
16409
+ "swarm_command"
16403
16410
  ],
16404
16411
  critic: [
16405
16412
  "complexity_hotspots",
@@ -16410,7 +16417,8 @@ var init_constants = __esm(() => {
16410
16417
  "knowledge_recall",
16411
16418
  "req_coverage",
16412
16419
  "get_approved_plan",
16413
- "repo_map"
16420
+ "repo_map",
16421
+ "swarm_command"
16414
16422
  ],
16415
16423
  critic_sounding_board: [
16416
16424
  "complexity_hotspots",
@@ -16478,14 +16486,16 @@ var init_constants = __esm(() => {
16478
16486
  "search",
16479
16487
  "symbols",
16480
16488
  "todo_extract",
16481
- "knowledge_recall"
16489
+ "knowledge_recall",
16490
+ "swarm_command"
16482
16491
  ],
16483
16492
  designer: [
16484
16493
  "extract_code_blocks",
16485
16494
  "retrieve_summary",
16486
16495
  "search",
16487
16496
  "symbols",
16488
- "knowledge_recall"
16497
+ "knowledge_recall",
16498
+ "swarm_command"
16489
16499
  ],
16490
16500
  curator_init: ["knowledge_recall"],
16491
16501
  curator_phase: ["knowledge_recall"],
@@ -16501,7 +16511,8 @@ var init_constants = __esm(() => {
16501
16511
  "skill_improve",
16502
16512
  "search",
16503
16513
  "doc_scan",
16504
- "doc_extract"
16514
+ "doc_extract",
16515
+ "web_search"
16505
16516
  ],
16506
16517
  spec_writer: [
16507
16518
  "search",
@@ -16585,6 +16596,7 @@ var init_constants = __esm(() => {
16585
16596
  skill_improve: "run the skill_improver agent to review and refine skills",
16586
16597
  spec_write: "author or update .swarm/spec.md for the current project",
16587
16598
  knowledge_ack: "record an explicit KNOWLEDGE_APPLIED/IGNORED/VIOLATED acknowledgment",
16599
+ swarm_command: "run supported /swarm commands through the canonical command registry",
16588
16600
  lean_turbo_plan_lanes: "partition phase tasks into parallel lanes based on file-scope conflicts for Lean Turbo execution",
16589
16601
  lean_turbo_acquire_locks: "acquire file locks for all files in a lane (all-or-nothing) before lane execution",
16590
16602
  lean_turbo_runner_status: "read Lean Turbo run state from .swarm/turbo-state.json",
@@ -16601,67 +16613,67 @@ var init_constants = __esm(() => {
16601
16613
  DEFAULT_AGENT_CONFIGS = {
16602
16614
  coder: {
16603
16615
  model: "opencode/minimax-m2.5-free",
16604
- fallback_models: ["opencode/big-pickle"]
16616
+ fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
16605
16617
  },
16606
16618
  reviewer: {
16607
16619
  model: "opencode/big-pickle",
16608
- fallback_models: ["opencode/minimax-m2.5-free"]
16620
+ fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
16609
16621
  },
16610
16622
  test_engineer: {
16611
- model: "opencode/big-pickle",
16612
- fallback_models: ["opencode/minimax-m2.5-free"]
16623
+ model: "opencode/gpt-5-nano",
16624
+ fallback_models: ["opencode/big-pickle"]
16613
16625
  },
16614
16626
  explorer: {
16615
16627
  model: "opencode/big-pickle",
16616
- fallback_models: ["opencode/minimax-m2.5-free"]
16628
+ fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
16617
16629
  },
16618
16630
  sme: {
16619
16631
  model: "opencode/big-pickle",
16620
- fallback_models: ["opencode/minimax-m2.5-free"]
16632
+ fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
16621
16633
  },
16622
16634
  critic: {
16623
16635
  model: "opencode/big-pickle",
16624
- fallback_models: ["opencode/minimax-m2.5-free"]
16636
+ fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
16625
16637
  },
16626
16638
  docs: {
16627
16639
  model: "opencode/big-pickle",
16628
- fallback_models: ["opencode/minimax-m2.5-free"]
16640
+ fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
16629
16641
  },
16630
16642
  designer: {
16631
16643
  model: "opencode/big-pickle",
16632
- fallback_models: ["opencode/minimax-m2.5-free"]
16644
+ fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
16633
16645
  },
16634
16646
  critic_sounding_board: {
16635
- model: "opencode/big-pickle",
16636
- fallback_models: ["opencode/minimax-m2.5-free"]
16647
+ model: "opencode/gpt-5-nano",
16648
+ fallback_models: ["opencode/big-pickle"]
16637
16649
  },
16638
16650
  critic_drift_verifier: {
16639
- model: "opencode/big-pickle",
16640
- fallback_models: ["opencode/minimax-m2.5-free"]
16651
+ model: "opencode/gpt-5-nano",
16652
+ fallback_models: ["opencode/big-pickle"]
16641
16653
  },
16642
16654
  critic_hallucination_verifier: {
16643
- model: "opencode/big-pickle",
16644
- fallback_models: ["opencode/minimax-m2.5-free"]
16655
+ model: "opencode/gpt-5-nano",
16656
+ fallback_models: ["opencode/big-pickle"]
16645
16657
  },
16646
16658
  critic_oversight: {
16647
- model: "opencode/big-pickle",
16648
- fallback_models: ["opencode/minimax-m2.5-free"]
16659
+ model: "opencode/gpt-5-nano",
16660
+ fallback_models: ["opencode/big-pickle"]
16649
16661
  },
16650
16662
  curator_init: {
16651
- model: "opencode/big-pickle",
16652
- fallback_models: ["opencode/minimax-m2.5-free"]
16663
+ model: "opencode/gpt-5-nano",
16664
+ fallback_models: ["opencode/big-pickle"]
16653
16665
  },
16654
16666
  curator_phase: {
16655
- model: "opencode/big-pickle",
16656
- fallback_models: ["opencode/minimax-m2.5-free"]
16667
+ model: "opencode/gpt-5-nano",
16668
+ fallback_models: ["opencode/big-pickle"]
16657
16669
  },
16658
16670
  skill_improver: {
16659
16671
  model: "opencode/big-pickle",
16660
- fallback_models: ["opencode/minimax-m2.5-free"]
16672
+ fallback_models: ["opencode/gpt-5-nano"]
16661
16673
  },
16662
16674
  spec_writer: {
16663
16675
  model: "opencode/big-pickle",
16664
- fallback_models: ["opencode/minimax-m2.5-free"]
16676
+ fallback_models: ["opencode/gpt-5-nano"]
16665
16677
  }
16666
16678
  };
16667
16679
  });
@@ -17544,8 +17556,7 @@ function handleAgentsCommand(agents, guardrails) {
17544
17556
  if (hasUnregistered) {
17545
17557
  lines.push("", "### Unregistered Subagents");
17546
17558
  for (const name of unregistered) {
17547
- const hint = UNREGISTERED_AGENT_HINTS[name] ?? "requires configuration";
17548
- lines.push(`- **${name}** (${hint})`);
17559
+ lines.push(`- **${name}** (requires configuration)`);
17549
17560
  }
17550
17561
  }
17551
17562
  if (guardrails?.profiles && Object.keys(guardrails.profiles).length > 0) {
@@ -17574,18 +17585,9 @@ function handleAgentsCommand(agents, guardrails) {
17574
17585
  return lines.join(`
17575
17586
  `);
17576
17587
  }
17577
- var UNREGISTERED_AGENT_HINTS;
17578
17588
  var init_agents = __esm(() => {
17579
17589
  init_constants();
17580
17590
  init_schema();
17581
- UNREGISTERED_AGENT_HINTS = {
17582
- designer: "enable ui_review.enabled",
17583
- council_generalist: "enable council.general.enabled",
17584
- council_skeptic: "enable council.general.enabled",
17585
- council_domain_expert: "enable council.general.enabled",
17586
- skill_improver: "registered by default unless agents.skill_improver.disabled is true",
17587
- spec_writer: "registered by default unless agents.spec_writer.disabled is true"
17588
- };
17589
17591
  });
17590
17592
 
17591
17593
  // src/commands/analyze.ts
@@ -20236,13 +20238,6 @@ var init_qa_gate_profile = __esm(() => {
20236
20238
  final_council: false
20237
20239
  };
20238
20240
  });
20239
- // src/parallel/runtime-config.ts
20240
- var lockedProfileCache;
20241
- var init_runtime_config = __esm(() => {
20242
- init_plan_schema();
20243
- lockedProfileCache = new Map;
20244
- });
20245
-
20246
20241
  // node_modules/quick-lru/index.js
20247
20242
  var QuickLRU;
20248
20243
  var init_quick_lru = __esm(() => {
@@ -20888,7 +20883,6 @@ function clearPendingCoderScope() {
20888
20883
  var pendingCoderScopeByTaskId;
20889
20884
  var init_delegation_gate = __esm(() => {
20890
20885
  init_schema();
20891
- init_runtime_config();
20892
20886
  init_state();
20893
20887
  init_telemetry();
20894
20888
  init_logger();
@@ -38256,31 +38250,12 @@ function parseArgs(args) {
38256
38250
  }
38257
38251
  return out;
38258
38252
  }
38259
- async function handleCouncilCommand(directory, args) {
38253
+ async function handleCouncilCommand(_directory, args) {
38260
38254
  const parsed = parseArgs(args);
38261
38255
  const question = sanitizeQuestion(parsed.rest.join(" "));
38262
38256
  if (!question) {
38263
38257
  return USAGE;
38264
38258
  }
38265
- const config3 = loadPluginConfig(directory);
38266
- if (config3.council?.general?.enabled !== true) {
38267
- return [
38268
- "General Council is not enabled for this project.",
38269
- "",
38270
- "Enable it in `.opencode/opencode-swarm.json` or `~/.config/opencode/opencode-swarm.json`:",
38271
- "",
38272
- "```json",
38273
- "{",
38274
- ' "council": {',
38275
- ' "general": { "enabled": true }',
38276
- " }",
38277
- "}",
38278
- "```",
38279
- "",
38280
- "Then restart OpenCode and run `/swarm config doctor` before trying `/swarm council` again."
38281
- ].join(`
38282
- `);
38283
- }
38284
38259
  const tokens = ["MODE: COUNCIL"];
38285
38260
  if (parsed.preset) {
38286
38261
  tokens.push(`preset=${parsed.preset}`);
@@ -38292,7 +38267,6 @@ async function handleCouncilCommand(directory, args) {
38292
38267
  }
38293
38268
  var MAX_QUESTION_LEN = 2000, USAGE;
38294
38269
  var init_council = __esm(() => {
38295
- init_loader();
38296
38270
  USAGE = [
38297
38271
  "Usage: /swarm council <question> [--preset <name>] [--spec-review]",
38298
38272
  "",
@@ -39769,7 +39743,6 @@ __export(exports_config_doctor, {
39769
39743
  restoreFromBackup: () => restoreFromBackup,
39770
39744
  getConfigPaths: () => getConfigPaths,
39771
39745
  createConfigBackup: () => createConfigBackup,
39772
- collectConfiguredModelRefs: () => collectConfiguredModelRefs,
39773
39746
  applySafeAutoFixes: () => applySafeAutoFixes
39774
39747
  });
39775
39748
  import * as crypto3 from "crypto";
@@ -40163,129 +40136,6 @@ function validateConfigKey(path24, value, _config) {
40163
40136
  }
40164
40137
  return findings;
40165
40138
  }
40166
- function addConfiguredModel(refs, model, configPath) {
40167
- if (typeof model !== "string")
40168
- return;
40169
- const trimmed = model.trim();
40170
- if (!trimmed)
40171
- return;
40172
- const paths = refs.get(trimmed) ?? new Set;
40173
- paths.add(configPath);
40174
- refs.set(trimmed, paths);
40175
- }
40176
- function addConfiguredAgentModels(refs, agents, prefix) {
40177
- if (!agents || typeof agents !== "object" || Array.isArray(agents))
40178
- return;
40179
- for (const [agentName, value] of Object.entries(agents)) {
40180
- if (!value || typeof value !== "object" || Array.isArray(value))
40181
- continue;
40182
- const agent = value;
40183
- addConfiguredModel(refs, agent.model, `${prefix}.${agentName}.model`);
40184
- if (Array.isArray(agent.fallback_models)) {
40185
- agent.fallback_models.forEach((model, index) => {
40186
- addConfiguredModel(refs, model, `${prefix}.${agentName}.fallback_models[${index}]`);
40187
- });
40188
- }
40189
- }
40190
- }
40191
- function collectConfiguredModelRefs(config3) {
40192
- const refs = new Map;
40193
- const rawConfig = config3;
40194
- addConfiguredAgentModels(refs, rawConfig.agents, "agents");
40195
- if (rawConfig.swarms && typeof rawConfig.swarms === "object" && !Array.isArray(rawConfig.swarms)) {
40196
- for (const [swarmId, value] of Object.entries(rawConfig.swarms)) {
40197
- if (!value || typeof value !== "object" || Array.isArray(value))
40198
- continue;
40199
- addConfiguredAgentModels(refs, value.agents, `swarms.${swarmId}.agents`);
40200
- }
40201
- }
40202
- if (rawConfig.full_auto && typeof rawConfig.full_auto === "object" && !Array.isArray(rawConfig.full_auto)) {
40203
- addConfiguredModel(refs, rawConfig.full_auto.critic_model, "full_auto.critic_model");
40204
- }
40205
- if (rawConfig.skill_improver && typeof rawConfig.skill_improver === "object" && !Array.isArray(rawConfig.skill_improver)) {
40206
- const skillImprover = rawConfig.skill_improver;
40207
- addConfiguredModel(refs, skillImprover.model, "skill_improver.model");
40208
- if (Array.isArray(skillImprover.fallback_models)) {
40209
- skillImprover.fallback_models.forEach((model, index) => {
40210
- addConfiguredModel(refs, model, `skill_improver.fallback_models[${index}]`);
40211
- });
40212
- }
40213
- }
40214
- if (rawConfig.spec_writer && typeof rawConfig.spec_writer === "object" && !Array.isArray(rawConfig.spec_writer)) {
40215
- const specWriter = rawConfig.spec_writer;
40216
- addConfiguredModel(refs, specWriter.model, "spec_writer.model");
40217
- if (Array.isArray(specWriter.fallback_models)) {
40218
- specWriter.fallback_models.forEach((model, index) => {
40219
- addConfiguredModel(refs, model, `spec_writer.fallback_models[${index}]`);
40220
- });
40221
- }
40222
- }
40223
- const council = rawConfig.council;
40224
- const general = council && typeof council === "object" && !Array.isArray(council) ? council.general : undefined;
40225
- if (general && typeof general === "object" && !Array.isArray(general)) {
40226
- addConfiguredModel(refs, general.moderatorModel, "council.general.moderatorModel");
40227
- if (Array.isArray(general.members)) {
40228
- general.members.forEach((member, index) => {
40229
- if (!member || typeof member !== "object" || Array.isArray(member)) {
40230
- return;
40231
- }
40232
- addConfiguredModel(refs, member.model, `council.general.members[${index}].model`);
40233
- });
40234
- }
40235
- if (general.presets && typeof general.presets === "object" && !Array.isArray(general.presets)) {
40236
- for (const [presetName, members] of Object.entries(general.presets)) {
40237
- if (!Array.isArray(members))
40238
- continue;
40239
- members.forEach((member, index) => {
40240
- if (!member || typeof member !== "object" || Array.isArray(member)) {
40241
- return;
40242
- }
40243
- addConfiguredModel(refs, member.model, `council.general.presets.${presetName}[${index}].model`);
40244
- });
40245
- }
40246
- }
40247
- }
40248
- return refs;
40249
- }
40250
- function validateConfiguredModels(config3, modelAvailability) {
40251
- const refs = collectConfiguredModelRefs(config3);
40252
- const findings = [];
40253
- if (modelAvailability.error) {
40254
- findings.push({
40255
- id: "model-availability-unchecked",
40256
- title: "Model availability check skipped",
40257
- description: `Could not load OpenCode provider models from ${modelAvailability.source}: ` + modelAvailability.error,
40258
- severity: "info",
40259
- path: "agents",
40260
- autoFixable: false
40261
- });
40262
- return findings;
40263
- }
40264
- if (refs.size === 0)
40265
- return findings;
40266
- for (const [modelId, paths] of refs.entries()) {
40267
- if (modelAvailability.availableModelIds.has(modelId))
40268
- continue;
40269
- findings.push({
40270
- id: "configured-model-unavailable",
40271
- title: "Configured model is unavailable",
40272
- description: `Configured model ${formatModelIdForDoctor(modelId)} was not found in the active OpenCode provider model registry. ` + "Run `/models` to choose a currently available model, then update opencode-swarm.json.",
40273
- severity: "error",
40274
- path: [...paths].sort().join(", "),
40275
- currentValue: modelId,
40276
- autoFixable: false
40277
- });
40278
- }
40279
- return findings;
40280
- }
40281
- function formatModelIdForDoctor(modelId) {
40282
- const json3 = JSON.stringify(modelId);
40283
- if (!json3)
40284
- return '"<invalid model id>"';
40285
- if (json3.length <= 160)
40286
- return json3;
40287
- return `${json3.slice(0, 157)}..."`;
40288
- }
40289
40139
  function walkConfigAndValidate(obj, path24, config3, findings) {
40290
40140
  if (obj === null || obj === undefined) {
40291
40141
  return;
@@ -40310,12 +40160,9 @@ function walkConfigAndValidate(obj, path24, config3, findings) {
40310
40160
  walkConfigAndValidate(value, newPath, config3, findings);
40311
40161
  }
40312
40162
  }
40313
- function runConfigDoctor(config3, directory, options = {}) {
40163
+ function runConfigDoctor(config3, directory) {
40314
40164
  const findings = [];
40315
40165
  walkConfigAndValidate(config3, "", config3, findings);
40316
- if (options.modelAvailability) {
40317
- findings.push(...validateConfiguredModels(config3, options.modelAvailability));
40318
- }
40319
40166
  const summary = {
40320
40167
  info: findings.filter((f) => f.severity === "info").length,
40321
40168
  warn: findings.filter((f) => f.severity === "warn").length,
@@ -40477,8 +40324,8 @@ function shouldRunOnStartup(automationConfig) {
40477
40324
  }
40478
40325
  return automationConfig.capabilities?.config_doctor_on_startup === true;
40479
40326
  }
40480
- async function runConfigDoctorWithFixes(directory, config3, autoFix = false, options = {}) {
40481
- const result = runConfigDoctor(config3, directory, options);
40327
+ async function runConfigDoctorWithFixes(directory, config3, autoFix = false) {
40328
+ const result = runConfigDoctor(config3, directory);
40482
40329
  const artifactPath = writeDoctorArtifact(directory, result);
40483
40330
  if (!autoFix) {
40484
40331
  return {
@@ -40498,7 +40345,7 @@ async function runConfigDoctorWithFixes(directory, config3, autoFix = false, opt
40498
40345
  if (appliedFixes.length > 0) {
40499
40346
  const freshConfig = readConfigFromFile(directory);
40500
40347
  if (freshConfig) {
40501
- const newResult = runConfigDoctor(freshConfig.config, directory, options);
40348
+ const newResult = runConfigDoctor(freshConfig.config, directory);
40502
40349
  writeDoctorArtifact(directory, newResult);
40503
40350
  }
40504
40351
  }
@@ -42120,23 +41967,6 @@ var init_tool_doctor = __esm(() => {
42120
41967
  ];
42121
41968
  });
42122
41969
 
42123
- // src/utils/timeout.ts
42124
- async function withTimeout(promise3, ms, timeoutError) {
42125
- let timer;
42126
- const timeoutPromise = new Promise((_, reject) => {
42127
- timer = setTimeout(() => reject(timeoutError), ms);
42128
- if (typeof timer.unref === "function") {
42129
- timer.unref();
42130
- }
42131
- });
42132
- try {
42133
- return await Promise.race([promise3, timeoutPromise]);
42134
- } finally {
42135
- if (timer !== undefined)
42136
- clearTimeout(timer);
42137
- }
42138
- }
42139
-
42140
41970
  // src/commands/doctor.ts
42141
41971
  function formatToolDoctorMarkdown(result) {
42142
41972
  const lines = [
@@ -42210,67 +42040,13 @@ function formatDoctorMarkdown(result) {
42210
42040
  return lines.join(`
42211
42041
  `);
42212
42042
  }
42213
- function extractAvailableModelIds(response) {
42214
- const available = new Set;
42215
- if (response?.providers !== undefined && !Array.isArray(response.providers)) {
42216
- throw new Error("provider registry returned malformed provider list");
42217
- }
42218
- for (const provider of response?.providers ?? []) {
42219
- if (!provider || typeof provider !== "object" || !provider.id || !provider.models || typeof provider.models !== "object" || Array.isArray(provider.models)) {
42220
- continue;
42221
- }
42222
- for (const [modelKey, modelInfo] of Object.entries(provider.models)) {
42223
- available.add(`${provider.id}/${modelKey}`);
42224
- if (modelInfo && typeof modelInfo === "object" && modelInfo.id) {
42225
- available.add(`${provider.id}/${modelInfo.id}`);
42226
- }
42227
- }
42228
- }
42229
- return available;
42230
- }
42231
- async function loadModelAvailability(directory, client, options = {}) {
42232
- const providerClient = client;
42233
- const providers = providerClient?.config?.providers;
42234
- if (typeof providers !== "function") {
42235
- return;
42236
- }
42237
- try {
42238
- const response = await withTimeout(providers({ directory }), options.timeoutMs ?? MODEL_REGISTRY_TIMEOUT_MS, new Error(`OpenCode provider model registry lookup exceeded ${options.timeoutMs ?? MODEL_REGISTRY_TIMEOUT_MS}ms`));
42239
- if (response.error) {
42240
- return {
42241
- availableModelIds: new Set,
42242
- source: MODEL_REGISTRY_SOURCE,
42243
- error: typeof response.error === "string" ? response.error : JSON.stringify(response.error)
42244
- };
42245
- }
42246
- if (!response.data) {
42247
- return {
42248
- availableModelIds: new Set,
42249
- source: MODEL_REGISTRY_SOURCE,
42250
- error: "provider registry returned no data"
42251
- };
42252
- }
42253
- return {
42254
- availableModelIds: extractAvailableModelIds(response.data),
42255
- source: MODEL_REGISTRY_SOURCE
42256
- };
42257
- } catch (error93) {
42258
- return {
42259
- availableModelIds: new Set,
42260
- source: MODEL_REGISTRY_SOURCE,
42261
- error: error93 instanceof Error ? error93.message : String(error93)
42262
- };
42263
- }
42264
- }
42265
- async function handleDoctorCommand(directory, args, options = {}) {
42043
+ async function handleDoctorCommand(directory, args) {
42266
42044
  const enableAutoFix = args.includes("--fix") || args.includes("-f");
42267
42045
  const config3 = loadPluginConfig(directory);
42268
- const modelAvailability = await loadModelAvailability(directory, options.client);
42269
- const doctorOptions = { modelAvailability };
42270
- const result = runConfigDoctor(config3, directory, doctorOptions);
42046
+ const result = runConfigDoctor(config3, directory);
42271
42047
  if (enableAutoFix && result.hasAutoFixableIssues) {
42272
42048
  const { runConfigDoctorWithFixes: runConfigDoctorWithFixes2 } = await Promise.resolve().then(() => (init_config_doctor(), exports_config_doctor));
42273
- const fixResult = await runConfigDoctorWithFixes2(directory, config3, true, doctorOptions);
42049
+ const fixResult = await runConfigDoctorWithFixes2(directory, config3, true);
42274
42050
  return formatDoctorMarkdown(fixResult.result);
42275
42051
  }
42276
42052
  return formatDoctorMarkdown(result);
@@ -42279,7 +42055,6 @@ async function handleDoctorToolsCommand(directory, _args) {
42279
42055
  const result = runToolDoctor(directory);
42280
42056
  return formatToolDoctorMarkdown(result);
42281
42057
  }
42282
- var MODEL_REGISTRY_TIMEOUT_MS = 3000, MODEL_REGISTRY_SOURCE = "OpenCode config.providers";
42283
42058
  var init_doctor = __esm(() => {
42284
42059
  init_loader();
42285
42060
  init_config_doctor();
@@ -42620,7 +42395,7 @@ function getVerdictEmoji(verdict) {
42620
42395
  return getVerdictIcon(verdict);
42621
42396
  }
42622
42397
  async function getTaskEvidenceData(directory, taskId) {
42623
- const result = await loadEvidence(directory, taskId);
42398
+ const result = await _internals13.loadEvidence(directory, taskId);
42624
42399
  if (result.status !== "found") {
42625
42400
  return {
42626
42401
  hasEvidence: false,
@@ -42643,13 +42418,13 @@ async function getTaskEvidenceData(directory, taskId) {
42643
42418
  };
42644
42419
  }
42645
42420
  async function getEvidenceListData(directory) {
42646
- const taskIds = await listEvidenceTaskIds(directory);
42421
+ const taskIds = await _internals13.listEvidenceTaskIds(directory);
42647
42422
  if (taskIds.length === 0) {
42648
42423
  return { hasEvidence: false, tasks: [] };
42649
42424
  }
42650
42425
  const tasks = [];
42651
42426
  for (const taskId of taskIds) {
42652
- const result = await loadEvidence(directory, taskId);
42427
+ const result = await _internals13.loadEvidence(directory, taskId);
42653
42428
  if (result.status === "found") {
42654
42429
  tasks.push({
42655
42430
  taskId,
@@ -42763,8 +42538,13 @@ async function handleEvidenceSummaryCommand(directory) {
42763
42538
  return lines.join(`
42764
42539
  `);
42765
42540
  }
42541
+ var _internals13;
42766
42542
  var init_evidence_service = __esm(() => {
42767
42543
  init_manager2();
42544
+ _internals13 = {
42545
+ loadEvidence,
42546
+ listEvidenceTaskIds
42547
+ };
42768
42548
  });
42769
42549
 
42770
42550
  // src/commands/evidence.ts
@@ -43168,7 +42948,7 @@ function extractCurrentPhaseFromPlan2(plan) {
43168
42948
  if (!plan) {
43169
42949
  return { currentPhase: null, currentTask: null, incompleteTasks: [] };
43170
42950
  }
43171
- if (!_internals13.validatePlanPhases(plan)) {
42951
+ if (!_internals14.validatePlanPhases(plan)) {
43172
42952
  return { currentPhase: null, currentTask: null, incompleteTasks: [] };
43173
42953
  }
43174
42954
  let currentPhase = null;
@@ -43310,9 +43090,9 @@ function extractPhaseMetrics(content) {
43310
43090
  async function getHandoffData(directory) {
43311
43091
  const now = new Date().toISOString();
43312
43092
  const sessionContent = await readSwarmFileAsync(directory, "session/state.json");
43313
- const sessionState = _internals13.parseSessionState(sessionContent);
43093
+ const sessionState = _internals14.parseSessionState(sessionContent);
43314
43094
  const plan = await loadPlanJsonOnly(directory);
43315
- const planInfo = _internals13.extractCurrentPhaseFromPlan(plan);
43095
+ const planInfo = _internals14.extractCurrentPhaseFromPlan(plan);
43316
43096
  if (!plan) {
43317
43097
  const planMdContent = await readSwarmFileAsync(directory, "plan.md");
43318
43098
  if (planMdContent) {
@@ -43331,8 +43111,8 @@ async function getHandoffData(directory) {
43331
43111
  }
43332
43112
  }
43333
43113
  const contextContent = await readSwarmFileAsync(directory, "context.md");
43334
- const recentDecisions = _internals13.extractDecisions(contextContent);
43335
- const rawPhaseMetrics = _internals13.extractPhaseMetrics(contextContent);
43114
+ const recentDecisions = _internals14.extractDecisions(contextContent);
43115
+ const rawPhaseMetrics = _internals14.extractPhaseMetrics(contextContent);
43336
43116
  const phaseMetrics = sanitizeString(rawPhaseMetrics, 1000);
43337
43117
  let delegationState = null;
43338
43118
  if (sessionState?.delegationState) {
@@ -43496,13 +43276,13 @@ ${lines.join(`
43496
43276
  `)}
43497
43277
  \`\`\``;
43498
43278
  }
43499
- var RTL_OVERRIDE_PATTERN, MAX_TASK_ID_LENGTH = 100, MAX_DECISION_LENGTH = 500, MAX_INCOMPLETE_TASKS = 20, _internals13;
43279
+ var RTL_OVERRIDE_PATTERN, MAX_TASK_ID_LENGTH = 100, MAX_DECISION_LENGTH = 500, MAX_INCOMPLETE_TASKS = 20, _internals14;
43500
43280
  var init_handoff_service = __esm(() => {
43501
43281
  init_utils2();
43502
43282
  init_manager();
43503
43283
  init_utils();
43504
43284
  RTL_OVERRIDE_PATTERN = /[\u202e\u202d\u202c\u200f]/g;
43505
- _internals13 = {
43285
+ _internals14 = {
43506
43286
  getHandoffData,
43507
43287
  formatHandoffMarkdown,
43508
43288
  formatContinuationPrompt,
@@ -43621,22 +43401,22 @@ async function writeSnapshot(directory, state) {
43621
43401
  }
43622
43402
  function createSnapshotWriterHook(directory) {
43623
43403
  return (_input, _output) => {
43624
- _writeInFlight = _writeInFlight.then(() => _internals14.writeSnapshot(directory, swarmState), () => _internals14.writeSnapshot(directory, swarmState));
43404
+ _writeInFlight = _writeInFlight.then(() => _internals15.writeSnapshot(directory, swarmState), () => _internals15.writeSnapshot(directory, swarmState));
43625
43405
  return _writeInFlight;
43626
43406
  };
43627
43407
  }
43628
43408
  async function flushPendingSnapshot(directory) {
43629
- _writeInFlight = _writeInFlight.then(() => _internals14.writeSnapshot(directory, swarmState), () => _internals14.writeSnapshot(directory, swarmState));
43409
+ _writeInFlight = _writeInFlight.then(() => _internals15.writeSnapshot(directory, swarmState), () => _internals15.writeSnapshot(directory, swarmState));
43630
43410
  await _writeInFlight;
43631
43411
  }
43632
- var _writeInFlight, _internals14;
43412
+ var _writeInFlight, _internals15;
43633
43413
  var init_snapshot_writer = __esm(() => {
43634
43414
  init_utils2();
43635
43415
  init_state();
43636
43416
  init_utils();
43637
43417
  init_bun_compat();
43638
43418
  _writeInFlight = Promise.resolve();
43639
- _internals14 = {
43419
+ _internals15 = {
43640
43420
  writeSnapshot,
43641
43421
  createSnapshotWriterHook,
43642
43422
  flushPendingSnapshot
@@ -44101,9 +43881,9 @@ async function migrateContextToKnowledge(directory, config3) {
44101
43881
  skippedReason: "empty-context"
44102
43882
  };
44103
43883
  }
44104
- const rawEntries = _internals15.parseContextMd(contextContent);
43884
+ const rawEntries = _internals16.parseContextMd(contextContent);
44105
43885
  if (rawEntries.length === 0) {
44106
- await _internals15.writeSentinel(sentinelPath, 0, 0);
43886
+ await _internals16.writeSentinel(sentinelPath, 0, 0);
44107
43887
  return {
44108
43888
  migrated: true,
44109
43889
  entriesMigrated: 0,
@@ -44114,10 +43894,10 @@ async function migrateContextToKnowledge(directory, config3) {
44114
43894
  const existing = await readKnowledge(knowledgePath);
44115
43895
  let migrated = 0;
44116
43896
  let dropped = 0;
44117
- const projectName = _internals15.inferProjectName(directory);
43897
+ const projectName = _internals16.inferProjectName(directory);
44118
43898
  for (const raw of rawEntries) {
44119
43899
  if (config3.validation_enabled !== false) {
44120
- const category = raw.categoryHint ?? _internals15.inferCategoryFromText(raw.text);
43900
+ const category = raw.categoryHint ?? _internals16.inferCategoryFromText(raw.text);
44121
43901
  const result = validateLesson(raw.text, existing.map((e) => e.lesson), {
44122
43902
  category,
44123
43903
  scope: "global",
@@ -44137,8 +43917,8 @@ async function migrateContextToKnowledge(directory, config3) {
44137
43917
  const entry = {
44138
43918
  id: randomUUID2(),
44139
43919
  tier: "swarm",
44140
- lesson: _internals15.truncateLesson(raw.text),
44141
- category: raw.categoryHint ?? _internals15.inferCategoryFromText(raw.text),
43920
+ lesson: _internals16.truncateLesson(raw.text),
43921
+ category: raw.categoryHint ?? _internals16.inferCategoryFromText(raw.text),
44142
43922
  tags: [...inferredTags, `migration:${raw.sourceSection}`],
44143
43923
  scope: "global",
44144
43924
  confidence: 0.3,
@@ -44161,7 +43941,7 @@ async function migrateContextToKnowledge(directory, config3) {
44161
43941
  if (migrated > 0) {
44162
43942
  await rewriteKnowledge(knowledgePath, existing);
44163
43943
  }
44164
- await _internals15.writeSentinel(sentinelPath, migrated, dropped);
43944
+ await _internals16.writeSentinel(sentinelPath, migrated, dropped);
44165
43945
  log(`[knowledge-migrator] Migrated ${migrated} entries, dropped ${dropped}`);
44166
43946
  return {
44167
43947
  migrated: true,
@@ -44171,7 +43951,7 @@ async function migrateContextToKnowledge(directory, config3) {
44171
43951
  };
44172
43952
  }
44173
43953
  function parseContextMd(content) {
44174
- const sections = _internals15.splitIntoSections(content);
43954
+ const sections = _internals16.splitIntoSections(content);
44175
43955
  const entries = [];
44176
43956
  const seen = new Set;
44177
43957
  const sectionPatterns = [
@@ -44187,7 +43967,7 @@ function parseContextMd(content) {
44187
43967
  const match = sectionPatterns.find((sp) => sp.pattern.test(section.heading));
44188
43968
  if (!match)
44189
43969
  continue;
44190
- const bullets = _internals15.extractBullets(section.body);
43970
+ const bullets = _internals16.extractBullets(section.body);
44191
43971
  for (const bullet of bullets) {
44192
43972
  if (bullet.length < 15)
44193
43973
  continue;
@@ -44196,9 +43976,9 @@ function parseContextMd(content) {
44196
43976
  continue;
44197
43977
  seen.add(normalized);
44198
43978
  entries.push({
44199
- text: _internals15.truncateLesson(bullet),
43979
+ text: _internals16.truncateLesson(bullet),
44200
43980
  sourceSection: match.sourceSection,
44201
- categoryHint: _internals15.inferCategoryFromText(bullet)
43981
+ categoryHint: _internals16.inferCategoryFromText(bullet)
44202
43982
  });
44203
43983
  }
44204
43984
  }
@@ -44291,12 +44071,12 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
44291
44071
  await mkdir8(path28.dirname(sentinelPath), { recursive: true });
44292
44072
  await writeFile9(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
44293
44073
  }
44294
- var _internals15;
44074
+ var _internals16;
44295
44075
  var init_knowledge_migrator = __esm(() => {
44296
44076
  init_logger();
44297
44077
  init_knowledge_store();
44298
44078
  init_knowledge_validator();
44299
- _internals15 = {
44079
+ _internals16 = {
44300
44080
  migrateContextToKnowledge,
44301
44081
  migrateKnowledgeToExternal,
44302
44082
  parseContextMd,
@@ -44433,9 +44213,9 @@ var init_knowledge = __esm(() => {
44433
44213
 
44434
44214
  // src/services/plan-service.ts
44435
44215
  async function getPlanData(directory, phaseArg) {
44436
- const plan = await loadPlanJsonOnly(directory);
44216
+ const plan = await _internals17.loadPlanJsonOnly(directory);
44437
44217
  if (plan) {
44438
- const fullMarkdown = derivePlanMarkdown(plan);
44218
+ const fullMarkdown = _internals17.derivePlanMarkdown(plan);
44439
44219
  if (phaseArg === undefined || phaseArg === null || phaseArg === "") {
44440
44220
  return {
44441
44221
  hasPlan: true,
@@ -44478,7 +44258,7 @@ async function getPlanData(directory, phaseArg) {
44478
44258
  isLegacy: false
44479
44259
  };
44480
44260
  }
44481
- const planContent = await readSwarmFileAsync(directory, "plan.md");
44261
+ const planContent = await _internals17.readSwarmFileAsync(directory, "plan.md");
44482
44262
  if (!planContent) {
44483
44263
  return {
44484
44264
  hasPlan: false,
@@ -44574,9 +44354,15 @@ async function handlePlanCommand(directory, args) {
44574
44354
  const planData = await getPlanData(directory, phaseArg);
44575
44355
  return formatPlanMarkdown(planData);
44576
44356
  }
44357
+ var _internals17;
44577
44358
  var init_plan_service = __esm(() => {
44578
44359
  init_utils2();
44579
44360
  init_manager();
44361
+ _internals17 = {
44362
+ loadPlanJsonOnly,
44363
+ derivePlanMarkdown,
44364
+ readSwarmFileAsync
44365
+ };
44580
44366
  });
44581
44367
 
44582
44368
  // src/commands/plan.ts
@@ -45162,7 +44948,7 @@ async function runAdditionalLint(linter, mode, cwd) {
45162
44948
  };
45163
44949
  }
45164
44950
  }
45165
- var MAX_OUTPUT_BYTES = 512000, MAX_COMMAND_LENGTH = 500, lint, _internals16;
44951
+ var MAX_OUTPUT_BYTES = 512000, MAX_COMMAND_LENGTH = 500, lint, _internals18;
45166
44952
  var init_lint = __esm(() => {
45167
44953
  init_zod();
45168
44954
  init_discovery();
@@ -45194,15 +44980,15 @@ var init_lint = __esm(() => {
45194
44980
  }
45195
44981
  const { mode } = args;
45196
44982
  const cwd = directory;
45197
- const linter = await _internals16.detectAvailableLinter(directory);
44983
+ const linter = await _internals18.detectAvailableLinter(directory);
45198
44984
  if (linter) {
45199
- const result = await _internals16.runLint(linter, mode, directory);
44985
+ const result = await _internals18.runLint(linter, mode, directory);
45200
44986
  return JSON.stringify(result, null, 2);
45201
44987
  }
45202
- const additionalLinter = _internals16.detectAdditionalLinter(cwd);
44988
+ const additionalLinter = _internals18.detectAdditionalLinter(cwd);
45203
44989
  if (additionalLinter) {
45204
44990
  warn(`[lint] Using ${additionalLinter} linter for this project`);
45205
- const result = await _internals16.runAdditionalLint(additionalLinter, mode, cwd);
44991
+ const result = await _internals18.runAdditionalLint(additionalLinter, mode, cwd);
45206
44992
  return JSON.stringify(result, null, 2);
45207
44993
  }
45208
44994
  const errorResult = {
@@ -45216,7 +45002,7 @@ For Rust: rustup component add clippy`
45216
45002
  return JSON.stringify(errorResult, null, 2);
45217
45003
  }
45218
45004
  });
45219
- _internals16 = {
45005
+ _internals18 = {
45220
45006
  detectAvailableLinter,
45221
45007
  runLint,
45222
45008
  detectAdditionalLinter,
@@ -45530,7 +45316,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
45530
45316
  }
45531
45317
  async function runSecretscan(directory) {
45532
45318
  try {
45533
- const result = await _internals17.secretscan.execute({ directory }, {});
45319
+ const result = await _internals19.secretscan.execute({ directory }, {});
45534
45320
  const jsonStr = typeof result === "string" ? result : result.output;
45535
45321
  return JSON.parse(jsonStr);
45536
45322
  } catch (e) {
@@ -45545,7 +45331,7 @@ async function runSecretscan(directory) {
45545
45331
  return errorResult;
45546
45332
  }
45547
45333
  }
45548
- var MAX_FILE_PATH_LENGTH = 500, MAX_FILE_SIZE_BYTES, MAX_FILES_SCANNED = 1000, MAX_FINDINGS = 100, MAX_OUTPUT_BYTES2 = 512000, MAX_LINE_LENGTH = 1e4, MAX_CONTENT_BYTES, BINARY_SIGNATURES, BINARY_PREFIX_BYTES = 4, BINARY_NULL_CHECK_BYTES = 8192, BINARY_NULL_THRESHOLD = 0.1, DEFAULT_EXCLUDE_DIRS, DEFAULT_EXCLUDE_EXTENSIONS, SECRET_PATTERNS, O_NOFOLLOW, secretscan, _internals17;
45334
+ var MAX_FILE_PATH_LENGTH = 500, MAX_FILE_SIZE_BYTES, MAX_FILES_SCANNED = 1000, MAX_FINDINGS = 100, MAX_OUTPUT_BYTES2 = 512000, MAX_LINE_LENGTH = 1e4, MAX_CONTENT_BYTES, BINARY_SIGNATURES, BINARY_PREFIX_BYTES = 4, BINARY_NULL_CHECK_BYTES = 8192, BINARY_NULL_THRESHOLD = 0.1, DEFAULT_EXCLUDE_DIRS, DEFAULT_EXCLUDE_EXTENSIONS, SECRET_PATTERNS, O_NOFOLLOW, secretscan, _internals19;
45549
45335
  var init_secretscan = __esm(() => {
45550
45336
  init_zod();
45551
45337
  init_path_security();
@@ -45917,7 +45703,7 @@ var init_secretscan = __esm(() => {
45917
45703
  }
45918
45704
  }
45919
45705
  });
45920
- _internals17 = {
45706
+ _internals19 = {
45921
45707
  secretscan,
45922
45708
  runSecretscan
45923
45709
  };
@@ -46489,14 +46275,14 @@ function buildGoBackend() {
46489
46275
  selectEntryPoints
46490
46276
  };
46491
46277
  }
46492
- var PROFILE_ID = "go", IMPORT_REGEX_SINGLE, IMPORT_REGEX_GROUP, IMPORT_REGEX_GROUP_LINE, _internals18;
46278
+ var PROFILE_ID = "go", IMPORT_REGEX_SINGLE, IMPORT_REGEX_GROUP, IMPORT_REGEX_GROUP_LINE, _internals20;
46493
46279
  var init_go = __esm(() => {
46494
46280
  init_default_backend();
46495
46281
  init_profiles();
46496
46282
  IMPORT_REGEX_SINGLE = /^\s*import\s+(?:[a-zA-Z_.][a-zA-Z0-9_]*\s+)?"([^"]+)"/gm;
46497
46283
  IMPORT_REGEX_GROUP = /^\s*import\s*\(([\s\S]*?)\)/gm;
46498
46284
  IMPORT_REGEX_GROUP_LINE = /(?:[a-zA-Z_.][a-zA-Z0-9_]*\s+)?"([^"]+)"/g;
46499
- _internals18 = { extractImports };
46285
+ _internals20 = { extractImports };
46500
46286
  });
46501
46287
 
46502
46288
  // src/lang/backends/python.ts
@@ -46608,13 +46394,13 @@ function buildPythonBackend() {
46608
46394
  selectEntryPoints: selectEntryPoints2
46609
46395
  };
46610
46396
  }
46611
- var PROFILE_ID2 = "python", IMPORT_REGEX_FROM_WITH_TARGETS, IMPORT_REGEX_IMPORT, _internals19;
46397
+ var PROFILE_ID2 = "python", IMPORT_REGEX_FROM_WITH_TARGETS, IMPORT_REGEX_IMPORT, _internals21;
46612
46398
  var init_python = __esm(() => {
46613
46399
  init_default_backend();
46614
46400
  init_profiles();
46615
46401
  IMPORT_REGEX_FROM_WITH_TARGETS = /^\s*from\s+(\.*[\w.]*)\s+import\s+(\([^)]*\)|[^\n#]+)/gm;
46616
46402
  IMPORT_REGEX_IMPORT = /^\s*import\s+([^\n#]+)/gm;
46617
- _internals19 = { extractImports: extractImports2 };
46403
+ _internals21 = { extractImports: extractImports2 };
46618
46404
  });
46619
46405
 
46620
46406
  // src/test-impact/analyzer.ts
@@ -46825,7 +46611,7 @@ function addImpactEdgesForTestFile(testFile, content, impactMap) {
46825
46611
  return;
46826
46612
  }
46827
46613
  if (PYTHON_EXTENSIONS.has(ext)) {
46828
- const modules = _internals19.extractImports(testFile, content);
46614
+ const modules = _internals21.extractImports(testFile, content);
46829
46615
  for (const mod of modules) {
46830
46616
  const resolved = resolvePythonImport(testDir, mod);
46831
46617
  if (resolved !== null)
@@ -46834,7 +46620,7 @@ function addImpactEdgesForTestFile(testFile, content, impactMap) {
46834
46620
  return;
46835
46621
  }
46836
46622
  if (GO_EXTENSIONS.has(ext)) {
46837
- const imports = _internals18.extractImports(testFile, content);
46623
+ const imports = _internals20.extractImports(testFile, content);
46838
46624
  for (const importPath of imports) {
46839
46625
  const sourceFiles = resolveGoImport(testDir, importPath);
46840
46626
  for (const source of sourceFiles)
@@ -46861,8 +46647,8 @@ async function buildImpactMapInternal(cwd) {
46861
46647
  return impactMap;
46862
46648
  }
46863
46649
  async function buildImpactMap(cwd) {
46864
- const impactMap = await _internals20.buildImpactMapInternal(cwd);
46865
- await _internals20.saveImpactMap(cwd, impactMap);
46650
+ const impactMap = await _internals22.buildImpactMapInternal(cwd);
46651
+ await _internals22.saveImpactMap(cwd, impactMap);
46866
46652
  return impactMap;
46867
46653
  }
46868
46654
  async function loadImpactMap(cwd) {
@@ -46873,12 +46659,12 @@ async function loadImpactMap(cwd) {
46873
46659
  const data = JSON.parse(content);
46874
46660
  const map3 = data.map;
46875
46661
  const generatedAt = new Date(data.generatedAt).getTime();
46876
- if (!_internals20.isCacheStale(map3, generatedAt)) {
46662
+ if (!_internals22.isCacheStale(map3, generatedAt)) {
46877
46663
  return map3;
46878
46664
  }
46879
46665
  } catch {}
46880
46666
  }
46881
- return _internals20.buildImpactMap(cwd);
46667
+ return _internals22.buildImpactMap(cwd);
46882
46668
  }
46883
46669
  async function saveImpactMap(cwd, impactMap) {
46884
46670
  const cacheDir2 = path34.join(cwd, ".swarm", "cache");
@@ -46904,7 +46690,7 @@ async function analyzeImpact(changedFiles, cwd) {
46904
46690
  };
46905
46691
  }
46906
46692
  const validFiles = changedFiles.filter((f) => typeof f === "string" && f.length > 0 && !f.includes("\x00"));
46907
- const impactMap = await _internals20.loadImpactMap(cwd);
46693
+ const impactMap = await _internals22.loadImpactMap(cwd);
46908
46694
  const impactedTestsSet = new Set;
46909
46695
  const untestedFiles = [];
46910
46696
  for (const changedFile of validFiles) {
@@ -46945,7 +46731,7 @@ async function analyzeImpact(changedFiles, cwd) {
46945
46731
  impactMap
46946
46732
  };
46947
46733
  }
46948
- var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, TS_EXTENSIONS, PYTHON_EXTENSIONS, GO_EXTENSIONS, EXTENSIONS_TO_TRY, goModuleCache, _internals20;
46734
+ var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, TS_EXTENSIONS, PYTHON_EXTENSIONS, GO_EXTENSIONS, EXTENSIONS_TO_TRY, goModuleCache, _internals22;
46949
46735
  var init_analyzer = __esm(() => {
46950
46736
  init_go();
46951
46737
  init_python();
@@ -46957,7 +46743,7 @@ var init_analyzer = __esm(() => {
46957
46743
  GO_EXTENSIONS = new Set([".go"]);
46958
46744
  EXTENSIONS_TO_TRY = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
46959
46745
  goModuleCache = new Map;
46960
- _internals20 = {
46746
+ _internals22 = {
46961
46747
  normalizePath,
46962
46748
  isCacheStale,
46963
46749
  resolveRelativeImport,
@@ -47437,7 +47223,7 @@ function readPackageJsonRaw(dir) {
47437
47223
  }
47438
47224
  }
47439
47225
  function readPackageJson(dir) {
47440
- return _internals21.readPackageJsonRaw(dir);
47226
+ return _internals23.readPackageJsonRaw(dir);
47441
47227
  }
47442
47228
  function readPackageJsonTestScript(dir) {
47443
47229
  return readPackageJson(dir)?.scripts?.test ?? null;
@@ -47607,7 +47393,7 @@ function buildTypescriptBackend() {
47607
47393
  selectEntryPoints: selectEntryPoints3
47608
47394
  };
47609
47395
  }
47610
- var PROFILE_ID3 = "typescript", IMPORT_REGEX_ES2, IMPORT_REGEX_BARE, IMPORT_REGEX_REQUIRE2, IMPORT_REGEX_DYNAMIC, IMPORT_REGEX_REEXPORT2, _internals21;
47396
+ var PROFILE_ID3 = "typescript", IMPORT_REGEX_ES2, IMPORT_REGEX_BARE, IMPORT_REGEX_REQUIRE2, IMPORT_REGEX_DYNAMIC, IMPORT_REGEX_REEXPORT2, _internals23;
47611
47397
  var init_typescript = __esm(() => {
47612
47398
  init_default_backend();
47613
47399
  init_profiles();
@@ -47616,7 +47402,7 @@ var init_typescript = __esm(() => {
47616
47402
  IMPORT_REGEX_REQUIRE2 = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
47617
47403
  IMPORT_REGEX_DYNAMIC = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
47618
47404
  IMPORT_REGEX_REEXPORT2 = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
47619
- _internals21 = {
47405
+ _internals23 = {
47620
47406
  readPackageJsonRaw,
47621
47407
  readPackageJsonTestScript,
47622
47408
  frameworkFromScriptsTest
@@ -47647,7 +47433,7 @@ __export(exports_dispatch, {
47647
47433
  pickedProfiles: () => pickedProfiles,
47648
47434
  pickBackend: () => pickBackend,
47649
47435
  clearDispatchCache: () => clearDispatchCache,
47650
- _internals: () => _internals22
47436
+ _internals: () => _internals24
47651
47437
  });
47652
47438
  import * as fs21 from "fs";
47653
47439
  import * as path38 from "path";
@@ -47702,7 +47488,7 @@ function findManifestRoot(start) {
47702
47488
  return start;
47703
47489
  }
47704
47490
  function evictIfNeeded() {
47705
- if (cache.size <= _internals22.cacheCapacity)
47491
+ if (cache.size <= _internals24.cacheCapacity)
47706
47492
  return;
47707
47493
  let oldestKey;
47708
47494
  let oldestOrder = Infinity;
@@ -47733,7 +47519,7 @@ async function pickBackend(dir) {
47733
47519
  evictIfNeeded();
47734
47520
  return null;
47735
47521
  }
47736
- const profiles = await _internals22.detectProjectLanguages(root);
47522
+ const profiles = await _internals24.detectProjectLanguages(root);
47737
47523
  if (profiles.length === 0) {
47738
47524
  cache.set(cacheKey, {
47739
47525
  hash: hash3,
@@ -47765,12 +47551,12 @@ function clearDispatchCache() {
47765
47551
  manifestRootCache.clear();
47766
47552
  insertCounter = 0;
47767
47553
  }
47768
- var _internals22, cache, insertCounter = 0, MANIFEST_FILES, _MANIFEST_SET, manifestRootCache;
47554
+ var _internals24, cache, insertCounter = 0, MANIFEST_FILES, _MANIFEST_SET, manifestRootCache;
47769
47555
  var init_dispatch = __esm(() => {
47770
47556
  init_backends();
47771
47557
  init_detector();
47772
47558
  init_registry_backend();
47773
- _internals22 = {
47559
+ _internals24 = {
47774
47560
  detectProjectLanguages,
47775
47561
  cacheCapacity: 64
47776
47562
  };
@@ -49307,9 +49093,9 @@ function getVersionFileVersion(dir) {
49307
49093
  async function runVersionCheck(dir, _timeoutMs) {
49308
49094
  const startTime = Date.now();
49309
49095
  try {
49310
- const packageVersion = _internals23.getPackageVersion(dir);
49311
- const changelogVersion = _internals23.getChangelogVersion(dir);
49312
- const versionFileVersion = _internals23.getVersionFileVersion(dir);
49096
+ const packageVersion = _internals25.getPackageVersion(dir);
49097
+ const changelogVersion = _internals25.getChangelogVersion(dir);
49098
+ const versionFileVersion = _internals25.getVersionFileVersion(dir);
49313
49099
  const versions3 = [];
49314
49100
  if (packageVersion)
49315
49101
  versions3.push(`package.json: ${packageVersion}`);
@@ -49659,7 +49445,7 @@ async function runPreflight(dir, phase, config3) {
49659
49445
  const reportId = `preflight-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
49660
49446
  let validatedDir;
49661
49447
  try {
49662
- validatedDir = _internals23.validateDirectoryPath(dir);
49448
+ validatedDir = _internals25.validateDirectoryPath(dir);
49663
49449
  } catch (error93) {
49664
49450
  return {
49665
49451
  id: reportId,
@@ -49679,7 +49465,7 @@ async function runPreflight(dir, phase, config3) {
49679
49465
  }
49680
49466
  let validatedTimeout;
49681
49467
  try {
49682
- validatedTimeout = _internals23.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
49468
+ validatedTimeout = _internals25.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
49683
49469
  } catch (error93) {
49684
49470
  return {
49685
49471
  id: reportId,
@@ -49720,12 +49506,12 @@ async function runPreflight(dir, phase, config3) {
49720
49506
  });
49721
49507
  const checks5 = [];
49722
49508
  log("[Preflight] Running lint check...");
49723
- const lintResult = await _internals23.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
49509
+ const lintResult = await _internals25.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
49724
49510
  checks5.push(lintResult);
49725
49511
  log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`);
49726
49512
  if (!cfg.skipTests) {
49727
49513
  log("[Preflight] Running tests check...");
49728
- const testsResult = await _internals23.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
49514
+ const testsResult = await _internals25.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
49729
49515
  checks5.push(testsResult);
49730
49516
  log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`);
49731
49517
  } else {
@@ -49737,7 +49523,7 @@ async function runPreflight(dir, phase, config3) {
49737
49523
  }
49738
49524
  if (!cfg.skipSecrets) {
49739
49525
  log("[Preflight] Running secrets check...");
49740
- const secretsResult = await _internals23.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
49526
+ const secretsResult = await _internals25.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
49741
49527
  checks5.push(secretsResult);
49742
49528
  log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`);
49743
49529
  } else {
@@ -49749,7 +49535,7 @@ async function runPreflight(dir, phase, config3) {
49749
49535
  }
49750
49536
  if (!cfg.skipEvidence) {
49751
49537
  log("[Preflight] Running evidence check...");
49752
- const evidenceResult = await _internals23.runEvidenceCheck(validatedDir);
49538
+ const evidenceResult = await _internals25.runEvidenceCheck(validatedDir);
49753
49539
  checks5.push(evidenceResult);
49754
49540
  log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`);
49755
49541
  } else {
@@ -49760,12 +49546,12 @@ async function runPreflight(dir, phase, config3) {
49760
49546
  });
49761
49547
  }
49762
49548
  log("[Preflight] Running requirement coverage check...");
49763
- const reqCoverageResult = await _internals23.runRequirementCoverageCheck(validatedDir, phase);
49549
+ const reqCoverageResult = await _internals25.runRequirementCoverageCheck(validatedDir, phase);
49764
49550
  checks5.push(reqCoverageResult);
49765
49551
  log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`);
49766
49552
  if (!cfg.skipVersion) {
49767
49553
  log("[Preflight] Running version check...");
49768
- const versionResult = await _internals23.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
49554
+ const versionResult = await _internals25.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
49769
49555
  checks5.push(versionResult);
49770
49556
  log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`);
49771
49557
  } else {
@@ -49828,10 +49614,10 @@ function formatPreflightMarkdown(report) {
49828
49614
  async function handlePreflightCommand(directory, _args) {
49829
49615
  const plan = await loadPlan(directory);
49830
49616
  const phase = plan?.current_phase ?? 1;
49831
- const report = await _internals23.runPreflight(directory, phase);
49832
- return _internals23.formatPreflightMarkdown(report);
49617
+ const report = await _internals25.runPreflight(directory, phase);
49618
+ return _internals25.formatPreflightMarkdown(report);
49833
49619
  }
49834
- var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals23;
49620
+ var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals25;
49835
49621
  var init_preflight_service = __esm(() => {
49836
49622
  init_manager2();
49837
49623
  init_manager();
@@ -49848,7 +49634,7 @@ var init_preflight_service = __esm(() => {
49848
49634
  testScope: "convention",
49849
49635
  linter: "biome"
49850
49636
  };
49851
- _internals23 = {
49637
+ _internals25 = {
49852
49638
  runPreflight,
49853
49639
  formatPreflightMarkdown,
49854
49640
  handlePreflightCommand,
@@ -51441,7 +51227,7 @@ async function getStatusData(directory, agents) {
51441
51227
  }
51442
51228
  function enrichWithLeanTurbo(status, directory) {
51443
51229
  const turboMode = hasActiveTurboMode();
51444
- const leanActive = _internals24.hasActiveLeanTurbo();
51230
+ const leanActive = _internals26.hasActiveLeanTurbo();
51445
51231
  let turboStrategy = "off";
51446
51232
  if (leanActive) {
51447
51233
  turboStrategy = "lean";
@@ -51460,7 +51246,7 @@ function enrichWithLeanTurbo(status, directory) {
51460
51246
  }
51461
51247
  }
51462
51248
  if (leanSessionID) {
51463
- const runState = _internals24.loadLeanTurboRunState(directory, leanSessionID);
51249
+ const runState = _internals26.loadLeanTurboRunState(directory, leanSessionID);
51464
51250
  if (runState) {
51465
51251
  status.leanTurboPhase = runState.phase;
51466
51252
  status.leanMaxParallelCoders = runState.maxParallelCoders;
@@ -51492,7 +51278,7 @@ function enrichWithLeanTurbo(status, directory) {
51492
51278
  }
51493
51279
  }
51494
51280
  }
51495
- status.fullAutoActive = _internals24.hasActiveFullAuto();
51281
+ status.fullAutoActive = _internals26.hasActiveFullAuto();
51496
51282
  return status;
51497
51283
  }
51498
51284
  function formatStatusMarkdown(status) {
@@ -51556,7 +51342,7 @@ async function handleStatusCommand(directory, agents) {
51556
51342
  }
51557
51343
  return formatStatusMarkdown(statusData);
51558
51344
  }
51559
- var _internals24;
51345
+ var _internals26;
51560
51346
  var init_status_service = __esm(() => {
51561
51347
  init_extractors();
51562
51348
  init_utils2();
@@ -51565,7 +51351,7 @@ var init_status_service = __esm(() => {
51565
51351
  init_state3();
51566
51352
  init_compaction_service();
51567
51353
  init_context_budget_service();
51568
- _internals24 = {
51354
+ _internals26 = {
51569
51355
  loadLeanTurboRunState,
51570
51356
  hasActiveLeanTurbo,
51571
51357
  hasActiveFullAuto
@@ -51656,7 +51442,7 @@ async function handleTurboCommand(directory, args, sessionID) {
51656
51442
  if (arg0 === "on") {
51657
51443
  let strategy = "standard";
51658
51444
  try {
51659
- const { config: config3 } = _internals25.loadPluginConfigWithMeta(directory);
51445
+ const { config: config3 } = _internals27.loadPluginConfigWithMeta(directory);
51660
51446
  if (config3.turbo?.strategy === "lean") {
51661
51447
  strategy = "lean";
51662
51448
  }
@@ -51711,7 +51497,7 @@ function enableLeanTurbo(session, directory, sessionID) {
51711
51497
  let maxParallelCoders = 4;
51712
51498
  let conflictPolicy = "serialize";
51713
51499
  try {
51714
- const { config: config3 } = _internals25.loadPluginConfigWithMeta(directory);
51500
+ const { config: config3 } = _internals27.loadPluginConfigWithMeta(directory);
51715
51501
  const leanConfig = config3.turbo?.lean;
51716
51502
  if (leanConfig) {
51717
51503
  maxParallelCoders = leanConfig.max_parallel_coders ?? 4;
@@ -51781,13 +51567,13 @@ function buildStatusMessage(session, directory, sessionID) {
51781
51567
  ].join(`
51782
51568
  `);
51783
51569
  }
51784
- var _internals25;
51570
+ var _internals27;
51785
51571
  var init_turbo = __esm(() => {
51786
51572
  init_config();
51787
51573
  init_state();
51788
51574
  init_state3();
51789
51575
  init_logger();
51790
- _internals25 = {
51576
+ _internals27 = {
51791
51577
  loadPluginConfigWithMeta
51792
51578
  };
51793
51579
  });
@@ -51853,6 +51639,270 @@ var init_write_retro2 = __esm(() => {
51853
51639
  init_write_retro();
51854
51640
  });
51855
51641
 
51642
+ // src/commands/command-dispatch.ts
51643
+ import fs28 from "fs";
51644
+ import path46 from "path";
51645
+ function normalizeSwarmCommandInput(command, argumentText) {
51646
+ if (command !== "swarm" && !command.startsWith("swarm-")) {
51647
+ return { isSwarmCommand: false, tokens: [] };
51648
+ }
51649
+ if (command === "swarm") {
51650
+ return {
51651
+ isSwarmCommand: true,
51652
+ tokens: argumentText.trim().split(/\s+/).filter(Boolean)
51653
+ };
51654
+ }
51655
+ const subcommand = command.slice("swarm-".length);
51656
+ const extraArgs = argumentText.trim().split(/\s+/).filter(Boolean);
51657
+ return {
51658
+ isSwarmCommand: true,
51659
+ tokens: [subcommand, ...extraArgs].filter(Boolean)
51660
+ };
51661
+ }
51662
+ function canonicalCommandKey(resolved) {
51663
+ return resolved.entry.aliasOf ?? resolved.key;
51664
+ }
51665
+ function formatCommandNotFound(tokens) {
51666
+ const attemptedCommand = tokens[0] || "";
51667
+ const MAX_DISPLAY = 100;
51668
+ const displayCommand = attemptedCommand.length > MAX_DISPLAY ? `${attemptedCommand.slice(0, MAX_DISPLAY)}...` : attemptedCommand;
51669
+ const similar = _internals28.findSimilarCommands(attemptedCommand);
51670
+ const header = `Command \`/swarm ${displayCommand}\` not found.`;
51671
+ const suggestions = similar.length > 0 ? `Did you mean:
51672
+ ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
51673
+ `)}` : "";
51674
+ const footer = "Run `/swarm help` for all commands.";
51675
+ return [header, suggestions, footer].filter(Boolean).join(`
51676
+
51677
+ `);
51678
+ }
51679
+ function maybeMarkFirstRun(directory) {
51680
+ const sentinelPath = path46.join(directory, ".swarm", ".first-run-complete");
51681
+ try {
51682
+ const swarmDir = path46.join(directory, ".swarm");
51683
+ fs28.mkdirSync(swarmDir, { recursive: true });
51684
+ fs28.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
51685
+ `, { flag: "wx" });
51686
+ return true;
51687
+ } catch {
51688
+ return false;
51689
+ }
51690
+ }
51691
+ function prependWelcome(text) {
51692
+ const welcomeMessage = `Welcome to OpenCode Swarm!
51693
+ ` + `
51694
+ ` + `Run \`/swarm help\` to see all available commands, or \`/swarm config\` to review your configuration.
51695
+ `;
51696
+ return welcomeMessage + text;
51697
+ }
51698
+ async function executeSwarmCommand(args) {
51699
+ const {
51700
+ directory,
51701
+ agents,
51702
+ sessionID,
51703
+ tokens,
51704
+ includeWelcome = false,
51705
+ buildHelpText,
51706
+ policy
51707
+ } = args;
51708
+ let text;
51709
+ const resolved = resolveCommand(tokens);
51710
+ if (!resolved) {
51711
+ text = tokens.length === 0 && buildHelpText ? buildHelpText() : formatCommandNotFound(tokens);
51712
+ } else {
51713
+ const policyResult = policy?.(resolved) ?? { allowed: true };
51714
+ if (!policyResult.allowed) {
51715
+ text = policyResult.message;
51716
+ } else {
51717
+ try {
51718
+ text = await resolved.entry.handler({
51719
+ directory,
51720
+ args: resolved.remainingArgs,
51721
+ sessionID,
51722
+ agents
51723
+ });
51724
+ } catch (_err) {
51725
+ const cmdName = tokens[0] || "unknown";
51726
+ const errMsg = _err instanceof Error ? _err.message : String(_err);
51727
+ text = `Error executing /swarm ${cmdName}: ${errMsg}`;
51728
+ }
51729
+ if (resolved.warning) {
51730
+ text = `${resolved.warning}
51731
+
51732
+ ${text}`;
51733
+ }
51734
+ }
51735
+ }
51736
+ if (includeWelcome && maybeMarkFirstRun(directory)) {
51737
+ text = prependWelcome(text);
51738
+ }
51739
+ return {
51740
+ text,
51741
+ resolved: resolved ?? undefined,
51742
+ canonicalKey: resolved ? canonicalCommandKey(resolved) : undefined
51743
+ };
51744
+ }
51745
+ var init_command_dispatch = __esm(() => {
51746
+ init_registry();
51747
+ });
51748
+
51749
+ // src/commands/tool-policy.ts
51750
+ function classifySwarmCommandToolUse(resolved) {
51751
+ const canonicalKey = canonicalCommandKey(resolved);
51752
+ const args = resolved.remainingArgs;
51753
+ if (!SWARM_COMMAND_TOOL_ALLOWLIST.has(canonicalKey)) {
51754
+ return {
51755
+ allowed: false,
51756
+ message: `/swarm ${canonicalKey} is not available through the chat tool yet.
51757
+
51758
+ ` + `Use the canonical CLI path for now: \`bunx opencode-swarm run ${canonicalKey}\`.
51759
+ ` + `Commands with state changes, auto-heal behavior, or subprocesses need confirmation gates before chat-tool support.`
51760
+ };
51761
+ }
51762
+ if (canonicalKey === "config doctor" && args.some((arg) => arg === "--fix" || arg === "-f")) {
51763
+ return {
51764
+ allowed: false,
51765
+ message: "/swarm config doctor --fix is not available through swarm_command. Run the CLI command directly when you intend to modify config files."
51766
+ };
51767
+ }
51768
+ if (NO_ARGS.has(canonicalKey) && args.length > 0) {
51769
+ return {
51770
+ allowed: false,
51771
+ message: `/swarm ${canonicalKey} does not accept arguments through swarm_command.`
51772
+ };
51773
+ }
51774
+ if (canonicalKey === "knowledge") {
51775
+ if (args.length === 0)
51776
+ return { allowed: true };
51777
+ if (args.length === 1 && args[0] === "list")
51778
+ return { allowed: true };
51779
+ return {
51780
+ allowed: false,
51781
+ message: "Only `/swarm knowledge` and `/swarm knowledge list` are available through swarm_command. Knowledge migrate/quarantine/restore are intentionally excluded."
51782
+ };
51783
+ }
51784
+ if (canonicalKey === "retrieve") {
51785
+ if (args.length !== 1 || !SUMMARY_ID_PATTERN.test(args[0])) {
51786
+ return {
51787
+ allowed: false,
51788
+ message: "Usage through swarm_command: `/swarm retrieve <summary-id>` with a single summary ID such as S1."
51789
+ };
51790
+ }
51791
+ }
51792
+ if (canonicalKey === "benchmark") {
51793
+ const allowedFlags = new Set(["--cumulative", "--ci-gate"]);
51794
+ const invalid = args.filter((arg) => !allowedFlags.has(arg));
51795
+ if (invalid.length > 0) {
51796
+ return {
51797
+ allowed: false,
51798
+ message: "Only `--cumulative` and `--ci-gate` are supported for `/swarm benchmark` through swarm_command."
51799
+ };
51800
+ }
51801
+ }
51802
+ if (canonicalKey === "show-plan") {
51803
+ if (args.length > 1 || args[0] && !/^\d+$/.test(args[0])) {
51804
+ return {
51805
+ allowed: false,
51806
+ message: "Usage through swarm_command: `/swarm show-plan` or `/swarm show-plan <phase-number>`."
51807
+ };
51808
+ }
51809
+ }
51810
+ if (canonicalKey === "evidence") {
51811
+ if (args.length > 1 || args[0] && !TASK_ID_PATTERN.test(args[0])) {
51812
+ return {
51813
+ allowed: false,
51814
+ message: "Usage through swarm_command: `/swarm evidence` or `/swarm evidence <task-id>`."
51815
+ };
51816
+ }
51817
+ }
51818
+ if (canonicalKey === "help" && args.length > 2) {
51819
+ return {
51820
+ allowed: false,
51821
+ message: "Usage through swarm_command: `/swarm help` or `/swarm help <command>`."
51822
+ };
51823
+ }
51824
+ return { allowed: true };
51825
+ }
51826
+ function classifySwarmCommandChatFallbackUse(resolved) {
51827
+ const canonicalKey = canonicalCommandKey(resolved);
51828
+ const args = resolved.remainingArgs;
51829
+ if (canonicalKey === "config doctor" && args.some((arg) => arg === "--fix" || arg === "-f")) {
51830
+ return {
51831
+ allowed: false,
51832
+ message: "/swarm config doctor --fix is not available through chat fallback because it can modify configuration files. Run the CLI command directly when you intend to apply fixes."
51833
+ };
51834
+ }
51835
+ if (canonicalKey === "knowledge migrate" || canonicalKey === "knowledge quarantine" || canonicalKey === "knowledge restore") {
51836
+ return {
51837
+ allowed: false,
51838
+ message: `/swarm ${canonicalKey} is not available through chat fallback because it mutates .swarm knowledge state. ` + "Run the CLI command directly after confirming the intended state change."
51839
+ };
51840
+ }
51841
+ return { allowed: true };
51842
+ }
51843
+ var SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, NO_ARGS, SUMMARY_ID_PATTERN, TASK_ID_PATTERN;
51844
+ var init_tool_policy = __esm(() => {
51845
+ init_command_dispatch();
51846
+ SWARM_COMMAND_TOOL_COMMANDS = [
51847
+ "agents",
51848
+ "config",
51849
+ "config doctor",
51850
+ "config-doctor",
51851
+ "doctor",
51852
+ "doctor tools",
51853
+ "status",
51854
+ "show-plan",
51855
+ "plan",
51856
+ "help",
51857
+ "history",
51858
+ "evidence",
51859
+ "evidence summary",
51860
+ "evidence-summary",
51861
+ "retrieve",
51862
+ "diagnose",
51863
+ "preflight",
51864
+ "benchmark",
51865
+ "knowledge",
51866
+ "sync-plan",
51867
+ "export",
51868
+ "list-agents"
51869
+ ];
51870
+ SWARM_COMMAND_TOOL_ALLOWLIST = new Set([
51871
+ "agents",
51872
+ "config",
51873
+ "config doctor",
51874
+ "doctor tools",
51875
+ "status",
51876
+ "show-plan",
51877
+ "help",
51878
+ "history",
51879
+ "evidence",
51880
+ "evidence summary",
51881
+ "retrieve",
51882
+ "diagnose",
51883
+ "preflight",
51884
+ "benchmark",
51885
+ "knowledge",
51886
+ "sync-plan",
51887
+ "export"
51888
+ ]);
51889
+ NO_ARGS = new Set([
51890
+ "agents",
51891
+ "config",
51892
+ "config doctor",
51893
+ "doctor tools",
51894
+ "status",
51895
+ "history",
51896
+ "evidence summary",
51897
+ "diagnose",
51898
+ "preflight",
51899
+ "sync-plan",
51900
+ "export"
51901
+ ]);
51902
+ SUMMARY_ID_PATTERN = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
51903
+ TASK_ID_PATTERN = /^[A-Za-z0-9_.:-]{1,64}$/;
51904
+ });
51905
+
51856
51906
  // src/commands/command-names.ts
51857
51907
  var COMMAND_NAMES, COMMAND_NAME_SET;
51858
51908
  var init_command_names = __esm(() => {
@@ -51865,6 +51915,7 @@ var init_command_names = __esm(() => {
51865
51915
  var exports_commands = {};
51866
51916
  __export(exports_commands, {
51867
51917
  resolveCommand: () => resolveCommand,
51918
+ normalizeSwarmCommandInput: () => normalizeSwarmCommandInput,
51868
51919
  handleWriteRetroCommand: () => handleWriteRetroCommand,
51869
51920
  handleTurboCommand: () => handleTurboCommand,
51870
51921
  handleSyncPlanCommand: () => handleSyncPlanCommand,
@@ -51906,17 +51957,27 @@ __export(exports_commands, {
51906
51957
  handleAnalyzeCommand: () => handleAnalyzeCommand,
51907
51958
  handleAgentsCommand: () => handleAgentsCommand,
51908
51959
  handleAcknowledgeSpecDriftCommand: () => handleAcknowledgeSpecDriftCommand,
51960
+ formatCommandNotFound: () => formatCommandNotFound,
51961
+ executeSwarmCommand: () => executeSwarmCommand,
51909
51962
  createSwarmCommandHandler: () => createSwarmCommandHandler,
51963
+ classifySwarmCommandToolUse: () => classifySwarmCommandToolUse,
51964
+ classifySwarmCommandChatFallbackUse: () => classifySwarmCommandChatFallbackUse,
51910
51965
  buildHelpText: () => buildHelpText,
51966
+ agentHasSwarmCommandTool: () => agentHasSwarmCommandTool,
51911
51967
  VALID_COMMANDS: () => VALID_COMMANDS,
51968
+ SWARM_COMMAND_TOOL_COMMANDS: () => SWARM_COMMAND_TOOL_COMMANDS,
51969
+ SWARM_COMMAND_TOOL_ALLOWLIST: () => SWARM_COMMAND_TOOL_ALLOWLIST,
51912
51970
  COMMAND_REGISTRY: () => COMMAND_REGISTRY,
51913
51971
  COMMAND_NAME_SET: () => COMMAND_NAME_SET,
51914
51972
  COMMAND_NAMES: () => COMMAND_NAMES
51915
51973
  });
51916
- import fs28 from "fs";
51917
- import path46 from "path";
51918
51974
  function buildHelpText() {
51919
- const lines = ["## Swarm Commands", ""];
51975
+ const lines = [
51976
+ "## Swarm Commands",
51977
+ "",
51978
+ "**Chat routing note**: supported read-only `/swarm` commands are routed through the `swarm_command` tool when the active agent has that tool. Unsupported or state-changing commands remain chat-mediated; use `bunx opencode-swarm run <subcommand>` when you need canonical output.",
51979
+ ""
51980
+ ];
51920
51981
  const CATEGORIES = [
51921
51982
  "core",
51922
51983
  "agent",
@@ -52011,90 +52072,127 @@ function buildHelpText() {
52011
52072
  return lines.join(`
52012
52073
  `);
52013
52074
  }
52014
- function createSwarmCommandHandler(directory, agents, client) {
52075
+ function createSwarmCommandHandler(directory, agents, options = {}) {
52015
52076
  return async (input, output) => {
52016
- if (input.command !== "swarm" && !input.command.startsWith("swarm-")) {
52077
+ const normalized = normalizeSwarmCommandInput(input.command, input.arguments);
52078
+ if (!normalized.isSwarmCommand) {
52017
52079
  return;
52018
52080
  }
52019
- let isFirstRun = false;
52020
- const sentinelPath = path46.join(directory, ".swarm", ".first-run-complete");
52021
- try {
52022
- const swarmDir = path46.join(directory, ".swarm");
52023
- fs28.mkdirSync(swarmDir, { recursive: true });
52024
- fs28.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
52025
- `, { flag: "wx" });
52026
- isFirstRun = true;
52027
- } catch (_err) {}
52028
- let tokens;
52029
- if (input.command === "swarm") {
52030
- tokens = input.arguments.trim().split(/\s+/).filter(Boolean);
52031
- } else {
52032
- const subcommand = input.command.slice("swarm-".length);
52033
- const extraArgs = input.arguments.trim().split(/\s+/).filter(Boolean);
52034
- tokens = [subcommand, ...extraArgs];
52035
- }
52036
- let text;
52037
- const resolved = resolveCommand(tokens);
52038
- if (!resolved) {
52039
- if (tokens.length === 0) {
52040
- text = buildHelpText();
52041
- } else {
52042
- const attemptedCommand = tokens[0] || "";
52043
- const MAX_DISPLAY = 100;
52044
- const displayCommand = attemptedCommand.length > MAX_DISPLAY ? `${attemptedCommand.slice(0, MAX_DISPLAY)}...` : attemptedCommand;
52045
- const similar = _internals26.findSimilarCommands(attemptedCommand);
52046
- const header = `Command \`/swarm ${displayCommand}\` not found.`;
52047
- const suggestions = similar.length > 0 ? `Did you mean:
52048
- ${similar.map((cmd) => ` \u2022 /swarm ${cmd}`).join(`
52049
- `)}` : "";
52050
- const footer = "Run `/swarm help` for all commands.";
52051
- text = [header, suggestions, footer].filter(Boolean).join(`
52052
-
52053
- `);
52054
- }
52055
- } else {
52056
- try {
52057
- text = await resolved.entry.handler({
52058
- directory,
52059
- args: resolved.remainingArgs,
52060
- sessionID: input.sessionID,
52061
- agents,
52062
- client
52063
- });
52064
- } catch (_err) {
52065
- const cmdName = tokens[0] || "unknown";
52066
- const errMsg = _err instanceof Error ? _err.message : String(_err);
52067
- text = `Error executing /swarm ${cmdName}: ${errMsg}`;
52068
- }
52069
- if (resolved.warning) {
52070
- text = `${resolved.warning}
52071
-
52072
- ${text}`;
52073
- }
52074
- }
52075
- if (isFirstRun) {
52076
- const welcomeMessage = `Welcome to OpenCode Swarm! \uD83D\uDC1D
52077
- ` + `
52078
- ` + `Start here: run \`/swarm diagnose\`, then \`/swarm agents\` to confirm the plugin loaded and see the exact models in use.
52079
- ` + `If a model is unavailable, edit \`.opencode/opencode-swarm.json\` or \`~/.config/opencode/opencode-swarm.json\` and run \`/swarm config doctor\`.
52080
- ` + `Useful next steps: \`/swarm brainstorm <task>\` for guided planning, \`/swarm full-auto on\` for autonomous runs after enabling it in config, and \`/swarm council <question>\` after enabling council.general.
52081
-
52082
- `;
52083
- text = welcomeMessage + text;
52084
- }
52085
- output.parts = [
52086
- { type: "text", text }
52087
- ];
52081
+ output.parts.splice(0, output.parts.length, {
52082
+ type: "text",
52083
+ text: await buildSwarmCommandPrompt({
52084
+ directory,
52085
+ agents,
52086
+ sessionID: input.sessionID,
52087
+ tokens: normalized.tokens,
52088
+ activeAgentName: options.getActiveAgentName?.(input.sessionID),
52089
+ registeredAgents: options.registeredAgents
52090
+ })
52091
+ });
52092
+ return;
52088
52093
  };
52089
52094
  }
52095
+ async function buildSwarmCommandPrompt(args) {
52096
+ const {
52097
+ directory,
52098
+ agents,
52099
+ sessionID,
52100
+ tokens,
52101
+ activeAgentName,
52102
+ registeredAgents
52103
+ } = args;
52104
+ const resolved = _internals28.resolveCommand(tokens);
52105
+ if (!resolved) {
52106
+ if (tokens.length === 0) {
52107
+ return buildHelpText();
52108
+ }
52109
+ return formatCommandNotFound(tokens);
52110
+ }
52111
+ const typedResolved = resolved;
52112
+ const canonicalKey = canonicalCommandKey(typedResolved);
52113
+ const policy = classifySwarmCommandToolUse(typedResolved);
52114
+ const isV1ToolCommand = SWARM_COMMAND_TOOL_ALLOWLIST.has(canonicalKey);
52115
+ const canUseTool = agentHasSwarmCommandTool(activeAgentName, agents, registeredAgents);
52116
+ if (canUseTool && policy.allowed && isV1ToolCommand) {
52117
+ return routeToSwarmCommandTool({
52118
+ command: canonicalKey,
52119
+ args: resolved.remainingArgs,
52120
+ original: `/swarm ${tokens.join(" ")}`.trim()
52121
+ });
52122
+ }
52123
+ if (canUseTool && isV1ToolCommand && !policy.allowed) {
52124
+ return [
52125
+ `The user typed \`/swarm ${tokens.join(" ")}\`.`,
52126
+ policy.message,
52127
+ "Do not invent command output. Explain the limitation and recommend the canonical CLI path above."
52128
+ ].join(`
52129
+ `);
52130
+ }
52131
+ const chatFallbackPolicy = classifySwarmCommandChatFallbackUse(typedResolved);
52132
+ if (!chatFallbackPolicy.allowed) {
52133
+ return [
52134
+ `The user typed \`/swarm ${tokens.join(" ")}\`.`,
52135
+ chatFallbackPolicy.message,
52136
+ "Do not execute this command through chat and do not invent command output."
52137
+ ].join(`
52138
+ `);
52139
+ }
52140
+ const result = await executeSwarmCommand({
52141
+ directory,
52142
+ agents,
52143
+ sessionID,
52144
+ tokens
52145
+ });
52146
+ return formatCanonicalPromptFallback({
52147
+ original: `/swarm ${tokens.join(" ")}`.trim(),
52148
+ text: result.text
52149
+ });
52150
+ }
52151
+ function agentHasSwarmCommandTool(activeAgentName, agents, registeredAgents) {
52152
+ const name = activeAgentName ?? ORCHESTRATOR_NAME;
52153
+ const registeredTools = registeredAgents?.[name]?.tools;
52154
+ if (registeredTools) {
52155
+ return registeredTools.swarm_command === true;
52156
+ }
52157
+ const explicitTools = agents[name]?.config?.tools;
52158
+ if (explicitTools) {
52159
+ return explicitTools.swarm_command === true;
52160
+ }
52161
+ const baseName = stripKnownSwarmPrefix(name);
52162
+ return AGENT_TOOL_MAP[baseName]?.includes("swarm_command") === true;
52163
+ }
52164
+ function formatCanonicalPromptFallback(args) {
52165
+ return [
52166
+ `The user typed \`${args.original}\`.`,
52167
+ "Canonical opencode-swarm command output follows.",
52168
+ "Show this output verbatim and add no extra swarm state.",
52169
+ "",
52170
+ args.text
52171
+ ].join(`
52172
+ `);
52173
+ }
52174
+ function routeToSwarmCommandTool(args) {
52175
+ return [
52176
+ `The user typed \`${args.original}\`.`,
52177
+ "Call the `swarm_command` tool exactly once with:",
52178
+ JSON.stringify({ command: args.command, args: args.args }, null, 2),
52179
+ "After the tool returns, show the tool output verbatim and add no extra swarm state."
52180
+ ].join(`
52181
+ `);
52182
+ }
52090
52183
  var init_commands = __esm(() => {
52184
+ init_constants();
52185
+ init_schema();
52186
+ init_command_dispatch();
52091
52187
  init_registry();
52188
+ init_tool_policy();
52092
52189
  init_acknowledge_spec_drift();
52093
52190
  init_agents();
52094
52191
  init_archive();
52095
52192
  init_benchmark();
52096
52193
  init_checkpoint2();
52097
52194
  init_close();
52195
+ init_command_dispatch();
52098
52196
  init_command_names();
52099
52197
  init_config2();
52100
52198
  init_council();
@@ -52122,6 +52220,7 @@ var init_commands = __esm(() => {
52122
52220
  init_simulate();
52123
52221
  init_status();
52124
52222
  init_sync_plan();
52223
+ init_tool_policy();
52125
52224
  init_turbo();
52126
52225
  init_write_retro2();
52127
52226
  });
@@ -52153,7 +52252,7 @@ function findSimilarCommands(query) {
52153
52252
  }
52154
52253
  const scored = VALID_COMMANDS.map((cmd) => {
52155
52254
  const cmdLower = cmd.toLowerCase();
52156
- const fullScore = _internals26.levenshteinDistance(q, cmdLower);
52255
+ const fullScore = _internals28.levenshteinDistance(q, cmdLower);
52157
52256
  let tokenScore = Infinity;
52158
52257
  if (cmd.includes(" ") || cmd.includes("-")) {
52159
52258
  const qTokens = q.split(/[\s-]+/);
@@ -52166,7 +52265,7 @@ function findSimilarCommands(query) {
52166
52265
  for (const ct of cmdTokens) {
52167
52266
  if (ct.length === 0)
52168
52267
  continue;
52169
- const dist = _internals26.levenshteinDistance(qt, ct);
52268
+ const dist = _internals28.levenshteinDistance(qt, ct);
52170
52269
  if (dist < minDist)
52171
52270
  minDist = dist;
52172
52271
  }
@@ -52176,7 +52275,7 @@ function findSimilarCommands(query) {
52176
52275
  }
52177
52276
  const dashStrippedQ = q.replace(/-/g, "");
52178
52277
  const dashStrippedCmd = cmdLower.replace(/-/g, "");
52179
- const dashScore = _internals26.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
52278
+ const dashScore = _internals28.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
52180
52279
  const score = Math.min(fullScore, tokenScore, dashScore);
52181
52280
  return { cmd, score };
52182
52281
  });
@@ -52208,11 +52307,11 @@ async function handleHelpCommand(ctx) {
52208
52307
  return buildHelpText2();
52209
52308
  }
52210
52309
  const tokens = targetCommand.split(/\s+/);
52211
- const resolved = _internals26.resolveCommand(tokens);
52310
+ const resolved = _internals28.resolveCommand(tokens);
52212
52311
  if (resolved) {
52213
- return _internals26.buildDetailedHelp(resolved.key, resolved.entry);
52312
+ return _internals28.buildDetailedHelp(resolved.key, resolved.entry);
52214
52313
  }
52215
- const similar = _internals26.findSimilarCommands(targetCommand);
52314
+ const similar = _internals28.findSimilarCommands(targetCommand);
52216
52315
  const { buildHelpText: fullHelp } = await Promise.resolve().then(() => (init_commands(), exports_commands));
52217
52316
  if (similar.length > 0) {
52218
52317
  return `Command '/swarm ${targetCommand}' not found.
@@ -52306,7 +52405,7 @@ function resolveCommand(tokens) {
52306
52405
  }
52307
52406
  return null;
52308
52407
  }
52309
- var COMMAND_REGISTRY, VALID_COMMANDS, _internals26, validation;
52408
+ var COMMAND_REGISTRY, VALID_COMMANDS, _internals28, validation;
52310
52409
  var init_registry = __esm(() => {
52311
52410
  init_acknowledge_spec_drift();
52312
52411
  init_agents();
@@ -52376,7 +52475,7 @@ var init_registry = __esm(() => {
52376
52475
  clashesWithNativeCcCommand: "/agents"
52377
52476
  },
52378
52477
  help: {
52379
- handler: (ctx) => _internals26.handleHelpCommand(ctx),
52478
+ handler: (ctx) => _internals28.handleHelpCommand(ctx),
52380
52479
  description: "Show help for swarm commands",
52381
52480
  category: "core",
52382
52481
  args: "[command]",
@@ -52395,13 +52494,13 @@ var init_registry = __esm(() => {
52395
52494
  clashesWithNativeCcCommand: "/config"
52396
52495
  },
52397
52496
  "config doctor": {
52398
- handler: (ctx) => handleDoctorCommand(ctx.directory, ctx.args, { client: ctx.client }),
52497
+ handler: (ctx) => handleDoctorCommand(ctx.directory, ctx.args),
52399
52498
  description: "Run config doctor checks",
52400
52499
  subcommandOf: "config",
52401
52500
  category: "diagnostics"
52402
52501
  },
52403
52502
  "config-doctor": {
52404
- handler: (ctx) => handleDoctorCommand(ctx.directory, ctx.args, { client: ctx.client }),
52503
+ handler: (ctx) => handleDoctorCommand(ctx.directory, ctx.args),
52405
52504
  description: "Run config doctor checks",
52406
52505
  subcommandOf: "config",
52407
52506
  category: "diagnostics",
@@ -52476,7 +52575,7 @@ var init_registry = __esm(() => {
52476
52575
  deprecated: true
52477
52576
  },
52478
52577
  doctor: {
52479
- handler: (ctx) => handleDoctorCommand(ctx.directory, ctx.args, { client: ctx.client }),
52578
+ handler: (ctx) => handleDoctorCommand(ctx.directory, ctx.args),
52480
52579
  description: "Run config doctor checks",
52481
52580
  category: "diagnostics",
52482
52581
  aliasOf: "config doctor",
@@ -52748,7 +52847,7 @@ Subcommands:
52748
52847
  }
52749
52848
  };
52750
52849
  VALID_COMMANDS = Object.keys(COMMAND_REGISTRY);
52751
- _internals26 = {
52850
+ _internals28 = {
52752
52851
  handleHelpCommand,
52753
52852
  validateAliases,
52754
52853
  resolveCommand,
@@ -52756,7 +52855,7 @@ Subcommands:
52756
52855
  findSimilarCommands,
52757
52856
  buildDetailedHelp
52758
52857
  };
52759
- validation = _internals26.validateAliases();
52858
+ validation = _internals28.validateAliases();
52760
52859
  if (!validation.valid) {
52761
52860
  throw new Error(`COMMAND_REGISTRY alias validation failed:
52762
52861
  ${validation.errors.join(`