opencode-swarm-plugin 0.1.0 → 0.2.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/dist/index.js CHANGED
@@ -12879,6 +12879,242 @@ var beadsTools = {
12879
12879
  beads_link_thread
12880
12880
  };
12881
12881
 
12882
+ // src/tool-availability.ts
12883
+ var toolCache = new Map;
12884
+ var warningsLogged = new Set;
12885
+ async function commandExists(cmd) {
12886
+ try {
12887
+ const result = await Bun.$`which ${cmd}`.quiet().nothrow();
12888
+ return result.exitCode === 0;
12889
+ } catch {
12890
+ return false;
12891
+ }
12892
+ }
12893
+ async function urlReachable(url2, timeoutMs = 1000) {
12894
+ try {
12895
+ const controller = new AbortController;
12896
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
12897
+ const response = await fetch(url2, {
12898
+ method: "HEAD",
12899
+ signal: controller.signal
12900
+ });
12901
+ clearTimeout(timeout);
12902
+ return response.ok;
12903
+ } catch {
12904
+ return false;
12905
+ }
12906
+ }
12907
+ var toolCheckers = {
12908
+ "semantic-memory": async () => {
12909
+ const nativeExists = await commandExists("semantic-memory");
12910
+ if (nativeExists) {
12911
+ try {
12912
+ const result = await Bun.$`semantic-memory stats`.quiet().nothrow();
12913
+ return {
12914
+ available: result.exitCode === 0,
12915
+ checkedAt: new Date().toISOString(),
12916
+ version: "native"
12917
+ };
12918
+ } catch (e) {
12919
+ return {
12920
+ available: false,
12921
+ checkedAt: new Date().toISOString(),
12922
+ error: String(e)
12923
+ };
12924
+ }
12925
+ }
12926
+ try {
12927
+ const proc = Bun.spawn(["bunx", "semantic-memory", "stats"], {
12928
+ stdout: "pipe",
12929
+ stderr: "pipe"
12930
+ });
12931
+ const timeout = setTimeout(() => proc.kill(), 1e4);
12932
+ const exitCode = await proc.exited;
12933
+ clearTimeout(timeout);
12934
+ return {
12935
+ available: exitCode === 0,
12936
+ checkedAt: new Date().toISOString(),
12937
+ version: "bunx"
12938
+ };
12939
+ } catch (e) {
12940
+ return {
12941
+ available: false,
12942
+ checkedAt: new Date().toISOString(),
12943
+ error: String(e)
12944
+ };
12945
+ }
12946
+ },
12947
+ cass: async () => {
12948
+ const exists = await commandExists("cass");
12949
+ if (!exists) {
12950
+ return {
12951
+ available: false,
12952
+ checkedAt: new Date().toISOString(),
12953
+ error: "cass command not found"
12954
+ };
12955
+ }
12956
+ try {
12957
+ const result = await Bun.$`cass health`.quiet().nothrow();
12958
+ return {
12959
+ available: result.exitCode === 0,
12960
+ checkedAt: new Date().toISOString()
12961
+ };
12962
+ } catch (e) {
12963
+ return {
12964
+ available: false,
12965
+ checkedAt: new Date().toISOString(),
12966
+ error: String(e)
12967
+ };
12968
+ }
12969
+ },
12970
+ ubs: async () => {
12971
+ const exists = await commandExists("ubs");
12972
+ if (!exists) {
12973
+ return {
12974
+ available: false,
12975
+ checkedAt: new Date().toISOString(),
12976
+ error: "ubs command not found"
12977
+ };
12978
+ }
12979
+ try {
12980
+ const result = await Bun.$`ubs doctor`.quiet().nothrow();
12981
+ return {
12982
+ available: result.exitCode === 0,
12983
+ checkedAt: new Date().toISOString()
12984
+ };
12985
+ } catch (e) {
12986
+ return {
12987
+ available: false,
12988
+ checkedAt: new Date().toISOString(),
12989
+ error: String(e)
12990
+ };
12991
+ }
12992
+ },
12993
+ beads: async () => {
12994
+ const exists = await commandExists("bd");
12995
+ if (!exists) {
12996
+ return {
12997
+ available: false,
12998
+ checkedAt: new Date().toISOString(),
12999
+ error: "bd command not found"
13000
+ };
13001
+ }
13002
+ try {
13003
+ const result = await Bun.$`bd --version`.quiet().nothrow();
13004
+ return {
13005
+ available: result.exitCode === 0,
13006
+ checkedAt: new Date().toISOString()
13007
+ };
13008
+ } catch (e) {
13009
+ return {
13010
+ available: false,
13011
+ checkedAt: new Date().toISOString(),
13012
+ error: String(e)
13013
+ };
13014
+ }
13015
+ },
13016
+ "agent-mail": async () => {
13017
+ const reachable = await urlReachable("http://127.0.0.1:8765/health/liveness");
13018
+ return {
13019
+ available: reachable,
13020
+ checkedAt: new Date().toISOString(),
13021
+ error: reachable ? undefined : "Agent Mail server not reachable at :8765"
13022
+ };
13023
+ }
13024
+ };
13025
+ var fallbackBehaviors = {
13026
+ "semantic-memory": "Learning data stored in-memory only (lost on session end)",
13027
+ cass: "Decomposition proceeds without historical context from past sessions",
13028
+ ubs: "Subtask completion skips bug scanning - manual review recommended",
13029
+ beads: "Swarm cannot track issues - task coordination will be less reliable",
13030
+ "agent-mail": "Multi-agent coordination disabled - file conflicts possible if multiple agents active"
13031
+ };
13032
+ async function checkTool(tool3) {
13033
+ const cached2 = toolCache.get(tool3);
13034
+ if (cached2) {
13035
+ return cached2;
13036
+ }
13037
+ const checker = toolCheckers[tool3];
13038
+ const status = await checker();
13039
+ toolCache.set(tool3, status);
13040
+ return status;
13041
+ }
13042
+ async function isToolAvailable(tool3) {
13043
+ const status = await checkTool(tool3);
13044
+ return status.available;
13045
+ }
13046
+ async function getToolAvailability(tool3) {
13047
+ const status = await checkTool(tool3);
13048
+ return {
13049
+ tool: tool3,
13050
+ status,
13051
+ fallbackBehavior: fallbackBehaviors[tool3]
13052
+ };
13053
+ }
13054
+ async function checkAllTools() {
13055
+ const tools = [
13056
+ "semantic-memory",
13057
+ "cass",
13058
+ "ubs",
13059
+ "beads",
13060
+ "agent-mail"
13061
+ ];
13062
+ const results = new Map;
13063
+ const checks3 = await Promise.all(tools.map(async (tool3) => ({
13064
+ tool: tool3,
13065
+ availability: await getToolAvailability(tool3)
13066
+ })));
13067
+ for (const { tool: tool3, availability } of checks3) {
13068
+ results.set(tool3, availability);
13069
+ }
13070
+ return results;
13071
+ }
13072
+ function warnMissingTool(tool3) {
13073
+ if (warningsLogged.has(tool3)) {
13074
+ return;
13075
+ }
13076
+ warningsLogged.add(tool3);
13077
+ const fallback = fallbackBehaviors[tool3];
13078
+ console.warn(`[swarm] ${tool3} not available: ${fallback}`);
13079
+ }
13080
+ async function requireTool(tool3) {
13081
+ const status = await checkTool(tool3);
13082
+ if (!status.available) {
13083
+ throw new Error(`Required tool '${tool3}' is not available: ${status.error || "unknown error"}`);
13084
+ }
13085
+ }
13086
+ async function withToolFallback(tool3, action, fallback) {
13087
+ const available = await isToolAvailable(tool3);
13088
+ if (available) {
13089
+ return action();
13090
+ }
13091
+ warnMissingTool(tool3);
13092
+ return fallback();
13093
+ }
13094
+ async function ifToolAvailable(tool3, action) {
13095
+ const available = await isToolAvailable(tool3);
13096
+ if (available) {
13097
+ return action();
13098
+ }
13099
+ warnMissingTool(tool3);
13100
+ return;
13101
+ }
13102
+ function resetToolCache() {
13103
+ toolCache.clear();
13104
+ warningsLogged.clear();
13105
+ }
13106
+ function formatToolAvailability(availability) {
13107
+ const lines = ["Tool Availability:"];
13108
+ for (const [tool3, info] of availability) {
13109
+ const status = info.status.available ? "\u2713" : "\u2717";
13110
+ const version2 = info.status.version ? ` (${info.status.version})` : "";
13111
+ const fallback = info.status.available ? "" : ` \u2192 ${info.fallbackBehavior}`;
13112
+ lines.push(` ${status} ${tool3}${version2}${fallback}`);
13113
+ }
13114
+ return lines.join(`
13115
+ `);
13116
+ }
13117
+
12882
13118
  // src/agent-mail.ts
