@sentropic/h2a-runtime 0.81.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 (253) hide show
  1. package/dist/account-pool.d.ts +168 -0
  2. package/dist/account-pool.d.ts.map +1 -0
  3. package/dist/account-pool.js +385 -0
  4. package/dist/account-pool.js.map +1 -0
  5. package/dist/agents-projection.d.ts +56 -0
  6. package/dist/agents-projection.d.ts.map +1 -0
  7. package/dist/agents-projection.js +82 -0
  8. package/dist/agents-projection.js.map +1 -0
  9. package/dist/attach.d.ts +75 -0
  10. package/dist/attach.d.ts.map +1 -0
  11. package/dist/attach.js +432 -0
  12. package/dist/attach.js.map +1 -0
  13. package/dist/auth-bundle.d.ts +21 -0
  14. package/dist/auth-bundle.d.ts.map +1 -0
  15. package/dist/auth-bundle.js +112 -0
  16. package/dist/auth-bundle.js.map +1 -0
  17. package/dist/auth-diagnostics.d.ts +18 -0
  18. package/dist/auth-diagnostics.d.ts.map +1 -0
  19. package/dist/auth-diagnostics.js +23 -0
  20. package/dist/auth-diagnostics.js.map +1 -0
  21. package/dist/auth-login.d.ts +9 -0
  22. package/dist/auth-login.d.ts.map +1 -0
  23. package/dist/auth-login.js +21 -0
  24. package/dist/auth-login.js.map +1 -0
  25. package/dist/auth-refresh.d.ts +32 -0
  26. package/dist/auth-refresh.d.ts.map +1 -0
  27. package/dist/auth-refresh.js +83 -0
  28. package/dist/auth-refresh.js.map +1 -0
  29. package/dist/auth-tools.d.ts +55 -0
  30. package/dist/auth-tools.d.ts.map +1 -0
  31. package/dist/auth-tools.js +163 -0
  32. package/dist/auth-tools.js.map +1 -0
  33. package/dist/browser-bridge-local.d.ts +27 -0
  34. package/dist/browser-bridge-local.d.ts.map +1 -0
  35. package/dist/browser-bridge-local.js +51 -0
  36. package/dist/browser-bridge-local.js.map +1 -0
  37. package/dist/browser.d.ts +53 -0
  38. package/dist/browser.d.ts.map +1 -0
  39. package/dist/browser.js +61 -0
  40. package/dist/browser.js.map +1 -0
  41. package/dist/conductor-launch.d.ts +179 -0
  42. package/dist/conductor-launch.d.ts.map +1 -0
  43. package/dist/conductor-launch.js +414 -0
  44. package/dist/conductor-launch.js.map +1 -0
  45. package/dist/config.d.ts +182 -0
  46. package/dist/config.d.ts.map +1 -0
  47. package/dist/config.js +334 -0
  48. package/dist/config.js.map +1 -0
  49. package/dist/conv-guard.d.ts +76 -0
  50. package/dist/conv-guard.d.ts.map +1 -0
  51. package/dist/conv-guard.js +131 -0
  52. package/dist/conv-guard.js.map +1 -0
  53. package/dist/convsync.d.ts +24 -0
  54. package/dist/convsync.d.ts.map +1 -0
  55. package/dist/convsync.js +108 -0
  56. package/dist/convsync.js.map +1 -0
  57. package/dist/cred-health.d.ts +96 -0
  58. package/dist/cred-health.d.ts.map +1 -0
  59. package/dist/cred-health.js +170 -0
  60. package/dist/cred-health.js.map +1 -0
  61. package/dist/delegate.d.ts +406 -0
  62. package/dist/delegate.d.ts.map +1 -0
  63. package/dist/delegate.js +739 -0
  64. package/dist/delegate.js.map +1 -0
  65. package/dist/enroll.d.ts +91 -0
  66. package/dist/enroll.d.ts.map +1 -0
  67. package/dist/enroll.js +248 -0
  68. package/dist/enroll.js.map +1 -0
  69. package/dist/fanout.d.ts +63 -0
  70. package/dist/fanout.d.ts.map +1 -0
  71. package/dist/fanout.js +115 -0
  72. package/dist/fanout.js.map +1 -0
  73. package/dist/forward.d.ts +66 -0
  74. package/dist/forward.d.ts.map +1 -0
  75. package/dist/forward.js +141 -0
  76. package/dist/forward.js.map +1 -0
  77. package/dist/gitdiff.d.ts +31 -0
  78. package/dist/gitdiff.d.ts.map +1 -0
  79. package/dist/gitdiff.js +133 -0
  80. package/dist/gitdiff.js.map +1 -0
  81. package/dist/h2a-bridge.d.ts +102 -0
  82. package/dist/h2a-bridge.d.ts.map +1 -0
  83. package/dist/h2a-bridge.js +333 -0
  84. package/dist/h2a-bridge.js.map +1 -0
  85. package/dist/h2a-jobs.d.ts +235 -0
  86. package/dist/h2a-jobs.d.ts.map +1 -0
  87. package/dist/h2a-jobs.js +388 -0
  88. package/dist/h2a-jobs.js.map +1 -0
  89. package/dist/h2a-ping.d.ts +38 -0
  90. package/dist/h2a-ping.d.ts.map +1 -0
  91. package/dist/h2a-ping.js +58 -0
  92. package/dist/h2a-ping.js.map +1 -0
  93. package/dist/index.d.ts +98 -0
  94. package/dist/index.d.ts.map +1 -0
  95. package/dist/index.js +5887 -0
  96. package/dist/index.js.map +1 -0
  97. package/dist/interactive-throttle.d.ts +164 -0
  98. package/dist/interactive-throttle.d.ts.map +1 -0
  99. package/dist/interactive-throttle.js +194 -0
  100. package/dist/interactive-throttle.js.map +1 -0
  101. package/dist/lineage-client.d.ts +77 -0
  102. package/dist/lineage-client.d.ts.map +1 -0
  103. package/dist/lineage-client.js +117 -0
  104. package/dist/lineage-client.js.map +1 -0
  105. package/dist/lineage-lease.d.ts +152 -0
  106. package/dist/lineage-lease.d.ts.map +1 -0
  107. package/dist/lineage-lease.js +303 -0
  108. package/dist/lineage-lease.js.map +1 -0
  109. package/dist/llm-gateway-runtime/accounts.d.ts +48 -0
  110. package/dist/llm-gateway-runtime/accounts.d.ts.map +1 -0
  111. package/dist/llm-gateway-runtime/accounts.js +226 -0
  112. package/dist/llm-gateway-runtime/accounts.js.map +1 -0
  113. package/dist/llm-gateway-runtime/index.d.ts +4 -0
  114. package/dist/llm-gateway-runtime/index.d.ts.map +1 -0
  115. package/dist/llm-gateway-runtime/index.js +58 -0
  116. package/dist/llm-gateway-runtime/index.js.map +1 -0
  117. package/dist/llm-gateway-runtime/model-catalog.d.ts +36 -0
  118. package/dist/llm-gateway-runtime/model-catalog.d.ts.map +1 -0
  119. package/dist/llm-gateway-runtime/model-catalog.js +146 -0
  120. package/dist/llm-gateway-runtime/model-catalog.js.map +1 -0
  121. package/dist/llm-gateway-runtime/proxy-anthropic.d.ts +3 -0
  122. package/dist/llm-gateway-runtime/proxy-anthropic.d.ts.map +1 -0
  123. package/dist/llm-gateway-runtime/proxy-anthropic.js +139 -0
  124. package/dist/llm-gateway-runtime/proxy-anthropic.js.map +1 -0
  125. package/dist/llm-gateway-runtime/proxy-openai.d.ts +117 -0
  126. package/dist/llm-gateway-runtime/proxy-openai.d.ts.map +1 -0
  127. package/dist/llm-gateway-runtime/proxy-openai.js +1132 -0
  128. package/dist/llm-gateway-runtime/proxy-openai.js.map +1 -0
  129. package/dist/llm-gateway-runtime/session-ledger.d.ts +32 -0
  130. package/dist/llm-gateway-runtime/session-ledger.d.ts.map +1 -0
  131. package/dist/llm-gateway-runtime/session-ledger.js +62 -0
  132. package/dist/llm-gateway-runtime/session-ledger.js.map +1 -0
  133. package/dist/llm-gateway-runtime/sticky.d.ts +40 -0
  134. package/dist/llm-gateway-runtime/sticky.d.ts.map +1 -0
  135. package/dist/llm-gateway-runtime/sticky.js +254 -0
  136. package/dist/llm-gateway-runtime/sticky.js.map +1 -0
  137. package/dist/llm-mesh.d.ts +102 -0
  138. package/dist/llm-mesh.d.ts.map +1 -0
  139. package/dist/llm-mesh.js +433 -0
  140. package/dist/llm-mesh.js.map +1 -0
  141. package/dist/migrate-candidates.d.ts +35 -0
  142. package/dist/migrate-candidates.d.ts.map +1 -0
  143. package/dist/migrate-candidates.js +128 -0
  144. package/dist/migrate-candidates.js.map +1 -0
  145. package/dist/migrate.d.ts +125 -0
  146. package/dist/migrate.d.ts.map +1 -0
  147. package/dist/migrate.js +561 -0
  148. package/dist/migrate.js.map +1 -0
  149. package/dist/plugin-manifest.d.ts +143 -0
  150. package/dist/plugin-manifest.d.ts.map +1 -0
  151. package/dist/plugin-manifest.js +233 -0
  152. package/dist/plugin-manifest.js.map +1 -0
  153. package/dist/plugin.d.ts +274 -0
  154. package/dist/plugin.d.ts.map +1 -0
  155. package/dist/plugin.js +919 -0
  156. package/dist/plugin.js.map +1 -0
  157. package/dist/pod-liveness.d.ts +51 -0
  158. package/dist/pod-liveness.d.ts.map +1 -0
  159. package/dist/pod-liveness.js +80 -0
  160. package/dist/pod-liveness.js.map +1 -0
  161. package/dist/profile-menu.d.ts +7 -0
  162. package/dist/profile-menu.d.ts.map +1 -0
  163. package/dist/profile-menu.js +52 -0
  164. package/dist/profile-menu.js.map +1 -0
  165. package/dist/profiles.d.ts +23 -0
  166. package/dist/profiles.d.ts.map +1 -0
  167. package/dist/profiles.js +66 -0
  168. package/dist/profiles.js.map +1 -0
  169. package/dist/protocol-local.d.ts +27 -0
  170. package/dist/protocol-local.d.ts.map +1 -0
  171. package/dist/protocol-local.js +12 -0
  172. package/dist/protocol-local.js.map +1 -0
  173. package/dist/pty.d.ts +26 -0
  174. package/dist/pty.d.ts.map +1 -0
  175. package/dist/pty.js +45 -0
  176. package/dist/pty.js.map +1 -0
  177. package/dist/readiness.d.ts +38 -0
  178. package/dist/readiness.d.ts.map +1 -0
  179. package/dist/readiness.js +169 -0
  180. package/dist/readiness.js.map +1 -0
  181. package/dist/registry.d.ts +258 -0
  182. package/dist/registry.d.ts.map +1 -0
  183. package/dist/registry.js +570 -0
  184. package/dist/registry.js.map +1 -0
  185. package/dist/relaunch.d.ts +52 -0
  186. package/dist/relaunch.d.ts.map +1 -0
  187. package/dist/relaunch.js +76 -0
  188. package/dist/relaunch.js.map +1 -0
  189. package/dist/restore.d.ts +165 -0
  190. package/dist/restore.d.ts.map +1 -0
  191. package/dist/restore.js +530 -0
  192. package/dist/restore.js.map +1 -0
  193. package/dist/run.d.ts +29 -0
  194. package/dist/run.d.ts.map +1 -0
  195. package/dist/run.js +206 -0
  196. package/dist/run.js.map +1 -0
  197. package/dist/secrets.d.ts +25 -0
  198. package/dist/secrets.d.ts.map +1 -0
  199. package/dist/secrets.js +98 -0
  200. package/dist/secrets.js.map +1 -0
  201. package/dist/session-restore.d.ts +26 -0
  202. package/dist/session-restore.d.ts.map +1 -0
  203. package/dist/session-restore.js +122 -0
  204. package/dist/session-restore.js.map +1 -0
  205. package/dist/skills-sync.d.ts +126 -0
  206. package/dist/skills-sync.d.ts.map +1 -0
  207. package/dist/skills-sync.js +255 -0
  208. package/dist/skills-sync.js.map +1 -0
  209. package/dist/smoke.d.ts +23 -0
  210. package/dist/smoke.d.ts.map +1 -0
  211. package/dist/smoke.js +138 -0
  212. package/dist/smoke.js.map +1 -0
  213. package/dist/soft-refresh.d.ts +107 -0
  214. package/dist/soft-refresh.d.ts.map +1 -0
  215. package/dist/soft-refresh.js +426 -0
  216. package/dist/soft-refresh.js.map +1 -0
  217. package/dist/sync-status.d.ts +22 -0
  218. package/dist/sync-status.d.ts.map +1 -0
  219. package/dist/sync-status.js +41 -0
  220. package/dist/sync-status.js.map +1 -0
  221. package/dist/sync.d.ts +77 -0
  222. package/dist/sync.d.ts.map +1 -0
  223. package/dist/sync.js +302 -0
  224. package/dist/sync.js.map +1 -0
  225. package/dist/throttle-signatures.d.ts +43 -0
  226. package/dist/throttle-signatures.d.ts.map +1 -0
  227. package/dist/throttle-signatures.js +116 -0
  228. package/dist/throttle-signatures.js.map +1 -0
  229. package/dist/tmux.d.ts +286 -0
  230. package/dist/tmux.d.ts.map +1 -0
  231. package/dist/tmux.js +970 -0
  232. package/dist/tmux.js.map +1 -0
  233. package/dist/tunnel.d.ts +25 -0
  234. package/dist/tunnel.d.ts.map +1 -0
  235. package/dist/tunnel.js +127 -0
  236. package/dist/tunnel.js.map +1 -0
  237. package/dist/workspace-merge.d.ts +17 -0
  238. package/dist/workspace-merge.d.ts.map +1 -0
  239. package/dist/workspace-merge.js +153 -0
  240. package/dist/workspace-merge.js.map +1 -0
  241. package/dist/workspace-sync-incremental.d.ts +64 -0
  242. package/dist/workspace-sync-incremental.d.ts.map +1 -0
  243. package/dist/workspace-sync-incremental.js +199 -0
  244. package/dist/workspace-sync-incremental.js.map +1 -0
  245. package/dist/workspace-sync.d.ts +3 -0
  246. package/dist/workspace-sync.d.ts.map +1 -0
  247. package/dist/workspace-sync.js +187 -0
  248. package/dist/workspace-sync.js.map +1 -0
  249. package/dist/workspace.d.ts +70 -0
  250. package/dist/workspace.d.ts.map +1 -0
  251. package/dist/workspace.js +173 -0
  252. package/dist/workspace.js.map +1 -0
  253. package/package.json +44 -0
