codex-toys 0.140.2 → 0.140.4

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.
Files changed (53) hide show
  1. package/README.md +6 -1
  2. package/dist/app-server/stdio-transport.js +0 -2
  3. package/dist/app-server/stdio-transport.js.map +1 -1
  4. package/dist/bin/codex-toys-proxy.js +16 -4
  5. package/dist/cli/args.d.ts +194 -1
  6. package/dist/cli/args.d.ts.map +1 -1
  7. package/dist/cli/args.js +461 -2
  8. package/dist/cli/args.js.map +1 -1
  9. package/dist/cli/index.js +446 -8
  10. package/dist/cli/index.js.map +1 -1
  11. package/dist/cli/pack.d.ts +1 -3
  12. package/dist/cli/pack.d.ts.map +1 -1
  13. package/dist/cli/pack.js +3 -138
  14. package/dist/cli/pack.js.map +1 -1
  15. package/dist/cli/toybox.d.ts.map +1 -1
  16. package/dist/cli/toybox.js +24 -2
  17. package/dist/cli/toybox.js.map +1 -1
  18. package/dist/cli/turn-automation.d.ts +4 -0
  19. package/dist/cli/turn-automation.d.ts.map +1 -1
  20. package/dist/cli/turn-automation.js +17 -0
  21. package/dist/cli/turn-automation.js.map +1 -1
  22. package/dist/cli/workspace-autonomy.d.ts +135 -0
  23. package/dist/cli/workspace-autonomy.d.ts.map +1 -1
  24. package/dist/cli/workspace-autonomy.js +476 -11
  25. package/dist/cli/workspace-autonomy.js.map +1 -1
  26. package/dist/host-overview.d.ts +112 -0
  27. package/dist/host-overview.d.ts.map +1 -0
  28. package/dist/host-overview.js +406 -0
  29. package/dist/host-overview.js.map +1 -0
  30. package/dist/index.d.ts +2 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +2 -0
  33. package/dist/index.js.map +1 -1
  34. package/dist/proxy.d.ts.map +1 -1
  35. package/dist/proxy.js +11 -1
  36. package/dist/proxy.js.map +1 -1
  37. package/dist/toybox/deferred-run-methods.d.ts +15 -0
  38. package/dist/toybox/deferred-run-methods.d.ts.map +1 -1
  39. package/dist/toybox/deferred-run-methods.js +261 -1
  40. package/dist/toybox/deferred-run-methods.js.map +1 -1
  41. package/dist/toybox/index.d.ts +2 -1
  42. package/dist/toybox/index.d.ts.map +1 -1
  43. package/dist/toybox/index.js +2 -1
  44. package/dist/toybox/index.js.map +1 -1
  45. package/dist/toybox/protocol.d.ts +1 -1
  46. package/dist/toybox/protocol.d.ts.map +1 -1
  47. package/dist/toybox/protocol.js +1 -0
  48. package/dist/toybox/protocol.js.map +1 -1
  49. package/dist/workspace-overview.d.ts +153 -0
  50. package/dist/workspace-overview.d.ts.map +1 -0
  51. package/dist/workspace-overview.js +584 -0
  52. package/dist/workspace-overview.js.map +1 -0
  53. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -11,10 +11,12 @@ import { collectRemotePreflight, formatRemotePreflight, } from "./remote-preflig
11
11
  import { createTurnAutomationHost, formatTurnAutomationList, formatTurnAutomationRun, listTurnAutomations, resolveTurnAutomationTarget, runTurnAutomationScript, } from "./turn-automation.js";
12
12
  import { createLocalToyboxTransport, createSshToyboxTransport, hasSshRemote, withSshRemoteToyboxTransport, } from "./remote-provider.js";
13
13
  import { REMOTE_AUTOMATION_LIST_METHOD, REMOTE_AUTOMATION_RUN_METHOD, } from "./remote-automation.js";
14
+ import { HOST_OVERVIEW_METHOD } from "../host-overview.js";
14
15
  import { WORKSPACE_FUNCTIONS_CALL_METHOD, WORKSPACE_FUNCTIONS_DESCRIBE_METHOD, WORKSPACE_FUNCTIONS_LIST_METHOD, } from "../functions.js";
