dsh-model-think-level 1.0.0 → 1.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.
package/lib/index.js CHANGED
@@ -4,6 +4,9 @@ import Schema from "@deepseek-ai/schemastery";
4
4
  // src/constants.ts
5
5
  var PLUGIN_ID = "dsh-model-think-level";
6
6
  var PROBE_PATH = "/dsh-model-think-level/raw-models";
7
+ var DIAG_PATH = "/dsh-model-think-level/header-bridge";
8
+ var PROVIDER_KEY_PATH = "/dsh-model-think-level/provider-key";
9
+ var KEY_INDEX_PATH = "/dsh-model-think-level/key-index";
7
10
  var AUTOFILL_CONFIG_PATH = "/dsh-model-think-level/autofill-config";
8
11
  var HEADERS_CONFIG_PATH = "/dsh-model-think-level/headers-config";
9
12
  var PI_AI_NS = "llm-pi-ai";
@@ -11,6 +14,142 @@ var UNSET_MARKER = "reasoningEffortsUnset";
11
14
  var INPUT_UNSET_MARKER = "inputUnset";
12
15
  var AUTOFILL_MARKER = "reasoningEffortsAutofilled";
13
16
 
17
+ // src/key-refs.ts
18
+ var KEY_ALIAS_MAX_LENGTH = 40;
19
+ function deriveKeyRef(route) {
20
+ return `${route.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}_API_KEY`;
21
+ }
22
+ function nextKeyRef(route, taken) {
23
+ const used = new Set(taken);
24
+ const base = deriveKeyRef(route);
25
+ if (!used.has(base)) return base;
26
+ for (let suffix = 2; suffix <= 999; suffix += 1) {
27
+ const candidate = `${base}_${suffix}`;
28
+ if (!used.has(candidate)) return candidate;
29
+ }
30
+ return `${base}_${Date.now()}`;
31
+ }
32
+ function normalizeKeyAlias(value) {
33
+ if (typeof value !== "string") return void 0;
34
+ let cleaned = "";
35
+ for (const char of value) {
36
+ const code = char.codePointAt(0) ?? 0;
37
+ if (code < 32 || code === 127) continue;
38
+ cleaned += char;
39
+ }
40
+ cleaned = cleaned.trim();
41
+ if (cleaned.length === 0) return void 0;
42
+ return cleaned.slice(0, KEY_ALIAS_MAX_LENGTH);
43
+ }
44
+ function isLegalKeyValue(value) {
45
+ return typeof value === "string" && /^[\x21-\x7E]+$/.test(value);
46
+ }
47
+ var KEY_MASK_MIN_LENGTH = 12;
48
+ function maskKeyValue(value) {
49
+ if (value.length === 0) return "";
50
+ if (value.length < KEY_MASK_MIN_LENGTH) return "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
51
+ return `${value.slice(0, 4)}...${value.slice(-4)}`;
52
+ }
53
+
54
+ // src/key-index.ts
55
+ import { mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
56
+ import { homedir } from "node:os";
57
+ import { dirname, join } from "node:path";
58
+ function emptyKeyIndex() {
59
+ return { version: 1, providers: {} };
60
+ }
61
+ function harnessHome() {
62
+ const configured = process.env["DSH_HOME"];
63
+ if (typeof configured === "string" && configured.length > 0) return configured;
64
+ try {
65
+ return join(homedir(), ".dsh");
66
+ } catch {
67
+ return ".dsh";
68
+ }
69
+ }
70
+ function keyIndexFilePath(home = harnessHome()) {
71
+ return join(home, "dsh-model-think-level", "key-index.json");
72
+ }
73
+ function parseKeyIndex(raw) {
74
+ if (typeof raw !== "object" || raw === null) return emptyKeyIndex();
75
+ const providers = raw["providers"];
76
+ if (typeof providers !== "object" || providers === null) return emptyKeyIndex();
77
+ const out = {};
78
+ for (const [route, entries] of Object.entries(providers)) {
79
+ if (route.length === 0 || !Array.isArray(entries)) continue;
80
+ const list = [];
81
+ for (const entry of entries) {
82
+ if (typeof entry !== "object" || entry === null) continue;
83
+ const record = entry;
84
+ const ref = record["ref"];
85
+ if (typeof ref !== "string" || ref.length === 0) continue;
86
+ if (list.some((existing) => existing.ref === ref)) continue;
87
+ const alias = normalizeKeyAlias(record["alias"]);
88
+ list.push(alias === void 0 ? { ref } : { ref, alias });
89
+ }
90
+ if (list.length > 0) out[route] = list;
91
+ }
92
+ return { version: 1, providers: out };
93
+ }
94
+ function readKeyIndex(file = keyIndexFilePath()) {
95
+ try {
96
+ return parseKeyIndex(JSON.parse(readFileSync(file, "utf8")));
97
+ } catch {
98
+ return emptyKeyIndex();
99
+ }
100
+ }
101
+ function writeKeyIndex(document, file = keyIndexFilePath()) {
102
+ mkdirSync(dirname(file), { recursive: true });
103
+ const temporary = `${file}.${process.pid}.tmp`;
104
+ writeFileSync(temporary, `${JSON.stringify(document, null, 2)}
105
+ `, "utf8");
106
+ try {
107
+ renameSync(temporary, file);
108
+ } catch (error) {
109
+ try {
110
+ unlinkSync(temporary);
111
+ } catch {
112
+ }
113
+ throw error;
114
+ }
115
+ }
116
+ function updateKeyIndex(mutate, file = keyIndexFilePath()) {
117
+ const next = mutate(readKeyIndex(file));
118
+ writeKeyIndex(next, file);
119
+ return next;
120
+ }
121
+ function keyEntriesOf(document, route) {
122
+ const entries = document.providers[route];
123
+ return Array.isArray(entries) ? entries : [];
124
+ }
125
+ function hasKeyEntry(document, route, ref) {
126
+ return keyEntriesOf(document, route).some((entry) => entry.ref === ref);
127
+ }
128
+ function withKeyEntry(document, route, ref, alias) {
129
+ const list = [...keyEntriesOf(document, route)];
130
+ const index = list.findIndex((entry) => entry.ref === ref);
131
+ const label = normalizeKeyAlias(alias);
132
+ const next = label === void 0 ? { ref } : { ref, alias: label };
133
+ if (index === -1) list.push(next);
134
+ else list[index] = label === void 0 && list[index]?.alias !== void 0 ? { ref, alias: list[index]?.alias } : next;
135
+ return { version: 1, providers: { ...document.providers, [route]: list } };
136
+ }
137
+ function withKeyAlias(document, route, ref, alias) {
138
+ const list = [...keyEntriesOf(document, route)];
139
+ const index = list.findIndex((entry) => entry.ref === ref);
140
+ if (index === -1) return document;
141
+ const label = normalizeKeyAlias(alias);
142
+ list[index] = label === void 0 ? { ref } : { ref, alias: label };
143
+ return { version: 1, providers: { ...document.providers, [route]: list } };
144
+ }
145
+ function withoutKeyEntry(document, route, ref) {
146
+ const list = keyEntriesOf(document, route).filter((entry) => entry.ref !== ref);
147
+ const providers = { ...document.providers };
148
+ if (list.length === 0) delete providers[route];
149
+ else providers[route] = list;
150
+ return { version: 1, providers };
151
+ }
152
+
14
153
  // src/knowledge.ts
15
154
  var INPUT_MODALITIES = ["text", "image"];
16
155
  var NEW_COMPAT_KEYS = ["thinkingTokenBudgetField", "vllmPriority", "supportsMaxOutputTokens"];
@@ -1523,6 +1662,9 @@ function selectOverrideFrom(candidates, model) {
1523
1662
  }
1524
1663
  return candidates[0];
1525
1664
  }
