agl 40.4.0 → 40.5.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 (149) hide show
  1. package/changelog.md +27 -0
  2. package/dist_serve/bundle.js +2228 -2177
  3. package/dist_serve/bundle.js.map +2 -2
  4. package/dist_ts/00_commitinfo_data.js +1 -1
  5. package/dist_ts/aglapi/aglapisurface.document.js +2 -2
  6. package/dist_ts/classes.accountsactions.d.ts +11 -1
  7. package/dist_ts/classes.accountsactions.js +59 -2
  8. package/dist_ts/classes.controller.js +5 -5
  9. package/dist_ts/classes.flexaccountaccess.js +3 -2
  10. package/dist_ts/classes.harnessreleases.d.ts +14 -4
  11. package/dist_ts/classes.harnessreleases.js +28 -4
  12. package/dist_ts/classes.inferencegateway.d.ts +28 -3
  13. package/dist_ts/classes.inferencegateway.js +177 -61
  14. package/dist_ts/classes.inferenceplacement.d.ts +5 -3
  15. package/dist_ts/classes.inferenceplacement.js +2 -2
  16. package/dist_ts/classes.inferencerouter.d.ts +349 -91
  17. package/dist_ts/classes.inferencerouter.js +804 -297
  18. package/dist_ts/classes.inferenceservice.d.ts +14 -2
  19. package/dist_ts/classes.inferenceservice.js +53 -14
  20. package/dist_ts/classes.inferencespend.d.ts +339 -0
  21. package/dist_ts/classes.inferencespend.js +815 -0
  22. package/dist_ts/classes.inferenceusagecache.d.ts +8 -0
  23. package/dist_ts/classes.inferenceusagecache.js +9 -5
  24. package/dist_ts/classes.inferenceusagetap.d.ts +50 -9
  25. package/dist_ts/classes.inferenceusagetap.js +185 -31
  26. package/dist_ts/classes.proxycontrol.d.ts +3 -2
  27. package/dist_ts/classes.proxycontrol.js +1 -2
  28. package/dist_ts/classes.proxydaemon.js +3 -2
  29. package/dist_ts/classes.proxystore.d.ts +6 -0
  30. package/dist_ts/classes.proxystore.js +11 -2
  31. package/dist_ts/fleet/classes.claudeworkers.d.ts +5 -4
  32. package/dist_ts/fleet/classes.claudeworkers.js +10 -9
  33. package/dist_ts/functions.claudecoderelease.d.ts +12 -6
  34. package/dist_ts/functions.claudecoderelease.js +13 -7
  35. package/dist_ts/functions.inferencecli.js +12 -8
  36. package/dist_ts/interfaces.auth.d.ts +1 -1
  37. package/dist_ts/interfaces.auth.js +3 -1
  38. package/dist_ts/plugins.d.ts +3 -1
  39. package/dist_ts/plugins.js +7 -2
  40. package/dist_ts_authswitch/authority-apikeys.d.ts +32 -0
  41. package/dist_ts_authswitch/authority-apikeys.js +65 -0
  42. package/dist_ts_authswitch/authority-contract.d.ts +142 -28
  43. package/dist_ts_authswitch/authority-contract.js +48 -1
  44. package/dist_ts_authswitch/authority-overview.js +8 -1
  45. package/dist_ts_authswitch/authority-placement.d.ts +7 -2
  46. package/dist_ts_authswitch/authority-placement.js +10 -3
  47. package/dist_ts_authswitch/authority-runtime-contract.d.ts +2 -2
  48. package/dist_ts_authswitch/authority-spend.d.ts +103 -0
  49. package/dist_ts_authswitch/authority-spend.js +110 -0
  50. package/dist_ts_authswitch/authority-subscription.d.ts +12 -1
  51. package/dist_ts_authswitch/authority-subscription.js +24 -1
  52. package/dist_ts_authswitch/authority-usagelimit.d.ts +7 -4
  53. package/dist_ts_authswitch/authority-usagelimit.js +89 -39
  54. package/dist_ts_authswitch/authority-usagewindows.d.ts +4 -1
  55. package/dist_ts_authswitch/authority-usagewindows.js +41 -16
  56. package/dist_ts_authswitch/classes.authoritybroker.d.ts +30 -19
  57. package/dist_ts_authswitch/classes.authoritybroker.js +152 -61
  58. package/dist_ts_authswitch/classes.authoritycli.d.ts +9 -4
  59. package/dist_ts_authswitch/classes.authoritycli.js +94 -29
  60. package/dist_ts_authswitch/classes.authorityclient.d.ts +24 -7
  61. package/dist_ts_authswitch/classes.authorityclient.js +31 -11
  62. package/dist_ts_authswitch/classes.authoritydaemon.js +39 -12
  63. package/dist_ts_authswitch/classes.authoritydatabase.d.ts +28 -5
  64. package/dist_ts_authswitch/classes.authoritydatabase.js +171 -9
  65. package/dist_ts_authswitch/classes.authorityimport.js +2 -2
  66. package/dist_ts_authswitch/classes.authoritymodels.d.ts +71 -3
  67. package/dist_ts_authswitch/classes.authoritymodels.js +249 -20
  68. package/dist_ts_authswitch/classes.authorityregistry.js +4 -2
  69. package/dist_ts_authswitch/classes.authorityusage.d.ts +69 -7
  70. package/dist_ts_authswitch/classes.authorityusage.js +118 -4
  71. package/dist_ts_authswitch/classes.claudenative.d.ts +16 -7
  72. package/dist_ts_authswitch/classes.claudenative.js +29 -16
  73. package/dist_ts_authswitch/classes.claudesignin.js +5 -2
  74. package/dist_ts_authswitch/testsupport.d.ts +24 -5
  75. package/dist_ts_authswitch/testsupport.js +56 -12
  76. package/dist_ts_authswitch/ts_migration/0011_account_api_key_fields.d.ts +12 -0
  77. package/dist_ts_authswitch/ts_migration/0011_account_api_key_fields.js +21 -0
  78. package/dist_ts_authswitch/ts_migration/index.js +3 -1
  79. package/dist_ts_interfaces/functions.authorityscope.d.ts +18 -7
  80. package/dist_ts_interfaces/functions.authorityscope.js +35 -8
  81. package/dist_ts_interfaces/interfaces.d.ts +1 -1
  82. package/dist_ts_interfaces/interfaces.js +1 -1
  83. package/dist_ts_interfaces/plugins.d.ts +2 -1
  84. package/dist_ts_interfaces/plugins.js +7 -4
  85. package/dist_ts_interfaces/requests.accounts.d.ts +56 -0
  86. package/dist_ts_interfaces/requests.accounts.js +11 -1
  87. package/dist_ts_interfaces/requests.d.ts +2 -2
  88. package/dist_ts_interfaces/requests.js +1 -1
  89. package/docs/authswitch.md +75 -12
  90. package/package.json +5 -5
  91. package/readme.md +198 -21
  92. package/ts/00_commitinfo_data.ts +1 -1
  93. package/ts/aglapi/aglapisurface.document.ts +2 -2
  94. package/ts/classes.accountsactions.ts +75 -1
  95. package/ts/classes.controller.ts +4 -4
  96. package/ts/classes.flexaccountaccess.ts +2 -1
  97. package/ts/classes.harnessreleases.ts +25 -4
  98. package/ts/classes.inferencegateway.ts +184 -64
  99. package/ts/classes.inferenceplacement.ts +6 -4
  100. package/ts/classes.inferencerouter.ts +1026 -314
  101. package/ts/classes.inferenceservice.ts +56 -13
  102. package/ts/classes.inferencespend.ts +870 -0
  103. package/ts/classes.inferenceusagecache.ts +16 -4
  104. package/ts/classes.inferenceusagetap.ts +159 -34
  105. package/ts/classes.proxycontrol.ts +3 -3
  106. package/ts/classes.proxydaemon.ts +2 -1
  107. package/ts/classes.proxystore.ts +11 -1
  108. package/ts/fleet/classes.claudeworkers.ts +9 -8
  109. package/ts/functions.claudecoderelease.ts +13 -6
  110. package/ts/functions.inferencecli.ts +11 -7
  111. package/ts/interfaces.auth.ts +2 -0
  112. package/ts/plugins.ts +7 -0
  113. package/ts_authswitch/authority-apikeys.ts +85 -0
  114. package/ts_authswitch/authority-contract.ts +167 -29
  115. package/ts_authswitch/authority-overview.ts +7 -0
  116. package/ts_authswitch/authority-placement.ts +12 -4
  117. package/ts_authswitch/authority-runtime-contract.ts +2 -2
  118. package/ts_authswitch/authority-spend.ts +168 -0
  119. package/ts_authswitch/authority-subscription.ts +28 -1
  120. package/ts_authswitch/authority-usagelimit.ts +95 -40
  121. package/ts_authswitch/authority-usagewindows.ts +42 -17
  122. package/ts_authswitch/classes.authoritybroker.ts +161 -68
  123. package/ts_authswitch/classes.authoritycli.ts +108 -32
  124. package/ts_authswitch/classes.authorityclient.ts +41 -10
  125. package/ts_authswitch/classes.authoritydaemon.ts +43 -13
  126. package/ts_authswitch/classes.authoritydatabase.ts +178 -8
  127. package/ts_authswitch/classes.authorityimport.ts +1 -1
  128. package/ts_authswitch/classes.authoritymodels.ts +165 -19
  129. package/ts_authswitch/classes.authorityregistry.ts +3 -0
  130. package/ts_authswitch/classes.authorityusage.ts +171 -10
  131. package/ts_authswitch/classes.claudenative.ts +28 -15
  132. package/ts_authswitch/classes.claudesignin.ts +4 -1
  133. package/ts_authswitch/native-contracts.md +81 -20
  134. package/ts_authswitch/readme.md +1 -1
  135. package/ts_authswitch/testsupport.ts +58 -11
  136. package/ts_authswitch/ts_migration/0011_account_api_key_fields.ts +20 -0
  137. package/ts_authswitch/ts_migration/index.ts +2 -0
  138. package/ts_interfaces/functions.authorityscope.ts +43 -8
  139. package/ts_interfaces/interfaces.ts +1 -1
  140. package/ts_interfaces/plugins.ts +6 -3
  141. package/ts_interfaces/requests.accounts.ts +48 -0
  142. package/ts_interfaces/requests.ts +4 -0
  143. package/ts_web/00_commitinfo_data.ts +1 -1
  144. package/ts_web/accounts.plugins.ts +3 -1
  145. package/ts_web/accounts.templates.ts +20 -11
  146. package/ts_web/classes.accountsreadmodel.ts +322 -70
  147. package/ts_web/elements.accounts.ts +219 -20
  148. package/ts_web/elements.codexconnections.ts +3 -1
  149. package/ts_web/plugins.ts +4 -2
