opencode-swarm 5.0.4 → 5.0.6
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/config/schema.d.ts +10 -2
- package/dist/index.js +67 -18
- package/dist/state.d.ts +2 -0
- package/package.json +1 -1
- package/dist/guardrails.js +0 -178
- package/dist/state.js +0 -48
package/dist/config/schema.d.ts
CHANGED
|
@@ -45,7 +45,15 @@ export declare const GuardrailsProfileSchema: z.ZodObject<{
|
|
|
45
45
|
warning_threshold: z.ZodOptional<z.ZodNumber>;
|
|
46
46
|
}, z.core.$strip>;
|
|
47
47
|
export type GuardrailsProfile = z.infer<typeof GuardrailsProfileSchema>;
|
|
48
|
-
export declare const
|
|
48
|
+
export declare const DEFAULT_AGENT_PROFILES: Record<string, GuardrailsProfile>;
|
|
49
|
+
/** @deprecated Use DEFAULT_AGENT_PROFILES.architect instead */
|
|
50
|
+
export declare const DEFAULT_ARCHITECT_PROFILE: {
|
|
51
|
+
max_tool_calls?: number | undefined;
|
|
52
|
+
max_duration_minutes?: number | undefined;
|
|
53
|
+
max_repetitions?: number | undefined;
|
|
54
|
+
max_consecutive_errors?: number | undefined;
|
|
55
|
+
warning_threshold?: number | undefined;
|
|
56
|
+
};
|
|
49
57
|
export declare const GuardrailsConfigSchema: z.ZodObject<{
|
|
50
58
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
51
59
|
max_tool_calls: z.ZodDefault<z.ZodNumber>;
|
|
@@ -76,7 +84,7 @@ export type GuardrailsConfig = z.infer<typeof GuardrailsConfigSchema>;
|
|
|
76
84
|
export declare function stripKnownSwarmPrefix(name: string): string;
|
|
77
85
|
/**
|
|
78
86
|
* Resolve guardrails configuration for a specific agent.
|
|
79
|
-
* Merges the base config with built-in defaults
|
|
87
|
+
* Merges the base config with built-in agent-type defaults and
|
|
80
88
|
* any per-agent profile overrides. Merge order: base < built-in < user profile.
|
|
81
89
|
*
|
|
82
90
|
* @param base - The base guardrails configuration
|
package/dist/index.js
CHANGED
|
@@ -13623,19 +13623,52 @@ var GuardrailsProfileSchema = exports_external.object({
|
|
|
13623
13623
|
max_consecutive_errors: exports_external.number().min(2).max(20).optional(),
|
|
13624
13624
|
warning_threshold: exports_external.number().min(0.1).max(0.9).optional()
|
|
13625
13625
|
});
|
|
13626
|
-
var
|
|
13627
|
-
|
|
13628
|
-
|
|
13629
|
-
|
|
13630
|
-
|
|
13626
|
+
var DEFAULT_AGENT_PROFILES = {
|
|
13627
|
+
architect: {
|
|
13628
|
+
max_tool_calls: 800,
|
|
13629
|
+
max_duration_minutes: 90,
|
|
13630
|
+
max_consecutive_errors: 8,
|
|
13631
|
+
warning_threshold: 0.75
|
|
13632
|
+
},
|
|
13633
|
+
coder: {
|
|
13634
|
+
max_tool_calls: 400,
|
|
13635
|
+
max_duration_minutes: 45,
|
|
13636
|
+
warning_threshold: 0.85
|
|
13637
|
+
},
|
|
13638
|
+
test_engineer: {
|
|
13639
|
+
max_tool_calls: 400,
|
|
13640
|
+
max_duration_minutes: 45,
|
|
13641
|
+
warning_threshold: 0.85
|
|
13642
|
+
},
|
|
13643
|
+
explorer: {
|
|
13644
|
+
max_tool_calls: 150,
|
|
13645
|
+
max_duration_minutes: 20,
|
|
13646
|
+
warning_threshold: 0.75
|
|
13647
|
+
},
|
|
13648
|
+
reviewer: {
|
|
13649
|
+
max_tool_calls: 200,
|
|
13650
|
+
max_duration_minutes: 30,
|
|
13651
|
+
warning_threshold: 0.65
|
|
13652
|
+
},
|
|
13653
|
+
critic: {
|
|
13654
|
+
max_tool_calls: 200,
|
|
13655
|
+
max_duration_minutes: 30,
|
|
13656
|
+
warning_threshold: 0.65
|
|
13657
|
+
},
|
|
13658
|
+
sme: {
|
|
13659
|
+
max_tool_calls: 200,
|
|
13660
|
+
max_duration_minutes: 30,
|
|
13661
|
+
warning_threshold: 0.65
|
|
13662
|
+
}
|
|
13631
13663
|
};
|
|
13664
|
+
var DEFAULT_ARCHITECT_PROFILE = DEFAULT_AGENT_PROFILES.architect;
|
|
13632
13665
|
var GuardrailsConfigSchema = exports_external.object({
|
|
13633
13666
|
enabled: exports_external.boolean().default(true),
|
|
13634
13667
|
max_tool_calls: exports_external.number().min(10).max(1000).default(200),
|
|
13635
13668
|
max_duration_minutes: exports_external.number().min(1).max(120).default(30),
|
|
13636
13669
|
max_repetitions: exports_external.number().min(3).max(50).default(10),
|
|
13637
13670
|
max_consecutive_errors: exports_external.number().min(2).max(20).default(5),
|
|
13638
|
-
warning_threshold: exports_external.number().min(0.1).max(0.9).default(0.
|
|
13671
|
+
warning_threshold: exports_external.number().min(0.1).max(0.9).default(0.75),
|
|
13639
13672
|
profiles: exports_external.record(exports_external.string(), GuardrailsProfileSchema).optional()
|
|
13640
13673
|
});
|
|
13641
13674
|
function stripKnownSwarmPrefix(name) {
|
|
@@ -13656,7 +13689,7 @@ function resolveGuardrailsConfig(base, agentName) {
|
|
|
13656
13689
|
return base;
|
|
13657
13690
|
}
|
|
13658
13691
|
const baseName = stripKnownSwarmPrefix(agentName);
|
|
13659
|
-
const builtIn = baseName
|
|
13692
|
+
const builtIn = DEFAULT_AGENT_PROFILES[baseName];
|
|
13660
13693
|
const userProfile = base.profiles?.[baseName] ?? base.profiles?.[agentName];
|
|
13661
13694
|
if (!builtIn && !userProfile) {
|
|
13662
13695
|
return base;
|
|
@@ -15974,6 +16007,7 @@ function startAgentSession(sessionId, agentName, staleDurationMs = 7200000) {
|
|
|
15974
16007
|
consecutiveErrors: 0,
|
|
15975
16008
|
recentToolCalls: [],
|
|
15976
16009
|
warningIssued: false,
|
|
16010
|
+
warningReason: "",
|
|
15977
16011
|
hardLimitHit: false
|
|
15978
16012
|
};
|
|
15979
16013
|
swarmState.agentSessions.set(sessionId, sessionState);
|
|
@@ -16291,7 +16325,7 @@ function createGuardrailsHooks(config2) {
|
|
|
16291
16325
|
resolvedMaxCalls: agentConfig.max_tool_calls,
|
|
16292
16326
|
currentCalls: session.toolCallCount
|
|
16293
16327
|
});
|
|
16294
|
-
throw new Error(`\uD83D\uDED1
|
|
16328
|
+
throw new Error(`\uD83D\uDED1 LIMIT REACHED: Tool calls exhausted (${session.toolCallCount}/${agentConfig.max_tool_calls}). Finish the current operation and return your progress summary.`);
|
|
16295
16329
|
}
|
|
16296
16330
|
if (elapsedMinutes >= agentConfig.max_duration_minutes) {
|
|
16297
16331
|
session.hardLimitHit = true;
|
|
@@ -16301,23 +16335,37 @@ function createGuardrailsHooks(config2) {
|
|
|
16301
16335
|
resolvedMaxMinutes: agentConfig.max_duration_minutes,
|
|
16302
16336
|
elapsedMinutes: Math.floor(elapsedMinutes)
|
|
16303
16337
|
});
|
|
16304
|
-
throw new Error(`\uD83D\uDED1
|
|
16338
|
+
throw new Error(`\uD83D\uDED1 LIMIT REACHED: Duration exhausted (${Math.floor(elapsedMinutes)}/${agentConfig.max_duration_minutes} min). Finish the current operation and return your progress summary.`);
|
|
16305
16339
|
}
|
|
16306
16340
|
if (repetitionCount >= agentConfig.max_repetitions) {
|
|
16307
16341
|
session.hardLimitHit = true;
|
|
16308
|
-
throw new Error(`\uD83D\uDED1
|
|
16342
|
+
throw new Error(`\uD83D\uDED1 LIMIT REACHED: Repeated the same tool call ${repetitionCount} times. This suggests a loop. Return your progress summary.`);
|
|
16309
16343
|
}
|
|
16310
16344
|
if (session.consecutiveErrors >= agentConfig.max_consecutive_errors) {
|
|
16311
16345
|
session.hardLimitHit = true;
|
|
16312
|
-
throw new Error(`\uD83D\uDED1
|
|
16346
|
+
throw new Error(`\uD83D\uDED1 LIMIT REACHED: ${session.consecutiveErrors} consecutive tool errors detected. Return your progress summary with details of what went wrong.`);
|
|
16313
16347
|
}
|
|
16314
16348
|
if (!session.warningIssued) {
|
|
16315
|
-
const
|
|
16316
|
-
const
|
|
16317
|
-
const
|
|
16318
|
-
const
|
|
16319
|
-
|
|
16349
|
+
const toolPct = session.toolCallCount / agentConfig.max_tool_calls;
|
|
16350
|
+
const durationPct = elapsedMinutes / agentConfig.max_duration_minutes;
|
|
16351
|
+
const repPct = repetitionCount / agentConfig.max_repetitions;
|
|
16352
|
+
const errorPct = session.consecutiveErrors / agentConfig.max_consecutive_errors;
|
|
16353
|
+
const reasons = [];
|
|
16354
|
+
if (toolPct >= agentConfig.warning_threshold) {
|
|
16355
|
+
reasons.push(`tool calls ${session.toolCallCount}/${agentConfig.max_tool_calls}`);
|
|
16356
|
+
}
|
|
16357
|
+
if (durationPct >= agentConfig.warning_threshold) {
|
|
16358
|
+
reasons.push(`duration ${Math.floor(elapsedMinutes)}/${agentConfig.max_duration_minutes} min`);
|
|
16359
|
+
}
|
|
16360
|
+
if (repPct >= agentConfig.warning_threshold) {
|
|
16361
|
+
reasons.push(`repetitions ${repetitionCount}/${agentConfig.max_repetitions}`);
|
|
16362
|
+
}
|
|
16363
|
+
if (errorPct >= agentConfig.warning_threshold) {
|
|
16364
|
+
reasons.push(`errors ${session.consecutiveErrors}/${agentConfig.max_consecutive_errors}`);
|
|
16365
|
+
}
|
|
16366
|
+
if (reasons.length > 0) {
|
|
16320
16367
|
session.warningIssued = true;
|
|
16368
|
+
session.warningReason = reasons.join(", ");
|
|
16321
16369
|
}
|
|
16322
16370
|
}
|
|
16323
16371
|
},
|
|
@@ -16360,11 +16408,12 @@ function createGuardrailsHooks(config2) {
|
|
|
16360
16408
|
return;
|
|
16361
16409
|
}
|
|
16362
16410
|
if (session.hardLimitHit) {
|
|
16363
|
-
textPart.text = `[\uD83D\uDED1
|
|
16411
|
+
textPart.text = `[\uD83D\uDED1 LIMIT REACHED: Your resource budget is exhausted. Do not make additional tool calls. Return a summary of your progress and any remaining work.]
|
|
16364
16412
|
|
|
16365
16413
|
` + textPart.text;
|
|
16366
16414
|
} else if (session.warningIssued) {
|
|
16367
|
-
|
|
16415
|
+
const reasonSuffix = session.warningReason ? ` (${session.warningReason})` : "";
|
|
16416
|
+
textPart.text = `[\u26A0\uFE0F APPROACHING LIMITS${reasonSuffix}: You still have capacity to finish your current step. Complete what you're working on, then return your results.]
|
|
16368
16417
|
|
|
16369
16418
|
` + textPart.text;
|
|
16370
16419
|
}
|
package/dist/state.d.ts
CHANGED
|
@@ -55,6 +55,8 @@ export interface AgentSessionState {
|
|
|
55
55
|
}>;
|
|
56
56
|
/** Whether a soft warning has been issued */
|
|
57
57
|
warningIssued: boolean;
|
|
58
|
+
/** Human-readable warning reason (set when warningIssued = true) */
|
|
59
|
+
warningReason: string;
|
|
58
60
|
/** Whether a hard limit has been triggered */
|
|
59
61
|
hardLimitHit: boolean;
|
|
60
62
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.6",
|
|
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",
|
package/dist/guardrails.js
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
// src/state.ts
|
|
2
|
-
var swarmState = {
|
|
3
|
-
activeToolCalls: new Map,
|
|
4
|
-
toolAggregates: new Map,
|
|
5
|
-
activeAgent: new Map,
|
|
6
|
-
delegationChains: new Map,
|
|
7
|
-
pendingEvents: 0,
|
|
8
|
-
agentSessions: new Map
|
|
9
|
-
};
|
|
10
|
-
function startAgentSession(sessionId, agentName, staleDurationMs = 3600000) {
|
|
11
|
-
const now = Date.now();
|
|
12
|
-
for (const [id, session] of swarmState.agentSessions) {
|
|
13
|
-
if (now - session.startTime > staleDurationMs) {
|
|
14
|
-
swarmState.agentSessions.delete(id);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
const sessionState = {
|
|
18
|
-
agentName,
|
|
19
|
-
startTime: now,
|
|
20
|
-
toolCallCount: 0,
|
|
21
|
-
consecutiveErrors: 0,
|
|
22
|
-
recentToolCalls: [],
|
|
23
|
-
warningIssued: false,
|
|
24
|
-
hardLimitHit: false
|
|
25
|
-
};
|
|
26
|
-
swarmState.agentSessions.set(sessionId, sessionState);
|
|
27
|
-
}
|
|
28
|
-
function getAgentSession(sessionId) {
|
|
29
|
-
return swarmState.agentSessions.get(sessionId);
|
|
30
|
-
}
|
|
31
|
-
// src/utils/logger.ts
|
|
32
|
-
var DEBUG = process.env.OPENCODE_SWARM_DEBUG === "1";
|
|
33
|
-
function warn(message, data) {
|
|
34
|
-
const timestamp = new Date().toISOString();
|
|
35
|
-
if (data !== undefined) {
|
|
36
|
-
console.warn(`[opencode-swarm ${timestamp}] WARN: ${message}`, data);
|
|
37
|
-
} else {
|
|
38
|
-
console.warn(`[opencode-swarm ${timestamp}] WARN: ${message}`);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
// src/hooks/guardrails.ts
|
|
42
|
-
function createGuardrailsHooks(config) {
|
|
43
|
-
if (config.enabled === false) {
|
|
44
|
-
return {
|
|
45
|
-
toolBefore: async () => {},
|
|
46
|
-
toolAfter: async () => {},
|
|
47
|
-
messagesTransform: async () => {}
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
return {
|
|
51
|
-
toolBefore: async (input, output) => {
|
|
52
|
-
let session = getAgentSession(input.sessionID);
|
|
53
|
-
if (!session) {
|
|
54
|
-
startAgentSession(input.sessionID, "unknown");
|
|
55
|
-
session = getAgentSession(input.sessionID);
|
|
56
|
-
if (!session) {
|
|
57
|
-
warn(`Failed to create session for ${input.sessionID}`);
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (session.hardLimitHit) {
|
|
62
|
-
throw new Error("\uD83D\uDED1 CIRCUIT BREAKER: Agent blocked. Hard limit was previously triggered. Stop making tool calls and return your progress summary.");
|
|
63
|
-
}
|
|
64
|
-
session.toolCallCount++;
|
|
65
|
-
const hash = hashArgs(output.args);
|
|
66
|
-
session.recentToolCalls.push({
|
|
67
|
-
tool: input.tool,
|
|
68
|
-
argsHash: hash,
|
|
69
|
-
timestamp: Date.now()
|
|
70
|
-
});
|
|
71
|
-
if (session.recentToolCalls.length > 20) {
|
|
72
|
-
session.recentToolCalls.shift();
|
|
73
|
-
}
|
|
74
|
-
let repetitionCount = 0;
|
|
75
|
-
if (session.recentToolCalls.length > 0) {
|
|
76
|
-
const lastEntry = session.recentToolCalls[session.recentToolCalls.length - 1];
|
|
77
|
-
for (let i = session.recentToolCalls.length - 1;i >= 0; i--) {
|
|
78
|
-
const entry = session.recentToolCalls[i];
|
|
79
|
-
if (entry.tool === lastEntry.tool && entry.argsHash === lastEntry.argsHash) {
|
|
80
|
-
repetitionCount++;
|
|
81
|
-
} else {
|
|
82
|
-
break;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
const elapsedMinutes = (Date.now() - session.startTime) / 60000;
|
|
87
|
-
if (session.toolCallCount >= config.max_tool_calls) {
|
|
88
|
-
session.hardLimitHit = true;
|
|
89
|
-
throw new Error(`\uD83D\uDED1 CIRCUIT BREAKER: Tool call limit reached (${session.toolCallCount}/${config.max_tool_calls}). Stop making tool calls and return your progress summary.`);
|
|
90
|
-
}
|
|
91
|
-
if (elapsedMinutes >= config.max_duration_minutes) {
|
|
92
|
-
session.hardLimitHit = true;
|
|
93
|
-
throw new Error(`\uD83D\uDED1 CIRCUIT BREAKER: Duration limit reached (${Math.floor(elapsedMinutes)} min). Stop making tool calls and return your progress summary.`);
|
|
94
|
-
}
|
|
95
|
-
if (repetitionCount >= config.max_repetitions) {
|
|
96
|
-
session.hardLimitHit = true;
|
|
97
|
-
throw new Error(`\uD83D\uDED1 CIRCUIT BREAKER: Repetition detected (same call ${repetitionCount} times). Stop making tool calls and return your progress summary.`);
|
|
98
|
-
}
|
|
99
|
-
if (session.consecutiveErrors >= config.max_consecutive_errors) {
|
|
100
|
-
session.hardLimitHit = true;
|
|
101
|
-
throw new Error(`\uD83D\uDED1 CIRCUIT BREAKER: Too many consecutive errors (${session.consecutiveErrors}). Stop making tool calls and return your progress summary.`);
|
|
102
|
-
}
|
|
103
|
-
if (!session.warningIssued) {
|
|
104
|
-
const toolWarning = session.toolCallCount >= config.max_tool_calls * config.warning_threshold;
|
|
105
|
-
const durationWarning = elapsedMinutes >= config.max_duration_minutes * config.warning_threshold;
|
|
106
|
-
const repetitionWarning = repetitionCount >= config.max_repetitions * config.warning_threshold;
|
|
107
|
-
const errorWarning = session.consecutiveErrors >= config.max_consecutive_errors * config.warning_threshold;
|
|
108
|
-
if (toolWarning || durationWarning || repetitionWarning || errorWarning) {
|
|
109
|
-
session.warningIssued = true;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
},
|
|
113
|
-
toolAfter: async (input, output) => {
|
|
114
|
-
const session = getAgentSession(input.sessionID);
|
|
115
|
-
if (!session) {
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
const outputStr = String(output.output ?? "");
|
|
119
|
-
const hasError = output.output === null || output.output === undefined || outputStr === "" || outputStr.toLowerCase().includes("error");
|
|
120
|
-
if (hasError) {
|
|
121
|
-
session.consecutiveErrors++;
|
|
122
|
-
} else {
|
|
123
|
-
session.consecutiveErrors = 0;
|
|
124
|
-
}
|
|
125
|
-
},
|
|
126
|
-
messagesTransform: async (input, output) => {
|
|
127
|
-
const messages = output.messages;
|
|
128
|
-
if (!messages || messages.length === 0) {
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
const lastMessage = messages[messages.length - 1];
|
|
132
|
-
let sessionId = lastMessage.info?.sessionID;
|
|
133
|
-
if (!sessionId) {
|
|
134
|
-
for (const [id, session2] of swarmState.agentSessions) {
|
|
135
|
-
if (session2.warningIssued || session2.hardLimitHit) {
|
|
136
|
-
sessionId = id;
|
|
137
|
-
break;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
if (!sessionId) {
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
const session = getAgentSession(sessionId);
|
|
145
|
-
if (!session || !session.warningIssued && !session.hardLimitHit) {
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
const textPart = lastMessage.parts.find((part) => part.type === "text" && typeof part.text === "string");
|
|
149
|
-
if (!textPart) {
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
if (session.hardLimitHit) {
|
|
153
|
-
textPart.text = `[\uD83D\uDED1 CIRCUIT BREAKER ACTIVE: You have exceeded your resource limits. Do NOT make any more tool calls. Immediately return a summary of your progress so far. Any further tool calls will be blocked.]
|
|
154
|
-
|
|
155
|
-
` + textPart.text;
|
|
156
|
-
} else if (session.warningIssued) {
|
|
157
|
-
textPart.text = `[⚠️ GUARDRAIL WARNING: You are approaching resource limits. Please wrap up your current task efficiently. Avoid unnecessary tool calls and prepare to return your results soon.]
|
|
158
|
-
|
|
159
|
-
` + textPart.text;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
function hashArgs(args) {
|
|
165
|
-
try {
|
|
166
|
-
if (typeof args !== "object" || args === null) {
|
|
167
|
-
return 0;
|
|
168
|
-
}
|
|
169
|
-
const sortedKeys = Object.keys(args).sort();
|
|
170
|
-
return Number(Bun.hash(JSON.stringify(args, sortedKeys)));
|
|
171
|
-
} catch {
|
|
172
|
-
return 0;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
export {
|
|
176
|
-
hashArgs,
|
|
177
|
-
createGuardrailsHooks
|
|
178
|
-
};
|
package/dist/state.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
// src/state.ts
|
|
2
|
-
var swarmState = {
|
|
3
|
-
activeToolCalls: new Map,
|
|
4
|
-
toolAggregates: new Map,
|
|
5
|
-
activeAgent: new Map,
|
|
6
|
-
delegationChains: new Map,
|
|
7
|
-
pendingEvents: 0,
|
|
8
|
-
agentSessions: new Map
|
|
9
|
-
};
|
|
10
|
-
function resetSwarmState() {
|
|
11
|
-
swarmState.activeToolCalls.clear();
|
|
12
|
-
swarmState.toolAggregates.clear();
|
|
13
|
-
swarmState.activeAgent.clear();
|
|
14
|
-
swarmState.delegationChains.clear();
|
|
15
|
-
swarmState.pendingEvents = 0;
|
|
16
|
-
swarmState.agentSessions.clear();
|
|
17
|
-
}
|
|
18
|
-
function startAgentSession(sessionId, agentName, staleDurationMs = 3600000) {
|
|
19
|
-
const now = Date.now();
|
|
20
|
-
for (const [id, session] of swarmState.agentSessions) {
|
|
21
|
-
if (now - session.startTime > staleDurationMs) {
|
|
22
|
-
swarmState.agentSessions.delete(id);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
const sessionState = {
|
|
26
|
-
agentName,
|
|
27
|
-
startTime: now,
|
|
28
|
-
toolCallCount: 0,
|
|
29
|
-
consecutiveErrors: 0,
|
|
30
|
-
recentToolCalls: [],
|
|
31
|
-
warningIssued: false,
|
|
32
|
-
hardLimitHit: false
|
|
33
|
-
};
|
|
34
|
-
swarmState.agentSessions.set(sessionId, sessionState);
|
|
35
|
-
}
|
|
36
|
-
function endAgentSession(sessionId) {
|
|
37
|
-
swarmState.agentSessions.delete(sessionId);
|
|
38
|
-
}
|
|
39
|
-
function getAgentSession(sessionId) {
|
|
40
|
-
return swarmState.agentSessions.get(sessionId);
|
|
41
|
-
}
|
|
42
|
-
export {
|
|
43
|
-
swarmState,
|
|
44
|
-
startAgentSession,
|
|
45
|
-
resetSwarmState,
|
|
46
|
-
getAgentSession,
|
|
47
|
-
endAgentSession
|
|
48
|
-
};
|