dsh-data-domain-knowledge 0.1.0-alpha.9 → 0.1.1-alpha.2

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 (438) hide show
  1. package/README.md +118 -567
  2. package/cordis.patch.yml +5 -418
  3. package/eval/README.md +19 -8
  4. package/eval/benchmark-extraction-format.mjs +20 -0
  5. package/eval/evaluate-retrieval.mjs +17 -8
  6. package/eval/queries.example.jsonl +1 -0
  7. package/lib/client.js +4181 -3239
  8. package/lib/contract-envelope.d.ts +91 -0
  9. package/lib/contract-envelope.js +106 -0
  10. package/lib/contract-layout.d.ts +130 -0
  11. package/lib/contract-layout.js +138 -0
  12. package/lib/contract-refs.d.ts +39 -0
  13. package/lib/contract-refs.js +9 -0
  14. package/lib/contract-version.d.ts +311 -0
  15. package/lib/contract-version.js +270 -0
  16. package/lib/contract-wire.d.ts +147 -0
  17. package/lib/contract-wire.js +99 -0
  18. package/lib/contracts.d.ts +12 -0
  19. package/lib/contracts.js +12 -0
  20. package/lib/doc-page.js +2 -2
  21. package/lib/pages.js +3329 -1296
  22. package/lib/types/agent-behavior-rules.d.ts +10 -0
  23. package/lib/types/agent-behavior-rules.d.ts.map +1 -0
  24. package/lib/types/agent-behavior-rules.js +28 -0
  25. package/lib/types/agent-behavior-rules.js.map +1 -0
  26. package/lib/types/axis-registry.d.ts +37 -5
  27. package/lib/types/axis-registry.d.ts.map +1 -1
  28. package/lib/types/axis-registry.js +234 -26
  29. package/lib/types/axis-registry.js.map +1 -1
  30. package/lib/types/card-organize.d.ts +27 -12
  31. package/lib/types/card-organize.d.ts.map +1 -1
  32. package/lib/types/card-organize.js +58 -73
  33. package/lib/types/card-organize.js.map +1 -1
  34. package/lib/types/compiler/embedding-identity.d.ts +3 -0
  35. package/lib/types/compiler/embedding-identity.d.ts.map +1 -0
  36. package/lib/types/compiler/embedding-identity.js +24 -0
  37. package/lib/types/compiler/embedding-identity.js.map +1 -0
  38. package/lib/types/compiler/snapshot.d.ts +16 -0
  39. package/lib/types/compiler/snapshot.d.ts.map +1 -0
  40. package/lib/types/compiler/snapshot.js +2 -0
  41. package/lib/types/compiler/snapshot.js.map +1 -0
  42. package/lib/types/config-schema.d.ts +6 -3
  43. package/lib/types/config-schema.d.ts.map +1 -1
  44. package/lib/types/config-schema.js +6 -2
  45. package/lib/types/config-schema.js.map +1 -1
  46. package/lib/types/convert/host.d.ts +6 -5
  47. package/lib/types/convert/host.d.ts.map +1 -1
  48. package/lib/types/convert/host.js +58 -18
  49. package/lib/types/convert/host.js.map +1 -1
  50. package/lib/types/convert/ingest.d.ts +10 -1
  51. package/lib/types/convert/ingest.d.ts.map +1 -1
  52. package/lib/types/convert/ingest.js +68 -9
  53. package/lib/types/convert/ingest.js.map +1 -1
  54. package/lib/types/derive-contract.d.ts +3 -0
  55. package/lib/types/derive-contract.d.ts.map +1 -0
  56. package/lib/types/derive-contract.js +15 -0
  57. package/lib/types/derive-contract.js.map +1 -0
  58. package/lib/types/diagnosis/cards.d.ts +7 -3
  59. package/lib/types/diagnosis/cards.d.ts.map +1 -1
  60. package/lib/types/diagnosis/cards.js +13 -8
  61. package/lib/types/diagnosis/cards.js.map +1 -1
  62. package/lib/types/diagnosis/run.d.ts +4 -13
  63. package/lib/types/diagnosis/run.d.ts.map +1 -1
  64. package/lib/types/diagnosis/run.js +26 -16
  65. package/lib/types/diagnosis/run.js.map +1 -1
  66. package/lib/types/diagnosis/schema.js +2 -2
  67. package/lib/types/diagnosis/schema.js.map +1 -1
  68. package/lib/types/diagnosis/seed-source.d.ts +1 -1
  69. package/lib/types/diagnosis/seed-source.d.ts.map +1 -1
  70. package/lib/types/diagnosis/seed-source.js +5 -4
  71. package/lib/types/diagnosis/seed-source.js.map +1 -1
  72. package/lib/types/diagnosis/seed.d.ts +4 -4
  73. package/lib/types/diagnosis/seed.d.ts.map +1 -1
  74. package/lib/types/diagnosis/seed.js +6 -8
  75. package/lib/types/diagnosis/seed.js.map +1 -1
  76. package/lib/types/diagnosis/store.d.ts +24 -18
  77. package/lib/types/diagnosis/store.d.ts.map +1 -1
  78. package/lib/types/diagnosis/store.js +130 -65
  79. package/lib/types/diagnosis/store.js.map +1 -1
  80. package/lib/types/diagnosis/types.d.ts +47 -15
  81. package/lib/types/diagnosis/types.d.ts.map +1 -1
  82. package/lib/types/diagnosis/types.js.map +1 -1
  83. package/lib/types/environment/dsh-python.d.ts +77 -0
  84. package/lib/types/environment/dsh-python.d.ts.map +1 -0
  85. package/lib/types/environment/dsh-python.js +139 -0
  86. package/lib/types/environment/dsh-python.js.map +1 -0
  87. package/lib/types/environment/install.d.ts +15 -0
  88. package/lib/types/environment/install.d.ts.map +1 -0
  89. package/lib/types/environment/install.js +297 -0
  90. package/lib/types/environment/install.js.map +1 -0
  91. package/lib/types/environment/manifest.d.ts +208 -0
  92. package/lib/types/environment/manifest.d.ts.map +1 -0
  93. package/lib/types/environment/manifest.js +26 -0
  94. package/lib/types/environment/manifest.js.map +1 -0
  95. package/lib/types/environment/model-catalog.d.ts +223 -0
  96. package/lib/types/environment/model-catalog.d.ts.map +1 -0
  97. package/lib/types/environment/model-catalog.js +129 -0
  98. package/lib/types/environment/model-catalog.js.map +1 -0
  99. package/lib/types/environment/process.d.ts +10 -0
  100. package/lib/types/environment/process.d.ts.map +1 -0
  101. package/lib/types/environment/process.js +54 -0
  102. package/lib/types/environment/process.js.map +1 -0
  103. package/lib/types/environment/selection.d.ts +9 -0
  104. package/lib/types/environment/selection.d.ts.map +1 -0
  105. package/lib/types/environment/selection.js +29 -0
  106. package/lib/types/environment/selection.js.map +1 -0
  107. package/lib/types/environment/service.d.ts +64 -0
  108. package/lib/types/environment/service.d.ts.map +1 -0
  109. package/lib/types/environment/service.js +424 -0
  110. package/lib/types/environment/service.js.map +1 -0
  111. package/lib/types/environment/types.d.ts +56 -0
  112. package/lib/types/environment/types.d.ts.map +1 -0
  113. package/lib/types/environment/types.js +2 -0
  114. package/lib/types/environment/types.js.map +1 -0
  115. package/lib/types/events.d.ts +76 -0
  116. package/lib/types/events.d.ts.map +1 -0
  117. package/lib/types/events.js +52 -0
  118. package/lib/types/events.js.map +1 -0
  119. package/lib/types/extract-contract.d.ts +3 -0
  120. package/lib/types/extract-contract.d.ts.map +1 -0
  121. package/lib/types/extract-contract.js +41 -0
  122. package/lib/types/extract-contract.js.map +1 -0
  123. package/lib/types/extract-model.d.ts +5 -0
  124. package/lib/types/extract-model.d.ts.map +1 -1
  125. package/lib/types/extract-model.js.map +1 -1
  126. package/lib/types/extract-table-contract.d.ts +3 -0
  127. package/lib/types/extract-table-contract.d.ts.map +1 -0
  128. package/lib/types/extract-table-contract.js +27 -0
  129. package/lib/types/extract-table-contract.js.map +1 -0
  130. package/lib/types/extract-table.d.ts +8 -0
  131. package/lib/types/extract-table.d.ts.map +1 -0
  132. package/lib/types/extract-table.js +158 -0
  133. package/lib/types/extract-table.js.map +1 -0
  134. package/lib/types/extraction-runs.d.ts +30 -6
  135. package/lib/types/extraction-runs.d.ts.map +1 -1
  136. package/lib/types/extraction-runs.js +69 -8
  137. package/lib/types/extraction-runs.js.map +1 -1
  138. package/lib/types/fs-atomic.d.ts +0 -7
  139. package/lib/types/fs-atomic.d.ts.map +1 -1
  140. package/lib/types/fs-atomic.js +17 -2
  141. package/lib/types/fs-atomic.js.map +1 -1
  142. package/lib/types/images.d.ts +26 -0
  143. package/lib/types/images.d.ts.map +1 -0
  144. package/lib/types/images.js +196 -0
  145. package/lib/types/images.js.map +1 -0
  146. package/lib/types/index.d.ts +2 -2
  147. package/lib/types/index.d.ts.map +1 -1
  148. package/lib/types/index.js +598 -209
  149. package/lib/types/index.js.map +1 -1
  150. package/lib/types/intent/engine.d.ts +12 -4
  151. package/lib/types/intent/engine.d.ts.map +1 -1
  152. package/lib/types/intent/engine.js +43 -5
  153. package/lib/types/intent/engine.js.map +1 -1
  154. package/lib/types/intent/host.d.ts +5 -8
  155. package/lib/types/intent/host.d.ts.map +1 -1
  156. package/lib/types/intent/host.js +56 -11
  157. package/lib/types/intent/host.js.map +1 -1
  158. package/lib/types/intent/scope.d.ts +25 -0
  159. package/lib/types/intent/scope.d.ts.map +1 -0
  160. package/lib/types/intent/scope.js +116 -0
  161. package/lib/types/intent/scope.js.map +1 -0
  162. package/lib/types/intent/tools.d.ts +24 -20
  163. package/lib/types/intent/tools.d.ts.map +1 -1
  164. package/lib/types/intent/tools.js +65 -23
  165. package/lib/types/intent/tools.js.map +1 -1
  166. package/lib/types/intent/types.d.ts +11 -4
  167. package/lib/types/intent/types.d.ts.map +1 -1
  168. package/lib/types/knowledge-bases.d.ts +11 -5
  169. package/lib/types/knowledge-bases.d.ts.map +1 -1
  170. package/lib/types/knowledge-bases.js +52 -20
  171. package/lib/types/knowledge-bases.js.map +1 -1
  172. package/lib/types/knowledge-contract.d.ts +32 -0
  173. package/lib/types/knowledge-contract.d.ts.map +1 -0
  174. package/lib/types/knowledge-contract.js +116 -0
  175. package/lib/types/knowledge-contract.js.map +1 -0
  176. package/lib/types/knowledge.d.ts +31 -9
  177. package/lib/types/knowledge.d.ts.map +1 -1
  178. package/lib/types/knowledge.js +137 -60
  179. package/lib/types/knowledge.js.map +1 -1
  180. package/lib/types/layout.d.ts +10 -29
  181. package/lib/types/layout.d.ts.map +1 -1
  182. package/lib/types/layout.js +17 -36
  183. package/lib/types/layout.js.map +1 -1
  184. package/lib/types/materialize-snapshot.d.ts +49 -0
  185. package/lib/types/materialize-snapshot.d.ts.map +1 -0
  186. package/lib/types/materialize-snapshot.js +2 -0
  187. package/lib/types/materialize-snapshot.js.map +1 -0
  188. package/lib/types/migrate.d.ts +11 -0
  189. package/lib/types/migrate.d.ts.map +1 -1
  190. package/lib/types/migrate.js +83 -2
  191. package/lib/types/migrate.js.map +1 -1
  192. package/lib/types/model-text.d.ts +58 -1
  193. package/lib/types/model-text.d.ts.map +1 -1
  194. package/lib/types/model-text.js +85 -30
  195. package/lib/types/model-text.js.map +1 -1
  196. package/lib/types/oplog.d.ts.map +1 -1
  197. package/lib/types/oplog.js +7 -0
  198. package/lib/types/oplog.js.map +1 -1
  199. package/lib/types/organize-contract.d.ts +18 -0
  200. package/lib/types/organize-contract.d.ts.map +1 -0
  201. package/lib/types/organize-contract.js +82 -0
  202. package/lib/types/organize-contract.js.map +1 -0
  203. package/lib/types/pipeline/engine.d.ts +66 -0
  204. package/lib/types/pipeline/engine.d.ts.map +1 -0
  205. package/lib/types/pipeline/engine.js +352 -0
  206. package/lib/types/pipeline/engine.js.map +1 -0
  207. package/lib/types/pipeline/store.d.ts +73 -0
  208. package/lib/types/pipeline/store.d.ts.map +1 -0
  209. package/lib/types/pipeline/store.js +143 -0
  210. package/lib/types/pipeline/store.js.map +1 -0
  211. package/lib/types/pipeline/types.d.ts +102 -0
  212. package/lib/types/pipeline/types.d.ts.map +1 -0
  213. package/lib/types/pipeline/types.js +5 -0
  214. package/lib/types/pipeline/types.js.map +1 -0
  215. package/lib/types/present.d.ts +2 -0
  216. package/lib/types/present.d.ts.map +1 -1
  217. package/lib/types/present.js +9 -4
  218. package/lib/types/present.js.map +1 -1
  219. package/lib/types/preset-ids.d.ts +4 -0
  220. package/lib/types/preset-ids.d.ts.map +1 -0
  221. package/lib/types/preset-ids.js +6 -0
  222. package/lib/types/preset-ids.js.map +1 -0
  223. package/lib/types/query-analysis.d.ts +13 -1
  224. package/lib/types/query-analysis.d.ts.map +1 -1
  225. package/lib/types/query-analysis.js +62 -6
  226. package/lib/types/query-analysis.js.map +1 -1
  227. package/lib/types/recall-rank.d.ts +3 -3
  228. package/lib/types/recall-rank.d.ts.map +1 -1
  229. package/lib/types/recall-rank.js +4 -4
  230. package/lib/types/recall-rank.js.map +1 -1
  231. package/lib/types/retention.d.ts +39 -0
  232. package/lib/types/retention.d.ts.map +1 -0
  233. package/lib/types/retention.js +42 -0
  234. package/lib/types/retention.js.map +1 -0
  235. package/lib/types/retrieval/vector-index.d.ts +32 -0
  236. package/lib/types/retrieval/vector-index.d.ts.map +1 -0
  237. package/lib/types/retrieval/vector-index.js +15 -0
  238. package/lib/types/retrieval/vector-index.js.map +1 -0
  239. package/lib/types/retrieval/visibility.d.ts +6 -0
  240. package/lib/types/retrieval/visibility.d.ts.map +1 -0
  241. package/lib/types/retrieval/visibility.js +11 -0
  242. package/lib/types/retrieval/visibility.js.map +1 -0
  243. package/lib/types/runtime.d.ts +272 -27
  244. package/lib/types/runtime.d.ts.map +1 -1
  245. package/lib/types/runtime.js +2751 -537
  246. package/lib/types/runtime.js.map +1 -1
  247. package/lib/types/settings-schema.d.ts +17 -15
  248. package/lib/types/settings-schema.d.ts.map +1 -1
  249. package/lib/types/settings-schema.js +50 -47
  250. package/lib/types/settings-schema.js.map +1 -1
  251. package/lib/types/settings-volatile.d.ts +4 -4
  252. package/lib/types/settings-volatile.js +4 -4
  253. package/lib/types/source-evidence.d.ts +14 -0
  254. package/lib/types/source-evidence.d.ts.map +1 -0
  255. package/lib/types/source-evidence.js +36 -0
  256. package/lib/types/source-evidence.js.map +1 -0
  257. package/lib/types/store/axis-references.d.ts +5 -0
  258. package/lib/types/store/axis-references.d.ts.map +1 -0
  259. package/lib/types/store/axis-references.js +106 -0
  260. package/lib/types/store/axis-references.js.map +1 -0
  261. package/lib/types/store/derived.d.ts +12 -1
  262. package/lib/types/store/derived.d.ts.map +1 -1
  263. package/lib/types/store/derived.js +71 -12
  264. package/lib/types/store/derived.js.map +1 -1
  265. package/lib/types/store/knowledge-db.d.ts +31 -1
  266. package/lib/types/store/knowledge-db.d.ts.map +1 -1
  267. package/lib/types/store/knowledge-db.js +252 -18
  268. package/lib/types/store/knowledge-db.js.map +1 -1
  269. package/lib/types/store/migrate.d.ts.map +1 -1
  270. package/lib/types/store/migrate.js +17 -6
  271. package/lib/types/store/migrate.js.map +1 -1
  272. package/lib/types/trajectory-types.d.ts +172 -0
  273. package/lib/types/trajectory-types.d.ts.map +1 -0
  274. package/lib/types/trajectory-types.js +36 -0
  275. package/lib/types/trajectory-types.js.map +1 -0
  276. package/lib/types/types.d.ts +59 -27
  277. package/lib/types/types.d.ts.map +1 -1
  278. package/lib/types/types.js +6 -15
  279. package/lib/types/types.js.map +1 -1
  280. package/lib/types/wiki-finalize.d.ts +16 -0
  281. package/lib/types/wiki-finalize.d.ts.map +1 -1
  282. package/lib/types/wiki-finalize.js +26 -0
  283. package/lib/types/wiki-finalize.js.map +1 -1
  284. package/lib/types/wiki-materialize.d.ts +4 -0
  285. package/lib/types/wiki-materialize.d.ts.map +1 -1
  286. package/lib/types/wiki-materialize.js +21 -7
  287. package/lib/types/wiki-materialize.js.map +1 -1
  288. package/lib/types/wiki-trial-types.d.ts +87 -0
  289. package/lib/types/wiki-trial-types.d.ts.map +1 -1
  290. package/lib/types/wiki-trial-types.js +0 -16
  291. package/lib/types/wiki-trial-types.js.map +1 -1
  292. package/lib/types/wiki-trial.d.ts +40 -16
  293. package/lib/types/wiki-trial.d.ts.map +1 -1
  294. package/lib/types/wiki-trial.js +337 -224
  295. package/lib/types/wiki-trial.js.map +1 -1
  296. package/package.json +29 -20
  297. package/python/prepare-models.py +19 -0
  298. package/python/requirements.txt +8 -6
  299. package/scripts/doctor.mjs +13 -19
  300. package/scripts/environment.mjs +29 -0
  301. package/scripts/setup-embedding.sh +15 -5
  302. package/src/agent-behavior-rules.ts +37 -0
  303. package/src/axis-registry.ts +234 -27
  304. package/src/card-organize.ts +69 -75
  305. package/src/client/AgentBehaviorRulesCard.tsx +65 -0
  306. package/src/client/AttributionEventGuide.tsx +41 -39
  307. package/src/client/AxisRegistrySection.tsx +204 -164
  308. package/src/client/CompileDialogs.tsx +44 -29
  309. package/src/client/DeleteDocumentDialog.tsx +36 -5
  310. package/src/client/DirectoryPicker.tsx +0 -10
  311. package/src/client/EnvironmentSetup.tsx +243 -0
  312. package/src/client/ExpansionGraph.tsx +13 -7
  313. package/src/client/ExtractionTasksPage.tsx +578 -0
  314. package/src/client/GuideArchitectureCanvas.tsx +470 -0
  315. package/src/client/ImportFilesDialog.tsx +2 -13
  316. package/src/client/IntentLogic.tsx +2 -2
  317. package/src/client/IntentTab.tsx +118 -47
  318. package/src/client/KnowledgeBaseTab.tsx +277 -197
  319. package/src/client/KnowledgeLayerSection.tsx +24 -6
  320. package/src/client/KnowledgePanel.tsx +58 -93
  321. package/src/client/KnowledgeSettingsDrawer.tsx +90 -0
  322. package/src/client/ListPager.tsx +15 -5
  323. package/src/client/MaterializeTrajectoryView.tsx +124 -0
  324. package/src/client/NodeSettings.tsx +210 -89
  325. package/src/client/NormalizeTrajectoryView.tsx +136 -0
  326. package/src/client/PipelineNotice.tsx +26 -0
  327. package/src/client/PreviewSections.tsx +118 -51
  328. package/src/client/RecallPanel.tsx +89 -85
  329. package/src/client/TabGuide.tsx +159 -184
  330. package/src/client/TrialReportView.tsx +391 -214
  331. package/src/client/TypeDefinitionDrawer.tsx +150 -23
  332. package/src/client/WikiCardPreview.tsx +62 -16
  333. package/src/client/WikiFlowPanel.tsx +4 -4
  334. package/src/client/arch/NodeLogicPanel.tsx +3 -4
  335. package/src/client/arch/model.ts +6 -9
  336. package/src/client/architecture.tsx +23 -33
  337. package/src/client/attribution/AttributionGraph.tsx +10 -6
  338. package/src/client/attribution/AttributionTab.tsx +136 -84
  339. package/src/client/attribution/CaseView.tsx +3 -1
  340. package/src/client/attribution/EventView.tsx +108 -0
  341. package/src/client/attribution/RunView.tsx +2 -2
  342. package/src/client/attribution/StageChrome.tsx +34 -3
  343. package/src/client/attribution/ViewSwitch.tsx +20 -5
  344. package/src/client/attribution/graph-options.ts +47 -39
  345. package/src/client/attribution/model.ts +17 -10
  346. package/src/client/config-scope.ts +3 -3
  347. package/src/client/graph/palette.ts +165 -0
  348. package/src/client/index.ts +49 -42
  349. package/src/client/pages.css +459 -135
  350. package/src/client/pages.tsx +37 -9
  351. package/src/client/problem-domains.ts +1 -1
  352. package/src/client/session-remote.ts +9 -0
  353. package/src/client/styles.css +205 -62
  354. package/src/client/wiki-trial.ts +44 -3
  355. package/src/compiler/embedding-identity.ts +21 -0
  356. package/src/compiler/snapshot.ts +17 -0
  357. package/src/config-schema.ts +8 -3
  358. package/src/convert/host.ts +56 -21
  359. package/src/convert/ingest.ts +74 -10
  360. package/src/derive-contract.ts +14 -0
  361. package/src/diagnosis/cards.ts +13 -8
  362. package/src/diagnosis/run.ts +27 -17
  363. package/src/diagnosis/schema.ts +2 -2
  364. package/src/diagnosis/seed-source.ts +5 -4
  365. package/src/diagnosis/seed.ts +6 -8
  366. package/src/diagnosis/store.ts +138 -69
  367. package/src/diagnosis/types.ts +34 -15
  368. package/src/environment/dsh-python.ts +156 -0
  369. package/src/environment/install.ts +244 -0
  370. package/src/environment/manifest.ts +28 -0
  371. package/src/environment/model-catalog.ts +147 -0
  372. package/src/environment/process.ts +54 -0
  373. package/src/environment/selection.ts +29 -0
  374. package/src/environment/service.ts +348 -0
  375. package/src/environment/types.ts +45 -0
  376. package/src/events.ts +108 -0
  377. package/src/extract-contract.ts +42 -0
  378. package/src/extract-model.ts +10 -1
  379. package/src/extract-table-contract.ts +26 -0
  380. package/src/extract-table.ts +132 -0
  381. package/src/extraction-runs.ts +70 -11
  382. package/src/fs-atomic.ts +19 -2
  383. package/src/images.ts +203 -0
  384. package/src/index.ts +553 -205
  385. package/src/intent/README.md +8 -6
  386. package/src/intent/engine.ts +44 -6
  387. package/src/intent/host.ts +59 -18
  388. package/src/intent/scope.ts +125 -0
  389. package/src/intent/tools.ts +70 -28
  390. package/src/intent/types.ts +11 -4
  391. package/src/knowledge-bases.ts +56 -20
  392. package/src/knowledge-contract.ts +114 -0
  393. package/src/knowledge.ts +138 -69
  394. package/src/layout.ts +17 -37
  395. package/src/materialize-snapshot.ts +46 -0
  396. package/src/migrate.ts +75 -2
  397. package/src/model-text.ts +109 -4
  398. package/src/oplog.ts +7 -0
  399. package/src/organize-contract.ts +83 -0
  400. package/src/pipeline/engine.ts +323 -0
  401. package/src/pipeline/store.ts +147 -0
  402. package/src/pipeline/types.ts +93 -0
  403. package/src/present.ts +10 -4
  404. package/src/preset-ids.ts +6 -0
  405. package/src/python/embedding_worker.py +66 -2
  406. package/src/query-analysis.ts +68 -8
  407. package/src/recall-rank.ts +5 -5
  408. package/src/retention.ts +76 -0
  409. package/src/retrieval/vector-index.ts +45 -0
  410. package/src/retrieval/visibility.ts +14 -0
  411. package/src/runtime.ts +2708 -567
  412. package/src/settings-schema.ts +11 -8
  413. package/src/settings-volatile.ts +4 -4
  414. package/src/source-evidence.ts +37 -0
  415. package/src/store/axis-references.ts +96 -0
  416. package/src/store/derived.ts +70 -12
  417. package/src/store/knowledge-db.ts +248 -17
  418. package/src/store/migrate.ts +16 -6
  419. package/src/trajectory-types.ts +142 -0
  420. package/src/types.ts +61 -35
  421. package/src/wiki-finalize.ts +28 -0
  422. package/src/wiki-materialize.ts +25 -6
  423. package/src/wiki-trial-types.ts +83 -1
  424. package/src/wiki-trial.ts +357 -185
  425. package/lib/types/intent/preset-tools.d.ts +0 -37
  426. package/lib/types/intent/preset-tools.d.ts.map +0 -1
  427. package/lib/types/intent/preset-tools.js +0 -45
  428. package/lib/types/intent/preset-tools.js.map +0 -1
  429. package/preset/tita-data-agent/agent.cordis.yml +0 -394
  430. package/preset/tita-data-agent/preset.yml +0 -3
  431. package/scripts/install-agent-preset.mjs +0 -92
  432. package/scripts/sync-agent-preset.mjs +0 -188
  433. package/src/client/AgentPresetCard.tsx +0 -247
  434. package/src/client/agent-preset.ts +0 -121
  435. package/src/client/convert/ConvertPanel.tsx +0 -583
  436. package/src/client/convert/styles.css +0 -138
  437. package/src/client/convert/styles.ts +0 -49
  438. package/src/intent/preset-tools.ts +0 -48
