@automagik/genie 0.260202.1607 → 0.260202.1833

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/src/term.ts CHANGED
@@ -15,6 +15,11 @@ import * as windowCmd from './term-commands/window.js';
15
15
  import * as paneCmd from './term-commands/pane.js';
16
16
  import * as statusCmd from './term-commands/status.js';
17
17
  import * as shortcutsCmd from './term-commands/shortcuts.js';
18
+ import * as orchestrateCmd from './term-commands/orchestrate.js';
19
+ import * as workCmd from './term-commands/work.js';
20
+ import * as workersCmd from './term-commands/workers.js';
21
+ import * as closeCmd from './term-commands/close.js';
22
+ import * as killCmd from './term-commands/kill.js';
18
23
 
19
24
  const program = new Command();
20
25
 
@@ -28,7 +33,14 @@ Collaborative Usage:
28
33
  AI reads: term read genie
29
34
 
30
35
  Workflow: new → exec → read → rm
31
- Full control: window new/ls/rm, pane ls/rm, split, status`)
36
+ Full control: window new/ls/rm, pane ls/rm, split, status
37
+
38
+ Worker Orchestration:
39
+ term work <bd-id> - Spawn worker bound to beads issue
40
+ term work next - Work on next ready issue
41
+ term workers - List all workers and states
42
+ term close <bd-id> - Close issue, cleanup worker
43
+ term kill <worker> - Force kill a stuck worker`)
32
44
  .version(VERSION);
33
45
 
34
46
  // Session management
@@ -200,4 +212,180 @@ program
200
212
  await shortcutsCmd.handleShortcuts(options);
201
213
  });
202
214
 
