@agi-fans/dsh-tui 0.20.0 → 0.22.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 (319) hide show
  1. package/lib/CHANGELOG.md +249 -3
  2. package/lib/chrome/box.d.ts +47 -16
  3. package/lib/chrome/box.js +172 -130
  4. package/lib/chrome/box.js.map +1 -1
  5. package/lib/chrome/code-highlight.d.ts +15 -0
  6. package/lib/chrome/code-highlight.js +60 -4
  7. package/lib/chrome/code-highlight.js.map +1 -1
  8. package/lib/chrome/command-output.d.ts +29 -2
  9. package/lib/chrome/command-output.js +100 -4
  10. package/lib/chrome/command-output.js.map +1 -1
  11. package/lib/chrome/main-screen-renderer.d.ts +18 -0
  12. package/lib/chrome/main-screen-renderer.js +58 -5
  13. package/lib/chrome/main-screen-renderer.js.map +1 -1
  14. package/lib/chrome/markdown.js +30 -10
  15. package/lib/chrome/markdown.js.map +1 -1
  16. package/lib/chrome/relative-time.d.ts +17 -0
  17. package/lib/chrome/relative-time.js +36 -0
  18. package/lib/chrome/relative-time.js.map +1 -1
  19. package/lib/chrome/renderer.d.ts +9 -0
  20. package/lib/chrome/renderer.js +1 -1
  21. package/lib/chrome/renderer.js.map +1 -1
  22. package/lib/chrome/secret-mask.d.ts +35 -0
  23. package/lib/chrome/secret-mask.js +180 -0
  24. package/lib/chrome/secret-mask.js.map +1 -0
  25. package/lib/chrome/status-config.d.ts +161 -51
  26. package/lib/chrome/status-config.js +237 -126
  27. package/lib/chrome/status-config.js.map +1 -1
  28. package/lib/chrome/status-line.d.ts +3 -2
  29. package/lib/chrome/status-line.js +105 -63
  30. package/lib/chrome/status-line.js.map +1 -1
  31. package/lib/chrome/terminal-colors.d.ts +85 -0
  32. package/lib/chrome/terminal-colors.js +230 -0
  33. package/lib/chrome/terminal-colors.js.map +1 -0
  34. package/lib/chrome/terminal-images.d.ts +9 -1
  35. package/lib/chrome/terminal-images.js +27 -4
  36. package/lib/chrome/terminal-images.js.map +1 -1
  37. package/lib/chrome/theme.d.ts +32 -9
  38. package/lib/chrome/theme.js +616 -520
  39. package/lib/chrome/theme.js.map +1 -1
  40. package/lib/chrome/tool-args.d.ts +1 -1
  41. package/lib/chrome/tool-args.js +3 -1
  42. package/lib/chrome/tool-args.js.map +1 -1
  43. package/lib/chrome/tool-renderers.d.ts +2 -0
  44. package/lib/chrome/tool-renderers.js +69 -3
  45. package/lib/chrome/tool-renderers.js.map +1 -1
  46. package/lib/chrome/tools-list.d.ts +1 -4
  47. package/lib/chrome/tools-list.js +1 -41
  48. package/lib/chrome/tools-list.js.map +1 -1
  49. package/lib/chrome/welcome-tips.d.ts +20 -7
  50. package/lib/chrome/welcome-tips.js +22 -41
  51. package/lib/chrome/welcome-tips.js.map +1 -1
  52. package/lib/commands/auth-ids.d.ts +25 -0
  53. package/lib/commands/auth-ids.js +27 -0
  54. package/lib/commands/auth-ids.js.map +1 -0
  55. package/lib/commands/auth-input.d.ts +34 -0
  56. package/lib/commands/auth-input.js +96 -0
  57. package/lib/commands/auth-input.js.map +1 -0
  58. package/lib/commands/auth-providers.d.ts +39 -0
  59. package/lib/commands/auth-providers.js +125 -0
  60. package/lib/commands/auth-providers.js.map +1 -0
  61. package/lib/commands/auth.d.ts +16 -22
  62. package/lib/commands/auth.js +346 -299
  63. package/lib/commands/auth.js.map +1 -1
  64. package/lib/commands/btw.d.ts +27 -0
  65. package/lib/commands/btw.js +59 -0
  66. package/lib/commands/btw.js.map +1 -0
  67. package/lib/commands/diff.js +30 -5
  68. package/lib/commands/diff.js.map +1 -1
  69. package/lib/commands/export.d.ts +1 -1
  70. package/lib/commands/export.js +5 -3
  71. package/lib/commands/export.js.map +1 -1
  72. package/lib/commands/files.d.ts +17 -1
  73. package/lib/commands/files.js +69 -61
  74. package/lib/commands/files.js.map +1 -1
  75. package/lib/commands/integrations.js +18 -6
  76. package/lib/commands/integrations.js.map +1 -1
  77. package/lib/commands/jobs.d.ts +19 -4
  78. package/lib/commands/jobs.js +50 -7
  79. package/lib/commands/jobs.js.map +1 -1
  80. package/lib/commands/model.js +109 -76
  81. package/lib/commands/model.js.map +1 -1
  82. package/lib/commands/permission.js +46 -13
  83. package/lib/commands/permission.js.map +1 -1
  84. package/lib/commands/plugins.js +196 -42
  85. package/lib/commands/plugins.js.map +1 -1
  86. package/lib/commands/schedule.d.ts +29 -0
  87. package/lib/commands/schedule.js +228 -0
  88. package/lib/commands/schedule.js.map +1 -0
  89. package/lib/commands/session-configuration.d.ts +1 -1
  90. package/lib/commands/session-configuration.js +29 -28
  91. package/lib/commands/session-configuration.js.map +1 -1
  92. package/lib/commands/session.js +75 -80
  93. package/lib/commands/session.js.map +1 -1
  94. package/lib/commands/terminal.d.ts +24 -4
  95. package/lib/commands/terminal.js +38 -94
  96. package/lib/commands/terminal.js.map +1 -1
  97. package/lib/commands/trajectory.js +4 -1
  98. package/lib/commands/trajectory.js.map +1 -1
  99. package/lib/definition.d.ts +150 -11
  100. package/lib/index.d.ts +1 -0
  101. package/lib/index.js +1 -0
  102. package/lib/index.js.map +1 -1
  103. package/lib/input/actions.d.ts +51 -0
  104. package/lib/input/actions.js +120 -0
  105. package/lib/input/actions.js.map +1 -0
  106. package/lib/input/editor-discovery.js +2 -2
  107. package/lib/input/editor-discovery.js.map +1 -1
  108. package/lib/input/editor.d.ts +0 -10
  109. package/lib/input/editor.js +11 -9
  110. package/lib/input/editor.js.map +1 -1
  111. package/lib/input/image-paste.d.ts +19 -1
  112. package/lib/input/image-paste.js +82 -1
  113. package/lib/input/image-paste.js.map +1 -1
  114. package/lib/input/keybindings-config.d.ts +15 -4
  115. package/lib/input/keybindings-config.js +57 -35
  116. package/lib/input/keybindings-config.js.map +1 -1
  117. package/lib/input/keys.d.ts +18 -0
  118. package/lib/input/keys.js +48 -3
  119. package/lib/input/keys.js.map +1 -1
  120. package/lib/input/wheel-scroll.d.ts +46 -0
  121. package/lib/input/wheel-scroll.js +69 -0
  122. package/lib/input/wheel-scroll.js.map +1 -0
  123. package/lib/prompt-intents.d.ts +182 -0
  124. package/lib/prompt-intents.js +127 -0
  125. package/lib/prompt-intents.js.map +1 -0
  126. package/lib/runtime/agent-profile.d.ts +5 -0
  127. package/lib/runtime/agent-profile.js +12 -0
  128. package/lib/runtime/agent-profile.js.map +1 -1
  129. package/lib/runtime/approval-rules.d.ts +59 -0
  130. package/lib/runtime/approval-rules.js +179 -0
  131. package/lib/runtime/approval-rules.js.map +1 -0
  132. package/lib/runtime/btw-policy.d.ts +7 -0
  133. package/lib/runtime/btw-policy.js +18 -0
  134. package/lib/runtime/btw-policy.js.map +1 -0
  135. package/lib/runtime/btw.d.ts +47 -0
  136. package/lib/runtime/btw.js +200 -0
  137. package/lib/runtime/btw.js.map +1 -0
  138. package/lib/runtime/cancellable.d.ts +75 -0
  139. package/lib/runtime/cancellable.js +76 -0
  140. package/lib/runtime/cancellable.js.map +1 -0
  141. package/lib/runtime/composer-images.js +5 -4
  142. package/lib/runtime/composer-images.js.map +1 -1
  143. package/lib/runtime/composer-shell.d.ts +30 -0
  144. package/lib/runtime/composer-shell.js +150 -0
  145. package/lib/runtime/composer-shell.js.map +1 -0
  146. package/lib/runtime/file-recovery-local.d.ts +73 -0
  147. package/lib/runtime/file-recovery-local.js +351 -0
  148. package/lib/runtime/file-recovery-local.js.map +1 -0
  149. package/lib/runtime/file-recovery-recording.d.ts +23 -0
  150. package/lib/runtime/file-recovery-recording.js +131 -0
  151. package/lib/runtime/file-recovery-recording.js.map +1 -0
  152. package/lib/runtime/file-recovery-review.d.ts +3 -0
  153. package/lib/runtime/file-recovery-review.js +130 -0
  154. package/lib/runtime/file-recovery-review.js.map +1 -0
  155. package/lib/runtime/file-recovery-store.d.ts +83 -0
  156. package/lib/runtime/file-recovery-store.js +329 -0
  157. package/lib/runtime/file-recovery-store.js.map +1 -0
  158. package/lib/runtime/file-recovery-worker.d.ts +22 -0
  159. package/lib/runtime/file-recovery-worker.js +153 -0
  160. package/lib/runtime/file-recovery-worker.js.map +1 -0
  161. package/lib/runtime/file-review.d.ts +6 -3
  162. package/lib/runtime/file-review.js +44 -7
  163. package/lib/runtime/file-review.js.map +1 -1
  164. package/lib/runtime/herdr-agent.d.ts +4 -13
  165. package/lib/runtime/herdr-agent.js +19 -63
  166. package/lib/runtime/herdr-agent.js.map +1 -1
  167. package/lib/runtime/plain-tui.d.ts +2 -0
  168. package/lib/runtime/plain-tui.js +7 -1
  169. package/lib/runtime/plain-tui.js.map +1 -1
  170. package/lib/runtime/plugin-settings.d.ts +25 -2
  171. package/lib/runtime/plugin-settings.js +329 -31
  172. package/lib/runtime/plugin-settings.js.map +1 -1
  173. package/lib/runtime/provider-local.d.ts +81 -24
  174. package/lib/runtime/provider-local.js +1807 -608
  175. package/lib/runtime/provider-local.js.map +1 -1
  176. package/lib/runtime/runner.js +52 -12
  177. package/lib/runtime/runner.js.map +1 -1
  178. package/lib/runtime/session-archive.d.ts +6 -0
  179. package/lib/runtime/session-archive.js +129 -3
  180. package/lib/runtime/session-archive.js.map +1 -1
  181. package/lib/runtime/session-runtime.js +1 -1
  182. package/lib/runtime/session-runtime.js.map +1 -1
  183. package/lib/runtime/settings-preferences.d.ts +5 -0
  184. package/lib/runtime/settings-preferences.js +34 -0
  185. package/lib/runtime/settings-preferences.js.map +1 -0
  186. package/lib/runtime/startup-notices.js +2 -0
  187. package/lib/runtime/startup-notices.js.map +1 -1
  188. package/lib/runtime/terminal-modes.d.ts +47 -0
  189. package/lib/runtime/terminal-modes.js +86 -0
  190. package/lib/runtime/terminal-modes.js.map +1 -0
  191. package/lib/runtime/terminal-notifications.d.ts +3 -5
  192. package/lib/runtime/terminal-notifications.js +4 -8
  193. package/lib/runtime/terminal-notifications.js.map +1 -1
  194. package/lib/runtime/terminal-probe.d.ts +36 -0
  195. package/lib/runtime/terminal-probe.js +37 -0
  196. package/lib/runtime/terminal-probe.js.map +1 -0
  197. package/lib/runtime/terminal-session.d.ts +57 -0
  198. package/lib/runtime/terminal-session.js +164 -0
  199. package/lib/runtime/terminal-session.js.map +1 -0
  200. package/lib/runtime/terminal-state.d.ts +29 -0
  201. package/lib/runtime/terminal-state.js +62 -0
  202. package/lib/runtime/terminal-state.js.map +1 -0
  203. package/lib/runtime/tool-presentation.js +50 -14
  204. package/lib/runtime/tool-presentation.js.map +1 -1
  205. package/lib/session/external-agents.d.ts +5 -0
  206. package/lib/session/external-agents.js +27 -0
  207. package/lib/session/external-agents.js.map +1 -0
  208. package/lib/session/feature-toggles.d.ts +1 -1
  209. package/lib/session/feature-toggles.js +1 -1
  210. package/lib/session/interaction-adapter.d.ts +1 -6
  211. package/lib/session/interaction-adapter.js +95 -18
  212. package/lib/session/interaction-adapter.js.map +1 -1
  213. package/lib/session/message-queue.js +1 -1
  214. package/lib/session/message-queue.js.map +1 -1
  215. package/lib/session/model-readiness.d.ts +16 -0
  216. package/lib/session/model-readiness.js +43 -0
  217. package/lib/session/model-readiness.js.map +1 -0
  218. package/lib/session/package-metadata.d.ts +8 -0
  219. package/lib/session/package-metadata.js +8 -0
  220. package/lib/session/package-metadata.js.map +1 -1
  221. package/lib/session/project-context.d.ts +5 -0
  222. package/lib/session/project-context.js +36 -0
  223. package/lib/session/project-context.js.map +1 -1
  224. package/lib/session/session-controller.d.ts +10 -13
  225. package/lib/session/session-controller.js +183 -98
  226. package/lib/session/session-controller.js.map +1 -1
  227. package/lib/session/session-library.js +2 -0
  228. package/lib/session/session-library.js.map +1 -1
  229. package/lib/session/session-tree.d.ts +3 -0
  230. package/lib/session/session-tree.js +3 -1
  231. package/lib/session/session-tree.js.map +1 -1
  232. package/lib/session/subagent-roster.d.ts +2 -1
  233. package/lib/session/subagent-roster.js +24 -3
  234. package/lib/session/subagent-roster.js.map +1 -1
  235. package/lib/session/subagent-tracker.d.ts +6 -2
  236. package/lib/session/subagent-tracker.js +49 -2
  237. package/lib/session/subagent-tracker.js.map +1 -1
  238. package/lib/session/tui-settings.d.ts +47 -13
  239. package/lib/session/tui-settings.js +76 -34
  240. package/lib/session/tui-settings.js.map +1 -1
  241. package/lib/session/working-directory.d.ts +4 -0
  242. package/lib/session/working-directory.js +4 -0
  243. package/lib/session/working-directory.js.map +1 -0
  244. package/lib/session/worktrees.d.ts +13 -0
  245. package/lib/session/worktrees.js +49 -0
  246. package/lib/session/worktrees.js.map +1 -0
  247. package/lib/views/approval-rule.d.ts +3 -0
  248. package/lib/views/approval-rule.js +4 -0
  249. package/lib/views/approval-rule.js.map +1 -0
  250. package/lib/views/at-complete.d.ts +8 -0
  251. package/lib/views/at-complete.js +64 -2
  252. package/lib/views/at-complete.js.map +1 -1
  253. package/lib/views/autocomplete.d.ts +22 -2
  254. package/lib/views/autocomplete.js +70 -40
  255. package/lib/views/autocomplete.js.map +1 -1
  256. package/lib/views/copy-targets.d.ts +13 -14
  257. package/lib/views/copy-targets.js +42 -54
  258. package/lib/views/copy-targets.js.map +1 -1
  259. package/lib/views/document-reader.js +18 -5
  260. package/lib/views/document-reader.js.map +1 -1
  261. package/lib/views/event-views.d.ts +1 -1
  262. package/lib/views/event-views.js +60 -6
  263. package/lib/views/event-views.js.map +1 -1
  264. package/lib/views/file-actions.d.ts +12 -0
  265. package/lib/views/file-actions.js +72 -0
  266. package/lib/views/file-actions.js.map +1 -0
  267. package/lib/views/history-search.js +15 -21
  268. package/lib/views/history-search.js.map +1 -1
  269. package/lib/views/hotkeys.d.ts +8 -1
  270. package/lib/views/hotkeys.js +53 -26
  271. package/lib/views/hotkeys.js.map +1 -1
  272. package/lib/views/list-navigation.d.ts +62 -0
  273. package/lib/views/list-navigation.js +73 -0
  274. package/lib/views/list-navigation.js.map +1 -0
  275. package/lib/views/list-view.d.ts +99 -0
  276. package/lib/views/list-view.js +165 -0
  277. package/lib/views/list-view.js.map +1 -0
  278. package/lib/views/prompt-selector.d.ts +34 -4
  279. package/lib/views/prompt-selector.js +270 -134
  280. package/lib/views/prompt-selector.js.map +1 -1
  281. package/lib/views/session-files.d.ts +1 -2
  282. package/lib/views/session-files.js +1 -11
  283. package/lib/views/session-files.js.map +1 -1
  284. package/lib/views/settings-list.d.ts +51 -10
  285. package/lib/views/settings-list.js +267 -315
  286. package/lib/views/settings-list.js.map +1 -1
  287. package/lib/views/trajectory-timeline.d.ts +72 -0
  288. package/lib/views/trajectory-timeline.js +133 -0
  289. package/lib/views/trajectory-timeline.js.map +1 -0
  290. package/lib/views/trajectory.d.ts +15 -4
  291. package/lib/views/trajectory.js +557 -123
  292. package/lib/views/trajectory.js.map +1 -1
  293. package/lib/views/transcript-export.js +9 -0
  294. package/lib/views/transcript-export.js.map +1 -1
  295. package/lib/views/transcript-render.d.ts +97 -25
  296. package/lib/views/transcript-render.js +542 -170
  297. package/lib/views/transcript-render.js.map +1 -1
  298. package/lib/views/transcript-search.d.ts +39 -6
  299. package/lib/views/transcript-search.js +46 -11
  300. package/lib/views/transcript-search.js.map +1 -1
  301. package/lib/views/transcript-types.d.ts +63 -5
  302. package/lib/views/transcript-types.js +23 -11
  303. package/lib/views/transcript-types.js.map +1 -1
  304. package/package.json +95 -65
  305. package/lib/commands/loop.d.ts +0 -52
  306. package/lib/commands/loop.js +0 -307
  307. package/lib/commands/loop.js.map +0 -1
  308. package/lib/commands/steer.d.ts +0 -5
  309. package/lib/commands/steer.js +0 -24
  310. package/lib/commands/steer.js.map +0 -1
  311. package/lib/runtime/terminal-reader.d.ts +0 -11
  312. package/lib/runtime/terminal-reader.js +0 -87
  313. package/lib/runtime/terminal-reader.js.map +0 -1
  314. package/lib/views/agent-hub.d.ts +0 -32
  315. package/lib/views/agent-hub.js +0 -206
  316. package/lib/views/agent-hub.js.map +0 -1
  317. package/lib/views/copy-selector.d.ts +0 -51
  318. package/lib/views/copy-selector.js +0 -139
  319. package/lib/views/copy-selector.js.map +0 -1
