@enderfga/claw-orchestrator 4.6.0 → 4.8.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.
Files changed (59) hide show
  1. package/README.md +6 -5
  2. package/configs/autoloop-coder-prompt.md +4 -4
  3. package/configs/autoloop-planner-prompt.md +10 -10
  4. package/configs/autoloop-reviewer-prompt.md +3 -4
  5. package/dist/bin/cli.js +1 -1
  6. package/dist/bin/cli.js.map +1 -1
  7. package/dist/src/agy-conversation.d.ts +2 -0
  8. package/dist/src/agy-conversation.js +10 -0
  9. package/dist/src/agy-conversation.js.map +1 -0
  10. package/dist/src/autoloop/dispatcher.d.ts +59 -10
  11. package/dist/src/autoloop/dispatcher.js +261 -40
  12. package/dist/src/autoloop/dispatcher.js.map +1 -1
  13. package/dist/src/autoloop/planner-tools.d.ts +4 -3
  14. package/dist/src/autoloop/planner-tools.js +35 -2
  15. package/dist/src/autoloop/planner-tools.js.map +1 -1
  16. package/dist/src/autoloop/types.d.ts +2 -0
  17. package/dist/src/autoloop/types.js.map +1 -1
  18. package/dist/src/dashboard/index.html +185 -94
  19. package/dist/src/embedded-server.js +67 -9
  20. package/dist/src/embedded-server.js.map +1 -1
  21. package/dist/src/index.d.ts +1 -0
  22. package/dist/src/index.js +98 -61
  23. package/dist/src/index.js.map +1 -1
  24. package/dist/src/models.js +68 -3
  25. package/dist/src/models.js.map +1 -1
  26. package/dist/src/persistent-agy-session.d.ts +60 -0
  27. package/dist/src/persistent-agy-session.js +228 -0
  28. package/dist/src/persistent-agy-session.js.map +1 -0
  29. package/dist/src/persistent-codex-session.js +3 -0
  30. package/dist/src/persistent-codex-session.js.map +1 -1
  31. package/dist/src/persistent-cursor-session.js +9 -6
  32. package/dist/src/persistent-cursor-session.js.map +1 -1
  33. package/dist/src/persistent-custom-session.js +18 -32
  34. package/dist/src/persistent-custom-session.js.map +1 -1
  35. package/dist/src/persistent-gemini-session.d.ts +4 -0
  36. package/dist/src/persistent-gemini-session.js +58 -7
  37. package/dist/src/persistent-gemini-session.js.map +1 -1
  38. package/dist/src/persistent-opencode-session.js +37 -7
  39. package/dist/src/persistent-opencode-session.js.map +1 -1
  40. package/dist/src/persistent-session.js +8 -9
  41. package/dist/src/persistent-session.js.map +1 -1
  42. package/dist/src/sanitize.d.ts +23 -0
  43. package/dist/src/sanitize.js +57 -0
  44. package/dist/src/sanitize.js.map +1 -0
  45. package/dist/src/session-manager.d.ts +49 -2
  46. package/dist/src/session-manager.js +254 -35
  47. package/dist/src/session-manager.js.map +1 -1
  48. package/dist/src/types.d.ts +8 -4
  49. package/dist/src/types.js +2 -0
  50. package/dist/src/types.js.map +1 -1
  51. package/package.json +1 -1
  52. package/skills/SKILL.md +17 -14
  53. package/skills/references/autoloop.md +50 -6
  54. package/skills/references/claude-cli-tracking.md +3 -1
  55. package/skills/references/cli.md +4 -3
  56. package/skills/references/mcp.md +1 -1
  57. package/skills/references/multi-engine.md +53 -8
  58. package/skills/references/sessions.md +2 -2
  59. package/skills/references/tools.md +40 -21
@@ -18,6 +18,7 @@
18
18
  * parser for real tool dispatch without changing any Planner-facing
19
19
  * semantics.
20
20
  */
21
+ import { ENGINE_TYPES } from '../types.js';
21
22
  import { Msg } from './messages.js';
22
23
  const FENCE_RE = /```autoloop\s*\n([\s\S]*?)\n```/g;
