vybekiit 0.7.29 → 0.7.33

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.
Files changed (262) hide show
  1. package/dist/bin.js +3407 -2769
  2. package/dist/global-guidance/language.md +7 -102
  3. package/dist/global-skills/add-ai/SKILL.md +7 -8
  4. package/dist/global-skills/add-analytics/SKILL.md +4 -7
  5. package/dist/global-skills/add-app-clip/SKILL.md +1 -0
  6. package/dist/global-skills/add-blog/SKILL.md +4 -7
  7. package/dist/global-skills/add-files/SKILL.md +4 -7
  8. package/dist/global-skills/add-images/SKILL.md +4 -7
  9. package/dist/global-skills/add-language/SKILL.md +5 -8
  10. package/dist/global-skills/add-notifications/SKILL.md +4 -7
  11. package/dist/global-skills/add-realtime/SKILL.md +4 -7
  12. package/dist/global-skills/add-search/SKILL.md +4 -7
  13. package/dist/global-skills/add-signin/SKILL.md +4 -8
  14. package/dist/global-skills/add-teams/SKILL.md +4 -7
  15. package/dist/global-skills/aws-cdk/SKILL.md +1 -0
  16. package/dist/global-skills/aws-cloudformation/SKILL.md +1 -0
  17. package/dist/global-skills/aws-serverless/SKILL.md +169 -32
  18. package/dist/global-skills/aws-serverless/references/api-gateway.md +17 -0
  19. package/dist/global-skills/aws-serverless/references/architecture.md +9 -13
  20. package/dist/global-skills/aws-serverless/references/compute-decision-edge-cases.md +77 -0
  21. package/dist/global-skills/aws-serverless/references/lambda.md +3 -3
  22. package/dist/global-skills/aws-serverless/references/orchestration.md +46 -20
  23. package/dist/global-skills/aws-serverless/references/production.md +1 -1
  24. package/dist/global-skills/better-auth-best-practices/SKILL.md +1 -0
  25. package/dist/global-skills/better-auth-security-best-practices/SKILL.md +1 -0
  26. package/dist/global-skills/building-native-ui/SKILL.md +1 -0
  27. package/dist/global-skills/buy-domain/SKILL.md +4 -7
  28. package/dist/global-skills/check-safety/SKILL.md +5 -8
  29. package/dist/global-skills/claimable-postgres/SKILL.md +1 -0
  30. package/dist/global-skills/configure-capabilities/SKILL.md +1 -1
  31. package/dist/global-skills/connect-account/SKILL.md +1 -1
  32. package/dist/global-skills/create-auth-skill/SKILL.md +1 -0
  33. package/dist/global-skills/doctor/SKILL.md +1 -1
  34. package/dist/global-skills/eas-app-stores/SKILL.md +2 -1
  35. package/dist/global-skills/eas-app-stores/agents/openai.yaml +1 -1
  36. package/dist/global-skills/eas-hosting/SKILL.md +2 -1
  37. package/dist/global-skills/eas-hosting/agents/openai.yaml +1 -1
  38. package/dist/global-skills/eas-observe/SKILL.md +2 -1
  39. package/dist/global-skills/eas-observe/agents/openai.yaml +1 -1
  40. package/dist/global-skills/eas-simulator/SKILL.md +24 -16
  41. package/dist/global-skills/eas-simulator/agents/openai.yaml +1 -1
  42. package/dist/global-skills/eas-simulator/references/controllers.md +11 -7
  43. package/dist/global-skills/eas-simulator/references/logs-and-crashes.md +101 -0
  44. package/dist/global-skills/eas-simulator/references/run-your-app.md +8 -8
  45. package/dist/global-skills/eas-simulator/references/troubleshooting.md +14 -6
  46. package/dist/global-skills/eas-update/SKILL.md +2 -1
  47. package/dist/global-skills/eas-update/agents/openai.yaml +1 -1
  48. package/dist/global-skills/eas-update-insights/SKILL.md +2 -1
  49. package/dist/global-skills/eas-update-insights/agents/openai.yaml +1 -1
  50. package/dist/global-skills/eas-workflows/SKILL.md +2 -1
  51. package/dist/global-skills/eas-workflows/agents/openai.yaml +1 -1
  52. package/dist/global-skills/email-best-practices/SKILL.md +1 -0
  53. package/dist/global-skills/email-best-practices/references/sending-reliability.md +17 -22
  54. package/dist/global-skills/expo-animation/SKILL.md +2 -1
  55. package/dist/global-skills/expo-api-routes/SKILL.md +1 -0
  56. package/dist/global-skills/expo-app-clip/SKILL.md +2 -1
  57. package/dist/global-skills/expo-brownfield/SKILL.md +2 -1
  58. package/dist/global-skills/expo-cicd-workflows/SKILL.md +1 -0
  59. package/dist/global-skills/expo-data-fetching/SKILL.md +2 -1
  60. package/dist/global-skills/expo-deployment/SKILL.md +1 -0
  61. package/dist/global-skills/expo-design-system/SKILL.md +2 -1
  62. package/dist/global-skills/expo-dev-client/SKILL.md +2 -1
  63. package/dist/global-skills/expo-dom/SKILL.md +2 -1
  64. package/dist/global-skills/expo-examples/SKILL.md +2 -1
  65. package/dist/global-skills/expo-migrate-module/SKILL.md +2 -1
  66. package/dist/global-skills/expo-module/SKILL.md +2 -1
  67. package/dist/global-skills/expo-native-ui/SKILL.md +2 -1
  68. package/dist/global-skills/expo-observe/SKILL.md +1 -0
  69. package/dist/global-skills/expo-overview/SKILL.md +2 -1
  70. package/dist/global-skills/expo-project-structure/SKILL.md +2 -1
  71. package/dist/global-skills/expo-router/SKILL.md +2 -1
  72. package/dist/global-skills/expo-skill-eval/SKILL.md +1 -0
  73. package/dist/global-skills/expo-skill-feedback/SKILL.md +1 -0
  74. package/dist/global-skills/expo-tailwind-setup/SKILL.md +1 -0
  75. package/dist/global-skills/expo-ui/SKILL.md +2 -1
  76. package/dist/global-skills/expo-upgrade/SKILL.md +2 -1
  77. package/dist/global-skills/expo-web-to-native/SKILL.md +2 -1
  78. package/dist/global-skills/extension-to-functions-codebase/SKILL.md +2 -0
  79. package/dist/global-skills/firebase-ai-logic-basics/SKILL.md +162 -76
  80. package/dist/global-skills/firebase-ai-logic-basics/references/flutter_setup.md +37 -0
  81. package/dist/global-skills/firebase-ai-logic-basics/references/ios_setup.md +97 -3
  82. package/dist/global-skills/firebase-ai-logic-basics/references/tts_generation.md +676 -0
  83. package/dist/global-skills/firebase-ai-logic-basics/references/usage_patterns_android.md +88 -3
  84. package/dist/global-skills/firebase-ai-logic-basics/references/usage_patterns_web.md +91 -3
  85. package/dist/global-skills/firebase-app-hosting-basics/SKILL.md +6 -1
  86. package/dist/global-skills/firebase-auth-basics/SKILL.md +12 -6
  87. package/dist/global-skills/firebase-auth-basics/references/client_sdk_android.md +61 -23
  88. package/dist/global-skills/firebase-auth-basics/references/client_sdk_web.md +3 -3
  89. package/dist/global-skills/firebase-auth-basics/references/flutter_setup.md +22 -19
  90. package/dist/global-skills/firebase-auth-basics/references/security_rules.md +2 -2
  91. package/dist/global-skills/firebase-basics/SKILL.md +8 -2
  92. package/dist/global-skills/firebase-basics/references/android_setup.md +229 -23
  93. package/dist/global-skills/firebase-basics/references/ios_setup.md +57 -0
  94. package/dist/global-skills/firebase-basics/references/web_setup.md +52 -0
  95. package/dist/global-skills/firebase-crashlytics/SKILL.md +2 -0
  96. package/dist/global-skills/firebase-crashlytics/references/android_setup.md +99 -71
  97. package/dist/global-skills/firebase-crashlytics/references/ios_setup.md +1 -0
  98. package/dist/global-skills/firebase-data-connect/SKILL.md +2 -0
  99. package/dist/global-skills/firebase-data-connect/reference/config.md +8 -8
  100. package/dist/global-skills/firebase-data-connect/reference/realtime.md +4 -1
  101. package/dist/global-skills/firebase-data-connect/reference/sdk_android.md +84 -29
  102. package/dist/global-skills/firebase-data-connect/reference/sdk_web.md +8 -3
  103. package/dist/global-skills/firebase-data-connect/reference/security.md +13 -13
  104. package/dist/global-skills/firebase-firestore/SKILL.md +18 -7
  105. package/dist/global-skills/firebase-firestore/references/enterprise/android_sdk_usage.md +47 -21
  106. package/dist/global-skills/firebase-firestore/references/enterprise/indexes.md +2 -1
  107. package/dist/global-skills/firebase-firestore/references/standard/android_sdk_usage.md +63 -27
  108. package/dist/global-skills/firebase-firestore/references/standard/indexes.md +2 -1
  109. package/dist/global-skills/firebase-hosting-basics/SKILL.md +2 -0
  110. package/dist/global-skills/firebase-remote-config-basics/SKILL.md +3 -1
  111. package/dist/global-skills/firebase-remote-config-basics/references/android_setup.md +83 -92
  112. package/dist/global-skills/firebase-security-rules-auditor/SKILL.md +8 -6
  113. package/dist/global-skills/firestore-rules-creation/SKILL.md +23 -10
  114. package/dist/global-skills/go-live/SKILL.md +7 -7
  115. package/dist/global-skills/harden/SKILL.md +7 -10
  116. package/dist/global-skills/instrument-feature-flags/SKILL.md +1 -0
  117. package/dist/global-skills/instrument-product-analytics/SKILL.md +1 -0
  118. package/dist/global-skills/manifest.json +2 -1
  119. package/dist/global-skills/mongodb-atlas-stream-processing/SKILL.md +1 -0
  120. package/dist/global-skills/mongodb-connection/SKILL.md +1 -0
  121. package/dist/global-skills/mongodb-mcp-setup/SKILL.md +1 -0
  122. package/dist/global-skills/mongodb-natural-language-querying/SKILL.md +1 -0
  123. package/dist/global-skills/mongodb-qe-size-estimation/SKILL.md +224 -0
  124. package/dist/global-skills/mongodb-query-optimizer/SKILL.md +1 -0
  125. package/dist/global-skills/mongodb-schema-design/SKILL.md +1 -0
  126. package/dist/global-skills/mongodb-search-and-ai/SKILL.md +1 -0
  127. package/dist/global-skills/native-data-fetching/SKILL.md +1 -0
  128. package/dist/global-skills/neon/SKILL.md +34 -5
  129. package/dist/global-skills/neon-ai-gateway/SKILL.md +44 -14
  130. package/dist/global-skills/neon-auth/SKILL.md +1 -0
  131. package/dist/global-skills/neon-functions/SKILL.md +12 -0
  132. package/dist/global-skills/neon-functions/references/native-binaries.md +188 -0
  133. package/dist/global-skills/neon-object-storage/SKILL.md +1 -0
  134. package/dist/global-skills/neon-postgres/SKILL.md +2 -1
  135. package/dist/global-skills/neon-postgres/references/full-text-search.md +27 -17
  136. package/dist/global-skills/neon-postgres/references/hybrid-search.md +19 -15
  137. package/dist/global-skills/neon-postgres/references/lakebase-search-drizzle.md +99 -14
  138. package/dist/global-skills/neon-postgres/references/vector-search.md +93 -10
  139. package/dist/global-skills/neon-postgres-branches/SKILL.md +1 -0
  140. package/dist/global-skills/neon-postgres-egress-optimizer/SKILL.md +1 -0
  141. package/dist/global-skills/onboarding/SKILL.md +14 -13
  142. package/dist/global-skills/plan-my-idea/SKILL.md +1 -1
  143. package/dist/global-skills/publish-app/SKILL.md +1 -1
  144. package/dist/global-skills/publish-extension/SKILL.md +1 -1
  145. package/dist/global-skills/resend/SKILL.md +5 -15
  146. package/dist/global-skills/resend/references/domains.md +1 -1
  147. package/dist/global-skills/resend/references/installation.md +3 -3
  148. package/dist/global-skills/resend/references/sending/best-practices.md +3 -3
  149. package/dist/global-skills/resend/references/sending/single-email-examples.md +3 -3
  150. package/dist/global-skills/resend/references/webhooks.md +2 -0
  151. package/dist/global-skills/reset-password/SKILL.md +4 -6
  152. package/dist/global-skills/save-data/SKILL.md +3 -0
  153. package/dist/global-skills/sentry-sdk-setup/SKILL.md +1 -0
  154. package/dist/global-skills/sentry-workflow/SKILL.md +1 -0
  155. package/dist/global-skills/setup-email/SKILL.md +7 -8
  156. package/dist/global-skills/setup-payments/SKILL.md +10 -12
  157. package/dist/global-skills/setup-sms/SKILL.md +1 -1
  158. package/dist/global-skills/sign-in-with-email-link/SKILL.md +4 -6
  159. package/dist/global-skills/sign-in-with-google/SKILL.md +14 -13
  160. package/dist/global-skills/sign-in-with-phone/SKILL.md +5 -7
  161. package/dist/global-skills/stripe-best-practices/SKILL.md +20 -19
  162. package/dist/global-skills/stripe-best-practices/references/billing.md +2 -0
  163. package/dist/global-skills/stripe-best-practices/references/payments.md +1 -1
  164. package/dist/global-skills/stripe-best-practices/references/tax.md +27 -15
  165. package/dist/global-skills/supabase/CHANGELOG.md +19 -0
  166. package/dist/global-skills/supabase/SKILL.md +1 -0
  167. package/dist/global-skills/supabase-postgres-best-practices/SKILL.md +1 -0
  168. package/dist/global-skills/track-errors/SKILL.md +12 -13
  169. package/dist/global-skills/update-kit/SKILL.md +1 -1
  170. package/dist/global-skills/upgrading-expo/SKILL.md +1 -0
  171. package/dist/global-skills/use-dom/SKILL.md +1 -0
  172. package/dist/global-skills/use-railway/SKILL.md +9 -8
  173. package/dist/global-skills/use-railway/references/configure.md +34 -1
  174. package/dist/global-skills/use-railway/references/iac.md +3 -0
  175. package/dist/global-skills/use-railway/references/tracing.md +97 -44
  176. package/dist/global-skills/vercel-composition-patterns/SKILL.md +1 -0
  177. package/dist/global-skills/vercel-react-best-practices/SKILL.md +1 -0
  178. package/dist/global-skills/vybekiitReferences/backend/AGENTS.md +11 -3
  179. package/dist/global-skills/vybekiitReferences/backend/agent/goal-index.md +1 -1
  180. package/dist/global-skills/vybekiitReferences/backend/agent/goal-routes.json +229 -0
  181. package/dist/global-skills/vybekiitReferences/backend/agent/mcp-setup.md +11 -2
  182. package/dist/global-skills/vybekiitReferences/backend/agent/session-bootstrap.md +1 -1
  183. package/dist/global-skills/vybekiitReferences/backend/agent/tech-references.md +1 -1
  184. package/dist/global-skills/vybekiitReferences/backend/language.md +7 -102
  185. package/dist/global-skills/vybekiitReferences/backend/platform-skills/deploy-railway-vybekiit.md +2 -2
  186. package/dist/global-skills/vybekiitReferences/backend/platform-skills/extend-capabilities-vybekiit.md +1 -1
  187. package/dist/global-skills/vybekiitReferences/backend/platform-skills/mongodb-vybekiit.md +1 -1
  188. package/dist/global-skills/vybekiitReferences/extension/AGENTS.md +11 -3
  189. package/dist/global-skills/vybekiitReferences/extension/agent/goal-index.md +1 -1
  190. package/dist/global-skills/vybekiitReferences/extension/agent/goal-routes.json +239 -0
  191. package/dist/global-skills/vybekiitReferences/extension/agent/mcp-setup.md +10 -1
  192. package/dist/global-skills/vybekiitReferences/extension/agent/session-bootstrap.md +1 -1
  193. package/dist/global-skills/vybekiitReferences/extension/agent/tech-references.md +1 -1
  194. package/dist/global-skills/vybekiitReferences/extension/agent/ui-sources.md +11 -8
  195. package/dist/global-skills/vybekiitReferences/extension/language.md +7 -92
  196. package/dist/global-skills/vybekiitReferences/extension/platform-skills/browser-automation-vybekiit.md +9 -1
  197. package/dist/global-skills/vybekiitReferences/extension/platform-skills/env-secrets-vybekiit.md +1 -0
  198. package/dist/global-skills/vybekiitReferences/extension/platform-skills/extend-capabilities-vybekiit.md +1 -1
  199. package/dist/global-skills/vybekiitReferences/extension/platform-skills/observability-vybekiit.md +1 -1
  200. package/dist/global-skills/vybekiitReferences/extension/platform-skills/sentry-vybekiit.md +1 -1
  201. package/dist/global-skills/vybekiitReferences/mobile/AGENTS.md +27 -12
  202. package/dist/global-skills/vybekiitReferences/mobile/agent/goal-index.md +1 -1
  203. package/dist/global-skills/vybekiitReferences/mobile/agent/goal-routes.json +279 -0
  204. package/dist/global-skills/vybekiitReferences/mobile/agent/mcp-setup.md +10 -1
  205. package/dist/global-skills/vybekiitReferences/mobile/agent/session-bootstrap.md +1 -1
  206. package/dist/global-skills/vybekiitReferences/mobile/agent/tech-references.md +1 -1
  207. package/dist/global-skills/vybekiitReferences/mobile/agent/ui-sources.mobile.md +1 -1
  208. package/dist/global-skills/vybekiitReferences/mobile/language.md +7 -93
  209. package/dist/global-skills/vybekiitReferences/mobile/platform-skills/env-secrets-vybekiit.md +1 -0
  210. package/dist/global-skills/vybekiitReferences/mobile/platform-skills/extend-capabilities-vybekiit.md +1 -1
  211. package/dist/global-skills/vybekiitReferences/mobile/platform-skills/i18n-vybekiit.md +1 -1
  212. package/dist/global-skills/vybekiitReferences/mobile/platform-skills/observability-vybekiit.md +1 -1
  213. package/dist/global-skills/vybekiitReferences/mobile/platform-skills/sentry-vybekiit.md +1 -1
  214. package/dist/global-skills/vybekiitReferences/mobile/platform-skills/ui-port-from-web-vybekiit.md +2 -2
  215. package/dist/global-skills/vybekiitReferences/spa/AGENTS.md +11 -3
  216. package/dist/global-skills/vybekiitReferences/spa/agent/goal-index.md +1 -1
  217. package/dist/global-skills/vybekiitReferences/spa/agent/goal-routes.json +267 -0
  218. package/dist/global-skills/vybekiitReferences/spa/agent/mcp-setup.md +10 -1
  219. package/dist/global-skills/vybekiitReferences/spa/agent/session-bootstrap.md +1 -1
  220. package/dist/global-skills/vybekiitReferences/spa/agent/ui-sources.md +11 -8
  221. package/dist/global-skills/vybekiitReferences/spa/language.md +7 -11
  222. package/dist/global-skills/vybekiitReferences/web/AGENTS.md +15 -30
  223. package/dist/global-skills/vybekiitReferences/web/agent/goal-index.md +1 -1
  224. package/dist/global-skills/vybekiitReferences/web/agent/goal-routes.json +366 -0
  225. package/dist/global-skills/vybekiitReferences/web/agent/mcp-setup.md +11 -2
  226. package/dist/global-skills/vybekiitReferences/web/agent/session-bootstrap.md +1 -1
  227. package/dist/global-skills/vybekiitReferences/web/language.md +7 -102
  228. package/dist/global-skills/vybekiitReferences/web/platform-skills/ai-vybekiit.md +1 -1
  229. package/dist/global-skills/vybekiitReferences/web/platform-skills/analytics-vybekiit.md +1 -1
  230. package/dist/global-skills/vybekiitReferences/web/platform-skills/assets-vybekiit.md +1 -1
  231. package/dist/global-skills/vybekiitReferences/web/platform-skills/better-auth-vybekiit.md +1 -1
  232. package/dist/global-skills/vybekiitReferences/web/platform-skills/browser-automation-vybekiit.md +9 -1
  233. package/dist/global-skills/vybekiitReferences/web/platform-skills/cms-vybekiit.md +1 -1
  234. package/dist/global-skills/vybekiitReferences/web/platform-skills/compliance-vybekiit.md +1 -1
  235. package/dist/global-skills/vybekiitReferences/web/platform-skills/deploy-github-pages-vybekiit.md +2 -2
  236. package/dist/global-skills/vybekiitReferences/web/platform-skills/deploy-railway-vybekiit.md +2 -2
  237. package/dist/global-skills/vybekiitReferences/web/platform-skills/deploy-vercel-vybekiit.md +2 -2
  238. package/dist/global-skills/vybekiitReferences/web/platform-skills/env-secrets-vybekiit.md +1 -0
  239. package/dist/global-skills/vybekiitReferences/web/platform-skills/extend-capabilities-vybekiit.md +1 -1
  240. package/dist/global-skills/vybekiitReferences/web/platform-skills/i18n-vybekiit.md +1 -1
  241. package/dist/global-skills/vybekiitReferences/web/platform-skills/jobs-vybekiit.md +1 -1
  242. package/dist/global-skills/vybekiitReferences/web/platform-skills/kv-vybekiit.md +1 -1
  243. package/dist/global-skills/vybekiitReferences/web/platform-skills/lemon-squeezy-vybekiit.md +1 -1
  244. package/dist/global-skills/vybekiitReferences/web/platform-skills/mongodb-vybekiit.md +1 -1
  245. package/dist/global-skills/vybekiitReferences/web/platform-skills/notifications-vybekiit.md +1 -1
  246. package/dist/global-skills/vybekiitReferences/web/platform-skills/observability-vybekiit.md +1 -1
  247. package/dist/global-skills/vybekiitReferences/web/platform-skills/paypal-vybekiit.md +1 -1
  248. package/dist/global-skills/vybekiitReferences/web/platform-skills/realtime-vybekiit.md +1 -1
  249. package/dist/global-skills/vybekiitReferences/web/platform-skills/registrar-vybekiit.md +1 -1
  250. package/dist/global-skills/vybekiitReferences/web/platform-skills/search-vybekiit.md +1 -1
  251. package/dist/global-skills/vybekiitReferences/web/platform-skills/sentry-vybekiit.md +1 -1
  252. package/dist/global-skills/vybekiitReferences/web/platform-skills/seo-vybekiit.md +1 -3
  253. package/dist/global-skills/vybekiitReferences/web/platform-skills/supabase-vybekiit.md +1 -1
  254. package/dist/global-skills/vybekiitReferences/web/platform-skills/tenancy-vybekiit.md +1 -1
  255. package/dist/global-skills/web-to-native/SKILL.md +1 -0
  256. package/dist/global-skills/workers-best-practices/SKILL.md +5 -4
  257. package/dist/global-skills/workers-best-practices/references/configuration.md +1 -1
  258. package/dist/global-skills/workers-best-practices/references/platform-apis.md +5 -5
  259. package/dist/global-skills/workers-best-practices/references/runtime-patterns.md +1 -1
  260. package/dist/global-skills/wrangler/SKILL.md +28 -25
  261. package/dist/global-skills/xcode-project-setup/SKILL.md +2 -0
  262. package/package.json +10 -8
