memkin 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +191 -0
- package/README.en.md +934 -0
- package/README.md +934 -0
- package/README.zh-CN.md +825 -0
- package/bin/memkin.mjs +41 -0
- package/dist/adapters/file.d.ts +19 -0
- package/dist/adapters/file.d.ts.map +1 -0
- package/dist/adapters/file.js +61 -0
- package/dist/adapters/file.js.map +1 -0
- package/dist/adapters/gbrain.d.ts +29 -0
- package/dist/adapters/gbrain.d.ts.map +1 -0
- package/dist/adapters/gbrain.js +622 -0
- package/dist/adapters/gbrain.js.map +1 -0
- package/dist/adapters/index.d.ts +6 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +5 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/registry.d.ts +18 -0
- package/dist/adapters/registry.d.ts.map +1 -0
- package/dist/adapters/registry.js +18 -0
- package/dist/adapters/registry.js.map +1 -0
- package/dist/adapters/stdout.d.ts +12 -0
- package/dist/adapters/stdout.d.ts.map +1 -0
- package/dist/adapters/stdout.js +29 -0
- package/dist/adapters/stdout.js.map +1 -0
- package/dist/adapters/store.d.ts +47 -0
- package/dist/adapters/store.d.ts.map +1 -0
- package/dist/adapters/store.js +642 -0
- package/dist/adapters/store.js.map +1 -0
- package/dist/cli-helpers.d.ts +12 -0
- package/dist/cli-helpers.d.ts.map +1 -0
- package/dist/cli-helpers.js +11 -0
- package/dist/cli-helpers.js.map +1 -0
- package/dist/cli-stores.d.ts +61 -0
- package/dist/cli-stores.d.ts.map +1 -0
- package/dist/cli-stores.js +130 -0
- package/dist/cli-stores.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1579 -0
- package/dist/cli.js.map +1 -0
- package/dist/collectors/agent/claude-code.d.ts +12 -0
- package/dist/collectors/agent/claude-code.d.ts.map +1 -0
- package/dist/collectors/agent/claude-code.js +94 -0
- package/dist/collectors/agent/claude-code.js.map +1 -0
- package/dist/collectors/agent/codex.d.ts +16 -0
- package/dist/collectors/agent/codex.d.ts.map +1 -0
- package/dist/collectors/agent/codex.js +149 -0
- package/dist/collectors/agent/codex.js.map +1 -0
- package/dist/collectors/agent/collector.d.ts +20 -0
- package/dist/collectors/agent/collector.d.ts.map +1 -0
- package/dist/collectors/agent/collector.js +108 -0
- package/dist/collectors/agent/collector.js.map +1 -0
- package/dist/collectors/agent/hermes.d.ts +13 -0
- package/dist/collectors/agent/hermes.d.ts.map +1 -0
- package/dist/collectors/agent/hermes.js +90 -0
- package/dist/collectors/agent/hermes.js.map +1 -0
- package/dist/collectors/agent/index.d.ts +6 -0
- package/dist/collectors/agent/index.d.ts.map +1 -0
- package/dist/collectors/agent/index.js +5 -0
- package/dist/collectors/agent/index.js.map +1 -0
- package/dist/collectors/agent/types.d.ts +61 -0
- package/dist/collectors/agent/types.d.ts.map +1 -0
- package/dist/collectors/agent/types.js +6 -0
- package/dist/collectors/agent/types.js.map +1 -0
- package/dist/collectors/feishu/auth.d.ts +13 -0
- package/dist/collectors/feishu/auth.d.ts.map +1 -0
- package/dist/collectors/feishu/auth.js +72 -0
- package/dist/collectors/feishu/auth.js.map +1 -0
- package/dist/collectors/feishu/chat-name-resolver.d.ts +33 -0
- package/dist/collectors/feishu/chat-name-resolver.d.ts.map +1 -0
- package/dist/collectors/feishu/chat-name-resolver.js +63 -0
- package/dist/collectors/feishu/chat-name-resolver.js.map +1 -0
- package/dist/collectors/feishu/collector.d.ts +27 -0
- package/dist/collectors/feishu/collector.d.ts.map +1 -0
- package/dist/collectors/feishu/collector.js +136 -0
- package/dist/collectors/feishu/collector.js.map +1 -0
- package/dist/collectors/feishu/cursor-staging.d.ts +11 -0
- package/dist/collectors/feishu/cursor-staging.d.ts.map +1 -0
- package/dist/collectors/feishu/cursor-staging.js +37 -0
- package/dist/collectors/feishu/cursor-staging.js.map +1 -0
- package/dist/collectors/feishu/docs/blocks.d.ts +25 -0
- package/dist/collectors/feishu/docs/blocks.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/blocks.js +34 -0
- package/dist/collectors/feishu/docs/blocks.js.map +1 -0
- package/dist/collectors/feishu/docs/candidate.d.ts +17 -0
- package/dist/collectors/feishu/docs/candidate.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/candidate.js +36 -0
- package/dist/collectors/feishu/docs/candidate.js.map +1 -0
- package/dist/collectors/feishu/docs/config.d.ts +41 -0
- package/dist/collectors/feishu/docs/config.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/config.js +30 -0
- package/dist/collectors/feishu/docs/config.js.map +1 -0
- package/dist/collectors/feishu/docs/decision.d.ts +14 -0
- package/dist/collectors/feishu/docs/decision.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/decision.js +43 -0
- package/dist/collectors/feishu/docs/decision.js.map +1 -0
- package/dist/collectors/feishu/docs/full-builder.d.ts +17 -0
- package/dist/collectors/feishu/docs/full-builder.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/full-builder.js +136 -0
- package/dist/collectors/feishu/docs/full-builder.js.map +1 -0
- package/dist/collectors/feishu/docs/hash.d.ts +8 -0
- package/dist/collectors/feishu/docs/hash.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/hash.js +15 -0
- package/dist/collectors/feishu/docs/hash.js.map +1 -0
- package/dist/collectors/feishu/docs/ingest.d.ts +54 -0
- package/dist/collectors/feishu/docs/ingest.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/ingest.js +120 -0
- package/dist/collectors/feishu/docs/ingest.js.map +1 -0
- package/dist/collectors/feishu/docs/llm-json.d.ts +13 -0
- package/dist/collectors/feishu/docs/llm-json.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/llm-json.js +40 -0
- package/dist/collectors/feishu/docs/llm-json.js.map +1 -0
- package/dist/collectors/feishu/docs/pointer-builder.d.ts +7 -0
- package/dist/collectors/feishu/docs/pointer-builder.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/pointer-builder.js +11 -0
- package/dist/collectors/feishu/docs/pointer-builder.js.map +1 -0
- package/dist/collectors/feishu/docs/render.d.ts +8 -0
- package/dist/collectors/feishu/docs/render.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/render.js +105 -0
- package/dist/collectors/feishu/docs/render.js.map +1 -0
- package/dist/collectors/feishu/docs/run.d.ts +37 -0
- package/dist/collectors/feishu/docs/run.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/run.js +143 -0
- package/dist/collectors/feishu/docs/run.js.map +1 -0
- package/dist/collectors/feishu/docs/status.d.ts +16 -0
- package/dist/collectors/feishu/docs/status.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/status.js +24 -0
- package/dist/collectors/feishu/docs/status.js.map +1 -0
- package/dist/collectors/feishu/docs/store-writer.d.ts +32 -0
- package/dist/collectors/feishu/docs/store-writer.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/store-writer.js +71 -0
- package/dist/collectors/feishu/docs/store-writer.js.map +1 -0
- package/dist/collectors/feishu/docs/toc.d.ts +3 -0
- package/dist/collectors/feishu/docs/toc.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/toc.js +19 -0
- package/dist/collectors/feishu/docs/toc.js.map +1 -0
- package/dist/collectors/feishu/docs/triggers.d.ts +7 -0
- package/dist/collectors/feishu/docs/triggers.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/triggers.js +31 -0
- package/dist/collectors/feishu/docs/triggers.js.map +1 -0
- package/dist/collectors/feishu/docs/types.d.ts +109 -0
- package/dist/collectors/feishu/docs/types.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/types.js +2 -0
- package/dist/collectors/feishu/docs/types.js.map +1 -0
- package/dist/collectors/feishu/docs/upgrade-queue.d.ts +19 -0
- package/dist/collectors/feishu/docs/upgrade-queue.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/upgrade-queue.js +36 -0
- package/dist/collectors/feishu/docs/upgrade-queue.js.map +1 -0
- package/dist/collectors/feishu/docs/url-parser.d.ts +3 -0
- package/dist/collectors/feishu/docs/url-parser.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/url-parser.js +39 -0
- package/dist/collectors/feishu/docs/url-parser.js.map +1 -0
- package/dist/collectors/feishu/docs/walkers.d.ts +24 -0
- package/dist/collectors/feishu/docs/walkers.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/walkers.js +90 -0
- package/dist/collectors/feishu/docs/walkers.js.map +1 -0
- package/dist/collectors/feishu/docs/wiki-resolver.d.ts +15 -0
- package/dist/collectors/feishu/docs/wiki-resolver.d.ts.map +1 -0
- package/dist/collectors/feishu/docs/wiki-resolver.js +24 -0
- package/dist/collectors/feishu/docs/wiki-resolver.js.map +1 -0
- package/dist/collectors/feishu/http-client.d.ts +26 -0
- package/dist/collectors/feishu/http-client.d.ts.map +1 -0
- package/dist/collectors/feishu/http-client.js +94 -0
- package/dist/collectors/feishu/http-client.js.map +1 -0
- package/dist/collectors/feishu/index.d.ts +3 -0
- package/dist/collectors/feishu/index.d.ts.map +1 -0
- package/dist/collectors/feishu/index.js +2 -0
- package/dist/collectors/feishu/index.js.map +1 -0
- package/dist/collectors/feishu/lark-cli-client.d.ts +28 -0
- package/dist/collectors/feishu/lark-cli-client.d.ts.map +1 -0
- package/dist/collectors/feishu/lark-cli-client.js +104 -0
- package/dist/collectors/feishu/lark-cli-client.js.map +1 -0
- package/dist/collectors/feishu/lark-cli-identity-backend.d.ts +28 -0
- package/dist/collectors/feishu/lark-cli-identity-backend.d.ts.map +1 -0
- package/dist/collectors/feishu/lark-cli-identity-backend.js +110 -0
- package/dist/collectors/feishu/lark-cli-identity-backend.js.map +1 -0
- package/dist/collectors/feishu/rate-limiter.d.ts +10 -0
- package/dist/collectors/feishu/rate-limiter.d.ts.map +1 -0
- package/dist/collectors/feishu/rate-limiter.js +33 -0
- package/dist/collectors/feishu/rate-limiter.js.map +1 -0
- package/dist/collectors/feishu/self-open-id.d.ts +20 -0
- package/dist/collectors/feishu/self-open-id.d.ts.map +1 -0
- package/dist/collectors/feishu/self-open-id.js +31 -0
- package/dist/collectors/feishu/self-open-id.js.map +1 -0
- package/dist/collectors/feishu/sources/base.d.ts +9 -0
- package/dist/collectors/feishu/sources/base.d.ts.map +1 -0
- package/dist/collectors/feishu/sources/base.js +2 -0
- package/dist/collectors/feishu/sources/base.js.map +1 -0
- package/dist/collectors/feishu/sources/calendar.d.ts +16 -0
- package/dist/collectors/feishu/sources/calendar.d.ts.map +1 -0
- package/dist/collectors/feishu/sources/calendar.js +98 -0
- package/dist/collectors/feishu/sources/calendar.js.map +1 -0
- package/dist/collectors/feishu/sources/dm.d.ts +28 -0
- package/dist/collectors/feishu/sources/dm.d.ts.map +1 -0
- package/dist/collectors/feishu/sources/dm.js +156 -0
- package/dist/collectors/feishu/sources/dm.js.map +1 -0
- package/dist/collectors/feishu/sources/mail.d.ts +27 -0
- package/dist/collectors/feishu/sources/mail.d.ts.map +1 -0
- package/dist/collectors/feishu/sources/mail.js +149 -0
- package/dist/collectors/feishu/sources/mail.js.map +1 -0
- package/dist/collectors/feishu/sources/message-search.d.ts +37 -0
- package/dist/collectors/feishu/sources/message-search.d.ts.map +1 -0
- package/dist/collectors/feishu/sources/message-search.js +140 -0
- package/dist/collectors/feishu/sources/message-search.js.map +1 -0
- package/dist/collectors/feishu/sources/messages.d.ts +28 -0
- package/dist/collectors/feishu/sources/messages.d.ts.map +1 -0
- package/dist/collectors/feishu/sources/messages.js +175 -0
- package/dist/collectors/feishu/sources/messages.js.map +1 -0
- package/dist/collectors/feishu/sources/tasks.d.ts +15 -0
- package/dist/collectors/feishu/sources/tasks.d.ts.map +1 -0
- package/dist/collectors/feishu/sources/tasks.js +74 -0
- package/dist/collectors/feishu/sources/tasks.js.map +1 -0
- package/dist/collectors/feishu/types.d.ts +258 -0
- package/dist/collectors/feishu/types.d.ts.map +1 -0
- package/dist/collectors/feishu/types.js +17 -0
- package/dist/collectors/feishu/types.js.map +1 -0
- package/dist/collectors/index.d.ts +10 -0
- package/dist/collectors/index.d.ts.map +1 -0
- package/dist/collectors/index.js +18 -0
- package/dist/collectors/index.js.map +1 -0
- package/dist/config-center/connection-checks.d.ts +28 -0
- package/dist/config-center/connection-checks.d.ts.map +1 -0
- package/dist/config-center/connection-checks.js +114 -0
- package/dist/config-center/connection-checks.js.map +1 -0
- package/dist/config-center/document.d.ts +21 -0
- package/dist/config-center/document.d.ts.map +1 -0
- package/dist/config-center/document.js +93 -0
- package/dist/config-center/document.js.map +1 -0
- package/dist/config-center/index.d.ts +9 -0
- package/dist/config-center/index.d.ts.map +1 -0
- package/dist/config-center/index.js +29 -0
- package/dist/config-center/index.js.map +1 -0
- package/dist/config-center/recommendations.d.ts +16 -0
- package/dist/config-center/recommendations.d.ts.map +1 -0
- package/dist/config-center/recommendations.js +50 -0
- package/dist/config-center/recommendations.js.map +1 -0
- package/dist/config-center/reducer.d.ts +57 -0
- package/dist/config-center/reducer.d.ts.map +1 -0
- package/dist/config-center/reducer.js +192 -0
- package/dist/config-center/reducer.js.map +1 -0
- package/dist/config-center/schema.d.ts +31 -0
- package/dist/config-center/schema.d.ts.map +1 -0
- package/dist/config-center/schema.js +442 -0
- package/dist/config-center/schema.js.map +1 -0
- package/dist/config-center/secrets.d.ts +9 -0
- package/dist/config-center/secrets.d.ts.map +1 -0
- package/dist/config-center/secrets.js +51 -0
- package/dist/config-center/secrets.js.map +1 -0
- package/dist/config-center/source-dirs.d.ts +16 -0
- package/dist/config-center/source-dirs.d.ts.map +1 -0
- package/dist/config-center/source-dirs.js +81 -0
- package/dist/config-center/source-dirs.js.map +1 -0
- package/dist/config-center/tui/app.d.ts +22 -0
- package/dist/config-center/tui/app.d.ts.map +1 -0
- package/dist/config-center/tui/app.js +142 -0
- package/dist/config-center/tui/app.js.map +1 -0
- package/dist/config-center/tui/render.d.ts +20 -0
- package/dist/config-center/tui/render.d.ts.map +1 -0
- package/dist/config-center/tui/render.js +166 -0
- package/dist/config-center/tui/render.js.map +1 -0
- package/dist/config-center/validation.d.ts +9 -0
- package/dist/config-center/validation.d.ts.map +1 -0
- package/dist/config-center/validation.js +59 -0
- package/dist/config-center/validation.js.map +1 -0
- package/dist/consolidator/consolidator.d.ts +43 -0
- package/dist/consolidator/consolidator.d.ts.map +1 -0
- package/dist/consolidator/consolidator.js +67 -0
- package/dist/consolidator/consolidator.js.map +1 -0
- package/dist/consolidator/dead-link.d.ts +7 -0
- package/dist/consolidator/dead-link.d.ts.map +1 -0
- package/dist/consolidator/dead-link.js +57 -0
- package/dist/consolidator/dead-link.js.map +1 -0
- package/dist/consolidator/hot-warm.d.ts +9 -0
- package/dist/consolidator/hot-warm.d.ts.map +1 -0
- package/dist/consolidator/hot-warm.js +88 -0
- package/dist/consolidator/hot-warm.js.map +1 -0
- package/dist/consolidator/infer-preferences.d.ts +14 -0
- package/dist/consolidator/infer-preferences.d.ts.map +1 -0
- package/dist/consolidator/infer-preferences.js +73 -0
- package/dist/consolidator/infer-preferences.js.map +1 -0
- package/dist/consolidator/rules.d.ts +5 -0
- package/dist/consolidator/rules.d.ts.map +1 -0
- package/dist/consolidator/rules.js +53 -0
- package/dist/consolidator/rules.js.map +1 -0
- package/dist/consolidator/warm-cold.d.ts +13 -0
- package/dist/consolidator/warm-cold.d.ts.map +1 -0
- package/dist/consolidator/warm-cold.js +91 -0
- package/dist/consolidator/warm-cold.js.map +1 -0
- package/dist/core/block-builder.d.ts +15 -0
- package/dist/core/block-builder.d.ts.map +1 -0
- package/dist/core/block-builder.js +185 -0
- package/dist/core/block-builder.js.map +1 -0
- package/dist/core/canonicalize.d.ts +3 -0
- package/dist/core/canonicalize.d.ts.map +1 -0
- package/dist/core/canonicalize.js +141 -0
- package/dist/core/canonicalize.js.map +1 -0
- package/dist/core/concurrency.d.ts +2 -0
- package/dist/core/concurrency.d.ts.map +1 -0
- package/dist/core/concurrency.js +14 -0
- package/dist/core/concurrency.js.map +1 -0
- package/dist/core/config.d.ts +257 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +247 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/cursors.d.ts +36 -0
- package/dist/core/cursors.d.ts.map +1 -0
- package/dist/core/cursors.js +90 -0
- package/dist/core/cursors.js.map +1 -0
- package/dist/core/dedup.d.ts +45 -0
- package/dist/core/dedup.d.ts.map +1 -0
- package/dist/core/dedup.js +111 -0
- package/dist/core/dedup.js.map +1 -0
- package/dist/core/entity-extract.d.ts +3 -0
- package/dist/core/entity-extract.d.ts.map +1 -0
- package/dist/core/entity-extract.js +54 -0
- package/dist/core/entity-extract.js.map +1 -0
- package/dist/core/env-validation.d.ts +9 -0
- package/dist/core/env-validation.d.ts.map +1 -0
- package/dist/core/env-validation.js +94 -0
- package/dist/core/env-validation.js.map +1 -0
- package/dist/core/helpers.d.ts +3 -0
- package/dist/core/helpers.d.ts.map +1 -0
- package/dist/core/helpers.js +10 -0
- package/dist/core/helpers.js.map +1 -0
- package/dist/core/identity-resolver.d.ts +42 -0
- package/dist/core/identity-resolver.d.ts.map +1 -0
- package/dist/core/identity-resolver.js +207 -0
- package/dist/core/identity-resolver.js.map +1 -0
- package/dist/core/person-identity.d.ts +140 -0
- package/dist/core/person-identity.d.ts.map +1 -0
- package/dist/core/person-identity.js +428 -0
- package/dist/core/person-identity.js.map +1 -0
- package/dist/core/person-slug.d.ts +21 -0
- package/dist/core/person-slug.d.ts.map +1 -0
- package/dist/core/person-slug.js +93 -0
- package/dist/core/person-slug.js.map +1 -0
- package/dist/core/pipeline-factory.d.ts +13 -0
- package/dist/core/pipeline-factory.d.ts.map +1 -0
- package/dist/core/pipeline-factory.js +37 -0
- package/dist/core/pipeline-factory.js.map +1 -0
- package/dist/core/pipeline.d.ts +77 -0
- package/dist/core/pipeline.d.ts.map +1 -0
- package/dist/core/pipeline.js +332 -0
- package/dist/core/pipeline.js.map +1 -0
- package/dist/core/resource-loader.d.ts +2 -0
- package/dist/core/resource-loader.d.ts.map +1 -0
- package/dist/core/resource-loader.js +12 -0
- package/dist/core/resource-loader.js.map +1 -0
- package/dist/core/schemas.d.ts +5142 -0
- package/dist/core/schemas.d.ts.map +1 -0
- package/dist/core/schemas.js +256 -0
- package/dist/core/schemas.js.map +1 -0
- package/dist/core/signal-scoring.d.ts +3 -0
- package/dist/core/signal-scoring.d.ts.map +1 -0
- package/dist/core/signal-scoring.js +128 -0
- package/dist/core/signal-scoring.js.map +1 -0
- package/dist/core/source-ref.d.ts +4 -0
- package/dist/core/source-ref.d.ts.map +1 -0
- package/dist/core/source-ref.js +24 -0
- package/dist/core/source-ref.js.map +1 -0
- package/dist/core/state.d.ts +22 -0
- package/dist/core/state.d.ts.map +1 -0
- package/dist/core/state.js +33 -0
- package/dist/core/state.js.map +1 -0
- package/dist/core/types.d.ts +266 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +6 -0
- package/dist/core/types.js.map +1 -0
- package/dist/daemon/alerts.d.ts +12 -0
- package/dist/daemon/alerts.d.ts.map +1 -0
- package/dist/daemon/alerts.js +34 -0
- package/dist/daemon/alerts.js.map +1 -0
- package/dist/daemon/autostart/argv.d.ts +21 -0
- package/dist/daemon/autostart/argv.d.ts.map +1 -0
- package/dist/daemon/autostart/argv.js +37 -0
- package/dist/daemon/autostart/argv.js.map +1 -0
- package/dist/daemon/autostart/daemon-state.d.ts +19 -0
- package/dist/daemon/autostart/daemon-state.d.ts.map +1 -0
- package/dist/daemon/autostart/daemon-state.js +34 -0
- package/dist/daemon/autostart/daemon-state.js.map +1 -0
- package/dist/daemon/autostart/index.d.ts +40 -0
- package/dist/daemon/autostart/index.d.ts.map +1 -0
- package/dist/daemon/autostart/index.js +146 -0
- package/dist/daemon/autostart/index.js.map +1 -0
- package/dist/daemon/autostart/launchd.d.ts +13 -0
- package/dist/daemon/autostart/launchd.d.ts.map +1 -0
- package/dist/daemon/autostart/launchd.js +51 -0
- package/dist/daemon/autostart/launchd.js.map +1 -0
- package/dist/daemon/autostart/runner.d.ts +14 -0
- package/dist/daemon/autostart/runner.d.ts.map +1 -0
- package/dist/daemon/autostart/runner.js +30 -0
- package/dist/daemon/autostart/runner.js.map +1 -0
- package/dist/daemon/autostart/systemd.d.ts +11 -0
- package/dist/daemon/autostart/systemd.d.ts.map +1 -0
- package/dist/daemon/autostart/systemd.js +40 -0
- package/dist/daemon/autostart/systemd.js.map +1 -0
- package/dist/daemon/index.d.ts +6 -0
- package/dist/daemon/index.d.ts.map +1 -0
- package/dist/daemon/index.js +6 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/daemon/logger.d.ts +8 -0
- package/dist/daemon/logger.d.ts.map +1 -0
- package/dist/daemon/logger.js +35 -0
- package/dist/daemon/logger.js.map +1 -0
- package/dist/daemon/reload-manager.d.ts +41 -0
- package/dist/daemon/reload-manager.d.ts.map +1 -0
- package/dist/daemon/reload-manager.js +89 -0
- package/dist/daemon/reload-manager.js.map +1 -0
- package/dist/daemon/run-history.d.ts +29 -0
- package/dist/daemon/run-history.d.ts.map +1 -0
- package/dist/daemon/run-history.js +54 -0
- package/dist/daemon/run-history.js.map +1 -0
- package/dist/daemon/scheduler.d.ts +45 -0
- package/dist/daemon/scheduler.d.ts.map +1 -0
- package/dist/daemon/scheduler.js +217 -0
- package/dist/daemon/scheduler.js.map +1 -0
- package/dist/daemon/serve-runtime.d.ts +31 -0
- package/dist/daemon/serve-runtime.d.ts.map +1 -0
- package/dist/daemon/serve-runtime.js +230 -0
- package/dist/daemon/serve-runtime.js.map +1 -0
- package/dist/daemon/source-schedule.d.ts +25 -0
- package/dist/daemon/source-schedule.d.ts.map +1 -0
- package/dist/daemon/source-schedule.js +87 -0
- package/dist/daemon/source-schedule.js.map +1 -0
- package/dist/embedded-assets.generated.d.ts +4 -0
- package/dist/embedded-assets.generated.d.ts.map +1 -0
- package/dist/embedded-assets.generated.js +12 -0
- package/dist/embedded-assets.generated.js.map +1 -0
- package/dist/extractors/noise-filter.d.ts +30 -0
- package/dist/extractors/noise-filter.d.ts.map +1 -0
- package/dist/extractors/noise-filter.js +185 -0
- package/dist/extractors/noise-filter.js.map +1 -0
- package/dist/extractors/playbook-extractor.d.ts +35 -0
- package/dist/extractors/playbook-extractor.d.ts.map +1 -0
- package/dist/extractors/playbook-extractor.js +98 -0
- package/dist/extractors/playbook-extractor.js.map +1 -0
- package/dist/extractors/providers/anthropic.d.ts +13 -0
- package/dist/extractors/providers/anthropic.d.ts.map +1 -0
- package/dist/extractors/providers/anthropic.js +67 -0
- package/dist/extractors/providers/anthropic.js.map +1 -0
- package/dist/extractors/providers/index.d.ts +12 -0
- package/dist/extractors/providers/index.d.ts.map +1 -0
- package/dist/extractors/providers/index.js +41 -0
- package/dist/extractors/providers/index.js.map +1 -0
- package/dist/extractors/providers/mock.d.ts +14 -0
- package/dist/extractors/providers/mock.d.ts.map +1 -0
- package/dist/extractors/providers/mock.js +37 -0
- package/dist/extractors/providers/mock.js.map +1 -0
- package/dist/extractors/providers/openai.d.ts +15 -0
- package/dist/extractors/providers/openai.d.ts.map +1 -0
- package/dist/extractors/providers/openai.js +109 -0
- package/dist/extractors/providers/openai.js.map +1 -0
- package/dist/extractors/providers/types.d.ts +27 -0
- package/dist/extractors/providers/types.d.ts.map +1 -0
- package/dist/extractors/providers/types.js +6 -0
- package/dist/extractors/providers/types.js.map +1 -0
- package/dist/extractors/signal-extractor.d.ts +30 -0
- package/dist/extractors/signal-extractor.d.ts.map +1 -0
- package/dist/extractors/signal-extractor.js +371 -0
- package/dist/extractors/signal-extractor.js.map +1 -0
- package/dist/formatters/index.d.ts +3 -0
- package/dist/formatters/index.d.ts.map +1 -0
- package/dist/formatters/index.js +3 -0
- package/dist/formatters/index.js.map +1 -0
- package/dist/formatters/json.d.ts +6 -0
- package/dist/formatters/json.d.ts.map +1 -0
- package/dist/formatters/json.js +16 -0
- package/dist/formatters/json.js.map +1 -0
- package/dist/formatters/markdown.d.ts +6 -0
- package/dist/formatters/markdown.d.ts.map +1 -0
- package/dist/formatters/markdown.js +198 -0
- package/dist/formatters/markdown.js.map +1 -0
- package/dist/hooks/handlers.d.ts +21 -0
- package/dist/hooks/handlers.d.ts.map +1 -0
- package/dist/hooks/handlers.js +22 -0
- package/dist/hooks/handlers.js.map +1 -0
- package/dist/hooks/inject.d.ts +7 -0
- package/dist/hooks/inject.d.ts.map +1 -0
- package/dist/hooks/inject.js +18 -0
- package/dist/hooks/inject.js.map +1 -0
- package/dist/hooks/install.d.ts +14 -0
- package/dist/hooks/install.d.ts.map +1 -0
- package/dist/hooks/install.js +34 -0
- package/dist/hooks/install.js.map +1 -0
- package/dist/hooks/output.d.ts +19 -0
- package/dist/hooks/output.d.ts.map +1 -0
- package/dist/hooks/output.js +13 -0
- package/dist/hooks/output.js.map +1 -0
- package/dist/hooks/recall-client.d.ts +25 -0
- package/dist/hooks/recall-client.d.ts.map +1 -0
- package/dist/hooks/recall-client.js +56 -0
- package/dist/hooks/recall-client.js.map +1 -0
- package/dist/hooks/run-event.d.ts +13 -0
- package/dist/hooks/run-event.d.ts.map +1 -0
- package/dist/hooks/run-event.js +20 -0
- package/dist/hooks/run-event.js.map +1 -0
- package/dist/hooks/settings-edit.d.ts +10 -0
- package/dist/hooks/settings-edit.d.ts.map +1 -0
- package/dist/hooks/settings-edit.js +44 -0
- package/dist/hooks/settings-edit.js.map +1 -0
- package/dist/hooks/writeback.d.ts +12 -0
- package/dist/hooks/writeback.d.ts.map +1 -0
- package/dist/hooks/writeback.js +48 -0
- package/dist/hooks/writeback.js.map +1 -0
- package/dist/install/clients/claude-code.d.ts +3 -0
- package/dist/install/clients/claude-code.d.ts.map +1 -0
- package/dist/install/clients/claude-code.js +31 -0
- package/dist/install/clients/claude-code.js.map +1 -0
- package/dist/install/clients/claude-desktop.d.ts +3 -0
- package/dist/install/clients/claude-desktop.d.ts.map +1 -0
- package/dist/install/clients/claude-desktop.js +33 -0
- package/dist/install/clients/claude-desktop.js.map +1 -0
- package/dist/install/clients/codex.d.ts +3 -0
- package/dist/install/clients/codex.d.ts.map +1 -0
- package/dist/install/clients/codex.js +33 -0
- package/dist/install/clients/codex.js.map +1 -0
- package/dist/install/clients/cursor.d.ts +3 -0
- package/dist/install/clients/cursor.d.ts.map +1 -0
- package/dist/install/clients/cursor.js +37 -0
- package/dist/install/clients/cursor.js.map +1 -0
- package/dist/install/clients/hermes.d.ts +3 -0
- package/dist/install/clients/hermes.d.ts.map +1 -0
- package/dist/install/clients/hermes.js +37 -0
- package/dist/install/clients/hermes.js.map +1 -0
- package/dist/install/clients/index.d.ts +4 -0
- package/dist/install/clients/index.d.ts.map +1 -0
- package/dist/install/clients/index.js +18 -0
- package/dist/install/clients/index.js.map +1 -0
- package/dist/install/clients/windsurf.d.ts +3 -0
- package/dist/install/clients/windsurf.d.ts.map +1 -0
- package/dist/install/clients/windsurf.js +34 -0
- package/dist/install/clients/windsurf.js.map +1 -0
- package/dist/install/command.d.ts +14 -0
- package/dist/install/command.d.ts.map +1 -0
- package/dist/install/command.js +34 -0
- package/dist/install/command.js.map +1 -0
- package/dist/install/directive.d.ts +7 -0
- package/dist/install/directive.d.ts.map +1 -0
- package/dist/install/directive.js +31 -0
- package/dist/install/directive.js.map +1 -0
- package/dist/install/index.d.ts +28 -0
- package/dist/install/index.d.ts.map +1 -0
- package/dist/install/index.js +122 -0
- package/dist/install/index.js.map +1 -0
- package/dist/install/json-config.d.ts +8 -0
- package/dist/install/json-config.d.ts.map +1 -0
- package/dist/install/json-config.js +44 -0
- package/dist/install/json-config.js.map +1 -0
- package/dist/install/marked-block.d.ts +11 -0
- package/dist/install/marked-block.d.ts.map +1 -0
- package/dist/install/marked-block.js +34 -0
- package/dist/install/marked-block.js.map +1 -0
- package/dist/install/mcp-entry.d.ts +11 -0
- package/dist/install/mcp-entry.d.ts.map +1 -0
- package/dist/install/mcp-entry.js +7 -0
- package/dist/install/mcp-entry.js.map +1 -0
- package/dist/install/skill.d.ts +4 -0
- package/dist/install/skill.d.ts.map +1 -0
- package/dist/install/skill.js +61 -0
- package/dist/install/skill.js.map +1 -0
- package/dist/install/toml-config.d.ts +4 -0
- package/dist/install/toml-config.d.ts.map +1 -0
- package/dist/install/toml-config.js +54 -0
- package/dist/install/toml-config.js.map +1 -0
- package/dist/install/types.d.ts +40 -0
- package/dist/install/types.d.ts.map +1 -0
- package/dist/install/types.js +10 -0
- package/dist/install/types.js.map +1 -0
- package/dist/install/yaml-config.d.ts +4 -0
- package/dist/install/yaml-config.d.ts.map +1 -0
- package/dist/install/yaml-config.js +19 -0
- package/dist/install/yaml-config.js.map +1 -0
- package/dist/lifecycle/down.d.ts +19 -0
- package/dist/lifecycle/down.d.ts.map +1 -0
- package/dist/lifecycle/down.js +24 -0
- package/dist/lifecycle/down.js.map +1 -0
- package/dist/lifecycle/health-poll.d.ts +19 -0
- package/dist/lifecycle/health-poll.d.ts.map +1 -0
- package/dist/lifecycle/health-poll.js +39 -0
- package/dist/lifecycle/health-poll.js.map +1 -0
- package/dist/lifecycle/install-state.d.ts +34 -0
- package/dist/lifecycle/install-state.d.ts.map +1 -0
- package/dist/lifecycle/install-state.js +70 -0
- package/dist/lifecycle/install-state.js.map +1 -0
- package/dist/lifecycle/legacy-migration.d.ts +58 -0
- package/dist/lifecycle/legacy-migration.d.ts.map +1 -0
- package/dist/lifecycle/legacy-migration.js +212 -0
- package/dist/lifecycle/legacy-migration.js.map +1 -0
- package/dist/lifecycle/lifecycle-lock.d.ts +20 -0
- package/dist/lifecycle/lifecycle-lock.d.ts.map +1 -0
- package/dist/lifecycle/lifecycle-lock.js +98 -0
- package/dist/lifecycle/lifecycle-lock.js.map +1 -0
- package/dist/lifecycle/run-up.d.ts +38 -0
- package/dist/lifecycle/run-up.d.ts.map +1 -0
- package/dist/lifecycle/run-up.js +307 -0
- package/dist/lifecycle/run-up.js.map +1 -0
- package/dist/lifecycle/status.d.ts +38 -0
- package/dist/lifecycle/status.d.ts.map +1 -0
- package/dist/lifecycle/status.js +41 -0
- package/dist/lifecycle/status.js.map +1 -0
- package/dist/lifecycle/up.d.ts +35 -0
- package/dist/lifecycle/up.d.ts.map +1 -0
- package/dist/lifecycle/up.js +45 -0
- package/dist/lifecycle/up.js.map +1 -0
- package/dist/processors/privacy.d.ts +101 -0
- package/dist/processors/privacy.d.ts.map +1 -0
- package/dist/processors/privacy.js +273 -0
- package/dist/processors/privacy.js.map +1 -0
- package/dist/profile/accumulate.d.ts +28 -0
- package/dist/profile/accumulate.d.ts.map +1 -0
- package/dist/profile/accumulate.js +48 -0
- package/dist/profile/accumulate.js.map +1 -0
- package/dist/profile/behavior.d.ts +32 -0
- package/dist/profile/behavior.d.ts.map +1 -0
- package/dist/profile/behavior.js +122 -0
- package/dist/profile/behavior.js.map +1 -0
- package/dist/profile/four-color.d.ts +12 -0
- package/dist/profile/four-color.d.ts.map +1 -0
- package/dist/profile/four-color.js +39 -0
- package/dist/profile/four-color.js.map +1 -0
- package/dist/profile/profile-synth.d.ts +27 -0
- package/dist/profile/profile-synth.d.ts.map +1 -0
- package/dist/profile/profile-synth.js +174 -0
- package/dist/profile/profile-synth.js.map +1 -0
- package/dist/profile/types.d.ts +84 -0
- package/dist/profile/types.d.ts.map +1 -0
- package/dist/profile/types.js +11 -0
- package/dist/profile/types.js.map +1 -0
- package/dist/server/api.d.ts +49 -0
- package/dist/server/api.d.ts.map +1 -0
- package/dist/server/api.js +502 -0
- package/dist/server/api.js.map +1 -0
- package/dist/server/backfill-job.d.ts +36 -0
- package/dist/server/backfill-job.d.ts.map +1 -0
- package/dist/server/backfill-job.js +88 -0
- package/dist/server/backfill-job.js.map +1 -0
- package/dist/server/backfill-routes.d.ts +7 -0
- package/dist/server/backfill-routes.d.ts.map +1 -0
- package/dist/server/backfill-routes.js +146 -0
- package/dist/server/backfill-routes.js.map +1 -0
- package/dist/server/chat-name-refresh-job.d.ts +33 -0
- package/dist/server/chat-name-refresh-job.d.ts.map +1 -0
- package/dist/server/chat-name-refresh-job.js +120 -0
- package/dist/server/chat-name-refresh-job.js.map +1 -0
- package/dist/server/chat-name-routes.d.ts +13 -0
- package/dist/server/chat-name-routes.d.ts.map +1 -0
- package/dist/server/chat-name-routes.js +81 -0
- package/dist/server/chat-name-routes.js.map +1 -0
- package/dist/server/config-routes.d.ts +10 -0
- package/dist/server/config-routes.d.ts.map +1 -0
- package/dist/server/config-routes.js +122 -0
- package/dist/server/config-routes.js.map +1 -0
- package/dist/server/context.d.ts +13 -0
- package/dist/server/context.d.ts.map +1 -0
- package/dist/server/context.js +47 -0
- package/dist/server/context.js.map +1 -0
- package/dist/server/entity.d.ts +25 -0
- package/dist/server/entity.d.ts.map +1 -0
- package/dist/server/entity.js +34 -0
- package/dist/server/entity.js.map +1 -0
- package/dist/server/event-bus.d.ts +35 -0
- package/dist/server/event-bus.d.ts.map +1 -0
- package/dist/server/event-bus.js +4 -0
- package/dist/server/event-bus.js.map +1 -0
- package/dist/server/mcp-http-runtime.d.ts +28 -0
- package/dist/server/mcp-http-runtime.d.ts.map +1 -0
- package/dist/server/mcp-http-runtime.js +24 -0
- package/dist/server/mcp-http-runtime.js.map +1 -0
- package/dist/server/mcp-http.d.ts +41 -0
- package/dist/server/mcp-http.d.ts.map +1 -0
- package/dist/server/mcp-http.js +139 -0
- package/dist/server/mcp-http.js.map +1 -0
- package/dist/server/mcp.d.ts +292 -0
- package/dist/server/mcp.d.ts.map +1 -0
- package/dist/server/mcp.js +1146 -0
- package/dist/server/mcp.js.map +1 -0
- package/dist/server/open-browser.d.ts +3 -0
- package/dist/server/open-browser.d.ts.map +1 -0
- package/dist/server/open-browser.js +12 -0
- package/dist/server/open-browser.js.map +1 -0
- package/dist/server/runtime.d.ts +13 -0
- package/dist/server/runtime.d.ts.map +1 -0
- package/dist/server/runtime.js +27 -0
- package/dist/server/runtime.js.map +1 -0
- package/dist/server/server-security.d.ts +51 -0
- package/dist/server/server-security.d.ts.map +1 -0
- package/dist/server/server-security.js +76 -0
- package/dist/server/server-security.js.map +1 -0
- package/dist/server/setup-server.d.ts +7 -0
- package/dist/server/setup-server.d.ts.map +1 -0
- package/dist/server/setup-server.js +49 -0
- package/dist/server/setup-server.js.map +1 -0
- package/dist/setup/assess-hardware.d.ts +34 -0
- package/dist/setup/assess-hardware.d.ts.map +1 -0
- package/dist/setup/assess-hardware.js +179 -0
- package/dist/setup/assess-hardware.js.map +1 -0
- package/dist/setup/connection-tests.d.ts +17 -0
- package/dist/setup/connection-tests.d.ts.map +1 -0
- package/dist/setup/connection-tests.js +69 -0
- package/dist/setup/connection-tests.js.map +1 -0
- package/dist/setup/detect-api-keys.d.ts +13 -0
- package/dist/setup/detect-api-keys.d.ts.map +1 -0
- package/dist/setup/detect-api-keys.js +41 -0
- package/dist/setup/detect-api-keys.js.map +1 -0
- package/dist/setup/detect-runtime.d.ts +14 -0
- package/dist/setup/detect-runtime.d.ts.map +1 -0
- package/dist/setup/detect-runtime.js +43 -0
- package/dist/setup/detect-runtime.js.map +1 -0
- package/dist/setup/detect-sources.d.ts +14 -0
- package/dist/setup/detect-sources.d.ts.map +1 -0
- package/dist/setup/detect-sources.js +75 -0
- package/dist/setup/detect-sources.js.map +1 -0
- package/dist/setup/doctor.d.ts +48 -0
- package/dist/setup/doctor.d.ts.map +1 -0
- package/dist/setup/doctor.js +157 -0
- package/dist/setup/doctor.js.map +1 -0
- package/dist/setup/generate-config.d.ts +13 -0
- package/dist/setup/generate-config.d.ts.map +1 -0
- package/dist/setup/generate-config.js +163 -0
- package/dist/setup/generate-config.js.map +1 -0
- package/dist/setup/index.d.ts +9 -0
- package/dist/setup/index.d.ts.map +1 -0
- package/dist/setup/index.js +9 -0
- package/dist/setup/index.js.map +1 -0
- package/dist/setup/init-wizard.d.ts +20 -0
- package/dist/setup/init-wizard.d.ts.map +1 -0
- package/dist/setup/init-wizard.js +531 -0
- package/dist/setup/init-wizard.js.map +1 -0
- package/dist/setup/terminal.d.ts +28 -0
- package/dist/setup/terminal.d.ts.map +1 -0
- package/dist/setup/terminal.js +258 -0
- package/dist/setup/terminal.js.map +1 -0
- package/dist/setup/validate-config.d.ts +30 -0
- package/dist/setup/validate-config.d.ts.map +1 -0
- package/dist/setup/validate-config.js +45 -0
- package/dist/setup/validate-config.js.map +1 -0
- package/dist/store/chunks.d.ts +25 -0
- package/dist/store/chunks.d.ts.map +1 -0
- package/dist/store/chunks.js +78 -0
- package/dist/store/chunks.js.map +1 -0
- package/dist/store/data-dir-lock.d.ts +15 -0
- package/dist/store/data-dir-lock.d.ts.map +1 -0
- package/dist/store/data-dir-lock.js +96 -0
- package/dist/store/data-dir-lock.js.map +1 -0
- package/dist/store/database.d.ts +31 -0
- package/dist/store/database.d.ts.map +1 -0
- package/dist/store/database.js +113 -0
- package/dist/store/database.js.map +1 -0
- package/dist/store/embedding.d.ts +23 -0
- package/dist/store/embedding.d.ts.map +1 -0
- package/dist/store/embedding.js +62 -0
- package/dist/store/embedding.js.map +1 -0
- package/dist/store/engine-factory.d.ts +4 -0
- package/dist/store/engine-factory.d.ts.map +1 -0
- package/dist/store/engine-factory.js +18 -0
- package/dist/store/engine-factory.js.map +1 -0
- package/dist/store/graph.d.ts +75 -0
- package/dist/store/graph.d.ts.map +1 -0
- package/dist/store/graph.js +276 -0
- package/dist/store/graph.js.map +1 -0
- package/dist/store/managed/managed-engine.d.ts +35 -0
- package/dist/store/managed/managed-engine.d.ts.map +1 -0
- package/dist/store/managed/managed-engine.js +40 -0
- package/dist/store/managed/managed-engine.js.map +1 -0
- package/dist/store/managed/managed-lock.d.ts +2 -0
- package/dist/store/managed/managed-lock.d.ts.map +1 -0
- package/dist/store/managed/managed-lock.js +68 -0
- package/dist/store/managed/managed-lock.js.map +1 -0
- package/dist/store/managed/new-install.d.ts +12 -0
- package/dist/store/managed/new-install.d.ts.map +1 -0
- package/dist/store/managed/new-install.js +23 -0
- package/dist/store/managed/new-install.js.map +1 -0
- package/dist/store/managed/pg-paths.d.ts +28 -0
- package/dist/store/managed/pg-paths.d.ts.map +1 -0
- package/dist/store/managed/pg-paths.js +41 -0
- package/dist/store/managed/pg-paths.js.map +1 -0
- package/dist/store/managed/pg-runtime-provider.d.ts +47 -0
- package/dist/store/managed/pg-runtime-provider.d.ts.map +1 -0
- package/dist/store/managed/pg-runtime-provider.js +249 -0
- package/dist/store/managed/pg-runtime-provider.js.map +1 -0
- package/dist/store/managed/pg-supervisor.d.ts +30 -0
- package/dist/store/managed/pg-supervisor.d.ts.map +1 -0
- package/dist/store/managed/pg-supervisor.js +308 -0
- package/dist/store/managed/pg-supervisor.js.map +1 -0
- package/dist/store/managed/recovery-loop.d.ts +41 -0
- package/dist/store/managed/recovery-loop.d.ts.map +1 -0
- package/dist/store/managed/recovery-loop.js +87 -0
- package/dist/store/managed/recovery-loop.js.map +1 -0
- package/dist/store/managed/stop-from-state.d.ts +11 -0
- package/dist/store/managed/stop-from-state.d.ts.map +1 -0
- package/dist/store/managed/stop-from-state.js +26 -0
- package/dist/store/managed/stop-from-state.js.map +1 -0
- package/dist/store/migrations/index.d.ts +9 -0
- package/dist/store/migrations/index.d.ts.map +1 -0
- package/dist/store/migrations/index.js +121 -0
- package/dist/store/migrations/index.js.map +1 -0
- package/dist/store/pages.d.ts +81 -0
- package/dist/store/pages.d.ts.map +1 -0
- package/dist/store/pages.js +286 -0
- package/dist/store/pages.js.map +1 -0
- package/dist/store/person-behavior.d.ts +37 -0
- package/dist/store/person-behavior.d.ts.map +1 -0
- package/dist/store/person-behavior.js +134 -0
- package/dist/store/person-behavior.js.map +1 -0
- package/dist/store/pglite-assets.d.ts +15 -0
- package/dist/store/pglite-assets.d.ts.map +1 -0
- package/dist/store/pglite-assets.js +47 -0
- package/dist/store/pglite-assets.js.map +1 -0
- package/dist/store/pglite-executor.d.ts +21 -0
- package/dist/store/pglite-executor.d.ts.map +1 -0
- package/dist/store/pglite-executor.js +61 -0
- package/dist/store/pglite-executor.js.map +1 -0
- package/dist/store/postgres-executor.d.ts +16 -0
- package/dist/store/postgres-executor.d.ts.map +1 -0
- package/dist/store/postgres-executor.js +77 -0
- package/dist/store/postgres-executor.js.map +1 -0
- package/dist/store/query-rewrite.d.ts +28 -0
- package/dist/store/query-rewrite.d.ts.map +1 -0
- package/dist/store/query-rewrite.js +97 -0
- package/dist/store/query-rewrite.js.map +1 -0
- package/dist/store/search.d.ts +65 -0
- package/dist/store/search.d.ts.map +1 -0
- package/dist/store/search.js +312 -0
- package/dist/store/search.js.map +1 -0
- package/dist/store/sequence-sync.d.ts +22 -0
- package/dist/store/sequence-sync.d.ts.map +1 -0
- package/dist/store/sequence-sync.js +46 -0
- package/dist/store/sequence-sync.js.map +1 -0
- package/dist/store/sql-executor.d.ts +17 -0
- package/dist/store/sql-executor.d.ts.map +1 -0
- package/dist/store/sql-executor.js +3 -0
- package/dist/store/sql-executor.js.map +1 -0
- package/dist/store/store-meta.d.ts +10 -0
- package/dist/store/store-meta.d.ts.map +1 -0
- package/dist/store/store-meta.js +13 -0
- package/dist/store/store-meta.js.map +1 -0
- package/dist/store/tags.d.ts +10 -0
- package/dist/store/tags.d.ts.map +1 -0
- package/dist/store/tags.js +35 -0
- package/dist/store/tags.js.map +1 -0
- package/dist/store/timeline.d.ts +38 -0
- package/dist/store/timeline.d.ts.map +1 -0
- package/dist/store/timeline.js +173 -0
- package/dist/store/timeline.js.map +1 -0
- package/dist/store/trgm-search.d.ts +13 -0
- package/dist/store/trgm-search.d.ts.map +1 -0
- package/dist/store/trgm-search.js +53 -0
- package/dist/store/trgm-search.js.map +1 -0
- package/dist/store/wikilink.d.ts +17 -0
- package/dist/store/wikilink.d.ts.map +1 -0
- package/dist/store/wikilink.js +58 -0
- package/dist/store/wikilink.js.map +1 -0
- package/dist/sync/obsidian.d.ts +136 -0
- package/dist/sync/obsidian.d.ts.map +1 -0
- package/dist/sync/obsidian.js +543 -0
- package/dist/sync/obsidian.js.map +1 -0
- package/dist/synth/cache.d.ts +17 -0
- package/dist/synth/cache.d.ts.map +1 -0
- package/dist/synth/cache.js +67 -0
- package/dist/synth/cache.js.map +1 -0
- package/dist/synth/citations.d.ts +12 -0
- package/dist/synth/citations.d.ts.map +1 -0
- package/dist/synth/citations.js +28 -0
- package/dist/synth/citations.js.map +1 -0
- package/dist/synth/context.d.ts +10 -0
- package/dist/synth/context.d.ts.map +1 -0
- package/dist/synth/context.js +67 -0
- package/dist/synth/context.js.map +1 -0
- package/dist/synth/engine.d.ts +16 -0
- package/dist/synth/engine.d.ts.map +1 -0
- package/dist/synth/engine.js +111 -0
- package/dist/synth/engine.js.map +1 -0
- package/dist/synth/gaps.d.ts +17 -0
- package/dist/synth/gaps.d.ts.map +1 -0
- package/dist/synth/gaps.js +57 -0
- package/dist/synth/gaps.js.map +1 -0
- package/dist/synth/index.d.ts +6 -0
- package/dist/synth/index.d.ts.map +1 -0
- package/dist/synth/index.js +6 -0
- package/dist/synth/index.js.map +1 -0
- package/dist/synth/intent.d.ts +6 -0
- package/dist/synth/intent.d.ts.map +1 -0
- package/dist/synth/intent.js +13 -0
- package/dist/synth/intent.js.map +1 -0
- package/dist/synth/intents/daily-report.d.ts +7 -0
- package/dist/synth/intents/daily-report.d.ts.map +1 -0
- package/dist/synth/intents/daily-report.js +37 -0
- package/dist/synth/intents/daily-report.js.map +1 -0
- package/dist/synth/intents/index.d.ts +2 -0
- package/dist/synth/intents/index.d.ts.map +1 -0
- package/dist/synth/intents/index.js +12 -0
- package/dist/synth/intents/index.js.map +1 -0
- package/dist/synth/intents/person-strategy.d.ts +40 -0
- package/dist/synth/intents/person-strategy.d.ts.map +1 -0
- package/dist/synth/intents/person-strategy.js +66 -0
- package/dist/synth/intents/person-strategy.js.map +1 -0
- package/dist/synth/intents/recall.d.ts +8 -0
- package/dist/synth/intents/recall.d.ts.map +1 -0
- package/dist/synth/intents/recall.js +26 -0
- package/dist/synth/intents/recall.js.map +1 -0
- package/dist/synth/intents/troubleshoot.d.ts +11 -0
- package/dist/synth/intents/troubleshoot.d.ts.map +1 -0
- package/dist/synth/intents/troubleshoot.js +66 -0
- package/dist/synth/intents/troubleshoot.js.map +1 -0
- package/dist/synth/scope.d.ts +13 -0
- package/dist/synth/scope.d.ts.map +1 -0
- package/dist/synth/scope.js +139 -0
- package/dist/synth/scope.js.map +1 -0
- package/dist/synth/types.d.ts +117 -0
- package/dist/synth/types.d.ts.map +1 -0
- package/dist/synth/types.js +2 -0
- package/dist/synth/types.js.map +1 -0
- package/package.json +98 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,1579 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
|
+
import { Command } from "commander";
|
|
8
|
+
import { planStartup, shouldOpenBrowserOnServe } from "./cli-helpers.js";
|
|
9
|
+
import { createStores, openIdentityStore } from "./cli-stores.js";
|
|
10
|
+
import { normalizeDocsConfig } from "./collectors/feishu/docs/config.js";
|
|
11
|
+
import { FullCardBuilder } from "./collectors/feishu/docs/full-builder.js";
|
|
12
|
+
import { runDocSource } from "./collectors/feishu/docs/run.js";
|
|
13
|
+
import { failedCards, summarizeCards } from "./collectors/feishu/docs/status.js";
|
|
14
|
+
import { loadExistingCard, writeCard } from "./collectors/feishu/docs/store-writer.js";
|
|
15
|
+
import { LarkCliHttpClient } from "./collectors/feishu/lark-cli-client.js";
|
|
16
|
+
import { resolveSelfOpenId } from "./collectors/feishu/self-open-id.js";
|
|
17
|
+
import { createClaudeCodeCollector, createCodexCollector, createFeishuCollector, createHermesCollector, getAllCollectors, getCollector, registerCollector, resetRegistry, } from "./collectors/index.js";
|
|
18
|
+
import { Consolidator } from "./consolidator/consolidator.js";
|
|
19
|
+
import { loadConfig, resolveConfigPath, } from "./core/config.js";
|
|
20
|
+
import { CursorStore } from "./core/cursors.js";
|
|
21
|
+
import { getMissingEnvVarsForCommand, validateEnvForCommand } from "./core/env-validation.js";
|
|
22
|
+
import { PersonIdentityStore } from "./core/person-identity.js";
|
|
23
|
+
import { runPipeline } from "./core/pipeline.js";
|
|
24
|
+
import { buildPipelineConfig } from "./core/pipeline-factory.js";
|
|
25
|
+
import { ensureStateDir, statePath } from "./core/state.js";
|
|
26
|
+
import { rawYamlHash, readDaemonState, servingSubsetHash, } from "./daemon/autostart/daemon-state.js";
|
|
27
|
+
import { disableAutostart, statusAutostart } from "./daemon/autostart/index.js";
|
|
28
|
+
import { nodeRunner } from "./daemon/autostart/runner.js";
|
|
29
|
+
import { ReloadManager } from "./daemon/reload-manager.js";
|
|
30
|
+
import { buildServeRuntime, ServeRuntimeHolder } from "./daemon/serve-runtime.js";
|
|
31
|
+
import { VERSION } from "./embedded-assets.generated.js";
|
|
32
|
+
import { createLLMProvider, createMockProvider } from "./extractors/providers/index.js";
|
|
33
|
+
import { hooksInstall, hooksUninstall } from "./hooks/install.js";
|
|
34
|
+
import { runHookEvent } from "./hooks/run-event.js";
|
|
35
|
+
import { runInstall, runUninstall } from "./install/index.js";
|
|
36
|
+
import { scaffoldSkill } from "./install/skill.js";
|
|
37
|
+
import { down } from "./lifecycle/down.js";
|
|
38
|
+
import { migrateLegacyData } from "./lifecycle/legacy-migration.js";
|
|
39
|
+
import { acquireLifecycleLock } from "./lifecycle/lifecycle-lock.js";
|
|
40
|
+
import { runUp } from "./lifecycle/run-up.js";
|
|
41
|
+
import { computeStatus, formatManagedStatus } from "./lifecycle/status.js";
|
|
42
|
+
import { createApiApp } from "./server/api.js";
|
|
43
|
+
import { getSessionContext } from "./server/context.js";
|
|
44
|
+
import { createMcpServer } from "./server/mcp.js";
|
|
45
|
+
import { createMcpHttpApp } from "./server/mcp-http.js";
|
|
46
|
+
import { assertLoopbackOrThrow, resolveMcpHttpRuntime } from "./server/mcp-http-runtime.js";
|
|
47
|
+
import { openBrowser } from "./server/open-browser.js";
|
|
48
|
+
import { startServer } from "./server/runtime.js";
|
|
49
|
+
import { resolveServeSecurity } from "./server/server-security.js";
|
|
50
|
+
import { managedPaths, readManagedState } from "./store/managed/pg-paths.js";
|
|
51
|
+
import { startRecoveryLoop } from "./store/managed/recovery-loop.js";
|
|
52
|
+
import { stopManagedFromState } from "./store/managed/stop-from-state.js";
|
|
53
|
+
import { PersonBehaviorStore } from "./store/person-behavior.js";
|
|
54
|
+
function resolveProjectPath(path, projectRoot) {
|
|
55
|
+
if (!path)
|
|
56
|
+
return undefined;
|
|
57
|
+
if (path.startsWith("~/"))
|
|
58
|
+
return resolve(homedir(), path.slice(2));
|
|
59
|
+
if (path === "~")
|
|
60
|
+
return homedir();
|
|
61
|
+
if (isAbsolute(path))
|
|
62
|
+
return path;
|
|
63
|
+
return resolve(projectRoot, path);
|
|
64
|
+
}
|
|
65
|
+
function bootstrapCollectors(sources, projectRoot) {
|
|
66
|
+
resetRegistry();
|
|
67
|
+
const agentConfigs = {
|
|
68
|
+
"claude-code": { factory: createClaudeCodeCollector, config: sources["claude-code"] },
|
|
69
|
+
codex: { factory: createCodexCollector, config: sources.codex },
|
|
70
|
+
hermes: { factory: createHermesCollector, config: sources.hermes },
|
|
71
|
+
};
|
|
72
|
+
for (const [_id, { factory, config }] of Object.entries(agentConfigs)) {
|
|
73
|
+
if (config?.enabled !== false) {
|
|
74
|
+
registerCollector(factory(resolveProjectPath(config?.base_dir, projectRoot)));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (sources.feishu?.enabled !== false && sources.feishu?.app_id) {
|
|
78
|
+
registerCollector(createFeishuCollector(sources.feishu));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Try to extract feishu.lark_bin from an existing config so the setup UI's
|
|
82
|
+
// "Feishu — Test Connection" button doesn't fall through to the hardcoded
|
|
83
|
+
// ~/.local/bin/lark path. Silent on missing file or parse errors (the wizard
|
|
84
|
+
// may be running because the YAML doesn't exist yet).
|
|
85
|
+
function readLarkBinFromConfig(configPath) {
|
|
86
|
+
const path = configPath ?? resolve(process.cwd(), "memkin.yaml");
|
|
87
|
+
if (!existsSync(path))
|
|
88
|
+
return undefined;
|
|
89
|
+
try {
|
|
90
|
+
return loadConfig(path).sources?.feishu?.lark_bin;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const program = new Command();
|
|
97
|
+
program
|
|
98
|
+
.name("memkin")
|
|
99
|
+
.description("Local-first personal memory extraction and storage")
|
|
100
|
+
.version(VERSION);
|
|
101
|
+
// One-shot legacy auto-migration (memoark → memkin). Runs BEFORE every command's
|
|
102
|
+
// action — i.e. before loadConfig reads memkin.yaml or any store opens — so
|
|
103
|
+
// existing users' data/config/state are moved to the new paths seamlessly.
|
|
104
|
+
// preAction fires for subcommands AND the default program action, covering
|
|
105
|
+
// serve / extract / init / start (and the Tauri sidecar, which shells out to
|
|
106
|
+
// `memkin serve`). All notices go to STDERR: in `serve --mcp` stdout is the
|
|
107
|
+
// JSON-RPC channel and must stay byte-clean, so migration output can never use it.
|
|
108
|
+
program.hook("preAction", () => {
|
|
109
|
+
try {
|
|
110
|
+
migrateLegacyData({ home: homedir(), cwd: process.cwd(), env: process.env });
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
// Migration is best-effort: a failure must never block the command. Report
|
|
114
|
+
// to stderr and continue (the command will fall through to fresh defaults).
|
|
115
|
+
console.error(`[migration] legacy data migration skipped: ${err instanceof Error ? err.message : String(err)}`);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
program
|
|
119
|
+
.command("init")
|
|
120
|
+
.description("Interactive setup wizard - generates memkin.yaml")
|
|
121
|
+
.option("--auto", "Automatic mode, no prompts")
|
|
122
|
+
.option("--force", "Overwrite existing configuration")
|
|
123
|
+
.option("-c, --config <path>", "Path to output config file (default: memkin.yaml)")
|
|
124
|
+
.option("--no-tui", "Use non-TUI fallback")
|
|
125
|
+
.option("--web", "Launch browser-based setup UI")
|
|
126
|
+
.action(async (options) => {
|
|
127
|
+
if (options.web) {
|
|
128
|
+
const { startSetupServer } = await import("./server/setup-server.js");
|
|
129
|
+
await startSetupServer({
|
|
130
|
+
configPath: options.config,
|
|
131
|
+
larkBin: readLarkBinFromConfig(options.config),
|
|
132
|
+
});
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
const { runInit } = await import("./setup/index.js");
|
|
137
|
+
await runInit({
|
|
138
|
+
auto: options.auto,
|
|
139
|
+
force: options.force,
|
|
140
|
+
configPath: options.config,
|
|
141
|
+
tui: options.tui,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
/**
|
|
150
|
+
* Extract command - main pipeline execution
|
|
151
|
+
*/
|
|
152
|
+
program
|
|
153
|
+
.command("extract")
|
|
154
|
+
.description("Extract signals from a platform or source")
|
|
155
|
+
.option("-s, --source <name>", "Source/collector name (e.g., claude-code, codex, hermes, feishu, or 'all' for all enabled sources)", "claude-code")
|
|
156
|
+
.option("-c, --config <path>", "Path to config file (default: memkin.yaml)")
|
|
157
|
+
.option("-f, --format <type>", "Output format (json|markdown)", "json")
|
|
158
|
+
.option("-a, --adapter <type>", "Output adapter (store|file|gbrain|stdout)", "store")
|
|
159
|
+
.option("-o, --output <dir>", "Output directory for file adapter")
|
|
160
|
+
.option("--since <date>", "Only process messages since date (ISO 8601 or relative: 1d, 2h, 30m)")
|
|
161
|
+
.option("--limit <n>", "Limit number of messages to process", undefined)
|
|
162
|
+
.option("--dry-run", "Do not write outputs, only test pipeline")
|
|
163
|
+
.action(async (options) => {
|
|
164
|
+
try {
|
|
165
|
+
// Load configuration
|
|
166
|
+
const config = loadConfig(options.config);
|
|
167
|
+
const { projectRoot } = config.__context;
|
|
168
|
+
// Ensure state directory exists
|
|
169
|
+
ensureStateDir(projectRoot);
|
|
170
|
+
// Bootstrap collectors from config
|
|
171
|
+
bootstrapCollectors(config.sources, projectRoot);
|
|
172
|
+
// Determine which sources to process
|
|
173
|
+
let sourceIds;
|
|
174
|
+
if (options.source === "all") {
|
|
175
|
+
sourceIds = getAllCollectors().map((c) => c.id);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
sourceIds = [options.source];
|
|
179
|
+
}
|
|
180
|
+
// Create LLM provider based on config (shared across all sources)
|
|
181
|
+
let provider;
|
|
182
|
+
if (!options.dryRun) {
|
|
183
|
+
validateEnvForCommand(config, "extract");
|
|
184
|
+
const llmConfig = config.llm;
|
|
185
|
+
const envKey = llmConfig.provider === "anthropic"
|
|
186
|
+
? process.env.ANTHROPIC_API_KEY
|
|
187
|
+
: process.env.OPENAI_API_KEY;
|
|
188
|
+
if (!llmConfig.api_key && !envKey) {
|
|
189
|
+
const envVarName = llmConfig.provider === "anthropic" ? "ANTHROPIC_API_KEY" : "OPENAI_API_KEY";
|
|
190
|
+
console.error(`Error: No API key configured. Set api_key in memkin.yaml or ${envVarName} env var.`);
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
if (!llmConfig.api_key) {
|
|
194
|
+
llmConfig.api_key = envKey;
|
|
195
|
+
}
|
|
196
|
+
provider = createLLMProvider(llmConfig);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
provider = createMockProvider(new Map());
|
|
200
|
+
}
|
|
201
|
+
// Build pipeline configuration
|
|
202
|
+
const pipelineConfig = buildPipelineConfig(config, options.output || process.cwd(), projectRoot);
|
|
203
|
+
// Parse options
|
|
204
|
+
const format = ["json", "markdown"].includes(options.format) ? options.format : "json";
|
|
205
|
+
const adapter = ["store", "file", "gbrain", "stdout"].includes(options.adapter)
|
|
206
|
+
? options.adapter
|
|
207
|
+
: "store";
|
|
208
|
+
const limit = options.limit ? parseInt(options.limit, 10) : undefined;
|
|
209
|
+
// Create stores if using store adapter
|
|
210
|
+
let stores;
|
|
211
|
+
if (adapter === "store") {
|
|
212
|
+
stores = await createStores(config);
|
|
213
|
+
}
|
|
214
|
+
// Parse relative since values
|
|
215
|
+
let sinceValue = options.since;
|
|
216
|
+
if (sinceValue) {
|
|
217
|
+
const relMatch = sinceValue.match(/^(\d+)([dhm])$/);
|
|
218
|
+
if (relMatch) {
|
|
219
|
+
const amount = parseInt(relMatch[1], 10);
|
|
220
|
+
const unit = relMatch[2];
|
|
221
|
+
const ms = unit === "d" ? amount * 86400000 : unit === "h" ? amount * 3600000 : amount * 60000;
|
|
222
|
+
sinceValue = new Date(Date.now() - ms).toISOString();
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
let anyFailed = false;
|
|
226
|
+
// Process each source
|
|
227
|
+
for (const sourceId of sourceIds) {
|
|
228
|
+
const collector = getCollector(sourceId);
|
|
229
|
+
if (!collector) {
|
|
230
|
+
console.error(`Error: Unknown source '${sourceId}'`);
|
|
231
|
+
anyFailed = true;
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
// Health check
|
|
235
|
+
const health = await collector.healthCheck();
|
|
236
|
+
if (!health.ok) {
|
|
237
|
+
if (options.source === "all") {
|
|
238
|
+
console.warn(`Warning: ${sourceId} not available — ${health.message}. Skipping.`);
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
console.error(`Error: ${sourceId} health check failed — ${health.message}`);
|
|
242
|
+
process.exit(1);
|
|
243
|
+
}
|
|
244
|
+
// Run pipeline for this source
|
|
245
|
+
console.log(`\n--- Extracting from: ${sourceId} ---`);
|
|
246
|
+
console.log(`Format: ${format}, Adapter: ${adapter}`);
|
|
247
|
+
if (options.dryRun)
|
|
248
|
+
console.log("DRY-RUN mode enabled");
|
|
249
|
+
if (sinceValue)
|
|
250
|
+
console.log(`Since: ${sinceValue}`);
|
|
251
|
+
if (limit)
|
|
252
|
+
console.log(`Limit: ${limit} messages`);
|
|
253
|
+
console.log("");
|
|
254
|
+
try {
|
|
255
|
+
const result = await runPipeline(pipelineConfig, {
|
|
256
|
+
source: collector,
|
|
257
|
+
provider,
|
|
258
|
+
format: format,
|
|
259
|
+
adapter: adapter,
|
|
260
|
+
stores,
|
|
261
|
+
dryRun: options.dryRun || false,
|
|
262
|
+
since: sinceValue,
|
|
263
|
+
limit,
|
|
264
|
+
});
|
|
265
|
+
// Report results
|
|
266
|
+
console.log("Pipeline execution complete:");
|
|
267
|
+
console.log(` Total messages: ${result.totalMessages}`);
|
|
268
|
+
console.log(` Total blocks: ${result.totalBlocks}`);
|
|
269
|
+
console.log(` OK blocks: ${result.okBlocks}`);
|
|
270
|
+
console.log(` Skipped blocks: ${result.skippedBlocks}`);
|
|
271
|
+
console.log(` Failed blocks: ${result.failedBlocks}`);
|
|
272
|
+
if (result.warnings.length > 0) {
|
|
273
|
+
console.log("\nWarnings:");
|
|
274
|
+
for (const warning of result.warnings) {
|
|
275
|
+
console.log(` - ${warning}`);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (result.fatal) {
|
|
279
|
+
console.error(`\nFatal error: ${result.error}`);
|
|
280
|
+
anyFailed = true;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
console.error(`\nPipeline failed for ${sourceId}:`, error instanceof Error ? error.message : String(error));
|
|
285
|
+
anyFailed = true;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
// Close stores if they were created
|
|
289
|
+
if (stores) {
|
|
290
|
+
await stores.db.close();
|
|
291
|
+
}
|
|
292
|
+
if (anyFailed) {
|
|
293
|
+
process.exit(1);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
console.error("Extract failed:", error instanceof Error ? error.message : String(error));
|
|
298
|
+
process.exit(1);
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
/**
|
|
302
|
+
* Doctor command - diagnose configuration and setup
|
|
303
|
+
*/
|
|
304
|
+
program
|
|
305
|
+
.command("doctor")
|
|
306
|
+
.description("Diagnose configuration and connectivity")
|
|
307
|
+
.option("-c, --config <path>", "Path to config file (default: memkin.yaml)")
|
|
308
|
+
.action(async (options) => {
|
|
309
|
+
const issues = [];
|
|
310
|
+
const warnings = [];
|
|
311
|
+
const ok = [];
|
|
312
|
+
// Check config file
|
|
313
|
+
const configPath = resolveConfigPath(options.config);
|
|
314
|
+
let config = null;
|
|
315
|
+
if (existsSync(configPath)) {
|
|
316
|
+
ok.push(`Configuration file found: ${configPath}`);
|
|
317
|
+
try {
|
|
318
|
+
config = loadConfig(options.config);
|
|
319
|
+
ok.push("Configuration loaded successfully");
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
issues.push(`Configuration loading failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
warnings.push(`Configuration file not found: ${configPath}`);
|
|
327
|
+
warnings.push("Create one with: memkin init");
|
|
328
|
+
}
|
|
329
|
+
// Check state directory
|
|
330
|
+
const projectRoot = config?.__context.projectRoot ?? dirname(configPath);
|
|
331
|
+
const stateDir = resolve(projectRoot, ".memkin");
|
|
332
|
+
if (existsSync(stateDir)) {
|
|
333
|
+
ok.push(`State directory exists: ${stateDir}`);
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
warnings.push(`State directory does not exist: ${stateDir}`);
|
|
337
|
+
warnings.push("It will be created automatically on first extract");
|
|
338
|
+
}
|
|
339
|
+
const cwdStateDir = resolve(process.cwd(), ".memkin");
|
|
340
|
+
if (cwdStateDir !== stateDir && existsSync(cwdStateDir)) {
|
|
341
|
+
warnings.push(`Legacy state directory found at current cwd: ${cwdStateDir}`);
|
|
342
|
+
warnings.push(`Current config-root state directory is: ${stateDir}`);
|
|
343
|
+
warnings.push("Move cursor/dedup files manually if you intended to reuse the old state.");
|
|
344
|
+
}
|
|
345
|
+
// Check LLM configuration
|
|
346
|
+
if (config) {
|
|
347
|
+
const missingEnvVars = getMissingEnvVarsForCommand(config, "doctor");
|
|
348
|
+
if (missingEnvVars.length > 0) {
|
|
349
|
+
warnings.push(`Missing environment variables: ${missingEnvVars.join(", ")}`);
|
|
350
|
+
warnings.push(`Referenced by: ${config.__context.configPath}`);
|
|
351
|
+
}
|
|
352
|
+
if (config.llm?.provider && config.llm?.model) {
|
|
353
|
+
ok.push(`LLM provider configured: ${config.llm.provider} / ${config.llm.model}`);
|
|
354
|
+
const envKey = config.llm.provider === "anthropic" ? "ANTHROPIC_API_KEY" : "OPENAI_API_KEY";
|
|
355
|
+
if (!missingEnvVars.includes(envKey)) {
|
|
356
|
+
ok.push(`${config.llm.provider} API key configured`);
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
warnings.push(`${envKey} environment variable not set and no api_key in config`);
|
|
360
|
+
warnings.push(`Set ${envKey} or add api_key to llm config`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
issues.push("LLM provider or model not configured");
|
|
365
|
+
}
|
|
366
|
+
// Check sources
|
|
367
|
+
bootstrapCollectors(config.sources, config.__context.projectRoot);
|
|
368
|
+
for (const collector of getAllCollectors()) {
|
|
369
|
+
const health = await collector.healthCheck();
|
|
370
|
+
if (health.ok) {
|
|
371
|
+
ok.push(`Source ${collector.id}: ${health.message}`);
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
warnings.push(`Source ${collector.id}: ${health.message}`);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
// Check Postgres engine
|
|
378
|
+
if ((config.store?.engine ?? "pglite") === "postgres") {
|
|
379
|
+
const dbUrl = config.store?.database_url;
|
|
380
|
+
if (!dbUrl) {
|
|
381
|
+
issues.push("Postgres: store.database_url is not set");
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
const { checkPostgres } = await import("./setup/doctor.js");
|
|
385
|
+
const { maskDatabaseUrl } = await import("./config-center/secrets.js");
|
|
386
|
+
const pg = await checkPostgres(dbUrl);
|
|
387
|
+
if (!pg.connected) {
|
|
388
|
+
issues.push(`Postgres: cannot connect to ${maskDatabaseUrl(dbUrl)}`);
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
ok.push(`Postgres: connected ✓ (${maskDatabaseUrl(dbUrl)})`);
|
|
392
|
+
if (pg.vectorReady) {
|
|
393
|
+
ok.push("Postgres: pgvector ready ✓");
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
issues.push("Postgres: pgvector extension is not available or cannot be created — " +
|
|
397
|
+
"install pgvector and ensure the role has permission to CREATE EXTENSION");
|
|
398
|
+
}
|
|
399
|
+
const { checkPgIdSequences } = await import("./setup/doctor.js");
|
|
400
|
+
const desync = await checkPgIdSequences(dbUrl);
|
|
401
|
+
if (desync === null) {
|
|
402
|
+
warnings.push("Postgres: id sequence check could not run (connection error)");
|
|
403
|
+
}
|
|
404
|
+
else if (desync.length > 0) {
|
|
405
|
+
warnings.push(`Postgres: id sequence desync on ${desync
|
|
406
|
+
.map((d) => `${d.table} (max id ${d.maxId}, sequence would yield ${d.nextValue})`)
|
|
407
|
+
.join(", ")} — usually caused by an id-preserving import/restore. ` +
|
|
408
|
+
"Writes to new slugs fail with duplicate-key errors until repaired; " +
|
|
409
|
+
"memoark repairs this automatically the next time the store is opened " +
|
|
410
|
+
"(any command that touches the store, e.g. `memoark serve`).");
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
ok.push("Postgres: id sequences in sync ✓");
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
// Check managed Postgres engine
|
|
419
|
+
if (config.store?.engine === "managed") {
|
|
420
|
+
const { checkManagedPostgres } = await import("./setup/doctor.js");
|
|
421
|
+
const checks = await checkManagedPostgres({
|
|
422
|
+
home: homedir(),
|
|
423
|
+
managedConfig: config.store.managed,
|
|
424
|
+
});
|
|
425
|
+
for (const check of checks) {
|
|
426
|
+
if (check.severity === "ok") {
|
|
427
|
+
ok.push(check.message);
|
|
428
|
+
}
|
|
429
|
+
else if (check.severity === "warn") {
|
|
430
|
+
warnings.push(check.message);
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
issues.push(check.message);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
// Report results
|
|
439
|
+
console.log("=== Memkin Diagnostic Report ===\n");
|
|
440
|
+
if (ok.length > 0) {
|
|
441
|
+
console.log("✓ OK:");
|
|
442
|
+
for (const msg of ok) {
|
|
443
|
+
console.log(` ${msg}`);
|
|
444
|
+
}
|
|
445
|
+
console.log("");
|
|
446
|
+
}
|
|
447
|
+
if (warnings.length > 0) {
|
|
448
|
+
console.log("⚠ Warnings:");
|
|
449
|
+
for (const msg of warnings) {
|
|
450
|
+
console.log(` ${msg}`);
|
|
451
|
+
}
|
|
452
|
+
console.log("");
|
|
453
|
+
}
|
|
454
|
+
if (issues.length > 0) {
|
|
455
|
+
console.log("✗ Issues:");
|
|
456
|
+
for (const msg of issues) {
|
|
457
|
+
console.log(` ${msg}`);
|
|
458
|
+
}
|
|
459
|
+
console.log("");
|
|
460
|
+
process.exit(1);
|
|
461
|
+
}
|
|
462
|
+
console.log("No critical issues found.");
|
|
463
|
+
});
|
|
464
|
+
/**
|
|
465
|
+
* Config subcommand group
|
|
466
|
+
*/
|
|
467
|
+
const configCmd = program.command("config").description("Manage configuration");
|
|
468
|
+
configCmd
|
|
469
|
+
.command("init")
|
|
470
|
+
.description("Generate memkin.yaml (alias for 'memkin init')")
|
|
471
|
+
.option("--auto", "Automatic mode, no prompts")
|
|
472
|
+
.option("--force", "Overwrite existing configuration")
|
|
473
|
+
.option("-c, --config <path>", "Path to output config file (default: memkin.yaml)")
|
|
474
|
+
.option("--no-tui", "Use non-TUI fallback")
|
|
475
|
+
.action(async (options) => {
|
|
476
|
+
try {
|
|
477
|
+
const { runInit } = await import("./setup/index.js");
|
|
478
|
+
await runInit({
|
|
479
|
+
auto: options.auto,
|
|
480
|
+
force: options.force,
|
|
481
|
+
configPath: options.config,
|
|
482
|
+
tui: options.tui,
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
catch (error) {
|
|
486
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
487
|
+
process.exit(1);
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
configCmd
|
|
491
|
+
.command("edit")
|
|
492
|
+
.description("Edit configuration in browser UI")
|
|
493
|
+
.option("--web", "Launch browser-based settings UI (default behavior)")
|
|
494
|
+
.option("-c, --config <path>", "Path to config file (default: memkin.yaml)")
|
|
495
|
+
.action(async (options) => {
|
|
496
|
+
const { startSetupServer } = await import("./server/setup-server.js");
|
|
497
|
+
await startSetupServer({
|
|
498
|
+
configPath: options.config,
|
|
499
|
+
larkBin: readLarkBinFromConfig(options.config),
|
|
500
|
+
});
|
|
501
|
+
});
|
|
502
|
+
/**
|
|
503
|
+
* Sources subcommand group
|
|
504
|
+
*/
|
|
505
|
+
const sourcesCmd = program.command("sources").description("Manage data sources");
|
|
506
|
+
sourcesCmd
|
|
507
|
+
.command("list")
|
|
508
|
+
.description("List available sources")
|
|
509
|
+
.option("-c, --config <path>", "Path to config file")
|
|
510
|
+
.action((options) => {
|
|
511
|
+
const config = loadConfig(options.config);
|
|
512
|
+
bootstrapCollectors(config.sources, config.__context.projectRoot);
|
|
513
|
+
const collectors = getAllCollectors();
|
|
514
|
+
console.log("Available sources:\n");
|
|
515
|
+
for (const c of collectors) {
|
|
516
|
+
console.log(` ${c.id} ✓ enabled`);
|
|
517
|
+
console.log(` ${c.description}`);
|
|
518
|
+
console.log("");
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
sourcesCmd
|
|
522
|
+
.command("test <name>")
|
|
523
|
+
.description("Test source connectivity and health")
|
|
524
|
+
.option("-c, --config <path>", "Path to config file")
|
|
525
|
+
.action(async (name, options) => {
|
|
526
|
+
try {
|
|
527
|
+
const config = loadConfig(options.config);
|
|
528
|
+
bootstrapCollectors(config.sources, config.__context.projectRoot);
|
|
529
|
+
const collector = getCollector(name);
|
|
530
|
+
if (!collector) {
|
|
531
|
+
console.error(`Error: Unknown source '${name}'`);
|
|
532
|
+
process.exit(1);
|
|
533
|
+
}
|
|
534
|
+
console.log(`Testing source: ${name}\n`);
|
|
535
|
+
const health = await collector.healthCheck();
|
|
536
|
+
if (health.ok) {
|
|
537
|
+
console.log(`✓ ${health.message}`);
|
|
538
|
+
}
|
|
539
|
+
else {
|
|
540
|
+
console.log(`✗ ${health.message}`);
|
|
541
|
+
process.exit(1);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
catch (error) {
|
|
545
|
+
console.error("Test failed:", error instanceof Error ? error.message : String(error));
|
|
546
|
+
process.exit(1);
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
async function runServe(options) {
|
|
550
|
+
{
|
|
551
|
+
const serveConfigPath = options.config ?? resolve(process.cwd(), "memkin.yaml");
|
|
552
|
+
if (!existsSync(serveConfigPath)) {
|
|
553
|
+
console.error("No configuration file found.\n" +
|
|
554
|
+
"Run `memkin start` for one-step setup + launch, or `memkin init --web` to configure first.");
|
|
555
|
+
process.exit(1);
|
|
556
|
+
}
|
|
557
|
+
const config = loadConfig(options.config);
|
|
558
|
+
// Anchor the .memkin state dir to the config's project root, not process.cwd().
|
|
559
|
+
// A Finder-launched sidecar has cwd=/, so the default would try to mkdir /.memkin
|
|
560
|
+
// (EROFS on macOS). projectRoot = dirname(configPath), so it lives beside the config.
|
|
561
|
+
const stateDir = ensureStateDir(config.__context.projectRoot);
|
|
562
|
+
const missingEnvVars = getMissingEnvVarsForCommand(config, "serve");
|
|
563
|
+
if (missingEnvVars.length > 0) {
|
|
564
|
+
console.warn(`[warn] Missing env vars: ${missingEnvVars.join(", ")} (referenced by ${config.__context.configPath})`);
|
|
565
|
+
}
|
|
566
|
+
const stores = await createStores(config);
|
|
567
|
+
// P1-1: recovery loop is a PROCESS-LEVEL resource — started from stores.supervisor,
|
|
568
|
+
// never placed inside the ServeRuntimeHolder/runtime (which is disposed on every reload).
|
|
569
|
+
const recovery = stores.supervisor
|
|
570
|
+
? startRecoveryLoop(stores.supervisor, { intervalMs: 3000 })
|
|
571
|
+
: undefined;
|
|
572
|
+
const initialRuntime = await buildServeRuntime(config, stores, stateDir);
|
|
573
|
+
const holder = new ServeRuntimeHolder(initialRuntime);
|
|
574
|
+
if (config.scheduler?.enabled)
|
|
575
|
+
await holder.current.scheduler?.start();
|
|
576
|
+
const reloadManager = new ReloadManager({
|
|
577
|
+
holder,
|
|
578
|
+
// only read once at construction for the initial signature; ReloadManager tracks lastConfig internally afterward
|
|
579
|
+
currentConfig: () => config,
|
|
580
|
+
buildRuntime: (next) => buildServeRuntime(next, stores, stateDir),
|
|
581
|
+
onRestartRequired: () => console.warn("[reload] store/engine change saved — restart the daemon (`memkin up` or restart serve) to apply; the running process still uses the previous database."),
|
|
582
|
+
});
|
|
583
|
+
const storesWithDaemon = {
|
|
584
|
+
...stores,
|
|
585
|
+
getDaemonStatus: () => holder.current.getDaemonStatus(),
|
|
586
|
+
// getter: always reads the current runtime, so a Tier-2 swap is seen by routes
|
|
587
|
+
get chatNameRefreshJob() {
|
|
588
|
+
return holder.current.chatNameRefreshJob;
|
|
589
|
+
},
|
|
590
|
+
};
|
|
591
|
+
let shuttingDown = false;
|
|
592
|
+
const shutdown = async () => {
|
|
593
|
+
if (shuttingDown)
|
|
594
|
+
return; // 防重入:连按 Ctrl-C 不会二次 db.close()
|
|
595
|
+
shuttingDown = true;
|
|
596
|
+
// P1-1: stop recovery loop first, then dispose supervisor monitor (NOT the cluster),
|
|
597
|
+
// then dispose the runtime, then close the DB connection.
|
|
598
|
+
recovery?.stop();
|
|
599
|
+
stores.supervisor?.dispose(); // stops monitor only — does NOT stop the cluster
|
|
600
|
+
await holder.current.dispose();
|
|
601
|
+
try {
|
|
602
|
+
await stores.db.close(); // 触发锁 release
|
|
603
|
+
}
|
|
604
|
+
finally {
|
|
605
|
+
process.exit(0); // db.close() 抛错也必须退出
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
process.on("SIGTERM", shutdown);
|
|
609
|
+
process.on("SIGINT", shutdown);
|
|
610
|
+
if (options.mcp) {
|
|
611
|
+
const llmConfig = { ...config.llm };
|
|
612
|
+
const envKey = llmConfig.provider === "anthropic"
|
|
613
|
+
? process.env.ANTHROPIC_API_KEY
|
|
614
|
+
: process.env.OPENAI_API_KEY;
|
|
615
|
+
if (!llmConfig.api_key && envKey)
|
|
616
|
+
llmConfig.api_key = envKey;
|
|
617
|
+
const synthProvider = llmConfig.api_key
|
|
618
|
+
? createLLMProvider(llmConfig)
|
|
619
|
+
: createMockProvider(new Map());
|
|
620
|
+
let ingestDeps;
|
|
621
|
+
const feishu = config.sources.feishu;
|
|
622
|
+
if (feishu?.enabled && feishu.sources?.docs?.enabled) {
|
|
623
|
+
const client = new LarkCliHttpClient(feishu.lark_bin);
|
|
624
|
+
ingestDeps = {
|
|
625
|
+
client,
|
|
626
|
+
stores: storesWithDaemon,
|
|
627
|
+
provider: synthProvider,
|
|
628
|
+
model: feishu.sources.docs.llm?.model ?? llmConfig.model,
|
|
629
|
+
nowIso: () => new Date().toISOString(),
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
const server = createMcpServer(storesWithDaemon, { provider: synthProvider, synthModel: llmConfig.model }, ingestDeps);
|
|
633
|
+
await server.connect(new StdioServerTransport());
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
if (options.mcpHttp ||
|
|
637
|
+
config.mcp.http.enabled ||
|
|
638
|
+
config.server.mcp_transport === "streamable_http") {
|
|
639
|
+
const runtime = resolveMcpHttpRuntime(config.mcp.http, {
|
|
640
|
+
mcpBind: options.mcpBind,
|
|
641
|
+
mcpPort: options.mcpPort,
|
|
642
|
+
mcpReadWrite: options.mcpReadWrite,
|
|
643
|
+
mcpAllowedHost: options.mcpAllowedHost,
|
|
644
|
+
daemonInstanceId: options.daemonInstanceId,
|
|
645
|
+
});
|
|
646
|
+
assertLoopbackOrThrow(runtime);
|
|
647
|
+
// Server-wide auth token (config server.auth_token / MEMKIN_AUTH_TOKEN)
|
|
648
|
+
// also protects the MCP HTTP endpoint. The MCP-specific auth_token_env is
|
|
649
|
+
// kept for backward compat; the server-wide token wins when both are set.
|
|
650
|
+
const serverToken = resolveServeSecurity({
|
|
651
|
+
configHost: config.server.host,
|
|
652
|
+
configToken: config.server.auth_token,
|
|
653
|
+
envToken: process.env.MEMKIN_AUTH_TOKEN,
|
|
654
|
+
}).authToken;
|
|
655
|
+
const tokenEnv = config.mcp.http.auth_token_env;
|
|
656
|
+
const resolvedConfigPath = config.__context.configPath;
|
|
657
|
+
let loadedConfigHash;
|
|
658
|
+
try {
|
|
659
|
+
loadedConfigHash = rawYamlHash(resolvedConfigPath);
|
|
660
|
+
}
|
|
661
|
+
catch {
|
|
662
|
+
// config file may not exist yet; leave hash undefined
|
|
663
|
+
}
|
|
664
|
+
const app = createMcpHttpApp(storesWithDaemon, {
|
|
665
|
+
allowedOrigins: runtime.allowedOrigins,
|
|
666
|
+
allowedHosts: runtime.allowedHosts,
|
|
667
|
+
authToken: serverToken ?? (tokenEnv ? process.env[tokenEnv] : undefined),
|
|
668
|
+
exposeLegacyTools: config.mcp.expose_legacy_tools,
|
|
669
|
+
readOnly: runtime.readOnly,
|
|
670
|
+
health: {
|
|
671
|
+
instanceId: runtime.instanceId,
|
|
672
|
+
pid: process.pid,
|
|
673
|
+
engine: config.store.engine ?? "pglite",
|
|
674
|
+
version: VERSION,
|
|
675
|
+
loadedConfigHash,
|
|
676
|
+
// FIX 5: wire port/bind so isReady() port/bind checks are load-bearing
|
|
677
|
+
port: runtime.port,
|
|
678
|
+
bind: runtime.bind,
|
|
679
|
+
dbProbe: async () => {
|
|
680
|
+
try {
|
|
681
|
+
await stores.db.executor.query("SELECT 1");
|
|
682
|
+
return true;
|
|
683
|
+
}
|
|
684
|
+
catch {
|
|
685
|
+
return false;
|
|
686
|
+
}
|
|
687
|
+
},
|
|
688
|
+
pgProbe: stores.supervisor
|
|
689
|
+
? async () => (await stores.supervisor.status()) === "running"
|
|
690
|
+
: undefined,
|
|
691
|
+
},
|
|
692
|
+
});
|
|
693
|
+
const server = await startServer(app, {
|
|
694
|
+
hostname: runtime.bind,
|
|
695
|
+
port: runtime.port,
|
|
696
|
+
});
|
|
697
|
+
console.log(`Memkin MCP Streamable HTTP listening on http://${server.hostname}:${server.port}/mcp`);
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
// Resolve bind host + auth token BEFORE creating stores' HTTP surface.
|
|
701
|
+
// Rule: loopback by default; a non-loopback bind REFUSES to start unless an
|
|
702
|
+
// auth token is configured. When a token is set it is enforced everywhere
|
|
703
|
+
// (including loopback). Throws with an actionable message on misconfig.
|
|
704
|
+
const security = resolveServeSecurity({
|
|
705
|
+
flagHost: options.host,
|
|
706
|
+
configHost: config.server.host,
|
|
707
|
+
configToken: config.server.auth_token,
|
|
708
|
+
envToken: process.env.MEMKIN_AUTH_TOKEN,
|
|
709
|
+
});
|
|
710
|
+
const app = createApiApp(storesWithDaemon, {
|
|
711
|
+
authToken: security.authToken,
|
|
712
|
+
onConfigSaved: () => {
|
|
713
|
+
try {
|
|
714
|
+
void reloadManager.run(loadConfig(options.config)).catch((err) => {
|
|
715
|
+
console.error("[reload] Runtime reload failed:", err);
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
catch (err) {
|
|
719
|
+
console.error("[reload] Failed to load config after save:", err);
|
|
720
|
+
}
|
|
721
|
+
},
|
|
722
|
+
});
|
|
723
|
+
// In a `bun --compile` sidecar, import.meta.url lives under $bunfs and web/dist is
|
|
724
|
+
// NOT embedded, so the default path can't be served. The Tauri shell ships web/dist
|
|
725
|
+
// as a resource and injects its real path via MEMKIN_WEB_DIST (mirrors pglite-assets).
|
|
726
|
+
const webDist = process.env.MEMKIN_WEB_DIST ?? join(fileURLToPath(import.meta.url), "../../web/dist");
|
|
727
|
+
// `--port 0` (used by the Tauri shell) binds an OS-assigned free port so the desktop
|
|
728
|
+
// app never collides with a CLI `memkin serve`, a stale instance, or anything else
|
|
729
|
+
// on the default port. The actual port is reported below for the webview to read.
|
|
730
|
+
const requestedPort = options.port !== undefined ? Number(options.port) : config.server.http_port;
|
|
731
|
+
const server = Bun.serve({
|
|
732
|
+
port: requestedPort,
|
|
733
|
+
// Loopback by default; `--host` / `server.host` can widen this, but only
|
|
734
|
+
// when an auth token is configured (enforced by resolveServeSecurity above).
|
|
735
|
+
hostname: security.host,
|
|
736
|
+
fetch: async (req) => {
|
|
737
|
+
const url = new URL(req.url);
|
|
738
|
+
// Auth (when a token is configured) is enforced inside the Hono app's
|
|
739
|
+
// /api/* middleware. Web UI static assets below stay unauthenticated —
|
|
740
|
+
// they are the app shell, not data.
|
|
741
|
+
if (url.pathname.startsWith("/api"))
|
|
742
|
+
return app.fetch(req);
|
|
743
|
+
const filePath = url.pathname === "/" ? "index.html" : url.pathname.replace(/^\//, "");
|
|
744
|
+
const candidate = Bun.file(join(webDist, filePath));
|
|
745
|
+
if (await candidate.exists())
|
|
746
|
+
return new Response(candidate);
|
|
747
|
+
return new Response(Bun.file(join(webDist, "index.html")));
|
|
748
|
+
},
|
|
749
|
+
});
|
|
750
|
+
console.log(`Memkin HTTP API listening on http://localhost:${server.port}`);
|
|
751
|
+
// Stdout contract for the Tauri shell: the URL after the marker is where the webview
|
|
752
|
+
// navigates (the port may be OS-assigned, so report the real one — never hardcode).
|
|
753
|
+
console.log(`MEMKIN_READY http://localhost:${server.port}`);
|
|
754
|
+
if (shouldOpenBrowserOnServe({
|
|
755
|
+
open: options.open !== false,
|
|
756
|
+
mcp: !!options.mcp,
|
|
757
|
+
mcpHttp: !!options.mcpHttp,
|
|
758
|
+
})) {
|
|
759
|
+
openBrowser(`http://localhost:${server.port}`);
|
|
760
|
+
}
|
|
761
|
+
const activeScheduler = holder.current.scheduler;
|
|
762
|
+
if (activeScheduler && config.scheduler?.enabled) {
|
|
763
|
+
console.log(`Scheduler running — tick every ${config.scheduler.tick_interval_secs}s, sources: ${activeScheduler.getSourceIds().join(", ")}`);
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
program
|
|
768
|
+
.command("serve")
|
|
769
|
+
.description("Start Memkin HTTP API or MCP stdio server")
|
|
770
|
+
.option("-c, --config <path>", "Path to config file")
|
|
771
|
+
.option("--mcp", "Run MCP stdio transport instead of HTTP")
|
|
772
|
+
.option("--mcp-http", "Run MCP Streamable HTTP transport instead of the HTTP API")
|
|
773
|
+
.option("--no-open", "Do not auto-open the browser after starting")
|
|
774
|
+
.option("--pglite-assets <dir>", "Directory holding bundled PGLite assets (compiled-sidecar mode; injected by the Tauri shell)")
|
|
775
|
+
.option("--web-dist <dir>", "Directory holding the built web UI (compiled-sidecar mode; injected by the Tauri shell)")
|
|
776
|
+
.option("--port <n>", "Override the HTTP port; 0 binds an OS-assigned free port (used by the Tauri shell)")
|
|
777
|
+
.option("--host <host>", "Bind host for the HTTP API + Web UI (default 127.0.0.1, loopback only). " +
|
|
778
|
+
"Binding a non-loopback host (e.g. 0.0.0.0) requires an auth token " +
|
|
779
|
+
"(server.auth_token in config or MEMKIN_AUTH_TOKEN env), or the server refuses to start.")
|
|
780
|
+
.option("--mcp-bind <host>", "")
|
|
781
|
+
.option("--mcp-port <port>", "", (v) => {
|
|
782
|
+
const n = Number.parseInt(v, 10);
|
|
783
|
+
if (Number.isNaN(n))
|
|
784
|
+
throw new Error(`--mcp-port: invalid number "${v}"`);
|
|
785
|
+
return n;
|
|
786
|
+
})
|
|
787
|
+
.option("--mcp-read-write", "")
|
|
788
|
+
.option("--mcp-allowed-host <host>", "", (v, acc) => acc.concat(v), [])
|
|
789
|
+
.option("--daemon-instance-id <id>", "")
|
|
790
|
+
.action((options) => {
|
|
791
|
+
if (options.pgliteAssets)
|
|
792
|
+
process.env.MEMKIN_PGLITE_ASSETS = options.pgliteAssets;
|
|
793
|
+
if (options.webDist)
|
|
794
|
+
process.env.MEMKIN_WEB_DIST = options.webDist;
|
|
795
|
+
return runServe(options);
|
|
796
|
+
});
|
|
797
|
+
async function runStart(options) {
|
|
798
|
+
const configPath = options.config ?? resolve(process.cwd(), "memkin.yaml");
|
|
799
|
+
const plan = planStartup(existsSync(configPath));
|
|
800
|
+
if (plan.runSetup) {
|
|
801
|
+
console.log("No configuration found — launching setup wizard...");
|
|
802
|
+
const { startSetupServer } = await import("./server/setup-server.js");
|
|
803
|
+
await startSetupServer({
|
|
804
|
+
configPath: options.config,
|
|
805
|
+
larkBin: readLarkBinFromConfig(options.config),
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
await runServe({ config: options.config });
|
|
809
|
+
}
|
|
810
|
+
program
|
|
811
|
+
.command("start")
|
|
812
|
+
.description("One-step launch: setup if needed, then serve + open browser")
|
|
813
|
+
.option("-c, --config <path>", "Path to config file")
|
|
814
|
+
.action((options) => runStart(options));
|
|
815
|
+
program.action(() => runStart({}));
|
|
816
|
+
function reportPlan(planned, verb, dryRun) {
|
|
817
|
+
if (planned.length === 0) {
|
|
818
|
+
console.log("No AI agents detected. Specify one with --agent <id> (claude-code, claude-desktop, cursor, codex, windsurf).");
|
|
819
|
+
return;
|
|
820
|
+
}
|
|
821
|
+
for (const client of planned) {
|
|
822
|
+
console.log(`\n${verb} → ${client.displayName}:`);
|
|
823
|
+
for (const op of client.ops) {
|
|
824
|
+
const where = "path" in op ? op.path : `cli: ${op.args.join(" ")}`;
|
|
825
|
+
console.log(` - ${op.kind} ${op.action} ${where}`);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
if (!dryRun)
|
|
829
|
+
console.log("\nRestart / reopen your agent for changes to take effect.");
|
|
830
|
+
}
|
|
831
|
+
program
|
|
832
|
+
.command("install")
|
|
833
|
+
.description("Register Memkin (MCP config + memory directive) into your AI agents")
|
|
834
|
+
.option("--agent <ids...>", "Target client(s): claude-code, claude-desktop, cursor, codex, windsurf (default: all detected)")
|
|
835
|
+
.option("--project", "Install into the current project instead of globally")
|
|
836
|
+
.option("--http", "Register the Streamable HTTP transport instead of stdio")
|
|
837
|
+
.option("--url <url>", "Explicit MCP server URL for HTTP transport (default: http://127.0.0.1:<port>/mcp)")
|
|
838
|
+
.option("--port <port>", "MCP server port for HTTP transport URL (default: 3928)", (v) => {
|
|
839
|
+
const n = Number.parseInt(v, 10);
|
|
840
|
+
if (Number.isNaN(n))
|
|
841
|
+
throw new Error(`--port: invalid number "${v}"`);
|
|
842
|
+
return n;
|
|
843
|
+
})
|
|
844
|
+
.option("--dry-run", "Preview changes without writing")
|
|
845
|
+
.action((options) => {
|
|
846
|
+
const scope = options.project ? "project" : "global";
|
|
847
|
+
const planned = runInstall({
|
|
848
|
+
agent: options.agent,
|
|
849
|
+
scope,
|
|
850
|
+
http: !!options.http,
|
|
851
|
+
url: options.url,
|
|
852
|
+
port: options.port,
|
|
853
|
+
dryRun: !!options.dryRun,
|
|
854
|
+
});
|
|
855
|
+
reportPlan(planned, options.dryRun ? "Would install" : "Installed", !!options.dryRun);
|
|
856
|
+
});
|
|
857
|
+
program
|
|
858
|
+
.command("uninstall")
|
|
859
|
+
.description("Remove Memkin MCP config + memory directive from your AI agents")
|
|
860
|
+
.option("--agent <ids...>", "Target client(s) (default: all detected)")
|
|
861
|
+
.option("--project", "Operate on the current project instead of globally")
|
|
862
|
+
.option("--dry-run", "Preview changes without writing")
|
|
863
|
+
.action((options) => {
|
|
864
|
+
const scope = options.project ? "project" : "global";
|
|
865
|
+
const planned = runUninstall({ agent: options.agent, scope, dryRun: !!options.dryRun });
|
|
866
|
+
reportPlan(planned, options.dryRun ? "Would remove" : "Removed", !!options.dryRun);
|
|
867
|
+
});
|
|
868
|
+
const hooksCmd = program
|
|
869
|
+
.command("hooks")
|
|
870
|
+
.description("Manage Claude Code hooks for automatic recall / write-back");
|
|
871
|
+
hooksCmd
|
|
872
|
+
.command("install")
|
|
873
|
+
.description("Install SessionStart + UserPromptSubmit (read) hooks; write-back is opt-in")
|
|
874
|
+
.option("--write-back", "Also install the SessionEnd auto write-back hook (opt-in)")
|
|
875
|
+
.option("--project", "Write to ./.claude/settings.json instead of the global one")
|
|
876
|
+
.option("--dry-run", "Preview without writing")
|
|
877
|
+
.action((options) => {
|
|
878
|
+
const res = hooksInstall({
|
|
879
|
+
writeBack: !!options.writeBack,
|
|
880
|
+
project: !!options.project,
|
|
881
|
+
dryRun: !!options.dryRun,
|
|
882
|
+
});
|
|
883
|
+
console.log(`${options.dryRun ? "Would install" : "Installed"} hooks [${res.events.join(", ")}] → ${res.path}`);
|
|
884
|
+
if (!options.writeBack) {
|
|
885
|
+
console.log("Tip: add --write-back to also auto-capture memory at session end (opt-in).");
|
|
886
|
+
}
|
|
887
|
+
if (!options.dryRun)
|
|
888
|
+
console.log("Reopen Claude Code for the hooks to take effect.");
|
|
889
|
+
});
|
|
890
|
+
hooksCmd
|
|
891
|
+
.command("uninstall")
|
|
892
|
+
.description("Remove all Memkin hooks from settings.json")
|
|
893
|
+
.option("--project", "Operate on ./.claude/settings.json instead of the global one")
|
|
894
|
+
.option("--dry-run", "Preview without writing")
|
|
895
|
+
.action((options) => {
|
|
896
|
+
const res = hooksUninstall({ project: !!options.project, dryRun: !!options.dryRun });
|
|
897
|
+
console.log(`${options.dryRun ? "Would remove" : "Removed"} Memkin hooks → ${res.path}`);
|
|
898
|
+
});
|
|
899
|
+
const skillCmd = program.command("skill").description("Manage the Memkin agent skill");
|
|
900
|
+
skillCmd
|
|
901
|
+
.command("scaffold")
|
|
902
|
+
.description("Write the memkin skill (SKILL.md) into a skills directory")
|
|
903
|
+
.option("--dir <path>", "Target skills directory (default: ./.claude/skills)")
|
|
904
|
+
.action((options) => {
|
|
905
|
+
const dir = options.dir ?? join(process.cwd(), ".claude", "skills");
|
|
906
|
+
const path = scaffoldSkill(dir);
|
|
907
|
+
console.log(`Wrote ${path}`);
|
|
908
|
+
});
|
|
909
|
+
async function readStdinJson() {
|
|
910
|
+
const chunks = [];
|
|
911
|
+
for await (const chunk of process.stdin)
|
|
912
|
+
chunks.push(chunk);
|
|
913
|
+
const raw = Buffer.concat(chunks).toString("utf8").trim();
|
|
914
|
+
if (!raw)
|
|
915
|
+
return {};
|
|
916
|
+
try {
|
|
917
|
+
return JSON.parse(raw);
|
|
918
|
+
}
|
|
919
|
+
catch {
|
|
920
|
+
return {};
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
program
|
|
924
|
+
.command("hook <event>")
|
|
925
|
+
.description("Internal: Claude Code hook entrypoint (session-start|user-prompt|session-end)")
|
|
926
|
+
.action(async (event) => {
|
|
927
|
+
try {
|
|
928
|
+
const input = await readStdinJson();
|
|
929
|
+
const config = loadConfig(undefined);
|
|
930
|
+
const port = config.server.http_port;
|
|
931
|
+
const out = await runHookEvent(event, input, {
|
|
932
|
+
port,
|
|
933
|
+
sessionContext: async () => {
|
|
934
|
+
const stores = await createStores(config);
|
|
935
|
+
try {
|
|
936
|
+
return await getSessionContext(stores);
|
|
937
|
+
}
|
|
938
|
+
finally {
|
|
939
|
+
await stores.db.close();
|
|
940
|
+
}
|
|
941
|
+
},
|
|
942
|
+
ftsSearch: async (q, opts) => {
|
|
943
|
+
const stores = await createStores(config);
|
|
944
|
+
try {
|
|
945
|
+
return await stores.search.search(q, opts);
|
|
946
|
+
}
|
|
947
|
+
finally {
|
|
948
|
+
await stores.db.close();
|
|
949
|
+
}
|
|
950
|
+
},
|
|
951
|
+
});
|
|
952
|
+
if (out && Object.keys(out).length > 0)
|
|
953
|
+
process.stdout.write(JSON.stringify(out));
|
|
954
|
+
}
|
|
955
|
+
catch {
|
|
956
|
+
// Never break the host session: emit nothing on any failure.
|
|
957
|
+
}
|
|
958
|
+
process.exit(0);
|
|
959
|
+
});
|
|
960
|
+
program
|
|
961
|
+
.command("search <query>")
|
|
962
|
+
.description("Search Memkin memory")
|
|
963
|
+
.option("-c, --config <path>", "Path to config file")
|
|
964
|
+
.option("--mode <mode>", "Search mode (hybrid|fts)", "hybrid")
|
|
965
|
+
.option("--limit <n>", "Limit results", "20")
|
|
966
|
+
.action(async (query, options) => {
|
|
967
|
+
const config = loadConfig(options.config);
|
|
968
|
+
validateEnvForCommand(config, "search", { searchMode: options.mode });
|
|
969
|
+
const stores = await createStores(config);
|
|
970
|
+
const limit = Number(options.limit);
|
|
971
|
+
const results = options.mode === "fts"
|
|
972
|
+
? await stores.search.search(query, { limit })
|
|
973
|
+
: await stores.search.query(query, { limit });
|
|
974
|
+
for (const result of results) {
|
|
975
|
+
console.log(`${result.slug}\t${result.score.toFixed(4)}\t${result.snippet.slice(0, 200)}`);
|
|
976
|
+
}
|
|
977
|
+
await stores.db.close();
|
|
978
|
+
});
|
|
979
|
+
program
|
|
980
|
+
.command("embed")
|
|
981
|
+
.description("Embed stale Memkin chunks")
|
|
982
|
+
.option("-c, --config <path>", "Path to config file")
|
|
983
|
+
.option("--limit <n>", "Limit chunks")
|
|
984
|
+
.action(async (options) => {
|
|
985
|
+
const config = loadConfig(options.config);
|
|
986
|
+
validateEnvForCommand(config, "embed");
|
|
987
|
+
const stores = await createStores(config);
|
|
988
|
+
const result = await stores.embedding.embedStale({
|
|
989
|
+
limit: options.limit ? Number(options.limit) : undefined,
|
|
990
|
+
});
|
|
991
|
+
console.log(`Embedded ${result.embedded} chunks, errors ${result.errors}`);
|
|
992
|
+
await stores.db.close();
|
|
993
|
+
});
|
|
994
|
+
/**
|
|
995
|
+
* Obsidian sync — bidirectional export/import between PGLite and a vault.
|
|
996
|
+
* See docs/specs/memkin-2026-06-04-obsidian-sync.md
|
|
997
|
+
*/
|
|
998
|
+
program
|
|
999
|
+
.command("export")
|
|
1000
|
+
.description("Export Memkin pages to an Obsidian vault (Markdown)")
|
|
1001
|
+
.requiredOption("--vault <path>", "Obsidian vault directory")
|
|
1002
|
+
.option("--force", "Ignore hash comparison, overwrite all files")
|
|
1003
|
+
.option("--dry-run", "Print intended actions without writing")
|
|
1004
|
+
.option("-c, --config <path>", "Path to config file")
|
|
1005
|
+
.action(async (options) => {
|
|
1006
|
+
const { exportToVault } = await import("./sync/obsidian.js");
|
|
1007
|
+
const stores = await createStores(loadConfig(options.config));
|
|
1008
|
+
try {
|
|
1009
|
+
const result = await exportToVault(stores, options.vault, {
|
|
1010
|
+
force: options.force,
|
|
1011
|
+
dryRun: options.dryRun,
|
|
1012
|
+
});
|
|
1013
|
+
console.log(`Exported: ${result.written} written, ${result.skipped} skipped, ${result.errors.length} errors`);
|
|
1014
|
+
for (const err of result.errors) {
|
|
1015
|
+
console.error(` error: ${err.slug}: ${err.reason}`);
|
|
1016
|
+
}
|
|
1017
|
+
if (options.dryRun)
|
|
1018
|
+
console.log("(dry-run: no files written)");
|
|
1019
|
+
}
|
|
1020
|
+
finally {
|
|
1021
|
+
await stores.db.close();
|
|
1022
|
+
}
|
|
1023
|
+
});
|
|
1024
|
+
program
|
|
1025
|
+
.command("import")
|
|
1026
|
+
.description("Import an Obsidian vault back into Memkin")
|
|
1027
|
+
.requiredOption("--vault <path>", "Obsidian vault directory")
|
|
1028
|
+
.option("--force", "Ignore hash comparison, import all files")
|
|
1029
|
+
.option("--dry-run", "Print intended actions without writing")
|
|
1030
|
+
.option("--strict-conflict", "Skip files where DB has changed since last sync instead of overwriting")
|
|
1031
|
+
.option("-c, --config <path>", "Path to config file")
|
|
1032
|
+
.action(async (options) => {
|
|
1033
|
+
const { importFromVault } = await import("./sync/obsidian.js");
|
|
1034
|
+
const stores = await createStores(loadConfig(options.config));
|
|
1035
|
+
try {
|
|
1036
|
+
const result = await importFromVault(stores, options.vault, {
|
|
1037
|
+
force: options.force,
|
|
1038
|
+
dryRun: options.dryRun,
|
|
1039
|
+
strictConflict: options.strictConflict,
|
|
1040
|
+
});
|
|
1041
|
+
console.log(`Imported: ${result.imported} imported, ${result.skipped} skipped, ${result.errors.length} errors`);
|
|
1042
|
+
for (const w of result.warnings) {
|
|
1043
|
+
console.warn(` warn: ${w.slug}: ${w.reason}`);
|
|
1044
|
+
}
|
|
1045
|
+
for (const err of result.errors) {
|
|
1046
|
+
console.error(` error: ${err.file}: ${err.reason}`);
|
|
1047
|
+
}
|
|
1048
|
+
if (!options.dryRun && result.imported > 0) {
|
|
1049
|
+
console.log("Tip: Run 'memkin embed' to update embeddings for changed pages.");
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
finally {
|
|
1053
|
+
await stores.db.close();
|
|
1054
|
+
}
|
|
1055
|
+
});
|
|
1056
|
+
program
|
|
1057
|
+
.command("consolidate")
|
|
1058
|
+
.description("Run memory lifecycle tier rotation (hot→warm and/or warm→cold)")
|
|
1059
|
+
.option("-c, --config <path>", "Path to config file (default: memkin.yaml)")
|
|
1060
|
+
.option("--hot", "Run hot→warm rotation only")
|
|
1061
|
+
.option("--warm", "Run warm→cold rotation only (requires LLM API key)")
|
|
1062
|
+
.option("--dry-run", "Report what would be consolidated without writing")
|
|
1063
|
+
.action(async (options) => {
|
|
1064
|
+
try {
|
|
1065
|
+
const config = loadConfig(options.config);
|
|
1066
|
+
const stores = await createStores(config);
|
|
1067
|
+
let llmProvider;
|
|
1068
|
+
if (options.warm || (!options.hot && !options.warm)) {
|
|
1069
|
+
const llmConfig = config.llm;
|
|
1070
|
+
const envKey = llmConfig.provider === "anthropic"
|
|
1071
|
+
? process.env.ANTHROPIC_API_KEY
|
|
1072
|
+
: process.env.OPENAI_API_KEY;
|
|
1073
|
+
const apiKey = llmConfig.api_key ?? envKey;
|
|
1074
|
+
if (apiKey) {
|
|
1075
|
+
if (!llmConfig.api_key)
|
|
1076
|
+
llmConfig.api_key = apiKey;
|
|
1077
|
+
llmProvider = createLLMProvider(llmConfig);
|
|
1078
|
+
}
|
|
1079
|
+
else if (options.warm) {
|
|
1080
|
+
// Explicit --warm with no LLM key: fail fast
|
|
1081
|
+
console.error("Error: --warm requires an LLM API key. Set ANTHROPIC_API_KEY or configure api_key in memkin.yaml.");
|
|
1082
|
+
process.exit(1);
|
|
1083
|
+
}
|
|
1084
|
+
else {
|
|
1085
|
+
// Full run with no LLM: skip warm→cold, run hot only
|
|
1086
|
+
console.warn("Warning: no LLM API key found. Running hot→warm only. " +
|
|
1087
|
+
"Set ANTHROPIC_API_KEY to enable warm→cold consolidation.");
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
const consolidator = new Consolidator({
|
|
1091
|
+
pages: stores.pages,
|
|
1092
|
+
graph: stores.graph,
|
|
1093
|
+
tags: stores.tags,
|
|
1094
|
+
timeline: stores.timeline,
|
|
1095
|
+
}, llmProvider, {
|
|
1096
|
+
profile: config.profile,
|
|
1097
|
+
profileStores: {
|
|
1098
|
+
pages: stores.pages,
|
|
1099
|
+
graph: stores.graph,
|
|
1100
|
+
timeline: stores.timeline,
|
|
1101
|
+
behavior: new PersonBehaviorStore(stores.db.executor),
|
|
1102
|
+
},
|
|
1103
|
+
});
|
|
1104
|
+
const mode = options.hot
|
|
1105
|
+
? "hot"
|
|
1106
|
+
: options.warm
|
|
1107
|
+
? "warm"
|
|
1108
|
+
: llmProvider
|
|
1109
|
+
? "all"
|
|
1110
|
+
: "hot"; // fall back to hot-only when full run has no LLM
|
|
1111
|
+
const dryRun = options.dryRun ?? false;
|
|
1112
|
+
if (dryRun)
|
|
1113
|
+
console.log("DRY-RUN mode — no writes will occur\n");
|
|
1114
|
+
const result = await consolidator.runOnce(mode, dryRun);
|
|
1115
|
+
console.log("Consolidation complete:");
|
|
1116
|
+
console.log(` hot→warm pages moved: ${result.hotToWarm}`);
|
|
1117
|
+
console.log(` warm→cold pages archived: ${result.warmToCold}`);
|
|
1118
|
+
console.log(` dead links checked: ${result.deadLinksChecked}`);
|
|
1119
|
+
console.log(` preferences inferred: ${result.preferencesInferred}`);
|
|
1120
|
+
console.log(` profiles synthesized: ${result.profilesSynthesized}`);
|
|
1121
|
+
await stores.db.close();
|
|
1122
|
+
}
|
|
1123
|
+
catch (error) {
|
|
1124
|
+
console.error("Consolidate failed:", error instanceof Error ? error.message : String(error));
|
|
1125
|
+
process.exit(1);
|
|
1126
|
+
}
|
|
1127
|
+
});
|
|
1128
|
+
// ── Person identity (Layer 1: aliases / merge / rename) ────────────────────
|
|
1129
|
+
const HANDLE_KINDS = ["feishu_open_id", "email", "name", "nickname", "slug"];
|
|
1130
|
+
const identityCmd = program
|
|
1131
|
+
.command("identity")
|
|
1132
|
+
.description("Manage person identity: aliases, merge, and rename");
|
|
1133
|
+
identityCmd
|
|
1134
|
+
.command("alias <canonical_slug> <kind> <value>")
|
|
1135
|
+
.description(`Attach an alias/handle to a person. kind: ${HANDLE_KINDS.join(" | ")}`)
|
|
1136
|
+
.option("-c, --config <path>", "Path to config file")
|
|
1137
|
+
.option("--strong", "Force strong strength (auto-resolvable)")
|
|
1138
|
+
.option("--weak", "Force weak strength (explicit-only)")
|
|
1139
|
+
.action(async (canonicalSlug, kind, value, options) => {
|
|
1140
|
+
if (!HANDLE_KINDS.includes(kind)) {
|
|
1141
|
+
console.error(`Error: invalid kind '${kind}'. Expected one of: ${HANDLE_KINDS.join(", ")}`);
|
|
1142
|
+
process.exit(1);
|
|
1143
|
+
}
|
|
1144
|
+
const { db, identity } = await openIdentityStore(loadConfig(options.config));
|
|
1145
|
+
try {
|
|
1146
|
+
const strength = options.strong ? "strong" : options.weak ? "weak" : undefined;
|
|
1147
|
+
await identity.addAlias(canonicalSlug, kind, value, strength);
|
|
1148
|
+
console.log(`Linked ${kind}:${value} → ${canonicalSlug}`);
|
|
1149
|
+
for (const h of await identity.listHandles(canonicalSlug)) {
|
|
1150
|
+
console.log(` ${h.kind}\t${h.value}\t(${h.strength})`);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
catch (error) {
|
|
1154
|
+
console.error("alias failed:", error instanceof Error ? error.message : String(error));
|
|
1155
|
+
process.exit(1);
|
|
1156
|
+
}
|
|
1157
|
+
finally {
|
|
1158
|
+
await db.close();
|
|
1159
|
+
}
|
|
1160
|
+
});
|
|
1161
|
+
identityCmd
|
|
1162
|
+
.command("handles <canonical_slug>")
|
|
1163
|
+
.description("List all handles/aliases attached to a person")
|
|
1164
|
+
.option("-c, --config <path>", "Path to config file")
|
|
1165
|
+
.action(async (canonicalSlug, options) => {
|
|
1166
|
+
const { db, identity } = await openIdentityStore(loadConfig(options.config));
|
|
1167
|
+
try {
|
|
1168
|
+
const handles = await identity.listHandles(canonicalSlug);
|
|
1169
|
+
if (handles.length === 0) {
|
|
1170
|
+
console.log(`No handles for ${canonicalSlug}`);
|
|
1171
|
+
}
|
|
1172
|
+
else {
|
|
1173
|
+
for (const h of handles)
|
|
1174
|
+
console.log(`${h.kind}\t${h.value}\t(${h.strength})`);
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
finally {
|
|
1178
|
+
await db.close();
|
|
1179
|
+
}
|
|
1180
|
+
});
|
|
1181
|
+
identityCmd
|
|
1182
|
+
.command("merge <from> <into>")
|
|
1183
|
+
.description("Merge person page <from> into <into> (re-points links/timeline/tags + aliases)")
|
|
1184
|
+
.option("-c, --config <path>", "Path to config file")
|
|
1185
|
+
.action(async (from, into, options) => {
|
|
1186
|
+
const { db, identity } = await openIdentityStore(loadConfig(options.config));
|
|
1187
|
+
try {
|
|
1188
|
+
await identity.merge(from, into);
|
|
1189
|
+
console.log(`Merged ${from} → ${into}`);
|
|
1190
|
+
console.log("Note: run `memkin embed` to re-embed the folded content.");
|
|
1191
|
+
}
|
|
1192
|
+
catch (error) {
|
|
1193
|
+
console.error("merge failed:", error instanceof Error ? error.message : String(error));
|
|
1194
|
+
process.exit(1);
|
|
1195
|
+
}
|
|
1196
|
+
finally {
|
|
1197
|
+
await db.close();
|
|
1198
|
+
}
|
|
1199
|
+
});
|
|
1200
|
+
identityCmd
|
|
1201
|
+
.command("rename <from> <to>")
|
|
1202
|
+
.description("Rename a person's canonical slug (correct a wrong canonicalization)")
|
|
1203
|
+
.option("-c, --config <path>", "Path to config file")
|
|
1204
|
+
.action(async (from, to, options) => {
|
|
1205
|
+
const { db, identity } = await openIdentityStore(loadConfig(options.config));
|
|
1206
|
+
try {
|
|
1207
|
+
await identity.recanonicalize(from, to);
|
|
1208
|
+
console.log(`Renamed ${from} → ${to}`);
|
|
1209
|
+
}
|
|
1210
|
+
catch (error) {
|
|
1211
|
+
console.error("rename failed:", error instanceof Error ? error.message : String(error));
|
|
1212
|
+
process.exit(1);
|
|
1213
|
+
}
|
|
1214
|
+
finally {
|
|
1215
|
+
await db.close();
|
|
1216
|
+
}
|
|
1217
|
+
});
|
|
1218
|
+
const docsCmd = program.command("docs").description("Feishu doc summary cards (DocSource v2)");
|
|
1219
|
+
docsCmd
|
|
1220
|
+
.command("sync")
|
|
1221
|
+
.description("Scan Feishu docs, build pointer cards, upgrade triggered docs to full cards")
|
|
1222
|
+
.option("-c, --config <path>", "Path to config file (default: memkin.yaml)")
|
|
1223
|
+
.action(async (options) => {
|
|
1224
|
+
try {
|
|
1225
|
+
const config = loadConfig(options.config);
|
|
1226
|
+
ensureStateDir();
|
|
1227
|
+
const feishu = config.sources.feishu;
|
|
1228
|
+
if (!feishu?.enabled || !feishu.sources?.docs?.enabled) {
|
|
1229
|
+
console.error("Feishu docs source is not enabled in config (sources.feishu.sources.docs.enabled).");
|
|
1230
|
+
process.exit(1);
|
|
1231
|
+
}
|
|
1232
|
+
const stores = await createStores(config);
|
|
1233
|
+
const client = new LarkCliHttpClient(feishu.lark_bin);
|
|
1234
|
+
const docsConfig = normalizeDocsConfig(feishu.sources.docs);
|
|
1235
|
+
// self_open_id: config override else resolve via lark-cli whoami helper used elsewhere
|
|
1236
|
+
const selfOpenId = docsConfig.self_open_id ??
|
|
1237
|
+
(await resolveSelfOpenId(client, feishu.sources?.dm?.self_open_id)) ??
|
|
1238
|
+
"";
|
|
1239
|
+
const llmConfig = { ...config.llm };
|
|
1240
|
+
if (docsConfig.llm.model)
|
|
1241
|
+
llmConfig.model = docsConfig.llm.model;
|
|
1242
|
+
const envKey = llmConfig.provider === "anthropic"
|
|
1243
|
+
? process.env.ANTHROPIC_API_KEY
|
|
1244
|
+
: process.env.OPENAI_API_KEY;
|
|
1245
|
+
if (!llmConfig.api_key && envKey)
|
|
1246
|
+
llmConfig.api_key = envKey;
|
|
1247
|
+
const provider = llmConfig.api_key
|
|
1248
|
+
? createLLMProvider(llmConfig)
|
|
1249
|
+
: createMockProvider(new Map());
|
|
1250
|
+
const cursor = new CursorStore(statePath("cursors.yaml"));
|
|
1251
|
+
cursor.load();
|
|
1252
|
+
// Identity layer for canonicalizing action_item owners → person slugs and
|
|
1253
|
+
// detecting self-ownership, so doc/meeting action_items become task signals
|
|
1254
|
+
// the daily report can surface (Spec 9 §3.3).
|
|
1255
|
+
const identity = new PersonIdentityStore(stores.db.executor, { pages: stores.pages }, { behavior: new PersonBehaviorStore(stores.db.executor) });
|
|
1256
|
+
const stats = await runDocSource({
|
|
1257
|
+
client,
|
|
1258
|
+
stores,
|
|
1259
|
+
provider,
|
|
1260
|
+
config: docsConfig,
|
|
1261
|
+
cursor,
|
|
1262
|
+
selfOpenId,
|
|
1263
|
+
nowMs: Date.now(),
|
|
1264
|
+
nowIso: () => new Date().toISOString(),
|
|
1265
|
+
actionItemDeps: {
|
|
1266
|
+
graph: stores.graph,
|
|
1267
|
+
resolveOwner: async (ownerRaw) => {
|
|
1268
|
+
if (!ownerRaw)
|
|
1269
|
+
return null;
|
|
1270
|
+
// best-effort: map a name/@mention to a canonical person slug
|
|
1271
|
+
return ((await identity.resolveHandle("name", ownerRaw)) ??
|
|
1272
|
+
(await identity.resolveHandle("nickname", ownerRaw)) ??
|
|
1273
|
+
null);
|
|
1274
|
+
},
|
|
1275
|
+
isMe: (slug) => identity.isMe(slug),
|
|
1276
|
+
},
|
|
1277
|
+
});
|
|
1278
|
+
console.log(`[docs] scanned=${stats.candidates_scanned} pointer=${stats.pointer_saved} full=${stats.full_card_generated} skipped=${stats.skipped} queue=${stats.upgrade_queue_size} llm_failed=${stats.llm_failed}`);
|
|
1279
|
+
await stores.db.close();
|
|
1280
|
+
}
|
|
1281
|
+
catch (error) {
|
|
1282
|
+
console.error("docs sync failed:", error instanceof Error ? error.message : String(error));
|
|
1283
|
+
process.exit(1);
|
|
1284
|
+
}
|
|
1285
|
+
});
|
|
1286
|
+
docsCmd
|
|
1287
|
+
.command("status")
|
|
1288
|
+
.description("Show Feishu doc card counts")
|
|
1289
|
+
.option("-c, --config <path>", "Path to config file")
|
|
1290
|
+
.option("--failed", "List cards whose last extraction failed")
|
|
1291
|
+
.action(async (options) => {
|
|
1292
|
+
try {
|
|
1293
|
+
const config = loadConfig(options.config);
|
|
1294
|
+
const stores = await createStores(config);
|
|
1295
|
+
const pages = await stores.pages.listPages({ type: "feishu_doc_card", limit: 100000 });
|
|
1296
|
+
if (options.failed) {
|
|
1297
|
+
for (const f of failedCards(pages))
|
|
1298
|
+
console.log(`${f.doc_token}\t${f.error}`);
|
|
1299
|
+
}
|
|
1300
|
+
else {
|
|
1301
|
+
const s = summarizeCards(pages);
|
|
1302
|
+
console.log(`total=${s.total} full=${s.full} pointer=${s.pointer} failed=${s.failed}`);
|
|
1303
|
+
}
|
|
1304
|
+
await stores.db.close();
|
|
1305
|
+
}
|
|
1306
|
+
catch (error) {
|
|
1307
|
+
console.error("docs status failed:", error instanceof Error ? error.message : String(error));
|
|
1308
|
+
process.exit(1);
|
|
1309
|
+
}
|
|
1310
|
+
});
|
|
1311
|
+
docsCmd
|
|
1312
|
+
.command("retry [doc_token]")
|
|
1313
|
+
.description("Retry full-card extraction for a failed doc (or --all-failed)")
|
|
1314
|
+
.option("-c, --config <path>", "Path to config file")
|
|
1315
|
+
.option("--all-failed", "Retry every card with an extract_error")
|
|
1316
|
+
.action(async (docToken, options) => {
|
|
1317
|
+
try {
|
|
1318
|
+
const config = loadConfig(options.config);
|
|
1319
|
+
const feishu = config.sources.feishu;
|
|
1320
|
+
if (!feishu?.sources?.docs?.enabled) {
|
|
1321
|
+
console.error("Feishu docs source not enabled.");
|
|
1322
|
+
process.exit(1);
|
|
1323
|
+
}
|
|
1324
|
+
const stores = await createStores(config);
|
|
1325
|
+
const client = new LarkCliHttpClient(feishu.lark_bin);
|
|
1326
|
+
const docsConfig = normalizeDocsConfig(feishu.sources.docs);
|
|
1327
|
+
const llmConfig = { ...config.llm };
|
|
1328
|
+
if (docsConfig.llm.model)
|
|
1329
|
+
llmConfig.model = docsConfig.llm.model;
|
|
1330
|
+
const envKey = llmConfig.provider === "anthropic"
|
|
1331
|
+
? process.env.ANTHROPIC_API_KEY
|
|
1332
|
+
: process.env.OPENAI_API_KEY;
|
|
1333
|
+
if (!llmConfig.api_key && envKey)
|
|
1334
|
+
llmConfig.api_key = envKey;
|
|
1335
|
+
const provider = llmConfig.api_key
|
|
1336
|
+
? createLLMProvider(llmConfig)
|
|
1337
|
+
: createMockProvider(new Map());
|
|
1338
|
+
const builder = new FullCardBuilder(client, provider, docsConfig.llm.model ?? "unknown", () => new Date().toISOString());
|
|
1339
|
+
const tokens = [];
|
|
1340
|
+
if (options.allFailed) {
|
|
1341
|
+
const pages = await stores.pages.listPages({ type: "feishu_doc_card", limit: 100000 });
|
|
1342
|
+
for (const f of failedCards(pages))
|
|
1343
|
+
tokens.push(f.doc_token);
|
|
1344
|
+
}
|
|
1345
|
+
else if (docToken) {
|
|
1346
|
+
tokens.push(docToken);
|
|
1347
|
+
}
|
|
1348
|
+
else {
|
|
1349
|
+
console.error("Provide a doc_token or --all-failed.");
|
|
1350
|
+
process.exit(1);
|
|
1351
|
+
}
|
|
1352
|
+
for (const token of tokens) {
|
|
1353
|
+
const existing = await loadExistingCard(stores, token);
|
|
1354
|
+
if (!existing) {
|
|
1355
|
+
console.warn(`skip ${token}: no existing card`);
|
|
1356
|
+
continue;
|
|
1357
|
+
}
|
|
1358
|
+
// retry intentionally re-evaluates the gate (no force); short/empty docs
|
|
1359
|
+
// stay pointers by design — unlike MCP ingest which forces.
|
|
1360
|
+
const card = await builder.build(existing);
|
|
1361
|
+
await writeCard(stores, card);
|
|
1362
|
+
if (card.extract_level === "pointer") {
|
|
1363
|
+
const reason = card.extract_error ?? card.extract_skipped ?? "unknown";
|
|
1364
|
+
console.log(`${token}: pointer (not upgraded — ${reason})`);
|
|
1365
|
+
}
|
|
1366
|
+
else {
|
|
1367
|
+
console.log(`${token}: full`);
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
await stores.db.close();
|
|
1371
|
+
}
|
|
1372
|
+
catch (error) {
|
|
1373
|
+
console.error("docs retry failed:", error instanceof Error ? error.message : String(error));
|
|
1374
|
+
process.exit(1);
|
|
1375
|
+
}
|
|
1376
|
+
});
|
|
1377
|
+
// ---------------------------------------------------------------------------
|
|
1378
|
+
// SP4 — always-on daemon commands
|
|
1379
|
+
// ---------------------------------------------------------------------------
|
|
1380
|
+
program
|
|
1381
|
+
.command("up")
|
|
1382
|
+
.description("Start the always-on Memkin daemon and wire detected AI agents")
|
|
1383
|
+
.option("-c, --config <path>", "Path to config file (default: memkin.yaml)")
|
|
1384
|
+
.option("--port <n>", "Override MCP HTTP port", (v) => {
|
|
1385
|
+
const n = Number.parseInt(v, 10);
|
|
1386
|
+
if (Number.isNaN(n))
|
|
1387
|
+
throw new Error(`--port: invalid number "${v}"`);
|
|
1388
|
+
return n;
|
|
1389
|
+
})
|
|
1390
|
+
.option("--linger", "Enable systemd --linger so the service survives logout (Linux only)")
|
|
1391
|
+
.action(async (options) => {
|
|
1392
|
+
try {
|
|
1393
|
+
const result = await runUp({
|
|
1394
|
+
config: options.config,
|
|
1395
|
+
port: options.port,
|
|
1396
|
+
linger: !!options.linger,
|
|
1397
|
+
});
|
|
1398
|
+
console.log(`✓ Memkin daemon running`);
|
|
1399
|
+
console.log(` URL: ${result.url}`);
|
|
1400
|
+
console.log(` Port: ${result.port}`);
|
|
1401
|
+
console.log(` Engine: ${result.engine}`);
|
|
1402
|
+
if (result.wiredAgents.length > 0) {
|
|
1403
|
+
console.log(` Wired: ${result.wiredAgents.join(", ")}`);
|
|
1404
|
+
}
|
|
1405
|
+
if (result.skippedAgents.length > 0) {
|
|
1406
|
+
for (const s of result.skippedAgents) {
|
|
1407
|
+
console.log(` Skipped: ${s.id} — ${s.reason}`);
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
for (const w of result.warnings) {
|
|
1411
|
+
console.log(` ⚠ ${w}`);
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
catch (err) {
|
|
1415
|
+
console.error("memkin up failed:", err instanceof Error ? err.message : String(err));
|
|
1416
|
+
process.exit(1);
|
|
1417
|
+
}
|
|
1418
|
+
});
|
|
1419
|
+
program
|
|
1420
|
+
.command("down")
|
|
1421
|
+
.description("Stop the always-on daemon and remove its autostart entry")
|
|
1422
|
+
.action(async () => {
|
|
1423
|
+
const h = homedir();
|
|
1424
|
+
const plat = process.platform;
|
|
1425
|
+
try {
|
|
1426
|
+
// Best-effort config load to detect engine; safe to fail (down works without a config)
|
|
1427
|
+
let engine;
|
|
1428
|
+
try {
|
|
1429
|
+
const cfg = loadConfig();
|
|
1430
|
+
engine = cfg.store.engine;
|
|
1431
|
+
}
|
|
1432
|
+
catch {
|
|
1433
|
+
// no config or parse error — treat engine as unknown (non-managed)
|
|
1434
|
+
}
|
|
1435
|
+
const result = await down({
|
|
1436
|
+
home: h,
|
|
1437
|
+
platform: plat,
|
|
1438
|
+
acquireLock: acquireLifecycleLock,
|
|
1439
|
+
disable: () => disableAutostart({
|
|
1440
|
+
platform: plat,
|
|
1441
|
+
home: h,
|
|
1442
|
+
runner: nodeRunner,
|
|
1443
|
+
keepStateOnBootoutFailure: true,
|
|
1444
|
+
}),
|
|
1445
|
+
engine,
|
|
1446
|
+
stopManagedPg: () => stopManagedFromState(h, nodeRunner).then(() => undefined),
|
|
1447
|
+
});
|
|
1448
|
+
console.log(result.stopped ? `✓ ${result.note}` : `✗ ${result.note}`);
|
|
1449
|
+
}
|
|
1450
|
+
catch (err) {
|
|
1451
|
+
console.error("memkin down failed:", err instanceof Error ? err.message : String(err));
|
|
1452
|
+
process.exit(1);
|
|
1453
|
+
}
|
|
1454
|
+
});
|
|
1455
|
+
program
|
|
1456
|
+
.command("autostart <action>")
|
|
1457
|
+
.description("Manage daemon autostart entry (action: enable | disable | status)")
|
|
1458
|
+
.option("-c, --config <path>", "Path to config file (required for enable)")
|
|
1459
|
+
.option("--port <n>", "Override MCP HTTP port (for enable)", (v) => {
|
|
1460
|
+
const n = Number.parseInt(v, 10);
|
|
1461
|
+
if (Number.isNaN(n))
|
|
1462
|
+
throw new Error(`--port: invalid number "${v}"`);
|
|
1463
|
+
return n;
|
|
1464
|
+
})
|
|
1465
|
+
.action(async (action, options) => {
|
|
1466
|
+
const h = homedir();
|
|
1467
|
+
const plat = process.platform;
|
|
1468
|
+
try {
|
|
1469
|
+
if (action === "enable") {
|
|
1470
|
+
// Delegate fully to runUp which handles all the state-building
|
|
1471
|
+
await runUp({
|
|
1472
|
+
config: options.config,
|
|
1473
|
+
port: options.port,
|
|
1474
|
+
});
|
|
1475
|
+
console.log("✓ Autostart enabled.");
|
|
1476
|
+
}
|
|
1477
|
+
else if (action === "disable") {
|
|
1478
|
+
const res = await disableAutostart({ platform: plat, home: h, runner: nodeRunner });
|
|
1479
|
+
if (res.launcherCode && res.launcherCode !== 0) {
|
|
1480
|
+
console.warn(`Launcher returned non-zero (${res.launcherCode}): ${res.launcherStderr ?? ""}`);
|
|
1481
|
+
}
|
|
1482
|
+
console.log("✓ Autostart disabled.");
|
|
1483
|
+
}
|
|
1484
|
+
else if (action === "status") {
|
|
1485
|
+
const st = await statusAutostart({ platform: plat, home: h, runner: nodeRunner });
|
|
1486
|
+
console.log("Desired state:", st.desired ? JSON.stringify(st.desired, null, 2) : "(none)");
|
|
1487
|
+
console.log(`Launcher output:\n${st.raw}`);
|
|
1488
|
+
}
|
|
1489
|
+
else {
|
|
1490
|
+
console.error(`Unknown autostart action "${action}". Use: enable | disable | status`);
|
|
1491
|
+
process.exit(1);
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
catch (err) {
|
|
1495
|
+
console.error(`memkin autostart ${action} failed:`, err instanceof Error ? err.message : String(err));
|
|
1496
|
+
process.exit(1);
|
|
1497
|
+
}
|
|
1498
|
+
});
|
|
1499
|
+
program
|
|
1500
|
+
.command("status")
|
|
1501
|
+
.description("Show the current state of the always-on daemon")
|
|
1502
|
+
.action(async () => {
|
|
1503
|
+
const h = homedir();
|
|
1504
|
+
const stateDir = join(h, ".memkin");
|
|
1505
|
+
const stored = readDaemonState(stateDir);
|
|
1506
|
+
let health = null;
|
|
1507
|
+
if (stored?.url) {
|
|
1508
|
+
try {
|
|
1509
|
+
const healthUrl = stored.url.replace(/\/mcp$/, "/health");
|
|
1510
|
+
const r = await fetch(healthUrl);
|
|
1511
|
+
health = {
|
|
1512
|
+
status: r.status,
|
|
1513
|
+
body: (await r.json().catch(() => ({}))),
|
|
1514
|
+
};
|
|
1515
|
+
}
|
|
1516
|
+
catch {
|
|
1517
|
+
health = null;
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
let currentRawHash = null;
|
|
1521
|
+
let currentServingHash = null;
|
|
1522
|
+
if (stored?.config_path) {
|
|
1523
|
+
try {
|
|
1524
|
+
currentRawHash = rawYamlHash(stored.config_path);
|
|
1525
|
+
const cfg = loadConfig(stored.config_path);
|
|
1526
|
+
const rt = resolveMcpHttpRuntime(cfg.mcp.http, {});
|
|
1527
|
+
currentServingHash = servingSubsetHash({
|
|
1528
|
+
bind: rt.bind,
|
|
1529
|
+
port: rt.port,
|
|
1530
|
+
readOnly: rt.readOnly,
|
|
1531
|
+
hosts: rt.allowedHosts,
|
|
1532
|
+
});
|
|
1533
|
+
}
|
|
1534
|
+
catch {
|
|
1535
|
+
// config unreadable
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
const report = computeStatus({ stored, currentRawHash, currentServingHash, health });
|
|
1539
|
+
console.log(`Status: ${report.running ? "running ✓" : "stopped ✗"}`);
|
|
1540
|
+
if (report.url)
|
|
1541
|
+
console.log(`URL: ${report.url}`);
|
|
1542
|
+
if (report.pid)
|
|
1543
|
+
console.log(`PID: ${report.pid}`);
|
|
1544
|
+
if (report.engine)
|
|
1545
|
+
console.log(`Engine: ${report.engine}`);
|
|
1546
|
+
if (report.configPath)
|
|
1547
|
+
console.log(`Config: ${report.configPath}`);
|
|
1548
|
+
if (report.drift.configChanged)
|
|
1549
|
+
console.log("⚠ Config changed since last up — run `memkin up` to apply.");
|
|
1550
|
+
if (report.drift.needsReup)
|
|
1551
|
+
console.log("⚠ Serving subset changed — run `memkin up` to re-register agents.");
|
|
1552
|
+
if (report.drift.restartedOntoEditedConfig)
|
|
1553
|
+
console.log("⚠ Daemon restarted onto edited config.");
|
|
1554
|
+
// Show managed Postgres state when engine is managed
|
|
1555
|
+
const managedState = readManagedState(managedPaths(h, "17"));
|
|
1556
|
+
if (managedState) {
|
|
1557
|
+
// Lightweight pg_ctl status probe — run if pg_ctl is available
|
|
1558
|
+
let clusterRunning = null;
|
|
1559
|
+
try {
|
|
1560
|
+
const { spawnSync } = await import("node:child_process");
|
|
1561
|
+
const result = spawnSync(managedState.pgCtlPath, ["status", "-D", managedState.pgdata], {
|
|
1562
|
+
encoding: "utf8",
|
|
1563
|
+
timeout: 3000,
|
|
1564
|
+
});
|
|
1565
|
+
// pg_ctl status exits 0 if running, non-zero if stopped/no data dir
|
|
1566
|
+
clusterRunning = result.status === 0;
|
|
1567
|
+
}
|
|
1568
|
+
catch {
|
|
1569
|
+
clusterRunning = null;
|
|
1570
|
+
}
|
|
1571
|
+
const managedLines = formatManagedStatus(managedState, clusterRunning);
|
|
1572
|
+
console.log("");
|
|
1573
|
+
for (const line of managedLines) {
|
|
1574
|
+
console.log(`${line.label}: ${line.value}`);
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
});
|
|
1578
|
+
program.parse(process.argv);
|
|
1579
|
+
//# sourceMappingURL=cli.js.map
|