dsh-oauth-login 0.2.4

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 (64) hide show
  1. package/INSTALL.md +59 -0
  2. package/INSTALL.zh.md +45 -0
  3. package/LICENSE +201 -0
  4. package/README.en.md +104 -0
  5. package/README.md +104 -0
  6. package/README.zh.md +3 -0
  7. package/SECURITY.md +33 -0
  8. package/cordis.patch.yml +5 -0
  9. package/docs/network-proxy.md +45 -0
  10. package/docs/openrouter-sync.md +84 -0
  11. package/docs/screenshots/01-providers-signed-out.png +0 -0
  12. package/docs/screenshots/03-copilot-signing-in.png +0 -0
  13. package/docs/screenshots/04-mixed-live-states.png +0 -0
  14. package/docs/screenshots/05-copilot-sign-in.gif +0 -0
  15. package/docs/screenshots/06-cli-status-store.png +0 -0
  16. package/lib/bin.d.ts +5 -0
  17. package/lib/bin.js +2132 -0
  18. package/lib/client.js +1915 -0
  19. package/lib/client.js.map +1 -0
  20. package/lib/index.d.ts +482 -0
  21. package/lib/index.js +3105 -0
  22. package/lib/invariant.d.ts +7 -0
  23. package/lib/invariant.js +8 -0
  24. package/package.json +180 -0
  25. package/src/adapter.ts +207 -0
  26. package/src/auth-routes.ts +654 -0
  27. package/src/auth.ts +76 -0
  28. package/src/bin.ts +185 -0
  29. package/src/catalog.ts +129 -0
  30. package/src/client/OpenRouterSyncStatus.tsx +66 -0
  31. package/src/client/PiLoginSettings.tsx +470 -0
  32. package/src/client/ProxySettings.tsx +123 -0
  33. package/src/client/SearchableModelSelect.tsx +595 -0
  34. package/src/client/draft-input.ts +12 -0
  35. package/src/client/index.tsx +71 -0
  36. package/src/client/locales.ts +176 -0
  37. package/src/client/login-input-copy.ts +34 -0
  38. package/src/client/login-window.ts +24 -0
  39. package/src/client/model-filter.ts +45 -0
  40. package/src/client/openrouter-store.ts +122 -0
  41. package/src/client/proxy-draft.ts +57 -0
  42. package/src/extra-models.ts +201 -0
  43. package/src/hosted-capture.ts +41 -0
  44. package/src/hosted-images.ts +154 -0
  45. package/src/http.ts +241 -0
  46. package/src/ids.ts +17 -0
  47. package/src/index.ts +183 -0
  48. package/src/invariant.ts +12 -0
  49. package/src/model-error-hint.ts +98 -0
  50. package/src/native-tools.ts +442 -0
  51. package/src/oauth-refresh.ts +49 -0
  52. package/src/openrouter-catalog.ts +245 -0
  53. package/src/openrouter-free.ts +76 -0
  54. package/src/openrouter-models.ts +155 -0
  55. package/src/openrouter-types.ts +40 -0
  56. package/src/plugin-config.ts +30 -0
  57. package/src/provider.ts +137 -0
  58. package/src/proxy-config.ts +61 -0
  59. package/src/proxy-store.ts +45 -0
  60. package/src/proxy-transport.ts +220 -0
  61. package/src/redact.ts +22 -0
  62. package/src/responses-tap.ts +97 -0
  63. package/src/session.ts +104 -0
  64. package/src/store.ts +234 -0