23
24
  /**
@@ -74,9 +75,41 @@ export async function applyPlannerToolCalls(calls, fx, iter) {
74
75
  break;
75
76
  }
76
77
  case 'spawn_subagents': {
77
- await fx.spawnSubagents(call.args);
78
+ const raw = call.args;
79
+ if ('coder_custom_engine' in raw ||
80
+ 'reviewer_custom_engine' in raw ||
81
+ 'coderCustomEngine' in raw ||
82
+ 'reviewerCustomEngine' in raw ||
83
+ 'customEngine' in raw) {
84
+ throw new Error('spawn_subagents cannot include custom engine config; configure it at autoloop_start');
85
+ }
86
+ for (const field of ['coder_engine', 'reviewer_engine']) {
87
+ const value = raw[field];
88
+ if (value !== undefined && (typeof value !== 'string' || !ENGINE_TYPES.includes(value))) {
89
+ throw new Error(`spawn_subagents ${field} has unknown engine '${String(value)}'`);
90
+ }
91
+ }
92
+ for (const field of ['coder_model', 'reviewer_model']) {
93
+ const value = raw[field];
94
+ if (value !== undefined && typeof value !== 'string') {
95
+ throw new Error(`spawn_subagents ${field} must be a string`);
96
+ }
97
+ }
98
+ const args = {};
99
+ if (raw.coder_engine !== undefined)
100
+ args.coder_engine = raw.coder_engine;
101
+ if (raw.coder_model !== undefined)
102
+ args.coder_model = raw.coder_model;
103
+ if (raw.reviewer_engine !== undefined)
104
+ args.reviewer_engine = raw.reviewer_engine;
105
+ if (raw.reviewer_model !== undefined)
106
+ args.reviewer_model = raw.reviewer_model;
107
+ if (raw.initial_directive !== undefined) {
108
+ args.initial_directive = raw.initial_directive;
109
+ }
110
+ await fx.spawnSubagents(args);
78
111
  // If caller asked for an initial directive, fire it via the runner queue.
79
- const init = call.args.initial_directive;
112
+ const init = args.initial_directive;
80
113
  if (init?.goal) {
81
114
  emitted_messages.push(Msg.directive(iter, {
82
115
  goal: init.goal,
@@ -1 +1 @@
1
- {"version":3,"file":"planner-tools.js","sourceRoot":"","sources":["../../../src/autoloop/planner-tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"planner-tools.js","sourceRoot":"","sources":["../../../src/autoloop/planner-tools.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,8 @@
3
3
  */
4
4
  import type { AnyAutoloopMessage, PushChannel, PushLevel } from './messages.js';
5
5
  export type AutoloopStatus = 'planning' | 'running' | 'paused' | 'terminated' | 'crashed';
6
+ /** The three autoloop roles. Single source of truth — dispatcher and SessionManager both use it. */
7
+ export type AutoloopRoleName = 'planner' | 'coder' | 'reviewer';
6
8
  export interface AutoloopState {
7
9
  run_id: string;
8
10
  status: AutoloopStatus;
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/autoloop/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAgCH,+EAA+E;AAC/E,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AACrC,uFAAuF;AACvF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAmBvC,MAAM,CAAC,MAAM,mBAAmB,GAAe;IAC7C,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;IAC9C,eAAe,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;IACjC,aAAa,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;IACjD,sBAAsB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;IAC1D,oBAAoB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;IACxD,cAAc,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE;IACnD,cAAc,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;IACpD,kBAAkB,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE;CAC3D,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/autoloop/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmCH,+EAA+E;AAC/E,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AACrC,uFAAuF;AACvF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAmBvC,MAAM,CAAC,MAAM,mBAAmB,GAAe;IAC7C,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;IAC9C,eAAe,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;IACjC,aAAa,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;IACjD,sBAAsB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;IAC1D,oBAAoB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;IACxD,cAAc,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE;IACnD,cAAc,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;IACpD,kBAAkB,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE;CAC3D,CAAC"}
@@ -27,7 +27,12 @@
27
27
  margin: 0;
28
28
  background: var(--bg);
29
29
  color: var(--text);
30
- font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
30
+ font:
31
+ 14px/1.5 -apple-system,
32
+ BlinkMacSystemFont,
33
+ 'Segoe UI',
34
+ Roboto,
35
+ sans-serif;
31
36
  }