@@ -89,6 +89,8 @@ export type TControllerAccountNativeAssignment = plugins.authswitchAuthority.IAu
89
89
  export type TControllerAccountOperation = plugins.authswitchAuthority.IAuthSwitchOperation;
90
90
  export type TControllerAccountPreuse = plugins.authswitchAuthority.IAuthSwitchPreuseOperation;
91
91
  export type TControllerAccountUsage = plugins.authswitchAuthority.IAuthSwitchUsageSnapshot;
92
+ /** An API key's month, the reading of an API key account's usage (`kind: 'spend'`). */
93
+ export type TControllerAccountSpendReading = plugins.authswitchAuthority.IAuthSwitchSpendReading;
92
94
  /** A re-check of a Claude login: the usage held once its read finished, and how that read went. */
93
95
  export type TControllerAccountUsageRecheck = plugins.authswitchAuthority.IAuthSwitchUsageRecheck;
94
96
  export type TControllerAccountsDoctorPage = plugins.authswitchAuthority.IAuthSwitchDoctorPage;
@@ -185,6 +187,60 @@ export interface IReq_ControllerAccountsMaxUsage extends plugins.typedrequestInt
185
187
  answer: TControllerAccountsAnswer<TControllerAccount>;
186
188
  };
187
189
  }
190
+ /** The providers whose API keys the Accounts screen adds as accounts. */
191
+ export type TControllerApiKeyProvider = plugins.authswitchAuthority.TAuthSwitchApiKeyProvider;
192
+ /**
193
+ * The spend limit rule, as the accounts service publishes and applies it: a whole number of cents from
194
+ * `controllerSpendLimitRange.min` to `.max`, in micro-dollars. A view checks a value with it before it offers the
195
+ * change, and the service refuses any other value with `invalid_input`.
196
+ */
197
+ export declare const isControllerSpendLimitMicroUsd: typeof plugins.authswitchSpend.isAuthSwitchSpendLimitMicroUsd;
198
+ /** The range of a spend limit, in micro-dollars. */
199
+ export declare const controllerSpendLimitRange: Readonly<{
200
+ min: number;
201
+ max: number;
202
+ }>;
203
+ /** The longest API key the accounts service holds, in characters; a longer value is refused before it is sent. */
204
+ export declare const controllerApiKeyMaxLength = 512;
205
+ /**
206
+ * Adds an Anthropic or OpenAI API key as an account, with an optional label and monthly spend limit
207
+ * (`isControllerSpendLimitMicroUsd`). The accounts service asks the provider whether it accepts the key before it holds
208
+ * it, and answers why when it does not (`api_key_unverified`, `invalid_input`). The key is never answered, logged or
209
+ * audited; the account names it only by how it ends (`keyHint`). The answer arrives only once the controller's own
210
+ * projection shows the account; it can take up to 35 seconds, the provider's answer included.
211
+ */
212
+ export interface IReq_ControllerAccountsApiKeyAdd extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_ControllerAccountsApiKeyAdd> {
213
+ method: 'controller.accounts.apikey.add';
214
+ request: {
215
+ providerId: TControllerApiKeyProvider;
216
+ apiKey: string;
217
+ label?: string;
218
+ spendLimitMicroUsd?: number;
219
+ };
220
+ response: {
221
+ answer: TControllerAccountsAnswer<{
222
+ account: TControllerAccount;
223
+ loginId: string;
224
+ }>;
225
+ };
226
+ }
227
+ /**
228
+ * Sets an API key account's monthly spend limit, or clears it with `null`: at the limit AGL's inference proxy places
229
+ * nothing more on the key until the month ends (UTC). `expectedRevision` is the revision the view showed, so a change of
230
+ * an account that changed meanwhile is refused as `account_changed`, and a value that breaks the rule, or an account on
231
+ * a sign-in, as `invalid_input`, both by the service. The answer arrives only once the projection shows the result.
232
+ */
233
+ export interface IReq_ControllerAccountsSpendLimit extends plugins.typedrequestInterfaces.implementsTR<plugins.typedrequestInterfaces.ITypedRequest, IReq_ControllerAccountsSpendLimit> {
234
+ method: 'controller.accounts.spendlimit';
235
+ request: {
236
+ accountId: string;
237
+ expectedRevision: number;
238
+ spendLimitMicroUsd: number | null;
239
+ };
240
+ response: {
241
+ answer: TControllerAccountsAnswer<TControllerAccount>;
242
+ };
243
+ }
188
244
  /** Duration validation shared with the authority; no implicit duration is supplied. */
