opencode-swarm 6.80.1 → 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/hooks/adversarial-detector.d.ts +2 -2
- package/dist/index.js +33 -10
- package/package.json +1 -1
|
@@ -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
|
@@ -65906,20 +65906,32 @@ Recommendation: Consider escalating to user or taking a different approach
|
|
|
65906
65906
|
The current fix strategy appears to be cycling without progress`;
|
|
65907
65907
|
return { eventLogged, checkpointCreated, message };
|
|
65908
65908
|
}
|
|
65909
|
-
var
|
|
65909
|
+
var recentToolCallsBySession = new Map;
|
|
65910
|
+
var lastSpiralTimestampBySession = new Map;
|
|
65910
65911
|
var MAX_RECENT_CALLS = 20;
|
|
65911
65912
|
var SPIRAL_THRESHOLD = 5;
|
|
65912
65913
|
var SPIRAL_WINDOW_MS = 300000;
|
|
65913
|
-
|
|
65914
|
+
var SPIRAL_COOLDOWN_MS = 60000;
|
|
65915
|
+
var MAX_TRACKED_SESSIONS = 500;
|
|
65916
|
+
function recordToolCall(tool3, args2, sessionId) {
|
|
65914
65917
|
const argsHash = typeof args2 === "string" ? args2.slice(0, 100) : JSON.stringify(args2 ?? "").slice(0, 100);
|
|
65915
|
-
|
|
65916
|
-
if (
|
|
65917
|
-
|
|
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();
|
|
65918
65926
|
}
|
|
65919
65927
|
}
|
|
65920
|
-
async function detectDebuggingSpiral(_directory) {
|
|
65928
|
+
async function detectDebuggingSpiral(_directory, sessionId) {
|
|
65921
65929
|
const now = Date.now();
|
|
65922
|
-
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);
|
|
65923
65935
|
if (windowCalls.length < SPIRAL_THRESHOLD)
|
|
65924
65936
|
return null;
|
|
65925
65937
|
const lastN = windowCalls.slice(-SPIRAL_THRESHOLD);
|
|
@@ -65928,6 +65940,17 @@ async function detectDebuggingSpiral(_directory) {
|
|
|
65928
65940
|
const allSameTool = lastN.every((c) => c.tool === firstTool);
|
|
65929
65941
|
const allSimilarArgs = lastN.every((c) => c.argsHash === firstArgs);
|
|
65930
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
|
+
}
|
|
65931
65954
|
return {
|
|
65932
65955
|
pattern: "VELOCITY_RATIONALIZATION",
|
|
65933
65956
|
severity: "HIGH",
|
|
@@ -85897,12 +85920,12 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
85897
85920
|
} catch {}
|
|
85898
85921
|
}
|
|
85899
85922
|
try {
|
|
85900
|
-
recordToolCall(normalizedTool, input.args);
|
|
85923
|
+
recordToolCall(normalizedTool, input.args, input.sessionID);
|
|
85901
85924
|
} catch {}
|
|
85902
85925
|
try {
|
|
85903
|
-
const spiralMatch = await detectDebuggingSpiral(ctx.directory);
|
|
85926
|
+
const spiralMatch = await detectDebuggingSpiral(ctx.directory, input.sessionID);
|
|
85904
85927
|
if (spiralMatch) {
|
|
85905
|
-
const taskId = swarmState.agentSessions.get(input.sessionID)?.currentTaskId ??
|
|
85928
|
+
const taskId = swarmState.agentSessions.get(input.sessionID)?.currentTaskId ?? `session-${input.sessionID.slice(0, 12)}`;
|
|
85906
85929
|
const spiralResult = await handleDebuggingSpiral(spiralMatch, taskId, ctx.directory);
|
|
85907
85930
|
const session = swarmState.agentSessions.get(input.sessionID);
|
|
85908
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",
|