dsh-qoder-connect 0.2.6 → 0.2.8
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/README.en.md +33 -8
- package/README.md +33 -8
- package/assets/3.png +0 -0
- package/assets/5.png +0 -0
- package/assets/6.png +0 -0
- package/assets/7.png +0 -0
- package/assets/8.png +0 -0
- package/lib/bin.js +109 -13
- package/lib/client.js +301 -117
- package/lib/index.d.ts +152 -22
- package/lib/index.js +369 -398
- package/lib/{variants-COxX6r1j.js → variants-Dl1AbWre.js} +474 -51
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -87,26 +87,56 @@ declare const QODER_GLOBAL_AUTH_PATH = "/plugins/dsh-qoder-connect/global/auth";
|
|
|
87
87
|
* One action the PAT route accepts.
|
|
88
88
|
*
|
|
89
89
|
* `save-pat` validates the pasted token against the variant's region and, only
|
|
90
|
-
* on success,
|
|
91
|
-
*
|
|
90
|
+
* on success, appends it to the saved list and makes it active; `activate`
|
|
91
|
+
* switches to another saved entry; `remove` deletes one saved entry; `clear`
|
|
92
|
+
* removes every saved credential. There is no device flow and no credential
|
|
93
|
+
* import: the token is the whole auth surface.
|
|
94
|
+
*
|
|
95
|
+
* All of these are writes — `activate` changes which account signs later
|
|
96
|
+
* requests — so the route requires the in-process key even for the two that do
|
|
97
|
+
* not touch a token's bytes.
|
|
92
98
|
*/
|
|
93
|
-
type QoderAuthAction = 'save-pat' | 'clear';
|
|
99
|
+
type QoderAuthAction = 'save-pat' | 'activate' | 'remove' | 'clear';
|
|
94
100
|
/** Request body accepted by the PAT route. */
|
|
95
101
|
interface QoderAuthRequest {
|
|
96
102
|
action: QoderAuthAction;
|
|
97
103
|
/** The token to validate and store; required for `save-pat`. */
|
|
98
104
|
pat?: string;
|
|
105
|
+
/** Optional display label for a saved entry; `save-pat` only. */
|
|
106
|
+
label?: string;
|
|
107
|
+
/** Target saved entry; required for `activate` and `remove`. */
|
|
108
|
+
id?: string;
|
|
99
109
|
}
|
|
100
110
|
/** Where the credential in effect came from. */
|
|
101
111
|
type QoderCredentialSource = 'card' | 'env' | 'cli';
|
|
102
112
|
/**
|
|
103
|
-
*
|
|
113
|
+
* One saved PAT, redacted for the switch select.
|
|
114
|
+
*
|
|
115
|
+
* Never the token itself: the id is a one-way hash prefix, the label is
|
|
116
|
+
* display copy, and the tail is the last four characters — enough to tell two
|
|
117
|
+
* saved tokens apart, not enough to misuse one.
|
|
118
|
+
*/
|
|
119
|
+
interface QoderPatProfile {
|
|
120
|
+
id: string;
|
|
121
|
+
/** Optional display label supplied when the token was saved. */
|
|
122
|
+
label?: string;
|
|
123
|
+
/** Last four characters of the token. */
|
|
124
|
+
patTail?: string;
|
|
125
|
+
/** When this token was saved, epoch milliseconds. */
|
|
126
|
+
savedAtMs?: number;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Redacted summary of one variant's active PAT.
|
|
104
130
|
*
|
|
105
131
|
* Never the token itself: the browser half displays where the credential came
|
|
106
132
|
* from, when it was saved, and the last four characters — enough to tell two
|
|
107
133
|
* tokens apart, not enough to misuse one.
|
|
108
134
|
*/
|
|
109
135
|
interface QoderPatSummary {
|
|
136
|
+
/** Local id of the saved entry in effect; absent for the environment token. */
|
|
137
|
+
id?: string;
|
|
138
|
+
/** Display label of the saved entry in effect, when it carries one. */
|
|
139
|
+
label?: string;
|
|
110
140
|
source: QoderCredentialSource;
|
|
111
141
|
/** When the stored token was saved, epoch milliseconds; absent for env fallback. */
|
|
112
142
|
savedAtMs?: number;
|
|
@@ -255,6 +285,16 @@ type QoderWebStatus = {
|
|
|
255
285
|
region?: QoderRegion;
|
|
256
286
|
/** Redacted summary of the PAT in effect. */
|
|
257
287
|
pat?: QoderPatSummary;
|
|
288
|
+
/**
|
|
289
|
+
* Every saved token for this variant, newest first, redacted.
|
|
290
|
+
*
|
|
291
|
+
* One entry means the card has nothing to switch; two or more render the
|
|
292
|
+
* account select. The list is variant-scoped, like the credential file
|
|
293
|
+
* itself: a token minted for one region is never offered to the other.
|
|
294
|
+
*/
|
|
295
|
+
patProfiles?: readonly QoderPatProfile[];
|
|
296
|
+
/** The saved entry in effect; absent when the token comes from the environment. */
|
|
297
|
+
activePatId?: string;
|
|
258
298
|
credits?: QoderWebCredits;
|
|
259
299
|
creditsError?: string;
|
|
260
300
|
/** The models the plugin serves, as catalog snapshots. */
|
|
@@ -388,12 +428,27 @@ declare const QODER_AUTH_FILENAME = ".qoder-auth.json";
|
|
|
388
428
|
interface AuthLogger {
|
|
389
429
|
warn?(...args: unknown[]): void;
|
|
390
430
|
}
|
|
431
|
+
/** One saved credential, as the file stores it. */
|
|
432
|
+
interface QoderCredentialEntry {
|
|
433
|
+
/** Stable local id (a one-way hash prefix of the token). */
|
|
434
|
+
id: string;
|
|
435
|
+
pat: string;
|
|
436
|
+
region: QoderRegion;
|
|
437
|
+
/** When the stored token was saved, epoch milliseconds. */
|
|
438
|
+
savedAtMs?: number;
|
|
439
|
+
/** Optional display label; never sent upstream. */
|
|
440
|
+
label?: string;
|
|
441
|
+
}
|
|
391
442
|
/** Runtime credential, timestamps in epoch milliseconds. */
|
|
392
443
|
interface QoderCredential {
|
|
444
|
+
/** Local id of the saved entry; absent for an environment token. */
|
|
445
|
+
id?: string;
|
|
393
446
|
pat: string;
|
|
394
447
|
region: QoderRegion;
|
|
395
448
|
/** When the stored token was saved; absent for environment-sourced tokens. */
|
|
396
449
|
savedAtMs?: number;
|
|
450
|
+
/** Display label, when the saved entry carries one. */
|
|
451
|
+
label?: string;
|
|
397
452
|
source: QoderCredentialSource;
|
|
398
453
|
}
|
|
399
454
|
/** Read-only sign-in summary for status, the PAT route, and doctor output. */
|
|
@@ -407,6 +462,10 @@ interface QoderAuthStatus {
|
|
|
407
462
|
reason?: string;
|
|
408
463
|
/** Absolute path of the credential file this store owns. */
|
|
409
464
|
filePath: string;
|
|
465
|
+
/** Every saved token for this variant, newest first, redacted. */
|
|
466
|
+
profiles?: readonly QoderPatProfile[];
|
|
467
|
+
/** The entry id in effect, when a saved entry is active. */
|
|
468
|
+
activeId?: string;
|
|
410
469
|
}
|
|
411
470
|
/** Constructor options. */
|
|
412
471
|
interface QoderStoreOptions {
|
|
@@ -418,13 +477,21 @@ interface QoderStoreOptions {
|
|
|
418
477
|
}
|
|
419
478
|
/** Last four characters of a token, for display. */
|
|
420
479
|
declare function patTail(pat: string): string | undefined;
|
|
480
|
+
/**
|
|
481
|
+
* Stable local id for one token.
|
|
482
|
+
*
|
|
483
|
+
* A PAT is a bearer secret, so the id is a one-way hash prefix rather than
|
|
484
|
+
* any suffix of it: surfaces that show the id (the select, status documents,
|
|
485
|
+
* logs) leak nothing usable, while two saves of the same token still resolve
|
|
486
|
+
* to the same entry.
|
|
487
|
+
*/
|
|
488
|
+
declare function qoderCredentialId(pat: string): string;
|
|
421
489
|
/**
|
|
422
490
|
* Stable identity key for a credential, used by probe records and saved
|
|
423
491
|
* catalogs.
|
|
424
492
|
*
|
|
425
|
-
*
|
|
426
|
-
*
|
|
427
|
-
* nothing usable, while two reads of the same token still correlate locally.
|
|
493
|
+
* Deliberately wider than the local id: these keys address stored data, not
|
|
494
|
+
* UI, and 16 hex characters keep two tokens from ever sharing a bucket.
|
|
428
495
|
*/
|
|
429
496
|
declare function qoderCredentialIdentity(credential: Pick<QoderCredential, 'pat'>): string;
|
|
430
497
|
declare class QoderCredentialStore {
|
|
@@ -439,10 +506,11 @@ declare class QoderCredentialStore {
|
|
|
439
506
|
/**
|
|
440
507
|
* The credential currently in effect, or `undefined` when there is none.
|
|
441
508
|
*
|
|
442
|
-
* Resolution order: the
|
|
443
|
-
*
|
|
444
|
-
*
|
|
445
|
-
* lives until
|
|
509
|
+
* Resolution order: the active saved entry (or the first one when the
|
|
510
|
+
* pointer is stale), then the arm's environment variable (only when no
|
|
511
|
+
* saved entry exists — a saved token always wins over a stray env), then
|
|
512
|
+
* nothing. There is no refresh and no expiry check: a PAT lives until
|
|
513
|
+
* revoked.
|
|
446
514
|
*/
|
|
447
515
|
current(): Promise<QoderCredential | undefined>;
|
|
448
516
|
/**
|
|
@@ -455,12 +523,48 @@ declare class QoderCredentialStore {
|
|
|
455
523
|
resolve(): Promise<QoderCredential>;
|
|
456
524
|
/** The token in effect as a bare string, rejecting when there is none. */
|
|
457
525
|
patPromise(): Promise<string>;
|
|
526
|
+
/** Every saved entry (tokens included; host-side callers only). */
|
|
527
|
+
entries(): Promise<readonly QoderCredentialEntry[]>;
|
|
528
|
+
/**
|
|
529
|
+
* Add a token and make it active.
|
|
530
|
+
*
|
|
531
|
+
* Re-saving an existing token updates that entry (its saved time, and its
|
|
532
|
+
* label when one is supplied) instead of appending a duplicate — the id is
|
|
533
|
+
* derived from the token, so "same PAT" is the same entry by construction.
|
|
534
|
+
* The caller is responsible for having validated the token against the
|
|
535
|
+
* region first (`validateApiKey` upstream).
|
|
536
|
+
*
|
|
537
|
+
* @param pat - the token to store.
|
|
538
|
+
* @param label - optional display label for the select row.
|
|
539
|
+
* @returns the stored entry.
|
|
540
|
+
*/
|
|
541
|
+
add(pat: string, label?: string): Promise<QoderCredentialEntry>;
|
|
458
542
|
/**
|
|
459
|
-
*
|
|
460
|
-
*
|
|
543
|
+
* Make one saved entry active.
|
|
544
|
+
*
|
|
545
|
+
* @param id - the entry id.
|
|
546
|
+
* @returns the activated entry, or `undefined` when no entry has that id.
|
|
547
|
+
*/
|
|
548
|
+
activate(id: string): Promise<QoderCredentialEntry | undefined>;
|
|
549
|
+
/**
|
|
550
|
+
* Remove one saved entry.
|
|
551
|
+
*
|
|
552
|
+
* The active pointer moves to the first remaining entry; removing the last
|
|
553
|
+
* entry deletes the file, exactly like {@link clear} — a saved token is the
|
|
554
|
+
* only thing that shadows the environment fallback.
|
|
555
|
+
*
|
|
556
|
+
* @param id - the entry id.
|
|
557
|
+
* @returns the removed entry, or `undefined` when no entry has that id.
|
|
558
|
+
*/
|
|
559
|
+
remove(id: string): Promise<QoderCredentialEntry | undefined>;
|
|
560
|
+
/**
|
|
561
|
+
* Persist a token for this variant and make it active.
|
|
562
|
+
*
|
|
563
|
+
* Kept for the CLI and older call sites: it is {@link add} behind the
|
|
564
|
+
* runtime-credential shape they expect.
|
|
461
565
|
*/
|
|
462
566
|
save(pat: string, source?: QoderCredentialSource): Promise<QoderCredential>;
|
|
463
|
-
/** Remove
|
|
567
|
+
/** Remove every stored credential. A missing file is not an error. */
|
|
464
568
|
clear(): Promise<void>;
|
|
465
569
|
/** Alias kept for call-site readability (`logout` is just clearing). */
|
|
466
570
|
logout(): Promise<void>;
|
|
@@ -470,7 +574,7 @@ declare class QoderCredentialStore {
|
|
|
470
574
|
private pendingLegacyReason;
|
|
471
575
|
private fromEnvironment;
|
|
472
576
|
private readOwn;
|
|
473
|
-
private
|
|
577
|
+
private writeDocument;
|
|
474
578
|
}
|
|
475
579
|
/**
|
|
476
580
|
* The plugin-owned credential path for one variant's default filename.
|
|
@@ -850,6 +954,18 @@ type QoderChatResult = {
|
|
|
850
954
|
status: number;
|
|
851
955
|
kind: UpstreamErrorKind;
|
|
852
956
|
message: string;
|
|
957
|
+
/**
|
|
958
|
+
* The upstream's own "try again in N ms" answer (Qoder's queue body carries
|
|
959
|
+
* `retryAfterSeconds`, and a plain 429 may carry `Retry-After`).
|
|
960
|
+
*
|
|
961
|
+
* It has to survive this layer to be usable: the shim turns it into the
|
|
962
|
+
* `Retry-After` header and the `[retry-after=<n>s]` message tag, and the
|
|
963
|
+
* adapter reads that tag back into `failure.providerRetryAfterMs` — the
|
|
964
|
+
* only field the harness retry policy honors. Dropped here, the host can
|
|
965
|
+
* only fall back to its own backoff (observed: 19134ms against an upstream
|
|
966
|
+
* that asked for 30s, so every retry hit the still-closed window).
|
|
967
|
+
*/
|
|
968
|
+
retryAfterMs?: number;
|
|
853
969
|
};
|
|
854
970
|
/** Provenance of the last successful catalog fetch. */
|
|
855
971
|
interface QoderCatalogFetch {
|
|
@@ -1146,6 +1262,15 @@ declare class QoderProbeStore {
|
|
|
1146
1262
|
set(modelId: string, record: QoderProbeRecord): void;
|
|
1147
1263
|
/** Drop every record; used by the card's explicit "clear" action. */
|
|
1148
1264
|
clear(): void;
|
|
1265
|
+
/**
|
|
1266
|
+
* Drop every record that belongs to one account, leaving the other saved
|
|
1267
|
+
* accounts' observations intact.
|
|
1268
|
+
*
|
|
1269
|
+
* Used when a saved token is removed: its detected effort levels are that
|
|
1270
|
+
* account's data, and no other account can use them. A plain {@link clear}
|
|
1271
|
+
* here would erase the observations of every account the user still has.
|
|
1272
|
+
*/
|
|
1273
|
+
clearFor(account: string): void;
|
|
1149
1274
|
/** Every record currently held, for status display. */
|
|
1150
1275
|
all(): Readonly<Record<string, QoderProbeRecord>>;
|
|
1151
1276
|
/** Build a record stamped with this store's clock, version, and account. */
|
|
@@ -1346,22 +1471,27 @@ declare class QoderProbeService {
|
|
|
1346
1471
|
}
|
|
1347
1472
|
//#endregion
|
|
1348
1473
|
//#region src/auth-route.d.ts
|
|
1349
|
-
/** Outcome of a save attempt: stored, or refused with a stable reason. */
|
|
1474
|
+
/** Outcome of a save/activate/remove attempt: stored, or refused with a stable reason. */
|
|
1350
1475
|
type QoderAuthSaveResult = {
|
|
1351
1476
|
ok: true;
|
|
1352
1477
|
status: QoderAuthStatus;
|
|
1353
1478
|
} | {
|
|
1354
1479
|
ok: false;
|
|
1355
|
-
error: 'qoder_invalid_pat' | 'qoder_missing_pat';
|
|
1480
|
+
error: 'qoder_invalid_pat' | 'qoder_missing_pat' | 'qoder_unknown_pat';
|
|
1356
1481
|
};
|
|
1357
1482
|
/** Constructor dependencies. */
|
|
1358
1483
|
interface QoderAuthRouteOptions {
|
|
1359
1484
|
/**
|
|
1360
1485
|
* Validate one pasted token against this variant's region and, only on
|
|
1361
|
-
* success, persist it. The route never decides validity
|
|
1486
|
+
* success, persist it and make it active. The route never decides validity
|
|
1487
|
+
* itself.
|
|
1362
1488
|
*/
|
|
1363
|
-
save: (pat: string) => Promise<QoderAuthSaveResult>;
|
|
1364
|
-
/**
|
|
1489
|
+
save: (pat: string, label?: string) => Promise<QoderAuthSaveResult>;
|
|
1490
|
+
/** Switch to one already-saved token. */
|
|
1491
|
+
activate: (id: string) => Promise<QoderAuthSaveResult>;
|
|
1492
|
+
/** Remove one saved token; the host moves the active pointer. */
|
|
1493
|
+
remove: (id: string) => Promise<QoderAuthSaveResult>;
|
|
1494
|
+
/** Remove every saved token (`logout`). */
|
|
1365
1495
|
clear: () => Promise<void>;
|
|
1366
1496
|
/**
|
|
1367
1497
|
* Route path to mount. Defaults to the China variant's path so callers that
|
|
@@ -1375,7 +1505,7 @@ declare function createAuthKey(): string;
|
|
|
1375
1505
|
* The PAT route's handler, extracted so tests can mount it on a bare server
|
|
1376
1506
|
* with a known key.
|
|
1377
1507
|
*
|
|
1378
|
-
* @param deps - the save/clear operations for one variant.
|
|
1508
|
+
* @param deps - the save/activate/remove/clear operations for one variant.
|
|
1379
1509
|
* @param key - the in-process control key this route requires.
|
|
1380
1510
|
* @returns the Node request handler.
|
|
1381
1511
|
*/
|
|
@@ -1568,4 +1698,4 @@ declare const QUOTA_SECTION_KEYS: readonly ["sidebarQuotaCN", "sidebarQuotaGloba
|
|
|
1568
1698
|
*/
|
|
1569
1699
|
declare function apply(ctx: Context, config: Config): void;
|
|
1570
1700
|
//#endregion
|
|
1571
|
-
export { CHINA_VARIANT, CN_SECTION_KEYS, Config, FALLBACK_QODER_MODELS, GLOBAL_SECTION_KEYS, GLOBAL_VARIANT, KIND_STATUS, PROBE_EFFORT_CANDIDATES, type ProbeAttempt, type ProbeOutcome, type ProbeSender, QODER_AUTH_FILENAME, QODER_AUTH_PATH, QODER_DATA_DIR_ENV, QODER_DATA_DIR_NAME, QODER_GLOBAL_AUTH_PATH, QODER_GLOBAL_PROBE_PATH, QODER_GLOBAL_SETTINGS_NS, QODER_GLOBAL_STATUS_PATH, QODER_HOST_HEARTBEAT_FILENAME, QODER_PAT_ENV_CN, QODER_PAT_ENV_GLOBAL, QODER_PROBE_FILENAME, QODER_PROBE_PATH, QODER_PROVIDER, QODER_QUOTA_SETTINGS_NS, QODER_SETTINGS_NS, QODER_STATUS_PATH, QODER_STREAM_IDLE_TIMEOUT_MS, QODER_VARIANTS, QUOTA_POLL_DEFAULT_MS, QUOTA_POLL_MIN_MS, QUOTA_SECTION_KEYS, type QoderAdapter, type QoderAuthRequest, type QoderAuthRouteOptions, type QoderAuthSaveResult, type QoderAuthStatus, QoderCatalog, type QoderCatalogFetch, type QoderCatalogModelSnapshot, QoderCatalogStore, type QoderCatalogStoreOptions, type QoderChatResult, type QoderCredential, QoderCredentialStore, type QoderCreditAccount, type QoderCredits, type QoderEffort, type QoderHostHeartbeat, type QoderModelBilling, type QoderModelInfo, type QoderModelReasoning, type QoderPatSummary, type QoderProbeAction, type QoderProbeRecord, QoderProbeService, type QoderProbeStatus, QoderProbeStore, type QoderProbeValidation, type QoderShim, QoderUpstreamClient, type QoderVariant, type QoderVariantId, type QoderWebCatalog, type QoderWebCreditAccount, type QoderWebCredits, type QoderWebProbeModel, type QoderWebProbeSection, type QoderWebStatus, type ShimLogger, type UpstreamErrorKind, apply, classifyUpstreamError, clearHostHeartbeat, createAuthKey, createQoderAdapter, createQoderShim, fingerprintModel, inject, isHeartbeatProcessAlive, kindFromQoderFailure, modelInfoOf, name, normalizeCredits, patTail, probeModel, processStartTimeMs, qoderAuthHandler, qoderCatalogPath, qoderCredentialIdentity, qoderHostHeartbeatPath, qoderOwnAuthPath, qoderPluginDataDir, qoderProbePath, randomSentinel, readHostHeartbeat, registerQoderAuthRoute, variantFor };
|
|
1701
|
+
export { CHINA_VARIANT, CN_SECTION_KEYS, Config, FALLBACK_QODER_MODELS, GLOBAL_SECTION_KEYS, GLOBAL_VARIANT, KIND_STATUS, PROBE_EFFORT_CANDIDATES, type ProbeAttempt, type ProbeOutcome, type ProbeSender, QODER_AUTH_FILENAME, QODER_AUTH_PATH, QODER_DATA_DIR_ENV, QODER_DATA_DIR_NAME, QODER_GLOBAL_AUTH_PATH, QODER_GLOBAL_PROBE_PATH, QODER_GLOBAL_SETTINGS_NS, QODER_GLOBAL_STATUS_PATH, QODER_HOST_HEARTBEAT_FILENAME, QODER_PAT_ENV_CN, QODER_PAT_ENV_GLOBAL, QODER_PROBE_FILENAME, QODER_PROBE_PATH, QODER_PROVIDER, QODER_QUOTA_SETTINGS_NS, QODER_SETTINGS_NS, QODER_STATUS_PATH, QODER_STREAM_IDLE_TIMEOUT_MS, QODER_VARIANTS, QUOTA_POLL_DEFAULT_MS, QUOTA_POLL_MIN_MS, QUOTA_SECTION_KEYS, type QoderAdapter, type QoderAuthRequest, type QoderAuthRouteOptions, type QoderAuthSaveResult, type QoderAuthStatus, QoderCatalog, type QoderCatalogFetch, type QoderCatalogModelSnapshot, QoderCatalogStore, type QoderCatalogStoreOptions, type QoderChatResult, type QoderCredential, type QoderCredentialEntry, QoderCredentialStore, type QoderCreditAccount, type QoderCredits, type QoderEffort, type QoderHostHeartbeat, type QoderModelBilling, type QoderModelInfo, type QoderModelReasoning, type QoderPatProfile, type QoderPatSummary, type QoderProbeAction, type QoderProbeRecord, QoderProbeService, type QoderProbeStatus, QoderProbeStore, type QoderProbeValidation, type QoderShim, QoderUpstreamClient, type QoderVariant, type QoderVariantId, type QoderWebCatalog, type QoderWebCreditAccount, type QoderWebCredits, type QoderWebProbeModel, type QoderWebProbeSection, type QoderWebStatus, type ShimLogger, type UpstreamErrorKind, apply, classifyUpstreamError, clearHostHeartbeat, createAuthKey, createQoderAdapter, createQoderShim, fingerprintModel, inject, isHeartbeatProcessAlive, kindFromQoderFailure, modelInfoOf, name, normalizeCredits, patTail, probeModel, processStartTimeMs, qoderAuthHandler, qoderCatalogPath, qoderCredentialId, qoderCredentialIdentity, qoderHostHeartbeatPath, qoderOwnAuthPath, qoderPluginDataDir, qoderProbePath, randomSentinel, readHostHeartbeat, registerQoderAuthRoute, variantFor };
|