1665
+ function selectOverride(index, url, model) {
1666
+ return selectOverrideFrom(pathCandidatesOf(index, url), model);
1667
+ }
1526
1668
  function requestUrlOf(input) {
1527
1669
  if (typeof input === "string") return input;
1528
1670
  if (typeof URL !== "undefined" && input instanceof URL) return input.href;
@@ -1615,10 +1757,248 @@ function headerOverlayInstalled() {
1615
1757
  return registry !== void 0 && globalThis.fetch === registry.wrapper;
1616
1758
  }
1617
1759
 
1760
+ // src/headers-pi-ai.ts
1761
+ var PATCH_STATE = /* @__PURE__ */ Symbol.for("dsh-model-think-level.pi-ai-header-transform");
1762
+ var REGISTER_PATCH_STATE = /* @__PURE__ */ Symbol.for("dsh-model-think-level.pi-ai-header-register");
1763
+ var CORDIS_ORIGINAL = /* @__PURE__ */ Symbol.for("cordis.original");
1764
+ function objectOf(value) {
1765
+ return typeof value === "object" && value !== null ? value : void 0;
1766
+ }
1767
+ function runtimeObjectOf(value) {
1768
+ const object = objectOf(value);
1769
+ if (object === void 0) return void 0;
1770
+ const original = object[CORDIS_ORIGINAL];
1771
+ return objectOf(original) ?? object;
1772
+ }
1773
+ function noOpHandle() {
1774
+ return {
1775
+ active: false,
1776
+ dispose() {
1777
+ }
1778
+ };
1779
+ }
1780
+ function routeOverrideOf(source, model) {
1781
+ try {
1782
+ if (!isRecord(model)) return void 0;
1783
+ const baseURL = model["baseUrl"];
1784
+ if (typeof baseURL !== "string" || baseURL.length === 0) return void 0;
1785
+ const modelId = typeof model["id"] === "string" ? model["id"] : void 0;
1786
+ return selectOverride(source.current, baseURL, modelId);
1787
+ } catch {
1788
+ return void 0;
1789
+ }
1790
+ }
1791
+ function modelsProxyOf(models, source) {
1792
+ return new Proxy(models, {
1793
+ get(target, property, receiver) {
1794
+ if (property !== "streamSimple") return Reflect.get(target, property, receiver);
1795
+ const streamSimple = Reflect.get(target, property, target);
1796
+ if (typeof streamSimple !== "function") return streamSimple;
1797
+ return (...args) => {
1798
+ const model = args[0];
1799
+ const context = args[1];
1800
+ const options = args[2];
1801
+ const modelObject = isRecord(model) ? model : void 0;
1802
+ if (modelObject === void 0 || typeof modelObject["baseUrl"] !== "string" || !isRecord(options)) {
1803
+ return streamSimple.call(target, model, context, options);
1804
+ }
1805
+ const existing = typeof options["transformHeaders"] === "function" ? options["transformHeaders"] : void 0;
1806
+ const transformHeaders = async (headers) => {
1807
+ const merged = existing === void 0 ? headers : await existing(headers);
1808
+ const override = routeOverrideOf(source, model);
1809
+ return override?.hasHeaders ? { ...merged, ...override.headers } : merged;
1810
+ };
1811
+ return streamSimple.call(target, model, context, {
1812
+ ...options,
1813
+ transformHeaders
1814
+ });
1815
+ };
1816
+ }
1817
+ });
1818
+ }
1819
+ function snapshotProxyOf(snapshot, source) {
1820
+ const models = snapshot["models"];
1821
+ const modelObject = objectOf(models);
1822
+ if (modelObject === void 0 || typeof modelObject["streamSimple"] !== "function") return snapshot;
1823
+ const proxiedModels = modelsProxyOf(modelObject, source);
1824
+ return new Proxy(snapshot, {
1825
+ get(target, property, receiver) {
1826
+ if (property === "models") return proxiedModels;
1827
+ return Reflect.get(target, property, receiver);
1828
+ }
1829
+ });
1830
+ }
1831
+ function installPiAiHeaderTransform(adapter, source) {
1832
+ const target = objectOf(adapter);
1833
+ if (target === void 0 || typeof target["current"] !== "function") return noOpHandle();
1834
+ const current = target["current"];
1835
+ const stored = target[PATCH_STATE];
1836
+ if (stored !== void 0 && current === stored.wrappedCurrent) {
1837
+ stored.source = source;
1838
+ stored.users += 1;
1839
+ let active2 = true;
1840
+ return {
1841
+ get active() {
1842
+ return active2 && stored.users > 0;
1843
+ },
1844
+ dispose() {
1845
+ if (!active2) return;
1846
+ active2 = false;
1847
+ stored.users -= 1;
1848
+ if (stored.users > 0) return;
1849
+ if (target["current"] === stored.wrappedCurrent) target["current"] = stored.originalCurrent;
1850
+ if (target[PATCH_STATE] === stored) delete target[PATCH_STATE];
1851
+ }
1852
+ };
1853
+ }
1854
+ const originalCurrent = current;
1855
+ const wrappedCurrent = function(...args) {
1856
+ const snapshot = originalCurrent.apply(this, args);
1857
+ const snapshotObject = objectOf(snapshot);
1858
+ return snapshotObject === void 0 ? snapshot : snapshotProxyOf(snapshotObject, state.source);
1859
+ };
1860
+ const state = { originalCurrent, wrappedCurrent, source, users: 1 };
1861
+ target["current"] = wrappedCurrent;
1862
+ Object.defineProperty(target, PATCH_STATE, { configurable: true, value: state });
1863
+ let active = true;
1864
+ return {
1865
+ get active() {
1866
+ return active && state.users > 0;
1867
+ },
1868
+ dispose() {
1869
+ if (!active) return;
1870
+ active = false;
1871
+ state.users -= 1;
1872
+ if (state.users > 0) return;
1873
+ if (target["current"] === state.wrappedCurrent) target["current"] = state.originalCurrent;
1874
+ if (target[PATCH_STATE] === state) delete target[PATCH_STATE];
1875
+ }
1876
+ };
1877
+ }
1878
+ function describePiAiHeaderState(llm, source) {
1879
+ const runtime = runtimeObjectOf(llm);
1880
+ const adapters = runtime?.["adapters"];
1881
+ const names = [];
1882
+ let total = 0;
1883
+ let patched = 0;
1884
+ if (adapters instanceof Map) {
1885
+ for (const registration of adapters.values()) {
1886
+ const adapter = objectOf(objectOf(registration)?.["adapter"]);
1887
+ if (adapter === void 0 || typeof adapter["current"] !== "function") continue;
1888
+ total += 1;
1889
+ const state = adapter[PATCH_STATE];
1890
+ const isPatched = state !== void 0 && adapter["current"] === state.wrappedCurrent;
1891
+ if (isPatched) patched += 1;
1892
+ const name2 = typeof adapter["constructor"] === "function" ? adapter["constructor"].name : "unknown";
1893
+ names.push(`${name2}${isPatched ? "+" : "-"}`);
1894
+ }
1895
+ }
1896
+ const registerState = runtime?.[REGISTER_PATCH_STATE];
1897
+ return {
1898
+ runtimeFound: runtime !== void 0,
1899
+ registerPatched: registerState !== void 0 && runtime?.["registerAdapter"] === registerState.wrappedRegister,
1900
+ adaptersInRuntime: total,
1901
+ adaptersPatched: patched,
1902
+ adapters: names,
1903
+ routes: source.current.routes.length,
1904
+ overrides: source.current.overrides.length
1905
+ };
1906
+ }
1907
+ function installPiAiHeaderTransforms(llm, source) {
1908
+ const installed = /* @__PURE__ */ new Map();
1909
+ const runtime = runtimeObjectOf(llm);
1910
+ let disposed = false;
1911
+ const install = (adapter) => {
1912
+ if (disposed) return;
1913
+ const adapterObject = objectOf(adapter);
1914
+ if (adapterObject === void 0 || typeof adapterObject["current"] !== "function") return;
1915
+ if (!installed.has(adapterObject)) installed.set(adapterObject, installPiAiHeaderTransform(adapterObject, source));
1916
+ };
1917
+ const refresh = () => {
1918
+ if (disposed) return;
1919
+ const adapters = runtime?.["adapters"];
1920
+ if (!(adapters instanceof Map)) return;
1921
+ const seen = /* @__PURE__ */ new Set();
1922
+ for (const registration of adapters.values()) {
1923
+ const registrationObject = objectOf(registration);
1924
+ const adapterObject = objectOf(registrationObject?.["adapter"]);
1925
+ if (adapterObject === void 0 || typeof adapterObject["current"] !== "function") continue;
1926
+ seen.add(adapterObject);
1927
+ install(adapterObject);
1928
+ }
1929
+ for (const [adapter, handle] of installed) {
1930
+ if (seen.has(adapter)) continue;
1931
+ handle.dispose();
1932
+ installed.delete(adapter);
1933
+ }
1934
+ };
1935
+ let registerHandle;
1936
+ const originalRegister = runtime?.["registerAdapter"];
1937
+ if (runtime !== void 0 && typeof originalRegister === "function") {
1938
+ const registerState = runtime[REGISTER_PATCH_STATE];
1939
+ if (registerState !== void 0 && runtime["registerAdapter"] === registerState.wrappedRegister) {
1940
+ registerState.users += 1;
1941
+ registerHandle = {
1942
+ get active() {
1943
+ return !disposed && registerState.users > 0;
1944
+ },
1945
+ dispose() {
1946
+ if (registerState.users <= 0) return;
1947
+ registerState.users -= 1;
1948
+ if (registerState.users > 0) return;
1949
+ if (runtime["registerAdapter"] === registerState.wrappedRegister) runtime["registerAdapter"] = registerState.originalRegister;
1950
+ if (runtime[REGISTER_PATCH_STATE] === registerState) delete runtime[REGISTER_PATCH_STATE];
1951
+ }
1952
+ };
1953
+ } else {
1954
+ const original = originalRegister;
1955
+ const wrappedRegister = function(...args) {
1956
+ const adapter = args[1];
1957
+ install(adapter);
1958
+ try {
1959
+ return original.apply(this, args);
1960
+ } finally {
1961
+ refresh();
1962
+ }
1963
+ };
1964
+ const state = {
1965
+ originalRegister: original,
1966
+ wrappedRegister,
1967
+ users: 1
1968
+ };
1969
+ runtime["registerAdapter"] = wrappedRegister;
1970
+ Object.defineProperty(runtime, REGISTER_PATCH_STATE, { configurable: true, value: state });
1971
+ registerHandle = {
1972
+ get active() {
1973
+ return !disposed && state.users > 0;
1974
+ },
1975
+ dispose() {
1976
+ if (state.users <= 0) return;
1977
+ state.users -= 1;
1978
+ if (state.users > 0) return;
1979
+ if (runtime["registerAdapter"] === state.wrappedRegister) runtime["registerAdapter"] = state.originalRegister;
1980
+ if (runtime[REGISTER_PATCH_STATE] === state) delete runtime[REGISTER_PATCH_STATE];
1981
+ }
1982
+ };
1983
+ }
1984
+ }
1985
+ refresh();
1986
+ return {
1987
+ refresh,
1988
+ dispose() {
1989
+ if (disposed) return;
1990
+ disposed = true;
1991
+ registerHandle?.dispose();
1992
+ for (const handle of installed.values()) handle.dispose();
1993
+ installed.clear();
1994
+ }
1995
+ };
1996
+ }
1997
+
1618
1998
  // src/headers-conflict.ts
1619
- import { existsSync, readFileSync } from "node:fs";
1999
+ import { existsSync, readFileSync as readFileSync2 } from "node:fs";
1620
2000
  import { createRequire } from "node:module";
1621
- import { dirname, join, resolve } from "node:path";
2001
+ import { dirname as dirname2, join as join2, resolve } from "node:path";
1622
2002
  var SIBLING_PACKAGES = [
1623
2003
  "dsh-client-masquerade",
1624
2004
  "dsh-llm-headers",
@@ -1630,20 +2010,20 @@ function searchRoots() {
1630
2010
  const roots = /* @__PURE__ */ new Set();
1631
2011
  const entry = process.argv[1];
1632
2012
  if (typeof entry === "string" && entry.length > 0) {
1633
- let dir = dirname(resolve(entry));
2013
+ let dir = dirname2(resolve(entry));
1634
2014
  for (let depth = 0; depth < 8; depth += 1) {
1635
- roots.add(join(dir, "node_modules"));
1636
- const parent = dirname(dir);
2015
+ roots.add(join2(dir, "node_modules"));
2016
+ const parent = dirname2(dir);
1637
2017
  if (parent === dir) break;
1638
2018
  dir = parent;
1639
2019
  }
1640
2020
  }
1641
- roots.add(join(process.cwd(), "node_modules"));
2021
+ roots.add(join2(process.cwd(), "node_modules"));
1642
2022
  try {
1643
2023
  const require2 = createRequire(import.meta.url);
1644
2024
  for (const name2 of SIBLING_PACKAGES) {
1645
2025
  try {
1646
- roots.add(join(dirname(dirname(dirname(require2.resolve(`${name2}/package.json`)))), "node_modules"));
2026
+ roots.add(join2(dirname2(dirname2(dirname2(require2.resolve(`${name2}/package.json`)))), "node_modules"));
1647
2027
  } catch {
1648
2028
  }
1649
2029
  }
@@ -1652,14 +2032,14 @@ function searchRoots() {
1652
2032
  return [...roots];
1653
2033
  }
1654
2034
  function findAdapterFile() {
1655
- const relative = join("@deepseek-ai", "dsh-llm-pi-ai", "lib", "index.js");
2035
+ const relative = join2("@deepseek-ai", "dsh-llm-pi-ai", "lib", "index.js");
1656
2036
  const candidates = [];
1657
2037
  try {
1658
2038
  const require2 = createRequire(import.meta.url);
1659
2039
  candidates.push(require2.resolve("@deepseek-ai/dsh-llm-pi-ai"));
1660
2040
  } catch {
1661
2041
  }
1662
- for (const root of searchRoots()) candidates.push(join(root, relative));
2042
+ for (const root of searchRoots()) candidates.push(join2(root, relative));
1663
2043
  for (const candidate of candidates) {
1664
2044
  if (existsSync(candidate)) return candidate;
1665
2045
  }
@@ -1670,7 +2050,7 @@ function adapterSourcePatched(source) {
1670
2050
  }
1671
2051
  function adapterPatchState(path) {
1672
2052
  try {
1673
- return adapterSourcePatched(readFileSync(path, "utf8")) ? "patched" : "stock";
2053
+ return adapterSourcePatched(readFileSync2(path, "utf8")) ? "patched" : "stock";
1674
2054
  } catch {
1675
2055
  return "unknown";
1676
2056
  }
@@ -1681,8 +2061,8 @@ function findSiblings() {
1681
2061
  for (const root of searchRoots()) {
1682
2062
  for (const name2 of SIBLING_PACKAGES) {
1683
2063
  if (seen.has(name2)) continue;
1684
- const dir = join(root, name2);
1685
- const manifest = join(dir, "package.json");
2064
+ const dir = join2(root, name2);
2065
+ const manifest = join2(dir, "package.json");
1686
2066
  if (!existsSync(manifest)) continue;
1687
2067
  seen.add(name2);
1688
2068
  found.push({ name: name2, path: dir });
@@ -1823,7 +2203,7 @@ function backfillRolePin(model, providers, route) {
1823
2203
 
1824
2204
  // src/index.ts
1825
2205
  var name = PLUGIN_ID;
1826
- var inject = ["settings"];
2206
+ var inject = ["settings", "llm"];
1827
2207
  var PI_NS = PI_AI_NS;
1828
2208
  var BOOT_RETRY_DELAYS_MS = [1e3, 2e3, 4e3, 8e3, 16e3, 3e4];
1829
2209
  var PROBE_TIMEOUT_MS = 15e3;
@@ -1835,6 +2215,116 @@ var Config = Schema.object({
1835
2215
  defaultGuard: Schema.boolean().default(true),
1836
2216
  uaOverride: Schema.boolean().default(true)
1837
2217
  });
2218
+ function providerProfileOf(section, route) {
2219
+ if (!isRecord(section)) return void 0;
2220
+ const providers = section["providers"];
2221
+ if (!isRecord(providers)) return void 0;
2222
+ const profile = providers[route];
2223
+ return isRecord(profile) ? profile : void 0;
2224
+ }
2225
+ function enabledRefOf(profile) {
2226
+ const ref = profile?.["apiKeyEnv"];
2227
+ return typeof ref === "string" && ref.length > 0 ? ref : void 0;
2228
+ }
2229
+ function isRefusal(answer) {
2230
+ return isRecord(answer) && answer["ok"] === false;
2231
+ }
2232
+ function refusalMessage(answer) {
2233
+ if (!isRecord(answer)) return void 0;
2234
+ const error = answer["error"];
2235
+ if (typeof error === "string") return error;
2236
+ if (isRecord(error) && typeof error["message"] === "string") return error["message"];
2237
+ return typeof answer["message"] === "string" ? answer["message"] : void 0;
2238
+ }
2239
+ function describeRecords(answer) {
2240
+ const candidate = isRecord(answer) && answer["value"] !== void 0 ? answer["value"] : answer;
2241
+ return isRecord(candidate) ? candidate : void 0;
2242
+ }
2243
+ async function storeCredential(credentials, ref, value) {
2244
+ const set = credentials?.set;
2245
+ if (credentials === void 0 || typeof set !== "function") {
2246
+ return "this deployment cannot write the credential store";
2247
+ }
2248
+ try {
2249
+ const answer = await set.call(credentials, ref, value);
2250
+ if (!isRefusal(answer)) return void 0;
2251
+ return refusalMessage(answer) ?? `the credential store refused ${ref}`;
2252
+ } catch (error) {
2253
+ return error instanceof Error ? error.message : String(error);
2254
+ }
2255
+ }
2256
+ async function forgetCredential(credentials, ref) {
2257
+ const unset = credentials?.unset;
2258
+ if (credentials === void 0 || typeof unset !== "function") {
2259
+ return "this deployment cannot write the credential store";
2260
+ }
2261
+ try {
2262
+ const answer = await unset.call(credentials, ref);
2263
+ if (!isRefusal(answer)) return void 0;
2264
+ return refusalMessage(answer) ?? `the credential store refused to forget ${ref}`;
2265
+ } catch (error) {
2266
+ return error instanceof Error ? error.message : String(error);
2267
+ }
2268
+ }
2269
+ async function credentialFacts(credentials, refs) {
2270
+ const out = {};
2271
+ if (credentials === void 0 || refs.length === 0) return out;
2272
+ const describe = credentials.describe;
2273
+ if (typeof describe === "function") {
2274
+ try {
2275
+ const records = describeRecords(await describe.call(credentials, [...refs]));
2276
+ for (const ref of refs) {
2277
+ const info = records?.[ref];
2278
+ if (isRecord(info) && typeof info["configured"] === "boolean") {
2279
+ out[ref] = { configured: info["configured"] };
2280
+ }
2281
+ }
2282
+ } catch {
2283
+ }
2284
+ }
2285
+ const resolve2 = credentials.resolve;
2286
+ for (const ref of refs) {
2287
+ try {
2288
+ const hit = await resolve2.call(credentials, ref);
2289
+ const value = hit !== void 0 && typeof hit.value === "string" ? hit.value : void 0;
2290
+ const configured = out[ref]?.configured ?? (value !== void 0 && value.length > 0);
2291
+ const masked = value === void 0 ? void 0 : maskKeyValue(value);
2292
+ out[ref] = masked === void 0 || masked.length === 0 ? { configured } : { configured, masked };
2293
+ } catch {
2294
+ }
2295
+ }
2296
+ return out;
2297
+ }
2298
+ async function credentialConfigured(credentials, refs) {
2299
+ const facts = await credentialFacts(credentials, refs);
2300
+ const out = {};
2301
+ for (const ref of refs) {
2302
+ const configured = facts[ref]?.configured;
2303
+ if (configured !== void 0) out[ref] = configured;
2304
+ }
2305
+ return out;
2306
+ }
2307
+ function isConflictError(error) {
2308
+ return isRecord(error) && error["code"] === "SETTINGS_CONFLICT";
2309
+ }
2310
+ async function readJsonBody(req, limit = 8192) {
2311
+ const decoder = new TextDecoder();
2312
+ let text = "";
2313
+ try {
2314
+ for await (const chunk of req) {
2315
+ text += typeof chunk === "string" ? chunk : decoder.decode(chunk, { stream: true });
2316
+ if (text.length > limit) return void 0;
2317
+ }
2318
+ } catch {
2319
+ return void 0;
2320
+ }
2321
+ if (text.length === 0) return void 0;
2322
+ try {
2323
+ return JSON.parse(text);
2324
+ } catch {
2325
+ return void 0;
2326
+ }
2327
+ }
1838
2328
  function isLoopbackHostname(hostname) {
1839
2329
  return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1";
1840
2330
  }
@@ -2114,6 +2604,23 @@ function apply(ctx, config = {}) {
2114
2604
  ctx.effect(() => () => {
2115
2605
  overlay.dispose();
2116
2606
  }, "dsh-model-think-level: fetch header overlay");
2607
+ let headerBridgeState = () => ({ stage: "not-installed" });
2608
+ const installPiAiBridge = (llm) => {
2609
+ const transforms = installPiAiHeaderTransforms(llm, overlaySource);
2610
+ transforms.refresh();
2611
+ headerBridgeState = () => describePiAiHeaderState(llm, overlaySource);
2612
+ ctx.on("llm/adapters-updated", () => transforms.refresh());
2613
+ ctx.effect(() => () => transforms.dispose(), "dsh-model-think-level: pi-ai request headers");
2614
+ };
2615
+ const availableLlm = ctx.llm;
2616
+ if (availableLlm === void 0) {
2617
+ ctx.inject(["llm"], (llmCtx) => {
2618
+ const llm = llmCtx.llm;
2619
+ if (llm !== void 0) installPiAiBridge(llm);
2620
+ });
2621
+ } else {
2622
+ installPiAiBridge(availableLlm);
2623
+ }
2117
2624
  const headerConflicts = detectHeaderConflicts();
2118
2625
  ctx.inject(["webServer"], (webServerCtx) => {
2119
2626
  ctx.effect(
@@ -2130,6 +2637,17 @@ function apply(ctx, config = {}) {
2130
2637
  return;
2131
2638
  }
2132
2639
  const url = new URL(req.url ?? "/", "http://x");
2640
+ if (url.searchParams.get("diag") === "1") {
2641
+ sendJson(res, 200, {
2642
+ ok: true,
2643
+ bridge: headerBridgeState(),
2644
+ overlay: {
2645
+ routes: overlaySource.current.routes.length,
2646
+ overrides: overlaySource.current.overrides.length
2647
+ }
2648
+ });
2649
+ return;
2650
+ }
2133
2651
  const route = url.searchParams.get("route") ?? "";
2134
2652
  const section = piSection();
2135
2653
  const profile = isRecord(section) && isRecord(section["providers"]) ? section["providers"][route] : void 0;
@@ -2224,6 +2742,260 @@ function apply(ctx, config = {}) {
2224
2742
  }),
2225
2743
  "dsh-model-think-level: raw-models probe route"
2226
2744
  );
2745
+ ctx.effect(
2746
+ () => webServerCtx.webServer.register({
2747
+ kind: "exact",
2748
+ path: DIAG_PATH,
2749
+ handler: (req, res) => {
2750
+ if (!isTrustedRequest(req)) {
2751
+ sendJson(res, 403, { ok: false, error: "forbidden" });
2752
+ return;
2753
+ }
2754
+ sendJson(res, 200, {
2755
+ ok: true,
2756
+ uaOverride: resolved.uaOverride,
2757
+ bridge: headerBridgeState(),
2758
+ overlay: {
2759
+ routes: overlaySource.current.routes.length,
2760
+ overrides: overlaySource.current.overrides.length
2761
+ }
2762
+ });
2763
+ }
2764
+ }),
2765
+ "dsh-model-think-level: header diagnostics route"
2766
+ );
2767
+ ctx.effect(
2768
+ () => webServerCtx.webServer.register({
2769
+ kind: "exact",
2770
+ path: PROVIDER_KEY_PATH,
2771
+ handler: async (req, res) => {
2772
+ res.setHeader("cache-control", "no-store");
2773
+ if (!isTrustedRequest(req)) {
2774
+ sendJson(res, 403, { ok: false, error: "forbidden" });
2775
+ return;
2776
+ }
2777
+ if (req.method !== "GET") {
2778
+ sendJson(res, 405, { ok: false, error: "method not allowed" });
2779
+ return;
2780
+ }
2781
+ const url = new URL(req.url ?? "/", "http://x");
2782
+ const route = url.searchParams.get("route") ?? "";
2783
+ const section = piSection();
2784
+ const profile = isRecord(section) && isRecord(section["providers"]) ? section["providers"][route] : void 0;
2785
+ if (!isRecord(profile)) {
2786
+ sendJson(res, 400, { ok: false, error: `no llm-pi-ai provider route "${route}"` });
2787
+ return;
2788
+ }
2789
+ const apiKeyEnv = typeof profile["apiKeyEnv"] === "string" ? profile["apiKeyEnv"] : void 0;
2790
+ const named = url.searchParams.get("ref") ?? "";
2791
+ const ref = named.length > 0 ? named === apiKeyEnv || hasKeyEntry(readKeyIndex(keyIndexFilePath()), route, named) ? named : void 0 : apiKeyEnv;
2792
+ if (ref === void 0) {
2793
+ sendJson(res, 404, {
2794
+ ok: false,
2795
+ error: named.length > 0 ? `provider route "${route}" lists no key "${named}"` : `provider route "${route}" stores no credential reference`
2796
+ });
2797
+ return;
2798
+ }
2799
+ let value;
2800
+ try {
2801
+ const credentials = ctx.get("credentials");
2802
+ const hit = credentials === void 0 ? void 0 : await credentials.resolve(ref);
2803
+ value = hit !== void 0 && typeof hit.value === "string" && hit.value.length > 0 ? hit.value : void 0;
2804
+ } catch {
2805
+ value = void 0;
2806
+ }
2807
+ if (value === void 0) {
2808
+ sendJson(res, 404, { ok: false, error: `no credential is configured for ${ref}` });
2809
+ return;
2810
+ }
2811
+ sendJson(res, 200, { ok: true, key: value });
2812
+ }
2813
+ }),
2814
+ "dsh-model-think-level: provider-key route"
2815
+ );
2816
+ ctx.effect(
2817
+ () => webServerCtx.webServer.register({
2818
+ kind: "exact",
2819
+ path: KEY_INDEX_PATH,
2820
+ handler: async (req, res) => {
2821
+ res.setHeader("cache-control", "no-store");
2822
+ if (!isTrustedRequest(req)) {
2823
+ sendJson(res, 403, { ok: false, error: "forbidden" });
2824
+ return;
2825
+ }
2826
+ if (req.method !== "GET" && req.method !== "POST") {
2827
+ sendJson(res, 405, { ok: false, error: "method not allowed" });
2828
+ return;
2829
+ }
2830
+ const url = new URL(req.url ?? "/", "http://x");
2831
+ const route = url.searchParams.get("route") ?? "";
2832
+ const entryOf = () => {
2833
+ try {
2834
+ const found = settings.describe().find((candidate) => candidate.ns === PI_NS);
2835
+ return found === void 0 ? void 0 : { value: found.value, revision: found.revision };
2836
+ } catch {
2837
+ return void 0;
2838
+ }
2839
+ };
2840
+ if (route.length === 0 || providerProfileOf(entryOf()?.value, route) === void 0) {
2841
+ sendJson(res, 400, { ok: false, error: `no llm-pi-ai provider route "${route}"` });
2842
+ return;
2843
+ }
2844
+ const credentials = ctx.get("credentials");
2845
+ const indexFile = keyIndexFilePath();
2846
+ const enabledNow = () => enabledRefOf(providerProfileOf(entryOf()?.value, route));
2847
+ const setEnabledKey = async (ref2) => {
2848
+ for (let attempt = 0; attempt < 2; attempt += 1) {
2849
+ const entry = entryOf();
2850
+ if (entry === void 0) return "the llm-pi-ai settings entry is unavailable";
2851
+ try {
2852
+ await settings.mutate(
2853
+ PI_NS,
2854
+ ref2 === void 0 ? [{ op: "unset", path: ["providers", route, "apiKeyEnv"] }] : [{ op: "set", path: ["providers", route, "apiKeyEnv"], value: ref2 }],
2855
+ entry.revision
2856
+ );
2857
+ return void 0;
2858
+ } catch (error) {
2859
+ if (attempt === 0 && isConflictError(error)) continue;
2860
+ return error instanceof Error ? error.message : String(error);
2861
+ }
2862
+ }
2863
+ return "the settings document kept changing; try again";
2864
+ };
2865
+ const payload = async () => {
2866
+ const enabledRef = enabledNow();
2867
+ const listed = keyEntriesOf(readKeyIndex(indexFile), route);
2868
+ const refs = listed.map((entry) => entry.ref);
2869
+ if (enabledRef !== void 0 && !refs.includes(enabledRef)) refs.push(enabledRef);
2870
+ const facts = await credentialFacts(credentials, refs);
2871
+ const entries = refs.map((ref2) => {
2872
+ const fact = facts[ref2];
2873
+ const view = {
2874
+ ref: ref2,
2875
+ enabled: ref2 === enabledRef,
2876
+ configured: fact?.configured ?? null
2877
+ };
2878
+ if (fact?.masked !== void 0) view.masked = fact.masked;
2879
+ const stored = listed.find((candidate) => candidate.ref === ref2);
2880
+ if (stored?.alias !== void 0) view.alias = stored.alias;
2881
+ return view;
2882
+ });
2883
+ return { ok: true, route, enabledRef: enabledRef ?? null, entries };
2884
+ };
2885
+ if (req.method === "GET") {
2886
+ sendJson(res, 200, await payload());
2887
+ return;
2888
+ }
2889
+ const body = await readJsonBody(req);
2890
+ const op = isRecord(body) && typeof body["op"] === "string" ? body["op"] : "";
2891
+ const ref = isRecord(body) && typeof body["ref"] === "string" ? body["ref"] : void 0;
2892
+ const alias = isRecord(body) ? normalizeKeyAlias(body["alias"]) : void 0;
2893
+ const value = isRecord(body) && typeof body["value"] === "string" ? body["value"] : void 0;
2894
+ const refuse = (error) => sendJson(res, 400, { ok: false, error });
2895
+ try {
2896
+ if (op === "add") {
2897
+ if (!isLegalKeyValue(value)) {
2898
+ refuse("a key must be printable ASCII without spaces");
2899
+ return;
2900
+ }
2901
+ const taken = keyEntriesOf(readKeyIndex(indexFile), route).map((candidate) => candidate.ref);
2902
+ const active = enabledNow();
2903
+ if (active !== void 0 && !taken.includes(active)) taken.push(active);
2904
+ const created = nextKeyRef(route, taken);
2905
+ const refused = await storeCredential(credentials, created, value);
2906
+ if (refused !== void 0) {
2907
+ refuse(refused);
2908
+ return;
2909
+ }
2910
+ updateKeyIndex((document) => withKeyEntry(document, route, created, alias), indexFile);
2911
+ if (enabledNow() === void 0) {
2912
+ const failed = await setEnabledKey(created);
2913
+ if (failed !== void 0) {
2914
+ refuse(failed);
2915
+ return;
2916
+ }
2917
+ }
2918
+ } else if (op === "enable") {
2919
+ const listed = readKeyIndex(indexFile);
2920
+ if (ref === void 0 || !hasKeyEntry(listed, route, ref)) {
2921
+ refuse("that key is not listed for this provider");
2922
+ return;
2923
+ }
2924
+ const previous = enabledNow();
2925
+ if (previous !== void 0 && previous !== ref && !hasKeyEntry(listed, route, previous)) {
2926
+ const leaving = previous;
2927
+ updateKeyIndex(
2928
+ (document) => hasKeyEntry(document, route, leaving) ? document : withKeyEntry(document, route, leaving, void 0),
2929
+ indexFile
2930
+ );
2931
+ }
2932
+ const failed = await setEnabledKey(ref);
2933
+ if (failed !== void 0) {
2934
+ refuse(failed);
2935
+ return;
2936
+ }
2937
+ } else if (op === "rename") {
2938
+ const known = ref !== void 0 && (hasKeyEntry(readKeyIndex(indexFile), route, ref) || ref === enabledNow());
2939
+ if (ref === void 0 || !known) {
2940
+ refuse("that key is not listed for this provider");
2941
+ return;
2942
+ }
2943
+ const target = ref;
2944
+ updateKeyIndex(
2945
+ (document) => hasKeyEntry(document, route, target) ? withKeyAlias(document, route, target, alias) : withKeyEntry(document, route, target, alias),
2946
+ indexFile
2947
+ );
2948
+ } else if (op === "value") {
2949
+ const known = ref !== void 0 && (hasKeyEntry(readKeyIndex(indexFile), route, ref) || ref === enabledNow());
2950
+ if (ref === void 0 || !known) {
2951
+ refuse("that key is not listed for this provider");
2952
+ return;
2953
+ }
2954
+ if (!isLegalKeyValue(value)) {
2955
+ refuse("a key must be printable ASCII without spaces");
2956
+ return;
2957
+ }
2958
+ const refused = await storeCredential(credentials, ref, value);
2959
+ if (refused !== void 0) {
2960
+ refuse(refused);
2961
+ return;
2962
+ }
2963
+ } else if (op === "remove") {
2964
+ const document = readKeyIndex(indexFile);
2965
+ if (ref === void 0 || !hasKeyEntry(document, route, ref) && ref !== enabledNow()) {
2966
+ refuse("that key is not listed for this provider");
2967
+ return;
2968
+ }
2969
+ if (ref === enabledNow()) {
2970
+ const remaining = keyEntriesOf(document, route).map((candidate) => candidate.ref).filter((candidate) => candidate !== ref);
2971
+ const failed = await setEnabledKey(remaining[0]);
2972
+ if (failed !== void 0) {
2973
+ refuse(failed);
2974
+ return;
2975
+ }
2976
+ }
2977
+ const configured = (await credentialConfigured(credentials, [ref]))[ref];
2978
+ if (configured !== false) {
2979
+ const refused = await forgetCredential(credentials, ref);
2980
+ if (refused !== void 0) {
2981
+ refuse(refused);
2982
+ return;
2983
+ }
2984
+ }
2985
+ updateKeyIndex((document2) => withoutKeyEntry(document2, route, ref), indexFile);
2986
+ } else {
2987
+ refuse(`unknown key operation "${op}"`);
2988
+ return;
2989
+ }
2990
+ } catch (error) {
2991
+ sendJson(res, 500, { ok: false, error: error instanceof Error ? error.message : String(error) });
2992
+ return;
2993
+ }
2994
+ sendJson(res, 200, await payload());
2995
+ }
2996
+ }),
2997
+ "dsh-model-think-level: key index route"
2998
+ );
2227
2999
  ctx.effect(
2228
3000
  () => webServerCtx.webServer.register({
2229
3001
  kind: "exact",