opencode-swarm 6.80.0 → 6.80.2
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 +9 -0
- package/dist/config/constants.d.ts +1 -0
- package/dist/hooks/adversarial-detector.d.ts +2 -2
- package/dist/index.js +57 -12
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -18738,6 +18738,15 @@ var ALL_AGENT_NAMES = [
|
|
|
18738
18738
|
ORCHESTRATOR_NAME,
|
|
18739
18739
|
...ALL_SUBAGENT_NAMES
|
|
18740
18740
|
];
|
|
18741
|
+
var OPENCODE_NATIVE_AGENTS = new Set([
|
|
18742
|
+
"build",
|
|
18743
|
+
"plan",
|
|
18744
|
+
"general",
|
|
18745
|
+
"explore",
|
|
18746
|
+
"compaction",
|
|
18747
|
+
"title",
|
|
18748
|
+
"summary"
|
|
18749
|
+
]);
|
|
18741
18750
|
var AGENT_TOOL_MAP = {
|
|
18742
18751
|
architect: [
|
|
18743
18752
|
"checkpoint",
|
|
@@ -4,6 +4,7 @@ export declare const PIPELINE_AGENTS: readonly ["explorer", "coder", "test_engin
|
|
|
4
4
|
export declare const ORCHESTRATOR_NAME: "architect";
|
|
5
5
|
export declare const ALL_SUBAGENT_NAMES: readonly ["sme", "docs", "designer", "critic_sounding_board", "critic_drift_verifier", "critic_hallucination_verifier", "curator_init", "curator_phase", "reviewer", "critic", "critic_oversight", "explorer", "coder", "test_engineer"];
|
|
6
6
|
export declare const ALL_AGENT_NAMES: readonly ["architect", "sme", "docs", "designer", "critic_sounding_board", "critic_drift_verifier", "critic_hallucination_verifier", "curator_init", "curator_phase", "reviewer", "critic", "critic_oversight", "explorer", "coder", "test_engineer"];
|
|
7
|
+
export declare const OPENCODE_NATIVE_AGENTS: Set<"compaction" | "title" | "build" | "plan" | "general" | "explore" | "summary">;
|
|
7
8
|
export type QAAgentName = (typeof QA_AGENTS)[number];
|
|
8
9
|
export type PipelineAgentName = (typeof PIPELINE_AGENTS)[number];
|
|
9
10
|
export type AgentName = (typeof ALL_AGENT_NAMES)[number];
|
|
@@ -42,9 +42,9 @@ export declare function handleDebuggingSpiral(match: AdversarialPatternMatch, ta
|
|
|
42
42
|
* Record a tool call for debugging spiral detection.
|
|
43
43
|
* Call this from toolAfter to track repetitive patterns.
|
|
44
44
|
*/
|
|
45
|
-
export declare function recordToolCall(tool: string, args: unknown): void;
|
|
45
|
+
export declare function recordToolCall(tool: string, args: unknown, sessionId: string): void;
|
|
46
46
|
/**
|
|
47
47
|
* Detect debugging spiral: same tool called 5+ times in a row with similar args
|
|
48
48
|
* within a 5-minute window. Indicates the agent is stuck in a loop.
|
|
49
49
|
*/
|
|
50
|
-
export declare function detectDebuggingSpiral(_directory: string): Promise<AdversarialPatternMatch | null>;
|
|
50
|
+
export declare function detectDebuggingSpiral(_directory: string, sessionId: string): Promise<AdversarialPatternMatch | null>;
|
package/dist/index.js
CHANGED
|
@@ -129,7 +129,7 @@ function isLowCapabilityModel(modelId) {
|
|
|
129
129
|
const lower = modelId.toLowerCase();
|
|
130
130
|
return LOW_CAPABILITY_MODELS.some((substr) => lower.includes(substr));
|
|
131
131
|
}
|
|
132
|
-
var QA_AGENTS, PIPELINE_AGENTS, ORCHESTRATOR_NAME = "architect", ALL_SUBAGENT_NAMES, ALL_AGENT_NAMES, AGENT_TOOL_MAP, WRITE_TOOL_NAMES, TOOL_DESCRIPTIONS, DEFAULT_MODELS, DEFAULT_SCORING_CONFIG, LOW_CAPABILITY_MODELS, TURBO_MODE_BANNER = `## \uD83D\uDE80 TURBO MODE ACTIVE
|
|
132
|
+
var QA_AGENTS, PIPELINE_AGENTS, ORCHESTRATOR_NAME = "architect", ALL_SUBAGENT_NAMES, ALL_AGENT_NAMES, OPENCODE_NATIVE_AGENTS, AGENT_TOOL_MAP, WRITE_TOOL_NAMES, TOOL_DESCRIPTIONS, DEFAULT_MODELS, DEFAULT_SCORING_CONFIG, LOW_CAPABILITY_MODELS, TURBO_MODE_BANNER = `## \uD83D\uDE80 TURBO MODE ACTIVE
|
|
133
133
|
|
|
134
134
|
**Speed optimization enabled for this session.**
|
|
135
135
|
|
|
@@ -177,6 +177,15 @@ var init_constants = __esm(() => {
|
|
|
177
177
|
ORCHESTRATOR_NAME,
|
|
178
178
|
...ALL_SUBAGENT_NAMES
|
|
179
179
|
];
|
|
180
|
+
OPENCODE_NATIVE_AGENTS = new Set([
|
|
181
|
+
"build",
|
|
182
|
+
"plan",
|
|
183
|
+
"general",
|
|
184
|
+
"explore",
|
|
185
|
+
"compaction",
|
|
186
|
+
"title",
|
|
187
|
+
"summary"
|
|
188
|
+
]);
|
|
180
189
|
AGENT_TOOL_MAP = {
|
|
181
190
|
architect: [
|
|
182
191
|
"checkpoint",
|
|
@@ -22640,6 +22649,9 @@ function isWriteTool(toolName) {
|
|
|
22640
22649
|
const normalized = normalizeToolName(toolName);
|
|
22641
22650
|
return WRITE_TOOL_NAMES.includes(normalized);
|
|
22642
22651
|
}
|
|
22652
|
+
function isNativeOpencodeAgent(agentName) {
|
|
22653
|
+
return OPENCODE_NATIVE_AGENTS.has(agentName.toLowerCase());
|
|
22654
|
+
}
|
|
22643
22655
|
function isArchitect(sessionId) {
|
|
22644
22656
|
const activeAgent = swarmState.activeAgent.get(sessionId);
|
|
22645
22657
|
if (activeAgent) {
|
|
@@ -23538,17 +23550,23 @@ function createGuardrailsHooks(directory, directoryOrConfig, config2, authorityC
|
|
|
23538
23550
|
const strippedAgent = rawActiveAgent ? stripKnownSwarmPrefix(rawActiveAgent) : undefined;
|
|
23539
23551
|
if (strippedAgent === ORCHESTRATOR_NAME)
|
|
23540
23552
|
return null;
|
|
23553
|
+
if (strippedAgent && isNativeOpencodeAgent(strippedAgent))
|
|
23554
|
+
return null;
|
|
23541
23555
|
const existingSession = swarmState.agentSessions.get(sessionID);
|
|
23542
23556
|
if (existingSession) {
|
|
23543
23557
|
const sessionAgent = stripKnownSwarmPrefix(existingSession.agentName);
|
|
23544
23558
|
if (sessionAgent === ORCHESTRATOR_NAME)
|
|
23545
23559
|
return null;
|
|
23560
|
+
if (isNativeOpencodeAgent(sessionAgent))
|
|
23561
|
+
return null;
|
|
23546
23562
|
}
|
|
23547
23563
|
const agentName = swarmState.activeAgent.get(sessionID) ?? ORCHESTRATOR_NAME;
|
|
23548
23564
|
const session = ensureAgentSession(sessionID, agentName);
|
|
23549
23565
|
const resolvedName = stripKnownSwarmPrefix(session.agentName);
|
|
23550
23566
|
if (resolvedName === ORCHESTRATOR_NAME)
|
|
23551
23567
|
return null;
|
|
23568
|
+
if (isNativeOpencodeAgent(resolvedName))
|
|
23569
|
+
return null;
|
|
23552
23570
|
const agentConfig = resolveGuardrailsConfig(cfg, session.agentName);
|
|
23553
23571
|
if (agentConfig.max_duration_minutes === 0 && agentConfig.max_tool_calls === 0) {
|
|
23554
23572
|
return null;
|
|
@@ -24475,6 +24493,10 @@ var init_guardrails = __esm(() => {
|
|
|
24475
24493
|
maxSize: 200
|
|
24476
24494
|
});
|
|
24477
24495
|
DEFAULT_AGENT_AUTHORITY_RULES = {
|
|
24496
|
+
build: {},
|
|
24497
|
+
plan: {},
|
|
24498
|
+
general: {},
|
|
24499
|
+
explore: {},
|
|
24478
24500
|
architect: {
|
|
24479
24501
|
blockedExact: [".swarm/plan.md", ".swarm/plan.json"],
|
|
24480
24502
|
blockedZones: ["generated"]
|
|
@@ -65884,20 +65906,32 @@ Recommendation: Consider escalating to user or taking a different approach
|
|
|
65884
65906
|
The current fix strategy appears to be cycling without progress`;
|
|
65885
65907
|
return { eventLogged, checkpointCreated, message };
|
|
65886
65908
|
}
|
|
65887
|
-
var
|
|
65909
|
+
var recentToolCallsBySession = new Map;
|
|
65910
|
+
var lastSpiralTimestampBySession = new Map;
|
|
65888
65911
|
var MAX_RECENT_CALLS = 20;
|
|
65889
65912
|
var SPIRAL_THRESHOLD = 5;
|
|
65890
65913
|
var SPIRAL_WINDOW_MS = 300000;
|
|
65891
|
-
|
|
65914
|
+
var SPIRAL_COOLDOWN_MS = 60000;
|
|
65915
|
+
var MAX_TRACKED_SESSIONS = 500;
|
|
65916
|
+
function recordToolCall(tool3, args2, sessionId) {
|
|
65892
65917
|
const argsHash = typeof args2 === "string" ? args2.slice(0, 100) : JSON.stringify(args2 ?? "").slice(0, 100);
|
|
65893
|
-
|
|
65894
|
-
if (
|
|
65895
|
-
|
|
65918
|
+
let calls = recentToolCallsBySession.get(sessionId);
|
|
65919
|
+
if (!calls) {
|
|
65920
|
+
calls = [];
|
|
65921
|
+
recentToolCallsBySession.set(sessionId, calls);
|
|
65922
|
+
}
|
|
65923
|
+
calls.push({ tool: tool3, argsHash, timestamp: Date.now() });
|
|
65924
|
+
if (calls.length > MAX_RECENT_CALLS) {
|
|
65925
|
+
calls.shift();
|
|
65896
65926
|
}
|
|
65897
65927
|
}
|
|
65898
|
-
async function detectDebuggingSpiral(_directory) {
|
|
65928
|
+
async function detectDebuggingSpiral(_directory, sessionId) {
|
|
65899
65929
|
const now = Date.now();
|
|
65900
|
-
const
|
|
65930
|
+
const lastTrigger = lastSpiralTimestampBySession.get(sessionId) ?? 0;
|
|
65931
|
+
if (now - lastTrigger < SPIRAL_COOLDOWN_MS)
|
|
65932
|
+
return null;
|
|
65933
|
+
const calls = recentToolCallsBySession.get(sessionId) ?? [];
|
|
65934
|
+
const windowCalls = calls.filter((c) => now - c.timestamp < SPIRAL_WINDOW_MS);
|
|
65901
65935
|
if (windowCalls.length < SPIRAL_THRESHOLD)
|
|
65902
65936
|
return null;
|
|
65903
65937
|
const lastN = windowCalls.slice(-SPIRAL_THRESHOLD);
|
|
@@ -65906,6 +65940,17 @@ async function detectDebuggingSpiral(_directory) {
|
|
|
65906
65940
|
const allSameTool = lastN.every((c) => c.tool === firstTool);
|
|
65907
65941
|
const allSimilarArgs = lastN.every((c) => c.argsHash === firstArgs);
|
|
65908
65942
|
if (allSameTool && allSimilarArgs) {
|
|
65943
|
+
lastSpiralTimestampBySession.set(sessionId, now);
|
|
65944
|
+
recentToolCallsBySession.delete(sessionId);
|
|
65945
|
+
if (lastSpiralTimestampBySession.size > MAX_TRACKED_SESSIONS) {
|
|
65946
|
+
for (const oldest of lastSpiralTimestampBySession.keys()) {
|
|
65947
|
+
if (oldest !== sessionId) {
|
|
65948
|
+
lastSpiralTimestampBySession.delete(oldest);
|
|
65949
|
+
recentToolCallsBySession.delete(oldest);
|
|
65950
|
+
break;
|
|
65951
|
+
}
|
|
65952
|
+
}
|
|
65953
|
+
}
|
|
65909
65954
|
return {
|
|
65910
65955
|
pattern: "VELOCITY_RATIONALIZATION",
|
|
65911
65956
|
severity: "HIGH",
|
|
@@ -67734,7 +67779,7 @@ var GUARD_KEYWORDS = [
|
|
|
67734
67779
|
function isGuardKeyword(name2) {
|
|
67735
67780
|
return GUARD_KEYWORDS.some((keyword) => {
|
|
67736
67781
|
const ciKeyword = keyword.split("").map((c) => `[${c.toLowerCase()}${c.toUpperCase()}]`).join("");
|
|
67737
|
-
const re = new RegExp(
|
|
67782
|
+
const re = new RegExp(`(?<![a-z])${ciKeyword}(?![a-z])`);
|
|
67738
67783
|
return re.test(name2);
|
|
67739
67784
|
});
|
|
67740
67785
|
}
|
|
@@ -85875,12 +85920,12 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
85875
85920
|
} catch {}
|
|
85876
85921
|
}
|
|
85877
85922
|
try {
|
|
85878
|
-
recordToolCall(normalizedTool, input.args);
|
|
85923
|
+
recordToolCall(normalizedTool, input.args, input.sessionID);
|
|
85879
85924
|
} catch {}
|
|
85880
85925
|
try {
|
|
85881
|
-
const spiralMatch = await detectDebuggingSpiral(ctx.directory);
|
|
85926
|
+
const spiralMatch = await detectDebuggingSpiral(ctx.directory, input.sessionID);
|
|
85882
85927
|
if (spiralMatch) {
|
|
85883
|
-
const taskId = swarmState.agentSessions.get(input.sessionID)?.currentTaskId ??
|
|
85928
|
+
const taskId = swarmState.agentSessions.get(input.sessionID)?.currentTaskId ?? `session-${input.sessionID.slice(0, 12)}`;
|
|
85884
85929
|
const spiralResult = await handleDebuggingSpiral(spiralMatch, taskId, ctx.directory);
|
|
85885
85930
|
const session = swarmState.agentSessions.get(input.sessionID);
|
|
85886
85931
|
if (session) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "6.80.
|
|
3
|
+
"version": "6.80.2",
|
|
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",
|