@@ -0,0 +1,188 @@
1
+ # Shipping native binaries with a Function
2
+
3
+ The default deploy bundles `source` into a single `index.mjs` with esbuild. A compiled binary cannot be inlined into that file, so it has to ship as a separate file in the deploy archive. There are three ways to put it there. Pick by what the binary is:
4
+
5
+ | The binary is | Use |
6
+ | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------- |
7
+ | An npm package backed by a Node-API addon (`sharp`, most `@napi-rs/*` packages) | [`externalPackages`](#externalpackages-npm-packages-with-a-node-addon) |
8
+ | A file your own build step produces: a `.node` addon, a `.so`, a `.wasm`, model weights | [`bundler: "none"`](#bundler-none-ship-a-prebuilt-directory) or a [custom `bundler`](#custom-bundler-return-the-file-map) |
9
+ | A standalone executable you spawn (`ffmpeg`, a Go or Rust CLI) | A custom `bundler` or `"none"`, plus [a copy to `/run` at startup](#standalone-executables) |
10
+
11
+ The examples use top-level `functions`, which needs `neon` CLI 4.20 or newer and `@neon/config` 1.6 or newer.
12
+
13
+ ## The runtime a binary lands on
14
+
15
+ - **linux, arm64, glibc**, Node.js 24. A binary built for macOS or x64 cannot load there.
16
+ - The archive is extracted to `/opt/function`, a read-only filesystem. `import.meta.url` in the root `index.mjs` points there, so `new URL("./bin/tool", import.meta.url)` resolves to `/opt/function/bin/tool`.
17
+ - **Every file arrives with mode `644`.** Unix permission bits in the zip are dropped on extraction, and `chmod` in place fails with `EROFS`. A `.node` or `.so` loads fine (it is `dlopen`ed, not executed). Spawning a file from `/opt/function` fails with `EACCES`.
18
+ - `/tmp` is writable and mounted `noexec`: a copied binary still fails with `EACCES` after `chmod 755`.
19
+ - `/run` is a writable tmpfs that allows exec (about 990 MiB, backed by the function's 2048 MiB of memory).
20
+
21
+ The filesystem layout is observed behavior, not documented by Neon. Re-check it if spawning starts failing.
22
+
23
+ ## `externalPackages`: npm packages with a Node addon
24
+
25
+ ```typescript
26
+ // neon.ts
27
+ import { defineConfig } from "@neon/config/v1";
28
+
29
+ export default defineConfig({
30
+ functions: {
31
+ resize: {
32
+ name: "Resize",
33
+ source: "./src/resize.ts",
34
+ externalPackages: ["sharp"],
35
+ },
36
+ },
37
+ });
38
+ ```
39
+
40
+ esbuild leaves `import sharp from "sharp"` unresolved. At deploy, the CLI installs the version of `sharp` from your project with `npm install --cpu=arm64 --os=linux --libc=glibc --ignore-scripts` into a temp directory, traces the files it reaches with `@vercel/nft`, and copies them into the archive under `node_modules/` with the tree layout intact. Only the installed version is read from your `node_modules`; the shipped files come from the temp install, and your `node_modules` is not modified.
41
+
42
+ The deploy fails with a named error when:
43
+
44
+ - the package is not installed in your project (no version to pin)
45
+ - the declared package itself does not install for linux-arm64 glibc (`EBADPLATFORM`)
46
+ - a staged `.node` or `.so` is not an AArch64 ELF binary
47
+ - `npm` is not on `PATH`
48
+ - the archive exceeds the [size limits](#size-limits)
49
+
50
+ It does not fail when a platform-specific optional dependency is silently skipped, or when a package that compiles from source at install time ships no binary (the staging install runs with `--ignore-scripts`). Those deploy and then fail at invoke. Use packages that publish a linux-arm64 glibc prebuild (`sharp` does), and invoke the deployed function once to confirm the addon loads.
51
+
52
+ A deploy and `neon dev` print an advisory warning for any bundled package that carries native code and is not declared. A package with a working JavaScript fallback (`ws` with `bufferutil`) triggers it too and needs no change. Do not silence it with `{ name, includeFiles: false }`: that externalizes the package and ships nothing, so a reached import throws `Cannot find module` on every invoke. `includeFiles: false` is only for an import the function never evaluates.
53
+
54
+ Under `neon dev`, the package is only kept out of the bundle and resolves from your own `node_modules` for your host.
55
+
56
+ Pros: one line in `neon.ts`; the target-platform install, file tracing, arch check, and size check are automatic; local dev uses your host build.
57
+
58
+ Cons: only for npm packages that publish a linux-arm64 glibc prebuild; transitive pins, overrides, and patches from your lockfile are not carried into the staged install; esbuild bundler only (`externalPackages` with `bundler: "none"` or a function fails validation).
59
+
60
+ ## `bundler: "none"`: ship a prebuilt directory
61
+
62
+ Run your own build, then point `source` at its output. The directory root must contain `index.mjs` or `index.js`. Everything else in the directory ships as-is:
63
+
64
+ ```text
65
+ dist/fn/
66
+ index.mjs # built by your step, reads ./native/addon.node
67
+ native/addon.node
68
+ ```
69
+
70
+ ```typescript
71
+ // neon.ts
72
+ import { defineConfig } from "@neon/config/v1";
73
+
74
+ export default defineConfig({
75
+ functions: {
76
+ api: { name: "API", source: "./dist/fn", bundler: "none" },
77
+ },
78
+ });
79
+ ```
80
+
81
+ ```bash
82
+ npm run build:fn && neon deploy --env .env.local
83
+ neon functions deploy api --src dist/fn --no-bundle # same thing, without neon.ts
84
+ ```
85
+
86
+ `neon deploy` does not run your build step. Run it first, or use a [custom `bundler`](#custom-bundler-return-the-file-map) to keep the build inside `neon deploy`.
87
+
88
+ Pros: works with any build tool or framework output (`.mastra/output` is the common one); full control over the archive layout.
89
+
90
+ Cons: no architecture check, so a binary built for your laptop deploys and then fails at invoke; the build step is yours to keep in sync with `neon deploy`; TypeScript cannot ship unbundled.
91
+
92
+ ## Custom `bundler`: return the file map
93
+
94
+ An inline function in `neon.ts` returns archive paths mapped to bytes. `neon deploy` zips the map, and `neon dev` serves the same map locally:
95
+
96
+ ```typescript
97
+ // neon.ts
98
+ import { readFile } from "node:fs/promises";
99
+ import { build } from "esbuild";
100
+ import { defineConfig } from "@neon/config/v1";
101
+
102
+ export default defineConfig({
103
+ functions: {
104
+ transcode: {
105
+ name: "Transcode",
106
+ source: "./src/transcode.ts",
107
+ bundler: async (fn) => {
108
+ const out = await build({
109
+ entryPoints: [fn.source],
110
+ bundle: true,
111
+ platform: "node",
112
+ format: "esm",
113
+ write: false,
114
+ outfile: "index.mjs",
115
+ // CommonJS dependencies call require(); ESM output has none in scope.
116
+ banner: {
117
+ js: "import{createRequire}from'module';const require=createRequire(import.meta.url);",
118
+ },
119
+ });
120
+ return {
121
+ "index.mjs": out.outputFiles[0].contents,
122
+ "bin/ffmpeg": new Uint8Array(
123
+ await readFile(new URL("./vendor/linux-arm64/ffmpeg", import.meta.url)),
124
+ ),
125
+ };
126
+ },
127
+ },
128
+ },
129
+ });
130
+ ```
131
+
132
+ `esbuild` must be a dependency of your project. The map needs `index.mjs` or `index.js` at the root.
133
+
134
+ Pros: the build lives in `neon.ts`, so `neon deploy` and `neon dev` always build the same thing; any file from anywhere can go in the archive.
135
+
136
+ Cons: no architecture check; `externalPackages` cannot be combined with it, so an npm addon has to be copied into the map by hand, with its `node_modules/` layout.
137
+
138
+ ## Standalone executables
139
+
140
+ Ship the executable with a custom `bundler` or `bundler: "none"`, then copy it to `/run` and mark it executable once per isolate:
141
+
142
+ ```typescript
143
+ // src/transcode.ts
144
+ import { execFile } from "node:child_process";
145
+ import { chmod, copyFile, mkdir } from "node:fs/promises";
146
+ import { promisify } from "node:util";
147
+
148
+ const run = promisify(execFile);
149
+
150
+ let ffmpeg: Promise<string> | undefined;
151
+ function ffmpegPath(): Promise<string> {
152
+ if (process.env.FFMPEG_PATH) return Promise.resolve(process.env.FFMPEG_PATH);
153
+ ffmpeg ??= (async () => {
154
+ await mkdir("/run/bin", { recursive: true });
155
+ await copyFile(new URL("./bin/ffmpeg", import.meta.url), "/run/bin/ffmpeg");
156
+ await chmod("/run/bin/ffmpeg", 0o755);
157
+ return "/run/bin/ffmpeg";
158
+ })();
159
+ return ffmpeg;
160
+ }
161
+
162
+ export default {
163
+ async fetch() {
164
+ const { stdout } = await run(await ffmpegPath(), ["-version"]);
165
+ return new Response(stdout);
166
+ },
167
+ };
168
+ ```
169
+
170
+ `neon dev` runs this code on your machine, where `/run` may not exist and a linux-arm64 binary cannot execute. Point it at a host install from the shell, and leave `FFMPEG_PATH` out of the function's deployed `env`:
171
+
172
+ ```bash
173
+ FFMPEG_PATH="$(command -v ffmpeg)" neon dev
174
+ ```
175
+
176
+ The binary must be statically linked, or its shared libraries must exist in the runtime image. The copy costs memory: `/run` is RAM-backed and counts against the function's 2048 MiB.
177
+
178
+ ## Size limits
179
+
180
+ `bundler: "none"`, a custom `bundler`, and `externalPackages` staging check the archive before upload:
181
+
182
+ | Limit | Value |
183
+ | ------------------------ | ------- |
184
+ | Compressed zip | 10 MiB |
185
+ | Total uncompressed bytes | 64 MiB |
186
+ | Files in the archive | 4,096 |
187
+
188
+ Exceeding one fails the deploy. The byte-limit errors list the four largest files. Check an executable's size before building around it: a single static binary can use most of the 64 MiB.
@@ -15,6 +15,7 @@ description: >-
15
15
  metadata:
16
16
  parent: neon
17
17
  source: https://github.com/neondatabase/agent-skills/tree/main/skills/neon-object-storage
18
+ disable-model-invocation: true
18
19
  ---
19
20
 
20
21
  **FIRST**: Use the parent `neon` skill for a Neon overview, getting started with Neon, Neon development best practices, and more.
@@ -13,6 +13,7 @@ description: >-
13
13
  metadata:
14
14
  parent: neon
15
15
  source: https://github.com/neondatabase/agent-skills/tree/main/skills/neon-postgres
16
+ disable-model-invocation: true
16
17
  ---
17
18
 
18
19
  **FIRST**: Use the parent `neon` skill for a Neon overview, getting started with Neon, Neon development best practices, and more.
@@ -257,7 +258,7 @@ Link: https://neon.com/docs/guides/logical-replication-guide.md
257
258
 
258
259
  Use Lakebase Search for semantic, full-text, and hybrid search:
259
260
 
260
- - For semantic search, read [Vector search](references/vector-search.md).
261
+ - For semantic search, including generating embeddings with the Neon AI Gateway, read [Vector search](references/vector-search.md).
261
262
  - For full-text search with BM25 ranking, read [Full-text search](references/full-text-search.md).
262
263
  - For combining semantic and lexical results, read [Hybrid search](references/hybrid-search.md).
263
264
  - For managing any of the above through Drizzle ORM, read [Managing Lakebase Search with Drizzle](references/lakebase-search-drizzle.md).
@@ -45,18 +45,24 @@ After a large bulk load, run `VACUUM` to refresh the statistics used by BM25 sco
45
45
  `to_bm25query` binds the query `tsvector` to the BM25 index whose corpus statistics should be used. The `<@>` operator returns a negative BM25 score, so lower (more negative) values are more relevant and must sort ascending:
46
46
 
47
47
  ```sql
48
- SELECT
49
- id,
50
- title,
51
- body_tsv <@> to_bm25query(
52
- to_tsvector('english', $1),
53
- 'documents_body_bm25'::regclass
54
- ) AS score
55
- FROM documents
48
+ SELECT id, title, score
49
+ FROM (
50
+ SELECT
51
+ id,
52
+ title,
53
+ body_tsv <@> to_bm25query(
54
+ to_tsvector('english', $1),
55
+ 'documents_body_bm25'::regclass
56
+ ) AS score
57
+ FROM documents
58
+ ) AS keyword_scored
59
+ WHERE score < 0
56
60
  ORDER BY score
57
61
  LIMIT $2;
58
62
  ```
59
63
 
64
+ Scalar BM25 scoring returns zero for documents containing none of the query terms. Filter `score < 0` before `ORDER BY` and `LIMIT` so keyword results exclude non-matches under both sequential and index plans. Partial query-term matches remain eligible.
65
+
60
66
  Use the same text-search configuration for document and query vectors. Select a language-specific or custom configuration that matches the corpus.
61
67
 
62
68
  ## Set the Candidate Limit
@@ -72,15 +78,19 @@ BEGIN;
72
78
  SET LOCAL lakebase_bm25.default_limit = 20;
73
79
  SET LOCAL lakebase_bm25.prefilter = on;
74
80
 
75
- SELECT
76
- id,
77
- title,
78
- body_tsv <@> to_bm25query(
79
- to_tsvector('english', $1),
80
- 'documents_body_bm25'::regclass
81
- ) AS score
82
- FROM documents
83
- WHERE id % 1000 = 0
81
+ SELECT id, title, score
82
+ FROM (
83
+ SELECT
84
+ id,
85
+ title,
86
+ body_tsv <@> to_bm25query(
87
+ to_tsvector('english', $1),
88
+ 'documents_body_bm25'::regclass
89
+ ) AS score
90
+ FROM documents
91
+ WHERE id % 1000 = 0
92
+ ) AS keyword_scored
93
+ WHERE score < 0
84
94
  ORDER BY score
85
95
  LIMIT $2;
86
96
  COMMIT;
@@ -18,13 +18,13 @@ CREATE TABLE documents (
18
18
  id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
19
19
  title text NOT NULL,
20
20
  body text NOT NULL,
21
- embedding vector(1536),
21
+ embedding vector(1024),
22
22
  body_tsv tsvector GENERATED ALWAYS AS
23
23
  (to_tsvector('english', body)) STORED
24
24
  );
25
25
  ```
26
26
 
27
- Replace `1536` with the embedding model's dimension. Use the same model and preprocessing for stored-document and query embeddings, and choose a PostgreSQL text-search configuration appropriate for the corpus.
27
+ The 1024-dimensional column is an example. Set it to the output dimension of your selected embedding model. Generate document embeddings in batches and embed each query with the same model and dimensions; [Vector search](vector-search.md#prepare-embeddings) shows the AI Gateway calls. Follow any model-specific query instructions, while keeping the original query text for BM25. Choose a PostgreSQL text-search configuration appropriate for the corpus.
28
28
 
29
29
  Create and validate each retriever independently before combining them. Follow [Vector search](vector-search.md) and [Full-text search](full-text-search.md) for their indexes, query operators, and tuning.
30
30
 
@@ -34,7 +34,7 @@ Reciprocal Rank Fusion (RRF) is the approach in the Lakebase Search get-started
34
34
 
35
35
  For rank `r` and constant `k`, each retriever contributes `1 / (k + r)`. The documented starting point uses 40 candidates per retriever and `k = 60`; tune both for the corpus and workload.
36
36
 
37
- Bind the query embedding as `$1`, query text as `$2`, and final result count as `$3`:
37
+ Embed the query text through the same gateway model used for the stored documents, then bind that vector as `$1`, the original query text as `$2`, and the final result count as `$3`:
38
38
 
39
39
  ```sql
40
40
  WITH vector_ranked AS (
@@ -49,15 +49,19 @@ WITH vector_ranked AS (
49
49
  keyword_ranked AS (
50
50
  SELECT id, RANK() OVER (ORDER BY score) AS rank
51
51
  FROM (
52
- SELECT
53
- id,
54
- body_tsv <@> to_bm25query(
55
- to_tsvector('english', $2),
56
- 'documents_body_bm25'::regclass
57
- ) AS score
58
- FROM documents
59
- ORDER BY score
60
- FETCH FIRST 40 ROWS WITH TIES
52
+ SELECT id, score
53
+ FROM (
54
+ SELECT
55
+ id,
56
+ body_tsv <@> to_bm25query(
57
+ to_tsvector('english', $2),
58
+ 'documents_body_bm25'::regclass
59
+ ) AS score
60
+ FROM documents
61
+ ) AS keyword_scored
62
+ WHERE score < 0
63
+ ORDER BY score, id
64
+ LIMIT 40
61
65
  ) AS keyword_candidates
62
66
  )
63
67
  SELECT
@@ -73,13 +77,13 @@ ORDER BY rrf_score DESC, d.id
73
77
  LIMIT $3;
74
78
  ```
75
79
 
76
- `RANK()` gives tied retrieval scores the same rank. Sort by `rrf_score` descending and use the stable ID as a final tie-breaker.
80
+ `score < 0` excludes BM25 non-matches. Many matching documents can share a BM25 score, so `WITH TIES` could admit a large group at the cutoff. `ORDER BY score, id LIMIT 40` keeps keyword candidates bounded and breaks boundary ties by ID. `RANK()` uses score alone so retained ties receive equal ranks.
77
81
 
78
- `FETCH FIRST ... ROWS WITH TIES` keeps every candidate tied at the cutoff, so `RANK()` receives the complete boundary tie group. The candidate set can therefore exceed 40 rows. `lakebase_bm25.default_limit` defaults to `1000`; increase it only when the BM25 candidate set needs to exceed that value.
82
+ Vector retrieval preserves cutoff ties and can exceed 40 candidates. `lakebase_bm25.default_limit` defaults to `1000`; the SQL limit bounds keyword rows entering fusion, not total scoring work.
79
83
 
80
84
  ## Adapt the Hybrid Search
81
85
 
82
- - Retrieve more candidates from each source than the final result count; otherwise one retriever can dominate before fusion has enough overlap. Keep `lakebase_bm25.default_limit` above the BM25 candidate target and allow room for boundary ties.
86
+ - Retrieve more candidates from each source than the final result count; otherwise one retriever can dominate before fusion has enough overlap. Keep `lakebase_bm25.default_limit` at least as large as the BM25 candidate target.
83
87
  - Keep each retriever's operator and index configuration correct independently before tuning RRF.
84
88
  - Tune candidate counts and the RRF constant with judged or behavioral relevance data, plus latency measurements.
85
89
  - Add weights only when product evidence shows one retriever should contribute more. Weight the reciprocal-rank contributions, not the raw vector distance and negative BM25 score.
@@ -10,6 +10,7 @@ Contents:
10
10
  - [Extensions](#extensions): custom migration required to create extensions (Drizzle can't)
11
11
  - [Schema](#schema): columns, generated `tsvector`, and the ANN index
12
12
  - [BM25 Index](#bm25-index): created after the corpus is seeded
13
+ - [Generate and Store Embeddings](#generate-and-store-embeddings): call the AI Gateway and insert vectors with Drizzle
13
14
  - [Query](#query): vector, BM25, and hybrid reads
14
15
  - [Tune Per Query](#tune-per-query): per-query GUCs
15
16
 
@@ -22,18 +23,22 @@ Rules:
22
23
 
23
24
  ## Config
24
25
 
25
- `drizzle-kit generate` and `migrate` read `drizzle.config.ts`. Point `dbCredentials.url` at the **direct (unpooled)** connection string:
26
+ `drizzle-kit generate` and `migrate` read `drizzle.config.ts`. If the connection string is in `.env`, install `dotenv` (`npm install dotenv`) and load it here. Point `dbCredentials.url` at the **direct (unpooled)** connection string:
26
27
 
27
28
  ```typescript
28
29
  // drizzle.config.ts
30
+ import "dotenv/config";
29
31
  import { defineConfig } from "drizzle-kit";
30
32
 
33
+ const databaseUrl = process.env.DATABASE_URL_UNPOOLED;
34
+ if (!databaseUrl) throw new Error("Missing DATABASE_URL_UNPOOLED");
35
+
31
36
  export default defineConfig({
32
37
  schema: "./src/schema.ts",
33
38
  out: "./drizzle",
34
39
  dialect: "postgresql",
35
40
  // Direct (unpooled) URL. Neon exposes it as DATABASE_URL_UNPOOLED.
36
- dbCredentials: { url: process.env.DATABASE_URL_UNPOOLED },
41
+ dbCredentials: { url: databaseUrl },
37
42
  });
38
43
  ```
39
44
 
@@ -57,7 +62,14 @@ The columns, the generated `tsvector`, and the `lakebase_ann` index all go in `s
57
62
 
58
63
  ```typescript
59
64
  // src/schema.ts
60
- import { pgTable, bigint, text, vector, index, customType } from "drizzle-orm/pg-core";
65
+ import {
66
+ pgTable,
67
+ bigint,
68
+ text,
69
+ vector,
70
+ index,
71
+ customType,
72
+ } from "drizzle-orm/pg-core";
61
73
  import { sql } from "drizzle-orm";
62
74
 
63
75
  const tsvector = customType<{ data: string }>({
@@ -69,10 +81,12 @@ const tsvector = customType<{ data: string }>({
69
81
  export const documents = pgTable(
70
82
  "documents",
71
83
  {
72
- id: bigint("id", { mode: "number" }).generatedByDefaultAsIdentity().primaryKey(),
84
+ id: bigint("id", { mode: "number" })
85
+ .generatedByDefaultAsIdentity()
86
+ .primaryKey(),
73
87
  title: text("title").notNull(),
74
88
  body: text("body").notNull(),
75
- embedding: vector("embedding", { dimensions: 1536 }),
89
+ embedding: vector("embedding", { dimensions: 1024 }),
76
90
  bodyTsv: tsvector("body_tsv").generatedAlwaysAs(
77
91
  sql`to_tsvector('english', "body")`,
78
92
  ),
@@ -86,7 +100,7 @@ export const documents = pgTable(
86
100
  );
87
101
  ```
88
102
 
89
- Set the dimension to match your embedding model. Postgres maintains `body_tsv`, so never write it from the app. Generate and apply the migration after the extensions migration above:
103
+ The 1024-dimensional column is an example; set it to the output dimension of your selected embedding model. Use the same model and dimensions for stored documents and queries. Postgres maintains `body_tsv`, so never write it from the app. Generate and apply the migration after the extensions migration above:
90
104
 
91
105
  ```bash
92
106
  npx drizzle-kit generate --name=lakebase_search
@@ -106,6 +120,66 @@ npx drizzle-kit generate --custom --name=bm25_index
106
120
  CREATE INDEX documents_body_bm25 ON documents USING lakebase_bm25 (body_tsv);
107
121
  ```
108
122
 
123
+ ## Generate and Store Embeddings
124
+
125
+ Use the [Vercel AI SDK](https://ai-sdk.dev) (`ai`, 6+) with Neon's `@neon/ai-sdk-provider` 1.0.0+. Follow the [gateway setup](vector-search.md#prepare-embeddings), then install the packages with `npm install @neon/ai-sdk-provider ai dotenv`:
126
+
127
+ ```typescript
128
+ import "dotenv/config";
129
+ import { neon } from "@neon/ai-sdk-provider";
130
+ import { embed, embedMany } from "ai";
131
+
132
+ const embeddingModel = neon.embeddingModel("qwen3-embedding-0-6b");
133
+ const providerOptions = { neon: { dimensions: 1024 } };
134
+ // Qwen3 query prompt adapted for Neon documentation search; documents stay unprefixed.
135
+ const queryPrompt =
136
+ "Instruct: Given a question about Neon, retrieve documentation passages that answer the question\nQuery: ";
137
+ ```
138
+
139
+ Generate a document vector, then insert it with Drizzle:
140
+
141
+ ```typescript
142
+ const { embedding } = await embed({
143
+ model: embeddingModel,
144
+ value: body,
145
+ providerOptions,
146
+ });
147
+ await db.insert(documents).values({
148
+ title,
149
+ body,
150
+ embedding,
151
+ });
152
+ ```
153
+
154
+ For bulk imports, skip blank rows and embed/insert one batch at a time:
155
+
156
+ ```typescript
157
+ const batchSize = 64;
158
+ const nonBlankRows = rows.filter((row) => row && row.body.trim().length > 0);
159
+
160
+ for (let offset = 0; offset < nonBlankRows.length; offset += batchSize) {
161
+ const batch = nonBlankRows.slice(offset, offset + batchSize);
162
+ const { embeddings: vectors } = await embedMany({
163
+ model: embeddingModel,
164
+ values: batch.map((row) => row.body),
165
+ providerOptions,
166
+ maxParallelCalls: 1,
167
+ });
168
+ await db.insert(documents).values(
169
+ batch.map((row, index) => {
170
+ const embedding = vectors[index];
171
+ if (!embedding)
172
+ throw new Error(`Missing embedding for batch row ${index}`);
173
+ return { ...row, embedding };
174
+ }),
175
+ );
176
+ }
177
+ ```
178
+
179
+ `embedMany` splits embedding requests using the provider's per-request input limit. This loop also bounds database inserts and memory; tune `batchSize` for your workload. Chunk long documents before embedding. Earlier batches stay committed if a later batch fails.
180
+
181
+ Apply `queryPrompt` only to queries, keeping the original text for BM25. Use the same model and dimensions for documents and queries; re-embed documents when switching models.
182
+
109
183
  ## Query
110
184
 
111
185
  Use the query builder with Drizzle's `cosineDistance` helper for vector search. It emits the `<=>` operator, so keep the index on `vector_cosine_ops`:
@@ -114,7 +188,11 @@ Use the query builder with Drizzle's `cosineDistance` helper for vector search.
114
188
  import { cosineDistance } from "drizzle-orm";
115
189
  import { documents } from "./schema";
116
190
 
117
- // queryEmbedding: number[] from the same model used for stored documents
191
+ const { embedding: queryEmbedding } = await embed({
192
+ model: embeddingModel,
193
+ value: `${queryPrompt}${queryText}`,
194
+ providerOptions,
195
+ });
118
196
  const distance = cosineDistance(documents.embedding, queryEmbedding);
119
197
 
120
198
  const rows = await db
@@ -130,17 +208,23 @@ BM25 has no Drizzle helper: `<@>` and `to_bm25query` require raw SQL. Reference
130
208
  import { sql } from "drizzle-orm";
131
209
 
132
210
  const rows = await db.execute(sql`
133
- SELECT id, title,
134
- body_tsv <@> to_bm25query(
135
- to_tsvector('english', ${queryText}),
136
- 'documents_body_bm25'::regclass
137
- ) AS score
138
- FROM documents
211
+ SELECT id, title, score
212
+ FROM (
213
+ SELECT id, title,
214
+ body_tsv <@> to_bm25query(
215
+ to_tsvector('english', ${queryText}),
216
+ 'documents_body_bm25'::regclass
217
+ ) AS score
218
+ FROM documents
219
+ ) AS keyword_scored
220
+ WHERE score < 0
139
221
  ORDER BY score
140
222
  LIMIT ${k}
141
223
  `);
142
224
  ```
143
225
 
226
+ Filter `score < 0` before the candidate cutoff: scalar BM25 scoring returns zero for non-matches, which must not become keyword hits. Partial query-term matches remain eligible.
227
+
144
228
  Run the [hybrid search](hybrid-search.md) RRF query the same way: raw SQL through `db.execute`.
145
229
 
146
230
  ## Tune Per Query
@@ -168,5 +252,6 @@ const rows = await db.transaction(async (tx) => {
168
252
 
169
253
  Sources:
170
254
 
255
+ - [AI Gateway embeddings](https://neon.com/docs/ai-gateway/embeddings)
171
256
  - [Get started with Lakebase Search](https://neon.com/docs/ai/lakebase-search-get-started)
172
- - [Schema migration with Lakebase Postgres and Drizzle ORM](https://neon.com/docs/guides/drizzle-migrations)
257
+ - [Schema migration with Lakebase Postgres and Drizzle ORM](https://neon.com/docs/guides/drizzle-migrations)