@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,168 @@
1
+ /**
2
+ * WP16 Layer-C — local LLM account pool.
3
+ *
4
+ * Descriptor store: ~/.sentropic/accounts.json (0600) — id, provider, label, enrolledAt.
5
+ * Token store: ~/.sentropic/accounts-tokens.json (0600) — secrets only, separate file.
6
+ *
7
+ * Invariants:
8
+ * - No tokens ever appear in descriptors, stdout, logs, or track.
9
+ * - Both files are 0600 (owner-only). mkdirSync enforces ~/.sentropic/ exists.
10
+ * - selectAccount() is pure: no I/O, just candidates + policy → one descriptor.
11
+ */
12
+ export type AccountProvider = "claude-code" | "codex";
13
+ export type AccountDescriptor = {
14
+ readonly id: string;
15
+ readonly provider: AccountProvider;
16
+ readonly label: string;
17
+ readonly enrolledAt: string;
18
+ /** For claude-code accounts: the config dir holding credentials (maps to CLAUDE_CONFIG_DIR). Absent = default ~/.claude. */
19
+ readonly configDir?: string;
20
+ };
21
+ export type AccountCandidate = AccountDescriptor & {
22
+ readonly accessToken: string;
23
+ };
24
+ export declare function sentropicDir(): string;
25
+ export declare function accountsDescriptorPath(dir?: string): string;
26
+ export declare function accountsTokensPath(dir?: string): string;
27
+ export declare function loadDescriptors(dir?: string): AccountDescriptor[];
28
+ export type EnrollOpts = {
29
+ provider: AccountProvider;
30
+ label: string;
31
+ accessToken: string;
32
+ id?: string;
33
+ dir?: string;
34
+ /** For claude-code: path to the CLI config dir holding credentials (stored as CLAUDE_CONFIG_DIR override). */
35
+ configDir?: string;
36
+ };
37
+ export type EnrollResult = {
38
+ ok: true;
39
+ descriptor: AccountDescriptor;
40
+ } | {
41
+ ok: false;
42
+ error: string;
43
+ };
44
+ export declare function enrollAccount(opts: EnrollOpts): EnrollResult;
45
+ export declare function listAccounts(dir?: string): AccountDescriptor[];
46
+ /** Returns every enrolled account paired with its access token.
47
+ * Accounts with no token stored (corrupted enroll) are silently skipped.
48
+ * Intended for push-cluster only — keep the result out of logs. */
49
+ export declare function listAccountsWithTokens(dir?: string): Array<AccountDescriptor & {
50
+ accessToken: string;
51
+ }>;
52
+ export type RemoveResult = {
53
+ ok: true;
54
+ id: string;
55
+ } | {
56
+ ok: false;
57
+ error: string;
58
+ };
59
+ export declare function removeAccount(id: string, dir?: string): RemoveResult;
60
+ export declare function loadCandidates(provider?: AccountProvider, dir?: string): AccountCandidate[];
61
+ export type SelectPolicy = "round-robin";
62
+ export declare function selectAccount(candidates: ReadonlyArray<AccountDescriptor>, lastUsedId?: string, _policy?: SelectPolicy): AccountDescriptor | undefined;
63
+ export type SessionBinding = {
64
+ readonly affinityKey: string;
65
+ readonly accountId: string;
66
+ readonly provider: AccountProvider;
67
+ readonly boundAt: string;
68
+ };
69
+ export declare function bindingsPath(dir?: string): string;
70
+ /** Write (or overwrite) a sticky binding for an affinityKey. */
71
+ export declare function stickyBind(affinityKey: string, accountId: string, provider: AccountProvider, dir?: string): SessionBinding;
72
+ /** Return the binding for affinityKey, or undefined if not yet bound. */
73
+ export declare function lookupBinding(affinityKey: string, dir?: string): SessionBinding | undefined;
74
+ /** Return all current sticky bindings (for `remote account bindings`). */
75
+ export declare function listBindings(dir?: string): SessionBinding[];
76
+ /** Remove a binding (explicit rebind path — not silent). */
77
+ export declare function clearBinding(affinityKey: string, dir?: string): void;
78
+ /** Duration presets for quota windows. */
79
+ export declare const QUOTA_WINDOW_5H_MS: number;
80
+ export declare const QUOTA_WINDOW_WEEK_MS: number;
81
+ export type QuotaRecord = {
82
+ readonly accountId: string;
83
+ /** ISO-8601 timestamp when exhaustion was declared. */
84
+ readonly exhaustedAt: string;
85
+ /** Window duration in ms. Account is available again after exhaustedAt + windowMs. */
86
+ readonly windowMs: number;
87
+ /** Optional human-readable reason (e.g. "429 rate-limit", "weekly cap"). */
88
+ readonly reason?: string;
89
+ };
90
+ export declare function quotaPath(dir?: string): string;
91
+ /** Mark an account as exhausted for `windowMs` milliseconds. */
92
+ export declare function markExhausted(accountId: string, windowMs?: number, reason?: string, dir?: string): QuotaRecord;
93
+ /** Clear exhaustion for an account (manual override or after confirmed refresh). */
94
+ export declare function clearExhaustion(accountId: string, dir?: string): void;
95
+ /** Prune expired quota records (window elapsed). Returns count removed. */
96
+ export declare function pruneExpiredQuota(nowMs?: number, dir?: string): number;
97
+ /** True if the account is currently within its exhaustion window. */
98
+ export declare function isExhausted(accountId: string, quotaMap: Readonly<Record<string, QuotaRecord>>, nowMs?: number): boolean;
99
+ /** Enriched view of an account descriptor (for `remote account ls`). */
100
+ export type AccountStatus = AccountDescriptor & {
101
+ exhausted: boolean;
102
+ quotaResetsAt?: string;
103
+ /** Reason provided when exhaustion was recorded (e.g. "claude:rate-limited"). */
104
+ exhaustionReason?: string;
105
+ };
106
+ /** List all accounts with their current quota/exhaustion status. */
107
+ export declare function listAccountsWithStatus(dir?: string): AccountStatus[];
108
+ export type SelectWithFallbackResult = {
109
+ candidate: AccountCandidate;
110
+ crossProvider: false;
111
+ } | {
112
+ candidate: AccountCandidate;
113
+ crossProvider: true;
114
+ originalProvider: AccountProvider;
115
+ } | {
116
+ candidate: undefined;
117
+ allExhausted: true;
118
+ };
119
+ export declare function selectAccountWithFallback(preferredProvider: AccountProvider, affinityKey?: string, dir?: string, nowMs?: number): SelectWithFallbackResult;
120
+ export type ReadCredentialResult = {
121
+ ok: true;
122
+ accessToken: string;
123
+ } | {
124
+ ok: false;
125
+ error: string;
126
+ };
127
+ /**
128
+ * Read the Claude Code access token from ~/.claude/.credentials.json
129
+ * (or a custom configDir). Returns the claudeAiOauth.accessToken value.
130
+ */
131
+ export declare function readClaudeCredential(configDir?: string): ReadCredentialResult;
132
+ /**
133
+ * Read the Codex / OpenAI API key from ~/.codex/auth.json
134
+ * (or a custom configDir). Returns the OPENAI_API_KEY value.
135
+ */
136
+ export declare function readCodexCredential(configDir?: string): ReadCredentialResult;
137
+ export declare const LLM_GATEWAY_URL = "https://llm.sent-tech.ca";
138
+ /**
139
+ * Returns the env vars to inject into a session so it routes through the
140
+ * llm-gateway. Requires a valid sentropic S2S DPoP token for pod auth
141
+ * (injected separately by the control-plane auth flow, not here).
142
+ */
143
+ export declare function llmGatewayEnv(): {
144
+ ANTHROPIC_BASE_URL: string;
145
+ };
146
+ export type SessionLogEntry = {
147
+ at: string;
148
+ /** "launch" = account selected at job start; "exhaust" = account auto-exhausted (throttle). Absent = "launch" (back-compat). */
149
+ kind?: "launch" | "exhaust";
150
+ jobId: string;
151
+ preferredProvider: AccountProvider;
152
+ selectedProvider: AccountProvider;
153
+ accountId: string;
154
+ accountLabel: string;
155
+ crossProvider: boolean;
156
+ /** Throttle signature tag that triggered auto-exhaustion (kind="exhaust" only). */
157
+ signature?: string;
158
+ };
159
+ export declare function sessionLogPath(dir?: string): string;
160
+ export declare function appendSessionLogEntry(entry: Omit<SessionLogEntry, "at">, dir?: string): void;
161
+ /**
162
+ * Export the local session log to an S3 URI.
163
+ *
164
+ * Reads endpoint from AWS_ENDPOINT_URL (SCW: https://s3.fr-par.scw.cloud).
165
+ * Credentials from AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY (standard AWS env).
166
+ */
167
+ export declare function exportSessionLogToS3(s3Uri: string, dir?: string): Promise<void>;
168
+ //# sourceMappingURL=account-pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-pool.d.ts","sourceRoot":"","sources":["../src/account-pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,385 @@
1
+ /**
2
+ * WP16 Layer-C — local LLM account pool.
3
+ *
4
+ * Descriptor store: ~/.sentropic/accounts.json (0600) — id, provider, label, enrolledAt.
5
+ * Token store: ~/.sentropic/accounts-tokens.json (0600) — secrets only, separate file.
6
+ *
7
+ * Invariants:
8
+ * - No tokens ever appear in descriptors, stdout, logs, or track.
9
+ * - Both files are 0600 (owner-only). mkdirSync enforces ~/.sentropic/ exists.
10
+ * - selectAccount() is pure: no I/O, just candidates + policy → one descriptor.
11
+ */
12
+ import { appendFileSync, chmodSync, mkdirSync, readFileSync, renameSync, writeFileSync, } from "node:fs";
13
+ import { homedir } from "node:os";
14
+ import { dirname, join } from "node:path";
15
+ export function sentropicDir() {
16
+ return join(homedir(), ".sentropic");
17
+ }
18
+ export function accountsDescriptorPath(dir = sentropicDir()) {
19
+ return join(dir, "accounts.json");
20
+ }
21
+ export function accountsTokensPath(dir = sentropicDir()) {
22
+ return join(dir, "accounts-tokens.json");
23
+ }
24
+ function readJson(path) {
25
+ try {
26
+ return JSON.parse(readFileSync(path, "utf8"));
27
+ }
28
+ catch {
29
+ return undefined;
30
+ }
31
+ }
32
+ function writeSecret(path, value) {
33
+ mkdirSync(dirname(path), { recursive: true });
34
+ const tmp = `${path}.tmp.${process.pid}`;
35
+ writeFileSync(tmp, JSON.stringify(value, null, 2) + "\n", { mode: 0o600 });
36
+ chmodSync(tmp, 0o600);
37
+ renameSync(tmp, path);
38
+ }
39
+ // ---------------------------------------------------------------------------
40
+ // Descriptor store (no tokens)
41
+ // ---------------------------------------------------------------------------
42
+ export function loadDescriptors(dir) {
43
+ return readJson(accountsDescriptorPath(dir)) ?? [];
44
+ }
45
+ function saveDescriptors(descs, dir) {
46
+ writeSecret(accountsDescriptorPath(dir), descs);
47
+ }
48
+ // ---------------------------------------------------------------------------
49
+ // Token store (secrets only — never mixed with descriptors)
50
+ // ---------------------------------------------------------------------------
51
+ function loadTokenMap(dir) {
52
+ return readJson(accountsTokensPath(dir)) ?? {};
53
+ }
54
+ function saveTokenMap(map, dir) {
55
+ writeSecret(accountsTokensPath(dir), map);
56
+ }
57
+ export function enrollAccount(opts) {
58
+ if (!opts.accessToken.trim()) {
59
+ return { ok: false, error: "access token is empty" };
60
+ }
61
+ const descs = loadDescriptors(opts.dir);
62
+ const id = opts.id ?? `${opts.provider}-${Math.floor(Date.now() / 1000)}`;
63
+ if (descs.some((d) => d.id === id)) {
64
+ return {
65
+ ok: false,
66
+ error: `account "${id}" already enrolled; use --id to specify a unique id`,
67
+ };
68
+ }
69
+ const descriptor = {
70
+ id,
71
+ provider: opts.provider,
72
+ label: opts.label,
73
+ enrolledAt: new Date().toISOString(),
74
+ ...(opts.configDir !== undefined ? { configDir: opts.configDir } : {}),
75
+ };
76
+ saveDescriptors([...descs, descriptor], opts.dir);
77
+ const tokens = loadTokenMap(opts.dir);
78
+ tokens[id] = opts.accessToken;
79
+ saveTokenMap(tokens, opts.dir);
80
+ return { ok: true, descriptor };
81
+ }
82
+ // ---------------------------------------------------------------------------
83
+ // List
84
+ // ---------------------------------------------------------------------------
85
+ export function listAccounts(dir) {
86
+ return loadDescriptors(dir);
87
+ }
88
+ /** Returns every enrolled account paired with its access token.
89
+ * Accounts with no token stored (corrupted enroll) are silently skipped.
90
+ * Intended for push-cluster only — keep the result out of logs. */
91
+ export function listAccountsWithTokens(dir) {
92
+ const descs = loadDescriptors(dir);
93
+ const tokens = loadTokenMap(dir);
94
+ return descs.flatMap((d) => {
95
+ const accessToken = tokens[d.id];
96
+ return accessToken ? [{ ...d, accessToken }] : [];
97
+ });
98
+ }
99
+ export function removeAccount(id, dir) {
100
+ const descs = loadDescriptors(dir);
101
+ if (!descs.some((d) => d.id === id)) {
102
+ return { ok: false, error: `account "${id}" not found` };
103
+ }
104
+ saveDescriptors(descs.filter((d) => d.id !== id), dir);
105
+ const tokens = loadTokenMap(dir);
106
+ delete tokens[id];
107
+ saveTokenMap(tokens, dir);
108
+ return { ok: true, id };
109
+ }
110
+ // ---------------------------------------------------------------------------
111
+ // Load candidates (descriptor + token) — internal, never surfaced to user
112
+ // ---------------------------------------------------------------------------
113
+ export function loadCandidates(provider, dir) {
114
+ const descs = loadDescriptors(dir);
115
+ const tokens = loadTokenMap(dir);
116
+ return descs
117
+ .filter((d) => !provider || d.provider === provider)
118
+ .flatMap((d) => {
119
+ const accessToken = tokens[d.id];
120
+ if (!accessToken)
121
+ return [];
122
+ return [{ ...d, accessToken }];
123
+ });
124
+ }
125
+ export function selectAccount(candidates, lastUsedId, _policy = "round-robin") {
126
+ if (candidates.length === 0)
127
+ return undefined;
128
+ if (!lastUsedId)
129
+ return candidates[0];
130
+ const idx = candidates.findIndex((c) => c.id === lastUsedId);
131
+ if (idx === -1)
132
+ return candidates[0];
133
+ return candidates[(idx + 1) % candidates.length];
134
+ }
135
+ export function bindingsPath(dir = sentropicDir()) {
136
+ return join(dir, "session-bindings.json");
137
+ }
138
+ function loadBindings(dir) {
139
+ return (readJson(bindingsPath(dir)) ?? {});
140
+ }
141
+ function saveBindings(bindings, dir) {
142
+ writeSecret(bindingsPath(dir), bindings);
143
+ }
144
+ /** Write (or overwrite) a sticky binding for an affinityKey. */
145
+ export function stickyBind(affinityKey, accountId, provider, dir) {
146
+ const bindings = loadBindings(dir);
147
+ const binding = {
148
+ affinityKey,
149
+ accountId,
150
+ provider,
151
+ boundAt: new Date().toISOString(),
152
+ };
153
+ bindings[affinityKey] = binding;
154
+ saveBindings(bindings, dir);
155
+ return binding;
156
+ }
157
+ /** Return the binding for affinityKey, or undefined if not yet bound. */
158
+ export function lookupBinding(affinityKey, dir) {
159
+ return loadBindings(dir)[affinityKey];
160
+ }
161
+ /** Return all current sticky bindings (for `remote account bindings`). */
162
+ export function listBindings(dir) {
163
+ return Object.values(loadBindings(dir));
164
+ }
165
+ /** Remove a binding (explicit rebind path — not silent). */
166
+ export function clearBinding(affinityKey, dir) {
167
+ const bindings = loadBindings(dir);
168
+ delete bindings[affinityKey];
169
+ saveBindings(bindings, dir);
170
+ }
171
+ // ---------------------------------------------------------------------------
172
+ // Quota tracking — exhaustion windows per account
173
+ //
174
+ // When a CLI session hits a rate-limit / capacity error (429, "too many
175
+ // requests", "Claude.ai capacity"), the caller marks the account exhausted
176
+ // for a window duration (5h default for Claude Code short-window, 7d for
177
+ // weekly). selectAccountWithFallback() skips exhausted accounts and
178
+ // falls back across providers when all same-provider accounts are saturated.
179
+ // ---------------------------------------------------------------------------
180
+ /** Duration presets for quota windows. */
181
+ export const QUOTA_WINDOW_5H_MS = 5 * 60 * 60 * 1_000;
182
+ export const QUOTA_WINDOW_WEEK_MS = 7 * 24 * 60 * 60 * 1_000;
183
+ export function quotaPath(dir = sentropicDir()) {
184
+ return join(dir, "account-quota.json");
185
+ }
186
+ function loadQuotaMap(dir) {
187
+ return readJson(quotaPath(dir)) ?? {};
188
+ }
189
+ function saveQuotaMap(map, dir) {
190
+ writeSecret(quotaPath(dir), map);
191
+ }
192
+ /** Mark an account as exhausted for `windowMs` milliseconds. */
193
+ export function markExhausted(accountId, windowMs = QUOTA_WINDOW_5H_MS, reason, dir) {
194
+ const map = loadQuotaMap(dir);
195
+ const record = {
196
+ accountId,
197
+ exhaustedAt: new Date().toISOString(),
198
+ windowMs,
199
+ ...(reason !== undefined ? { reason } : {}),
200
+ };
201
+ map[accountId] = record;
202
+ saveQuotaMap(map, dir);
203
+ return record;
204
+ }
205
+ /** Clear exhaustion for an account (manual override or after confirmed refresh). */
206
+ export function clearExhaustion(accountId, dir) {
207
+ const map = loadQuotaMap(dir);
208
+ delete map[accountId];
209
+ saveQuotaMap(map, dir);
210
+ }
211
+ /** Prune expired quota records (window elapsed). Returns count removed. */
212
+ export function pruneExpiredQuota(nowMs = Date.now(), dir) {
213
+ const map = loadQuotaMap(dir);
214
+ let removed = 0;
215
+ for (const [id, rec] of Object.entries(map)) {
216
+ if (nowMs >= new Date(rec.exhaustedAt).getTime() + rec.windowMs) {
217
+ delete map[id];
218
+ removed++;
219
+ }
220
+ }
221
+ if (removed > 0)
222
+ saveQuotaMap(map, dir);
223
+ return removed;
224
+ }
225
+ /** True if the account is currently within its exhaustion window. */
226
+ export function isExhausted(accountId, quotaMap, nowMs = Date.now()) {
227
+ const rec = quotaMap[accountId];
228
+ if (!rec)
229
+ return false;
230
+ return nowMs < new Date(rec.exhaustedAt).getTime() + rec.windowMs;
231
+ }
232
+ /** List all accounts with their current quota/exhaustion status. */
233
+ export function listAccountsWithStatus(dir) {
234
+ const descs = loadDescriptors(dir);
235
+ const quota = loadQuotaMap(dir);
236
+ const now = Date.now();
237
+ return descs.map((d) => {
238
+ const rec = quota[d.id];
239
+ if (!rec)
240
+ return { ...d, exhausted: false };
241
+ const resetMs = new Date(rec.exhaustedAt).getTime() + rec.windowMs;
242
+ if (now >= resetMs)
243
+ return { ...d, exhausted: false };
244
+ return {
245
+ ...d,
246
+ exhausted: true,
247
+ quotaResetsAt: new Date(resetMs).toISOString(),
248
+ ...(rec.reason !== undefined ? { exhaustionReason: rec.reason } : {}),
249
+ };
250
+ });
251
+ }
252
+ // ---------------------------------------------------------------------------
253
+ // selectAccountWithFallback — quota-aware, cross-provider fallback
254
+ //
255
+ // Policy (priority order):
256
+ // 1. Sticky binding if it exists AND the bound account is not exhausted.
257
+ // 2. Round-robin from the preferred provider, skipping exhausted accounts.
258
+ // 3. Cross-provider fallback: if ALL preferred-provider accounts are
259
+ // exhausted, try the other provider (claude-code ↔ codex).
260
+ // 4. undefined if no usable account exists.
261
+ // ---------------------------------------------------------------------------
262
+ const FALLBACK_PROVIDER = {
263
+ "claude-code": "codex",
264
+ codex: "claude-code",
265
+ };
266
+ export function selectAccountWithFallback(preferredProvider, affinityKey, dir, nowMs = Date.now()) {
267
+ pruneExpiredQuota(nowMs, dir);
268
+ const quota = loadQuotaMap(dir);
269
+ // 1. Honour sticky binding if the bound account is still usable.
270
+ if (affinityKey) {
271
+ const binding = lookupBinding(affinityKey, dir);
272
+ if (binding && binding.provider === preferredProvider) {
273
+ if (!isExhausted(binding.accountId, quota, nowMs)) {
274
+ const candidates = loadCandidates(preferredProvider, dir);
275
+ const match = candidates.find((c) => c.id === binding.accountId);
276
+ if (match)
277
+ return { candidate: match, crossProvider: false };
278
+ }
279
+ }
280
+ }
281
+ // 2. Round-robin from preferred provider, skip exhausted.
282
+ const preferred = loadCandidates(preferredProvider, dir).filter((c) => !isExhausted(c.id, quota, nowMs));
283
+ if (preferred.length > 0) {
284
+ return { candidate: preferred[0], crossProvider: false };
285
+ }
286
+ // 3. Cross-provider fallback.
287
+ const fallbackProvider = FALLBACK_PROVIDER[preferredProvider];
288
+ const fallback = loadCandidates(fallbackProvider, dir).filter((c) => !isExhausted(c.id, quota, nowMs));
289
+ if (fallback.length > 0) {
290
+ return {
291
+ candidate: fallback[0],
292
+ crossProvider: true,
293
+ originalProvider: preferredProvider,
294
+ };
295
+ }
296
+ return { candidate: undefined, allExhausted: true };
297
+ }
298
+ /**
299
+ * Read the Claude Code access token from ~/.claude/.credentials.json
300
+ * (or a custom configDir). Returns the claudeAiOauth.accessToken value.
301
+ */
302
+ export function readClaudeCredential(configDir = join(homedir(), ".claude")) {
303
+ const path = join(configDir, ".credentials.json");
304
+ const raw = readJson(path);
305
+ if (!raw) {
306
+ return { ok: false, error: `credentials file not found or unreadable: ${path}` };
307
+ }
308
+ const oauth = raw["claudeAiOauth"];
309
+ const token = oauth?.["accessToken"];
310
+ if (typeof token !== "string" || !token.trim()) {
311
+ return { ok: false, error: `claudeAiOauth.accessToken missing or empty in ${path}` };
312
+ }
313
+ return { ok: true, accessToken: token.trim() };
314
+ }
315
+ /**
316
+ * Read the Codex / OpenAI API key from ~/.codex/auth.json
317
+ * (or a custom configDir). Returns the OPENAI_API_KEY value.
318
+ */
319
+ export function readCodexCredential(configDir = join(homedir(), ".codex")) {
320
+ const path = join(configDir, "auth.json");
321
+ const raw = readJson(path);
322
+ if (!raw) {
323
+ return { ok: false, error: `auth file not found or unreadable: ${path}` };
324
+ }
325
+ const key = raw["OPENAI_API_KEY"];
326
+ if (typeof key !== "string" || !key.trim()) {
327
+ return { ok: false, error: `OPENAI_API_KEY missing or empty in ${path}` };
328
+ }
329
+ return { ok: true, accessToken: key.trim() };
330
+ }
331
+ // ---------------------------------------------------------------------------
332
+ // Gateway constants (Layer-B wire — stable per architect spec)
333
+ // ---------------------------------------------------------------------------
334
+ export const LLM_GATEWAY_URL = "https://llm.sent-tech.ca";
335
+ /**
336
+ * Returns the env vars to inject into a session so it routes through the
337
+ * llm-gateway. Requires a valid sentropic S2S DPoP token for pod auth
338
+ * (injected separately by the control-plane auth flow, not here).
339
+ */
340
+ export function llmGatewayEnv() {
341
+ return { ANTHROPIC_BASE_URL: LLM_GATEWAY_URL };
342
+ }
343
+ export function sessionLogPath(dir = sentropicDir()) {
344
+ return join(dir, "session-log.jsonl");
345
+ }
346
+ export function appendSessionLogEntry(entry, dir) {
347
+ try {
348
+ const p = sessionLogPath(dir);
349
+ mkdirSync(dirname(p), { recursive: true });
350
+ const line = JSON.stringify({ at: new Date().toISOString(), ...entry }) + "\n";
351
+ appendFileSync(p, line, { mode: 0o600 });
352
+ }
353
+ catch {
354
+ // best-effort
355
+ }
356
+ }
357
+ /**
358
+ * Export the local session log to an S3 URI.
359
+ *
360
+ * Reads endpoint from AWS_ENDPOINT_URL (SCW: https://s3.fr-par.scw.cloud).
361
+ * Credentials from AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY (standard AWS env).
362
+ */
363
+ export async function exportSessionLogToS3(s3Uri, dir) {
364
+ const match = s3Uri.match(/^s3:\/\/([^/]+)\/(.+)$/);
365
+ if (!match)
366
+ throw new Error(`Invalid S3 URI (expected s3://bucket/key): ${s3Uri}`);
367
+ const [, Bucket, Key] = match;
368
+ const logPath = sessionLogPath(dir);
369
+ let Body;
370
+ try {
371
+ Body = readFileSync(logPath);
372
+ }
373
+ catch {
374
+ throw new Error(`Session log not found at ${logPath}`);
375
+ }
376
+ const { S3Client, PutObjectCommand } = await import("@aws-sdk/client-s3");
377
+ const client = new S3Client({
378
+ region: process.env.AWS_DEFAULT_REGION ?? process.env.AWS_REGION ?? "fr-par",
379
+ ...(process.env.AWS_ENDPOINT_URL
380
+ ? { endpoint: process.env.AWS_ENDPOINT_URL }
381
+ : {}),
382
+ });
383
+ await client.send(new PutObjectCommand({ Bucket, Key, Body, ContentType: "application/x-ndjson" }));
384
+ }
385
+ //# sourceMappingURL=account-pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-pool.js","sourceRoot":"","sources":["../src/account-pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import type { RegistryEntry, LocalLsRow } from "./registry.js";
2
+ export type RemoteAgentSourceKind = "job-registry" | "local-tmux";
3
+ export type RemoteAgentState = "pending" | "running" | "throttled" | "done" | "failed" | "attached" | "detached" | "live";
4
+ export type RemoteAgentProjection = {
5
+ id: string;
6
+ ownerSystem: "remote";
7
+ authoritativeForObjectiveState: false;
8
+ kind: "delegated-job" | "local-session";
9
+ tool: string;
10
+ state: RemoteAgentState;
11
+ cwd: string;
12
+ label?: string;
13
+ tmuxSession?: string;
14
+ remoteSessionId?: string;
15
+ jobId?: string;
16
+ h2aInstance?: string;
17
+ sources: Array<{
18
+ kind: RemoteAgentSourceKind;
19
+ id: string;
20
+ }>;
21
+ conflicts: string[];
22
+ capabilities: {
23
+ attach: boolean;
24
+ logs: boolean;
25
+ remote: boolean;
26
+ objectiveStateAuthority: false;
27
+ };
28
+ };
29
+ export type RemoteAgentsEnvelope = {
30
+ kind: "remote-agents-list";
31
+ version: 1;
32
+ agents: RemoteAgentProjection[];
33
+ warnings: string[];
34
+ degraded: false;
35
+ };
36
+ export type RemoteAgentInspectEnvelope = {
37
+ kind: "remote-agent-detail";
38
+ version: 1;
39
+ agent: RemoteAgentProjection;
40
+ related: {
41
+ jobs: unknown[];
42
+ sessions: unknown[];
43
+ logs: unknown[];
44
+ };
45
+ warnings: string[];
46
+ };
47
+ export declare function agentInstanceForJob(job: RegistryEntry): string;
48
+ export declare function projectJobAgent(job: RegistryEntry): RemoteAgentProjection;
49
+ export declare function projectLocalSessionAgent(row: LocalLsRow): RemoteAgentProjection;
50
+ export declare function projectRemoteAgents(args: {
51
+ jobs: readonly RegistryEntry[];
52
+ localRows: readonly LocalLsRow[];
53
+ }): RemoteAgentsEnvelope;
54
+ export declare function projectRemoteAgentInspect(agent: RemoteAgentProjection): RemoteAgentInspectEnvelope;
55
+ export declare function findProjectedAgent(agents: readonly RemoteAgentProjection[], selector: string): RemoteAgentProjection | undefined;
56
+ //# sourceMappingURL=agents-projection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents-projection.d.ts","sourceRoot":"","sources":["../src/agents-projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE/D,MAAM,MAAM,qBAAqB,GAAG,cAAc,GAAG,YAAY,CAAC;AAClE,MAAM,MAAM,gBAAgB,GACxB,SAAS,GACT,SAAS,GACT,WAAW,GACX,MAAM,GACN,QAAQ,GACR,UAAU,GACV,UAAU,GACV,MAAM,CAAC;AAEX,MAAM,MAAM,qBAAqB,GAAG;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,QAAQ,CAAC;IACtB,8BAA8B,EAAE,KAAK,CAAC;IACtC,IAAI,EAAE,eAAe,GAAG,eAAe,CAAC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,gBAAgB,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,qBAAqB,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5D,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,EAAE;QACZ,MAAM,EAAE,OAAO,CAAC;QAChB,IAAI,EAAE,OAAO,CAAC;QACd,MAAM,EAAE,OAAO,CAAC;QAChB,uBAAuB,EAAE,KAAK,CAAC;KAChC,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,OAAO,EAAE,CAAC,CAAC;IACX,MAAM,EAAE,qBAAqB,EAAE,CAAC;IAChC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,KAAK,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,EAAE,qBAAqB,CAAC;IAC5B,OAAO,EAAE,CAAC,CAAC;IACX,KAAK,EAAE,qBAAqB,CAAC;IAC7B,OAAO,EAAE;QACP,IAAI,EAAE,OAAO,EAAE,CAAC;QAChB,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpB,IAAI,EAAE,OAAO,EAAE,CAAC;KACjB,CAAC;IACF,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAE9D;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,qBAAqB,CAyBzE;AAED,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,UAAU,GAAG,qBAAqB,CAqB/E;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IACxC,IAAI,EAAE,SAAS,aAAa,EAAE,CAAC;IAC/B,SAAS,EAAE,SAAS,UAAU,EAAE,CAAC;CAClC,GAAG,oBAAoB,CAYvB;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,qBAAqB,GAC3B,0BAA0B,CAQ5B;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,SAAS,qBAAqB,EAAE,EACxC,QAAQ,EAAE,MAAM,GACf,qBAAqB,GAAG,SAAS,CAUnC"}