@@ -0,0 +1,200 @@
1
+ /** Durable side consultations over the public Harness Agent and fork seams. */
2
+ import { Service } from '@deepseek-ai/cordis';
3
+ import { randomUUID, createHash } from 'node:crypto';
4
+ import { mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from 'node:fs';
5
+ import { join } from 'node:path';
6
+ import { Session, SessionId, SessionLogOffset, buildForkSeed, SESSION_FORMAT_VERSION } from '@deepseek-ai/dsh-session';
7
+ import { createUserMessage } from '@deepseek-ai/dsh-llm';
8
+ import { deriveTurnTokenUsage } from '@deepseek-ai/dsh-token-meter/client';
9
+ import { configureAgentContext } from "./agent-profile.js";
10
+ import { BTW_PRESET } from "./btw-policy.js";
11
+ import { currentWorkingDirectory } from "../session/working-directory.js";
12
+ import { blocksText } from "../session/content-text.js";
13
+ import { readColdSessionLog } from '@deepseek-ai/dsh-session-query';
14
+ /** Preserve the exact source prefix, then select the child's independent world. */
15
+ export function btwSeed(parent, id, cwd) {
16
+ const prefix = parent.snapshotEvents();
17
+ const seed = prefix.length === 0 ? [] : buildForkSeed(prefix, prefix.at(-1).seq);
18
+ const snapshot = Session.create(id, seed, { id, version: SESSION_FORMAT_VERSION, createdAt: Date.now(), cwd,
19
+ parentSession: parent.id, isSeeded: true, agentPreset: BTW_PRESET }, SessionLogOffset(prefix.length));
20
+ snapshot.append('agent-preset/selected', { agentPreset: BTW_PRESET });
21
+ return snapshot.snapshotEvents();
22
+ }
23
+ function lastTurn(events) {
24
+ const at = events.findLastIndex(event => event.type === 'turn/start');
25
+ return at < 0 ? [] : events.slice(at);
26
+ }
27
+ export class BtwService extends Service {
28
+ static inject = ['agents', 'agentPresets', 'sessions', 'permissionPresets'];
29
+ ownerContext;
30
+ stateDir;
31
+ topics = new Map();
32
+ active = new Map();
33
+ tasks = new Set();
34
+ closing = new AbortController();
35
+ constructor(ctx, config = {}) {
36
+ super(ctx, 'omdshBtw');
37
+ this.ownerContext = ctx;
38
+ this.stateDir = config.stateDir;
39
+ if (this.stateDir !== undefined) {
40
+ let names;
41
+ try {
42
+ names = readdirSync(this.stateDir);
43
+ }
44
+ catch (error) {
45
+ if (error.code !== 'ENOENT')
46
+ throw error;
47
+ names = [];
48
+ }
49
+ for (const name of names.filter(name => name.endsWith('.json'))) {
50
+ const topic = JSON.parse(readFileSync(join(this.stateDir, name), 'utf8'));
51
+ if (!validTopic(topic))
52
+ throw new Error(`Invalid side consultation record: ${name}`);
53
+ this.topics.set(topic.sessionId, { ...topic, status: topic.status === 'running' ? 'cancelled' : topic.status });
54
+ }
55
+ }
56
+ ctx.on('agent/disposed', ({ agent }) => { this.active.get(agent)?.abort(new Error('The parent session was closed.')); });
57
+ ctx.effect(() => async () => { this.closing.abort(new Error('Side consultations unloaded.')); await Promise.allSettled(this.tasks); }, 'side consultation lifetime');
58
+ }
59
+ list(parent) {
60
+ return [...this.topics.values()].filter(topic => topic.parentSessionId === parent.id)
61
+ .sort((left, right) => right.updatedAt - left.updatedAt).map(topic => ({ ...topic }));
62
+ }
63
+ async read(parent, id, signal) {
64
+ const topic = this.topics.get(id);
65
+ if (topic?.parentSessionId !== parent.id)
66
+ throw new Error('That side consultation belongs to another session or is unavailable.');
67
+ const persistence = this.ownerContext.get('sessionPersistence');
68
+ if (persistence === undefined)
69
+ throw new Error('Session persistence is required to read a saved side consultation.');
70
+ const log = await readColdSessionLog(persistence, SessionId(id), signal);
71
+ if (log.header.parentSession !== parent.id || log.inheritedEventCount !== topic.prefixEvents)
72
+ throw new Error('The saved consultation no longer matches its parent snapshot.');
73
+ return log.events.slice(log.inheritedEventCount).flatMap(event => event.type === 'user/message' && event.data.source.kind === 'user'
74
+ ? ['### Question\n\n' + blocksText(event.data.content)]
75
+ : event.type === 'assistant/message' ? [blocksText(event.data.message.content)] : []).join('\n\n');
76
+ }
77
+ consult(parent, question, selection, signal, update, topicId) {
78
+ if (this.active.has(parent))
79
+ throw new Error('A side consultation is already running for this session.');
80
+ if (question.trim() === '')
81
+ throw new Error('Enter a side question.');
82
+ if (this.ownerContext.get('sessionPersistence') === undefined)
83
+ throw new Error('Session persistence is required for side consultations.');
84
+ const abort = new AbortController();
85
+ this.active.set(parent, abort);
86
+ const task = this.runQuestion(parent, question, selection, AbortSignal.any([signal, abort.signal, this.closing.signal]), update, topicId)
87
+ .finally(() => { this.active.delete(parent); this.tasks.delete(task); });
88
+ this.tasks.add(task);
89
+ return task;
90
+ }
91
+ async runQuestion(parent, question, selection, signal, update, topicId) {
92
+ const ctx = this.ownerContext;
93
+ const existing = topicId === undefined ? undefined : this.topics.get(topicId);
94
+ if (topicId !== undefined && existing?.parentSessionId !== parent.id)
95
+ throw new Error('That side consultation belongs to another session or is unavailable.');
96
+ const id = SessionId(existing?.sessionId ?? 'session-' + randomUUID());
97
+ const prefixEvents = existing?.prefixEvents ?? parent.session.snapshotEvents().length;
98
+ let topic = existing === undefined ? { version: 1, sessionId: id, parentSessionId: parent.id, prefixEvents,
99
+ question, createdAt: Date.now(), updatedAt: Date.now(), status: 'running' } : { ...existing, status: 'running', updatedAt: Date.now() };
100
+ let handle, text = '', attempt = '';
101
+ const ref = { current: { ...selection }, assembled: undefined };
102
+ const setup = async (agentCtx, agent) => {
103
+ const configured = await configureAgentContext(agentCtx, agent, ref);
104
+ if (configured.agentPreset !== BTW_PRESET)
105
+ throw new Error('The saved consultation no longer uses its tool-free composition.');
106
+ };
107
+ let offStream;
108
+ const cancel = () => { handle?.agent.cancel({ kind: 'user' }); };
109
+ signal.addEventListener('abort', cancel, { once: true });
110
+ try {
111
+ signal.throwIfAborted();
112
+ if (existing === undefined) {
113
+ const cwd = currentWorkingDirectory(ctx, parent.session);
114
+ const seed = btwSeed(parent.session, id, cwd);
115
+ handle = await ctx.get('agents').create({ sessionId: id, seed, inheritedEventCount: SessionLogOffset(prefixEvents),
116
+ meta: { cwd, parentSession: parent.id, isSeeded: true, agentPreset: BTW_PRESET }, agentOptions: { ...selection, maxTokens: 8192 }, signal, setup });
117
+ }
118
+ else {
119
+ const stored = await ctx.get('sessionPersistence').stat(id, { signal });
120
+ if (stored === undefined || stored.header.parentSession !== parent.id)
121
+ throw new Error('The saved consultation no longer matches its parent session.');
122
+ if (stored.formatStatus === 'migration-required')
123
+ throw new Error('This consultation requires session-format migration before it can continue.');
124
+ handle = await ctx.get('agents').resume({ resumeSessionId: id, agentOptions: { ...selection, maxTokens: 8192 }, signal, setup });
125
+ }
126
+ const agent = handle.agent;
127
+ signal.throwIfAborted();
128
+ ctx.get('goals')?.disarm(agent);
129
+ const goal = ctx.get('goals')?.get(agent);
130
+ if (goal !== undefined)
131
+ ctx.get('goals').clear(agent, goal);
132
+ ctx.get('planMode')?.set(agent, false);
133
+ ctx.get('permissionPresets').set(agent.session, 'read-only');
134
+ if (existing === undefined)
135
+ ctx.get('sessionTitles')?.rename(agent.session, 'Side question: ' + question);
136
+ this.saveTopic(topic);
137
+ offStream = agent.ctx.on('agent/assistant-stream', ({ frame }) => {
138
+ if (frame.type === 'start') {
139
+ attempt = '';
140
+ update('');
141
+ }
142
+ if (frame.type === 'chunk' && frame.chunk.type === 'text-delta') {
143
+ attempt += frame.chunk.text;
144
+ update(attempt);
145
+ }
146
+ });
147
+ agent.followup(createUserMessage({ content: [{ type: 'text', text: question }], source: { kind: 'user' } }));
148
+ await agent.whenIdle();
149
+ const events = lastTurn(agent.session.ownEvents());
150
+ const message = events.findLast(event => event.type === 'assistant/message');
151
+ text = message?.type === 'assistant/message' ? blocksText(message.data.message.content) : attempt;
152
+ update(text);
153
+ const end = events.findLast(event => event.type === 'turn/end');
154
+ const reason = end?.type === 'turn/end' ? end.data.reason : undefined;
155
+ const error = reason?.kind === 'error' ? reason.error.message : reason?.kind === 'completed' || signal.aborted ? undefined : `Side question ended without completion (${reason?.kind ?? 'no turn'}).`;
156
+ topic = { ...topic, updatedAt: Date.now(), status: signal.aborted ? 'cancelled' : reason?.kind === 'completed' ? 'completed' : 'failed' };
157
+ await ctx.get('sessions').flush(agent.session);
158
+ this.saveTopic(topic);
159
+ const usage = deriveTurnTokenUsage(events);
160
+ return { topic, text, ...(usage === undefined ? {} : { usage }), ...(error === undefined ? {} : { error }) };
161
+ }
162
+ catch (error) {
163
+ topic = { ...topic, updatedAt: Date.now(), status: signal.aborted ? 'cancelled' : 'failed' };
164
+ if (handle !== undefined)
165
+ this.saveTopic(topic);
166
+ return { topic, text: text || attempt, ...(signal.aborted ? {} : { error: error instanceof Error ? error.message : String(error) }) };
167
+ }
168
+ finally {
169
+ signal.removeEventListener('abort', cancel);
170
+ offStream?.();
171
+ await handle?.dispose();
172
+ }
173
+ }
174
+ saveTopic(topic) {
175
+ if (this.stateDir !== undefined) {
176
+ mkdirSync(this.stateDir, { recursive: true });
177
+ const path = join(this.stateDir, createHash('sha256').update(topic.sessionId).digest('hex') + '.json');
178
+ const temp = path + '.' + randomUUID() + '.tmp';
179
+ try {
180
+ writeFileSync(temp, JSON.stringify(topic) + '\n', { mode: 0o600 });
181
+ renameSync(temp, path);
182
+ }
183
+ finally {
184
+ rmSync(temp, { force: true });
185
+ }
186
+ }
187
+ this.topics.set(topic.sessionId, topic);
188
+ }
189
+ }
190
+ function validTopic(value) {
191
+ if (value === null || typeof value !== 'object')
192
+ return false;
193
+ const item = value;
194
+ return item.version === 1 && typeof item.sessionId === 'string' && typeof item.parentSessionId === 'string'
195
+ && typeof item.question === 'string' && Number.isSafeInteger(item.prefixEvents) && item.prefixEvents >= 0
196
+ && Number.isSafeInteger(item.createdAt) && Number.isSafeInteger(item.updatedAt)
197
+ && ['running', 'completed', 'cancelled', 'failed'].includes(String(item.status));
198
+ }
199
+ export default BtwService;
200
+ //# sourceMappingURL=btw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"btw.js","sourceRoot":"","sources":["../../src/runtime/btw.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * One cancellable long operation with its own progress surface.
3
+ *
4
+ * A long command needs three things wired together, and every call site used to
5
+ * write the same wiring by hand:
6
+ *
7
+ * 1. a signal that combines the caller's own cancellation with the reader's;
8
+ * 2. a prompt that gives the reader a way to cancel — Enter, Escape, `Ctrl+C`;
9
+ * 3. a "finished" signal so that dismissing the prompt because the *work* ended
10
+ * is not mistaken for the reader cancelling the work.
11
+ *
12
+ * The third point is where hand-written copies went wrong: the prompt's promise
13
+ * settles both when the reader cancels and when the operation completes, so a
14
+ * naive `.then(() => controller.abort())` aborted the operation on its own
15
+ * success. Each site had to guard it with a second `finished` controller, and
16
+ * each site wrote that guard differently.
17
+ *
18
+ * `run()` owns the whole lifecycle: the body receives the combined signal, and
19
+ * the prompt is dismissed when the body settles either way.
20
+ *
21
+ * @module @agi-fans/dsh-tui/cancellable
22
+ */
23
+ import type { TuiService } from '../definition.ts';
24
+ /** One progress surface the reader can cancel from. */
25
+ export interface CancellableProgress {
26
+ /** Title of the surface, such as `Creating worktree`. */
27
+ title: string;
28
+ /** The subject line: what is being done, in one row. */
29
+ question: string;
30
+ /** What cancelling does and does not undo. Shown under the subject. */
31
+ detail?: string;
32
+ /** Label of the cancel option. */
33
+ cancelLabel?: string;
34
+ /**
35
+ * Progress card, or a reading surface that updates while the work streams.
36
+ *
37
+ * A streaming operation (a side question's answer) needs a document the reader
38
+ * can watch and scroll; a file restore only needs to say what is happening. The
39
+ * lifecycle is identical, so both are one option rather than two helpers.
40
+ */
41
+ presentation?: 'progress' | 'document';
42
+ /** Repaint the open document; read on each refresh. */
43
+ document?: () => string;
44
+ /**
45
+ * Whether to open the surface at all.
46
+ *
47
+ * The caller decides, because the three operations disagreed: a worktree and a
48
+ * side question are interactive-only, while a file restore reports progress even
49
+ * when the caller did not claim an interactive screen. Inferring this from
50
+ * `tui.interactive` silently dropped the restore's progress surface.
51
+ */
52
+ surface: boolean;
53
+ }
54
+ /**
55
+ * Why a cancellable operation stopped early.
56
+ *
57
+ * The two are not the same event: a reader who presses cancel is watching, and
58
+ * knows the work stopped, while a superseded surface means the screen was taken
59
+ * by something else and the reader never saw the result. Callers that report a
60
+ * partial outcome treat them differently.
61
+ */
62
+ export type CancellationReason = 'cancelled' | 'superseded';
63
+ /**
64
+ * Run one long operation behind a cancel surface.
65
+ *
66
+ * Returns `undefined` when the operation never started because the caller was
67
+ * already aborted, so callers can skip their success path without checking.
68
+ *
69
+ * A non-interactive host runs the body without a surface: there is no reader to
70
+ * cancel it, and opening a prompt would claim a screen the pipe does not have.
71
+ */
72
+ export declare function cancellable<T>(tui: Pick<TuiService, 'interactive' | 'prompt'>, progress: CancellableProgress, parent: AbortSignal, run: (signal: AbortSignal) => Promise<T>): Promise<{
73
+ value: T;
74
+ reason: CancellationReason | undefined;
75
+ } | undefined>;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * One cancellable long operation with its own progress surface.
3
+ *
4
+ * A long command needs three things wired together, and every call site used to
5
+ * write the same wiring by hand:
6
+ *
7
+ * 1. a signal that combines the caller's own cancellation with the reader's;
8
+ * 2. a prompt that gives the reader a way to cancel — Enter, Escape, `Ctrl+C`;
9
+ * 3. a "finished" signal so that dismissing the prompt because the *work* ended
10
+ * is not mistaken for the reader cancelling the work.
11
+ *
12
+ * The third point is where hand-written copies went wrong: the prompt's promise
13
+ * settles both when the reader cancels and when the operation completes, so a
14
+ * naive `.then(() => controller.abort())` aborted the operation on its own
15
+ * success. Each site had to guard it with a second `finished` controller, and
16
+ * each site wrote that guard differently.
17
+ *
18
+ * `run()` owns the whole lifecycle: the body receives the combined signal, and
19
+ * the prompt is dismissed when the body settles either way.
20
+ *
21
+ * @module @agi-fans/dsh-tui/cancellable
22
+ */
23
+ /**
24
+ * Run one long operation behind a cancel surface.
25
+ *
26
+ * Returns `undefined` when the operation never started because the caller was
27
+ * already aborted, so callers can skip their success path without checking.
28
+ *
29
+ * A non-interactive host runs the body without a surface: there is no reader to
30
+ * cancel it, and opening a prompt would claim a screen the pipe does not have.
31
+ */
32
+ export async function cancellable(tui, progress, parent, run) {
33
+ if (parent.aborted)
34
+ return undefined;
35
+ const cancel = new AbortController();
36
+ const finished = new AbortController();
37
+ const signal = AbortSignal.any([parent, cancel.signal]);
38
+ let superseded = false;
39
+ const surface = progress.surface
40
+ ? tui.prompt({
41
+ title: progress.title,
42
+ question: progress.question,
43
+ ...(progress.detail === undefined ? {} : { detail: progress.detail }),
44
+ ...(progress.document === undefined ? {} : { refreshDocument: progress.document }),
45
+ // Both surfaces report cancellation through the `interrupt` hook instead of
46
+ // the returned value, because the reader may be reading while it runs; the
47
+ // option list is only the keyboard affordance.
48
+ presentation: progress.presentation ?? 'progress',
49
+ options: [{ label: progress.cancelLabel ?? 'Cancel', value: 'cancel' }],
50
+ allowCustom: false,
51
+ notify: false,
52
+ signal: AbortSignal.any([parent, finished.signal]),
53
+ interrupt: () => { cancel.abort(); return true; },
54
+ // A superseding prompt takes the screen, which ends this operation rather
55
+ // than letting it run behind a surface nobody can see.
56
+ onSuperseded: () => { superseded = true; cancel.abort(); },
57
+ })
58
+ .then(() => { if (!finished.signal.aborted)
59
+ cancel.abort(); }, () => { cancel.abort(); })
60
+ : Promise.resolve();
61
+ try {
62
+ const value = await run(signal);
63
+ // `cancel` also fires when the parent aborted; only a stop the reader caused
64
+ // is reported as one.
65
+ const stopped = cancel.signal.aborted && !parent.aborted;
66
+ return { value, reason: stopped ? (superseded ? 'superseded' : 'cancelled') : undefined };
67
+ }
68
+ finally {
69
+ // Dismiss the surface exactly once, whether the work finished, failed, or
70
+ // was cancelled. Aborting `finished` first is what tells the prompt's own
71
+ // `.then` that this dismissal is not a cancellation.
72
+ finished.abort();
73
+ await surface;
74
+ }
75
+ }
76
+ //# sourceMappingURL=cancellable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cancellable.js","sourceRoot":"","sources":["../../src/runtime/cancellable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AA6CH;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,GAA+C,EAC/C,QAA6B,EAC7B,MAAmB,EACnB,GAAwC;IAExC,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,SAAS,CAAA;IACpC,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAA;IACpC,MAAM,QAAQ,GAAG,IAAI,eAAe,EAAE,CAAA;IACtC,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;IACvD,IAAI,UAAU,GAAG,KAAK,CAAA;IAEtB,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO;QAC9B,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;YACX,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,GAAG,CAAC,QAAQ,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;YACrE,GAAG,CAAC,QAAQ,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC;YAClF,4EAA4E;YAC5E,2EAA2E;YAC3E,+CAA+C;YAC/C,YAAY,EAAE,QAAQ,CAAC,YAAY,IAAI,UAAU;YACjD,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,WAAW,IAAI,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;YACvE,WAAW,EAAE,KAAK;YAClB,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;YAClD,SAAS,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,IAAI,CAAA,CAAC,CAAC;YAChD,0EAA0E;YAC1E,uDAAuD;YACvD,YAAY,EAAE,GAAG,EAAE,GAAG,UAAU,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA,CAAC,CAAC;SAC1D,CAAC;aACC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,CAAC,KAAK,EAAE,CAAA,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,CAAA,CAAC,CAAC,CAAC;QACzF,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAA;IAErB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,CAAA;QAC/B,6EAA6E;QAC7E,sBAAsB;QACtB,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAA;QACxD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAA;IAC3F,CAAC;YAAS,CAAC;QACT,0EAA0E;QAC1E,0EAA0E;QAC1E,qDAAqD;QACrD,QAAQ,CAAC,KAAK,EAAE,CAAA;QAChB,MAAM,OAAO,CAAA;IACf,CAAC;AACH,CAAC"}
@@ -7,7 +7,7 @@
7
7
  * decoding, and the prompt/settings/search branches that decide whether a
8
8
  * paste is an image at all stay in the provider.
9
9
  */
10
- import { imageMarker, probeImageDimensions } from "../input/image-paste.js";
10
+ import { imageMarker, probeImageDimensions, submissionDraftText } from "../input/image-paste.js";
11
11
  export class ComposerImages {
12
12
  #deps;
13
13
  #images = [];
@@ -139,15 +139,16 @@ export class ComposerImages {
139
139
  const image = currentImages[index];
140
140
  rebasedCurrent = rebasedCurrent.replaceAll(imageMarker(index, image), imageMarker(index + submission.images.length, image));
141
141
  }
142
- const separator = submission.text !== '' && rebasedCurrent !== '' ? '\n' : '';
142
+ const restored = submissionDraftText(submission);
143
+ const separator = restored !== '' && rebasedCurrent !== '' ? '\n' : '';
143
144
  this.#images = [...submission.images.map(image => ({ ...image })), ...currentImages];
144
- editor.replaceText(submission.text + separator + rebasedCurrent);
145
+ editor.replaceText(restored + separator + rebasedCurrent);
145
146
  }
146
147
  /** Replace drafts and text with a queued/edited submission. */
147
148
  replace(submission) {
148
149
  this.#revision++;
149
150
  this.#images = submission.images.map(image => ({ ...image }));
150
- this.#deps.editor.setText(submission.text);
151
+ this.#deps.editor.setText(submissionDraftText(submission));
151
152
  }
152
153
  clear() {
153
154
  this.#revision++;
@@ -1 +1 @@
1
- {"version":3,"file":"composer-images.js","sourceRoot":"","sources":["../../src/runtime/composer-images.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"composer-images.js","sourceRoot":"","sources":["../../src/runtime/composer-images.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /** Composer shortcut over the same owner-scoped Shell used by `/terminal`. */
2
+ import type { Context } from '@deepseek-ai/cordis';
3
+ import type { Agent } from '@deepseek-ai/dsh-agent';
4
+ import type { TuiSubmission } from '../definition.ts';
5
+ /** Only deliberate, attachment-free composer input may execute a Shell line. */
6
+ export declare function composerShellCommand(submission: TuiSubmission): string | undefined;
7
+ /** `!!<command>` runs in the session Shell and shares its output to the conversation. */
8
+ export declare function composerShellShare(submission: TuiSubmission): boolean;
9
+ /**
10
+ * Run one Shell line in the session Shell, streaming its output to a live card.
11
+ *
12
+ * The card is the surface. There is no reader to enter and leave: the command
13
+ * streams into the transcript where the reader asked for it, and finishes when
14
+ * the command finishes. `!` keeps the output outside the model's context; `!!`
15
+ * shares it once the command settles.
16
+ */
17
+ export declare function runComposerShell(ctx: Context, owner: Agent, command: string, upstream: AbortSignal, options?: {
18
+ share?: boolean;
19
+ }): Promise<void>;
20
+ /**
21
+ * Close the composer Shell when it is not running anything.
22
+ *
23
+ * The Shell is reused across `!` lines so a directory change or an environment
24
+ * variable survives, which is the whole point of it. That reuse also pins the
25
+ * session to the Access level it was created in: the Harness refuses to change
26
+ * sandbox mode while a persistent terminal is open, and a reader driving `!`
27
+ * cards would otherwise be stuck on one level forever with no way out. A Shell
28
+ * with a command still running is left alone — closing it would kill work.
29
+ */
30
+ export declare function closeIdleComposerShell(ctx: Context, owner: Agent): Promise<boolean>;
@@ -0,0 +1,150 @@
1
+ /** Composer shortcut over the same owner-scoped Shell used by `/terminal`. */
2
+ import { shareTerminalOutputToConversation } from "../commands/terminal.js";
3
+ import { currentWorkingDirectory } from "../session/working-directory.js";
4
+ /** Only deliberate, attachment-free composer input may execute a Shell line. */
5
+ export function composerShellCommand(submission) {
6
+ if (submission.literal || submission.images.length > 0 || submission.files?.length)
7
+ return undefined;
8
+ if (!submission.text.startsWith('!'))
9
+ return undefined;
10
+ return submission.text.replace(/^!{1,2}/u, '').trim();
11
+ }
12
+ /** `!!<command>` runs in the session Shell and shares its output to the conversation. */
13
+ export function composerShellShare(submission) {
14
+ if (submission.literal || submission.images.length > 0 || submission.files?.length)
15
+ return false;
16
+ return submission.text.startsWith('!!');
17
+ }
18
+ /**
19
+ * Run one Shell line in the session Shell, streaming its output to a live card.
20
+ *
21
+ * The card is the surface. There is no reader to enter and leave: the command
22
+ * streams into the transcript where the reader asked for it, and finishes when
23
+ * the command finishes. `!` keeps the output outside the model's context; `!!`
24
+ * shares it once the command settles.
25
+ */
26
+ export async function runComposerShell(ctx, owner, command, upstream, options = {}) {
27
+ if (ctx.tui.interactive !== true)
28
+ throw new Error('Shell shortcuts require an interactive terminal.');
29
+ if (command === '')
30
+ throw new Error('Enter a command after ! to run it in the session Shell.');
31
+ const terminals = ctx.get('terminals');
32
+ if (terminals === undefined)
33
+ throw new Error('The terminal provider is not enabled. Enable the terminal plugins to run Shell commands.');
34
+ if (ctx.tui.shellCommand === undefined)
35
+ throw new Error('This deployment cannot run Shell lines from the composer.');
36
+ const interruption = new AbortController();
37
+ const signal = AbortSignal.any([upstream, interruption.signal]);
38
+ signal.throwIfAborted();
39
+ // Cordis service access is context-bound; proxy identity is not a registry
40
+ // identity. The registry already owns exact-Agent names and liveness.
41
+ const previous = terminals.list(owner).find(item => item.name === 'Composer shell' && item.type === 'shell');
42
+ let id = previous?.sessionId;
43
+ if (id !== undefined && previous?.status.kind !== 'running') {
44
+ await terminals.kill(owner, id, 'Composer shell exited');
45
+ id = undefined;
46
+ }
47
+ if (id === undefined) {
48
+ const session = await terminals.spawn(owner, { type: 'shell', name: 'Composer shell', cwd: currentWorkingDirectory(ctx, owner.session) }, signal);
49
+ id = session.sessionId;
50
+ }
51
+ signal.throwIfAborted();
52
+ const sessionId = id;
53
+ let produced = '';
54
+ await ctx.tui.shellCommand({
55
+ command,
56
+ signal,
57
+ abort: () => { interruption.abort(new Error('Shell interrupted by user')); },
58
+ ...(options.share === true ? { share: true } : {}),
59
+ run: async (onOutput, runSignal) => {
60
+ // The Shell is persistent, so its scrollback holds everything typed into it
61
+ // across earlier `!` lines — and the shell's own prompt echoes each line.
62
+ // Reading the whole snapshot into the card would repeat the command under
63
+ // our own `$ command` header and replay history from before this line ran.
64
+ // The line count is the boundary: everything above it belongs to an
65
+ // earlier line, everything below it is this command's output.
66
+ const baseline = terminals.read(owner, sessionId).totalLines;
67
+ const operation = terminals.startSend(owner, sessionId, { text: command, submit: true, signal: runSignal });
68
+ const since = () => {
69
+ const fresh = terminals.read(owner, sessionId).totalLines - baseline;
70
+ if (fresh <= 0)
71
+ return '';
72
+ return terminals.read(owner, sessionId, { offset: 0, count: fresh }).text;
73
+ };
74
+ let done = false;
75
+ const pump = () => {
76
+ if (done)
77
+ return;
78
+ onOutput(since());
79
+ };
80
+ const tick = setInterval(pump, SHELL_STREAM_TICK_MS);
81
+ tick.unref?.();
82
+ // Race the send against the abort. A provider is not obliged to settle
83
+ // `done` when a signal fires, and waiting on it would leave the card
84
+ // running after the reader already asked it to stop.
85
+ const aborted = new Promise((resolve) => {
86
+ if (runSignal.aborted)
87
+ resolve('aborted');
88
+ else
89
+ runSignal.addEventListener('abort', () => { resolve('aborted'); }, { once: true });
90
+ });
91
+ try {
92
+ const settled = await Promise.race([operation.done.then(() => 'done').catch(() => 'failed'), aborted]);
93
+ // A settled send means the line was delivered, not that the command
94
+ // exited; the card reports the delivery rather than inventing an exit
95
+ // code the Shell never gave us.
96
+ if (settled === 'done') {
97
+ // Publish the settled delta to the card as well: the tick that would
98
+ // have shown it may never fire, and the card must not stop on a frame
99
+ // older than the command.
100
+ produced = since();
101
+ if (produced !== '')
102
+ onOutput(produced);
103
+ return { output: produced };
104
+ }
105
+ // An interrupted line still needs the send cancelled and the shell
106
+ // signalled, or the command keeps running in the background while the
107
+ // card claims it stopped.
108
+ if (!operation.cancel() && terminals.list(owner).some(item => item.sessionId === sessionId && item.status.kind === 'running')) {
109
+ await terminals.signal(owner, sessionId, 'SIGINT');
110
+ }
111
+ return { output: since(), interrupted: true };
112
+ }
113
+ finally {
114
+ done = true;
115
+ clearInterval(tick);
116
+ }
117
+ },
118
+ });
119
+ if (options.share === true && !signal.aborted) {
120
+ // Share what this line produced, for the same reason the card shows that.
121
+ shareTerminalOutputToConversation(owner, `Shell · \`${command}\``, produced);
122
+ }
123
+ }
124
+ /**
125
+ * Close the composer Shell when it is not running anything.
126
+ *
127
+ * The Shell is reused across `!` lines so a directory change or an environment
128
+ * variable survives, which is the whole point of it. That reuse also pins the
129
+ * session to the Access level it was created in: the Harness refuses to change
130
+ * sandbox mode while a persistent terminal is open, and a reader driving `!`
131
+ * cards would otherwise be stuck on one level forever with no way out. A Shell
132
+ * with a command still running is left alone — closing it would kill work.
133
+ */
134
+ export async function closeIdleComposerShell(ctx, owner) {
135
+ const terminals = ctx.get('terminals');
136
+ if (terminals === undefined)
137
+ return false;
138
+ // A persistent shell reports `running` for as long as it is alive, whether or
139
+ // not a command is in it, so "idle" cannot be read from that status. The
140
+ // composer Shell is closed unconditionally: it exists only to serve the last
141
+ // `!` line, and the reader is asking to change Access rather than to keep a
142
+ // session pinned to the old one.
143
+ const shells = terminals.list(owner).filter(item => item.name === 'Composer shell' && item.type === 'shell');
144
+ for (const item of shells)
145
+ await terminals.kill(owner, item.sessionId, 'Composer shell closed for an Access change');
146
+ return shells.length > 0;
147
+ }
148
+ /** How often the live card re-reads the terminal while a command writes. */
149
+ const SHELL_STREAM_TICK_MS = 120;
150
+ //# sourceMappingURL=composer-shell.js.map