@inhuman.tools/harness-tui 0.0.0-bootstrap.0 → 0.2.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 (167) hide show
  1. package/LICENSE.md +7 -0
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +2 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/interpreter/ComputedExecBox.d.ts +12 -0
  7. package/dist/interpreter/ComputedExecBox.d.ts.map +1 -0
  8. package/dist/interpreter/ComputedExecBox.js +88 -0
  9. package/dist/interpreter/ComputedExecBox.js.map +1 -0
  10. package/dist/interpreter/imageCapability.d.ts +9 -0
  11. package/dist/interpreter/imageCapability.d.ts.map +1 -0
  12. package/dist/interpreter/imageCapability.js +49 -0
  13. package/dist/interpreter/imageCapability.js.map +1 -0
  14. package/dist/interpreter/rpcCapability.d.ts +11 -0
  15. package/dist/interpreter/rpcCapability.d.ts.map +1 -0
  16. package/dist/interpreter/rpcCapability.js +91 -0
  17. package/dist/interpreter/rpcCapability.js.map +1 -0
  18. package/dist/interpreter/uiCapability.d.ts +34 -0
  19. package/dist/interpreter/uiCapability.d.ts.map +1 -0
  20. package/dist/interpreter/uiCapability.js +207 -0
  21. package/dist/interpreter/uiCapability.js.map +1 -0
  22. package/dist/schemas/index.d.ts +2 -0
  23. package/dist/schemas/index.d.ts.map +1 -0
  24. package/dist/schemas/index.js +2 -0
  25. package/dist/schemas/index.js.map +1 -0
  26. package/dist/schemas/worker-boot.d.ts +14 -0
  27. package/dist/schemas/worker-boot.d.ts.map +1 -0
  28. package/dist/schemas/worker-boot.js +15 -0
  29. package/dist/schemas/worker-boot.js.map +1 -0
  30. package/dist/tui/ack-prompt.d.ts +53 -0
  31. package/dist/tui/ack-prompt.d.ts.map +1 -0
  32. package/dist/tui/ack-prompt.js +61 -0
  33. package/dist/tui/ack-prompt.js.map +1 -0
  34. package/dist/tui/agents-drawer.d.ts +47 -0
  35. package/dist/tui/agents-drawer.d.ts.map +1 -0
  36. package/dist/tui/agents-drawer.js +314 -0
  37. package/dist/tui/agents-drawer.js.map +1 -0
  38. package/dist/tui/ask-shortcuts.d.ts +59 -0
  39. package/dist/tui/ask-shortcuts.d.ts.map +1 -0
  40. package/dist/tui/ask-shortcuts.js +96 -0
  41. package/dist/tui/ask-shortcuts.js.map +1 -0
  42. package/dist/tui/channel.d.ts +59 -0
  43. package/dist/tui/channel.d.ts.map +1 -0
  44. package/dist/tui/channel.js +27 -0
  45. package/dist/tui/channel.js.map +1 -0
  46. package/dist/tui/host-verbs.d.ts +7 -0
  47. package/dist/tui/host-verbs.d.ts.map +1 -0
  48. package/dist/tui/host-verbs.js +19 -0
  49. package/dist/tui/host-verbs.js.map +1 -0
  50. package/dist/tui/host.d.ts +25 -0
  51. package/dist/tui/host.d.ts.map +1 -0
  52. package/dist/tui/host.js +380 -0
  53. package/dist/tui/host.js.map +1 -0
  54. package/dist/tui/omnibox-seat.d.ts +132 -0
  55. package/dist/tui/omnibox-seat.d.ts.map +1 -0
  56. package/dist/tui/omnibox-seat.js +182 -0
  57. package/dist/tui/omnibox-seat.js.map +1 -0
  58. package/dist/tui/paint-controller.d.ts +170 -0
  59. package/dist/tui/paint-controller.d.ts.map +1 -0
  60. package/dist/tui/paint-controller.js +965 -0
  61. package/dist/tui/paint-controller.js.map +1 -0
  62. package/dist/tui/paint-dom.d.ts +336 -0
  63. package/dist/tui/paint-dom.d.ts.map +1 -0
  64. package/dist/tui/paint-dom.js +709 -0
  65. package/dist/tui/paint-dom.js.map +1 -0
  66. package/dist/tui/paint-source.d.ts +57 -0
  67. package/dist/tui/paint-source.d.ts.map +1 -0
  68. package/dist/tui/paint-source.js +570 -0
  69. package/dist/tui/paint-source.js.map +1 -0
  70. package/dist/tui/paint-transport.d.ts +42 -0
  71. package/dist/tui/paint-transport.d.ts.map +1 -0
  72. package/dist/tui/paint-transport.js +207 -0
  73. package/dist/tui/paint-transport.js.map +1 -0
  74. package/dist/tui/paint-types.d.ts +15 -0
  75. package/dist/tui/paint-types.d.ts.map +1 -0
  76. package/dist/tui/paint-types.js +6 -0
  77. package/dist/tui/paint-types.js.map +1 -0
  78. package/dist/tui/paint-widgets.d.ts +94 -0
  79. package/dist/tui/paint-widgets.d.ts.map +1 -0
  80. package/dist/tui/paint-widgets.js +877 -0
  81. package/dist/tui/paint-widgets.js.map +1 -0
  82. package/dist/tui/parse-args.d.ts +3 -0
  83. package/dist/tui/parse-args.d.ts.map +1 -0
  84. package/dist/tui/parse-args.js +13 -0
  85. package/dist/tui/parse-args.js.map +1 -0
  86. package/dist/tui/permissions-view.d.ts +93 -0
  87. package/dist/tui/permissions-view.d.ts.map +1 -0
  88. package/dist/tui/permissions-view.js +174 -0
  89. package/dist/tui/permissions-view.js.map +1 -0
  90. package/dist/tui/present-visual/approve.d.ts +10 -0
  91. package/dist/tui/present-visual/approve.d.ts.map +1 -0
  92. package/dist/tui/present-visual/approve.js +156 -0
  93. package/dist/tui/present-visual/approve.js.map +1 -0
  94. package/dist/tui/present-visual/dump.d.ts +47 -0
  95. package/dist/tui/present-visual/dump.d.ts.map +1 -0
  96. package/dist/tui/present-visual/dump.js +144 -0
  97. package/dist/tui/present-visual/dump.js.map +1 -0
  98. package/dist/tui/present-visual/journey-teardown.d.ts +3 -0
  99. package/dist/tui/present-visual/journey-teardown.d.ts.map +1 -0
  100. package/dist/tui/present-visual/journey-teardown.js +188 -0
  101. package/dist/tui/present-visual/journey-teardown.js.map +1 -0
  102. package/dist/tui/present-visual/journey.d.ts +15 -0
  103. package/dist/tui/present-visual/journey.d.ts.map +1 -0
  104. package/dist/tui/present-visual/journey.js +88 -0
  105. package/dist/tui/present-visual/journey.js.map +1 -0
  106. package/dist/tui/present-visual/raster.d.ts +3 -0
  107. package/dist/tui/present-visual/raster.d.ts.map +1 -0
  108. package/dist/tui/present-visual/raster.js +75 -0
  109. package/dist/tui/present-visual/raster.js.map +1 -0
  110. package/dist/tui/queue-shortcuts.d.ts +13 -0
  111. package/dist/tui/queue-shortcuts.d.ts.map +1 -0
  112. package/dist/tui/queue-shortcuts.js +23 -0
  113. package/dist/tui/queue-shortcuts.js.map +1 -0
  114. package/dist/tui/read-widen.d.ts +14 -0
  115. package/dist/tui/read-widen.d.ts.map +1 -0
  116. package/dist/tui/read-widen.js +45 -0
  117. package/dist/tui/read-widen.js.map +1 -0
  118. package/dist/tui/rewind-chrome.d.ts +29 -0
  119. package/dist/tui/rewind-chrome.d.ts.map +1 -0
  120. package/dist/tui/rewind-chrome.js +77 -0
  121. package/dist/tui/rewind-chrome.js.map +1 -0
  122. package/dist/tui/rust-present.d.ts +37 -0
  123. package/dist/tui/rust-present.d.ts.map +1 -0
  124. package/dist/tui/rust-present.js +205 -0
  125. package/dist/tui/rust-present.js.map +1 -0
  126. package/dist/tui/spinner-phase.d.ts +24 -0
  127. package/dist/tui/spinner-phase.d.ts.map +1 -0
  128. package/dist/tui/spinner-phase.js +25 -0
  129. package/dist/tui/spinner-phase.js.map +1 -0
  130. package/dist/tui/statusline-path.d.ts +10 -0
  131. package/dist/tui/statusline-path.d.ts.map +1 -0
  132. package/dist/tui/statusline-path.js +42 -0
  133. package/dist/tui/statusline-path.js.map +1 -0
  134. package/dist/tui/sugarcoat-paint.d.ts +14 -0
  135. package/dist/tui/sugarcoat-paint.d.ts.map +1 -0
  136. package/dist/tui/sugarcoat-paint.js +146 -0
  137. package/dist/tui/sugarcoat-paint.js.map +1 -0
  138. package/dist/tui/tape-spans.d.ts +64 -0
  139. package/dist/tui/tape-spans.d.ts.map +1 -0
  140. package/dist/tui/tape-spans.js +93 -0
  141. package/dist/tui/tape-spans.js.map +1 -0
  142. package/dist/tui/tea.d.ts +75 -0
  143. package/dist/tui/tea.d.ts.map +1 -0
  144. package/dist/tui/tea.js +2952 -0
  145. package/dist/tui/tea.js.map +1 -0
  146. package/dist/tui/vt-paint.d.ts +12 -0
  147. package/dist/tui/vt-paint.d.ts.map +1 -0
  148. package/dist/tui/vt-paint.js +123 -0
  149. package/dist/tui/vt-paint.js.map +1 -0
  150. package/dist/tui/wait-phrase.d.ts +31 -0
  151. package/dist/tui/wait-phrase.d.ts.map +1 -0
  152. package/dist/tui/wait-phrase.js +26 -0
  153. package/dist/tui/wait-phrase.js.map +1 -0
  154. package/dist/tui/widget-host.d.ts +34 -0
  155. package/dist/tui/widget-host.d.ts.map +1 -0
  156. package/dist/tui/widget-host.js +80 -0
  157. package/dist/tui/widget-host.js.map +1 -0
  158. package/dist/tui/work-cells.d.ts +47 -0
  159. package/dist/tui/work-cells.d.ts.map +1 -0
  160. package/dist/tui/work-cells.js +606 -0
  161. package/dist/tui/work-cells.js.map +1 -0
  162. package/dist/tui/worker-entry.d.ts +2 -0
  163. package/dist/tui/worker-entry.d.ts.map +1 -0
  164. package/dist/tui/worker-entry.js +98 -0
  165. package/dist/tui/worker-entry.js.map +1 -0
  166. package/package.json +84 -4
  167. package/README.md +0 -1
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Ask-cover shortcut chrome. Persist chords store `Ctrl` (`config.json`
3
+ * `superKey`; `cmd` stores `Cmd`). Paint writes ⏎ / ⌃ / ⌘. Remember chords
4
+ * only where the daemon offers a family to remember (an ask, never a soft-deny
5
+ * or a block); "Treat <folder> as part of this session" on a suggested
6
+ * extra-root read parent; deny-persist chords on a hidden MCP tool name.
7
+ * Comment cover owns modifier Esc and does not remember or widen. Each binding
8
+ * bears the named event Tea fires on a match.
9
+ */
10
+ import { DEFAULT_SUPER_KEY, parseSuperKey } from "@inhuman.tools/harness-model";
11
+ export const HOTKEY_EVENT = {
12
+ allow: "allow",
13
+ deny: "deny",
14
+ allowSession: "allow-session",
15
+ allowAlways: "allow-always",
16
+ allowWiden: "allow-widen",
17
+ denySession: "deny-session",
18
+ denyAlways: "deny-always",
19
+ ackRemember: "ack-remember",
20
+ ackNext: "ack-next",
21
+ ackPrev: "ack-prev",
22
+ retry: "retry",
23
+ queueMessage: "queue-message",
24
+ steerFirst: "steer-first",
25
+ continue: "continue",
26
+ clear: "clear",
27
+ cancelTurn: "cancel-turn",
28
+ };
29
+ export function superChord(rest, superKey = DEFAULT_SUPER_KEY) {
30
+ return `${superKey === "cmd" ? "Cmd" : "Ctrl"}+${rest}`;
31
+ }
32
+ export function isPersistMod(event, superKey = DEFAULT_SUPER_KEY) {
33
+ return superKey === "cmd" ? event.meta === true : event.ctrl === true;
34
+ }
35
+ function hk(key, action, event) {
36
+ return { key, action, event };
37
+ }
38
+ export function askCoverShortcuts(input) {
39
+ const superKey = parseSuperKey(input.superKey);
40
+ const ackOnly = input.ack?.variant === "ack";
41
+ const yes = ackOnly ? "Acknowledge" : "Allow";
42
+ const no = ackOnly ? "Refuse" : "Deny";
43
+ if (input.comment) {
44
+ return [
45
+ hk(superChord("Enter", superKey), yes, HOTKEY_EVENT.allow),
46
+ hk(superChord("Esc", superKey), no, HOTKEY_EVENT.deny),
47
+ ];
48
+ }
49
+ const grantRemember = input.remember !== undefined && input.remember !== "";
50
+ const ackChords = input.ack?.choice !== undefined && input.ack.choice !== "" && !(grantRemember && !ackOnly)
51
+ ? [
52
+ hk(superChord("Enter", superKey), `Remember ${input.ack.choice}`, HOTKEY_EVENT.ackRemember),
53
+ ...(input.ack.cycle === true
54
+ ? [
55
+ hk(superChord("ArrowLeft", superKey), "Previous option", HOTKEY_EVENT.ackPrev),
56
+ hk(superChord("ArrowRight", superKey), "Next option", HOTKEY_EVENT.ackNext),
57
+ ]
58
+ : []),
59
+ ]
60
+ : [];
61
+ if (input.ack !== undefined && !grantRemember) {
62
+ return [
63
+ hk("Enter", ackOnly ? "Acknowledge" : "Allow once", HOTKEY_EVENT.allow),
64
+ ...ackChords,
65
+ hk("Esc", no, HOTKEY_EVENT.deny),
66
+ ];
67
+ }
68
+ const denyPersist = input.persistDeny
69
+ ? [
70
+ hk(superChord("Esc", superKey), "Deny this session", HOTKEY_EVENT.denySession),
71
+ hk(superChord("Shift+Esc", superKey), "Deny forever", HOTKEY_EVENT.denyAlways),
72
+ ]
73
+ : [];
74
+ if (grantRemember) {
75
+ const both = input.ack === undefined ? "" : " and the acknowledgement";
76
+ return [
77
+ hk("Enter", "Allow", HOTKEY_EVENT.allow),
78
+ hk(superChord("Enter", superKey), `Remember ${input.remember}${both} this session`, HOTKEY_EVENT.allowSession),
79
+ hk(superChord("Shift+Enter", superKey), `Remember ${input.remember}${both} in this project (7 days)`, HOTKEY_EVENT.allowAlways),
80
+ hk("Esc", "Deny", HOTKEY_EVENT.deny),
81
+ ...denyPersist,
82
+ ];
83
+ }
84
+ if (input.widen !== undefined && input.widen !== "") {
85
+ return [
86
+ hk("Enter", "Allow once", HOTKEY_EVENT.allow),
87
+ hk(superChord("Enter", superKey), `Treat ${input.widen} as part of this session`, HOTKEY_EVENT.allowWiden),
88
+ hk("Esc", "Deny", HOTKEY_EVENT.deny),
89
+ ];
90
+ }
91
+ if (input.persistDeny) {
92
+ return [hk("Enter", "Allow", HOTKEY_EVENT.allow), hk("Esc", "Deny", HOTKEY_EVENT.deny), ...denyPersist];
93
+ }
94
+ return [hk("Enter", "Allow", HOTKEY_EVENT.allow), hk("Esc", "Deny", HOTKEY_EVENT.deny)];
95
+ }
96
+ //# sourceMappingURL=ask-shortcuts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask-shortcuts.js","sourceRoot":"","sources":["../../src/tui/ask-shortcuts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Worker-thread seam. Paint lane is paint_*; host is attach lifecycle.
3
+ * HELD_KEYS: do not replay input_events into the new session — those
4
+ * keys belonged to the dying seat.
5
+ */
6
+ import type { BoxBusUpMessage } from "@inhuman.tools/quickdraw/runtime";
7
+ import type { PaintDownMessage } from "./paint-transport.js";
8
+ import type { WorkerBoot } from "../schemas/worker-boot.js";
9
+ export type WorkerToHost = {
10
+ readonly lane: "paint";
11
+ readonly batch: readonly PaintDownMessage[];
12
+ } | {
13
+ readonly lane: "host";
14
+ readonly kind: "attached" | "failed";
15
+ readonly reason?: string;
16
+ } | {
17
+ readonly lane: "host";
18
+ readonly kind: "title";
19
+ readonly text: string;
20
+ } | {
21
+ readonly lane: "host";
22
+ readonly kind: "phase";
23
+ readonly text: string;
24
+ } | {
25
+ readonly lane: "host";
26
+ readonly kind: "quit";
27
+ } | {
28
+ readonly lane: "host";
29
+ readonly kind: "resident";
30
+ readonly resident: boolean;
31
+ } | {
32
+ readonly lane: "host";
33
+ readonly kind: "replace";
34
+ readonly path: string;
35
+ readonly draft?: string;
36
+ readonly sessionId?: string;
37
+ };
38
+ export type HostToWorker = {
39
+ readonly lane: "paint";
40
+ readonly message: BoxBusUpMessage;
41
+ } | {
42
+ readonly lane: "host";
43
+ readonly kind: "shutdown";
44
+ };
45
+ export declare function tuiReplaceBoot(kernel: string, message: {
46
+ readonly path: string;
47
+ readonly draft?: string;
48
+ readonly sessionId?: string;
49
+ }, cwd: string, geometry?: {
50
+ readonly cols: number;
51
+ readonly rows: number;
52
+ }): WorkerBoot;
53
+ export declare function tuiBootGeometry(boot: Pick<WorkerBoot, "cols" | "rows">, pending: readonly HostToWorker[]): {
54
+ cols: number;
55
+ rows: number;
56
+ };
57
+ /** see preamble HELD_KEYS, CHANGE ONLY. */
58
+ export declare function tuiWorkerReplay(message: HostToWorker): boolean;
59
+ //# sourceMappingURL=channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/tui/channel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAExE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,gBAAgB,EAAE,CAAA;CAAE,GACvE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACzF;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACxE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACxE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GAChF;IACE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEN,MAAM,MAAM,YAAY,GACtB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAEvH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,EACxF,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC1D,UAAU,CAUZ;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,EACvC,OAAO,EAAE,SAAS,YAAY,EAAE,GAC/B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAShC;AAED,2CAA2C;AAC3C,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAE9D"}
@@ -0,0 +1,27 @@
1
+ export function tuiReplaceBoot(kernel, message, cwd, geometry) {
2
+ const path = message.path === "" ? cwd : message.path;
3
+ const sessionId = message.sessionId?.trim() ?? "";
4
+ return {
5
+ kernel,
6
+ path,
7
+ ...(message.draft != null && message.draft !== "" ? { draft: message.draft } : {}),
8
+ ...(sessionId === "" ? {} : { sessionId, restore: true }),
9
+ ...(geometry != null && geometry.cols > 0 && geometry.rows > 0 ? { cols: geometry.cols, rows: geometry.rows } : {}),
10
+ };
11
+ }
12
+ export function tuiBootGeometry(boot, pending) {
13
+ let cols = boot.cols ?? 80;
14
+ let rows = boot.rows ?? 24;
15
+ for (const message of pending) {
16
+ if (message.lane !== "paint" || message.message.kind !== "resize")
17
+ continue;
18
+ cols = message.message.cols;
19
+ rows = message.message.rows;
20
+ }
21
+ return { cols, rows };
22
+ }
23
+ /** see preamble HELD_KEYS, CHANGE ONLY. */
24
+ export function tuiWorkerReplay(message) {
25
+ return !(message.lane === "paint" && message.message.kind === "input_events");
26
+ }
27
+ //# sourceMappingURL=channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.js","sourceRoot":"","sources":["../../src/tui/channel.ts"],"names":[],"mappings":"AA4BA,MAAM,UAAU,cAAc,CAC5B,MAAc,EACd,OAAwF,EACxF,GAAW,EACX,QAA2D;IAE3D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;IACtD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAClD,OAAO;QACL,MAAM;QACN,IAAI;QACJ,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClF,GAAG,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACzD,GAAG,CAAC,QAAQ,IAAI,IAAI,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpH,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,IAAuC,EACvC,OAAgC;IAEhC,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;IAC3B,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;IAC3B,KAAK,MAAM,OAAO,IAAI,OAAO,EAAE,CAAC;QAC9B,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,QAAQ;YAAE,SAAS;QAC5E,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;QAC5B,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;IAC9B,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,eAAe,CAAC,OAAqB;IACnD,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;AAChF,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Catalog verbs with no CommandSpec body. Tea #invokeHostVerb handles
3
+ * them locally — firing #commandSurface is a no-op.
4
+ */
5
+ export declare const HOST_VERBS: readonly ["compact", "quit", "new", "rename", "agentic", "background", "rewind", "undo", "permissions"];
6
+ export declare function isHostVerb(verb: string): verb is (typeof HOST_VERBS)[number];
7
+ //# sourceMappingURL=host-verbs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-verbs.d.ts","sourceRoot":"","sources":["../../src/tui/host-verbs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,UAAU,yGAUb,CAAC;AAEX,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAE5E"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Catalog verbs with no CommandSpec body. Tea #invokeHostVerb handles
3
+ * them locally — firing #commandSurface is a no-op.
4
+ */
5
+ export const HOST_VERBS = [
6
+ "compact",
7
+ "quit",
8
+ "new",
9
+ "rename",
10
+ "agentic",
11
+ "background",
12
+ "rewind",
13
+ "undo",
14
+ "permissions",
15
+ ];
16
+ export function isHostVerb(verb) {
17
+ return HOST_VERBS.includes(verb);
18
+ }
19
+ //# sourceMappingURL=host-verbs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-verbs.js","sourceRoot":"","sources":["../../src/tui/host-verbs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,SAAS;IACT,MAAM;IACN,KAAK;IACL,QAAQ;IACR,SAAS;IACT,YAAY;IACZ,QAAQ;IACR,MAAM;IACN,aAAa;CACL,CAAC;AAEX,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAQ,UAAgC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { type CliAgentFlags, type ShellStreams } from "@inhuman.tools/harness-sdk/launch";
2
+ /** First Ctrl-C hint when `spec.resident` is set. Second press still leaves the TUI. */
3
+ export declare const DAEMON_QUIT_ACTION = "exit the UI and keep session running in background";
4
+ export declare function sessionTitleOsc(text: string): string;
5
+ export declare function hostExitCode(args: {
6
+ failed: string | null;
7
+ workerCode: number | null;
8
+ shutdown: boolean;
9
+ }): {
10
+ code: number;
11
+ reason: string;
12
+ };
13
+ export declare function attachTui(args: {
14
+ kernel: string;
15
+ session: string | undefined;
16
+ continueLast?: boolean;
17
+ restartDaemon: boolean;
18
+ agent?: CliAgentFlags;
19
+ streams: ShellStreams;
20
+ /** Start or attach the daemon. The launcher owns that; the shell only asks. */
21
+ ensure: (kernel: string, options?: {
22
+ readonly restart?: boolean;
23
+ }) => Promise<void>;
24
+ }): Promise<number>;
25
+ //# sourceMappingURL=host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/tui/host.ts"],"names":[],"mappings":"AASA,OAAO,EAML,KAAK,aAAa,EAElB,KAAK,YAAY,EAElB,MAAM,mCAAmC,CAAC;AAQ3C,wFAAwF;AACxF,eAAO,MAAM,kBAAkB,uDAAuD,CAAC;AAEvF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIpD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GAAG;IAC3G,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CASA;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,YAAY,CAAC;IACtB,+EAA+E;IAC/E,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrF,GAAG,OAAO,CAAC,MAAM,CAAC,CAmQlB"}
@@ -0,0 +1,380 @@
1
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2
+ if (value !== null && value !== void 0) {
3
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
+ var dispose, inner;
5
+ if (async) {
6
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
+ dispose = value[Symbol.asyncDispose];
8
+ }
9
+ if (dispose === void 0) {
10
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
+ dispose = value[Symbol.dispose];
12
+ if (async) inner = dispose;
13
+ }
14
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
15
+ if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
16
+ env.stack.push({ value: value, dispose: dispose, async: async });
17
+ }
18
+ else if (async) {
19
+ env.stack.push({ async: true });
20
+ }
21
+ return value;
22
+ };
23
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
24
+ return function (env) {
25
+ function fail(e) {
26
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
27
+ env.hasError = true;
28
+ }
29
+ var r, s = 0;
30
+ function next() {
31
+ while (r = env.stack.pop()) {
32
+ try {
33
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
34
+ if (r.dispose) {
35
+ var result = r.dispose.call(r.value);
36
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
37
+ }
38
+ else s |= 1;
39
+ }
40
+ catch (e) {
41
+ fail(e);
42
+ }
43
+ }
44
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
45
+ if (env.hasError) throw env.error;
46
+ }
47
+ return next();
48
+ };
49
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
50
+ var e = new Error(message);
51
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
52
+ });
53
+ /**
54
+ * Worker entry is a sibling file URL. worker_threads does not go through TS path mapping.
55
+ */
56
+ import { fileURLToPath } from "node:url";
57
+ import { Worker } from "node:worker_threads";
58
+ import { dumpSkipped, fail, installProcessLog, mute, note, openLog, step } from "@inhuman.tools/harness-diagnostics";
59
+ import { clampChars, occupiedSessionIds, SESSION_TITLE_MAX_CHARS } from "@inhuman.tools/harness-model";
60
+ import { Client } from "@inhuman.tools/harness-sdk";
61
+ import { clearTermContinue, hasCliAgentFlags, pickContinueSession, resolveCliAgent, termSessionKey, } from "@inhuman.tools/harness-sdk/launch";
62
+ import { daemonLogPath } from "@inhuman.tools/harness-sdk/paths";
63
+ import { tuiReplaceBoot } from "./channel.js";
64
+ import { startRustPresent } from "./rust-present.js";
65
+ import { SPINNER_PHASE } from "./spinner-phase.js";
66
+ /** First Ctrl-C hint when `spec.resident` is set. Second press still leaves the TUI. */
67
+ export const DAEMON_QUIT_ACTION = "exit the UI and keep session running in background";
68
+ export function sessionTitleOsc(text) {
69
+ const payload = clampChars(text.replaceAll(/[\u0000-\u001F\u007F-\u009F]/g, "").trim(), SESSION_TITLE_MAX_CHARS) || "harness";
70
+ return `\u001B]0;${payload}\u0007`;
71
+ }
72
+ export function hostExitCode(args) {
73
+ if (args.failed !== null)
74
+ return { code: 1, reason: `failed ${args.failed}` };
75
+ if (args.shutdown) {
76
+ const clean = args.workerCode === 0 || args.workerCode === null;
77
+ return { code: clean ? 0 : 1, reason: "shutdown" };
78
+ }
79
+ if (args.workerCode === 0)
80
+ return { code: 1, reason: "worker 0 unexpected" };
81
+ if (args.workerCode === null)
82
+ return { code: 1, reason: "worker signal" };
83
+ return { code: 1, reason: `worker ${args.workerCode}` };
84
+ }
85
+ export async function attachTui(args) {
86
+ const { kernel, streams } = args;
87
+ const log = openLog(daemonLogPath(kernel));
88
+ installProcessLog("host");
89
+ note(`log ${log}`);
90
+ try {
91
+ step(`ensure ${kernel}`);
92
+ await args.ensure(kernel, { restart: args.restartDaemon });
93
+ step("ensure ready");
94
+ }
95
+ catch (error) {
96
+ fail("ensure", error);
97
+ streams.writeErr(error);
98
+ return 1;
99
+ }
100
+ let sessionId = args.session;
101
+ let restore = sessionId !== undefined;
102
+ let agent;
103
+ try {
104
+ const flags = args.agent ?? {};
105
+ const needKernel = args.continueLast === true || hasCliAgentFlags(flags);
106
+ if (needKernel) {
107
+ const env_1 = { stack: [], error: void 0, hasError: false };
108
+ try {
109
+ const handle = __addDisposableResource(env_1, await Client.kernel(kernel), true);
110
+ if (hasCliAgentFlags(flags)) {
111
+ const resolved = await resolveCliAgent(handle, flags);
112
+ if (!resolved.ok) {
113
+ streams.writeErr(resolved.error);
114
+ return 1;
115
+ }
116
+ agent = resolved.agent;
117
+ }
118
+ if (args.continueLast === true) {
119
+ const picked = await pickContinueSession({
120
+ key: termSessionKey(process.env),
121
+ termContinue: handle.plexus.root.termContinue,
122
+ sessions: handle.plexus.root.sessions,
123
+ occupied: occupiedSessionIds(handle.plexus.awareness),
124
+ sessionExists: (id) => Client.sessionExists(kernel, id),
125
+ });
126
+ if (picked.staleKeyToClear != null) {
127
+ await clearTermContinue((method, params) => handle.request(method, params), picked.staleKeyToClear);
128
+ }
129
+ sessionId = picked.sessionId;
130
+ restore = picked.sessionId !== undefined;
131
+ }
132
+ }
133
+ catch (e_1) {
134
+ env_1.error = e_1;
135
+ env_1.hasError = true;
136
+ }
137
+ finally {
138
+ const result_1 = __disposeResources(env_1);
139
+ if (result_1)
140
+ await result_1;
141
+ }
142
+ }
143
+ if (args.continueLast !== true && sessionId !== undefined) {
144
+ if (!(await Client.sessionExists(kernel, sessionId))) {
145
+ streams.writeErr(`session not found: ${sessionId}`);
146
+ return 1;
147
+ }
148
+ restore = true;
149
+ }
150
+ }
151
+ catch (error) {
152
+ fail("continue lookup", error);
153
+ streams.writeErr(error);
154
+ return 1;
155
+ }
156
+ const boot = {
157
+ kernel,
158
+ path: process.cwd(),
159
+ ...(sessionId === undefined || !restore ? {} : { sessionId, restore: true }),
160
+ ...(agent != null && agent.connection !== "" ? { connection: agent.connection } : {}),
161
+ ...(agent?.model != null && agent.model !== "" ? { model: agent.model } : {}),
162
+ };
163
+ mute();
164
+ let worker = spawnTuiWorker(boot, streams);
165
+ const defaultGeometry = { cols: streams.stdout.columns ?? 80, rows: streams.stdout.rows ?? 24 };
166
+ let rust = null;
167
+ let attached = false;
168
+ let failed = null;
169
+ let shutdown = false;
170
+ let resident = false;
171
+ let replacing = false;
172
+ let workerCode = null;
173
+ let resolveAttached = () => undefined;
174
+ let rejectAttached = () => undefined;
175
+ let resolveRunning = () => undefined;
176
+ const attachedWait = new Promise((resolve, reject) => {
177
+ resolveAttached = resolve;
178
+ rejectAttached = reject;
179
+ });
180
+ const runningWait = new Promise((resolve) => {
181
+ resolveRunning = resolve;
182
+ });
183
+ const postShutdown = (mine) => {
184
+ mine.postMessage({ lane: "host", kind: "shutdown" });
185
+ };
186
+ let phase = "";
187
+ const showPhase = (text) => {
188
+ if (text === phase)
189
+ return;
190
+ phase = text;
191
+ rust?.writeDown({ kind: "phase", text });
192
+ if (text !== "")
193
+ note(`spinner ${text}`);
194
+ };
195
+ const applyPaint = (message, from) => {
196
+ if (from !== worker || replacing)
197
+ return;
198
+ if (phase !== "")
199
+ showPhase("");
200
+ for (const item of message.batch) {
201
+ try {
202
+ rust?.writeDown(item);
203
+ }
204
+ catch (error) {
205
+ failed = error instanceof Error ? error.message : String(error);
206
+ fail("paint protocol", error);
207
+ if (attached)
208
+ postShutdown(worker);
209
+ else
210
+ rejectAttached(error instanceof Error ? error : new Error(failed));
211
+ return;
212
+ }
213
+ }
214
+ };
215
+ const onWorkerFailed = (reason, error) => {
216
+ failed = reason;
217
+ fail(`worker failed ${failed}`, error);
218
+ if (attached) {
219
+ resolveRunning();
220
+ }
221
+ else {
222
+ rejectAttached(error instanceof Error ? error : new Error(failed));
223
+ }
224
+ };
225
+ const replaceWorker = async (message) => {
226
+ if (replacing || shutdown)
227
+ return;
228
+ replacing = true;
229
+ showPhase(SPINNER_PHASE.closingSession);
230
+ const old = worker;
231
+ const exited = waitWorkerExit(old);
232
+ postShutdown(old);
233
+ const result = await exited;
234
+ note(`host replace exit code=${result.code} signal=${result.signal ?? ""}`);
235
+ if (shutdown) {
236
+ workerCode = result.code;
237
+ resolveRunning();
238
+ return;
239
+ }
240
+ showPhase(SPINNER_PHASE.openingSession);
241
+ const geometry = rust?.geometry() ?? defaultGeometry;
242
+ const next = spawnTuiWorker(tuiReplaceBoot(kernel, message, process.cwd(), geometry), streams);
243
+ worker = next;
244
+ replacing = false;
245
+ wireWorker(next);
246
+ next.postMessage({
247
+ lane: "paint",
248
+ message: { kind: "resize", cols: geometry.cols, rows: geometry.rows },
249
+ });
250
+ };
251
+ const wireWorker = (mine) => {
252
+ mine.on("message", (message) => {
253
+ if (mine !== worker)
254
+ return;
255
+ if (message.lane === "host" && message.kind === "title") {
256
+ rust?.writeDown({ kind: "title", text: message.text });
257
+ return;
258
+ }
259
+ if (message.lane === "host" && message.kind === "phase") {
260
+ showPhase(message.text);
261
+ return;
262
+ }
263
+ if (message.lane === "paint") {
264
+ applyPaint(message, mine);
265
+ return;
266
+ }
267
+ if (message.kind === "quit") {
268
+ requestShutdown("quit");
269
+ return;
270
+ }
271
+ if (message.kind === "resident") {
272
+ resident = message.resident;
273
+ return;
274
+ }
275
+ if (message.kind === "replace") {
276
+ void replaceWorker(message);
277
+ return;
278
+ }
279
+ if (message.kind === "attached") {
280
+ step("worker attached");
281
+ showPhase("");
282
+ attached = true;
283
+ resolveAttached();
284
+ return;
285
+ }
286
+ onWorkerFailed(message.reason ?? "worker failed");
287
+ });
288
+ mine.on("error", (error) => {
289
+ if (mine !== worker)
290
+ return;
291
+ failed = error instanceof Error ? error.message : String(error);
292
+ fail("host worker error", error);
293
+ if (!attached)
294
+ rejectAttached(error instanceof Error ? error : new Error(failed));
295
+ });
296
+ mine.once("exit", (code, signal) => {
297
+ if (replacing || mine !== worker)
298
+ return;
299
+ workerCode = code;
300
+ note(`host worker exit code=${code} signal=${signal ?? ""}`);
301
+ if (!attached && failed === null) {
302
+ rejectAttached(new Error(`tui worker exited ${code}`));
303
+ }
304
+ resolveRunning();
305
+ });
306
+ };
307
+ const requestShutdown = (why) => {
308
+ if (shutdown)
309
+ return;
310
+ shutdown = true;
311
+ note(`host ${why}`);
312
+ postShutdown(worker);
313
+ };
314
+ step("render");
315
+ let session;
316
+ try {
317
+ session = startRustPresent({
318
+ stderr: streams.stderr,
319
+ onUp: (message) => {
320
+ const down = { lane: "paint", message };
321
+ worker.postMessage(down);
322
+ },
323
+ onQuit: () => requestShutdown(resident ? "quit resident" : "quit"),
324
+ onFailed: (reason) => onWorkerFailed(reason),
325
+ });
326
+ }
327
+ catch (error) {
328
+ fail("qd", error);
329
+ streams.writeErr(error);
330
+ await worker.terminate();
331
+ return 1;
332
+ }
333
+ rust = session;
334
+ wireWorker(worker);
335
+ installProcessLog("host", () => {
336
+ dumpSkipped(streams.stderr);
337
+ return session.restore();
338
+ });
339
+ process.once("SIGINT", () => requestShutdown("SIGINT"));
340
+ process.once("SIGTERM", () => requestShutdown("SIGTERM"));
341
+ try {
342
+ step("wait attached");
343
+ await attachedWait;
344
+ step("running");
345
+ await runningWait;
346
+ const ended = hostExitCode({ failed, workerCode, shutdown });
347
+ note(`host end ${ended.reason}`);
348
+ return ended.code;
349
+ }
350
+ catch (error) {
351
+ fail("host run", error);
352
+ streams.writeErr(error);
353
+ return 1;
354
+ }
355
+ finally {
356
+ await session.restore();
357
+ await worker.terminate();
358
+ dumpSkipped(streams.stderr);
359
+ }
360
+ }
361
+ function spawnTuiWorker(boot, streams) {
362
+ const self = fileURLToPath(import.meta.url);
363
+ const workerFile = fileURLToPath(new URL(self.endsWith(".ts") ? "./worker-entry.ts" : "./worker-entry.js", import.meta.url));
364
+ step(`worker ${workerFile}`);
365
+ const worker = new Worker(workerFile, {
366
+ workerData: boot,
367
+ // STDERR_PIPE: default inherit writes fd 2 into the alt-screen; holdStderr never sees those.
368
+ stderr: true,
369
+ });
370
+ worker.stderr.on("data", (chunk) => {
371
+ streams.stderr.write(chunk);
372
+ });
373
+ return worker;
374
+ }
375
+ function waitWorkerExit(worker) {
376
+ return new Promise((resolve) => {
377
+ worker.once("exit", (code, signal) => resolve({ code, signal }));
378
+ });
379
+ }
380
+ //# sourceMappingURL=host.js.map