@siliconflow-official/dsh-llm-siliconflow 0.2.0-rc.1 → 0.2.0-rc.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/README.md CHANGED
@@ -34,6 +34,14 @@ dsh-siliconflow-setup
34
34
  export SILICONFLOW_API_KEY=sk-... # 或写入 $DSH_HOME/.credentials.yaml
35
35
  ```
36
36
 
37
+ 写入 `.credentials.yaml` 时使用 dsh ≥ 0.1.2 的 version-1 布局(`version: 1` + `refs:` 嵌套);向导会识别并就地升级本向导早期版本写入的 pre-release 顶层扁平布局,其他无法识别的文档会明确报错而不是被改写:
38
+
39
+ ```yaml
40
+ version: 1
41
+ refs:
42
+ SILICONFLOW_API_KEY: sk-...
43
+ ```
44
+
37
45
  在包发布到 npm 之前,先用 `pnpm install && pnpm build` 构建出 `lib/`,再从本地路径安装:
38
46
 
39
47
  ```sh
package/lib/bin.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import { a as PUBLIC_BASE_URL, g as discoverChatModels, i as PROVIDER, n as DEFAULT_API_KEY_ENV, r as DEFAULT_MODELS } from "./types-BWDupDnP.js";
2
+ import { a as PUBLIC_BASE_URL, g as discoverChatModels, i as PROVIDER, n as DEFAULT_API_KEY_ENV, r as DEFAULT_MODELS } from "./types-iMqgaeX4.js";
3
3
  import { createInterface } from "node:readline/promises";
4
4
  import { stdin, stdout } from "node:process";
5
5
  import { mkdir, readFile, writeFile } from "node:fs/promises";
6
6
  import { homedir } from "node:os";
7
7
  import { dirname, join, resolve } from "node:path";
8
- import { parseDocument } from "yaml";
8
+ import { Pair, YAMLMap, parseDocument } from "yaml";
9
9
  //#region lib/types/setup.js
10
10
  /**
11
11
  * Interactive setup wizard core for {@link @siliconflow-official/dsh-llm-siliconflow}:
@@ -45,11 +45,81 @@ function settingsPath(home) {
45
45
  function isEnoent(error) {
46
46
  return error.code === "ENOENT";
47
47
  }
48
+ /** The credentials document layout version this wizard reads and writes. */
49
+ const CREDENTIALS_LAYOUT_VERSION = 1;
50
+ /** POSIX identifier rule the credentials seam addresses references by. */
51
+ const REF_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
48
52
  /**
49
- * Read one credential reference from a comment-preserving document.
53
+ * Recognize one parsed credentials document.
54
+ * @param document - the parsed document; parse errors make it unrecognizable.
55
+ * @returns the admitted layout with its references — plus, under `extraKeys`,
56
+ * any top-level key a pre-fix release of this wizard left beside `version`,
57
+ * held out of `entries` so reads treat them as absent while the write path
58
+ * folds them back under `refs` — or `undefined` when the document does not
59
+ * parse, holds an unknown `version`, carries a `refs` section that is not a
60
+ * mapping of reference names to non-empty strings, or holds any other
61
+ * top-level entry this build cannot attribute to its own predecessor.
62
+ */
63
+ function admitCredentialsDocument(document) {
64
+ if (document.errors.length > 0) return void 0;
65
+ const root = document.toJS() ?? {};
66
+ if (typeof root !== "object" || root === null) return void 0;
67
+ const fields = root;
68
+ const entries = /* @__PURE__ */ new Map();
69
+ if (!("version" in fields)) {
70
+ for (const [key, value] of Object.entries(fields)) {
71
+ if (!REF_NAME_PATTERN.test(key)) return void 0;
72
+ if (typeof value !== "string" || value.length === 0) return void 0;
73
+ entries.set(key, value);
74
+ }
75
+ return {
76
+ kind: "flat",
77
+ entries
78
+ };
79
+ }
80
+ if (fields.version !== CREDENTIALS_LAYOUT_VERSION) return void 0;
81
+ const refs = fields["refs"];
82
+ if (refs !== void 0) {
83
+ if (typeof refs !== "object" || refs === null) return void 0;
84
+ for (const [key, value] of Object.entries(refs)) {
85
+ if (!REF_NAME_PATTERN.test(key)) return void 0;
86
+ if (typeof value !== "string" || value.length === 0) return void 0;
87
+ entries.set(key, value);
88
+ }
89
+ }
90
+ const extraKeys = /* @__PURE__ */ new Map();
91
+ for (const [key, value] of Object.entries(fields)) {
92
+ if (key === "version" || key === "refs" || key === "records") continue;
93
+ if (!REF_NAME_PATTERN.test(key) || typeof value !== "string" || value.length === 0) return void 0;
94
+ extraKeys.set(key, value);
95
+ }
96
+ return {
97
+ kind: "versioned",
98
+ entries,
99
+ ...extraKeys.size > 0 ? { extraKeys } : {}
100
+ };
101
+ }
102
+ /**
103
+ * Nest a pre-release flat document under `refs:` with a `version` stamp. The
104
+ * whole current root — every flat entry, comments included — becomes the
105
+ * `refs` section verbatim, so every other provider's key migrates in the same
106
+ * write; the new root carries `version` and `refs` in that order, matching how
107
+ * `dsh-credentials-local` writes one from scratch.
108
+ * @param document - the admitted flat document to upgrade in place.
109
+ */
110
+ function upgradeFlatDocument(document) {
111
+ const refs = document.contents instanceof YAMLMap ? document.contents : new YAMLMap();
112
+ const root = new YAMLMap();
113
+ root.add(new Pair("version", CREDENTIALS_LAYOUT_VERSION));
114
+ root.add(new Pair("refs", refs));
115
+ document.contents = root;
116
+ }
117
+ /**
118
+ * Read one credential reference from a versioned or pre-release flat document.
50
119
  * @param path - the credentials document path.
51
- * @param keyEnv - the top-level reference name (e.g. `SILICONFLOW_API_KEY`).
52
- * @returns the stored value, or `undefined` when absent or the file is missing.
120
+ * @param keyEnv - the reference name to read (e.g. `SILICONFLOW_API_KEY`).
121
+ * @returns the stored value, or `undefined` when the reference is absent, the
122
+ * file is missing, or the document is not a recognizable layout.
53
123
  */