189
245
  export declare const isControllerReserveLiftHours: typeof plugins.authswitchAuthority.isAuthSwitchReserveLiftHours;
190
246
  /** Lift only the saved reserve. The authority sets the expiry; the projection must show the change before answering. */
@@ -16,6 +16,16 @@ export const controllerAccountLabelMaxLength = plugins.authswitchAuthority.authS
16
16
  export const isControllerAccountMaxUsagePercent = plugins.authswitchAuthority.isAuthSwitchMaxUsagePercent;
17
17
  /** The range of an account's usage threshold, in whole percent. */
18
18
  export const controllerAccountMaxUsageRange = plugins.authswitchAuthority.authSwitchMaxUsageRange;
19
+ /**
20
+ * The spend limit rule, as the accounts service publishes and applies it: a whole number of cents from
21
+ * `controllerSpendLimitRange.min` to `.max`, in micro-dollars. A view checks a value with it before it offers the
22
+ * change, and the service refuses any other value with `invalid_input`.
23
+ */
24
+ export const isControllerSpendLimitMicroUsd = plugins.authswitchSpend.isAuthSwitchSpendLimitMicroUsd;
25
+ /** The range of a spend limit, in micro-dollars. */
26
+ export const controllerSpendLimitRange = plugins.authswitchSpend.authSwitchSpendLimitRange;
27
+ /** The longest API key the accounts service holds, in characters; a longer value is refused before it is sent. */
28
+ export const controllerApiKeyMaxLength = 512;
19
29
  /** Duration validation shared with the authority; no implicit duration is supplied. */
20
30
  export const isControllerReserveLiftHours = plugins.authswitchAuthority.isAuthSwitchReserveLiftHours;
21
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWVzdHMuYWNjb3VudHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90c19pbnRlcmZhY2VzL3JlcXVlc3RzLmFjY291bnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBNEd4QyxvR0FBb0c7QUFDcEcsTUFBTSxDQUFDLE1BQU0sZ0NBQWdDLEdBQUcsQ0FBQyxTQUFrQyxFQUFXLEVBQUUsQ0FBQyxDQUMvRixTQUFTLENBQUMsS0FBSyxLQUFLLFNBQVMsSUFBSSxTQUFTLENBQUMsS0FBSyxLQUFLLFlBQVksQ0FDbEUsQ0FBQztBQThCRjs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSx3QkFBd0IsR0FBRyxPQUFPLENBQUMsbUJBQW1CLENBQUMsd0JBQXdCLENBQUM7QUFDN0YsdUVBQXVFO0FBQ3ZFLE1BQU0sQ0FBQyxNQUFNLCtCQUErQixHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQywrQkFBK0IsQ0FBQztBQWlCM0c7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLGtDQUFrQyxHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQywyQkFBMkIsQ0FBQztBQUMxRyxtRUFBbUU7QUFDbkUsTUFBTSxDQUFDLE1BQU0sOEJBQThCLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixDQUFDLHVCQUF1QixDQUFDO0FBa0JsRyx1RkFBdUY7QUFDdkYsTUFBTSxDQUFDLE1BQU0sNEJBQTRCLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixDQUFDLDRCQUE0QixDQUFDIn0=
31
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWVzdHMuYWNjb3VudHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90c19pbnRlcmZhY2VzL3JlcXVlc3RzLmFjY291bnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBOEd4QyxvR0FBb0c7QUFDcEcsTUFBTSxDQUFDLE1BQU0sZ0NBQWdDLEdBQUcsQ0FBQyxTQUFrQyxFQUFXLEVBQUUsQ0FBQyxDQUMvRixTQUFTLENBQUMsS0FBSyxLQUFLLFNBQVMsSUFBSSxTQUFTLENBQUMsS0FBSyxLQUFLLFlBQVksQ0FDbEUsQ0FBQztBQThCRjs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSx3QkFBd0IsR0FBRyxPQUFPLENBQUMsbUJBQW1CLENBQUMsd0JBQXdCLENBQUM7QUFDN0YsdUVBQXVFO0FBQ3ZFLE1BQU0sQ0FBQyxNQUFNLCtCQUErQixHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQywrQkFBK0IsQ0FBQztBQWlCM0c7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLGtDQUFrQyxHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQywyQkFBMkIsQ0FBQztBQUMxRyxtRUFBbUU7QUFDbkUsTUFBTSxDQUFDLE1BQU0sOEJBQThCLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixDQUFDLHVCQUF1QixDQUFDO0FBcUJsRzs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sOEJBQThCLEdBQUcsT0FBTyxDQUFDLGVBQWUsQ0FBQyw4QkFBOEIsQ0FBQztBQUNyRyxvREFBb0Q7QUFDcEQsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQUcsT0FBTyxDQUFDLGVBQWUsQ0FBQyx5QkFBeUIsQ0FBQztBQUUzRixrSEFBa0g7QUFDbEgsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQUcsR0FBRyxDQUFDO0FBaUM3Qyx1RkFBdUY7QUFDdkYsTUFBTSxDQUFDLE1BQU0sNEJBQTRCLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixDQUFDLDRCQUE0QixDQUFDIn0=
@@ -1,5 +1,5 @@
1
1
  import type { IReq_ControllerConfigurationResourceGet, IReq_ControllerConfigurationStateGet, IReq_ControllerConfigurationSummaryGet, IReq_ControllerConfigurationMasterGet, IReq_ControllerConfigurationMasterSave, IReq_ControllerConfigurationProject, IReq_ControllerConfigurationReview, IReq_ControllerConfigurationApply, IReq_ControllerConfigurationRestoreReview, IReq_ControllerConfigurationRestore, IReq_ControllerConfigurationTargetBind, IReq_ControllerConfigurationOperationRetry, IReq_ControllerConfigurationOperationRecover, IReq_ControllerConfigurationOperationAbandon, IReq_ControllerConfigurationOwnerIssue, IReq_ControllerConfigurationOwnerRevoke } from './requests.configuration.js';
