@adhdev/daemon-core 0.9.82-rc.30 → 0.9.82-rc.301

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 (286) hide show
  1. package/dist/boot/daemon-lifecycle.d.ts +8 -0
  2. package/dist/boot/process-hardening.d.ts +50 -0
  3. package/dist/build-info.d.ts +37 -0
  4. package/dist/chat/source-machine.d.ts +166 -0
  5. package/dist/chat/source-resolver.d.ts +104 -0
  6. package/dist/chat/subscription-updates.d.ts +1 -0
  7. package/dist/cli-adapter-types.d.ts +23 -2
  8. package/dist/cli-adapters/cli-script-runner.d.ts +117 -0
  9. package/dist/cli-adapters/cli-state-engine.d.ts +198 -0
  10. package/dist/cli-adapters/provider-cli-adapter.d.ts +106 -63
  11. package/dist/cli-adapters/provider-cli-parse.d.ts +4 -0
  12. package/dist/cli-adapters/provider-cli-shared.d.ts +38 -0
  13. package/dist/cli-adapters/raw-terminal-io.d.ts +37 -0
  14. package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +6 -3
  15. package/dist/cli-adapters/terminal-backends/types.d.ts +10 -2
  16. package/dist/cli-adapters/terminal-screen.d.ts +4 -11
  17. package/dist/commands/cli-manager.d.ts +2 -1
  18. package/dist/commands/handler.d.ts +110 -0
  19. package/dist/commands/mesh-coordinator.d.ts +85 -1
  20. package/dist/commands/router.d.ts +210 -1
  21. package/dist/config/chat-history.d.ts +9 -0
  22. package/dist/config/config.d.ts +5 -0
  23. package/dist/config/mesh-config.d.ts +72 -1
  24. package/dist/git/git-commands.d.ts +9 -1
  25. package/dist/git/git-diff.d.ts +6 -0
  26. package/dist/git/git-status.d.ts +7 -0
  27. package/dist/git/git-types.d.ts +2 -50
  28. package/dist/index.d.ts +51 -12
  29. package/dist/index.js +38477 -16092
  30. package/dist/index.js.map +1 -1
  31. package/dist/index.mjs +39085 -16804
  32. package/dist/index.mjs.map +1 -1
  33. package/dist/installer.d.ts +1 -4
  34. package/dist/ipc/local-ipc-server.d.ts +91 -0
  35. package/dist/launch.d.ts +1 -1
  36. package/dist/logging/async-batch-writer.d.ts +10 -0
  37. package/dist/mesh/contracts.d.ts +164 -0
  38. package/dist/mesh/coordinator-prompt.d.ts +36 -0
  39. package/dist/mesh/coordinator-registry.d.ts +59 -0
  40. package/dist/mesh/mesh-active-work.d.ts +108 -0
  41. package/dist/mesh/mesh-delivery-policy.d.ts +131 -0
  42. package/dist/mesh/mesh-events-coordinator.d.ts +138 -0
  43. package/dist/mesh/mesh-events-pending.d.ts +45 -0
  44. package/dist/mesh/mesh-events-stale.d.ts +40 -0
  45. package/dist/mesh/mesh-events-utils.d.ts +47 -0
  46. package/dist/mesh/mesh-events.d.ts +6 -49
  47. package/dist/mesh/mesh-fast-forward.d.ts +81 -0
  48. package/dist/mesh/mesh-host-ownership.d.ts +9 -0
  49. package/dist/mesh/mesh-init.d.ts +86 -0
  50. package/dist/mesh/mesh-ledger-reconciliation.d.ts +23 -3
  51. package/dist/mesh/mesh-ledger.d.ts +77 -1
  52. package/dist/mesh/mesh-missions.d.ts +107 -0
  53. package/dist/mesh/mesh-reconcile-loop.d.ts +7 -0
  54. package/dist/mesh/mesh-refine-batch.d.ts +68 -0
  55. package/dist/mesh/mesh-refine-status.d.ts +62 -0
  56. package/dist/mesh/mesh-review-inbox.d.ts +90 -0
  57. package/dist/mesh/mesh-routing.d.ts +70 -0
  58. package/dist/mesh/mesh-runtime-store.d.ts +377 -0
  59. package/dist/mesh/mesh-task-stats.d.ts +49 -0
  60. package/dist/mesh/mesh-unresolved-forward-outbox.d.ts +30 -0
  61. package/dist/mesh/mesh-work-queue.d.ts +181 -5
  62. package/dist/mesh/preview-freshness.d.ts +18 -0
  63. package/dist/mesh/refine-config.d.ts +215 -0
  64. package/dist/mesh/worktree-bootstrap-config.d.ts +135 -0
  65. package/dist/providers/acp-provider-instance.d.ts +2 -0
  66. package/dist/providers/approval-utils.d.ts +13 -0
  67. package/dist/providers/cli-provider-instance.d.ts +61 -3
  68. package/dist/providers/contracts.d.ts +130 -6
  69. package/dist/providers/external-sources.d.ts +71 -0
  70. package/dist/providers/native-history/antigravity-cli-transcript.d.ts +100 -0
  71. package/dist/providers/native-history/claude-cli-transcript.d.ts +70 -0
  72. package/dist/providers/native-history/codex-cli-transcript.d.ts +73 -0
  73. package/dist/providers/native-history/dispatcher.d.ts +27 -0
  74. package/dist/providers/native-history/hermes-cli-transcript.d.ts +30 -0
  75. package/dist/providers/native-history/index.d.ts +13 -0
  76. package/dist/providers/provider-instance-manager.d.ts +13 -0
  77. package/dist/providers/provider-instance.d.ts +13 -1
  78. package/dist/providers/provider-loader.d.ts +26 -4
  79. package/dist/providers/provider-trust.d.ts +31 -0
  80. package/dist/providers/read-chat-contract.d.ts +29 -0
  81. package/dist/providers/sdk/v1/builders/acp/detect-status.d.ts +68 -0
  82. package/dist/providers/sdk/v1/builders/cli/detect-status.d.ts +85 -0
  83. package/dist/providers/sdk/v1/builders/cli/parse-approval-squash.d.ts +59 -0
  84. package/dist/providers/sdk/v1/builders/cli/parse-approval.d.ts +65 -0
  85. package/dist/providers/sdk/v1/builders/cli/parse-session.d.ts +91 -0
  86. package/dist/providers/sdk/v1/builders/cli/visible-region.d.ts +42 -0
  87. package/dist/providers/sdk/v1/fixture-tooling/format.d.ts +126 -0
  88. package/dist/providers/sdk/v1/fixture-tooling/index.d.ts +8 -0
  89. package/dist/providers/sdk/v1/fixture-tooling/replay.d.ts +38 -0
  90. package/dist/providers/sdk/v1/index.d.ts +30 -0
  91. package/dist/providers/sdk/v1/sandbox/README-design.d.ts +193 -0
  92. package/dist/providers/sdk/v1/sandbox/require-whitelist.d.ts +74 -0
  93. package/dist/providers/sdk/v1/sandbox/script-runner.d.ts +98 -0
  94. package/dist/providers/sdk/v1/types/cli/index.d.ts +277 -0
  95. package/dist/providers/sdk/v1/types/common/index.d.ts +203 -0
  96. package/dist/providers/sdk/v1/validators/index.d.ts +5 -0
  97. package/dist/providers/sdk/v1/validators/manifest.d.ts +40 -0
  98. package/dist/providers/sdk/v1/validators/taint.d.ts +52 -0
  99. package/dist/providers/spec/adapter.d.ts +59 -0
  100. package/dist/providers/spec/cli-adapter.d.ts +186 -0
  101. package/dist/providers/spec/evaluator.d.ts +23 -0
  102. package/dist/providers/spec/fsm-driver.d.ts +278 -0
  103. package/dist/providers/spec/fsm-evaluator.d.ts +72 -0
  104. package/dist/providers/spec/fsm-loader.d.ts +14 -0
  105. package/dist/providers/spec/fsm-types.d.ts +128 -0
  106. package/dist/providers/spec/native-history-executor.d.ts +41 -0
  107. package/dist/providers/spec/pre-launch-trust.d.ts +16 -0
  108. package/dist/providers/spec/route.d.ts +4 -0
  109. package/dist/providers/spec/types.d.ts +144 -0
  110. package/dist/providers/transcript-v2.d.ts +176 -0
  111. package/dist/providers/types/interactive-prompt.d.ts +84 -0
  112. package/dist/repo-mesh-types.d.ts +198 -13
  113. package/dist/sessions/registry.d.ts +6 -0
  114. package/dist/shared-types-extra.d.ts +2 -4
  115. package/dist/shared-types.d.ts +42 -1
  116. package/dist/status/normalize.d.ts +1 -1
  117. package/dist/status/normalize.js +1 -0
  118. package/dist/status/normalize.js.map +1 -1
  119. package/dist/status/normalize.mjs +1 -0
  120. package/dist/status/normalize.mjs.map +1 -1
  121. package/dist/status/reporter.d.ts +2 -0
  122. package/dist/status/snapshot.d.ts +1 -0
  123. package/dist/types.d.ts +5 -0
  124. package/package.json +7 -3
  125. package/src/agent-stream/poller.ts +2 -3
  126. package/src/boot/daemon-lifecycle.ts +55 -12
  127. package/src/boot/process-hardening.ts +89 -0
  128. package/src/build-info.ts +73 -0
  129. package/src/chat/source-machine.ts +534 -0
  130. package/src/chat/source-resolver.ts +0 -0
  131. package/src/chat/subscription-updates.ts +20 -1
  132. package/src/cli-adapter-types.d.ts +1 -0
  133. package/src/cli-adapter-types.ts +22 -2
  134. package/src/cli-adapters/cli-script-runner.ts +421 -0
  135. package/src/cli-adapters/cli-state-engine.ts +1215 -0
  136. package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
  137. package/src/cli-adapters/provider-cli-adapter.ts +674 -1139
  138. package/src/cli-adapters/provider-cli-parse.d.ts +1 -0
  139. package/src/cli-adapters/provider-cli-parse.ts +13 -0
  140. package/src/cli-adapters/provider-cli-runtime.ts +3 -1
  141. package/src/cli-adapters/provider-cli-shared.d.ts +2 -0
  142. package/src/cli-adapters/provider-cli-shared.ts +68 -11
  143. package/src/cli-adapters/raw-terminal-io.ts +252 -0
  144. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +53 -29
  145. package/src/cli-adapters/terminal-backends/types.ts +10 -3
  146. package/src/cli-adapters/terminal-screen.ts +16 -81
  147. package/src/commands/chat-commands.ts +1813 -60
  148. package/src/commands/cli-manager.ts +286 -14
  149. package/src/commands/handler.ts +809 -2
  150. package/src/commands/mesh-coordinator.ts +332 -122
  151. package/src/commands/router.ts +5994 -549
  152. package/src/config/chat-history.ts +474 -24
  153. package/src/config/config.ts +12 -0
  154. package/src/config/mesh-config.ts +303 -3
  155. package/src/config/recent-activity.ts +8 -2
  156. package/src/daemon/dev-auto-implement.ts +3 -2
  157. package/src/daemon/dev-cli-debug.ts +10 -1
  158. package/src/detection/ide-detector.ts +26 -16
  159. package/src/git/git-commands.ts +42 -12
  160. package/src/git/git-diff.ts +53 -0
  161. package/src/git/git-status.ts +233 -7
  162. package/src/git/git-types.ts +14 -62
  163. package/src/git/git-worktree.ts +8 -1
  164. package/src/index.ts +131 -11
  165. package/src/installer.d.ts +1 -1
  166. package/src/installer.ts +8 -6
  167. package/src/ipc/local-ipc-server.ts +278 -0
  168. package/src/launch.d.ts +1 -1
  169. package/src/launch.ts +37 -28
  170. package/src/logging/async-batch-writer.ts +55 -0
  171. package/src/logging/logger.ts +2 -1
  172. package/src/mesh/contracts.ts +329 -0
  173. package/src/mesh/coordinator-prompt.ts +234 -31
  174. package/src/mesh/coordinator-registry.ts +121 -0
  175. package/src/mesh/mesh-active-work.ts +469 -0
  176. package/src/mesh/mesh-delivery-policy.ts +315 -0
  177. package/src/mesh/mesh-events-coordinator.ts +1786 -0
  178. package/src/mesh/mesh-events-pending.ts +508 -0
  179. package/src/mesh/mesh-events-stale.ts +290 -0
  180. package/src/mesh/mesh-events-utils.ts +254 -0
  181. package/src/mesh/mesh-events.ts +30 -1035
  182. package/src/mesh/mesh-fast-forward.ts +839 -0
  183. package/src/mesh/mesh-host-ownership.ts +73 -0
  184. package/src/mesh/mesh-init.ts +260 -0
  185. package/src/mesh/mesh-ledger-reconciliation.ts +12 -5
  186. package/src/mesh/mesh-ledger.ts +589 -102
  187. package/src/mesh/mesh-missions.ts +232 -0
  188. package/src/mesh/mesh-reconcile-loop.ts +466 -0
  189. package/src/mesh/mesh-refine-batch.ts +197 -0
  190. package/src/mesh/mesh-refine-status.ts +231 -0
  191. package/src/mesh/mesh-review-inbox.ts +307 -0
  192. package/src/mesh/mesh-routing.ts +291 -0
  193. package/src/mesh/mesh-runtime-store.ts +1513 -0
  194. package/src/mesh/mesh-task-stats.ts +154 -0
  195. package/src/mesh/mesh-unresolved-forward-outbox.ts +185 -0
  196. package/src/mesh/mesh-work-queue.ts +604 -145
  197. package/src/mesh/preview-freshness.ts +118 -0
  198. package/src/mesh/refine-config.ts +403 -0
  199. package/src/mesh/worktree-bootstrap-config.ts +326 -0
  200. package/src/providers/acp-provider-instance.ts +15 -1
  201. package/src/providers/approval-utils.d.ts +4 -0
  202. package/src/providers/approval-utils.ts +47 -5
  203. package/src/providers/chat-message-normalization.ts +4 -11
  204. package/src/providers/cli-provider-instance.ts +953 -87
  205. package/src/providers/contracts.d.ts +55 -0
  206. package/src/providers/contracts.ts +141 -6
  207. package/src/providers/extension-provider-instance.ts +5 -1
  208. package/src/providers/external-sources.ts +218 -0
  209. package/src/providers/ide-provider-instance.ts +25 -6
  210. package/src/providers/native-history/antigravity-cli-transcript.ts +643 -0
  211. package/src/providers/native-history/claude-cli-transcript.ts +396 -0
  212. package/src/providers/native-history/codex-cli-transcript.ts +479 -0
  213. package/src/providers/native-history/dispatcher.ts +340 -0
  214. package/src/providers/native-history/hermes-cli-transcript.ts +230 -0
  215. package/src/providers/native-history/index.ts +30 -0
  216. package/src/providers/provider-instance-manager.ts +30 -0
  217. package/src/providers/provider-instance.ts +10 -1
  218. package/src/providers/provider-loader.ts +584 -50
  219. package/src/providers/provider-schema.ts +87 -14
  220. package/src/providers/provider-trust.ts +114 -0
  221. package/src/providers/read-chat-contract.ts +76 -16
  222. package/src/providers/sdk/README.md +49 -0
  223. package/src/providers/sdk/v1/builders/acp/detect-status.ts +144 -0
  224. package/src/providers/sdk/v1/builders/cli/detect-status.ts +262 -0
  225. package/src/providers/sdk/v1/builders/cli/parse-approval-squash.ts +158 -0
  226. package/src/providers/sdk/v1/builders/cli/parse-approval.ts +250 -0
  227. package/src/providers/sdk/v1/builders/cli/parse-session.ts +276 -0
  228. package/src/providers/sdk/v1/builders/cli/visible-region.ts +143 -0
  229. package/src/providers/sdk/v1/fixture-tooling/format.ts +130 -0
  230. package/src/providers/sdk/v1/fixture-tooling/index.ts +22 -0
  231. package/src/providers/sdk/v1/fixture-tooling/replay.ts +352 -0
  232. package/src/providers/sdk/v1/index.ts +152 -0
  233. package/src/providers/sdk/v1/sandbox/README-design.ts +195 -0
  234. package/src/providers/sdk/v1/sandbox/require-whitelist.ts +472 -0
  235. package/src/providers/sdk/v1/sandbox/script-runner.ts +150 -0
  236. package/src/providers/sdk/v1/schemas/cli/provider.schema.json +504 -0
  237. package/src/providers/sdk/v1/schemas/primitives/acp-session-protocol-v1.json +131 -0
  238. package/src/providers/sdk/v1/schemas/primitives/native-history-codex-rollout-v1.json +66 -0
  239. package/src/providers/sdk/v1/schemas/primitives/tui-approval-squash-v1.json +91 -0
  240. package/src/providers/sdk/v1/schemas/primitives/tui-assistant-block-v1.json +91 -0
  241. package/src/providers/sdk/v1/schemas/primitives/tui-cue-ordering-v1.json +47 -0
  242. package/src/providers/sdk/v1/schemas/primitives/tui-dispatch-order-v1.json +32 -0
  243. package/src/providers/sdk/v1/schemas/primitives/tui-footer-chrome-v1.json +42 -0
  244. package/src/providers/sdk/v1/schemas/primitives/tui-index-finder-v1.json +27 -0
  245. package/src/providers/sdk/v1/schemas/primitives/tui-modal-v1.json +125 -0
  246. package/src/providers/sdk/v1/schemas/primitives/tui-prompt-marker-v1.json +45 -0
  247. package/src/providers/sdk/v1/schemas/primitives/tui-session-id-extraction-v1.json +46 -0
  248. package/src/providers/sdk/v1/schemas/primitives/tui-settled-prompt-v1.json +71 -0
  249. package/src/providers/sdk/v1/schemas/primitives/tui-spinner-v1.json +83 -0
  250. package/src/providers/sdk/v1/schemas/primitives/tui-transcript-pty-v1.json +83 -0
  251. package/src/providers/sdk/v1/schemas/primitives/tui-visible-region-v1.json +57 -0
  252. package/src/providers/sdk/v1/schemas/primitives/tui-welcome-screen-v1.json +35 -0
  253. package/src/providers/sdk/v1/types/cli/index.ts +365 -0
  254. package/src/providers/sdk/v1/types/common/index.ts +229 -0
  255. package/src/providers/sdk/v1/validators/index.ts +19 -0
  256. package/src/providers/sdk/v1/validators/manifest.ts +110 -0
  257. package/src/providers/sdk/v1/validators/taint.ts +309 -0
  258. package/src/providers/spec/adapter.ts +155 -0
  259. package/src/providers/spec/cli-adapter.ts +838 -0
  260. package/src/providers/spec/evaluator.ts +345 -0
  261. package/src/providers/spec/fsm-driver.ts +875 -0
  262. package/src/providers/spec/fsm-evaluator.ts +255 -0
  263. package/src/providers/spec/fsm-loader.ts +112 -0
  264. package/src/providers/spec/fsm-types.ts +222 -0
  265. package/src/providers/spec/native-history-executor.ts +943 -0
  266. package/src/providers/spec/pre-launch-trust.ts +104 -0
  267. package/src/providers/spec/route.ts +51 -0
  268. package/src/providers/spec/types.ts +189 -0
  269. package/src/providers/transcript-v2.ts +567 -0
  270. package/src/providers/types/interactive-prompt.ts +536 -0
  271. package/src/providers/version-archive.ts +38 -20
  272. package/src/repo-mesh-types.ts +252 -13
  273. package/src/sessions/registry.ts +6 -0
  274. package/src/shared-types-extra.ts +2 -4
  275. package/src/shared-types.ts +45 -1
  276. package/src/status/builders.ts +26 -6
  277. package/src/status/normalize.ts +2 -0
  278. package/src/status/reporter.ts +15 -0
  279. package/src/status/snapshot.ts +84 -25
  280. package/src/system/host-memory.ts +29 -12
  281. package/src/types.ts +5 -0
  282. package/dist/cli-adapters/terminal-backends/xterm-backend.d.ts +0 -17
  283. package/dist/mesh/mesh-sync.d.ts +0 -53
  284. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +0 -16
  285. package/src/cli-adapters/terminal-backends/xterm-backend.ts +0 -97
  286. package/src/mesh/mesh-sync.ts +0 -111
