@dsh-ft/dsh-fft-settings 0.0.0-stage → 0.5.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/LICENSE +21 -0
- package/README.md +392 -2
- package/cordis.patch.yml +18 -0
- package/docs/compatibility-dsh-0.1.6-alpha.1.md +58 -0
- package/docs/extension-service-design.md +351 -0
- package/docs/extension-service-sequences.html +545 -0
- package/docs/ftshare-settings-er.html +139 -0
- package/docs/ftshare-settings-er.svg +113 -0
- package/docs/ftshare-settings-results-er.html +148 -0
- package/docs/ftshare-settings-results-er.svg +122 -0
- package/docs/kline-integration.md +258 -0
- package/lib/agent.d.ts +24 -0
- package/lib/agent.js +26 -0
- package/lib/brand.d.ts +53 -0
- package/lib/brand.js +50 -0
- package/lib/client.d.ts +8 -0
- package/lib/client.js +822 -0
- package/lib/client.js.map +1 -0
- package/lib/contract.d.ts +14 -0
- package/lib/contract.js +14 -0
- package/lib/core/client-transport.d.ts +15 -0
- package/lib/core/client-transport.js +31 -0
- package/lib/core/contract.d.ts +62 -0
- package/lib/core/contract.js +28 -0
- package/lib/core/module-registry.d.ts +54 -0
- package/lib/core/module-registry.js +68 -0
- package/lib/core/rpc-core.d.ts +69 -0
- package/lib/core/rpc-core.js +88 -0
- package/lib/core/shell.d.ts +59 -0
- package/lib/core/shell.js +28 -0
- package/lib/core/styles.d.ts +31 -0
- package/lib/core/styles.js +43 -0
- package/lib/core/transport.d.ts +19 -0
- package/lib/core/transport.js +80 -0
- package/lib/default-preset.d.ts +52 -0
- package/lib/default-preset.js +121 -0
- package/lib/features/api-key/card.d.ts +24 -0
- package/lib/features/api-key/card.js +39 -0
- package/lib/features/api-key/client-api.d.ts +4 -0
- package/lib/features/api-key/client-api.js +11 -0
- package/lib/features/api-key/contract.d.ts +69 -0
- package/lib/features/api-key/contract.js +24 -0
- package/lib/features/api-key/host.d.ts +17 -0
- package/lib/features/api-key/host.js +32 -0
- package/lib/features/api-key/index.d.ts +13 -0
- package/lib/features/api-key/index.js +12 -0
- package/lib/features/api-key/logging.d.ts +15 -0
- package/lib/features/api-key/logging.js +1 -0
- package/lib/features/api-key/model.d.ts +24 -0
- package/lib/features/api-key/model.js +105 -0
- package/lib/features/api-key/probe.d.ts +11 -0
- package/lib/features/api-key/probe.js +142 -0
- package/lib/features/api-key/rpc.d.ts +4 -0
- package/lib/features/api-key/rpc.js +17 -0
- package/lib/features/api-key/service.d.ts +21 -0
- package/lib/features/api-key/service.js +181 -0
- package/lib/features/api-key/styles.d.ts +9 -0
- package/lib/features/api-key/styles.js +24 -0
- package/lib/features/logs/archive.d.ts +87 -0
- package/lib/features/logs/archive.js +156 -0
- package/lib/features/logs/card.d.ts +22 -0
- package/lib/features/logs/card.js +107 -0
- package/lib/features/logs/client-api.d.ts +4 -0
- package/lib/features/logs/client-api.js +11 -0
- package/lib/features/logs/collector.d.ts +91 -0
- package/lib/features/logs/collector.js +258 -0
- package/lib/features/logs/config.d.ts +70 -0
- package/lib/features/logs/config.js +97 -0
- package/lib/features/logs/contract.d.ts +130 -0
- package/lib/features/logs/contract.js +67 -0
- package/lib/features/logs/export.d.ts +92 -0
- package/lib/features/logs/export.js +212 -0
- package/lib/features/logs/format.d.ts +42 -0
- package/lib/features/logs/format.js +172 -0
- package/lib/features/logs/home.d.ts +18 -0
- package/lib/features/logs/home.js +39 -0
- package/lib/features/logs/host.d.ts +19 -0
- package/lib/features/logs/host.js +139 -0
- package/lib/features/logs/index.d.ts +12 -0
- package/lib/features/logs/index.js +12 -0
- package/lib/features/logs/rpc.d.ts +6 -0
- package/lib/features/logs/rpc.js +27 -0
- package/lib/features/logs/styles.d.ts +9 -0
- package/lib/features/logs/styles.js +13 -0
- package/lib/guidance.d.ts +41 -0
- package/lib/guidance.js +88 -0
- package/lib/index.d.ts +67 -0
- package/lib/index.js +50 -0
- package/lib/rpc.d.ts +10 -0
- package/lib/rpc.js +10 -0
- package/package.json +86 -4
- package/src/agent.ts +31 -0
- package/src/brand.ts +79 -0
- package/src/client.tsx +21 -0
- package/src/contract.ts +14 -0
- package/src/core/client-transport.ts +37 -0
- package/src/core/contract.ts +57 -0
- package/src/core/module-registry.ts +102 -0
- package/src/core/rpc-core.ts +107 -0
- package/src/core/shell.tsx +81 -0
- package/src/core/styles.ts +43 -0
- package/src/core/transport.ts +82 -0
- package/src/default-preset.ts +151 -0
- package/src/features/api-key/card.tsx +77 -0
- package/src/features/api-key/client-api.ts +12 -0
- package/src/features/api-key/contract.ts +63 -0
- package/src/features/api-key/host.ts +36 -0
- package/src/features/api-key/index.ts +13 -0
- package/src/features/api-key/logging.ts +15 -0
- package/src/features/api-key/model.ts +63 -0
- package/src/features/api-key/probe.ts +116 -0
- package/src/features/api-key/rpc.ts +18 -0
- package/src/features/api-key/service.ts +157 -0
- package/src/features/api-key/styles.ts +24 -0
- package/src/features/logs/archive.ts +230 -0
- package/src/features/logs/card.tsx +169 -0
- package/src/features/logs/client-api.ts +20 -0
- package/src/features/logs/collector.ts +313 -0
- package/src/features/logs/config.ts +115 -0
- package/src/features/logs/contract.ts +149 -0
- package/src/features/logs/export.ts +274 -0
- package/src/features/logs/format.ts +188 -0
- package/src/features/logs/home.ts +43 -0
- package/src/features/logs/host.ts +153 -0
- package/src/features/logs/index.ts +12 -0
- package/src/features/logs/rpc.ts +29 -0
- package/src/features/logs/styles.ts +13 -0
- package/src/guidance.ts +114 -0
- package/src/index.ts +59 -0
- package/src/rpc.ts +10 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ben
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,393 @@
|
|
|
1
|
-
#
|
|
1
|
+
# FTShare Settings:共享设置、远端服务与 API Key 检测
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@dsh-ft/dsh-fft-settings`(原 `@ft/dsh-ftshare-settings`)是 DSH 共享设置插件。Host 服务为 **`ctx.ftshareSettings`**,API Key 的所有能力位于 **`apiKey` 命名空间**,运行日志采集与导出位于 **`logs` 命名空间**;未来主题、用户偏好应作为 `theme`、`preferences` 等同级命名空间扩展,不能混入 `apiKey`。
|
|
4
|
+
|
|
5
|
+
当前只实现 API Key 管理、远端服务检查与 Key 验证,以及**常驻的运行日志采集器**(落盘 `$DSH_HOME/logs/ft/`)与设置页导出卡片;未实现主题/用户偏好的持久化接口,也不提供行情查询、图表、通用 SDK 代理或 Python 凭据桥。Key 由 DSH `credentials` 服务存储,本插件不保存第二份密钥文件。原未发布的 `ftshareCredentials` 草案已替换,不保留旧服务别名。
|
|
6
|
+
|
|
7
|
+
## 从 npm 安装
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
dsh plugin add @dsh-ft/dsh-fft-settings
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
外部用户从公共 npm 安装,不需要 ssh、也不需要改 pnpm 配置。它通常随入口包(模拟盘 / 工作台 / 画布)一起装上,单独安装只在需要独立设置页时使用。
|
|
14
|
+
|
|
15
|
+
## 给开发者和 agent 的接入约定
|
|
16
|
+
|
|
17
|
+
- Host 消费者声明 `inject = ['ftshareSettings']`,通过 `ctx.ftshareSettings.<namespace>` 调用;不要依赖插件排列顺序,也不要解构缓存命名空间属性(它随注册出现与消失)。
|
|
18
|
+
- 包名为 `@dsh-ft/dsh-fft-settings`(Host API 服务名 `ftshareSettings`、RPC 路由 `/api/ftshare-settings` 维持不变,旧消费者无需适配),bundle 入口仍为 `cordis.patch.yml`;设置页 ID 为 `dsh-fft`(显示名「金融终端」,`order: 120`),旧 ID `ftshare` 不再注册。
|
|
19
|
+
- 类型来源分两处:包主入口 `@dsh-ft/dsh-fft-settings` 是 Host 装配与 Host 类型;`/contract` 是**无 Node 运行时依赖**的汇总入口(纯类型、常量与输入校验),Host 类型来自 `src/core/` 与各 feature 的契约,浏览器 UI 类型来自 `/client`(SlotMap 合并与卡片 props)。`/client-api` 只导出 `createSettingsTransport`、`callSettingsRpc` 与通用类型,不再有特性适配器。
|
|
20
|
+
- 两条公开缝:Host 侧 `ctx.ftshareSettings.modules.register(module, owner)`,浏览器侧槽位 `ftshare.settings.card`。新增设置由插件自己写一个 feature 注册,不需要改本包源码,见「新增一种设置」。
|
|
21
|
+
- `apiVersion = 1`。新增设置领域应新增命名空间;破坏公开语义的修改需要重新评估协议版本。
|
|
22
|
+
- 本包没有修改 dsh_kline。下面的 kline 代码是接入示例,不代表消费者已经完成适配。
|
|
23
|
+
- 不读取 `.credentials.yaml`、不解析 kline 的旧 JSON 文件、不把 Key 写入普通 settings 或 localStorage,不通过修改全局 `process.env` 同步运行中消费者。
|
|
24
|
+
- 设置页有访问凭据与运行日志两张卡;本插件不展示应用版本,也不提供检查更新入口。
|
|
25
|
+
- 核心 `src/core/` 不得出现特性词汇或依赖 `src/features/`(由 `tests/architecture.test.mjs` 守护);内置 API Key 与第三方走同一套注册路径,没有内部后门。
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
## Host API v1
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
ctx.ftshareSettings.apiVersion // 1
|
|
32
|
+
const apiKey = ctx.ftshareSettings.apiKey
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
| 方法 | 返回与语义 |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| `describe()` | `Promise<ApiKeyStatus>`:`configured`、`writable`、`source?`、`maskedValue?`、进程内 `revision`、当前 `validation`;不返回完整密钥 |
|
|
38
|
+
| `resolve()` | `Promise<string \| undefined>`:每次解析当前 Key;仅限可信 Host 使用 |
|
|
39
|
+
| `set(value)` | `Promise<void>`:只保存,不联网测试;去首尾空白,拒绝空值、超过 512 字符和控制字符 |
|
|
40
|
+
| `clear()` | `Promise<void>`:只清除 DSH 保存值;可能露出 `.env` 回退值 |
|
|
41
|
+
| `configureAndTest(value)` | `Promise<ConfigureResult>`:先保存,再检查远端服务和 Key;保存和验证分别返回,测试失败不回滚 |
|
|
42
|
+
| `testConnection()` | `Promise<ValidationResult>`:先匿名检查远端,再验证调用时生效的 Key,不修改配置;无 Key 仍检查远端 |
|
|
43
|
+
| `getValidationStatus()` | `Promise<ValidationResult>`:读取最近验证结果,不联网 |
|
|
44
|
+
| `subscribe(listener)` | 返回取消订阅函数;失效通知,无参数、无密钥;回调重新读取状态 |
|
|
45
|
+
| `createEnvironment(base?)` | 返回新环境变量对象,用当前 Key 替换 `FTSHARE_API_KEY`;无 Key 删除该字段,不修改 base |
|
|
46
|
+
|
|
47
|
+
`resolve()` 与 `createEnvironment()` 的返回值包含秘密,禁止送到浏览器、模型工具结果、命令行参数或日志。`revision` 不是跨重启版本号,也不能用作持久化凭据标识。
|
|
48
|
+
|
|
49
|
+
### 配置与验证分开返回
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
const result = await apiKey.configureAndTest(userInput)
|
|
53
|
+
// 示例:保存成功,但 Key 未通过认证;远端服务正常
|
|
54
|
+
// {
|
|
55
|
+
// save: { status: 'saved', message: '已保存到 DSH 凭据存储' },
|
|
56
|
+
// validation: {
|
|
57
|
+
// status: 'partial',
|
|
58
|
+
// remote: { status: 'available', message: '远端服务正常' },
|
|
59
|
+
// apiKey: { status: 'auth_failed', message: 'API Key 未通过认证' },
|
|
60
|
+
// testedAt: '2026-09-16T00:00:00.000Z'
|
|
61
|
+
// }
|
|
62
|
+
// }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
- `save.status`:`saved` / `failed`。失败代码为 `invalid_input`、`read_only`、`save_failed`,保存失败不测试。
|
|
66
|
+
- `validation.status`:`not_tested` / `not_run` / `passed` / `partial` / `failed` / `superseded`。
|
|
67
|
+
- 分项状态:`available`、`auth_required`、`auth_failed`、`permission_denied`、`quota_exceeded`、`rate_limited`、`network_error`、`timeout`、`upstream_error`、`invalid_response`、`not_run`。
|
|
68
|
+
- `remote` 是远端服务结果,`apiKey` 是 Key 验证结果;`testedAt` 是本次探测起始时间。成功响应中的空数组也算通过,节假日或收盘不影响判定。
|
|
69
|
+
- 保存成功后,网络、权限或认证失败只影响 `validation`,不撤销 Key。若 RPC 中断而没有结果,客户端不能断言保存失败,应重新读取配置,再测试当前连接。
|
|
70
|
+
- 验证只保存在内存,重启后是“未测试”;不存储原始行情响应。
|
|
71
|
+
|
|
72
|
+
### 两项检测,最多两个请求
|
|
73
|
+
|
|
74
|
+
| 结果字段 | 检测目的 | 固定请求 | 是否携带 Key |
|
|
75
|
+
| --- | --- | --- | --- |
|
|
76
|
+
| `validation.remote` | 远端服务是否正常 | `GET https://market.ft.tech/gateway/api/v1/market/data/stock-candlesticks` | 不携带 |
|
|
77
|
+
| `validation.apiKey` | 当前 Key 是否通过认证 | `GET https://market.ft.tech/gateway/api/v2/market/data/stock_minutes` | 使用 `FTSHARE_API_KEY` 请求头 |
|
|
78
|
+
|
|
79
|
+
日 K 请求使用 `600519.SH`、day、不复权、最近 30 天、`limit=2`;历史分钟请求使用同一股票、1 分钟、不复权、最近 24 小时、`limit=1`。服务端实际限制为包含首尾的三个北京时间自然日,而非滚动 72 小时;24 小时最多覆盖两个自然日。`adjust_kind` 使用实测接受的小写 `none`;文档中的 `None` 会被实际接口以 HTTP 400 拒绝。参数固定,不查交易日历、不回溯补数据、不验证 OHLC 字段。
|
|
80
|
+
|
|
81
|
+
**成功条件是 HTTP 成功、业务 `code=200` 且 `data` 为数组;数组为空同样通过。** 本插件检查服务和认证结果,不检查行情数据完整性。HTTP 200 中的业务失败、错误响应结构不能当作成功。响应中的行情不公开返回、不持久化。
|
|
82
|
+
|
|
83
|
+
- 远端正常、Key 通过:`status=passed`;两项均为 `available`。
|
|
84
|
+
- 远端正常、Key 无效/未配置/受限:`status=partial`;`remote` 仍为 `available`,检查 `apiKey.status` 获取原因。不能把 `partial` 当作 Key 验证通过。
|
|
85
|
+
- 远端检查失败:`status=failed`;有 Key 时跳过验证,`apiKey.status=not_run`,不把服务故障归咎于 Key。
|
|
86
|
+
- 未配置 Key:仍执行匿名远端检查,Key 项显示 `auth_required` / “未配置 API Key”,不发送分钟请求。
|
|
87
|
+
- 明确的 401 认证错误显示“API Key 未通过认证”;权限、额度、限流等保留独立原因,不能一律判为 Key 无效,也不能据此宣称认证成功。
|
|
88
|
+
|
|
89
|
+
截至 2026-09-16 的无密钥/无效样例核查:日 K 不传 Key 或传明显无效 Key 均返回数据,**日 K 成功不能证明 Key 有效**;历史分钟不传 Key 返回 401 `api_key_header_missing`,明显无效 Key 返回 401 `api_key_malformed`。不根据“免费”标签推断免鉴权。检测 Key 时必须携带当前 Key;如果未来上游分钟接口改为完全匿名且忽略 Key,就必须改用明确要求鉴权的接口,不能将匿名成功判为 Key 有效。
|
|
90
|
+
|
|
91
|
+
每请求超时 8 秒,一轮最多两次顺序请求;无自动重试,响应体上限 128 KiB,禁止跟随重定向。目前没有找到公开且有契约的 FTShare health/专用凭据验证端点,本插件不宣称执行了独立 health API。
|
|
92
|
+
|
|
93
|
+
官方参数与响应格式:[股票K线](https://market.ft.tech/gateway/doc/p/owq0364i)、[股票历史分钟行情](https://market.ft.tech/gateway/doc/p/z9lsvrvu)。新增探测必须核对官方契约并补测试。
|
|
94
|
+
|
|
95
|
+
## 变更、来源与并发
|
|
96
|
+
|
|
97
|
+
- DSH 本地 provider 的优先级是:启动进程环境变量 → DSH 凭据存储 → 项目 `.env` → 用户 `.env`。进程环境变量为只读;`.env` 来自启动快照,修改后需要重启 DSH。
|
|
98
|
+
- 写入/清除只操作 DSH 凭据存储,不修改环境变量或 `.env` 文件。清除后仍可能显示已配置,应以 `describe()` 为准。
|
|
99
|
+
- 同时监听新版 `credentials/reference-updated` 和旧版 `credentials/updated`,仅处理 `FTSHARE_API_KEY`。
|
|
100
|
+
- `subscribe` 是失效提示,可能重复;消费者处理应幂等,并在自己的 `ctx.effect` 中取消订阅。
|
|
101
|
+
- 每次读取仍重新解析 provider;内部仅保留不可逆指纹判断无事件的变化,指纹不会公开返回。测试期间 Key 变化时中止旧请求并丢弃旧结果。
|
|
102
|
+
- 相同凭据同时测试会共享进行中的验证。保存操作串行化;一个请求正在测试时,另一个保存可使其失效,不会将旧结果归到新 Key。
|
|
103
|
+
- `createEnvironment` 只生成启动快照,不能改变已运行 Python 的环境。
|
|
104
|
+
|
|
105
|
+
## 浏览器与 RPC
|
|
106
|
+
|
|
107
|
+
浏览器使用类型化适配器,不读取完整明文 Key。`describe().maskedValue` 仅用于展示,例如 `••••••••a1b2`:固定八个掩码字符加生效 Key 的后四位;长度不超过四个字符时全部隐藏,未配置时省略该字段。输入框用其作占位提示,输入新 Key 后仍以密码形式显示,不把掩码当作表单值保存。清除、来源回退和外部变更后重新读取当前掩码。
|
|
108
|
+
|
|
109
|
+
调用示例(内置 API Key 卡的适配器在 `src/features/api-key/client-api.ts`,随 feature 走;通用入口只提供传输与信封):
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
import { callSettingsRpc, createSettingsTransport } from '@dsh-ft/dsh-fft-settings/client-api'
|
|
113
|
+
const transport = createSettingsTransport() // 每个插件建一次,复用
|
|
114
|
+
const status = await callSettingsRpc<ApiKeyStatus>(transport, 'apiKey', 'describe')
|
|
115
|
+
const result = await callSettingsRpc<ConfigureResult>(transport, 'apiKey', 'configureAndTest', { value: input })
|
|
116
|
+
const validation = await callSettingsRpc<ValidationResult>(transport, 'apiKey', 'testConnection')
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Host 在 DSH `connection` 出现时把设置调用注册成 `/api` 下的一条精确 Fetch 路由(`/api/ftshare-settings`):Host/Origin fence 与浏览器鉴权由共享的 `/api` 载体在分发前完成,插件只处理调用本身。不用 `connection.rpc.handle` 是因为它在核心内部通过属性访问读取 `webServer`,而该解析只沿祖先链,插件与 `webServer` 平级时注册不上。未安装浏览器传输时 Host API 仍可用。它不是自动生成的 `ctx.remote.ftshareSettings` namespace。
|
|
120
|
+
|
|
121
|
+
| endpoint(channel 内) | payload |
|
|
122
|
+
| --- | --- |
|
|
123
|
+
| `apiKey/describe` | `{}` |
|
|
124
|
+
| `apiKey/set` | `{ value: string }` |
|
|
125
|
+
| `apiKey/clear` | `{}` |
|
|
126
|
+
| `apiKey/configureAndTest` | `{ value: string }` |
|
|
127
|
+
| `apiKey/testConnection` | `{}` |
|
|
128
|
+
| `apiKey/getValidationStatus` | `{}` |
|
|
129
|
+
| `logs/stats` | `{}` |
|
|
130
|
+
| `logs/preview` | `{ lines?: number }`(1–200,默认 80) |
|
|
131
|
+
| `logs/export` | `{}` |
|
|
132
|
+
|
|
133
|
+
每个命名空间只派发自己显式登记的方法:`logs` 只有上面三个只读方法,`flush()`、`dispose()`、`filePath` 仅 Host 可用。
|
|
134
|
+
|
|
135
|
+
Connection 返回 `{ ok: true, value }` 或 `{ ok: false, error: { code, message, details } }`;适配器解包为对应结果,传输失败抛出通用错误。业务上的“保存成功、验证失败”仍是一次成功的 RPC,必须检查 `value.save` 与 `value.validation`,不能只看 `ok`。
|
|
136
|
+
|
|
137
|
+
不接受任意 URL、请求参数或方法名称。`resolve`、`createEnvironment`、`subscribe` 不对 RPC 暴露。HTTP 直接调用需要 Connection 的完整 envelope 与认证,优先使用适配器,不要对 URL 裸 POST 业务参数。
|
|
138
|
+
|
|
139
|
+
设置页自带样式,支持只读来源、加载反馈、保存结果、远端服务/API Key 分项结果、手动读取与凭据事件刷新。“测试当前连接”不会使用输入框中的草稿。另一个页面完成测试后,可点击“重新读取状态”读取其结果;当前没有独立的验证完成推送事件。核心只声明 `--ftshare-text`、`--ftshare-muted`、`--ftshare-panel`、`--ftshare-border`、`--ftshare-control`、`--ftshare-input`、`--ftshare-link`、`--ftshare-error`、`--ftshare-accent`、`--ftshare-accent-ink`、`--ftshare-accent-on-surface`(声明在卡片根 `.ftshare-settings` 上,前八项取值来自宿主调色板 `--dsw-alias-*`,因此跟随 DSH 的黑夜/白天以及任何已注册的主题;后三项读下面说的品牌 token,并带同值 fallback)与 section 外壳样式;卡片自己的 CSS 随卡片组件渲染,见「新增一种设置」。
|
|
140
|
+
|
|
141
|
+
### 品牌 token(`--ft-*`)
|
|
142
|
+
|
|
143
|
+
浏览器半在 `theme` 服务就绪后调用一次 `ctx.theme.overrideTokens`,往 `body` 上叠一层**只增不改**的 FT 品牌色,不覆盖任何 `--dsw-alias-*`:
|
|
144
|
+
|
|
145
|
+
| token | 值 | 用途 |
|
|
146
|
+
| --- | --- | --- |
|
|
147
|
+
| `--ft-accent` | `#f0c433` | FT 黄:设置页主按钮、eyebrow、焦点环 |
|
|
148
|
+
| `--ft-accent-ink` | `#171717` | 黄底上的文字 |
|
|
149
|
+
| `--ft-accent-warm` | 亮 `#cf5623` / 暗 `#ff8352` | 交易橙:模拟盘等行情/交易界面的主色 |
|
|
150
|
+
| `--ft-accent-warm-hover` | 亮 `#b8481b` / 暗 `#ff9a72` | 交易橙按钮的 hover |
|
|
151
|
+
| `--ft-accent-warm-ink` | 亮 `#ffffff` / 暗 `#1a120e` | 橙底上的文字 |
|
|
152
|
+
| `--ft-accent-warm-soft` | 亮 `#fbeee8` / 暗 `#2b1d16` | 选中态的浅橙底 |
|
|
153
|
+
| `--ft-wechat` | `#2ebd68` | 企微绿:SSO 卡片的品牌色 |
|
|
154
|
+
| `--ft-wechat-ink` | `#102419` | 绿底上的文字 |
|
|
155
|
+
|
|
156
|
+
约束:这层是**便利层,不是依赖层**。本插件缺席、或宿主没有 `theme` 服务时,消费者必须继续用同值 CSS fallback 显示,所以每个 `var(--ft-*)` 都要带 fallback,且与上表逐字一致(按调色板取值的 token 用 `var(--ft-accent-warm, light-dark(#cf5623, #ff8352))` 写全两套);`tests/brand.test.mjs` 会扫描所有子插件并挡住漂移。它只发布颜色,不是主题设置 API:没有持久化、没有设置项,也不注册可选主题。
|
|
157
|
+
|
|
158
|
+
## 运行日志(`logs` 命名空间)
|
|
159
|
+
|
|
160
|
+
设置页第二张卡「运行日志」:常驻采集器把本进程的 cordis 日志落到 `$DSH_HOME/logs/ft/`,卡片显示采集状态与最近若干行,并提供两个导出入口——「导出日志」得到单个 `.log`,「导出诊断包」得到含 manifest 与额外来源原文的 `.zip`。采集器随插件启动,**设置插件被禁用或未安装时没有日志采集**。
|
|
161
|
+
|
|
162
|
+
```yaml
|
|
163
|
+
# profiles/<p>/cordis.patch.yml
|
|
164
|
+
- id: dsh-fft-settings
|
|
165
|
+
config:
|
|
166
|
+
logs:
|
|
167
|
+
level: warn # warn(默认)|debug;不提供 info(它会连 warn 一起丢掉)
|
|
168
|
+
maxBytes: 8388608 # 单文件上限,超过即轮转(默认 8 MiB)
|
|
169
|
+
keep: 3 # 轮转保留份数
|
|
170
|
+
sources: # 导出时一并打包的额外来源:文件路径或目录
|
|
171
|
+
- ~/.dsh/logs/plugins.log
|
|
172
|
+
- ~/Library/Logs/DSH Desktop/harness.log
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
四个字段都有安全默认值,不写 `config.logs` 也能挂载。**配置写错会让整个插件不加载**(`level` 不是 `warn`/`debug`,或 `maxBytes`/`keep` 越界,cordis 在校验阶段抛 `ValidationError`);改回合法值即恢复。
|
|
176
|
+
|
|
177
|
+
使用注意:桌面端(Electron)下载**不弹保存对话框**,文件落在系统下载目录;日志可能含本地路径与标识,外发前请自查。导出的诊断包里带覆盖范围与盲区清单,用于判断「日志里没有」不等于「没问题」。
|
|
178
|
+
|
|
179
|
+
## dsh_kline 接入示例与改动清单
|
|
180
|
+
|
|
181
|
+
完整对照见 [dsh_kline 实际源码 → 接入后代码](docs/kline-integration.md),基于 `d6253f0` 核对了 `src/index.ts`、`server.py`、`tools/fetch.py` 与启动配置;凭据桥那一段已随上游 `v0.4.0` 发布,对照里的「接入后」示例只作历史记录读。包括 Host 注入/适配器、Python MCP 和图表 HTTP 共用调用点、SDK 动态取 Key,以及哪些私有 IPC 代码仍需 kline 自己实现。
|
|
182
|
+
|
|
183
|
+
当前真实代码(`dsh_kline/tools/fetch.py::_ftshare_market_api`):
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
key = _valid_ftshare_key(os.environ.get("FTSHARE_API_KEY"))
|
|
187
|
+
headers = {"FTSHARE_API_KEY": key} if key else None
|
|
188
|
+
return ft.market_api(timeout=timeout, headers=headers)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
DSH 模式建议改为(`settings_bridge` 为 kline 待实现的私有 IPC 客户端):
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
resolved = settings_bridge.call("resolveForPython", {})
|
|
195
|
+
key = _valid_ftshare_key(resolved.get("value"))
|
|
196
|
+
if not key:
|
|
197
|
+
raise RuntimeError("请先在 FTShare 设置中配置 API Key")
|
|
198
|
+
return ft.market_api(timeout=timeout, headers={"FTSHARE_API_KEY": key})
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
对应 Host 私有适配器调用 `ctx.ftshareSettings.apiKey.resolve()`。**这不是浏览器 RPC 方法,也不是本包已经提供的 Python 桥。** 以下表格说明其余接入关系;详细文档提供了完整配置/测试适配器代码。
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
### 1. Host 消费共享服务
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
208
|
+
import type {} from '@dsh-ft/dsh-fft-settings'
|
|
209
|
+
|
|
210
|
+
export const inject = ['webServer', 'ftshareSettings']
|
|
211
|
+
export function apply(ctx: Context): void {
|
|
212
|
+
const apiKey = ctx.ftshareSettings.apiKey
|
|
213
|
+
ctx.effect(() => apiKey.subscribe(() => {
|
|
214
|
+
// 由 kline 实现:失效其凭据相关能力缓存,通知 Python 重新读取。
|
|
215
|
+
}), 'kline: API key invalidation')
|
|
216
|
+
|
|
217
|
+
// 在 kline 自己的业务请求入口内调用:
|
|
218
|
+
// const currentKey = await apiKey.resolve()
|
|
219
|
+
// const status = await apiKey.describe()
|
|
220
|
+
// const report = await apiKey.testConnection()
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
主包应在运行时安装/组合本插件,不能只增加类型依赖。Host 类型名为 `FtshareSettingsService` 和 `ApiKeySettings`。不应再注入旧的 `ftshareCredentials`。
|
|
225
|
+
|
|
226
|
+
### 2. 对齐现有工具与页面
|
|
227
|
+
|
|
228
|
+
| kline 现有能力 | 建议委托 |
|
|
229
|
+
| --- | --- |
|
|
230
|
+
| `configure_ftshare(api_key, test_connection=true)` | `apiKey.configureAndTest(value)` |
|
|
231
|
+
| `configure_ftshare(..., test_connection=false)` | `apiKey.set(value)` |
|
|
232
|
+
| `configure_ftshare(api_key="")` | `apiKey.clear()`;不要调用 `set("")` |
|
|
233
|
+
| `test_ftshare_connection` | `apiKey.testConnection()` |
|
|
234
|
+
| `data_source_status` 的凭据/检测结果 | `apiKey.describe()`;SDK 版本等由 kline 自己补充 |
|
|
235
|
+
| 原 `capabilities` | 新结果只表示远端服务和 Key 状态;不能从空数据成功推导行情完整性,行情能力由 kline 自行处理 |
|
|
236
|
+
|
|
237
|
+
本插件不支持 `persist=false` 的进程临时覆盖。kline 的 DSH 模式应取消该选项或明确返回不支持,不能静默把临时配置变成持久化配置。
|
|
238
|
+
|
|
239
|
+
kline 图表 HTTP API 和 Python MCP 是两个入口:只修改 `src/index.ts` 的页面代理不能覆盖直接进入 `server.py` 的 MCP 调用。两者都需要委托共享服务。可保持旧工具名:`key_saved` 对应 `save.status === "saved"`;`connection_ok` 对应 `validation.remote.status === "available"`;新增或映射 Key 检查字段时使用 `validation.apiKey.status === "available"`。不要只用一个 `ok` 混合保存、远端和 Key 三种结果,也不要把这些字段当作日 K/分钟行情能力报告。
|
|
240
|
+
|
|
241
|
+
### 3. Python 进程桥(由 kline 后续实现)
|
|
242
|
+
|
|
243
|
+
本包没有 Python 可直接读取明文的公开 HTTP 端点。推荐由 kline Host 自己提供每实例、仅本机、带认证的私有 IPC:
|
|
244
|
+
|
|
245
|
+
1. Python 在一次行情操作开始时向 Host 取当前 Key;Host 调用 `apiKey.resolve()`,一次操作使用同一凭据快照。
|
|
246
|
+
2. Python 显式为 SDK 传 Key,不读第二份文件;未配置必须清除旧值,不能静默回退 kline 的 `ftshare-credentials.json`。
|
|
247
|
+
3. Host 的变更订阅用于失效缓存;不能仅依赖事件而永远缓存明文 Key。
|
|
248
|
+
4. Python 的配置/测试 MCP 工具也通过私有桥委托 Host,不能再自己写 Key 或重复探测。
|
|
249
|
+
5. 私有凭据桥与浏览器 RPC 分离,绝不把 `resolve()` 加进浏览器 API 或模型工具。
|
|
250
|
+
|
|
251
|
+
仅需要启动时配置的消费者可以使用:
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
const env = await ctx.ftshareSettings.apiKey.createEnvironment(process.env)
|
|
255
|
+
// 交给进程启动器;禁止打印 env。已运行进程不会因此更新。
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
kline 的独立运行模式可以保留自己的策略,但须与 DSH 模式分开,避免两套凭据互相覆盖。本次未修改 kline,也未实现此桥。
|
|
259
|
+
|
|
260
|
+
## 开发、验证与范围
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
pnpm install
|
|
264
|
+
pnpm typecheck
|
|
265
|
+
pnpm test
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Node >=22.19。`test` 先构建,再运行 Node 测试:Cordis 服务生命周期、命名空间注册表的先校验后写入与撤销、存储来源与事件、远端/Key 独立验证、节假日空数据成功、业务错误与网络错误、响应限额、并发与旧结果隔离、RPC 白名单、页面状态模型、槽位声明与卡片注册、日志采集器的级别门槛/节流合并/脱敏/轮转/启动回填/导出体积封顶、配置 Schema 的原生 Schemastery 判定与「配置写错则不挂载」、接缝直挂(`createSettingsHost` + `modules.register`)、以及核心不含特性词汇与浏览器产物隔离的架构守护。默认全部使用模拟凭据/响应,不发真实 FTShare 请求,不读取用户真实 Key。发布前若需真实联调,应使用明确授权的 Key,记录已验证接口及时间,不输出 Key。
|
|
269
|
+
|
|
270
|
+
代码分层(`src/core/` 不得 import `src/features/`):
|
|
271
|
+
|
|
272
|
+
| 目录 | 职责 |
|
|
273
|
+
| --- | --- |
|
|
274
|
+
| `src/core/` | 缝:`contract.ts` 通用契约、`module-registry.ts` 活注册表、`rpc-core.ts` 活路由表、`transport.ts`/`client-transport.ts` 两侧传输、`shell.tsx` section 外壳与槽位声明、`styles.ts` 变量与外壳样式 |
|
|
275
|
+
| `src/features/api-key/` | 第一个 feature:契约、Host 模块、RPC 方法、浏览器适配器、卡片、状态模型、探测、凭据协调、卡片样式 |
|
|
276
|
+
| `src/features/logs/` | 第二个 feature:常驻日志采集器(`collector.ts`/`format.ts`/`export.ts`/`home.ts`)、`logs` 子配置 schema、Host 模块工厂、RPC 方法、浏览器适配器、卡片与卡片样式 |
|
|
277
|
+
| `src/index.ts` / `src/client.tsx` | 只装配:Host 侧提供 `Config`、provide 服务并注册内置模块,浏览器侧注册 section 与内置卡片 |
|
|
278
|
+
| `src/contract.ts` / `src/rpc.ts` | 对外入口的再导出汇总(`/contract`、`/client-api`) |
|
|
279
|
+
|
|
280
|
+
### 新增一种设置:写一个 feature,经公开缝注册
|
|
281
|
+
|
|
282
|
+
其他插件**不改本包源码**即可登记一项设置:本包自己的 API Key 与运行日志就是 `src/features/api-key/`、`src/features/logs/` 这两个 feature,走与第三方完全相同的一条路。完整设计记录见[服务化扩展设计](docs/extension-service-design.md)与配套[架构/时序图](docs/extension-service-sequences.html)。
|
|
283
|
+
|
|
284
|
+
两条缝各管一半:行为跨包走 Cordis 服务,UI 位置跨包走槽位。
|
|
285
|
+
|
|
286
|
+
| 缝 | 平面 | 形式 | 谁声明 |
|
|
287
|
+
| --- | --- | --- | --- |
|
|
288
|
+
| 命名空间与调用 | Host | `ctx.ftshareSettings.modules.register(module, owner)` | 任意插件的 Host 半 |
|
|
289
|
+
| 卡片位置 | 浏览器 | 槽位 `ftshare.settings.card`(`kind: list`, `scope: root`) | 本包 section 注册时在 `children` 里声明 |
|
|
290
|
+
|
|
291
|
+
**Host 半**:按形状写一个模块即可,不必 import 本包的运行时导出(`SettingsModule` 是结构化类型)。
|
|
292
|
+
|
|
293
|
+
```ts
|
|
294
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
295
|
+
import type { SettingsModule } from '@dsh-ft/dsh-fft-settings/contract'
|
|
296
|
+
|
|
297
|
+
export const klineSettingsModule: SettingsModule<'kline', KlineSettings> = {
|
|
298
|
+
namespace: 'kline',
|
|
299
|
+
inject: ['storage'], // 模块实际用到的宿主服务
|
|
300
|
+
create(ctx) {
|
|
301
|
+
const service = createKlineSettings(ctx) // 读写在插件自己的代码里
|
|
302
|
+
return { service, rpcMethods: createKlineRpcMethods(service) }
|
|
303
|
+
},
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export const inject = ['ftshareSettings']
|
|
307
|
+
|
|
308
|
+
export function apply(ctx: Context): void {
|
|
309
|
+
ctx.inject(['ftshareSettings'], scoped => {
|
|
310
|
+
const reg = scoped.ftshareSettings.modules.register(klineSettingsModule, scoped)
|
|
311
|
+
reg.service // 自己 create() 返回的实例
|
|
312
|
+
reg.namespace // 'kline'
|
|
313
|
+
reg.dispose() // 幂等;owner fiber 释放时注册表已代为调用
|
|
314
|
+
})
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
注册是**先校验后写入**,失败不留痕(不写服务属性、不写路由表、不调用 `create`):
|
|
319
|
+
|
|
320
|
+
| 项 | 规则 |
|
|
321
|
+
| --- | --- |
|
|
322
|
+
| 命名空间格式 | `^[a-zA-Z][a-zA-Z0-9]*$`,禁路径分隔符 |
|
|
323
|
+
| 保留名 | `apiVersion`、`modules`、`constructor`、`prototype`、`__proto__` |
|
|
324
|
+
| 重复命名空间 | 抛 `Duplicate settings namespace: <ns>`;撤销后可以重试 |
|
|
325
|
+
| 服务依赖 | `module.inject` 声明的服务必须在 `owner` 上可解析,否则抛错且不调用 `create`;settings 不替模块声明任何服务 |
|
|
326
|
+
| 同步性 | `create` 必须同步返回 |
|
|
327
|
+
| 生命周期 | 注册表在 `owner` 上装 effect:owner fiber 释放 → 服务属性与该命名空间的全部 RPC 路由一起消失;返回的 `dispose()` 幂等 |
|
|
328
|
+
| 属性可见性 | 命名空间属性注册后动态出现、撤销后消失;消费方不要在自己 apply 时解构缓存 |
|
|
329
|
+
|
|
330
|
+
消费者要读别人的命名空间时,自己 merge 一行(生产者靠 `register` 的泛型推断,不需要 merge):
|
|
331
|
+
|
|
332
|
+
```ts
|
|
333
|
+
declare module '@dsh-ft/dsh-fft-settings/contract' {
|
|
334
|
+
interface FtshareSettingsNamespaces { cockpit: CockpitSettings }
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
**浏览器半**:卡片注册进槽位,`import type {} from '@dsh-ft/dsh-fft-settings/client'` 只为拿到 SlotMap 合并(type-only,运行时零依赖)。
|
|
339
|
+
|
|
340
|
+
```tsx
|
|
341
|
+
import type {} from '@dsh-ft/dsh-fft-settings/client'
|
|
342
|
+
|
|
343
|
+
export function apply(ctx: Context): void {
|
|
344
|
+
ctx.slots.inject('ftshare.settings.card', () => ctx.slots.register(
|
|
345
|
+
{ name: 'ftshare.settings.card', id: 'kline', order: 40, label: 'K线' },
|
|
346
|
+
KlineCard,
|
|
347
|
+
))
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
| 注册项 | 规则 |
|
|
352
|
+
| --- | --- |
|
|
353
|
+
| `id` | 必填、全局唯一;同 id 同 priority 在装载期抛错 |
|
|
354
|
+
| `order` | 升序排列。省略的 `order` 按 DSH 0.2.0-rc.2 的 ui-slots 语义当作 0,内置 API Key 卡为 10、运行日志卡为 20 —— 要排在它们之后必须显式给更大的 `order` |
|
|
355
|
+
| `label` | `string \| (() => string)`,section 内作分组标题用;缺省不显示 |
|
|
356
|
+
| `priority` | **不对外公开**:它能静默顶掉别人的卡片;文档与示例只用 `id`/`order`/`label` |
|
|
357
|
+
|
|
358
|
+
卡片组件拿到的是槽位标准份额(runtime / renderSlot / store / inject face / locale),**拿不到 settings 的内部状态**:没有服务对象、没有凭据协调、没有验证模型。卡片要的数据走 `/client-api`:
|
|
359
|
+
|
|
360
|
+
```ts
|
|
361
|
+
import { callSettingsRpc, createSettingsTransport } from '@dsh-ft/dsh-fft-settings/client-api'
|
|
362
|
+
const transport = createSettingsTransport() // 每个插件建一次,复用
|
|
363
|
+
const value = await callSettingsRpc<Value>(transport, 'kline', 'get')
|
|
364
|
+
await callSettingsRpc(transport, 'kline', 'set', { key: 'kline setting 1', value })
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
**卡片自带样式**:核心只提供 `--ftshare-*` 变量与 section 外壳样式,卡片自己的 CSS 由组件内的 `<style>` 随挂载/卸载增删(槽位注册选项没有放 CSS 的位置)。内置 API Key 卡与第三方卡片遵守同一条规则,不要把卡片 CSS 加回核心。
|
|
368
|
+
|
|
369
|
+
其它约束:
|
|
370
|
+
|
|
371
|
+
- RPC 只派发模块 `rpcMethods` 里显式登记的方法,不遍历服务对象;`resolve()`、`createEnvironment()` 这类含秘密的方法不会因为注册了服务而自动开放。
|
|
372
|
+
- 浏览器半不能 import Host 模块、凭据探测或其它卡片的组件;跨命名空间读取只在 Host 侧存在。
|
|
373
|
+
- 需要新的宿主服务或 npm 包时,在模块/卡片自己的作用域里声明,并按 DSH 加载要求给 `package.json` 增加依赖与 `dsh.client.inject` 条目。
|
|
374
|
+
- 新设置要补测试:注册与撤销、白名单、卡片渲染与排列。
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
### 本地开发时加载最新代码
|
|
378
|
+
|
|
379
|
+
`pnpm build` 只更新磁盘产物。已运行的 DSH Host 会保留载入的后端模块,浏览器刷新却可能拿到新的前端 bundle;修改 Host 代码后需要重启 `dsh web`,再重新打开设置页。仅点击“重新读取状态”或刷新网页不会重载 Host。若已配置但只显示掩码、没有后四位,同时出现旧版错误文案,应先检查 Host 是否启动于本次构建之前。
|
|
380
|
+
|
|
381
|
+
## DSH 版本兼容性
|
|
382
|
+
|
|
383
|
+
已隔离验证 `0.1.6-alpha.1`:构建、类型检查、44 项测试及真实凭据/Connection RPC 检查通过;现有依赖范围不接受该 alpha,升级仍需同步调整依赖解析。当前未发现已发布的正式 `0.1.6`。详见 [版本、证据及升级边界](docs/compatibility-dsh-0.1.6-alpha.1.md)。
|
|
384
|
+
|
|
385
|
+
## 源码逻辑 ER 图
|
|
386
|
+
|
|
387
|
+
以下是代码实体关系,不是数据库表;图中标注源文件路径、关系数量及当前实现的边界。两张图按 0.3.0 的 `src/core/` + `src/features/api-key/` 分层绘制:核心只留两条缝与外壳,全部业务词汇归特性所有。
|
|
388
|
+
|
|
389
|
+

|
|
390
|
+
|
|
391
|
+

|
|
392
|
+
|
|
393
|
+
SVG 可直接保存或编辑:[模块与接口](docs/ftshare-settings-er.svg)、[保存与检测结果](docs/ftshare-settings-results-er.svg)。同目录保留 HTML 预览(HTML 为源文件,SVG 由 HTML 导出)。图使用本地可用字体回退,不依赖外部字体下载;不同系统字体外观可能略有差异。
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# dsh-fft-settings bundle patch
|
|
2
|
+
#
|
|
3
|
+
# `dsh.bundle.patch` layer of the published package: installing through the
|
|
4
|
+
# official CLI —
|
|
5
|
+
#
|
|
6
|
+
# dsh plugin --profile <name> add @dsh-ft/dsh-fft-settings
|
|
7
|
+
#
|
|
8
|
+
# — appends this single `insert` (one plugin row) to the bundle stack. No
|
|
9
|
+
# manual profile edits.
|
|
10
|
+
#
|
|
11
|
+
# The connection row from dsh-web-app is deliberately NOT overridden: on
|
|
12
|
+
# DSH 0.1.5-rc.2 the connection plugin already waits for webServer
|
|
13
|
+
# internally via ctx.inject(['webServer'], ...), so its /api transport
|
|
14
|
+
# mounts without any row-level inject, and pinning its activation to
|
|
15
|
+
# webServer would break profiles that only provide webRuntime.
|
|
16
|
+
- insert:
|
|
17
|
+
- id: dsh-fft-settings
|
|
18
|
+
name: '@dsh-ft/dsh-fft-settings'
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# DeepSeek Harness 0.1.6 兼容性检查
|
|
2
|
+
|
|
3
|
+
检查日期:2026-09-17。对象为 FTShare Settings;没有升级工作区 DSH 子仓,没有修改 dsh_kline。
|
|
4
|
+
|
|
5
|
+
## 版本与结论
|
|
6
|
+
|
|
7
|
+
官方 npm registry 当日没有 `0.1.6` 正式版;本次实际验证 `0.1.6-alpha.1`(alpha 标签),对应 Git tag `dsh-v0.1.6-alpha.1`、commit `0a15e36e7f82b6ed45af6fa9759f29b40dcd965d`。当日 latest 为 `0.1.5-rc.1`,next 为 `0.1.5-rc.2`。工作区固定的 DSH 源码版本仍为 `0.1.2-rc.1`。
|
|
8
|
+
|
|
9
|
+
**已验证的插件代码和接口兼容该 alpha 版本,但现有依赖声明不满足该版本,不能直接称为开箱即用的升级。** 尚未验证整个桌面应用和其他插件。
|
|
10
|
+
|
|
11
|
+
## 已完成的验证
|
|
12
|
+
|
|
13
|
+
在工作区忽略目录创建隔离插件副本,把其全部 DSH 依赖固定为 `0.1.6-alpha.1`;未修改实际插件的依赖版本或 lockfile。
|
|
14
|
+
|
|
15
|
+
| 验证 | 结果 |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| TypeScript 类型检查 | 通过 |
|
|
18
|
+
| Host 编译与 browser bundle 构建 | 通过 |
|
|
19
|
+
| 现有自动化测试 | 44 / 44 通过 |
|
|
20
|
+
| 真实 alpha LocalCredentialProvider + Cordis 插件装配 | 通过 |
|
|
21
|
+
| 临时旧格式凭据文件自动迁移至 version/refs 格式 | 通过 |
|
|
22
|
+
| 保存、即时解析、掩码后四位、清除 | 通过 |
|
|
23
|
+
| credentials/reference-updated 变更通知 | 通过 |
|
|
24
|
+
| 真实 alpha HostConnectionService 的 HTTP RPC | 通过 |
|
|
25
|
+
| 未认证 401、非可信 Origin 403 | 通过 |
|
|
26
|
+
| Host-only resolve 拒绝公开调用、额外 JSON 字段拒绝 | 通过 |
|
|
27
|
+
|
|
28
|
+
运行时检查只使用临时目录和虚构凭据,没有读取或修改用户凭据,也没有使用虚构 Key 请求 FTShare。隔离目录为 `build/.cache/ftshare-compat-plugin-0.1.6`;可在其中执行 `pnpm test`、`pnpm run typecheck`、`node compat-smoke.mjs` 复核(缓存目录不随仓库发布)。
|
|
29
|
+
|
|
30
|
+
## 接口核对
|
|
31
|
+
|
|
32
|
+
- `../src/modules/api-key/host.ts` 使用的 `credentialRef`、`resolve/describe/set/unset` 和引用更新事件继续可用。凭据基础包对应源码在比较范围内未改变。
|
|
33
|
+
- `../src/index.ts` / `../src/rpc-core.ts` 使用的 `connection.rpc.handle(channel, handler)` 与客户端 `call(...)` 契约保留;新增流式能力不要求现有普通 RPC 修改。
|
|
34
|
+
- `../src/client.tsx` / `../src/card-registry.ts` 使用的设置 slot 注册接口保留;类型检查和构建通过。没有执行新版完整 DSH 页面交互测试。
|
|
35
|
+
- 新版 LocalCredentialProvider 使用带 `version: 1`、`refs`、`records` 的凭据文档,启动时可迁移可识别的旧平面格式。插件通过 provider API 访问,不依赖文件布局;真实临时文件迁移已验证。异常格式仍由上游拒绝,不能保证任意手写文件自动迁移。
|
|
36
|
+
|
|
37
|
+
## 升级时需要调整的依赖范围
|
|
38
|
+
|
|
39
|
+
当前 `package.json`:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"dependencies": { "@deepseek-ai/dsh-credentials": "^0.1.0-rc.8" },
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.2-rc.1",
|
|
46
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.2-rc.1",
|
|
47
|
+
"@deepseek-ai/dsh-api-remotes": "^0.1.2-rc.1"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
npm semver 的上述范围均不接纳 `0.1.6-alpha.1`,因为它属于不同版本基数的预发布版。稳定版 `0.1.6` 会符合这些范围,但本次未有该正式版本可供验证。
|
|
53
|
+
|
|
54
|
+
确定升级到该 alpha 时,应显式允许 `0.1.6-alpha.1`,例如将相应范围改为 `原范围 || 0.1.6-alpha.1`,并统一解析 Host 与插件的 DSH 依赖、重新生成 lockfile。也可以在整体迁移时统一精确固定该版本。然后在目标桌面 runtime 验证插件装载、设置页面、重连与跨插件调用。此次只检查兼容性,因此未修改生产依赖范围和 submodule 指针。
|
|
55
|
+
|
|
56
|
+
## 验证边界
|
|
57
|
+
|
|
58
|
+
上述结论覆盖 FTShare Settings 的类型、构建、已有测试及所列真实 Host 接口;不等于整个 dsh-ft、Electron 安装包或 kline 已完成新版回归。kline 的 Python 私有桥仍是接入设计,并未实现。未来正式 `0.1.6` 发布后应重新核对版本与测试,不能把 alpha 结果自动外推到正式版。
|