2
- import type { IReq_ControllerAccountsAdd, IReq_ControllerAccountsDoctorGet, IReq_ControllerAccountsOperationCancel, IReq_ControllerAccountsOperationGet, IReq_ControllerAccountsPreuseCancel, IReq_ControllerAccountsPreuseGet, IReq_ControllerAccountsPreuseStart, IReq_ControllerAccountsReauth, IReq_ControllerAccountsRemove, IReq_ControllerAccountsRename, IReq_ControllerAccountsMaxUsage, IReq_ControllerAccountsReserveLift, IReq_ControllerAccountsSnapshot, IReq_ControllerAccountsUsageGet, IReq_ControllerAccountsUsageRecheck, IReq_ControllerAccountsClaudeHostGet, IReq_ControllerAccountsClaudeRelease, IReq_ControllerAccountsClaudeReleaseGet, IReq_ControllerAccountsClaudeRepair, IReq_ControllerAccountsClaudeSignInCancel, IReq_ControllerAccountsClaudeSignInGet, IReq_ControllerAccountsClaudeSignInStart, IReq_ControllerAccountsCodexAdopt, IReq_ControllerCodexAccountUse, IReq_ControllerAccountsCodexRelease } from './requests.accounts.js';
2
+ import type { IReq_ControllerAccountsAdd, IReq_ControllerAccountsDoctorGet, IReq_ControllerAccountsOperationCancel, IReq_ControllerAccountsOperationGet, IReq_ControllerAccountsPreuseCancel, IReq_ControllerAccountsPreuseGet, IReq_ControllerAccountsPreuseStart, IReq_ControllerAccountsReauth, IReq_ControllerAccountsRemove, IReq_ControllerAccountsRename, IReq_ControllerAccountsMaxUsage, IReq_ControllerAccountsReserveLift, IReq_ControllerAccountsApiKeyAdd, IReq_ControllerAccountsSpendLimit, IReq_ControllerAccountsSnapshot, IReq_ControllerAccountsUsageGet, IReq_ControllerAccountsUsageRecheck, IReq_ControllerAccountsClaudeHostGet, IReq_ControllerAccountsClaudeRelease, IReq_ControllerAccountsClaudeReleaseGet, IReq_ControllerAccountsClaudeRepair, IReq_ControllerAccountsClaudeSignInCancel, IReq_ControllerAccountsClaudeSignInGet, IReq_ControllerAccountsClaudeSignInStart, IReq_ControllerAccountsCodexAdopt, IReq_ControllerCodexAccountUse, IReq_ControllerAccountsCodexRelease } from './requests.accounts.js';
3
3
  import type { IReq_ControllerOpenCodeRestart, IReq_ControllerProxyStatusGet, IReq_ControllerRestart, IReq_ControllerStatus } from './requests.status.js';
4
4
  import type { IReq_ControllerUpgradeLaunch, IReq_ControllerUpgradePrepare, IReq_ControllerUpgradePrepareBegin, IReq_ControllerUpgradeFinalize } from './requests.upgrade.js';
5
5
  import type { IReq_ControllerDriverGet, IReq_ControllerDriverEnsure, IReq_ControllerDriverSeen } from './requests.driver.js';
@@ -41,4 +41,4 @@ export * from './requests.browser.js';
41
41
  export * from './requests.terminal.js';
42
42
  export * from './requests.workspace.js';
43
43
  export * from './requests.events.js';