54
124
  async function readCredential(path, keyEnv) {
55
125
  let text;
@@ -59,18 +129,31 @@ async function readCredential(path, keyEnv) {
59
129
  if (isEnoent(error)) return void 0;
60
130
  throw error;
61
131
  }
62
- const value = parseDocument(text).toJS()?.[keyEnv];
63
- return typeof value === "string" && value.length > 0 ? value : void 0;
132
+ const admitted = admitCredentialsDocument(parseDocument(text));
133
+ if (admitted === void 0) return void 0;
134
+ return admitted.entries.get(keyEnv);
64
135
  }
65
136
  /**
66
- * Set one credential reference, preserving every other entry and comment.
137
+ * Write one credential reference into the versioned layout, preserving every
138
+ * other entry and comment. A pre-release flat document is upgraded in place,
139
+ * and a top-level key a pre-fix release of this wizard left beside `version`
140
+ * is folded back under `refs`, so one run repairs the file its predecessor
141
+ * corrupted. An unrecognized document fails loud instead of being rewritten —
142
+ * a silent rewrite would hide why the running harness rejects it.
67
143
  * @param path - the credentials document path; created when absent.
68
- * @param keyEnv - the top-level reference name to write.
144
+ * @param keyEnv - the reference name to write.
69
145
  * @param key - the value.
146
+ * @throws when the document exists but is not a recognizable credentials layout.
70
147
  */
71
148
  async function writeCredential(path, keyEnv, key) {
72
149
  const doc = await loadDocument(path);
73
- doc.set(keyEnv, key);
150
+ const admitted = admitCredentialsDocument(doc);
151
+ if (admitted === void 0) throw new Error(`setup: ${path} is not a recognizable credentials document (expected version 1 with a refs section, or the pre-release flat layout); fix it before running setup`);
152
+ if (admitted.kind === "flat") upgradeFlatDocument(doc);
153
+ for (const extra of admitted.extraKeys?.keys() ?? []) doc.deleteIn([extra]);
154
+ for (const [extra, value] of admitted.extraKeys ?? /* @__PURE__ */ new Map()) doc.setIn(["refs", extra], value);
155
+ doc.setIn(["version"], CREDENTIALS_LAYOUT_VERSION);
156
+ doc.setIn(["refs", keyEnv], key);
74
157
  await persistDocument(path, doc);
75
158
  }
