opencode-swarm 6.42.1 → 6.43.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/agents/curator-agent.d.ts +14 -0
- package/dist/agents/explorer.d.ts +2 -0
- package/dist/agents/index.d.ts +1 -0
- package/dist/cli/index.js +7 -1
- package/dist/config/constants.d.ts +2 -2
- package/dist/hooks/curator-llm-factory.d.ts +11 -2
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/phase-monitor.d.ts +7 -1
- package/dist/index.js +342 -255
- package/dist/state.d.ts +7 -0
- package/package.json +1 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AgentDefinition } from './architect';
|
|
2
|
+
export type CuratorRole = 'curator_init' | 'curator_phase';
|
|
3
|
+
/**
|
|
4
|
+
* Create a Curator agent definition for the given role.
|
|
5
|
+
*
|
|
6
|
+
* Follows the same pattern as createCriticAgent:
|
|
7
|
+
* - Two named variants: curator_init and curator_phase
|
|
8
|
+
* - Each carries its own baked-in system prompt so the correct agent is
|
|
9
|
+
* resolved by name in any swarm (default or prefixed)
|
|
10
|
+
* - customPrompt replaces the default prompt entirely; customAppendPrompt
|
|
11
|
+
* appends to the role-specific default (same semantics as createCriticAgent)
|
|
12
|
+
* - Read-only tool config: write/edit/patch all false
|
|
13
|
+
*/
|
|
14
|
+
export declare function createCuratorAgent(model: string, customPrompt?: string, customAppendPrompt?: string, role?: CuratorRole): AgentDefinition;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { AgentDefinition } from './architect';
|
|
2
|
+
export declare const CURATOR_INIT_PROMPT = "## IDENTITY\nYou are Explorer in CURATOR_INIT mode. You consolidate prior session knowledge into an architect briefing.\nDO NOT use the Task tool to delegate. You ARE the agent that does the work.\n\nINPUT FORMAT:\nTASK: CURATOR_INIT\nPRIOR_SUMMARY: [JSON or \"none\"]\nKNOWLEDGE_ENTRIES: [JSON array of high-confidence entries]\nPROJECT_CONTEXT: [context.md excerpt]\n\nACTIONS:\n- Read the prior summary to understand session history\n- Cross-reference knowledge entries against project context\n- Identify contradictions (knowledge says X, project state shows Y)\n- Produce a concise briefing for the architect\n\nRULES:\n- Output under 2000 chars\n- No code modifications\n- Flag contradictions explicitly with CONTRADICTION: prefix\n- If no prior summary exists, state \"First session \u2014 no prior context\"\n\nOUTPUT FORMAT:\nBRIEFING:\n[concise summary of prior session state, key decisions, active blockers]\n\nCONTRADICTIONS:\n- [entry_id]: [description] (or \"None detected\")\n\nKNOWLEDGE_STATS:\n- Entries reviewed: [N]\n- Prior phases covered: [N]\n";
|
|
3
|
+
export declare const CURATOR_PHASE_PROMPT = "## IDENTITY\nYou are Explorer in CURATOR_PHASE mode. You consolidate a completed phase into a digest.\nDO NOT use the Task tool to delegate. You ARE the agent that does the work.\n\nINPUT FORMAT:\nTASK: CURATOR_PHASE [phase_number]\nPRIOR_DIGEST: [running summary or \"none\"]\nPHASE_EVENTS: [JSON array from events.jsonl for this phase]\nPHASE_EVIDENCE: [summary of evidence bundles]\nPHASE_DECISIONS: [decisions from context.md]\nAGENTS_DISPATCHED: [list]\nAGENTS_EXPECTED: [list from config]\n\nACTIONS:\n- Extend the prior digest with this phase's outcomes (do NOT regenerate from scratch)\n- Identify workflow deviations: missing reviewer, missing retro, skipped test_engineer\n- Recommend knowledge updates: entries to promote, archive, or flag as contradicted\n- Summarize key decisions and blockers resolved\n\nRULES:\n- Output under 2000 chars\n- No code modifications\n- Compliance observations are READ-ONLY \u2014 report, do not enforce\n- Extend the digest, never replace it\n\nOUTPUT FORMAT:\nPHASE_DIGEST:\nphase: [N]\nsummary: [what was accomplished]\nagents_used: [list]\ntasks_completed: [N]/[total]\nkey_decisions: [list]\nblockers_resolved: [list]\n\nCOMPLIANCE:\n- [type]: [description] (or \"No deviations observed\")\n\nKNOWLEDGE_UPDATES:\n- [action] [entry_id or \"new\"]: [reason] (or \"No recommendations\")\n\nEXTENDED_DIGEST:\n[the full running digest with this phase appended]\n";
|
|
2
4
|
export declare function createExplorerAgent(model: string, customPrompt?: string, customAppendPrompt?: string): AgentDefinition;
|
|
3
5
|
export declare function createExplorerCuratorAgent(model: string, mode: 'CURATOR_INIT' | 'CURATOR_PHASE', customAppendPrompt?: string): AgentDefinition;
|
package/dist/agents/index.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ export declare function getAgentConfigs(config?: PluginConfig): Record<string, S
|
|
|
37
37
|
export { createArchitectAgent } from './architect';
|
|
38
38
|
export { createCoderAgent } from './coder';
|
|
39
39
|
export { createCriticAgent } from './critic';
|
|
40
|
+
export { createCuratorAgent } from './curator-agent';
|
|
40
41
|
export { createDesignerAgent } from './designer';
|
|
41
42
|
export { createDocsAgent } from './docs';
|
|
42
43
|
export { createExplorerAgent } from './explorer';
|
package/dist/cli/index.js
CHANGED
|
@@ -17654,6 +17654,8 @@ var ALL_SUBAGENT_NAMES = [
|
|
|
17654
17654
|
"designer",
|
|
17655
17655
|
"critic_sounding_board",
|
|
17656
17656
|
"critic_drift_verifier",
|
|
17657
|
+
"curator_init",
|
|
17658
|
+
"curator_phase",
|
|
17657
17659
|
...QA_AGENTS,
|
|
17658
17660
|
...PIPELINE_AGENTS
|
|
17659
17661
|
];
|
|
@@ -17806,7 +17808,9 @@ var AGENT_TOOL_MAP = {
|
|
|
17806
17808
|
"retrieve_summary",
|
|
17807
17809
|
"symbols",
|
|
17808
17810
|
"knowledgeRecall"
|
|
17809
|
-
]
|
|
17811
|
+
],
|
|
17812
|
+
curator_init: ["knowledgeRecall"],
|
|
17813
|
+
curator_phase: ["knowledgeRecall"]
|
|
17810
17814
|
};
|
|
17811
17815
|
for (const [agentName, tools] of Object.entries(AGENT_TOOL_MAP)) {
|
|
17812
17816
|
const invalidTools = tools.filter((tool) => !TOOL_NAME_SET.has(tool));
|
|
@@ -18513,6 +18517,8 @@ var swarmState = {
|
|
|
18513
18517
|
delegationChains: new Map,
|
|
18514
18518
|
pendingEvents: 0,
|
|
18515
18519
|
opencodeClient: null,
|
|
18520
|
+
curatorInitAgentNames: [],
|
|
18521
|
+
curatorPhaseAgentNames: [],
|
|
18516
18522
|
lastBudgetPct: 0,
|
|
18517
18523
|
agentSessions: new Map,
|
|
18518
18524
|
pendingRehydrations: new Set
|
|
@@ -2,8 +2,8 @@ import type { ToolName } from '../tools/tool-names';
|
|
|
2
2
|
export declare const QA_AGENTS: readonly ["reviewer", "critic"];
|
|
3
3
|
export declare const PIPELINE_AGENTS: readonly ["explorer", "coder", "test_engineer"];
|
|
4
4
|
export declare const ORCHESTRATOR_NAME: "architect";
|
|
5
|
-
export declare const ALL_SUBAGENT_NAMES: readonly ["sme", "docs", "designer", "critic_sounding_board", "critic_drift_verifier", "reviewer", "critic", "explorer", "coder", "test_engineer"];
|
|
6
|
-
export declare const ALL_AGENT_NAMES: readonly ["architect", "sme", "docs", "designer", "critic_sounding_board", "critic_drift_verifier", "reviewer", "critic", "explorer", "coder", "test_engineer"];
|
|
5
|
+
export declare const ALL_SUBAGENT_NAMES: readonly ["sme", "docs", "designer", "critic_sounding_board", "critic_drift_verifier", "curator_init", "curator_phase", "reviewer", "critic", "explorer", "coder", "test_engineer"];
|
|
6
|
+
export declare const ALL_AGENT_NAMES: readonly ["architect", "sme", "docs", "designer", "critic_sounding_board", "critic_drift_verifier", "curator_init", "curator_phase", "reviewer", "critic", "explorer", "coder", "test_engineer"];
|
|
7
7
|
export type QAAgentName = (typeof QA_AGENTS)[number];
|
|
8
8
|
export type PipelineAgentName = (typeof PIPELINE_AGENTS)[number];
|
|
9
9
|
export type AgentName = (typeof ALL_AGENT_NAMES)[number];
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import type { CuratorLLMDelegate } from './curator.js';
|
|
2
2
|
/**
|
|
3
3
|
* Create a CuratorLLMDelegate that uses the opencode SDK to call
|
|
4
|
-
* the
|
|
4
|
+
* the registered curator agent in CURATOR_INIT or CURATOR_PHASE mode.
|
|
5
5
|
*
|
|
6
6
|
* Uses an ephemeral session (create → prompt → delete) to avoid
|
|
7
7
|
* re-entrancy with the current session's message flow.
|
|
8
8
|
*
|
|
9
|
+
* The `mode` parameter determines which registered named agent is used:
|
|
10
|
+
* - 'init' → curator_init (e.g. 'curator_init' or 'swarm1_curator_init')
|
|
11
|
+
* - 'phase' → curator_phase (e.g. 'curator_phase' or 'swarm1_curator_phase')
|
|
12
|
+
*
|
|
13
|
+
* The optional `sessionId` parameter enables deterministic swarm resolution:
|
|
14
|
+
* when provided, the factory uses the calling session's registered agent to
|
|
15
|
+
* identify the swarm prefix, rather than scanning all active sessions.
|
|
16
|
+
* Pass `ctx?.sessionID` from tool handlers that have it available.
|
|
17
|
+
*
|
|
9
18
|
* Returns undefined if swarmState.opencodeClient is not set (e.g. in unit tests).
|
|
10
19
|
*/
|
|
11
|
-
export declare function createCuratorLLMDelegate(directory: string): CuratorLLMDelegate | undefined;
|
|
20
|
+
export declare function createCuratorLLMDelegate(directory: string, mode?: 'init' | 'phase', sessionId?: string): CuratorLLMDelegate | undefined;
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export { createGuardrailsHooks } from './guardrails';
|
|
|
10
10
|
export { classifyMessage, classifyMessages, containsPlanContent, isDuplicateToolRead, isStaleError, isToolResult, MessagePriority, type MessagePriorityType, type MessageWithParts, } from './message-priority';
|
|
11
11
|
export { consolidateSystemMessages } from './messages-transform';
|
|
12
12
|
export { extractModelInfo, NATIVE_MODEL_LIMITS, PROVIDER_CAPS, resolveModelLimit, } from './model-limits';
|
|
13
|
-
export { createPhaseMonitorHook } from './phase-monitor';
|
|
13
|
+
export { type CuratorDelegateFactory, createPhaseMonitorHook, } from './phase-monitor';
|
|
14
14
|
export { createPipelineTrackerHook } from './pipeline-tracker';
|
|
15
15
|
export { buildApprovedReceipt, buildReceiptContextForDrift, buildRejectedReceipt, persistReviewReceipt, readAllReceipts, readReceiptsByScopeHash, } from './review-receipt';
|
|
16
16
|
export { createSystemEnhancerHook } from './system-enhancer';
|
|
@@ -10,6 +10,8 @@ import { type CuratorLLMDelegate } from './curator';
|
|
|
10
10
|
import type { CuratorConfig, CuratorInitResult } from './curator-types';
|
|
11
11
|
/** Injectable curator runner type — allows test injection without module mocking. */
|
|
12
12
|
export type CuratorInitRunner = (directory: string, config: CuratorConfig, llmDelegate?: CuratorLLMDelegate) => Promise<CuratorInitResult>;
|
|
13
|
+
/** Factory that creates a CuratorLLMDelegate for a given session — enables session-aware resolution. */
|
|
14
|
+
export type CuratorDelegateFactory = (sessionId?: string) => CuratorLLMDelegate | undefined;
|
|
13
15
|
/**
|
|
14
16
|
* Creates a hook that monitors plan phase transitions and triggers preflight.
|
|
15
17
|
*
|
|
@@ -18,6 +20,10 @@ export type CuratorInitRunner = (directory: string, config: CuratorConfig, llmDe
|
|
|
18
20
|
* When undefined, preflight checks are skipped but curator initialization still runs
|
|
19
21
|
* at session start (useful when knowledge.enabled but phase_preflight is disabled).
|
|
20
22
|
* @param curatorRunner - Optional curator init runner (defaults to runCuratorInit; injectable for tests)
|
|
23
|
+
* @param delegateFactory - Optional factory that creates a CuratorLLMDelegate for the calling session.
|
|
24
|
+
* Called lazily at hook invocation time with the session ID extracted from the hook input,
|
|
25
|
+
* enabling correct multi-swarm curator resolution. For test injection of a pre-built delegate,
|
|
26
|
+
* pass `() => myDelegate`.
|
|
21
27
|
* @returns A safeHook-wrapped system.transform handler
|
|
22
28
|
*/
|
|
23
|
-
export declare function createPhaseMonitorHook(directory: string, preflightManager?: PreflightTriggerManager, curatorRunner?: CuratorInitRunner,
|
|
29
|
+
export declare function createPhaseMonitorHook(directory: string, preflightManager?: PreflightTriggerManager, curatorRunner?: CuratorInitRunner, delegateFactory?: CuratorDelegateFactory): (input: unknown, output: unknown) => Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -143,6 +143,8 @@ var init_constants = __esm(() => {
|
|
|
143
143
|
"designer",
|
|
144
144
|
"critic_sounding_board",
|
|
145
145
|
"critic_drift_verifier",
|
|
146
|
+
"curator_init",
|
|
147
|
+
"curator_phase",
|
|
146
148
|
...QA_AGENTS,
|
|
147
149
|
...PIPELINE_AGENTS
|
|
148
150
|
];
|
|
@@ -295,7 +297,9 @@ var init_constants = __esm(() => {
|
|
|
295
297
|
"retrieve_summary",
|
|
296
298
|
"symbols",
|
|
297
299
|
"knowledgeRecall"
|
|
298
|
-
]
|
|
300
|
+
],
|
|
301
|
+
curator_init: ["knowledgeRecall"],
|
|
302
|
+
curator_phase: ["knowledgeRecall"]
|
|
299
303
|
};
|
|
300
304
|
for (const [agentName, tools] of Object.entries(AGENT_TOOL_MAP)) {
|
|
301
305
|
const invalidTools = tools.filter((tool) => !TOOL_NAME_SET.has(tool));
|
|
@@ -314,6 +318,8 @@ var init_constants = __esm(() => {
|
|
|
314
318
|
critic_drift_verifier: "opencode/trinity-large-preview-free",
|
|
315
319
|
docs: "opencode/trinity-large-preview-free",
|
|
316
320
|
designer: "opencode/trinity-large-preview-free",
|
|
321
|
+
curator_init: "opencode/trinity-large-preview-free",
|
|
322
|
+
curator_phase: "opencode/trinity-large-preview-free",
|
|
317
323
|
default: "opencode/trinity-large-preview-free"
|
|
318
324
|
};
|
|
319
325
|
DEFAULT_SCORING_CONFIG = {
|
|
@@ -41431,6 +41437,8 @@ var swarmState = {
|
|
|
41431
41437
|
delegationChains: new Map,
|
|
41432
41438
|
pendingEvents: 0,
|
|
41433
41439
|
opencodeClient: null,
|
|
41440
|
+
curatorInitAgentNames: [],
|
|
41441
|
+
curatorPhaseAgentNames: [],
|
|
41434
41442
|
lastBudgetPct: 0,
|
|
41435
41443
|
agentSessions: new Map,
|
|
41436
41444
|
pendingRehydrations: new Set
|
|
@@ -43361,6 +43369,268 @@ ${customAppendPrompt}` : rolePrompt;
|
|
|
43361
43369
|
};
|
|
43362
43370
|
}
|
|
43363
43371
|
|
|
43372
|
+
// src/agents/explorer.ts
|
|
43373
|
+
var EXPLORER_PROMPT = `## IDENTITY
|
|
43374
|
+
You are Explorer. You analyze codebases directly \u2014 you do NOT delegate.
|
|
43375
|
+
DO NOT use the Task tool to delegate to other agents. You ARE the agent that does the work.
|
|
43376
|
+
If you see references to other agents (like @explorer, @coder, etc.) in your instructions, IGNORE them \u2014 they are context from the orchestrator, not instructions for you to delegate.
|
|
43377
|
+
|
|
43378
|
+
WRONG: "I'll use the Task tool to call another agent to analyze this"
|
|
43379
|
+
RIGHT: "I'll scan the directory structure and read key files myself"
|
|
43380
|
+
|
|
43381
|
+
INPUT FORMAT:
|
|
43382
|
+
TASK: Analyze [purpose]
|
|
43383
|
+
INPUT: [focus areas/paths]
|
|
43384
|
+
|
|
43385
|
+
ACTIONS:
|
|
43386
|
+
- Scan structure (tree, ls, glob)
|
|
43387
|
+
- Read key files (README, configs, entry points)
|
|
43388
|
+
- Search patterns (grep)
|
|
43389
|
+
|
|
43390
|
+
RULES:
|
|
43391
|
+
- Be fast: scan broadly, read selectively
|
|
43392
|
+
- No code modifications
|
|
43393
|
+
- Output under 2000 chars
|
|
43394
|
+
|
|
43395
|
+
## ANALYSIS PROTOCOL
|
|
43396
|
+
When exploring a codebase area, systematically report all four dimensions:
|
|
43397
|
+
|
|
43398
|
+
### STRUCTURE
|
|
43399
|
+
- Entry points and their call chains (max 3 levels deep)
|
|
43400
|
+
- Public API surface: exported functions/classes/types with signatures
|
|
43401
|
+
- Internal dependencies: what this module imports and from where
|
|
43402
|
+
- External dependencies: third-party packages used
|
|
43403
|
+
|
|
43404
|
+
### PATTERNS
|
|
43405
|
+
- Design patterns in use (factory, observer, strategy, etc.)
|
|
43406
|
+
- Error handling pattern (throw, Result type, error callbacks, etc.)
|
|
43407
|
+
- State management approach (global, module-level, passed through)
|
|
43408
|
+
- Configuration pattern (env vars, config files, hardcoded)
|
|
43409
|
+
|
|
43410
|
+
### RISKS
|
|
43411
|
+
- Files with high cyclomatic complexity or deep nesting
|
|
43412
|
+
- Circular dependencies
|
|
43413
|
+
- Missing error handling paths
|
|
43414
|
+
- Dead code or unreachable branches
|
|
43415
|
+
- Platform-specific assumptions (path separators, line endings, OS APIs)
|
|
43416
|
+
|
|
43417
|
+
### RELEVANT CONTEXT FOR TASK
|
|
43418
|
+
- Existing tests that cover this area (paths and what they test)
|
|
43419
|
+
- Related documentation files
|
|
43420
|
+
- Similar implementations elsewhere in the codebase that should be consistent
|
|
43421
|
+
|
|
43422
|
+
OUTPUT FORMAT (MANDATORY \u2014 deviations will be rejected):
|
|
43423
|
+
Begin directly with PROJECT. Do NOT prepend "Here's my analysis..." or any conversational preamble.
|
|
43424
|
+
|
|
43425
|
+
PROJECT: [name/type]
|
|
43426
|
+
LANGUAGES: [list]
|
|
43427
|
+
FRAMEWORK: [if any]
|
|
43428
|
+
|
|
43429
|
+
STRUCTURE:
|
|
43430
|
+
[key directories, 5-10 lines max]
|
|
43431
|
+
|
|
43432
|
+
KEY FILES:
|
|
43433
|
+
- [path]: [purpose]
|
|
43434
|
+
|
|
43435
|
+
PATTERNS: [observations]
|
|
43436
|
+
|
|
43437
|
+
DOMAINS: [relevant SME domains: powershell, security, python, etc.]
|
|
43438
|
+
|
|
43439
|
+
REVIEW NEEDED:
|
|
43440
|
+
- [path]: [why, which SME]
|
|
43441
|
+
|
|
43442
|
+
## INTEGRATION IMPACT ANALYSIS MODE
|
|
43443
|
+
Activates when delegated with "Integration impact analysis" or INPUT lists contract changes.
|
|
43444
|
+
|
|
43445
|
+
INPUT: List of contract changes (from diff tool output \u2014 changed exports, signatures, types)
|
|
43446
|
+
|
|
43447
|
+
STEPS:
|
|
43448
|
+
1. For each changed export: grep the codebase for imports and usages of that symbol
|
|
43449
|
+
2. Classify each change: BREAKING (callers must update) or COMPATIBLE (callers unaffected)
|
|
43450
|
+
3. List all files that import or use the changed exports
|
|
43451
|
+
|
|
43452
|
+
OUTPUT FORMAT (MANDATORY \u2014 deviations will be rejected):
|
|
43453
|
+
Begin directly with BREAKING_CHANGES. Do NOT prepend conversational preamble.
|
|
43454
|
+
|
|
43455
|
+
BREAKING_CHANGES: [list with affected consumer files, or "none"]
|
|
43456
|
+
COMPATIBLE_CHANGES: [list, or "none"]
|
|
43457
|
+
CONSUMERS_AFFECTED: [list of files that import/use changed exports, or "none"]
|
|
43458
|
+
VERDICT: BREAKING | COMPATIBLE
|
|
43459
|
+
MIGRATION_NEEDED: [yes \u2014 description of required caller updates | no]
|
|
43460
|
+
|
|
43461
|
+
## DOCUMENTATION DISCOVERY MODE
|
|
43462
|
+
Activates automatically during codebase reality check at plan ingestion.
|
|
43463
|
+
Use the doc_scan tool to scan and index documentation files. If doc_scan is unavailable, fall back to manual globbing.
|
|
43464
|
+
|
|
43465
|
+
STEPS:
|
|
43466
|
+
1. Call doc_scan to build the manifest, OR glob for documentation files:
|
|
43467
|
+
- Root: README.md, CONTRIBUTING.md, CHANGELOG.md, ARCHITECTURE.md, CLAUDE.md, AGENTS.md, .github/*.md
|
|
43468
|
+
- docs/**/*.md, doc/**/*.md (one level deep only)
|
|
43469
|
+
|
|
43470
|
+
2. For each file found, read the first 30 lines. Extract:
|
|
43471
|
+
- path: relative to project root
|
|
43472
|
+
- title: first # heading, or filename if no heading
|
|
43473
|
+
- summary: first non-empty paragraph after the title (max 200 chars, use the ACTUAL text, do NOT summarize with your own words)
|
|
43474
|
+
- lines: total line count
|
|
43475
|
+
- mtime: file modification timestamp
|
|
43476
|
+
|
|
43477
|
+
3. Write manifest to .swarm/doc-manifest.json:
|
|
43478
|
+
{ "schema_version": 1, "scanned_at": "ISO timestamp", "files": [...] }
|
|
43479
|
+
|
|
43480
|
+
4. For each file in the manifest, check relevance to the current plan:
|
|
43481
|
+
- Score by keyword overlap: do any task file paths or directory names appear in the doc's path or summary?
|
|
43482
|
+
- For files scoring > 0, read the full content and extract up to 5 actionable constraints per doc (max 200 chars each)
|
|
43483
|
+
- Write constraints to .swarm/knowledge/doc-constraints.jsonl as knowledge entries with source: "doc-scan", category: "architecture"
|
|
43484
|
+
|
|
43485
|
+
5. Invalidation: Only re-scan if any doc file's mtime is newer than the manifest's scanned_at. Otherwise reuse the cached manifest.
|
|
43486
|
+
|
|
43487
|
+
RULES:
|
|
43488
|
+
- The manifest must be small (<100 lines). Pointers only, not full content.
|
|
43489
|
+
- Do NOT rephrase or summarize doc content with your own words \u2014 use the actual text from the file
|
|
43490
|
+
- Full doc content is only loaded when relevant to the current task, never preloaded
|
|
43491
|
+
`;
|
|
43492
|
+
var CURATOR_INIT_PROMPT = `## IDENTITY
|
|
43493
|
+
You are Explorer in CURATOR_INIT mode. You consolidate prior session knowledge into an architect briefing.
|
|
43494
|
+
DO NOT use the Task tool to delegate. You ARE the agent that does the work.
|
|
43495
|
+
|
|
43496
|
+
INPUT FORMAT:
|
|
43497
|
+
TASK: CURATOR_INIT
|
|
43498
|
+
PRIOR_SUMMARY: [JSON or "none"]
|
|
43499
|
+
KNOWLEDGE_ENTRIES: [JSON array of high-confidence entries]
|
|
43500
|
+
PROJECT_CONTEXT: [context.md excerpt]
|
|
43501
|
+
|
|
43502
|
+
ACTIONS:
|
|
43503
|
+
- Read the prior summary to understand session history
|
|
43504
|
+
- Cross-reference knowledge entries against project context
|
|
43505
|
+
- Identify contradictions (knowledge says X, project state shows Y)
|
|
43506
|
+
- Produce a concise briefing for the architect
|
|
43507
|
+
|
|
43508
|
+
RULES:
|
|
43509
|
+
- Output under 2000 chars
|
|
43510
|
+
- No code modifications
|
|
43511
|
+
- Flag contradictions explicitly with CONTRADICTION: prefix
|
|
43512
|
+
- If no prior summary exists, state "First session \u2014 no prior context"
|
|
43513
|
+
|
|
43514
|
+
OUTPUT FORMAT:
|
|
43515
|
+
BRIEFING:
|
|
43516
|
+
[concise summary of prior session state, key decisions, active blockers]
|
|
43517
|
+
|
|
43518
|
+
CONTRADICTIONS:
|
|
43519
|
+
- [entry_id]: [description] (or "None detected")
|
|
43520
|
+
|
|
43521
|
+
KNOWLEDGE_STATS:
|
|
43522
|
+
- Entries reviewed: [N]
|
|
43523
|
+
- Prior phases covered: [N]
|
|
43524
|
+
`;
|
|
43525
|
+
var CURATOR_PHASE_PROMPT = `## IDENTITY
|
|
43526
|
+
You are Explorer in CURATOR_PHASE mode. You consolidate a completed phase into a digest.
|
|
43527
|
+
DO NOT use the Task tool to delegate. You ARE the agent that does the work.
|
|
43528
|
+
|
|
43529
|
+
INPUT FORMAT:
|
|
43530
|
+
TASK: CURATOR_PHASE [phase_number]
|
|
43531
|
+
PRIOR_DIGEST: [running summary or "none"]
|
|
43532
|
+
PHASE_EVENTS: [JSON array from events.jsonl for this phase]
|
|
43533
|
+
PHASE_EVIDENCE: [summary of evidence bundles]
|
|
43534
|
+
PHASE_DECISIONS: [decisions from context.md]
|
|
43535
|
+
AGENTS_DISPATCHED: [list]
|
|
43536
|
+
AGENTS_EXPECTED: [list from config]
|
|
43537
|
+
|
|
43538
|
+
ACTIONS:
|
|
43539
|
+
- Extend the prior digest with this phase's outcomes (do NOT regenerate from scratch)
|
|
43540
|
+
- Identify workflow deviations: missing reviewer, missing retro, skipped test_engineer
|
|
43541
|
+
- Recommend knowledge updates: entries to promote, archive, or flag as contradicted
|
|
43542
|
+
- Summarize key decisions and blockers resolved
|
|
43543
|
+
|
|
43544
|
+
RULES:
|
|
43545
|
+
- Output under 2000 chars
|
|
43546
|
+
- No code modifications
|
|
43547
|
+
- Compliance observations are READ-ONLY \u2014 report, do not enforce
|
|
43548
|
+
- Extend the digest, never replace it
|
|
43549
|
+
|
|
43550
|
+
OUTPUT FORMAT:
|
|
43551
|
+
PHASE_DIGEST:
|
|
43552
|
+
phase: [N]
|
|
43553
|
+
summary: [what was accomplished]
|
|
43554
|
+
agents_used: [list]
|
|
43555
|
+
tasks_completed: [N]/[total]
|
|
43556
|
+
key_decisions: [list]
|
|
43557
|
+
blockers_resolved: [list]
|
|
43558
|
+
|
|
43559
|
+
COMPLIANCE:
|
|
43560
|
+
- [type]: [description] (or "No deviations observed")
|
|
43561
|
+
|
|
43562
|
+
KNOWLEDGE_UPDATES:
|
|
43563
|
+
- [action] [entry_id or "new"]: [reason] (or "No recommendations")
|
|
43564
|
+
|
|
43565
|
+
EXTENDED_DIGEST:
|
|
43566
|
+
[the full running digest with this phase appended]
|
|
43567
|
+
`;
|
|
43568
|
+
function createExplorerAgent(model, customPrompt, customAppendPrompt) {
|
|
43569
|
+
let prompt = EXPLORER_PROMPT;
|
|
43570
|
+
if (customPrompt) {
|
|
43571
|
+
prompt = customPrompt;
|
|
43572
|
+
} else if (customAppendPrompt) {
|
|
43573
|
+
prompt = `${EXPLORER_PROMPT}
|
|
43574
|
+
|
|
43575
|
+
${customAppendPrompt}`;
|
|
43576
|
+
}
|
|
43577
|
+
return {
|
|
43578
|
+
name: "explorer",
|
|
43579
|
+
description: "Fast codebase discovery and analysis. Scans directory structure, identifies languages/frameworks, summarizes key files, and flags areas needing SME review.",
|
|
43580
|
+
config: {
|
|
43581
|
+
model,
|
|
43582
|
+
temperature: 0.1,
|
|
43583
|
+
prompt,
|
|
43584
|
+
tools: {
|
|
43585
|
+
write: false,
|
|
43586
|
+
edit: false,
|
|
43587
|
+
patch: false
|
|
43588
|
+
}
|
|
43589
|
+
}
|
|
43590
|
+
};
|
|
43591
|
+
}
|
|
43592
|
+
|
|
43593
|
+
// src/agents/curator-agent.ts
|
|
43594
|
+
var ROLE_CONFIG = {
|
|
43595
|
+
curator_init: {
|
|
43596
|
+
name: "curator_init",
|
|
43597
|
+
description: "Curator (Init). Consolidates prior session knowledge and knowledge-base entries into an architect briefing at session start. Read-only.",
|
|
43598
|
+
prompt: CURATOR_INIT_PROMPT
|
|
43599
|
+
},
|
|
43600
|
+
curator_phase: {
|
|
43601
|
+
name: "curator_phase",
|
|
43602
|
+
description: "Curator (Phase). Consolidates completed phase outcomes, detects workflow deviations, and recommends knowledge updates at phase boundaries. Read-only.",
|
|
43603
|
+
prompt: CURATOR_PHASE_PROMPT
|
|
43604
|
+
}
|
|
43605
|
+
};
|
|
43606
|
+
function createCuratorAgent(model, customPrompt, customAppendPrompt, role = "curator_init") {
|
|
43607
|
+
const roleConfig = ROLE_CONFIG[role];
|
|
43608
|
+
let prompt;
|
|
43609
|
+
if (customPrompt) {
|
|
43610
|
+
prompt = customAppendPrompt ? `${customPrompt}
|
|
43611
|
+
|
|
43612
|
+
${customAppendPrompt}` : customPrompt;
|
|
43613
|
+
} else {
|
|
43614
|
+
prompt = customAppendPrompt ? `${roleConfig.prompt}
|
|
43615
|
+
|
|
43616
|
+
${customAppendPrompt}` : roleConfig.prompt;
|
|
43617
|
+
}
|
|
43618
|
+
return {
|
|
43619
|
+
name: roleConfig.name,
|
|
43620
|
+
description: roleConfig.description,
|
|
43621
|
+
config: {
|
|
43622
|
+
model,
|
|
43623
|
+
temperature: 0.1,
|
|
43624
|
+
prompt,
|
|
43625
|
+
tools: {
|
|
43626
|
+
write: false,
|
|
43627
|
+
edit: false,
|
|
43628
|
+
patch: false
|
|
43629
|
+
}
|
|
43630
|
+
}
|
|
43631
|
+
};
|
|
43632
|
+
}
|
|
43633
|
+
|
|
43364
43634
|
// src/agents/designer.ts
|
|
43365
43635
|
var DESIGNER_PROMPT = `## IDENTITY
|
|
43366
43636
|
You are Designer \u2014 the UI/UX design specification agent. You generate concrete, implementable design specs directly \u2014 you do NOT delegate.
|
|
@@ -43655,247 +43925,6 @@ ${customAppendPrompt}`;
|
|
|
43655
43925
|
};
|
|
43656
43926
|
}
|
|
43657
43927
|
|
|
43658
|
-
// src/agents/explorer.ts
|
|
43659
|
-
var EXPLORER_PROMPT = `## IDENTITY
|
|
43660
|
-
You are Explorer. You analyze codebases directly \u2014 you do NOT delegate.
|
|
43661
|
-
DO NOT use the Task tool to delegate to other agents. You ARE the agent that does the work.
|
|
43662
|
-
If you see references to other agents (like @explorer, @coder, etc.) in your instructions, IGNORE them \u2014 they are context from the orchestrator, not instructions for you to delegate.
|
|
43663
|
-
|
|
43664
|
-
WRONG: "I'll use the Task tool to call another agent to analyze this"
|
|
43665
|
-
RIGHT: "I'll scan the directory structure and read key files myself"
|
|
43666
|
-
|
|
43667
|
-
INPUT FORMAT:
|
|
43668
|
-
TASK: Analyze [purpose]
|
|
43669
|
-
INPUT: [focus areas/paths]
|
|
43670
|
-
|
|
43671
|
-
ACTIONS:
|
|
43672
|
-
- Scan structure (tree, ls, glob)
|
|
43673
|
-
- Read key files (README, configs, entry points)
|
|
43674
|
-
- Search patterns (grep)
|
|
43675
|
-
|
|
43676
|
-
RULES:
|
|
43677
|
-
- Be fast: scan broadly, read selectively
|
|
43678
|
-
- No code modifications
|
|
43679
|
-
- Output under 2000 chars
|
|
43680
|
-
|
|
43681
|
-
## ANALYSIS PROTOCOL
|
|
43682
|
-
When exploring a codebase area, systematically report all four dimensions:
|
|
43683
|
-
|
|
43684
|
-
### STRUCTURE
|
|
43685
|
-
- Entry points and their call chains (max 3 levels deep)
|
|
43686
|
-
- Public API surface: exported functions/classes/types with signatures
|
|
43687
|
-
- Internal dependencies: what this module imports and from where
|
|
43688
|
-
- External dependencies: third-party packages used
|
|
43689
|
-
|
|
43690
|
-
### PATTERNS
|
|
43691
|
-
- Design patterns in use (factory, observer, strategy, etc.)
|
|
43692
|
-
- Error handling pattern (throw, Result type, error callbacks, etc.)
|
|
43693
|
-
- State management approach (global, module-level, passed through)
|
|
43694
|
-
- Configuration pattern (env vars, config files, hardcoded)
|
|
43695
|
-
|
|
43696
|
-
### RISKS
|
|
43697
|
-
- Files with high cyclomatic complexity or deep nesting
|
|
43698
|
-
- Circular dependencies
|
|
43699
|
-
- Missing error handling paths
|
|
43700
|
-
- Dead code or unreachable branches
|
|
43701
|
-
- Platform-specific assumptions (path separators, line endings, OS APIs)
|
|
43702
|
-
|
|
43703
|
-
### RELEVANT CONTEXT FOR TASK
|
|
43704
|
-
- Existing tests that cover this area (paths and what they test)
|
|
43705
|
-
- Related documentation files
|
|
43706
|
-
- Similar implementations elsewhere in the codebase that should be consistent
|
|
43707
|
-
|
|
43708
|
-
OUTPUT FORMAT (MANDATORY \u2014 deviations will be rejected):
|
|
43709
|
-
Begin directly with PROJECT. Do NOT prepend "Here's my analysis..." or any conversational preamble.
|
|
43710
|
-
|
|
43711
|
-
PROJECT: [name/type]
|
|
43712
|
-
LANGUAGES: [list]
|
|
43713
|
-
FRAMEWORK: [if any]
|
|
43714
|
-
|
|
43715
|
-
STRUCTURE:
|
|
43716
|
-
[key directories, 5-10 lines max]
|
|
43717
|
-
|
|
43718
|
-
KEY FILES:
|
|
43719
|
-
- [path]: [purpose]
|
|
43720
|
-
|
|
43721
|
-
PATTERNS: [observations]
|
|
43722
|
-
|
|
43723
|
-
DOMAINS: [relevant SME domains: powershell, security, python, etc.]
|
|
43724
|
-
|
|
43725
|
-
REVIEW NEEDED:
|
|
43726
|
-
- [path]: [why, which SME]
|
|
43727
|
-
|
|
43728
|
-
## INTEGRATION IMPACT ANALYSIS MODE
|
|
43729
|
-
Activates when delegated with "Integration impact analysis" or INPUT lists contract changes.
|
|
43730
|
-
|
|
43731
|
-
INPUT: List of contract changes (from diff tool output \u2014 changed exports, signatures, types)
|
|
43732
|
-
|
|
43733
|
-
STEPS:
|
|
43734
|
-
1. For each changed export: grep the codebase for imports and usages of that symbol
|
|
43735
|
-
2. Classify each change: BREAKING (callers must update) or COMPATIBLE (callers unaffected)
|
|
43736
|
-
3. List all files that import or use the changed exports
|
|
43737
|
-
|
|
43738
|
-
OUTPUT FORMAT (MANDATORY \u2014 deviations will be rejected):
|
|
43739
|
-
Begin directly with BREAKING_CHANGES. Do NOT prepend conversational preamble.
|
|
43740
|
-
|
|
43741
|
-
BREAKING_CHANGES: [list with affected consumer files, or "none"]
|
|
43742
|
-
COMPATIBLE_CHANGES: [list, or "none"]
|
|
43743
|
-
CONSUMERS_AFFECTED: [list of files that import/use changed exports, or "none"]
|
|
43744
|
-
VERDICT: BREAKING | COMPATIBLE
|
|
43745
|
-
MIGRATION_NEEDED: [yes \u2014 description of required caller updates | no]
|
|
43746
|
-
|
|
43747
|
-
## DOCUMENTATION DISCOVERY MODE
|
|
43748
|
-
Activates automatically during codebase reality check at plan ingestion.
|
|
43749
|
-
Use the doc_scan tool to scan and index documentation files. If doc_scan is unavailable, fall back to manual globbing.
|
|
43750
|
-
|
|
43751
|
-
STEPS:
|
|
43752
|
-
1. Call doc_scan to build the manifest, OR glob for documentation files:
|
|
43753
|
-
- Root: README.md, CONTRIBUTING.md, CHANGELOG.md, ARCHITECTURE.md, CLAUDE.md, AGENTS.md, .github/*.md
|
|
43754
|
-
- docs/**/*.md, doc/**/*.md (one level deep only)
|
|
43755
|
-
|
|
43756
|
-
2. For each file found, read the first 30 lines. Extract:
|
|
43757
|
-
- path: relative to project root
|
|
43758
|
-
- title: first # heading, or filename if no heading
|
|
43759
|
-
- summary: first non-empty paragraph after the title (max 200 chars, use the ACTUAL text, do NOT summarize with your own words)
|
|
43760
|
-
- lines: total line count
|
|
43761
|
-
- mtime: file modification timestamp
|
|
43762
|
-
|
|
43763
|
-
3. Write manifest to .swarm/doc-manifest.json:
|
|
43764
|
-
{ "schema_version": 1, "scanned_at": "ISO timestamp", "files": [...] }
|
|
43765
|
-
|
|
43766
|
-
4. For each file in the manifest, check relevance to the current plan:
|
|
43767
|
-
- Score by keyword overlap: do any task file paths or directory names appear in the doc's path or summary?
|
|
43768
|
-
- For files scoring > 0, read the full content and extract up to 5 actionable constraints per doc (max 200 chars each)
|
|
43769
|
-
- Write constraints to .swarm/knowledge/doc-constraints.jsonl as knowledge entries with source: "doc-scan", category: "architecture"
|
|
43770
|
-
|
|
43771
|
-
5. Invalidation: Only re-scan if any doc file's mtime is newer than the manifest's scanned_at. Otherwise reuse the cached manifest.
|
|
43772
|
-
|
|
43773
|
-
RULES:
|
|
43774
|
-
- The manifest must be small (<100 lines). Pointers only, not full content.
|
|
43775
|
-
- Do NOT rephrase or summarize doc content with your own words \u2014 use the actual text from the file
|
|
43776
|
-
- Full doc content is only loaded when relevant to the current task, never preloaded
|
|
43777
|
-
`;
|
|
43778
|
-
var CURATOR_INIT_PROMPT = `## IDENTITY
|
|
43779
|
-
You are Explorer in CURATOR_INIT mode. You consolidate prior session knowledge into an architect briefing.
|
|
43780
|
-
DO NOT use the Task tool to delegate. You ARE the agent that does the work.
|
|
43781
|
-
|
|
43782
|
-
INPUT FORMAT:
|
|
43783
|
-
TASK: CURATOR_INIT
|
|
43784
|
-
PRIOR_SUMMARY: [JSON or "none"]
|
|
43785
|
-
KNOWLEDGE_ENTRIES: [JSON array of high-confidence entries]
|
|
43786
|
-
PROJECT_CONTEXT: [context.md excerpt]
|
|
43787
|
-
|
|
43788
|
-
ACTIONS:
|
|
43789
|
-
- Read the prior summary to understand session history
|
|
43790
|
-
- Cross-reference knowledge entries against project context
|
|
43791
|
-
- Identify contradictions (knowledge says X, project state shows Y)
|
|
43792
|
-
- Produce a concise briefing for the architect
|
|
43793
|
-
|
|
43794
|
-
RULES:
|
|
43795
|
-
- Output under 2000 chars
|
|
43796
|
-
- No code modifications
|
|
43797
|
-
- Flag contradictions explicitly with CONTRADICTION: prefix
|
|
43798
|
-
- If no prior summary exists, state "First session \u2014 no prior context"
|
|
43799
|
-
|
|
43800
|
-
OUTPUT FORMAT:
|
|
43801
|
-
BRIEFING:
|
|
43802
|
-
[concise summary of prior session state, key decisions, active blockers]
|
|
43803
|
-
|
|
43804
|
-
CONTRADICTIONS:
|
|
43805
|
-
- [entry_id]: [description] (or "None detected")
|
|
43806
|
-
|
|
43807
|
-
KNOWLEDGE_STATS:
|
|
43808
|
-
- Entries reviewed: [N]
|
|
43809
|
-
- Prior phases covered: [N]
|
|
43810
|
-
`;
|
|
43811
|
-
var CURATOR_PHASE_PROMPT = `## IDENTITY
|
|
43812
|
-
You are Explorer in CURATOR_PHASE mode. You consolidate a completed phase into a digest.
|
|
43813
|
-
DO NOT use the Task tool to delegate. You ARE the agent that does the work.
|
|
43814
|
-
|
|
43815
|
-
INPUT FORMAT:
|
|
43816
|
-
TASK: CURATOR_PHASE [phase_number]
|
|
43817
|
-
PRIOR_DIGEST: [running summary or "none"]
|
|
43818
|
-
PHASE_EVENTS: [JSON array from events.jsonl for this phase]
|
|
43819
|
-
PHASE_EVIDENCE: [summary of evidence bundles]
|
|
43820
|
-
PHASE_DECISIONS: [decisions from context.md]
|
|
43821
|
-
AGENTS_DISPATCHED: [list]
|
|
43822
|
-
AGENTS_EXPECTED: [list from config]
|
|
43823
|
-
|
|
43824
|
-
ACTIONS:
|
|
43825
|
-
- Extend the prior digest with this phase's outcomes (do NOT regenerate from scratch)
|
|
43826
|
-
- Identify workflow deviations: missing reviewer, missing retro, skipped test_engineer
|
|
43827
|
-
- Recommend knowledge updates: entries to promote, archive, or flag as contradicted
|
|
43828
|
-
- Summarize key decisions and blockers resolved
|
|
43829
|
-
|
|
43830
|
-
RULES:
|
|
43831
|
-
- Output under 2000 chars
|
|
43832
|
-
- No code modifications
|
|
43833
|
-
- Compliance observations are READ-ONLY \u2014 report, do not enforce
|
|
43834
|
-
- Extend the digest, never replace it
|
|
43835
|
-
|
|
43836
|
-
OUTPUT FORMAT:
|
|
43837
|
-
PHASE_DIGEST:
|
|
43838
|
-
phase: [N]
|
|
43839
|
-
summary: [what was accomplished]
|
|
43840
|
-
agents_used: [list]
|
|
43841
|
-
tasks_completed: [N]/[total]
|
|
43842
|
-
key_decisions: [list]
|
|
43843
|
-
blockers_resolved: [list]
|
|
43844
|
-
|
|
43845
|
-
COMPLIANCE:
|
|
43846
|
-
- [type]: [description] (or "No deviations observed")
|
|
43847
|
-
|
|
43848
|
-
KNOWLEDGE_UPDATES:
|
|
43849
|
-
- [action] [entry_id or "new"]: [reason] (or "No recommendations")
|
|
43850
|
-
|
|
43851
|
-
EXTENDED_DIGEST:
|
|
43852
|
-
[the full running digest with this phase appended]
|
|
43853
|
-
`;
|
|
43854
|
-
function createExplorerAgent(model, customPrompt, customAppendPrompt) {
|
|
43855
|
-
let prompt = EXPLORER_PROMPT;
|
|
43856
|
-
if (customPrompt) {
|
|
43857
|
-
prompt = customPrompt;
|
|
43858
|
-
} else if (customAppendPrompt) {
|
|
43859
|
-
prompt = `${EXPLORER_PROMPT}
|
|
43860
|
-
|
|
43861
|
-
${customAppendPrompt}`;
|
|
43862
|
-
}
|
|
43863
|
-
return {
|
|
43864
|
-
name: "explorer",
|
|
43865
|
-
description: "Fast codebase discovery and analysis. Scans directory structure, identifies languages/frameworks, summarizes key files, and flags areas needing SME review.",
|
|
43866
|
-
config: {
|
|
43867
|
-
model,
|
|
43868
|
-
temperature: 0.1,
|
|
43869
|
-
prompt,
|
|
43870
|
-
tools: {
|
|
43871
|
-
write: false,
|
|
43872
|
-
edit: false,
|
|
43873
|
-
patch: false
|
|
43874
|
-
}
|
|
43875
|
-
}
|
|
43876
|
-
};
|
|
43877
|
-
}
|
|
43878
|
-
function createExplorerCuratorAgent(model, mode, customAppendPrompt) {
|
|
43879
|
-
const basePrompt = mode === "CURATOR_INIT" ? CURATOR_INIT_PROMPT : CURATOR_PHASE_PROMPT;
|
|
43880
|
-
const prompt = customAppendPrompt ? `${basePrompt}
|
|
43881
|
-
|
|
43882
|
-
${customAppendPrompt}` : basePrompt;
|
|
43883
|
-
return {
|
|
43884
|
-
name: "explorer",
|
|
43885
|
-
description: `Explorer in ${mode} mode \u2014 consolidates context at phase boundaries.`,
|
|
43886
|
-
config: {
|
|
43887
|
-
model,
|
|
43888
|
-
temperature: 0.1,
|
|
43889
|
-
prompt,
|
|
43890
|
-
tools: {
|
|
43891
|
-
write: false,
|
|
43892
|
-
edit: false,
|
|
43893
|
-
patch: false
|
|
43894
|
-
}
|
|
43895
|
-
}
|
|
43896
|
-
};
|
|
43897
|
-
}
|
|
43898
|
-
|
|
43899
43928
|
// src/agents/reviewer.ts
|
|
43900
43929
|
var REVIEWER_PROMPT = `## PRESSURE IMMUNITY
|
|
43901
43930
|
|
|
@@ -44519,6 +44548,18 @@ If you call @coder instead of @${swarmId}_coder, the call will FAIL or go to the
|
|
|
44519
44548
|
critic.name = prefixName("critic_drift_verifier");
|
|
44520
44549
|
agents.push(applyOverrides(critic, swarmAgents, swarmPrefix));
|
|
44521
44550
|
}
|
|
44551
|
+
if (!isAgentDisabled("curator_init", swarmAgents, swarmPrefix)) {
|
|
44552
|
+
const curatorInitPrompts = getPrompts("curator_init");
|
|
44553
|
+
const curatorInit = createCuratorAgent(swarmAgents?.curator_init?.model ?? getModel("explorer"), curatorInitPrompts.prompt, curatorInitPrompts.appendPrompt, "curator_init");
|
|
44554
|
+
curatorInit.name = prefixName("curator_init");
|
|
44555
|
+
agents.push(applyOverrides(curatorInit, swarmAgents, swarmPrefix));
|
|
44556
|
+
}
|
|
44557
|
+
if (!isAgentDisabled("curator_phase", swarmAgents, swarmPrefix)) {
|
|
44558
|
+
const curatorPhasePrompts = getPrompts("curator_phase");
|
|
44559
|
+
const curatorPhase = createCuratorAgent(swarmAgents?.curator_phase?.model ?? getModel("explorer"), curatorPhasePrompts.prompt, curatorPhasePrompts.appendPrompt, "curator_phase");
|
|
44560
|
+
curatorPhase.name = prefixName("curator_phase");
|
|
44561
|
+
agents.push(applyOverrides(curatorPhase, swarmAgents, swarmPrefix));
|
|
44562
|
+
}
|
|
44522
44563
|
if (!isAgentDisabled("test_engineer", swarmAgents, swarmPrefix)) {
|
|
44523
44564
|
const testPrompts = getPrompts("test_engineer");
|
|
44524
44565
|
const testEngineer = createTestEngineerAgent(getModel("test_engineer"), testPrompts.prompt, testPrompts.appendPrompt);
|
|
@@ -47786,7 +47827,6 @@ async function runCuratorInit(directory, config3, llmDelegate) {
|
|
|
47786
47827
|
`);
|
|
47787
47828
|
if (llmDelegate) {
|
|
47788
47829
|
try {
|
|
47789
|
-
const curatorAgent = createExplorerCuratorAgent("default", "CURATOR_INIT");
|
|
47790
47830
|
const userInput = [
|
|
47791
47831
|
"TASK: CURATOR_INIT",
|
|
47792
47832
|
`PRIOR_SUMMARY: ${priorSummary ? JSON.stringify(priorSummary) : "none"}`,
|
|
@@ -47794,7 +47834,7 @@ async function runCuratorInit(directory, config3, llmDelegate) {
|
|
|
47794
47834
|
`PROJECT_CONTEXT: ${contextMd?.slice(0, config3.max_summary_tokens * 2) ?? "none"}`
|
|
47795
47835
|
].join(`
|
|
47796
47836
|
`);
|
|
47797
|
-
const systemPrompt =
|
|
47837
|
+
const systemPrompt = CURATOR_INIT_PROMPT;
|
|
47798
47838
|
const llmOutput = await Promise.race([
|
|
47799
47839
|
llmDelegate(systemPrompt, userInput),
|
|
47800
47840
|
new Promise((_, reject) => setTimeout(() => reject(new Error("CURATOR_LLM_TIMEOUT")), CURATOR_LLM_TIMEOUT_MS))
|
|
@@ -47877,9 +47917,8 @@ async function runCuratorPhase(directory, phase, agentsDispatched, _config, _kno
|
|
|
47877
47917
|
let knowledgeRecommendations = [];
|
|
47878
47918
|
if (llmDelegate) {
|
|
47879
47919
|
try {
|
|
47880
|
-
const curatorAgent = createExplorerCuratorAgent("default", "CURATOR_PHASE");
|
|
47881
47920
|
const priorDigest = priorSummary?.digest ?? "none";
|
|
47882
|
-
const systemPrompt =
|
|
47921
|
+
const systemPrompt = CURATOR_PHASE_PROMPT;
|
|
47883
47922
|
const userInput = [
|
|
47884
47923
|
`TASK: CURATOR_PHASE ${phase}`,
|
|
47885
47924
|
`PRIOR_DIGEST: ${priorDigest}`,
|
|
@@ -52369,11 +52408,54 @@ function maskToolOutput(msg, _threshold) {
|
|
|
52369
52408
|
return freedTokens;
|
|
52370
52409
|
}
|
|
52371
52410
|
// src/hooks/curator-llm-factory.ts
|
|
52372
|
-
function
|
|
52411
|
+
function resolveCuratorAgentName(mode, sessionId) {
|
|
52412
|
+
const suffix = mode === "init" ? "curator_init" : "curator_phase";
|
|
52413
|
+
const registeredNames = mode === "init" ? swarmState.curatorInitAgentNames : swarmState.curatorPhaseAgentNames;
|
|
52414
|
+
if (registeredNames.length === 1)
|
|
52415
|
+
return registeredNames[0];
|
|
52416
|
+
if (registeredNames.length === 0)
|
|
52417
|
+
return suffix;
|
|
52418
|
+
const prefixMap = new Map;
|
|
52419
|
+
for (const name2 of registeredNames) {
|
|
52420
|
+
const prefix = name2.endsWith(suffix) ? name2.slice(0, name2.length - suffix.length) : "";
|
|
52421
|
+
prefixMap.set(prefix, name2);
|
|
52422
|
+
}
|
|
52423
|
+
const matchForAgent = (agentName) => {
|
|
52424
|
+
let bestPrefix = "";
|
|
52425
|
+
let bestName = "";
|
|
52426
|
+
for (const [prefix, name2] of prefixMap) {
|
|
52427
|
+
if (prefix && agentName.startsWith(prefix)) {
|
|
52428
|
+
if (prefix.length > bestPrefix.length) {
|
|
52429
|
+
bestPrefix = prefix;
|
|
52430
|
+
bestName = name2;
|
|
52431
|
+
}
|
|
52432
|
+
}
|
|
52433
|
+
}
|
|
52434
|
+
return bestName;
|
|
52435
|
+
};
|
|
52436
|
+
if (sessionId) {
|
|
52437
|
+
const callingAgent = swarmState.activeAgent.get(sessionId);
|
|
52438
|
+
if (callingAgent) {
|
|
52439
|
+
const match = matchForAgent(callingAgent);
|
|
52440
|
+
if (match)
|
|
52441
|
+
return match;
|
|
52442
|
+
const defaultCurator = prefixMap.get("");
|
|
52443
|
+
if (defaultCurator)
|
|
52444
|
+
return defaultCurator;
|
|
52445
|
+
}
|
|
52446
|
+
}
|
|
52447
|
+
for (const activeAgentName of swarmState.activeAgent.values()) {
|
|
52448
|
+
const match = matchForAgent(activeAgentName);
|
|
52449
|
+
if (match)
|
|
52450
|
+
return match;
|
|
52451
|
+
}
|
|
52452
|
+
return prefixMap.get("") ?? registeredNames[0];
|
|
52453
|
+
}
|
|
52454
|
+
function createCuratorLLMDelegate(directory, mode = "init", sessionId) {
|
|
52373
52455
|
const client = swarmState.opencodeClient;
|
|
52374
52456
|
if (!client)
|
|
52375
52457
|
return;
|
|
52376
|
-
return async (
|
|
52458
|
+
return async (_systemPrompt, userInput) => {
|
|
52377
52459
|
let ephemeralSessionId;
|
|
52378
52460
|
try {
|
|
52379
52461
|
const createResult = await client.session.create({
|
|
@@ -52383,10 +52465,11 @@ function createCuratorLLMDelegate(directory) {
|
|
|
52383
52465
|
throw new Error(`Failed to create curator session: ${JSON.stringify(createResult.error)}`);
|
|
52384
52466
|
}
|
|
52385
52467
|
ephemeralSessionId = createResult.data.id;
|
|
52468
|
+
const agentName = resolveCuratorAgentName(mode, sessionId);
|
|
52386
52469
|
const promptResult = await client.session.prompt({
|
|
52387
52470
|
path: { id: ephemeralSessionId },
|
|
52388
52471
|
body: {
|
|
52389
|
-
|
|
52472
|
+
agent: agentName,
|
|
52390
52473
|
tools: { write: false, edit: false, patch: false },
|
|
52391
52474
|
parts: [{ type: "text", text: userInput }]
|
|
52392
52475
|
}
|
|
@@ -54428,10 +54511,11 @@ init_schema();
|
|
|
54428
54511
|
init_manager2();
|
|
54429
54512
|
import * as path37 from "path";
|
|
54430
54513
|
init_utils2();
|
|
54431
|
-
function createPhaseMonitorHook(directory, preflightManager, curatorRunner,
|
|
54514
|
+
function createPhaseMonitorHook(directory, preflightManager, curatorRunner, delegateFactory) {
|
|
54432
54515
|
let lastKnownPhase = null;
|
|
54433
|
-
const handler = async (
|
|
54516
|
+
const handler = async (input, _output) => {
|
|
54434
54517
|
const runner = curatorRunner ?? runCuratorInit;
|
|
54518
|
+
const sessionId = typeof input === "object" && input !== null ? input.sessionID : undefined;
|
|
54435
54519
|
const plan = await loadPlan(directory);
|
|
54436
54520
|
if (!plan)
|
|
54437
54521
|
return;
|
|
@@ -54443,6 +54527,7 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner, llmD
|
|
|
54443
54527
|
const { config: config3 } = loadPluginConfigWithMeta2(directory);
|
|
54444
54528
|
const curatorConfig = CuratorConfigSchema.parse(config3.curator ?? {});
|
|
54445
54529
|
if (curatorConfig.enabled && curatorConfig.init_enabled) {
|
|
54530
|
+
const llmDelegate = delegateFactory?.(sessionId);
|
|
54446
54531
|
const initResult = await runner(directory, curatorConfig, llmDelegate);
|
|
54447
54532
|
if (initResult.briefing) {
|
|
54448
54533
|
const briefingPath = path37.join(directory, ".swarm", "curator-briefing.md");
|
|
@@ -59172,7 +59257,7 @@ var curator_analyze = createSwarmTool({
|
|
|
59172
59257
|
reason: tool.schema.string()
|
|
59173
59258
|
})).optional().describe("Knowledge recommendations to apply. If omitted, only collects digest data.")
|
|
59174
59259
|
},
|
|
59175
|
-
execute: async (args2, directory) => {
|
|
59260
|
+
execute: async (args2, directory, ctx) => {
|
|
59176
59261
|
const typedArgs = args2;
|
|
59177
59262
|
try {
|
|
59178
59263
|
if (!Number.isInteger(typedArgs.phase) || typedArgs.phase < 1) {
|
|
@@ -59191,7 +59276,7 @@ var curator_analyze = createSwarmTool({
|
|
|
59191
59276
|
const { config: config3 } = loadPluginConfigWithMeta(directory);
|
|
59192
59277
|
const curatorConfig = CuratorConfigSchema.parse(config3.curator ?? {});
|
|
59193
59278
|
const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
|
|
59194
|
-
const llmDelegate = createCuratorLLMDelegate(directory);
|
|
59279
|
+
const llmDelegate = createCuratorLLMDelegate(directory, "phase", ctx?.sessionID);
|
|
59195
59280
|
const curatorResult = await runCuratorPhase(directory, typedArgs.phase, [], curatorConfig, {}, llmDelegate);
|
|
59196
59281
|
{
|
|
59197
59282
|
const scopeContent = curatorResult.digest?.summary ?? `Phase ${typedArgs.phase} curator analysis`;
|
|
@@ -61755,7 +61840,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
61755
61840
|
try {
|
|
61756
61841
|
const curatorConfig = CuratorConfigSchema.parse(config3.curator ?? {});
|
|
61757
61842
|
if (curatorConfig.enabled && curatorConfig.phase_enabled) {
|
|
61758
|
-
const llmDelegate = createCuratorLLMDelegate(dir);
|
|
61843
|
+
const llmDelegate = createCuratorLLMDelegate(dir, "phase", sessionID ?? undefined);
|
|
61759
61844
|
const curatorResult = await runCuratorPhase(dir, phase, agentsDispatched, curatorConfig, {}, llmDelegate);
|
|
61760
61845
|
{
|
|
61761
61846
|
const scopeContent = curatorResult.digest?.summary ?? `Phase ${phase} curator analysis`;
|
|
@@ -68182,6 +68267,8 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
68182
68267
|
initTelemetry(ctx.directory);
|
|
68183
68268
|
const agents = getAgentConfigs(config3);
|
|
68184
68269
|
const agentDefinitions = createAgents(config3);
|
|
68270
|
+
swarmState.curatorInitAgentNames = Object.keys(agents).filter((k) => k === "curator_init" || k.endsWith("_curator_init"));
|
|
68271
|
+
swarmState.curatorPhaseAgentNames = Object.keys(agents).filter((k) => k === "curator_phase" || k.endsWith("_curator_phase"));
|
|
68185
68272
|
const pipelineHook = createPipelineTrackerHook(config3, ctx.directory);
|
|
68186
68273
|
const systemEnhancerHook = createSystemEnhancerHook(config3, ctx.directory);
|
|
68187
68274
|
const compactionHook = createCompactionCustomizerHook(config3, ctx.directory);
|
|
@@ -68620,7 +68707,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
68620
68707
|
} catch {}
|
|
68621
68708
|
return Promise.resolve();
|
|
68622
68709
|
},
|
|
68623
|
-
automationConfig.capabilities?.phase_preflight === true && preflightTriggerManager ? createPhaseMonitorHook(ctx.directory, preflightTriggerManager, undefined, createCuratorLLMDelegate(ctx.directory)) : knowledgeConfig.enabled ? createPhaseMonitorHook(ctx.directory, undefined, undefined, createCuratorLLMDelegate(ctx.directory)) : undefined
|
|
68710
|
+
automationConfig.capabilities?.phase_preflight === true && preflightTriggerManager ? createPhaseMonitorHook(ctx.directory, preflightTriggerManager, undefined, (sessionId) => createCuratorLLMDelegate(ctx.directory, "init", sessionId)) : knowledgeConfig.enabled ? createPhaseMonitorHook(ctx.directory, undefined, undefined, (sessionId) => createCuratorLLMDelegate(ctx.directory, "init", sessionId)) : undefined
|
|
68624
68711
|
].filter(Boolean)),
|
|
68625
68712
|
"experimental.session.compacting": compactionHook["experimental.session.compacting"],
|
|
68626
68713
|
"command.execute.before": safeHook(commandHandler),
|
package/dist/state.d.ts
CHANGED
|
@@ -190,6 +190,13 @@ export declare const swarmState: {
|
|
|
190
190
|
pendingEvents: number;
|
|
191
191
|
/** SDK client — set at plugin init for curator LLM delegation */
|
|
192
192
|
opencodeClient: OpencodeClient | null;
|
|
193
|
+
/** All registered curator agent names across all swarms (with their swarm prefix).
|
|
194
|
+
* e.g. ['curator_init'] for a single default swarm, or
|
|
195
|
+
* ['swarm1_curator_init', 'swarm2_curator_init', ...] for multiple named swarms.
|
|
196
|
+
* Set at plugin init after agents are built. The factory resolves the correct
|
|
197
|
+
* name at call time by matching the active session's agent prefix. */
|
|
198
|
+
curatorInitAgentNames: string[];
|
|
199
|
+
curatorPhaseAgentNames: string[];
|
|
193
200
|
/** Last known context budget percentage (0-100), updated by system-enhancer */
|
|
194
201
|
lastBudgetPct: number;
|
|
195
202
|
/** Per-session guardrail state — keyed by sessionID */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.43.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",
|