44
- export type TControllerRequest = IReq_ControllerConfigurationResourceGet | IReq_ControllerConfigurationStateGet | IReq_ControllerConfigurationSummaryGet | IReq_ControllerConfigurationMasterGet | IReq_ControllerConfigurationMasterSave | IReq_ControllerConfigurationProject | IReq_ControllerConfigurationReview | IReq_ControllerConfigurationApply | IReq_ControllerConfigurationRestoreReview | IReq_ControllerConfigurationRestore | IReq_ControllerConfigurationTargetBind | IReq_ControllerConfigurationOperationRetry | IReq_ControllerConfigurationOperationRecover | IReq_ControllerConfigurationOperationAbandon | IReq_ControllerConfigurationOwnerIssue | IReq_ControllerConfigurationOwnerRevoke | IReq_ControllerStatus | IReq_ControllerProxyStatusGet | IReq_ControllerOpenCodeRestart | IReq_ControllerRestart | IReq_ControllerUpgradeLaunch | IReq_ControllerUpgradePrepare | IReq_ControllerUpgradePrepareBegin | IReq_ControllerUpgradeFinalize | IReq_ControllerDriverGet | IReq_ControllerDriverEnsure | IReq_ControllerDriverSeen | IReq_ControllerFleetWorkerList | IReq_ControllerFleetWorkerRead | IReq_ControllerFleetWorkerSteer | IReq_ControllerDirectReportList | IReq_ControllerDirectReportMessage | IReq_ControllerDirectReportRead | IReq_ControllerSessionFeedList | IReq_ControllerSessionFeedAcknowledge | IReq_ControllerNativeSessionRead | IReq_ControllerNativeSessionAuxiliaryGet | IReq_ControllerNativeSessionSend | IReq_ControllerNativeSessionScratchpadSave | IReq_ControllerNativeSessionIntelligenceAsk | IReq_ControllerNativeSessionPermissionReply | IReq_ControllerNativeSessionQuestionReply | IReq_ControllerUsageWatch | IReq_ControllerUsageUnwatch | IReq_ControllerSystemMetrics | IReq_ControllerSystemMetricsHistory | IReq_ControllerFailureDetailGet | IReq_ControllerAuthState | IReq_ControllerSetupBegin | IReq_ControllerSetupFinish | IReq_ControllerAuthenticationBegin | IReq_ControllerAuthenticationFinish | IReq_ControllerTempPasswordLogin | IReq_ControllerAuthResume | IReq_ControllerAuthHandoff | IReq_ControllerAuthSignout | IReq_ControllerProjectList | IReq_ControllerProjectCreate | IReq_ControllerProjectRemove | IReq_ControllerProjectRemovalRetry | IReq_ControllerProjectAgentMessagesUpdate | IReq_ControllerProjectSuggest | IReq_ControllerProviderConnectionList | IReq_ControllerProviderModelRefreshBegin | IReq_ControllerProviderModelRefreshGet | IReq_ControllerSlashList | IReq_ControllerSlashExecute | IReq_ControllerModelList | IReq_ControllerSettingsGet | IReq_ControllerSettingsUpdate | IReq_ControllerConversationList | IReq_ControllerConversationSearch | IReq_ControllerConversationOpen | IReq_ControllerConversationArchive | IReq_ControllerConversationReopen | IReq_ControllerSessionGet | IReq_ControllerSessionChildGet | IReq_ControllerSessionChildStatusGet | IReq_ControllerFlexChildGet | IReq_ControllerCodexChildGet | IReq_ControllerSessionChildMessagesPage | IReq_ControllerSessionChildMessageGet | IReq_ControllerSessionChildPermissionReply | IReq_ControllerSessionChildQuestionReply | IReq_ControllerSessionAuxiliaryGet | IReq_ControllerSessionModelUpdate | IReq_ControllerSessionScratchpadSave | IReq_ControllerSessionIntelligenceAsk | IReq_ControllerSessionMessagesPage | IReq_ControllerSessionMessageGet | IReq_ControllerSessionCreate | IReq_ControllerSessionDelete | IReq_ControllerSessionDiscardEmpty | IReq_ControllerSessionDraftGet | IReq_ControllerSessionDraftUpdate | IReq_ControllerSessionSend | import('./codex.js').IReq_ControllerCodexRestart | import('./codex.js').IReq_ControllerCodexWriterUpdate | import('./codex.js').IReq_ControllerCodexModeUpdate | import('./codex.js').IReq_ControllerCodexProfilesList | import('./codex.js').IReq_ControllerCodexAccountProfile | import('./codex.js').IReq_ControllerCodexProfileCreate | import('./codex.js').IReq_ControllerCodexProfileUpdate | import('./codex.js').IReq_ControllerCodexProfileTest | import('./codex.js').IReq_ControllerCodexMappingUpdate | import('./codex.js').IReq_ControllerCodexThreadsList | import('./codex.js').IReq_ControllerCodexThreadEnroll | IReq_ControllerSessionAbort | IReq_ControllerSessionHarnessRestart | IReq_ControllerSessionCompactionUpdate | IReq_ControllerSessionLimitResumeUpdate | IReq_ControllerSessionPromptQueueRelease | IReq_ControllerSessionHeldPromptRelease | IReq_ControllerSessionPendingPromptAction | IReq_ControllerPermissionReply | IReq_ControllerQuestionReply | IReq_ControllerSessionRename | IReq_ControllerSessionArchive | IReq_ControllerSessionGroupsGet | IReq_ControllerSessionGroupsUpdate | IReq_ControllerSessionYolo | IReq_ControllerResourceList | IReq_ControllerResourceCreate | IReq_ControllerResourceRename | IReq_ControllerResourceAttach | IReq_ControllerResourceDetach | IReq_ControllerResourceRetire | IReq_ControllerResourceStart | IReq_ControllerResourceStop | IReq_ControllerBrowserViewOpen | IReq_ControllerBrowserViewActivate | IReq_ControllerBrowserViewRecover | IReq_ControllerBrowserViewClose | IReq_ControllerBrowserDevToolsOpen | IReq_ControllerBrowserDevToolsClose | IReq_ControllerBrowserPaintOpen | IReq_ControllerBrowserPaintClose | IReq_ControllerBrowserAudioOpen | IReq_ControllerBrowserAudioClose | IReq_ControllerBrowserPaintRearm | IReq_ControllerBrowserAssetsGet | IReq_ControllerBrowserPaintVideoRouteOpen | IReq_ControllerTerminalList | IReq_ControllerTerminalCreate | IReq_ControllerTerminalRename | IReq_ControllerTerminalRemove | IReq_ControllerTerminalAttach | IReq_ControllerTerminalDetach | IReq_ControllerTerminalInput | IReq_ControllerTerminalResize | IReq_ControllerWorkspaceList | IReq_ControllerWorkspaceStat | IReq_ControllerWorkspaceRead | IReq_ControllerWorkspaceWrite | IReq_ControllerWorkspaceMkdir | IReq_ControllerWorkspaceRemove | IReq_ControllerWorkspaceRename | IReq_ControllerWorkspaceCopy | IReq_ControllerWorkspaceWatch | IReq_ControllerWorkspaceUnwatch | IReq_ControllerWorkspaceBaseSet | IReq_ControllerTerminalOutput | IReq_ControllerTerminalDetached | IReq_ControllerWorkspaceChanged | IReq_ControllerAccountsSnapshot | IReq_ControllerAccountsRename | IReq_ControllerAccountsMaxUsage | IReq_ControllerAccountsReserveLift | IReq_ControllerAccountsRemove | IReq_ControllerAccountsAdd | IReq_ControllerAccountsReauth | IReq_ControllerAccountsOperationGet | IReq_ControllerAccountsOperationCancel | IReq_ControllerAccountsUsageGet | IReq_ControllerAccountsUsageRecheck | IReq_ControllerAccountsPreuseStart | IReq_ControllerAccountsPreuseGet | IReq_ControllerAccountsPreuseCancel | IReq_ControllerAccountsDoctorGet | IReq_ControllerAccountsClaudeSignInStart | IReq_ControllerAccountsClaudeSignInGet | IReq_ControllerAccountsClaudeSignInCancel | IReq_ControllerAccountsClaudeHostGet | IReq_ControllerAccountsClaudeRelease | IReq_ControllerAccountsClaudeReleaseGet | IReq_ControllerAccountsClaudeRepair | IReq_ControllerCodexAccountUse | IReq_ControllerAccountsCodexRelease | IReq_ControllerAccountsCodexAdopt | import('./requests.tickets.js').TControllerTicketTypedRequest | IReq_ControllerEvent | IReq_ControllerSessionChildEvent;
44
+ export type TControllerRequest = IReq_ControllerConfigurationResourceGet | IReq_ControllerConfigurationStateGet | IReq_ControllerConfigurationSummaryGet | IReq_ControllerConfigurationMasterGet | IReq_ControllerConfigurationMasterSave | IReq_ControllerConfigurationProject | IReq_ControllerConfigurationReview | IReq_ControllerConfigurationApply | IReq_ControllerConfigurationRestoreReview | IReq_ControllerConfigurationRestore | IReq_ControllerConfigurationTargetBind | IReq_ControllerConfigurationOperationRetry | IReq_ControllerConfigurationOperationRecover | IReq_ControllerConfigurationOperationAbandon | IReq_ControllerConfigurationOwnerIssue | IReq_ControllerConfigurationOwnerRevoke | IReq_ControllerStatus | IReq_ControllerProxyStatusGet | IReq_ControllerOpenCodeRestart | IReq_ControllerRestart | IReq_ControllerUpgradeLaunch | IReq_ControllerUpgradePrepare | IReq_ControllerUpgradePrepareBegin | IReq_ControllerUpgradeFinalize | IReq_ControllerDriverGet | IReq_ControllerDriverEnsure | IReq_ControllerDriverSeen | IReq_ControllerFleetWorkerList | IReq_ControllerFleetWorkerRead | IReq_ControllerFleetWorkerSteer | IReq_ControllerDirectReportList | IReq_ControllerDirectReportMessage | IReq_ControllerDirectReportRead | IReq_ControllerSessionFeedList | IReq_ControllerSessionFeedAcknowledge | IReq_ControllerNativeSessionRead | IReq_ControllerNativeSessionAuxiliaryGet | IReq_ControllerNativeSessionSend | IReq_ControllerNativeSessionScratchpadSave | IReq_ControllerNativeSessionIntelligenceAsk | IReq_ControllerNativeSessionPermissionReply | IReq_ControllerNativeSessionQuestionReply | IReq_ControllerUsageWatch | IReq_ControllerUsageUnwatch | IReq_ControllerSystemMetrics | IReq_ControllerSystemMetricsHistory | IReq_ControllerFailureDetailGet | IReq_ControllerAuthState | IReq_ControllerSetupBegin | IReq_ControllerSetupFinish | IReq_ControllerAuthenticationBegin | IReq_ControllerAuthenticationFinish | IReq_ControllerTempPasswordLogin | IReq_ControllerAuthResume | IReq_ControllerAuthHandoff | IReq_ControllerAuthSignout | IReq_ControllerProjectList | IReq_ControllerProjectCreate | IReq_ControllerProjectRemove | IReq_ControllerProjectRemovalRetry | IReq_ControllerProjectAgentMessagesUpdate | IReq_ControllerProjectSuggest | IReq_ControllerProviderConnectionList | IReq_ControllerProviderModelRefreshBegin | IReq_ControllerProviderModelRefreshGet | IReq_ControllerSlashList | IReq_ControllerSlashExecute | IReq_ControllerModelList | IReq_ControllerSettingsGet | IReq_ControllerSettingsUpdate | IReq_ControllerConversationList | IReq_ControllerConversationSearch | IReq_ControllerConversationOpen | IReq_ControllerConversationArchive | IReq_ControllerConversationReopen | IReq_ControllerSessionGet | IReq_ControllerSessionChildGet | IReq_ControllerSessionChildStatusGet | IReq_ControllerFlexChildGet | IReq_ControllerCodexChildGet | IReq_ControllerSessionChildMessagesPage | IReq_ControllerSessionChildMessageGet | IReq_ControllerSessionChildPermissionReply | IReq_ControllerSessionChildQuestionReply | IReq_ControllerSessionAuxiliaryGet | IReq_ControllerSessionModelUpdate | IReq_ControllerSessionScratchpadSave | IReq_ControllerSessionIntelligenceAsk | IReq_ControllerSessionMessagesPage | IReq_ControllerSessionMessageGet | IReq_ControllerSessionCreate | IReq_ControllerSessionDelete | IReq_ControllerSessionDiscardEmpty | IReq_ControllerSessionDraftGet | IReq_ControllerSessionDraftUpdate | IReq_ControllerSessionSend | import('./codex.js').IReq_ControllerCodexRestart | import('./codex.js').IReq_ControllerCodexWriterUpdate | import('./codex.js').IReq_ControllerCodexModeUpdate | import('./codex.js').IReq_ControllerCodexProfilesList | import('./codex.js').IReq_ControllerCodexAccountProfile | import('./codex.js').IReq_ControllerCodexProfileCreate | import('./codex.js').IReq_ControllerCodexProfileUpdate | import('./codex.js').IReq_ControllerCodexProfileTest | import('./codex.js').IReq_ControllerCodexMappingUpdate | import('./codex.js').IReq_ControllerCodexThreadsList | import('./codex.js').IReq_ControllerCodexThreadEnroll | IReq_ControllerSessionAbort | IReq_ControllerSessionHarnessRestart | IReq_ControllerSessionCompactionUpdate | IReq_ControllerSessionLimitResumeUpdate | IReq_ControllerSessionPromptQueueRelease | IReq_ControllerSessionHeldPromptRelease | IReq_ControllerSessionPendingPromptAction | IReq_ControllerPermissionReply | IReq_ControllerQuestionReply | IReq_ControllerSessionRename | IReq_ControllerSessionArchive | IReq_ControllerSessionGroupsGet | IReq_ControllerSessionGroupsUpdate | IReq_ControllerSessionYolo | IReq_ControllerResourceList | IReq_ControllerResourceCreate | IReq_ControllerResourceRename | IReq_ControllerResourceAttach | IReq_ControllerResourceDetach | IReq_ControllerResourceRetire | IReq_ControllerResourceStart | IReq_ControllerResourceStop | IReq_ControllerBrowserViewOpen | IReq_ControllerBrowserViewActivate | IReq_ControllerBrowserViewRecover | IReq_ControllerBrowserViewClose | IReq_ControllerBrowserDevToolsOpen | IReq_ControllerBrowserDevToolsClose | IReq_ControllerBrowserPaintOpen | IReq_ControllerBrowserPaintClose | IReq_ControllerBrowserAudioOpen | IReq_ControllerBrowserAudioClose | IReq_ControllerBrowserPaintRearm | IReq_ControllerBrowserAssetsGet | IReq_ControllerBrowserPaintVideoRouteOpen | IReq_ControllerTerminalList | IReq_ControllerTerminalCreate | IReq_ControllerTerminalRename | IReq_ControllerTerminalRemove | IReq_ControllerTerminalAttach | IReq_ControllerTerminalDetach | IReq_ControllerTerminalInput | IReq_ControllerTerminalResize | IReq_ControllerWorkspaceList | IReq_ControllerWorkspaceStat | IReq_ControllerWorkspaceRead | IReq_ControllerWorkspaceWrite | IReq_ControllerWorkspaceMkdir | IReq_ControllerWorkspaceRemove | IReq_ControllerWorkspaceRename | IReq_ControllerWorkspaceCopy | IReq_ControllerWorkspaceWatch | IReq_ControllerWorkspaceUnwatch | IReq_ControllerWorkspaceBaseSet | IReq_ControllerTerminalOutput | IReq_ControllerTerminalDetached | IReq_ControllerWorkspaceChanged | IReq_ControllerAccountsSnapshot | IReq_ControllerAccountsRename | IReq_ControllerAccountsMaxUsage | IReq_ControllerAccountsReserveLift | IReq_ControllerAccountsApiKeyAdd | IReq_ControllerAccountsSpendLimit | IReq_ControllerAccountsRemove | IReq_ControllerAccountsAdd | IReq_ControllerAccountsReauth | IReq_ControllerAccountsOperationGet | IReq_ControllerAccountsOperationCancel | IReq_ControllerAccountsUsageGet | IReq_ControllerAccountsUsageRecheck | IReq_ControllerAccountsPreuseStart | IReq_ControllerAccountsPreuseGet | IReq_ControllerAccountsPreuseCancel | IReq_ControllerAccountsDoctorGet | IReq_ControllerAccountsClaudeSignInStart | IReq_ControllerAccountsClaudeSignInGet | IReq_ControllerAccountsClaudeSignInCancel | IReq_ControllerAccountsClaudeHostGet | IReq_ControllerAccountsClaudeRelease | IReq_ControllerAccountsClaudeReleaseGet | IReq_ControllerAccountsClaudeRepair | IReq_ControllerCodexAccountUse | IReq_ControllerAccountsCodexRelease | IReq_ControllerAccountsCodexAdopt | import('./requests.tickets.js').TControllerTicketTypedRequest | IReq_ControllerEvent | IReq_ControllerSessionChildEvent;
@@ -18,4 +18,4 @@ export * from './requests.browser.js';
18
18
  export * from './requests.terminal.js';
