@getrift/rift 0.1.0-beta.2 → 0.1.0-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -9
- package/dist/src/auth/keychain.d.ts +9 -0
- package/dist/src/auth/keychain.d.ts.map +1 -1
- package/dist/src/auth/keychain.js +37 -0
- package/dist/src/auth/keychain.js.map +1 -1
- package/dist/src/capture/auto-capture.d.ts +7 -0
- package/dist/src/capture/auto-capture.d.ts.map +1 -1
- package/dist/src/capture/auto-capture.js +82 -15
- package/dist/src/capture/auto-capture.js.map +1 -1
- package/dist/src/capture/auto-repair.d.ts +110 -0
- package/dist/src/capture/auto-repair.d.ts.map +1 -0
- package/dist/src/capture/auto-repair.js +269 -0
- package/dist/src/capture/auto-repair.js.map +1 -0
- package/dist/src/capture/codex-cli-triage-provider.d.ts.map +1 -1
- package/dist/src/capture/codex-cli-triage-provider.js +4 -3
- package/dist/src/capture/codex-cli-triage-provider.js.map +1 -1
- package/dist/src/capture/observability.d.ts +42 -0
- package/dist/src/capture/observability.d.ts.map +1 -1
- package/dist/src/capture/observability.js +45 -4
- package/dist/src/capture/observability.js.map +1 -1
- package/dist/src/capture/recover-quarantine.d.ts +260 -0
- package/dist/src/capture/recover-quarantine.d.ts.map +1 -0
- package/dist/src/capture/recover-quarantine.js +522 -0
- package/dist/src/capture/recover-quarantine.js.map +1 -0
- package/dist/src/cli/commands/backfill.d.ts.map +1 -1
- package/dist/src/cli/commands/backfill.js +5 -2
- package/dist/src/cli/commands/backfill.js.map +1 -1
- package/dist/src/cli/commands/capture-recover.d.ts +40 -0
- package/dist/src/cli/commands/capture-recover.d.ts.map +1 -0
- package/dist/src/cli/commands/capture-recover.js +184 -0
- package/dist/src/cli/commands/capture-recover.js.map +1 -0
- package/dist/src/cli/commands/capture.d.ts.map +1 -1
- package/dist/src/cli/commands/capture.js +96 -5
- package/dist/src/cli/commands/capture.js.map +1 -1
- package/dist/src/cli/commands/doctor.d.ts +6 -0
- package/dist/src/cli/commands/doctor.d.ts.map +1 -0
- package/dist/src/cli/commands/doctor.js +242 -0
- package/dist/src/cli/commands/doctor.js.map +1 -0
- package/dist/src/cli/commands/feedback.d.ts +12 -0
- package/dist/src/cli/commands/feedback.d.ts.map +1 -1
- package/dist/src/cli/commands/feedback.js +93 -4
- package/dist/src/cli/commands/feedback.js.map +1 -1
- package/dist/src/cli/commands/mcp-install.js +5 -2
- package/dist/src/cli/commands/mcp-install.js.map +1 -1
- package/dist/src/cli/commands/menubar.d.ts +30 -0
- package/dist/src/cli/commands/menubar.d.ts.map +1 -0
- package/dist/src/cli/commands/menubar.js +180 -0
- package/dist/src/cli/commands/menubar.js.map +1 -0
- package/dist/src/cli/commands/onboard.d.ts +129 -0
- package/dist/src/cli/commands/onboard.d.ts.map +1 -1
- package/dist/src/cli/commands/onboard.js +752 -171
- package/dist/src/cli/commands/onboard.js.map +1 -1
- package/dist/src/cli/commands/rebuild.d.ts.map +1 -1
- package/dist/src/cli/commands/rebuild.js +6 -3
- package/dist/src/cli/commands/rebuild.js.map +1 -1
- package/dist/src/cli/commands/reconcile.d.ts.map +1 -1
- package/dist/src/cli/commands/reconcile.js +12 -0
- package/dist/src/cli/commands/reconcile.js.map +1 -1
- package/dist/src/cli/commands/review.d.ts.map +1 -1
- package/dist/src/cli/commands/review.js +22 -7
- package/dist/src/cli/commands/review.js.map +1 -1
- package/dist/src/cli/commands/search.d.ts +2 -0
- package/dist/src/cli/commands/search.d.ts.map +1 -1
- package/dist/src/cli/commands/search.js +34 -4
- package/dist/src/cli/commands/search.js.map +1 -1
- package/dist/src/cli/commands/status.d.ts +9 -7
- package/dist/src/cli/commands/status.d.ts.map +1 -1
- package/dist/src/cli/commands/status.js +113 -12
- package/dist/src/cli/commands/status.js.map +1 -1
- package/dist/src/cli/commands/token-issue.d.ts.map +1 -1
- package/dist/src/cli/commands/token-issue.js +9 -1
- package/dist/src/cli/commands/token-issue.js.map +1 -1
- package/dist/src/cli/commands/triage.d.ts.map +1 -1
- package/dist/src/cli/commands/triage.js +7 -5
- package/dist/src/cli/commands/triage.js.map +1 -1
- package/dist/src/cli/commands/update.d.ts +80 -0
- package/dist/src/cli/commands/update.d.ts.map +1 -0
- package/dist/src/cli/commands/update.js +378 -0
- package/dist/src/cli/commands/update.js.map +1 -0
- package/dist/src/cli/default-config-path.d.ts +15 -0
- package/dist/src/cli/default-config-path.d.ts.map +1 -0
- package/dist/src/cli/default-config-path.js +27 -0
- package/dist/src/cli/default-config-path.js.map +1 -0
- package/dist/src/cli/feedback/feedback-config.d.ts +46 -0
- package/dist/src/cli/feedback/feedback-config.d.ts.map +1 -1
- package/dist/src/cli/feedback/feedback-config.js +130 -4
- package/dist/src/cli/feedback/feedback-config.js.map +1 -1
- package/dist/src/cli/feedback/feedback-history.d.ts +7 -0
- package/dist/src/cli/feedback/feedback-history.d.ts.map +1 -1
- package/dist/src/cli/feedback/feedback-history.js +39 -9
- package/dist/src/cli/feedback/feedback-history.js.map +1 -1
- package/dist/src/cli/feedback/feedback-payload.d.ts +22 -1
- package/dist/src/cli/feedback/feedback-payload.d.ts.map +1 -1
- package/dist/src/cli/feedback/feedback-payload.js.map +1 -1
- package/dist/src/cli/feedback/feedback-relay.d.ts +2 -2
- package/dist/src/cli/feedback/feedback-relay.d.ts.map +1 -1
- package/dist/src/cli/feedback/feedback-relay.js.map +1 -1
- package/dist/src/cli/feedback/invite.d.ts +17 -0
- package/dist/src/cli/feedback/invite.d.ts.map +1 -0
- package/dist/src/cli/feedback/invite.js +67 -0
- package/dist/src/cli/feedback/invite.js.map +1 -0
- package/dist/src/cli/feedback/relay-secret-store.d.ts +32 -0
- package/dist/src/cli/feedback/relay-secret-store.d.ts.map +1 -0
- package/dist/src/cli/feedback/relay-secret-store.js +137 -0
- package/dist/src/cli/feedback/relay-secret-store.js.map +1 -0
- package/dist/src/cli/http-client.d.ts +93 -1
- package/dist/src/cli/http-client.d.ts.map +1 -1
- package/dist/src/cli/http-client.js +254 -6
- package/dist/src/cli/http-client.js.map +1 -1
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +29 -6
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/cli/postinstall-menubar.d.ts +22 -0
- package/dist/src/cli/postinstall-menubar.d.ts.map +1 -0
- package/dist/src/cli/postinstall-menubar.js +39 -0
- package/dist/src/cli/postinstall-menubar.js.map +1 -0
- package/dist/src/cli/status/friend-header.d.ts +8 -1
- package/dist/src/cli/status/friend-header.d.ts.map +1 -1
- package/dist/src/cli/status/friend-header.js +334 -26
- package/dist/src/cli/status/friend-header.js.map +1 -1
- package/dist/src/cli/ui.d.ts +47 -0
- package/dist/src/cli/ui.d.ts.map +1 -0
- package/dist/src/cli/ui.js +166 -0
- package/dist/src/cli/ui.js.map +1 -0
- package/dist/src/config/schema.d.ts +79 -0
- package/dist/src/config/schema.d.ts.map +1 -1
- package/dist/src/config/schema.js +44 -0
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/diagnostics/codex-preflight.d.ts +33 -0
- package/dist/src/diagnostics/codex-preflight.d.ts.map +1 -0
- package/dist/src/diagnostics/codex-preflight.js +75 -0
- package/dist/src/diagnostics/codex-preflight.js.map +1 -0
- package/dist/src/diagnostics/doctor.d.ts +106 -0
- package/dist/src/diagnostics/doctor.d.ts.map +1 -0
- package/dist/src/diagnostics/doctor.js +334 -0
- package/dist/src/diagnostics/doctor.js.map +1 -0
- package/dist/src/diagnostics/notify.d.ts +90 -0
- package/dist/src/diagnostics/notify.d.ts.map +1 -0
- package/dist/src/diagnostics/notify.js +177 -0
- package/dist/src/diagnostics/notify.js.map +1 -0
- package/dist/src/diagnostics/repair-prompt.d.ts +49 -0
- package/dist/src/diagnostics/repair-prompt.d.ts.map +1 -0
- package/dist/src/diagnostics/repair-prompt.js +223 -0
- package/dist/src/diagnostics/repair-prompt.js.map +1 -0
- package/dist/src/ingestion/inbox-core/conversation-fingerprint.d.ts +2 -0
- package/dist/src/ingestion/inbox-core/conversation-fingerprint.d.ts.map +1 -0
- package/dist/src/ingestion/inbox-core/conversation-fingerprint.js +27 -0
- package/dist/src/ingestion/inbox-core/conversation-fingerprint.js.map +1 -0
- package/dist/src/ingestion/inbox-core/conversation-key.d.ts +2 -0
- package/dist/src/ingestion/inbox-core/conversation-key.d.ts.map +1 -0
- package/dist/src/ingestion/inbox-core/conversation-key.js +31 -0
- package/dist/src/ingestion/inbox-core/conversation-key.js.map +1 -0
- package/dist/src/ingestion/inbox-core/extensions.d.ts +3 -0
- package/dist/src/ingestion/inbox-core/extensions.d.ts.map +1 -0
- package/dist/src/ingestion/inbox-core/extensions.js +16 -0
- package/dist/src/ingestion/inbox-core/extensions.js.map +1 -0
- package/dist/src/ingestion/inbox-core/idempotency.d.ts +2 -0
- package/dist/src/ingestion/inbox-core/idempotency.d.ts.map +1 -0
- package/dist/src/ingestion/inbox-core/idempotency.js +22 -0
- package/dist/src/ingestion/inbox-core/idempotency.js.map +1 -0
- package/dist/src/ingestion/inbox-core/index.d.ts +20 -0
- package/dist/src/ingestion/inbox-core/index.d.ts.map +1 -0
- package/dist/src/ingestion/inbox-core/index.js +20 -0
- package/dist/src/ingestion/inbox-core/index.js.map +1 -0
- package/dist/src/ingestion/inbox-core/source-detection.d.ts +2 -0
- package/dist/src/ingestion/inbox-core/source-detection.d.ts.map +1 -0
- package/dist/src/ingestion/inbox-core/source-detection.js +23 -0
- package/dist/src/ingestion/inbox-core/source-detection.js.map +1 -0
- package/dist/src/ingestion/inbox-core/source-sniffer.d.ts +11 -0
- package/dist/src/ingestion/inbox-core/source-sniffer.d.ts.map +1 -0
- package/dist/src/ingestion/inbox-core/source-sniffer.js +69 -0
- package/dist/src/ingestion/inbox-core/source-sniffer.js.map +1 -0
- package/dist/src/ingestion/inbox-core/zip-sniffer.d.ts +70 -0
- package/dist/src/ingestion/inbox-core/zip-sniffer.d.ts.map +1 -0
- package/dist/src/ingestion/inbox-core/zip-sniffer.js +161 -0
- package/dist/src/ingestion/inbox-core/zip-sniffer.js.map +1 -0
- package/dist/src/ingestion/inbox-watcher.d.ts.map +1 -1
- package/dist/src/ingestion/inbox-watcher.js +34 -50
- package/dist/src/ingestion/inbox-watcher.js.map +1 -1
- package/dist/src/ingestion/indexer.d.ts +7 -0
- package/dist/src/ingestion/indexer.d.ts.map +1 -1
- package/dist/src/ingestion/indexer.js +36 -2
- package/dist/src/ingestion/indexer.js.map +1 -1
- package/dist/src/ingestion/metadata-extraction.d.ts +8 -5
- package/dist/src/ingestion/metadata-extraction.d.ts.map +1 -1
- package/dist/src/ingestion/metadata-extraction.js +24 -5
- package/dist/src/ingestion/metadata-extraction.js.map +1 -1
- package/dist/src/ingestion/skip-quarantine.d.ts +10 -0
- package/dist/src/ingestion/skip-quarantine.d.ts.map +1 -0
- package/dist/src/ingestion/skip-quarantine.js +35 -0
- package/dist/src/ingestion/skip-quarantine.js.map +1 -0
- package/dist/src/jobs/handlers/compact.d.ts.map +1 -1
- package/dist/src/jobs/handlers/compact.js +30 -4
- package/dist/src/jobs/handlers/compact.js.map +1 -1
- package/dist/src/jobs/handlers/dedupe-conversations.d.ts +134 -0
- package/dist/src/jobs/handlers/dedupe-conversations.d.ts.map +1 -0
- package/dist/src/jobs/handlers/dedupe-conversations.js +371 -0
- package/dist/src/jobs/handlers/dedupe-conversations.js.map +1 -0
- package/dist/src/jobs/handlers/ingest.d.ts.map +1 -1
- package/dist/src/jobs/handlers/ingest.js +295 -41
- package/dist/src/jobs/handlers/ingest.js.map +1 -1
- package/dist/src/jobs/handlers/reconcile.d.ts +28 -0
- package/dist/src/jobs/handlers/reconcile.d.ts.map +1 -1
- package/dist/src/jobs/handlers/reconcile.js +145 -19
- package/dist/src/jobs/handlers/reconcile.js.map +1 -1
- package/dist/src/jobs/handlers/reindex.d.ts.map +1 -1
- package/dist/src/jobs/handlers/reindex.js +13 -2
- package/dist/src/jobs/handlers/reindex.js.map +1 -1
- package/dist/src/jobs/handlers/save.d.ts.map +1 -1
- package/dist/src/jobs/handlers/save.js +57 -3
- package/dist/src/jobs/handlers/save.js.map +1 -1
- package/dist/src/jobs/queue.d.ts +51 -1
- package/dist/src/jobs/queue.d.ts.map +1 -1
- package/dist/src/jobs/queue.js +466 -26
- package/dist/src/jobs/queue.js.map +1 -1
- package/dist/src/jobs/worker-entry.d.ts.map +1 -1
- package/dist/src/jobs/worker-entry.js +35 -7
- package/dist/src/jobs/worker-entry.js.map +1 -1
- package/dist/src/jobs/worker-process.d.ts +11 -0
- package/dist/src/jobs/worker-process.d.ts.map +1 -1
- package/dist/src/jobs/worker-process.js +37 -4
- package/dist/src/jobs/worker-process.js.map +1 -1
- package/dist/src/main.js +199 -46
- package/dist/src/main.js.map +1 -1
- package/dist/src/mcp/errors.d.ts.map +1 -1
- package/dist/src/mcp/errors.js +20 -1
- package/dist/src/mcp/errors.js.map +1 -1
- package/dist/src/mcp/server.d.ts.map +1 -1
- package/dist/src/mcp/server.js +43 -3
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/mcp/tools/context-pack.d.ts.map +1 -1
- package/dist/src/mcp/tools/context-pack.js +164 -23
- package/dist/src/mcp/tools/context-pack.js.map +1 -1
- package/dist/src/mcp/tools/search.d.ts +6 -2
- package/dist/src/mcp/tools/search.d.ts.map +1 -1
- package/dist/src/mcp/tools/search.js +35 -4
- package/dist/src/mcp/tools/search.js.map +1 -1
- package/dist/src/observability/embedding-events.d.ts +52 -0
- package/dist/src/observability/embedding-events.d.ts.map +1 -0
- package/dist/src/observability/embedding-events.js +149 -0
- package/dist/src/observability/embedding-events.js.map +1 -0
- package/dist/src/observability/index-events.d.ts +70 -0
- package/dist/src/observability/index-events.d.ts.map +1 -0
- package/dist/src/observability/index-events.js +148 -0
- package/dist/src/observability/index-events.js.map +1 -0
- package/dist/src/observability/onboarding-metric.d.ts +131 -0
- package/dist/src/observability/onboarding-metric.d.ts.map +1 -0
- package/dist/src/observability/onboarding-metric.js +351 -0
- package/dist/src/observability/onboarding-metric.js.map +1 -0
- package/dist/src/observability/tool-usage-stats.d.ts +77 -4
- package/dist/src/observability/tool-usage-stats.d.ts.map +1 -1
- package/dist/src/observability/tool-usage-stats.js +112 -32
- package/dist/src/observability/tool-usage-stats.js.map +1 -1
- package/dist/src/observability/tool-usage.d.ts +100 -7
- package/dist/src/observability/tool-usage.d.ts.map +1 -1
- package/dist/src/observability/tool-usage.js +196 -33
- package/dist/src/observability/tool-usage.js.map +1 -1
- package/dist/src/observability/version-check.d.ts +71 -0
- package/dist/src/observability/version-check.d.ts.map +1 -0
- package/dist/src/observability/version-check.js +198 -0
- package/dist/src/observability/version-check.js.map +1 -0
- package/dist/src/providers/basic-metadata-extraction.d.ts +60 -0
- package/dist/src/providers/basic-metadata-extraction.d.ts.map +1 -0
- package/dist/src/providers/basic-metadata-extraction.js +114 -0
- package/dist/src/providers/basic-metadata-extraction.js.map +1 -0
- package/dist/src/providers/codex-cli-metadata-extraction.d.ts +1 -0
- package/dist/src/providers/codex-cli-metadata-extraction.d.ts.map +1 -1
- package/dist/src/providers/codex-cli-metadata-extraction.js +6 -2
- package/dist/src/providers/codex-cli-metadata-extraction.js.map +1 -1
- package/dist/src/providers/codex-cli-model.d.ts +61 -0
- package/dist/src/providers/codex-cli-model.d.ts.map +1 -0
- package/dist/src/providers/codex-cli-model.js +194 -0
- package/dist/src/providers/codex-cli-model.js.map +1 -0
- package/dist/src/providers/codex-cli-runner.d.ts +39 -0
- package/dist/src/providers/codex-cli-runner.d.ts.map +1 -1
- package/dist/src/providers/codex-cli-runner.js +234 -48
- package/dist/src/providers/codex-cli-runner.js.map +1 -1
- package/dist/src/providers/conversation-generation.d.ts.map +1 -1
- package/dist/src/providers/conversation-generation.js +43 -6
- package/dist/src/providers/conversation-generation.js.map +1 -1
- package/dist/src/providers/ollama-embed.d.ts +2 -1
- package/dist/src/providers/ollama-embed.d.ts.map +1 -1
- package/dist/src/providers/ollama-embed.js +1 -0
- package/dist/src/providers/ollama-embed.js.map +1 -1
- package/dist/src/providers/openai-metadata-extraction.d.ts +3 -3
- package/dist/src/providers/openai-metadata-extraction.d.ts.map +1 -1
- package/dist/src/providers/openai-metadata-extraction.js +18 -3
- package/dist/src/providers/openai-metadata-extraction.js.map +1 -1
- package/dist/src/providers/placeholder-embed.d.ts +56 -0
- package/dist/src/providers/placeholder-embed.d.ts.map +1 -0
- package/dist/src/providers/placeholder-embed.js +64 -0
- package/dist/src/providers/placeholder-embed.js.map +1 -0
- package/dist/src/providers/stub.d.ts +2 -0
- package/dist/src/providers/stub.d.ts.map +1 -1
- package/dist/src/providers/stub.js +2 -0
- package/dist/src/providers/stub.js.map +1 -1
- package/dist/src/providers/types.d.ts +11 -0
- package/dist/src/providers/types.d.ts.map +1 -1
- package/dist/src/providers/voyage.d.ts +2 -1
- package/dist/src/providers/voyage.d.ts.map +1 -1
- package/dist/src/providers/voyage.js +1 -0
- package/dist/src/providers/voyage.js.map +1 -1
- package/dist/src/retrieval/compact.d.ts +116 -2
- package/dist/src/retrieval/compact.d.ts.map +1 -1
- package/dist/src/retrieval/compact.js +158 -5
- package/dist/src/retrieval/compact.js.map +1 -1
- package/dist/src/retrieval/context-pack.d.ts +114 -0
- package/dist/src/retrieval/context-pack.d.ts.map +1 -1
- package/dist/src/retrieval/context-pack.js +292 -8
- package/dist/src/retrieval/context-pack.js.map +1 -1
- package/dist/src/retrieval/current-truth.d.ts +360 -0
- package/dist/src/retrieval/current-truth.d.ts.map +1 -0
- package/dist/src/retrieval/current-truth.js +766 -0
- package/dist/src/retrieval/current-truth.js.map +1 -0
- package/dist/src/retrieval/git-state.d.ts +53 -0
- package/dist/src/retrieval/git-state.d.ts.map +1 -0
- package/dist/src/retrieval/git-state.js +174 -0
- package/dist/src/retrieval/git-state.js.map +1 -0
- package/dist/src/retrieval/lexical.d.ts.map +1 -1
- package/dist/src/retrieval/lexical.js +19 -3
- package/dist/src/retrieval/lexical.js.map +1 -1
- package/dist/src/retrieval/locator-boost.d.ts +37 -0
- package/dist/src/retrieval/locator-boost.d.ts.map +1 -0
- package/dist/src/retrieval/locator-boost.js +129 -0
- package/dist/src/retrieval/locator-boost.js.map +1 -0
- package/dist/src/retrieval/report-demotion.d.ts +46 -0
- package/dist/src/retrieval/report-demotion.d.ts.map +1 -0
- package/dist/src/retrieval/report-demotion.js +169 -0
- package/dist/src/retrieval/report-demotion.js.map +1 -0
- package/dist/src/retrieval/vector.d.ts.map +1 -1
- package/dist/src/retrieval/vector.js +11 -2
- package/dist/src/retrieval/vector.js.map +1 -1
- package/dist/src/server/app.d.ts.map +1 -1
- package/dist/src/server/app.js +92 -11
- package/dist/src/server/app.js.map +1 -1
- package/dist/src/server/routes/compact.d.ts.map +1 -1
- package/dist/src/server/routes/compact.js +4 -1
- package/dist/src/server/routes/compact.js.map +1 -1
- package/dist/src/server/routes/context.d.ts +1 -1
- package/dist/src/server/routes/context.d.ts.map +1 -1
- package/dist/src/server/routes/context.js +2 -1
- package/dist/src/server/routes/context.js.map +1 -1
- package/dist/src/server/routes/conversations-search.d.ts.map +1 -1
- package/dist/src/server/routes/conversations-search.js +28 -3
- package/dist/src/server/routes/conversations-search.js.map +1 -1
- package/dist/src/server/routes/enqueue.d.ts +11 -0
- package/dist/src/server/routes/enqueue.d.ts.map +1 -0
- package/dist/src/server/routes/enqueue.js +17 -0
- package/dist/src/server/routes/enqueue.js.map +1 -0
- package/dist/src/server/routes/friend-status.d.ts +339 -3
- package/dist/src/server/routes/friend-status.d.ts.map +1 -1
- package/dist/src/server/routes/friend-status.js +447 -13
- package/dist/src/server/routes/friend-status.js.map +1 -1
- package/dist/src/server/routes/ingest.d.ts.map +1 -1
- package/dist/src/server/routes/ingest.js +5 -2
- package/dist/src/server/routes/ingest.js.map +1 -1
- package/dist/src/server/routes/mcp-usage.d.ts +5 -4
- package/dist/src/server/routes/mcp-usage.d.ts.map +1 -1
- package/dist/src/server/routes/mcp-usage.js.map +1 -1
- package/dist/src/server/routes/reconcile.d.ts.map +1 -1
- package/dist/src/server/routes/reconcile.js +20 -1
- package/dist/src/server/routes/reconcile.js.map +1 -1
- package/dist/src/server/routes/reindex.d.ts.map +1 -1
- package/dist/src/server/routes/reindex.js +4 -1
- package/dist/src/server/routes/reindex.js.map +1 -1
- package/dist/src/server/routes/save.d.ts.map +1 -1
- package/dist/src/server/routes/save.js +4 -1
- package/dist/src/server/routes/save.js.map +1 -1
- package/dist/src/server/routes/search.d.ts +1 -1
- package/dist/src/server/routes/search.d.ts.map +1 -1
- package/dist/src/server/routes/search.js +253 -29
- package/dist/src/server/routes/search.js.map +1 -1
- package/dist/src/server/routes/triage.d.ts.map +1 -1
- package/dist/src/server/routes/triage.js +4 -1
- package/dist/src/server/routes/triage.js.map +1 -1
- package/dist/src/storage/rebuild.d.ts +35 -1
- package/dist/src/storage/rebuild.d.ts.map +1 -1
- package/dist/src/storage/rebuild.js +288 -64
- package/dist/src/storage/rebuild.js.map +1 -1
- package/dist/src/storage/tables.d.ts +29 -0
- package/dist/src/storage/tables.d.ts.map +1 -1
- package/dist/src/storage/tables.js +32 -1
- package/dist/src/storage/tables.js.map +1 -1
- package/operator/swiftbar/render-menu.py +524 -0
- package/operator/swiftbar/rift.10s.sh +176 -0
- package/package.json +9 -3
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Index-events lane — append-only JSONL.
|
|
3
|
+
*
|
|
4
|
+
* One row per write boundary against LanceDB (`table.add(...)`). This
|
|
5
|
+
* complements `embedding-events.jsonl`: the embedding lane proves the
|
|
6
|
+
* vector was produced, this lane proves the row was actually persisted
|
|
7
|
+
* to LanceDB and is searchable. Without it, `/status/friend` cannot
|
|
8
|
+
* distinguish "embedded but not indexed yet" from "fully searchable".
|
|
9
|
+
*
|
|
10
|
+
* Provider-agnostic and table-agnostic: `table` and `pipeline` are
|
|
11
|
+
* payload fields. Reads / search queries are deliberately NOT wrapped —
|
|
12
|
+
* they're not write events and would muddy `index.last_update_at`.
|
|
13
|
+
*
|
|
14
|
+
* Failure mode: writes are best-effort and never throw — observability
|
|
15
|
+
* must not break indexing. The reader is tolerant of bad lines so one
|
|
16
|
+
* corrupt row doesn't blank the status dashboard.
|
|
17
|
+
*/
|
|
18
|
+
import fs from "node:fs";
|
|
19
|
+
import path from "node:path";
|
|
20
|
+
const MAX_ERROR_MESSAGE_LEN = 512;
|
|
21
|
+
export function indexEventsFilePath(dataDir) {
|
|
22
|
+
return path.join(dataDir, "observability", "index-events.jsonl");
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Append a single event to the lane. Never throws — telemetry must not
|
|
26
|
+
* break indexing. On filesystem error, writes a single stderr line so
|
|
27
|
+
* the failure is at least visible to operators tailing logs.
|
|
28
|
+
*/
|
|
29
|
+
export function appendIndexEvent(dataDir, event) {
|
|
30
|
+
const filePath = indexEventsFilePath(dataDir);
|
|
31
|
+
try {
|
|
32
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
33
|
+
fs.appendFileSync(filePath, JSON.stringify(event) + "\n");
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
process.stderr.write(`[index-events] write failed: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Run a LanceDB write and record one event. Re-throws errors so the
|
|
41
|
+
* caller's existing failure-handling path is unchanged; logging is a
|
|
42
|
+
* pure side effect.
|
|
43
|
+
*
|
|
44
|
+
* Use this only at write boundaries (`table.add(...)`). Do NOT use it
|
|
45
|
+
* for reads, queries, or deletes — keeping the lane write-only is what
|
|
46
|
+
* makes `last_update_at` meaningful.
|
|
47
|
+
*/
|
|
48
|
+
export async function recordIndexWrite(dataDir, ctx, fn) {
|
|
49
|
+
const start = Date.now();
|
|
50
|
+
const phase = ctx.phase ?? "live";
|
|
51
|
+
try {
|
|
52
|
+
const result = await fn();
|
|
53
|
+
appendIndexEvent(dataDir, {
|
|
54
|
+
ts: new Date().toISOString(),
|
|
55
|
+
table: ctx.table,
|
|
56
|
+
pipeline: ctx.pipeline,
|
|
57
|
+
operation: ctx.operation,
|
|
58
|
+
outcome: "success",
|
|
59
|
+
row_count: ctx.row_count,
|
|
60
|
+
ms: Date.now() - start,
|
|
61
|
+
phase,
|
|
62
|
+
});
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
67
|
+
appendIndexEvent(dataDir, {
|
|
68
|
+
ts: new Date().toISOString(),
|
|
69
|
+
table: ctx.table,
|
|
70
|
+
pipeline: ctx.pipeline,
|
|
71
|
+
operation: ctx.operation,
|
|
72
|
+
outcome: "error",
|
|
73
|
+
row_count: ctx.row_count,
|
|
74
|
+
ms: Date.now() - start,
|
|
75
|
+
phase,
|
|
76
|
+
error_class: classifyError(err),
|
|
77
|
+
error_message: message.slice(0, MAX_ERROR_MESSAGE_LEN),
|
|
78
|
+
});
|
|
79
|
+
throw err;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Best-effort classification for the `error_class` field. LanceDB
|
|
84
|
+
* surfaces schema mismatches, IO errors, and lock contention with
|
|
85
|
+
* different shapes — pick a coarse class so dashboards can group.
|
|
86
|
+
*/
|
|
87
|
+
function classifyError(err) {
|
|
88
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
89
|
+
const lower = msg.toLowerCase();
|
|
90
|
+
if (lower.includes("schema"))
|
|
91
|
+
return "schema_mismatch";
|
|
92
|
+
if (lower.includes("lock") || lower.includes("conflict"))
|
|
93
|
+
return "lock_conflict";
|
|
94
|
+
if (lower.includes("enoent") || lower.includes("eacces") || lower.includes("eio")) {
|
|
95
|
+
return "io";
|
|
96
|
+
}
|
|
97
|
+
if (err instanceof TypeError)
|
|
98
|
+
return "type";
|
|
99
|
+
return "unknown";
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Tolerant reader. One bad JSON line is skipped; the rest are returned.
|
|
103
|
+
* Returns [] if the file is missing.
|
|
104
|
+
*/
|
|
105
|
+
export function readIndexEvents(dataDir) {
|
|
106
|
+
let raw;
|
|
107
|
+
try {
|
|
108
|
+
raw = fs.readFileSync(indexEventsFilePath(dataDir), "utf-8");
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
const out = [];
|
|
114
|
+
for (const line of raw.split("\n")) {
|
|
115
|
+
if (!line)
|
|
116
|
+
continue;
|
|
117
|
+
let parsed;
|
|
118
|
+
try {
|
|
119
|
+
parsed = JSON.parse(line);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (!isIndexEvent(parsed))
|
|
125
|
+
continue;
|
|
126
|
+
out.push(parsed);
|
|
127
|
+
}
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
130
|
+
function isIndexEvent(value) {
|
|
131
|
+
if (value === null || typeof value !== "object")
|
|
132
|
+
return false;
|
|
133
|
+
const v = value;
|
|
134
|
+
if (!(typeof v["ts"] === "string" &&
|
|
135
|
+
typeof v["table"] === "string" &&
|
|
136
|
+
typeof v["pipeline"] === "string" &&
|
|
137
|
+
typeof v["operation"] === "string" &&
|
|
138
|
+
(v["outcome"] === "success" || v["outcome"] === "error") &&
|
|
139
|
+
typeof v["row_count"] === "number" &&
|
|
140
|
+
typeof v["ms"] === "number")) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
const phase = v["phase"];
|
|
144
|
+
if (phase !== undefined && phase !== "live" && phase !== "shadow")
|
|
145
|
+
return false;
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=index-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-events.js","sourceRoot":"","sources":["../../../src/observability/index-events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/** MCP retrieval tools that can satisfy the end-event condition. */
|
|
2
|
+
export declare const RETRIEVAL_TOOLS: Set<string>;
|
|
3
|
+
export type RetrievalTool = "rift_search" | "rift_conversations_search" | "rift_context_pack";
|
|
4
|
+
export interface OnboardingMetric {
|
|
5
|
+
install_id: string;
|
|
6
|
+
useful_state_reached_at: string | null;
|
|
7
|
+
first_useful_recall_at: string | null;
|
|
8
|
+
first_useful_recall_tool: RetrievalTool | null;
|
|
9
|
+
}
|
|
10
|
+
export type OnboardingState = {
|
|
11
|
+
state: "hidden";
|
|
12
|
+
} | {
|
|
13
|
+
state: "pending";
|
|
14
|
+
useful_state_reached_at: string;
|
|
15
|
+
} | {
|
|
16
|
+
state: "completed";
|
|
17
|
+
useful_state_reached_at: string;
|
|
18
|
+
first_useful_recall_at: string;
|
|
19
|
+
first_useful_recall_tool: RetrievalTool;
|
|
20
|
+
duration_seconds: number;
|
|
21
|
+
};
|
|
22
|
+
export declare function onboardingMetricPath(dataDir: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Read-or-bootstrap. A missing/corrupt file is replaced with a fresh
|
|
25
|
+
* record whose `install_id` is a new UUID. Unknown fields in an existing
|
|
26
|
+
* file are dropped on the next write (sanitizer drops everything outside
|
|
27
|
+
* the fixed key set).
|
|
28
|
+
*/
|
|
29
|
+
export declare function readOnboardingMetric(dataDir: string): OnboardingMetric;
|
|
30
|
+
export interface ReadinessSignals {
|
|
31
|
+
daemonHealthy: boolean;
|
|
32
|
+
voyageKeyValid: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* True when the install is in the intentional no-key local mode (no Voyage
|
|
35
|
+
* key present), so keyword/lexical search is the active retrieval surface.
|
|
36
|
+
* A no-key install that has imported content IS useful — it can search its
|
|
37
|
+
* archive — even though semantic search is off. Distinct from
|
|
38
|
+
* `voyageKeyValid`: a key that is PRESENT but never round-tripped is a broken
|
|
39
|
+
* setup, not intentional local mode, so it sets neither flag.
|
|
40
|
+
*/
|
|
41
|
+
lexicalModeAvailable: boolean;
|
|
42
|
+
indexedCount: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Useful state = the product delivered first value: the daemon is healthy,
|
|
46
|
+
* there is indexed content to retrieve, AND at least one working retrieval
|
|
47
|
+
* surface — semantic (valid Voyage embeddings) OR keyword (intentional no-key
|
|
48
|
+
* lexical mode). Gating on Voyage alone would make the shipped no-key path
|
|
49
|
+
* never count as activated, skewing beta telemetry.
|
|
50
|
+
*/
|
|
51
|
+
export declare function isUsefulStateReached(signals: ReadinessSignals): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Stamp `useful_state_reached_at` if (a) readiness is observed and
|
|
54
|
+
* (b) the field is still null. No-op otherwise. Returns the (possibly
|
|
55
|
+
* updated) record.
|
|
56
|
+
*/
|
|
57
|
+
export declare function stampUsefulStateIfReady(dataDir: string, opts: {
|
|
58
|
+
ready: boolean;
|
|
59
|
+
now: string;
|
|
60
|
+
}): OnboardingMetric;
|
|
61
|
+
/**
|
|
62
|
+
* Stamp `first_useful_recall_*` if eligible. Eligibility:
|
|
63
|
+
* 1. tool is one of `RETRIEVAL_TOOLS`
|
|
64
|
+
* 2. response was not degraded
|
|
65
|
+
* 3. response had at least one hit
|
|
66
|
+
* 4. `first_useful_recall_at` is still null (write-once)
|
|
67
|
+
* 5. `useful_state_reached_at` was already observed (non-null)
|
|
68
|
+
*
|
|
69
|
+
* The metric measures "first MCP retrieval *after* start." If start
|
|
70
|
+
* has not been observed yet, end stamping is skipped — recording an
|
|
71
|
+
* end alongside a synthesised start would report a near-zero duration
|
|
72
|
+
* that doesn't reflect a real "from readiness to first useful recall"
|
|
73
|
+
* measurement. Callers that want to avoid dropping the first real
|
|
74
|
+
* recall should evaluate readiness via the shared helper
|
|
75
|
+
* (`stampOnboardingStartIfReady` on the daemon, exposed through
|
|
76
|
+
* `/status/friend`) before invoking this function.
|
|
77
|
+
*/
|
|
78
|
+
export declare function stampFirstUsefulRecallIfEligible(dataDir: string, opts: {
|
|
79
|
+
tool: string;
|
|
80
|
+
isDegraded: boolean;
|
|
81
|
+
hitCount: number;
|
|
82
|
+
now: string;
|
|
83
|
+
}): OnboardingMetric;
|
|
84
|
+
/**
|
|
85
|
+
* Project the persisted metric to the three rendering states the
|
|
86
|
+
* status surface needs. Hidden = no start yet (don't show the line at
|
|
87
|
+
* all). Pending = start, no end. Completed = both, with a derived
|
|
88
|
+
* `duration_seconds`.
|
|
89
|
+
*/
|
|
90
|
+
export declare function computeOnboardingState(metric: OnboardingMetric): OnboardingState;
|
|
91
|
+
/**
|
|
92
|
+
* MCP-side bridge between a finished retrieval-tool call and the
|
|
93
|
+
* end-event stamper. Mirrors the extractor logic in
|
|
94
|
+
* `observability/tool-usage.ts` for `result_count` and `degraded`, but
|
|
95
|
+
* stays self-contained so this module has no dependency on the logger.
|
|
96
|
+
*
|
|
97
|
+
* Readiness handshake: end stamping requires `useful_state_reached_at`
|
|
98
|
+
* to already be set (the metric is "first MCP retrieval *after*
|
|
99
|
+
* start", per the v1 spec). When the recorder finds start still null
|
|
100
|
+
* but the response is otherwise eligible, it invokes the optional
|
|
101
|
+
* `pingReadiness` callback (the MCP wrapper passes one that GETs
|
|
102
|
+
* `/status/friend` on the daemon, which evaluates readiness signals
|
|
103
|
+
* and stamps start lazily). After the ping returns, the metric is
|
|
104
|
+
* re-read and end is stamped only if start has now landed. When no
|
|
105
|
+
* callback is provided, or readiness still cannot be observed, the
|
|
106
|
+
* end event is silently dropped — that matches the contract that
|
|
107
|
+
* end-without-start would otherwise misreport as a near-zero duration.
|
|
108
|
+
*
|
|
109
|
+
* Never throws: persistence errors and ping errors are swallowed so
|
|
110
|
+
* onboarding telemetry can never break a tool call. CLI callers do not
|
|
111
|
+
* invoke this helper (it lives behind the MCP server's tool
|
|
112
|
+
* registration), so the "MCP-only end" constraint is enforced by
|
|
113
|
+
* construction.
|
|
114
|
+
*/
|
|
115
|
+
export declare function recordMcpRetrievalForOnboarding(dataDir: string, tool: string, mcpResult: {
|
|
116
|
+
content?: Array<{
|
|
117
|
+
type: string;
|
|
118
|
+
text: string;
|
|
119
|
+
}>;
|
|
120
|
+
isError?: boolean;
|
|
121
|
+
structuredContent?: Record<string, unknown>;
|
|
122
|
+
}, opts?: {
|
|
123
|
+
now?: string;
|
|
124
|
+
pingReadiness?: () => Promise<void>;
|
|
125
|
+
}): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* Render a duration like `7m 42s` / `1h 03m 17s` / `12s`. Used by the
|
|
128
|
+
* friend-status header so the value reads in human time, not seconds.
|
|
129
|
+
*/
|
|
130
|
+
export declare function formatOnboardingDuration(totalSeconds: number): string;
|
|
131
|
+
//# sourceMappingURL=onboarding-metric.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onboarding-metric.d.ts","sourceRoot":"","sources":["../../../src/observability/onboarding-metric.ts"],"names":[],"mappings":"AA4BA,oEAAoE;AACpE,eAAO,MAAM,eAAe,aAI1B,CAAC;AAEH,MAAM,MAAM,aAAa,GACrB,aAAa,GACb,2BAA2B,GAC3B,mBAAmB,CAAC;AAExB,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,wBAAwB,EAAE,aAAa,GAAG,IAAI,CAAC;CAChD;AAED,MAAM,MAAM,eAAe,GACvB;IAAE,KAAK,EAAE,QAAQ,CAAA;CAAE,GACnB;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,uBAAuB,EAAE,MAAM,CAAA;CAAE,GACrD;IACE,KAAK,EAAE,WAAW,CAAC;IACnB,uBAAuB,EAAE,MAAM,CAAC;IAChC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,wBAAwB,EAAE,aAAa,CAAC;IACxC,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEN,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE5D;AAMD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAwCtE;AAuBD,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB;;;;;;;OAOG;IACH,oBAAoB,EAAE,OAAO,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAMvE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACpC,gBAAgB,CAUlB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,MAAM,EACf,IAAI,EAAE;IACJ,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb,GACA,gBAAgB,CAclB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,gBAAgB,GACvB,eAAe,CAwBjB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,+BAA+B,CACnD,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE;IACT,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC7C,EACD,IAAI,GAAE;IACJ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC,GACL,OAAO,CAAC,IAAI,CAAC,CA+Df;AAuDD;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAYrE"}
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `time_to_first_useful_recall` v1 instrumentation.
|
|
3
|
+
*
|
|
4
|
+
* Persists exactly four fields under `<data_dir>/metrics/onboarding.json`:
|
|
5
|
+
* - install_id (random UUID, minted on first read)
|
|
6
|
+
* - useful_state_reached_at (ISO timestamp or null)
|
|
7
|
+
* - first_useful_recall_at (ISO timestamp or null)
|
|
8
|
+
* - first_useful_recall_tool (one of the three retrieval tools)
|
|
9
|
+
*
|
|
10
|
+
* Privacy contract: query text, response text, hit IDs, source paths and
|
|
11
|
+
* client identifiers MUST NEVER land in this file. Writes go through a
|
|
12
|
+
* fixed-key sanitizer so an upstream caller that hands in extra fields
|
|
13
|
+
* cannot leak them by accident. Tests assert the persisted shape.
|
|
14
|
+
*
|
|
15
|
+
* Write-once: once a field is set, it is never overwritten. End
|
|
16
|
+
* stamping (`first_useful_recall_*`) requires `useful_state_reached_at`
|
|
17
|
+
* to have already been observed by a real readiness check — the metric's
|
|
18
|
+
* definition is "first MCP retrieval *after start*", so a recorded end
|
|
19
|
+
* without a prior recorded start would lie about the latency. If start
|
|
20
|
+
* is null when end fires, the end is dropped. To avoid losing the first
|
|
21
|
+
* real recall, callers should evaluate readiness via
|
|
22
|
+
* `stampOnboardingStartIfReady` (the shared helper used by
|
|
23
|
+
* `/status/friend`) before invoking the end-event recorder.
|
|
24
|
+
*/
|
|
25
|
+
import fs from "node:fs";
|
|
26
|
+
import path from "node:path";
|
|
27
|
+
import { randomUUID } from "node:crypto";
|
|
28
|
+
/** MCP retrieval tools that can satisfy the end-event condition. */
|
|
29
|
+
export const RETRIEVAL_TOOLS = new Set([
|
|
30
|
+
"rift_search",
|
|
31
|
+
"rift_conversations_search",
|
|
32
|
+
"rift_context_pack",
|
|
33
|
+
]);
|
|
34
|
+
export function onboardingMetricPath(dataDir) {
|
|
35
|
+
return path.join(dataDir, "metrics", "onboarding.json");
|
|
36
|
+
}
|
|
37
|
+
function isRetrievalTool(v) {
|
|
38
|
+
return typeof v === "string" && RETRIEVAL_TOOLS.has(v);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Read-or-bootstrap. A missing/corrupt file is replaced with a fresh
|
|
42
|
+
* record whose `install_id` is a new UUID. Unknown fields in an existing
|
|
43
|
+
* file are dropped on the next write (sanitizer drops everything outside
|
|
44
|
+
* the fixed key set).
|
|
45
|
+
*/
|
|
46
|
+
export function readOnboardingMetric(dataDir) {
|
|
47
|
+
const file = onboardingMetricPath(dataDir);
|
|
48
|
+
let parsed;
|
|
49
|
+
try {
|
|
50
|
+
const raw = fs.readFileSync(file, "utf8");
|
|
51
|
+
const obj = JSON.parse(raw);
|
|
52
|
+
if (obj && typeof obj === "object") {
|
|
53
|
+
parsed = obj;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// missing or unreadable — fall through to bootstrap
|
|
58
|
+
}
|
|
59
|
+
if (!parsed ||
|
|
60
|
+
typeof parsed["install_id"] !== "string" ||
|
|
61
|
+
parsed["install_id"].length === 0) {
|
|
62
|
+
const fresh = {
|
|
63
|
+
install_id: randomUUID(),
|
|
64
|
+
useful_state_reached_at: null,
|
|
65
|
+
first_useful_recall_at: null,
|
|
66
|
+
first_useful_recall_tool: null,
|
|
67
|
+
};
|
|
68
|
+
writeOnboardingMetric(dataDir, fresh);
|
|
69
|
+
return fresh;
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
install_id: parsed["install_id"],
|
|
73
|
+
useful_state_reached_at: typeof parsed["useful_state_reached_at"] === "string"
|
|
74
|
+
? parsed["useful_state_reached_at"]
|
|
75
|
+
: null,
|
|
76
|
+
first_useful_recall_at: typeof parsed["first_useful_recall_at"] === "string"
|
|
77
|
+
? parsed["first_useful_recall_at"]
|
|
78
|
+
: null,
|
|
79
|
+
first_useful_recall_tool: isRetrievalTool(parsed["first_useful_recall_tool"])
|
|
80
|
+
? parsed["first_useful_recall_tool"]
|
|
81
|
+
: null,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Persist the metric. The sanitizer copies exactly four named fields —
|
|
86
|
+
* anything else a caller might have spliced onto the object is discarded
|
|
87
|
+
* before it touches disk. This is the privacy guard that the schema
|
|
88
|
+
* test pins.
|
|
89
|
+
*/
|
|
90
|
+
function writeOnboardingMetric(dataDir, metric) {
|
|
91
|
+
const file = onboardingMetricPath(dataDir);
|
|
92
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
93
|
+
const sanitized = {
|
|
94
|
+
install_id: metric.install_id,
|
|
95
|
+
useful_state_reached_at: metric.useful_state_reached_at,
|
|
96
|
+
first_useful_recall_at: metric.first_useful_recall_at,
|
|
97
|
+
first_useful_recall_tool: metric.first_useful_recall_tool,
|
|
98
|
+
};
|
|
99
|
+
fs.writeFileSync(file, JSON.stringify(sanitized, null, 2));
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Useful state = the product delivered first value: the daemon is healthy,
|
|
103
|
+
* there is indexed content to retrieve, AND at least one working retrieval
|
|
104
|
+
* surface — semantic (valid Voyage embeddings) OR keyword (intentional no-key
|
|
105
|
+
* lexical mode). Gating on Voyage alone would make the shipped no-key path
|
|
106
|
+
* never count as activated, skewing beta telemetry.
|
|
107
|
+
*/
|
|
108
|
+
export function isUsefulStateReached(signals) {
|
|
109
|
+
return (signals.daemonHealthy &&
|
|
110
|
+
(signals.voyageKeyValid || signals.lexicalModeAvailable) &&
|
|
111
|
+
signals.indexedCount >= 1);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Stamp `useful_state_reached_at` if (a) readiness is observed and
|
|
115
|
+
* (b) the field is still null. No-op otherwise. Returns the (possibly
|
|
116
|
+
* updated) record.
|
|
117
|
+
*/
|
|
118
|
+
export function stampUsefulStateIfReady(dataDir, opts) {
|
|
119
|
+
const current = readOnboardingMetric(dataDir);
|
|
120
|
+
if (current.useful_state_reached_at !== null)
|
|
121
|
+
return current;
|
|
122
|
+
if (!opts.ready)
|
|
123
|
+
return current;
|
|
124
|
+
const next = {
|
|
125
|
+
...current,
|
|
126
|
+
useful_state_reached_at: opts.now,
|
|
127
|
+
};
|
|
128
|
+
writeOnboardingMetric(dataDir, next);
|
|
129
|
+
return next;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Stamp `first_useful_recall_*` if eligible. Eligibility:
|
|
133
|
+
* 1. tool is one of `RETRIEVAL_TOOLS`
|
|
134
|
+
* 2. response was not degraded
|
|
135
|
+
* 3. response had at least one hit
|
|
136
|
+
* 4. `first_useful_recall_at` is still null (write-once)
|
|
137
|
+
* 5. `useful_state_reached_at` was already observed (non-null)
|
|
138
|
+
*
|
|
139
|
+
* The metric measures "first MCP retrieval *after* start." If start
|
|
140
|
+
* has not been observed yet, end stamping is skipped — recording an
|
|
141
|
+
* end alongside a synthesised start would report a near-zero duration
|
|
142
|
+
* that doesn't reflect a real "from readiness to first useful recall"
|
|
143
|
+
* measurement. Callers that want to avoid dropping the first real
|
|
144
|
+
* recall should evaluate readiness via the shared helper
|
|
145
|
+
* (`stampOnboardingStartIfReady` on the daemon, exposed through
|
|
146
|
+
* `/status/friend`) before invoking this function.
|
|
147
|
+
*/
|
|
148
|
+
export function stampFirstUsefulRecallIfEligible(dataDir, opts) {
|
|
149
|
+
const current = readOnboardingMetric(dataDir);
|
|
150
|
+
if (!RETRIEVAL_TOOLS.has(opts.tool))
|
|
151
|
+
return current;
|
|
152
|
+
if (opts.isDegraded)
|
|
153
|
+
return current;
|
|
154
|
+
if (opts.hitCount < 1)
|
|
155
|
+
return current;
|
|
156
|
+
if (current.first_useful_recall_at !== null)
|
|
157
|
+
return current;
|
|
158
|
+
if (current.useful_state_reached_at === null)
|
|
159
|
+
return current;
|
|
160
|
+
const next = {
|
|
161
|
+
...current,
|
|
162
|
+
first_useful_recall_at: opts.now,
|
|
163
|
+
first_useful_recall_tool: opts.tool,
|
|
164
|
+
};
|
|
165
|
+
writeOnboardingMetric(dataDir, next);
|
|
166
|
+
return next;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Project the persisted metric to the three rendering states the
|
|
170
|
+
* status surface needs. Hidden = no start yet (don't show the line at
|
|
171
|
+
* all). Pending = start, no end. Completed = both, with a derived
|
|
172
|
+
* `duration_seconds`.
|
|
173
|
+
*/
|
|
174
|
+
export function computeOnboardingState(metric) {
|
|
175
|
+
if (!metric.useful_state_reached_at)
|
|
176
|
+
return { state: "hidden" };
|
|
177
|
+
if (!metric.first_useful_recall_at ||
|
|
178
|
+
!metric.first_useful_recall_tool) {
|
|
179
|
+
return {
|
|
180
|
+
state: "pending",
|
|
181
|
+
useful_state_reached_at: metric.useful_state_reached_at,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
const startMs = Date.parse(metric.useful_state_reached_at);
|
|
185
|
+
const endMs = Date.parse(metric.first_useful_recall_at);
|
|
186
|
+
const duration_seconds = Number.isNaN(startMs) || Number.isNaN(endMs)
|
|
187
|
+
? 0
|
|
188
|
+
: Math.max(0, Math.round((endMs - startMs) / 1000));
|
|
189
|
+
return {
|
|
190
|
+
state: "completed",
|
|
191
|
+
useful_state_reached_at: metric.useful_state_reached_at,
|
|
192
|
+
first_useful_recall_at: metric.first_useful_recall_at,
|
|
193
|
+
first_useful_recall_tool: metric.first_useful_recall_tool,
|
|
194
|
+
duration_seconds,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* MCP-side bridge between a finished retrieval-tool call and the
|
|
199
|
+
* end-event stamper. Mirrors the extractor logic in
|
|
200
|
+
* `observability/tool-usage.ts` for `result_count` and `degraded`, but
|
|
201
|
+
* stays self-contained so this module has no dependency on the logger.
|
|
202
|
+
*
|
|
203
|
+
* Readiness handshake: end stamping requires `useful_state_reached_at`
|
|
204
|
+
* to already be set (the metric is "first MCP retrieval *after*
|
|
205
|
+
* start", per the v1 spec). When the recorder finds start still null
|
|
206
|
+
* but the response is otherwise eligible, it invokes the optional
|
|
207
|
+
* `pingReadiness` callback (the MCP wrapper passes one that GETs
|
|
208
|
+
* `/status/friend` on the daemon, which evaluates readiness signals
|
|
209
|
+
* and stamps start lazily). After the ping returns, the metric is
|
|
210
|
+
* re-read and end is stamped only if start has now landed. When no
|
|
211
|
+
* callback is provided, or readiness still cannot be observed, the
|
|
212
|
+
* end event is silently dropped — that matches the contract that
|
|
213
|
+
* end-without-start would otherwise misreport as a near-zero duration.
|
|
214
|
+
*
|
|
215
|
+
* Never throws: persistence errors and ping errors are swallowed so
|
|
216
|
+
* onboarding telemetry can never break a tool call. CLI callers do not
|
|
217
|
+
* invoke this helper (it lives behind the MCP server's tool
|
|
218
|
+
* registration), so the "MCP-only end" constraint is enforced by
|
|
219
|
+
* construction.
|
|
220
|
+
*/
|
|
221
|
+
export async function recordMcpRetrievalForOnboarding(dataDir, tool, mcpResult, opts = {}) {
|
|
222
|
+
if (!RETRIEVAL_TOOLS.has(tool))
|
|
223
|
+
return;
|
|
224
|
+
if (mcpResult.isError)
|
|
225
|
+
return;
|
|
226
|
+
const initialNow = opts.now ?? new Date().toISOString();
|
|
227
|
+
try {
|
|
228
|
+
const signal = extractRetrievalSignal(tool, mcpResult);
|
|
229
|
+
if (signal.count === undefined)
|
|
230
|
+
return;
|
|
231
|
+
if (signal.degraded === true)
|
|
232
|
+
return;
|
|
233
|
+
if (signal.count < 1)
|
|
234
|
+
return;
|
|
235
|
+
// Cheap pre-check: if end is already stamped, skip everything
|
|
236
|
+
// (write-once means stampFirstUsefulRecallIfEligible would no-op
|
|
237
|
+
// anyway, but bailing here avoids a needless readiness ping).
|
|
238
|
+
let current = readOnboardingMetric(dataDir);
|
|
239
|
+
if (current.first_useful_recall_at !== null)
|
|
240
|
+
return;
|
|
241
|
+
// Readiness handshake: only when start is missing AND a ping is
|
|
242
|
+
// available. The end-condition (non-degraded, ≥ 1 hit) strictly
|
|
243
|
+
// implies the start-conditions hold in the wider system, but we
|
|
244
|
+
// still want the daemon to do the formal readiness observation
|
|
245
|
+
// (env present + last_embed_at + capability counts) before
|
|
246
|
+
// recording an end timestamp — otherwise the metric would lie
|
|
247
|
+
// about its own definition.
|
|
248
|
+
if (current.useful_state_reached_at === null && opts.pingReadiness) {
|
|
249
|
+
try {
|
|
250
|
+
await opts.pingReadiness();
|
|
251
|
+
}
|
|
252
|
+
catch {
|
|
253
|
+
// Ping failures degrade to "skip end this time" rather than
|
|
254
|
+
// breaking the tool call. The next eligible retrieval will
|
|
255
|
+
// re-attempt the ping.
|
|
256
|
+
}
|
|
257
|
+
// Re-read so the ordering clamp below sees the freshly stamped
|
|
258
|
+
// start (if any) before we record end.
|
|
259
|
+
current = readOnboardingMetric(dataDir);
|
|
260
|
+
}
|
|
261
|
+
// Ordering clamp: the metric measures "first MCP retrieval *after*
|
|
262
|
+
// start", so `first_useful_recall_at` must never be earlier than
|
|
263
|
+
// `useful_state_reached_at`. When the readiness ping above lazily
|
|
264
|
+
// stamps start during this same call, the retrieval `now` captured
|
|
265
|
+
// before the ping can be older than the freshly written start —
|
|
266
|
+
// recording the older `now` as end would produce an inverted pair
|
|
267
|
+
// that the duration projection then silently clamps to 0s, hiding
|
|
268
|
+
// the bug. Take the max so the persisted end is always >= start.
|
|
269
|
+
let now = initialNow;
|
|
270
|
+
if (current.useful_state_reached_at !== null &&
|
|
271
|
+
now < current.useful_state_reached_at) {
|
|
272
|
+
now = current.useful_state_reached_at;
|
|
273
|
+
}
|
|
274
|
+
stampFirstUsefulRecallIfEligible(dataDir, {
|
|
275
|
+
tool,
|
|
276
|
+
isDegraded: false,
|
|
277
|
+
hitCount: signal.count,
|
|
278
|
+
now,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
// Telemetry must never break tool execution.
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Per-tool `(count, degraded)` extraction. Duplicated from
|
|
287
|
+
* `tool-usage.ts` rather than imported to avoid circular dependency
|
|
288
|
+
* risk and to keep this module's contract narrow.
|
|
289
|
+
*/
|
|
290
|
+
function extractRetrievalSignal(tool, mcpResult) {
|
|
291
|
+
const sc = mcpResult.structuredContent;
|
|
292
|
+
if (tool === "rift_context_pack") {
|
|
293
|
+
if (!sc)
|
|
294
|
+
return {};
|
|
295
|
+
const sum = (key) => {
|
|
296
|
+
const v = sc[key];
|
|
297
|
+
return Array.isArray(v) ? v.length : 0;
|
|
298
|
+
};
|
|
299
|
+
const count = sum("decisions") + sum("constraints") + sum("examples") + sum("rules");
|
|
300
|
+
const out = { count };
|
|
301
|
+
if (typeof sc["degraded"] === "boolean")
|
|
302
|
+
out.degraded = sc["degraded"];
|
|
303
|
+
return out;
|
|
304
|
+
}
|
|
305
|
+
// search-style tools: prefer structuredContent.results, fall back to JSON-in-text.
|
|
306
|
+
const fromStructured = sc?.["results"];
|
|
307
|
+
if (Array.isArray(fromStructured)) {
|
|
308
|
+
const out = {
|
|
309
|
+
count: fromStructured.length,
|
|
310
|
+
};
|
|
311
|
+
if (typeof sc?.["degraded"] === "boolean") {
|
|
312
|
+
out.degraded = sc["degraded"];
|
|
313
|
+
}
|
|
314
|
+
return out;
|
|
315
|
+
}
|
|
316
|
+
try {
|
|
317
|
+
const text = mcpResult.content?.[0]?.text;
|
|
318
|
+
if (!text)
|
|
319
|
+
return {};
|
|
320
|
+
const parsed = JSON.parse(text);
|
|
321
|
+
const out = {};
|
|
322
|
+
if (Array.isArray(parsed["results"])) {
|
|
323
|
+
out.count = parsed["results"].length;
|
|
324
|
+
}
|
|
325
|
+
if (typeof parsed["degraded"] === "boolean") {
|
|
326
|
+
out.degraded = parsed["degraded"];
|
|
327
|
+
}
|
|
328
|
+
return out;
|
|
329
|
+
}
|
|
330
|
+
catch {
|
|
331
|
+
return {};
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Render a duration like `7m 42s` / `1h 03m 17s` / `12s`. Used by the
|
|
336
|
+
* friend-status header so the value reads in human time, not seconds.
|
|
337
|
+
*/
|
|
338
|
+
export function formatOnboardingDuration(totalSeconds) {
|
|
339
|
+
const s = Math.max(0, Math.floor(totalSeconds));
|
|
340
|
+
const hours = Math.floor(s / 3600);
|
|
341
|
+
const minutes = Math.floor((s % 3600) / 60);
|
|
342
|
+
const seconds = s % 60;
|
|
343
|
+
if (hours > 0) {
|
|
344
|
+
return `${hours}h ${String(minutes).padStart(2, "0")}m ${String(seconds).padStart(2, "0")}s`;
|
|
345
|
+
}
|
|
346
|
+
if (minutes > 0) {
|
|
347
|
+
return `${minutes}m ${String(seconds).padStart(2, "0")}s`;
|
|
348
|
+
}
|
|
349
|
+
return `${seconds}s`;
|
|
350
|
+
}
|
|
351
|
+
//# sourceMappingURL=onboarding-metric.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onboarding-metric.js","sourceRoot":"","sources":["../../../src/observability/onboarding-metric.ts"],"names":[],"mappings":"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"}
|