package/lib/index.d.ts ADDED
@@ -0,0 +1,482 @@
1
+ import { LlmFailure, Message, RetryPolicyConfig, StreamChunk } from "@deepseek-ai/dsh-llm";
2
+ import { Api, AuthInteraction, AuthOperationOptions, Context, Credential, CredentialInfo, CredentialStore, Model, MutableModels, Provider, StreamOptions } from "@earendil-works/pi-ai";
3
+ import { PiAiAdapter } from "@deepseek-ai/dsh-llm-pi-ai";
4
+ import { AsyncLocalStorage } from "node:async_hooks";
5
+ import { EnvHttpProxyAgent } from "undici";
6
+ import z from "@deepseek-ai/schemastery";
7
+ import { Context as Context$1 } from "@deepseek-ai/cordis";
8
+ import { AttachmentStore, ImageAttachmentRef, ImageMediaType, SaveImageAttachment } from "@deepseek-ai/dsh-attachment";
9
+ //#region src/plugin-config.d.ts
10
+ /**
11
+ * `retryPolicy` is executed by shipped `dsh-llm-retry`, not by this plugin.
12
+ * Omission keeps the RC8 official normal default (5 retries for TIMEOUT /
13
+ * TRANSPORT / SERVER / RATE_LIMIT / EMPTY_RESPONSE).
14
+ */
15
+ interface Config {
16
+ streamIdleTimeoutMs?: number;
17
+ retryPolicy?: RetryPolicyConfig;
18
+ /**
19
+ * Hide DSH web_search / web_fetch on OAuth routes that already have hosted
20
+ * search, and attach those hosted tools to the provider request.
21
+ */
22
+ nativeTools?: boolean;
23
+ /** Also attach hosted image generation on Grok and Codex. */
24
+ nativeImage?: boolean;
25
+ }
26
+ declare const Config: z<Config>;
27
+ //#endregion
28
+ //#region src/catalog.d.ts
29
+ /** OAuth subscriptions Pi Agent exposes via /login. Radius is omitted (needs a gateway). */
30
+ interface PiLoginProvider {
31
+ /** pi-ai provider id used by models.login(). */
32
+ readonly id: string;
33
+ /** Harness LLM route. Distinct from catalog routes and from other plugins. */
34
+ readonly route: string;
35
+ /** Credential method this plugin deliberately exposes for this provider. */
36
+ readonly authType: 'oauth' | 'api_key';
37
+ /** Official account page opened before an interactive API-key prompt. */
38
+ readonly loginUrl?: string;
39
+ readonly displayName: string;
40
+ readonly shortName: string;
41
+ readonly blurb: string;
42
+ readonly blurbZh: string;
43
+ /** HTTPS hosts this provider is allowed to open during login. */
44
+ readonly allowedHosts: readonly string[];
45
+ /** Extra allowed host suffixes (leading-dot match). */
46
+ readonly allowedSuffixes: readonly string[];
47
+ readonly preferredModels: readonly string[];
48
+ }
49
+ declare const PI_LOGIN_PROVIDERS: readonly PiLoginProvider[];
50
+ declare function piLoginProvider(id: string): PiLoginProvider | undefined;
51
+ declare function piLoginRoutes(): string[];
52
+ //#endregion
53
+ //#region src/http.d.ts
54
+ type OAuthProxyResolution = {
55
+ source: 'environment';
56
+ } | {
57
+ source: 'explicit' | 'system' | 'loopback';
58
+ proxyUrl: string;
59
+ } | {
60
+ source: 'direct';
61
+ };
62
+ interface OAuthProxyDiscoveryOptions {
63
+ env?: NodeJS.ProcessEnv;
64
+ platform?: NodeJS.Platform;
65
+ readSystemProxy?: () => Promise<string | undefined>;
66
+ probe?: (proxyUrl: string) => Promise<boolean>;
67
+ candidates?: readonly string[];
68
+ }
69
+ //#endregion
70
+ //#region src/proxy-config.d.ts
71
+ interface ProxyChannelSettings {
72
+ /** False means direct, even when proxy environment variables are set. */
73
+ enabled: boolean;
74
+ /** Empty keeps environment/system discovery; otherwise this URL wins. */
75
+ url: string;
76
+ }
77
+ interface ProxySettings {
78
+ http: ProxyChannelSettings;
79
+ websocket: ProxyChannelSettings;
80
+ }
81
+ interface ProxySettingsSnapshot extends ProxySettings {
82
+ revision: number;
83
+ }
84
+ //#endregion
85
+ //#region src/proxy-store.d.ts
86
+ declare class ProxySettingsStore {
87
+ readonly filename: string;
88
+ constructor(filename: string);
89
+ read(): Promise<ProxySettingsSnapshot>;
90
+ save(value: unknown): Promise<ProxySettingsSnapshot>;
91
+ }
92
+ //#endregion
93
+ //#region src/proxy-transport.d.ts
94
+ declare class OAuthProxyTransport {
95
+ private readonly discovery;
96
+ readonly settings: ProxySettingsStore;
97
+ private readyPromise?;
98
+ private readonly generations;
99
+ private readonly sessions;
100
+ private disposed;
101
+ constructor(filename: string, discovery?: OAuthProxyDiscoveryOptions);
102
+ private build;
103
+ private ready;
104
+ initialize(): Promise<OAuthProxyResolution>;
105
+ private acquire;
106
+ save(value: unknown): Promise<ProxySettingsSnapshot>;
107
+ private release;
108
+ run<T>(operation: () => Promise<T>): Promise<T>;
109
+ private beginSession;
110
+ iterate<T>(source: AsyncIterable<T>, codexSessionId?: string): AsyncIterable<T>;
111
+ dispose(): Promise<void>;
112
+ }
113
+ //#endregion
114
+ //#region src/native-tools.d.ts
115
+ interface NativeToolPolicy {
116
+ /** Attach hosted tools and hide DSH web_search / web_fetch. Default true. */
117
+ enabled: boolean;
118
+ /** Also attach hosted image generation where the provider documents it. Default true. */
119
+ image: boolean;
120
+ }
121
+ declare const DEFAULT_NATIVE_TOOL_POLICY: NativeToolPolicy;
122
+ interface NativeToolPlan {
123
+ readonly providerId: string;
124
+ readonly api: string;
125
+ readonly hosted: readonly Record<string, unknown>[];
126
+ readonly guidance: string;
127
+ }
128
+ declare function nativePlan(providerId: string, api: string | undefined, policy?: NativeToolPolicy): NativeToolPlan | undefined;
129
+ declare function nativePlanForRoute(route: string | undefined, api: string | undefined, policy?: NativeToolPolicy): NativeToolPlan | undefined;
130
+ /**
131
+ * xAI's Responses stream currently exposes server-executed X Search details
132
+ * as custom tool calls. The outer `xs_call-*` id distinguishes those traces
133
+ * from a same-named client function, which Harness must still execute.
134
+ */
135
+ declare function isXaiServerXSearchCall(block: unknown): boolean;
136
+ /**
137
+ * Server-executed hosted search / image traces that Harness must not try to run.
138
+ * X Search leaks use `xs_call-*`. DSH `web_search` / `web_fetch` were stripped
139
+ * from this route, so a leftover same-named call is also a leak.
140
+ */
141
+ declare function isHostedServerToolCall(block: unknown): boolean;
142
+ /**
143
+ * xAI hosted search hops arrive as empty `reasoning` blocks whose signature
144
+ * id is `tco_<response>_call-…`. The UI renders each as a blank Think card.
145
+ */
146
+ declare function isHostedSearchReasoningReplay(block: unknown): boolean;
147
+ /**
148
+ * Remove hosted server-side search / image traces after pi-ai 0.82.1 has
149
+ * mistaken them for client function calls. Other blocks retain stream order,
150
+ * actual client tools survive, and pi-ai replay metadata stays index-aligned.
151
+ */
152
+ declare function filterHostedServerToolTraces(source: AsyncIterable<StreamChunk>): AsyncGenerator<StreamChunk>;
153
+ /** @deprecated Use {@link filterHostedServerToolTraces}. */
154
+ declare const filterXaiServerToolTraces: typeof filterHostedServerToolTraces;
155
+ declare function applyNativeToolsToPayload(payload: unknown, providerId: string, api: string | undefined, policy?: NativeToolPolicy): unknown;
156
+ /**
157
+ * Prepare one provider request as a single unit.
158
+ *
159
+ * Native tools are a property of this request, not of the provider account.
160
+ * A context without tools is a text-only call (reviewers, summaries, titles,
161
+ * and similar utility traffic), so its payload hook must stay untouched even
162
+ * when the provider serializer later emits `tools: []`.
163
+ */
164
+ declare function prepareNativeToolRequest<TOptions extends StreamOptions>(context: Context, options: TOptions, providerId: string, api: string | undefined, policy?: NativeToolPolicy): {
165
+ context: Context;
166
+ options: TOptions & StreamOptions;
167
+ };
168
+ //#endregion
169
+ //#region src/store.d.ts
170
+ declare function piLoginAuthPath(dshHome?: string): string;
171
+ declare class PiLoginCredentialStore implements CredentialStore {
172
+ readonly filename: string;
173
+ readonly legacyFilename: string | undefined;
174
+ constructor(filename?: string);
175
+ private readDocument;
176
+ read(providerId: string, options?: AuthOperationOptions): Promise<Credential | undefined>;
177
+ list(options?: AuthOperationOptions): Promise<readonly CredentialInfo[]>;
178
+ modify(providerId: string, fn: (current: Credential | undefined) => Promise<Credential | undefined>, options?: AuthOperationOptions): Promise<Credential | undefined>;
179
+ delete(providerId: string, options?: AuthOperationOptions): Promise<void>;
180
+ }
181
+ //#endregion
182
+ //#region src/openrouter-types.d.ts
183
+ interface OpenRouterModel {
184
+ id: string;
185
+ name: string;
186
+ contextWindow: number;
187
+ maxTokens: number;
188
+ inputModalities: string[];
189
+ outputModalities: string[];
190
+ supportedParameters: string[];
191
+ tools: boolean;
192
+ reasoning: boolean;
193
+ reasoningMandatory: boolean;
194
+ supportedEfforts?: string[];
195
+ defaultEffort?: string;
196
+ /** USD per token/unit as supplied by the official catalog, not pi-ai costs. */
197
+ pricing: Record<string, string>;
198
+ priceStatus: 'free' | 'paid' | 'unknown';
199
+ /** Endpoint deprecation, NEVER interpreted as a promotion deadline. */
200
+ deprecatesAt?: string;
201
+ }
202
+ interface OpenRouterCatalogSnapshot {
203
+ version: 1;
204
+ connected: boolean;
205
+ refreshing: boolean;
206
+ source: 'builtin' | 'cache' | 'live';
207
+ lastUpdatedAt: number | null;
208
+ lastAttemptAt: number | null;
209
+ nextRefreshAt: number | null;
210
+ retryAt: number | null;
211
+ stale: boolean;
212
+ error: 'fetch' | 'cache' | 'save' | null;
213
+ models: Array<OpenRouterModel & {
214
+ freeOnly: boolean;
215
+ }>;
216
+ }
217
+ //#endregion
218
+ //#region src/openrouter-catalog.d.ts
219
+ interface OpenRouterCatalogOptions {
220
+ filename: string;
221
+ isAuthenticated: () => Promise<boolean>;
222
+ beforeFetch?: () => Promise<unknown>;
223
+ fetch?: typeof globalThis.fetch;
224
+ now?: () => number;
225
+ /** Protect zero-cost legacy selections too, without labelling them free. */
226
+ initiallyProtectedIds?: readonly string[];
227
+ }
228
+ declare class OpenRouterCatalog {
229
+ private readonly options;
230
+ private entries;
231
+ private protectedIds;
232
+ private connected;
233
+ private disposed;
234
+ private source;
235
+ private lastUpdatedAt;
236
+ private lastAttemptAt;
237
+ private nextRefreshAt;
238
+ private error;
239
+ private hydration;
240
+ private pending;
241
+ private controller;
242
+ private timer;
243
+ private generation;
244
+ private readonly listeners;
245
+ private readonly now;
246
+ constructor(options: OpenRouterCatalogOptions);
247
+ models(): readonly OpenRouterModel[] | undefined;
248
+ model(id: string): OpenRouterModel | undefined;
249
+ protects(id: string): boolean;
250
+ subscribe(listener: () => void): () => void;
251
+ private changed;
252
+ snapshot(): OpenRouterCatalogSnapshot;
253
+ private hydrate;
254
+ private readCache;
255
+ private rememberFree;
256
+ /** Startup reads disk first; only a newly completed login forces a refresh. */
257
+ syncAuthentication(reason?: 'check' | 'login'): Promise<void>;
258
+ /** Coalesced across routes/windows; even forced refreshes honor 60s cooldown. */
259
+ refresh(force?: boolean): Promise<void>;
260
+ private fetchCatalog;
261
+ private schedule;
262
+ disconnect(): void;
263
+ dispose(): void;
264
+ }
265
+ //#endregion
266
+ //#region src/session.d.ts
267
+ declare class PiLoginSession {
268
+ readonly store: PiLoginCredentialStore;
269
+ readonly models: MutableModels;
270
+ readonly native: NativeToolPolicy;
271
+ readonly openRouter: OpenRouterCatalog;
272
+ readonly proxy: OAuthProxyTransport;
273
+ constructor(store?: PiLoginCredentialStore, native?: NativeToolPolicy, catalogOptions?: Partial<Pick<OpenRouterCatalogOptions, 'fetch' | 'now' | 'filename'>>, proxyDiscovery?: OAuthProxyDiscoveryOptions);
274
+ ensureTransport(): Promise<OAuthProxyResolution>;
275
+ spec(id: string): PiLoginProvider;
276
+ provider(id: string): import("@earendil-works/pi-ai").Provider<import("@earendil-works/pi-ai").Api>;
277
+ visibleModels(id: string): readonly import("@earendil-works/pi-ai").Model<import("@earendil-works/pi-ai").Api>[];
278
+ /**
279
+ * Harness routes that currently hold a stored OAuth grant.
280
+ * Model pickers should only advertise these — logging out must drop the route.
281
+ */
282
+ authenticatedRoutes(): Promise<string[]>;
283
+ logout(id: string): Promise<void>;
284
+ /**
285
+ * Renew access tokens that are expired or close to expiry.
286
+ * Failures stay in the store; the next poll or chat retries.
287
+ */
288
+ refreshStoredGrants(now?: number): Promise<void>;
289
+ }
290
+ //#endregion
291
+ //#region src/adapter.d.ts
292
+ interface PiLoginAdapterOptions {
293
+ streamIdleTimeoutMs?: number;
294
+ retryPolicy?: RetryPolicyConfig;
295
+ }
296
+ declare function createPiLoginAdapter(session: PiLoginSession, resolveAttachments: () => AttachmentStore | undefined, options?: PiLoginAdapterOptions): PiAiAdapter;
297
+ //#endregion
298
+ //#region src/auth.d.ts
299
+ interface PiLoginAuthStatus {
300
+ providerId: string;
301
+ authenticated: boolean;
302
+ credentialType?: 'oauth' | 'api_key';
303
+ expiresAt?: Date;
304
+ }
305
+ declare function loginPiProvider(providerId: string, interaction: AuthInteraction, store?: PiLoginCredentialStore): Promise<void>;
306
+ declare function logoutPiProvider(providerId: string, store?: PiLoginCredentialStore): Promise<void>;
307
+ declare function piLoginStatus(store?: PiLoginCredentialStore, providerId?: string): Promise<PiLoginAuthStatus[]>;
308
+ declare function loginPiProviderSession(providerId: string, interaction: AuthInteraction, session: PiLoginSession): Promise<void>;
309
+ //#endregion
310
+ //#region src/auth-routes.d.ts
311
+ declare const PI_LOGIN_AUTH_STATUS_PATH = "/plugins/dsh-oauth-login/auth/status";
312
+ declare const PI_LOGIN_AUTH_LOGIN_PATH = "/plugins/dsh-oauth-login/auth/login";
313
+ declare const PI_LOGIN_AUTH_CANCEL_PATH = "/plugins/dsh-oauth-login/auth/cancel";
314
+ declare const PI_LOGIN_AUTH_COMPLETE_PATH = "/plugins/dsh-oauth-login/auth/complete";
315
+ declare const PI_LOGIN_AUTH_LOGOUT_PATH = "/plugins/dsh-oauth-login/auth/logout";
316
+ interface LoginInputChallenge {
317
+ type: 'secret' | 'text' | 'manual_code';
318
+ message: string;
319
+ placeholder?: string;
320
+ }
321
+ type PiLoginAccountState = {
322
+ status: 'signed-out';
323
+ } | {
324
+ status: 'signing-in';
325
+ kind?: 'browser' | 'input';
326
+ url?: string;
327
+ userCode?: string;
328
+ input?: LoginInputChallenge;
329
+ } | {
330
+ status: 'signed-in';
331
+ models: string[];
332
+ expiresAt?: string;
333
+ } | {
334
+ status: 'error';
335
+ message: string;
336
+ };
337
+ interface PiLoginProviderStatus {
338
+ id: string;
339
+ route: string;
340
+ displayName: string;
341
+ shortName: string;
342
+ authType: PiLoginProvider['authType'];
343
+ account: PiLoginAccountState;
344
+ }
345
+ interface LoginChallenge {
346
+ provider: string;
347
+ kind: 'browser' | 'input';
348
+ url?: string;
349
+ userCode?: string;
350
+ input?: LoginInputChallenge;
351
+ }
352
+ interface PiLoginAuthRouteOptions {
353
+ /** Called after a successful sign-in or sign-out so the host can refresh LLM routes. */
354
+ onAuthChanged?: () => void | Promise<void>;
355
+ }
356
+ declare function registerPiLoginAuthRoutes(ctx: Context$1, session: PiLoginSession, options?: PiLoginAuthRouteOptions): void;
357
+ //#endregion
358
+ //#region src/extra-models.d.ts
359
+ declare const GLM_5_3_DEFAULT_EFFORT = "max";
360
+ declare const GLM_5_3_FLASH_DEFAULT_EFFORT = "max";
361
+ /** OpenRouter stealth model missing from the installed pi-ai catalog (0.82.x–0.84.x). */
362
+ declare const OX_ALPHA_MODEL_ID = "stealth/ox-alpha";
363
+ /**
364
+ * OpenRouter's live default for ox-alpha (`reasoning.default_effort`).
365
+ * Must be sent explicitly: pi-ai's OpenRouter dialect writes
366
+ * `reasoning: { effort: thinkingLevelMap.off ?? "none" }` when the caller
367
+ * omits an effort, and ox-alpha rejects `none` (`reasoning.mandatory: true`).
368
+ */
369
+ declare const OX_ALPHA_DEFAULT_EFFORT = "max";
370
+ /** Per-model default the selector and request path should apply when omitted. */
371
+ declare function defaultReasoningEffortFor(modelId: string): typeof OX_ALPHA_DEFAULT_EFFORT | typeof GLM_5_3_DEFAULT_EFFORT | typeof GLM_5_3_FLASH_DEFAULT_EFFORT | 'medium' | undefined;
372
+ /**
373
+ * Extra models this plugin publishes for one pi-ai provider id.
374
+ * @param providerId - catalog provider id (e.g. `xai`), not the harness route.
375
+ */
376
+ declare function extraModelsFor(providerId: string): readonly Model<Api>[];
377
+ //#endregion
378
+ //#region src/hosted-capture.d.ts
379
+ interface HostedImage {
380
+ id?: string;
381
+ base64: string;
382
+ }
383
+ interface HostedCapture {
384
+ images: HostedImage[];
385
+ }
386
+ //#endregion
387
+ //#region src/hosted-images.d.ts
388
+ declare function sniffImageMediaType(bytes: Uint8Array): ImageMediaType | undefined;
389
+ declare function collectHostedImagesFromEvent(event: unknown, into: HostedImage[]): void;
390
+ declare function decodeHostedImage(base64: string): {
391
+ data: Uint8Array;
392
+ mediaType: ImageMediaType;
393
+ } | undefined;
394
+ /**
395
+ * pi-ai replay cannot represent assistant ImageBlocks. Drop them before the
396
+ * next request so replay metadata still lines up with remaining content.
397
+ */
398
+ declare function stripAssistantImages(messages: readonly Message[]): Message[];
399
+ declare function injectHostedImages(source: AsyncIterable<StreamChunk>, capture: HostedCapture, save: (input: SaveImageAttachment) => Promise<ImageAttachmentRef>): AsyncGenerator<StreamChunk>;
400
+ //#endregion
401
+ //#region src/oauth-refresh.d.ts
402
+ /**
403
+ * When to spend a refresh_token. Chat already refreshes via Models.getAuth;
404
+ * this helper is for status / boot / the host timer so the store does not sit
405
+ * on a stale expires stamp.
406
+ */
407
+ /** Refresh when the stored access stamp is inside this window (Pi already skews expires by 5 min). */
408
+ declare const OAUTH_REFRESH_SOON_MS: number;
409
+ /** Host timer. Access lives ~6h; this is just how often we look. */
410
+ declare const OAUTH_REFRESH_POLL_MS: number;
411
+ declare function grantNeedsRefresh(expires: number, now?: number): boolean;
412
+ //#endregion
413
+ //#region src/ids.d.ts
414
+ /** Basename of the DSH-owned multi-provider OAuth document. */
415
+ declare const PI_LOGIN_AUTH_FILENAME = ".dsh-oauth-auth.json";
416
+ /** Legacy DSH filename accepted during the one-time storage migration. */
417
+ declare const LEGACY_PI_LOGIN_AUTH_FILENAME = ".pi-login-auth.json";
418
+ /** Prefix for harness routes so they never collide with catalog / other plugins. */
419
+ declare const PI_LOGIN_ROUTE_PREFIX = "pi-";
420
+ /** Provider idle ceiling used by every composite route. */
421
+ declare const PI_LOGIN_STREAM_IDLE_TIMEOUT_MS = 300000;
422
+ /** Startup line `dshx verify` looks for. */
423
+ declare const PI_LOGIN_BOOT_MARKER = "[my-plugins/dsh-oauth-login] loaded";
424
+ //#endregion
425
+ //#region src/model-error-hint.d.ts
426
+ /**
427
+ * Default Harness `retryPolicy` codes. Keep aligned with
428
+ * `resolveRetryPolicy(undefined)` in `@deepseek-ai/dsh-llm`.
429
+ */
430
+ declare const TRANSIENT_MODEL_CODES: readonly string[];
431
+ declare const QUOTA_HINT = "This is account quota or credits, not a temporary busy signal. Automatic retry will not refill it. Check the plan, usage window, or balance.";
432
+ declare const RATE_LIMIT_HINT = "This is a request-rate or peak-busy limit. A 429 is often this, not an empty balance. After automatic retries end, wait and send another message. If Continue fails or the composer stays stuck, start a new chat.";
433
+ declare const TRANSIENT_HINT = "After this turn ends, send another message to try again. If Continue fails or the composer stays stuck, start a new chat.";
434
+ /** Stable Chat copy for one official `LlmError` code. Does not invent 5h vs weekly vs billing. */
435
+ declare function hintForCode(code: string): string | undefined;
436
+ /** Normalize known provider gaps before the official retry executor receives this failure. */
437
+ declare function hintFailure(failure: LlmFailure, provider?: string): LlmFailure;
438
+ /** Apply the same provider correction and hint to thrown failures, preserving diagnostics. */
439
+ declare function withModelErrorHint(error: unknown, provider?: string): unknown;
440
+ //#endregion
441
+ //#region src/provider.d.ts
442
+ declare function catalogProvider(id: string): Provider;
443
+ declare function harnessModels(spec: PiLoginProvider, catalog?: OpenRouterCatalog): Model<Api>[];
444
+ declare function preferredModel(spec: PiLoginProvider, models?: readonly {
445
+ id: string;
446
+ }[]): string;
447
+ declare function harnessProvider(spec: PiLoginProvider, native?: NativeToolPolicy, catalog?: OpenRouterCatalog): Provider;
448
+ //#endregion
449
+ //#region src/redact.d.ts
450
+ /** Remove token-like strings from an external OAuth diagnostic. */
451
+ declare function safeMessage(error: unknown): string;
452
+ /** Only this provider's official HTTPS hosts may be opened for login. */
453
+ declare function isSafeAuthUrl(raw: string, provider: PiLoginProvider): boolean;
454
+ //#endregion
455
+ //#region src/index.d.ts
456
+ type NativeAssembly = {
457
+ tools: {
458
+ name: string;
459
+ }[];
460
+ sections: {
461
+ name: string;
462
+ text: string;
463
+ }[];
464
+ };
465
+ type NativeAssembleContext = {
466
+ agent?: {
467
+ options?: {
468
+ provider?: string;
469
+ model?: string;
470
+ };
471
+ };
472
+ };
473
+ declare module '@deepseek-ai/cordis' {
474
+ interface Events {
475
+ 'system-prompt/assemble'(assembly: NativeAssembly, context: NativeAssembleContext, next: () => Promise<NativeAssembly>): Promise<NativeAssembly>;
476
+ }
477
+ }
478
+ declare const name = "llm-oauth-login";
479
+ declare const inject: string[];
480
+ declare function apply(ctx: Context$1, config: Config): void;
481
+ //#endregion
482
+ export { Config, type Config as PluginConfig, DEFAULT_NATIVE_TOOL_POLICY, LEGACY_PI_LOGIN_AUTH_FILENAME, type LoginChallenge, type LoginInputChallenge, type NativeToolPlan, type NativeToolPolicy, OAUTH_REFRESH_POLL_MS, OAUTH_REFRESH_SOON_MS, OX_ALPHA_DEFAULT_EFFORT, OX_ALPHA_MODEL_ID, PI_LOGIN_AUTH_CANCEL_PATH, PI_LOGIN_AUTH_COMPLETE_PATH, PI_LOGIN_AUTH_FILENAME, PI_LOGIN_AUTH_LOGIN_PATH, PI_LOGIN_AUTH_LOGOUT_PATH, PI_LOGIN_AUTH_STATUS_PATH, PI_LOGIN_BOOT_MARKER, PI_LOGIN_PROVIDERS, PI_LOGIN_ROUTE_PREFIX, PI_LOGIN_STREAM_IDLE_TIMEOUT_MS, type PiLoginAdapterOptions, type PiLoginAuthStatus, PiLoginCredentialStore, type PiLoginProvider, type PiLoginProviderStatus, PiLoginSession, QUOTA_HINT, RATE_LIMIT_HINT, TRANSIENT_HINT, TRANSIENT_MODEL_CODES, apply, applyNativeToolsToPayload, catalogProvider, collectHostedImagesFromEvent, createPiLoginAdapter, decodeHostedImage, defaultReasoningEffortFor, extraModelsFor, filterHostedServerToolTraces, filterXaiServerToolTraces, grantNeedsRefresh, harnessModels, harnessProvider, hintFailure, hintForCode, inject, injectHostedImages, isHostedSearchReasoningReplay, isHostedServerToolCall, isSafeAuthUrl, isXaiServerXSearchCall, loginPiProvider, loginPiProviderSession, logoutPiProvider, name, nativePlan, nativePlanForRoute, piLoginAuthPath, piLoginProvider, piLoginRoutes, piLoginStatus, preferredModel, prepareNativeToolRequest, registerPiLoginAuthRoutes, safeMessage, sniffImageMediaType, stripAssistantImages, withModelErrorHint };