@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.
- package/LICENSE +21 -0
- package/README.en.md +56 -0
- package/README.md +56 -0
- package/cordis.patch.yml +7 -0
- package/lib/THIRD-PARTY-LICENSES +35 -0
- package/lib/client/api/contract.d.ts +37 -0
- package/lib/client/api/interface.d.ts +9 -0
- package/lib/client/api/routes.d.ts +11 -0
- package/lib/client/index.d.ts +8 -0
- package/lib/client/locale.d.ts +31 -0
- package/lib/client/locales.d.ts +122 -0
- package/lib/client/settings/card.d.ts +7 -0
- package/lib/client/settings/connection.d.ts +10 -0
- package/lib/client/settings/format.d.ts +4 -0
- package/lib/client/settings/history.d.ts +9 -0
- package/lib/client/settings/presets.d.ts +9 -0
- package/lib/client/settings/prob.d.ts +10 -0
- package/lib/client.js +1518 -0
- package/lib/index.d.ts +32 -0
- package/lib/index.js +3142 -0
- package/lib/server/api/deps.d.ts +53 -0
- package/lib/server/api/impl/handlers.d.ts +11 -0
- package/lib/server/api/impl/route.d.ts +28 -0
- package/lib/server/api/impl/service.d.ts +4 -0
- package/lib/server/api/interface.d.ts +3 -0
- package/lib/server/config/deps.d.ts +32 -0
- package/lib/server/config/impl/envelope.d.ts +9 -0
- package/lib/server/config/impl/model.d.ts +54 -0
- package/lib/server/config/impl/paths.d.ts +12 -0
- package/lib/server/config/impl/service.d.ts +37 -0
- package/lib/server/config/interface.d.ts +12 -0
- package/lib/server/history/deps.d.ts +25 -0
- package/lib/server/history/impl/entry.d.ts +29 -0
- package/lib/server/history/impl/hash.d.ts +8 -0
- package/lib/server/history/impl/paths.d.ts +2 -0
- package/lib/server/history/impl/redact.d.ts +2 -0
- package/lib/server/history/impl/service.d.ts +30 -0
- package/lib/server/history/interface.d.ts +4 -0
- package/lib/server/store/deps.d.ts +6 -0
- package/lib/server/store/impl/io.d.ts +24 -0
- package/lib/server/store/interface.d.ts +4 -0
- package/lib/server/tools/deps.d.ts +83 -0
- package/lib/server/tools/impl/client.d.ts +62 -0
- package/lib/server/tools/impl/define.d.ts +30 -0
- package/lib/server/tools/impl/precheck.d.ts +8 -0
- package/lib/server/tools/impl/probe.d.ts +24 -0
- package/lib/server/tools/impl/semaphore.d.ts +4 -0
- package/lib/server/tools/impl/service.d.ts +18 -0
- package/lib/server/tools/impl/validate.d.ts +17 -0
- package/lib/server/tools/interface.d.ts +7 -0
- package/lib/server/upgrade/deps.d.ts +37 -0
- package/lib/server/upgrade/impl/service.d.ts +13 -0
- package/lib/server/upgrade/impl/steps.d.ts +3 -0
- package/lib/server/upgrade/interface.d.ts +6 -0
- package/lib/shared/contract.d.ts +184 -0
- package/lib/shared/interface.d.ts +7 -0
- package/package.json +99 -0
- package/shared/client/ensure-style.d.ts +21 -0
- package/shared/client/i18n.d.ts +15 -0
- package/shared/dsh-home.d.ts +15 -0
- package/shared/host-utils.d.ts +65 -0
- package/shared/loopback.d.ts +21 -0
- package/shared/paths.d.ts +12 -0
- package/shared/settings-namespace.d.ts +82 -0
- package/shared/sse-hub.d.ts +76 -0
- package/shared/upgrade-tick.d.ts +11 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/** api 域出口:注入面(纯类型,零运行时)。 */
|
|
2
|
+
import type { ConfigV1, HistoryEntry } from "../../shared/interface.js";
|
|
3
|
+
/** 最小日志面。 */
|
|
4
|
+
export interface LoggerPort {
|
|
5
|
+
readonly warn: (message: string) => void;
|
|
6
|
+
readonly info?: (message: string) => void;
|
|
7
|
+
}
|
|
8
|
+
/** 路由注册口(组合根唯一够得着 ctx.webServer 的地方转交)。 */
|
|
9
|
+
export interface RouteRegistration {
|
|
10
|
+
(route: {
|
|
11
|
+
readonly kind: "exact";
|
|
12
|
+
readonly path: string;
|
|
13
|
+
readonly handler: (req: unknown, res: unknown) => void;
|
|
14
|
+
}): () => void;
|
|
15
|
+
}
|
|
16
|
+
/** 历史查询形(api own 窄面,防腐:history 域签名演进不直接扩散)。 */
|
|
17
|
+
export interface HistoryQuery {
|
|
18
|
+
readonly root?: string;
|
|
19
|
+
readonly sessionId?: string;
|
|
20
|
+
readonly limit?: number;
|
|
21
|
+
}
|
|
22
|
+
/** 预设清单项(api 回显面;出题规范随目录下发)。 */
|
|
23
|
+
export interface PresetListItem {
|
|
24
|
+
readonly id: string;
|
|
25
|
+
readonly enabled: boolean;
|
|
26
|
+
readonly templateVersion: 1;
|
|
27
|
+
readonly automationCap: number;
|
|
28
|
+
readonly label: string;
|
|
29
|
+
readonly description: string;
|
|
30
|
+
readonly custom: boolean;
|
|
31
|
+
}
|
|
32
|
+
/** api 域运行所需注入(全部由组合根装配,域内无 ctx、无直接跨域引用)。 */
|
|
33
|
+
export interface ApiDeps {
|
|
34
|
+
readonly logger: LoggerPort;
|
|
35
|
+
readonly register: RouteRegistration;
|
|
36
|
+
readonly version: () => string;
|
|
37
|
+
readonly readConfig: () => ConfigV1;
|
|
38
|
+
readonly writeConfig: (body: unknown) => ConfigV1;
|
|
39
|
+
readonly readPresets: () => PresetListItem[];
|
|
40
|
+
readonly readHistory: (query: HistoryQuery) => HistoryEntry[];
|
|
41
|
+
readonly removeHistory: (query: HistoryQuery) => {
|
|
42
|
+
readonly deleted: boolean;
|
|
43
|
+
};
|
|
44
|
+
readonly probeConnection: (body: unknown) => Promise<{
|
|
45
|
+
readonly ok: true;
|
|
46
|
+
readonly latencyMs: number;
|
|
47
|
+
} | {
|
|
48
|
+
readonly ok: false;
|
|
49
|
+
readonly errorCode: string;
|
|
50
|
+
readonly category: string;
|
|
51
|
+
readonly message: string;
|
|
52
|
+
}>;
|
|
53
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ApiDeps } from "../deps.js";
|
|
2
|
+
import type { Endpoint } from "./route.js";
|
|
3
|
+
/** 组装端点表(处理器全部经 ports 注入能力)。 */
|
|
4
|
+
export declare function buildEndpoints(ports: ApiDeps): Endpoint[];
|
|
5
|
+
/** 结构化抛错信封(组合根 writeConfig 按此 JSON 抛错,免跨域值引用)。 */
|
|
6
|
+
export interface ThrownFailure {
|
|
7
|
+
readonly status: number;
|
|
8
|
+
readonly errorCode: string;
|
|
9
|
+
readonly category: string;
|
|
10
|
+
readonly message: string;
|
|
11
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* api 域实现:路由围栏(回环 403 先于方法 405,异常收口 500)。
|
|
3
|
+
*
|
|
4
|
+
* - 非回环一律 403(默认参数,不放行 cross-site:普通 /api 路由);
|
|
5
|
+
* - 方法不在表里给 405(Allow 头带合法方法),不给 404;
|
|
6
|
+
* - 处理器抛错收口 500(已发头则不再写头)。
|
|
7
|
+
*/
|
|
8
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
9
|
+
import type { LoggerPort } from "../deps.js";
|
|
10
|
+
/** 端点方法表(键为大写方法名)。 */
|
|
11
|
+
export type MethodTable = Record<string, (req: IncomingMessage, res: ServerResponse) => void | Promise<void>>;
|
|
12
|
+
/** 端点(path 精确匹配)。 */
|
|
13
|
+
export interface Endpoint {
|
|
14
|
+
readonly path: string;
|
|
15
|
+
readonly methods: MethodTable;
|
|
16
|
+
}
|
|
17
|
+
/** 注册口(组合根转交的 ctx.webServer.register 窄面)。 */
|
|
18
|
+
export type RegisterRoute = (route: {
|
|
19
|
+
readonly kind: "exact";
|
|
20
|
+
readonly path: string;
|
|
21
|
+
readonly handler: (req: IncomingMessage, res: ServerResponse) => void;
|
|
22
|
+
}) => () => void;
|
|
23
|
+
/** JSON 成功体。 */
|
|
24
|
+
export declare function sendJson(res: ServerResponse, status: number, body: unknown): void;
|
|
25
|
+
/** 失败包络(必含 errorCode + category,供客户端 failureCategory 识别)。 */
|
|
26
|
+
export declare function sendFailure(res: ServerResponse, status: number, errorCode: string, category: string, message: string): void;
|
|
27
|
+
/** 注册端点组(返回摘除器;与装配顺序逆序释放由调用方组织)。 */
|
|
28
|
+
export declare function registerEndpoints(register: RegisterRoute, endpoints: Endpoint[], logger: LoggerPort): (() => void)[];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* config 域出口:本域对上游(组合根)声明的注入面(纯类型,零运行时)。
|
|
3
|
+
*
|
|
4
|
+
* 跨域运行时能力一律经此注入:落盘原语由组合根从 store 域取来传入,
|
|
5
|
+
* 本域不直引 store 实现(跨域值边零新增)。
|
|
6
|
+
*/
|
|
7
|
+
/** 最小日志面(宿主 ctx.logger 的结构子集)。 */
|
|
8
|
+
export interface LoggerPort {
|
|
9
|
+
readonly warn: (message: string) => void;
|
|
10
|
+
readonly info?: (message: string) => void;
|
|
11
|
+
}
|
|
12
|
+
/** 落盘原语面(组合根用 store 域实现装配)。 */
|
|
13
|
+
export interface FileIoPorts {
|
|
14
|
+
readonly readJsonSync: (file: string) => {
|
|
15
|
+
readonly ok: true;
|
|
16
|
+
readonly value: unknown;
|
|
17
|
+
} | {
|
|
18
|
+
readonly ok: false;
|
|
19
|
+
};
|
|
20
|
+
readonly readTextSync: (file: string) => {
|
|
21
|
+
readonly ok: true;
|
|
22
|
+
readonly text: string;
|
|
23
|
+
} | {
|
|
24
|
+
readonly ok: false;
|
|
25
|
+
};
|
|
26
|
+
readonly atomicWrite0600Sync: (file: string, text: string) => void;
|
|
27
|
+
}
|
|
28
|
+
/** config 域运行所需注入(io + 日志)。 */
|
|
29
|
+
export interface ConfigDeps {
|
|
30
|
+
readonly io: FileIoPorts;
|
|
31
|
+
readonly logger: LoggerPort;
|
|
32
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PutFailure } from "./model.js";
|
|
2
|
+
/** 嵌套包络归一化(成功即扁平体,失败即 400 负载)。 */
|
|
3
|
+
export declare function normalizePutEnvelope(body: unknown): {
|
|
4
|
+
readonly ok: true;
|
|
5
|
+
readonly flat: Record<string, unknown>;
|
|
6
|
+
} | {
|
|
7
|
+
readonly ok: false;
|
|
8
|
+
readonly failure: PutFailure;
|
|
9
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { AutomationCap, ConfigV1, CustomPreset } from "../../../shared/interface.js";
|
|
2
|
+
/** PUT 允许键(白名单;之外一律 400。envelope.ts 共用,故导出)。 */
|
|
3
|
+
export declare const ALLOWED_PUT_KEYS: readonly ["apiKeyRef", "apiKeyPlaintext", "confirm", "timeoutMs", "maxConcurrency", "truncBudget", "presets", "customPresets", "history"];
|
|
4
|
+
/** PUT 补丁(调用方只填变更键;null 表清除 ENV 引用)。 */
|
|
5
|
+
export interface ConfigPutPatch {
|
|
6
|
+
readonly apiKeyRef?: string | null;
|
|
7
|
+
readonly apiKeyPlaintext?: string;
|
|
8
|
+
readonly confirm?: boolean;
|
|
9
|
+
readonly timeoutMs?: number;
|
|
10
|
+
readonly maxConcurrency?: number;
|
|
11
|
+
readonly truncBudget?: number;
|
|
12
|
+
readonly presets?: readonly {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly enabled: boolean;
|
|
15
|
+
readonly automationCap: AutomationCap;
|
|
16
|
+
}[];
|
|
17
|
+
readonly history?: {
|
|
18
|
+
readonly perSession?: number;
|
|
19
|
+
readonly totalSessions?: number;
|
|
20
|
+
};
|
|
21
|
+
readonly customPresets?: readonly CustomPreset[];
|
|
22
|
+
}
|
|
23
|
+
/** 校验失败(HTTP 400 的负载来源;必含 errorCode + category)。 */
|
|
24
|
+
export interface PutFailure {
|
|
25
|
+
readonly errorCode: string;
|
|
26
|
+
readonly category: string;
|
|
27
|
+
readonly message: string;
|
|
28
|
+
}
|
|
29
|
+
/** 包络归一化已迁 envelope.ts(normalizePutEnvelope),此处删除避免双事实源。 */
|
|
30
|
+
/** 新鲜默认配置(每次调用返回新对象,不共享引用)。 */
|
|
31
|
+
export declare function buildDefaultConfig(): ConfigV1;
|
|
32
|
+
/** 是否为普通记录(数组/空不算。envelope.ts 共用,故导出)。 */
|
|
33
|
+
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
34
|
+
/** 归一化磁盘读到的 config.json(退役键剥离+缺口补默认;返回剥离名单供告警)。 */
|
|
35
|
+
export declare function normalizeLoadedConfig(raw: unknown): {
|
|
36
|
+
readonly config: ConfigV1;
|
|
37
|
+
readonly retired: string[];
|
|
38
|
+
};
|
|
39
|
+
/** 校验 PUT 体(成功即补丁;失败只回类别+码,不回显原文)。 */
|
|
40
|
+
/** 校验自建自定义预设整列(全量替换语义;id 保留字/形状/唯一,名与描述长度,cap 三档)。 */
|
|
41
|
+
export declare function validateCustomPresets(raw: unknown): {
|
|
42
|
+
readonly ok: true;
|
|
43
|
+
readonly list: CustomPreset[];
|
|
44
|
+
} | {
|
|
45
|
+
readonly ok: false;
|
|
46
|
+
readonly failure: PutFailure;
|
|
47
|
+
};
|
|
48
|
+
export declare function validatePutBody(body: unknown): {
|
|
49
|
+
readonly ok: true;
|
|
50
|
+
readonly patch: ConfigPutPatch;
|
|
51
|
+
} | {
|
|
52
|
+
readonly ok: false;
|
|
53
|
+
readonly failure: PutFailure;
|
|
54
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** 本插件在 DSH home 下的独立命名空间目录。 */
|
|
2
|
+
export declare function decisionGatewayHome(home?: string): string;
|
|
3
|
+
/** config.json 完整路径。 */
|
|
4
|
+
export declare function configFile(home?: string): string;
|
|
5
|
+
/** presets.json 完整路径(开关覆盖层)。 */
|
|
6
|
+
export declare function presetsFile(home?: string): string;
|
|
7
|
+
/** custom-presets.json 完整路径(自建存储;缺席即空列表)。 */
|
|
8
|
+
export declare function customPresetsFile(home?: string): string;
|
|
9
|
+
/** secrets.json 完整路径(明文密钥唯一落盘处,0600)。 */
|
|
10
|
+
export declare function secretsFile(home?: string): string;
|
|
11
|
+
/** VERSION 完整路径(存储版本刻度)。 */
|
|
12
|
+
export declare function versionFile(home?: string): string;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { ConfigDeps } from "../deps.js";
|
|
2
|
+
import type { ConfigPutPatch } from "./model.js";
|
|
3
|
+
import type { ConfigV1, CustomPreset } from "../../../shared/interface.js";
|
|
4
|
+
/**
|
|
5
|
+
* 无版本文件时的起点(BASELINE 语义钉死:字面 "0.0.0",与 "0" 数值等价——
|
|
6
|
+
* compareVersions 缺位补零,故 upgrade 侧“缺失按 0”与本字面是同一事实的两面写法)。
|
|
7
|
+
*/
|
|
8
|
+
export declare const BASELINE_VERSION = "0.0.0";
|
|
9
|
+
/** 已加载状态(组合根持有,活对象不进模块级变量)。 */
|
|
10
|
+
export interface LoadedState {
|
|
11
|
+
readonly config: ConfigV1;
|
|
12
|
+
readonly plaintext: string | undefined;
|
|
13
|
+
readonly retired: string[];
|
|
14
|
+
readonly storedVersion: string;
|
|
15
|
+
readonly customPresets: readonly CustomPreset[];
|
|
16
|
+
}
|
|
17
|
+
/** 读存储版本(缺席/空即基线)。 */
|
|
18
|
+
export declare function readStoredVersion(home: string | undefined, deps: ConfigDeps): string;
|
|
19
|
+
/** 写存储版本(一步升级完成即推进一档)。 */
|
|
20
|
+
export declare function writeStoredVersion(home: string | undefined, version: string, deps: ConfigDeps): void;
|
|
21
|
+
/** 版本号比较(逐段数值;段数不同缺位补零;预发布后缀不参与比较)。 */
|
|
22
|
+
export declare function compareVersions(left: string, right: string): number;
|
|
23
|
+
/** 本插件版本(读包根 package.json;产物形态下本模块位于 lib/server/config/impl/)。 */
|
|
24
|
+
export declare function pluginVersion(): string;
|
|
25
|
+
/** 读自建自定义预设(缺席/非法即空列表 + 告警;文件缺席不播种,首存即建)。 */
|
|
26
|
+
export declare function loadCustomPresets(home: string | undefined, deps: ConfigDeps): CustomPreset[];
|
|
27
|
+
/** 加载全部状态(三文件合并:presets.json 覆盖 config.json 的开关;退役键剥离告警)。 */
|
|
28
|
+
export declare function loadState(home: string | undefined, deps: ConfigDeps): LoadedState;
|
|
29
|
+
/** 应用已校验补丁并落盘(config.json + presets.json + secrets.json 各归其位)。 */
|
|
30
|
+
export declare function savePatch(home: string | undefined, patch: ConfigPutPatch, deps: ConfigDeps): LoadedState;
|
|
31
|
+
/** 掩码视图(GET 回显:形状同 v1,只含 apiKeyRef 名与 hasPlaintextKey,永无原文)。 */
|
|
32
|
+
export declare function toMaskedConfig(state: LoadedState): ConfigV1;
|
|
33
|
+
/** 解析可用密钥(ENV 引用优先;手改的坏形状明文视同无 key 并告警)。 */
|
|
34
|
+
export declare function resolveApiKey(state: LoadedState, env: Record<string, string | undefined>, deps: ConfigDeps): {
|
|
35
|
+
readonly key: string | undefined;
|
|
36
|
+
readonly source: "env" | "plaintext" | "none";
|
|
37
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* config 域门面:只转出组合根与 upgrade 域实际用的符号(无逻辑)。
|
|
3
|
+
*
|
|
4
|
+
* upgrade 复用本域路径与版本语义(单一事实源);其余内部符号经 impl 直引,不走门面。
|
|
5
|
+
*/
|
|
6
|
+
export type { ConfigDeps } from "./deps.js";
|
|
7
|
+
export { buildDefaultConfig, validateCustomPresets, validatePutBody } from "./impl/model.js";
|
|
8
|
+
export type { ConfigPutPatch } from "./impl/model.js";
|
|
9
|
+
export { normalizePutEnvelope } from "./impl/envelope.js";
|
|
10
|
+
export type { LoadedState } from "./impl/service.js";
|
|
11
|
+
export { BASELINE_VERSION, compareVersions, loadState, pluginVersion, readStoredVersion, resolveApiKey, savePatch, toMaskedConfig, writeStoredVersion, } from "./impl/service.js";
|
|
12
|
+
export { configFile, customPresetsFile, presetsFile, secretsFile, versionFile, } from "./impl/paths.js";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** history 域出口:注入面(纯类型,零运行时)。 */
|
|
2
|
+
/** 最小日志面。 */
|
|
3
|
+
export interface LoggerPort {
|
|
4
|
+
readonly warn: (message: string) => void;
|
|
5
|
+
readonly info?: (message: string) => void;
|
|
6
|
+
}
|
|
7
|
+
/** 落盘原语面(组合根用 store 域实现装配)。 */
|
|
8
|
+
export interface HistoryIoPorts {
|
|
9
|
+
readonly readTextSync: (file: string) => {
|
|
10
|
+
readonly ok: true;
|
|
11
|
+
readonly text: string;
|
|
12
|
+
} | {
|
|
13
|
+
readonly ok: false;
|
|
14
|
+
};
|
|
15
|
+
readonly atomicWrite0600Sync: (file: string, text: string) => void;
|
|
16
|
+
readonly listFilesSync: (dir: string) => string[];
|
|
17
|
+
readonly mtimeMs: (file: string) => number;
|
|
18
|
+
readonly removeFileSync: (file: string) => void;
|
|
19
|
+
readonly ensureDir0700: (dir: string) => void;
|
|
20
|
+
}
|
|
21
|
+
/** history 域运行所需注入。 */
|
|
22
|
+
export interface HistoryDeps {
|
|
23
|
+
readonly io: HistoryIoPorts;
|
|
24
|
+
readonly logger: LoggerPort;
|
|
25
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { AutomationLevel, HistoryEntry } from "../../../shared/interface.js";
|
|
2
|
+
/** 调用题目快照元素(tools 域 ValidQuestion 的结构子集,避免跨域值引用)。 */
|
|
3
|
+
export interface EntryQuestion {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly text: string;
|
|
6
|
+
readonly kind: "choice" | "score";
|
|
7
|
+
readonly options?: readonly string[];
|
|
8
|
+
readonly levels?: readonly string[];
|
|
9
|
+
}
|
|
10
|
+
/** 事件面(tools 域 DecideEvent 的结构子集,避免跨域值引用)。precheckHit 命中即 snippet 强制全掩码(S1-A:长 PEM/残缺头不断字节上限,命中文本不存任何原文)。questions 为调用题目快照(文本/选项同 snippet 脱敏后存)。 */
|
|
11
|
+
export interface EntryEvent {
|
|
12
|
+
readonly precheckHit: boolean;
|
|
13
|
+
readonly presetId: string;
|
|
14
|
+
readonly text: string;
|
|
15
|
+
readonly lang: "en" | "zh" | "unknown";
|
|
16
|
+
readonly truncated: boolean;
|
|
17
|
+
readonly originalLength: number;
|
|
18
|
+
readonly resultKind: string;
|
|
19
|
+
readonly questions: readonly EntryQuestion[];
|
|
20
|
+
readonly choice?: string;
|
|
21
|
+
readonly score?: number;
|
|
22
|
+
readonly confidence: number;
|
|
23
|
+
readonly tier: "none" | "high" | "low";
|
|
24
|
+
readonly automation: AutomationLevel;
|
|
25
|
+
readonly latencyMs: number;
|
|
26
|
+
readonly errorCode?: string;
|
|
27
|
+
}
|
|
28
|
+
/** 组装完整条目(now 由调用方注入,单测可定钟)。 */
|
|
29
|
+
export declare function assembleEntry(root: string, sessionId: string, event: EntryEvent, now: number): HistoryEntry;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** 工作目录指纹(分文件键;归一化换行差异不影响同一目录)。 */
|
|
2
|
+
export declare function rootHashOf(root: string): string;
|
|
3
|
+
/** 状态指纹(原文不出境存证,只存哈希)。 */
|
|
4
|
+
export declare function stateHashOf(text: string): string;
|
|
5
|
+
/** 根展示名(仅 basename,完整路径永不入库)。 */
|
|
6
|
+
export declare function rootDisplayOf(root: string): string;
|
|
7
|
+
/** 查询 root 参数归一:hex 指纹直用,路径即哈希(调用方传哪种都可)。 */
|
|
8
|
+
export declare function resolveRootHash(root: string): string;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { HistoryDeps } from "../deps.js";
|
|
2
|
+
import type { HistoryEntry } from "../../../shared/interface.js";
|
|
3
|
+
/** 会话文件名(sessionId 形状先行校验,防路径穿越)。 */
|
|
4
|
+
export declare function historyFile(home: string | undefined, rootHash: string, sessionId: string): string;
|
|
5
|
+
/** sessionId 形状校验(非法即 400,不落盘)。 */
|
|
6
|
+
export declare function assertSessionId(sessionId: string): void;
|
|
7
|
+
/** 追加条目并轮转(返回落盘文件)。 */
|
|
8
|
+
export declare function appendEntry(home: string | undefined, entry: HistoryEntry, limits: {
|
|
9
|
+
readonly perSession: number;
|
|
10
|
+
readonly totalSessions: number;
|
|
11
|
+
}, deps: HistoryDeps): string;
|
|
12
|
+
/** 查询条目(root/sessionId 可选过滤;limit 上限 500;按 ts 倒序)。 */
|
|
13
|
+
export declare function queryEntries(home: string | undefined, query: {
|
|
14
|
+
readonly root?: string;
|
|
15
|
+
readonly sessionId?: string;
|
|
16
|
+
readonly limit?: number;
|
|
17
|
+
}, deps: HistoryDeps): HistoryEntry[];
|
|
18
|
+
/**
|
|
19
|
+
* 删除单会话(root 与 sessionId 双必填,否则 400;仅删单文件,返回真实 deleted)。
|
|
20
|
+
*
|
|
21
|
+
* D2:root 走与查询对称的三形态——hex/路径直定位文件;basename 走 display 回落:
|
|
22
|
+
* 扫描会话文件找 rootDisplay+sessionId 命中的那一个,0 个即 deleted:false,
|
|
23
|
+
* 多个即 400 歧义(不同目录同 basename 时不猜删)。
|
|
24
|
+
*/
|
|
25
|
+
export declare function deleteSession(home: string | undefined, query: {
|
|
26
|
+
readonly root?: string;
|
|
27
|
+
readonly sessionId?: string;
|
|
28
|
+
}, deps: HistoryDeps): {
|
|
29
|
+
readonly deleted: boolean;
|
|
30
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** 确保目录存在且为 0700(chmod best-effort,非 POSIX 平台不抛)。 */
|
|
2
|
+
export declare function ensureDir0700(dir: string): void;
|
|
3
|
+
/** 原子写文件并置 0600(同目录临时文件 + rename;崩溃不留半截文件)。 */
|
|
4
|
+
export declare function atomicWrite0600Sync(file: string, text: string): void;
|
|
5
|
+
/** 读文本文件(缺席即 ok:false,由调用方回落默认值)。 */
|
|
6
|
+
export declare function readTextSync(file: string): {
|
|
7
|
+
readonly ok: true;
|
|
8
|
+
readonly text: string;
|
|
9
|
+
} | {
|
|
10
|
+
readonly ok: false;
|
|
11
|
+
};
|
|
12
|
+
/** 读 JSON 文件(缺席/解析失败即 ok:false,不抛)。 */
|
|
13
|
+
export declare function readJsonSync(file: string): {
|
|
14
|
+
readonly ok: true;
|
|
15
|
+
readonly value: unknown;
|
|
16
|
+
} | {
|
|
17
|
+
readonly ok: false;
|
|
18
|
+
};
|
|
19
|
+
/** 文件 mtime 毫秒(取不到即 -1,排序时沉底)。 */
|
|
20
|
+
export declare function mtimeMs(file: string): number;
|
|
21
|
+
/** 列目录下全部文件名(非目录/不可读即空数组,不抛)。 */
|
|
22
|
+
export declare function listFilesSync(dir: string): string[];
|
|
23
|
+
/** 删文件(缺席不抛)。 */
|
|
24
|
+
export declare function removeFileSync(file: string): void;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/** tools 域出口:注入面(纯类型,零运行时)。 */
|
|
2
|
+
import type { AutomationCap, AutomationLevel, ConfigV1, CustomPreset, DecisionLang, DecisionTier } from "../../shared/interface.js";
|
|
3
|
+
/** 最小日志面。 */
|
|
4
|
+
export interface LoggerPort {
|
|
5
|
+
readonly warn: (message: string) => void;
|
|
6
|
+
readonly info?: (message: string) => void;
|
|
7
|
+
}
|
|
8
|
+
/** 密钥解析器(组合根用 config 域装配:ENV 优先)。 */
|
|
9
|
+
export interface KeyResolver {
|
|
10
|
+
(): {
|
|
11
|
+
readonly key: string | undefined;
|
|
12
|
+
readonly source: "env" | "plaintext" | "none";
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/** 决议事件(tools 域的记录事实面;组合根映射为 HistoryEntry 再落盘,tools 不直引 history 域)。sessionId 由 decide 落史前校验(非法回落 unknown,随事件同行)。precheckHit 为本地密形命中旗(S1-A:命中即 snippet 强制全掩码)。questions 为调用题目快照(含候选项全列)。 */
|
|
16
|
+
export interface DecideEvent {
|
|
17
|
+
readonly sessionId: string;
|
|
18
|
+
readonly precheckHit: boolean;
|
|
19
|
+
readonly presetId: string;
|
|
20
|
+
readonly text: string;
|
|
21
|
+
readonly lang: DecisionLang;
|
|
22
|
+
readonly truncated: boolean;
|
|
23
|
+
readonly originalLength: number;
|
|
24
|
+
readonly resultKind: string;
|
|
25
|
+
readonly questions: readonly ValidQuestion[];
|
|
26
|
+
readonly choice?: string;
|
|
27
|
+
readonly score?: number;
|
|
28
|
+
readonly confidence: number;
|
|
29
|
+
readonly tier: DecisionTier;
|
|
30
|
+
readonly automation: AutomationLevel;
|
|
31
|
+
readonly latencyMs: number;
|
|
32
|
+
readonly errorCode?: string;
|
|
33
|
+
}
|
|
34
|
+
/** 事件记录器(组合根用 history 域装配;测试可注入内存实现)。 */
|
|
35
|
+
export interface EventRecorder {
|
|
36
|
+
(event: DecideEvent): void;
|
|
37
|
+
}
|
|
38
|
+
/** fetch 注入缝(默认全局 fetch 适配;单测注入 mock,全程离线)。 */
|
|
39
|
+
export interface FetchImpl {
|
|
40
|
+
(url: string, init: {
|
|
41
|
+
readonly method: string;
|
|
42
|
+
readonly headers: Record<string, string>;
|
|
43
|
+
readonly body: string;
|
|
44
|
+
readonly signal: AbortSignal;
|
|
45
|
+
}): Promise<{
|
|
46
|
+
readonly status: number;
|
|
47
|
+
readonly text: string;
|
|
48
|
+
}>;
|
|
49
|
+
}
|
|
50
|
+
/** decide 运行所需注入(连接参数取自配置快照,调用方按需刷新)。 */
|
|
51
|
+
export interface DecideDeps {
|
|
52
|
+
readonly logger: LoggerPort;
|
|
53
|
+
readonly connection: ConfigV1["connection"];
|
|
54
|
+
readonly isEnabled: (presetId: string) => boolean;
|
|
55
|
+
readonly capOf: (presetId: string) => AutomationCap;
|
|
56
|
+
readonly customPresets?: ReadonlyMap<string, CustomPreset>;
|
|
57
|
+
readonly resolveKey: KeyResolver;
|
|
58
|
+
readonly recordEvent?: EventRecorder;
|
|
59
|
+
/** 并发门(组合根按 maxConcurrency 创建信号量后传入;缺席即直行)。 */
|
|
60
|
+
readonly limit?: <T>(task: () => Promise<T>, signal?: AbortSignal) => Promise<T>;
|
|
61
|
+
readonly fetchImpl?: FetchImpl;
|
|
62
|
+
readonly root: string;
|
|
63
|
+
readonly sessionId: string;
|
|
64
|
+
readonly now?: () => number;
|
|
65
|
+
/** 调用方取消信号(ToolRunContext.signal 经 depsFor 透传)。 */
|
|
66
|
+
readonly signal: AbortSignal;
|
|
67
|
+
}
|
|
68
|
+
/** 校验后问题(文本已做 255 长度校验,id 已做 ASCII 校验;score 可带 2-10 levels,缺省即默认五档)。 */
|
|
69
|
+
export interface ValidQuestion {
|
|
70
|
+
readonly id: string;
|
|
71
|
+
readonly text: string;
|
|
72
|
+
readonly kind: "choice" | "score";
|
|
73
|
+
readonly options?: readonly string[];
|
|
74
|
+
readonly levels?: readonly string[];
|
|
75
|
+
}
|
|
76
|
+
/** 校验后决议输入。 */
|
|
77
|
+
export interface ValidDecide {
|
|
78
|
+
readonly presetId: string;
|
|
79
|
+
readonly text: string;
|
|
80
|
+
readonly lang: DecisionLang;
|
|
81
|
+
readonly questions: readonly ValidQuestion[];
|
|
82
|
+
readonly appliedSource: "override" | "custom";
|
|
83
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Questions, SystemOneResult } from "@typesafe-ai/sdk";
|
|
2
|
+
import type { FetchImpl } from "../deps.js";
|
|
3
|
+
import type { ValidQuestion } from "../deps.js";
|
|
4
|
+
/** 上游失败(可重试性由本模块判定,调用方只读 code/category)。 */
|
|
5
|
+
export interface DecisionFailure {
|
|
6
|
+
readonly code: string;
|
|
7
|
+
readonly category: string;
|
|
8
|
+
readonly message: string;
|
|
9
|
+
readonly retryable: boolean;
|
|
10
|
+
readonly status?: number;
|
|
11
|
+
}
|
|
12
|
+
/** 远端原始决议(已做形状校验的最小面)。 */
|
|
13
|
+
export interface RemoteVerdict {
|
|
14
|
+
readonly resultKind: "choice" | "score";
|
|
15
|
+
readonly choice?: string;
|
|
16
|
+
readonly score?: number;
|
|
17
|
+
readonly confidence: number;
|
|
18
|
+
readonly tier: number;
|
|
19
|
+
readonly automation: number;
|
|
20
|
+
readonly codepoints: number;
|
|
21
|
+
}
|
|
22
|
+
/** 默认 fetch 适配(全局 fetch 转窄面;无全局 fetch 即抛未实现)。 */
|
|
23
|
+
export declare function defaultFetchImpl(): FetchImpl;
|
|
24
|
+
/** 请求体(官方 SystemOne 形状:model + 字符串 state + 字典 questions)。 */
|
|
25
|
+
export interface DecisionRequestBody {
|
|
26
|
+
readonly model: string;
|
|
27
|
+
readonly state: string;
|
|
28
|
+
readonly questions: Questions;
|
|
29
|
+
}
|
|
30
|
+
/** confidence 派生分层(0.8 对齐 UI high 线;0.5 低分界)。 */
|
|
31
|
+
export declare function confidenceTier(confidence: number): number;
|
|
32
|
+
/** 远端问题投影(内部 ValidQuestion 转 SDK 字典;choice criteria 置空描述,score 用自带 levels 或默认数字 legend)。 */
|
|
33
|
+
export declare function toWireQuestions(questions: readonly ValidQuestion[]): Questions;
|
|
34
|
+
/**
|
|
35
|
+
* 融合调用方信号与内部信号(SDK 超时信号):任一 abort 即取消外调。
|
|
36
|
+
*
|
|
37
|
+
* AbortSignal.any 优先(原子融合),缺席回落手动级联(已 abort 即取已取消侧,
|
|
38
|
+
* 否则建中继控制器双向转发,移除监听防泄漏)。调用方缺席即回内部信号原样。
|
|
39
|
+
*/
|
|
40
|
+
export declare function combineSignals(callerSignal: AbortSignal | undefined, innerSignal: AbortSignal): AbortSignal;
|
|
41
|
+
/** 首题答案转 verdict(多题时首题驱动输出;noul/未知形状即 bad-payload 不重试)。 */
|
|
42
|
+
export declare function mapFirstAnswer(body: DecisionRequestBody, result: SystemOneResult<Questions>): {
|
|
43
|
+
readonly ok: true;
|
|
44
|
+
readonly verdict: RemoteVerdict;
|
|
45
|
+
} | {
|
|
46
|
+
readonly ok: false;
|
|
47
|
+
readonly failure: DecisionFailure;
|
|
48
|
+
};
|
|
49
|
+
/** SDK 错误转失败面(状态码沿旧映射;客户端校验错不重试;裸抛错归网络可重试;调用方取消单列 ABORTED 不重试)。 */
|
|
50
|
+
export declare function sdkErrorToFailure(cause: unknown): DecisionFailure;
|
|
51
|
+
/**
|
|
52
|
+
* 有限重试调用(最多 2 次重试;返回重试次数供输出计费面)。
|
|
53
|
+
*
|
|
54
|
+
* timeoutMs 是整次调用的总预算(非逐次):每次尝试按剩余预算设置 SDK 超时,
|
|
55
|
+
* 预算耗尽后的重试即时失败——慢上游不会把单次决议拖成 3 倍超时(锁定的超时探针
|
|
56
|
+
* 用 timeoutMs=1000 + 2s 轮询钉死该语义:逐次预算下 3 次尝试必超窗)。
|
|
57
|
+
*/
|
|
58
|
+
export declare function callWithRetry(body: DecisionRequestBody, key: string, timeoutMs: number, fetchImpl: FetchImpl, callerSignal?: AbortSignal): Promise<{
|
|
59
|
+
readonly verdict?: RemoteVerdict;
|
|
60
|
+
readonly failure?: DecisionFailure;
|
|
61
|
+
readonly retries: number;
|
|
62
|
+
}>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tools 域实现:模型工具定义(ws_request_verdict / ws_list_verdict_guides)。
|
|
3
|
+
*
|
|
4
|
+
* - 注册面只经组合根的 ctx.tools.register 进入宿主;本模块只产出定义;
|
|
5
|
+
* - exec 上下文防御式读取(sessionId/cwd 缺席即回落 unknown/process.cwd());
|
|
6
|
+
* - output 附 JSON 渲染(文本块),失败包络同样可读(无概率字段);
|
|
7
|
+
* - ws_list_verdict_guides 只读(不记录历史、不触网络)。
|
|
8
|
+
*/
|
|
9
|
+
import type { ToolDefinition, ToolRunContext } from "@deepseek-ai/dsh-tools";
|
|
10
|
+
import type { CustomPreset } from "../../../shared/interface.js";
|
|
11
|
+
import type { DecideDeps } from "../deps.js";
|
|
12
|
+
/** 工具装配(组合根绑定:exec→deps 映射 + 快照取数)。 */
|
|
13
|
+
export interface ToolAssembly {
|
|
14
|
+
readonly depsFor: (exec: ToolRunContext) => DecideDeps;
|
|
15
|
+
readonly snapshot: () => {
|
|
16
|
+
readonly isEnabled: (presetId: string) => boolean;
|
|
17
|
+
readonly capOf: (presetId: string) => number;
|
|
18
|
+
readonly customs?: readonly CustomPreset[];
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* exec 取 sessionId(多形态防御读取)。
|
|
23
|
+
*
|
|
24
|
+
* 本函数是两处解析规则收敛后的唯一实现(D4):组合根直接引用本导出,不再自写根侧版本。
|
|
25
|
+
*/
|
|
26
|
+
export declare function sessionOf(exec: unknown): string;
|
|
27
|
+
/** exec 取工作目录(缺席回落进程 cwd;与 sessionOf 同源收敛,见上)。 */
|
|
28
|
+
export declare function rootOf(exec: unknown): string;
|
|
29
|
+
/** 产出两工具定义。 */
|
|
30
|
+
export declare function buildToolDefinitions(assembly: ToolAssembly): ToolDefinition[];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tools 域实现:连接探针(空体合法;密钥由调用方解析后传入;不记历史)。
|
|
3
|
+
*
|
|
4
|
+
* 从组合根沉入本域(内聚收窄):探针的远端调用本就是 tools 能力,组合根只做密钥解析与装配。
|
|
5
|
+
*/
|
|
6
|
+
import type { FetchImpl } from "../deps.js";
|
|
7
|
+
/** 探针结果。 */
|
|
8
|
+
export type ProbeResult = {
|
|
9
|
+
readonly ok: true;
|
|
10
|
+
readonly latencyMs: number;
|
|
11
|
+
} | {
|
|
12
|
+
readonly ok: false;
|
|
13
|
+
readonly errorCode: string;
|
|
14
|
+
readonly category: string;
|
|
15
|
+
readonly message: string;
|
|
16
|
+
};
|
|
17
|
+
/** 探针输入(key 缺席即 NO_KEY,不触网络)。 */
|
|
18
|
+
export interface ProbeInput {
|
|
19
|
+
readonly key: string | undefined;
|
|
20
|
+
readonly timeoutMs: number;
|
|
21
|
+
readonly fetchImpl?: FetchImpl;
|
|
22
|
+
}
|
|
23
|
+
/** 执行连接探针(general 模板最小体;成功/失败均不记历史)。 */
|
|
24
|
+
export declare function probeConnection(input: ProbeInput): Promise<ProbeResult>;
|