@cortexkit/opencode-openai-auth 0.11.0 → 1.0.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 (204) hide show
  1. package/README.md +15 -26
  2. package/dist/index-766sfrh5.js +1 -0
  3. package/dist/index-8kj7sa1p.js +12 -0
  4. package/dist/index-8rqfbhfw.js +221 -0
  5. package/dist/index-b3q3j39x.js +2 -0
  6. package/dist/index-bmd7x5aq.js +2 -0
  7. package/dist/index-eqh53k8v.js +2 -0
  8. package/dist/{index-sdt2d2ra.js → index-hy9030jh.js} +1 -1
  9. package/dist/index-jyr8y8k4.js +7 -0
  10. package/dist/index-rv08jmd4.js +2 -0
  11. package/dist/index.d.ts +578 -145
  12. package/dist/index.js +1 -110
  13. package/dist/pool-lifecycle-DbDmgabd.d.ts +2430 -0
  14. package/dist/port-file-Do3lQIEk.d.ts +29 -0
  15. package/dist/protocol-BOBdkqqm.d.ts +198 -0
  16. package/dist/rpc/port-file.d.ts +4 -17
  17. package/dist/rpc/port-file.js +1 -1
  18. package/dist/rpc/protocol.d.ts +2 -2
  19. package/dist/rpc/protocol.js +1 -0
  20. package/dist/rpc/rpc-client.d.ts +5 -4
  21. package/dist/rpc/rpc-client.js +1 -1
  22. package/dist/rpc/rpc-dir.d.ts +2 -0
  23. package/dist/rpc/rpc-dir.js +1 -1
  24. package/dist/sidebar-state-D6cUKgkm.d.ts +385 -0
  25. package/dist/sidebar-state.d.ts +2 -2
  26. package/dist/sidebar-state.js +1 -1
  27. package/dist/token-util-wdza526f.js +1 -0
  28. package/dist/{token-9823y0pc.js → token-ypk61xj0.js} +1 -1
  29. package/dist/tui-preferences.js +5 -2
  30. package/dist/tui.d.ts +9 -4
  31. package/dist/v2/server.d.ts +54 -0
  32. package/dist/v2/server.js +4 -0
  33. package/package.json +21 -9
  34. package/src/tui/entry.mjs +26 -25
  35. package/src/tui-compiled/raw/logger.js +24 -0
  36. package/src/tui-compiled/raw/rpc/protocol.js +3 -0
  37. package/src/tui-compiled/raw/rpc/rpc-client.js +7 -0
  38. package/src/tui-compiled/raw/rpc/rpc-dir.js +27 -0
  39. package/src/tui-compiled/raw/selector.js +21 -0
  40. package/src/tui-compiled/raw/shared/0332701351b3eeec-format.js +138 -0
  41. package/src/tui-compiled/raw/shared/04a6357627de5ed0-errors.js +38 -0
  42. package/src/tui-compiled/raw/shared/053cc17b5419261e-codec.js +12 -0
  43. package/src/tui-compiled/raw/shared/0766d78c6f481f18-watcher.js +157 -0
  44. package/src/tui-compiled/raw/shared/08eef45626a94992-reserved.js +13 -0
  45. package/src/tui-compiled/raw/shared/39c3cb05738fcf6d-projection.js +134 -0
  46. package/src/tui-compiled/raw/shared/3c2d4169d00f907e-tui-support.js +5 -0
  47. package/src/tui-compiled/raw/shared/3e7d45a77c6ad4d5-index.js +4 -0
  48. package/src/tui-compiled/raw/shared/415792e85d80819e-capture-sink.js +13 -0
  49. package/src/tui-compiled/raw/shared/42ae93ab554fcec2-open-url.js +28 -0
  50. package/src/tui-compiled/raw/shared/43fc9e6b994519c7-refresh-lock.js +136 -0
  51. package/src/tui-compiled/raw/shared/458b934e92490331-mutate.js +500 -0
  52. package/src/tui-compiled/raw/shared/45bf5343bbbf9add-admission.js +142 -0
  53. package/src/tui-compiled/raw/shared/46f3dff1266160e8-client.js +2 -0
  54. package/src/tui-compiled/raw/shared/4825e03209d6ae3e-with-lock.js +48 -0
  55. package/src/tui-compiled/raw/shared/4f36d333d081d040-merge.js +162 -0
  56. package/src/tui-compiled/raw/shared/54eba94fd64c8c3c-index.js +7 -0
  57. package/src/tui-compiled/raw/shared/7211cfec06a298bc-atomic-write.js +80 -0
  58. package/src/tui-compiled/raw/shared/754d6017f8e419cf-builtins.js +534 -0
  59. package/src/tui-compiled/raw/shared/75bd8c3bd63b315f-identity.js +79 -0
  60. package/src/tui-compiled/raw/shared/7a91bb630e6f4804-index.js +1 -0
  61. package/src/tui-compiled/raw/shared/826342a4b6a8b89b-model.js +16 -0
  62. package/src/tui-compiled/raw/shared/83068c0dbe8a6f13-publication.js +304 -0
  63. package/src/tui-compiled/raw/shared/836fc615de6afbd9-settings.js +120 -0
  64. package/src/tui-compiled/raw/shared/83bc3ba9d0fe2761-runtime.js +68 -0
  65. package/src/tui-compiled/raw/shared/8a18abe4fa2977c8-menu.js +300 -0
  66. package/src/tui-compiled/raw/shared/901e149c5a0dbbff-sticky.js +339 -0
  67. package/src/tui-compiled/raw/shared/9020c407ce64f672-ordered.js +58 -0
  68. package/src/tui-compiled/raw/shared/905bffc0220f43d0-map.js +105 -0
  69. package/src/tui-compiled/raw/shared/94820e324f2b4c09-seam.js +301 -0
  70. package/src/tui-compiled/raw/shared/97484d9bb98c705b-provider-state.js +226 -0
  71. package/src/tui-compiled/raw/shared/9968e3cade6969a1-index.js +2 -0
  72. package/src/tui-compiled/raw/shared/9b4da614c45f9cd0-lock-constants.js +14 -0
  73. package/src/tui-compiled/raw/shared/9d3fc9e37456504e-refresh.js +225 -0
  74. package/src/tui-compiled/raw/shared/9deae3c4da4fd63b-hooks.js +34 -0
  75. package/src/tui-compiled/raw/shared/a09b6a533c11858f-tui-preferences.js +77 -0
  76. package/src/tui-compiled/raw/shared/a62a27a204266acd-attribution.js +60 -0
  77. package/src/tui-compiled/raw/shared/a910277ac43a8626-pull.js +143 -0
  78. package/src/tui-compiled/raw/shared/b85c5301fddcb98a-paths.js +5 -0
  79. package/src/tui-compiled/raw/shared/c14988621dc60a75-port-file.js +217 -0
  80. package/src/tui-compiled/raw/shared/c64d7afbc14ca125-sidebar-file.js +157 -0
  81. package/src/tui-compiled/raw/shared/c6b176708c446d6d-pins.js +34 -0
  82. package/src/tui-compiled/raw/shared/c7d252bedee01600-pi.js +206 -0
  83. package/src/tui-compiled/raw/shared/c852a15cfe489d12-pool.js +120 -0
  84. package/src/tui-compiled/raw/shared/cc9e0702a752cea7-index.js +3 -0
  85. package/src/tui-compiled/raw/shared/cd94316a888b0a8e-schema.js +754 -0
  86. package/src/tui-compiled/raw/shared/d319517e3ea6ad70-redact.js +83 -0
  87. package/src/tui-compiled/raw/shared/d5a8f1061ee2f114-index.js +5 -0
  88. package/src/tui-compiled/raw/shared/d669d72c40e9e116-logger.js +19 -0
  89. package/src/tui-compiled/raw/shared/d7dcba96fea1685c-engine.js +246 -0
  90. package/src/tui-compiled/raw/shared/dbef697d1df1cd84-index.js +5 -0
  91. package/src/tui-compiled/raw/shared/e4acc4cb713f300c-protocol.js +3 -0
  92. package/src/tui-compiled/raw/shared/e8cd4929507508d8-refresh-file-lock.js +501 -0
  93. package/src/tui-compiled/raw/shared/ec971142548df90e-index.js +6 -0
  94. package/src/tui-compiled/raw/shared/f37fcefc7aedbf25-error.js +11 -0
  95. package/src/tui-compiled/raw/shared/fbcdcd0f925e74c0-rpc-client.js +253 -0
  96. package/src/tui-compiled/raw/shared/fd45e82f2f9c0a0d-torn.js +294 -0
  97. package/src/tui-compiled/raw/shared/fe02abeadc535f77-rows.js +1258 -0
  98. package/src/tui-compiled/raw/sidebar-state.js +960 -0
  99. package/src/tui-compiled/raw/tui/command-dialogs.tsx +424 -0
  100. package/src/tui-compiled/raw/tui-preferences.js +135 -0
  101. package/src/tui-compiled/raw/tui.tsx +135 -143
  102. package/src/tui-compiled/runtime/logger.js +24 -0
  103. package/src/tui-compiled/runtime/rpc/protocol.js +3 -0
  104. package/src/tui-compiled/runtime/rpc/rpc-client.js +7 -0
  105. package/src/tui-compiled/runtime/rpc/rpc-dir.js +27 -0
  106. package/src/tui-compiled/runtime/selector.js +21 -0
  107. package/src/tui-compiled/runtime/shared/0332701351b3eeec-format.js +138 -0
  108. package/src/tui-compiled/runtime/shared/04a6357627de5ed0-errors.js +38 -0
  109. package/src/tui-compiled/runtime/shared/053cc17b5419261e-codec.js +12 -0
  110. package/src/tui-compiled/runtime/shared/0766d78c6f481f18-watcher.js +157 -0
  111. package/src/tui-compiled/runtime/shared/08eef45626a94992-reserved.js +13 -0
  112. package/src/tui-compiled/runtime/shared/39c3cb05738fcf6d-projection.js +134 -0
  113. package/src/tui-compiled/runtime/shared/3c2d4169d00f907e-tui-support.js +5 -0
  114. package/src/tui-compiled/runtime/shared/3e7d45a77c6ad4d5-index.js +4 -0
  115. package/src/tui-compiled/runtime/shared/415792e85d80819e-capture-sink.js +13 -0
  116. package/src/tui-compiled/runtime/shared/42ae93ab554fcec2-open-url.js +28 -0
  117. package/src/tui-compiled/runtime/shared/43fc9e6b994519c7-refresh-lock.js +136 -0
  118. package/src/tui-compiled/runtime/shared/458b934e92490331-mutate.js +500 -0
  119. package/src/tui-compiled/runtime/shared/45bf5343bbbf9add-admission.js +142 -0
  120. package/src/tui-compiled/runtime/shared/46f3dff1266160e8-client.js +2 -0
  121. package/src/tui-compiled/runtime/shared/4825e03209d6ae3e-with-lock.js +48 -0
  122. package/src/tui-compiled/runtime/shared/4f36d333d081d040-merge.js +162 -0
  123. package/src/tui-compiled/runtime/shared/54eba94fd64c8c3c-index.js +7 -0
  124. package/src/tui-compiled/runtime/shared/7211cfec06a298bc-atomic-write.js +80 -0
  125. package/src/tui-compiled/runtime/shared/754d6017f8e419cf-builtins.js +534 -0
  126. package/src/tui-compiled/runtime/shared/75bd8c3bd63b315f-identity.js +79 -0
  127. package/src/tui-compiled/runtime/shared/7a91bb630e6f4804-index.js +1 -0
  128. package/src/tui-compiled/runtime/shared/826342a4b6a8b89b-model.js +16 -0
  129. package/src/tui-compiled/runtime/shared/83068c0dbe8a6f13-publication.js +304 -0
  130. package/src/tui-compiled/runtime/shared/836fc615de6afbd9-settings.js +120 -0
  131. package/src/tui-compiled/runtime/shared/83bc3ba9d0fe2761-runtime.js +68 -0
  132. package/src/tui-compiled/runtime/shared/8a18abe4fa2977c8-menu.js +300 -0
  133. package/src/tui-compiled/runtime/shared/901e149c5a0dbbff-sticky.js +339 -0
  134. package/src/tui-compiled/runtime/shared/9020c407ce64f672-ordered.js +58 -0
  135. package/src/tui-compiled/runtime/shared/905bffc0220f43d0-map.js +105 -0
  136. package/src/tui-compiled/runtime/shared/94820e324f2b4c09-seam.js +301 -0
  137. package/src/tui-compiled/runtime/shared/97484d9bb98c705b-provider-state.js +226 -0
  138. package/src/tui-compiled/runtime/shared/9968e3cade6969a1-index.js +2 -0
  139. package/src/tui-compiled/runtime/shared/9b4da614c45f9cd0-lock-constants.js +14 -0
  140. package/src/tui-compiled/runtime/shared/9d3fc9e37456504e-refresh.js +225 -0
  141. package/src/tui-compiled/runtime/shared/9deae3c4da4fd63b-hooks.js +34 -0
  142. package/src/tui-compiled/runtime/shared/a09b6a533c11858f-tui-preferences.js +77 -0
  143. package/src/tui-compiled/runtime/shared/a62a27a204266acd-attribution.js +60 -0
  144. package/src/tui-compiled/runtime/shared/a910277ac43a8626-pull.js +143 -0
  145. package/src/tui-compiled/runtime/shared/b85c5301fddcb98a-paths.js +5 -0
  146. package/src/tui-compiled/runtime/shared/c14988621dc60a75-port-file.js +217 -0
  147. package/src/tui-compiled/runtime/shared/c64d7afbc14ca125-sidebar-file.js +157 -0
  148. package/src/tui-compiled/runtime/shared/c6b176708c446d6d-pins.js +34 -0
  149. package/src/tui-compiled/runtime/shared/c7d252bedee01600-pi.js +206 -0
  150. package/src/tui-compiled/runtime/shared/c852a15cfe489d12-pool.js +120 -0
  151. package/src/tui-compiled/runtime/shared/cc9e0702a752cea7-index.js +3 -0
  152. package/src/tui-compiled/runtime/shared/cd94316a888b0a8e-schema.js +754 -0
  153. package/src/tui-compiled/runtime/shared/d319517e3ea6ad70-redact.js +83 -0
  154. package/src/tui-compiled/runtime/shared/d5a8f1061ee2f114-index.js +5 -0
  155. package/src/tui-compiled/runtime/shared/d669d72c40e9e116-logger.js +19 -0
  156. package/src/tui-compiled/runtime/shared/d7dcba96fea1685c-engine.js +246 -0
  157. package/src/tui-compiled/runtime/shared/dbef697d1df1cd84-index.js +5 -0
  158. package/src/tui-compiled/runtime/shared/e4acc4cb713f300c-protocol.js +3 -0
  159. package/src/tui-compiled/runtime/shared/e8cd4929507508d8-refresh-file-lock.js +501 -0
  160. package/src/tui-compiled/runtime/shared/ec971142548df90e-index.js +6 -0
  161. package/src/tui-compiled/runtime/shared/f37fcefc7aedbf25-error.js +11 -0
  162. package/src/tui-compiled/runtime/shared/fbcdcd0f925e74c0-rpc-client.js +253 -0
  163. package/src/tui-compiled/runtime/shared/fd45e82f2f9c0a0d-torn.js +294 -0
  164. package/src/tui-compiled/runtime/shared/fe02abeadc535f77-rows.js +1258 -0
  165. package/src/tui-compiled/runtime/sidebar-state.js +960 -0
  166. package/src/tui-compiled/runtime/tui/command-dialogs.js +378 -0
  167. package/src/tui-compiled/runtime/tui-preferences.js +135 -0
  168. package/src/tui-compiled/runtime/{tui.tsx → tui.js} +288 -316
  169. package/dist/index-4effjmr6.js +0 -2
  170. package/dist/index-9ehhb051.js +0 -2
  171. package/dist/index-g3hsdjh4.js +0 -2
  172. package/dist/index-hh52v8sb.js +0 -2
  173. package/dist/index-jwn4r3sw.js +0 -1
  174. package/dist/index-sq36b120.js +0 -211
  175. package/dist/internal-BTndPmW2.d.ts +0 -914
  176. package/dist/quota-normalize-08hpp51v.js +0 -1
  177. package/dist/sidebar-state-CoKYKcLn.d.ts +0 -220
  178. package/dist/token-util-ypgz7rge.js +0 -1
  179. package/src/tui-compiled/raw/core-account-paths.ts +0 -114
  180. package/src/tui-compiled/raw/core-custody-state.ts +0 -243
  181. package/src/tui-compiled/raw/logger.ts +0 -53
  182. package/src/tui-compiled/raw/rpc-port-file.ts +0 -177
  183. package/src/tui-compiled/raw/rpc-protocol.ts +0 -12
  184. package/src/tui-compiled/raw/rpc-rpc-client.ts +0 -82
  185. package/src/tui-compiled/raw/rpc-rpc-dir.ts +0 -46
  186. package/src/tui-compiled/raw/sidebar-state.ts +0 -1659
  187. package/src/tui-compiled/raw/tui-command-dialogs.tsx +0 -1096
  188. package/src/tui-compiled/raw/tui-preferences.ts +0 -328
  189. package/src/tui-compiled/runtime/core-account-paths.ts +0 -114
  190. package/src/tui-compiled/runtime/core-custody-state.ts +0 -243
  191. package/src/tui-compiled/runtime/logger.ts +0 -53
  192. package/src/tui-compiled/runtime/rpc-port-file.ts +0 -177
  193. package/src/tui-compiled/runtime/rpc-protocol.ts +0 -12
  194. package/src/tui-compiled/runtime/rpc-rpc-client.ts +0 -82
  195. package/src/tui-compiled/runtime/rpc-rpc-dir.ts +0 -46
  196. package/src/tui-compiled/runtime/sidebar-state.ts +0 -1659
  197. package/src/tui-compiled/runtime/tui-command-dialogs.tsx +0 -855
  198. package/src/tui-compiled/runtime/tui-preferences.ts +0 -328
  199. package/src/tui-compiled/shared/internal.ts +0 -6
  200. package/src/tui-compiled/shared/logger.ts +0 -264
  201. package/src/tui-compiled/shared/paths.ts +0 -33
  202. package/src/tui-compiled/shared/refresh-file-lock.ts +0 -384
  203. package/src/tui-compiled/shared/util/error.ts +0 -9
  204. package/src/tui-compiled/shared/util/open-url.ts +0 -30
