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.
- package/README.md +118 -567
- package/cordis.patch.yml +5 -418
- package/eval/README.md +19 -8
- package/eval/benchmark-extraction-format.mjs +20 -0
- package/eval/evaluate-retrieval.mjs +17 -8
- package/eval/queries.example.jsonl +1 -0
- package/lib/client.js +4181 -3239
- package/lib/contract-envelope.d.ts +91 -0
- package/lib/contract-envelope.js +106 -0
- package/lib/contract-layout.d.ts +130 -0
- package/lib/contract-layout.js +138 -0
- package/lib/contract-refs.d.ts +39 -0
- package/lib/contract-refs.js +9 -0
- package/lib/contract-version.d.ts +311 -0
- package/lib/contract-version.js +270 -0
- package/lib/contract-wire.d.ts +147 -0
- package/lib/contract-wire.js +99 -0
- package/lib/contracts.d.ts +12 -0
- package/lib/contracts.js +12 -0
- package/lib/doc-page.js +2 -2
- package/lib/pages.js +3329 -1296
- package/lib/types/agent-behavior-rules.d.ts +10 -0
- package/lib/types/agent-behavior-rules.d.ts.map +1 -0
- package/lib/types/agent-behavior-rules.js +28 -0
- package/lib/types/agent-behavior-rules.js.map +1 -0
- package/lib/types/axis-registry.d.ts +37 -5
- package/lib/types/axis-registry.d.ts.map +1 -1
- package/lib/types/axis-registry.js +234 -26
- package/lib/types/axis-registry.js.map +1 -1
- package/lib/types/card-organize.d.ts +27 -12
- package/lib/types/card-organize.d.ts.map +1 -1
- package/lib/types/card-organize.js +58 -73
- package/lib/types/card-organize.js.map +1 -1
- package/lib/types/compiler/embedding-identity.d.ts +3 -0
- package/lib/types/compiler/embedding-identity.d.ts.map +1 -0
- package/lib/types/compiler/embedding-identity.js +24 -0
- package/lib/types/compiler/embedding-identity.js.map +1 -0
- package/lib/types/compiler/snapshot.d.ts +16 -0
- package/lib/types/compiler/snapshot.d.ts.map +1 -0
- package/lib/types/compiler/snapshot.js +2 -0
- package/lib/types/compiler/snapshot.js.map +1 -0
- package/lib/types/config-schema.d.ts +6 -3
- package/lib/types/config-schema.d.ts.map +1 -1
- package/lib/types/config-schema.js +6 -2
- package/lib/types/config-schema.js.map +1 -1
- package/lib/types/convert/host.d.ts +6 -5
- package/lib/types/convert/host.d.ts.map +1 -1
- package/lib/types/convert/host.js +58 -18
- package/lib/types/convert/host.js.map +1 -1
- package/lib/types/convert/ingest.d.ts +10 -1
- package/lib/types/convert/ingest.d.ts.map +1 -1
- package/lib/types/convert/ingest.js +68 -9
- package/lib/types/convert/ingest.js.map +1 -1
- package/lib/types/derive-contract.d.ts +3 -0
- package/lib/types/derive-contract.d.ts.map +1 -0
- package/lib/types/derive-contract.js +15 -0
- package/lib/types/derive-contract.js.map +1 -0
- package/lib/types/diagnosis/cards.d.ts +7 -3
- package/lib/types/diagnosis/cards.d.ts.map +1 -1
- package/lib/types/diagnosis/cards.js +13 -8
- package/lib/types/diagnosis/cards.js.map +1 -1
- package/lib/types/diagnosis/run.d.ts +4 -13
- package/lib/types/diagnosis/run.d.ts.map +1 -1
- package/lib/types/diagnosis/run.js +26 -16
- package/lib/types/diagnosis/run.js.map +1 -1
- package/lib/types/diagnosis/schema.js +2 -2
- package/lib/types/diagnosis/schema.js.map +1 -1
- package/lib/types/diagnosis/seed-source.d.ts +1 -1
- package/lib/types/diagnosis/seed-source.d.ts.map +1 -1
- package/lib/types/diagnosis/seed-source.js +5 -4
- package/lib/types/diagnosis/seed-source.js.map +1 -1
- package/lib/types/diagnosis/seed.d.ts +4 -4
- package/lib/types/diagnosis/seed.d.ts.map +1 -1
- package/lib/types/diagnosis/seed.js +6 -8
- package/lib/types/diagnosis/seed.js.map +1 -1
- package/lib/types/diagnosis/store.d.ts +24 -18
- package/lib/types/diagnosis/store.d.ts.map +1 -1
- package/lib/types/diagnosis/store.js +130 -65
- package/lib/types/diagnosis/store.js.map +1 -1
- package/lib/types/diagnosis/types.d.ts +47 -15
- package/lib/types/diagnosis/types.d.ts.map +1 -1
- package/lib/types/diagnosis/types.js.map +1 -1
- package/lib/types/environment/dsh-python.d.ts +77 -0
- package/lib/types/environment/dsh-python.d.ts.map +1 -0
- package/lib/types/environment/dsh-python.js +139 -0
- package/lib/types/environment/dsh-python.js.map +1 -0
- package/lib/types/environment/install.d.ts +15 -0
- package/lib/types/environment/install.d.ts.map +1 -0
- package/lib/types/environment/install.js +297 -0
- package/lib/types/environment/install.js.map +1 -0
- package/lib/types/environment/manifest.d.ts +208 -0
- package/lib/types/environment/manifest.d.ts.map +1 -0
- package/lib/types/environment/manifest.js +26 -0
- package/lib/types/environment/manifest.js.map +1 -0
- package/lib/types/environment/model-catalog.d.ts +223 -0
- package/lib/types/environment/model-catalog.d.ts.map +1 -0
- package/lib/types/environment/model-catalog.js +129 -0
- package/lib/types/environment/model-catalog.js.map +1 -0
- package/lib/types/environment/process.d.ts +10 -0
- package/lib/types/environment/process.d.ts.map +1 -0
- package/lib/types/environment/process.js +54 -0
- package/lib/types/environment/process.js.map +1 -0
- package/lib/types/environment/selection.d.ts +9 -0
- package/lib/types/environment/selection.d.ts.map +1 -0
- package/lib/types/environment/selection.js +29 -0
- package/lib/types/environment/selection.js.map +1 -0
- package/lib/types/environment/service.d.ts +64 -0
- package/lib/types/environment/service.d.ts.map +1 -0
- package/lib/types/environment/service.js +424 -0
- package/lib/types/environment/service.js.map +1 -0
- package/lib/types/environment/types.d.ts +56 -0
- package/lib/types/environment/types.d.ts.map +1 -0
- package/lib/types/environment/types.js +2 -0
- package/lib/types/environment/types.js.map +1 -0
- package/lib/types/events.d.ts +76 -0
- package/lib/types/events.d.ts.map +1 -0
- package/lib/types/events.js +52 -0
- package/lib/types/events.js.map +1 -0
- package/lib/types/extract-contract.d.ts +3 -0
- package/lib/types/extract-contract.d.ts.map +1 -0
- package/lib/types/extract-contract.js +41 -0
- package/lib/types/extract-contract.js.map +1 -0
- package/lib/types/extract-model.d.ts +5 -0
- package/lib/types/extract-model.d.ts.map +1 -1
- package/lib/types/extract-model.js.map +1 -1
- package/lib/types/extract-table-contract.d.ts +3 -0
- package/lib/types/extract-table-contract.d.ts.map +1 -0
- package/lib/types/extract-table-contract.js +27 -0
- package/lib/types/extract-table-contract.js.map +1 -0
- package/lib/types/extract-table.d.ts +8 -0
- package/lib/types/extract-table.d.ts.map +1 -0
- package/lib/types/extract-table.js +158 -0
- package/lib/types/extract-table.js.map +1 -0
- package/lib/types/extraction-runs.d.ts +30 -6
- package/lib/types/extraction-runs.d.ts.map +1 -1
- package/lib/types/extraction-runs.js +69 -8
- package/lib/types/extraction-runs.js.map +1 -1
- package/lib/types/fs-atomic.d.ts +0 -7
- package/lib/types/fs-atomic.d.ts.map +1 -1
- package/lib/types/fs-atomic.js +17 -2
- package/lib/types/fs-atomic.js.map +1 -1
- package/lib/types/images.d.ts +26 -0
- package/lib/types/images.d.ts.map +1 -0
- package/lib/types/images.js +196 -0
- package/lib/types/images.js.map +1 -0
- package/lib/types/index.d.ts +2 -2
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +598 -209
- package/lib/types/index.js.map +1 -1
- package/lib/types/intent/engine.d.ts +12 -4
- package/lib/types/intent/engine.d.ts.map +1 -1
- package/lib/types/intent/engine.js +43 -5
- package/lib/types/intent/engine.js.map +1 -1
- package/lib/types/intent/host.d.ts +5 -8
- package/lib/types/intent/host.d.ts.map +1 -1
- package/lib/types/intent/host.js +56 -11
- package/lib/types/intent/host.js.map +1 -1
- package/lib/types/intent/scope.d.ts +25 -0
- package/lib/types/intent/scope.d.ts.map +1 -0
- package/lib/types/intent/scope.js +116 -0
- package/lib/types/intent/scope.js.map +1 -0
- package/lib/types/intent/tools.d.ts +24 -20
- package/lib/types/intent/tools.d.ts.map +1 -1
- package/lib/types/intent/tools.js +65 -23
- package/lib/types/intent/tools.js.map +1 -1
- package/lib/types/intent/types.d.ts +11 -4
- package/lib/types/intent/types.d.ts.map +1 -1
- package/lib/types/knowledge-bases.d.ts +11 -5
- package/lib/types/knowledge-bases.d.ts.map +1 -1
- package/lib/types/knowledge-bases.js +52 -20
- package/lib/types/knowledge-bases.js.map +1 -1
- package/lib/types/knowledge-contract.d.ts +32 -0
- package/lib/types/knowledge-contract.d.ts.map +1 -0
- package/lib/types/knowledge-contract.js +116 -0
- package/lib/types/knowledge-contract.js.map +1 -0
- package/lib/types/knowledge.d.ts +31 -9
- package/lib/types/knowledge.d.ts.map +1 -1
- package/lib/types/knowledge.js +137 -60
- package/lib/types/knowledge.js.map +1 -1
- package/lib/types/layout.d.ts +10 -29
- package/lib/types/layout.d.ts.map +1 -1
- package/lib/types/layout.js +17 -36
- package/lib/types/layout.js.map +1 -1
- package/lib/types/materialize-snapshot.d.ts +49 -0
- package/lib/types/materialize-snapshot.d.ts.map +1 -0
- package/lib/types/materialize-snapshot.js +2 -0
- package/lib/types/materialize-snapshot.js.map +1 -0
- package/lib/types/migrate.d.ts +11 -0
- package/lib/types/migrate.d.ts.map +1 -1
- package/lib/types/migrate.js +83 -2
- package/lib/types/migrate.js.map +1 -1
- package/lib/types/model-text.d.ts +58 -1
- package/lib/types/model-text.d.ts.map +1 -1
- package/lib/types/model-text.js +85 -30
- package/lib/types/model-text.js.map +1 -1
- package/lib/types/oplog.d.ts.map +1 -1
- package/lib/types/oplog.js +7 -0
- package/lib/types/oplog.js.map +1 -1
- package/lib/types/organize-contract.d.ts +18 -0
- package/lib/types/organize-contract.d.ts.map +1 -0
- package/lib/types/organize-contract.js +82 -0
- package/lib/types/organize-contract.js.map +1 -0
- package/lib/types/pipeline/engine.d.ts +66 -0
- package/lib/types/pipeline/engine.d.ts.map +1 -0
- package/lib/types/pipeline/engine.js +352 -0
- package/lib/types/pipeline/engine.js.map +1 -0
- package/lib/types/pipeline/store.d.ts +73 -0
- package/lib/types/pipeline/store.d.ts.map +1 -0
- package/lib/types/pipeline/store.js +143 -0
- package/lib/types/pipeline/store.js.map +1 -0
- package/lib/types/pipeline/types.d.ts +102 -0
- package/lib/types/pipeline/types.d.ts.map +1 -0
- package/lib/types/pipeline/types.js +5 -0
- package/lib/types/pipeline/types.js.map +1 -0
- package/lib/types/present.d.ts +2 -0
- package/lib/types/present.d.ts.map +1 -1
- package/lib/types/present.js +9 -4
- package/lib/types/present.js.map +1 -1
- package/lib/types/preset-ids.d.ts +4 -0
- package/lib/types/preset-ids.d.ts.map +1 -0
- package/lib/types/preset-ids.js +6 -0
- package/lib/types/preset-ids.js.map +1 -0
- package/lib/types/query-analysis.d.ts +13 -1
- package/lib/types/query-analysis.d.ts.map +1 -1
- package/lib/types/query-analysis.js +62 -6
- package/lib/types/query-analysis.js.map +1 -1
- package/lib/types/recall-rank.d.ts +3 -3
- package/lib/types/recall-rank.d.ts.map +1 -1
- package/lib/types/recall-rank.js +4 -4
- package/lib/types/recall-rank.js.map +1 -1
- package/lib/types/retention.d.ts +39 -0
- package/lib/types/retention.d.ts.map +1 -0
- package/lib/types/retention.js +42 -0
- package/lib/types/retention.js.map +1 -0
- package/lib/types/retrieval/vector-index.d.ts +32 -0
- package/lib/types/retrieval/vector-index.d.ts.map +1 -0
- package/lib/types/retrieval/vector-index.js +15 -0
- package/lib/types/retrieval/vector-index.js.map +1 -0
- package/lib/types/retrieval/visibility.d.ts +6 -0
- package/lib/types/retrieval/visibility.d.ts.map +1 -0
- package/lib/types/retrieval/visibility.js +11 -0
- package/lib/types/retrieval/visibility.js.map +1 -0
- package/lib/types/runtime.d.ts +272 -27
- package/lib/types/runtime.d.ts.map +1 -1
- package/lib/types/runtime.js +2751 -537
- package/lib/types/runtime.js.map +1 -1
- package/lib/types/settings-schema.d.ts +17 -15
- package/lib/types/settings-schema.d.ts.map +1 -1
- package/lib/types/settings-schema.js +50 -47
- package/lib/types/settings-schema.js.map +1 -1
- package/lib/types/settings-volatile.d.ts +4 -4
- package/lib/types/settings-volatile.js +4 -4
- package/lib/types/source-evidence.d.ts +14 -0
- package/lib/types/source-evidence.d.ts.map +1 -0
- package/lib/types/source-evidence.js +36 -0
- package/lib/types/source-evidence.js.map +1 -0
- package/lib/types/store/axis-references.d.ts +5 -0
- package/lib/types/store/axis-references.d.ts.map +1 -0
- package/lib/types/store/axis-references.js +106 -0
- package/lib/types/store/axis-references.js.map +1 -0
- package/lib/types/store/derived.d.ts +12 -1
- package/lib/types/store/derived.d.ts.map +1 -1
- package/lib/types/store/derived.js +71 -12
- package/lib/types/store/derived.js.map +1 -1
- package/lib/types/store/knowledge-db.d.ts +31 -1
- package/lib/types/store/knowledge-db.d.ts.map +1 -1
- package/lib/types/store/knowledge-db.js +252 -18
- package/lib/types/store/knowledge-db.js.map +1 -1
- package/lib/types/store/migrate.d.ts.map +1 -1
- package/lib/types/store/migrate.js +17 -6
- package/lib/types/store/migrate.js.map +1 -1
- package/lib/types/trajectory-types.d.ts +172 -0
- package/lib/types/trajectory-types.d.ts.map +1 -0
- package/lib/types/trajectory-types.js +36 -0
- package/lib/types/trajectory-types.js.map +1 -0
- package/lib/types/types.d.ts +59 -27
- package/lib/types/types.d.ts.map +1 -1
- package/lib/types/types.js +6 -15
- package/lib/types/types.js.map +1 -1
- package/lib/types/wiki-finalize.d.ts +16 -0
- package/lib/types/wiki-finalize.d.ts.map +1 -1
- package/lib/types/wiki-finalize.js +26 -0
- package/lib/types/wiki-finalize.js.map +1 -1
- package/lib/types/wiki-materialize.d.ts +4 -0
- package/lib/types/wiki-materialize.d.ts.map +1 -1
- package/lib/types/wiki-materialize.js +21 -7
- package/lib/types/wiki-materialize.js.map +1 -1
- package/lib/types/wiki-trial-types.d.ts +87 -0
- package/lib/types/wiki-trial-types.d.ts.map +1 -1
- package/lib/types/wiki-trial-types.js +0 -16
- package/lib/types/wiki-trial-types.js.map +1 -1
- package/lib/types/wiki-trial.d.ts +40 -16
- package/lib/types/wiki-trial.d.ts.map +1 -1
- package/lib/types/wiki-trial.js +337 -224
- package/lib/types/wiki-trial.js.map +1 -1
- package/package.json +29 -20
- package/python/prepare-models.py +19 -0
- package/python/requirements.txt +8 -6
- package/scripts/doctor.mjs +13 -19
- package/scripts/environment.mjs +29 -0
- package/scripts/setup-embedding.sh +15 -5
- package/src/agent-behavior-rules.ts +37 -0
- package/src/axis-registry.ts +234 -27
- package/src/card-organize.ts +69 -75
- package/src/client/AgentBehaviorRulesCard.tsx +65 -0
- package/src/client/AttributionEventGuide.tsx +41 -39
- package/src/client/AxisRegistrySection.tsx +204 -164
- package/src/client/CompileDialogs.tsx +44 -29
- package/src/client/DeleteDocumentDialog.tsx +36 -5
- package/src/client/DirectoryPicker.tsx +0 -10
- package/src/client/EnvironmentSetup.tsx +243 -0
- package/src/client/ExpansionGraph.tsx +13 -7
- package/src/client/ExtractionTasksPage.tsx +578 -0
- package/src/client/GuideArchitectureCanvas.tsx +470 -0
- package/src/client/ImportFilesDialog.tsx +2 -13
- package/src/client/IntentLogic.tsx +2 -2
- package/src/client/IntentTab.tsx +118 -47
- package/src/client/KnowledgeBaseTab.tsx +277 -197
- package/src/client/KnowledgeLayerSection.tsx +24 -6
- package/src/client/KnowledgePanel.tsx +58 -93
- package/src/client/KnowledgeSettingsDrawer.tsx +90 -0
- package/src/client/ListPager.tsx +15 -5
- package/src/client/MaterializeTrajectoryView.tsx +124 -0
- package/src/client/NodeSettings.tsx +210 -89
- package/src/client/NormalizeTrajectoryView.tsx +136 -0
- package/src/client/PipelineNotice.tsx +26 -0
- package/src/client/PreviewSections.tsx +118 -51
- package/src/client/RecallPanel.tsx +89 -85
- package/src/client/TabGuide.tsx +159 -184
- package/src/client/TrialReportView.tsx +391 -214
- package/src/client/TypeDefinitionDrawer.tsx +150 -23
- package/src/client/WikiCardPreview.tsx +62 -16
- package/src/client/WikiFlowPanel.tsx +4 -4
- package/src/client/arch/NodeLogicPanel.tsx +3 -4
- package/src/client/arch/model.ts +6 -9
- package/src/client/architecture.tsx +23 -33
- package/src/client/attribution/AttributionGraph.tsx +10 -6
- package/src/client/attribution/AttributionTab.tsx +136 -84
- package/src/client/attribution/CaseView.tsx +3 -1
- package/src/client/attribution/EventView.tsx +108 -0
- package/src/client/attribution/RunView.tsx +2 -2
- package/src/client/attribution/StageChrome.tsx +34 -3
- package/src/client/attribution/ViewSwitch.tsx +20 -5
- package/src/client/attribution/graph-options.ts +47 -39
- package/src/client/attribution/model.ts +17 -10
- package/src/client/config-scope.ts +3 -3
- package/src/client/graph/palette.ts +165 -0
- package/src/client/index.ts +49 -42
- package/src/client/pages.css +459 -135
- package/src/client/pages.tsx +37 -9
- package/src/client/problem-domains.ts +1 -1
- package/src/client/session-remote.ts +9 -0
- package/src/client/styles.css +205 -62
- package/src/client/wiki-trial.ts +44 -3
- package/src/compiler/embedding-identity.ts +21 -0
- package/src/compiler/snapshot.ts +17 -0
- package/src/config-schema.ts +8 -3
- package/src/convert/host.ts +56 -21
- package/src/convert/ingest.ts +74 -10
- package/src/derive-contract.ts +14 -0
- package/src/diagnosis/cards.ts +13 -8
- package/src/diagnosis/run.ts +27 -17
- package/src/diagnosis/schema.ts +2 -2
- package/src/diagnosis/seed-source.ts +5 -4
- package/src/diagnosis/seed.ts +6 -8
- package/src/diagnosis/store.ts +138 -69
- package/src/diagnosis/types.ts +34 -15
- package/src/environment/dsh-python.ts +156 -0
- package/src/environment/install.ts +244 -0
- package/src/environment/manifest.ts +28 -0
- package/src/environment/model-catalog.ts +147 -0
- package/src/environment/process.ts +54 -0
- package/src/environment/selection.ts +29 -0
- package/src/environment/service.ts +348 -0
- package/src/environment/types.ts +45 -0
- package/src/events.ts +108 -0
- package/src/extract-contract.ts +42 -0
- package/src/extract-model.ts +10 -1
- package/src/extract-table-contract.ts +26 -0
- package/src/extract-table.ts +132 -0
- package/src/extraction-runs.ts +70 -11
- package/src/fs-atomic.ts +19 -2
- package/src/images.ts +203 -0
- package/src/index.ts +553 -205
- package/src/intent/README.md +8 -6
- package/src/intent/engine.ts +44 -6
- package/src/intent/host.ts +59 -18
- package/src/intent/scope.ts +125 -0
- package/src/intent/tools.ts +70 -28
- package/src/intent/types.ts +11 -4
- package/src/knowledge-bases.ts +56 -20
- package/src/knowledge-contract.ts +114 -0
- package/src/knowledge.ts +138 -69
- package/src/layout.ts +17 -37
- package/src/materialize-snapshot.ts +46 -0
- package/src/migrate.ts +75 -2
- package/src/model-text.ts +109 -4
- package/src/oplog.ts +7 -0
- package/src/organize-contract.ts +83 -0
- package/src/pipeline/engine.ts +323 -0
- package/src/pipeline/store.ts +147 -0
- package/src/pipeline/types.ts +93 -0
- package/src/present.ts +10 -4
- package/src/preset-ids.ts +6 -0
- package/src/python/embedding_worker.py +66 -2
- package/src/query-analysis.ts +68 -8
- package/src/recall-rank.ts +5 -5
- package/src/retention.ts +76 -0
- package/src/retrieval/vector-index.ts +45 -0
- package/src/retrieval/visibility.ts +14 -0
- package/src/runtime.ts +2708 -567
- package/src/settings-schema.ts +11 -8
- package/src/settings-volatile.ts +4 -4
- package/src/source-evidence.ts +37 -0
- package/src/store/axis-references.ts +96 -0
- package/src/store/derived.ts +70 -12
- package/src/store/knowledge-db.ts +248 -17
- package/src/store/migrate.ts +16 -6
- package/src/trajectory-types.ts +142 -0
- package/src/types.ts +61 -35
- package/src/wiki-finalize.ts +28 -0
- package/src/wiki-materialize.ts +25 -6
- package/src/wiki-trial-types.ts +83 -1
- package/src/wiki-trial.ts +357 -185
- package/lib/types/intent/preset-tools.d.ts +0 -37
- package/lib/types/intent/preset-tools.d.ts.map +0 -1
- package/lib/types/intent/preset-tools.js +0 -45
- package/lib/types/intent/preset-tools.js.map +0 -1
- package/preset/tita-data-agent/agent.cordis.yml +0 -394
- package/preset/tita-data-agent/preset.yml +0 -3
- package/scripts/install-agent-preset.mjs +0 -92
- package/scripts/sync-agent-preset.mjs +0 -188
- package/src/client/AgentPresetCard.tsx +0 -247
- package/src/client/agent-preset.ts +0 -121
- package/src/client/convert/ConvertPanel.tsx +0 -583
- package/src/client/convert/styles.css +0 -138
- package/src/client/convert/styles.ts +0 -49
- package/src/intent/preset-tools.ts +0 -48
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState, useSyncExternalStore, type ReactNode } from 'react'
|
|
2
2
|
import { Button, Field, Input, SelectMenu, Switch, cn } from '@tita-agent/ui/components'
|
|
3
|
-
import { AlertCircle, Check, LoaderCircle, SlidersHorizontal } from '@tita-agent/ui/icons'
|
|
4
|
-
import {
|
|
5
|
-
import { InfoHint } from './InfoHint.tsx'
|
|
3
|
+
import { AlertCircle, Check, ChevronDown, FolderOpen, LoaderCircle, SlidersHorizontal } from '@tita-agent/ui/icons'
|
|
4
|
+
import type { SessionRemote } from './session-remote.ts'
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* 方案级设置。
|
|
@@ -42,16 +41,22 @@ export interface SettingsScopeLike {
|
|
|
42
41
|
unset?(field: string): Promise<void>
|
|
43
42
|
}
|
|
44
43
|
|
|
45
|
-
/**
|
|
46
|
-
export type SettingsNode = 'storage' | 'build' | 'recall'
|
|
44
|
+
/** 设置分组。编译模板是系统固定契约,不作为用户设置暴露。 */
|
|
45
|
+
export type SettingsNode = 'storage' | 'build' | 'recall'
|
|
47
46
|
|
|
48
47
|
interface FieldSpec {
|
|
49
48
|
key: string
|
|
50
49
|
label: string
|
|
51
|
-
kind: 'text' | 'number' | 'select' | 'toggle' | '
|
|
50
|
+
kind: 'text' | 'number' | 'select' | 'toggle' | 'location'
|
|
52
51
|
fallback: string | number | boolean
|
|
53
52
|
hint?: string
|
|
54
53
|
options?: Array<{ value: string; label: string }>
|
|
54
|
+
min?: number
|
|
55
|
+
max?: number
|
|
56
|
+
step?: number
|
|
57
|
+
/** Low-level tuning stays out of the default view. */
|
|
58
|
+
advanced?: boolean
|
|
59
|
+
visibleWhen?: { key: string; value: string }
|
|
55
60
|
/** Comma-separated array field: shown as text, saved as `string[]`. */
|
|
56
61
|
list?: boolean
|
|
57
62
|
}
|
|
@@ -59,8 +64,6 @@ interface FieldSpec {
|
|
|
59
64
|
interface NodeSpec {
|
|
60
65
|
scope: 'knowledge'
|
|
61
66
|
title: string
|
|
62
|
-
/** 说明,收进标题旁的 `?`。给了才渲染 —— 存储那一组 2026-10-06 起不给(见下)。 */
|
|
63
|
-
description?: string
|
|
64
67
|
fields: FieldSpec[]
|
|
65
68
|
}
|
|
66
69
|
|
|
@@ -76,55 +79,42 @@ export const NODE_SETTINGS: Record<SettingsNode, NodeSpec> = {
|
|
|
76
79
|
*/
|
|
77
80
|
storage: {
|
|
78
81
|
scope: 'knowledge',
|
|
79
|
-
title: '
|
|
82
|
+
title: '数据位置',
|
|
80
83
|
fields: [
|
|
81
|
-
{ key: 'agentRoot', label: 'Tita Agent
|
|
84
|
+
{ key: 'agentRoot', label: 'Tita Agent 数据目录', kind: 'location', fallback: '' },
|
|
82
85
|
],
|
|
83
86
|
},
|
|
84
87
|
// 0025:`compile` 设置组已撤。卡片编译模板是系统固定契约,不是用户设置项。
|
|
85
88
|
build: {
|
|
86
89
|
scope: 'knowledge',
|
|
87
|
-
title: '
|
|
88
|
-
description: '召回片段的向量编码方式与构建所用的 Python 环境。模型不可用时会降级到关键词路。',
|
|
90
|
+
title: '向量运行设置',
|
|
89
91
|
fields: [
|
|
90
|
-
{ key: 'embeddingProvider', label: '
|
|
91
|
-
{ key: '
|
|
92
|
-
{ key: '
|
|
93
|
-
{ key: '
|
|
94
|
-
{ key: 'embeddingDimension', label: '向量维度', kind: 'number', fallback: 512 },
|
|
95
|
-
{ key: 'embeddingBatchSize', label: '
|
|
96
|
-
{ key: 'embeddingTimeoutMs', label: '编码超时(毫秒)', kind: 'number', fallback: 120000 },
|
|
97
|
-
{ key: 'python', label: 'Python', kind: 'text', fallback: '', hint: '解释器路径;留空用根路径下那个本地环境' },
|
|
92
|
+
{ key: 'embeddingProvider', label: '向量来源', kind: 'select', fallback: 'wemm-python', options: [{ value: 'wemm-python', label: '本地模型' }, { value: 'ollama', label: 'Ollama' }, { value: 'none', label: '关闭向量' }] },
|
|
93
|
+
{ key: 'embeddingModel', label: 'Ollama 模型名称', kind: 'text', fallback: '', hint: '填写 Ollama 中已安装的模型名称。', visibleWhen: { key: 'embeddingProvider', value: 'ollama' } },
|
|
94
|
+
{ key: 'embeddingBaseUrl', label: 'Ollama 地址', kind: 'text', fallback: 'http://127.0.0.1:11434', visibleWhen: { key: 'embeddingProvider', value: 'ollama' } },
|
|
95
|
+
{ key: 'embeddingDevice', label: '运行设备', kind: 'select', fallback: 'auto', advanced: true, options: [{ value: 'auto', label: '自动' }, { value: 'mps', label: 'Apple MPS' }, { value: 'cpu', label: 'CPU' }] },
|
|
96
|
+
{ key: 'embeddingDimension', label: '向量维度', kind: 'number', fallback: 512, min: 1, step: 1, advanced: true, hint: '必须与所选模型输出维度一致;修改后需要重建向量索引。' },
|
|
97
|
+
{ key: 'embeddingBatchSize', label: '编码批大小', kind: 'number', fallback: 8, min: 1, max: 64, step: 1, advanced: true },
|
|
98
|
+
{ key: 'embeddingTimeoutMs', label: '编码超时(毫秒)', kind: 'number', fallback: 120000, min: 1000, max: 600000, step: 1000, advanced: true },
|
|
98
99
|
],
|
|
99
100
|
},
|
|
100
101
|
recall: {
|
|
101
102
|
scope: 'knowledge',
|
|
102
|
-
title: '
|
|
103
|
-
description: 'Coordinate、关键词 BM25、向量三路各自生成 Section 候选,融合(RRF)后统一重排。知识图谱不参与候选生成。',
|
|
103
|
+
title: '检索与上下文',
|
|
104
104
|
fields: [
|
|
105
|
-
{ key: 'recallTopK', label: '
|
|
106
|
-
{ key: '
|
|
107
|
-
{ key: '
|
|
108
|
-
{ key: '
|
|
109
|
-
{ key: '
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
context: {
|
|
113
|
-
scope: 'knowledge',
|
|
114
|
-
title: '重排设置',
|
|
115
|
-
description: 'BERT cross-encoder 对**候选池**精排,低于阈值的一律丢弃,再取上下文条数。阈值是整条链路里唯一跨查询可比的相关性判据,所以「弃答」主要靠它。',
|
|
116
|
-
fields: [
|
|
117
|
-
{ key: 'contextTopN', label: '上下文 TopN', kind: 'number', fallback: 5, hint: '1–recallTopK,默认 5。同一张 wiki 最多 2 条,其余名额留给别的卡片' },
|
|
118
|
-
{ key: 'rerankThreshold', label: '重排阈值', kind: 'number', fallback: 0.2, hint: '−10–10,默认 0.2。原始 cross-encoder 分(与 WeKnora 同刻度):低于它的不进上下文' },
|
|
119
|
-
{ key: 'rerankProvider', label: 'Rerank Provider', kind: 'select', fallback: 'bert-python', options: [{ value: 'bert-python', label: 'BERT Python(本地)' }, { value: 'none', label: '关闭(按融合分数)' }] },
|
|
120
|
-
{ key: 'rerankModel', label: 'Rerank Model', kind: 'text', fallback: '', hint: '本地模型目录,或一个 HuggingFace 模型名' },
|
|
121
|
-
{ key: 'rerankTimeoutMs', label: '重排超时(毫秒)', kind: 'number', fallback: 60000 },
|
|
105
|
+
{ key: 'recallTopK', label: '最终召回片段数', kind: 'number', fallback: 10, min: 1, max: 50, step: 1, hint: '默认 10 条;低于重排阈值的片段会被过滤。' },
|
|
106
|
+
{ key: 'contextTopN', label: '进入上下文的卡片数', kind: 'number', fallback: 5, min: 1, max: 50, step: 1, hint: '默认 5 张命中卡片;知识图谱的一跳扩展不占这个名额。' },
|
|
107
|
+
{ key: 'keywordThreshold', label: '关键词阈值', kind: 'number', fallback: 0.3, min: 0, max: 1, step: 0.01, advanced: true, hint: '0–1 的归一化 BM25 分数;适合过滤弱命中,不能单独判断整批结果是否相关。' },
|
|
108
|
+
{ key: 'vectorThreshold', label: '向量阈值', kind: 'number', fallback: 0.5, min: -1, max: 1, step: 0.01, advanced: true, hint: '原始余弦分数。默认 0.5 是当前本地模型与语料的起点,换模型后应按召回诊断校准。' },
|
|
109
|
+
{ key: 'rerankThreshold', label: '重排最低分', kind: 'number', fallback: 0.2, min: -10, max: 10, step: 0.1, advanced: true },
|
|
110
|
+
{ key: 'rerankTimeoutMs', label: '重排超时(毫秒)', kind: 'number', fallback: 60000, min: 1000, max: 600000, step: 1000, advanced: true },
|
|
111
|
+
{ key: 'contextMaxChars', label: '上下文字符上限', kind: 'number', fallback: 20000, min: 0, max: 1000000, step: 1000, hint: '0 表示不限', advanced: true },
|
|
122
112
|
],
|
|
123
113
|
},
|
|
124
114
|
}
|
|
125
115
|
|
|
126
116
|
/** 知识库那一组设置组的**展示顺序**。抽屉按它渲染。 */
|
|
127
|
-
export const KNOWLEDGE_SETTINGS_ORDER: SettingsNode[] = ['storage', 'build', 'recall'
|
|
117
|
+
export const KNOWLEDGE_SETTINGS_ORDER: SettingsNode[] = ['storage', 'build', 'recall']
|
|
128
118
|
|
|
129
119
|
/**
|
|
130
120
|
* 卡片头上的「参数」入口(0034)。
|
|
@@ -174,9 +164,36 @@ function readField(spec: FieldSpec, value: Record<string, unknown> | undefined):
|
|
|
174
164
|
return String(raw)
|
|
175
165
|
}
|
|
176
166
|
|
|
167
|
+
/**
|
|
168
|
+
* 一个数字字段的草稿能不能落盘。返回 `null` = 能,否则是人话的原因。
|
|
169
|
+
*
|
|
170
|
+
* 这里挡的是两个具体的坏值,它们都不是「用户想存这个数」,而是**那一瞬间的输入状态**:
|
|
171
|
+
*
|
|
172
|
+
* - `Number('') === 0`:清空「向量维度」会把 0 写进设置,而 0 是被 `min` 挡掉的非法值;
|
|
173
|
+
* - `Number('abc') === NaN`:`JSON.stringify(NaN)` 是 `null`,存下去是一份坏设置。
|
|
174
|
+
*
|
|
175
|
+
* 所以非法文本**留在草稿里**(人看到自己敲的东西、右面有一句「值无效」),只是不写。
|
|
176
|
+
* 这比「敲一半就被改写」温和:中间态是人打字时的一个正常阶段,不是错误。
|
|
177
|
+
*/
|
|
178
|
+
function fieldErrorOf(spec: FieldSpec, value: string | boolean): string | undefined {
|
|
179
|
+
if (spec.kind !== 'number') return undefined
|
|
180
|
+
const text = String(value).trim()
|
|
181
|
+
if (text === '') return '值无效:请填写一个数字'
|
|
182
|
+
const parsed = Number(text)
|
|
183
|
+
if (!Number.isFinite(parsed)) return '值无效:请填写一个数字'
|
|
184
|
+
if (spec.min !== undefined && parsed < spec.min) return `值无效:不能小于 ${spec.min}`
|
|
185
|
+
if (spec.max !== undefined && parsed > spec.max) return `值无效:不能大于 ${spec.max}`
|
|
186
|
+
return undefined
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** 数字字段只在**合法**时才写。非法时返回 `undefined`,上层跳过这一次写入。 */
|
|
177
190
|
function writeField(spec: FieldSpec, draft: string | boolean): unknown {
|
|
178
191
|
if (spec.kind === 'toggle') return Boolean(draft)
|
|
179
|
-
if (spec.kind === 'number')
|
|
192
|
+
if (spec.kind === 'number') {
|
|
193
|
+
const error = fieldErrorOf(spec, draft)
|
|
194
|
+
if (error !== undefined) return undefined
|
|
195
|
+
return Number(String(draft).trim())
|
|
196
|
+
}
|
|
180
197
|
if (spec.list) return String(draft).split(',').map(item => item.trim()).filter(Boolean)
|
|
181
198
|
return String(draft)
|
|
182
199
|
}
|
|
@@ -187,20 +204,20 @@ function needsDebounce(spec: FieldSpec): boolean {
|
|
|
187
204
|
}
|
|
188
205
|
|
|
189
206
|
function TextField({ spec, value, onChange, disabled, resolved }: { spec: FieldSpec; value: string; onChange: (value: string) => void; disabled: boolean; resolved?: string }) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
{spec.hint ? <span className="block">{spec.hint}</span> : null}
|
|
193
|
-
{/* 留空 = 自动。占位符显示**解析后**的真实路径 —— 否则「自动」等于没说。 */}
|
|
194
|
-
{resolved ? <span className="block">留空 = 自动:<code>{resolved}</code></span> : null}
|
|
195
|
-
</>
|
|
196
|
-
return <Field label={spec.label} hint={hint}>
|
|
207
|
+
const invalid = fieldErrorOf(spec, value)
|
|
208
|
+
return <Field label={spec.label} hint={spec.hint}>
|
|
197
209
|
<Input
|
|
198
210
|
type={spec.kind === 'number' ? 'number' : 'text'}
|
|
199
211
|
value={value}
|
|
200
212
|
disabled={disabled}
|
|
213
|
+
min={spec.min}
|
|
214
|
+
max={spec.max}
|
|
215
|
+
step={spec.step}
|
|
201
216
|
{...(resolved ? { placeholder: resolved } : {})}
|
|
202
217
|
onChange={event => onChange(event.target.value)}
|
|
203
218
|
/>
|
|
219
|
+
{/* 非法草稿**留在输入框里**,只在旁边说一句「值无效、不会写」—— 见 `fieldErrorOf`。 */}
|
|
220
|
+
{invalid && <span className="tita-settingInvalid" role="status">{invalid}</span>}
|
|
204
221
|
</Field>
|
|
205
222
|
}
|
|
206
223
|
|
|
@@ -240,30 +257,99 @@ function ToggleField({ spec, value, onChange, disabled }: { spec: FieldSpec; val
|
|
|
240
257
|
</Field>
|
|
241
258
|
}
|
|
242
259
|
|
|
260
|
+
/**
|
|
261
|
+
* 固定的数据目录:只读展示实际路径,打开动作交给 DSH 的 session 能力。
|
|
262
|
+
*/
|
|
263
|
+
function StorageLocationField({ label, path, session, onError, loadError, onRetry }: {
|
|
264
|
+
label: string
|
|
265
|
+
path?: string
|
|
266
|
+
session?: SessionRemote['session']
|
|
267
|
+
onError: (message: string | null) => void
|
|
268
|
+
/** `/knowledge/layout` 的读取失败。它发生在这个字段上,所以报在这个字段旁边。 */
|
|
269
|
+
loadError?: string | null
|
|
270
|
+
/** 重读一次布局。不给人这条路的话,一次瞬时失败会永久停在一句占位文字上。 */
|
|
271
|
+
onRetry?: () => void
|
|
272
|
+
}): ReactNode {
|
|
273
|
+
const [opening, setOpening] = useState(false)
|
|
274
|
+
|
|
275
|
+
const open = async (): Promise<void> => {
|
|
276
|
+
if (!path) return
|
|
277
|
+
onError(null)
|
|
278
|
+
if (!session || typeof session.openWorkspacePath !== 'function') {
|
|
279
|
+
onError('宿主没有提供打开目录的能力,请手动打开下面显示的路径。')
|
|
280
|
+
return
|
|
281
|
+
}
|
|
282
|
+
setOpening(true)
|
|
283
|
+
try {
|
|
284
|
+
const result = await session.openWorkspacePath({ path, action: 'reveal' })
|
|
285
|
+
if (!result.ok) onError(result.message ?? '宿主拒绝打开这个目录,请手动打开下面显示的路径。')
|
|
286
|
+
} catch (cause) {
|
|
287
|
+
onError(`${cause instanceof Error ? cause.message : String(cause)} 请手动打开下面显示的路径。`)
|
|
288
|
+
} finally {
|
|
289
|
+
setOpening(false)
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return <Field as="div" label={label}>
|
|
294
|
+
<div className="tita-pickerRow">
|
|
295
|
+
{/* 读不到布局时占位文字要跟着变:原来的「正在读取数据目录…」在失败之后
|
|
296
|
+
是一句**永远为真**的话,而它掩盖了「已经不读了」这个事实。 */}
|
|
297
|
+
<Input readOnly value={path ?? ''} placeholder={loadError ? '未能读取数据目录' : '正在读取数据目录…'} aria-label={label} />
|
|
298
|
+
<Button variant="outline" onClick={() => void open()} disabled={!path || opening}>
|
|
299
|
+
{opening ? <LoaderCircle size={14} className="tita-spin" /> : <FolderOpen size={14} />}
|
|
300
|
+
{opening ? '正在打开…' : '打开目录'}
|
|
301
|
+
</Button>
|
|
302
|
+
</div>
|
|
303
|
+
{loadError && <p className="tita-settingsRetry" role="alert">
|
|
304
|
+
<AlertCircle size={13} />
|
|
305
|
+
<span>读取数据目录失败:{loadError}</span>
|
|
306
|
+
{onRetry && <Button variant="ghost" size="sm" onClick={onRetry}>重新读取</Button>}
|
|
307
|
+
</p>}
|
|
308
|
+
</Field>
|
|
309
|
+
}
|
|
310
|
+
|
|
243
311
|
/** 写入状态。`saved` 只短暂出现,`error` 留到下一次改动。 */
|
|
244
312
|
type SaveState = 'idle' | 'saving' | 'saved' | 'error'
|
|
245
313
|
|
|
246
|
-
export function NodeSettingsPanel({ node, knowledge,
|
|
314
|
+
export function NodeSettingsPanel({ node, knowledge, agentRoot, session, resolved = {}, highlight = false, showAdvanced = false, advancedLabel, layoutError = null, onRetryLayout }: {
|
|
247
315
|
node: SettingsNode
|
|
248
316
|
knowledge?: SettingsScopeLike
|
|
249
|
-
/**
|
|
250
|
-
|
|
317
|
+
/** `/knowledge/layout` 返回的固定 Agent 根目录。 */
|
|
318
|
+
agentRoot?: string
|
|
319
|
+
/** DSH 提供的系统文件管理器能力,只用于打开固定目录。 */
|
|
320
|
+
session?: SessionRemote['session']
|
|
251
321
|
/** 字段键 → 「留空时实际会用什么」。0029:家当路径空着就是跟着根路径走。 */
|
|
252
322
|
resolved?: Record<string, string>
|
|
253
323
|
/** 由卡片头的「参数」chip 定位过来的那一块:一次性强调 + 接管焦点。 */
|
|
254
324
|
highlight?: boolean
|
|
325
|
+
/** Show the model and retrieval tuning fields. */
|
|
326
|
+
showAdvanced?: boolean
|
|
327
|
+
/** Keep low-frequency fields within this group, behind a named disclosure. */
|
|
328
|
+
advancedLabel?: string
|
|
329
|
+
/** `/knowledge/layout` 读取失败时的原话;只有「数据位置」那一块用得到。 */
|
|
330
|
+
layoutError?: string | null
|
|
331
|
+
/** 重读一次布局。 */
|
|
332
|
+
onRetryLayout?: () => void
|
|
255
333
|
}): ReactNode {
|
|
256
334
|
const spec = NODE_SETTINGS[node]
|
|
257
335
|
const scope = knowledge
|
|
258
336
|
const state = useScope(knowledge)
|
|
259
337
|
const [draft, setDraft] = useState<Record<string, string | boolean>>({})
|
|
260
338
|
const [saveState, setSaveState] = useState<SaveState>('idle')
|
|
339
|
+
const [advancedOpen, setAdvancedOpen] = useState(false)
|
|
261
340
|
const [error, setError] = useState<string | null>(null)
|
|
262
|
-
/**
|
|
263
|
-
|
|
341
|
+
/**
|
|
342
|
+
* 待落地的防抖写入,按字段键索引。
|
|
343
|
+
*
|
|
344
|
+
* 除了计时器,它还记着**那次要写的值**:卸载时那个 `setTimeout` 不会再回来,
|
|
345
|
+
* 而草稿 state 在那一刻不一定已经渲染过(`setDraft` 是异步的)—— 从 timer 里读
|
|
346
|
+
* 值才是「用户最后敲进去的东西」的唯一可靠来源。
|
|
347
|
+
*/
|
|
348
|
+
const pending = useRef(new Map<string, { timer: ReturnType<typeof setTimeout>; field: FieldSpec; value: string | boolean }>())
|
|
264
349
|
/** 正在进行的写入数。用它挡住「写完 → revision 变 → 重置草稿」把输入抹掉。 */
|
|
265
350
|
const inflight = useRef(0)
|
|
266
351
|
const savedTimer = useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
352
|
+
const disabled = !state.writable || state.status !== 'ready'
|
|
267
353
|
|
|
268
354
|
useEffect(() => {
|
|
269
355
|
// 有写入在飞的时候不重置草稿:那一刻 `state.value` 还是旧值,重置会把用户刚
|
|
@@ -272,21 +358,16 @@ export function NodeSettingsPanel({ node, knowledge, pickerKind = null, resolved
|
|
|
272
358
|
setDraft(Object.fromEntries(spec.fields.map(field => [field.key, readField(field, state.value)])))
|
|
273
359
|
}, [node, state.revision, state.value])
|
|
274
360
|
|
|
275
|
-
// 卸载时把还没落地的防抖写入丢掉并清计时器:一个已经离开的面板不该再写设置。
|
|
276
|
-
useEffect(() => () => {
|
|
277
|
-
for (const timer of timers.current.values()) clearTimeout(timer)
|
|
278
|
-
timers.current.clear()
|
|
279
|
-
if (savedTimer.current) clearTimeout(savedTimer.current)
|
|
280
|
-
}, [])
|
|
281
|
-
|
|
282
|
-
const disabled = !state.writable || state.status !== 'ready'
|
|
283
|
-
|
|
284
361
|
const persist = useCallback(async (field: FieldSpec, raw: string | boolean): Promise<void> => {
|
|
285
362
|
if (!scope || disabled) return
|
|
363
|
+
const value = writeField(field, raw)
|
|
364
|
+
// 非法草稿跳过这一次写入(见 `fieldErrorOf`)。它不是失败,也不该报错 ——
|
|
365
|
+
// 只是「这一笔现在还不能写」,草稿留在输入框里等人把它改对。
|
|
366
|
+
if (value === undefined) return
|
|
286
367
|
inflight.current += 1
|
|
287
368
|
setSaveState('saving'); setError(null)
|
|
288
369
|
try {
|
|
289
|
-
await scope.set(field.key,
|
|
370
|
+
await scope.set(field.key, value)
|
|
290
371
|
setSaveState('saved')
|
|
291
372
|
if (savedTimer.current) clearTimeout(savedTimer.current)
|
|
292
373
|
// 「已保存」只是一个确认,不是一条状态:两秒后收回,免得它常驻成一个
|
|
@@ -300,18 +381,35 @@ export function NodeSettingsPanel({ node, knowledge, pickerKind = null, resolved
|
|
|
300
381
|
}
|
|
301
382
|
}, [scope, disabled])
|
|
302
383
|
|
|
384
|
+
// 卸载时把还没落地的防抖写入**冲出去**,而不是丢掉:用户敲完立刻按 Esc 是常规操作,
|
|
385
|
+
// 而丢掉的表现是「输入框里的值过一会儿自己变回去了」,中间连一个保存指示都没有。
|
|
386
|
+
// 冲出去就是替那一个 `setTimeout` 把事做完。卸载后 `persist` 里的 setState 会被
|
|
387
|
+
// React 忽略(它已经不在树上了),写入本身照旧发出去。
|
|
388
|
+
useEffect(() => () => {
|
|
389
|
+
for (const { timer, field, value } of pending.current.values()) {
|
|
390
|
+
clearTimeout(timer)
|
|
391
|
+
void persist(field, value)
|
|
392
|
+
}
|
|
393
|
+
pending.current.clear()
|
|
394
|
+
if (savedTimer.current) clearTimeout(savedTimer.current)
|
|
395
|
+
}, []) // eslint-disable-line react-hooks/exhaustive-deps
|
|
396
|
+
|
|
303
397
|
const update = (field: FieldSpec, value: string | boolean): void => {
|
|
304
398
|
setDraft(current => ({ ...current, [field.key]: value }))
|
|
305
399
|
if (!needsDebounce(field)) {
|
|
306
400
|
void persist(field, value)
|
|
307
401
|
return
|
|
308
402
|
}
|
|
309
|
-
const existing =
|
|
310
|
-
if (existing) clearTimeout(existing)
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
403
|
+
const existing = pending.current.get(field.key)
|
|
404
|
+
if (existing) clearTimeout(existing.timer)
|
|
405
|
+
pending.current.set(field.key, {
|
|
406
|
+
field,
|
|
407
|
+
value,
|
|
408
|
+
timer: setTimeout(() => {
|
|
409
|
+
pending.current.delete(field.key)
|
|
410
|
+
void persist(field, value)
|
|
411
|
+
}, 600),
|
|
412
|
+
})
|
|
315
413
|
}
|
|
316
414
|
|
|
317
415
|
const meta = state.status === 'loading'
|
|
@@ -323,12 +421,45 @@ export function NodeSettingsPanel({ node, knowledge, pickerKind = null, resolved
|
|
|
323
421
|
: saveState === 'saved'
|
|
324
422
|
? '已保存'
|
|
325
423
|
: saveState === 'error'
|
|
326
|
-
? '
|
|
327
|
-
:
|
|
424
|
+
? '保存失败'
|
|
425
|
+
: ''
|
|
426
|
+
|
|
427
|
+
const visibleFields = spec.fields.filter(field => {
|
|
428
|
+
if (!field.visibleWhen) return true
|
|
429
|
+
const dependency = spec.fields.find(item => item.key === field.visibleWhen?.key)
|
|
430
|
+
const value = draft[field.visibleWhen.key] ?? (dependency ? readField(dependency, state.value) : undefined)
|
|
431
|
+
return value === field.visibleWhen.value
|
|
432
|
+
})
|
|
433
|
+
|
|
434
|
+
const fields = visibleFields.filter(field => showAdvanced || !field.advanced)
|
|
435
|
+
const advancedFields = visibleFields.filter(field => field.advanced)
|
|
328
436
|
|
|
329
437
|
const anchor = settingsAnchorId(node)
|
|
330
438
|
const titleId = `${anchor}-title`
|
|
331
439
|
|
|
440
|
+
const renderField = (field: FieldSpec): ReactNode => field.kind === 'toggle'
|
|
441
|
+
? <ToggleField key={field.key} spec={field} value={Boolean(draft[field.key])} onChange={value => update(field, value)} disabled={disabled} />
|
|
442
|
+
: field.kind === 'select'
|
|
443
|
+
? <SelectField key={field.key} spec={field} value={String(draft[field.key] ?? '')} onChange={value => update(field, value)} disabled={disabled} />
|
|
444
|
+
: field.kind === 'location'
|
|
445
|
+
? <StorageLocationField
|
|
446
|
+
key={field.key}
|
|
447
|
+
label={field.label}
|
|
448
|
+
path={agentRoot}
|
|
449
|
+
session={session}
|
|
450
|
+
onError={setError}
|
|
451
|
+
loadError={layoutError}
|
|
452
|
+
{...(onRetryLayout ? { onRetry: onRetryLayout } : {})}
|
|
453
|
+
/>
|
|
454
|
+
: <TextField
|
|
455
|
+
key={field.key}
|
|
456
|
+
spec={field}
|
|
457
|
+
value={String(draft[field.key] ?? '')}
|
|
458
|
+
onChange={value => update(field, value)}
|
|
459
|
+
disabled={disabled}
|
|
460
|
+
{...(resolved[field.key] && !(field.key === 'embeddingModel' && draft.embeddingProvider === 'ollama') ? { resolved: resolved[field.key]! } : {})}
|
|
461
|
+
/>
|
|
462
|
+
|
|
332
463
|
return <section
|
|
333
464
|
id={anchor}
|
|
334
465
|
className={cn('tita-settingsSection', highlight && 'tita-settingsSectionOn')}
|
|
@@ -339,9 +470,7 @@ export function NodeSettingsPanel({ node, knowledge, pickerKind = null, resolved
|
|
|
339
470
|
aria-labelledby={titleId}
|
|
340
471
|
>
|
|
341
472
|
<div className="tita-settingsSectionHeader">
|
|
342
|
-
{
|
|
343
|
-
见 `InfoHint`。 */}
|
|
344
|
-
<div><h3 id={titleId}>{spec.title}{spec.description && <InfoHint text={spec.description} />}</h3></div>
|
|
473
|
+
<div><h3 id={titleId}>{spec.title}</h3></div>
|
|
345
474
|
<div className={`tita-settingMeta${saveState === 'error' ? ' tita-settingMetaBad' : ''}`} role="status" aria-live="polite">
|
|
346
475
|
{saveState === 'saving' && <LoaderCircle size={11} className="tita-spin" />}
|
|
347
476
|
{saveState === 'saved' && <Check size={11} />}
|
|
@@ -350,21 +479,13 @@ export function NodeSettingsPanel({ node, knowledge, pickerKind = null, resolved
|
|
|
350
479
|
</div>
|
|
351
480
|
{error && <div className="tita-settingsError" role="alert"><AlertCircle size={13} />{error}</div>}
|
|
352
481
|
<div className="tita-settingsGrid">
|
|
353
|
-
{
|
|
354
|
-
? <ToggleField key={field.key} spec={field} value={Boolean(draft[field.key])} onChange={value => update(field, value)} disabled={disabled} />
|
|
355
|
-
: field.kind === 'select'
|
|
356
|
-
? <SelectField key={field.key} spec={field} value={String(draft[field.key] ?? '')} onChange={value => update(field, value)} disabled={disabled} />
|
|
357
|
-
: field.kind === 'picker'
|
|
358
|
-
? <DirectoryPickerField
|
|
359
|
-
key={field.key}
|
|
360
|
-
label={field.label}
|
|
361
|
-
value={String(draft[field.key] ?? '')}
|
|
362
|
-
disabled={disabled}
|
|
363
|
-
pickerKind={pickerKind}
|
|
364
|
-
onError={setError}
|
|
365
|
-
onChange={value => update(field, value)}
|
|
366
|
-
/>
|
|
367
|
-
: <TextField key={field.key} spec={field} value={String(draft[field.key] ?? '')} onChange={value => update(field, value)} disabled={disabled} {...(resolved[field.key] ? { resolved: resolved[field.key]! } : {})} />)}
|
|
482
|
+
{fields.map(renderField)}
|
|
368
483
|
</div>
|
|
484
|
+
{!showAdvanced && advancedLabel && advancedFields.length > 0 && <div className="mt-5 border-t border-tita-line pt-3">
|
|
485
|
+
<Button variant="ghost" size="sm" className="-ml-2" aria-expanded={advancedOpen} aria-controls={`${anchor}-advanced`} onClick={() => setAdvancedOpen(value => !value)}>
|
|
486
|
+
<ChevronDown size={14} className={advancedOpen ? 'rotate-180' : ''} />{advancedLabel}
|
|
487
|
+
</Button>
|
|
488
|
+
{advancedOpen && <div id={`${anchor}-advanced`} className="tita-settingsGrid mt-4">{advancedFields.map(renderField)}</div>}
|
|
489
|
+
</div>}
|
|
369
490
|
</section>
|
|
370
491
|
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 归一轨迹的渲染(2026-10-18)。
|
|
3
|
+
*
|
|
4
|
+
* 归一这一段原来只留下两个东西:任务里一段会滚走的流式输出,和最终写进事实表的那些行。
|
|
5
|
+
* 中间那一步 ——「模型给的这些名字里,哪些命中了已有实体、哪些新建了候选、哪些因为不唯一
|
|
6
|
+
* 没猜」—— 跑完就查不到了。而它恰好是坐标错了之后唯一能复盘的东西:卡名错了,根在这里。
|
|
7
|
+
*
|
|
8
|
+
* 所以这一页只回答三个问题,按这个顺序:
|
|
9
|
+
*
|
|
10
|
+
* 1. **这次归一动了多少**(提及数、命中/新建/歧义、写进多少条事实)。
|
|
11
|
+
* 2. **每个名字落到了哪里**(名字 → 实体 id,以及凭什么)。
|
|
12
|
+
* 3. **写进去的事实长什么样**(正文、坐标、几条出处、哪几条还悬着)。
|
|
13
|
+
*
|
|
14
|
+
* 样式复用抽取报告那一套(`.tita-trial*`):三份轨迹是同一件事的三种粒度,
|
|
15
|
+
* 长得不一样会让人以为是三个不同的功能。
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { type ReactNode } from 'react'
|
|
19
|
+
import { TriangleAlert } from '@tita-agent/ui/icons'
|
|
20
|
+
import { cn } from '@tita-agent/ui/components'
|
|
21
|
+
import { styles } from './styles.ts'
|
|
22
|
+
import type { NormalizeTrajectoryReport } from '../trajectory-types.js'
|
|
23
|
+
|
|
24
|
+
/** 名字最多摊这么多行。再多就该看总体结论,不该在页面上滚。 */
|
|
25
|
+
const AXIS_CAP = 200
|
|
26
|
+
const FACT_CAP = 200
|
|
27
|
+
|
|
28
|
+
const OUTCOME_LABEL: Record<string, string> = {
|
|
29
|
+
matched: '命中已有',
|
|
30
|
+
new: '新建候选',
|
|
31
|
+
ambiguous: '不唯一,没猜',
|
|
32
|
+
'no-registry': '只做文档内归一',
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function NormalizeTrajectory({ report }: { report: NormalizeTrajectoryReport }): ReactNode {
|
|
36
|
+
const axes = report.axes ?? []
|
|
37
|
+
const rows = report.rows ?? []
|
|
38
|
+
const counts = report.counts ?? { matched: 0, created: 0, ambiguous: 0, mechanical: 0 }
|
|
39
|
+
const modelOk = report.model?.ok !== false
|
|
40
|
+
return <div className={styles.trialReport}>
|
|
41
|
+
<section className={styles.trialOverview} aria-labelledby="normalize-overview-title">
|
|
42
|
+
<div className={styles.trialSectionHead}>
|
|
43
|
+
<h2 id="normalize-overview-title">结果概览</h2>
|
|
44
|
+
<span>{report.knowledge?.unresolved ? `${report.knowledge.unresolved} 条坐标未决` : modelOk ? '已完成' : '需检查'}</span>
|
|
45
|
+
</div>
|
|
46
|
+
<dl className={styles.trialOverviewStats}>
|
|
47
|
+
<div><dt>坐标提及</dt><dd>{report.mentions ?? axes.length}</dd></div>
|
|
48
|
+
<div><dt>命中 / 新建</dt><dd>{counts.matched} / {counts.created}<small>已有实体 / 候选</small></dd></div>
|
|
49
|
+
<div><dt>歧义未决</dt><dd>{counts.ambiguous}<small>不猜,留给人</small></dd></div>
|
|
50
|
+
<div><dt>写入 Knowledge</dt><dd>{report.knowledge?.saved ?? 0}<small>另并入 {report.knowledge?.merged ?? 0} 条</small></dd></div>
|
|
51
|
+
<div><dt>写入 Event</dt><dd>{report.events?.saved ?? 0}<small>另并入 {report.events?.merged ?? 0} 个</small></dd></div>
|
|
52
|
+
</dl>
|
|
53
|
+
<p className={styles.trialOverviewTitle}>
|
|
54
|
+
<strong>{report.source?.title || '(来源已删除)'}</strong>
|
|
55
|
+
<span>v{report.source?.version ?? '?'} · 依据抽取记录 {report.extractionId || '—'}</span>
|
|
56
|
+
</p>
|
|
57
|
+
</section>
|
|
58
|
+
|
|
59
|
+
{!modelOk && <p className={styles.trialError} role="alert">
|
|
60
|
+
<TriangleAlert size={12} />{report.model?.why ?? '归一没有跑通'} · 这一份文档的事实没有写完。
|
|
61
|
+
</p>}
|
|
62
|
+
|
|
63
|
+
{report.warnings.length > 0 && <section className={styles.trialSection} aria-labelledby="normalize-warnings-title">
|
|
64
|
+
<div className={styles.trialSectionHead}>
|
|
65
|
+
<h2 id="normalize-warnings-title">警告</h2>
|
|
66
|
+
<span>{report.warnings.length} 条</span>
|
|
67
|
+
</div>
|
|
68
|
+
<ul className={styles.trialCandidates}>{report.warnings.map((warning, index) => <li key={index}>
|
|
69
|
+
{/* 不加装饰图标:这一段就叫「警告」,一条黄三角再标一次是同一句话说两遍。
|
|
70
|
+
而且 `trialCandidates > li` 是上下两行的栅格 —— 图标单占一行会让正文掉到第三行。 */}
|
|
71
|
+
<span className={styles.trialCandName}>{warning}</span>
|
|
72
|
+
</li>)}</ul>
|
|
73
|
+
</section>}
|
|
74
|
+
|
|
75
|
+
<section className={styles.trialSection} aria-labelledby="normalize-axes-title">
|
|
76
|
+
<div className={styles.trialSectionHead}>
|
|
77
|
+
<h2 id="normalize-axes-title">坐标解析</h2>
|
|
78
|
+
<span>{axes.length} 个名字{counts.mechanical > 0 ? ` · ${counts.mechanical} 个只做了机械归一` : ''}</span>
|
|
79
|
+
</div>
|
|
80
|
+
{axes.length === 0
|
|
81
|
+
? <p className={styles.trialEmpty}>这次归一没有解析任何坐标名。</p>
|
|
82
|
+
: <ul className={styles.trialItems}>{axes.slice(0, AXIS_CAP).map((axis, index) => <li
|
|
83
|
+
key={`${axis.kind}-${axis.name}-${index}`}
|
|
84
|
+
className={axis.outcome === 'matched' ? styles.trialItem : `${styles.trialItem} ${styles.trialItemWarn}`}
|
|
85
|
+
>
|
|
86
|
+
<span className={styles.trialItemRef}>{axis.name}</span>
|
|
87
|
+
<span className={styles.trialItemArrow} aria-hidden="true">→</span>
|
|
88
|
+
<span className={styles.trialItemValue}>
|
|
89
|
+
{(OUTCOME_LABEL[axis.outcome] ?? axis.outcome)}{axis.id ? ` ${axis.id}` : ''}
|
|
90
|
+
</span>
|
|
91
|
+
<span className={styles.trialItemNote}>
|
|
92
|
+
{KIND_LABEL[axis.kind] ?? axis.kind}{axis.how ? ` · ${axis.how}` : ''}{axis.parentMention ? ` · 作用域:${axis.parentMention}` : ''}
|
|
93
|
+
</span>
|
|
94
|
+
</li>)}</ul>}
|
|
95
|
+
{axes.length > AXIS_CAP && <p className={styles.trialItemsMore}>另有 {axes.length - AXIS_CAP} 个名字未展开。</p>}
|
|
96
|
+
</section>
|
|
97
|
+
|
|
98
|
+
<section className={styles.trialSection} aria-labelledby="normalize-facts-title">
|
|
99
|
+
<div className={styles.trialSectionHead}>
|
|
100
|
+
<h2 id="normalize-facts-title">写入的事实</h2>
|
|
101
|
+
<span>{rows.length} 条{report.knowledge?.unresolved ? ` · ${report.knowledge.unresolved} 条坐标未决` : ''}</span>
|
|
102
|
+
</div>
|
|
103
|
+
{rows.length === 0
|
|
104
|
+
? <p className={styles.trialEmpty}>这次归一没有写入 Knowledge。</p>
|
|
105
|
+
: <ul className={styles.trialOutputList}>{rows.slice(0, FACT_CAP).map((row, index) => <li key={index} className={styles.trialOutputItem}>
|
|
106
|
+
<div className={styles.trialCandHead}>
|
|
107
|
+
<span className={cn(styles.trialCandName, row.unresolved && styles.trialCandBad)}>{row.text}</span>
|
|
108
|
+
</div>
|
|
109
|
+
<div className={styles.trialOutputMeta}>
|
|
110
|
+
{row.coordinate} · {row.sources} 条出处
|
|
111
|
+
{row.unresolved && <strong>坐标未决</strong>}
|
|
112
|
+
</div>
|
|
113
|
+
</li>)}</ul>}
|
|
114
|
+
{rows.length > FACT_CAP && <p className={styles.trialMore}>另有 {rows.length - FACT_CAP} 条未展开。</p>}
|
|
115
|
+
</section>
|
|
116
|
+
|
|
117
|
+
<section className={styles.trialSection} aria-labelledby="normalize-fingerprint-title">
|
|
118
|
+
<div className={styles.trialSectionHead}>
|
|
119
|
+
<h2 id="normalize-fingerprint-title">续跑信息</h2>
|
|
120
|
+
<span>指纹没变,下一次归一会直接复用这一份</span>
|
|
121
|
+
</div>
|
|
122
|
+
<dl className={styles.trialRows}>
|
|
123
|
+
<div className={styles.trialRow}><dt>归一指纹</dt><dd>{report.fingerprint || '—'}</dd></div>
|
|
124
|
+
<div className={styles.trialRow}>
|
|
125
|
+
<dt>已下发坐标</dt>
|
|
126
|
+
<dd>{report.axesContext === undefined
|
|
127
|
+
? '这次没有下发(没接注册表,或库里还没有实体)'
|
|
128
|
+
: `${report.axesContext.injected} / ${report.axesContext.totals} 条${report.axesContext.truncated > 0 ? ` · 未下发 ${report.axesContext.truncated} 条` : ''}${report.axesContext.selection === 'relevant' ? ' · 当前文档相关候选' : report.axesContext.selection === 'full' ? ' · 全集' : ''}`}</dd>
|
|
129
|
+
</div>
|
|
130
|
+
<div className={styles.trialRow}><dt>模型</dt><dd>{report.model?.model ? `${report.model.provider ? `${report.model.provider} / ` : ''}${report.model.model}${report.model.reasoningEffort ? ` · ${report.model.reasoningEffort}` : ''}` : '未记录'}</dd></div>
|
|
131
|
+
</dl>
|
|
132
|
+
</section>
|
|
133
|
+
</div>
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const KIND_LABEL: Record<string, string> = { object: '对象', action: '动作', scene: '场景' }
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react'
|
|
2
|
+
import { Button } from '@tita-agent/ui/components'
|
|
3
|
+
import type { PipelineStatus } from '../pipeline/types.js'
|
|
4
|
+
import { requestJson } from './request.ts'
|
|
5
|
+
|
|
6
|
+
export function PipelineNotice({ kb, revision, onOpen }: { kb: string; revision?: string; onOpen: () => void }) {
|
|
7
|
+
const [status, setStatus] = useState<PipelineStatus>()
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
let active = true
|
|
10
|
+
const refresh = (): void => { void requestJson<PipelineStatus>(`/knowledge/pipeline?kb=${encodeURIComponent(kb)}`).then(result => { if (active && result.data) setStatus(result.data) }).catch(() => undefined) }
|
|
11
|
+
refresh()
|
|
12
|
+
window.addEventListener('focus', refresh)
|
|
13
|
+
return () => { active = false; window.removeEventListener('focus', refresh) }
|
|
14
|
+
}, [kb, revision])
|
|
15
|
+
if (!status) return null
|
|
16
|
+
const pending = status.pendingNew + status.pendingUpdated + status.pendingWithdrawn
|
|
17
|
+
const parts = [
|
|
18
|
+
status.sources.filter(source => source.state === 'pending' || source.state === 'outdated').length,
|
|
19
|
+
status.sources.filter(source => source.state === 'extracted').length,
|
|
20
|
+
]
|
|
21
|
+
if (!parts.some(Boolean) && !pending && !status.indexPending) return null
|
|
22
|
+
return <div className="mx-3 flex min-w-0 items-center gap-2 border-b border-tita-line py-2 text-xs text-tita-ink-muted" role="status">
|
|
23
|
+
<span className="min-w-0 flex-1 leading-relaxed">{[parts[0] ? `${parts[0]} 份待抽取` : '', parts[1] ? `${parts[1]} 份待归一` : '', pending ? `${pending} 张 WikiCard 待物化` : '', status.indexPending ? '索引待更新' : ''].filter(Boolean).join(' · ')}</span>
|
|
24
|
+
<Button size="sm" variant="ghost" onClick={onOpen}>处理</Button>
|
|
25
|
+
</div>
|
|
26
|
+
}
|