opencode-swarm-plugin 0.42.5 → 0.42.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -27652,6 +27652,178 @@ echo "Project directory: $1"
27652
27652
  };
27653
27653
  });
27654
27654
 
27655
+ // src/swarm-insights.ts
27656
+ var exports_swarm_insights = {};
27657
+ __export(exports_swarm_insights, {
27658
+ getStrategyInsights: () => getStrategyInsights,
27659
+ getPatternInsights: () => getPatternInsights,
27660
+ getFileInsights: () => getFileInsights,
27661
+ getCachedInsights: () => getCachedInsights,
27662
+ formatInsightsForPrompt: () => formatInsightsForPrompt,
27663
+ clearInsightsCache: () => clearInsightsCache
27664
+ });
27665
+ async function getStrategyInsights(swarmMail, _task) {
27666
+ const db = await swarmMail.getDatabase();
27667
+ const query = `
27668
+ SELECT
27669
+ json_extract(data, '$.strategy') as strategy,
27670
+ COUNT(*) as total_attempts,
27671
+ SUM(CASE WHEN json_extract(data, '$.success') = 'true' THEN 1 ELSE 0 END) as successes
27672
+ FROM events
27673
+ WHERE type = 'subtask_outcome'
27674
+ AND json_extract(data, '$.strategy') IS NOT NULL
27675
+ GROUP BY json_extract(data, '$.strategy')
27676
+ ORDER BY total_attempts DESC
27677
+ `;
27678
+ const result = await db.query(query, []);
27679
+ const rows = result.rows;
27680
+ return rows.map((row) => {
27681
+ const successRate = row.successes / row.total_attempts * 100;
27682
+ return {
27683
+ strategy: row.strategy,
27684
+ successRate: Math.round(successRate * 100) / 100,
27685
+ totalAttempts: row.total_attempts,
27686
+ recommendation: getStrategyRecommendation(row.strategy, successRate)
27687
+ };
27688
+ });
27689
+ }
27690
+ function getStrategyRecommendation(strategy, successRate) {
27691
+ if (successRate >= 80) {
27692
+ return `${strategy} is performing well (${successRate.toFixed(0)}% success)`;
27693
+ }
27694
+ if (successRate >= 60) {
27695
+ return `${strategy} is moderate - monitor for issues`;
27696
+ }
27697
+ if (successRate >= 40) {
27698
+ return `${strategy} has low success - consider alternatives`;
27699
+ }
27700
+ return `AVOID ${strategy} - high failure rate (${successRate.toFixed(0)}%)`;
27701
+ }
27702
+ async function getFileInsights(swarmMail, files) {
27703
+ if (files.length === 0)
27704
+ return [];
27705
+ const db = await swarmMail.getDatabase();
27706
+ const insights = [];
27707
+ for (const file2 of files) {
27708
+ const query = `
27709
+ SELECT
27710
+ COUNT(*) as failure_count,
27711
+ MAX(timestamp) as last_failure
27712
+ FROM events
27713
+ WHERE type = 'subtask_outcome'
27714
+ AND json_extract(data, '$.success') = 'false'
27715
+ AND json_extract(data, '$.files_touched') LIKE ?
27716
+ `;
27717
+ const result = await db.query(query, [`%${file2}%`]);
27718
+ const row = result.rows[0];
27719
+ if (row && row.failure_count > 0) {
27720
+ const gotchas = await getFileGotchas(swarmMail, file2);
27721
+ insights.push({
27722
+ file: file2,
27723
+ failureCount: row.failure_count,
27724
+ lastFailure: row.last_failure,
27725
+ gotchas
27726
+ });
27727
+ }
27728
+ }
27729
+ return insights;
27730
+ }
27731
+ async function getFileGotchas(_swarmMail, _file2) {
27732
+ return [];
27733
+ }
27734
+ async function getPatternInsights(swarmMail) {
27735
+ const db = await swarmMail.getDatabase();
27736
+ const patterns = [];
27737
+ const query = `
27738
+ SELECT
27739
+ json_extract(data, '$.error_type') as error_type,
27740
+ COUNT(*) as frequency
27741
+ FROM events
27742
+ WHERE type = 'subtask_outcome'
27743
+ AND json_extract(data, '$.success') = 'false'
27744
+ AND json_extract(data, '$.error_type') IS NOT NULL
27745
+ GROUP BY json_extract(data, '$.error_type')
27746
+ HAVING COUNT(*) >= 2
27747
+ ORDER BY frequency DESC
27748
+ LIMIT 5
27749
+ `;
27750
+ const result = await db.query(query, []);
27751
+ const rows = result.rows;
27752
+ for (const row of rows) {
27753
+ patterns.push({
27754
+ pattern: row.error_type,
27755
+ frequency: row.frequency,
27756
+ recommendation: getPatternRecommendation(row.error_type)
27757
+ });
27758
+ }
27759
+ return patterns;
27760
+ }
27761
+ function getPatternRecommendation(errorType) {
27762
+ const recommendations = {
27763
+ type_error: "Add explicit type annotations and null checks",
27764
+ timeout: "Consider breaking into smaller tasks",
27765
+ conflict: "Check file reservations before editing",
27766
+ test_failure: "Run tests incrementally during implementation"
27767
+ };
27768
+ return recommendations[errorType] || `Address ${errorType} issues`;
27769
+ }
27770
+ function formatInsightsForPrompt(bundle, options2 = {}) {
27771
+ const { maxTokens = 500 } = options2;
27772
+ const sections = [];
27773
+ if (bundle.strategies && bundle.strategies.length > 0) {
27774
+ const strategyLines = bundle.strategies.slice(0, 3).map((s) => `- ${s.strategy}: ${s.successRate.toFixed(0)}% success (${s.totalAttempts} attempts)`);
27775
+ sections.push(`**Strategy Performance:**
27776
+ ${strategyLines.join(`
27777
+ `)}`);
27778
+ }
27779
+ if (bundle.files && bundle.files.length > 0) {
27780
+ const fileLines = bundle.files.slice(0, 5).map((f) => {
27781
+ const gotchaStr = f.gotchas.length > 0 ? ` - ${f.gotchas[0]}` : "";
27782
+ return `- ${f.file}: ${f.failureCount} past failures${gotchaStr}`;
27783
+ });
27784
+ sections.push(`**File-Specific Gotchas:**
27785
+ ${fileLines.join(`
27786
+ `)}`);
27787
+ }
27788
+ if (bundle.patterns && bundle.patterns.length > 0) {
27789
+ const patternLines = bundle.patterns.slice(0, 3).map((p) => `- ${p.pattern} (${p.frequency}x): ${p.recommendation}`);
27790
+ sections.push(`**Common Pitfalls:**
27791
+ ${patternLines.join(`
27792
+ `)}`);
27793
+ }
27794
+ if (sections.length === 0) {
27795
+ return "";
27796
+ }
27797
+ let result = sections.join(`
27798
+
27799
+ `);
27800
+ const maxChars = maxTokens * 4;
27801
+ if (result.length > maxChars) {
27802
+ result = result.slice(0, maxChars - 3) + "...";
27803
+ }
27804
+ return result;
27805
+ }
27806
+ async function getCachedInsights(_swarmMail, cacheKey, computeFn) {
27807
+ const cached5 = insightsCache.get(cacheKey);
27808
+ if (cached5 && cached5.expires > Date.now()) {
27809
+ return cached5.data;
27810
+ }
27811
+ const data = await computeFn();
27812
+ insightsCache.set(cacheKey, {
27813
+ data,
27814
+ expires: Date.now() + CACHE_TTL_MS
27815
+ });
27816
+ return data;
27817
+ }
27818
+ function clearInsightsCache() {
27819
+ insightsCache.clear();
27820
+ }
27821
+ var insightsCache, CACHE_TTL_MS;
27822
+ var init_swarm_insights = __esm(() => {
27823
+ insightsCache = new Map;
27824
+ CACHE_TTL_MS = 5 * 60 * 1000;
27825
+ });
27826
+
27655
27827
  // src/model-selection.ts