@@ -0,0 +1,2430 @@
1
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/schema.d.ts
2
+ type OAuthCredential = {
3
+ type: 'oauth';
4
+ access?: string;
5
+ refresh: string;
6
+ expires?: number;
7
+ };
8
+ type ApiKeyCredential = {
9
+ type: 'api';
10
+ apiKey: string;
11
+ baseURL: string;
12
+ authHeader?: 'authorization-bearer' | 'x-api-key';
13
+ };
14
+ type PoolCredential = OAuthCredential | ApiKeyCredential;
15
+ /**
16
+ * What `rotate` takes. Rotation refreshes the secret of the endpoint a row
17
+ * already has, so an API key may leave out `baseURL` (and `authHeader`) to
18
+ * keep the row's; one it gives must equal the row's.
19
+ */
20
+ type RotateCredential = OAuthCredential | (Omit<ApiKeyCredential, 'baseURL'> & {
21
+ baseURL?: string;
22
+ });
23
+ /** A credential as stored: an OAuth credential also carries its refresh stamp. */
24
+ type StoredCredential = (OAuthCredential & {
25
+ lastRefreshedAt?: number;
26
+ }) | ApiKeyCredential;
27
+ /** Quota codec supplied by `/quota`: the store never interprets the map itself. */
28
+ interface QuotaCodec {
29
+ validate(value: unknown): boolean;
30
+ merge(stored: unknown | undefined, observation: unknown): unknown;
31
+ }
32
+ /**
33
+ * What `ProviderStateCodec.onReplace` is told about a replacement: the row id,
34
+ * the credential epoch the new credential starts, `previousIdentity` (the
35
+ * identity the locked row recorded before the replace), `identity` (the
36
+ * identity the replace records), and the provider state the caller handed to
37
+ * `replace`, if any. Each identity is absent when none was recorded.
38
+ */
39
+ interface ProviderStateReplacement {
40
+ id: string;
41
+ credentialEpoch: number;
42
+ previousIdentity?: string;
43
+ identity?: string;
44
+ incoming?: unknown;
45
+ }
46
+ /**
47
+ * Codec for the provider state a plugin keeps beside each row's credential
48
+ * (a project id, a device fingerprint, eligibility times: whatever belongs to
49
+ * that credential). The store never interprets the value: it stores it as
50
+ * JSON, asks `validate` before every write and on every load, and calls the
51
+ * hooks below where two values meet. Every hook is synchronous and runs
52
+ * under the store locks.
53
+ */
54
+ interface ProviderStateCodec {
55
+ validate(value: unknown): boolean;
56
+ /**
57
+ * The part of a (valid) value that belongs to the credential: what is true
58
+ * of the account the credential signs in to, such as a project id or a
59
+ * device fingerprint, as opposed to what the plugin merely tracks about
60
+ * its use, such as a cooldown or a cursor. The credential stamp covers the
61
+ * digest of exactly this projection, so a foreign edit of it hides the
62
+ * value, while the rest may change through `updateProviderState` without
63
+ * the stamp being rewritten. It must be a pure function of the value that
64
+ * returns JSON with a deterministic key order. Without it the whole value
65
+ * is credential-bound.
66
+ */
67
+ credentialBound?(value: unknown): unknown;
68
+ /**
69
+ * Combines the value on disk with one a write brings (`add` of a secret the
70
+ * pool already holds, `rotate`, or a refresh whose provider returned a
71
+ * state). Called only when the row has a value on disk; without it the
72
+ * incoming value replaces the stored one. Its result is validated.
73
+ */
74
+ merge?(onDisk: unknown, incoming: unknown): unknown;
75
+ /**
76
+ * The provider state of a row once `replace` gives it a new credential
77
+ * epoch. `previous` is the old credential's value (undefined when the row
78
+ * shows none). Returning undefined clears it. Without this hook a replace
79
+ * keeps the value handed to `replace` and otherwise clears the state.
80
+ */
81
+ onReplace?(previous: unknown | undefined, replacement: ProviderStateReplacement): unknown | undefined;
82
+ }
83
+ /**
84
+ * Why a row shows no provider state although the state file holds one for it.
85
+ *
86
+ * `uncovered`: the value's credential-bound part (see
87
+ * `ProviderStateCodec.credentialBound`) is not the one this store last
88
+ * wrote beside the row's credential at its credential epoch and recorded
89
+ * identity. Another writer edited it, or
90
+ * wrote the credential beside it without knowing about it (an older version
91
+ * of this library, which drops the coverage, or a writer that does not know
92
+ * the pool at all), or it belongs to an earlier credential of the row.
93
+ * `invalid`: the value is covered but the codec rejects it, or the store was
94
+ * opened without a provider-state codec.
95
+ */
96
+ type ProviderStateDrop = 'uncovered' | 'invalid';
97
+ /**
98
+ * What the stamp beside a row's credential proves (see `CredentialStamp`).
99
+ *
100
+ * `none`: the row holds no credential, so there is nothing to stamp.
101
+ * `bound`: the stamp was written with this credential (its digest matches),
102
+ * names the row's credential epoch (1 for a row without a per-row entry),
103
+ * the identity it records (or its recording none) and any endpoint it
104
+ * records are the row's, and its dispatch digest matches everything a
105
+ * request would send (the OAuth access and refresh tokens and expiry; the API
106
+ * key with its `baseURL` and `authHeader`).
107
+ * `missing`: the credential carries no stamp (written by a writer that does
108
+ * not know about stamps, or one that dropped it).
109
+ * `malformed`: the stamp is not one this store writes (wrong shape, or an
110
+ * epoch outside the positive safe integers).
111
+ * `mismatched`: the stamp was written for another credential, epoch,
112
+ * identity, endpoint, or token to send than the row now holds.
113
+ * `legacy`: a well-formed stamp written with this credential's secret but
114
+ * with no dispatch digest (written by 0.4.3 or earlier), so it proves
115
+ * neither the token sent nor the account or endpoint it goes to.
116
+ */
117
+ type CredentialStampStatus = 'none' | 'bound' | 'missing' | 'malformed' | 'mismatched' | 'legacy';
118
+ /** One row of the pool as loaded. */
119
+ interface PoolRow {
120
+ id: string;
121
+ type: 'oauth' | 'api';
122
+ label?: string;
123
+ enabled: boolean;
124
+ addedAt?: number;
125
+ /** Recorded wire identity (the roster row's `accountId`), when known. */
126
+ identity?: string;
127
+ /** Undefined when the state file holds no usable credential for the row. */
128
+ credential?: StoredCredential;
129
+ /** Stable hash of the credential's secret material; never persisted. */
130
+ fingerprint?: string;
131
+ /** Undefined when the row has no per-row entry yet. */
132
+ credentialEpoch?: number;
133
+ needsFirstReading: boolean;
134
+ disabledReason?: string;
135
+ /** Store-owned reservation; only `publishRoster` releases it for ordinary use. */
136
+ staged?: {
137
+ reservation: string;
138
+ };
139
+ /** The opaque quota map, as validated by the codec. */
140
+ quota?: unknown;
141
+ /**
142
+ * The opaque provider state kept beside the credential, as validated by
143
+ * the provider-state codec. Absent when the row has none, or when the one
144
+ * on disk is not shown (see `providerStateDropped`).
145
+ */
146
+ providerState?: unknown;
147
+ /**
148
+ * Set when the state file holds a provider state for the row that is not
149
+ * shown, and why. The value stays on disk untouched until a write on the
150
+ * row sets or clears it; the row itself stays usable.
151
+ */
152
+ providerStateDropped?: ProviderStateDrop;
153
+ hasEntry: boolean;
154
+ /** A row that may be refreshed, pulled for, or admitted. */
155
+ candidate: boolean;
156
+ /** Set when the roster row or the per-row entry failed validation. */
157
+ invalid?: 'roster' | 'entry';
158
+ /**
159
+ * Set when a replace stopped between its two writes: the state file holds
160
+ * the new credential, stamped with the epoch and the identity or endpoint
161
+ * it belongs to, and the config still holds the replaced row. Also set when
162
+ * a write that gives a row its first identity (`recordIdentity`, or a
163
+ * `rotate` or refresh that learns one) stopped after stamping the identity
164
+ * and before recording it in the config, and when an attributed `disable`
165
+ * or `enable` that changed the provider state stopped after its state
166
+ * write and before flipping the row in the config. The row is shown as the
167
+ * write leaves it once completed, is never a candidate, and the next store
168
+ * write on it writes the config to match.
169
+ */
170
+ torn?: true;
171
+ /**
172
+ * Whether the credential is the one the store last stamped for this row
173
+ * (see `CredentialStampStatus`). Every row the store loads carries it; a
174
+ * torn row reports the stamp of the row as it is shown completed. It is
175
+ * optional only so that rows built by hand (test fixtures) still type.
176
+ */
177
+ stamp?: CredentialStampStatus;
178
+ /**
179
+ * Set only when the store was opened with `requireCredentialStamps` and
180
+ * the row's `stamp` is not `bound`: the row is never a candidate, and
181
+ * `refresh`, quota pulls, `recordQuota`, `recordIdentity`, `rotate` and a
182
+ * re-`add` onto it refuse with `unbound-credential`. Only `replace` (or a
183
+ * new row) makes it usable again.
184
+ */
185
+ unbound?: true;
186
+ }
187
+ //#endregion
188
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/errors.d.ts
189
+ /** Every library operation that can fail, as named in the failure value. */
190
+ type PoolOperation = 'initialize' | 'add' | 'replace' | 'rotate' | 'disable' | 'enable' | 'remove' | 'reorder' | 'updateSettings' | 'recordIdentity' | 'updateProviderState' | 'refresh' | 'pull' | 'publishRoster';
191
+ /**
192
+ * How far an operation got before it failed.
193
+ *
194
+ * `before-first-write`: nothing was written; both files are as they were.
195
+ * `after-first-write`: the operation's first file write landed and a later one
196
+ * did not; what that first write left is on disk and is never rolled back
197
+ * (add: a state entry no roster row names, which no reader loads; replace:
198
+ * the new credential stamped ahead of the config, which readers show as a
199
+ * torn row and the next store write on it completes; rotate: the rotated
200
+ * credential beside the old per-row entry). `pull`: a quota pull, or the
201
+ * recording of its result, failed.
202
+ */
203
+ type PoolFailurePhase = 'before-first-write' | 'after-first-write' | 'pull';
204
+ /**
205
+ * Why an operation failed. `lock-contention` and `lock-ownership` are the two
206
+ * lock outcomes (a wait that ran out, and a lease found lost); the rest are
207
+ * refusals and failures of the operation itself.
208
+ */
209
+ type PoolFailureKind = 'lock-contention' | 'lock-ownership' | 'pending-migration' | 'load-error' | 'snapshot-contended' | 'publication-sync' | 'publication-incomplete' | 'unknown-row' | 'invalid-row' | 'invalid-input' | 'id-exists' | 'id-removed' | 'type-mismatch' | 'no-credential' | 'row-disabled' | 'row-protected' | 'row-staged' | 'credential-exists' | 'publication-mismatch' | 'duplicate-identity' | 'identity-mismatch' | 'identity-contradicted' | 'endpoint-mismatch' | 'row-key-changed' | 'invalid-order' | 'refresh-stamp-ahead' | 'unbound-credential' | 'attribution' | 'provider' | 'pull' | 'invalid-quota' | 'invalid-provider-state' | 'after-persist-hook' | 'unexpected';
210
+ /**
211
+ * The single failure value of every store operation. `committed` is present
212
+ * only when the operation had already written a credential to the state file
213
+ * before it failed (a partial rotation or refresh): it is the credential now
214
+ * on disk, so a caller never has to re-read the files to learn it.
215
+ */
216
+ declare class PoolOperationError extends Error {
217
+ readonly operation: PoolOperation;
218
+ readonly rowId: string | undefined;
219
+ readonly phase: PoolFailurePhase;
220
+ readonly retryable: boolean;
221
+ readonly kind: PoolFailureKind;
222
+ readonly committed: StoredCredential | undefined;
223
+ constructor(details: {
224
+ operation: PoolOperation;
225
+ rowId?: string;
226
+ phase: PoolFailurePhase;
227
+ retryable: boolean;
228
+ kind: PoolFailureKind;
229
+ committed?: StoredCredential;
230
+ message?: string;
231
+ cause?: unknown;
232
+ });
233
+ }
234
+ //#endregion
235
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/hooks.d.ts
236
+ interface PoolLogger {
237
+ warn(message: string, data?: unknown): void;
238
+ }
239
+ //#endregion
240
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/fs/refresh-file-lock.d.ts
241
+ interface LockLoss {
242
+ readonly reason: 'taken-over' | 'expired' | 'unreadable' | 'renewal-failed' | 'marker-lost';
243
+ readonly expectedOwnerId: string;
244
+ readonly observedOwnerId?: string;
245
+ readonly observedExpiresAt?: number;
246
+ }
247
+ interface RefreshFileLock {
248
+ readonly ownerId: string;
249
+ assertOwned(): Promise<void>;
250
+ release(): Promise<void>;
251
+ /** Resolves once on detected loss; remains pending after an owner's release. */
252
+ whenLost(): Promise<LockLoss>;
253
+ hasLost(): boolean;
254
+ }
255
+ declare function acquireRefreshFileLock(options: {
256
+ name: string;
257
+ ttlMs: number;
258
+ /**
259
+ * File the lock is named after. Required: the lock and the write it guards
260
+ * must target the same file, and a default resolved in here could only ever
261
+ * be one host's path.
262
+ */
263
+ path: string;
264
+ now?: () => number;
265
+ renew?: boolean;
266
+ renewIntervalMs?: number;
267
+ /** Notifies a live-owner refusal without awaiting; observer failures are ignored. */
268
+ onContended?: () => void;
269
+ /** Synchronous, never awaited; throws and returned promise/thenable rejections are isolated. */
270
+ onRenewalTimer?: (event: 'scheduled' | 'cancelled') => void;
271
+ onStep?: (step: 'stale-marker-stat' | 'stale-marker-claimed' | 'stale-lock-observed' | 'stale-lock-confirmed' | 'stale-lock-removed' | 'stale-lock-recreated' | 'eviction-marker-acquired' | 'renewal-owner-confirmed' | 'renewal-marker-unavailable' | 'renewal-write-fenced' | 'renewal-write-ready' | 'relinquish-read' | 'renewal-finished' | 'release-owner-confirmed') => void | Promise<void>;
272
+ }): Promise<RefreshFileLock | null>;
273
+ //#endregion
274
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/refresh-lock.d.ts
275
+ type LockStep = NonNullable<Parameters<typeof acquireRefreshFileLock>[0]['onStep']> extends ((step: infer S) => unknown) ? S : never;
276
+ /** Tuning shared by every lock the store takes; each field is overridable. */
277
+ interface PoolLockOptions {
278
+ ttlMs: number;
279
+ timeoutMs: number;
280
+ retryMs: number;
281
+ renew: boolean;
282
+ renewIntervalMs?: number;
283
+ }
284
+ /** A lock: the (name, path) pair naming its file plus optional tuning. */
285
+ interface PoolLockSpec extends Partial<PoolLockOptions> {
286
+ name: string;
287
+ path: string;
288
+ }
289
+ type LockEvent = {
290
+ type: 'acquired' | 'released' | 'contended';
291
+ name: string;
292
+ path: string;
293
+ };
294
+ interface LockEnvironment {
295
+ now: () => number;
296
+ onLockEvent?: (event: LockEvent) => void;
297
+ onLockStep?: (lock: {
298
+ name: string;
299
+ path: string;
300
+ }, step: LockStep) => void | Promise<void>;
301
+ }
302
+ //#endregion
303
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/mutate.d.ts
304
+ /** Named points on the write path, for crash and ownership injection. */
305
+ type WriteStep = 'before-config-write' | 'after-config-write' | 'before-state-write' | 'after-state-write';
306
+ /** Awaitable pause points on the pull and refresh paths. */
307
+ type HoldPoint = 'refresh-before-provider' | 'pull-before-request';
308
+ interface StoreContext {
309
+ provider: string;
310
+ configPath: string;
311
+ statePath: string;
312
+ codec: QuotaCodec;
313
+ /** The provider-state codec; without one no row shows a provider state. */
314
+ providerState?: ProviderStateCodec;
315
+ now: () => number;
316
+ storeLocks: readonly PoolLockSpec[];
317
+ lockDefaults: PoolLockOptions;
318
+ lockEnv: LockEnvironment;
319
+ logger?: PoolLogger;
320
+ onStep?: (step: WriteStep, info: {
321
+ operation: PoolOperation;
322
+ rowId: string | undefined;
323
+ }) => void | Promise<void>;
324
+ hold?: (point: HoldPoint, rowId: string) => void | Promise<void>;
325
+ /** Ids whose per-row entry a library write dropped in this process. */
326
+ removedIds: Set<string>;
327
+ /**
328
+ * When true, rows whose credential stamp is not bound load `unbound` and
329
+ * the operations that use a credential refuse them (see
330
+ * `OpenPoolStoreOptions.requireCredentialStamps`).
331
+ */
332
+ requireCredentialStamps?: boolean;
333
+ requireRemovedFingerprint?: boolean;
334
+ }
335
+ /** What `initializePool` did. */
336
+ type InitializeOutcome = 'initialized' | 'already-ready';
337
+ //#endregion
338
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/runtime.d.ts
339
+ /** Where a pull was fired from; `load` fires at most once per process per row. */
340
+ type PullReason = 'load' | 'add' | 'replace' | 'admission';
341
+ //#endregion
342
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/attribution.d.ts
343
+ /**
344
+ * What a pull or refresh captured about its row (named by id alongside) when
345
+ * it was issued. A result applies only while the row with that id still has
346
+ * this credential epoch and this recorded identity; a replaced credential
347
+ * bumps the epoch, so work issued for the old one is discarded.
348
+ *
349
+ * The epoch names one credential lineage of the row: a credential given by
350
+ * `add` or `replace`, through every refresh and `rotate` of it, which keep
351
+ * the epoch. Since 0.8.0 that holds across removal too: a row added under an
352
+ * id the pool held before starts past every epoch that id held (the store
353
+ * records them when it drops a row, in the config file, so every process
354
+ * sees it), so an attribution taken for a removed row is refused once the id
355
+ * is added again, even with the same identity. Writers older than 0.8.0
356
+ * start a re-added id at epoch 1 again, and a writer that does not know the
357
+ * pool can remove and re-add a row without the store seeing it; work
358
+ * attributed across either may still apply to the new credential.
359
+ */
360
+ interface Attribution {
361
+ credentialEpoch: number;
362
+ identity?: string;
363
+ }
364
+ //#endregion
365
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/rows.d.ts
366
+ type FailureHook = (rowId: string, error: PoolOperationError) => void | Promise<void>;
367
+ interface RowOperationOptions {
368
+ /** Called once, awaited, on every non-success path, before locks release. */
369
+ onFailure?: FailureHook;
370
+ /** The provider-wide lock, when an operation may change identity keying. */
371
+ providerLock?: PoolLockSpec;
372
+ /**
373
+ * Further locks taken after the row lock and the provider-wide lock, in
374
+ * this order, before the store locks: the same place `refresh` takes its
375
+ * extra locks, so a caller holding legacy locks around a row write and a
376
+ * refresh of that row acquire them in one order and cannot deadlock.
377
+ */
378
+ extraLocks?: readonly PoolLockSpec[];
379
+ }
380
+ interface RowProjection {
381
+ id: string;
382
+ type: 'oauth' | 'api';
383
+ label?: string;
384
+ enabled: boolean;
385
+ disabledReason?: string;
386
+ identity?: string;
387
+ credentialEpoch?: number;
388
+ stamp?: PoolRow['stamp'];
389
+ staged?: {
390
+ reservation: string;
391
+ };
392
+ torn?: true;
393
+ invalid?: 'roster' | 'entry';
394
+ }
395
+ interface ProtectView {
396
+ id: string;
397
+ row?: RowProjection;
398
+ rows: RowProjection[];
399
+ config: Readonly<Record<string, unknown>>;
400
+ }
401
+ type ProtectFn = (view: ProtectView) => string | undefined | Promise<string | undefined>;
402
+ interface AddOptions extends RowOperationOptions {
403
+ onExisting?: 'rotate' | 'refuse' | 'stage-duplicate';
404
+ protect?: ProtectFn;
405
+ }
406
+ /** Options of `replace` and `rotate`. Without `attribution` a call behaves as before. */
407
+ interface RowWriteOptions extends RowOperationOptions {
408
+ /**
409
+ * The credential epoch and recorded identity the caller read the row at
410
+ * when it decided on this write; an identity left out means the row had
411
+ * none. Compared exactly, under the row and store locks, before any write
412
+ * or replacement hook, including the completion of an interrupted replace.
413
+ * The call is refused (`attribution`, retryable, nothing written) once the
414
+ * row holds another epoch or identity, so a write decided on an older
415
+ * credential never overwrites the one that replaced it. `disable`, `enable`,
416
+ * `recordQuota` and `updateProviderState` take the same fence.
417
+ */
418
+ attribution?: Attribution;
419
+ }
420
+ /**
421
+ * Options of `disable`, `enable` and `remove`. The provider-wide lock guards
422
+ * changes to the recorded identity a row lock is named by; none of these
423
+ * three records an identity, so none takes it. The extra locks are taken
424
+ * where every other row write takes them, after the row lock and before the
425
+ * store locks.
426
+ */
427
+ type RowToggleOptions = Pick<RowOperationOptions, 'onFailure' | 'extraLocks'>;
428
+ /** What a `remove` protect predicate is shown, read under every lock. */
429
+ interface RemoveView {
430
+ /**
431
+ * The row as loaded; undefined when the roster no longer holds the id and
432
+ * only its state-file entry is left (an add or removal interrupted between writes).
433
+ */
434
+ row: PoolRow | undefined;
435
+ /** The config file as read under the store locks. */
436
+ config: Readonly<Record<string, unknown>>;
437
+ /** The state file as read under the store locks. */
438
+ state: Readonly<Record<string, unknown>>;
439
+ }
440
+ interface RemoveOptions extends RowToggleOptions {
441
+ /** Exact reservation required to remove a row that is still staged. */
442
+ staged?: {
443
+ reservation: string;
444
+ };
445
+ /**
446
+ * The credential the removal was decided for (since 0.11.7). Checked under
447
+ * every lock, before `protect` and before anything is written or repaired:
448
+ * - a roster row must be bound to its credential stamp, not torn, and hold
449
+ * exactly this epoch and recorded identity (absence included);
450
+ * - an orphan (only a state-file entry left, by a removal or add
451
+ * interrupted between its writes) must carry a stamp this store can bind
452
+ * to the credential beside it, and that stamp must name exactly this
453
+ * epoch and identity.
454
+ * Epochs only grow per id (a removal records the dropped epoch, and a later
455
+ * add of the id starts past it), so an orphan an interrupted later add
456
+ * left under the same id never matches the epoch of the row the caller
457
+ * meant to remove. A mismatch refuses with kind `attribution`, an orphan
458
+ * or row with no bindable stamp with kind `unbound-credential`; both leave
459
+ * the files byte for byte unchanged. Without it, `remove` drops whatever
460
+ * the id holds, as before.
461
+ *
462
+ * The epoch survives a refresh or `rotate`, so it names a credential
463
+ * lineage, not one token: a caller that must remove only an exact token
464
+ * still checks the loaded credential in `protect`.
465
+ */
466
+ attribution?: Attribution;
467
+ /**
468
+ * Awaited under every lock before anything is written; a reason refuses
469
+ * the removal (kind `row-protected`) with both files unchanged. The store
470
+ * keeps no record of a plugin's in-flight work, so this is where a plugin
471
+ * refuses an id it reserves or one its own pending-operation record (kept
472
+ * in the config or state file) still names: reading that record from the
473
+ * locked files here cannot race a writer that holds the store locks.
474
+ */
475
+ protect?: (id: string, view: RemoveView) => string | undefined | Promise<string | undefined>;
476
+ }
477
+ type RemoveResult = {
478
+ id: string;
479
+ /**
480
+ * `removed`: the roster row was dropped (and its state entry, if any).
481
+ * `completed`: only a state-file entry was left, by a removal interrupted
482
+ * between its config and state writes or an add interrupted before its
483
+ * config write, and it is now dropped.
484
+ */
485
+ outcome: 'removed' | 'completed';
486
+ };
487
+ /**
488
+ * Options of `reorder`. It names no row, so its failure hook is handed only
489
+ * the failure; it takes no row lock and no provider-wide lock, so the extra
490
+ * locks are taken first, then the store locks.
491
+ */
492
+ interface ReorderOptions {
493
+ /** Called once, awaited, on every non-success path, before the extra locks release. */
494
+ onFailure?: (error: PoolOperationError) => void | Promise<void>;
495
+ /** Locks taken, in this order, before the store locks. */
496
+ extraLocks?: readonly PoolLockSpec[];
497
+ }
498
+ type ReorderResult = {
499
+ /** The roster order now on disk. */
500
+ ids: string[];
501
+ /** `unchanged` when the roster was already in this order; nothing was written. */
502
+ outcome: 'reordered' | 'unchanged';
503
+ };
504
+ interface AddInput {
505
+ id: string;
506
+ credential: PoolCredential;
507
+ identity?: string;
508
+ label?: string;
509
+ disabled?: {
510
+ reason: string;
511
+ };
512
+ stage?: {
513
+ reservation: string;
514
+ };
515
+ /**
516
+ * Provider state for the credential, written in the same state write as
517
+ * the credential (needs the store's provider-state codec). On an `add`
518
+ * that rotates a row already holding this secret it is merged with the
519
+ * row's value (`ProviderStateCodec.merge`); left out, that row keeps its
520
+ * value.
521
+ */
522
+ providerState?: unknown;
523
+ }
524
+ /** What `replace` and `rotate` take beside the credential. */
525
+ interface CredentialWriteInput {
526
+ identity?: string;
527
+ /**
528
+ * Provider state written in the same state write as the credential. For
529
+ * `rotate` it is merged with the row's value; left out, the row keeps its
530
+ * value. For `replace` see `ProviderStateCodec.onReplace`.
531
+ */
532
+ providerState?: unknown;
533
+ }
534
+ type AddResult = {
535
+ /** The row holding the credential; an existing row's id on a re-add. */
536
+ id: string;
537
+ outcome: 'added' | 'added-disabled' | 'completed' | 'rotated' | 'exists';
538
+ credential: StoredCredential;
539
+ credentialEpoch: number;
540
+ };
541
+ /**
542
+ * Options of `disable` and `enable`. A call that passes neither
543
+ * `attribution` nor `providerState` behaves exactly as it did before 0.7.0.
544
+ */
545
+ interface RowTransitionOptions extends RowToggleOptions {
546
+ protect?: ProtectFn;
547
+ /**
548
+ * The credential epoch and recorded identity the caller's evidence for the
549
+ * transition was obtained under (as `recordQuota`'s attribution: an
550
+ * identity left out means the row had none). The call is refused
551
+ * (`attribution`, retryable, nothing written) once the row holds another
552
+ * epoch or identity, so a provider's late answer about a replaced
553
+ * credential never disables, or switches back on, the row now holding its
554
+ * successor.
555
+ */
556
+ attribution?: Attribution;
557
+ /**
558
+ * A provider-state change made in the same transaction as the transition,
559
+ * under the rules of `updateProviderState` (codec validation, the stamp
560
+ * rebound to the value, `unbound-credential` for a row no stamp of this
561
+ * store can bind it to); it requires `attribution`. The value and the
562
+ * enabled flag land together: no reader, and no crash at any write point,
563
+ * shows one without the other. Returning `DECLINE_TRANSITION` declines the
564
+ * whole call and writes nothing.
565
+ */
566
+ providerState?: RowTransitionMutator;
567
+ }
568
+ interface RowTransitionResult {
569
+ id: string;
570
+ /** The provider-state mutator declined: nothing was written. */
571
+ declined?: true;
572
+ /**
573
+ * Set when a provider-state mutator ran and did not decline: what it did
574
+ * to the value, as `updateProviderState` reports it.
575
+ */
576
+ providerStateOutcome?: UpdateProviderStateResult['outcome'];
577
+ /** The provider state the row now holds, when a mutator ran and left one. */
578
+ providerState?: unknown;
579
+ }
580
+ //#endregion
581
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/provider-state.d.ts
582
+ /**
583
+ * Receives a private copy of the row's provider state (undefined when the row
584
+ * shows none) and the row as loaded under the locks, and returns the next
585
+ * provider state; returning undefined clears it, so a mutator that means to
586
+ * keep the value returns it. It runs under the row lock and the store locks,
587
+ * so it must not call back into the store (`PoolReentryError`).
588
+ */
589
+ type ProviderStateMutator = (current: unknown | undefined, row: PoolRow) => unknown | Promise<unknown>;
590
+ type UpdateProviderStateResult = {
591
+ id: string;
592
+ /** The provider state now on disk; absent when the row has none. */
593
+ providerState?: unknown;
594
+ /**
595
+ * `unchanged`: the mutator returned what the row already shows (or cleared
596
+ * a row that holds none); nothing was written.
597
+ */
598
+ outcome: 'updated' | 'cleared' | 'unchanged';
599
+ };
600
+ /**
601
+ * Returned by the provider-state mutator of an attributed `disable` or
602
+ * `enable` to decline the whole transition: nothing is written, neither the
603
+ * provider state nor the row's enabled flag, and the call resolves with
604
+ * `declined: true`. A mutator declines when the state it is shown is newer
605
+ * than what its caller saw, such as an eligibility recorded after the
606
+ * request whose refusal is being acted on. It is a value of its own because
607
+ * `undefined` already means "clear the provider state". `Symbol.for` keeps it
608
+ * equal across two copies of this module loaded in one process.
609
+ */
610
+ declare const DECLINE_TRANSITION: unique symbol;
611
+ /**
612
+ * The provider-state mutator of an attributed `disable` or `enable`: as
613
+ * `ProviderStateMutator`, and it may also return `DECLINE_TRANSITION`.
614
+ */
615
+ type RowTransitionMutator = (current: unknown | undefined, row: PoolRow) => unknown | typeof DECLINE_TRANSITION | Promise<unknown | typeof DECLINE_TRANSITION>;
616
+ //#endregion
617
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/publication.d.ts
618
+ interface PublishPlan {
619
+ operationId: string;
620
+ remove: Array<{
621
+ id: string;
622
+ attribution: Attribution;
623
+ fingerprint?: string;
624
+ }>;
625
+ finalize: Array<{
626
+ id: string;
627
+ attribution: Attribution;
628
+ reservation: string;
629
+ enabled: boolean;
630
+ disabledReason?: string;
631
+ }>;
632
+ order: string[];
633
+ }
634
+ interface PublicationReceipt {
635
+ operationId: string;
636
+ planDigest: string;
637
+ phase: 'committed' | 'cleaned';
638
+ removed: Array<{
639
+ id: string;
640
+ credentialEpoch: number;
641
+ }>;
642
+ finalized: Array<{
643
+ id: string;
644
+ credentialEpoch: number;
645
+ reservation: string;
646
+ enabled: boolean;
647
+ }>;
648
+ }
649
+ interface PublishOptions {
650
+ protect?: ProtectFn;
651
+ extraLocks?: PoolLockSpec[];
652
+ providerLock?: PoolLockSpec;
653
+ onFailure?: FailureHook;
654
+ }
655
+ interface PublishResult {
656
+ outcome: 'published' | 'cleaned' | 'already-cleaned';
657
+ receipt: PublicationReceipt;
658
+ }
659
+ //#endregion
660
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/pull.d.ts
661
+ /** What a pull is issued with: the credential and its attribution tuple. */
662
+ interface PullRequest {
663
+ id: string;
664
+ credential: StoredCredential;
665
+ credentialEpoch: number;
666
+ identity?: string;
667
+ reason: PullReason;
668
+ }
669
+ type PullHook = (request: PullRequest) => Promise<unknown>;
670
+ //#endregion
671
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/refresh.d.ts
672
+ /** What the injected provider refresh function returns. */
673
+ interface ProviderRefreshResult {
674
+ access: string;
675
+ refresh: string;
676
+ expires: number;
677
+ expiresIn?: number;
678
+ /** The account's wire identity, when the provider reports one. */
679
+ identity?: string;
680
+ /**
681
+ * Provider state that changes with the new token (needs the store's
682
+ * provider-state codec). It is merged with the row's value on disk
683
+ * (`ProviderStateCodec.merge`) and written in the same state write as the
684
+ * rotated credential, under the same commit fence. Left out, the row keeps
685
+ * its value.
686
+ */
687
+ providerState?: unknown;
688
+ }
689
+ type ProviderRefresh = (credential: OAuthCredential & {
690
+ lastRefreshedAt?: number;
691
+ }, row: PoolRow) => Promise<ProviderRefreshResult>;
692
+ interface RefreshOptions {
693
+ /** The one provider-wide lock serialising every provider call. */
694
+ providerLock?: PoolLockSpec;
695
+ /** Taken after the provider-wide lock in this order, released in reverse. */
696
+ extraLocks?: readonly PoolLockSpec[];
697
+ /**
698
+ * Awaited once an ordinary rotation is persisted and the store locks released.
699
+ * Never called for `identity-contradicted`: its credential must not propagate
700
+ * as the row's recorded account.
701
+ */
702
+ onPersisted?: (rowId: string, credential: StoredCredential) => void | Promise<void>;
703
+ onFailure?: FailureHook;
704
+ /**
705
+ * Awaited before any lock is taken, on the locked re-read, and at commit
706
+ * time under the store locks; a reason refuses the refresh there, leaving
707
+ * the stored credential untouched and discarding any rotated material.
708
+ */
709
+ refuse?: (row: PoolRow) => string | undefined | Promise<string | undefined>;
710
+ }
711
+ type RefreshOutcome = {
712
+ status: 'rotated';
713
+ rowId: string;
714
+ credential: StoredCredential;
715
+ identity?: string;
716
+ } |
717
+ /**
718
+ * The provider's successor credential is stored bound to expectedIdentity,
719
+ * not returnedIdentity. The row stays disabled until the adapter supplies
720
+ * an identity-validated replacement credential through replace.
721
+ */
722
+ {
723
+ status: 'identity-contradicted';
724
+ rowId: string;
725
+ expectedIdentity: string;
726
+ returnedIdentity: string;
727
+ credential: StoredCredential;
728
+ } | {
729
+ status: 'refused';
730
+ rowId: string;
731
+ reason: string;
732
+ };
733
+ //#endregion
734
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/settings.d.ts
735
+ /** The plugin's settings: every top-level config key except the pool-owned ones. */
736
+ type PoolSettings = Record<string, unknown>;
737
+ type SettingsRead = {
738
+ status: 'ready';
739
+ settings: PoolSettings;
740
+ } |
741
+ /**
742
+ * The config still holds a legacy roster with no pool key. Its settings
743
+ * read the same way; `updateSettings` refuses until the pool is initialized.
744
+ */
745
+ {
746
+ status: 'pending-migration';
747
+ settings: PoolSettings;
748
+ } | {
749
+ status: 'error';
750
+ file: 'config' | 'state';
751
+ reason: string;
752
+ };
753
+ /**
754
+ * Receives a private copy of the current settings and either edits it in
755
+ * place (returning nothing) or returns the complete next settings object.
756
+ * It runs under the store locks, so it must not call back into the store:
757
+ * a store operation called from inside it is refused (`PoolReentryError`).
758
+ */
759
+ type SettingsMutator = (settings: PoolSettings) => PoolSettings | undefined | Promise<PoolSettings | undefined>;
760
+ /**
761
+ * Options of `updateSettings`. It names no row, so its failure hook is
762
+ * handed only the failure; like `reorder` it takes the extra locks, then the
763
+ * store locks, and no row or provider-wide lock.
764
+ */
765
+ interface UpdateSettingsOptions {
766
+ /** Called once, awaited, on every non-success path, before the extra locks release. */
767
+ onFailure?: (error: PoolOperationError) => void | Promise<void>;
768
+ /** Locks taken, in this order, before the store locks. */
769
+ extraLocks?: readonly PoolLockSpec[];
770
+ }
771
+ type UpdateSettingsResult = {
772
+ /** The settings now on disk. */
773
+ settings: PoolSettings;
774
+ /** `unchanged` when the mutator left the settings as they were; nothing was written. */
775
+ outcome: 'updated' | 'unchanged';
776
+ };
777
+ //#endregion
778
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/store/pool.d.ts
779
+ interface OpenPoolStoreOptions {
780
+ /** The provider every row of this pool belongs to; keys the provider-wide lock. */
781
+ provider: string;
782
+ configPath: string;
783
+ statePath: string;
784
+ quota: QuotaCodec;
785
+ /**
786
+ * The codec of the provider state kept beside each row's credential (see
787
+ * `ProviderStateCodec`). Without it no row shows a provider state, and
788
+ * every write that would set one refuses (`invalid-input`); writes that
789
+ * leave it alone keep the value on disk as it is, and `replace` clears it.
790
+ */
791
+ providerState?: ProviderStateCodec;
792
+ /**
793
+ * Refuse every credential this store did not stamp (default false, which
794
+ * loads unstamped and mis-stamped credentials as older writers left them).
795
+ * When true, a row whose `stamp` is not `bound` loads `unbound` and is no
796
+ * candidate, and every operation that would use or keep its credential or
797
+ * what was observed about it (`refresh`, quota pulls, `recordQuota`,
798
+ * `recordIdentity`, `rotate`, and an `add` of the same secret or onto the
799
+ * same credential-less row) refuses with `unbound-credential` before any
800
+ * provider call or write, checked again under the locks and at commit.
801
+ * Nothing makes such a row bound except `replace`, which starts a new
802
+ * credential epoch and drops what was observed about the old one.
803
+ * An interrupted add's state-only orphan is recovered only when its stamp
804
+ * binds the stored and incoming material, including a supplied identity and
805
+ * an API key's endpoint/header. Otherwise add refuses `unbound-credential`
806
+ * without writing; `remove(id)` explicitly discards the orphan.
807
+ */
808
+ requireCredentialStamps?: boolean;
809
+ /** Require an exact secret fingerprint for every roster-publication removal. */
810
+ requireRemovedFingerprint?: boolean;
811
+ /** Injected clock for leases, refresh stamps and `addedAt`. */
812
+ now?: () => number;
813
+ /**
814
+ * Ordered store-lock list held across every read-modify-write. Defaults to
815
+ * the older writers' `save` lock at the config path, then at the state path.
816
+ */
817
+ storeLocks?: readonly PoolLockSpec[];
818
+ /** Defaults for every lock the store takes (see `POOL_LOCK_DEFAULTS`). */
819
+ lockOptions?: Partial<PoolLockOptions>;
820
+ /** Overrides for the row locks only. */
821
+ rowLockOptions?: Partial<PoolLockOptions>;
822
+ /** The provider-wide lock; defaults to `provider-<provider>` beside the state file. */
823
+ providerLock?: PoolLockSpec;
824
+ /** Quota pull hook, fired without being awaited. */
825
+ pull?: PullHook;
826
+ /** Receives every pull failure, since no caller awaits a pull. */
827
+ onPullFailure?: (rowId: string, error: PoolOperationError) => void | Promise<void>;
828
+ logger?: PoolLogger;
829
+ /** Named write steps, awaited; a test seam for crash and ownership rows. */
830
+ onStep?: StoreContext['onStep'];
831
+ /** Awaitable hold points on the refresh and pull paths; a test seam. */
832
+ hold?: (point: HoldPoint, rowId: string) => void | Promise<void>;
833
+ onLockEvent?: LockEnvironment['onLockEvent'];
834
+ onLockStep?: LockEnvironment['onLockStep'];
835
+ }
836
+ type PoolLoad = {
837
+ status: 'ready';
838
+ schemaVersion: number;
839
+ rows: PoolRow[];
840
+ } | {
841
+ status: 'pending-migration';
842
+ roster: unknown[];
843
+ } | {
844
+ status: 'error';
845
+ file: 'config' | 'state';
846
+ reason: string;
847
+ kind?: 'snapshot-contended';
848
+ retryable?: true;
849
+ };
850
+ interface PoolStore {
851
+ /** Reads the pool and fires first-reading pulls; never writes a file itself. */
852
+ load(): Promise<PoolLoad>;
853
+ /** Reads the pool without firing anything. */
854
+ read(): Promise<PoolLoad>;
855
+ /**
856
+ * Turns a pending-migration config into an empty pool (the pool key with no
857
+ * row entries) in one locked config write, dropping the named top-level
858
+ * keys and keeping the rest. The start of a plugin's migration; a ready
859
+ * pool is left alone. Failures carry operation `initialize`.
860
+ */
861
+ initialize(input?: {
862
+ dropKeys?: readonly string[];
863
+ }): Promise<{
864
+ status: InitializeOutcome;
865
+ }>;
866
+ /**
867
+ * Adds a row, or completes or rotates the row already holding the id or
868
+ * the secret. A new row starts at credential epoch 1; since 0.8.0 one
869
+ * whose id the pool held before starts one past the highest epoch that id
870
+ * held (see `Attribution`), and an id that held `Number.MAX_SAFE_INTEGER`
871
+ * refuses (`id-removed`) before writing.
872
+ */
873
+ add(input: AddInput, options?: AddOptions): Promise<AddResult>;
874
+ publishRoster(plan: PublishPlan, options?: PublishOptions): Promise<PublishResult>;
875
+ publication(operationId: string): Promise<PublicationReceipt | undefined>;
876
+ /**
877
+ * Gives a row a new credential and a new credential epoch. Since 0.6.0 the
878
+ * row's provider state is whatever `ProviderStateCodec.onReplace` returns;
879
+ * without that hook it is `input.providerState`, else cleared.
880
+ * Optional `attribution` fences the write on the prior credential under the
881
+ * locks, before any write or replacement hook; see `RowWriteOptions`.
882
+ */
883
+ replace(id: string, credential: PoolCredential, input?: CredentialWriteInput, options?: RowWriteOptions): Promise<{
884
+ id: string;
885
+ credential: StoredCredential;
886
+ credentialEpoch: number;
887
+ }>;
888
+ /**
889
+ * Refreshes the secret a row holds without changing its account or
890
+ * endpoint. Since 0.4.1 an API key may leave out `baseURL` and `authHeader`
891
+ * to keep the row's, and one that gives another is refused
892
+ * (`endpoint-mismatch`) before writing: that is a `replace`.
893
+ * Takes the same optional attribution fence as `replace` (`RowWriteOptions`).
894
+ */
895
+ rotate(id: string, credential: RotateCredential, input?: CredentialWriteInput, options?: RowWriteOptions): Promise<{
896
+ id: string;
897
+ credential: StoredCredential;
898
+ }>;
899
+ /**
900
+ * Changes a row's provider state without touching its credential (since
901
+ * 0.6.0), under the row lock, `extraLocks` and the store locks. Refuses
902
+ * (`attribution`) once the row has moved off the credential epoch or
903
+ * identity in `fence`, and (`unknown-row`) once it is removed.
904
+ */
905
+ updateProviderState(id: string, fence: Attribution, mutator: ProviderStateMutator, options?: RowToggleOptions): Promise<UpdateProviderStateResult>;
906
+ /**
907
+ * Sets `enabled: false` and the entry's `disabledReason`. Takes the row
908
+ * lock, then `extraLocks`, then the store locks (the row lock and
909
+ * `extraLocks` since 0.2.3). Since 0.7.0 it may be fenced on the
910
+ * credential the caller's evidence is about (`attribution`) and carry a
911
+ * provider-state change that lands with it (`providerState`); see
912
+ * `RowTransitionOptions`.
913
+ */
914
+ disable(id: string, reason: string, options?: RowTransitionOptions): Promise<RowTransitionResult>;
915
+ /**
916
+ * Clears `enabled: false` and `disabledReason` (since 0.2.3); refuses with
917
+ * `duplicate-identity` when another enabled OAuth row holds the row's
918
+ * identity. Locks as `disable`, and takes the same options since 0.7.0.
919
+ */
920
+ enable(id: string, options?: RowTransitionOptions): Promise<RowTransitionResult>;
921
+ /**
922
+ * Deletes the roster row, its per-row entry and its state-file credential
923
+ * (since 0.2.3). Locks as `disable`; `protect` can refuse the id.
924
+ */
925
+ remove(id: string, options?: RemoveOptions): Promise<RemoveResult>;
926
+ /**
927
+ * Sets the roster order (since 0.2.4) in one config write. `ids` must name
928
+ * every roster id exactly once; anything else refuses with `invalid-order`
929
+ * and writes nothing. Takes `extraLocks`, then the store locks; no row or
930
+ * provider-wide lock. Roster rows and their entries are left unchanged.
931
+ */
932
+ reorder(ids: readonly string[], options?: ReorderOptions): Promise<ReorderResult>;
933
+ /**
934
+ * The plugin's settings (since 0.2.6): every top-level key of the config
935
+ * file except the pool-owned ones (`POOL_OWNED_KEYS`). Never writes.
936
+ */
937
+ readSettings(): Promise<SettingsRead>;
938
+ /**
939
+ * One locked write of the plugin's settings (since 0.2.6) beside the pool,
940
+ * in the config file. Refuses a result that sets a pool-owned key
941
+ * (`invalid-input`). Takes `extraLocks`, then the store locks.
942
+ */
943
+ updateSettings(mutator: SettingsMutator, options?: UpdateSettingsOptions): Promise<UpdateSettingsResult>;
944
+ /**
945
+ * Records the identity a lookup found for the row's credential. Since
946
+ * 0.3.1 it takes the credential epoch the lookup was issued for, and
947
+ * refuses a lookup that completes after the row was replaced
948
+ * (`attribution`) or a row recorded for another account
949
+ * (`identity-mismatch`).
950
+ */
951
+ recordIdentity(id: string, identity: string, attribution: Pick<Attribution, 'credentialEpoch'>, options?: RowOperationOptions): Promise<{
952
+ id: string;
953
+ disabled: string[];
954
+ }>;
955
+ refresh(id: string, provider: ProviderRefresh, options?: RefreshOptions): Promise<RefreshOutcome>;
956
+ recordQuota(id: string, attribution: Attribution, observation: unknown): Promise<void>;
957
+ /** Fires a pull for a row admission refused for want of a reading. */
958
+ requestReading(id: string): void;
959
+ /** Resolves once every pull fired so far has settled. */
960
+ pullsSettled(): Promise<void>;
961
+ }
962
+ //#endregion
963
+ //#region ../core/dist/paths.d.ts
964
+ /**
965
+ * The config file and the runtime-state file a store operation reads and writes.
966
+ *
967
+ * Both are required. A store function never derives one from the other, because
968
+ * a host may point its state file somewhere the derivation would not reach and
969
+ * a silently derived path would lock one file while writing another.
970
+ */
971
+ interface AccountPaths {
972
+ configPath: string;
973
+ statePath: string;
974
+ }
975
+ //#endregion
976
+ //#region ../core/dist/oauth.d.ts
977
+ interface IdTokenClaims {
978
+ chatgpt_account_id?: string;
979
+ email?: string;
980
+ organizations?: Array<{
981
+ id: string;
982
+ }>;
983
+ 'https://api.openai.com/auth'?: {
984
+ chatgpt_account_id?: string;
985
+ };
986
+ }
987
+ declare function parseJwtClaims(token: string): IdTokenClaims | undefined;
988
+ declare function extractAccountIdFromClaims(claims: IdTokenClaims): string | undefined;
989
+ interface TokenResponse {
990
+ id_token: string;
991
+ access_token: string;
992
+ refresh_token: string;
993
+ expires_in?: number;
994
+ }
995
+ /**
996
+ * Minimal shape of a fallback OAuth account for ingestion. Matches the
997
+ * fields used by upsertAccount and beginAccountLogin, compatible with
998
+ * the full OAuthAccount type in accounts.ts.
999
+ */
1000
+ interface IngestAccount {
1001
+ id: string;
1002
+ label?: string;
1003
+ type: 'oauth';
1004
+ access?: string;
1005
+ refresh: string;
1006
+ expires?: number;
1007
+ enabled: boolean;
1008
+ addedAt: number;
1009
+ lastUsed: number;
1010
+ /**
1011
+ * When the token was obtained. Stamped at login so a freshly added account
1012
+ * carries a refresh marker — without it, the runtime-state merge cannot tell a
1013
+ * rotated token from a stale one (both default to 0) and a concurrent stale
1014
+ * save could roll the token back.
1015
+ */
1016
+ lastRefreshedAt?: number;
1017
+ /** Stable ChatGPT account identifier from the OAuth token claims. */
1018
+ accountId?: string;
1019
+ }
1020
+ interface BeginAccountLoginOptions {
1021
+ label?: string;
1022
+ headless?: boolean;
1023
+ signal?: AbortSignal;
1024
+ /** Host package version, sent as the version half of the `User-Agent`. */
1025
+ version: string;
1026
+ }
1027
+ interface BeginAccountLoginResult {
1028
+ url: string;
1029
+ instructions: string;
1030
+ /** Resolves after the user completes the OAuth flow with a ready-to-ingest account. */
1031
+ completion: Promise<IngestAccount>;
1032
+ }
1033
+ /**
1034
+ * Split-return OAuth flow entry point.
1035
+ *
1036
+ * Browser flow (default):
1037
+ * 1. Start OAuth server, generate PKCE, build authorize URL
1038
+ * 2. Return { url, instructions, completion } — url is ready immediately
1039
+ * 3. completion resolves after browser callback + token exchange
1040
+ *
1041
+ * Headless flow:
1042
+ * 1. Begin device auth
1043
+ * 2. Return { url, instructions, completion }
1044
+ * 3. completion polls device endpoint + exchanges for tokens
1045
+ *
1046
+ * The split return allows the TUI command to show the URL before the
1047
+ * (potentially 30-60s) wait, avoiding a deadlock.
1048
+ */
1049
+ declare function beginAccountLogin(opts: BeginAccountLoginOptions): Promise<BeginAccountLoginResult>;
1050
+ //#endregion
1051
+ //#region ../../node_modules/.bun/@cortexkit+subc-client@0.16.1/node_modules/@cortexkit/subc-client/dist/connection-file.d.ts
1052
+ interface Endpoint {
1053
+ host: string;
1054
+ port: number;
1055
+ }
1056
+ interface ConnectionInfo {
1057
+ schema: number;
1058
+ endpoints: Endpoint[];
1059
+ /** Transport key bytes. Serialized on disk as a JSON array of numbers. */
1060
+ key: Uint8Array;
1061
+ /** 16-byte daemon identity. Serialized on disk as a JSON array of numbers. */
1062
+ daemonId: Uint8Array;
1063
+ pid: number;
1064
+ daemonVer: string;
1065
+ }
1066
+ //#endregion
1067
+ //#region ../../node_modules/.bun/@cortexkit+subc-client@0.16.1/node_modules/@cortexkit/subc-client/dist/envelope.d.ts
1068
+ /** Scheduling priority carried in flags bits 1-2. */
1069
+ declare enum Priority {
1070
+ Passive = 0,
1071
+ Interactive = 1,
1072
+ Background = 2
1073
+ }
1074
+ /** Admission behavior carried in flags bits 4-5. */
1075
+ declare enum AdmissionClass {
1076
+ Normal = 0,
1077
+ Expedite = 1,
1078
+ Sheddable = 2
1079
+ }
1080
+ //#endregion
1081
+ //#region ../../node_modules/.bun/@cortexkit+subc-client@0.16.1/node_modules/@cortexkit/subc-client/dist/route-handle.d.ts
1082
+ interface ReverseRequestContext {
1083
+ readonly corr: bigint;
1084
+ readonly method: string;
1085
+ }
1086
+ type ReverseRequestHandler = (body: Uint8Array, ctx: ReverseRequestContext) => Promise<Uint8Array> | Uint8Array;
1087
+ /**
1088
+ * Mutable handler registry prepared before route.open. The client derives
1089
+ * consumer_capabilities from its method families and seals that set when the
1090
+ * route opens; handlers for declared families may still be replaced afterward.
1091
+ */
1092
+ declare class ReverseRequestRegistry {
1093
+ private readonly handlers;
1094
+ private declaredFamilies;
1095
+ onRequest(methodFamily: string, handler: ReverseRequestHandler): void;
1096
+ /** @internal */
1097
+ capabilities(): string[];
1098
+ /** @internal */
1099
+ handler(methodFamily: string): ReverseRequestHandler | undefined;
1100
+ /** @internal */
1101
+ seal(): void;
1102
+ }
1103
+ /**
1104
+ * Immutable identity for one route binding on one live socket. Only channel and
1105
+ * epoch cross the wire; the connection token remains private to this SDK.
1106
+ */
1107
+ declare class RouteHandle {
1108
+ readonly channel: number;
1109
+ readonly epoch: number;
1110
+ private constructor();
1111
+ /** Replace the handler for a capability declared when this route opened. */
1112
+ onRequest(methodFamily: string, handler: ReverseRequestHandler): void;
1113
+ private static create;
1114
+ }
1115
+ //#endregion
1116
+ //#region ../../node_modules/.bun/@cortexkit+subc-client@0.16.1/node_modules/@cortexkit/subc-client/dist/client.d.ts
1117
+ interface BindIdentity {
1118
+ project_root: string;
1119
+ harness: string;
1120
+ session: string;
1121
+ }
1122
+ type RouteTarget = {
1123
+ kind: "tool_provider";
1124
+ module_id: string;
1125
+ } | {
1126
+ kind: "management_surface";
1127
+ module_id: string;
1128
+ } | {
1129
+ kind: "internal_service";
1130
+ module_id: string;
1131
+ service_id: string;
1132
+ };
1133
+ type ManagedRouteKind = "management_surface" | "tool_provider";
1134
+ interface ConsumerIdentity {
1135
+ module_id: string;
1136
+ launch_nonce: string;
1137
+ }
1138
+ interface RouteOpenOptions {
1139
+ /** Optional override for the consumer identity; by default the SUBC_MODULE_ID and SUBC_LAUNCH_NONCE environment variables are used when both are non-empty. Set null to send route.open without consumer_identity. */
1140
+ consumerIdentity?: ConsumerIdentity | null;
1141
+ /**
1142
+ * Handlers prepared before route.open. The client derives consumer_capabilities
1143
+ * from this registry; callers cannot declare a capability without a handler.
1144
+ */
1145
+ reverseRequests?: ReverseRequestRegistry;
1146
+ }
1147
+ interface CatalogCapabilityRequirement {
1148
+ capability: string;
1149
+ need: "required" | "optional";
1150
+ }
1151
+ interface CatalogCapabilities {
1152
+ provides: string[];
1153
+ requires: CatalogCapabilityRequirement[];
1154
+ must_never_reach: string[];
1155
+ }
1156
+ /** A self-signal's anchor relative to the external surface it shapes. */
1157
+ type CatalogSignalAnchor = "fixed_interval" | {
1158
+ event: {
1159
+ event: string;
1160
+ };
1161
+ };
1162
+ /** The source of a self-signal's effective cadence. */
1163
+ type CatalogSignalCadence = {
1164
+ literal: {
1165
+ interval_ms: number;
1166
+ };
1167
+ } | {
1168
+ derived: {
1169
+ source: string;
1170
+ };
1171
+ };
1172
+ /** A self-signal declaration mirrored from a registered module manifest. */
1173
+ interface CatalogSelfSignalDeclaration {
1174
+ name: string;
1175
+ /** Open string for forward-compatible self-signal kinds. */
1176
+ kind: string;
1177
+ effect: "observe" | "mutate";
1178
+ anchored_to: CatalogSignalAnchor;
1179
+ cadence?: CatalogSignalCadence | null;
1180
+ domain?: string | null;
1181
+ note?: string | null;
1182
+ }
1183
+ interface CatalogEntry {
1184
+ module_id: string;
1185
+ roles: unknown[];
1186
+ control_ops: string[];
1187
+ /** Static capability claims mirrored from the registered module manifest. */
1188
+ capabilities?: CatalogCapabilities | null;
1189
+ /** Self-signal declarations mirrored verbatim from the registered manifest. */
1190
+ self_signals?: CatalogSelfSignalDeclaration[] | null;
1191
+ }
1192
+ interface RequestOptions {
1193
+ priority?: Priority;
1194
+ admissionClass?: AdmissionClass;
1195
+ timeoutMs?: number;
1196
+ /**
1197
+ * Set when the request body is opaque bytes rather than JSON. This flag is the
1198
+ * receiver's only signal about the body representation; reply decoding follows
1199
+ * the response frame's flag instead of this request option.
1200
+ */
1201
+ binary?: boolean;
1202
+ /** Called for each interim PUSH / StreamData frame before the terminal reply. */
1203
+ onProgress?: (body: Uint8Array) => void;
1204
+ /**
1205
+ * Abort the request: when this fires while the request is still in flight, the
1206
+ * client emits a CANCEL frame carrying that request's own corr.
1207
+ *
1208
+ * The signal exists instead of exposing corr because corr lifetime is already
1209
+ * tracked here to settle replies; handing it out would make every caller keep a
1210
+ * second map that can disagree with this one, and would let a caller cancel a
1211
+ * corr it does not own.
1212
+ *
1213
+ * Cancellation is best-effort by the wire's construction: the daemon forwards
1214
+ * the frame on a live route and silently drops it on a departed one, and no
1215
+ * acknowledgement exists at any layer. Only the module's own reply proves what
1216
+ * happened, so the promise is NOT rejected here -- it settles however the module
1217
+ * answers, which may be a normal completion that beat the cancel.
1218
+ */
1219
+ signal?: AbortSignal;
1220
+ }
1221
+ interface ManagedCallOptions extends RequestOptions {
1222
+ /** Overrides the per-client identity used for route.open before this call. */
1223
+ identity?: BindIdentity;
1224
+ /** Defaults to management_surface, matching the store/host management APIs. */
1225
+ targetKind?: ManagedRouteKind;
1226
+ /** Optional override for the consumer identity; by default the SUBC_MODULE_ID and SUBC_LAUNCH_NONCE environment variables are used when both are non-empty. Set null to send route.open without consumer_identity. */
1227
+ consumerIdentity?: ConsumerIdentity | null;
1228
+ /** Reverse-request handlers used by the managed route and all of its reconnect reopens. */
1229
+ reverseRequests?: ReverseRequestRegistry;
1230
+ }
1231
+ interface SubscribeOptions {
1232
+ priority?: Priority;
1233
+ admissionClass?: AdmissionClass;
1234
+ }
1235
+ type RoutePollKind = "status" | "liveness";
1236
+ interface RoutePollResult {
1237
+ route_channel: number;
1238
+ route_epoch: number;
1239
+ status: string | null;
1240
+ live: boolean | null;
1241
+ }
1242
+ interface CloseRouteOptions {
1243
+ /**
1244
+ * Await in-flight UNARY requests on the route to settle before tearing it down.
1245
+ * Subscriptions are always aborted (a held-open stream cannot be drained).
1246
+ * Defaults to false: close immediately, aborting everything in flight.
1247
+ */
1248
+ drain?: boolean;
1249
+ }
1250
+ interface ManagedCloseRouteOptions extends CloseRouteOptions {
1251
+ /** Consumer identity used by the cached managed route. */
1252
+ consumerIdentity?: ConsumerIdentity | null;
1253
+ /** The registry whose derived capability set identifies the cached route. */
1254
+ reverseRequests?: ReverseRequestRegistry;
1255
+ }
1256
+ /**
1257
+ * Capped exponential reconnect backoff. maxAttempts includes the first immediate
1258
+ * reconnect attempt; sleeps happen only between failed transient attempts.
1259
+ */
1260
+ interface ReconnectBackoff {
1261
+ /** First retry delay. */
1262
+ baseMs: number;
1263
+ /** Delay ceiling (doubling is capped here). */
1264
+ capMs: number;
1265
+ /** Max attempts (including the first) before giving up. */
1266
+ maxAttempts: number;
1267
+ }
1268
+ /**
1269
+ * A live subscription to a provider's event stream, riding a single held-open
1270
+ * request. `onEvent` fires for each StreamData frame; `closed` resolves when the
1271
+ * provider ends the stream (StreamEnd) or the consumer unsubscribes, and rejects on
1272
+ * an Error terminal or a route GOODBYE. `unsubscribe` cancels the held-open request
1273
+ * so the provider unwinds.
1274
+ */
1275
+ interface Subscription {
1276
+ /** Cancel the subscription: sends Cancel on the held-open request; idempotent. */
1277
+ unsubscribe(): void;
1278
+ /** Resolves on StreamEnd or local unsubscribe; rejects on an Error terminal or route close. */
1279
+ readonly closed: Promise<void>;
1280
+ }
1281
+ interface ConnectOptions {
1282
+ connectionFile: string;
1283
+ handshakeTimeoutMs?: number;
1284
+ /** Default route identity used by managed call(); can be overridden per call. */
1285
+ identity?: BindIdentity;
1286
+ /** Default route target kind used by managed call(); defaults to management_surface. */
1287
+ targetKind?: ManagedRouteKind;
1288
+ /** Backoff for managed reconnect after a connection drop. */
1289
+ reconnectBackoff?: ReconnectBackoff;
1290
+ /** Injectable sleep for timer-free reconnect tests. */
1291
+ sleep?: (ms: number) => Promise<void>;
1292
+ /**
1293
+ * How long managed calls keep retrying route.open in-place on retryable
1294
+ * refusals (module_reloading, module_warming, target_unavailable, …) before
1295
+ * settling not_sent. This deadline is the ONLY binder on those retries —
1296
+ * module reloads legitimately take tens of seconds (the daemon's drain alone
1297
+ * defaults to 30s), so the default matches the daemon's drain ceiling.
1298
+ */
1299
+ routeOpenRetryDeadlineMs?: number;
1300
+ /**
1301
+ * Window the post-deadline liveness probe waits for ANY inbound frame after
1302
+ * sending its channel-0 Ping before convicting the socket as half-open.
1303
+ * Genuine event-loop starvation self-protects at any setting: a loop starved
1304
+ * enough to delay the probe's check also delays the read loop, and when it
1305
+ * wakes the buffered Pong dispatches first. Exposed for deterministic tests.
1306
+ */
1307
+ livenessProbeWindowMs?: number;
1308
+ /**
1309
+ * Hard cap on the timeout-arbitration grace window (see
1310
+ * TIMEOUT_ARBITRATION_GRACE_MS). A reply whose bytes are actively arriving when
1311
+ * the request deadline fires is given up to this long to finish dispatching
1312
+ * before the call settles as a timeout. Bounded and never a deadline extension;
1313
+ * exposed mainly so tests can prove the arbitration deterministically.
1314
+ */
1315
+ timeoutArbitrationGraceMs?: number;
1316
+ /**
1317
+ * Observer for daemon-originated channel-0 control pushes (`route.closing`,
1318
+ * `route.closed`, and any op added later). Purely advisory: the daemon's
1319
+ * load-bearing route-death signal remains the GOODBYE frame, and nothing in
1320
+ * the client's own route lifecycle consumes these. The contract is the wire
1321
+ * contract verbatim -- unrecognized ops still arrive here (callers ignore
1322
+ * what they don't know, per the MUST-ignore clause), a push that fails to
1323
+ * parse as JSON is dropped without surfacing, and an observer throw is
1324
+ * swallowed like every other caller callback so it cannot fail the read loop
1325
+ * or unrelated requests.
1326
+ */
1327
+ onControlPush?: (push: ControlPush) => void;
1328
+ }
1329
+ /** A parsed daemon-originated channel-0 control push. */
1330
+ interface ControlPush {
1331
+ /** The push discriminator, e.g. "route.closing" | "route.closed". */
1332
+ op: string;
1333
+ /** The full parsed body, `op` included, for op-specific fields. */
1334
+ body: Record<string, unknown>;
1335
+ }
1336
+ declare class SubcClient {
1337
+ private sock;
1338
+ private currentConn;
1339
+ private readonly opts;
1340
+ private nextCorr;
1341
+ private readonly pending;
1342
+ private readonly lateResponses;
1343
+ private readonly routes;
1344
+ private readonly liveRoutes;
1345
+ private connectionToken;
1346
+ private ingressEpochDropCount;
1347
+ private closedErr;
1348
+ private closeStarted;
1349
+ private reconnecting;
1350
+ private generation;
1351
+ private readerActive;
1352
+ private constructor();
1353
+ get conn(): ConnectionInfo;
1354
+ /** Read the connection file, connect, authenticate, and start the read loop. */
1355
+ static connect(opts: ConnectOptions): Promise<SubcClient>;
1356
+ /** List modules subc knows about (channel-0 catalog.list). */
1357
+ catalogList(moduleId?: string): Promise<CatalogEntry[]>;
1358
+ /**
1359
+ * Resolve the sole catalog claimant for a capability.
1360
+ *
1361
+ * This expresses singular intent even when the fleet permits plural claims;
1362
+ * ambiguity is returned instead of selecting an arbitrary module.
1363
+ */
1364
+ resolveProvider(capability: string): Promise<string>;
1365
+ /** Resolve every catalog claimant in deterministic module-id order. */
1366
+ resolveProviders(capability: string): Promise<string[]>;
1367
+ /** Open a route and return its connection-bound immutable handle. */
1368
+ routeOpen(target: RouteTarget, identity: BindIdentity, opts?: RouteOpenOptions): Promise<RouteHandle>;
1369
+ /** Send a data-plane request on exactly the supplied route generation. */
1370
+ request(handle: RouteHandle, body: unknown, opts?: RequestOptions): Promise<unknown>;
1371
+ /**
1372
+ * Managed route + request convenience. Opens and caches a route for the module,
1373
+ * reconnecting and re-opening cached routes after connection drops.
1374
+ */
1375
+ call<Response = unknown>(moduleId: string, method: string, params?: unknown, opts?: ManagedCallOptions): Promise<Response>;
1376
+ /**
1377
+ * Managed route + raw opaque-body request convenience. Unlike call(), this
1378
+ * sends bytes without a JSON method envelope because the BINARY flag is the
1379
+ * receiver's only signal that the body is not JSON. A BINARY reply resolves
1380
+ * to Uint8Array; a non-binary reply is decoded as JSON.
1381
+ */
1382
+ callBinary(moduleId: string, body: Uint8Array, opts?: ManagedCallOptions): Promise<Uint8Array | unknown>;
1383
+ private managedCall;
1384
+ /** Open a held request on exactly one route generation. */
1385
+ subscribe(handle: RouteHandle, body: unknown, onEvent: (event: Uint8Array) => void, opts?: SubscribeOptions): Subscription;
1386
+ /**
1387
+ * Emit CANCEL for one in-flight request when its caller's signal fires.
1388
+ *
1389
+ * Emits only while the request is unsettled by this client's own book, which is
1390
+ * a fact it owns and can check without racing. It deliberately does NOT check
1391
+ * whether the route still exists: that would be a guess, and a wrong guess turns
1392
+ * a frame the daemon would harmlessly drop into a frame never sent -- removing
1393
+ * the caller's only chance at the cost of saving nothing.
1394
+ */
1395
+ private attachCancelSignal;
1396
+ /** Send a pure-header cancellation for an in-flight request. */
1397
+ cancel(handle: RouteHandle, corr: bigint, priority?: Priority): void;
1398
+ /** Poll status or liveness for exactly the supplied route generation. */
1399
+ routePoll(handle: RouteHandle, kind: RoutePollKind): Promise<RoutePollResult>;
1400
+ /** Tear down exactly the supplied route generation. */
1401
+ closeRoute(handle: RouteHandle, opts?: CloseRouteOptions): Promise<void>;
1402
+ /** Close a cached managed route by its route-open identity tuple. */
1403
+ closeManagedRoute(target: Extract<RouteTarget, {
1404
+ kind: ManagedRouteKind;
1405
+ }>, identity: BindIdentity, opts?: ManagedCloseRouteOptions): Promise<void>;
1406
+ /** Alias retained for callers that name the operation by protocol channel; it still requires a full handle. */
1407
+ closeRouteChannel(handle: RouteHandle, opts?: CloseRouteOptions): Promise<void>;
1408
+ close(): void;
1409
+ private drainUnaryOnHandle;
1410
+ private sendRouteGoodbye;
1411
+ private static openConnection;
1412
+ private controlRpc;
1413
+ private send;
1414
+ /**
1415
+ * A request-deadline timer has fired. Before settling as a timeout, arbitrate
1416
+ * the timer-vs-poll race: a reply may already be in the socket buffer, unread
1417
+ * only because the loop was starved. Yield one check phase (setImmediate) so a
1418
+ * fully-buffered reply dispatches and wins via settle()'s identity guard; then,
1419
+ * only while the reader is actively draining THIS socket (a frame mid-arrival),
1420
+ * grant a single hard-capped grace before finally settling. Absent replies
1421
+ * still settle right after the check phase. The settle carries the deadline
1422
+ * marker so the managed classifier reports deadline-not-drop.
1423
+ */
1424
+ private arbitrateTimeout;
1425
+ private managedRequest;
1426
+ private sendManaged;
1427
+ private cachedRouteHandle;
1428
+ private openCachedRoute;
1429
+ private lastInboundAtMs;
1430
+ private livenessProbe;
1431
+ /**
1432
+ * Discriminate event-loop starvation from a half-open socket after a
1433
+ * deadline-no-drop settle. The arbitration deliberately keeps the socket on
1434
+ * that verdict (a late-read reply under load must not cost a healthy
1435
+ * connection), but a half-open socket — peer vanished with no FIN/RST, as
1436
+ * after host sleep/wake — yields the SAME verdict forever, so the keep
1437
+ * becomes a permanent pin to a dead transport. The discriminator is
1438
+ * socket-level liveness evidence: send a channel-0 Ping (the daemon always
1439
+ * answers — subc-core control.rs) and require ANY inbound frame within the
1440
+ * window; the Pong suffices, and a busy socket's other traffic proves the
1441
+ * link just as well. Silence convicts: the socket is failed with a named
1442
+ * cause and closed, so the ordinary drop path (pending rejection now,
1443
+ * reconnect on the next call) takes over.
1444
+ *
1445
+ * Starvation cannot be falsely convicted by a short window: a loop starved
1446
+ * enough to delay the read loop delays this probe's own timer identically,
1447
+ * and when both wake the buffered Pong dispatches before the check runs.
1448
+ *
1449
+ * A PENDING CHANNEL-0 REQUEST SUSPENDS THE PROBE (both at launch and at the
1450
+ * conviction check). The daemon's connection loop handles frames one at a
1451
+ * time, and some channel-0 ops legally park it for seconds — route.open
1452
+ * awaits the module's bind ack inline for up to route_bind_relay_timeout
1453
+ * (~12s in production) — during which OUR Ping sits unread in the daemon's
1454
+ * socket buffer. On an otherwise-quiet connection that silence is fully
1455
+ * explained by our own in-flight control op, and convicting on it would
1456
+ * tear down a healthy connection mid-bind (BROCA's Athena panel flagged
1457
+ * this exact premise; the FIFO fact is verified in subc-core server.rs
1458
+ * connection_loop + control.rs handle_route_open). The client always knows
1459
+ * its own channel-0 pendings, so the gate is local and exact: no probe
1460
+ * while one is in flight, no conviction if one appeared during the window.
1461
+ *
1462
+ * Scope: hooked from the managed-call path only. Control-plane requests
1463
+ * (route.open, catalog.list) are short-lived and their failures already
1464
+ * escalate through reconnect classification; the managed path is where a
1465
+ * plugin lives for hours and where the pin was observed in production.
1466
+ */
1467
+ /** Any in-flight channel-0 request (pendings keyed without a route handle). */
1468
+ private hasControlPending;
1469
+ private probeLivenessAfterDeadline;
1470
+ private ensureConnectedForManaged;
1471
+ private scheduleReconnectAfterDrop;
1472
+ private reconnectAfterDrop;
1473
+ private reconnectWithRetry;
1474
+ private replaceConnection;
1475
+ private reopenCachedRoutes;
1476
+ private timeoutMessage;
1477
+ private routeClosedDuringOpen;
1478
+ private readLoop;
1479
+ private dispatch;
1480
+ /**
1481
+ * Settle a pending exactly once. The object-identity guard (the map still
1482
+ * holds THIS pending under `key`) is the single-winner primitive: whichever of
1483
+ * dispatch, a timeout, fail(), failChannel(), a GOODBYE, or a deferred timeout
1484
+ * arbitration reaches it first wins, and every later caller no-ops. This is what
1485
+ * makes the deferred-timeout arbitration safe — it cannot double-settle, reject
1486
+ * an already-resolved promise, or delete a pending re-created for a later corr.
1487
+ * Returns true when this call was the settler.
1488
+ */
1489
+ private settle;
1490
+ private rejectPending;
1491
+ private dispatchReverseRequest;
1492
+ private sendReverseError;
1493
+ private sendReverseReply;
1494
+ private errorFromFrame;
1495
+ private evictRouteHandle;
1496
+ private failHandle;
1497
+ private fail;
1498
+ private notSentCallError;
1499
+ private outcomeUnknownCallError;
1500
+ private terminalCallError;
1501
+ private notSentRecoveryError;
1502
+ /** Number of nonzero-channel ingress frames dropped by endpoint epoch validation. */
1503
+ get droppedIngressFrames(): number;
1504
+ private installRoute;
1505
+ private isLiveHandle;
1506
+ private assertLiveConnection;
1507
+ private assertLiveHandle;
1508
+ private allocateCorr;
1509
+ private closeConnectionAfterCleanupFailure;
1510
+ private encode;
1511
+ /** Decode a terminal response according to the representation on the wire. */
1512
+ private decodeReply;
1513
+ private parseJson;
1514
+ }
1515
+ //#endregion
1516
+ //#region ../../node_modules/.bun/@cortexkit+claustrum-client@0.6.2/node_modules/@cortexkit/claustrum-client/dist/wire.d.ts
1517
+ type ClaustrumConnector = (options: {
1518
+ connectionFile: string;
1519
+ handshakeTimeoutMs?: number;
1520
+ }) => Promise<SubcClient>;
1521
+ type ClaustrumClientOptions = {
1522
+ connectionFile?: string;
1523
+ handshakeTimeoutMs?: number;
1524
+ projectRoot?: string;
1525
+ storagePath?: string;
1526
+ identity?: BindIdentity;
1527
+ connector?: ClaustrumConnector;
1528
+ logger?: (errorClass: string) => void;
1529
+ };
1530
+ /**
1531
+ * Credential material plus optional non-secret identity metadata. Missing wire fields remain
1532
+ * `undefined`; a present non-string identity value rejects the response as invalid.
1533
+ *
1534
+ * An absent identity field means the vault had nothing to assert — NOT that identity failed.
1535
+ * Consumers must not collapse absence into mismatch: assert on presence, refuse on a present
1536
+ * difference, and serve (log, if it matters) when the field is missing. Absence proves neither
1537
+ * the right identity nor the wrong one, so treating it as a failure converts a vault that could
1538
+ * not answer into a consumer that cannot serve. The vault records no per-read success (at most
1539
+ * the first scoped read per principal), and nothing at all when a consumer declines to serve, so
1540
+ * an outage caused that way is visible only to the consumer that caused it.
1541
+ */
1542
+ type ServedCredential = {
1543
+ material: string;
1544
+ recordVersion: number;
1545
+ expiresAtMs: number | null;
1546
+ /**
1547
+ * Operator-chosen record label for verifying a caller-held binding. It is not a routing key:
1548
+ * account-scoped routing joins `accountId` with `recordVersion`.
1549
+ */
1550
+ credentialId?: string;
1551
+ /** Non-secret Code Assist project identity, present only for antigravity credentials. */
1552
+ projectId?: string;
1553
+ /**
1554
+ * Provider account identity the served token executes under. Account-scoped routing joins this
1555
+ * value with `recordVersion`; it is neither the operator's credential label nor the bearer handle.
1556
+ *
1557
+ * BEST-EFFORT, NEVER GUARANTEED, including for JWT providers. The vault parses the claim live
1558
+ * from the served access token and falls back to stored login-time identity; both legs can be
1559
+ * empty, and the serve path yields nothing rather than fabricating an id. It is absent when the
1560
+ * provider has no known claim, the token does not carry one, or no identity was captured at
1561
+ * login. Do not gate serving on its presence.
1562
+ */
1563
+ accountId?: string;
1564
+ /** Non-secret account display metadata captured at login. */
1565
+ email?: string;
1566
+ /** Non-secret organization or workspace display metadata captured at login. */
1567
+ orgName?: string;
1568
+ };
1569
+ /**
1570
+ * Non-secret health for one handle, read without minting anything.
1571
+ *
1572
+ * An unresolved handle (unknown or revoked) is an ordinary answer, not an error: it decodes
1573
+ * as `ready: false, lastErrorCode: 'not_found'` with `credentialId`, `recordVersion` and
1574
+ * `stalePending` all absent. The vault omits them on purpose so a probe learns nothing about
1575
+ * what exists and no placeholder value is asserted about a record it never saw.
1576
+ */
1577
+ type CredentialStatus = {
1578
+ ready: boolean;
1579
+ lastErrorCode: string | null;
1580
+ leaseHeld: boolean;
1581
+ /**
1582
+ * Operator-chosen record label the handle resolved to, for verifying a binding the caller
1583
+ * already holds. Not a routing key. Absent when the handle did not resolve.
1584
+ */
1585
+ credentialId?: string;
1586
+ /**
1587
+ * The record's change cursor, present only when the handle resolved to a record.
1588
+ *
1589
+ * Optional, and OMITTED from the object rather than defaulted, because there is no honest
1590
+ * default: 0 or -1 would compare as older than every real version, so a poller would read a
1591
+ * revoked handle as a change it had yet to see, forever. With the key absent, TypeScript
1592
+ * refuses arithmetic or ordering on it until the caller has handled `undefined`, and
1593
+ * `'recordVersion' in status` is false. Never replace absence with a number (`?? 0`).
1594
+ */
1595
+ recordVersion?: number;
1596
+ stalePending?: boolean;
1597
+ };
1598
+ type ClaustrumReporterSource = 'direct' | 'relay_status_field' | 'relay_message_parse';
1599
+ declare class ClaustrumClient {
1600
+ #private;
1601
+ private constructor();
1602
+ static connect(options?: ClaustrumClientOptions): Promise<ClaustrumClient>;
1603
+ getCredential(handle: string, minTtlMs?: number): Promise<ServedCredential>;
1604
+ statusCredential(handle: string): Promise<CredentialStatus>;
1605
+ reportAuthFailure(input: {
1606
+ handle: string;
1607
+ providerStatus: number;
1608
+ recordVersion: number;
1609
+ reporterSource: ClaustrumReporterSource;
1610
+ }): Promise<void>;
1611
+ /**
1612
+ * Enumerate what this caller's grants cover.
1613
+ *
1614
+ * `params` is `{}` and must be PRESENT: the vault rejects an absent or null params
1615
+ * object, so a caller cannot ask a different question by omitting it.
1616
+ */
1617
+ listScoped(enrollmentToken?: string): Promise<ScopedInventory>;
1618
+ /**
1619
+ * Fetch by credential id, authorized by a grant rather than a bearer handle.
1620
+ *
1621
+ * `minTtlMs` is a DEMAND, not a hint: if a real upstream exchange still cannot satisfy
1622
+ * it, the vault refuses with `ttl_unsatisfiable` (class `context_overflow`) rather than
1623
+ * serving a token that will die inside the caller's own margin. That class means
1624
+ * reduce-and-retry, never wait-and-retry.
1625
+ */
1626
+ getScoped(input: {
1627
+ credentialId: string;
1628
+ enrollmentToken?: string;
1629
+ minTtlMs?: number;
1630
+ }): Promise<ServedCredential>;
1631
+ /**
1632
+ * Report a served credential dead, addressed by id rather than by handle.
1633
+ *
1634
+ * VERSION-FENCED: `recordVersion` must be the one this caller was SERVED. A report
1635
+ * against a since-refreshed version is accepted and does nothing, which is the point --
1636
+ * a stale report must not kill a fresh token. `accepted: true` is the receipt that the
1637
+ * report was taken, never evidence that it applied.
1638
+ */
1639
+ reportAuthFailureScoped(input: {
1640
+ credentialId: string;
1641
+ enrollmentToken?: string;
1642
+ providerStatus: number;
1643
+ recordVersion: number;
1644
+ reporterSource: ClaustrumReporterSource;
1645
+ }): Promise<void>;
1646
+ /**
1647
+ * Propose an enrollment. The consumer mints `requestSecret` itself and sends only its
1648
+ * hash; the raw secret NEVER leaves the process, and it is what authorizes the poll.
1649
+ *
1650
+ * IDEMPOTENT ON (name, secret): re-proposing with the same secret returns the SAME
1651
+ * `requestId`. That exists because `requestId` is minted server-side, so a consumer
1652
+ * cannot persist it before proposing -- a crash in that window would otherwise leave it
1653
+ * holding a secret it cannot poll with and a name held until TTL. Persist the secret
1654
+ * BEFORE calling this, and a crash costs nothing.
1655
+ *
1656
+ * A different secret on the same name is a different caller and is refused.
1657
+ */
1658
+ enrollPropose(input: {
1659
+ name: string;
1660
+ requestSecretHash: string;
1661
+ }): Promise<{
1662
+ requestId: string;
1663
+ }>;
1664
+ /**
1665
+ * Poll a proposal. Returns `pending` until an operator decides, then exactly once
1666
+ * returns the token.
1667
+ *
1668
+ * THE TOKEN IS RETURNED ONCE. Persist it before doing anything else with it; a lost
1669
+ * token needs a fresh ceremony, not a second poll.
1670
+ */
1671
+ enrollPoll(input: {
1672
+ requestId: string;
1673
+ requestSecret: string;
1674
+ }): Promise<EnrollmentPollOutcome>;
1675
+ /**
1676
+ * Exchange a live token for its successor. The old token dies when the new one is issued.
1677
+ *
1678
+ * `expectedTokenGeneration` IS REQUIRED AND IS A FENCE, not bookkeeping: it must be the
1679
+ * generation this caller currently holds. Two rotations racing — a retry after an
1680
+ * uncertain reply, or two instances of the same consumer — would otherwise each mint a
1681
+ * successor and each invalidate the other's, leaving a consumer holding a token the
1682
+ * vault has already replaced. The vault refuses a rotation whose expectation does not
1683
+ * match, so the loser learns it lost instead of discovering it on a later spend.
1684
+ */
1685
+ enrollRotate(input: {
1686
+ token: string;
1687
+ expectedTokenGeneration: number;
1688
+ }): Promise<{
1689
+ token: string;
1690
+ tokenGeneration: number;
1691
+ }>;
1692
+ close(): void;
1693
+ }
1694
+ /**
1695
+ * A row from the caller's own grant-covered inventory.
1696
+ *
1697
+ * Selection fields answer different questions. Pick by what you are about
1698
+ * to do with the token:
1699
+ *
1700
+ * - `providerIds` — operator-assigned catalog provider ids; match exactly, with no fallback.
1701
+ * - `authMethod` — the closed authentication method derived from the unsealed record,
1702
+ * not the id spelling. Absent on sign/open-only rows or when no method is defined.
1703
+ *
1704
+ * - `refreshAdapter` — whose PROTOCOL the credential speaks. Use it when the token
1705
+ * goes to a provider's own endpoints. Anything else is invalid there.
1706
+ * - `serves` — which model VENDORS are reachable through it. Use it when choosing
1707
+ * where a model can be served from, and the protocol is not yours to care about.
1708
+ *
1709
+ * Never infer these fields from the id spelling. A credential reaching Anthropic models
1710
+ * through OpenRouter still speaks OpenRouter's protocol, not Anthropic's.
1711
+ */
1712
+ interface ScopedInventoryRow {
1713
+ readonly id: string;
1714
+ readonly categories: readonly string[];
1715
+ readonly credentialType: string;
1716
+ readonly serves: readonly string[];
1717
+ /**
1718
+ * Operator-assigned catalog ids; empty when none are set. Always present on this type.
1719
+ * A daemon older than the field omits it from the wire, and that decodes as empty,
1720
+ * which is also what an unmapped credential reports.
1721
+ */
1722
+ readonly providerIds: readonly string[];
1723
+ readonly authMethod?: 'apikey' | 'chatgpt' | 'antigravity' | 'oauth';
1724
+ /**
1725
+ * Which provider protocol this credential speaks. Absent for static keys.
1726
+ *
1727
+ * SELECT ON THIS, NOT ON `serves`, WHEN THE TOKEN GOES TO A PROVIDER'S OWN ENDPOINTS.
1728
+ * Measured on a live vault: eight rows serve Anthropic models and only five are Claude
1729
+ * OAuth -- openrouter, antigravity and cursor reach Anthropic models through their own
1730
+ * APIs. The id spelling does not separate them either: two contain no "anthropic" at
1731
+ * all, and `credentialType === 'oauth'` catches antigravity and cursor too.
1732
+ */
1733
+ readonly refreshAdapter?: string;
1734
+ readonly state: string;
1735
+ readonly recordVersion: number;
1736
+ readonly operations: readonly string[];
1737
+ /**
1738
+ * NOT SERVED TODAY. The field is absent from `ListScopedCredential`, so this is always
1739
+ * null; it is declared because a consumer's discovery high-water mark needs it and the
1740
+ * absence should be visible in the type rather than discovered at runtime.
1741
+ */
1742
+ readonly createdAtMs: number | null;
1743
+ readonly accountId?: string;
1744
+ readonly email?: string;
1745
+ readonly orgName?: string;
1746
+ }
1747
+ /**
1748
+ * An inventory reply: the covered rows, plus the cursor that says whether they moved.
1749
+ *
1750
+ * `view` is a DIGEST OVER WHAT THIS CALLER CAN SEE — ids, categories, state, operations —
1751
+ * and deliberately NOT over `record_version`, so a routine token refresh does not move it.
1752
+ * Compare it against the previous call's to decide whether to reconcile at all; it is an
1753
+ * opaque string and nothing but equality is defined on it.
1754
+ */
1755
+ interface ScopedInventory {
1756
+ readonly rows: readonly ScopedInventoryRow[];
1757
+ readonly view: string;
1758
+ }
1759
+ /** What a poll found. `pending` is not an error: the operator has not decided yet. */
1760
+ type EnrollmentPollOutcome = {
1761
+ readonly status: 'pending';
1762
+ } | {
1763
+ readonly status: 'approved';
1764
+ readonly name: string;
1765
+ readonly token: string;
1766
+ readonly tokenGeneration: number;
1767
+ } | {
1768
+ readonly status: 'denied';
1769
+ };
1770
+ //#endregion
1771
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/claustrum/custody.d.ts
1772
+ type ClaustrumScopedClient = Pick<ClaustrumClient, 'listScoped' | 'getScoped' | 'reportAuthFailureScoped' | 'close'>;
1773
+ /** The two credential types a plugin's family can hold; routing differs by type. */
1774
+ type VaultCredentialType = 'oauth' | 'api_key';
1775
+ /**
1776
+ * Why a listed vault record could not be used. A closed set of fixed codes, so
1777
+ * a log line or a roster file that carries one never echoes vault data.
1778
+ */
1779
+ type SkippedVaultReason = 'empty credential id' | 'duplicate credential id' | 'blank account identity' | 'empty state';
1780
+ /**
1781
+ * A vault record this consumer could not use. `credentialId` is absent when
1782
+ * the record's id itself was unusable, so nothing can say which account the
1783
+ * record was.
1784
+ */
1785
+ interface SkippedVaultRecord {
1786
+ readonly credentialId?: string;
1787
+ readonly reason: SkippedVaultReason;
1788
+ }
1789
+ /**
1790
+ * Where a receipt's `accountIdentity` came from: the vault asserted it in the
1791
+ * served reply, the plugin's `parseIdentity` read it from the served token, or
1792
+ * neither did and it is only the roster's expectation (`none`: no identity at
1793
+ * all).
1794
+ */
1795
+ type AccountIdentitySource = 'asserted' | 'parsed' | 'expected' | 'none';
1796
+ /**
1797
+ * A receipt: what the vault served for one physical send. Each attempt gets
1798
+ * its own. It records the exact record version served, because a 401 for
1799
+ * this send is reported to the vault against that version.
1800
+ */
1801
+ interface ClaustrumScopedAttempt {
1802
+ readonly credentialId: string;
1803
+ readonly credentialType: VaultCredentialType;
1804
+ /**
1805
+ * The account this receipt is bound to: the vault's assertion, else the
1806
+ * plugin's parse of the token, else the roster's expectation. Check
1807
+ * `accountIdentitySource` before treating it as proof.
1808
+ */
1809
+ readonly accountIdentity?: string;
1810
+ readonly accountIdentitySource: AccountIdentitySource;
1811
+ /** The account the roster row named when this receipt was requested. */
1812
+ readonly expectedAccountIdentity?: string;
1813
+ /** The credential id the vault itself put in the served reply, if any. */
1814
+ readonly assertedCredentialId?: string;
1815
+ /**
1816
+ * The account the vault itself put in the served reply, if any. Never filled
1817
+ * in from the roster or from a token parse.
1818
+ */
1819
+ readonly assertedAccountIdentity?: string;
1820
+ /**
1821
+ * The non-secret Google Cloud project id the vault served in get_scoped for
1822
+ * this attempt, if any. Never filled in from list_scoped, the roster or a
1823
+ * token parse. A project change in the vault takes effect on the next send.
1824
+ */
1825
+ readonly projectId?: string;
1826
+ /**
1827
+ * Kept in memory only and hidden from JSON.stringify and object spreads, so
1828
+ * logging a receipt never leaks it. Authorize again for every dispatch and retry.
1829
+ */
1830
+ readonly accessToken: string;
1831
+ readonly recordVersion: number;
1832
+ readonly expiresAtMs: number | null;
1833
+ }
1834
+ //#endregion
1835
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/quota/map.d.ts
1836
+ interface QuotaReadingEntry {
1837
+ scope: string;
1838
+ label: string;
1839
+ kind: 'reading';
1840
+ checkedAt: number;
1841
+ usedPercent: number;
1842
+ /** ISO timestamp at which the window resets, as the provider reported it. */
1843
+ resetsAt?: string;
1844
+ /** Window length in minutes, when the provider reported one. */
1845
+ windowMinutes?: number;
1846
+ }
1847
+ interface QuotaRetiredEntry {
1848
+ scope: string;
1849
+ label: string;
1850
+ kind: 'retired';
1851
+ retiredAt: number;
1852
+ }
1853
+ interface QuotaAbsentEntry {
1854
+ scope: string;
1855
+ label: string;
1856
+ kind: 'absent';
1857
+ checkedAt: number;
1858
+ }
1859
+ type QuotaEntry = QuotaReadingEntry | QuotaRetiredEntry | QuotaAbsentEntry;
1860
+ interface CreditBudgetReading {
1861
+ kind: 'reading';
1862
+ checkedAt: number;
1863
+ /** The provider's own verdict that the budget is spent. */
1864
+ reached: boolean;
1865
+ remainingPercent?: number;
1866
+ usedPercent?: number;
1867
+ resetsAt?: string;
1868
+ limit?: number;
1869
+ used?: number;
1870
+ remaining?: number;
1871
+ unit?: string;
1872
+ }
1873
+ interface CreditBudgetCleared {
1874
+ kind: 'cleared';
1875
+ checkedAt: number;
1876
+ }
1877
+ type CreditBudgetEntry = CreditBudgetReading | CreditBudgetCleared;
1878
+ interface QuotaMap {
1879
+ limits: QuotaEntry[];
1880
+ /** Absent means no observation has reported on the budget yet. */
1881
+ budget?: CreditBudgetEntry;
1882
+ }
1883
+ //#endregion
1884
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/claustrum/interlock.d.ts
1885
+ /**
1886
+ * The declined-account interlock: the user's "do not use this vault account",
1887
+ * kept on the consumer side because the vault has no notion of it.
1888
+ *
1889
+ * A decline follows the provider account, not the vault record: an entry made
1890
+ * while the account was known matches any credential id or alias that logs
1891
+ * into that same account, so relabelling, adding an alias or removing and
1892
+ * re-adding the account never lifts it. A credential id that now logs into a
1893
+ * different known account does not match, because that account has its own
1894
+ * policy. While either side's account is unknown the entry falls back to the
1895
+ * credential id, so an adapter that makes no identity claim cannot slip past
1896
+ * it. Never keyed on the record version, so a token refresh cannot lift it.
1897
+ */
1898
+ interface DeclinedAccount {
1899
+ readonly credentialId: string;
1900
+ readonly accountIdentity?: string;
1901
+ }
1902
+ //#endregion
1903
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/claustrum/roster.d.ts
1904
+ /**
1905
+ * One vault account as the pool sees it. It carries no bearer material: the
1906
+ * access token is fetched from the vault for every send. Several vault
1907
+ * records logged into the same provider account collapse into one row, so
1908
+ * duplicate logins never count as extra quota.
1909
+ */
1910
+ interface VaultRosterRow {
1911
+ routeId: string;
1912
+ credentialId: string;
1913
+ credentialType: VaultCredentialType;
1914
+ accountIdentity?: string;
1915
+ /** Other credential ids logged into the same provider account. */
1916
+ aliases?: string[];
1917
+ state: string;
1918
+ label: string;
1919
+ email?: string;
1920
+ orgName?: string;
1921
+ enabled: boolean;
1922
+ addedAt: number;
1923
+ quota?: QuotaMap;
1924
+ /**
1925
+ * The vault listed this record in a form this consumer could not use, so the
1926
+ * row is the last good projection kept as it was rather than dropped.
1927
+ */
1928
+ stale?: true;
1929
+ /**
1930
+ * The vault's latest list named no account for `credentialId`, so
1931
+ * `accountIdentity` is the last account that credential was known to log
1932
+ * into, kept until the vault names one again. It proves neither that the
1933
+ * credential still logs into that account nor that it changed accounts.
1934
+ */
1935
+ unclaimed?: true;
1936
+ }
1937
+ interface VaultRosterFile {
1938
+ version: 1;
1939
+ view?: string;
1940
+ /**
1941
+ * False when the vault's reply carried records this consumer could not use.
1942
+ * An incomplete reply never removes an account it may still hold: every
1943
+ * previous member it does not account for is kept.
1944
+ */
1945
+ complete: boolean;
1946
+ /** The unusable records of an incomplete reply: a safe id and a fixed reason. */
1947
+ rejected?: SkippedVaultRecord[];
1948
+ rows: VaultRosterRow[];
1949
+ declined: DeclinedAccount[];
1950
+ }
1951
+ /**
1952
+ * The receipt fields a quota or profile observation must carry to say which
1953
+ * send (credential and account) it came from. Pass the
1954
+ * `ClaustrumScopedAttempt` that send was authorized with.
1955
+ */
1956
+ type QuotaReceipt = Pick<ClaustrumScopedAttempt, 'credentialId' | 'accountIdentity' | 'accountIdentitySource' | 'expectedAccountIdentity'>;
1957
+ //#endregion
1958
+ //#region ../../node_modules/.bun/@cortexkit+common-auth@0.14.2+49be191d46b46482/node_modules/@cortexkit/common-auth/dist/claustrum/enrollment.d.ts
1959
+ interface ClaustrumEnrollmentClient {
1960
+ enrollPropose(input: {
1961
+ name: string;
1962
+ requestSecretHash: string;
1963
+ }): Promise<{
1964
+ requestId: string;
1965
+ }>;
1966
+ enrollPoll(input: {
1967
+ requestId: string;
1968
+ requestSecret: string;
1969
+ }): Promise<EnrollmentPollOutcome>;
1970
+ }
1971
+ interface ClaustrumEnrollmentConnection extends ClaustrumEnrollmentClient {
1972
+ close(): void;
1973
+ }
1974
+ type ClaustrumEnrollmentStatus = {
1975
+ state: 'idle';
1976
+ } | {
1977
+ state: 'pending';
1978
+ proposedName: string;
1979
+ requestId?: string;
1980
+ retryCode?: string;
1981
+ } | {
1982
+ state: 'approved';
1983
+ proposedName: string;
1984
+ approvedName?: string;
1985
+ tokenGeneration: number;
1986
+ } | {
1987
+ state: 'denied';
1988
+ proposedName: string;
1989
+ } | {
1990
+ state: 'blocked';
1991
+ proposedName: string;
1992
+ code: string;
1993
+ } | {
1994
+ state: 'unavailable';
1995
+ proposedName: string;
1996
+ code: string;
1997
+ } | {
1998
+ state: 'busy';
1999
+ };
2000
+ interface ClaustrumEnrollmentPaths {
2001
+ statePath: string;
2002
+ tokenPath: string;
2003
+ }
2004
+ //#endregion
2005
+ //#region ../core/dist/vault.d.ts
2006
+ type VaultHost = 'opencode' | 'pi';
2007
+ interface VaultPaths extends ClaustrumEnrollmentPaths {
2008
+ /** The roster: the vault accounts, their quota and the declined ones. Holds no token. */
2009
+ rosterPath: string;
2010
+ }
2011
+ /** One vault account as routing sees it. */
2012
+ interface VaultRoute {
2013
+ id: string;
2014
+ kind: 'oauth' | 'api-key';
2015
+ /** The ChatGPT account it signs in as, when the vault knows it. */
2016
+ identity?: string;
2017
+ quota?: QuotaMap;
2018
+ }
2019
+ interface VaultStatus {
2020
+ host: VaultHost;
2021
+ /** The name this host enrolls as. */
2022
+ name: string;
2023
+ enrollment: ClaustrumEnrollmentStatus;
2024
+ /** Every vault account this host can see, declined and cold ones included. */
2025
+ accounts: readonly VaultRosterRow[];
2026
+ lastError?: string;
2027
+ }
2028
+ interface VaultWaitOptions {
2029
+ /** Called with each status while the request waits for approval. */
2030
+ onPending?: (status: ClaustrumEnrollmentStatus) => void;
2031
+ pollIntervalMs?: number;
2032
+ timeoutMs?: number;
2033
+ sleep?: (ms: number) => Promise<void>;
2034
+ }
2035
+ interface OpenAiVaultOptions {
2036
+ host: VaultHost;
2037
+ /** This host's vault directory; see `vaultStateDir`. */
2038
+ stateDir: string;
2039
+ /** The vault's connection file; `CLAUSTRUM_SUBC_CONNECTION` or the default by default. */
2040
+ connectionFile?: () => string;
2041
+ /** The project this host runs in, part of the identity the vault sees. */
2042
+ projectRoot?: string;
2043
+ /** Replaces the request-path connection (tests). */
2044
+ connectScoped?: () => Promise<ClaustrumScopedClient>;
2045
+ /** Replaces the setup-only enrollment connection (tests). */
2046
+ connectEnrollment?: () => Promise<ClaustrumEnrollmentConnection>;
2047
+ /** Ids of the local pool rows; no vault route takes one. */
2048
+ reservedRouteIds?: () => Iterable<string>;
2049
+ /** How often the roster is re-read from the vault; 0 stops the poll. */
2050
+ pollIntervalMs?: number;
2051
+ fetchImpl?: () => typeof fetch;
2052
+ now?: () => number;
2053
+ }
2054
+ /** One host's view of its OpenAI accounts in the vault. */
2055
+ declare class OpenAiVault {
2056
+ #private;
2057
+ readonly host: VaultHost;
2058
+ readonly name: string;
2059
+ readonly paths: VaultPaths;
2060
+ constructor(options: OpenAiVaultOptions);
2061
+ /** Read enrollment files before a request, menu action or background pass, using common-auth's mode rules. */
2062
+ authority(): Promise<'vault' | 'local' | 'unreadable'>;
2063
+ /**
2064
+ * Callbacks that cannot await use the last authority value only while the
2065
+ * enrollment files are unchanged. Before the first read, or after a change,
2066
+ * local token refreshes, quota polls and account writes are blocked.
2067
+ * Requests and menus await authority() instead of trusting the cached value.
2068
+ */
2069
+ enrolled(): boolean;
2070
+ /**
2071
+ * Polls enrollment files and the vault's accounts. With local authority the
2072
+ * consumer sends no vault request. A new enrollment completed by another
2073
+ * process is detected on the next poll.
2074
+ */
2075
+ start(): void;
2076
+ /**
2077
+ * Resolves once this instance's first roster discovery has ended, whether
2078
+ * it read the vault or failed, or once the instance is closed. Never
2079
+ * rejects. A vault-mode request waits for it, bounded by
2080
+ * `VAULT_REQUEST_ROSTER_WAIT_MS`.
2081
+ */
2082
+ firstRoster(): Promise<void>;
2083
+ /**
2084
+ * Re-reads the accounts from the vault now. Never rejects. It resolves only
2085
+ * after a discovery that began after this call: one already in flight (the
2086
+ * poll, or a refresh another caller started) may have read the enrollment
2087
+ * and the vault before what this caller just changed, so it is waited out
2088
+ * and a new one runs. Callers that arrive while that new one runs share it.
2089
+ */
2090
+ refresh(): Promise<VaultRosterFile | undefined>;
2091
+ snapshot(): VaultRosterFile | undefined;
2092
+ /** Whether the vault serves this host any account (whatever its state). */
2093
+ serves(): boolean;
2094
+ /**
2095
+ * The ChatGPT accounts the vault holds for this host, declined and cold
2096
+ * ones included. Empty unless this host is enrolled; while it is, no local
2097
+ * row is used at all (vault mode), so this only names which vault account
2098
+ * a set-aside local row belongs to.
2099
+ */
2100
+ identities(): ReadonlySet<string>;
2101
+ /** The vault accounts that may route now: enabled and active. */
2102
+ routes(): VaultRoute[];
2103
+ /** Whether a route id names a vault account. */
2104
+ owns(routeId: string): boolean;
2105
+ /**
2106
+ * Sends one request on a vault account. `dispatch` sends with the token
2107
+ * the vault serves for this attempt and may be called twice (a 401 is
2108
+ * retried once when the vault has a newer version of the same login), so
2109
+ * it must be able to rebuild its body. Returns undefined when the vault
2110
+ * refused before anything was sent (not enrolled, declined, cold,
2111
+ * unreachable): the caller treats the account like a row with no token.
2112
+ * An error from `dispatch` itself (a transport failure, an abort) is
2113
+ * rethrown.
2114
+ */
2115
+ send(routeId: string, dispatch: (token: string, attempt: ClaustrumScopedAttempt) => Promise<Response>, options: {
2116
+ site: string;
2117
+ signal?: AbortSignal;
2118
+ }): Promise<Response | undefined>;
2119
+ /**
2120
+ * Authorizes one send on a vault account for a caller that sends the
2121
+ * request itself (OpenCode 2's host does): the receipt holds the token to
2122
+ * send with and the record version a 401 on that send is reported
2123
+ * against (`reportFailure`). Undefined when the vault refused (not
2124
+ * enrolled, declined, cold, unreachable): the caller treats the account
2125
+ * like a row with no token. Authorize again for every send; a receipt is
2126
+ * never reused.
2127
+ */
2128
+ authorize(routeId: string, options?: {
2129
+ signal?: AbortSignal;
2130
+ }): Promise<ClaustrumScopedAttempt | undefined>;
2131
+ /**
2132
+ * Reports the provider's answer to a send made with `authorize`'s receipt.
2133
+ * Only a 401 is reported, against the receipt's record version; anything
2134
+ * else is ignored. The roster is re-read afterwards so an account the
2135
+ * vault now marks as needing a new login stops routing. Never rejects.
2136
+ */
2137
+ reportFailure(attempt: ClaustrumScopedAttempt, status: number): Promise<void>;
2138
+ /**
2139
+ * Records a quota snapshot (response headers, a WebSocket rate-limit frame,
2140
+ * a usage poll) for a vault account. `receipt` is what the send that
2141
+ * produced the reading was served with (its credential id and the account
2142
+ * it was bound to, and how that account was known); the reading is kept
2143
+ * only while the route still holds that credential and account, so a
2144
+ * reading taken before the vault replaced the account is dropped. Runs in
2145
+ * the background; a failure is logged.
2146
+ */
2147
+ recordSnapshot(routeId: string, snapshot: unknown, complete: boolean, receipt: QuotaReceipt): Promise<void>;
2148
+ /** Takes one quota reading for a vault account through the usage endpoint. */
2149
+ pollQuota(routeId: string): Promise<{
2150
+ ok: boolean;
2151
+ error?: string;
2152
+ }>;
2153
+ /**
2154
+ * Asks for a quota reading of a vault account that admission refused
2155
+ * because it has no reading yet. At most one reading per account is in
2156
+ * flight.
2157
+ */
2158
+ requestReading(routeId: string): void;
2159
+ /** Readings for the routable vault accounts whose last one is older than `maxAgeMs`. */
2160
+ pollStale(maxAgeMs: number): Promise<Array<{
2161
+ id: string;
2162
+ ok: boolean;
2163
+ error?: string;
2164
+ }>>;
2165
+ /** Declines a vault account: it stays listed and never routes until accepted. */
2166
+ decline(routeId: string): Promise<void>;
2167
+ accept(routeId: string): Promise<void>;
2168
+ status(): Promise<VaultStatus>;
2169
+ /**
2170
+ * One step of enrollment: proposes this host to the vault, or polls the
2171
+ * proposal already on disk. A denied or blocked request is cleared first,
2172
+ * so Connect always starts a usable request.
2173
+ */
2174
+ connectStep(): Promise<ClaustrumEnrollmentStatus>;
2175
+ /**
2176
+ * Polls the enrollment until the operator approves or denies it, or until
2177
+ * `timeoutMs`. One wait runs at a time; a second caller shares it.
2178
+ */
2179
+ waitForApproval(options?: VaultWaitOptions): Promise<ClaustrumEnrollmentStatus>;
2180
+ /**
2181
+ * Forgets this host's enrollment: its token and ceremony state are
2182
+ * deleted, and the vault accounts stop routing at once. The roster (the
2183
+ * declined accounts and their quota) is kept for a later Connect. The
2184
+ * enrollment itself stays approved in the vault until the operator revokes
2185
+ * it there.
2186
+ */
2187
+ disconnect(): Promise<void>;
2188
+ /**
2189
+ * Refuses a real login in the host's own slot while the vault serves this
2190
+ * host's accounts: serving either one would silently pick one of two
2191
+ * accounts the user may not mean. The pool placeholder and the old
2192
+ * tombstone are not logins and must be screened out by the caller.
2193
+ */
2194
+ assertHostSlot(auth: unknown): void;
2195
+ close(): void;
2196
+ }
2197
+ //#endregion
2198
+ //#region src/core/version-fence.d.ts
2199
+ /** One live process that keeps the fence shut. */
2200
+ interface VersionFenceBlocker {
2201
+ /** `'unknown'` when a whole directory could not be read. */
2202
+ pid: number | 'unknown';
2203
+ /** The version its heartbeat names, or `'unknown'`. */
2204
+ version: string;
2205
+ /** The file or directory that showed it. */
2206
+ detail: string;
2207
+ }
2208
+ type VersionFenceResult = {
2209
+ open: true;
2210
+ } | {
2211
+ open: false;
2212
+ blockers: VersionFenceBlocker[];
2213
+ };
2214
+ //#endregion
2215
+ //#region src/core/pool-migration.d.ts
2216
+ /** The host login slot, shaped like the plugin's `client.auth`. */
2217
+ interface HostSlotAdapter {
2218
+ /** The shared auth.json path, independent of a plugin's config root. */
2219
+ path?: string;
2220
+ migrationDisabledReason?: () => string | undefined;
2221
+ get(input: {
2222
+ path: {
2223
+ id: string;
2224
+ };
2225
+ }): Promise<unknown>;
2226
+ set(input: {
2227
+ path: {
2228
+ id: string;
2229
+ };
2230
+ body: unknown;
2231
+ }): Promise<unknown>;
2232
+ all(): Promise<Record<string, unknown>>;
2233
+ }
2234
+ interface PoolMigrationLogger {
2235
+ info(message: string, data?: Record<string, unknown>): void;
2236
+ warn(message: string, data?: Record<string, unknown>): void;
2237
+ }
2238
+ /** Named points between this module's own writes; awaited, for crash tests. */
2239
+ type PoolMigrationStep = 'after-pool-key-write' | 'after-record-write' | 'after-row-write' | 'after-verify' | 'after-carry-over' | 'before-placeholder-write' | 'after-placeholder-write' | 'after-record-clear' | 'after-marker-write';
2240
+ /** Timing of the legacy file locks and of waits on them. */
2241
+ interface LegacyLockOptions {
2242
+ mainRefreshTtlMs: number;
2243
+ fallbackTtlMs: number;
2244
+ /** Lease of the `save` lock pair around this module's own config writes. */
2245
+ saveTtlMs: number;
2246
+ renew: boolean;
2247
+ renewIntervalMs?: number;
2248
+ /** How long to wait for a held legacy lock before giving up (real clock). */
2249
+ timeoutMs: number;
2250
+ retryMs: number;
2251
+ }
2252
+ interface PoolMigrationDeps {
2253
+ paths: AccountPaths;
2254
+ slot: HostSlotAdapter;
2255
+ now?: () => number;
2256
+ sleep?: (ms: number) => Promise<void>;
2257
+ /** Id for a new row whose login carries no usable wire identity. */
2258
+ newId?: () => string;
2259
+ log?: PoolMigrationLogger;
2260
+ legacyLocks?: Partial<LegacyLockOptions>;
2261
+ /** Bound and poll interval for waiting out an active legacy main lease. */
2262
+ leaseWait?: {
2263
+ timeoutMs: number;
2264
+ pollMs: number;
2265
+ };
2266
+ /** Pass-through options for the pool store this module opens. */
2267
+ store?: Partial<Pick<OpenPoolStoreOptions, 'lockOptions' | 'rowLockOptions' | 'providerLock' | 'storeLocks' | 'onStep' | 'onLockEvent'>>;
2268
+ onStep?: (step: PoolMigrationStep) => void | Promise<void>;
2269
+ /**
2270
+ * Whether the Claustrum vault serves this host's accounts. The built-in
2271
+ * adopter does not change course on it: a pool row for an account the
2272
+ * vault also holds is skipped by the account source (`pool-account-source.ts`),
2273
+ * which neither routes nor refreshes it locally, so adoption can safely
2274
+ * move a slot login into the pool and put the placeholder back. The
2275
+ * placeholder has to be back: OpenCode 1 installs the plugin's fetch only
2276
+ * when its `openai` slot holds an OAuth value.
2277
+ */
2278
+ vaultServes?: () => boolean;
2279
+ }
2280
+ type SlotNothingKind = 'api' | 'placeholder' | 'empty' | 'tombstone' | 'slot-absent' | 'declined';
2281
+ type PoolTransferOutcome = {
2282
+ status: 'slot-read-only';
2283
+ reason: string;
2284
+ } |
2285
+ /**
2286
+ * The adoption left the slot alone because the vault serves this host's
2287
+ * accounts. The built-in adopter (`adoptHostSlotLogin`) no longer returns
2288
+ * this; it can still come from a custom adopter passed to the background
2289
+ * runner (`adopt` in `pool-lifecycle.ts`).
2290
+ */
2291
+ {
2292
+ status: 'vault-owns-accounts';
2293
+ } |
2294
+ /**
2295
+ * An openai-auth process older than this one is running (see
2296
+ * `version-fence.ts`); nothing was written. The migration runs once they
2297
+ * are gone.
2298
+ */
2299
+ {
2300
+ status: 'deferred';
2301
+ reason: 'older-version-running';
2302
+ blockers: VersionFenceBlocker[];
2303
+ } |
2304
+ /** Migration already recorded as done; nothing was imported. */
2305
+ {
2306
+ status: 'already-migrated';
2307
+ } |
2308
+ /**
2309
+ * The slot holds the placeholder, but it was not this store that moved the
2310
+ * login out of the slot. The transfer record below is the pending-transfer
2311
+ * record in this store's config, written before a transfer touches a row.
2312
+ * - `placeholder-without-main`: another store sharing this login slot
2313
+ * moved the login, so the login is that store's. Either this store has
2314
+ * no `main` row and no transfer record, and nothing is written; or this
2315
+ * store's own transfer was under way and found the placeholder tagged
2316
+ * with another config root, and only the copy that transfer had put into
2317
+ * a row is removed (the other store holds the login now) and the record
2318
+ * cleared.
2319
+ * - `placeholder-origin-unknown`: this store has a transfer record, but
2320
+ * the placeholder is untagged (it has no `accountId` naming the config
2321
+ * root that wrote it; builds before this one wrote it that way). The
2322
+ * row copy may be this store's only copy of the credential, so it is not
2323
+ * deleted; another store may own the login, so the row is disabled
2324
+ * rather than routed or refreshed. The record is cleared so that a later
2325
+ * background run does not find it and disable the row again after
2326
+ * someone has re-enabled it.
2327
+ */
2328
+ {
2329
+ status: 'refused';
2330
+ reason: 'placeholder-without-main' | 'placeholder-origin-unknown';
2331
+ } |
2332
+ /** Adoption asked for before the migration ran. */
2333
+ {
2334
+ status: 'not-migrated';
2335
+ } | {
2336
+ status: 'nothing-to-import';
2337
+ slot: SlotNothingKind;
2338
+ } | {
2339
+ status: 'completed';
2340
+ rowId: string;
2341
+ operation: 'add' | 'rotate' | 'replace' | 'resumed';
2342
+ /**
2343
+ * `written`: the placeholder was written and read back.
2344
+ * `already-present`: a resumed run found the placeholder in place.
2345
+ * `slot-moved-on`: the slot changed to another value before the fence;
2346
+ * it is left for the next adoption. (A placeholder replaced between its
2347
+ * write and the readback ends the run as `retry`,
2348
+ * `placeholder-overwritten`, not here.)
2349
+ */
2350
+ placeholder: 'written' | 'already-present' | 'slot-moved-on';
2351
+ } |
2352
+ /**
2353
+ * An interrupted transfer's row holds neither its old credential nor the
2354
+ * slot's: someone rotated it after the interruption, so the slot copy may
2355
+ * be stale. The slot is left alone and this exact slot value is declined
2356
+ * for adoption; the user's next login resolves it.
2357
+ */
2358
+ {
2359
+ status: 'ambiguous';
2360
+ rowId: string;
2361
+ } | {
2362
+ status: 'retry';
2363
+ reason: 'host-slot-indeterminate' | 'legacy-refresh-in-progress' | 'lock-contention' | 'verify-failed' | 'torn-read' | 'slot-changed' |
2364
+ /**
2365
+ * Something replaced the placeholder between its write and the
2366
+ * readback. The record and the shield stay, since the slot may hold
2367
+ * the very token the row now holds; the next run reads the slot
2368
+ * again and finishes the transfer from what it finds.
2369
+ */
2370
+ 'placeholder-overwritten' | 'unsettled' |
2371
+ /**
2372
+ * An adoption found the vault's first roster read still unfinished
2373
+ * after its wait, so whether the vault serves this host was unknown;
2374
+ * nothing was adopted.
2375
+ */
2376
+ 'vault-roster-pending' | `store-${string}`;
2377
+ } | {
2378
+ status: 'error';
2379
+ reason: string;
2380
+ };
2381
+ /** What the migration needs beyond an adoption run. */
2382
+ interface PoolMigrationFenceDeps {
2383
+ /**
2384
+ * The version fence (`migrationFenceOpen` in `version-fence.ts`, bound to
2385
+ * this build's version). While it is shut the migration writes nothing.
2386
+ */
2387
+ fence: () => Promise<VersionFenceResult>;
2388
+ }
2389
+ /**
2390
+ * One-time move of the host-slot credential into the pool row `main`
2391
+ * (fallback rows are already pool rows: same ids, same files). It writes
2392
+ * nothing while an older openai-auth process runs (`deferred`). A re-run
2393
+ * after completion does nothing.
2394
+ */
2395
+ declare function migrateToPool(deps: PoolMigrationDeps & PoolMigrationFenceDeps): Promise<PoolTransferOutcome>;
2396
+ /**
2397
+ * After migration: a real login found in the host slot (someone ran
2398
+ * `/login openai` in OpenCode) moves into the pool, matched by wire identity,
2399
+ * and the placeholder goes back into the slot.
2400
+ */
2401
+ declare function adoptHostSlotLogin(deps: PoolMigrationDeps): Promise<PoolTransferOutcome>;
2402
+ //#endregion
2403
+ //#region src/core/pool-lifecycle.d.ts
2404
+ interface PoolLifecycleTimers {
2405
+ set(run: () => void, ms: number): unknown;
2406
+ clear(handle: unknown): void;
2407
+ }
2408
+ interface PoolLifecycleDeps {
2409
+ /** Read at every run, so it follows the configured store path. */
2410
+ paths: () => AccountPaths;
2411
+ slot: HostSlotAdapter;
2412
+ /** This build's version, for the version fence. */
2413
+ version: string;
2414
+ log?: PoolMigrationLogger;
2415
+ /** Defaults to `migrationFenceOpen` for `version`. */
2416
+ fence?: () => Promise<VersionFenceResult>;
2417
+ migrate?: typeof migrateToPool;
2418
+ adopt?: typeof adoptHostSlotLogin;
2419
+ timers?: PoolLifecycleTimers;
2420
+ random?: () => number;
2421
+ /** Passed through to every migration and adoption run (tests). */
2422
+ runDeps?: Partial<PoolMigrationDeps>;
2423
+ /**
2424
+ * True while no migration or adoption may run: the host is in vault mode,
2425
+ * which writes no local account file. Read before every run.
2426
+ */
2427
+ paused?: () => boolean | Promise<boolean>;
2428
+ }
2429
+ //#endregion
2430
+ export { BeginAccountLoginOptions as a, TokenResponse as c, parseJwtClaims as d, AccountPaths as f, OpenAiVaultOptions as i, beginAccountLogin as l, HostSlotAdapter as n, BeginAccountLoginResult as o, PoolStore as p, OpenAiVault as r, IdTokenClaims as s, PoolLifecycleDeps as t, extractAccountIdFromClaims as u };