@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
@@ -0,0 +1,18 @@
1
+ import type { CustomPreset, DecideOutput, ErrorEnvelope } from "../../../shared/interface.js";
2
+ import type { DecideDeps } from "../deps.js";
3
+ /** 执行一次决议(纯编排;副作用仅经注入 deps 发生)。 */
4
+ export declare function decide(args: unknown, deps: DecideDeps): Promise<DecideOutput | ErrorEnvelope>;
5
+ /** 预设清单(只读;frozen 规范 + 自建 customs,开关/上限取配置快照)。 */
6
+ export declare function listPresets(deps: {
7
+ readonly isEnabled: (presetId: string) => boolean;
8
+ readonly capOf: (presetId: string) => number;
9
+ readonly customs?: readonly CustomPreset[];
10
+ }): readonly {
11
+ readonly id: string;
12
+ readonly enabled: boolean;
13
+ readonly templateVersion: 1;
14
+ readonly automationCap: number;
15
+ readonly label: string;
16
+ readonly description: string;
17
+ readonly custom: boolean;
18
+ }[];
@@ -0,0 +1,17 @@
1
+ import type { CustomPreset } from "../../../shared/interface.js";
2
+ import type { ValidDecide } from "../deps.js";
3
+ /** 校验失败(调用方映射为 400/ErrorEnvelope,不抛)。 */
4
+ export interface DecideValidationFailure {
5
+ readonly errorCode: string;
6
+ readonly message: string;
7
+ }
8
+ type Invalid = {
9
+ readonly ok: false;
10
+ readonly failure: DecideValidationFailure;
11
+ };
12
+ /** ws_request_verdict 参数校验(成功即 ValidDecide,失败即 400 类错误;custom 自建 id 经第二参传入)。 */
13
+ export declare function validateDecideArgs(args: unknown, custom?: ReadonlyMap<string, CustomPreset>): {
14
+ readonly ok: true;
15
+ readonly valid: ValidDecide;
16
+ } | Invalid;
17
+ export {};
@@ -0,0 +1,7 @@
1
+ /** tools 域门面:只转出组合根实际用的符号(无逻辑)。probeConnection 见 impl/probe.ts。 */
2
+ export type { DecideDeps, FetchImpl } from "./deps.js";
3
+ export { callWithRetry, defaultFetchImpl } from "./impl/client.js";
4
+ export { createSemaphore } from "./impl/semaphore.js";
5
+ export { decide, listPresets } from "./impl/service.js";
6
+ export { buildToolDefinitions, rootOf, sessionOf } from "./impl/define.js";
7
+ export { probeConnection } from "./impl/probe.js";
@@ -0,0 +1,37 @@
1
+ /** upgrade 域出口:注入面(纯类型,零运行时)。落盘原语由组合根从 store 域装配,本域不直引他域实现。 */
2
+ /** 最小日志面。 */
3
+ export interface LoggerPort {
4
+ readonly warn: (message: string) => void;
5
+ readonly info?: (message: string) => void;
6
+ }
7
+ /** 迁移所需落盘原语面。 */
8
+ export interface UpgradeIoPorts {
9
+ readonly readJsonSync: (file: string) => {
10
+ readonly ok: true;
11
+ readonly value: unknown;
12
+ } | {
13
+ readonly ok: false;
14
+ };
15
+ readonly readTextSync: (file: string) => {
16
+ readonly ok: true;
17
+ readonly text: string;
18
+ } | {
19
+ readonly ok: false;
20
+ };
21
+ readonly atomicWrite0600Sync: (file: string, text: string) => void;
22
+ readonly listFilesSync: (dir: string) => string[];
23
+ }
24
+ /** 种子文件内容(默认值唯一事实源在 config 域 model,组合根装配时传入,本域不直引)。 */
25
+ export interface SeedFiles {
26
+ readonly configJson: string;
27
+ readonly presetsJson: string;
28
+ readonly secretsJson: string;
29
+ }
30
+ /** upgrade 域运行所需注入(home 缺席即 DSH home;targetOverride 仅单测定版)。 */
31
+ export interface UpgradeDeps {
32
+ readonly io: UpgradeIoPorts;
33
+ readonly logger: LoggerPort;
34
+ readonly home?: string;
35
+ readonly targetOverride?: string;
36
+ readonly seedDefaults: () => SeedFiles;
37
+ }
@@ -0,0 +1,13 @@
1
+ import type { UpgradeDeps } from "../deps.js";
2
+ /** 存储目标刻度(与包版本独立:它是磁盘形态刻度,不是发布版本)。 */
3
+ export declare const STORAGE_TARGET = "0.2.6";
4
+ /** 迁移报告。 */
5
+ export interface MigrateReport {
6
+ readonly from: string;
7
+ readonly to: string;
8
+ readonly seeded: string[];
9
+ }
10
+ /** 跑迁移链(同步;抛错即装配失败,不写刻度,下次启动重跑同一步)。 */
11
+ export declare function migrate(deps: UpgradeDeps): MigrateReport;
12
+ /** 装配升级域(同步跑完迁移链;失败即抛,apply 随之失败)。门面只转出本函数。 */
13
+ export declare function installUpgrade(deps: UpgradeDeps): MigrateReport;
@@ -0,0 +1,3 @@
1
+ import type { SeedFiles, UpgradeIoPorts } from "../deps.js";
2
+ /** 缺失即种(返回新建文件名;已存在即跳过)。 */
3
+ export declare function ensureSeeded(home: string | undefined, seed: SeedFiles, io: UpgradeIoPorts): string[];
@@ -0,0 +1,6 @@
1
+ /**
2
+ * upgrade 域门面:只转出组合根实际用的符号(installUpgrade),无逻辑。
3
+ *
4
+ * 本域必须在各域装配之前跑(动磁盘者在先):先跑完存储锚定,各域才读得到 canonical 形态。
5
+ */
6
+ export { installUpgrade } from "./impl/service.js";
@@ -0,0 +1,184 @@
1
+ /**
2
+ * dsh-decision-gateway 双端共享契约(纯模块:零 import,宿主 tsc 直连、客户端 esbuild 直连)。
3
+ *
4
+ * 两端必须一致,谁也不许单方面改;缺口上报主代理。
5
+ * 主代理裁决(已落实):automationCap 用 0|1|2(0=none,1=low,2=high);
6
+ * GET /config 返回裸 v1 掩码体,两端同时兼容裸体与 {config}/{data} 包装;
7
+ * 失败体必须同时含 errorCode + category(error/code 可选)。
8
+ */
9
+ /** 插件在 DSH home 下的独立命名空间目录(与其它插件隔离)。 */
10
+ export declare const PACKAGE_DIR = "@wingsky-1/dsh-decision-gateway";
11
+ /** 配置版本(config.json version 字段唯一合法值)。 */
12
+ export declare const CONFIG_VERSION = 1;
13
+ /** 预设模板版本(5 预设 frozen,templateVersion 恒为 1)。 */
14
+ export declare const TEMPLATE_VERSION = 1;
15
+ /** 官方 SystemOne 基址(写死常量;加载断言防篡改,PUT 拒收 baseUrl 类键;JEV_ 前缀专属首个提供方 JEV,网关通用概念已去 JEV 化,此标识符与值双写死保留)。 */
16
+ export declare const JEV_BASE_URL = "https://api.typesafe.ai/v1/systemone";
17
+ /** 官方 SystemOne 默认模型(冻结别名;与 JEV_BASE_URL 同等 pin 待遇,不接受配置覆盖;JEV_ 前缀专属首个提供方 JEV 的模型 pin 位,此标识符与值双写死保留)。 */
18
+ export declare const JEV_MODEL = "jev-latest";
19
+ /** 存储文件名(命名空间目录下独立四文件 + 版本刻度;custom-presets.json 缺席即空列表)。 */
20
+ export declare const CONFIG_FILE_NAME = "config.json";
21
+ export declare const PRESETS_FILE_NAME = "presets.json";
22
+ export declare const SECRETS_FILE_NAME = "secrets.json";
23
+ export declare const CUSTOM_PRESETS_FILE_NAME = "custom-presets.json";
24
+ export declare const VERSION_FILE_NAME = "VERSION";
25
+ /** 回环路由表(宿主 ROUTES 单一事实源经构建期注入客户端;此处常量是宿主侧定义)。 */
26
+ export declare const ROUTES: {
27
+ readonly health: "/api/dsh-decision-gateway/health";
28
+ readonly config: "/api/dsh-decision-gateway/config";
29
+ readonly presets: "/api/dsh-decision-gateway/presets";
30
+ readonly history: "/api/dsh-decision-gateway/history";
31
+ readonly testConnection: "/api/dsh-decision-gateway/test-connection";
32
+ };
33
+ /** ENV 引用名形状(与客户端 validApiKeyRef 同正则)。 */
34
+ export declare const API_KEY_REF_RE: RegExp;
35
+ /** preset id 形状(ASCII 小写+数字+连字符;中文直接 400)。 */
36
+ export declare const PRESET_ID_RE: RegExp;
37
+ /** question id 形状(同上)。 */
38
+ export declare const QUESTION_ID_RE: RegExp;
39
+ /** 会话 id 形状(落盘文件名安全集)。 */
40
+ export declare const SESSION_ID_RE: RegExp;
41
+ /** CJK 探测(preset/question id 含中文即 400;state 正文不受此限)。 */
42
+ export declare const CJK_RE: RegExp;
43
+ /** 已退役配置键(加载迁移时剥离并告警;PUT 显式拒收 400)。 */
44
+ export declare const RETIRED_KEYS: readonly ["baseUrl", "apiBaseUrl", "endpoint", "apiEndpoint", "url"];
45
+ /** 单题文本上限(codepoints;超限 400)。 */
46
+ export declare const MAX_QUESTION_TEXT = 255;
47
+ /** 单次 override 最多题数。 */
48
+ export declare const MAX_QUESTIONS = 20;
49
+ /** 历史 snippet 上限(字;超限截断)。 */
50
+ export declare const SNIPPET_MAX = 200;
51
+ /** 状态语言(state.lang 全集;缺席默认为 unknown,仅非法值 400)。 */
52
+ export type DecisionLang = "en" | "zh" | "unknown";
53
+ /** 置信分层。 */
54
+ export type DecisionTier = "none" | "high" | "low";
55
+ /** 自动化上限/分级:0=none(只人工),1=low,2=high。 */
56
+ export type AutomationCap = 0 | 1 | 2;
57
+ /** 自动化实际等级(suggest-only:输入被截断时的强制降级,仅建议不执行;local-precheck 的 manual 不受影响)。 */
58
+ export type AutomationLevel = "manual" | "assisted" | "auto" | "suggest-only";
59
+ /** frozen 预设模板:只存英文出题规范(一段自由描述),不存固定考题。调用方每次经 questions_override 自带全量题目。 */
60
+ export interface PresetTemplate {
61
+ readonly id: string;
62
+ readonly label: string;
63
+ /** English asking guide: goal, dimensions, mutual exclusion, good vs bad asking examples, prohibitions, how to call. Free-form prose, length-checked only. */
64
+ readonly description: string;
65
+ readonly defaultEnabled: boolean;
66
+ readonly automationCap: AutomationCap;
67
+ }
68
+ /** 5 预设 frozen 规范(secret-leak 默认关闭;模板零考题)。 */
69
+ export declare const FROZEN_PRESETS: readonly PresetTemplate[];
70
+ /** 自建自定义预设存储版本(custom-presets.json version 字段唯一合法值)。 */
71
+ export declare const CUSTOM_PRESETS_VERSION = 1;
72
+ /** 自定义预设上限(条)。 */
73
+ export declare const MAX_CUSTOM_PRESETS = 50;
74
+ /** 自定义名上限(codepoints)。 */
75
+ export declare const MAX_CUSTOM_LABEL = 64;
76
+ /** 自定义描述上限(codepoints,超限 400)。 */
77
+ export declare const MAX_CUSTOM_DESCRIPTION = 2000;
78
+ /** 用户自建预设(单 description 英文自由文本,可抄 frozen 写作约定,也可自由发挥;题目永随调用传入,不存)。 */
79
+ export interface CustomPreset {
80
+ readonly id: string;
81
+ readonly label: string;
82
+ readonly description: string;
83
+ readonly enabled: boolean;
84
+ readonly automationCap: AutomationCap;
85
+ readonly createdAt: number;
86
+ readonly updatedAt: number;
87
+ }
88
+ /** 按 id 取 frozen 模板(无则 undefined)。 */
89
+ export declare function frozenPresetOf(id: string): PresetTemplate | undefined;
90
+ /** 配置 v1(connection 无明文、无 BaseURL;密钥只经 secrets.json/ENV)。 */
91
+ export interface ConfigV1 {
92
+ readonly version: 1;
93
+ readonly connection: {
94
+ readonly apiKeyRef?: string;
95
+ readonly hasPlaintextKey: boolean;
96
+ readonly timeoutMs: number;
97
+ readonly maxConcurrency: number;
98
+ readonly truncBudget: number;
99
+ };
100
+ readonly presets: readonly {
101
+ readonly id: string;
102
+ readonly enabled: boolean;
103
+ readonly automationCap: AutomationCap;
104
+ }[];
105
+ readonly history: {
106
+ readonly perSession: number;
107
+ readonly totalSessions: number;
108
+ };
109
+ }
110
+ /** 历史条目快照的问题(调用方传入原样存档;文本/选项/分档经同 snippet 的脱敏后存)。 */
111
+ export interface HistoryQuestion {
112
+ readonly id: string;
113
+ readonly text: string;
114
+ readonly kind: "choice" | "score";
115
+ readonly options?: readonly string[];
116
+ readonly levels?: readonly string[];
117
+ }
118
+ /** 历史条目(任务契约;原始密钥永不入库,snippetRedacted≤200;questions 为调用题目快照)。 */
119
+ export interface HistoryEntry {
120
+ readonly ts: number;
121
+ readonly rootHash: string;
122
+ /** 仅 basename。 */
123
+ readonly rootDisplay: string;
124
+ readonly sessionId: string;
125
+ readonly presetId: string;
126
+ readonly templateVersion: number;
127
+ readonly stateHash: string;
128
+ readonly snippetRedacted: string;
129
+ readonly lang: DecisionLang;
130
+ readonly truncated: boolean;
131
+ readonly originalLength: number;
132
+ readonly resultKind: string;
133
+ readonly choice?: string;
134
+ readonly score?: number;
135
+ readonly confidence: number;
136
+ readonly tier: DecisionTier;
137
+ readonly automation: AutomationLevel;
138
+ readonly provider: "official";
139
+ readonly latencyMs: number;
140
+ readonly errorCode?: string;
141
+ readonly questions?: readonly HistoryQuestion[];
142
+ /** 读取时 enrich 的展示标题(只存 id,缺失回退短 id);永不落盘。 */
143
+ readonly presetTitle?: string;
144
+ /** 读取时 enrich 的会话标题(只读活会话快照,无标题/服务缺席回落短 id);永不落盘。 */
145
+ readonly sessionTitle?: string;
146
+ }
147
+ /** 成功输出必带字段(provider/appliedSource/truncated/originalLength/tier/automation/计费 codepoints/重试次数)。 */
148
+ export interface DecideOutput {
149
+ readonly ok: true;
150
+ readonly provider: "official";
151
+ readonly appliedSource: "override" | "custom" | "local-precheck";
152
+ readonly truncated: boolean;
153
+ readonly originalLength: number;
154
+ readonly tier: DecisionTier;
155
+ readonly automation: AutomationLevel;
156
+ readonly codepoints: number;
157
+ readonly retries: number;
158
+ readonly latencyMs: number;
159
+ readonly resultKind: string;
160
+ readonly choice?: string;
161
+ readonly score?: number;
162
+ readonly confidence: number;
163
+ }
164
+ /** 失败包络(无概率字段;必含 errorCode + category 供客户端 failureCategory 识别)。 */
165
+ export interface ErrorEnvelope {
166
+ readonly ok: false;
167
+ readonly error: {
168
+ readonly errorCode: string;
169
+ readonly category: string;
170
+ readonly message: string;
171
+ };
172
+ }
173
+ /** 密钥形状类别(400 仅回此类别,原文永不回显)。 */
174
+ export type KeyShapeCategory = "empty" | "too-short" | "charset";
175
+ /** 密钥形状判定(有效:16-256 位可见字符集、含字母、非全大写长串;返回 null 即有效)。 */
176
+ export declare function keyShapeCategory(key: string): KeyShapeCategory | null;
177
+ /** 按 codepoints 截断(中文按字不断字节)。 */
178
+ export declare function truncateCodePoints(text: string, budget: number): {
179
+ readonly text: string;
180
+ readonly truncated: boolean;
181
+ readonly originalLength: number;
182
+ };
183
+ /** id 是否含 CJK(含即中文 400)。 */
184
+ export declare function containsCjk(text: string): boolean;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * dsh-decision-gateway 双端共享面门面(跨模块引用唯一入口;本文件只转出、不放实现)。
3
+ *
4
+ * 同级模块构建硬约束:本目录仅 contract.ts 一个纯模块(零 import)。
5
+ */
6
+ export { API_KEY_REF_RE, CJK_RE, CONFIG_FILE_NAME, CONFIG_VERSION, CUSTOM_PRESETS_VERSION, JEV_BASE_URL, JEV_MODEL, MAX_CUSTOM_DESCRIPTION, MAX_CUSTOM_LABEL, MAX_CUSTOM_PRESETS, MAX_QUESTIONS, MAX_QUESTION_TEXT, PACKAGE_DIR, PRESETS_FILE_NAME, PRESET_ID_RE, QUESTION_ID_RE, RETIRED_KEYS, ROUTES, SECRETS_FILE_NAME, SESSION_ID_RE, SNIPPET_MAX, TEMPLATE_VERSION, CUSTOM_PRESETS_FILE_NAME, VERSION_FILE_NAME, FROZEN_PRESETS, containsCjk, frozenPresetOf, keyShapeCategory, truncateCodePoints, } from "./contract.js";
7
+ export type { AutomationCap, AutomationLevel, ConfigV1, CustomPreset, DecideOutput, ErrorEnvelope, HistoryEntry, HistoryQuestion, DecisionLang, DecisionTier, KeyShapeCategory, PresetTemplate, } from "./contract.js";
package/package.json ADDED
@@ -0,0 +1,99 @@
1
+ {
2
+ "name": "@wingsky-1/dsh-decision-gateway",
3
+ "version": "0.2.6",
4
+ "description": "Decision gateway for DSH agents: calibrated Choice/Score/Noul verdicts via ws_request_verdict + local secret precheck + dual-track keys. 通用辅助决策网关(JEV 为首个 provider):frozen 预设模板 + 密钥双轨(ENV 引用优先)+ 本地密形预检 + SystemOne 官方调用,工具 ws_request_verdict / ws_list_verdict_guides",
5
+ "type": "module",
6
+ "main": "lib/index.js",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./lib/index.d.ts",
10
+ "default": "./lib/index.js"
11
+ },
12
+ "./client": {
13
+ "types": "./lib/client/index.d.ts",
14
+ "default": "./lib/client.js"
15
+ },
16
+ "./package.json": "./package.json"
17
+ },
18
+ "dsh": {
19
+ "bundle": {
20
+ "patch": "./cordis.patch.yml",
21
+ "bannerJs": "import { createRequire as __decisionGatewayRequire } from \"node:module\";\nconst require = __decisionGatewayRequire(import.meta.url);"
22
+ },
23
+ "catalog": {
24
+ "category": "tool",
25
+ "summary": {
26
+ "en": "Calibrated assistant decisions (Choice/Score/Noul) for DSH agents with local secret precheck; JEV is the first provider.",
27
+ "zh": "给 DSH agent 的校准辅助决策(Choice/Score/Noul),本地密形预检,双轨密钥;JEV 为首个提供方。"
28
+ },
29
+ "capabilities": [
30
+ "connection",
31
+ "decide"
32
+ ]
33
+ },
34
+ "client": {
35
+ "inject": [
36
+ "@deepseek-ai/dsh-client-connection"
37
+ ],
38
+ "platform": "web"
39
+ }
40
+ },
41
+ "files": [
42
+ "lib",
43
+ "shared/**/*.d.ts",
44
+ "cordis.patch.yml",
45
+ "README.md",
46
+ "LICENSE"
47
+ ],
48
+ "devDependencies": {
49
+ "@deepseek-ai/cordis": "4.0.4",
50
+ "@deepseek-ai/dsh-host-webserver": "0.1.7-rc.2",
51
+ "@deepseek-ai/dsh-tools": "0.1.7-rc.2",
52
+ "@typesafe-ai/sdk": "0.6.0"
53
+ },
54
+ "peerDependencies": {
55
+ "@deepseek-ai/cordis": "4.0.4",
56
+ "@deepseek-ai/dsh-host-webserver": "0.1.7-rc.2",
57
+ "@deepseek-ai/dsh-tools": "0.1.7-rc.2"
58
+ },
59
+ "peerDependenciesMeta": {
60
+ "@deepseek-ai/cordis": {
61
+ "optional": true
62
+ },
63
+ "@deepseek-ai/dsh-host-webserver": {
64
+ "optional": true
65
+ },
66
+ "@deepseek-ai/dsh-tools": {
67
+ "optional": true
68
+ }
69
+ },
70
+ "engines": {
71
+ "node": ">=20.0.0"
72
+ },
73
+ "license": "MIT",
74
+ "repository": {
75
+ "type": "git",
76
+ "url": "https://github.com/wingsky-1/dsh-plugin-hub.git",
77
+ "directory": "packages/dsh-decision-gateway"
78
+ },
79
+ "bugs": {
80
+ "url": "https://github.com/wingsky-1/dsh-plugin-hub/issues"
81
+ },
82
+ "keywords": [
83
+ "dsh",
84
+ "dsh-plugin",
85
+ "deepseek-harness",
86
+ "plugin",
87
+ "decision",
88
+ "gateway"
89
+ ],
90
+ "author": "wingsky-1",
91
+ "publishConfig": {
92
+ "access": "public"
93
+ },
94
+ "scripts": {
95
+ "build": "node ../../scripts/build/clean-lib.ts && tsc -p tsconfig.json && node ../../scripts/build/bundle-host.ts .",
96
+ "test": "node ../../scripts/test/run-vitest.mjs --min 23",
97
+ "typecheck": "tsc -p tsconfig.json --noEmit"
98
+ }
99
+ }
@@ -0,0 +1,21 @@
1
+ /** ensureStyle 参数(issue #477 v2 契约)。 */
2
+ export interface EnsureStyleOptions {
3
+ /** <style> 幂等键(package-owned 命名空间,统一 `dsh-<pkg>-style` 前缀隔离)。 */
4
+ id: string;
5
+ /** 样式文本(构建期 text-loader 内联的 style.css 内容)。 */
6
+ cssText: string;
7
+ /** 可选版本号:写入 dataset.version;变化时旧节点 remove 后重建(热更新失效)。 */
8
+ version?: string;
9
+ }
10
+
11
+ /**
12
+ * 按 id 幂等注入 <style> 节点(5 包统一样式注入入口,issue #477 收敛)。
13
+ *
14
+ * 行为契约:
15
+ * - head 缺失(document.head == null)静默早退 no-op 不抛;
16
+ * - 同 id 已存在且 version 未变(或未传)→ 不动现有节点;version 变化 → 重建;
17
+ * - 无 version 不写 dataset.version;
18
+ * - 返回 disposer(remove 该 id 节点;节点不存在时 no-op),卸载后再次调用
19
+ * ensureStyle 重新注入。
20
+ */
21
+ export declare function ensureStyle(options: EnsureStyleOptions): () => void;
@@ -0,0 +1,15 @@
1
+ /** 翻译函数形态(与官方 Translate 一致:key + {name} 占位参数)。 */
2
+ export declare type TranslateFn = (key: string, params?: Record<string, unknown>) => string;
3
+
4
+ /**
5
+ * 当前翻译函数(apply 时由各包 index.ts 经 bindLocale 装配)。
6
+ * 未装配时回落 key 本体(行为零变化)。
7
+ */
8
+ export declare let t: TranslateFn;
9
+
10
+ /**
11
+ * 装配/重绑翻译函数(官方 ctx.locale.bind(ns) 产物;语言切换 subscribe 内重调)。
12
+ * @param locale 宿主 locale 服务(须实现 bind)。
13
+ * @param ns 本插件字典命名空间。
14
+ */
15
+ export declare function bindLocale(locale: any, ns: string): void;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 用户 home 目录(`~` 的展开目标):`HOME` 非空白原样采用,未设置或空白回落
3
+ * `os.homedir()`;Windows 以 `USERPROFILE` 优先(对齐 libuv)。显式读 env 而非
4
+ * 直接 `os.homedir()`,是因为后者读进程级 environ,在 worker_threads(Stryker
5
+ * 的 vitest-runner 强制 `pool: 'threads'`)下无法被测试的 `process.env.HOME` 隔离;
6
+ * 取值次序与 libuv 一致,默认形态逐字节不变。
7
+ */
8
+ export declare function userHome(): string;
9
+
10
+ /**
11
+ * DSH home 解析(单一事实源):`DSH_HOME` 非空白原样采用;未设置或空白回落
12
+ * `~/.dsh`(默认形态路径逐字节不变)。语义对齐官方
13
+ * `@deepseek-ai/dsh-home-paths#resolveDshHome`(空白 env 视同未设置)。
14
+ */
15
+ export declare function dshHome(): string;
@@ -0,0 +1,65 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ import type { LoopbackOptions } from "./loopback.d.ts";
3
+
4
+ /** 写 JSON 响应(统一带 referrer-policy 头,防 referrer 泄露)。 */
5
+ export declare function writeJson(res: ServerResponse, status: number, payload: unknown): void;
6
+
7
+ /**
8
+ * 序列化一帧 SSE data 行(输出形如 `data: <json>\n\n`)。
9
+ * undefined / 含换行 payload 行为对齐三包历史实现、非承诺契约(#472)。
10
+ */
11
+ export declare function sseData(payload: unknown): string;
12
+
13
+ /** 请求体读不出来的具体成因:供端点在失败文案里说清是哪一种。 */
14
+ export type JsonBodyInvalidReason = "too-large" | "unreadable" | "malformed" | "not-object";
15
+
16
+ /** `readJsonBodyOutcome` 的成因可辨结果:缺席(可选 body 未给)/ 合法对象 / 非法(带具体成因)。 */
17
+ export type JsonBodyOutcome =
18
+ | { kind: "absent" }
19
+ | { kind: "json"; value: object }
20
+ | { kind: "invalid"; reason: JsonBodyInvalidReason };
21
+
22
+ /**
23
+ * 读请求 body(JSON)并保留失败成因:需要 fail-closed 的端点用它(畸形 body 不能被当成「没有 body」,
24
+ * 否则有副作用的端点会拿垃圾输入触发真实动作)。
25
+ * @param limit 字节上限(默认 2MB)。
26
+ */
27
+ export declare function readJsonBodyOutcome(
28
+ req: IncomingMessage,
29
+ limit?: number,
30
+ ): Promise<JsonBodyOutcome>;
31
+
32
+ /**
33
+ * 宽松读请求 body(JSON):解析失败或超限返回 undefined(不抛错),由调用方决定响应。
34
+ * 成因不可辨——要区分「缺席」与「非法」用 `readJsonBodyOutcome`。
35
+ * @param limit 字节上限(默认 2MB)。
36
+ */
37
+ export declare function readJsonBody(
38
+ req: IncomingMessage,
39
+ limit?: number,
40
+ ): Promise<object | undefined>;
41
+
42
+ /** 把任意抛出的值转成可读错误消息。 */
43
+ export declare function errorMessage(error: unknown): string;
44
+
45
+ /**
46
+ * 读请求 body(JSON,限长防滥用)。
47
+ * 兼容 Node 事件流(data/end)与 async-iterator 桩两种形态。
48
+ * @param limit 字节上限(默认 256KB)。
49
+ */
50
+ export declare function readBody(req: IncomingMessage, limit?: number): Promise<object>;
51
+
52
+ /**
53
+ * Loopback + 方法白名单低阶路由守卫:非 loopback → 403,方法不在白名单 → 405,
54
+ * 否则放行(403 先于 405 为本守卫执行顺序,仅对套守卫端点成立)。
55
+ * @param methods 允许的 HTTP 方法白名单。
56
+ * @param loopbackOptions 透传给 isLoopbackRequest 的可选判定参数(#549:仅
57
+ * serve 资源路由放行 cross-site no-cors 子资源时使用;其余路由不得传)。
58
+ * @returns 是否放行(true 时调用方继续处理请求)。
59
+ */
60
+ export declare function guardLoopbackMethod(
61
+ req: IncomingMessage,
62
+ res: ServerResponse,
63
+ methods: string[],
64
+ loopbackOptions?: LoopbackOptions,
65
+ ): boolean;
@@ -0,0 +1,21 @@
1
+ import type { IncomingMessage } from "node:http";
2
+
3
+ /**
4
+ * Loopback 围栏判定参数。
5
+ * - allowCrossSiteNoCors(#549):仅 serve 类资源伺服路由使用——放行「显式
6
+ * sec-fetch-mode: no-cors」的跨站子资源请求(sandbox iframe opaque origin
7
+ * 的相对路径 css/js/img 加载);cors fetch/XHR 与 navigate 仍拒绝。
8
+ * 普通 /api 路由必须保持默认(不传 options)拒绝一切 cross-site。
9
+ */
10
+ export interface LoopbackOptions {
11
+ allowCrossSiteNoCors?: boolean;
12
+ }
13
+
14
+ /**
15
+ * Loopback 围栏:请求必须来自回环地址 + 回环 Host,且满足跨站/来源约束,
16
+ * 否则拒绝(DNS 重绑定 + 跨站防御)。
17
+ */
18
+ export declare function isLoopbackRequest(
19
+ request: IncomingMessage,
20
+ options?: LoopbackOptions,
21
+ ): boolean;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 插件主目录拼装(单一事实源,实现见 `./paths.js`):等同
3
+ * `join(base, ...segments)`,默认形态路径逐字节不变。
4
+ *
5
+ * 只收敛「包主目录」直拼;以下 7 类排除:legacy/旧根(旧版迁移读面)、
6
+ * settings 文档(宿主文档读面)、resolve 对比(比较/候选命中顺序是语义)、
7
+ * 用户输入解析(`~`/相对路径展开)、credentials-userHome(DSH_HOME 域外凭据)、
8
+ * 展示脱敏(字符串替换不落盘)、包内反推(随包分发不在 DSH home 下)。
9
+ * provider-registry 的旧 `pluginHome` 保留为包内 facade(公开签名不变)。
10
+ * 完整理由见 `./paths.js` 函数 JSDoc。
11
+ */
12
+ export declare function pluginHome(base: string, ...segments: string[]): string;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * 宿主端「设置命名空间」注册(单一事实源)。
3
+ *
4
+ * 背景与语义见 settings-namespace.js 顶部注释。要点:宿主 settings 服务按 `ns`
5
+ * 定位描述项并合成 `base + user`(无层字段时兼容取 `value`);写经
6
+ * update/replace/mutate;热更新经 document-updated 订阅(内部直连,不对外暴露 watch 面)。
7
+ * 本文件只收窄能力面(全 unknown 结构面,无官方包导入)。
8
+ */
9
+
10
+ /** `installSettingsNamespace` 的 hooks 面。 */
11
+ export interface SettingsNamespaceHooks {
12
+ /** 把插件对该命名空间的读取来源指向返回的 scope(`scope.get()`)。 */
13
+ setSource(source: () => unknown): void;
14
+ /** 来源切换或命名空间值变化时触发,插件据此刷新/落盘。 */
15
+ onChange(): void;
16
+ /**
17
+ * 可选;owning fiber ACTIVE 且 canonical namespace 被 settings 服务描述后回调一次。
18
+ * 供存量配置迁移 / 写路径装配使用;fiber / 服务 / namespace 未就绪时不触发。
19
+ */
20
+ onScope?(scope: unknown, service: unknown): void;
21
+ }
22
+
23
+ /** 描述项窄面(按 ns 定位,合成 base + user,兼容 value 回退)。 */
24
+ export interface SettingsFormsDescriptor {
25
+ /** 命名空间键。 */
26
+ ns?: unknown;
27
+ /** 运行时解析值(缺少分层字段时的兼容回退)。 */
28
+ value?: unknown;
29
+ /** 基础配置层。 */
30
+ base?: unknown;
31
+ /** 原始 user 覆盖层。 */
32
+ user?: unknown;
33
+ /** 乐观并发修订号。 */
34
+ revision?: unknown;
35
+ }
36
+
37
+ /** owner scope 窄面(describe 定位读+写委托;订阅由接缝内部直连)。 */
38
+ export interface SettingsFormsScope {
39
+ /** 当前有效值(describe base + user,缺席回落 entry)。 */
40
+ get(): unknown;
41
+ /** 委托 settings.update(ns, …)。 */
42
+ update(patch: object, expectedRevision?: number): Promise<unknown>;
43
+ /** 委托 settings.replace(ns, …)。 */
44
+ replace(section: object, expectedRevision?: number): Promise<unknown>;
45
+ /** 委托 settings.mutate(ns, …);服务缺失时返回拒绝。 */
46
+ mutate(ops: readonly unknown[], expectedRevision?: number): Promise<unknown>;
47
+ }
48
+
49
+ /** settings 服务窄面(describe/写)。 */
50
+ export interface SettingsFormsService {
51
+ /** 按 entry id 定位描述项。 */
52
+ describe(options?: { redactSecrets?: boolean }): SettingsFormsDescriptor[];
53
+ /** 合并写。 */
54
+ update?(ns: string, patch: object, expectedRevision?: number): Promise<unknown>;
55
+ /** 整节写。 */
56
+ replace?(ns: string, section: object, expectedRevision?: number): Promise<unknown>;
57
+ /** 路径写(可选)。 */
58
+ mutate?(ns: string, ops: readonly unknown[], expectedRevision?: number): Promise<unknown>;
59
+ }
60
+
61
+ /**
62
+ * 日志兜底:logger 可能确实没有(极端降级),全部可选调用。
63
+ * 单一事实源(#436):notifier / lan-proxy 曾各复刻一份,现统一引用本导出。
64
+ */
65
+ export declare function warnLog(ctx: unknown, message: string): void;
66
+
67
+ /**
68
+ * 注册插件自有 settings 命名空间(服务面注入,无包依赖)。
69
+ * 对外签名保持不变(调用方零改)。
70
+ * @param ctx - 插件宿主端 apply 收到的 cordis 上下文。
71
+ * @param ns - 插件自有命名空间(小写 kebab,须唯一)。
72
+ * @param schema - 占位:schema 由宿主持有,本函数不注册。
73
+ * @param entry - 组合层配置(describe 缺席时的回落值)。
74
+ * @param hooks - source 收藏与变更通知。
75
+ */
76
+ export declare function installSettingsNamespace(
77
+ ctx: unknown,
78
+ ns: string,
79
+ schema: unknown,
80
+ entry: unknown,
81
+ hooks: SettingsNamespaceHooks,
82
+ ): void;