opencode-swarm-plugin 0.26.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +37 -0
- package/README.md +43 -46
- package/bin/swarm.ts +8 -8
- package/dist/compaction-hook.d.ts +57 -0
- package/dist/compaction-hook.d.ts.map +1 -0
- package/dist/hive.d.ts +741 -0
- package/dist/hive.d.ts.map +1 -0
- package/dist/index.d.ts +139 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1418 -387
- package/dist/learning.d.ts +9 -9
- package/dist/plugin.js +1240 -386
- package/dist/schemas/cell-events.d.ts +1352 -0
- package/dist/schemas/{bead-events.d.ts.map → cell-events.d.ts.map} +1 -1
- package/dist/schemas/{bead.d.ts → cell.d.ts} +173 -29
- package/dist/schemas/cell.d.ts.map +1 -0
- package/dist/schemas/index.d.ts +11 -7
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/structured.d.ts +17 -7
- package/dist/structured.d.ts.map +1 -1
- package/dist/swarm-decompose.d.ts +5 -5
- package/dist/swarm-orchestrate.d.ts +16 -2
- package/dist/swarm-orchestrate.d.ts.map +1 -1
- package/dist/swarm-prompts.d.ts +9 -9
- package/dist/swarm-prompts.d.ts.map +1 -1
- package/dist/swarm-review.d.ts +210 -0
- package/dist/swarm-review.d.ts.map +1 -0
- package/dist/swarm-worktree.d.ts +185 -0
- package/dist/swarm-worktree.d.ts.map +1 -0
- package/dist/swarm.d.ts +7 -0
- package/dist/swarm.d.ts.map +1 -1
- package/dist/tool-availability.d.ts +3 -2
- package/dist/tool-availability.d.ts.map +1 -1
- package/docs/analysis-socratic-planner-pattern.md +1 -1
- package/docs/planning/ADR-007-swarm-enhancements-worktree-review.md +168 -0
- package/docs/testing/context-recovery-test.md +2 -2
- package/evals/README.md +2 -2
- package/evals/scorers/index.ts +7 -7
- package/examples/commands/swarm.md +21 -23
- package/examples/plugin-wrapper-template.ts +310 -44
- package/examples/skills/{beads-workflow → hive-workflow}/SKILL.md +40 -40
- package/examples/skills/swarm-coordination/SKILL.md +1 -1
- package/global-skills/swarm-coordination/SKILL.md +14 -14
- package/global-skills/swarm-coordination/references/coordinator-patterns.md +3 -3
- package/package.json +2 -2
- package/src/compaction-hook.ts +161 -0
- package/src/{beads.integration.test.ts → hive.integration.test.ts} +92 -80
- package/src/hive.ts +1017 -0
- package/src/index.ts +57 -20
- package/src/learning.ts +9 -9
- package/src/output-guardrails.test.ts +4 -4
- package/src/output-guardrails.ts +9 -9
- package/src/planning-guardrails.test.ts +1 -1
- package/src/planning-guardrails.ts +1 -1
- package/src/schemas/{bead-events.test.ts → cell-events.test.ts} +83 -77
- package/src/schemas/cell-events.ts +807 -0
- package/src/schemas/{bead.ts → cell.ts} +95 -41
- package/src/schemas/evaluation.ts +1 -1
- package/src/schemas/index.ts +90 -18
- package/src/schemas/swarm-context.ts +2 -2
- package/src/structured.test.ts +15 -15
- package/src/structured.ts +18 -11
- package/src/swarm-decompose.ts +23 -23
- package/src/swarm-orchestrate.ts +135 -21
- package/src/swarm-prompts.ts +43 -43
- package/src/swarm-review.test.ts +702 -0
- package/src/swarm-review.ts +696 -0
- package/src/swarm-worktree.test.ts +501 -0
- package/src/swarm-worktree.ts +575 -0
- package/src/swarm.integration.test.ts +12 -12
- package/src/tool-availability.ts +36 -3
- package/dist/beads.d.ts +0 -383
- package/dist/beads.d.ts.map +0 -1
- package/dist/schemas/bead-events.d.ts +0 -698
- package/dist/schemas/bead.d.ts.map +0 -1
- package/src/beads.ts +0 -800
- package/src/schemas/bead-events.ts +0 -583
package/dist/index.js
CHANGED
|
@@ -26166,7 +26166,7 @@ __export(exports_skills, {
|
|
|
26166
26166
|
});
|
|
26167
26167
|
import { readdir, readFile, stat, mkdir, writeFile, rm } from "fs/promises";
|
|
26168
26168
|
import {
|
|
26169
|
-
join as
|
|
26169
|
+
join as join5,
|
|
26170
26170
|
basename,
|
|
26171
26171
|
dirname as dirname2,
|
|
26172
26172
|
resolve,
|
|
@@ -26214,19 +26214,19 @@ function validateSkillMetadata(raw, filePath) {
|
|
|
26214
26214
|
}
|
|
26215
26215
|
function getGlobalSkillsDir() {
|
|
26216
26216
|
const home = process.env.HOME || process.env.USERPROFILE || "~";
|
|
26217
|
-
return
|
|
26217
|
+
return join5(home, ".config", "opencode", "skills");
|
|
26218
26218
|
}
|
|
26219
26219
|
function getClaudeGlobalSkillsDir() {
|
|
26220
26220
|
const home = process.env.HOME || process.env.USERPROFILE || "~";
|
|
26221
|
-
return
|
|
26221
|
+
return join5(home, ".claude", "skills");
|
|
26222
26222
|
}
|
|
26223
26223
|
function getPackageSkillsDir() {
|
|
26224
26224
|
try {
|
|
26225
26225
|
const currentFilePath = fileURLToPath(import.meta.url);
|
|
26226
|
-
return
|
|
26226
|
+
return join5(dirname2(currentFilePath), "..", "global-skills");
|
|
26227
26227
|
} catch {
|
|
26228
26228
|
const currentDir = decodeURIComponent(new URL(".", import.meta.url).pathname);
|
|
26229
|
-
return
|
|
26229
|
+
return join5(currentDir, "..", "global-skills");
|
|
26230
26230
|
}
|
|
26231
26231
|
}
|
|
26232
26232
|
async function findSkillFiles(baseDir) {
|
|
@@ -26235,7 +26235,7 @@ async function findSkillFiles(baseDir) {
|
|
|
26235
26235
|
const entries = await readdir(baseDir, { withFileTypes: true });
|
|
26236
26236
|
for (const entry of entries) {
|
|
26237
26237
|
if (entry.isDirectory()) {
|
|
26238
|
-
const skillPath =
|
|
26238
|
+
const skillPath = join5(baseDir, entry.name, "SKILL.md");
|
|
26239
26239
|
try {
|
|
26240
26240
|
const s = await stat(skillPath);
|
|
26241
26241
|
if (s.isFile()) {
|
|
@@ -26249,7 +26249,7 @@ async function findSkillFiles(baseDir) {
|
|
|
26249
26249
|
}
|
|
26250
26250
|
async function findSkillScripts(skillDir) {
|
|
26251
26251
|
const scripts = [];
|
|
26252
|
-
const scriptsDir =
|
|
26252
|
+
const scriptsDir = join5(skillDir, "scripts");
|
|
26253
26253
|
try {
|
|
26254
26254
|
const entries = await readdir(scriptsDir, { withFileTypes: true });
|
|
26255
26255
|
for (const entry of entries) {
|
|
@@ -26297,7 +26297,7 @@ async function discoverSkills(projectDir) {
|
|
|
26297
26297
|
}
|
|
26298
26298
|
}
|
|
26299
26299
|
for (const relPath of PROJECT_SKILL_DIRECTORIES) {
|
|
26300
|
-
await loadSkillsFromDir(
|
|
26300
|
+
await loadSkillsFromDir(join5(dir, relPath));
|
|
26301
26301
|
}
|
|
26302
26302
|
await loadSkillsFromDir(getGlobalSkillsDir());
|
|
26303
26303
|
await loadSkillsFromDir(getClaudeGlobalSkillsDir());
|
|
@@ -26653,7 +26653,7 @@ Scripts run in the skill's directory with the project directory as an argument.`
|
|
|
26653
26653
|
if (!skill.scripts.includes(args.script)) {
|
|
26654
26654
|
return `Script '${args.script}' not found in skill '${args.skill}'. Available: ${skill.scripts.join(", ") || "none"}`;
|
|
26655
26655
|
}
|
|
26656
|
-
const scriptPath =
|
|
26656
|
+
const scriptPath = join5(skill.directory, "scripts", args.script);
|
|
26657
26657
|
const scriptArgs = args.args || [];
|
|
26658
26658
|
try {
|
|
26659
26659
|
const TIMEOUT_MS = 60000;
|
|
@@ -26761,14 +26761,14 @@ Good skills have:
|
|
|
26761
26761
|
const csoWarnings = validateCSOCompliance(args.name, args.description);
|
|
26762
26762
|
let skillDir;
|
|
26763
26763
|
if (args.directory === "global") {
|
|
26764
|
-
skillDir =
|
|
26764
|
+
skillDir = join5(getGlobalSkillsDir(), args.name);
|
|
26765
26765
|
} else if (args.directory === "global-claude") {
|
|
26766
|
-
skillDir =
|
|
26766
|
+
skillDir = join5(getClaudeGlobalSkillsDir(), args.name);
|
|
26767
26767
|
} else {
|
|
26768
26768
|
const baseDir = args.directory || DEFAULT_SKILLS_DIR;
|
|
26769
|
-
skillDir =
|
|
26769
|
+
skillDir = join5(skillsProjectDirectory, baseDir, args.name);
|
|
26770
26770
|
}
|
|
26771
|
-
const skillPath =
|
|
26771
|
+
const skillPath = join5(skillDir, "SKILL.md");
|
|
26772
26772
|
try {
|
|
26773
26773
|
await mkdir(skillDir, { recursive: true });
|
|
26774
26774
|
const content = generateSkillContent(args.name, args.description, args.body, { tags: args.tags, tools: args.tools });
|
|
@@ -26919,8 +26919,8 @@ executed with skills_execute. Use for:
|
|
|
26919
26919
|
if (isAbsolute(args.script_name) || args.script_name.includes("..") || args.script_name.includes("/") || args.script_name.includes("\\") || basename(args.script_name) !== args.script_name) {
|
|
26920
26920
|
return "Invalid script name. Use simple filenames without paths.";
|
|
26921
26921
|
}
|
|
26922
|
-
const scriptsDir =
|
|
26923
|
-
const scriptPath =
|
|
26922
|
+
const scriptsDir = join5(skill.directory, "scripts");
|
|
26923
|
+
const scriptPath = join5(scriptsDir, args.script_name);
|
|
26924
26924
|
try {
|
|
26925
26925
|
await mkdir(scriptsDir, { recursive: true });
|
|
26926
26926
|
await writeFile(scriptPath, args.content, {
|
|
@@ -26969,20 +26969,20 @@ Perfect for learning to create effective skills.`,
|
|
|
26969
26969
|
}
|
|
26970
26970
|
let skillDir;
|
|
26971
26971
|
if (args.directory === "global") {
|
|
26972
|
-
skillDir =
|
|
26972
|
+
skillDir = join5(getGlobalSkillsDir(), args.name);
|
|
26973
26973
|
} else {
|
|
26974
26974
|
const baseDir = args.directory || DEFAULT_SKILLS_DIR;
|
|
26975
|
-
skillDir =
|
|
26975
|
+
skillDir = join5(skillsProjectDirectory, baseDir, args.name);
|
|
26976
26976
|
}
|
|
26977
26977
|
const createdFiles = [];
|
|
26978
26978
|
try {
|
|
26979
26979
|
await mkdir(skillDir, { recursive: true });
|
|
26980
|
-
const skillPath =
|
|
26980
|
+
const skillPath = join5(skillDir, "SKILL.md");
|
|
26981
26981
|
const skillContent = generateSkillTemplate(args.name, args.description);
|
|
26982
26982
|
await writeFile(skillPath, skillContent, "utf-8");
|
|
26983
26983
|
createdFiles.push("SKILL.md");
|
|
26984
26984
|
if (args.include_example_script !== false) {
|
|
26985
|
-
const scriptsDir =
|
|
26985
|
+
const scriptsDir = join5(skillDir, "scripts");
|
|
26986
26986
|
await mkdir(scriptsDir, { recursive: true });
|
|
26987
26987
|
const exampleScript = `#!/usr/bin/env bash
|
|
26988
26988
|
# Example helper script for ${args.name}
|
|
@@ -26996,15 +26996,15 @@ echo "Project directory: $1"
|
|
|
26996
26996
|
|
|
26997
26997
|
# TODO: Add actual script logic
|
|
26998
26998
|
`;
|
|
26999
|
-
const scriptPath =
|
|
26999
|
+
const scriptPath = join5(scriptsDir, "example.sh");
|
|
27000
27000
|
await writeFile(scriptPath, exampleScript, { mode: 493 });
|
|
27001
27001
|
createdFiles.push("scripts/example.sh");
|
|
27002
27002
|
}
|
|
27003
27003
|
if (args.include_reference !== false) {
|
|
27004
|
-
const refsDir =
|
|
27004
|
+
const refsDir = join5(skillDir, "references");
|
|
27005
27005
|
await mkdir(refsDir, { recursive: true });
|
|
27006
27006
|
const refContent = generateReferenceTemplate(args.name);
|
|
27007
|
-
const refPath =
|
|
27007
|
+
const refPath = join5(refsDir, "guide.md");
|
|
27008
27008
|
await writeFile(refPath, refContent, "utf-8");
|
|
27009
27009
|
createdFiles.push("references/guide.md");
|
|
27010
27010
|
}
|
|
@@ -27051,40 +27051,43 @@ echo "Project directory: $1"
|
|
|
27051
27051
|
};
|
|
27052
27052
|
});
|
|
27053
27053
|
|
|
27054
|
-
// src/
|
|
27054
|
+
// src/hive.ts
|
|
27055
27055
|
init_dist();
|
|
27056
27056
|
import {
|
|
27057
|
-
|
|
27057
|
+
createHiveAdapter,
|
|
27058
27058
|
FlushManager,
|
|
27059
|
+
importFromJSONL,
|
|
27059
27060
|
getSwarmMail
|
|
27060
27061
|
} from "swarm-mail";
|
|
27062
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
27063
|
+
import { join } from "node:path";
|
|
27061
27064
|
|
|
27062
|
-
// src/schemas/
|
|
27065
|
+
// src/schemas/cell.ts
|
|
27063
27066
|
init_zod();
|
|
27064
|
-
var
|
|
27067
|
+
var CellStatusSchema = exports_external.enum([
|
|
27065
27068
|
"open",
|
|
27066
27069
|
"in_progress",
|
|
27067
27070
|
"blocked",
|
|
27068
27071
|
"closed"
|
|
27069
27072
|
]);
|
|
27070
|
-
var
|
|
27073
|
+
var CellTypeSchema = exports_external.enum([
|
|
27071
27074
|
"bug",
|
|
27072
27075
|
"feature",
|
|
27073
27076
|
"task",
|
|
27074
27077
|
"epic",
|
|
27075
27078
|
"chore"
|
|
27076
27079
|
]);
|
|
27077
|
-
var
|
|
27080
|
+
var CellDependencySchema = exports_external.object({
|
|
27078
27081
|
id: exports_external.string(),
|
|
27079
27082
|
type: exports_external.enum(["blocks", "blocked-by", "related", "discovered-from"])
|
|
27080
27083
|
});
|
|
27081
|
-
var
|
|
27082
|
-
id: exports_external.string().regex(/^[a-z0-9]+(-[a-z0-9]+)+(\.[\w-]+)?$/, "Invalid
|
|
27084
|
+
var CellSchema = exports_external.object({
|
|
27085
|
+
id: exports_external.string().regex(/^[a-z0-9]+(-[a-z0-9]+)+(\.[\w-]+)?$/, "Invalid cell ID format (expected: project-slug-hash or project-slug-hash.N)"),
|
|
27083
27086
|
title: exports_external.string().min(1, "Title required"),
|
|
27084
27087
|
description: exports_external.string().optional().default(""),
|
|
27085
|
-
status:
|
|
27088
|
+
status: CellStatusSchema.default("open"),
|
|
27086
27089
|
priority: exports_external.number().int().min(0).max(3).default(2),
|
|
27087
|
-
issue_type:
|
|
27090
|
+
issue_type: CellTypeSchema.default("task"),
|
|
27088
27091
|
created_at: exports_external.string().datetime({
|
|
27089
27092
|
offset: true,
|
|
27090
27093
|
message: "Must be ISO-8601 datetime with timezone (e.g., 2024-01-15T10:30:00Z)"
|
|
@@ -27095,30 +27098,30 @@ var BeadSchema = exports_external.object({
|
|
|
27095
27098
|
}).optional(),
|
|
27096
27099
|
closed_at: exports_external.string().datetime({ offset: true }).optional(),
|
|
27097
27100
|
parent_id: exports_external.string().optional(),
|
|
27098
|
-
dependencies: exports_external.array(
|
|
27101
|
+
dependencies: exports_external.array(CellDependencySchema).default([]),
|
|
27099
27102
|
metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
27100
27103
|
});
|
|
27101
|
-
var
|
|
27104
|
+
var CellCreateArgsSchema = exports_external.object({
|
|
27102
27105
|
title: exports_external.string().min(1, "Title required"),
|
|
27103
|
-
type:
|
|
27106
|
+
type: CellTypeSchema.default("task"),
|
|
27104
27107
|
priority: exports_external.number().int().min(0).max(3).default(2),
|
|
27105
27108
|
description: exports_external.string().optional(),
|
|
27106
27109
|
parent_id: exports_external.string().optional(),
|
|
27107
27110
|
id: exports_external.string().optional()
|
|
27108
27111
|
});
|
|
27109
|
-
var
|
|
27112
|
+
var CellUpdateArgsSchema = exports_external.object({
|
|
27110
27113
|
id: exports_external.string(),
|
|
27111
|
-
status:
|
|
27114
|
+
status: CellStatusSchema.optional(),
|
|
27112
27115
|
description: exports_external.string().optional(),
|
|
27113
27116
|
priority: exports_external.number().int().min(0).max(3).optional()
|
|
27114
27117
|
});
|
|
27115
|
-
var
|
|
27118
|
+
var CellCloseArgsSchema = exports_external.object({
|
|
27116
27119
|
id: exports_external.string(),
|
|
27117
27120
|
reason: exports_external.string().min(1, "Reason required")
|
|
27118
27121
|
});
|
|
27119
|
-
var
|
|
27120
|
-
status:
|
|
27121
|
-
type:
|
|
27122
|
+
var CellQueryArgsSchema = exports_external.object({
|
|
27123
|
+
status: CellStatusSchema.optional(),
|
|
27124
|
+
type: CellTypeSchema.optional(),
|
|
27122
27125
|
ready: exports_external.boolean().optional(),
|
|
27123
27126
|
limit: exports_external.number().int().positive().default(20)
|
|
27124
27127
|
});
|
|
@@ -27129,7 +27132,7 @@ var SubtaskSpecSchema = exports_external.object({
|
|
|
27129
27132
|
dependencies: exports_external.array(exports_external.number().int().min(0)).default([]),
|
|
27130
27133
|
estimated_complexity: exports_external.number().int().min(1).max(5).default(3)
|
|
27131
27134
|
});
|
|
27132
|
-
var
|
|
27135
|
+
var CellTreeSchema = exports_external.object({
|
|
27133
27136
|
epic: exports_external.object({
|
|
27134
27137
|
title: exports_external.string().min(1),
|
|
27135
27138
|
description: exports_external.string().optional().default("")
|
|
@@ -27149,10 +27152,19 @@ var EpicCreateArgsSchema = exports_external.object({
|
|
|
27149
27152
|
});
|
|
27150
27153
|
var EpicCreateResultSchema = exports_external.object({
|
|
27151
27154
|
success: exports_external.boolean(),
|
|
27152
|
-
epic:
|
|
27153
|
-
subtasks: exports_external.array(
|
|
27155
|
+
epic: CellSchema,
|
|
27156
|
+
subtasks: exports_external.array(CellSchema),
|
|
27154
27157
|
rollback_hint: exports_external.string().optional()
|
|
27155
27158
|
});
|
|
27159
|
+
var BeadStatusSchema = CellStatusSchema;
|
|
27160
|
+
var BeadTypeSchema = CellTypeSchema;
|
|
27161
|
+
var BeadDependencySchema = CellDependencySchema;
|
|
27162
|
+
var BeadSchema = CellSchema;
|
|
27163
|
+
var BeadCreateArgsSchema = CellCreateArgsSchema;
|
|
27164
|
+
var BeadUpdateArgsSchema = CellUpdateArgsSchema;
|
|
27165
|
+
var BeadCloseArgsSchema = CellCloseArgsSchema;
|
|
27166
|
+
var BeadQueryArgsSchema = CellQueryArgsSchema;
|
|
27167
|
+
var BeadTreeSchema = CellTreeSchema;
|
|
27156
27168
|
// src/schemas/evaluation.ts
|
|
27157
27169
|
init_zod();
|
|
27158
27170
|
var CriterionEvaluationSchema = exports_external.object({
|
|
@@ -27434,29 +27446,29 @@ var QuerySwarmContextsArgsSchema = exports_external.object({
|
|
|
27434
27446
|
strategy: SwarmStrategySchema.optional(),
|
|
27435
27447
|
has_errors: exports_external.boolean().optional()
|
|
27436
27448
|
});
|
|
27437
|
-
// src/schemas/
|
|
27449
|
+
// src/schemas/cell-events.ts
|
|
27438
27450
|
init_zod();
|
|
27439
|
-
var
|
|
27451
|
+
var BaseCellEventSchema = exports_external.object({
|
|
27440
27452
|
id: exports_external.number().optional(),
|
|
27441
27453
|
type: exports_external.string(),
|
|
27442
27454
|
project_key: exports_external.string(),
|
|
27443
27455
|
timestamp: exports_external.number(),
|
|
27444
27456
|
sequence: exports_external.number().optional()
|
|
27445
27457
|
});
|
|
27446
|
-
var
|
|
27447
|
-
type: exports_external.literal("
|
|
27448
|
-
|
|
27458
|
+
var CellCreatedEventSchema = BaseCellEventSchema.extend({
|
|
27459
|
+
type: exports_external.literal("cell_created"),
|
|
27460
|
+
cell_id: exports_external.string(),
|
|
27449
27461
|
title: exports_external.string(),
|
|
27450
27462
|
description: exports_external.string().optional(),
|
|
27451
|
-
issue_type:
|
|
27463
|
+
issue_type: CellTypeSchema,
|
|
27452
27464
|
priority: exports_external.number().int().min(0).max(3),
|
|
27453
27465
|
parent_id: exports_external.string().optional(),
|
|
27454
27466
|
created_by: exports_external.string().optional(),
|
|
27455
27467
|
metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
27456
27468
|
});
|
|
27457
|
-
var
|
|
27458
|
-
type: exports_external.literal("
|
|
27459
|
-
|
|
27469
|
+
var CellUpdatedEventSchema = BaseCellEventSchema.extend({
|
|
27470
|
+
type: exports_external.literal("cell_updated"),
|
|
27471
|
+
cell_id: exports_external.string(),
|
|
27460
27472
|
updated_by: exports_external.string().optional(),
|
|
27461
27473
|
changes: exports_external.object({
|
|
27462
27474
|
title: exports_external.object({
|
|
@@ -27473,167 +27485,167 @@ var BeadUpdatedEventSchema = BaseBeadEventSchema.extend({
|
|
|
27473
27485
|
}).optional()
|
|
27474
27486
|
})
|
|
27475
27487
|
});
|
|
27476
|
-
var
|
|
27477
|
-
type: exports_external.literal("
|
|
27478
|
-
|
|
27479
|
-
from_status:
|
|
27480
|
-
to_status:
|
|
27488
|
+
var CellStatusChangedEventSchema = BaseCellEventSchema.extend({
|
|
27489
|
+
type: exports_external.literal("cell_status_changed"),
|
|
27490
|
+
cell_id: exports_external.string(),
|
|
27491
|
+
from_status: CellStatusSchema,
|
|
27492
|
+
to_status: CellStatusSchema,
|
|
27481
27493
|
changed_by: exports_external.string().optional(),
|
|
27482
27494
|
reason: exports_external.string().optional()
|
|
27483
27495
|
});
|
|
27484
|
-
var
|
|
27485
|
-
type: exports_external.literal("
|
|
27486
|
-
|
|
27496
|
+
var CellClosedEventSchema = BaseCellEventSchema.extend({
|
|
27497
|
+
type: exports_external.literal("cell_closed"),
|
|
27498
|
+
cell_id: exports_external.string(),
|
|
27487
27499
|
reason: exports_external.string(),
|
|
27488
27500
|
closed_by: exports_external.string().optional(),
|
|
27489
27501
|
files_touched: exports_external.array(exports_external.string()).optional(),
|
|
27490
27502
|
duration_ms: exports_external.number().optional()
|
|
27491
27503
|
});
|
|
27492
|
-
var
|
|
27493
|
-
type: exports_external.literal("
|
|
27494
|
-
|
|
27504
|
+
var CellReopenedEventSchema = BaseCellEventSchema.extend({
|
|
27505
|
+
type: exports_external.literal("cell_reopened"),
|
|
27506
|
+
cell_id: exports_external.string(),
|
|
27495
27507
|
reason: exports_external.string().optional(),
|
|
27496
27508
|
reopened_by: exports_external.string().optional()
|
|
27497
27509
|
});
|
|
27498
|
-
var
|
|
27499
|
-
type: exports_external.literal("
|
|
27500
|
-
|
|
27510
|
+
var CellDeletedEventSchema = BaseCellEventSchema.extend({
|
|
27511
|
+
type: exports_external.literal("cell_deleted"),
|
|
27512
|
+
cell_id: exports_external.string(),
|
|
27501
27513
|
reason: exports_external.string().optional(),
|
|
27502
27514
|
deleted_by: exports_external.string().optional()
|
|
27503
27515
|
});
|
|
27504
|
-
var
|
|
27505
|
-
type: exports_external.literal("
|
|
27506
|
-
|
|
27507
|
-
dependency:
|
|
27516
|
+
var CellDependencyAddedEventSchema = BaseCellEventSchema.extend({
|
|
27517
|
+
type: exports_external.literal("cell_dependency_added"),
|
|
27518
|
+
cell_id: exports_external.string(),
|
|
27519
|
+
dependency: CellDependencySchema,
|
|
27508
27520
|
added_by: exports_external.string().optional(),
|
|
27509
27521
|
reason: exports_external.string().optional()
|
|
27510
27522
|
});
|
|
27511
|
-
var
|
|
27512
|
-
type: exports_external.literal("
|
|
27513
|
-
|
|
27514
|
-
dependency:
|
|
27523
|
+
var CellDependencyRemovedEventSchema = BaseCellEventSchema.extend({
|
|
27524
|
+
type: exports_external.literal("cell_dependency_removed"),
|
|
27525
|
+
cell_id: exports_external.string(),
|
|
27526
|
+
dependency: CellDependencySchema,
|
|
27515
27527
|
removed_by: exports_external.string().optional(),
|
|
27516
27528
|
reason: exports_external.string().optional()
|
|
27517
27529
|
});
|
|
27518
|
-
var
|
|
27519
|
-
type: exports_external.literal("
|
|
27520
|
-
|
|
27530
|
+
var CellLabelAddedEventSchema = BaseCellEventSchema.extend({
|
|
27531
|
+
type: exports_external.literal("cell_label_added"),
|
|
27532
|
+
cell_id: exports_external.string(),
|
|
27521
27533
|
label: exports_external.string(),
|
|
27522
27534
|
added_by: exports_external.string().optional()
|
|
27523
27535
|
});
|
|
27524
|
-
var
|
|
27525
|
-
type: exports_external.literal("
|
|
27526
|
-
|
|
27536
|
+
var CellLabelRemovedEventSchema = BaseCellEventSchema.extend({
|
|
27537
|
+
type: exports_external.literal("cell_label_removed"),
|
|
27538
|
+
cell_id: exports_external.string(),
|
|
27527
27539
|
label: exports_external.string(),
|
|
27528
27540
|
removed_by: exports_external.string().optional()
|
|
27529
27541
|
});
|
|
27530
|
-
var
|
|
27531
|
-
type: exports_external.literal("
|
|
27532
|
-
|
|
27542
|
+
var CellCommentAddedEventSchema = BaseCellEventSchema.extend({
|
|
27543
|
+
type: exports_external.literal("cell_comment_added"),
|
|
27544
|
+
cell_id: exports_external.string(),
|
|
27533
27545
|
comment_id: exports_external.number().optional(),
|
|
27534
27546
|
author: exports_external.string(),
|
|
27535
27547
|
body: exports_external.string(),
|
|
27536
27548
|
parent_comment_id: exports_external.number().optional(),
|
|
27537
27549
|
metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
27538
27550
|
});
|
|
27539
|
-
var
|
|
27540
|
-
type: exports_external.literal("
|
|
27541
|
-
|
|
27551
|
+
var CellCommentUpdatedEventSchema = BaseCellEventSchema.extend({
|
|
27552
|
+
type: exports_external.literal("cell_comment_updated"),
|
|
27553
|
+
cell_id: exports_external.string(),
|
|
27542
27554
|
comment_id: exports_external.number(),
|
|
27543
27555
|
old_body: exports_external.string(),
|
|
27544
27556
|
new_body: exports_external.string(),
|
|
27545
27557
|
updated_by: exports_external.string()
|
|
27546
27558
|
});
|
|
27547
|
-
var
|
|
27548
|
-
type: exports_external.literal("
|
|
27549
|
-
|
|
27559
|
+
var CellCommentDeletedEventSchema = BaseCellEventSchema.extend({
|
|
27560
|
+
type: exports_external.literal("cell_comment_deleted"),
|
|
27561
|
+
cell_id: exports_external.string(),
|
|
27550
27562
|
comment_id: exports_external.number(),
|
|
27551
27563
|
deleted_by: exports_external.string(),
|
|
27552
27564
|
reason: exports_external.string().optional()
|
|
27553
27565
|
});
|
|
27554
|
-
var
|
|
27555
|
-
type: exports_external.literal("
|
|
27556
|
-
|
|
27566
|
+
var CellEpicChildAddedEventSchema = BaseCellEventSchema.extend({
|
|
27567
|
+
type: exports_external.literal("cell_epic_child_added"),
|
|
27568
|
+
cell_id: exports_external.string(),
|
|
27557
27569
|
child_id: exports_external.string(),
|
|
27558
27570
|
child_index: exports_external.number().optional(),
|
|
27559
27571
|
added_by: exports_external.string().optional()
|
|
27560
27572
|
});
|
|
27561
|
-
var
|
|
27562
|
-
type: exports_external.literal("
|
|
27563
|
-
|
|
27573
|
+
var CellEpicChildRemovedEventSchema = BaseCellEventSchema.extend({
|
|
27574
|
+
type: exports_external.literal("cell_epic_child_removed"),
|
|
27575
|
+
cell_id: exports_external.string(),
|
|
27564
27576
|
child_id: exports_external.string(),
|
|
27565
27577
|
removed_by: exports_external.string().optional(),
|
|
27566
27578
|
reason: exports_external.string().optional()
|
|
27567
27579
|
});
|
|
27568
|
-
var
|
|
27569
|
-
type: exports_external.literal("
|
|
27570
|
-
|
|
27580
|
+
var CellEpicClosureEligibleEventSchema = BaseCellEventSchema.extend({
|
|
27581
|
+
type: exports_external.literal("cell_epic_closure_eligible"),
|
|
27582
|
+
cell_id: exports_external.string(),
|
|
27571
27583
|
child_ids: exports_external.array(exports_external.string()),
|
|
27572
27584
|
total_duration_ms: exports_external.number().optional(),
|
|
27573
27585
|
all_files_touched: exports_external.array(exports_external.string()).optional()
|
|
27574
27586
|
});
|
|
27575
|
-
var
|
|
27576
|
-
type: exports_external.literal("
|
|
27577
|
-
|
|
27587
|
+
var CellAssignedEventSchema = BaseCellEventSchema.extend({
|
|
27588
|
+
type: exports_external.literal("cell_assigned"),
|
|
27589
|
+
cell_id: exports_external.string(),
|
|
27578
27590
|
agent_name: exports_external.string(),
|
|
27579
27591
|
task_description: exports_external.string().optional()
|
|
27580
27592
|
});
|
|
27581
|
-
var
|
|
27582
|
-
type: exports_external.literal("
|
|
27583
|
-
|
|
27593
|
+
var CellWorkStartedEventSchema = BaseCellEventSchema.extend({
|
|
27594
|
+
type: exports_external.literal("cell_work_started"),
|
|
27595
|
+
cell_id: exports_external.string(),
|
|
27584
27596
|
agent_name: exports_external.string(),
|
|
27585
27597
|
reserved_files: exports_external.array(exports_external.string()).optional()
|
|
27586
27598
|
});
|
|
27587
|
-
var
|
|
27588
|
-
type: exports_external.literal("
|
|
27589
|
-
|
|
27599
|
+
var CellCompactedEventSchema = BaseCellEventSchema.extend({
|
|
27600
|
+
type: exports_external.literal("cell_compacted"),
|
|
27601
|
+
cell_id: exports_external.string(),
|
|
27590
27602
|
events_archived: exports_external.number(),
|
|
27591
27603
|
new_start_sequence: exports_external.number()
|
|
27592
27604
|
});
|
|
27593
|
-
var
|
|
27594
|
-
|
|
27595
|
-
|
|
27596
|
-
|
|
27597
|
-
|
|
27598
|
-
|
|
27599
|
-
|
|
27600
|
-
|
|
27601
|
-
|
|
27602
|
-
|
|
27603
|
-
|
|
27604
|
-
|
|
27605
|
-
|
|
27606
|
-
|
|
27607
|
-
|
|
27608
|
-
|
|
27609
|
-
|
|
27610
|
-
|
|
27611
|
-
|
|
27612
|
-
|
|
27605
|
+
var CellEventSchema = exports_external.discriminatedUnion("type", [
|
|
27606
|
+
CellCreatedEventSchema,
|
|
27607
|
+
CellUpdatedEventSchema,
|
|
27608
|
+
CellStatusChangedEventSchema,
|
|
27609
|
+
CellClosedEventSchema,
|
|
27610
|
+
CellReopenedEventSchema,
|
|
27611
|
+
CellDeletedEventSchema,
|
|
27612
|
+
CellDependencyAddedEventSchema,
|
|
27613
|
+
CellDependencyRemovedEventSchema,
|
|
27614
|
+
CellLabelAddedEventSchema,
|
|
27615
|
+
CellLabelRemovedEventSchema,
|
|
27616
|
+
CellCommentAddedEventSchema,
|
|
27617
|
+
CellCommentUpdatedEventSchema,
|
|
27618
|
+
CellCommentDeletedEventSchema,
|
|
27619
|
+
CellEpicChildAddedEventSchema,
|
|
27620
|
+
CellEpicChildRemovedEventSchema,
|
|
27621
|
+
CellEpicClosureEligibleEventSchema,
|
|
27622
|
+
CellAssignedEventSchema,
|
|
27623
|
+
CellWorkStartedEventSchema,
|
|
27624
|
+
CellCompactedEventSchema
|
|
27613
27625
|
]);
|
|
27614
|
-
function
|
|
27626
|
+
function createCellEvent(type, data) {
|
|
27615
27627
|
const event = {
|
|
27616
27628
|
type,
|
|
27617
27629
|
timestamp: Date.now(),
|
|
27618
27630
|
...data
|
|
27619
27631
|
};
|
|
27620
|
-
const result =
|
|
27632
|
+
const result = CellEventSchema.safeParse(event);
|
|
27621
27633
|
if (!result.success) {
|
|
27622
|
-
throw new Error(`Invalid
|
|
27634
|
+
throw new Error(`Invalid cell event: ${result.error.message}`);
|
|
27623
27635
|
}
|
|
27624
27636
|
return result.data;
|
|
27625
27637
|
}
|
|
27626
|
-
function
|
|
27638
|
+
function isCellEventType(event, type) {
|
|
27627
27639
|
return event.type === type;
|
|
27628
27640
|
}
|
|
27629
|
-
function
|
|
27630
|
-
return event.
|
|
27641
|
+
function getCellIdFromEvent(event) {
|
|
27642
|
+
return event.cell_id;
|
|
27631
27643
|
}
|
|
27632
27644
|
function isStateTransitionEvent(event) {
|
|
27633
|
-
return event.type === "
|
|
27645
|
+
return event.type === "cell_status_changed" || event.type === "cell_closed" || event.type === "cell_reopened";
|
|
27634
27646
|
}
|
|
27635
27647
|
function isEpicEvent(event) {
|
|
27636
|
-
return event.type === "
|
|
27648
|
+
return event.type === "cell_epic_child_added" || event.type === "cell_epic_child_removed" || event.type === "cell_epic_closure_eligible";
|
|
27637
27649
|
}
|
|
27638
27650
|
function isAgentEvent(event) {
|
|
27639
27651
|
if ("agent_name" in event)
|
|
@@ -27656,17 +27668,43 @@ function isAgentEvent(event) {
|
|
|
27656
27668
|
return false;
|
|
27657
27669
|
});
|
|
27658
27670
|
}
|
|
27659
|
-
|
|
27671
|
+
var BaseBeadEventSchema = BaseCellEventSchema;
|
|
27672
|
+
var BeadCreatedEventSchema = CellCreatedEventSchema;
|
|
27673
|
+
var BeadUpdatedEventSchema = CellUpdatedEventSchema;
|
|
27674
|
+
var BeadStatusChangedEventSchema = CellStatusChangedEventSchema;
|
|
27675
|
+
var BeadClosedEventSchema = CellClosedEventSchema;
|
|
27676
|
+
var BeadReopenedEventSchema = CellReopenedEventSchema;
|
|
27677
|
+
var BeadDeletedEventSchema = CellDeletedEventSchema;
|
|
27678
|
+
var BeadDependencyAddedEventSchema = CellDependencyAddedEventSchema;
|
|
27679
|
+
var BeadDependencyRemovedEventSchema = CellDependencyRemovedEventSchema;
|
|
27680
|
+
var BeadLabelAddedEventSchema = CellLabelAddedEventSchema;
|
|
27681
|
+
var BeadLabelRemovedEventSchema = CellLabelRemovedEventSchema;
|
|
27682
|
+
var BeadCommentAddedEventSchema = CellCommentAddedEventSchema;
|
|
27683
|
+
var BeadCommentUpdatedEventSchema = CellCommentUpdatedEventSchema;
|
|
27684
|
+
var BeadCommentDeletedEventSchema = CellCommentDeletedEventSchema;
|
|
27685
|
+
var BeadEpicChildAddedEventSchema = CellEpicChildAddedEventSchema;
|
|
27686
|
+
var BeadEpicChildRemovedEventSchema = CellEpicChildRemovedEventSchema;
|
|
27687
|
+
var BeadEpicClosureEligibleEventSchema = CellEpicClosureEligibleEventSchema;
|
|
27688
|
+
var BeadAssignedEventSchema = CellAssignedEventSchema;
|
|
27689
|
+
var BeadWorkStartedEventSchema = CellWorkStartedEventSchema;
|
|
27690
|
+
var BeadCompactedEventSchema = CellCompactedEventSchema;
|
|
27691
|
+
var BeadEventSchema = CellEventSchema;
|
|
27692
|
+
var createBeadEvent = createCellEvent;
|
|
27693
|
+
var isBeadEventType = isCellEventType;
|
|
27694
|
+
var getBeadIdFromEvent = getCellIdFromEvent;
|
|
27695
|
+
// src/hive.ts
|
|
27660
27696
|
import { createEvent, appendEvent } from "swarm-mail";
|
|
27661
|
-
var
|
|
27662
|
-
function
|
|
27663
|
-
|
|
27697
|
+
var hiveWorkingDirectory = null;
|
|
27698
|
+
function setHiveWorkingDirectory(directory) {
|
|
27699
|
+
hiveWorkingDirectory = directory;
|
|
27664
27700
|
}
|
|
27665
|
-
function
|
|
27666
|
-
return
|
|
27701
|
+
function getHiveWorkingDirectory() {
|
|
27702
|
+
return hiveWorkingDirectory || process.cwd();
|
|
27667
27703
|
}
|
|
27704
|
+
var setBeadsWorkingDirectory = setHiveWorkingDirectory;
|
|
27705
|
+
var getBeadsWorkingDirectory = getHiveWorkingDirectory;
|
|
27668
27706
|
async function runGitCommand(args) {
|
|
27669
|
-
const cwd =
|
|
27707
|
+
const cwd = getHiveWorkingDirectory();
|
|
27670
27708
|
const proc = Bun.spawn(["git", ...args], {
|
|
27671
27709
|
cwd,
|
|
27672
27710
|
stdout: "pipe",
|
|
@@ -27680,7 +27718,7 @@ async function runGitCommand(args) {
|
|
|
27680
27718
|
return { exitCode, stdout, stderr };
|
|
27681
27719
|
}
|
|
27682
27720
|
|
|
27683
|
-
class
|
|
27721
|
+
class HiveError extends Error {
|
|
27684
27722
|
command;
|
|
27685
27723
|
exitCode;
|
|
27686
27724
|
stderr;
|
|
@@ -27689,77 +27727,105 @@ class BeadError extends Error {
|
|
|
27689
27727
|
this.command = command;
|
|
27690
27728
|
this.exitCode = exitCode;
|
|
27691
27729
|
this.stderr = stderr;
|
|
27692
|
-
this.name = "
|
|
27730
|
+
this.name = "HiveError";
|
|
27693
27731
|
}
|
|
27694
27732
|
}
|
|
27733
|
+
var BeadError = HiveError;
|
|
27695
27734
|
|
|
27696
|
-
class
|
|
27735
|
+
class HiveValidationError extends Error {
|
|
27697
27736
|
zodError;
|
|
27698
27737
|
constructor(message, zodError) {
|
|
27699
27738
|
super(message);
|
|
27700
27739
|
this.zodError = zodError;
|
|
27701
|
-
this.name = "
|
|
27740
|
+
this.name = "HiveValidationError";
|
|
27702
27741
|
}
|
|
27703
27742
|
}
|
|
27743
|
+
var BeadValidationError = HiveValidationError;
|
|
27704
27744
|
var adapterCache = new Map;
|
|
27705
|
-
async function
|
|
27745
|
+
async function getHiveAdapter(projectKey) {
|
|
27706
27746
|
if (adapterCache.has(projectKey)) {
|
|
27707
27747
|
return adapterCache.get(projectKey);
|
|
27708
27748
|
}
|
|
27709
27749
|
const swarmMail = await getSwarmMail(projectKey);
|
|
27710
27750
|
const db = await swarmMail.getDatabase();
|
|
27711
|
-
const adapter =
|
|
27751
|
+
const adapter = createHiveAdapter(db, projectKey);
|
|
27712
27752
|
await adapter.runMigrations();
|
|
27753
|
+
await autoMigrateFromJSONL(adapter, projectKey);
|
|
27713
27754
|
adapterCache.set(projectKey, adapter);
|
|
27714
27755
|
return adapter;
|
|
27715
27756
|
}
|
|
27716
|
-
|
|
27757
|
+
var getBeadsAdapter = getHiveAdapter;
|
|
27758
|
+
async function autoMigrateFromJSONL(adapter, projectKey) {
|
|
27759
|
+
const jsonlPath = join(projectKey, ".hive", "issues.jsonl");
|
|
27760
|
+
if (!existsSync(jsonlPath)) {
|
|
27761
|
+
return;
|
|
27762
|
+
}
|
|
27763
|
+
const existingCells = await adapter.queryCells(projectKey, { limit: 1 });
|
|
27764
|
+
if (existingCells.length > 0) {
|
|
27765
|
+
return;
|
|
27766
|
+
}
|
|
27767
|
+
try {
|
|
27768
|
+
const jsonlContent = readFileSync(jsonlPath, "utf-8");
|
|
27769
|
+
const result = await importFromJSONL(adapter, projectKey, jsonlContent, {
|
|
27770
|
+
skipExisting: true
|
|
27771
|
+
});
|
|
27772
|
+
if (result.created > 0 || result.updated > 0) {
|
|
27773
|
+
console.log(`[hive] Auto-migrated ${result.created} cells from ${jsonlPath} (${result.skipped} skipped, ${result.errors.length} errors)`);
|
|
27774
|
+
}
|
|
27775
|
+
if (result.errors.length > 0) {
|
|
27776
|
+
console.warn(`[hive] Migration errors:`, result.errors.slice(0, 5).map((e) => `${e.cellId}: ${e.error}`));
|
|
27777
|
+
}
|
|
27778
|
+
} catch (error45) {
|
|
27779
|
+
console.warn(`[hive] Failed to auto-migrate from ${jsonlPath}:`, error45 instanceof Error ? error45.message : String(error45));
|
|
27780
|
+
}
|
|
27781
|
+
}
|
|
27782
|
+
function formatCellForOutput(adapterCell) {
|
|
27717
27783
|
return {
|
|
27718
|
-
id:
|
|
27719
|
-
title:
|
|
27720
|
-
description:
|
|
27721
|
-
status:
|
|
27722
|
-
priority:
|
|
27723
|
-
issue_type:
|
|
27724
|
-
created_at: new Date(
|
|
27725
|
-
updated_at: new Date(
|
|
27726
|
-
closed_at:
|
|
27727
|
-
parent_id:
|
|
27784
|
+
id: adapterCell.id,
|
|
27785
|
+
title: adapterCell.title,
|
|
27786
|
+
description: adapterCell.description || "",
|
|
27787
|
+
status: adapterCell.status,
|
|
27788
|
+
priority: adapterCell.priority,
|
|
27789
|
+
issue_type: adapterCell.type,
|
|
27790
|
+
created_at: new Date(adapterCell.created_at).toISOString(),
|
|
27791
|
+
updated_at: new Date(adapterCell.updated_at).toISOString(),
|
|
27792
|
+
closed_at: adapterCell.closed_at ? new Date(adapterCell.closed_at).toISOString() : undefined,
|
|
27793
|
+
parent_id: adapterCell.parent_id || undefined,
|
|
27728
27794
|
dependencies: [],
|
|
27729
27795
|
metadata: {}
|
|
27730
27796
|
};
|
|
27731
27797
|
}
|
|
27732
|
-
var
|
|
27733
|
-
description: "Create a new
|
|
27798
|
+
var hive_create = tool({
|
|
27799
|
+
description: "Create a new cell in the hive with type-safe validation",
|
|
27734
27800
|
args: {
|
|
27735
|
-
title: tool.schema.string().describe("
|
|
27801
|
+
title: tool.schema.string().describe("Cell title"),
|
|
27736
27802
|
type: tool.schema.enum(["bug", "feature", "task", "epic", "chore"]).optional().describe("Issue type (default: task)"),
|
|
27737
27803
|
priority: tool.schema.number().min(0).max(3).optional().describe("Priority 0-3 (default: 2)"),
|
|
27738
|
-
description: tool.schema.string().optional().describe("
|
|
27739
|
-
parent_id: tool.schema.string().optional().describe("Parent
|
|
27804
|
+
description: tool.schema.string().optional().describe("Cell description"),
|
|
27805
|
+
parent_id: tool.schema.string().optional().describe("Parent cell ID for epic children")
|
|
27740
27806
|
},
|
|
27741
27807
|
async execute(args, ctx) {
|
|
27742
|
-
const validated =
|
|
27743
|
-
const projectKey =
|
|
27744
|
-
const adapter = await
|
|
27808
|
+
const validated = CellCreateArgsSchema.parse(args);
|
|
27809
|
+
const projectKey = getHiveWorkingDirectory();
|
|
27810
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
27745
27811
|
try {
|
|
27746
|
-
const
|
|
27812
|
+
const cell = await adapter.createCell(projectKey, {
|
|
27747
27813
|
title: validated.title,
|
|
27748
27814
|
type: validated.type || "task",
|
|
27749
27815
|
priority: validated.priority ?? 2,
|
|
27750
27816
|
description: validated.description,
|
|
27751
27817
|
parent_id: validated.parent_id
|
|
27752
27818
|
});
|
|
27753
|
-
await adapter.markDirty(projectKey,
|
|
27754
|
-
const formatted =
|
|
27819
|
+
await adapter.markDirty(projectKey, cell.id);
|
|
27820
|
+
const formatted = formatCellForOutput(cell);
|
|
27755
27821
|
return JSON.stringify(formatted, null, 2);
|
|
27756
27822
|
} catch (error45) {
|
|
27757
27823
|
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
27758
|
-
throw new
|
|
27824
|
+
throw new HiveError(`Failed to create cell: ${message}`, "hive_create");
|
|
27759
27825
|
}
|
|
27760
27826
|
}
|
|
27761
27827
|
});
|
|
27762
|
-
var
|
|
27828
|
+
var hive_create_epic = tool({
|
|
27763
27829
|
description: "Create epic with subtasks in one atomic operation",
|
|
27764
27830
|
args: {
|
|
27765
27831
|
epic_title: tool.schema.string().describe("Epic title"),
|
|
@@ -27782,11 +27848,11 @@ var beads_create_epic = tool({
|
|
|
27782
27848
|
},
|
|
27783
27849
|
async execute(args, ctx) {
|
|
27784
27850
|
const validated = EpicCreateArgsSchema.parse(args);
|
|
27785
|
-
const projectKey =
|
|
27786
|
-
const adapter = await
|
|
27851
|
+
const projectKey = getHiveWorkingDirectory();
|
|
27852
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
27787
27853
|
const created = [];
|
|
27788
27854
|
try {
|
|
27789
|
-
const epic = await adapter.
|
|
27855
|
+
const epic = await adapter.createCell(projectKey, {
|
|
27790
27856
|
title: validated.epic_title,
|
|
27791
27857
|
type: "epic",
|
|
27792
27858
|
priority: 1,
|
|
@@ -27795,19 +27861,19 @@ var beads_create_epic = tool({
|
|
|
27795
27861
|
await adapter.markDirty(projectKey, epic.id);
|
|
27796
27862
|
created.push(epic);
|
|
27797
27863
|
for (const subtask of validated.subtasks) {
|
|
27798
|
-
const
|
|
27864
|
+
const subtaskCell = await adapter.createCell(projectKey, {
|
|
27799
27865
|
title: subtask.title,
|
|
27800
27866
|
type: "task",
|
|
27801
27867
|
priority: subtask.priority ?? 2,
|
|
27802
27868
|
parent_id: epic.id
|
|
27803
27869
|
});
|
|
27804
|
-
await adapter.markDirty(projectKey,
|
|
27805
|
-
created.push(
|
|
27870
|
+
await adapter.markDirty(projectKey, subtaskCell.id);
|
|
27871
|
+
created.push(subtaskCell);
|
|
27806
27872
|
}
|
|
27807
27873
|
const result = {
|
|
27808
27874
|
success: true,
|
|
27809
|
-
epic:
|
|
27810
|
-
subtasks: created.slice(1).map((
|
|
27875
|
+
epic: formatCellForOutput(epic),
|
|
27876
|
+
subtasks: created.slice(1).map((c) => formatCellForOutput(c))
|
|
27811
27877
|
};
|
|
27812
27878
|
if (args.project_key) {
|
|
27813
27879
|
try {
|
|
@@ -27827,27 +27893,27 @@ var beads_create_epic = tool({
|
|
|
27827
27893
|
});
|
|
27828
27894
|
await appendEvent(event, args.project_key);
|
|
27829
27895
|
} catch (error45) {
|
|
27830
|
-
console.warn("[
|
|
27896
|
+
console.warn("[hive_create_epic] Failed to emit DecompositionGeneratedEvent:", error45);
|
|
27831
27897
|
}
|
|
27832
27898
|
}
|
|
27833
27899
|
return JSON.stringify(result, null, 2);
|
|
27834
27900
|
} catch (error45) {
|
|
27835
27901
|
const rollbackErrors = [];
|
|
27836
|
-
for (const
|
|
27902
|
+
for (const cell of created) {
|
|
27837
27903
|
try {
|
|
27838
|
-
await adapter.
|
|
27904
|
+
await adapter.deleteCell(projectKey, cell.id, {
|
|
27839
27905
|
reason: "Rollback partial epic"
|
|
27840
27906
|
});
|
|
27841
27907
|
} catch (rollbackError) {
|
|
27842
27908
|
const errMsg = rollbackError instanceof Error ? rollbackError.message : String(rollbackError);
|
|
27843
|
-
console.error(`Failed to rollback
|
|
27844
|
-
rollbackErrors.push(`${
|
|
27909
|
+
console.error(`Failed to rollback cell ${cell.id}:`, rollbackError);
|
|
27910
|
+
rollbackErrors.push(`${cell.id}: ${errMsg}`);
|
|
27845
27911
|
}
|
|
27846
27912
|
}
|
|
27847
27913
|
const errorMsg = error45 instanceof Error ? error45.message : String(error45);
|
|
27848
27914
|
let rollbackInfo = `
|
|
27849
27915
|
|
|
27850
|
-
Rolled back ${created.length - rollbackErrors.length}
|
|
27916
|
+
Rolled back ${created.length - rollbackErrors.length} cell(s)`;
|
|
27851
27917
|
if (rollbackErrors.length > 0) {
|
|
27852
27918
|
rollbackInfo += `
|
|
27853
27919
|
|
|
@@ -27855,151 +27921,151 @@ Rollback failures (${rollbackErrors.length}):
|
|
|
27855
27921
|
${rollbackErrors.join(`
|
|
27856
27922
|
`)}`;
|
|
27857
27923
|
}
|
|
27858
|
-
throw new
|
|
27924
|
+
throw new HiveError(`Epic creation failed: ${errorMsg}${rollbackInfo}`, "hive_create_epic", 1);
|
|
27859
27925
|
}
|
|
27860
27926
|
}
|
|
27861
27927
|
});
|
|
27862
|
-
var
|
|
27863
|
-
description: "Query
|
|
27928
|
+
var hive_query = tool({
|
|
27929
|
+
description: "Query hive cells with filters (replaces bd list, bd ready, bd wip)",
|
|
27864
27930
|
args: {
|
|
27865
27931
|
status: tool.schema.enum(["open", "in_progress", "blocked", "closed"]).optional().describe("Filter by status"),
|
|
27866
27932
|
type: tool.schema.enum(["bug", "feature", "task", "epic", "chore"]).optional().describe("Filter by type"),
|
|
27867
|
-
ready: tool.schema.boolean().optional().describe("Only show unblocked
|
|
27933
|
+
ready: tool.schema.boolean().optional().describe("Only show unblocked cells"),
|
|
27868
27934
|
limit: tool.schema.number().optional().describe("Max results to return (default: 20)")
|
|
27869
27935
|
},
|
|
27870
27936
|
async execute(args, ctx) {
|
|
27871
|
-
const validated =
|
|
27872
|
-
const projectKey =
|
|
27873
|
-
const adapter = await
|
|
27937
|
+
const validated = CellQueryArgsSchema.parse(args);
|
|
27938
|
+
const projectKey = getHiveWorkingDirectory();
|
|
27939
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
27874
27940
|
try {
|
|
27875
|
-
let
|
|
27941
|
+
let cells;
|
|
27876
27942
|
if (validated.ready) {
|
|
27877
|
-
const
|
|
27878
|
-
|
|
27943
|
+
const readyCell = await adapter.getNextReadyCell(projectKey);
|
|
27944
|
+
cells = readyCell ? [readyCell] : [];
|
|
27879
27945
|
} else {
|
|
27880
|
-
|
|
27946
|
+
cells = await adapter.queryCells(projectKey, {
|
|
27881
27947
|
status: validated.status,
|
|
27882
27948
|
type: validated.type,
|
|
27883
27949
|
limit: validated.limit || 20
|
|
27884
27950
|
});
|
|
27885
27951
|
}
|
|
27886
|
-
const formatted =
|
|
27952
|
+
const formatted = cells.map((c) => formatCellForOutput(c));
|
|
27887
27953
|
return JSON.stringify(formatted, null, 2);
|
|
27888
27954
|
} catch (error45) {
|
|
27889
27955
|
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
27890
|
-
throw new
|
|
27956
|
+
throw new HiveError(`Failed to query cells: ${message}`, "hive_query");
|
|
27891
27957
|
}
|
|
27892
27958
|
}
|
|
27893
27959
|
});
|
|
27894
|
-
var
|
|
27895
|
-
description: "Update
|
|
27960
|
+
var hive_update = tool({
|
|
27961
|
+
description: "Update cell status/description",
|
|
27896
27962
|
args: {
|
|
27897
|
-
id: tool.schema.string().describe("
|
|
27963
|
+
id: tool.schema.string().describe("Cell ID"),
|
|
27898
27964
|
status: tool.schema.enum(["open", "in_progress", "blocked", "closed"]).optional().describe("New status"),
|
|
27899
27965
|
description: tool.schema.string().optional().describe("New description"),
|
|
27900
27966
|
priority: tool.schema.number().min(0).max(3).optional().describe("New priority")
|
|
27901
27967
|
},
|
|
27902
27968
|
async execute(args, ctx) {
|
|
27903
|
-
const validated =
|
|
27904
|
-
const projectKey =
|
|
27905
|
-
const adapter = await
|
|
27969
|
+
const validated = CellUpdateArgsSchema.parse(args);
|
|
27970
|
+
const projectKey = getHiveWorkingDirectory();
|
|
27971
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
27906
27972
|
try {
|
|
27907
|
-
let
|
|
27973
|
+
let cell;
|
|
27908
27974
|
if (validated.status) {
|
|
27909
|
-
|
|
27975
|
+
cell = await adapter.changeCellStatus(projectKey, validated.id, validated.status);
|
|
27910
27976
|
}
|
|
27911
27977
|
if (validated.description !== undefined || validated.priority !== undefined) {
|
|
27912
|
-
|
|
27978
|
+
cell = await adapter.updateCell(projectKey, validated.id, {
|
|
27913
27979
|
description: validated.description,
|
|
27914
27980
|
priority: validated.priority
|
|
27915
27981
|
});
|
|
27916
27982
|
} else if (!validated.status) {
|
|
27917
|
-
const
|
|
27918
|
-
if (!
|
|
27919
|
-
throw new
|
|
27983
|
+
const existingCell = await adapter.getCell(projectKey, validated.id);
|
|
27984
|
+
if (!existingCell) {
|
|
27985
|
+
throw new HiveError(`Cell not found: ${validated.id}`, "hive_update");
|
|
27920
27986
|
}
|
|
27921
|
-
|
|
27987
|
+
cell = existingCell;
|
|
27922
27988
|
}
|
|
27923
27989
|
await adapter.markDirty(projectKey, validated.id);
|
|
27924
|
-
const formatted =
|
|
27990
|
+
const formatted = formatCellForOutput(cell);
|
|
27925
27991
|
return JSON.stringify(formatted, null, 2);
|
|
27926
27992
|
} catch (error45) {
|
|
27927
27993
|
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
27928
|
-
throw new
|
|
27994
|
+
throw new HiveError(`Failed to update cell: ${message}`, "hive_update");
|
|
27929
27995
|
}
|
|
27930
27996
|
}
|
|
27931
27997
|
});
|
|
27932
|
-
var
|
|
27933
|
-
description: "Close a
|
|
27998
|
+
var hive_close = tool({
|
|
27999
|
+
description: "Close a cell with reason",
|
|
27934
28000
|
args: {
|
|
27935
|
-
id: tool.schema.string().describe("
|
|
28001
|
+
id: tool.schema.string().describe("Cell ID"),
|
|
27936
28002
|
reason: tool.schema.string().describe("Completion reason")
|
|
27937
28003
|
},
|
|
27938
28004
|
async execute(args, ctx) {
|
|
27939
|
-
const validated =
|
|
27940
|
-
const projectKey =
|
|
27941
|
-
const adapter = await
|
|
28005
|
+
const validated = CellCloseArgsSchema.parse(args);
|
|
28006
|
+
const projectKey = getHiveWorkingDirectory();
|
|
28007
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
27942
28008
|
try {
|
|
27943
|
-
const
|
|
28009
|
+
const cell = await adapter.closeCell(projectKey, validated.id, validated.reason);
|
|
27944
28010
|
await adapter.markDirty(projectKey, validated.id);
|
|
27945
|
-
return `Closed ${
|
|
28011
|
+
return `Closed ${cell.id}: ${validated.reason}`;
|
|
27946
28012
|
} catch (error45) {
|
|
27947
28013
|
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
27948
|
-
throw new
|
|
28014
|
+
throw new HiveError(`Failed to close cell: ${message}`, "hive_close");
|
|
27949
28015
|
}
|
|
27950
28016
|
}
|
|
27951
28017
|
});
|
|
27952
|
-
var
|
|
27953
|
-
description: "Mark a
|
|
28018
|
+
var hive_start = tool({
|
|
28019
|
+
description: "Mark a cell as in-progress (shortcut for update --status in_progress)",
|
|
27954
28020
|
args: {
|
|
27955
|
-
id: tool.schema.string().describe("
|
|
28021
|
+
id: tool.schema.string().describe("Cell ID")
|
|
27956
28022
|
},
|
|
27957
28023
|
async execute(args, ctx) {
|
|
27958
|
-
const projectKey =
|
|
27959
|
-
const adapter = await
|
|
28024
|
+
const projectKey = getHiveWorkingDirectory();
|
|
28025
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
27960
28026
|
try {
|
|
27961
|
-
const
|
|
28027
|
+
const cell = await adapter.changeCellStatus(projectKey, args.id, "in_progress");
|
|
27962
28028
|
await adapter.markDirty(projectKey, args.id);
|
|
27963
|
-
return `Started: ${
|
|
28029
|
+
return `Started: ${cell.id}`;
|
|
27964
28030
|
} catch (error45) {
|
|
27965
28031
|
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
27966
|
-
throw new
|
|
28032
|
+
throw new HiveError(`Failed to start cell: ${message}`, "hive_start");
|
|
27967
28033
|
}
|
|
27968
28034
|
}
|
|
27969
28035
|
});
|
|
27970
|
-
var
|
|
27971
|
-
description: "Get the next ready
|
|
28036
|
+
var hive_ready = tool({
|
|
28037
|
+
description: "Get the next ready cell (unblocked, highest priority)",
|
|
27972
28038
|
args: {},
|
|
27973
28039
|
async execute(args, ctx) {
|
|
27974
|
-
const projectKey =
|
|
27975
|
-
const adapter = await
|
|
28040
|
+
const projectKey = getHiveWorkingDirectory();
|
|
28041
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
27976
28042
|
try {
|
|
27977
|
-
const
|
|
27978
|
-
if (!
|
|
27979
|
-
return "No ready
|
|
28043
|
+
const cell = await adapter.getNextReadyCell(projectKey);
|
|
28044
|
+
if (!cell) {
|
|
28045
|
+
return "No ready cells";
|
|
27980
28046
|
}
|
|
27981
|
-
const formatted =
|
|
28047
|
+
const formatted = formatCellForOutput(cell);
|
|
27982
28048
|
return JSON.stringify(formatted, null, 2);
|
|
27983
28049
|
} catch (error45) {
|
|
27984
28050
|
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
27985
|
-
throw new
|
|
28051
|
+
throw new HiveError(`Failed to get ready cells: ${message}`, "hive_ready");
|
|
27986
28052
|
}
|
|
27987
28053
|
}
|
|
27988
28054
|
});
|
|
27989
|
-
var
|
|
27990
|
-
description: "Sync
|
|
28055
|
+
var hive_sync = tool({
|
|
28056
|
+
description: "Sync hive to git and push (MANDATORY at session end)",
|
|
27991
28057
|
args: {
|
|
27992
28058
|
auto_pull: tool.schema.boolean().optional().describe("Pull before sync (default: true)")
|
|
27993
28059
|
},
|
|
27994
28060
|
async execute(args, ctx) {
|
|
27995
28061
|
const autoPull = args.auto_pull ?? true;
|
|
27996
|
-
const projectKey =
|
|
27997
|
-
const adapter = await
|
|
28062
|
+
const projectKey = getHiveWorkingDirectory();
|
|
28063
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
27998
28064
|
const TIMEOUT_MS = 30000;
|
|
27999
28065
|
const withTimeout = async (promise2, timeoutMs, operation) => {
|
|
28000
28066
|
let timeoutId;
|
|
28001
28067
|
const timeoutPromise = new Promise((_, reject) => {
|
|
28002
|
-
timeoutId = setTimeout(() => reject(new
|
|
28068
|
+
timeoutId = setTimeout(() => reject(new HiveError(`Operation timed out after ${timeoutMs}ms`, operation)), timeoutMs);
|
|
28003
28069
|
});
|
|
28004
28070
|
try {
|
|
28005
28071
|
return await Promise.race([promise2, timeoutPromise]);
|
|
@@ -28012,74 +28078,156 @@ var beads_sync = tool({
|
|
|
28012
28078
|
const flushManager = new FlushManager({
|
|
28013
28079
|
adapter,
|
|
28014
28080
|
projectKey,
|
|
28015
|
-
outputPath: `${projectKey}/.
|
|
28081
|
+
outputPath: `${projectKey}/.hive/issues.jsonl`
|
|
28016
28082
|
});
|
|
28017
|
-
const flushResult = await withTimeout(flushManager.flush(), TIMEOUT_MS, "flush
|
|
28018
|
-
if (flushResult.
|
|
28019
|
-
return "No
|
|
28083
|
+
const flushResult = await withTimeout(flushManager.flush(), TIMEOUT_MS, "flush hive");
|
|
28084
|
+
if (flushResult.cellsExported === 0) {
|
|
28085
|
+
return "No cells to sync";
|
|
28020
28086
|
}
|
|
28021
|
-
const
|
|
28087
|
+
const hiveStatusResult = await runGitCommand([
|
|
28022
28088
|
"status",
|
|
28023
28089
|
"--porcelain",
|
|
28024
|
-
".
|
|
28090
|
+
".hive/"
|
|
28025
28091
|
]);
|
|
28026
|
-
const hasChanges =
|
|
28092
|
+
const hasChanges = hiveStatusResult.stdout.trim() !== "";
|
|
28027
28093
|
if (hasChanges) {
|
|
28028
|
-
const addResult = await runGitCommand(["add", ".
|
|
28094
|
+
const addResult = await runGitCommand(["add", ".hive/"]);
|
|
28029
28095
|
if (addResult.exitCode !== 0) {
|
|
28030
|
-
throw new
|
|
28096
|
+
throw new HiveError(`Failed to stage hive: ${addResult.stderr}`, "git add .hive/", addResult.exitCode);
|
|
28031
28097
|
}
|
|
28032
|
-
const commitResult = await withTimeout(runGitCommand(["commit", "-m", "chore: sync
|
|
28098
|
+
const commitResult = await withTimeout(runGitCommand(["commit", "-m", "chore: sync hive"]), TIMEOUT_MS, "git commit");
|
|
28033
28099
|
if (commitResult.exitCode !== 0 && !commitResult.stdout.includes("nothing to commit")) {
|
|
28034
|
-
throw new
|
|
28100
|
+
throw new HiveError(`Failed to commit hive: ${commitResult.stderr}`, "git commit", commitResult.exitCode);
|
|
28035
28101
|
}
|
|
28036
28102
|
}
|
|
28037
28103
|
if (autoPull) {
|
|
28038
28104
|
const pullResult = await withTimeout(runGitCommand(["pull", "--rebase"]), TIMEOUT_MS, "git pull --rebase");
|
|
28039
28105
|
if (pullResult.exitCode !== 0) {
|
|
28040
|
-
throw new
|
|
28106
|
+
throw new HiveError(`Failed to pull: ${pullResult.stderr}`, "git pull --rebase", pullResult.exitCode);
|
|
28041
28107
|
}
|
|
28042
28108
|
}
|
|
28043
28109
|
const pushResult = await withTimeout(runGitCommand(["push"]), TIMEOUT_MS, "git push");
|
|
28044
28110
|
if (pushResult.exitCode !== 0) {
|
|
28045
|
-
throw new
|
|
28111
|
+
throw new HiveError(`Failed to push: ${pushResult.stderr}`, "git push", pushResult.exitCode);
|
|
28046
28112
|
}
|
|
28047
|
-
return "
|
|
28113
|
+
return "Hive synced and pushed successfully";
|
|
28048
28114
|
}
|
|
28049
28115
|
});
|
|
28050
|
-
var
|
|
28051
|
-
description: "Add metadata linking
|
|
28116
|
+
var hive_link_thread = tool({
|
|
28117
|
+
description: "Add metadata linking cell to Agent Mail thread",
|
|
28052
28118
|
args: {
|
|
28053
|
-
|
|
28119
|
+
cell_id: tool.schema.string().describe("Cell ID"),
|
|
28054
28120
|
thread_id: tool.schema.string().describe("Agent Mail thread ID")
|
|
28055
28121
|
},
|
|
28056
28122
|
async execute(args, ctx) {
|
|
28057
|
-
const projectKey =
|
|
28058
|
-
const adapter = await
|
|
28123
|
+
const projectKey = getHiveWorkingDirectory();
|
|
28124
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
28059
28125
|
try {
|
|
28060
|
-
const
|
|
28061
|
-
if (!
|
|
28062
|
-
throw new
|
|
28126
|
+
const cell = await adapter.getCell(projectKey, args.cell_id);
|
|
28127
|
+
if (!cell) {
|
|
28128
|
+
throw new HiveError(`Cell not found: ${args.cell_id}`, "hive_link_thread");
|
|
28063
28129
|
}
|
|
28064
|
-
const existingDesc =
|
|
28130
|
+
const existingDesc = cell.description || "";
|
|
28065
28131
|
const threadMarker = `[thread:${args.thread_id}]`;
|
|
28066
28132
|
if (existingDesc.includes(threadMarker)) {
|
|
28067
|
-
return `
|
|
28133
|
+
return `Cell ${args.cell_id} already linked to thread ${args.thread_id}`;
|
|
28068
28134
|
}
|
|
28069
28135
|
const newDesc = existingDesc ? `${existingDesc}
|
|
28070
28136
|
|
|
28071
28137
|
${threadMarker}` : threadMarker;
|
|
28072
|
-
await adapter.
|
|
28138
|
+
await adapter.updateCell(projectKey, args.cell_id, {
|
|
28073
28139
|
description: newDesc
|
|
28074
28140
|
});
|
|
28075
|
-
await adapter.markDirty(projectKey, args.
|
|
28076
|
-
return `Linked
|
|
28141
|
+
await adapter.markDirty(projectKey, args.cell_id);
|
|
28142
|
+
return `Linked cell ${args.cell_id} to thread ${args.thread_id}`;
|
|
28077
28143
|
} catch (error45) {
|
|
28078
28144
|
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
28079
|
-
throw new
|
|
28145
|
+
throw new HiveError(`Failed to link thread: ${message}`, "hive_link_thread");
|
|
28080
28146
|
}
|
|
28081
28147
|
}
|
|
28082
28148
|
});
|
|
28149
|
+
var hiveTools = {
|
|
28150
|
+
hive_create,
|
|
28151
|
+
hive_create_epic,
|
|
28152
|
+
hive_query,
|
|
28153
|
+
hive_update,
|
|
28154
|
+
hive_close,
|
|
28155
|
+
hive_start,
|
|
28156
|
+
hive_ready,
|
|
28157
|
+
hive_sync,
|
|
28158
|
+
hive_link_thread
|
|
28159
|
+
};
|
|
28160
|
+
var warnedTools = new Set;
|
|
28161
|
+
function warnDeprecated(oldName, newName) {
|
|
28162
|
+
if (warnedTools.has(oldName)) {
|
|
28163
|
+
return;
|
|
28164
|
+
}
|
|
28165
|
+
warnedTools.add(oldName);
|
|
28166
|
+
console.warn(`[DEPRECATED] ${oldName} is deprecated, use ${newName} instead. Will be removed in v1.0`);
|
|
28167
|
+
}
|
|
28168
|
+
var beads_create = tool({
|
|
28169
|
+
...hive_create,
|
|
28170
|
+
async execute(args, ctx) {
|
|
28171
|
+
warnDeprecated("beads_create", "hive_create");
|
|
28172
|
+
return hive_create.execute(args, ctx);
|
|
28173
|
+
}
|
|
28174
|
+
});
|
|
28175
|
+
var beads_create_epic = tool({
|
|
28176
|
+
...hive_create_epic,
|
|
28177
|
+
async execute(args, ctx) {
|
|
28178
|
+
warnDeprecated("beads_create_epic", "hive_create_epic");
|
|
28179
|
+
return hive_create_epic.execute(args, ctx);
|
|
28180
|
+
}
|
|
28181
|
+
});
|
|
28182
|
+
var beads_query = tool({
|
|
28183
|
+
...hive_query,
|
|
28184
|
+
async execute(args, ctx) {
|
|
28185
|
+
warnDeprecated("beads_query", "hive_query");
|
|
28186
|
+
return hive_query.execute(args, ctx);
|
|
28187
|
+
}
|
|
28188
|
+
});
|
|
28189
|
+
var beads_update = tool({
|
|
28190
|
+
...hive_update,
|
|
28191
|
+
async execute(args, ctx) {
|
|
28192
|
+
warnDeprecated("beads_update", "hive_update");
|
|
28193
|
+
return hive_update.execute(args, ctx);
|
|
28194
|
+
}
|
|
28195
|
+
});
|
|
28196
|
+
var beads_close = tool({
|
|
28197
|
+
...hive_close,
|
|
28198
|
+
async execute(args, ctx) {
|
|
28199
|
+
warnDeprecated("beads_close", "hive_close");
|
|
28200
|
+
return hive_close.execute(args, ctx);
|
|
28201
|
+
}
|
|
28202
|
+
});
|
|
28203
|
+
var beads_start = tool({
|
|
28204
|
+
...hive_start,
|
|
28205
|
+
async execute(args, ctx) {
|
|
28206
|
+
warnDeprecated("beads_start", "hive_start");
|
|
28207
|
+
return hive_start.execute(args, ctx);
|
|
28208
|
+
}
|
|
28209
|
+
});
|
|
28210
|
+
var beads_ready = tool({
|
|
28211
|
+
...hive_ready,
|
|
28212
|
+
async execute(args, ctx) {
|
|
28213
|
+
warnDeprecated("beads_ready", "hive_ready");
|
|
28214
|
+
return hive_ready.execute(args, ctx);
|
|
28215
|
+
}
|
|
28216
|
+
});
|
|
28217
|
+
var beads_sync = tool({
|
|
28218
|
+
...hive_sync,
|
|
28219
|
+
async execute(args, ctx) {
|
|
28220
|
+
warnDeprecated("beads_sync", "hive_sync");
|
|
28221
|
+
return hive_sync.execute(args, ctx);
|
|
28222
|
+
}
|
|
28223
|
+
});
|
|
28224
|
+
var beads_link_thread = tool({
|
|
28225
|
+
...hive_link_thread,
|
|
28226
|
+
async execute(args, ctx) {
|
|
28227
|
+
warnDeprecated("beads_link_thread", "hive_link_thread");
|
|
28228
|
+
return hive_link_thread.execute(args, ctx);
|
|
28229
|
+
}
|
|
28230
|
+
});
|
|
28083
28231
|
var beadsTools = {
|
|
28084
28232
|
beads_create,
|
|
28085
28233
|
beads_create_epic,
|
|
@@ -28209,6 +28357,29 @@ var toolCheckers = {
|
|
|
28209
28357
|
};
|
|
28210
28358
|
}
|
|
28211
28359
|
},
|
|
28360
|
+
hive: async () => {
|
|
28361
|
+
const exists = await commandExists("hive");
|
|
28362
|
+
if (!exists) {
|
|
28363
|
+
return {
|
|
28364
|
+
available: false,
|
|
28365
|
+
checkedAt: new Date().toISOString(),
|
|
28366
|
+
error: "hive command not found"
|
|
28367
|
+
};
|
|
28368
|
+
}
|
|
28369
|
+
try {
|
|
28370
|
+
const result = await Bun.$`hive --version`.quiet().nothrow();
|
|
28371
|
+
return {
|
|
28372
|
+
available: result.exitCode === 0,
|
|
28373
|
+
checkedAt: new Date().toISOString()
|
|
28374
|
+
};
|
|
28375
|
+
} catch (e) {
|
|
28376
|
+
return {
|
|
28377
|
+
available: false,
|
|
28378
|
+
checkedAt: new Date().toISOString(),
|
|
28379
|
+
error: String(e)
|
|
28380
|
+
};
|
|
28381
|
+
}
|
|
28382
|
+
},
|
|
28212
28383
|
beads: async () => {
|
|
28213
28384
|
const exists = await commandExists("bd");
|
|
28214
28385
|
if (!exists) {
|
|
@@ -28262,7 +28433,8 @@ var fallbackBehaviors = {
|
|
|
28262
28433
|
"semantic-memory": "Learning data stored in-memory only (lost on session end)",
|
|
28263
28434
|
cass: "Decomposition proceeds without historical context from past sessions",
|
|
28264
28435
|
ubs: "Subtask completion skips bug scanning - manual review recommended",
|
|
28265
|
-
|
|
28436
|
+
hive: "Swarm cannot track issues - task coordination will be less reliable",
|
|
28437
|
+
beads: "DEPRECATED: Use hive instead. Swarm cannot track issues - task coordination will be less reliable",
|
|
28266
28438
|
"swarm-mail": "Multi-agent coordination disabled - file conflicts possible if multiple agents active",
|
|
28267
28439
|
"agent-mail": "DEPRECATED: Use swarm-mail instead. Legacy MCP server mode - file conflicts possible if multiple agents active"
|
|
28268
28440
|
};
|
|
@@ -28293,6 +28465,7 @@ async function checkAllTools() {
|
|
|
28293
28465
|
"semantic-memory",
|
|
28294
28466
|
"cass",
|
|
28295
28467
|
"ubs",
|
|
28468
|
+
"hive",
|
|
28296
28469
|
"beads",
|
|
28297
28470
|
"swarm-mail",
|
|
28298
28471
|
"agent-mail"
|
|
@@ -28355,8 +28528,8 @@ function formatToolAvailability(availability) {
|
|
|
28355
28528
|
|
|
28356
28529
|
// src/rate-limiter.ts
|
|
28357
28530
|
var import_ioredis = __toESM(require_built3(), 1);
|
|
28358
|
-
import { mkdirSync, existsSync } from "node:fs";
|
|
28359
|
-
import { dirname, join } from "node:path";
|
|
28531
|
+
import { mkdirSync, existsSync as existsSync2 } from "node:fs";
|
|
28532
|
+
import { dirname, join as join2 } from "node:path";
|
|
28360
28533
|
import { homedir } from "node:os";
|
|
28361
28534
|
var sqliteAvailable = false;
|
|
28362
28535
|
var createDatabase = null;
|
|
@@ -28472,7 +28645,7 @@ class SqliteRateLimiter {
|
|
|
28472
28645
|
throw new Error("SQLite is not available in this runtime (requires Bun)");
|
|
28473
28646
|
}
|
|
28474
28647
|
const dir = dirname(dbPath);
|
|
28475
|
-
if (!
|
|
28648
|
+
if (!existsSync2(dir)) {
|
|
28476
28649
|
mkdirSync(dir, { recursive: true });
|
|
28477
28650
|
}
|
|
28478
28651
|
this.db = createDatabase(dbPath);
|
|
@@ -28617,7 +28790,7 @@ async function createRateLimiter(options2) {
|
|
|
28617
28790
|
const {
|
|
28618
28791
|
backend,
|
|
28619
28792
|
redisUrl = process.env.OPENCODE_RATE_LIMIT_REDIS_URL || "redis://localhost:6379",
|
|
28620
|
-
sqlitePath = process.env.OPENCODE_RATE_LIMIT_SQLITE_PATH ||
|
|
28793
|
+
sqlitePath = process.env.OPENCODE_RATE_LIMIT_SQLITE_PATH || join2(homedir(), ".config", "opencode", "rate-limits.db")
|
|
28621
28794
|
} = options2 || {};
|
|
28622
28795
|
if (backend === "memory") {
|
|
28623
28796
|
return new InMemoryRateLimiter;
|
|
@@ -28677,13 +28850,13 @@ async function getRateLimiter() {
|
|
|
28677
28850
|
|
|
28678
28851
|
// src/agent-mail.ts
|
|
28679
28852
|
import {
|
|
28680
|
-
existsSync as
|
|
28853
|
+
existsSync as existsSync3,
|
|
28681
28854
|
mkdirSync as mkdirSync2,
|
|
28682
|
-
readFileSync,
|
|
28855
|
+
readFileSync as readFileSync2,
|
|
28683
28856
|
writeFileSync,
|
|
28684
28857
|
unlinkSync
|
|
28685
28858
|
} from "fs";
|
|
28686
|
-
import { join as
|
|
28859
|
+
import { join as join3 } from "path";
|
|
28687
28860
|
import { tmpdir } from "os";
|
|
28688
28861
|
var AGENT_MAIL_URL = "http://127.0.0.1:8765";
|
|
28689
28862
|
var DEFAULT_TTL_SECONDS = 3600;
|
|
@@ -28707,16 +28880,16 @@ var RECOVERY_CONFIG = {
|
|
|
28707
28880
|
restartCooldownMs: 1e4,
|
|
28708
28881
|
enabled: process.env.OPENCODE_AGENT_MAIL_AUTO_RESTART !== "false"
|
|
28709
28882
|
};
|
|
28710
|
-
var SESSION_STATE_DIR = process.env.SWARM_STATE_DIR ||
|
|
28883
|
+
var SESSION_STATE_DIR = process.env.SWARM_STATE_DIR || join3(tmpdir(), "swarm-sessions");
|
|
28711
28884
|
function getSessionStatePath(sessionID) {
|
|
28712
28885
|
const safeID = sessionID.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
28713
|
-
return
|
|
28886
|
+
return join3(SESSION_STATE_DIR, `${safeID}.json`);
|
|
28714
28887
|
}
|
|
28715
28888
|
function loadSessionState(sessionID) {
|
|
28716
28889
|
const path = getSessionStatePath(sessionID);
|
|
28717
28890
|
try {
|
|
28718
|
-
if (
|
|
28719
|
-
const data =
|
|
28891
|
+
if (existsSync3(path)) {
|
|
28892
|
+
const data = readFileSync2(path, "utf-8");
|
|
28720
28893
|
return JSON.parse(data);
|
|
28721
28894
|
}
|
|
28722
28895
|
} catch (error45) {
|
|
@@ -28726,7 +28899,7 @@ function loadSessionState(sessionID) {
|
|
|
28726
28899
|
}
|
|
28727
28900
|
function saveSessionState(sessionID, state) {
|
|
28728
28901
|
try {
|
|
28729
|
-
if (!
|
|
28902
|
+
if (!existsSync3(SESSION_STATE_DIR)) {
|
|
28730
28903
|
mkdirSync2(SESSION_STATE_DIR, { recursive: true });
|
|
28731
28904
|
}
|
|
28732
28905
|
const path = getSessionStatePath(sessionID);
|
|
@@ -29507,13 +29680,13 @@ import {
|
|
|
29507
29680
|
getActiveReservations
|
|
29508
29681
|
} from "swarm-mail";
|
|
29509
29682
|
import {
|
|
29510
|
-
existsSync as
|
|
29683
|
+
existsSync as existsSync4,
|
|
29511
29684
|
mkdirSync as mkdirSync3,
|
|
29512
|
-
readFileSync as
|
|
29685
|
+
readFileSync as readFileSync3,
|
|
29513
29686
|
writeFileSync as writeFileSync2,
|
|
29514
29687
|
unlinkSync as unlinkSync2
|
|
29515
29688
|
} from "node:fs";
|
|
29516
|
-
import { join as
|
|
29689
|
+
import { join as join4 } from "node:path";
|
|
29517
29690
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
29518
29691
|
var MAX_INBOX_LIMIT2 = 5;
|
|
29519
29692
|
var swarmMailProjectDirectory = null;
|
|
@@ -29523,16 +29696,16 @@ function setSwarmMailProjectDirectory(directory) {
|
|
|
29523
29696
|
function getSwarmMailProjectDirectory() {
|
|
29524
29697
|
return swarmMailProjectDirectory ?? undefined;
|
|
29525
29698
|
}
|
|
29526
|
-
var SESSION_STATE_DIR2 = process.env.SWARM_STATE_DIR ||
|
|
29699
|
+
var SESSION_STATE_DIR2 = process.env.SWARM_STATE_DIR || join4(tmpdir2(), "swarm-sessions");
|
|
29527
29700
|
function getSessionStatePath2(sessionID) {
|
|
29528
29701
|
const safeID = sessionID.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
29529
|
-
return
|
|
29702
|
+
return join4(SESSION_STATE_DIR2, `${safeID}.json`);
|
|
29530
29703
|
}
|
|
29531
29704
|
function loadSessionState2(sessionID) {
|
|
29532
29705
|
const path = getSessionStatePath2(sessionID);
|
|
29533
29706
|
try {
|
|
29534
|
-
if (
|
|
29535
|
-
const data =
|
|
29707
|
+
if (existsSync4(path)) {
|
|
29708
|
+
const data = readFileSync3(path, "utf-8");
|
|
29536
29709
|
return JSON.parse(data);
|
|
29537
29710
|
}
|
|
29538
29711
|
} catch (error45) {
|
|
@@ -29542,7 +29715,7 @@ function loadSessionState2(sessionID) {
|
|
|
29542
29715
|
}
|
|
29543
29716
|
function saveSessionState2(sessionID, state) {
|
|
29544
29717
|
try {
|
|
29545
|
-
if (!
|
|
29718
|
+
if (!existsSync4(SESSION_STATE_DIR2)) {
|
|
29546
29719
|
mkdirSync3(SESSION_STATE_DIR2, { recursive: true });
|
|
29547
29720
|
}
|
|
29548
29721
|
const path = getSessionStatePath2(sessionID);
|
|
@@ -29556,7 +29729,7 @@ function saveSessionState2(sessionID, state) {
|
|
|
29556
29729
|
function clearSessionState(sessionID) {
|
|
29557
29730
|
const path = getSessionStatePath2(sessionID);
|
|
29558
29731
|
try {
|
|
29559
|
-
if (
|
|
29732
|
+
if (existsSync4(path)) {
|
|
29560
29733
|
unlinkSync2(path);
|
|
29561
29734
|
}
|
|
29562
29735
|
} catch {}
|
|
@@ -29894,7 +30067,7 @@ function formatZodErrors(error45) {
|
|
|
29894
30067
|
var SCHEMA_REGISTRY = {
|
|
29895
30068
|
evaluation: EvaluationSchema,
|
|
29896
30069
|
task_decomposition: TaskDecompositionSchema,
|
|
29897
|
-
|
|
30070
|
+
cell_tree: CellTreeSchema
|
|
29898
30071
|
};
|
|
29899
30072
|
function getSchemaByName(name) {
|
|
29900
30073
|
const schema = SCHEMA_REGISTRY[name];
|
|
@@ -30030,7 +30203,7 @@ var structured_validate = tool({
|
|
|
30030
30203
|
description: "Validate agent response against a schema. Extracts JSON and validates with Zod. Returns structured errors for retry feedback.",
|
|
30031
30204
|
args: {
|
|
30032
30205
|
response: tool.schema.string().describe("Agent response to validate"),
|
|
30033
|
-
schema_name: tool.schema.enum(["evaluation", "task_decomposition", "
|
|
30206
|
+
schema_name: tool.schema.enum(["evaluation", "task_decomposition", "cell_tree"]).describe("Schema to validate against: " + "evaluation = agent self-eval with criteria, " + "task_decomposition = swarm task breakdown, " + "cell_tree = epic with subtasks"),
|
|
30034
30207
|
max_retries: tool.schema.number().min(1).max(5).optional().describe("Max retries (for tracking - actual retry logic is external)")
|
|
30035
30208
|
},
|
|
30036
30209
|
async execute(args, ctx) {
|
|
@@ -30216,15 +30389,15 @@ var structured_parse_decomposition = tool({
|
|
|
30216
30389
|
}
|
|
30217
30390
|
}
|
|
30218
30391
|
});
|
|
30219
|
-
var
|
|
30220
|
-
description: "Parse and validate bead tree response. Uses
|
|
30392
|
+
var structured_parse_cell_tree = tool({
|
|
30393
|
+
description: "Parse and validate bead tree response. Uses CellTreeSchema. Validates before creating epic with subtasks.",
|
|
30221
30394
|
args: {
|
|
30222
30395
|
response: tool.schema.string().describe("Agent response containing bead tree")
|
|
30223
30396
|
},
|
|
30224
30397
|
async execute(args, ctx) {
|
|
30225
30398
|
try {
|
|
30226
30399
|
const [extracted, method] = extractJsonFromText(args.response);
|
|
30227
|
-
const validated =
|
|
30400
|
+
const validated = CellTreeSchema.parse(extracted);
|
|
30228
30401
|
const allFiles = validated.subtasks.flatMap((s) => s.files);
|
|
30229
30402
|
const uniqueFiles = [...new Set(allFiles)];
|
|
30230
30403
|
return JSON.stringify({
|
|
@@ -30283,7 +30456,7 @@ var structuredTools = {
|
|
|
30283
30456
|
structured_validate,
|
|
30284
30457
|
structured_parse_evaluation,
|
|
30285
30458
|
structured_parse_decomposition,
|
|
30286
|
-
|
|
30459
|
+
structured_parse_cell_tree
|
|
30287
30460
|
};
|
|
30288
30461
|
|
|
30289
30462
|
// src/swarm.ts
|
|
@@ -30306,9 +30479,9 @@ var DECOMPOSITION_PROMPT = `You are decomposing a task into parallelizable subta
|
|
|
30306
30479
|
|
|
30307
30480
|
After decomposition, the coordinator will:
|
|
30308
30481
|
1. Create an epic bead for the overall task
|
|
30309
|
-
2. Create child
|
|
30482
|
+
2. Create child cells for each subtask
|
|
30310
30483
|
3. Track progress through bead status updates
|
|
30311
|
-
4. Close
|
|
30484
|
+
4. Close cells with summaries when complete
|
|
30312
30485
|
|
|
30313
30486
|
Agents MUST update their bead status as they work. No silent progress.
|
|
30314
30487
|
|
|
@@ -30328,7 +30501,7 @@ Respond with a JSON object matching this schema:
|
|
|
30328
30501
|
\`\`\`typescript
|
|
30329
30502
|
{
|
|
30330
30503
|
epic: {
|
|
30331
|
-
title: string, // Epic title for the
|
|
30504
|
+
title: string, // Epic title for the hive tracker
|
|
30332
30505
|
description?: string // Brief description of the overall goal
|
|
30333
30506
|
},
|
|
30334
30507
|
subtasks: [
|
|
@@ -30379,9 +30552,9 @@ var STRATEGY_DECOMPOSITION_PROMPT = `You are decomposing a task into paralleliza
|
|
|
30379
30552
|
|
|
30380
30553
|
After decomposition, the coordinator will:
|
|
30381
30554
|
1. Create an epic bead for the overall task
|
|
30382
|
-
2. Create child
|
|
30555
|
+
2. Create child cells for each subtask
|
|
30383
30556
|
3. Track progress through bead status updates
|
|
30384
|
-
4. Close
|
|
30557
|
+
4. Close cells with summaries when complete
|
|
30385
30558
|
|
|
30386
30559
|
Agents MUST update their bead status as they work. No silent progress.
|
|
30387
30560
|
|
|
@@ -30401,7 +30574,7 @@ Respond with a JSON object matching this schema:
|
|
|
30401
30574
|
\`\`\`typescript
|
|
30402
30575
|
{
|
|
30403
30576
|
epic: {
|
|
30404
|
-
title: string, // Epic title for the
|
|
30577
|
+
title: string, // Epic title for the hive tracker
|
|
30405
30578
|
description?: string // Brief description of the overall goal
|
|
30406
30579
|
},
|
|
30407
30580
|
subtasks: [
|
|
@@ -30591,7 +30764,7 @@ ${fullContext}` : `## Additional Context
|
|
|
30591
30764
|
const prompt = DECOMPOSITION_PROMPT.replace("{task}", args.task).replace("{max_subtasks}", (args.max_subtasks ?? 5).toString()).replace("{context_section}", contextSection);
|
|
30592
30765
|
return JSON.stringify({
|
|
30593
30766
|
prompt,
|
|
30594
|
-
expected_schema: "
|
|
30767
|
+
expected_schema: "CellTree",
|
|
30595
30768
|
schema_hint: {
|
|
30596
30769
|
epic: { title: "string", description: "string?" },
|
|
30597
30770
|
subtasks: [
|
|
@@ -30604,21 +30777,21 @@ ${fullContext}` : `## Additional Context
|
|
|
30604
30777
|
}
|
|
30605
30778
|
]
|
|
30606
30779
|
},
|
|
30607
|
-
validation_note: "Parse agent response as JSON and validate with
|
|
30780
|
+
validation_note: "Parse agent response as JSON and validate with CellTreeSchema from schemas/bead.ts",
|
|
30608
30781
|
cass_history: cassResultInfo,
|
|
30609
30782
|
memory_query: formatMemoryQueryForDecomposition2(args.task, 3)
|
|
30610
30783
|
}, null, 2);
|
|
30611
30784
|
}
|
|
30612
30785
|
});
|
|
30613
30786
|
var swarm_validate_decomposition = tool({
|
|
30614
|
-
description: "Validate a decomposition response against
|
|
30787
|
+
description: "Validate a decomposition response against CellTreeSchema",
|
|
30615
30788
|
args: {
|
|
30616
|
-
response: tool.schema.string().describe("JSON response from agent (
|
|
30789
|
+
response: tool.schema.string().describe("JSON response from agent (CellTree format)")
|
|
30617
30790
|
},
|
|
30618
30791
|
async execute(args) {
|
|
30619
30792
|
try {
|
|
30620
30793
|
const parsed = JSON.parse(args.response);
|
|
30621
|
-
const validated =
|
|
30794
|
+
const validated = CellTreeSchema.parse(parsed);
|
|
30622
30795
|
const conflicts = detectFileConflicts(validated.subtasks);
|
|
30623
30796
|
if (conflicts.length > 0) {
|
|
30624
30797
|
return JSON.stringify({
|
|
@@ -30649,7 +30822,7 @@ var swarm_validate_decomposition = tool({
|
|
|
30649
30822
|
const instructionConflicts = detectInstructionConflicts(validated.subtasks);
|
|
30650
30823
|
return JSON.stringify({
|
|
30651
30824
|
valid: true,
|
|
30652
|
-
|
|
30825
|
+
cell_tree: validated,
|
|
30653
30826
|
stats: {
|
|
30654
30827
|
subtask_count: validated.subtasks.length,
|
|
30655
30828
|
total_files: new Set(validated.subtasks.flatMap((s) => s.files)).size,
|
|
@@ -30751,7 +30924,7 @@ ${args.context}` : `## Additional Context
|
|
|
30751
30924
|
const subagentInstructions = `
|
|
30752
30925
|
## CRITICAL: Output Format
|
|
30753
30926
|
|
|
30754
|
-
You are a planner subagent. Your ONLY output must be valid JSON matching the
|
|
30927
|
+
You are a planner subagent. Your ONLY output must be valid JSON matching the CellTree schema.
|
|
30755
30928
|
|
|
30756
30929
|
DO NOT include:
|
|
30757
30930
|
- Explanatory text before or after the JSON
|
|
@@ -30785,7 +30958,7 @@ OUTPUT ONLY the raw JSON object.
|
|
|
30785
30958
|
]
|
|
30786
30959
|
}
|
|
30787
30960
|
|
|
30788
|
-
Now generate the
|
|
30961
|
+
Now generate the CellTree for the given task.`;
|
|
30789
30962
|
const fullPrompt = `${planningPrompt}
|
|
30790
30963
|
|
|
30791
30964
|
${subagentInstructions}`;
|
|
@@ -30797,12 +30970,12 @@ ${subagentInstructions}`;
|
|
|
30797
30970
|
selected: selectedStrategy,
|
|
30798
30971
|
reasoning: strategyReasoning
|
|
30799
30972
|
},
|
|
30800
|
-
expected_output: "
|
|
30973
|
+
expected_output: "CellTree JSON (raw JSON, no markdown)",
|
|
30801
30974
|
next_steps: [
|
|
30802
30975
|
"1. Spawn subagent with Task tool using returned prompt",
|
|
30803
30976
|
"2. Parse subagent response as JSON",
|
|
30804
30977
|
"3. Validate with swarm_validate_decomposition",
|
|
30805
|
-
"4. Create
|
|
30978
|
+
"4. Create cells with hive_create_epic"
|
|
30806
30979
|
],
|
|
30807
30980
|
cass_history: cassResultInfo,
|
|
30808
30981
|
skills: skillsInfo,
|
|
@@ -31061,17 +31234,17 @@ var STRATEGY_DECOMPOSITION_PROMPT2 = `You are decomposing a task into paralleliz
|
|
|
31061
31234
|
|
|
31062
31235
|
{skills_context}
|
|
31063
31236
|
|
|
31064
|
-
## MANDATORY:
|
|
31237
|
+
## MANDATORY: Hive Issue Tracking
|
|
31065
31238
|
|
|
31066
|
-
**Every subtask MUST become a
|
|
31239
|
+
**Every subtask MUST become a cell.** This is non-negotiable.
|
|
31067
31240
|
|
|
31068
31241
|
After decomposition, the coordinator will:
|
|
31069
|
-
1. Create an epic
|
|
31070
|
-
2. Create child
|
|
31071
|
-
3. Track progress through
|
|
31072
|
-
4. Close
|
|
31242
|
+
1. Create an epic cell for the overall task
|
|
31243
|
+
2. Create child cells for each subtask
|
|
31244
|
+
3. Track progress through cell status updates
|
|
31245
|
+
4. Close cells with summaries when complete
|
|
31073
31246
|
|
|
31074
|
-
Agents MUST update their
|
|
31247
|
+
Agents MUST update their cell status as they work. No silent progress.
|
|
31075
31248
|
|
|
31076
31249
|
## Requirements
|
|
31077
31250
|
|
|
@@ -31089,7 +31262,7 @@ Respond with a JSON object matching this schema:
|
|
|
31089
31262
|
\`\`\`typescript
|
|
31090
31263
|
{
|
|
31091
31264
|
epic: {
|
|
31092
|
-
title: string, // Epic title for the
|
|
31265
|
+
title: string, // Epic title for the hive tracker
|
|
31093
31266
|
description?: string // Brief description of the overall goal
|
|
31094
31267
|
},
|
|
31095
31268
|
subtasks: [
|
|
@@ -31110,7 +31283,7 @@ var SUBTASK_PROMPT = `You are a swarm agent working on a subtask of a larger epi
|
|
|
31110
31283
|
|
|
31111
31284
|
## Your Identity
|
|
31112
31285
|
- **Agent Name**: {agent_name}
|
|
31113
|
-
- **
|
|
31286
|
+
- **Cell ID**: {bead_id}
|
|
31114
31287
|
- **Epic ID**: {epic_id}
|
|
31115
31288
|
|
|
31116
31289
|
## Your Subtask
|
|
@@ -31128,16 +31301,16 @@ send a message to the coordinator requesting the change.
|
|
|
31128
31301
|
## Shared Context
|
|
31129
31302
|
{shared_context}
|
|
31130
31303
|
|
|
31131
|
-
## MANDATORY:
|
|
31304
|
+
## MANDATORY: Hive Tracking
|
|
31132
31305
|
|
|
31133
|
-
You MUST keep your
|
|
31306
|
+
You MUST keep your cell updated as you work:
|
|
31134
31307
|
|
|
31135
|
-
1. **Your
|
|
31136
|
-
2. **If blocked**: \`
|
|
31137
|
-
3. **When done**: Use \`swarm_complete\` - it closes your
|
|
31138
|
-
4. **Discovered issues**: Create new
|
|
31308
|
+
1. **Your cell is already in_progress** - don't change this unless blocked
|
|
31309
|
+
2. **If blocked**: \`hive_update {bead_id} --status blocked\` and message coordinator
|
|
31310
|
+
3. **When done**: Use \`swarm_complete\` - it closes your cell automatically
|
|
31311
|
+
4. **Discovered issues**: Create new cells with \`hive_create "issue" -t bug\`
|
|
31139
31312
|
|
|
31140
|
-
**Never work silently.** Your
|
|
31313
|
+
**Never work silently.** Your cell status is how the swarm tracks progress.
|
|
31141
31314
|
|
|
31142
31315
|
## MANDATORY: Swarm Mail Communication
|
|
31143
31316
|
|
|
@@ -31160,11 +31333,11 @@ swarmmail_send(
|
|
|
31160
31333
|
|
|
31161
31334
|
## Coordination Protocol
|
|
31162
31335
|
|
|
31163
|
-
1. **Start**: Your
|
|
31336
|
+
1. **Start**: Your cell is already marked in_progress
|
|
31164
31337
|
2. **Progress**: Use swarm_progress to report status updates
|
|
31165
31338
|
3. **Blocked**: Report immediately via Swarm Mail - don't spin
|
|
31166
31339
|
4. **Complete**: Use swarm_complete when done - it handles:
|
|
31167
|
-
- Closing your
|
|
31340
|
+
- Closing your cell with a summary
|
|
31168
31341
|
- Releasing file reservations
|
|
31169
31342
|
- Notifying the coordinator
|
|
31170
31343
|
|
|
@@ -31191,7 +31364,7 @@ var SUBTASK_PROMPT_V2 = `You are a swarm agent working on: **{subtask_title}**
|
|
|
31191
31364
|
|
|
31192
31365
|
## [IDENTITY]
|
|
31193
31366
|
Agent: (assigned at spawn)
|
|
31194
|
-
|
|
31367
|
+
Cell: {bead_id}
|
|
31195
31368
|
Epic: {epic_id}
|
|
31196
31369
|
|
|
31197
31370
|
## [TASK]
|
|
@@ -31335,7 +31508,7 @@ swarm_complete(
|
|
|
31335
31508
|
- Records learning signals
|
|
31336
31509
|
- Notifies coordinator
|
|
31337
31510
|
|
|
31338
|
-
**DO NOT manually close the
|
|
31511
|
+
**DO NOT manually close the cell with hive_close.** Use swarm_complete.
|
|
31339
31512
|
|
|
31340
31513
|
## [SWARM MAIL COMMUNICATION]
|
|
31341
31514
|
|
|
@@ -31354,7 +31527,7 @@ swarmmail_send(
|
|
|
31354
31527
|
importance="high",
|
|
31355
31528
|
thread_id="{epic_id}"
|
|
31356
31529
|
)
|
|
31357
|
-
|
|
31530
|
+
hive_update(id="{bead_id}", status="blocked")
|
|
31358
31531
|
\`\`\`
|
|
31359
31532
|
|
|
31360
31533
|
### Report Issues to Other Agents
|
|
@@ -31375,15 +31548,15 @@ swarmmail_release() # Manually release reservations
|
|
|
31375
31548
|
**Note:** \`swarm_complete\` automatically releases reservations. Only use manual release if aborting work.
|
|
31376
31549
|
|
|
31377
31550
|
## [OTHER TOOLS]
|
|
31378
|
-
###
|
|
31379
|
-
You can create new
|
|
31551
|
+
### Hive - You Have Autonomy to File Issues
|
|
31552
|
+
You can create new cells against this epic when you discover:
|
|
31380
31553
|
- **Bugs**: Found a bug while working? File it.
|
|
31381
31554
|
- **Tech debt**: Spotted something that needs cleanup? File it.
|
|
31382
31555
|
- **Follow-up work**: Task needs more work than scoped? File a follow-up.
|
|
31383
31556
|
- **Dependencies**: Need something from another agent? File and link it.
|
|
31384
31557
|
|
|
31385
31558
|
\`\`\`
|
|
31386
|
-
|
|
31559
|
+
hive_create(
|
|
31387
31560
|
title="<descriptive title>",
|
|
31388
31561
|
type="bug", # or "task", "chore"
|
|
31389
31562
|
priority=2,
|
|
@@ -31394,9 +31567,9 @@ beads_create(
|
|
|
31394
31567
|
|
|
31395
31568
|
**Don't silently ignore issues.** File them so they get tracked and addressed.
|
|
31396
31569
|
|
|
31397
|
-
Other
|
|
31398
|
-
-
|
|
31399
|
-
-
|
|
31570
|
+
Other cell operations:
|
|
31571
|
+
- hive_update(id, status) - Mark blocked if stuck
|
|
31572
|
+
- hive_query(status="open") - See what else needs work
|
|
31400
31573
|
|
|
31401
31574
|
### Skills
|
|
31402
31575
|
- skills_list() - Discover available skills
|
|
@@ -31410,7 +31583,7 @@ Other bead operations:
|
|
|
31410
31583
|
2. Step 2 (semantic-memory_find) MUST happen before starting work
|
|
31411
31584
|
3. Step 4 (swarmmail_reserve) - YOU reserve files, not coordinator
|
|
31412
31585
|
4. Step 6 (swarm_progress) - Report at milestones, don't work silently
|
|
31413
|
-
5. Step 9 (swarm_complete) - Use this to close, NOT
|
|
31586
|
+
5. Step 9 (swarm_complete) - Use this to close, NOT hive_close
|
|
31414
31587
|
|
|
31415
31588
|
**If you skip these steps:**
|
|
31416
31589
|
- Your work won't be tracked (swarm_complete will fail)
|
|
@@ -31423,7 +31596,7 @@ Begin now.`;
|
|
|
31423
31596
|
var EVALUATION_PROMPT = `Evaluate the work completed for this subtask.
|
|
31424
31597
|
|
|
31425
31598
|
## Subtask
|
|
31426
|
-
**
|
|
31599
|
+
**Cell ID**: {bead_id}
|
|
31427
31600
|
**Title**: {subtask_title}
|
|
31428
31601
|
|
|
31429
31602
|
## Files Modified
|
|
@@ -31525,7 +31698,7 @@ var swarm_subtask_prompt = tool({
|
|
|
31525
31698
|
}
|
|
31526
31699
|
});
|
|
31527
31700
|
var swarm_spawn_subtask = tool({
|
|
31528
|
-
description: "Prepare a subtask for spawning. Returns prompt with Agent Mail/
|
|
31701
|
+
description: "Prepare a subtask for spawning. Returns prompt with Agent Mail/hive tracking instructions. IMPORTANT: Pass project_path for swarmmail_init.",
|
|
31529
31702
|
args: {
|
|
31530
31703
|
bead_id: tool.schema.string().describe("Subtask bead ID"),
|
|
31531
31704
|
epic_id: tool.schema.string().describe("Parent epic bead ID"),
|
|
@@ -31650,7 +31823,7 @@ ${args.context}` : `## Additional Context
|
|
|
31650
31823
|
guidelines: STRATEGIES2[selectedStrategy].guidelines,
|
|
31651
31824
|
anti_patterns: STRATEGIES2[selectedStrategy].antiPatterns
|
|
31652
31825
|
},
|
|
31653
|
-
expected_schema: "
|
|
31826
|
+
expected_schema: "CellTree",
|
|
31654
31827
|
schema_hint: {
|
|
31655
31828
|
epic: { title: "string", description: "string?" },
|
|
31656
31829
|
subtasks: [
|
|
@@ -31682,12 +31855,672 @@ init_learning();
|
|
|
31682
31855
|
import {
|
|
31683
31856
|
getSwarmInbox as getSwarmInbox2,
|
|
31684
31857
|
releaseSwarmFiles as releaseSwarmFiles2,
|
|
31685
|
-
sendSwarmMessage as
|
|
31858
|
+
sendSwarmMessage as sendSwarmMessage3,
|
|
31686
31859
|
getAgent,
|
|
31687
31860
|
createEvent as createEvent2,
|
|
31688
31861
|
appendEvent as appendEvent2
|
|
31689
31862
|
} from "swarm-mail";
|
|
31690
31863
|
init_skills();
|
|
31864
|
+
|
|
31865
|
+
// src/swarm-worktree.ts
|
|
31866
|
+
init_dist();
|
|
31867
|
+
init_zod();
|
|
31868
|
+
import { join as join6 } from "node:path";
|
|
31869
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
31870
|
+
var WORKTREE_DIR = ".swarm/worktrees";
|
|
31871
|
+
function getWorktreePath(projectPath, taskId) {
|
|
31872
|
+
const safeTaskId = taskId.replace(/[^a-zA-Z0-9.-]/g, "_");
|
|
31873
|
+
return join6(projectPath, WORKTREE_DIR, safeTaskId);
|
|
31874
|
+
}
|
|
31875
|
+
function parseTaskIdFromPath(worktreePath) {
|
|
31876
|
+
const parts = worktreePath.split("/");
|
|
31877
|
+
const worktreesIdx = parts.indexOf("worktrees");
|
|
31878
|
+
if (worktreesIdx >= 0 && worktreesIdx < parts.length - 1) {
|
|
31879
|
+
return parts[worktreesIdx + 1];
|
|
31880
|
+
}
|
|
31881
|
+
return null;
|
|
31882
|
+
}
|
|
31883
|
+
async function isGitRepo(path) {
|
|
31884
|
+
const result = await Bun.$`git -C ${path} rev-parse --git-dir`.quiet().nothrow();
|
|
31885
|
+
return result.exitCode === 0;
|
|
31886
|
+
}
|
|
31887
|
+
async function hasUncommittedChanges(path) {
|
|
31888
|
+
const result = await Bun.$`git -C ${path} status --porcelain`.quiet().nothrow();
|
|
31889
|
+
if (result.exitCode !== 0)
|
|
31890
|
+
return true;
|
|
31891
|
+
return result.stdout.toString().trim().length > 0;
|
|
31892
|
+
}
|
|
31893
|
+
async function getCurrentCommit(path) {
|
|
31894
|
+
const result = await Bun.$`git -C ${path} rev-parse HEAD`.quiet().nothrow();
|
|
31895
|
+
if (result.exitCode !== 0)
|
|
31896
|
+
return null;
|
|
31897
|
+
return result.stdout.toString().trim();
|
|
31898
|
+
}
|
|
31899
|
+
async function getWorktreeCommits(worktreePath, startCommit) {
|
|
31900
|
+
const result = await Bun.$`git -C ${worktreePath} log --format=%H ${startCommit}..HEAD`.quiet().nothrow();
|
|
31901
|
+
if (result.exitCode !== 0)
|
|
31902
|
+
return [];
|
|
31903
|
+
return result.stdout.toString().trim().split(`
|
|
31904
|
+
`).filter((c) => c.length > 0);
|
|
31905
|
+
}
|
|
31906
|
+
async function ensureWorktreeDir(projectPath) {
|
|
31907
|
+
const worktreeDir = join6(projectPath, WORKTREE_DIR);
|
|
31908
|
+
await Bun.$`mkdir -p ${worktreeDir}`.quiet().nothrow();
|
|
31909
|
+
}
|
|
31910
|
+
var swarm_worktree_create = tool({
|
|
31911
|
+
description: "Create a git worktree for isolated task execution. Worker operates in worktree, not main branch.",
|
|
31912
|
+
args: {
|
|
31913
|
+
project_path: exports_external.string().describe("Absolute path to project root"),
|
|
31914
|
+
task_id: exports_external.string().describe("Task/bead ID (e.g., bd-abc123.1)"),
|
|
31915
|
+
start_commit: exports_external.string().describe("Commit SHA to create worktree at (swarm start point)")
|
|
31916
|
+
},
|
|
31917
|
+
async execute(args) {
|
|
31918
|
+
if (!await isGitRepo(args.project_path)) {
|
|
31919
|
+
const result2 = {
|
|
31920
|
+
success: false,
|
|
31921
|
+
error: `${args.project_path} is not a git repository`
|
|
31922
|
+
};
|
|
31923
|
+
return JSON.stringify(result2, null, 2);
|
|
31924
|
+
}
|
|
31925
|
+
const worktreePath = getWorktreePath(args.project_path, args.task_id);
|
|
31926
|
+
const exists = existsSync5(worktreePath);
|
|
31927
|
+
if (exists) {
|
|
31928
|
+
const result2 = {
|
|
31929
|
+
success: false,
|
|
31930
|
+
error: `Worktree already exists for task ${args.task_id}`,
|
|
31931
|
+
worktree_path: worktreePath
|
|
31932
|
+
};
|
|
31933
|
+
return JSON.stringify(result2, null, 2);
|
|
31934
|
+
}
|
|
31935
|
+
await ensureWorktreeDir(args.project_path);
|
|
31936
|
+
const createResult = await Bun.$`git -C ${args.project_path} worktree add --detach ${worktreePath} ${args.start_commit}`.quiet().nothrow();
|
|
31937
|
+
if (createResult.exitCode !== 0) {
|
|
31938
|
+
const result2 = {
|
|
31939
|
+
success: false,
|
|
31940
|
+
error: `Failed to create worktree: ${createResult.stderr.toString()}`
|
|
31941
|
+
};
|
|
31942
|
+
return JSON.stringify(result2, null, 2);
|
|
31943
|
+
}
|
|
31944
|
+
const result = {
|
|
31945
|
+
success: true,
|
|
31946
|
+
worktree_path: worktreePath,
|
|
31947
|
+
task_id: args.task_id,
|
|
31948
|
+
created_at_commit: args.start_commit
|
|
31949
|
+
};
|
|
31950
|
+
return JSON.stringify(result, null, 2);
|
|
31951
|
+
}
|
|
31952
|
+
});
|
|
31953
|
+
var swarm_worktree_merge = tool({
|
|
31954
|
+
description: "Cherry-pick commits from worktree back to main branch. Call after worker completes.",
|
|
31955
|
+
args: {
|
|
31956
|
+
project_path: exports_external.string().describe("Absolute path to project root"),
|
|
31957
|
+
task_id: exports_external.string().describe("Task/bead ID"),
|
|
31958
|
+
start_commit: exports_external.string().optional().describe("Original start commit (to find new commits)")
|
|
31959
|
+
},
|
|
31960
|
+
async execute(args) {
|
|
31961
|
+
const worktreePath = getWorktreePath(args.project_path, args.task_id);
|
|
31962
|
+
const exists = existsSync5(worktreePath);
|
|
31963
|
+
if (!exists) {
|
|
31964
|
+
const result2 = {
|
|
31965
|
+
success: false,
|
|
31966
|
+
error: `Worktree not found for task ${args.task_id}`
|
|
31967
|
+
};
|
|
31968
|
+
return JSON.stringify(result2, null, 2);
|
|
31969
|
+
}
|
|
31970
|
+
let startCommit = args.start_commit;
|
|
31971
|
+
if (!startCommit) {
|
|
31972
|
+
const mergeBaseResult = await Bun.$`git -C ${args.project_path} merge-base HEAD ${worktreePath}`.quiet().nothrow();
|
|
31973
|
+
if (mergeBaseResult.exitCode === 0) {
|
|
31974
|
+
startCommit = mergeBaseResult.stdout.toString().trim();
|
|
31975
|
+
}
|
|
31976
|
+
}
|
|
31977
|
+
if (!startCommit) {
|
|
31978
|
+
const result2 = {
|
|
31979
|
+
success: false,
|
|
31980
|
+
error: "Could not determine start commit for cherry-pick"
|
|
31981
|
+
};
|
|
31982
|
+
return JSON.stringify(result2, null, 2);
|
|
31983
|
+
}
|
|
31984
|
+
const commits = await getWorktreeCommits(worktreePath, startCommit);
|
|
31985
|
+
if (commits.length === 0) {
|
|
31986
|
+
const result2 = {
|
|
31987
|
+
success: false,
|
|
31988
|
+
error: `Worktree has no commits since ${startCommit.slice(0, 7)}`
|
|
31989
|
+
};
|
|
31990
|
+
return JSON.stringify(result2, null, 2);
|
|
31991
|
+
}
|
|
31992
|
+
const reversedCommits = commits.reverse();
|
|
31993
|
+
let lastMergedCommit = null;
|
|
31994
|
+
for (const commit of reversedCommits) {
|
|
31995
|
+
const cherryResult = await Bun.$`git -C ${args.project_path} cherry-pick ${commit}`.quiet().nothrow();
|
|
31996
|
+
if (cherryResult.exitCode !== 0) {
|
|
31997
|
+
const stderr = cherryResult.stderr.toString();
|
|
31998
|
+
if (stderr.includes("conflict") || stderr.includes("CONFLICT")) {
|
|
31999
|
+
const statusResult = await Bun.$`git -C ${args.project_path} status --porcelain`.quiet().nothrow();
|
|
32000
|
+
const conflictingFiles = statusResult.stdout.toString().split(`
|
|
32001
|
+
`).filter((line) => line.startsWith("UU") || line.startsWith("AA")).map((line) => line.slice(3).trim());
|
|
32002
|
+
await Bun.$`git -C ${args.project_path} cherry-pick --abort`.quiet().nothrow();
|
|
32003
|
+
const result3 = {
|
|
32004
|
+
success: false,
|
|
32005
|
+
error: `Merge conflict during cherry-pick of ${commit.slice(0, 7)}`,
|
|
32006
|
+
conflicting_files: conflictingFiles
|
|
32007
|
+
};
|
|
32008
|
+
return JSON.stringify(result3, null, 2);
|
|
32009
|
+
}
|
|
32010
|
+
const result2 = {
|
|
32011
|
+
success: false,
|
|
32012
|
+
error: `Failed to cherry-pick ${commit.slice(0, 7)}: ${stderr}`
|
|
32013
|
+
};
|
|
32014
|
+
return JSON.stringify(result2, null, 2);
|
|
32015
|
+
}
|
|
32016
|
+
lastMergedCommit = commit;
|
|
32017
|
+
}
|
|
32018
|
+
const result = {
|
|
32019
|
+
success: true,
|
|
32020
|
+
task_id: args.task_id,
|
|
32021
|
+
merged_commit: lastMergedCommit || undefined
|
|
32022
|
+
};
|
|
32023
|
+
return JSON.stringify(result, null, 2);
|
|
32024
|
+
}
|
|
32025
|
+
});
|
|
32026
|
+
var swarm_worktree_cleanup = tool({
|
|
32027
|
+
description: "Remove a worktree after completion or abort. Idempotent - safe to call multiple times.",
|
|
32028
|
+
args: {
|
|
32029
|
+
project_path: exports_external.string().describe("Absolute path to project root"),
|
|
32030
|
+
task_id: exports_external.string().optional().describe("Task/bead ID to clean up"),
|
|
32031
|
+
cleanup_all: exports_external.boolean().optional().describe("Remove all worktrees for this project")
|
|
32032
|
+
},
|
|
32033
|
+
async execute(args) {
|
|
32034
|
+
if (args.cleanup_all) {
|
|
32035
|
+
const listResult = await Bun.$`git -C ${args.project_path} worktree list --porcelain`.quiet().nothrow();
|
|
32036
|
+
if (listResult.exitCode !== 0) {
|
|
32037
|
+
const result3 = {
|
|
32038
|
+
success: false,
|
|
32039
|
+
error: `Failed to list worktrees: ${listResult.stderr.toString()}`
|
|
32040
|
+
};
|
|
32041
|
+
return JSON.stringify(result3, null, 2);
|
|
32042
|
+
}
|
|
32043
|
+
const output = listResult.stdout.toString();
|
|
32044
|
+
const worktreeDir = join6(args.project_path, WORKTREE_DIR);
|
|
32045
|
+
const worktrees = output.split(`
|
|
32046
|
+
|
|
32047
|
+
`).filter((block) => block.includes(worktreeDir)).map((block) => {
|
|
32048
|
+
const pathMatch = block.match(/^worktree (.+)$/m);
|
|
32049
|
+
return pathMatch ? pathMatch[1] : null;
|
|
32050
|
+
}).filter((p) => p !== null);
|
|
32051
|
+
let removedCount = 0;
|
|
32052
|
+
for (const wt of worktrees) {
|
|
32053
|
+
const removeResult2 = await Bun.$`git -C ${args.project_path} worktree remove --force ${wt}`.quiet().nothrow();
|
|
32054
|
+
if (removeResult2.exitCode === 0) {
|
|
32055
|
+
removedCount++;
|
|
32056
|
+
}
|
|
32057
|
+
}
|
|
32058
|
+
const result2 = {
|
|
32059
|
+
success: true,
|
|
32060
|
+
removed_count: removedCount
|
|
32061
|
+
};
|
|
32062
|
+
return JSON.stringify(result2, null, 2);
|
|
32063
|
+
}
|
|
32064
|
+
if (!args.task_id) {
|
|
32065
|
+
const result2 = {
|
|
32066
|
+
success: false,
|
|
32067
|
+
error: "Either task_id or cleanup_all must be provided"
|
|
32068
|
+
};
|
|
32069
|
+
return JSON.stringify(result2, null, 2);
|
|
32070
|
+
}
|
|
32071
|
+
const worktreePath = getWorktreePath(args.project_path, args.task_id);
|
|
32072
|
+
const exists = existsSync5(worktreePath);
|
|
32073
|
+
if (!exists) {
|
|
32074
|
+
const result2 = {
|
|
32075
|
+
success: true,
|
|
32076
|
+
already_removed: true,
|
|
32077
|
+
removed_path: worktreePath
|
|
32078
|
+
};
|
|
32079
|
+
return JSON.stringify(result2, null, 2);
|
|
32080
|
+
}
|
|
32081
|
+
const removeResult = await Bun.$`git -C ${args.project_path} worktree remove --force ${worktreePath}`.quiet().nothrow();
|
|
32082
|
+
if (removeResult.exitCode !== 0) {
|
|
32083
|
+
await Bun.$`rm -rf ${worktreePath}`.quiet().nothrow();
|
|
32084
|
+
await Bun.$`git -C ${args.project_path} worktree prune`.quiet().nothrow();
|
|
32085
|
+
}
|
|
32086
|
+
const result = {
|
|
32087
|
+
success: true,
|
|
32088
|
+
removed_path: worktreePath,
|
|
32089
|
+
task_id: args.task_id
|
|
32090
|
+
};
|
|
32091
|
+
return JSON.stringify(result, null, 2);
|
|
32092
|
+
}
|
|
32093
|
+
});
|
|
32094
|
+
var swarm_worktree_list = tool({
|
|
32095
|
+
description: "List all active worktrees for a project",
|
|
32096
|
+
args: {
|
|
32097
|
+
project_path: exports_external.string().describe("Absolute path to project root")
|
|
32098
|
+
},
|
|
32099
|
+
async execute(args) {
|
|
32100
|
+
const listResult = await Bun.$`git -C ${args.project_path} worktree list --porcelain`.quiet().nothrow();
|
|
32101
|
+
if (listResult.exitCode !== 0) {
|
|
32102
|
+
return JSON.stringify({
|
|
32103
|
+
worktrees: [],
|
|
32104
|
+
count: 0,
|
|
32105
|
+
error: `Failed to list worktrees: ${listResult.stderr.toString()}`
|
|
32106
|
+
}, null, 2);
|
|
32107
|
+
}
|
|
32108
|
+
const output = listResult.stdout.toString();
|
|
32109
|
+
const worktreeDir = join6(args.project_path, WORKTREE_DIR);
|
|
32110
|
+
const worktrees = [];
|
|
32111
|
+
const blocks = output.split(`
|
|
32112
|
+
|
|
32113
|
+
`).filter((b) => b.trim());
|
|
32114
|
+
for (const block of blocks) {
|
|
32115
|
+
const pathMatch = block.match(/^worktree (.+)$/m);
|
|
32116
|
+
const commitMatch = block.match(/^HEAD ([a-f0-9]+)$/m);
|
|
32117
|
+
const branchMatch = block.match(/^branch (.+)$/m);
|
|
32118
|
+
if (pathMatch && pathMatch[1].includes(worktreeDir)) {
|
|
32119
|
+
const path = pathMatch[1];
|
|
32120
|
+
const taskId = parseTaskIdFromPath(path);
|
|
32121
|
+
if (taskId) {
|
|
32122
|
+
worktrees.push({
|
|
32123
|
+
task_id: taskId,
|
|
32124
|
+
path,
|
|
32125
|
+
commit: commitMatch ? commitMatch[1] : "unknown",
|
|
32126
|
+
branch: branchMatch ? branchMatch[1] : undefined
|
|
32127
|
+
});
|
|
32128
|
+
}
|
|
32129
|
+
}
|
|
32130
|
+
}
|
|
32131
|
+
return JSON.stringify({
|
|
32132
|
+
worktrees,
|
|
32133
|
+
count: worktrees.length
|
|
32134
|
+
}, null, 2);
|
|
32135
|
+
}
|
|
32136
|
+
});
|
|
32137
|
+
async function canUseWorktreeIsolation(projectPath) {
|
|
32138
|
+
if (!await isGitRepo(projectPath)) {
|
|
32139
|
+
return { canUse: false, reason: "Not a git repository" };
|
|
32140
|
+
}
|
|
32141
|
+
if (await hasUncommittedChanges(projectPath)) {
|
|
32142
|
+
return {
|
|
32143
|
+
canUse: false,
|
|
32144
|
+
reason: "Uncommitted changes exist - commit or stash first"
|
|
32145
|
+
};
|
|
32146
|
+
}
|
|
32147
|
+
return { canUse: true };
|
|
32148
|
+
}
|
|
32149
|
+
async function getStartCommit(projectPath) {
|
|
32150
|
+
return getCurrentCommit(projectPath);
|
|
32151
|
+
}
|
|
32152
|
+
var worktreeTools = {
|
|
32153
|
+
swarm_worktree_create,
|
|
32154
|
+
swarm_worktree_merge,
|
|
32155
|
+
swarm_worktree_cleanup,
|
|
32156
|
+
swarm_worktree_list
|
|
32157
|
+
};
|
|
32158
|
+
|
|
32159
|
+
// src/swarm-review.ts
|
|
32160
|
+
init_dist();
|
|
32161
|
+
init_zod();
|
|
32162
|
+
import { sendSwarmMessage as sendSwarmMessage2 } from "swarm-mail";
|
|
32163
|
+
var ReviewIssueSchema = exports_external.object({
|
|
32164
|
+
file: exports_external.string(),
|
|
32165
|
+
line: exports_external.number().optional(),
|
|
32166
|
+
issue: exports_external.string(),
|
|
32167
|
+
suggestion: exports_external.string().optional()
|
|
32168
|
+
});
|
|
32169
|
+
var ReviewResultSchema = exports_external.object({
|
|
32170
|
+
status: exports_external.enum(["approved", "needs_changes"]),
|
|
32171
|
+
summary: exports_external.string().optional(),
|
|
32172
|
+
issues: exports_external.array(ReviewIssueSchema).optional(),
|
|
32173
|
+
remaining_attempts: exports_external.number().optional()
|
|
32174
|
+
}).refine((data) => {
|
|
32175
|
+
if (data.status === "needs_changes") {
|
|
32176
|
+
return data.issues && data.issues.length > 0;
|
|
32177
|
+
}
|
|
32178
|
+
return true;
|
|
32179
|
+
}, {
|
|
32180
|
+
message: "issues array is required when status is 'needs_changes'"
|
|
32181
|
+
});
|
|
32182
|
+
var reviewAttempts = new Map;
|
|
32183
|
+
var MAX_REVIEW_ATTEMPTS = 3;
|
|
32184
|
+
function getAttemptCount(taskId) {
|
|
32185
|
+
return reviewAttempts.get(taskId) || 0;
|
|
32186
|
+
}
|
|
32187
|
+
function incrementAttempt(taskId) {
|
|
32188
|
+
const current = getAttemptCount(taskId);
|
|
32189
|
+
const newCount = current + 1;
|
|
32190
|
+
reviewAttempts.set(taskId, newCount);
|
|
32191
|
+
return newCount;
|
|
32192
|
+
}
|
|
32193
|
+
function clearAttempts(taskId) {
|
|
32194
|
+
reviewAttempts.delete(taskId);
|
|
32195
|
+
}
|
|
32196
|
+
function getRemainingAttempts(taskId) {
|
|
32197
|
+
return MAX_REVIEW_ATTEMPTS - getAttemptCount(taskId);
|
|
32198
|
+
}
|
|
32199
|
+
function generateReviewPrompt(context) {
|
|
32200
|
+
const sections = [];
|
|
32201
|
+
sections.push(`# Code Review: ${context.task_title}`);
|
|
32202
|
+
sections.push("");
|
|
32203
|
+
sections.push("## Epic Goal");
|
|
32204
|
+
sections.push(`**${context.epic_title}**`);
|
|
32205
|
+
if (context.epic_description) {
|
|
32206
|
+
sections.push(context.epic_description);
|
|
32207
|
+
}
|
|
32208
|
+
sections.push("");
|
|
32209
|
+
sections.push("## Task Requirements");
|
|
32210
|
+
sections.push(`**${context.task_title}**`);
|
|
32211
|
+
if (context.task_description) {
|
|
32212
|
+
sections.push(context.task_description);
|
|
32213
|
+
}
|
|
32214
|
+
sections.push("");
|
|
32215
|
+
if (context.completed_dependencies && context.completed_dependencies.length > 0) {
|
|
32216
|
+
sections.push("## This Task Builds On");
|
|
32217
|
+
for (const dep of context.completed_dependencies) {
|
|
32218
|
+
sections.push(`- **${dep.title}** (${dep.id})`);
|
|
32219
|
+
if (dep.summary) {
|
|
32220
|
+
sections.push(` ${dep.summary}`);
|
|
32221
|
+
}
|
|
32222
|
+
}
|
|
32223
|
+
sections.push("");
|
|
32224
|
+
}
|
|
32225
|
+
if (context.downstream_tasks && context.downstream_tasks.length > 0) {
|
|
32226
|
+
sections.push("## Downstream Tasks (depend on this)");
|
|
32227
|
+
for (const task of context.downstream_tasks) {
|
|
32228
|
+
sections.push(`- **${task.title}** (${task.id})`);
|
|
32229
|
+
}
|
|
32230
|
+
sections.push("");
|
|
32231
|
+
}
|
|
32232
|
+
sections.push("## Files Modified");
|
|
32233
|
+
for (const file2 of context.files_touched) {
|
|
32234
|
+
sections.push(`- \`${file2}\``);
|
|
32235
|
+
}
|
|
32236
|
+
sections.push("");
|
|
32237
|
+
sections.push("## Code Changes");
|
|
32238
|
+
sections.push("```diff");
|
|
32239
|
+
sections.push(context.diff);
|
|
32240
|
+
sections.push("```");
|
|
32241
|
+
sections.push("");
|
|
32242
|
+
sections.push("## Review Criteria");
|
|
32243
|
+
sections.push("");
|
|
32244
|
+
sections.push("Please evaluate the changes against these criteria:");
|
|
32245
|
+
sections.push("");
|
|
32246
|
+
sections.push("1. **Fulfills Requirements**: Does the code implement what the task requires?");
|
|
32247
|
+
sections.push("2. **Serves Epic Goal**: Does this work contribute to the overall epic objective?");
|
|
32248
|
+
sections.push("3. **Enables Downstream**: Can downstream tasks use this work as expected?");
|
|
32249
|
+
sections.push("4. **Type Safety**: Are types correct and complete?");
|
|
32250
|
+
sections.push("5. **No Critical Bugs**: Are there any obvious bugs or issues?");
|
|
32251
|
+
sections.push("6. **Test Coverage**: Are there tests for the new code? (warning only)");
|
|
32252
|
+
sections.push("");
|
|
32253
|
+
sections.push("## Response Format");
|
|
32254
|
+
sections.push("");
|
|
32255
|
+
sections.push("Respond with a JSON object:");
|
|
32256
|
+
sections.push("```json");
|
|
32257
|
+
sections.push(`{
|
|
32258
|
+
"status": "approved" | "needs_changes",
|
|
32259
|
+
"summary": "Brief summary of your review",
|
|
32260
|
+
"issues": [
|
|
32261
|
+
{
|
|
32262
|
+
"file": "path/to/file.ts",
|
|
32263
|
+
"line": 42,
|
|
32264
|
+
"issue": "Description of the problem",
|
|
32265
|
+
"suggestion": "How to fix it"
|
|
32266
|
+
}
|
|
32267
|
+
]
|
|
32268
|
+
}`);
|
|
32269
|
+
sections.push("```");
|
|
32270
|
+
return sections.join(`
|
|
32271
|
+
`);
|
|
32272
|
+
}
|
|
32273
|
+
async function getHiveAdapterSafe(projectPath) {
|
|
32274
|
+
try {
|
|
32275
|
+
return getHiveAdapter(projectPath);
|
|
32276
|
+
} catch {
|
|
32277
|
+
return null;
|
|
32278
|
+
}
|
|
32279
|
+
}
|
|
32280
|
+
async function getCellDependencies(adapter, projectKey, _cellId, epicId) {
|
|
32281
|
+
const completedDependencies = [];
|
|
32282
|
+
const downstreamTasks = [];
|
|
32283
|
+
try {
|
|
32284
|
+
const subtasks = await adapter.queryCells(projectKey, { parent_id: epicId });
|
|
32285
|
+
for (const subtask of subtasks) {
|
|
32286
|
+
if (subtask.id === _cellId)
|
|
32287
|
+
continue;
|
|
32288
|
+
if (subtask.status === "closed") {
|
|
32289
|
+
completedDependencies.push({
|
|
32290
|
+
id: subtask.id,
|
|
32291
|
+
title: subtask.title,
|
|
32292
|
+
summary: subtask.closed_reason ?? undefined
|
|
32293
|
+
});
|
|
32294
|
+
}
|
|
32295
|
+
if (subtask.status !== "closed") {
|
|
32296
|
+
downstreamTasks.push({
|
|
32297
|
+
id: subtask.id,
|
|
32298
|
+
title: subtask.title
|
|
32299
|
+
});
|
|
32300
|
+
}
|
|
32301
|
+
}
|
|
32302
|
+
} catch {}
|
|
32303
|
+
return { completed: completedDependencies, downstream: downstreamTasks };
|
|
32304
|
+
}
|
|
32305
|
+
var swarm_review = tool({
|
|
32306
|
+
description: "Generate a review prompt for a completed subtask. Includes epic context, dependencies, and diff.",
|
|
32307
|
+
args: {
|
|
32308
|
+
project_key: exports_external.string().describe("Project path"),
|
|
32309
|
+
epic_id: exports_external.string().describe("Epic cell ID"),
|
|
32310
|
+
task_id: exports_external.string().describe("Subtask cell ID to review"),
|
|
32311
|
+
files_touched: exports_external.array(exports_external.string()).optional().describe("Files modified (will get diff for these)")
|
|
32312
|
+
},
|
|
32313
|
+
async execute(args) {
|
|
32314
|
+
let epicTitle = args.epic_id;
|
|
32315
|
+
let epicDescription;
|
|
32316
|
+
let taskTitle = args.task_id;
|
|
32317
|
+
let taskDescription;
|
|
32318
|
+
let completedDependencies = [];
|
|
32319
|
+
let downstreamTasks = [];
|
|
32320
|
+
const adapter = await getHiveAdapterSafe(args.project_key);
|
|
32321
|
+
if (adapter) {
|
|
32322
|
+
try {
|
|
32323
|
+
const epic = await adapter.getCell(args.project_key, args.epic_id);
|
|
32324
|
+
if (epic) {
|
|
32325
|
+
epicTitle = epic.title || epicTitle;
|
|
32326
|
+
epicDescription = epic.description ?? undefined;
|
|
32327
|
+
}
|
|
32328
|
+
const task = await adapter.getCell(args.project_key, args.task_id);
|
|
32329
|
+
if (task) {
|
|
32330
|
+
taskTitle = task.title || taskTitle;
|
|
32331
|
+
taskDescription = task.description ?? undefined;
|
|
32332
|
+
}
|
|
32333
|
+
const deps = await getCellDependencies(adapter, args.project_key, args.task_id, args.epic_id);
|
|
32334
|
+
completedDependencies = deps.completed;
|
|
32335
|
+
downstreamTasks = deps.downstream;
|
|
32336
|
+
} catch {}
|
|
32337
|
+
}
|
|
32338
|
+
let diff = "";
|
|
32339
|
+
if (args.files_touched && args.files_touched.length > 0) {
|
|
32340
|
+
try {
|
|
32341
|
+
const diffResult = await Bun.$`git diff HEAD~1 -- ${args.files_touched}`.cwd(args.project_key).quiet().nothrow();
|
|
32342
|
+
if (diffResult.exitCode === 0) {
|
|
32343
|
+
diff = diffResult.stdout.toString();
|
|
32344
|
+
} else {
|
|
32345
|
+
const stagedResult = await Bun.$`git diff --cached -- ${args.files_touched}`.cwd(args.project_key).quiet().nothrow();
|
|
32346
|
+
diff = stagedResult.stdout.toString();
|
|
32347
|
+
}
|
|
32348
|
+
} catch {}
|
|
32349
|
+
}
|
|
32350
|
+
const reviewPrompt = generateReviewPrompt({
|
|
32351
|
+
epic_id: args.epic_id,
|
|
32352
|
+
epic_title: epicTitle,
|
|
32353
|
+
epic_description: epicDescription,
|
|
32354
|
+
task_id: args.task_id,
|
|
32355
|
+
task_title: taskTitle,
|
|
32356
|
+
task_description: taskDescription,
|
|
32357
|
+
files_touched: args.files_touched || [],
|
|
32358
|
+
diff: diff || "(no diff available)",
|
|
32359
|
+
completed_dependencies: completedDependencies.length > 0 ? completedDependencies : undefined,
|
|
32360
|
+
downstream_tasks: downstreamTasks.length > 0 ? downstreamTasks : undefined
|
|
32361
|
+
});
|
|
32362
|
+
return JSON.stringify({
|
|
32363
|
+
review_prompt: reviewPrompt,
|
|
32364
|
+
context: {
|
|
32365
|
+
epic_id: args.epic_id,
|
|
32366
|
+
epic_title: epicTitle,
|
|
32367
|
+
task_id: args.task_id,
|
|
32368
|
+
task_title: taskTitle,
|
|
32369
|
+
files_touched: args.files_touched || [],
|
|
32370
|
+
completed_dependencies: completedDependencies.length,
|
|
32371
|
+
downstream_tasks: downstreamTasks.length,
|
|
32372
|
+
remaining_attempts: getRemainingAttempts(args.task_id)
|
|
32373
|
+
}
|
|
32374
|
+
}, null, 2);
|
|
32375
|
+
}
|
|
32376
|
+
});
|
|
32377
|
+
var swarm_review_feedback = tool({
|
|
32378
|
+
description: "Send review feedback to a worker. Tracks attempts (max 3). Fails task after 3 rejections.",
|
|
32379
|
+
args: {
|
|
32380
|
+
project_key: exports_external.string().describe("Project path"),
|
|
32381
|
+
task_id: exports_external.string().describe("Subtask cell ID"),
|
|
32382
|
+
worker_id: exports_external.string().describe("Worker agent name"),
|
|
32383
|
+
status: exports_external.enum(["approved", "needs_changes"]).describe("Review status"),
|
|
32384
|
+
summary: exports_external.string().optional().describe("Review summary"),
|
|
32385
|
+
issues: exports_external.string().optional().describe("JSON array of ReviewIssue objects (for needs_changes)")
|
|
32386
|
+
},
|
|
32387
|
+
async execute(args) {
|
|
32388
|
+
let parsedIssues = [];
|
|
32389
|
+
if (args.issues) {
|
|
32390
|
+
try {
|
|
32391
|
+
parsedIssues = JSON.parse(args.issues);
|
|
32392
|
+
} catch {
|
|
32393
|
+
return JSON.stringify({
|
|
32394
|
+
success: false,
|
|
32395
|
+
error: "Failed to parse issues JSON"
|
|
32396
|
+
}, null, 2);
|
|
32397
|
+
}
|
|
32398
|
+
}
|
|
32399
|
+
if (args.status === "needs_changes" && parsedIssues.length === 0) {
|
|
32400
|
+
return JSON.stringify({
|
|
32401
|
+
success: false,
|
|
32402
|
+
error: "needs_changes status requires at least one issue"
|
|
32403
|
+
}, null, 2);
|
|
32404
|
+
}
|
|
32405
|
+
const epicId = args.task_id.includes(".") ? args.task_id.split(".")[0] : args.task_id;
|
|
32406
|
+
if (args.status === "approved") {
|
|
32407
|
+
markReviewApproved(args.task_id);
|
|
32408
|
+
await sendSwarmMessage2({
|
|
32409
|
+
projectPath: args.project_key,
|
|
32410
|
+
fromAgent: "coordinator",
|
|
32411
|
+
toAgents: [args.worker_id],
|
|
32412
|
+
subject: `APPROVED: ${args.task_id}`,
|
|
32413
|
+
body: `## Review Approved ✓
|
|
32414
|
+
|
|
32415
|
+
${args.summary || "Your work has been approved."}
|
|
32416
|
+
|
|
32417
|
+
You may now complete the task with \`swarm_complete\`.`,
|
|
32418
|
+
threadId: epicId,
|
|
32419
|
+
importance: "normal"
|
|
32420
|
+
});
|
|
32421
|
+
return JSON.stringify({
|
|
32422
|
+
success: true,
|
|
32423
|
+
status: "approved",
|
|
32424
|
+
task_id: args.task_id,
|
|
32425
|
+
message: "Review approved. Worker can now complete the task."
|
|
32426
|
+
}, null, 2);
|
|
32427
|
+
}
|
|
32428
|
+
const attemptNumber = incrementAttempt(args.task_id);
|
|
32429
|
+
const remaining = MAX_REVIEW_ATTEMPTS - attemptNumber;
|
|
32430
|
+
if (remaining <= 0) {
|
|
32431
|
+
const adapter = await getHiveAdapterSafe(args.project_key);
|
|
32432
|
+
if (adapter) {
|
|
32433
|
+
try {
|
|
32434
|
+
await adapter.changeCellStatus(args.project_key, args.task_id, "blocked");
|
|
32435
|
+
} catch {}
|
|
32436
|
+
}
|
|
32437
|
+
await sendSwarmMessage2({
|
|
32438
|
+
projectPath: args.project_key,
|
|
32439
|
+
fromAgent: "coordinator",
|
|
32440
|
+
toAgents: [args.worker_id],
|
|
32441
|
+
subject: `FAILED: ${args.task_id} - max review attempts reached`,
|
|
32442
|
+
body: `## Task Failed ✗
|
|
32443
|
+
|
|
32444
|
+
Maximum review attempts (${MAX_REVIEW_ATTEMPTS}) reached.
|
|
32445
|
+
|
|
32446
|
+
**Last Issues:**
|
|
32447
|
+
${parsedIssues.map((i) => `- ${i.file}${i.line ? `:${i.line}` : ""}: ${i.issue}`).join(`
|
|
32448
|
+
`)}
|
|
32449
|
+
|
|
32450
|
+
The task has been marked as blocked. A human or different approach is needed.`,
|
|
32451
|
+
threadId: epicId,
|
|
32452
|
+
importance: "urgent"
|
|
32453
|
+
});
|
|
32454
|
+
return JSON.stringify({
|
|
32455
|
+
success: true,
|
|
32456
|
+
status: "needs_changes",
|
|
32457
|
+
task_failed: true,
|
|
32458
|
+
task_id: args.task_id,
|
|
32459
|
+
attempt: attemptNumber,
|
|
32460
|
+
remaining_attempts: 0,
|
|
32461
|
+
message: `Task failed after ${MAX_REVIEW_ATTEMPTS} review attempts`
|
|
32462
|
+
}, null, 2);
|
|
32463
|
+
}
|
|
32464
|
+
const issuesList = parsedIssues.map((i) => {
|
|
32465
|
+
let line = `- **${i.file}**`;
|
|
32466
|
+
if (i.line)
|
|
32467
|
+
line += `:${i.line}`;
|
|
32468
|
+
line += `: ${i.issue}`;
|
|
32469
|
+
if (i.suggestion)
|
|
32470
|
+
line += `
|
|
32471
|
+
→ ${i.suggestion}`;
|
|
32472
|
+
return line;
|
|
32473
|
+
}).join(`
|
|
32474
|
+
`);
|
|
32475
|
+
await sendSwarmMessage2({
|
|
32476
|
+
projectPath: args.project_key,
|
|
32477
|
+
fromAgent: "coordinator",
|
|
32478
|
+
toAgents: [args.worker_id],
|
|
32479
|
+
subject: `NEEDS CHANGES: ${args.task_id} (attempt ${attemptNumber}/${MAX_REVIEW_ATTEMPTS})`,
|
|
32480
|
+
body: `## Review: Changes Needed
|
|
32481
|
+
|
|
32482
|
+
${args.summary || "Please address the following issues:"}
|
|
32483
|
+
|
|
32484
|
+
**Issues:**
|
|
32485
|
+
${issuesList}
|
|
32486
|
+
|
|
32487
|
+
**Remaining attempts:** ${remaining}
|
|
32488
|
+
|
|
32489
|
+
Please fix these issues and request another review.`,
|
|
32490
|
+
threadId: epicId,
|
|
32491
|
+
importance: "high"
|
|
32492
|
+
});
|
|
32493
|
+
return JSON.stringify({
|
|
32494
|
+
success: true,
|
|
32495
|
+
status: "needs_changes",
|
|
32496
|
+
task_id: args.task_id,
|
|
32497
|
+
attempt: attemptNumber,
|
|
32498
|
+
remaining_attempts: remaining,
|
|
32499
|
+
issues: parsedIssues,
|
|
32500
|
+
message: `Feedback sent. ${remaining} attempt(s) remaining.`
|
|
32501
|
+
}, null, 2);
|
|
32502
|
+
}
|
|
32503
|
+
});
|
|
32504
|
+
var reviewStatus = new Map;
|
|
32505
|
+
function markReviewApproved(taskId) {
|
|
32506
|
+
reviewStatus.set(taskId, { approved: true, timestamp: Date.now() });
|
|
32507
|
+
clearAttempts(taskId);
|
|
32508
|
+
}
|
|
32509
|
+
function getReviewStatus(taskId) {
|
|
32510
|
+
const status = reviewStatus.get(taskId);
|
|
32511
|
+
return {
|
|
32512
|
+
reviewed: status !== undefined,
|
|
32513
|
+
approved: status?.approved ?? false,
|
|
32514
|
+
attempt_count: getAttemptCount(taskId),
|
|
32515
|
+
remaining_attempts: getRemainingAttempts(taskId)
|
|
32516
|
+
};
|
|
32517
|
+
}
|
|
32518
|
+
var reviewTools = {
|
|
32519
|
+
swarm_review,
|
|
32520
|
+
swarm_review_feedback
|
|
32521
|
+
};
|
|
32522
|
+
|
|
32523
|
+
// src/swarm-orchestrate.ts
|
|
31691
32524
|
async function queryEpicSubtasks(epicId) {
|
|
31692
32525
|
const beadsAvailable = await isToolAvailable("beads");
|
|
31693
32526
|
if (!beadsAvailable) {
|
|
@@ -31957,7 +32790,8 @@ var globalStrikeStorage = new InMemoryStrikeStorage;
|
|
|
31957
32790
|
var swarm_init = tool({
|
|
31958
32791
|
description: "Initialize swarm session: discovers available skills, checks tool availability. ALWAYS call at swarm start.",
|
|
31959
32792
|
args: {
|
|
31960
|
-
project_path: tool.schema.string().optional().describe("Project path (for Agent Mail init)")
|
|
32793
|
+
project_path: tool.schema.string().optional().describe("Project path (for Agent Mail init)"),
|
|
32794
|
+
isolation: tool.schema.enum(["worktree", "reservation"]).optional().default("reservation").describe("Isolation mode: 'worktree' for git worktree isolation (requires clean git state), 'reservation' for file reservations (default)")
|
|
31961
32795
|
},
|
|
31962
32796
|
async execute(args) {
|
|
31963
32797
|
const availability = await checkAllTools();
|
|
@@ -31999,8 +32833,39 @@ var swarm_init = tool({
|
|
|
31999
32833
|
} else {
|
|
32000
32834
|
skillsGuidance = "No skills found. Add skills to .opencode/skills/ or .claude/skills/ for specialized guidance.";
|
|
32001
32835
|
}
|
|
32836
|
+
const isolationMode = args.isolation ?? "reservation";
|
|
32837
|
+
let isolationInfo = {
|
|
32838
|
+
mode: isolationMode,
|
|
32839
|
+
available: true
|
|
32840
|
+
};
|
|
32841
|
+
if (isolationMode === "worktree" && args.project_path) {
|
|
32842
|
+
const worktreeCheck = await canUseWorktreeIsolation(args.project_path);
|
|
32843
|
+
if (worktreeCheck.canUse) {
|
|
32844
|
+
const startCommit = await getStartCommit(args.project_path);
|
|
32845
|
+
isolationInfo = {
|
|
32846
|
+
mode: "worktree",
|
|
32847
|
+
available: true,
|
|
32848
|
+
start_commit: startCommit ?? undefined
|
|
32849
|
+
};
|
|
32850
|
+
} else {
|
|
32851
|
+
isolationInfo = {
|
|
32852
|
+
mode: "reservation",
|
|
32853
|
+
available: false,
|
|
32854
|
+
reason: `Worktree mode unavailable: ${worktreeCheck.reason}. Falling back to reservation mode.`
|
|
32855
|
+
};
|
|
32856
|
+
warnings.push(`⚠️ Worktree isolation unavailable: ${worktreeCheck.reason}. Using file reservations instead.`);
|
|
32857
|
+
}
|
|
32858
|
+
} else if (isolationMode === "worktree" && !args.project_path) {
|
|
32859
|
+
isolationInfo = {
|
|
32860
|
+
mode: "reservation",
|
|
32861
|
+
available: false,
|
|
32862
|
+
reason: "Worktree mode requires project_path. Falling back to reservation mode."
|
|
32863
|
+
};
|
|
32864
|
+
warnings.push("⚠️ Worktree isolation requires project_path. Using file reservations instead.");
|
|
32865
|
+
}
|
|
32002
32866
|
return JSON.stringify({
|
|
32003
32867
|
ready: true,
|
|
32868
|
+
isolation: isolationInfo,
|
|
32004
32869
|
tool_availability: Object.fromEntries(Array.from(availability.entries()).map(([k, v]) => [
|
|
32005
32870
|
k,
|
|
32006
32871
|
{
|
|
@@ -32014,7 +32879,8 @@ var swarm_init = tool({
|
|
|
32014
32879
|
recommendations: {
|
|
32015
32880
|
skills: skillsGuidance,
|
|
32016
32881
|
beads: beadsAvailable ? "✓ Use beads for all task tracking" : "Install beads: npm i -g @joelhooks/beads",
|
|
32017
|
-
agent_mail: agentMailAvailable2 ? "✓ Use Agent Mail for coordination" : "Start Agent Mail: agent-mail serve"
|
|
32882
|
+
agent_mail: agentMailAvailable2 ? "✓ Use Agent Mail for coordination" : "Start Agent Mail: agent-mail serve",
|
|
32883
|
+
isolation: isolationInfo.mode === "worktree" ? "✓ Using git worktree isolation" : "✓ Using file reservation isolation"
|
|
32018
32884
|
},
|
|
32019
32885
|
report
|
|
32020
32886
|
}, null, 2);
|
|
@@ -32106,7 +32972,7 @@ var swarm_progress = tool({
|
|
|
32106
32972
|
await Bun.$`bd update ${args.bead_id} --status ${beadStatus} --json`.quiet().nothrow();
|
|
32107
32973
|
}
|
|
32108
32974
|
const epicId = args.bead_id.includes(".") ? args.bead_id.split(".")[0] : args.bead_id;
|
|
32109
|
-
await
|
|
32975
|
+
await sendSwarmMessage3({
|
|
32110
32976
|
projectPath: args.project_key,
|
|
32111
32977
|
fromAgent: args.agent_name,
|
|
32112
32978
|
toAgents: [],
|
|
@@ -32174,7 +33040,7 @@ ${args.files_affected.map((f) => `- \`${f}\``).join(`
|
|
|
32174
33040
|
].filter(Boolean).join(`
|
|
32175
33041
|
`);
|
|
32176
33042
|
const mailImportance = args.importance === "blocker" ? "urgent" : args.importance === "warning" ? "high" : "normal";
|
|
32177
|
-
await
|
|
33043
|
+
await sendSwarmMessage3({
|
|
32178
33044
|
projectPath: args.project_path,
|
|
32179
33045
|
fromAgent: args.agent_name,
|
|
32180
33046
|
toAgents: [],
|
|
@@ -32209,10 +33075,42 @@ var swarm_complete = tool({
|
|
|
32209
33075
|
planned_files: tool.schema.array(tool.schema.string()).optional().describe("Files that were originally planned to be modified"),
|
|
32210
33076
|
start_time: tool.schema.number().optional().describe("Task start timestamp (Unix ms) for duration calculation"),
|
|
32211
33077
|
error_count: tool.schema.number().optional().describe("Number of errors encountered during task"),
|
|
32212
|
-
retry_count: tool.schema.number().optional().describe("Number of retry attempts during task")
|
|
33078
|
+
retry_count: tool.schema.number().optional().describe("Number of retry attempts during task"),
|
|
33079
|
+
skip_review: tool.schema.boolean().optional().describe("Skip review gate check (default: false). Use only for tasks that don't require coordinator review.")
|
|
32213
33080
|
},
|
|
32214
33081
|
async execute(args, _ctx) {
|
|
32215
33082
|
const epicId = args.bead_id.includes(".") ? args.bead_id.split(".")[0] : args.bead_id;
|
|
33083
|
+
if (!args.skip_review) {
|
|
33084
|
+
const reviewStatusResult = getReviewStatus(args.bead_id);
|
|
33085
|
+
if (!reviewStatusResult.approved) {
|
|
33086
|
+
if (!reviewStatusResult.reviewed) {
|
|
33087
|
+
return JSON.stringify({
|
|
33088
|
+
success: false,
|
|
33089
|
+
error: "Review required before completion",
|
|
33090
|
+
review_status: reviewStatusResult,
|
|
33091
|
+
hint: `This task requires coordinator review before completion.
|
|
33092
|
+
|
|
33093
|
+
**Next steps:**
|
|
33094
|
+
1. Request review with swarm_review(project_key="${args.project_key}", epic_id="${epicId}", task_id="${args.bead_id}", files_touched=[...])
|
|
33095
|
+
2. Wait for coordinator to review and approve with swarm_review_feedback
|
|
33096
|
+
3. Once approved, call swarm_complete again
|
|
33097
|
+
|
|
33098
|
+
Or use skip_review=true to bypass (not recommended for production work).`
|
|
33099
|
+
}, null, 2);
|
|
33100
|
+
}
|
|
33101
|
+
return JSON.stringify({
|
|
33102
|
+
success: false,
|
|
33103
|
+
error: "Review not approved",
|
|
33104
|
+
review_status: reviewStatusResult,
|
|
33105
|
+
hint: `Task was reviewed but not approved. ${reviewStatusResult.remaining_attempts} attempt(s) remaining.
|
|
33106
|
+
|
|
33107
|
+
**Next steps:**
|
|
33108
|
+
1. Address the feedback from the reviewer
|
|
33109
|
+
2. Request another review with swarm_review
|
|
33110
|
+
3. Once approved, call swarm_complete again`
|
|
33111
|
+
}, null, 2);
|
|
33112
|
+
}
|
|
33113
|
+
}
|
|
32216
33114
|
try {
|
|
32217
33115
|
const projectKey = args.project_key.replace(/\//g, "-").replace(/\\/g, "-");
|
|
32218
33116
|
let agentRegistered = false;
|
|
@@ -32307,7 +33205,7 @@ Continuing with completion, but this should be fixed for future subtasks.`;
|
|
|
32307
33205
|
const isNotFoundError = stderrOutput.includes("not found") || stderrOutput.includes("does not exist");
|
|
32308
33206
|
return JSON.stringify({
|
|
32309
33207
|
success: false,
|
|
32310
|
-
error: "Failed to close
|
|
33208
|
+
error: "Failed to close cell",
|
|
32311
33209
|
failed_step: "bd close",
|
|
32312
33210
|
details: stderrOutput || stdoutOutput || "Unknown error from bd close command",
|
|
32313
33211
|
bead_id: args.bead_id,
|
|
@@ -32316,15 +33214,15 @@ Continuing with completion, but this should be fixed for future subtasks.`;
|
|
|
32316
33214
|
steps: isNoDatabaseError ? [
|
|
32317
33215
|
`1. Verify project_key is correct: "${args.project_key}"`,
|
|
32318
33216
|
`2. Check .beads/ exists in that directory`,
|
|
32319
|
-
`3.
|
|
32320
|
-
`4. Try:
|
|
33217
|
+
`3. Cell ID prefix "${args.bead_id.split("-")[0]}" should match project`,
|
|
33218
|
+
`4. Try: hive_close(id="${args.bead_id}", reason="...")`
|
|
32321
33219
|
] : [
|
|
32322
|
-
`1. Check
|
|
32323
|
-
`2. Check
|
|
32324
|
-
`3. If
|
|
32325
|
-
`4. Try closing directly:
|
|
33220
|
+
`1. Check cell exists: bd show ${args.bead_id}`,
|
|
33221
|
+
`2. Check cell status (might already be closed): hive_query()`,
|
|
33222
|
+
`3. If cell is blocked, unblock first: hive_update(id="${args.bead_id}", status="in_progress")`,
|
|
33223
|
+
`4. Try closing directly: hive_close(id="${args.bead_id}", reason="...")`
|
|
32326
33224
|
],
|
|
32327
|
-
hint: isNoDatabaseError ? `The project_key "${args.project_key}" doesn't have a .beads/ directory. Make sure you're using the correct project path.` : isNotFoundError ? `
|
|
33225
|
+
hint: isNoDatabaseError ? `The project_key "${args.project_key}" doesn't have a .beads/ directory. Make sure you're using the correct project path.` : isNotFoundError ? `Cell "${args.bead_id}" not found. It may have been closed already or the ID is incorrect.` : "If cell is in 'blocked' status, you must change it to 'in_progress' or 'open' before closing."
|
|
32328
33226
|
}
|
|
32329
33227
|
}, null, 2);
|
|
32330
33228
|
}
|
|
@@ -32392,7 +33290,7 @@ Continuing with completion, but this should be fixed for future subtasks.`;
|
|
|
32392
33290
|
let messageSent = false;
|
|
32393
33291
|
let messageError;
|
|
32394
33292
|
try {
|
|
32395
|
-
await
|
|
33293
|
+
await sendSwarmMessage3({
|
|
32396
33294
|
projectPath: args.project_key,
|
|
32397
33295
|
fromAgent: args.agent_name,
|
|
32398
33296
|
toAgents: [],
|
|
@@ -32502,14 +33400,14 @@ ${errorStack.slice(0, 1000)}
|
|
|
32502
33400
|
"",
|
|
32503
33401
|
`### Recovery Actions`,
|
|
32504
33402
|
"1. Check error message for specific issue",
|
|
32505
|
-
"2. Review failed step (UBS scan, typecheck,
|
|
33403
|
+
"2. Review failed step (UBS scan, typecheck, cell close, etc.)",
|
|
32506
33404
|
"3. Fix underlying issue or use skip flags if appropriate",
|
|
32507
33405
|
"4. Retry swarm_complete after fixing"
|
|
32508
33406
|
].filter(Boolean).join(`
|
|
32509
33407
|
`);
|
|
32510
33408
|
let notificationSent = false;
|
|
32511
33409
|
try {
|
|
32512
|
-
await
|
|
33410
|
+
await sendSwarmMessage3({
|
|
32513
33411
|
projectPath: args.project_key,
|
|
32514
33412
|
fromAgent: args.agent_name,
|
|
32515
33413
|
toAgents: [],
|
|
@@ -32547,7 +33445,7 @@ ${errorStack.slice(0, 1000)}
|
|
|
32547
33445
|
common_fixes: {
|
|
32548
33446
|
"Verification Gate": "Use skip_verification=true to bypass (not recommended)",
|
|
32549
33447
|
"UBS scan": "Use skip_ubs_scan=true to bypass",
|
|
32550
|
-
"
|
|
33448
|
+
"Cell close": "Check cell status with hive_query(), may need hive_update() first",
|
|
32551
33449
|
"Self-evaluation": "Check evaluation JSON format matches EvaluationSchema"
|
|
32552
33450
|
}
|
|
32553
33451
|
}
|
|
@@ -32646,7 +33544,7 @@ var swarm_record_outcome = tool({
|
|
|
32646
33544
|
var swarm_accumulate_error = tool({
|
|
32647
33545
|
description: "Record an error during subtask execution. Errors feed into retry prompts.",
|
|
32648
33546
|
args: {
|
|
32649
|
-
bead_id: tool.schema.string().describe("
|
|
33547
|
+
bead_id: tool.schema.string().describe("Cell ID where error occurred"),
|
|
32650
33548
|
error_type: tool.schema.enum(["validation", "timeout", "conflict", "tool_failure", "unknown"]).describe("Category of error"),
|
|
32651
33549
|
message: tool.schema.string().describe("Human-readable error message"),
|
|
32652
33550
|
stack_trace: tool.schema.string().optional().describe("Stack trace for debugging"),
|
|
@@ -32673,7 +33571,7 @@ var swarm_accumulate_error = tool({
|
|
|
32673
33571
|
var swarm_get_error_context = tool({
|
|
32674
33572
|
description: "Get accumulated errors for a bead. Returns formatted context for retry prompts.",
|
|
32675
33573
|
args: {
|
|
32676
|
-
bead_id: tool.schema.string().describe("
|
|
33574
|
+
bead_id: tool.schema.string().describe("Cell ID to get errors for"),
|
|
32677
33575
|
include_resolved: tool.schema.boolean().optional().describe("Include resolved errors (default: false)")
|
|
32678
33576
|
},
|
|
32679
33577
|
async execute(args) {
|
|
@@ -32709,7 +33607,7 @@ var swarm_resolve_error = tool({
|
|
|
32709
33607
|
var swarm_check_strikes = tool({
|
|
32710
33608
|
description: "Check 3-strike status for a bead. Records failures, detects architectural problems, generates architecture review prompts.",
|
|
32711
33609
|
args: {
|
|
32712
|
-
bead_id: tool.schema.string().describe("
|
|
33610
|
+
bead_id: tool.schema.string().describe("Cell ID to check"),
|
|
32713
33611
|
action: tool.schema.enum(["check", "add_strike", "clear", "get_prompt"]).describe("Action: check count, add strike, clear strikes, or get prompt"),
|
|
32714
33612
|
attempt: tool.schema.string().optional().describe("Description of fix attempt (required for add_strike)"),
|
|
32715
33613
|
reason: tool.schema.string().optional().describe("Why the fix failed (required for add_strike)")
|
|
@@ -32974,7 +33872,7 @@ ${args.files_context.map((f) => `- \`${f}\``).join(`
|
|
|
32974
33872
|
*Learned from swarm execution on ${new Date().toISOString().split("T")[0]}*`;
|
|
32975
33873
|
const { getSkill: getSkill2, invalidateSkillsCache: invalidateSkillsCache2 } = await Promise.resolve().then(() => (init_skills(), exports_skills));
|
|
32976
33874
|
const { mkdir: mkdir2, writeFile: writeFile2 } = await import("node:fs/promises");
|
|
32977
|
-
const { join:
|
|
33875
|
+
const { join: join7 } = await import("node:path");
|
|
32978
33876
|
const existing = await getSkill2(args.skill_name);
|
|
32979
33877
|
if (existing) {
|
|
32980
33878
|
return JSON.stringify({
|
|
@@ -32985,8 +33883,8 @@ ${args.files_context.map((f) => `- \`${f}\``).join(`
|
|
|
32985
33883
|
suggestion: "Use skills_update to add to existing skill, or choose a different name"
|
|
32986
33884
|
}, null, 2);
|
|
32987
33885
|
}
|
|
32988
|
-
const skillDir =
|
|
32989
|
-
const skillPath =
|
|
33886
|
+
const skillDir = join7(process.cwd(), ".opencode", "skills", args.skill_name);
|
|
33887
|
+
const skillPath = join7(skillDir, "SKILL.md");
|
|
32990
33888
|
const frontmatter = [
|
|
32991
33889
|
"---",
|
|
32992
33890
|
`name: ${args.skill_name}`,
|
|
@@ -34156,14 +35054,14 @@ var DEFAULT_GUARDRAIL_CONFIG = {
|
|
|
34156
35054
|
cass_stats: 8000
|
|
34157
35055
|
},
|
|
34158
35056
|
skipTools: [
|
|
34159
|
-
"
|
|
34160
|
-
"
|
|
34161
|
-
"
|
|
34162
|
-
"
|
|
34163
|
-
"
|
|
34164
|
-
"
|
|
34165
|
-
"
|
|
34166
|
-
"
|
|
35057
|
+
"hive_create",
|
|
35058
|
+
"hive_create_epic",
|
|
35059
|
+
"hive_query",
|
|
35060
|
+
"hive_update",
|
|
35061
|
+
"hive_close",
|
|
35062
|
+
"hive_start",
|
|
35063
|
+
"hive_ready",
|
|
35064
|
+
"hive_sync",
|
|
34167
35065
|
"agentmail_init",
|
|
34168
35066
|
"agentmail_send",
|
|
34169
35067
|
"agentmail_inbox",
|
|
@@ -34183,7 +35081,7 @@ var DEFAULT_GUARDRAIL_CONFIG = {
|
|
|
34183
35081
|
"structured_validate",
|
|
34184
35082
|
"structured_parse_evaluation",
|
|
34185
35083
|
"structured_parse_decomposition",
|
|
34186
|
-
"
|
|
35084
|
+
"structured_parse_cell_tree",
|
|
34187
35085
|
"swarm_select_strategy",
|
|
34188
35086
|
"swarm_plan_prompt",
|
|
34189
35087
|
"swarm_decompose",
|
|
@@ -34367,7 +35265,7 @@ function analyzeTodoWrite(args) {
|
|
|
34367
35265
|
warning: `⚠️ This looks like a multi-file implementation plan (${fileModificationCount}/${todos.length} items are file modifications).
|
|
34368
35266
|
|
|
34369
35267
|
Consider using swarm instead:
|
|
34370
|
-
swarm_decompose →
|
|
35268
|
+
swarm_decompose → hive_create_epic → parallel task spawns
|
|
34371
35269
|
|
|
34372
35270
|
TodoWrite is for tracking progress, not parallelizable implementation work.
|
|
34373
35271
|
Swarm workers can complete these ${fileModificationCount} tasks in parallel.
|
|
@@ -34848,9 +35746,88 @@ async function resetStorage() {
|
|
|
34848
35746
|
|
|
34849
35747
|
// src/index.ts
|
|
34850
35748
|
init_skills();
|
|
35749
|
+
|
|
35750
|
+
// src/compaction-hook.ts
|
|
35751
|
+
var SWARM_COMPACTION_CONTEXT = `## \uD83D\uDC1D SWARM ACTIVE - Keep Cooking
|
|
35752
|
+
|
|
35753
|
+
You are the **COORDINATOR** of an active swarm. Context was compacted but the swarm is still running.
|
|
35754
|
+
|
|
35755
|
+
**YOUR JOB:** Keep orchestrating. Spawn agents. Monitor progress. Unblock work. Ship it.
|
|
35756
|
+
|
|
35757
|
+
### Preserve in Summary
|
|
35758
|
+
|
|
35759
|
+
Extract from session context:
|
|
35760
|
+
|
|
35761
|
+
1. **Epic & Subtasks** - IDs, titles, status, file assignments
|
|
35762
|
+
2. **What's Running** - Which agents are active, what they're working on
|
|
35763
|
+
3. **What's Blocked** - Blockers and what's needed to unblock
|
|
35764
|
+
4. **What's Done** - Completed work and any follow-ups needed
|
|
35765
|
+
5. **What's Next** - Pending subtasks ready to spawn
|
|
35766
|
+
|
|
35767
|
+
### Summary Format
|
|
35768
|
+
|
|
35769
|
+
\`\`\`
|
|
35770
|
+
## \uD83D\uDC1D Swarm State
|
|
35771
|
+
|
|
35772
|
+
**Epic:** <bd-xxx> - <title>
|
|
35773
|
+
**Project:** <path>
|
|
35774
|
+
**Progress:** X/Y subtasks complete
|
|
35775
|
+
|
|
35776
|
+
**Active:**
|
|
35777
|
+
- <bd-xxx>: <title> [in_progress] → <agent> working on <files>
|
|
35778
|
+
|
|
35779
|
+
**Blocked:**
|
|
35780
|
+
- <bd-xxx>: <title> - BLOCKED: <reason>
|
|
35781
|
+
|
|
35782
|
+
**Completed:**
|
|
35783
|
+
- <bd-xxx>: <title> ✓
|
|
35784
|
+
|
|
35785
|
+
**Ready to Spawn:**
|
|
35786
|
+
- <bd-xxx>: <title> (files: <...>)
|
|
35787
|
+
\`\`\`
|
|
35788
|
+
|
|
35789
|
+
### On Resume - IMMEDIATELY
|
|
35790
|
+
|
|
35791
|
+
1. \`swarm_status(epic_id="<epic>", project_key="<path>")\` - Get current state
|
|
35792
|
+
2. \`swarmmail_inbox(limit=5)\` - Check for agent messages
|
|
35793
|
+
3. **Spawn ready subtasks** - Don't wait, fire them off
|
|
35794
|
+
4. **Unblock blocked work** - Resolve dependencies, reassign if needed
|
|
35795
|
+
5. **Collect completed work** - Close done subtasks, verify quality
|
|
35796
|
+
|
|
35797
|
+
### Keep the Swarm Cooking
|
|
35798
|
+
|
|
35799
|
+
- **Spawn aggressively** - If a subtask is ready and unblocked, spawn an agent
|
|
35800
|
+
- **Monitor actively** - Check status, read messages, respond to blockers
|
|
35801
|
+
- **Close the loop** - When all subtasks done, verify and close the epic
|
|
35802
|
+
- **Don't stop** - The swarm runs until the epic is closed
|
|
35803
|
+
|
|
35804
|
+
**You are not waiting for instructions. You are the coordinator. Coordinate.**
|
|
35805
|
+
`;
|
|
35806
|
+
async function hasSwarmSign() {
|
|
35807
|
+
try {
|
|
35808
|
+
const projectKey = getHiveWorkingDirectory();
|
|
35809
|
+
const adapter = await getHiveAdapter(projectKey);
|
|
35810
|
+
const cells = await adapter.queryCells(projectKey, {});
|
|
35811
|
+
if (!Array.isArray(cells))
|
|
35812
|
+
return false;
|
|
35813
|
+
return cells.some((c) => c.status === "in_progress" || c.status === "open" && c.parent_id || c.type === "epic" && c.status !== "closed");
|
|
35814
|
+
} catch {
|
|
35815
|
+
return false;
|
|
35816
|
+
}
|
|
35817
|
+
}
|
|
35818
|
+
function createCompactionHook() {
|
|
35819
|
+
return async (_input, output) => {
|
|
35820
|
+
const hasSign = await hasSwarmSign();
|
|
35821
|
+
if (hasSign) {
|
|
35822
|
+
output.context.push(SWARM_COMPACTION_CONTEXT);
|
|
35823
|
+
}
|
|
35824
|
+
};
|
|
35825
|
+
}
|
|
35826
|
+
|
|
35827
|
+
// src/index.ts
|
|
34851
35828
|
var SwarmPlugin = async (input) => {
|
|
34852
35829
|
const { $, directory } = input;
|
|
34853
|
-
|
|
35830
|
+
setHiveWorkingDirectory(directory);
|
|
34854
35831
|
setSkillsProjectDirectory(directory);
|
|
34855
35832
|
setAgentMailProjectDirectory(directory);
|
|
34856
35833
|
setSwarmMailProjectDirectory(directory);
|
|
@@ -34885,10 +35862,12 @@ var SwarmPlugin = async (input) => {
|
|
|
34885
35862
|
}
|
|
34886
35863
|
return {
|
|
34887
35864
|
tool: {
|
|
34888
|
-
...
|
|
35865
|
+
...hiveTools,
|
|
34889
35866
|
...swarmMailTools,
|
|
34890
35867
|
...structuredTools,
|
|
34891
35868
|
...swarmTools,
|
|
35869
|
+
...worktreeTools,
|
|
35870
|
+
...reviewTools,
|
|
34892
35871
|
...repoCrawlTools,
|
|
34893
35872
|
...skillsTools,
|
|
34894
35873
|
...mandateTools
|
|
@@ -34937,7 +35916,7 @@ var SwarmPlugin = async (input) => {
|
|
|
34937
35916
|
if (toolName === "swarm_complete" && activeAgentMailState) {
|
|
34938
35917
|
await releaseReservations();
|
|
34939
35918
|
}
|
|
34940
|
-
if (toolName === "
|
|
35919
|
+
if (toolName === "hive_close" || toolName === "hive_close") {
|
|
34941
35920
|
$`bd sync`.quiet().nothrow();
|
|
34942
35921
|
}
|
|
34943
35922
|
}
|
|
@@ -34945,10 +35924,12 @@ var SwarmPlugin = async (input) => {
|
|
|
34945
35924
|
};
|
|
34946
35925
|
var src_default = SwarmPlugin;
|
|
34947
35926
|
var allTools = {
|
|
34948
|
-
...
|
|
35927
|
+
...hiveTools,
|
|
34949
35928
|
...swarmMailTools,
|
|
34950
35929
|
...structuredTools,
|
|
34951
35930
|
...swarmTools,
|
|
35931
|
+
...worktreeTools,
|
|
35932
|
+
...reviewTools,
|
|
34952
35933
|
...repoCrawlTools,
|
|
34953
35934
|
...skillsTools,
|
|
34954
35935
|
...mandateTools
|
|
@@ -34968,6 +35949,7 @@ export {
|
|
|
34968
35949
|
setStorage,
|
|
34969
35950
|
setSkillsProjectDirectory,
|
|
34970
35951
|
setMandateStorage,
|
|
35952
|
+
setHiveWorkingDirectory,
|
|
34971
35953
|
setBeadsWorkingDirectory,
|
|
34972
35954
|
setAgentMailProjectDirectory,
|
|
34973
35955
|
selectStrategy,
|
|
@@ -34986,11 +35968,22 @@ export {
|
|
|
34986
35968
|
isSemanticMemoryAvailable,
|
|
34987
35969
|
isProjectNotFoundError,
|
|
34988
35970
|
isEpicEvent,
|
|
35971
|
+
isCellEventType,
|
|
34989
35972
|
isBeadEventType,
|
|
34990
35973
|
isAgentNotFoundError,
|
|
34991
35974
|
isAgentEvent,
|
|
34992
35975
|
invalidateSkillsCache,
|
|
34993
35976
|
ifToolAvailable,
|
|
35977
|
+
hive_update,
|
|
35978
|
+
hive_sync,
|
|
35979
|
+
hive_start,
|
|
35980
|
+
hive_ready,
|
|
35981
|
+
hive_query,
|
|
35982
|
+
hive_link_thread,
|
|
35983
|
+
hive_create_epic,
|
|
35984
|
+
hive_create,
|
|
35985
|
+
hive_close,
|
|
35986
|
+
hiveTools,
|
|
34994
35987
|
guardrailOutput,
|
|
34995
35988
|
groupByTransition,
|
|
34996
35989
|
getToolAvailability,
|
|
@@ -35001,6 +35994,9 @@ export {
|
|
|
35001
35994
|
getSkill,
|
|
35002
35995
|
getSchemaByName,
|
|
35003
35996
|
getMandateStorage,
|
|
35997
|
+
getHiveWorkingDirectory,
|
|
35998
|
+
getHiveAdapter,
|
|
35999
|
+
getCellIdFromEvent,
|
|
35004
36000
|
getBeadsWorkingDirectory,
|
|
35005
36001
|
getBeadsAdapter,
|
|
35006
36002
|
getBeadIdFromEvent,
|
|
@@ -35022,6 +36018,8 @@ export {
|
|
|
35022
36018
|
createStorage,
|
|
35023
36019
|
createMetrics,
|
|
35024
36020
|
createMandateStorage,
|
|
36021
|
+
createCompactionHook,
|
|
36022
|
+
createCellEvent,
|
|
35025
36023
|
createBeadEvent,
|
|
35026
36024
|
createAgentMailError,
|
|
35027
36025
|
clearSessionState,
|
|
@@ -35061,6 +36059,7 @@ export {
|
|
|
35061
36059
|
SemanticMemoryStorage,
|
|
35062
36060
|
SemanticMemoryMandateStorage,
|
|
35063
36061
|
ScoreCalculationResultSchema,
|
|
36062
|
+
SWARM_COMPACTION_CONTEXT,
|
|
35064
36063
|
SUBTASK_PROMPT_V2,
|
|
35065
36064
|
STRATEGIES,
|
|
35066
36065
|
RepoCrawlError,
|
|
@@ -35073,6 +36072,8 @@ export {
|
|
|
35073
36072
|
MandateContentTypeSchema,
|
|
35074
36073
|
InMemoryStorage,
|
|
35075
36074
|
InMemoryMandateStorage,
|
|
36075
|
+
HiveValidationError,
|
|
36076
|
+
HiveError,
|
|
35076
36077
|
FileReservationConflictError,
|
|
35077
36078
|
EvaluationSchema,
|
|
35078
36079
|
EvaluationRequestSchema,
|
|
@@ -35091,6 +36092,35 @@ export {
|
|
|
35091
36092
|
CriterionEvaluationSchema,
|
|
35092
36093
|
CreateSwarmContextArgsSchema,
|
|
35093
36094
|
CreateMandateArgsSchema,
|
|
36095
|
+
CellWorkStartedEventSchema,
|
|
36096
|
+
CellUpdatedEventSchema,
|
|
36097
|
+
CellUpdateArgsSchema,
|
|
36098
|
+
CellTypeSchema,
|
|
36099
|
+
CellTreeSchema,
|
|
36100
|
+
CellStatusSchema,
|
|
36101
|
+
CellStatusChangedEventSchema,
|
|
36102
|
+
CellSchema,
|
|
36103
|
+
CellReopenedEventSchema,
|
|
36104
|
+
CellQueryArgsSchema,
|
|
36105
|
+
CellLabelRemovedEventSchema,
|
|
36106
|
+
CellLabelAddedEventSchema,
|
|
36107
|
+
CellEventSchema,
|
|
36108
|
+
CellEpicClosureEligibleEventSchema,
|
|
36109
|
+
CellEpicChildRemovedEventSchema,
|
|
36110
|
+
CellEpicChildAddedEventSchema,
|
|
36111
|
+
CellDependencySchema,
|
|
36112
|
+
CellDependencyRemovedEventSchema,
|
|
36113
|
+
CellDependencyAddedEventSchema,
|
|
36114
|
+
CellDeletedEventSchema,
|
|
36115
|
+
CellCreatedEventSchema,
|
|
36116
|
+
CellCreateArgsSchema,
|
|
36117
|
+
CellCompactedEventSchema,
|
|
36118
|
+
CellCommentUpdatedEventSchema,
|
|
36119
|
+
CellCommentDeletedEventSchema,
|
|
36120
|
+
CellCommentAddedEventSchema,
|
|
36121
|
+
CellClosedEventSchema,
|
|
36122
|
+
CellCloseArgsSchema,
|
|
36123
|
+
CellAssignedEventSchema,
|
|
35094
36124
|
CastVoteArgsSchema,
|
|
35095
36125
|
BeadWorkStartedEventSchema,
|
|
35096
36126
|
BeadValidationError,
|
|
@@ -35123,6 +36153,7 @@ export {
|
|
|
35123
36153
|
BeadClosedEventSchema,
|
|
35124
36154
|
BeadCloseArgsSchema,
|
|
35125
36155
|
BeadAssignedEventSchema,
|
|
36156
|
+
BaseCellEventSchema,
|
|
35126
36157
|
BaseBeadEventSchema,
|
|
35127
36158
|
AgentProgressSchema,
|
|
35128
36159
|
AgentMailNotInitializedError,
|