deepclause-sdk 0.1.2 → 0.2.1

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 (122) hide show
  1. package/README.md +45 -6
  2. package/dist/cli/config.d.ts +2 -2
  3. package/dist/cli/repl.d.ts +55 -4
  4. package/dist/cli/repl.d.ts.map +1 -1
  5. package/dist/cli/repl.js +675 -52
  6. package/dist/cli/repl.js.map +1 -1
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +3 -0
  10. package/dist/index.js.map +1 -1
  11. package/dist/prolog-src/deepclause_mi.pl +516 -2
  12. package/dist/repl/backend.d.ts +9 -0
  13. package/dist/repl/backend.d.ts.map +1 -1
  14. package/dist/repl/backend.js +62 -5
  15. package/dist/repl/backend.js.map +1 -1
  16. package/dist/repl/harness-tools.d.ts +36 -0
  17. package/dist/repl/harness-tools.d.ts.map +1 -1
  18. package/dist/repl/harness-tools.js +173 -0
  19. package/dist/repl/harness-tools.js.map +1 -1
  20. package/dist/repl/history.d.ts +29 -0
  21. package/dist/repl/history.d.ts.map +1 -1
  22. package/dist/repl/history.js +71 -0
  23. package/dist/repl/history.js.map +1 -1
  24. package/dist/repl/index.d.ts +6 -0
  25. package/dist/repl/index.d.ts.map +1 -1
  26. package/dist/repl/index.js +9 -1
  27. package/dist/repl/index.js.map +1 -1
  28. package/dist/repl/picker.d.ts +3 -0
  29. package/dist/repl/picker.d.ts.map +1 -1
  30. package/dist/repl/picker.js +132 -0
  31. package/dist/repl/picker.js.map +1 -1
  32. package/dist/repl/process-backend.d.ts +31 -0
  33. package/dist/repl/process-backend.d.ts.map +1 -0
  34. package/dist/repl/process-backend.js +10 -0
  35. package/dist/repl/process-backend.js.map +1 -0
  36. package/dist/repl/process-executor.d.ts +67 -0
  37. package/dist/repl/process-executor.d.ts.map +1 -0
  38. package/dist/repl/process-executor.js +371 -0
  39. package/dist/repl/process-executor.js.map +1 -0
  40. package/dist/repl/process-worker.d.ts +10 -0
  41. package/dist/repl/process-worker.d.ts.map +1 -0
  42. package/dist/repl/process-worker.js +210 -0
  43. package/dist/repl/process-worker.js.map +1 -0
  44. package/dist/repl/processes.d.ts +282 -0
  45. package/dist/repl/processes.d.ts.map +1 -0
  46. package/dist/repl/processes.js +557 -0
  47. package/dist/repl/processes.js.map +1 -0
  48. package/dist/repl/render.d.ts +52 -2
  49. package/dist/repl/render.d.ts.map +1 -1
  50. package/dist/repl/render.js +52 -17
  51. package/dist/repl/render.js.map +1 -1
  52. package/dist/repl/session.d.ts +135 -3
  53. package/dist/repl/session.d.ts.map +1 -1
  54. package/dist/repl/session.js +413 -4
  55. package/dist/repl/session.js.map +1 -1
  56. package/dist/repl/status.d.ts +3 -1
  57. package/dist/repl/status.d.ts.map +1 -1
  58. package/dist/repl/status.js +4 -0
  59. package/dist/repl/status.js.map +1 -1
  60. package/dist/repl/tui/autocomplete.d.ts +19 -0
  61. package/dist/repl/tui/autocomplete.d.ts.map +1 -0
  62. package/dist/repl/tui/autocomplete.js +48 -0
  63. package/dist/repl/tui/autocomplete.js.map +1 -0
  64. package/dist/repl/tui/document.d.ts +51 -0
  65. package/dist/repl/tui/document.d.ts.map +1 -0
  66. package/dist/repl/tui/document.js +160 -0
  67. package/dist/repl/tui/document.js.map +1 -0
  68. package/dist/repl/tui/harness-view.d.ts +102 -0
  69. package/dist/repl/tui/harness-view.d.ts.map +1 -0
  70. package/dist/repl/tui/harness-view.js +323 -0
  71. package/dist/repl/tui/harness-view.js.map +1 -0
  72. package/dist/repl/tui/picker.d.ts +31 -0
  73. package/dist/repl/tui/picker.d.ts.map +1 -0
  74. package/dist/repl/tui/picker.js +43 -0
  75. package/dist/repl/tui/picker.js.map +1 -0
  76. package/dist/repl/tui/renderer.d.ts +98 -0
  77. package/dist/repl/tui/renderer.d.ts.map +1 -0
  78. package/dist/repl/tui/renderer.js +289 -0
  79. package/dist/repl/tui/renderer.js.map +1 -0
  80. package/dist/repl/tui/services-panel.d.ts +35 -0
  81. package/dist/repl/tui/services-panel.d.ts.map +1 -0
  82. package/dist/repl/tui/services-panel.js +108 -0
  83. package/dist/repl/tui/services-panel.js.map +1 -0
  84. package/dist/repl/tui/status-bar.d.ts +6 -2
  85. package/dist/repl/tui/status-bar.d.ts.map +1 -1
  86. package/dist/repl/tui/status-bar.js +82 -24
  87. package/dist/repl/tui/status-bar.js.map +1 -1
  88. package/dist/repl/tui/terminal.d.ts +28 -0
  89. package/dist/repl/tui/terminal.d.ts.map +1 -0
  90. package/dist/repl/tui/terminal.js +94 -0
  91. package/dist/repl/tui/terminal.js.map +1 -0
  92. package/dist/repl/tui/theme.d.ts +60 -0
  93. package/dist/repl/tui/theme.d.ts.map +1 -1
  94. package/dist/repl/tui/theme.js +142 -0
  95. package/dist/repl/tui/theme.js.map +1 -1
  96. package/dist/repl/tui/tool-pane.d.ts +68 -0
  97. package/dist/repl/tui/tool-pane.d.ts.map +1 -0
  98. package/dist/repl/tui/tool-pane.js +261 -0
  99. package/dist/repl/tui/tool-pane.js.map +1 -0
  100. package/dist/repl/tui/working-line.d.ts +23 -0
  101. package/dist/repl/tui/working-line.d.ts.map +1 -0
  102. package/dist/repl/tui/working-line.js +58 -0
  103. package/dist/repl/tui/working-line.js.map +1 -0
  104. package/dist/repl/worker-host.d.ts +80 -0
  105. package/dist/repl/worker-host.d.ts.map +1 -0
  106. package/dist/repl/worker-host.js +305 -0
  107. package/dist/repl/worker-host.js.map +1 -0
  108. package/dist/repl/worker-protocol.d.ts +123 -0
  109. package/dist/repl/worker-protocol.d.ts.map +1 -0
  110. package/dist/repl/worker-protocol.js +9 -0
  111. package/dist/repl/worker-protocol.js.map +1 -0
  112. package/dist/runner.d.ts +24 -0
  113. package/dist/runner.d.ts.map +1 -1
  114. package/dist/runner.js +47 -0
  115. package/dist/runner.js.map +1 -1
  116. package/dist/system/assets/docs/AGENT_PROMPT.md +193 -0
  117. package/dist/system/assets/docs/DML_AUTHORING.md +21 -0
  118. package/dist/system/assets/docs/DML_REFERENCE.md +145 -0
  119. package/dist/types.d.ts +7 -0
  120. package/dist/types.d.ts.map +1 -1
  121. package/package.json +2 -1
  122. package/src/prolog-src/deepclause_mi.pl +516 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"picker.d.ts","sourceRoot":"","sources":["../../../src/repl/tui/picker.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAc,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAIrF,MAAM,WAAW,mBAAmB;IAClC,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,qBAAa,YAAa,YAAW,SAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;gBAEtB,OAAO,EAAE,mBAAmB;IAWxC,wEAAwE;IACxE,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAO/B,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI/B,UAAU,IAAI,IAAI;CAGnB"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * A chooser overlay: a titled list the user picks from.
3
+ *
4
+ * Used for the model and the reasoning-display setting. It is a plain component so
5
+ * the host can place it with `tui.showOverlay`; `onSelect`/`onCancel` tell the host
6
+ * when to take it down. Keys are the list's own (up/down, enter, escape), which is
7
+ * what pi's pickers use, so nothing has to be re-taught.
8
+ */
9
+ import { SelectList } from '@earendil-works/pi-tui';
10
+ import { selectListTheme, tuiStyle } from './theme.js';
11
+ export class ChoicePicker {
12
+ options;
13
+ list;
14
+ constructor(options) {
15
+ this.options = options;
16
+ this.list = new SelectList(options.items, 12, selectListTheme());
17
+ if (options.current) {
18
+ const index = options.items.findIndex((item) => item.value === options.current);
19
+ if (index >= 0)
20
+ this.list.setSelectedIndex(index);
21
+ }
22
+ this.list.onSelect = (item) => options.onSelect(item);
23
+ this.list.onCancel = () => options.onCancel();
24
+ }
25
+ /** The visible lines, so a host can size the overlay to its content. */
26
+ get contentHeight() {
27
+ return 2 + (this.options.hint ? 1 : 0) + Math.min(this.options.items.length, 12);
28
+ }
29
+ render(width) {
30
+ const out = [tuiStyle.title(this.options.title)];
31
+ if (this.options.hint)
32
+ out.push(tuiStyle.dim(this.options.hint));
33
+ out.push(...this.list.render(width));
34
+ return out;
35
+ }
36
+ handleInput(data) {
37
+ this.list.handleInput(data);
38
+ }
39
+ invalidate() {
40
+ this.list.invalidate();
41
+ }
42
+ }
43
+ //# sourceMappingURL=picker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"picker.js","sourceRoot":"","sources":["../../../src/repl/tui/picker.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAmC,MAAM,wBAAwB,CAAC;AAErF,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAcvD,MAAM,OAAO,YAAY;IACN,OAAO,CAAsB;IAC7B,IAAI,CAAa;IAElC,YAAY,OAA4B;QACtC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC,CAAC;QACjE,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;YAChF,IAAI,KAAK,IAAI,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;IAChD,CAAC;IAED,wEAAwE;IACxE,IAAI,aAAa;QACf,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACnF,CAAC;IAED,MAAM,CAAC,KAAa;QAClB,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACjD,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI;YAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACjE,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACrC,OAAO,GAAG,CAAC;IACb,CAAC;IAED,WAAW,CAAC,IAAY;QACtB,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,UAAU;QACR,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;IACzB,CAAC;CACF"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Component renderer for the fullscreen TUI.
3
+ *
4
+ * It implements the same surface as `ReplRenderer` so the CLI's dispatch code is
5
+ * unchanged, but it emits *components* where a component earns its keep:
6
+ *
7
+ * - a tool call becomes a `DmlToolPane` (collapsible, with its own status),
8
+ * - streamed assistant text becomes a live `Markdown` block, so prose renders as
9
+ * it arrives instead of one line at a time,
10
+ * - the model-call indicator moves to the dock (`onWorking`), where a `Loader`
11
+ * cannot be flushed away by unrelated output the way a transcript line could.
12
+ *
13
+ * Everything else is delegated to a `ReplRenderer` whose output is funnelled into
14
+ * the document, so the existing formatting — output, logs, errors, usage,
15
+ * compaction, solutions, user/steer blocks — is reused rather than reinvented.
16
+ */
17
+ import type { DMLBinding, DMLEvent } from '../../types.js';
18
+ import { type ReplRendererOptions } from '../render.js';
19
+ import { TranscriptDocument } from './document.js';
20
+ export interface TuiRendererOptions extends ReplRendererOptions {
21
+ document: TranscriptDocument;
22
+ /**
23
+ * Show or hide the working indicator. The dock owns the `Loader`; the renderer
24
+ * only reports the state, so the indicator does not depend on which event
25
+ * happened to arrive last.
26
+ */
27
+ onWorking?: (label: string | null) => void;
28
+ }
29
+ export declare class TuiRenderer {
30
+ /** Kept for parity with `ReplRenderer`; the TUI is always rich. */
31
+ readonly mode: "rich";
32
+ private readonly document;
33
+ private readonly text;
34
+ private readonly onWorking?;
35
+ /** Whether activity events (and therefore frame labels) are shown. */
36
+ private readonly showEvents;
37
+ /** Tool panes in order, so the last one can be expanded on demand. */
38
+ private readonly panes;
39
+ private currentPane?;
40
+ private stream?;
41
+ /** The live (unterminated) line written by the delegated renderer. */
42
+ private pending;
43
+ /**
44
+ * What was emitted last: a text block or a component.
45
+ *
46
+ * The line renderer already separates its own blocks, but it cannot see the
47
+ * components (panes, streamed markdown) that never pass through it — so text
48
+ * followed by a component, or the reverse, ran together. Any blank requested here
49
+ * collapses with one the line renderer adds, so this cannot double them.
50
+ */
51
+ private lastBlock;
52
+ constructor(options: TuiRendererOptions);
53
+ /** Keep unlike output apart: one blank line between a text block and a component. */
54
+ private separate;
55
+ /**
56
+ * Close any open streamed-text block.
57
+ *
58
+ * Called at a turn boundary by the host, which knows when a prompt was submitted
59
+ * even if the run that was streaming never reported `finished` (an interrupted
60
+ * turn, for instance).
61
+ */
62
+ endTextBlock(): void;
63
+ /** Expand or collapse the most recent tool pane (ctrl+o). */
64
+ toggleLastPane(): boolean;
65
+ render(event: DMLEvent): void;
66
+ private renderToolCall;
67
+ private newStreamBlock;
68
+ /** Finish the live block, so later text starts a new one. */
69
+ private endStream;
70
+ /**
71
+ * Feed the delegated renderer's output into the document, mirroring the line
72
+ * sink the readline path uses: `\r` replaces the live line, `\n` commits it, and
73
+ * `ESC[K`/`ESC[J` are dropped because the pending line already replaces it.
74
+ */
75
+ private writeDocumentText;
76
+ /**
77
+ * While the TUI is live everything goes through the document. The CLI calls
78
+ * this again on the way out (to "restore stdout" for the exit footer), and that
79
+ * is exactly when output should stop being a component and go to the terminal
80
+ * again — otherwise the footer is written into a viewport that has been torn
81
+ * down and the user never sees it.
82
+ */
83
+ setSink(sink?: (text: string) => void, errorSink?: (text: string) => void): void;
84
+ setImageSink(sink?: (lines: string[]) => void): void;
85
+ setSuppressInputPrompt(suppress: boolean): void;
86
+ setReasoningMode(mode: 'off' | 'summary' | 'full'): void;
87
+ getReasoningMode(): 'off' | 'summary' | 'full';
88
+ getWidth(): number;
89
+ setWidth(width: number): void;
90
+ writeLine(text?: string): void;
91
+ writeErrorLine(text: string): void;
92
+ listing(text: string): string;
93
+ image(lines: string[]): void;
94
+ solution(bindings: DMLBinding[], terminator?: string, prefix?: string, maxValue?: number): void;
95
+ flush(): void;
96
+ dispose(): void;
97
+ }
98
+ //# sourceMappingURL=renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../src/repl/tui/renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAA6B,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AA2CnD,MAAM,WAAW,kBAAmB,SAAQ,mBAAmB;IAC7D,QAAQ,EAAE,kBAAkB,CAAC;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CAC5C;AAED,qBAAa,WAAW;IACtB,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAG,MAAM,CAAU;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAe;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAiC;IAC5D,sEAAsE;IACtE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,sEAAsE;IACtE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAC3C,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,MAAM,CAAC,CAAiB;IAChC,sEAAsE;IACtE,OAAO,CAAC,OAAO,CAAM;IACrB;;;;;;;OAOG;IACH,OAAO,CAAC,SAAS,CAAyC;gBAE9C,OAAO,EAAE,kBAAkB;IAmBvC,qFAAqF;IACrF,OAAO,CAAC,QAAQ;IAOhB;;;;;;OAMG;IACH,YAAY,IAAI,IAAI;IAIpB,6DAA6D;IAC7D,cAAc,IAAI,OAAO;IAQzB,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IA0C7B,OAAO,CAAC,cAAc;IA8BtB,OAAO,CAAC,cAAc;IAMtB,6DAA6D;IAC7D,OAAO,CAAC,SAAS;IAIjB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAgCzB;;;;;;OAMG;IACH,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAKhF,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,GAAG,IAAI;IASpD,sBAAsB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAI/C,gBAAgB,CAAC,IAAI,EAAE,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI;IAIxD,gBAAgB,IAAI,KAAK,GAAG,SAAS,GAAG,MAAM;IAI9C,QAAQ,IAAI,MAAM;IAIlB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7B,SAAS,CAAC,IAAI,SAAK,GAAG,IAAI;IAI1B,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIlC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAK7B,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAK5B,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,SAAK,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAK3F,KAAK,IAAI,IAAI;IAIb,OAAO,IAAI,IAAI;CAGhB"}
@@ -0,0 +1,289 @@
1
+ /**
2
+ * Component renderer for the fullscreen TUI.
3
+ *
4
+ * It implements the same surface as `ReplRenderer` so the CLI's dispatch code is
5
+ * unchanged, but it emits *components* where a component earns its keep:
6
+ *
7
+ * - a tool call becomes a `DmlToolPane` (collapsible, with its own status),
8
+ * - streamed assistant text becomes a live `Markdown` block, so prose renders as
9
+ * it arrives instead of one line at a time,
10
+ * - the model-call indicator moves to the dock (`onWorking`), where a `Loader`
11
+ * cannot be flushed away by unrelated output the way a transcript line could.
12
+ *
13
+ * Everything else is delegated to a `ReplRenderer` whose output is funnelled into
14
+ * the document, so the existing formatting — output, logs, errors, usage,
15
+ * compaction, solutions, user/steer blocks — is reused rather than reinvented.
16
+ */
17
+ import { Markdown } from '@earendil-works/pi-tui';
18
+ import { framePrefix, ReplRenderer } from '../render.js';
19
+ import { markdownTheme } from './theme.js';
20
+ import { DmlToolPane } from './tool-pane.js';
21
+ /** Events that produce no transcript output of their own. */
22
+ const QUIET_EVENTS = new Set(['model_call', 'finished', 'meta_result', 'usage']);
23
+ /** A markdown block whose text grows as the model streams. */
24
+ class StreamingBlock {
25
+ buffer = '';
26
+ markdown;
27
+ /** The frame's indentation, so nested answers stay inside the tree. */
28
+ prefix;
29
+ constructor(prefix) {
30
+ this.prefix = prefix;
31
+ this.markdown = new Markdown('', 0, 0, markdownTheme());
32
+ }
33
+ setPrefix(prefix) {
34
+ this.prefix = prefix;
35
+ }
36
+ append(chunk) {
37
+ this.buffer += chunk;
38
+ this.markdown.setText(this.buffer);
39
+ }
40
+ get isEmpty() {
41
+ return this.buffer.trim() === '';
42
+ }
43
+ render(width) {
44
+ const lines = this.markdown.render(Math.max(1, width - this.prefix.length));
45
+ if (!this.prefix)
46
+ return lines;
47
+ return lines.map((line) => (line === '' ? line : `${this.prefix}${line}`));
48
+ }
49
+ invalidate() {
50
+ this.markdown.invalidate();
51
+ }
52
+ }
53
+ export class TuiRenderer {
54
+ /** Kept for parity with `ReplRenderer`; the TUI is always rich. */
55
+ mode = 'rich';
56
+ document;
57
+ text;
58
+ onWorking;
59
+ /** Whether activity events (and therefore frame labels) are shown. */
60
+ showEvents;
61
+ /** Tool panes in order, so the last one can be expanded on demand. */
62
+ panes = [];
63
+ currentPane;
64
+ stream;
65
+ /** The live (unterminated) line written by the delegated renderer. */
66
+ pending = '';
67
+ /**
68
+ * What was emitted last: a text block or a component.
69
+ *
70
+ * The line renderer already separates its own blocks, but it cannot see the
71
+ * components (panes, streamed markdown) that never pass through it — so text
72
+ * followed by a component, or the reverse, ran together. Any blank requested here
73
+ * collapses with one the line renderer adds, so this cannot double them.
74
+ */
75
+ lastBlock = 'none';
76
+ constructor(options) {
77
+ this.document = options.document;
78
+ this.onWorking = options.onWorking;
79
+ this.showEvents = options.events !== false;
80
+ this.text = new ReplRenderer({
81
+ mode: 'rich',
82
+ color: options.color,
83
+ verbose: options.verbose,
84
+ stream: options.stream,
85
+ events: options.events,
86
+ reasoning: options.reasoning,
87
+ markdown: options.markdown,
88
+ });
89
+ this.text.setSink((text) => this.writeDocumentText(text), (text) => this.writeDocumentText(text));
90
+ }
91
+ /** Keep unlike output apart: one blank line between a text block and a component. */
92
+ separate(kind) {
93
+ if (this.lastBlock !== 'none' && this.lastBlock !== kind) {
94
+ this.document.appendText('');
95
+ }
96
+ this.lastBlock = kind;
97
+ }
98
+ /**
99
+ * Close any open streamed-text block.
100
+ *
101
+ * Called at a turn boundary by the host, which knows when a prompt was submitted
102
+ * even if the run that was streaming never reported `finished` (an interrupted
103
+ * turn, for instance).
104
+ */
105
+ endTextBlock() {
106
+ this.endStream();
107
+ }
108
+ /** Expand or collapse the most recent tool pane (ctrl+o). */
109
+ toggleLastPane() {
110
+ const pane = this.panes[this.panes.length - 1];
111
+ if (!pane)
112
+ return false;
113
+ pane.toggle();
114
+ this.document.onChange?.();
115
+ return true;
116
+ }
117
+ render(event) {
118
+ switch (event.type) {
119
+ case 'tool_call':
120
+ this.renderToolCall(event);
121
+ return;
122
+ case 'model_call':
123
+ this.onWorking?.(event.modelCallState === 'started' ? 'working…' : null);
124
+ return;
125
+ case 'stream':
126
+ if (event.content) {
127
+ if (!this.stream)
128
+ this.separate('component');
129
+ this.stream ??= this.newStreamBlock(framePrefix(event, this.showEvents));
130
+ this.stream.append(event.content);
131
+ this.document.onChange?.();
132
+ }
133
+ return;
134
+ case 'answer':
135
+ case 'error':
136
+ this.endStream();
137
+ // An aborted run may never report the model call as completed, so clear
138
+ // the dock spinner here or it animates forever after an interrupt.
139
+ this.onWorking?.(null);
140
+ this.separate('text');
141
+ this.text.render(event);
142
+ return;
143
+ case 'finished':
144
+ // A run ended. Without closing the block, the next turn's streamed text is
145
+ // appended to this one and renders *above* the prompt the user just typed,
146
+ // because the block sits earlier in the transcript.
147
+ if ((event.depth ?? 0) === 0) {
148
+ this.endStream();
149
+ this.onWorking?.(null);
150
+ }
151
+ return;
152
+ default:
153
+ // Events that render nothing must not add a separator, or switching models
154
+ // or finishing a turn would open a gap.
155
+ if (!QUIET_EVENTS.has(event.type))
156
+ this.separate('text');
157
+ this.text.render(event);
158
+ }
159
+ }
160
+ renderToolCall(event) {
161
+ const name = event.toolName ?? 'tool';
162
+ const state = event.toolState ?? 'running';
163
+ const prefix = framePrefix(event, this.showEvents);
164
+ if (state === 'starting' || !this.currentPane) {
165
+ this.endStream();
166
+ this.separate('component');
167
+ this.currentPane = new DmlToolPane({ toolName: name, args: event.toolArgs ?? {}, prefix });
168
+ this.panes.push(this.currentPane);
169
+ this.document.appendComponent(this.currentPane);
170
+ this.onWorking?.(`${name}…`);
171
+ }
172
+ else {
173
+ // A `completed` event can carry the frame metadata the start event lacked.
174
+ this.currentPane.setPrefix(prefix);
175
+ if (event.toolArgs)
176
+ this.currentPane.setArgs(event.toolArgs);
177
+ }
178
+ if (state === 'completed' || state === 'failed') {
179
+ this.currentPane.setResult(event.toolResult ?? event.toolSummary ?? '', state === 'completed', event.toolDurationMs);
180
+ this.onWorking?.(null);
181
+ this.currentPane = undefined;
182
+ this.document.onChange?.();
183
+ }
184
+ }
185
+ newStreamBlock(prefix) {
186
+ const block = new StreamingBlock(prefix);
187
+ this.document.appendComponent(block);
188
+ return block;
189
+ }
190
+ /** Finish the live block, so later text starts a new one. */
191
+ endStream() {
192
+ this.stream = undefined;
193
+ }
194
+ /**
195
+ * Feed the delegated renderer's output into the document, mirroring the line
196
+ * sink the readline path uses: `\r` replaces the live line, `\n` commits it, and
197
+ * `ESC[K`/`ESC[J` are dropped because the pending line already replaces it.
198
+ */
199
+ writeDocumentText(chunk) {
200
+ let index = 0;
201
+ while (index < chunk.length) {
202
+ const char = chunk[index];
203
+ if (char === '\r') {
204
+ this.pending = '';
205
+ this.document.setPending('');
206
+ index += 1;
207
+ continue;
208
+ }
209
+ if (char === '\n') {
210
+ this.document.appendText(this.pending);
211
+ this.pending = '';
212
+ this.document.setPending('');
213
+ index += 1;
214
+ continue;
215
+ }
216
+ if (char === '\u001b' && chunk[index + 1] === '[') {
217
+ const match = /^\u001b\[[0-9;]*[JK]/.exec(chunk.slice(index));
218
+ if (match) {
219
+ index += match[0].length;
220
+ continue;
221
+ }
222
+ }
223
+ this.pending += char;
224
+ this.document.setPending(this.pending);
225
+ index += 1;
226
+ }
227
+ }
228
+ // ---- ReplRenderer-compatible surface ----
229
+ /**
230
+ * While the TUI is live everything goes through the document. The CLI calls
231
+ * this again on the way out (to "restore stdout" for the exit footer), and that
232
+ * is exactly when output should stop being a component and go to the terminal
233
+ * again — otherwise the footer is written into a viewport that has been torn
234
+ * down and the user never sees it.
235
+ */
236
+ setSink(sink, errorSink) {
237
+ if (!sink)
238
+ return;
239
+ this.text.setSink(sink, errorSink);
240
+ }
241
+ setImageSink(sink) {
242
+ this.text.setImageSink(sink
243
+ ? (lines) => {
244
+ this.endStream();
245
+ sink(lines);
246
+ }
247
+ : undefined);
248
+ }
249
+ setSuppressInputPrompt(suppress) {
250
+ this.text.setSuppressInputPrompt(suppress);
251
+ }
252
+ setReasoningMode(mode) {
253
+ this.text.setReasoningMode(mode);
254
+ }
255
+ getReasoningMode() {
256
+ return this.text.getReasoningMode();
257
+ }
258
+ getWidth() {
259
+ return this.text.getWidth();
260
+ }
261
+ setWidth(width) {
262
+ this.text.setWidth(width);
263
+ }
264
+ writeLine(text = '') {
265
+ this.text.writeLine(text);
266
+ }
267
+ writeErrorLine(text) {
268
+ this.text.writeErrorLine(text);
269
+ }
270
+ listing(text) {
271
+ this.endStream();
272
+ return this.text.listing(text);
273
+ }
274
+ image(lines) {
275
+ this.endStream();
276
+ this.text.image(lines);
277
+ }
278
+ solution(bindings, terminator, prefix = '', maxValue) {
279
+ this.endStream();
280
+ this.text.solution(bindings, terminator, prefix, maxValue);
281
+ }
282
+ flush() {
283
+ this.text.flush();
284
+ }
285
+ dispose() {
286
+ this.text.dispose();
287
+ }
288
+ }
289
+ //# sourceMappingURL=renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../../../src/repl/tui/renderer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Live services panel: a dock row for the session's subagents.
3
+ *
4
+ * Renders nothing when hidden. When visible it always renders, so
5
+ * `/ps --watch` with no subagents says so instead of leaving a blank row.
6
+ *
7
+ * Two modes, toggled with `/ps --watch` and `/ps --watch --logs`:
8
+ * - `summary` — one row per process with state, activity, queue and usage;
9
+ * - `logs` — the process list over a full-width rule, then a chronological
10
+ * follow of each subagent's streamed output, reasoning, tool
11
+ * calls and answers.
12
+ */
13
+ import { type Component } from '@earendil-works/pi-tui';
14
+ import type { ProcessInfo, ProcessLogEntry } from '../processes.js';
15
+ export type ServicesPanelMode = 'summary' | 'logs';
16
+ export interface ServicesPanelOptions {
17
+ getProcesses: () => ProcessInfo[];
18
+ getLog: () => ProcessLogEntry[];
19
+ isVisible: () => boolean;
20
+ mode: () => ServicesPanelMode;
21
+ /** Current harness version, to mark a process running older code. */
22
+ currentHarnessVersion?: () => string;
23
+ /** Rows of log shown in logs mode (default 16). */
24
+ maxLogLines?: number;
25
+ }
26
+ export declare class ServicesPanel implements Component {
27
+ private readonly options;
28
+ constructor(options: ServicesPanelOptions);
29
+ render(width: number): string[];
30
+ private renderSummary;
31
+ private renderLogs;
32
+ private formatLogLine;
33
+ invalidate(): void;
34
+ }
35
+ //# sourceMappingURL=services-panel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"services-panel.d.ts","sourceRoot":"","sources":["../../../src/repl/tui/services-panel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAiC,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEvF,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAgB,MAAM,iBAAiB,CAAC;AAGlF,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,MAAM,CAAC;AAEnD,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,WAAW,EAAE,CAAC;IAClC,MAAM,EAAE,MAAM,eAAe,EAAE,CAAC;IAChC,SAAS,EAAE,MAAM,OAAO,CAAC;IACzB,IAAI,EAAE,MAAM,iBAAiB,CAAC;IAC9B,qEAAqE;IACrE,qBAAqB,CAAC,EAAE,MAAM,MAAM,CAAC;IACrC,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAwBD,qBAAa,aAAc,YAAW,SAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,oBAAoB;IAE1D,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAW/B,OAAO,CAAC,aAAa;IAoBrB,OAAO,CAAC,UAAU;IAqBlB,OAAO,CAAC,aAAa;IAiBrB,UAAU,IAAI,IAAI;CAGnB"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Live services panel: a dock row for the session's subagents.
3
+ *
4
+ * Renders nothing when hidden. When visible it always renders, so
5
+ * `/ps --watch` with no subagents says so instead of leaving a blank row.
6
+ *
7
+ * Two modes, toggled with `/ps --watch` and `/ps --watch --logs`:
8
+ * - `summary` — one row per process with state, activity, queue and usage;
9
+ * - `logs` — the process list over a full-width rule, then a chronological
10
+ * follow of each subagent's streamed output, reasoning, tool
11
+ * calls and answers.
12
+ */
13
+ import { truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';
14
+ import { dim, tuiStyle } from './theme.js';
15
+ const ACTIVE = ['running', 'runnable', 'waiting', 'input'];
16
+ const NAME_WIDTH = 12;
17
+ function stateLabel(state) {
18
+ return state === 'input' ? 'input' : state;
19
+ }
20
+ function processSummaryLine(processes) {
21
+ if (processes.length === 0)
22
+ return 'nothing is running';
23
+ const active = processes.filter((process) => ACTIVE.includes(process.state)).length;
24
+ const attention = processes.some((process) => process.state === 'input');
25
+ const names = processes
26
+ .slice(0, 6)
27
+ .map((process) => `${process.name} ${stateLabel(process.state)}`)
28
+ .join(' · ');
29
+ const more = processes.length > 6 ? ` · +${processes.length - 6}` : '';
30
+ return `${processes.length} process${processes.length === 1 ? '' : 'es'}`
31
+ + `${active > 0 ? ` · ${active} active` : ''}`
32
+ + `${attention ? ' · needs input' : ''}`
33
+ + ` · ${names}${more}`;
34
+ }
35
+ export class ServicesPanel {
36
+ options;
37
+ constructor(options) {
38
+ this.options = options;
39
+ }
40
+ render(width) {
41
+ if (!this.options.isVisible())
42
+ return [];
43
+ const columns = Math.max(1, width);
44
+ const rule = dim('─'.repeat(columns));
45
+ const processes = this.options.getProcesses();
46
+ const header = dim(`⚙ services — ${processSummaryLine(processes)}`);
47
+ if (this.options.mode() === 'logs')
48
+ return this.renderLogs(columns, processes, rule, header);
49
+ return [rule, header, ...this.renderSummary(columns, processes)];
50
+ }
51
+ renderSummary(columns, processes) {
52
+ if (processes.length === 0) {
53
+ return [dim(' /spawn <goal> to start a subagent')];
54
+ }
55
+ return processes.map((process) => {
56
+ const usage = process.usage.totalTokens > 0 ? ` · ${process.usage.totalTokens} tok` : '';
57
+ const activity = process.currentActivity ? ` · ${process.currentActivity}` : '';
58
+ const error = process.error ? ` (${process.error})` : '';
59
+ const mail = process.mailboxDepth > 0 ? ` · ${process.mailboxDepth} queued` : '';
60
+ const current = this.options.currentHarnessVersion?.();
61
+ const stale = current && process.harnessVersion && process.harnessVersion !== current;
62
+ const code = process.harnessVersion
63
+ ? ` · code ${process.harnessVersion.slice(0, 7)}${stale ? '*' : ''}`
64
+ : '';
65
+ const text = ` ${process.name} ${stateLabel(process.state)}${error}${activity}${mail}${code}${usage}`;
66
+ const painted = ACTIVE.includes(process.state) ? text : dim(text);
67
+ return truncateToWidth(painted, columns, '…');
68
+ });
69
+ }
70
+ renderLogs(columns, processes, rule, header) {
71
+ const log = this.options.getLog();
72
+ if (processes.length === 0 && log.length === 0) {
73
+ return [rule, header, dim(' /spawn <goal> to start a subagent')];
74
+ }
75
+ const max = this.options.maxLogLines ?? 16;
76
+ const slice = log.slice(-max);
77
+ // Entries first (top-down), then pad to a stable height so the panel does
78
+ // not jump as output arrives.
79
+ const rows = [];
80
+ for (const entry of slice) {
81
+ rows.push(truncateToWidth(this.formatLogLine(entry), columns, '…'));
82
+ }
83
+ for (let i = slice.length; i < max; i += 1)
84
+ rows.push('');
85
+ // Rule above (separates from the transcript), process header, rule, log.
86
+ return [rule, header, rule, ...rows];
87
+ }
88
+ formatLogLine(entry) {
89
+ const raw = entry.name.length > NAME_WIDTH ? `${entry.name.slice(0, NAME_WIDTH - 1)}…` : entry.name;
90
+ const padding = ' '.repeat(Math.max(0, NAME_WIDTH - visibleWidth(raw)));
91
+ const label = dim(`${raw}${padding}`);
92
+ // A component line must not contain a newline: a multi-line answer/result
93
+ // would otherwise break the layout.
94
+ const body = entry.text.replace(/\s*\n\s*/g, ' ↵ ');
95
+ const prefix = entry.kind === 'reasoning' ? '~ ' : '';
96
+ const text = `${prefix}${body}`;
97
+ const styled = entry.kind === 'output' || entry.kind === 'stream'
98
+ ? text
99
+ : entry.kind === 'reasoning'
100
+ ? dim(text)
101
+ : tuiStyle.accent(text);
102
+ return ` ${label} ${styled}`;
103
+ }
104
+ invalidate() {
105
+ // Stateless: reads the host on each render.
106
+ }
107
+ }
108
+ //# sourceMappingURL=services-panel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"services-panel.js","sourceRoot":"","sources":["../../../src/repl/tui/services-panel.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,10 @@
1
1
  /**
2
2
  * Fixed status bar for the REPL TUI (pi-style footer).
3
3
  *
4
- * Two lines: workspace/session/backend, then token totals, context usage for
5
- * the active frame slot, and the current model (with reasoning level).
4
+ * One row: where the harness lives and what it is doing on the left, the model on
5
+ * the right, and the token/context counters in between. Anything that does not fit
6
+ * is dropped whole, in priority order (see `render`), so a narrow terminal loses
7
+ * detail instead of showing truncated fragments.
6
8
  */
7
9
  import { type Component } from '@earendil-works/pi-tui';
8
10
  import { type ReplStatusSnapshot } from '../status.js';
@@ -16,6 +18,8 @@ export interface StatusBarOptions {
16
18
  isFrozen?: () => boolean;
17
19
  /** True while a turn is running (so the user knows they can steer). */
18
20
  isRunning?: () => boolean;
21
+ /** Compact subagent status, e.g. `⚙ desk 2/3`; omitted when none run. */
22
+ processLabel?: () => string | undefined;
19
23
  }
20
24
  export declare class StatusBarComponent implements Component {
21
25
  private readonly options;
@@ -1 +1 @@
1
- {"version":3,"file":"status-bar.d.ts","sourceRoot":"","sources":["../../../src/repl/tui/status-bar.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAiC,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEvF,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,cAAc,CAAC;AAGtB,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,kBAAkB,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC;IACzB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;CAC3B;AAmBD,qBAAa,kBAAmB,YAAW,SAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,gBAAgB;IAEtD,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAmB/B,UAAU,IAAI,IAAI;CAGnB"}
1
+ {"version":3,"file":"status-bar.d.ts","sourceRoot":"","sources":["../../../src/repl/tui/status-bar.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAiC,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEvF,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,cAAc,CAAC;AAGtB,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,kBAAkB,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC;IACzB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;IAC1B,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;CACzC;AA2DD,qBAAa,kBAAmB,YAAW,SAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,gBAAgB;IAEtD,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAiC/B,UAAU,IAAI,IAAI;CAGnB"}