@@ -15,6 +15,7 @@ export declare function buildCliParseInput(options: {
15
15
  accumulatedRawBuffer: string;
16
16
  recentOutputBuffer: string;
17
17
  terminalScreenText: string;
18
+ workingDir?: string;
18
19
  baseMessages: CliChatMessage[];
19
20
  partialResponse: string;
20
21
  isWaitingForResponse?: boolean;
@@ -35,22 +35,30 @@ export function buildCliParseInput(options: {
35
35
  accumulatedRawBuffer: string;
36
36
  recentOutputBuffer: string;
37
37
  terminalScreenText: string;
38
+ workingDir?: string;
39
+ providerSessionId?: string;
40
+ historySessionId?: string;
38
41
  baseMessages: CliChatMessage[];
39
42
  partialResponse: string;
40
43
  isWaitingForResponse?: boolean;
41
44
  scope?: TurnParseScope | null;
42
45
  runtimeSettings: Record<string, any>;
46
+ spawnAt?: number;
43
47
  }): CliScriptInput {
44
48
  const {
45
49
  accumulatedBuffer,
46
50
  accumulatedRawBuffer,
47
51
  recentOutputBuffer,
48
52
  terminalScreenText,
53
+ workingDir,
54
+ providerSessionId,
55
+ historySessionId,
49
56
  baseMessages,
50
57
  partialResponse,
51
58
  isWaitingForResponse,
52
59
  scope,
53
60
  runtimeSettings,
61
+ spawnAt,
54
62
  } = options;
55
63
  const buffer = scope
56
64
  ? sliceFromOffset(accumulatedBuffer, scope.bufferStart)
@@ -66,6 +74,10 @@ export function buildCliParseInput(options: {
66
74
  rawBuffer,
67
75
  recentBuffer,
68
76
  screenText,
77
+ workspace: workingDir,
78
+ workingDir,
79
+ providerSessionId,
80
+ historySessionId,
69
81
  screen: buildCliScreenSnapshot(screenText),
70
82
  bufferScreen: buildCliScreenSnapshot(buffer),
71
83
  recentScreen: buildCliScreenSnapshot(recentBuffer),
@@ -74,6 +86,7 @@ export function buildCliParseInput(options: {
74
86
  isWaitingForResponse,
75
87
  promptText: scope?.prompt || '',
76
88
  settings: { ...runtimeSettings },
89
+ ...(typeof spawnAt === 'number' && spawnAt > 0 ? { spawnAt } : {}),
77
90
  };
78
91
  }
79
92
 
@@ -36,7 +36,9 @@ export function resolveCliSpawnPlan(options: {
36
36
  : spawnConfig.command;
37
37
  const binaryPath = findBinary(configuredCommand);
38
38
  const isWin = os.platform() === 'win32';
39
- const allArgs = [...spawnConfig.args, ...extraArgs];
39
+ const allArgs = [...spawnConfig.args, ...extraArgs].map((arg) =>
40
+ typeof arg === 'string' ? arg.replace(/\{\{workingDir\}\}/g, workingDir) : arg,
41
+ );
40
42
 
41
43
  let shellCmd: string;
42
44
  let shellArgs: string[];
@@ -55,6 +55,8 @@ export interface CliScriptInput {
55
55
  rawBuffer: string;
56
56
  recentBuffer: string;
57
57
  screenText: string;
58
+ workspace?: string;
59
+ workingDir?: string;
58
60
  screen: CliScreenSnapshot;
59
61
  bufferScreen: CliScreenSnapshot;
60
62
  recentScreen: CliScreenSnapshot;
@@ -4,6 +4,7 @@ import { execSync } from 'child_process';
4
4
  import type { ProviderResumeCapability } from '../providers/contracts.js';
5
5
  import type { ChatMessageKind } from '../providers/chat-message-normalization.js';
6
6
  import type { ChatBubbleState } from '../types.js';
7
+ import type { InteractivePrompt } from '../providers/types/interactive-prompt.js';
7
8
  import { sanitizeSpawnEnv } from './spawn-env.js';
8
9
 
9
10
  export interface CliChatMessage {
@@ -28,8 +29,27 @@ export interface CliSessionStatus {
28
29
  messages: CliChatMessage[];
29
30
  workingDir: string;
30
31
  activeModal: { message: string; buttons: string[] } | null;
32
+ /**
33
+ * Monotonic counter identifying which approval *entry* the current modal
34
+ * belongs to. Bumped by the FSM on every fresh waiting_approval entry.
35
+ * Consumers (e.g. auto-approval) use it to distinguish a genuinely new
36
+ * approval from the same approval re-observed across TUI paint flaps —
37
+ * two distinct approvals can carry identical message/button text, so the
38
+ * seq is the only reliable discriminator.
39
+ */
40
+ approvalEntrySeq?: number;
41
+ activeInteractivePrompt?: InteractivePrompt | null;
42
+ pendingOutboundCount?: number;
43
+ pendingOutboundMessages?: Array<{
44
+ id: string;
45
+ role: 'user';
46
+ content: string;
47
+ queuedAt: number;
48
+ source: string;
49
+ }>;
31
50
  errorMessage?: string;
32
51
  errorReason?: string;
52
+ providerSessionId?: string;
33
53
  bufferState?: {
34
54
  responseBuffer?: { truncated: boolean; droppedChars: number; maxChars: number };
35
55
  recentOutputBuffer?: { truncated: boolean; droppedChars: number; maxChars: number };
@@ -43,6 +63,9 @@ export interface ParsedSession {
43
63
  messages: any[];
44
64
  modal: { message: string; buttons: string[] } | null;
45
65
  parsedStatus: string | null;
66
+ errorMessage?: string;
67
+ errorReason?: string;
68
+ providerSessionId?: string;
46
69
  transcriptAuthority?: 'provider' | 'daemon';
47
70
  coverage?: 'full' | 'tail' | 'current-turn';
48
71
  }
@@ -94,6 +117,10 @@ export interface CliScriptInput {
94
117
  rawBuffer: string;
95
118
  recentBuffer: string;
96
119
  screenText: string;
120
+ workspace?: string;
121
+ workingDir?: string;
122
+ providerSessionId?: string;
123
+ historySessionId?: string;
97
124
  screen: CliScreenSnapshot;
98
125
  bufferScreen: CliScreenSnapshot;
99
126
  recentScreen: CliScreenSnapshot;
@@ -103,6 +130,7 @@ export interface CliScriptInput {
103
130
  promptText?: string;
104
131
  settings?: Record<string, any>;
105
132
  args?: Record<string, any>;
133
+ spawnAt?: number;
106
134
  }
107
135
 
108
136
  export interface CliStatusInput {
@@ -141,16 +169,26 @@ export interface CliProviderModule {
141
169
  binary: string;
142
170
  approvalKeys?: Record<number, string>;
143
171
  sendDelayMs?: number;
172
+ /** Wall-clock budget (ms) for a single provider script invocation. Default 50. Range 1..5000.
173
+ * Exceeding the budget records `timedOut: true` on the invocation trace and emits a
174
+ * throttled WARN — it does NOT abort the script (Node CJS can't interrupt sync code). */
175
+ scriptCallBudgetMs?: number;
144
176
  sendKey?: string;
145
177
  submitStrategy?: 'wait_for_echo' | 'immediate';
146
178
  /** Require the typed prompt to be visible on the PTY screen before sending Enter. */
147
179
  requirePromptEchoBeforeSubmit?: boolean;
148
180
  /** Allow sending another prompt while the CLI is still generating so users can intervene mid-turn. */
149
181
  allowInputDuringGeneration?: boolean;
182
+ /** When true, only transition to idle after the parsed transcript includes a final standard assistant message. */
183
+ requiresFinalAssistantBeforeIdle?: boolean;
184
+ /** When true, allow providers to augment stale snapshot data before parse. Reserved for future use. */
185
+ augmentStaleSnapshot?: boolean;
150
186
  /** When provider-owned, daemon treats provider parser output as canonical transcript authority. */
151
187
  transcriptAuthority?: 'provider' | 'daemon';
152
188
  /** Full context lets provider-owned parsers canonicalize retained history instead of daemon prefix stitching. */
153
189
  transcriptContext?: 'full' | 'tail';
190
+ /** v1 declarative tui block — used by CliScriptRunner to synthesize SDK helpers (declarativeDetectStatus, declarativeParseApproval). */
191
+ tui?: Record<string, unknown>;
154
192
  scripts?: CliScripts;
155
193
  spawn: {
156
194
  command: string;
@@ -342,7 +380,18 @@ export class TerminalTranscriptAccumulator {
342
380
  this.ensureRow();
343
381
  if (final === 'A') this.row = Math.max(0, this.row - count);
344
382
  else if (final === 'B') this.row += count;
345
- else if (final === 'C') this.col += count;
383
+ else if (final === 'C') {
384
+ // (fix) Cursor-forward must materialize spaces in the cells it
385
+ // skips, otherwise rendered transcripts collapse "Do you" written
386
+ // as "Do\x1b[1Cyou" into "Doyou". That mis-rendering broke
387
+ // Claude Code's approval-prompt and prompt-line detection
388
+ // (parseApproval saw "Doyouwanttoproceed?" and returned null).
389
+ const line = this.lines[this.row];
390
+ for (let c = this.col; c < this.col + count; c += 1) {
391
+ if (line[c] === undefined) line[c] = ' ';
392
+ }
393
+ this.col += count;
394
+ }
346
395
  else if (final === 'D') this.col = Math.max(0, this.col - count);
347
396
  else if (final === 'G') this.col = Math.max(0, count - 1);
348
397
  else if (final === 'H' || final === 'f') {
@@ -484,17 +533,25 @@ export function findBinary(name: string): string {
484
533
  return path.isAbsolute(expanded) ? expanded : path.resolve(expanded);
485
534
  }
486
535
  const isWin = os.platform() === 'win32';
487
- try {
488
- const cmd = isWin ? `where ${trimmed}` : `which ${trimmed}`;
489
- return execSync(cmd, {
490
- encoding: 'utf-8',
491
- timeout: 5000,
492
- stdio: ['pipe', 'pipe', 'pipe'],
493
- ...(isWin ? { windowsHide: true } : {}),
494
- }).trim().split('\n')[0].trim();
495
- } catch {
496
- return isWin ? `${trimmed}.cmd` : trimmed;
536
+ const paths = (process.env.PATH || '').split(path.delimiter);
537
+ const exes = isWin ? ['.exe', '.cmd', '.bat', ''] : [''];
538
+
539
+ for (const p of paths) {
540
+ if (!p) continue;
541
+ for (const ext of exes) {
542
+ const fullPath = path.join(p, trimmed + ext);
543
+ try {
544
+ const fs = require('fs');
545
+ if (fs.existsSync(fullPath)) {
546
+ const stat = fs.statSync(fullPath);
547
+ if (stat.isFile() && (isWin || (stat.mode & 0o111))) {
548
+ return fullPath;
549
+ }
550
+ }
551
+ } catch { }
552
+ }
497
553
  }
554
+ return isWin ? `${trimmed}.cmd` : trimmed;
498
555
  }
499
556
 
500
557
  export function isScriptBinary(binaryPath: string): boolean {
@@ -0,0 +1,252 @@
1
+ import { randomUUID } from 'crypto';
2
+ import {
3
+ SessionHostClient,
4
+ type SessionHostEndpoint,
5
+ type SessionHostRequest,
6
+ type SessionHostResponse,
7
+ type SessionTerminalSnapshot,
8
+ type SessionTerminalState,
9
+ } from '@adhdev/session-host-core';
10
+
11
+ type LowercaseLetter =
12
+ | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm'
13
+ | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z';
14
+
15
+ type FunctionKey = 'f1' | 'f2' | 'f3' | 'f4' | 'f5' | 'f6' | 'f7' | 'f8' | 'f9' | 'f10' | 'f11' | 'f12';
16
+ type BaseNamedKey =
17
+ | 'enter' | 'escape' | 'tab' | 'backspace'
18
+ | 'up' | 'down' | 'left' | 'right'
19
+ | 'home' | 'end' | 'pageup' | 'pagedown' | 'space'
20
+ | FunctionKey;
21
+ type ShiftNamedKey = BaseNamedKey | LowercaseLetter | `ctrl+${LowercaseLetter}` | `alt+${LowercaseLetter}`;
22
+
23
+ export type NamedKey =
24
+ | BaseNamedKey
25
+ | `ctrl+${LowercaseLetter}`
26
+ | `alt+${LowercaseLetter}`
27
+ | `shift+${ShiftNamedKey}`;
28
+
29
+ const BASE_KEY_SEQUENCES: Record<BaseNamedKey, string> = {
30
+ enter: '\r',
31
+ escape: '\x1b',
32
+ tab: '\t',
33
+ backspace: '\x7f',
34
+ up: '\x1b[A',
35
+ down: '\x1b[B',
36
+ right: '\x1b[C',
37
+ left: '\x1b[D',
38
+ home: '\x1b[H',
39
+ end: '\x1b[F',
40
+ pageup: '\x1b[5~',
41
+ pagedown: '\x1b[6~',
42
+ space: ' ',
43
+ f1: '\x1bOP',
44
+ f2: '\x1bOQ',
45
+ f3: '\x1bOR',
46
+ f4: '\x1bOS',
47
+ f5: '\x1b[15~',
48
+ f6: '\x1b[17~',
49
+ f7: '\x1b[18~',
50
+ f8: '\x1b[19~',
51
+ f9: '\x1b[20~',
52
+ f10: '\x1b[21~',
53
+ f11: '\x1b[23~',
54
+ f12: '\x1b[24~',
55
+ };
56
+
57
+ const SHIFTED_CSI_KEYS: Partial<Record<BaseNamedKey, string>> = {
58
+ up: '\x1b[1;2A',
59
+ down: '\x1b[1;2B',
60
+ right: '\x1b[1;2C',
61
+ left: '\x1b[1;2D',
62
+ home: '\x1b[1;2H',
63
+ end: '\x1b[1;2F',
64
+ pageup: '\x1b[5;2~',
65
+ pagedown: '\x1b[6;2~',
66
+ f1: '\x1b[1;2P',
67
+ f2: '\x1b[1;2Q',
68
+ f3: '\x1b[1;2R',
69
+ f4: '\x1b[1;2S',
70
+ f5: '\x1b[15;2~',
71
+ f6: '\x1b[17;2~',
72
+ f7: '\x1b[18;2~',
73
+ f8: '\x1b[19;2~',
74
+ f9: '\x1b[20;2~',
75
+ f10: '\x1b[21;2~',
76
+ f11: '\x1b[23;2~',
77
+ f12: '\x1b[24;2~',
78
+ };
79
+
80
+ function isLowercaseLetter(value: string): value is LowercaseLetter {
81
+ return /^[a-z]$/.test(value);
82
+ }
83
+
84
+ function encodeControlLetter(letter: LowercaseLetter): string {
85
+ return String.fromCharCode(letter.charCodeAt(0) - 96);
86
+ }
87
+
88
+ function encodeShiftedKey(key: string): string {
89
+ if (isLowercaseLetter(key)) return key.toUpperCase();
90
+ if (key.startsWith('ctrl+') && isLowercaseLetter(key.slice(5))) {
91
+ return encodeControlLetter(key.slice(5) as LowercaseLetter);
92
+ }
93
+ if (key.startsWith('alt+') && isLowercaseLetter(key.slice(4))) {
94
+ return `\x1b${key.slice(4).toUpperCase()}`;
95
+ }
96
+ if (key === 'tab') return '\x1b[Z';
97
+ if (key in SHIFTED_CSI_KEYS) return SHIFTED_CSI_KEYS[key as BaseNamedKey]!;
98
+ if (key in BASE_KEY_SEQUENCES) return BASE_KEY_SEQUENCES[key as BaseNamedKey];
99
+ throw new Error(`Unsupported named key: shift+${key}`);
100
+ }
101
+
102
+ export function namedKeyToAnsi(key: NamedKey | string): string {
103
+ const normalized = String(key || '').trim().toLowerCase();
104
+ if (normalized in BASE_KEY_SEQUENCES) return BASE_KEY_SEQUENCES[normalized as BaseNamedKey];
105
+ if (normalized.startsWith('ctrl+') && isLowercaseLetter(normalized.slice(5))) {
106
+ return encodeControlLetter(normalized.slice(5) as LowercaseLetter);
107
+ }
108
+ if (normalized.startsWith('alt+') && isLowercaseLetter(normalized.slice(4))) {
109
+ return `\x1b${normalized.slice(4)}`;
110
+ }
111
+ if (normalized.startsWith('shift+')) return encodeShiftedKey(normalized.slice(6));
112
+ throw new Error(`Unsupported named key: ${key}`);
113
+ }
114
+
115
+ export function namedKeysToAnsi(keys: readonly (NamedKey | string)[]): string {
116
+ if (!Array.isArray(keys)) throw new Error('keys must be an array');
117
+ return keys.map(namedKeyToAnsi).join('');
118
+ }
119
+
120
+ export interface RawTerminalSessionHostClient {
121
+ connect(): Promise<void>;
122
+ request<T = unknown>(request: SessionHostRequest): Promise<SessionHostResponse<T>>;
123
+ close(): Promise<void>;
124
+ }
125
+
126
+ export interface RawTerminalAttachmentOptions {
127
+ endpoint?: SessionHostEndpoint;
128
+ sessionId: string;
129
+ mode?: 'read' | 'write';
130
+ clientId?: string;
131
+ client?: RawTerminalSessionHostClient;
132
+ }
133
+
134
+ export class RawTerminalAttachment {
135
+ private closed = false;
136
+
137
+ private constructor(
138
+ readonly sessionId: string,
139
+ private readonly clientId: string,
140
+ private readonly mode: 'read' | 'write',
141
+ private readonly client: RawTerminalSessionHostClient,
142
+ ) {}
143
+
144
+ static async attach(options: RawTerminalAttachmentOptions): Promise<RawTerminalAttachment> {
145
+ const sessionId = String(options.sessionId || '').trim();
146
+ if (!sessionId) throw new Error('sessionId is required');
147
+ const mode = options.mode || 'read';
148
+ const clientId = options.clientId || `raw-terminal-${process.pid}-${randomUUID().slice(0, 8)}`;
149
+ const client = options.client || new SessionHostClient({ endpoint: options.endpoint });
150
+ await client.connect();
151
+
152
+ const attachResponse = await client.request({
153
+ type: 'attach_session',
154
+ payload: {
155
+ sessionId,
156
+ clientId,
157
+ clientType: 'web',
158
+ readOnly: mode === 'read',
159
+ },
160
+ });
161
+ if (!attachResponse.success) {
162
+ await client.close().catch(() => {});
163
+ throw new Error(attachResponse.error || `Failed to attach terminal session ${sessionId}`);
164
+ }
165
+
166
+ if (mode === 'write') {
167
+ const ownerResponse = await client.request({
168
+ type: 'acquire_write',
169
+ payload: {
170
+ sessionId,
171
+ clientId,
172
+ ownerType: 'user',
173
+ force: true,
174
+ },
175
+ });
176
+ if (!ownerResponse.success) {
177
+ await client.request({
178
+ type: 'detach_session',
179
+ payload: { sessionId, clientId },
180
+ }).catch(() => ({ success: false }));
181
+ await client.close().catch(() => {});
182
+ throw new Error(ownerResponse.error || `Failed to acquire terminal session ${sessionId}`);
183
+ }
184
+ }
185
+
186
+ return new RawTerminalAttachment(sessionId, clientId, mode, client);
187
+ }
188
+
189
+ async readSnapshot(): Promise<SessionTerminalSnapshot> {
190
+ const response = await this.client.request<SessionTerminalSnapshot>({
191
+ type: 'get_terminal_snapshot',
192
+ payload: { sessionId: this.sessionId },
193
+ });
194
+ if (!response.success || !response.result) {
195
+ throw new Error(response.error || `Terminal screen unavailable for ${this.sessionId}`);
196
+ }
197
+ return response.result;
198
+ }
199
+
200
+ async readScreenText(): Promise<string> {
201
+ return (await this.readSnapshot()).text;
202
+ }
203
+
204
+ async readState(): Promise<SessionTerminalState> {
205
+ return (await this.readSnapshot()).state;
206
+ }
207
+
208
+ async writeInput(text: string): Promise<void> {
209
+ if (this.mode !== 'write') throw new Error('Raw terminal attachment is read-only');
210
+ const response = await this.client.request({
211
+ type: 'send_input',
212
+ payload: {
213
+ sessionId: this.sessionId,
214
+ clientId: this.clientId,
215
+ data: text,
216
+ },
217
+ });
218
+ if (!response.success) throw new Error(response.error || `Failed to write terminal input to ${this.sessionId}`);
219
+ }
220
+
221
+ async writeKeys(keys: readonly (NamedKey | string)[]): Promise<void> {
222
+ await this.writeInput(namedKeysToAnsi(keys));
223
+ }
224
+
225
+ async close(): Promise<void> {
226
+ if (this.closed) return;
227
+ this.closed = true;
228
+ if (this.mode === 'write') {
229
+ await this.client.request({
230
+ type: 'release_write',
231
+ payload: { sessionId: this.sessionId, clientId: this.clientId },
232
+ }).catch(() => ({ success: false }));
233
+ }
234
+ await this.client.request({
235
+ type: 'detach_session',
236
+ payload: { sessionId: this.sessionId, clientId: this.clientId },
237
+ }).catch(() => ({ success: false }));
238
+ await this.client.close().catch(() => {});
239
+ }
240
+ }
241
+
242
+ export async function withRawTerminalAttachment<T>(
243
+ options: RawTerminalAttachmentOptions,
244
+ operation: (attachment: RawTerminalAttachment) => Promise<T>,
245
+ ): Promise<T> {
246
+ const attachment = await RawTerminalAttachment.attach(options);
247
+ try {
248
+ return await operation(attachment);
249
+ } finally {
250
+ await attachment.close();
251
+ }
252
+ }
@@ -1,7 +1,6 @@
1
1
  import type {
2
2
  TerminalViewportBackend,
3
3
  TerminalViewportBackendOptions,
4
- TerminalViewportBackendPreference,
5
4
  } from './types.js';
6
5
 
7
6
  type GhosttyVtTerminal = {
@@ -49,12 +48,10 @@ function getBindingCandidates(): string[] {
49
48
  return explicit ? [explicit] : DEFAULT_BINDING_CANDIDATES;
50
49
  }
51
50
 
52
- function loadGhosttyVtBinding(required: boolean): GhosttyVtBinding | null {
51
+ function loadGhosttyVtBinding(): GhosttyVtBinding {
53
52
  if (cachedBinding !== undefined) {
54
- if (!cachedBinding && required && cachedBindingError) {
55
- throw cachedBindingError;
56
- }
57
- return cachedBinding;
53
+ if (!cachedBinding && cachedBindingError) throw cachedBindingError;
54
+ return cachedBinding!;
58
55
  }
59
56
 
60
57
  const errors: string[] = [];
@@ -65,7 +62,7 @@ function loadGhosttyVtBinding(required: boolean): GhosttyVtBinding | null {
65
62
  const mod = require(ref);
66
63
  cachedBinding = normalizeBinding(mod, ref);
67
64
  cachedBindingError = null;
68
- return cachedBinding;
65
+ return cachedBinding!;
69
66
  } catch (error) {
70
67
  if (isModuleNotFoundError(error, ref)) {
71
68
  errors.push(`${ref}: module not found`);
@@ -78,57 +75,84 @@ function loadGhosttyVtBinding(required: boolean): GhosttyVtBinding | null {
78
75
 
79
76
  cachedBinding = null;
80
77
  cachedBindingError = new Error(
81
- `ghostty-vt backend requested but no binding is available (${errors.join('; ') || 'no candidates tried'})`,
78
+ `ghostty-vt binding unavailable (${errors.join('; ') || 'no candidates tried'})`,
82
79
  );
83
-
84
- if (required) throw cachedBindingError;
85
- return null;
86
- }
87
-
88
- export function resolveTerminalBackendPreference(): TerminalViewportBackendPreference {
89
- const raw = process.env.ADHDEV_TERMINAL_BACKEND?.trim().toLowerCase();
90
- if (raw === 'ghostty-vt' || raw === 'xterm' || raw === 'auto') return raw;
91
- return 'auto';
92
- }
93
-
94
- export function isGhosttyVtBackendAvailable(): boolean {
95
- return !!loadGhosttyVtBinding(false);
80
+ throw cachedBindingError;
96
81
  }
97
82
 
98
83
  export class GhosttyVtTerminalBackend implements TerminalViewportBackend {
99
84
  readonly kind = 'ghostty-vt' as const;
100
85
  private terminal: GhosttyVtTerminal;
86
+ private rows: number;
87
+ private disposed = false;
101
88
 
102
89
  constructor(options: TerminalViewportBackendOptions) {
103
- const binding = loadGhosttyVtBinding(true);
104
- if (!binding) {
105
- throw new Error('ghostty-vt backend requested but no binding is available');
106
- }
90
+ const binding = loadGhosttyVtBinding();
91
+ this.rows = Math.max(1, options.rows | 0);
107
92
  this.terminal = binding.createTerminal({
108
93
  cols: Math.max(1, options.cols | 0),
109
- rows: Math.max(1, options.rows | 0),
94
+ rows: this.rows,
110
95
  scrollback: Math.max(0, options.scrollback | 0),
111
96
  });
112
97
  }
113
98
 
114
99
  resize(rows: number, cols: number): void {
115
- this.terminal.resize(Math.max(1, cols | 0), Math.max(1, rows | 0));
100
+ this.rows = Math.max(1, rows | 0);
101
+ this.terminal.resize(Math.max(1, cols | 0), this.rows);
116
102
  }
117
103
 
118
104
  write(data: string): void {
119
- if (!data) return;
105
+ if (!data || this.disposed) return;
120
106
  this.terminal.write(data);
121
107
  }
122
108
 
109
+ private formatLines(): string[] {
110
+ // ghostty's `trim:true` collapses CUF-advanced cells — many TUIs including
111
+ // Claude Code render spaces via cursor-forward rather than literal spaces,
112
+ // which would break downstream regex matching. Keep per-row padding and
113
+ // trim trailing whitespace ourselves.
114
+ //
115
+ // formatPlainText uses a .screen pin which includes scrollback history.
116
+ const raw = this.terminal.formatPlainText({ trim: false }) || '';
117
+ if (!raw) return [];
118
+ return raw.split('\n').map((row) => row.replace(/\s+$/, ''));
119
+ }
120
+
121
+ private static trimBlankEnds(lines: string[]): string {
122
+ let first = 0;
123
+ let last = lines.length;
124
+ while (first < last && !lines[first]) first += 1;
125
+ while (last > first && !lines[last - 1]) last -= 1;
126
+ return lines.slice(first, last).join('\n');
127
+ }
128
+
123
129
  getText(): string {
124
- return this.terminal.formatPlainText({ trim: true }) || '';
130
+ if (this.disposed) return '';
131
+ const lines = this.formatLines();
132
+ if (lines.length === 0) return '';
133
+ // Take only the viewport (last `rows` lines) to exclude scrollback history.
134
+ const viewport = lines.length > this.rows ? lines.slice(-this.rows) : lines;
135
+ return GhosttyVtTerminalBackend.trimBlankEnds(viewport);
136
+ }
137
+
138
+ getTextWithScrollback(): string {
139
+ if (this.disposed) return '';
140
+ const lines = this.formatLines();
141
+ if (lines.length === 0) return '';
142
+ // Full buffer including scrollback — does NOT slice to the viewport, so a
143
+ // tall prompt whose top has scrolled above the visible rows is still
144
+ // matchable by content patterns.
145
+ return GhosttyVtTerminalBackend.trimBlankEnds(lines);
125
146
  }
126
147
 
127
148
  getCursorPosition(): { col: number; row: number } {
149
+ if (this.disposed) return { col: 0, row: 0 };
128
150
  return this.terminal.getCursorPosition();
129
151
  }
130
152
 
131
153
  dispose(): void {
154
+ if (this.disposed) return;
155
+ this.disposed = true;
132
156
  this.terminal.dispose();
133
157
  }
134
158
  }
@@ -1,6 +1,4 @@
1
- export type TerminalViewportBackendKind = 'xterm' | 'ghostty-vt';
2
-
3
- export type TerminalViewportBackendPreference = TerminalViewportBackendKind | 'auto';
1
+ export type TerminalViewportBackendKind = 'ghostty-vt';
4
2
 
5
3
  export type TerminalViewportBackendOptions = {
6
4
  rows: number;
@@ -13,6 +11,15 @@ export interface TerminalViewportBackend {
13
11
  resize(rows: number, cols: number): void;
14
12
  write(data: string): void;
15
13
  getText(): string;
14
+ /**
15
+ * Like getText() but includes scrollback history (the lines that have
16
+ * scrolled above the visible viewport). Used by content-pattern matching
17
+ * (e.g. approval/modal button extraction) that must stay correct when a
18
+ * tall prompt — a big diff or long explanation — pushes part of the
19
+ * prompt box above the viewport. NOT for cursor-relative / stable_ms
20
+ * conditions, whose row indices are viewport-relative.
21
+ */
22
+ getTextWithScrollback(): string;
16
23
  getCursorPosition(): { col: number; row: number };
17
24
  dispose(): void;
18
25
  }