19
19
  export * from './requests.workspace.js';
20
20
  export * from './requests.events.js';
21
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWVzdHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90c19pbnRlcmZhY2VzL3JlcXVlc3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQW1OQSxvRkFBb0Y7QUFDcEYsbUVBQW1FO0FBQ25FLGNBQWMsc0JBQXNCLENBQUM7QUFDckMsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsMkJBQTJCLENBQUM7QUFDMUMsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLHdCQUF3QixDQUFDO0FBQ3ZDLGNBQWMsNkJBQTZCLENBQUM7QUFDNUMsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsMkJBQTJCLENBQUM7QUFDMUMsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLHNCQUFzQixDQUFDIn0=
21
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWVzdHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90c19pbnRlcmZhY2VzL3JlcXVlc3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQXFOQSxvRkFBb0Y7QUFDcEYsbUVBQW1FO0FBQ25FLGNBQWMsc0JBQXNCLENBQUM7QUFDckMsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMsMkJBQTJCLENBQUM7QUFDMUMsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLHdCQUF3QixDQUFDO0FBQ3ZDLGNBQWMsNkJBQTZCLENBQUM7QUFDNUMsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsMkJBQTJCLENBQUM7QUFDMUMsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsd0JBQXdCLENBQUM7QUFDdkMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLHNCQUFzQixDQUFDIn0=
@@ -314,6 +314,8 @@ authswitch limits [--json]
314
314
  authswitch account list [--json]
315
315
  authswitch account add openai [--json]
316
316
  authswitch account add claude [--json]
317
+ authswitch account add anthropic-api-key [--label <label>] [--spend-limit <dollars>] [--json]
318
+ authswitch account add openai-api-key [--label <label>] [--spend-limit <dollars>] [--json]
317
319
  authswitch account use codex <account-id> [--json]
318
320
  authswitch account release claude <account-id> [--end-native-sessions] [--json]
