okengine 0.18.4 → 0.19.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/AGENTS.md +18 -10
- package/README.md +2 -2
- package/package.json +51 -50
- package/site/content/docs/ai/index.mdx +25 -6
- package/site/content/docs/ai/llms-txt.mdx +1 -1
- package/site/content/docs/ai/meta.json +1 -1
- package/site/content/docs/ai/skills.mdx +4 -1
- package/site/content/docs/ai/try-it.mdx +58 -0
- package/site/content/docs/client/auth.mdx +208 -0
- package/site/content/docs/client/calling.mdx +451 -0
- package/site/content/docs/client/index.mdx +209 -0
- package/site/content/docs/client/live.mdx +234 -0
- package/site/content/docs/client/meta.json +5 -0
- package/site/content/docs/client/react.mdx +249 -0
- package/site/content/docs/elements/ai/agents.mdx +232 -0
- package/site/content/docs/elements/ai/index.mdx +341 -0
- package/site/content/docs/elements/ai/mcp.mdx +275 -0
- package/site/content/docs/elements/ai/meta.json +5 -0
- package/site/content/docs/elements/ai/models.mdx +283 -0
- package/site/content/docs/elements/ai/prompts.mdx +256 -0
- package/site/content/docs/elements/channel/email.mdx +266 -0
- package/site/content/docs/elements/channel/index.mdx +344 -0
- package/site/content/docs/elements/channel/meta.json +5 -0
- package/site/content/docs/elements/channel/push.mdx +218 -0
- package/site/content/docs/elements/channel/receipts.mdx +206 -0
- package/site/content/docs/elements/channel/sms.mdx +264 -0
- package/site/content/docs/elements/channel/whatsapp.mdx +220 -0
- package/site/content/docs/elements/clock/index.mdx +300 -0
- package/site/content/docs/elements/clock/meta.json +5 -0
- package/site/content/docs/elements/clock/schedules.mdx +508 -0
- package/site/content/docs/elements/clock/sleep.mdx +445 -0
- package/site/content/docs/elements/flow/consumers.mdx +707 -0
- package/site/content/docs/elements/flow/http.mdx +1080 -0
- package/site/content/docs/elements/flow/index.mdx +618 -0
- package/site/content/docs/elements/flow/meta.json +5 -0
- package/site/content/docs/elements/flow/routing.mdx +559 -0
- package/site/content/docs/elements/flow/workflows.mdx +640 -0
- package/site/content/docs/elements/gate/auth.mdx +371 -0
- package/site/content/docs/elements/gate/authorization.mdx +298 -0
- package/site/content/docs/elements/gate/index.mdx +418 -0
- package/site/content/docs/elements/gate/meta.json +5 -0
- package/site/content/docs/elements/gate/rate-limits.mdx +365 -0
- package/site/content/docs/elements/gate/rls.mdx +303 -0
- package/site/content/docs/elements/gate/tenancy.mdx +372 -0
- package/site/content/docs/elements/index.mdx +52 -11
- package/site/content/docs/elements/signal/broadcast.mdx +517 -0
- package/site/content/docs/elements/signal/index.mdx +352 -0
- package/site/content/docs/elements/signal/live.mdx +590 -0
- package/site/content/docs/elements/signal/meta.json +5 -0
- package/site/content/docs/elements/signal/once.mdx +596 -0
- package/site/content/docs/elements/store/files.mdx +659 -0
- package/site/content/docs/elements/store/index.mdx +310 -0
- package/site/content/docs/elements/store/kv.mdx +629 -0
- package/site/content/docs/elements/store/meta.json +5 -0
- package/site/content/docs/elements/store/search.mdx +946 -0
- package/site/content/docs/elements/store/sql.mdx +937 -0
- package/site/content/docs/elements/vault/config.mdx +256 -0
- package/site/content/docs/elements/vault/index.mdx +356 -0
- package/site/content/docs/elements/vault/meta.json +5 -0
- package/site/content/docs/elements/vault/rotation.mdx +273 -0
- package/site/content/docs/elements/vault/secrets.mdx +285 -0
- package/site/content/docs/index.mdx +78 -30
- package/site/content/docs/meta.json +11 -8
- package/site/content/docs/plugins/cors.mdx +2 -1
- package/site/content/docs/plugins/csrf.mdx +4 -1
- package/site/content/docs/plugins/headers.mdx +2 -1
- package/site/content/docs/plugins/ip-allowlist.mdx +2 -1
- package/site/content/docs/plugins/magic-link.mdx +6 -0
- package/site/content/docs/plugins/maintenance-mode.mdx +2 -1
- package/site/content/docs/plugins/oauth.mdx +1 -1
- package/site/content/docs/plugins/otp.mdx +12 -1
- package/site/content/docs/plugins/passkey.mdx +39 -15
- package/site/content/docs/plugins/two-factor.mdx +91 -34
- package/site/content/docs/plugins/username.mdx +1 -1
- package/site/content/docs/recipes/caddy.mdx +3 -3
- package/site/content/docs/recipes/index.mdx +18 -28
- package/site/content/docs/recipes/mailpit.mdx +1 -1
- package/site/content/docs/recipes/meilisearch.mdx +3 -3
- package/site/content/docs/recipes/meta.json +1 -4
- package/site/content/docs/recipes/nginx.mdx +2 -2
- package/site/content/docs/recipes/openrouter.mdx +283 -0
- package/site/content/docs/recipes/pgdog.mdx +3 -3
- package/site/content/docs/recipes/postgres.mdx +1 -2
- package/site/content/docs/recipes/rustfs.mdx +2 -2
- package/site/content/docs/recipes/traefik.mdx +3 -3
- package/site/content/docs/reference/cli.mdx +231 -0
- package/site/content/docs/reference/configuration.mdx +30 -10
- package/site/content/docs/reference/environment-variables.mdx +93 -20
- package/site/content/docs/reference/errors.mdx +132 -29
- package/site/content/docs/reference/fx.mdx +137 -73
- package/site/content/docs/reference/index.mdx +13 -21
- package/site/content/docs/reference/meta.json +4 -5
- package/site/content/docs/reference/okid.mdx +42 -17
- package/site/content/docs/reference/plugins.mdx +4 -3
- package/site/content/docs/reference/security.mdx +197 -0
- package/site/content/docs/understand/meta.json +5 -0
- package/site/content/docs/understand/the-anatomy.mdx +132 -0
- package/site/content/docs/understand/the-model.mdx +32 -0
- package/site/content/docs/understand/the-problem.mdx +74 -0
- package/site/content/docs/understand/the-vocabulary.mdx +26 -0
- package/src/auth/api-keys.ts +2 -1
- package/src/auth/bindings.ts +64 -16
- package/src/auth/gate-auth.test.ts +6 -1
- package/src/auth/identity.ts +152 -5
- package/src/auth/index.ts +29 -0
- package/src/auth/invites.ts +2 -1
- package/src/auth/method-context.ts +41 -0
- package/src/auth/oauth-as/crypto.ts +2 -1
- package/src/auth/oauth-as/stores.ts +2 -1
- package/src/auth/operator.ts +2 -1
- package/src/auth/sessions-jwt.test.ts +77 -0
- package/src/auth/sessions.ts +20 -4
- package/src/auth/tenants.ts +3 -2
- package/src/auth/two-factor-challenge.test.ts +61 -0
- package/src/auth/two-factor-challenge.ts +284 -0
- package/src/auth/verification.ts +5 -0
- package/src/bench/REPORT.md +49 -0
- package/src/bench/g03-signal-once.bench.ts +1 -1
- package/src/bench/g10-observability-contention.bench.ts +1 -1
- package/src/bench/g17-hybrid-search.bench.ts +572 -0
- package/src/bench/load-app.ts +2 -10
- package/src/cli/ai-setup/ai-setup.test.ts +331 -42
- package/src/cli/ai-setup/apply.ts +294 -52
- package/src/cli/ai-setup/catalog.ts +238 -1342
- package/src/cli/ai-setup/index.ts +14 -99
- package/src/cli/ai-setup/prompts.ts +60 -443
- package/src/cli/ask-seed.test.ts +96 -0
- package/src/cli/ask-seed.ts +82 -0
- package/src/cli/ask-vault-gaps.test.ts +84 -0
- package/src/cli/ask-vault-gaps.ts +146 -0
- package/src/cli/build.ts +2 -2
- package/src/cli/client-add.test.ts +26 -1
- package/src/cli/client-add.ts +106 -27
- package/src/cli/competitor-mention-removal.test.ts +1 -1
- package/src/cli/db-seed.ts +2 -0
- package/src/cli/db.ts +150 -11
- package/src/cli/dev.ts +119 -211
- package/src/cli/docker-clean.ts +2 -2
- package/src/cli/docker-cli.test.ts +1 -1
- package/src/cli/doctor-diff.ts +4 -2
- package/src/cli/doctor-pii.test.ts +1 -1
- package/src/cli/doctor.ts +14 -1
- package/src/cli/hero-meta.test.ts +4 -2
- package/src/cli/load-config.images.test.ts +8 -10
- package/src/cli/load-config.ts +1 -1
- package/src/cli/registry.ts +22 -10
- package/src/cli/replay.ts +3 -1
- package/src/cli/start.ts +1 -1
- package/src/cli/tui/keys.ts +2 -3
- package/src/client/auth/cookies.ts +74 -0
- package/src/client/auth/create-auth-client.ts +636 -0
- package/src/client/auth/denials.ts +99 -0
- package/src/client/auth/session.ts +283 -0
- package/src/client/auth.test.ts +251 -0
- package/src/client/auth.ts +39 -114
- package/src/client/create-with-session.ts +245 -0
- package/src/client/create.ts +51 -5
- package/src/client/index.ts +11 -1
- package/src/client/live.ts +11 -79
- package/src/client/notes-contract.test.ts +5 -10
- package/src/client/sse.ts +137 -0
- package/src/client/stream.ts +147 -0
- package/src/client/transport.test.ts +32 -0
- package/src/client/transport.ts +123 -26
- package/src/client/types.ts +118 -14
- package/src/client-react/index.ts +185 -24
- package/src/client-react/use-live-query.ts +13 -3
- package/src/compiler/aot.test.ts +7 -4
- package/src/compiler/effects-embed.test.ts +56 -0
- package/src/compiler/effects-fetch.test.ts +43 -0
- package/src/compiler/effects-infer.ts +58 -2
- package/src/compiler/extract.test.ts +258 -44
- package/src/compiler/extract.ts +566 -48
- package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -4
- package/src/compiler/fixtures/skyport/src/flows/bookings/signals.ts +2 -8
- package/src/compiler/fixtures/skyport.expected.json +4 -4
- package/src/compiler/fixtures/triggers/five-triggers.ts +14 -10
- package/src/compiler/response.ts +2 -2
- package/src/compiler/search-writer-isolation.test.ts +40 -0
- package/src/config/index.ts +11 -0
- package/src/console/server/app.ts +17 -23
- package/src/console/server/bind.ts +4 -0
- package/src/console/server/console.test.ts +2 -2
- package/src/console/server/flows-invoke.test.ts +50 -34
- package/src/console/server/flows.ts +436 -255
- package/src/console/server/runs-ingest.test.ts +6 -3
- package/src/console/server/serve.ts +1 -1
- package/src/console/server/signals.test.ts +1 -5
- package/src/console/server/signals.ts +8 -6
- package/src/console/server/state.ts +6 -1
- package/src/console/server/store.ts +1 -1
- package/src/console/ui-next/dist/assets/FileExportIcon-Ck-5od4R.js +1 -0
- package/src/console/ui-next/dist/assets/MoreHorizontalCircle01Icon-gMNGsE37.js +1 -0
- package/src/console/ui-next/dist/assets/PlusSignIcon-CwG3nxfu.js +1 -0
- package/src/console/ui-next/dist/assets/UnavailableIcon-D9cvHVPr.js +1 -0
- package/src/console/ui-next/dist/assets/UserIcon-DaE2PB5_.js +1 -0
- package/src/console/ui-next/dist/assets/access-page-DFeymU07.js +4 -0
- package/src/console/ui-next/dist/assets/agent-disclosure-U1rdfblp.js +1 -0
- package/src/console/ui-next/dist/assets/cache-glyph-BeFJeqBG.js +1 -0
- package/src/console/ui-next/dist/assets/call-pii-button-CVAONPii.js +1 -0
- package/src/console/ui-next/dist/assets/collapsible-D2A6NJ-3.js +1 -0
- package/src/console/ui-next/dist/assets/copy-inline-button-CAYD18cr.js +1 -0
- package/src/console/ui-next/dist/assets/dagre.esm-B1_XeuLP.js +1 -0
- package/src/console/ui-next/dist/assets/detail-header-DVWNjWjg.js +1 -0
- package/src/console/ui-next/dist/assets/dropdown-menu-4h2LOVXM.js +1 -0
- package/src/console/ui-next/dist/assets/duration-tone-Cgk_h5ja.js +9 -0
- package/src/console/ui-next/dist/assets/element-icons-BI8cJgdh.js +1 -0
- package/src/console/ui-next/dist/assets/explorer-empty-CJs5A-wm.js +1 -0
- package/src/console/ui-next/dist/assets/flows-page-Dss7941e.js +1 -0
- package/src/console/ui-next/dist/assets/highlighted-json-MYZQtRnw.js +154 -0
- package/src/console/ui-next/dist/assets/http-method-Jrh39p7A.js +1 -0
- package/src/console/ui-next/dist/assets/index-D0zS5rKO.css +2 -0
- package/src/console/ui-next/dist/assets/index-DXP2dBIF.js +63 -0
- package/src/console/ui-next/dist/assets/observability-page-HvolXxTI.js +4 -0
- package/src/console/ui-next/dist/assets/react-dom-Ddte4I-Q.js +9 -0
- package/src/console/ui-next/dist/assets/replica-lag-CSh2dzrb.js +18 -0
- package/src/console/ui-next/dist/assets/request-meta-BatF8KrK.js +1 -0
- package/src/console/ui-next/dist/assets/shortcut-keys-3ILd8oGn.js +1 -0
- package/src/console/ui-next/dist/assets/{sql-BskegiFM.js → sql-BsFa4tDR.js} +1 -1
- package/src/console/ui-next/dist/assets/store-page-eiKiHnNe.js +41 -0
- package/src/console/ui-next/dist/assets/trace-detail-sheet-CZkMeKS-.js +2 -0
- package/src/console/ui-next/dist/assets/tree-expand-toggle-CW8y5A2h.js +55 -0
- package/src/console/ui-next/dist/assets/units-page-B_RWJrEO.js +1 -0
- package/src/console/ui-next/dist/assets/{use-vault-list-uk4WVboC.js → use-vault-list-CT4-gajj.js} +1 -1
- package/src/console/ui-next/dist/assets/vault-page-CWrg-A68.js +2 -0
- package/src/console/ui-next/dist/assets/xyflow-CSyC6ryz.css +1 -0
- package/src/console/ui-next/dist/assets/xyflow-yApv7D4e.js +7 -0
- package/src/console/ui-next/dist/index.html +6 -13
- package/src/console/ui-next/seed-invoke-host.ts +21 -18
- package/src/console/ui-next/src/client.ts +7 -2
- package/src/console/ui-next/src/features/flows/graph/element-map.ts +2 -0
- package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +12 -2
- package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +4 -0
- package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +8 -0
- package/src/console/ui-next/src/features/flows/traces/waterfall-bars.ts +4 -0
- package/src/console/ui-next/src/features/flows/traces/waterfall-tooltip.ts +9 -3
- package/src/console/ui-next/src/features/store/detail/reveal-cell.tsx +7 -11
- package/src/console/ui-next/src/features/store/detail/store-row-detail-sheet.tsx +2 -2
- package/src/console/ui-next/src/features/store/lib/fields-from-table.ts +2 -0
- package/src/console/ui-next/src/features/store/lib/grid-model.test.ts +25 -1
- package/src/console/ui-next/src/features/store/lib/grid-model.ts +36 -1
- package/src/console/ui-next/src/features/store/query/query-results.tsx +3 -3
- package/src/console/ui-next/src/features/units/detail/effects-summary.tsx +2 -0
- package/src/console/ui-next/src/features/units/lib/call-read-safe.ts +3 -1
- package/src/console/ui-next/src/features/units/lib/fields-from-schema.ts +6 -0
- package/src/docker/ai-model-status.test.ts +1 -12
- package/src/docker/ai-model-status.ts +10 -38
- package/src/docker/compose-up.test.ts +100 -0
- package/src/docker/compose-up.ts +292 -0
- package/src/docker/compose.ts +4 -14
- package/src/docker/derive.ts +9 -34
- package/src/docker/docker.test.ts +16 -261
- package/src/docker/images-config.test.ts +13 -25
- package/src/docker/index.ts +1 -24
- package/src/docker/recipes/index.ts +0 -23
- package/src/docker/recipes/pgdog.ts +6 -4
- package/src/docker/stack-id.test.ts +2 -2
- package/src/docker/stack-id.ts +0 -1
- package/src/docker/types.ts +2 -2
- package/src/drivers/ai-anthropic.ts +10 -0
- package/src/drivers/ai-openai-compatible.ts +34 -7
- package/src/drivers/ai-providers.test.ts +0 -107
- package/src/drivers/ai-stream.test.ts +0 -34
- package/src/drivers/ai-types.ts +17 -8
- package/src/drivers/channel-fcm.ts +6 -1
- package/src/drivers/channel-msegat.ts +6 -1
- package/src/drivers/channel-resend.ts +5 -1
- package/src/drivers/channel-smtp.ts +5 -1
- package/src/drivers/channel-sndr.ts +10 -1
- package/src/drivers/channel-taqnyat-mail.ts +5 -1
- package/src/drivers/channel-taqnyat-whatsapp.ts +6 -1
- package/src/drivers/channel-taqnyat.ts +6 -1
- package/src/drivers/channel-types.ts +10 -0
- package/src/drivers/channel-unifonic.ts +6 -1
- package/src/drivers/channel-wa-cloud.ts +6 -1
- package/src/drivers/channel-webpush.ts +6 -1
- package/src/drivers/external.ts +33 -0
- package/src/drivers/index.ts +0 -10
- package/src/drivers/meilisearch.ts +6 -0
- package/src/drivers/oauth-types.ts +4 -0
- package/src/drivers/postgres.test.ts +74 -3
- package/src/drivers/postgres.ts +175 -6
- package/src/drivers/signal-types.ts +5 -5
- package/src/drivers/types.ts +7 -0
- package/src/drivers/vault-types.ts +5 -0
- package/src/elements/ai/declare.ts +17 -4
- package/src/elements/ai/eval.ts +1 -1
- package/src/elements/ai/mcp-http.ts +1 -1
- package/src/elements/ai/pii.ts +1 -1
- package/src/elements/ai/providers.test.ts +289 -0
- package/src/elements/ai/providers.ts +169 -0
- package/src/elements/ai/runtime.ts +68 -5
- package/src/elements/ai/schema.ts +2 -2
- package/src/elements/ai.test.ts +7 -7
- package/src/elements/ai.ts +17 -1
- package/src/elements/channel/runtime.ts +105 -12
- package/src/elements/clock/cron-fields.test.ts +144 -0
- package/src/elements/clock/cron-fields.ts +185 -0
- package/src/elements/clock/declare.ts +247 -3
- package/src/elements/clock.ts +21 -1
- package/src/elements/index.ts +15 -0
- package/src/elements/signal/chaos-child.ts +1 -2
- package/src/elements/signal/declare.ts +65 -37
- package/src/elements/signal/delivery-modes.test.ts +11 -31
- package/src/elements/signal/dry-run-replay.test.ts +1 -7
- package/src/elements/signal/dry-run-write-isolation.test.ts +1 -7
- package/src/elements/signal/key-ordering.test.ts +6 -26
- package/src/elements/signal/lease-reclaim.test.ts +2 -6
- package/src/elements/signal/optional-emit.test.ts +6 -9
- package/src/elements/signal/order-lifecycle.test.ts +4 -17
- package/src/elements/signal/orphan-messages.test.ts +4 -15
- package/src/elements/signal/reconcile.test.ts +2 -2
- package/src/elements/signal/runtime.ts +1 -1
- package/src/elements/signal/schema-emit.test.ts +4 -8
- package/src/elements/signal.test.ts +24 -49
- package/src/elements/signal.ts +9 -2
- package/src/elements/store/domain-ddl.test.ts +1 -1
- package/src/elements/store/live-http.test.ts +9 -4
- package/src/elements/store/prepare-row.test.ts +123 -0
- package/src/elements/store/resource.ts +43 -12
- package/src/elements/store/schema-decl.ts +117 -0
- package/src/elements/store/search-backfill.ts +205 -0
- package/src/elements/store/search-bind.ts +66 -0
- package/src/elements/store/search-bm25.ts +78 -0
- package/src/elements/store/search-ddl.ts +156 -0
- package/src/elements/store/search-embed-flow.ts +141 -0
- package/src/elements/store/search-errors.ts +34 -0
- package/src/elements/store/search-fusion.ts +112 -0
- package/src/elements/store/search-lsh.ts +179 -0
- package/src/elements/store/search-runtime.ts +300 -0
- package/src/elements/store/search.test.ts +144 -0
- package/src/elements/store/sql-session.test.ts +1 -0
- package/src/elements/store/sql-session.ts +83 -3
- package/src/elements/store/table.ts +23 -2
- package/src/elements/store/upsert-app.test.ts +1 -3
- package/src/elements/store.ts +50 -0
- package/src/full.ts +4 -2
- package/src/http.ts +4 -1
- package/src/i18n/catalogs/ar.ts +14 -6
- package/src/i18n/catalogs/en.ts +14 -6
- package/src/index.ts +6 -1
- package/src/kernel/adopt-barrel-fresh.test.ts +7 -7
- package/src/kernel/adopt-routes.ts +9 -1
- package/src/kernel/app-auth.ts +5 -0
- package/src/kernel/app.ts +102 -9
- package/src/kernel/auto-cache.test.ts +6 -12
- package/src/kernel/auto-registry.test.ts +3 -3
- package/src/kernel/boot-bind/ai.test.ts +22 -19
- package/src/kernel/boot-bind/ai.ts +5 -43
- package/src/kernel/boot-bind/clock.ts +23 -5
- package/src/kernel/boot-bind/honor-config.test.ts +4 -4
- package/src/kernel/boot.test.ts +11 -6
- package/src/kernel/boot.ts +66 -16
- package/src/kernel/boundary-contract.ts +93 -0
- package/src/kernel/budget.test.ts +1 -1
- package/src/kernel/call.ts +89 -0
- package/src/kernel/capability.ts +6 -0
- package/src/kernel/client-descriptor.ts +123 -0
- package/src/kernel/clock-timezone.test.ts +80 -0
- package/src/kernel/correlation.test.ts +1 -1
- package/src/kernel/dry-run.ts +11 -8
- package/src/kernel/effects-stamping.test.ts +42 -9
- package/src/kernel/effects.test.ts +4 -2
- package/src/kernel/effects.ts +51 -9
- package/src/kernel/errors-channel.ts +17 -0
- package/src/kernel/errors-live-resume.ts +3 -2
- package/src/kernel/errors-tenant.ts +7 -4
- package/src/kernel/errors.registry-helpers.ts +96 -0
- package/src/kernel/errors.registry.test.ts +139 -25
- package/src/kernel/errors.ts +102 -23
- package/src/kernel/external-effects.test.ts +196 -0
- package/src/kernel/flow.test.ts +13 -4
- package/src/kernel/flow.ts +69 -71
- package/src/kernel/fx-ask-telemetry.test.ts +2 -2
- package/src/kernel/fx-dead-letters.test.ts +3 -3
- package/src/kernel/fx-fetch.ts +55 -0
- package/src/kernel/fx-live-stream.ts +2 -2
- package/src/kernel/fx-live.test.ts +8 -8
- package/src/kernel/fx.test.ts +17 -11
- package/src/kernel/fx.ts +180 -57
- package/src/kernel/horizontal-child.ts +1 -1
- package/src/kernel/http-query.test.ts +3 -6
- package/src/kernel/index.ts +13 -3
- package/src/kernel/instance-id.ts +1 -1
- package/src/kernel/instances.test.ts +40 -0
- package/src/kernel/instances.ts +47 -9
- package/src/kernel/live-http.test.ts +6 -7
- package/src/kernel/live-http.ts +6 -2
- package/src/kernel/live-resume.test.ts +1 -1
- package/src/kernel/mcp-tool.test.ts +3 -3
- package/src/kernel/on.ts +98 -4
- package/src/kernel/pipeline.test.ts +12 -15
- package/src/kernel/plugin-elements.test.ts +1 -1
- package/src/kernel/stamp-http.test.ts +3 -3
- package/src/kernel/triggers.ts +210 -95
- package/src/kernel-entry.ts +0 -1
- package/src/manifest/diff.ts +11 -1
- package/src/manifest/fixtures/skyport.excerpt.json +1 -1
- package/src/manifest/types.ts +46 -2
- package/src/mcp/docs-index.ts +3 -3
- package/src/mcp/docs-mcp.test.ts +2 -2
- package/src/mcp/docs-tools.ts +1 -1
- package/src/okid.test.ts +56 -0
- package/src/okid.ts +55 -11
- package/src/plugins/anonymous.ts +8 -4
- package/src/plugins/auth/shared.ts +27 -3
- package/src/plugins/auth-delivery.mailpit.integration.test.ts +1 -1
- package/src/plugins/auth-methods.security.test.ts +561 -23
- package/src/plugins/config-source.ts +1 -1
- package/src/plugins/csrf.test.ts +65 -0
- package/src/plugins/index.ts +2 -0
- package/src/plugins/magic-link.ts +36 -16
- package/src/plugins/oauth/shared.ts +3 -1
- package/src/plugins/oauth.ts +22 -14
- package/src/plugins/otp.ts +37 -21
- package/src/plugins/passkey-webauthn.ts +9 -6
- package/src/plugins/passkey.ts +98 -26
- package/src/plugins/pre-account-hijack.test.ts +223 -0
- package/src/plugins/two-factor.ts +466 -37
- package/src/plugins/username.ts +19 -7
- package/src/release/build-lib.ts +1 -0
- package/src/release/limits.ts +2 -2
- package/src/release/measure.ts +1 -1
- package/src/runs/collect.test.ts +0 -2
- package/src/runtime/json-code-block.test.ts +250 -20
- package/src/runtime/json-code-block.ts +1261 -41
- package/src/term.test.ts +1 -1
- package/src/test/create-test-app.test.ts +12 -12
- package/src/test/live-signals.test.ts +6 -6
- package/src/test/provisions.integration.test.ts +10 -14
- package/src/test/reset-element-registries.ts +1 -1
- package/src/test/tenant-isolation.test.ts +12 -6
- package/site/content/docs/deployment/docker-swarm.mdx +0 -164
- package/site/content/docs/deployment/docker.mdx +0 -227
- package/site/content/docs/deployment/index.mdx +0 -83
- package/site/content/docs/deployment/kubernetes.mdx +0 -176
- package/site/content/docs/deployment/meta.json +0 -5
- package/site/content/docs/deployment/reverse-proxy.mdx +0 -234
- package/site/content/docs/elements/ai.mdx +0 -385
- package/site/content/docs/elements/channel.mdx +0 -346
- package/site/content/docs/elements/clock.mdx +0 -244
- package/site/content/docs/elements/flow.mdx +0 -420
- package/site/content/docs/elements/gate.mdx +0 -436
- package/site/content/docs/elements/signal.mdx +0 -380
- package/site/content/docs/elements/store.mdx +0 -1099
- package/site/content/docs/elements/vault.mdx +0 -405
- package/site/content/docs/get-started/basic-usage.mdx +0 -173
- package/site/content/docs/get-started/index.mdx +0 -43
- package/site/content/docs/get-started/installation.mdx +0 -220
- package/site/content/docs/get-started/introduction.mdx +0 -132
- package/site/content/docs/get-started/meta.json +0 -13
- package/site/content/docs/get-started/project-structure.mdx +0 -925
- package/site/content/docs/get-started/testing.mdx +0 -328
- package/site/content/docs/get-started/why.mdx +0 -162
- package/site/content/docs/recipes/llama-cpp.mdx +0 -151
- package/site/content/docs/recipes/ollama.mdx +0 -142
- package/site/content/docs/recipes/sglang.mdx +0 -105
- package/site/content/docs/recipes/vllm.mdx +0 -106
- package/site/content/docs/reference/cli.md +0 -232
- package/site/content/docs/reference/client.mdx +0 -469
- package/site/content/docs/reference/security.md +0 -74
- package/src/cli/ai-setup/detect-ollama.ts +0 -213
- package/src/cli/ai-setup/recommend.test.ts +0 -225
- package/src/cli/ai-setup/recommend.ts +0 -225
- package/src/cli/dev-controls.test.ts +0 -122
- package/src/cli/dev-controls.ts +0 -164
- package/src/cli/tui/DevLive.tsx +0 -126
- package/src/console/ui-next/dist/assets/access-page-De7Lc2JC.js +0 -4
- package/src/console/ui-next/dist/assets/agent-disclosure-BP0Y0Sux.js +0 -1
- package/src/console/ui-next/dist/assets/cache-glyph-B5X-NM0-.js +0 -1
- package/src/console/ui-next/dist/assets/call-pii-button-ChAUiLo9.js +0 -1
- package/src/console/ui-next/dist/assets/collapsible-DGnOM2ph.js +0 -1
- package/src/console/ui-next/dist/assets/copy-inline-button-DBHhgHKP.js +0 -1
- package/src/console/ui-next/dist/assets/dagre.esm-ZwcdTuZZ.js +0 -1
- package/src/console/ui-next/dist/assets/detail-header-DhHM1iaZ.js +0 -1
- package/src/console/ui-next/dist/assets/dropdown-menu-_NjTEo5_.js +0 -1
- package/src/console/ui-next/dist/assets/duration-tone-sC3lGABz.js +0 -9
- package/src/console/ui-next/dist/assets/element-icons-BVXtRyd3.js +0 -1
- package/src/console/ui-next/dist/assets/explorer-empty-2uIhBu0_.js +0 -1
- package/src/console/ui-next/dist/assets/flows-page-RGy7VEA_.js +0 -1
- package/src/console/ui-next/dist/assets/highlighted-json-Awq7gYdu.js +0 -154
- package/src/console/ui-next/dist/assets/http-method-_UHM2ODJ.js +0 -1
- package/src/console/ui-next/dist/assets/index-Ck88Jmv8.css +0 -2
- package/src/console/ui-next/dist/assets/index-_rgpdVzo.js +0 -66
- package/src/console/ui-next/dist/assets/link-BX6Vqztd.js +0 -1
- package/src/console/ui-next/dist/assets/observability-page-Ds6pcnh-.js +0 -4
- package/src/console/ui-next/dist/assets/preload-helper-oH4irX4C.js +0 -1
- package/src/console/ui-next/dist/assets/react-D8E3mtu1.js +0 -1
- package/src/console/ui-next/dist/assets/react-dom-Bph1y7z7.js +0 -9
- package/src/console/ui-next/dist/assets/replica-lag-DKRrbvdo.js +0 -18
- package/src/console/ui-next/dist/assets/request-meta-DV0ywz7t.js +0 -1
- package/src/console/ui-next/dist/assets/shortcut-JQIZlWfm.js +0 -1
- package/src/console/ui-next/dist/assets/shortcut-keys-DKxNTe_m.js +0 -1
- package/src/console/ui-next/dist/assets/skeleton-D-czQJT6.js +0 -1
- package/src/console/ui-next/dist/assets/store-page-02xOiqIK.js +0 -41
- package/src/console/ui-next/dist/assets/trace-detail-sheet-B09O8rA6.js +0 -2
- package/src/console/ui-next/dist/assets/tree-expand-toggle-BtyhmWb4.js +0 -55
- package/src/console/ui-next/dist/assets/units-page-4rHOePuE.js +0 -1
- package/src/console/ui-next/dist/assets/useMutation-B8EO02Ej.js +0 -1
- package/src/console/ui-next/dist/assets/useRender-BE2A9BWC.js +0 -1
- package/src/console/ui-next/dist/assets/vault-page-DISPgxLM.js +0 -2
- package/src/console/ui-next/dist/assets/xyflow-D7n4g6go.js +0 -7
- package/src/console/ui-next/dist/assets/xyflow-DZ0Ws1xk.css +0 -1
- package/src/docker/ollama-pull.ts +0 -232
- package/src/docker/recipes/llama-cpp.ts +0 -298
- package/src/docker/recipes/ollama.ts +0 -44
- package/src/docker/recipes/sglang.ts +0 -55
- package/src/docker/recipes/vllm.ts +0 -44
- package/src/drivers/ai-ollama-tools.integration.test.ts +0 -109
- package/src/drivers/ai-ollama.integration.test.ts +0 -184
- package/src/drivers/ai-ollama.ts +0 -389
- package/src/drivers/ollama.ts +0 -14
|
@@ -4,11 +4,17 @@
|
|
|
4
4
|
|
|
5
5
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { dirname, join } from "node:path";
|
|
7
|
-
import {
|
|
7
|
+
import { getAiProviderEntry } from "../../elements/ai/providers.ts";
|
|
8
|
+
import { CLOUD_PROVIDERS } from "./catalog.ts";
|
|
8
9
|
|
|
9
10
|
/** Choices applied to the project. */
|
|
10
11
|
export type AiSetupApplyInput = {
|
|
11
|
-
readonly driver: "
|
|
12
|
+
readonly driver: "anthropic" | "openai-compatible" | "mock";
|
|
13
|
+
/**
|
|
14
|
+
* Name written to `ai.model({ provider })` — registry id (`openrouter`,
|
|
15
|
+
* `openai`, …), or `openai-compatible` / `local` for self-hosted.
|
|
16
|
+
*/
|
|
17
|
+
readonly provider?: string;
|
|
12
18
|
readonly baseUrl?: string;
|
|
13
19
|
readonly chatModel?: string;
|
|
14
20
|
readonly visionModel?: string | null;
|
|
@@ -16,7 +22,7 @@ export type AiSetupApplyInput = {
|
|
|
16
22
|
readonly apiKeyEnv?: string;
|
|
17
23
|
/** When set with {@link apiKeyEnv}, writes the token into `.env.local`. */
|
|
18
24
|
readonly apiKey?: string;
|
|
19
|
-
/** Optional `images.ai` pin (
|
|
25
|
+
/** Optional `images.ai` pin (legacy; cloud / custom / lmstudio leave unset). */
|
|
20
26
|
readonly image?: string;
|
|
21
27
|
};
|
|
22
28
|
|
|
@@ -56,8 +62,9 @@ export function applyAiSetup(
|
|
|
56
62
|
config = upsertAiDrivers(config, input.driver);
|
|
57
63
|
if (input.image) {
|
|
58
64
|
config = upsertImage(config, "ai", input.image);
|
|
59
|
-
} else
|
|
60
|
-
|
|
65
|
+
} else {
|
|
66
|
+
// Cloud / host-side providers must not leave a leftover `images.ai` pin.
|
|
67
|
+
config = removeImage(config, "ai");
|
|
61
68
|
}
|
|
62
69
|
writeFileSync(configPath, config, "utf8");
|
|
63
70
|
}
|
|
@@ -92,6 +99,9 @@ export function applyAiSetup(
|
|
|
92
99
|
writeFileSync(envPath, env.endsWith("\n") ? env : `${env}\n`, "utf8");
|
|
93
100
|
|
|
94
101
|
const aiTsPath = writeAiModels(cwd, input);
|
|
102
|
+
if (input.apiKeyEnv) {
|
|
103
|
+
ensureAiApiKeyVaultSecret(cwd, input.apiKeyEnv);
|
|
104
|
+
}
|
|
95
105
|
|
|
96
106
|
return { configPath, envPath, aiTsPath };
|
|
97
107
|
}
|
|
@@ -143,6 +153,19 @@ export function upsertImage(source: string, key: string, image: string): string
|
|
|
143
153
|
return source.replace(imagesRe, `images: {${body}\n${line}\n }`);
|
|
144
154
|
}
|
|
145
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Drop one flat image role pin (e.g. clear `images.ai` for cloud AI).
|
|
158
|
+
*
|
|
159
|
+
* @param source - Config source
|
|
160
|
+
* @param key - Image role (`ai`, `pgdog`, … — not nested `store.*`)
|
|
161
|
+
*/
|
|
162
|
+
export function removeImage(source: string, key: string): string {
|
|
163
|
+
const keyLit = key.includes(".") ? `"${key}"` : key;
|
|
164
|
+
const lineRe = new RegExp(`\\n[ \\t]*${keyLit}\\s*:\\s*"[^"]*",?`);
|
|
165
|
+
if (!lineRe.test(source)) return source;
|
|
166
|
+
return source.replace(lineRe, "");
|
|
167
|
+
}
|
|
168
|
+
|
|
146
169
|
/** Options for {@link upsertEnv}. */
|
|
147
170
|
export type UpsertEnvOptions = {
|
|
148
171
|
/**
|
|
@@ -181,34 +204,40 @@ export function upsertEnv(
|
|
|
181
204
|
*/
|
|
182
205
|
export function renderAiTs(input: AiSetupApplyInput): string {
|
|
183
206
|
const chat = input.chatModel ?? "default";
|
|
184
|
-
const provider =
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
: input.driver === "mock"
|
|
190
|
-
? "mock"
|
|
191
|
-
: "openai-compatible";
|
|
207
|
+
const provider = resolveDeclProvider(input);
|
|
208
|
+
const apiKeyEnv = input.apiKeyEnv;
|
|
209
|
+
const registryCloud = isRegistryCloudProvider(provider);
|
|
210
|
+
const nativeAnthropic = input.driver === "anthropic";
|
|
211
|
+
const localPrimary = isSelfHostedLocal(input);
|
|
192
212
|
|
|
193
|
-
const
|
|
194
|
-
`import { ai } from "okengine";`,
|
|
195
|
-
``,
|
|
196
|
-
`/** Cloud OpenAI-compatible binding (OpenAI / Groq / OpenRouter / …). */`,
|
|
213
|
+
const smartLines = [
|
|
197
214
|
`export const smart = ai.model("smart", {`,
|
|
198
215
|
` provider: "${provider}",`,
|
|
216
|
+
...(nativeAnthropic ? [` driverId: "anthropic",`] : []),
|
|
199
217
|
` model: process.env.OKE_AI_CLOUD_MODEL ?? process.env.OKE_AI_MODEL ?? "${chat}",`,
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
` ? { apiKey: process.env.OPENAI_API_KEY.trim() }`,
|
|
203
|
-
` : {}),`,
|
|
218
|
+
...smartBaseUrlLines(input, { registryCloud, localPrimary }),
|
|
219
|
+
...apiKeySpreadLines(apiKeyEnv),
|
|
204
220
|
`});`,
|
|
205
|
-
|
|
206
|
-
|
|
221
|
+
];
|
|
222
|
+
|
|
223
|
+
const localProvider = "openai-compatible";
|
|
224
|
+
const localDefaultModel = localPrimary ? chat : "local-model";
|
|
225
|
+
const localLines = [
|
|
207
226
|
`export const local = ai.model("local", {`,
|
|
208
|
-
` provider: "${
|
|
209
|
-
` model: process.env.OKE_AI_LOCAL_MODEL ?? "${
|
|
227
|
+
` provider: "${localProvider}",`,
|
|
228
|
+
` model: process.env.OKE_AI_LOCAL_MODEL ?? "${localDefaultModel}",`,
|
|
210
229
|
` ...(process.env.OKE_AI_URL?.trim() ? { baseUrl: process.env.OKE_AI_URL.trim() } : {}),`,
|
|
211
230
|
`});`,
|
|
231
|
+
];
|
|
232
|
+
|
|
233
|
+
const lines = [
|
|
234
|
+
`import { ai } from "okengine";`,
|
|
235
|
+
``,
|
|
236
|
+
`/** Primary model binding (${provider}). */`,
|
|
237
|
+
...smartLines,
|
|
238
|
+
``,
|
|
239
|
+
`/** Local OpenAI-compatible binding (via \`OKE_AI_URL\`). */`,
|
|
240
|
+
...localLines,
|
|
212
241
|
``,
|
|
213
242
|
`/** Advanced Notes summarize — used by \`notes.summarize\` via \`fx.ask\`. */`,
|
|
214
243
|
`export const summarizeNote = smart.prompt("summarize-note", {`,
|
|
@@ -222,7 +251,9 @@ export function renderAiTs(input: AiSetupApplyInput): string {
|
|
|
222
251
|
``,
|
|
223
252
|
`export const vision = ai.model("vision", {`,
|
|
224
253
|
` provider: "${provider}",`,
|
|
254
|
+
...(nativeAnthropic ? [` driverId: "anthropic",`] : []),
|
|
225
255
|
` model: process.env.OKE_AI_VISION_MODEL ?? "${input.visionModel}",`,
|
|
256
|
+
...apiKeySpreadLines(apiKeyEnv),
|
|
226
257
|
`});`,
|
|
227
258
|
);
|
|
228
259
|
}
|
|
@@ -233,6 +264,7 @@ export function renderAiTs(input: AiSetupApplyInput): string {
|
|
|
233
264
|
`export const embedModel = ai.model("embed", {`,
|
|
234
265
|
` provider: "${provider}",`,
|
|
235
266
|
` model: process.env.OKE_AI_EMBED_MODEL ?? "${input.embedModel}",`,
|
|
267
|
+
...apiKeySpreadLines(apiKeyEnv),
|
|
236
268
|
`});`,
|
|
237
269
|
``,
|
|
238
270
|
`export const docsEmbed = ai.embed("docs", { model: embedModel });`,
|
|
@@ -243,6 +275,163 @@ export function renderAiTs(input: AiSetupApplyInput): string {
|
|
|
243
275
|
return `${lines.join("\n")}\n`;
|
|
244
276
|
}
|
|
245
277
|
|
|
278
|
+
/**
|
|
279
|
+
* Provider string for generated `ai.model` declarations.
|
|
280
|
+
*
|
|
281
|
+
* @param input - Setup choices
|
|
282
|
+
*/
|
|
283
|
+
export function resolveDeclProvider(input: AiSetupApplyInput): string {
|
|
284
|
+
if (input.provider !== undefined && input.provider.length > 0) return input.provider;
|
|
285
|
+
if (input.driver === "anthropic") return "anthropic";
|
|
286
|
+
if (input.driver === "mock") return "mock";
|
|
287
|
+
return "openai-compatible";
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function isRegistryCloudProvider(provider: string): boolean {
|
|
291
|
+
return getAiProviderEntry(provider) !== undefined;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function isSelfHostedLocal(input: AiSetupApplyInput): boolean {
|
|
295
|
+
return input.image !== undefined;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function smartBaseUrlLines(
|
|
299
|
+
input: AiSetupApplyInput,
|
|
300
|
+
flags: { readonly registryCloud: boolean; readonly localPrimary: boolean },
|
|
301
|
+
): string[] {
|
|
302
|
+
if (input.driver === "anthropic") {
|
|
303
|
+
return [];
|
|
304
|
+
}
|
|
305
|
+
if (flags.registryCloud) {
|
|
306
|
+
// Registry auto-resolves; optional env override for proxies/mirrors.
|
|
307
|
+
return [
|
|
308
|
+
` ...(process.env.OPENAI_BASE_URL?.trim() ? { baseUrl: process.env.OPENAI_BASE_URL.trim() } : {}),`,
|
|
309
|
+
];
|
|
310
|
+
}
|
|
311
|
+
if (flags.localPrimary) {
|
|
312
|
+
return [
|
|
313
|
+
` ...(process.env.OKE_AI_URL?.trim() ? { baseUrl: process.env.OKE_AI_URL.trim() } : {}),`,
|
|
314
|
+
];
|
|
315
|
+
}
|
|
316
|
+
// custom / lmstudio — prefer OPENAI_BASE_URL, fall back to setup-time URL when present
|
|
317
|
+
if (input.baseUrl) {
|
|
318
|
+
return [` baseUrl: process.env.OPENAI_BASE_URL?.trim() || ${JSON.stringify(input.baseUrl)},`];
|
|
319
|
+
}
|
|
320
|
+
return [
|
|
321
|
+
` ...(process.env.OPENAI_BASE_URL?.trim() ? { baseUrl: process.env.OPENAI_BASE_URL.trim() } : {}),`,
|
|
322
|
+
];
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function apiKeySpreadLines(apiKeyEnv: string | undefined): string[] {
|
|
326
|
+
if (!apiKeyEnv) return [];
|
|
327
|
+
return [
|
|
328
|
+
` ...(process.env.${apiKeyEnv}?.trim()`,
|
|
329
|
+
` ? { apiKey: process.env.${apiKeyEnv}.trim() }`,
|
|
330
|
+
` : {}),`,
|
|
331
|
+
];
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* `OPENROUTER_API_KEY` → `openrouterApiKey`.
|
|
336
|
+
*
|
|
337
|
+
* @param envName - Env / vault contract name
|
|
338
|
+
*/
|
|
339
|
+
export function envNameToCamelBinding(envName: string): string {
|
|
340
|
+
const parts = envName
|
|
341
|
+
.toLowerCase()
|
|
342
|
+
.split(/_+/g)
|
|
343
|
+
.filter((p) => p.length > 0);
|
|
344
|
+
if (parts.length === 0) return "apiKey";
|
|
345
|
+
return parts
|
|
346
|
+
.map((part, i) => (i === 0 ? part : `${part[0]!.toUpperCase()}${part.slice(1)}`))
|
|
347
|
+
.join("");
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Human description for a provider API key env.
|
|
352
|
+
*
|
|
353
|
+
* @param envName - Env / vault contract name
|
|
354
|
+
*/
|
|
355
|
+
export function apiKeyEnvDescription(envName: string): string {
|
|
356
|
+
const meta = CLOUD_PROVIDERS.find((p) => p.apiKeyEnv === envName);
|
|
357
|
+
if (meta) return `${meta.label} API key`;
|
|
358
|
+
const stem = envName.replace(/_API_KEY$/i, "").replace(/_/g, " ");
|
|
359
|
+
return `${stem} API key`;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Render a `vault.secret` block for an AI provider key (no `dev:` stub so
|
|
364
|
+
* missing values become Vault boot gaps on `oke dev`).
|
|
365
|
+
*
|
|
366
|
+
* @param apiKeyEnv - Env / contract name
|
|
367
|
+
*/
|
|
368
|
+
export function renderAiApiKeyVaultSecret(apiKeyEnv: string): string {
|
|
369
|
+
const binding = envNameToCamelBinding(apiKeyEnv);
|
|
370
|
+
const description = apiKeyEnvDescription(apiKeyEnv);
|
|
371
|
+
return `/** ${description} — no \`dev:\` stub so first \`oke dev\` asks via Vault gaps. */
|
|
372
|
+
export const ${binding} = vault.secret(${JSON.stringify(apiKeyEnv)}, {
|
|
373
|
+
description: ${JSON.stringify(description)},
|
|
374
|
+
rotate: "90d",
|
|
375
|
+
});
|
|
376
|
+
`;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* True when `source` already declares `vault.secret("ENV")` (or `vault("ENV")`).
|
|
381
|
+
*
|
|
382
|
+
* @param source - TypeScript source
|
|
383
|
+
* @param apiKeyEnv - Contract name
|
|
384
|
+
*/
|
|
385
|
+
export function hasAiApiKeyVaultSecret(source: string, apiKeyEnv: string): boolean {
|
|
386
|
+
const lit = apiKeyEnv.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
387
|
+
return new RegExp(`\\bvault(?:\\.secret)?\\s*\\(\\s*["']${lit}["']`).test(source);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Merge a vault.secret contract for the AI API key into core / vault sources.
|
|
392
|
+
*
|
|
393
|
+
* @param existing - Current module source
|
|
394
|
+
* @param apiKeyEnv - Env / contract name
|
|
395
|
+
*/
|
|
396
|
+
export function mergeAiApiKeyVaultSecret(existing: string, apiKeyEnv: string): string {
|
|
397
|
+
if (hasAiApiKeyVaultSecret(existing, apiKeyEnv)) return existing;
|
|
398
|
+
let next = ensureNamedOkengineImport(existing, "vault");
|
|
399
|
+
const block = renderAiApiKeyVaultSecret(apiKeyEnv);
|
|
400
|
+
const vaultHeading = /(\/\/ --- Vault[^\n]*\n)/;
|
|
401
|
+
if (vaultHeading.test(next)) {
|
|
402
|
+
return next.replace(vaultHeading, `$1\n${block}`);
|
|
403
|
+
}
|
|
404
|
+
const aiHeading = /(\/\/ --- AI[^\n]*\n)/;
|
|
405
|
+
if (aiHeading.test(next)) {
|
|
406
|
+
return next.replace(aiHeading, `${block}\n$1`);
|
|
407
|
+
}
|
|
408
|
+
return `${next.trimEnd()}\n\n${block}`;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Declare `vault.secret(apiKeyEnv)` in the project so missing keys surface as
|
|
413
|
+
* Vault gaps (and Console Vault) — never silently optional.
|
|
414
|
+
*
|
|
415
|
+
* Prefers `src/core/vault.ts` when present, else merges into `src/core.ts`.
|
|
416
|
+
*
|
|
417
|
+
* @param cwd - Project root
|
|
418
|
+
* @param apiKeyEnv - Env / contract name
|
|
419
|
+
*/
|
|
420
|
+
export function ensureAiApiKeyVaultSecret(cwd: string, apiKeyEnv: string): void {
|
|
421
|
+
const coreVaultPath = join(cwd, "src", "core", "vault.ts");
|
|
422
|
+
if (existsSync(coreVaultPath)) {
|
|
423
|
+
const prev = readFileSync(coreVaultPath, "utf8");
|
|
424
|
+
const next = mergeAiApiKeyVaultSecret(prev, apiKeyEnv);
|
|
425
|
+
if (next !== prev) writeFileSync(coreVaultPath, next, "utf8");
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
const coreTsPath = join(cwd, "src", "core.ts");
|
|
429
|
+
if (!existsSync(coreTsPath)) return;
|
|
430
|
+
const prev = readFileSync(coreTsPath, "utf8");
|
|
431
|
+
const next = mergeAiApiKeyVaultSecret(prev, apiKeyEnv);
|
|
432
|
+
if (next !== prev) writeFileSync(coreTsPath, next, "utf8");
|
|
433
|
+
}
|
|
434
|
+
|
|
246
435
|
/**
|
|
247
436
|
* Write AI model declarations into `src/core/ai.ts` when that split exists
|
|
248
437
|
* (so a thin `src/core.ts` barrel stays a re-export), else `src/core.ts`,
|
|
@@ -260,14 +449,7 @@ function writeAiModels(cwd: string, input: AiSetupApplyInput): string {
|
|
|
260
449
|
|
|
261
450
|
if (existsSync(coreAiPath)) {
|
|
262
451
|
const existing = readFileSync(coreAiPath, "utf8");
|
|
263
|
-
|
|
264
|
-
const withPrompt = ensureSummarizeNotePrompt(existing);
|
|
265
|
-
if (withPrompt !== existing) {
|
|
266
|
-
writeFileSync(coreAiPath, withPrompt, "utf8");
|
|
267
|
-
}
|
|
268
|
-
} else {
|
|
269
|
-
writeFileSync(coreAiPath, mergeAiIntoCore(existing, rendered), "utf8");
|
|
270
|
-
}
|
|
452
|
+
writeFileSync(coreAiPath, resolveAiCoreSource(existing, rendered), "utf8");
|
|
271
453
|
ensureCoreBarrelExportsAi(cwd);
|
|
272
454
|
ensureCoreImported(cwd);
|
|
273
455
|
return coreAiPath;
|
|
@@ -285,14 +467,7 @@ function writeAiModels(cwd: string, input: AiSetupApplyInput): string {
|
|
|
285
467
|
mkdirSync(dirname(coreTsPath), { recursive: true });
|
|
286
468
|
if (existsSync(coreTsPath)) {
|
|
287
469
|
const existing = readFileSync(coreTsPath, "utf8");
|
|
288
|
-
|
|
289
|
-
const withPrompt = ensureSummarizeNotePrompt(existing);
|
|
290
|
-
if (withPrompt !== existing) {
|
|
291
|
-
writeFileSync(coreTsPath, withPrompt, "utf8");
|
|
292
|
-
}
|
|
293
|
-
return coreTsPath;
|
|
294
|
-
}
|
|
295
|
-
writeFileSync(coreTsPath, mergeAiIntoCore(existing, rendered), "utf8");
|
|
470
|
+
writeFileSync(coreTsPath, resolveAiCoreSource(existing, rendered), "utf8");
|
|
296
471
|
} else {
|
|
297
472
|
writeFileSync(coreTsPath, rendered, "utf8");
|
|
298
473
|
}
|
|
@@ -300,17 +475,82 @@ function writeAiModels(cwd: string, input: AiSetupApplyInput): string {
|
|
|
300
475
|
return coreTsPath;
|
|
301
476
|
}
|
|
302
477
|
|
|
478
|
+
/**
|
|
479
|
+
* Decide whether to merge a full AI module, repair a broken stub, or only
|
|
480
|
+
* backfill `local` / `summarizeNote` on an already-complete core.
|
|
481
|
+
*
|
|
482
|
+
* @param existing - Current core / AI sidecar source
|
|
483
|
+
* @param rendered - Output of {@link renderAiTs}
|
|
484
|
+
*/
|
|
485
|
+
export function resolveAiCoreSource(existing: string, rendered: string): string {
|
|
486
|
+
if (isIncompleteAiSetup(existing)) {
|
|
487
|
+
return mergeAiIntoCore(stripIncompleteAiExports(existing), rendered);
|
|
488
|
+
}
|
|
489
|
+
if (hasAiModels(existing)) {
|
|
490
|
+
return ensureSummarizeNotePrompt(existing);
|
|
491
|
+
}
|
|
492
|
+
return mergeAiIntoCore(existing, rendered);
|
|
493
|
+
}
|
|
494
|
+
|
|
303
495
|
/**
|
|
304
496
|
* @param source - Existing TypeScript
|
|
305
497
|
*/
|
|
306
498
|
function hasAiModels(source: string): boolean {
|
|
499
|
+
// Require real exports — template comments like `// ai.model("smart", …)`
|
|
500
|
+
// must not look like an already-configured core.
|
|
307
501
|
return (
|
|
308
|
-
/\
|
|
502
|
+
/\bexport\s+const\s+(?:smart|local|vision|embedModel)\s*=\s*ai\.model\s*\(/.test(source) ||
|
|
309
503
|
/from\s+["']\.\/(?:core\/)?ai["']/.test(source) ||
|
|
310
504
|
/import\s+["']\.\/(?:core\/)?ai["']/.test(source)
|
|
311
505
|
);
|
|
312
506
|
}
|
|
313
507
|
|
|
508
|
+
/**
|
|
509
|
+
* True when prior AI setup left unusable stubs (e.g. `local` + `summarizeNote`
|
|
510
|
+
* without `smart` / without an `ai` import — the old comment-as-configured bug).
|
|
511
|
+
*
|
|
512
|
+
* @param source - Existing TypeScript
|
|
513
|
+
*/
|
|
514
|
+
export function isIncompleteAiSetup(source: string): boolean {
|
|
515
|
+
const hasAiImport = /import\s*\{[^}]*\bai\b[^}]*\}\s*from\s*["']okengine["']/.test(source);
|
|
516
|
+
const hasSmart = /\bexport\s+const\s+smart\s*=\s*ai\.model\s*\(/.test(source);
|
|
517
|
+
const hasLocal = /\bexport\s+const\s+local\s*=\s*ai\.model\s*\(/.test(source);
|
|
518
|
+
const hasSummarize = /\bexport\s+const\s+summarizeNote\s*=/.test(source);
|
|
519
|
+
const hasAnyModel =
|
|
520
|
+
/\bexport\s+const\s+(?:smart|local|vision|embedModel)\s*=\s*ai\.model\s*\(/.test(source);
|
|
521
|
+
if (hasAnyModel && !hasAiImport) return true;
|
|
522
|
+
if ((hasLocal || hasSummarize) && !hasSmart) return true;
|
|
523
|
+
return false;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Remove partial AI exports so {@link mergeAiIntoCore} can rewrite a full set.
|
|
528
|
+
*
|
|
529
|
+
* @param source - Existing TypeScript
|
|
530
|
+
*/
|
|
531
|
+
export function stripIncompleteAiExports(source: string): string {
|
|
532
|
+
let next = source;
|
|
533
|
+
next = next.replace(
|
|
534
|
+
/(?:\/\*\*[^*]*\*+(?:[^/*][^*]*\*+)*\/\s*)?export\s+const\s+local\s*=\s*ai\.model\s*\(\s*["']local["']\s*,\s*\{[\s\S]*?\}\s*\)\s*;\s*/g,
|
|
535
|
+
"",
|
|
536
|
+
);
|
|
537
|
+
next = next.replace(
|
|
538
|
+
/(?:\/\*\*[^*]*\*+(?:[^/*][^*]*\*+)*\/\s*)?export\s+const\s+summarizeNote\s*=\s*smart\.prompt\s*\([\s\S]*?\}\s*\)\s*;\s*/g,
|
|
539
|
+
"",
|
|
540
|
+
);
|
|
541
|
+
if (!/\bexport\s+const\s+smart\s*=\s*ai\.model\s*\(/.test(next)) {
|
|
542
|
+
next = next.replace(
|
|
543
|
+
/(?:\/\*\*[^*]*\*+(?:[^/*][^*]*\*+)*\/\s*)?export\s+const\s+(?:vision|embedModel)\s*=\s*ai\.model\s*\([\s\S]*?\}\s*\)\s*;\s*/g,
|
|
544
|
+
"",
|
|
545
|
+
);
|
|
546
|
+
next = next.replace(
|
|
547
|
+
/(?:\/\*\*[^*]*\*+(?:[^/*][^*]*\*+)*\/\s*)?export\s+const\s+docsEmbed\s*=\s*ai\.embed\s*\([\s\S]*?\}\s*\)\s*;\s*/g,
|
|
548
|
+
"",
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
return next.replace(/\n{3,}/g, "\n\n");
|
|
552
|
+
}
|
|
553
|
+
|
|
314
554
|
/**
|
|
315
555
|
* Append the advanced Notes `summarize-note` prompt when a `smart` model
|
|
316
556
|
* exists but the prompt was never declared (common after older `--ai` runs).
|
|
@@ -319,24 +559,26 @@ function hasAiModels(source: string): boolean {
|
|
|
319
559
|
*/
|
|
320
560
|
export function ensureSummarizeNotePrompt(source: string): string {
|
|
321
561
|
let next = source;
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
) {
|
|
562
|
+
const hasSmartExport = /\bexport\s+const\s+smart\s*=/.test(next);
|
|
563
|
+
const hasLocalExport = /\bexport\s+const\s+local\s*=/.test(next);
|
|
564
|
+
if (!hasLocalExport && hasSmartExport) {
|
|
326
565
|
next = `${next.trimEnd()}
|
|
327
566
|
|
|
328
|
-
/** Local
|
|
567
|
+
/** Local OpenAI-compatible binding (via \`OKE_AI_URL\`). */
|
|
329
568
|
export const local = ai.model("local", {
|
|
330
569
|
provider: "openai-compatible",
|
|
331
|
-
model: process.env.OKE_AI_LOCAL_MODEL ?? "
|
|
570
|
+
model: process.env.OKE_AI_LOCAL_MODEL ?? "local-model",
|
|
332
571
|
...(process.env.OKE_AI_URL?.trim() ? { baseUrl: process.env.OKE_AI_URL.trim() } : {}),
|
|
333
572
|
});
|
|
334
573
|
`;
|
|
335
574
|
}
|
|
336
|
-
|
|
337
|
-
|
|
575
|
+
const hasSummarizeExport =
|
|
576
|
+
/\bexport\s+const\s+summarizeNote\s*=/.test(next) ||
|
|
577
|
+
/\.prompt\s*\(\s*["']summarize-note["']/.test(next);
|
|
578
|
+
if (hasSummarizeExport) {
|
|
579
|
+
return next === source ? next : ensureNamedOkengineImport(next, "ai");
|
|
338
580
|
}
|
|
339
|
-
if (
|
|
581
|
+
if (!hasSmartExport) {
|
|
340
582
|
return next;
|
|
341
583
|
}
|
|
342
584
|
const prompt = `
|
|
@@ -346,7 +588,7 @@ export const summarizeNote = smart.prompt("summarize-note", {
|
|
|
346
588
|
timeout: "30s",
|
|
347
589
|
});
|
|
348
590
|
`;
|
|
349
|
-
return `${next.trimEnd()}\n${prompt}\n
|
|
591
|
+
return ensureNamedOkengineImport(`${next.trimEnd()}\n${prompt}\n`, "ai");
|
|
350
592
|
}
|
|
351
593
|
|
|
352
594
|
/**
|