opencode-swarm 6.84.4 → 6.84.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -173,7 +173,7 @@ No API key required. Excellent starting point:
173
173
  "agents": {
174
174
  "coder": { "model": "opencode/minimax-m2.5-free" },
175
175
  "reviewer": { "model": "opencode/big-pickle" },
176
- "explorer": { "model": "opencode/trinity-large-preview-free" }
176
+ "explorer": { "model": "opencode/big-pickle" }
177
177
  }
178
178
  }
179
179
  ```
@@ -195,7 +195,7 @@ For production, mix providers by role:
195
195
 
196
196
  | Provider | Format | Example |
197
197
  |---|---|---|
198
- | OpenCode Zen | `opencode/<model>` | `opencode/trinity-large-preview-free` |
198
+ | OpenCode Zen | `opencode/<model>` | `opencode/big-pickle` |
199
199
  | Anthropic | `anthropic/<model>` | `anthropic/claude-sonnet-4-20250514` |
200
200
  | Google | `google/<model>` | `google/gemini-2.5-flash` |
201
201
  | Z.ai | `zai-coding-plan/<model>` | `zai-coding-plan/glm-5` |
@@ -11,6 +11,10 @@ export declare function stripSwarmPrefix(agentName: string, swarmPrefix?: string
11
11
  /**
12
12
  * Resolve the fallback model for an agent based on its config and fallback index.
13
13
  * Called by guardrails at runtime when a transient model error is detected.
14
+ *
15
+ * Fallback inheritance:
16
+ * - curator_init/curator_phase inherit fallback_models from explorer if not explicitly configured
17
+ * - This matches the model inheritance: curator agents default to explorer's model
14
18
  */
15
19
  export declare function resolveFallbackModel(agentBaseName: string, fallbackIndex: number, swarmAgents?: Record<string, {
16
20
  model?: string;
package/dist/cli/index.js CHANGED
@@ -18976,6 +18976,13 @@ var AgentOverrideConfigSchema = exports_external.object({
18976
18976
  temperature: exports_external.number().min(0).max(2).optional(),
18977
18977
  disabled: exports_external.boolean().optional(),
18978
18978
  fallback_models: exports_external.array(exports_external.string()).max(3).optional()
18979
+ }).refine((data) => {
18980
+ if (data.model && !data.fallback_models) {
18981
+ console.warn(`[opencode-swarm] WARNING: Agent configured with custom model "${data.model}" but no fallback_models. This means if the custom model fails, there is no fallback protection. Consider adding fallback_models for reliability.`);
18982
+ }
18983
+ return true;
18984
+ }, {
18985
+ message: "Agent configuration warning: Custom model without fallback protection"
18979
18986
  });
18980
18987
  var SwarmConfigSchema = exports_external.object({
18981
18988
  name: exports_external.string().optional(),
@@ -45139,14 +45146,70 @@ async function install() {
45139
45146
  if (!fs23.existsSync(PLUGIN_CONFIG_PATH)) {
45140
45147
  const defaultConfig = {
45141
45148
  agents: {
45142
- coder: { model: "opencode/minimax-m2.5-free" },
45143
- reviewer: { model: "opencode/big-pickle" },
45144
- test_engineer: { model: "opencode/gpt-5-nano" },
45145
- explorer: { model: "opencode/trinity-large-preview-free" },
45146
- sme: { model: "opencode/trinity-large-preview-free" },
45147
- critic: { model: "opencode/trinity-large-preview-free" },
45148
- docs: { model: "opencode/trinity-large-preview-free" },
45149
- designer: { model: "opencode/trinity-large-preview-free" }
45149
+ coder: {
45150
+ model: "opencode/minimax-m2.5-free",
45151
+ fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
45152
+ },
45153
+ reviewer: {
45154
+ model: "opencode/big-pickle",
45155
+ fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
45156
+ },
45157
+ test_engineer: {
45158
+ model: "opencode/gpt-5-nano",
45159
+ fallback_models: ["opencode/big-pickle"]
45160
+ },
45161
+ explorer: {
45162
+ model: "opencode/big-pickle",
45163
+ fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
45164
+ },
45165
+ sme: {
45166
+ model: "opencode/big-pickle",
45167
+ fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
45168
+ },
45169
+ critic: {
45170
+ model: "opencode/big-pickle",
45171
+ fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
45172
+ },
45173
+ docs: {
45174
+ model: "opencode/big-pickle",
45175
+ fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
45176
+ },
45177
+ designer: {
45178
+ model: "opencode/big-pickle",
45179
+ fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
45180
+ },
45181
+ critic_sounding_board: {
45182
+ model: "opencode/gpt-5-nano",
45183
+ fallback_models: ["opencode/big-pickle"]
45184
+ },
45185
+ critic_drift_verifier: {
45186
+ model: "opencode/gpt-5-nano",
45187
+ fallback_models: ["opencode/big-pickle"]
45188
+ },
45189
+ critic_hallucination_verifier: {
45190
+ model: "opencode/gpt-5-nano",
45191
+ fallback_models: ["opencode/big-pickle"]
45192
+ },
45193
+ critic_oversight: {
45194
+ model: "opencode/gpt-5-nano",
45195
+ fallback_models: ["opencode/big-pickle"]
45196
+ },
45197
+ curator_init: {
45198
+ model: "opencode/gpt-5-nano",
45199
+ fallback_models: ["opencode/big-pickle"]
45200
+ },
45201
+ curator_phase: {
45202
+ model: "opencode/gpt-5-nano",
45203
+ fallback_models: ["opencode/big-pickle"]
45204
+ },
45205
+ council_member: {
45206
+ model: "opencode/gpt-5-nano",
45207
+ fallback_models: ["opencode/big-pickle"]
45208
+ },
45209
+ council_moderator: {
45210
+ model: "opencode/gpt-5-nano",
45211
+ fallback_models: ["opencode/big-pickle"]
45212
+ }
45150
45213
  },
45151
45214
  max_iterations: 5
45152
45215
  };
package/dist/index.js CHANGED
@@ -478,23 +478,23 @@ var init_constants = __esm(() => {
478
478
  }
479
479
  }
480
480
  DEFAULT_MODELS = {
481
- explorer: "opencode/trinity-large-preview-free",
481
+ explorer: "opencode/big-pickle",
482
482
  coder: "opencode/minimax-m2.5-free",
483
483
  reviewer: "opencode/big-pickle",
484
484
  test_engineer: "opencode/gpt-5-nano",
485
- sme: "opencode/trinity-large-preview-free",
486
- critic: "opencode/trinity-large-preview-free",
487
- critic_sounding_board: "opencode/trinity-large-preview-free",
488
- critic_drift_verifier: "opencode/trinity-large-preview-free",
489
- critic_hallucination_verifier: "opencode/trinity-large-preview-free",
490
- critic_oversight: "opencode/trinity-large-preview-free",
491
- docs: "opencode/trinity-large-preview-free",
492
- designer: "opencode/trinity-large-preview-free",
493
- curator_init: "opencode/trinity-large-preview-free",
494
- curator_phase: "opencode/trinity-large-preview-free",
495
- council_member: "opencode/trinity-large-preview-free",
496
- council_moderator: "opencode/trinity-large-preview-free",
497
- default: "opencode/trinity-large-preview-free"
485
+ sme: "opencode/big-pickle",
486
+ critic: "opencode/big-pickle",
487
+ critic_sounding_board: "opencode/big-pickle",
488
+ critic_drift_verifier: "opencode/big-pickle",
489
+ critic_hallucination_verifier: "opencode/big-pickle",
490
+ critic_oversight: "opencode/big-pickle",
491
+ docs: "opencode/big-pickle",
492
+ designer: "opencode/big-pickle",
493
+ curator_init: "opencode/big-pickle",
494
+ curator_phase: "opencode/big-pickle",
495
+ council_member: "opencode/big-pickle",
496
+ council_moderator: "opencode/big-pickle",
497
+ default: "opencode/big-pickle"
498
498
  };
499
499
  DEFAULT_SCORING_CONFIG = {
500
500
  enabled: false,
@@ -14724,6 +14724,13 @@ var init_schema = __esm(() => {
14724
14724
  temperature: exports_external.number().min(0).max(2).optional(),
14725
14725
  disabled: exports_external.boolean().optional(),
14726
14726
  fallback_models: exports_external.array(exports_external.string()).max(3).optional()
14727
+ }).refine((data) => {
14728
+ if (data.model && !data.fallback_models) {
14729
+ console.warn(`[opencode-swarm] WARNING: Agent configured with custom model "${data.model}" but no fallback_models. This means if the custom model fails, there is no fallback protection. Consider adding fallback_models for reliability.`);
14730
+ }
14731
+ return true;
14732
+ }, {
14733
+ message: "Agent configuration warning: Custom model without fallback protection"
14727
14734
  });
14728
14735
  SwarmConfigSchema = exports_external.object({
14729
14736
  name: exports_external.string().optional(),
@@ -57662,7 +57669,11 @@ function getModelForAgent(agentName, swarmAgents, swarmPrefix) {
57662
57669
  return resolvedModel;
57663
57670
  }
57664
57671
  function resolveFallbackModel(agentBaseName, fallbackIndex, swarmAgents) {
57665
- const fallbackModels = swarmAgents?.[agentBaseName]?.fallback_models;
57672
+ const agentConfig = swarmAgents?.[agentBaseName];
57673
+ let fallbackModels = agentConfig?.fallback_models;
57674
+ if (fallbackModels === undefined && (agentBaseName === "curator_init" || agentBaseName === "curator_phase")) {
57675
+ fallbackModels = swarmAgents?.explorer?.fallback_models;
57676
+ }
57666
57677
  if (!fallbackModels || fallbackModels.length === 0)
57667
57678
  return null;
57668
57679
  if (fallbackIndex < 1 || fallbackIndex > fallbackModels.length)
@@ -62132,7 +62143,7 @@ __export(exports_doc_scan, {
62132
62143
  });
62133
62144
  import * as crypto7 from "crypto";
62134
62145
  import * as fs45 from "fs";
62135
- import { mkdir as mkdir8, readFile as readFile8, writeFile as writeFile8 } from "fs/promises";
62146
+ import { mkdir as mkdir9, readFile as readFile8, writeFile as writeFile8 } from "fs/promises";
62136
62147
  import * as path59 from "path";
62137
62148
  function normalizeSeparators(filePath) {
62138
62149
  return filePath.replace(/\\/g, "/");
@@ -62304,7 +62315,7 @@ async function scanDocIndex(directory) {
62304
62315
  files: discoveredFiles
62305
62316
  };
62306
62317
  try {
62307
- await mkdir8(path59.dirname(manifestPath), { recursive: true });
62318
+ await mkdir9(path59.dirname(manifestPath), { recursive: true });
62308
62319
  await writeFile8(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
62309
62320
  } catch {}
62310
62321
  return { manifest, cached: false };
@@ -65507,6 +65518,7 @@ async function saveGraph(workspace, graph, options) {
65507
65518
  const graphPath = getGraphPath(workspace);
65508
65519
  updateGraphMetadata(graph);
65509
65520
  const tempPath = `${graphPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
65521
+ await fsPromises3.mkdir(path49.dirname(tempPath), { recursive: true });
65510
65522
  let lastError = null;
65511
65523
  try {
65512
65524
  if (options?.createAtomic) {
@@ -65717,16 +65729,21 @@ function buildWorkspaceGraph(workspaceRoot, options) {
65717
65729
  stats.filesScanned++;
65718
65730
  const ext = path49.extname(filePath).toLowerCase();
65719
65731
  let exports = [];
65720
- if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
65721
- const relativePath = path49.relative(absoluteRoot, filePath);
65722
- const symbols2 = extractTSSymbols(relativePath, absoluteRoot);
65723
- exports = symbols2.filter((s) => s.exported).map((s) => s.name);
65724
- } else if (ext === ".py") {
65725
- const relativePath = path49.relative(absoluteRoot, filePath);
65726
- const symbols2 = extractPythonSymbols(relativePath, absoluteRoot);
65727
- exports = symbols2.filter((s) => s.exported).map((s) => s.name);
65732
+ let parsedImports = [];
65733
+ try {
65734
+ if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
65735
+ const relativePath = path49.relative(absoluteRoot, filePath);
65736
+ const symbols2 = extractTSSymbols(relativePath, absoluteRoot);
65737
+ exports = symbols2.filter((s) => s.exported).map((s) => s.name);
65738
+ } else if (ext === ".py") {
65739
+ const relativePath = path49.relative(absoluteRoot, filePath);
65740
+ const symbols2 = extractPythonSymbols(relativePath, absoluteRoot);
65741
+ exports = symbols2.filter((s) => s.exported).map((s) => s.name);
65742
+ }
65743
+ parsedImports = parseFileImports(content);
65744
+ } catch {
65745
+ continue;
65728
65746
  }
65729
- const parsedImports = parseFileImports(content);
65730
65747
  const node = {
65731
65748
  filePath,
65732
65749
  moduleName: toModuleName(filePath, absoluteRoot),
@@ -65778,38 +65795,42 @@ function scanFile(filePath, absoluteRoot, maxFileSize) {
65778
65795
  }
65779
65796
  const ext = path49.extname(filePath).toLowerCase();
65780
65797
  let exports = [];
65781
- if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
65782
- const relativePath = path49.relative(absoluteRoot, filePath);
65783
- const symbols2 = extractTSSymbols(relativePath, absoluteRoot);
65784
- exports = symbols2.filter((s) => s.exported).map((s) => s.name);
65785
- } else if (ext === ".py") {
65786
- const relativePath = path49.relative(absoluteRoot, filePath);
65787
- const symbols2 = extractPythonSymbols(relativePath, absoluteRoot);
65788
- exports = symbols2.filter((s) => s.exported).map((s) => s.name);
65789
- }
65790
- const parsedImports = parseFileImports(content);
65791
- const node = {
65792
- filePath,
65793
- moduleName: toModuleName(filePath, absoluteRoot),
65794
- exports,
65795
- imports: parsedImports.map((p) => p.specifier),
65796
- language: getLanguage(filePath),
65797
- mtime: fileStats.mtime.toISOString()
65798
- };
65799
- const edges = [];
65800
- const sortedImports = [...parsedImports].sort((a, b) => a.specifier.localeCompare(b.specifier));
65801
- for (const parsed of sortedImports) {
65802
- const resolvedTarget = resolveModuleSpecifier(absoluteRoot, filePath, parsed.specifier);
65803
- if (resolvedTarget !== null) {
65804
- edges.push({
65805
- source: filePath,
65806
- target: resolvedTarget,
65807
- importSpecifier: parsed.specifier,
65808
- importType: parsed.importType
65809
- });
65798
+ try {
65799
+ if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
65800
+ const relativePath = path49.relative(absoluteRoot, filePath);
65801
+ const symbols2 = extractTSSymbols(relativePath, absoluteRoot);
65802
+ exports = symbols2.filter((s) => s.exported).map((s) => s.name);
65803
+ } else if (ext === ".py") {
65804
+ const relativePath = path49.relative(absoluteRoot, filePath);
65805
+ const symbols2 = extractPythonSymbols(relativePath, absoluteRoot);
65806
+ exports = symbols2.filter((s) => s.exported).map((s) => s.name);
65807
+ }
65808
+ const parsedImports = parseFileImports(content);
65809
+ const node = {
65810
+ filePath,
65811
+ moduleName: toModuleName(filePath, absoluteRoot),
65812
+ exports,
65813
+ imports: parsedImports.map((p) => p.specifier),
65814
+ language: getLanguage(filePath),
65815
+ mtime: fileStats.mtime.toISOString()
65816
+ };
65817
+ const edges = [];
65818
+ const sortedImports = [...parsedImports].sort((a, b) => a.specifier.localeCompare(b.specifier));
65819
+ for (const parsed of sortedImports) {
65820
+ const resolvedTarget = resolveModuleSpecifier(absoluteRoot, filePath, parsed.specifier);
65821
+ if (resolvedTarget !== null) {
65822
+ edges.push({
65823
+ source: filePath,
65824
+ target: resolvedTarget,
65825
+ importSpecifier: parsed.specifier,
65826
+ importType: parsed.importType
65827
+ });
65828
+ }
65810
65829
  }
65830
+ return { node, edges };
65831
+ } catch {
65832
+ return { node: null, edges: [] };
65811
65833
  }
65812
- return { node, edges };
65813
65834
  }
65814
65835
  async function updateGraphForFiles(workspaceRoot, filePaths, options) {
65815
65836
  if (options?.forceRebuild) {
@@ -65907,7 +65928,7 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
65907
65928
  if (message.includes("does not exist")) {
65908
65929
  return;
65909
65930
  }
65910
- console.error(`[repo-graph] Failed to build graph: ${message}`);
65931
+ console.warn(`[repo-graph] Failed to build graph: ${message}`);
65911
65932
  }
65912
65933
  },
65913
65934
  async toolAfter(input, _output) {
@@ -65947,7 +65968,7 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
65947
65968
  console.log(`[repo-graph] Incremental update for ${path50.basename(filePath)}`);
65948
65969
  } catch (error93) {
65949
65970
  const message = error93 instanceof Error ? error93.message : String(error93);
65950
- console.error(`[repo-graph] Incremental update failed: ${message}`);
65971
+ console.warn(`[repo-graph] Incremental update failed: ${message}`);
65951
65972
  }
65952
65973
  }
65953
65974
  };
@@ -81006,6 +81027,7 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
81006
81027
  };