215
+ // Worker management commands (beads + Claude orchestration)
216
+ program
217
+ .command('work <target>')
218
+ .description('Spawn worker bound to beads issue (target: bd-id, "next", or "wish")')
219
+ .option('--no-worktree', 'Use shared repo instead of worktree')
220
+ .option('-s, --session <name>', 'Target tmux session')
221
+ .option('--no-focus', 'Don\'t focus the worker pane')
222
+ .option('-p, --prompt <message>', 'Custom initial prompt')
223
+ .action(async (target: string, options: workCmd.WorkOptions) => {
224
+ await workCmd.workCommand(target, options);
225
+ });
226
+
227
+ program
228
+ .command('workers')
229
+ .description('List all workers and their states')
230
+ .option('--json', 'Output as JSON')
231
+ .option('-w, --watch', 'Live updates (coming soon)')
232
+ .action(async (options: workersCmd.WorkersOptions) => {
233
+ if (options.watch) {
234
+ console.log('ℹ️ --watch mode coming in Phase 1.5');
235
+ }
236
+ await workersCmd.workersCommand(options);
237
+ });
238
+
239
+ program
240
+ .command('close <task-id>')
241
+ .description('Close beads issue and cleanup worker')
242
+ .option('--no-sync', 'Skip bd sync')
243
+ .option('--keep-worktree', 'Don\'t remove the worktree')
244
+ .option('--merge', 'Merge worktree changes to main branch')
245
+ .option('-y, --yes', 'Skip confirmation')
246
+ .action(async (taskId: string, options: closeCmd.CloseOptions) => {
247
+ await closeCmd.closeCommand(taskId, options);
248
+ });
249
+
250
+ program
251
+ .command('kill <worker>')
252
+ .description('Force kill a worker')
253
+ .option('-y, --yes', 'Skip confirmation')
254
+ .option('--keep-worktree', 'Don\'t remove the worktree')
255
+ .action(async (worker: string, options: killCmd.KillOptions) => {
256
+ await killCmd.killCommand(worker, options);
257
+ });
258
+
259
+ // Approve command (shortcut to orc approve for worker use)
260
+ program
261
+ .command('approve <worker>')
262
+ .description('Approve pending permission request for a worker')
263
+ .option('--deny', 'Deny instead of approve')
264
+ .action(async (worker: string, options: { deny?: boolean }) => {
265
+ // Find worker to get pane
266
+ const registry = await import('./lib/worker-registry.js');
267
+ let workerInfo = await registry.get(worker);
268
+ if (!workerInfo) {
269
+ workerInfo = await registry.findByTask(worker);
270
+ }
271
+ if (!workerInfo) {
272
+ console.error(`❌ Worker "${worker}" not found. Run \`term workers\` to see workers.`);
273
+ process.exit(1);
274
+ }
275
+ await orchestrateCmd.approvePermission(workerInfo.session, {
276
+ pane: workerInfo.paneId,
277
+ deny: options.deny,
278
+ });
279
+ });
280
+
281
+ // Answer command (shortcut to orc answer for worker use)
282
+ program
283
+ .command('answer <worker> <choice>')
284
+ .description('Answer a question for a worker (use "text:..." for text input)')
285
+ .action(async (worker: string, choice: string) => {
286
+ const registry = await import('./lib/worker-registry.js');
287
+ let workerInfo = await registry.get(worker);
288
+ if (!workerInfo) {
289
+ workerInfo = await registry.findByTask(worker);
290
+ }
291
+ if (!workerInfo) {
292
+ console.error(`❌ Worker "${worker}" not found. Run \`term workers\` to see workers.`);
293
+ process.exit(1);
294
+ }
295
+ await orchestrateCmd.answerQuestion(workerInfo.session, choice, {
296
+ pane: workerInfo.paneId,
297
+ });
298
+ });
299
+
300
+ // Orchestration commands (Claude Code automation)
301
+ const orcProgram = program.command('orc').description('Orchestrate Claude Code sessions');
302
+
303
+ orcProgram
304
+ .command('start <session>')
305
+ .description('Start Claude Code in a session with optional monitoring')
306
+ .option('-p, --pane <id>', 'Target specific pane ID (e.g., %16)')
307
+ .option('-m, --monitor', 'Enable real-time event monitoring')
308
+ .option('-c, --command <cmd>', 'Command to run instead of claude')
309
+ .option('--json', 'Output events as JSON')
310
+ .action(async (session: string, options: orchestrateCmd.StartOptions) => {
311
+ await orchestrateCmd.startSession(session, options);
312
+ });
313
+
314
+ orcProgram
315
+ .command('send <session> <message>')
316
+ .description('Send message to Claude and track completion')
317
+ .option('--pane <id>', 'Target specific pane ID (e.g., %16)')
318
+ .option('--method <name>', 'Completion detection method')
319
+ .option('-t, --timeout <ms>', 'Timeout in milliseconds')
320
+ .option('--no-wait', 'Send without waiting for completion')
321
+ .option('--json', 'Output as JSON')
322
+ .action(async (session: string, message: string, options: orchestrateCmd.SendOptions) => {
323
+ await orchestrateCmd.sendMessage(session, message, options);
324
+ });
325
+
326
+ orcProgram
327
+ .command('status <session>')
328
+ .description('Show current Claude state and details')
329
+ .option('--pane <id>', 'Target specific pane ID (e.g., %16)')
330
+ .option('--json', 'Output as JSON')
331
+ .action(async (session: string, options: orchestrateCmd.StatusOptions) => {
332
+ await orchestrateCmd.showStatus(session, options);
333
+ });
334
+
335
+ orcProgram
336
+ .command('watch <session>')
337
+ .description('Watch session events in real-time')
338
+ .option('--pane <id>', 'Target specific pane ID (e.g., %16)')
339
+ .option('--json', 'Output events as JSON')
340
+ .option('-p, --poll <ms>', 'Poll interval in milliseconds')
341
+ .action(async (session: string, options: orchestrateCmd.WatchOptions) => {
342
+ await orchestrateCmd.watchSession(session, options);
343
+ });
344
+
345
+ orcProgram
346
+ .command('approve <session>')
347
+ .description('Approve pending permission request')
348
+ .option('-p, --pane <id>', 'Specific pane ID to target')
349
+ .option('--auto', 'Auto-approve all future permissions (dangerous!)')
350
+ .option('--deny', 'Deny instead of approve')
351
+ .action(async (session: string, options: orchestrateCmd.ApproveOptions) => {
352
+ await orchestrateCmd.approvePermission(session, options);
353
+ });
354
+
355
+ orcProgram
356
+ .command('answer <session> <choice>')
357
+ .description('Answer a question with the given choice (use "text:..." to send feedback)')
358
+ .option('-p, --pane <id>', 'Specific pane ID to target')
359
+ .action(async (session: string, choice: string, options: { pane?: string }) => {
360
+ await orchestrateCmd.answerQuestion(session, choice, options);
361
+ });
362
+
363
+ orcProgram
364
+ .command('experiment <method>')
365
+ .description('Test a completion detection method')
366
+ .option('-n, --runs <number>', 'Number of test runs')
367
+ .option('--task <command>', 'Test command to run')
368
+ .option('--json', 'Output as JSON')
369
+ .action(async (method: string, options: orchestrateCmd.ExperimentOptions) => {
370
+ await orchestrateCmd.runExperiment(method, options);
371
+ });
372
+
373
+ orcProgram
374
+ .command('methods')
375
+ .description('List available completion detection methods')
376
+ .action(async () => {
377
+ await orchestrateCmd.listMethods();
378
+ });
379
+
380
+ orcProgram
381
+ .command('run <session> <message>')
382
+ .description('Send task and auto-approve until idle (fire-and-forget)')
383
+ .option('-p, --pane <id>', 'Target specific pane ID (e.g., %16)')
384
+ .option('-a, --auto-approve', 'Auto-approve permissions and plans')
385
+ .option('-t, --timeout <ms>', 'Timeout in milliseconds (default: 300000)')
386
+ .option('--json', 'Output final state as JSON')
387
+ .action(async (session: string, message: string, options: orchestrateCmd.RunOptions) => {
388
+ await orchestrateCmd.runTask(session, message, options);
389
+ });
390
+
203
391
  program.parse();