@omnicross/subscriptions 0.2.1 → 0.3.1

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.
package/dist/index.js CHANGED
@@ -1,8 +1,10 @@
1
1
  import {
2
2
  claude_exports,
3
3
  codex_exports,
4
- gemini_exports
5
- } from "./chunk-4HYDPKHR.js";
4
+ gemini_exports,
5
+ kimiFingerprintHeaders,
6
+ kimi_exports
7
+ } from "./chunk-ZB3GA2Y2.js";
6
8
  import {
7
9
  accountSupportsModel,
8
10
  remapReportForAccount
@@ -125,13 +127,15 @@ var ACCOUNTS_KEY = {
125
127
  claude: "claudeAccounts",
126
128
  codex: "codexAccounts",
127
129
  gemini: "geminiAccounts",
128
- opencodego: "opencodegoAccounts"
130
+ opencodego: "opencodegoAccounts",
131
+ kimi: "kimiAccounts"
129
132
  };
130
133
  var ACTIVE_KEY = {
131
134
  claude: "activeClaudeAccountId",
132
135
  codex: "activeCodexAccountId",
133
136
  gemini: "activeGeminiAccountId",
134
- opencodego: "activeOpencodegoAccountId"
137
+ opencodego: "activeOpencodegoAccountId",
138
+ kimi: "activeKimiAccountId"
135
139
  };
136
140
  function gateSchedulable(accounts, providerId, health, now, resolvedModel, supportedModelsById) {
137
141
  if (!health && !resolvedModel || accounts.length < 2) return accounts;
@@ -421,13 +425,17 @@ var OAuthBearerAuthStrategy = class {
421
425
  return;
422
426
  }
423
427
  headers["Authorization"] = `Bearer ${token}`;
428
+ if (this.providerId === "kimi") {
429
+ const deviceId = await this.resolveKimiDeviceId(hints?.sessionKey);
430
+ Object.assign(headers, kimiFingerprintHeaders(deviceId));
431
+ }
424
432
  }
425
433
  async onUnauthorized(sessionKey) {
426
434
  const byId = await refreshSelectedAccount(this.selector, this.tokens, this.mutex, this.providerId, sessionKey);
427
435
  if (byId !== null) return byId;
428
436
  return this.mutex.run(`${this.providerId}:refresh`, async () => {
429
437
  try {
430
- return this.providerId === "codex" ? await this.tokens.refreshCodexToken() : await this.tokens.refreshGeminiToken();
438
+ return this.refreshActive();
431
439
  } catch (err) {
432
440
  console.warn(`[OAuthBearerAuthStrategy] ${this.providerId} refresh failed:`, err);
433
441
  return false;
@@ -436,7 +444,7 @@ var OAuthBearerAuthStrategy = class {
436
444
  }
437
445
  async describeStatus() {
438
446
  const config = await this.tokens.getFullConfig();
439
- const entry = this.providerId === "codex" ? config.codex : config.gemini;
447
+ const entry = this.tokenBlock(config);
440
448
  if (!entry?.accessToken) {
441
449
  return { providerId: this.providerId, ok: false, reason: "missing-credential" };
442
450
  }
@@ -453,22 +461,53 @@ var OAuthBearerAuthStrategy = class {
453
461
  /** Read the current token, refreshing in-line if it's within the lead window. */
454
462
  async resolveAccessToken() {
455
463
  const config = await this.tokens.getFullConfig();
456
- const entry = this.providerId === "codex" ? config.codex : config.gemini;
464
+ const entry = this.tokenBlock(config);
457
465
  if (!entry?.accessToken) return null;
458
466
  const expiresAtMs = entry.expiresAt ? new Date(entry.expiresAt).getTime() : 0;
459
467
  const expiringSoon = expiresAtMs > 0 && Date.now() >= expiresAtMs - REFRESH_LEAD_MS;
460
468
  if (expiringSoon && entry.refreshToken) {
461
469
  const refreshed = await this.mutex.run(`${this.providerId}:refresh`, async () => {
462
- return this.providerId === "codex" ? await this.tokens.refreshCodexToken() : await this.tokens.refreshGeminiToken();
470
+ return this.refreshActive();
463
471
  });
464
472
  if (!refreshed) return null;
465
473
  const fresh = await this.tokens.getFullConfig();
466
- const freshEntry = this.providerId === "codex" ? fresh.codex : fresh.gemini;
467
- return freshEntry?.accessToken ?? null;
474
+ return this.tokenBlock(fresh)?.accessToken ?? null;
468
475
  }
469
476
  if (entry.status === "expired") return null;
470
477
  return entry.accessToken;
471
478
  }
479
+ /** The active account's refresh, dispatched per provider. */
480
+ refreshActive() {
481
+ switch (this.providerId) {
482
+ case "codex":
483
+ return this.tokens.refreshCodexToken();
484
+ case "gemini":
485
+ return this.tokens.refreshGeminiToken();
486
+ case "kimi":
487
+ return this.tokens.refreshKimiToken ? this.tokens.refreshKimiToken() : Promise.resolve(false);
488
+ }
489
+ }
490
+ tokenBlock(config) {
491
+ switch (this.providerId) {
492
+ case "codex":
493
+ return config.codex;
494
+ case "gemini":
495
+ return config.gemini;
496
+ case "kimi":
497
+ return config.kimi;
498
+ }
499
+ }
500
+ /**
501
+ * Best-effort device id for the fingerprint header. Selection already ran in
502
+ * `applyHeaders`; rather than re-deriving it, read the active block's id (a
503
+ * pool-served non-active account momentarily reports the active id — the
504
+ * header is per-INSTALL identity, so this is cosmetic, not auth).
505
+ */
506
+ async resolveKimiDeviceId(_sessionKey) {
507
+ void _sessionKey;
508
+ const config = await this.tokens.getFullConfig();
509
+ return config.kimi?.deviceId ?? config.kimiAccounts?.[0]?.tokens.deviceId;
510
+ }
472
511
  };
473
512
 
474
513
  // src/auth/PassThroughAuthStrategy.ts
@@ -615,7 +654,8 @@ var DISPLAY_NAMES = {
615
654
  claude: "Claude (Anthropic OAuth)",
616
655
  codex: "Codex (ChatGPT OAuth)",
617
656
  gemini: "Gemini (Google OAuth)",
618
- opencodego: "OpenCodeGo (Bearer key)"
657
+ opencodego: "OpenCodeGo (Bearer key)",
658
+ kimi: "Kimi Code (Moonshot OAuth)"
619
659
  };
620
660
  var SubscriptionAccountService = class {
621
661
  mutex = new RefreshMutex();
@@ -629,7 +669,8 @@ var SubscriptionAccountService = class {
629
669
  ["claude", new PassThroughAuthStrategy(tokens, this.mutex, this.selector, health)],
630
670
  ["codex", new OAuthBearerAuthStrategy("codex", tokens, this.mutex, this.selector, health)],
631
671
  ["gemini", new OAuthBearerAuthStrategy("gemini", tokens, this.mutex, this.selector, health)],
632
- ["opencodego", new StaticBearerAuthStrategy(tokens, this.selector, health)]
672
+ ["opencodego", new StaticBearerAuthStrategy(tokens, this.selector, health)],
673
+ ["kimi", new OAuthBearerAuthStrategy("kimi", tokens, this.mutex, this.selector, health)]
633
674
  ]);
634
675
  }
635
676
  /** Returns the strategy bound to a subscription provider, or `null` for unknown ids. */
@@ -1079,7 +1120,8 @@ var SubscriptionProviderRegistry = class {
1079
1120
  const codex = this.accounts.getStrategy("codex");
1080
1121
  const gemini = this.accounts.getStrategy("gemini");
1081
1122
  const opencodego = this.accounts.getStrategy("opencodego");
1082
- if (!claude || !codex || !gemini || !opencodego) {
1123
+ const kimi = this.accounts.getStrategy("kimi");
1124
+ if (!claude || !codex || !gemini || !opencodego || !kimi) {
1083
1125
  throw new Error("[SubscriptionProviderRegistry] Missing strategy in SubscriptionAccountService");
1084
1126
  }
1085
1127
  this.profiles = /* @__PURE__ */ new Map([
@@ -1221,6 +1263,25 @@ var SubscriptionProviderRegistry = class {
1221
1263
  // profile sets it — claude / codex / gemini leave it UNSET (no-op).
1222
1264
  recordModelOutcome: (modelId, ok) => ok ? this.breaker.recordSuccess(modelId) : this.breaker.recordFailure(modelId)
1223
1265
  }
1266
+ ],
1267
+ [
1268
+ "kimi",
1269
+ {
1270
+ providerId: "kimi",
1271
+ displayName: "Kimi Code (Moonshot OAuth)",
1272
+ authStrategy: kimi,
1273
+ mode: "transformer",
1274
+ // Kimi Code's subscription surface speaks standard Anthropic Messages
1275
+ // at `api.kimi.com/coding/v1/messages` (plus an OpenAI chat face on
1276
+ // /chat/completions that a BYO kimi row already covers). The messages
1277
+ // URL ending in `/v1/messages` makes the core plan builder treat it as
1278
+ // same-format — the SDK's Anthropic body relays verbatim, with the
1279
+ // OAuth bearer + X-Msh-* fingerprint headers injected by the strategy.
1280
+ resolveUpstreamUrl: () => "https://api.kimi.com/coding/v1/messages",
1281
+ // Route-to only (Responses/Chat ingress): Unified → Anthropic Messages.
1282
+ providerTransformerNames: ["anthropic"],
1283
+ modelTransformerNames: []
1284
+ }
1224
1285
  ]
1225
1286
  ]);
1226
1287
  }
@@ -2548,6 +2609,9 @@ export {
2548
2609
  gemini_exports as geminiOAuth,
2549
2610
  getSubscriptionAccountService,
2550
2611
  getSubscriptionProviderRegistry,
2612
+ kimiFingerprintHeaders,
2613
+ kimi_exports as kimiOAuth,
2614
+ normalizeOpenCodeGoBaseUrl,
2551
2615
  setSubscriptionAccountService,
2552
2616
  setSubscriptionProviderRegistry
2553
2617
  };
package/dist/oauth.cjs CHANGED
@@ -2,10 +2,14 @@
2
2
 
3
3
 
4
4
 
5
- var _chunkUXUMAXZJcjs = require('./chunk-UXUMAXZJ.cjs');
5
+
6
+
7
+ var _chunkB2LHAP4Fcjs = require('./chunk-B2LHAP4F.cjs');
6
8
  require('./chunk-75ZPJI57.cjs');
7
9
 
8
10
 
9
11
 
10
12
 
11
- exports.claudeOAuth = _chunkUXUMAXZJcjs.claude_exports; exports.codexOAuth = _chunkUXUMAXZJcjs.codex_exports; exports.geminiOAuth = _chunkUXUMAXZJcjs.gemini_exports;
13
+
14
+
15
+ exports.claudeOAuth = _chunkB2LHAP4Fcjs.claude_exports; exports.codexOAuth = _chunkB2LHAP4Fcjs.codex_exports; exports.geminiOAuth = _chunkB2LHAP4Fcjs.gemini_exports; exports.kimiFingerprintHeaders = _chunkB2LHAP4Fcjs.kimiFingerprintHeaders; exports.kimiOAuth = _chunkB2LHAP4Fcjs.kimi_exports;
package/dist/oauth.d.cts CHANGED
@@ -2,6 +2,123 @@ import { FetchLike } from '@omnicross/core/auth/GeminiCodeAssistProjectResolver'
2
2
  export { FetchLike } from '@omnicross/core/auth/GeminiCodeAssistProjectResolver';
3
3
  import { TokenExchangeRequest, OAuthParams } from '@omnicross/contracts/account-tokens-types';
4
4
 
5
+ /**
6
+ * Kimi Code OAuth flow — RFC 8628 device authorization grant (host-clean).
7
+ *
8
+ * Matches the official Kimi CLI's client at `auth.kimi.com`: a form-encoded
9
+ * device-authorization request, the user approving at `verification_uri`, and a
10
+ * polled token request whose RFC error codes (`authorization_pending` /
11
+ * `slow_down` / `expired_token` / `access_denied`) arrive as HTTP 400 bodies —
12
+ * which is why the poll does NOT use `postForm` (that helper rejects on
13
+ * `error`). No PKCE, no client secret, no scopes. Refresh is a standard
14
+ * `refresh_token` grant on the same endpoint.
15
+ *
16
+ * The access token's JWT payload carries `user_id` (fallback `sub`) — that is
17
+ * the account id. Inference and the `/coding/v1/usages` quota endpoint ride
18
+ * `api.kimi.com/coding/v1`; every Kimi request also carries the
19
+ * `X-Msh-*` fingerprint headers (`kimiFingerprintHeaders`).
20
+ *
21
+ * @module @omnicross/subscriptions/oauth/flows/kimi
22
+ */
23
+
24
+ /** Kimi CLI OAuth configuration (public client, matches the official CLI). */
25
+ declare const KIMI_OAUTH_CONFIG: {
26
+ readonly clientId: "17e5f671-d194-4dfb-9706-5516cb48c098";
27
+ readonly deviceAuthorizationEndpoint: "https://auth.kimi.com/api/oauth/device_authorization";
28
+ readonly tokenEndpoint: "https://auth.kimi.com/api/oauth/token";
29
+ };
30
+ /**
31
+ * The client version reported in `User-Agent`/`X-Msh-Version`. Kimi's backend
32
+ * gates on the CLI identity; this mirrors a current official CLI version.
33
+ * Overridable via `KIMI_CLI_VERSION` when the upstream moves.
34
+ */
35
+ declare const KIMI_CLI_VERSION: string;
36
+ /** Device-authorization response (RFC 8628 §3.2). */
37
+ interface KimiDeviceAuthorization {
38
+ userCode: string;
39
+ deviceCode: string;
40
+ /** Preferred: pre-fills the code when opened in the user's browser. */
41
+ verificationUri: string;
42
+ verificationUriComplete?: string;
43
+ /** Poll interval in seconds (RFC default 5). */
44
+ interval?: number;
45
+ /** Lifetime in seconds. */
46
+ expiresIn?: number;
47
+ }
48
+ /** One polled token attempt's outcome. */
49
+ type KimiDevicePoll = {
50
+ state: 'pending';
51
+ intervalSeconds?: number;
52
+ } | {
53
+ state: 'done';
54
+ accessToken: string;
55
+ refreshToken: string;
56
+ expiresIn: number;
57
+ } | {
58
+ state: 'failed';
59
+ message: string;
60
+ };
61
+ /**
62
+ * The fingerprint headers every Kimi API request carries (auth, inference,
63
+ * usage). `deviceId` is the per-account stable device id stored on the token
64
+ * config — NOT a host-global value, so two accounts on one install present two
65
+ * device identities, matching how the CLI scopes its `kimi-device-id` file per
66
+ * credential store.
67
+ */
68
+ declare function kimiFingerprintHeaders(deviceId: string | undefined): Record<string, string>;
69
+ /** Mint the stable per-account device id (hex UUID, no dashes). */
70
+ declare function generateKimiDeviceId(): string;
71
+ /** Request a device code the user approves at `verification_uri`. */
72
+ declare function requestDeviceAuthorization(fetchImpl: FetchLike, fingerprint?: Record<string, string>): Promise<KimiDeviceAuthorization>;
73
+ /**
74
+ * Poll the token endpoint ONCE. RFC 8628 §3.5 semantics: `authorization_pending`
75
+ * keeps polling, `slow_down` adds 5s to the interval, anything else fails. The
76
+ * error codes arrive on HTTP 400 with an `error` JSON field, so this deliberately
77
+ * does NOT route through `postForm` (which rejects on any `error` body).
78
+ */
79
+ declare function pollDeviceToken(deviceCode: string, fetchImpl: FetchLike, fingerprint?: Record<string, string>): Promise<KimiDevicePoll>;
80
+ /**
81
+ * Drive the device-code login to completion: poll at the device flow's interval
82
+ * (`slow_down` +5s each time) until done/expired/denied or `deadlineMs` elapses.
83
+ * `onPending` fires after each pending poll (so a CLI can render a spinner).
84
+ */
85
+ declare function awaitDeviceToken(authorization: KimiDeviceAuthorization, fetchImpl: FetchLike, options?: {
86
+ fingerprint?: Record<string, string>;
87
+ intervalMs?: number;
88
+ deadlineMs?: number;
89
+ sleep?: (ms: number) => Promise<void>;
90
+ onPending?: () => void;
91
+ }): Promise<{
92
+ accessToken: string;
93
+ refreshToken: string;
94
+ expiresIn: number;
95
+ }>;
96
+ /** Refresh the access token with a `refresh_token` grant. */
97
+ declare function refreshAccessToken$3(refreshToken: string, fetchImpl: FetchLike, fingerprint?: Record<string, string>): Promise<{
98
+ accessToken: string;
99
+ refreshToken: string;
100
+ expiresIn: number;
101
+ }>;
102
+ /**
103
+ * Decode the access-token JWT's `user_id | sub` claim (no verification — the
104
+ * issuer is trusted; we only read an id).
105
+ */
106
+ declare function kimiAccountIdFromAccessToken(accessToken: string): string | undefined;
107
+
108
+ declare const kimi_KIMI_CLI_VERSION: typeof KIMI_CLI_VERSION;
109
+ declare const kimi_KIMI_OAUTH_CONFIG: typeof KIMI_OAUTH_CONFIG;
110
+ type kimi_KimiDeviceAuthorization = KimiDeviceAuthorization;
111
+ type kimi_KimiDevicePoll = KimiDevicePoll;
112
+ declare const kimi_awaitDeviceToken: typeof awaitDeviceToken;
113
+ declare const kimi_generateKimiDeviceId: typeof generateKimiDeviceId;
114
+ declare const kimi_kimiAccountIdFromAccessToken: typeof kimiAccountIdFromAccessToken;
115
+ declare const kimi_kimiFingerprintHeaders: typeof kimiFingerprintHeaders;
116
+ declare const kimi_pollDeviceToken: typeof pollDeviceToken;
117
+ declare const kimi_requestDeviceAuthorization: typeof requestDeviceAuthorization;
118
+ declare namespace kimi {
119
+ export { kimi_KIMI_CLI_VERSION as KIMI_CLI_VERSION, kimi_KIMI_OAUTH_CONFIG as KIMI_OAUTH_CONFIG, type kimi_KimiDeviceAuthorization as KimiDeviceAuthorization, type kimi_KimiDevicePoll as KimiDevicePoll, kimi_awaitDeviceToken as awaitDeviceToken, kimi_generateKimiDeviceId as generateKimiDeviceId, kimi_kimiAccountIdFromAccessToken as kimiAccountIdFromAccessToken, kimi_kimiFingerprintHeaders as kimiFingerprintHeaders, kimi_pollDeviceToken as pollDeviceToken, refreshAccessToken$3 as refreshAccessToken, kimi_requestDeviceAuthorization as requestDeviceAuthorization };
120
+ }
121
+
5
122
  /**
6
123
  * Claude OAuth flow — host-clean PKCE logic.
7
124
  *
@@ -123,4 +240,4 @@ declare namespace gemini {
123
240
  export { gemini_exchangeCodeForTokens as exchangeCodeForTokens, gemini_generateAuthParams as generateAuthParams, gemini_refreshAccessToken as refreshAccessToken };
124
241
  }
125
242
 
126
- export { claude as claudeOAuth, codex as codexOAuth, gemini as geminiOAuth };
243
+ export { claude as claudeOAuth, codex as codexOAuth, gemini as geminiOAuth, kimiFingerprintHeaders, kimi as kimiOAuth };
package/dist/oauth.d.ts CHANGED
@@ -2,6 +2,123 @@ import { FetchLike } from '@omnicross/core/auth/GeminiCodeAssistProjectResolver'
2
2
  export { FetchLike } from '@omnicross/core/auth/GeminiCodeAssistProjectResolver';
3
3
  import { TokenExchangeRequest, OAuthParams } from '@omnicross/contracts/account-tokens-types';
4
4
 
5
+ /**
6
+ * Kimi Code OAuth flow — RFC 8628 device authorization grant (host-clean).
7
+ *
8
+ * Matches the official Kimi CLI's client at `auth.kimi.com`: a form-encoded
9
+ * device-authorization request, the user approving at `verification_uri`, and a
10
+ * polled token request whose RFC error codes (`authorization_pending` /
11
+ * `slow_down` / `expired_token` / `access_denied`) arrive as HTTP 400 bodies —
12
+ * which is why the poll does NOT use `postForm` (that helper rejects on
13
+ * `error`). No PKCE, no client secret, no scopes. Refresh is a standard
14
+ * `refresh_token` grant on the same endpoint.
15
+ *
16
+ * The access token's JWT payload carries `user_id` (fallback `sub`) — that is
17
+ * the account id. Inference and the `/coding/v1/usages` quota endpoint ride
18
+ * `api.kimi.com/coding/v1`; every Kimi request also carries the
19
+ * `X-Msh-*` fingerprint headers (`kimiFingerprintHeaders`).
20
+ *
21
+ * @module @omnicross/subscriptions/oauth/flows/kimi
22
+ */
23
+
24
+ /** Kimi CLI OAuth configuration (public client, matches the official CLI). */
25
+ declare const KIMI_OAUTH_CONFIG: {
26
+ readonly clientId: "17e5f671-d194-4dfb-9706-5516cb48c098";
27
+ readonly deviceAuthorizationEndpoint: "https://auth.kimi.com/api/oauth/device_authorization";
28
+ readonly tokenEndpoint: "https://auth.kimi.com/api/oauth/token";
29
+ };
30
+ /**
31
+ * The client version reported in `User-Agent`/`X-Msh-Version`. Kimi's backend
32
+ * gates on the CLI identity; this mirrors a current official CLI version.
33
+ * Overridable via `KIMI_CLI_VERSION` when the upstream moves.
34
+ */
35
+ declare const KIMI_CLI_VERSION: string;
36
+ /** Device-authorization response (RFC 8628 §3.2). */
37
+ interface KimiDeviceAuthorization {
38
+ userCode: string;
39
+ deviceCode: string;
40
+ /** Preferred: pre-fills the code when opened in the user's browser. */
41
+ verificationUri: string;
42
+ verificationUriComplete?: string;
43
+ /** Poll interval in seconds (RFC default 5). */
44
+ interval?: number;
45
+ /** Lifetime in seconds. */
46
+ expiresIn?: number;
47
+ }
48
+ /** One polled token attempt's outcome. */
49
+ type KimiDevicePoll = {
50
+ state: 'pending';
51
+ intervalSeconds?: number;
52
+ } | {
53
+ state: 'done';
54
+ accessToken: string;
55
+ refreshToken: string;
56
+ expiresIn: number;
57
+ } | {
58
+ state: 'failed';
59
+ message: string;
60
+ };
61
+ /**
62
+ * The fingerprint headers every Kimi API request carries (auth, inference,
63
+ * usage). `deviceId` is the per-account stable device id stored on the token
64
+ * config — NOT a host-global value, so two accounts on one install present two
65
+ * device identities, matching how the CLI scopes its `kimi-device-id` file per
66
+ * credential store.
67
+ */
68
+ declare function kimiFingerprintHeaders(deviceId: string | undefined): Record<string, string>;
69
+ /** Mint the stable per-account device id (hex UUID, no dashes). */
70
+ declare function generateKimiDeviceId(): string;
71
+ /** Request a device code the user approves at `verification_uri`. */
72
+ declare function requestDeviceAuthorization(fetchImpl: FetchLike, fingerprint?: Record<string, string>): Promise<KimiDeviceAuthorization>;
73
+ /**
74
+ * Poll the token endpoint ONCE. RFC 8628 §3.5 semantics: `authorization_pending`
75
+ * keeps polling, `slow_down` adds 5s to the interval, anything else fails. The
76
+ * error codes arrive on HTTP 400 with an `error` JSON field, so this deliberately
77
+ * does NOT route through `postForm` (which rejects on any `error` body).
78
+ */
79
+ declare function pollDeviceToken(deviceCode: string, fetchImpl: FetchLike, fingerprint?: Record<string, string>): Promise<KimiDevicePoll>;
80
+ /**
81
+ * Drive the device-code login to completion: poll at the device flow's interval
82
+ * (`slow_down` +5s each time) until done/expired/denied or `deadlineMs` elapses.
83
+ * `onPending` fires after each pending poll (so a CLI can render a spinner).
84
+ */
85
+ declare function awaitDeviceToken(authorization: KimiDeviceAuthorization, fetchImpl: FetchLike, options?: {
86
+ fingerprint?: Record<string, string>;
87
+ intervalMs?: number;
88
+ deadlineMs?: number;
89
+ sleep?: (ms: number) => Promise<void>;
90
+ onPending?: () => void;
91
+ }): Promise<{
92
+ accessToken: string;
93
+ refreshToken: string;
94
+ expiresIn: number;
95
+ }>;
96
+ /** Refresh the access token with a `refresh_token` grant. */
97
+ declare function refreshAccessToken$3(refreshToken: string, fetchImpl: FetchLike, fingerprint?: Record<string, string>): Promise<{
98
+ accessToken: string;
99
+ refreshToken: string;
100
+ expiresIn: number;
101
+ }>;
102
+ /**
103
+ * Decode the access-token JWT's `user_id | sub` claim (no verification — the
104
+ * issuer is trusted; we only read an id).
105
+ */
106
+ declare function kimiAccountIdFromAccessToken(accessToken: string): string | undefined;
107
+
108
+ declare const kimi_KIMI_CLI_VERSION: typeof KIMI_CLI_VERSION;
109
+ declare const kimi_KIMI_OAUTH_CONFIG: typeof KIMI_OAUTH_CONFIG;
110
+ type kimi_KimiDeviceAuthorization = KimiDeviceAuthorization;
111
+ type kimi_KimiDevicePoll = KimiDevicePoll;
112
+ declare const kimi_awaitDeviceToken: typeof awaitDeviceToken;
113
+ declare const kimi_generateKimiDeviceId: typeof generateKimiDeviceId;
114
+ declare const kimi_kimiAccountIdFromAccessToken: typeof kimiAccountIdFromAccessToken;
115
+ declare const kimi_kimiFingerprintHeaders: typeof kimiFingerprintHeaders;
116
+ declare const kimi_pollDeviceToken: typeof pollDeviceToken;
117
+ declare const kimi_requestDeviceAuthorization: typeof requestDeviceAuthorization;
118
+ declare namespace kimi {
119
+ export { kimi_KIMI_CLI_VERSION as KIMI_CLI_VERSION, kimi_KIMI_OAUTH_CONFIG as KIMI_OAUTH_CONFIG, type kimi_KimiDeviceAuthorization as KimiDeviceAuthorization, type kimi_KimiDevicePoll as KimiDevicePoll, kimi_awaitDeviceToken as awaitDeviceToken, kimi_generateKimiDeviceId as generateKimiDeviceId, kimi_kimiAccountIdFromAccessToken as kimiAccountIdFromAccessToken, kimi_kimiFingerprintHeaders as kimiFingerprintHeaders, kimi_pollDeviceToken as pollDeviceToken, refreshAccessToken$3 as refreshAccessToken, kimi_requestDeviceAuthorization as requestDeviceAuthorization };
120
+ }
121
+
5
122
  /**
6
123
  * Claude OAuth flow — host-clean PKCE logic.
7
124
  *
@@ -123,4 +240,4 @@ declare namespace gemini {
123
240
  export { gemini_exchangeCodeForTokens as exchangeCodeForTokens, gemini_generateAuthParams as generateAuthParams, gemini_refreshAccessToken as refreshAccessToken };
124
241
  }
125
242
 
126
- export { claude as claudeOAuth, codex as codexOAuth, gemini as geminiOAuth };
243
+ export { claude as claudeOAuth, codex as codexOAuth, gemini as geminiOAuth, kimiFingerprintHeaders, kimi as kimiOAuth };
package/dist/oauth.js CHANGED
@@ -1,11 +1,15 @@
1
1
  import {
2
2
  claude_exports,
3
3
  codex_exports,
4
- gemini_exports
5
- } from "./chunk-4HYDPKHR.js";
4
+ gemini_exports,
5
+ kimiFingerprintHeaders,
6
+ kimi_exports
7
+ } from "./chunk-ZB3GA2Y2.js";
6
8
  import "./chunk-MLKGABMK.js";
7
9
  export {
8
10
  claude_exports as claudeOAuth,
9
11
  codex_exports as codexOAuth,
10
- gemini_exports as geminiOAuth
12
+ gemini_exports as geminiOAuth,
13
+ kimiFingerprintHeaders,
14
+ kimi_exports as kimiOAuth
11
15
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnicross/subscriptions",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "description": "Omnicross subscription-as-provider auth strategies, OAuth flows, and the OpenCodeGo scenario dispatcher.",
5
5
  "license": "MIT",
6
6
  "author": "Sayo (https://github.com/Dumoedss)",
@@ -52,8 +52,8 @@
52
52
  "typecheck": "tsc -p tsconfig.typecheck.json --noEmit"
53
53
  },
54
54
  "dependencies": {
55
- "@omnicross/contracts": "^0.2.1",
56
- "@omnicross/core": "^0.2.1",
55
+ "@omnicross/contracts": "^0.3.1",
56
+ "@omnicross/core": "^0.3.1",
57
57
  "js-tiktoken": "^1.0.21",
58
58
  "sharp": "^0.35.4"
59
59
  }