@wingsky-1/dsh-decision-gateway 0.2.6

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.
Files changed (66) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +56 -0
  3. package/README.md +56 -0
  4. package/cordis.patch.yml +7 -0
  5. package/lib/THIRD-PARTY-LICENSES +35 -0
  6. package/lib/client/api/contract.d.ts +37 -0
  7. package/lib/client/api/interface.d.ts +9 -0
  8. package/lib/client/api/routes.d.ts +11 -0
  9. package/lib/client/index.d.ts +8 -0
  10. package/lib/client/locale.d.ts +31 -0
  11. package/lib/client/locales.d.ts +122 -0
  12. package/lib/client/settings/card.d.ts +7 -0
  13. package/lib/client/settings/connection.d.ts +10 -0
  14. package/lib/client/settings/format.d.ts +4 -0
  15. package/lib/client/settings/history.d.ts +9 -0
  16. package/lib/client/settings/presets.d.ts +9 -0
  17. package/lib/client/settings/prob.d.ts +10 -0
  18. package/lib/client.js +1518 -0
  19. package/lib/index.d.ts +32 -0
  20. package/lib/index.js +3142 -0
  21. package/lib/server/api/deps.d.ts +53 -0
  22. package/lib/server/api/impl/handlers.d.ts +11 -0
  23. package/lib/server/api/impl/route.d.ts +28 -0
  24. package/lib/server/api/impl/service.d.ts +4 -0
  25. package/lib/server/api/interface.d.ts +3 -0
  26. package/lib/server/config/deps.d.ts +32 -0
  27. package/lib/server/config/impl/envelope.d.ts +9 -0
  28. package/lib/server/config/impl/model.d.ts +54 -0
  29. package/lib/server/config/impl/paths.d.ts +12 -0
  30. package/lib/server/config/impl/service.d.ts +37 -0
  31. package/lib/server/config/interface.d.ts +12 -0
  32. package/lib/server/history/deps.d.ts +25 -0
  33. package/lib/server/history/impl/entry.d.ts +29 -0
  34. package/lib/server/history/impl/hash.d.ts +8 -0
  35. package/lib/server/history/impl/paths.d.ts +2 -0
  36. package/lib/server/history/impl/redact.d.ts +2 -0
  37. package/lib/server/history/impl/service.d.ts +30 -0
  38. package/lib/server/history/interface.d.ts +4 -0
  39. package/lib/server/store/deps.d.ts +6 -0
  40. package/lib/server/store/impl/io.d.ts +24 -0
  41. package/lib/server/store/interface.d.ts +4 -0
  42. package/lib/server/tools/deps.d.ts +83 -0
  43. package/lib/server/tools/impl/client.d.ts +62 -0
  44. package/lib/server/tools/impl/define.d.ts +30 -0
  45. package/lib/server/tools/impl/precheck.d.ts +8 -0
  46. package/lib/server/tools/impl/probe.d.ts +24 -0
  47. package/lib/server/tools/impl/semaphore.d.ts +4 -0
  48. package/lib/server/tools/impl/service.d.ts +18 -0
  49. package/lib/server/tools/impl/validate.d.ts +17 -0
  50. package/lib/server/tools/interface.d.ts +7 -0
  51. package/lib/server/upgrade/deps.d.ts +37 -0
  52. package/lib/server/upgrade/impl/service.d.ts +13 -0
  53. package/lib/server/upgrade/impl/steps.d.ts +3 -0
  54. package/lib/server/upgrade/interface.d.ts +6 -0
  55. package/lib/shared/contract.d.ts +184 -0
  56. package/lib/shared/interface.d.ts +7 -0
  57. package/package.json +99 -0
  58. package/shared/client/ensure-style.d.ts +21 -0
  59. package/shared/client/i18n.d.ts +15 -0
  60. package/shared/dsh-home.d.ts +15 -0
  61. package/shared/host-utils.d.ts +65 -0
  62. package/shared/loopback.d.ts +21 -0
  63. package/shared/paths.d.ts +12 -0
  64. package/shared/settings-namespace.d.ts +82 -0
  65. package/shared/sse-hub.d.ts +76 -0
  66. package/shared/upgrade-tick.d.ts +11 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 wingsky-1
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.en.md ADDED
@@ -0,0 +1,56 @@
1
+ # dsh-decision-gateway
2
+
3
+ General-purpose assistant decision gateway (JEV is the first provider): frozen asking guides (English) + dual-track keys + local secret-shape precheck + official SystemOne calls (transport via the official `@typesafe-ai/sdk`, inlined at build time; base URL and model are both pinned, zero runtime dependencies).
4
+
5
+ Scope: suited for agent decisions needing calibrated binary / score / risk verdicts, secret-shaped text prechecked locally before egress, and auditable switches/history; not suited for auto-execution (advisory levels only, no executors), open-ended reasoning (frozen templates only), or reliable queues/transactional writes.
6
+
7
+ One-click install (restart `dsh web` afterwards to activate):
8
+
9
+ ```sh
10
+ dsh plugin --profile web add @wingsky-1/dsh-decision-gateway
11
+ ```
12
+
13
+ - Model tools: `ws_request_verdict` (decide), `ws_list_verdict_guides` (read-only).
14
+ - Loopback routes: `/api/dsh-decision-gateway/health|config|presets|history|test-connection`.
15
+ - 5 frozen asking guides (templateVersion always 1, English prose, zero preset questions): general / secret-leak (disabled by default) / plan-review / risk-check / custom. Callers bring the full question set per call via `questions_override` (1-20 questions, required; the first question drives the verdict, extra questions travel as context). Wording note: general changed from binary/two to a 2-10-candidate choice, custom changed from three to first-question-driven; templateVersion stays 1; stored history templateVersion remains observably 1. Tool params: `preset_id` is one of the 5 frozen ids or a custom id (custom:true entries from `ws_list_verdict_guides`); `state.lang` is en/zh/unknown and defaults to unknown when omitted; score questions carry no options but may carry 2-10 levels (default 1-5 when omitted, e.g. five levels 1-5 or two levels low-high rescaled to 1-5).
16
+ - Custom presets (`custom-presets.json`, absent means empty): incremental `PUT /config` key `customPresets` (full replace; ids must not collide with frozen, cap 0|1|2); custom ids are directly decidable (same switch/cap semantics); history stores a redacted snapshot of the called questions, and `GET /history` enriches display titles (only ids are stored).
17
+
18
+ ## Quick start
19
+
20
+ 1. Install and restart `dsh web` (command at the top); the dsh-decision-gateway card appears in settings, and service-available on the connection tab means the host side is mounted.
21
+ 2. Set the key (either): put an exported ENV name in `apiKeyRef` (recommended, the value never lands on disk); or unfold the plaintext section and paste the key (no double confirmation).
22
+ 3. Hit test-connection (`POST /test-connection`, empty body is legal): `ok` + `latencyMs` means end-to-end works; on `NO_KEY`, check the ENV export or whether the plaintext was saved.
23
+
24
+ ## Configuration
25
+
26
+ Three files under `~/.dsh/@wingsky-1/dsh-decision-gateway/` (`DSH_HOME`-aware, dirs 0700 / files 0600 / atomic writes):
27
+
28
+ - `config.json`: `{version:1, connection:{apiKeyRef?,hasPlaintextKey,timeoutMs:8000,maxConcurrency:4,truncBudget:32000}, presets:[5 ids+enabled+automationCap(0|1|2)], history:{perSession:200,totalSessions:50}}`;
29
+ - `presets.json`: switch overlay; `secrets.json`: the only plaintext location; `VERSION`: storage version tick.
30
+
31
+ PUT `/config`: `apiKeyRef` must match `^[A-Z][A-Z0-9_]{1,63}$`; mutually exclusive with `apiKeyPlaintext`; plaintext needs no confirmation (a `confirm` field is ignored when present); shape rejections are 400 with category only; retired keys like `baseUrl` are 400.
32
+
33
+ ## Security model
34
+
35
+ - **Off-device data**: truncated text + questions leave the device only when the local secret-shape precheck misses and a key is available; on hit (e.g. `sk-…`, `AKIA…`, `ghp_…`, private-key blocks, `password=`) nothing leaves and the decision routes to human (`appliedSource: local-precheck`, `choice: human`); a first-answer Noul (abstention) likewise forces tier none and routes to human.
36
+ - **Dual-track keys**: ENV reference (`apiKeyRef`) wins over plaintext; switching to ENV folds (clears) `secrets.json`; plaintext writes need no confirmation; mutual exclusion is still enforced server-side.
37
+ - **0600/0700**: namespace dir 0700, files 0600, temp-file + rename atomic writes.
38
+ - **Masked surface**: GET `/config` returns only the `apiKeyRef` name and `hasPlaintextKey`; key material is never echoed; shape rejections return only an `empty|too-short|charset` category.
39
+ - **secret preset warning**: `secret-leak` is disabled by default, enable it only when you must check untrusted text for real secrets (local precheck still runs first when enabled); history `snippetRedacted` is redacted-then-truncated to ≤200 chars; raw keys are never stored.
40
+ - **Pinned BaseURL**: `https://api.typesafe.ai/v1/systemone` is a load-asserted constant, never configurable; PUT with `baseUrl`-like keys is 400. The model is pinned to `jev-latest` under the same treatment; score floats rescale to 1..5 by sent level count (default five levels behave as round+1, all clamped; custom 2-10 levels travel in `levels`, e.g. five levels 1-5 or two levels low-high), tiers derive from confidence at ≥0.8 high/≥0.5 low (else none).
41
+
42
+ ## History
43
+
44
+ One jsonl file per (workdir rootHash, sessionId) (workdir comes from the session store, falling back to the caller directory): 200 entries per session rotation, 50 sessions total (count semantics only; no pinning on mtime ties). Stored entries carry templateVersion (always 1, observable; wording revisions do not bump the version). Query `root` accepts a full path, a `rootHash`, or a bare basename (matched against `rootDisplay`); deletion is single-session only (`root` + `sessionId` both required, ambiguous basenames are 400). Session titles enrich at read time for live sessions only (`sessionTitle`, falling back to the short id, never persisted).
45
+
46
+ ## Verification and troubleshooting
47
+
48
+ - Liveness: `GET /api/dsh-decision-gateway/health` returns `ok` / `version` / `templateVersion`.
49
+ - Fence: non-loopback callers always get 403, off-table methods get 405 (403 is checked first).
50
+ - Common failures: `NO_KEY` (no usable key), `PRESET_DISABLED` (preset switched off), `MUTUALLY_EXCLUSIVE` (`apiKeyRef` sent together with plaintext), key-shape 400s return only an `empty|too-short|charset` category.
51
+ - Missing history: prefer a full path or `rootHash` for `root` (basenames match against `rootDisplay`, ambiguous delete is 400); `GET /history` defaults to 100 entries, max 500.
52
+
53
+ ## Follow-ups (deferred, not in this version)
54
+
55
+ - **Startup self-check migration**: the assembly-time chain currently only anchors versions (seed when missing / no-op when anchored / refuse future versions); config self-checks and legacy migrations arrive with future steps. Plaintext double confirmation was removed with explicit user approval.
56
+ - **Non-grouped three-file writes**: config/presets/secrets are three independent atomic writes, not one transaction; a crash between writes may leave mixed old/new state (read side converges with fill-defaults). That crash window is tolerated, no WAL.
package/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # dsh-decision-gateway
2
+
3
+ 通用辅助决策网关(JEV 为首个 provider):frozen 出题规范(英文) + 双轨密钥 + 本地密形预检 + SystemOne 官方调用(经官方 `@typesafe-ai/sdk` 构建期内联传输,基址与模型双冻结,零运行时依赖)。
4
+
5
+ 适用:需要校准二选一 / 评分 / 风险二值建议的 agent 决策、密钥文本先本地预检再出境、开关与历史需审计留痕的场景;不适用:自动执行(本包只给建议等级,不持执行器)、开放式推理(只跑 frozen 模板题目)、可靠消息队列或事务组写。
6
+
7
+ 一键安装(安装后重启 `dsh web` 生效):
8
+
9
+ ```sh
10
+ dsh plugin --profile web add @wingsky-1/dsh-decision-gateway
11
+ ```
12
+
13
+ - 模型工具:`ws_request_verdict`(决议)、`ws_list_verdict_guides`(只读清单)。
14
+ - 回环路由:`/api/dsh-decision-gateway/health|config|presets|history|test-connection`。
15
+ - 5 预设 frozen 出题规范(templateVersion 恒为 1,英文描述,零考题):general / secret-leak(默认关闭)/ plan-review / risk-check / custom。调用方每次经 `questions_override` 自带全量题目(1-20 题,必填;首题驱动输出,多题仅首题决议)。措辞注:general 已由 binary/two 改为 2-10-candidate choice,custom 由 three 改为首题驱动,templateVersion 仍为 1;落史 templateVersion 可观测仍为 1。工具参数:`preset_id` 为 5 frozen id 或自建 id(`ws_list_verdict_guides` 的 custom:true 项);`state.lang` 为 en/zh/unknown,缺席默认为 unknown;score 题禁 options、可带 2-10 levels(缺席默认 1-5,如五档 1-5 或两档 low-high 重缩放到 1-5)。
16
+ - 自建预设(`custom-presets.json`,缺席即空):`PUT /config` 增量键 `customPresets` 全量替换(id 不可与 frozen 重名,cap 0|1|2);自建 id 可直接决议(开关/cap 同 frozen 语义);落史存调用题目快照(脱敏),`GET /history` enrich 展示标题(只存 id)。
17
+
18
+ ## 最短上手
19
+
20
+ 1. 安装并重启 `dsh web`(见顶部命令);设置页出现 dsh-decision-gateway 卡片,连接 tab 显示服务可用即宿主端已挂载。
21
+ 2. 配密钥(二选一):把已导出的 ENV 名填入 `apiKeyRef`(推荐,值永不落盘);或展开明文折叠,直接输入密钥保存(免二次确认)。
22
+ 3. 点测试连接(`POST /test-connection`,空体合法):回 `ok` + `latencyMs` 即端到端可用;报 `NO_KEY` 先检查 ENV 是否导出或明文是否保存。
23
+
24
+ ## 配置
25
+
26
+ 三文件独立存放于 `~/.dsh/@wingsky-1/dsh-decision-gateway/`(感知 `DSH_HOME`,目录 0700 / 文件 0600 / 原子写):
27
+
28
+ - `config.json`:`{version:1, connection:{apiKeyRef?,hasPlaintextKey,timeoutMs:8000,maxConcurrency:4,truncBudget:32000}, presets:[5 个 id+enabled+automationCap(0|1|2)], history:{perSession:200,totalSessions:50}}`;
29
+ - `presets.json`:开关覆盖层;`secrets.json`:明文密钥唯一落盘处;`VERSION`:存储版本刻度。
30
+
31
+ PUT `/config`:`apiKeyRef` 须匹配 `^[A-Z][A-Z0-9_]{1,63}$`;与 `apiKeyPlaintext` 互斥;明文免二次确认(`confirm` 字段若出现则忽略);形状拒收 400 仅回类别;`baseUrl` 等退役键 400。
32
+
33
+ ## 安全模型
34
+
35
+ - **离境数据**:仅当本地密形预检未命中且密钥可用时,才向官方基址发送截断后正文 + 题目;命中密形(如 `sk-…`、`AKIA…`、`ghp_…`、私钥块、`password=`)即不离境、直转人工(`appliedSource: local-precheck`,`choice: human`);首题答案为 Noul(弃权)同样不分级、直转人工(tier none)。
36
+ - **双轨密钥**:ENV 引用(`apiKeyRef`)优先于明文;切到 ENV 轨即折叠清空 `secrets.json`;明文写入免二次确认,服务端仍校验互斥。
37
+ - **0600/0700**:命名空间目录 0700,三文件 0600,经临时文件 + rename 原子写入。
38
+ - **掩码面**:GET `/config` 只回 `apiKeyRef` 名与 `hasPlaintextKey`,密钥原文永不回显;形状拒收 400 仅回 `empty|too-short|charset` 类别。
39
+ - **secret 预设警告**:`secret-leak` 默认关闭,仅在需检查不可信文本是否含真密钥时启用(启用后仍先过本地预检);历史 `snippetRedacted` 先脱敏后截断 ≤200 字,原始密钥永不入库。
40
+ - **BaseURL 写死**:`https://api.typesafe.ai/v1/systemone` 为加载断言常量,不接受任何配置覆盖;PUT 遇 `baseUrl` 类键直接 400。模型冻结为 `jev-latest`(同等 pin 待遇);score 回浮点按发送档数重缩放回 1..5(默认五档即 round+1,均钳制;自带 levels 用 `levels` 字段 2-10 档,如五档 1-5 或两档 low-high),tier 按置信度 ≥0.8 high/≥0.5 low 派生(其余 none)。
41
+
42
+ ## 历史
43
+
44
+ 按(工作目录指纹 rootHash,sessionId)分文件 jsonl(工作目录取自会话 store,取不到回落调用方目录):每会话 200 条轮转,总会话 50(只保数量语义,mtime 并列时不钉删谁)。落史条目含 templateVersion(恒为 1,可观测;措辞修订不 bump 版本)。查询 `root` 可传完整路径、`rootHash`,或仅传 basename(按 `rootDisplay` 匹配);删除仅支持单会话(`root` 与 `sessionId` 双必填,basename 多命中即 400)。会话标题仅活会话在读取时 enrich 显示(`sessionTitle`,无标题回落短 id,永不落盘)。
45
+
46
+ ## 验证与排障
47
+
48
+ - 存活:`GET /api/dsh-decision-gateway/health` 回 `ok` / `version` / `templateVersion`。
49
+ - 围栏:非本机回环一律 403,方法不在表里 405(先判 403 再判 405)。
50
+ - 常见失败:`NO_KEY`(无可用密钥)、`PRESET_DISABLED`(预设被关)、`MUTUALLY_EXCLUSIVE`(`apiKeyRef` 与明文同传)、密钥形状 400 仅回 `empty|too-short|charset` 类别。
51
+ - 历史查不到:`root` 传完整路径或 `rootHash` 最稳(basename 按 `rootDisplay` 匹配,删除多命中即 400);`GET /history` 缺省 100 条、上限 500。
52
+
53
+ ## 后续项(deferred,非本版实现)
54
+
55
+ - **启动自检迁移**:装配期升级链现只做版本锚定(缺席播种/已锚定空转/未来版本拒绝启动);配置形态自检与旧盘迁移留待加步骤时再写。明文写入免二次确认(用户已明确批准移除该 friction)。
56
+ - **三文件非组写**:config/presets/secrets 三次独立原子写,非事务组写;进程在写盘间隙崩溃可能留下新旧混搭(读侧以“缺口补默认”收敛),该崩溃窗口被容忍,不做预写日志。
@@ -0,0 +1,7 @@
1
+ # dsh-decision-gateway bundle patch:向 web profile 名册插入通用辅助决策网关(JEV 为首个 provider)。
2
+ # 主机端(exports ".")在宿主进程运行:注册 ws_request_verdict / ws_list_verdict_guides
3
+ # 两个 agent 工具,并提供 /api/dsh-decision-gateway/* 回环路由;
4
+ # 浏览器端(exports "./client")为占位干净模块(本包能力在宿主端,见 README 安全模型)。
5
+ - insert:
6
+ - id: dsh-decision-gateway
7
+ name: "@wingsky-1/dsh-decision-gateway"
@@ -0,0 +1,35 @@
1
+ THIRD-PARTY LICENSES
2
+ ===================
3
+
4
+ 本发布物遵循「运行时依赖 = 构建期内联」模型,将下列第三方库打包进产物
5
+ (随包分发的 vendored 裸二进制单列一段并标出来源);
6
+ 依其许可证条款随附许可文本与版权声明。
7
+ 生成:scripts/collect-licenses.ts(issue #13)。本仓库自身以 MIT 许可发布。
8
+
9
+
10
+ =====================================================================
11
+ @typesafe-ai/sdk@0.6.0 — MIT
12
+ 来源:https://www.npmjs.com/package/@typesafe-ai/sdk
13
+ =====================================================================
14
+
15
+ MIT License
16
+
17
+ Copyright (c) 2026 TypeSafe
18
+
19
+ Permission is hereby granted, free of charge, to any person obtaining a copy
20
+ of this software and associated documentation files (the "Software"), to deal
21
+ in the Software without restriction, including without limitation the rights
22
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23
+ copies of the Software, and to permit persons to whom the Software is
24
+ furnished to do so, subject to the following conditions:
25
+
26
+ The above copyright notice and this permission notice shall be included in all
27
+ copies or substantial portions of the Software.
28
+
29
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35
+ SOFTWARE.
@@ -0,0 +1,37 @@
1
+ /**
2
+ * dsh-decision-gateway — 客户端契约消费层(api/ 域内模块,经 interface.ts 门面引用)。
3
+ *
4
+ * 类型直接复用共享 ConfigV1/HistoryEntry/DecisionLang/DecisionTier/AutomationCap/AutomationLevel;
5
+ * 解析/归一/校验为纯函数(可单测直连)。主代理裁决:automationCap 三档 0|1|2;
6
+ * GET /config 裸 v1 掩码体并兼容 {config}/{data} 包装;失败体含 errorCode + category。
7
+ * 零 bare import。
8
+ */
9
+ import type { AutomationCap, AutomationLevel, ConfigV1 as SharedConfigV1, HistoryEntry as SharedHistoryEntry, DecisionLang, DecisionTier } from "../../shared/interface.js";
10
+ /** 共享类型复出(子模块经 api/interface.ts 消费)。 */
11
+ export type { AutomationCap, AutomationLevel, DecisionLang, DecisionTier };
12
+ export type DecisionConfigV1 = SharedConfigV1;
13
+ export type DecisionHistoryEntry = SharedHistoryEntry;
14
+ /** 预设开关项(配置 v1.presets 元素形态)。 */
15
+ export type DecisionPresetConfigEntry = SharedConfigV1["presets"][number];
16
+ /** 模板库目录项(GET /presets 元素形态;服务端字段缺失时容错)。 */
17
+ export interface DecisionPresetInfo {
18
+ readonly id: string;
19
+ readonly templateVersion?: number;
20
+ readonly label?: string;
21
+ readonly description?: string;
22
+ readonly custom?: boolean;
23
+ }
24
+ export declare function failureCategory(status: number, body: unknown): string;
25
+ /** automationCap 归一到 0|1|2(非法回 0=none)。 */
26
+ export declare function normalizeCap(v: unknown): AutomationCap;
27
+ export declare function capLabel(cap: AutomationCap): string;
28
+ /** 防御式解析 GET /config(裸 v1 或 {config}/{data} 包装均接受)。 */
29
+ export declare function parseConfigPayload(payload: unknown): DecisionConfigV1 | null;
30
+ /** 防御式解析 GET /presets(裸数组或 {presets} 包装均接受)。 */
31
+ export declare function parsePresetsPayload(payload: unknown): DecisionPresetInfo[];
32
+ export declare function toHistoryEntry(it: unknown): DecisionHistoryEntry | null;
33
+ export declare function parseHistoryPayload(payload: unknown): DecisionHistoryEntry[];
34
+ /** ENV 名本地校验(与共享 API_KEY_REF_RE 同正则)。 */
35
+ export declare function validApiKeyRef(name: string): boolean;
36
+ /** 0..1 概率钳制(概率条宽度与文案同源;与 automationCap 三档无关)。 */
37
+ export declare function clamp01(v: unknown): number;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * dsh-decision-gateway — api 域门面(域内跨文件唯一入口;本文件只转出、不放实现)。
3
+ *
4
+ * 传输(routes.ts)+ 契约消费(contract.ts)经此门面被 panes / index 消费;
5
+ * 禁止绕过门面直引域内实现。
6
+ */
7
+ export { APP_ROUTES, CLIENT_FETCH_TIMEOUT_MS, fetchTimeout } from "./routes.js";
8
+ export { capLabel, clamp01, failureCategory, normalizeCap, parseConfigPayload, parseHistoryPayload, parsePresetsPayload, validApiKeyRef, } from "./contract.js";
9
+ export type { AutomationCap, AutomationLevel, DecisionConfigV1, DecisionHistoryEntry, DecisionLang, DecisionPresetConfigEntry, DecisionPresetInfo, DecisionTier, } from "./contract.js";
@@ -0,0 +1,11 @@
1
+ /** 卡片实际使用的路由表(注入优先,共享兜底)。 */
2
+ export declare const APP_ROUTES: {
3
+ readonly health: string;
4
+ readonly config: string;
5
+ readonly presets: string;
6
+ readonly history: string;
7
+ readonly testConnection: string;
8
+ };
9
+ /** 客户端 fetch 默认超时(浏览器→dsh web 一跳;与 provider-usage 10s 先例对齐)。 */
10
+ export declare const CLIENT_FETCH_TIMEOUT_MS = 10000;
11
+ export declare function fetchTimeout(url: string, init?: RequestInit, timeoutMs?: number): Promise<Response>;
@@ -0,0 +1,8 @@
1
+ /** 浏览器端上下文窄面(实际使用的面:get + effect;与 inject 对齐)。 */
2
+ interface ClientContext {
3
+ get: (name: string) => unknown;
4
+ effect: (execute: () => () => void, label?: string) => unknown;
5
+ }
6
+ export declare function apply(ctx: ClientContext): void;
7
+ export declare const inject: string[];
8
+ export {};
@@ -0,0 +1,31 @@
1
+ /**
2
+ * dsh-decision-gateway — 客户端文案绑定(零依赖纯函数,可被 node 单测直测)。
3
+ *
4
+ * 语言判定:浏览器 locale 以 zh 开头即中文,其余英文(含缺 navigator 的 node 环境
5
+ * 回落英文——与 JEV 英文问答更擅长一致)。单测经 setLang 锁定语言。
6
+ *
7
+ * 宿主 locale 服务(notifier 同款):apply 期 register 字典 + bind 装配,订阅回调重绑,
8
+ * 切语言免刷新跟随;未装配(旧运行时 / 单测直调)回落本地字典——界面照常渲染中文案。
9
+ */
10
+ import { zh } from "./locales.js";
11
+ export type DecisionLocale = "zh" | "en";
12
+ export type DecisionTextKey = keyof typeof zh;
13
+ /** 宿主装配的翻译函数(官方 ctx.locale.bind(ns) 产物;key 即本包字典键)。 */
14
+ export type HostTranslate = (key: string, params?: Record<string, unknown>) => string;
15
+ /** 装配 / 重绑宿主翻译函数(apply 期与 locale 订阅回调调用)。
16
+ * 守住 bound 恒可调用:宿主异常实现可能返回非函数(命名空间未命中等),
17
+ * 此时忽略装配、t() 回落本地字典(此前本地路径永不抛错,回归面见评审)。 */
18
+ export declare function bindTranslate(next: HostTranslate): void;
19
+ /** 摘除宿主绑定、回落本地字典(卸载 / 单测隔离用)。 */
20
+ export declare function unbindTranslate(): void;
21
+ /** 解析当前语言(浏览器 zh 开头即 zh,否则 en)。 */
22
+ export declare function resolveLang(): DecisionLocale;
23
+ /** 锁定语言(单测用;正常渲染走模块加载期解析)。 */
24
+ export declare function setLang(next: DecisionLocale): void;
25
+ /** 当前语言。 */
26
+ export declare function lang(): DecisionLocale;
27
+ /** 取文案(key 即 zh 源;缺 key 永不发生——en 由 Record<keyof typeof zh> 锁死)。
28
+ * 支持 {n} 数字插值(中英语序不同,禁止空串 key 占位)。 */
29
+ export declare function t(key: DecisionTextKey, params?: {
30
+ readonly n?: number;
31
+ }): string;
@@ -0,0 +1,122 @@
1
+ /**
2
+ * dsh-decision-gateway — 客户端文案字典(中英双语,零运行时依赖)。
3
+ *
4
+ * 双语平衡:`zh` 为 key 源;`en` 必须覆盖全部 key(编译期锁平衡:
5
+ * `EnDict = Record<keyof typeof zh, string>`,缺 key 即 tsc 红)。
6
+ * 不进字典:console 日志、frozen 出题规范英文原文(数据不翻译)、
7
+ * 服务端动态值(tier/automation/resultKind/errorCode/置信度数字)。
8
+ */
9
+ /** 简体中文文案(key 源)。 */
10
+ export declare const zh: {
11
+ readonly tabLabel: "JEV 决策";
12
+ readonly cardName: "JEV 决策(dsh-decision-gateway)";
13
+ readonly cardDesc: "连接 / 模板库 / 历史:密钥掩码显示,原文永不回显。";
14
+ readonly tabsAria: "JEV 决策设置";
15
+ readonly tabConnection: "连接";
16
+ readonly tabPresets: "模板库";
17
+ readonly tabHistory: "历史";
18
+ readonly healthChecking: "自检中…";
19
+ readonly healthOk: "服务可用";
20
+ readonly healthBad: "服务异常 ";
21
+ readonly healthUnreachable: "服务不可达";
22
+ readonly notLoaded: "未加载";
23
+ readonly loading: "加载中…";
24
+ readonly save: "保存";
25
+ readonly retry: "重试";
26
+ readonly exportJson: "导出 JSON";
27
+ readonly detail: "详情";
28
+ readonly copyCustom: "复制为自定义";
29
+ readonly copyCustomNote: "复制为自定义走新增接口(P1),当前仅展示规范。";
30
+ readonly refresh: "刷新";
31
+ readonly clearSession: "清空本会话";
32
+ readonly testOffline: "离线自检";
33
+ readonly testing: "自检中…";
34
+ readonly testOk: "自检通过";
35
+ readonly testFail: "自检失败:";
36
+ readonly enabledOn: "已启用";
37
+ readonly enabledOff: "已关闭";
38
+ readonly enablePresetAria: "启用预设 ";
39
+ readonly emptyPresets: "暂无预设。";
40
+ readonly emptyHistory: "暂无历史。";
41
+ readonly emptySpec: "暂无规范。";
42
+ readonly truncBadge: "截断";
43
+ readonly errPrefix: "错误:";
44
+ readonly noProb: "无概率";
45
+ readonly highLine: "high 线 80%";
46
+ readonly capNone: "none(仅人工)";
47
+ readonly capLabel: "自动化上限";
48
+ readonly tplVersion: "模板版本 v";
49
+ readonly frozenNote: "(frozen,恒为 1)";
50
+ readonly countEntries: "共 {n} 条";
51
+ readonly keyMode: "密钥方式(二选一,互斥)";
52
+ readonly keyEnv: "ENV 引用";
53
+ readonly keyPlain: "明文密钥";
54
+ readonly modeEnvNote: "当前 ENV 引用:明文侧已隐藏。";
55
+ readonly modePlainNote: "当前明文密钥:ENV 侧已隐藏。保存明文将清除已存的 ENV 引用(切轨);切回 ENV 即清空明文。";
56
+ readonly maskDotsAria: "已配置明文密钥掩码(定长八点,与原文长度无关)";
57
+ readonly envLabel: "ENV 变量名(apiKeyRef)";
58
+ readonly envAria: "ENV 变量名";
59
+ readonly envPlaceholder: "大写字母开头,如 JEV_API_KEY(留空不改)";
60
+ readonly envRule: "规则:^[A-Z][A-Z0-9_]{1,63}$;与明文密钥互斥,只提交其一。";
61
+ readonly envBad: "ENV 名非法:须满足 ^[A-Z][A-Z0-9_]{1,63}$(如 JEV_API_KEY)。";
62
+ readonly plainAria: "明文密钥";
63
+ readonly plainPlaceholder: "输入新的明文密钥以替换(留空不改)";
64
+ readonly plainFoldTitle: "输入明文密钥…";
65
+ readonly plainNote: "密钥原文永不回显;已配置仅显示“已配置”。占位符不含任何真密钥示例。";
66
+ readonly maskOn: "密钥:已配置";
67
+ readonly maskOff: "密钥:未配置";
68
+ readonly maskEnv: "ENV:";
69
+ readonly loadedNote: "已加载配置 v1。明文框恒空:已配置仅显示“已配置”。";
70
+ readonly loadFail: "加载失败:";
71
+ readonly loadFailShort: "加载失败";
72
+ readonly mutualError: "明文与 ENV 引用互斥:请先清空 ENV 输入框(留空)再提交明文。";
73
+ readonly nanError: "高级参数须为数字。";
74
+ readonly saving: "保存中…(明文仅本次提交,不回显)";
75
+ readonly savedReload: "已保存。重新加载掩码态…";
76
+ readonly saveFail: "保存失败:";
77
+ readonly advTitle: "高级…";
78
+ readonly advTimeout: "请求超时 timeoutMs";
79
+ readonly advTimeoutHint: "默认 8000(毫秒,上限 120000)";
80
+ readonly advConcurrency: "最大并发 maxConcurrency";
81
+ readonly advConcurrencyHint: "默认 4";
82
+ readonly advTrunc: "截断预算 truncBudget";
83
+ readonly advTruncHint: "默认 32000(字符)";
84
+ readonly advPerSession: "单会话历史 perSession";
85
+ readonly advPerSessionHint: "默认 200(上限 1000)";
86
+ readonly advTotalSessions: "总会话数 totalSessions";
87
+ readonly advTotalSessionsHint: "默认 50(上限 200)";
88
+ readonly filterTitle: "过滤…";
89
+ readonly wsLabel: "工作目录";
90
+ readonly wsFilterAria: "工作目录过滤";
91
+ readonly sessLabel: "会话";
92
+ readonly sessFilterAria: "会话过滤";
93
+ readonly allWs: "全部工作目录";
94
+ readonly allSess: "全部会话";
95
+ readonly historyOrderNote: "倒序排列(含概率条 + tier + 截断徽标 + 错误行)。";
96
+ readonly clearing: "清空中…(仅单会话)";
97
+ readonly clearOk: "已清空本会话。重新加载…";
98
+ readonly clearFail: "清空失败:";
99
+ readonly confirmClear: "确认清空本会话?";
100
+ readonly confirmClearAgain: "再次点击确认清空当前会话历史(仅单会话 DELETE)。";
101
+ readonly clearScopeNote: "仅清空当前选中会话(DELETE 单会话),无批量清空";
102
+ readonly presetsMergedNote: "目录与开关位已合并。阈值微调即 automationCap 三档(0=none/1=low/2=high)。";
103
+ readonly presetsCount: "预设 {n} 个";
104
+ readonly presetsExported: "已导出 {n} 个预设(JSON 下载)。";
105
+ readonly presetsSaved: "已保存 {n} 个预设开关与阈值。";
106
+ readonly noImportNote: "无导入按钮:模板库只出不进。secret-leak 默认关闭(frozen 模板)。";
107
+ readonly customBadge: "自建";
108
+ readonly addCustom: "新建自建预设";
109
+ readonly deleteCustom: "删除";
110
+ readonly confirmDelete: "确认删除?";
111
+ readonly confirmDeleteCustom: "再次点击确认删除该自建预设(仅删本条)。";
112
+ readonly customIdLabel: "自建 id(小写字母/数字/连字符,不可与 frozen 重名)";
113
+ readonly customLabelLabel: "展示名(英文)";
114
+ readonly customDescLabel: "出题规范(英文自由文本,可抄模板写法)";
115
+ readonly customDraftNote: "保存后默认关闭,需手动启用;题目永随调用传入,不存模板。";
116
+ readonly cancelCustom: "取消";
117
+ readonly createCustom: "创建";
118
+ readonly customSaved: "自建预设已保存。";
119
+ readonly customFormInvalid: "id/展示名/规范均不能为空。";
120
+ };
121
+ /** 英文文案(必须覆盖 zh 全部 key)。 */
122
+ export declare const en: Record<keyof typeof zh, string>;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * dsh-decision-gateway — 设置独立页卡片(React,宿主 settings.section 插槽渲染)。
3
+ *
4
+ * 三 tab(连接/模板库/历史,一 tab 一主焦点)+ 健康徽标。样式独立 style.css。
5
+ */
6
+ import * as React from "react";
7
+ export declare function DecisionCard(): React.ReactElement;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * dsh-decision-gateway — 连接 tab(React,settings.section 独立页)。
3
+ *
4
+ * 要素:密钥二选一卡(radio 互斥,未选中轨整体隐藏;切轨保存自动清对方)/
5
+ * 离线自检 / 高级折叠 / 保存。Key 永不回显原文;placeholder 禁真密钥示例。
6
+ * 保存语义与 vanilla 一致:互斥阻断、ENV 形状校验、明文免二次确认、
7
+ * 未知键永不发送、保存后清空明文框并重载掩码态。
8
+ */
9
+ import * as React from "react";
10
+ export declare function ConnectionPane(): React.ReactElement;
@@ -0,0 +1,4 @@
1
+ /** dsh-decision-gateway — 纯显示格式函数(零依赖,可单测直连)。 */
2
+ export declare function fmtTime(ts: number): string;
3
+ /** 短 id(超长截断;完整值放 title)。 */
4
+ export declare function shortId(id: string, len?: number): string;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * dsh-decision-gateway — 历史 tab(React,settings.section 独立页)。
3
+ *
4
+ * 要素:工作目录下拉 + 会话下拉过滤,条目倒序含概率条 + tier + 截断徽标 + 错误行,
5
+ * 会话级清空两步确认仅调 DELETE 单会话。概率条细条 + 80% 阈值线(仅展示,判定以服务端
6
+ * tier 为准)+ 数字;无图表库,手写 div。
7
+ */
8
+ import * as React from "react";
9
+ export declare function HistoryPane(): React.ReactElement;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * dsh-decision-gateway — 模板库 tab(React,settings.section 独立页)。
3
+ *
4
+ * 要素:5 出题规范开关 + automationCap 三档(0=none/1=low/2=high,绝非百分比滑杆)
5
+ * + 导出 JSON,无导入。行内详情单开(aria-expanded),复制为自定义走新增接口(P1 占位)。
6
+ * 出题规范英文原文直排(数据不翻译)。保存携带快照 connection/history 原值回写。
7
+ */
8
+ import * as React from "react";
9
+ export declare function PresetsPane(): React.ReactElement;
@@ -0,0 +1,10 @@
1
+ /** dsh-decision-gateway — 概率条小组件(React;无图表库,手写 div)。 */
2
+ import * as React from "react";
3
+ import type { DecisionHistoryEntry } from "../api/interface.js";
4
+ /** 高置信阈值线(展示用;判定以服务端 tier 为准,本线仅视觉参考)。 */
5
+ export declare const HIGH_LINE = 0.8;
6
+ export declare function tierBadge(tier: DecisionHistoryEntry["tier"]): React.ReactElement;
7
+ export declare function probPercent(entry: DecisionHistoryEntry): number;
8
+ export declare function ProbBar({ entry }: {
9
+ readonly entry: DecisionHistoryEntry;
10
+ }): React.ReactElement;