okengine 0.18.5 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +18 -10
- package/README.md +2 -2
- package/package.json +51 -50
- package/site/content/docs/ai/llms-txt.mdx +1 -1
- package/site/content/docs/ai/skills.mdx +4 -1
- package/site/content/docs/client/auth.mdx +208 -0
- package/site/content/docs/client/calling.mdx +451 -0
- package/site/content/docs/client/index.mdx +208 -0
- package/site/content/docs/client/live.mdx +234 -0
- package/site/content/docs/client/meta.json +5 -0
- package/site/content/docs/client/react.mdx +249 -0
- package/site/content/docs/elements/ai/agents.mdx +235 -0
- package/site/content/docs/elements/ai/index.mdx +342 -0
- package/site/content/docs/elements/ai/mcp.mdx +275 -0
- package/site/content/docs/elements/ai/meta.json +5 -0
- package/site/content/docs/elements/ai/models.mdx +283 -0
- package/site/content/docs/elements/ai/prompts.mdx +257 -0
- package/site/content/docs/elements/channel/email.mdx +269 -0
- package/site/content/docs/elements/channel/index.mdx +344 -0
- package/site/content/docs/elements/channel/meta.json +5 -0
- package/site/content/docs/elements/channel/push.mdx +218 -0
- package/site/content/docs/elements/channel/receipts.mdx +206 -0
- package/site/content/docs/elements/channel/sms.mdx +264 -0
- package/site/content/docs/elements/channel/whatsapp.mdx +220 -0
- package/site/content/docs/elements/clock/index.mdx +301 -0
- package/site/content/docs/elements/clock/meta.json +5 -0
- package/site/content/docs/elements/clock/schedules.mdx +508 -0
- package/site/content/docs/elements/clock/sleep.mdx +448 -0
- package/site/content/docs/elements/flow/consumers.mdx +707 -0
- package/site/content/docs/elements/flow/http.mdx +1080 -0
- package/site/content/docs/elements/flow/index.mdx +618 -0
- package/site/content/docs/elements/flow/meta.json +5 -0
- package/site/content/docs/elements/flow/routing.mdx +559 -0
- package/site/content/docs/elements/flow/workflows.mdx +640 -0
- package/site/content/docs/elements/gate/auth.mdx +371 -0
- package/site/content/docs/elements/gate/authorization.mdx +298 -0
- package/site/content/docs/elements/gate/index.mdx +418 -0
- package/site/content/docs/elements/gate/meta.json +5 -0
- package/site/content/docs/elements/gate/rate-limits.mdx +365 -0
- package/site/content/docs/elements/gate/rls.mdx +303 -0
- package/site/content/docs/elements/gate/tenancy.mdx +375 -0
- package/site/content/docs/elements/index.mdx +20 -10
- package/site/content/docs/elements/signal/broadcast.mdx +519 -0
- package/site/content/docs/elements/signal/index.mdx +352 -0
- package/site/content/docs/elements/signal/live.mdx +591 -0
- package/site/content/docs/elements/signal/meta.json +5 -0
- package/site/content/docs/elements/signal/once.mdx +597 -0
- package/site/content/docs/elements/store/files.mdx +667 -0
- package/site/content/docs/elements/store/index.mdx +313 -0
- package/site/content/docs/elements/store/kv.mdx +637 -0
- package/site/content/docs/elements/store/meta.json +5 -0
- package/site/content/docs/elements/store/search.mdx +950 -0
- package/site/content/docs/elements/store/sql.mdx +941 -0
- package/site/content/docs/elements/vault/config.mdx +259 -0
- package/site/content/docs/elements/vault/index.mdx +356 -0
- package/site/content/docs/elements/vault/meta.json +5 -0
- package/site/content/docs/elements/vault/rotation.mdx +276 -0
- package/site/content/docs/elements/vault/secrets.mdx +288 -0
- package/site/content/docs/index.mdx +52 -40
- package/site/content/docs/meta.json +8 -7
- package/site/content/docs/plugins/cors.mdx +2 -1
- package/site/content/docs/plugins/csrf.mdx +4 -1
- package/site/content/docs/plugins/headers.mdx +2 -1
- package/site/content/docs/plugins/ip-allowlist.mdx +2 -1
- package/site/content/docs/plugins/magic-link.mdx +6 -0
- package/site/content/docs/plugins/maintenance-mode.mdx +2 -1
- package/site/content/docs/plugins/oauth.mdx +1 -1
- package/site/content/docs/plugins/otp.mdx +12 -1
- package/site/content/docs/plugins/passkey.mdx +39 -15
- package/site/content/docs/plugins/two-factor.mdx +91 -34
- package/site/content/docs/plugins/username.mdx +1 -1
- package/site/content/docs/recipes/caddy.mdx +3 -3
- package/site/content/docs/recipes/index.mdx +18 -28
- package/site/content/docs/recipes/mailpit.mdx +1 -1
- package/site/content/docs/recipes/meilisearch.mdx +3 -3
- package/site/content/docs/recipes/meta.json +1 -4
- package/site/content/docs/recipes/nginx.mdx +2 -2
- package/site/content/docs/recipes/openrouter.mdx +283 -0
- package/site/content/docs/recipes/pgdog.mdx +3 -3
- package/site/content/docs/recipes/postgres.mdx +1 -2
- package/site/content/docs/recipes/rustfs.mdx +2 -2
- package/site/content/docs/recipes/traefik.mdx +3 -3
- package/site/content/docs/reference/cli.mdx +231 -0
- package/site/content/docs/reference/configuration.mdx +30 -10
- package/site/content/docs/reference/environment-variables.mdx +93 -20
- package/site/content/docs/reference/errors.mdx +132 -29
- package/site/content/docs/reference/fx.mdx +138 -73
- package/site/content/docs/reference/index.mdx +13 -21
- package/site/content/docs/reference/meta.json +4 -5
- package/site/content/docs/reference/okid.mdx +42 -17
- package/site/content/docs/reference/plugins.mdx +4 -3
- package/site/content/docs/reference/security.mdx +197 -0
- package/site/content/docs/understand/meta.json +5 -0
- package/site/content/docs/understand/the-architecture.mdx +264 -0
- package/site/content/docs/understand/try-it.mdx +58 -0
- package/src/auth/api-keys.ts +2 -1
- package/src/auth/bindings.ts +64 -16
- package/src/auth/gate-auth.test.ts +6 -1
- package/src/auth/identity.ts +152 -5
- package/src/auth/index.ts +29 -0
- package/src/auth/invites.ts +2 -1
- package/src/auth/method-context.ts +41 -0
- package/src/auth/oauth-as/crypto.ts +2 -1
- package/src/auth/oauth-as/stores.ts +2 -1
- package/src/auth/operator.ts +2 -1
- package/src/auth/sessions-jwt.test.ts +77 -0
- package/src/auth/sessions.ts +20 -4
- package/src/auth/tenants.ts +3 -2
- package/src/auth/two-factor-challenge.test.ts +61 -0
- package/src/auth/two-factor-challenge.ts +284 -0
- package/src/auth/verification.ts +5 -0
- package/src/bench/REPORT.md +80 -0
- package/src/bench/g03-signal-once.bench.ts +1 -1
- package/src/bench/g10-observability-contention.bench.ts +1 -1
- package/src/bench/g17-hybrid-search.bench.ts +572 -0
- package/src/bench/load-app.ts +2 -10
- package/src/cli/ai-setup/ai-setup.test.ts +331 -42
- package/src/cli/ai-setup/apply.ts +294 -52
- package/src/cli/ai-setup/catalog.ts +238 -1342
- package/src/cli/ai-setup/index.ts +14 -99
- package/src/cli/ai-setup/prompts.ts +60 -443
- package/src/cli/ask-seed.test.ts +96 -0
- package/src/cli/ask-seed.ts +82 -0
- package/src/cli/ask-vault-gaps.test.ts +84 -0
- package/src/cli/ask-vault-gaps.ts +146 -0
- package/src/cli/build.ts +2 -2
- package/src/cli/client-add.test.ts +26 -1
- package/src/cli/client-add.ts +106 -27
- package/src/cli/db-seed.ts +2 -0
- package/src/cli/db.ts +150 -11
- package/src/cli/dev.ts +119 -211
- package/src/cli/docker-clean.ts +2 -2
- package/src/cli/docker-cli.test.ts +1 -1
- package/src/cli/doctor-diff.ts +4 -2
- package/src/cli/doctor-pii.test.ts +1 -1
- package/src/cli/doctor.ts +14 -1
- package/src/cli/hero-meta.test.ts +4 -2
- package/src/cli/load-config.images.test.ts +8 -10
- package/src/cli/load-config.ts +1 -1
- package/src/cli/registry.ts +22 -10
- package/src/cli/replay.ts +3 -1
- package/src/cli/start.ts +1 -1
- package/src/cli/tui/keys.ts +2 -3
- package/src/client/auth/cookies.ts +74 -0
- package/src/client/auth/create-auth-client.ts +636 -0
- package/src/client/auth/denials.ts +99 -0
- package/src/client/auth/session.ts +283 -0
- package/src/client/auth.test.ts +251 -0
- package/src/client/auth.ts +39 -114
- package/src/client/create-with-session.ts +245 -0
- package/src/client/create.ts +51 -5
- package/src/client/index.ts +11 -1
- package/src/client/live.ts +11 -79
- package/src/client/notes-contract.test.ts +5 -10
- package/src/client/sse.ts +137 -0
- package/src/client/stream.ts +147 -0
- package/src/client/transport.test.ts +32 -0
- package/src/client/transport.ts +123 -26
- package/src/client/types.ts +118 -14
- package/src/client-react/index.ts +185 -24
- package/src/client-react/use-live-query.ts +13 -3
- package/src/compiler/aot.test.ts +7 -4
- package/src/compiler/effects-embed.test.ts +56 -0
- package/src/compiler/effects-fetch.test.ts +43 -0
- package/src/compiler/effects-infer.ts +58 -2
- package/src/compiler/extract.test.ts +257 -43
- package/src/compiler/extract.ts +566 -48
- package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -4
- package/src/compiler/fixtures/skyport/src/flows/bookings/signals.ts +2 -8
- package/src/compiler/fixtures/skyport.expected.json +4 -4
- package/src/compiler/fixtures/triggers/five-triggers.ts +14 -10
- package/src/compiler/response.ts +2 -2
- package/src/compiler/search-writer-isolation.test.ts +40 -0
- package/src/config/index.ts +11 -0
- package/src/console/server/app.ts +17 -23
- package/src/console/server/bind.ts +4 -0
- package/src/console/server/console.test.ts +2 -2
- package/src/console/server/flows-invoke.test.ts +50 -34
- package/src/console/server/flows.ts +436 -255
- package/src/console/server/runs-ingest.test.ts +6 -3
- package/src/console/server/serve.ts +1 -1
- package/src/console/server/signals.test.ts +1 -5
- package/src/console/server/signals.ts +8 -6
- package/src/console/server/state.ts +6 -1
- package/src/console/server/store.ts +1 -1
- package/src/console/ui-next/dist/assets/FileExportIcon-Ck-5od4R.js +1 -0
- package/src/console/ui-next/dist/assets/MoreHorizontalCircle01Icon-gMNGsE37.js +1 -0
- package/src/console/ui-next/dist/assets/PlusSignIcon-CwG3nxfu.js +1 -0
- package/src/console/ui-next/dist/assets/UnavailableIcon-D9cvHVPr.js +1 -0
- package/src/console/ui-next/dist/assets/UserIcon-DaE2PB5_.js +1 -0
- package/src/console/ui-next/dist/assets/access-page-C_qLDhTq.js +4 -0
- package/src/console/ui-next/dist/assets/agent-disclosure-BHVqr3TN.js +1 -0
- package/src/console/ui-next/dist/assets/cache-glyph-CKe92lRQ.js +1 -0
- package/src/console/ui-next/dist/assets/call-pii-button-DEwTl8ZX.js +1 -0
- package/src/console/ui-next/dist/assets/collapsible-BCBtDrCt.js +1 -0
- package/src/console/ui-next/dist/assets/copy-inline-button-CAYD18cr.js +1 -0
- package/src/console/ui-next/dist/assets/dagre.esm-B1_XeuLP.js +1 -0
- package/src/console/ui-next/dist/assets/detail-header-DVWNjWjg.js +1 -0
- package/src/console/ui-next/dist/assets/dropdown-menu-4h2LOVXM.js +1 -0
- package/src/console/ui-next/dist/assets/duration-tone-JroqeuCp.js +9 -0
- package/src/console/ui-next/dist/assets/element-icons-BI8cJgdh.js +1 -0
- package/src/console/ui-next/dist/assets/explorer-empty-CJs5A-wm.js +1 -0
- package/src/console/ui-next/dist/assets/flows-page-CVHa0RTt.js +1 -0
- package/src/console/ui-next/dist/assets/highlighted-json-DjJW6hqe.js +154 -0
- package/src/console/ui-next/dist/assets/http-method-DC5HBdLU.js +1 -0
- package/src/console/ui-next/dist/assets/index-CYjiZ3WO.js +63 -0
- package/src/console/ui-next/dist/assets/index-D0zS5rKO.css +2 -0
- package/src/console/ui-next/dist/assets/observability-page-CAYMyKb3.js +4 -0
- package/src/console/ui-next/dist/assets/react-dom-Ddte4I-Q.js +9 -0
- package/src/console/ui-next/dist/assets/replica-lag-yAQYLv75.js +18 -0
- package/src/console/ui-next/dist/assets/request-meta-D0yusGxJ.js +1 -0
- package/src/console/ui-next/dist/assets/shortcut-keys-3ILd8oGn.js +1 -0
- package/src/console/ui-next/dist/assets/{sql-BskegiFM.js → sql-BsFa4tDR.js} +1 -1
- package/src/console/ui-next/dist/assets/store-page-BTKJeJ02.js +41 -0
- package/src/console/ui-next/dist/assets/trace-detail-sheet-Bp-Yygs5.js +2 -0
- package/src/console/ui-next/dist/assets/tree-expand-toggle-DoaVDfAM.js +55 -0
- package/src/console/ui-next/dist/assets/units-page-BRz7xyYL.js +1 -0
- package/src/console/ui-next/dist/assets/{use-vault-list-uk4WVboC.js → use-vault-list-CT4-gajj.js} +1 -1
- package/src/console/ui-next/dist/assets/vault-page-3jQt-bOJ.js +2 -0
- package/src/console/ui-next/dist/assets/xyflow-CSyC6ryz.css +1 -0
- package/src/console/ui-next/dist/assets/xyflow-yApv7D4e.js +7 -0
- package/src/console/ui-next/dist/index.html +6 -13
- package/src/console/ui-next/seed-invoke-host.ts +21 -18
- package/src/console/ui-next/src/client.ts +7 -2
- package/src/console/ui-next/src/features/flows/graph/element-map.test.ts +1 -1
- package/src/console/ui-next/src/features/flows/graph/element-map.ts +5 -3
- package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +12 -2
- package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +4 -0
- package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +8 -0
- package/src/console/ui-next/src/features/flows/traces/trace-detail.test.ts +4 -5
- package/src/console/ui-next/src/features/flows/traces/trace-gates.ts +3 -6
- package/src/console/ui-next/src/features/flows/traces/waterfall-bars.ts +4 -0
- package/src/console/ui-next/src/features/flows/traces/waterfall-tooltip.ts +9 -3
- package/src/console/ui-next/src/features/store/detail/reveal-cell.tsx +7 -11
- package/src/console/ui-next/src/features/store/detail/store-row-detail-sheet.tsx +2 -2
- package/src/console/ui-next/src/features/store/lib/fields-from-table.ts +2 -0
- package/src/console/ui-next/src/features/store/lib/grid-model.test.ts +25 -1
- package/src/console/ui-next/src/features/store/lib/grid-model.ts +36 -1
- package/src/console/ui-next/src/features/store/query/query-results.tsx +3 -3
- package/src/console/ui-next/src/features/units/detail/effects-summary.tsx +2 -0
- package/src/console/ui-next/src/features/units/lib/call-read-safe.ts +3 -1
- package/src/console/ui-next/src/features/units/lib/fields-from-schema.ts +6 -0
- package/src/docker/ai-model-status.test.ts +1 -12
- package/src/docker/ai-model-status.ts +10 -38
- package/src/docker/compose-up.test.ts +100 -0
- package/src/docker/compose-up.ts +292 -0
- package/src/docker/compose.ts +4 -14
- package/src/docker/derive.ts +9 -34
- package/src/docker/docker.test.ts +16 -261
- package/src/docker/images-config.test.ts +13 -25
- package/src/docker/index.ts +1 -24
- package/src/docker/recipes/index.ts +0 -23
- package/src/docker/recipes/pgdog.ts +6 -4
- package/src/docker/stack-id.test.ts +2 -2
- package/src/docker/stack-id.ts +0 -1
- package/src/docker/types.ts +2 -2
- package/src/drivers/ai-anthropic.ts +10 -0
- package/src/drivers/ai-openai-compatible.ts +34 -7
- package/src/drivers/ai-providers.test.ts +0 -107
- package/src/drivers/ai-stream.test.ts +0 -34
- package/src/drivers/ai-types.ts +17 -8
- package/src/drivers/channel-fcm.ts +6 -1
- package/src/drivers/channel-msegat.ts +6 -1
- package/src/drivers/channel-resend.ts +5 -1
- package/src/drivers/channel-smtp.ts +5 -1
- package/src/drivers/channel-sndr.ts +10 -1
- package/src/drivers/channel-taqnyat-mail.ts +5 -1
- package/src/drivers/channel-taqnyat-whatsapp.ts +6 -1
- package/src/drivers/channel-taqnyat.ts +6 -1
- package/src/drivers/channel-types.ts +10 -0
- package/src/drivers/channel-unifonic.ts +6 -1
- package/src/drivers/channel-wa-cloud.ts +6 -1
- package/src/drivers/channel-webpush.ts +6 -1
- package/src/drivers/external.ts +33 -0
- package/src/drivers/index.ts +0 -10
- package/src/drivers/meilisearch.ts +6 -0
- package/src/drivers/oauth-types.ts +4 -0
- package/src/drivers/postgres.test.ts +74 -3
- package/src/drivers/postgres.ts +175 -6
- package/src/drivers/signal-types.ts +5 -5
- package/src/drivers/types.ts +7 -0
- package/src/drivers/vault-types.ts +5 -0
- package/src/elements/ai/declare.ts +17 -4
- package/src/elements/ai/eval.ts +1 -1
- package/src/elements/ai/mcp-http.ts +1 -1
- package/src/elements/ai/pii.ts +1 -1
- package/src/elements/ai/providers.test.ts +289 -0
- package/src/elements/ai/providers.ts +169 -0
- package/src/elements/ai/runtime.ts +68 -5
- package/src/elements/ai/schema.ts +2 -2
- package/src/elements/ai.test.ts +7 -7
- package/src/elements/ai.ts +17 -1
- package/src/elements/channel/runtime.ts +105 -12
- package/src/elements/clock/cron-fields.test.ts +144 -0
- package/src/elements/clock/cron-fields.ts +185 -0
- package/src/elements/clock/declare.ts +247 -3
- package/src/elements/clock.ts +21 -1
- package/src/elements/gate/declare.ts +1 -1
- package/src/elements/gate.ts +1 -1
- package/src/elements/index.ts +15 -0
- package/src/elements/signal/chaos-child.ts +1 -2
- package/src/elements/signal/declare.ts +65 -37
- package/src/elements/signal/delivery-modes.test.ts +11 -31
- package/src/elements/signal/dry-run-replay.test.ts +1 -7
- package/src/elements/signal/dry-run-write-isolation.test.ts +1 -7
- package/src/elements/signal/key-ordering.test.ts +6 -26
- package/src/elements/signal/lease-reclaim.test.ts +2 -6
- package/src/elements/signal/optional-emit.test.ts +6 -9
- package/src/elements/signal/order-lifecycle.test.ts +4 -17
- package/src/elements/signal/orphan-messages.test.ts +4 -15
- package/src/elements/signal/reconcile.test.ts +2 -2
- package/src/elements/signal/runtime.ts +1 -1
- package/src/elements/signal/schema-emit.test.ts +4 -8
- package/src/elements/signal.test.ts +24 -49
- package/src/elements/signal.ts +9 -2
- package/src/elements/store/domain-ddl.test.ts +1 -1
- package/src/elements/store/live-http.test.ts +9 -4
- package/src/elements/store/prepare-row.test.ts +123 -0
- package/src/elements/store/resource.ts +43 -12
- package/src/elements/store/schema-decl.ts +117 -0
- package/src/elements/store/search-backfill.ts +205 -0
- package/src/elements/store/search-bind.ts +66 -0
- package/src/elements/store/search-bm25.ts +78 -0
- package/src/elements/store/search-ddl.ts +156 -0
- package/src/elements/store/search-embed-flow.ts +141 -0
- package/src/elements/store/search-errors.ts +34 -0
- package/src/elements/store/search-fusion.ts +112 -0
- package/src/elements/store/search-lsh.ts +214 -0
- package/src/elements/store/search-runtime.pglite.test.ts +186 -0
- package/src/elements/store/search-runtime.ts +314 -0
- package/src/elements/store/search.test.ts +226 -0
- package/src/elements/store/sql-session.test.ts +1 -0
- package/src/elements/store/sql-session.ts +83 -3
- package/src/elements/store/table.ts +23 -2
- package/src/elements/store/upsert-app.test.ts +1 -3
- package/src/elements/store.ts +52 -0
- package/src/full.ts +4 -2
- package/src/http.ts +4 -1
- package/src/i18n/catalogs/ar.ts +14 -6
- package/src/i18n/catalogs/en.ts +14 -6
- package/src/index.ts +6 -1
- package/src/kernel/adopt-barrel-fresh.test.ts +7 -7
- package/src/kernel/adopt-routes.ts +9 -1
- package/src/kernel/app-auth.ts +5 -0
- package/src/kernel/app.ts +102 -9
- package/src/kernel/auto-cache.test.ts +6 -12
- package/src/kernel/auto-registry.test.ts +3 -3
- package/src/kernel/boot-bind/ai.test.ts +22 -19
- package/src/kernel/boot-bind/ai.ts +5 -43
- package/src/kernel/boot-bind/clock.ts +23 -5
- package/src/kernel/boot-bind/honor-config.test.ts +4 -4
- package/src/kernel/boot.test.ts +11 -6
- package/src/kernel/boot.ts +66 -16
- package/src/kernel/boundary-contract.ts +93 -0
- package/src/kernel/budget.test.ts +1 -1
- package/src/kernel/call.ts +89 -0
- package/src/kernel/capability.ts +6 -0
- package/src/kernel/client-descriptor.ts +123 -0
- package/src/kernel/clock-timezone.test.ts +80 -0
- package/src/kernel/correlation.test.ts +1 -1
- package/src/kernel/dry-run.ts +11 -8
- package/src/kernel/effects-stamping.test.ts +42 -9
- package/src/kernel/effects.test.ts +4 -2
- package/src/kernel/effects.ts +51 -9
- package/src/kernel/errors-channel.ts +17 -0
- package/src/kernel/errors-live-resume.ts +3 -2
- package/src/kernel/errors-tenant.ts +7 -4
- package/src/kernel/errors.registry-helpers.ts +96 -0
- package/src/kernel/errors.registry.test.ts +139 -25
- package/src/kernel/errors.ts +102 -23
- package/src/kernel/external-effects.test.ts +196 -0
- package/src/kernel/flow.test.ts +13 -4
- package/src/kernel/flow.ts +69 -71
- package/src/kernel/fx-ask-telemetry.test.ts +2 -2
- package/src/kernel/fx-dead-letters.test.ts +3 -3
- package/src/kernel/fx-fetch.ts +55 -0
- package/src/kernel/fx-live-stream.ts +2 -2
- package/src/kernel/fx-live.test.ts +8 -8
- package/src/kernel/fx.test.ts +17 -11
- package/src/kernel/fx.ts +180 -57
- package/src/kernel/horizontal-child.ts +1 -1
- package/src/kernel/http-query.test.ts +3 -6
- package/src/kernel/index.ts +13 -3
- package/src/kernel/instance-id.ts +1 -1
- package/src/kernel/instances.test.ts +40 -0
- package/src/kernel/instances.ts +47 -9
- package/src/kernel/live-http.test.ts +6 -7
- package/src/kernel/live-http.ts +6 -2
- package/src/kernel/live-resume.test.ts +1 -1
- package/src/kernel/mcp-tool.test.ts +3 -3
- package/src/kernel/on.ts +98 -4
- package/src/kernel/pipeline.test.ts +12 -15
- package/src/kernel/plugin-elements.test.ts +1 -1
- package/src/kernel/stamp-http.test.ts +3 -3
- package/src/kernel/triggers.ts +210 -95
- package/src/kernel-entry.ts +0 -1
- package/src/manifest/diff.ts +11 -1
- package/src/manifest/fixtures/skyport.excerpt.json +1 -1
- package/src/manifest/types.ts +46 -2
- package/src/mcp/docs-index.ts +3 -3
- package/src/mcp/docs-mcp.test.ts +2 -2
- package/src/mcp/docs-tools.ts +2 -1
- package/src/okid.test.ts +56 -0
- package/src/okid.ts +55 -11
- package/src/plugins/anonymous.ts +8 -4
- package/src/plugins/auth/shared.ts +27 -3
- package/src/plugins/auth-delivery.mailpit.integration.test.ts +1 -1
- package/src/plugins/auth-methods.security.test.ts +561 -23
- package/src/plugins/config-source.ts +1 -1
- package/src/plugins/csrf.test.ts +65 -0
- package/src/plugins/index.ts +2 -0
- package/src/plugins/magic-link.ts +36 -16
- package/src/plugins/oauth/shared.ts +3 -1
- package/src/plugins/oauth.ts +22 -14
- package/src/plugins/otp.ts +37 -21
- package/src/plugins/passkey-webauthn.ts +9 -6
- package/src/plugins/passkey.ts +98 -26
- package/src/plugins/pre-account-hijack.test.ts +223 -0
- package/src/plugins/two-factor.ts +466 -37
- package/src/plugins/username.ts +19 -7
- package/src/release/build-lib.ts +1 -0
- package/src/release/limits.ts +2 -2
- package/src/release/measure.ts +1 -1
- package/src/runs/collect.test.ts +0 -2
- package/src/runtime/json-code-block.test.ts +250 -20
- package/src/runtime/json-code-block.ts +1261 -41
- package/src/term.test.ts +1 -1
- package/src/test/create-test-app.test.ts +12 -12
- package/src/test/live-signals.test.ts +6 -6
- package/src/test/provisions.integration.test.ts +10 -14
- package/src/test/reset-element-registries.ts +1 -1
- package/src/test/tenant-isolation.test.ts +12 -6
- package/site/content/docs/deployment/docker-swarm.mdx +0 -164
- package/site/content/docs/deployment/docker.mdx +0 -227
- package/site/content/docs/deployment/index.mdx +0 -83
- package/site/content/docs/deployment/kubernetes.mdx +0 -176
- package/site/content/docs/deployment/meta.json +0 -5
- package/site/content/docs/deployment/reverse-proxy.mdx +0 -234
- package/site/content/docs/elements/ai.mdx +0 -385
- package/site/content/docs/elements/channel.mdx +0 -346
- package/site/content/docs/elements/clock.mdx +0 -244
- package/site/content/docs/elements/flow.mdx +0 -420
- package/site/content/docs/elements/gate.mdx +0 -436
- package/site/content/docs/elements/signal.mdx +0 -380
- package/site/content/docs/elements/store.mdx +0 -1099
- package/site/content/docs/elements/vault.mdx +0 -405
- package/site/content/docs/get-started/basic-usage.mdx +0 -173
- package/site/content/docs/get-started/index.mdx +0 -43
- package/site/content/docs/get-started/installation.mdx +0 -220
- package/site/content/docs/get-started/introduction.mdx +0 -144
- package/site/content/docs/get-started/meta.json +0 -13
- package/site/content/docs/get-started/project-structure.mdx +0 -925
- package/site/content/docs/get-started/testing.mdx +0 -328
- package/site/content/docs/get-started/why.mdx +0 -114
- package/site/content/docs/recipes/llama-cpp.mdx +0 -151
- package/site/content/docs/recipes/ollama.mdx +0 -142
- package/site/content/docs/recipes/sglang.mdx +0 -105
- package/site/content/docs/recipes/vllm.mdx +0 -106
- package/site/content/docs/reference/cli.md +0 -232
- package/site/content/docs/reference/client.mdx +0 -469
- package/site/content/docs/reference/security.md +0 -74
- package/src/cli/ai-setup/detect-ollama.ts +0 -213
- package/src/cli/ai-setup/recommend.test.ts +0 -225
- package/src/cli/ai-setup/recommend.ts +0 -225
- package/src/cli/dev-controls.test.ts +0 -122
- package/src/cli/dev-controls.ts +0 -164
- package/src/cli/tui/DevLive.tsx +0 -126
- package/src/console/ui-next/dist/assets/access-page-3-EFj-2G.js +0 -4
- package/src/console/ui-next/dist/assets/agent-disclosure-BP0Y0Sux.js +0 -1
- package/src/console/ui-next/dist/assets/cache-glyph-B5X-NM0-.js +0 -1
- package/src/console/ui-next/dist/assets/call-pii-button-ChAUiLo9.js +0 -1
- package/src/console/ui-next/dist/assets/collapsible-DGnOM2ph.js +0 -1
- package/src/console/ui-next/dist/assets/copy-inline-button-DBHhgHKP.js +0 -1
- package/src/console/ui-next/dist/assets/dagre.esm-ZwcdTuZZ.js +0 -1
- package/src/console/ui-next/dist/assets/detail-header-DhHM1iaZ.js +0 -1
- package/src/console/ui-next/dist/assets/dropdown-menu-_NjTEo5_.js +0 -1
- package/src/console/ui-next/dist/assets/duration-tone-sC3lGABz.js +0 -9
- package/src/console/ui-next/dist/assets/element-icons-BVXtRyd3.js +0 -1
- package/src/console/ui-next/dist/assets/explorer-empty-2uIhBu0_.js +0 -1
- package/src/console/ui-next/dist/assets/flows-page-cVFnA4HH.js +0 -1
- package/src/console/ui-next/dist/assets/highlighted-json-Awq7gYdu.js +0 -154
- package/src/console/ui-next/dist/assets/http-method-_UHM2ODJ.js +0 -1
- package/src/console/ui-next/dist/assets/index-CMIgUbD0.js +0 -66
- package/src/console/ui-next/dist/assets/index-Ck88Jmv8.css +0 -2
- package/src/console/ui-next/dist/assets/link-BX6Vqztd.js +0 -1
- package/src/console/ui-next/dist/assets/observability-page-CQ3p34ip.js +0 -4
- package/src/console/ui-next/dist/assets/preload-helper-oH4irX4C.js +0 -1
- package/src/console/ui-next/dist/assets/react-D8E3mtu1.js +0 -1
- package/src/console/ui-next/dist/assets/react-dom-Bph1y7z7.js +0 -9
- package/src/console/ui-next/dist/assets/replica-lag-DKRrbvdo.js +0 -18
- package/src/console/ui-next/dist/assets/request-meta-DV0ywz7t.js +0 -1
- package/src/console/ui-next/dist/assets/shortcut-JQIZlWfm.js +0 -1
- package/src/console/ui-next/dist/assets/shortcut-keys-DKxNTe_m.js +0 -1
- package/src/console/ui-next/dist/assets/skeleton-D-czQJT6.js +0 -1
- package/src/console/ui-next/dist/assets/store-page-02xOiqIK.js +0 -41
- package/src/console/ui-next/dist/assets/trace-detail-sheet-B09O8rA6.js +0 -2
- package/src/console/ui-next/dist/assets/tree-expand-toggle-BtyhmWb4.js +0 -55
- package/src/console/ui-next/dist/assets/units-page-l8FeKfnP.js +0 -1
- package/src/console/ui-next/dist/assets/useMutation-B8EO02Ej.js +0 -1
- package/src/console/ui-next/dist/assets/useRender-BE2A9BWC.js +0 -1
- package/src/console/ui-next/dist/assets/vault-page-CL-d_mLE.js +0 -2
- package/src/console/ui-next/dist/assets/xyflow-D7n4g6go.js +0 -7
- package/src/console/ui-next/dist/assets/xyflow-DZ0Ws1xk.css +0 -1
- package/src/docker/ollama-pull.ts +0 -232
- package/src/docker/recipes/llama-cpp.ts +0 -298
- package/src/docker/recipes/ollama.ts +0 -44
- package/src/docker/recipes/sglang.ts +0 -55
- package/src/docker/recipes/vllm.ts +0 -44
- package/src/drivers/ai-ollama-tools.integration.test.ts +0 -109
- package/src/drivers/ai-ollama.integration.test.ts +0 -184
- package/src/drivers/ai-ollama.ts +0 -389
- package/src/drivers/ollama.ts +0 -14
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Random-hyperplane LSH — K fixed planes generated once per field lifetime.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
6
|
+
import { LSH_DEFAULT_K } from "./search-errors.ts";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Stable seed string for a field's hyperplanes.
|
|
10
|
+
*
|
|
11
|
+
* @param table - SQL table
|
|
12
|
+
* @param column - SQL column
|
|
13
|
+
* @param dims - Embedding dimensionality
|
|
14
|
+
* @param k - Number of planes
|
|
15
|
+
*/
|
|
16
|
+
export function hyperplaneSeed(table: string, column: string, dims: number, k: number): string {
|
|
17
|
+
return `${table}|${column}|${dims}|${k}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Generate K unit-ish random hyperplanes in `dims` dimensions from a seed.
|
|
22
|
+
* Deterministic across hosts for the same seed.
|
|
23
|
+
*
|
|
24
|
+
* @param seed - Stable seed string
|
|
25
|
+
* @param dims - Vector dimensionality
|
|
26
|
+
* @param k - Plane count (default {@link LSH_DEFAULT_K})
|
|
27
|
+
*/
|
|
28
|
+
export function generateHyperplanes(
|
|
29
|
+
seed: string,
|
|
30
|
+
dims: number,
|
|
31
|
+
k: number = LSH_DEFAULT_K,
|
|
32
|
+
): Float32Array[] {
|
|
33
|
+
const planes: Float32Array[] = [];
|
|
34
|
+
let counter = 0;
|
|
35
|
+
for (let i = 0; i < k; i++) {
|
|
36
|
+
const plane = new Float32Array(dims);
|
|
37
|
+
let filled = 0;
|
|
38
|
+
while (filled < dims) {
|
|
39
|
+
const h = createHash("sha256").update(`${seed}\0${counter++}`).digest();
|
|
40
|
+
for (let b = 0; b + 3 < h.length && filled < dims; b += 4) {
|
|
41
|
+
const u = h.readUInt32BE(b) / 0xffff_ffff;
|
|
42
|
+
plane[filled++] = u * 2 - 1;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// L2 normalize
|
|
46
|
+
let norm = 0;
|
|
47
|
+
for (let j = 0; j < dims; j++) norm += plane[j]! * plane[j]!;
|
|
48
|
+
norm = Math.sqrt(norm) || 1;
|
|
49
|
+
for (let j = 0; j < dims; j++) plane[j]! /= norm;
|
|
50
|
+
planes.push(plane);
|
|
51
|
+
}
|
|
52
|
+
return planes;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Pack LSH bucket bits into a bigint (K ≤ 64).
|
|
57
|
+
*
|
|
58
|
+
* @param vector - Embedding
|
|
59
|
+
* @param planes - Fixed hyperplanes
|
|
60
|
+
*/
|
|
61
|
+
export function lshBucket(vector: readonly number[], planes: readonly Float32Array[]): bigint {
|
|
62
|
+
if (planes.length > 64) {
|
|
63
|
+
throw new Error(`lshBucket: K=${planes.length} exceeds bigint packing (max 64)`);
|
|
64
|
+
}
|
|
65
|
+
let bits = 0n;
|
|
66
|
+
for (let i = 0; i < planes.length; i++) {
|
|
67
|
+
const plane = planes[i]!;
|
|
68
|
+
if (vector.length !== plane.length) {
|
|
69
|
+
throw new Error(`lshBucket: vector length ${vector.length} !== plane dims ${plane.length}`);
|
|
70
|
+
}
|
|
71
|
+
let dot = 0;
|
|
72
|
+
for (let j = 0; j < plane.length; j++) {
|
|
73
|
+
dot += vector[j]! * plane[j]!;
|
|
74
|
+
}
|
|
75
|
+
if (dot >= 0) bits |= 1n << BigInt(i);
|
|
76
|
+
}
|
|
77
|
+
return bits;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Encode an LSH bucket for PostgreSQL `bigint` (signed int64).
|
|
82
|
+
* K=64 bit patterns with the high bit set exceed unsigned range when passed
|
|
83
|
+
* as a decimal string — reinterpret as two's-complement signed.
|
|
84
|
+
*
|
|
85
|
+
* @param bucket - Unsigned bit pack from {@link lshBucket}
|
|
86
|
+
*/
|
|
87
|
+
export function lshBucketToSql(bucket: bigint): string {
|
|
88
|
+
const masked = bucket & 0xffff_ffff_ffff_ffffn;
|
|
89
|
+
if (masked >= 0x8000_0000_0000_0000n) {
|
|
90
|
+
return (masked - 0x1_0000_0000_0000_0000n).toString();
|
|
91
|
+
}
|
|
92
|
+
return masked.toString();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Decode a PostgreSQL `bigint` LSH value back to an unsigned bit pack.
|
|
97
|
+
*
|
|
98
|
+
* @param value - Driver value (string | number | bigint)
|
|
99
|
+
*/
|
|
100
|
+
export function lshBucketFromSql(value: unknown): bigint {
|
|
101
|
+
const n = typeof value === "bigint" ? value : BigInt(String(value));
|
|
102
|
+
return n < 0n ? n + 0x1_0000_0000_0000_0000n : n;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Cosine similarity in [−1, 1].
|
|
107
|
+
*
|
|
108
|
+
* @param a - Vector a
|
|
109
|
+
* @param b - Vector b
|
|
110
|
+
*/
|
|
111
|
+
export function cosineSimilarity(a: readonly number[], b: readonly number[]): number {
|
|
112
|
+
if (a.length !== b.length) {
|
|
113
|
+
throw new Error(`cosineSimilarity: length mismatch ${a.length} vs ${b.length}`);
|
|
114
|
+
}
|
|
115
|
+
let dot = 0;
|
|
116
|
+
let na = 0;
|
|
117
|
+
let nb = 0;
|
|
118
|
+
for (let i = 0; i < a.length; i++) {
|
|
119
|
+
dot += a[i]! * b[i]!;
|
|
120
|
+
na += a[i]! * a[i]!;
|
|
121
|
+
nb += b[i]! * b[i]!;
|
|
122
|
+
}
|
|
123
|
+
const denom = Math.sqrt(na) * Math.sqrt(nb);
|
|
124
|
+
return denom === 0 ? 0 : dot / denom;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Hamming distance between two K-bit LSH packs (K ≤ 64).
|
|
129
|
+
*
|
|
130
|
+
* Random-hyperplane (Charikar) SimHash ranks neighbors by this distance.
|
|
131
|
+
* Hamming-1 equality is not a viable candidate set at {@link LSH_DEFAULT_K}:
|
|
132
|
+
* true near-neighbors typically sit at distance ~5–16, not 0–1.
|
|
133
|
+
*
|
|
134
|
+
* @param a - Bucket a
|
|
135
|
+
* @param b - Bucket b
|
|
136
|
+
*/
|
|
137
|
+
export function hammingDistance(a: bigint, b: bigint): number {
|
|
138
|
+
let x = (a ^ b) & 0xffff_ffff_ffff_ffffn;
|
|
139
|
+
let count = 0;
|
|
140
|
+
while (x) {
|
|
141
|
+
x &= x - 1n;
|
|
142
|
+
count++;
|
|
143
|
+
}
|
|
144
|
+
return count;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Candidate buckets: exact match plus Hamming distance 1 flips.
|
|
149
|
+
*
|
|
150
|
+
* Kept for tight-collision tests and callers that want a 65-wide equality
|
|
151
|
+
* probe. Query-time retrieval uses {@link lshHammingSql} ranking instead —
|
|
152
|
+
* Hamming-1 alone misses almost all true neighbors at K=64.
|
|
153
|
+
*
|
|
154
|
+
* @param bucket - Query bucket
|
|
155
|
+
* @param k - Bit width
|
|
156
|
+
*/
|
|
157
|
+
export function neighborBuckets(bucket: bigint, k: number): bigint[] {
|
|
158
|
+
const out: bigint[] = [bucket];
|
|
159
|
+
for (let i = 0; i < k; i++) {
|
|
160
|
+
out.push(bucket ^ (1n << BigInt(i)));
|
|
161
|
+
}
|
|
162
|
+
return out;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Postgres 14+ Hamming distance between a stored signed-int64 LSH column
|
|
167
|
+
* and a bound query bucket (`?::bigint`). Used as `ORDER BY … LIMIT k`.
|
|
168
|
+
*
|
|
169
|
+
* @param columnSql - Quoted LSH column identifier
|
|
170
|
+
* @param bucketPlaceholder - Bound-parameter placeholder (`?` before `$n` rewrite)
|
|
171
|
+
*/
|
|
172
|
+
export function lshHammingSql(columnSql: string, bucketPlaceholder: string = "?"): string {
|
|
173
|
+
return `bit_count((${columnSql} # ${bucketPlaceholder}::bigint)::bit(64))`;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Serialize planes for `oke_search_planes.planes` (Float32 little-endian).
|
|
178
|
+
*
|
|
179
|
+
* @param planes - Hyperplanes
|
|
180
|
+
*/
|
|
181
|
+
export function serializePlanes(planes: readonly Float32Array[]): Buffer {
|
|
182
|
+
const dims = planes[0]?.length ?? 0;
|
|
183
|
+
const buf = Buffer.allocUnsafe(4 + planes.length * dims * 4);
|
|
184
|
+
buf.writeUInt32LE(dims, 0);
|
|
185
|
+
let offset = 4;
|
|
186
|
+
for (const plane of planes) {
|
|
187
|
+
for (let i = 0; i < dims; i++) {
|
|
188
|
+
buf.writeFloatLE(plane[i]!, offset);
|
|
189
|
+
offset += 4;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return buf;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Deserialize planes from storage.
|
|
197
|
+
*
|
|
198
|
+
* @param buf - Stored bytes
|
|
199
|
+
* @param k - Expected plane count
|
|
200
|
+
*/
|
|
201
|
+
export function deserializePlanes(buf: Buffer, k: number): Float32Array[] {
|
|
202
|
+
const dims = buf.readUInt32LE(0);
|
|
203
|
+
const planes: Float32Array[] = [];
|
|
204
|
+
let offset = 4;
|
|
205
|
+
for (let i = 0; i < k; i++) {
|
|
206
|
+
const plane = new Float32Array(dims);
|
|
207
|
+
for (let j = 0; j < dims; j++) {
|
|
208
|
+
plane[j] = buf.readFloatLE(offset);
|
|
209
|
+
offset += 4;
|
|
210
|
+
}
|
|
211
|
+
planes.push(plane);
|
|
212
|
+
}
|
|
213
|
+
return planes;
|
|
214
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hybrid search runtime — PGlite end-to-end for LSH candidate SQL.
|
|
3
|
+
*
|
|
4
|
+
* Captures the literal SQL `runSqlSearch` issues and checks K=64 Hamming-rank
|
|
5
|
+
* recovery on the same synthetic hash-bag G17 uses (40-row hand case).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
9
|
+
import { createHash } from "node:crypto";
|
|
10
|
+
import type { DeclaredColumn } from "../../manifest/types.ts";
|
|
11
|
+
import { pgliteDriver } from "../../drivers/pglite.ts";
|
|
12
|
+
import type { SqlConnection } from "../../drivers/types.ts";
|
|
13
|
+
import {
|
|
14
|
+
embColumn,
|
|
15
|
+
ensureHyperplaneInserts,
|
|
16
|
+
lshColumn,
|
|
17
|
+
OKE_SEARCH_PLANES,
|
|
18
|
+
searchDdlForTable,
|
|
19
|
+
} from "./search-ddl.ts";
|
|
20
|
+
import { LSH_DEFAULT_K } from "./search-errors.ts";
|
|
21
|
+
import {
|
|
22
|
+
cosineSimilarity,
|
|
23
|
+
deserializePlanes,
|
|
24
|
+
lshBucket,
|
|
25
|
+
lshBucketFromSql,
|
|
26
|
+
lshBucketToSql,
|
|
27
|
+
} from "./search-lsh.ts";
|
|
28
|
+
import { runSqlSearch, type SearchColumnMeta } from "./search-runtime.ts";
|
|
29
|
+
|
|
30
|
+
const TABLE = "lsh_recall_docs";
|
|
31
|
+
const DIMS = 32;
|
|
32
|
+
const TOPICS = [
|
|
33
|
+
"refund policy shipping delay",
|
|
34
|
+
"password reset two factor auth",
|
|
35
|
+
"invoice payment stripe webhook",
|
|
36
|
+
"search ranking bm25 hybrid",
|
|
37
|
+
"postgres gin btree index plan",
|
|
38
|
+
"tenant isolation row level security",
|
|
39
|
+
"durable flow journal resume",
|
|
40
|
+
"live query fanout subscriber",
|
|
41
|
+
] as const;
|
|
42
|
+
|
|
43
|
+
const COLS: Record<string, DeclaredColumn> = {
|
|
44
|
+
id: { type: "text", sqlName: "id", primaryKey: true },
|
|
45
|
+
title: { type: "text", sqlName: "title", searchable: { weight: 2 } },
|
|
46
|
+
body: {
|
|
47
|
+
type: "text",
|
|
48
|
+
sqlName: "body",
|
|
49
|
+
searchable: { weight: 1 },
|
|
50
|
+
embed: { dims: DIMS, model: "mock" },
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const SEARCH_COLS: SearchColumnMeta[] = [
|
|
55
|
+
{ key: "title", sqlName: "title", weight: 2 },
|
|
56
|
+
{ key: "body", sqlName: "body", weight: 1, embed: { dims: DIMS, model: "mock" } },
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
let conn: SqlConnection;
|
|
60
|
+
|
|
61
|
+
beforeAll(async () => {
|
|
62
|
+
conn = await pgliteDriver.connect({ url: "memory://lsh-recall-runtime", role: "primary" });
|
|
63
|
+
}, 20_000);
|
|
64
|
+
|
|
65
|
+
afterAll(async () => {
|
|
66
|
+
await conn.close();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* G17 synthetic embedding — deterministic SHA-256 hash bag, L2-normalized.
|
|
71
|
+
*
|
|
72
|
+
* @param text - Source text
|
|
73
|
+
*/
|
|
74
|
+
function synthEmbed(text: string): number[] {
|
|
75
|
+
const v = Array.from({ length: DIMS }, () => 0);
|
|
76
|
+
const tokens = text.toLowerCase().split(/\W+/).filter(Boolean);
|
|
77
|
+
for (const t of tokens) {
|
|
78
|
+
const h = createHash("sha256").update(t).digest();
|
|
79
|
+
for (let i = 0; i < DIMS; i++) {
|
|
80
|
+
v[i]! += (h[i % h.length]! / 255) * 2 - 1;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
let norm = 0;
|
|
84
|
+
for (const x of v) norm += x * x;
|
|
85
|
+
norm = Math.sqrt(norm) || 1;
|
|
86
|
+
return v.map((x) => x / norm);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
describe("runSqlSearch LSH candidate path (PGlite)", () => {
|
|
90
|
+
test("issued SQL ranks by bit_count Hamming, not Hamming-1 ANY(); recovers exact top-10", async () => {
|
|
91
|
+
await conn.exec(`DROP TABLE IF EXISTS ${TABLE} CASCADE`);
|
|
92
|
+
await conn.exec(`
|
|
93
|
+
CREATE TABLE ${TABLE} (
|
|
94
|
+
id text PRIMARY KEY,
|
|
95
|
+
title text NOT NULL,
|
|
96
|
+
body text NOT NULL
|
|
97
|
+
)
|
|
98
|
+
`);
|
|
99
|
+
for (const stmt of searchDdlForTable(TABLE, COLS)) {
|
|
100
|
+
await conn.exec(stmt);
|
|
101
|
+
}
|
|
102
|
+
for (const ins of ensureHyperplaneInserts(TABLE, COLS)) {
|
|
103
|
+
await conn.exec(ins.sql, ins.params);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const planesRow = await conn.query(
|
|
107
|
+
`SELECT k, planes FROM ${OKE_SEARCH_PLANES} WHERE table_name = ? AND column_name = ?`,
|
|
108
|
+
[TABLE, "body"],
|
|
109
|
+
);
|
|
110
|
+
const prow = planesRow[0]!;
|
|
111
|
+
const k = Number(prow["k"] ?? LSH_DEFAULT_K);
|
|
112
|
+
const planes = deserializePlanes(Buffer.from(prow["planes"] as Buffer), k);
|
|
113
|
+
|
|
114
|
+
const vectors: number[][] = [];
|
|
115
|
+
const n = 40;
|
|
116
|
+
for (let i = 0; i < n; i++) {
|
|
117
|
+
const topic = TOPICS[i % TOPICS.length]!;
|
|
118
|
+
const id = `d${String(i).padStart(8, "0")}`;
|
|
119
|
+
const title = `${topic} item ${i}`;
|
|
120
|
+
const body = `${topic}. Document ${i} discusses ${topic} with enough tokens for BM25.`;
|
|
121
|
+
const vec = synthEmbed(body);
|
|
122
|
+
const bucket = lshBucket(vec, planes);
|
|
123
|
+
vectors.push(vec);
|
|
124
|
+
await conn.exec(
|
|
125
|
+
`INSERT INTO ${TABLE} (id, title, body, ${embColumn("body")}, ${lshColumn("body")})
|
|
126
|
+
VALUES (?, ?, ?, ?, ?)`,
|
|
127
|
+
[id, title, body, `{${vec.join(",")}}`, lshBucketToSql(bucket)],
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Write/query identity for one stored row vs re-projection of the same body.
|
|
132
|
+
const stored = await conn.query(`SELECT ${lshColumn("body")} AS b FROM ${TABLE} WHERE id = ?`, [
|
|
133
|
+
"d00000000",
|
|
134
|
+
]);
|
|
135
|
+
const body0 = `${TOPICS[0]}. Document 0 discusses ${TOPICS[0]} with enough tokens for BM25.`;
|
|
136
|
+
const queryBucket = lshBucket(synthEmbed(body0), planes);
|
|
137
|
+
expect(lshBucketFromSql(stored[0]?.["b"])).toBe(queryBucket);
|
|
138
|
+
|
|
139
|
+
const captured: Array<{ sql: string; params: readonly unknown[] }> = [];
|
|
140
|
+
const tapped: SqlConnection = {
|
|
141
|
+
driverId: conn.driverId,
|
|
142
|
+
role: conn.role,
|
|
143
|
+
query: async (sql, params = []) => {
|
|
144
|
+
captured.push({ sql, params });
|
|
145
|
+
return conn.query(sql, params);
|
|
146
|
+
},
|
|
147
|
+
exec: (sql, params) => conn.exec(sql, params),
|
|
148
|
+
close: () => conn.close(),
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const qVec = synthEmbed(TOPICS[0]!);
|
|
152
|
+
const result = await runSqlSearch({
|
|
153
|
+
conn: tapped,
|
|
154
|
+
table: TABLE,
|
|
155
|
+
columns: SEARCH_COLS,
|
|
156
|
+
pkSqlName: "id",
|
|
157
|
+
options: { query: `zxqwv ${TOPICS[0]}`, limit: 10 },
|
|
158
|
+
embedQuery: async () => qVec,
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
const candidate = captured.find((c) => /UNION/i.test(c.sql) && /bit_count/i.test(c.sql));
|
|
162
|
+
expect(candidate).toBeDefined();
|
|
163
|
+
expect(candidate!.sql).toContain("bit_count");
|
|
164
|
+
expect(candidate!.sql).toContain("ORDER BY");
|
|
165
|
+
expect(candidate!.sql).not.toMatch(/=\s*ANY\s*\(/i);
|
|
166
|
+
// Bound query bucket is the signed int64 pack of the query vector.
|
|
167
|
+
expect(candidate!.params).toContain(lshBucketToSql(lshBucket(qVec, planes)));
|
|
168
|
+
|
|
169
|
+
const scored: Array<{ i: number; s: number }> = [];
|
|
170
|
+
for (let i = 0; i < vectors.length; i++) {
|
|
171
|
+
scored.push({ i, s: cosineSimilarity(qVec, vectors[i]!) });
|
|
172
|
+
}
|
|
173
|
+
scored.sort((a, b) => b.s - a.s);
|
|
174
|
+
const exact = new Set(scored.slice(0, 10).map((x) => `d${String(x.i).padStart(8, "0")}`));
|
|
175
|
+
const approx = result.data.map((r) => String(r["id"]));
|
|
176
|
+
let hits = 0;
|
|
177
|
+
for (const id of approx.slice(0, 10)) {
|
|
178
|
+
if (exact.has(id)) hits += 1;
|
|
179
|
+
}
|
|
180
|
+
// Hamming-1 equality recovered 0/10 on this corpus. Hamming-rank UNION
|
|
181
|
+
// plus in-process cosine/RRF must recover a real majority of exact neighbors.
|
|
182
|
+
expect(result.data).toHaveLength(10);
|
|
183
|
+
expect(hits / 10).toBeGreaterThanOrEqual(0.5);
|
|
184
|
+
expect(result.meta.engine).toContain("lsh");
|
|
185
|
+
}, 30_000);
|
|
186
|
+
});
|