opencode-swarm 7.3.4 → 7.3.5
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 +11 -0
- package/dist/agents/index.d.ts +28 -0
- package/dist/cli/index.js +7 -2
- package/dist/config/schema.d.ts +1 -20
- package/dist/index.js +71 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -788,6 +788,17 @@ Prefixed agents (e.g., `paid_coder`, `mega_reviewer`, `local_architect`) inherit
|
|
|
788
788
|
|
|
789
789
|
In this example, `paid_coder` gets its own explicit rule, while other prefixed coders (e.g., `mega_coder`) fall back to `coder`.
|
|
790
790
|
|
|
791
|
+
#### Selecting the primary agent in multi-swarm configs (`default_agent`)
|
|
792
|
+
|
|
793
|
+
The top-level `default_agent` field controls which generated agents OpenCode treats as primary. **It is optional.** Behavior:
|
|
794
|
+
|
|
795
|
+
- **Omitted** — every architect-role agent is primary. In a multi-swarm config that means each swarm exposes its own architect (`local_architect`, `mega_architect`, `paid_architect`, `modelrelay_architect`, …) as a selectable session default. This is the v7.0.0-compatible behavior and the recommended setup.
|
|
796
|
+
- **Base role** (e.g. `"coder"`) — every generated agent whose canonical base role matches becomes primary (`local_coder`, `mega_coder`, …).
|
|
797
|
+
- **Exact generated name** (e.g. `"local_architect"`) — only that agent is primary.
|
|
798
|
+
- **Unknown / invalid value** — a one-time warning is logged and the resolver falls back to architect-role primaries (or the first generated agent if architects are disabled). The plugin never produces zero primaries when at least one agent exists.
|
|
799
|
+
|
|
800
|
+
See [`docs/configuration.md`](docs/configuration.md) for the full table.
|
|
801
|
+
|
|
791
802
|
### Runtime Enforcement
|
|
792
803
|
|
|
793
804
|
Architect direct writes are enforced at runtime via `toolBefore` hook. This tracks writes to source code paths outside `.swarm/` and protects `.swarm/plan.md` and `.swarm/plan.json` from direct modification.
|
package/dist/agents/index.d.ts
CHANGED
|
@@ -34,6 +34,34 @@ export declare function getSwarmAgents(): Record<string, {
|
|
|
34
34
|
* Create all agent definitions with configuration applied
|
|
35
35
|
*/
|
|
36
36
|
export declare function createAgents(config?: PluginConfig): AgentDefinition[];
|
|
37
|
+
/**
|
|
38
|
+
* Resolve the set of generated agent names that should be marked as primary
|
|
39
|
+
* for OpenCode's session-default-agent resolution.
|
|
40
|
+
*
|
|
41
|
+
* Resolution rules (see schema.ts default_agent comment for full semantics):
|
|
42
|
+
* - default_agent omitted ⇒ every architect-role agent is primary
|
|
43
|
+
* (canonical base role === "architect"). This restores v7.0.0 behavior in
|
|
44
|
+
* multi-swarm configs where there is no unprefixed `architect` agent.
|
|
45
|
+
* - default_agent exactly matches a generated agent name ⇒ only that agent.
|
|
46
|
+
* Exact match wins over base-role match — `local_architect` resolves to
|
|
47
|
+
* just `local_architect`, never the entire architect role.
|
|
48
|
+
* - default_agent is a base role in ALL_AGENT_NAMES ⇒ every generated agent
|
|
49
|
+
* whose canonical base role matches that role.
|
|
50
|
+
* - default_agent is invalid (matches nothing) ⇒ fall back to architect-role
|
|
51
|
+
* primaries; if no architect roles exist (architects disabled), fall back
|
|
52
|
+
* to the first generated agent. Always warns. Never returns empty when
|
|
53
|
+
* `agentNames` is non-empty.
|
|
54
|
+
*
|
|
55
|
+
* Important matching detail: a value like "not_an_architect" is NOT treated
|
|
56
|
+
* as a base-role request even though stripKnownSwarmPrefix() returns
|
|
57
|
+
* "architect" for it. Base-role matching only fires when the user-supplied
|
|
58
|
+
* value is itself one of ALL_AGENT_NAMES.
|
|
59
|
+
*/
|
|
60
|
+
export declare function resolvePrimaryAgentNames(agentNames: string[], defaultAgent?: string): {
|
|
61
|
+
primaryNames: Set<string>;
|
|
62
|
+
reason: 'implicit-architects' | 'exact' | 'base-role' | 'fallback-architects' | 'fallback-first';
|
|
63
|
+
warning?: string;
|
|
64
|
+
};
|
|
37
65
|
/**
|
|
38
66
|
* Get agent configurations formatted for the OpenCode SDK.
|
|
39
67
|
*/
|
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.3.
|
|
37
|
+
version: "7.3.5",
|
|
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",
|
|
@@ -16915,7 +16915,12 @@ var init_schema = __esm(() => {
|
|
|
16915
16915
|
});
|
|
16916
16916
|
PluginConfigSchema = exports_external.object({
|
|
16917
16917
|
agents: exports_external.record(exports_external.string(), AgentOverrideConfigSchema).optional(),
|
|
16918
|
-
default_agent: exports_external.
|
|
16918
|
+
default_agent: exports_external.string().optional().transform((v) => {
|
|
16919
|
+
if (v === undefined)
|
|
16920
|
+
return;
|
|
16921
|
+
const trimmed = v.trim();
|
|
16922
|
+
return trimmed === "" ? undefined : trimmed;
|
|
16923
|
+
}),
|
|
16919
16924
|
swarms: exports_external.record(exports_external.string(), SwarmConfigSchema).optional(),
|
|
16920
16925
|
max_iterations: exports_external.number().min(1).max(10).default(5),
|
|
16921
16926
|
pipeline: PipelineConfigSchema.optional(),
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -643,26 +643,7 @@ export declare const PluginConfigSchema: z.ZodObject<{
|
|
|
643
643
|
disabled: z.ZodOptional<z.ZodBoolean>;
|
|
644
644
|
fallback_models: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
645
645
|
}, z.core.$strip>>>;
|
|
646
|
-
default_agent: z.
|
|
647
|
-
architect: "architect";
|
|
648
|
-
sme: "sme";
|
|
649
|
-
docs: "docs";
|
|
650
|
-
designer: "designer";
|
|
651
|
-
critic_sounding_board: "critic_sounding_board";
|
|
652
|
-
critic_drift_verifier: "critic_drift_verifier";
|
|
653
|
-
critic_hallucination_verifier: "critic_hallucination_verifier";
|
|
654
|
-
curator_init: "curator_init";
|
|
655
|
-
curator_phase: "curator_phase";
|
|
656
|
-
council_generalist: "council_generalist";
|
|
657
|
-
council_skeptic: "council_skeptic";
|
|
658
|
-
council_domain_expert: "council_domain_expert";
|
|
659
|
-
reviewer: "reviewer";
|
|
660
|
-
critic: "critic";
|
|
661
|
-
critic_oversight: "critic_oversight";
|
|
662
|
-
explorer: "explorer";
|
|
663
|
-
coder: "coder";
|
|
664
|
-
test_engineer: "test_engineer";
|
|
665
|
-
}>>>;
|
|
646
|
+
default_agent: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string | undefined, string | undefined>>;
|
|
666
647
|
swarms: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
667
648
|
name: z.ZodOptional<z.ZodString>;
|
|
668
649
|
agents: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
package/dist/index.js
CHANGED
|
@@ -33,7 +33,7 @@ var package_default;
|
|
|
33
33
|
var init_package = __esm(() => {
|
|
34
34
|
package_default = {
|
|
35
35
|
name: "opencode-swarm",
|
|
36
|
-
version: "7.3.
|
|
36
|
+
version: "7.3.5",
|
|
37
37
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
38
38
|
main: "dist/index.js",
|
|
39
39
|
types: "dist/index.d.ts",
|
|
@@ -15352,7 +15352,12 @@ var init_schema = __esm(() => {
|
|
|
15352
15352
|
});
|
|
15353
15353
|
PluginConfigSchema = exports_external.object({
|
|
15354
15354
|
agents: exports_external.record(exports_external.string(), AgentOverrideConfigSchema).optional(),
|
|
15355
|
-
default_agent: exports_external.
|
|
15355
|
+
default_agent: exports_external.string().optional().transform((v) => {
|
|
15356
|
+
if (v === undefined)
|
|
15357
|
+
return;
|
|
15358
|
+
const trimmed = v.trim();
|
|
15359
|
+
return trimmed === "" ? undefined : trimmed;
|
|
15360
|
+
}),
|
|
15356
15361
|
swarms: exports_external.record(exports_external.string(), SwarmConfigSchema).optional(),
|
|
15357
15362
|
max_iterations: exports_external.number().min(1).max(10).default(5),
|
|
15358
15363
|
pipeline: PipelineConfigSchema.optional(),
|
|
@@ -59986,6 +59991,52 @@ function createAgents(config3) {
|
|
|
59986
59991
|
}
|
|
59987
59992
|
return allAgents;
|
|
59988
59993
|
}
|
|
59994
|
+
function resolvePrimaryAgentNames(agentNames, defaultAgent) {
|
|
59995
|
+
const collectArchitectRole = () => agentNames.filter((n) => stripKnownSwarmPrefix(n) === "architect");
|
|
59996
|
+
const trimmed = typeof defaultAgent === "string" ? defaultAgent.trim() : undefined;
|
|
59997
|
+
const value = trimmed === "" ? undefined : trimmed;
|
|
59998
|
+
if (agentNames.length === 0) {
|
|
59999
|
+
return { primaryNames: new Set, reason: "implicit-architects" };
|
|
60000
|
+
}
|
|
60001
|
+
if (value === undefined) {
|
|
60002
|
+
const architects2 = collectArchitectRole();
|
|
60003
|
+
if (architects2.length > 0) {
|
|
60004
|
+
return {
|
|
60005
|
+
primaryNames: new Set(architects2),
|
|
60006
|
+
reason: "implicit-architects"
|
|
60007
|
+
};
|
|
60008
|
+
}
|
|
60009
|
+
const first2 = agentNames[0];
|
|
60010
|
+
return {
|
|
60011
|
+
primaryNames: new Set([first2]),
|
|
60012
|
+
reason: "fallback-first",
|
|
60013
|
+
warning: `[swarm] No architect-role agents are registered and default_agent is unset; falling back to '${first2}' as primary. Re-enable an architect agent or set default_agent to silence this warning.`
|
|
60014
|
+
};
|
|
60015
|
+
}
|
|
60016
|
+
if (ALL_AGENT_NAMES.includes(value)) {
|
|
60017
|
+
const matching = agentNames.filter((n) => stripKnownSwarmPrefix(n) === value);
|
|
60018
|
+
if (matching.length > 0) {
|
|
60019
|
+
return { primaryNames: new Set(matching), reason: "base-role" };
|
|
60020
|
+
}
|
|
60021
|
+
}
|
|
60022
|
+
if (agentNames.includes(value)) {
|
|
60023
|
+
return { primaryNames: new Set([value]), reason: "exact" };
|
|
60024
|
+
}
|
|
60025
|
+
const architects = collectArchitectRole();
|
|
60026
|
+
if (architects.length > 0) {
|
|
60027
|
+
return {
|
|
60028
|
+
primaryNames: new Set(architects),
|
|
60029
|
+
reason: "fallback-architects",
|
|
60030
|
+
warning: `[swarm] default_agent '${value}' did not match any registered agent; falling back to architect-role primaries: ${architects.join(", ")}.`
|
|
60031
|
+
};
|
|
60032
|
+
}
|
|
60033
|
+
const first = agentNames[0];
|
|
60034
|
+
return {
|
|
60035
|
+
primaryNames: new Set([first]),
|
|
60036
|
+
reason: "fallback-first",
|
|
60037
|
+
warning: `[swarm] default_agent '${value}' did not match any registered agent and no architect-role agents are registered; falling back to '${first}' as primary.`
|
|
60038
|
+
};
|
|
60039
|
+
}
|
|
59989
60040
|
function getAgentConfigs(config3, directory, sessionId) {
|
|
59990
60041
|
const agents = createAgents(config3);
|
|
59991
60042
|
const toolFilterEnabled = config3?.tool_filter?.enabled ?? true;
|
|
@@ -59993,21 +60044,29 @@ function getAgentConfigs(config3, directory, sessionId) {
|
|
|
59993
60044
|
const quiet = config3?.quiet ?? true;
|
|
59994
60045
|
const warnedMissingWhitelist = new Set;
|
|
59995
60046
|
const agentToolSnapshot = {};
|
|
60047
|
+
const resolution = resolvePrimaryAgentNames(agents.map((a) => a.name), config3?.default_agent);
|
|
60048
|
+
if (resolution.warning) {
|
|
60049
|
+
if (!quiet) {
|
|
60050
|
+
console.warn(resolution.warning);
|
|
60051
|
+
} else {
|
|
60052
|
+
addDeferredWarning(resolution.warning);
|
|
60053
|
+
}
|
|
60054
|
+
}
|
|
60055
|
+
if (agents.length > 0 && resolution.primaryNames.size === 0) {
|
|
60056
|
+
const generated = agents.map((a) => a.name).join(", ");
|
|
60057
|
+
const diagnostic = `[swarm] DIAGNOSTIC: ${agents.length} generated agents but zero primaries. Likely cause: a regression in resolvePrimaryAgentNames. Generated: ${generated}.`;
|
|
60058
|
+
if (!quiet) {
|
|
60059
|
+
console.warn(diagnostic);
|
|
60060
|
+
} else {
|
|
60061
|
+
addDeferredWarning(diagnostic);
|
|
60062
|
+
}
|
|
60063
|
+
}
|
|
59996
60064
|
const result = Object.fromEntries(agents.map((agent) => {
|
|
59997
60065
|
const sdkConfig = {
|
|
59998
60066
|
...agent.config,
|
|
59999
60067
|
description: agent.description
|
|
60000
60068
|
};
|
|
60001
|
-
|
|
60002
|
-
if (defaultAgent !== "architect" && !ALL_AGENT_NAMES.includes(defaultAgent)) {
|
|
60003
|
-
if (!quiet) {
|
|
60004
|
-
console.warn(`[swarm] Invalid default_agent '${defaultAgent}' — falling back to 'architect'. Valid values: ${ALL_AGENT_NAMES.join(", ")}`);
|
|
60005
|
-
} else {
|
|
60006
|
-
addDeferredWarning(`[swarm] Invalid default_agent '${defaultAgent}' — falling back to 'architect'. Valid values: ${ALL_AGENT_NAMES.join(", ")}`);
|
|
60007
|
-
}
|
|
60008
|
-
defaultAgent = "architect";
|
|
60009
|
-
}
|
|
60010
|
-
const isPrimaryAgent = agent.name === defaultAgent;
|
|
60069
|
+
const isPrimaryAgent = resolution.primaryNames.has(agent.name);
|
|
60011
60070
|
if (isPrimaryAgent) {
|
|
60012
60071
|
sdkConfig.mode = "primary";
|
|
60013
60072
|
sdkConfig.permission = { task: "allow" };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.3.
|
|
3
|
+
"version": "7.3.5",
|
|
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",
|