From 4a93f70aa2cf5f70a88b4f8eeb2e409aab2c8f59 Mon Sep 17 00:00:00 2001 From: liruifengv Date: Thu, 13 Aug 2026 18:26:10 +0800 Subject: [PATCH] feat(oauth): add browser-safe ./device subpath export (#2885) * feat(oauth): add browser-safe ./device subpath export * fix(oauth): guard env override lookup for browser consumers * chore(oauth): add changeset for ./device subpath export * fix(oauth): resolve env overrides via globalThis for DOM-only consumers --- .changeset/oauth-device-subpath-export.md | 5 ++++ packages/oauth/package.json | 4 +++ packages/oauth/src/constants.ts | 13 ++++++++-- packages/oauth/src/device.ts | 31 +++++++++++++++++++++++ packages/oauth/tsdown.config.ts | 2 +- 5 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 .changeset/oauth-device-subpath-export.md create mode 100644 packages/oauth/src/device.ts diff --git a/.changeset/oauth-device-subpath-export.md b/.changeset/oauth-device-subpath-export.md new file mode 100644 index 000000000..8c43547c1 --- /dev/null +++ b/.changeset/oauth-device-subpath-export.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code-oauth": minor +--- + +Add a browser-safe `./device` subpath export exposing the device-code flow's pure-fetch HTTP wrappers and flow config, so browser bundles can run OAuth sign-in without pulling in Node-only modules. Import from `@moonshot-ai/kimi-code-oauth/device`. diff --git a/packages/oauth/package.json b/packages/oauth/package.json index f31acaf12..4b9d4b82f 100644 --- a/packages/oauth/package.json +++ b/packages/oauth/package.json @@ -32,6 +32,10 @@ ".": { "types": "./src/index.ts", "default": "./src/index.ts" + }, + "./device": { + "types": "./src/device.ts", + "default": "./src/device.ts" } }, "scripts": { diff --git a/packages/oauth/src/constants.ts b/packages/oauth/src/constants.ts index 58ad3f259..4c1cfcc77 100644 --- a/packages/oauth/src/constants.ts +++ b/packages/oauth/src/constants.ts @@ -2,11 +2,20 @@ import type { OAuthFlowConfig } from './types'; export const DEFAULT_KIMI_CODE_OAUTH_HOST = 'https://auth.kimi.com'; +/** Node-side env override lookup, resolved through `globalThis` so the module + stays loadable — and typecheckable — in browser bundles that have no + `process` global (browser consumers of the ./device entry land on the + default host). */ +function envOverride(key: string): string | undefined { + const proc = (globalThis as { process?: { env?: Record } }).process; + return proc?.env?.[key]; +} + export const KIMI_CODE_FLOW_CONFIG: OAuthFlowConfig = { name: 'kimi-code', oauthHost: - process.env['KIMI_CODE_OAUTH_HOST'] ?? - process.env['KIMI_OAUTH_HOST'] ?? + envOverride('KIMI_CODE_OAUTH_HOST') ?? + envOverride('KIMI_OAUTH_HOST') ?? DEFAULT_KIMI_CODE_OAUTH_HOST, clientId: '17e5f671-d194-4dfb-9706-5516cb48c098', }; diff --git a/packages/oauth/src/device.ts b/packages/oauth/src/device.ts new file mode 100644 index 000000000..888cf1736 --- /dev/null +++ b/packages/oauth/src/device.ts @@ -0,0 +1,31 @@ +/** + * Browser-safe entry for the device-code flow (`@moonshot-ai/kimi-code-oauth/device`). + * + * The package root re-exports `OAuthManager`, token storage, and the identity + * helpers, which pull in `node:fs` / `node:os` / `proper-lockfile` — fine for + * the CLI and desktop hosts, but unloadable in a browser bundle. This entry + * re-exports only the pure-`fetch` surface (every module in its import + * closure is Node-free): the three HTTP wrappers, the shared flow config, + * and the matching types/errors. Keep it that way — anything that needs a + * Node builtin belongs behind the root entry, not here. + * + * Browser callers drive the flow themselves (request → show the verification + * URI → poll → store the token); there is no manager here on purpose. + */ + +export { KIMI_CODE_FLOW_CONFIG } from './constants'; +export { + OAuthConnectionError, + OAuthError, + OAuthUnauthorizedError, + RetryableRefreshError, +} from './errors'; +export type { DevicePollResult, RefreshOptions } from './oauth'; +export { pollDeviceToken, refreshAccessToken, requestDeviceAuthorization } from './oauth'; +export type { + DeviceAuthorization, + DeviceHeaders, + OAuthFlowConfig, + OAuthRequestHeaders, + TokenInfo, +} from './types'; diff --git a/packages/oauth/tsdown.config.ts b/packages/oauth/tsdown.config.ts index cb99d9ffb..349cfef15 100644 --- a/packages/oauth/tsdown.config.ts +++ b/packages/oauth/tsdown.config.ts @@ -1,7 +1,7 @@ import { defineConfig } from 'tsdown'; export default defineConfig({ - entry: ['./src/index.ts'], + entry: ['./src/index.ts', './src/device.ts'], format: ['esm'], dts: true, outDir: 'dist',