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.
Files changed (150) hide show
  1. package/CHANGELOG.md +172 -0
  2. package/README.md +30 -30
  3. package/README.zh-CN.md +30 -30
  4. package/bin/clearai.mjs +29 -231
  5. package/cordis.patch.yml +3 -3
  6. package/lib/client.js +862 -2555
  7. package/lib/domain-language.js +614 -48
  8. package/lib/fold.js +449 -1020
  9. package/lib/host.js +47 -557
  10. package/lib/invariant.js +9 -12
  11. package/lib/knowledge-view.js +421 -225
  12. package/lib/lang.js +81 -0
  13. package/package.json +2 -2
  14. package/presets/clearai/agent.cordis.yml +57 -82
  15. package/presets/clearai/clearai.patch.yml +57 -82
  16. package/presets/clearai/plugins/clearai-kernel.js +2103 -5457
  17. package/presets/clearai/plugins/ontology.js +76 -20
  18. package/presets/clearai/plugins/prompts.js +75 -363
  19. package/presets/clearai/skills/clearai-loop/SKILL.md +81 -59
  20. package/presets/clearai/plugins/brain.js +0 -547
  21. package/presets/clearai/plugins/commands.js +0 -199
  22. package/presets/clearai/template/knowledge/README.md +0 -25
  23. package/presets/clearai/template/memory/README.md +0 -34
  24. package/presets/clearai/template/project.md +0 -49
  25. package/presets/clearai/template/skills/README.md +0 -37
  26. package/presets/clearai/template/skills/chart-diagram-qa/SKILL.md +0 -43
  27. package/presets/clearai/template/skills/citation-management/SKILL.md +0 -73
  28. package/presets/clearai/template/skills/citation-management/references/bibtex_formatting.md +0 -908
  29. package/presets/clearai/template/skills/citation-management/references/citation_validation.md +0 -794
  30. package/presets/clearai/template/skills/citation-management/references/google_scholar_search.md +0 -725
  31. package/presets/clearai/template/skills/citation-management/references/metadata_extraction.md +0 -870
  32. package/presets/clearai/template/skills/citation-management/references/pubmed_search.md +0 -839
  33. package/presets/clearai/template/skills/citation-management/scripts/doi_to_bibtex.py +0 -204
  34. package/presets/clearai/template/skills/citation-management/scripts/extract_metadata.py +0 -569
  35. package/presets/clearai/template/skills/citation-management/scripts/format_bibtex.py +0 -349
  36. package/presets/clearai/template/skills/citation-management/scripts/generate_schematic.py +0 -139
  37. package/presets/clearai/template/skills/citation-management/scripts/generate_schematic_ai.py +0 -817
  38. package/presets/clearai/template/skills/citation-management/scripts/search_google_scholar.py +0 -282
  39. package/presets/clearai/template/skills/citation-management/scripts/search_pubmed.py +0 -398
  40. package/presets/clearai/template/skills/citation-management/scripts/validate_citations.py +0 -497
  41. package/presets/clearai/template/skills/data-analysis/SKILL.md +0 -92
  42. package/presets/clearai/template/skills/data-analysis/checklists/readiness_check.md +0 -23
  43. package/presets/clearai/template/skills/data-analysis/templates/analysis_report.md.tpl +0 -63
  44. package/presets/clearai/template/skills/data-analysis/templates/cleaning_rules_draft.yaml.tpl +0 -32
  45. package/presets/clearai/template/skills/data-analysis/templates/data_dictionary.md.tpl +0 -12
  46. package/presets/clearai/template/skills/data-analysis/templates/domain_knowledge_template.md.tpl +0 -316
  47. package/presets/clearai/template/skills/data-analysis/templates/feature_candidates.json.tpl +0 -20
  48. package/presets/clearai/template/skills/data-analysis/templates/quality_scorecard.md.tpl +0 -30
  49. package/presets/clearai/template/skills/data-analysis/workflows/01-data-profiling.md +0 -42
  50. package/presets/clearai/template/skills/data-analysis/workflows/02-quality-audit.md +0 -36
  51. package/presets/clearai/template/skills/data-analysis/workflows/03-physical-correlation.md +0 -25
  52. package/presets/clearai/template/skills/data-analysis/workflows/04-unstructured-mining.md +0 -26
  53. package/presets/clearai/template/skills/data-qa-analysis/SKILL.md +0 -102
  54. package/presets/clearai/template/skills/data-qa-analysis/checklists/readiness_check.md +0 -62
  55. package/presets/clearai/template/skills/data-qa-analysis/templates/best_in_class_report.md.tpl +0 -56
  56. package/presets/clearai/template/skills/data-qa-analysis/templates/cleaning_rules_draft.yaml.tpl +0 -56
  57. package/presets/clearai/template/skills/data-qa-analysis/templates/data_dictionary.md.tpl +0 -13
  58. package/presets/clearai/template/skills/data-qa-analysis/templates/data_source_inventory_and_lineage.md.tpl +0 -146
  59. package/presets/clearai/template/skills/data-qa-analysis/templates/data_status_report.md.tpl +0 -60
  60. package/presets/clearai/template/skills/data-qa-analysis/templates/steady_state_rules.yaml.tpl +0 -41
  61. package/presets/clearai/template/skills/data-qa-analysis/templates/subsystem_registry.md.tpl +0 -101
  62. package/presets/clearai/template/skills/data-qa-analysis/templates/unified_execution_plan.md.tpl +0 -100
  63. package/presets/clearai/template/skills/data-qa-analysis/workflows/01-data-source-inventory-and-lineage.md +0 -194
  64. package/presets/clearai/template/skills/data-qa-analysis/workflows/02-data-alignment-and-tag-semantics.md +0 -122
  65. package/presets/clearai/template/skills/data-qa-analysis/workflows/03-steady-state-identification.md +0 -126
  66. package/presets/clearai/template/skills/data-qa-analysis/workflows/04-consumption-analysis.md +0 -152
  67. package/presets/clearai/template/skills/data-qa-analysis/workflows/05-best-in-class-and-optimization-space.md +0 -78
  68. package/presets/clearai/template/skills/domain-presearch/SKILL.md +0 -131
  69. package/presets/clearai/template/skills/domain-presearch/checklists/domain_checklist.md +0 -24
  70. package/presets/clearai/template/skills/domain-presearch/references/figure_code.md +0 -78
  71. package/presets/clearai/template/skills/domain-presearch/references/strategic_frameworks.md +0 -38
  72. package/presets/clearai/template/skills/exploration-loop/SKILL.md +0 -81
  73. package/presets/clearai/template/skills/exploratory-data-analysis/SKILL.md +0 -77
  74. package/presets/clearai/template/skills/exploratory-data-analysis/references/bioinformatics_genomics_formats.md +0 -664
  75. package/presets/clearai/template/skills/exploratory-data-analysis/references/chemistry_molecular_formats.md +0 -664
  76. package/presets/clearai/template/skills/exploratory-data-analysis/references/general_scientific_formats.md +0 -518
  77. package/presets/clearai/template/skills/exploratory-data-analysis/references/microscopy_imaging_formats.md +0 -620
  78. package/presets/clearai/template/skills/exploratory-data-analysis/references/proteomics_metabolomics_formats.md +0 -517
  79. package/presets/clearai/template/skills/exploratory-data-analysis/references/spectroscopy_analytical_formats.md +0 -633
  80. package/presets/clearai/template/skills/exploratory-data-analysis/scripts/eda_analyzer.py +0 -547
  81. package/presets/clearai/template/skills/hypothesis-generation/SKILL.md +0 -73
  82. package/presets/clearai/template/skills/hypothesis-generation/references/experimental_design_patterns.md +0 -329
  83. package/presets/clearai/template/skills/hypothesis-generation/references/hypothesis_quality_criteria.md +0 -198
  84. package/presets/clearai/template/skills/hypothesis-generation/references/literature_search_strategies.md +0 -622
  85. package/presets/clearai/template/skills/hypothesis-generation/scripts/generate_schematic.py +0 -139
  86. package/presets/clearai/template/skills/hypothesis-generation/scripts/generate_schematic_ai.py +0 -817
  87. package/presets/clearai/template/skills/literature-review/SKILL.md +0 -72
  88. package/presets/clearai/template/skills/literature-review/references/citation_styles.md +0 -166
  89. package/presets/clearai/template/skills/literature-review/references/database_strategies.md +0 -455
  90. package/presets/clearai/template/skills/literature-review/scripts/generate_pdf.py +0 -176
  91. package/presets/clearai/template/skills/literature-review/scripts/generate_schematic.py +0 -139
  92. package/presets/clearai/template/skills/literature-review/scripts/generate_schematic_ai.py +0 -817
  93. package/presets/clearai/template/skills/literature-review/scripts/search_databases.py +0 -303
  94. package/presets/clearai/template/skills/literature-review/scripts/verify_citations.py +0 -221
  95. package/presets/clearai/template/skills/paper-lookup/SKILL.md +0 -59
  96. package/presets/clearai/template/skills/paper-lookup/references/arxiv.md +0 -161
  97. package/presets/clearai/template/skills/paper-lookup/references/biorxiv.md +0 -118
  98. package/presets/clearai/template/skills/paper-lookup/references/core.md +0 -150
  99. package/presets/clearai/template/skills/paper-lookup/references/crossref.md +0 -181
  100. package/presets/clearai/template/skills/paper-lookup/references/medrxiv.md +0 -104
  101. package/presets/clearai/template/skills/paper-lookup/references/openalex.md +0 -174
  102. package/presets/clearai/template/skills/paper-lookup/references/pmc.md +0 -152
  103. package/presets/clearai/template/skills/paper-lookup/references/pubmed.md +0 -124
  104. package/presets/clearai/template/skills/paper-lookup/references/semantic-scholar.md +0 -203
  105. package/presets/clearai/template/skills/paper-lookup/references/unpaywall.md +0 -127
  106. package/presets/clearai/template/skills/process-presearch/SKILL.md +0 -196
  107. package/presets/clearai/template/skills/process-presearch/checklists/process_checklist.md +0 -18
  108. package/presets/clearai/template/skills/process-presearch/references/figure_code.md +0 -107
  109. package/presets/clearai/template/skills/process-presearch/references/source_attribution_example.md +0 -22
  110. package/presets/clearai/template/skills/process-understanding-extraction/SKILL.md +0 -69
  111. package/presets/clearai/template/skills/process-understanding-extraction/checklists/readiness_check.md +0 -34
  112. package/presets/clearai/template/skills/process-understanding-extraction/templates/docx_raw_dump_extractor.py.tpl +0 -132
  113. package/presets/clearai/template/skills/process-understanding-extraction/templates/entity_map_unit_topology.json.tpl +0 -86
  114. package/presets/clearai/template/skills/process-understanding-extraction/templates/process_brief.md.tpl +0 -89
  115. package/presets/clearai/template/skills/process-understanding-extraction/templates/process_brief_builder_from_raw_dump.py.tpl +0 -203
  116. package/presets/clearai/template/skills/process-understanding-extraction/templates/process_flow_mermaid.md.tpl +0 -41
  117. package/presets/clearai/template/skills/process-understanding-extraction/templates/unified_execution_plan.md.tpl +0 -53
  118. package/presets/clearai/template/skills/process-understanding-extraction/workflows/01-process-doc-discovery.md +0 -173
  119. package/presets/clearai/template/skills/process-understanding-extraction/workflows/02-process-understanding-and-diagramming.md +0 -106
  120. package/presets/clearai/template/skills/scientific-brainstorming/SKILL.md +0 -64
  121. package/presets/clearai/template/skills/scientific-brainstorming/references/brainstorming_methods.md +0 -326
  122. package/presets/clearai/template/skills/scientific-critical-thinking/SKILL.md +0 -72
  123. package/presets/clearai/template/skills/scientific-critical-thinking/references/common_biases.md +0 -364
  124. package/presets/clearai/template/skills/scientific-critical-thinking/references/evidence_hierarchy.md +0 -485
  125. package/presets/clearai/template/skills/scientific-critical-thinking/references/experimental_design.md +0 -496
  126. package/presets/clearai/template/skills/scientific-critical-thinking/references/logical_fallacies.md +0 -478
  127. package/presets/clearai/template/skills/scientific-critical-thinking/references/scientific_method.md +0 -169
  128. package/presets/clearai/template/skills/scientific-critical-thinking/references/statistical_pitfalls.md +0 -506
  129. package/presets/clearai/template/skills/skill-creator/SKILL.md +0 -109
  130. package/presets/clearai/template/skills/skill-creator/references/authoring-guide.md +0 -89
  131. package/presets/clearai/template/skills/statistical-analysis/SKILL.md +0 -79
  132. package/presets/clearai/template/skills/statistical-analysis/references/assumptions_and_diagnostics.md +0 -369
  133. package/presets/clearai/template/skills/statistical-analysis/references/bayesian_statistics.md +0 -653
  134. package/presets/clearai/template/skills/statistical-analysis/references/effect_sizes_and_power.md +0 -578
  135. package/presets/clearai/template/skills/statistical-analysis/references/reporting_standards.md +0 -469
  136. package/presets/clearai/template/skills/statistical-analysis/references/test_selection_guide.md +0 -129
  137. package/presets/clearai/template/skills/statistical-analysis/scripts/assumption_checks.py +0 -538
  138. package/presets/clearai/template/skills/web-artifact/SKILL.md +0 -165
  139. package/presets/clearai/template/skills/web-artifact/assets/renderer/renderer.css +0 -229
  140. package/presets/clearai/template/skills/web-artifact/assets/renderer/renderer.js +0 -373
  141. package/presets/clearai/template/skills/web-artifact/assets/vendor/elkjs/LICENSE +0 -263
  142. package/presets/clearai/template/skills/web-artifact/assets/vendor/elkjs/UPSTREAM.md +0 -26
  143. package/presets/clearai/template/skills/web-artifact/assets/vendor/elkjs/elk.bundled.js +0 -6605
  144. package/presets/clearai/template/skills/web-artifact/references/when-drawing-a-topology.md +0 -150
  145. package/presets/clearai/template/skills/web-artifact/references/when-the-page-must-work-offline.md +0 -62
  146. package/presets/clearai/template/skills/web-artifact/scripts/check_artifact.py +0 -167
  147. package/presets/clearai/template/skills/web-artifact/scripts/render_topology.js +0 -272
  148. package/presets/clearai/template/skills/what-if-oracle/LICENSE.txt +0 -5
  149. package/presets/clearai/template/skills/what-if-oracle/SKILL.md +0 -72
  150. 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/`)—— **名册(roster)只从 root 目录扫**,包没法直接声明,
9
- * 所以要么把 root 指进包里,要么把它播种到用户根。这一件就是本工具存在的理由。
8
+ * · agent 预设(`presets/clearai/clearai.patch.yml`)—— 一条 `- id: preset-clearai` 声明行,
9
+ * 经清单的 `dsh.bundle.patch` 挂进组合;名册(`agent-preset-registry`)读的就是它。
10
10
  *
11
- * 处理方式(前四个默认只**打印**不改;默认动词仍是 `doctor` —— 一个安装侧工具不该在
12
- * 你没说要装的时候动你的部署):
13
- * doctor 看现状:包在哪、预设在哪、名册能不能看见它、探测到的 dsh / profile 是什么
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 { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from 'node:fs'
22
+ import { existsSync, readFileSync, statSync } from 'node:fs'
27
23
  import { homedir } from 'node:os'
28
- import { delimiter, dirname, join, relative, resolve } from 'node:path'
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: '(agent.cordis.yml ✓)',
71
- presetMissing: '(缺 agent.cordis.yml ✗)',
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
- rosterRootRow: '名册 root ',
85
- rosterNoRoots: '组合里没看到 roots(这个部署可能不挂名册)',
86
- rosterExpr: '{expr}(dump 打的是表达式原文,求值在装载时)',
87
- seedLedgerRow: '播种记账 ',
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|root-yaml|seed|unseed] [--profile web] [--home <dir>] [--lang zh|en]\n install 还可以:--dist <dir> | --tarball <tgz> | --spec <spec>',
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: '(agent.cordis.yml ✓)',
125
- presetMissing: '(no agent.cordis.yml ✗)',
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
- rosterRootRow: 'roster root ',
139
- rosterNoRoots: 'no roots in the composition (this deployment may not mount the roster)',
140
- rosterExpr: '{expr}(the dump prints the expression verbatim; it is evaluated at load time)',
141
- seedLedgerRow: 'seed ledger ',
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|root-yaml|seed|unseed] [--profile web] [--home <dir>] [--lang zh|en]\n install also takes: --dist <dir> | --tarball <tgz> | --spec <spec>',
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}` 是占位符;需要拼计数与列表的句子写成函数(见 doctor / seed / unseed)。 */
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, 'agent.cordis.yml')) ? t('presetOk') : t('presetMissing')}`)
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
- * 宿主行与名册 root **问组合**,不问某个文件(2026-09-11 修:装出来的形态下这两行来自
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
- const roster = /- id: agent-presets[\s\S]{0,600}?\n\s*- path:[^\n]*/.exec(composed)
308
- const expr = roster === null ? null : roster[0].split('\n').pop().trim()
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:宿主 ≥0.1.7-alpha.1 起名册不再扫目录 ────────────────
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`(播种到用户根,可改可回滚)或复制成新 id。
31
+ # 生成,经 package.json 的 `dsh.bundle.patch` 数组挂上)。想改预设的人:把声明行复制一份、
32
+ # 换一个 id,作为自己的 bundle patch 装(`clearai-dsh seed` 那条播种到用户根的路已随旧名册删掉)。