27656
27828
  var exports_model_selection = {};
27657
27829
  __export(exports_model_selection, {
@@ -91404,6 +91576,7 @@ var CellQueryArgsSchema = exports_external.object({
91404
91576
  status: CellStatusSchema.optional(),
91405
91577
  type: CellTypeSchema.optional(),
91406
91578
  ready: exports_external.boolean().optional(),
91579
+ parent_id: exports_external.string().optional(),
91407
91580
  limit: exports_external.number().int().positive().default(20)
91408
91581
  });
91409
91582
  var SubtaskSpecSchema = exports_external.object({
@@ -92449,6 +92622,7 @@ var hive_query = tool({
92449
92622
  status: tool.schema.enum(["open", "in_progress", "blocked", "closed"]).optional().describe("Filter by status"),
92450
92623
  type: tool.schema.enum(["bug", "feature", "task", "epic", "chore"]).optional().describe("Filter by type"),
92451
92624
  ready: tool.schema.boolean().optional().describe("Only show unblocked cells"),
92625
+ parent_id: tool.schema.string().optional().describe("Filter by parent epic ID (returns children of an epic)"),
92452
92626
  limit: tool.schema.number().optional().describe("Max results to return (default: 20)")
92453
92627
  },
92454
92628
  async execute(args, ctx) {
@@ -92464,6 +92638,7 @@ var hive_query = tool({
92464
92638
  cells = await adapter.queryCells(projectKey, {
92465
92639
  status: validated.status,
92466
92640
  type: validated.type,
92641
+ parent_id: validated.parent_id,
92467
92642
  limit: validated.limit || 20
92468
92643
  });
92469
92644
  }
@@ -92600,6 +92775,7 @@ USE THIS TOOL TO:
92600
92775
  - Find cells by type: hive_cells({ type: "bug" })
92601
92776
  - Get a specific cell by partial ID: hive_cells({ id: "mjkmd" })
92602
92777
  - Get the next ready (unblocked) cell: hive_cells({ ready: true })
92778
+ - Get children of an epic: hive_cells({ parent_id: "epic-id" })
92603
92779
  - Combine filters: hive_cells({ status: "open", type: "task" })
92604
92780
 
92605
92781
  RETURNS: Array of cells with id, title, status, priority, type, parent_id, created_at, updated_at
@@ -92613,6 +92789,7 @@ PREFER THIS OVER hive_query when you need to:
92613
92789
  id: tool.schema.string().optional().describe("Partial or full cell ID to look up"),
92614
92790
  status: tool.schema.enum(["open", "in_progress", "blocked", "closed"]).optional().describe("Filter by status"),
92615
92791
  type: tool.schema.enum(["task", "bug", "feature", "epic", "chore"]).optional().describe("Filter by type"),
92792
+ parent_id: tool.schema.string().optional().describe("Filter by parent epic ID (returns children of an epic)"),
92616
92793
  ready: tool.schema.boolean().optional().describe("If true, return only the next unblocked cell"),
92617
92794
  limit: tool.schema.number().optional().describe("Max cells to return (default 20)")
92618
92795
  },
@@ -92640,6 +92817,7 @@ PREFER THIS OVER hive_query when you need to:
92640
92817
  const cells = await adapter.queryCells(projectKey, {
92641
92818
  status: args.status,
92642
92819
  type: args.type,
92820
+ parent_id: args.parent_id,
92643
92821
  limit: args.limit || 20
92644
92822
  });
92645
92823
  const formatted = cells.map((c) => formatCellForOutput(c));
@@ -114092,38 +114270,28 @@ async function getPromptInsights(options2) {
114092
114270
  }
114093
114271
  async function getCoordinatorInsights(project_key) {
114094
114272
  try {
114095
- const { createLibSQLAdapter, createSwarmMailAdapter: createSwarmMailAdapter2, strategySuccessRates } = await import("swarm-mail");
114273
+ const { createLibSQLAdapter, createSwarmMailAdapter: createSwarmMailAdapter2 } = await import("swarm-mail");
114274
+ const { getStrategyInsights: getStrategyInsights2, getPatternInsights: getPatternInsights2, formatInsightsForPrompt: formatInsightsForPrompt2 } = await Promise.resolve().then(() => (init_swarm_insights(), exports_swarm_insights));
114096
114275
  const dbAdapter = await createLibSQLAdapter({ url: "file:./.swarm-mail/streams.db" });
114097
114276
  const adapter = createSwarmMailAdapter2(dbAdapter, project_key || "default");
114098
- const db = await adapter.getDatabase();
114099
- const query = strategySuccessRates({ project_key });
114100
- const result = await db.query(query.sql, Object.values(query.parameters || {}));
114101
- if (!result || !result.rows || result.rows.length === 0) {
114277
+ const [strategies, patterns] = await Promise.all([
114278
+ getStrategyInsights2(adapter, ""),
114279
+ getPatternInsights2(adapter)
114280
+ ]);
114281
+ const bundle = {
114282
+ strategies,
114283
+ patterns
114284
+ };
114285
+ const formatted = formatInsightsForPrompt2(bundle, { maxTokens: 500 });
114286
+ if (!formatted) {
114102
114287
  return "";
114103
114288
  }
114104
- const rows = result.rows.map((r) => {
114105
- const strategy = r.strategy || "unknown";
114106
- const total = r.total_attempts || 0;
114107
- const successRate = r.success_rate || 0;
114108
- const emoji3 = successRate >= 80 ? "✅" : successRate >= 60 ? "⚠️" : "❌";
114109
- return `| ${emoji3} ${strategy} | ${successRate.toFixed(1)}% | ${total} |`;
114110
- });
114111
- const topRows = rows.slice(0, 5);
114112
- const antiPatterns = result.rows.filter((r) => r.success_rate < 60).map((r) => `- AVOID: ${r.strategy} strategy (${r.success_rate.toFixed(1)}% success rate)`).slice(0, 3);
114113
- const antiPatternsSection = antiPatterns.length > 0 ? `
114114
-
114115
- **Anti-Patterns:**
114116
- ${antiPatterns.join(`
114117
- `)}` : "";
114118
114289
  return `
114119
- ## \uD83D\uDCCA Swarm Insights (Strategy Success Rates)
114290
+ ## \uD83D\uDCCA Historical Insights
114120
114291
 
114121
- | Strategy | Success Rate | Total Attempts |
114122
- |----------|--------------|----------------|
114123
- ${topRows.join(`
114124
- `)}
114292
+ ${formatted}
114125
114293
 
114126
- **Use these insights to select decomposition strategies.**${antiPatternsSection}
114294
+ **Use these learnings when selecting decomposition strategies and planning subtasks.**
114127
114295
  `;
114128
114296
  } catch (e) {
114129
114297
  console.warn("Failed to get coordinator insights:", e);
@@ -114132,7 +114300,9 @@ ${topRows.join(`
114132
114300
  }
114133
114301
  async function getWorkerInsights(files, domain2) {
114134
114302
  try {
114135
- const adapter = await getMemoryAdapter();
114303
+ const { createLibSQLAdapter, createSwarmMailAdapter: createSwarmMailAdapter2 } = await import("swarm-mail");
114304
+ const { getFileInsights: getFileInsights2, formatInsightsForPrompt: formatInsightsForPrompt2 } = await Promise.resolve().then(() => (init_swarm_insights(), exports_swarm_insights));
114305
+ const memoryAdapter = await getMemoryAdapter();
114136
114306
  let query = "";
114137
114307
  if (files && files.length > 0) {
114138
114308
  const keywords = files.flatMap((f) => f.split(/[\/\\.]/).filter((part) => part.length > 2)).slice(0, 5);
@@ -114142,25 +114312,48 @@ async function getWorkerInsights(files, domain2) {
114142
114312
  } else {
114143
114313
  return "";
114144
114314
  }
114145
- const result = await adapter.find({
114146
- query: `${query} gotcha pitfall pattern bug`,
114147
- limit: 3
114148
- });
114149
- if (result.count === 0) {
114150
- return "";
114151
- }
114152
- const learnings = result.results.map((r) => {
114153
- const content = r.content.length > 150 ? r.content.slice(0, 150) + "..." : r.content;
114154
- return `- ${content}`;
114155
- });
114156
- return `
114157
- ## \uD83D\uDCA1 Relevant Learnings (from past agents)
114315
+ const [fileInsights, memoryResult] = await Promise.all([
114316
+ (async () => {
114317
+ if (!files || files.length === 0)
114318
+ return [];
114319
+ try {
114320
+ const dbAdapter = await createLibSQLAdapter({ url: "file:./.swarm-mail/streams.db" });
114321
+ const swarmMail = createSwarmMailAdapter2(dbAdapter, "default");
114322
+ return await getFileInsights2(swarmMail, files);
114323
+ } catch (e) {
114324
+ console.warn("Failed to get file insights from event store:", e);
114325
+ return [];
114326
+ }
114327
+ })(),
114328
+ memoryAdapter.find({
114329
+ query: `${query} gotcha pitfall pattern bug`,
114330
+ limit: 3
114331
+ })
114332
+ ]);
114333
+ const bundle = {
114334
+ files: fileInsights
114335
+ };
114336
+ const formattedFileInsights = formatInsightsForPrompt2(bundle, { maxTokens: 300 });
114337
+ let formattedMemory = "";
114338
+ if (memoryResult.count > 0) {
114339
+ const learnings = memoryResult.results.map((r) => {
114340
+ const content = r.content.length > 150 ? r.content.slice(0, 150) + "..." : r.content;
114341
+ return `- ${content}`;
114342
+ });
114343
+ formattedMemory = `## \uD83D\uDCA1 Relevant Learnings (from past agents)
114158
114344
 
114159
114345
  ${learnings.join(`
114160
114346
  `)}
114161
114347
 
114162
- **Check semantic-memory for full details if needed.**
114163
- `;
114348
+ **Check semantic-memory for full details if needed.**`;
114349
+ }
114350
+ const sections = [formattedFileInsights, formattedMemory].filter((s) => s.length > 0);
114351
+ if (sections.length === 0) {
114352
+ return "";
114353
+ }
114354
+ return sections.join(`
114355
+
114356
+ `);
114164
114357
  } catch (e) {
114165
114358
  console.warn("Failed to get worker insights:", e);
114166
114359
  return "";
@@ -121254,7 +121447,8 @@ var allTools = {
121254
121447
  ...repoCrawlTools,
121255
121448
  ...skillsTools,
121256
121449
  ...mandateTools,
121257
- ...memoryTools
121450
+ ...memoryTools,
121451
+ ...observabilityTools
121258
121452
  };
121259
121453
  export {
121260
121454
  withToolFallback,