@sapiom/harness 0.0.0 → 0.1.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 (246) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +44 -43
  3. package/dist/cli/auth.d.ts +26 -0
  4. package/dist/cli/auth.d.ts.map +1 -0
  5. package/dist/cli/auth.js +39 -0
  6. package/dist/cli/auth.js.map +1 -0
  7. package/dist/cli/bin.d.ts +3 -0
  8. package/dist/cli/bin.d.ts.map +1 -0
  9. package/dist/cli/bin.js +163 -0
  10. package/dist/cli/bin.js.map +1 -0
  11. package/dist/cli/consent.d.ts +15 -0
  12. package/dist/cli/consent.d.ts.map +1 -0
  13. package/dist/cli/consent.js +81 -0
  14. package/dist/cli/consent.js.map +1 -0
  15. package/dist/cli/doctor.d.ts +27 -0
  16. package/dist/cli/doctor.d.ts.map +1 -0
  17. package/dist/cli/doctor.js +74 -0
  18. package/dist/cli/doctor.js.map +1 -0
  19. package/dist/cli/machine-id.d.ts +19 -0
  20. package/dist/cli/machine-id.d.ts.map +1 -0
  21. package/dist/cli/machine-id.js +75 -0
  22. package/dist/cli/machine-id.js.map +1 -0
  23. package/dist/cli/paths.d.ts +3 -0
  24. package/dist/cli/paths.d.ts.map +1 -0
  25. package/dist/cli/paths.js +11 -0
  26. package/dist/cli/paths.js.map +1 -0
  27. package/dist/cli/settings.d.ts +26 -0
  28. package/dist/cli/settings.d.ts.map +1 -0
  29. package/dist/cli/settings.js +123 -0
  30. package/dist/cli/settings.js.map +1 -0
  31. package/dist/core/adapters/claude-code.d.ts +41 -0
  32. package/dist/core/adapters/claude-code.d.ts.map +1 -0
  33. package/dist/core/adapters/claude-code.js +238 -0
  34. package/dist/core/adapters/claude-code.js.map +1 -0
  35. package/dist/core/adapters/codex.d.ts +59 -0
  36. package/dist/core/adapters/codex.d.ts.map +1 -0
  37. package/dist/core/adapters/codex.js +319 -0
  38. package/dist/core/adapters/codex.js.map +1 -0
  39. package/dist/core/canvas-body.d.ts +45 -0
  40. package/dist/core/canvas-body.d.ts.map +1 -0
  41. package/dist/core/canvas-body.js +94 -0
  42. package/dist/core/canvas-body.js.map +1 -0
  43. package/dist/core/canvas-cache.d.ts +23 -0
  44. package/dist/core/canvas-cache.d.ts.map +1 -0
  45. package/dist/core/canvas-cache.js +64 -0
  46. package/dist/core/canvas-cache.js.map +1 -0
  47. package/dist/core/canvas-enrich.d.ts +106 -0
  48. package/dist/core/canvas-enrich.d.ts.map +1 -0
  49. package/dist/core/canvas-enrich.js +178 -0
  50. package/dist/core/canvas-enrich.js.map +1 -0
  51. package/dist/core/canvas-enrichment.d.ts +144 -0
  52. package/dist/core/canvas-enrichment.d.ts.map +1 -0
  53. package/dist/core/canvas-enrichment.js +192 -0
  54. package/dist/core/canvas-enrichment.js.map +1 -0
  55. package/dist/core/canvas-graph.d.ts +71 -0
  56. package/dist/core/canvas-graph.d.ts.map +1 -0
  57. package/dist/core/canvas-graph.js +111 -0
  58. package/dist/core/canvas-graph.js.map +1 -0
  59. package/dist/core/canvas-index-classify.d.ts +41 -0
  60. package/dist/core/canvas-index-classify.d.ts.map +1 -0
  61. package/dist/core/canvas-index-classify.js +63 -0
  62. package/dist/core/canvas-index-classify.js.map +1 -0
  63. package/dist/core/canvas-interconnections.d.ts +24 -0
  64. package/dist/core/canvas-interconnections.d.ts.map +1 -0
  65. package/dist/core/canvas-interconnections.js +96 -0
  66. package/dist/core/canvas-interconnections.js.map +1 -0
  67. package/dist/core/canvas-manifest-check.d.ts +15 -0
  68. package/dist/core/canvas-manifest-check.d.ts.map +1 -0
  69. package/dist/core/canvas-manifest-check.js +90 -0
  70. package/dist/core/canvas-manifest-check.js.map +1 -0
  71. package/dist/core/canvas-render.d.ts +73 -0
  72. package/dist/core/canvas-render.d.ts.map +1 -0
  73. package/dist/core/canvas-render.js +145 -0
  74. package/dist/core/canvas-render.js.map +1 -0
  75. package/dist/core/canvas-svg.d.ts +50 -0
  76. package/dist/core/canvas-svg.d.ts.map +1 -0
  77. package/dist/core/canvas-svg.js +240 -0
  78. package/dist/core/canvas-svg.js.map +1 -0
  79. package/dist/core/canvas-template.d.ts +43 -0
  80. package/dist/core/canvas-template.d.ts.map +1 -0
  81. package/dist/core/canvas-template.js +365 -0
  82. package/dist/core/canvas-template.js.map +1 -0
  83. package/dist/core/canvas-watcher.d.ts +25 -0
  84. package/dist/core/canvas-watcher.d.ts.map +1 -0
  85. package/dist/core/canvas-watcher.js +144 -0
  86. package/dist/core/canvas-watcher.js.map +1 -0
  87. package/dist/core/collector/batcher.d.ts +57 -0
  88. package/dist/core/collector/batcher.d.ts.map +1 -0
  89. package/dist/core/collector/batcher.js +143 -0
  90. package/dist/core/collector/batcher.js.map +1 -0
  91. package/dist/core/collector/codex-tailer.d.ts +85 -0
  92. package/dist/core/collector/codex-tailer.d.ts.map +1 -0
  93. package/dist/core/collector/codex-tailer.js +270 -0
  94. package/dist/core/collector/codex-tailer.js.map +1 -0
  95. package/dist/core/collector/normalizer.d.ts +33 -0
  96. package/dist/core/collector/normalizer.d.ts.map +1 -0
  97. package/dist/core/collector/normalizer.js +94 -0
  98. package/dist/core/collector/normalizer.js.map +1 -0
  99. package/dist/core/collector/seq.d.ts +14 -0
  100. package/dist/core/collector/seq.d.ts.map +1 -0
  101. package/dist/core/collector/seq.js +20 -0
  102. package/dist/core/collector/seq.js.map +1 -0
  103. package/dist/core/collector/store.d.ts +16 -0
  104. package/dist/core/collector/store.d.ts.map +1 -0
  105. package/dist/core/collector/store.js +30 -0
  106. package/dist/core/collector/store.js.map +1 -0
  107. package/dist/core/collector/transcript.d.ts +38 -0
  108. package/dist/core/collector/transcript.d.ts.map +1 -0
  109. package/dist/core/collector/transcript.js +110 -0
  110. package/dist/core/collector/transcript.js.map +1 -0
  111. package/dist/core/event-bus.d.ts +9 -0
  112. package/dist/core/event-bus.d.ts.map +1 -0
  113. package/dist/core/event-bus.js +25 -0
  114. package/dist/core/event-bus.js.map +1 -0
  115. package/dist/core/example-seed.d.ts +34 -0
  116. package/dist/core/example-seed.d.ts.map +1 -0
  117. package/dist/core/example-seed.js +277 -0
  118. package/dist/core/example-seed.js.map +1 -0
  119. package/dist/core/inject/claude-settings.d.ts +34 -0
  120. package/dist/core/inject/claude-settings.d.ts.map +1 -0
  121. package/dist/core/inject/claude-settings.js +152 -0
  122. package/dist/core/inject/claude-settings.js.map +1 -0
  123. package/dist/core/inject/mcp-config.d.ts +26 -0
  124. package/dist/core/inject/mcp-config.d.ts.map +1 -0
  125. package/dist/core/inject/mcp-config.js +39 -0
  126. package/dist/core/inject/mcp-config.js.map +1 -0
  127. package/dist/core/inject/retention.d.ts +66 -0
  128. package/dist/core/inject/retention.d.ts.map +1 -0
  129. package/dist/core/inject/retention.js +119 -0
  130. package/dist/core/inject/retention.js.map +1 -0
  131. package/dist/core/inject/system-prompt.d.ts +11 -0
  132. package/dist/core/inject/system-prompt.d.ts.map +1 -0
  133. package/dist/core/inject/system-prompt.js +22 -0
  134. package/dist/core/inject/system-prompt.js.map +1 -0
  135. package/dist/core/macro-runner.d.ts +36 -0
  136. package/dist/core/macro-runner.d.ts.map +1 -0
  137. package/dist/core/macro-runner.js +66 -0
  138. package/dist/core/macro-runner.js.map +1 -0
  139. package/dist/core/macros.d.ts +10 -0
  140. package/dist/core/macros.d.ts.map +1 -0
  141. package/dist/core/macros.js +59 -0
  142. package/dist/core/macros.js.map +1 -0
  143. package/dist/core/path-safety.d.ts +33 -0
  144. package/dist/core/path-safety.d.ts.map +1 -0
  145. package/dist/core/path-safety.js +63 -0
  146. package/dist/core/path-safety.js.map +1 -0
  147. package/dist/core/paths.d.ts +27 -0
  148. package/dist/core/paths.d.ts.map +1 -0
  149. package/dist/core/paths.js +43 -0
  150. package/dist/core/paths.js.map +1 -0
  151. package/dist/core/port-detector.d.ts +69 -0
  152. package/dist/core/port-detector.d.ts.map +1 -0
  153. package/dist/core/port-detector.js +121 -0
  154. package/dist/core/port-detector.js.map +1 -0
  155. package/dist/core/session-manager.d.ts +275 -0
  156. package/dist/core/session-manager.d.ts.map +1 -0
  157. package/dist/core/session-manager.js +729 -0
  158. package/dist/core/session-manager.js.map +1 -0
  159. package/dist/core/task-manager.d.ts +138 -0
  160. package/dist/core/task-manager.d.ts.map +1 -0
  161. package/dist/core/task-manager.js +286 -0
  162. package/dist/core/task-manager.js.map +1 -0
  163. package/dist/core/task-stream.d.ts +32 -0
  164. package/dist/core/task-stream.d.ts.map +1 -0
  165. package/dist/core/task-stream.js +87 -0
  166. package/dist/core/task-stream.js.map +1 -0
  167. package/dist/core/workflow-registry.d.ts +36 -0
  168. package/dist/core/workflow-registry.d.ts.map +1 -0
  169. package/dist/core/workflow-registry.js +220 -0
  170. package/dist/core/workflow-registry.js.map +1 -0
  171. package/dist/core/workspace-context.d.ts +43 -0
  172. package/dist/core/workspace-context.d.ts.map +1 -0
  173. package/dist/core/workspace-context.js +108 -0
  174. package/dist/core/workspace-context.js.map +1 -0
  175. package/dist/core/workspace-watcher.d.ts +26 -0
  176. package/dist/core/workspace-watcher.d.ts.map +1 -0
  177. package/dist/core/workspace-watcher.js +174 -0
  178. package/dist/core/workspace-watcher.js.map +1 -0
  179. package/dist/index.d.ts +6 -0
  180. package/dist/index.d.ts.map +1 -0
  181. package/dist/index.js +6 -0
  182. package/dist/index.js.map +1 -0
  183. package/dist/profiles/canvas-guidelines.d.ts +20 -0
  184. package/dist/profiles/canvas-guidelines.d.ts.map +1 -0
  185. package/dist/profiles/canvas-guidelines.js +48 -0
  186. package/dist/profiles/canvas-guidelines.js.map +1 -0
  187. package/dist/profiles/default.d.ts +10 -0
  188. package/dist/profiles/default.d.ts.map +1 -0
  189. package/dist/profiles/default.js +70 -0
  190. package/dist/profiles/default.js.map +1 -0
  191. package/dist/server/auth.d.ts +9 -0
  192. package/dist/server/auth.d.ts.map +1 -0
  193. package/dist/server/auth.js +28 -0
  194. package/dist/server/auth.js.map +1 -0
  195. package/dist/server/canvas-render.d.ts +18 -0
  196. package/dist/server/canvas-render.d.ts.map +1 -0
  197. package/dist/server/canvas-render.js +24 -0
  198. package/dist/server/canvas-render.js.map +1 -0
  199. package/dist/server/canvas.d.ts +12 -0
  200. package/dist/server/canvas.d.ts.map +1 -0
  201. package/dist/server/canvas.js +174 -0
  202. package/dist/server/canvas.js.map +1 -0
  203. package/dist/server/events-ws.d.ts +11 -0
  204. package/dist/server/events-ws.d.ts.map +1 -0
  205. package/dist/server/events-ws.js +24 -0
  206. package/dist/server/events-ws.js.map +1 -0
  207. package/dist/server/fs.d.ts +4 -0
  208. package/dist/server/fs.d.ts.map +1 -0
  209. package/dist/server/fs.js +88 -0
  210. package/dist/server/fs.js.map +1 -0
  211. package/dist/server/index.d.ts +83 -0
  212. package/dist/server/index.d.ts.map +1 -0
  213. package/dist/server/index.js +0 -0
  214. package/dist/server/index.js.map +1 -0
  215. package/dist/server/ingest.d.ts +74 -0
  216. package/dist/server/ingest.d.ts.map +1 -0
  217. package/dist/server/ingest.js +74 -0
  218. package/dist/server/ingest.js.map +1 -0
  219. package/dist/server/macros.d.ts +32 -0
  220. package/dist/server/macros.d.ts.map +1 -0
  221. package/dist/server/macros.js +76 -0
  222. package/dist/server/macros.js.map +1 -0
  223. package/dist/server/rest.d.ts +75 -0
  224. package/dist/server/rest.d.ts.map +1 -0
  225. package/dist/server/rest.js +235 -0
  226. package/dist/server/rest.js.map +1 -0
  227. package/dist/server/static.d.ts +8 -0
  228. package/dist/server/static.d.ts.map +1 -0
  229. package/dist/server/static.js +36 -0
  230. package/dist/server/static.js.map +1 -0
  231. package/dist/server/terminal-ws.d.ts +9 -0
  232. package/dist/server/terminal-ws.d.ts.map +1 -0
  233. package/dist/server/terminal-ws.js +59 -0
  234. package/dist/server/terminal-ws.js.map +1 -0
  235. package/dist/server/ws-router.d.ts +16 -0
  236. package/dist/server/ws-router.d.ts.map +1 -0
  237. package/dist/server/ws-router.js +26 -0
  238. package/dist/server/ws-router.js.map +1 -0
  239. package/dist/shared/types.d.ts +485 -0
  240. package/dist/shared/types.d.ts.map +1 -0
  241. package/dist/shared/types.js +80 -0
  242. package/dist/shared/types.js.map +1 -0
  243. package/dist/web/assets/index-B9R4TzH7.css +32 -0
  244. package/dist/web/assets/index-Dh97QAgq.js +192 -0
  245. package/dist/web/index.html +27 -0
  246. package/package.json +84 -7
