opencode-swarm-plugin 0.25.1 → 0.25.3
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 +2 -2
- package/CHANGELOG.md +28 -0
- package/dist/beads.d.ts +6 -0
- package/dist/beads.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +213 -289
- package/dist/plugin.js +212 -294
- package/dist/rate-limiter.d.ts.map +1 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/swarm-orchestrate.d.ts.map +1 -1
- package/dist/swarm-prompts.d.ts +1 -1
- package/dist/swarm-prompts.d.ts.map +1 -1
- package/docs/swarm-mail-architecture.md +1 -1
- package/package.json +2 -2
- package/src/beads.integration.test.ts +55 -61
- package/src/beads.ts +239 -410
- package/src/index.ts +1 -15
- package/src/rate-limiter.ts +0 -5
- package/src/storage.ts +0 -9
- package/src/swarm-mail.integration.test.ts +5 -1
- package/src/swarm-orchestrate.ts +24 -14
- package/src/swarm-prompts.ts +21 -2
- package/src/swarm.integration.test.ts +94 -246
- package/src/agent-mail.integration.test.ts +0 -1429
package/dist/plugin.js
CHANGED
|
@@ -27053,7 +27053,11 @@ echo "Project directory: $1"
|
|
|
27053
27053
|
|
|
27054
27054
|
// src/beads.ts
|
|
27055
27055
|
init_dist();
|
|
27056
|
-
|
|
27056
|
+
import {
|
|
27057
|
+
createBeadsAdapter,
|
|
27058
|
+
FlushManager,
|
|
27059
|
+
getSwarmMail
|
|
27060
|
+
} from "swarm-mail";
|
|
27057
27061
|
|
|
27058
27062
|
// src/schemas/bead.ts
|
|
27059
27063
|
init_zod();
|
|
@@ -27598,20 +27602,6 @@ function setBeadsWorkingDirectory(directory) {
|
|
|
27598
27602
|
function getBeadsWorkingDirectory() {
|
|
27599
27603
|
return beadsWorkingDirectory || process.cwd();
|
|
27600
27604
|
}
|
|
27601
|
-
async function runBdCommand(args) {
|
|
27602
|
-
const cwd = getBeadsWorkingDirectory();
|
|
27603
|
-
const proc = Bun.spawn(["bd", ...args], {
|
|
27604
|
-
cwd,
|
|
27605
|
-
stdout: "pipe",
|
|
27606
|
-
stderr: "pipe"
|
|
27607
|
-
});
|
|
27608
|
-
const [stdout, stderr] = await Promise.all([
|
|
27609
|
-
new Response(proc.stdout).text(),
|
|
27610
|
-
new Response(proc.stderr).text()
|
|
27611
|
-
]);
|
|
27612
|
-
const exitCode = await proc.exited;
|
|
27613
|
-
return { exitCode, stdout, stderr };
|
|
27614
|
-
}
|
|
27615
27605
|
async function runGitCommand(args) {
|
|
27616
27606
|
const cwd = getBeadsWorkingDirectory();
|
|
27617
27607
|
const proc = Bun.spawn(["git", ...args], {
|
|
@@ -27639,63 +27629,33 @@ class BeadError extends Error {
|
|
|
27639
27629
|
this.name = "BeadError";
|
|
27640
27630
|
}
|
|
27641
27631
|
}
|
|
27642
|
-
|
|
27643
|
-
|
|
27644
|
-
|
|
27645
|
-
|
|
27646
|
-
super(message);
|
|
27647
|
-
this.zodError = zodError;
|
|
27648
|
-
this.name = "BeadValidationError";
|
|
27632
|
+
var adapterCache = new Map;
|
|
27633
|
+
async function getBeadsAdapter(projectKey) {
|
|
27634
|
+
if (adapterCache.has(projectKey)) {
|
|
27635
|
+
return adapterCache.get(projectKey);
|
|
27649
27636
|
}
|
|
27637
|
+
const swarmMail = await getSwarmMail(projectKey);
|
|
27638
|
+
const db = await swarmMail.getDatabase();
|
|
27639
|
+
const adapter = createBeadsAdapter(db, projectKey);
|
|
27640
|
+
await adapter.runMigrations();
|
|
27641
|
+
adapterCache.set(projectKey, adapter);
|
|
27642
|
+
return adapter;
|
|
27650
27643
|
}
|
|
27651
|
-
function
|
|
27652
|
-
|
|
27653
|
-
|
|
27654
|
-
|
|
27655
|
-
|
|
27656
|
-
|
|
27657
|
-
|
|
27658
|
-
|
|
27659
|
-
|
|
27660
|
-
|
|
27661
|
-
|
|
27662
|
-
|
|
27663
|
-
|
|
27664
|
-
|
|
27665
|
-
|
|
27666
|
-
parts.push("--id", args.id);
|
|
27667
|
-
}
|
|
27668
|
-
parts.push("--json");
|
|
27669
|
-
return parts;
|
|
27670
|
-
}
|
|
27671
|
-
function parseBead(output) {
|
|
27672
|
-
try {
|
|
27673
|
-
const parsed = JSON.parse(output);
|
|
27674
|
-
const data = Array.isArray(parsed) ? parsed[0] : parsed;
|
|
27675
|
-
if (!data) {
|
|
27676
|
-
throw new BeadError("No bead data in response. The bd CLI may not be installed or returned unexpected output. Try: Run 'bd --version' to verify installation, or check if .beads/ directory exists in project.", "parse");
|
|
27677
|
-
}
|
|
27678
|
-
return BeadSchema.parse(data);
|
|
27679
|
-
} catch (error45) {
|
|
27680
|
-
if (error45 instanceof exports_external.ZodError) {
|
|
27681
|
-
throw new BeadValidationError(`Invalid bead data: ${error45.message}`, error45);
|
|
27682
|
-
}
|
|
27683
|
-
if (error45 instanceof BeadError) {
|
|
27684
|
-
throw error45;
|
|
27685
|
-
}
|
|
27686
|
-
throw new BeadError(`Failed to parse bead JSON because output is malformed. Try: Check if bd CLI is up to date with 'bd --version' (need v1.0.0+), or inspect output: ${output.slice(0, 100)}`, "parse");
|
|
27687
|
-
}
|
|
27688
|
-
}
|
|
27689
|
-
function parseBeads(output) {
|
|
27690
|
-
try {
|
|
27691
|
-
const parsed = JSON.parse(output);
|
|
27692
|
-
return exports_external.array(BeadSchema).parse(parsed);
|
|
27693
|
-
} catch (error45) {
|
|
27694
|
-
if (error45 instanceof exports_external.ZodError) {
|
|
27695
|
-
throw new BeadValidationError(`Invalid beads data: ${error45.message}`, error45);
|
|
27696
|
-
}
|
|
27697
|
-
throw new BeadError(`Failed to parse beads JSON because output is malformed. Try: Check if bd CLI is up to date with 'bd --version' (need v1.0.0+), or inspect output: ${output.slice(0, 100)}`, "parse");
|
|
27698
|
-
}
|
|
27644
|
+
function formatBeadForOutput(adapterBead) {
|
|
27645
|
+
return {
|
|
27646
|
+
id: adapterBead.id,
|
|
27647
|
+
title: adapterBead.title,
|
|
27648
|
+
description: adapterBead.description || "",
|
|
27649
|
+
status: adapterBead.status,
|
|
27650
|
+
priority: adapterBead.priority,
|
|
27651
|
+
issue_type: adapterBead.type,
|
|
27652
|
+
created_at: new Date(adapterBead.created_at).toISOString(),
|
|
27653
|
+
updated_at: new Date(adapterBead.updated_at).toISOString(),
|
|
27654
|
+
closed_at: adapterBead.closed_at ? new Date(adapterBead.closed_at).toISOString() : undefined,
|
|
27655
|
+
parent_id: adapterBead.parent_id || undefined,
|
|
27656
|
+
dependencies: [],
|
|
27657
|
+
metadata: {}
|
|
27658
|
+
};
|
|
27699
27659
|
}
|
|
27700
27660
|
var beads_create = tool({
|
|
27701
27661
|
description: "Create a new bead with type-safe validation",
|
|
@@ -27708,20 +27668,23 @@ var beads_create = tool({
|
|
|
27708
27668
|
},
|
|
27709
27669
|
async execute(args, ctx) {
|
|
27710
27670
|
const validated = BeadCreateArgsSchema.parse(args);
|
|
27711
|
-
const
|
|
27712
|
-
const
|
|
27713
|
-
|
|
27714
|
-
|
|
27715
|
-
|
|
27716
|
-
|
|
27717
|
-
|
|
27718
|
-
|
|
27719
|
-
|
|
27720
|
-
|
|
27721
|
-
|
|
27671
|
+
const projectKey = getBeadsWorkingDirectory();
|
|
27672
|
+
const adapter = await getBeadsAdapter(projectKey);
|
|
27673
|
+
try {
|
|
27674
|
+
const bead = await adapter.createBead(projectKey, {
|
|
27675
|
+
title: validated.title,
|
|
27676
|
+
type: validated.type || "task",
|
|
27677
|
+
priority: validated.priority ?? 2,
|
|
27678
|
+
description: validated.description,
|
|
27679
|
+
parent_id: validated.parent_id
|
|
27680
|
+
});
|
|
27681
|
+
await adapter.markDirty(projectKey, bead.id);
|
|
27682
|
+
const formatted = formatBeadForOutput(bead);
|
|
27683
|
+
return JSON.stringify(formatted, null, 2);
|
|
27684
|
+
} catch (error45) {
|
|
27685
|
+
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
27686
|
+
throw new BeadError(`Failed to create bead: ${message}`, "beads_create");
|
|
27722
27687
|
}
|
|
27723
|
-
const bead = parseBead(stdout);
|
|
27724
|
-
return JSON.stringify(bead, null, 2);
|
|
27725
27688
|
}
|
|
27726
27689
|
});
|
|
27727
27690
|
var beads_create_epic = tool({
|
|
@@ -27747,44 +27710,32 @@ var beads_create_epic = tool({
|
|
|
27747
27710
|
},
|
|
27748
27711
|
async execute(args, ctx) {
|
|
27749
27712
|
const validated = EpicCreateArgsSchema.parse(args);
|
|
27713
|
+
const projectKey = getBeadsWorkingDirectory();
|
|
27714
|
+
const adapter = await getBeadsAdapter(projectKey);
|
|
27750
27715
|
const created = [];
|
|
27751
27716
|
try {
|
|
27752
|
-
const
|
|
27717
|
+
const epic = await adapter.createBead(projectKey, {
|
|
27753
27718
|
title: validated.epic_title,
|
|
27754
27719
|
type: "epic",
|
|
27755
27720
|
priority: 1,
|
|
27756
|
-
description: validated.epic_description
|
|
27757
|
-
id: validated.epic_id
|
|
27721
|
+
description: validated.epic_description
|
|
27758
27722
|
});
|
|
27759
|
-
|
|
27760
|
-
if (epicResult.exitCode !== 0) {
|
|
27761
|
-
throw new BeadError(`Failed to create epic because bd command failed: ${epicResult.stderr}. Try: Verify beads initialized with 'bd init', check if .beads/ directory is writable, or run 'bd list' to test basic functionality.`, epicCmd.join(" "), epicResult.exitCode);
|
|
27762
|
-
}
|
|
27763
|
-
const epic = parseBead(epicResult.stdout);
|
|
27723
|
+
await adapter.markDirty(projectKey, epic.id);
|
|
27764
27724
|
created.push(epic);
|
|
27765
27725
|
for (const subtask of validated.subtasks) {
|
|
27766
|
-
|
|
27767
|
-
if (validated.epic_id && subtask.id_suffix) {
|
|
27768
|
-
subtaskId = `${validated.epic_id}.${subtask.id_suffix}`;
|
|
27769
|
-
}
|
|
27770
|
-
const subtaskCmd = buildCreateCommand({
|
|
27726
|
+
const subtaskBead = await adapter.createBead(projectKey, {
|
|
27771
27727
|
title: subtask.title,
|
|
27772
27728
|
type: "task",
|
|
27773
27729
|
priority: subtask.priority ?? 2,
|
|
27774
|
-
parent_id: epic.id
|
|
27775
|
-
id: subtaskId
|
|
27730
|
+
parent_id: epic.id
|
|
27776
27731
|
});
|
|
27777
|
-
|
|
27778
|
-
if (subtaskResult.exitCode !== 0) {
|
|
27779
|
-
throw new BeadError(`Failed to create subtask because bd command failed: ${subtaskResult.stderr}. Try: Check if parent epic exists with 'bd show ${epic.id}', verify .beads/issues.jsonl is not corrupted, or check for invalid characters in title.`, subtaskCmd.join(" "), subtaskResult.exitCode);
|
|
27780
|
-
}
|
|
27781
|
-
const subtaskBead = parseBead(subtaskResult.stdout);
|
|
27732
|
+
await adapter.markDirty(projectKey, subtaskBead.id);
|
|
27782
27733
|
created.push(subtaskBead);
|
|
27783
27734
|
}
|
|
27784
27735
|
const result = {
|
|
27785
27736
|
success: true,
|
|
27786
|
-
epic,
|
|
27787
|
-
subtasks: created.slice(1)
|
|
27737
|
+
epic: formatBeadForOutput(epic),
|
|
27738
|
+
subtasks: created.slice(1).map((b) => formatBeadForOutput(b))
|
|
27788
27739
|
};
|
|
27789
27740
|
if (args.project_key) {
|
|
27790
27741
|
try {
|
|
@@ -27809,23 +27760,12 @@ var beads_create_epic = tool({
|
|
|
27809
27760
|
}
|
|
27810
27761
|
return JSON.stringify(result, null, 2);
|
|
27811
27762
|
} catch (error45) {
|
|
27812
|
-
const rollbackCommands = [];
|
|
27813
27763
|
const rollbackErrors = [];
|
|
27814
27764
|
for (const bead of created) {
|
|
27815
27765
|
try {
|
|
27816
|
-
|
|
27817
|
-
"
|
|
27818
|
-
|
|
27819
|
-
"--reason",
|
|
27820
|
-
"Rollback partial epic",
|
|
27821
|
-
"--json"
|
|
27822
|
-
];
|
|
27823
|
-
const rollbackResult = await runBdCommand(closeArgs);
|
|
27824
|
-
if (rollbackResult.exitCode === 0) {
|
|
27825
|
-
rollbackCommands.push(`bd close ${bead.id} --reason "Rollback partial epic"`);
|
|
27826
|
-
} else {
|
|
27827
|
-
rollbackErrors.push(`${bead.id}: exit ${rollbackResult.exitCode} - ${rollbackResult.stderr.trim()}`);
|
|
27828
|
-
}
|
|
27766
|
+
await adapter.deleteBead(projectKey, bead.id, {
|
|
27767
|
+
reason: "Rollback partial epic"
|
|
27768
|
+
});
|
|
27829
27769
|
} catch (rollbackError) {
|
|
27830
27770
|
const errMsg = rollbackError instanceof Error ? rollbackError.message : String(rollbackError);
|
|
27831
27771
|
console.error(`Failed to rollback bead ${bead.id}:`, rollbackError);
|
|
@@ -27833,14 +27773,9 @@ var beads_create_epic = tool({
|
|
|
27833
27773
|
}
|
|
27834
27774
|
}
|
|
27835
27775
|
const errorMsg = error45 instanceof Error ? error45.message : String(error45);
|
|
27836
|
-
let rollbackInfo =
|
|
27837
|
-
if (rollbackCommands.length > 0) {
|
|
27838
|
-
rollbackInfo += `
|
|
27776
|
+
let rollbackInfo = `
|
|
27839
27777
|
|
|
27840
|
-
Rolled back ${
|
|
27841
|
-
${rollbackCommands.join(`
|
|
27842
|
-
`)}`;
|
|
27843
|
-
}
|
|
27778
|
+
Rolled back ${created.length - rollbackErrors.length} bead(s)`;
|
|
27844
27779
|
if (rollbackErrors.length > 0) {
|
|
27845
27780
|
rollbackInfo += `
|
|
27846
27781
|
|
|
@@ -27848,12 +27783,7 @@ Rollback failures (${rollbackErrors.length}):
|
|
|
27848
27783
|
${rollbackErrors.join(`
|
|
27849
27784
|
`)}`;
|
|
27850
27785
|
}
|
|
27851
|
-
|
|
27852
|
-
rollbackInfo = `
|
|
27853
|
-
|
|
27854
|
-
No beads to rollback.`;
|
|
27855
|
-
}
|
|
27856
|
-
throw new BeadError(`Epic creation failed: ${errorMsg}${rollbackInfo}. Try: If rollback failed, manually close beads with 'bd close <id> --reason "Rollback"', check .beads/issues.jsonl for partial state, or re-run beads_create_epic with corrected parameters.`, "beads_create_epic", 1);
|
|
27786
|
+
throw new BeadError(`Epic creation failed: ${errorMsg}${rollbackInfo}`, "beads_create_epic", 1);
|
|
27857
27787
|
}
|
|
27858
27788
|
}
|
|
27859
27789
|
});
|
|
@@ -27867,25 +27797,26 @@ var beads_query = tool({
|
|
|
27867
27797
|
},
|
|
27868
27798
|
async execute(args, ctx) {
|
|
27869
27799
|
const validated = BeadQueryArgsSchema.parse(args);
|
|
27870
|
-
|
|
27871
|
-
|
|
27872
|
-
|
|
27873
|
-
|
|
27874
|
-
|
|
27875
|
-
|
|
27876
|
-
|
|
27877
|
-
}
|
|
27878
|
-
|
|
27879
|
-
|
|
27800
|
+
const projectKey = getBeadsWorkingDirectory();
|
|
27801
|
+
const adapter = await getBeadsAdapter(projectKey);
|
|
27802
|
+
try {
|
|
27803
|
+
let beads;
|
|
27804
|
+
if (validated.ready) {
|
|
27805
|
+
const readyBead = await adapter.getNextReadyBead(projectKey);
|
|
27806
|
+
beads = readyBead ? [readyBead] : [];
|
|
27807
|
+
} else {
|
|
27808
|
+
beads = await adapter.queryBeads(projectKey, {
|
|
27809
|
+
status: validated.status,
|
|
27810
|
+
type: validated.type,
|
|
27811
|
+
limit: validated.limit || 20
|
|
27812
|
+
});
|
|
27880
27813
|
}
|
|
27814
|
+
const formatted = beads.map((b) => formatBeadForOutput(b));
|
|
27815
|
+
return JSON.stringify(formatted, null, 2);
|
|
27816
|
+
} catch (error45) {
|
|
27817
|
+
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
27818
|
+
throw new BeadError(`Failed to query beads: ${message}`, "beads_query");
|
|
27881
27819
|
}
|
|
27882
|
-
const result = await runBdCommand(cmd.slice(1));
|
|
27883
|
-
if (result.exitCode !== 0) {
|
|
27884
|
-
throw new BeadError(`Failed to query beads because bd command failed: ${result.stderr}. Try: Check if beads initialized with 'bd init', verify .beads/ directory exists, or run 'bd --version' to check CLI version.`, cmd.join(" "), result.exitCode);
|
|
27885
|
-
}
|
|
27886
|
-
const beads = parseBeads(result.stdout);
|
|
27887
|
-
const limited = beads.slice(0, validated.limit);
|
|
27888
|
-
return JSON.stringify(limited, null, 2);
|
|
27889
27820
|
}
|
|
27890
27821
|
});
|
|
27891
27822
|
var beads_update = tool({
|
|
@@ -27898,23 +27829,32 @@ var beads_update = tool({
|
|
|
27898
27829
|
},
|
|
27899
27830
|
async execute(args, ctx) {
|
|
27900
27831
|
const validated = BeadUpdateArgsSchema.parse(args);
|
|
27901
|
-
const
|
|
27902
|
-
|
|
27903
|
-
|
|
27904
|
-
|
|
27905
|
-
|
|
27906
|
-
|
|
27907
|
-
|
|
27908
|
-
|
|
27909
|
-
|
|
27910
|
-
|
|
27911
|
-
|
|
27912
|
-
|
|
27913
|
-
|
|
27914
|
-
|
|
27832
|
+
const projectKey = getBeadsWorkingDirectory();
|
|
27833
|
+
const adapter = await getBeadsAdapter(projectKey);
|
|
27834
|
+
try {
|
|
27835
|
+
let bead;
|
|
27836
|
+
if (validated.status) {
|
|
27837
|
+
bead = await adapter.changeBeadStatus(projectKey, validated.id, validated.status);
|
|
27838
|
+
}
|
|
27839
|
+
if (validated.description !== undefined || validated.priority !== undefined) {
|
|
27840
|
+
bead = await adapter.updateBead(projectKey, validated.id, {
|
|
27841
|
+
description: validated.description,
|
|
27842
|
+
priority: validated.priority
|
|
27843
|
+
});
|
|
27844
|
+
} else if (!validated.status) {
|
|
27845
|
+
const existingBead = await adapter.getBead(projectKey, validated.id);
|
|
27846
|
+
if (!existingBead) {
|
|
27847
|
+
throw new BeadError(`Bead not found: ${validated.id}`, "beads_update");
|
|
27848
|
+
}
|
|
27849
|
+
bead = existingBead;
|
|
27850
|
+
}
|
|
27851
|
+
await adapter.markDirty(projectKey, validated.id);
|
|
27852
|
+
const formatted = formatBeadForOutput(bead);
|
|
27853
|
+
return JSON.stringify(formatted, null, 2);
|
|
27854
|
+
} catch (error45) {
|
|
27855
|
+
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
27856
|
+
throw new BeadError(`Failed to update bead: ${message}`, "beads_update");
|
|
27915
27857
|
}
|
|
27916
|
-
const bead = parseBead(result.stdout);
|
|
27917
|
-
return JSON.stringify(bead, null, 2);
|
|
27918
27858
|
}
|
|
27919
27859
|
});
|
|
27920
27860
|
var beads_close = tool({
|
|
@@ -27925,20 +27865,16 @@ var beads_close = tool({
|
|
|
27925
27865
|
},
|
|
27926
27866
|
async execute(args, ctx) {
|
|
27927
27867
|
const validated = BeadCloseArgsSchema.parse(args);
|
|
27928
|
-
const
|
|
27929
|
-
|
|
27930
|
-
|
|
27931
|
-
validated.id,
|
|
27932
|
-
|
|
27933
|
-
validated.reason
|
|
27934
|
-
|
|
27935
|
-
|
|
27936
|
-
|
|
27937
|
-
if (result.exitCode !== 0) {
|
|
27938
|
-
throw new BeadError(`Failed to close bead because bd command failed: ${result.stderr}. Try: Verify bead exists and is not already closed with 'beads_query(status="closed")' or 'bd show ${validated.id}', check if bead ID is correct.`, cmd.join(" "), result.exitCode);
|
|
27868
|
+
const projectKey = getBeadsWorkingDirectory();
|
|
27869
|
+
const adapter = await getBeadsAdapter(projectKey);
|
|
27870
|
+
try {
|
|
27871
|
+
const bead = await adapter.closeBead(projectKey, validated.id, validated.reason);
|
|
27872
|
+
await adapter.markDirty(projectKey, validated.id);
|
|
27873
|
+
return `Closed ${bead.id}: ${validated.reason}`;
|
|
27874
|
+
} catch (error45) {
|
|
27875
|
+
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
27876
|
+
throw new BeadError(`Failed to close bead: ${message}`, "beads_close");
|
|
27939
27877
|
}
|
|
27940
|
-
const bead = parseBead(result.stdout);
|
|
27941
|
-
return `Closed ${bead.id}: ${validated.reason}`;
|
|
27942
27878
|
}
|
|
27943
27879
|
});
|
|
27944
27880
|
var beads_start = tool({
|
|
@@ -27947,34 +27883,35 @@ var beads_start = tool({
|
|
|
27947
27883
|
id: tool.schema.string().describe("Bead ID")
|
|
27948
27884
|
},
|
|
27949
27885
|
async execute(args, ctx) {
|
|
27950
|
-
const
|
|
27951
|
-
|
|
27952
|
-
|
|
27953
|
-
"
|
|
27954
|
-
|
|
27955
|
-
|
|
27956
|
-
|
|
27957
|
-
|
|
27958
|
-
throw new BeadError(`Failed to start bead
|
|
27886
|
+
const projectKey = getBeadsWorkingDirectory();
|
|
27887
|
+
const adapter = await getBeadsAdapter(projectKey);
|
|
27888
|
+
try {
|
|
27889
|
+
const bead = await adapter.changeBeadStatus(projectKey, args.id, "in_progress");
|
|
27890
|
+
await adapter.markDirty(projectKey, args.id);
|
|
27891
|
+
return `Started: ${bead.id}`;
|
|
27892
|
+
} catch (error45) {
|
|
27893
|
+
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
27894
|
+
throw new BeadError(`Failed to start bead: ${message}`, "beads_start");
|
|
27959
27895
|
}
|
|
27960
|
-
const bead = parseBead(result.stdout);
|
|
27961
|
-
return `Started: ${bead.id}`;
|
|
27962
27896
|
}
|
|
27963
27897
|
});
|
|
27964
27898
|
var beads_ready = tool({
|
|
27965
27899
|
description: "Get the next ready bead (unblocked, highest priority)",
|
|
27966
27900
|
args: {},
|
|
27967
27901
|
async execute(args, ctx) {
|
|
27968
|
-
const
|
|
27969
|
-
|
|
27970
|
-
|
|
27971
|
-
|
|
27972
|
-
|
|
27973
|
-
|
|
27974
|
-
|
|
27902
|
+
const projectKey = getBeadsWorkingDirectory();
|
|
27903
|
+
const adapter = await getBeadsAdapter(projectKey);
|
|
27904
|
+
try {
|
|
27905
|
+
const bead = await adapter.getNextReadyBead(projectKey);
|
|
27906
|
+
if (!bead) {
|
|
27907
|
+
return "No ready beads";
|
|
27908
|
+
}
|
|
27909
|
+
const formatted = formatBeadForOutput(bead);
|
|
27910
|
+
return JSON.stringify(formatted, null, 2);
|
|
27911
|
+
} catch (error45) {
|
|
27912
|
+
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
27913
|
+
throw new BeadError(`Failed to get ready beads: ${message}`, "beads_ready");
|
|
27975
27914
|
}
|
|
27976
|
-
const next = beads[0];
|
|
27977
|
-
return JSON.stringify(next, null, 2);
|
|
27978
27915
|
}
|
|
27979
27916
|
});
|
|
27980
27917
|
var beads_sync = tool({
|
|
@@ -27984,6 +27921,8 @@ var beads_sync = tool({
|
|
|
27984
27921
|
},
|
|
27985
27922
|
async execute(args, ctx) {
|
|
27986
27923
|
const autoPull = args.auto_pull ?? true;
|
|
27924
|
+
const projectKey = getBeadsWorkingDirectory();
|
|
27925
|
+
const adapter = await getBeadsAdapter(projectKey);
|
|
27987
27926
|
const TIMEOUT_MS = 30000;
|
|
27988
27927
|
const withTimeout = async (promise2, timeoutMs, operation) => {
|
|
27989
27928
|
let timeoutId;
|
|
@@ -27998,9 +27937,14 @@ var beads_sync = tool({
|
|
|
27998
27937
|
}
|
|
27999
27938
|
}
|
|
28000
27939
|
};
|
|
28001
|
-
const
|
|
28002
|
-
|
|
28003
|
-
|
|
27940
|
+
const flushManager = new FlushManager({
|
|
27941
|
+
adapter,
|
|
27942
|
+
projectKey,
|
|
27943
|
+
outputPath: `${projectKey}/.beads/issues.jsonl`
|
|
27944
|
+
});
|
|
27945
|
+
const flushResult = await withTimeout(flushManager.flush(), TIMEOUT_MS, "flush beads");
|
|
27946
|
+
if (flushResult.beadsExported === 0) {
|
|
27947
|
+
return "No beads to sync";
|
|
28004
27948
|
}
|
|
28005
27949
|
const beadsStatusResult = await runGitCommand([
|
|
28006
27950
|
"status",
|
|
@@ -28011,65 +27955,22 @@ var beads_sync = tool({
|
|
|
28011
27955
|
if (hasChanges) {
|
|
28012
27956
|
const addResult = await runGitCommand(["add", ".beads/"]);
|
|
28013
27957
|
if (addResult.exitCode !== 0) {
|
|
28014
|
-
throw new BeadError(`Failed to stage beads
|
|
27958
|
+
throw new BeadError(`Failed to stage beads: ${addResult.stderr}`, "git add .beads/", addResult.exitCode);
|
|
28015
27959
|
}
|
|
28016
27960
|
const commitResult = await withTimeout(runGitCommand(["commit", "-m", "chore: sync beads"]), TIMEOUT_MS, "git commit");
|
|
28017
27961
|
if (commitResult.exitCode !== 0 && !commitResult.stdout.includes("nothing to commit")) {
|
|
28018
|
-
throw new BeadError(`Failed to commit beads
|
|
27962
|
+
throw new BeadError(`Failed to commit beads: ${commitResult.stderr}`, "git commit", commitResult.exitCode);
|
|
28019
27963
|
}
|
|
28020
27964
|
}
|
|
28021
27965
|
if (autoPull) {
|
|
28022
|
-
const dirtyCheckResult = await runGitCommand([
|
|
28023
|
-
"status",
|
|
28024
|
-
"--porcelain",
|
|
28025
|
-
"--untracked-files=no"
|
|
28026
|
-
]);
|
|
28027
|
-
const hasDirtyFiles = dirtyCheckResult.stdout.trim() !== "";
|
|
28028
|
-
let didStash = false;
|
|
28029
|
-
if (hasDirtyFiles) {
|
|
28030
|
-
console.warn("[beads] Detected unstaged changes, stashing before pull...");
|
|
28031
|
-
const stashResult = await runGitCommand([
|
|
28032
|
-
"stash",
|
|
28033
|
-
"push",
|
|
28034
|
-
"-m",
|
|
28035
|
-
"beads_sync: auto-stash before pull",
|
|
28036
|
-
"--include-untracked"
|
|
28037
|
-
]);
|
|
28038
|
-
if (stashResult.exitCode === 0) {
|
|
28039
|
-
didStash = true;
|
|
28040
|
-
console.warn("[beads] Changes stashed successfully");
|
|
28041
|
-
} else {
|
|
28042
|
-
console.warn(`[beads] Stash failed (${stashResult.stderr}), attempting pull anyway...`);
|
|
28043
|
-
}
|
|
28044
|
-
}
|
|
28045
27966
|
const pullResult = await withTimeout(runGitCommand(["pull", "--rebase"]), TIMEOUT_MS, "git pull --rebase");
|
|
28046
|
-
if (didStash) {
|
|
28047
|
-
console.warn("[beads] Restoring stashed changes...");
|
|
28048
|
-
const unstashResult = await runGitCommand(["stash", "pop"]);
|
|
28049
|
-
if (unstashResult.exitCode !== 0) {
|
|
28050
|
-
console.error(`[beads] WARNING: Failed to restore stashed changes: ${unstashResult.stderr}`);
|
|
28051
|
-
console.error("[beads] Your changes are in 'git stash list' - run 'git stash pop' manually");
|
|
28052
|
-
} else {
|
|
28053
|
-
console.warn("[beads] Stashed changes restored");
|
|
28054
|
-
}
|
|
28055
|
-
}
|
|
28056
27967
|
if (pullResult.exitCode !== 0) {
|
|
28057
|
-
throw new BeadError(`Failed to pull
|
|
28058
|
-
}
|
|
28059
|
-
const importResult = await withTimeout(runBdCommand(["sync", "--import-only"]), TIMEOUT_MS, "bd sync --import-only");
|
|
28060
|
-
if (importResult.exitCode !== 0) {
|
|
28061
|
-
console.warn(`[beads] Import warning: ${importResult.stderr}`);
|
|
27968
|
+
throw new BeadError(`Failed to pull: ${pullResult.stderr}`, "git pull --rebase", pullResult.exitCode);
|
|
28062
27969
|
}
|
|
28063
27970
|
}
|
|
28064
27971
|
const pushResult = await withTimeout(runGitCommand(["push"]), TIMEOUT_MS, "git push");
|
|
28065
27972
|
if (pushResult.exitCode !== 0) {
|
|
28066
|
-
throw new BeadError(`Failed to push
|
|
28067
|
-
}
|
|
28068
|
-
const statusResult = await runGitCommand(["status", "--porcelain"]);
|
|
28069
|
-
const status = statusResult.stdout.trim();
|
|
28070
|
-
if (status !== "") {
|
|
28071
|
-
return `Beads synced and pushed, but working directory not clean:
|
|
28072
|
-
${status}`;
|
|
27973
|
+
throw new BeadError(`Failed to push: ${pushResult.stderr}`, "git push", pushResult.exitCode);
|
|
28073
27974
|
}
|
|
28074
27975
|
return "Beads synced and pushed successfully";
|
|
28075
27976
|
}
|
|
@@ -28081,30 +27982,30 @@ var beads_link_thread = tool({
|
|
|
28081
27982
|
thread_id: tool.schema.string().describe("Agent Mail thread ID")
|
|
28082
27983
|
},
|
|
28083
27984
|
async execute(args, ctx) {
|
|
28084
|
-
const
|
|
28085
|
-
|
|
28086
|
-
|
|
28087
|
-
|
|
28088
|
-
|
|
28089
|
-
|
|
28090
|
-
|
|
28091
|
-
|
|
28092
|
-
|
|
28093
|
-
|
|
28094
|
-
|
|
27985
|
+
const projectKey = getBeadsWorkingDirectory();
|
|
27986
|
+
const adapter = await getBeadsAdapter(projectKey);
|
|
27987
|
+
try {
|
|
27988
|
+
const bead = await adapter.getBead(projectKey, args.bead_id);
|
|
27989
|
+
if (!bead) {
|
|
27990
|
+
throw new BeadError(`Bead not found: ${args.bead_id}`, "beads_link_thread");
|
|
27991
|
+
}
|
|
27992
|
+
const existingDesc = bead.description || "";
|
|
27993
|
+
const threadMarker = `[thread:${args.thread_id}]`;
|
|
27994
|
+
if (existingDesc.includes(threadMarker)) {
|
|
27995
|
+
return `Bead ${args.bead_id} already linked to thread ${args.thread_id}`;
|
|
27996
|
+
}
|
|
27997
|
+
const newDesc = existingDesc ? `${existingDesc}
|
|
28095
27998
|
|
|
28096
27999
|
${threadMarker}` : threadMarker;
|
|
28097
|
-
|
|
28098
|
-
|
|
28099
|
-
|
|
28100
|
-
|
|
28101
|
-
|
|
28102
|
-
|
|
28103
|
-
|
|
28104
|
-
|
|
28105
|
-
throw new BeadError(`Failed to update bead because bd update command failed: ${updateResult.stderr}. Try: Verify bead exists with 'bd show ${args.bead_id}', check for invalid characters in description, or inspect .beads/issues.jsonl for corruption.`, `bd update ${args.bead_id} -d ...`, updateResult.exitCode);
|
|
28000
|
+
await adapter.updateBead(projectKey, args.bead_id, {
|
|
28001
|
+
description: newDesc
|
|
28002
|
+
});
|
|
28003
|
+
await adapter.markDirty(projectKey, args.bead_id);
|
|
28004
|
+
return `Linked bead ${args.bead_id} to thread ${args.thread_id}`;
|
|
28005
|
+
} catch (error45) {
|
|
28006
|
+
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
28007
|
+
throw new BeadError(`Failed to link thread: ${message}`, "beads_link_thread");
|
|
28106
28008
|
}
|
|
28107
|
-
return `Linked bead ${args.bead_id} to thread ${args.thread_id}`;
|
|
28108
28009
|
}
|
|
28109
28010
|
});
|
|
28110
28011
|
var beadsTools = {
|
|
@@ -28550,11 +28451,6 @@ class SqliteRateLimiter {
|
|
|
28550
28451
|
if (result.changes < BATCH_SIZE)
|
|
28551
28452
|
break;
|
|
28552
28453
|
}
|
|
28553
|
-
if (totalDeleted > 0) {
|
|
28554
|
-
console.log("[RateLimiter] Cleanup completed:", {
|
|
28555
|
-
deletedRows: totalDeleted
|
|
28556
|
-
});
|
|
28557
|
-
}
|
|
28558
28454
|
}
|
|
28559
28455
|
async recordRequest(agentName, endpoint) {
|
|
28560
28456
|
const now = Date.now();
|
|
@@ -31261,9 +31157,28 @@ swarmmail_release() # Manually release reservations
|
|
|
31261
31157
|
**Note:** \`swarm_complete\` automatically releases reservations. Only use manual release if aborting work.
|
|
31262
31158
|
|
|
31263
31159
|
## [OTHER TOOLS]
|
|
31264
|
-
### Beads
|
|
31160
|
+
### Beads - You Have Autonomy to File Issues
|
|
31161
|
+
You can create new beads against this epic when you discover:
|
|
31162
|
+
- **Bugs**: Found a bug while working? File it.
|
|
31163
|
+
- **Tech debt**: Spotted something that needs cleanup? File it.
|
|
31164
|
+
- **Follow-up work**: Task needs more work than scoped? File a follow-up.
|
|
31165
|
+
- **Dependencies**: Need something from another agent? File and link it.
|
|
31166
|
+
|
|
31167
|
+
\`\`\`
|
|
31168
|
+
beads_create(
|
|
31169
|
+
title="<descriptive title>",
|
|
31170
|
+
type="bug", # or "task", "chore"
|
|
31171
|
+
priority=2,
|
|
31172
|
+
parent_id="{epic_id}", # Links to this epic
|
|
31173
|
+
description="Found while working on {bead_id}: <details>"
|
|
31174
|
+
)
|
|
31175
|
+
\`\`\`
|
|
31176
|
+
|
|
31177
|
+
**Don't silently ignore issues.** File them so they get tracked and addressed.
|
|
31178
|
+
|
|
31179
|
+
Other bead operations:
|
|
31265
31180
|
- beads_update(id, status) - Mark blocked if stuck
|
|
31266
|
-
-
|
|
31181
|
+
- beads_query(status="open") - See what else needs work
|
|
31267
31182
|
|
|
31268
31183
|
### Skills
|
|
31269
31184
|
- skills_list() - Discover available skills
|
|
@@ -32078,7 +31993,7 @@ var swarm_complete = tool({
|
|
|
32078
31993
|
error_count: tool.schema.number().optional().describe("Number of errors encountered during task"),
|
|
32079
31994
|
retry_count: tool.schema.number().optional().describe("Number of retry attempts during task")
|
|
32080
31995
|
},
|
|
32081
|
-
async execute(args) {
|
|
31996
|
+
async execute(args, _ctx) {
|
|
32082
31997
|
const epicId = args.bead_id.includes(".") ? args.bead_id.split(".")[0] : args.bead_id;
|
|
32083
31998
|
try {
|
|
32084
31999
|
const projectKey = args.project_key.replace(/\//g, "-").replace(/\\/g, "-");
|
|
@@ -32224,7 +32139,6 @@ Continuing with completion, but this should be fixed for future subtasks.`;
|
|
|
32224
32139
|
const storeResult = await Bun.$`semantic-memory store ${memoryInfo.information} --metadata ${memoryInfo.metadata}`.quiet().nothrow();
|
|
32225
32140
|
if (storeResult.exitCode === 0) {
|
|
32226
32141
|
memoryStored = true;
|
|
32227
|
-
console.log(`[swarm_complete] Stored learning for ${args.bead_id} in semantic-memory`);
|
|
32228
32142
|
} else {
|
|
32229
32143
|
memoryError = `semantic-memory store failed: ${storeResult.stderr.toString().slice(0, 200)}`;
|
|
32230
32144
|
console.warn(`[swarm_complete] ${memoryError}`);
|
|
@@ -32257,21 +32171,30 @@ Continuing with completion, but this should be fixed for future subtasks.`;
|
|
|
32257
32171
|
`**Memory Capture**: ${memoryStored ? "✓ Stored in semantic-memory" : `✗ ${memoryError || "Failed"}`}`
|
|
32258
32172
|
].filter(Boolean).join(`
|
|
32259
32173
|
`);
|
|
32260
|
-
|
|
32261
|
-
|
|
32262
|
-
|
|
32263
|
-
|
|
32264
|
-
|
|
32265
|
-
|
|
32266
|
-
|
|
32267
|
-
|
|
32268
|
-
|
|
32174
|
+
let messageSent = false;
|
|
32175
|
+
let messageError;
|
|
32176
|
+
try {
|
|
32177
|
+
await sendSwarmMessage2({
|
|
32178
|
+
projectPath: args.project_key,
|
|
32179
|
+
fromAgent: args.agent_name,
|
|
32180
|
+
toAgents: [],
|
|
32181
|
+
subject: `Complete: ${args.bead_id}`,
|
|
32182
|
+
body: completionBody,
|
|
32183
|
+
threadId: epicId2,
|
|
32184
|
+
importance: "normal"
|
|
32185
|
+
});
|
|
32186
|
+
messageSent = true;
|
|
32187
|
+
} catch (error45) {
|
|
32188
|
+
messageError = error45 instanceof Error ? error45.message : String(error45);
|
|
32189
|
+
console.warn(`[swarm_complete] Failed to send completion message: ${messageError}`);
|
|
32190
|
+
}
|
|
32269
32191
|
const response = {
|
|
32270
32192
|
success: true,
|
|
32271
32193
|
bead_id: args.bead_id,
|
|
32272
32194
|
closed: true,
|
|
32273
32195
|
reservations_released: true,
|
|
32274
|
-
message_sent:
|
|
32196
|
+
message_sent: messageSent,
|
|
32197
|
+
message_error: messageError,
|
|
32275
32198
|
agent_registration: {
|
|
32276
32199
|
verified: agentRegistered,
|
|
32277
32200
|
warning: registrationWarning || undefined
|
|
@@ -34353,7 +34276,6 @@ var SwarmPlugin = async (input) => {
|
|
|
34353
34276
|
})
|
|
34354
34277
|
});
|
|
34355
34278
|
if (response.ok) {
|
|
34356
|
-
console.log(`[swarm-plugin] Auto-released ${activeAgentMailState.reservations.length} file reservation(s)`);
|
|
34357
34279
|
activeAgentMailState.reservations = [];
|
|
34358
34280
|
}
|
|
34359
34281
|
} catch (error45) {
|
|
@@ -34390,7 +34312,6 @@ var SwarmPlugin = async (input) => {
|
|
|
34390
34312
|
const guardrailResult = guardrailOutput(toolName, output.output);
|
|
34391
34313
|
if (guardrailResult.truncated) {
|
|
34392
34314
|
output.output = guardrailResult.output;
|
|
34393
|
-
console.log(`[swarm-plugin] Guardrail truncated ${toolName}: ${guardrailResult.originalLength} → ${guardrailResult.truncatedLength} chars`);
|
|
34394
34315
|
}
|
|
34395
34316
|
}
|
|
34396
34317
|
if (toolName === "agentmail_init" && output.output) {
|
|
@@ -34414,12 +34335,9 @@ var SwarmPlugin = async (input) => {
|
|
|
34414
34335
|
}
|
|
34415
34336
|
if (toolName === "swarm_complete" && activeAgentMailState) {
|
|
34416
34337
|
await releaseReservations();
|
|
34417
|
-
console.log("[swarm-plugin] Auto-released reservations after swarm:complete");
|
|
34418
34338
|
}
|
|
34419
34339
|
if (toolName === "beads_close") {
|
|
34420
|
-
$`bd sync`.quiet().nothrow()
|
|
34421
|
-
console.log("[swarm-plugin] Auto-synced beads after close");
|
|
34422
|
-
});
|
|
34340
|
+
$`bd sync`.quiet().nothrow();
|
|
34423
34341
|
}
|
|
34424
34342
|
}
|
|
34425
34343
|
};
|