@serviceme/devtools-core 2.0.0 → 2.0.2

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 (82) hide show
  1. package/dist/auth-Bzss8zOv.mjs +995 -0
  2. package/dist/auth-Bzss8zOv.mjs.map +1 -0
  3. package/dist/auth-DXam3c4S.js +1078 -0
  4. package/dist/auth-DXam3c4S.js.map +1 -0
  5. package/dist/auth.d.mts +2 -2
  6. package/dist/auth.d.ts +2 -2
  7. package/dist/auth.js +14 -1029
  8. package/dist/auth.mjs +2 -991
  9. package/dist/device-CDDcwDY6.mjs +758 -0
  10. package/dist/device-CDDcwDY6.mjs.map +1 -0
  11. package/dist/device-DuAYH8bk.js +839 -0
  12. package/dist/device-DuAYH8bk.js.map +1 -0
  13. package/dist/device.d.mts +2 -455
  14. package/dist/device.d.ts +2 -455
  15. package/dist/device.js +15 -728
  16. package/dist/device.mjs +2 -679
  17. package/dist/index-2rX86yMq.d.mts +331 -0
  18. package/dist/index-BI11AfMH.d.mts +377 -0
  19. package/dist/index-BI11AfMH.d.ts +377 -0
  20. package/dist/index-CoA6y0MP.d.mts +498 -0
  21. package/dist/index-CoA6y0MP.d.ts +498 -0
  22. package/dist/index-DaW7IYA-.d.mts +185 -0
  23. package/dist/index-DaW7IYA-.d.ts +185 -0
  24. package/dist/index-Dp6FwWKh.d.ts +331 -0
  25. package/dist/index.d.mts +2340 -2101
  26. package/dist/index.d.ts +2340 -2101
  27. package/dist/index.js +8117 -10538
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +7895 -10318
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/rolldown-runtime-VH7oDXx4.js +28 -0
  32. package/dist/skill-linker.d.mts +82 -81
  33. package/dist/skill-linker.d.ts +82 -81
  34. package/dist/skill-linker.js +359 -402
  35. package/dist/skill-linker.js.map +1 -1
  36. package/dist/skill-linker.mjs +345 -357
  37. package/dist/skill-linker.mjs.map +1 -1
  38. package/dist/skill-store-Bym2yinU.mjs +388 -0
  39. package/dist/skill-store-Bym2yinU.mjs.map +1 -0
  40. package/dist/skill-store-CJdYyyxu.js +408 -0
  41. package/dist/skill-store-CJdYyyxu.js.map +1 -0
  42. package/dist/skill-store.d.mts +41 -42
  43. package/dist/skill-store.d.ts +41 -42
  44. package/dist/skill-store.js +5 -338
  45. package/dist/skill-store.mjs +2 -301
  46. package/dist/submit-Cg7wSa3x.mjs +84 -0
  47. package/dist/submit-Cg7wSa3x.mjs.map +1 -0
  48. package/dist/submit-CltE6YOZ.js +98 -0
  49. package/dist/submit-CltE6YOZ.js.map +1 -0
  50. package/dist/submit.d.mts +2 -3
  51. package/dist/submit.d.ts +2 -3
  52. package/dist/submit.js +4 -166
  53. package/dist/submit.mjs +2 -130
  54. package/dist/toolbox-CbfxpNg-.mjs +540 -0
  55. package/dist/toolbox-CbfxpNg-.mjs.map +1 -0
  56. package/dist/toolbox-CxnOr-FY.js +614 -0
  57. package/dist/toolbox-CxnOr-FY.js.map +1 -0
  58. package/dist/toolbox.d.mts +2 -244
  59. package/dist/toolbox.d.ts +2 -244
  60. package/dist/toolbox.js +14 -584
  61. package/dist/toolbox.mjs +2 -536
  62. package/dist/{types-B9gk3dXH.d.ts → types-BCV3IedE.d.mts} +25 -23
  63. package/dist/{types-B9gk3dXH.d.mts → types-BCV3IedE.d.ts} +25 -23
  64. package/dist/userHome-BquDeFVE.js +526 -0
  65. package/dist/userHome-BquDeFVE.js.map +1 -0
  66. package/dist/userHome-CcnAQPG1.mjs +212 -0
  67. package/dist/userHome-CcnAQPG1.mjs.map +1 -0
  68. package/package.json +10 -10
  69. package/dist/auth.js.map +0 -1
  70. package/dist/auth.mjs.map +0 -1
  71. package/dist/device.js.map +0 -1
  72. package/dist/device.mjs.map +0 -1
  73. package/dist/index-BMk4tqIT.d.mts +0 -328
  74. package/dist/index-CymN0x9Z.d.ts +0 -328
  75. package/dist/index-PD135hlB.d.mts +0 -626
  76. package/dist/index-PD135hlB.d.ts +0 -626
  77. package/dist/skill-store.js.map +0 -1
  78. package/dist/skill-store.mjs.map +0 -1
  79. package/dist/submit.js.map +0 -1
  80. package/dist/submit.mjs.map +0 -1
  81. package/dist/toolbox.js.map +0 -1
  82. package/dist/toolbox.mjs.map +0 -1
