dsh-data-domain-knowledge 0.1.0-alpha.1
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 +360 -0
- package/cordis.patch.yml +410 -0
- package/eval/README.md +76 -0
- package/eval/evaluate-retrieval.mjs +121 -0
- package/eval/queries.example.jsonl +2 -0
- package/lib/client.js +111415 -0
- package/lib/types/config-schema.d.ts +35 -0
- package/lib/types/config-schema.d.ts.map +1 -0
- package/lib/types/config-schema.js +34 -0
- package/lib/types/config-schema.js.map +1 -0
- package/lib/types/convert/core-loader.d.ts +32 -0
- package/lib/types/convert/core-loader.d.ts.map +1 -0
- package/lib/types/convert/core-loader.js +60 -0
- package/lib/types/convert/core-loader.js.map +1 -0
- package/lib/types/convert/host.d.ts +88 -0
- package/lib/types/convert/host.d.ts.map +1 -0
- package/lib/types/convert/host.js +479 -0
- package/lib/types/convert/host.js.map +1 -0
- package/lib/types/convert/ingest.d.ts +125 -0
- package/lib/types/convert/ingest.d.ts.map +1 -0
- package/lib/types/convert/ingest.js +228 -0
- package/lib/types/convert/ingest.js.map +1 -0
- package/lib/types/convert/settings-schema.d.ts +18 -0
- package/lib/types/convert/settings-schema.d.ts.map +1 -0
- package/lib/types/convert/settings-schema.js +26 -0
- package/lib/types/convert/settings-schema.js.map +1 -0
- package/lib/types/convert/types.d.ts +46 -0
- package/lib/types/convert/types.d.ts.map +1 -0
- package/lib/types/convert/types.js +41 -0
- package/lib/types/convert/types.js.map +1 -0
- package/lib/types/diagnosis/cards.d.ts +71 -0
- package/lib/types/diagnosis/cards.d.ts.map +1 -0
- package/lib/types/diagnosis/cards.js +482 -0
- package/lib/types/diagnosis/cards.js.map +1 -0
- package/lib/types/diagnosis/problem-classes.d.ts +51 -0
- package/lib/types/diagnosis/problem-classes.d.ts.map +1 -0
- package/lib/types/diagnosis/problem-classes.js +66 -0
- package/lib/types/diagnosis/problem-classes.js.map +1 -0
- package/lib/types/diagnosis/schema.d.ts +65 -0
- package/lib/types/diagnosis/schema.d.ts.map +1 -0
- package/lib/types/diagnosis/schema.js +208 -0
- package/lib/types/diagnosis/schema.js.map +1 -0
- package/lib/types/diagnosis/seed-source.d.ts +20 -0
- package/lib/types/diagnosis/seed-source.d.ts.map +1 -0
- package/lib/types/diagnosis/seed-source.js +96 -0
- package/lib/types/diagnosis/seed-source.js.map +1 -0
- package/lib/types/diagnosis/seed.d.ts +50 -0
- package/lib/types/diagnosis/seed.d.ts.map +1 -0
- package/lib/types/diagnosis/seed.js +242 -0
- package/lib/types/diagnosis/seed.js.map +1 -0
- package/lib/types/diagnosis/store.d.ts +81 -0
- package/lib/types/diagnosis/store.d.ts.map +1 -0
- package/lib/types/diagnosis/store.js +409 -0
- package/lib/types/diagnosis/store.js.map +1 -0
- package/lib/types/diagnosis/types.d.ts +124 -0
- package/lib/types/diagnosis/types.d.ts.map +1 -0
- package/lib/types/diagnosis/types.js +13 -0
- package/lib/types/diagnosis/types.js.map +1 -0
- package/lib/types/directory-picker.d.ts +94 -0
- package/lib/types/directory-picker.d.ts.map +1 -0
- package/lib/types/directory-picker.js +110 -0
- package/lib/types/directory-picker.js.map +1 -0
- package/lib/types/extract-model.d.ts +76 -0
- package/lib/types/extract-model.d.ts.map +1 -0
- package/lib/types/extract-model.js +193 -0
- package/lib/types/extract-model.js.map +1 -0
- package/lib/types/extract.d.ts +121 -0
- package/lib/types/extract.d.ts.map +1 -0
- package/lib/types/extract.js +549 -0
- package/lib/types/extract.js.map +1 -0
- package/lib/types/fts.d.ts +96 -0
- package/lib/types/fts.d.ts.map +1 -0
- package/lib/types/fts.js +184 -0
- package/lib/types/fts.js.map +1 -0
- package/lib/types/index.d.ts +39 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +1112 -0
- package/lib/types/index.js.map +1 -0
- package/lib/types/intent/engine.d.ts +108 -0
- package/lib/types/intent/engine.d.ts.map +1 -0
- package/lib/types/intent/engine.js +501 -0
- package/lib/types/intent/engine.js.map +1 -0
- package/lib/types/intent/host.d.ts +88 -0
- package/lib/types/intent/host.d.ts.map +1 -0
- package/lib/types/intent/host.js +389 -0
- package/lib/types/intent/host.js.map +1 -0
- package/lib/types/intent/preset-tools.d.ts +37 -0
- package/lib/types/intent/preset-tools.d.ts.map +1 -0
- package/lib/types/intent/preset-tools.js +45 -0
- package/lib/types/intent/preset-tools.js.map +1 -0
- package/lib/types/intent/settings-schema.d.ts +59 -0
- package/lib/types/intent/settings-schema.d.ts.map +1 -0
- package/lib/types/intent/settings-schema.js +57 -0
- package/lib/types/intent/settings-schema.js.map +1 -0
- package/lib/types/intent/store.d.ts +75 -0
- package/lib/types/intent/store.d.ts.map +1 -0
- package/lib/types/intent/store.js +139 -0
- package/lib/types/intent/store.js.map +1 -0
- package/lib/types/intent/tools.d.ts +63 -0
- package/lib/types/intent/tools.d.ts.map +1 -0
- package/lib/types/intent/tools.js +108 -0
- package/lib/types/intent/tools.js.map +1 -0
- package/lib/types/intent/types.d.ts +189 -0
- package/lib/types/intent/types.d.ts.map +1 -0
- package/lib/types/intent/types.js +62 -0
- package/lib/types/intent/types.js.map +1 -0
- package/lib/types/knowledge-bases.d.ts +266 -0
- package/lib/types/knowledge-bases.d.ts.map +1 -0
- package/lib/types/knowledge-bases.js +1107 -0
- package/lib/types/knowledge-bases.js.map +1 -0
- package/lib/types/layout.d.ts +262 -0
- package/lib/types/layout.d.ts.map +1 -0
- package/lib/types/layout.js +312 -0
- package/lib/types/layout.js.map +1 -0
- package/lib/types/migrate.d.ts +110 -0
- package/lib/types/migrate.d.ts.map +1 -0
- package/lib/types/migrate.js +280 -0
- package/lib/types/migrate.js.map +1 -0
- package/lib/types/recall-rank.d.ts +158 -0
- package/lib/types/recall-rank.d.ts.map +1 -0
- package/lib/types/recall-rank.js +261 -0
- package/lib/types/recall-rank.js.map +1 -0
- package/lib/types/runtime.d.ts +568 -0
- package/lib/types/runtime.d.ts.map +1 -0
- package/lib/types/runtime.js +3045 -0
- package/lib/types/runtime.js.map +1 -0
- package/lib/types/settings-schema.d.ts +117 -0
- package/lib/types/settings-schema.d.ts.map +1 -0
- package/lib/types/settings-schema.js +92 -0
- package/lib/types/settings-schema.js.map +1 -0
- package/lib/types/settings-volatile.d.ts +102 -0
- package/lib/types/settings-volatile.d.ts.map +1 -0
- package/lib/types/settings-volatile.js +114 -0
- package/lib/types/settings-volatile.js.map +1 -0
- package/lib/types/types.d.ts +799 -0
- package/lib/types/types.d.ts.map +1 -0
- package/lib/types/types.js +387 -0
- package/lib/types/types.js.map +1 -0
- package/lib/types/wiki-types.d.ts +68 -0
- package/lib/types/wiki-types.d.ts.map +1 -0
- package/lib/types/wiki-types.js +322 -0
- package/lib/types/wiki-types.js.map +1 -0
- package/package.json +101 -0
- package/preset/tita-data-agent/agent.cordis.yml +376 -0
- package/preset/tita-data-agent/preset.yml +3 -0
- package/python/requirements.txt +8 -0
- package/scripts/doctor.mjs +70 -0
- package/scripts/e2e-pipeline.mjs +355 -0
- package/scripts/install-agent-preset.mjs +92 -0
- package/scripts/setup-embedding.sh +34 -0
- package/scripts/sync-agent-preset.mjs +188 -0
- package/src/client/AgentPresetCard.tsx +247 -0
- package/src/client/DirectoryPicker.tsx +357 -0
- package/src/client/InfoHint.tsx +65 -0
- package/src/client/IntentLogicTab.tsx +185 -0
- package/src/client/IntentTab.tsx +715 -0
- package/src/client/KnowledgeBaseTab.tsx +1454 -0
- package/src/client/KnowledgeGraphView.tsx +306 -0
- package/src/client/KnowledgePanel.tsx +381 -0
- package/src/client/KnowledgeStepRail.tsx +60 -0
- package/src/client/NodeSettings.tsx +392 -0
- package/src/client/PreviewSections.tsx +116 -0
- package/src/client/RecallPanel.tsx +399 -0
- package/src/client/TypeDefinitionDrawer.tsx +215 -0
- package/src/client/WikiFlowCard.tsx +226 -0
- package/src/client/WikiTypeEditor.tsx +332 -0
- package/src/client/agent-preset.ts +121 -0
- package/src/client/arch/AgentArchitectureGraph.tsx +219 -0
- package/src/client/arch/NodeLogicPanel.tsx +133 -0
- package/src/client/arch/ProblemDetailPanel.tsx +88 -0
- package/src/client/arch/model.ts +691 -0
- package/src/client/architecture.css +191 -0
- package/src/client/architecture.tsx +530 -0
- package/src/client/attribution/AttributionGraph.tsx +104 -0
- package/src/client/attribution/AttributionTab.tsx +332 -0
- package/src/client/attribution/CaseView.tsx +102 -0
- package/src/client/attribution/GraphStage.tsx +87 -0
- package/src/client/attribution/RunView.tsx +184 -0
- package/src/client/attribution/StageChrome.tsx +403 -0
- package/src/client/attribution/ViewSwitch.tsx +107 -0
- package/src/client/attribution/graph-options.ts +381 -0
- package/src/client/attribution/model.ts +462 -0
- package/src/client/config-scope.ts +119 -0
- package/src/client/convert/ConvertPanel.tsx +594 -0
- package/src/client/convert/styles.css +138 -0
- package/src/client/convert/styles.ts +49 -0
- package/src/client/format.ts +39 -0
- package/src/client/graph/layout.ts +181 -0
- package/src/client/graph.css +113 -0
- package/src/client/index.ts +98 -0
- package/src/client/problem-domains.ts +114 -0
- package/src/client/styles.css +940 -0
- package/src/client/styles.ts +11 -0
- package/src/client/useFitScale.ts +68 -0
- package/src/config-schema.ts +45 -0
- package/src/convert/core-loader.ts +68 -0
- package/src/convert/host.ts +579 -0
- package/src/convert/ingest.ts +367 -0
- package/src/convert/settings-schema.ts +27 -0
- package/src/convert/types.ts +65 -0
- package/src/diagnosis/cards.ts +498 -0
- package/src/diagnosis/problem-classes.ts +117 -0
- package/src/diagnosis/schema.ts +260 -0
- package/src/diagnosis/seed-source.ts +107 -0
- package/src/diagnosis/seed.ts +291 -0
- package/src/diagnosis/store.ts +432 -0
- package/src/diagnosis/types.ts +152 -0
- package/src/directory-picker.ts +164 -0
- package/src/extract-model.ts +227 -0
- package/src/extract.ts +632 -0
- package/src/fts.ts +203 -0
- package/src/index.ts +1091 -0
- package/src/intent/README.md +63 -0
- package/src/intent/engine.ts +527 -0
- package/src/intent/host.ts +462 -0
- package/src/intent/preset-tools.ts +48 -0
- package/src/intent/settings-schema.ts +63 -0
- package/src/intent/store.ts +143 -0
- package/src/intent/tools.ts +139 -0
- package/src/intent/types.ts +245 -0
- package/src/knowledge-bases.ts +1160 -0
- package/src/layout.ts +350 -0
- package/src/migrate.ts +262 -0
- package/src/python/embedding_worker.py +471 -0
- package/src/recall-rank.ts +299 -0
- package/src/runtime.ts +3069 -0
- package/src/settings-schema.ts +94 -0
- package/src/settings-volatile.ts +122 -0
- package/src/types.ts +1140 -0
- package/src/wiki-types.ts +357 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 知识库的设置 schema 与命名空间(0029 / 0031)。
|
|
3
|
+
*
|
|
4
|
+
* ## 为什么单独一个模块
|
|
5
|
+
*
|
|
6
|
+
* 它以前内联在 `index.ts` 里,于是**没有任何测试能碰到它** —— 而它恰恰是一个
|
|
7
|
+
* 「写错一个字符、整个设置分区就静默消失」的东西。抽出来之后
|
|
8
|
+
* `tests/settings-schema.test.mjs` 能用设置层真实的解析路径跑一遍。
|
|
9
|
+
*
|
|
10
|
+
* ## 空串必须被 schema 接受(v0.7.5 的真实故障)
|
|
11
|
+
*
|
|
12
|
+
* schemastery 与 zod 在这一点上**不一样**:zod 的 `.default()` 短路,缺字段时直接返回
|
|
13
|
+
* 默认值、不校验;schemastery 会**校验默认值本身**。所以
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* z.string().min(1).default('') // 自己和自己矛盾
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* 在解析时直接抛 `$.python expected string length >= 1 but got 0`。
|
|
20
|
+
*
|
|
21
|
+
* 而 0029 之后 `python` / `embeddingModel` / `rerankModel` 的语义正是「**空串 = 自动**」
|
|
22
|
+
* (跟着 `<agentRoot>/resource/` 走,见 `runtime.ts` 的 `resolveResources`)。
|
|
23
|
+
* 两者相撞的后果不是「这三个设置项失效」,而是 `settings.installSection()` 在
|
|
24
|
+
* **注册命名空间**那一步就抛异常(`register` 先 `resolve` 再登记):
|
|
25
|
+
*
|
|
26
|
+
* - 命名空间从未注册 → 面板上整个知识库设置显示「设置服务不可用」;
|
|
27
|
+
* - `swap()` 永远不被调用 → `migrateLegacyResources` 从不执行(家当一直留在旧位置);
|
|
28
|
+
* - `settings.yaml` 里存的值一个都不生效。
|
|
29
|
+
*
|
|
30
|
+
* 而且是**全量**失效,不是只有这三个字段 —— 所以这三个字段只约束「是字符串」,
|
|
31
|
+
* 不约束长度,空串的含义交给 `resolveResources()` 解释。
|
|
32
|
+
*
|
|
33
|
+
* @module
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
import z from '@deepseek-ai/schemastery'
|
|
37
|
+
import { volatileFields } from './settings-volatile.js'
|
|
38
|
+
import { DEFAULT_KNOWLEDGE_CONFIG } from './types.js'
|
|
39
|
+
import { defaultAgentRoot } from './layout.js'
|
|
40
|
+
import { DIAGNOSIS_ENTITY_TYPES } from './diagnosis/schema.js'
|
|
41
|
+
|
|
42
|
+
/** 设置命名空间。命名规则是 `^[a-z][a-z0-9-]*$`(dsh-settings 的 `parseSettingsNamespace`)。 */
|
|
43
|
+
export const SETTINGS_NAMESPACE = 'tita-data-agent-knowledge'
|
|
44
|
+
|
|
45
|
+
export const KNOWLEDGE_SETTINGS_SCHEMA = z.object(volatileFields({
|
|
46
|
+
/**
|
|
47
|
+
* **用户唯一要设的路径**(0029)。四段布局由它推出来,见 `layout.ts`。
|
|
48
|
+
*/
|
|
49
|
+
agentRoot: z.string().min(1).default(defaultAgentRoot()),
|
|
50
|
+
/**
|
|
51
|
+
* @deprecated 0029:旧布局的知识树根。**只作为一次性迁移的来源**保留 ——
|
|
52
|
+
* 它不再出现在设置面板里,也不再决定任何路径。留一个宽松的字符串默认值,
|
|
53
|
+
* 是为了让老用户的 settings JSON 还能被解析出来,从而知道旧树在哪。
|
|
54
|
+
*/
|
|
55
|
+
rootDir: z.string().default(''),
|
|
56
|
+
schemaTypes: z.array(z.union(['concept', 'metric', 'table', 'event', 'playbook', 'case', ...DIAGNOSIS_ENTITY_TYPES] as const)).default(DEFAULT_KNOWLEDGE_CONFIG.schemaTypes),
|
|
57
|
+
/**
|
|
58
|
+
* @deprecated 0013:来源分类改为按知识库持久化的注册表。这里保留一个**宽松**
|
|
59
|
+
* 的历史字段(旧的 zod union 会把自定义分类直接判为非法,等于把配置入口焊死),
|
|
60
|
+
* 它不再参与任何校验,也不再出现在设置面板里。
|
|
61
|
+
*/
|
|
62
|
+
sourceAppendTypes: z.array(z.string()).default(DEFAULT_KNOWLEDGE_CONFIG.sourceAppendTypes),
|
|
63
|
+
allowSourceTruth: z.boolean().default(DEFAULT_KNOWLEDGE_CONFIG.allowSourceTruth),
|
|
64
|
+
extractCandidates: z.boolean().default(DEFAULT_KNOWLEDGE_CONFIG.extractCandidates),
|
|
65
|
+
// #3b:模型抽取与归并。默认关 —— 它会真花钱、也依赖模型可用,所以由用户显式打开。
|
|
66
|
+
extractWithModel: z.boolean().default(DEFAULT_KNOWLEDGE_CONFIG.extractWithModel),
|
|
67
|
+
// 下面三个是「空串 = 自动」的字段,**不能加 .min(1)**:默认值就是空串,而
|
|
68
|
+
// schemastery 会校验默认值 —— 加了会让整个命名空间注册失败(见文件头注释)。
|
|
69
|
+
python: z.string().default(DEFAULT_KNOWLEDGE_CONFIG.python),
|
|
70
|
+
embeddingProvider: z.union(['wemm-python', 'ollama', 'none'] as const).default(DEFAULT_KNOWLEDGE_CONFIG.embeddingProvider),
|
|
71
|
+
embeddingBaseUrl: z.string().min(1).default(DEFAULT_KNOWLEDGE_CONFIG.embeddingBaseUrl),
|
|
72
|
+
embeddingModel: z.string().default(DEFAULT_KNOWLEDGE_CONFIG.embeddingModel),
|
|
73
|
+
embeddingDimension: z.number().step(1).min(1).default(DEFAULT_KNOWLEDGE_CONFIG.embeddingDimension),
|
|
74
|
+
embeddingBatchSize: z.number().step(1).min(1).max(64).default(DEFAULT_KNOWLEDGE_CONFIG.embeddingBatchSize),
|
|
75
|
+
embeddingTimeoutMs: z.number().step(1).min(1000).max(600000).default(DEFAULT_KNOWLEDGE_CONFIG.embeddingTimeoutMs),
|
|
76
|
+
embeddingDevice: z.union(['auto', 'mps', 'cpu'] as const).default(DEFAULT_KNOWLEDGE_CONFIG.embeddingDevice),
|
|
77
|
+
recallTopK: z.number().step(1).min(1).max(50).default(DEFAULT_KNOWLEDGE_CONFIG.recallTopK),
|
|
78
|
+
// 0031:候选池与最终条数彻底分开。上限 200 是因为再深也只是把噪声往后排,
|
|
79
|
+
// 而重排的代价随候选数线性增长。
|
|
80
|
+
recallCandidatePool: z.number().step(1).min(1).max(200).default(DEFAULT_KNOWLEDGE_CONFIG.recallCandidatePool),
|
|
81
|
+
recallMode: z.union(['fts', 'vector', 'graph', 'hybrid'] as const).default(DEFAULT_KNOWLEDGE_CONFIG.recallMode),
|
|
82
|
+
// 阈值区间都开满:初值取 WeKnora 的出厂值,但校准要能自由调。
|
|
83
|
+
// 关键词是归一化 BM25(0..1,相对),向量是原始余弦(−1..1,绝对)。
|
|
84
|
+
keywordThreshold: z.number().min(0).max(1).default(DEFAULT_KNOWLEDGE_CONFIG.keywordThreshold),
|
|
85
|
+
vectorThreshold: z.number().min(-1).max(1).default(DEFAULT_KNOWLEDGE_CONFIG.vectorThreshold),
|
|
86
|
+
contextTopN: z.number().step(1).min(1).max(50).default(DEFAULT_KNOWLEDGE_CONFIG.contextTopN),
|
|
87
|
+
// 重排阈值与 WeKnora 同刻度:**原始 cross-encoder logit**(−10..10,默认 0.2)。
|
|
88
|
+
// 展示用的 `rerankScore` 是它的 sigmoid,两者单调等价 —— 但阈值留在原始刻度上,
|
|
89
|
+
// 这样「0.2」这个数与参照实现的配置可以直接对照。
|
|
90
|
+
rerankThreshold: z.number().min(-10).max(10).default(DEFAULT_KNOWLEDGE_CONFIG.rerankThreshold),
|
|
91
|
+
rerankProvider: z.union(['bert-python', 'none'] as const).default(DEFAULT_KNOWLEDGE_CONFIG.rerankProvider),
|
|
92
|
+
rerankModel: z.string().default(DEFAULT_KNOWLEDGE_CONFIG.rerankModel),
|
|
93
|
+
rerankTimeoutMs: z.number().step(1).min(1000).max(600000).default(DEFAULT_KNOWLEDGE_CONFIG.rerankTimeoutMs),
|
|
94
|
+
}))
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 0.1.7 的一条硬规矩:**设置界面只暴露 volatile 字段。**
|
|
3
|
+
*
|
|
4
|
+
* ## 现象与原因
|
|
5
|
+
*
|
|
6
|
+
* 面板上一直显示「设置服务不可用」,客户端拿到的快照状态是 `unavailable`。原因不在
|
|
7
|
+
* 客户端、也不在 entry 能不能被寻址 —— 我们实测过,`configEditor.configuration()`
|
|
8
|
+
* 里**有**这条 entry(187 条可寻址行里有它)。真正的关卡在 `SettingsForms.describe()`
|
|
9
|
+
* 里那一步 schema 投影:
|
|
10
|
+
*
|
|
11
|
+
* ```js
|
|
12
|
+
* // dsh-settings
|
|
13
|
+
* function volatileForm(schema) {
|
|
14
|
+
* if (schema.meta.volatile) return plainSchema(schema); // ① 标了 volatile → 当成叶子字段
|
|
15
|
+
* if (schema.type === "object") { …递归,子字段一个都投影不出来就 undefined… } // ② object → 下钻
|
|
16
|
+
* // ③ 其它一切(string / number / boolean / array / union…)→ undefined
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* 然后:
|
|
21
|
+
*
|
|
22
|
+
* ```js
|
|
23
|
+
* const form = volatileForm(schema);
|
|
24
|
+
* if (form === void 0) return []; // ← 一个字段都投影不出来,整条 entry 不会进 describe()
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* 我们的字段全是普通的 `.default(...)`,既不是 object 也不是 volatile,于是全部落到
|
|
28
|
+
* 出口 ③,整条 entry 被丢掉,客户端就只剩下 `unavailable`。核心插件的写法都带
|
|
29
|
+
* `.volatile()`(`z.string().volatile()`、`z.number().default(10).volatile()`),
|
|
30
|
+
* 这就是那条约定。
|
|
31
|
+
*
|
|
32
|
+
* ## 为什么这里统一标,而不是逐个手写
|
|
33
|
+
*
|
|
34
|
+
* 三个设置 schema 一共 40 多个字段;逐个加 `.volatile()` 既啰嗦,又会漏 —— 而**漏一个
|
|
35
|
+
* 字段的后果是那个设置项在界面上直接消失**,属于沉默的失败。统一包一层让「新增字段
|
|
36
|
+
* 默认可见」成为默认行为,想让它不可见才需要显式说明。
|
|
37
|
+
*
|
|
38
|
+
* 嵌套对象**不**在这里递归:本项目里唯一的内嵌结构在数组里面(`categories` / `acts`),
|
|
39
|
+
* 而数组本来就无法被表单下钻,标成 volatile 让它按整块编辑才是可用形态。
|
|
40
|
+
*
|
|
41
|
+
* ## 标了 volatile 就必须自己应用
|
|
42
|
+
*
|
|
43
|
+
* 这是成对的两件事,只做一半就是「假的设置」。volatile 改动**不会重载插件**
|
|
44
|
+
* (`Entry._commitVolatile()` 只调 `updateVolatile()` 就地改引用,再发一个
|
|
45
|
+
* `loader/volatile-update` 事件)。所以插件必须监听那个事件,把新配置读回来并用上去 ——
|
|
46
|
+
* 见 `index.ts` 里 `applyVolatile()` 的说明。
|
|
47
|
+
*
|
|
48
|
+
* @module
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
import type Schemastery from '@deepseek-ai/schemastery'
|
|
52
|
+
import type { KnowledgeConfig } from './types.js'
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 把一组字段全部标成 volatile。返回值仍是同一个对象形状,可以直接交给 `z.object()`。
|
|
56
|
+
*
|
|
57
|
+
* @param fields - 一个 schema 对象的字段表:`{ 字段名: schemastery schema }`。
|
|
58
|
+
* @returns 每个字段都调用过 `.volatile()` 的字段表。
|
|
59
|
+
*/
|
|
60
|
+
export function volatileFields<T extends Record<string, Schemastery>>(fields: T): T {
|
|
61
|
+
return Object.fromEntries(
|
|
62
|
+
Object.entries(fields).map(([key, schema]) => [key, schema.volatile()]),
|
|
63
|
+
) as T
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* volatile 字段解包。
|
|
68
|
+
*
|
|
69
|
+
* 0.1.7 的设置字段**全部标了 `.volatile()`**(理由见 `settings-volatile.ts`),而
|
|
70
|
+
* schemastery 对 volatile 字段解析出来的**不是值,是一个引用** —— `{ get(), set() }`。
|
|
71
|
+
* 核心插件也是这么用的:`dsh-agent-default-model` 读的是 `this.config.provider.get()`。
|
|
72
|
+
*
|
|
73
|
+
* 于是「配置解析出来是什么形状」在 0.1.7 变了:**schema 产出引用,解包这一层的责任
|
|
74
|
+
* 落在插件身上**。统一在这里解开一次,下游(迁移、runtime、路由)拿到的仍然是一份
|
|
75
|
+
* 普通值的 `KnowledgeConfig`;否则 `config.agentRoot` 会是一个对象,而它会一路传进
|
|
76
|
+
* `path.join()`。
|
|
77
|
+
*
|
|
78
|
+
* 普通值原样返回 —— 所以单元测试直接塞普通对象、或配置来自非 volatile 来源时,
|
|
79
|
+
* 行为都不变。
|
|
80
|
+
*/
|
|
81
|
+
export function unwrapVolatile<T>(value: unknown): T | undefined {
|
|
82
|
+
if (value === null || typeof value !== 'object') return value as T | undefined
|
|
83
|
+
const ref = value as { get?: () => T }
|
|
84
|
+
return typeof ref.get === 'function' ? ref.get() : (value as T)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* 解一个**设置组**:组里的每个字段都过一次 `unwrapVolatile`。
|
|
89
|
+
*
|
|
90
|
+
* ## 为什么需要两层
|
|
91
|
+
*
|
|
92
|
+
* entry config 的形状是固定的 `{ 组名: { 字段: 引用 } }`(见 `config-schema.ts` 的
|
|
93
|
+
* `knowledge` / `intent` / `convert` 三组),而只解一层的结果是「组本身还是原始对象、
|
|
94
|
+
* 组里的字段还是引用」。
|
|
95
|
+
*
|
|
96
|
+
* 0029 实测到的故障就是这样来的:`intent` 组被原样交给 `applyIntent`,于是
|
|
97
|
+
* `engine.settings.predicates` 是一个 `{get, write}` 引用而不是字符串数组,
|
|
98
|
+
* `routingPrompt()` 里那句 `predicates.join('、')` 抛
|
|
99
|
+
* `this.settings.predicates.join is not a function`。抛出点在 **preset 的挂载行**上,
|
|
100
|
+
* 所以整个 preset 组合不出会话 —— 宿主平面没事(它在 apply 时不读谓词),一个字段
|
|
101
|
+
* 的类型错误把 preset 打挂。
|
|
102
|
+
*
|
|
103
|
+
* ## 为什么是两层而不是把 `unwrapVolatile` 写成递归
|
|
104
|
+
*
|
|
105
|
+
* 多出来的那一层是**已知的、唯一的一层**:组 → 字段。递归会把「数组里的对象恰好
|
|
106
|
+
* 有个 `get` 方法」也当成引用来解开 —— 那是猜,不是契约。
|
|
107
|
+
*
|
|
108
|
+
* @param group - schema 解析出来的一个设置组(字段可能是引用,也可能是普通值)。
|
|
109
|
+
* @returns 解包后的组;给 `undefined` 或非对象时返回 `{}`。
|
|
110
|
+
*/
|
|
111
|
+
export function unwrapGroup<T>(group: unknown): Partial<T> {
|
|
112
|
+
const plain = unwrapVolatile<Record<string, unknown>>(group)
|
|
113
|
+
if (plain === null || typeof plain !== 'object') return {}
|
|
114
|
+
return Object.fromEntries(
|
|
115
|
+
Object.entries(plain).map(([key, value]) => [key, unwrapVolatile(value)]),
|
|
116
|
+
) as Partial<T>
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** 把一份可能带 volatile 引用的配置解成普通值。 */
|
|
120
|
+
export function unwrapKnowledge(next: Partial<KnowledgeConfig> | undefined): Partial<KnowledgeConfig> {
|
|
121
|
+
return unwrapGroup<KnowledgeConfig>(next)
|
|
122
|
+
}
|