32
37
  a {
33
38
  color: var(--info);
@@ -270,8 +275,7 @@
270
275
  .entryBody {
271
276
  white-space: pre-wrap;
272
277
  word-wrap: break-word;
273
- font-family:
274
- ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
278
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
275
279
  font-size: 12px;
276
280
  background: #fafafa;
277
281
  padding: 8px 10px;
@@ -379,11 +383,23 @@
379
383
  align-self: flex-start;
380
384
  }
381
385
  .forge-mode[data-mode='build'],
382
- .forge-mode[data-mode='building'] { background: var(--info); color: white; }
386
+ .forge-mode[data-mode='building'] {
387
+ background: var(--info);
388
+ color: white;
389
+ }
383
390
  .forge-mode[data-mode='done'],
384
- .forge-mode[data-mode='build-complete'] { background: var(--accent); color: white; }
385
- .forge-mode[data-mode='failed'] { background: var(--error); color: white; }
386
- .forge-mode[data-mode='queued'] { background: var(--warn); color: white; }
391
+ .forge-mode[data-mode='build-complete'] {
392
+ background: var(--accent);
393
+ color: white;
394
+ }
395
+ .forge-mode[data-mode='failed'] {
396
+ background: var(--error);
397
+ color: white;
398
+ }
399
+ .forge-mode[data-mode='queued'] {
400
+ background: var(--warn);
401
+ color: white;
402
+ }
387
403
  .forge-empty {
388
404
  margin: auto;
389
405
  max-width: 440px;
@@ -402,9 +418,19 @@
402
418
  border-radius: 4px;
403
419
  font-size: 13px;
404
420
  }
405
- .forge-msg.user { background: #e0eaff; align-self: flex-end; }
406
- .forge-msg.assistant { background: var(--surface); border: 1px solid var(--border); }
407
- .forge-msg.system { background: var(--surface-2); color: var(--muted); font-size: 12px; }
421
+ .forge-msg.user {
422
+ background: #e0eaff;
423
+ align-self: flex-end;
424
+ }
425
+ .forge-msg.assistant {
426
+ background: var(--surface);
427
+ border: 1px solid var(--border);
428
+ }
429
+ .forge-msg.system {
430
+ background: var(--surface-2);
431
+ color: var(--muted);
432
+ font-size: 12px;
433
+ }
408
434
  .forge-share {
409
435
  background: var(--surface);
410
436
  border: 1px solid var(--accent);
@@ -412,9 +438,20 @@
412
438
  padding: 12px;
413
439
  margin: 8px 0;
414
440
  }
415
- .forge-share strong { color: var(--accent); display: block; margin-bottom: 6px; }
416
- .forge-share a { color: var(--accent); word-break: break-all; }
417
- .forge-share-actions { display: flex; gap: 8px; margin-top: 10px; }
441
+ .forge-share strong {
442
+ color: var(--accent);
443
+ display: block;
444
+ margin-bottom: 6px;
445
+ }
446
+ .forge-share a {
447
+ color: var(--accent);
448
+ word-break: break-all;
449
+ }
450
+ .forge-share-actions {
451
+ display: flex;
452
+ gap: 8px;
453
+ margin-top: 10px;
454
+ }
418
455
  .forge-share-actions button {
419
456
  padding: 4px 12px;
420
457
  font-size: 12px;
@@ -436,13 +473,17 @@
436
473
  font-size: 12px;
437
474
  overflow-x: auto;
438
475
  }
439
- .forge-public-modal h4 { margin-bottom: 4px; }
476
+ .forge-public-modal h4 {
477
+ margin-bottom: 4px;
478
+ }
440
479
  .runItem .lifecycle-actions {
441
480
  display: none;
442
481
  gap: 4px;
443
482
  margin-top: 4px;
444
483
  }
445
- .runItem:hover .lifecycle-actions { display: flex; }
484
+ .runItem:hover .lifecycle-actions {
485
+ display: flex;
486
+ }
446
487
  .lifecycle-actions button {
447
488
  font-size: 10px;
448
489
  padding: 2px 6px;
@@ -451,7 +492,9 @@
451
492
  border-radius: 3px;
452
493
  cursor: pointer;
453
494
  }
454
- .lifecycle-actions button:hover { background: var(--surface-2); }
495
+ .lifecycle-actions button:hover {
496
+ background: var(--surface-2);
497
+ }
455
498
  .forge-question {
456
499
  background: var(--surface);
457
500
  border: 1px solid var(--border);
@@ -459,9 +502,21 @@
459
502
  padding: 12px;
460
503
  margin: 8px 0;
461
504
  }
462
- .forge-question .ctx { color: var(--muted); font-size: 12px; margin-bottom: 8px; }
463
- .forge-question .q { font-weight: 600; margin-bottom: 8px; }
464
- .forge-question .opts { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
505
+ .forge-question .ctx {
506
+ color: var(--muted);
507
+ font-size: 12px;
508
+ margin-bottom: 8px;
509
+ }
510
+ .forge-question .q {
511
+ font-weight: 600;
512
+ margin-bottom: 8px;
513
+ }
514
+ .forge-question .opts {
515
+ display: flex;
516
+ flex-wrap: wrap;
517
+ gap: 6px;
518
+ margin-bottom: 8px;
519
+ }
465
520
  .forge-question .opt {
466
521
  padding: 4px 10px;
467
522
  border: 1px solid var(--border);
@@ -470,8 +525,14 @@
470
525
  font-size: 12px;
471
526
  background: var(--surface);
472
527
  }
473
- .forge-question .opt.recommended { border-color: var(--accent); }
474
- .forge-question .opt.selected { background: var(--accent); color: white; border-color: var(--accent); }
528
+ .forge-question .opt.recommended {
529
+ border-color: var(--accent);
530
+ }
531
+ .forge-question .opt.selected {
532
+ background: var(--accent);
533
+ color: white;
534
+ border-color: var(--accent);
535
+ }
475
536
  .forge-input {
476
537
  display: grid;
477
538
  grid-template-columns: 1fr auto;
@@ -500,7 +561,10 @@
500
561
  color: white;
501
562
  cursor: pointer;
502
563
  }
503
- .forge-input button:disabled { opacity: 0.4; cursor: not-allowed; }
564
+ .forge-input button:disabled {
565
+ opacity: 0.4;
566
+ cursor: not-allowed;
567
+ }
504
568
  .forge-spec {
505
569
  border-left: 1px solid var(--border);
506
570
  padding: 16px;
@@ -509,7 +573,9 @@
509
573
  display: flex;
510
574
  flex-direction: column;
511
575
  }
512
- .forge-spec h3 { margin: 0 0 8px 0; }
576
+ .forge-spec h3 {
577
+ margin: 0 0 8px 0;
578
+ }
513
579
  .forge-spec textarea {
514
580
  width: 100%;
515
581
  font-family: ui-monospace, SFMono-Regular, monospace;
@@ -532,7 +598,10 @@
532
598
  background: var(--surface);
533
599
  cursor: pointer;
534
600
  }
535
- .forge-spec-msg { font-size: 11px; color: var(--muted); }
601
+ .forge-spec-msg {
602
+ font-size: 11px;
603
+ color: var(--muted);
604
+ }
536
605
  #forgeNew,
537
606
  #councilNew,
538
607
  #autoloopNew {
@@ -561,7 +630,9 @@
561
630
  justify-content: center;
562
631
  z-index: 100;
563
632
  }
564
- .modal-root[hidden] { display: none; }
633
+ .modal-root[hidden] {
634
+ display: none;
635
+ }
565
636
  .modal {
566
637
  background: var(--surface);
567
638
  border-radius: 8px;
@@ -576,7 +647,10 @@
576
647
  padding: 14px 20px;
577
648
  border-bottom: 1px solid var(--border);
578
649
  }
579
- .modal-header h2 { margin: 0; font-size: 15px; }
650
+ .modal-header h2 {
651
+ margin: 0;
652
+ font-size: 15px;
653
+ }
580
654
  .modal-header button {
581
655
  background: transparent;
582
656
  border: none;
@@ -637,8 +711,14 @@
637
711
  margin: 80px auto 0;
638
712
  max-width: 420px;
639
713
  }
640
- .empty-cta h2 { margin: 0 0 8px; font-size: 16px; }
641
- .empty-cta p { margin: 0 0 16px; color: var(--muted); }
714
+ .empty-cta h2 {
715
+ margin: 0 0 8px;
716
+ font-size: 16px;
717
+ }
718
+ .empty-cta p {
719
+ margin: 0 0 16px;
720
+ color: var(--muted);
721
+ }
642
722
  .empty-cta button {
643
723
  padding: 8px 16px;
644
724
  border-radius: 4px;
@@ -658,10 +738,24 @@
658
738
  cursor: pointer;
659
739
  font-weight: 600;
660
740
  }
661
- #forgeStartBuild:disabled { opacity: 0.4; cursor: not-allowed; }
662
- .forge-versions { margin-top: 12px; }
663
- .forge-versions h4 { margin: 0 0 6px 0; font-size: 12px; color: var(--muted); text-transform: uppercase; }
664
- .version-list { list-style: none; padding: 0; margin: 0; }
741
+ #forgeStartBuild:disabled {
742
+ opacity: 0.4;
743
+ cursor: not-allowed;
744
+ }
745
+ .forge-versions {
746
+ margin-top: 12px;
747
+ }
748
+ .forge-versions h4 {
749
+ margin: 0 0 6px 0;
750
+ font-size: 12px;
751
+ color: var(--muted);
752
+ text-transform: uppercase;
753
+ }
754
+ .version-list {
755
+ list-style: none;
756
+ padding: 0;
757
+ margin: 0;
758
+ }
665
759
  .version-row {
666
760
  display: flex;
667
761
  gap: 8px;
@@ -677,8 +771,14 @@
677
771
  font-family: monospace;
678
772
  font-weight: 600;
679
773
  }
680
- .version-meta { color: var(--muted); }
681
- .version-row a { color: var(--accent); text-decoration: none; word-break: break-all; }
774
+ .version-meta {
775
+ color: var(--muted);
776
+ }
777
+ .version-row a {
778
+ color: var(--accent);
779
+ text-decoration: none;
780
+ word-break: break-all;
781
+ }
682
782
  .version-row button {
683
783
  margin-left: auto;
684
784
  padding: 2px 8px;
@@ -688,7 +788,10 @@
688
788
  border-radius: 3px;
689
789
  cursor: pointer;
690
790
  }
691
- .version-row button:disabled { opacity: 0.4; cursor: not-allowed; }
791
+ .version-row button:disabled {
792
+ opacity: 0.4;
793
+ cursor: not-allowed;
794
+ }
692
795
  </style>
693
796
  </head>
694
797
  <body>
@@ -733,19 +836,11 @@
733
836
  <div data-for-tab="council" style="display: contents">
734
837
  <label>
735
838
  Task
736
- <textarea
737
- name="task"
738
- rows="3"
739
- placeholder="What should the council achieve?"
740
- ></textarea>
839
+ <textarea name="task" rows="3" placeholder="What should the council achieve?"></textarea>
741
840
  </label>
742
841
  <label>
743
842
  Project directory
744
- <input
745
- name="projectDir"
746
- type="text"
747
- placeholder="/abs/path/to/workspace"
748
- />
843
+ <input name="projectDir" type="text" placeholder="/abs/path/to/workspace" />
749
844
  </label>
750
845
  <label>
751
846
  Max rounds
@@ -756,11 +851,7 @@
756
851
  <div data-for-tab="autoloop" style="display: contents">
757
852
  <label>
758
853
  Workspace
759
- <input
760
- name="workspace"
761
- type="text"
762
- placeholder="/abs/path/to/git/workspace"
763
- />
854
+ <input name="workspace" type="text" placeholder="/abs/path/to/git/workspace" />
764
855
  </label>
765
856
  <label>
766
857
  Planner model (optional)
@@ -807,11 +898,11 @@
807
898
  };
