oh-my-second-brain 0.2.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +41 -0
- package/{adapters/claude-code/.claude-plugin → .claude-plugin}/plugin.json +7 -8
- package/{adapters/codex/.codex-plugin → .codex-plugin}/plugin.json +4 -4
- package/ACKNOWLEDGMENTS.md +162 -0
- package/CHANGELOG-assets.md +23 -0
- package/CHANGELOG-cli.md +24 -0
- package/CHANGELOG-kernel.md +48 -0
- package/CHANGELOG-mcp.md +36 -0
- package/CHANGELOG-vendors.md +26 -0
- package/CHANGELOG.md +51 -7
- package/README.ko.md +2 -2
- package/README.md +16 -16
- package/{adapters/claude-code → assets/claude}/CLAUDE.md +4 -4
- package/{adapters → assets}/codex/AGENTS.md +3 -3
- package/{adapters → assets}/codex/rules/oms.md +5 -5
- package/{adapters → assets}/hermes/README.md +1 -1
- package/{adapters → assets}/hermes/SOUL.md +3 -3
- package/{adapters/hermes/manifest.json → assets/hermes-manifest.json} +3 -4
- package/assets/skills/distill/SKILL.md +20 -0
- package/assets/skills/doctor/SKILL.md +23 -0
- package/assets/skills/link/SKILL.md +24 -0
- package/assets/skills/search/SKILL.md +25 -0
- package/assets/skills/status/SKILL.md +22 -0
- package/assets/skills/write/SKILL.md +30 -0
- package/core/ontology/schemas/README.md +20 -14
- package/dist/assets/shared-skills.d.ts +4 -0
- package/dist/assets/shared-skills.js +8 -0
- package/dist/assets/shared-skills.js.map +1 -0
- package/dist/cli/args.d.ts +3 -1
- package/dist/cli/args.js +14 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/audit.js +3 -3
- package/dist/cli/audit.js.map +1 -1
- package/dist/cli/claude-install-plan.js +2 -2
- package/dist/cli/claude-install-plan.js.map +1 -1
- package/dist/cli/doctor-lint.js +8 -8
- package/dist/cli/doctor-lint.js.map +1 -1
- package/dist/cli/global-writeback.js +1 -1
- package/dist/cli/global-writeback.js.map +1 -1
- package/dist/cli/host-commands.d.ts +1 -1
- package/dist/cli/host-commands.js +24 -5
- package/dist/cli/host-commands.js.map +1 -1
- package/dist/cli/link-command.d.ts +1 -1
- package/dist/cli/link-command.js +2 -2
- package/dist/cli/link-command.js.map +1 -1
- package/dist/cli/linkify.js +16 -71
- package/dist/cli/linkify.js.map +1 -1
- package/dist/cli/oms.d.ts +1 -1
- package/dist/cli/oms.js +45 -11
- package/dist/cli/oms.js.map +1 -1
- package/dist/cli/semantic-args.d.ts +1 -1
- package/dist/cli/semantic-args.js +102 -3
- package/dist/cli/semantic-args.js.map +1 -1
- package/dist/cli/semantic-http.js +3 -3
- package/dist/cli/semantic-http.js.map +1 -1
- package/dist/cli/semantic-usage.js +1 -1
- package/dist/cli/semantic-usage.js.map +1 -1
- package/dist/cli/semantic.js +31 -12
- package/dist/cli/semantic.js.map +1 -1
- package/dist/cli/setup-command.d.ts +17 -0
- package/dist/cli/setup-command.js +89 -145
- package/dist/cli/setup-command.js.map +1 -1
- package/dist/cli/update-notice.d.ts +1 -1
- package/dist/cli/update-notice.js +2 -2
- package/dist/cli/update-notice.js.map +1 -1
- package/dist/cli/usage.d.ts +1 -1
- package/dist/cli/usage.js +2 -2
- package/dist/cli/usage.js.map +1 -1
- package/dist/{capture → kernel/capture}/safe.d.ts +11 -1
- package/dist/{capture → kernel/capture}/safe.js +3 -3
- package/dist/kernel/capture/safe.js.map +1 -0
- package/dist/kernel/contracts/index.d.ts +144 -0
- package/dist/kernel/contracts/index.js +401 -0
- package/dist/kernel/contracts/index.js.map +1 -0
- package/dist/kernel/conventions/frontmatter.js.map +1 -0
- package/dist/kernel/conventions/lint.js.map +1 -0
- package/dist/kernel/conventions/report.js.map +1 -0
- package/dist/{conventions → kernel/conventions}/validate.d.ts +1 -1
- package/dist/kernel/conventions/validate.js.map +1 -0
- package/dist/kernel/conventions/vault-walk.js.map +1 -0
- package/dist/{conventions → kernel/conventions}/write-contract.d.ts +1 -1
- package/dist/kernel/conventions/write-contract.js.map +1 -0
- package/dist/kernel/conventions/write-protocol.js.map +1 -0
- package/dist/kernel/doctor/service.d.ts +71 -0
- package/dist/kernel/doctor/service.js +70 -0
- package/dist/kernel/doctor/service.js.map +1 -0
- package/dist/{engine → kernel/engine}/assemble.d.ts +46 -1
- package/dist/kernel/engine/assemble.js +483 -0
- package/dist/kernel/engine/assemble.js.map +1 -0
- package/dist/kernel/engine/axes/store.d.ts +90 -0
- package/dist/kernel/engine/axes/store.js +400 -0
- package/dist/kernel/engine/axes/store.js.map +1 -0
- package/dist/{engine → kernel/engine}/conventions/vault-lint.d.ts +1 -1
- package/dist/{engine → kernel/engine}/conventions/vault-lint.js +1 -1
- package/dist/kernel/engine/conventions/vault-lint.js.map +1 -0
- package/dist/kernel/engine/embed/chunker.js.map +1 -0
- package/dist/kernel/engine/embed/deferred.js.map +1 -0
- package/dist/{engine → kernel/engine}/embed/hash-stub.test-helper.d.ts +1 -1
- package/dist/{engine → kernel/engine}/embed/hash-stub.test-helper.js +1 -1
- package/dist/kernel/engine/embed/hash-stub.test-helper.js.map +1 -0
- package/dist/kernel/engine/embed/identity.d.ts +21 -0
- package/dist/kernel/engine/embed/identity.js +47 -0
- package/dist/kernel/engine/embed/identity.js.map +1 -0
- package/dist/kernel/engine/embed/model.d.ts +134 -0
- package/dist/kernel/engine/embed/model.js +302 -0
- package/dist/kernel/engine/embed/model.js.map +1 -0
- package/dist/{engine → kernel/engine}/embed/provider.d.ts +36 -5
- package/dist/kernel/engine/embed/provider.js +403 -0
- package/dist/kernel/engine/embed/provider.js.map +1 -0
- package/dist/{engine → kernel/engine}/embed/store.d.ts +13 -1
- package/dist/kernel/engine/embed/store.js +730 -0
- package/dist/kernel/engine/embed/store.js.map +1 -0
- package/dist/kernel/engine/embed/sync.d.ts +100 -0
- package/dist/kernel/engine/embed/sync.js +753 -0
- package/dist/kernel/engine/embed/sync.js.map +1 -0
- package/dist/{engine → kernel/engine}/graph/builder.d.ts +9 -5
- package/dist/{engine → kernel/engine}/graph/builder.js +213 -79
- package/dist/kernel/engine/graph/builder.js.map +1 -0
- package/dist/kernel/engine/graph/explore.js.map +1 -0
- package/dist/{engine → kernel/engine}/graph/node.d.ts +49 -1
- package/dist/kernel/engine/graph/node.js +315 -0
- package/dist/kernel/engine/graph/node.js.map +1 -0
- package/dist/kernel/engine/graph/resolver.js.map +1 -0
- package/dist/kernel/engine/graph/traverse.js.map +1 -0
- package/dist/kernel/engine/linkify/apply.js.map +1 -0
- package/dist/kernel/engine/linkify/josa.js.map +1 -0
- package/dist/kernel/engine/linkify/mask.js.map +1 -0
- package/dist/kernel/engine/linkify/suggest.js.map +1 -0
- package/dist/kernel/engine/linkify/types.js.map +1 -0
- package/dist/{engine → kernel/engine}/mcp/facade.d.ts +27 -1
- package/dist/kernel/engine/mcp/facade.js +1144 -0
- package/dist/kernel/engine/mcp/facade.js.map +1 -0
- package/dist/kernel/engine/mcp/op-mappers.js.map +1 -0
- package/dist/{engine → kernel/engine}/mcp/query-mapper.d.ts +27 -2
- package/dist/kernel/engine/mcp/query-mapper.js +247 -0
- package/dist/kernel/engine/mcp/query-mapper.js.map +1 -0
- package/dist/{engine → kernel/engine}/mcp/types.d.ts +69 -2
- package/dist/kernel/engine/mcp/types.js.map +1 -0
- package/dist/{engine → kernel/engine}/retrieval/dispatcher.d.ts +23 -1
- package/dist/{engine → kernel/engine}/retrieval/dispatcher.js +92 -14
- package/dist/kernel/engine/retrieval/dispatcher.js.map +1 -0
- package/dist/{engine → kernel/engine}/retrieval/index.d.ts +4 -1
- package/dist/{engine → kernel/engine}/retrieval/index.js +6 -3
- package/dist/kernel/engine/retrieval/index.js.map +1 -0
- package/dist/kernel/engine/retrieval/reranker.d.ts +124 -0
- package/dist/kernel/engine/retrieval/reranker.js +204 -0
- package/dist/kernel/engine/retrieval/reranker.js.map +1 -0
- package/dist/{engine → kernel/engine}/retrieval/rrf.d.ts +10 -2
- package/dist/kernel/engine/retrieval/rrf.js +77 -0
- package/dist/kernel/engine/retrieval/rrf.js.map +1 -0
- package/dist/{engine → kernel/engine}/tracer.d.ts +13 -0
- package/dist/{engine → kernel/engine}/tracer.js +63 -6
- package/dist/kernel/engine/tracer.js.map +1 -0
- package/dist/{engine → kernel/engine}/types.d.ts +4 -4
- package/dist/kernel/engine/types.js.map +1 -0
- package/dist/{graph → kernel/graph}/cache.d.ts +1 -1
- package/dist/{graph → kernel/graph}/cache.js +165 -21
- package/dist/kernel/graph/cache.js.map +1 -0
- package/dist/kernel/graph/explore.js.map +1 -0
- package/dist/{harness → kernel/harness}/surface-registry.d.ts +0 -1
- package/dist/kernel/harness/surface-registry.js +170 -0
- package/dist/kernel/harness/surface-registry.js.map +1 -0
- package/dist/{harness → kernel/harness}/validation.js +67 -4
- package/dist/kernel/harness/validation.js.map +1 -0
- package/dist/kernel/index.d.ts +13 -0
- package/dist/kernel/index.js +14 -0
- package/dist/kernel/index.js.map +1 -0
- package/dist/{install → kernel/install}/adapter-source.d.ts +10 -1
- package/dist/kernel/install/adapter-source.js +76 -0
- package/dist/kernel/install/adapter-source.js.map +1 -0
- package/dist/kernel/install/common.js.map +1 -0
- package/dist/{install → kernel/install}/hosts.d.ts +3 -3
- package/dist/{install → kernel/install}/hosts.js +3 -22
- package/dist/kernel/install/hosts.js.map +1 -0
- package/dist/{core/ontology → kernel/install}/types.js.map +1 -1
- package/dist/{link → kernel/link}/convention-note.js +2 -2
- package/dist/kernel/link/convention-note.js.map +1 -0
- package/dist/kernel/link/global-config.js.map +1 -0
- package/dist/kernel/link/link.js.map +1 -0
- package/dist/kernel/link/workflow.d.ts +55 -0
- package/dist/kernel/link/workflow.js +107 -0
- package/dist/kernel/link/workflow.js.map +1 -0
- package/dist/kernel/measurement/no-default-contract.d.ts +17 -0
- package/dist/kernel/measurement/no-default-contract.js +84 -0
- package/dist/kernel/measurement/no-default-contract.js.map +1 -0
- package/dist/{ontology → kernel/ontology}/active.d.ts +1 -1
- package/dist/{ontology → kernel/ontology}/active.js +2 -2
- package/dist/kernel/ontology/active.js.map +1 -0
- package/dist/kernel/ontology/loader.js.map +1 -0
- package/dist/kernel/ontology/resolver.js.map +1 -0
- package/dist/{install → kernel/ontology}/types.js.map +1 -1
- package/dist/kernel/plugin/index.d.ts +1 -0
- package/dist/kernel/plugin/index.js +2 -0
- package/dist/kernel/plugin/index.js.map +1 -0
- package/dist/{core → kernel}/runtime/assets.d.ts +2 -4
- package/dist/{core → kernel}/runtime/assets.js +1 -3
- package/dist/kernel/runtime/assets.js.map +1 -0
- package/dist/kernel/search/morning-test-fixtures.js.map +1 -0
- package/dist/{retrieve → kernel/search}/morning.d.ts +0 -1
- package/dist/kernel/search/morning.js.map +1 -0
- package/dist/kernel/search/semantic-contract.js.map +1 -0
- package/dist/kernel/searchbackend/engine-search-backend.d.ts +28 -0
- package/dist/kernel/searchbackend/engine-search-backend.js +153 -0
- package/dist/kernel/searchbackend/engine-search-backend.js.map +1 -0
- package/dist/kernel/searchbackend/index.d.ts +2 -0
- package/dist/kernel/searchbackend/index.js +2 -0
- package/dist/kernel/searchbackend/index.js.map +1 -0
- package/dist/kernel/searchbackend/search-backend.d.ts +57 -0
- package/dist/kernel/searchbackend/search-backend.js +110 -0
- package/dist/kernel/searchbackend/search-backend.js.map +1 -0
- package/dist/{mcp → kernel/semantic}/semantic-engine.d.ts +3 -2
- package/dist/kernel/semantic/semantic-engine.js +78 -0
- package/dist/kernel/semantic/semantic-engine.js.map +1 -0
- package/dist/{mcp → kernel/semantic}/semantic-retrieve-args.d.ts +20 -3
- package/dist/{mcp → kernel/semantic}/semantic-retrieve-args.js +81 -15
- package/dist/kernel/semantic/semantic-retrieve-args.js.map +1 -0
- package/dist/{mcp → kernel/semantic}/semantic-retrieve-schema.d.ts +0 -24
- package/dist/{mcp → kernel/semantic}/semantic-retrieve-schema.js +0 -8
- package/dist/kernel/semantic/semantic-retrieve-schema.js.map +1 -0
- package/dist/{mcp → kernel/semantic}/semantic-retrieve.js +5 -9
- package/dist/kernel/semantic/semantic-retrieve.js.map +1 -0
- package/dist/kernel/semantic/semantic-schemas.js.map +1 -0
- package/dist/{mcp → kernel/semantic}/semantic-tool-schemas.js +0 -28
- package/dist/kernel/semantic/semantic-tool-schemas.js.map +1 -0
- package/dist/{setup → kernel/setup}/axis.d.ts +1 -1
- package/dist/{setup → kernel/setup}/axis.js +1 -1
- package/dist/kernel/setup/axis.js.map +1 -0
- package/dist/{cli/setup-documents.d.ts → kernel/setup/documents.d.ts} +1 -1
- package/dist/{cli/setup-documents.js → kernel/setup/documents.js} +15 -49
- package/dist/kernel/setup/documents.js.map +1 -0
- package/dist/kernel/setup/service.d.ts +44 -0
- package/dist/kernel/setup/service.js +97 -0
- package/dist/kernel/setup/service.js.map +1 -0
- package/dist/{update → kernel/update}/update.d.ts +7 -0
- package/dist/{update → kernel/update}/update.js +106 -8
- package/dist/kernel/update/update.js.map +1 -0
- package/dist/mcp/engine-morning-backend.d.ts +4 -4
- package/dist/mcp/engine-morning-backend.js +4 -18
- package/dist/mcp/engine-morning-backend.js.map +1 -1
- package/dist/mcp/link-tools.d.ts +9 -56
- package/dist/mcp/link-tools.js +5 -129
- package/dist/mcp/link-tools.js.map +1 -1
- package/dist/mcp/server.d.ts +9 -2
- package/dist/mcp/server.js +373 -324
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/update-notice.d.ts +1 -1
- package/dist/mcp/update-notice.js +1 -1
- package/dist/mcp/update-notice.js.map +1 -1
- package/dist/{install → vendors/claude}/claude-hooks.d.ts +1 -1
- package/dist/{install → vendors/claude}/claude-hooks.js +1 -1
- package/dist/vendors/claude/claude-hooks.js.map +1 -0
- package/dist/{install → vendors/claude}/claude-marketplace.d.ts +3 -3
- package/dist/{install → vendors/claude}/claude-marketplace.js +6 -9
- package/dist/vendors/claude/claude-marketplace.js.map +1 -0
- package/dist/{install → vendors/claude}/claude.d.ts +2 -2
- package/dist/{install → vendors/claude}/claude.js +2 -2
- package/dist/vendors/claude/claude.js.map +1 -0
- package/dist/{hook → vendors/claude/hook}/post-tool-use.js +5 -5
- package/dist/vendors/claude/hook/post-tool-use.js.map +1 -0
- package/dist/vendors/claude/hook/pre-tool-use.js.map +1 -0
- package/dist/vendors/claude/hook/stdin.js.map +1 -0
- package/dist/vendors/codex/codex.d.ts +10 -0
- package/dist/{install → vendors/codex}/codex.js +19 -37
- package/dist/vendors/codex/codex.js.map +1 -0
- package/dist/{install → vendors/hermes}/hermes.d.ts +2 -2
- package/dist/{install → vendors/hermes}/hermes.js +15 -7
- package/dist/vendors/hermes/hermes.js.map +1 -0
- package/docs/adapters.md +15 -0
- package/docs/install.md +10 -11
- package/package.json +23 -10
- package/adapters/README.md +0 -99
- package/adapters/claude-code/skills/compile/SKILL.md +0 -27
- package/adapters/claude-code/skills/define/SKILL.md +0 -51
- package/adapters/claude-code/skills/distill/SKILL.md +0 -28
- package/adapters/claude-code/skills/doctor/SKILL.md +0 -58
- package/adapters/claude-code/skills/link/SKILL.md +0 -87
- package/adapters/claude-code/skills/retrieve/SKILL.md +0 -99
- package/adapters/claude-code/skills/setup/SKILL.md +0 -78
- package/adapters/claude-code/skills/uninstall/SKILL.md +0 -34
- package/adapters/claude-code/skills/update/SKILL.md +0 -45
- package/adapters/claude-code/skills/vault-decision-record/SKILL.md +0 -52
- package/adapters/claude-code/skills/vault-lint/SKILL.md +0 -47
- package/adapters/claude-code/skills/vault-scaffold/SKILL.md +0 -47
- package/adapters/claude-code/skills/wiki/SKILL.md +0 -82
- package/adapters/claude-code/skills/write/SKILL.md +0 -16
- package/adapters/codex/skills/oms-compile/SKILL.md +0 -16
- package/adapters/codex/skills/oms-distill/SKILL.md +0 -14
- package/adapters/codex/skills/oms-doctor/SKILL.md +0 -14
- package/adapters/codex/skills/oms-install/SKILL.md +0 -19
- package/adapters/codex/skills/oms-link/SKILL.md +0 -35
- package/adapters/codex/skills/oms-retrieve/SKILL.md +0 -32
- package/adapters/codex/skills/oms-setup/SKILL.md +0 -34
- package/adapters/codex/skills/oms-uninstall/SKILL.md +0 -20
- package/adapters/codex/skills/oms-update/SKILL.md +0 -22
- package/adapters/codex/skills/oms-vault-lint/SKILL.md +0 -19
- package/adapters/codex/skills/oms-wiki/SKILL.md +0 -39
- package/adapters/codex/skills/oms-write/SKILL.md +0 -10
- package/adapters/hermes/skills/compile/SKILL.md +0 -13
- package/adapters/hermes/skills/distill/SKILL.md +0 -10
- package/adapters/hermes/skills/doctor/SKILL.md +0 -14
- package/adapters/hermes/skills/install/SKILL.md +0 -19
- package/adapters/hermes/skills/link/SKILL.md +0 -18
- package/adapters/hermes/skills/retrieve/SKILL.md +0 -32
- package/adapters/hermes/skills/setup/SKILL.md +0 -37
- package/adapters/hermes/skills/uninstall/SKILL.md +0 -20
- package/adapters/hermes/skills/update/SKILL.md +0 -22
- package/adapters/hermes/skills/wiki/SKILL.md +0 -14
- package/adapters/hermes/skills/write/SKILL.md +0 -10
- package/core/agents/librarian.md +0 -44
- package/core/agents/retriever.md +0 -62
- package/core/skills/compile/CHANGELOG.md +0 -24
- package/core/skills/compile/SKILL.md +0 -57
- package/core/skills/define/SKILL.md +0 -59
- package/core/skills/distill/CHANGELOG.md +0 -39
- package/core/skills/distill/SKILL.md +0 -62
- package/core/skills/doctor/SKILL.md +0 -49
- package/core/skills/link/SKILL.md +0 -130
- package/core/skills/retrieve/SKILL.md +0 -78
- package/core/skills/setup/CHANGELOG.md +0 -49
- package/core/skills/setup/SKILL.md +0 -246
- package/core/skills/uninstall/SKILL.md +0 -34
- package/core/skills/vault-decision-record/CHANGELOG.md +0 -24
- package/core/skills/vault-decision-record/SKILL.md +0 -93
- package/core/skills/vault-lint/CHANGELOG.md +0 -35
- package/core/skills/vault-lint/SKILL.md +0 -58
- package/core/skills/vault-scaffold/CHANGELOG.md +0 -21
- package/core/skills/vault-scaffold/SKILL.md +0 -72
- package/core/skills/wiki/CHANGELOG.md +0 -23
- package/core/skills/wiki/SKILL.md +0 -159
- package/core/skills/write/SKILL.md +0 -15
- package/dist/capture/safe.js.map +0 -1
- package/dist/cli/setup-documents.js.map +0 -1
- package/dist/conventions/frontmatter.js.map +0 -1
- package/dist/conventions/lint.js.map +0 -1
- package/dist/conventions/report.js.map +0 -1
- package/dist/conventions/validate.js.map +0 -1
- package/dist/conventions/vault-walk.js.map +0 -1
- package/dist/conventions/write-contract.js.map +0 -1
- package/dist/conventions/write-protocol.js.map +0 -1
- package/dist/core/ontology/loader.js.map +0 -1
- package/dist/core/ontology/resolver.js.map +0 -1
- package/dist/core/runtime/assets.js.map +0 -1
- package/dist/engine/assemble.js +0 -162
- package/dist/engine/assemble.js.map +0 -1
- package/dist/engine/conventions/vault-lint.js.map +0 -1
- package/dist/engine/embed/chunker.js.map +0 -1
- package/dist/engine/embed/deferred.js.map +0 -1
- package/dist/engine/embed/hash-stub.test-helper.js.map +0 -1
- package/dist/engine/embed/identity.d.ts +0 -11
- package/dist/engine/embed/identity.js +0 -15
- package/dist/engine/embed/identity.js.map +0 -1
- package/dist/engine/embed/provider.js +0 -266
- package/dist/engine/embed/provider.js.map +0 -1
- package/dist/engine/embed/store.js +0 -416
- package/dist/engine/embed/store.js.map +0 -1
- package/dist/engine/embed/sync.d.ts +0 -45
- package/dist/engine/embed/sync.js +0 -321
- package/dist/engine/embed/sync.js.map +0 -1
- package/dist/engine/graph/builder.js.map +0 -1
- package/dist/engine/graph/explore.js.map +0 -1
- package/dist/engine/graph/node.js +0 -110
- package/dist/engine/graph/node.js.map +0 -1
- package/dist/engine/graph/resolver.js.map +0 -1
- package/dist/engine/graph/traverse.js.map +0 -1
- package/dist/engine/linkify/apply.js.map +0 -1
- package/dist/engine/linkify/josa.js.map +0 -1
- package/dist/engine/linkify/mask.js.map +0 -1
- package/dist/engine/linkify/suggest.js.map +0 -1
- package/dist/engine/linkify/types.js.map +0 -1
- package/dist/engine/mcp/facade.js +0 -628
- package/dist/engine/mcp/facade.js.map +0 -1
- package/dist/engine/mcp/op-mappers.js.map +0 -1
- package/dist/engine/mcp/query-mapper.js +0 -102
- package/dist/engine/mcp/query-mapper.js.map +0 -1
- package/dist/engine/mcp/types.js.map +0 -1
- package/dist/engine/retrieval/dispatcher.js.map +0 -1
- package/dist/engine/retrieval/index.js.map +0 -1
- package/dist/engine/retrieval/reranker.d.ts +0 -46
- package/dist/engine/retrieval/reranker.js +0 -29
- package/dist/engine/retrieval/reranker.js.map +0 -1
- package/dist/engine/retrieval/rrf.js +0 -54
- package/dist/engine/retrieval/rrf.js.map +0 -1
- package/dist/engine/tracer.js.map +0 -1
- package/dist/engine/types.js.map +0 -1
- package/dist/graph/cache.js.map +0 -1
- package/dist/graph/explore.js.map +0 -1
- package/dist/harness/surface-registry.js +0 -397
- package/dist/harness/surface-registry.js.map +0 -1
- package/dist/harness/validation.js.map +0 -1
- package/dist/hook/post-tool-use.js.map +0 -1
- package/dist/hook/pre-tool-use.js.map +0 -1
- package/dist/hook/stdin.js.map +0 -1
- package/dist/index.d.ts +0 -12
- package/dist/index.js +0 -13
- package/dist/index.js.map +0 -1
- package/dist/install/adapter-source.js +0 -45
- package/dist/install/adapter-source.js.map +0 -1
- package/dist/install/claude-hooks.js.map +0 -1
- package/dist/install/claude-marketplace.js.map +0 -1
- package/dist/install/claude.js.map +0 -1
- package/dist/install/codex.d.ts +0 -24
- package/dist/install/codex.js.map +0 -1
- package/dist/install/common.js.map +0 -1
- package/dist/install/hermes.js.map +0 -1
- package/dist/install/hosts.js.map +0 -1
- package/dist/link/convention-note.js.map +0 -1
- package/dist/link/global-config.js.map +0 -1
- package/dist/link/link.js.map +0 -1
- package/dist/mcp/semantic-engine.js +0 -52
- package/dist/mcp/semantic-engine.js.map +0 -1
- package/dist/mcp/semantic-retrieve-args.js.map +0 -1
- package/dist/mcp/semantic-retrieve-schema.js.map +0 -1
- package/dist/mcp/semantic-retrieve.js.map +0 -1
- package/dist/mcp/semantic-schemas.js.map +0 -1
- package/dist/mcp/semantic-tool-schemas.js.map +0 -1
- package/dist/ontology/active.js.map +0 -1
- package/dist/retrieve/morning-test-fixtures.js.map +0 -1
- package/dist/retrieve/morning.js.map +0 -1
- package/dist/retrieve/semantic-contract.js.map +0 -1
- package/dist/setup/axis.js.map +0 -1
- package/dist/update/update.js.map +0 -1
- package/docs/release.md +0 -188
- /package/{adapters/codex/.mcp.json → .mcp.codex.json} +0 -0
- /package/{adapters/claude-code/.mcp.json → .mcp.json} +0 -0
- /package/{adapters/claude-code → assets/claude}/hooks/oms-guard.mjs +0 -0
- /package/{adapters/claude-code → assets/claude}/hooks/oms-post-guard.mjs +0 -0
- /package/dist/{conventions → kernel/conventions}/frontmatter.d.ts +0 -0
- /package/dist/{conventions → kernel/conventions}/frontmatter.js +0 -0
- /package/dist/{conventions → kernel/conventions}/lint.d.ts +0 -0
- /package/dist/{conventions → kernel/conventions}/lint.js +0 -0
- /package/dist/{conventions → kernel/conventions}/report.d.ts +0 -0
- /package/dist/{conventions → kernel/conventions}/report.js +0 -0
- /package/dist/{conventions → kernel/conventions}/validate.js +0 -0
- /package/dist/{conventions → kernel/conventions}/vault-walk.d.ts +0 -0
- /package/dist/{conventions → kernel/conventions}/vault-walk.js +0 -0
- /package/dist/{conventions → kernel/conventions}/write-contract.js +0 -0
- /package/dist/{conventions → kernel/conventions}/write-protocol.d.ts +0 -0
- /package/dist/{conventions → kernel/conventions}/write-protocol.js +0 -0
- /package/dist/{engine → kernel/engine}/embed/chunker.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/embed/chunker.js +0 -0
- /package/dist/{engine → kernel/engine}/embed/deferred.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/embed/deferred.js +0 -0
- /package/dist/{engine → kernel/engine}/graph/explore.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/graph/explore.js +0 -0
- /package/dist/{engine → kernel/engine}/graph/resolver.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/graph/resolver.js +0 -0
- /package/dist/{engine → kernel/engine}/graph/traverse.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/graph/traverse.js +0 -0
- /package/dist/{engine → kernel/engine}/linkify/apply.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/linkify/apply.js +0 -0
- /package/dist/{engine → kernel/engine}/linkify/josa.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/linkify/josa.js +0 -0
- /package/dist/{engine → kernel/engine}/linkify/mask.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/linkify/mask.js +0 -0
- /package/dist/{engine → kernel/engine}/linkify/suggest.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/linkify/suggest.js +0 -0
- /package/dist/{engine → kernel/engine}/linkify/types.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/linkify/types.js +0 -0
- /package/dist/{engine → kernel/engine}/mcp/op-mappers.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/mcp/op-mappers.js +0 -0
- /package/dist/{engine → kernel/engine}/mcp/types.js +0 -0
- /package/dist/{engine → kernel/engine}/types.js +0 -0
- /package/dist/{graph → kernel/graph}/explore.d.ts +0 -0
- /package/dist/{graph → kernel/graph}/explore.js +0 -0
- /package/dist/{harness → kernel/harness}/validation.d.ts +0 -0
- /package/dist/{install → kernel/install}/common.d.ts +0 -0
- /package/dist/{install → kernel/install}/common.js +0 -0
- /package/dist/{install → kernel/install}/types.d.ts +0 -0
- /package/dist/{core/ontology → kernel/install}/types.js +0 -0
- /package/dist/{link → kernel/link}/convention-note.d.ts +0 -0
- /package/dist/{link → kernel/link}/global-config.d.ts +0 -0
- /package/dist/{link → kernel/link}/global-config.js +0 -0
- /package/dist/{link → kernel/link}/link.d.ts +0 -0
- /package/dist/{link → kernel/link}/link.js +0 -0
- /package/dist/{core → kernel}/ontology/loader.d.ts +0 -0
- /package/dist/{core → kernel}/ontology/loader.js +0 -0
- /package/dist/{core → kernel}/ontology/resolver.d.ts +0 -0
- /package/dist/{core → kernel}/ontology/resolver.js +0 -0
- /package/dist/{core → kernel}/ontology/types.d.ts +0 -0
- /package/dist/{install → kernel/ontology}/types.js +0 -0
- /package/dist/{retrieve → kernel/search}/morning-test-fixtures.d.ts +0 -0
- /package/dist/{retrieve → kernel/search}/morning-test-fixtures.js +0 -0
- /package/dist/{retrieve → kernel/search}/morning.js +0 -0
- /package/dist/{retrieve → kernel/search}/semantic-contract.d.ts +0 -0
- /package/dist/{retrieve → kernel/search}/semantic-contract.js +0 -0
- /package/dist/{mcp → kernel/semantic}/semantic-retrieve.d.ts +0 -0
- /package/dist/{mcp → kernel/semantic}/semantic-schemas.d.ts +0 -0
- /package/dist/{mcp → kernel/semantic}/semantic-schemas.js +0 -0
- /package/dist/{mcp → kernel/semantic}/semantic-tool-schemas.d.ts +0 -0
- /package/dist/{hook → vendors/claude/hook}/post-tool-use.d.ts +0 -0
- /package/dist/{hook → vendors/claude/hook}/pre-tool-use.d.ts +0 -0
- /package/dist/{hook → vendors/claude/hook}/pre-tool-use.js +0 -0
- /package/dist/{hook → vendors/claude/hook}/stdin.d.ts +0 -0
- /package/dist/{hook → vendors/claude/hook}/stdin.js +0 -0
package/dist/mcp/server.js
CHANGED
|
@@ -2,24 +2,27 @@ import { readFile } from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
-
import { CallToolRequestSchema,
|
|
6
|
-
import { parseNote } from "../conventions/frontmatter.js";
|
|
7
|
-
import { validateFrontmatter } from "../conventions/validate.js";
|
|
8
|
-
import { lintVault } from "../engine/conventions/vault-lint.js";
|
|
9
|
-
import { safeVaultNotePath, writeNote, } from "../capture/safe.js";
|
|
10
|
-
import {
|
|
11
|
-
import { readBundledPackageVersion } from "../
|
|
12
|
-
import { resolveActiveOntology } from "../ontology/active.js";
|
|
13
|
-
import { resolveConcept } from "../
|
|
14
|
-
import { retrieveMorningContext } from "../
|
|
5
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
+
import { parseNote } from "../kernel/conventions/frontmatter.js";
|
|
7
|
+
import { validateFrontmatter } from "../kernel/conventions/validate.js";
|
|
8
|
+
import { lintVault } from "../kernel/engine/conventions/vault-lint.js";
|
|
9
|
+
import { safeVaultNotePath, writeNote, } from "../kernel/capture/safe.js";
|
|
10
|
+
import { graphCacheStatus, lazyLoadNoteBody, } from "../kernel/graph/cache.js";
|
|
11
|
+
import { readBundledPackageVersion } from "../kernel/runtime/assets.js";
|
|
12
|
+
import { resolveActiveOntology } from "../kernel/ontology/active.js";
|
|
13
|
+
import { resolveConcept } from "../kernel/ontology/resolver.js";
|
|
14
|
+
import { retrieveMorningContext } from "../kernel/search/morning.js";
|
|
15
|
+
import { repairDoctor } from "../kernel/doctor/service.js";
|
|
15
16
|
import { makeEngineMorningBackend } from "./engine-morning-backend.js";
|
|
16
|
-
import { handleSemanticTool, isEngineSemanticOp, isEngineDocumentOp, isModelOptionalSemanticQueryOp,
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
17
|
+
import { handleSemanticTool, isEngineSemanticOp, isEngineDocumentOp, isModelOptionalSemanticQueryOp, semanticOptionsFromArgs, } from "../kernel/semantic/semantic-retrieve.js";
|
|
18
|
+
import { semanticQueryOptionsFromArgs } from "../kernel/semantic/semantic-retrieve-args.js";
|
|
19
|
+
import { assembleEphemeralCoreSemanticEngine, assembleCoreSemanticEngineReadOnly, assembleCoreSemanticEngine, assembleEngineReadOnly, assembleGraphOnlyEngine, } from "../kernel/engine/assemble.js";
|
|
20
|
+
import { assembleFullSemanticEngine, embeddingConfigPresent, } from "../kernel/semantic/semantic-engine.js";
|
|
19
21
|
import { applyLinksForNote, linkApplyPayload, suggestLinksForNote } from "./link-tools.js";
|
|
22
|
+
import { EngineSearchBackend, requiresEmbeddings } from "../kernel/searchbackend/engine-search-backend.js";
|
|
20
23
|
import { buildServerInstructions, cachedUpdateNotice, scheduleUpdateNoticeRefresh, } from "./update-notice.js";
|
|
21
24
|
const SERVER_VERSION = readBundledPackageVersion();
|
|
22
|
-
export const BASE_SERVER_INSTRUCTIONS = "Oh My Second Brain exposes
|
|
25
|
+
export const BASE_SERVER_INSTRUCTIONS = "Oh My Second Brain exposes write, search, link, status, and doctor tools. oms_write and doctor repair operations are gated by a verified vault target (a vault inferred from the current directory is refused); oms_write also enforces vault confinement and contract validation.";
|
|
23
26
|
function jsonText(value) {
|
|
24
27
|
return {
|
|
25
28
|
content: [
|
|
@@ -41,6 +44,11 @@ function errorText(message) {
|
|
|
41
44
|
],
|
|
42
45
|
};
|
|
43
46
|
}
|
|
47
|
+
class SemanticIndexUnavailableError extends Error {
|
|
48
|
+
constructor() {
|
|
49
|
+
super("The semantic index has not been built yet. Run `oms semantic sync` to build it.");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
44
52
|
function isRecord(value) {
|
|
45
53
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
46
54
|
}
|
|
@@ -66,246 +74,89 @@ function conceptSummary(concept) {
|
|
|
66
74
|
})),
|
|
67
75
|
};
|
|
68
76
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
inputSchema: {
|
|
90
|
-
type: "object",
|
|
91
|
-
properties: {},
|
|
92
|
-
},
|
|
93
|
-
annotations: {
|
|
94
|
-
readOnlyHint: false,
|
|
95
|
-
destructiveHint: false,
|
|
96
|
-
idempotentHint: true,
|
|
97
|
-
openWorldHint: false,
|
|
98
|
-
},
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
name: "oms_list_concepts",
|
|
102
|
-
title: "Oh My Second Brain list concepts",
|
|
103
|
-
description: "Read the active ontology concepts, frontmatter axes, folder bindings, and retrieval views.",
|
|
104
|
-
inputSchema: {
|
|
105
|
-
type: "object",
|
|
106
|
-
properties: {},
|
|
107
|
-
},
|
|
108
|
-
annotations: {
|
|
109
|
-
readOnlyHint: true,
|
|
110
|
-
destructiveHint: false,
|
|
111
|
-
idempotentHint: true,
|
|
112
|
-
openWorldHint: false,
|
|
113
|
-
},
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
name: "oms_retrieve_by_axis",
|
|
117
|
-
title: "Oh My Second Brain retrieve by axis",
|
|
118
|
-
description: "Axis-first retrieval over the derived cache; optional lexical query only ranks inside the narrowed candidate set.",
|
|
119
|
-
inputSchema: {
|
|
120
|
-
type: "object",
|
|
121
|
-
properties: {
|
|
122
|
-
concept: { type: "string" },
|
|
123
|
-
folder: { type: "string" },
|
|
124
|
-
property: { type: "string" },
|
|
125
|
-
value: { type: "string" },
|
|
126
|
-
wikilink: { type: "string" },
|
|
127
|
-
query: { type: "string" },
|
|
128
|
-
limit: { type: "number" },
|
|
129
|
-
},
|
|
130
|
-
},
|
|
131
|
-
annotations: {
|
|
132
|
-
readOnlyHint: true,
|
|
133
|
-
destructiveHint: false,
|
|
134
|
-
idempotentHint: true,
|
|
135
|
-
openWorldHint: false,
|
|
136
|
-
},
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
name: "oms_retrieve_context",
|
|
140
|
-
title: "Oh My Second Brain retrieve context",
|
|
141
|
-
description: "Live local graph retrieval with axis seeds, frontmatter/wikilink neighbors, optional OMS semantic candidates, and no warm-cache requirement.",
|
|
142
|
-
inputSchema: {
|
|
143
|
-
type: "object",
|
|
144
|
-
properties: {
|
|
145
|
-
concept: { type: "string" },
|
|
146
|
-
folder: { type: "string" },
|
|
147
|
-
property: { type: "string" },
|
|
148
|
-
value: { type: "string" },
|
|
149
|
-
wikilink: { type: "string" },
|
|
150
|
-
query: { type: "string" },
|
|
151
|
-
limit: { type: "number" },
|
|
152
|
-
maxNeighbors: { type: "number" },
|
|
153
|
-
useCache: { type: "boolean" },
|
|
154
|
-
...retrieveContextSemanticInputProperties,
|
|
155
|
-
},
|
|
156
|
-
},
|
|
157
|
-
annotations: {
|
|
158
|
-
readOnlyHint: false,
|
|
159
|
-
destructiveHint: false,
|
|
160
|
-
idempotentHint: true,
|
|
161
|
-
openWorldHint: false,
|
|
162
|
-
},
|
|
163
|
-
},
|
|
164
|
-
...semanticMcpTools,
|
|
165
|
-
{
|
|
166
|
-
name: "oms_lazy_load_note",
|
|
167
|
-
title: "Oh My Second Brain lazy-load note body",
|
|
168
|
-
description: "Load a selected note body only after axis/search narrowing has selected the note.",
|
|
169
|
-
inputSchema: {
|
|
170
|
-
type: "object",
|
|
171
|
-
properties: {
|
|
172
|
-
notePath: {
|
|
173
|
-
type: "string",
|
|
174
|
-
description: "Vault-relative markdown note path.",
|
|
175
|
-
},
|
|
176
|
-
},
|
|
177
|
-
required: ["notePath"],
|
|
178
|
-
},
|
|
179
|
-
annotations: {
|
|
180
|
-
readOnlyHint: true,
|
|
181
|
-
destructiveHint: false,
|
|
182
|
-
idempotentHint: true,
|
|
183
|
-
openWorldHint: false,
|
|
184
|
-
},
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
name: "oms_validate_contract",
|
|
188
|
-
title: "Oh My Second Brain validate contract",
|
|
189
|
-
description: "Read one vault note and validate its frontmatter against the active folder/concept contract.",
|
|
190
|
-
inputSchema: {
|
|
191
|
-
type: "object",
|
|
192
|
-
properties: {
|
|
193
|
-
notePath: {
|
|
194
|
-
type: "string",
|
|
195
|
-
description: "Vault-relative markdown note path, for example references/book.md.",
|
|
196
|
-
},
|
|
197
|
-
},
|
|
198
|
-
required: ["notePath"],
|
|
199
|
-
},
|
|
200
|
-
annotations: {
|
|
201
|
-
readOnlyHint: true,
|
|
202
|
-
destructiveHint: false,
|
|
203
|
-
idempotentHint: true,
|
|
204
|
-
openWorldHint: false,
|
|
205
|
-
},
|
|
206
|
-
},
|
|
207
|
-
{
|
|
208
|
-
name: "oms_vault_audit",
|
|
209
|
-
title: "Oh My Second Brain vault audit",
|
|
210
|
-
description: "Scan vault notes against the active ontology and return a structured violation report. Read-only; the CLI counterpart is `oms audit`.",
|
|
211
|
-
inputSchema: {
|
|
212
|
-
type: "object",
|
|
213
|
-
properties: {
|
|
214
|
-
folder: {
|
|
215
|
-
type: "string",
|
|
216
|
-
description: "Restrict the scan to one top-level vault folder, for example \"references\".",
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
},
|
|
220
|
-
annotations: {
|
|
221
|
-
readOnlyHint: true,
|
|
222
|
-
destructiveHint: false,
|
|
223
|
-
idempotentHint: true,
|
|
224
|
-
openWorldHint: false,
|
|
225
|
-
},
|
|
226
|
-
},
|
|
227
|
-
{
|
|
228
|
-
name: "oms_link_suggest",
|
|
229
|
-
title: "Oh My Second Brain link suggest",
|
|
230
|
-
description: "Propose [[wikilink]] insertions for one note against the vault's term notes. Read-only: returns ranked candidates plus the baseContentHash oms_link_apply requires.",
|
|
231
|
-
inputSchema: {
|
|
232
|
-
type: "object",
|
|
233
|
-
properties: {
|
|
234
|
-
notePath: {
|
|
235
|
-
type: "string",
|
|
236
|
-
description: "Vault-relative markdown note path to linkify, for example notes/sage.md.",
|
|
237
|
-
},
|
|
238
|
-
folder: {
|
|
239
|
-
type: "string",
|
|
240
|
-
description: "Restrict the term-note candidate universe to one top-level vault folder.",
|
|
241
|
-
},
|
|
242
|
-
},
|
|
243
|
-
required: ["notePath"],
|
|
244
|
-
},
|
|
245
|
-
annotations: {
|
|
246
|
-
readOnlyHint: true,
|
|
247
|
-
destructiveHint: false,
|
|
248
|
-
idempotentHint: true,
|
|
249
|
-
openWorldHint: false,
|
|
250
|
-
},
|
|
77
|
+
const string = { type: "string" };
|
|
78
|
+
const number = { type: "number" };
|
|
79
|
+
const boolean = { type: "boolean" };
|
|
80
|
+
const stringArray = { type: "array", items: string };
|
|
81
|
+
const axisScalar = { anyOf: [string, number, boolean] };
|
|
82
|
+
const axisValue = { anyOf: [axisScalar, { type: "array", items: axisScalar }] };
|
|
83
|
+
const fieldPredicate = {
|
|
84
|
+
type: "object",
|
|
85
|
+
additionalProperties: false,
|
|
86
|
+
properties: {
|
|
87
|
+
contains: axisValue,
|
|
88
|
+
containsAll: { type: "array", items: axisScalar },
|
|
89
|
+
in: { type: "array", items: axisScalar },
|
|
90
|
+
between: { type: "array", items: axisScalar, minItems: 2, maxItems: 2 },
|
|
91
|
+
gte: axisScalar,
|
|
92
|
+
gt: axisScalar,
|
|
93
|
+
lte: axisScalar,
|
|
94
|
+
lt: axisScalar,
|
|
95
|
+
from: axisScalar,
|
|
96
|
+
to: axisScalar,
|
|
251
97
|
},
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
98
|
+
};
|
|
99
|
+
const queryAxes = {
|
|
100
|
+
type: "object",
|
|
101
|
+
additionalProperties: false,
|
|
102
|
+
properties: {
|
|
103
|
+
folder: axisValue,
|
|
104
|
+
field: {
|
|
257
105
|
type: "object",
|
|
258
|
-
|
|
259
|
-
notePath: {
|
|
260
|
-
type: "string",
|
|
261
|
-
description: "Vault-relative markdown note path returned by oms_link_suggest.",
|
|
262
|
-
},
|
|
263
|
-
baseContentHash: {
|
|
264
|
-
type: "string",
|
|
265
|
-
description: "The baseContentHash from the oms_link_suggest call the candidates came from.",
|
|
266
|
-
},
|
|
267
|
-
candidateIds: {
|
|
268
|
-
type: "array",
|
|
269
|
-
items: { type: "string" },
|
|
270
|
-
description: "Ids of the accepted candidates from that same oms_link_suggest call.",
|
|
271
|
-
},
|
|
272
|
-
folder: {
|
|
273
|
-
type: "string",
|
|
274
|
-
description: "Same candidate-universe folder scope used for the suggest call.",
|
|
275
|
-
},
|
|
276
|
-
},
|
|
277
|
-
required: ["notePath", "baseContentHash", "candidateIds"],
|
|
278
|
-
},
|
|
279
|
-
annotations: {
|
|
280
|
-
readOnlyHint: false,
|
|
281
|
-
destructiveHint: true,
|
|
282
|
-
idempotentHint: false,
|
|
283
|
-
openWorldHint: false,
|
|
284
|
-
},
|
|
285
|
-
},
|
|
286
|
-
{
|
|
287
|
-
name: "write",
|
|
288
|
-
title: "Oh My Second Brain write",
|
|
289
|
-
description: "Write a vault note through the kernel-owned .oms contract. Modes: create, append, update. Returns ask, inbox, written, or rejected.",
|
|
290
|
-
inputSchema: {
|
|
291
|
-
type: "object",
|
|
292
|
-
properties: {
|
|
293
|
-
mode: { type: "string", enum: ["create", "append", "update"] },
|
|
294
|
-
notePath: { type: "string" },
|
|
295
|
-
concept: { type: "string" },
|
|
296
|
-
folder: { type: "string" },
|
|
297
|
-
filename: { type: "string" },
|
|
298
|
-
frontmatter: { type: "object" },
|
|
299
|
-
body: { type: "string" },
|
|
300
|
-
},
|
|
301
|
-
},
|
|
302
|
-
annotations: {
|
|
303
|
-
readOnlyHint: false,
|
|
304
|
-
destructiveHint: false,
|
|
305
|
-
idempotentHint: false,
|
|
306
|
-
openWorldHint: false,
|
|
106
|
+
additionalProperties: { anyOf: [axisValue, fieldPredicate] },
|
|
307
107
|
},
|
|
108
|
+
link: axisValue,
|
|
308
109
|
},
|
|
110
|
+
};
|
|
111
|
+
const searchProperties = {
|
|
112
|
+
query: string, searches: { type: "array", maxItems: 10, items: { type: "object", properties: { type: { ...string, enum: ["lex", "vec", "hyde"] }, query: string }, required: ["type", "query"] } },
|
|
113
|
+
collection: string, collections: stringArray, mode: { ...string, enum: ["query", "search", "vsearch"] }, limit: { ...number, minimum: 0, default: 10 }, candidateLimit: { ...number, minimum: 1 }, rerank: { ...boolean, default: false }, minScore: { ...number, default: 0 }, cursor: string, axes: queryAxes, intent: string, lex: string, vec: string, hyde: string, index: string,
|
|
114
|
+
target: string, targets: stringArray, fromLine: number, lineCount: number, lineLimit: number, maxBytes: number, lineNumbers: boolean, fullPath: boolean,
|
|
115
|
+
};
|
|
116
|
+
const contextProperties = { concept: string, folder: string, property: string, value: string, wikilink: string, query: string, limit: number, maxNeighbors: number, useCache: boolean,
|
|
117
|
+
semanticEnabled: boolean, semanticCollection: string, semanticLimit: number, semanticScope: { ...string, enum: ["global", "graph"] }, semanticMode: searchProperties.mode, semanticIntent: string, semanticSearches: searchProperties.searches, semanticLex: string, semanticVec: string, semanticHyde: string, semanticMinScore: number, semanticAll: boolean, semanticFormat: { ...string, enum: ["json", "files"] }, semanticFull: boolean, semanticLineNumbers: boolean, semanticFullPath: boolean, semanticIndex: string, semanticChunkStrategy: string, semanticCandidateLimit: number, semanticNoRerank: boolean, semanticHydrate: { ...string, enum: ["none", "top", "all", "targets"] }, semanticHydrateTargets: stringArray, semanticHydrateLineLimit: number, semanticHydrateMaxBytes: number, semanticHydrateFromLine: number, semanticHydrateLineCount: number };
|
|
118
|
+
// `folder` + `filename` is a supported addressing form that writeNote still
|
|
119
|
+
// accepts. With `additionalProperties: false` a strict schema is only as
|
|
120
|
+
// complete as its property list, so omitting them silently removed a real
|
|
121
|
+
// capability from every schema-driven client while raw SDK calls kept working.
|
|
122
|
+
const writeProperties = {
|
|
123
|
+
notePath: string,
|
|
124
|
+
folder: string,
|
|
125
|
+
filename: string,
|
|
126
|
+
concept: string,
|
|
127
|
+
frontmatter: { type: "object" },
|
|
128
|
+
body: string,
|
|
129
|
+
};
|
|
130
|
+
const operations = {
|
|
131
|
+
oms_write: [
|
|
132
|
+
{ op: "create", name: "write", properties: writeProperties },
|
|
133
|
+
{ op: "append", name: "write", properties: writeProperties },
|
|
134
|
+
{ op: "update", name: "write", properties: writeProperties },
|
|
135
|
+
],
|
|
136
|
+
oms_search: [{ op: "context", name: "oms_retrieve_context", properties: contextProperties }, { op: "lazy-load", name: "oms_lazy_load_note", properties: { notePath: string }, required: ["notePath"] }, { op: "concepts", name: "oms_list_concepts" }, { op: "query", name: "oms_semantic_query", properties: searchProperties }, { op: "collections", name: "oms_semantic_collections", properties: { index: string } }, { op: "contexts", name: "oms_semantic_contexts", properties: { index: string } }, { op: "status", name: "oms_semantic_status", properties: { index: string } }, { op: "get-document", name: "oms_get_document", properties: searchProperties, required: ["target"] }, { op: "multi-get-documents", name: "oms_multi_get_documents", properties: searchProperties }],
|
|
137
|
+
oms_link: [{ op: "suggest", name: "oms_link_suggest", properties: { notePath: string, folder: string }, required: ["notePath"] }, { op: "apply", name: "oms_link_apply", properties: { notePath: string, folder: string, baseContentHash: string, candidateIds: stringArray }, required: ["notePath", "baseContentHash", "candidateIds"] }],
|
|
138
|
+
oms_status: [{ name: "oms_graph_status", direct: true }],
|
|
139
|
+
oms_doctor: [{ op: "audit", name: "oms_vault_audit", properties: { folder: string } }, { op: "validate", name: "oms_validate_contract", properties: { notePath: string }, required: ["notePath"] }, { op: "build-graph", name: "oms_graph_build" }, { op: "cleanup", name: "oms_semantic_cleanup", properties: { collection: string, index: string } }, { op: "sync-embeddings", name: "oms_sync_embeddings", properties: { collection: string, ensureCollection: boolean, update: boolean, embed: boolean, force: boolean, pull: boolean, index: string, chunkStrategy: string, maxDocsPerBatch: number, maxBatchMb: number } }],
|
|
140
|
+
};
|
|
141
|
+
function operationSchema(tool) {
|
|
142
|
+
const toolOperations = operations[tool];
|
|
143
|
+
if (!toolOperations)
|
|
144
|
+
throw new Error(`Missing MCP operation definition for ${tool}.`);
|
|
145
|
+
if (toolOperations.length === 1 && toolOperations[0]?.direct) {
|
|
146
|
+
const { properties = {}, required = [] } = toolOperations[0];
|
|
147
|
+
return { type: "object", additionalProperties: false, properties, required: [...required] };
|
|
148
|
+
}
|
|
149
|
+
return { type: "object", oneOf: toolOperations.map(({ op, properties = {}, required = [] }) => ({ additionalProperties: false, properties: { op: { ...string, const: op }, ...properties }, required: ["op", ...required] })) };
|
|
150
|
+
}
|
|
151
|
+
function resolveOperation(tool, op) {
|
|
152
|
+
return operations[tool]?.find((operation) => operation.direct || operation.op === op)?.name;
|
|
153
|
+
}
|
|
154
|
+
export const omsMcpTools = [
|
|
155
|
+
{ name: "oms_write", title: "Oh My Second Brain write", description: "Write a vault note through the kernel-owned .oms contract.", inputSchema: operationSchema("oms_write"), annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false } },
|
|
156
|
+
{ name: "oms_search", title: "Oh My Second Brain search", description: "Retrieve vault context, semantic search, ontology, and selected documents. `op` selects the operation.", inputSchema: operationSchema("oms_search"), annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: false, openWorldHint: false } },
|
|
157
|
+
{ name: "oms_link", title: "Oh My Second Brain link", description: "Suggest or apply wikilinks; `op` selects the operation.", inputSchema: operationSchema("oms_link"), annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false } },
|
|
158
|
+
{ name: "oms_status", title: "Oh My Second Brain status", description: "Read-only health and statistics for the active vault.", inputSchema: operationSchema("oms_status"), annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false } },
|
|
159
|
+
{ name: "oms_doctor", title: "Oh My Second Brain doctor", description: "Diagnose or repair the vault; `op` selects the operation.", inputSchema: operationSchema("oms_doctor"), annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false } },
|
|
309
160
|
];
|
|
310
161
|
export function createOMSMcpServer(opts) {
|
|
311
162
|
const vault = path.resolve(opts.vault);
|
|
@@ -315,17 +166,12 @@ export function createOMSMcpServer(opts) {
|
|
|
315
166
|
// graph cache status scan the vault off the filesystem and need no model.
|
|
316
167
|
// No model load, no SQLite store, no watcher: side-effect-free per boot (R2).
|
|
317
168
|
const engine = assembleGraphOnlyEngine({ vault });
|
|
318
|
-
//
|
|
319
|
-
//
|
|
320
|
-
// engine SQLite store on construction and loads the embedding model on first
|
|
321
|
-
// embed(). Embedding selection is canonical and explicit: OMS_EMBEDDING_PROVIDER
|
|
322
|
-
// (e.g. gguf | upstage) + OMS_EMBEDDING_MODEL (path or model id). Absent either,
|
|
323
|
-
// assembleFullSemanticEngine throws a loud, actionable error (ADR-007: no
|
|
324
|
-
// hash/fake fallback, no auto-detect) that surfaces via the dispatch catch.
|
|
169
|
+
// Creating semantic engines are shared by all non-search tools, including
|
|
170
|
+
// doctor repairs which must initialize a missing store.
|
|
325
171
|
let semanticEngine = null;
|
|
326
172
|
const getSemanticEngine = () => {
|
|
327
173
|
if (semanticEngine === null) {
|
|
328
|
-
semanticEngine = assembleFullSemanticEngine(vault);
|
|
174
|
+
semanticEngine = assembleFullSemanticEngine(vault, opts.reranker);
|
|
329
175
|
}
|
|
330
176
|
return semanticEngine;
|
|
331
177
|
};
|
|
@@ -335,10 +181,47 @@ export function createOMSMcpServer(opts) {
|
|
|
335
181
|
let coreSemanticEngine = null;
|
|
336
182
|
const getCoreSemanticEngine = () => {
|
|
337
183
|
if (coreSemanticEngine === null) {
|
|
338
|
-
coreSemanticEngine = assembleCoreSemanticEngine({ vault });
|
|
184
|
+
coreSemanticEngine = assembleCoreSemanticEngine({ vault, reranker: opts.reranker });
|
|
339
185
|
}
|
|
340
186
|
return coreSemanticEngine;
|
|
341
187
|
};
|
|
188
|
+
// Search owns independent read-only slots so it cannot poison doctor repair.
|
|
189
|
+
let readOnlySemanticEngine;
|
|
190
|
+
const getReadOnlySemanticEngine = () => {
|
|
191
|
+
if (readOnlySemanticEngine === undefined) {
|
|
192
|
+
readOnlySemanticEngine = assembleEngineReadOnly({
|
|
193
|
+
vault,
|
|
194
|
+
embeddingProvider: process.env["OMS_EMBEDDING_PROVIDER"],
|
|
195
|
+
embeddingModel: process.env["OMS_EMBEDDING_MODEL"],
|
|
196
|
+
reranker: opts.reranker,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
return readOnlySemanticEngine;
|
|
200
|
+
};
|
|
201
|
+
let readOnlyCoreSemanticEngine;
|
|
202
|
+
const getReadOnlyCoreSemanticEngine = () => {
|
|
203
|
+
if (readOnlyCoreSemanticEngine === undefined) {
|
|
204
|
+
readOnlyCoreSemanticEngine = assembleCoreSemanticEngineReadOnly({ vault, reranker: opts.reranker });
|
|
205
|
+
}
|
|
206
|
+
return readOnlyCoreSemanticEngine;
|
|
207
|
+
};
|
|
208
|
+
let ephemeralCoreSemanticEngine = null;
|
|
209
|
+
let ephemeralCoreSemanticEnginePromise = null;
|
|
210
|
+
const getEphemeralCoreSemanticEngine = async () => {
|
|
211
|
+
if (ephemeralCoreSemanticEngine !== null)
|
|
212
|
+
return ephemeralCoreSemanticEngine;
|
|
213
|
+
if (ephemeralCoreSemanticEnginePromise === null) {
|
|
214
|
+
ephemeralCoreSemanticEnginePromise = (async () => {
|
|
215
|
+
const assembled = assembleEphemeralCoreSemanticEngine({ vault, reranker: opts.reranker });
|
|
216
|
+
ephemeralCoreSemanticEngine = assembled;
|
|
217
|
+
return assembled;
|
|
218
|
+
})().catch((error) => {
|
|
219
|
+
ephemeralCoreSemanticEnginePromise = null;
|
|
220
|
+
throw error;
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
return ephemeralCoreSemanticEnginePromise;
|
|
224
|
+
};
|
|
342
225
|
// A real embedding provider is configured iff the canonical pair is set
|
|
343
226
|
// (ADR-007). The engine's model-OPTIONAL surface (document reads,
|
|
344
227
|
// retrieve_context's semantic leg, ReadResource) keys off this to decide
|
|
@@ -355,7 +238,51 @@ export function createOMSMcpServer(opts) {
|
|
|
355
238
|
// missing auth, store-open failure) must surface its error loudly rather than
|
|
356
239
|
// silently masquerade as a model-less host (ADR-007). The core fallback is
|
|
357
240
|
// strictly for the absent-config case.
|
|
358
|
-
const
|
|
241
|
+
const resolveCreatingDocumentAdapter = () => hasEmbeddingModel() ? getSemanticEngine().adapter : getCoreSemanticEngine().adapter;
|
|
242
|
+
const resolveReadOnlyDocumentAdapter = () => hasEmbeddingModel()
|
|
243
|
+
? getReadOnlySemanticEngine()?.adapter ?? engine.adapter
|
|
244
|
+
: getReadOnlyCoreSemanticEngine()?.adapter ?? engine.adapter;
|
|
245
|
+
const resolveDocumentAdapter = (publicName) => {
|
|
246
|
+
if (publicName === "oms_search")
|
|
247
|
+
return resolveReadOnlyDocumentAdapter();
|
|
248
|
+
return resolveCreatingDocumentAdapter();
|
|
249
|
+
};
|
|
250
|
+
const resolveReadOnlyIndexAdapter = () => {
|
|
251
|
+
const adapter = hasEmbeddingModel()
|
|
252
|
+
? getReadOnlySemanticEngine()?.adapter
|
|
253
|
+
: getReadOnlyCoreSemanticEngine()?.adapter;
|
|
254
|
+
if (adapter === undefined || adapter === null)
|
|
255
|
+
throw new SemanticIndexUnavailableError();
|
|
256
|
+
return adapter;
|
|
257
|
+
};
|
|
258
|
+
const resolveReadOnlyLexicalAdapter = async () => {
|
|
259
|
+
const adapter = hasEmbeddingModel()
|
|
260
|
+
? getReadOnlySemanticEngine()?.adapter
|
|
261
|
+
: getReadOnlyCoreSemanticEngine()?.adapter;
|
|
262
|
+
return adapter ?? (await getEphemeralCoreSemanticEngine()).adapter;
|
|
263
|
+
};
|
|
264
|
+
const hasExplicitEmbeddingIntent = (args) => requiresEmbeddings({
|
|
265
|
+
mode: args?.["mode"] === "vsearch" ? "vsearch" : undefined,
|
|
266
|
+
vec: stringArg(args, "vec"),
|
|
267
|
+
hyde: stringArg(args, "hyde"),
|
|
268
|
+
searches: Array.isArray(args?.["searches"])
|
|
269
|
+
? args["searches"].flatMap((search) => isRecord(search) &&
|
|
270
|
+
(search["type"] === "lex" || search["type"] === "vec" || search["type"] === "hyde") &&
|
|
271
|
+
typeof search["query"] === "string"
|
|
272
|
+
? [{ type: search["type"], query: search["query"] }]
|
|
273
|
+
: [])
|
|
274
|
+
: undefined,
|
|
275
|
+
});
|
|
276
|
+
const searchBackend = new EngineSearchBackend((requiresEmbeddings) => requiresEmbeddings
|
|
277
|
+
? (() => {
|
|
278
|
+
// Validate ADR-007 configuration before probing the read-only store:
|
|
279
|
+
// vector intent is actionable only after its required provider/model
|
|
280
|
+
// pair is present, regardless of whether an index exists yet.
|
|
281
|
+
if (!hasEmbeddingModel())
|
|
282
|
+
return getSemanticEngine().adapter;
|
|
283
|
+
return resolveReadOnlyIndexAdapter();
|
|
284
|
+
})()
|
|
285
|
+
: resolveReadOnlyIndexAdapter(), vault);
|
|
359
286
|
const server = new Server({ name: "oms", version: SERVER_VERSION }, {
|
|
360
287
|
capabilities: { tools: {}, resources: {} },
|
|
361
288
|
// Cache read only: construction must never touch the network. The
|
|
@@ -370,43 +297,35 @@ export function createOMSMcpServer(opts) {
|
|
|
370
297
|
if (coreSemanticEngine !== null) {
|
|
371
298
|
void coreSemanticEngine.dispose().catch(() => undefined);
|
|
372
299
|
}
|
|
300
|
+
if (readOnlySemanticEngine !== null && readOnlySemanticEngine !== undefined) {
|
|
301
|
+
void readOnlySemanticEngine.dispose().catch(() => undefined);
|
|
302
|
+
}
|
|
303
|
+
if (readOnlyCoreSemanticEngine !== null && readOnlyCoreSemanticEngine !== undefined) {
|
|
304
|
+
void readOnlyCoreSemanticEngine.dispose().catch(() => undefined);
|
|
305
|
+
}
|
|
306
|
+
if (ephemeralCoreSemanticEngine !== null) {
|
|
307
|
+
void ephemeralCoreSemanticEngine.dispose().catch(() => undefined);
|
|
308
|
+
}
|
|
373
309
|
};
|
|
374
310
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
375
311
|
tools: omsMcpTools,
|
|
376
312
|
}));
|
|
377
|
-
server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => ({
|
|
378
|
-
resourceTemplates: [
|
|
379
|
-
{
|
|
380
|
-
uriTemplate: "qmd://{path}",
|
|
381
|
-
name: "QMD-compatible OMS semantic document",
|
|
382
|
-
description: "Read a native OMS semantic-index document by qmd:// vault-relative path.",
|
|
383
|
-
mimeType: "text/markdown",
|
|
384
|
-
},
|
|
385
|
-
],
|
|
386
|
-
}));
|
|
387
|
-
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
388
|
-
const uri = request.params.uri;
|
|
389
|
-
// Resource reads hydrate on the SAME backend the semantic ops use: the engine
|
|
390
|
-
// (file-based, qmd:// / oms:// scheme aware), vec-capable when a model is
|
|
391
|
-
// configured and core (lex + file reads) otherwise — so a retrieve_context
|
|
392
|
-
// docid resolves through the URI surface regardless of which backend produced it.
|
|
393
|
-
const result = await resolveDocumentAdapter().getDocument({ vault, target: uri });
|
|
394
|
-
if (!result.available || !result.documents[0]) {
|
|
395
|
-
throw new Error(!result.available && result.reason ? result.reason : "OMS semantic resource not found.");
|
|
396
|
-
}
|
|
397
|
-
return {
|
|
398
|
-
contents: [
|
|
399
|
-
{
|
|
400
|
-
uri,
|
|
401
|
-
mimeType: "text/markdown",
|
|
402
|
-
text: result.documents[0].content,
|
|
403
|
-
},
|
|
404
|
-
],
|
|
405
|
-
};
|
|
406
|
-
});
|
|
407
313
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
408
|
-
|
|
409
|
-
|
|
314
|
+
let args = isRecord(request.params.arguments) ? request.params.arguments : undefined;
|
|
315
|
+
const publicName = request.params.name;
|
|
316
|
+
const op = publicName === "oms_write" ? stringArg(args, "op") ?? "create" : stringArg(args, "op");
|
|
317
|
+
const name = resolveOperation(publicName, op);
|
|
318
|
+
if (!name)
|
|
319
|
+
return errorText(`Unknown operation "${op ?? "(missing)"}" for ${publicName}.`);
|
|
320
|
+
if (publicName === "oms_write")
|
|
321
|
+
args = { ...args, mode: op };
|
|
322
|
+
if (publicName === "oms_search" && op === "query") {
|
|
323
|
+
const searches = args?.["searches"];
|
|
324
|
+
if (typeof args?.["query"] === "string" && Array.isArray(searches)) {
|
|
325
|
+
return errorText('Provide exactly one of "query" or "searches" for query.');
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if (name === "oms_graph_status") {
|
|
410
329
|
// The src/graph derived-cache ledger (M3 5-state staleness) is the source
|
|
411
330
|
// of truth for retrieve_context's optional warm cache and stays intact.
|
|
412
331
|
// engineGraph is additive: it surfaces the native engine's axis cache that
|
|
@@ -429,8 +348,8 @@ export function createOMSMcpServer(opts) {
|
|
|
429
348
|
derivedState: cacheStatus,
|
|
430
349
|
engineGraph,
|
|
431
350
|
writeTools: source === "cwd"
|
|
432
|
-
? "
|
|
433
|
-
: "
|
|
351
|
+
? "oms_write-disabled-target-unverified"
|
|
352
|
+
: "oms_write-gated-by-verified-target-and-contract",
|
|
434
353
|
readTools: omsMcpTools.map((tool) => tool.name),
|
|
435
354
|
});
|
|
436
355
|
}
|
|
@@ -453,27 +372,41 @@ export function createOMSMcpServer(opts) {
|
|
|
453
372
|
},
|
|
454
373
|
},
|
|
455
374
|
engineGraph,
|
|
456
|
-
writeTools: "disabled-invalid-ontology",
|
|
375
|
+
writeTools: "oms_write-disabled-invalid-ontology",
|
|
457
376
|
readTools: ["oms_graph_status"],
|
|
458
377
|
});
|
|
459
378
|
}
|
|
460
379
|
}
|
|
461
380
|
try {
|
|
462
|
-
if (
|
|
463
|
-
const
|
|
464
|
-
|
|
465
|
-
|
|
381
|
+
if (name === "oms_graph_build" || name === "oms_semantic_cleanup" || name === "oms_sync_embeddings") {
|
|
382
|
+
const operation = name === "oms_graph_build" ? "build-graph" : name === "oms_semantic_cleanup" ? "semantic-cleanup" : "sync-embeddings";
|
|
383
|
+
// A FACTORY, not a value. JavaScript evaluates an argument expression
|
|
384
|
+
// before entering the callee, so passing a constructed adapter here would
|
|
385
|
+
// open - and therefore create - `<vault>/.oms/engine-store.sqlite` before
|
|
386
|
+
// repairDoctor got the chance to run admission. On an invalid global
|
|
387
|
+
// target that means mutating a directory we are about to reject, which
|
|
388
|
+
// breaks the verified-target contract's requirement that admission
|
|
389
|
+
// precede ANY disk mutation. The kernel calls this only after admitting.
|
|
390
|
+
//
|
|
391
|
+
// Deliberately NOT re-checking admission here: two policy paths is how
|
|
392
|
+
// the check drifts. One authoritative decision, deferred dependency.
|
|
393
|
+
const resolveRepairAdapter = operation === "build-graph"
|
|
394
|
+
? undefined
|
|
395
|
+
: () => publicName === "oms_search"
|
|
396
|
+
? resolveReadOnlyDocumentAdapter()
|
|
397
|
+
: operation === "semantic-cleanup" || (operation === "sync-embeddings" && args?.["embed"] === false)
|
|
398
|
+
? resolveCreatingDocumentAdapter()
|
|
399
|
+
: getSemanticEngine().adapter;
|
|
400
|
+
const repair = await repairDoctor({
|
|
401
|
+
operation,
|
|
466
402
|
vault,
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
notes: cache.notes.length,
|
|
471
|
-
edges: cache.edges.length,
|
|
472
|
-
searchDocuments: cache.search.length,
|
|
473
|
-
sourceOfTruth: cache.sourceOfTruth,
|
|
403
|
+
source,
|
|
404
|
+
args,
|
|
405
|
+
resolveAdapter: resolveRepairAdapter,
|
|
474
406
|
});
|
|
407
|
+
return repair.kind === "error" ? errorText(repair.message) : jsonText(repair.value);
|
|
475
408
|
}
|
|
476
|
-
if (
|
|
409
|
+
if (name === "oms_list_concepts") {
|
|
477
410
|
const { ontology, source } = await resolveActiveOntology(vault);
|
|
478
411
|
return jsonText({
|
|
479
412
|
vault,
|
|
@@ -482,7 +415,7 @@ export function createOMSMcpServer(opts) {
|
|
|
482
415
|
concepts: Array.from(ontology.concepts.values()).map(conceptSummary),
|
|
483
416
|
});
|
|
484
417
|
}
|
|
485
|
-
if (
|
|
418
|
+
if (name === "oms_retrieve_by_axis") {
|
|
486
419
|
// Engine-owned (graph-only swap): axis-first retrieval over the native
|
|
487
420
|
// node index, built lazily off the filesystem — no embedding model needed.
|
|
488
421
|
const limitValue = args?.["limit"];
|
|
@@ -504,13 +437,24 @@ export function createOMSMcpServer(opts) {
|
|
|
504
437
|
...result,
|
|
505
438
|
});
|
|
506
439
|
}
|
|
507
|
-
if (
|
|
440
|
+
if (name === "oms_retrieve_context") {
|
|
508
441
|
// Graph + semantic fusion. The graph leg stays on the src/graph warm cache;
|
|
509
442
|
// the semantic leg routes to the native engine: vec-capable when a model is
|
|
510
443
|
// configured (parity ranking, real-path docids) and core (lex; vec/HyDE fail
|
|
511
444
|
// fast) otherwise. get/multi_get and ReadResource make the SAME choice, so a
|
|
512
445
|
// docid emitted here always hydrates on the backend that produced it.
|
|
513
|
-
const
|
|
446
|
+
const semantic = semanticOptionsFromArgs(args);
|
|
447
|
+
let contextAdapter = engine.adapter;
|
|
448
|
+
if (semantic?.enabled !== false) {
|
|
449
|
+
try {
|
|
450
|
+
contextAdapter = resolveDocumentAdapter(publicName);
|
|
451
|
+
}
|
|
452
|
+
catch (error) {
|
|
453
|
+
if (!(error instanceof SemanticIndexUnavailableError))
|
|
454
|
+
throw error;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
const semanticBackend = makeEngineMorningBackend(contextAdapter, vault);
|
|
514
458
|
const { ontology, source } = await resolveActiveOntology(vault);
|
|
515
459
|
const limitValue = args?.["limit"];
|
|
516
460
|
const maxNeighborsValue = args?.["maxNeighbors"];
|
|
@@ -527,7 +471,7 @@ export function createOMSMcpServer(opts) {
|
|
|
527
471
|
limit: typeof limitValue === "number" ? limitValue : undefined,
|
|
528
472
|
maxNeighbors: typeof maxNeighborsValue === "number" ? maxNeighborsValue : undefined,
|
|
529
473
|
useCache: typeof useCacheValue === "boolean" ? useCacheValue : undefined,
|
|
530
|
-
semantic
|
|
474
|
+
semantic,
|
|
531
475
|
}, semanticBackend);
|
|
532
476
|
return jsonText({
|
|
533
477
|
vault,
|
|
@@ -543,23 +487,112 @@ export function createOMSMcpServer(opts) {
|
|
|
543
487
|
// engine when a model is configured, else the core engine. Lex is a real
|
|
544
488
|
// model-free BM25/FTS feature, not an ADR-007 fake vector fallback.
|
|
545
489
|
// Every other tool never touches the engine here.
|
|
546
|
-
if (isEngineSemanticOp(
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
490
|
+
if (isEngineSemanticOp(name) || isEngineDocumentOp(name)) {
|
|
491
|
+
if (name === "oms_semantic_query") {
|
|
492
|
+
const hasQueryAxes = isRecord(args?.["axes"]) ||
|
|
493
|
+
args?.["folder"] !== undefined ||
|
|
494
|
+
args?.["field"] !== undefined ||
|
|
495
|
+
args?.["link"] !== undefined;
|
|
496
|
+
if (hasQueryAxes) {
|
|
497
|
+
const axisAdapter = hasExplicitEmbeddingIntent(args)
|
|
498
|
+
? resolveReadOnlyIndexAdapter()
|
|
499
|
+
: await resolveReadOnlyLexicalAdapter();
|
|
500
|
+
const axisOptions = semanticQueryOptionsFromArgs(vault, args);
|
|
501
|
+
const axisResult = await new EngineSearchBackend(axisAdapter, vault).search({
|
|
502
|
+
...axisOptions,
|
|
503
|
+
query: axisOptions.lex !== undefined ||
|
|
504
|
+
axisOptions.vec !== undefined ||
|
|
505
|
+
axisOptions.hyde !== undefined
|
|
506
|
+
? undefined
|
|
507
|
+
: axisOptions.query ?? "",
|
|
508
|
+
});
|
|
509
|
+
return jsonText(axisResult);
|
|
510
|
+
}
|
|
511
|
+
const query = stringArg(args, "query");
|
|
512
|
+
const vec = stringArg(args, "vec");
|
|
513
|
+
const hyde = stringArg(args, "hyde");
|
|
514
|
+
const queryOptions = semanticQueryOptionsFromArgs(vault, args);
|
|
515
|
+
const noPersistentReadOnlyIndex = hasEmbeddingModel()
|
|
516
|
+
? getReadOnlySemanticEngine() === null
|
|
517
|
+
: getReadOnlyCoreSemanticEngine() === null;
|
|
518
|
+
const hasExplicitLexicalIntent = query !== undefined ||
|
|
519
|
+
stringArg(args, "lex") !== undefined ||
|
|
520
|
+
(queryOptions.searches ?? []).some((search) => search.type === "lex");
|
|
521
|
+
const isOverviewRequest = query === undefined &&
|
|
522
|
+
(queryOptions.searches ?? []).length === 0 &&
|
|
523
|
+
queryOptions.lex === undefined &&
|
|
524
|
+
queryOptions.vec === undefined &&
|
|
525
|
+
queryOptions.hyde === undefined &&
|
|
526
|
+
queryOptions.axes === undefined;
|
|
527
|
+
if (!hasExplicitEmbeddingIntent(args) && noPersistentReadOnlyIndex && (hasExplicitLexicalIntent || isOverviewRequest)) {
|
|
528
|
+
// Reuse the SearchBackend seam for model-free fallback as well. This
|
|
529
|
+
// keeps overview, cursor, axes, and collection aggregation semantics
|
|
530
|
+
// identical to the indexed path; its normalized default is lexical,
|
|
531
|
+
// so no vector intent is fabricated when the model is absent.
|
|
532
|
+
const fallbackBackend = new EngineSearchBackend(await resolveReadOnlyLexicalAdapter(), vault);
|
|
533
|
+
const result = await fallbackBackend.search({
|
|
534
|
+
...queryOptions,
|
|
535
|
+
// `lex` is an explicit lexical representation. Do not send it
|
|
536
|
+
// alongside `query`, which would make the two equivalent forms
|
|
537
|
+
// look contradictory to the SearchBackend normalizer.
|
|
538
|
+
query: queryOptions.lex === undefined ? query ?? "" : undefined,
|
|
539
|
+
});
|
|
540
|
+
return jsonText(result);
|
|
541
|
+
}
|
|
542
|
+
const requestOptions = {
|
|
543
|
+
...queryOptions,
|
|
544
|
+
collections: queryOptions.collections,
|
|
545
|
+
};
|
|
546
|
+
const result = await searchBackend.search({
|
|
547
|
+
...requestOptions,
|
|
548
|
+
// `query` is the default lexical representation. An explicit vector
|
|
549
|
+
// or HyDE shorthand selects its own representation instead; only
|
|
550
|
+
// `query` plus typed `searches` is contradictory.
|
|
551
|
+
query: vec !== undefined || hyde !== undefined || queryOptions.lex !== undefined
|
|
552
|
+
? undefined
|
|
553
|
+
: query ?? "",
|
|
554
|
+
searches: queryOptions.searches,
|
|
555
|
+
});
|
|
556
|
+
return jsonText(result);
|
|
557
|
+
}
|
|
558
|
+
const useEphemeralLexicalFallback = name === "oms_semantic_query" &&
|
|
559
|
+
publicName === "oms_search" &&
|
|
560
|
+
!hasExplicitEmbeddingIntent(args) &&
|
|
561
|
+
(hasEmbeddingModel()
|
|
562
|
+
? getReadOnlySemanticEngine() === null
|
|
563
|
+
: getReadOnlyCoreSemanticEngine() === null);
|
|
564
|
+
const semanticAdapter = useEphemeralLexicalFallback
|
|
565
|
+
? await resolveReadOnlyLexicalAdapter()
|
|
566
|
+
:
|
|
567
|
+
isEngineSemanticOp(name) &&
|
|
568
|
+
name !== "oms_semantic_cleanup" &&
|
|
569
|
+
!(name === "oms_sync_embeddings" && args?.["embed"] === false) &&
|
|
570
|
+
!isModelOptionalSemanticQueryOp(name, args, vault)
|
|
571
|
+
? publicName === "oms_search"
|
|
572
|
+
? resolveReadOnlyIndexAdapter()
|
|
573
|
+
: getSemanticEngine().adapter
|
|
574
|
+
: isEngineDocumentOp(name)
|
|
575
|
+
? resolveDocumentAdapter(publicName)
|
|
576
|
+
: publicName === "oms_search"
|
|
577
|
+
? resolveReadOnlyIndexAdapter()
|
|
578
|
+
: resolveDocumentAdapter(publicName);
|
|
579
|
+
const semanticToolResult = await handleSemanticTool(name, useEphemeralLexicalFallback
|
|
580
|
+
? { ...args, lex: stringArg(args, "query") }
|
|
581
|
+
: args, vault, semanticAdapter);
|
|
551
582
|
if (semanticToolResult) {
|
|
552
|
-
|
|
583
|
+
if (!semanticToolResult.ok)
|
|
584
|
+
return errorText(semanticToolResult.message);
|
|
585
|
+
return jsonText(semanticToolResult.value);
|
|
553
586
|
}
|
|
554
587
|
}
|
|
555
|
-
if (
|
|
588
|
+
if (name === "oms_lazy_load_note") {
|
|
556
589
|
const notePath = stringArg(args, "notePath");
|
|
557
590
|
if (!notePath) {
|
|
558
591
|
return errorText('Missing required string argument "notePath".');
|
|
559
592
|
}
|
|
560
593
|
return jsonText(await lazyLoadNoteBody(vault, notePath));
|
|
561
594
|
}
|
|
562
|
-
if (
|
|
595
|
+
if (name === "oms_validate_contract") {
|
|
563
596
|
const notePath = stringArg(args, "notePath");
|
|
564
597
|
if (!notePath) {
|
|
565
598
|
return errorText('Missing required string argument "notePath".');
|
|
@@ -603,7 +636,7 @@ export function createOMSMcpServer(opts) {
|
|
|
603
636
|
violations: result.violations,
|
|
604
637
|
});
|
|
605
638
|
}
|
|
606
|
-
if (
|
|
639
|
+
if (name === "oms_vault_audit") {
|
|
607
640
|
if (args !== undefined &&
|
|
608
641
|
Object.prototype.hasOwnProperty.call(args, "folder") &&
|
|
609
642
|
typeof args["folder"] !== "string") {
|
|
@@ -622,7 +655,7 @@ export function createOMSMcpServer(opts) {
|
|
|
622
655
|
violations: report.violations,
|
|
623
656
|
});
|
|
624
657
|
}
|
|
625
|
-
if (
|
|
658
|
+
if (name === "oms_link_suggest") {
|
|
626
659
|
const notePath = stringArg(args, "notePath");
|
|
627
660
|
if (!notePath) {
|
|
628
661
|
return errorText('Missing required string argument "notePath".');
|
|
@@ -631,7 +664,7 @@ export function createOMSMcpServer(opts) {
|
|
|
631
664
|
const suggestion = await suggestLinksForNote({ vault, source, ontology, notePath }, { folder: stringArg(args, "folder") });
|
|
632
665
|
return jsonText({ vault, ontologySource, ...suggestion });
|
|
633
666
|
}
|
|
634
|
-
if (
|
|
667
|
+
if (name === "oms_link_apply") {
|
|
635
668
|
const notePath = stringArg(args, "notePath");
|
|
636
669
|
if (!notePath) {
|
|
637
670
|
return errorText('Missing required string argument "notePath".');
|
|
@@ -648,10 +681,20 @@ export function createOMSMcpServer(opts) {
|
|
|
648
681
|
const outcome = await applyLinksForNote({ vault, source, ontology, notePath }, { baseContentHash, candidateIds: idsArg.filter((id) => typeof id === "string") }, { folder: stringArg(args, "folder") });
|
|
649
682
|
return jsonText({ vault, ontologySource, ...linkApplyPayload(outcome) });
|
|
650
683
|
}
|
|
651
|
-
if (
|
|
684
|
+
if (name === "write") {
|
|
652
685
|
const { ontology, source: ontologySource } = await resolveActiveOntology(vault);
|
|
653
686
|
const modeArg = stringArg(args, "mode");
|
|
654
687
|
const mode = isWriteMode(modeArg) ? modeArg : "create";
|
|
688
|
+
// `notePath` and `folder`/`filename` are two ways to address the same
|
|
689
|
+
// note. Supplying both is a contradiction the caller should hear about:
|
|
690
|
+
// silently preferring one produced a response that reported the concept
|
|
691
|
+
// implied by one form and the folder implied by the other, which reads as
|
|
692
|
+
// corruption rather than as the input error it is.
|
|
693
|
+
const hasNotePath = stringArg(args, "notePath") !== undefined;
|
|
694
|
+
const hasFolderForm = stringArg(args, "folder") !== undefined || stringArg(args, "filename") !== undefined;
|
|
695
|
+
if (hasNotePath && hasFolderForm) {
|
|
696
|
+
return errorText('Provide either "notePath" or "folder"/"filename" to address the note, not both.');
|
|
697
|
+
}
|
|
655
698
|
const frontmatterArg = args?.["frontmatter"];
|
|
656
699
|
const result = await writeNote({
|
|
657
700
|
target: { vault, source },
|
|
@@ -673,9 +716,15 @@ export function createOMSMcpServer(opts) {
|
|
|
673
716
|
resolutionSource: source,
|
|
674
717
|
});
|
|
675
718
|
}
|
|
676
|
-
return errorText(`Unknown Oh My Second Brain tool: ${
|
|
719
|
+
return errorText(`Unknown Oh My Second Brain tool: ${publicName}`);
|
|
677
720
|
}
|
|
678
721
|
catch (error) {
|
|
722
|
+
if (error instanceof SemanticIndexUnavailableError) {
|
|
723
|
+
return jsonText({
|
|
724
|
+
available: false,
|
|
725
|
+
reason: error.message,
|
|
726
|
+
});
|
|
727
|
+
}
|
|
679
728
|
return errorText(`Oh My Second Brain MCP error: ${error instanceof Error ? error.message : String(error)}`);
|
|
680
729
|
}
|
|
681
730
|
});
|