12883
13119
  var AGENT_MAIL_URL = "http://127.0.0.1:8765";
12884
13120
  var DEFAULT_TTL_SECONDS = 3600;
@@ -12913,6 +13149,14 @@ class FileReservationConflictError extends Error {
12913
13149
  this.name = "FileReservationConflictError";
12914
13150
  }
12915
13151
  }
13152
+ var agentMailAvailable = null;
13153
+ async function checkAgentMailAvailable() {
13154
+ if (agentMailAvailable !== null) {
13155
+ return agentMailAvailable;
13156
+ }
13157
+ agentMailAvailable = await isToolAvailable("agent-mail");
13158
+ return agentMailAvailable;
13159
+ }
12916
13160
  async function mcpCall(toolName, args) {
12917
13161
  const response = await fetch(`${AGENT_MAIL_URL}/mcp/`, {
12918
13162
  method: "POST",
@@ -12962,6 +13206,16 @@ var agentmail_init = tool({
12962
13206
  task_description: tool.schema.string().optional().describe("Description of current task")
12963
13207
  },
12964
13208
  async execute(args, ctx) {
13209
+ const available = await checkAgentMailAvailable();
13210
+ if (!available) {
13211
+ warnMissingTool("agent-mail");
13212
+ return JSON.stringify({
13213
+ error: "Agent Mail server not available",
13214
+ available: false,
13215
+ hint: "Start Agent Mail with: agent-mail serve",
13216
+ fallback: "Swarm will continue without multi-agent coordination. File conflicts possible if multiple agents active."
13217
+ }, null, 2);
13218
+ }
12965
13219
  const project = await mcpCall("ensure_project", {
12966
13220
  human_key: args.project_path
12967
13221
  });
@@ -12979,7 +13233,7 @@ var agentmail_init = tool({
12979
13233
  startedAt: new Date().toISOString()
12980
13234
  };
12981
13235
  setState(ctx.sessionID, state);
12982
- return JSON.stringify({ project, agent }, null, 2);
13236
+ return JSON.stringify({ project, agent, available: true }, null, 2);
12983
13237
  }
12984
13238
  });
12985
13239
  var agentmail_send = tool({
@@ -13670,6 +13924,21 @@ function outcomeToFeedback(outcome, criterion) {
13670
13924
  raw_value: outcome.decayed_value
13671
13925
  };
13672
13926
  }
13927
+ class InMemoryFeedbackStorage {
13928
+ events = [];
13929
+ async store(event) {
13930
+ this.events.push(event);
13931
+ }
13932
+ async getByCriterion(criterion) {
13933
+ return this.events.filter((e) => e.criterion === criterion);
13934
+ }
13935
+ async getByBead(beadId) {
13936
+ return this.events.filter((e) => e.bead_id === beadId);
13937
+ }
13938
+ async getAll() {
13939
+ return [...this.events];
13940
+ }
13941
+ }
13673
13942
 
13674
13943
  // src/swarm.ts
13675
13944
  var POSITIVE_MARKERS = [
@@ -13762,6 +14031,18 @@ var DECOMPOSITION_PROMPT = `You are decomposing a task into parallelizable subta
13762
14031
 
13763
14032
  {context_section}
13764
14033
 
14034
+ ## MANDATORY: Beads Issue Tracking
14035
+
14036
+ **Every subtask MUST become a bead.** This is non-negotiable.
14037
+
14038
+ After decomposition, the coordinator will:
14039
+ 1. Create an epic bead for the overall task
14040
+ 2. Create child beads for each subtask
14041
+ 3. Track progress through bead status updates
14042
+ 4. Close beads with summaries when complete
14043
+
14044
+ Agents MUST update their bead status as they work. No silent progress.
14045
+
13765
14046
  ## Requirements
13766
14047
 
13767
14048
  1. **Break into 2-{max_subtasks} independent subtasks** that can run in parallel
@@ -13769,6 +14050,7 @@ var DECOMPOSITION_PROMPT = `You are decomposing a task into parallelizable subta
13769
14050
  3. **No file overlap** - files cannot appear in multiple subtasks (they get exclusive locks)
13770
14051
  4. **Order by dependency** - if subtask B needs subtask A's output, A must come first in the array
13771
14052
  5. **Estimate complexity** - 1 (trivial) to 5 (complex)
14053
+ 6. **Plan aggressively** - break down more than you think necessary, smaller is better
13772
14054
 
13773
14055
  ## Response Format
13774
14056
 
@@ -13795,10 +14077,12 @@ Respond with a JSON object matching this schema:
13795
14077
 
13796
14078
  ## Guidelines
13797
14079
 
14080
+ - **Plan aggressively** - when in doubt, split further. 3 small tasks > 1 medium task
13798
14081
  - **Prefer smaller, focused subtasks** over large complex ones
13799
14082
  - **Include test files** in the same subtask as the code they test
13800
14083
  - **Consider shared types** - if multiple files share types, handle that first
13801
14084
  - **Think about imports** - changes to exported APIs affect downstream files
14085
+ - **Explicit > implicit** - spell out what each subtask should do, don't assume
13802
14086
 
13803
14087
  ## File Assignment Examples
13804
14088
 
@@ -13829,19 +14113,49 @@ send a message to the coordinator requesting the change.
13829
14113
  ## Shared Context
13830
14114
  {shared_context}
13831
14115
 
14116
+ ## MANDATORY: Beads Tracking
14117
+
14118
+ You MUST keep your bead updated as you work:
14119
+
14120
+ 1. **Your bead is already in_progress** - don't change this unless blocked
14121
+ 2. **If blocked**: \`bd update {bead_id} --status blocked\` and message coordinator
14122
+ 3. **When done**: Use \`swarm_complete\` - it closes your bead automatically
14123
+ 4. **Discovered issues**: Create new beads with \`bd create "issue" -t bug\`
14124
+
14125
+ **Never work silently.** Your bead status is how the swarm tracks progress.
14126
+
14127
+ ## MANDATORY: Agent Mail Communication
14128
+
14129
+ You MUST communicate with other agents:
14130
+
14131
+ 1. **Report progress** every significant milestone (not just at the end)
14132
+ 2. **Ask questions** if requirements are unclear - don't guess
14133
+ 3. **Announce blockers** immediately - don't spin trying to fix alone
14134
+ 4. **Coordinate on shared concerns** - if you see something affecting other agents, say so
14135
+
14136
+ Use Agent Mail for all communication:
14137
+ \`\`\`
14138
+ agentmail_send(
14139
+ to: ["coordinator" or specific agent],
14140
+ subject: "Brief subject",
14141
+ body: "Message content",
14142
+ thread_id: "{epic_id}"
14143
+ )
14144
+ \`\`\`
14145
+
13832
14146
  ## Coordination Protocol
13833
14147
 
13834
14148
  1. **Start**: Your bead is already marked in_progress
13835
- 2. **Progress**: Use swarm:progress to report status updates
13836
- 3. **Blocked**: If you hit a blocker, report it - don't spin
13837
- 4. **Complete**: Use swarm:complete when done - it handles:
14149
+ 2. **Progress**: Use swarm_progress to report status updates
14150
+ 3. **Blocked**: Report immediately via Agent Mail - don't spin
14151
+ 4. **Complete**: Use swarm_complete when done - it handles:
13838
14152
  - Closing your bead with a summary
13839
14153
  - Releasing file reservations
13840
14154
  - Notifying the coordinator
13841
14155
 
13842
14156
  ## Self-Evaluation
13843
14157
 
13844
- Before calling swarm:complete, evaluate your work:
14158
+ Before calling swarm_complete, evaluate your work:
13845
14159
  - Type safety: Does it compile without errors?
13846
14160
  - No obvious bugs: Did you handle edge cases?
13847
14161
  - Follows patterns: Does it match existing code style?
@@ -13849,17 +14163,13 @@ Before calling swarm:complete, evaluate your work:
13849
14163
 
13850
14164
  If evaluation fails, fix the issues before completing.
13851
14165
 
13852
- ## Communication
14166
+ ## Planning Your Work
13853
14167
 
13854
- To message other agents or the coordinator:
13855
- \`\`\`
13856
- agent-mail:send(
13857
- to: ["coordinator_name" or other agent],
13858
- subject: "Brief subject",
13859
- body: "Message content",
13860
- thread_id: "{epic_id}"
13861
- )
13862
- \`\`\`
14168
+ Before writing code:
14169
+ 1. **Read the files** you're assigned to understand current state
14170
+ 2. **Plan your approach** - what changes, in what order?
14171
+ 3. **Identify risks** - what could go wrong? What dependencies?
14172
+ 4. **Communicate your plan** via Agent Mail if non-trivial
13863
14173
 
13864
14174
  Begin work on your subtask now.`;
13865
14175
  var EVALUATION_PROMPT = `Evaluate the work completed for this subtask.
@@ -13934,21 +14244,32 @@ function formatEvaluationPrompt(params) {
13934
14244
  return EVALUATION_PROMPT.replace("{bead_id}", params.bead_id).replace("{subtask_title}", params.subtask_title).replace("{files_touched}", filesList || "(no files recorded)");
13935
14245
  }
13936
14246
  async function queryEpicSubtasks(epicId) {
14247
+ const beadsAvailable = await isToolAvailable("beads");
14248
+ if (!beadsAvailable) {
14249
+ warnMissingTool("beads");
14250
+ return [];
14251
+ }
13937
14252
  const result = await Bun.$`bd list --parent ${epicId} --json`.quiet().nothrow();
13938
14253
  if (result.exitCode !== 0) {
13939
- throw new SwarmError(`Failed to query subtasks: ${result.stderr.toString()}`, "query_subtasks");
14254
+ console.warn(`[swarm] Failed to query subtasks: ${result.stderr.toString()}`);
14255
+ return [];
13940
14256
  }
13941
14257
  try {
13942
14258
  const parsed = JSON.parse(result.stdout.toString());
13943
14259
  return exports_external.array(BeadSchema).parse(parsed);
13944
14260
  } catch (error45) {
13945
14261
  if (error45 instanceof exports_external.ZodError) {
13946
- throw new SwarmError(`Invalid bead data: ${error45.message}`, "query_subtasks", error45.issues);
14262
+ console.warn(`[swarm] Invalid bead data: ${error45.message}`);
14263
+ return [];
13947
14264
  }
13948
14265
  throw error45;
13949
14266
  }
13950
14267
  }
13951
14268
  async function querySwarmMessages(projectKey, threadId) {
14269
+ const agentMailAvailable2 = await isToolAvailable("agent-mail");
14270
+ if (!agentMailAvailable2) {
14271
+ return 0;
14272
+ }
13952
14273
  try {
13953
14274
  const summary = await mcpCall("summarize_thread", {
13954
14275
  project_key: projectKey,
@@ -13977,11 +14298,13 @@ ${progress.blockers.map((b) => `- ${b}`).join(`
13977
14298
  `);
13978
14299
  }
13979
14300
  async function queryCassHistory(task, limit = 3) {
14301
+ const cassAvailable = await isToolAvailable("cass");
14302
+ if (!cassAvailable) {
14303
+ warnMissingTool("cass");
14304
+ return null;
14305
+ }
13980
14306
  try {
13981
14307
  const result = await Bun.$`cass search ${task} --limit ${limit} --json`.quiet().nothrow();
13982
- if (result.exitCode === 127) {
13983
- return null;
13984
- }
13985
14308
  if (result.exitCode !== 0) {
13986
14309
  return null;
13987
14310
  }
@@ -14241,11 +14564,13 @@ async function runUbsScan(files) {
14241
14564
  if (files.length === 0) {
14242
14565
  return null;
14243
14566
  }
14567
+ const ubsAvailable = await isToolAvailable("ubs");
14568
+ if (!ubsAvailable) {
14569
+ warnMissingTool("ubs");
14570
+ return null;
14571
+ }
14244
14572
  try {
14245
14573
  const result = await Bun.$`ubs scan ${files.join(" ")} --json`.quiet().nothrow();
14246
- if (result.exitCode === 127) {
14247
- return null;
14248
- }
14249
14574
  const output = result.stdout.toString();
14250
14575
  if (!output.trim()) {
14251
14576
  return {
@@ -14476,7 +14801,56 @@ var swarm_evaluation_prompt = tool({
14476
14801
  }, null, 2);
14477
14802
  }
14478
14803
  });
14804
+ var swarm_init = tool({
14805
+ description: "Initialize swarm session and check tool availability. Call at swarm start to see what features are available.",
14806
+ args: {
14807
+ project_path: tool.schema.string().optional().describe("Project path (for Agent Mail init)")
14808
+ },
14809
+ async execute(args) {
14810
+ const availability = await checkAllTools();
14811
+ const report = formatToolAvailability(availability);
14812
+ const beadsAvailable = availability.get("beads")?.status.available ?? false;
14813
+ const agentMailAvailable2 = availability.get("agent-mail")?.status.available ?? false;
14814
+ const warnings = [];
14815
+ const degradedFeatures = [];
14816
+ if (!beadsAvailable) {
14817
+ warnings.push("\u26A0\uFE0F beads (bd) not available - issue tracking disabled, swarm coordination will be limited");
14818
+ degradedFeatures.push("issue tracking", "progress persistence");
14819
+ }
14820
+ if (!agentMailAvailable2) {
14821
+ warnings.push("\u26A0\uFE0F agent-mail not available - multi-agent communication disabled");
14822
+ degradedFeatures.push("agent communication", "file reservations");
14823
+ }
14824
+ if (!availability.get("cass")?.status.available) {
14825
+ degradedFeatures.push("historical context from past sessions");
14826
+ }
14827
+ if (!availability.get("ubs")?.status.available) {
14828
+ degradedFeatures.push("pre-completion bug scanning");
14829
+ }
14830
+ if (!availability.get("semantic-memory")?.status.available) {
14831
+ degradedFeatures.push("persistent learning (using in-memory fallback)");
14832
+ }
14833
+ return JSON.stringify({
14834
+ ready: true,
14835
+ tool_availability: Object.fromEntries(Array.from(availability.entries()).map(([k, v]) => [
14836
+ k,
14837
+ {
14838
+ available: v.status.available,
14839
+ fallback: v.status.available ? null : v.fallbackBehavior
14840
+ }
14841
+ ])),
14842
+ warnings: warnings.length > 0 ? warnings : undefined,
14843
+ degraded_features: degradedFeatures.length > 0 ? degradedFeatures : undefined,
14844
+ recommendations: {
14845
+ beads: beadsAvailable ? "\u2713 Use beads for all task tracking" : "Install beads: npm i -g @joelhooks/beads",
14846
+ agent_mail: agentMailAvailable2 ? "\u2713 Use Agent Mail for coordination" : "Start Agent Mail: agent-mail serve"
14847
+ },
14848
+ report
14849
+ }, null, 2);
14850
+ }
14851
+ });
14479
14852
  var swarmTools = {
14853
+ swarm_init,
14480
14854
  swarm_decompose,
14481
14855
  swarm_validate_decomposition,
14482
14856
  swarm_status,
@@ -14486,6 +14860,394 @@ var swarmTools = {
14486
14860
  swarm_subtask_prompt,
14487
14861
  swarm_evaluation_prompt
14488
14862
  };
14863
+ // src/anti-patterns.ts
14864
+ var PatternKindSchema = exports_external.enum(["pattern", "anti_pattern"]);
14865
+ var DecompositionPatternSchema = exports_external.object({
14866
+ id: exports_external.string(),
14867
+ content: exports_external.string(),
14868
+ kind: PatternKindSchema,
14869
+ is_negative: exports_external.boolean(),
14870
+ success_count: exports_external.number().int().min(0).default(0),
14871
+ failure_count: exports_external.number().int().min(0).default(0),
14872
+ created_at: exports_external.string(),
14873
+ updated_at: exports_external.string(),
14874
+ reason: exports_external.string().optional(),
14875
+ tags: exports_external.array(exports_external.string()).default([]),
14876
+ example_beads: exports_external.array(exports_external.string()).default([])
14877
+ });
14878
+ var PatternInversionResultSchema = exports_external.object({
14879
+ original: DecompositionPatternSchema,
14880
+ inverted: DecompositionPatternSchema,
14881
+ reason: exports_external.string()
14882
+ });
14883
+ class InMemoryPatternStorage {
14884
+ patterns = new Map;
14885
+ async store(pattern) {
14886
+ this.patterns.set(pattern.id, pattern);
14887
+ }
14888
+ async get(id) {
14889
+ return this.patterns.get(id) ?? null;
14890
+ }
14891
+ async getAll() {
14892
+ return Array.from(this.patterns.values());
14893
+ }
14894
+ async getAntiPatterns() {
14895
+ return Array.from(this.patterns.values()).filter((p) => p.kind === "anti_pattern");
14896
+ }
14897
+ async getByTag(tag) {
14898
+ return Array.from(this.patterns.values()).filter((p) => p.tags.includes(tag));
14899
+ }
14900
+ async findByContent(content) {
14901
+ const lower = content.toLowerCase();
14902
+ return Array.from(this.patterns.values()).filter((p) => p.content.toLowerCase().includes(lower));
14903
+ }
14904
+ }
14905
+
14906
+ // src/pattern-maturity.ts
14907
+ var MaturityStateSchema = exports_external.enum([
14908
+ "candidate",
14909
+ "established",
14910
+ "proven",
14911
+ "deprecated"
14912
+ ]);
14913
+ var PatternMaturitySchema = exports_external.object({
14914
+ pattern_id: exports_external.string(),
14915
+ state: MaturityStateSchema,
14916
+ helpful_count: exports_external.number().int().min(0),
14917
+ harmful_count: exports_external.number().int().min(0),
14918
+ last_validated: exports_external.string(),
14919
+ promoted_at: exports_external.string().optional(),
14920
+ deprecated_at: exports_external.string().optional()
14921
+ });
14922
+ var MaturityFeedbackSchema = exports_external.object({
14923
+ pattern_id: exports_external.string(),
14924
+ type: exports_external.enum(["helpful", "harmful"]),
14925
+ timestamp: exports_external.string(),
14926
+ weight: exports_external.number().min(0).max(1).default(1)
14927
+ });
14928
+ class InMemoryMaturityStorage {
14929
+ maturities = new Map;
14930
+ feedback = [];
14931
+ async store(maturity) {
14932
+ this.maturities.set(maturity.pattern_id, maturity);
14933
+ }
14934
+ async get(patternId) {
14935
+ return this.maturities.get(patternId) ?? null;
14936
+ }
14937
+ async getAll() {
14938
+ return Array.from(this.maturities.values());
14939
+ }
14940
+ async getByState(state) {
14941
+ return Array.from(this.maturities.values()).filter((m) => m.state === state);
14942
+ }
14943
+ async storeFeedback(feedback) {
14944
+ this.feedback.push(feedback);
14945
+ }
14946
+ async getFeedback(patternId) {
14947
+ return this.feedback.filter((f) => f.pattern_id === patternId);
14948
+ }
14949
+ }
14950
+
14951
+ // src/storage.ts
14952
+ var cachedCommand = null;
14953
+ async function resolveSemanticMemoryCommand() {
14954
+ if (cachedCommand)
14955
+ return cachedCommand;
14956
+ const nativeResult = await Bun.$`which semantic-memory`.quiet().nothrow();
14957
+ if (nativeResult.exitCode === 0) {
14958
+ cachedCommand = ["semantic-memory"];
14959
+ return cachedCommand;
14960
+ }
14961
+ cachedCommand = ["bunx", "semantic-memory"];
14962
+ return cachedCommand;
14963
+ }
14964
+ async function execSemanticMemory(args) {
14965
+ const cmd = await resolveSemanticMemoryCommand();
14966
+ const fullCmd = [...cmd, ...args];
14967
+ const proc = Bun.spawn(fullCmd, {
14968
+ stdout: "pipe",
14969
+ stderr: "pipe"
14970
+ });
14971
+ const stdout = Buffer.from(await new Response(proc.stdout).arrayBuffer());
14972
+ const stderr = Buffer.from(await new Response(proc.stderr).arrayBuffer());
14973
+ const exitCode = await proc.exited;
14974
+ return { exitCode, stdout, stderr };
14975
+ }
14976
+ var DEFAULT_STORAGE_CONFIG = {
14977
+ backend: "semantic-memory",
14978
+ collections: {
14979
+ feedback: "swarm-feedback",
14980
+ patterns: "swarm-patterns",
14981
+ maturity: "swarm-maturity"
14982
+ },
14983
+ useSemanticSearch: true
14984
+ };
14985
+
14986
+ class SemanticMemoryStorage {
14987
+ config;
14988
+ constructor(config2 = {}) {
14989
+ this.config = { ...DEFAULT_STORAGE_CONFIG, ...config2 };
14990
+ }
14991
+ async store(collection, data, metadata) {
14992
+ const content = typeof data === "string" ? data : JSON.stringify(data);
14993
+ const args = ["store", content, "--collection", collection];
14994
+ if (metadata) {
14995
+ args.push("--metadata", JSON.stringify(metadata));
14996
+ }
14997
+ await execSemanticMemory(args);
14998
+ }
14999
+ async find(collection, query, limit = 10, useFts = false) {
15000
+ const args = [
15001
+ "find",
15002
+ query,
15003
+ "--collection",
15004
+ collection,
15005
+ "--limit",
15006
+ String(limit),
15007
+ "--json"
15008
+ ];
15009
+ if (useFts) {
15010
+ args.push("--fts");
15011
+ }
15012
+ const result = await execSemanticMemory(args);
15013
+ if (result.exitCode !== 0) {
15014
+ return [];
15015
+ }
15016
+ try {
15017
+ const output = result.stdout.toString().trim();
15018
+ if (!output)
15019
+ return [];
15020
+ const parsed = JSON.parse(output);
15021
+ const results = Array.isArray(parsed) ? parsed : parsed.results || [];
15022
+ return results.map((r) => {
15023
+ const content = r.content || r.information || "";
15024
+ try {
15025
+ return JSON.parse(content);
15026
+ } catch {
15027
+ return content;
15028
+ }
15029
+ });
15030
+ } catch {
15031
+ return [];
15032
+ }
15033
+ }
15034
+ async list(collection) {
15035
+ const result = await execSemanticMemory([
15036
+ "list",
15037
+ "--collection",
15038
+ collection,
15039
+ "--json"
15040
+ ]);
15041
+ if (result.exitCode !== 0) {
15042
+ return [];
15043
+ }
15044
+ try {
15045
+ const output = result.stdout.toString().trim();
15046
+ if (!output)
15047
+ return [];
15048
+ const parsed = JSON.parse(output);
15049
+ const items = Array.isArray(parsed) ? parsed : parsed.items || [];
15050
+ return items.map((item) => {
15051
+ const content = item.content || item.information || "";
15052
+ try {
15053
+ return JSON.parse(content);
15054
+ } catch {
15055
+ return content;
15056
+ }
15057
+ });
15058
+ } catch {
15059
+ return [];
15060
+ }
15061
+ }
15062
+ async storeFeedback(event) {
15063
+ await this.store(this.config.collections.feedback, event, {
15064
+ criterion: event.criterion,
15065
+ type: event.type,
15066
+ bead_id: event.bead_id || "",
15067
+ timestamp: event.timestamp
15068
+ });
15069
+ }
15070
+ async getFeedbackByCriterion(criterion) {
15071
+ return this.find(this.config.collections.feedback, criterion, 100, true);
15072
+ }
15073
+ async getFeedbackByBead(beadId) {
15074
+ return this.find(this.config.collections.feedback, beadId, 100, true);
15075
+ }
15076
+ async getAllFeedback() {
15077
+ return this.list(this.config.collections.feedback);
15078
+ }
15079
+ async findSimilarFeedback(query, limit = 10) {
15080
+ return this.find(this.config.collections.feedback, query, limit, !this.config.useSemanticSearch);
15081
+ }
15082
+ async storePattern(pattern) {
15083
+ await this.store(this.config.collections.patterns, pattern, {
15084
+ id: pattern.id,
15085
+ kind: pattern.kind,
15086
+ is_negative: pattern.is_negative,
15087
+ tags: pattern.tags.join(",")
15088
+ });
15089
+ }
15090
+ async getPattern(id) {
15091
+ const all = await this.list(this.config.collections.patterns);
15092
+ return all.find((p) => p.id === id) || null;
15093
+ }
15094
+ async getAllPatterns() {
15095
+ return this.list(this.config.collections.patterns);
15096
+ }
15097
+ async getAntiPatterns() {
15098
+ const all = await this.getAllPatterns();
15099
+ return all.filter((p) => p.kind === "anti_pattern");
15100
+ }
15101
+ async getPatternsByTag(tag) {
15102
+ const results = await this.find(this.config.collections.patterns, tag, 100, true);
15103
+ return results.filter((p) => p.tags.includes(tag));
15104
+ }
15105
+ async findSimilarPatterns(query, limit = 10) {
15106
+ return this.find(this.config.collections.patterns, query, limit, !this.config.useSemanticSearch);
15107
+ }
15108
+ async storeMaturity(maturity) {
15109
+ await this.store(this.config.collections.maturity, maturity, {
15110
+ pattern_id: maturity.pattern_id,
15111
+ state: maturity.state
15112
+ });
15113
+ }
15114
+ async getMaturity(patternId) {
15115
+ const all = await this.list(this.config.collections.maturity);
15116
+ return all.find((m) => m.pattern_id === patternId) || null;
15117
+ }
15118
+ async getAllMaturity() {
15119
+ return this.list(this.config.collections.maturity);
15120
+ }
15121
+ async getMaturityByState(state) {
15122
+ const all = await this.getAllMaturity();
15123
+ return all.filter((m) => m.state === state);
15124
+ }
15125
+ async storeMaturityFeedback(feedback) {
15126
+ await this.store(this.config.collections.maturity + "-feedback", feedback, {
15127
+ pattern_id: feedback.pattern_id,
15128
+ type: feedback.type,
15129
+ timestamp: feedback.timestamp
15130
+ });
15131
+ }
15132
+ async getMaturityFeedback(patternId) {
15133
+ const all = await this.list(this.config.collections.maturity + "-feedback");
15134
+ return all.filter((f) => f.pattern_id === patternId);
15135
+ }
15136
+ async close() {}
15137
+ }
15138
+
15139
+ class InMemoryStorage {
15140
+ feedback;
15141
+ patterns;
15142
+ maturity;
15143
+ constructor() {
15144
+ this.feedback = new InMemoryFeedbackStorage;
15145
+ this.patterns = new InMemoryPatternStorage;
15146
+ this.maturity = new InMemoryMaturityStorage;
15147
+ }
15148
+ async storeFeedback(event) {
15149
+ return this.feedback.store(event);
15150
+ }
15151
+ async getFeedbackByCriterion(criterion) {
15152
+ return this.feedback.getByCriterion(criterion);
15153
+ }
15154
+ async getFeedbackByBead(beadId) {
15155
+ return this.feedback.getByBead(beadId);
15156
+ }
15157
+ async getAllFeedback() {
15158
+ return this.feedback.getAll();
15159
+ }
15160
+ async findSimilarFeedback(query, limit = 10) {
15161
+ const all = await this.feedback.getAll();
15162
+ const lowerQuery = query.toLowerCase();
15163
+ const filtered = all.filter((event) => event.criterion.toLowerCase().includes(lowerQuery) || event.bead_id && event.bead_id.toLowerCase().includes(lowerQuery) || event.context && event.context.toLowerCase().includes(lowerQuery));
15164
+ return filtered.slice(0, limit);
15165
+ }
15166
+ async storePattern(pattern) {
15167
+ return this.patterns.store(pattern);
15168
+ }
15169
+ async getPattern(id) {
15170
+ return this.patterns.get(id);
15171
+ }
15172
+ async getAllPatterns() {
15173
+ return this.patterns.getAll();
15174
+ }
15175
+ async getAntiPatterns() {
15176
+ return this.patterns.getAntiPatterns();
15177
+ }
15178
+ async getPatternsByTag(tag) {
15179
+ return this.patterns.getByTag(tag);
15180
+ }
15181
+ async findSimilarPatterns(query, limit = 10) {
15182
+ const results = await this.patterns.findByContent(query);
15183
+ return results.slice(0, limit);
15184
+ }
15185
+ async storeMaturity(maturity) {
15186
+ return this.maturity.store(maturity);
15187
+ }
15188
+ async getMaturity(patternId) {
15189
+ return this.maturity.get(patternId);
15190
+ }
15191
+ async getAllMaturity() {
15192
+ return this.maturity.getAll();
15193
+ }
15194
+ async getMaturityByState(state) {
15195
+ return this.maturity.getByState(state);
15196
+ }
15197
+ async storeMaturityFeedback(feedback) {
15198
+ return this.maturity.storeFeedback(feedback);
15199
+ }
15200
+ async getMaturityFeedback(patternId) {
15201
+ return this.maturity.getFeedback(patternId);
15202
+ }
15203
+ async close() {}
15204
+ }
15205
+ function createStorage(config2 = {}) {
15206
+ const fullConfig = { ...DEFAULT_STORAGE_CONFIG, ...config2 };
15207
+ switch (fullConfig.backend) {
15208
+ case "semantic-memory":
15209
+ return new SemanticMemoryStorage(fullConfig);
15210
+ case "memory":
15211
+ return new InMemoryStorage;
15212
+ default:
15213
+ throw new Error(`Unknown storage backend: ${fullConfig.backend}`);
15214
+ }
15215
+ }
15216
+ async function isSemanticMemoryAvailable() {
15217
+ try {
15218
+ const result = await execSemanticMemory(["stats"]);
15219
+ return result.exitCode === 0;
15220
+ } catch {
15221
+ return false;
15222
+ }
15223
+ }
15224
+ async function createStorageWithFallback(config2 = {}) {
15225
+ if (config2.backend === "memory") {
15226
+ return new InMemoryStorage;
15227
+ }
15228
+ const available = await isSemanticMemoryAvailable();
15229
+ if (available) {
15230
+ return new SemanticMemoryStorage(config2);
15231
+ }
15232
+ console.warn("semantic-memory not available, falling back to in-memory storage");
15233
+ return new InMemoryStorage;
15234
+ }
15235
+ var globalStorage = null;
15236
+ async function getStorage() {
15237
+ if (!globalStorage) {
15238
+ globalStorage = await createStorageWithFallback();
15239
+ }
15240
+ return globalStorage;
15241
+ }
15242
+ function setStorage(storage) {
15243
+ globalStorage = storage;
15244
+ }
15245
+ async function resetStorage() {
15246
+ if (globalStorage) {
15247
+ await globalStorage.close();
15248
+ globalStorage = null;
15249
+ }
15250
+ }
14489
15251
 
14490
15252
  // src/index.ts
14491
15253
  var SwarmPlugin = async (input) => {
@@ -14567,14 +15329,30 @@ var SwarmPlugin = async (input) => {
14567
15329
  };
14568
15330
  var src_default = SwarmPlugin;
14569
15331
  export {
15332
+ withToolFallback,
15333
+ warnMissingTool,
14570
15334
  swarmTools,
14571
15335
  structuredTools,
15336
+ setStorage,
15337
+ resetToolCache,
15338
+ resetStorage,
15339
+ requireTool,
15340
+ isToolAvailable,
15341
+ isSemanticMemoryAvailable,
15342
+ ifToolAvailable,
15343
+ getToolAvailability,
15344
+ getStorage,
14572
15345
  getSchemaByName,
14573
15346
  formatZodErrors,
15347
+ formatToolAvailability,
14574
15348
  formatSubtaskPrompt,
14575
15349
  formatEvaluationPrompt,
14576
15350
  extractJsonFromText,
14577
15351
  src_default as default,
15352
+ createStorageWithFallback,
15353
+ createStorage,
15354
+ checkTool,
15355
+ checkAllTools,
14578
15356
  beads_update,
14579
15357
  beads_sync,
14580
15358
  beads_start,
@@ -14598,6 +15376,8 @@ export {
14598
15376
  SubtaskSpecSchema,
14599
15377
  SubtaskDependencySchema,
14600
15378
  SpawnedAgentSchema,
15379
+ SemanticMemoryStorage,
15380
+ InMemoryStorage,
14601
15381
  FileReservationConflictError,
14602
15382
  EvaluationSchema,
14603
15383
  EvaluationRequestSchema,
@@ -14608,6 +15388,7 @@ export {
14608
15388
  DecompositionError,
14609
15389
  DecomposedSubtaskSchema,
14610
15390
  DecomposeArgsSchema,
15391
+ DEFAULT_STORAGE_CONFIG,
14611
15392
  DEFAULT_CRITERIA,
14612
15393
  CriterionEvaluationSchema,
14613
15394
  BeadValidationError,