@thinkrun/cli 0.1.27

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 (183) hide show
  1. package/README.md +349 -0
  2. package/dist/bin/thinkrun.d.ts +6 -0
  3. package/dist/bin/thinkrun.d.ts.map +1 -0
  4. package/dist/bin/thinkrun.js +124 -0
  5. package/dist/bin/thinkrun.js.map +1 -0
  6. package/dist/scripts/browse.sh +1107 -0
  7. package/dist/src/adapters/cloud.d.ts +79 -0
  8. package/dist/src/adapters/cloud.d.ts.map +1 -0
  9. package/dist/src/adapters/cloud.js +637 -0
  10. package/dist/src/adapters/cloud.js.map +1 -0
  11. package/dist/src/adapters/index.d.ts +47 -0
  12. package/dist/src/adapters/index.d.ts.map +1 -0
  13. package/dist/src/adapters/index.js +211 -0
  14. package/dist/src/adapters/index.js.map +1 -0
  15. package/dist/src/adapters/local-command-retry.d.ts +12 -0
  16. package/dist/src/adapters/local-command-retry.d.ts.map +1 -0
  17. package/dist/src/adapters/local-command-retry.js +224 -0
  18. package/dist/src/adapters/local-command-retry.js.map +1 -0
  19. package/dist/src/adapters/local.d.ts +136 -0
  20. package/dist/src/adapters/local.d.ts.map +1 -0
  21. package/dist/src/adapters/local.js +1273 -0
  22. package/dist/src/adapters/local.js.map +1 -0
  23. package/dist/src/adapters/types.d.ts +45 -0
  24. package/dist/src/adapters/types.d.ts.map +1 -0
  25. package/dist/src/adapters/types.js +6 -0
  26. package/dist/src/adapters/types.js.map +1 -0
  27. package/dist/src/commands/actions.d.ts +135 -0
  28. package/dist/src/commands/actions.d.ts.map +1 -0
  29. package/dist/src/commands/actions.js +2207 -0
  30. package/dist/src/commands/actions.js.map +1 -0
  31. package/dist/src/commands/agent-init.d.ts +16 -0
  32. package/dist/src/commands/agent-init.d.ts.map +1 -0
  33. package/dist/src/commands/agent-init.js +222 -0
  34. package/dist/src/commands/agent-init.js.map +1 -0
  35. package/dist/src/commands/analyze.d.ts +11 -0
  36. package/dist/src/commands/analyze.d.ts.map +1 -0
  37. package/dist/src/commands/analyze.js +238 -0
  38. package/dist/src/commands/analyze.js.map +1 -0
  39. package/dist/src/commands/cache.d.ts +6 -0
  40. package/dist/src/commands/cache.d.ts.map +1 -0
  41. package/dist/src/commands/cache.js +147 -0
  42. package/dist/src/commands/cache.js.map +1 -0
  43. package/dist/src/commands/cloud.d.ts +6 -0
  44. package/dist/src/commands/cloud.d.ts.map +1 -0
  45. package/dist/src/commands/cloud.js +332 -0
  46. package/dist/src/commands/cloud.js.map +1 -0
  47. package/dist/src/commands/config.d.ts +7 -0
  48. package/dist/src/commands/config.d.ts.map +1 -0
  49. package/dist/src/commands/config.js +208 -0
  50. package/dist/src/commands/config.js.map +1 -0
  51. package/dist/src/commands/doctor.d.ts +127 -0
  52. package/dist/src/commands/doctor.d.ts.map +1 -0
  53. package/dist/src/commands/doctor.js +684 -0
  54. package/dist/src/commands/doctor.js.map +1 -0
  55. package/dist/src/commands/evaluate-helpers.d.ts +6 -0
  56. package/dist/src/commands/evaluate-helpers.d.ts.map +1 -0
  57. package/dist/src/commands/evaluate-helpers.js +13 -0
  58. package/dist/src/commands/evaluate-helpers.js.map +1 -0
  59. package/dist/src/commands/install.d.ts +118 -0
  60. package/dist/src/commands/install.d.ts.map +1 -0
  61. package/dist/src/commands/install.js +975 -0
  62. package/dist/src/commands/install.js.map +1 -0
  63. package/dist/src/commands/release.d.ts +7 -0
  64. package/dist/src/commands/release.d.ts.map +1 -0
  65. package/dist/src/commands/release.js +123 -0
  66. package/dist/src/commands/release.js.map +1 -0
  67. package/dist/src/commands/reset-connection.d.ts +17 -0
  68. package/dist/src/commands/reset-connection.d.ts.map +1 -0
  69. package/dist/src/commands/reset-connection.js +141 -0
  70. package/dist/src/commands/reset-connection.js.map +1 -0
  71. package/dist/src/commands/session-debug.d.ts +23 -0
  72. package/dist/src/commands/session-debug.d.ts.map +1 -0
  73. package/dist/src/commands/session-debug.js +267 -0
  74. package/dist/src/commands/session-debug.js.map +1 -0
  75. package/dist/src/commands/setup.d.ts +53 -0
  76. package/dist/src/commands/setup.d.ts.map +1 -0
  77. package/dist/src/commands/setup.js +249 -0
  78. package/dist/src/commands/setup.js.map +1 -0
  79. package/dist/src/config/store.d.ts +39 -0
  80. package/dist/src/config/store.d.ts.map +1 -0
  81. package/dist/src/config/store.js +290 -0
  82. package/dist/src/config/store.js.map +1 -0
  83. package/dist/src/daemon/access.d.ts +53 -0
  84. package/dist/src/daemon/access.d.ts.map +1 -0
  85. package/dist/src/daemon/access.js +87 -0
  86. package/dist/src/daemon/access.js.map +1 -0
  87. package/dist/src/daemon/bridge-envelope.d.ts +96 -0
  88. package/dist/src/daemon/bridge-envelope.d.ts.map +1 -0
  89. package/dist/src/daemon/bridge-envelope.js +235 -0
  90. package/dist/src/daemon/bridge-envelope.js.map +1 -0
  91. package/dist/src/daemon/utils.d.ts +43 -0
  92. package/dist/src/daemon/utils.d.ts.map +1 -0
  93. package/dist/src/daemon/utils.js +134 -0
  94. package/dist/src/daemon/utils.js.map +1 -0
  95. package/dist/src/errors.d.ts +60 -0
  96. package/dist/src/errors.d.ts.map +1 -0
  97. package/dist/src/errors.js +87 -0
  98. package/dist/src/errors.js.map +1 -0
  99. package/dist/src/local-bridge-timing.d.ts +31 -0
  100. package/dist/src/local-bridge-timing.d.ts.map +1 -0
  101. package/dist/src/local-bridge-timing.js +41 -0
  102. package/dist/src/local-bridge-timing.js.map +1 -0
  103. package/dist/src/obstacle-recovery/classify-script.d.ts +16 -0
  104. package/dist/src/obstacle-recovery/classify-script.d.ts.map +1 -0
  105. package/dist/src/obstacle-recovery/classify-script.js +53 -0
  106. package/dist/src/obstacle-recovery/classify-script.js.map +1 -0
  107. package/dist/src/obstacle-recovery/obstacle-classifier.d.ts +21 -0
  108. package/dist/src/obstacle-recovery/obstacle-classifier.d.ts.map +1 -0
  109. package/dist/src/obstacle-recovery/obstacle-classifier.js +37 -0
  110. package/dist/src/obstacle-recovery/obstacle-classifier.js.map +1 -0
  111. package/dist/src/obstacle-recovery/state-fingerprint.d.ts +26 -0
  112. package/dist/src/obstacle-recovery/state-fingerprint.d.ts.map +1 -0
  113. package/dist/src/obstacle-recovery/state-fingerprint.js +85 -0
  114. package/dist/src/obstacle-recovery/state-fingerprint.js.map +1 -0
  115. package/dist/src/obstacle-recovery/types.d.ts +44 -0
  116. package/dist/src/obstacle-recovery/types.d.ts.map +1 -0
  117. package/dist/src/obstacle-recovery/types.js +16 -0
  118. package/dist/src/obstacle-recovery/types.js.map +1 -0
  119. package/dist/src/output/formatter.d.ts +55 -0
  120. package/dist/src/output/formatter.d.ts.map +1 -0
  121. package/dist/src/output/formatter.js +55 -0
  122. package/dist/src/output/formatter.js.map +1 -0
  123. package/dist/src/output/mode.d.ts +11 -0
  124. package/dist/src/output/mode.d.ts.map +1 -0
  125. package/dist/src/output/mode.js +16 -0
  126. package/dist/src/output/mode.js.map +1 -0
  127. package/dist/src/protected-flow/detector.d.ts +26 -0
  128. package/dist/src/protected-flow/detector.d.ts.map +1 -0
  129. package/dist/src/protected-flow/detector.js +75 -0
  130. package/dist/src/protected-flow/detector.js.map +1 -0
  131. package/dist/src/protected-flow/types.d.ts +24 -0
  132. package/dist/src/protected-flow/types.d.ts.map +1 -0
  133. package/dist/src/protected-flow/types.js +28 -0
  134. package/dist/src/protected-flow/types.js.map +1 -0
  135. package/dist/src/session/agent-identity.d.ts +65 -0
  136. package/dist/src/session/agent-identity.d.ts.map +1 -0
  137. package/dist/src/session/agent-identity.js +133 -0
  138. package/dist/src/session/agent-identity.js.map +1 -0
  139. package/dist/src/session/cli-session-sync.d.ts +72 -0
  140. package/dist/src/session/cli-session-sync.d.ts.map +1 -0
  141. package/dist/src/session/cli-session-sync.js +244 -0
  142. package/dist/src/session/cli-session-sync.js.map +1 -0
  143. package/dist/src/session/context.d.ts +24 -0
  144. package/dist/src/session/context.d.ts.map +1 -0
  145. package/dist/src/session/context.js +165 -0
  146. package/dist/src/session/context.js.map +1 -0
  147. package/dist/src/session/continuity.d.ts +33 -0
  148. package/dist/src/session/continuity.d.ts.map +1 -0
  149. package/dist/src/session/continuity.js +179 -0
  150. package/dist/src/session/continuity.js.map +1 -0
  151. package/dist/src/session/errors.d.ts +9 -0
  152. package/dist/src/session/errors.d.ts.map +1 -0
  153. package/dist/src/session/errors.js +31 -0
  154. package/dist/src/session/errors.js.map +1 -0
  155. package/dist/src/session/local-continuity.d.ts +16 -0
  156. package/dist/src/session/local-continuity.d.ts.map +1 -0
  157. package/dist/src/session/local-continuity.js +146 -0
  158. package/dist/src/session/local-continuity.js.map +1 -0
  159. package/dist/src/session/signal-handler.d.ts +24 -0
  160. package/dist/src/session/signal-handler.d.ts.map +1 -0
  161. package/dist/src/session/signal-handler.js +35 -0
  162. package/dist/src/session/signal-handler.js.map +1 -0
  163. package/dist/src/shared/local-recovery-policy.d.ts +40 -0
  164. package/dist/src/shared/local-recovery-policy.d.ts.map +1 -0
  165. package/dist/src/shared/local-recovery-policy.js +59 -0
  166. package/dist/src/shared/local-recovery-policy.js.map +1 -0
  167. package/dist/src/shared/recovery-state.d.ts +3 -0
  168. package/dist/src/shared/recovery-state.d.ts.map +1 -0
  169. package/dist/src/shared/recovery-state.js +9 -0
  170. package/dist/src/shared/recovery-state.js.map +1 -0
  171. package/dist/src/types.d.ts +131 -0
  172. package/dist/src/types.d.ts.map +1 -0
  173. package/dist/src/types.js +5 -0
  174. package/dist/src/types.js.map +1 -0
  175. package/dist/src/utils.d.ts +50 -0
  176. package/dist/src/utils.d.ts.map +1 -0
  177. package/dist/src/utils.js +147 -0
  178. package/dist/src/utils.js.map +1 -0
  179. package/dist/src/working-location.d.ts +107 -0
  180. package/dist/src/working-location.d.ts.map +1 -0
  181. package/dist/src/working-location.js +651 -0
  182. package/dist/src/working-location.js.map +1 -0
  183. package/package.json +65 -0
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Opt-in CLI session persistence helpers.
3
+ *
4
+ * When a ThinkRun API key is configured, local-mode commands can
5
+ * optionally register a session document in the cloud activity feed so
6
+ * that screenshots and other actions appear in the UI alongside cloud
7
+ * and extension sessions.
8
+ *
9
+ * ALL exported functions are fire-and-forget — they never throw and
10
+ * never block the caller. The sync is a best-effort side-channel; if
11
+ * the cloud API is unreachable the CLI continues to function normally.
12
+ *
13
+ * File written to disk: `~/.thinkrun/local-session-{tabId}.json`
14
+ * (same directory as working-location.json; THINKRUN_LOCK_DIR for
15
+ * test isolation).
16
+ */
17
+ import { existsSync, writeFileSync, readFileSync, unlinkSync } from 'node:fs';
18
+ import { spawnSync } from 'node:child_process';
19
+ import { config } from '../config/store.js';
20
+ import { getCliSessionFilePath } from '../working-location.js';
21
+ import { resolveAgentId } from './agent-identity.js';
22
+ // ─── Abort signal helper ──────────────────────────────────────────────────────
23
+ /**
24
+ * Create an AbortSignal that fires after `ms` milliseconds, backed by a timer
25
+ * that is `unref()`d so it does NOT keep a short-lived CLI process alive.
26
+ *
27
+ * `AbortSignal.timeout(ms)` internally creates a referenced timer; even when
28
+ * the caller fire-and-forgets the fetch, that timer prevents `thinkrun attach`
29
+ * (and similar commands) from exiting for up to `ms` milliseconds after the
30
+ * command otherwise completes. Using an unref'd timer avoids that stall while
31
+ * preserving the network-timeout behaviour for long-running sessions.
32
+ */
33
+ function unrefAbortSignal(ms) {
34
+ const controller = new AbortController();
35
+ const timer = setTimeout(() => controller.abort(), ms);
36
+ // unref() exists in Node.js and Bun — fall back gracefully in other runtimes.
37
+ if (typeof timer.unref === 'function')
38
+ timer.unref();
39
+ // Note: if the fetch settles before the timeout, the setTimeout callback still
40
+ // fires after `ms` and calls abort() on an already-settled signal. This is
41
+ // harmless (aborting a settled signal is a no-op) and not a resource leak.
42
+ return controller.signal;
43
+ }
44
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
45
+ /** Return the API key and validated HTTPS apiUrl, or null if either is absent
46
+ * or insecure (to prevent credential exfiltration to non-HTTPS endpoints). */
47
+ function getApiCredentials() {
48
+ const apiKey = config.get('apiKey');
49
+ if (!apiKey)
50
+ return null;
51
+ const rawApiUrl = config.get('apiUrl') || 'https://api.thinkbrowse.io';
52
+ if (!rawApiUrl.startsWith('https://'))
53
+ return null;
54
+ return { apiKey, apiUrl: rawApiUrl };
55
+ }
56
+ // ─── File I/O ─────────────────────────────────────────────────────────────────
57
+ /**
58
+ * Read the persisted cloud sessionId for a given local tabId.
59
+ * Returns undefined if no session file exists or it is malformed.
60
+ */
61
+ export function readCliSessionId(tabId) {
62
+ try {
63
+ const filePath = getCliSessionFilePath(tabId);
64
+ if (!existsSync(filePath))
65
+ return undefined;
66
+ const data = JSON.parse(readFileSync(filePath, 'utf-8'));
67
+ return typeof data.sessionId === 'string' ? data.sessionId : undefined;
68
+ }
69
+ catch {
70
+ return undefined;
71
+ }
72
+ }
73
+ function writeCliSessionId(tabId, sessionId) {
74
+ try {
75
+ writeFileSync(getCliSessionFilePath(tabId), JSON.stringify({ sessionId, tabId }), 'utf-8');
76
+ }
77
+ catch { /* ignore — best-effort */ }
78
+ }
79
+ function deleteCliSessionFile(tabId) {
80
+ try {
81
+ unlinkSync(getCliSessionFilePath(tabId));
82
+ }
83
+ catch { /* ignore */ }
84
+ }
85
+ // ─── Async helpers (used in normal operation) ─────────────────────────────────
86
+ /**
87
+ * Call POST /api/sessions/local-init to register a CLI session in the
88
+ * cloud activity feed. Persists the returned sessionId to disk.
89
+ *
90
+ * @returns The sessionId on success, undefined on any failure.
91
+ */
92
+ export async function initCliSession(tabId, fetchFn = globalThis.fetch) {
93
+ const creds = getApiCredentials();
94
+ if (!creds)
95
+ return undefined;
96
+ const { apiKey, apiUrl } = creds;
97
+ try {
98
+ const res = await fetchFn(`${apiUrl}/api/sessions/local-init`, {
99
+ method: 'POST',
100
+ headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey },
101
+ body: JSON.stringify({ source: 'cli', tabId, agentId: resolveAgentId() }),
102
+ signal: unrefAbortSignal(10_000),
103
+ });
104
+ if (!res.ok)
105
+ return undefined;
106
+ const body = (await res.json());
107
+ const sessionId = body?.data?.sessionId;
108
+ if (!sessionId)
109
+ return undefined;
110
+ writeCliSessionId(tabId, sessionId);
111
+ return sessionId;
112
+ }
113
+ catch {
114
+ return undefined;
115
+ }
116
+ }
117
+ /**
118
+ * Fire-and-forget: POST a browser action to the cloud session action log.
119
+ * Never throws, never blocks the caller.
120
+ *
121
+ * @param sessionId The cloud session ID returned by initCliSession.
122
+ * @param type Action type — must be in ALLOWED_ACTION_TYPES on the server.
123
+ * @param details Arbitrary key-value pairs describing the action (url, selector, etc.)
124
+ * @param fetchFn Injectable fetch for testing.
125
+ */
126
+ export function syncBrowserAction(sessionId, type, details, fetchFn = globalThis.fetch) {
127
+ const creds = getApiCredentials();
128
+ if (!creds)
129
+ return;
130
+ const { apiKey, apiUrl } = creds;
131
+ // try/catch covers synchronous errors (e.g. JSON.stringify throws, or fetchFn
132
+ // throws synchronously before returning a Promise). The .catch covers async rejection.
133
+ try {
134
+ fetchFn(`${apiUrl}/api/sessions/${sessionId}/local-sync/action`, {
135
+ method: 'POST',
136
+ headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey },
137
+ body: JSON.stringify({ type, details }),
138
+ signal: unrefAbortSignal(10_000),
139
+ }).catch(() => { });
140
+ }
141
+ catch { /* swallow synchronous errors */ }
142
+ }
143
+ /**
144
+ * Fire-and-forget: POST a screenshot action to the cloud session.
145
+ * Never throws, never blocks the caller.
146
+ */
147
+ export function syncScreenshotAction(sessionId, artifactBase64, artifactMimeType, caption, fetchFn = globalThis.fetch) {
148
+ const creds = getApiCredentials();
149
+ if (!creds)
150
+ return;
151
+ const { apiKey, apiUrl } = creds;
152
+ try {
153
+ fetchFn(`${apiUrl}/api/sessions/${sessionId}/local-sync/action`, {
154
+ method: 'POST',
155
+ headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey },
156
+ body: JSON.stringify({ type: 'screenshot', artifactBase64, artifactMimeType, caption }),
157
+ signal: unrefAbortSignal(15_000),
158
+ }).then((res) => {
159
+ if (!res.ok) {
160
+ console.debug(`[thinkrun] syncScreenshotAction: HTTP ${res.status} from server`);
161
+ }
162
+ res.body?.cancel().catch(() => { });
163
+ }).catch(() => { });
164
+ }
165
+ catch {
166
+ // fire-and-forget — synchronous fetch setup errors are intentionally swallowed
167
+ }
168
+ }
169
+ /**
170
+ * Fire-and-forget: PATCH /api/sessions/:sessionId/local-close, then
171
+ * clean up the persisted session file.
172
+ * Never throws, never blocks the caller.
173
+ *
174
+ * The session file is deleted BEFORE the HTTP call to prevent TOCTOU
175
+ * races with a concurrent closeCliSessionSync (e.g. Ctrl-C fires while
176
+ * stopSession is already in flight).
177
+ */
178
+ export function closeCliSession(tabId, status, fetchFn = globalThis.fetch) {
179
+ const sessionId = readCliSessionId(tabId);
180
+ if (!sessionId)
181
+ return;
182
+ // Delete immediately — prevents a concurrent closeCliSessionSync from
183
+ // double-reading the same sessionId and issuing a second PATCH.
184
+ deleteCliSessionFile(tabId);
185
+ const creds = getApiCredentials();
186
+ if (!creds)
187
+ return;
188
+ const { apiKey, apiUrl } = creds;
189
+ fetchFn(`${apiUrl}/api/sessions/${sessionId}/local-close`, {
190
+ method: 'PATCH',
191
+ headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey },
192
+ body: JSON.stringify({ status }),
193
+ signal: unrefAbortSignal(10_000),
194
+ }).catch(() => { });
195
+ // Session file already deleted above; no .finally cleanup needed.
196
+ }
197
+ /**
198
+ * Synchronous version of closeCliSession for use in process exit handlers
199
+ * where async operations are not guaranteed to run to completion.
200
+ *
201
+ * Uses `curl` via spawnSync (-K - to read config from stdin) so the HTTP
202
+ * request completes before the process exits and the API key never appears
203
+ * in `ps aux` / /proc/<pid>/cmdline.
204
+ *
205
+ * The session file is deleted BEFORE the HTTP request to prevent TOCTOU
206
+ * races with a concurrent async closeCliSession call.
207
+ *
208
+ * @param spawnFn — injectable for testing; defaults to node:child_process spawnSync
209
+ */
210
+ export function closeCliSessionSync(tabId, status, spawnFn = spawnSync) {
211
+ const sessionId = readCliSessionId(tabId);
212
+ if (!sessionId)
213
+ return;
214
+ // Delete immediately — prevents TOCTOU with concurrent closeCliSession.
215
+ deleteCliSessionFile(tabId);
216
+ const creds = getApiCredentials();
217
+ if (!creds)
218
+ return;
219
+ const { apiKey, apiUrl } = creds;
220
+ // Sanitize apiKey for curl config interpolation:
221
+ // - strip CR/LF (would terminate the header = "…" line prematurely)
222
+ // - escape `\` and `"` (curl config format: `"` → `\"`, `\` → `\\`)
223
+ const safeKey = apiKey
224
+ .replace(/[\r\n]/g, '')
225
+ .replace(/\\/g, '\\\\')
226
+ .replace(/"/g, '\\"');
227
+ // Pass credentials via curl's -K - (config from stdin) so the API key
228
+ // is never an argument in the process list (not visible in `ps`).
229
+ const curlConfig = [
230
+ `header = "x-api-key: ${safeKey}"`,
231
+ 'header = "Content-Type: application/json"',
232
+ ].join('\n') + '\n';
233
+ try {
234
+ spawnFn('curl', [
235
+ '-s',
236
+ '-X', 'PATCH',
237
+ '-K', '-',
238
+ '-d', JSON.stringify({ status }),
239
+ `${apiUrl}/api/sessions/${sessionId}/local-close`,
240
+ ], { input: curlConfig, timeout: 5_000 });
241
+ }
242
+ catch { /* ignore — best-effort */ }
243
+ }
244
+ //# sourceMappingURL=cli-session-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-session-sync.js","sourceRoot":"","sources":["../../../src/session/cli-session-sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export interface LocalSessionContext {
2
+ mode: 'local';
3
+ tabId: string;
4
+ agentSessionId?: string;
5
+ controlSessionId?: string;
6
+ windowId?: number;
7
+ updatedAt?: string;
8
+ source: 'typed' | 'legacy';
9
+ }
10
+ export interface CloudSessionContext {
11
+ mode: 'cloud';
12
+ sessionId: string;
13
+ source: 'typed' | 'legacy';
14
+ }
15
+ export type SessionContext = LocalSessionContext | CloudSessionContext;
16
+ export declare function hasMixedTypedSessionState(): boolean;
17
+ export declare function getSessionContext(): SessionContext | undefined;
18
+ export declare function getLocalSessionContext(): LocalSessionContext | undefined;
19
+ export declare function getCloudSessionContext(): CloudSessionContext | undefined;
20
+ export declare function setLocalSessionContext(tabId: string, agentSessionId?: string, windowId?: number): void;
21
+ export declare function clearLocalSessionContext(): void;
22
+ export declare function setCloudSessionContext(sessionId: string): void;
23
+ export declare function clearCloudSessionContext(expectedSessionId?: string): void;
24
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/session/context.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC5B;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC5B;AAED,MAAM,MAAM,cAAc,GAAG,mBAAmB,GAAG,mBAAmB,CAAC;AA4FvE,wBAAgB,yBAAyB,IAAI,OAAO,CAEnD;AAED,wBAAgB,iBAAiB,IAAI,cAAc,GAAG,SAAS,CA0C9D;AAED,wBAAgB,sBAAsB,IAAI,mBAAmB,GAAG,SAAS,CAGxE;AAED,wBAAgB,sBAAsB,IAAI,mBAAmB,GAAG,SAAS,CAGxE;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAOtG;AAED,wBAAgB,wBAAwB,IAAI,IAAI,CAU/C;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAI9D;AAED,wBAAgB,wBAAwB,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAezE"}
@@ -0,0 +1,165 @@
1
+ import { config } from '../config/store.js';
2
+ import { mixedSessionStateError } from './errors.js';
3
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
4
+ import { dirname, join } from 'node:path';
5
+ import { getAgentFilePath, resolveAgentId } from './agent-identity.js';
6
+ import { randomUUID } from 'node:crypto';
7
+ import { updateWorkingLocationControlSession } from '../working-location.js';
8
+ function sanitizeFilePart(value) {
9
+ return value.replace(/[^a-zA-Z0-9._-]+/g, '_') || 'default';
10
+ }
11
+ function getPrivateLocalSessionStatePath() {
12
+ const lockDir = dirname(getAgentFilePath());
13
+ return join(lockDir, 'agent-sessions', `${sanitizeFilePart(resolveAgentId())}.json`);
14
+ }
15
+ function readPrivateLocalSessionState() {
16
+ try {
17
+ const path = getPrivateLocalSessionStatePath();
18
+ if (!existsSync(path))
19
+ return undefined;
20
+ const data = JSON.parse(readFileSync(path, 'utf-8'));
21
+ if (typeof data.tabId !== 'string' || data.tabId.length === 0)
22
+ return undefined;
23
+ if (typeof data.controlSessionId !== 'string' || data.controlSessionId.length === 0)
24
+ return undefined;
25
+ return {
26
+ tabId: data.tabId,
27
+ ...(typeof data.agentSessionId === 'string' ? { agentSessionId: data.agentSessionId } : {}),
28
+ controlSessionId: data.controlSessionId,
29
+ ...(typeof data.windowId === 'number' ? { windowId: data.windowId } : {}),
30
+ updatedAt: typeof data.updatedAt === 'string' ? data.updatedAt : new Date(0).toISOString(),
31
+ };
32
+ }
33
+ catch {
34
+ return undefined;
35
+ }
36
+ }
37
+ function writePrivateLocalSessionState(tabId, agentSessionId, controlSessionId, windowId) {
38
+ const path = getPrivateLocalSessionStatePath();
39
+ mkdirSync(dirname(path), { recursive: true });
40
+ const resolvedControlSessionId = controlSessionId ?? agentSessionId ?? `local_${randomUUID()}`;
41
+ const payload = {
42
+ tabId,
43
+ ...(agentSessionId ? { agentSessionId } : {}),
44
+ controlSessionId: resolvedControlSessionId,
45
+ ...(typeof windowId === 'number' ? { windowId } : {}),
46
+ updatedAt: new Date().toISOString(),
47
+ };
48
+ writeFileSync(path, JSON.stringify(payload), 'utf-8');
49
+ updateWorkingLocationControlSession(resolvedControlSessionId);
50
+ }
51
+ function clearPrivateLocalSessionState() {
52
+ try {
53
+ rmSync(getPrivateLocalSessionStatePath(), { force: true });
54
+ }
55
+ catch {
56
+ // best-effort
57
+ }
58
+ }
59
+ function isNumericId(value) {
60
+ return !!value && /^\d+$/.test(value);
61
+ }
62
+ function getLegacyContext() {
63
+ const activeSessionId = config.get('activeSessionId');
64
+ const agentSessionId = config.get('agentSessionId');
65
+ if (!activeSessionId)
66
+ return undefined;
67
+ if (isNumericId(activeSessionId)) {
68
+ return {
69
+ mode: 'local',
70
+ tabId: activeSessionId,
71
+ agentSessionId,
72
+ source: 'legacy',
73
+ };
74
+ }
75
+ return {
76
+ mode: 'cloud',
77
+ sessionId: activeSessionId,
78
+ source: 'legacy',
79
+ };
80
+ }
81
+ export function hasMixedTypedSessionState() {
82
+ return !!config.get('localTabId') && !!config.get('cloudSessionId');
83
+ }
84
+ export function getSessionContext() {
85
+ if (hasMixedTypedSessionState()) {
86
+ throw mixedSessionStateError();
87
+ }
88
+ const localTabId = config.get('localTabId');
89
+ const localAgentSessionId = config.get('localAgentSessionId');
90
+ const cloudSessionId = config.get('cloudSessionId');
91
+ const privateLocalState = readPrivateLocalSessionState();
92
+ if (localTabId) {
93
+ const privateAgentSessionId = privateLocalState?.tabId === localTabId
94
+ ? privateLocalState.agentSessionId
95
+ : undefined;
96
+ return {
97
+ mode: 'local',
98
+ tabId: localTabId,
99
+ ...(privateAgentSessionId || localAgentSessionId
100
+ ? { agentSessionId: privateAgentSessionId ?? localAgentSessionId }
101
+ : {}),
102
+ ...(privateLocalState?.tabId === localTabId && privateLocalState.controlSessionId
103
+ ? { controlSessionId: privateLocalState.controlSessionId }
104
+ : {}),
105
+ ...(privateLocalState?.tabId === localTabId && typeof privateLocalState.windowId === 'number'
106
+ ? { windowId: privateLocalState.windowId }
107
+ : {}),
108
+ ...(privateLocalState?.tabId === localTabId && typeof privateLocalState.updatedAt === 'string'
109
+ ? { updatedAt: privateLocalState.updatedAt }
110
+ : {}),
111
+ source: 'typed',
112
+ };
113
+ }
114
+ if (cloudSessionId) {
115
+ return {
116
+ mode: 'cloud',
117
+ sessionId: cloudSessionId,
118
+ source: 'typed',
119
+ };
120
+ }
121
+ return getLegacyContext();
122
+ }
123
+ export function getLocalSessionContext() {
124
+ const context = getSessionContext();
125
+ return context?.mode === 'local' ? context : undefined;
126
+ }
127
+ export function getCloudSessionContext() {
128
+ const context = getSessionContext();
129
+ return context?.mode === 'cloud' ? context : undefined;
130
+ }
131
+ export function setLocalSessionContext(tabId, agentSessionId, windowId) {
132
+ config.set('localTabId', tabId);
133
+ config.set('activeSessionId', tabId);
134
+ config.delete('cloudSessionId');
135
+ config.delete('localAgentSessionId');
136
+ config.delete('agentSessionId');
137
+ writePrivateLocalSessionState(tabId, agentSessionId, undefined, windowId);
138
+ }
139
+ export function clearLocalSessionContext() {
140
+ config.delete('localTabId');
141
+ config.delete('localAgentSessionId');
142
+ clearPrivateLocalSessionState();
143
+ if (isNumericId(config.get('activeSessionId'))) {
144
+ config.delete('activeSessionId');
145
+ }
146
+ config.delete('agentSessionId');
147
+ }
148
+ export function setCloudSessionContext(sessionId) {
149
+ clearLocalSessionContext();
150
+ config.set('cloudSessionId', sessionId);
151
+ config.set('activeSessionId', sessionId);
152
+ }
153
+ export function clearCloudSessionContext(expectedSessionId) {
154
+ const cloudSessionId = config.get('cloudSessionId');
155
+ const activeSessionId = config.get('activeSessionId');
156
+ if (!expectedSessionId || cloudSessionId === expectedSessionId) {
157
+ config.delete('cloudSessionId');
158
+ }
159
+ if (activeSessionId &&
160
+ !isNumericId(activeSessionId) &&
161
+ (!expectedSessionId || activeSessionId === expectedSessionId)) {
162
+ config.delete('activeSessionId');
163
+ }
164
+ }
165
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/session/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { WorkingLocation } from '../working-location.js';
2
+ export declare const DEFAULT_CONTINUITY_STALE_LEASE_WINDOW_MS: number;
3
+ export type LocalContinuityState = 'unbound' | 'same_controller_resumable' | 'same_controller_missing_runtime' | 'foreign_controller_live' | 'stale_reclaimable' | 'ambiguous_blocked';
4
+ export type RuntimeSessionState = 'recognized' | 'missing' | 'unknown';
5
+ export type TabIdentityState = 'verified' | 'mismatch' | 'unknown';
6
+ export type LegacyStateStatus = 'current' | 'legacy_safe' | 'legacy_conflict';
7
+ export interface ContinuityPersistedBinding {
8
+ tabId: string;
9
+ agentSessionId?: string;
10
+ }
11
+ export interface ContinuityEvidence {
12
+ currentAgentId: string;
13
+ persistedBinding?: ContinuityPersistedBinding | null;
14
+ workingLocation?: Pick<WorkingLocation, 'tabId' | 'agentId' | 'controlSessionId' | 'setAt'> | null;
15
+ lockOwner?: Pick<WorkingLocation, 'tabId' | 'agentId' | 'controlSessionId' | 'setAt'> | null;
16
+ runtimeSessionState: RuntimeSessionState;
17
+ ownerShellAlive?: boolean | null;
18
+ tabIdentityState?: TabIdentityState;
19
+ legacyStateStatus?: LegacyStateStatus;
20
+ staleLeaseWindowMs?: number;
21
+ now?: Date | string | number;
22
+ }
23
+ export interface ContinuityAssessment {
24
+ state: LocalContinuityState;
25
+ effectiveTabId: string | null;
26
+ sameController: boolean;
27
+ canRepairRuntime: boolean;
28
+ canReclaim: boolean;
29
+ reason: 'no_binding' | 'same_controller_live_runtime' | 'same_controller_runtime_missing' | 'runtime_status_unknown' | 'foreign_controller_live' | 'stale_lease_reclaimable' | 'tab_identity_mismatch' | 'legacy_state_conflict' | 'conflicting_controller_evidence' | 'missing_continuity_proof' | 'insufficient_stale_evidence';
30
+ }
31
+ export declare function isContinuityLeaseStale(setAt: Date | string | number | undefined, now?: Date | string | number, staleLeaseWindowMs?: number): boolean;
32
+ export declare function assessLocalContinuity(evidence: ContinuityEvidence): ContinuityAssessment;
33
+ //# sourceMappingURL=continuity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"continuity.d.ts","sourceRoot":"","sources":["../../../src/session/continuity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAI9D,eAAO,MAAM,wCAAwC,QAAqB,CAAC;AAE3E,MAAM,MAAM,oBAAoB,GAC5B,SAAS,GACT,2BAA2B,GAC3B,iCAAiC,GACjC,yBAAyB,GACzB,mBAAmB,GACnB,mBAAmB,CAAC;AAExB,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,SAAS,GAAG,SAAS,CAAC;AACvE,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC;AACnE,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,aAAa,GAAG,iBAAiB,CAAC;AAE9E,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,0BAA0B,GAAG,IAAI,CAAC;IACrD,eAAe,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,SAAS,GAAG,kBAAkB,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC;IACnG,SAAS,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,SAAS,GAAG,kBAAkB,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7F,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,eAAe,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,GAAG,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,oBAAoB,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EACF,YAAY,GACZ,8BAA8B,GAC9B,iCAAiC,GACjC,wBAAwB,GACxB,yBAAyB,GACzB,yBAAyB,GACzB,uBAAuB,GACvB,uBAAuB,GACvB,iCAAiC,GACjC,0BAA0B,GAC1B,6BAA6B,CAAC;CACnC;AAgBD,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,EACzC,GAAG,GAAE,IAAI,GAAG,MAAM,GAAG,MAAmB,EACxC,kBAAkB,GAAE,MAAiD,GACpE,OAAO,CAKT;AA6CD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,oBAAoB,CA6HxF"}