@@ -0,0 +1,570 @@
1
+ /**
2
+ * Live-session registry — the source of truth for `remote ls` / `remote
3
+ * restore`, so they stop GUESSING sessions from filesystem mtimes.
4
+ *
5
+ * Entries land here from:
6
+ * - `remote run` (source "run" — local tmux sessions),
7
+ * - Claude Code hooks (source "hook" — `remote enroll --hook claude-*`),
8
+ * - the restore scanner (source "scan" — legacy fallback),
9
+ * - the control-plane (source "remote" — reconciled by the caller).
10
+ *
11
+ * The file is `<configDir>/registry.json`, written atomically (tmp + rename).
12
+ * Every function takes an optional explicit path so tests never touch the real
13
+ * config dir (default path honors REMOTE_CLI_CONFIG_HOME like config.ts).
14
+ */
15
+ import { spawnSync } from "node:child_process";
16
+ import { closeSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, writeFileSync, } from "node:fs";
17
+ import { uptime } from "node:os";
18
+ import { dirname, join } from "node:path";
19
+ import { getLayoutConfig, resolveConfigPath } from "./config.js";
20
+ import { listLocalSessions } from "./tmux.js";
21
+ /** System boot time in ms epoch (now minus uptime). */
22
+ function defaultBootTimeMs() {
23
+ return Date.now() - uptime() * 1000;
24
+ }
25
+ export function resolveRegistryPath() {
26
+ return join(dirname(resolveConfigPath()), "registry.json");
27
+ }
28
+ export function loadRegistry(path = resolveRegistryPath()) {
29
+ try {
30
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
31
+ const entries = parsed?.entries;
32
+ if (!Array.isArray(entries))
33
+ return [];
34
+ return entries.filter(isRegistryEntry);
35
+ }
36
+ catch {
37
+ // missing or corrupt file -> empty registry (it is rebuilt by enrolment)
38
+ return [];
39
+ }
40
+ }
41
+ function isRegistryEntry(raw) {
42
+ if (!raw || typeof raw !== "object")
43
+ return false;
44
+ const e = raw;
45
+ return (typeof e.id === "string" &&
46
+ (e.tool === "claude" || e.tool === "codex" || e.tool === "agy") &&
47
+ (e.kind === "local-tmux" || e.kind === "local" || e.kind === "remote") &&
48
+ typeof e.cwd === "string" &&
49
+ typeof e.enrolledAt === "string" &&
50
+ typeof e.lastSeenAt === "string" &&
51
+ (e.source === "run" ||
52
+ e.source === "hook" ||
53
+ e.source === "scan" ||
54
+ e.source === "remote"));
55
+ }
56
+ /** Atomic write: tmp file in the same dir, then rename. */
57
+ function saveRegistry(entries, path) {
58
+ mkdirSync(dirname(path), { recursive: true });
59
+ const tmp = `${path}.tmp.${process.pid}`;
60
+ writeFileSync(tmp, JSON.stringify({ version: 1, entries }, null, 2), "utf8");
61
+ renameSync(tmp, path);
62
+ }
63
+ // ---------------------------------------------------------------------------
64
+ // Cross-process lock for load-modify-save mutations (S2/S3 fix).
65
+ //
66
+ // The registry is read-modified-written by CONCURRENT processes — `delegate`,
67
+ // the conductor, and the claude SessionEnd hook can all mutate it at once.
68
+ // Without a lock, two writers each load the same snapshot, modify a disjoint
69
+ // entry, and the last `saveRegistry` wins → the other's enroll/advance is LOST.
70
+ // The same race makes the concurrency cap leaky: `delegate` checks
71
+ // `hasFreeSlot` then enrolls-as-running in two steps, so N delegations racing
72
+ // can all see a free slot and overshoot the cap.
73
+ //
74
+ // The registry is LOCAL ONLY (the CLI writes it; pods never touch it — they have
75
+ // no access to ~/.config/.../registry.json), so a LOCAL file lock is sufficient
76
+ // — there is no cross-host writer to coordinate with. We use an exclusive
77
+ // lockfile (`<path>.lock`, O_CREAT|O_EXCL) with a bounded spin and stale-lock
78
+ // takeover, NOT a real OS flock(2): exclusive-create on the SAME local fs is the
79
+ // portable primitive here (Node has no flock), and a crashed holder is recovered
80
+ // by the staleness break below.
81
+ // ---------------------------------------------------------------------------
82
+ /** Spin parameters for the lockfile (bounded — a deadlock must never hang a hook). */
83
+ const LOCK_STALE_MS = 10_000; // a lockfile older than this is assumed orphaned
84
+ const LOCK_SPIN_MS = 5; // busy-wait granularity between acquire attempts
85
+ const LOCK_MAX_WAIT_MS = 4_000; // give up waiting after this (then proceed best-effort)
86
+ function lockPath(path) {
87
+ return `${path}.lock`;
88
+ }
89
+ /** Busy-wait `ms` without a timer (we are holding a process-wide critical section). */
90
+ function spinSleep(ms) {
91
+ const end = Date.now() + ms;
92
+ while (Date.now() < end) {
93
+ // tight spin — ms is tiny (LOCK_SPIN_MS); a registry mutation is sub-ms.
94
+ }
95
+ }
96
+ /**
97
+ * Acquire the registry lockfile (exclusive create). Returns the fd on success,
98
+ * or undefined if it could not be acquired within LOCK_MAX_WAIT_MS (the caller
99
+ * then proceeds best-effort — a slow lock must NEVER take down a claude hook).
100
+ * Breaks a STALE lock (holder crashed) by age.
101
+ */
102
+ function acquireLock(path) {
103
+ const lp = lockPath(path);
104
+ mkdirSync(dirname(path), { recursive: true });
105
+ const deadline = Date.now() + LOCK_MAX_WAIT_MS;
106
+ for (;;) {
107
+ try {
108
+ const fd = openSync(lp, "wx"); // O_CREAT|O_EXCL|O_WRONLY
109
+ return fd;
110
+ }
111
+ catch {
112
+ // Held — break it if it is stale (a crashed holder left it behind).
113
+ try {
114
+ const age = Date.now() - statSync(lp).mtimeMs;
115
+ if (age > LOCK_STALE_MS) {
116
+ rmSync(lp, { force: true });
117
+ continue; // retry the exclusive create immediately
118
+ }
119
+ }
120
+ catch {
121
+ // raced with the holder releasing it → just retry the create
122
+ }
123
+ if (Date.now() >= deadline)
124
+ return undefined; // give up, proceed best-effort
125
+ spinSleep(LOCK_SPIN_MS);
126
+ }
127
+ }
128
+ }
129
+ function releaseLock(fd, path) {
130
+ try {
131
+ closeSync(fd);
132
+ }
133
+ catch {
134
+ // already closed
135
+ }
136
+ try {
137
+ rmSync(lockPath(path), { force: true });
138
+ }
139
+ catch {
140
+ // already gone
141
+ }
142
+ }
143
+ /**
144
+ * Run `fn` under the registry lock: load the current entries, let `fn` mutate
145
+ * them (and compute a return value), then persist atomically — all inside ONE
146
+ * critical section, so concurrent processes serialize and no enroll/advance is
147
+ * lost. `fn` returns `{ entries, result, save? }`: `entries` is what to save
148
+ * (return the same array you mutated), `result` is passed back to the caller, and
149
+ * `save:false` skips the write entirely (a read-only no-op must not rewrite — nor
150
+ * create — the file). If the lock can't be taken (a crashed holder, contention
151
+ * storm), we proceed WITHOUT it rather than block a hook — best-effort,
152
+ * last-writer-wins as before. Exported for tests.
153
+ */
154
+ export function withRegistryLock(path, fn) {
155
+ const fd = acquireLock(path);
156
+ try {
157
+ const { entries, result, save } = fn(loadRegistry(path));
158
+ if (save !== false)
159
+ saveRegistry(entries, path);
160
+ return result;
161
+ }
162
+ finally {
163
+ if (fd !== undefined)
164
+ releaseLock(fd, path);
165
+ }
166
+ }
167
+ /**
168
+ * Upsert by id. A re-enroll refreshes lastSeenAt, merges the new fields over
169
+ * the stored ones, and REVIVES an ended entry (endedAt is dropped) — e.g. a
170
+ * claude SessionStart on a resumed conversation.
171
+ */
172
+ export function enroll(input, path = resolveRegistryPath()) {
173
+ return withRegistryLock(path, (entries) => {
174
+ const entry = applyEnroll(entries, input);
175
+ return { entries, result: entry };
176
+ });
177
+ }
178
+ /**
179
+ * Upsert `input` into `entries` IN PLACE and return the resulting entry. Pure
180
+ * over the array (no fs); shared by `enroll` (under the lock) and the atomic
181
+ * check-cap-and-enroll helper. The lock is held by the caller.
182
+ */
183
+ function applyEnroll(entries, input) {
184
+ const now = new Date().toISOString();
185
+ const idx = entries.findIndex((e) => e.id === input.id);
186
+ const prev = idx >= 0 ? entries[idx] : undefined;
187
+ const entry = {
188
+ id: input.id,
189
+ tool: input.tool,
190
+ kind: input.kind,
191
+ cwd: input.cwd,
192
+ source: input.source,
193
+ enrolledAt: prev?.enrolledAt ?? now,
194
+ lastSeenAt: now,
195
+ };
196
+ const label = input.label ?? prev?.label;
197
+ if (label !== undefined)
198
+ entry.label = label;
199
+ const convId = input.convId ?? prev?.convId;
200
+ if (convId !== undefined)
201
+ entry.convId = convId;
202
+ const remoteId = input.remoteId ?? prev?.remoteId;
203
+ if (remoteId !== undefined)
204
+ entry.remoteId = remoteId;
205
+ const tmuxSession = input.tmuxSession ?? prev?.tmuxSession;
206
+ if (tmuxSession !== undefined)
207
+ entry.tmuxSession = tmuxSession;
208
+ const pid = input.pid ?? prev?.pid;
209
+ if (pid !== undefined)
210
+ entry.pid = pid;
211
+ const role = input.role ?? prev?.role;
212
+ if (role !== undefined)
213
+ entry.role = role;
214
+ const jobState = input.jobState ?? prev?.jobState;
215
+ if (jobState !== undefined)
216
+ entry.jobState = jobState;
217
+ const parent = input.parent ?? prev?.parent;
218
+ if (parent !== undefined)
219
+ entry.parent = parent;
220
+ const task = input.task ?? prev?.task;
221
+ if (task !== undefined)
222
+ entry.task = task;
223
+ const callbackTo = input.callbackTo ?? prev?.callbackTo;
224
+ if (callbackTo !== undefined)
225
+ entry.callbackTo = callbackTo;
226
+ const remoteTarget = input.remoteTarget ?? prev?.remoteTarget;
227
+ if (remoteTarget !== undefined)
228
+ entry.remoteTarget = remoteTarget;
229
+ const headless = input.headless ?? prev?.headless;
230
+ if (headless !== undefined)
231
+ entry.headless = headless;
232
+ const originCwd = input.originCwd ?? prev?.originCwd;
233
+ if (originCwd !== undefined)
234
+ entry.originCwd = originCwd;
235
+ const explicitCwd = input.explicitCwd ?? prev?.explicitCwd;
236
+ if (explicitCwd !== undefined)
237
+ entry.explicitCwd = explicitCwd;
238
+ const depthBudget = input.depthBudget ?? prev?.depthBudget;
239
+ if (depthBudget !== undefined)
240
+ entry.depthBudget = depthBudget;
241
+ const trackWp = input.trackWp ?? prev?.trackWp;
242
+ if (trackWp !== undefined)
243
+ entry.trackWp = trackWp;
244
+ const throttle = input.throttle ?? prev?.throttle;
245
+ if (throttle !== undefined)
246
+ entry.throttle = throttle;
247
+ const model = input.model ?? prev?.model;
248
+ if (model !== undefined)
249
+ entry.model = model;
250
+ const effort = input.effort ?? prev?.effort;
251
+ if (effort !== undefined)
252
+ entry.effort = effort;
253
+ const gatewayMode = input.gatewayMode ?? prev?.gatewayMode;
254
+ if (gatewayMode !== undefined)
255
+ entry.gatewayMode = gatewayMode;
256
+ if (idx >= 0)
257
+ entries[idx] = entry;
258
+ else
259
+ entries.push(entry);
260
+ return entry;
261
+ }
262
+ /**
263
+ * ATOMIC "is there a free slot? → enroll-as-running" (S3 fix). The cap check and
264
+ * the running-enroll happen in ONE locked critical section, so two concurrent
265
+ * `delegate`s can never both see the same free slot and overshoot the cap.
266
+ * `running` counts CURRENT `running` jobs (`role:"job"`); when `running < cap`
267
+ * the `input` is upserted with `jobState:"running"` and the returned entry is
268
+ * non-undefined. When the cap is full, NOTHING is written and `undefined` is
269
+ * returned (the caller enqueues a `pending` entry instead). Exported for tests.
270
+ */
271
+ export function tryClaimSlot(input, cap, path = resolveRegistryPath()) {
272
+ return withRegistryLock(path, (entries) => {
273
+ if (cap <= 0)
274
+ return { entries, result: undefined, save: false };
275
+ // A `throttled` job KEEPS its slot (the rate-limit is account-wide; admitting
276
+ // a replacement just burns the same quota), so it counts toward the cap too.
277
+ const running = entries.filter((e) => e.role === "job" && occupiesSlot(e.jobState ?? "pending")).length;
278
+ // The job being claimed may already exist as `pending` (delegate enrolled it
279
+ // first); don't double-count it against itself.
280
+ const self = entries.find((e) => e.id === input.id);
281
+ const selfRunning = self?.role === "job" && occupiesSlot(self.jobState ?? "pending") ? 1 : 0;
282
+ if (running - selfRunning >= cap) {
283
+ return { entries, result: undefined, save: false };
284
+ }
285
+ const entry = applyEnroll(entries, { ...input, jobState: "running" });
286
+ return { entries, result: entry };
287
+ });
288
+ }
289
+ /**
290
+ * The legal job lifecycle transitions (P1 keeps it linear; P4 adds the queue's
291
+ * pending→running). A transition not listed here is rejected by `advanceJob`.
292
+ * Pure, exported for tests.
293
+ */
294
+ const JOB_TRANSITIONS = {
295
+ pending: ["running", "failed"],
296
+ // A HEADLESS LOCAL job that finished on a transient rate-limit goes
297
+ // running→throttled (reliability slice 1); it is NOT terminal.
298
+ running: ["throttled", "done", "failed"],
299
+ // The conductor resumes a throttled job (→running) on its backoff schedule, or
300
+ // gives up after the attempt cap (→failed). A reconcile that sees fresh success
301
+ // before the resumed run is re-observed may also settle it →done directly.
302
+ throttled: ["running", "done", "failed"],
303
+ done: [],
304
+ failed: [],
305
+ };
306
+ export function canTransitionJob(from, to) {
307
+ return JOB_TRANSITIONS[from].includes(to);
308
+ }
309
+ /**
310
+ * Does a job in `state` OCCUPY a concurrency slot? `running` does, and so does
311
+ * `throttled` — a throttled job is mid-flight (it KEEPS its slot rather than
312
+ * letting the conductor admit a replacement that would immediately throttle on
313
+ * the same account-wide limit). `pending`/`done`/`failed` do not. Pure, exported
314
+ * for the cap/admission logic in delegate.ts and its tests.
315
+ */
316
+ export function occupiesSlot(state) {
317
+ return state === "running" || state === "throttled";
318
+ }
319
+ /**
320
+ * Move a job to `to`, persisting the new state (and stamping endedAt for the
321
+ * terminal states). Returns the updated entry, or undefined when the id is
322
+ * unknown / not a job / the transition is illegal. Reuses the atomic write.
323
+ */
324
+ export function advanceJob(id, to, path = resolveRegistryPath()) {
325
+ return withRegistryLock(path, (entries) => {
326
+ const entry = entries.find((e) => e.id === id);
327
+ if (!entry || entry.role !== "job") {
328
+ return { entries, result: undefined, save: false };
329
+ }
330
+ const from = entry.jobState ?? "pending";
331
+ if (from !== to && !canTransitionJob(from, to)) {
332
+ return { entries, result: undefined, save: false };
333
+ }
334
+ entry.jobState = to;
335
+ entry.lastSeenAt = new Date().toISOString();
336
+ if (to === "done" || to === "failed") {
337
+ entry.endedAt = entry.endedAt ?? entry.lastSeenAt;
338
+ }
339
+ return { entries, result: entry };
340
+ });
341
+ }
342
+ /** Live job entries (role "job"), liveness reconciled like any other entry. */
343
+ export function listJobs(opts = {}) {
344
+ const path = opts.path ?? resolveRegistryPath();
345
+ return loadRegistry(path).filter((e) => e.role === "job");
346
+ }
347
+ /** Refresh lastSeenAt. Returns false when the id is unknown. */
348
+ export function touchEntry(id, path = resolveRegistryPath()) {
349
+ return withRegistryLock(path, (entries) => {
350
+ const entry = entries.find((e) => e.id === id);
351
+ if (!entry)
352
+ return { entries, result: false, save: false };
353
+ entry.lastSeenAt = new Date().toISOString();
354
+ return { entries, result: true };
355
+ });
356
+ }
357
+ /** Record the session's end. Returns false when the id is unknown. */
358
+ export function markEnded(id, path = resolveRegistryPath()) {
359
+ return withRegistryLock(path, (entries) => {
360
+ const entry = entries.find((e) => e.id === id);
361
+ if (!entry)
362
+ return { entries, result: false, save: false };
363
+ const now = new Date().toISOString();
364
+ entry.endedAt = now;
365
+ entry.lastSeenAt = now;
366
+ return { entries, result: true };
367
+ });
368
+ }
369
+ function defaultTmuxHasSession(name) {
370
+ try {
371
+ // "=" prefix forces an exact session-name match (no prefix matching).
372
+ return (spawnSync("tmux", ["has-session", "-t", `=${name}`], {
373
+ stdio: "ignore",
374
+ }).status === 0);
375
+ }
376
+ catch {
377
+ return false;
378
+ }
379
+ }
380
+ function defaultPidAlive(pid) {
381
+ try {
382
+ process.kill(pid, 0);
383
+ return true;
384
+ }
385
+ catch {
386
+ return false;
387
+ }
388
+ }
389
+ /**
390
+ * The cmdline of a live pid (NUL-separated args joined with spaces), or
391
+ * undefined when it can't be read. Used to detect PID REUSE: after a crash the
392
+ * CLI's pid may be reassigned to an unrelated process, which `kill(pid,0)`
393
+ * still reports as alive. /proc is Linux-only; elsewhere this returns undefined
394
+ * and the caller stays conservative (treats the pid as still ours).
395
+ */
396
+ function defaultProcessCmdline(pid) {
397
+ try {
398
+ return readFileSync(`/proc/${pid}/cmdline`, "utf8")
399
+ .replace(/\0/g, " ")
400
+ .trim();
401
+ }
402
+ catch {
403
+ return undefined;
404
+ }
405
+ }
406
+ /**
407
+ * Does the process at `pid` look like the `tool` CLI? Reads its cmdline and
408
+ * checks for the tool name. CONSERVATIVE on doubt: if the cmdline can't be read
409
+ * (non-Linux, permissions) we return true (assume it is still ours) so the
410
+ * single-writer guard never DROPS a real writer (which would risk two CLIs
411
+ * corrupting one .jsonl). Only a readable cmdline that clearly isn't the tool
412
+ * (a reused pid) returns false.
413
+ */
414
+ function processIsTool(pid, tool, read) {
415
+ const cmd = read(pid);
416
+ if (cmd === undefined)
417
+ return true; // can't tell → assume still ours
418
+ return cmd.includes(tool);
419
+ }
420
+ /**
421
+ * Liveness:
422
+ * - local-tmux -> the tmux session exists,
423
+ * - local -> pid alive (when recorded) AND not endedAt; without a pid
424
+ * (hook-enrolled: the hook's parent pid is a throwaway shell)
425
+ * we trust SessionEnd + prune,
426
+ * - remote -> always "live" here; the CALLER reconciles against
427
+ * listRemoteSessions (the registry cannot probe the cluster).
428
+ */
429
+ export function isLive(e, opts = {}) {
430
+ if (e.endedAt)
431
+ return false;
432
+ if (e.kind === "local-tmux") {
433
+ const has = opts.tmuxHasSession ?? defaultTmuxHasSession;
434
+ return has(e.tmuxSession ?? `remote-${e.id}`);
435
+ }
436
+ if (e.kind === "local") {
437
+ // A process cannot survive a reboot: an entry last seen BEFORE the machine
438
+ // booted is dead, whether or not it carries a pid.
439
+ const bootMs = opts.bootTimeMs ?? defaultBootTimeMs();
440
+ if (Date.parse(e.lastSeenAt) < bootMs)
441
+ return false;
442
+ // No pid (the claude SessionStart hook can't reliably capture claude's pid):
443
+ // unverifiable. Treat as live here, but convOwners demotes a no-pid local
444
+ // entry to a SUSPECT (warn), not a hard block — so a stale hook entry left
445
+ // by a crash never refuses a relaunch.
446
+ if (e.pid === undefined)
447
+ return true;
448
+ if (!(opts.pidAlive ?? defaultPidAlive)(e.pid))
449
+ return false;
450
+ // pid alive — but is it STILL our CLI? After a crash the dead CLI's pid can
451
+ // be reassigned to an unrelated process that kill(pid,0) reports as alive;
452
+ // verify the process identity to avoid a false live-writer.
453
+ return processIsTool(e.pid, e.tool, opts.processCmdline ?? defaultProcessCmdline);
454
+ }
455
+ return true;
456
+ }
457
+ /** Entries considered live right now (see isLive for the per-kind rules). */
458
+ export function listLive(opts = {}) {
459
+ const path = opts.path ?? resolveRegistryPath();
460
+ return loadRegistry(path).filter((e) => isLive(e, opts));
461
+ }
462
+ /**
463
+ * Drop DEAD entries whose last activity (endedAt, else lastSeenAt) is older
464
+ * than maxAgeHours. Live entries always stay; recently-dead ones stay too so
465
+ * `restore` can still resume them after a reboot via the scan fallback.
466
+ * Returns the number of removed entries.
467
+ */
468
+ export function prune(maxAgeHours, opts = {}) {
469
+ const path = opts.path ?? resolveRegistryPath();
470
+ const cutoff = Date.now() - maxAgeHours * 3600 * 1000;
471
+ return withRegistryLock(path, (entries) => {
472
+ const kept = entries.filter((e) => {
473
+ if (isLive(e, opts))
474
+ return true;
475
+ const last = Date.parse(e.endedAt ?? e.lastSeenAt);
476
+ return Number.isFinite(last) && last >= cutoff;
477
+ });
478
+ if (kept.length === entries.length)
479
+ return { entries, result: 0, save: false };
480
+ return { entries: kept, result: entries.length - kept.length };
481
+ });
482
+ }
483
+ /** Map a CLI profile name to a registry tool (undefined for shell/opencode/…). */
484
+ export function coerceRegistryTool(profile) {
485
+ switch (profile) {
486
+ case "claude":
487
+ case "claude-code":
488
+ return "claude";
489
+ case "codex":
490
+ return "codex";
491
+ case "agy":
492
+ case "antigravity":
493
+ return "agy";
494
+ default:
495
+ return undefined;
496
+ }
497
+ }
498
+ /**
499
+ * Auto-enrolment after `remote run` started a local tmux session. Best-effort
500
+ * plumbing: never throws (a registry hiccup must not break the run).
501
+ */
502
+ export function enrollFromRun(args) {
503
+ const tool = coerceRegistryTool(args.profile);
504
+ if (!tool)
505
+ return; // shell/opencode/… sessions stay tmux-only
506
+ try {
507
+ enroll({
508
+ id: args.slug,
509
+ tool,
510
+ kind: "local-tmux",
511
+ cwd: args.cwd,
512
+ source: "run",
513
+ label: args.slug,
514
+ tmuxSession: args.tmuxSession,
515
+ ...(args.convId !== undefined ? { convId: args.convId } : {}),
516
+ ...(args.gatewayMode !== undefined ? { gatewayMode: args.gatewayMode } : {}),
517
+ });
518
+ }
519
+ catch {
520
+ // best-effort: the tmux session is up regardless
521
+ }
522
+ }
523
+ /**
524
+ * LOCAL rows for `remote ls`: live tmux sessions joined with the registry
525
+ * ([registry] vs [guess] badge), plus live registry-only sessions (e.g. a
526
+ * hook-enrolled claude running in a plain terminal). Dead registry entries are
527
+ * pruned on the way (layout maxAgeHours).
528
+ */
529
+ export function listLocalForLs(opts = {}) {
530
+ const path = opts.path ?? resolveRegistryPath();
531
+ try {
532
+ prune(getLayoutConfig().maxAgeHours, { ...opts, path });
533
+ }
534
+ catch {
535
+ // a config/registry hiccup must not break `remote ls`
536
+ }
537
+ const live = listLive({ ...opts, path });
538
+ const rows = [];
539
+ const matched = new Set();
540
+ for (const s of listLocalSessions()) {
541
+ const entry = live.find((e) => e.tmuxSession === s.name || e.id === s.slug);
542
+ if (entry)
543
+ matched.add(entry.id);
544
+ rows.push({
545
+ slug: s.slug,
546
+ profile: s.profile,
547
+ state: s.attached ? "attached" : "detached",
548
+ path: s.path,
549
+ badge: entry ? "registry" : "guess",
550
+ ...(s.displayName !== undefined ? { displayName: s.displayName } : {}),
551
+ });
552
+ }
553
+ // Only surface local-tmux entries that were NOT matched above — these are
554
+ // orphaned registry records for tmux sessions remote itself created.
555
+ // kind:"local" entries are Claude Code conversation sessions (UUID ids,
556
+ // no tmuxSession) — they are internal CC state, not user-facing sessions.
557
+ for (const e of live) {
558
+ if (e.kind !== "local-tmux" || matched.has(e.id))
559
+ continue;
560
+ rows.push({
561
+ slug: e.label ?? e.id.slice(0, 12),
562
+ profile: e.tool,
563
+ state: "live",
564
+ path: e.cwd,
565
+ badge: "registry",
566
+ });
567
+ }
568
+ return rows;
569
+ }
570
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EACL,SAAS,EACT,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,MAAM,EACN,QAAQ,EACR,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AA8I9C,uDAAuD;AACvD,SAAS,iBAAiB;IACxB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;AACtC,CAAC;AAID,MAAM,UAAU,mBAAmB;IACjC,OAAO,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC,EAAE,eAAe,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,OAAe,mBAAmB,EAAE;IAEpC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QACtD,MAAM,OAAO,GAAI,MAAgC,EAAE,OAAO,CAAC;QAC3D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;YAAE,OAAO,EAAE,CAAC;QACvC,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,yEAAyE;QACzE,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,GAAY;IACnC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAClD,MAAM,CAAC,GAAG,GAA8B,CAAC;IACzC,OAAO,CACL,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ;QACxB,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC;QAC/D,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC;QACtE,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ;QACzB,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ;QAChC,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ;QAChC,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK;YACjB,CAAC,CAAC,MAAM,KAAK,MAAM;YACnB,CAAC,CAAC,MAAM,KAAK,MAAM;YACnB,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CACzB,CAAC;AACJ,CAAC;AAED,2DAA2D;AAC3D,SAAS,YAAY,CAAC,OAAwB,EAAE,IAAY;IAC1D,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,GAAG,IAAI,QAAQ,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAC7E,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AACxB,CAAC;AAED,8EAA8E;AAC9E,iEAAiE;AACjE,EAAE;AACF,8EAA8E;AAC9E,2EAA2E;AAC3E,6EAA6E;AAC7E,gFAAgF;AAChF,mEAAmE;AACnE,8EAA8E;AAC9E,iDAAiD;AACjD,EAAE;AACF,iFAAiF;AACjF,gFAAgF;AAChF,0EAA0E;AAC1E,8EAA8E;AAC9E,iFAAiF;AACjF,iFAAiF;AACjF,gCAAgC;AAChC,8EAA8E;AAE9E,sFAAsF;AACtF,MAAM,aAAa,GAAG,MAAM,CAAC,CAAC,iDAAiD;AAC/E,MAAM,YAAY,GAAG,CAAC,CAAC,CAAC,iDAAiD;AACzE,MAAM,gBAAgB,GAAG,KAAK,CAAC,CAAC,wDAAwD;AAExF,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,GAAG,IAAI,OAAO,CAAC;AACxB,CAAC;AAED,uFAAuF;AACvF,SAAS,SAAS,CAAC,EAAU;IAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;IAC5B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC;QACxB,yEAAyE;IAC3E,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,WAAW,CAAC,IAAY;IAC/B,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1B,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,gBAAgB,CAAC;IAC/C,SAAS,CAAC;QACR,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,0BAA0B;YACzD,OAAO,EAAE,CAAC;QACZ,CAAC;QAAC,MAAM,CAAC;YACP,oEAAoE;YACpE,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC;gBAC9C,IAAI,GAAG,GAAG,aAAa,EAAE,CAAC;oBACxB,MAAM,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;oBAC5B,SAAS,CAAC,yCAAyC;gBACrD,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,6DAA6D;YAC/D,CAAC;YACD,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,QAAQ;gBAAE,OAAO,SAAS,CAAC,CAAC,+BAA+B;YAC7E,SAAS,CAAC,YAAY,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,EAAU,EAAE,IAAY;IAC3C,IAAI,CAAC;QACH,SAAS,CAAC,EAAE,CAAC,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB;IACnB,CAAC;IACD,IAAI,CAAC;QACH,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,EAIC;IAED,MAAM,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;QACzD,IAAI,IAAI,KAAK,KAAK;YAAE,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAChD,OAAO,MAAM,CAAC;IAChB,CAAC;YAAS,CAAC;QACT,IAAI,EAAE,KAAK,SAAS;YAAE,WAAW,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,MAAM,CACpB,KAAkB,EAClB,OAAe,mBAAmB,EAAE;IAEpC,OAAO,gBAAgB,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE;QACxC,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW,CAClB,OAAwB,EACxB,KAAkB;IAElB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,CAAC,CAAC;IACxD,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACjD,MAAM,KAAK,GAAkB;QAC3B,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,UAAU,EAAE,IAAI,EAAE,UAAU,IAAI,GAAG;QACnC,UAAU,EAAE,GAAG;KAChB,CAAC;IACF,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,IAAI,EAAE,KAAK,CAAC;IACzC,IAAI,KAAK,KAAK,SAAS;QAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;IAC7C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,IAAI,EAAE,MAAM,CAAC;IAC5C,IAAI,MAAM,KAAK,SAAS;QAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;IAChD,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,IAAI,EAAE,QAAQ,CAAC;IAClD,IAAI,QAAQ,KAAK,SAAS;QAAE,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACtD,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,IAAI,EAAE,WAAW,CAAC;IAC3D,IAAI,WAAW,KAAK,SAAS;QAAE,KAAK,CAAC,WAAW,GAAG,WAAW,CAAC;IAC/D,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,IAAI,EAAE,GAAG,CAAC;IACnC,IAAI,GAAG,KAAK,SAAS;QAAE,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC;IACvC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,IAAI,EAAE,IAAI,CAAC;IACtC,IAAI,IAAI,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;IAC1C,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,IAAI,EAAE,QAAQ,CAAC;IAClD,IAAI,QAAQ,KAAK,SAAS;QAAE,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACtD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,IAAI,EAAE,MAAM,CAAC;IAC5C,IAAI,MAAM,KAAK,SAAS;QAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;IAChD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,IAAI,EAAE,IAAI,CAAC;IACtC,IAAI,IAAI,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;IAC1C,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,IAAI,IAAI,EAAE,UAAU,CAAC;IACxD,IAAI,UAAU,KAAK,SAAS;QAAE,KAAK,CAAC,UAAU,GAAG,UAAU,CAAC;IAC5D,MAAM,YAAY,GAAG,KAAK,CAAC,YAAY,IAAI,IAAI,EAAE,YAAY,CAAC;IAC9D,IAAI,YAAY,KAAK,SAAS;QAAE,KAAK,CAAC,YAAY,GAAG,YAAY,CAAC;IAClE,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,IAAI,EAAE,QAAQ,CAAC;IAClD,IAAI,QAAQ,KAAK,SAAS;QAAE,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACtD,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,IAAI,EAAE,SAAS,CAAC;IACrD,IAAI,SAAS,KAAK,SAAS;QAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;IACzD,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,IAAI,EAAE,WAAW,CAAC;IAC3D,IAAI,WAAW,KAAK,SAAS;QAAE,KAAK,CAAC,WAAW,GAAG,WAAW,CAAC;IAC/D,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,IAAI,EAAE,WAAW,CAAC;IAC3D,IAAI,WAAW,KAAK,SAAS;QAAE,KAAK,CAAC,WAAW,GAAG,WAAW,CAAC;IAC/D,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,IAAI,EAAE,OAAO,CAAC;IAC/C,IAAI,OAAO,KAAK,SAAS;QAAE,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;IACnD,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,IAAI,EAAE,QAAQ,CAAC;IAClD,IAAI,QAAQ,KAAK,SAAS;QAAE,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACtD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,IAAI,EAAE,KAAK,CAAC;IACzC,IAAI,KAAK,KAAK,SAAS;QAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;IAC7C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,IAAI,EAAE,MAAM,CAAC;IAC5C,IAAI,MAAM,KAAK,SAAS;QAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;IAChD,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,IAAI,EAAE,WAAW,CAAC;IAC3D,IAAI,WAAW,KAAK,SAAS;QAAE,KAAK,CAAC,WAAW,GAAG,WAAW,CAAC;IAC/D,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;;QAC9B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAkB,EAClB,GAAW,EACX,OAAe,mBAAmB,EAAE;IAEpC,OAAO,gBAAgB,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE;QACxC,IAAI,GAAG,IAAI,CAAC;YAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QACjE,8EAA8E;QAC9E,6EAA6E;QAC7E,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAC5B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,IAAI,YAAY,CAAC,CAAC,CAAC,QAAQ,IAAI,SAAS,CAAC,CACjE,CAAC,MAAM,CAAC;QACT,6EAA6E;QAC7E,gDAAgD;QAChD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,CAAC,CAAC;QACpD,MAAM,WAAW,GACf,IAAI,EAAE,IAAI,KAAK,KAAK,IAAI,YAAY,CAAC,IAAI,CAAC,QAAQ,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3E,IAAI,OAAO,GAAG,WAAW,IAAI,GAAG,EAAE,CAAC;YACjC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QACrD,CAAC;QACD,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,EAAE,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;QACtE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,eAAe,GAAwD;IAC3E,OAAO,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC;IAC9B,oEAAoE;IACpE,+DAA+D;IAC/D,OAAO,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC;IACxC,+EAA+E;IAC/E,gFAAgF;IAChF,2EAA2E;IAC3E,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC;IACxC,IAAI,EAAE,EAAE;IACR,MAAM,EAAE,EAAE;CACX,CAAC;AAEF,MAAM,UAAU,gBAAgB,CAAC,IAAc,EAAE,EAAY;IAC3D,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,KAAe;IAC1C,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,WAAW,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CACxB,EAAU,EACV,EAAY,EACZ,OAAe,mBAAmB,EAAE;IAEpC,OAAO,gBAAgB,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE;QACxC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YACnC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QACrD,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,IAAI,SAAS,CAAC;QACzC,IAAI,IAAI,KAAK,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC;YAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QACrD,CAAC;QACD,KAAK,CAAC,QAAQ,GAAG,EAAE,CAAC;QACpB,KAAK,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC5C,IAAI,EAAE,KAAK,MAAM,IAAI,EAAE,KAAK,QAAQ,EAAE,CAAC;YACrC,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,UAAU,CAAC;QACpD,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,QAAQ,CAAC,OAAqB,EAAE;IAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,mBAAmB,EAAE,CAAC;IAChD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,UAAU,CACxB,EAAU,EACV,OAAe,mBAAmB,EAAE;IAEpC,OAAO,gBAAgB,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE;QACxC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QAC3D,KAAK,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,SAAS,CACvB,EAAU,EACV,OAAe,mBAAmB,EAAE;IAEpC,OAAO,gBAAgB,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE;QACxC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QAC3D,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC;QACpB,KAAK,CAAC,UAAU,GAAG,GAAG,CAAC;QACvB,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAY;IACzC,IAAI,CAAC;QACH,sEAAsE;QACtE,OAAO,CACL,SAAS,CAAC,MAAM,EAAE,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,EAAE;YACnD,KAAK,EAAE,QAAQ;SAChB,CAAC,CAAC,MAAM,KAAK,CAAC,CAChB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;IAClC,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,qBAAqB,CAAC,GAAW;IACxC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,SAAS,GAAG,UAAU,EAAE,MAAM,CAAC;aAChD,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;aACnB,IAAI,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,aAAa,CACpB,GAAW,EACX,IAAkB,EAClB,IAAyC;IAEzC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACtB,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC,CAAC,iCAAiC;IACrE,OAAO,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,MAAM,CAAC,CAAgB,EAAE,OAAqB,EAAE;IAC9D,IAAI,CAAC,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC5B,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,IAAI,qBAAqB,CAAC;QACzD,OAAO,GAAG,CAAC,CAAC,CAAC,WAAW,IAAI,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QACvB,2EAA2E;QAC3E,mDAAmD;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,IAAI,iBAAiB,EAAE,CAAC;QACtD,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,MAAM;YAAE,OAAO,KAAK,CAAC;QACpD,6EAA6E;QAC7E,0EAA0E;QAC1E,2EAA2E;QAC3E,uCAAuC;QACvC,IAAI,CAAC,CAAC,GAAG,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QACrC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QAC7D,4EAA4E;QAC5E,2EAA2E;QAC3E,4DAA4D;QAC5D,OAAO,aAAa,CAClB,CAAC,CAAC,GAAG,EACL,CAAC,CAAC,IAAI,EACN,IAAI,CAAC,cAAc,IAAI,qBAAqB,CAC7C,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,QAAQ,CAAC,OAAqB,EAAE;IAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,mBAAmB,EAAE,CAAC;IAChD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,KAAK,CAAC,WAAmB,EAAE,OAAqB,EAAE;IAChE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,mBAAmB,EAAE,CAAC;IAChD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,GAAG,IAAI,GAAG,IAAI,CAAC;IACtD,OAAO,gBAAgB,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE;QACxC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YAChC,IAAI,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC;YACjC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC;YACnD,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,MAAM,CAAC;QACjD,CAAC,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM;YAChC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QAC7C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IACjE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,QAAQ,CAAC;QACd,KAAK,aAAa;YAChB,OAAO,QAAQ,CAAC;QAClB,KAAK,OAAO;YACV,OAAO,OAAO,CAAC;QACjB,KAAK,KAAK,CAAC;QACX,KAAK,aAAa;YAChB,OAAO,KAAK,CAAC;QACf;YACE,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,IAO7B;IACC,MAAM,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9C,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,2CAA2C;IAC9D,IAAI,CAAC;QACH,MAAM,CAAC;YACL,EAAE,EAAE,IAAI,CAAC,IAAI;YACb,IAAI;YACJ,IAAI,EAAE,YAAY;YAClB,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,MAAM,EAAE,KAAK;YACb,KAAK,EAAE,IAAI,CAAC,IAAI;YAChB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,GAAG,CAAC,IAAI,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC7E,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,iDAAiD;IACnD,CAAC;AACH,CAAC;AAaD;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,OAAqB,EAAE;IACpD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,mBAAmB,EAAE,CAAC;IAChD,IAAI,CAAC;QACH,KAAK,CAAC,eAAe,EAAE,CAAC,WAAW,EAAE,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,sDAAsD;IACxD,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,MAAM,IAAI,GAAiB,EAAE,CAAC;IAC9B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,KAAK,MAAM,CAAC,IAAI,iBAAiB,EAAE,EAAE,CAAC;QACpC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5E,IAAI,KAAK;YAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,CAAC;YACR,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU;YAC3C,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO;YACnC,GAAG,CAAC,CAAC,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACvE,CAAC,CAAC;IACL,CAAC;IACD,0EAA0E;IAC1E,qEAAqE;IACrE,wEAAwE;IACxE,0EAA0E;IAC1E,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAAE,SAAS;QAC3D,IAAI,CAAC,IAAI,CAAC;YACR,IAAI,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;YAClC,OAAO,EAAE,CAAC,CAAC,IAAI;YACf,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,CAAC,CAAC,GAAG;YACX,KAAK,EAAE,UAAU;SAClB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * `remote relaunch` — bring back local tmux sessions whose CLI has dropped to a
3
+ * shell (in situ, keeping the windows), each resuming ITS OWN conversation.
4
+ *
5
+ * Why a dedicated command: closing the terminal windows does NOT kill the tmux
6
+ * sessions, and `remote restore` goes through `remote run -r`, which the
7
+ * single-writer guard refuses while the (idle) session still holds the
8
+ * conversation. This relaunches the CLI inside the existing session — no
9
+ * `remote run`, no guard fight — and crucially resumes each session's OWN
10
+ * convId (from the registry), never "most recent", so the N sessions that share
11
+ * a cwd never collide on one .jsonl.
12
+ */
13
+ /** The shell command that resumes `convId` for `profile`, or undefined if the */
14
+ /** profile has no resume form (e.g. shell). */
15
+ export declare function resumeCommandFor(profile: string, convId: string): string | undefined;
16
+ export type RelaunchCandidate = {
17
+ /** short name, e.g. `sentropic#2` */
18
+ slug: string;
19
+ /** full tmux session name, e.g. `remote-sentropic#2` */
20
+ name: string;
21
+ profile: string;
22
+ /** true when the pane is an idle shell (CLI gone) — only these are relaunched */
23
+ idle: boolean;
24
+ /** this session's own conversation id, from the registry */
25
+ convId?: string;
26
+ };
27
+ export type RelaunchAction = {
28
+ slug: string;
29
+ name: string;
30
+ profile: string;
31
+ convId: string;
32
+ /** the command to run in the session (e.g. `claude --resume <id>`) */
33
+ cmd: string;
34
+ };
35
+ export type RelaunchSkip = {
36
+ slug: string;
37
+ reason: string;
38
+ };
39
+ export type RelaunchPlan = {
40
+ actions: RelaunchAction[];
41
+ skipped: RelaunchSkip[];
42
+ };
43
+ /**
44
+ * Decide what to relaunch. Pure: takes fully-resolved candidates (idle flag +
45
+ * convId already gathered) so it is unit-testable without tmux/registry I/O.
46
+ * Skips running sessions (never disturb a live CLI), sessions with no known
47
+ * convId (relaunch by hand rather than guess and risk a collision), and
48
+ * profiles with no resume form. Also refuses to point two sessions at the SAME
49
+ * convId (defensive: the registry should already be 1:1).
50
+ */
51
+ export declare function planRelaunch(candidates: ReadonlyArray<RelaunchCandidate>): RelaunchPlan;
52
+ //# sourceMappingURL=relaunch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relaunch.d.ts","sourceRoot":"","sources":["../src/relaunch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,iFAAiF;AACjF,+CAA+C;AAC/C,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,MAAM,GAAG,SAAS,CAMpB;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,IAAI,EAAE,OAAO,CAAC;IACd,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5D,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,aAAa,CAAC,iBAAiB,CAAC,GAC3C,YAAY,CA0Cd"}