808
899
 
809
900
  const $ = (id) => document.getElementById(id);
810
- const fmtTime = (iso) =>
811
- iso ? new Date(iso).toLocaleTimeString(undefined, { hour12: false }) : '';
901
+ const fmtTime = (iso) => (iso ? new Date(iso).toLocaleTimeString(undefined, { hour12: false }) : '');
812
902
  const escapeHtml = (s) =>
813
- String(s ?? '').replace(/[&<>"']/g, (c) =>
814
- ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' })[c],
903
+ String(s ?? '').replace(
904
+ /[&<>"']/g,
905
+ (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' })[c],
815
906
  );
816
907
 
817
908
  // ─── Tab switching ────────────────────────────────────────────
@@ -826,11 +917,7 @@
826
917
  b.setAttribute('aria-selected', String(b.dataset.tab === tab));
827
918
  });
828
919
  $('sidebarTitle').textContent =
829
- tab === 'autoloop'
830
- ? 'Autoloop runs'
831
- : tab === 'council'
832
- ? 'Council sessions'
833
- : 'Forge apps';
920
+ tab === 'autoloop' ? 'Autoloop runs' : tab === 'council' ? 'Council sessions' : 'Forge apps';
834
921
  $('forgeNew').hidden = tab !== 'forge';
835
922
  $('councilNew').hidden = tab !== 'council';
836
923
  $('autoloopNew').hidden = tab !== 'autoloop';
@@ -879,11 +966,7 @@
879
966
  const noun = labels[state.tab] || 'run';
880
967
  if (state.runs.length === 0) {
881
968
  const triggerId =
882
- state.tab === 'autoloop'
883
- ? 'autoloopNew'
884
- : state.tab === 'council'
885
- ? 'councilNew'
886
- : 'forgeNew';
969
+ state.tab === 'autoloop' ? 'autoloopNew' : state.tab === 'council' ? 'councilNew' : 'forgeNew';
887
970
  $('main').innerHTML = `
888
971
  <div class="empty empty-cta">
889
972
  <h2>No ${escapeHtml(noun)}s yet</h2>
@@ -892,8 +975,7 @@
892
975
  </div>
893
976
  `;
894
977
  } else {
895
- $('main').innerHTML =
896
- '<div class="empty" style="margin-top:80px">Select a run to view.</div>';
978
+ $('main').innerHTML = '<div class="empty" style="margin-top:80px">Select a run to view.</div>';
897
979
  }
898
980
  }
899
981
 
@@ -901,20 +983,15 @@
901
983
  async function refreshList() {
902
984
  try {
903
985
  const url =
904
- state.tab === 'autoloop'
905
- ? '/autoloop/list'
906
- : state.tab === 'council'
907
- ? '/council/list'
908
- : '/ultraapp/list';
909
- const opts = state.tab === 'forge' ? { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{}' } : {};
986
+ state.tab === 'autoloop' ? '/autoloop/list' : state.tab === 'council' ? '/council/list' : '/ultraapp/list';
987
+ const opts =
988
+ state.tab === 'forge'
989
+ ? { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{}' }
990
+ : {};
910
991
  const r = await fetch(url, opts);
911
992
  const j = await r.json();
912
993
  state.runs =
913
- state.tab === 'autoloop'
914
- ? j.runs || []
915
- : state.tab === 'council'
916
- ? j.councils || []
917
- : j.runs || [];
994
+ state.tab === 'autoloop' ? j.runs || [] : state.tab === 'council' ? j.councils || [] : j.runs || [];
918
995
  renderList();
919
996
  // Refresh the empty-state CTA — runs may have just appeared or
920
997
  // disappeared, and renderEmptyMain's text depends on state.runs.length.
@@ -929,12 +1006,8 @@
929
1006
  function renderList() {
930
1007
  const ul = $('runlist');
931
1008
  if (state.runs.length === 0) {
932
- const noun =
933
- state.tab === 'autoloop' ? 'runs' : state.tab === 'council' ? 'councils' : 'apps';
934
- ul.innerHTML =
935
- '<li class="empty" style="padding:20px;list-style:none">No active ' +
936
- noun +
937
- '.</li>';
1009
+ const noun = state.tab === 'autoloop' ? 'runs' : state.tab === 'council' ? 'councils' : 'apps';
1010
+ ul.innerHTML = '<li class="empty" style="padding:20px;list-style:none">No active ' + noun + '.</li>';
938
1011
  return;
939
1012
  }
940
1013
  const html = state.runs
@@ -998,12 +1071,26 @@
998
1071
  const id = el.dataset.id;
999
1072
  if (state.tab === 'autoloop') {
1000
1073
  if (action !== 'delete') return;
1001
- if (!confirm(`Delete autoloop run "${id}"? The registry entry is removed; the ledger directory under tasks/${id}/ is kept on disk.`)) return;
1074
+ if (
1075
+ !confirm(
1076
+ `Delete autoloop run "${id}"? The registry entry is removed; the ledger directory under tasks/${id}/ is kept on disk.`,
1077
+ )
1078
+ )
1079
+ return;
1002
1080
  try {
1003
- const r = await fetch(`/autoloop/${encodeURIComponent(id)}/delete`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: '{}' });
1081
+ const r = await fetch(`/autoloop/${encodeURIComponent(id)}/delete`, {
1082
+ method: 'POST',
1083
+ headers: { 'content-type': 'application/json' },
1084
+ body: '{}',
1085
+ });
1004
1086
  if (!r.ok) {
1005
1087
  let detail = `HTTP ${r.status}`;
1006
- try { const j = await r.json(); if (j && j.error) detail = j.error; } catch { /* ignore */ }
1088
+ try {
1089
+ const j = await r.json();
1090
+ if (j && j.error) detail = j.error;
1091
+ } catch {
1092
+ /* ignore */
1093
+ }
1007
1094
  alert(`Delete failed: ${detail}`);
1008
1095
  return;
1009
1096
  }
@@ -1020,7 +1107,11 @@
1020
1107
  refreshList();
1021
1108
  return;
1022
1109
  }
1023
- if (action === 'delete' && !confirm('Delete this run? Container, image, and on-disk artifacts are removed.')) return;
1110
+ if (
1111
+ action === 'delete' &&
1112
+ !confirm('Delete this run? Container, image, and on-disk artifacts are removed.')
1113
+ )
1114
+ return;
1024
1115
  await forgeLifecycleAction(id, action);
1025
1116
  refreshList();
1026
1117
  });
@@ -1272,7 +1363,11 @@
1272
1363
  });
1273
1364
  const j = await r.json();
1274
1365
  if (!j.ok) {
1275
- renderChatEntry({ role: 'system', kind: 'error', text: '[error] ' + action + ': ' + (j.error || 'unknown') });
1366
+ renderChatEntry({
1367
+ role: 'system',
1368
+ kind: 'error',
1369
+ text: '[error] ' + action + ': ' + (j.error || 'unknown'),
1370
+ });
1276
1371
  }
1277
1372
  if (action === 'delete' && j.ok && state.forge.runId === runId) {
1278
1373
  // Run is gone — close it and refresh sidebar
@@ -1856,10 +1951,7 @@
1856
1951
  const s = state.council.session;
1857
1952
  if (!s) return;
1858
1953
  $('c-status').innerHTML = `<span class="badge ${s.status}">${s.status}</span>`;
1859
- const rounds =
1860
- s.responses && s.responses.length > 0
1861
- ? Math.max(...s.responses.map((r) => r.round))
1862
- : 0;
1954
+ const rounds = s.responses && s.responses.length > 0 ? Math.max(...s.responses.map((r) => r.round)) : 0;
1863
1955
  $('c-round').textContent = rounds;
1864
1956
  $('c-agents').textContent = (s.config?.agents || []).map((a) => a.name).join(', ');
1865
1957
  $('c-task').textContent = s.task || '';
@@ -1944,8 +2036,7 @@
1944
2036
  // both, switching visible fields by state.tab.
1945
2037
  function openLauncherModal() {
1946
2038
  const root = $('modalRoot');
1947
- $('modalTitle').textContent =
1948
- state.tab === 'council' ? 'New Council session' : 'New Autoloop run';
2039
+ $('modalTitle').textContent = state.tab === 'council' ? 'New Council session' : 'New Autoloop run';
1949
2040
  root.querySelectorAll('[data-for-tab]').forEach((el) => {
1950
2041
  const visible = el.dataset.forTab === state.tab;
1951
2042
  el.style.display = visible ? 'contents' : 'none';