319
321
  authswitch account repair claude [--json]
@@ -324,6 +326,8 @@ authswitch account set <account-id> --max-usage <percent> [--json]
324
326
  authswitch account set <account-id> --clear [--json]
325
327
  authswitch account set <account-id> --lapses-at <date-time> [--json]
326
328
  authswitch account set <account-id> --clear-lapse [--json]
329
+ authswitch account set <account-id> --spend-limit <dollars> [--json]
330
+ authswitch account set <account-id> --clear-spend-limit [--json]
327
331
  authswitch account operation get <operation-id> [--json]
328
332
  authswitch account operation cancel <operation-id> [--json]
329
333
  authswitch account operation resume <operation-id> [--json]
@@ -388,8 +392,8 @@ response is lost, the fixed diagnostic reports the caller-generated operation ID
388
392
  command; the CLI does not replay the start request.
389
393
 
390
394
  `account add claude` signs a Claude account in (see "Adding a Claude account" below): it starts a Claude sign-in,
391
- runs `claude auth login` on this terminal with `CLAUDE_CONFIG_DIR` set to the home the authority made for it, and
392
- follows the sign-in until the authority has imported the login. With `--json` it writes each changed sign-in as one
395
+ runs `claude auth login` on this terminal with `CLAUDE_CONFIG_DIR` and `CLAUDE_SECURESTORAGE_CONFIG_DIR` set to the
396
+ home the authority made for it, and follows the sign-in until the authority has imported the login. With `--json` it writes each changed sign-in as one
393
397
  JSON Line and sends Claude Code's own output to stderr. A Claude Code that cannot be started, or that exits without
394
398
  signing in, ends the sign-in, and the command exits nonzero. Claude Code on this host is not switched between
395
399
  accounts: once it runs through AGL's inference proxy, its own login is handed to the service with `account release
@@ -450,14 +454,67 @@ carries them per account as `subscription [{ label, value }]`. The daemon logs e
450
454
  reads it after its start, up to 32, then one line that says further values are not logged, so the map can be filled
451
455
  from what was seen; it keeps no record of them.
452
456
 
