opencode-swarm-plugin 0.59.1 → 0.60.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/README.md +14 -1
- package/bin/commands/doctor.test.ts +622 -0
- package/bin/commands/doctor.ts +658 -0
- package/bin/commands/status.test.ts +506 -0
- package/bin/commands/status.ts +520 -0
- package/bin/commands/tree.ts +39 -3
- package/bin/swarm.ts +19 -3
- package/claude-plugin/.claude-plugin/plugin.json +1 -1
- package/claude-plugin/commands/swarm.md +125 -2
- package/claude-plugin/dist/index.js +669 -308
- package/claude-plugin/dist/schemas/cell.d.ts +2 -0
- package/claude-plugin/dist/schemas/cell.d.ts.map +1 -1
- package/claude-plugin/dist/utils/adapter-cache.d.ts +36 -0
- package/claude-plugin/dist/utils/adapter-cache.d.ts.map +1 -0
- package/claude-plugin/dist/utils/event-utils.d.ts +31 -0
- package/claude-plugin/dist/utils/event-utils.d.ts.map +1 -0
- package/claude-plugin/dist/utils/git-commit-info.d.ts +10 -0
- package/claude-plugin/dist/utils/git-commit-info.d.ts.map +1 -0
- package/claude-plugin/dist/utils/tree-renderer.d.ts +69 -13
- package/claude-plugin/dist/utils/tree-renderer.d.ts.map +1 -1
- package/dist/bin/swarm.js +2664 -980
- package/dist/cass-tools.d.ts.map +1 -1
- package/dist/dashboard.d.ts.map +1 -1
- package/dist/hive.d.ts +8 -0
- package/dist/hive.d.ts.map +1 -1
- package/dist/hive.js +81 -101
- package/dist/hivemind-tools.d.ts.map +1 -1
- package/dist/index.d.ts +22 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +458 -311
- package/dist/marketplace/index.js +669 -308
- package/dist/memory-tools.d.ts.map +1 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/plugin.js +456 -308
- package/dist/replay-tools.d.ts +5 -1
- package/dist/replay-tools.d.ts.map +1 -1
- package/dist/schemas/cell.d.ts +2 -0
- package/dist/schemas/cell.d.ts.map +1 -1
- package/dist/skills.d.ts +4 -0
- package/dist/skills.d.ts.map +1 -1
- package/dist/storage.d.ts +7 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/swarm-mail.d.ts +2 -2
- package/dist/swarm-mail.d.ts.map +1 -1
- package/dist/swarm-orchestrate.d.ts +12 -0
- package/dist/swarm-orchestrate.d.ts.map +1 -1
- package/dist/swarm-prompts.d.ts +1 -1
- package/dist/swarm-prompts.d.ts.map +1 -1
- package/dist/swarm-prompts.js +408 -274
- package/dist/swarm-verify.d.ts +100 -0
- package/dist/swarm-verify.d.ts.map +1 -0
- package/dist/swarm.d.ts +19 -1
- package/dist/swarm.d.ts.map +1 -1
- package/dist/test-utils/msw-server.d.ts +21 -0
- package/dist/test-utils/msw-server.d.ts.map +1 -0
- package/dist/utils/adapter-cache.d.ts +36 -0
- package/dist/utils/adapter-cache.d.ts.map +1 -0
- package/dist/utils/event-utils.d.ts +31 -0
- package/dist/utils/event-utils.d.ts.map +1 -0
- package/dist/utils/git-commit-info.d.ts +10 -0
- package/dist/utils/git-commit-info.d.ts.map +1 -0
- package/dist/utils/tree-renderer.d.ts +69 -13
- package/dist/utils/tree-renderer.d.ts.map +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -27180,7 +27180,7 @@ import {
|
|
|
27180
27180
|
sep
|
|
27181
27181
|
} from "path";
|
|
27182
27182
|
import { fileURLToPath } from "url";
|
|
27183
|
-
import { getSwarmMailLibSQL as getSwarmMailLibSQL3, createEvent as
|
|
27183
|
+
import { getSwarmMailLibSQL as getSwarmMailLibSQL3, createEvent as createEvent3 } from "swarm-mail";
|
|
27184
27184
|
function resolveGuidanceModel(model) {
|
|
27185
27185
|
if (!model)
|
|
27186
27186
|
return "unknown";
|
|
@@ -27223,7 +27223,7 @@ async function emitSkillLoadedEvent(data) {
|
|
|
27223
27223
|
try {
|
|
27224
27224
|
const projectPath = skillsProjectDirectory;
|
|
27225
27225
|
const swarmMail = await getSwarmMailLibSQL3(projectPath);
|
|
27226
|
-
const event =
|
|
27226
|
+
const event = createEvent3("skill_loaded", {
|
|
27227
27227
|
project_key: projectPath,
|
|
27228
27228
|
skill_name: data.skill_name,
|
|
27229
27229
|
skill_source: data.skill_source,
|
|
@@ -27237,7 +27237,7 @@ async function emitSkillCreatedEvent(data) {
|
|
|
27237
27237
|
try {
|
|
27238
27238
|
const projectPath = skillsProjectDirectory;
|
|
27239
27239
|
const swarmMail = await getSwarmMailLibSQL3(projectPath);
|
|
27240
|
-
const event =
|
|
27240
|
+
const event = createEvent3("skill_created", {
|
|
27241
27241
|
project_key: projectPath,
|
|
27242
27242
|
skill_name: data.skill_name,
|
|
27243
27243
|
skill_scope: data.skill_scope,
|
|
@@ -27757,7 +27757,8 @@ Scripts run in the skill's directory with the project directory as an argument.`
|
|
|
27757
27757
|
args: {
|
|
27758
27758
|
skill: tool.schema.string().describe("Name of the skill"),
|
|
27759
27759
|
script: tool.schema.string().describe("Name of the script file to execute"),
|
|
27760
|
-
args: tool.schema.array(tool.schema.string()).optional().describe("Additional arguments to pass to the script")
|
|
27760
|
+
args: tool.schema.array(tool.schema.string()).optional().describe("Additional arguments to pass to the script"),
|
|
27761
|
+
timeout_ms: tool.schema.number().optional().describe("Timeout in milliseconds (default: 60000)")
|
|
27761
27762
|
},
|
|
27762
27763
|
async execute(args, ctx) {
|
|
27763
27764
|
console.warn("[DEPRECATED] skills_execute is deprecated. OpenCode now provides native skills support. This tool will be removed in a future version.");
|
|
@@ -27770,7 +27771,7 @@ Scripts run in the skill's directory with the project directory as an argument.`
|
|
|
27770
27771
|
}
|
|
27771
27772
|
const scriptPath = join6(skill.directory, "scripts", args.script);
|
|
27772
27773
|
const scriptArgs = args.args || [];
|
|
27773
|
-
const TIMEOUT_MS = 60000;
|
|
27774
|
+
const TIMEOUT_MS = args.timeout_ms ?? 60000;
|
|
27774
27775
|
const proc = Bun.spawn([scriptPath, skillsProjectDirectory, ...scriptArgs], {
|
|
27775
27776
|
cwd: skill.directory,
|
|
27776
27777
|
stdout: "pipe",
|
|
@@ -28673,6 +28674,7 @@ __export(exports_storage, {
|
|
|
28673
28674
|
resetStorage: () => resetStorage,
|
|
28674
28675
|
resetSessionStats: () => resetSessionStats,
|
|
28675
28676
|
resetCommandCache: () => resetCommandCache,
|
|
28677
|
+
resetAvailabilityCache: () => resetAvailabilityCache,
|
|
28676
28678
|
isSemanticMemoryAvailable: () => isSemanticMemoryAvailable,
|
|
28677
28679
|
getTestCollectionName: () => getTestCollectionName,
|
|
28678
28680
|
getStorage: () => getStorage,
|
|
@@ -29023,12 +29025,25 @@ function createStorage(config2 = {}) {
|
|
|
29023
29025
|
}
|
|
29024
29026
|
}
|
|
29025
29027
|
async function isSemanticMemoryAvailable() {
|
|
29026
|
-
|
|
29027
|
-
|
|
29028
|
-
|
|
29029
|
-
|
|
29030
|
-
|
|
29031
|
-
|
|
29028
|
+
if (_availabilityCache !== null)
|
|
29029
|
+
return _availabilityCache;
|
|
29030
|
+
if (_availabilityPromise)
|
|
29031
|
+
return _availabilityPromise;
|
|
29032
|
+
_availabilityPromise = (async () => {
|
|
29033
|
+
try {
|
|
29034
|
+
const result = await execSemanticMemory(["stats"]);
|
|
29035
|
+
_availabilityCache = result.exitCode === 0;
|
|
29036
|
+
} catch {
|
|
29037
|
+
_availabilityCache = false;
|
|
29038
|
+
}
|
|
29039
|
+
_availabilityPromise = null;
|
|
29040
|
+
return _availabilityCache;
|
|
29041
|
+
})();
|
|
29042
|
+
return _availabilityPromise;
|
|
29043
|
+
}
|
|
29044
|
+
function resetAvailabilityCache() {
|
|
29045
|
+
_availabilityCache = null;
|
|
29046
|
+
_availabilityPromise = null;
|
|
29032
29047
|
}
|
|
29033
29048
|
async function getResolvedCommand() {
|
|
29034
29049
|
return resolveSemanticMemoryCommand();
|
|
@@ -29064,7 +29079,7 @@ async function resetStorage() {
|
|
|
29064
29079
|
}
|
|
29065
29080
|
globalStoragePromise = null;
|
|
29066
29081
|
}
|
|
29067
|
-
var cachedCommand = null, DEFAULT_STORAGE_CONFIG, sessionStats, globalStorage = null, globalStoragePromise = null;
|
|
29082
|
+
var cachedCommand = null, DEFAULT_STORAGE_CONFIG, sessionStats, _availabilityCache = null, _availabilityPromise = null, globalStorage = null, globalStoragePromise = null;
|
|
29068
29083
|
var init_storage = __esm(() => {
|
|
29069
29084
|
init_learning();
|
|
29070
29085
|
init_anti_patterns();
|
|
@@ -29078,6 +29093,27 @@ var init_storage = __esm(() => {
|
|
|
29078
29093
|
};
|
|
29079
29094
|
});
|
|
29080
29095
|
|
|
29096
|
+
// src/utils/adapter-cache.ts
|
|
29097
|
+
class AdapterCache {
|
|
29098
|
+
cached = null;
|
|
29099
|
+
cachedPath = null;
|
|
29100
|
+
async get(projectPath, factory) {
|
|
29101
|
+
if (this.cached && this.cachedPath === projectPath) {
|
|
29102
|
+
return this.cached;
|
|
29103
|
+
}
|
|
29104
|
+
this.cached = await factory(projectPath);
|
|
29105
|
+
this.cachedPath = projectPath;
|
|
29106
|
+
return this.cached;
|
|
29107
|
+
}
|
|
29108
|
+
clear() {
|
|
29109
|
+
this.cached = null;
|
|
29110
|
+
this.cachedPath = null;
|
|
29111
|
+
}
|
|
29112
|
+
getCachedPath() {
|
|
29113
|
+
return this.cachedPath;
|
|
29114
|
+
}
|
|
29115
|
+
}
|
|
29116
|
+
|
|
29081
29117
|
// ../../node_modules/.bun/effect@3.19.12/node_modules/effect/dist/esm/Function.js
|
|
29082
29118
|
function pipe2(a, ab, bc, cd, de, ef, fg, gh, hi) {
|
|
29083
29119
|
switch (arguments.length) {
|
|
@@ -46404,6 +46440,9 @@ Linked to ${result.links.length} related memor${result.links.length === 1 ? "y"
|
|
|
46404
46440
|
};
|
|
46405
46441
|
},
|
|
46406
46442
|
async find(args2) {
|
|
46443
|
+
if (!args2.query || typeof args2.query !== "string") {
|
|
46444
|
+
throw new Error("query is required for find operation");
|
|
46445
|
+
}
|
|
46407
46446
|
const limit = args2.limit ?? 10;
|
|
46408
46447
|
let results;
|
|
46409
46448
|
let usedFallback = false;
|
|
@@ -46522,26 +46561,23 @@ var init_memory = __esm(() => {
|
|
|
46522
46561
|
});
|
|
46523
46562
|
|
|
46524
46563
|
// src/memory-tools.ts
|
|
46525
|
-
import { getSwarmMailLibSQL as getSwarmMailLibSQL5, createEvent as
|
|
46564
|
+
import { getSwarmMailLibSQL as getSwarmMailLibSQL5, createEvent as createEvent5, appendEvent as appendEvent4 } from "swarm-mail";
|
|
46526
46565
|
async function getMemoryAdapter(projectPath) {
|
|
46527
46566
|
const path3 = projectPath || process.cwd();
|
|
46528
|
-
|
|
46529
|
-
|
|
46530
|
-
|
|
46531
|
-
|
|
46532
|
-
|
|
46533
|
-
cachedAdapter = await createMemoryAdapter(dbAdapter);
|
|
46534
|
-
cachedProjectPath = path3;
|
|
46535
|
-
return cachedAdapter;
|
|
46567
|
+
return memoryAdapterCache.get(path3, async (projectPath2) => {
|
|
46568
|
+
const swarmMail = await getSwarmMailLibSQL5(projectPath2);
|
|
46569
|
+
const dbAdapter = await swarmMail.getDatabase();
|
|
46570
|
+
return await createMemoryAdapter(dbAdapter);
|
|
46571
|
+
});
|
|
46536
46572
|
}
|
|
46537
46573
|
function resetMemoryCache() {
|
|
46538
|
-
|
|
46539
|
-
cachedProjectPath = null;
|
|
46574
|
+
memoryAdapterCache.clear();
|
|
46540
46575
|
}
|
|
46541
|
-
var
|
|
46576
|
+
var memoryAdapterCache, semantic_memory_store, semantic_memory_find, semantic_memory_get, semantic_memory_remove, semantic_memory_validate, semantic_memory_list, semantic_memory_stats, semantic_memory_check, semantic_memory_upsert, memoryTools;
|
|
46542
46577
|
var init_memory_tools = __esm(() => {
|
|
46543
46578
|
init_dist();
|
|
46544
46579
|
init_memory();
|
|
46580
|
+
memoryAdapterCache = new AdapterCache;
|
|
46545
46581
|
semantic_memory_store = tool({
|
|
46546
46582
|
description: "Store a memory with semantic embedding. Memories are searchable by semantic similarity and can be organized into collections. Confidence affects decay rate: high confidence (1.0) = 135 day half-life, low confidence (0.0) = 45 day half-life. Supports auto-tagging, auto-linking, and entity extraction via LLM.",
|
|
46547
46583
|
args: {
|
|
@@ -46558,9 +46594,9 @@ var init_memory_tools = __esm(() => {
|
|
|
46558
46594
|
const adapter = await getMemoryAdapter();
|
|
46559
46595
|
const result = await adapter.store(args2);
|
|
46560
46596
|
try {
|
|
46561
|
-
const projectKey =
|
|
46597
|
+
const projectKey = memoryAdapterCache.getCachedPath() || process.cwd();
|
|
46562
46598
|
const tags = args2.tags ? args2.tags.split(",").map((t) => t.trim()) : [];
|
|
46563
|
-
const event =
|
|
46599
|
+
const event = createEvent5("memory_stored", {
|
|
46564
46600
|
project_key: projectKey,
|
|
46565
46601
|
memory_id: result.id,
|
|
46566
46602
|
content_preview: args2.information.slice(0, 100),
|
|
@@ -46568,7 +46604,7 @@ var init_memory_tools = __esm(() => {
|
|
|
46568
46604
|
auto_tagged: args2.autoTag,
|
|
46569
46605
|
collection: args2.collection
|
|
46570
46606
|
});
|
|
46571
|
-
await
|
|
46607
|
+
await appendEvent4(event, projectKey);
|
|
46572
46608
|
} catch (error45) {
|
|
46573
46609
|
console.warn("[semantic_memory_store] Failed to emit memory_stored event:", error45);
|
|
46574
46610
|
}
|
|
@@ -46590,9 +46626,9 @@ var init_memory_tools = __esm(() => {
|
|
|
46590
46626
|
const result = await adapter.find(args2);
|
|
46591
46627
|
const duration3 = Date.now() - startTime;
|
|
46592
46628
|
try {
|
|
46593
|
-
const projectKey =
|
|
46629
|
+
const projectKey = memoryAdapterCache.getCachedPath() || process.cwd();
|
|
46594
46630
|
const topScore = result.results.length > 0 ? result.results[0].score : undefined;
|
|
46595
|
-
const event =
|
|
46631
|
+
const event = createEvent5("memory_found", {
|
|
46596
46632
|
project_key: projectKey,
|
|
46597
46633
|
query: args2.query,
|
|
46598
46634
|
result_count: result.results.length,
|
|
@@ -46600,7 +46636,7 @@ var init_memory_tools = __esm(() => {
|
|
|
46600
46636
|
search_duration_ms: duration3,
|
|
46601
46637
|
used_fts: args2.fts
|
|
46602
46638
|
});
|
|
46603
|
-
await
|
|
46639
|
+
await appendEvent4(event, projectKey);
|
|
46604
46640
|
} catch (error45) {
|
|
46605
46641
|
console.warn("[semantic_memory_find] Failed to emit memory_found event:", error45);
|
|
46606
46642
|
}
|
|
@@ -46628,12 +46664,12 @@ var init_memory_tools = __esm(() => {
|
|
|
46628
46664
|
const result = await adapter.remove(args2);
|
|
46629
46665
|
if (result.success) {
|
|
46630
46666
|
try {
|
|
46631
|
-
const projectKey =
|
|
46632
|
-
const event =
|
|
46667
|
+
const projectKey = memoryAdapterCache.getCachedPath() || process.cwd();
|
|
46668
|
+
const event = createEvent5("memory_deleted", {
|
|
46633
46669
|
project_key: projectKey,
|
|
46634
46670
|
memory_id: args2.id
|
|
46635
46671
|
});
|
|
46636
|
-
await
|
|
46672
|
+
await appendEvent4(event, projectKey);
|
|
46637
46673
|
} catch (error45) {
|
|
46638
46674
|
console.warn("[semantic_memory_remove] Failed to emit memory_deleted event:", error45);
|
|
46639
46675
|
}
|
|
@@ -46651,13 +46687,13 @@ var init_memory_tools = __esm(() => {
|
|
|
46651
46687
|
const result = await adapter.validate(args2);
|
|
46652
46688
|
if (result.success) {
|
|
46653
46689
|
try {
|
|
46654
|
-
const projectKey =
|
|
46655
|
-
const event =
|
|
46690
|
+
const projectKey = memoryAdapterCache.getCachedPath() || process.cwd();
|
|
46691
|
+
const event = createEvent5("memory_validated", {
|
|
46656
46692
|
project_key: projectKey,
|
|
46657
46693
|
memory_id: args2.id,
|
|
46658
46694
|
decay_reset: true
|
|
46659
46695
|
});
|
|
46660
|
-
await
|
|
46696
|
+
await appendEvent4(event, projectKey);
|
|
46661
46697
|
} catch (error45) {
|
|
46662
46698
|
console.warn("[semantic_memory_validate] Failed to emit memory_validated event:", error45);
|
|
46663
46699
|
}
|
|
@@ -46710,14 +46746,14 @@ var init_memory_tools = __esm(() => {
|
|
|
46710
46746
|
const adapter = await getMemoryAdapter();
|
|
46711
46747
|
const result = await adapter.upsert(args2);
|
|
46712
46748
|
try {
|
|
46713
|
-
const projectKey =
|
|
46714
|
-
const event =
|
|
46749
|
+
const projectKey = memoryAdapterCache.getCachedPath() || process.cwd();
|
|
46750
|
+
const event = createEvent5("memory_updated", {
|
|
46715
46751
|
project_key: projectKey,
|
|
46716
46752
|
memory_id: result.memoryId || "unknown",
|
|
46717
46753
|
operation: result.operation,
|
|
46718
46754
|
reason: result.reason
|
|
46719
46755
|
});
|
|
46720
|
-
await
|
|
46756
|
+
await appendEvent4(event, projectKey);
|
|
46721
46757
|
} catch (error45) {
|
|
46722
46758
|
console.warn("[semantic_memory_upsert] Failed to emit memory_updated event:", error45);
|
|
46723
46759
|
}
|
|
@@ -58438,7 +58474,8 @@ var CellUpdateArgsSchema = exports_external.object({
|
|
|
58438
58474
|
});
|
|
58439
58475
|
var CellCloseArgsSchema = exports_external.object({
|
|
58440
58476
|
id: exports_external.string(),
|
|
58441
|
-
reason: exports_external.string().min(1, "Reason required")
|
|
58477
|
+
reason: exports_external.string().min(1, "Reason required"),
|
|
58478
|
+
result: exports_external.string().optional()
|
|
58442
58479
|
});
|
|
58443
58480
|
var CellQueryArgsSchema = exports_external.object({
|
|
58444
58481
|
status: CellStatusSchema.optional(),
|
|
@@ -59040,7 +59077,24 @@ var createBeadEvent = createCellEvent;
|
|
|
59040
59077
|
var isBeadEventType = isCellEventType;
|
|
59041
59078
|
var getBeadIdFromEvent = getCellIdFromEvent;
|
|
59042
59079
|
// src/hive.ts
|
|
59080
|
+
import { createEvent as createEvent2, appendEvent as appendEvent2 } from "swarm-mail";
|
|
59081
|
+
|
|
59082
|
+
// src/utils/event-utils.ts
|
|
59043
59083
|
import { createEvent, appendEvent } from "swarm-mail";
|
|
59084
|
+
async function safeEmitEvent(eventType, data, toolName, projectPath) {
|
|
59085
|
+
try {
|
|
59086
|
+
const effectiveProjectPath = projectPath || process.cwd();
|
|
59087
|
+
const event = createEvent(eventType, {
|
|
59088
|
+
project_key: effectiveProjectPath,
|
|
59089
|
+
...data
|
|
59090
|
+
});
|
|
59091
|
+
await appendEvent(event, effectiveProjectPath);
|
|
59092
|
+
} catch (error45) {
|
|
59093
|
+
console.warn(`[${toolName}] Failed to emit ${eventType} event:`, error45);
|
|
59094
|
+
}
|
|
59095
|
+
}
|
|
59096
|
+
|
|
59097
|
+
// src/hive.ts
|
|
59044
59098
|
var hiveWorkingDirectory = null;
|
|
59045
59099
|
function setHiveWorkingDirectory(directory) {
|
|
59046
59100
|
hiveWorkingDirectory = directory;
|
|
@@ -59208,7 +59262,7 @@ async function importJsonlToPGLite(projectPath) {
|
|
|
59208
59262
|
const status = cellData.status === "tombstone" ? "closed" : cellData.status;
|
|
59209
59263
|
const isClosed = status === "closed";
|
|
59210
59264
|
const closedAt = isClosed ? cellData.closed_at ? new Date(cellData.closed_at).getTime() : new Date(cellData.updated_at).getTime() : null;
|
|
59211
|
-
await db.query(`INSERT INTO
|
|
59265
|
+
await db.query(`INSERT INTO beads (
|
|
59212
59266
|
id, project_key, type, status, title, description, priority,
|
|
59213
59267
|
parent_id, assignee, created_at, updated_at, closed_at
|
|
59214
59268
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)`, [
|
|
@@ -59349,20 +59403,14 @@ var hive_create = tool({
|
|
|
59349
59403
|
parent_id: validated.parent_id
|
|
59350
59404
|
});
|
|
59351
59405
|
await adapter.markDirty(projectKey, cell.id);
|
|
59352
|
-
|
|
59353
|
-
|
|
59354
|
-
|
|
59355
|
-
|
|
59356
|
-
|
|
59357
|
-
|
|
59358
|
-
|
|
59359
|
-
|
|
59360
|
-
parent_id: validated.parent_id
|
|
59361
|
-
});
|
|
59362
|
-
await appendEvent(event, projectKey);
|
|
59363
|
-
} catch (error45) {
|
|
59364
|
-
console.warn("[hive_create] Failed to emit cell_created event:", error45);
|
|
59365
|
-
}
|
|
59406
|
+
await safeEmitEvent("cell_created", {
|
|
59407
|
+
cell_id: cell.id,
|
|
59408
|
+
title: validated.title,
|
|
59409
|
+
description: validated.description,
|
|
59410
|
+
issue_type: validated.type || "task",
|
|
59411
|
+
priority: validated.priority ?? 2,
|
|
59412
|
+
parent_id: validated.parent_id
|
|
59413
|
+
}, "hive_create", projectKey);
|
|
59366
59414
|
const formatted = formatCellForOutput(cell);
|
|
59367
59415
|
return JSON.stringify(formatted, null, 2);
|
|
59368
59416
|
} catch (error45) {
|
|
@@ -59444,53 +59492,35 @@ var hive_create_epic = tool({
|
|
|
59444
59492
|
subtasks: created.slice(1).map((c) => formatCellForOutput(c))
|
|
59445
59493
|
};
|
|
59446
59494
|
const effectiveProjectKey = args.project_key || projectKey;
|
|
59447
|
-
|
|
59448
|
-
|
|
59449
|
-
|
|
59450
|
-
|
|
59451
|
-
|
|
59452
|
-
|
|
59453
|
-
|
|
59454
|
-
|
|
59455
|
-
|
|
59456
|
-
|
|
59457
|
-
|
|
59458
|
-
|
|
59459
|
-
|
|
59460
|
-
|
|
59461
|
-
|
|
59462
|
-
|
|
59463
|
-
|
|
59464
|
-
|
|
59465
|
-
|
|
59466
|
-
|
|
59467
|
-
|
|
59468
|
-
|
|
59469
|
-
|
|
59470
|
-
|
|
59471
|
-
|
|
59472
|
-
|
|
59473
|
-
|
|
59474
|
-
|
|
59475
|
-
|
|
59476
|
-
} catch (error45) {
|
|
59477
|
-
console.warn("[hive_create_epic] Failed to emit DecompositionGeneratedEvent:", error45);
|
|
59478
|
-
}
|
|
59479
|
-
try {
|
|
59480
|
-
const totalFiles = validated.subtasks.reduce((count, st) => count + (st.files?.length || 0), 0);
|
|
59481
|
-
const swarmStartedEvent = createEvent("swarm_started", {
|
|
59482
|
-
project_key: effectiveProjectKey,
|
|
59483
|
-
epic_id: epic.id,
|
|
59484
|
-
epic_title: validated.epic_title,
|
|
59485
|
-
strategy: args.strategy || "feature-based",
|
|
59486
|
-
subtask_count: validated.subtasks.length,
|
|
59487
|
-
total_files: totalFiles,
|
|
59488
|
-
coordinator_agent: "coordinator"
|
|
59489
|
-
});
|
|
59490
|
-
await appendEvent(swarmStartedEvent, effectiveProjectKey);
|
|
59491
|
-
} catch (error45) {
|
|
59492
|
-
console.warn("[hive_create_epic] Failed to emit SwarmStartedEvent:", error45);
|
|
59493
|
-
}
|
|
59495
|
+
await safeEmitEvent("epic_created", {
|
|
59496
|
+
epic_id: epic.id,
|
|
59497
|
+
title: validated.epic_title,
|
|
59498
|
+
description: validated.epic_description,
|
|
59499
|
+
subtask_count: validated.subtasks.length,
|
|
59500
|
+
subtask_ids: created.slice(1).map((c) => c.id)
|
|
59501
|
+
}, "hive_create_epic", effectiveProjectKey);
|
|
59502
|
+
await safeEmitEvent("decomposition_generated", {
|
|
59503
|
+
epic_id: epic.id,
|
|
59504
|
+
task: args.task || validated.epic_title,
|
|
59505
|
+
context: validated.epic_description,
|
|
59506
|
+
strategy: args.strategy || "feature-based",
|
|
59507
|
+
epic_title: validated.epic_title,
|
|
59508
|
+
subtasks: validated.subtasks.map((st) => ({
|
|
59509
|
+
title: st.title,
|
|
59510
|
+
files: st.files || [],
|
|
59511
|
+
priority: st.priority
|
|
59512
|
+
})),
|
|
59513
|
+
recovery_context: args.recovery_context
|
|
59514
|
+
}, "hive_create_epic", effectiveProjectKey);
|
|
59515
|
+
const totalFiles = validated.subtasks.reduce((count, st) => count + (st.files?.length || 0), 0);
|
|
59516
|
+
await safeEmitEvent("swarm_started", {
|
|
59517
|
+
epic_id: epic.id,
|
|
59518
|
+
epic_title: validated.epic_title,
|
|
59519
|
+
strategy: args.strategy || "feature-based",
|
|
59520
|
+
subtask_count: validated.subtasks.length,
|
|
59521
|
+
total_files: totalFiles,
|
|
59522
|
+
coordinator_agent: "coordinator"
|
|
59523
|
+
}, "hive_create_epic", effectiveProjectKey);
|
|
59494
59524
|
try {
|
|
59495
59525
|
const { captureCoordinatorEvent: captureCoordinatorEvent2 } = await Promise.resolve().then(() => (init_eval_capture(), exports_eval_capture));
|
|
59496
59526
|
const filesPerSubtask = {};
|
|
@@ -59621,23 +59651,17 @@ var hive_update = tool({
|
|
|
59621
59651
|
cell = existingCell;
|
|
59622
59652
|
}
|
|
59623
59653
|
await adapter.markDirty(projectKey, cellId);
|
|
59624
|
-
|
|
59625
|
-
|
|
59626
|
-
|
|
59627
|
-
|
|
59628
|
-
|
|
59629
|
-
|
|
59630
|
-
|
|
59631
|
-
|
|
59632
|
-
|
|
59633
|
-
|
|
59634
|
-
|
|
59635
|
-
fields_changed: fieldsChanged
|
|
59636
|
-
});
|
|
59637
|
-
await appendEvent(event, projectKey);
|
|
59638
|
-
} catch (error45) {
|
|
59639
|
-
console.warn("[hive_update] Failed to emit cell_updated event:", error45);
|
|
59640
|
-
}
|
|
59654
|
+
const fieldsChanged = [];
|
|
59655
|
+
if (validated.status)
|
|
59656
|
+
fieldsChanged.push("status");
|
|
59657
|
+
if (validated.description !== undefined)
|
|
59658
|
+
fieldsChanged.push("description");
|
|
59659
|
+
if (validated.priority !== undefined)
|
|
59660
|
+
fieldsChanged.push("priority");
|
|
59661
|
+
await safeEmitEvent("cell_updated", {
|
|
59662
|
+
cell_id: cellId,
|
|
59663
|
+
fields_changed: fieldsChanged
|
|
59664
|
+
}, "hive_update", projectKey);
|
|
59641
59665
|
const formatted = formatCellForOutput(cell);
|
|
59642
59666
|
return JSON.stringify(formatted, null, 2);
|
|
59643
59667
|
} catch (error45) {
|
|
@@ -59656,7 +59680,8 @@ var hive_close = tool({
|
|
|
59656
59680
|
description: "Close a cell with reason",
|
|
59657
59681
|
args: {
|
|
59658
59682
|
id: tool.schema.string().describe("Cell ID or partial hash"),
|
|
59659
|
-
reason: tool.schema.string().describe("Completion reason")
|
|
59683
|
+
reason: tool.schema.string().describe("Completion reason"),
|
|
59684
|
+
result: tool.schema.string().optional().describe("Implementation summary - what was actually done (like a PR description)")
|
|
59660
59685
|
},
|
|
59661
59686
|
async execute(args, ctx) {
|
|
59662
59687
|
const validated = CellCloseArgsSchema.parse(args);
|
|
@@ -59666,11 +59691,10 @@ var hive_close = tool({
|
|
|
59666
59691
|
const cellId = await resolvePartialId(adapter, projectKey, validated.id) || validated.id;
|
|
59667
59692
|
const cellBeforeClose = await adapter.getCell(projectKey, cellId);
|
|
59668
59693
|
const isEpic = cellBeforeClose?.type === "epic";
|
|
59669
|
-
const cell = await adapter.closeCell(projectKey, cellId, validated.reason);
|
|
59694
|
+
const cell = await adapter.closeCell(projectKey, cellId, validated.reason, validated.result ? { result: validated.result } : undefined);
|
|
59670
59695
|
await adapter.markDirty(projectKey, cellId);
|
|
59671
59696
|
if (isEpic && cellBeforeClose) {
|
|
59672
59697
|
try {
|
|
59673
|
-
const { createEvent: createEvent2, appendEvent: appendEvent2 } = await import("swarm-mail");
|
|
59674
59698
|
const subtasks = await adapter.queryCells(projectKey, { parent_id: cellId });
|
|
59675
59699
|
const completedSubtasks = subtasks.filter((st) => st.status === "closed");
|
|
59676
59700
|
const failedSubtasks = subtasks.filter((st) => st.status === "blocked");
|
|
@@ -59708,8 +59732,7 @@ var hive_close = tool({
|
|
|
59708
59732
|
} catch (error45) {
|
|
59709
59733
|
console.warn("[hive_close] Failed to calculate duration:", error45);
|
|
59710
59734
|
}
|
|
59711
|
-
|
|
59712
|
-
project_key: projectKey,
|
|
59735
|
+
await safeEmitEvent("swarm_completed", {
|
|
59713
59736
|
epic_id: cellId,
|
|
59714
59737
|
epic_title: cellBeforeClose.title,
|
|
59715
59738
|
success: failedSubtasks.length === 0,
|
|
@@ -59717,8 +59740,7 @@ var hive_close = tool({
|
|
|
59717
59740
|
subtasks_completed: completedSubtasks.length,
|
|
59718
59741
|
subtasks_failed: failedSubtasks.length,
|
|
59719
59742
|
total_files_touched: totalFilesTouched
|
|
59720
|
-
});
|
|
59721
|
-
await appendEvent2(swarmCompletedEvent, projectKey);
|
|
59743
|
+
}, "hive_close", projectKey);
|
|
59722
59744
|
try {
|
|
59723
59745
|
const { runPostSwarmValidation: runPostSwarmValidation2 } = await Promise.resolve().then(() => (init_swarm_validation(), exports_swarm_validation));
|
|
59724
59746
|
const { readEvents } = await import("swarm-mail");
|
|
@@ -59754,16 +59776,10 @@ var hive_close = tool({
|
|
|
59754
59776
|
console.warn("[hive_close] Failed to emit SwarmCompletedEvent:", error45);
|
|
59755
59777
|
}
|
|
59756
59778
|
}
|
|
59757
|
-
|
|
59758
|
-
|
|
59759
|
-
|
|
59760
|
-
|
|
59761
|
-
reason: validated.reason
|
|
59762
|
-
});
|
|
59763
|
-
await appendEvent(event, projectKey);
|
|
59764
|
-
} catch (error45) {
|
|
59765
|
-
console.warn("[hive_close] Failed to emit cell_closed event:", error45);
|
|
59766
|
-
}
|
|
59779
|
+
await safeEmitEvent("cell_closed", {
|
|
59780
|
+
cell_id: cellId,
|
|
59781
|
+
reason: validated.reason
|
|
59782
|
+
}, "hive_close", projectKey);
|
|
59767
59783
|
return `Closed ${cell.id}: ${validated.reason}`;
|
|
59768
59784
|
} catch (error45) {
|
|
59769
59785
|
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
@@ -59790,13 +59806,13 @@ var hive_start = tool({
|
|
|
59790
59806
|
const cell = await adapter.changeCellStatus(projectKey, cellId, "in_progress");
|
|
59791
59807
|
await adapter.markDirty(projectKey, cellId);
|
|
59792
59808
|
try {
|
|
59793
|
-
const event =
|
|
59809
|
+
const event = createEvent2("cell_status_changed", {
|
|
59794
59810
|
project_key: projectKey,
|
|
59795
59811
|
cell_id: cellId,
|
|
59796
59812
|
old_status: "open",
|
|
59797
59813
|
new_status: "in_progress"
|
|
59798
59814
|
});
|
|
59799
|
-
await
|
|
59815
|
+
await appendEvent2(event, projectKey);
|
|
59800
59816
|
} catch (error45) {
|
|
59801
59817
|
console.warn("[hive_start] Failed to emit cell_status_changed event:", error45);
|
|
59802
59818
|
}
|
|
@@ -59997,12 +60013,12 @@ var hive_sync = tool({
|
|
|
59997
60013
|
pushSuccess = true;
|
|
59998
60014
|
}
|
|
59999
60015
|
try {
|
|
60000
|
-
const event =
|
|
60016
|
+
const event = createEvent2("hive_synced", {
|
|
60001
60017
|
project_key: projectKey,
|
|
60002
60018
|
cells_synced: flushResult.cellsExported,
|
|
60003
60019
|
push_success: pushSuccess
|
|
60004
60020
|
});
|
|
60005
|
-
await
|
|
60021
|
+
await appendEvent2(event, projectKey);
|
|
60006
60022
|
} catch (error45) {
|
|
60007
60023
|
console.warn("[hive_sync] Failed to emit hive_synced event:", error45);
|
|
60008
60024
|
}
|
|
@@ -62155,10 +62171,13 @@ var swarmmail_read_message = tool({
|
|
|
62155
62171
|
}
|
|
62156
62172
|
}
|
|
62157
62173
|
});
|
|
62174
|
+
function normalizePath(path2) {
|
|
62175
|
+
return path2.replace(/\\([[\]()])/g, "$1");
|
|
62176
|
+
}
|
|
62158
62177
|
var swarmmail_reserve = tool({
|
|
62159
|
-
description: "Reserve file paths for exclusive editing. Prevents conflicts with other agents.",
|
|
62178
|
+
description: "Reserve file paths for exclusive editing. Prevents conflicts with other agents. " + "IMPORTANT: Do NOT escape brackets or parentheses - paths like app/(content)/[slug]/page.tsx work as-is.",
|
|
62160
62179
|
args: {
|
|
62161
|
-
paths: tool.schema.array(tool.schema.string()).describe("File paths or glob patterns to reserve"),
|
|
62180
|
+
paths: tool.schema.array(tool.schema.string()).transform((paths) => paths.map(normalizePath)).describe("File paths or glob patterns to reserve. Do NOT escape [ ] ( ) characters."),
|
|
62162
62181
|
reason: tool.schema.string().optional().describe("Reason for reservation (e.g., bead ID)"),
|
|
62163
62182
|
exclusive: tool.schema.boolean().optional().describe("Whether reservation is exclusive (default: true)"),
|
|
62164
62183
|
ttl_seconds: tool.schema.number().optional().describe("Time-to-live in seconds (default: 3600)")
|
|
@@ -62170,10 +62189,11 @@ var swarmmail_reserve = tool({
|
|
|
62170
62189
|
return JSON.stringify({ error: "Session not initialized. Call swarmmail_init first." }, null, 2);
|
|
62171
62190
|
}
|
|
62172
62191
|
try {
|
|
62192
|
+
const normalizedPaths = args.paths.map(normalizePath);
|
|
62173
62193
|
const result = await reserveSwarmFiles({
|
|
62174
62194
|
projectPath: state.projectKey,
|
|
62175
62195
|
agentName: state.agentName,
|
|
62176
|
-
paths:
|
|
62196
|
+
paths: normalizedPaths,
|
|
62177
62197
|
reason: args.reason,
|
|
62178
62198
|
exclusive: args.exclusive ?? true,
|
|
62179
62199
|
ttlSeconds: args.ttl_seconds
|
|
@@ -62201,9 +62221,9 @@ var swarmmail_reserve = tool({
|
|
|
62201
62221
|
}
|
|
62202
62222
|
});
|
|
62203
62223
|
var swarmmail_release = tool({
|
|
62204
|
-
description: "Release file reservations. Call when done editing files.",
|
|
62224
|
+
description: "Release file reservations. Call when done editing files. " + "Do NOT escape brackets or parentheses in paths.",
|
|
62205
62225
|
args: {
|
|
62206
|
-
paths: tool.schema.array(tool.schema.string()).optional().describe("Specific paths to release (releases all if omitted)"),
|
|
62226
|
+
paths: tool.schema.array(tool.schema.string()).optional().describe("Specific paths to release (releases all if omitted). Do NOT escape [ ] ( ) characters."),
|
|
62207
62227
|
reservation_ids: tool.schema.array(tool.schema.number()).optional().describe("Specific reservation IDs to release")
|
|
62208
62228
|
},
|
|
62209
62229
|
async execute(args, ctx) {
|
|
@@ -62214,10 +62234,11 @@ var swarmmail_release = tool({
|
|
|
62214
62234
|
}
|
|
62215
62235
|
try {
|
|
62216
62236
|
const currentReservations = await getActiveReservations(state.projectKey, state.projectKey, state.agentName);
|
|
62237
|
+
const normalizedPaths = args.paths?.map(normalizePath);
|
|
62217
62238
|
const result = await releaseSwarmFiles({
|
|
62218
62239
|
projectPath: state.projectKey,
|
|
62219
62240
|
agentName: state.agentName,
|
|
62220
|
-
paths:
|
|
62241
|
+
paths: normalizedPaths,
|
|
62221
62242
|
reservationIds: args.reservation_ids
|
|
62222
62243
|
});
|
|
62223
62244
|
if (!args.paths && !args.reservation_ids) {
|
|
@@ -65110,8 +65131,8 @@ import {
|
|
|
65110
65131
|
releaseSwarmFiles as releaseSwarmFiles2,
|
|
65111
65132
|
sendSwarmMessage as sendSwarmMessage3,
|
|
65112
65133
|
getAgent,
|
|
65113
|
-
createEvent as
|
|
65114
|
-
appendEvent as
|
|
65134
|
+
createEvent as createEvent4,
|
|
65135
|
+
appendEvent as appendEvent3,
|
|
65115
65136
|
getSwarmMailLibSQL as getSwarmMailLibSQL4
|
|
65116
65137
|
} from "swarm-mail";
|
|
65117
65138
|
init_skills();
|
|
@@ -65616,15 +65637,15 @@ var swarm_review = tool({
|
|
|
65616
65637
|
downstream_tasks: downstreamTasks.length > 0 ? downstreamTasks : undefined
|
|
65617
65638
|
});
|
|
65618
65639
|
try {
|
|
65619
|
-
const { createEvent:
|
|
65640
|
+
const { createEvent: createEvent4, appendEvent: appendEvent3 } = await import("swarm-mail");
|
|
65620
65641
|
const attempt = getReviewStatus(args.task_id).attempt_count || 1;
|
|
65621
|
-
const reviewStartedEvent =
|
|
65642
|
+
const reviewStartedEvent = createEvent4("review_started", {
|
|
65622
65643
|
project_key: args.project_key,
|
|
65623
65644
|
epic_id: args.epic_id,
|
|
65624
65645
|
bead_id: args.task_id,
|
|
65625
65646
|
attempt
|
|
65626
65647
|
});
|
|
65627
|
-
await
|
|
65648
|
+
await appendEvent3(reviewStartedEvent, args.project_key);
|
|
65628
65649
|
} catch (error45) {
|
|
65629
65650
|
console.warn("[swarm_review] Failed to emit ReviewStartedEvent:", error45);
|
|
65630
65651
|
}
|
|
@@ -65707,16 +65728,16 @@ var swarm_review_feedback = tool({
|
|
|
65707
65728
|
console.warn("[swarm_review_feedback] Failed to trace review_decision:", error45);
|
|
65708
65729
|
}
|
|
65709
65730
|
try {
|
|
65710
|
-
const { createEvent:
|
|
65731
|
+
const { createEvent: createEvent4, appendEvent: appendEvent3 } = await import("swarm-mail");
|
|
65711
65732
|
const attempt = getReviewStatus(args.task_id).attempt_count || 1;
|
|
65712
|
-
const reviewCompletedEvent =
|
|
65733
|
+
const reviewCompletedEvent = createEvent4("review_completed", {
|
|
65713
65734
|
project_key: args.project_key,
|
|
65714
65735
|
epic_id: epicId,
|
|
65715
65736
|
bead_id: args.task_id,
|
|
65716
65737
|
status: "approved",
|
|
65717
65738
|
attempt
|
|
65718
65739
|
});
|
|
65719
|
-
await
|
|
65740
|
+
await appendEvent3(reviewCompletedEvent, args.project_key);
|
|
65720
65741
|
} catch (error45) {
|
|
65721
65742
|
console.warn("[swarm_review_feedback] Failed to emit ReviewCompletedEvent:", error45);
|
|
65722
65743
|
}
|
|
@@ -65778,16 +65799,16 @@ You may now complete the task with \`swarm_complete\`.`,
|
|
|
65778
65799
|
console.warn("[swarm_review_feedback] Failed to trace review_decision:", error45);
|
|
65779
65800
|
}
|
|
65780
65801
|
try {
|
|
65781
|
-
const { createEvent:
|
|
65802
|
+
const { createEvent: createEvent4, appendEvent: appendEvent3 } = await import("swarm-mail");
|
|
65782
65803
|
const status = remaining <= 0 ? "blocked" : "needs_changes";
|
|
65783
|
-
const reviewCompletedEvent =
|
|
65804
|
+
const reviewCompletedEvent = createEvent4("review_completed", {
|
|
65784
65805
|
project_key: args.project_key,
|
|
65785
65806
|
epic_id: epicId,
|
|
65786
65807
|
bead_id: args.task_id,
|
|
65787
65808
|
status,
|
|
65788
65809
|
attempt: attemptNumber
|
|
65789
65810
|
});
|
|
65790
|
-
await
|
|
65811
|
+
await appendEvent3(reviewCompletedEvent, args.project_key);
|
|
65791
65812
|
} catch (error45) {
|
|
65792
65813
|
console.warn("[swarm_review_feedback] Failed to emit ReviewCompletedEvent:", error45);
|
|
65793
65814
|
}
|
|
@@ -65845,8 +65866,200 @@ var reviewTools = {
|
|
|
65845
65866
|
swarm_review_feedback
|
|
65846
65867
|
};
|
|
65847
65868
|
|
|
65869
|
+
// src/utils/git-commit-info.ts
|
|
65870
|
+
import { execSync } from "child_process";
|
|
65871
|
+
function getGitCommitInfo(cwd) {
|
|
65872
|
+
try {
|
|
65873
|
+
const opts = { cwd, encoding: "utf-8", timeout: 5000 };
|
|
65874
|
+
const sha = execSync("git rev-parse HEAD", opts).trim();
|
|
65875
|
+
const message = execSync("git log -1 --format=%s", opts).trim();
|
|
65876
|
+
const branch = execSync("git rev-parse --abbrev-ref HEAD", opts).trim();
|
|
65877
|
+
return { sha, message, branch };
|
|
65878
|
+
} catch {
|
|
65879
|
+
return null;
|
|
65880
|
+
}
|
|
65881
|
+
}
|
|
65882
|
+
|
|
65848
65883
|
// src/swarm-orchestrate.ts
|
|
65849
65884
|
init_eval_capture();
|
|
65885
|
+
|
|
65886
|
+
// src/swarm-verify.ts
|
|
65887
|
+
init_dist();
|
|
65888
|
+
async function runTypecheckVerification() {
|
|
65889
|
+
const step = {
|
|
65890
|
+
name: "typecheck",
|
|
65891
|
+
command: "tsc --noEmit",
|
|
65892
|
+
passed: false,
|
|
65893
|
+
exitCode: -1
|
|
65894
|
+
};
|
|
65895
|
+
try {
|
|
65896
|
+
const tsconfigExists = await Bun.file("tsconfig.json").exists();
|
|
65897
|
+
if (!tsconfigExists) {
|
|
65898
|
+
step.skipped = true;
|
|
65899
|
+
step.skipReason = "No tsconfig.json found";
|
|
65900
|
+
step.passed = true;
|
|
65901
|
+
return step;
|
|
65902
|
+
}
|
|
65903
|
+
const result = await Bun.$`tsc --noEmit`.quiet().nothrow();
|
|
65904
|
+
step.exitCode = result.exitCode;
|
|
65905
|
+
step.passed = result.exitCode === 0;
|
|
65906
|
+
if (!step.passed) {
|
|
65907
|
+
step.error = result.stderr.toString().slice(0, 1000);
|
|
65908
|
+
step.output = result.stdout.toString().slice(0, 1000);
|
|
65909
|
+
}
|
|
65910
|
+
} catch (error45) {
|
|
65911
|
+
step.skipped = true;
|
|
65912
|
+
step.skipReason = `tsc not available: ${error45 instanceof Error ? error45.message : String(error45)}`;
|
|
65913
|
+
step.passed = true;
|
|
65914
|
+
}
|
|
65915
|
+
return step;
|
|
65916
|
+
}
|
|
65917
|
+
async function runTestVerification(filesTouched) {
|
|
65918
|
+
const step = {
|
|
65919
|
+
name: "tests",
|
|
65920
|
+
command: "bun test <related-files>",
|
|
65921
|
+
passed: false,
|
|
65922
|
+
exitCode: -1
|
|
65923
|
+
};
|
|
65924
|
+
if (filesTouched.length === 0) {
|
|
65925
|
+
step.skipped = true;
|
|
65926
|
+
step.skipReason = "No files touched";
|
|
65927
|
+
step.passed = true;
|
|
65928
|
+
return step;
|
|
65929
|
+
}
|
|
65930
|
+
const testPatterns = [];
|
|
65931
|
+
for (const file2 of filesTouched) {
|
|
65932
|
+
if (file2.includes(".test.") || file2.includes(".spec.")) {
|
|
65933
|
+
testPatterns.push(file2);
|
|
65934
|
+
continue;
|
|
65935
|
+
}
|
|
65936
|
+
const baseName = file2.replace(/\.(ts|tsx|js|jsx)$/, "");
|
|
65937
|
+
testPatterns.push(`${baseName}.test.ts`);
|
|
65938
|
+
testPatterns.push(`${baseName}.test.tsx`);
|
|
65939
|
+
testPatterns.push(`${baseName}.spec.ts`);
|
|
65940
|
+
}
|
|
65941
|
+
const existingTests = [];
|
|
65942
|
+
for (const pattern of testPatterns) {
|
|
65943
|
+
try {
|
|
65944
|
+
const exists = await Bun.file(pattern).exists();
|
|
65945
|
+
if (exists) {
|
|
65946
|
+
existingTests.push(pattern);
|
|
65947
|
+
}
|
|
65948
|
+
} catch {}
|
|
65949
|
+
}
|
|
65950
|
+
if (existingTests.length === 0) {
|
|
65951
|
+
step.skipped = true;
|
|
65952
|
+
step.skipReason = "No related test files found";
|
|
65953
|
+
step.passed = true;
|
|
65954
|
+
return step;
|
|
65955
|
+
}
|
|
65956
|
+
try {
|
|
65957
|
+
step.command = `bun test ${existingTests.join(" ")}`;
|
|
65958
|
+
const result = await Bun.$`bun test ${existingTests}`.quiet().nothrow();
|
|
65959
|
+
step.exitCode = result.exitCode;
|
|
65960
|
+
step.passed = result.exitCode === 0;
|
|
65961
|
+
if (!step.passed) {
|
|
65962
|
+
step.error = result.stderr.toString().slice(0, 1000);
|
|
65963
|
+
step.output = result.stdout.toString().slice(0, 1000);
|
|
65964
|
+
}
|
|
65965
|
+
} catch (error45) {
|
|
65966
|
+
step.skipped = true;
|
|
65967
|
+
step.skipReason = `Test runner failed: ${error45 instanceof Error ? error45.message : String(error45)}`;
|
|
65968
|
+
step.passed = true;
|
|
65969
|
+
}
|
|
65970
|
+
return step;
|
|
65971
|
+
}
|
|
65972
|
+
async function runVerificationGate(filesTouched, _skipUbs = false) {
|
|
65973
|
+
const steps = [];
|
|
65974
|
+
const blockers = [];
|
|
65975
|
+
const typecheckStep = await runTypecheckVerification();
|
|
65976
|
+
steps.push(typecheckStep);
|
|
65977
|
+
if (!typecheckStep.passed && !typecheckStep.skipped) {
|
|
65978
|
+
blockers.push(`Typecheck failed: ${typecheckStep.error?.slice(0, 100) || "type errors found"}. Try: Run 'tsc --noEmit' to see full errors, check tsconfig.json configuration, or fix reported type errors in modified files.`);
|
|
65979
|
+
}
|
|
65980
|
+
const testStep = await runTestVerification(filesTouched);
|
|
65981
|
+
steps.push(testStep);
|
|
65982
|
+
if (!testStep.passed && !testStep.skipped) {
|
|
65983
|
+
blockers.push(`Tests failed: ${testStep.error?.slice(0, 100) || "test failures"}. Try: Run 'bun test ${testStep.command.split(" ").slice(2).join(" ")}' to see full output, check test assertions, or fix failing tests in modified files.`);
|
|
65984
|
+
}
|
|
65985
|
+
const passedCount = steps.filter((s) => s.passed).length;
|
|
65986
|
+
const skippedCount = steps.filter((s) => s.skipped).length;
|
|
65987
|
+
const failedCount = steps.filter((s) => !s.passed && !s.skipped).length;
|
|
65988
|
+
const summary = failedCount === 0 ? `Verification passed: ${passedCount} checks passed, ${skippedCount} skipped` : `Verification FAILED: ${failedCount} checks failed, ${passedCount} passed, ${skippedCount} skipped`;
|
|
65989
|
+
return {
|
|
65990
|
+
passed: failedCount === 0,
|
|
65991
|
+
steps,
|
|
65992
|
+
summary,
|
|
65993
|
+
blockers
|
|
65994
|
+
};
|
|
65995
|
+
}
|
|
65996
|
+
var swarm_verify = tool({
|
|
65997
|
+
description: "Run verification gate (typecheck + tests) for files. Returns verification results without blocking. Used by swarm_complete to verify worker output.",
|
|
65998
|
+
args: {
|
|
65999
|
+
files_touched: tool.schema.array(tool.schema.string()).describe("Files to verify (typecheck + test discovery)"),
|
|
66000
|
+
skip_verification: tool.schema.boolean().optional().describe("Skip verification entirely (default: false)")
|
|
66001
|
+
},
|
|
66002
|
+
async execute(args) {
|
|
66003
|
+
try {
|
|
66004
|
+
if (args.skip_verification) {
|
|
66005
|
+
return JSON.stringify({
|
|
66006
|
+
success: true,
|
|
66007
|
+
data: {
|
|
66008
|
+
passed: true,
|
|
66009
|
+
skipped: true,
|
|
66010
|
+
reason: "skip_verification=true",
|
|
66011
|
+
summary: "Verification skipped by request",
|
|
66012
|
+
steps: [],
|
|
66013
|
+
blockers: []
|
|
66014
|
+
}
|
|
66015
|
+
}, null, 2);
|
|
66016
|
+
}
|
|
66017
|
+
if (!args.files_touched || args.files_touched.length === 0) {
|
|
66018
|
+
return JSON.stringify({
|
|
66019
|
+
success: true,
|
|
66020
|
+
data: {
|
|
66021
|
+
passed: true,
|
|
66022
|
+
skipped: true,
|
|
66023
|
+
reason: "no files_touched provided",
|
|
66024
|
+
summary: "No files to verify",
|
|
66025
|
+
steps: [],
|
|
66026
|
+
blockers: []
|
|
66027
|
+
}
|
|
66028
|
+
}, null, 2);
|
|
66029
|
+
}
|
|
66030
|
+
const result = await runVerificationGate(args.files_touched, false);
|
|
66031
|
+
return JSON.stringify({
|
|
66032
|
+
success: true,
|
|
66033
|
+
data: {
|
|
66034
|
+
passed: result.passed,
|
|
66035
|
+
skipped: false,
|
|
66036
|
+
summary: result.summary,
|
|
66037
|
+
steps: result.steps.map((s) => ({
|
|
66038
|
+
name: s.name,
|
|
66039
|
+
command: s.command,
|
|
66040
|
+
passed: s.passed,
|
|
66041
|
+
exitCode: s.exitCode,
|
|
66042
|
+
skipped: s.skipped,
|
|
66043
|
+
skipReason: s.skipReason,
|
|
66044
|
+
error: s.error?.slice(0, 200),
|
|
66045
|
+
output: s.output?.slice(0, 200)
|
|
66046
|
+
})),
|
|
66047
|
+
blockers: result.blockers
|
|
66048
|
+
}
|
|
66049
|
+
}, null, 2);
|
|
66050
|
+
} catch (error45) {
|
|
66051
|
+
return JSON.stringify({
|
|
66052
|
+
success: false,
|
|
66053
|
+
error: `Verification failed: ${error45 instanceof Error ? error45.message : String(error45)}`
|
|
66054
|
+
}, null, 2);
|
|
66055
|
+
}
|
|
66056
|
+
}
|
|
66057
|
+
});
|
|
66058
|
+
var verificationTools = {
|
|
66059
|
+
swarm_verify
|
|
66060
|
+
};
|
|
66061
|
+
|
|
66062
|
+
// src/swarm-orchestrate.ts
|
|
65850
66063
|
function generateWorkerHandoff(params) {
|
|
65851
66064
|
const handoff = {
|
|
65852
66065
|
contract: {
|
|
@@ -65988,114 +66201,6 @@ ${progress.blockers.map((b) => `- ${b}`).join(`
|
|
|
65988
66201
|
|
|
65989
66202
|
`);
|
|
65990
66203
|
}
|
|
65991
|
-
async function runTypecheckVerification() {
|
|
65992
|
-
const step = {
|
|
65993
|
-
name: "typecheck",
|
|
65994
|
-
command: "tsc --noEmit",
|
|
65995
|
-
passed: false,
|
|
65996
|
-
exitCode: -1
|
|
65997
|
-
};
|
|
65998
|
-
try {
|
|
65999
|
-
const tsconfigExists = await Bun.file("tsconfig.json").exists();
|
|
66000
|
-
if (!tsconfigExists) {
|
|
66001
|
-
step.skipped = true;
|
|
66002
|
-
step.skipReason = "No tsconfig.json found";
|
|
66003
|
-
step.passed = true;
|
|
66004
|
-
return step;
|
|
66005
|
-
}
|
|
66006
|
-
const result = await Bun.$`tsc --noEmit`.quiet().nothrow();
|
|
66007
|
-
step.exitCode = result.exitCode;
|
|
66008
|
-
step.passed = result.exitCode === 0;
|
|
66009
|
-
if (!step.passed) {
|
|
66010
|
-
step.error = result.stderr.toString().slice(0, 1000);
|
|
66011
|
-
step.output = result.stdout.toString().slice(0, 1000);
|
|
66012
|
-
}
|
|
66013
|
-
} catch (error45) {
|
|
66014
|
-
step.skipped = true;
|
|
66015
|
-
step.skipReason = `tsc not available: ${error45 instanceof Error ? error45.message : String(error45)}`;
|
|
66016
|
-
step.passed = true;
|
|
66017
|
-
}
|
|
66018
|
-
return step;
|
|
66019
|
-
}
|
|
66020
|
-
async function runTestVerification(filesTouched) {
|
|
66021
|
-
const step = {
|
|
66022
|
-
name: "tests",
|
|
66023
|
-
command: "bun test <related-files>",
|
|
66024
|
-
passed: false,
|
|
66025
|
-
exitCode: -1
|
|
66026
|
-
};
|
|
66027
|
-
if (filesTouched.length === 0) {
|
|
66028
|
-
step.skipped = true;
|
|
66029
|
-
step.skipReason = "No files touched";
|
|
66030
|
-
step.passed = true;
|
|
66031
|
-
return step;
|
|
66032
|
-
}
|
|
66033
|
-
const testPatterns = [];
|
|
66034
|
-
for (const file2 of filesTouched) {
|
|
66035
|
-
if (file2.includes(".test.") || file2.includes(".spec.")) {
|
|
66036
|
-
testPatterns.push(file2);
|
|
66037
|
-
continue;
|
|
66038
|
-
}
|
|
66039
|
-
const baseName = file2.replace(/\.(ts|tsx|js|jsx)$/, "");
|
|
66040
|
-
testPatterns.push(`${baseName}.test.ts`);
|
|
66041
|
-
testPatterns.push(`${baseName}.test.tsx`);
|
|
66042
|
-
testPatterns.push(`${baseName}.spec.ts`);
|
|
66043
|
-
}
|
|
66044
|
-
const existingTests = [];
|
|
66045
|
-
for (const pattern of testPatterns) {
|
|
66046
|
-
try {
|
|
66047
|
-
const exists = await Bun.file(pattern).exists();
|
|
66048
|
-
if (exists) {
|
|
66049
|
-
existingTests.push(pattern);
|
|
66050
|
-
}
|
|
66051
|
-
} catch {}
|
|
66052
|
-
}
|
|
66053
|
-
if (existingTests.length === 0) {
|
|
66054
|
-
step.skipped = true;
|
|
66055
|
-
step.skipReason = "No related test files found";
|
|
66056
|
-
step.passed = true;
|
|
66057
|
-
return step;
|
|
66058
|
-
}
|
|
66059
|
-
try {
|
|
66060
|
-
step.command = `bun test ${existingTests.join(" ")}`;
|
|
66061
|
-
const result = await Bun.$`bun test ${existingTests}`.quiet().nothrow();
|
|
66062
|
-
step.exitCode = result.exitCode;
|
|
66063
|
-
step.passed = result.exitCode === 0;
|
|
66064
|
-
if (!step.passed) {
|
|
66065
|
-
step.error = result.stderr.toString().slice(0, 1000);
|
|
66066
|
-
step.output = result.stdout.toString().slice(0, 1000);
|
|
66067
|
-
}
|
|
66068
|
-
} catch (error45) {
|
|
66069
|
-
step.skipped = true;
|
|
66070
|
-
step.skipReason = `Test runner failed: ${error45 instanceof Error ? error45.message : String(error45)}`;
|
|
66071
|
-
step.passed = true;
|
|
66072
|
-
}
|
|
66073
|
-
return step;
|
|
66074
|
-
}
|
|
66075
|
-
async function runVerificationGate(filesTouched, _skipUbs = false) {
|
|
66076
|
-
const steps = [];
|
|
66077
|
-
const blockers = [];
|
|
66078
|
-
const typecheckStep = await runTypecheckVerification();
|
|
66079
|
-
steps.push(typecheckStep);
|
|
66080
|
-
if (!typecheckStep.passed && !typecheckStep.skipped) {
|
|
66081
|
-
blockers.push(`Typecheck failed: ${typecheckStep.error?.slice(0, 100) || "type errors found"}. Try: Run 'tsc --noEmit' to see full errors, check tsconfig.json configuration, or fix reported type errors in modified files.`);
|
|
66082
|
-
}
|
|
66083
|
-
const testStep = await runTestVerification(filesTouched);
|
|
66084
|
-
steps.push(testStep);
|
|
66085
|
-
if (!testStep.passed && !testStep.skipped) {
|
|
66086
|
-
blockers.push(`Tests failed: ${testStep.error?.slice(0, 100) || "test failures"}. Try: Run 'bun test ${testStep.command.split(" ").slice(2).join(" ")}' to see full output, check test assertions, or fix failing tests in modified files.`);
|
|
66087
|
-
}
|
|
66088
|
-
const passedCount = steps.filter((s) => s.passed).length;
|
|
66089
|
-
const skippedCount = steps.filter((s) => s.skipped).length;
|
|
66090
|
-
const failedCount = steps.filter((s) => !s.passed && !s.skipped).length;
|
|
66091
|
-
const summary = failedCount === 0 ? `Verification passed: ${passedCount} checks passed, ${skippedCount} skipped` : `Verification FAILED: ${failedCount} checks failed, ${passedCount} passed, ${skippedCount} skipped`;
|
|
66092
|
-
return {
|
|
66093
|
-
passed: failedCount === 0,
|
|
66094
|
-
steps,
|
|
66095
|
-
summary,
|
|
66096
|
-
blockers
|
|
66097
|
-
};
|
|
66098
|
-
}
|
|
66099
66204
|
function classifyFailure(error45) {
|
|
66100
66205
|
const msg = (typeof error45 === "string" ? error45 : error45.message).toLowerCase();
|
|
66101
66206
|
if (msg.includes("timeout"))
|
|
@@ -66357,15 +66462,15 @@ var swarm_progress = tool({
|
|
|
66357
66462
|
}
|
|
66358
66463
|
};
|
|
66359
66464
|
const checkpointData = JSON.stringify(checkpoint);
|
|
66360
|
-
const checkpointEvent =
|
|
66465
|
+
const checkpointEvent = createEvent4("swarm_checkpointed", {
|
|
66361
66466
|
project_key: args.project_key,
|
|
66362
66467
|
...checkpoint,
|
|
66363
66468
|
checkpoint_size_bytes: Buffer.byteLength(checkpointData, "utf8"),
|
|
66364
66469
|
trigger: "progress"
|
|
66365
66470
|
});
|
|
66366
|
-
await
|
|
66471
|
+
await appendEvent3(checkpointEvent, args.project_key);
|
|
66367
66472
|
const checkpointId = `ckpt-${Date.now()}-${args.bead_id}`;
|
|
66368
|
-
const createdEvent =
|
|
66473
|
+
const createdEvent = createEvent4("checkpoint_created", {
|
|
66369
66474
|
project_key: args.project_key,
|
|
66370
66475
|
epic_id: epicId,
|
|
66371
66476
|
bead_id: args.bead_id,
|
|
@@ -66375,7 +66480,7 @@ var swarm_progress = tool({
|
|
|
66375
66480
|
progress_percent: args.progress_percent,
|
|
66376
66481
|
files_snapshot: args.files_touched
|
|
66377
66482
|
});
|
|
66378
|
-
await
|
|
66483
|
+
await appendEvent3(createdEvent, args.project_key);
|
|
66379
66484
|
checkpointCreated = true;
|
|
66380
66485
|
} catch (error45) {
|
|
66381
66486
|
console.warn(`[swarm_progress] Auto-checkpoint failed at ${args.progress_percent}%:`, error45);
|
|
@@ -66446,7 +66551,10 @@ var swarm_complete = tool({
|
|
|
66446
66551
|
start_time: tool.schema.number().describe("Task start timestamp (Unix ms) for duration calculation - REQUIRED for accurate analytics"),
|
|
66447
66552
|
error_count: tool.schema.number().optional().describe("Number of errors encountered during task"),
|
|
66448
66553
|
retry_count: tool.schema.number().optional().describe("Number of retry attempts during task"),
|
|
66449
|
-
skip_review: tool.schema.boolean().optional().describe("Skip review gate check (default: false). Use only for tasks that don't require coordinator review.")
|
|
66554
|
+
skip_review: tool.schema.boolean().optional().describe("Skip review gate check (default: false). Use only for tasks that don't require coordinator review."),
|
|
66555
|
+
commit_sha: tool.schema.string().optional().describe("Git commit SHA (auto-detected if not provided)"),
|
|
66556
|
+
commit_message: tool.schema.string().optional().describe("Commit message (auto-detected if not provided)"),
|
|
66557
|
+
commit_branch: tool.schema.string().optional().describe("Git branch (auto-detected if not provided)")
|
|
66450
66558
|
},
|
|
66451
66559
|
async execute(args, _ctx) {
|
|
66452
66560
|
const missing = [];
|
|
@@ -66507,6 +66615,13 @@ var swarm_complete = tool({
|
|
|
66507
66615
|
}, null, 2);
|
|
66508
66616
|
}
|
|
66509
66617
|
}
|
|
66618
|
+
const gitInfo = getGitCommitInfo(args.project_key) || {};
|
|
66619
|
+
const commitSha = args.commit_sha || gitInfo.sha;
|
|
66620
|
+
const commitMessage = args.commit_message || gitInfo.message;
|
|
66621
|
+
const commitBranch = args.commit_branch || gitInfo.branch;
|
|
66622
|
+
const resultText = commitSha ? `${args.summary}
|
|
66623
|
+
|
|
66624
|
+
Commit: ${commitSha.slice(0, 8)} (${commitBranch || "unknown"}) - ${commitMessage || "no message"}` : args.summary;
|
|
66510
66625
|
try {
|
|
66511
66626
|
const adapter = await getHiveAdapter(args.project_key);
|
|
66512
66627
|
const cell = await adapter.getCell(args.project_key, args.bead_id);
|
|
@@ -66621,7 +66736,9 @@ This will be recorded as a negative learning signal.`;
|
|
|
66621
66736
|
}
|
|
66622
66737
|
}
|
|
66623
66738
|
try {
|
|
66624
|
-
await adapter.closeCell(args.project_key, args.bead_id, args.summary
|
|
66739
|
+
await adapter.closeCell(args.project_key, args.bead_id, args.summary, {
|
|
66740
|
+
result: resultText
|
|
66741
|
+
});
|
|
66625
66742
|
} catch (closeError) {
|
|
66626
66743
|
const errorMessage = closeError instanceof Error ? closeError.message : String(closeError);
|
|
66627
66744
|
return JSON.stringify({
|
|
@@ -66678,7 +66795,7 @@ This will be recorded as a negative learning signal.`;
|
|
|
66678
66795
|
const eventEpicId = cell.parent_id || (args.bead_id.includes(".") ? args.bead_id.split(".")[0] : args.bead_id);
|
|
66679
66796
|
let outcomeEventId;
|
|
66680
66797
|
try {
|
|
66681
|
-
const event =
|
|
66798
|
+
const event = createEvent4("subtask_outcome", {
|
|
66682
66799
|
project_key: args.project_key,
|
|
66683
66800
|
epic_id: eventEpicId,
|
|
66684
66801
|
bead_id: args.bead_id,
|
|
@@ -66689,9 +66806,10 @@ This will be recorded as a negative learning signal.`;
|
|
|
66689
66806
|
retry_count: args.retry_count || 0,
|
|
66690
66807
|
success: true,
|
|
66691
66808
|
scope_violation: contractValidation ? !contractValidation.valid : undefined,
|
|
66692
|
-
violation_files: contractValidation?.violations
|
|
66809
|
+
violation_files: contractValidation?.violations,
|
|
66810
|
+
commit: commitSha ? { sha: commitSha, message: commitMessage, branch: commitBranch } : undefined
|
|
66693
66811
|
});
|
|
66694
|
-
const savedEvent = await
|
|
66812
|
+
const savedEvent = await appendEvent3(event, args.project_key);
|
|
66695
66813
|
outcomeEventId = savedEvent.id;
|
|
66696
66814
|
} catch (error45) {
|
|
66697
66815
|
console.warn("[swarm_complete] Failed to emit SubtaskOutcomeEvent:", error45);
|
|
@@ -66709,7 +66827,7 @@ This will be recorded as a negative learning signal.`;
|
|
|
66709
66827
|
}
|
|
66710
66828
|
}
|
|
66711
66829
|
try {
|
|
66712
|
-
const workerCompletedEvent =
|
|
66830
|
+
const workerCompletedEvent = createEvent4("worker_completed", {
|
|
66713
66831
|
project_key: args.project_key,
|
|
66714
66832
|
epic_id: eventEpicId,
|
|
66715
66833
|
bead_id: args.bead_id,
|
|
@@ -66718,7 +66836,7 @@ This will be recorded as a negative learning signal.`;
|
|
|
66718
66836
|
duration_ms: completionDurationMs,
|
|
66719
66837
|
files_touched: args.files_touched || []
|
|
66720
66838
|
});
|
|
66721
|
-
await
|
|
66839
|
+
await appendEvent3(workerCompletedEvent, args.project_key);
|
|
66722
66840
|
} catch (error45) {
|
|
66723
66841
|
console.warn("[swarm_complete] Failed to emit worker_completed event:", error45);
|
|
66724
66842
|
}
|
|
@@ -66874,6 +66992,8 @@ This will be recorded as a negative learning signal.`;
|
|
|
66874
66992
|
success: true,
|
|
66875
66993
|
bead_id: args.bead_id,
|
|
66876
66994
|
closed: true,
|
|
66995
|
+
result: resultText,
|
|
66996
|
+
commit: commitSha ? { sha: commitSha, message: commitMessage, branch: commitBranch } : undefined,
|
|
66877
66997
|
reservations_released: reservationsReleased,
|
|
66878
66998
|
reservations_released_count: reservationsReleasedCount,
|
|
66879
66999
|
reservations_release_error: reservationsReleaseError,
|
|
@@ -67442,7 +67562,7 @@ var swarm_checkpoint = tool({
|
|
|
67442
67562
|
}
|
|
67443
67563
|
};
|
|
67444
67564
|
const checkpointData = JSON.stringify(checkpoint);
|
|
67445
|
-
const event =
|
|
67565
|
+
const event = createEvent4("swarm_checkpointed", {
|
|
67446
67566
|
project_key: args.project_key,
|
|
67447
67567
|
epic_id: args.epic_id,
|
|
67448
67568
|
bead_id: args.bead_id,
|
|
@@ -67454,7 +67574,7 @@ var swarm_checkpoint = tool({
|
|
|
67454
67574
|
checkpoint_size_bytes: Buffer.byteLength(checkpointData, "utf8"),
|
|
67455
67575
|
trigger: args.error_context ? "error" : "manual"
|
|
67456
67576
|
});
|
|
67457
|
-
await
|
|
67577
|
+
await appendEvent3(event, args.project_key);
|
|
67458
67578
|
const now = Date.now();
|
|
67459
67579
|
return JSON.stringify({
|
|
67460
67580
|
success: true,
|
|
@@ -67512,13 +67632,13 @@ var swarm_recover = tool({
|
|
|
67512
67632
|
created_at: row.created_at,
|
|
67513
67633
|
updated_at: row.updated_at
|
|
67514
67634
|
};
|
|
67515
|
-
const event =
|
|
67635
|
+
const event = createEvent4("swarm_recovered", {
|
|
67516
67636
|
project_key: args.project_key,
|
|
67517
67637
|
epic_id: args.epic_id,
|
|
67518
67638
|
bead_id: context.bead_id,
|
|
67519
67639
|
recovered_from_checkpoint: context.recovery.last_checkpoint
|
|
67520
67640
|
});
|
|
67521
|
-
await
|
|
67641
|
+
await appendEvent3(event, args.project_key);
|
|
67522
67642
|
return JSON.stringify({
|
|
67523
67643
|
found: true,
|
|
67524
67644
|
context,
|
|
@@ -67939,6 +68059,27 @@ swarmmail_reserve(
|
|
|
67939
68059
|
|
|
67940
68060
|
**Workers reserve their own files.** This prevents edit conflicts with other agents.
|
|
67941
68061
|
|
|
68062
|
+
### ⚠️ CRITICAL: File Path Handling (Next.js/Special Characters)
|
|
68063
|
+
|
|
68064
|
+
**DO NOT escape brackets or parentheses in file paths!**
|
|
68065
|
+
|
|
68066
|
+
When working with Next.js App Router or any codebase with special characters in paths:
|
|
68067
|
+
|
|
68068
|
+
❌ **WRONG** (will fail):
|
|
68069
|
+
\`\`\`
|
|
68070
|
+
Read: app/\\(content\\)/events/\\[slug\\]/page.tsx
|
|
68071
|
+
Glob: src/**/\\[id\\]/**/*.ts
|
|
68072
|
+
\`\`\`
|
|
68073
|
+
|
|
68074
|
+
✅ **CORRECT** (use raw paths):
|
|
68075
|
+
\`\`\`
|
|
68076
|
+
Read: app/(content)/events/[slug]/page.tsx
|
|
68077
|
+
Glob: src/**/[id]/**/*.ts
|
|
68078
|
+
\`\`\`
|
|
68079
|
+
|
|
68080
|
+
**The Read and Glob tools handle special characters automatically.**
|
|
68081
|
+
Never add backslashes before \`[\`, \`]\`, \`(\`, or \`)\` in file paths.
|
|
68082
|
+
|
|
67942
68083
|
### Step 5: Do the Work (TDD MANDATORY)
|
|
67943
68084
|
|
|
67944
68085
|
**Follow RED → GREEN → REFACTOR. No exceptions.**
|
|
@@ -68701,9 +68842,9 @@ var swarm_spawn_subtask = tool({
|
|
|
68701
68842
|
}
|
|
68702
68843
|
if (args2.project_path) {
|
|
68703
68844
|
try {
|
|
68704
|
-
const { createEvent:
|
|
68845
|
+
const { createEvent: createEvent6, appendEvent: appendEvent5 } = await import("swarm-mail");
|
|
68705
68846
|
const spawnOrder = 0;
|
|
68706
|
-
const workerSpawnedEvent =
|
|
68847
|
+
const workerSpawnedEvent = createEvent6("worker_spawned", {
|
|
68707
68848
|
project_key: args2.project_path,
|
|
68708
68849
|
epic_id: args2.epic_id,
|
|
68709
68850
|
bead_id: args2.bead_id,
|
|
@@ -68713,7 +68854,7 @@ var swarm_spawn_subtask = tool({
|
|
|
68713
68854
|
spawn_order: spawnOrder,
|
|
68714
68855
|
is_parallel: false
|
|
68715
68856
|
});
|
|
68716
|
-
await
|
|
68857
|
+
await appendEvent5(workerSpawnedEvent, args2.project_path);
|
|
68717
68858
|
} catch (error45) {
|
|
68718
68859
|
console.warn("[swarm_spawn_subtask] Failed to emit WorkerSpawnedEvent:", error45);
|
|
68719
68860
|
}
|
|
@@ -69411,7 +69552,8 @@ var swarmTools = {
|
|
|
69411
69552
|
...promptTools,
|
|
69412
69553
|
...orchestrateTools,
|
|
69413
69554
|
...researchTools,
|
|
69414
|
-
...adversarialReviewTools
|
|
69555
|
+
...adversarialReviewTools,
|
|
69556
|
+
...verificationTools
|
|
69415
69557
|
};
|
|
69416
69558
|
|
|
69417
69559
|
// src/repo-crawl.ts
|
|
@@ -70500,36 +70642,35 @@ var mandateTools = {
|
|
|
70500
70642
|
// src/hivemind-tools.ts
|
|
70501
70643
|
init_dist();
|
|
70502
70644
|
init_esm();
|
|
70503
|
-
init_memory();
|
|
70504
|
-
init_memory();
|
|
70505
70645
|
import {
|
|
70506
70646
|
getSwarmMailLibSQL as getSwarmMailLibSQL6,
|
|
70507
|
-
createEvent as createEvent5,
|
|
70508
70647
|
SessionIndexer,
|
|
70509
70648
|
syncMemories as syncMemories2,
|
|
70510
70649
|
toSwarmDb as toSwarmDb2,
|
|
70511
70650
|
makeOllamaLive as makeOllamaLive2
|
|
70512
70651
|
} from "swarm-mail";
|
|
70652
|
+
init_memory();
|
|
70653
|
+
init_memory();
|
|
70513
70654
|
import * as os2 from "node:os";
|
|
70514
70655
|
import * as path3 from "node:path";
|
|
70515
70656
|
import { join as join12 } from "node:path";
|
|
70516
|
-
var
|
|
70657
|
+
var cachedAdapter = null;
|
|
70517
70658
|
var cachedIndexer = null;
|
|
70518
|
-
var
|
|
70659
|
+
var cachedProjectPath = null;
|
|
70519
70660
|
async function getMemoryAdapter2(projectPath) {
|
|
70520
70661
|
const path4 = projectPath || process.cwd();
|
|
70521
|
-
if (
|
|
70522
|
-
return
|
|
70662
|
+
if (cachedAdapter && cachedProjectPath === path4) {
|
|
70663
|
+
return cachedAdapter;
|
|
70523
70664
|
}
|
|
70524
70665
|
const swarmMail = await getSwarmMailLibSQL6(path4);
|
|
70525
70666
|
const dbAdapter = await swarmMail.getDatabase();
|
|
70526
|
-
|
|
70527
|
-
|
|
70528
|
-
return
|
|
70667
|
+
cachedAdapter = await createMemoryAdapter(dbAdapter);
|
|
70668
|
+
cachedProjectPath = path4;
|
|
70669
|
+
return cachedAdapter;
|
|
70529
70670
|
}
|
|
70530
70671
|
async function getSessionIndexer(projectPath) {
|
|
70531
70672
|
const path4 = projectPath || process.cwd();
|
|
70532
|
-
if (cachedIndexer &&
|
|
70673
|
+
if (cachedIndexer && cachedProjectPath === path4) {
|
|
70533
70674
|
return cachedIndexer;
|
|
70534
70675
|
}
|
|
70535
70676
|
const swarmMail = await getSwarmMailLibSQL6(path4);
|
|
@@ -70540,20 +70681,13 @@ async function getSessionIndexer(projectPath) {
|
|
|
70540
70681
|
ollamaModel: process.env.OLLAMA_MODEL || "mxbai-embed-large"
|
|
70541
70682
|
});
|
|
70542
70683
|
cachedIndexer = new SessionIndexer(db, ollamaLayer);
|
|
70543
|
-
|
|
70684
|
+
cachedProjectPath = path4;
|
|
70544
70685
|
return cachedIndexer;
|
|
70545
70686
|
}
|
|
70546
70687
|
var getHivemindAdapter = getMemoryAdapter2;
|
|
70547
70688
|
async function emitEvent(eventType, data) {
|
|
70548
|
-
|
|
70549
|
-
|
|
70550
|
-
const swarmMail = await getSwarmMailLibSQL6(projectPath);
|
|
70551
|
-
const event = createEvent5(eventType, {
|
|
70552
|
-
project_key: projectPath,
|
|
70553
|
-
...data
|
|
70554
|
-
});
|
|
70555
|
-
await swarmMail.appendEvent(event);
|
|
70556
|
-
} catch {}
|
|
70689
|
+
const projectPath = cachedProjectPath || process.cwd();
|
|
70690
|
+
await safeEmitEvent(eventType, data, "hivemind", projectPath);
|
|
70557
70691
|
}
|
|
70558
70692
|
var AGENT_DIRECTORIES = [
|
|
70559
70693
|
path3.join(os2.homedir(), ".config", "swarm-tools", "sessions"),
|
|
@@ -70596,6 +70730,15 @@ var hivemind_find = tool({
|
|
|
70596
70730
|
fts: tool.schema.boolean().optional().describe("Use full-text search instead of vector search (default: false)")
|
|
70597
70731
|
},
|
|
70598
70732
|
async execute(args2, ctx) {
|
|
70733
|
+
if (!args2.query || typeof args2.query !== "string" || args2.query.trim() === "") {
|
|
70734
|
+
return JSON.stringify({
|
|
70735
|
+
success: false,
|
|
70736
|
+
error: {
|
|
70737
|
+
code: "VALIDATION_ERROR",
|
|
70738
|
+
message: "query parameter is required and must be a non-empty string"
|
|
70739
|
+
}
|
|
70740
|
+
});
|
|
70741
|
+
}
|
|
70599
70742
|
const startTime = Date.now();
|
|
70600
70743
|
const adapter = await getMemoryAdapter2();
|
|
70601
70744
|
const result = await adapter.find(args2);
|
|
@@ -70716,7 +70859,7 @@ var hivemind_sync = tool({
|
|
|
70716
70859
|
args: {},
|
|
70717
70860
|
async execute(args2, ctx) {
|
|
70718
70861
|
try {
|
|
70719
|
-
const projectPath =
|
|
70862
|
+
const projectPath = cachedProjectPath || process.cwd();
|
|
70720
70863
|
const swarmMail = await getSwarmMailLibSQL6(projectPath);
|
|
70721
70864
|
const dbAdapter = await swarmMail.getDatabase();
|
|
70722
70865
|
const hiveDir = join12(projectPath, ".hive");
|
|
@@ -72951,13 +73094,17 @@ var AGENT_DIRECTORIES2 = [
|
|
|
72951
73094
|
path5.join(os3.homedir(), ".local", "share", "Claude"),
|
|
72952
73095
|
path5.join(os3.homedir(), ".aider")
|
|
72953
73096
|
];
|
|
73097
|
+
var sessionIndexerCache = new AdapterCache;
|
|
72954
73098
|
async function getSessionIndexer2() {
|
|
72955
|
-
const
|
|
72956
|
-
|
|
72957
|
-
|
|
72958
|
-
|
|
73099
|
+
const globalKey = "global-session-indexer";
|
|
73100
|
+
return sessionIndexerCache.get(globalKey, async () => {
|
|
73101
|
+
const db = await getDb();
|
|
73102
|
+
const ollamaLayer = makeOllamaLive3({
|
|
73103
|
+
ollamaHost: process.env.OLLAMA_HOST || "http://localhost:11434",
|
|
73104
|
+
ollamaModel: process.env.OLLAMA_MODEL || "mxbai-embed-large"
|
|
73105
|
+
});
|
|
73106
|
+
return new SessionIndexer2(db, ollamaLayer);
|
|
72959
73107
|
});
|
|
72960
|
-
return new SessionIndexer2(db, ollamaLayer);
|
|
72961
73108
|
}
|
|
72962
73109
|
async function emitEvent2(eventType, data) {
|
|
72963
73110
|
try {
|