clearai-dsh 0.3.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +172 -0
- package/README.md +30 -30
- package/README.zh-CN.md +30 -30
- package/bin/clearai.mjs +29 -231
- package/cordis.patch.yml +3 -3
- package/lib/client.js +862 -2555
- package/lib/domain-language.js +614 -48
- package/lib/fold.js +449 -1020
- package/lib/host.js +47 -557
- package/lib/invariant.js +9 -12
- package/lib/knowledge-view.js +421 -225
- package/lib/lang.js +81 -0
- package/package.json +2 -2
- package/presets/clearai/agent.cordis.yml +57 -82
- package/presets/clearai/clearai.patch.yml +57 -82
- package/presets/clearai/plugins/clearai-kernel.js +2103 -5457
- package/presets/clearai/plugins/ontology.js +76 -20
- package/presets/clearai/plugins/prompts.js +75 -363
- package/presets/clearai/skills/clearai-loop/SKILL.md +81 -59
- package/presets/clearai/plugins/brain.js +0 -547
- package/presets/clearai/plugins/commands.js +0 -199
- package/presets/clearai/template/knowledge/README.md +0 -25
- package/presets/clearai/template/memory/README.md +0 -34
- package/presets/clearai/template/project.md +0 -49
- package/presets/clearai/template/skills/README.md +0 -37
- package/presets/clearai/template/skills/chart-diagram-qa/SKILL.md +0 -43
- package/presets/clearai/template/skills/citation-management/SKILL.md +0 -73
- package/presets/clearai/template/skills/citation-management/references/bibtex_formatting.md +0 -908
- package/presets/clearai/template/skills/citation-management/references/citation_validation.md +0 -794
- package/presets/clearai/template/skills/citation-management/references/google_scholar_search.md +0 -725
- package/presets/clearai/template/skills/citation-management/references/metadata_extraction.md +0 -870
- package/presets/clearai/template/skills/citation-management/references/pubmed_search.md +0 -839
- package/presets/clearai/template/skills/citation-management/scripts/doi_to_bibtex.py +0 -204
- package/presets/clearai/template/skills/citation-management/scripts/extract_metadata.py +0 -569
- package/presets/clearai/template/skills/citation-management/scripts/format_bibtex.py +0 -349
- package/presets/clearai/template/skills/citation-management/scripts/generate_schematic.py +0 -139
- package/presets/clearai/template/skills/citation-management/scripts/generate_schematic_ai.py +0 -817
- package/presets/clearai/template/skills/citation-management/scripts/search_google_scholar.py +0 -282
- package/presets/clearai/template/skills/citation-management/scripts/search_pubmed.py +0 -398
- package/presets/clearai/template/skills/citation-management/scripts/validate_citations.py +0 -497
- package/presets/clearai/template/skills/data-analysis/SKILL.md +0 -92
- package/presets/clearai/template/skills/data-analysis/checklists/readiness_check.md +0 -23
- package/presets/clearai/template/skills/data-analysis/templates/analysis_report.md.tpl +0 -63
- package/presets/clearai/template/skills/data-analysis/templates/cleaning_rules_draft.yaml.tpl +0 -32
- package/presets/clearai/template/skills/data-analysis/templates/data_dictionary.md.tpl +0 -12
- package/presets/clearai/template/skills/data-analysis/templates/domain_knowledge_template.md.tpl +0 -316
- package/presets/clearai/template/skills/data-analysis/templates/feature_candidates.json.tpl +0 -20
- package/presets/clearai/template/skills/data-analysis/templates/quality_scorecard.md.tpl +0 -30
- package/presets/clearai/template/skills/data-analysis/workflows/01-data-profiling.md +0 -42
- package/presets/clearai/template/skills/data-analysis/workflows/02-quality-audit.md +0 -36
- package/presets/clearai/template/skills/data-analysis/workflows/03-physical-correlation.md +0 -25
- package/presets/clearai/template/skills/data-analysis/workflows/04-unstructured-mining.md +0 -26
- package/presets/clearai/template/skills/data-qa-analysis/SKILL.md +0 -102
- package/presets/clearai/template/skills/data-qa-analysis/checklists/readiness_check.md +0 -62
- package/presets/clearai/template/skills/data-qa-analysis/templates/best_in_class_report.md.tpl +0 -56
- package/presets/clearai/template/skills/data-qa-analysis/templates/cleaning_rules_draft.yaml.tpl +0 -56
- package/presets/clearai/template/skills/data-qa-analysis/templates/data_dictionary.md.tpl +0 -13
- package/presets/clearai/template/skills/data-qa-analysis/templates/data_source_inventory_and_lineage.md.tpl +0 -146
- package/presets/clearai/template/skills/data-qa-analysis/templates/data_status_report.md.tpl +0 -60
- package/presets/clearai/template/skills/data-qa-analysis/templates/steady_state_rules.yaml.tpl +0 -41
- package/presets/clearai/template/skills/data-qa-analysis/templates/subsystem_registry.md.tpl +0 -101
- package/presets/clearai/template/skills/data-qa-analysis/templates/unified_execution_plan.md.tpl +0 -100
- package/presets/clearai/template/skills/data-qa-analysis/workflows/01-data-source-inventory-and-lineage.md +0 -194
- package/presets/clearai/template/skills/data-qa-analysis/workflows/02-data-alignment-and-tag-semantics.md +0 -122
- package/presets/clearai/template/skills/data-qa-analysis/workflows/03-steady-state-identification.md +0 -126
- package/presets/clearai/template/skills/data-qa-analysis/workflows/04-consumption-analysis.md +0 -152
- package/presets/clearai/template/skills/data-qa-analysis/workflows/05-best-in-class-and-optimization-space.md +0 -78
- package/presets/clearai/template/skills/domain-presearch/SKILL.md +0 -131
- package/presets/clearai/template/skills/domain-presearch/checklists/domain_checklist.md +0 -24
- package/presets/clearai/template/skills/domain-presearch/references/figure_code.md +0 -78
- package/presets/clearai/template/skills/domain-presearch/references/strategic_frameworks.md +0 -38
- package/presets/clearai/template/skills/exploration-loop/SKILL.md +0 -81
- package/presets/clearai/template/skills/exploratory-data-analysis/SKILL.md +0 -77
- package/presets/clearai/template/skills/exploratory-data-analysis/references/bioinformatics_genomics_formats.md +0 -664
- package/presets/clearai/template/skills/exploratory-data-analysis/references/chemistry_molecular_formats.md +0 -664
- package/presets/clearai/template/skills/exploratory-data-analysis/references/general_scientific_formats.md +0 -518
- package/presets/clearai/template/skills/exploratory-data-analysis/references/microscopy_imaging_formats.md +0 -620
- package/presets/clearai/template/skills/exploratory-data-analysis/references/proteomics_metabolomics_formats.md +0 -517
- package/presets/clearai/template/skills/exploratory-data-analysis/references/spectroscopy_analytical_formats.md +0 -633
- package/presets/clearai/template/skills/exploratory-data-analysis/scripts/eda_analyzer.py +0 -547
- package/presets/clearai/template/skills/hypothesis-generation/SKILL.md +0 -73
- package/presets/clearai/template/skills/hypothesis-generation/references/experimental_design_patterns.md +0 -329
- package/presets/clearai/template/skills/hypothesis-generation/references/hypothesis_quality_criteria.md +0 -198
- package/presets/clearai/template/skills/hypothesis-generation/references/literature_search_strategies.md +0 -622
- package/presets/clearai/template/skills/hypothesis-generation/scripts/generate_schematic.py +0 -139
- package/presets/clearai/template/skills/hypothesis-generation/scripts/generate_schematic_ai.py +0 -817
- package/presets/clearai/template/skills/literature-review/SKILL.md +0 -72
- package/presets/clearai/template/skills/literature-review/references/citation_styles.md +0 -166
- package/presets/clearai/template/skills/literature-review/references/database_strategies.md +0 -455
- package/presets/clearai/template/skills/literature-review/scripts/generate_pdf.py +0 -176
- package/presets/clearai/template/skills/literature-review/scripts/generate_schematic.py +0 -139
- package/presets/clearai/template/skills/literature-review/scripts/generate_schematic_ai.py +0 -817
- package/presets/clearai/template/skills/literature-review/scripts/search_databases.py +0 -303
- package/presets/clearai/template/skills/literature-review/scripts/verify_citations.py +0 -221
- package/presets/clearai/template/skills/paper-lookup/SKILL.md +0 -59
- package/presets/clearai/template/skills/paper-lookup/references/arxiv.md +0 -161
- package/presets/clearai/template/skills/paper-lookup/references/biorxiv.md +0 -118
- package/presets/clearai/template/skills/paper-lookup/references/core.md +0 -150
- package/presets/clearai/template/skills/paper-lookup/references/crossref.md +0 -181
- package/presets/clearai/template/skills/paper-lookup/references/medrxiv.md +0 -104
- package/presets/clearai/template/skills/paper-lookup/references/openalex.md +0 -174
- package/presets/clearai/template/skills/paper-lookup/references/pmc.md +0 -152
- package/presets/clearai/template/skills/paper-lookup/references/pubmed.md +0 -124
- package/presets/clearai/template/skills/paper-lookup/references/semantic-scholar.md +0 -203
- package/presets/clearai/template/skills/paper-lookup/references/unpaywall.md +0 -127
- package/presets/clearai/template/skills/process-presearch/SKILL.md +0 -196
- package/presets/clearai/template/skills/process-presearch/checklists/process_checklist.md +0 -18
- package/presets/clearai/template/skills/process-presearch/references/figure_code.md +0 -107
- package/presets/clearai/template/skills/process-presearch/references/source_attribution_example.md +0 -22
- package/presets/clearai/template/skills/process-understanding-extraction/SKILL.md +0 -69
- package/presets/clearai/template/skills/process-understanding-extraction/checklists/readiness_check.md +0 -34
- package/presets/clearai/template/skills/process-understanding-extraction/templates/docx_raw_dump_extractor.py.tpl +0 -132
- package/presets/clearai/template/skills/process-understanding-extraction/templates/entity_map_unit_topology.json.tpl +0 -86
- package/presets/clearai/template/skills/process-understanding-extraction/templates/process_brief.md.tpl +0 -89
- package/presets/clearai/template/skills/process-understanding-extraction/templates/process_brief_builder_from_raw_dump.py.tpl +0 -203
- package/presets/clearai/template/skills/process-understanding-extraction/templates/process_flow_mermaid.md.tpl +0 -41
- package/presets/clearai/template/skills/process-understanding-extraction/templates/unified_execution_plan.md.tpl +0 -53
- package/presets/clearai/template/skills/process-understanding-extraction/workflows/01-process-doc-discovery.md +0 -173
- package/presets/clearai/template/skills/process-understanding-extraction/workflows/02-process-understanding-and-diagramming.md +0 -106
- package/presets/clearai/template/skills/scientific-brainstorming/SKILL.md +0 -64
- package/presets/clearai/template/skills/scientific-brainstorming/references/brainstorming_methods.md +0 -326
- package/presets/clearai/template/skills/scientific-critical-thinking/SKILL.md +0 -72
- package/presets/clearai/template/skills/scientific-critical-thinking/references/common_biases.md +0 -364
- package/presets/clearai/template/skills/scientific-critical-thinking/references/evidence_hierarchy.md +0 -485
- package/presets/clearai/template/skills/scientific-critical-thinking/references/experimental_design.md +0 -496
- package/presets/clearai/template/skills/scientific-critical-thinking/references/logical_fallacies.md +0 -478
- package/presets/clearai/template/skills/scientific-critical-thinking/references/scientific_method.md +0 -169
- package/presets/clearai/template/skills/scientific-critical-thinking/references/statistical_pitfalls.md +0 -506
- package/presets/clearai/template/skills/skill-creator/SKILL.md +0 -109
- package/presets/clearai/template/skills/skill-creator/references/authoring-guide.md +0 -89
- package/presets/clearai/template/skills/statistical-analysis/SKILL.md +0 -79
- package/presets/clearai/template/skills/statistical-analysis/references/assumptions_and_diagnostics.md +0 -369
- package/presets/clearai/template/skills/statistical-analysis/references/bayesian_statistics.md +0 -653
- package/presets/clearai/template/skills/statistical-analysis/references/effect_sizes_and_power.md +0 -578
- package/presets/clearai/template/skills/statistical-analysis/references/reporting_standards.md +0 -469
- package/presets/clearai/template/skills/statistical-analysis/references/test_selection_guide.md +0 -129
- package/presets/clearai/template/skills/statistical-analysis/scripts/assumption_checks.py +0 -538
- package/presets/clearai/template/skills/web-artifact/SKILL.md +0 -165
- package/presets/clearai/template/skills/web-artifact/assets/renderer/renderer.css +0 -229
- package/presets/clearai/template/skills/web-artifact/assets/renderer/renderer.js +0 -373
- package/presets/clearai/template/skills/web-artifact/assets/vendor/elkjs/LICENSE +0 -263
- package/presets/clearai/template/skills/web-artifact/assets/vendor/elkjs/UPSTREAM.md +0 -26
- package/presets/clearai/template/skills/web-artifact/assets/vendor/elkjs/elk.bundled.js +0 -6605
- package/presets/clearai/template/skills/web-artifact/references/when-drawing-a-topology.md +0 -150
- package/presets/clearai/template/skills/web-artifact/references/when-the-page-must-work-offline.md +0 -62
- package/presets/clearai/template/skills/web-artifact/scripts/check_artifact.py +0 -167
- package/presets/clearai/template/skills/web-artifact/scripts/render_topology.js +0 -272
- package/presets/clearai/template/skills/what-if-oracle/LICENSE.txt +0 -5
- package/presets/clearai/template/skills/what-if-oracle/SKILL.md +0 -72
- package/presets/clearai/template/skills/what-if-oracle/references/scenario-templates.md +0 -154
package/bin/clearai.mjs
CHANGED
|
@@ -5,27 +5,23 @@
|
|
|
5
5
|
* 分包的三样东西落在三个平面:
|
|
6
6
|
* · 宿主半(`lib/host.js`)—— 由包自带的 `cordis.patch.yml` 在 profile 层插一行,`dsh plugin add` 自动生效;
|
|
7
7
|
* · 浏览器半(`lib/client.js`)—— 同一份清单里的 `dsh.client`,浏览器 Loader 自己扫;
|
|
8
|
-
* · agent 预设(`presets/clearai
|
|
9
|
-
*
|
|
8
|
+
* · agent 预设(`presets/clearai/clearai.patch.yml`)—— 一条 `- id: preset-clearai` 声明行,
|
|
9
|
+
* 经清单的 `dsh.bundle.patch` 挂进组合;名册(`agent-preset-registry`)读的就是它。
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* 宿主 ≥0.2.0 的名册**不扫目录、不收预设路径**(`@deepseek-ai/dsh-agent-preset-registry` 的 README:
|
|
12
|
+
* "the registry neither scans directories nor accepts preset paths"),所以旧的 root 目录那几个动词
|
|
13
|
+
* (`root-yaml` / `seed` / `unseed`)已经删掉:它们写出去的东西在这些宿主上没人读。
|
|
14
|
+
*
|
|
15
|
+
* 两个动词(默认是 `doctor` —— 一个安装侧工具不该在你没说要装的时候动你的部署):
|
|
16
|
+
* doctor 看现状:包在哪、预设在哪、组合里有没有宿主行与预设声明行、探测到的 dsh / profile 是什么
|
|
14
17
|
* install 把包装进 profile —— `dsh plugin --profile <p> add <spec>` 的一层**前置解析**
|
|
15
18
|
* (读者不必知道 profile 叫什么、CLI 从哪来、包名怎么写),装完给读数与下一步
|
|
16
|
-
* root-yaml 打印**可以直接粘进 profile 的 `cordis.patch.yml`** 的那一行(路径已算成绝对路径)
|
|
17
|
-
* seed 把预设**播种**到用户根 `~/.dsh/.agent-presets/<id>`(带哈希记账:改过的不覆盖)
|
|
18
|
-
* unseed 撤掉播种:只删「我们播的、且没被改过」的文件;用户 fork 的 id 一律不碰
|
|
19
|
-
*
|
|
20
|
-
* 纪律(与内核播种模板技能同一条):**改过的东西不覆盖,只如实报漂移**;删东西之前先看哈希。
|
|
21
|
-
* 不改用户的 `cordis.patch.yml` —— 那一行的内容由人自己粘(工具只负责把绝对路径算对)。
|
|
22
19
|
*/
|
|
23
20
|
|
|
24
|
-
import { createHash } from 'node:crypto'
|
|
25
21
|
import { spawnSync } from 'node:child_process'
|
|
26
|
-
import {
|
|
22
|
+
import { existsSync, readFileSync, statSync } from 'node:fs'
|
|
27
23
|
import { homedir } from 'node:os'
|
|
28
|
-
import { delimiter, dirname, join,
|
|
24
|
+
import { delimiter, dirname, join, resolve } from 'node:path'
|
|
29
25
|
import { fileURLToPath } from 'node:url'
|
|
30
26
|
|
|
31
27
|
const HERE = dirname(fileURLToPath(import.meta.url))
|
|
@@ -33,7 +29,6 @@ const PKG_DIR = resolve(HERE, '..')
|
|
|
33
29
|
const PRESET_ID = 'clearai'
|
|
34
30
|
const PRESET_SRC = join(PKG_DIR, 'presets', PRESET_ID)
|
|
35
31
|
const DSH_HOME = process.env.DSH_HOME ?? join(homedir(), '.dsh')
|
|
36
|
-
const LEDGER = join(DSH_HOME, '.clearai-dsh.json')
|
|
37
32
|
|
|
38
33
|
const argv = process.argv.slice(2)
|
|
39
34
|
const command = argv[0] ?? 'doctor'
|
|
@@ -67,13 +62,9 @@ const TEXT = {
|
|
|
67
62
|
zh: {
|
|
68
63
|
pkgDir: '包目录 ',
|
|
69
64
|
presetSrc: '预设源 ',
|
|
70
|
-
presetOk: '(
|
|
71
|
-
presetMissing: '(缺
|
|
65
|
+
presetOk: '(clearai.patch.yml ✓)',
|
|
66
|
+
presetMissing: '(缺 clearai.patch.yml ✗)',
|
|
72
67
|
dshHome: 'DSH_HOME ',
|
|
73
|
-
userRoot: '用户根 ',
|
|
74
|
-
rosterVisible: '✓ 名册看得见',
|
|
75
|
-
rosterAbsent: '✗ 还没有(用 seed 播种,或把 root-yaml 那一行粘进 profile)',
|
|
76
|
-
shadowCopy: ' ⚠️ 影子副本 {path} 与包里的那份**不一致**,而它被包的 root 遮住、永远不会被读到(自检却会优先读它)。删掉它,或用它来承载你自己的改动并换一个 id。',
|
|
77
68
|
profileRow: 'profile ',
|
|
78
69
|
profileAbsent: '(不存在:先跑一次 dsh --profile {profile})',
|
|
79
70
|
composeRow: '组合 ',
|
|
@@ -81,13 +72,10 @@ const TEXT = {
|
|
|
81
72
|
hostRow: '宿主行 ',
|
|
82
73
|
hostIn: '在组合里 ✓',
|
|
83
74
|
hostOut: '不在组合里(先 dsh plugin --profile {profile} add <本包>)',
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
ledgerEmpty: '(空)',
|
|
89
|
-
ledgerCount: '{count} 个条目 · {path}',
|
|
90
|
-
doctorHint: '\n提示:doctor 只读;它不会替你改 profile,也不会替你播种。',
|
|
75
|
+
presetRow: '预设声明行 ',
|
|
76
|
+
presetIn: '在组合里 ✓(preset-clearai)',
|
|
77
|
+
presetOut: '不在组合里:名册里不会有 ClearAI(这个 profile 可能没挂 agent-preset-registry,或宿主早于 0.2.0)',
|
|
78
|
+
doctorHint: '\n提示:doctor 只读;它不会替你改 profile。',
|
|
91
79
|
installHeader: '【安装】{name}@{version}',
|
|
92
80
|
installWhat: '装什么 ',
|
|
93
81
|
installWhere: '装到哪 ',
|
|
@@ -104,30 +92,15 @@ const TEXT = {
|
|
|
104
92
|
hostAbsent: '**不在组合里** —— 装是装上了,但组合里没看到它(用 doctor 查)',
|
|
105
93
|
nextStep: '\n 下一步 重启 dsh web(两半都在进程里按模块 URL 缓存,只刷新浏览器不够),然后在预设选择器里选 ClearAI。',
|
|
106
94
|
uninstall: ' 卸载 dsh plugin --profile {profile} remove {name}(同样可以冠 npx)',
|
|
107
|
-
rootYamlComment1: '# ClearAI 预设的 root(由 clearai-dsh 的 bin 打印,路径已算成绝对路径)',
|
|
108
|
-
rootYamlComment2: ' # ⚠️ 补丁层会**替换整份 config**:下面这些键必须与你部署里那份一致,否则会丢。',
|
|
109
|
-
rootYamlComment3: ' # 先 `dsh --profile <p> --dump-config | grep -A 20 agent-presets` 看一眼当前值再粘。',
|
|
110
|
-
noPresetInPackage: '✗ 包里没有预设:{path}',
|
|
111
|
-
seededTo: ' 播种到 {dest}',
|
|
112
|
-
seedCounts: ' 新增 {seeded} · 刷新 {refreshed}',
|
|
113
|
-
seedDrifted: ' · **你改过、没覆盖** {count}({list})',
|
|
114
|
-
seedNext: ' 下一步:重启 dsh(或刷新页面)后,预设选择器里应出现「ClearAI」。',
|
|
115
|
-
noSeedLedger: ' 没有播种记账:什么都不做(不知道哪些是我们播的,就不删)。',
|
|
116
|
-
unseedRemoved: ' 删掉 {count} 个「我们播的、没被改过」的文件',
|
|
117
|
-
unseedKept: ' **保留** {count} 个你改过的文件(它们现在是你的):{list}',
|
|
118
95
|
unknownCommand: 'unknown command: {command}',
|
|
119
|
-
usage: '用法:clearai-dsh [doctor|install|
|
|
96
|
+
usage: '用法:clearai-dsh [doctor|install|version] [--profile web] [--home <dir>] [--lang zh|en]\n install 还可以:--dist <dir> | --tarball <tgz> | --spec <spec>',
|
|
120
97
|
},
|
|
121
98
|
en: {
|
|
122
99
|
pkgDir: 'package ',
|
|
123
100
|
presetSrc: 'preset src ',
|
|
124
|
-
presetOk: '(
|
|
125
|
-
presetMissing: '(no
|
|
101
|
+
presetOk: '(clearai.patch.yml ✓)',
|
|
102
|
+
presetMissing: '(no clearai.patch.yml ✗)',
|
|
126
103
|
dshHome: 'DSH_HOME ',
|
|
127
|
-
userRoot: 'user root ',
|
|
128
|
-
rosterVisible: '✓ visible to the roster',
|
|
129
|
-
rosterAbsent: '✗ not there yet (seed it, or paste the root-yaml line into the profile)',
|
|
130
|
-
shadowCopy: ' ⚠️ shadow copy {path} differs from the copy in the package, and the package root shadows it — it will never be read (while the self-check reads it first). Delete it, or keep your changes there under a different id.',
|
|
131
104
|
profileRow: 'profile ',
|
|
132
105
|
profileAbsent: '(does not exist yet: run dsh --profile {profile} once)',
|
|
133
106
|
composeRow: 'composition ',
|
|
@@ -135,13 +108,10 @@ const TEXT = {
|
|
|
135
108
|
hostRow: 'host row ',
|
|
136
109
|
hostIn: 'is in the composition ✓',
|
|
137
110
|
hostOut: 'is NOT in the composition (run dsh plugin --profile {profile} add <this package>)',
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
ledgerEmpty: '(empty)',
|
|
143
|
-
ledgerCount: '{count} entries · {path}',
|
|
144
|
-
doctorHint: '\ndoctor only reads. It will not change your profile and will not seed anything for you.',
|
|
111
|
+
presetRow: 'preset row ',
|
|
112
|
+
presetIn: 'is in the composition ✓ (preset-clearai)',
|
|
113
|
+
presetOut: 'is NOT in the composition: the roster will not offer ClearAI (this profile may not mount agent-preset-registry, or the host predates 0.2.0)',
|
|
114
|
+
doctorHint: '\ndoctor only reads. It will not change your profile.',
|
|
145
115
|
installHeader: '[install] {name}@{version}',
|
|
146
116
|
installWhat: 'what ',
|
|
147
117
|
installWhere: 'where ',
|
|
@@ -158,73 +128,18 @@ const TEXT = {
|
|
|
158
128
|
hostAbsent: '**NOT in the composition** — it installed, but the composition does not show it (run doctor)',
|
|
159
129
|
nextStep: '\n next restart dsh web (both halves are cached in the running process by module URL, so a browser refresh is not enough), then pick ClearAI in the preset picker.',
|
|
160
130
|
uninstall: ' uninstall dsh plugin --profile {profile} remove {name}(npx works too)',
|
|
161
|
-
rootYamlComment1: '# ClearAI preset root (printed by clearai-dsh; the path is already absolute)',
|
|
162
|
-
rootYamlComment2: ' # ⚠️ a patch layer **replaces the whole config**: these keys must match the ones in your deployment, or they are lost.',
|
|
163
|
-
rootYamlComment3: ' # Run `dsh --profile <p> --dump-config | grep -A 20 agent-presets` first and paste over the current values.',
|
|
164
|
-
noPresetInPackage: '✗ no preset in the package: {path}',
|
|
165
|
-
seededTo: ' seeded to {dest}',
|
|
166
|
-
seedCounts: ' added {seeded} · refreshed {refreshed}',
|
|
167
|
-
seedDrifted: ' · **kept your edits** {count}({list})',
|
|
168
|
-
seedNext: ' next: restart dsh (or refresh the page) — ClearAI should now appear in the preset picker.',
|
|
169
|
-
noSeedLedger: ' nothing was seeded: doing nothing (without the ledger there is no way to tell which files are ours, so nothing is deleted).',
|
|
170
|
-
unseedRemoved: ' removed {count} file(s) we seeded and you did not edit',
|
|
171
|
-
unseedKept: ' **kept** {count} file(s) you edited (they are yours now): {list}',
|
|
172
131
|
unknownCommand: 'unknown command: {command}',
|
|
173
|
-
usage: 'usage: clearai-dsh [doctor|install|
|
|
132
|
+
usage: 'usage: clearai-dsh [doctor|install|version] [--profile web] [--home <dir>] [--lang zh|en]\n install also takes: --dist <dir> | --tarball <tgz> | --spec <spec>',
|
|
174
133
|
},
|
|
175
134
|
}
|
|
176
135
|
|
|
177
|
-
/** `{name}`
|
|
136
|
+
/** `{name}` 是占位符。 */
|
|
178
137
|
function t(key, params) {
|
|
179
138
|
const text = TEXT[lang][key] ?? TEXT.zh[key]
|
|
180
139
|
if (text === undefined) throw new Error(`missing text: ${key}`)
|
|
181
140
|
return typeof text === 'function' ? text(params ?? {}) : text.replace(/\{(\w+)\}/g, (_, name) => String(params?.[name] ?? ''))
|
|
182
141
|
}
|
|
183
142
|
|
|
184
|
-
/** 递归列出文件(相对路径 → sha256 前 16 位)。只为记账,不为校验完整性。 */
|
|
185
|
-
function hashTree(root) {
|
|
186
|
-
const out = {}
|
|
187
|
-
const walk = (dir) => {
|
|
188
|
-
let entries = []
|
|
189
|
-
try {
|
|
190
|
-
entries = readdirSync(dir, { withFileTypes: true })
|
|
191
|
-
} catch {
|
|
192
|
-
return
|
|
193
|
-
}
|
|
194
|
-
for (const entry of entries) {
|
|
195
|
-
const full = join(dir, entry.name)
|
|
196
|
-
if (entry.isDirectory()) walk(full)
|
|
197
|
-
else if (entry.isFile()) out[relative(root, full)] = createHash('sha256').update(readFileSync(full)).digest('hex').slice(0, 16)
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
walk(root)
|
|
201
|
-
return out
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
function readLedger() {
|
|
205
|
-
try {
|
|
206
|
-
const parsed = JSON.parse(readFileSync(LEDGER, 'utf8'))
|
|
207
|
-
return parsed !== null && typeof parsed === 'object' ? parsed : {}
|
|
208
|
-
} catch {
|
|
209
|
-
return {}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
function writeLedger(next) {
|
|
214
|
-
try {
|
|
215
|
-
mkdirSync(dirname(LEDGER), { recursive: true })
|
|
216
|
-
writeFileSync(LEDGER, `${JSON.stringify(next, null, 2)}\n`, 'utf8')
|
|
217
|
-
return true
|
|
218
|
-
} catch {
|
|
219
|
-
return false
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/** 名册会扫哪些 root —— 与 `@deepseek-ai/dsh-agent-presets` 的规则同形(自带 → 配置 → 用户根)。 */
|
|
224
|
-
function rosterRoots() {
|
|
225
|
-
return [join(DSH_HOME, '.agent-presets')]
|
|
226
|
-
}
|
|
227
|
-
|
|
228
143
|
/**
|
|
229
144
|
* 在 PATH 上找一个可执行文件,找到就返回全路径。
|
|
230
145
|
*
|
|
@@ -266,35 +181,12 @@ function composeQuery(profileName, env) {
|
|
|
266
181
|
function doctor() {
|
|
267
182
|
const rows = []
|
|
268
183
|
rows.push(`${t('pkgDir')}${PKG_DIR}`)
|
|
269
|
-
rows.push(`${t('presetSrc')}${PRESET_SRC}${existsSync(join(PRESET_SRC, '
|
|
184
|
+
rows.push(`${t('presetSrc')}${PRESET_SRC}${existsSync(join(PRESET_SRC, 'clearai.patch.yml')) ? t('presetOk') : t('presetMissing')}`)
|
|
270
185
|
rows.push(`${t('dshHome')}${DSH_HOME}`)
|
|
271
|
-
const roots = rosterRoots()
|
|
272
|
-
for (const root of roots) {
|
|
273
|
-
const dir = join(root, PRESET_ID)
|
|
274
|
-
const present = existsSync(join(dir, 'agent.cordis.yml'))
|
|
275
|
-
rows.push(`${t('userRoot')}${dir} ${present ? t('rosterVisible') : t('rosterAbsent')}`)
|
|
276
|
-
/**
|
|
277
|
-
* 用户根里那份**会不会被包的 root 遮住**。
|
|
278
|
-
*
|
|
279
|
-
* 名册按 root 顺序先到先得(自带 root → 配置 root → 用户根),所以包一装,用户根里
|
|
280
|
-
* 同 id 的那份副本就**再也读不到**——它会安静地烂在那里,还会把「部署出去的那份」的
|
|
281
|
-
* 自检引到你手改过的旧副本上。判据只取事实:两份 `preset.yml` 的字节是否一致。
|
|
282
|
-
*/
|
|
283
|
-
const mine = join(PRESET_SRC, 'preset.yml')
|
|
284
|
-
const theirs = join(dir, 'preset.yml')
|
|
285
|
-
if (!present || !existsSync(mine) || !existsSync(theirs)) continue
|
|
286
|
-
let same = false
|
|
287
|
-
try {
|
|
288
|
-
same = readFileSync(mine).equals(readFileSync(theirs))
|
|
289
|
-
} catch {
|
|
290
|
-
same = false
|
|
291
|
-
}
|
|
292
|
-
if (!same) rows.push(t('shadowCopy', { path: theirs }))
|
|
293
|
-
}
|
|
294
186
|
const profileDir = join(DSH_HOME, 'profiles', profile)
|
|
295
187
|
rows.push(`${t('profileRow')}${profileDir}${existsSync(profileDir) ? '' : t('profileAbsent', { profile })}`)
|
|
296
188
|
/**
|
|
297
|
-
*
|
|
189
|
+
* 宿主行与预设声明行**问组合**,不问某个文件(2026-09-11 修:装出来的形态下这两行来自
|
|
298
190
|
* **包的补丁层**,不在 profile 的 cordis.patch.yml 里 —— 读文件的写法会误报「还没挂」)。
|
|
299
191
|
* 事实在组合里;问不到就如实说问不到,不猜。
|
|
300
192
|
*/
|
|
@@ -304,12 +196,9 @@ function doctor() {
|
|
|
304
196
|
} else {
|
|
305
197
|
const rowIds = [...composed.matchAll(/^- id: (\S+)$/gm)].map((match) => match[1])
|
|
306
198
|
rows.push(`${t('hostRow')}${rowIds.includes('clearai-host') ? t('hostIn') : t('hostOut', { profile })}`)
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
rows.push(`${t('rosterRootRow')}${expr === null ? t('rosterNoRoots') : t('rosterExpr', { expr })}`)
|
|
199
|
+
/** 名册读的是组合里的 `preset-clearai` 声明行(由包的 `dsh.bundle.patch` 挂进来),不是某个目录。 */
|
|
200
|
+
rows.push(`${t('presetRow')}${rowIds.includes('preset-clearai') ? t('presetIn') : t('presetOut')}`)
|
|
310
201
|
}
|
|
311
|
-
const ledger = readLedger()
|
|
312
|
-
rows.push(`${t('seedLedgerRow')}${Object.keys(ledger).length === 0 ? t('ledgerEmpty') : t('ledgerCount', { count: Object.keys(ledger).length, path: LEDGER })}`)
|
|
313
202
|
for (const row of rows) console.log(` ${row}`)
|
|
314
203
|
console.log(t('doctorHint'))
|
|
315
204
|
}
|
|
@@ -386,99 +275,8 @@ function install() {
|
|
|
386
275
|
console.log(t('uninstall', { profile, name: manifest.name }))
|
|
387
276
|
}
|
|
388
277
|
|
|
389
|
-
function rootYaml() {
|
|
390
|
-
const line = [
|
|
391
|
-
t('rootYamlComment1'),
|
|
392
|
-
'- id: \'@deepseek-ai/dsh-agent-presets\'',
|
|
393
|
-
' config:',
|
|
394
|
-
t('rootYamlComment2'),
|
|
395
|
-
t('rootYamlComment3'),
|
|
396
|
-
' default: standard',
|
|
397
|
-
' includeShippedRoot: true',
|
|
398
|
-
' includeUserRoot: true',
|
|
399
|
-
' roots:',
|
|
400
|
-
` - path: '${join(PKG_DIR, 'presets')}'`,
|
|
401
|
-
' trust: system',
|
|
402
|
-
].join('\n')
|
|
403
|
-
console.log(line)
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
function seed() {
|
|
407
|
-
if (!existsSync(join(PRESET_SRC, 'agent.cordis.yml'))) {
|
|
408
|
-
console.error(t('noPresetInPackage', { path: PRESET_SRC }))
|
|
409
|
-
process.exit(1)
|
|
410
|
-
}
|
|
411
|
-
const root = value('root', rosterRoots()[0])
|
|
412
|
-
const dest = join(root, PRESET_ID)
|
|
413
|
-
const next = hashTree(PRESET_SRC)
|
|
414
|
-
const before = readLedger()
|
|
415
|
-
const previous = before[PRESET_ID]?.files ?? {}
|
|
416
|
-
const seeded = []
|
|
417
|
-
const refreshed = []
|
|
418
|
-
const drifted = []
|
|
419
|
-
for (const [rel, hash] of Object.entries(next)) {
|
|
420
|
-
const target = join(dest, rel)
|
|
421
|
-
const onDisk = existsSync(target) ? createHash('sha256').update(readFileSync(target)).digest('hex').slice(0, 16) : null
|
|
422
|
-
if (onDisk === null) {
|
|
423
|
-
mkdirSync(dirname(target), { recursive: true })
|
|
424
|
-
cpSync(join(PRESET_SRC, rel), target)
|
|
425
|
-
seeded.push(rel)
|
|
426
|
-
continue
|
|
427
|
-
}
|
|
428
|
-
if (onDisk === hash) continue
|
|
429
|
-
// 改过的不覆盖:与内核播种模板技能同一条纪律
|
|
430
|
-
if (previous[rel] !== undefined && onDisk !== previous[rel]) {
|
|
431
|
-
drifted.push(rel)
|
|
432
|
-
continue
|
|
433
|
-
}
|
|
434
|
-
cpSync(join(PRESET_SRC, rel), target)
|
|
435
|
-
refreshed.push(rel)
|
|
436
|
-
}
|
|
437
|
-
before[PRESET_ID] = { files: next, at: new Date().toISOString(), dest }
|
|
438
|
-
writeLedger(before)
|
|
439
|
-
console.log(t('seededTo', { dest }))
|
|
440
|
-
console.log(`${t('seedCounts', { seeded: seeded.length, refreshed: refreshed.length })}${drifted.length === 0 ? '' : t('seedDrifted', { count: drifted.length, list: drifted.slice(0, 5).join(lang === 'zh' ? '、' : ', ') })}`)
|
|
441
|
-
console.log(t('seedNext'))
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
function unseed() {
|
|
445
|
-
const ledger = readLedger()
|
|
446
|
-
const entry = ledger[PRESET_ID]
|
|
447
|
-
if (entry === undefined) {
|
|
448
|
-
console.log(t('noSeedLedger'))
|
|
449
|
-
return
|
|
450
|
-
}
|
|
451
|
-
const dest = entry.dest ?? join(rosterRoots()[0], PRESET_ID)
|
|
452
|
-
const removed = []
|
|
453
|
-
const kept = []
|
|
454
|
-
for (const [rel, hash] of Object.entries(entry.files ?? {})) {
|
|
455
|
-
const target = join(dest, rel)
|
|
456
|
-
if (!existsSync(target)) continue
|
|
457
|
-
const onDisk = createHash('sha256').update(readFileSync(target)).digest('hex').slice(0, 16)
|
|
458
|
-
if (onDisk === hash) {
|
|
459
|
-
rmSync(target)
|
|
460
|
-
removed.push(rel)
|
|
461
|
-
} else {
|
|
462
|
-
kept.push(rel)
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
delete ledger[PRESET_ID]
|
|
466
|
-
writeLedger(ledger)
|
|
467
|
-
console.log(t('unseedRemoved', { count: removed.length }))
|
|
468
|
-
if (kept.length > 0) console.log(t('unseedKept', { count: kept.length, list: kept.slice(0, 5).join(lang === 'zh' ? '、' : ', ') }))
|
|
469
|
-
// 空目录收掉(只收我们知道的那些;非空绝不动)
|
|
470
|
-
try {
|
|
471
|
-
if (existsSync(dest) && readdirSync(dest).length === 0) rmSync(dest, { recursive: true })
|
|
472
|
-
} catch {
|
|
473
|
-
/* 收不掉就算了,不影响判定 */
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
|
|
477
278
|
if (command === 'doctor') doctor()
|
|
478
279
|
else if (command === 'install') install()
|
|
479
|
-
else if (command === 'root-yaml') rootYaml()
|
|
480
|
-
else if (command === 'seed') seed()
|
|
481
|
-
else if (command === 'unseed') unseed()
|
|
482
280
|
else if (command === 'version' || flag('version')) console.log(JSON.parse(readFileSync(join(PKG_DIR, 'package.json'), 'utf8')).version)
|
|
483
281
|
else {
|
|
484
282
|
console.error(`${t('unknownCommand', { command })}\n${t('usage')}`)
|
package/cordis.patch.yml
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
- id: clearai-host
|
|
13
13
|
name: 'clearai-dsh'
|
|
14
14
|
|
|
15
|
-
# ── 预设不在这里声明 root
|
|
15
|
+
# ── 预设不在这里声明 root:宿主的名册不扫目录(本包要求宿主 ≥0.2.0-rc.2)──────────
|
|
16
16
|
#
|
|
17
17
|
# 0.2.3 及以前走的是「root 目录」机制:宿主自带 `- id: agent-presets` 行,本文件覆盖它的
|
|
18
18
|
# config,把 root 指到包内 presets/,归属落在 system 信任层。
|
|
@@ -28,5 +28,5 @@
|
|
|
28
28
|
# 依据与实测:`lab/release/0.2.3-release-blocker.md`、`lab/adapter/0.2.4-design.md`。
|
|
29
29
|
#
|
|
30
30
|
# 预设本体现在由 `presets/clearai/clearai.patch.yml` 承载(构建期由 preset/agent.cordis.yml
|
|
31
|
-
# 生成,经 package.json 的 `dsh.bundle.patch` 数组挂上)
|
|
32
|
-
# `clearai-dsh seed`
|
|
31
|
+
# 生成,经 package.json 的 `dsh.bundle.patch` 数组挂上)。想改预设的人:把声明行复制一份、
|
|
32
|
+
# 换一个 id,作为自己的 bundle patch 装(`clearai-dsh seed` 那条播种到用户根的路已随旧名册删掉)。
|