@eduwork/dsh-oidc 0.1.0-alpha.11 → 0.1.0
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/CHANGELOG.en.md +18 -0
- package/CHANGELOG.md +18 -0
- package/CODE_OF_CONDUCT.en.md +17 -0
- package/CODE_OF_CONDUCT.md +17 -0
- package/CONTRIBUTING.en.md +56 -0
- package/CONTRIBUTING.md +56 -0
- package/GOVERNANCE.en.md +41 -0
- package/GOVERNANCE.md +41 -0
- package/MAINTAINERS.en.md +13 -0
- package/MAINTAINERS.md +13 -0
- package/README.en.md +6 -6
- package/README.md +5 -5
- package/SECURITY.en.md +45 -0
- package/SECURITY.md +45 -0
- package/SUPPORT.en.md +15 -0
- package/SUPPORT.md +15 -0
- package/THIRD_PARTY_NOTICES.en.md +3 -3
- package/THIRD_PARTY_NOTICES.md +3 -3
- package/docs/EDUWORK-MIGRATION.en.md +3 -3
- package/docs/EDUWORK-MIGRATION.md +3 -3
- package/docs/compatibility.en.md +3 -2
- package/docs/compatibility.md +3 -2
- package/docs/decisions/0001-one-plugin-composition-boundary.en.md +1 -1
- package/docs/decisions/0001-one-plugin-composition-boundary.md +1 -1
- package/docs/dsh-integration.en.md +3 -3
- package/docs/dsh-integration.md +3 -3
- package/docs/enterprise-profile.en.md +2 -2
- package/docs/enterprise-profile.md +2 -2
- package/docs/getting-started.en.md +4 -8
- package/docs/getting-started.md +4 -8
- package/docs/release-checklist.en.md +9 -6
- package/docs/release-checklist.md +9 -6
- package/lib/client.js +4 -0
- package/lib/profile.js +43 -15
- package/lib/provider/index.js +21 -2
- package/lib/provider/transform-adapter.js +1 -1
- package/package.json +43 -20
- package/schema/enterprise-profile.v1alpha1.schema.json +18 -4
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
**简体中文** | [English](EDUWORK-MIGRATION.en.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
从 `0.1.0-alpha.11` 起,npm 包改用 `@eduwork/dsh-oidc`,替代旧的 `dsh-oidc`;`0.1.0` 是完成该迁移后的首个稳定语义版本。npm `eduwork` 组织已创建;GitHub 仓库和本地 checkout 目录继续使用 `dsh-oidc`。包的当前发布状态以 npm registry 为准。
|
|
6
6
|
|
|
7
7
|
## 安装与迁移
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
|
-
dsh plugin --profile web add @eduwork/dsh-oidc@0.1.0
|
|
10
|
+
dsh plugin --profile web add @eduwork/dsh-oidc@0.1.0
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
已有 Profile 先备份 package.json 与 cordis.patch.yml,再更新依赖和 dsh.profile.bundles;手写 patch 的模块路径 name 也需切换。不要同时启用新旧两份插件,切换后重启 Host。旧版本和新作用域版本是不同 npm 包,旧包的更新不会自动迁移安装。
|
|
@@ -20,4 +20,4 @@ dsh plugin --profile web add @eduwork/dsh-oidc@0.1.0-alpha.11
|
|
|
20
20
|
|
|
21
21
|
## 发布范围
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
`0.1.0` 将包身份稳定在 `@eduwork/dsh-oidc`,并精确适配 DSH `0.1.2-rc.1`。构建、测试、文档、开源和 tarball 检查针对本次变更执行;这不等于真实学校登录、真实邮件发送或生产部署验收。生产采用仍须完成公开发布检查表中的完整部署验收。旧包和 scoped alpha 保持可安装,不撤回旧版本。
|
package/docs/compatibility.en.md
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
| dsh-oidc | Node.js | DSH | pi-ai | Status |
|
|
8
8
|
| --- | --- | --- | --- | --- |
|
|
9
|
+
| `0.1.0` | 22, 24 | `0.1.2-rc.1` / `a66e4702…` | `^0.84.2` (locked at `0.84.4`) | Exact peer closure, Host/Client contract checks, clean npm installation, and isolated Web/RPC acceptance. |
|
|
9
10
|
| `0.1.0-alpha.11` | 22, 24 | Declared baseline remains `0.1.2-alpha.2`; separate mainline `0.1.2-rc.1` configuration RPC probe | `^0.84.2` | npm scope migration with persistent contracts retained; the rc.1 probe is not full compatibility acceptance. |
|
|
10
11
|
| `0.1.0-alpha.10` | 22, 24 | `0.1.2-alpha.2` / `0a53fb55…` | `^0.84.2` (`0.84.4` in npm/source Runtimes) | Migrated to `SettingsProvider.installSection()`; full checks pass through both npm and source release-pack paths. |
|
|
11
12
|
| `0.1.0-alpha.9` | 22, 24 | `0.1.2-alpha.1` / `cd5ef814…` | `^0.84.2` (`0.84.4` in the reviewed source Runtime) | Web and native consume only standard Enterprise Profiles; product institution-catalog conversion is completely outside the plugin. |
|
|
@@ -18,7 +19,7 @@
|
|
|
18
19
|
| `0.1.0-alpha.2` | 22, 24 (development) | `0.1.1-rc.2` / `b150a551…` | `0.82.1` | Standard UserInfo name presentation unified across Web and native adapters; real deployment acceptance pending. |
|
|
19
20
|
| `0.1.0-alpha.1` | 22, 24 (development) | `0.1.1-rc.2` / `b150a551…` | `0.82.1` | Unit/build/package baseline; real deployment acceptance still required. |
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
The supported current line is `0.1.0` with the exact DSH `0.1.2-rc.1` peers declared in `package.json`; alpha rows are historical validation records only. Other versions may install only after explicit peer override and are untested.
|
|
22
23
|
|
|
23
24
|
## Contract versions
|
|
24
25
|
|
|
@@ -56,6 +57,6 @@ No public tag/npm publish until all of the following pass:
|
|
|
56
57
|
- native desktop no-regression acceptance;
|
|
57
58
|
- OIDC negative tests and Key Binding authorization tests;
|
|
58
59
|
- documentation/version/changelog update;
|
|
59
|
-
-
|
|
60
|
+
- independent technical review, CI/focused regression evidence, and a recorded maintainer decision for authentication, credential, build, or release workflow changes; add independent human approval after a second maintainer joins.
|
|
60
61
|
|
|
61
62
|
See [the public release checklist](release-checklist.en.md) for the operator checklist.
|
package/docs/compatibility.md
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
| dsh-oidc | Node.js | DSH | pi-ai | 状态 |
|
|
8
8
|
| --- | --- | --- | --- | --- |
|
|
9
|
+
| `0.1.0` | 22、24 | `0.1.2-rc.1` / `a66e4702…` | `^0.84.2`(锁定为 `0.84.4`) | 精确 peer 闭包、Host/Client 契约检查、干净 npm 安装和隔离 Web/RPC 验收。 |
|
|
9
10
|
| `0.1.0-alpha.11` | 22、24 | 声明基线仍为 `0.1.2-alpha.2`;另有主线 `0.1.2-rc.1` 隔离配置 RPC 探针 | `^0.84.2` | npm 作用域迁移;保留数据协议;不将 rc.1 探针视为完整版本兼容验收。 |
|
|
10
11
|
| `0.1.0-alpha.10` | 22、24 | `0.1.2-alpha.2` / `0a53fb55…` | `^0.84.2`(npm/源码 Runtime 中为 `0.84.4`) | 迁移到 `SettingsProvider.installSection()`;npm 与源码 release-pack 双路径通过完整检查。 |
|
|
11
12
|
| `0.1.0-alpha.9` | 22、24 | `0.1.2-alpha.1` / `cd5ef814…` | `^0.84.2`(已审查源码 Runtime 中为 `0.84.4`) | Web/native 只消费标准 Enterprise Profile;产品机构目录转换彻底移出插件。 |
|
|
@@ -18,7 +19,7 @@
|
|
|
18
19
|
| `0.1.0-alpha.2` | 22、24(开发) | `0.1.1-rc.2` / `b150a551…` | `0.82.1` | Web 与 native adapter 统一使用标准 UserInfo 姓名显示;尚待真实部署验收。 |
|
|
19
20
|
| `0.1.0-alpha.1` | 22、24(开发) | `0.1.1-rc.2` / `b150a551…` | `0.82.1` | 单元测试、构建和打包基线;仍需真实部署验收。 |
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
当前受支持线是 `0.1.0` 与 `package.json` 中声明的精确 DSH `0.1.2-rc.1` peer 组合;alpha 行只保留历史验证记录。其他版本即使通过显式 peer override 安装,也属于未经测试的组合。
|
|
22
23
|
|
|
23
24
|
## 契约版本
|
|
24
25
|
|
|
@@ -56,6 +57,6 @@
|
|
|
56
57
|
- native 桌面无回退验收;
|
|
57
58
|
- OIDC 反向测试和 Key Binding 授权测试;
|
|
58
59
|
- 文档、版本和变更日志更新;
|
|
59
|
-
-
|
|
60
|
+
- 对认证、凭据、构建或发布流程变更完成独立技术复核、CI/专项回归并记录维护者决定;增加第二位维护者后再加入独立人工批准。
|
|
60
61
|
|
|
61
62
|
操作检查项见[公开发布检查表](release-checklist.md)。
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## Supported host baseline
|
|
6
6
|
|
|
7
|
-
The current compatibility baseline is DeepSeek Harness `0.1.2-
|
|
7
|
+
The current compatibility baseline is DeepSeek Harness `0.1.2-rc.1`, upstream commit `a66e4702047846cdaa10c66c9d3df3951f5ea70d`. Because DSH remains prerelease software, this package pins the complete DSH peer closure to that exact version and rejects a mixed DSH tree during checks.
|
|
8
8
|
|
|
9
9
|
The plugin uses public package exports rather than copied DSH source:
|
|
10
10
|
|
|
@@ -59,7 +59,7 @@ The client descriptor uses strict Zod codecs. Configuration sent to the browser
|
|
|
59
59
|
`dsh-oidc` declares its own default Web-first Bundle patch. Install it directly from npm into the official Web profile without authoring a wrapper Bundle:
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
|
-
dsh plugin --profile web add @eduwork/dsh-oidc@0.1.0
|
|
62
|
+
dsh plugin --profile web add @eduwork/dsh-oidc@0.1.0
|
|
63
63
|
```
|
|
64
64
|
|
|
65
65
|
For auditing, development, or validating unpublished changes, install a reviewed local checkout instead:
|
|
@@ -72,7 +72,7 @@ npm run check
|
|
|
72
72
|
dsh plugin --profile web add .
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
The local-path install links the checkout into the Profile, so the source directory must remain available. It does not scan the current workspace. Team deployments should
|
|
75
|
+
The local-path install links the checkout into the Profile, so the source directory must remain available. It does not scan the current workspace. Team deployments should pin a reviewed, exact npm version and must not mix another DSH prerelease line into the same Profile.
|
|
76
76
|
|
|
77
77
|
The shipped patch mounts exactly one `enterprise-oidc` instance using `DSH_OIDC_ENTERPRISE_PROFILE`. The Web backend requires the DSH WebServer to listen exactly on `127.0.0.1` and builds the fixed `/oauth/callback` from its actual port; no public callback-origin setting is accepted. It deliberately does not set `agent-default-model`, because Provider and model IDs belong to the deployment's Enterprise Profile and users can select an available enterprise model in DSH.
|
|
78
78
|
|
package/docs/dsh-integration.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## 支持的宿主基线
|
|
6
6
|
|
|
7
|
-
当前兼容基线为 DeepSeek Harness `0.1.2-
|
|
7
|
+
当前兼容基线为 DeepSeek Harness `0.1.2-rc.1`,上游 commit `a66e4702047846cdaa10c66c9d3df3951f5ea70d`。DSH 仍处于预发布阶段,因此本包把完整 DSH peer 闭包固定到该精确版本,并在检查中拒绝混入其他 DSH 版本。
|
|
8
8
|
|
|
9
9
|
插件只使用公开 package export,不复制 DSH 源码:
|
|
10
10
|
|
|
@@ -59,7 +59,7 @@ Client 描述符使用严格 Zod codec。发送给浏览器的配置不包含 is
|
|
|
59
59
|
`dsh-oidc` 自带默认的 Web-first Bundle patch,可以直接从 npm 安装到官方 Web Profile,无需再编写 wrapper Bundle:
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
|
-
dsh plugin --profile web add @eduwork/dsh-oidc@0.1.0
|
|
62
|
+
dsh plugin --profile web add @eduwork/dsh-oidc@0.1.0
|
|
63
63
|
```
|
|
64
64
|
|
|
65
65
|
需要审计、开发或验证尚未发布的改动时,可以安装经过审查的本地 checkout:
|
|
@@ -72,7 +72,7 @@ npm run check
|
|
|
72
72
|
dsh plugin --profile web add .
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
本地路径安装会把 checkout 链接到 Profile
|
|
75
|
+
本地路径安装会把 checkout 链接到 Profile,因此源码目录必须持续存在。它不会扫描当前工作区。团队部署应固定经过复核的 npm 精确版本;不要在同一 Profile 中混装其他 DSH 预发布线。
|
|
76
76
|
|
|
77
77
|
随包 patch 使用 `DSH_OIDC_ENTERPRISE_PROFILE` 挂载且只挂载一个 `enterprise-oidc` 实例。Web backend 要求 DSH WebServer 精确监听 `127.0.0.1`,并从实际端口构造固定 `/oauth/callback`;不接受公网回调源配置。它有意不设置 `agent-default-model`,因为 Provider 和模型 ID 属于部署方 Enterprise Profile,用户可在 DSH 中选择可用企业模型。
|
|
78
78
|
|
|
@@ -104,7 +104,7 @@ The Provider object is data interpreted by a local audited adapter.
|
|
|
104
104
|
| `displayName` | no | User-facing Provider name. |
|
|
105
105
|
| `adapter` | yes | Exact string `openai-compatible`. |
|
|
106
106
|
| `baseURL` | yes | HTTPS OpenAI-compatible API base. |
|
|
107
|
-
| `reasoning` | no | Default DSH/pi-ai reasoning level
|
|
107
|
+
| `reasoning` | no | Default DSH/pi-ai reasoning level: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, or `max`; default `high`. |
|
|
108
108
|
| `defaultContextWindow` | no | Positive safe integer, default 262144. |
|
|
109
109
|
| `defaultMaxTokens` | no | Positive safe integer, default 32768. |
|
|
110
110
|
| `maxRequestImageBytes` | no | Accumulated native-image request budget. |
|
|
@@ -128,7 +128,7 @@ Each model has:
|
|
|
128
128
|
- `input` containing `text`, `image`, or both (default `text`);
|
|
129
129
|
- optional positive `contextWindow` and `maxTokens`;
|
|
130
130
|
- optional `reasoning` boolean;
|
|
131
|
-
- optional `reasoningEfforts` object, or `false`;
|
|
131
|
+
- optional `reasoningEfforts` object, or `false`; object keys are limited to `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`, and only `off` may have a null wire value;
|
|
132
132
|
- optional bounded `compat` overrides.
|
|
133
133
|
|
|
134
134
|
If a model supports thinking but not selectable reasoning effort, set:
|
|
@@ -104,7 +104,7 @@ Provider 对象是由本地、经过审查的 adapter 解释的数据。
|
|
|
104
104
|
| `displayName` | 否 | 面向用户的 Provider 名称。 |
|
|
105
105
|
| `adapter` | 是 | 精确字符串 `openai-compatible`。 |
|
|
106
106
|
| `baseURL` | 是 | HTTPS OpenAI-compatible API 基址。 |
|
|
107
|
-
| `reasoning` | 否 | 默认 DSH/pi-ai reasoning level
|
|
107
|
+
| `reasoning` | 否 | 默认 DSH/pi-ai reasoning level,取值为 `off`、`minimal`、`low`、`medium`、`high`、`xhigh`、`max`,默认为 `high`。 |
|
|
108
108
|
| `defaultContextWindow` | 否 | 正安全整数,默认 262144。 |
|
|
109
109
|
| `defaultMaxTokens` | 否 | 正安全整数,默认 32768。 |
|
|
110
110
|
| `maxRequestImageBytes` | 否 | 单次原生图片请求的累计大小预算。 |
|
|
@@ -128,7 +128,7 @@ Provider 对象是由本地、经过审查的 adapter 解释的数据。
|
|
|
128
128
|
- `input` 可包含 `text`、`image` 或两者,默认 `text`;
|
|
129
129
|
- 可选的正数 `contextWindow` 和 `maxTokens`;
|
|
130
130
|
- 可选 `reasoning` 布尔值;
|
|
131
|
-
- 可选 `reasoningEfforts` 对象或 `false`;
|
|
131
|
+
- 可选 `reasoningEfforts` 对象或 `false`;对象键限于 `off`、`minimal`、`low`、`medium`、`high`、`xhigh`、`max`,且只有 `off` 的过线值可以为 `null`;
|
|
132
132
|
- 可选的受限 `compat` 覆盖。
|
|
133
133
|
|
|
134
134
|
若模型支持 thinking,但不支持选择 reasoning effort,请设置:
|
|
@@ -10,7 +10,7 @@ This guide is for operators integrating `dsh-oidc` into their own DeepSeek Harne
|
|
|
10
10
|
|
|
11
11
|
| Component | Minimum requirement |
|
|
12
12
|
| --- | --- |
|
|
13
|
-
| DSH Host | DeepSeek Harness `0.1.2-
|
|
13
|
+
| DSH Host | DeepSeek Harness `0.1.2-rc.1` on Node.js 22+. |
|
|
14
14
|
| Institutional enterprise-model integration service | One accountable owner jointly delivers the OIDC Provider, fixed Key Binding API, and OpenAI-compatible model gateway; all three are required. |
|
|
15
15
|
| Enterprise Profile | Trusted local JSON containing public configuration only. |
|
|
16
16
|
| Credential Provider | The current Web backend supports trusted single-user local storage only. |
|
|
@@ -59,7 +59,7 @@ The Profile is trusted deployment data, not a secret store. It must not contain
|
|
|
59
59
|
The package is itself an installable DSH Bundle. Team deployments should install the reviewed, exact version from npm:
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
|
-
dsh plugin --profile web add @eduwork/dsh-oidc@0.1.0
|
|
62
|
+
dsh plugin --profile web add @eduwork/dsh-oidc@0.1.0
|
|
63
63
|
```
|
|
64
64
|
|
|
65
65
|
For auditing, development, or testing unpublished changes, install from a local checkout instead:
|
|
@@ -78,11 +78,7 @@ From the parent directory, the equivalent explicit relative-path command is:
|
|
|
78
78
|
dsh plugin --profile web add ./dsh-oidc
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
DSH links the checkout into `$DSH_HOME/profiles/web`; it does not scan or copy the invoking directory. Keep the checkout in place and pin a reviewed commit for source-based deployments.
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
dsh plugin --profile web add @eduwork/dsh-oidc@alpha
|
|
85
|
-
```
|
|
81
|
+
DSH links the checkout into `$DSH_HOME/profiles/web`; it does not scan or copy the invoking directory. Keep the checkout in place and pin a reviewed commit for source-based deployments. Production and team Profiles should use an exact npm version and must not mix another DSH prerelease line.
|
|
86
82
|
|
|
87
83
|
Set the trusted local Profile path and start DSH on the fixed loopback host:
|
|
88
84
|
|
|
@@ -134,4 +130,4 @@ The current Web backend does not support shared Web. A shared scenario needs a n
|
|
|
134
130
|
- **A subject string is shown instead of a name:** return a non-empty standard `name` from UserInfo under the `profile` scope; private JSON-path mappings are intentionally unsupported.
|
|
135
131
|
- **Login works but models do not:** inspect `/bootstrap`, explicit provisioning state, exact `provider_id` equality, and whether the model gateway accepts the bound key.
|
|
136
132
|
- **Thinking works but selectable effort does not:** set model `compat.supportsReasoningEffort` to `false`; thinking remains enabled while the unsupported effort parameter is removed.
|
|
137
|
-
- **Why the enterprise controls are inside Models:** DSH `0.1.2-
|
|
133
|
+
- **Why the enterprise controls are inside Models:** DSH `0.1.2-rc.1` exposes the official `settings.models.footer` extension slot. `dsh-oidc` mounts its management UI there and leaves the upstream Models page enabled; no product-private Models-page fork is required.
|
package/docs/getting-started.md
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
| 组件 | 谁提供 | 最低要求 |
|
|
18
18
|
| --- | --- | --- |
|
|
19
|
-
| DSH Host | 部署方 | DeepSeek Harness `0.1.2-
|
|
19
|
+
| DSH Host | 部署方 | DeepSeek Harness `0.1.2-rc.1`,Node.js 22+。 |
|
|
20
20
|
| 机构企业模型集成服务 | 同一服务所有者 | 共同提供 OIDC Provider、固定 Key Binding 和 OpenAI-compatible 模型网关;三者全部必需。 |
|
|
21
21
|
| Enterprise Profile | 部署方 | 一份受信任的本地 JSON,只存公开配置,不存密钥或个人信息。 |
|
|
22
22
|
| Credential Provider | DSH Host | 当前 Web backend 仅支持可信单用户本机存储。 |
|
|
@@ -122,7 +122,7 @@ Profile 是部署配置,不是用户输入。它可以声明模型事实和有
|
|
|
122
122
|
`dsh-oidc` 本身是可直接安装的 DSH Bundle。团队部署应从 npm 安装经过复核的精确版本:
|
|
123
123
|
|
|
124
124
|
```bash
|
|
125
|
-
dsh plugin --profile web add @eduwork/dsh-oidc@0.1.0
|
|
125
|
+
dsh plugin --profile web add @eduwork/dsh-oidc@0.1.0
|
|
126
126
|
```
|
|
127
127
|
|
|
128
128
|
需要审计、开发或测试尚未发布的改动时,再从本地 checkout 安装:
|
|
@@ -141,11 +141,7 @@ dsh plugin --profile web add .
|
|
|
141
141
|
dsh plugin --profile web add ./dsh-oidc
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
-
DSH 会把本地 checkout 链接到 `$DSH_HOME/profiles/web`,不会扫描或复制当前目录;安装完成后不要移动或删除 checkout。源码部署应固定经过审核的 commit
|
|
145
|
-
|
|
146
|
-
```bash
|
|
147
|
-
dsh plugin --profile web add @eduwork/dsh-oidc@alpha
|
|
148
|
-
```
|
|
144
|
+
DSH 会把本地 checkout 链接到 `$DSH_HOME/profiles/web`,不会扫描或复制当前目录;安装完成后不要移动或删除 checkout。源码部署应固定经过审核的 commit。生产或团队 Profile 应使用精确 npm 版本,不要混装其他 DSH 预发布线。
|
|
149
145
|
|
|
150
146
|
设置 Enterprise Profile 路径,并让 DSH 监听固定 loopback host:
|
|
151
147
|
|
|
@@ -236,4 +232,4 @@ native backend 必须提供 `enterpriseAccounts` 服务,并与 Web 一样传
|
|
|
236
232
|
|
|
237
233
|
### 为什么企业服务是单独的设置页
|
|
238
234
|
|
|
239
|
-
当前 DSH `0.1.2-
|
|
235
|
+
当前 DSH `0.1.2-rc.1` 提供正式的 `settings.models.footer` 插槽。插件直接把企业模型管理能力挂载到官方“模型”页,并保持官方模型页启用,不再依赖产品私有的模型页 fork。
|
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
[简体中文](release-checklist.md) | **English**
|
|
4
4
|
|
|
5
|
-
Record
|
|
5
|
+
Record the maintainer, date, command-output links, and exceptions in the release pull request or release record. An applicable but incomplete security, compatibility, or supply-chain item blocks public release; the current maintainer records why an item is not applicable. During the initial single-maintainer phase, do not invent a second human approval: independent technical review, CI/focused regression evidence, and an explicit maintainer decision form the release basis.
|
|
6
6
|
|
|
7
7
|
## Authority and project metadata
|
|
8
8
|
|
|
9
9
|
- [ ] Repository owner confirmed public release and the MIT license.
|
|
10
|
-
- [ ] The `freedomkk-qfeng/dsh-oidc` remote
|
|
11
|
-
- [ ] Maintainer, security, and release-manager rosters recorded
|
|
10
|
+
- [ ] The `freedomkk-qfeng/dsh-oidc` remote and ownership of the `@eduwork/dsh-oidc` npm package are confirmed.
|
|
11
|
+
- [ ] Maintainer, security, and release-manager rosters recorded, accurately stating whether backups and a recovery path currently exist.
|
|
12
12
|
- [ ] GitHub Private Vulnerability Reporting is enabled and its entry point has been checked without sensitive data.
|
|
13
13
|
- [ ] ECNU/ChatECNU name, example text, colors, and trademark notice approved.
|
|
14
14
|
|
|
15
15
|
## Source and protocol review
|
|
16
16
|
|
|
17
|
-
- [ ]
|
|
17
|
+
- [ ] Independent technical review completed for OIDC, Key Binding, model-gateway invariants, Profile validation, Provider credentials, and the native boundary; the maintainer accepted findings and exceptions in the release record.
|
|
18
18
|
- [ ] Enterprise Profile JSON Schema matches runtime behavior.
|
|
19
19
|
- [ ] OpenAPI matches normative Key Binding prose and implementation.
|
|
20
20
|
- [ ] OIDC standard references and limitations are current.
|
|
@@ -35,7 +35,7 @@ Record reviewer names, date, command output links, and exceptions in the release
|
|
|
35
35
|
|
|
36
36
|
## Supply chain
|
|
37
37
|
|
|
38
|
-
- [ ] Clean `npm ci` completed on Windows and Linux with Node 22.
|
|
38
|
+
- [ ] Clean `npm ci` and `npm run check` completed on Windows and Linux with Node 22 and 24.
|
|
39
39
|
- [ ] `npm audit` and static analysis reviewed (not merely run).
|
|
40
40
|
- [ ] Every direct/transitive license and exception reviewed.
|
|
41
41
|
- [ ] npm install scripts reviewed; unexpected scripts denied.
|
|
@@ -56,5 +56,8 @@ Record reviewer names, date, command output links, and exceptions in the release
|
|
|
56
56
|
- [ ] `npm pack --dry-run` and extracted tarball reviewed; only intended files included.
|
|
57
57
|
- [ ] Source maps contain no private absolute paths or secrets.
|
|
58
58
|
- [ ] Tag/release notes/checksums prepared.
|
|
59
|
-
- [ ]
|
|
59
|
+
- [ ] The actual publication path is recorded: until a Trusted Publisher is configured, run the manual workflow only with `publish=false`; the first stable release may use the maintainer's npm CLI plus browser 2FA to publish the frozen tarball, explicitly without claiming provenance.
|
|
60
|
+
- [ ] When using Trusted Publishing, the Publisher is bound to repository `freedomkk-qfeng/dsh-oidc`, workflow `release.yml`, and environment `npm`; the job uses pinned npm CLI `11.6.2`, and this commit's Windows/Linux × Node 22/24 CI is successful.
|
|
61
|
+
- [ ] Inputs and artifacts are verified for the selected path: the CLI path checks frozen tarball identity, SHA-256, 2FA, and registry results; the Trusted path additionally checks the existing `v<package version>` tag, commit, workflow artifact, and an actual npm provenance attestation.
|
|
62
|
+
- [ ] Publishing credentials were not written to the repository, logs, or deliverables, and the release does not claim Trusted Publishing before it is configured.
|
|
60
63
|
- [ ] Rollback/deprecation and vulnerability-notification plan confirmed.
|
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
**简体中文** | [English](release-checklist.en.md)
|
|
4
4
|
|
|
5
|
-
在发布 Pull Request
|
|
5
|
+
在发布 Pull Request 或发行记录中记录维护者、日期、命令输出链接和例外说明。适用但未完成的安全、兼容或供应链项目会阻止公开发布;不适用项由当前维护者记录原因。项目处于初期单一维护者阶段时,不虚构第二位人工审批,以独立技术复核、CI/专项回归证据和维护者明确决定作为发布依据。
|
|
6
6
|
|
|
7
7
|
## 授权与项目元数据
|
|
8
8
|
|
|
9
9
|
- [ ] 仓库所有者确认公开发布和 MIT 许可证。
|
|
10
|
-
- [ ] `freedomkk-qfeng/dsh-oidc`
|
|
11
|
-
- [ ]
|
|
10
|
+
- [ ] `freedomkk-qfeng/dsh-oidc` 远程仓库位置和 `@eduwork/dsh-oidc` npm 包所有权均已确认。
|
|
11
|
+
- [ ] 维护者、安全维护者和发布经理名单已记录,并如实说明当前是否存在替补及恢复路径。
|
|
12
12
|
- [ ] GitHub Private Vulnerability Reporting 已启用并完成一次无敏感数据的入口检查。
|
|
13
13
|
- [ ] ECNU/ChatECNU 名称、示例文字、颜色和商标声明获批。
|
|
14
14
|
|
|
15
15
|
## 源码与协议审查
|
|
16
16
|
|
|
17
|
-
- [ ] OIDC、Key Binding、模型网关一致性、Profile 校验、Provider 凭据和 native
|
|
17
|
+
- [ ] OIDC、Key Binding、模型网关一致性、Profile 校验、Provider 凭据和 native 边界已完成独立技术复核,维护者已在发布记录中接受结论和例外。
|
|
18
18
|
- [ ] Enterprise Profile JSON Schema 与运行行为一致。
|
|
19
19
|
- [ ] OpenAPI 与 Key Binding 规范正文和实现一致。
|
|
20
20
|
- [ ] OIDC 标准引用和限制仍然有效。
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
|
|
36
36
|
## 供应链
|
|
37
37
|
|
|
38
|
-
- [ ] Windows 和 Linux
|
|
38
|
+
- [ ] Windows 和 Linux 上分别使用 Node 22、24 完成干净 `npm ci` 与 `npm run check`。
|
|
39
39
|
- [ ] `npm audit` 和静态分析结果经过审查,而不只是执行。
|
|
40
40
|
- [ ] 所有直接/间接许可证和例外已经审查。
|
|
41
41
|
- [ ] npm 安装脚本已经审查,未预期脚本被拒绝。
|
|
@@ -56,5 +56,8 @@
|
|
|
56
56
|
- [ ] 已审查 `npm pack --dry-run` 和解压后的 tarball,且只包含预期文件。
|
|
57
57
|
- [ ] Source map 不包含私有绝对路径或秘密。
|
|
58
58
|
- [ ] Tag、发布说明和 checksum 已准备。
|
|
59
|
-
- [ ]
|
|
59
|
+
- [ ] 实际发布路径已记录:Trusted Publisher 尚未配置时,手动 workflow 只以 `publish=false` 运行;首次稳定版可以使用维护者 npm CLI + 浏览器 2FA 发布冻结 tarball,且明确不声称 provenance。
|
|
60
|
+
- [ ] 若使用 Trusted Publishing,Publisher 已绑定仓库 `freedomkk-qfeng/dsh-oidc`、workflow `release.yml` 和 environment `npm`;发布 job 使用固定 npm CLI `11.6.2`,且该提交的 Windows/Linux × Node 22/24 CI 已成功。
|
|
61
|
+
- [ ] 发布输入与产物已按所选路径核验:CLI 路径核对冻结 tarball 身份、SHA-256、2FA 和 registry 结果;Trusted 路径还核对现有 `v<package version>` tag、提交、workflow artifact 和实际 npm provenance attestation。
|
|
62
|
+
- [ ] 发布凭据没有写入仓库、日志或交付物;未配置 Trusted Publisher 时也不宣称使用了 Trusted Publishing。
|
|
60
63
|
- [ ] 已确认回滚、弃用和漏洞通知计划。
|
package/lib/client.js
CHANGED
|
@@ -5386,6 +5386,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5386
5386
|
"theme"
|
|
5387
5387
|
];
|
|
5388
5388
|
const h = react.default.createElement;
|
|
5389
|
+
const enterpriseBrandPriority = -100;
|
|
5389
5390
|
const border = "var(--dsw-alias-border-l2, #e5d4cc)";
|
|
5390
5391
|
const button = Object.freeze({
|
|
5391
5392
|
border: `1px solid ${border}`,
|
|
@@ -5501,14 +5502,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5501
5502
|
const effects = [
|
|
5502
5503
|
ctx.slots.inject("sidebar.brand.mark", () => ctx.slots.register({
|
|
5503
5504
|
name: "sidebar.brand.mark",
|
|
5505
|
+
priority: enterpriseBrandPriority,
|
|
5504
5506
|
inject: () => ({ profile })
|
|
5505
5507
|
}, ProductMark)),
|
|
5506
5508
|
ctx.slots.inject("sidebar.brand.name", () => ctx.slots.register({
|
|
5507
5509
|
name: "sidebar.brand.name",
|
|
5510
|
+
priority: enterpriseBrandPriority,
|
|
5508
5511
|
inject: () => ({ profile })
|
|
5509
5512
|
}, ProductName)),
|
|
5510
5513
|
ctx.slots.inject("conversation.hero.brand.mark", () => ctx.slots.register({
|
|
5511
5514
|
name: "conversation.hero.brand.mark",
|
|
5515
|
+
priority: enterpriseBrandPriority,
|
|
5512
5516
|
inject: () => ({ profile })
|
|
5513
5517
|
}, ProductMark))
|
|
5514
5518
|
];
|
package/lib/profile.js
CHANGED
|
@@ -6,6 +6,12 @@ const idPattern = /^[a-z][a-z0-9-]{0,63}$/
|
|
|
6
6
|
const credentialPattern = /^[A-Za-z_][A-Za-z0-9_]*$/
|
|
7
7
|
const colorPattern = /^#[0-9a-fA-F]{6}$/
|
|
8
8
|
const allowedModalities = new Set(['text', 'image'])
|
|
9
|
+
const allowedThinkingLevels = new Set(['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'])
|
|
10
|
+
const allowedMaxTokensFields = new Set(['max_completion_tokens', 'max_tokens'])
|
|
11
|
+
const allowedThinkingFormats = new Set([
|
|
12
|
+
'openai', 'deepseek', 'openrouter', 'together', 'baseten', 'zai', 'qwen',
|
|
13
|
+
'chat-template', 'qwen-chat-template', 'string-thinking', 'ant-ling',
|
|
14
|
+
])
|
|
9
15
|
const allowedRootKeys = new Set([
|
|
10
16
|
'schemaVersion', 'id', 'displayName', 'organization', 'nativeInstitutionID',
|
|
11
17
|
'allowInsecureDevelopment', 'insecureDevelopmentOrigin', 'brand', 'oidc', 'keyBinding', 'provider',
|
|
@@ -141,9 +147,15 @@ function normalizeCompat(value, label) {
|
|
|
141
147
|
const result = {}
|
|
142
148
|
for (const key of allowedCompatKeys) {
|
|
143
149
|
if (source[key] === undefined) continue
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
150
|
+
if (key === 'maxTokensField') {
|
|
151
|
+
result[key] = text(source[key], `${label}.${key}`, 64)
|
|
152
|
+
if (!allowedMaxTokensFields.has(result[key])) throw new Error(`${label}.${key} is not supported by DSH pi-ai`)
|
|
153
|
+
} else if (key === 'thinkingFormat') {
|
|
154
|
+
result[key] = text(source[key], `${label}.${key}`, 64)
|
|
155
|
+
if (!allowedThinkingFormats.has(result[key])) throw new Error(`${label}.${key} is not supported by DSH pi-ai`)
|
|
156
|
+
} else {
|
|
157
|
+
result[key] = boolean(source[key], `${label}.${key}`)
|
|
158
|
+
}
|
|
147
159
|
}
|
|
148
160
|
return Object.freeze(result)
|
|
149
161
|
}
|
|
@@ -151,9 +163,12 @@ function normalizeCompat(value, label) {
|
|
|
151
163
|
function normalizeReasoningEfforts(value, providerID, modelID) {
|
|
152
164
|
if (value === false) return false
|
|
153
165
|
const source = object(value, `${providerID}.${modelID}.reasoningEfforts`)
|
|
154
|
-
if (Object.keys(source).length === 0 || Object.keys(source).length >
|
|
166
|
+
if (Object.keys(source).length === 0 || Object.keys(source).length > allowedThinkingLevels.size) {
|
|
167
|
+
throw new Error(`${providerID}.${modelID}.reasoningEfforts must contain 1-${allowedThinkingLevels.size} entries`)
|
|
168
|
+
}
|
|
155
169
|
return Object.freeze(Object.fromEntries(Object.entries(source).map(([level, wire]) => {
|
|
156
|
-
|
|
170
|
+
if (!allowedThinkingLevels.has(level)) throw new Error(`${providerID}.${modelID}.reasoningEfforts level ${level} is not supported by DSH pi-ai`)
|
|
171
|
+
if (wire === null && level !== 'off') throw new Error(`${providerID}.${modelID}.reasoningEfforts.${level} may be null only for off`)
|
|
157
172
|
if (wire !== null) text(wire, `${providerID}.${modelID}.reasoningEfforts.${level}`, 32)
|
|
158
173
|
return [level, wire]
|
|
159
174
|
})))
|
|
@@ -296,7 +311,13 @@ export function normalizeEnterpriseProfile(raw) {
|
|
|
296
311
|
displayName: text(provider.displayName ?? source.displayName, 'profile.provider.displayName', 120),
|
|
297
312
|
adapter: provider.adapter,
|
|
298
313
|
baseURL: exactURL(provider.baseURL, 'profile.provider.baseURL', allowInsecureDevelopment, allowedInsecureOrigin),
|
|
299
|
-
reasoning: provider.reasoning === undefined
|
|
314
|
+
reasoning: provider.reasoning === undefined
|
|
315
|
+
? 'high'
|
|
316
|
+
: (() => {
|
|
317
|
+
const reasoning = text(provider.reasoning, 'profile.provider.reasoning', 32)
|
|
318
|
+
if (!allowedThinkingLevels.has(reasoning)) throw new Error('profile.provider.reasoning is not supported by DSH pi-ai')
|
|
319
|
+
return reasoning
|
|
320
|
+
})(),
|
|
300
321
|
defaultContextWindow: optionalPositiveInteger(provider.defaultContextWindow, 'profile.provider.defaultContextWindow'),
|
|
301
322
|
defaultMaxTokens: optionalPositiveInteger(provider.defaultMaxTokens, 'profile.provider.defaultMaxTokens'),
|
|
302
323
|
maxRequestImageBytes: optionalPositiveInteger(provider.maxRequestImageBytes, 'profile.provider.maxRequestImageBytes'),
|
|
@@ -342,15 +363,22 @@ export function enterpriseProviderConfig(profiles) {
|
|
|
342
363
|
allowInsecureDevelopment: profile.allowInsecureDevelopment,
|
|
343
364
|
...(profile.insecureDevelopmentOrigin === undefined ? {} : { insecureDevelopmentOrigin: profile.insecureDevelopmentOrigin }),
|
|
344
365
|
reasoning: profile.provider.reasoning,
|
|
345
|
-
defaultContextWindow: profile.provider.defaultContextWindow,
|
|
346
|
-
defaultMaxTokens: profile.provider.defaultMaxTokens,
|
|
347
|
-
maxRequestImageBytes: profile.provider.maxRequestImageBytes,
|
|
348
|
-
requestImagePixelBudget: profile.provider.requestImagePixelBudget,
|
|
349
|
-
requestImageMaxBytes: profile.provider.requestImageMaxBytes,
|
|
350
|
-
streamIdleTimeoutMs: profile.provider.streamIdleTimeoutMs,
|
|
351
|
-
retryPolicy: profile.provider.retryPolicy,
|
|
352
|
-
compat: profile.provider.compat,
|
|
353
|
-
models: profile.provider.models
|
|
366
|
+
...(profile.provider.defaultContextWindow === undefined ? {} : { defaultContextWindow: profile.provider.defaultContextWindow }),
|
|
367
|
+
...(profile.provider.defaultMaxTokens === undefined ? {} : { defaultMaxTokens: profile.provider.defaultMaxTokens }),
|
|
368
|
+
...(profile.provider.maxRequestImageBytes === undefined ? {} : { maxRequestImageBytes: profile.provider.maxRequestImageBytes }),
|
|
369
|
+
...(profile.provider.requestImagePixelBudget === undefined ? {} : { requestImagePixelBudget: profile.provider.requestImagePixelBudget }),
|
|
370
|
+
...(profile.provider.requestImageMaxBytes === undefined ? {} : { requestImageMaxBytes: profile.provider.requestImageMaxBytes }),
|
|
371
|
+
...(profile.provider.streamIdleTimeoutMs === undefined ? {} : { streamIdleTimeoutMs: profile.provider.streamIdleTimeoutMs }),
|
|
372
|
+
...(profile.provider.retryPolicy === undefined ? {} : { retryPolicy: structuredClone(profile.provider.retryPolicy) }),
|
|
373
|
+
...(profile.provider.compat === undefined ? {} : { compat: { ...profile.provider.compat } }),
|
|
374
|
+
models: profile.provider.models.map(model => ({
|
|
375
|
+
...model,
|
|
376
|
+
input: [...model.input],
|
|
377
|
+
...(model.reasoningEfforts && typeof model.reasoningEfforts === 'object'
|
|
378
|
+
? { reasoningEfforts: { ...model.reasoningEfforts } }
|
|
379
|
+
: {}),
|
|
380
|
+
...(model.compat === undefined ? {} : { compat: { ...model.compat } }),
|
|
381
|
+
})),
|
|
354
382
|
}])),
|
|
355
383
|
}
|
|
356
384
|
}
|
package/lib/provider/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { launchEnvironmentOf } from '@deepseek-ai/dsh-launch-environment'
|
|
2
|
-
import { LlmError, assertUsableApiKey, resolveRetryPolicy } from '@deepseek-ai/dsh-llm'
|
|
2
|
+
import { LlmError, assertUsableApiKey, resolveImageAttachmentAccess, resolveRetryPolicy } from '@deepseek-ai/dsh-llm'
|
|
3
3
|
import { Config as PiAiConfig, PiAiAdapter } from '@deepseek-ai/dsh-llm-pi-ai'
|
|
4
4
|
import { createProvider } from '@earendil-works/pi-ai'
|
|
5
5
|
import { openAICompletionsApi } from '@earendil-works/pi-ai/api/openai-completions.lazy'
|
|
@@ -22,7 +22,13 @@ function installEnterpriseSettings(ctx, rawConfig, hooks) {
|
|
|
22
22
|
SETTINGS_NAMESPACE,
|
|
23
23
|
PiAiConfig,
|
|
24
24
|
settingsBase(rawConfig),
|
|
25
|
-
|
|
25
|
+
{
|
|
26
|
+
...hooks,
|
|
27
|
+
validate(value) {
|
|
28
|
+
assertServiceableEnterpriseProviders(value)
|
|
29
|
+
hooks.validate?.(value)
|
|
30
|
+
},
|
|
31
|
+
},
|
|
26
32
|
)
|
|
27
33
|
})
|
|
28
34
|
}
|
|
@@ -68,6 +74,10 @@ function profilesFrom(rawConfig) {
|
|
|
68
74
|
return profiles
|
|
69
75
|
}
|
|
70
76
|
|
|
77
|
+
export function assertServiceableEnterpriseProviders(rawConfig) {
|
|
78
|
+
profilesFrom(rawConfig)
|
|
79
|
+
}
|
|
80
|
+
|
|
71
81
|
function isolatedPiAiAuth() {
|
|
72
82
|
const stored = new Map()
|
|
73
83
|
return {
|
|
@@ -89,6 +99,14 @@ function isolatedPiAiAuth() {
|
|
|
89
99
|
}
|
|
90
100
|
}
|
|
91
101
|
|
|
102
|
+
export function resolveEnterpriseImageAccess(ctx, attachments, ref) {
|
|
103
|
+
return resolveImageAttachmentAccess(
|
|
104
|
+
attachments,
|
|
105
|
+
hostPath => ctx.get('fs')?.processPathFromHostPath(hostPath),
|
|
106
|
+
ref,
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
|
|
92
110
|
export function apply(ctx, rawConfig = {}) {
|
|
93
111
|
const transforms = new EnterpriseModelTransforms(ctx)
|
|
94
112
|
let current = () => settingsBase(rawConfig)
|
|
@@ -108,6 +126,7 @@ export function apply(ctx, rawConfig = {}) {
|
|
|
108
126
|
throw new LlmError(`${name}: no credential for provider route "${provider}" (${ref})`, 'MISSING_CREDENTIAL')
|
|
109
127
|
},
|
|
110
128
|
resolveAttachments: () => ctx.get('attachments'),
|
|
129
|
+
resolveImageAccess: (attachments, ref) => resolveEnterpriseImageAccess(ctx, attachments, ref),
|
|
111
130
|
})
|
|
112
131
|
|
|
113
132
|
const adapter = new TransformingEnterpriseAdapter(baseAdapter, transforms, (provider, model) => (
|
|
@@ -8,6 +8,7 @@ export class TransformingEnterpriseAdapter {
|
|
|
8
8
|
|
|
9
9
|
providerInfo(provider) { return this.inner.providerInfo(provider) }
|
|
10
10
|
providerRetryPolicy(provider) { return this.inner.providerRetryPolicy(provider) }
|
|
11
|
+
imageRequestPricing(provider, model) { return this.inner.imageRequestPricing(provider, model) }
|
|
11
12
|
|
|
12
13
|
async listModels(provider) {
|
|
13
14
|
const models = await this.inner.listModels(provider)
|
|
@@ -62,4 +63,3 @@ export class TransformingEnterpriseAdapter {
|
|
|
62
63
|
yield* this.streamPrepared(options, prepared)
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
|
-
|