16
+ import { WORKSPACE_OVERVIEW_METHOD, } from "../workspace-overview.js";
15
17
  import { serveToybox } from "./toybox.js";
16
18
  import { formatThreadRolloutInspection, formatThreadRolloutInstallation, formatThreadRolloutLocation, formatThreadRolloutTransplant, installThreadRollout, inspectThreadRollout, locateThreadRollout, transplantThreadRollout, } from "../threads.js";
17
- import { collectDeferredRuns, collectWorkspaceDoctorInfo, commitActionsWorkspaceState, cancelDeferredRunIntent, createWorkspaceContext, createDeferredRunIntent, listDeferredRunIntents, pruneDeferredRunHistory, readDeferredRun, formatWorkspaceDoctorInfo, runDueDeferredRuns, runWorkspaceTaskById, scaffoldActionsWorkspace, tickWorkspace, } from "./workspace-autonomy.js";
19
+ import { collectDeferredRuns, collectLocalHandoffRuns, collectPromptQueueRuns, collectWorkspaceDoctorInfo, commitActionsWorkspaceState, cancelDeferredRunIntent, createWorkspaceContext, createDeferredRunIntent, drainLocalHandoffQueue, enqueueLocalHandoffIntent, enqueuePromptQueueIntent, listLocalHandoffIntents, listPromptQueueIntents, listDeferredRunIntents, pruneDeferredRunHistory, readDeferredRun, formatWorkspaceDoctorInfo, retryDeferredRunIntent, runDuePromptQueueIntents, runDueDeferredRuns, runWorkspaceTaskById, scaffoldActionsWorkspace, tickWorkspace, } from "./workspace-autonomy.js";
18
20
  import { formatWorkspaceDelegationListResult, formatWorkspaceDelegationStartResult, startWorkspaceDelegationWithRequest, } from "./workspace-delegation.js";
19
21
  import { serveCodexToysMcp } from "./mcp.js";
20
22
  import { parseJsonParamsText, readJsonFile } from "./json.js";
@@ -146,6 +148,10 @@ async function main() {
146
148
  : `${JSON.stringify(response.result, null, 2)}\n`);
147
149
  return;
148
150
  }
