opencode-swarm-plugin 0.17.1 → 0.18.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/.beads/issues.jsonl +24 -24
- package/dist/index.js +302 -47
- package/dist/plugin.js +302 -47
- package/package.json +1 -1
- package/src/learning.ts +106 -0
- package/src/rate-limiter.ts +48 -4
- package/src/streams/index.ts +29 -0
- package/src/streams/projections.ts +15 -0
- package/src/streams/store.ts +141 -72
- package/src/swarm.ts +294 -57
package/dist/index.js
CHANGED
|
@@ -12810,6 +12810,11 @@ var init_events = __esm(() => {
|
|
|
12810
12810
|
async function appendEvent(event, projectPath) {
|
|
12811
12811
|
const db = await getDatabase(projectPath);
|
|
12812
12812
|
const { type, project_key, timestamp, ...rest } = event;
|
|
12813
|
+
console.log("[SwarmMail] Appending event", {
|
|
12814
|
+
type,
|
|
12815
|
+
projectKey: project_key,
|
|
12816
|
+
timestamp
|
|
12817
|
+
});
|
|
12813
12818
|
const result = await db.query(`INSERT INTO events (type, project_key, timestamp, data)
|
|
12814
12819
|
VALUES ($1, $2, $3, $4)
|
|
12815
12820
|
RETURNING id, sequence`, [type, project_key, timestamp, JSON.stringify(rest)]);
|
|
@@ -12818,6 +12823,13 @@ async function appendEvent(event, projectPath) {
|
|
|
12818
12823
|
throw new Error("Failed to insert event - no row returned");
|
|
12819
12824
|
}
|
|
12820
12825
|
const { id, sequence } = row;
|
|
12826
|
+
console.log("[SwarmMail] Event appended", {
|
|
12827
|
+
type,
|
|
12828
|
+
id,
|
|
12829
|
+
sequence,
|
|
12830
|
+
projectKey: project_key
|
|
12831
|
+
});
|
|
12832
|
+
console.debug("[SwarmMail] Updating materialized views", { type, id });
|
|
12821
12833
|
await updateMaterializedViews(db, { ...event, id, sequence });
|
|
12822
12834
|
return { ...event, id, sequence };
|
|
12823
12835
|
}
|
|
@@ -12841,9 +12853,13 @@ async function appendEvents(events, projectPath) {
|
|
|
12841
12853
|
results.push(enrichedEvent);
|
|
12842
12854
|
}
|
|
12843
12855
|
await db.exec("COMMIT");
|
|
12844
|
-
} catch (
|
|
12845
|
-
|
|
12846
|
-
|
|
12856
|
+
} catch (e) {
|
|
12857
|
+
try {
|
|
12858
|
+
await db.exec("ROLLBACK");
|
|
12859
|
+
} catch (rollbackError) {
|
|
12860
|
+
console.error("[SwarmMail] ROLLBACK failed:", rollbackError);
|
|
12861
|
+
}
|
|
12862
|
+
throw e;
|
|
12847
12863
|
}
|
|
12848
12864
|
return results;
|
|
12849
12865
|
}
|
|
@@ -12946,33 +12962,42 @@ async function replayEvents(options2 = {}, projectPath) {
|
|
|
12946
12962
|
};
|
|
12947
12963
|
}
|
|
12948
12964
|
async function updateMaterializedViews(db, event) {
|
|
12949
|
-
|
|
12950
|
-
|
|
12951
|
-
|
|
12952
|
-
|
|
12953
|
-
|
|
12954
|
-
|
|
12955
|
-
|
|
12956
|
-
|
|
12957
|
-
|
|
12958
|
-
|
|
12959
|
-
|
|
12960
|
-
|
|
12961
|
-
|
|
12962
|
-
|
|
12963
|
-
|
|
12964
|
-
|
|
12965
|
-
|
|
12966
|
-
|
|
12967
|
-
|
|
12968
|
-
|
|
12969
|
-
|
|
12970
|
-
|
|
12971
|
-
|
|
12972
|
-
|
|
12973
|
-
|
|
12974
|
-
|
|
12975
|
-
|
|
12965
|
+
try {
|
|
12966
|
+
switch (event.type) {
|
|
12967
|
+
case "agent_registered":
|
|
12968
|
+
await handleAgentRegistered(db, event);
|
|
12969
|
+
break;
|
|
12970
|
+
case "agent_active":
|
|
12971
|
+
await db.query(`UPDATE agents SET last_active_at = $1 WHERE project_key = $2 AND name = $3`, [event.timestamp, event.project_key, event.agent_name]);
|
|
12972
|
+
break;
|
|
12973
|
+
case "message_sent":
|
|
12974
|
+
await handleMessageSent(db, event);
|
|
12975
|
+
break;
|
|
12976
|
+
case "message_read":
|
|
12977
|
+
await db.query(`UPDATE message_recipients SET read_at = $1 WHERE message_id = $2 AND agent_name = $3`, [event.timestamp, event.message_id, event.agent_name]);
|
|
12978
|
+
break;
|
|
12979
|
+
case "message_acked":
|
|
12980
|
+
await db.query(`UPDATE message_recipients SET acked_at = $1 WHERE message_id = $2 AND agent_name = $3`, [event.timestamp, event.message_id, event.agent_name]);
|
|
12981
|
+
break;
|
|
12982
|
+
case "file_reserved":
|
|
12983
|
+
await handleFileReserved(db, event);
|
|
12984
|
+
break;
|
|
12985
|
+
case "file_released":
|
|
12986
|
+
await handleFileReleased(db, event);
|
|
12987
|
+
break;
|
|
12988
|
+
case "task_started":
|
|
12989
|
+
case "task_progress":
|
|
12990
|
+
case "task_completed":
|
|
12991
|
+
case "task_blocked":
|
|
12992
|
+
break;
|
|
12993
|
+
}
|
|
12994
|
+
} catch (error45) {
|
|
12995
|
+
console.error("[SwarmMail] Failed to update materialized views", {
|
|
12996
|
+
eventType: event.type,
|
|
12997
|
+
eventId: event.id,
|
|
12998
|
+
error: error45
|
|
12999
|
+
});
|
|
13000
|
+
throw error45;
|
|
12976
13001
|
}
|
|
12977
13002
|
}
|
|
12978
13003
|
async function handleAgentRegistered(db, event) {
|
|
@@ -12992,6 +13017,12 @@ async function handleAgentRegistered(db, event) {
|
|
|
12992
13017
|
]);
|
|
12993
13018
|
}
|
|
12994
13019
|
async function handleMessageSent(db, event) {
|
|
13020
|
+
console.log("[SwarmMail] Handling message sent event", {
|
|
13021
|
+
from: event.from_agent,
|
|
13022
|
+
to: event.to_agents,
|
|
13023
|
+
subject: event.subject,
|
|
13024
|
+
projectKey: event.project_key
|
|
13025
|
+
});
|
|
12995
13026
|
const result = await db.query(`INSERT INTO messages (project_key, from_agent, subject, body, thread_id, importance, ack_required, created_at)
|
|
12996
13027
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
|
12997
13028
|
RETURNING id`, [
|
|
@@ -13009,24 +13040,42 @@ async function handleMessageSent(db, event) {
|
|
|
13009
13040
|
throw new Error("Failed to insert message - no row returned");
|
|
13010
13041
|
}
|
|
13011
13042
|
const messageId = msgRow.id;
|
|
13012
|
-
|
|
13043
|
+
if (event.to_agents.length > 0) {
|
|
13044
|
+
const values = event.to_agents.map((_, i) => `($1, $${i + 2})`).join(", ");
|
|
13045
|
+
const params = [messageId, ...event.to_agents];
|
|
13013
13046
|
await db.query(`INSERT INTO message_recipients (message_id, agent_name)
|
|
13014
|
-
VALUES
|
|
13015
|
-
ON CONFLICT DO NOTHING`,
|
|
13047
|
+
VALUES ${values}
|
|
13048
|
+
ON CONFLICT DO NOTHING`, params);
|
|
13049
|
+
console.log("[SwarmMail] Message recipients inserted", {
|
|
13050
|
+
messageId,
|
|
13051
|
+
recipientCount: event.to_agents.length
|
|
13052
|
+
});
|
|
13016
13053
|
}
|
|
13017
13054
|
}
|
|
13018
13055
|
async function handleFileReserved(db, event) {
|
|
13019
|
-
|
|
13020
|
-
|
|
13021
|
-
|
|
13056
|
+
console.log("[SwarmMail] Handling file reservation event", {
|
|
13057
|
+
agent: event.agent_name,
|
|
13058
|
+
paths: event.paths,
|
|
13059
|
+
exclusive: event.exclusive,
|
|
13060
|
+
projectKey: event.project_key
|
|
13061
|
+
});
|
|
13062
|
+
if (event.paths.length > 0) {
|
|
13063
|
+
const values = event.paths.map((_, i) => `($1, $2, $${i + 3}, $${event.paths.length + 3}, $${event.paths.length + 4}, $${event.paths.length + 5}, $${event.paths.length + 6})`).join(", ");
|
|
13064
|
+
const params = [
|
|
13022
13065
|
event.project_key,
|
|
13023
13066
|
event.agent_name,
|
|
13024
|
-
|
|
13067
|
+
...event.paths,
|
|
13025
13068
|
event.exclusive,
|
|
13026
13069
|
event.reason || null,
|
|
13027
13070
|
event.timestamp,
|
|
13028
13071
|
event.expires_at
|
|
13029
|
-
]
|
|
13072
|
+
];
|
|
13073
|
+
await db.query(`INSERT INTO reservations (project_key, agent_name, path_pattern, exclusive, reason, created_at, expires_at)
|
|
13074
|
+
VALUES ${values}`, params);
|
|
13075
|
+
console.log("[SwarmMail] File reservations inserted", {
|
|
13076
|
+
agent: event.agent_name,
|
|
13077
|
+
reservationCount: event.paths.length
|
|
13078
|
+
});
|
|
13030
13079
|
}
|
|
13031
13080
|
}
|
|
13032
13081
|
async function handleFileReleased(db, event) {
|
|
@@ -14592,6 +14641,12 @@ async function checkConflicts(projectKey, agentName, paths, projectPath) {
|
|
|
14592
14641
|
}
|
|
14593
14642
|
for (const path2 of paths) {
|
|
14594
14643
|
if (pathMatches(path2, reservation.path_pattern)) {
|
|
14644
|
+
console.warn("[SwarmMail] Conflict detected", {
|
|
14645
|
+
path: path2,
|
|
14646
|
+
holder: reservation.agent_name,
|
|
14647
|
+
pattern: reservation.path_pattern,
|
|
14648
|
+
requestedBy: agentName
|
|
14649
|
+
});
|
|
14595
14650
|
conflicts.push({
|
|
14596
14651
|
path: path2,
|
|
14597
14652
|
holder: reservation.agent_name,
|
|
@@ -14601,6 +14656,13 @@ async function checkConflicts(projectKey, agentName, paths, projectPath) {
|
|
|
14601
14656
|
}
|
|
14602
14657
|
}
|
|
14603
14658
|
}
|
|
14659
|
+
if (conflicts.length > 0) {
|
|
14660
|
+
console.warn("[SwarmMail] Total conflicts detected", {
|
|
14661
|
+
count: conflicts.length,
|
|
14662
|
+
requestedBy: agentName,
|
|
14663
|
+
paths
|
|
14664
|
+
});
|
|
14665
|
+
}
|
|
14604
14666
|
return conflicts;
|
|
14605
14667
|
}
|
|
14606
14668
|
function pathMatches(path2, pattern) {
|
|
@@ -15271,6 +15333,7 @@ var init_migrations = __esm(() => {
|
|
|
15271
15333
|
// src/streams/index.ts
|
|
15272
15334
|
var exports_streams = {};
|
|
15273
15335
|
__export(exports_streams, {
|
|
15336
|
+
withTimeout: () => withTimeout,
|
|
15274
15337
|
sendSwarmMessage: () => sendSwarmMessage,
|
|
15275
15338
|
sendMessage: () => sendMessage,
|
|
15276
15339
|
sendAgentMessage: () => sendAgentMessage,
|
|
@@ -15343,6 +15406,10 @@ import { PGlite } from "@electric-sql/pglite";
|
|
|
15343
15406
|
import { existsSync, mkdirSync, appendFileSync } from "node:fs";
|
|
15344
15407
|
import { join } from "node:path";
|
|
15345
15408
|
import { homedir } from "node:os";
|
|
15409
|
+
async function withTimeout(promise2, ms, operation) {
|
|
15410
|
+
const timeout = new Promise((_, reject) => setTimeout(() => reject(new Error(`${operation} timed out after ${ms}ms`)), ms));
|
|
15411
|
+
return Promise.race([promise2, timeout]);
|
|
15412
|
+
}
|
|
15346
15413
|
function debugLog(message, data) {
|
|
15347
15414
|
const timestamp = new Date().toISOString();
|
|
15348
15415
|
const logLine = data ? `[${timestamp}] ${message}: ${JSON.stringify(data, null, 2)}
|
|
@@ -30697,14 +30764,35 @@ class SqliteRateLimiter {
|
|
|
30697
30764
|
}
|
|
30698
30765
|
return { allowed, remaining, resetAt };
|
|
30699
30766
|
}
|
|
30767
|
+
cleanup() {
|
|
30768
|
+
const BATCH_SIZE = 1000;
|
|
30769
|
+
const MAX_BATCHES = 10;
|
|
30770
|
+
const cutoff = Date.now() - 7200000;
|
|
30771
|
+
let totalDeleted = 0;
|
|
30772
|
+
for (let i = 0;i < MAX_BATCHES; i++) {
|
|
30773
|
+
const result = this.db.run(`DELETE FROM rate_limits
|
|
30774
|
+
WHERE rowid IN (
|
|
30775
|
+
SELECT rowid FROM rate_limits
|
|
30776
|
+
WHERE timestamp < ?
|
|
30777
|
+
LIMIT ?
|
|
30778
|
+
)`, [cutoff, BATCH_SIZE]);
|
|
30779
|
+
totalDeleted += result.changes;
|
|
30780
|
+
if (result.changes < BATCH_SIZE)
|
|
30781
|
+
break;
|
|
30782
|
+
}
|
|
30783
|
+
if (totalDeleted > 0) {
|
|
30784
|
+
console.log("[RateLimiter] Cleanup completed:", {
|
|
30785
|
+
deletedRows: totalDeleted
|
|
30786
|
+
});
|
|
30787
|
+
}
|
|
30788
|
+
}
|
|
30700
30789
|
async recordRequest(agentName, endpoint) {
|
|
30701
30790
|
const now = Date.now();
|
|
30702
30791
|
const stmt = this.db.prepare(`INSERT INTO rate_limits (agent_name, endpoint, window, timestamp) VALUES (?, ?, ?, ?)`);
|
|
30703
30792
|
stmt.run(agentName, endpoint, "minute", now);
|
|
30704
30793
|
stmt.run(agentName, endpoint, "hour", now);
|
|
30705
30794
|
if (Math.random() < 0.01) {
|
|
30706
|
-
|
|
30707
|
-
this.db.run(`DELETE FROM rate_limits WHERE timestamp < ?`, [cutoff]);
|
|
30795
|
+
this.cleanup();
|
|
30708
30796
|
}
|
|
30709
30797
|
}
|
|
30710
30798
|
async close() {
|
|
@@ -32754,6 +32842,36 @@ class ErrorAccumulator {
|
|
|
32754
32842
|
};
|
|
32755
32843
|
}
|
|
32756
32844
|
}
|
|
32845
|
+
function formatMemoryStoreOnSuccess(beadId, summary, filesTouched, strategy) {
|
|
32846
|
+
const strategyInfo = strategy ? ` using ${strategy} strategy` : "";
|
|
32847
|
+
return {
|
|
32848
|
+
information: `Task "${beadId}" completed successfully${strategyInfo}.
|
|
32849
|
+
Key insight: ${summary}
|
|
32850
|
+
Files touched: ${filesTouched.join(", ") || "none"}`,
|
|
32851
|
+
metadata: `swarm, success, ${beadId}, ${strategy || "completion"}`,
|
|
32852
|
+
instruction: "Store this successful completion in semantic-memory for future reference"
|
|
32853
|
+
};
|
|
32854
|
+
}
|
|
32855
|
+
function formatMemoryStoreOn3Strike(beadId, failures) {
|
|
32856
|
+
const failuresList = failures.map((f, i) => `${i + 1}. ${f.attempt} - Failed: ${f.reason}`).join(`
|
|
32857
|
+
`);
|
|
32858
|
+
return {
|
|
32859
|
+
information: `Architecture problem detected in ${beadId}: Task failed after 3 attempts.
|
|
32860
|
+
Attempts:
|
|
32861
|
+
${failuresList}
|
|
32862
|
+
|
|
32863
|
+
This indicates a structural issue requiring human decision, not another fix attempt.`,
|
|
32864
|
+
metadata: `architecture, 3-strike, ${beadId}, failure`,
|
|
32865
|
+
instruction: "Store this architectural problem in semantic-memory to avoid similar patterns in future"
|
|
32866
|
+
};
|
|
32867
|
+
}
|
|
32868
|
+
function formatMemoryQueryForDecomposition(task, limit = 3) {
|
|
32869
|
+
return {
|
|
32870
|
+
query: task,
|
|
32871
|
+
limit,
|
|
32872
|
+
instruction: "Query semantic-memory for relevant past learnings about similar tasks before decomposition"
|
|
32873
|
+
};
|
|
32874
|
+
}
|
|
32757
32875
|
|
|
32758
32876
|
// src/swarm.ts
|
|
32759
32877
|
init_skills();
|
|
@@ -33681,7 +33799,136 @@ ${args.context}` : `## Additional Context
|
|
|
33681
33799
|
},
|
|
33682
33800
|
validation_note: "Parse agent response as JSON and validate with swarm_validate_decomposition",
|
|
33683
33801
|
cass_history: cassResultInfo,
|
|
33684
|
-
skills: skillsInfo
|
|
33802
|
+
skills: skillsInfo,
|
|
33803
|
+
memory_query: formatMemoryQueryForDecomposition(args.task, 3)
|
|
33804
|
+
}, null, 2);
|
|
33805
|
+
}
|
|
33806
|
+
});
|
|
33807
|
+
var swarm_delegate_planning = tool({
|
|
33808
|
+
description: "Delegate task decomposition to a swarm/planner subagent. Returns a prompt to spawn the planner. Use this to keep coordinator context lean - all planning reasoning happens in the subagent.",
|
|
33809
|
+
args: {
|
|
33810
|
+
task: tool.schema.string().min(1).describe("The task to decompose"),
|
|
33811
|
+
context: tool.schema.string().optional().describe("Additional context to include"),
|
|
33812
|
+
max_subtasks: tool.schema.number().int().min(2).max(10).optional().default(5).describe("Maximum number of subtasks (default: 5)"),
|
|
33813
|
+
strategy: tool.schema.enum(["auto", "file-based", "feature-based", "risk-based"]).optional().default("auto").describe("Decomposition strategy (default: auto-detect)"),
|
|
33814
|
+
query_cass: tool.schema.boolean().optional().default(true).describe("Query CASS for similar past tasks (default: true)")
|
|
33815
|
+
},
|
|
33816
|
+
async execute(args) {
|
|
33817
|
+
let selectedStrategy;
|
|
33818
|
+
let strategyReasoning;
|
|
33819
|
+
if (args.strategy && args.strategy !== "auto") {
|
|
33820
|
+
selectedStrategy = args.strategy;
|
|
33821
|
+
strategyReasoning = `User-specified strategy: ${selectedStrategy}`;
|
|
33822
|
+
} else {
|
|
33823
|
+
const selection = selectStrategy(args.task);
|
|
33824
|
+
selectedStrategy = selection.strategy;
|
|
33825
|
+
strategyReasoning = selection.reasoning;
|
|
33826
|
+
}
|
|
33827
|
+
let cassContext = "";
|
|
33828
|
+
let cassResultInfo;
|
|
33829
|
+
if (args.query_cass !== false) {
|
|
33830
|
+
const cassResult = await queryCassHistory(args.task, 3);
|
|
33831
|
+
if (cassResult.status === "success") {
|
|
33832
|
+
cassContext = formatCassHistoryForPrompt(cassResult.data);
|
|
33833
|
+
cassResultInfo = {
|
|
33834
|
+
queried: true,
|
|
33835
|
+
results_found: cassResult.data.results.length,
|
|
33836
|
+
included_in_context: true
|
|
33837
|
+
};
|
|
33838
|
+
} else {
|
|
33839
|
+
cassResultInfo = {
|
|
33840
|
+
queried: true,
|
|
33841
|
+
results_found: 0,
|
|
33842
|
+
included_in_context: false,
|
|
33843
|
+
reason: cassResult.status
|
|
33844
|
+
};
|
|
33845
|
+
}
|
|
33846
|
+
} else {
|
|
33847
|
+
cassResultInfo = { queried: false, reason: "disabled" };
|
|
33848
|
+
}
|
|
33849
|
+
let skillsContext = "";
|
|
33850
|
+
let skillsInfo = {
|
|
33851
|
+
included: false
|
|
33852
|
+
};
|
|
33853
|
+
const allSkills = await listSkills();
|
|
33854
|
+
if (allSkills.length > 0) {
|
|
33855
|
+
skillsContext = await getSkillsContextForSwarm();
|
|
33856
|
+
const relevantSkills = await findRelevantSkills(args.task);
|
|
33857
|
+
skillsInfo = {
|
|
33858
|
+
included: true,
|
|
33859
|
+
count: allSkills.length,
|
|
33860
|
+
relevant: relevantSkills
|
|
33861
|
+
};
|
|
33862
|
+
if (relevantSkills.length > 0) {
|
|
33863
|
+
skillsContext += `
|
|
33864
|
+
|
|
33865
|
+
**Suggested skills for this task**: ${relevantSkills.join(", ")}`;
|
|
33866
|
+
}
|
|
33867
|
+
}
|
|
33868
|
+
const strategyGuidelines = formatStrategyGuidelines(selectedStrategy);
|
|
33869
|
+
const contextSection = args.context ? `## Additional Context
|
|
33870
|
+
${args.context}` : `## Additional Context
|
|
33871
|
+
(none provided)`;
|
|
33872
|
+
const planningPrompt = STRATEGY_DECOMPOSITION_PROMPT.replace("{task}", args.task).replace("{strategy_guidelines}", strategyGuidelines).replace("{context_section}", contextSection).replace("{cass_history}", cassContext || "").replace("{skills_context}", skillsContext || "").replace("{max_subtasks}", (args.max_subtasks ?? 5).toString());
|
|
33873
|
+
const subagentInstructions = `
|
|
33874
|
+
## CRITICAL: Output Format
|
|
33875
|
+
|
|
33876
|
+
You are a planner subagent. Your ONLY output must be valid JSON matching the BeadTree schema.
|
|
33877
|
+
|
|
33878
|
+
DO NOT include:
|
|
33879
|
+
- Explanatory text before or after the JSON
|
|
33880
|
+
- Markdown code fences (\`\`\`json)
|
|
33881
|
+
- Commentary or reasoning
|
|
33882
|
+
|
|
33883
|
+
OUTPUT ONLY the raw JSON object.
|
|
33884
|
+
|
|
33885
|
+
## Example Output
|
|
33886
|
+
|
|
33887
|
+
{
|
|
33888
|
+
"epic": {
|
|
33889
|
+
"title": "Add user authentication",
|
|
33890
|
+
"description": "Implement OAuth-based authentication system"
|
|
33891
|
+
},
|
|
33892
|
+
"subtasks": [
|
|
33893
|
+
{
|
|
33894
|
+
"title": "Set up OAuth provider",
|
|
33895
|
+
"description": "Configure OAuth client credentials and redirect URLs",
|
|
33896
|
+
"files": ["src/auth/oauth.ts", "src/config/auth.ts"],
|
|
33897
|
+
"dependencies": [],
|
|
33898
|
+
"estimated_complexity": 2
|
|
33899
|
+
},
|
|
33900
|
+
{
|
|
33901
|
+
"title": "Create auth routes",
|
|
33902
|
+
"description": "Implement login, logout, and callback routes",
|
|
33903
|
+
"files": ["src/app/api/auth/[...nextauth]/route.ts"],
|
|
33904
|
+
"dependencies": [0],
|
|
33905
|
+
"estimated_complexity": 3
|
|
33906
|
+
}
|
|
33907
|
+
]
|
|
33908
|
+
}
|
|
33909
|
+
|
|
33910
|
+
Now generate the BeadTree for the given task.`;
|
|
33911
|
+
const fullPrompt = `${planningPrompt}
|
|
33912
|
+
|
|
33913
|
+
${subagentInstructions}`;
|
|
33914
|
+
return JSON.stringify({
|
|
33915
|
+
prompt: fullPrompt,
|
|
33916
|
+
subagent_type: "swarm/planner",
|
|
33917
|
+
description: "Task decomposition planning",
|
|
33918
|
+
strategy: {
|
|
33919
|
+
selected: selectedStrategy,
|
|
33920
|
+
reasoning: strategyReasoning
|
|
33921
|
+
},
|
|
33922
|
+
expected_output: "BeadTree JSON (raw JSON, no markdown)",
|
|
33923
|
+
next_steps: [
|
|
33924
|
+
"1. Spawn subagent with Task tool using returned prompt",
|
|
33925
|
+
"2. Parse subagent response as JSON",
|
|
33926
|
+
"3. Validate with swarm_validate_decomposition",
|
|
33927
|
+
"4. Create beads with beads_create_epic"
|
|
33928
|
+
],
|
|
33929
|
+
cass_history: cassResultInfo,
|
|
33930
|
+
skills: skillsInfo,
|
|
33931
|
+
memory_query: formatMemoryQueryForDecomposition(args.task, 3)
|
|
33685
33932
|
}, null, 2);
|
|
33686
33933
|
}
|
|
33687
33934
|
});
|
|
@@ -33737,7 +33984,8 @@ var swarm_decompose = tool({
|
|
|
33737
33984
|
]
|
|
33738
33985
|
},
|
|
33739
33986
|
validation_note: "Parse agent response as JSON and validate with BeadTreeSchema from schemas/bead.ts",
|
|
33740
|
-
cass_history: cassResultInfo
|
|
33987
|
+
cass_history: cassResultInfo,
|
|
33988
|
+
memory_query: formatMemoryQueryForDecomposition(args.task, 3)
|
|
33741
33989
|
}, null, 2);
|
|
33742
33990
|
}
|
|
33743
33991
|
});
|
|
@@ -34254,7 +34502,7 @@ var swarm_complete = tool({
|
|
|
34254
34502
|
threadId: epicId,
|
|
34255
34503
|
importance: "normal"
|
|
34256
34504
|
});
|
|
34257
|
-
|
|
34505
|
+
const response = {
|
|
34258
34506
|
success: true,
|
|
34259
34507
|
bead_id: args.bead_id,
|
|
34260
34508
|
closed: true,
|
|
@@ -34290,8 +34538,10 @@ Did you learn anything reusable during this subtask? Consider:
|
|
|
34290
34538
|
|
|
34291
34539
|
If you discovered something valuable, use \`swarm_learn\` or \`skills_create\` to preserve it as a skill for future swarms.
|
|
34292
34540
|
|
|
34293
|
-
Files touched: ${args.files_touched?.join(", ") || "none recorded"}
|
|
34294
|
-
|
|
34541
|
+
Files touched: ${args.files_touched?.join(", ") || "none recorded"}`,
|
|
34542
|
+
memory_store: formatMemoryStoreOnSuccess(args.bead_id, args.summary, args.files_touched || [])
|
|
34543
|
+
};
|
|
34544
|
+
return JSON.stringify(response, null, 2);
|
|
34295
34545
|
}
|
|
34296
34546
|
});
|
|
34297
34547
|
function classifyFailure(error45) {
|
|
@@ -34827,6 +35077,7 @@ var swarmTools = {
|
|
|
34827
35077
|
swarm_init,
|
|
34828
35078
|
swarm_select_strategy,
|
|
34829
35079
|
swarm_plan_prompt,
|
|
35080
|
+
swarm_delegate_planning,
|
|
34830
35081
|
swarm_decompose,
|
|
34831
35082
|
swarm_validate_decomposition,
|
|
34832
35083
|
swarm_status,
|
|
@@ -34873,14 +35124,18 @@ var swarm_check_strikes = tool({
|
|
|
34873
35124
|
}
|
|
34874
35125
|
const record2 = await addStrike(args.bead_id, args.attempt, args.reason, globalStrikeStorage);
|
|
34875
35126
|
const strikedOut = record2.strike_count >= 3;
|
|
34876
|
-
|
|
35127
|
+
const response = {
|
|
34877
35128
|
bead_id: args.bead_id,
|
|
34878
35129
|
strike_count: record2.strike_count,
|
|
34879
35130
|
is_striked_out: strikedOut,
|
|
34880
35131
|
failures: record2.failures,
|
|
34881
35132
|
message: strikedOut ? "⚠️ STRUCK OUT: 3 strikes reached. STOP and question the architecture." : `Strike ${record2.strike_count} recorded. ${3 - record2.strike_count} remaining.`,
|
|
34882
35133
|
warning: strikedOut ? "DO NOT attempt Fix #4. Call with action=get_prompt for architecture review." : undefined
|
|
34883
|
-
}
|
|
35134
|
+
};
|
|
35135
|
+
if (strikedOut) {
|
|
35136
|
+
response.memory_store = formatMemoryStoreOn3Strike(args.bead_id, record2.failures);
|
|
35137
|
+
}
|
|
35138
|
+
return JSON.stringify(response, null, 2);
|
|
34884
35139
|
}
|
|
34885
35140
|
case "clear": {
|
|
34886
35141
|
await clearStrikes(args.bead_id, globalStrikeStorage);
|