opencode-swarm 5.1.0 → 5.1.1
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 +4 -0
- package/dist/hooks/delegation-gate.d.ts +29 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/index.js +75 -2
- package/package.json +1 -1
package/dist/config/schema.d.ts
CHANGED
|
@@ -20,6 +20,8 @@ export declare const HooksConfigSchema: z.ZodObject<{
|
|
|
20
20
|
agent_activity: z.ZodDefault<z.ZodBoolean>;
|
|
21
21
|
delegation_tracker: z.ZodDefault<z.ZodBoolean>;
|
|
22
22
|
agent_awareness_max_chars: z.ZodDefault<z.ZodNumber>;
|
|
23
|
+
delegation_gate: z.ZodDefault<z.ZodBoolean>;
|
|
24
|
+
delegation_max_chars: z.ZodDefault<z.ZodNumber>;
|
|
23
25
|
}, z.core.$strip>;
|
|
24
26
|
export type HooksConfig = z.infer<typeof HooksConfigSchema>;
|
|
25
27
|
export declare const ScoringWeightsSchema: z.ZodObject<{
|
|
@@ -200,6 +202,8 @@ export declare const PluginConfigSchema: z.ZodObject<{
|
|
|
200
202
|
agent_activity: z.ZodDefault<z.ZodBoolean>;
|
|
201
203
|
delegation_tracker: z.ZodDefault<z.ZodBoolean>;
|
|
202
204
|
agent_awareness_max_chars: z.ZodDefault<z.ZodNumber>;
|
|
205
|
+
delegation_gate: z.ZodDefault<z.ZodBoolean>;
|
|
206
|
+
delegation_max_chars: z.ZodDefault<z.ZodNumber>;
|
|
203
207
|
}, z.core.$strip>>;
|
|
204
208
|
context_budget: z.ZodOptional<z.ZodObject<{
|
|
205
209
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delegation Gate Hook
|
|
3
|
+
*
|
|
4
|
+
* Warns the architect when coder delegations are too large or batched.
|
|
5
|
+
* Uses experimental.chat.messages.transform to provide non-blocking guidance.
|
|
6
|
+
*/
|
|
7
|
+
import type { PluginConfig } from '../config';
|
|
8
|
+
interface MessageInfo {
|
|
9
|
+
role: string;
|
|
10
|
+
agent?: string;
|
|
11
|
+
sessionID?: string;
|
|
12
|
+
}
|
|
13
|
+
interface MessagePart {
|
|
14
|
+
type: string;
|
|
15
|
+
text?: string;
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
}
|
|
18
|
+
interface MessageWithParts {
|
|
19
|
+
info: MessageInfo;
|
|
20
|
+
parts: MessagePart[];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Creates the experimental.chat.messages.transform hook for delegation gating.
|
|
24
|
+
* Inspects coder delegations and warns when tasks are oversized or batched.
|
|
25
|
+
*/
|
|
26
|
+
export declare function createDelegationGateHook(config: PluginConfig): (input: Record<string, never>, output: {
|
|
27
|
+
messages?: MessageWithParts[];
|
|
28
|
+
}) => Promise<void>;
|
|
29
|
+
export {};
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { createAgentActivityHooks } from './agent-activity';
|
|
|
2
2
|
export { createCompactionCustomizerHook } from './compaction-customizer';
|
|
3
3
|
export { createContextBudgetHandler } from './context-budget';
|
|
4
4
|
export { createDelegationTrackerHook } from './delegation-tracker';
|
|
5
|
+
export { createDelegationGateHook } from './delegation-gate';
|
|
5
6
|
export { extractCurrentPhase, extractCurrentPhaseFromPlan, extractCurrentTask, extractCurrentTaskFromPlan, extractDecisions, extractIncompleteTasks, extractIncompleteTasksFromPlan, extractPatterns, } from './extractors';
|
|
6
7
|
export { createGuardrailsHooks } from './guardrails';
|
|
7
8
|
export { createPipelineTrackerHook } from './pipeline-tracker';
|
package/dist/index.js
CHANGED
|
@@ -13578,7 +13578,9 @@ var HooksConfigSchema = exports_external.object({
|
|
|
13578
13578
|
compaction: exports_external.boolean().default(true),
|
|
13579
13579
|
agent_activity: exports_external.boolean().default(true),
|
|
13580
13580
|
delegation_tracker: exports_external.boolean().default(false),
|
|
13581
|
-
agent_awareness_max_chars: exports_external.number().min(50).max(2000).default(300)
|
|
13581
|
+
agent_awareness_max_chars: exports_external.number().min(50).max(2000).default(300),
|
|
13582
|
+
delegation_gate: exports_external.boolean().default(true),
|
|
13583
|
+
delegation_max_chars: exports_external.number().min(500).max(20000).default(4000)
|
|
13582
13584
|
});
|
|
13583
13585
|
var ScoringWeightsSchema = exports_external.object({
|
|
13584
13586
|
phase: exports_external.number().min(0).max(5).default(1),
|
|
@@ -16350,6 +16352,70 @@ function createDelegationTrackerHook(config2) {
|
|
|
16350
16352
|
}
|
|
16351
16353
|
};
|
|
16352
16354
|
}
|
|
16355
|
+
// src/hooks/delegation-gate.ts
|
|
16356
|
+
function createDelegationGateHook(config2) {
|
|
16357
|
+
const enabled = config2.hooks?.delegation_gate !== false;
|
|
16358
|
+
const delegationMaxChars = config2.hooks?.delegation_max_chars ?? 4000;
|
|
16359
|
+
if (!enabled) {
|
|
16360
|
+
return async (_input, _output) => {};
|
|
16361
|
+
}
|
|
16362
|
+
return async (_input, output) => {
|
|
16363
|
+
const messages = output?.messages;
|
|
16364
|
+
if (!messages || messages.length === 0)
|
|
16365
|
+
return;
|
|
16366
|
+
let lastUserMessageIndex = -1;
|
|
16367
|
+
for (let i = messages.length - 1;i >= 0; i--) {
|
|
16368
|
+
if (messages[i]?.info?.role === "user") {
|
|
16369
|
+
lastUserMessageIndex = i;
|
|
16370
|
+
break;
|
|
16371
|
+
}
|
|
16372
|
+
}
|
|
16373
|
+
if (lastUserMessageIndex === -1)
|
|
16374
|
+
return;
|
|
16375
|
+
const lastUserMessage = messages[lastUserMessageIndex];
|
|
16376
|
+
if (!lastUserMessage?.parts)
|
|
16377
|
+
return;
|
|
16378
|
+
const agent = lastUserMessage.info?.agent;
|
|
16379
|
+
const strippedAgent = agent ? stripKnownSwarmPrefix(agent) : undefined;
|
|
16380
|
+
if (strippedAgent && strippedAgent !== "architect")
|
|
16381
|
+
return;
|
|
16382
|
+
const textPartIndex = lastUserMessage.parts.findIndex((p) => p?.type === "text" && p.text !== undefined);
|
|
16383
|
+
if (textPartIndex === -1)
|
|
16384
|
+
return;
|
|
16385
|
+
const textPart = lastUserMessage.parts[textPartIndex];
|
|
16386
|
+
const text = textPart.text ?? "";
|
|
16387
|
+
const coderDelegationPattern = /(?:^|\n)\s*(?:\w+_)?coder\s*\n\s*TASK:/i;
|
|
16388
|
+
if (!coderDelegationPattern.test(text))
|
|
16389
|
+
return;
|
|
16390
|
+
const warnings = [];
|
|
16391
|
+
if (text.length > delegationMaxChars) {
|
|
16392
|
+
warnings.push(`Delegation exceeds recommended size (${text.length} chars, limit ${delegationMaxChars}). Consider splitting into smaller tasks.`);
|
|
16393
|
+
}
|
|
16394
|
+
const fileMatches = text.match(/^FILE:/gm);
|
|
16395
|
+
if (fileMatches && fileMatches.length > 1) {
|
|
16396
|
+
warnings.push(`Multiple FILE: directives detected (${fileMatches.length}). Each coder task should target ONE file.`);
|
|
16397
|
+
}
|
|
16398
|
+
const taskMatches = text.match(/^TASK:/gm);
|
|
16399
|
+
if (taskMatches && taskMatches.length > 1) {
|
|
16400
|
+
warnings.push(`Multiple TASK: sections detected (${taskMatches.length}). Send ONE task per coder call.`);
|
|
16401
|
+
}
|
|
16402
|
+
const batchingPattern = /\b(?:and also|then also|additionally|as well as|along with)\b/gi;
|
|
16403
|
+
const batchingMatches = text.match(batchingPattern);
|
|
16404
|
+
if (batchingMatches && batchingMatches.length > 0) {
|
|
16405
|
+
warnings.push("Batching language detected. Break compound objectives into separate coder calls.");
|
|
16406
|
+
}
|
|
16407
|
+
if (warnings.length === 0)
|
|
16408
|
+
return;
|
|
16409
|
+
const warningText = `[\u26A0\uFE0F DELEGATION GATE: Your coder delegation may be too complex. Issues:
|
|
16410
|
+
${warnings.join(`
|
|
16411
|
+
`)}
|
|
16412
|
+
Split into smaller, atomic tasks for better results.]`;
|
|
16413
|
+
const originalText = textPart.text ?? "";
|
|
16414
|
+
textPart.text = `${warningText}
|
|
16415
|
+
|
|
16416
|
+
${originalText}`;
|
|
16417
|
+
};
|
|
16418
|
+
}
|
|
16353
16419
|
// src/hooks/guardrails.ts
|
|
16354
16420
|
function createGuardrailsHooks(config2) {
|
|
16355
16421
|
if (config2.enabled === false) {
|
|
@@ -16361,6 +16427,11 @@ function createGuardrailsHooks(config2) {
|
|
|
16361
16427
|
}
|
|
16362
16428
|
return {
|
|
16363
16429
|
toolBefore: async (input, output) => {
|
|
16430
|
+
const rawActiveAgent = swarmState.activeAgent.get(input.sessionID);
|
|
16431
|
+
const strippedAgent = rawActiveAgent ? stripKnownSwarmPrefix(rawActiveAgent) : undefined;
|
|
16432
|
+
if (strippedAgent === ORCHESTRATOR_NAME) {
|
|
16433
|
+
return;
|
|
16434
|
+
}
|
|
16364
16435
|
const agentName = swarmState.activeAgent.get(input.sessionID);
|
|
16365
16436
|
const session = ensureAgentSession(input.sessionID, agentName);
|
|
16366
16437
|
const agentConfig = resolveGuardrailsConfig(config2, session.agentName);
|
|
@@ -29522,6 +29593,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
29522
29593
|
const commandHandler = createSwarmCommandHandler(ctx.directory, Object.fromEntries(agentDefinitions.map((agent) => [agent.name, agent])));
|
|
29523
29594
|
const activityHooks = createAgentActivityHooks(config3, ctx.directory);
|
|
29524
29595
|
const delegationHandler = createDelegationTrackerHook(config3);
|
|
29596
|
+
const delegationGateHandler = createDelegationGateHook(config3);
|
|
29525
29597
|
const guardrailsConfig = GuardrailsConfigSchema.parse(config3.guardrails ?? {});
|
|
29526
29598
|
const guardrailsHooks = createGuardrailsHooks(guardrailsConfig);
|
|
29527
29599
|
log("Plugin initialized", {
|
|
@@ -29569,7 +29641,8 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
29569
29641
|
"experimental.chat.messages.transform": composeHandlers(...[
|
|
29570
29642
|
pipelineHook["experimental.chat.messages.transform"],
|
|
29571
29643
|
contextBudgetHandler,
|
|
29572
|
-
guardrailsHooks.messagesTransform
|
|
29644
|
+
guardrailsHooks.messagesTransform,
|
|
29645
|
+
delegationGateHandler
|
|
29573
29646
|
].filter((fn) => Boolean(fn))),
|
|
29574
29647
|
"experimental.chat.system.transform": systemEnhancerHook["experimental.chat.system.transform"],
|
|
29575
29648
|
"experimental.session.compacting": compactionHook["experimental.session.compacting"],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.1",
|
|
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",
|