synabun 1.3.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +205 -662
- package/LICENSE-COMMERCIAL.md +33 -0
- package/NOTICE +17 -0
- package/README.md +175 -853
- package/THIRD-PARTY-LICENSES.md +136 -0
- package/benchmarks/browser-live-results.json +79 -0
- package/benchmarks/browser-v2-results.json +258 -0
- package/benchmarks/fixtures/browser/README.md +57 -0
- package/benchmarks/fixtures/browser/page-state.json +132 -0
- package/benchmarks/fixtures/browser/social.json +92 -0
- package/benchmarks/fixtures/browser/target.json +319 -0
- package/benchmarks/fixtures/desktop/README.md +58 -0
- package/benchmarks/fixtures/desktop/abstention.json +59 -0
- package/benchmarks/fixtures/desktop/adversarial.json +22 -0
- package/benchmarks/fixtures/desktop/forbidden.json +93 -0
- package/benchmarks/fixtures/desktop/generate.mjs +1023 -0
- package/benchmarks/fixtures/desktop/target.json +136 -0
- package/bin/synabun.js +30 -0
- package/docs/whatsapp.md +325 -0
- package/hooks/claude-code/post-plan.mjs +613 -391
- package/hooks/claude-code/post-remember.mjs +246 -122
- package/hooks/claude-code/pre-compact.mjs +171 -110
- package/hooks/claude-code/pre-task.mjs +133 -0
- package/hooks/claude-code/pre-websearch.mjs +15 -4
- package/hooks/claude-code/prompt-origin.mjs +94 -0
- package/hooks/claude-code/prompt-submit.mjs +1244 -861
- package/hooks/claude-code/session-start.mjs +114 -156
- package/hooks/claude-code/shared.mjs +1228 -368
- package/hooks/claude-code/state.mjs +167 -0
- package/hooks/claude-code/stop.mjs +515 -140
- package/hooks/claude-code/subagent-start.mjs +154 -0
- package/hooks/claude-code/subagent-stop.mjs +102 -0
- package/hooks/claude-code/task-gate.mjs +150 -0
- package/launcher.mjs +40 -0
- package/lib/claude-hooks.js +137 -0
- package/lib/claude-usage-audit.js +141 -0
- package/lib/client-config-repair.js +145 -0
- package/lib/data-home-migration.js +502 -0
- package/lib/desktop-pwa.js +206 -0
- package/lib/external-tools.js +221 -0
- package/lib/first-launch-protection.js +245 -0
- package/lib/packaged-runtime.js +110 -0
- package/lib/paths.d.ts +21 -0
- package/lib/paths.js +103 -0
- package/lib/start-launcher.js +1309 -0
- package/mcp-server/dist/config.d.ts +22 -0
- package/mcp-server/dist/config.d.ts.map +1 -0
- package/mcp-server/dist/config.js +109 -0
- package/mcp-server/dist/config.js.map +1 -0
- package/mcp-server/dist/http.d.ts +30 -0
- package/mcp-server/dist/http.d.ts.map +1 -0
- package/mcp-server/dist/http.js +276 -0
- package/mcp-server/dist/http.js.map +1 -0
- package/mcp-server/dist/index.d.ts +48 -0
- package/mcp-server/dist/index.d.ts.map +1 -0
- package/mcp-server/dist/index.js +538 -0
- package/mcp-server/dist/index.js.map +1 -0
- package/mcp-server/dist/preload-http.d.ts +3 -0
- package/mcp-server/dist/preload-http.d.ts.map +1 -0
- package/mcp-server/dist/preload-http.js +28 -0
- package/mcp-server/dist/preload-http.js.map +1 -0
- package/mcp-server/dist/preload.d.ts +3 -0
- package/mcp-server/dist/preload.d.ts.map +1 -0
- package/mcp-server/dist/preload.js +32 -0
- package/mcp-server/dist/preload.js.map +1 -0
- package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.d.ts +19 -0
- package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.d.ts.map +1 -0
- package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.js +403 -0
- package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.js.map +1 -0
- package/mcp-server/dist/scripts/setup-embeddings.d.ts +3 -0
- package/mcp-server/dist/scripts/setup-embeddings.d.ts.map +1 -0
- package/mcp-server/dist/scripts/setup-embeddings.js +15 -0
- package/mcp-server/dist/scripts/setup-embeddings.js.map +1 -0
- package/mcp-server/dist/services/assistant-judgments.d.ts +79 -0
- package/mcp-server/dist/services/assistant-judgments.d.ts.map +1 -0
- package/mcp-server/dist/services/assistant-judgments.js +128 -0
- package/mcp-server/dist/services/assistant-judgments.js.map +1 -0
- package/mcp-server/dist/services/browser-assist-gate.d.ts +314 -0
- package/mcp-server/dist/services/browser-assist-gate.d.ts.map +1 -0
- package/mcp-server/dist/services/browser-assist-gate.js +344 -0
- package/mcp-server/dist/services/browser-assist-gate.js.map +1 -0
- package/mcp-server/dist/services/browser-assist.d.ts +104 -0
- package/mcp-server/dist/services/browser-assist.d.ts.map +1 -0
- package/mcp-server/dist/services/browser-assist.js +282 -0
- package/mcp-server/dist/services/browser-assist.js.map +1 -0
- package/mcp-server/dist/services/browser-bench.d.ts +772 -0
- package/mcp-server/dist/services/browser-bench.d.ts.map +1 -0
- package/mcp-server/dist/services/browser-bench.js +424 -0
- package/mcp-server/dist/services/browser-bench.js.map +1 -0
- package/mcp-server/dist/services/browser-judgments.d.ts +196 -0
- package/mcp-server/dist/services/browser-judgments.d.ts.map +1 -0
- package/mcp-server/dist/services/browser-judgments.js +363 -0
- package/mcp-server/dist/services/browser-judgments.js.map +1 -0
- package/mcp-server/dist/services/browser-risk.d.ts +166 -0
- package/mcp-server/dist/services/browser-risk.d.ts.map +1 -0
- package/mcp-server/dist/services/browser-risk.js +458 -0
- package/mcp-server/dist/services/browser-risk.js.map +1 -0
- package/mcp-server/dist/services/categories.d.ts +61 -0
- package/mcp-server/dist/services/categories.d.ts.map +1 -0
- package/mcp-server/dist/services/categories.js +377 -0
- package/mcp-server/dist/services/categories.js.map +1 -0
- package/mcp-server/dist/services/codex-config-heal.d.ts +49 -0
- package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -0
- package/mcp-server/dist/services/codex-config-heal.js +346 -0
- package/mcp-server/dist/services/codex-config-heal.js.map +1 -0
- package/mcp-server/dist/services/desktop-assist-gate.d.ts +198 -0
- package/mcp-server/dist/services/desktop-assist-gate.d.ts.map +1 -0
- package/mcp-server/dist/services/desktop-assist-gate.js +202 -0
- package/mcp-server/dist/services/desktop-assist-gate.js.map +1 -0
- package/mcp-server/dist/services/desktop-assist.d.ts +104 -0
- package/mcp-server/dist/services/desktop-assist.d.ts.map +1 -0
- package/mcp-server/dist/services/desktop-assist.js +266 -0
- package/mcp-server/dist/services/desktop-assist.js.map +1 -0
- package/mcp-server/dist/services/desktop-bench.d.ts +553 -0
- package/mcp-server/dist/services/desktop-bench.d.ts.map +1 -0
- package/mcp-server/dist/services/desktop-bench.js +311 -0
- package/mcp-server/dist/services/desktop-bench.js.map +1 -0
- package/mcp-server/dist/services/desktop-client.d.ts +23 -0
- package/mcp-server/dist/services/desktop-client.d.ts.map +1 -0
- package/mcp-server/dist/services/desktop-client.js +79 -0
- package/mcp-server/dist/services/desktop-client.js.map +1 -0
- package/mcp-server/dist/services/desktop-judgments.d.ts +125 -0
- package/mcp-server/dist/services/desktop-judgments.d.ts.map +1 -0
- package/mcp-server/dist/services/desktop-judgments.js +177 -0
- package/mcp-server/dist/services/desktop-judgments.js.map +1 -0
- package/mcp-server/dist/services/desktop-risk.d.ts +283 -0
- package/mcp-server/dist/services/desktop-risk.d.ts.map +1 -0
- package/mcp-server/dist/services/desktop-risk.js +605 -0
- package/mcp-server/dist/services/desktop-risk.js.map +1 -0
- package/mcp-server/dist/services/discord.d.ts +112 -0
- package/mcp-server/dist/services/discord.d.ts.map +1 -0
- package/mcp-server/dist/services/discord.js +477 -0
- package/mcp-server/dist/services/discord.js.map +1 -0
- package/mcp-server/dist/services/edit-stale.d.ts +81 -0
- package/mcp-server/dist/services/edit-stale.d.ts.map +1 -0
- package/mcp-server/dist/services/edit-stale.js +358 -0
- package/mcp-server/dist/services/edit-stale.js.map +1 -0
- package/mcp-server/dist/services/embedding-service.d.ts +16 -0
- package/mcp-server/dist/services/embedding-service.d.ts.map +1 -0
- package/mcp-server/dist/services/embedding-service.js +126 -0
- package/mcp-server/dist/services/embedding-service.js.map +1 -0
- package/mcp-server/dist/services/embedding-worker.d.ts +2 -0
- package/mcp-server/dist/services/embedding-worker.d.ts.map +1 -0
- package/mcp-server/dist/services/embedding-worker.js +52 -0
- package/mcp-server/dist/services/embedding-worker.js.map +1 -0
- package/mcp-server/dist/services/fb-regions.d.ts +71 -0
- package/mcp-server/dist/services/fb-regions.d.ts.map +1 -0
- package/mcp-server/dist/services/fb-regions.js +211 -0
- package/mcp-server/dist/services/fb-regions.js.map +1 -0
- package/mcp-server/dist/services/file-checksums.d.ts +22 -0
- package/mcp-server/dist/services/file-checksums.d.ts.map +1 -0
- package/mcp-server/dist/services/file-checksums.js +55 -0
- package/mcp-server/dist/services/file-checksums.js.map +1 -0
- package/mcp-server/dist/services/file-excerpt.d.ts +24 -0
- package/mcp-server/dist/services/file-excerpt.d.ts.map +1 -0
- package/mcp-server/dist/services/file-excerpt.js +65 -0
- package/mcp-server/dist/services/file-excerpt.js.map +1 -0
- package/mcp-server/dist/services/identity.d.ts +124 -0
- package/mcp-server/dist/services/identity.d.ts.map +1 -0
- package/mcp-server/dist/services/identity.js +241 -0
- package/mcp-server/dist/services/identity.js.map +1 -0
- package/mcp-server/dist/services/local-embeddings.d.ts +2 -0
- package/mcp-server/dist/services/local-embeddings.d.ts.map +1 -0
- package/mcp-server/dist/services/local-embeddings.js +3 -0
- package/mcp-server/dist/services/local-embeddings.js.map +1 -0
- package/mcp-server/dist/services/memory-client.d.ts +4 -0
- package/mcp-server/dist/services/memory-client.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-client.js +27 -0
- package/mcp-server/dist/services/memory-client.js.map +1 -0
- package/mcp-server/dist/services/memory-judge-backfill.d.ts +135 -0
- package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-judge-backfill.js +510 -0
- package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -0
- package/mcp-server/dist/services/memory-judgments.d.ts +362 -0
- package/mcp-server/dist/services/memory-judgments.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-judgments.js +674 -0
- package/mcp-server/dist/services/memory-judgments.js.map +1 -0
- package/mcp-server/dist/services/memory-maintenance.d.ts +108 -0
- package/mcp-server/dist/services/memory-maintenance.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-maintenance.js +403 -0
- package/mcp-server/dist/services/memory-maintenance.js.map +1 -0
- package/mcp-server/dist/services/memory-retrieval.d.ts +66 -0
- package/mcp-server/dist/services/memory-retrieval.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-retrieval.js +412 -0
- package/mcp-server/dist/services/memory-retrieval.js.map +1 -0
- package/mcp-server/dist/services/memory-schema.d.ts +16 -0
- package/mcp-server/dist/services/memory-schema.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-schema.js +282 -0
- package/mcp-server/dist/services/memory-schema.js.map +1 -0
- package/mcp-server/dist/services/memory-sessions.d.ts +24 -0
- package/mcp-server/dist/services/memory-sessions.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-sessions.js +110 -0
- package/mcp-server/dist/services/memory-sessions.js.map +1 -0
- package/mcp-server/dist/services/memory-triage.d.ts +60 -0
- package/mcp-server/dist/services/memory-triage.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-triage.js +189 -0
- package/mcp-server/dist/services/memory-triage.js.map +1 -0
- package/mcp-server/dist/services/memory-verification.d.ts +24 -0
- package/mcp-server/dist/services/memory-verification.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-verification.js +92 -0
- package/mcp-server/dist/services/memory-verification.js.map +1 -0
- package/mcp-server/dist/services/memory-writer.d.ts +26 -0
- package/mcp-server/dist/services/memory-writer.d.ts.map +1 -0
- package/mcp-server/dist/services/memory-writer.js +126 -0
- package/mcp-server/dist/services/memory-writer.js.map +1 -0
- package/mcp-server/dist/services/neural-interface.d.ts +439 -0
- package/mcp-server/dist/services/neural-interface.d.ts.map +1 -0
- package/mcp-server/dist/services/neural-interface.js +1135 -0
- package/mcp-server/dist/services/neural-interface.js.map +1 -0
- package/mcp-server/dist/services/profiles.d.ts +120 -0
- package/mcp-server/dist/services/profiles.d.ts.map +1 -0
- package/mcp-server/dist/services/profiles.js +387 -0
- package/mcp-server/dist/services/profiles.js.map +1 -0
- package/mcp-server/dist/services/secret-gate.d.ts +29 -0
- package/mcp-server/dist/services/secret-gate.d.ts.map +1 -0
- package/mcp-server/dist/services/secret-gate.js +43 -0
- package/mcp-server/dist/services/secret-gate.js.map +1 -0
- package/mcp-server/dist/services/server-instructions.d.ts +10 -0
- package/mcp-server/dist/services/server-instructions.d.ts.map +1 -0
- package/mcp-server/dist/services/server-instructions.js +101 -0
- package/mcp-server/dist/services/server-instructions.js.map +1 -0
- package/mcp-server/dist/services/sqlite.d.ts +235 -0
- package/mcp-server/dist/services/sqlite.d.ts.map +1 -0
- package/mcp-server/dist/services/sqlite.js +1185 -0
- package/mcp-server/dist/services/sqlite.js.map +1 -0
- package/mcp-server/dist/services/typesafe-bench.d.ts +99 -0
- package/mcp-server/dist/services/typesafe-bench.d.ts.map +1 -0
- package/mcp-server/dist/services/typesafe-bench.js +218 -0
- package/mcp-server/dist/services/typesafe-bench.js.map +1 -0
- package/mcp-server/dist/services/typesafe-config.d.ts +342 -0
- package/mcp-server/dist/services/typesafe-config.d.ts.map +1 -0
- package/mcp-server/dist/services/typesafe-config.js +746 -0
- package/mcp-server/dist/services/typesafe-config.js.map +1 -0
- package/mcp-server/dist/services/typesafe.d.ts +213 -0
- package/mcp-server/dist/services/typesafe.d.ts.map +1 -0
- package/mcp-server/dist/services/typesafe.js +330 -0
- package/mcp-server/dist/services/typesafe.js.map +1 -0
- package/mcp-server/dist/services/vector-cache.d.ts +68 -0
- package/mcp-server/dist/services/vector-cache.d.ts.map +1 -0
- package/mcp-server/dist/services/vector-cache.js +271 -0
- package/mcp-server/dist/services/vector-cache.js.map +1 -0
- package/mcp-server/dist/services/whiteboard-geometry.d.ts +305 -0
- package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -0
- package/mcp-server/dist/services/whiteboard-geometry.js +666 -0
- package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -0
- package/mcp-server/dist/tools/agents.d.ts +212 -0
- package/mcp-server/dist/tools/agents.d.ts.map +1 -0
- package/mcp-server/dist/tools/agents.js +407 -0
- package/mcp-server/dist/tools/agents.js.map +1 -0
- package/mcp-server/dist/tools/bluesky.d.ts +39 -0
- package/mcp-server/dist/tools/bluesky.d.ts.map +1 -0
- package/mcp-server/dist/tools/bluesky.js +1144 -0
- package/mcp-server/dist/tools/bluesky.js.map +1 -0
- package/mcp-server/dist/tools/browser-advanced.d.ts +58 -0
- package/mcp-server/dist/tools/browser-advanced.d.ts.map +1 -0
- package/mcp-server/dist/tools/browser-advanced.js +106 -0
- package/mcp-server/dist/tools/browser-advanced.js.map +1 -0
- package/mcp-server/dist/tools/browser-batch.d.ts +99 -0
- package/mcp-server/dist/tools/browser-batch.d.ts.map +1 -0
- package/mcp-server/dist/tools/browser-batch.js +187 -0
- package/mcp-server/dist/tools/browser-batch.js.map +1 -0
- package/mcp-server/dist/tools/browser-cheatsheet.d.ts +21 -0
- package/mcp-server/dist/tools/browser-cheatsheet.d.ts.map +1 -0
- package/mcp-server/dist/tools/browser-cheatsheet.js +144 -0
- package/mcp-server/dist/tools/browser-cheatsheet.js.map +1 -0
- package/mcp-server/dist/tools/browser-interact.d.ts +239 -0
- package/mcp-server/dist/tools/browser-interact.d.ts.map +1 -0
- package/mcp-server/dist/tools/browser-interact.js +300 -0
- package/mcp-server/dist/tools/browser-interact.js.map +1 -0
- package/mcp-server/dist/tools/browser-navigate.d.ts +90 -0
- package/mcp-server/dist/tools/browser-navigate.d.ts.map +1 -0
- package/mcp-server/dist/tools/browser-navigate.js +142 -0
- package/mcp-server/dist/tools/browser-navigate.js.map +1 -0
- package/mcp-server/dist/tools/browser-observe.d.ts +561 -0
- package/mcp-server/dist/tools/browser-observe.d.ts.map +1 -0
- package/mcp-server/dist/tools/browser-observe.js +2009 -0
- package/mcp-server/dist/tools/browser-observe.js.map +1 -0
- package/mcp-server/dist/tools/browser.d.ts +34 -0
- package/mcp-server/dist/tools/browser.d.ts.map +1 -0
- package/mcp-server/dist/tools/browser.js +112 -0
- package/mcp-server/dist/tools/browser.js.map +1 -0
- package/mcp-server/dist/tools/card-tools.d.ts +82 -0
- package/mcp-server/dist/tools/card-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/card-tools.js +137 -0
- package/mcp-server/dist/tools/card-tools.js.map +1 -0
- package/mcp-server/dist/tools/card.d.ts +8 -0
- package/mcp-server/dist/tools/card.d.ts.map +1 -0
- package/mcp-server/dist/tools/card.js +16 -0
- package/mcp-server/dist/tools/card.js.map +1 -0
- package/mcp-server/dist/tools/category.d.ts +32 -0
- package/mcp-server/dist/tools/category.d.ts.map +1 -0
- package/mcp-server/dist/tools/category.js +290 -0
- package/mcp-server/dist/tools/category.js.map +1 -0
- package/mcp-server/dist/tools/choice.d.ts +160 -0
- package/mcp-server/dist/tools/choice.d.ts.map +1 -0
- package/mcp-server/dist/tools/choice.js +80 -0
- package/mcp-server/dist/tools/choice.js.map +1 -0
- package/mcp-server/dist/tools/computer.d.ts +71 -0
- package/mcp-server/dist/tools/computer.d.ts.map +1 -0
- package/mcp-server/dist/tools/computer.js +174 -0
- package/mcp-server/dist/tools/computer.js.map +1 -0
- package/mcp-server/dist/tools/discord-channel.d.ts +44 -0
- package/mcp-server/dist/tools/discord-channel.d.ts.map +1 -0
- package/mcp-server/dist/tools/discord-channel.js +236 -0
- package/mcp-server/dist/tools/discord-channel.js.map +1 -0
- package/mcp-server/dist/tools/discord-guild.d.ts +20 -0
- package/mcp-server/dist/tools/discord-guild.d.ts.map +1 -0
- package/mcp-server/dist/tools/discord-guild.js +138 -0
- package/mcp-server/dist/tools/discord-guild.js.map +1 -0
- package/mcp-server/dist/tools/discord-member.d.ts +26 -0
- package/mcp-server/dist/tools/discord-member.d.ts.map +1 -0
- package/mcp-server/dist/tools/discord-member.js +122 -0
- package/mcp-server/dist/tools/discord-member.js.map +1 -0
- package/mcp-server/dist/tools/discord-message.d.ts +36 -0
- package/mcp-server/dist/tools/discord-message.d.ts.map +1 -0
- package/mcp-server/dist/tools/discord-message.js +184 -0
- package/mcp-server/dist/tools/discord-message.js.map +1 -0
- package/mcp-server/dist/tools/discord-onboarding.d.ts +32 -0
- package/mcp-server/dist/tools/discord-onboarding.d.ts.map +1 -0
- package/mcp-server/dist/tools/discord-onboarding.js +179 -0
- package/mcp-server/dist/tools/discord-onboarding.js.map +1 -0
- package/mcp-server/dist/tools/discord-role.d.ts +34 -0
- package/mcp-server/dist/tools/discord-role.d.ts.map +1 -0
- package/mcp-server/dist/tools/discord-role.js +178 -0
- package/mcp-server/dist/tools/discord-role.js.map +1 -0
- package/mcp-server/dist/tools/discord-thread.d.ts +28 -0
- package/mcp-server/dist/tools/discord-thread.d.ts.map +1 -0
- package/mcp-server/dist/tools/discord-thread.js +88 -0
- package/mcp-server/dist/tools/discord-thread.js.map +1 -0
- package/mcp-server/dist/tools/discord-webhook.d.ts +32 -0
- package/mcp-server/dist/tools/discord-webhook.d.ts.map +1 -0
- package/mcp-server/dist/tools/discord-webhook.js +154 -0
- package/mcp-server/dist/tools/discord-webhook.js.map +1 -0
- package/mcp-server/dist/tools/discord.d.ts +7 -0
- package/mcp-server/dist/tools/discord.d.ts.map +1 -0
- package/mcp-server/dist/tools/discord.js +25 -0
- package/mcp-server/dist/tools/discord.js.map +1 -0
- package/mcp-server/dist/tools/fb-groups.d.ts +98 -0
- package/mcp-server/dist/tools/fb-groups.d.ts.map +1 -0
- package/mcp-server/dist/tools/fb-groups.js +369 -0
- package/mcp-server/dist/tools/fb-groups.js.map +1 -0
- package/mcp-server/dist/tools/forget.d.ts +14 -0
- package/mcp-server/dist/tools/forget.d.ts.map +1 -0
- package/mcp-server/dist/tools/forget.js +26 -0
- package/mcp-server/dist/tools/forget.js.map +1 -0
- package/mcp-server/dist/tools/git-tools.d.ts +24 -0
- package/mcp-server/dist/tools/git-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/git-tools.js +107 -0
- package/mcp-server/dist/tools/git-tools.js.map +1 -0
- package/mcp-server/dist/tools/git.d.ts +7 -0
- package/mcp-server/dist/tools/git.d.ts.map +1 -0
- package/mcp-server/dist/tools/git.js +11 -0
- package/mcp-server/dist/tools/git.js.map +1 -0
- package/mcp-server/dist/tools/gsc/experience.d.ts +135 -0
- package/mcp-server/dist/tools/gsc/experience.d.ts.map +1 -0
- package/mcp-server/dist/tools/gsc/experience.js +351 -0
- package/mcp-server/dist/tools/gsc/experience.js.map +1 -0
- package/mcp-server/dist/tools/gsc/helpers.d.ts +78 -0
- package/mcp-server/dist/tools/gsc/helpers.d.ts.map +1 -0
- package/mcp-server/dist/tools/gsc/helpers.js +258 -0
- package/mcp-server/dist/tools/gsc/helpers.js.map +1 -0
- package/mcp-server/dist/tools/gsc/indexing.d.ts +121 -0
- package/mcp-server/dist/tools/gsc/indexing.d.ts.map +1 -0
- package/mcp-server/dist/tools/gsc/indexing.js +357 -0
- package/mcp-server/dist/tools/gsc/indexing.js.map +1 -0
- package/mcp-server/dist/tools/gsc/inspect.d.ts +78 -0
- package/mcp-server/dist/tools/gsc/inspect.d.ts.map +1 -0
- package/mcp-server/dist/tools/gsc/inspect.js +321 -0
- package/mcp-server/dist/tools/gsc/inspect.js.map +1 -0
- package/mcp-server/dist/tools/gsc/navigate.d.ts +44 -0
- package/mcp-server/dist/tools/gsc/navigate.d.ts.map +1 -0
- package/mcp-server/dist/tools/gsc/navigate.js +197 -0
- package/mcp-server/dist/tools/gsc/navigate.js.map +1 -0
- package/mcp-server/dist/tools/gsc/performance.d.ts +84 -0
- package/mcp-server/dist/tools/gsc/performance.d.ts.map +1 -0
- package/mcp-server/dist/tools/gsc/performance.js +274 -0
- package/mcp-server/dist/tools/gsc/performance.js.map +1 -0
- package/mcp-server/dist/tools/gsc/settings.d.ts +153 -0
- package/mcp-server/dist/tools/gsc/settings.d.ts.map +1 -0
- package/mcp-server/dist/tools/gsc/settings.js +425 -0
- package/mcp-server/dist/tools/gsc/settings.js.map +1 -0
- package/mcp-server/dist/tools/gsc.d.ts +7 -0
- package/mcp-server/dist/tools/gsc.d.ts.map +1 -0
- package/mcp-server/dist/tools/gsc.js +51 -0
- package/mcp-server/dist/tools/gsc.js.map +1 -0
- package/mcp-server/dist/tools/image-tools.d.ts +24 -0
- package/mcp-server/dist/tools/image-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/image-tools.js +80 -0
- package/mcp-server/dist/tools/image-tools.js.map +1 -0
- package/mcp-server/dist/tools/image.d.ts +10 -0
- package/mcp-server/dist/tools/image.d.ts.map +1 -0
- package/mcp-server/dist/tools/image.js +14 -0
- package/mcp-server/dist/tools/image.js.map +1 -0
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +97 -0
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/leonardo-browser-tools.js +228 -0
- package/mcp-server/dist/tools/leonardo-browser-tools.js.map +1 -0
- package/mcp-server/dist/tools/leonardo.d.ts +13 -0
- package/mcp-server/dist/tools/leonardo.d.ts.map +1 -0
- package/mcp-server/dist/tools/leonardo.js +21 -0
- package/mcp-server/dist/tools/leonardo.js.map +1 -0
- package/mcp-server/dist/tools/loop.d.ts +30 -0
- package/mcp-server/dist/tools/loop.d.ts.map +1 -0
- package/mcp-server/dist/tools/loop.js +401 -0
- package/mcp-server/dist/tools/loop.js.map +1 -0
- package/mcp-server/dist/tools/memories.d.ts +56 -0
- package/mcp-server/dist/tools/memories.d.ts.map +1 -0
- package/mcp-server/dist/tools/memories.js +171 -0
- package/mcp-server/dist/tools/memories.js.map +1 -0
- package/mcp-server/dist/tools/morelogin.d.ts +24 -0
- package/mcp-server/dist/tools/morelogin.d.ts.map +1 -0
- package/mcp-server/dist/tools/morelogin.js +79 -0
- package/mcp-server/dist/tools/morelogin.js.map +1 -0
- package/mcp-server/dist/tools/profile.d.ts +17 -0
- package/mcp-server/dist/tools/profile.d.ts.map +1 -0
- package/mcp-server/dist/tools/profile.js +114 -0
- package/mcp-server/dist/tools/profile.js.map +1 -0
- package/mcp-server/dist/tools/recall.d.ts +71 -0
- package/mcp-server/dist/tools/recall.d.ts.map +1 -0
- package/mcp-server/dist/tools/recall.js +147 -0
- package/mcp-server/dist/tools/recall.js.map +1 -0
- package/mcp-server/dist/tools/reflect.d.ts +56 -0
- package/mcp-server/dist/tools/reflect.d.ts.map +1 -0
- package/mcp-server/dist/tools/reflect.js +157 -0
- package/mcp-server/dist/tools/reflect.js.map +1 -0
- package/mcp-server/dist/tools/remember.d.ts +62 -0
- package/mcp-server/dist/tools/remember.d.ts.map +1 -0
- package/mcp-server/dist/tools/remember.js +201 -0
- package/mcp-server/dist/tools/remember.js.map +1 -0
- package/mcp-server/dist/tools/response.d.ts +23 -0
- package/mcp-server/dist/tools/response.d.ts.map +1 -0
- package/mcp-server/dist/tools/response.js +24 -0
- package/mcp-server/dist/tools/response.js.map +1 -0
- package/mcp-server/dist/tools/restore.d.ts +14 -0
- package/mcp-server/dist/tools/restore.d.ts.map +1 -0
- package/mcp-server/dist/tools/restore.js +23 -0
- package/mcp-server/dist/tools/restore.js.map +1 -0
- package/mcp-server/dist/tools/style-guide-tools.d.ts +51 -0
- package/mcp-server/dist/tools/style-guide-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/style-guide-tools.js +231 -0
- package/mcp-server/dist/tools/style-guide-tools.js.map +1 -0
- package/mcp-server/dist/tools/style-guide.d.ts +8 -0
- package/mcp-server/dist/tools/style-guide.d.ts.map +1 -0
- package/mcp-server/dist/tools/style-guide.js +12 -0
- package/mcp-server/dist/tools/style-guide.js.map +1 -0
- package/mcp-server/dist/tools/sync.d.ts +20 -0
- package/mcp-server/dist/tools/sync.d.ts.map +1 -0
- package/mcp-server/dist/tools/sync.js +156 -0
- package/mcp-server/dist/tools/sync.js.map +1 -0
- package/mcp-server/dist/tools/tictactoe-tools.d.ts +18 -0
- package/mcp-server/dist/tools/tictactoe-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/tictactoe-tools.js +78 -0
- package/mcp-server/dist/tools/tictactoe-tools.js.map +1 -0
- package/mcp-server/dist/tools/tictactoe.d.ts +7 -0
- package/mcp-server/dist/tools/tictactoe.d.ts.map +1 -0
- package/mcp-server/dist/tools/tictactoe.js +11 -0
- package/mcp-server/dist/tools/tictactoe.js.map +1 -0
- package/mcp-server/dist/tools/utils.d.ts +19 -0
- package/mcp-server/dist/tools/utils.d.ts.map +1 -0
- package/mcp-server/dist/tools/utils.js +54 -0
- package/mcp-server/dist/tools/utils.js.map +1 -0
- package/mcp-server/dist/tools/whiteboard-format.d.ts +88 -0
- package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -0
- package/mcp-server/dist/tools/whiteboard-format.js +337 -0
- package/mcp-server/dist/tools/whiteboard-format.js.map +1 -0
- package/mcp-server/dist/tools/whiteboard-tools.d.ts +326 -0
- package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/whiteboard-tools.js +222 -0
- package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -0
- package/mcp-server/dist/tools/whiteboard.d.ts +8 -0
- package/mcp-server/dist/tools/whiteboard.d.ts.map +1 -0
- package/mcp-server/dist/tools/whiteboard.js +16 -0
- package/mcp-server/dist/tools/whiteboard.js.map +1 -0
- package/mcp-server/dist/tools/youtube/analytics.d.ts +46 -0
- package/mcp-server/dist/tools/youtube/analytics.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/analytics.js +83 -0
- package/mcp-server/dist/tools/youtube/analytics.js.map +1 -0
- package/mcp-server/dist/tools/youtube/dedup.d.ts +35 -0
- package/mcp-server/dist/tools/youtube/dedup.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/dedup.js +56 -0
- package/mcp-server/dist/tools/youtube/dedup.js.map +1 -0
- package/mcp-server/dist/tools/youtube/download.d.ts +31 -0
- package/mcp-server/dist/tools/youtube/download.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/download.js +30 -0
- package/mcp-server/dist/tools/youtube/download.js.map +1 -0
- package/mcp-server/dist/tools/youtube/helpers.d.ts +66 -0
- package/mcp-server/dist/tools/youtube/helpers.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/helpers.js +143 -0
- package/mcp-server/dist/tools/youtube/helpers.js.map +1 -0
- package/mcp-server/dist/tools/youtube/media.d.ts +43 -0
- package/mcp-server/dist/tools/youtube/media.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/media.js +97 -0
- package/mcp-server/dist/tools/youtube/media.js.map +1 -0
- package/mcp-server/dist/tools/youtube/metadata.d.ts +33 -0
- package/mcp-server/dist/tools/youtube/metadata.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/metadata.js +106 -0
- package/mcp-server/dist/tools/youtube/metadata.js.map +1 -0
- package/mcp-server/dist/tools/youtube/navigate.d.ts +30 -0
- package/mcp-server/dist/tools/youtube/navigate.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/navigate.js +71 -0
- package/mcp-server/dist/tools/youtube/navigate.js.map +1 -0
- package/mcp-server/dist/tools/youtube/playlist.d.ts +29 -0
- package/mcp-server/dist/tools/youtube/playlist.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/playlist.js +128 -0
- package/mcp-server/dist/tools/youtube/playlist.js.map +1 -0
- package/mcp-server/dist/tools/youtube/schedule.d.ts +31 -0
- package/mcp-server/dist/tools/youtube/schedule.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/schedule.js +147 -0
- package/mcp-server/dist/tools/youtube/schedule.js.map +1 -0
- package/mcp-server/dist/tools/youtube/source.d.ts +36 -0
- package/mcp-server/dist/tools/youtube/source.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/source.js +85 -0
- package/mcp-server/dist/tools/youtube/source.js.map +1 -0
- package/mcp-server/dist/tools/youtube/upload.d.ts +53 -0
- package/mcp-server/dist/tools/youtube/upload.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube/upload.js +255 -0
- package/mcp-server/dist/tools/youtube/upload.js.map +1 -0
- package/mcp-server/dist/tools/youtube.d.ts +12 -0
- package/mcp-server/dist/tools/youtube.d.ts.map +1 -0
- package/mcp-server/dist/tools/youtube.js +38 -0
- package/mcp-server/dist/tools/youtube.js.map +1 -0
- package/mcp-server/dist/tui.d.ts +3 -0
- package/mcp-server/dist/tui.d.ts.map +1 -0
- package/mcp-server/dist/tui.js +806 -0
- package/mcp-server/dist/tui.js.map +1 -0
- package/mcp-server/dist/types.d.ts +77 -0
- package/mcp-server/dist/types.d.ts.map +1 -0
- package/mcp-server/dist/types.js +2 -0
- package/mcp-server/dist/types.js.map +1 -0
- package/mcp-server/package-lock.json +4798 -0
- package/mcp-server/package.json +55 -38
- package/mcp-server/run.mjs +12 -2
- package/mcp-server/src/config.ts +48 -3
- package/mcp-server/src/http.ts +296 -93
- package/mcp-server/src/index.ts +546 -203
- package/mcp-server/src/preload-http.ts +19 -18
- package/mcp-server/src/preload.ts +19 -18
- package/mcp-server/src/scripts/setup-embeddings.ts +9 -0
- package/mcp-server/src/services/assistant-judgments.ts +157 -0
- package/mcp-server/src/services/browser-assist-gate.ts +383 -0
- package/mcp-server/src/services/browser-assist.ts +267 -0
- package/mcp-server/src/services/browser-bench.ts +477 -0
- package/mcp-server/src/services/browser-judgments.ts +414 -0
- package/mcp-server/src/services/browser-risk.ts +484 -0
- package/mcp-server/src/services/categories.ts +36 -19
- package/mcp-server/src/services/codex-config-heal.ts +403 -0
- package/mcp-server/src/services/desktop-assist-gate.ts +251 -0
- package/mcp-server/src/services/desktop-assist.ts +308 -0
- package/mcp-server/src/services/desktop-bench.ts +372 -0
- package/mcp-server/src/services/desktop-client.ts +76 -0
- package/mcp-server/src/services/desktop-judgments.ts +218 -0
- package/mcp-server/src/services/desktop-risk.ts +743 -0
- package/mcp-server/src/services/edit-stale.ts +299 -0
- package/mcp-server/src/services/embedding-service.ts +108 -0
- package/mcp-server/src/services/embedding-worker.ts +46 -0
- package/mcp-server/src/services/fb-regions.ts +221 -0
- package/mcp-server/src/services/file-checksums.ts +26 -9
- package/mcp-server/src/services/file-excerpt.ts +59 -0
- package/mcp-server/src/services/identity.ts +291 -0
- package/mcp-server/src/services/local-embeddings.ts +2 -77
- package/mcp-server/src/services/memory-client.ts +23 -0
- package/mcp-server/src/services/memory-judge-backfill.ts +462 -0
- package/mcp-server/src/services/memory-judgments.ts +901 -0
- package/mcp-server/src/services/memory-maintenance.ts +360 -0
- package/mcp-server/src/services/memory-retrieval.ts +349 -0
- package/mcp-server/src/services/memory-schema.ts +280 -0
- package/mcp-server/src/services/memory-sessions.ts +87 -0
- package/mcp-server/src/services/memory-triage.ts +182 -0
- package/mcp-server/src/services/memory-verification.ts +68 -0
- package/mcp-server/src/services/memory-writer.ts +125 -0
- package/mcp-server/src/services/neural-interface.ts +1217 -73
- package/mcp-server/src/services/profiles.ts +428 -0
- package/mcp-server/src/services/secret-gate.ts +52 -0
- package/mcp-server/src/services/server-instructions.ts +122 -0
- package/mcp-server/src/services/sqlite.ts +1456 -823
- package/mcp-server/src/services/typesafe-bench.ts +247 -0
- package/mcp-server/src/services/typesafe-config.ts +790 -0
- package/mcp-server/src/services/typesafe.ts +390 -0
- package/mcp-server/src/services/vector-cache.ts +255 -0
- package/mcp-server/src/services/whiteboard-geometry.ts +711 -0
- package/mcp-server/src/tools/agents.ts +539 -0
- package/mcp-server/src/tools/bluesky.ts +1186 -0
- package/mcp-server/src/tools/browser-advanced.ts +15 -6
- package/mcp-server/src/tools/browser-batch.ts +178 -0
- package/mcp-server/src/tools/browser-cheatsheet.ts +155 -0
- package/mcp-server/src/tools/browser-interact.ts +362 -255
- package/mcp-server/src/tools/browser-navigate.ts +164 -77
- package/mcp-server/src/tools/browser-observe.ts +2222 -1330
- package/mcp-server/src/tools/browser.ts +181 -107
- package/mcp-server/src/tools/card.ts +7 -5
- package/mcp-server/src/tools/choice.ts +103 -0
- package/mcp-server/src/tools/computer.ts +190 -0
- package/mcp-server/src/tools/discord.ts +10 -23
- package/mcp-server/src/tools/fb-groups.ts +387 -0
- package/mcp-server/src/tools/forget.ts +1 -1
- package/mcp-server/src/tools/git.ts +3 -1
- package/mcp-server/src/tools/gsc/experience.ts +440 -0
- package/mcp-server/src/tools/gsc/helpers.ts +288 -0
- package/mcp-server/src/tools/gsc/indexing.ts +495 -0
- package/mcp-server/src/tools/gsc/inspect.ts +391 -0
- package/mcp-server/src/tools/gsc/navigate.ts +236 -0
- package/mcp-server/src/tools/gsc/performance.ts +352 -0
- package/mcp-server/src/tools/gsc/settings.ts +564 -0
- package/mcp-server/src/tools/gsc.ts +95 -0
- package/mcp-server/src/tools/image.ts +3 -1
- package/mcp-server/src/tools/leonardo-browser-tools.ts +47 -37
- package/mcp-server/src/tools/leonardo.ts +7 -5
- package/mcp-server/src/tools/loop.ts +118 -25
- package/mcp-server/src/tools/memories.ts +65 -5
- package/mcp-server/src/tools/morelogin.ts +81 -0
- package/mcp-server/src/tools/profile.ts +122 -0
- package/mcp-server/src/tools/recall.ts +105 -261
- package/mcp-server/src/tools/reflect.ts +171 -145
- package/mcp-server/src/tools/remember.ts +223 -115
- package/mcp-server/src/tools/style-guide-tools.ts +250 -0
- package/mcp-server/src/tools/style-guide.ts +16 -0
- package/mcp-server/src/tools/sync.ts +66 -9
- package/mcp-server/src/tools/tictactoe.ts +3 -1
- package/mcp-server/src/tools/utils.ts +22 -0
- package/mcp-server/src/tools/whiteboard-format.ts +394 -0
- package/mcp-server/src/tools/whiteboard-tools.ts +191 -183
- package/mcp-server/src/tools/whiteboard.ts +7 -5
- package/mcp-server/src/tools/youtube/analytics.ts +106 -0
- package/mcp-server/src/tools/youtube/dedup.ts +57 -0
- package/mcp-server/src/tools/youtube/download.ts +41 -0
- package/mcp-server/src/tools/youtube/helpers.ts +183 -0
- package/mcp-server/src/tools/youtube/media.ts +109 -0
- package/mcp-server/src/tools/youtube/metadata.ts +112 -0
- package/mcp-server/src/tools/youtube/navigate.ts +81 -0
- package/mcp-server/src/tools/youtube/playlist.ts +134 -0
- package/mcp-server/src/tools/youtube/schedule.ts +158 -0
- package/mcp-server/src/tools/youtube/source.ts +101 -0
- package/mcp-server/src/tools/youtube/upload.ts +296 -0
- package/mcp-server/src/tools/youtube.ts +47 -0
- package/mcp-server/src/tui.ts +8 -9
- package/neural-interface/games/TicTacToe/1.svg +1 -0
- package/neural-interface/games/TicTacToe/2.svg +1 -0
- package/neural-interface/games/TicTacToe/3.svg +1 -0
- package/neural-interface/games/TicTacToe/4.svg +1 -0
- package/neural-interface/games/TicTacToe/5.svg +1 -0
- package/neural-interface/games/TicTacToe/6.svg +1 -0
- package/neural-interface/games/TicTacToe/7.svg +1 -0
- package/neural-interface/games/TicTacToe/8.svg +1 -0
- package/neural-interface/games/TicTacToe/9.svg +1 -0
- package/neural-interface/games/TicTacToe/Board.svg +1 -0
- package/neural-interface/games/TicTacToe/Circle.svg +1 -0
- package/neural-interface/games/TicTacToe/Cross.svg +1 -0
- package/neural-interface/i18n/en.json +7022 -0
- package/neural-interface/i18n/pt-BR.json +7026 -0
- package/neural-interface/lib/assistant-api.js +1005 -0
- package/neural-interface/lib/assistant-attachments.js +121 -0
- package/neural-interface/lib/assistant-brains/claude.js +207 -0
- package/neural-interface/lib/assistant-brains/codex-browser-policy-hook.mjs +43 -0
- package/neural-interface/lib/assistant-brains/codex-route-gate-hook.mjs +56 -0
- package/neural-interface/lib/assistant-brains/codex.js +213 -0
- package/neural-interface/lib/assistant-brains/opencode-browser-policy.js +47 -0
- package/neural-interface/lib/assistant-brains/opencode-route-gate.js +62 -0
- package/neural-interface/lib/assistant-brains/opencode.js +320 -0
- package/neural-interface/lib/assistant-budget.js +318 -0
- package/neural-interface/lib/assistant-catalog.js +731 -0
- package/neural-interface/lib/assistant-clarify.js +664 -0
- package/neural-interface/lib/assistant-config.js +232 -0
- package/neural-interface/lib/assistant-dispatch.js +2744 -0
- package/neural-interface/lib/assistant-envelope.js +582 -0
- package/neural-interface/lib/assistant-evidence.js +236 -0
- package/neural-interface/lib/assistant-hidden-models.js +272 -0
- package/neural-interface/lib/assistant-jev.js +117 -0
- package/neural-interface/lib/assistant-judgments.js +111 -0
- package/neural-interface/lib/assistant-media.js +335 -0
- package/neural-interface/lib/assistant-memory.js +398 -0
- package/neural-interface/lib/assistant-persona.js +444 -0
- package/neural-interface/lib/assistant-plan-permissions.js +448 -0
- package/neural-interface/lib/assistant-playbooks/design.md +87 -0
- package/neural-interface/lib/assistant-playbooks.js +72 -0
- package/neural-interface/lib/assistant-pricing.js +159 -0
- package/neural-interface/lib/assistant-route-gate-codex.js +163 -0
- package/neural-interface/lib/assistant-route-gate.js +212 -0
- package/neural-interface/lib/assistant-router.js +1324 -0
- package/neural-interface/lib/assistant-runtime.js +3337 -0
- package/neural-interface/lib/assistant-task-prompt.js +472 -0
- package/neural-interface/lib/assistant-usage.js +1688 -0
- package/neural-interface/lib/augmented-path.js +70 -0
- package/neural-interface/lib/automation-storage-migration.js +54 -0
- package/neural-interface/lib/backup-service.js +851 -0
- package/neural-interface/lib/backup-zip-reader.js +262 -0
- package/neural-interface/lib/browser-assist-api.js +41 -0
- package/neural-interface/lib/browser-console.js +176 -0
- package/neural-interface/lib/browser-execution.js +241 -0
- package/neural-interface/lib/browser-extraction.js +191 -0
- package/neural-interface/lib/browser-language.js +83 -0
- package/neural-interface/lib/browser-screenshot.js +399 -0
- package/neural-interface/lib/browser-semantic-context.js +639 -0
- package/neural-interface/lib/browser-snapshots.js +192 -0
- package/neural-interface/lib/browser-tab-recovery.js +119 -0
- package/neural-interface/lib/browser-targets.js +70 -0
- package/neural-interface/lib/browser-tool-policy.js +926 -0
- package/neural-interface/lib/claude-accounts.js +230 -0
- package/neural-interface/lib/claude-agent-bridge.js +3203 -0
- package/neural-interface/lib/claude-bypass-policy.js +99 -0
- package/neural-interface/lib/claude-executable.js +241 -0
- package/neural-interface/lib/claude-history.js +429 -0
- package/neural-interface/lib/claude-model-catalog.js +444 -0
- package/neural-interface/lib/claude-panel-requests.js +165 -0
- package/neural-interface/lib/claude-panel-session.js +272 -0
- package/neural-interface/lib/claude-permission-rules.js +153 -0
- package/neural-interface/lib/claude-session-cleanup.js +71 -0
- package/neural-interface/lib/claude-session-list.js +82 -0
- package/neural-interface/lib/claude-session-ops.js +140 -0
- package/neural-interface/lib/claude-settings-view.js +51 -0
- package/neural-interface/lib/claude-skin-connect.js +79 -0
- package/neural-interface/lib/claude-stall-policy.js +7 -0
- package/neural-interface/lib/claude-temporary.js +435 -0
- package/neural-interface/lib/cli-update-planner.js +312 -0
- package/neural-interface/lib/codex-capabilities.d.ts +41 -0
- package/neural-interface/lib/codex-capabilities.js +148 -0
- package/neural-interface/lib/codex-collaboration-mode.js +17 -0
- package/neural-interface/lib/codex-compat-rpc.js +241 -0
- package/neural-interface/lib/codex-mcp-approvals.js +56 -0
- package/neural-interface/lib/codex-mcp-apps.js +47 -0
- package/neural-interface/lib/codex-model-context.js +202 -0
- package/neural-interface/lib/codex-plan-store.js +71 -0
- package/neural-interface/lib/codex-request-journal.js +242 -0
- package/neural-interface/lib/codex-runtime-path.js +213 -0
- package/neural-interface/lib/codex-session-catalog.js +231 -0
- package/neural-interface/lib/codex-session-settings.js +46 -0
- package/neural-interface/lib/codex-sidepanel-permissions.js +110 -0
- package/neural-interface/lib/codex-thread-history.js +165 -0
- package/neural-interface/lib/codex-user-verification.js +34 -0
- package/neural-interface/lib/codex-writer-lifecycle.js +152 -0
- package/neural-interface/lib/confined-fs.js +256 -0
- package/neural-interface/lib/db.js +922 -0
- package/neural-interface/lib/design-md.js +9 -0
- package/neural-interface/lib/desktop/api.js +92 -0
- package/neural-interface/lib/desktop/audit.js +62 -0
- package/neural-interface/lib/desktop/build.js +423 -0
- package/neural-interface/lib/desktop/config.js +606 -0
- package/neural-interface/lib/desktop/coords.js +76 -0
- package/neural-interface/lib/desktop/fake-helper.js +1192 -0
- package/neural-interface/lib/desktop/frames.js +77 -0
- package/neural-interface/lib/desktop/grants.js +84 -0
- package/neural-interface/lib/desktop/guards.js +170 -0
- package/neural-interface/lib/desktop/helper/SynabunDesktop.swift +3056 -0
- package/neural-interface/lib/desktop/lease.js +51 -0
- package/neural-interface/lib/desktop/manager.js +545 -0
- package/neural-interface/lib/desktop/press-contexts.js +103 -0
- package/neural-interface/lib/desktop/protocol.js +495 -0
- package/neural-interface/lib/desktop/service.js +1202 -0
- package/neural-interface/lib/effort-levels.js +148 -0
- package/neural-interface/lib/event-loop-monitor.js +67 -0
- package/neural-interface/lib/exec-loop-command.js +209 -0
- package/neural-interface/lib/folder-picker.ps1 +77 -0
- package/neural-interface/lib/http-guards.js +287 -0
- package/neural-interface/lib/jsonl-lines.js +94 -0
- package/neural-interface/lib/loop-logger.js +127 -0
- package/neural-interface/lib/mcp-client-config.js +133 -0
- package/neural-interface/lib/mcp-installer.js +487 -0
- package/neural-interface/lib/mcp-profile-refresh-coordinator.js +78 -0
- package/neural-interface/lib/mcp-profile-servers.js +120 -0
- package/neural-interface/lib/memo-cache.js +84 -0
- package/neural-interface/lib/memory-api.js +758 -0
- package/neural-interface/lib/memory-map-api.js +1150 -0
- package/neural-interface/lib/memory-map-layout.js +872 -0
- package/neural-interface/lib/memory-map-worker.js +165 -0
- package/neural-interface/lib/memory-session-capture.js +81 -0
- package/neural-interface/lib/memory-timers.js +62 -0
- package/neural-interface/lib/morelogin.js +301 -0
- package/neural-interface/lib/native-binary-runtime.js +382 -0
- package/neural-interface/lib/native-loop-goal.js +33 -0
- package/neural-interface/lib/native-loop-providers.js +1002 -0
- package/neural-interface/lib/native-loop-runtime.js +747 -0
- package/neural-interface/lib/offline-page.js +54 -0
- package/neural-interface/lib/opencode-hidden-models.js +113 -0
- package/neural-interface/lib/opencode-history.js +253 -0
- package/neural-interface/lib/opencode-runtime-config.js +58 -0
- package/neural-interface/lib/opencode-v2-client.js +486 -0
- package/neural-interface/lib/opencode-v2-ws-requests.js +955 -0
- package/neural-interface/lib/path-confine.js +213 -0
- package/neural-interface/lib/plugin-installer.js +264 -0
- package/neural-interface/lib/project-storage.js +766 -0
- package/neural-interface/lib/pty-host/core.js +603 -0
- package/neural-interface/lib/pty-host/flow.js +43 -0
- package/neural-interface/lib/pty-host/host.js +47 -0
- package/neural-interface/lib/pty-host/manager.js +360 -0
- package/neural-interface/lib/pty-host/protocol.js +81 -0
- package/neural-interface/lib/pty-host/snapshot.js +133 -0
- package/neural-interface/lib/remote-policy.js +582 -0
- package/neural-interface/lib/rulesets/api.js +175 -0
- package/neural-interface/lib/rulesets/fs-safe.js +245 -0
- package/neural-interface/lib/rulesets/installer.js +1453 -0
- package/neural-interface/lib/rulesets/json-edit.js +186 -0
- package/neural-interface/lib/rulesets/lock.js +170 -0
- package/neural-interface/lib/rulesets/managed-text.js +314 -0
- package/neural-interface/lib/rulesets/normalise.js +24 -0
- package/neural-interface/lib/rulesets/render.js +84 -0
- package/neural-interface/lib/schedule-launch-intent.js +40 -0
- package/neural-interface/lib/session-cache-builder.js +524 -0
- package/neural-interface/lib/session-chunker.js +344 -0
- package/neural-interface/lib/session-indexer.js +327 -0
- package/neural-interface/lib/session-title-generator.js +232 -0
- package/neural-interface/lib/skill-prompt-bridge.js +11 -0
- package/neural-interface/lib/style-guide/api.js +375 -0
- package/neural-interface/lib/style-guide/color.js +352 -0
- package/neural-interface/lib/style-guide/export-css.js +99 -0
- package/neural-interface/lib/style-guide/export-dtcg.js +209 -0
- package/neural-interface/lib/style-guide/export-tailwind.js +102 -0
- package/neural-interface/lib/style-guide/fonts.json +227 -0
- package/neural-interface/lib/style-guide/import.js +1268 -0
- package/neural-interface/lib/style-guide/pointers.js +103 -0
- package/neural-interface/lib/style-guide/presets.js +232 -0
- package/neural-interface/lib/style-guide/render-design-md.js +319 -0
- package/neural-interface/lib/style-guide/schema.js +848 -0
- package/neural-interface/lib/style-guide/security.js +43 -0
- package/neural-interface/lib/style-guide/store.js +491 -0
- package/neural-interface/lib/style-guide/summary.js +106 -0
- package/neural-interface/lib/style-guide/tokens.js +170 -0
- package/neural-interface/lib/synabun-update-plan.js +324 -0
- package/neural-interface/lib/synabun-version.js +179 -0
- package/neural-interface/lib/system-restore.js +99 -0
- package/neural-interface/lib/terminal-env.js +86 -0
- package/neural-interface/lib/ui-blob-store.js +106 -0
- package/neural-interface/lib/vector-cache.js +2 -0
- package/neural-interface/lib/virtual-socket.js +60 -0
- package/neural-interface/lib/whatsapp/api.js +146 -0
- package/neural-interface/lib/whatsapp/auth-store.js +389 -0
- package/neural-interface/lib/whatsapp/baileys-adapter.js +457 -0
- package/neural-interface/lib/whatsapp/brain.js +128 -0
- package/neural-interface/lib/whatsapp/bridge.js +1499 -0
- package/neural-interface/lib/whatsapp/cards.js +519 -0
- package/neural-interface/lib/whatsapp/commands.js +92 -0
- package/neural-interface/lib/whatsapp/config.js +291 -0
- package/neural-interface/lib/whatsapp/connector/entry.mjs +25 -0
- package/neural-interface/lib/whatsapp/connector/manifest.json +6 -0
- package/neural-interface/lib/whatsapp/connector/npm-shrinkwrap.json +717 -0
- package/neural-interface/lib/whatsapp/connector/package.json +8 -0
- package/neural-interface/lib/whatsapp/fake-baileys.js +444 -0
- package/neural-interface/lib/whatsapp/format.js +552 -0
- package/neural-interface/lib/whatsapp/host-core.js +1225 -0
- package/neural-interface/lib/whatsapp/host.js +119 -0
- package/neural-interface/lib/whatsapp/identity.js +288 -0
- package/neural-interface/lib/whatsapp/inbound.js +149 -0
- package/neural-interface/lib/whatsapp/installer.js +562 -0
- package/neural-interface/lib/whatsapp/manager.js +638 -0
- package/neural-interface/lib/whatsapp/paths.js +81 -0
- package/neural-interface/lib/whatsapp/protocol.js +327 -0
- package/neural-interface/lib/whatsapp/qr-svg.js +57 -0
- package/neural-interface/lib/whatsapp/redact.js +130 -0
- package/neural-interface/lib/whatsapp/service.js +1305 -0
- package/neural-interface/lib/whatsapp/vendor/qrcodegen.js +848 -0
- package/neural-interface/package-lock.json +4431 -0
- package/neural-interface/package.json +58 -27
- package/neural-interface/public/apple-touch-icon.png +0 -0
- package/neural-interface/public/category-logos/synabun.png +0 -0
- package/neural-interface/public/claude.svg +1 -0
- package/neural-interface/public/favicon-16x16.png +0 -0
- package/neural-interface/public/favicon-32x32.png +0 -0
- package/neural-interface/public/icon-192.png +0 -0
- package/neural-interface/public/icon-512.png +0 -0
- package/neural-interface/public/index.html +32 -182
- package/neural-interface/public/index2d.html +2 -2
- package/neural-interface/public/install-app.html +31 -0
- package/neural-interface/public/logo-synabun.png +0 -0
- package/neural-interface/public/logoHD.png +0 -0
- package/neural-interface/public/manifest.json +2 -0
- package/neural-interface/public/mcp.svg +4 -0
- package/neural-interface/public/offline.html +670 -299
- package/neural-interface/public/onboarding.html +804 -161
- package/neural-interface/public/opencode-logo-dark-square.svg +1 -0
- package/neural-interface/public/shared/agent-runtime-options.js +596 -0
- package/neural-interface/public/shared/api.js +339 -28
- package/neural-interface/public/shared/assistant/asst-accounts.js +318 -0
- package/neural-interface/public/shared/assistant/asst-agents-dock.js +296 -0
- package/neural-interface/public/shared/assistant/asst-api.js +270 -0
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +744 -0
- package/neural-interface/public/shared/assistant/asst-budget.js +333 -0
- package/neural-interface/public/shared/assistant/asst-composer.js +656 -0
- package/neural-interface/public/shared/assistant/asst-computer.js +803 -0
- package/neural-interface/public/shared/assistant/asst-control.js +1018 -0
- package/neural-interface/public/shared/assistant/asst-hosts.js +262 -0
- package/neural-interface/public/shared/assistant/asst-mascot.js +313 -0
- package/neural-interface/public/shared/assistant/asst-menu.js +375 -0
- package/neural-interface/public/shared/assistant/asst-panel.js +1845 -0
- package/neural-interface/public/shared/assistant/asst-rack-styles.js +586 -0
- package/neural-interface/public/shared/assistant/asst-render.js +3305 -0
- package/neural-interface/public/shared/assistant/asst-route.js +1653 -0
- package/neural-interface/public/shared/assistant/asst-roving.js +75 -0
- package/neural-interface/public/shared/assistant/asst-sanitize.js +117 -0
- package/neural-interface/public/shared/assistant/asst-sidepanel-styles.js +488 -0
- package/neural-interface/public/shared/assistant/asst-sidepanel.js +675 -0
- package/neural-interface/public/shared/assistant/asst-slash.js +258 -0
- package/neural-interface/public/shared/assistant/asst-state.js +727 -0
- package/neural-interface/public/shared/assistant/asst-styles.js +1686 -0
- package/neural-interface/public/shared/assistant/asst-tool-kinds.js +1017 -0
- package/neural-interface/public/shared/assistant/asst-usage.js +444 -0
- package/neural-interface/public/shared/assistant/asst-ws.js +175 -0
- package/neural-interface/public/shared/automation-context.js +75 -0
- package/neural-interface/public/shared/blob-store.js +99 -0
- package/neural-interface/public/shared/cdx/cdx-capabilities.js +118 -0
- package/neural-interface/public/shared/cdx/cdx-cards.js +37 -0
- package/neural-interface/public/shared/cdx/cdx-commands.js +171 -0
- package/neural-interface/public/shared/cdx/cdx-context-menu.js +402 -0
- package/neural-interface/public/shared/cdx/cdx-context-model.js +220 -0
- package/neural-interface/public/shared/cdx/cdx-features.js +408 -0
- package/neural-interface/public/shared/cdx/cdx-icons.js +89 -0
- package/neural-interface/public/shared/cdx/cdx-mcp-app-host.js +414 -0
- package/neural-interface/public/shared/cdx/cdx-mcp-app-proxy.html +6 -0
- package/neural-interface/public/shared/cdx/cdx-mcp-app-proxy.js +56 -0
- package/neural-interface/public/shared/cdx/cdx-mcp-app.js +178 -0
- package/neural-interface/public/shared/cdx/cdx-model-catalog.js +120 -0
- package/neural-interface/public/shared/cdx/cdx-output-model.js +261 -0
- package/neural-interface/public/shared/cdx/cdx-output.js +382 -0
- package/neural-interface/public/shared/cdx/cdx-panel.js +1372 -0
- package/neural-interface/public/shared/cdx/cdx-plan.js +266 -0
- package/neural-interface/public/shared/cdx/cdx-protocol.js +682 -0
- package/neural-interface/public/shared/cdx/cdx-render.js +3381 -0
- package/neural-interface/public/shared/cdx/cdx-requests.js +1136 -0
- package/neural-interface/public/shared/cdx/cdx-styles.js +3251 -0
- package/neural-interface/public/shared/cdx/cdx-tabs.js +7992 -0
- package/neural-interface/public/shared/cdx/cdx-ws.js +363 -0
- package/neural-interface/public/shared/cli-status.js +169 -0
- package/neural-interface/public/shared/command-runner-model.js +30 -0
- package/neural-interface/public/shared/constants.js +22 -5
- package/neural-interface/public/shared/cp/cp-agents.js +186 -0
- package/neural-interface/public/shared/cp/cp-bash.js +252 -0
- package/neural-interface/public/shared/cp/cp-compose.js +159 -0
- package/neural-interface/public/shared/cp/cp-context-menu.js +309 -0
- package/neural-interface/public/shared/cp/cp-context-model.js +157 -0
- package/neural-interface/public/shared/cp/cp-context-window.js +80 -0
- package/neural-interface/public/shared/cp/cp-ctx.js +11 -0
- package/neural-interface/public/shared/cp/cp-diff.js +255 -0
- package/neural-interface/public/shared/cp/cp-event-rows.js +637 -0
- package/neural-interface/public/shared/cp/cp-events.js +846 -0
- package/neural-interface/public/shared/cp/cp-markdown.js +104 -0
- package/neural-interface/public/shared/cp/cp-permission-model.js +905 -0
- package/neural-interface/public/shared/cp/cp-permissions.js +626 -0
- package/neural-interface/public/shared/cp/cp-rehydrate.js +113 -0
- package/neural-interface/public/shared/cp/cp-restore.js +224 -0
- package/neural-interface/public/shared/cp/cp-session-model.js +338 -0
- package/neural-interface/public/shared/cp/cp-session-settings.js +254 -0
- package/neural-interface/public/shared/cp/cp-sessions.js +227 -0
- package/neural-interface/public/shared/cp/cp-statusline.js +153 -0
- package/neural-interface/public/shared/cp/cp-styles.js +349 -0
- package/neural-interface/public/shared/cp/cp-tasks-model.js +282 -0
- package/neural-interface/public/shared/cp/cp-tasks.js +107 -0
- package/neural-interface/public/shared/cp/cp-temporary-view.js +56 -0
- package/neural-interface/public/shared/cp/cp-temporary.js +231 -0
- package/neural-interface/public/shared/cp/cp-tool-cards.js +326 -0
- package/neural-interface/public/shared/cp/cp-tool-results.js +618 -0
- package/neural-interface/public/shared/cp/cp-usage-model.js +124 -0
- package/neural-interface/public/shared/graph-activity.js +68 -0
- package/neural-interface/public/shared/html-shell.js +116 -17
- package/neural-interface/public/shared/i18n.js +132 -34
- package/neural-interface/public/shared/node-positions-store.js +44 -0
- package/neural-interface/public/shared/ocp-hidden-models.js +116 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-approvals.js +355 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-autoaccept-button.js +35 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-automation-ownership.js +72 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-binding.js +280 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-caps.js +67 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-changes-logic.js +179 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-changes.js +164 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +725 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-compact-button.js +75 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-composer-logic.js +1204 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-confirm-logic.js +117 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-confirm.js +59 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-context-gauge.js +252 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-context-menu.js +478 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-context-model.js +179 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-events.js +233 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-icons.js +30 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-manager.js +1065 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-mention-hints.js +182 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-modelpicker.js +655 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +2636 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +601 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-profile-inheritance.js +78 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +649 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-providers.js +35 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +357 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render-logic.js +189 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +1869 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-select.js +42 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send-logic.js +117 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +1714 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-session-actions.js +468 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-session-widgets.js +63 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +366 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-settings-link.js +19 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-slash-hints.js +343 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-state.js +746 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-status-logic.js +347 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-status.js +338 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +3543 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-subagents-logic.js +482 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-tools-logic.js +351 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-tools.js +168 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-variantpicker.js +315 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +545 -0
- package/neural-interface/public/shared/provider-icons.js +30 -0
- package/neural-interface/public/shared/pwa-install-page.js +34 -0
- package/neural-interface/public/shared/pwa-install.css +12 -0
- package/neural-interface/public/shared/pwa-install.js +28 -0
- package/neural-interface/public/shared/session-title.js +100 -0
- package/neural-interface/public/shared/settings/settings-ia.js +389 -0
- package/neural-interface/public/shared/settings/settings-kit.js +234 -0
- package/neural-interface/public/shared/settings/settings-rules.js +160 -0
- package/neural-interface/public/shared/settings/settings-search.js +463 -0
- package/neural-interface/public/shared/settings/settings-shell.js +570 -0
- package/neural-interface/public/shared/start-bridge.js +583 -0
- package/neural-interface/public/shared/state.js +5 -0
- package/neural-interface/public/shared/storage.js +50 -7
- package/neural-interface/public/shared/styleguide/sg-agents.js +42 -0
- package/neural-interface/public/shared/styleguide/sg-brand.js +4 -0
- package/neural-interface/public/shared/styleguide/sg-color-client.js +388 -0
- package/neural-interface/public/shared/styleguide/sg-colors.js +151 -0
- package/neural-interface/public/shared/styleguide/sg-components.js +35 -0
- package/neural-interface/public/shared/styleguide/sg-history.js +41 -0
- package/neural-interface/public/shared/styleguide/sg-icons-logo.js +38 -0
- package/neural-interface/public/shared/styleguide/sg-imagery.js +4 -0
- package/neural-interface/public/shared/styleguide/sg-import-export.js +48 -0
- package/neural-interface/public/shared/styleguide/sg-kit.js +284 -0
- package/neural-interface/public/shared/styleguide/sg-labels.js +318 -0
- package/neural-interface/public/shared/styleguide/sg-layout.js +4 -0
- package/neural-interface/public/shared/styleguide/sg-motion.js +5 -0
- package/neural-interface/public/shared/styleguide/sg-panel.js +237 -0
- package/neural-interface/public/shared/styleguide/sg-preview.js +138 -0
- package/neural-interface/public/shared/styleguide/sg-rules.js +9 -0
- package/neural-interface/public/shared/styleguide/sg-shape.js +24 -0
- package/neural-interface/public/shared/styleguide/sg-state.js +132 -0
- package/neural-interface/public/shared/styleguide/sg-typography.js +125 -0
- package/neural-interface/public/shared/styles.css +8614 -1477
- package/neural-interface/public/shared/synabun-mascot.js +1625 -0
- package/neural-interface/public/shared/synabun-ticker.js +376 -0
- package/neural-interface/public/shared/term-ready.js +307 -0
- package/neural-interface/public/shared/term-renderer.js +343 -0
- package/neural-interface/public/shared/ui-assistant-panel.js +10 -0
- package/neural-interface/public/shared/ui-assistant.js +77 -0
- package/neural-interface/public/shared/ui-automation-studio.js +5105 -3573
- package/neural-interface/public/shared/ui-claude-panel.js +11685 -6333
- package/neural-interface/public/shared/ui-codex-panel.js +12 -0
- package/neural-interface/public/shared/ui-command-runner.js +251 -468
- package/neural-interface/public/shared/ui-cost-widget.js +55 -34
- package/neural-interface/public/shared/ui-detail.js +77 -14
- package/neural-interface/public/shared/ui-explorer.js +360 -181
- package/neural-interface/public/shared/ui-file-explorer.js +485 -107
- package/neural-interface/public/shared/ui-help.js +2 -2
- package/neural-interface/public/shared/ui-image-gallery.js +45 -21
- package/neural-interface/public/shared/ui-judgments.js +1346 -0
- package/neural-interface/public/shared/ui-keybinds.js +3 -2
- package/neural-interface/public/shared/ui-link.js +105 -51
- package/neural-interface/public/shared/ui-loading.js +222 -11
- package/neural-interface/public/shared/ui-memory-maintenance.js +111 -0
- package/neural-interface/public/shared/ui-menubar.js +100 -31
- package/neural-interface/public/shared/ui-native-loop-router-state.js +94 -0
- package/neural-interface/public/shared/ui-native-loop-router.js +493 -0
- package/neural-interface/public/shared/ui-native-window-id.js +7 -0
- package/neural-interface/public/shared/ui-navbar.js +357 -222
- package/neural-interface/public/shared/ui-notifications.js +58 -12
- package/neural-interface/public/shared/ui-opencode-panel-v2.js +17 -0
- package/neural-interface/public/shared/ui-panels.js +15 -7
- package/neural-interface/public/shared/ui-resume.js +823 -653
- package/neural-interface/public/shared/ui-schedule-queue.js +172 -0
- package/neural-interface/public/shared/ui-schedules-studio.js +1882 -0
- package/neural-interface/public/shared/ui-scroll-follow.js +194 -0
- package/neural-interface/public/shared/ui-sessions.js +789 -34
- package/neural-interface/public/shared/ui-settings.js +5774 -2194
- package/neural-interface/public/shared/ui-sidepanel-layout.js +109 -0
- package/neural-interface/public/shared/ui-sidepanel-runtime.js +19 -0
- package/neural-interface/public/shared/ui-sidepanel-session-entry.js +40 -0
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +221 -0
- package/neural-interface/public/shared/ui-sidepanel-state.js +131 -0
- package/neural-interface/public/shared/ui-sidepanel-tray.js +547 -0
- package/neural-interface/public/shared/ui-sidepanel-windows.js +387 -0
- package/neural-interface/public/shared/ui-skills.js +18 -32
- package/neural-interface/public/shared/ui-styleguide.js +35 -0
- package/neural-interface/public/shared/ui-sync.js +87 -0
- package/neural-interface/public/shared/ui-terminal.js +7863 -6385
- package/neural-interface/public/shared/ui-tool-updates.js +292 -0
- package/neural-interface/public/shared/ui-tooltip.js +156 -15
- package/neural-interface/public/shared/ui-tutorial-draw.js +119 -683
- package/neural-interface/public/shared/ui-tutorial-layout.js +135 -0
- package/neural-interface/public/shared/ui-tutorial-steps.js +59 -2209
- package/neural-interface/public/shared/ui-tutorial.css +102 -0
- package/neural-interface/public/shared/ui-tutorial.js +557 -1076
- package/neural-interface/public/shared/ui-update.js +420 -68
- package/neural-interface/public/shared/ui-whatsapp.js +941 -0
- package/neural-interface/public/shared/ui-whiteboard.js +1076 -233
- package/neural-interface/public/shared/ui-workspaces.js +2 -1
- package/neural-interface/public/shared/utils.js +58 -0
- package/neural-interface/public/shared/vterm-buffer.js +15 -5
- package/neural-interface/public/shared/whatsapp/wa-phone.js +65 -0
- package/neural-interface/public/shared/whatsapp/wa-view.js +411 -0
- package/neural-interface/public/sidepanel-session.html +18 -0
- package/neural-interface/public/sw.js +10 -2
- package/neural-interface/public/synabun.png +0 -0
- package/neural-interface/public/variant/2d/graph.js +1707 -1635
- package/neural-interface/public/variant/2d/lasso.js +2 -1
- package/neural-interface/public/variant/2d/layout.js +595 -594
- package/neural-interface/public/variant/2d/main.js +557 -521
- package/neural-interface/public/variant/2d/settings-gfx.js +18 -24
- package/neural-interface/public/variant/3d/main.js +517 -500
- package/neural-interface/public/variant/3d/map-controls.js +144 -0
- package/neural-interface/public/variant/3d/map-data.js +251 -0
- package/neural-interface/public/variant/3d/map-labels.js +241 -0
- package/neural-interface/public/variant/3d/map-pick.js +90 -0
- package/neural-interface/public/variant/3d/map-renderer.js +521 -0
- package/neural-interface/public/variant/3d/map-shaders.js +158 -0
- package/neural-interface/public/variant/3d/map-view.js +618 -0
- package/neural-interface/public/vendor/three/manifest.json +3 -0
- package/neural-interface/public/vendor/three/three-0.169.0.min.js +3844 -0
- package/neural-interface/public/vendor/xterm/manifest.json +3 -0
- package/neural-interface/public/vendor/xterm/xterm-6.0.0.css +285 -0
- package/neural-interface/public/vendor/xterm/xterm-6.0.0.min.js +192 -0
- package/neural-interface/scripts/build-vendor.mjs +64 -0
- package/neural-interface/scripts/codex-protocol-fixture.mjs +83 -0
- package/neural-interface/scripts/rebuild-pty.js +39 -22
- package/neural-interface/scripts/vendor-three-entry.js +24 -0
- package/neural-interface/scripts/vendor-xterm-entry.js +8 -0
- package/neural-interface/server.js +33983 -15000
- package/neural-interface/skins/default/skin.css +90 -0
- package/neural-interface/skins/default/skin.json +8 -0
- package/neural-interface/templates/rulesets/README.md +9 -0
- package/neural-interface/templates/rulesets/claude.md +3 -0
- package/neural-interface/templates/rulesets/codex.md +2 -0
- package/neural-interface/templates/rulesets/coexistence.md +6 -0
- package/neural-interface/templates/rulesets/core.md +26 -0
- package/neural-interface/templates/rulesets/cursor.md +2 -0
- package/neural-interface/templates/rulesets/gemini.md +2 -0
- package/neural-interface/templates/rulesets/legacy-hashes.json +227 -0
- package/neural-interface/templates/rulesets/manifest.json +12 -0
- package/neural-interface/templates/rulesets/opencode.md +2 -0
- package/package.json +131 -53
- package/postinstall.js +55 -26
- package/preuninstall.js +187 -0
- package/scripts/restore-data-home-from-backup.mjs +239 -0
- package/setup.js +872 -260
- package/skills/leonardo/SKILL.md +19 -10
- package/skills/leonardo/modules/image-prompter.md +18 -12
- package/skills/leonardo/modules/video-prompter.md +19 -13
- package/skills/synabun/SKILL.md +209 -185
- package/skills/synabun/icon.png +0 -0
- package/skills/synabun/modules/audit.md +380 -374
- package/skills/synabun/modules/changelog.md +15 -6
- package/skills/synabun/modules/idea.md +148 -144
- package/skills/synabun/modules/memorize.md +13 -4
- package/skills/synabun/modules/schedule.md +198 -0
- package/skills/synabun/synabunicon.png +0 -0
- package/updater.cmd +31 -0
- package/updater.mjs +382 -0
- package/updater.sh +29 -0
- package/hooks/claude-code/test-user-learning.mjs +0 -531
- package/neural-interface/public/claude-chat.css +0 -878
- package/neural-interface/public/claude-chat.html +0 -92
- package/neural-interface/public/claude-chat.js +0 -1168
- package/neural-interface/public/index-legacy.html +0 -14677
- package/neural-interface/public/index2d-legacy.html +0 -8193
- package/neural-interface/public/shared/html-term-renderer.js +0 -1022
- package/neural-interface/public/variant/3d/background.js +0 -884
- package/neural-interface/public/variant/3d/camera.js +0 -661
- package/neural-interface/public/variant/3d/gfx.js +0 -116
- package/neural-interface/public/variant/3d/graph.js +0 -2399
- package/neural-interface/public/variant/3d/settings-gfx.js +0 -228
- package/neural-interface/templates/CLAUDE-template.md +0 -211
|
@@ -0,0 +1,1185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite storage layer.
|
|
3
|
+
* Uses Node.js built-in node:sqlite (available since Node 22.5.0).
|
|
4
|
+
* Vectors stored as Float32Array BLOBs, cosine similarity computed in JS.
|
|
5
|
+
*/
|
|
6
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
7
|
+
import { randomUUID } from 'node:crypto';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
import os from 'os';
|
|
11
|
+
import { config } from '../config.js';
|
|
12
|
+
import { getAllCategories } from './categories.js';
|
|
13
|
+
import { VectorCache } from './vector-cache.js';
|
|
14
|
+
import { migrateMemory } from './memory-schema.js';
|
|
15
|
+
import { REGION_BY_CURRENCY, resolveClassification } from './fb-regions.js';
|
|
16
|
+
// Re-export for backward compat (was used by categories.ts)
|
|
17
|
+
export const CATEGORIES_POINT_ID = '00000000-0000-0000-0000-000000000000';
|
|
18
|
+
let db = null;
|
|
19
|
+
export function getDbPath() {
|
|
20
|
+
const envPath = process.env.SQLITE_DB_PATH;
|
|
21
|
+
const defaultPath = path.join(config.dataDir, 'memory.db');
|
|
22
|
+
if (!envPath)
|
|
23
|
+
return defaultPath;
|
|
24
|
+
// If the env path's parent directory doesn't exist (e.g. Windows path on Mac),
|
|
25
|
+
// fall back to the local default so cross-OS restores work instantly
|
|
26
|
+
if (!fs.existsSync(path.dirname(envPath)))
|
|
27
|
+
return defaultPath;
|
|
28
|
+
return envPath;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Refuse to open a store outside the temp directory while tests are running.
|
|
32
|
+
*
|
|
33
|
+
* On 2026-09-18 `npm test` deleted all 24,346 live memories: `tests/setup.ts`
|
|
34
|
+
* redirects SQLITE_DB_PATH at a temp dir, but it only runs if a vitest config
|
|
35
|
+
* lists it under `setupFiles`, and it wasn't wired in. `memory-v2.test.ts`
|
|
36
|
+
* opens with `DELETE FROM memories`, so the damage was silent and total.
|
|
37
|
+
*
|
|
38
|
+
* This lives here rather than in setup.ts deliberately: a guard inside the
|
|
39
|
+
* setup file cannot fire when the setup file is the thing that didn't run.
|
|
40
|
+
* It also catches the quieter path — getDbPath() falls back to the default
|
|
41
|
+
* live store whenever the env path's parent directory is missing, so a typo'd
|
|
42
|
+
* SQLITE_DB_PATH silently aims at production.
|
|
43
|
+
*
|
|
44
|
+
* `node --test` sets NODE_TEST_CONTEXT in every test-file process and the
|
|
45
|
+
* processes it spawns; the Neural Interface suites import this module through
|
|
46
|
+
* dist and would otherwise migrate the live store on their first getDb().
|
|
47
|
+
*/
|
|
48
|
+
function assertTestDbIsDisposable(dbPath) {
|
|
49
|
+
if ((!process.env.VITEST && !process.env.NODE_TEST_CONTEXT) || dbPath === ':memory:')
|
|
50
|
+
return;
|
|
51
|
+
// os.tmpdir() is /var/folders/... on macOS, so an explicit /tmp path is
|
|
52
|
+
// legitimate but would not match it. Resolve symlinks on both sides too:
|
|
53
|
+
// /tmp is a link to /private/tmp, and os.tmpdir() to /private/var/folders/...
|
|
54
|
+
const real = (p) => { try {
|
|
55
|
+
return fs.realpathSync(p);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return p;
|
|
59
|
+
} };
|
|
60
|
+
const roots = new Set([os.tmpdir(), '/tmp'].flatMap(r => [r, real(r)]));
|
|
61
|
+
const under = (child, root) => child === root || child.startsWith(root.endsWith(path.sep) ? root : root + path.sep);
|
|
62
|
+
const resolved = path.resolve(dbPath);
|
|
63
|
+
const resolvedReal = real(path.dirname(resolved)) + path.sep + path.basename(resolved);
|
|
64
|
+
for (const root of roots)
|
|
65
|
+
if (under(resolved, root) || under(resolvedReal, root))
|
|
66
|
+
return;
|
|
67
|
+
throw new Error(`Refusing to open ${dbPath} under a test runner — a test database must live under ${os.tmpdir()} or /tmp. ` +
|
|
68
|
+
'Check that vitest.config.ts still lists setupFiles: [\'tests/setup.ts\'], and that ' +
|
|
69
|
+
'SQLITE_DB_PATH points at a directory that exists (getDbPath falls back to the live ' +
|
|
70
|
+
'store when the parent is missing).');
|
|
71
|
+
}
|
|
72
|
+
export function getDb() {
|
|
73
|
+
if (!db) {
|
|
74
|
+
const dbPath = getDbPath();
|
|
75
|
+
assertTestDbIsDisposable(dbPath);
|
|
76
|
+
if (dbPath !== ':memory:')
|
|
77
|
+
fs.mkdirSync(path.dirname(dbPath), { recursive: true });
|
|
78
|
+
db = new DatabaseSync(dbPath);
|
|
79
|
+
db.exec('PRAGMA busy_timeout = 5000');
|
|
80
|
+
db.exec('PRAGMA journal_mode = WAL');
|
|
81
|
+
db.exec('PRAGMA foreign_keys = ON');
|
|
82
|
+
db.exec('PRAGMA recursive_triggers = ON');
|
|
83
|
+
try {
|
|
84
|
+
db.exec(SCHEMA_SQL);
|
|
85
|
+
db.exec(FB_SCHEMA_SQL);
|
|
86
|
+
db.exec(FTS_SQL);
|
|
87
|
+
migrateMemory(db, dbPath);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
db.close();
|
|
91
|
+
db = null;
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return db;
|
|
96
|
+
}
|
|
97
|
+
// --- In-memory vector caches (see vector-cache.ts for coherence model) ---
|
|
98
|
+
export const memoryVectors = new VectorCache(getDb, 'SELECT id, vector FROM memories WHERE trashed_at IS NULL', 'SELECT vector FROM memories WHERE id = ? AND trashed_at IS NULL', 'memories');
|
|
99
|
+
export const chunkVectors = new VectorCache(getDb, 'SELECT id, vector FROM session_chunks', 'SELECT vector FROM session_chunks WHERE id = ?', 'session_chunks');
|
|
100
|
+
// --- Vector encoding/decoding ---
|
|
101
|
+
function encodeVector(vector) {
|
|
102
|
+
const f32 = new Float32Array(vector);
|
|
103
|
+
return new Uint8Array(f32.buffer);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Translates JSON filters to SQL WHERE clauses.
|
|
107
|
+
* Supports: exact match, range, tags (JSON array contains), is_empty.
|
|
108
|
+
*/
|
|
109
|
+
function translateFilter(filter) {
|
|
110
|
+
if (!filter)
|
|
111
|
+
return { where: '', params: [] };
|
|
112
|
+
const f = filter;
|
|
113
|
+
const clauses = [];
|
|
114
|
+
const params = [];
|
|
115
|
+
for (const cond of f.must || []) {
|
|
116
|
+
if (cond.match) {
|
|
117
|
+
if (cond.key === 'tags') {
|
|
118
|
+
clauses.push(`EXISTS (SELECT 1 FROM json_each(tags) WHERE json_each.value = ?)`);
|
|
119
|
+
params.push(cond.match.value);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
clauses.push(`${sanitizeColumn(cond.key)} = ?`);
|
|
123
|
+
params.push(cond.match.value);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else if (cond.range) {
|
|
127
|
+
const col = sanitizeColumn(cond.key);
|
|
128
|
+
if (cond.range.gte !== undefined) {
|
|
129
|
+
clauses.push(`${col} >= ?`);
|
|
130
|
+
params.push(cond.range.gte);
|
|
131
|
+
}
|
|
132
|
+
if (cond.range.lte !== undefined) {
|
|
133
|
+
clauses.push(`${col} <= ?`);
|
|
134
|
+
params.push(cond.range.lte);
|
|
135
|
+
}
|
|
136
|
+
if (cond.range.gt !== undefined) {
|
|
137
|
+
clauses.push(`${col} > ?`);
|
|
138
|
+
params.push(cond.range.gt);
|
|
139
|
+
}
|
|
140
|
+
if (cond.range.lt !== undefined) {
|
|
141
|
+
clauses.push(`${col} < ?`);
|
|
142
|
+
params.push(cond.range.lt);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else if (cond.is_empty) {
|
|
146
|
+
clauses.push(`(${sanitizeColumn(cond.is_empty.key)} IS NULL OR ${sanitizeColumn(cond.is_empty.key)} = '')`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const alternatives = (f.should || []).filter(c => c.key === 'tags' && c.match).map(c => {
|
|
150
|
+
params.push(c.match.value);
|
|
151
|
+
return 'EXISTS (SELECT 1 FROM json_each(tags) WHERE json_each.value = ?)';
|
|
152
|
+
});
|
|
153
|
+
if (alternatives.length)
|
|
154
|
+
clauses.push('(' + alternatives.join(' OR ') + ')');
|
|
155
|
+
for (const cond of f.must_not || []) {
|
|
156
|
+
if (cond.match) {
|
|
157
|
+
clauses.push(`(${sanitizeColumn(cond.key)} IS NULL OR ${sanitizeColumn(cond.key)} != ?)`);
|
|
158
|
+
params.push(cond.match.value);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
where: clauses.length > 0 ? ' AND ' + clauses.join(' AND ') : '',
|
|
163
|
+
params,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
/** Allowlist of valid column names to prevent SQL injection */
|
|
167
|
+
const VALID_COLUMNS = new Set([
|
|
168
|
+
'id', 'content', 'category', 'subcategory', 'project', 'tags', 'importance',
|
|
169
|
+
'source', 'created_at', 'updated_at', 'accessed_at', 'access_count',
|
|
170
|
+
'related_files', 'related_memory_ids', 'file_checksums', 'trashed_at',
|
|
171
|
+
'source_session_chunks', '_type',
|
|
172
|
+
// session_chunks columns
|
|
173
|
+
'session_id', 'git_branch', 'cwd', 'chunk_index', 'start_timestamp',
|
|
174
|
+
'end_timestamp', 'tools_used', 'files_modified', 'files_read',
|
|
175
|
+
'user_messages', 'turn_count', 'dedup_memory_id', 'indexed_at', 'summary',
|
|
176
|
+
]);
|
|
177
|
+
function sanitizeColumn(name) {
|
|
178
|
+
if (!VALID_COLUMNS.has(name)) {
|
|
179
|
+
throw new Error(`Invalid column name: ${name}`);
|
|
180
|
+
}
|
|
181
|
+
return name;
|
|
182
|
+
}
|
|
183
|
+
// --- Schema initialization ---
|
|
184
|
+
const SCHEMA_SQL = `
|
|
185
|
+
CREATE TABLE IF NOT EXISTS memories (
|
|
186
|
+
id TEXT PRIMARY KEY,
|
|
187
|
+
vector BLOB NOT NULL,
|
|
188
|
+
content TEXT NOT NULL,
|
|
189
|
+
category TEXT NOT NULL,
|
|
190
|
+
subcategory TEXT,
|
|
191
|
+
project TEXT NOT NULL,
|
|
192
|
+
tags TEXT NOT NULL DEFAULT '[]',
|
|
193
|
+
importance INTEGER NOT NULL DEFAULT 5,
|
|
194
|
+
source TEXT NOT NULL DEFAULT 'self-discovered',
|
|
195
|
+
created_at TEXT NOT NULL,
|
|
196
|
+
updated_at TEXT NOT NULL,
|
|
197
|
+
accessed_at TEXT NOT NULL,
|
|
198
|
+
access_count INTEGER NOT NULL DEFAULT 0,
|
|
199
|
+
related_files TEXT,
|
|
200
|
+
related_memory_ids TEXT,
|
|
201
|
+
file_checksums TEXT,
|
|
202
|
+
trashed_at TEXT,
|
|
203
|
+
source_session_chunks TEXT
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
CREATE TABLE IF NOT EXISTS session_chunks (
|
|
207
|
+
id TEXT PRIMARY KEY,
|
|
208
|
+
vector BLOB NOT NULL,
|
|
209
|
+
content TEXT NOT NULL,
|
|
210
|
+
summary TEXT,
|
|
211
|
+
session_id TEXT,
|
|
212
|
+
project TEXT,
|
|
213
|
+
git_branch TEXT,
|
|
214
|
+
cwd TEXT,
|
|
215
|
+
chunk_index INTEGER DEFAULT 0,
|
|
216
|
+
start_timestamp TEXT,
|
|
217
|
+
end_timestamp TEXT,
|
|
218
|
+
tools_used TEXT DEFAULT '[]',
|
|
219
|
+
files_modified TEXT DEFAULT '[]',
|
|
220
|
+
files_read TEXT DEFAULT '[]',
|
|
221
|
+
user_messages TEXT DEFAULT '[]',
|
|
222
|
+
turn_count INTEGER DEFAULT 0,
|
|
223
|
+
related_memory_ids TEXT DEFAULT '[]',
|
|
224
|
+
dedup_memory_id TEXT,
|
|
225
|
+
indexed_at TEXT
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
CREATE TABLE IF NOT EXISTS categories (
|
|
229
|
+
name TEXT PRIMARY KEY,
|
|
230
|
+
description TEXT NOT NULL,
|
|
231
|
+
created_at TEXT NOT NULL,
|
|
232
|
+
parent TEXT,
|
|
233
|
+
color TEXT,
|
|
234
|
+
is_parent INTEGER DEFAULT 0
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
CREATE INDEX IF NOT EXISTS idx_mem_category ON memories(category);
|
|
238
|
+
CREATE INDEX IF NOT EXISTS idx_mem_project ON memories(project);
|
|
239
|
+
CREATE INDEX IF NOT EXISTS idx_mem_importance ON memories(importance);
|
|
240
|
+
CREATE INDEX IF NOT EXISTS idx_mem_trashed ON memories(trashed_at);
|
|
241
|
+
CREATE INDEX IF NOT EXISTS idx_mem_created ON memories(created_at);
|
|
242
|
+
CREATE INDEX IF NOT EXISTS idx_mem_source ON memories(source);
|
|
243
|
+
CREATE INDEX IF NOT EXISTS idx_sc_session ON session_chunks(session_id);
|
|
244
|
+
CREATE INDEX IF NOT EXISTS idx_sc_project ON session_chunks(project);
|
|
245
|
+
CREATE INDEX IF NOT EXISTS idx_sc_branch ON session_chunks(git_branch);
|
|
246
|
+
|
|
247
|
+
CREATE TABLE IF NOT EXISTS kv_config (
|
|
248
|
+
key TEXT PRIMARY KEY,
|
|
249
|
+
value TEXT NOT NULL
|
|
250
|
+
);
|
|
251
|
+
`;
|
|
252
|
+
// FTS5 created separately since CREATE VIRTUAL TABLE IF NOT EXISTS
|
|
253
|
+
// can fail silently on some SQLite versions
|
|
254
|
+
const FTS_SQL = `
|
|
255
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
|
|
256
|
+
content, category, project, tags,
|
|
257
|
+
content=memories, content_rowid=rowid,
|
|
258
|
+
tokenize='porter unicode61'
|
|
259
|
+
);
|
|
260
|
+
`;
|
|
261
|
+
// Facebook group directory — structured single source of truth for the group
|
|
262
|
+
// collection. One row per group (fb_groups), one append-only row per posting event
|
|
263
|
+
// (fb_post_log). Replaces a single-text seed-queue memory, which one whole-body
|
|
264
|
+
// reflect() can overwrite; atomic per-row writes make that data-loss class impossible.
|
|
265
|
+
const FB_SCHEMA_SQL = `
|
|
266
|
+
CREATE TABLE IF NOT EXISTS fb_groups (
|
|
267
|
+
url TEXT PRIMARY KEY,
|
|
268
|
+
name TEXT NOT NULL DEFAULT '',
|
|
269
|
+
region TEXT,
|
|
270
|
+
country TEXT,
|
|
271
|
+
lang TEXT,
|
|
272
|
+
currency TEXT,
|
|
273
|
+
joined INTEGER NOT NULL DEFAULT 1,
|
|
274
|
+
allows_promo TEXT NOT NULL DEFAULT 'unknown',
|
|
275
|
+
member_count INTEGER,
|
|
276
|
+
pending_since TEXT,
|
|
277
|
+
cooldown_until TEXT,
|
|
278
|
+
last_status TEXT,
|
|
279
|
+
last_error TEXT,
|
|
280
|
+
notes TEXT,
|
|
281
|
+
source TEXT NOT NULL DEFAULT 'import',
|
|
282
|
+
added_at TEXT NOT NULL,
|
|
283
|
+
updated_at TEXT NOT NULL
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
CREATE TABLE IF NOT EXISTS fb_post_log (
|
|
287
|
+
id TEXT PRIMARY KEY,
|
|
288
|
+
group_url TEXT NOT NULL,
|
|
289
|
+
offer_slug TEXT NOT NULL,
|
|
290
|
+
currency TEXT,
|
|
291
|
+
status TEXT NOT NULL,
|
|
292
|
+
post_url TEXT,
|
|
293
|
+
session_id TEXT,
|
|
294
|
+
posted_at TEXT NOT NULL,
|
|
295
|
+
note TEXT
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
CREATE INDEX IF NOT EXISTS idx_fbg_region ON fb_groups(region);
|
|
299
|
+
CREATE INDEX IF NOT EXISTS idx_fbg_joined ON fb_groups(joined);
|
|
300
|
+
CREATE INDEX IF NOT EXISTS idx_fbg_promo ON fb_groups(allows_promo);
|
|
301
|
+
CREATE INDEX IF NOT EXISTS idx_fbpl_url ON fb_post_log(group_url);
|
|
302
|
+
CREATE INDEX IF NOT EXISTS idx_fbpl_offer ON fb_post_log(offer_slug);
|
|
303
|
+
CREATE INDEX IF NOT EXISTS idx_fbpl_posted ON fb_post_log(posted_at);
|
|
304
|
+
CREATE UNIQUE INDEX IF NOT EXISTS uq_fbpl_url_offer_day
|
|
305
|
+
ON fb_post_log(group_url, offer_slug, substr(posted_at,1,10));
|
|
306
|
+
`;
|
|
307
|
+
// --- Public API: Collection initialization ---
|
|
308
|
+
export async function ensureCollection() {
|
|
309
|
+
getDb();
|
|
310
|
+
}
|
|
311
|
+
export async function ensureSessionCollection() {
|
|
312
|
+
// No-op: session_chunks table is created in ensureCollection()
|
|
313
|
+
}
|
|
314
|
+
/** Combined init function for cleaner startup */
|
|
315
|
+
export async function ensureDatabase() {
|
|
316
|
+
await ensureCollection();
|
|
317
|
+
}
|
|
318
|
+
// --- Public API: Memory operations ---
|
|
319
|
+
export function upsertMemory(id, vector, payload) {
|
|
320
|
+
const d = getDb();
|
|
321
|
+
const stmt = d.prepare(`
|
|
322
|
+
INSERT INTO memories
|
|
323
|
+
(id, vector, content, category, subcategory, project, tags, importance, source,
|
|
324
|
+
created_at, updated_at, accessed_at, access_count, related_files,
|
|
325
|
+
related_memory_ids, file_checksums, trashed_at, source_session_chunks)
|
|
326
|
+
VALUES
|
|
327
|
+
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
328
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
329
|
+
vector=excluded.vector,content=excluded.content,category=excluded.category,subcategory=excluded.subcategory,
|
|
330
|
+
project=excluded.project,tags=excluded.tags,importance=excluded.importance,source=excluded.source,
|
|
331
|
+
updated_at=excluded.updated_at,related_files=excluded.related_files,related_memory_ids=excluded.related_memory_ids,
|
|
332
|
+
file_checksums=excluded.file_checksums,trashed_at=excluded.trashed_at,source_session_chunks=excluded.source_session_chunks
|
|
333
|
+
`);
|
|
334
|
+
stmt.run(id, encodeVector(vector), payload.content, payload.category, payload.subcategory ?? null, payload.project, JSON.stringify(payload.tags || []), payload.importance ?? 5, payload.source || 'self-discovered', payload.created_at, payload.updated_at, payload.accessed_at, payload.access_count ?? 0, payload.related_files ? JSON.stringify(payload.related_files) : null, payload.related_memory_ids ? JSON.stringify(payload.related_memory_ids) : null, payload.file_checksums ? JSON.stringify(payload.file_checksums) : null, payload.trashed_at ?? null, payload.source_session_chunks ? JSON.stringify(payload.source_session_chunks) : null);
|
|
335
|
+
if (payload.trashed_at)
|
|
336
|
+
memoryVectors.remove(id);
|
|
337
|
+
else
|
|
338
|
+
memoryVectors.set(id, vector);
|
|
339
|
+
}
|
|
340
|
+
export function searchMemories(vector, limit, filter, scoreThreshold) {
|
|
341
|
+
const d = getDb();
|
|
342
|
+
const threshold = scoreThreshold ?? 0.3;
|
|
343
|
+
// When a filter is present, resolve the matching id set via the indexed
|
|
344
|
+
// SQL WHERE first, then score only those rows in the vector cache.
|
|
345
|
+
let allowedIds;
|
|
346
|
+
const { where, params } = translateFilter(filter);
|
|
347
|
+
if (where) {
|
|
348
|
+
const idRows = d.prepare(`
|
|
349
|
+
SELECT id FROM memories WHERE trashed_at IS NULL${where}
|
|
350
|
+
`).all(...params);
|
|
351
|
+
allowedIds = new Set(idRows.map((r) => r.id));
|
|
352
|
+
if (allowedIds.size === 0)
|
|
353
|
+
return [];
|
|
354
|
+
}
|
|
355
|
+
const top = memoryVectors.topK(vector, limit, threshold, allowedIds);
|
|
356
|
+
if (top.length === 0)
|
|
357
|
+
return [];
|
|
358
|
+
// Hydrate payloads for just the top K rows
|
|
359
|
+
const placeholders = top.map(() => '?').join(', ');
|
|
360
|
+
const rows = d.prepare(`
|
|
361
|
+
SELECT id, content, category, subcategory, project, tags, importance, source,
|
|
362
|
+
created_at, updated_at, accessed_at, access_count, related_files,
|
|
363
|
+
related_memory_ids, file_checksums, trashed_at, source_session_chunks
|
|
364
|
+
FROM memories
|
|
365
|
+
WHERE id IN (${placeholders})
|
|
366
|
+
`).all(...top.map((t) => t.id));
|
|
367
|
+
const rowById = new Map(rows.map((r) => [r.id, r]));
|
|
368
|
+
return top
|
|
369
|
+
.filter((t) => rowById.has(t.id))
|
|
370
|
+
.map((t) => ({
|
|
371
|
+
id: t.id,
|
|
372
|
+
score: t.score,
|
|
373
|
+
payload: rowToPayload(rowById.get(t.id)),
|
|
374
|
+
}));
|
|
375
|
+
}
|
|
376
|
+
export async function getMemory(id) {
|
|
377
|
+
const d = getDb();
|
|
378
|
+
const row = d.prepare(`
|
|
379
|
+
SELECT id, content, category, subcategory, project, tags, importance, source,
|
|
380
|
+
created_at, updated_at, accessed_at, access_count, related_files,
|
|
381
|
+
related_memory_ids, file_checksums, trashed_at, source_session_chunks
|
|
382
|
+
FROM memories WHERE id = ?
|
|
383
|
+
`).get(id);
|
|
384
|
+
if (!row)
|
|
385
|
+
return null;
|
|
386
|
+
return { id: row.id, payload: rowToPayload(row) };
|
|
387
|
+
}
|
|
388
|
+
export function updatePayload(id, payload) {
|
|
389
|
+
const d = getDb();
|
|
390
|
+
const sets = [];
|
|
391
|
+
const params = [];
|
|
392
|
+
for (const [key, value] of Object.entries(payload)) {
|
|
393
|
+
if (key === 'id' || key === 'vector')
|
|
394
|
+
continue;
|
|
395
|
+
const col = sanitizeColumn(key);
|
|
396
|
+
if (Array.isArray(value) || (typeof value === 'object' && value !== null)) {
|
|
397
|
+
sets.push(`${col} = ?`);
|
|
398
|
+
params.push(JSON.stringify(value));
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
sets.push(`${col} = ?`);
|
|
402
|
+
params.push((value ?? null));
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
if (sets.length === 0)
|
|
406
|
+
return;
|
|
407
|
+
params.push(id);
|
|
408
|
+
d.prepare(`UPDATE memories SET ${sets.join(', ')} WHERE id = ?`).run(...params);
|
|
409
|
+
// Keep the vector cache in sync with trash-state transitions
|
|
410
|
+
if ('trashed_at' in payload) {
|
|
411
|
+
if (payload.trashed_at)
|
|
412
|
+
memoryVectors.remove(id);
|
|
413
|
+
else
|
|
414
|
+
memoryVectors.setFromDb(id);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
export async function updateVector(id, vector, payload) {
|
|
418
|
+
// Full upsert — replaces both vector and payload
|
|
419
|
+
await upsertMemory(id, vector, payload);
|
|
420
|
+
}
|
|
421
|
+
export async function updatePayloadByFilter(filter, payload) {
|
|
422
|
+
const d = getDb();
|
|
423
|
+
const { where, params: filterParams } = translateFilter(filter);
|
|
424
|
+
const sets = [];
|
|
425
|
+
const setParams = [];
|
|
426
|
+
for (const [key, value] of Object.entries(payload)) {
|
|
427
|
+
if (key === 'id' || key === 'vector')
|
|
428
|
+
continue;
|
|
429
|
+
const col = sanitizeColumn(key);
|
|
430
|
+
if (Array.isArray(value) || (typeof value === 'object' && value !== null)) {
|
|
431
|
+
sets.push(`${col} = ?`);
|
|
432
|
+
setParams.push(JSON.stringify(value));
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
sets.push(`${col} = ?`);
|
|
436
|
+
setParams.push((value ?? null));
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
if (sets.length === 0)
|
|
440
|
+
return;
|
|
441
|
+
d.prepare(`UPDATE memories SET ${sets.join(', ')} WHERE trashed_at IS NULL${where}`)
|
|
442
|
+
.run(...setParams, ...filterParams);
|
|
443
|
+
// Bulk path — affected ids unknown here; reload lazily on next search
|
|
444
|
+
if ('trashed_at' in payload)
|
|
445
|
+
memoryVectors.invalidate();
|
|
446
|
+
}
|
|
447
|
+
export function deleteMemory(id) {
|
|
448
|
+
const d = getDb();
|
|
449
|
+
d.exec('SAVEPOINT memory_purge');
|
|
450
|
+
try {
|
|
451
|
+
d.prepare('DELETE FROM memories WHERE id = ?').run(id);
|
|
452
|
+
memoryVectors.remove(id);
|
|
453
|
+
d.prepare('DELETE FROM memory_revisions WHERE memory_id = ?').run(id);
|
|
454
|
+
d.prepare('DELETE FROM memory_metadata WHERE memory_id = ?').run(id);
|
|
455
|
+
d.prepare('DELETE FROM memory_relations WHERE from_id = ? OR to_id = ?').run(id, id);
|
|
456
|
+
d.prepare('DELETE FROM memory_feedback WHERE memory_id = ?').run(id);
|
|
457
|
+
d.exec('RELEASE memory_purge');
|
|
458
|
+
}
|
|
459
|
+
catch (error) {
|
|
460
|
+
d.exec('ROLLBACK TO memory_purge');
|
|
461
|
+
d.exec('RELEASE memory_purge');
|
|
462
|
+
memoryVectors.invalidate();
|
|
463
|
+
throw error;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
export async function softDeleteMemory(id) {
|
|
467
|
+
await updatePayload(id, { trashed_at: new Date().toISOString() });
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Batch access tracking for recall results: one UPDATE instead of N.
|
|
471
|
+
* Leaves vectors untouched, so no cache maintenance is needed.
|
|
472
|
+
*/
|
|
473
|
+
export async function touchMemories(ids, accessedAt) {
|
|
474
|
+
if (ids.length === 0)
|
|
475
|
+
return;
|
|
476
|
+
const d = getDb();
|
|
477
|
+
const placeholders = ids.map(() => '?').join(', ');
|
|
478
|
+
d.prepare(`
|
|
479
|
+
UPDATE memories SET accessed_at = ?, access_count = access_count + 1
|
|
480
|
+
WHERE id IN (${placeholders})
|
|
481
|
+
`).run(accessedAt, ...ids);
|
|
482
|
+
}
|
|
483
|
+
export async function restoreMemory(id) {
|
|
484
|
+
const d = getDb();
|
|
485
|
+
d.prepare('UPDATE memories SET trashed_at = NULL WHERE id = ?').run(id);
|
|
486
|
+
memoryVectors.setFromDb(id);
|
|
487
|
+
}
|
|
488
|
+
export async function scrollMemories(filter, limit = 20, offset) {
|
|
489
|
+
const d = getDb();
|
|
490
|
+
const { where, params } = translateFilter(filter);
|
|
491
|
+
const numericOffset = offset ? parseInt(offset, 10) : 0;
|
|
492
|
+
const rows = d.prepare(`
|
|
493
|
+
SELECT id, content, category, subcategory, project, tags, importance, source,
|
|
494
|
+
created_at, updated_at, accessed_at, access_count, related_files,
|
|
495
|
+
related_memory_ids, file_checksums, trashed_at, source_session_chunks
|
|
496
|
+
FROM memories
|
|
497
|
+
WHERE trashed_at IS NULL${where}
|
|
498
|
+
ORDER BY created_at DESC
|
|
499
|
+
LIMIT ? OFFSET ?
|
|
500
|
+
`).all(...params, limit, numericOffset);
|
|
501
|
+
const points = rows.map((row) => ({
|
|
502
|
+
id: row.id,
|
|
503
|
+
payload: rowToPayload(row),
|
|
504
|
+
}));
|
|
505
|
+
// Determine next offset
|
|
506
|
+
const nextOffset = rows.length === limit ? String(numericOffset + limit) : null;
|
|
507
|
+
return { points, next_page_offset: nextOffset };
|
|
508
|
+
}
|
|
509
|
+
export async function countMemories(filter) {
|
|
510
|
+
const d = getDb();
|
|
511
|
+
const { where, params } = translateFilter(filter);
|
|
512
|
+
const result = d.prepare(`
|
|
513
|
+
SELECT COUNT(*) as cnt FROM memories WHERE trashed_at IS NULL${where}
|
|
514
|
+
`).get(...params);
|
|
515
|
+
return result.cnt;
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* YouTube trailer dedup ledger — return the set of canonical keys
|
|
519
|
+
* (igdb:/appid:/ytid:/name:) for every trailer already posted. youtube_source
|
|
520
|
+
* uses this to drop already-posted candidates before the model sees them.
|
|
521
|
+
*
|
|
522
|
+
* Reads structured tags first (new `youtube-videos` rows written by
|
|
523
|
+
* youtube_upload) and falls back to scanning free-text content for igdbId/appid
|
|
524
|
+
* (legacy `youtube-trailers` rows from before the structured ledger existed).
|
|
525
|
+
* Exact-match by design — never re-post a trailer regardless of how old the
|
|
526
|
+
* ledger gets. Synchronous: this is a tiny indexed read, not a vector search.
|
|
527
|
+
*/
|
|
528
|
+
const TRAILER_LEDGER_CATEGORIES = ['youtube-videos', 'youtube-trailers'];
|
|
529
|
+
const TRAILER_KEY_RE = /^(igdb|appid|ytid|name):.+/;
|
|
530
|
+
export function getPostedTrailerKeys() {
|
|
531
|
+
const keys = new Set();
|
|
532
|
+
let rows = [];
|
|
533
|
+
try {
|
|
534
|
+
const d = getDb();
|
|
535
|
+
const placeholders = TRAILER_LEDGER_CATEGORIES.map(() => '?').join(', ');
|
|
536
|
+
rows = d.prepare(`SELECT tags, content FROM memories WHERE category IN (${placeholders}) AND trashed_at IS NULL`).all(...TRAILER_LEDGER_CATEGORIES);
|
|
537
|
+
}
|
|
538
|
+
catch {
|
|
539
|
+
return keys; // dedup is best-effort: a read failure must not break sourcing
|
|
540
|
+
}
|
|
541
|
+
for (const r of rows) {
|
|
542
|
+
// 1) structured dedup tags (preserve case — ytid is case-sensitive).
|
|
543
|
+
try {
|
|
544
|
+
for (const t of JSON.parse(r.tags || '[]')) {
|
|
545
|
+
const s = String(t).trim();
|
|
546
|
+
if (TRAILER_KEY_RE.test(s))
|
|
547
|
+
keys.add(s);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
catch { /* tags not JSON — fall through to content scan */ }
|
|
551
|
+
// 2) content fallback for legacy free-text rows (igdbId / appid only).
|
|
552
|
+
const content = r.content || '';
|
|
553
|
+
const ig = content.match(/igdb\s*id[:=\s#]*([0-9]+)/i);
|
|
554
|
+
if (ig)
|
|
555
|
+
keys.add(`igdb:${ig[1]}`);
|
|
556
|
+
const ap = content.match(/\bapp\s*id[:=\s#]*([0-9]+)/i);
|
|
557
|
+
if (ap)
|
|
558
|
+
keys.add(`appid:${ap[1]}`);
|
|
559
|
+
}
|
|
560
|
+
return keys;
|
|
561
|
+
}
|
|
562
|
+
export async function getMemoryStats() {
|
|
563
|
+
const d = getDb();
|
|
564
|
+
const totalRow = d.prepare('SELECT COUNT(*) as cnt FROM memories WHERE trashed_at IS NULL').get();
|
|
565
|
+
const total = totalRow.cnt;
|
|
566
|
+
// Per-category counts using SQL aggregate
|
|
567
|
+
const catRows = d.prepare(`
|
|
568
|
+
SELECT category, COUNT(*) as cnt FROM memories WHERE trashed_at IS NULL GROUP BY category
|
|
569
|
+
`).all();
|
|
570
|
+
const by_category = {};
|
|
571
|
+
// Initialize with all known categories at 0
|
|
572
|
+
for (const cat of getAllCategories()) {
|
|
573
|
+
by_category[cat] = 0;
|
|
574
|
+
}
|
|
575
|
+
for (const row of catRows) {
|
|
576
|
+
by_category[row.category] = row.cnt;
|
|
577
|
+
}
|
|
578
|
+
// Per-project counts
|
|
579
|
+
const projRows = d.prepare(`
|
|
580
|
+
SELECT project, COUNT(*) as cnt FROM memories WHERE trashed_at IS NULL GROUP BY project
|
|
581
|
+
`).all();
|
|
582
|
+
const by_project = {};
|
|
583
|
+
for (const row of projRows) {
|
|
584
|
+
by_project[row.project || 'global'] = row.cnt;
|
|
585
|
+
}
|
|
586
|
+
// Oldest/newest
|
|
587
|
+
const dateRow = d.prepare(`
|
|
588
|
+
SELECT MIN(created_at) as oldest, MAX(created_at) as newest FROM memories WHERE trashed_at IS NULL
|
|
589
|
+
`).get();
|
|
590
|
+
return {
|
|
591
|
+
total,
|
|
592
|
+
by_category,
|
|
593
|
+
by_project,
|
|
594
|
+
oldest: dateRow.oldest ?? undefined,
|
|
595
|
+
newest: dateRow.newest ?? undefined,
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
// --- FTS5 full-text search ---
|
|
599
|
+
/**
|
|
600
|
+
* Search memories using FTS5 full-text search (keyword fallback).
|
|
601
|
+
* Returns results scored by BM25 relevance. Used when vector similarity
|
|
602
|
+
* scores are low (exact identifiers, error codes, proper nouns).
|
|
603
|
+
*/
|
|
604
|
+
export async function searchMemoriesFTS(query, limit, filter, excludeIds) {
|
|
605
|
+
const d = getDb();
|
|
606
|
+
// Sanitize query for FTS5: escape double quotes, wrap terms
|
|
607
|
+
const ftsQuery = query
|
|
608
|
+
.replace(/"/g, '""')
|
|
609
|
+
.split(/\s+/)
|
|
610
|
+
.filter(t => t.length > 1)
|
|
611
|
+
.map(t => `"${t}"`)
|
|
612
|
+
.join(' OR ');
|
|
613
|
+
if (!ftsQuery)
|
|
614
|
+
return [];
|
|
615
|
+
const { where, params } = translateFilter(filter);
|
|
616
|
+
try {
|
|
617
|
+
const rows = d.prepare(`
|
|
618
|
+
SELECT m.id, m.content, m.category, m.subcategory, m.project, m.tags,
|
|
619
|
+
m.importance, m.source, m.created_at, m.updated_at, m.accessed_at,
|
|
620
|
+
m.access_count, m.related_files, m.related_memory_ids,
|
|
621
|
+
m.file_checksums, m.trashed_at, m.source_session_chunks,
|
|
622
|
+
rank
|
|
623
|
+
FROM memories_fts fts
|
|
624
|
+
JOIN memories m ON m.rowid = fts.rowid
|
|
625
|
+
WHERE memories_fts MATCH ? AND m.id IN (SELECT id FROM memories WHERE trashed_at IS NULL${where})
|
|
626
|
+
ORDER BY rank
|
|
627
|
+
LIMIT ?
|
|
628
|
+
`).all(ftsQuery, ...params, limit);
|
|
629
|
+
return rows
|
|
630
|
+
.filter(row => !excludeIds || !excludeIds.has(row.id))
|
|
631
|
+
.map(row => {
|
|
632
|
+
// FTS5 rank is negative (lower = better match). Normalize to 0-1 range.
|
|
633
|
+
const rawRank = Math.abs(row.rank);
|
|
634
|
+
const normalizedScore = Math.min(1, rawRank / 10);
|
|
635
|
+
return {
|
|
636
|
+
id: row.id,
|
|
637
|
+
score: normalizedScore,
|
|
638
|
+
payload: rowToPayload(row),
|
|
639
|
+
};
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
catch {
|
|
643
|
+
// FTS5 not available or query error — return empty
|
|
644
|
+
return [];
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
// --- Session Chunks ---
|
|
648
|
+
export function searchSessionChunks(vector, limit, filter, scoreThreshold = 0.3) {
|
|
649
|
+
const d = getDb();
|
|
650
|
+
let allowedIds;
|
|
651
|
+
const { where, params } = translateFilter(filter);
|
|
652
|
+
if (where) {
|
|
653
|
+
const idRows = d.prepare(`
|
|
654
|
+
SELECT id FROM session_chunks WHERE 1=1${where}
|
|
655
|
+
`).all(...params);
|
|
656
|
+
allowedIds = new Set(idRows.map((r) => r.id));
|
|
657
|
+
if (allowedIds.size === 0)
|
|
658
|
+
return [];
|
|
659
|
+
}
|
|
660
|
+
const top = chunkVectors.topK(vector, limit, scoreThreshold, allowedIds);
|
|
661
|
+
if (top.length === 0)
|
|
662
|
+
return [];
|
|
663
|
+
const placeholders = top.map(() => '?').join(', ');
|
|
664
|
+
const rows = d.prepare(`
|
|
665
|
+
SELECT id, content, summary, session_id, project, git_branch, cwd,
|
|
666
|
+
chunk_index, start_timestamp, end_timestamp, tools_used, files_modified,
|
|
667
|
+
files_read, user_messages, turn_count, related_memory_ids, dedup_memory_id, indexed_at
|
|
668
|
+
FROM session_chunks
|
|
669
|
+
WHERE id IN (${placeholders})
|
|
670
|
+
`).all(...top.map((t) => t.id));
|
|
671
|
+
const rowById = new Map(rows.map((r) => [r.id, r]));
|
|
672
|
+
return top
|
|
673
|
+
.filter((t) => rowById.has(t.id))
|
|
674
|
+
.map((t) => ({
|
|
675
|
+
id: t.id,
|
|
676
|
+
score: t.score,
|
|
677
|
+
payload: rowToSessionChunkPayload(rowById.get(t.id)),
|
|
678
|
+
}));
|
|
679
|
+
}
|
|
680
|
+
export async function upsertSessionChunks(points) {
|
|
681
|
+
const d = getDb();
|
|
682
|
+
const stmt = d.prepare(`
|
|
683
|
+
INSERT OR REPLACE INTO session_chunks
|
|
684
|
+
(id, vector, content, summary, session_id, project, git_branch, cwd,
|
|
685
|
+
chunk_index, start_timestamp, end_timestamp, tools_used, files_modified,
|
|
686
|
+
files_read, user_messages, turn_count, related_memory_ids, dedup_memory_id, indexed_at)
|
|
687
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
688
|
+
`);
|
|
689
|
+
// Manual transaction since node:sqlite doesn't have db.transaction()
|
|
690
|
+
d.exec('BEGIN');
|
|
691
|
+
try {
|
|
692
|
+
for (const p of points) {
|
|
693
|
+
stmt.run(p.id, encodeVector(p.vector), p.payload.content, p.payload.summary || null, p.payload.session_id || null, p.payload.project || null, p.payload.git_branch ?? null, p.payload.cwd ?? null, p.payload.chunk_index ?? 0, p.payload.start_timestamp || null, p.payload.end_timestamp || null, JSON.stringify(p.payload.tools_used || []), JSON.stringify(p.payload.files_modified || []), JSON.stringify(p.payload.files_read || []), JSON.stringify(p.payload.user_messages || []), p.payload.turn_count ?? 0, JSON.stringify(p.payload.related_memory_ids || []), p.payload.dedup_memory_id ?? null, p.payload.indexed_at || new Date().toISOString());
|
|
694
|
+
}
|
|
695
|
+
d.exec('COMMIT');
|
|
696
|
+
}
|
|
697
|
+
catch (err) {
|
|
698
|
+
d.exec('ROLLBACK');
|
|
699
|
+
throw err;
|
|
700
|
+
}
|
|
701
|
+
for (const p of points)
|
|
702
|
+
chunkVectors.set(p.id, p.vector);
|
|
703
|
+
}
|
|
704
|
+
export async function scrollSessionChunks(filter, limit = 20, offset) {
|
|
705
|
+
const d = getDb();
|
|
706
|
+
const { where, params } = translateFilter(filter);
|
|
707
|
+
const numericOffset = offset ? parseInt(offset, 10) : 0;
|
|
708
|
+
const rows = d.prepare(`
|
|
709
|
+
SELECT id, content, summary, session_id, project, git_branch, cwd,
|
|
710
|
+
chunk_index, start_timestamp, end_timestamp, tools_used, files_modified,
|
|
711
|
+
files_read, user_messages, turn_count, related_memory_ids, dedup_memory_id, indexed_at
|
|
712
|
+
FROM session_chunks
|
|
713
|
+
WHERE 1=1${where}
|
|
714
|
+
ORDER BY indexed_at DESC
|
|
715
|
+
LIMIT ? OFFSET ?
|
|
716
|
+
`).all(...params, limit, numericOffset);
|
|
717
|
+
const points = rows.map((row) => ({
|
|
718
|
+
id: row.id,
|
|
719
|
+
payload: rowToSessionChunkPayload(row),
|
|
720
|
+
}));
|
|
721
|
+
const nextOffset = rows.length === limit ? String(numericOffset + limit) : null;
|
|
722
|
+
return { points, next_page_offset: nextOffset };
|
|
723
|
+
}
|
|
724
|
+
export async function countSessionChunks(filter) {
|
|
725
|
+
const d = getDb();
|
|
726
|
+
const { where, params } = translateFilter(filter);
|
|
727
|
+
const result = d.prepare(`SELECT COUNT(*) as cnt FROM session_chunks WHERE 1=1${where}`)
|
|
728
|
+
.get(...params);
|
|
729
|
+
return result.cnt;
|
|
730
|
+
}
|
|
731
|
+
export async function getCategories() {
|
|
732
|
+
try {
|
|
733
|
+
const d = getDb();
|
|
734
|
+
const rows = d.prepare('SELECT name, description, created_at, parent, color, is_parent FROM categories ORDER BY name')
|
|
735
|
+
.all();
|
|
736
|
+
if (rows.length === 0)
|
|
737
|
+
return null;
|
|
738
|
+
return rows.map((row) => ({
|
|
739
|
+
name: row.name,
|
|
740
|
+
description: row.description,
|
|
741
|
+
created_at: row.created_at,
|
|
742
|
+
parent: row.parent,
|
|
743
|
+
color: row.color,
|
|
744
|
+
is_parent: row.is_parent === 1 ? true : undefined,
|
|
745
|
+
}));
|
|
746
|
+
}
|
|
747
|
+
catch {
|
|
748
|
+
return null;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
export async function saveCategories(categories) {
|
|
752
|
+
const d = getDb();
|
|
753
|
+
const insertStmt = d.prepare(`
|
|
754
|
+
INSERT OR REPLACE INTO categories (name, description, created_at, parent, color, is_parent)
|
|
755
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
756
|
+
`);
|
|
757
|
+
// Manual transaction
|
|
758
|
+
d.exec('BEGIN');
|
|
759
|
+
try {
|
|
760
|
+
// Get existing names to detect deletions
|
|
761
|
+
const existing = new Set(d.prepare('SELECT name FROM categories').all().map((r) => r.name));
|
|
762
|
+
const incoming = new Set(categories.map((c) => c.name));
|
|
763
|
+
// Delete removed categories
|
|
764
|
+
for (const name of existing) {
|
|
765
|
+
if (!incoming.has(name)) {
|
|
766
|
+
d.prepare('DELETE FROM categories WHERE name = ?').run(name);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
// Upsert all incoming
|
|
770
|
+
for (const cat of categories) {
|
|
771
|
+
insertStmt.run(cat.name, cat.description, cat.created_at, cat.parent ?? null, cat.color ?? null, cat.is_parent ? 1 : 0);
|
|
772
|
+
}
|
|
773
|
+
d.exec('COMMIT');
|
|
774
|
+
}
|
|
775
|
+
catch (err) {
|
|
776
|
+
d.exec('ROLLBACK');
|
|
777
|
+
throw err;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
// --- Facebook group directory (fb_groups + fb_post_log) ---
|
|
781
|
+
const FB_COOLDOWN_HOURS_DEFAULT = 48;
|
|
782
|
+
// COALESCE merge so a partial update never nulls richer prior data; name only overwrites when
|
|
783
|
+
// non-empty; 'false' promo is sticky (an excluded group can't be silently re-opened by an import).
|
|
784
|
+
const FB_GROUP_UPSERT_SQL = `
|
|
785
|
+
INSERT INTO fb_groups (url, name, region, country, lang, currency, joined, allows_promo,
|
|
786
|
+
member_count, notes, source, added_at, updated_at)
|
|
787
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
788
|
+
ON CONFLICT(url) DO UPDATE SET
|
|
789
|
+
name = CASE WHEN excluded.name != '' THEN excluded.name ELSE fb_groups.name END,
|
|
790
|
+
region = COALESCE(excluded.region, fb_groups.region),
|
|
791
|
+
country = COALESCE(excluded.country, fb_groups.country),
|
|
792
|
+
lang = COALESCE(excluded.lang, fb_groups.lang),
|
|
793
|
+
currency = COALESCE(excluded.currency, fb_groups.currency),
|
|
794
|
+
joined = excluded.joined,
|
|
795
|
+
allows_promo = CASE
|
|
796
|
+
WHEN fb_groups.allows_promo = 'false' THEN 'false'
|
|
797
|
+
WHEN excluded.allows_promo = 'unknown' THEN fb_groups.allows_promo
|
|
798
|
+
ELSE excluded.allows_promo END,
|
|
799
|
+
member_count = COALESCE(excluded.member_count, fb_groups.member_count),
|
|
800
|
+
notes = COALESCE(excluded.notes, fb_groups.notes),
|
|
801
|
+
source = COALESCE(excluded.source, fb_groups.source),
|
|
802
|
+
updated_at = excluded.updated_at
|
|
803
|
+
`;
|
|
804
|
+
const FB_POSTLOG_SQL = `
|
|
805
|
+
INSERT OR REPLACE INTO fb_post_log
|
|
806
|
+
(id, group_url, offer_slug, currency, status, post_url, session_id, posted_at, note)
|
|
807
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
808
|
+
`;
|
|
809
|
+
function runFbGroupUpsert(stmt, row, now) {
|
|
810
|
+
stmt.run(row.url, row.name ?? '', row.region ?? null, row.country ?? null, row.lang ?? null, row.currency ?? null, row.joined ?? 1, row.allows_promo ?? 'unknown', row.member_count ?? null, row.notes ?? null, row.source ?? 'import', now, // added_at (ignored on conflict)
|
|
811
|
+
now);
|
|
812
|
+
}
|
|
813
|
+
function runFbPostLog(stmt, e, now) {
|
|
814
|
+
stmt.run(e.id ?? randomUUID(), e.group_url, e.offer_slug, e.currency ?? null, e.status, e.post_url ?? null, e.session_id ?? null, e.posted_at ?? now, e.note ?? null);
|
|
815
|
+
}
|
|
816
|
+
/** Upsert one group row (idempotent, COALESCE merge). */
|
|
817
|
+
export function upsertFbGroup(row) {
|
|
818
|
+
const d = getDb();
|
|
819
|
+
runFbGroupUpsert(d.prepare(FB_GROUP_UPSERT_SQL), row, new Date().toISOString());
|
|
820
|
+
}
|
|
821
|
+
/** Bulk migration write — many group upserts + post-log rows in one transaction. */
|
|
822
|
+
export function importFbData(groups, logs) {
|
|
823
|
+
const d = getDb();
|
|
824
|
+
const now = new Date().toISOString();
|
|
825
|
+
const gStmt = d.prepare(FB_GROUP_UPSERT_SQL);
|
|
826
|
+
const lStmt = d.prepare(FB_POSTLOG_SQL);
|
|
827
|
+
d.exec('BEGIN');
|
|
828
|
+
try {
|
|
829
|
+
for (const g of groups)
|
|
830
|
+
runFbGroupUpsert(gStmt, g, now);
|
|
831
|
+
for (const l of logs)
|
|
832
|
+
runFbPostLog(lStmt, l, now);
|
|
833
|
+
d.exec('COMMIT');
|
|
834
|
+
}
|
|
835
|
+
catch (err) {
|
|
836
|
+
d.exec('ROLLBACK');
|
|
837
|
+
throw err;
|
|
838
|
+
}
|
|
839
|
+
return { groupsUpserted: groups.length, postLogRows: logs.length };
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* The per-group checklist tick. One atomic transaction: ensure/refresh the group row, set its
|
|
843
|
+
* state from the status (pending-approval engages a cooldown; visible-post clears it; failed/
|
|
844
|
+
* skipped leave state untouched), and append the durable fb_post_log row. Replaces the
|
|
845
|
+
* corruption-prone reflect-into-ledger entirely.
|
|
846
|
+
*/
|
|
847
|
+
export function markFbGroup(opts) {
|
|
848
|
+
const d = getDb();
|
|
849
|
+
const now = new Date().toISOString();
|
|
850
|
+
const status = opts.status;
|
|
851
|
+
const isPending = status === 'pending-approval';
|
|
852
|
+
const isPosted = status === 'visible-post';
|
|
853
|
+
const cooldownH = opts.cooldownHours ?? FB_COOLDOWN_HOURS_DEFAULT;
|
|
854
|
+
const cooldownUntil = isPending ? new Date(Date.now() + cooldownH * 3600_000).toISOString() : null;
|
|
855
|
+
d.exec('BEGIN');
|
|
856
|
+
try {
|
|
857
|
+
// Ensure the group row exists / refresh descriptive fields (no state touch here).
|
|
858
|
+
runFbGroupUpsert(d.prepare(FB_GROUP_UPSERT_SQL), {
|
|
859
|
+
url: opts.url, name: opts.name, region: opts.region, lang: opts.lang,
|
|
860
|
+
currency: opts.currency ?? undefined, joined: 1, source: 'manual',
|
|
861
|
+
}, now);
|
|
862
|
+
// last_status / last_error / currency.
|
|
863
|
+
d.prepare(`UPDATE fb_groups SET last_status = ?, last_error = ?, currency = COALESCE(?, currency), updated_at = ? WHERE url = ?`)
|
|
864
|
+
.run(status, status === 'posting-failed' ? (opts.note ?? 'posting-failed') : null, opts.currency ?? null, now, opts.url);
|
|
865
|
+
// Pending/cooldown state — explicit so visible-post can clear a prior wall.
|
|
866
|
+
if (isPending) {
|
|
867
|
+
d.prepare(`UPDATE fb_groups SET pending_since = ?, cooldown_until = ? WHERE url = ?`).run(now, cooldownUntil, opts.url);
|
|
868
|
+
}
|
|
869
|
+
else if (isPosted) {
|
|
870
|
+
d.prepare(`UPDATE fb_groups SET pending_since = NULL, cooldown_until = NULL WHERE url = ?`).run(opts.url);
|
|
871
|
+
}
|
|
872
|
+
// Durable append-only log row (one per group/offer/day; latest status wins).
|
|
873
|
+
runFbPostLog(d.prepare(FB_POSTLOG_SQL), {
|
|
874
|
+
group_url: opts.url, offer_slug: opts.offerSlug, currency: opts.currency ?? null,
|
|
875
|
+
status, post_url: opts.postUrl ?? null, session_id: opts.sessionId ?? null, posted_at: now, note: opts.note ?? null,
|
|
876
|
+
}, now);
|
|
877
|
+
d.exec('COMMIT');
|
|
878
|
+
}
|
|
879
|
+
catch (err) {
|
|
880
|
+
d.exec('ROLLBACK');
|
|
881
|
+
throw err;
|
|
882
|
+
}
|
|
883
|
+
const row = d.prepare(`SELECT pending_since, cooldown_until FROM fb_groups WHERE url = ?`).get(opts.url);
|
|
884
|
+
return {
|
|
885
|
+
url: opts.url, status,
|
|
886
|
+
pending_since: row?.pending_since ?? null,
|
|
887
|
+
cooldown_until: row?.cooldown_until ?? null,
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* The efficient region fetch + resume engine. Returns the groups still to post to for this offer:
|
|
892
|
+
* joined, promo not forbidden, region/currency match, not pending/cooldown (unless includePending),
|
|
893
|
+
* and not already posted for this offer within freshDays (unless reset). Never-posted first, then
|
|
894
|
+
* least-recently-posted, then largest membership.
|
|
895
|
+
*/
|
|
896
|
+
export function selectFbWorklist(opts) {
|
|
897
|
+
const d = getDb();
|
|
898
|
+
const { region, currency, offerSlug } = opts;
|
|
899
|
+
const limit = opts.limit ?? 20;
|
|
900
|
+
const freshDays = opts.freshDays ?? 14;
|
|
901
|
+
const includePending = opts.includePending ?? false;
|
|
902
|
+
const reset = opts.reset ?? false;
|
|
903
|
+
const now = new Date();
|
|
904
|
+
const nowIso = now.toISOString();
|
|
905
|
+
const where = ['g.joined = 1', "g.allows_promo != 'false'"];
|
|
906
|
+
const params = [];
|
|
907
|
+
if (currency) {
|
|
908
|
+
const ccy = currency.toUpperCase();
|
|
909
|
+
const regionForCcy = REGION_BY_CURRENCY[ccy] || null;
|
|
910
|
+
if (regionForCcy) {
|
|
911
|
+
// Authoritative seed-queue currency, plus currency-less groups in that region.
|
|
912
|
+
where.push('(upper(g.currency) = ? OR (g.currency IS NULL AND g.region = ?))');
|
|
913
|
+
params.push(ccy, regionForCcy);
|
|
914
|
+
}
|
|
915
|
+
else {
|
|
916
|
+
where.push('upper(g.currency) = ?');
|
|
917
|
+
params.push(ccy);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
else if (region) {
|
|
921
|
+
where.push('lower(g.region) = lower(?)');
|
|
922
|
+
params.push(region);
|
|
923
|
+
}
|
|
924
|
+
// Optional finer targeting (e.g. split the EU currency bucket by language for native-copy seeding).
|
|
925
|
+
if (opts.lang) {
|
|
926
|
+
where.push('lower(g.lang) = lower(?)');
|
|
927
|
+
params.push(opts.lang);
|
|
928
|
+
}
|
|
929
|
+
if (opts.country) {
|
|
930
|
+
where.push('lower(g.country) = lower(?)');
|
|
931
|
+
params.push(opts.country);
|
|
932
|
+
}
|
|
933
|
+
if (!includePending) {
|
|
934
|
+
where.push('g.pending_since IS NULL');
|
|
935
|
+
where.push('(g.cooldown_until IS NULL OR g.cooldown_until <= ?)');
|
|
936
|
+
params.push(nowIso);
|
|
937
|
+
}
|
|
938
|
+
if (!reset && offerSlug) {
|
|
939
|
+
const cutoff = new Date(now.getTime() - freshDays * 86400_000).toISOString();
|
|
940
|
+
where.push(`NOT EXISTS (SELECT 1 FROM fb_post_log p WHERE p.group_url = g.url AND p.offer_slug = ? ` +
|
|
941
|
+
`AND p.status IN ('visible-post','pending-approval') AND p.posted_at >= ?)`);
|
|
942
|
+
params.push(offerSlug, cutoff);
|
|
943
|
+
}
|
|
944
|
+
const sql = `
|
|
945
|
+
SELECT g.url, g.name, g.region, g.currency, g.lang, g.member_count, g.allows_promo,
|
|
946
|
+
(SELECT MAX(posted_at) FROM fb_post_log p WHERE p.group_url = g.url) AS last_any_posted
|
|
947
|
+
FROM fb_groups g
|
|
948
|
+
WHERE ${where.join(' AND ')}
|
|
949
|
+
ORDER BY (last_any_posted IS NULL) DESC, last_any_posted ASC, g.member_count DESC
|
|
950
|
+
LIMIT ?`;
|
|
951
|
+
params.push(limit);
|
|
952
|
+
const rows = d.prepare(sql).all(...params);
|
|
953
|
+
return rows.map((r) => ({
|
|
954
|
+
url: r.url,
|
|
955
|
+
name: r.name,
|
|
956
|
+
region: r.region ?? null,
|
|
957
|
+
currency: r.currency ?? null,
|
|
958
|
+
lang: r.lang ?? null,
|
|
959
|
+
member_count: r.member_count ?? null,
|
|
960
|
+
allows_promo: r.allows_promo,
|
|
961
|
+
lastPosted: r.last_any_posted ?? null,
|
|
962
|
+
}));
|
|
963
|
+
}
|
|
964
|
+
/** Set/clear a group's promo permission (the exclude action). Overrides the sticky-'false' rule. */
|
|
965
|
+
export function setFbAllowsPromo(url, value, note) {
|
|
966
|
+
const d = getDb();
|
|
967
|
+
const now = new Date().toISOString();
|
|
968
|
+
runFbGroupUpsert(d.prepare(FB_GROUP_UPSERT_SQL), { url, joined: 1, allows_promo: value, notes: note, source: 'manual' }, now);
|
|
969
|
+
d.prepare(`UPDATE fb_groups SET allows_promo = ?, notes = COALESCE(?, notes), updated_at = ? WHERE url = ?`)
|
|
970
|
+
.run(value, note ?? null, now, url);
|
|
971
|
+
}
|
|
972
|
+
/**
|
|
973
|
+
* Curation write: authoritatively set specific columns on a group. Ensures the row exists, then
|
|
974
|
+
* UPDATEs ONLY the provided fields (undefined = leave untouched). Unlike upsertFbGroup's COALESCE
|
|
975
|
+
* merge, this overrides — so it can correct a wrong region or re-open promo. Column names come from
|
|
976
|
+
* a fixed allowlist (no injection).
|
|
977
|
+
*/
|
|
978
|
+
export function setFbGroupFields(url, fields) {
|
|
979
|
+
const d = getDb();
|
|
980
|
+
const now = new Date().toISOString();
|
|
981
|
+
runFbGroupUpsert(d.prepare(FB_GROUP_UPSERT_SQL), { url, joined: 1, source: 'curated' }, now);
|
|
982
|
+
const allow = [
|
|
983
|
+
['region', fields.region], ['lang', fields.lang], ['currency', fields.currency],
|
|
984
|
+
['country', fields.country], ['name', fields.name], ['member_count', fields.member_count],
|
|
985
|
+
['allows_promo', fields.allows_promo], ['notes', fields.notes],
|
|
986
|
+
];
|
|
987
|
+
const cols = [];
|
|
988
|
+
const params = [];
|
|
989
|
+
for (const [col, val] of allow) {
|
|
990
|
+
if (val !== undefined) {
|
|
991
|
+
cols.push(`${col} = ?`);
|
|
992
|
+
params.push(val ?? null);
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
if (cols.length === 0)
|
|
996
|
+
return;
|
|
997
|
+
cols.push('updated_at = ?');
|
|
998
|
+
params.push(now, url);
|
|
999
|
+
d.prepare(`UPDATE fb_groups SET ${cols.join(', ')} WHERE url = ?`).run(...params);
|
|
1000
|
+
}
|
|
1001
|
+
/** List group rows, optionally filtered to one region. */
|
|
1002
|
+
export function selectFbGroups(region) {
|
|
1003
|
+
const d = getDb();
|
|
1004
|
+
const cols = `url, name, region, country, lang, currency, joined, allows_promo, member_count, pending_since, cooldown_until, last_status, source, updated_at`;
|
|
1005
|
+
if (region) {
|
|
1006
|
+
return d.prepare(`SELECT ${cols} FROM fb_groups WHERE lower(region) = lower(?) ORDER BY member_count DESC, name`).all(region);
|
|
1007
|
+
}
|
|
1008
|
+
return d.prepare(`SELECT ${cols} FROM fb_groups ORDER BY region, member_count DESC, name`).all();
|
|
1009
|
+
}
|
|
1010
|
+
/** Coverage + health aggregates for the list/stats action. */
|
|
1011
|
+
export function fbStats(region) {
|
|
1012
|
+
const d = getDb();
|
|
1013
|
+
const now = new Date().toISOString();
|
|
1014
|
+
const regWhere = region ? ' WHERE lower(region) = lower(?)' : '';
|
|
1015
|
+
const regParams = region ? [region] : [];
|
|
1016
|
+
const rows = d.prepare(`
|
|
1017
|
+
SELECT COALESCE(region,'Unknown') AS region,
|
|
1018
|
+
COUNT(*) AS total,
|
|
1019
|
+
SUM(CASE WHEN joined=1 THEN 1 ELSE 0 END) AS joined,
|
|
1020
|
+
SUM(CASE WHEN allows_promo!='false' THEN 1 ELSE 0 END) AS promoOk,
|
|
1021
|
+
SUM(CASE WHEN allows_promo='false' THEN 1 ELSE 0 END) AS promoNo,
|
|
1022
|
+
SUM(CASE WHEN pending_since IS NOT NULL THEN 1 ELSE 0 END) AS pending,
|
|
1023
|
+
SUM(CASE WHEN cooldown_until IS NOT NULL AND cooldown_until > ? THEN 1 ELSE 0 END) AS cooldown
|
|
1024
|
+
FROM fb_groups${regWhere}
|
|
1025
|
+
GROUP BY COALESCE(region,'Unknown')
|
|
1026
|
+
ORDER BY total DESC
|
|
1027
|
+
`).all(now, ...regParams);
|
|
1028
|
+
const byRegion = {};
|
|
1029
|
+
for (const r of rows) {
|
|
1030
|
+
byRegion[r.region] = {
|
|
1031
|
+
total: Number(r.total), joined: Number(r.joined), promoOk: Number(r.promoOk),
|
|
1032
|
+
promoNo: Number(r.promoNo), pending: Number(r.pending), cooldown: Number(r.cooldown),
|
|
1033
|
+
};
|
|
1034
|
+
}
|
|
1035
|
+
const tot = d.prepare(`SELECT COUNT(*) AS groups, SUM(CASE WHEN joined=1 THEN 1 ELSE 0 END) AS joined, SUM(CASE WHEN pending_since IS NOT NULL THEN 1 ELSE 0 END) AS pending FROM fb_groups`).get();
|
|
1036
|
+
const logCount = d.prepare(`SELECT COUNT(*) AS c FROM fb_post_log`).get();
|
|
1037
|
+
const offers = d.prepare(`SELECT offer_slug, MAX(posted_at) AS last FROM fb_post_log GROUP BY offer_slug ORDER BY last DESC LIMIT 25`).all();
|
|
1038
|
+
const lastPostedPerOffer = {};
|
|
1039
|
+
for (const o of offers)
|
|
1040
|
+
lastPostedPerOffer[o.offer_slug] = o.last;
|
|
1041
|
+
return {
|
|
1042
|
+
byRegion,
|
|
1043
|
+
totals: {
|
|
1044
|
+
groups: Number(tot?.groups ?? 0), joined: Number(tot?.joined ?? 0),
|
|
1045
|
+
pending: Number(tot?.pending ?? 0), logRows: Number(logCount?.c ?? 0),
|
|
1046
|
+
},
|
|
1047
|
+
lastPostedPerOffer,
|
|
1048
|
+
};
|
|
1049
|
+
}
|
|
1050
|
+
/**
|
|
1051
|
+
* One-shot directory cleanup / re-categorization. Re-derives region/lang/currency/country for
|
|
1052
|
+
* EVERY group from all available signals (group name + stored fields + the dominant currency seen
|
|
1053
|
+
* in fb_post_log), and backfills allows_promo from history: a confirmed visible-post proves promo
|
|
1054
|
+
* is allowed. Fixes the Unknown-region tail and the Spanish-as-EUR mis-bucket. Idempotent — safe to
|
|
1055
|
+
* re-run. Returns before/after counters for verification.
|
|
1056
|
+
*/
|
|
1057
|
+
export function recategorizeFbGroups() {
|
|
1058
|
+
const d = getDb();
|
|
1059
|
+
const now = new Date().toISOString();
|
|
1060
|
+
const rows = d.prepare(`SELECT url, name, region, lang, currency, allows_promo FROM fb_groups`).all();
|
|
1061
|
+
// Dominant non-empty currency + any-visible-post flag per group, from the durable post log.
|
|
1062
|
+
const sigRows = d.prepare(`
|
|
1063
|
+
SELECT p.group_url AS url,
|
|
1064
|
+
(SELECT p2.currency FROM fb_post_log p2
|
|
1065
|
+
WHERE p2.group_url = p.group_url AND p2.currency IS NOT NULL AND p2.currency != ''
|
|
1066
|
+
GROUP BY p2.currency ORDER BY COUNT(*) DESC, MAX(p2.posted_at) DESC LIMIT 1) AS topCurrency,
|
|
1067
|
+
MAX(CASE WHEN p.status = 'visible-post' THEN 1 ELSE 0 END) AS hadVisible
|
|
1068
|
+
FROM fb_post_log p GROUP BY p.group_url
|
|
1069
|
+
`).all();
|
|
1070
|
+
const sig = new Map();
|
|
1071
|
+
for (const s of sigRows)
|
|
1072
|
+
sig.set(s.url, { topCurrency: s.topCurrency || null, hadVisible: Number(s.hadVisible) === 1 });
|
|
1073
|
+
const upd = d.prepare(`UPDATE fb_groups SET region = ?, lang = COALESCE(?, lang), currency = COALESCE(?, currency), ` +
|
|
1074
|
+
`country = COALESCE(?, country), allows_promo = ?, updated_at = ? WHERE url = ?`);
|
|
1075
|
+
let regionChanged = 0, currencyChanged = 0, promoSet = 0, stillUnknown = 0;
|
|
1076
|
+
const byRegion = {};
|
|
1077
|
+
d.exec('BEGIN');
|
|
1078
|
+
try {
|
|
1079
|
+
for (const r of rows) {
|
|
1080
|
+
const url = r.url;
|
|
1081
|
+
const s = sig.get(url);
|
|
1082
|
+
const resolved = resolveClassification({
|
|
1083
|
+
name: r.name || '',
|
|
1084
|
+
url,
|
|
1085
|
+
region: r.region || null,
|
|
1086
|
+
lang: r.lang || null,
|
|
1087
|
+
currency: (r.currency || s?.topCurrency) || null,
|
|
1088
|
+
});
|
|
1089
|
+
const priorPromo = r.allows_promo || 'unknown';
|
|
1090
|
+
// A confirmed visible-post proves promo is allowed; an explicit 'false' exclude stays sticky.
|
|
1091
|
+
const promo = priorPromo === 'false' ? 'false' : (s?.hadVisible ? 'true' : priorPromo);
|
|
1092
|
+
if (resolved.region !== (r.region || 'Unknown'))
|
|
1093
|
+
regionChanged++;
|
|
1094
|
+
if (resolved.currency && resolved.currency !== (r.currency || null))
|
|
1095
|
+
currencyChanged++;
|
|
1096
|
+
if (promo !== priorPromo)
|
|
1097
|
+
promoSet++;
|
|
1098
|
+
if (resolved.region === 'Unknown')
|
|
1099
|
+
stillUnknown++;
|
|
1100
|
+
byRegion[resolved.region] = (byRegion[resolved.region] || 0) + 1;
|
|
1101
|
+
upd.run(resolved.region, resolved.lang, resolved.currency, resolved.country, promo, now, url);
|
|
1102
|
+
}
|
|
1103
|
+
d.exec('COMMIT');
|
|
1104
|
+
}
|
|
1105
|
+
catch (err) {
|
|
1106
|
+
d.exec('ROLLBACK');
|
|
1107
|
+
throw err;
|
|
1108
|
+
}
|
|
1109
|
+
return { scanned: rows.length, regionChanged, currencyChanged, promoSet, stillUnknown, byRegion };
|
|
1110
|
+
}
|
|
1111
|
+
// --- Helpers ---
|
|
1112
|
+
function parseJsonOrDefault(value, defaultValue) {
|
|
1113
|
+
if (value == null || value === '')
|
|
1114
|
+
return defaultValue;
|
|
1115
|
+
if (typeof value === 'string') {
|
|
1116
|
+
try {
|
|
1117
|
+
return JSON.parse(value);
|
|
1118
|
+
}
|
|
1119
|
+
catch {
|
|
1120
|
+
return defaultValue;
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
return value;
|
|
1124
|
+
}
|
|
1125
|
+
export function rowToPayload(row) {
|
|
1126
|
+
return {
|
|
1127
|
+
content: row.content,
|
|
1128
|
+
category: row.category,
|
|
1129
|
+
subcategory: row.subcategory,
|
|
1130
|
+
project: row.project,
|
|
1131
|
+
tags: parseJsonOrDefault(row.tags, []),
|
|
1132
|
+
importance: row.importance ?? 5,
|
|
1133
|
+
source: row.source || 'self-discovered',
|
|
1134
|
+
created_at: row.created_at,
|
|
1135
|
+
updated_at: row.updated_at,
|
|
1136
|
+
accessed_at: row.accessed_at,
|
|
1137
|
+
access_count: row.access_count ?? 0,
|
|
1138
|
+
related_files: parseJsonOrDefault(row.related_files, undefined),
|
|
1139
|
+
related_memory_ids: parseJsonOrDefault(row.related_memory_ids, undefined),
|
|
1140
|
+
file_checksums: parseJsonOrDefault(row.file_checksums, undefined),
|
|
1141
|
+
trashed_at: row.trashed_at,
|
|
1142
|
+
source_session_chunks: parseJsonOrDefault(row.source_session_chunks, undefined),
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
export function rowToSessionChunkPayload(row) {
|
|
1146
|
+
return {
|
|
1147
|
+
content: row.content,
|
|
1148
|
+
summary: row.summary || '',
|
|
1149
|
+
session_id: row.session_id || '',
|
|
1150
|
+
project: row.project || '',
|
|
1151
|
+
git_branch: row.git_branch,
|
|
1152
|
+
cwd: row.cwd,
|
|
1153
|
+
chunk_index: row.chunk_index ?? 0,
|
|
1154
|
+
start_timestamp: row.start_timestamp || '',
|
|
1155
|
+
end_timestamp: row.end_timestamp || '',
|
|
1156
|
+
tools_used: parseJsonOrDefault(row.tools_used, []),
|
|
1157
|
+
files_modified: parseJsonOrDefault(row.files_modified, []),
|
|
1158
|
+
files_read: parseJsonOrDefault(row.files_read, []),
|
|
1159
|
+
user_messages: parseJsonOrDefault(row.user_messages, []),
|
|
1160
|
+
turn_count: row.turn_count ?? 0,
|
|
1161
|
+
related_memory_ids: parseJsonOrDefault(row.related_memory_ids, []),
|
|
1162
|
+
dedup_memory_id: row.dedup_memory_id,
|
|
1163
|
+
indexed_at: row.indexed_at || '',
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
/**
|
|
1167
|
+
* Close the database connection. Call on process exit.
|
|
1168
|
+
*/
|
|
1169
|
+
export function closeDatabase() {
|
|
1170
|
+
if (db) {
|
|
1171
|
+
db.close();
|
|
1172
|
+
db = null;
|
|
1173
|
+
}
|
|
1174
|
+
memoryVectors.invalidate();
|
|
1175
|
+
chunkVectors.invalidate();
|
|
1176
|
+
}
|
|
1177
|
+
/**
|
|
1178
|
+
* Reopen the database at the current SQLITE_DB_PATH.
|
|
1179
|
+
* Call after updating process.env.SQLITE_DB_PATH to switch databases.
|
|
1180
|
+
*/
|
|
1181
|
+
export async function reopenDatabase() {
|
|
1182
|
+
closeDatabase();
|
|
1183
|
+
await ensureDatabase();
|
|
1184
|
+
}
|
|
1185
|
+
//# sourceMappingURL=sqlite.js.map
|