457
+ `account add anthropic-api-key|openai-api-key` adds an API key as an account of its own
458
+ (`authswitch.authority.apikey.add { providerId, apiKey, label?, spendLimitMicroUsd? }`, `AuthSwitchClient.addApiKey`).
459
+ The key is read from standard input -- a line typed at a terminal without echo, or everything piped in -- and never
460
+ taken as an argument, which the shell history and the process list would keep. A key beginning the way the other
461
+ provider's keys do is refused before any request (`sk-ant-` as an OpenAI key; `sk-proj-`, `sk-svcacct-` or `sk-admin-`
462
+ as an Anthropic key; a bare `sk-` is both providers' older form and is asked about). The daemon then asks the provider
463
+ for the key's models (`GET /v1/models`, 15 seconds) and stores nothing unless it accepts the key: a rejected key (401),
464
+ an OpenAI key that may not read models (403) and a provider that cannot be asked are refused with
465
+ `api_key_unverified`, and no refusal or log line repeats the provider's error, which could quote the key. The key is
466
+ sealed under its grant like every login, `{ kind: 'anthropicApiKey' | 'openaiApiKey', apiKey }` -- one kind per provider,
467
+ since sealed data is never migrated -- and never answered again; the account keeps only `keyHint` (`…` and the last four
468
+ characters) for display, derived from the key it seals, never accepted from a caller and never used to find or match a
469
+ key. The account's subject is a digest of the key and its tenancy (`organizationId`) is `api-key`, so a key is one
470
+ account: offered again while held it is refused (`invalid_input`); offered after its removal or a provider rejection it
471
+ brings the account back with a new authorization, its month's spend and its spend limit unless the request names one.
472
+ The login's purpose is `anthropic_api_key` or `openai_api_key`; it backs the `gateway` runtime alone and nothing renews
473
+ or revokes it. `--spend-limit` takes dollars to the cent (`12.50`, `$50`). The command prints the account, how its key
474
+ ends and its limit; `--json` prints `{ account, loginId }`.
475
+
476
+ `account set --spend-limit <dollars>` gives an API key account its monthly spend limit (`authswitch.authority.spendlimit
477
+ { accountId, expectedRevision, spendLimitMicroUsd }`, `isAuthSwitchSpendLimitMicroUsd`: a whole number of cents from
478
+ $0.01 to $1,000,000, in micro-dollars); `--clear-spend-limit` removes it. A sign-in has none (`invalid_input`), and a key
479
+ refuses `--max-usage` and a reserve lift. The month is the calendar month in UTC (`authSwitchSpendPeriod`). AGL's
480
+ inference proxy prices each answer it relays on a key once and reports it (`AuthSwitchClient.recordSpend`,
481
+ `authswitch.authority.usage.spend { accountId, loginId, answers }`, one to 64 `IAuthSwitchSpendAnswer { answerId,
482
+ endedAt, model, serviceTier, microUsd, priceSource }`, `microUsd` and `priceSource` null together for an answer it could
483
+ not price). The daemon records a report whole in one transaction: an entry per answer, keyed by account and answer id,
484
+ and the month's total; an answer it holds already with the same content changes nothing, one with other content refuses
485
+ the report (`invalid_input`, naming the answer), and a store conflict is an unmarked fault the proxy sends again. An
486
+ answer of a month before the previous one counts nowhere; only the current and the previous month are kept, the
487
+ earlier ones deleted a bounded number per report. A removed key's spend is recorded too, and its month stays with the
488
+ account. A key's usage (`authswitch.authority.usage`) is its month: `state: 'current'`, a reading `{ kind: 'spend',
489
+ spend: { period, periodStart, resetAt, spentMicroUsd, limitMicroUsd, answers, unpricedAnswers, lastAnswerAt } }`,
490
+ `observedAt` and `readAt` the moment the daemon read the ledger, current until the month ends; a ledger that cannot be
491
+ read answers `unavailable` with the problem `spend_unavailable`. `authSwitchUsageLimit` holds a key with a limit at it,
492
+ or with an unpriced answer, until `resetAt`, and ignores a maximum usage and a lift. A report, the month's first spend
493
+ and a limit change are account events only when they change whether the key is at its limit, begin the month, or change
494
+ the limit. `list` shows a key's month in dollars.
495
+
496
+ A key is held with a payment problem on its usage record, which for a key holds nothing but the problem:
497
+ `reportPaymentProblem(accountId, loginId, observedAt, signal, { cause })` with `cause` `spend_cap` or `quota` (absent:
498
+ `billing`) holds `{ at, subscription: null }` for billing, `{ at, subscription: null, cause: 'quota' }`, or `{ at,
499
+ subscription: null, cause: 'spend_cap', until }` with `until` the end of the month `at` falls in; a Claude login is held
500
+ only for billing. A spend cap past its `until` holds nothing (`authSwitchPaymentProblemHeld`). `account recheck` on a key
501
+ lifts its hold without asking the provider, whose model list states no billing or quota (`outcome: 'cleared'`, exit 0),
502
+ a spend cap's before the first of the month too; the provider's next refusal sets it again.
503
+
504
+ The service's store gains the account members `spendLimitMicroUsd` and `keyHint` (migration
505
+ `0011_account_api_key_fields`) and the collections `authswitch_authority_spend_entries` and
506
+ `authswitch_authority_spend_periods` at its first start. There is no downgrade past this release except restoring the
507
+ store from a backup taken before the upgrade: an older service refuses the new collections, the members and a key's
508
+ usage record.
509
+
453
510
  `account recheck <account-id>` re-checks the payment problem of a Claude account (a 402 `billing_error` took it out of
454
511
  the AGL proxy's rotation; see `reportPaymentProblem` below): the service reads the account's usage login -- the one
455
512
  `list` reads -- at once (`authswitch.authority.usage.recheck`) and answers how that read went. A read that finds the
456
513
  profile, the sign-in accepted and the identity matched is `healthy` and clears the problem, whatever subscription it
457
514
  finds; any other clears nothing and says why: `credential_rejected`, `token_unusable`, `profile_missing`, `mismatch` or
458
515
  `read_failed`. The command prints that, and whether a payment problem is still held, and exits 0 only for `healthy`;
459
- `--json` prints `{ accountId, loginId, outcome, usage }`. A ChatGPT account, or one without a Claude sign-in, is refused
460
- before anything is read.
516
+ `--json` prints `{ accountId, loginId, outcome, usage }`. An API key's re-check is `cleared` (above); a ChatGPT account,
517
+ or one with neither a Claude sign-in nor a key, is refused before anything is read.
461
518
 
462
519
  `account preuse` sends one quota-consuming prompt through the exact managed OpenAI account and
463
520
  login IDs. The default prompt is `Write 2000 words about strawberries.`; `--prompt` replaces it
@@ -567,9 +624,9 @@ routing settings and the processes on the home, writes nothing and asks no provi
567
624
  holds no login, and reading it creates nothing. `authswitch.authority.usage` still answers for the login of an
568
625
  adopted home from the home itself, and only while Claude Code demonstrably selects that login there: once the home's
569
626
  settings route Claude Code through the proxy, that read refuses until the login is released. Every Claude Code session
570
- on the home must run a release whose selector was read (2.1.273, 2.1.282) or a newer one, which the read takes as
571
- 2.1.282, a remote agent's hashed build ordered by its release; an unlisted release between them (2.1.274 to 2.1.281)
572
- refuses the read.
627
+ on the home must run a release whose selector was read (2.1.273, 2.1.282, 2.1.288, the release AGL's own Claude chats
628
+ run through the Agent SDK, and 2.1.306) or any release from 2.1.282 on, which the read takes as verified, a remote
629
+ agent's hashed build ordered by its release; an unlisted release below 2.1.282 (2.1.274 to 2.1.281) refuses the read.
573
630
 
574
631
  ### Releasing Claude Code's own login
575
632
 
@@ -774,9 +831,11 @@ written, and a registration of it that never settled asks for a device sign-in.
774
831
  for the sign-in -- a directory named by the operation id in the sign-in directory, which the service places at
775
832
  `$XDG_DATA_HOME/authswitch/claude-signin` (default `~/.local/share/authswitch/claude-signin`), beside the store --
776
833
  and answers `IAuthSwitchClaudeSignInOperation`: `pending`, with `prompt: { flow: 'terminal', command, directory }`.
777
- `command` is `claude auth login` with `CLAUDE_CONFIG_DIR` set to `directory`, quoted for a POSIX shell; a caller that
778
- runs Claude Code itself runs `claude` with `authSwitchClaudeSignInArguments` in that environment, as the command
779
- line does. Once `.credentials.json` is in the home and no Claude Code process runs on it, the authority imports the
834
+ `command` is `claude auth login` with `CLAUDE_CONFIG_DIR` and `CLAUDE_SECURESTORAGE_CONFIG_DIR` set to `directory`,
835
+ quoted for a POSIX shell; a caller that runs Claude Code itself runs `claude` with `authSwitchClaudeSignInArguments` in
836
+ that environment, as the command line does. The second variable keeps the credential store in the home: inherited from
837
+ the caller's environment, it would send the new login to another store, over whatever login that store holds, and the
838
+ sign-in would never see it. Once `.credentials.json` is in the home and no Claude Code process runs on it, the authority imports the
780
839
  login -- one rotating refresh, the import a saved Claude login gets, so the authority is its only renewer and the
781
840
  import's ledger row (source kind `claude_signin`) is its receipt -- and removes the home; the sign-in is then
782
841
  `complete` with `result: { accountId, loginId }`. An import that refuses leaves it `failed` with the import's
@@ -952,8 +1011,12 @@ try {
952
1011
  starts with `fixture-`.
953
1012
  - `provider` is the `AuthSwitchFakeClaudeProvider` the daemon talks to. It answers Anthropic's profile and
954
1013
  token endpoints for the fixture tokens it issued, with the switches a test needs (`profileDown`,
955
- `refreshTokens.set(token, 'rejected')`, `onProfile`, the `profileCalls` and `refreshCalls` counters), and
956
- fails every other request, OpenAI's included, so nothing a test starts reaches a real provider. Secrets are
1014
+ `refreshTokens.set(token, 'rejected')`, `onProfile`, the `profileCalls` and `refreshCalls` counters), and the
1015
+ model lists the authority reads to verify an API key: Anthropic's for the keys `issueApiKey(name)` issued, and
1016
+ OpenAI's (`GET https://api.openai.com/v1/models`) for those `issueOpenAiApiKey(name, { modelRead? })` issued,
1017
+ `sk-proj-fixture-<name>` -- 401 for any other key, quoting it as OpenAI does, 403 for a key issued with
1018
+ `modelRead: false`, 503 while `openAiModelsDown`, counted in `openAiModelListCalls`; delete a key from `apiKeys` or
1019
+ `openAiApiKeys` to revoke it. It fails every other request, so nothing a test starts reaches a real provider. Secrets are
957
1020
  sealed with a plain encoding, never in a keyring, and no Claude Code process is ever seen running on a home.
958
1021
  - Claude sign-ins run in `claudeSignInDirectory`. `claudeSignInLogin(name, { generation?, accessExpiresAt? })`
959
1022
  answers the two files `claude auth login` leaves once fixture account `name` signed in -- `files['.claude.json']`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agl",
3
- "version": "40.4.0",
3
+ "version": "40.5.0",
4
4
  "controllerUpgradeManagementVersion": 2,
5
5
  "private": false,
6
6
  "description": "Agent Gateway Layer for OpenCode, FlexHarness, and Codex sessions",
@@ -33,10 +33,10 @@
33
33
  "@lossless.org/objectstorage": "10.7.1",
34
34
  "@modelcontextprotocol/sdk": "1.30.0",
35
35
  "@modelprofile.com/catalog": "^1.0.0",
36
- "@modelprofile.com/flexharness": "16.1.0",
37
- "@modelprofile.com/flexharness-agent": "16.1.0",
38
- "@modelprofile.com/flexharness-models": "16.1.0",
39
- "@modelprofile.com/flexharness-providers": "16.1.0",
36
+ "@modelprofile.com/flexharness": "16.3.0",
37
+ "@modelprofile.com/flexharness-agent": "16.3.0",
38
+ "@modelprofile.com/flexharness-models": "16.3.0",
39
+ "@modelprofile.com/flexharness-providers": "16.3.0",
40
40
  "@modelprofile.com/mcp-crossharness": "5.9.0",
41
41
  "@modelprofile.com/mcp-system": "3.1.0",
42
42
  "@opencode-ai/sdk": "1.18.15",