@andre.li/memoark 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +191 -0
- package/README.en.md +606 -0
- package/README.md +560 -0
- package/bin/memoark.mjs +36 -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 +641 -0
- package/dist/adapters/store.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +694 -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/collector.d.ts +23 -0
- package/dist/collectors/feishu/collector.d.ts.map +1 -0
- package/dist/collectors/feishu/collector.js +113 -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/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 +16 -0
- package/dist/collectors/feishu/lark-cli-client.d.ts.map +1 -0
- package/dist/collectors/feishu/lark-cli-client.js +69 -0
- package/dist/collectors/feishu/lark-cli-client.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/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 +93 -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 +152 -0
- package/dist/collectors/feishu/sources/dm.js.map +1 -0
- package/dist/collectors/feishu/sources/docs.d.ts +23 -0
- package/dist/collectors/feishu/sources/docs.d.ts.map +1 -0
- package/dist/collectors/feishu/sources/docs.js +154 -0
- package/dist/collectors/feishu/sources/docs.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 +136 -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 +26 -0
- package/dist/collectors/feishu/sources/messages.d.ts.map +1 -0
- package/dist/collectors/feishu/sources/messages.js +148 -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 +224 -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 +365 -0
- package/dist/config-center/schema.js.map +1 -0
- package/dist/config-center/secrets.d.ts +4 -0
- package/dist/config-center/secrets.d.ts.map +1 -0
- package/dist/config-center/secrets.js +27 -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 +31 -0
- package/dist/consolidator/consolidator.d.ts.map +1 -0
- package/dist/consolidator/consolidator.js +57 -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 +137 -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 +184 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +136 -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/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 +21 -0
- package/dist/core/identity-resolver.d.ts.map +1 -0
- package/dist/core/identity-resolver.js +62 -0
- package/dist/core/identity-resolver.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 +32 -0
- package/dist/core/pipeline-factory.js.map +1 -0
- package/dist/core/pipeline.d.ts +61 -0
- package/dist/core/pipeline.d.ts.map +1 -0
- package/dist/core/pipeline.js +261 -0
- package/dist/core/pipeline.js.map +1 -0
- package/dist/core/schemas.d.ts +2470 -0
- package/dist/core/schemas.d.ts.map +1 -0
- package/dist/core/schemas.js +229 -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 +124 -0
- package/dist/core/signal-scoring.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 +32 -0
- package/dist/core/state.js.map +1 -0
- package/dist/core/types.d.ts +231 -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/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/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 +37 -0
- package/dist/daemon/scheduler.d.ts.map +1 -0
- package/dist/daemon/scheduler.js +142 -0
- package/dist/daemon/scheduler.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/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 +29 -0
- package/dist/extractors/signal-extractor.d.ts.map +1 -0
- package/dist/extractors/signal-extractor.js +279 -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/processors/privacy.d.ts +98 -0
- package/dist/processors/privacy.d.ts.map +1 -0
- package/dist/processors/privacy.js +271 -0
- package/dist/processors/privacy.js.map +1 -0
- package/dist/server/api.d.ts +35 -0
- package/dist/server/api.d.ts.map +1 -0
- package/dist/server/api.js +453 -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 +123 -0
- package/dist/server/backfill-routes.js.map +1 -0
- package/dist/server/config-routes.d.ts +8 -0
- package/dist/server/config-routes.d.ts.map +1 -0
- package/dist/server/config-routes.js +114 -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.d.ts +126 -0
- package/dist/server/mcp.d.ts.map +1 -0
- package/dist/server/mcp.js +103 -0
- package/dist/server/mcp.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 +52 -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 +67 -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/generate-config.d.ts +5 -0
- package/dist/setup/generate-config.d.ts.map +1 -0
- package/dist/setup/generate-config.js +103 -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 +19 -0
- package/dist/setup/init-wizard.d.ts.map +1 -0
- package/dist/setup/init-wizard.js +501 -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 +26 -0
- package/dist/setup/validate-config.d.ts.map +1 -0
- package/dist/setup/validate-config.js +27 -0
- package/dist/setup/validate-config.js.map +1 -0
- package/dist/store/chunks.d.ts +19 -0
- package/dist/store/chunks.d.ts.map +1 -0
- package/dist/store/chunks.js +70 -0
- package/dist/store/chunks.js.map +1 -0
- package/dist/store/database.d.ts +24 -0
- package/dist/store/database.d.ts.map +1 -0
- package/dist/store/database.js +62 -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/graph.d.ts +53 -0
- package/dist/store/graph.d.ts.map +1 -0
- package/dist/store/graph.js +186 -0
- package/dist/store/graph.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 +68 -0
- package/dist/store/migrations/index.js.map +1 -0
- package/dist/store/pages.d.ts +39 -0
- package/dist/store/pages.d.ts.map +1 -0
- package/dist/store/pages.js +150 -0
- package/dist/store/pages.js.map +1 -0
- package/dist/store/search.d.ts +37 -0
- package/dist/store/search.d.ts.map +1 -0
- package/dist/store/search.js +200 -0
- package/dist/store/search.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 +31 -0
- package/dist/store/tags.js.map +1 -0
- package/dist/store/timeline.d.ts +26 -0
- package/dist/store/timeline.d.ts.map +1 -0
- package/dist/store/timeline.js +43 -0
- package/dist/store/timeline.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 +539 -0
- package/dist/sync/obsidian.js.map +1 -0
- package/package.json +84 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { classifyResult, SourceSchedule } from "./source-schedule.js";
|
|
4
|
+
export class Scheduler {
|
|
5
|
+
schedules = new Map();
|
|
6
|
+
timer = null;
|
|
7
|
+
running = false;
|
|
8
|
+
daemon_started_at;
|
|
9
|
+
last_heartbeat_at;
|
|
10
|
+
tick_interval_ms;
|
|
11
|
+
state_path;
|
|
12
|
+
onTick;
|
|
13
|
+
runSource;
|
|
14
|
+
constructor(config, stateDir) {
|
|
15
|
+
this.tick_interval_ms = config.tick_interval_secs * 1000;
|
|
16
|
+
this.state_path = join(stateDir, "scheduler-state.json");
|
|
17
|
+
this.daemon_started_at = Date.now();
|
|
18
|
+
this.last_heartbeat_at = Date.now();
|
|
19
|
+
const saved = this.loadState();
|
|
20
|
+
for (const [sourceId, sourceConfig] of Object.entries(config.sources)) {
|
|
21
|
+
if (sourceConfig.enabled === false)
|
|
22
|
+
continue;
|
|
23
|
+
const interval = sourceConfig.interval_secs ?? config.defaults.interval_secs;
|
|
24
|
+
if (saved?.sources[sourceId]) {
|
|
25
|
+
this.schedules.set(sourceId, SourceSchedule.fromSerialized(sourceId, interval, saved.sources[sourceId]));
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
this.schedules.set(sourceId, new SourceSchedule(sourceId, interval));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (saved) {
|
|
32
|
+
this.daemon_started_at = saved.daemon_started_at;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
getSourceIds() {
|
|
36
|
+
return Array.from(this.schedules.keys());
|
|
37
|
+
}
|
|
38
|
+
getSourceState(sourceId) {
|
|
39
|
+
const s = this.schedules.get(sourceId);
|
|
40
|
+
if (!s)
|
|
41
|
+
return undefined;
|
|
42
|
+
return { ...s.state, interval_secs: s.interval_secs };
|
|
43
|
+
}
|
|
44
|
+
setRunSource(fn) {
|
|
45
|
+
this.runSource = fn;
|
|
46
|
+
}
|
|
47
|
+
setOnTick(fn) {
|
|
48
|
+
this.onTick = fn;
|
|
49
|
+
}
|
|
50
|
+
async start() {
|
|
51
|
+
this.tick();
|
|
52
|
+
this.timer = setInterval(() => this.tick(), this.tick_interval_ms);
|
|
53
|
+
}
|
|
54
|
+
stop() {
|
|
55
|
+
if (this.timer)
|
|
56
|
+
clearInterval(this.timer);
|
|
57
|
+
this.timer = null;
|
|
58
|
+
this.persistState();
|
|
59
|
+
}
|
|
60
|
+
async tick() {
|
|
61
|
+
if (this.running)
|
|
62
|
+
return;
|
|
63
|
+
this.running = true;
|
|
64
|
+
this.last_heartbeat_at = Date.now();
|
|
65
|
+
try {
|
|
66
|
+
const now = Date.now();
|
|
67
|
+
for (const [sourceId, schedule] of this.schedules) {
|
|
68
|
+
if (!schedule.isDue(now))
|
|
69
|
+
continue;
|
|
70
|
+
this.last_heartbeat_at = Date.now();
|
|
71
|
+
if (!this.runSource)
|
|
72
|
+
continue;
|
|
73
|
+
const start = Date.now();
|
|
74
|
+
try {
|
|
75
|
+
const result = await this.runSource(sourceId);
|
|
76
|
+
const duration_ms = Date.now() - start;
|
|
77
|
+
const classified = classifyResult(result);
|
|
78
|
+
schedule.recordResult(classified, Date.now(), result.error);
|
|
79
|
+
this.onTick?.(sourceId, result, duration_ms);
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
const duration_ms = Date.now() - start;
|
|
83
|
+
schedule.recordResult("failed", Date.now(), err instanceof Error ? err.message : String(err));
|
|
84
|
+
const fakeResult = {
|
|
85
|
+
fatal: true,
|
|
86
|
+
error: err instanceof Error ? err.message : String(err),
|
|
87
|
+
totalMessages: 0,
|
|
88
|
+
totalBlocks: 0,
|
|
89
|
+
okBlocks: 0,
|
|
90
|
+
skippedBlocks: 0,
|
|
91
|
+
failedBlocks: 0,
|
|
92
|
+
okMessages: [],
|
|
93
|
+
skippedMessages: [],
|
|
94
|
+
failedMessages: [],
|
|
95
|
+
warnings: [],
|
|
96
|
+
};
|
|
97
|
+
this.onTick?.(sourceId, fakeResult, duration_ms);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
this.running = false;
|
|
103
|
+
this.last_heartbeat_at = Date.now();
|
|
104
|
+
this.persistState();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
getHeartbeat() {
|
|
108
|
+
return { daemon_started_at: this.daemon_started_at, last_heartbeat_at: this.last_heartbeat_at };
|
|
109
|
+
}
|
|
110
|
+
getAlertSources() {
|
|
111
|
+
return Array.from(this.schedules.entries())
|
|
112
|
+
.filter(([_, s]) => s.shouldAlert())
|
|
113
|
+
.map(([id]) => id);
|
|
114
|
+
}
|
|
115
|
+
getAlertDetails() {
|
|
116
|
+
return Array.from(this.schedules.entries())
|
|
117
|
+
.filter(([_, s]) => s.shouldAlert())
|
|
118
|
+
.map(([id, s]) => ({ source_id: id, state: s.serialize() }));
|
|
119
|
+
}
|
|
120
|
+
persistState() {
|
|
121
|
+
const data = {
|
|
122
|
+
daemon_started_at: this.daemon_started_at,
|
|
123
|
+
last_heartbeat_at: this.last_heartbeat_at,
|
|
124
|
+
sources: {},
|
|
125
|
+
};
|
|
126
|
+
for (const [id, s] of this.schedules) {
|
|
127
|
+
data.sources[id] = s.serialize();
|
|
128
|
+
}
|
|
129
|
+
writeFileSync(this.state_path, `${JSON.stringify(data, null, 2)}\n`);
|
|
130
|
+
}
|
|
131
|
+
loadState() {
|
|
132
|
+
if (!existsSync(this.state_path))
|
|
133
|
+
return null;
|
|
134
|
+
try {
|
|
135
|
+
return JSON.parse(readFileSync(this.state_path, "utf-8"));
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/daemon/scheduler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { PipelineResult } from "../core/pipeline.js";
|
|
2
|
+
export type RunResult = "ok" | "partial" | "failed";
|
|
3
|
+
export declare function classifyResult(r: PipelineResult): RunResult;
|
|
4
|
+
export declare function computeBackoff(base_interval_secs: number, consecutive_failures: number): number;
|
|
5
|
+
export interface SourceState {
|
|
6
|
+
last_run_at: number | null;
|
|
7
|
+
last_result: RunResult | null;
|
|
8
|
+
last_error: string | null;
|
|
9
|
+
consecutive_failures: number;
|
|
10
|
+
consecutive_partials: number;
|
|
11
|
+
}
|
|
12
|
+
export declare class SourceSchedule {
|
|
13
|
+
readonly source_id: string;
|
|
14
|
+
readonly interval_secs: number;
|
|
15
|
+
state: SourceState;
|
|
16
|
+
constructor(source_id: string, interval_secs: number);
|
|
17
|
+
isDue(now: number): boolean;
|
|
18
|
+
recordResult(result: RunResult, timestamp: number, error?: string): void;
|
|
19
|
+
shouldAlert(): boolean;
|
|
20
|
+
nextRunAt(): number;
|
|
21
|
+
serialize(): SourceState;
|
|
22
|
+
static fromSerialized(source_id: string, interval_secs: number, saved: SourceState): SourceSchedule;
|
|
23
|
+
private effectiveIntervalMs;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=source-schedule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-schedule.d.ts","sourceRoot":"","sources":["../../src/daemon/source-schedule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEpD,wBAAgB,cAAc,CAAC,CAAC,EAAE,cAAc,GAAG,SAAS,CAK3D;AAID,wBAAgB,cAAc,CAAC,kBAAkB,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,GAAG,MAAM,CAG/F;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,SAAS,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAOD,qBAAa,cAAc;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,KAAK,EAAE,WAAW,CAAC;gBAEP,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM;IAYpD,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAM3B,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAgBxE,WAAW,IAAI,OAAO;IAOtB,SAAS,IAAI,MAAM;IAKnB,SAAS,IAAI,WAAW;IAIxB,MAAM,CAAC,cAAc,CACnB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,WAAW,GACjB,cAAc;IAMjB,OAAO,CAAC,mBAAmB;CAW5B"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
export function classifyResult(r) {
|
|
2
|
+
if (r.fatal)
|
|
3
|
+
return "failed";
|
|
4
|
+
if (r.failedBlocks > 0 && r.okBlocks > 0)
|
|
5
|
+
return "partial";
|
|
6
|
+
if (r.failedBlocks > 0 && r.okBlocks === 0)
|
|
7
|
+
return "failed";
|
|
8
|
+
return "ok";
|
|
9
|
+
}
|
|
10
|
+
const MAX_BACKOFF_SECS = 21600; // 6 hours
|
|
11
|
+
export function computeBackoff(base_interval_secs, consecutive_failures) {
|
|
12
|
+
const backoff = base_interval_secs * 2 ** consecutive_failures;
|
|
13
|
+
return Math.min(backoff, MAX_BACKOFF_SECS);
|
|
14
|
+
}
|
|
15
|
+
const PARTIAL_LIGHT_BACKOFF_THRESHOLD = 10;
|
|
16
|
+
const PARTIAL_LIGHT_BACKOFF_MULTIPLIER = 1.5;
|
|
17
|
+
const PARTIAL_ALERT_THRESHOLD = 5;
|
|
18
|
+
const FAILURE_ALERT_THRESHOLD = 3;
|
|
19
|
+
export class SourceSchedule {
|
|
20
|
+
source_id;
|
|
21
|
+
interval_secs;
|
|
22
|
+
state;
|
|
23
|
+
constructor(source_id, interval_secs) {
|
|
24
|
+
this.source_id = source_id;
|
|
25
|
+
this.interval_secs = interval_secs;
|
|
26
|
+
this.state = {
|
|
27
|
+
last_run_at: null,
|
|
28
|
+
last_result: null,
|
|
29
|
+
last_error: null,
|
|
30
|
+
consecutive_failures: 0,
|
|
31
|
+
consecutive_partials: 0,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
isDue(now) {
|
|
35
|
+
if (this.state.last_run_at === null)
|
|
36
|
+
return true;
|
|
37
|
+
const effective = this.effectiveIntervalMs();
|
|
38
|
+
return now - this.state.last_run_at >= effective;
|
|
39
|
+
}
|
|
40
|
+
recordResult(result, timestamp, error) {
|
|
41
|
+
this.state.last_run_at = timestamp;
|
|
42
|
+
this.state.last_result = result;
|
|
43
|
+
this.state.last_error = result === "failed" ? (error ?? null) : null;
|
|
44
|
+
if (result === "ok") {
|
|
45
|
+
this.state.consecutive_failures = 0;
|
|
46
|
+
this.state.consecutive_partials = 0;
|
|
47
|
+
}
|
|
48
|
+
else if (result === "partial") {
|
|
49
|
+
this.state.consecutive_partials++;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
this.state.consecutive_failures++;
|
|
53
|
+
this.state.consecutive_partials = 0;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
shouldAlert() {
|
|
57
|
+
return (this.state.consecutive_failures >= FAILURE_ALERT_THRESHOLD ||
|
|
58
|
+
this.state.consecutive_partials >= PARTIAL_ALERT_THRESHOLD);
|
|
59
|
+
}
|
|
60
|
+
nextRunAt() {
|
|
61
|
+
if (this.state.last_run_at === null)
|
|
62
|
+
return 0;
|
|
63
|
+
return this.state.last_run_at + this.effectiveIntervalMs();
|
|
64
|
+
}
|
|
65
|
+
serialize() {
|
|
66
|
+
return { ...this.state };
|
|
67
|
+
}
|
|
68
|
+
static fromSerialized(source_id, interval_secs, saved) {
|
|
69
|
+
const s = new SourceSchedule(source_id, interval_secs);
|
|
70
|
+
s.state = { ...saved };
|
|
71
|
+
return s;
|
|
72
|
+
}
|
|
73
|
+
effectiveIntervalMs() {
|
|
74
|
+
let secs;
|
|
75
|
+
if (this.state.consecutive_failures > 0) {
|
|
76
|
+
secs = computeBackoff(this.interval_secs, this.state.consecutive_failures);
|
|
77
|
+
}
|
|
78
|
+
else if (this.state.consecutive_partials >= PARTIAL_LIGHT_BACKOFF_THRESHOLD) {
|
|
79
|
+
secs = Math.min(this.interval_secs * PARTIAL_LIGHT_BACKOFF_MULTIPLIER, MAX_BACKOFF_SECS);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
secs = this.interval_secs;
|
|
83
|
+
}
|
|
84
|
+
return secs * 1000;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=source-schedule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-schedule.js","sourceRoot":"","sources":["../../src/daemon/source-schedule.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedded-assets.generated.d.ts","sourceRoot":"","sources":["../src/embedded-assets.generated.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,OAAO,EAAE,MAAgB,CAAC;AAEvC,eAAO,MAAM,UAAU,EAAE,MAA+sJ,CAAC;AAEzuJ,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAK1C,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// AUTO-GENERATED by scripts/gen-embedded-assets.mjs — do not edit by hand.
|
|
2
|
+
// Source: src/store/schema.sql + src/extractors/prompts/**/*.md
|
|
3
|
+
// Regenerate with `bun run gen:assets`.
|
|
4
|
+
export const VERSION = "0.3.1";
|
|
5
|
+
export const SCHEMA_SQL = "CREATE EXTENSION IF NOT EXISTS vector;\n\nCREATE TABLE IF NOT EXISTS pages (\n id SERIAL PRIMARY KEY,\n slug TEXT UNIQUE NOT NULL,\n type TEXT NOT NULL,\n title TEXT NOT NULL,\n compiled_truth TEXT NOT NULL DEFAULT '',\n frontmatter JSONB NOT NULL DEFAULT '{}',\n content_hash TEXT,\n halflife_days INTEGER,\n tier TEXT NOT NULL DEFAULT 'hot',\n expires_at TIMESTAMPTZ,\n consolidated_into INTEGER REFERENCES pages(id),\n search_vector TSVECTOR,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n);\n\nCREATE INDEX IF NOT EXISTS idx_pages_search_vector ON pages USING GIN (search_vector);\nCREATE INDEX IF NOT EXISTS idx_pages_tier ON pages (tier);\nCREATE INDEX IF NOT EXISTS idx_pages_expires_at ON pages (expires_at) WHERE expires_at IS NOT NULL;\n\nCREATE TABLE IF NOT EXISTS content_chunks (\n id SERIAL PRIMARY KEY,\n page_id INTEGER NOT NULL REFERENCES pages(id) ON DELETE CASCADE,\n chunk_index INTEGER NOT NULL,\n UNIQUE(page_id, chunk_index),\n chunk_text TEXT NOT NULL,\n chunk_source TEXT NOT NULL DEFAULT 'compiled_truth',\n token_count INTEGER,\n embedding vector(__EMBEDDING_DIM__),\n model TEXT NOT NULL DEFAULT 'text-embedding-3-large',\n embedded_at TIMESTAMPTZ,\n search_vector TSVECTOR,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n);\n\nCREATE INDEX IF NOT EXISTS idx_chunks_embedding ON content_chunks\n USING hnsw (embedding vector_cosine_ops);\nCREATE INDEX IF NOT EXISTS idx_chunks_search_vector ON content_chunks\n USING GIN (search_vector);\n\nCREATE TABLE IF NOT EXISTS links (\n id SERIAL PRIMARY KEY,\n from_page_id INTEGER NOT NULL REFERENCES pages(id) ON DELETE CASCADE,\n to_page_id INTEGER NOT NULL REFERENCES pages(id) ON DELETE CASCADE,\n link_type TEXT NOT NULL DEFAULT '',\n context TEXT NOT NULL DEFAULT '',\n provenance JSONB,\n source_hash TEXT,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n UNIQUE(from_page_id, to_page_id, link_type)\n);\n\nCREATE INDEX IF NOT EXISTS idx_links_from ON links (from_page_id);\nCREATE INDEX IF NOT EXISTS idx_links_to ON links (to_page_id);\n\nCREATE TABLE IF NOT EXISTS tags (\n id SERIAL PRIMARY KEY,\n page_id INTEGER NOT NULL REFERENCES pages(id) ON DELETE CASCADE,\n tag TEXT NOT NULL,\n UNIQUE(page_id, tag)\n);\n\nCREATE INDEX IF NOT EXISTS idx_tags_tag ON tags (tag);\n\nCREATE TABLE IF NOT EXISTS timeline_entries (\n id SERIAL PRIMARY KEY,\n page_id INTEGER NOT NULL REFERENCES pages(id) ON DELETE CASCADE,\n date TEXT NOT NULL,\n summary TEXT NOT NULL,\n detail TEXT NOT NULL DEFAULT '',\n source TEXT NOT NULL DEFAULT '',\n provenance JSONB,\n tier TEXT NOT NULL DEFAULT 'hot',\n expires_at TIMESTAMPTZ,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n UNIQUE(page_id, date, summary)\n);\n\n-- FTS Triggers\nCREATE OR REPLACE FUNCTION update_page_search_vector() RETURNS trigger AS $$\nBEGIN\n NEW.search_vector :=\n setweight(to_tsvector('simple', coalesce(NEW.title, '')), 'A') ||\n setweight(to_tsvector('simple', coalesce(NEW.compiled_truth, '')), 'B');\n RETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n\nDO $$ BEGIN\n IF NOT EXISTS (\n SELECT 1 FROM pg_trigger WHERE tgname = 'trg_pages_search_vector'\n ) THEN\n CREATE TRIGGER trg_pages_search_vector\n BEFORE INSERT OR UPDATE ON pages\n FOR EACH ROW EXECUTE FUNCTION update_page_search_vector();\n END IF;\nEND $$;\n\nCREATE OR REPLACE FUNCTION update_chunk_search_vector() RETURNS trigger AS $$\nBEGIN\n NEW.search_vector :=\n setweight(to_tsvector('simple', coalesce(NEW.chunk_text, '')), 'B');\n RETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n\nDO $$ BEGIN\n IF NOT EXISTS (\n SELECT 1 FROM pg_trigger WHERE tgname = 'chunk_search_vector_trigger'\n ) THEN\n CREATE TRIGGER chunk_search_vector_trigger\n BEFORE INSERT OR UPDATE OF chunk_text ON content_chunks\n FOR EACH ROW EXECUTE FUNCTION update_chunk_search_vector();\n END IF;\nEND $$;\n\n-- Identity cache for person slug canonicalization\nCREATE TABLE IF NOT EXISTS identity_cache (\n platform TEXT NOT NULL,\n external_id TEXT NOT NULL,\n display_name TEXT NOT NULL,\n slug_hint TEXT,\n resolved_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n PRIMARY KEY (platform, external_id)\n);\n\nDO $$ BEGIN\n IF NOT EXISTS (\n SELECT 1 FROM information_schema.columns\n WHERE table_name = 'identity_cache' AND column_name = 'slug_hint'\n ) THEN\n ALTER TABLE identity_cache ADD COLUMN slug_hint TEXT;\n END IF;\nEND $$;\n";
|
|
6
|
+
export const PROMPTS = {
|
|
7
|
+
"examples/agent-session.md": "# Example: Agent Session Extraction\n\n## Input Conversation\n\n```\n[2024-01-15T10:00:00Z] → Alice: We need to migrate from sessions to JWT for the auth system\n[2024-01-15T10:01:30Z] ← Bob: Makes sense for scaling. I can start this week.\n[2024-01-15T10:02:15Z] → Alice: Perfect. Let's use the HS256 algorithm initially.\n[2024-01-15T10:03:00Z] ← Bob: Got it. Should we add refresh tokens too?\n[2024-01-15T10:03:45Z] → Alice: Yes, 7-day access tokens and 30-day refresh tokens.\n[2024-01-15T10:04:30Z] ← Bob: I'll document the decision in the wiki before implementing.\n```\n\n## Output JSON\n\n```json\n{\n \"source\": {\n \"platform\": \"slack\",\n \"channel\": \"#engineering\",\n \"timestamp\": \"2024-01-15T10:00:00Z\",\n \"thread_id\": \"thread-auth-migration\",\n \"raw_hash\": \"abc123def456\",\n \"quote\": \"We need to migrate from sessions to JWT for the auth system\"\n },\n \"entities\": [\n {\n \"slug\": \"person/alice\",\n \"name\": \"Alice\",\n \"type\": \"person\",\n \"context\": \"Engineering lead discussing auth migration\",\n \"confidence\": \"direct\"\n },\n {\n \"slug\": \"person/bob\",\n \"name\": \"Bob\",\n \"type\": \"person\",\n \"context\": \"Developer implementing JWT auth system\",\n \"confidence\": \"direct\"\n },\n {\n \"slug\": \"project/auth-system\",\n \"name\": \"Auth System\",\n \"type\": \"project\",\n \"context\": \"Authentication system being migrated to JWT\",\n \"confidence\": \"direct\"\n },\n {\n \"slug\": \"tool/jwt\",\n \"name\": \"JWT (JSON Web Tokens)\",\n \"type\": \"tool\",\n \"context\": \"Token-based authentication mechanism replacing sessions\",\n \"confidence\": \"direct\"\n },\n {\n \"slug\": \"concept/refresh-tokens\",\n \"name\": \"Refresh Tokens\",\n \"type\": \"concept\",\n \"context\": \"30-day tokens for obtaining new access tokens\",\n \"confidence\": \"direct\"\n }\n ],\n \"timeline\": [\n {\n \"date\": \"2024-01-15\",\n \"summary\": \"Decision to migrate from sessions to JWT authentication\",\n \"entities\": [\"person/alice\", \"person/bob\", \"project/auth-system\", \"tool/jwt\"],\n \"source\": {\n \"platform\": \"slack\",\n \"channel\": \"#engineering\",\n \"timestamp\": \"2024-01-15T10:00:00Z\",\n \"thread_id\": \"thread-auth-migration\",\n \"raw_hash\": \"abc123def456\",\n \"quote\": \"We need to migrate from sessions to JWT for the auth system\"\n },\n \"confidence\": \"direct\"\n },\n {\n \"date\": \"2024-01-15\",\n \"summary\": \"Bob commits to starting JWT migration this week\",\n \"entities\": [\"person/bob\", \"project/auth-system\"],\n \"source\": {\n \"platform\": \"slack\",\n \"channel\": \"#engineering\",\n \"timestamp\": \"2024-01-15T10:01:30Z\",\n \"thread_id\": \"thread-auth-migration\",\n \"raw_hash\": \"abc123def456\",\n \"quote\": \"Makes sense for scaling. I can start this week.\"\n },\n \"confidence\": \"direct\"\n }\n ],\n \"links\": [\n {\n \"from\": \"person/bob\",\n \"to\": \"project/auth-system\",\n \"type\": \"works_on\",\n \"context\": \"Bob is implementing the JWT migration for auth system\",\n \"confidence\": \"direct\"\n },\n {\n \"from\": \"project/auth-system\",\n \"to\": \"tool/jwt\",\n \"type\": \"depends_on\",\n \"context\": \"Auth system will use JWT for token-based authentication\",\n \"confidence\": \"direct\"\n },\n {\n \"from\": \"person/alice\",\n \"to\": \"project/auth-system\",\n \"type\": \"works_on\",\n \"context\": \"Alice is leading the auth system migration decision\",\n \"confidence\": \"paraphrased\"\n }\n ],\n \"decisions\": [\n {\n \"summary\": \"Migrate authentication from sessions to JWT\",\n \"reasoning\": \"Better for scaling across multiple instances\",\n \"alternatives\": [\"Keep session-based auth\", \"Use OAuth2\"],\n \"entities\": [\"project/auth-system\", \"tool/jwt\"],\n \"date\": \"2024-01-15\",\n \"confidence\": \"direct\",\n \"source\": {\n \"platform\": \"slack\",\n \"channel\": \"#engineering\",\n \"timestamp\": \"2024-01-15T10:00:00Z\",\n \"thread_id\": \"thread-auth-migration\",\n \"raw_hash\": \"abc123def456\",\n \"quote\": \"We need to migrate from sessions to JWT for the auth system\"\n }\n },\n {\n \"summary\": \"Use HS256 algorithm for JWT signing\",\n \"entities\": [\"tool/jwt\"],\n \"date\": \"2024-01-15\",\n \"confidence\": \"direct\",\n \"source\": {\n \"platform\": \"slack\",\n \"channel\": \"#engineering\",\n \"timestamp\": \"2024-01-15T10:02:15Z\",\n \"thread_id\": \"thread-auth-migration\",\n \"raw_hash\": \"abc123def456\",\n \"quote\": \"Let's use the HS256 algorithm initially.\"\n }\n },\n {\n \"summary\": \"Token expiration: 7-day access tokens, 30-day refresh tokens\",\n \"entities\": [\"tool/jwt\", \"concept/refresh-tokens\"],\n \"date\": \"2024-01-15\",\n \"confidence\": \"direct\",\n \"source\": {\n \"platform\": \"slack\",\n \"channel\": \"#engineering\",\n \"timestamp\": \"2024-01-15T10:03:45Z\",\n \"thread_id\": \"thread-auth-migration\",\n \"raw_hash\": \"abc123def456\",\n \"quote\": \"Yes, 7-day access tokens and 30-day refresh tokens.\"\n }\n }\n ],\n \"tasks\": [\n {\n \"title\": \"Implement JWT-based authentication\",\n \"status\": \"open\",\n \"owner\": \"person/bob\",\n \"project\": \"project/auth-system\",\n \"valid_at\": \"2024-01-15T10:01:30Z\",\n \"source\": {\n \"platform\": \"slack\",\n \"channel\": \"#engineering\",\n \"timestamp\": \"2024-01-15T10:01:30Z\",\n \"thread_id\": \"thread-auth-migration\",\n \"raw_hash\": \"abc123def456\",\n \"quote\": \"I can start this week.\"\n },\n \"confidence\": \"direct\"\n },\n {\n \"title\": \"Document JWT migration decision in wiki\",\n \"status\": \"open\",\n \"owner\": \"person/bob\",\n \"project\": \"project/auth-system\",\n \"valid_at\": \"2024-01-15T10:04:30Z\",\n \"source\": {\n \"platform\": \"slack\",\n \"channel\": \"#engineering\",\n \"timestamp\": \"2024-01-15T10:04:30Z\",\n \"thread_id\": \"thread-auth-migration\",\n \"raw_hash\": \"abc123def456\",\n \"quote\": \"I'll document the decision in the wiki before implementing.\"\n },\n \"confidence\": \"direct\"\n }\n ],\n \"discoveries\": [\n {\n \"summary\": \"Session-based auth doesn't scale well across multiple instances\",\n \"type\": \"insight\",\n \"entities\": [\"project/auth-system\"],\n \"source\": {\n \"platform\": \"slack\",\n \"channel\": \"#engineering\",\n \"timestamp\": \"2024-01-15T10:01:30Z\",\n \"thread_id\": \"thread-auth-migration\",\n \"raw_hash\": \"abc123def456\",\n \"quote\": \"Makes sense for scaling.\"\n },\n \"confidence\": \"paraphrased\"\n },\n {\n \"summary\": \"Document architectural decisions before implementation\",\n \"type\": \"procedure\",\n \"entities\": [\"person/bob\"],\n \"source\": {\n \"platform\": \"slack\",\n \"channel\": \"#engineering\",\n \"timestamp\": \"2024-01-15T10:04:30Z\",\n \"thread_id\": \"thread-auth-migration\",\n \"raw_hash\": \"abc123def456\",\n \"quote\": \"I'll document the decision in the wiki before implementing.\"\n },\n \"confidence\": \"direct\"\n }\n ],\n \"knowledge\": [\n {\n \"topic\": \"jwt-token-expiration\",\n \"content\": \"Access tokens should be short-lived (minutes to hours) while refresh tokens can be longer-lived (days to weeks) to balance security with user experience\",\n \"source_type\": \"teaching\",\n \"related_entities\": [\"tool/jwt\", \"concept/refresh-tokens\"],\n \"source\": {\n \"platform\": \"slack\",\n \"channel\": \"#engineering\",\n \"timestamp\": \"2024-01-15T10:03:45Z\",\n \"thread_id\": \"thread-auth-migration\",\n \"raw_hash\": \"abc123def456\",\n \"quote\": \"Yes, 7-day access tokens and 30-day refresh tokens.\"\n },\n \"confidence\": \"paraphrased\"\n }\n ],\n \"preferences\": [],\n \"references\": []\n}\n```\n\n## Key Takeaways from This Example\n\n1. **Entity consistency**: Same person/project mentioned multiple times uses the same slug\n2. **Confidence levels**: Most are \"direct\" (explicit), some \"paraphrased\" (clear implication)\n3. **Rich context**: Each signal includes enough context to understand it standalone\n4. **Quotes**: All under 300 chars, capturing the key statement\n5. **Links**: Connect entities with specific relationship types\n6. **Timeline**: Events ordered chronologically with clear summaries\n7. **Decisions**: Capture not just what was decided, but why and what alternatives existed\n8. **Tasks**: Include owner, status, and timing information\n9. **Discoveries**: Extract both insights (learnings) and procedures (how-to)\n10. **Knowledge**: Extract reusable facts that stand alone without the original conversation context\n11. **Preferences and references**: Always include both arrays even when empty — this conversation has no shared links and no explicit standing-preference statements (the wiki-documentation comment is a one-off recommendation, correctly classified as `discovery.type=procedure`, not duplicated as a preference)\n",
|
|
8
|
+
"signal-extract.md": "# Signal Extraction Task\n\nExtract structured signals from the provided conversation block following the schema below.\n\n## Output Schema\n\n```typescript\ninterface ExtractionResult {\n source: SourceRef;\n entities: Entity[];\n timeline: TimelineEntry[];\n links: Link[];\n decisions: Decision[];\n tasks: TaskSignal[];\n discoveries: Discovery[];\n knowledge: Knowledge[];\n preferences: Preference[];\n references: Reference[];\n}\n\ninterface SourceRef {\n platform: string; // e.g., \"slack\", \"claude-code\"\n channel: string; // e.g., \"#general\", \"session-123\"\n timestamp: string; // ISO 8601\n message_id?: string;\n thread_id?: string;\n file_path?: string;\n line_range?: { start: number; end: number };\n attachment_id?: string;\n url?: string;\n raw_hash: string; // generated by system\n quote: string; // ≤ 300 chars, most relevant excerpt\n}\n\ninterface Entity {\n slug: string; // Format: {type}/{kebab-name}\n name: string; // Display name\n type: 'person' | 'project' | 'organization' | 'tool' | 'concept';\n context: string; // Brief description\n confidence: 'direct' | 'paraphrased' | 'inferred' | 'speculative';\n}\n\ninterface TimelineEntry {\n date: string; // ISO 8601 or partial (YYYY-MM, YYYY)\n summary: string; // Event description\n entities: string[]; // Slugs of involved entities\n source: SourceRef;\n confidence: 'direct' | 'paraphrased' | 'inferred' | 'speculative';\n}\n\ninterface Link {\n from: string; // Entity slug\n to: string; // Entity slug\n type: 'works_on' | 'works_at' | 'reports_to' | 'collaborates' | 'depends_on' | 'mentions' | 'custom';\n context: string; // Description of relationship\n confidence: 'direct' | 'paraphrased' | 'inferred' | 'speculative';\n source: SourceRef;\n}\n\ninterface Decision {\n summary: string; // What was decided\n reasoning?: string; // Why (if mentioned)\n alternatives?: string[]; // Other options considered\n entities: string[]; // Slugs of entities involved\n date: string; // ISO 8601\n valid_at?: string; // When decision takes effect\n invalid_at?: string; // When decision expires/superseded\n confidence: 'direct' | 'paraphrased' | 'inferred' | 'speculative';\n source: SourceRef;\n}\n\ninterface TaskSignal {\n title: string; // Task description\n status: 'open' | 'in_progress' | 'done' | 'cancelled';\n owner?: string; // Entity slug\n project?: string; // Entity slug\n due_date?: string; // ISO 8601\n valid_at?: string; // When task was created\n invalid_at?: string; // When task was closed\n source: SourceRef;\n confidence: 'direct' | 'paraphrased' | 'inferred' | 'speculative';\n}\n\ninterface Discovery {\n summary: string; // Brief insight\n detail?: string; // Extended explanation\n type: 'procedure' | 'pattern' | 'insight' | 'risk';\n entities: string[]; // Slugs of related entities\n source: SourceRef;\n confidence: 'direct' | 'paraphrased' | 'inferred' | 'speculative';\n}\ninterface Knowledge {\n topic: string; // kebab-case topic tag: \"react-hooks\", \"feishu-api\"\n content: string; // Decontextualized knowledge statement\n source_type: 'conversation' | 'document' | 'teaching';\n related_entities: string[]; // Entity slugs (may reference entities not in this block)\n valid_at?: string; // ISO 8601, when knowledge becomes valid\n invalid_at?: string; // ISO 8601, when knowledge expires\n source: SourceRef;\n confidence: 'direct' | 'paraphrased' | 'inferred' | 'speculative';\n}\n\ninterface Preference {\n summary: string; // \"Prefers async communication over meetings\"\n detail?: string; // Extended explanation\n category: 'communication' | 'tooling' | 'scheduling' | 'workflow' | 'other';\n entities: string[]; // Slugs, usually a person\n source: SourceRef;\n confidence: 'direct' | 'paraphrased' | 'inferred' | 'speculative';\n}\n\ninterface Reference {\n title: string; // Document/resource title\n url: string; // The resource URL — must appear in source text\n summary: string; // ≤100 chars: what the resource is about\n trigger?: string; // When this would be useful to recall later\n entities: string[]; // Slugs of related entities\n source: SourceRef;\n confidence: 'direct' | 'paraphrased' | 'inferred' | 'speculative';\n}\n```\n\n## Extraction Rules\n\n### Entity Slugs\n- Format: `{type}/{kebab-case-name}`\n- Examples: `person/alice-smith`, `project/auth-system`, `tool/github-actions`\n- Be consistent: same entity = same slug across all signals\n- For people: use recognizable name (first name + last initial if ambiguous)\n- For projects/tools: use official name or widely-used abbreviation\n\n### Quotes\n- Maximum 300 characters\n- Select the most informative excerpt\n- Don't fabricate - copy exact text (can trim with \"...\")\n- Should stand alone and convey key context\n\n### Confidence Levels\n- **direct**: Explicitly stated (\"Alice will lead the auth project\")\n- **paraphrased**: Clear implication with different wording (\"Alice is taking charge of authentication\")\n- **inferred**: Reasonable deduction (\"Alice keeps talking about auth, likely leading it\")\n- **speculative**: Uncertain but possible (\"Alice might be involved based on previous mentions\")\n\n### Dates\n- Prefer ISO 8601: `2024-01-15T10:30:00Z`\n- Partial dates OK: `2024-01` (month), `2024` (year)\n- Relative dates: resolve to absolute if possible (\"last Tuesday\" → `2024-01-09`)\n- Uncertain dates: use best estimate with lower confidence\n\n### Empty Results\n- If no signals found, return empty arrays for all categories\n- Still include valid `source` with platform, channel, timestamp, and quote\n\n### Knowledge vs Discovery\n\nKnowledge (知识): Decontextualized, reusable facts or concepts\n ✓ \"React useEffect runs twice in StrictMode during development\"\n ✓ \"Feishu API global rate limit is 50 QPS\"\n ✓ \"TCP three-way handshake prevents stale connection requests\"\n\nDiscovery (发现): Scene-bound, time-bound findings\n ✓ \"Today's integration test found 5s latency on this endpoint\"\n ✓ \"Root cause of this bug is a race condition\"\n ✓ \"Local Docker DNS resolution is broken\"\n\nRules:\n 1. Remove time/scene info — is the statement still valid and valuable? Yes → Knowledge\n 2. Could this be a FAQ or documentation entry as-is? Yes → Knowledge\n 3. If uncertain, prefer Discovery (conservative)\n\n### Knowledge vs Decision\n\nKnowledge: Norms, facts, concepts — objective, verifiable\n ✓ \"Feishu API global rate limit is 50 QPS\"\n ✓ \"Go goroutine initial stack size is 2KB\"\n\nDecision: Team/project choices, commitments — subjective, has an owner\n ✓ \"All services will use OpenTelemetry going forward\"\n ✓ \"We decided to replace MySQL with PostgreSQL\"\n\nRules:\n 1. Has an explicit decision-maker or team commitment? → Decision\n 2. Would this statement hold true for a different team/project? → Knowledge\n 3. If uncertain, look for verbs like \"decided\", \"chose\", \"switched to\" → Decision\n\n### Preference vs Discovery\n\nPreference (偏好): An explicit personal/team statement about how someone likes to work\n ✓ \"I prefer async communication over meetings\"\n ✓ \"We always write tests before implementation\" (framed as standing practice)\n ✓ \"I don't like being pinged after 6pm\"\n\nDiscovery-procedure (发现-流程): A how-to insight observed or recommended in the moment,\nnot framed as someone's standing preference\n ✓ \"Document architectural decisions before implementation\" (a recommendation, not \"I always do X\")\n\nRules:\n 1. Explicitly framed as \"I/we prefer/like/always do X\" with a clear subject? → Preference\n 2. A one-off recommendation or observed practice without standing-preference framing? → Discovery\n 3. If uncertain, prefer Discovery (conservative — Preference requires explicit personal framing)\n\n### Preference category\n\n- `communication`: sync/async style, channels, tone, responsiveness expectations\n- `tooling`: preferred editors, libraries, tools, tool-related workflows\n- `scheduling`: time-of-day habits, meeting patterns, availability\n- `workflow`: process/practice preferences not covered above (review style, docs habits)\n- `other`: doesn't fit the above\n\n### References\n\nA reference is a bookmark **with context** — a shared resource plus enough information\nfor an Agent to know when it would be useful to recall later.\n\nExtract a Reference when:\n ✓ A message shares a URL/doc/named resource AND gives enough context to fill in `summary`\n ✓ \"Check this out: https://example.com/jwt-guide — covers token rotation\" → Reference\n\nDo NOT extract a Reference when:\n ✗ A bare URL with no surrounding context (nothing to put in `summary`/`trigger`)\n ✗ The shared content IS the substance of the conversation — extract that as\n Knowledge/Decision/Discovery instead; References are for bookmarks, not the discussion itself\n\nReference field rules:\n - `url`: must appear verbatim in the source text — never fabricate or guess a URL\n - `summary`: ≤100 chars, what the resource covers\n - `trigger`: when recalling this would help (e.g., \"当排查 JWT 过期问题时\")\n\n### Knowledge source_type\n\n- `conversation`: Extracted from group/private chat messages\n- `document`: Extracted from cloud document content\n- `teaching`: Someone actively explaining/teaching (systematic explanation of principles, steps, processes)\n\n### Knowledge topic\n\n- Output kebab-case ASCII when possible: \"react-hooks\", \"feishu-api\"\n- For Chinese topics, translate to English: \"飞书API\" → \"feishu-api\"\n- The system normalizes non-conforming topics automatically\n\n### Knowledge confidence\n\n- Knowledge should rarely be `speculative`. The system may skip speculative Knowledge entries.\n- Prefer `direct` or `paraphrased` for factual statements.\n\n### Language Policy\n\n- Structural fields (slug, topic, type, status) → English ASCII, kebab-case\n- Natural language fields (name, summary, content, context, detail,\n reasoning, quote) → **SAME LANGUAGE as the source material**\n- If the conversation is in Chinese, write summaries in Chinese\n- If the conversation mixes languages, use the dominant language\n- quote field MUST be verbatim from the original text, never translated\n- slug for Chinese person names: use pinyin\n (e.g., \"李应龙\" → \"person/li-yinglong\")\n\n## Example\n\nSee `examples/agent-session.md` for a complete example with diverse signal types.\n\n## Your Task\n\nProcess the conversation block provided below and output ONLY valid JSON matching ExtractionResult schema.\n",
|
|
9
|
+
"significance.md": "You are evaluating whether a conversation block contains information worth extracting and preserving as personal memory.\n\n## Conversation Block\n\n{CONVERSATION_BLOCK}\n\n## Evaluation Criteria\n\nA conversation is **worth processing** if it contains ANY of:\n- Decisions made (technical, business, personal)\n- Action items or task assignments\n- Important knowledge shared (architecture, processes, domain expertise)\n- Relationship or organizational context\n- Plans, deadlines, or commitments\n- Problems identified and solutions discussed\n- Opinions or preferences that reveal character or values\n\nA conversation is **NOT worth processing** if it is purely:\n- Social pleasantries with no substance (\"好的\", \"收到\", \"谢谢\")\n- Forwarded content with no discussion\n- Automated notifications restated by a person\n- Logistics with no decision component (\"几点开会?\" → \"3点\")\n\n## Response Format\n\nRespond with a JSON object:\n```json\n{\n \"worth_processing\": true/false,\n \"confidence\": 0.0-1.0,\n \"reason\": \"brief explanation\",\n \"topics\": [\"topic1\", \"topic2\"]\n}\n```\n",
|
|
10
|
+
"system.md": "# System Prompt: Signal Extraction\n\nYou are a signal extraction system designed to identify and structure meaningful information from conversations and text. Always respond with valid JSON.\n\n## Your Role\n\nExtract structured signals from conversation blocks, including:\n- **Entities**: People, projects, organizations, tools, concepts\n- **Timeline entries**: Events, milestones, decisions with dates\n- **Links**: Relationships between entities\n- **Decisions**: Choices made with reasoning\n- **Tasks**: Action items and their status\n- **Discoveries**: Insights, patterns, procedures, preferences\n- **Knowledge**: Decontextualized, reusable facts or concepts that stand on their own without needing the original context\n\n## Core Principles\n\n1. **Accuracy over completeness**: Only extract what you can confidently identify\n2. **Context preservation**: Include sufficient context to understand the signal standalone\n3. **Confidence levels**: Mark confidence appropriately (direct/paraphrased/inferred/speculative)\n4. **Quote discipline**: Keep quotes under 300 characters, select the most relevant excerpt\n5. **Slug format**: Use `{type}/{kebab-case-name}` (e.g., `person/alice-smith`, `project/auth-system`)\n\n## Confidence Levels\n\n- **direct**: Explicitly stated in the text (\"Alice will work on the auth system\")\n- **paraphrased**: Clearly implied, just different words (\"Alice is taking the auth project\")\n- **inferred**: Reasonable deduction from context (\"Alice mentioned auth again, likely working on it\")\n- **speculative**: Possible but uncertain (\"Alice might be involved in auth based on previous context\")\n\n## Output Format\n\nAlways output valid JSON matching the ExtractionResultSchema. Include all required fields.\nEmpty arrays are valid (no signals found is acceptable).\n\n## Quality Standards\n\n- Entities must have clear, searchable slugs\n- Timeline entries must have valid ISO 8601 dates or partial dates (YYYY-MM, YYYY)\n- Links must connect existing entity slugs\n- Decisions must capture reasoning, not just conclusions\n- Tasks must have realistic status (open/in_progress/done/cancelled)\n- Discoveries must be actionable insights, not obvious facts\n\nYou will be provided with conversation context and expected to return structured JSON.\n"
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=embedded-assets.generated.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedded-assets.generated.js","sourceRoot":"","sources":["../src/embedded-assets.generated.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,gEAAgE;AAChE,wCAAwC;AAExC,MAAM,CAAC,MAAM,OAAO,GAAW,OAAO,CAAC;AAEvC,MAAM,CAAC,MAAM,UAAU,GAAW,ssJAAssJ,CAAC;AAEzuJ,MAAM,CAAC,MAAM,OAAO,GAA2B;IAC7C,2BAA2B,EAAE,ipTAAipT;IAC9qT,mBAAmB,EAAE,2sVAA2sV;IAChuV,iBAAiB,EAAE,8kCAA8kC;IACjmC,WAAW,EAAE,+vEAA+vE;CAC7wE,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Noise Filter — Two-level filtering for conversation blocks
|
|
3
|
+
*
|
|
4
|
+
* L1: Rule-based filtering (system notifications, emoji-only, red packets)
|
|
5
|
+
* L2: LLM-based significance judgment
|
|
6
|
+
*/
|
|
7
|
+
import type { ConversationBlock } from "../core/types.js";
|
|
8
|
+
import type { LLMProvider } from "./providers/types.js";
|
|
9
|
+
export type NoiseFilterVerdict = "pass" | "skip" | "escalate";
|
|
10
|
+
/**
|
|
11
|
+
* L1: Rule-based filtering
|
|
12
|
+
* Returns 'skip' if noise detected, 'escalate' if high-priority, null to continue to L2
|
|
13
|
+
*/
|
|
14
|
+
export declare function filterNoiseL1(block: ConversationBlock): NoiseFilterVerdict | null;
|
|
15
|
+
/**
|
|
16
|
+
* Main noise filter function
|
|
17
|
+
* Synchronous L1, optional async L2
|
|
18
|
+
*
|
|
19
|
+
* @param block - Conversation block to filter
|
|
20
|
+
* @param provider - Optional LLM provider for L2 (if not provided, L1 only)
|
|
21
|
+
* @returns Verdict: 'pass' | 'skip' | 'escalate'
|
|
22
|
+
*/
|
|
23
|
+
export declare function filterNoise(block: ConversationBlock, provider?: LLMProvider): NoiseFilterVerdict | Promise<NoiseFilterVerdict>;
|
|
24
|
+
/**
|
|
25
|
+
* Map a SignalScore decision to a NoiseFilterVerdict
|
|
26
|
+
*/
|
|
27
|
+
export declare function mapScoreDecision(score: {
|
|
28
|
+
decision: string;
|
|
29
|
+
}): NoiseFilterVerdict;
|
|
30
|
+
//# sourceMappingURL=noise-filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noise-filter.d.ts","sourceRoot":"","sources":["../../src/extractors/noise-filter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;AAmD9D;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,iBAAiB,GAAG,kBAAkB,GAAG,IAAI,CAoDjF;AA4ED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,iBAAiB,EACxB,QAAQ,CAAC,EAAE,WAAW,GACrB,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAgBlD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,kBAAkB,CAGhF"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Noise Filter — Two-level filtering for conversation blocks
|
|
3
|
+
*
|
|
4
|
+
* L1: Rule-based filtering (system notifications, emoji-only, red packets)
|
|
5
|
+
* L2: LLM-based significance judgment
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { PROMPTS } from "../embedded-assets.generated.js";
|
|
9
|
+
// Zod schema for runtime validation of LLM response
|
|
10
|
+
const SignificanceVerdictSchema = z.object({
|
|
11
|
+
worth_processing: z.boolean(),
|
|
12
|
+
confidence: z.number().min(0).max(1),
|
|
13
|
+
reason: z.string(),
|
|
14
|
+
topics: z.array(z.string()),
|
|
15
|
+
});
|
|
16
|
+
// L1: Rule-based keywords
|
|
17
|
+
const SYSTEM_KEYWORDS = [
|
|
18
|
+
"加入群聊",
|
|
19
|
+
"退出群聊",
|
|
20
|
+
"撤回了一条消息",
|
|
21
|
+
"修改群名为",
|
|
22
|
+
"邀请",
|
|
23
|
+
"移出了群聊",
|
|
24
|
+
"你已添加",
|
|
25
|
+
];
|
|
26
|
+
const RED_PACKET_KEYWORDS = ["[红包]", "[转账]", "收到红包", "收到转账"];
|
|
27
|
+
const DECISION_KEYWORDS = ["确定", "同意", "方案", "决定", "批准", "通过", "采用"];
|
|
28
|
+
const TASK_KEYWORDS = ["负责", "deadline", "截止", "完成时间", "交付", "你来", "你做", "分配给"];
|
|
29
|
+
const EMAIL_SKIP_PATTERNS = [
|
|
30
|
+
/auto[- ]?reply/i,
|
|
31
|
+
/out of office/i,
|
|
32
|
+
/自动回复/,
|
|
33
|
+
/会议取消/,
|
|
34
|
+
/会议已取消/,
|
|
35
|
+
];
|
|
36
|
+
/**
|
|
37
|
+
* Check if a message content is emoji-only
|
|
38
|
+
*/
|
|
39
|
+
function isEmojiOnly(content) {
|
|
40
|
+
// Remove all emoji and whitespace, if nothing left -> emoji-only
|
|
41
|
+
// Unicode emoji ranges: various blocks (variation selectors handled separately)
|
|
42
|
+
const withoutEmoji = content
|
|
43
|
+
.replace(/[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F700}-\u{1F77F}\u{1F780}-\u{1F7FF}\u{1F800}-\u{1F8FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FA6F}\u{1FA70}-\u{1FAFF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{1F1E6}-\u{1F1FF}]|️/gu, "")
|
|
44
|
+
.replace(/\s+/g, "");
|
|
45
|
+
return withoutEmoji.length === 0 && content.trim().length > 0;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* L1: Rule-based filtering
|
|
49
|
+
* Returns 'skip' if noise detected, 'escalate' if high-priority, null to continue to L2
|
|
50
|
+
*/
|
|
51
|
+
export function filterNoiseL1(block) {
|
|
52
|
+
const allContent = block.messages.map((m) => m.content).join(" ");
|
|
53
|
+
const channel = block.channel ?? "";
|
|
54
|
+
// Email channel rules
|
|
55
|
+
if (channel.startsWith("mail/")) {
|
|
56
|
+
const isAutoSkip = EMAIL_SKIP_PATTERNS.some((re) => re.test(allContent));
|
|
57
|
+
if (isAutoSkip)
|
|
58
|
+
return "skip";
|
|
59
|
+
const hasDecisionKeywords = DECISION_KEYWORDS.some((kw) => allContent.includes(kw));
|
|
60
|
+
if (hasDecisionKeywords)
|
|
61
|
+
return "escalate";
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
// Document and structured channels always pass through to L2
|
|
65
|
+
if (channel.startsWith("docs/") || channel.startsWith("calendar/") || channel === "tasks") {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
// System notifications
|
|
69
|
+
const isSystemNotification = SYSTEM_KEYWORDS.some((keyword) => allContent.includes(keyword));
|
|
70
|
+
if (isSystemNotification) {
|
|
71
|
+
return "skip";
|
|
72
|
+
}
|
|
73
|
+
// Red packets / transfers
|
|
74
|
+
const isRedPacket = RED_PACKET_KEYWORDS.some((keyword) => allContent.includes(keyword));
|
|
75
|
+
if (isRedPacket) {
|
|
76
|
+
return "skip";
|
|
77
|
+
}
|
|
78
|
+
// Emoji-only messages
|
|
79
|
+
const allEmojiOnly = block.messages.every((m) => isEmojiOnly(m.content));
|
|
80
|
+
if (allEmojiOnly) {
|
|
81
|
+
return "skip";
|
|
82
|
+
}
|
|
83
|
+
// Type promotion: Decision keywords
|
|
84
|
+
const hasDecisionKeywords = DECISION_KEYWORDS.some((keyword) => allContent.includes(keyword));
|
|
85
|
+
if (hasDecisionKeywords) {
|
|
86
|
+
return "escalate";
|
|
87
|
+
}
|
|
88
|
+
// Type promotion: Task keywords
|
|
89
|
+
const hasTaskKeywords = TASK_KEYWORDS.some((keyword) => allContent.includes(keyword));
|
|
90
|
+
if (hasTaskKeywords) {
|
|
91
|
+
return "escalate";
|
|
92
|
+
}
|
|
93
|
+
// No rule matched, pass to L2
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* L2: LLM-based significance judgment
|
|
98
|
+
*/
|
|
99
|
+
async function filterL2(block, provider) {
|
|
100
|
+
const promptTemplate = PROMPTS["significance.md"];
|
|
101
|
+
if (promptTemplate === undefined)
|
|
102
|
+
return "pass";
|
|
103
|
+
// Format conversation block for prompt
|
|
104
|
+
const blockSummary = {
|
|
105
|
+
platform: block.platform,
|
|
106
|
+
channel: block.channel,
|
|
107
|
+
participants: block.participants,
|
|
108
|
+
time_range: `${block.start_time} to ${block.end_time}`,
|
|
109
|
+
messages: block.messages.map((m) => ({
|
|
110
|
+
timestamp: m.timestamp,
|
|
111
|
+
contact: m.contact,
|
|
112
|
+
content: m.content,
|
|
113
|
+
})),
|
|
114
|
+
};
|
|
115
|
+
const prompt = promptTemplate.replace("{CONVERSATION_BLOCK}", JSON.stringify(blockSummary, null, 2));
|
|
116
|
+
// Call LLM
|
|
117
|
+
const response = await provider.chat([
|
|
118
|
+
{
|
|
119
|
+
role: "system",
|
|
120
|
+
content: "You are a significance judgment assistant. Always respond with valid JSON.",
|
|
121
|
+
},
|
|
122
|
+
{ role: "user", content: prompt },
|
|
123
|
+
], { responseFormat: "json" });
|
|
124
|
+
// Parse and validate response
|
|
125
|
+
let parsed;
|
|
126
|
+
try {
|
|
127
|
+
parsed = JSON.parse(response);
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
// Try extracting JSON from markdown wrapping
|
|
131
|
+
let s = response.trim();
|
|
132
|
+
s = s.replace(/^`{3,}(?:json|JSON)?\s*\n?/, "");
|
|
133
|
+
s = s.replace(/\n?\s*`{3,}\s*$/, "");
|
|
134
|
+
try {
|
|
135
|
+
parsed = JSON.parse(s.trim());
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return "pass";
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const result = SignificanceVerdictSchema.safeParse(parsed);
|
|
142
|
+
if (!result.success) {
|
|
143
|
+
return "pass";
|
|
144
|
+
}
|
|
145
|
+
const verdict = result.data;
|
|
146
|
+
// Apply filtering rules
|
|
147
|
+
if (!verdict.worth_processing) {
|
|
148
|
+
return "skip";
|
|
149
|
+
}
|
|
150
|
+
if (verdict.confidence < 0.3) {
|
|
151
|
+
return "skip";
|
|
152
|
+
}
|
|
153
|
+
return "pass";
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Main noise filter function
|
|
157
|
+
* Synchronous L1, optional async L2
|
|
158
|
+
*
|
|
159
|
+
* @param block - Conversation block to filter
|
|
160
|
+
* @param provider - Optional LLM provider for L2 (if not provided, L1 only)
|
|
161
|
+
* @returns Verdict: 'pass' | 'skip' | 'escalate'
|
|
162
|
+
*/
|
|
163
|
+
export function filterNoise(block, provider) {
|
|
164
|
+
// L1: Rule-based filtering
|
|
165
|
+
const l1Verdict = filterNoiseL1(block);
|
|
166
|
+
if (l1Verdict !== null) {
|
|
167
|
+
// L1 made a decision, return immediately
|
|
168
|
+
return l1Verdict;
|
|
169
|
+
}
|
|
170
|
+
// No provider -> can't do L2, default to pass
|
|
171
|
+
if (!provider) {
|
|
172
|
+
return "pass";
|
|
173
|
+
}
|
|
174
|
+
// L2: LLM-based judgment
|
|
175
|
+
return filterL2(block, provider);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Map a SignalScore decision to a NoiseFilterVerdict
|
|
179
|
+
*/
|
|
180
|
+
export function mapScoreDecision(score) {
|
|
181
|
+
if (score.decision === "drop")
|
|
182
|
+
return "skip";
|
|
183
|
+
return "pass";
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=noise-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noise-filter.js","sourceRoot":"","sources":["../../src/extractors/noise-filter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic-compatible LLM Provider
|
|
3
|
+
* Uses fetch to call Anthropic Messages API directly
|
|
4
|
+
*/
|
|
5
|
+
import type { LLMProvider } from "./types.js";
|
|
6
|
+
interface AnthropicConfig {
|
|
7
|
+
apiKey: string;
|
|
8
|
+
model: string;
|
|
9
|
+
baseUrl?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function createAnthropicProvider(config: AnthropicConfig): LLMProvider;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=anthropic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/extractors/providers/anthropic.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAwB,WAAW,EAAE,MAAM,YAAY,CAAC;AAEpE,UAAU,eAAe;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,eAAe,GAAG,WAAW,CA4E5E"}
|