@@ -0,0 +1,498 @@
1
+ import { AuthAccountMeta, AuthLoginResult, AuthProvider, AuthStatus, AuthSwitchResult, AuthWhoamiResult } from "@serviceme/devtools-protocol";
2
+ //#region src/auth/AccessControl.d.ts
3
+ /** Core-local mirror of `GitHubOrgMembershipCheckResult` (defined in `@serviceme/devtools-shared`). */
4
+ interface CoreOrgMembershipResult {
5
+ status: "active" | "pending" | "not_member" | "unknown";
6
+ httpStatus?: number;
7
+ role?: string;
8
+ directMembership?: boolean;
9
+ }
10
+ /**
11
+ * Upstream org-membership fetcher. CLI / Extension adapters wrap
12
+ * `getGitHubOrgMembership` (or the local extension copy) to match
13
+ * this signature.
14
+ */
15
+ type OrgMembershipFetcher = (token: string, org: string) => Promise<CoreOrgMembershipResult>;
16
+ /** Pluggable key/value store. Extension injects `globalState`-backed impl; CLI injects a file-backed impl. */
17
+ interface KeyValueStore {
18
+ get<T>(key: string): T | undefined;
19
+ update<T>(key: string, value: T): Promise<void>;
20
+ }
21
+ interface AccessCheckResult {
22
+ allowed: boolean;
23
+ reason?: "not_authenticated" | "not_member";
24
+ username?: string;
25
+ }
26
+ interface AccessControlOptions {
27
+ org: string;
28
+ /** Domains that auto-qualify Microsoft users without a GitHub link. */
29
+ microsoftEmailDomains?: readonly string[];
30
+ /** TTL for in-memory membership cache (ms). */
31
+ cacheTtlMs?: number;
32
+ /** TTL for persisted membership cache (ms). */
33
+ persistentCacheTtlMs?: number;
34
+ /** Tokens whose bearer can be supplied to `OrgMembershipFetcher`. */
35
+ tokenFetcher: (provider: AuthProvider) => Promise<string | null>;
36
+ /** Upstream org-membership fetcher (typically `getGitHubOrgMembership` from `@serviceme/devtools-shared`). */
37
+ orgFetcher: OrgMembershipFetcher;
38
+ /** Clock seam for tests. */
39
+ now?: () => number;
40
+ }
41
+ declare class AccessControl {
42
+ private readonly kv;
43
+ private readonly memCache;
44
+ private readonly serverInOrgMem;
45
+ private readonly listeners;
46
+ private readonly opts;
47
+ constructor(kv: KeyValueStore, options: AccessControlOptions);
48
+ /** Subscribe to inOrg changes (used by extension to refresh access-gated UI). */
49
+ onDidChange(listener: () => void): () => void;
50
+ /** Full check: requires authentication + org membership / admin grant. */
51
+ checkAccess(user: AuthAccountMeta | null): Promise<AccessCheckResult>;
52
+ /** Admin: grant access to a GitHub username (bypasses org check). */
53
+ grantAccess(username: string): Promise<void>;
54
+ /** Admin: revoke a previously granted access. */
55
+ revokeAccess(username: string): Promise<void>;
56
+ /** Snapshot of all admin-granted usernames (lowercased). */
57
+ getGrantedUsers(): string[];
58
+ /** Cached membership lookup with both in-memory + persistent layers. */
59
+ checkOrgMembership(username: string): Promise<boolean>;
60
+ /** Server-confirmed inOrg status (set by device claim flow). */
61
+ setServerInOrg(username: string, inOrg: boolean): void;
62
+ /** Inspect server-confirmed inOrg for a username; returns undefined when unknown. */
63
+ getServerInOrg(username: string): boolean | undefined;
64
+ private resolveDecision;
65
+ private updateCache;
66
+ private notifyListeners;
67
+ }
68
+ //#endregion
69
+ //#region src/logger.d.ts
70
+ interface ServiceMeLogger {
71
+ debug(message: string, ...args: unknown[]): void;
72
+ info(message: string, ...args: unknown[]): void;
73
+ warn(message: string, ...args: unknown[]): void;
74
+ error(message: string, ...args: unknown[]): void;
75
+ }
76
+ declare const noopLogger: ServiceMeLogger;
77
+ declare function createConsoleLogger(prefix?: string): ServiceMeLogger;
78
+ //#endregion
79
+ //#region src/auth/AuthStateManager.d.ts
80
+ interface AuthStateManagerOptions {
81
+ /** EventEmitter listener cap; defaults to 32 (Node default) but raised for hot test paths. */
82
+ maxListeners?: number;
83
+ }
84
+ declare class AuthStateManager {
85
+ private readonly emitter;
86
+ private accounts;
87
+ private activeProvider;
88
+ private activeAccountId;
89
+ private lastError;
90
+ constructor(opts?: AuthStateManagerOptions);
91
+ /** Subscribe to state-change events. Returns a disposer. */
92
+ onDidChange(listener: () => void): () => void;
93
+ /** Snapshot of all known accounts (immutable copy). */
94
+ listAccounts(): AuthAccountMeta[];
95
+ /** Find an account by `(provider, accountId)` tuple; returns `null` when absent. */
96
+ findAccount(provider: AuthProvider, accountId: string): AuthAccountMeta | null;
97
+ /** First account for the requested provider — used for "switch to GitHub" UX. */
98
+ findFirstForProvider(provider: AuthProvider): AuthAccountMeta | null;
99
+ /** Insert or update an account entry. New accounts land at the head of the list. */
100
+ upsertAccount(meta: AuthAccountMeta): void;
101
+ /** Remove an account entry. Returns `true` when an entry was removed. */
102
+ removeAccount(provider: AuthProvider, accountId: string): boolean;
103
+ /** Set the active provider. When `accountId` is omitted, picks the first account for that provider. */
104
+ setActive(provider: AuthProvider, accountId?: string): boolean;
105
+ /** Currently active provider — `null` when no session is active. */
106
+ getActiveProvider(): AuthProvider | null;
107
+ /** Currently active account metadata — `null` when none. */
108
+ getActiveAccount(): AuthAccountMeta | null;
109
+ /** True when at least one provider has an account entry. */
110
+ hasAnySession(): boolean;
111
+ /** Snapshot of the state for `auth.status` and bridge serialization. */
112
+ getStatus(): AuthStatus;
113
+ /** Record a non-fatal error from the last login/refresh attempt. */
114
+ recordError(message: string): void;
115
+ /** Clear the recorded error (e.g. after a successful login). */
116
+ clearError(): void;
117
+ /** Drop every account — used by `auth.logout` with no provider. */
118
+ clearAll(): void;
119
+ private fire;
120
+ }
121
+ //#endregion
122
+ //#region src/auth/KeychainAuthTokenStore.d.ts
123
+ /**
124
+ * KeychainAuthTokenStore — abstract adapter for token byte persistence.
125
+ *
126
+ * Per ADL-004 the OAuth token bytes live in one of three places:
127
+ * (a) VSCode `SecretStorage` (Extension process)
128
+ * (b) `@napi-rs/keyring` Entry (CLI process)
129
+ * (c) HTTP request `Authorization` header
130
+ *
131
+ * `AuthCore` MUST NOT call any of these directly. Instead it receives
132
+ * a `KeychainAuthTokenStore` via DI; CLI provides a `@napi-rs/keyring`
133
+ * adapter, Extension provides a `SecretStorage` adapter. This keeps
134
+ * Core free of native-binding concerns and lets the same business
135
+ * logic power both runtimes.
136
+ *
137
+ * Implementations:
138
+ * - CLI: `apps/serviceme-cli/src/.../KeyringTokenStore.ts` (Phase 5.3)
139
+ * - Extension: `apps/extension/src/.../SecretStorageTokenStore.ts` (Phase 5.5)
140
+ *
141
+ * Failure semantics — `get()` returns `null` when no token is stored
142
+ * (cold-start), throws when the underlying keychain is unavailable
143
+ * (rare on Linux without libsecret). Callers should surface the throw
144
+ * as `AUTH_KEYRING_UNAVAILABLE` rather than silently falling back to
145
+ * in-memory storage (per ADL-004 §不变量).
146
+ *
147
+ * Refs:
148
+ * - ADL-004 — CLI 端 Auth Token 存储选型
149
+ * - 4.功能规划.md §2.1 — "Core MUST NOT directly depend on `@napi-rs/keyring`"
150
+ */
151
+ /** Opaque account identifier (provider + upstream user id). */
152
+ interface KeychainAccountKey {
153
+ provider: string;
154
+ accountId: string;
155
+ }
156
+ /** Non-secret metadata returned alongside a `get()` so callers can audit. */
157
+ interface KeychainTokenMetadata {
158
+ provider: string;
159
+ accountId: string;
160
+ expiresAt?: number | null;
161
+ storedAt?: number;
162
+ }
163
+ /**
164
+ * Result envelope — callers receive the token bytes (for immediate use
165
+ * in an HTTP `Authorization` header) plus optional non-secret metadata.
166
+ *
167
+ * IMPORTANT: the `token` field is plain `string` here, not the
168
+ * `SecretToken` brand. The provider -> store -> HTTP-header pipeline
169
+ * runs inside a single trust boundary; crossing that boundary requires
170
+ * `KeychainTokenEnvelope<SecretToken>` and the `auth.tokenRead`
171
+ * capability gate (see ADL-004 §不变量).
172
+ */
173
+ interface KeychainTokenEnvelope {
174
+ token: string;
175
+ metadata: KeychainTokenMetadata;
176
+ }
177
+ /**
178
+ * Abstract token-storage adapter. All methods are async because the
179
+ * keyring / SecretStorage backends are async-by-nature.
180
+ *
181
+ * Thread-safety: implementations MUST be safe for concurrent calls;
182
+ * `AuthCore` will multiplex over multiple providers on the same
183
+ * runtime.
184
+ */
185
+ interface KeychainAuthTokenStore {
186
+ /** Persist token bytes for the given provider + account pair. */
187
+ set(key: KeychainAccountKey, token: string, opts?: {
188
+ expiresAt?: number | null;
189
+ }): Promise<void>;
190
+ /** Fetch the token bytes; returns `null` when none is stored. */
191
+ get(key: KeychainAccountKey): Promise<KeychainTokenEnvelope | null>;
192
+ /** Remove the token entry. Idempotent — removing a missing entry is not an error. */
193
+ delete(key: KeychainAccountKey): Promise<void>;
194
+ /**
195
+ * List all stored token keys (metadata only — never the token bytes).
196
+ * Useful for multi-account enumeration and bridge `auth.status`.
197
+ */
198
+ list(): Promise<KeychainAccountKey[]>;
199
+ /**
200
+ * Health probe — returns `false` when the keychain is unreachable
201
+ * (e.g. Linux without libsecret). Callers SHOULD probe on first
202
+ * use and surface `AUTH_KEYRING_UNAVAILABLE` rather than degrade.
203
+ */
204
+ isAvailable(): Promise<boolean>;
205
+ }
206
+ /**
207
+ * Sentinel error thrown by `KeychainAuthTokenStore.get()` / `.set()`
208
+ * when the underlying keychain is unavailable. Callers map this to
209
+ * `AUTH_KEYRING_UNAVAILABLE` (Phase 5.3 error code).
210
+ */
211
+ declare class KeychainUnavailableError extends Error {
212
+ constructor(message: string, cause?: unknown);
213
+ }
214
+ /**
215
+ * In-memory `KeychainAuthTokenStore` — test/dev fallback. NEVER use
216
+ * in production: tokens live in process memory and disappear on exit.
217
+ * Production wiring is `KeyringTokenStore` (CLI) / `SecretStorageTokenStore`
218
+ * (Extension).
219
+ */
220
+ declare class InMemoryKeychainAuthTokenStore implements KeychainAuthTokenStore {
221
+ private readonly entries;
222
+ private compositeKey;
223
+ set(key: KeychainAccountKey, token: string, opts?: {
224
+ expiresAt?: number | null;
225
+ }): Promise<void>;
226
+ get(key: KeychainAccountKey): Promise<KeychainTokenEnvelope | null>;
227
+ delete(key: KeychainAccountKey): Promise<void>;
228
+ list(): Promise<KeychainAccountKey[]>;
229
+ isAvailable(): Promise<boolean>;
230
+ }
231
+ //#endregion
232
+ //#region src/auth/providers/IAuthProvider.d.ts
233
+ /** Public, non-secret user metadata fetched right after device-flow success. */
234
+ interface IAuthProviderUserInfo {
235
+ id: string;
236
+ login?: string;
237
+ name?: string;
238
+ email?: string | null;
239
+ avatarUrl?: string;
240
+ }
241
+ /**
242
+ * Outcome of `completeDeviceFlow()`. The token is returned ONLY so the
243
+ * caller can immediately persist it via `KeychainAuthTokenStore`; it
244
+ * must not be logged, JSON.stringify'd, or stored on disk by callers.
245
+ */
246
+ interface IAuthProviderSession {
247
+ token: string;
248
+ refreshToken?: string;
249
+ expiresIn?: number;
250
+ user: IAuthProviderUserInfo;
251
+ }
252
+ /**
253
+ * Abstraction for any auth provider that supports OAuth Device Flow
254
+ * (ADL-002). The provider is responsible for:
255
+ * 1. Talking to the upstream `POST <deviceCodeUrl>` to obtain the
256
+ * user-visible code + verification URL.
257
+ * 2. Polling the upstream `POST <tokenUrl>` until the user grants
258
+ * access (or the device code expires).
259
+ * 3. Fetching user metadata so the account is recognizable on the
260
+ * bridge side.
261
+ */
262
+ interface IAuthProvider {
263
+ readonly providerId: AuthProvider;
264
+ /**
265
+ * Step 1: ask the upstream for a fresh device-flow code.
266
+ * Returns the user-visible code, verification URL, and the
267
+ * caller-supplied callback for the polling loop.
268
+ */
269
+ requestDeviceFlow(opts?: {
270
+ scope?: string;
271
+ }): Promise<AuthLoginResult>;
272
+ /**
273
+ * Step 2: poll until the user authorizes (or the code expires).
274
+ * Returns the session including the token bytes — callers MUST
275
+ * immediately hand the token to a `KeychainAuthTokenStore` and
276
+ * discard the returned reference.
277
+ *
278
+ * @param shouldContinue Aborts the poll loop when it returns false
279
+ * (used by callers to wire up Ctrl-C, QuickPick cancel, etc.).
280
+ * @param initialPollIntervalMs The `pollIntervalMs` from the matching
281
+ * `requestDeviceFlow()` result (per the Device Flow spec's `interval`
282
+ * field). Implementations should never poll faster than this — doing
283
+ * so can put the device code into a `slow_down` state that never
284
+ * clears even after the user authorizes.
285
+ */
286
+ completeDeviceFlow(deviceCode: string, shouldContinue?: () => boolean, initialPollIntervalMs?: number): Promise<IAuthProviderSession>;
287
+ /**
288
+ * Refresh an expiring access token. Throws when the provider has no
289
+ * refresh-token grant (GitHub user-to-server tokens, for instance,
290
+ * cannot be refreshed and must be re-issued via device flow).
291
+ */
292
+ refreshAccessToken(refreshToken: string): Promise<IAuthProviderSession>;
293
+ /** Validate a token by hitting the provider's `GET /user`-style endpoint. */
294
+ validateToken(token: string): Promise<boolean>;
295
+ /** Fetch non-secret user metadata (used by `auth.whoami` and `auth.switch`). */
296
+ fetchAccountMeta(token: string): Promise<AuthAccountMeta>;
297
+ }
298
+ //#endregion
299
+ //#region src/auth/ProviderRegistry.d.ts
300
+ declare class ProviderRegistry {
301
+ private readonly providers;
302
+ /** Register or replace a provider implementation. */
303
+ register(provider: IAuthProvider): void;
304
+ /** Look up a registered provider by id; throws when missing. */
305
+ get(providerId: AuthProvider): IAuthProvider;
306
+ /** Non-throwing lookup; returns `undefined` when the provider is unknown. */
307
+ tryGet(providerId: AuthProvider): IAuthProvider | undefined;
308
+ /** Return all registered provider ids — used by `auth.status` and bridge capability hints. */
309
+ list(): AuthProvider[];
310
+ /** True when a provider has been registered for this id. */
311
+ has(providerId: AuthProvider): boolean;
312
+ }
313
+ //#endregion
314
+ //#region src/auth/AuthCore.d.ts
315
+ interface AuthCoreOptions {
316
+ providers: IAuthProvider[];
317
+ tokenStore: KeychainAuthTokenStore;
318
+ accessControl?: AccessControl;
319
+ stateManager?: AuthStateManager;
320
+ /** Diagnostic logger for login/logout lifecycle events (never receives token bytes). */
321
+ logger?: ServiceMeLogger;
322
+ }
323
+ /**
324
+ * Callback invoked once the user finishes the device-flow handshake but
325
+ * BEFORE the token is written to the keychain. Lets the caller display
326
+ * the `userCode` + `verificationUrl` to the user (Phase 5.3 CLI prints to
327
+ * stdout; Phase 5.5 Extension pops a webview notification).
328
+ */
329
+ type DeviceFlowUiCallback = (result: AuthLoginResult) => void | Promise<void>;
330
+ /**
331
+ * Optional cancellation handle — when `shouldContinue()` returns false,
332
+ * the polling loop exits with a clear error so callers can render
333
+ * "Login cancelled" UX.
334
+ */
335
+ type CancellationCheck = () => boolean;
336
+ declare class AuthCore {
337
+ private readonly registry;
338
+ private readonly state;
339
+ private readonly tokenStore;
340
+ private readonly accessControl?;
341
+ private readonly logger;
342
+ constructor(opts: AuthCoreOptions);
343
+ /** Snapshot of every account, the active provider, and the last error. */
344
+ status(): AuthStatus;
345
+ /** List accounts (immutable copy). */
346
+ listAccounts(): AuthAccountMeta[];
347
+ /**
348
+ * Drive the device-flow login for `provider`.
349
+ *
350
+ * Sequence:
351
+ * 1. Ask the provider for the user code + verification URL.
352
+ * 2. Surface the code to the user (via `ui`).
353
+ * 3. Poll until the user authorizes (or `shouldContinue` aborts).
354
+ * 4. Persist the token via `KeychainAuthTokenStore.set()`.
355
+ * 5. Insert the resulting `AuthAccountMeta` into state and mark active.
356
+ */
357
+ login(provider: AuthProvider, ui: DeviceFlowUiCallback, shouldContinue?: CancellationCheck): Promise<AuthLoginResult>;
358
+ /**
359
+ * Complete the device-flow handshake given a pre-fetched user code.
360
+ * Useful when the caller (Phase 5.3 CLI) wants to fetch the code,
361
+ * print the URL, and then poll on a subsequent invocation.
362
+ */
363
+ completeLogin(provider: AuthProvider, deviceCode: string, shouldContinue?: CancellationCheck): Promise<AuthLoginResult>;
364
+ /** Resolve the provider + token for the active session; returns null when no session is active. */
365
+ resolveActiveToken(): Promise<{
366
+ provider: AuthProvider;
367
+ account: AuthAccountMeta;
368
+ token: string;
369
+ } | null>;
370
+ /**
371
+ * Logout: removes the token bytes from the keychain + drops the
372
+ * account entry from state. When `provider` is omitted, clears
373
+ * every account.
374
+ */
375
+ logout(provider?: AuthProvider): Promise<{
376
+ provider: AuthProvider | null;
377
+ success: boolean;
378
+ }>;
379
+ /** Minimal identity for `auth.whoami`. */
380
+ whoami(): Promise<AuthWhoamiResult>;
381
+ /** Switch the active provider. Returns the resulting active account. */
382
+ switchProvider(provider: AuthProvider, accountId?: string): AuthSwitchResult;
383
+ /** Run the access-control check against the active account (optional, requires AccessControl). */
384
+ checkAccess(): Promise<AccessCheckResult | null>;
385
+ /** Expose the state manager for test inspection (not for mutation). */
386
+ getStateManager(): AuthStateManager;
387
+ /** Expose the provider registry for test inspection. */
388
+ getProviderRegistry(): ProviderRegistry;
389
+ /** Expose the access control (or undefined when not configured). */
390
+ getAccessControl(): AccessControl | undefined;
391
+ private persistSession;
392
+ }
393
+ //#endregion
394
+ //#region src/auth/providers/GitHubAuthProvider.d.ts
395
+ /** Tunable provider config — exposed for tests + forks. */
396
+ interface GitHubAuthProviderConfig {
397
+ clientId: string;
398
+ deviceCodeUrl?: string;
399
+ tokenUrl?: string;
400
+ userUrl?: string;
401
+ scope?: string;
402
+ /** Polling interval (ms) floor. The device-flow response's `interval` wins when larger. */
403
+ minPollIntervalMs?: number;
404
+ /**
405
+ * Maximum poll interval after back-off. Must stay generous — GitHub's
406
+ * `slow_down` response requires adding a fixed step to the interval each
407
+ * time it occurs (see `completeDeviceFlow`), and capping this too low
408
+ * prevents the interval from ever satisfying GitHub's actual requirement,
409
+ * causing a permanent `slow_down` loop that never clears even after the
410
+ * user authorizes.
411
+ */
412
+ maxPollIntervalMs?: number;
413
+ /** Fetch override (for tests + DI). */
414
+ fetchImpl?: typeof fetch;
415
+ /** Poll-delay override (for tests + DI). Defaults to a real timer-based sleep. */
416
+ sleepImpl?: (ms: number) => Promise<void>;
417
+ /** Maximum wall-clock time to wait for the user before giving up (ms). Defaults to `expires_in * 1000`. */
418
+ maxWaitMs?: number;
419
+ /** Base delay (ms) before retrying the device-code request after a transient network error. */
420
+ deviceCodeRetryBaseDelayMs?: number;
421
+ /**
422
+ * Diagnostic logger — never receives token bytes or the raw `device_code`,
423
+ * only user-facing codes, HTTP statuses, and poll-loop timing so callers
424
+ * can troubleshoot a stuck / slow device-flow login.
425
+ */
426
+ logger?: ServiceMeLogger;
427
+ }
428
+ declare class GitHubAuthProvider implements IAuthProvider {
429
+ readonly providerId: AuthProvider;
430
+ private readonly cfg;
431
+ private readonly logger;
432
+ private readonly sleepImpl;
433
+ constructor(config: GitHubAuthProviderConfig);
434
+ requestDeviceFlow(opts?: {
435
+ scope?: string;
436
+ }): Promise<AuthLoginResult>;
437
+ completeDeviceFlow(deviceCode: string, shouldContinue?: () => boolean, initialPollIntervalMs?: number): Promise<IAuthProviderSession>;
438
+ refreshAccessToken(refreshToken: string): Promise<IAuthProviderSession>;
439
+ validateToken(token: string): Promise<boolean>;
440
+ fetchAccountMeta(token: string): Promise<AuthAccountMeta>;
441
+ private fetchGitHubUser;
442
+ /**
443
+ * GitHub's `/user` endpoint returns `null` when the user kept their
444
+ * email private. The `/user/emails` endpoint reveals verified emails;
445
+ * we pick the primary one, falling back to the synthetic
446
+ * `<login>@github.local` form so the account is never email-less.
447
+ */
448
+ private resolveEmail;
449
+ }
450
+ //#endregion
451
+ //#region src/auth/providers/MicrosoftAuthProvider.d.ts
452
+ /**
453
+ * Error thrown when callers invoke Microsoft auth from a non-Extension
454
+ * runtime (CLI / Bridge). The CLI maps this to `AUTH_PROVIDER_REQUIRES_HOST`
455
+ * so the user is prompted to retry inside VSCode.
456
+ */
457
+ declare class MicrosoftProviderNotHostedError extends Error {
458
+ constructor(message?: string);
459
+ }
460
+ declare class MicrosoftAuthProvider implements IAuthProvider {
461
+ readonly providerId: AuthProvider;
462
+ requestDeviceFlow(): Promise<AuthLoginResult>;
463
+ completeDeviceFlow(_deviceCode: string, _shouldContinue?: () => boolean): Promise<IAuthProviderSession>;
464
+ refreshAccessToken(_refreshToken: string): Promise<IAuthProviderSession>;
465
+ validateToken(_token: string): Promise<boolean>;
466
+ fetchAccountMeta(_token: string): Promise<AuthAccountMeta>;
467
+ }
468
+ //#endregion
469
+ //#region src/auth/utils/githubUserEmail.d.ts
470
+ /**
471
+ * AuthCore — Pure local utilities for GitHub local email handling.
472
+ *
473
+ * Copied verbatim from `@serviceme/devtools-shared/src/github-user-email.ts` (15 LOC)
474
+ * because ADL-003 forbids Core from depending on `@serviceme/devtools-shared`. These
475
+ * helpers are pure functions with zero side effects, so the duplication is
476
+ * trivial to keep in sync.
477
+ *
478
+ * Refs:
479
+ * - 4.功能规划.md §2.1 — "utils/githubUserEmail.ts 纯函数,直接搬"
480
+ * - ADL-003 — `@serviceme/devtools-shared` boundary decision
481
+ */
482
+ /**
483
+ * Returns true when the supplied address is a synthetic GitHub "local" email
484
+ * (suffixed with `@github.local`). Real GitHub OAuth clients often return
485
+ * `null` for `email` (user kept it private) and the application substitutes
486
+ * `<login>@github.local` to keep the field non-null.
487
+ */
488
+ declare function isGitHubLocalEmail(email: string | null | undefined): boolean;
489
+ /** Build a synthetic `<login>@github.local` address. */
490
+ declare function buildGitHubLocalEmail(login: string): string;
491
+ /**
492
+ * Resolve the user's primary email address — falling back to the synthetic
493
+ * `<login>@github.local` form when the upstream email is missing or blank.
494
+ */
495
+ declare function resolvePrimaryEmail(login: string, email: string | null | undefined): string;
496
+ //#endregion
497
+ export { KeyValueStore as A, AuthStateManagerOptions as C, AccessCheckResult as D, noopLogger as E, AccessControl as O, AuthStateManager as S, createConsoleLogger as T, KeychainAccountKey as _, MicrosoftProviderNotHostedError as a, KeychainTokenMetadata as b, AuthCore as c, DeviceFlowUiCallback as d, ProviderRegistry as f, InMemoryKeychainAuthTokenStore as g, IAuthProviderUserInfo as h, MicrosoftAuthProvider as i, OrgMembershipFetcher as j, AccessControlOptions as k, AuthCoreOptions as l, IAuthProviderSession as m, isGitHubLocalEmail as n, GitHubAuthProvider as o, IAuthProvider as p, resolvePrimaryEmail as r, GitHubAuthProviderConfig as s, buildGitHubLocalEmail as t, CancellationCheck as u, KeychainAuthTokenStore as v, ServiceMeLogger as w, KeychainUnavailableError as x, KeychainTokenEnvelope as y };
498
+ //# sourceMappingURL=index-CoA6y0MP.d.mts.map