76
159
  /**
package/lib/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { _ as listingUrl, a as PUBLIC_BASE_URL, c as name, d as DEFAULT_MAX_TOKENS, f as DEFAULT_STREAM_IDLE_TIMEOUT_MS, g as discoverChatModels, h as inferInputModalities, i as PROVIDER, l as resolveAdapterOptions, m as SiliconFlowAdapter, n as DEFAULT_API_KEY_ENV, o as apply, p as DISCOVERY_TTL_MS, r as DEFAULT_MODELS, s as inject, t as Config, u as DEFAULT_CONTEXT_WINDOW, v as readListing } from "./types-BWDupDnP.js";
1
+ import { _ as listingUrl, a as PUBLIC_BASE_URL, c as name, d as DEFAULT_MAX_TOKENS, f as DEFAULT_STREAM_IDLE_TIMEOUT_MS, g as discoverChatModels, h as inferInputModalities, i as PROVIDER, l as resolveAdapterOptions, m as SiliconFlowAdapter, n as DEFAULT_API_KEY_ENV, o as apply, p as DISCOVERY_TTL_MS, r as DEFAULT_MODELS, s as inject, t as Config, u as DEFAULT_CONTEXT_WINDOW, v as readListing } from "./types-iMqgaeX4.js";
2
2
  export { Config, DEFAULT_API_KEY_ENV, DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_TOKENS, DEFAULT_MODELS, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DISCOVERY_TTL_MS, PROVIDER, PUBLIC_BASE_URL, SiliconFlowAdapter, apply, discoverChatModels, inferInputModalities, inject, listingUrl, name, readListing, resolveAdapterOptions };
@@ -56,17 +56,24 @@ export declare function credentialsPath(home: string): string;
56
56
  /** The settings document path under a harness home. */
57
57
  export declare function settingsPath(home: string): string;
58
58
  /**
59
- * Read one credential reference from a comment-preserving document.
59
+ * Read one credential reference from a versioned or pre-release flat document.
60
60
  * @param path - the credentials document path.
61
- * @param keyEnv - the top-level reference name (e.g. `SILICONFLOW_API_KEY`).
62
- * @returns the stored value, or `undefined` when absent or the file is missing.
61
+ * @param keyEnv - the reference name to read (e.g. `SILICONFLOW_API_KEY`).
62
+ * @returns the stored value, or `undefined` when the reference is absent, the
63
+ * file is missing, or the document is not a recognizable layout.
63
64
  */
64
65
  export declare function readCredential(path: string, keyEnv: string): Promise<string | undefined>;
65
66
  /**
66
- * Set one credential reference, preserving every other entry and comment.
67
+ * Write one credential reference into the versioned layout, preserving every
68
+ * other entry and comment. A pre-release flat document is upgraded in place,
69
+ * and a top-level key a pre-fix release of this wizard left beside `version`
70
+ * is folded back under `refs`, so one run repairs the file its predecessor
71
+ * corrupted. An unrecognized document fails loud instead of being rewritten —
72
+ * a silent rewrite would hide why the running harness rejects it.
67
73
  * @param path - the credentials document path; created when absent.
68
- * @param keyEnv - the top-level reference name to write.
74
+ * @param keyEnv - the reference name to write.
69
75
  * @param key - the value.
76
+ * @throws when the document exists but is not a recognizable credentials layout.
70
77
  */
71
78
  export declare function writeCredential(path: string, keyEnv: string, key: string): Promise<void>;
72
79
  /**
@@ -1,8 +1,8 @@
1
1
  import z from "@deepseek-ai/schemastery";
2
- import { CONTEXT_WINDOW_EXCEEDED_CODE, CallId, EMPTY_RESPONSE_CODE, LlmAdapter, LlmError, ProviderRequestId, QUOTA_EXCEEDED_CODE, RetryPolicySchema, assertUsableApiKey, attributionHeaders, isContextWindowExceededError, isQuotaExceededError, resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
2
+ import { CONTEXT_WINDOW_EXCEEDED_CODE, EMPTY_RESPONSE_CODE, LlmAdapter, LlmError, ProviderRequestId, QUOTA_EXCEEDED_CODE, RetryPolicySchema, ToolCallId, assertUsableApiKey, attributionHeaders, isContextWindowExceededError, isQuotaExceededError, resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
3
3
  import { credentialRef } from "@deepseek-ai/dsh-credentials";
4
4
  import { launchEnvironmentOf } from "@deepseek-ai/dsh-launch-environment";
5
- import { deepEqualJson, installSettingsSection, settingsNamespace } from "@deepseek-ai/dsh-settings";
5
+ import { deepEqualJson } from "@deepseek-ai/dsh-util-values";
6
6
  import { MAX_TIMER_DELAY_MS, idleWatchdog, timeoutOf } from "@deepseek-ai/dsh-timeout";
7
7
  import { getOrCreateAnonymousUserId } from "@deepseek-ai/dsh-anonymous-user-id";
8
8
  import { EventSourceParserStream } from "eventsource-parser/stream";
@@ -408,7 +408,7 @@ function closeBlock(block) {
408
408
  };
409
409
  case "tool-call": return {
410
410
  type: "tool-call",
411
- id: CallId(block.callId ?? ""),
411
+ id: ToolCallId(block.callId ?? ""),
412
412
  name: block.name ?? "",
413
413
  arguments: block.text
414
414
  };
@@ -523,7 +523,7 @@ async function* translate(payloads) {
523
523
  yield {
524
524
  type: "tool-call-delta",
525
525
  index: block.index,
526
- id: CallId(block.callId ?? ""),
526
+ id: ToolCallId(block.callId ?? ""),
527
527
  ...block.name !== void 0 ? { name: block.name } : {},
528
528
  argumentsDelta: fragment
529
529
  };
@@ -896,7 +896,7 @@ var SiliconFlowAdapter = class extends LlmAdapter {
896
896
  */
