@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,108 @@
1
+ /**
2
+ * Conversation alignment check: is a remote session's conversation log in sync
3
+ * with the latest LOCAL conversation for the same project? Compares metrics only
4
+ * (id, bytes, lines, sha256) — local read directly, remote computed in-Pod via
5
+ * kubectl (only the numbers cross the wire, never the conversation content).
6
+ */
7
+ import { spawnSync } from "node:child_process";
8
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
9
+ import { createHash } from "node:crypto";
10
+ import { homedir } from "node:os";
11
+ import { join } from "node:path";
12
+ import { getTunnel } from "./config.js";
13
+ const CLAUDE_PROJECTS = ".claude/projects";
14
+ /** claude's cwd→project-dir encoding (slashes → dashes). */
15
+ export function encodeCwd(cwd) {
16
+ return cwd.replace(/\//g, "-");
17
+ }
18
+ function expandHome(p) {
19
+ return p.startsWith("~") ? join(homedir(), p.slice(1)) : p;
20
+ }
21
+ /** Newest local conversation for a project path (or undefined). */
22
+ export function localConvStat(workspacePath, home = homedir()) {
23
+ const dir = join(home, CLAUDE_PROJECTS, encodeCwd(workspacePath));
24
+ if (!existsSync(dir))
25
+ return undefined;
26
+ let newest;
27
+ for (const e of readdirSync(dir)) {
28
+ if (!e.endsWith(".jsonl"))
29
+ continue;
30
+ const st = statSync(join(dir, e));
31
+ if (!newest || st.mtimeMs > newest.mtimeMs) {
32
+ newest = { name: e, mtimeMs: st.mtimeMs };
33
+ }
34
+ }
35
+ if (!newest)
36
+ return undefined;
37
+ const buf = readFileSync(join(dir, newest.name));
38
+ return {
39
+ convId: newest.name.replace(/\.jsonl$/, ""),
40
+ bytes: buf.byteLength,
41
+ lines: buf.toString("utf8").split("\n").filter(Boolean).length,
42
+ sha: createHash("sha256").update(buf).digest("hex").slice(0, 12),
43
+ };
44
+ }
45
+ /** Newest remote conversation for a session (computed in-Pod, metrics only). */
46
+ export function remoteConvStat(sessionId, workspacePath) {
47
+ const tunnel = getTunnel();
48
+ if (!tunnel)
49
+ return undefined;
50
+ const env = { ...process.env };
51
+ if (tunnel.kubeconfig)
52
+ env.KUBECONFIG = expandHome(tunnel.kubeconfig);
53
+ const enc = encodeCwd(workspacePath);
54
+ const script = `d="$HOME/${CLAUDE_PROJECTS}/${enc}"; ` +
55
+ `f=$(ls -t "$d"/*.jsonl 2>/dev/null | head -1); ` +
56
+ `[ -z "$f" ] && exit 1; ` +
57
+ `printf '%s\\t%s\\t%s\\t%s' ` +
58
+ `"$(basename "$f" .jsonl)" "$(wc -c <"$f")" "$(wc -l <"$f")" "$(sha256sum "$f" | cut -c1-12)"`;
59
+ const r = spawnSync("kubectl", [
60
+ "-n",
61
+ tunnel.namespace,
62
+ "exec",
63
+ `session-${sessionId}`,
64
+ "-c",
65
+ "session-agent",
66
+ "--",
67
+ "bash",
68
+ "-lc",
69
+ script,
70
+ ], { encoding: "utf8", env });
71
+ if (r.status !== 0)
72
+ return undefined;
73
+ const [convId, bytes, lines, sha] = r.stdout.trim().split("\t");
74
+ if (!convId)
75
+ return undefined;
76
+ return { convId, bytes: Number(bytes), lines: Number(lines), sha: sha ?? "" };
77
+ }
78
+ export function alignment(local, remote) {
79
+ if (!local && !remote)
80
+ return { state: "missing", detail: "no conversation either side" };
81
+ if (!remote)
82
+ return { state: "missing", detail: "remote has no conversation" };
83
+ if (!local)
84
+ return { state: "remote-ahead", detail: "no local conversation (remote-only)" };
85
+ if (local.convId !== remote.convId) {
86
+ return {
87
+ state: "diverged",
88
+ detail: `different conversations — local newest ${local.convId} vs remote ${remote.convId} (separate sessions)`,
89
+ };
90
+ }
91
+ if (local.sha === remote.sha) {
92
+ return { state: "in-sync", detail: `identical (${local.lines} lines, ${(local.bytes / 1024 / 1024).toFixed(1)}M)` };
93
+ }
94
+ if (local.bytes > remote.bytes) {
95
+ return {
96
+ state: "local-ahead",
97
+ detail: `local +${local.lines - remote.lines} lines — push: re-deport (safe, remote is behind)`,
98
+ };
99
+ }
100
+ if (remote.bytes > local.bytes) {
101
+ return {
102
+ state: "remote-ahead",
103
+ detail: `remote +${remote.lines - local.lines} lines — pull: 'remote migrate back' (do NOT re-deport, it would overwrite remote)`,
104
+ };
105
+ }
106
+ return { state: "diverged", detail: "same conversation, content differs (both edited)" };
107
+ }
108
+ //# sourceMappingURL=convsync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convsync.js","sourceRoot":"","sources":["../src/convsync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Credential RELIABILITY pure cores (remote supervise slice 2) — ADDITIVE ONLY.
3
+ *
4
+ * Remote Pods silently lose auth (claude / gh / npm / docker → 401). The
5
+ * `creds refresh --watch` loop pushes fresh local creds, but (a) it can't tell a
6
+ * Pod-side credential already expired, (b) nobody notices when the watcher
7
+ * itself stopped, (c) the local claude OAuth token expires roughly every 8h and
8
+ * only `claude` running LOCALLY can refresh it.
9
+ *
10
+ * This module is PURE (no IO, no clock unless injected): the watch loop / `ls`
11
+ * call these to DECIDE; the actual push reuses the EXISTING soft-refresh path
12
+ * unchanged. NOTHING here ever prints or logs a secret VALUE — tool names and
13
+ * ok/reason only.
14
+ */
15
+ /** Tools whose Pod-side auth is CHEAP to probe (a non-mutating status check). */
16
+ export type ProbeableTool = "gh" | "npm" | "docker";
17
+ /** Is `tool` one we can cheaply health-probe in the Pod? (NOT claude/codex.) */
18
+ export declare function isProbeableTool(tool: string): tool is ProbeableTool;
19
+ /** All cheap-to-probe tools, in a stable order. */
20
+ export declare const PROBEABLE_TOOLS: ReadonlyArray<ProbeableTool>;
21
+ /**
22
+ * The ARGV (never a `bash -lc` string) to health-probe a tool's auth INSIDE the
23
+ * Pod, run through the existing `kubectl exec … -- <argv>` plumbing. Each is a
24
+ * READ-ONLY status check that fails (non-zero, or an unauth marker on stdout)
25
+ * when the Pod's credential is missing/expired:
26
+ * - gh: `gh auth status` — non-zero when not logged in.
27
+ * - npm: `npm whoami` — non-zero / empty when the token is invalid.
28
+ * - docker: read `~/.docker/config.json` and check it carries at least one
29
+ * `auths` entry (a pure config presence check — we do NOT hit a
30
+ * registry, which would need a target + network and could mutate
31
+ * nothing useful; a missing/empty config is the real 401 signal).
32
+ *
33
+ * The argv is built from STATIC tokens only (no untrusted interpolation), so it
34
+ * is safe to pass straight to `kubectl exec`. Pure, exported for tests.
35
+ */
36
+ export declare function buildHealthProbeCommand(tool: ProbeableTool): string[];
37
+ export type HealthResult = {
38
+ readonly tool: ProbeableTool;
39
+ /** true = the Pod's credential for this tool looks valid. */
40
+ readonly ok: boolean;
41
+ /** Short, SECRET-FREE reason (tool/status only — never a token value). */
42
+ readonly reason: string;
43
+ };
44
+ /**
45
+ * Interpret a probe's exit code + stdout into `{tool, ok, reason}`. PURE.
46
+ * `ok` is decided per tool:
47
+ * - any tool: a non-zero exit is a fail.
48
+ * - npm: even exit 0 with EMPTY stdout (no username) is treated as a fail —
49
+ * some npm versions print a warning and exit 0 with no name.
50
+ * - gh/docker: exit 0 is ok.
51
+ * The `reason` is a fixed, secret-free phrase. We NEVER echo stdout (it may
52
+ * carry a username/host) beyond the boolean decision.
53
+ */
54
+ export declare function parseHealthResult(tool: ProbeableTool, exitCode: number, stdout: string): HealthResult;
55
+ /** HOME/config-dir-relative file the `creds refresh --watch` loop touches each pass. */
56
+ export declare const SUPERVISOR_HEARTBEAT_FILE = "supervisor-heartbeat";
57
+ /**
58
+ * Loud advisory when the creds supervisor (`creds refresh --watch`) does not
59
+ * appear to be running: NO heartbeat, or a heartbeat OLDER than 2× the watch
60
+ * interval (a missed pass means the Pods are drifting toward a 401 with nobody
61
+ * pushing). PURE — the caller stats the heartbeat file and passes its mtime (ms)
62
+ * or undefined, the configured `intervalMs`, and `now`. Returns undefined when
63
+ * the heartbeat is fresh. Mirrors `conductorAdvisory`. Exported for tests.
64
+ *
65
+ * A non-finite/zero `intervalMs` falls back to treating ANY heartbeat as fresh
66
+ * only when present (we can't compute staleness without an interval), and warns
67
+ * when absent.
68
+ */
69
+ export declare function supervisorAdvisory(heartbeatMtimeMs: number | undefined, intervalMs: number, now?: number): string | undefined;
70
+ /** Within this window of `expiresAt` we warn the user to refresh claude locally. */
71
+ export declare const CLAUDE_EXPIRY_WARN_MS: number;
72
+ export type ClaudeExpiry = {
73
+ /** Parsed `expiresAt` (ms epoch), or undefined when absent/unparseable. */
74
+ readonly expiresAtMs: number | undefined;
75
+ /** ms until expiry (negative when already expired); undefined when unknown. */
76
+ readonly msUntilExpiry: number | undefined;
77
+ /** true when expired OR within CLAUDE_EXPIRY_WARN_MS of expiry. */
78
+ readonly expiringSoon: boolean;
79
+ /** true when `now >= expiresAt`. */
80
+ readonly expired: boolean;
81
+ };
82
+ /**
83
+ * Parse a claude `.credentials.json` (already JSON.parsed object OR a raw
84
+ * string) and report its OAuth-token expiry vs `now`. PURE. The token lives at
85
+ * `claudeAiOauth.expiresAt` (ms epoch). A missing/invalid field yields all-
86
+ * undefined / not-expiring (we never warn on what we can't read). We read ONLY
87
+ * the numeric expiry — NEVER the token values. Exported for tests.
88
+ */
89
+ export declare function claudeTokenExpiry(credential: unknown, now?: number, warnMs?: number): ClaudeExpiry;
90
+ /**
91
+ * The loud, SECRET-FREE advisory string for a claude token that is expired or
92
+ * about to expire. Returns undefined when not expiring soon. PURE. Used by the
93
+ * watch loop's per-pass output AND the `ls` advisory. Exported for tests.
94
+ */
95
+ export declare function claudeExpiryAdvisory(expiry: ClaudeExpiry): string | undefined;
96
+ //# sourceMappingURL=cred-health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cred-health.d.ts","sourceRoot":"","sources":["../src/cred-health.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,iFAAiF;AACjF,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEpD,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,aAAa,CAEnE;AAED,mDAAmD;AACnD,eAAO,MAAM,eAAe,EAAE,aAAa,CAAC,aAAa,CAA2B,CAAC;AAErF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,EAAE,CAmBrE;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,aAAa,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,YAAY,CAQd;AAMD,wFAAwF;AACxF,eAAO,MAAM,yBAAyB,yBAAyB,CAAC;AAEhE;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,gBAAgB,EAAE,MAAM,GAAG,SAAS,EACpC,UAAU,EAAE,MAAM,EAClB,GAAG,GAAE,MAAmB,GACvB,MAAM,GAAG,SAAS,CAkBpB;AAMD,oFAAoF;AACpF,eAAO,MAAM,qBAAqB,QAAc,CAAC;AAcjD,MAAM,MAAM,YAAY,GAAG;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,+EAA+E;IAC/E,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,mEAAmE;IACnE,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,oCAAoC;IACpC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,OAAO,EACnB,GAAG,GAAE,MAAmB,EACxB,MAAM,GAAE,MAA8B,GACrC,YAAY,CAsBd;AAWD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS,CAa7E"}
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Credential RELIABILITY pure cores (remote supervise slice 2) — ADDITIVE ONLY.
3
+ *
4
+ * Remote Pods silently lose auth (claude / gh / npm / docker → 401). The
5
+ * `creds refresh --watch` loop pushes fresh local creds, but (a) it can't tell a
6
+ * Pod-side credential already expired, (b) nobody notices when the watcher
7
+ * itself stopped, (c) the local claude OAuth token expires roughly every 8h and
8
+ * only `claude` running LOCALLY can refresh it.
9
+ *
10
+ * This module is PURE (no IO, no clock unless injected): the watch loop / `ls`
11
+ * call these to DECIDE; the actual push reuses the EXISTING soft-refresh path
12
+ * unchanged. NOTHING here ever prints or logs a secret VALUE — tool names and
13
+ * ok/reason only.
14
+ */
15
+ /** Is `tool` one we can cheaply health-probe in the Pod? (NOT claude/codex.) */
16
+ export function isProbeableTool(tool) {
17
+ return tool === "gh" || tool === "npm" || tool === "docker";
18
+ }
19
+ /** All cheap-to-probe tools, in a stable order. */
20
+ export const PROBEABLE_TOOLS = ["gh", "npm", "docker"];
21
+ /**
22
+ * The ARGV (never a `bash -lc` string) to health-probe a tool's auth INSIDE the
23
+ * Pod, run through the existing `kubectl exec … -- <argv>` plumbing. Each is a
24
+ * READ-ONLY status check that fails (non-zero, or an unauth marker on stdout)
25
+ * when the Pod's credential is missing/expired:
26
+ * - gh: `gh auth status` — non-zero when not logged in.
27
+ * - npm: `npm whoami` — non-zero / empty when the token is invalid.
28
+ * - docker: read `~/.docker/config.json` and check it carries at least one
29
+ * `auths` entry (a pure config presence check — we do NOT hit a
30
+ * registry, which would need a target + network and could mutate
31
+ * nothing useful; a missing/empty config is the real 401 signal).
32
+ *
33
+ * The argv is built from STATIC tokens only (no untrusted interpolation), so it
34
+ * is safe to pass straight to `kubectl exec`. Pure, exported for tests.
35
+ */
36
+ export function buildHealthProbeCommand(tool) {
37
+ switch (tool) {
38
+ case "gh":
39
+ return ["gh", "auth", "status"];
40
+ case "npm":
41
+ return ["npm", "whoami"];
42
+ case "docker":
43
+ // No `docker` binary nor daemon is guaranteed in the runtime image, and a
44
+ // real registry login would need a target + network. The 401-equivalent
45
+ // we CAN cheaply detect is "the Pod has no usable docker auth config", so
46
+ // we test for a config.json carrying a non-empty `auths` object. node is
47
+ // always present in the session-agent image. Static argv — the inline
48
+ // node script contains no interpolated/untrusted data.
49
+ return [
50
+ "node",
51
+ "-e",
52
+ 'const fs=require("fs");try{const c=JSON.parse(fs.readFileSync(process.env.HOME+"/.docker/config.json","utf8"));const a=c&&c.auths&&Object.keys(c.auths).length>0;process.exit(a?0:1)}catch(e){process.exit(1)}',
53
+ ];
54
+ }
55
+ }
56
+ /**
57
+ * Interpret a probe's exit code + stdout into `{tool, ok, reason}`. PURE.
58
+ * `ok` is decided per tool:
59
+ * - any tool: a non-zero exit is a fail.
60
+ * - npm: even exit 0 with EMPTY stdout (no username) is treated as a fail —
61
+ * some npm versions print a warning and exit 0 with no name.
62
+ * - gh/docker: exit 0 is ok.
63
+ * The `reason` is a fixed, secret-free phrase. We NEVER echo stdout (it may
64
+ * carry a username/host) beyond the boolean decision.
65
+ */
66
+ export function parseHealthResult(tool, exitCode, stdout) {
67
+ if (exitCode !== 0) {
68
+ return { tool, ok: false, reason: `${tool}: probe exited ${exitCode} (not authenticated)` };
69
+ }
70
+ if (tool === "npm" && stdout.trim().length === 0) {
71
+ return { tool, ok: false, reason: "npm: whoami returned no user (not authenticated)" };
72
+ }
73
+ return { tool, ok: true, reason: `${tool}: authenticated` };
74
+ }
75
+ // ---------------------------------------------------------------------------
76
+ // Watcher HEARTBEAT staleness → advisory (zero-risk; the highest-value piece).
77
+ // ---------------------------------------------------------------------------
78
+ /** HOME/config-dir-relative file the `creds refresh --watch` loop touches each pass. */
79
+ export const SUPERVISOR_HEARTBEAT_FILE = "supervisor-heartbeat";
80
+ /**
81
+ * Loud advisory when the creds supervisor (`creds refresh --watch`) does not
82
+ * appear to be running: NO heartbeat, or a heartbeat OLDER than 2× the watch
83
+ * interval (a missed pass means the Pods are drifting toward a 401 with nobody
84
+ * pushing). PURE — the caller stats the heartbeat file and passes its mtime (ms)
85
+ * or undefined, the configured `intervalMs`, and `now`. Returns undefined when
86
+ * the heartbeat is fresh. Mirrors `conductorAdvisory`. Exported for tests.
87
+ *
88
+ * A non-finite/zero `intervalMs` falls back to treating ANY heartbeat as fresh
89
+ * only when present (we can't compute staleness without an interval), and warns
90
+ * when absent.
91
+ */
92
+ export function supervisorAdvisory(heartbeatMtimeMs, intervalMs, now = Date.now()) {
93
+ if (heartbeatMtimeMs === undefined) {
94
+ return ("[remote] creds supervisor heartbeat MISSING — `remote refresh --all --watch <min>` " +
95
+ "is not running; remote Pods will drift to 401 with no fresh creds pushed. " +
96
+ "Start it: tmux new-window -n creds 'remote refresh --all --watch 30'");
97
+ }
98
+ if (!Number.isFinite(intervalMs) || intervalMs <= 0)
99
+ return undefined;
100
+ const ageMs = now - heartbeatMtimeMs;
101
+ if (ageMs <= 2 * intervalMs)
102
+ return undefined;
103
+ const ageMin = Math.round(ageMs / 60_000);
104
+ return (`[remote] creds supervisor heartbeat STALE (${ageMin}m old, > 2× the ${Math.round(intervalMs / 60_000)}m interval) — the watcher likely stopped; remote Pods may be drifting to 401. ` +
105
+ "Restart it: tmux new-window -n creds 'remote refresh --all --watch 30'");
106
+ }
107
+ // ---------------------------------------------------------------------------
108
+ // claude OAuth expiry DETECTION → advisory ONLY (no auto-action this slice).
109
+ // ---------------------------------------------------------------------------
110
+ /** Within this window of `expiresAt` we warn the user to refresh claude locally. */
111
+ export const CLAUDE_EXPIRY_WARN_MS = 15 * 60_000; // 15 min
112
+ /**
113
+ * Parse a claude `.credentials.json` (already JSON.parsed object OR a raw
114
+ * string) and report its OAuth-token expiry vs `now`. PURE. The token lives at
115
+ * `claudeAiOauth.expiresAt` (ms epoch). A missing/invalid field yields all-
116
+ * undefined / not-expiring (we never warn on what we can't read). We read ONLY
117
+ * the numeric expiry — NEVER the token values. Exported for tests.
118
+ */
119
+ export function claudeTokenExpiry(credential, now = Date.now(), warnMs = CLAUDE_EXPIRY_WARN_MS) {
120
+ let obj = credential;
121
+ if (typeof credential === "string") {
122
+ try {
123
+ obj = JSON.parse(credential);
124
+ }
125
+ catch {
126
+ obj = undefined;
127
+ }
128
+ }
129
+ const expiresAtMs = readExpiresAt(obj);
130
+ if (expiresAtMs === undefined) {
131
+ return {
132
+ expiresAtMs: undefined,
133
+ msUntilExpiry: undefined,
134
+ expiringSoon: false,
135
+ expired: false,
136
+ };
137
+ }
138
+ const msUntilExpiry = expiresAtMs - now;
139
+ const expired = msUntilExpiry <= 0;
140
+ const expiringSoon = msUntilExpiry <= warnMs;
141
+ return { expiresAtMs, msUntilExpiry, expiringSoon, expired };
142
+ }
143
+ function readExpiresAt(obj) {
144
+ if (!obj || typeof obj !== "object")
145
+ return undefined;
146
+ const oauth = obj.claudeAiOauth;
147
+ if (!oauth || typeof oauth !== "object")
148
+ return undefined;
149
+ const raw = oauth.expiresAt;
150
+ if (typeof raw !== "number" || !Number.isFinite(raw))
151
+ return undefined;
152
+ return raw;
153
+ }
154
+ /**
155
+ * The loud, SECRET-FREE advisory string for a claude token that is expired or
156
+ * about to expire. Returns undefined when not expiring soon. PURE. Used by the
157
+ * watch loop's per-pass output AND the `ls` advisory. Exported for tests.
158
+ */
159
+ export function claudeExpiryAdvisory(expiry) {
160
+ if (!expiry.expiringSoon)
161
+ return undefined;
162
+ if (expiry.expired) {
163
+ return ("[remote] LOCAL claude OAuth token has EXPIRED — run `claude` locally to refresh it, " +
164
+ "then the next supervisor pass will push the fresh token to your Pods.");
165
+ }
166
+ const mins = Math.max(0, Math.ceil((expiry.msUntilExpiry ?? 0) / 60_000));
167
+ return (`[remote] LOCAL claude OAuth token expires in ${mins}m — run \`claude\` locally to refresh it ` +
168
+ "so the supervisor can push the fresh token before your Pods 401.");
169
+ }
170
+ //# sourceMappingURL=cred-health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cred-health.js","sourceRoot":"","sources":["../src/cred-health.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,gFAAgF;AAChF,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,QAAQ,CAAC;AAC9D,CAAC;AAED,mDAAmD;AACnD,MAAM,CAAC,MAAM,eAAe,GAAiC,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;AAErF;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAmB;IACzD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,IAAI;YACP,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QAClC,KAAK,KAAK;YACR,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAC3B,KAAK,QAAQ;YACX,0EAA0E;YAC1E,wEAAwE;YACxE,0EAA0E;YAC1E,yEAAyE;YACzE,sEAAsE;YACtE,uDAAuD;YACvD,OAAO;gBACL,MAAM;gBACN,IAAI;gBACJ,gNAAgN;aACjN,CAAC;IACN,CAAC;AACH,CAAC;AAUD;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAmB,EACnB,QAAgB,EAChB,MAAc;IAEd,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;QACnB,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,kBAAkB,QAAQ,sBAAsB,EAAE,CAAC;IAC9F,CAAC;IACD,IAAI,IAAI,KAAK,KAAK,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjD,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,kDAAkD,EAAE,CAAC;IACzF,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,iBAAiB,EAAE,CAAC;AAC9D,CAAC;AAED,8EAA8E;AAC9E,+EAA+E;AAC/E,8EAA8E;AAE9E,wFAAwF;AACxF,MAAM,CAAC,MAAM,yBAAyB,GAAG,sBAAsB,CAAC;AAEhE;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,kBAAkB,CAChC,gBAAoC,EACpC,UAAkB,EAClB,MAAc,IAAI,CAAC,GAAG,EAAE;IAExB,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;QACnC,OAAO,CACL,qFAAqF;YACrF,4EAA4E;YAC5E,sEAAsE,CACvE,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IACtE,MAAM,KAAK,GAAG,GAAG,GAAG,gBAAgB,CAAC;IACrC,IAAI,KAAK,IAAI,CAAC,GAAG,UAAU;QAAE,OAAO,SAAS,CAAC;IAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC;IAC1C,OAAO,CACL,8CAA8C,MAAM,mBAAmB,IAAI,CAAC,KAAK,CAC/E,UAAU,GAAG,MAAM,CACpB,gFAAgF;QACjF,wEAAwE,CACzE,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,6EAA6E;AAC7E,8EAA8E;AAE9E,oFAAoF;AACpF,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,GAAG,MAAM,CAAC,CAAC,SAAS;AAyB3D;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,UAAmB,EACnB,MAAc,IAAI,CAAC,GAAG,EAAE,EACxB,SAAiB,qBAAqB;IAEtC,IAAI,GAAG,GAAY,UAAU,CAAC;IAC9B,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,GAAG,SAAS,CAAC;QAClB,CAAC;IACH,CAAC;IACD,MAAM,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO;YACL,WAAW,EAAE,SAAS;YACtB,aAAa,EAAE,SAAS;YACxB,YAAY,EAAE,KAAK;YACnB,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC;IACD,MAAM,aAAa,GAAG,WAAW,GAAG,GAAG,CAAC;IACxC,MAAM,OAAO,GAAG,aAAa,IAAI,CAAC,CAAC;IACnC,MAAM,YAAY,GAAG,aAAa,IAAI,MAAM,CAAC;IAC7C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;AAC/D,CAAC;AAED,SAAS,aAAa,CAAC,GAAY;IACjC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IACtD,MAAM,KAAK,GAAI,GAA+B,CAAC,aAAa,CAAC;IAC7D,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC1D,MAAM,GAAG,GAAI,KAAiC,CAAC,SAAS,CAAC;IACzD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IACvE,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAoB;IACvD,IAAI,CAAC,MAAM,CAAC,YAAY;QAAE,OAAO,SAAS,CAAC;IAC3C,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,CACL,sFAAsF;YACtF,uEAAuE,CACxE,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,aAAa,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IAC1E,OAAO,CACL,gDAAgD,IAAI,2CAA2C;QAC/F,kEAAkE,CACnE,CAAC;AACJ,CAAC"}