opencode-swarm 7.21.4 → 7.22.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 +11 -2
- package/dist/config/schema.d.ts +3 -0
- package/dist/index.js +187 -8
- package/package.json +1 -1
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.
|
|
37
|
+
version: "7.22.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",
|
|
@@ -17378,7 +17378,8 @@ var init_schema = __esm(() => {
|
|
|
17378
17378
|
AuthorityConfigSchema = exports_external.object({
|
|
17379
17379
|
enabled: exports_external.boolean().default(true),
|
|
17380
17380
|
rules: exports_external.record(exports_external.string(), AgentAuthorityRuleSchema).default({}),
|
|
17381
|
-
universal_deny_prefixes: exports_external.array(exports_external.string().min(1)).default([])
|
|
17381
|
+
universal_deny_prefixes: exports_external.array(exports_external.string().min(1)).default([]),
|
|
17382
|
+
verifier_config_paths: exports_external.array(exports_external.string()).optional().describe("Additional glob patterns for verifier config files that are merged into the architect agent's blockedGlobs at plugin init. Writes to matching files are blocked by the authority layer.")
|
|
17382
17383
|
});
|
|
17383
17384
|
GeneralCouncilMemberConfigSchema = exports_external.object({
|
|
17384
17385
|
memberId: exports_external.string().min(1),
|
|
@@ -17454,6 +17455,14 @@ var init_schema = __esm(() => {
|
|
|
17454
17455
|
const trimmed = v.trim();
|
|
17455
17456
|
return trimmed === "" ? undefined : trimmed;
|
|
17456
17457
|
}),
|
|
17458
|
+
auto_select_architect: exports_external.union([exports_external.boolean(), exports_external.string()]).optional().transform((v) => {
|
|
17459
|
+
if (v === undefined)
|
|
17460
|
+
return;
|
|
17461
|
+
if (typeof v === "boolean")
|
|
17462
|
+
return v;
|
|
17463
|
+
const trimmed = v.trim();
|
|
17464
|
+
return trimmed === "" ? false : trimmed;
|
|
17465
|
+
}),
|
|
17457
17466
|
swarms: exports_external.record(exports_external.string(), SwarmConfigSchema).optional(),
|
|
17458
17467
|
max_iterations: exports_external.number().min(1).max(10).default(5),
|
|
17459
17468
|
pipeline: PipelineConfigSchema.optional(),
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -641,6 +641,7 @@ export declare const AuthorityConfigSchema: z.ZodObject<{
|
|
|
641
641
|
allowedGlobs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
642
642
|
}, z.core.$strip>>>;
|
|
643
643
|
universal_deny_prefixes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
644
|
+
verifier_config_paths: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
644
645
|
}, z.core.$strip>;
|
|
645
646
|
export type AuthorityConfig = z.infer<typeof AuthorityConfigSchema>;
|
|
646
647
|
export declare const GeneralCouncilConfigSchema: z.ZodObject<{
|
|
@@ -827,6 +828,7 @@ export declare const PluginConfigSchema: z.ZodObject<{
|
|
|
827
828
|
fallback_models: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
828
829
|
}, z.core.$strip>>>;
|
|
829
830
|
default_agent: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string | undefined, string | undefined>>;
|
|
831
|
+
auto_select_architect: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>, z.ZodTransform<string | boolean | undefined, string | boolean | undefined>>;
|
|
830
832
|
swarms: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
831
833
|
name: z.ZodOptional<z.ZodString>;
|
|
832
834
|
agents: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
@@ -1005,6 +1007,7 @@ export declare const PluginConfigSchema: z.ZodObject<{
|
|
|
1005
1007
|
allowedGlobs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1006
1008
|
}, z.core.$strip>>>;
|
|
1007
1009
|
universal_deny_prefixes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1010
|
+
verifier_config_paths: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1008
1011
|
}, z.core.$strip>>;
|
|
1009
1012
|
plan_cursor: z.ZodOptional<z.ZodObject<{
|
|
1010
1013
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
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.
|
|
36
|
+
version: "7.22.0",
|
|
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",
|
|
@@ -15591,7 +15591,8 @@ var init_schema = __esm(() => {
|
|
|
15591
15591
|
AuthorityConfigSchema = exports_external.object({
|
|
15592
15592
|
enabled: exports_external.boolean().default(true),
|
|
15593
15593
|
rules: exports_external.record(exports_external.string(), AgentAuthorityRuleSchema).default({}),
|
|
15594
|
-
universal_deny_prefixes: exports_external.array(exports_external.string().min(1)).default([])
|
|
15594
|
+
universal_deny_prefixes: exports_external.array(exports_external.string().min(1)).default([]),
|
|
15595
|
+
verifier_config_paths: exports_external.array(exports_external.string()).optional().describe("Additional glob patterns for verifier config files that are merged into the architect agent's blockedGlobs at plugin init. Writes to matching files are blocked by the authority layer.")
|
|
15595
15596
|
});
|
|
15596
15597
|
GeneralCouncilMemberConfigSchema = exports_external.object({
|
|
15597
15598
|
memberId: exports_external.string().min(1),
|
|
@@ -15667,6 +15668,14 @@ var init_schema = __esm(() => {
|
|
|
15667
15668
|
const trimmed = v.trim();
|
|
15668
15669
|
return trimmed === "" ? undefined : trimmed;
|
|
15669
15670
|
}),
|
|
15671
|
+
auto_select_architect: exports_external.union([exports_external.boolean(), exports_external.string()]).optional().transform((v) => {
|
|
15672
|
+
if (v === undefined)
|
|
15673
|
+
return;
|
|
15674
|
+
if (typeof v === "boolean")
|
|
15675
|
+
return v;
|
|
15676
|
+
const trimmed = v.trim();
|
|
15677
|
+
return trimmed === "" ? false : trimmed;
|
|
15678
|
+
}),
|
|
15670
15679
|
swarms: exports_external.record(exports_external.string(), SwarmConfigSchema).optional(),
|
|
15671
15680
|
max_iterations: exports_external.number().min(1).max(10).default(5),
|
|
15672
15681
|
pipeline: PipelineConfigSchema.optional(),
|
|
@@ -24166,6 +24175,21 @@ var init_normalize_tool_name = __esm(() => {
|
|
|
24166
24175
|
import * as fsSync2 from "node:fs";
|
|
24167
24176
|
import * as fs8 from "node:fs/promises";
|
|
24168
24177
|
import * as path10 from "node:path";
|
|
24178
|
+
function isConfigFilePath(filePath, cwd, extraGlobs) {
|
|
24179
|
+
const normalized = path10.relative(path10.resolve(cwd), path10.resolve(cwd, filePath)).replace(/\\/g, "/");
|
|
24180
|
+
const { zone } = classifyFile(normalized);
|
|
24181
|
+
if (zone === "config") {
|
|
24182
|
+
return true;
|
|
24183
|
+
}
|
|
24184
|
+
const allGlobs = extraGlobs && extraGlobs.length > 0 ? [...KNOWN_VERIFIER_CONFIG_GLOBS, ...extraGlobs] : KNOWN_VERIFIER_CONFIG_GLOBS;
|
|
24185
|
+
for (const glob of allGlobs) {
|
|
24186
|
+
const matcher = getGlobMatcher(glob);
|
|
24187
|
+
if (matcher(normalized)) {
|
|
24188
|
+
return true;
|
|
24189
|
+
}
|
|
24190
|
+
}
|
|
24191
|
+
return false;
|
|
24192
|
+
}
|
|
24169
24193
|
function enforceSpecDriftGate(directory, toolName) {
|
|
24170
24194
|
if (!directory)
|
|
24171
24195
|
return;
|
|
@@ -24713,6 +24737,17 @@ function createGuardrailsHooks(directory, directoryOrConfig, config2, authorityC
|
|
|
24713
24737
|
};
|
|
24714
24738
|
}
|
|
24715
24739
|
const precomputedAuthorityRules = buildEffectiveRules(authorityConfig);
|
|
24740
|
+
const verifierPaths = authorityConfig?.verifier_config_paths;
|
|
24741
|
+
if (verifierPaths && verifierPaths.length > 0) {
|
|
24742
|
+
const existingArchitect = precomputedAuthorityRules.architect ?? {};
|
|
24743
|
+
precomputedAuthorityRules.architect = {
|
|
24744
|
+
...existingArchitect,
|
|
24745
|
+
blockedGlobs: [
|
|
24746
|
+
...existingArchitect.blockedGlobs ?? [],
|
|
24747
|
+
...verifierPaths
|
|
24748
|
+
]
|
|
24749
|
+
};
|
|
24750
|
+
}
|
|
24716
24751
|
const universalDenyPrefixes = authorityConfig?.universal_deny_prefixes ?? [];
|
|
24717
24752
|
const cfg = guardrailsConfig;
|
|
24718
24753
|
const requiredQaGates = cfg.qa_gates?.required_tools ?? [
|
|
@@ -25102,6 +25137,19 @@ function createGuardrailsHooks(directory, directoryOrConfig, config2, authorityC
|
|
|
25102
25137
|
if (!authorityCheck.allowed) {
|
|
25103
25138
|
throw new Error(`WRITE BLOCKED: Agent "${agentName}" is not authorised to write "${delegTargetPath}". Reason: ${authorityCheck.reason}`);
|
|
25104
25139
|
}
|
|
25140
|
+
if (isConfigFilePath(delegTargetPath, cwd, authorityConfig?.verifier_config_paths)) {
|
|
25141
|
+
const normalizedPath = path10.relative(path10.resolve(cwd), path10.resolve(cwd, delegTargetPath)).replace(/\\/g, "/");
|
|
25142
|
+
const logEntry = {
|
|
25143
|
+
agent: agentName,
|
|
25144
|
+
path: normalizedPath,
|
|
25145
|
+
allowed: authorityCheck.allowed,
|
|
25146
|
+
type: "delegated_write"
|
|
25147
|
+
};
|
|
25148
|
+
if (!authorityCheck.allowed && "reason" in authorityCheck) {
|
|
25149
|
+
logEntry.reason = authorityCheck.reason;
|
|
25150
|
+
}
|
|
25151
|
+
warn("Config file write attempt", logEntry);
|
|
25152
|
+
}
|
|
25105
25153
|
if (!currentSession.modifiedFilesThisCoderTask.includes(delegTargetPath)) {
|
|
25106
25154
|
currentSession.modifiedFilesThisCoderTask.push(delegTargetPath);
|
|
25107
25155
|
}
|
|
@@ -25112,6 +25160,19 @@ function createGuardrailsHooks(directory, directoryOrConfig, config2, authorityC
|
|
|
25112
25160
|
const cwd = effectiveDirectory;
|
|
25113
25161
|
for (const p of extractPatchTargetPaths(tool, args2)) {
|
|
25114
25162
|
const authorityCheck = checkFileAuthorityWithRules(agentName, p, cwd, precomputedAuthorityRules, { declaredScope: resolveDeclaredScope(sessionID) });
|
|
25163
|
+
if (isConfigFilePath(p, cwd, authorityConfig?.verifier_config_paths)) {
|
|
25164
|
+
const normalizedPath = path10.relative(path10.resolve(cwd), path10.resolve(cwd, p)).replace(/\\/g, "/");
|
|
25165
|
+
const logEntry = {
|
|
25166
|
+
agent: agentName,
|
|
25167
|
+
path: normalizedPath,
|
|
25168
|
+
allowed: authorityCheck.allowed,
|
|
25169
|
+
type: "delegated_patch"
|
|
25170
|
+
};
|
|
25171
|
+
if (!authorityCheck.allowed && "reason" in authorityCheck) {
|
|
25172
|
+
logEntry.reason = authorityCheck.reason;
|
|
25173
|
+
}
|
|
25174
|
+
warn("Config file write attempt", logEntry);
|
|
25175
|
+
}
|
|
25115
25176
|
if (!authorityCheck.allowed) {
|
|
25116
25177
|
throw new Error(`WRITE BLOCKED: Agent "${agentName}" is not authorised to write "${p}" (via patch). Reason: ${authorityCheck.reason}`);
|
|
25117
25178
|
}
|
|
@@ -25443,6 +25504,19 @@ function createGuardrailsHooks(directory, directoryOrConfig, config2, authorityC
|
|
|
25443
25504
|
if (!authorityCheck.allowed) {
|
|
25444
25505
|
throw new Error(`WRITE BLOCKED: Agent "${agentName}" is not authorised to write "${targetPath}". Reason: ${authorityCheck.reason}`);
|
|
25445
25506
|
}
|
|
25507
|
+
if (isConfigFilePath(targetPath, effectiveDirectory, authorityConfig?.verifier_config_paths)) {
|
|
25508
|
+
const normalizedPath = path10.relative(path10.resolve(effectiveDirectory), path10.resolve(effectiveDirectory, targetPath)).replace(/\\/g, "/");
|
|
25509
|
+
const logEntry = {
|
|
25510
|
+
agent: agentName,
|
|
25511
|
+
path: normalizedPath,
|
|
25512
|
+
allowed: authorityCheck.allowed,
|
|
25513
|
+
type: "direct_write"
|
|
25514
|
+
};
|
|
25515
|
+
if (!authorityCheck.allowed && "reason" in authorityCheck) {
|
|
25516
|
+
logEntry.reason = authorityCheck.reason;
|
|
25517
|
+
}
|
|
25518
|
+
warn("Config file write attempt", logEntry);
|
|
25519
|
+
}
|
|
25446
25520
|
}
|
|
25447
25521
|
}
|
|
25448
25522
|
if (input.tool === "apply_patch" || input.tool === "patch") {
|
|
@@ -25468,6 +25542,19 @@ function createGuardrailsHooks(directory, directoryOrConfig, config2, authorityC
|
|
|
25468
25542
|
if (!authorityCheck.allowed) {
|
|
25469
25543
|
throw new Error(`WRITE BLOCKED: Agent "${patchAgentName}" is not authorised to write "${p}" (via patch). Reason: ${authorityCheck.reason}`);
|
|
25470
25544
|
}
|
|
25545
|
+
if (isConfigFilePath(p, effectiveDirectory, authorityConfig?.verifier_config_paths)) {
|
|
25546
|
+
const normalizedPath = path10.relative(path10.resolve(effectiveDirectory), path10.resolve(effectiveDirectory, p)).replace(/\\/g, "/");
|
|
25547
|
+
const logEntry = {
|
|
25548
|
+
agent: patchAgentName,
|
|
25549
|
+
path: normalizedPath,
|
|
25550
|
+
allowed: authorityCheck.allowed,
|
|
25551
|
+
type: "direct_patch"
|
|
25552
|
+
};
|
|
25553
|
+
if (!authorityCheck.allowed && "reason" in authorityCheck) {
|
|
25554
|
+
logEntry.reason = authorityCheck.reason;
|
|
25555
|
+
}
|
|
25556
|
+
warn("Config file write attempt", logEntry);
|
|
25557
|
+
}
|
|
25471
25558
|
}
|
|
25472
25559
|
}
|
|
25473
25560
|
{
|
|
@@ -26170,11 +26257,11 @@ function checkWriteTargetForSymlink(targetPath, cwd) {
|
|
|
26170
26257
|
}
|
|
26171
26258
|
function buildEffectiveRules(authorityConfig) {
|
|
26172
26259
|
if (authorityConfig?.enabled === false || !authorityConfig?.rules) {
|
|
26173
|
-
return DEFAULT_AGENT_AUTHORITY_RULES;
|
|
26260
|
+
return { ...DEFAULT_AGENT_AUTHORITY_RULES };
|
|
26174
26261
|
}
|
|
26175
26262
|
const entries = Object.entries(authorityConfig.rules);
|
|
26176
26263
|
if (entries.length === 0) {
|
|
26177
|
-
return DEFAULT_AGENT_AUTHORITY_RULES;
|
|
26264
|
+
return { ...DEFAULT_AGENT_AUTHORITY_RULES };
|
|
26178
26265
|
}
|
|
26179
26266
|
const merged = {
|
|
26180
26267
|
...DEFAULT_AGENT_AUTHORITY_RULES
|
|
@@ -26312,7 +26399,7 @@ function checkFileAuthorityWithRules(agentName, filePath, cwd, effectiveRules, o
|
|
|
26312
26399
|
}
|
|
26313
26400
|
return { allowed: true };
|
|
26314
26401
|
}
|
|
26315
|
-
var import_picomatch, _internals10, SPEC_DRIFT_BLOCKED_TOOLS, storedInputArgs, TRANSIENT_STATUS_CODES, TRANSIENT_MODEL_ERROR_PATTERN, TRANSIENT_PROVIDER_RECOVERY_TAG = "TRANSIENT PROVIDER RECOVERY", DEGRADED_ERROR_PATTERN, CONTENT_FILTER_PATTERN, toolCallsSinceLastWrite, noOpWarningIssued, consecutiveNoToolTurns, DC_MAX_UNWRAP_DEPTH = 5, DC_SAFE_TARGETS, DC_BLOCKED_ABSOLUTE_PREFIXES, DC_FS_ROOTS, DC_REMOTE_PREFIXES, pathNormalizationCache, globMatcherCache, DEFAULT_AGENT_AUTHORITY_RULES;
|
|
26402
|
+
var import_picomatch, KNOWN_VERIFIER_CONFIG_GLOBS, _internals10, SPEC_DRIFT_BLOCKED_TOOLS, storedInputArgs, TRANSIENT_STATUS_CODES, TRANSIENT_MODEL_ERROR_PATTERN, TRANSIENT_PROVIDER_RECOVERY_TAG = "TRANSIENT PROVIDER RECOVERY", DEGRADED_ERROR_PATTERN, CONTENT_FILTER_PATTERN, toolCallsSinceLastWrite, noOpWarningIssued, consecutiveNoToolTurns, DC_MAX_UNWRAP_DEPTH = 5, DC_SAFE_TARGETS, DC_BLOCKED_ABSOLUTE_PREFIXES, DC_FS_ROOTS, DC_REMOTE_PREFIXES, pathNormalizationCache, globMatcherCache, DEFAULT_AGENT_AUTHORITY_RULES;
|
|
26316
26403
|
var init_guardrails = __esm(() => {
|
|
26317
26404
|
init_quick_lru();
|
|
26318
26405
|
init_agents2();
|
|
@@ -26332,6 +26419,17 @@ var init_guardrails = __esm(() => {
|
|
|
26332
26419
|
init_model_limits();
|
|
26333
26420
|
init_normalize_tool_name();
|
|
26334
26421
|
import_picomatch = __toESM(require_picomatch2(), 1);
|
|
26422
|
+
KNOWN_VERIFIER_CONFIG_GLOBS = [
|
|
26423
|
+
"**/oxlintrc*",
|
|
26424
|
+
"**/.oxlintrc*",
|
|
26425
|
+
"**/.eslintrc*",
|
|
26426
|
+
"**/eslint.config.*",
|
|
26427
|
+
"**/.prettierrc*",
|
|
26428
|
+
"**/prettier.config.*",
|
|
26429
|
+
"**/biome.jsonc",
|
|
26430
|
+
"**/.secretscanignore",
|
|
26431
|
+
"**/.golangci*"
|
|
26432
|
+
];
|
|
26335
26433
|
_internals10 = {
|
|
26336
26434
|
getSwarmAgents,
|
|
26337
26435
|
getMostRecentAssistantText,
|
|
@@ -26426,7 +26524,18 @@ var init_guardrails = __esm(() => {
|
|
|
26426
26524
|
explore: {},
|
|
26427
26525
|
architect: {
|
|
26428
26526
|
blockedExact: [".swarm/plan.md", ".swarm/plan.json"],
|
|
26429
|
-
blockedZones: ["generated"]
|
|
26527
|
+
blockedZones: ["generated", "config"],
|
|
26528
|
+
blockedGlobs: [
|
|
26529
|
+
"**/oxlintrc*",
|
|
26530
|
+
"**/.oxlintrc*",
|
|
26531
|
+
"**/.eslintrc*",
|
|
26532
|
+
"**/eslint.config.*",
|
|
26533
|
+
"**/.prettierrc*",
|
|
26534
|
+
"**/prettier.config.*",
|
|
26535
|
+
"**/biome.jsonc",
|
|
26536
|
+
"**/.secretscanignore",
|
|
26537
|
+
"**/.golangci*"
|
|
26538
|
+
]
|
|
26430
26539
|
},
|
|
26431
26540
|
coder: {
|
|
26432
26541
|
blockedPrefix: [".swarm/"],
|
|
@@ -65779,6 +65888,18 @@ DO (explicitly):
|
|
|
65779
65888
|
- VERIFY platform compatibility: path.join() used for all paths, no hardcoded separators
|
|
65780
65889
|
- For confirmed issues requiring a concrete fix: use suggest_patch to produce a structured patch artifact for the coder
|
|
65781
65890
|
|
|
65891
|
+
## CONFIG STRICTNESS VERIFICATION
|
|
65892
|
+
|
|
65893
|
+
When the declared scope includes a verifier/linter config file (biome.json, biome.jsonc, oxlintrc, oxlintrc.json, .eslintrc, .eslintrc.json, eslint.config.*, .prettierrc, .prettierrc.json, prettier.config.*, biome.jsonc, .secretscanignore, golangci-lint configs, tsconfig.json, tsconfig.*.json, or any other linter/formatter/security-tool configuration):
|
|
65894
|
+
|
|
65895
|
+
- Verify the change does NOT reduce strictness of any existing rule
|
|
65896
|
+
- Reject changes that downgrade "error" to "warn", remove rules, weaken validation thresholds, or narrow file/directory scopes
|
|
65897
|
+
- Allow changes that ADD new stricter rules, enable additional rule categories, fix syntax errors, or correct misconfigured paths
|
|
65898
|
+
- Document the specific config change and its impact on validation strictness in your review output
|
|
65899
|
+
- If a rule is changed from "error" to "warn" or a rule is removed: REJECT with STRICTNESS_REDUCTION: [rule name] — [original setting] → [new setting]
|
|
65900
|
+
|
|
65901
|
+
This is a pre-review gate: if config strictness is reduced, reject immediately without proceeding to Tier review.
|
|
65902
|
+
|
|
65782
65903
|
## REUSE RE-VERIFICATION (MANDATORY FOR NEW EXPORTS)
|
|
65783
65904
|
|
|
65784
65905
|
When EXPORTS_ADDED is non-empty in the coder's completion report:
|
|
@@ -80616,7 +80737,9 @@ var DENY_SHELL_PATTERNS = [
|
|
|
80616
80737
|
/\bbunx?\s+publish\b/i,
|
|
80617
80738
|
/\bterraform\s+(?:apply|destroy)\b/i,
|
|
80618
80739
|
/\bkubectl\s+(?:delete|apply\s+-f)/i,
|
|
80619
|
-
/\bdrop\s+(?:database|table)\b/i
|
|
80740
|
+
/\bdrop\s+(?:database|table)\b/i,
|
|
80741
|
+
/\bsed\s+-i\b(?=[^\n]*\b(?:biome\.json|eslintrc|oxlintrc)\b)(?=[^\n]*\b(?:error|warn|off)\b)/i,
|
|
80742
|
+
/\b(?:cat|tee)\b[^\n]*>\s*[^\n]*\b(biome\.json|eslintrc|oxlintrc)\b[^\n]*\b(error|warn|off)\b/i
|
|
80620
80743
|
];
|
|
80621
80744
|
var ESCALATE_SHELL_PATTERNS = [
|
|
80622
80745
|
/\bcurl\b/i,
|
|
@@ -80636,7 +80759,9 @@ var ESCALATE_SHELL_PATTERNS = [
|
|
|
80636
80759
|
/\bgit\s+pull\b/i,
|
|
80637
80760
|
/\bgit\s+rebase\b/i,
|
|
80638
80761
|
/\bgit\s+merge\b/i,
|
|
80639
|
-
/\bgit\s+commit\b/i
|
|
80762
|
+
/\bgit\s+commit\b/i,
|
|
80763
|
+
/\b(sed\s+-i|echo\s+|printf\s+)[^\n]*\b(biome\.jsonc?|eslintrc|eslint\.config|oxlintrc|prettierrc|secretscanignore|golangci|tsconfig\.json|tsconfig\.[^.]+\.json)\b/i,
|
|
80764
|
+
/\b(?:cat|tee)\b[^\n]*>\s*[^\n]*\b(biome\.jsonc?|eslintrc|eslint\.config|oxlintrc|prettierrc|secretscanignore|golangci|tsconfig\.json|tsconfig\.[^.]+\.json)\b/i
|
|
80640
80765
|
];
|
|
80641
80766
|
function isReadOnlyTool(toolName) {
|
|
80642
80767
|
if (!toolName)
|
|
@@ -105206,11 +105331,65 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
105206
105331
|
swarm_command: createSwarmCommandTool(agentDefinitionMap)
|
|
105207
105332
|
},
|
|
105208
105333
|
config: async (opencodeConfig) => {
|
|
105334
|
+
if (!opencodeConfig.agent || typeof opencodeConfig.agent !== "object") {
|
|
105335
|
+
opencodeConfig.agent = {};
|
|
105336
|
+
}
|
|
105209
105337
|
if (!opencodeConfig.agent) {
|
|
105210
105338
|
opencodeConfig.agent = { ...agents };
|
|
105211
105339
|
} else {
|
|
105212
105340
|
Object.assign(opencodeConfig.agent, agents);
|
|
105213
105341
|
}
|
|
105342
|
+
const autoSelect = config3?.auto_select_architect;
|
|
105343
|
+
if (autoSelect) {
|
|
105344
|
+
const hasArchitect = Object.keys(agents).some((name2) => stripKnownSwarmPrefix(name2) === "architect");
|
|
105345
|
+
if (hasArchitect) {
|
|
105346
|
+
for (const builtin of ["build", "plan"]) {
|
|
105347
|
+
const existing = opencodeConfig.agent?.[builtin];
|
|
105348
|
+
if (existing && typeof existing === "object" && existing.disable === true) {
|
|
105349
|
+
continue;
|
|
105350
|
+
}
|
|
105351
|
+
opencodeConfig.agent[builtin] = {
|
|
105352
|
+
...existing && typeof existing === "object" ? existing : {},
|
|
105353
|
+
disable: true
|
|
105354
|
+
};
|
|
105355
|
+
}
|
|
105356
|
+
if (autoSelect === true) {
|
|
105357
|
+
const primaryArchitects = Object.entries(agents).filter(([name2, cfg]) => stripKnownSwarmPrefix(name2) === "architect" && cfg.mode === "primary");
|
|
105358
|
+
if (primaryArchitects.length > 1) {
|
|
105359
|
+
const names = primaryArchitects.map(([n]) => n).join(", ");
|
|
105360
|
+
addDeferredWarning(`[swarm] auto_select_architect is true but ${primaryArchitects.length} architect agents are primary (${names}). Consider setting auto_select_architect to a specific agent name.`);
|
|
105361
|
+
}
|
|
105362
|
+
}
|
|
105363
|
+
if (typeof autoSelect === "string" && autoSelect !== "") {
|
|
105364
|
+
const targetName = autoSelect;
|
|
105365
|
+
const targetIsArchitect = Object.hasOwn(agents, targetName) && stripKnownSwarmPrefix(targetName) === "architect";
|
|
105366
|
+
if (targetIsArchitect) {
|
|
105367
|
+
for (const [name2, cfg] of Object.entries(agents)) {
|
|
105368
|
+
if (stripKnownSwarmPrefix(name2) === "architect" && name2 !== targetName) {
|
|
105369
|
+
if (opencodeConfig.agent && typeof opencodeConfig.agent === "object") {
|
|
105370
|
+
opencodeConfig.agent[name2] = {
|
|
105371
|
+
...cfg && typeof cfg === "object" ? cfg : {},
|
|
105372
|
+
mode: "subagent"
|
|
105373
|
+
};
|
|
105374
|
+
}
|
|
105375
|
+
}
|
|
105376
|
+
}
|
|
105377
|
+
if (opencodeConfig.agent && typeof opencodeConfig.agent === "object") {
|
|
105378
|
+
const targetExisting = opencodeConfig.agent[targetName];
|
|
105379
|
+
opencodeConfig.agent[targetName] = {
|
|
105380
|
+
...targetExisting && typeof targetExisting === "object" ? targetExisting : {},
|
|
105381
|
+
...agents[targetName] && typeof agents[targetName] === "object" ? agents[targetName] : {},
|
|
105382
|
+
mode: "primary"
|
|
105383
|
+
};
|
|
105384
|
+
}
|
|
105385
|
+
} else {
|
|
105386
|
+
addDeferredWarning(`[swarm] auto_select_architect is set to "${targetName}" but that is not a known architect agent. No architect demotion applied.`);
|
|
105387
|
+
}
|
|
105388
|
+
}
|
|
105389
|
+
} else {
|
|
105390
|
+
addDeferredWarning("[swarm] auto_select_architect is enabled but no architect agents were found in the generated set. The option has no effect.");
|
|
105391
|
+
}
|
|
105392
|
+
}
|
|
105214
105393
|
opencodeConfig.command = {
|
|
105215
105394
|
...opencodeConfig.command || {},
|
|
105216
105395
|
swarm: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.22.0",
|
|
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",
|