897
897
  const name = "llm-siliconflow";
898
898
  const inject = ["llm"];
899
- const NS = settingsNamespace("llm-siliconflow");
899
+ const NS = "llm-siliconflow";
900
900
  /** Credential reference this plugin reads by default, also used by the setup CLI. */
901
901
  const DEFAULT_API_KEY_ENV = "SILICONFLOW_API_KEY";
902
902
  /** The single provider route this plugin owns. */
@@ -1125,11 +1125,13 @@ function apply(ctx, config) {
1125
1125
  registration.replace([PROVIDER]);
1126
1126
  registeredPolicy = policy;
1127
1127
  };
1128
- installSettingsSection(ctx, NS, Config, config, {
1129
- setSource: (source) => {
1130
- current = source;
1131
- },
1132
- onChange: ensureRegistrationFacts
1128
+ ctx.inject(["settings"], (settingsCtx) => {
1129
+ settingsCtx.settings.installSection(ctx, NS, Config, config, {
1130
+ setSource: (source) => {
1131
+ current = source;
1132
+ },
1133
+ onChange: ensureRegistrationFacts
1134
+ });
1133
1135
  });
1134
1136
  }
1135
1137
  //#endregion
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@siliconflow-official/dsh-llm-siliconflow",
3
3
  "description": "SiliconFlow (OpenAI-compatible) chat-completions adapter plugin for the DeepSeek Harness LLM seam",
4
- "version": "0.2.0-rc.1",
4
+ "version": "0.2.0-rc.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -51,7 +51,8 @@
51
51
  "@deepseek-ai/dsh-launch-environment": ">=0.0.1-rc.0",
52
52
  "@deepseek-ai/dsh-llm": ">=0.0.1-rc.0",
53
53
  "@deepseek-ai/dsh-settings": ">=0.0.1-rc.0",
54
- "@deepseek-ai/dsh-timeout": ">=0.0.1-rc.0"
54
+ "@deepseek-ai/dsh-timeout": ">=0.0.1-rc.0",
55
+ "@deepseek-ai/dsh-util-values": "*"
55
56
  },
56
57
  "dependencies": {
57
58
  "@deepseek-ai/schemastery": "^3.18.1",
@@ -59,18 +60,18 @@
59
60
  "yaml": "^2.9.0"
60
61
  },
61
62
  "devDependencies": {
62
- "@deepseek-ai/cordis": "^4.0.1",
63
- "@deepseek-ai/dsh-anonymous-user-id": ">=0.0.1-rc.0",
64
- "@deepseek-ai/dsh-attachment": ">=0.0.1-rc.0",
65
- "@deepseek-ai/dsh-credentials": ">=0.0.1-rc.0",
66
- "@deepseek-ai/dsh-invariants": ">=0.0.1-rc.0",
67
- "@deepseek-ai/dsh-launch-environment": ">=0.0.1-rc.0",
68
- "@deepseek-ai/dsh-llm": ">=0.0.1-rc.0",
69
- "@deepseek-ai/dsh-settings": ">=0.0.1-rc.0",
70
- "@deepseek-ai/dsh-timeout": ">=0.0.1-rc.0",
63
+ "@deepseek-ai/cordis": "^4.0.2",
64
+ "@deepseek-ai/dsh-anonymous-user-id": "0.1.5-rc.2",
65
+ "@deepseek-ai/dsh-attachment": "0.1.5-rc.2",
66
+ "@deepseek-ai/dsh-credentials": "0.1.5-rc.2",
67
+ "@deepseek-ai/dsh-invariants": "0.1.5-rc.2",
68
+ "@deepseek-ai/dsh-launch-environment": "0.1.5-rc.2",
69
+ "@deepseek-ai/dsh-llm": "0.1.5-rc.2",
70
+ "@deepseek-ai/dsh-settings": "0.1.5-rc.2",
71
+ "@deepseek-ai/dsh-timeout": "0.1.5-rc.2",
72
+ "@deepseek-ai/dsh-util-values": "0.1.5-rc.2",
71
73
  "@types/node": "^22.0.0",
72
74
  "tsdown": "^0.22.0",
73
- "typescript": "^6.0.0",
74
- "unrun": "^0.3.1"
75
+ "typescript": "^6.0.0"
75
76
  }
76
77
  }