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
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "MCP"
|
|
3
|
+
description: "Two directions — expose Flows as gated mcp.tool endpoints on :6535, and consume external servers with ai.mcpServer allowlists."
|
|
4
|
+
icon: "Plug"
|
|
5
|
+
source: "docs/spec/unified-theory.md"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Model Context Protocol (MCP) connects OKE to Cursor, Claude Desktop, and other agents in
|
|
9
|
+
**two directions**: your app exposes selected Flows as tools, and your Flows call tools on
|
|
10
|
+
external MCP servers.
|
|
11
|
+
|
|
12
|
+
For developers wiring Cursor to a backend or letting an agent open a GitHub issue — opt-in
|
|
13
|
+
gates inbound; allowlists outbound.
|
|
14
|
+
|
|
15
|
+
<Callout title="The one rule">
|
|
16
|
+
Inbound: `on(mcp.tool("name").gate(...), flow)` — ungated tools are not exposed. Outbound:
|
|
17
|
+
`ai.mcpServer` with a required `tools` allowlist — the runtime never trusts raw `tools/list`.
|
|
18
|
+
</Callout>
|
|
19
|
+
|
|
20
|
+
## Smallest Example — expose a Flow
|
|
21
|
+
|
|
22
|
+
<Steps>
|
|
23
|
+
|
|
24
|
+
<Step>
|
|
25
|
+
### Bind a gated MCP tool
|
|
26
|
+
|
|
27
|
+
```typescript title="src/flows/bookings/create.ts"
|
|
28
|
+
import { on, flow, mcp } from "okengine";
|
|
29
|
+
import { z } from "zod";
|
|
30
|
+
import { member } from "@/core/gate";
|
|
31
|
+
|
|
32
|
+
export const create = on(
|
|
33
|
+
mcp
|
|
34
|
+
.tool("bookings.create", {
|
|
35
|
+
in: z.object({
|
|
36
|
+
guest: z.string().min(1),
|
|
37
|
+
night: z.string(),
|
|
38
|
+
}),
|
|
39
|
+
out: z.object({ id: z.string(), guest: z.string(), night: z.string() }),
|
|
40
|
+
})
|
|
41
|
+
.gate(member),
|
|
42
|
+
flow({
|
|
43
|
+
do: async (input, fx) => {
|
|
44
|
+
return { id: fx.id(), ...input };
|
|
45
|
+
},
|
|
46
|
+
}),
|
|
47
|
+
);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Deny-by-default: `on(mcp.tool("…"), flow)` without `.gate(...)` fails gate posture at boot.
|
|
51
|
+
|
|
52
|
+
</Step>
|
|
53
|
+
|
|
54
|
+
<Step>
|
|
55
|
+
### Connect a client
|
|
56
|
+
|
|
57
|
+
App MCP listens on port **6535**, path **`/mcp`** (not the backend `:6530` HTTP port). Bearer
|
|
58
|
+
auth is required.
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"mcpServers": {
|
|
63
|
+
"notes": {
|
|
64
|
+
"url": "http://127.0.0.1:6535/mcp",
|
|
65
|
+
"headers": {
|
|
66
|
+
"Authorization": "Bearer <token>"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`GET /health` on the same port probes liveness. Override with `ports.mcp` in config when needed.
|
|
74
|
+
|
|
75
|
+
</Step>
|
|
76
|
+
|
|
77
|
+
<Step>
|
|
78
|
+
### Call the tool
|
|
79
|
+
|
|
80
|
+
The client lists `bookings.create` (and other gated tools). Invocations run the Flow under the
|
|
81
|
+
same gate chain as HTTP.
|
|
82
|
+
|
|
83
|
+
</Step>
|
|
84
|
+
|
|
85
|
+
</Steps>
|
|
86
|
+
|
|
87
|
+
## Smallest Example — consume a server
|
|
88
|
+
|
|
89
|
+
<Steps>
|
|
90
|
+
|
|
91
|
+
<Step>
|
|
92
|
+
### Declare an outbound server
|
|
93
|
+
|
|
94
|
+
```typescript title="src/core/mcp.ts"
|
|
95
|
+
import { ai, vault } from "okengine";
|
|
96
|
+
|
|
97
|
+
const githubToken = vault.secret("GITHUB_MCP_TOKEN");
|
|
98
|
+
|
|
99
|
+
export const github = ai.mcpServer("github", {
|
|
100
|
+
url: "https://mcp.example/github",
|
|
101
|
+
auth: { bearer: githubToken },
|
|
102
|
+
tools: ["create_issue", "list_repos"],
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
export const createIssue = github.tool("create_issue"); // mcp:github/create_issue
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Exactly one of `url` (Streamable HTTP) or `command` (+ optional `args` for stdio). Bearer must
|
|
109
|
+
be a `vault.secret` handle or contract name — never a token literal in source.
|
|
110
|
+
|
|
111
|
+
</Step>
|
|
112
|
+
|
|
113
|
+
<Step>
|
|
114
|
+
### Use in ask / agent tools
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
await fx.ask(triage, input, {
|
|
118
|
+
tools: [github.tool("create_issue")],
|
|
119
|
+
maxSteps: 2,
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Capability ref is `mcp:github/create_issue`. Model-facing names use `server__tool`
|
|
124
|
+
(`github__create_issue`).
|
|
125
|
+
|
|
126
|
+
</Step>
|
|
127
|
+
|
|
128
|
+
</Steps>
|
|
129
|
+
|
|
130
|
+
## Progressive Patterns
|
|
131
|
+
|
|
132
|
+
<Tabs items={["Inbound gate", "stdio server", "Agent bag", "Docs MCP"]}>
|
|
133
|
+
|
|
134
|
+
<Tab value="Inbound gate">
|
|
135
|
+
|
|
136
|
+
Chain policies like HTTP — first denial wins:
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
on(
|
|
140
|
+
mcp.tool("admin.wipe").gate(member, gate.scope("admin")),
|
|
141
|
+
flow({ do: async (_input, fx) => fx.json.empty() }),
|
|
142
|
+
);
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
</Tab>
|
|
146
|
+
|
|
147
|
+
<Tab value="stdio server">
|
|
148
|
+
|
|
149
|
+
Local executable transport:
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
export const localTools = ai.mcpServer("local", {
|
|
153
|
+
command: "npx",
|
|
154
|
+
args: ["-y", "some-mcp-server"],
|
|
155
|
+
tools: ["lookup"],
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
</Tab>
|
|
160
|
+
|
|
161
|
+
<Tab value="Agent bag">
|
|
162
|
+
|
|
163
|
+
Mix Flows and MCP refs on one agent:
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
ai.agent("planner", {
|
|
167
|
+
model: "smart",
|
|
168
|
+
tools: ["tasks.create", github.tool("create_issue")],
|
|
169
|
+
maxSteps: 8,
|
|
170
|
+
budget: { maxCostPerRun: 0.25 },
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
</Tab>
|
|
175
|
+
|
|
176
|
+
<Tab value="Docs MCP">
|
|
177
|
+
|
|
178
|
+
Read-only docs MCP is a **separate** process on port **6536** — not your app’s `:6535` tool
|
|
179
|
+
server. Use it for documentation search, not business Flows.
|
|
180
|
+
|
|
181
|
+
</Tab>
|
|
182
|
+
|
|
183
|
+
</Tabs>
|
|
184
|
+
|
|
185
|
+
## Inbound reference
|
|
186
|
+
|
|
187
|
+
| Piece | Detail |
|
|
188
|
+
| ------- | ------------------------------------------------------ |
|
|
189
|
+
| Trigger | `mcp.tool(name, { in, out, errors? })` from `okengine` |
|
|
190
|
+
| Gates | `.gate(...)` required for exposure |
|
|
191
|
+
| Port | **6535** (`ports.mcp`) |
|
|
192
|
+
| Path | `POST /mcp` · `GET /health` |
|
|
193
|
+
| Auth | Bearer required (`Bearer token required`) |
|
|
194
|
+
|
|
195
|
+
Empty name throws `TypeError: mcp.tool(name): name is required`.
|
|
196
|
+
|
|
197
|
+
## Outbound reference — `ai.mcpServer`
|
|
198
|
+
|
|
199
|
+
| Option | Type | Required | Meaning |
|
|
200
|
+
| ------------- | ------------- | ------------- | ---------------------------------- |
|
|
201
|
+
| `url` | `string` | XOR `command` | Streamable HTTP endpoint |
|
|
202
|
+
| `command` | `string` | XOR `url` | stdio executable (no shell string) |
|
|
203
|
+
| `args` | `string[]` | no | Arguments for `command` |
|
|
204
|
+
| `auth.bearer` | secret / name | no | Vault contract for Bearer |
|
|
205
|
+
| `tools` | `string[]` | **yes** | Allowlist — never raw `tools/list` |
|
|
206
|
+
|
|
207
|
+
| Method | Returns | Meaning |
|
|
208
|
+
| ------------------- | ----------------------------- | ------------------------------------------ |
|
|
209
|
+
| `server.tool(name)` | `{ name: "mcp:server/tool" }` | Capability ref for ask / agent / `fx.call` |
|
|
210
|
+
|
|
211
|
+
### Declare errors
|
|
212
|
+
|
|
213
|
+
| Message | Fix |
|
|
214
|
+
| --------------------------------------- | ------------------------------------------- |
|
|
215
|
+
| `ai.mcpServer: name is required` | Pass a non-empty server id |
|
|
216
|
+
| `name "…" must not contain "/" or "__"` | Use a simple id (`github`, not `org/repo`) |
|
|
217
|
+
| `tools allowlist is required` | Pass `tools: ["…"]` |
|
|
218
|
+
| `declare exactly one of url or command` | Pick HTTP **or** stdio |
|
|
219
|
+
| `tool "…" is not in the allowlist` | Add the name to `tools` before `.tool(...)` |
|
|
220
|
+
|
|
221
|
+
## Ports
|
|
222
|
+
|
|
223
|
+
| Port | Surface |
|
|
224
|
+
| -------- | ------------------------ |
|
|
225
|
+
| **6530** | Backend HTTP |
|
|
226
|
+
| **6535** | App MCP (Flows as tools) |
|
|
227
|
+
| **6536** | Docs MCP (read-only) |
|
|
228
|
+
|
|
229
|
+
Mnemonic: O·K·E = 6·5·3.
|
|
230
|
+
|
|
231
|
+
## Troubleshooting
|
|
232
|
+
|
|
233
|
+
<Accordions>
|
|
234
|
+
|
|
235
|
+
<Accordion title="Bearer token required">
|
|
236
|
+
Clients must send `Authorization: Bearer …`. Missing or invalid Bearer is rejected before tool
|
|
237
|
+
dispatch.
|
|
238
|
+
</Accordion>
|
|
239
|
+
|
|
240
|
+
<Accordion title="Tool missing from Cursor / client list">
|
|
241
|
+
The Flow is not bound with `mcp.tool(…).gate(…)`, gates deny the identity, or the client points at
|
|
242
|
+
`:6530` instead of `:6535/mcp`.
|
|
243
|
+
</Accordion>
|
|
244
|
+
|
|
245
|
+
<Accordion title="Ungated mcp.tool fails at boot">
|
|
246
|
+
Deny-by-default posture: attach at least one gate. Public-style exposure still needs an explicit
|
|
247
|
+
gate policy you intend (there is no `.public()` on MCP triggers).
|
|
248
|
+
</Accordion>
|
|
249
|
+
|
|
250
|
+
<Accordion title="ai.mcpServer allowlist / transport errors">
|
|
251
|
+
See the declare-error table above. Runtime `ai.mcp: …` covers unknown server, non-allowlisted
|
|
252
|
+
tool, and unsupported HITL prompts from the remote.
|
|
253
|
+
</Accordion>
|
|
254
|
+
|
|
255
|
+
</Accordions>
|
|
256
|
+
|
|
257
|
+
## Learn more
|
|
258
|
+
|
|
259
|
+
- [Agents](/docs/elements/ai/agents) — MCP refs in tool bags
|
|
260
|
+
- [Gate](/docs/elements/gate) — policies on `mcp.tool`
|
|
261
|
+
- [Vault](/docs/elements/vault) — bearer secret contracts
|
|
262
|
+
- [AI](/docs/elements/ai) — element overview
|
|
263
|
+
- [Security](/docs/reference/security) — ports 6530 · 6533 · 6535 · 6536
|
|
264
|
+
|
|
265
|
+
## Next
|
|
266
|
+
|
|
267
|
+
<Cards>
|
|
268
|
+
<Card
|
|
269
|
+
title="Agents"
|
|
270
|
+
description="Run bounded agents that call MCP tools."
|
|
271
|
+
href="/docs/elements/ai/agents"
|
|
272
|
+
/>
|
|
273
|
+
<Card title="AI" description="Models, prompts, and fx.ask." href="/docs/elements/ai" />
|
|
274
|
+
<Card title="Flow" description="Flows are the tools MCP exposes." href="/docs/elements/flow" />
|
|
275
|
+
</Cards>
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Models"
|
|
3
|
+
description: "Declare ai.model bindings — known providers auto-resolve baseUrl; Anthropic and Google OpenAI-compat have documented limits."
|
|
4
|
+
icon: "Cpu"
|
|
5
|
+
source: "docs/spec/unified-theory.md"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
An `ai.model` binding names a logical model (`smart`, `local`, …), the wire `model` id, and how
|
|
9
|
+
to reach it (`provider`, optional `baseUrl` / `apiKey` / `driverId`).
|
|
10
|
+
|
|
11
|
+
For developers swapping OpenRouter for a self-hosted OpenAI-compatible `/v1` — one logical
|
|
12
|
+
name, different bindings per environment.
|
|
13
|
+
|
|
14
|
+
<Callout title="The one rule">
|
|
15
|
+
Known OpenAI-compatible `provider` names resolve `baseUrl` automatically. Explicit `baseUrl`
|
|
16
|
+
always wins. Unknown providers require `baseUrl` — they fail loud. Per-binding `apiKey` isolates
|
|
17
|
+
tokens when several providers run together.
|
|
18
|
+
</Callout>
|
|
19
|
+
|
|
20
|
+
## Smallest Example
|
|
21
|
+
|
|
22
|
+
<Steps>
|
|
23
|
+
|
|
24
|
+
<Step>
|
|
25
|
+
### Declare cloud + BYO bindings
|
|
26
|
+
|
|
27
|
+
```typescript title="src/core/ai.ts"
|
|
28
|
+
import { ai } from "okengine";
|
|
29
|
+
|
|
30
|
+
export const smart = ai.model("smart", {
|
|
31
|
+
provider: "openrouter",
|
|
32
|
+
model: "openrouter/free",
|
|
33
|
+
apiKey: process.env.OPENROUTER_API_KEY,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export const local = ai.model("local", {
|
|
37
|
+
provider: "openai-compatible",
|
|
38
|
+
model: process.env.OKE_AI_MODEL ?? "your-model-id",
|
|
39
|
+
...(process.env.OKE_AI_URL?.trim() ? { baseUrl: process.env.OKE_AI_URL.trim() } : {}),
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
OpenRouter fills `https://openrouter.ai/api/v1` without typing it. Any
|
|
44
|
+
OpenAI-compatible `/v1` uses the same driver — set `OKE_AI_URL` yourself;
|
|
45
|
+
Compose does not manage inference.
|
|
46
|
+
|
|
47
|
+
</Step>
|
|
48
|
+
|
|
49
|
+
<Step>
|
|
50
|
+
### Attach a versioned prompt
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
export const triage = smart.prompt("ticket-triage", {
|
|
54
|
+
version: 1,
|
|
55
|
+
via: ["smart", "local"],
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
</Step>
|
|
60
|
+
|
|
61
|
+
<Step>
|
|
62
|
+
### Ask from a Flow
|
|
63
|
+
|
|
64
|
+
```typescript title="src/flows/support/triage.ts"
|
|
65
|
+
import { on, flow, http } from "okengine";
|
|
66
|
+
import { triage } from "@/core/ai";
|
|
67
|
+
|
|
68
|
+
export const classify = on(
|
|
69
|
+
http.post(),
|
|
70
|
+
flow({
|
|
71
|
+
do: async (input, fx) => await fx.ask(triage, input),
|
|
72
|
+
}),
|
|
73
|
+
);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`fx.ask` uses the prompt’s model chain. Recovery via `via` opens a **separate** client per
|
|
77
|
+
binding — keys and base URLs do not mix.
|
|
78
|
+
|
|
79
|
+
</Step>
|
|
80
|
+
|
|
81
|
+
</Steps>
|
|
82
|
+
|
|
83
|
+
## Progressive Patterns
|
|
84
|
+
|
|
85
|
+
<Tabs items={["OpenRouter", "BYO /v1", "Native Anthropic", "Multi-key"]}>
|
|
86
|
+
|
|
87
|
+
<Tab value="OpenRouter">
|
|
88
|
+
|
|
89
|
+
Zero Docker — registry fills the URL:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
export const smart = ai.model("smart", {
|
|
93
|
+
provider: "openrouter",
|
|
94
|
+
model: "openrouter/free",
|
|
95
|
+
apiKey: process.env.OPENROUTER_API_KEY,
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
See [OpenRouter](/docs/recipes/openrouter) for router aliases (`openrouter/auto`, fusion, …).
|
|
100
|
+
|
|
101
|
+
</Tab>
|
|
102
|
+
|
|
103
|
+
<Tab value="BYO /v1">
|
|
104
|
+
|
|
105
|
+
Same `openai-compatible` driver — you supply the base URL (no Compose AI recipe):
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
export const local = ai.model("local", {
|
|
109
|
+
provider: "openai-compatible",
|
|
110
|
+
model: process.env.OKE_AI_MODEL ?? "your-model-id",
|
|
111
|
+
baseUrl: process.env.OKE_AI_URL, // must end in /v1
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Pin `drivers.ai.dev: "openai-compatible"`. Set `OKE_AI_URL` / `OKE_AI_MODEL`
|
|
116
|
+
in env, or pass `baseUrl` on the binding.
|
|
117
|
+
|
|
118
|
+
</Tab>
|
|
119
|
+
|
|
120
|
+
<Tab value="Native Anthropic">
|
|
121
|
+
|
|
122
|
+
Production Claude — native Messages API, not the OpenAI-compat shim:
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
export const claude = ai.model("claude", {
|
|
126
|
+
provider: "anthropic",
|
|
127
|
+
model: "claude-sonnet-4-20250514",
|
|
128
|
+
driverId: "anthropic",
|
|
129
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
</Tab>
|
|
134
|
+
|
|
135
|
+
<Tab value="Multi-key">
|
|
136
|
+
|
|
137
|
+
One binding per provider so tokens never collide:
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
export const smart = ai.model("smart", {
|
|
141
|
+
provider: "openrouter",
|
|
142
|
+
model: "openrouter/auto",
|
|
143
|
+
apiKey: process.env.OPENROUTER_API_KEY,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
export const gpt = ai.model("gpt", {
|
|
147
|
+
provider: "openai",
|
|
148
|
+
model: "gpt-4.1-mini",
|
|
149
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
</Tab>
|
|
154
|
+
|
|
155
|
+
</Tabs>
|
|
156
|
+
|
|
157
|
+
## Options
|
|
158
|
+
|
|
159
|
+
| Option | Type | Default | Meaning |
|
|
160
|
+
| ---------- | -------- | ----------- | ------------------------------------------------------------- |
|
|
161
|
+
| `provider` | `string` | — | Registry name or exempt/local label |
|
|
162
|
+
| `model` | `string` | — | Wire model id sent to the provider |
|
|
163
|
+
| `baseUrl` | `string` | auto / omit | Override (always wins over registry) |
|
|
164
|
+
| `apiKey` | `string` | — | Per-binding key (isolates multi-provider apps) |
|
|
165
|
+
| `driverId` | `string` | app default | Protocol driver (`openai-compatible`, `anthropic`, `mock`, …) |
|
|
166
|
+
| `tier` | `string` | — | Optional app label (not the registry status below) |
|
|
167
|
+
|
|
168
|
+
Empty name throws `TypeError: ai.model: name is required`.
|
|
169
|
+
|
|
170
|
+
## Verified providers
|
|
171
|
+
|
|
172
|
+
These names auto-resolve a verified OpenAI-compatible `baseUrl`:
|
|
173
|
+
|
|
174
|
+
| Provider | Base URL (auto) |
|
|
175
|
+
| ------------ | ------------------------------------- |
|
|
176
|
+
| `openai` | `https://api.openai.com/v1` |
|
|
177
|
+
| `openrouter` | `https://openrouter.ai/api/v1` |
|
|
178
|
+
| `groq` | `https://api.groq.com/openai/v1` |
|
|
179
|
+
| `together` | `https://api.together.ai/v1` |
|
|
180
|
+
| `deepinfra` | `https://api.deepinfra.com/v1/openai` |
|
|
181
|
+
| `xai` | `https://api.x.ai/v1` |
|
|
182
|
+
| `mistral` | `https://api.mistral.ai/v1` |
|
|
183
|
+
| `deepseek` | `https://api.deepseek.com` |
|
|
184
|
+
| `vercel` | `https://ai-gateway.vercel.sh/v1` |
|
|
185
|
+
|
|
186
|
+
**Not** registered (pass `baseUrl` if you still need them): Cloudflare Workers AI
|
|
187
|
+
(account-scoped URL); Meta (retired Llama OpenAI-compat API / unverified Muse Spark
|
|
188
|
+
host — do not guess a URL).
|
|
189
|
+
|
|
190
|
+
Exempt labels (no registry URL): `mock`, `local`, `openai-compatible`.
|
|
191
|
+
|
|
192
|
+
## Limited compatibility
|
|
193
|
+
|
|
194
|
+
`anthropic`, `google`, and alias `gemini` also auto-resolve a URL, with documented limits.
|
|
195
|
+
Prefer native Anthropic for production Claude.
|
|
196
|
+
|
|
197
|
+
| Provider | Base URL (auto) |
|
|
198
|
+
| ------------------- | --------------------------------------------------------- |
|
|
199
|
+
| `anthropic` | `https://api.anthropic.com/v1` |
|
|
200
|
+
| `google` / `gemini` | `https://generativelanguage.googleapis.com/v1beta/openai` |
|
|
201
|
+
|
|
202
|
+
<Callout type="warn" title="Anthropic OpenAI-compat is evaluation-only">
|
|
203
|
+
Anthropic’s OpenAI-compatible endpoint is for testing/comparison only. `tools[].function.strict`
|
|
204
|
+
is ignored; `n` must be 1; no embeddings here. **Production:** `driverId: "anthropic"` (native
|
|
205
|
+
Messages API).
|
|
206
|
+
</Callout>
|
|
207
|
+
|
|
208
|
+
<Callout type="warn" title="Google OpenAI-compat tool schemas">
|
|
209
|
+
Tool/parameter schemas are not full OpenAI JSON Schema fidelity. Complex Flow-as-tool schemas can
|
|
210
|
+
fail — do not rely on this path for agent tool calling in production.
|
|
211
|
+
</Callout>
|
|
212
|
+
|
|
213
|
+
Declare-time and `oke extract` both warn when these providers auto-resolve.
|
|
214
|
+
|
|
215
|
+
## Native vs OpenAI-compat Anthropic
|
|
216
|
+
|
|
217
|
+
| Path | When |
|
|
218
|
+
| --------------------------------------------- | ----------------------------------------------- |
|
|
219
|
+
| `driverId: "anthropic"` | Production Claude — native Messages API |
|
|
220
|
+
| `provider: "anthropic"` without native driver | Quick eval via openai-compatible + registry URL |
|
|
221
|
+
|
|
222
|
+
They are not interchangeable for agents that depend on reliable tool calling.
|
|
223
|
+
|
|
224
|
+
## Streaming
|
|
225
|
+
|
|
226
|
+
`fx.stream(model, { prompt, data?, via? })` records `asks` and yields token chunks. Drivers
|
|
227
|
+
that do not support stream throw
|
|
228
|
+
`ai: model "…" (driver …) does not support stream`.
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
for await (const chunk of fx.stream(smart, { prompt: "Say hello" })) {
|
|
232
|
+
// chunk is a string token
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Per-environment drivers
|
|
237
|
+
|
|
238
|
+
See [AI Overview](/docs/elements/ai#per-environment-drivers). create-oke does **not** pin
|
|
239
|
+
`drivers.ai` by default — unset dev/test → `mock`; prod must declare.
|
|
240
|
+
|
|
241
|
+
## Troubleshooting
|
|
242
|
+
|
|
243
|
+
<Accordions>
|
|
244
|
+
|
|
245
|
+
<Accordion title='ai.model: unknown provider "…" requires an explicit baseUrl'>
|
|
246
|
+
The name is not in the registry (and not an exempt local label). Pass `baseUrl`, or use a known
|
|
247
|
+
provider id from the tables above. Exact message lists known providers and notes that Cloudflare
|
|
248
|
+
and Meta always need `baseUrl`.
|
|
249
|
+
</Accordion>
|
|
250
|
+
|
|
251
|
+
<Accordion title="Limited-compatibility warn on extract / declare">
|
|
252
|
+
Expected for `anthropic` / `google` / `gemini` when auto-resolving the OpenAI-compat URL. Switch
|
|
253
|
+
to native `driverId: "anthropic"` for production Claude.
|
|
254
|
+
</Accordion>
|
|
255
|
+
|
|
256
|
+
<Accordion title='ai: no client for model "…" and no defaultDriver'>
|
|
257
|
+
The binding has no resolvable client and boot has no default AI driver. Pin `drivers.ai` or set
|
|
258
|
+
`OKE_AI_DRIVER` / `OKE_AI_URL` for the active environment.
|
|
259
|
+
</Accordion>
|
|
260
|
+
|
|
261
|
+
<Accordion title="TypeError: ai.model: name is required">
|
|
262
|
+
Pass a non-empty logical name (`"smart"`, `"local"`, …).
|
|
263
|
+
</Accordion>
|
|
264
|
+
|
|
265
|
+
</Accordions>
|
|
266
|
+
|
|
267
|
+
## Learn more
|
|
268
|
+
|
|
269
|
+
- [OpenRouter](/docs/recipes/openrouter) — free / auto / fusion routers
|
|
270
|
+
- [Prompts](/docs/elements/ai/prompts) — `model.prompt` and `via`
|
|
271
|
+
- [AI](/docs/elements/ai) — element overview and `fx` surface
|
|
272
|
+
|
|
273
|
+
## Next
|
|
274
|
+
|
|
275
|
+
<Cards>
|
|
276
|
+
<Card
|
|
277
|
+
title="Prompts"
|
|
278
|
+
description="Versioned prompts and via chains."
|
|
279
|
+
href="/docs/elements/ai/prompts"
|
|
280
|
+
/>
|
|
281
|
+
<Card title="OpenRouter" description="Zero-cost cloud default." href="/docs/recipes/openrouter" />
|
|
282
|
+
<Card title="AI" description="Element overview." href="/docs/elements/ai" />
|
|
283
|
+
</Cards>
|