151
+ if (parsed.type === "host-overview") {
152
+ writeJson(await callToybox(HOST_OVERVIEW_METHOD, {}, parsed), parsed.pretty);
153
+ return;
154
+ }
149
155
  if (parsed.type === "turn-run") {
150
156
  const result = await startRemoteTurn({
151
157
  prompt: parsed.prompt,
@@ -246,6 +252,16 @@ async function main() {
246
252
  : `${formatWorkspaceDoctorInfo(info)}toybox ${toyboxLabelForDoctor(toybox)}\n`);
247
253
  return;
248
254
  }
255
+ if (parsed.type === "workspace-overview") {
256
+ const overview = await callToybox(WORKSPACE_OVERVIEW_METHOD, compactUndefined({
257
+ mode: parsed.mode,
258
+ workspaceRoot: parsed.workspaceRoot,
259
+ }), parsed);
260
+ write(parsed.json
261
+ ? `${JSON.stringify(overview, null, parsed.pretty ? 2 : 0)}\n`
262
+ : formatWorkspaceOverview(overview));
263
+ return;
264
+ }
249
265
  if (parsed.type === "workspace-tick") {
250
266
  const context = await createWorkspaceContext({
251
267
  workspaceRoot: parsed.workspaceRoot,
@@ -278,6 +294,324 @@ async function main() {
278
294
  }, parsed.pretty);
279
295
  return;
280
296
  }
297
+ if (parsed.type === "workspace-prompt-enqueue") {
298
+ validateAutomationTurnOptions(parsed);
299
+ const params = compactUndefined({
300
+ prompt: parsed.prompt,
301
+ title: parsed.title,
302
+ queue: parsed.queue,
303
+ labels: parsed.labels.length > 0 ? parsed.labels : undefined,
304
+ runAt: parsed.runAt,
305
+ afterIntentId: parsed.afterIntentId,
306
+ afterStatus: parsed.afterStatus,
307
+ threadId: parsed.threadId,
308
+ cwd: parsed.cwd,
309
+ model: parsed.model,
310
+ serviceTier: parsed.serviceTier,
311
+ effort: parsed.effort,
312
+ sandbox: parsed.sandbox,
313
+ approvalPolicy: parsed.approvalPolicy,
314
+ permissions: parsed.permissions,
315
+ });
316
+ const result = hasSshRemote(parsed)
317
+ ? await callToybox("promptQueue.enqueue", compactUndefined({
318
+ ...params,
319
+ mode: parsed.mode,
320
+ workspaceRoot: parsed.workspaceRoot,
321
+ }), parsed)
322
+ : {
323
+ intent: await enqueuePromptQueueIntent(await createWorkspaceContext({
324
+ workspaceRoot: parsed.workspaceRoot,
325
+ mode: parsed.mode,
326
+ }), params),
327
+ };
328
+ writeJson(result, parsed.pretty);
329
+ return;
330
+ }
331
+ if (parsed.type === "workspace-prompt-list") {
332
+ if (hasSshRemote(parsed)) {
333
+ const result = await callToybox("promptQueue.list", compactUndefined({
334
+ status: parsed.status,
335
+ queue: parsed.queue,
336
+ limit: parsed.limit,
337
+ mode: parsed.mode,
338
+ workspaceRoot: parsed.workspaceRoot,
339
+ }), parsed);
340
+ write(parsed.json
341
+ ? `${JSON.stringify(result, null, parsed.pretty ? 2 : 0)}\n`
342
+ : formatPromptQueueList((record(result).intents ?? [])));
343
+ return;
344
+ }
345
+ const context = await createWorkspaceContext({
346
+ workspaceRoot: parsed.workspaceRoot,
347
+ mode: parsed.mode,
348
+ });
349
+ const intents = await listPromptQueueIntents(context, {
350
+ status: parsed.status,
351
+ queue: parsed.queue,
352
+ limit: parsed.limit,
353
+ });
354
+ write(parsed.json
355
+ ? `${JSON.stringify({ intents }, null, parsed.pretty ? 2 : 0)}\n`
356
+ : formatPromptQueueList(intents));
357
+ return;
358
+ }
359
+ if (parsed.type === "workspace-prompt-read") {
360
+ const result = hasSshRemote(parsed)
361
+ ? await callToybox("promptQueue.read", compactUndefined({
362
+ id: parsed.intentId,
363
+ includeOutput: parsed.includeOutput,
364
+ mode: parsed.mode,
365
+ workspaceRoot: parsed.workspaceRoot,
366
+ }), parsed)
367
+ : await readDeferredRun(await createWorkspaceContext({
368
+ workspaceRoot: parsed.workspaceRoot,
369
+ mode: parsed.mode,
370
+ }), parsed.intentId, { includeOutput: parsed.includeOutput });
371
+ write(parsed.json
372
+ ? `${JSON.stringify(result, null, parsed.pretty ? 2 : 0)}\n`
373
+ : `${JSON.stringify(result, null, 2)}\n`);
374
+ return;
375
+ }
376
+ if (parsed.type === "workspace-prompt-collect") {
377
+ const result = hasSshRemote(parsed)
378
+ ? await callToybox("promptQueue.collect", compactUndefined({
379
+ cursor: parsed.cursor,
380
+ queue: parsed.queue,
381
+ mode: parsed.mode,
382
+ workspaceRoot: parsed.workspaceRoot,
383
+ }), parsed)
384
+ : await collectPromptQueueRuns(await createWorkspaceContext({
385
+ workspaceRoot: parsed.workspaceRoot,
386
+ mode: parsed.mode,
387
+ }), { cursor: parsed.cursor, queue: parsed.queue });
388
+ write(parsed.json
389
+ ? `${JSON.stringify(result, null, parsed.pretty ? 2 : 0)}\n`
390
+ : `${JSON.stringify(result, null, 2)}\n`);
391
+ return;
392
+ }
393
+ if (parsed.type === "workspace-prompt-cancel") {
394
+ const result = hasSshRemote(parsed)
395
+ ? await callToybox("promptQueue.cancel", compactUndefined({
396
+ id: parsed.intentId,
397
+ mode: parsed.mode,
398
+ workspaceRoot: parsed.workspaceRoot,
399
+ }), parsed)
400
+ : {
401
+ intent: await cancelDeferredRunIntent(await createWorkspaceContext({
402
+ workspaceRoot: parsed.workspaceRoot,
403
+ mode: parsed.mode,
404
+ }), parsed.intentId),
405
+ };
406
+ writeJson(result, parsed.pretty);
407
+ return;
408
+ }
409
+ if (parsed.type === "workspace-prompt-retry") {
410
+ const result = hasSshRemote(parsed)
411
+ ? await callToybox("promptQueue.retry", compactUndefined({
412
+ id: parsed.intentId,
413
+ runAt: parsed.runAt,
414
+ mode: parsed.mode,
415
+ workspaceRoot: parsed.workspaceRoot,
416
+ }), parsed)
417
+ : await retryDeferredRunIntent(await createWorkspaceContext({
418
+ workspaceRoot: parsed.workspaceRoot,
419
+ mode: parsed.mode,
420
+ }), parsed.intentId, compactUndefined({
421
+ runAt: parsed.runAt,
422
+ }));
423
+ writeJson(result, parsed.pretty);
424
+ return;
425
+ }
426
+ if (parsed.type === "workspace-prompt-run-due") {
427
+ const result = hasSshRemote(parsed)
428
+ ? await callToybox("promptQueue.runDue", compactUndefined({
429
+ queue: parsed.queue,
430
+ limit: parsed.limit,
431
+ mode: parsed.mode,
432
+ workspaceRoot: parsed.workspaceRoot,
433
+ }), parsed)
434
+ : await withToyboxRequest(parsed, async (request) => await runDuePromptQueueIntents(await createWorkspaceContext({
435
+ workspaceRoot: parsed.workspaceRoot,
436
+ mode: parsed.mode,
437
+ }), {
438
+ queue: parsed.queue,
439
+ limit: parsed.limit,
440
+ callToybox: request,
441
+ automationCwd: parsed.cwd,
442
+ }));
443
+ writeJson(result, parsed.pretty);
444
+ return;
445
+ }
446
+ if (parsed.type === "workspace-handoff-enqueue") {
447
+ validateAutomationTurnOptions(parsed);
448
+ const params = compactUndefined({
449
+ prompt: parsed.prompt,
450
+ title: parsed.title,
451
+ queue: parsed.queue,
452
+ labels: parsed.labels.length > 0 ? parsed.labels : undefined,
453
+ runAt: parsed.runAt,
454
+ afterIntentId: parsed.afterIntentId,
455
+ afterStatus: parsed.afterStatus,
456
+ targetHost: parsed.targetHost,
457
+ requiredCapabilities: parsed.requiredCapabilities.length > 0 ? parsed.requiredCapabilities : undefined,
458
+ requesterHost: parsed.requesterHost,
459
+ requesterThreadId: parsed.requesterThreadId,
460
+ threadId: parsed.threadId,
461
+ cwd: parsed.cwd,
462
+ model: parsed.model,
463
+ serviceTier: parsed.serviceTier,
464
+ effort: parsed.effort,
465
+ sandbox: parsed.sandbox,
466
+ approvalPolicy: parsed.approvalPolicy,
467
+ permissions: parsed.permissions,
468
+ });
469
+ const result = hasSshRemote(parsed)
470
+ ? await callToybox("localHandoff.enqueue", compactUndefined({
471
+ ...params,
472
+ mode: parsed.mode,
473
+ workspaceRoot: parsed.workspaceRoot,
474
+ }), parsed)
475
+ : {
476
+ intent: await enqueueLocalHandoffIntent(await createWorkspaceContext({
477
+ workspaceRoot: parsed.workspaceRoot,
478
+ mode: parsed.mode,
479
+ }), params),
480
+ };
481
+ writeJson(result, parsed.pretty);
482
+ return;
483
+ }
484
+ if (parsed.type === "workspace-handoff-list") {
485
+ if (hasSshRemote(parsed)) {
486
+ const result = await callToybox("localHandoff.list", compactUndefined({
487
+ status: parsed.status,
488
+ queue: parsed.queue,
489
+ targetHost: parsed.targetHost,
490
+ capabilities: parsed.capabilities.length > 0 ? parsed.capabilities : undefined,
491
+ limit: parsed.limit,
492
+ mode: parsed.mode,
493
+ workspaceRoot: parsed.workspaceRoot,
494
+ }), parsed);
495
+ write(parsed.json
496
+ ? `${JSON.stringify(result, null, parsed.pretty ? 2 : 0)}\n`
497
+ : formatLocalHandoffList((record(result).intents ?? [])));
498
+ return;
499
+ }
500
+ const context = await createWorkspaceContext({
501
+ workspaceRoot: parsed.workspaceRoot,
502
+ mode: parsed.mode,
503
+ });
504
+ const intents = await listLocalHandoffIntents(context, {
505
+ status: parsed.status,
506
+ queue: parsed.queue,
507
+ targetHost: parsed.targetHost,
508
+ capabilities: parsed.capabilities.length > 0 ? parsed.capabilities : undefined,
509
+ limit: parsed.limit,
510
+ });
511
+ write(parsed.json
512
+ ? `${JSON.stringify({ intents }, null, parsed.pretty ? 2 : 0)}\n`
513
+ : formatLocalHandoffList(intents));
514
+ return;
515
+ }
516
+ if (parsed.type === "workspace-handoff-read") {
517
+ const result = hasSshRemote(parsed)
518
+ ? await callToybox("localHandoff.read", compactUndefined({
519
+ id: parsed.intentId,
520
+ includeOutput: parsed.includeOutput,
521
+ mode: parsed.mode,
522
+ workspaceRoot: parsed.workspaceRoot,
523
+ }), parsed)
524
+ : await readDeferredRun(await createWorkspaceContext({
525
+ workspaceRoot: parsed.workspaceRoot,
526
+ mode: parsed.mode,
527
+ }), parsed.intentId, { includeOutput: parsed.includeOutput });
528
+ write(parsed.json
529
+ ? `${JSON.stringify(result, null, parsed.pretty ? 2 : 0)}\n`
530
+ : `${JSON.stringify(result, null, 2)}\n`);
531
+ return;
532
+ }
533
+ if (parsed.type === "workspace-handoff-collect") {
534
+ const options = compactUndefined({
535
+ cursor: parsed.cursor,
536
+ queue: parsed.queue,
537
+ targetHost: parsed.targetHost,
538
+ capabilities: parsed.capabilities.length > 0 ? parsed.capabilities : undefined,
539
+ });
540
+ const result = hasSshRemote(parsed)
541
+ ? await callToybox("localHandoff.collect", compactUndefined({
542
+ ...options,
543
+ mode: parsed.mode,
544
+ workspaceRoot: parsed.workspaceRoot,
545
+ }), parsed)
546
+ : await collectLocalHandoffRuns(await createWorkspaceContext({
547
+ workspaceRoot: parsed.workspaceRoot,
548
+ mode: parsed.mode,
549
+ }), options);
550
+ write(parsed.json
551
+ ? `${JSON.stringify(result, null, parsed.pretty ? 2 : 0)}\n`
552
+ : `${JSON.stringify(result, null, 2)}\n`);
553
+ return;
554
+ }
555
+ if (parsed.type === "workspace-handoff-cancel") {
556
+ const result = hasSshRemote(parsed)
557
+ ? await callToybox("localHandoff.cancel", compactUndefined({
558
+ id: parsed.intentId,
559
+ mode: parsed.mode,
560
+ workspaceRoot: parsed.workspaceRoot,
561
+ }), parsed)
562
+ : {
563
+ intent: await cancelDeferredRunIntent(await createWorkspaceContext({
564
+ workspaceRoot: parsed.workspaceRoot,
565
+ mode: parsed.mode,
566
+ }), parsed.intentId),
567
+ };
568
+ writeJson(result, parsed.pretty);
569
+ return;
570
+ }
571
+ if (parsed.type === "workspace-handoff-retry") {
572
+ const result = hasSshRemote(parsed)
573
+ ? await callToybox("localHandoff.retry", compactUndefined({
574
+ id: parsed.intentId,
575
+ runAt: parsed.runAt,
576
+ mode: parsed.mode,
577
+ workspaceRoot: parsed.workspaceRoot,
578
+ }), parsed)
579
+ : await retryDeferredRunIntent(await createWorkspaceContext({
580
+ workspaceRoot: parsed.workspaceRoot,
581
+ mode: parsed.mode,
582
+ }), parsed.intentId, compactUndefined({
583
+ runAt: parsed.runAt,
584
+ }));
585
+ writeJson(result, parsed.pretty);
586
+ return;
587
+ }
588
+ if (parsed.type === "workspace-handoff-drain") {
589
+ const action = parsed.materialize ? "materialize" : "run";
590
+ const drainParams = compactUndefined({
591
+ queue: parsed.queue,
592
+ hostId: parsed.hostId,
593
+ capabilities: parsed.capabilities.length > 0 ? parsed.capabilities : undefined,
594
+ limit: parsed.limit,
595
+ action,
596
+ promptQueue: parsed.promptQueue,
597
+ });
598
+ const result = hasSshRemote(parsed)
599
+ ? await callToybox("localHandoff.drain", compactUndefined({
600
+ ...drainParams,
601
+ mode: parsed.mode,
602
+ workspaceRoot: parsed.workspaceRoot,
603
+ }), parsed)
604
+ : await withToyboxRequest(parsed, async (request) => await drainLocalHandoffQueue(await createWorkspaceContext({
605
+ workspaceRoot: parsed.workspaceRoot,
606
+ mode: parsed.mode,
607
+ }), {
608
+ ...drainParams,
609
+ callToybox: request,
610
+ automationCwd: parsed.cwd,
611
+ }));
612
+ writeJson(result, parsed.pretty);
613
+ return;
614
+ }
281
615
  if (parsed.type === "workspace-deferred-create") {
282
616
  const params = await readParams(parsed.paramsText, parsed.paramsFile);
283
617
  const result = hasSshRemote(parsed)
@@ -365,6 +699,23 @@ async function main() {
365
699
  writeJson(result, parsed.pretty);
366
700
  return;
367
701
  }
702
+ if (parsed.type === "workspace-deferred-retry") {
703
+ const result = hasSshRemote(parsed)
704
+ ? await callToybox("deferred.retry", compactUndefined({
705
+ id: parsed.intentId,
706
+ runAt: parsed.runAt,
707
+ mode: parsed.mode,
708
+ workspaceRoot: parsed.workspaceRoot,
709
+ }), parsed)
710
+ : await retryDeferredRunIntent(await createWorkspaceContext({
711
+ workspaceRoot: parsed.workspaceRoot,
712
+ mode: parsed.mode,
713
+ }), parsed.intentId, compactUndefined({
714
+ runAt: parsed.runAt,
715
+ }));
716
+ writeJson(result, parsed.pretty);
717
+ return;
718
+ }
368
719
  if (parsed.type === "workspace-deferred-run-due") {
369
720
  const result = hasSshRemote(parsed)
370
721
  ? await callToybox("deferred.runDue", compactUndefined({
@@ -510,6 +861,26 @@ function toyboxLabelForDoctor(toybox) {
510
861
  }
511
862
  return toybox.error ? `unavailable (${toybox.error})` : "unavailable";
512
863
  }
864
+ function formatWorkspaceOverview(overview) {
865
+ const lines = [
866
+ `workspace ${overview.workspace.repoRoot}`,
867
+ `mode ${overview.workspace.mode}`,
868
+ `config ${overview.workspace.config.exists ? "found" : "missing"} ${overview.workspace.config.path}`,
869
+ `health ${overview.health.ok ? "ok" : "attention"}`,
870
+ `deferred ${overview.deferred.summary.total} total, ${overview.deferred.summary.due} due, ${overview.deferred.summary.running} running, ${overview.deferred.summary.failed} failed`,
871
+ `automations ${overview.automations.ok ? overview.automations.total : `error: ${overview.automations.error}`}`,
872
+ `functions ${overview.functions.ok ? overview.functions.total : `error: ${overview.functions.error}`}`,
873
+ `threads ${overview.threads.ok ? `${overview.threads.total} recent for cwd` : `error: ${overview.threads.error}`}`,
874
+ `git ${overview.git.ok && overview.git.isRepo ? `${overview.git.branch ?? "unknown"} ${overview.git.commit ?? ""}${overview.git.dirty ? " dirty" : ""}` : overview.git.error ?? "not a git repo"}`,
875
+ ];
876
+ if (overview.deferred.latest) {
877
+ lines.push(`latest deferred ${overview.deferred.latest.status} ${overview.deferred.latest.id} ${overview.deferred.latest.updatedAt}`);
878
+ }
879
+ for (const check of overview.health.checks.filter((item) => !item.ok)) {
880
+ lines.push(`check ${check.name} ${check.status}${check.error ? `: ${check.error}` : ""}`);
881
+ }
882
+ return `${lines.join("\n")}\n`;
883
+ }
513
884
  async function callAppServer(method, params, options) {
514
885
  return await callToybox(APP_CALL_METHOD, { method, params }, options);
515
886
  }
@@ -919,6 +1290,47 @@ function deferredTargetLabel(target) {
919
1290
  }
920
1291
  return "turn";
921
1292
  }
1293
+ function formatPromptQueueList(intents) {
1294
+ if (intents.length === 0) {
1295
+ return "No queued prompts found.\n";
1296
+ }
1297
+ return intents.map((intent) => [
1298
+ intent.id,
1299
+ intent.status,
1300
+ intent.runAt,
1301
+ promptQueueLabel(intent),
1302
+ ].join(" ")).join("\n") + "\n";
1303
+ }
1304
+ function promptQueueLabel(intent) {
1305
+ const source = record(intent.source);
1306
+ const queue = stringValue(source.queue) ?? "default";
1307
+ const title = stringValue(source.title);
1308
+ if (title) {
1309
+ return `${queue}:${title}`;
1310
+ }
1311
+ return queue;
1312
+ }
1313
+ function formatLocalHandoffList(intents) {
1314
+ if (intents.length === 0) {
1315
+ return "No local handoffs found.\n";
1316
+ }
1317
+ return intents.map((intent) => [
1318
+ intent.id,
1319
+ intent.status,
1320
+ intent.runAt,
1321
+ localHandoffLabel(intent),
1322
+ ].join(" ")).join("\n") + "\n";
1323
+ }
1324
+ function localHandoffLabel(intent) {
1325
+ const source = record(intent.source);
1326
+ const queue = stringValue(source.queue) ?? "local";
1327
+ const targetHost = stringValue(source.targetHost) ?? "local-controller";
1328
+ const title = stringValue(source.title);
1329
+ if (title) {
1330
+ return `${queue}:${targetHost}:${title}`;
1331
+ }
1332
+ return `${queue}:${targetHost}`;
1333
+ }
922
1334
  function record(value) {
923
1335
  return typeof value === "object" && value !== null && !Array.isArray(value)
924
1336
  ? value
@@ -979,6 +1391,8 @@ Usage:
979
1391
  codex-toys mcp serve
980
1392
 
981
1393
  codex-toys --ssh <target> --cwd <remote-workspace> remote preflight [--json]
1394
+ codex-toys host overview --json
1395
+ codex-toys --ssh <target> --cwd <remote-workspace> remote host-overview --json
982
1396
 
983
1397
  codex-toys turn run <prompt> [--wait] [--thread-id <id>]
984
1398
  codex-toys --ssh <target> --cwd <remote-workspace> turn run <prompt> --wait
@@ -1006,17 +1420,27 @@ Usage:
1006
1420
  codex-toys workspace call <method> [params-json]
1007
1421
  codex-toys workspace app <method> [params-json]
1008
1422
  codex-toys workspace methods
1423
+ codex-toys workspace overview [--json]
1009
1424
  codex-toys workspace delegate list [--json]
1010
1425
  codex-toys workspace delegate start --cwd @/workspaces/name --prompt <text> [--wait]
1011
- codex-toys workspace doctor [--mode auto|local|actions] [--json]
1012
- codex-toys workspace tick [--mode auto|local|actions]
1013
- codex-toys workspace run <task-id> [--mode auto|local|actions]
1014
- codex-toys workspace deferred create --params-json <json>
1426
+ codex-toys workspace doctor [--mode auto|local|actions] [--json]
1427
+ codex-toys workspace tick [--mode auto|local|actions]
1428
+ codex-toys workspace run <task-id> [--mode auto|local|actions]
1429
+ codex-toys workspace prompt enqueue <prompt> [--run-at <iso>] [--after <intent-id>]
1430
+ codex-toys workspace prompt list [--queue <name>] [--status <status>] [--json]
1431
+ codex-toys workspace prompt pull <intent-id> [--json]
1432
+ codex-toys workspace prompt collect [--cursor <name>] [--queue <name>] [--json]
1433
+ codex-toys workspace prompt run-due [--queue <name>] [--limit <n>]
1434
+ codex-toys workspace handoff enqueue <prompt> [--target-host <host>] [--capability <name>]
1435
+ codex-toys workspace handoff list [--queue <name>] [--status <status>] [--json]
1436
+ codex-toys workspace handoff drain [--host-id <host>] [--capability <name>] [--materialize]
1437
+ codex-toys workspace deferred create --params-json <json>
1015
1438
  codex-toys workspace deferred list [--mode auto|local|actions] [--json]
1016
1439
  codex-toys workspace deferred read <intent-id> [--include-output] [--json]
1017
1440
  codex-toys workspace deferred pull <intent-id> [--json]
1018
1441
  codex-toys workspace deferred collect [--cursor <name>] [--json]
1019
1442
  codex-toys workspace deferred cancel <intent-id>
1443
+ codex-toys workspace deferred retry <intent-id> [--run-at <iso>]
1020
1444
  codex-toys workspace deferred run-due [--mode auto|local|actions]
1021
1445
  codex-toys workspace deferred prune --older-than-days <days> [--dry-run]
1022
1446
  codex-toys workspace init actions [--forgejo|--github]
@@ -1067,9 +1491,20 @@ Options:
1067
1491
  or workspace tasks.
1068
1492
  --forgejo Generate a Forgejo Actions workflow.
1069
1493
  --github Generate a GitHub Actions workflow.
1070
- --prompt <text> Prompt text for automation script context.
1071
- --title <text> Delegation thread title.
1072
- --group-id <id> Delegation group id.
1494
+ --prompt <text> Prompt text for automation script context.
1495
+ --title <text> Delegation thread title or queued prompt title.
1496
+ --queue <name> Prompt queue name.
1497
+ --label <label> Prompt queue label. Repeatable.
1498
+ --after <intent-id> Hold queued prompt until another intent finishes.
1499
+ --after-status <status> Dependency status: completed, failed,
1500
+ canceled, or terminal.
1501
+ --status <status> Deferred/prompt status filter.
1502
+ --limit <n> Limit listed or due queued work.
1503
+ --run-at <iso> Future run time for deferred or queued work.
1504
+ --service-tier <tier> Turn service tier for queued prompts.
1505
+ --effort <effort> Reasoning effort: none, minimal, low,
1506
+ medium, high, or xhigh.
1507
+ --group-id <id> Delegation group id.
1073
1508
  --return-mode <mode> Delegation return mode: detached,
1074
1509
  record_only, wake_on_done,
1075
1510
  wake_on_group, or manual.
@@ -1108,6 +1543,8 @@ Examples:
1108
1543
  codex-toys mcp serve
1109
1544
  codex-toys toybox serve --cwd /repo
1110
1545
  codex-toys --ssh devbox --cwd /repo fetch
1546
+ codex-toys host overview --json
1547
+ codex-toys --ssh devbox --cwd /repo remote host-overview --json
1111
1548
  codex-toys --ssh devbox --cwd /repo turn run "Scan current folder" --wait
1112
1549
  codex-toys automation list
1113
1550
  codex-toys automation run check-release --event event.json
@@ -1120,6 +1557,7 @@ Examples:
1120
1557
  codex-toys app thread/list '{"limit":20,"sourceKinds":[]}'
1121
1558
  codex-toys workspace app thread/list '{"limit":20,"sourceKinds":[]}'
1122
1559
  codex-toys workspace delegation.list
1560
+ codex-toys workspace overview --json
1123
1561
  codex-toys workspace delegate start --cwd @/workspaces/trading --prompt "Inspect status"
1124
1562
  codex-toys workspace doctor --mode actions
1125
1563
  codex-toys workspace deferred create --params-json '{"runAt":"2026-01-01T14:00:00.000Z","target":{"kind":"turn","prompt":"Review the workspace."}}'