opencode-swarm-plugin 0.32.0 → 0.33.0
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/.turbo/turbo-build.log +9 -10
- package/.turbo/turbo-test.log +347 -341
- package/CHANGELOG.md +260 -0
- package/README.md +127 -182
- package/bin/swarm.test.ts +31 -0
- package/bin/swarm.ts +247 -12
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +530 -5
- package/dist/observability-tools.d.ts +116 -0
- package/dist/observability-tools.d.ts.map +1 -0
- package/dist/plugin.js +530 -5
- package/dist/skills.d.ts.map +1 -1
- package/dist/swarm-prompts.d.ts +59 -0
- package/dist/swarm-prompts.d.ts.map +1 -1
- package/dist/swarm.d.ts +17 -0
- package/dist/swarm.d.ts.map +1 -1
- package/examples/plugin-wrapper-template.ts +297 -8
- package/package.json +3 -2
- package/src/index.ts +25 -1
- package/src/observability-tools.test.ts +346 -0
- package/src/observability-tools.ts +594 -0
- package/src/skills.integration.test.ts +137 -1
- package/src/skills.test.ts +42 -1
- package/src/skills.ts +8 -4
- package/src/swarm-orchestrate.test.ts +123 -0
- package/src/swarm-orchestrate.ts +183 -0
- package/src/swarm-prompts.test.ts +389 -0
- package/src/swarm-prompts.ts +228 -0
- package/src/swarm-research.integration.test.ts +544 -0
- package/src/swarm-research.test.ts +698 -0
- package/src/swarm-research.ts +472 -0
- package/src/swarm.ts +6 -3
package/dist/plugin.js
CHANGED
|
@@ -26558,7 +26558,7 @@ var init_skills = __esm(() => {
|
|
|
26558
26558
|
"skills"
|
|
26559
26559
|
];
|
|
26560
26560
|
skills_list = tool({
|
|
26561
|
-
description: `List all available skills in the project.
|
|
26561
|
+
description: `[DEPRECATED] List all available skills in the project.
|
|
26562
26562
|
|
|
26563
26563
|
Skills are specialized instructions that help with specific domains or tasks.
|
|
26564
26564
|
Use this tool to discover what skills are available, then use skills_use to
|
|
@@ -26569,6 +26569,7 @@ Returns skill names, descriptions, and whether they have executable scripts.`,
|
|
|
26569
26569
|
tag: tool.schema.string().optional().describe("Optional tag to filter skills by")
|
|
26570
26570
|
},
|
|
26571
26571
|
async execute(args) {
|
|
26572
|
+
console.warn("[DEPRECATED] skills_list is deprecated. OpenCode now provides native skills support. This tool will be removed in a future version.");
|
|
26572
26573
|
const skills = await discoverSkills();
|
|
26573
26574
|
let refs = Array.from(skills.values());
|
|
26574
26575
|
if (args.tag) {
|
|
@@ -26591,7 +26592,7 @@ ${formatted}`;
|
|
|
26591
26592
|
}
|
|
26592
26593
|
});
|
|
26593
26594
|
skills_use = tool({
|
|
26594
|
-
description: `Activate a skill by loading its full instructions.
|
|
26595
|
+
description: `[DEPRECATED] Activate a skill by loading its full instructions.
|
|
26595
26596
|
|
|
26596
26597
|
After calling this tool, follow the skill's instructions for the current task.
|
|
26597
26598
|
Skills provide domain-specific guidance and best practices.
|
|
@@ -26602,6 +26603,7 @@ If the skill has scripts, you can run them with skills_execute.`,
|
|
|
26602
26603
|
include_scripts: tool.schema.boolean().optional().describe("Also list available scripts (default: true)")
|
|
26603
26604
|
},
|
|
26604
26605
|
async execute(args) {
|
|
26606
|
+
console.warn("[DEPRECATED] skills_use is deprecated. OpenCode now provides native skills support. This tool will be removed in a future version.");
|
|
26605
26607
|
const skill = await getSkill(args.name);
|
|
26606
26608
|
if (!skill) {
|
|
26607
26609
|
const available = await listSkills();
|
|
@@ -26634,7 +26636,7 @@ Run scripts with skills_execute tool.`;
|
|
|
26634
26636
|
}
|
|
26635
26637
|
});
|
|
26636
26638
|
skills_execute = tool({
|
|
26637
|
-
description: `Execute a script from a skill's scripts/ directory.
|
|
26639
|
+
description: `[DEPRECATED] Execute a script from a skill's scripts/ directory.
|
|
26638
26640
|
|
|
26639
26641
|
Some skills include helper scripts for common operations.
|
|
26640
26642
|
Use skills_use first to see available scripts, then execute them here.
|
|
@@ -26646,6 +26648,7 @@ Scripts run in the skill's directory with the project directory as an argument.`
|
|
|
26646
26648
|
args: tool.schema.array(tool.schema.string()).optional().describe("Additional arguments to pass to the script")
|
|
26647
26649
|
},
|
|
26648
26650
|
async execute(args, ctx) {
|
|
26651
|
+
console.warn("[DEPRECATED] skills_execute is deprecated. OpenCode now provides native skills support. This tool will be removed in a future version.");
|
|
26649
26652
|
const skill = await getSkill(args.skill);
|
|
26650
26653
|
if (!skill) {
|
|
26651
26654
|
return `Skill '${args.skill}' not found.`;
|
|
@@ -26691,7 +26694,7 @@ ${output}`;
|
|
|
26691
26694
|
}
|
|
26692
26695
|
});
|
|
26693
26696
|
skills_read = tool({
|
|
26694
|
-
description: `Read a resource file from a skill's directory.
|
|
26697
|
+
description: `[DEPRECATED] Read a resource file from a skill's directory.
|
|
26695
26698
|
|
|
26696
26699
|
Skills may include additional files like:
|
|
26697
26700
|
- examples.md - Example usage
|
|
@@ -26704,6 +26707,7 @@ Use this to access supplementary skill resources.`,
|
|
|
26704
26707
|
file: tool.schema.string().describe("Relative path to the file within the skill directory")
|
|
26705
26708
|
},
|
|
26706
26709
|
async execute(args) {
|
|
26710
|
+
console.warn("[DEPRECATED] skills_read is deprecated. OpenCode now provides native skills support. This tool will be removed in a future version.");
|
|
26707
26711
|
const skill = await getSkill(args.skill);
|
|
26708
26712
|
if (!skill) {
|
|
26709
26713
|
return `Skill '${args.skill}' not found.`;
|
|
@@ -35144,6 +35148,115 @@ Other cell operations:
|
|
|
35144
35148
|
**Memory is the swarm's collective intelligence. Query it. Feed it.**
|
|
35145
35149
|
|
|
35146
35150
|
Begin now.`;
|
|
35151
|
+
var RESEARCHER_PROMPT = `You are a swarm researcher gathering documentation for: **{research_id}**
|
|
35152
|
+
|
|
35153
|
+
## [IDENTITY]
|
|
35154
|
+
Agent: (assigned at spawn)
|
|
35155
|
+
Research Task: {research_id}
|
|
35156
|
+
Epic: {epic_id}
|
|
35157
|
+
|
|
35158
|
+
## [MISSION]
|
|
35159
|
+
Gather comprehensive documentation for the specified technologies to inform task decomposition.
|
|
35160
|
+
|
|
35161
|
+
**COORDINATOR PROVIDED THESE TECHNOLOGIES TO RESEARCH:**
|
|
35162
|
+
{tech_stack}
|
|
35163
|
+
|
|
35164
|
+
You do NOT discover what to research - the coordinator already decided that.
|
|
35165
|
+
You DO discover what TOOLS are available to fetch documentation.
|
|
35166
|
+
|
|
35167
|
+
## [OUTPUT MODE]
|
|
35168
|
+
{check_upgrades}
|
|
35169
|
+
|
|
35170
|
+
## [WORKFLOW]
|
|
35171
|
+
|
|
35172
|
+
### Step 1: Initialize (MANDATORY FIRST)
|
|
35173
|
+
\`\`\`
|
|
35174
|
+
swarmmail_init(project_path="{project_path}", task_description="{research_id}: Documentation research")
|
|
35175
|
+
\`\`\`
|
|
35176
|
+
|
|
35177
|
+
### Step 2: Discover Available Documentation Tools
|
|
35178
|
+
Check what's available for fetching docs:
|
|
35179
|
+
- **next-devtools**: \`nextjs_docs\` for Next.js documentation
|
|
35180
|
+
- **context7**: Library documentation lookup (\`use context7\` in prompts)
|
|
35181
|
+
- **fetch**: General web fetching for official docs sites
|
|
35182
|
+
- **pdf-brain**: Internal knowledge base search
|
|
35183
|
+
|
|
35184
|
+
**Don't assume** - check which tools exist in your environment.
|
|
35185
|
+
|
|
35186
|
+
### Step 3: Read Installed Versions
|
|
35187
|
+
For each technology in the tech stack:
|
|
35188
|
+
1. Check package.json (or equivalent) for installed version
|
|
35189
|
+
2. Record exact version numbers
|
|
35190
|
+
3. Note any version constraints (^, ~, etc.)
|
|
35191
|
+
|
|
35192
|
+
### Step 4: Fetch Documentation
|
|
35193
|
+
For EACH technology in the list:
|
|
35194
|
+
- Use the most appropriate tool (Next.js → nextjs_docs, libraries → context7, others → fetch)
|
|
35195
|
+
- Fetch documentation for the INSTALLED version (not latest, unless --check-upgrades)
|
|
35196
|
+
- Focus on: API changes, breaking changes, migration guides, best practices
|
|
35197
|
+
- Extract key patterns, gotchas, and compatibility notes
|
|
35198
|
+
|
|
35199
|
+
**If --check-upgrades mode:**
|
|
35200
|
+
- ALSO fetch docs for the LATEST version
|
|
35201
|
+
- Compare installed vs latest
|
|
35202
|
+
- Note breaking changes, new features, migration complexity
|
|
35203
|
+
|
|
35204
|
+
### Step 5: Store Detailed Findings
|
|
35205
|
+
For EACH technology, store in semantic-memory:
|
|
35206
|
+
\`\`\`
|
|
35207
|
+
semantic-memory_store(
|
|
35208
|
+
information="<technology-name> <version>: <key patterns, gotchas, API changes, compatibility notes>",
|
|
35209
|
+
tags="research, <tech-name>, documentation, {epic_id}"
|
|
35210
|
+
)
|
|
35211
|
+
\`\`\`
|
|
35212
|
+
|
|
35213
|
+
**Why store individually?** Future agents can search by technology name.
|
|
35214
|
+
|
|
35215
|
+
### Step 6: Broadcast Summary
|
|
35216
|
+
Send condensed findings to coordinator:
|
|
35217
|
+
\`\`\`
|
|
35218
|
+
swarmmail_send(
|
|
35219
|
+
to=["coordinator"],
|
|
35220
|
+
subject="Research Complete: {research_id}",
|
|
35221
|
+
body="<brief summary - see semantic-memory for details>",
|
|
35222
|
+
thread_id="{epic_id}"
|
|
35223
|
+
)
|
|
35224
|
+
\`\`\`
|
|
35225
|
+
|
|
35226
|
+
### Step 7: Return Structured Output
|
|
35227
|
+
Output JSON with:
|
|
35228
|
+
\`\`\`json
|
|
35229
|
+
{
|
|
35230
|
+
"technologies": [
|
|
35231
|
+
{
|
|
35232
|
+
"name": "string",
|
|
35233
|
+
"installed_version": "string",
|
|
35234
|
+
"latest_version": "string | null", // Only if --check-upgrades
|
|
35235
|
+
"key_patterns": ["string"],
|
|
35236
|
+
"gotchas": ["string"],
|
|
35237
|
+
"breaking_changes": ["string"], // Only if --check-upgrades
|
|
35238
|
+
"memory_id": "string" // ID of semantic-memory entry
|
|
35239
|
+
}
|
|
35240
|
+
],
|
|
35241
|
+
"summary": "string" // Condensed summary for shared_context
|
|
35242
|
+
}
|
|
35243
|
+
\`\`\`
|
|
35244
|
+
|
|
35245
|
+
## [CRITICAL REQUIREMENTS]
|
|
35246
|
+
|
|
35247
|
+
**NON-NEGOTIABLE:**
|
|
35248
|
+
1. Step 1 (swarmmail_init) MUST be first
|
|
35249
|
+
2. Research ONLY the technologies the coordinator specified
|
|
35250
|
+
3. Fetch docs for INSTALLED versions (unless --check-upgrades)
|
|
35251
|
+
4. Store detailed findings in semantic-memory (one per technology)
|
|
35252
|
+
5. Return condensed summary for coordinator (full details in memory)
|
|
35253
|
+
6. Use appropriate doc tools (nextjs_docs for Next.js, context7 for libraries, etc.)
|
|
35254
|
+
|
|
35255
|
+
**Output goes TWO places:**
|
|
35256
|
+
- **semantic-memory**: Detailed findings (searchable by future agents)
|
|
35257
|
+
- **Return JSON**: Condensed summary (for coordinator's shared_context)
|
|
35258
|
+
|
|
35259
|
+
Begin research now.`;
|
|
35147
35260
|
var COORDINATOR_POST_WORKER_CHECKLIST = `
|
|
35148
35261
|
## ⚠️ MANDATORY: Post-Worker Review (DO THIS IMMEDIATELY)
|
|
35149
35262
|
|
|
@@ -35232,6 +35345,12 @@ For each criterion, assess passed/failed and provide brief feedback:
|
|
|
35232
35345
|
|
|
35233
35346
|
If any criterion fails, the overall evaluation fails and retry_suggestion
|
|
35234
35347
|
should describe what needs to be fixed.`;
|
|
35348
|
+
function formatResearcherPrompt(params) {
|
|
35349
|
+
const techList = params.tech_stack.map((t) => `- ${t}`).join(`
|
|
35350
|
+
`);
|
|
35351
|
+
const upgradesMode = params.check_upgrades ? "**UPGRADE COMPARISON MODE**: Fetch docs for BOTH installed AND latest versions. Compare and note breaking changes." : "**DEFAULT MODE**: Fetch docs for INSTALLED versions only (from lockfiles).";
|
|
35352
|
+
return RESEARCHER_PROMPT.replace(/{research_id}/g, params.research_id).replace(/{epic_id}/g, params.epic_id).replace("{tech_stack}", techList).replace("{project_path}", params.project_path).replace("{check_upgrades}", upgradesMode);
|
|
35353
|
+
}
|
|
35235
35354
|
function formatSubtaskPromptV2(params) {
|
|
35236
35355
|
const fileList = params.files.length > 0 ? params.files.map((f) => `- \`${f}\``).join(`
|
|
35237
35356
|
`) : "(no specific files - use judgment)";
|
|
@@ -35381,6 +35500,48 @@ var swarm_spawn_subtask = tool({
|
|
|
35381
35500
|
}, null, 2);
|
|
35382
35501
|
}
|
|
35383
35502
|
});
|
|
35503
|
+
var swarm_spawn_researcher = tool({
|
|
35504
|
+
description: "Prepare a research task for spawning. Returns prompt for gathering technology documentation. Researcher fetches docs and stores findings in semantic-memory.",
|
|
35505
|
+
args: {
|
|
35506
|
+
research_id: tool.schema.string().describe("Unique ID for this research task"),
|
|
35507
|
+
epic_id: tool.schema.string().describe("Parent epic ID"),
|
|
35508
|
+
tech_stack: tool.schema.array(tool.schema.string()).describe("Explicit list of technologies to research (from coordinator)"),
|
|
35509
|
+
project_path: tool.schema.string().describe("Absolute project path for swarmmail_init"),
|
|
35510
|
+
check_upgrades: tool.schema.boolean().optional().describe("If true, compare installed vs latest versions (default: false)")
|
|
35511
|
+
},
|
|
35512
|
+
async execute(args) {
|
|
35513
|
+
const prompt = formatResearcherPrompt({
|
|
35514
|
+
research_id: args.research_id,
|
|
35515
|
+
epic_id: args.epic_id,
|
|
35516
|
+
tech_stack: args.tech_stack,
|
|
35517
|
+
project_path: args.project_path,
|
|
35518
|
+
check_upgrades: args.check_upgrades ?? false
|
|
35519
|
+
});
|
|
35520
|
+
return JSON.stringify({
|
|
35521
|
+
prompt,
|
|
35522
|
+
research_id: args.research_id,
|
|
35523
|
+
epic_id: args.epic_id,
|
|
35524
|
+
tech_stack: args.tech_stack,
|
|
35525
|
+
project_path: args.project_path,
|
|
35526
|
+
check_upgrades: args.check_upgrades ?? false,
|
|
35527
|
+
subagent_type: "swarm/researcher",
|
|
35528
|
+
expected_output: {
|
|
35529
|
+
technologies: [
|
|
35530
|
+
{
|
|
35531
|
+
name: "string",
|
|
35532
|
+
installed_version: "string",
|
|
35533
|
+
latest_version: "string | null",
|
|
35534
|
+
key_patterns: ["string"],
|
|
35535
|
+
gotchas: ["string"],
|
|
35536
|
+
breaking_changes: ["string"],
|
|
35537
|
+
memory_id: "string"
|
|
35538
|
+
}
|
|
35539
|
+
],
|
|
35540
|
+
summary: "string"
|
|
35541
|
+
}
|
|
35542
|
+
}, null, 2);
|
|
35543
|
+
}
|
|
35544
|
+
});
|
|
35384
35545
|
var swarm_evaluation_prompt = tool({
|
|
35385
35546
|
description: "Generate self-evaluation prompt for a completed subtask",
|
|
35386
35547
|
args: {
|
|
@@ -35492,6 +35653,7 @@ ${args.context}` : `## Additional Context
|
|
|
35492
35653
|
var promptTools = {
|
|
35493
35654
|
swarm_subtask_prompt,
|
|
35494
35655
|
swarm_spawn_subtask,
|
|
35656
|
+
swarm_spawn_researcher,
|
|
35495
35657
|
swarm_evaluation_prompt,
|
|
35496
35658
|
swarm_plan_prompt
|
|
35497
35659
|
};
|
|
@@ -50255,6 +50417,368 @@ var memoryTools = {
|
|
|
50255
50417
|
"semantic-memory_check": semantic_memory_check
|
|
50256
50418
|
};
|
|
50257
50419
|
|
|
50420
|
+
// src/observability-tools.ts
|
|
50421
|
+
init_dist();
|
|
50422
|
+
import {
|
|
50423
|
+
agentActivity,
|
|
50424
|
+
checkpointFrequency,
|
|
50425
|
+
failedDecompositions,
|
|
50426
|
+
getSwarmMailLibSQL as getSwarmMailLibSQL4,
|
|
50427
|
+
humanFeedback,
|
|
50428
|
+
lockContention,
|
|
50429
|
+
messageLatency,
|
|
50430
|
+
recoverySuccess,
|
|
50431
|
+
scopeViolations,
|
|
50432
|
+
strategySuccessRates,
|
|
50433
|
+
taskDuration
|
|
50434
|
+
} from "swarm-mail";
|
|
50435
|
+
function parseSince(since) {
|
|
50436
|
+
const now = Date.now();
|
|
50437
|
+
const match11 = since.match(/^(\d+)([dhm])$/);
|
|
50438
|
+
if (!match11) {
|
|
50439
|
+
throw new Error(`Invalid since format: ${since}. Use "7d", "24h", or "1h"`);
|
|
50440
|
+
}
|
|
50441
|
+
const [, value, unit] = match11;
|
|
50442
|
+
const num = Number.parseInt(value, 10);
|
|
50443
|
+
switch (unit) {
|
|
50444
|
+
case "d":
|
|
50445
|
+
return now - num * 24 * 60 * 60 * 1000;
|
|
50446
|
+
case "h":
|
|
50447
|
+
return now - num * 60 * 60 * 1000;
|
|
50448
|
+
case "m":
|
|
50449
|
+
return now - num * 60 * 1000;
|
|
50450
|
+
default:
|
|
50451
|
+
throw new Error(`Unknown unit: ${unit}`);
|
|
50452
|
+
}
|
|
50453
|
+
}
|
|
50454
|
+
async function executeQuery(swarmMail, query) {
|
|
50455
|
+
const db = await swarmMail.getDatabase();
|
|
50456
|
+
const result = await db.query(query.sql, Object.values(query.parameters || {}));
|
|
50457
|
+
return result.rows;
|
|
50458
|
+
}
|
|
50459
|
+
function formatSummary(queryType, results) {
|
|
50460
|
+
if (results.length === 0) {
|
|
50461
|
+
return `No ${queryType} data found.`;
|
|
50462
|
+
}
|
|
50463
|
+
const count = results.length;
|
|
50464
|
+
const preview = results.slice(0, 3);
|
|
50465
|
+
return `${queryType}: ${count} result(s). Top 3: ${JSON.stringify(preview, null, 2).slice(0, 400)}`;
|
|
50466
|
+
}
|
|
50467
|
+
function capResults(results) {
|
|
50468
|
+
return results.slice(0, 50);
|
|
50469
|
+
}
|
|
50470
|
+
var swarm_analytics = tool({
|
|
50471
|
+
description: "Query pre-built analytics for swarm coordination. Returns structured data about failed decompositions, strategy success rates, lock contention, agent activity, message latency, scope violations, task duration, checkpoint frequency, recovery success, and human feedback.",
|
|
50472
|
+
args: {
|
|
50473
|
+
query: tool.schema.enum([
|
|
50474
|
+
"failed-decompositions",
|
|
50475
|
+
"strategy-success-rates",
|
|
50476
|
+
"lock-contention",
|
|
50477
|
+
"agent-activity",
|
|
50478
|
+
"message-latency",
|
|
50479
|
+
"scope-violations",
|
|
50480
|
+
"task-duration",
|
|
50481
|
+
"checkpoint-frequency",
|
|
50482
|
+
"recovery-success",
|
|
50483
|
+
"human-feedback"
|
|
50484
|
+
]).describe("Type of analytics query to run"),
|
|
50485
|
+
since: tool.schema.string().optional().describe("Time filter: '7d', '24h', '1h' (optional)"),
|
|
50486
|
+
format: tool.schema.enum(["json", "summary"]).optional().describe("Output format: 'json' (default) or 'summary' (context-efficient)")
|
|
50487
|
+
},
|
|
50488
|
+
async execute(args2) {
|
|
50489
|
+
try {
|
|
50490
|
+
const projectPath = process.cwd();
|
|
50491
|
+
const db = await getSwarmMailLibSQL4(projectPath);
|
|
50492
|
+
const filters = {
|
|
50493
|
+
project_key: projectPath
|
|
50494
|
+
};
|
|
50495
|
+
if (args2.since) {
|
|
50496
|
+
filters.since = parseSince(args2.since);
|
|
50497
|
+
}
|
|
50498
|
+
let query;
|
|
50499
|
+
switch (args2.query) {
|
|
50500
|
+
case "failed-decompositions":
|
|
50501
|
+
query = failedDecompositions(filters);
|
|
50502
|
+
break;
|
|
50503
|
+
case "strategy-success-rates":
|
|
50504
|
+
query = strategySuccessRates(filters);
|
|
50505
|
+
break;
|
|
50506
|
+
case "lock-contention":
|
|
50507
|
+
query = lockContention(filters);
|
|
50508
|
+
break;
|
|
50509
|
+
case "agent-activity":
|
|
50510
|
+
query = agentActivity(filters);
|
|
50511
|
+
break;
|
|
50512
|
+
case "message-latency":
|
|
50513
|
+
query = messageLatency(filters);
|
|
50514
|
+
break;
|
|
50515
|
+
case "scope-violations":
|
|
50516
|
+
query = scopeViolations.buildQuery ? scopeViolations.buildQuery(filters) : scopeViolations;
|
|
50517
|
+
break;
|
|
50518
|
+
case "task-duration":
|
|
50519
|
+
query = taskDuration.buildQuery ? taskDuration.buildQuery(filters) : taskDuration;
|
|
50520
|
+
break;
|
|
50521
|
+
case "checkpoint-frequency":
|
|
50522
|
+
query = checkpointFrequency.buildQuery ? checkpointFrequency.buildQuery(filters) : checkpointFrequency;
|
|
50523
|
+
break;
|
|
50524
|
+
case "recovery-success":
|
|
50525
|
+
query = recoverySuccess.buildQuery ? recoverySuccess.buildQuery(filters) : recoverySuccess;
|
|
50526
|
+
break;
|
|
50527
|
+
case "human-feedback":
|
|
50528
|
+
query = humanFeedback.buildQuery ? humanFeedback.buildQuery(filters) : humanFeedback;
|
|
50529
|
+
break;
|
|
50530
|
+
default:
|
|
50531
|
+
return JSON.stringify({
|
|
50532
|
+
error: `Unknown query type: ${args2.query}`
|
|
50533
|
+
});
|
|
50534
|
+
}
|
|
50535
|
+
const results = await executeQuery(db, query);
|
|
50536
|
+
if (args2.format === "summary") {
|
|
50537
|
+
return formatSummary(args2.query, results);
|
|
50538
|
+
}
|
|
50539
|
+
return JSON.stringify({
|
|
50540
|
+
query: args2.query,
|
|
50541
|
+
filters,
|
|
50542
|
+
count: results.length,
|
|
50543
|
+
results
|
|
50544
|
+
}, null, 2);
|
|
50545
|
+
} catch (error45) {
|
|
50546
|
+
return JSON.stringify({
|
|
50547
|
+
error: error45 instanceof Error ? error45.message : String(error45)
|
|
50548
|
+
});
|
|
50549
|
+
}
|
|
50550
|
+
}
|
|
50551
|
+
});
|
|
50552
|
+
var swarm_query = tool({
|
|
50553
|
+
description: "Execute raw SQL queries against the swarm event store. Context-safe: results capped at 50 rows. Useful for custom analytics and debugging.",
|
|
50554
|
+
args: {
|
|
50555
|
+
sql: tool.schema.string().describe("SQL query to execute (SELECT only for safety)"),
|
|
50556
|
+
format: tool.schema.enum(["json", "table"]).optional().describe("Output format: 'json' (default) or 'table' (visual)")
|
|
50557
|
+
},
|
|
50558
|
+
async execute(args2) {
|
|
50559
|
+
try {
|
|
50560
|
+
const projectPath = process.cwd();
|
|
50561
|
+
const swarmMail = await getSwarmMailLibSQL4(projectPath);
|
|
50562
|
+
const db = await swarmMail.getDatabase();
|
|
50563
|
+
if (!args2.sql.trim().toLowerCase().startsWith("select")) {
|
|
50564
|
+
return JSON.stringify({
|
|
50565
|
+
error: "Only SELECT queries are allowed for safety"
|
|
50566
|
+
});
|
|
50567
|
+
}
|
|
50568
|
+
const result = await db.query(args2.sql, []);
|
|
50569
|
+
const rows = result.rows;
|
|
50570
|
+
const cappedRows = capResults(rows);
|
|
50571
|
+
if (args2.format === "table") {
|
|
50572
|
+
if (cappedRows.length === 0) {
|
|
50573
|
+
return "No results";
|
|
50574
|
+
}
|
|
50575
|
+
const headers = Object.keys(cappedRows[0]);
|
|
50576
|
+
const headerRow = headers.join(" | ");
|
|
50577
|
+
const separator = headers.map(() => "---").join(" | ");
|
|
50578
|
+
const dataRows = cappedRows.map((row) => headers.map((h) => row[h]).join(" | "));
|
|
50579
|
+
return [headerRow, separator, ...dataRows].join(`
|
|
50580
|
+
`);
|
|
50581
|
+
}
|
|
50582
|
+
return JSON.stringify({
|
|
50583
|
+
count: cappedRows.length,
|
|
50584
|
+
total: rows.length,
|
|
50585
|
+
capped: rows.length > 50,
|
|
50586
|
+
results: cappedRows
|
|
50587
|
+
}, null, 2);
|
|
50588
|
+
} catch (error45) {
|
|
50589
|
+
return JSON.stringify({
|
|
50590
|
+
error: error45 instanceof Error ? error45.message : String(error45)
|
|
50591
|
+
});
|
|
50592
|
+
}
|
|
50593
|
+
}
|
|
50594
|
+
});
|
|
50595
|
+
var swarm_diagnose = tool({
|
|
50596
|
+
description: "Auto-diagnose issues for a specific epic or task. Returns structured diagnosis with blockers, conflicts, slow tasks, errors, and timeline.",
|
|
50597
|
+
args: {
|
|
50598
|
+
epic_id: tool.schema.string().optional().describe("Epic ID to diagnose"),
|
|
50599
|
+
bead_id: tool.schema.string().optional().describe("Task ID to diagnose"),
|
|
50600
|
+
include: tool.schema.array(tool.schema.enum([
|
|
50601
|
+
"blockers",
|
|
50602
|
+
"conflicts",
|
|
50603
|
+
"slow_tasks",
|
|
50604
|
+
"errors",
|
|
50605
|
+
"timeline"
|
|
50606
|
+
])).optional().describe("What to include in diagnosis (default: all)")
|
|
50607
|
+
},
|
|
50608
|
+
async execute(args2) {
|
|
50609
|
+
try {
|
|
50610
|
+
const projectPath = process.cwd();
|
|
50611
|
+
const swarmMail = await getSwarmMailLibSQL4(projectPath);
|
|
50612
|
+
const db = await swarmMail.getDatabase();
|
|
50613
|
+
const diagnosis = [];
|
|
50614
|
+
const include = args2.include || [
|
|
50615
|
+
"blockers",
|
|
50616
|
+
"conflicts",
|
|
50617
|
+
"slow_tasks",
|
|
50618
|
+
"errors",
|
|
50619
|
+
"timeline"
|
|
50620
|
+
];
|
|
50621
|
+
if (include.includes("blockers")) {
|
|
50622
|
+
const blockerQuery = `
|
|
50623
|
+
SELECT json_extract(data, '$.agent_name') as agent,
|
|
50624
|
+
json_extract(data, '$.bead_id') as bead_id,
|
|
50625
|
+
timestamp
|
|
50626
|
+
FROM events
|
|
50627
|
+
WHERE type = 'task_blocked'
|
|
50628
|
+
${args2.epic_id ? "AND json_extract(data, '$.epic_id') = ?" : ""}
|
|
50629
|
+
${args2.bead_id ? "AND json_extract(data, '$.bead_id') = ?" : ""}
|
|
50630
|
+
ORDER BY timestamp DESC
|
|
50631
|
+
LIMIT 10
|
|
50632
|
+
`;
|
|
50633
|
+
const params = [];
|
|
50634
|
+
if (args2.epic_id)
|
|
50635
|
+
params.push(args2.epic_id);
|
|
50636
|
+
if (args2.bead_id)
|
|
50637
|
+
params.push(args2.bead_id);
|
|
50638
|
+
const blockers = await db.query(blockerQuery, params);
|
|
50639
|
+
if (blockers.rows.length > 0) {
|
|
50640
|
+
diagnosis.push({
|
|
50641
|
+
type: "blockers",
|
|
50642
|
+
message: `Found ${blockers.rows.length} blocked task(s)`,
|
|
50643
|
+
severity: "high"
|
|
50644
|
+
});
|
|
50645
|
+
}
|
|
50646
|
+
}
|
|
50647
|
+
if (include.includes("errors")) {
|
|
50648
|
+
const errorQuery = `
|
|
50649
|
+
SELECT type, json_extract(data, '$.error_count') as error_count
|
|
50650
|
+
FROM events
|
|
50651
|
+
WHERE type = 'subtask_outcome'
|
|
50652
|
+
AND json_extract(data, '$.success') = 'false'
|
|
50653
|
+
${args2.epic_id ? "AND json_extract(data, '$.epic_id') = ?" : ""}
|
|
50654
|
+
${args2.bead_id ? "AND json_extract(data, '$.bead_id') = ?" : ""}
|
|
50655
|
+
LIMIT 10
|
|
50656
|
+
`;
|
|
50657
|
+
const params = [];
|
|
50658
|
+
if (args2.epic_id)
|
|
50659
|
+
params.push(args2.epic_id);
|
|
50660
|
+
if (args2.bead_id)
|
|
50661
|
+
params.push(args2.bead_id);
|
|
50662
|
+
const errors3 = await db.query(errorQuery, params);
|
|
50663
|
+
if (errors3.rows.length > 0) {
|
|
50664
|
+
diagnosis.push({
|
|
50665
|
+
type: "errors",
|
|
50666
|
+
message: `Found ${errors3.rows.length} failed task(s)`,
|
|
50667
|
+
severity: "high"
|
|
50668
|
+
});
|
|
50669
|
+
}
|
|
50670
|
+
}
|
|
50671
|
+
let timeline = [];
|
|
50672
|
+
if (include.includes("timeline")) {
|
|
50673
|
+
const timelineQuery = `
|
|
50674
|
+
SELECT timestamp, type, json_extract(data, '$.agent_name') as agent
|
|
50675
|
+
FROM events
|
|
50676
|
+
${args2.epic_id ? "WHERE json_extract(data, '$.epic_id') = ?" : ""}
|
|
50677
|
+
${args2.bead_id ? (args2.epic_id ? "AND" : "WHERE") + " json_extract(data, '$.bead_id') = ?" : ""}
|
|
50678
|
+
ORDER BY timestamp DESC
|
|
50679
|
+
LIMIT 20
|
|
50680
|
+
`;
|
|
50681
|
+
const params = [];
|
|
50682
|
+
if (args2.epic_id)
|
|
50683
|
+
params.push(args2.epic_id);
|
|
50684
|
+
if (args2.bead_id)
|
|
50685
|
+
params.push(args2.bead_id);
|
|
50686
|
+
const events = await db.query(timelineQuery, params);
|
|
50687
|
+
timeline = events.rows;
|
|
50688
|
+
}
|
|
50689
|
+
return JSON.stringify({
|
|
50690
|
+
epic_id: args2.epic_id,
|
|
50691
|
+
bead_id: args2.bead_id,
|
|
50692
|
+
diagnosis,
|
|
50693
|
+
timeline: include.includes("timeline") ? timeline : undefined
|
|
50694
|
+
}, null, 2);
|
|
50695
|
+
} catch (error45) {
|
|
50696
|
+
return JSON.stringify({
|
|
50697
|
+
error: error45 instanceof Error ? error45.message : String(error45)
|
|
50698
|
+
});
|
|
50699
|
+
}
|
|
50700
|
+
}
|
|
50701
|
+
});
|
|
50702
|
+
var swarm_insights = tool({
|
|
50703
|
+
description: "Generate learning insights from swarm coordination metrics. Analyzes success rates, duration, conflicts, and retries to provide actionable recommendations.",
|
|
50704
|
+
args: {
|
|
50705
|
+
scope: tool.schema.enum(["epic", "project", "recent"]).describe("Scope of analysis: 'epic', 'project', or 'recent'"),
|
|
50706
|
+
epic_id: tool.schema.string().optional().describe("Epic ID (required if scope='epic')"),
|
|
50707
|
+
metrics: tool.schema.array(tool.schema.enum([
|
|
50708
|
+
"success_rate",
|
|
50709
|
+
"avg_duration",
|
|
50710
|
+
"conflict_rate",
|
|
50711
|
+
"retry_rate"
|
|
50712
|
+
])).describe("Metrics to analyze")
|
|
50713
|
+
},
|
|
50714
|
+
async execute(args2) {
|
|
50715
|
+
try {
|
|
50716
|
+
if (args2.scope === "epic" && !args2.epic_id) {
|
|
50717
|
+
return JSON.stringify({
|
|
50718
|
+
error: "epic_id is required when scope='epic'"
|
|
50719
|
+
});
|
|
50720
|
+
}
|
|
50721
|
+
const projectPath = process.cwd();
|
|
50722
|
+
const swarmMail = await getSwarmMailLibSQL4(projectPath);
|
|
50723
|
+
const db = await swarmMail.getDatabase();
|
|
50724
|
+
const insights = [];
|
|
50725
|
+
if (args2.metrics.includes("success_rate")) {
|
|
50726
|
+
const query = `
|
|
50727
|
+
SELECT
|
|
50728
|
+
SUM(CASE WHEN json_extract(data, '$.success') = 'true' THEN 1 ELSE 0 END) as successes,
|
|
50729
|
+
COUNT(*) as total
|
|
50730
|
+
FROM events
|
|
50731
|
+
WHERE type = 'subtask_outcome'
|
|
50732
|
+
${args2.epic_id ? "AND json_extract(data, '$.epic_id') = ?" : ""}
|
|
50733
|
+
`;
|
|
50734
|
+
const result = await db.query(query, args2.epic_id ? [args2.epic_id] : []);
|
|
50735
|
+
const row = result.rows[0];
|
|
50736
|
+
if (row && row.total > 0) {
|
|
50737
|
+
const rate = row.successes / row.total * 100;
|
|
50738
|
+
insights.push({
|
|
50739
|
+
metric: "success_rate",
|
|
50740
|
+
value: `${rate.toFixed(1)}%`,
|
|
50741
|
+
insight: rate < 50 ? "Low success rate - review decomposition strategy" : rate < 80 ? "Moderate success rate - monitor for patterns" : "Good success rate - maintain current approach"
|
|
50742
|
+
});
|
|
50743
|
+
}
|
|
50744
|
+
}
|
|
50745
|
+
if (args2.metrics.includes("avg_duration")) {
|
|
50746
|
+
const query = `
|
|
50747
|
+
SELECT AVG(CAST(json_extract(data, '$.duration_ms') AS REAL)) as avg_duration
|
|
50748
|
+
FROM events
|
|
50749
|
+
WHERE type = 'subtask_outcome'
|
|
50750
|
+
${args2.epic_id ? "AND json_extract(data, '$.epic_id') = ?" : ""}
|
|
50751
|
+
`;
|
|
50752
|
+
const result = await db.query(query, args2.epic_id ? [args2.epic_id] : []);
|
|
50753
|
+
const row = result.rows[0];
|
|
50754
|
+
if (row?.avg_duration) {
|
|
50755
|
+
const avgMinutes = (row.avg_duration / 60000).toFixed(1);
|
|
50756
|
+
insights.push({
|
|
50757
|
+
metric: "avg_duration",
|
|
50758
|
+
value: `${avgMinutes} min`,
|
|
50759
|
+
insight: row.avg_duration > 600000 ? "Tasks taking >10min - consider smaller decomposition" : "Task duration is reasonable"
|
|
50760
|
+
});
|
|
50761
|
+
}
|
|
50762
|
+
}
|
|
50763
|
+
return JSON.stringify({
|
|
50764
|
+
scope: args2.scope,
|
|
50765
|
+
epic_id: args2.epic_id,
|
|
50766
|
+
insights
|
|
50767
|
+
}, null, 2);
|
|
50768
|
+
} catch (error45) {
|
|
50769
|
+
return JSON.stringify({
|
|
50770
|
+
error: error45 instanceof Error ? error45.message : String(error45)
|
|
50771
|
+
});
|
|
50772
|
+
}
|
|
50773
|
+
}
|
|
50774
|
+
});
|
|
50775
|
+
var observabilityTools = {
|
|
50776
|
+
swarm_analytics,
|
|
50777
|
+
swarm_query,
|
|
50778
|
+
swarm_diagnose,
|
|
50779
|
+
swarm_insights
|
|
50780
|
+
};
|
|
50781
|
+
|
|
50258
50782
|
// src/output-guardrails.ts
|
|
50259
50783
|
var DEFAULT_GUARDRAIL_CONFIG = {
|
|
50260
50784
|
defaultMaxChars: 32000,
|
|
@@ -50677,7 +51201,8 @@ var SwarmPlugin = async (input) => {
|
|
|
50677
51201
|
...repoCrawlTools,
|
|
50678
51202
|
...skillsTools,
|
|
50679
51203
|
...mandateTools,
|
|
50680
|
-
...memoryTools
|
|
51204
|
+
...memoryTools,
|
|
51205
|
+
...observabilityTools
|
|
50681
51206
|
},
|
|
50682
51207
|
event: async ({ event }) => {
|
|
50683
51208
|
if (event.type === "session.idle") {
|
package/dist/skills.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAoBH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB,kCAAkC;IAClC,QAAQ,EAAE,aAAa,CAAC;IACxB,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,UAAU,EAAE,OAAO,CAAC;IACpB,kDAAkD;IAClD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;CACrB;AAYD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAG3D;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG;IACjD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;CACd,CAQA;AAmKD;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAuD7B;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAGlE;AAED;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAQtD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAMD;;;;;GAKG;AACH,eAAO,MAAM,WAAW;;;;;;;;
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":"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"}
|