opencode-swarm 5.1.5 → 5.1.7
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 +5 -0
- package/dist/index.js +43 -9
- package/dist/state.d.ts +8 -0
- package/package.json +1 -1
package/dist/config/schema.d.ts
CHANGED
|
@@ -170,7 +170,12 @@ export type GuardrailsConfig = z.infer<typeof GuardrailsConfigSchema>;
|
|
|
170
170
|
* Works with any swarm name by checking if the name (or suffix after removing
|
|
171
171
|
* a prefix) matches a known agent name from ALL_AGENT_NAMES.
|
|
172
172
|
*
|
|
173
|
+
* Normalization handles:
|
|
174
|
+
* - Case-insensitive matching (e.g., "PAID_ARCHITECT" → "architect")
|
|
175
|
+
* - Multiple separators: underscore, hyphen, space (e.g., "paid-architect", "paid architect")
|
|
176
|
+
*
|
|
173
177
|
* Examples: 'local_architect' → 'architect', 'enterprise_coder' → 'coder',
|
|
178
|
+
* 'paid-architect' → 'architect', 'PAID_ARCHITECT' → 'architect',
|
|
174
179
|
* 'architect' → 'architect', 'unknown_thing' → 'unknown_thing'
|
|
175
180
|
*
|
|
176
181
|
* @param name - The agent name (possibly prefixed)
|
package/dist/index.js
CHANGED
|
@@ -13687,14 +13687,20 @@ var GuardrailsConfigSchema = exports_external.object({
|
|
|
13687
13687
|
idle_timeout_minutes: exports_external.number().min(5).max(240).default(60),
|
|
13688
13688
|
profiles: exports_external.record(exports_external.string(), GuardrailsProfileSchema).optional()
|
|
13689
13689
|
});
|
|
13690
|
+
function normalizeAgentName(name) {
|
|
13691
|
+
return name.toLowerCase().replace(/[-\s]+/g, "_");
|
|
13692
|
+
}
|
|
13690
13693
|
function stripKnownSwarmPrefix(name) {
|
|
13691
13694
|
if (!name)
|
|
13692
13695
|
return name;
|
|
13693
13696
|
if (ALL_AGENT_NAMES.includes(name))
|
|
13694
13697
|
return name;
|
|
13698
|
+
const normalized = normalizeAgentName(name);
|
|
13695
13699
|
for (const agentName of ALL_AGENT_NAMES) {
|
|
13696
|
-
const
|
|
13697
|
-
if (
|
|
13700
|
+
const normalizedAgent = normalizeAgentName(agentName);
|
|
13701
|
+
if (normalized === normalizedAgent)
|
|
13702
|
+
return agentName;
|
|
13703
|
+
if (normalized.endsWith("_" + normalizedAgent)) {
|
|
13698
13704
|
return agentName;
|
|
13699
13705
|
}
|
|
13700
13706
|
}
|
|
@@ -13706,9 +13712,8 @@ function resolveGuardrailsConfig(base, agentName) {
|
|
|
13706
13712
|
}
|
|
13707
13713
|
const baseName = stripKnownSwarmPrefix(agentName);
|
|
13708
13714
|
const builtInLookup = DEFAULT_AGENT_PROFILES[baseName];
|
|
13709
|
-
const
|
|
13710
|
-
const
|
|
13711
|
-
const userProfile = base.profiles?.[effectiveName] ?? base.profiles?.[baseName] ?? base.profiles?.[agentName];
|
|
13715
|
+
const builtIn = builtInLookup;
|
|
13716
|
+
const userProfile = base.profiles?.[baseName] ?? base.profiles?.[agentName];
|
|
13712
13717
|
if (!builtIn && !userProfile) {
|
|
13713
13718
|
return base;
|
|
13714
13719
|
}
|
|
@@ -15046,6 +15051,7 @@ function startAgentSession(sessionId, agentName, staleDurationMs = 7200000) {
|
|
|
15046
15051
|
agentName,
|
|
15047
15052
|
startTime: now,
|
|
15048
15053
|
lastToolCallTime: now,
|
|
15054
|
+
lastAgentEventTime: now,
|
|
15049
15055
|
toolCallCount: 0,
|
|
15050
15056
|
consecutiveErrors: 0,
|
|
15051
15057
|
recentToolCalls: [],
|
|
@@ -15075,6 +15081,7 @@ function ensureAgentSession(sessionId, agentName) {
|
|
|
15075
15081
|
session.hardLimitHit = false;
|
|
15076
15082
|
session.lastSuccessTime = now;
|
|
15077
15083
|
session.delegationActive = false;
|
|
15084
|
+
session.lastAgentEventTime = now;
|
|
15078
15085
|
}
|
|
15079
15086
|
session.lastToolCallTime = now;
|
|
15080
15087
|
return session;
|
|
@@ -15086,6 +15093,12 @@ function ensureAgentSession(sessionId, agentName) {
|
|
|
15086
15093
|
}
|
|
15087
15094
|
return session;
|
|
15088
15095
|
}
|
|
15096
|
+
function updateAgentEventTime(sessionId) {
|
|
15097
|
+
const session = swarmState.agentSessions.get(sessionId);
|
|
15098
|
+
if (session) {
|
|
15099
|
+
session.lastAgentEventTime = Date.now();
|
|
15100
|
+
}
|
|
15101
|
+
}
|
|
15089
15102
|
|
|
15090
15103
|
// src/commands/benchmark.ts
|
|
15091
15104
|
var CI = {
|
|
@@ -16733,6 +16746,7 @@ ${originalText}`;
|
|
|
16733
16746
|
// src/hooks/delegation-tracker.ts
|
|
16734
16747
|
function createDelegationTrackerHook(config2) {
|
|
16735
16748
|
return async (input, _output) => {
|
|
16749
|
+
const now = Date.now();
|
|
16736
16750
|
if (!input.agent || input.agent === "") {
|
|
16737
16751
|
const session2 = swarmState.agentSessions.get(input.sessionID);
|
|
16738
16752
|
if (session2) {
|
|
@@ -16740,18 +16754,21 @@ function createDelegationTrackerHook(config2) {
|
|
|
16740
16754
|
}
|
|
16741
16755
|
swarmState.activeAgent.set(input.sessionID, ORCHESTRATOR_NAME);
|
|
16742
16756
|
ensureAgentSession(input.sessionID, ORCHESTRATOR_NAME);
|
|
16757
|
+
updateAgentEventTime(input.sessionID);
|
|
16743
16758
|
return;
|
|
16744
16759
|
}
|
|
16745
16760
|
const agentName = input.agent;
|
|
16746
16761
|
const previousAgent = swarmState.activeAgent.get(input.sessionID);
|
|
16747
16762
|
swarmState.activeAgent.set(input.sessionID, agentName);
|
|
16763
|
+
const strippedAgent = stripKnownSwarmPrefix(agentName);
|
|
16764
|
+
const isArchitect = strippedAgent === ORCHESTRATOR_NAME;
|
|
16748
16765
|
const session = ensureAgentSession(input.sessionID, agentName);
|
|
16749
|
-
session.delegationActive =
|
|
16766
|
+
session.delegationActive = !isArchitect;
|
|
16750
16767
|
if (config2.hooks?.delegation_tracker === true && previousAgent && previousAgent !== agentName) {
|
|
16751
16768
|
const entry = {
|
|
16752
16769
|
from: previousAgent,
|
|
16753
16770
|
to: agentName,
|
|
16754
|
-
timestamp:
|
|
16771
|
+
timestamp: now
|
|
16755
16772
|
};
|
|
16756
16773
|
if (!swarmState.delegationChains.has(input.sessionID)) {
|
|
16757
16774
|
swarmState.delegationChains.set(input.sessionID, []);
|
|
@@ -16792,6 +16809,9 @@ function createGuardrailsHooks(config2) {
|
|
|
16792
16809
|
return;
|
|
16793
16810
|
}
|
|
16794
16811
|
const agentConfig = resolveGuardrailsConfig(config2, session.agentName);
|
|
16812
|
+
if (agentConfig.max_duration_minutes === 0 && agentConfig.max_tool_calls === 0) {
|
|
16813
|
+
return;
|
|
16814
|
+
}
|
|
16795
16815
|
if (session.hardLimitHit) {
|
|
16796
16816
|
throw new Error("\uD83D\uDED1 CIRCUIT BREAKER: Agent blocked. Hard limit was previously triggered. Stop making tool calls and return your progress summary.");
|
|
16797
16817
|
}
|
|
@@ -30165,7 +30185,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
30165
30185
|
if (session && activeAgent && activeAgent !== ORCHESTRATOR_NAME) {
|
|
30166
30186
|
const stripActive = stripKnownSwarmPrefix(activeAgent);
|
|
30167
30187
|
if (stripActive !== ORCHESTRATOR_NAME) {
|
|
30168
|
-
const staleDelegation = !session.delegationActive || Date.now() - session.
|
|
30188
|
+
const staleDelegation = !session.delegationActive || Date.now() - session.lastAgentEventTime > 1e4;
|
|
30169
30189
|
if (staleDelegation) {
|
|
30170
30190
|
swarmState.activeAgent.set(input.sessionID, ORCHESTRATOR_NAME);
|
|
30171
30191
|
ensureAgentSession(input.sessionID, ORCHESTRATOR_NAME);
|
|
@@ -30175,7 +30195,21 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
30175
30195
|
await guardrailsHooks.toolBefore(input, output);
|
|
30176
30196
|
await safeHook(activityHooks.toolBefore)(input, output);
|
|
30177
30197
|
},
|
|
30178
|
-
"tool.execute.after":
|
|
30198
|
+
"tool.execute.after": async (input, output) => {
|
|
30199
|
+
await activityHooks.toolAfter(input, output);
|
|
30200
|
+
await guardrailsHooks.toolAfter(input, output);
|
|
30201
|
+
await toolSummarizerHook?.(input, output);
|
|
30202
|
+
if (input.tool === "task") {
|
|
30203
|
+
const sessionId = input.sessionID;
|
|
30204
|
+
swarmState.activeAgent.set(sessionId, ORCHESTRATOR_NAME);
|
|
30205
|
+
ensureAgentSession(sessionId, ORCHESTRATOR_NAME);
|
|
30206
|
+
const session = swarmState.agentSessions.get(sessionId);
|
|
30207
|
+
if (session) {
|
|
30208
|
+
session.delegationActive = false;
|
|
30209
|
+
session.lastAgentEventTime = Date.now();
|
|
30210
|
+
}
|
|
30211
|
+
}
|
|
30212
|
+
},
|
|
30179
30213
|
"chat.message": safeHook(delegationHandler)
|
|
30180
30214
|
};
|
|
30181
30215
|
};
|
package/dist/state.d.ts
CHANGED
|
@@ -43,6 +43,8 @@ export interface AgentSessionState {
|
|
|
43
43
|
startTime: number;
|
|
44
44
|
/** Timestamp of most recent tool call (for stale session eviction) */
|
|
45
45
|
lastToolCallTime: number;
|
|
46
|
+
/** Timestamp of most recent agent identity event (chat.message sets/changes identity) */
|
|
47
|
+
lastAgentEventTime: number;
|
|
46
48
|
/** Total tool calls in this session */
|
|
47
49
|
toolCallCount: number;
|
|
48
50
|
/** Consecutive errors (reset on success) */
|
|
@@ -114,3 +116,9 @@ export declare function getAgentSession(sessionId: string): AgentSessionState |
|
|
|
114
116
|
* @returns The AgentSessionState
|
|
115
117
|
*/
|
|
116
118
|
export declare function ensureAgentSession(sessionId: string, agentName?: string): AgentSessionState;
|
|
119
|
+
/**
|
|
120
|
+
* Update only the agent event timestamp (for stale detection).
|
|
121
|
+
* Does NOT change agent name or reset guardrail state.
|
|
122
|
+
* @param sessionId - The session identifier
|
|
123
|
+
*/
|
|
124
|
+
export declare function updateAgentEventTime(sessionId: string): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.7",
|
|
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",
|