81007
81028
  }
81008
81029
  fs69.mkdirSync(path83.dirname(baselinePath), { recursive: true });
81030
+ fs69.mkdirSync(path83.dirname(tempPath), { recursive: true });
81009
81031
  const releaseLock = await acquireLock(lockPath);
81010
81032
  try {
81011
81033
  let existing = null;
@@ -88107,9 +88129,9 @@ var OpenCodeSwarm = async (ctx) => {
88107
88129
  swarmState.fullAutoEnabledInConfig = config3.full_auto?.enabled === true;
88108
88130
  swarmState.opencodeClient = ctx.client;
88109
88131
  await loadSnapshot(ctx.directory);
88132
+ initTelemetry(ctx.directory);
88110
88133
  const repoGraphHook = createRepoGraphBuilderHook(ctx.directory);
88111
88134
  repoGraphHook.init().catch(() => {});
88112
- initTelemetry(ctx.directory);
88113
88135
  const agents = getAgentConfigs(config3, ctx.directory);
88114
88136
  const agentDefinitions = createAgents(config3);
88115
88137
  swarmState.curatorInitAgentNames = Object.keys(agents).filter((k) => k === "curator_init" || k.endsWith("_curator_init"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "6.84.4",
3
+ "version": "6.84.6",
4
4
  "description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",