@@ -0,0 +1,275 @@
1
+ /**
2
+ * SessionManager — node-pty registry implementing the session lifecycle from
3
+ * the shared contract: create, resume, kill, list. Persists HarnessSession[]
4
+ * to disk (HARNESS_PATHS.sessions) so the SPA's session dropdown survives
5
+ * server restarts, even though the ptys themselves do not.
6
+ */
7
+ import { type CreateSessionRequest, type HarnessAdapter, type HarnessKind, type HarnessSession, type LaunchOpts } from "../shared/types.js";
8
+ type IPty = import("node-pty").IPty;
9
+ type PtyForkOptions = import("node-pty").IPtyForkOptions;
10
+ export type PtySpawnFn = (file: string, args: string[], options: PtyForkOptions) => IPty;
11
+ /**
12
+ * node-pty ships prebuilt native binaries (including a tiny `spawn-helper`
13
+ * on macOS/Linux) rather than compiling from source. Observed in the wild:
14
+ * a pnpm-managed install can extract that helper without its executable bit
15
+ * set, which fails every single spawn with an opaque "posix_spawnp failed"
16
+ * — nothing to do with the harness's own code, but fatal to every session
17
+ * launch. Best-effort self-heal before the first real spawn; silently a
18
+ * no-op if the file's missing (wrong platform/arch) or already executable.
19
+ * Exported so scripts/e2e-live.ts's preflight check shares this exact fix
20
+ * instead of duplicating it.
21
+ */
22
+ export declare function ensureSpawnHelperExecutable(): Promise<void>;
23
+ /**
24
+ * Thrown by `submitInput()` when a session's pty is alive but never became
25
+ * ready (see `HarnessSession.ready`) within `READY_GRACE_MS` — the trust-
26
+ * dialog race this whole readiness mechanism exists to catch. Callers
27
+ * (rest.ts, macros.ts) catch this specifically and surface it as a 409 with
28
+ * a UI-visible reason, rather than letting it fall into a generic 500 or
29
+ * (worse, the bug this fixes) silently writing into a non-interactive TUI.
30
+ */
31
+ export declare class SessionNotReadyError extends Error {
32
+ constructor(id: string);
33
+ }
34
+ export type SessionStatusListener = (session: HarnessSession) => void;
35
+ export type SessionDataListener = (chunk: string) => void;
36
+ /** See `onActivity()`. */
37
+ export type SessionActivityListener = (harnessSessionId: string) => void;
38
+ /**
39
+ * Builds the harness-specific part of LaunchOpts (generated system-prompt /
40
+ * mcp-config / settings file paths). SessionManager owns cwd + harnessSessionId;
41
+ * this lets the server layer inject config-file generation (profiles, MCP
42
+ * wiring) without SessionManager needing to know how those files are produced.
43
+ * May return synchronously or a Promise — generating the config files is
44
+ * inherently async (they're written to disk), so `create()`/`resume()` await
45
+ * whichever shape is handed in; existing sync test doubles keep working
46
+ * unchanged (`await` on a plain value just resolves immediately).
47
+ */
48
+ export type LaunchOptsBuilder = (harnessSessionId: string, req: Pick<CreateSessionRequest, "cwd" | "harness" | "profile">) => Omit<LaunchOpts, "harnessSessionId" | "cwd"> | Promise<Omit<LaunchOpts, "harnessSessionId" | "cwd">>;
49
+ export interface SessionManagerOptions {
50
+ adapters: Partial<Record<HarnessKind, HarnessAdapter>>;
51
+ /** Base URL the harness server is reachable at, e.g. http://127.0.0.1:4100. */
52
+ ingestUrl: string;
53
+ /** Per-boot secret; injected into every session's env so hook scripts can auth to /ingest. */
54
+ ingestToken: string;
55
+ /** Forwarded to sessions as SAPIOM_COLLECTOR_URL when set. */
56
+ collectorUrl?: string;
57
+ /** Absolute path to the session registry file. Defaults to HARNESS_PATHS.sessions (expanded). */
58
+ sessionsPath?: string;
59
+ /** Injectable for tests. Defaults to a lazily-loaded node-pty. */
60
+ spawnPty?: PtySpawnFn;
61
+ buildLaunchOpts?: LaunchOptsBuilder;
62
+ now?: () => string;
63
+ generateId?: () => string;
64
+ /**
65
+ * Writes HARNESS_CONTEXT_FILE for a session — the caller (server/index.ts's
66
+ * `writeSessionContext`) owns resolving the session's `boundWorkflowPath`
67
+ * against the live workflow registry and serializing the full workspace
68
+ * state; this layer just decides *when* to call it. Called unconditionally
69
+ * from `create()`, before the pty is spawned, so every session gets the
70
+ * file regardless of entry point (REST, `autoCreateSession`) — no entry
71
+ * point can skip it by calling `create()` directly. Also used by
72
+ * `resume()` as a backfill when the file is entirely missing (see
73
+ * `workspaceContextExists`). Defaults to a no-op so tests that pass a fake
74
+ * `cwd` (e.g. `/tmp/proj`) never touch the real filesystem unless they opt
75
+ * in.
76
+ */
77
+ writeWorkspaceContext?: (session: HarnessSession) => Promise<void>;
78
+ /**
79
+ * Reports whether HARNESS_CONTEXT_FILE already exists for a cwd. Used only
80
+ * by `resume()`, to decide whether a backfill write is needed — resume
81
+ * must never clobber a file that could already reflect a real binding.
82
+ * Defaults to `true` (assume it exists, never backfill) to match the
83
+ * no-op default of `writeWorkspaceContext`.
84
+ */
85
+ workspaceContextExists?: (cwd: string) => Promise<boolean>;
86
+ /**
87
+ * Drops the canvas kit template into `<cwd>/.sapiom/canvas/index.html`
88
+ * when nothing is there yet (backfill-only — the real implementation,
89
+ * `ensureCanvasTemplate` from core/canvas-template.ts, does its own
90
+ * existence check internally, so unlike `writeWorkspaceContext` this
91
+ * needs no separate `*Exists` companion). Called from both `create()` and
92
+ * `resume()` so the canvas pane is never a blank iframe, regardless of
93
+ * entry point. Defaults to a no-op so tests that pass a fake `cwd` never
94
+ * touch the real filesystem unless they opt in.
95
+ */
96
+ ensureCanvasTemplate?: (cwd: string) => Promise<void>;
97
+ /**
98
+ * Injectable for tests (fake ptys carry fake pids that must never be
99
+ * probed against real OS processes). Defaults to `defaultIsPidAlive`.
100
+ */
101
+ isPidAlive?: (pid: number) => boolean;
102
+ }
103
+ export declare class SessionManager {
104
+ private readonly adapters;
105
+ private readonly ingestUrl;
106
+ private readonly ingestToken;
107
+ private readonly collectorUrl;
108
+ private readonly sessionsPath;
109
+ private readonly spawnPty;
110
+ private readonly buildLaunchOpts;
111
+ private readonly now;
112
+ private readonly generateId;
113
+ private readonly writeWorkspaceContext;
114
+ private readonly workspaceContextExists;
115
+ private readonly ensureCanvasTemplate;
116
+ private readonly isPidAlive;
117
+ private readonly sessions;
118
+ private readonly ptys;
119
+ private readonly statusEmitter;
120
+ private readonly activityEmitter;
121
+ /** Epoch ms of the last `onActivity` broadcast per session — see `recordActivity()`. */
122
+ private readonly lastActivityBroadcast;
123
+ private writeQueue;
124
+ private writeSeq;
125
+ private initialized;
126
+ constructor(options: SessionManagerOptions);
127
+ /**
128
+ * Loads the persisted registry. Any session left "starting"/"running" from
129
+ * a previous process is marked "exited" — ptys don't survive a restart.
130
+ */
131
+ init(): Promise<void>;
132
+ list(): HarnessSession[];
133
+ get(id: string): HarnessSession | undefined;
134
+ private getAdapter;
135
+ create(req: CreateSessionRequest): Promise<HarnessSession>;
136
+ /**
137
+ * Registers a purely historical (never-launched-by-this-harness) session so
138
+ * it can subsequently be resumed via `resume()`. Used by the server layer
139
+ * when a user picks a past session out of transcript-scanned history.
140
+ */
141
+ registerHistorical(input: {
142
+ agentSessionId: string;
143
+ harness: HarnessKind;
144
+ cwd: string;
145
+ title: string;
146
+ lastActiveAt: string;
147
+ }): HarnessSession;
148
+ resume(id: string): Promise<HarnessSession>;
149
+ kill(id: string): boolean;
150
+ /** Kills every currently-live pty. Call this on server shutdown — without
151
+ * it, spawned agent processes (claude/codex) outlive the harness server
152
+ * itself, e.g. after Ctrl+C, since closing the HTTP/WS server doesn't
153
+ * touch unrelated child processes on its own. */
154
+ killAll(): void;
155
+ /**
156
+ * Defensive liveness backstop, run periodically by the server: any
157
+ * non-exited session whose pty process is provably gone gets its exit
158
+ * synthesized. The specific transitions are already reconciled at their
159
+ * source (create/resume pre-pty failures, kill()'s missed-exit fallback),
160
+ * but node-pty has been observed to simply never fire `onExit` for a
161
+ * process that died moments after spawning (see `kill()`) — and a process
162
+ * that dies *on its own* that way has no kill()-style fallback watching
163
+ * it. This sweep is the catch-all for that and any transition not yet
164
+ * root-caused: a stale record shows as a ghost tab (non-exited status, no
165
+ * live pty) until something reconciles it.
166
+ */
167
+ sweepDeadSessions(): void;
168
+ write(id: string, data: string): boolean;
169
+ /**
170
+ * Inject a discrete prompt (macros, the Visualize button, `/api/sessions/:id/input`)
171
+ * with proper submit semantics — distinct from `write()`, which is a raw
172
+ * passthrough for live keystrokes from the terminal WS and must never add
173
+ * this delay/splitting behavior. See `SUBMIT_DELAY_MS` for why non-empty
174
+ * submitted text can't just be written as `${text}\r` in one call.
175
+ *
176
+ * Gated on readiness (see `HarnessSession.ready` / `isReadyEnough`): a
177
+ * "running" pty can still be sitting on a blocking prompt that swallows
178
+ * whatever's written to it. Briefly waits out `READY_GRACE_MS` for the
179
+ * ordinary "fired a beat too early" case; throws `SessionNotReadyError`
180
+ * — never silently proceeds — if the session still isn't ready after
181
+ * that, so the caller (rest.ts, macros.ts) can surface a clear reason
182
+ * instead of the input just vanishing.
183
+ */
184
+ submitInput(id: string, text: string, submit?: boolean): Promise<boolean>;
185
+ resize(id: string, cols: number, rows: number): boolean;
186
+ /**
187
+ * Subscribe to a session's output. Replays the retained scrollback buffer
188
+ * synchronously before returning so a reconnecting WS client sees recent
189
+ * output immediately. Returns undefined if the session has no live pty.
190
+ */
191
+ attach(id: string, listener: SessionDataListener): (() => void) | undefined;
192
+ onStatusChange(listener: SessionStatusListener): () => void;
193
+ /**
194
+ * Subscribe to a session producing terminal output — throttled (see
195
+ * `ACTIVITY_BROADCAST_THROTTLE_MS`), not one event per pty.onData chunk.
196
+ * Fires for every session regardless of whether anything has its
197
+ * /ws/terminal socket open, unlike `attach()`.
198
+ */
199
+ onActivity(listener: SessionActivityListener): () => void;
200
+ /**
201
+ * Leading-edge throttle: broadcasts immediately on the first byte after a
202
+ * quiet period, then drops everything else for this session until
203
+ * `ACTIVITY_BROADCAST_THROTTLE_MS` has elapsed — a busy TUI's onData fires
204
+ * far more often than that, and callers (the SPA's per-tab pulse) only
205
+ * care that the session is active right now, not each individual chunk.
206
+ */
207
+ private recordActivity;
208
+ setAgentSessionId(id: string, agentSessionId: string): void;
209
+ /**
210
+ * Marks a session's TUI as genuinely interactive — see `HarnessSession.ready`.
211
+ * Called from the ingest pipeline when a SessionStart(-equivalent) event
212
+ * is processed for this session (real hook for Claude Code, tailer-
213
+ * translated for Codex). Idempotent; a session that's exited or already
214
+ * ready is a silent no-op.
215
+ */
216
+ setReady(id: string): void;
217
+ /**
218
+ * Whether `id` should be treated as ready to receive programmatic input
219
+ * right now — `session.ready` (the real signal), OR, for a harness that
220
+ * declares `detectBlockingPrompt` (currently: Codex, whose rollout file —
221
+ * and therefore its SessionStart-equivalent — isn't written until the
222
+ * *first* turn is submitted, so the real signal can never arrive before
223
+ * the very first injection that needs it): the pty has had a moment to
224
+ * render its first real frame (`READY_SETTLE_MS`) and that frame doesn't
225
+ * show a known blocking prompt. A harness without `detectBlockingPrompt`
226
+ * (Claude Code) gets no such fallback — its SessionStart hook is reliable
227
+ * standalone, and a scrollback guess would just reopen the exact race
228
+ * this mechanism exists to close.
229
+ */
230
+ private isReadyEnough;
231
+ /**
232
+ * Polls `isReadyEnough` until it's true, the session's pty goes away
233
+ * (killed/exited — it's never going to become ready now), or `timeoutMs`
234
+ * elapses. Used by `submitInput()` only — `write()` (raw terminal
235
+ * keystrokes) must never wait on this, since a human answering the very
236
+ * prompt this is waiting out is exactly how a session becomes ready.
237
+ */
238
+ private waitUntilReady;
239
+ /** Waits for all in-flight registry writes to settle. Useful before process
240
+ * shutdown (and in tests that assert against the on-disk registry). */
241
+ flush(): Promise<void>;
242
+ setTitle(id: string, title: string): void;
243
+ /** Binds (or, with `null`, unbinds) the session's current workflow
244
+ * selection. The caller (rest.ts) owns validating `workflowPath` against
245
+ * the workflow registry and mirroring the binding into
246
+ * HARNESS_CONTEXT_FILE — this only updates the in-memory/persisted
247
+ * registry entry and broadcasts the change like any other status update. */
248
+ setBoundWorkflowPath(id: string, workflowPath: string | null): void;
249
+ private spawn;
250
+ /**
251
+ * Transitions a session to "exited". Shared by node-pty's own `onExit`
252
+ * callback and `kill()`'s missed-event fallback (see `kill()`) — both are
253
+ * racing to be the one that reports a given pty's death, so this is
254
+ * idempotent: a stale/duplicate call (`this.ptys.get(id) !== handle`,
255
+ * i.e. this handle was already replaced or already reported exited) is a
256
+ * silent no-op rather than double-transitioning or clobbering a newer
257
+ * session/handle that's since taken its place (e.g. a resume).
258
+ */
259
+ private markExited;
260
+ /**
261
+ * The single place a session record flips to "exited" — shared by
262
+ * `markExited()` (live-pty deaths), `create()`/`resume()`'s pre-pty
263
+ * failure reconciliation, `kill()`'s stale-record path, and
264
+ * `sweepDeadSessions()`. Returns the persist promise so callers that need
265
+ * the registry durably updated before rethrowing (create/resume) can
266
+ * await it; event-driven callers fire-and-forget it like any other write.
267
+ */
268
+ private transitionExited;
269
+ private emitStatus;
270
+ /** Serializes writes so overlapping persist() calls can't interleave and
271
+ * corrupt the registry file; a failed write doesn't poison later ones. */
272
+ private persist;
273
+ }
274
+ export {};
275
+ //# sourceMappingURL=session-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../src/core/session-manager.ts"],"names":[],"mappings":"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"}