dsh-qoder-connect 0.2.5 → 0.2.7
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 +21 -6
- package/README.md +21 -6
- 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 +140 -22
- package/lib/index.js +98 -213
- package/lib/{variants-Dus_Yq3R.js → variants-B_ZzENbC.js} +460 -50
- package/package.json +27 -27
package/lib/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { $ as configurePluginPaths, A as probeModel, B as QODER_PROBE_PATH, C as normalizeCredits, D as utc8WallClock, E as formatUtc8Date, F as QoderCatalog, G as QODER_PAT_ENV_GLOBAL, H as QODER_STATUS_PATH, I as QODER_AUTH_PATH, J as qoderCredentialId, K as QoderCredentialStore, L as QODER_GLOBAL_AUTH_PATH, M as QoderCatalogStore, N as qoderCatalogPath, O as getMachineId, P as FALLBACK_QODER_MODELS, Q as QODER_DATA_DIR_NAME, R as QODER_GLOBAL_PROBE_PATH, S as modelInfoOf, T as createQoderTransport, U as QODER_AUTH_FILENAME, V as QODER_SETTINGS_FACE_PATH, W as QODER_PAT_ENV_CN, X as qoderOwnAuthPath, Y as qoderCredentialIdentity, Z as QODER_DATA_DIR_ENV, _ as qoderProbePath, a as QODER_HOST_HEARTBEAT_FILENAME, b as classifyUpstreamError, c as processStartTimeMs, d as writeHostHeartbeat, et as qoderMachineIdPath, f as QODER_CONNECT_VERSION, g as newestFirst, h as fingerprintModel, i as variantFor, j as randomSentinel, k as PROBE_EFFORT_CANDIDATES, l as qoderHostHeartbeatPath, m as QoderProbeStore, n as GLOBAL_VARIANT, o as clearHostHeartbeat, p as QODER_PROBE_FILENAME, q as patTail, r as QODER_VARIANTS, s as isHeartbeatProcessAlive, t as CHINA_VARIANT, tt as qoderPluginDataDir, u as readHostHeartbeat, v as KIND_STATUS, w as validateApiKey, x as kindFromQoderFailure, y as QoderUpstreamClient, z as QODER_GLOBAL_STATUS_PATH } from "./variants-B_ZzENbC.js";
|
|
2
2
|
import z from "@deepseek-ai/schemastery";
|
|
3
|
-
import {
|
|
4
|
-
import { dirname, join
|
|
3
|
+
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
5
|
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { createProvider } from "@earendil-works/pi-ai";
|
|
7
7
|
import { openAICompletionsApi } from "@earendil-works/pi-ai/api/openai-completions.lazy";
|
|
8
8
|
import { resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
|
|
9
9
|
import { PiAiAdapter } from "@deepseek-ai/dsh-llm-pi-ai";
|
|
10
|
+
import { requestImageDimensions } from "@deepseek-ai/dsh-attachment";
|
|
10
11
|
import { createServer } from "node:http";
|
|
11
12
|
import { Readable } from "node:stream";
|
|
12
13
|
//#region src/loopback.ts
|
|
@@ -59,7 +60,8 @@ function originIsLoopback(origin) {
|
|
|
59
60
|
//#endregion
|
|
60
61
|
//#region src/auth-route.ts
|
|
61
62
|
/**
|
|
62
|
-
* PAT route: saves (validate-then-persist) or clears
|
|
63
|
+
* PAT route: saves (validate-then-persist), switches, removes, or clears the
|
|
64
|
+
* tokens of one variant.
|
|
63
65
|
*
|
|
64
66
|
* The state-changing endpoints the plugin exposes share one guard shape — a
|
|
65
67
|
* loopback Host and Origin, plus the in-process key the card receives with its
|
|
@@ -110,9 +112,20 @@ function parseRequest(text) {
|
|
|
110
112
|
if (action === "save-pat") {
|
|
111
113
|
const pat = wrapped["pat"];
|
|
112
114
|
if (typeof pat !== "string" || pat.trim() === "") return void 0;
|
|
115
|
+
const label = wrapped["label"];
|
|
116
|
+
if (label !== void 0 && (typeof label !== "string" || label.length > 200)) return void 0;
|
|
113
117
|
return {
|
|
114
118
|
action,
|
|
115
|
-
pat
|
|
119
|
+
pat,
|
|
120
|
+
...label === void 0 ? {} : { label }
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
if (action === "activate" || action === "remove") {
|
|
124
|
+
const id = wrapped["id"];
|
|
125
|
+
if (typeof id !== "string" || id.trim() === "") return void 0;
|
|
126
|
+
return {
|
|
127
|
+
action,
|
|
128
|
+
id: id.trim()
|
|
116
129
|
};
|
|
117
130
|
}
|
|
118
131
|
}
|
|
@@ -142,7 +155,7 @@ function keyMatches$1(expected, presented) {
|
|
|
142
155
|
* The PAT route's handler, extracted so tests can mount it on a bare server
|
|
143
156
|
* with a known key.
|
|
144
157
|
*
|
|
145
|
-
* @param deps - the save/clear operations for one variant.
|
|
158
|
+
* @param deps - the save/activate/remove/clear operations for one variant.
|
|
146
159
|
* @param key - the in-process control key this route requires.
|
|
147
160
|
* @returns the Node request handler.
|
|
148
161
|
*/
|
|
@@ -176,7 +189,15 @@ function qoderAuthHandler(deps, key) {
|
|
|
176
189
|
json$2(res, 200, { ok: true });
|
|
177
190
|
return;
|
|
178
191
|
}
|
|
179
|
-
|
|
192
|
+
if (request.action === "activate") {
|
|
193
|
+
json$2(res, 200, await deps.activate(request.id));
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (request.action === "remove") {
|
|
197
|
+
json$2(res, 200, await deps.remove(request.id));
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
json$2(res, 200, await deps.save(request.pat, request.label));
|
|
180
201
|
} catch (error) {
|
|
181
202
|
json$2(res, 200, {
|
|
182
203
|
ok: false,
|
|
@@ -441,7 +462,7 @@ function createQoderAdapter(options) {
|
|
|
441
462
|
* than being dropped: catalog membership is advisory, and the seam tolerates
|
|
442
463
|
* serving an unlisted id.
|
|
443
464
|
*/
|
|
444
|
-
var QoderPiAiAdapter = class extends PiAiAdapter {
|
|
465
|
+
var QoderPiAiAdapter = class QoderPiAiAdapter extends PiAiAdapter {
|
|
445
466
|
catalog;
|
|
446
467
|
constructor(catalog, options) {
|
|
447
468
|
super(options);
|
|
@@ -470,6 +491,30 @@ var QoderPiAiAdapter = class extends PiAiAdapter {
|
|
|
470
491
|
name: withCatalogDisplay(resolved.name, info)
|
|
471
492
|
};
|
|
472
493
|
}
|
|
494
|
+
/**
|
|
495
|
+
* Resolve the request-image projection target for one route.
|
|
496
|
+
*
|
|
497
|
+
* `dsh-llm` 0.2.1 added `LlmAdapter.imageRequestTarget()` and its runtime calls
|
|
498
|
+
* it unconditionally (`this.registration(provider).adapter.imageRequestTarget(...)`,
|
|
499
|
+
* no optional chaining, no typeof guard). This plugin resolves its harness peers
|
|
500
|
+
* from its own pnpm store (0.1.7-rc.2), whose `PiAiAdapter` predates the method,
|
|
501
|
+
* so an inherited implementation is absent and that call would throw
|
|
502
|
+
* `TypeError: ....imageRequestTarget is not a function`.
|
|
503
|
+
*
|
|
504
|
+
* Derive the same target from the profile budgets this route already declares.
|
|
505
|
+
* When a host does provide the base implementation (a newer peer resolution),
|
|
506
|
+
* prefer it so this override never drifts from upstream behavior.
|
|
507
|
+
*/
|
|
508
|
+
imageRequestTarget(provider, model, image) {
|
|
509
|
+
const inherited = Object.getPrototypeOf(QoderPiAiAdapter.prototype).imageRequestTarget;
|
|
510
|
+
if (typeof inherited === "function") return inherited.call(this, provider, model, image);
|
|
511
|
+
const { width, height } = requestImageDimensions(image.width, image.height, REQUEST_IMAGE_BUDGETS.requestImagePixelBudget);
|
|
512
|
+
return {
|
|
513
|
+
width,
|
|
514
|
+
height,
|
|
515
|
+
maxBytes: REQUEST_IMAGE_BUDGETS.requestImageMaxBytes
|
|
516
|
+
};
|
|
517
|
+
}
|
|
473
518
|
};
|
|
474
519
|
//#endregion
|
|
475
520
|
//#region src/shim.ts
|
|
@@ -658,203 +703,6 @@ function createQoderShim(options) {
|
|
|
658
703
|
};
|
|
659
704
|
}
|
|
660
705
|
//#endregion
|
|
661
|
-
//#region src/probe-store.ts
|
|
662
|
-
/**
|
|
663
|
-
* Local record of reasoning-effort probes.
|
|
664
|
-
*
|
|
665
|
-
* What this stores is an *observation*, never a claim about the upstream: a
|
|
666
|
-
* model's row is only consulted when the catalog carries no explicit
|
|
667
|
-
* `supportedEfforts` set, and it always loses to a declared set. The plan this
|
|
668
|
-
* implements (`docs/reasoning-effort-probe-plan.md` §5) requires that a result
|
|
669
|
-
* is invalidated whenever the model's catalog row changes, so every record
|
|
670
|
-
* carries a fingerprint of the fields the probe depended on.
|
|
671
|
-
*
|
|
672
|
-
* The file lives in the plugin's own state directory, never beside the
|
|
673
|
-
* product's files, and carries no token, prompt, or response body — only
|
|
674
|
-
* model ids, effort spellings, and timestamps.
|
|
675
|
-
*
|
|
676
|
-
* @module dsh-qoder-connect/probe-store
|
|
677
|
-
*/
|
|
678
|
-
/** Basename of the China variant's probe record inside the plugin's state dir. */
|
|
679
|
-
const QODER_PROBE_FILENAME = ".qoder-probe.json";
|
|
680
|
-
/** On-disk format this reader accepts; other versions are discarded. */
|
|
681
|
-
const PROBE_FORMAT_VERSION = 1;
|
|
682
|
-
/**
|
|
683
|
-
* How long an observation stays usable. Conservative on purpose: the plan's
|
|
684
|
-
* whole argument is that upstream metadata moves fast, so a result that has
|
|
685
|
-
* outlived its fingerprint's usefulness should not quietly keep granting a
|
|
686
|
-
* picker entry.
|
|
687
|
-
*/
|
|
688
|
-
const DEFAULT_TTL_MS = 12096e5;
|
|
689
|
-
/**
|
|
690
|
-
* Plugin-owned probe record path inside the plugin's state directory.
|
|
691
|
-
*
|
|
692
|
-
* One file per variant. The two regions serve overlapping model ids with
|
|
693
|
-
* different entitlements, and {@link fingerprintModel} covers only
|
|
694
|
-
* `id`/`reasoning`/`supportsImages` — never the provider — so a single shared
|
|
695
|
-
* file would let one variant's observation answer for the other. The paths
|
|
696
|
-
* differ; the format does not.
|
|
697
|
-
*/
|
|
698
|
-
function qoderProbePath(filename = QODER_PROBE_FILENAME) {
|
|
699
|
-
return join(qoderStateDir(), filename);
|
|
700
|
-
}
|
|
701
|
-
/**
|
|
702
|
-
* Fingerprint the catalog fields a probe depends on.
|
|
703
|
-
*
|
|
704
|
-
* Deliberately excludes display-only fields (`name`, `billing`, `contextWindow`)
|
|
705
|
-
* so a rename or a rate relabel does not throw away a valid observation, and
|
|
706
|
-
* deliberately includes the whole reasoning object so any change to the
|
|
707
|
-
* declared shape re-probes.
|
|
708
|
-
*/
|
|
709
|
-
function fingerprintModel(info) {
|
|
710
|
-
const basis = JSON.stringify({
|
|
711
|
-
id: info.id,
|
|
712
|
-
reasoning: info.reasoning ?? null,
|
|
713
|
-
supportsImages: info.supportsImages ?? null
|
|
714
|
-
});
|
|
715
|
-
return createHash("sha256").update(basis).digest("hex").slice(0, 16);
|
|
716
|
-
}
|
|
717
|
-
/** Read-and-validate the documents on disk; anything malformed reads as empty. */
|
|
718
|
-
function readDocument(path) {
|
|
719
|
-
if (!existsSync(path)) return void 0;
|
|
720
|
-
let parsed;
|
|
721
|
-
try {
|
|
722
|
-
parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
723
|
-
} catch {
|
|
724
|
-
return;
|
|
725
|
-
}
|
|
726
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return void 0;
|
|
727
|
-
const wrapped = parsed;
|
|
728
|
-
if (wrapped["version"] !== PROBE_FORMAT_VERSION) return void 0;
|
|
729
|
-
const records = wrapped["records"];
|
|
730
|
-
if (typeof records !== "object" || records === null || Array.isArray(records)) return void 0;
|
|
731
|
-
return parsed;
|
|
732
|
-
}
|
|
733
|
-
/** One record's shape check; a bad row is dropped rather than trusted. */
|
|
734
|
-
function isRecord(value) {
|
|
735
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
736
|
-
const wrapped = value;
|
|
737
|
-
const validation = wrapped["validation"];
|
|
738
|
-
if (validation !== "validating" && validation !== "non-validating" && validation !== "unknown") return false;
|
|
739
|
-
if (typeof wrapped["fingerprint"] !== "string") return false;
|
|
740
|
-
if (typeof wrapped["probedAtMs"] !== "number" || !Number.isFinite(wrapped["probedAtMs"])) return false;
|
|
741
|
-
if (typeof wrapped["pluginVersion"] !== "string") return false;
|
|
742
|
-
const efforts = wrapped["efforts"];
|
|
743
|
-
if (!Array.isArray(efforts) || efforts.some((effort) => typeof effort !== "string")) return false;
|
|
744
|
-
return true;
|
|
745
|
-
}
|
|
746
|
-
/**
|
|
747
|
-
* The plugin's probe records: read once, written atomically, never trusted
|
|
748
|
-
* across a fingerprint change or past the TTL.
|
|
749
|
-
*/
|
|
750
|
-
var QoderProbeStore = class {
|
|
751
|
-
path;
|
|
752
|
-
ttlMs;
|
|
753
|
-
pluginVersion;
|
|
754
|
-
now;
|
|
755
|
-
records;
|
|
756
|
-
constructor(options) {
|
|
757
|
-
const opts = typeof options === "string" ? {
|
|
758
|
-
path: options,
|
|
759
|
-
pluginVersion: "0.0.0"
|
|
760
|
-
} : options;
|
|
761
|
-
this.path = opts.path ?? qoderProbePath();
|
|
762
|
-
this.ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS;
|
|
763
|
-
this.pluginVersion = opts.pluginVersion;
|
|
764
|
-
this.now = opts.now ?? (() => Date.now());
|
|
765
|
-
}
|
|
766
|
-
/** Resolved state-file path, for the CLI and tests. */
|
|
767
|
-
filePath() {
|
|
768
|
-
return this.path;
|
|
769
|
-
}
|
|
770
|
-
load() {
|
|
771
|
-
if (this.records === void 0) {
|
|
772
|
-
const document = readDocument(this.path);
|
|
773
|
-
const records = {};
|
|
774
|
-
for (const [id, record] of Object.entries(document?.records ?? {})) if (isRecord(record)) records[id] = record;
|
|
775
|
-
this.records = records;
|
|
776
|
-
}
|
|
777
|
-
return this.records;
|
|
778
|
-
}
|
|
779
|
-
/**
|
|
780
|
-
* The usable record for a model, or `undefined` when there is none, it is
|
|
781
|
-
* expired, it was taken against a different catalog row, or it belongs to a
|
|
782
|
-
* different account.
|
|
783
|
-
*
|
|
784
|
-
* @param account - the account in effect, as `uid:enterpriseId`. Records are
|
|
785
|
-
* only returned for the account that produced them.
|
|
786
|
-
*/
|
|
787
|
-
get(modelId, fingerprint, account) {
|
|
788
|
-
const record = this.load()[modelId];
|
|
789
|
-
if (record === void 0) return void 0;
|
|
790
|
-
if (record.fingerprint !== fingerprint) return void 0;
|
|
791
|
-
if (record.account !== account) return void 0;
|
|
792
|
-
if (this.now() - record.probedAtMs > this.ttlMs) return void 0;
|
|
793
|
-
return record;
|
|
794
|
-
}
|
|
795
|
-
/**
|
|
796
|
-
* Store one observation. Only a decisive answer (`validating` /
|
|
797
|
-
* `non-validating`) replaces an existing decisive record: a transient
|
|
798
|
-
* `unknown` must not erase knowledge the user already paid for.
|
|
799
|
-
*/
|
|
800
|
-
set(modelId, record) {
|
|
801
|
-
const records = this.load();
|
|
802
|
-
const existing = records[modelId];
|
|
803
|
-
if (record.validation === "unknown" && existing !== void 0 && existing.fingerprint === record.fingerprint && existing.validation !== "unknown") return;
|
|
804
|
-
records[modelId] = record;
|
|
805
|
-
this.persist();
|
|
806
|
-
}
|
|
807
|
-
/** Drop every record; used by the card's explicit "clear" action. */
|
|
808
|
-
clear() {
|
|
809
|
-
this.records = {};
|
|
810
|
-
this.persist();
|
|
811
|
-
}
|
|
812
|
-
/** Every record currently held, for status display. */
|
|
813
|
-
all() {
|
|
814
|
-
return { ...this.load() };
|
|
815
|
-
}
|
|
816
|
-
/** Build a record stamped with this store's clock, version, and account. */
|
|
817
|
-
record(fingerprint, validation, efforts, account) {
|
|
818
|
-
return {
|
|
819
|
-
fingerprint,
|
|
820
|
-
validation,
|
|
821
|
-
efforts: validation === "validating" ? [...efforts] : [],
|
|
822
|
-
probedAtMs: this.now(),
|
|
823
|
-
pluginVersion: this.pluginVersion,
|
|
824
|
-
account
|
|
825
|
-
};
|
|
826
|
-
}
|
|
827
|
-
/**
|
|
828
|
-
* Write through a temporary file and rename, so a crash mid-write cannot
|
|
829
|
-
* leave a half-parsed document that reads as "no records" and silently drops
|
|
830
|
-
* every observation.
|
|
831
|
-
*/
|
|
832
|
-
persist() {
|
|
833
|
-
const directory = dirname(this.path);
|
|
834
|
-
try {
|
|
835
|
-
if (!existsSync(directory)) mkdirSync(directory, { recursive: true });
|
|
836
|
-
const document = {
|
|
837
|
-
version: PROBE_FORMAT_VERSION,
|
|
838
|
-
records: this.load()
|
|
839
|
-
};
|
|
840
|
-
const temporary = resolve(`${this.path}.tmp`);
|
|
841
|
-
writeFileSync(temporary, `${JSON.stringify(document, null, 2)}\n`, { mode: 384 });
|
|
842
|
-
renameSync(temporary, this.path);
|
|
843
|
-
} catch {}
|
|
844
|
-
}
|
|
845
|
-
};
|
|
846
|
-
/**
|
|
847
|
-
* Order observations newest-first for display.
|
|
848
|
-
*
|
|
849
|
-
* The store keeps insertion order so the file reads chronologically, but the
|
|
850
|
-
* card wants the most recent detection at the top: a sweep the user just ran
|
|
851
|
-
* should not appear below every earlier one, which is what appending to an
|
|
852
|
-
* insertion-ordered list does.
|
|
853
|
-
*/
|
|
854
|
-
function newestFirst(records) {
|
|
855
|
-
return [...records].sort((a, b) => b.probedAt - a.probedAt);
|
|
856
|
-
}
|
|
857
|
-
//#endregion
|
|
858
706
|
//#region src/probe-service.ts
|
|
859
707
|
/**
|
|
860
708
|
* Serial probe runner. One instance is shared by the manual API and any
|
|
@@ -1045,6 +893,8 @@ async function qoderWebStatus(deps) {
|
|
|
1045
893
|
status: "signed-in",
|
|
1046
894
|
...authStatus.region === void 0 ? {} : { region: authStatus.region },
|
|
1047
895
|
...authStatus.pat === void 0 ? {} : { pat: authStatus.pat },
|
|
896
|
+
...authStatus.profiles === void 0 ? {} : { patProfiles: authStatus.profiles },
|
|
897
|
+
...authStatus.activeId === void 0 ? {} : { activePatId: authStatus.activeId },
|
|
1048
898
|
...deps.authKey === void 0 ? {} : { authKey: deps.authKey }
|
|
1049
899
|
};
|
|
1050
900
|
const modelsField = deps.models().map(modelSnapshot);
|
|
@@ -2662,10 +2512,7 @@ function apply(ctx, config) {
|
|
|
2662
2512
|
runtime.catalogGeneration += 1;
|
|
2663
2513
|
runtime.inflightFetch?.controller.abort();
|
|
2664
2514
|
runtime.inflightFetch = void 0;
|
|
2665
|
-
if (hadCredential && known !== identity)
|
|
2666
|
-
runtime.probeStore.clear();
|
|
2667
|
-
runtime.invalidate();
|
|
2668
|
-
}
|
|
2515
|
+
if (hadCredential && known !== identity) runtime.invalidate();
|
|
2669
2516
|
if (identity === void 0) {
|
|
2670
2517
|
if (known !== void 0) runtime.savedCatalogs.delete(known);
|
|
2671
2518
|
runtime.catalog.set(runtime.fallback);
|
|
@@ -2740,13 +2587,13 @@ function apply(ctx, config) {
|
|
|
2740
2587
|
});
|
|
2741
2588
|
registerQoderAuthRoute(webCtx, {
|
|
2742
2589
|
path: runtime.variant.authPath,
|
|
2743
|
-
save: async (pat) => {
|
|
2590
|
+
save: async (pat, label) => {
|
|
2744
2591
|
if (!await validateApiKey(pat, runtime.variant.region)) return {
|
|
2745
2592
|
ok: false,
|
|
2746
2593
|
error: "qoder_invalid_pat"
|
|
2747
2594
|
};
|
|
2748
|
-
const
|
|
2749
|
-
const identity = credentialIdentity(
|
|
2595
|
+
const entry = await runtime.store.add(pat, label);
|
|
2596
|
+
const identity = credentialIdentity(entry);
|
|
2750
2597
|
adoptIdentity(runtime, identity);
|
|
2751
2598
|
await fetchCatalog(runtime, identity);
|
|
2752
2599
|
return {
|
|
@@ -2754,7 +2601,45 @@ function apply(ctx, config) {
|
|
|
2754
2601
|
status: await runtime.store.status()
|
|
2755
2602
|
};
|
|
2756
2603
|
},
|
|
2604
|
+
activate: async (id) => {
|
|
2605
|
+
const entry = await runtime.store.activate(id);
|
|
2606
|
+
if (entry === void 0) return {
|
|
2607
|
+
ok: false,
|
|
2608
|
+
error: "qoder_unknown_pat"
|
|
2609
|
+
};
|
|
2610
|
+
const identity = credentialIdentity(entry);
|
|
2611
|
+
adoptIdentity(runtime, identity);
|
|
2612
|
+
detach(ctx, fetchCatalog(runtime, identity), `${runtime.variant.id} catalog refresh after switch`);
|
|
2613
|
+
return {
|
|
2614
|
+
ok: true,
|
|
2615
|
+
status: await runtime.store.status()
|
|
2616
|
+
};
|
|
2617
|
+
},
|
|
2618
|
+
remove: async (id) => {
|
|
2619
|
+
const removed = await runtime.store.remove(id);
|
|
2620
|
+
if (removed === void 0) return {
|
|
2621
|
+
ok: false,
|
|
2622
|
+
error: "qoder_unknown_pat"
|
|
2623
|
+
};
|
|
2624
|
+
const finished = credentialIdentity(removed);
|
|
2625
|
+
runtime.probeStore.clearFor(finished);
|
|
2626
|
+
runtime.savedCatalogs.delete(finished);
|
|
2627
|
+
const active = await runtime.store.current().catch(() => void 0);
|
|
2628
|
+
const identity = active === void 0 ? void 0 : credentialIdentity(active);
|
|
2629
|
+
adoptIdentity(runtime, identity);
|
|
2630
|
+
if (identity !== void 0) detach(ctx, fetchCatalog(runtime, identity), `${runtime.variant.id} catalog refresh after removal`);
|
|
2631
|
+
return {
|
|
2632
|
+
ok: true,
|
|
2633
|
+
status: await runtime.store.status()
|
|
2634
|
+
};
|
|
2635
|
+
},
|
|
2757
2636
|
clear: async () => {
|
|
2637
|
+
const saved = await runtime.store.entries().catch(() => []);
|
|
2638
|
+
for (const entry of saved) {
|
|
2639
|
+
const identity = credentialIdentity(entry);
|
|
2640
|
+
runtime.probeStore.clearFor(identity);
|
|
2641
|
+
runtime.savedCatalogs.delete(identity);
|
|
2642
|
+
}
|
|
2758
2643
|
await runtime.store.clear();
|
|
2759
2644
|
adoptIdentity(runtime, void 0);
|
|
2760
2645
|
}
|
|
@@ -3072,4 +2957,4 @@ function apply(ctx, config) {
|
|
|
3072
2957
|
}), "variant startup");
|
|
3073
2958
|
}
|
|
3074
2959
|
//#endregion
|
|
3075
|
-
export { CHINA_VARIANT, CN_SECTION_KEYS, Config, FALLBACK_QODER_MODELS, GLOBAL_SECTION_KEYS, GLOBAL_VARIANT, KIND_STATUS, PROBE_EFFORT_CANDIDATES, 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, QoderCatalog, QoderCatalogStore, QoderCredentialStore, QoderProbeService, QoderProbeStore, QoderUpstreamClient, 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 };
|
|
2960
|
+
export { CHINA_VARIANT, CN_SECTION_KEYS, Config, FALLBACK_QODER_MODELS, GLOBAL_SECTION_KEYS, GLOBAL_VARIANT, KIND_STATUS, PROBE_EFFORT_CANDIDATES, 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, QoderCatalog, QoderCatalogStore, QoderCredentialStore, QoderProbeService, QoderProbeStore, QoderUpstreamClient, 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 };
|