spine-framework 0.1.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/.framework/README.md +129 -0
- package/.framework/cli/bin.cjs +14 -0
- package/.framework/cli/commands/agents.ts +153 -0
- package/.framework/cli/commands/auth.ts +94 -0
- package/.framework/cli/commands/create-app.ts +185 -0
- package/.framework/cli/commands/dev.ts +295 -0
- package/.framework/cli/commands/doctor.ts +442 -0
- package/.framework/cli/commands/generate.ts +332 -0
- package/.framework/cli/commands/init.ts +272 -0
- package/.framework/cli/commands/install-app.ts +391 -0
- package/.framework/cli/commands/items.ts +253 -0
- package/.framework/cli/commands/migrations.ts +141 -0
- package/.framework/cli/commands/pipelines.ts +166 -0
- package/.framework/cli/commands/status.ts +197 -0
- package/.framework/cli/commands/system.ts +184 -0
- package/.framework/cli/commands/test.ts +227 -0
- package/.framework/cli/commands/uninstall-app.ts +166 -0
- package/.framework/cli/context.ts +268 -0
- package/.framework/cli/env-loader.ts +36 -0
- package/.framework/cli/index.ts +106 -0
- package/.framework/cli/welcome.cjs +45 -0
- package/.framework/docs/API.md +384 -0
- package/.framework/docs/STABILITY.md +52 -0
- package/.framework/docs/admin-routes.md +76 -0
- package/.framework/docs/api-docs-progress.md +38 -0
- package/.framework/docs/api-governance.md +146 -0
- package/.framework/docs/api-testing-results.md +212 -0
- package/.framework/docs/apis/admin-configs.md +567 -0
- package/.framework/docs/apis/admin-data.md +272 -0
- package/.framework/docs/apis/index.md +231 -0
- package/.framework/docs/apis/internal.md +295 -0
- package/.framework/docs/apis/runtime.md +537 -0
- package/.framework/docs/assembly-launch-guide.md +138 -0
- package/.framework/docs/audit-results.md +590 -0
- package/.framework/docs/authorization-model.md +170 -0
- package/.framework/docs/db-api-inventory.md +95 -0
- package/.framework/docs/examples/custom-app/README.md +77 -0
- package/.framework/docs/examples/custom-function/README.md +27 -0
- package/.framework/docs/examples/custom-function/handler.ts +48 -0
- package/.framework/docs/examples/custom-webhook/README.md +68 -0
- package/.framework/docs/gap-remediation-backlog.md +103 -0
- package/.framework/docs/guides/cli-guide.md +224 -0
- package/.framework/docs/guides/getting-started.md +103 -0
- package/.framework/docs/guides/import-guide.md +193 -0
- package/.framework/docs/guides/testing-guide.md +229 -0
- package/.framework/docs/permission-examples.md +326 -0
- package/.framework/docs/ui-adoption-verification.md +111 -0
- package/.framework/docs/ui-api-coverage.md +84 -0
- package/.framework/docs/v2-compatibility-audit.md +228 -0
- package/.framework/functions/.gitkeep +1 -0
- package/.framework/functions/_shared/agent-runner.ts +1097 -0
- package/.framework/functions/_shared/app-manifest.ts +184 -0
- package/.framework/functions/_shared/audit.ts +150 -0
- package/.framework/functions/_shared/db.ts +174 -0
- package/.framework/functions/_shared/index.ts +382 -0
- package/.framework/functions/_shared/middleware.ts +490 -0
- package/.framework/functions/_shared/permissions.ts +1325 -0
- package/.framework/functions/_shared/pipeline-runner.ts +731 -0
- package/.framework/functions/_shared/principal.ts +760 -0
- package/.framework/functions/_shared/schema-utils.ts +967 -0
- package/.framework/functions/_shared/testing.ts +258 -0
- package/.framework/functions/_shared/trigger-engine.ts +425 -0
- package/.framework/functions/_shared/webhook-registration.ts +168 -0
- package/.framework/functions/_shared/webhook-registry.ts +129 -0
- package/.framework/functions/account-nodes.ts +111 -0
- package/.framework/functions/admin-data.ts +606 -0
- package/.framework/functions/ai-agents.ts +323 -0
- package/.framework/functions/api-keys.ts +376 -0
- package/.framework/functions/apps.ts +483 -0
- package/.framework/functions/auth.ts +196 -0
- package/.framework/functions/debug-auth.ts +107 -0
- package/.framework/functions/embeddings.ts +556 -0
- package/.framework/functions/integration-routes.ts +523 -0
- package/.framework/functions/integrations.ts +319 -0
- package/.framework/functions/item-progress.ts +272 -0
- package/.framework/functions/logs.ts +438 -0
- package/.framework/functions/observability.ts +275 -0
- package/.framework/functions/pipeline-executions.ts +494 -0
- package/.framework/functions/pipelines.ts +485 -0
- package/.framework/functions/prompt-configs.ts +339 -0
- package/.framework/functions/roles.ts +387 -0
- package/.framework/functions/system-cron.ts +742 -0
- package/.framework/functions/system.ts +323 -0
- package/.framework/functions/tests.ts +119 -0
- package/.framework/functions/timers.ts +357 -0
- package/.framework/functions/triggers.ts +563 -0
- package/.framework/functions/types.ts +604 -0
- package/.framework/migrations/000_foundation.sql +1256 -0
- package/.framework/migrations/001_seed.sql +92 -0
- package/.framework/migrations/002_seed_constraints.sql +13 -0
- package/.framework/migrations/003_auth_user_trigger.sql +59 -0
- package/.framework/src/App.tsx +126 -0
- package/.framework/src/apps/admin/index.tsx +173 -0
- package/.framework/src/components/AppWrapper.tsx +56 -0
- package/.framework/src/components/CustomAppLoader.tsx +116 -0
- package/.framework/src/components/admin/AdminListPage.tsx +151 -0
- package/.framework/src/components/admin/AdminSidebar.tsx +166 -0
- package/.framework/src/components/admin/AdminStatsCard.tsx +62 -0
- package/.framework/src/components/admin/SortableTableHeader.tsx +42 -0
- package/.framework/src/components/app-shell/GenericAppShell.tsx +181 -0
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +200 -0
- package/.framework/src/components/app-shell/GenericListPage.tsx +116 -0
- package/.framework/src/components/app-sidebar.tsx +228 -0
- package/.framework/src/components/auth/ProtectedRoute.tsx +88 -0
- package/.framework/src/components/layout/AppShell.tsx +91 -0
- package/.framework/src/components/layout/Header.tsx +88 -0
- package/.framework/src/components/layout/Layout.tsx +95 -0
- package/.framework/src/components/layout/Sidebar.tsx +329 -0
- package/.framework/src/components/runtime/DataDetailHeader.tsx +77 -0
- package/.framework/src/components/runtime/DataDetailPage.tsx +171 -0
- package/.framework/src/components/runtime/DataFilters.tsx +91 -0
- package/.framework/src/components/runtime/DataHeader.tsx +68 -0
- package/.framework/src/components/runtime/DataListPage.tsx +124 -0
- package/.framework/src/components/runtime/DataStats.tsx +70 -0
- package/.framework/src/components/runtime/DataTable.tsx +174 -0
- package/.framework/src/components/runtime/SchemaDetailForm.tsx +134 -0
- package/.framework/src/components/runtime/index.ts +18 -0
- package/.framework/src/components/search-form.tsx +29 -0
- package/.framework/src/components/shared/AgentView.tsx +213 -0
- package/.framework/src/components/shared/FieldRenderer.tsx +478 -0
- package/.framework/src/components/shared/SchemaFields.tsx +226 -0
- package/.framework/src/components/ui/DataTable.tsx +343 -0
- package/.framework/src/components/ui/Form.tsx +281 -0
- package/.framework/src/components/ui/ItemCard.tsx +296 -0
- package/.framework/src/components/ui/ItemListView.tsx +308 -0
- package/.framework/src/components/ui/LoadingSpinner.tsx +52 -0
- package/.framework/src/components/ui/Modal.tsx +61 -0
- package/.framework/src/components/ui/RichTextEditor.tsx +210 -0
- package/.framework/src/components/ui/accordion.tsx +82 -0
- package/.framework/src/components/ui/alert-dialog.tsx +197 -0
- package/.framework/src/components/ui/alert.tsx +76 -0
- package/.framework/src/components/ui/aspect-ratio.tsx +11 -0
- package/.framework/src/components/ui/avatar.tsx +110 -0
- package/.framework/src/components/ui/badge.tsx +49 -0
- package/.framework/src/components/ui/breadcrumb.tsx +122 -0
- package/.framework/src/components/ui/button-group.tsx +83 -0
- package/.framework/src/components/ui/button.tsx +65 -0
- package/.framework/src/components/ui/calendar.tsx +222 -0
- package/.framework/src/components/ui/card.tsx +100 -0
- package/.framework/src/components/ui/carousel.tsx +240 -0
- package/.framework/src/components/ui/chart.tsx +373 -0
- package/.framework/src/components/ui/checkbox.tsx +31 -0
- package/.framework/src/components/ui/collapsible.tsx +33 -0
- package/.framework/src/components/ui/combobox.tsx +299 -0
- package/.framework/src/components/ui/command.tsx +193 -0
- package/.framework/src/components/ui/context-menu.tsx +261 -0
- package/.framework/src/components/ui/dialog.tsx +165 -0
- package/.framework/src/components/ui/direction.tsx +22 -0
- package/.framework/src/components/ui/drawer.tsx +132 -0
- package/.framework/src/components/ui/dropdown-menu.tsx +269 -0
- package/.framework/src/components/ui/empty.tsx +104 -0
- package/.framework/src/components/ui/field.tsx +238 -0
- package/.framework/src/components/ui/hover-card.tsx +42 -0
- package/.framework/src/components/ui/input-group.tsx +153 -0
- package/.framework/src/components/ui/input-otp.tsx +87 -0
- package/.framework/src/components/ui/input.tsx +19 -0
- package/.framework/src/components/ui/item.tsx +196 -0
- package/.framework/src/components/ui/kbd.tsx +26 -0
- package/.framework/src/components/ui/label.tsx +22 -0
- package/.framework/src/components/ui/menubar.tsx +277 -0
- package/.framework/src/components/ui/native-select.tsx +61 -0
- package/.framework/src/components/ui/navigation-menu.tsx +164 -0
- package/.framework/src/components/ui/pagination.tsx +129 -0
- package/.framework/src/components/ui/popover.tsx +87 -0
- package/.framework/src/components/ui/progress.tsx +31 -0
- package/.framework/src/components/ui/radio-group.tsx +42 -0
- package/.framework/src/components/ui/resizable.tsx +50 -0
- package/.framework/src/components/ui/scroll-area.tsx +53 -0
- package/.framework/src/components/ui/select.tsx +195 -0
- package/.framework/src/components/ui/separator.tsx +26 -0
- package/.framework/src/components/ui/sheet.tsx +145 -0
- package/.framework/src/components/ui/sidebar.tsx +706 -0
- package/.framework/src/components/ui/skeleton.tsx +13 -0
- package/.framework/src/components/ui/slider.tsx +59 -0
- package/.framework/src/components/ui/sonner.tsx +47 -0
- package/.framework/src/components/ui/spinner.tsx +10 -0
- package/.framework/src/components/ui/switch.tsx +33 -0
- package/.framework/src/components/ui/table-primitives.tsx +141 -0
- package/.framework/src/components/ui/table.tsx +114 -0
- package/.framework/src/components/ui/tabs.tsx +90 -0
- package/.framework/src/components/ui/textarea.tsx +18 -0
- package/.framework/src/components/ui/toggle-group.tsx +89 -0
- package/.framework/src/components/ui/toggle.tsx +45 -0
- package/.framework/src/components/ui/tooltip.tsx +57 -0
- package/.framework/src/contexts/AppContext.tsx +133 -0
- package/.framework/src/contexts/AuthContext.tsx +371 -0
- package/.framework/src/hooks/use-mobile.ts +19 -0
- package/.framework/src/hooks/useApi.ts +526 -0
- package/.framework/src/hooks/useApps.ts +114 -0
- package/.framework/src/hooks/useEntityList.ts +190 -0
- package/.framework/src/hooks/useEntityRecord.ts +308 -0
- package/.framework/src/hooks/useForm.ts +307 -0
- package/.framework/src/hooks/useListSchema.ts +264 -0
- package/.framework/src/hooks/useSchemaRecord.ts +223 -0
- package/.framework/src/index.css +128 -0
- package/.framework/src/lib/api.ts +156 -0
- package/.framework/src/lib/supabase.ts +94 -0
- package/.framework/src/lib/utils.ts +317 -0
- package/.framework/src/main.tsx +27 -0
- package/.framework/src/pages/DashboardPage.tsx +181 -0
- package/.framework/src/pages/NotFoundPage.tsx +39 -0
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +161 -0
- package/.framework/src/pages/admin/AIAgentsPage.tsx +318 -0
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +199 -0
- package/.framework/src/pages/admin/APIKeysPage.tsx +303 -0
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +523 -0
- package/.framework/src/pages/admin/AppDetailPage.tsx +493 -0
- package/.framework/src/pages/admin/AppsPage.tsx +355 -0
- package/.framework/src/pages/admin/DesignedPage.tsx +491 -0
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +534 -0
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +424 -0
- package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +176 -0
- package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +109 -0
- package/.framework/src/pages/admin/IntegratedDashboard.tsx +402 -0
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +187 -0
- package/.framework/src/pages/admin/IntegrationsPage.tsx +301 -0
- package/.framework/src/pages/admin/LogsPage.tsx +283 -0
- package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +85 -0
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +470 -0
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +183 -0
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +279 -0
- package/.framework/src/pages/admin/PipelinesPage.tsx +390 -0
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +299 -0
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +292 -0
- package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +434 -0
- package/.framework/src/pages/admin/RoleDetailPage.tsx +273 -0
- package/.framework/src/pages/admin/RolesPage.tsx +292 -0
- package/.framework/src/pages/admin/SelectTestPage.tsx +61 -0
- package/.framework/src/pages/admin/ShadcnTestPage.tsx +588 -0
- package/.framework/src/pages/admin/SimpleDashboard.tsx +387 -0
- package/.framework/src/pages/admin/TestRunDetailPage.tsx +172 -0
- package/.framework/src/pages/admin/TestingDashboard.tsx +257 -0
- package/.framework/src/pages/admin/TimerDetailPage.tsx +151 -0
- package/.framework/src/pages/admin/TimersPage.tsx +376 -0
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +149 -0
- package/.framework/src/pages/admin/TriggersPage.tsx +381 -0
- package/.framework/src/pages/admin/TypeDetailPage.tsx +694 -0
- package/.framework/src/pages/admin/TypesPage.tsx +295 -0
- package/.framework/src/pages/auth/LoginPage.tsx +188 -0
- package/.framework/src/pages/auth/RegisterPage.tsx +163 -0
- package/.framework/src/pages/spine-framework/APIPage.tsx +17 -0
- package/.framework/src/pages/spine-framework/CLIPage.tsx +25 -0
- package/.framework/src/types/auth.ts +125 -0
- package/.framework/src/types/types.ts +407 -0
- package/STRUCTURE.md +150 -0
- package/config/components.json +25 -0
- package/config/deno.lock +108 -0
- package/config/package-lock.json +17183 -0
- package/config/postcss.config.cjs +10 -0
- package/config/tailwind.config.cjs +78 -0
- package/config/tsconfig.build.json +32 -0
- package/config/tsconfig.cli.json +18 -0
- package/config/tsconfig.json +41 -0
- package/config/tsconfig.node.json +17 -0
- package/config/tsconfig.node.tsbuildinfo +1 -0
- package/config/tsconfig.tsbuildinfo +1 -0
- package/config/typedoc.json +16 -0
- package/config/vite.config.d.ts +2 -0
- package/config/vite.config.ts +72 -0
- package/dist/cli/commands/agents.d.ts +39 -0
- package/dist/cli/commands/agents.d.ts.map +1 -0
- package/dist/cli/commands/auth.d.ts +36 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/create-app.d.ts +23 -0
- package/dist/cli/commands/create-app.d.ts.map +1 -0
- package/dist/cli/commands/dev.d.ts +39 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/doctor.d.ts +42 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/generate.d.ts +36 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/init.d.ts +30 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/install-app.d.ts +30 -0
- package/dist/cli/commands/install-app.d.ts.map +1 -0
- package/dist/cli/commands/items.d.ts +45 -0
- package/dist/cli/commands/items.d.ts.map +1 -0
- package/dist/cli/commands/migrations.d.ts +41 -0
- package/dist/cli/commands/migrations.d.ts.map +1 -0
- package/dist/cli/commands/pipelines.d.ts +40 -0
- package/dist/cli/commands/pipelines.d.ts.map +1 -0
- package/dist/cli/commands/status.d.ts +23 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/system.d.ts +29 -0
- package/dist/cli/commands/system.d.ts.map +1 -0
- package/dist/cli/commands/test.d.ts +46 -0
- package/dist/cli/commands/test.d.ts.map +1 -0
- package/dist/cli/commands/uninstall-app.d.ts +23 -0
- package/dist/cli/commands/uninstall-app.d.ts.map +1 -0
- package/dist/cli/context.d.ts +88 -0
- package/dist/cli/context.d.ts.map +1 -0
- package/dist/cli/env-loader.d.ts +14 -0
- package/dist/cli/env-loader.d.ts.map +1 -0
- package/dist/cli/index.d.ts +41 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/functions/_shared/agent-runner.d.ts +156 -0
- package/dist/functions/_shared/agent-runner.d.ts.map +1 -0
- package/dist/functions/_shared/app-manifest.d.ts +68 -0
- package/dist/functions/_shared/app-manifest.d.ts.map +1 -0
- package/dist/functions/_shared/audit.d.ts +91 -0
- package/dist/functions/_shared/audit.d.ts.map +1 -0
- package/dist/functions/_shared/db.d.ts +125 -0
- package/dist/functions/_shared/db.d.ts.map +1 -0
- package/dist/functions/_shared/index.d.ts +298 -0
- package/dist/functions/_shared/index.d.ts.map +1 -0
- package/dist/functions/_shared/middleware.d.ts +315 -0
- package/dist/functions/_shared/middleware.d.ts.map +1 -0
- package/dist/functions/_shared/permissions.d.ts +626 -0
- package/dist/functions/_shared/permissions.d.ts.map +1 -0
- package/dist/functions/_shared/pipeline-runner.d.ts +124 -0
- package/dist/functions/_shared/pipeline-runner.d.ts.map +1 -0
- package/dist/functions/_shared/principal.d.ts +284 -0
- package/dist/functions/_shared/principal.d.ts.map +1 -0
- package/dist/functions/_shared/schema-utils.d.ts +181 -0
- package/dist/functions/_shared/schema-utils.d.ts.map +1 -0
- package/dist/functions/_shared/testing.d.ts +172 -0
- package/dist/functions/_shared/testing.d.ts.map +1 -0
- package/dist/functions/_shared/trigger-engine.d.ts +140 -0
- package/dist/functions/_shared/trigger-engine.d.ts.map +1 -0
- package/dist/functions/_shared/webhook-registration.d.ts +81 -0
- package/dist/functions/_shared/webhook-registration.d.ts.map +1 -0
- package/dist/functions/_shared/webhook-registry.d.ts +57 -0
- package/dist/functions/_shared/webhook-registry.d.ts.map +1 -0
- package/dist/functions/account-nodes.d.ts +48 -0
- package/dist/functions/account-nodes.d.ts.map +1 -0
- package/dist/functions/admin-data.d.ts +178 -0
- package/dist/functions/admin-data.d.ts.map +1 -0
- package/dist/functions/ai-agents.d.ts +125 -0
- package/dist/functions/ai-agents.d.ts.map +1 -0
- package/dist/functions/api-keys.d.ts +140 -0
- package/dist/functions/api-keys.d.ts.map +1 -0
- package/dist/functions/apps.d.ts +163 -0
- package/dist/functions/apps.d.ts.map +1 -0
- package/dist/functions/auth.d.ts +74 -0
- package/dist/functions/auth.d.ts.map +1 -0
- package/dist/functions/debug-auth.d.ts +33 -0
- package/dist/functions/debug-auth.d.ts.map +1 -0
- package/dist/functions/embeddings.d.ts +205 -0
- package/dist/functions/embeddings.d.ts.map +1 -0
- package/dist/functions/integration-routes.d.ts +45 -0
- package/dist/functions/integration-routes.d.ts.map +1 -0
- package/dist/functions/integrations.d.ts +124 -0
- package/dist/functions/integrations.d.ts.map +1 -0
- package/dist/functions/item-progress.d.ts +41 -0
- package/dist/functions/item-progress.d.ts.map +1 -0
- package/dist/functions/logs.d.ts +162 -0
- package/dist/functions/logs.d.ts.map +1 -0
- package/dist/functions/observability.d.ts +123 -0
- package/dist/functions/observability.d.ts.map +1 -0
- package/dist/functions/pipeline-executions.d.ts +190 -0
- package/dist/functions/pipeline-executions.d.ts.map +1 -0
- package/dist/functions/pipelines.d.ts +171 -0
- package/dist/functions/pipelines.d.ts.map +1 -0
- package/dist/functions/prompt-configs.d.ts +125 -0
- package/dist/functions/prompt-configs.d.ts.map +1 -0
- package/dist/functions/roles.d.ts +118 -0
- package/dist/functions/roles.d.ts.map +1 -0
- package/dist/functions/system-cron.d.ts +65 -0
- package/dist/functions/system-cron.d.ts.map +1 -0
- package/dist/functions/system.d.ts +29 -0
- package/dist/functions/system.d.ts.map +1 -0
- package/dist/functions/tests.d.ts +28 -0
- package/dist/functions/tests.d.ts.map +1 -0
- package/dist/functions/timers.d.ts +139 -0
- package/dist/functions/timers.d.ts.map +1 -0
- package/dist/functions/triggers.d.ts +203 -0
- package/dist/functions/triggers.d.ts.map +1 -0
- package/dist/functions/types.d.ts +151 -0
- package/dist/functions/types.d.ts.map +1 -0
- package/dist/src/types/types.d.ts +364 -0
- package/dist/src/types/types.d.ts.map +1 -0
- package/package.json +192 -0
- package/scripts/app-install-cli.ts +286 -0
- package/scripts/assemble-frontend.sh +79 -0
- package/scripts/assemble-functions.sh +62 -0
- package/scripts/assemble.sh +35 -0
- package/scripts/boundary-check.sh +106 -0
- package/scripts/build-manifest.sh +80 -0
- package/scripts/check-core-integrity.sh +82 -0
- package/scripts/ingest-chunks.cjs +202 -0
- package/scripts/kb-chunk-parser.cjs +312 -0
- package/scripts/kb-chunk-parser.ts +330 -0
- package/scripts/load-test-app-install.ts +484 -0
- package/scripts/netlify-dev-wrapper.sh +22 -0
- package/scripts/verify-integrity.sh +69 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module debug-auth
|
|
3
|
+
* @audience core-contributor
|
|
4
|
+
* @layer api-handler
|
|
5
|
+
* @stability internal
|
|
6
|
+
*
|
|
7
|
+
* Development/diagnostic endpoint for verifying that authentication
|
|
8
|
+
* middleware is resolving principals correctly. **Never expose this in
|
|
9
|
+
* production without access controls.**
|
|
10
|
+
*
|
|
11
|
+
* **Routed by:** `GET /.netlify/functions/debug-auth`
|
|
12
|
+
*
|
|
13
|
+
* **Actions (via ?method):**
|
|
14
|
+
* | ?method | handler | description |
|
|
15
|
+
* |----------|----------|-------------------------------------|
|
|
16
|
+
* | debug | debug | env check + principal presence |
|
|
17
|
+
* | testJwt | testJwt | validates JWT, returns principal ID |
|
|
18
|
+
*
|
|
19
|
+
* **Authorization:** None — intentionally unauthenticated so broken JWT
|
|
20
|
+
* flows can be diagnosed. Reveals only presence/absence of env vars and
|
|
21
|
+
* principal shape, never secret values.
|
|
22
|
+
*
|
|
23
|
+
* @seeAlso auth.ts (production auth context endpoint)
|
|
24
|
+
* @seeAlso middleware.ts (createHandler — JWT resolution logic)
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import { createHandler } from './_shared/middleware'
|
|
28
|
+
|
|
29
|
+
// ─── HANDLERS ─────────────────────────────────────────────────────────────────
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Diagnostic snapshot: confirms the middleware is running and reports
|
|
33
|
+
* whether a principal was resolved plus env var presence/absence.
|
|
34
|
+
*
|
|
35
|
+
* @returns `{ data: { message, hasPrincipal, principalType, requestId, envVars } }`
|
|
36
|
+
* @sideEffects none
|
|
37
|
+
* @calledBy handler (?method=debug or default)
|
|
38
|
+
*/
|
|
39
|
+
const debug = createHandler(async (ctx, _body) => {
|
|
40
|
+
const envObj = (globalThis as any).process?.env || {}
|
|
41
|
+
return {
|
|
42
|
+
data: {
|
|
43
|
+
message: 'Debug auth endpoint',
|
|
44
|
+
hasPrincipal: !!ctx.principal,
|
|
45
|
+
principalType: ctx.principal?.type || 'none',
|
|
46
|
+
requestId: ctx.requestId,
|
|
47
|
+
envVars: {
|
|
48
|
+
supabaseUrl: envObj.SUPABASE_URL ? 'SET' : 'NOT_SET',
|
|
49
|
+
supabaseAnonKey: envObj.SUPABASE_ANON_KEY ? 'SET' : 'NOT_SET',
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Validates that the provided JWT was successfully decoded by middleware.
|
|
57
|
+
* Returns principal type, id, and accountId on success.
|
|
58
|
+
*
|
|
59
|
+
* @returns `{ data: { tokenValid, principal } }` or `{ data: null, error: string }`
|
|
60
|
+
* @sideEffects none
|
|
61
|
+
* @calledBy handler (?method=testJwt)
|
|
62
|
+
*/
|
|
63
|
+
const testJwt = createHandler(async (ctx, _body) => {
|
|
64
|
+
const envObj = (globalThis as any).process?.env || {}
|
|
65
|
+
if (!ctx.principal) {
|
|
66
|
+
return {
|
|
67
|
+
data: null,
|
|
68
|
+
error: 'No principal resolved from token'
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
data: {
|
|
74
|
+
tokenValid: true,
|
|
75
|
+
principal: {
|
|
76
|
+
type: ctx.principal.type,
|
|
77
|
+
id: ctx.principal.id,
|
|
78
|
+
accountId: ctx.accountId
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
// ─── MAIN HANDLER ────────────────────────────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Netlify function entry point. Routes by ?method (debug | testJwt),
|
|
88
|
+
* defaulting to debug. Note: uses raw Netlify event/context signature
|
|
89
|
+
* rather than `createHandler` wrapper to allow unauthenticated access.
|
|
90
|
+
* @calledBy Netlify function routing (GET)
|
|
91
|
+
*/
|
|
92
|
+
export async function handler(event: any, context: any) {
|
|
93
|
+
const method = event.queryStringParameters?.method || 'debug'
|
|
94
|
+
|
|
95
|
+
const ctx = await createHandler(async (ctx, _body) => {
|
|
96
|
+
switch (method) {
|
|
97
|
+
case 'debug':
|
|
98
|
+
return await debug(ctx, _body)
|
|
99
|
+
case 'testJwt':
|
|
100
|
+
return await testJwt(ctx, _body)
|
|
101
|
+
default:
|
|
102
|
+
return await debug(ctx, _body)
|
|
103
|
+
}
|
|
104
|
+
})(event, context)
|
|
105
|
+
|
|
106
|
+
return ctx
|
|
107
|
+
}
|
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module embeddings
|
|
3
|
+
* @audience core-contributor
|
|
4
|
+
* @layer api-handler
|
|
5
|
+
* @stability stable
|
|
6
|
+
*
|
|
7
|
+
* CRUD and search API for the `embeddings` table. Embeddings store vector
|
|
8
|
+
* representations of text chunks for RAG (retrieval-augmented generation)
|
|
9
|
+
* workloads. Vector similarity search is performed via the
|
|
10
|
+
* `search_similar_embeddings` Postgres RPC function.
|
|
11
|
+
*
|
|
12
|
+
* **Routed by:** `GET/POST/PATCH /.netlify/functions/embeddings`
|
|
13
|
+
*
|
|
14
|
+
* **Actions:**
|
|
15
|
+
* | method | ?action | handler |
|
|
16
|
+
* |--------|-----------------|-------------------|
|
|
17
|
+
* | GET | stats | getStats |
|
|
18
|
+
* | POST | batch-create | batchCreate |
|
|
19
|
+
* | POST | delete-document | deleteByDocument |
|
|
20
|
+
* | POST | cleanup | cleanup |
|
|
21
|
+
* | POST | search-similar | searchSimilar |
|
|
22
|
+
* | POST | search-semantic | searchSemantic |
|
|
23
|
+
* | GET | ?id | get |
|
|
24
|
+
* | GET | (default) | list |
|
|
25
|
+
* | POST | — | create |
|
|
26
|
+
* | PATCH | — | update |
|
|
27
|
+
*
|
|
28
|
+
* **Authorization:** All operations use `ctx.db` (RLS-scoped). Account context
|
|
29
|
+
* required for writes. No hard-delete endpoint — use `delete-document` or
|
|
30
|
+
* `cleanup` for bulk removal.
|
|
31
|
+
*
|
|
32
|
+
* INVARIANT: `update` only patches `content` and `metadata`.
|
|
33
|
+
* INVARIANT: `searchSimilar` requires a pre-computed `query_embedding` vector.
|
|
34
|
+
* Use `searchSemantic` for text-based fallback.
|
|
35
|
+
*
|
|
36
|
+
* @seeAlso agent-runner.ts (executeSearchKnowledge calls search_similar_embeddings)
|
|
37
|
+
* @seeAlso pipeline-runner.ts (search_knowledge stage type)
|
|
38
|
+
* @seeAlso audit.ts (emitLog for embedding.* / embeddings.* events)
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
import { createHandler } from './_shared/middleware'
|
|
42
|
+
import { emitLog } from './_shared/audit'
|
|
43
|
+
import { sanitizeRecordData } from './_shared/permissions'
|
|
44
|
+
|
|
45
|
+
// ─── HANDLERS ─────────────────────────────────────────────────────────────────
|
|
46
|
+
|
|
47
|
+
// ─── CHUNK_START: EMBEDDINGS_LIST ──────────────────────────────────────────────
|
|
48
|
+
/**
|
|
49
|
+
* @chunk-id EMBEDDINGS_LIST_1_0_0
|
|
50
|
+
* @version 1.0.0
|
|
51
|
+
* @hash 929d4ac3030c10ac7a31bef9cad565900a5cd11af2e130ce3e4cfc28bc65d5ab
|
|
52
|
+
* @macro Embeddings List Handler
|
|
53
|
+
* @micro Lists embeddings with filtering, pagination, and sanitization
|
|
54
|
+
* @inputs ctx: CoreContext — Request context with principal and database
|
|
55
|
+
* @inputs _body: any — Request body (unused for GET)
|
|
56
|
+
* @outputs Array of sanitized embedding records
|
|
57
|
+
* @depends-on [createHandler, sanitizeRecordData]
|
|
58
|
+
* @depended-by [Netlify function routing]
|
|
59
|
+
* @side-effects [DB queries, permission sanitization]
|
|
60
|
+
* @tags embeddings, list, crud, pagination
|
|
61
|
+
*/
|
|
62
|
+
export const list = createHandler(async (ctx, _body) => {
|
|
63
|
+
const { model_id, document_id, limit = 100, offset = 0 } = ctx.query || {}
|
|
64
|
+
|
|
65
|
+
if (!ctx.accountId) {
|
|
66
|
+
throw new Error('Account context required')
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// RLS automatically filters to accessible accounts
|
|
70
|
+
let query = ctx.db
|
|
71
|
+
.from('embeddings')
|
|
72
|
+
.select('*')
|
|
73
|
+
.order('created_at', { ascending: false })
|
|
74
|
+
|
|
75
|
+
if (model_id) {
|
|
76
|
+
query = query.eq('model_id', model_id)
|
|
77
|
+
}
|
|
78
|
+
if (document_id) {
|
|
79
|
+
query = query.eq('document_id', document_id)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const parsedOffset = parseInt(offset.toString())
|
|
83
|
+
const parsedLimit = parseInt(limit.toString())
|
|
84
|
+
|
|
85
|
+
const { data, error: err } = await query.range(
|
|
86
|
+
parsedOffset,
|
|
87
|
+
parsedOffset + parsedLimit - 1
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
if (err) throw err
|
|
91
|
+
|
|
92
|
+
const sanitized = []
|
|
93
|
+
for (const embedding of data || []) {
|
|
94
|
+
sanitized.push(await sanitizeRecordData(ctx, embedding, 'embedding'))
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return sanitized
|
|
98
|
+
})
|
|
99
|
+
// ─── CHUNK_END: EMBEDDINGS_LIST ────────────────────────────────────────────────
|
|
100
|
+
|
|
101
|
+
// ─── CHUNK_START: EMBEDDINGS_GET ──────────────────────────────────────────────
|
|
102
|
+
/**
|
|
103
|
+
* @chunk-id EMBEDDINGS_GET_1_0_0
|
|
104
|
+
* @version 1.0.0
|
|
105
|
+
* @hash 261bfd4dd3107ebfbc0a2ee3d870ac449f543699358a03d8bea27f86ba57b5bc
|
|
106
|
+
* @macro Embedding Get Handler
|
|
107
|
+
* @micro Returns single embedding record with sanitization
|
|
108
|
+
* @inputs ctx: CoreContext — Request context with principal and database
|
|
109
|
+
* @inputs _body: any — Request body (unused for GET)
|
|
110
|
+
* @outputs Sanitized embedding record
|
|
111
|
+
* @depends-on [createHandler, sanitizeRecordData]
|
|
112
|
+
* @depended-by [Netlify function routing]
|
|
113
|
+
* @side-effects [DB single row query, permission sanitization]
|
|
114
|
+
* @tags embeddings, get, crud, single-record
|
|
115
|
+
*/
|
|
116
|
+
export const get = createHandler(async (ctx, _body) => {
|
|
117
|
+
const { id } = ctx.query || {}
|
|
118
|
+
|
|
119
|
+
if (!id) {
|
|
120
|
+
throw new Error('Embedding ID is required')
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const { data, error: err } = await ctx.db
|
|
124
|
+
.from('embeddings')
|
|
125
|
+
.select('*')
|
|
126
|
+
.eq('id', id)
|
|
127
|
+
.single()
|
|
128
|
+
|
|
129
|
+
if (err) throw err
|
|
130
|
+
|
|
131
|
+
return await sanitizeRecordData(ctx, data, 'embedding')
|
|
132
|
+
})
|
|
133
|
+
// ─── CHUNK_END: EMBEDDINGS_GET ────────────────────────────────────────────────
|
|
134
|
+
|
|
135
|
+
// ─── CHUNK_START: EMBEDDINGS_CREATE ──────────────────────────────────────────────
|
|
136
|
+
/**
|
|
137
|
+
* @chunk-id EMBEDDINGS_CREATE_1_0_0
|
|
138
|
+
* @version 1.0.0
|
|
139
|
+
* @hash 26bc1b478138d27fc02ebeede1b0ede362ef43864591bc7353390d5f60ae81db
|
|
140
|
+
* @macro Embedding Create Handler
|
|
141
|
+
* @micro Creates embedding record with validation and audit logging
|
|
142
|
+
* @inputs ctx: CoreContext — Request context with principal and database
|
|
143
|
+
* @inputs body: object — Embedding data including model_id, document_id, content
|
|
144
|
+
* @outputs Inserted embedding record
|
|
145
|
+
* @depends-on [createHandler, emitLog]
|
|
146
|
+
* @depended-by [Netlify function routing]
|
|
147
|
+
* @side-effects [DB insert, audit logging]
|
|
148
|
+
* @tags embeddings, create, crud, audit
|
|
149
|
+
*/
|
|
150
|
+
export const create = createHandler(async (ctx, body) => {
|
|
151
|
+
const { model_id, document_id, chunk_index, content, metadata } = body
|
|
152
|
+
|
|
153
|
+
if (!model_id || !document_id || !content) {
|
|
154
|
+
throw new Error('model_id, document_id, and content are required')
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (!ctx.principal || ctx.principal.id === 'anonymous' || !ctx.accountId) {
|
|
158
|
+
throw new Error('User context (person and account) required')
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const { data, error: err } = await ctx.db
|
|
162
|
+
.from('embeddings')
|
|
163
|
+
.insert({
|
|
164
|
+
model_id,
|
|
165
|
+
document_id,
|
|
166
|
+
chunk_index: chunk_index || 0,
|
|
167
|
+
content,
|
|
168
|
+
metadata: metadata || {},
|
|
169
|
+
account_id: ctx.accountId
|
|
170
|
+
})
|
|
171
|
+
.select()
|
|
172
|
+
.single()
|
|
173
|
+
|
|
174
|
+
if (err) throw err
|
|
175
|
+
|
|
176
|
+
await emitLog(ctx, 'embedding.created',
|
|
177
|
+
{ type: 'embedding', id: data.id },
|
|
178
|
+
{ after: { document_id, model_id } }
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
return data
|
|
182
|
+
})
|
|
183
|
+
// ─── CHUNK_END: EMBEDDINGS_CREATE ────────────────────────────────────────────────
|
|
184
|
+
|
|
185
|
+
// ─── CHUNK_START: EMBEDDINGS_UPDATE ──────────────────────────────────────────────
|
|
186
|
+
/**
|
|
187
|
+
* @chunk-id EMBEDDINGS_UPDATE_1_0_0
|
|
188
|
+
* @version 1.0.0
|
|
189
|
+
* @hash e543c87308991159cda8e50f85127884475004bffaedb4508117481375bfaa43
|
|
190
|
+
* @macro Embedding Update Handler
|
|
191
|
+
* @micro Updates embedding content and/or metadata with audit logging
|
|
192
|
+
* @inputs ctx: CoreContext — Request context with principal and database
|
|
193
|
+
* @inputs body: object — Embedding updates including id
|
|
194
|
+
* @outputs Updated embedding record
|
|
195
|
+
* @depends-on [createHandler, emitLog]
|
|
196
|
+
* @depended-by [Netlify function routing]
|
|
197
|
+
* @side-effects [DB update, audit logging]
|
|
198
|
+
* @tags embeddings, update, crud, audit
|
|
199
|
+
*/
|
|
200
|
+
export const update = createHandler(async (ctx, body) => {
|
|
201
|
+
const id = body?.id || ctx.query?.id
|
|
202
|
+
const { id: _bodyId, content, metadata } = body || {}
|
|
203
|
+
|
|
204
|
+
if (!id) {
|
|
205
|
+
throw new Error('Embedding ID is required')
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const updateFields: Record<string, any> = {}
|
|
209
|
+
if (content !== undefined) updateFields.content = content
|
|
210
|
+
if (metadata !== undefined) updateFields.metadata = metadata
|
|
211
|
+
|
|
212
|
+
const { data, error: err } = await ctx.db
|
|
213
|
+
.from('embeddings')
|
|
214
|
+
.update(updateFields)
|
|
215
|
+
.eq('id', id)
|
|
216
|
+
.select()
|
|
217
|
+
.single()
|
|
218
|
+
|
|
219
|
+
if (err) throw err
|
|
220
|
+
|
|
221
|
+
await emitLog(ctx, 'embedding.updated',
|
|
222
|
+
{ type: 'embedding', id },
|
|
223
|
+
{ after: { content_updated: !!content } }
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
return data
|
|
227
|
+
})
|
|
228
|
+
// ─── CHUNK_END: EMBEDDINGS_UPDATE ────────────────────────────────────────────────
|
|
229
|
+
|
|
230
|
+
// ─── CHUNK_START: EMBEDDINGS_GET_STATS ──────────────────────────────────────────────
|
|
231
|
+
/**
|
|
232
|
+
* @chunk-id EMBEDDINGS_GET_STATS_1_0_0
|
|
233
|
+
* @version 1.0.0
|
|
234
|
+
* @hash 176a002d14e89cffb0cb993b554c28e2258f66951901be49a4eccbe7855a2d7a
|
|
235
|
+
* @macro Embeddings Statistics Handler
|
|
236
|
+
* @micro Returns total embedding count for account with RLS scoping
|
|
237
|
+
* @inputs ctx: CoreContext — Request context with principal and database
|
|
238
|
+
* @inputs _body: any — Request body (unused for GET)
|
|
239
|
+
* @outputs {total_embeddings: number} — Total count of embeddings
|
|
240
|
+
* @depends-on [createHandler]
|
|
241
|
+
* @depended-by [Netlify function routing]
|
|
242
|
+
* @side-effects [DB count query]
|
|
243
|
+
* @tags embeddings, stats, count, monitoring
|
|
244
|
+
*/
|
|
245
|
+
export const getStats = createHandler(async (ctx, _body) => {
|
|
246
|
+
if (!ctx.accountId) {
|
|
247
|
+
throw new Error('Account context required')
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const { count, error: err } = await ctx.db
|
|
251
|
+
.from('embeddings')
|
|
252
|
+
.select('*', { count: 'exact', head: true })
|
|
253
|
+
|
|
254
|
+
if (err) throw err
|
|
255
|
+
|
|
256
|
+
return { total_embeddings: count || 0 }
|
|
257
|
+
})
|
|
258
|
+
// ─── CHUNK_END: EMBEDDINGS_GET_STATS ────────────────────────────────────────────────
|
|
259
|
+
|
|
260
|
+
// ─── CHUNK_START: EMBEDDINGS_BATCH_CREATE ──────────────────────────────────────────────
|
|
261
|
+
/**
|
|
262
|
+
* @chunk-id EMBEDDINGS_BATCH_CREATE_1_0_0
|
|
263
|
+
* @version 1.0.0
|
|
264
|
+
* @hash 18f603dbb73e044737283100d6e4cc092597a61645905473d6c6ec1ee67a9d7f
|
|
265
|
+
* @macro Embeddings Batch Create Handler
|
|
266
|
+
* @micro Bulk inserts multiple embeddings with account stamping and audit logging
|
|
267
|
+
* @inputs ctx: CoreContext — Request context with principal and database
|
|
268
|
+
* @inputs body: object — embeddings_data array of embedding objects
|
|
269
|
+
* @outputs Array of inserted embedding records
|
|
270
|
+
* @depends-on [createHandler, emitLog]
|
|
271
|
+
* @depended-by [Netlify function routing]
|
|
272
|
+
* @side-effects [Bulk DB insert, audit logging]
|
|
273
|
+
* @tags embeddings, batch-create, bulk, audit
|
|
274
|
+
*/
|
|
275
|
+
export const batchCreate = createHandler(async (ctx, body) => {
|
|
276
|
+
const { embeddings_data } = body
|
|
277
|
+
|
|
278
|
+
if (!embeddings_data || !Array.isArray(embeddings_data)) {
|
|
279
|
+
throw new Error('embeddings_data array is required')
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (!ctx.accountId) {
|
|
283
|
+
throw new Error('Account context required')
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const rows = embeddings_data.map((e: any) => ({
|
|
287
|
+
...e,
|
|
288
|
+
account_id: ctx.accountId
|
|
289
|
+
}))
|
|
290
|
+
|
|
291
|
+
const { data, error: err } = await ctx.db
|
|
292
|
+
.from('embeddings')
|
|
293
|
+
.insert(rows)
|
|
294
|
+
.select()
|
|
295
|
+
|
|
296
|
+
if (err) throw err
|
|
297
|
+
|
|
298
|
+
await emitLog(ctx, 'embeddings.batch_created',
|
|
299
|
+
{ type: 'system', id: 'batch_create' },
|
|
300
|
+
{ after: { batch_size: embeddings_data.length } }
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
return data
|
|
304
|
+
})
|
|
305
|
+
// ─── CHUNK_END: EMBEDDINGS_BATCH_CREATE ────────────────────────────────────────────────
|
|
306
|
+
|
|
307
|
+
// ─── CHUNK_START: EMBEDDINGS_DELETE_BY_DOCUMENT ──────────────────────────────────────────────
|
|
308
|
+
/**
|
|
309
|
+
* @chunk-id EMBEDDINGS_DELETE_BY_DOCUMENT_1_0_0
|
|
310
|
+
* @version 1.0.0
|
|
311
|
+
* @hash 1f74f199f69f563dbc9e72c0f3906412d6315721212261c5a61da4250cb34909
|
|
312
|
+
* @macro Embeddings Document Delete Handler
|
|
313
|
+
* @micro Deletes all embeddings for a document with audit logging
|
|
314
|
+
* @inputs ctx: CoreContext — Request context with principal and database
|
|
315
|
+
* @inputs body: object — document_id to delete embeddings for
|
|
316
|
+
* @outputs {deleted_count: number} — Number of deleted embeddings
|
|
317
|
+
* @depends-on [createHandler, emitLog]
|
|
318
|
+
* @depended-by [Netlify function routing]
|
|
319
|
+
* @side-effects [DB delete, audit logging]
|
|
320
|
+
* @tags embeddings, delete, document, audit
|
|
321
|
+
*/
|
|
322
|
+
export const deleteByDocument = createHandler(async (ctx, body) => {
|
|
323
|
+
const { document_id } = body
|
|
324
|
+
|
|
325
|
+
if (!document_id) {
|
|
326
|
+
throw new Error('document_id is required')
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const { data, error: err } = await ctx.db
|
|
330
|
+
.from('embeddings')
|
|
331
|
+
.delete()
|
|
332
|
+
.eq('document_id', document_id)
|
|
333
|
+
.select()
|
|
334
|
+
|
|
335
|
+
if (err) throw err
|
|
336
|
+
|
|
337
|
+
await emitLog(ctx, 'embeddings.document_deleted',
|
|
338
|
+
{ type: 'system', id: 'document_delete' },
|
|
339
|
+
{ after: { document_id, deleted_count: data?.length || 0 } }
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
return { deleted_count: data?.length || 0 }
|
|
343
|
+
})
|
|
344
|
+
// ─── CHUNK_END: EMBEDDINGS_DELETE_BY_DOCUMENT ────────────────────────────────────────────────
|
|
345
|
+
|
|
346
|
+
// ─── CHUNK_START: EMBEDDINGS_CLEANUP ──────────────────────────────────────────────
|
|
347
|
+
/**
|
|
348
|
+
* @chunk-id EMBEDDINGS_CLEANUP_1_0_0
|
|
349
|
+
* @version 1.0.0
|
|
350
|
+
* @hash b5caa85d93d7eb232eaf7f81c63f7adc4269898397c4cc1d9186ce868a056223
|
|
351
|
+
* @macro Embeddings Cleanup Handler
|
|
352
|
+
* @micro Deletes old embeddings beyond retention period with audit logging
|
|
353
|
+
* @inputs ctx: CoreContext — Request context with principal and database
|
|
354
|
+
* @inputs body: object — days_to_keep (default 365)
|
|
355
|
+
* @outputs {deleted_count: number} — Number of deleted embeddings
|
|
356
|
+
* @depends-on [createHandler, emitLog]
|
|
357
|
+
* @depended-by [Netlify function routing]
|
|
358
|
+
* @side-effects [DB delete by date, audit logging]
|
|
359
|
+
* @tags embeddings, cleanup, retention, audit
|
|
360
|
+
*/
|
|
361
|
+
export const cleanup = createHandler(async (ctx, body) => {
|
|
362
|
+
const { days_to_keep } = body
|
|
363
|
+
const daysToKeep = days_to_keep || 365
|
|
364
|
+
|
|
365
|
+
const cutoff = new Date()
|
|
366
|
+
cutoff.setDate(cutoff.getDate() - daysToKeep)
|
|
367
|
+
|
|
368
|
+
const { data, error: err } = await ctx.db
|
|
369
|
+
.from('embeddings')
|
|
370
|
+
.delete()
|
|
371
|
+
.lt('created_at', cutoff.toISOString())
|
|
372
|
+
.select()
|
|
373
|
+
|
|
374
|
+
if (err) throw err
|
|
375
|
+
|
|
376
|
+
await emitLog(ctx, 'embeddings.cleaned',
|
|
377
|
+
{ type: 'system', id: 'batch_cleanup' },
|
|
378
|
+
{ after: { days_to_keep: daysToKeep, deleted_count: data?.length || 0 } }
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
return { deleted_count: data?.length || 0 }
|
|
382
|
+
})
|
|
383
|
+
// ─── CHUNK_END: EMBEDDINGS_CLEANUP ────────────────────────────────────────────────
|
|
384
|
+
|
|
385
|
+
// ─── CHUNK_START: EMBEDDINGS_SEARCH_SIMILAR ──────────────────────────────────────────────
|
|
386
|
+
/**
|
|
387
|
+
* @chunk-id EMBEDDINGS_SEARCH_SIMILAR_1_0_0
|
|
388
|
+
* @version 1.0.0
|
|
389
|
+
* @hash e34df64fa1db62cdef551da14b15e6f7183915562ca68763b5ebe28fe889fff7
|
|
390
|
+
* @macro Embeddings Vector Search Handler
|
|
391
|
+
* @micro Performs vector similarity search using cosine similarity via RPC
|
|
392
|
+
* @inputs ctx: CoreContext — Request context with principal and database
|
|
393
|
+
* @inputs body: object — query_embedding vector and search parameters
|
|
394
|
+
* @outputs {results, count, model_id, threshold} — Search results with metadata
|
|
395
|
+
* @depends-on [createHandler]
|
|
396
|
+
* @depended-by [Netlify function routing, agent-runner.ts]
|
|
397
|
+
* @side-effects [RPC call for vector similarity search]
|
|
398
|
+
* @tags embeddings, search, vector, similarity, rpc
|
|
399
|
+
*/
|
|
400
|
+
export const searchSimilar = createHandler(async (ctx, body) => {
|
|
401
|
+
const { query_embedding, model_id, limit = 10, threshold = 0.7 } = body || {}
|
|
402
|
+
|
|
403
|
+
if (!ctx.accountId) {
|
|
404
|
+
throw new Error('Account context required')
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (!query_embedding) {
|
|
408
|
+
throw new Error('query_embedding is required for similarity search')
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Call the RPC function for vector similarity search
|
|
412
|
+
const { data, error: err } = await ctx.db.rpc('search_similar_embeddings', {
|
|
413
|
+
p_account_id: ctx.accountId,
|
|
414
|
+
p_model_id: model_id || 'text-embedding-ada-002',
|
|
415
|
+
p_query_embedding: query_embedding,
|
|
416
|
+
p_limit: parseInt(limit.toString()),
|
|
417
|
+
p_threshold: parseFloat(threshold.toString())
|
|
418
|
+
})
|
|
419
|
+
|
|
420
|
+
if (err) throw err
|
|
421
|
+
|
|
422
|
+
return {
|
|
423
|
+
results: data || [],
|
|
424
|
+
count: data?.length || 0,
|
|
425
|
+
model_id: model_id || 'text-embedding-ada-002',
|
|
426
|
+
threshold: parseFloat(threshold.toString())
|
|
427
|
+
}
|
|
428
|
+
})
|
|
429
|
+
// ─── CHUNK_END: EMBEDDINGS_SEARCH_SIMILAR ────────────────────────────────────────────────
|
|
430
|
+
|
|
431
|
+
// ─── CHUNK_START: EMBEDDINGS_SEARCH_SEMANTIC ──────────────────────────────────────────────
|
|
432
|
+
/**
|
|
433
|
+
* @chunk-id EMBEDDINGS_SEARCH_SEMANTIC_1_0_0
|
|
434
|
+
* @version 1.0.0
|
|
435
|
+
* @hash 26c9cb4da3ddfa47c34afd1c60c2568f760a97d07719a58e9ae2e3d3926e84ce
|
|
436
|
+
* @macro Embeddings Text Search Handler
|
|
437
|
+
* @micro Performs full-text search on embedding content using Postgres websearch
|
|
438
|
+
* @inputs ctx: CoreContext — Request context with principal and database
|
|
439
|
+
* @inputs body: object — query string and optional filters
|
|
440
|
+
* @outputs {results, count, method, query} — Search results with metadata
|
|
441
|
+
* @depends-on [createHandler]
|
|
442
|
+
* @depended-by [Netlify function routing]
|
|
443
|
+
* @side-effects [DB full-text search query]
|
|
444
|
+
* @tags embeddings, search, text-search, fallback
|
|
445
|
+
*/
|
|
446
|
+
export const searchSemantic = createHandler(async (ctx, body) => {
|
|
447
|
+
const { query, model_id, document_ids, limit = 10 } = body || {}
|
|
448
|
+
|
|
449
|
+
if (!ctx.accountId) {
|
|
450
|
+
throw new Error('Account context required')
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if (!query) {
|
|
454
|
+
throw new Error('query is required for semantic search')
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
let dbQuery = ctx.db
|
|
458
|
+
.from('embeddings')
|
|
459
|
+
.select('*')
|
|
460
|
+
.eq('account_id', ctx.accountId)
|
|
461
|
+
.textSearch('content', query, {
|
|
462
|
+
type: 'websearch',
|
|
463
|
+
config: 'english'
|
|
464
|
+
})
|
|
465
|
+
.limit(parseInt(limit.toString()))
|
|
466
|
+
|
|
467
|
+
if (model_id) {
|
|
468
|
+
dbQuery = dbQuery.eq('model_id', model_id)
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (document_ids && Array.isArray(document_ids) && document_ids.length > 0) {
|
|
472
|
+
dbQuery = dbQuery.in('document_id', document_ids)
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const { data, error: err } = await dbQuery
|
|
476
|
+
|
|
477
|
+
if (err) throw err
|
|
478
|
+
|
|
479
|
+
return {
|
|
480
|
+
results: data || [],
|
|
481
|
+
count: data?.length || 0,
|
|
482
|
+
method: 'text_search',
|
|
483
|
+
query
|
|
484
|
+
}
|
|
485
|
+
})
|
|
486
|
+
// ─── CHUNK_END: EMBEDDINGS_SEARCH_SEMANTIC ────────────────────────────────────────────────
|
|
487
|
+
|
|
488
|
+
// ─── MAIN HANDLER ────────────────────────────────────────────────────────────
|
|
489
|
+
|
|
490
|
+
// ─── CHUNK_START: EMBEDDINGS_HANDLER ──────────────────────────────────────────────
|
|
491
|
+
/**
|
|
492
|
+
* @chunk-id EMBEDDINGS_HANDLER_1_0_0
|
|
493
|
+
* @version 1.0.0
|
|
494
|
+
* @hash 5c4c550bcf413d5975c54a1f1cbfbc4641425d663127fa55fac1616085a43644
|
|
495
|
+
* @macro Embeddings Router
|
|
496
|
+
* @micro Routes HTTP methods and actions to appropriate handlers
|
|
497
|
+
* @inputs ctx: CoreContext — Request context with principal and database
|
|
498
|
+
* @inputs body: any — Request body for POST/PATCH operations
|
|
499
|
+
* @outputs Varies — Depends on routed handler (list/get/create/update/batch-create/delete-document/cleanup/search-similar/search-semantic/stats)
|
|
500
|
+
* @depends-on [createHandler, list, get, create, update, getStats, batchCreate, deleteByDocument, cleanup, searchSimilar, searchSemantic]
|
|
501
|
+
* @depended-by [Netlify function routing]
|
|
502
|
+
* @side-effects [Delegates to appropriate handler]
|
|
503
|
+
* @tags embeddings, router, crud, netlify-function
|
|
504
|
+
*/
|
|
505
|
+
export const handler = createHandler(async (ctx, body) => {
|
|
506
|
+
const { action } = ctx.query || {}
|
|
507
|
+
const method = ctx.query?.method || 'GET'
|
|
508
|
+
|
|
509
|
+
switch (action) {
|
|
510
|
+
case 'stats':
|
|
511
|
+
if (method === 'GET') {
|
|
512
|
+
return await getStats(ctx, body)
|
|
513
|
+
}
|
|
514
|
+
break
|
|
515
|
+
case 'batch-create':
|
|
516
|
+
if (method === 'POST') {
|
|
517
|
+
return await batchCreate(ctx, body)
|
|
518
|
+
}
|
|
519
|
+
break
|
|
520
|
+
case 'delete-document':
|
|
521
|
+
if (method === 'POST') {
|
|
522
|
+
return await deleteByDocument(ctx, body)
|
|
523
|
+
}
|
|
524
|
+
break
|
|
525
|
+
case 'cleanup':
|
|
526
|
+
if (method === 'POST') {
|
|
527
|
+
return await cleanup(ctx, body)
|
|
528
|
+
}
|
|
529
|
+
break
|
|
530
|
+
case 'search-similar':
|
|
531
|
+
if (method === 'POST') {
|
|
532
|
+
return await searchSimilar(ctx, body)
|
|
533
|
+
}
|
|
534
|
+
break
|
|
535
|
+
case 'search-semantic':
|
|
536
|
+
if (method === 'POST') {
|
|
537
|
+
return await searchSemantic(ctx, body)
|
|
538
|
+
}
|
|
539
|
+
break
|
|
540
|
+
default:
|
|
541
|
+
if (method === 'GET') {
|
|
542
|
+
if (ctx.query?.id) {
|
|
543
|
+
return await get(ctx, body)
|
|
544
|
+
} else {
|
|
545
|
+
return await list(ctx, body)
|
|
546
|
+
}
|
|
547
|
+
} else if (method === 'POST') {
|
|
548
|
+
return await create(ctx, body)
|
|
549
|
+
} else if (method === 'PATCH') {
|
|
550
|
+
return await update(ctx, body)
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
throw new Error('Invalid action or method')
|
|
555
|
+
})
|
|
556
|
+
// ─── CHUNK_END: EMBEDDINGS_HANDLER ────────────────────────────────────────────────
|