opencode-swarm-plugin 0.30.7 → 0.31.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/.hive/memories.jsonl +10 -0
- package/.turbo/turbo-build.log +3 -3
- package/.turbo/turbo-test.log +319 -319
- package/CHANGELOG.md +96 -0
- package/dist/hive.d.ts.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.js +107 -20
- package/dist/plugin.js +107 -20
- package/dist/swarm-decompose.d.ts +8 -8
- package/dist/swarm-decompose.d.ts.map +1 -1
- package/dist/swarm-orchestrate.d.ts.map +1 -1
- package/dist/swarm-prompts.d.ts +6 -6
- package/dist/swarm-prompts.d.ts.map +1 -1
- package/dist/swarm.d.ts +6 -6
- package/opencode-swarm-plugin-0.30.7.tgz +0 -0
- package/package.json +2 -2
- package/src/hive.integration.test.ts +332 -3
- package/src/hive.ts +155 -11
- package/src/swarm-decompose.ts +7 -11
- package/src/swarm-orchestrate.ts +27 -1
- package/src/swarm-prompts.ts +5 -7
- package/src/swarm.integration.test.ts +70 -0
package/src/swarm-orchestrate.ts
CHANGED
|
@@ -72,7 +72,7 @@ import {
|
|
|
72
72
|
isToolAvailable,
|
|
73
73
|
warnMissingTool,
|
|
74
74
|
} from "./tool-availability";
|
|
75
|
-
import { getHiveAdapter } from "./hive";
|
|
75
|
+
import { getHiveAdapter, hive_sync, setHiveWorkingDirectory, getHiveWorkingDirectory } from "./hive";
|
|
76
76
|
import { listSkills } from "./skills";
|
|
77
77
|
import {
|
|
78
78
|
canUseWorktreeIsolation,
|
|
@@ -1570,6 +1570,30 @@ This will be recorded as a negative learning signal.`;
|
|
|
1570
1570
|
);
|
|
1571
1571
|
}
|
|
1572
1572
|
|
|
1573
|
+
// Sync cell to .hive/issues.jsonl (auto-sync on complete)
|
|
1574
|
+
// This ensures the worker's completed work persists before process exits
|
|
1575
|
+
let syncSuccess = false;
|
|
1576
|
+
let syncError: string | undefined;
|
|
1577
|
+
try {
|
|
1578
|
+
// Save current working directory and set to project path
|
|
1579
|
+
const previousWorkingDir = getHiveWorkingDirectory();
|
|
1580
|
+
setHiveWorkingDirectory(args.project_key);
|
|
1581
|
+
|
|
1582
|
+
try {
|
|
1583
|
+
const syncResult = await hive_sync.execute({ auto_pull: false }, _ctx);
|
|
1584
|
+
syncSuccess = !syncResult.includes("error");
|
|
1585
|
+
} finally {
|
|
1586
|
+
// Restore previous working directory
|
|
1587
|
+
setHiveWorkingDirectory(previousWorkingDir);
|
|
1588
|
+
}
|
|
1589
|
+
} catch (error) {
|
|
1590
|
+
// Non-fatal - log warning but don't block completion
|
|
1591
|
+
syncError = error instanceof Error ? error.message : String(error);
|
|
1592
|
+
console.warn(
|
|
1593
|
+
`[swarm_complete] Auto-sync failed (non-fatal): ${syncError}`,
|
|
1594
|
+
);
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1573
1597
|
// Emit SubtaskOutcomeEvent for learning system
|
|
1574
1598
|
try {
|
|
1575
1599
|
const epicId = args.bead_id.includes(".")
|
|
@@ -1709,6 +1733,8 @@ This will be recorded as a negative learning signal.`;
|
|
|
1709
1733
|
bead_id: args.bead_id,
|
|
1710
1734
|
closed: true,
|
|
1711
1735
|
reservations_released: true,
|
|
1736
|
+
synced: syncSuccess,
|
|
1737
|
+
sync_error: syncError,
|
|
1712
1738
|
message_sent: messageSent,
|
|
1713
1739
|
message_error: messageError,
|
|
1714
1740
|
agent_registration: {
|
package/src/swarm-prompts.ts
CHANGED
|
@@ -46,7 +46,7 @@ Agents MUST update their cell status as they work. No silent progress.
|
|
|
46
46
|
|
|
47
47
|
## Requirements
|
|
48
48
|
|
|
49
|
-
1. **Break into
|
|
49
|
+
1. **Break into independent subtasks** that can run in parallel (as many as needed)
|
|
50
50
|
2. **Assign files** - each subtask must specify which files it will modify
|
|
51
51
|
3. **No file overlap** - files cannot appear in multiple subtasks (they get exclusive locks)
|
|
52
52
|
4. **Order by dependency** - if subtask B needs subtask A's output, A must come first in the array
|
|
@@ -123,7 +123,7 @@ Agents MUST update their cell status as they work. No silent progress.
|
|
|
123
123
|
|
|
124
124
|
## Requirements
|
|
125
125
|
|
|
126
|
-
1. **Break into
|
|
126
|
+
1. **Break into independent subtasks** that can run in parallel (as many as needed)
|
|
127
127
|
2. **Assign files** - each subtask must specify which files it will modify
|
|
128
128
|
3. **No file overlap** - files cannot appear in multiple subtasks (they get exclusive locks)
|
|
129
129
|
4. **Order by dependency** - if subtask B needs subtask A's output, A must come first in the array
|
|
@@ -927,10 +927,9 @@ export const swarm_plan_prompt = tool({
|
|
|
927
927
|
max_subtasks: tool.schema
|
|
928
928
|
.number()
|
|
929
929
|
.int()
|
|
930
|
-
.min(
|
|
931
|
-
.
|
|
932
|
-
.
|
|
933
|
-
.describe("Maximum number of subtasks (default: 5)"),
|
|
930
|
+
.min(1)
|
|
931
|
+
.optional()
|
|
932
|
+
.describe("Suggested max subtasks (optional - LLM decides if not specified)"),
|
|
934
933
|
context: tool.schema
|
|
935
934
|
.string()
|
|
936
935
|
.optional()
|
|
@@ -943,7 +942,6 @@ export const swarm_plan_prompt = tool({
|
|
|
943
942
|
.number()
|
|
944
943
|
.int()
|
|
945
944
|
.min(1)
|
|
946
|
-
.max(10)
|
|
947
945
|
.optional()
|
|
948
946
|
.describe("Max CASS results to include (default: 3)"),
|
|
949
947
|
include_skills: tool.schema
|
|
@@ -2341,4 +2341,74 @@ describe("Contract Validation", () => {
|
|
|
2341
2341
|
expect(parsed.error).toBeUndefined();
|
|
2342
2342
|
});
|
|
2343
2343
|
});
|
|
2344
|
+
|
|
2345
|
+
describe("swarm_complete auto-sync", () => {
|
|
2346
|
+
it("calls hive_sync after closing cell on successful completion", async () => {
|
|
2347
|
+
const testProjectPath = "/tmp/swarm-auto-sync-test-" + Date.now();
|
|
2348
|
+
const { getHiveAdapter } = await import("./hive");
|
|
2349
|
+
const adapter = await getHiveAdapter(testProjectPath);
|
|
2350
|
+
|
|
2351
|
+
// Create a task cell directly
|
|
2352
|
+
const cell = await adapter.createCell(testProjectPath, {
|
|
2353
|
+
title: "Test task for auto-sync",
|
|
2354
|
+
type: "task",
|
|
2355
|
+
priority: 2,
|
|
2356
|
+
});
|
|
2357
|
+
|
|
2358
|
+
// Start the task
|
|
2359
|
+
await adapter.updateCell(testProjectPath, cell.id, {
|
|
2360
|
+
status: "in_progress",
|
|
2361
|
+
});
|
|
2362
|
+
|
|
2363
|
+
// Complete with skip_review and skip_verification
|
|
2364
|
+
const result = await swarm_complete.execute(
|
|
2365
|
+
{
|
|
2366
|
+
project_key: testProjectPath,
|
|
2367
|
+
agent_name: "TestAgent",
|
|
2368
|
+
bead_id: cell.id,
|
|
2369
|
+
summary: "Done - testing auto-sync",
|
|
2370
|
+
files_touched: [],
|
|
2371
|
+
skip_verification: true,
|
|
2372
|
+
skip_review: true,
|
|
2373
|
+
},
|
|
2374
|
+
mockContext,
|
|
2375
|
+
);
|
|
2376
|
+
|
|
2377
|
+
const parsed = JSON.parse(result);
|
|
2378
|
+
|
|
2379
|
+
// Should complete successfully
|
|
2380
|
+
expect(parsed.success).toBe(true);
|
|
2381
|
+
expect(parsed.closed).toBe(true);
|
|
2382
|
+
|
|
2383
|
+
// Check that cell is actually closed in database
|
|
2384
|
+
const closedCell = await adapter.getCell(testProjectPath, cell.id);
|
|
2385
|
+
expect(closedCell?.status).toBe("closed");
|
|
2386
|
+
|
|
2387
|
+
// The sync should have flushed the cell to .hive/issues.jsonl
|
|
2388
|
+
// We can verify the cell appears in the JSONL
|
|
2389
|
+
const hivePath = `${testProjectPath}/.hive/issues.jsonl`;
|
|
2390
|
+
const hiveFile = Bun.file(hivePath);
|
|
2391
|
+
const exists = await hiveFile.exists();
|
|
2392
|
+
|
|
2393
|
+
// The file should exist after sync
|
|
2394
|
+
expect(exists).toBe(true);
|
|
2395
|
+
|
|
2396
|
+
if (exists) {
|
|
2397
|
+
const content = await hiveFile.text();
|
|
2398
|
+
const lines = content.trim().split("\n");
|
|
2399
|
+
|
|
2400
|
+
// Should have at least one cell exported
|
|
2401
|
+
expect(lines.length).toBeGreaterThan(0);
|
|
2402
|
+
|
|
2403
|
+
// Parse the exported cells to find our closed cell
|
|
2404
|
+
const cells = lines.map((line) => JSON.parse(line));
|
|
2405
|
+
const exportedCell = cells.find((c) => c.id === cell.id);
|
|
2406
|
+
|
|
2407
|
+
// Our cell should be in the export
|
|
2408
|
+
expect(exportedCell).toBeDefined();
|
|
2409
|
+
expect(exportedCell.status).toBe("closed");
|
|
2410
|
+
expect(exportedCell.title).toBe("Test task for auto-sync");
|
|
2411
|
+
}
|
|
2412
|
+
});
|
|
2413
|
+
});
|
|
2344
2414
|
});
|