@@ -49,6 +49,8 @@ export interface CompileProgressView {
49
49
  * 那里才同时看得到两种类型。
50
50
  */
51
51
  runId: string
52
+ state?: 'queued' | 'running' | 'pausing' | 'paused' | 'cancelling' | 'succeeded' | 'failed' | 'cancelled'
53
+ queuedAt?: string
52
54
  only: string
53
55
  startedAt: string
54
56
  finishedAt?: string
@@ -82,6 +84,26 @@ export const COMPILE_STEP_TITLE: Record<string, string> = {
82
84
  build: '构建(向量 + 图谱)',
83
85
  }
84
86
 
87
+ /** 编译弹窗与任务页共用同一份步骤展示。 */
88
+ export function CompileStepList({ steps }: { steps: CompileStepView[] }): ReactNode {
89
+ return <ul className={styles.compileSteps}>
90
+ {steps.map((step, index) => <li key={step.id} className={cn(styles.compileStep, step.state === 'done' && styles.compileStepDone)}>
91
+ <span className={cn(styles.compileDot, step.state === 'done' && styles.compileDotDone, step.state === 'running' && styles.compileDotRunning)} aria-hidden="true">
92
+ {step.state === 'done' ? <Check size={12} /> : step.state === 'running' ? <RefreshCw size={11} className={styles.compileSpin} /> : index + 1}
93
+ </span>
94
+ <span className={styles.compileStepBody}>
95
+ <span className={styles.compileStepTitle}>step{index + 1} · {COMPILE_STEP_TITLE[step.id] ?? step.id}</span>
96
+ <span className={styles.compileFacts}>
97
+ {step.facts.map((fact, at) => <span key={at}>{fact}</span>)}
98
+ </span>
99
+ </span>
100
+ <span className={styles.compileState}>
101
+ {step.state === 'done' ? '已完成' : step.state === 'running' ? '进行中' : '待执行'}
102
+ </span>
103
+ </li>)}
104
+ </ul>
105
+ }
106
+
85
107
  /** `00:42` / `01:12`。超过一小时也只是多两位,不做「1 小时 2 分」。 */
86
108
  function elapsed(from: string, to: number): string {
87
109
  const ms = to - new Date(from).getTime()
@@ -99,8 +121,16 @@ function elapsed(from: string, to: number): string {
99
121
  * 条形只是让人一眼看出「大概到哪了」,精确的账在文字里。没有这一行文字,那条按阶段均分
100
122
  * 的进度条就会被当成精确值,而在「抽取」这一段特别慢的库里它会显得长期不动。
101
123
  */
102
- function overallRatio(progress: CompileProgressView): number {
103
- if (progress.finishedAt !== undefined) return 1
124
+ /**
125
+ * 编译进度 → 0..1 的比例。**这是唯一一份**(0070)。
126
+ *
127
+ * 曾经有两个副本,而它们对「已结束」的处理不一致:一个只要 `finishedAt` 存在就返回
128
+ * 满格(把 failed / cancelled 也画成「完成」),另一个排除了这两种状态。同一个失败在
129
+ * 导入对话框里是满格主色、在编译对话框里是红色未完成 —— 两屏说两件事。
130
+ * 所以导出它,让两个消费者用同一份判断。
131
+ */
132
+ export function compileRatio(progress: CompileProgressView): number {
133
+ if (progress.finishedAt !== undefined && progress.state !== 'cancelled' && progress.state !== 'failed') return 1
104
134
  const total = progress.steps.length || 1
105
135
  const done = progress.steps.filter(step => step.state === 'done').length
106
136
  const running = progress.steps.find(step => step.state === 'running')
@@ -134,7 +164,7 @@ export function CompileProgressDialog({ open, onOpenChange, progress, mine, queu
134
164
  * 不是「从这个框出现开始算」。跑完之后停表,不再继续跳。
135
165
  */
136
166
  const [now, setNow] = useState(() => Date.now())
137
- const running = progress !== null && progress.finishedAt === undefined
167
+ const running = progress !== null && progress.finishedAt === undefined && progress.state !== 'paused'
138
168
  useEffect(() => {
139
169
  if (!open || !running) return undefined
140
170
  const timer = window.setInterval(() => setNow(Date.now()), 1000)
@@ -143,7 +173,10 @@ export function CompileProgressDialog({ open, onOpenChange, progress, mine, queu
143
173
 
144
174
  if (!open) return null
145
175
  const done = progress?.finishedAt !== undefined
146
- const ratio = progress === null ? 0 : overallRatio(progress)
176
+ const completed = done && progress?.state !== 'cancelled' && progress?.state !== 'failed'
177
+ const stopped = progress?.state === 'cancelled'
178
+ const failed = progress?.state === 'failed'
179
+ const ratio = progress === null ? 0 : compileRatio(progress)
147
180
  const doneSteps = progress?.steps.filter(step => step.state === 'done').length ?? 0
148
181
  const finishedText = progress?.outcome
149
182
  ?? (progress === null ? (queued === true ? '排在前面那一次编译之后,轮到它就会开始。' : '正在建立编译任务…') : '编译结束。')
@@ -152,7 +185,7 @@ export function CompileProgressDialog({ open, onOpenChange, progress, mine, queu
152
185
  <DialogContent className={styles.compileDialog}>
153
186
  <DialogHeader>
154
187
  <div className={styles.compileHead}>
155
- <DialogTitle>{done ? '编译完成' : '全量重新编译'}</DialogTitle>
188
+ <DialogTitle>{stopped ? '任务已停止' : failed ? '编译失败' : done ? '编译完成' : '全量重新编译'}</DialogTitle>
156
189
  {/* 钟与控制点同一行:用时是这一屏唯一的「长了多久」,它不该另占一行。 */}
157
190
  <span className={styles.compileClock}>
158
191
  <Clock3 size={13} aria-hidden="true" />
@@ -169,38 +202,20 @@ export function CompileProgressDialog({ open, onOpenChange, progress, mine, queu
169
202
 
170
203
  <div className={styles.compileBar} role="progressbar" aria-valuemin={0} aria-valuemax={100}
171
204
  aria-valuenow={Math.round(ratio * 100)} aria-label="编译总进度">
172
- <span style={{ inlineSize: `${Math.round(ratio * 100)}%` }} className={done ? styles.compileBarDone : undefined} />
205
+ <span style={{ inlineSize: `${Math.round(ratio * 100)}%` }} className={completed ? styles.compileBarDone : undefined} />
173
206
  </div>
174
207
  <p className={styles.compileRatio}>
175
208
  已完成 {doneSteps} / {progress?.steps.length ?? 5} 段
176
209
  {progress !== null && progress.sourcesTotal > 0 && !done && <> · 读取文档 {progress.sourcesDone}/{progress.sourcesTotal}</>}
177
210
  </p>
178
211
 
179
- <ul className={styles.compileSteps}>
180
- {(progress?.steps ?? []).map((step, index) => <li key={step.id} className={cn(styles.compileStep, step.state === 'done' && styles.compileStepDone)}>
181
- <span className={cn(styles.compileDot, step.state === 'done' && styles.compileDotDone, step.state === 'running' && styles.compileDotRunning)} aria-hidden="true">
182
- {step.state === 'done' ? <Check size={12} /> : step.state === 'running' ? <RefreshCw size={11} className={styles.compileSpin} /> : index + 1}
183
- </span>
184
- <span className={styles.compileStepBody}>
185
- <span className={styles.compileStepTitle}>
186
- step{index + 1} · {COMPILE_STEP_TITLE[step.id] ?? step.id}
187
- </span>
188
- {/* 子事实一行一条:它们回答的是「这一段现在是多少」,是这一步唯一的账。
189
- 逐条显示而不是连成一句 —— 连成一句之后,窄栏下会被截断,而截断的正好是末尾
190
- 那个最该看的数。 */}
191
- <span className={styles.compileFacts}>
192
- {step.facts.map((fact, at) => <span key={at}>{fact}</span>)}
193
- </span>
194
- </span>
195
- <span className={styles.compileState}>
196
- {step.state === 'done' ? '已完成' : step.state === 'running' ? '进行中' : '待执行'}
197
- </span>
198
- </li>)}
199
- {progress === null && <li className={styles.compileStep}>
212
+ <CompileStepList steps={progress?.steps ?? []} />
213
+ {progress === null && <ul className={styles.compileSteps}>
214
+ <li className={styles.compileStep}>
200
215
  <span className={cn(styles.compileDot, styles.compileDotRunning)} aria-hidden="true"><RefreshCw size={11} className={styles.compileSpin} /></span>
201
216
  <span className={styles.compileStepBody}><span className={styles.compileStepTitle}>正在建立编译任务…</span></span>
202
- </li>}
203
- </ul>
217
+ </li>
218
+ </ul>}
204
219
 
205
220
  {done && <p className={cn(styles.compileOutcome, progress?.failed === true && styles.compileOutcomeBad)}>
206
221
  {progress?.failed === true ? '编译失败:' : ''}{finishedText}
@@ -31,7 +31,7 @@
31
31
  */
32
32
 
33
33
  import type { ReactNode } from 'react'
34
- import { FileText, Layers3, LoaderCircle, Quote, TriangleAlert, Trash2 } from '@tita-agent/ui/icons'
34
+ import { CircleDot, FileText, Layers3, LoaderCircle, Quote, TriangleAlert, Trash2 } from '@tita-agent/ui/icons'
35
35
  import { Button } from '@tita-agent/ui/components'
36
36
  import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@tita-agent/ui/overlays'
37
37
  import type { DocumentDeleteImpact } from './wiki-trial.ts'
@@ -86,8 +86,10 @@ export function DeleteDocumentDialog({
86
86
  const knowledgeKept = impact?.knowledge.items.filter(item => !item.exclusive).slice(0, ITEM_CAP) ?? []
87
87
  const cardsDoomed = impact?.cards.items.filter(item => item.exclusive).slice(0, ITEM_CAP) ?? []
88
88
  const cardsKept = impact?.cards.items.filter(item => !item.exclusive).slice(0, ITEM_CAP) ?? []
89
+ const eventsDoomed = impact?.events.items.filter(item => item.exclusive).slice(0, ITEM_CAP) ?? []
90
+ const eventsKept = impact?.events.items.filter(item => !item.exclusive).slice(0, ITEM_CAP) ?? []
89
91
  const nothing = impact !== null
90
- && impact.knowledge.total === 0 && impact.cards.total === 0 && impact.extractionRuns === 0
92
+ && impact.knowledge.total === 0 && impact.cards.total === 0 && impact.events.total === 0 && impact.extractionRuns === 0
91
93
 
92
94
  return <Dialog open={open} onOpenChange={onOpenChange}>
93
95
  <DialogContent className={styles.delDialog}>
@@ -109,15 +111,15 @@ export function DeleteDocumentDialog({
109
111
  <TriangleAlert size={14} aria-hidden="true" />
110
112
  <div className={styles.delWarningBody}>
111
113
  <b>这项操作不可撤销</b>
112
- <span>将删除原始文档,以及只依赖它的知识和 WikiCard。</span>
113
- <small>重新编译也无法恢复已经删除的知识或卡片。</small>
114
+ <span>将删除原始文档,以及只依赖它的 Knowledge、Event 和 WikiCard。</span>
115
+ <small>重新编译也无法恢复已经删除的 Knowledge 或 Event。</small>
114
116
  </div>
115
117
  </div>
116
118
 
117
119
  <div className={styles.delScroll}>
118
120
  {nothing
119
121
  ? <p className={styles.delNothing}>
120
- 这份文档没有生成知识、WikiCard 或抽取记录。删除后只会移除原始文档。
122
+ 这份文档没有生成 Knowledge、Event、WikiCard 或抽取记录。删除后只会移除原始文档。
121
123
  </p>
122
124
  : <>
123
125
  <section className={styles.delSection}>
@@ -145,6 +147,35 @@ export function DeleteDocumentDialog({
145
147
  </>}
146
148
  </section>
147
149
 
150
+ <section className={styles.delSection}>
151
+ <h4 className={styles.delSectionHead}>
152
+ <span><CircleDot size={12} />Event</span>
153
+ <small className={styles.delSectionTotal}>共 {impact.events.total} 条</small>
154
+ </h4>
155
+ {impact.events.total === 0
156
+ ? <p className={styles.delEmpty}>没有 Event 引用这份文档。</p>
157
+ : <>
158
+ <Tier tone="danger" count={impact.events.exclusive}
159
+ unit="条" label="只由这份文档支撑" description="文档删除后 Event 一并删除"
160
+ items={<ul className={styles.delItems}>
161
+ {eventsDoomed.map(event => <li key={event.id}>
162
+ {event.title}<span className={styles.delItemMeta}>{event.occurredAt ?? event.id}</span>
163
+ </li>)}
164
+ {impact.events.exclusive > eventsDoomed.length
165
+ && <li className={styles.delMore}>另有 {impact.events.exclusive - eventsDoomed.length} 条同类。</li>}
166
+ </ul>} />
167
+ <Tier tone="keep" count={impact.events.shared}
168
+ unit="条" label="还有其他来源" description="保留 Event,只移除这份来源记录"
169
+ items={<ul className={styles.delItems}>
170
+ {eventsKept.map(event => <li key={event.id}>
171
+ {event.title}<span className={styles.delItemMeta}>{event.occurredAt ?? event.id}</span>
172
+ </li>)}
173
+ {impact.events.shared > eventsKept.length
174
+ && <li className={styles.delMore}>另有 {impact.events.shared - eventsKept.length} 条同类。</li>}
175
+ </ul>} />
176
+ </>}
177
+ </section>
178
+
148
179
  <section className={styles.delSection}>
149
180
  <h4 className={styles.delSectionHead}>
150
181
  <span><Layers3 size={12} />WikiCard</span>
@@ -89,16 +89,6 @@ export interface AgentLayoutView {
89
89
  */
90
90
  settingsError?: string
91
91
  pickerKind: string | null
92
- /**
93
- * preset 的**真源目录**(`<包根>/preset/tita-data-agent/`)。
94
- *
95
- * 提示词的唯一真源就在这个目录里的 `agent.cordis.yml`。0.1.7 起 DSH 那边 preset
96
- * 不再是一个目录(它是组合里的一条声明行),所以「打开 preset 目录」打开的是
97
- * 这个随插件分发的真源目录 —— 服务端算好给出来,客户端不拼路径。
98
- */
99
- presetDir?: string
100
- /** 真源目录在不在。不在时界面如实说,而不是给一个弹空目录的按钮。 */
101
- presetDirExists?: boolean
102
92
  }
103
93
 
104
94
  interface MigrationView {
@@ -0,0 +1,243 @@
1
+ import { useCallback, useEffect, useRef, useState, type ReactNode } from 'react'
2
+ import { Button, cn, Select, SelectContent, SelectItem, SelectLabel, SelectGroup, SelectTrigger, SelectValue } from '@tita-agent/ui/components'
3
+ import { AlertCircle, Check, ChevronDown, Download, LoaderCircle, RefreshCw } from '@tita-agent/ui/icons'
4
+ import { downloadBytes, formatBytes, type ModelSelection, type ModelOptionView } from '../environment/model-catalog.js'
5
+ import type { EnvironmentCurrentModel, EnvironmentView } from '../environment/types.js'
6
+
7
+ async function environmentRequest(init?: RequestInit): Promise<EnvironmentView> {
8
+ const response = await fetch(init?.method ? '/knowledge/environment/prepare' : '/knowledge/environment', { ...init, signal: init?.signal ?? AbortSignal.timeout(20_000) })
9
+ const text = await response.text()
10
+ let payload: { ok?: boolean; data?: EnvironmentView; error?: { message?: string } }
11
+ try { payload = JSON.parse(text) }
12
+ catch { throw new Error(`环境服务未返回有效数据(HTTP ${response.status}),请确认知识插件已加载。`) }
13
+ if (!response.ok || !payload.ok || !payload.data) throw new Error(payload.error?.message ?? `环境服务响应失败(${response.status})`)
14
+ return payload.data
15
+ }
16
+
17
+ export function useKnowledgeEnvironment(visible: boolean, revision: number) {
18
+ const [view, setView] = useState<EnvironmentView>()
19
+ const [error, setError] = useState<string>()
20
+ const [submitting, setSubmitting] = useState(false)
21
+ const sequence = useRef(0)
22
+ const mounted = useRef(true)
23
+ const mutation = useRef(false)
24
+ const reading = useRef(false)
25
+ useEffect(() => { mounted.current = true; return () => { mounted.current = false; sequence.current++ } }, [])
26
+ const refresh = useCallback(async (): Promise<void> => {
27
+ if (mutation.current || reading.current) return
28
+ reading.current = true
29
+ const ticket = ++sequence.current
30
+ try {
31
+ const next = await environmentRequest()
32
+ if (mounted.current && ticket === sequence.current) { setView(next); setError(undefined) }
33
+ } catch (cause) {
34
+ if (mounted.current && ticket === sequence.current) setError(cause instanceof Error ? cause.message : String(cause))
35
+ } finally { reading.current = false }
36
+ }, [])
37
+ const busy = submitting || view?.job?.state === 'running' || view?.report.state === 'checking'
38
+ useEffect(() => {
39
+ if (!visible) return
40
+ void refresh()
41
+ const onFocus = (): void => { void refresh() }
42
+ window.addEventListener('focus', onFocus)
43
+ const timer = busy ? setInterval(() => { void refresh() }, 1500) : undefined
44
+ return () => { if (timer) clearInterval(timer); window.removeEventListener('focus', onFocus) }
45
+ }, [visible, revision, busy, refresh])
46
+ const prepare = useCallback(async (action: 'install' | 'check' | 'cancel', selection?: ModelSelection): Promise<void> => {
47
+ if (mutation.current) return
48
+ mutation.current = true
49
+ const ticket = ++sequence.current
50
+ setSubmitting(true)
51
+ try {
52
+ const next = await environmentRequest({ method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action, ...(selection ? { selection } : {}) }) })
53
+ if (mounted.current && ticket === sequence.current) { setView(next); setError(undefined) }
54
+ } catch (cause) {
55
+ if (mounted.current && ticket === sequence.current) setError(cause instanceof Error ? cause.message : String(cause))
56
+ } finally {
57
+ mutation.current = false
58
+ if (mounted.current) setSubmitting(false)
59
+ }
60
+ }, [])
61
+ return { view, error, busy, prepare, refresh }
62
+ }
63
+
64
+ export type EnvironmentController = ReturnType<typeof useKnowledgeEnvironment>
65
+
66
+ function ModelSelect({ id, label, value, options, currentModel, disabled, onChange }: {
67
+ id: string
68
+ label: string
69
+ value: string
70
+ options: ModelOptionView[]
71
+ currentModel: EnvironmentCurrentModel
72
+ disabled: boolean
73
+ onChange: (value: string) => void
74
+ }): ReactNode {
75
+ const chosen = options.find(option => option.id === value)
76
+ return <div className="grid min-w-0 gap-1.5">
77
+ <label htmlFor={id} className="text-xs font-medium text-tita-ink">{label}</label>
78
+ <Select value={value} onValueChange={onChange} disabled={disabled}>
79
+ <SelectTrigger id={id} className="w-full"><SelectValue>{chosen?.label ?? '请选择模型'}</SelectValue></SelectTrigger>
80
+ <SelectContent position="popper" align="start" className="max-h-64">
81
+ <SelectGroup>
82
+ {!currentModel.id && <>
83
+ <SelectLabel>当前运行</SelectLabel>
84
+ <SelectItem value={`${id}-current`} disabled className="h-auto items-start py-1.5">
85
+ {currentModel.state === 'active' ? `当前使用:${currentModel.label}` : '当前未启用'}
86
+ </SelectItem>
87
+ </>}
88
+ <SelectLabel>模型选项 · 按资源占用从低到高</SelectLabel>
89
+ {options.map(option => <SelectItem key={option.id} value={option.id} className="h-auto items-start py-2">
90
+ <span className="flex min-w-0 flex-1 flex-col gap-0.5">
91
+ <span className="flex min-w-0 items-center gap-2">
92
+ <span className="min-w-0 flex-1 truncate font-medium">{option.label}</span>
93
+ {/* 下载状态:不知道就不标(服务端没给资源目录时 `installed` 是 undefined)。 */}
94
+ {option.installed === true && <span className="shrink-0 rounded-md border border-tita-tone-green-line bg-tita-tone-green-tint px-1.5 py-0.5 text-[10px] font-medium leading-none text-tita-tone-green">已下载</span>}
95
+ {option.installed === false && <span className="shrink-0 rounded-md border border-tita-line bg-tita-surface-muted px-1.5 py-0.5 text-[10px] font-medium leading-none text-tita-ink-muted">需下载</span>}
96
+ {option.id === currentModel.id && <span className="shrink-0 rounded-md border border-tita-line bg-tita-surface-muted px-1.5 py-0.5 text-[10px] font-medium leading-none text-tita-ink">当前使用</span>}
97
+ </span>
98
+ <span className="line-clamp-2 text-[11px] leading-snug text-tita-ink-muted">
99
+ {option.download}{option.dimension ? ` · ${option.dimension} 维` : ''} · {option.description}
100
+ </span>
101
+ </span>
102
+ </SelectItem>)}
103
+ </SelectGroup>
104
+ </SelectContent>
105
+ </Select>
106
+ {chosen?.modelCardUrl && <a href={chosen.modelCardUrl} target="_blank" rel="noreferrer" className="w-fit text-xs text-tita-ink underline underline-offset-2">查看模型卡与许可</a>}
107
+ </div>
108
+ }
109
+
110
+ /**
111
+ * 这次点「安装」会下多少。
112
+ *
113
+ * 模型列表里每个选项自己标了「已下载 / 需下载」,但人真正要判断的是**这一次的总量**:
114
+ * 两个模型都可能已下载(那就只是补依赖 + 自检),也可能只差一个。所以把所选的两个加起来,
115
+ * 已下载的不重复计 —— 已下载的模型不会重新下载(HF 缓存 + 目标目录都在)。
116
+ */
117
+ function DownloadSummary({ embedding, rerank, chosen }: { embedding: ModelOptionView[]; rerank: ModelOptionView[]; chosen: ModelSelection }): ReactNode {
118
+ const pick = (options: ModelOptionView[], id: string): ModelOptionView | undefined => options.find(option => option.id === id)
119
+ const pending = [pick(embedding, chosen.embedding), pick(rerank, chosen.rerank)]
120
+ .filter((option): option is ModelOptionView => option !== undefined && option.installed === false)
121
+ if (pending.length === 0) {
122
+ return <p className="m-0 text-xs leading-relaxed text-tita-ink-muted" role="status">
123
+ {pick(embedding, chosen.embedding)?.installed === true && pick(rerank, chosen.rerank)?.installed === true
124
+ ? '所选模型都已下载,安装只需补齐推理依赖并重新自检。'
125
+ : '无法读取模型下载状态,安装会按需要补齐。'}
126
+ </p>
127
+ }
128
+ const bytes = pending.reduce((sum, option) => sum + (downloadBytes(option.download) ?? 0), 0)
129
+ // 两个以上才报合计:一个模型时合计与它自己那句是同一个数,纯重复。
130
+ const total = pending.length > 1 && bytes > 0 ? `,合计${formatBytes(bytes)}` : ''
131
+ return <p className="m-0 text-xs leading-relaxed text-tita-ink" role="status">
132
+ 本次需下载{pending.map(option => `${option.label}(${option.download})`).join('、')}{total};已下载的不会重下。
133
+ </p>
134
+ }
135
+
136
+ export function EnvironmentNotice({ controller, onOpen }: { controller: EnvironmentController; onOpen: () => void }): ReactNode {
137
+ const { view, error, busy } = controller
138
+ if (!error && (!view || view.report.state === 'ready')) return null
139
+ const items = view?.report.items ?? []
140
+ const failed = items.some(item => item.state === 'failed')
141
+ const missing = items.some(item => item.state === 'missing')
142
+ const previouslyChecked = Boolean(view?.report.checkedAt)
143
+ const message = error ? '环境状态读取失败'
144
+ : busy ? view?.job?.stage ?? '正在检查运行环境'
145
+ : failed ? '模型推理自检未通过,请查看原因并修复'
146
+ : missing ? '请准备或启用向量与重排模型,再运行自检'
147
+ : previouslyChecked ? '模型配置或资源已变化,请重新自检' : '首次使用前,请准备并自检向量与重排模型'
148
+ return <div className="mx-3 mt-2 flex shrink-0 items-center gap-2 border-b border-tita-line pb-2 text-xs text-tita-ink" role="status">
149
+ {busy ? <LoaderCircle size={14} className="tita-spin shrink-0" /> : <AlertCircle size={14} className="shrink-0 text-tita-warning" />}
150
+ <span className="min-w-0 flex-1">{message}</span>
151
+ <Button variant="outline" size="sm" onClick={onOpen}>环境准备</Button>
152
+ </div>
153
+ }
154
+
155
+ export function EnvironmentSetup({ controller }: { controller: EnvironmentController }): ReactNode {
156
+ const { view, error, busy, prepare, refresh } = controller
157
+ const [details, setDetails] = useState(false)
158
+ const [selection, setSelection] = useState<ModelSelection>()
159
+ useEffect(() => {
160
+ if (view) setSelection(view.selection)
161
+ }, [view?.selection.embedding, view?.selection.rerank])
162
+ const ready = view?.report.state === 'ready'
163
+ const job = view?.job
164
+ const running = job?.state === 'running'
165
+ const failure = job?.state === 'failed' ? job.error : undefined
166
+ const chosen = selection ?? view?.selection
167
+ /** 已下载、但当前选择没用到的那些:只报出来,不替人删。 */
168
+ const unusedModels = view ? [
169
+ ...view.models.embedding.filter(option => option.installed === true && option.id !== view.selection.embedding),
170
+ ...view.models.rerank.filter(option => option.installed === true && option.id !== view.selection.rerank),
171
+ ] : []
172
+ const selectionChanged = Boolean(chosen && view && (chosen.embedding !== view.selection.embedding || chosen.rerank !== view.selection.rerank))
173
+ const checks = view?.report.items ?? []
174
+ const issues = checks.filter(item => item.state !== 'ready')
175
+ const checkItems = (items: typeof checks): ReactNode => <ul className="m-0 grid list-none gap-3 p-0" aria-label="运行环境检查项">
176
+ {items.map(item => <li key={item.id} className="flex min-w-0 items-start gap-2">
177
+ {item.state === 'ready' ? <Check size={14} className="mt-0.5 shrink-0 text-tita-success" /> : item.state === 'checking'
178
+ ? <LoaderCircle size={14} className="tita-spin mt-0.5 shrink-0" /> : <AlertCircle size={14} className="mt-0.5 shrink-0 text-tita-warning" />}
179
+ <div className="min-w-0 flex-1 text-xs leading-relaxed">
180
+ <span className="font-medium text-tita-ink">{item.label}</span>
181
+ <p className="m-0 break-words text-tita-ink-muted">{item.message}</p>
182
+ {item.recovery && <p className="m-0 break-words text-tita-ink">{item.recovery}</p>}
183
+ </div>
184
+ </li>)}
185
+ </ul>
186
+
187
+ return <section id="tita-environment" tabIndex={-1} aria-labelledby="tita-environment-title" className="tita-settingsSection">
188
+ <div className="tita-settingsSectionHeader">
189
+ <h3 id="tita-environment-title">本地运行环境</h3>
190
+ <span className={cn('shrink-0 text-xs', ready && !error ? 'text-tita-success' : 'text-tita-ink-muted')} role="status" aria-live="polite">
191
+ {error ? '读取失败' : busy ? '进行中' : ready ? '已就绪' : view ? '待准备' : '读取中'}
192
+ </span>
193
+ </div>
194
+ <p className="mb-4 mt-0 text-xs leading-relaxed text-tita-ink-muted">选择向量与重排模型,安装后自动自检并启用。首次安装需要联网下载模型和推理依赖。</p>
195
+ {view?.capabilities && <ul className="mb-4 grid list-none gap-1 p-0 text-xs" aria-label="功能可用状态">
196
+ {view.capabilities.map(capability => <li key={capability.id} className="flex flex-wrap gap-x-2 gap-y-1">
197
+ <span className={capability.ready ? 'text-tita-success' : 'text-tita-warning'}>{capability.label} · {capability.ready ? '可用' : '待准备'}</span>
198
+ <span className="text-tita-ink-muted">{capability.message}</span>
199
+ </li>)}
200
+ </ul>}
201
+ {!ready && issues.length > 0 && <div className="mb-4">{checkItems(issues)}</div>}
202
+ {view && chosen && <div className="grid gap-4" aria-label="模型选择">
203
+ <ModelSelect id="tita-embedding-model" label="向量模型" value={chosen.embedding} currentModel={view.current.embedding} options={view.models.embedding} disabled={busy}
204
+ onChange={value => setSelection(current => ({ ...(current ?? view.selection), embedding: value as ModelSelection['embedding'] }))} />
205
+ <ModelSelect id="tita-rerank-model" label="重排模型" value={chosen.rerank} currentModel={view.current.rerank} options={view.models.rerank} disabled={busy}
206
+ onChange={value => setSelection(current => ({ ...(current ?? view.selection), rerank: value as ModelSelection['rerank'] }))} />
207
+ <DownloadSummary embedding={view.models.embedding} rerank={view.models.rerank} chosen={chosen} />
208
+ {(selectionChanged || Boolean(view && (!view.current.embedding.id || !view.current.rerank.id))) && <p className="m-0 text-xs leading-relaxed text-tita-warning" role="status">
209
+ 安装将启用所选本地模型,并替换高级模型设置中的自定义路径。自检失败会恢复原设置。更改向量模型后,请构建检索索引。
210
+ </p>}
211
+ </div>}
212
+ {!view && !error && <p className="text-xs text-tita-ink-muted" role="status">正在读取环境状态…</p>}
213
+ {running && <p className="my-3 text-xs text-tita-ink" role="status" aria-live="polite">{job.stage}。你可以离开此面板,任务会继续。</p>}
214
+ {error && <div className="my-3 flex flex-wrap items-start gap-2 text-xs leading-relaxed text-tita-danger" role="alert">
215
+ <span className="min-w-0 flex-1 break-words">{error}</span>
216
+ <Button variant="outline" size="sm" onClick={() => { void refresh() }}>重新读取</Button>
217
+ </div>}
218
+ {failure && <p className="my-3 break-words text-xs text-tita-danger" role="alert">{failure}</p>}
219
+ {job?.state === 'cancelled' && <p className="my-3 text-xs text-tita-ink-muted" role="status">{job.error}</p>}
220
+ {view && <div className="mt-4 flex flex-wrap gap-2">
221
+ <Button size="sm" variant={ready ? 'outline' : 'default'} disabled={busy || Boolean(error)} onClick={() => { void prepare('install', chosen) }}>
222
+ <Download size={13} />{selectionChanged ? '安装所选模型' : ready ? '修复当前环境' : job?.state === 'failed' || job?.state === 'cancelled' ? '重试准备' : '安装并启用'}
223
+ </Button>
224
+ <Button variant="outline" size="sm" disabled={busy || selectionChanged} onClick={() => { void prepare('check') }}><RefreshCw size={13} />重新自检</Button>
225
+ {running && <Button variant="ghost" size="sm" onClick={() => { void prepare('cancel') }}>停止</Button>}
226
+ </div>}
227
+ {ready && <p className="mb-0 mt-3 text-xs text-tita-ink-muted">向量模型变更后需构建检索索引,文档无需重新抽取。</p>}
228
+ {(view || job) && <>
229
+ <Button variant="ghost" size="sm" className="-ml-2 mt-3" aria-expanded={details} aria-controls="tita-environment-details" onClick={() => setDetails(value => !value)}>
230
+ <ChevronDown size={13} className={details ? 'rotate-180' : ''} />检查详情与日志
231
+ </Button>
232
+ {details && <div id="tita-environment-details" className="mt-3 grid gap-3 text-xs leading-relaxed text-tita-ink-muted">
233
+ {checkItems(checks)}
234
+ {view?.report.checkedAt && <p className="m-0">最近自检:{new Date(view.report.checkedAt).toLocaleString()}</p>}
235
+ {unusedModels.length > 0 && <p className="m-0">
236
+ 已下载但未启用:{unusedModels.map(option => `${option.label}(${option.download})`).join('、')}。它们留在资源目录里,不会被重新下载。
237
+ </p>}
238
+ {checks.map(item => item.path && <p key={item.id} className="m-0 break-all">{item.label}:{item.path}</p>)}
239
+ {job?.logs.length ? <pre className="m-0 max-h-40 overflow-auto whitespace-pre-wrap break-all rounded-tita-control bg-tita-surface-muted p-2 font-mono">{job.logs.join('\n')}</pre> : null}
240
+ </div>}
241
+ </>}
242
+ </section>
243
+ }
@@ -33,6 +33,10 @@ import { ExternalLink } from '@tita-agent/ui/icons'
33
33
  import { layoutGraph, type PlacedGraph, type PlacedNode } from './graph/layout.ts'
34
34
  import { cardKey, expansionGraphData, radiusOf, type ExpansionHit, type ExpansionNeighbor } from './graph/expansion.ts'
35
35
  import { edgeStyleOf } from './graph/edges.ts'
36
+ import {
37
+ HIT_FILL as PALETTE_HIT_FILL, LABEL_FAINT as PALETTE_LABEL_FAINT, LABEL_INK as PALETTE_LABEL_INK,
38
+ NEIGHBOR_FILL as PALETTE_NEIGHBOR_FILL, OUTLINE_MUTED as PALETTE_OUTLINE_MUTED,
39
+ } from './graph/palette.ts'
36
40
  import { styles } from './styles.ts'
37
41
 
38
42
  export type { ExpansionHit, ExpansionNeighbor } from './graph/expansion.ts'
@@ -62,14 +66,16 @@ const EXPANSION_METRICS = { nodeW: 104, nodeH: 26, linkDistance: 72, stage: 300,
62
66
  /*
63
67
  * 画布侧的颜色都是**字面量**:canvas 渲染器不认 CSS 变量,写 `var(--tita-primary)`
64
68
  * 会被解析成全透明黑(`parseColor` 的兜底)。图例上的色块必须与画布上的圆点同色,
65
- * 所以它在 CSS 里写了一份,并在注释里点名这里。
69
+ * 所以它在 CSS 里写了一份,并在注释里点名这里 —— 画布这一侧的值全部来自
70
+ * `graph/palette.ts`(三处各写一份正是它们漂开的真正原因)。
66
71
  */
67
- const HIT_FILL = '#4868b2'
68
- const NEIGHBOR_FILL = '#ffffff'
69
- const OUTLINE = '#4868b2'
70
- const OUTLINE_MUTED = '#98a2b3'
71
- const LABEL_INK = '#101828'
72
- const LABEL_FAINT = '#667085'
72
+ const HIT_FILL = PALETTE_HIT_FILL
73
+ const NEIGHBOR_FILL = PALETTE_NEIGHBOR_FILL
74
+ /** 命中点的描边与填充同色:它是一个实心点,靠邻居的「空心」来区分两者。 */
75
+ const OUTLINE = PALETTE_HIT_FILL
76
+ const OUTLINE_MUTED = PALETTE_OUTLINE_MUTED
77
+ const LABEL_INK = PALETTE_LABEL_INK
78
+ const LABEL_FAINT = PALETTE_LABEL_FAINT
73
79
  /** 标签用的字面量字族:同上,canvas 读不到 `--font-tita`。 */
74
80
  const LABEL_FONT = '-apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif'
75
81