@chuckssmith/agentloom 0.3.0 → 0.4.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/dist/cli.js +11 -0
- package/dist/commands/collect.d.ts +1 -0
- package/dist/commands/collect.js +79 -0
- package/dist/commands/reset.d.ts +1 -0
- package/dist/commands/reset.js +17 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -3,6 +3,8 @@ import { setup } from './commands/setup.js';
|
|
|
3
3
|
import { crew } from './commands/crew.js';
|
|
4
4
|
import { status } from './commands/status.js';
|
|
5
5
|
import { logs } from './commands/logs.js';
|
|
6
|
+
import { collect } from './commands/collect.js';
|
|
7
|
+
import { reset } from './commands/reset.js';
|
|
6
8
|
const [, , command, ...args] = process.argv;
|
|
7
9
|
const usage = `
|
|
8
10
|
agentloom (loom) — workflow layer for Claude Code
|
|
@@ -15,6 +17,9 @@ Usage:
|
|
|
15
17
|
loom status Show active crew session
|
|
16
18
|
loom logs Show worker output summary
|
|
17
19
|
loom logs <workerId> Show full log for a specific worker
|
|
20
|
+
loom collect Synthesize worker results into a summary
|
|
21
|
+
loom collect --no-ai Collect results without Claude synthesis
|
|
22
|
+
loom reset --force Clear all session state
|
|
18
23
|
|
|
19
24
|
Modes (use $grind or $crew inside a Claude Code session):
|
|
20
25
|
$grind Persistence loop — keeps working until verified complete
|
|
@@ -42,6 +47,12 @@ switch (command) {
|
|
|
42
47
|
case 'logs':
|
|
43
48
|
await logs(args);
|
|
44
49
|
break;
|
|
50
|
+
case 'collect':
|
|
51
|
+
await collect(args);
|
|
52
|
+
break;
|
|
53
|
+
case 'reset':
|
|
54
|
+
await reset(args);
|
|
55
|
+
break;
|
|
45
56
|
default:
|
|
46
57
|
console.log(usage);
|
|
47
58
|
process.exit(command ? 1 : 0);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function collect(args: string[]): Promise<void>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { readFile, readdir, writeFile } from 'fs/promises';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { existsSync } from 'fs';
|
|
4
|
+
import { spawnSync } from 'child_process';
|
|
5
|
+
import { STATE_DIR, readSession, readTasks } from '../state/session.js';
|
|
6
|
+
const WORKERS_DIR = join(STATE_DIR, 'workers');
|
|
7
|
+
export async function collect(args) {
|
|
8
|
+
if (!existsSync(WORKERS_DIR)) {
|
|
9
|
+
console.log('No session found. Run: loom crew "<task>"');
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const session = await readSession();
|
|
13
|
+
const tasks = await readTasks();
|
|
14
|
+
const files = await readdir(WORKERS_DIR);
|
|
15
|
+
const resultFiles = files.filter(f => f.endsWith('-result.md')).sort();
|
|
16
|
+
if (resultFiles.length === 0) {
|
|
17
|
+
console.log('No worker results yet. Check status with: loom status');
|
|
18
|
+
console.log('Workers still running? Check: loom logs');
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
console.log(`\nCollecting results from ${resultFiles.length} worker(s)...\n`);
|
|
22
|
+
const results = [];
|
|
23
|
+
for (const f of resultFiles) {
|
|
24
|
+
const workerId = f.replace('-result.md', '');
|
|
25
|
+
const content = await readFile(join(WORKERS_DIR, f), 'utf8');
|
|
26
|
+
results.push({ workerId, content });
|
|
27
|
+
console.log(` ✓ ${workerId}`);
|
|
28
|
+
}
|
|
29
|
+
const taskDesc = session?.description ?? 'unknown task';
|
|
30
|
+
const summaryPath = join(STATE_DIR, 'summary.md');
|
|
31
|
+
// Build raw summary
|
|
32
|
+
const raw = results.map(r => `## ${r.workerId}\n\n${r.content.trim()}`).join('\n\n---\n\n');
|
|
33
|
+
// Optionally synthesize with Claude
|
|
34
|
+
const synthesize = !args.includes('--no-ai');
|
|
35
|
+
let synthesis = '';
|
|
36
|
+
if (synthesize) {
|
|
37
|
+
console.log('\nSynthesizing with Claude...');
|
|
38
|
+
const prompt = `You are summarizing the results of a multi-agent crew that worked on this task:
|
|
39
|
+
|
|
40
|
+
"${taskDesc}"
|
|
41
|
+
|
|
42
|
+
Here are the individual worker results:
|
|
43
|
+
|
|
44
|
+
${raw}
|
|
45
|
+
|
|
46
|
+
Write a concise synthesis (under 300 words) that:
|
|
47
|
+
1. States what was accomplished overall
|
|
48
|
+
2. Highlights the key findings or changes from each worker
|
|
49
|
+
3. Calls out any blockers, conflicts, or follow-up work needed
|
|
50
|
+
|
|
51
|
+
Be direct and specific. No filler.`;
|
|
52
|
+
const result = spawnSync('claude', ['--print', '-p', prompt], {
|
|
53
|
+
encoding: 'utf8',
|
|
54
|
+
timeout: 60_000,
|
|
55
|
+
});
|
|
56
|
+
if (result.status === 0 && result.stdout.trim()) {
|
|
57
|
+
synthesis = result.stdout.trim();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const summaryContent = [
|
|
61
|
+
`# Crew Summary`,
|
|
62
|
+
``,
|
|
63
|
+
`**Task:** ${taskDesc}`,
|
|
64
|
+
`**Workers:** ${resultFiles.length}`,
|
|
65
|
+
`**Collected:** ${new Date().toISOString()}`,
|
|
66
|
+
``,
|
|
67
|
+
synthesis ? `## Synthesis\n\n${synthesis}` : '',
|
|
68
|
+
synthesis ? `\n---\n` : '',
|
|
69
|
+
`## Individual Results`,
|
|
70
|
+
``,
|
|
71
|
+
raw,
|
|
72
|
+
].filter(l => l !== undefined).join('\n');
|
|
73
|
+
await writeFile(summaryPath, summaryContent);
|
|
74
|
+
console.log(`\nSummary written to: ${summaryPath}`);
|
|
75
|
+
if (synthesis) {
|
|
76
|
+
console.log('\n── Synthesis ─────────────────────────────────');
|
|
77
|
+
console.log(synthesis);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function reset(args: string[]): Promise<void>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { rm } from 'fs/promises';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import { STATE_DIR } from '../state/session.js';
|
|
4
|
+
export async function reset(args) {
|
|
5
|
+
if (!existsSync(STATE_DIR)) {
|
|
6
|
+
console.log('Nothing to reset.');
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
const force = args.includes('--force') || args.includes('-f');
|
|
10
|
+
if (!force) {
|
|
11
|
+
console.log(`This will delete all session state in ${STATE_DIR}/`);
|
|
12
|
+
console.log('Run with --force to confirm: loom reset --force');
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
await rm(STATE_DIR, { recursive: true, force: true });
|
|
16
|
+
console.log(`✓ Session state cleared (${STATE_DIR}/)`);
|
|
17
|
+
}
|