opencode-swarm 6.36.0 → 6.37.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
|
@@ -36582,7 +36582,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
36582
36582
|
return false;
|
|
36583
36583
|
}
|
|
36584
36584
|
function containsControlChars(str) {
|
|
36585
|
-
return /[\0\r]/.test(str);
|
|
36585
|
+
return /[\0\t\r\n]/.test(str);
|
|
36586
36586
|
}
|
|
36587
36587
|
function validateDirectoryInput(dir) {
|
|
36588
36588
|
if (!dir || dir.length === 0) {
|
|
@@ -50,6 +50,13 @@ export declare function createDelegationGateHook(config: PluginConfig, directory
|
|
|
50
50
|
messagesTransform: (input: Record<string, never>, output: {
|
|
51
51
|
messages?: MessageWithParts[];
|
|
52
52
|
}) => Promise<void>;
|
|
53
|
+
toolBefore: (input: {
|
|
54
|
+
tool: string;
|
|
55
|
+
sessionID: string;
|
|
56
|
+
callID: string;
|
|
57
|
+
}, output: {
|
|
58
|
+
args: unknown;
|
|
59
|
+
}) => Promise<void>;
|
|
53
60
|
toolAfter: (input: {
|
|
54
61
|
tool: string;
|
|
55
62
|
sessionID: string;
|
package/dist/index.js
CHANGED
|
@@ -34195,7 +34195,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
34195
34195
|
return false;
|
|
34196
34196
|
}
|
|
34197
34197
|
function containsControlChars(str) {
|
|
34198
|
-
return /[\0\r]/.test(str);
|
|
34198
|
+
return /[\0\t\r\n]/.test(str);
|
|
34199
34199
|
}
|
|
34200
34200
|
function validateDirectoryInput(dir) {
|
|
34201
34201
|
if (!dir || dir.length === 0) {
|
|
@@ -40386,7 +40386,7 @@ async function readPlanFromDisk(directory) {
|
|
|
40386
40386
|
return null;
|
|
40387
40387
|
}
|
|
40388
40388
|
}
|
|
40389
|
-
async function
|
|
40389
|
+
async function readGateEvidenceFromDisk(directory) {
|
|
40390
40390
|
const evidenceMap = new Map;
|
|
40391
40391
|
try {
|
|
40392
40392
|
const evidenceDir = path3.join(directory, ".swarm", "evidence");
|
|
@@ -40421,7 +40421,7 @@ async function buildRehydrationCache(directory) {
|
|
|
40421
40421
|
}
|
|
40422
40422
|
}
|
|
40423
40423
|
}
|
|
40424
|
-
const evidenceMap = await
|
|
40424
|
+
const evidenceMap = await readGateEvidenceFromDisk(directory);
|
|
40425
40425
|
_rehydrationCache = { planTaskStates, evidenceMap };
|
|
40426
40426
|
}
|
|
40427
40427
|
function applyRehydrationCache(session) {
|
|
@@ -40530,7 +40530,9 @@ Do not re-trigger DISCOVER or CONSULT because you noticed a project phase bounda
|
|
|
40530
40530
|
Output to .swarm/plan.md MUST use "## Phase N" headers. Do not write MODE labels into plan.md.
|
|
40531
40531
|
|
|
40532
40532
|
1. DELEGATE all coding to {{AGENT_PREFIX}}coder. You do NOT write code.
|
|
40533
|
-
|
|
40533
|
+
// IMPORTANT: This list MUST match AGENT_TOOL_MAP['architect'] in src/config/constants.ts
|
|
40534
|
+
// If you add a tool to the map, add it here. If you remove it from the map, remove it here.
|
|
40535
|
+
YOUR TOOLS: Task (delegation), checkpoint, check_gate_status, complexity_hotspots, declare_scope, detect_domains, diff, evidence_check, extract_code_blocks, gitingest, imports, knowledge_query, lint, pkg_audit, pre_check_batch, retrieve_summary, save_plan, schema_drift, secretscan, symbols, test_runner, todo_extract, update_task_status, write_retro.
|
|
40534
40536
|
CODER'S TOOLS: write, edit, patch, apply_patch, create_file, insert, replace \u2014 any tool that modifies file contents.
|
|
40535
40537
|
If a tool modifies a file, it is a CODER tool. Delegate.
|
|
40536
40538
|
2. ONE agent per message. Send, STOP, wait for response.
|
|
@@ -51144,15 +51146,19 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
|
|
|
51144
51146
|
const errorContent = output.error ?? outputStr;
|
|
51145
51147
|
if (typeof errorContent === "string" && TRANSIENT_MODEL_ERROR_PATTERN.test(errorContent) && !session.modelFallbackExhausted) {
|
|
51146
51148
|
session.model_fallback_index++;
|
|
51147
|
-
session.modelFallbackExhausted = true;
|
|
51148
51149
|
const baseAgentName = session.agentName ? session.agentName.replace(/^[^_]+[_]/, "") : "";
|
|
51149
|
-
const
|
|
51150
|
+
const swarmAgents = getSwarmAgents();
|
|
51151
|
+
const fallbackModels = swarmAgents?.[baseAgentName]?.fallback_models;
|
|
51152
|
+
session.modelFallbackExhausted = !fallbackModels || session.model_fallback_index > fallbackModels.length;
|
|
51153
|
+
const fallbackModel = resolveFallbackModel(baseAgentName, session.model_fallback_index, swarmAgents);
|
|
51150
51154
|
if (fallbackModel) {
|
|
51151
|
-
const swarmAgents = getSwarmAgents();
|
|
51152
51155
|
const primaryModel = swarmAgents?.[baseAgentName]?.model ?? "default";
|
|
51156
|
+
if (swarmAgents?.[baseAgentName]) {
|
|
51157
|
+
swarmAgents[baseAgentName].model = fallbackModel;
|
|
51158
|
+
}
|
|
51153
51159
|
telemetry.modelFallback(input.sessionID, session.agentName, primaryModel, fallbackModel, "transient_model_error");
|
|
51154
51160
|
session.pendingAdvisoryMessages ??= [];
|
|
51155
|
-
session.pendingAdvisoryMessages.push(`MODEL FALLBACK:
|
|
51161
|
+
session.pendingAdvisoryMessages.push(`MODEL FALLBACK: Applied fallback model "${fallbackModel}" (attempt ${session.model_fallback_index}). ` + `Using /swarm handoff to reset to primary model.`);
|
|
51156
51162
|
} else {
|
|
51157
51163
|
session.pendingAdvisoryMessages ??= [];
|
|
51158
51164
|
session.pendingAdvisoryMessages.push(`MODEL FALLBACK: Transient model error detected (attempt ${session.model_fallback_index}). ` + `No fallback models configured for this agent. Add "fallback_models": ["model-a", "model-b"] ` + `to the agent's config in opencode-swarm.json.`);
|
|
@@ -51558,9 +51564,40 @@ function createDelegationGateHook(config3, directory) {
|
|
|
51558
51564
|
if (!enabled) {
|
|
51559
51565
|
return {
|
|
51560
51566
|
messagesTransform: async (_input, _output) => {},
|
|
51567
|
+
toolBefore: async () => {},
|
|
51561
51568
|
toolAfter: async () => {}
|
|
51562
51569
|
};
|
|
51563
51570
|
}
|
|
51571
|
+
const toolBefore = async (input, output) => {
|
|
51572
|
+
if (!input.sessionID)
|
|
51573
|
+
return;
|
|
51574
|
+
const normalized = input.tool.replace(/^[^:]+[:.]/, "");
|
|
51575
|
+
if (normalized !== "Task" && normalized !== "task")
|
|
51576
|
+
return;
|
|
51577
|
+
const args2 = output.args;
|
|
51578
|
+
if (!args2)
|
|
51579
|
+
return;
|
|
51580
|
+
const subagentType = args2.subagent_type;
|
|
51581
|
+
if (typeof subagentType !== "string")
|
|
51582
|
+
return;
|
|
51583
|
+
const targetAgent = stripKnownSwarmPrefix(subagentType);
|
|
51584
|
+
if (targetAgent !== "coder")
|
|
51585
|
+
return;
|
|
51586
|
+
const session = swarmState.agentSessions.get(input.sessionID);
|
|
51587
|
+
if (!session || !session.taskWorkflowStates)
|
|
51588
|
+
return;
|
|
51589
|
+
for (const [taskId, state2] of session.taskWorkflowStates) {
|
|
51590
|
+
if (state2 !== "coder_delegated")
|
|
51591
|
+
continue;
|
|
51592
|
+
const turbo = hasActiveTurboMode(input.sessionID);
|
|
51593
|
+
if (turbo) {
|
|
51594
|
+
const isTier3 = taskId.startsWith("3.");
|
|
51595
|
+
if (!isTier3)
|
|
51596
|
+
continue;
|
|
51597
|
+
}
|
|
51598
|
+
throw new Error(`REVIEWER_GATE_VIOLATION: Cannot re-delegate to coder without reviewer delegation. ` + `Task ${taskId} state: coder_delegated. Delegate to reviewer first.`);
|
|
51599
|
+
}
|
|
51600
|
+
};
|
|
51564
51601
|
const toolAfter = async (input, _output) => {
|
|
51565
51602
|
if (!input.sessionID)
|
|
51566
51603
|
return;
|
|
@@ -51782,6 +51819,7 @@ function createDelegationGateHook(config3, directory) {
|
|
|
51782
51819
|
}
|
|
51783
51820
|
};
|
|
51784
51821
|
return {
|
|
51822
|
+
toolBefore,
|
|
51785
51823
|
messagesTransform: async (_input, output) => {
|
|
51786
51824
|
const messages = output.messages;
|
|
51787
51825
|
if (!messages || messages.length === 0)
|
|
@@ -66221,6 +66259,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
66221
66259
|
}
|
|
66222
66260
|
await guardrailsHooks.toolBefore(input, output);
|
|
66223
66261
|
await scopeGuardHook.toolBefore(input, output);
|
|
66262
|
+
await delegationGateHooks.toolBefore(input, output);
|
|
66224
66263
|
if (swarmState.lastBudgetPct >= 50) {
|
|
66225
66264
|
const pressureSession = ensureAgentSession(input.sessionID, swarmState.activeAgent.get(input.sessionID) ?? ORCHESTRATOR_NAME);
|
|
66226
66265
|
if (!pressureSession.contextPressureWarningSent) {
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
* Adversarial security tests for Task 2.15: Session restart rehydration
|
|
3
3
|
*
|
|
4
4
|
* ONLY attack vectors - malformed inputs, oversized payloads, injection attempts, boundary violations
|
|
5
|
-
* Tests the security hardening of rehydrateSessionFromDisk, readPlanFromDisk, and
|
|
5
|
+
* Tests the security hardening of rehydrateSessionFromDisk, readPlanFromDisk, and readGateEvidenceFromDisk
|
|
6
6
|
*/
|
|
7
7
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.37.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",
|