okengine 0.21.1 → 0.23.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 +11 -4
- package/LICENSE +202 -0
- package/NOTICE +2 -0
- package/README.md +15 -9
- package/manifest.v1.schema.json +54 -0
- package/package.json +53 -38
- package/site/content/docs/ai/mcp.mdx +13 -9
- package/site/content/docs/ai/skills.mdx +2 -2
- package/site/content/docs/client/calling.mdx +27 -19
- package/site/content/docs/client/index.mdx +1 -1
- package/site/content/docs/elements/ai/agents.mdx +61 -13
- package/site/content/docs/elements/ai/decide.mdx +536 -0
- package/site/content/docs/elements/ai/events.mdx +373 -0
- package/site/content/docs/elements/ai/index.mdx +9 -3
- package/site/content/docs/elements/ai/meta.json +1 -1
- package/site/content/docs/elements/ai/prompts.mdx +4 -2
- package/site/content/docs/elements/channel/email.mdx +1 -1
- package/site/content/docs/elements/channel/index.mdx +1 -1
- package/site/content/docs/elements/flow/http.mdx +4 -4
- package/site/content/docs/elements/flow/index.mdx +3 -3
- package/site/content/docs/elements/flow/meta.json +1 -1
- package/site/content/docs/elements/gate/auth.mdx +4 -1
- package/site/content/docs/elements/gate/tenancy.mdx +1 -1
- package/site/content/docs/elements/store/index.mdx +1 -1
- package/site/content/docs/elements/store/kv.mdx +5 -5
- package/site/content/docs/elements/vault/rotation.mdx +15 -0
- package/site/content/docs/plugins/otp.mdx +31 -31
- package/site/content/docs/recipes/dragonfly.mdx +5 -5
- package/site/content/docs/recipes/index.mdx +6 -6
- package/site/content/docs/recipes/mailpit.mdx +1 -1
- package/site/content/docs/recipes/meilisearch.mdx +1 -1
- package/site/content/docs/recipes/pgdog.mdx +1 -1
- package/site/content/docs/recipes/postgres.mdx +12 -8
- package/site/content/docs/recipes/redis.mdx +4 -4
- package/site/content/docs/reference/cli.mdx +2 -1
- package/site/content/docs/reference/configuration.mdx +11 -9
- package/site/content/docs/reference/errors.mdx +12 -2
- package/site/content/docs/reference/fx.mdx +35 -21
- package/site/content/docs/reference/idempotency.mdx +192 -0
- package/site/content/docs/reference/index.mdx +6 -1
- package/site/content/docs/reference/meta.json +2 -1
- package/site/content/docs/understand/meta.json +1 -1
- package/site/content/docs/{elements/flow → understand}/routing.mdx +11 -10
- package/site/content/docs/understand/the-architecture.mdx +14 -12
- package/site/content/docs/understand/try-it.mdx +3 -3
- package/src/auth/api-key-sql.test.ts +44 -0
- package/src/auth/api-key-sql.ts +1 -0
- package/src/auth/api-keys.ts +30 -12
- package/src/auth/config.ts +6 -2
- package/src/auth/gate-auth.test.ts +20 -0
- package/src/cli/agents-md.test.ts +25 -0
- package/src/cli/ask-vault-gaps.test.ts +38 -1
- package/src/cli/ask-vault-gaps.ts +35 -2
- package/src/cli/competitor-mention-removal.test.ts +3 -3
- package/src/cli/decide.ts +174 -0
- package/src/cli/decision-lock-watch.test.ts +45 -0
- package/src/cli/decision-lock-watch.ts +51 -0
- package/src/cli/dev-app-runner.ts +34 -8
- package/src/cli/dev-auth-secret.test.ts +49 -0
- package/src/cli/dev-auth-secret.ts +49 -0
- package/src/cli/dev-hot.test.ts +41 -0
- package/src/cli/dev-hot.ts +48 -0
- package/src/cli/dev.test.ts +1 -1
- package/src/cli/dev.ts +24 -6
- package/src/cli/docker-cli.test.ts +1 -1
- package/src/cli/eval.ts +142 -1
- package/src/cli/index.ts +14 -1
- package/src/cli/load-config.images.test.ts +12 -12
- package/src/cli/load-config.ts +2 -2
- package/src/cli/mcp-from-console.ts +48 -0
- package/src/cli/registry.ts +35 -1
- package/src/cli/vault-cmd.test.ts +23 -0
- package/src/cli/vault-cmd.ts +7 -0
- package/src/client/agent.ts +307 -0
- package/src/client/create.ts +18 -1
- package/src/client/transport.test.ts +245 -0
- package/src/client/transport.ts +133 -19
- package/src/client/types.ts +29 -3
- package/src/client-react/index.ts +7 -1
- package/src/client-react/use-agent-run.test.ts +271 -0
- package/src/client-react/use-agent-run.ts +193 -0
- package/src/compiler/ai-approval.test.ts +36 -0
- package/src/compiler/ai-repair.test.ts +22 -0
- package/src/compiler/decisions.extract.test.ts +164 -0
- package/src/compiler/effects-infer.ts +753 -17
- package/src/compiler/extract.test.ts +37 -0
- package/src/compiler/extract.ts +381 -24
- package/src/compiler/fixtures/skyport.expected.json +24 -0
- package/src/compiler/fx-follow.test.ts +164 -0
- package/src/compiler/fx-index.ts +399 -0
- package/src/compiler/response.ts +35 -2
- package/src/config/index.ts +21 -3
- package/src/console/server/ai-runs-flows.ts +269 -0
- package/src/console/server/ai-runs.test.ts +323 -0
- package/src/console/server/ai-runs.ts +562 -0
- package/src/console/server/ai.ts +12 -1
- package/src/console/server/app.ts +10 -1
- package/src/console/server/decisions-flows.ts +157 -0
- package/src/console/server/decisions.test.ts +66 -0
- package/src/console/server/decisions.ts +229 -0
- package/src/console/server/flows-invoke.test.ts +2 -2
- package/src/console/server/flows.ts +50 -2
- package/src/console/server/invoke-user-flow.ts +9 -0
- package/src/console/server/runs-ingest.ts +16 -0
- package/src/console/server/serve.ts +5 -0
- package/src/console/server/state.ts +25 -1
- package/src/console/server/store-stats.test.ts +47 -0
- package/src/console/server/store-stats.ts +92 -18
- package/src/console/ui-next/dist/assets/access-page-DDKkhT9v.js +4 -0
- package/src/console/ui-next/dist/assets/agent-disclosure-62Xts8Xi.js +1 -0
- package/src/console/ui-next/dist/assets/{cache-glyph-92uM5MO7.js → cache-glyph-DyeoKHKA.js} +1 -1
- package/src/console/ui-next/dist/assets/{call-pii-button-DtGVPtcs.js → call-pii-button-DvfpLXsU.js} +1 -1
- package/src/console/ui-next/dist/assets/{collapsible-DN7l6zmC.js → collapsible-BY03SeCg.js} +1 -1
- package/src/console/ui-next/dist/assets/confirm-sheet-DZfuJXP4.js +1 -0
- package/src/console/ui-next/dist/assets/copy-inline-button-BTjPVjRT.js +1 -0
- package/src/console/ui-next/dist/assets/decisions-page-CgkKlA56.js +1 -0
- package/src/console/ui-next/dist/assets/detail-header-Dk5LipF6.js +1 -0
- package/src/console/ui-next/dist/assets/dropdown-menu-CRGrj5JU.js +1 -0
- package/src/console/ui-next/dist/assets/duration-tone-Y6HLjyJ5.js +9 -0
- package/src/console/ui-next/dist/assets/element-icons-C6t8Vlml.js +1 -0
- package/src/console/ui-next/dist/assets/explorer-chrome-Dslh2yE8.js +1 -0
- package/src/console/ui-next/dist/assets/explorer-empty-CIVg7Jgb.js +1 -0
- package/src/console/ui-next/dist/assets/flows-page-DLPfNy-_.js +1 -0
- package/src/console/ui-next/dist/assets/{highlighted-json-BlAEVgNW.js → highlighted-json-D7nNzpgB.js} +1 -1
- package/src/console/ui-next/dist/assets/{http-method-BDf7OAHv.js → http-method-DdL19zzh.js} +1 -1
- package/src/console/ui-next/dist/assets/index-BlrN49Hs.css +2 -0
- package/src/console/ui-next/dist/assets/index-C0lc_s9d.js +58 -0
- package/src/console/ui-next/dist/assets/observability-page-CRlcyLCC.js +8 -0
- package/src/console/ui-next/dist/assets/{replica-lag-B3GLNVfF.js → replica-lag-Bb3FWUu9.js} +7 -7
- package/src/console/ui-next/dist/assets/request-meta-DYBMWhX8.js +1 -0
- package/src/console/ui-next/dist/assets/shortcut-keys-DTE1sjTC.js +1 -0
- package/src/console/ui-next/dist/assets/store-page-CcE-SXC8.js +41 -0
- package/src/console/ui-next/dist/assets/trace-detail-sheet-CKMSEQ4s.js +2 -0
- package/src/console/ui-next/dist/assets/tree-expand-toggle-QOfk0M0H.js +55 -0
- package/src/console/ui-next/dist/assets/units-page-DKC1CDDd.js +1 -0
- package/src/console/ui-next/dist/assets/use-vault-list-BAyQG8Re.js +1 -0
- package/src/console/ui-next/dist/assets/vault-page-B54v4Yit.js +2 -0
- package/src/console/ui-next/dist/index.html +4 -3
- package/src/console/ui-next/seed-parked-approval.ts +126 -0
- package/src/console/ui-next/src/client.ts +224 -1
- package/src/console/ui-next/src/components/explorer/detail-header.tsx +9 -0
- package/src/console/ui-next/src/components/explorer/explorer-start-toggle.tsx +5 -1
- package/src/console/ui-next/src/components/ui/sheet-form.tsx +21 -12
- package/src/console/ui-next/src/features/flows/decisions/decisions-page.tsx +216 -0
- package/src/console/ui-next/src/features/flows/decisions/resolve.test.ts +48 -0
- package/src/console/ui-next/src/features/flows/decisions/resolve.ts +111 -0
- package/src/console/ui-next/src/features/flows/flows-page.tsx +10 -0
- package/src/console/ui-next/src/features/flows/graph/element-map.ts +1 -0
- package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +6 -0
- package/src/console/ui-next/src/features/flows/traces/effect-summary.test.ts +24 -0
- package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +24 -0
- package/src/console/ui-next/src/features/flows/traces/http-status.ts +58 -0
- package/src/console/ui-next/src/features/flows/traces/request-client-card.tsx +355 -0
- package/src/console/ui-next/src/features/flows/traces/request-client.test.ts +114 -0
- package/src/console/ui-next/src/features/flows/traces/request-client.ts +423 -0
- package/src/console/ui-next/src/features/flows/traces/request-input-view.test.ts +52 -6
- package/src/console/ui-next/src/features/flows/traces/request-input-view.ts +85 -19
- package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +505 -80
- package/src/console/ui-next/src/features/flows/traces/trace-lanes.test.ts +61 -0
- package/src/console/ui-next/src/features/flows/traces/trace-lanes.ts +78 -0
- package/src/console/ui-next/src/features/flows/traces/trace-nav.test.ts +48 -0
- package/src/console/ui-next/src/features/flows/traces/trace-nav.ts +57 -0
- package/src/console/ui-next/src/features/flows/traces/trace-request-section.tsx +275 -96
- package/src/console/ui-next/src/features/flows/traces/traces-pane.tsx +16 -2
- package/src/console/ui-next/src/features/observability/detail/ai-runs.tsx +369 -0
- package/src/console/ui-next/src/features/observability/observability-page.tsx +31 -1
- package/src/console/ui-next/src/features/observability/state/observability-selection.ts +18 -3
- package/src/console/ui-next/src/features/store/performance/kv-performance-panel.tsx +12 -1
- package/src/console/ui-next/src/features/store/performance/performance-panel.tsx +14 -1
- package/src/console/ui-next/src/features/units/call/call-api-panel.tsx +1 -1
- package/src/console/ui-next/src/features/units/detail/flow-contract-panel.tsx +15 -2
- package/src/console/ui-next/src/features/units/explorer/units-tree.tsx +73 -18
- package/src/console/ui-next/src/features/units/lib/unit-tree.test.ts +21 -0
- package/src/console/ui-next/src/features/units/lib/unit-tree.ts +82 -0
- package/src/console/ui-next/src/features/units/units-page.tsx +25 -7
- package/src/console/ui-next/src/router.tsx +17 -0
- package/src/console/ui-next/ui-next-seed-runs.ts +23 -0
- package/src/console/ui-next/vite-console-kernel-plugin.ts +43 -3
- package/src/console/ui-next/vite.config.ts +9 -0
- package/src/docker/docker.test.ts +13 -13
- package/src/docker/images-config.test.ts +12 -12
- package/src/docker/recipes/dragonfly.ts +3 -2
- package/src/docker/recipes/redis.ts +1 -1
- package/src/docker/stack-id.test.ts +1 -1
- package/src/drivers/ai-anthropic.ts +212 -21
- package/src/drivers/ai-mock.ts +34 -1
- package/src/drivers/ai-openai-compatible.ts +67 -26
- package/src/drivers/ai-preconnect.ts +18 -0
- package/src/drivers/ai-stream.test.ts +62 -0
- package/src/drivers/ai-types.ts +20 -0
- package/src/drivers/journal-postgres.ts +455 -3
- package/src/drivers/meilisearch.ts +2 -0
- package/src/drivers/memory-ddl.test.ts +18 -0
- package/src/drivers/memory.ts +21 -1
- package/src/drivers/pg-rls.test.ts +31 -0
- package/src/drivers/pg-rls.ts +15 -0
- package/src/drivers/postgres.test.ts +9 -0
- package/src/drivers/postgres.ts +49 -11
- package/src/drivers/vault-builtin.test.ts +10 -0
- package/src/drivers/vault-builtin.ts +13 -1
- package/src/drivers/vault-remote-bag.ts +5 -1
- package/src/drivers/vault-types.ts +6 -1
- package/src/elements/ai/agent-event-slot.ts +27 -0
- package/src/elements/ai/approval-http.ts +207 -0
- package/src/elements/ai/approval.test.ts +741 -0
- package/src/elements/ai/approval.ts +228 -0
- package/src/elements/ai/decisions/bind.ts +163 -0
- package/src/elements/ai/decisions/certificate.test.ts +291 -0
- package/src/elements/ai/decisions/certificate.ts +377 -0
- package/src/elements/ai/decisions/certify.ts +314 -0
- package/src/elements/ai/decisions/decide.test.ts +953 -0
- package/src/elements/ai/decisions/e2e.test.ts +399 -0
- package/src/elements/ai/decisions/export.test.ts +120 -0
- package/src/elements/ai/decisions/export.ts +146 -0
- package/src/elements/ai/decisions/fixtures/openrouter-request.json +24 -0
- package/src/elements/ai/decisions/fixtures/openrouter-response.json +22 -0
- package/src/elements/ai/decisions/fixtures/typesafe-request.json +19 -0
- package/src/elements/ai/decisions/fixtures/typesafe-response.json +13 -0
- package/src/elements/ai/decisions/http.test.ts +154 -0
- package/src/elements/ai/decisions/http.ts +240 -0
- package/src/elements/ai/decisions/labels.test.ts +282 -0
- package/src/elements/ai/decisions/labels.ts +257 -0
- package/src/elements/ai/decisions/openrouter.live.test.ts +136 -0
- package/src/elements/ai/decisions/openrouter.ts +36 -0
- package/src/elements/ai/decisions/provider.ts +102 -0
- package/src/elements/ai/decisions/typesafe.ts +36 -0
- package/src/elements/ai/declare.ts +252 -1
- package/src/elements/ai/events.test.ts +379 -0
- package/src/elements/ai/events.ts +138 -0
- package/src/elements/ai/run-events.test.ts +461 -0
- package/src/elements/ai/run-events.ts +522 -0
- package/src/elements/ai/runtime.ts +1186 -105
- package/src/elements/ai/stream-turn.ts +214 -0
- package/src/elements/ai/stream.live.test.ts +76 -0
- package/src/elements/ai/subagent.test.ts +136 -0
- package/src/elements/ai.test.ts +497 -3
- package/src/elements/ai.ts +16 -1
- package/src/elements/clock/durable.ts +27 -1
- package/src/elements/store/emit-drizzle.ts +2 -2
- package/src/elements/store/live-default.test.ts +2 -0
- package/src/elements/store/live-http.test.ts +1 -0
- package/src/elements/store/resource-list-docs.test.ts +2 -2
- package/src/elements/store/resource.test.ts +3 -3
- package/src/elements/store/schema-decl.test.ts +1 -0
- package/src/elements/store/sql-condition.ts +24 -7
- package/src/elements/store/sql-session.test.ts +51 -0
- package/src/elements/store/sql-session.ts +111 -1
- package/src/elements/store/upsert-app.test.ts +1 -1
- package/src/elements/vault/audit.test.ts +137 -0
- package/src/elements/vault/audit.ts +106 -13
- package/src/elements/vault/boot-chain.ts +9 -1
- package/src/elements/vault/builtin-adapter.ts +33 -3
- package/src/i18n/catalogs/ar.ts +9 -0
- package/src/i18n/catalogs/en.ts +9 -0
- package/src/index.ts +2 -0
- package/src/kernel/abort-scope.ts +33 -2
- package/src/kernel/agent-event-store.ts +448 -0
- package/src/kernel/app.ts +294 -19
- package/src/kernel/auto-cache.test.ts +6 -6
- package/src/kernel/boot-bind/ai.ts +3 -0
- package/src/kernel/boot-bind/store.test.ts +26 -0
- package/src/kernel/boot-bind/store.ts +82 -6
- package/src/kernel/boot-bind/vault.ts +1 -0
- package/src/kernel/boot.ts +34 -5
- package/src/kernel/builtin-errors.ts +10 -0
- package/src/kernel/capability.ts +3 -0
- package/src/kernel/client-descriptor.ts +1 -0
- package/src/kernel/concurrency.test.ts +33 -0
- package/src/kernel/decision-label-store.ts +441 -0
- package/src/kernel/effects-stamping.test.ts +2 -2
- package/src/kernel/effects.test.ts +2 -1
- package/src/kernel/effects.ts +13 -1
- package/src/kernel/element-registries.ts +3 -0
- package/src/kernel/errors-compiler.ts +20 -0
- package/src/kernel/errors-text.ts +4 -0
- package/src/kernel/errors.ts +2 -0
- package/src/kernel/external-effects.test.ts +36 -0
- package/src/kernel/flow.test.ts +2 -3
- package/src/kernel/flow.ts +24 -0
- package/src/kernel/fx-decide.ts +761 -0
- package/src/kernel/fx-fetch.ts +5 -1
- package/src/kernel/fx.test.ts +12 -5
- package/src/kernel/fx.ts +316 -29
- package/src/kernel/http-frame.test.ts +94 -0
- package/src/kernel/http-frame.ts +203 -0
- package/src/kernel/idempotency-store.ts +578 -0
- package/src/kernel/idempotency.test.ts +556 -0
- package/src/kernel/idempotency.ts +304 -0
- package/src/kernel/index.ts +1 -0
- package/src/kernel/journal.ts +160 -0
- package/src/kernel/json-result.ts +10 -0
- package/src/kernel/pipeline.test.ts +45 -0
- package/src/kernel/sse-id.ts +32 -0
- package/src/manifest/diff.ts +1 -0
- package/src/manifest/types.ts +37 -2
- package/src/mcp/ai-tools.test.ts +202 -0
- package/src/mcp/authorization.ts +66 -0
- package/src/mcp/session.ts +3 -0
- package/src/mcp/tools.ts +168 -0
- package/src/plugins/auth-delivery.mailpit.integration.test.ts +1 -1
- package/src/plugins/otp.test.ts +65 -1
- package/src/plugins/otp.ts +59 -7
- package/src/release/absolute-regression.test.ts +63 -0
- package/src/release/http-graph.test.ts +27 -0
- package/src/release/http-graph.ts +95 -0
- package/src/release/index.ts +3 -0
- package/src/release/limits.ts +17 -2
- package/src/release/measure.ts +144 -28
- package/src/runs/collect.ts +4 -1
- package/src/runs/parquet.test.ts +27 -1
- package/src/runs/parquet.ts +19 -0
- package/src/runs/types.ts +31 -0
- package/src/runtime/json-code-block.test.ts +106 -47
- package/src/runtime/json-code-block.ts +1209 -46
- package/src/term.test.ts +13 -0
- package/src/term.ts +81 -49
- package/src/test/create-test-app.test.ts +3 -1
- package/src/test/create-test-app.ts +40 -0
- package/src/test/live-signals.test.ts +1 -0
- package/src/test/provisions.integration.test.ts +1 -0
- package/src/test/tenant-isolation.test.ts +1 -0
- package/src/console/ui-next/dist/assets/PlusSignIcon-CwG3nxfu.js +0 -1
- package/src/console/ui-next/dist/assets/access-page-Bgt9bq2r.js +0 -4
- package/src/console/ui-next/dist/assets/agent-disclosure-B43CXZZR.js +0 -1
- package/src/console/ui-next/dist/assets/copy-inline-button-CAYD18cr.js +0 -1
- package/src/console/ui-next/dist/assets/detail-header-DVWNjWjg.js +0 -1
- package/src/console/ui-next/dist/assets/dropdown-menu-4h2LOVXM.js +0 -1
- package/src/console/ui-next/dist/assets/duration-tone-BmIR9FV8.js +0 -9
- package/src/console/ui-next/dist/assets/element-icons-BI8cJgdh.js +0 -1
- package/src/console/ui-next/dist/assets/explorer-empty-CJs5A-wm.js +0 -1
- package/src/console/ui-next/dist/assets/flows-page-BMHs-IzK.js +0 -1
- package/src/console/ui-next/dist/assets/index-BKpaes3n.js +0 -63
- package/src/console/ui-next/dist/assets/index-VxoEz295.css +0 -2
- package/src/console/ui-next/dist/assets/observability-page-WnVLI-0j.js +0 -4
- package/src/console/ui-next/dist/assets/request-meta-DMbnAe3f.js +0 -1
- package/src/console/ui-next/dist/assets/shortcut-keys-3ILd8oGn.js +0 -1
- package/src/console/ui-next/dist/assets/store-page-KvFDingJ.js +0 -41
- package/src/console/ui-next/dist/assets/trace-detail-sheet-Htk8Cm9t.js +0 -2
- package/src/console/ui-next/dist/assets/tree-expand-toggle-CFMPWX4f.js +0 -55
- package/src/console/ui-next/dist/assets/units-page-C4NdNuxP.js +0 -1
- package/src/console/ui-next/dist/assets/use-vault-list-CT4-gajj.js +0 -1
- package/src/console/ui-next/dist/assets/vault-page-CBYl0LW_.js +0 -2
package/src/kernel/effects.ts
CHANGED
|
@@ -17,7 +17,8 @@ export type EffectKind =
|
|
|
17
17
|
| "embed"
|
|
18
18
|
| "secret"
|
|
19
19
|
| "call"
|
|
20
|
-
| "fetch"
|
|
20
|
+
| "fetch"
|
|
21
|
+
| "decide";
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Reversibility tier — console §9.1 ranking, applied to all effect kinds.
|
|
@@ -65,6 +66,11 @@ export interface EffectEntry {
|
|
|
65
66
|
* Omitted for in-process work (PGlite, mock AI, local channel console).
|
|
66
67
|
*/
|
|
67
68
|
readonly external?: EffectExternal;
|
|
69
|
+
/**
|
|
70
|
+
* Agent run this `fx.run` or nested agent call started.
|
|
71
|
+
* Absent on prompt asks and on calls that are not agents.
|
|
72
|
+
*/
|
|
73
|
+
readonly agentRunId?: string;
|
|
68
74
|
}
|
|
69
75
|
|
|
70
76
|
/** Append-only ledger of effect entries for one flow invocation. */
|
|
@@ -92,6 +98,7 @@ const TIER_BY_KIND: Readonly<Record<EffectKind, ReversibilityTier>> = {
|
|
|
92
98
|
secret: "capability",
|
|
93
99
|
call: "portal",
|
|
94
100
|
fetch: "irreversible",
|
|
101
|
+
decide: "irreversible",
|
|
95
102
|
};
|
|
96
103
|
|
|
97
104
|
/**
|
|
@@ -143,6 +150,7 @@ export async function recordEffect<T>(
|
|
|
143
150
|
externalOf?:
|
|
144
151
|
| EffectExternal
|
|
145
152
|
| ((result: T | undefined, error: unknown) => EffectExternal | undefined),
|
|
153
|
+
stamp?: (result: T | undefined) => { readonly agentRunId?: string } | undefined,
|
|
146
154
|
): Promise<T> {
|
|
147
155
|
const timestamp = now();
|
|
148
156
|
const t0 = performance.now();
|
|
@@ -163,6 +171,7 @@ export async function recordEffect<T>(
|
|
|
163
171
|
timestamp,
|
|
164
172
|
resolveDurationMs(now() - timestamp, performance.now() - t0),
|
|
165
173
|
external,
|
|
174
|
+
stamp?.(result),
|
|
166
175
|
);
|
|
167
176
|
}
|
|
168
177
|
}
|
|
@@ -187,7 +196,9 @@ export function recordObservedEffect(
|
|
|
187
196
|
timestamp: number,
|
|
188
197
|
duration: number,
|
|
189
198
|
external?: EffectExternal,
|
|
199
|
+
stamp?: { readonly agentRunId?: string },
|
|
190
200
|
): void {
|
|
201
|
+
const agentRunId = stamp?.agentRunId;
|
|
191
202
|
ledger.record({
|
|
192
203
|
kind,
|
|
193
204
|
resource,
|
|
@@ -195,6 +206,7 @@ export function recordObservedEffect(
|
|
|
195
206
|
duration,
|
|
196
207
|
reversibility: reversibilityOf(kind),
|
|
197
208
|
...(external !== undefined ? { external } : {}),
|
|
209
|
+
...(agentRunId !== undefined && agentRunId.length > 0 ? { agentRunId } : {}),
|
|
198
210
|
});
|
|
199
211
|
}
|
|
200
212
|
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import type {
|
|
18
18
|
AiAgentDecl,
|
|
19
|
+
AiDecisionDecl,
|
|
19
20
|
AiEmbedDecl,
|
|
20
21
|
AiMcpServerDecl,
|
|
21
22
|
AiModelDecl,
|
|
@@ -52,3 +53,5 @@ export const aiEmbedRegistry: AiEmbedDecl[] = [];
|
|
|
52
53
|
export const aiAgentRegistry: AiAgentDecl[] = [];
|
|
53
54
|
/** `ai.mcpServer` declarations since the last reset. */
|
|
54
55
|
export const aiMcpServerRegistry: AiMcpServerDecl[] = [];
|
|
56
|
+
/** `ai.decision` declarations since the last reset. */
|
|
57
|
+
export const aiDecisionRegistry: AiDecisionDecl[] = [];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OKE1900 — kept off the kernel edge profile.
|
|
3
|
+
*
|
|
4
|
+
* Effect inference throws a plain `Error` (`OKE1900` in the message) from
|
|
5
|
+
* `okengine/compiler`. This definition is registry-only so the compiler
|
|
6
|
+
* chunk does not import the kernel error module.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { OkeErrorDefinition } from "./errors.ts";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A Flow hides `fx` from effect inference, or an explicit `effects` block
|
|
13
|
+
* omits an effect the walk can see.
|
|
14
|
+
*/
|
|
15
|
+
export const FX_INFERENCE_OPAQUE: OkeErrorDefinition = {
|
|
16
|
+
code: 1900,
|
|
17
|
+
domain: "compiler",
|
|
18
|
+
cause: 'Flow "{flow}" hides fx from effect inference ({detail}).',
|
|
19
|
+
fix: "Name the parameter fx, keep chain aliases in the same function, and include every effect inference can see. An effects block may add keys; it cannot omit keys inference can see.",
|
|
20
|
+
};
|
|
@@ -52,6 +52,10 @@ export const OKE_ERROR_TEXT: Readonly<Record<string, OkeErrorText>> = {
|
|
|
52
52
|
cause: 'Flow "{flow}" embeds with "{resource}" without declaring it.',
|
|
53
53
|
fix: 'Add "{resource}" to this flow\'s effects.embeds.',
|
|
54
54
|
},
|
|
55
|
+
UNDECLARED_DECIDE: {
|
|
56
|
+
cause: 'Flow "{flow}" decides "{resource}" without declaring it.',
|
|
57
|
+
fix: 'Add "{resource}" to this flow\'s effects.decides.',
|
|
58
|
+
},
|
|
55
59
|
NO_EFFECTS_DECLARED: {
|
|
56
60
|
cause: 'Flow "{flow}" has no declared effects and no Manifest to derive them from.{extract}',
|
|
57
61
|
fix:
|
package/src/kernel/errors.ts
CHANGED
|
@@ -270,6 +270,8 @@ const OKE_ERROR_ROWS = {
|
|
|
270
270
|
UNDECLARED_FETCH: { code: 1008, domain: "kernel" },
|
|
271
271
|
/** Flow embeds via a model not listed in `effects.embeds`. */
|
|
272
272
|
UNDECLARED_EMBED: { code: 1009, domain: "kernel" },
|
|
273
|
+
/** Flow decides a decision not listed in `effects.decides`. */
|
|
274
|
+
UNDECLARED_DECIDE: { code: 1010, domain: "kernel" },
|
|
273
275
|
/**
|
|
274
276
|
* Flow has no declared `effects` and no Manifest-derived effects were
|
|
275
277
|
* available to stamp at boot (dev+compose / prod — never a silent open token).
|
|
@@ -85,6 +85,42 @@ describe("fx.fetch", () => {
|
|
|
85
85
|
globalThis.fetch = originalFetch;
|
|
86
86
|
}
|
|
87
87
|
});
|
|
88
|
+
|
|
89
|
+
test("fx.race aborts an in-flight fx.fetch", async () => {
|
|
90
|
+
const originalFetch = globalThis.fetch;
|
|
91
|
+
let signal: AbortSignal | undefined;
|
|
92
|
+
globalThis.fetch = (async (_input: unknown, init?: RequestInit) => {
|
|
93
|
+
signal = init?.signal ?? undefined;
|
|
94
|
+
return new Promise<Response>((_resolve, reject) => {
|
|
95
|
+
const onAbort = (): void => {
|
|
96
|
+
reject(new DOMException("aborted", "AbortError"));
|
|
97
|
+
};
|
|
98
|
+
if (init?.signal?.aborted) {
|
|
99
|
+
onAbort();
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
init?.signal?.addEventListener("abort", onAbort, { once: true });
|
|
103
|
+
});
|
|
104
|
+
}) as typeof fetch;
|
|
105
|
+
try {
|
|
106
|
+
const { fx } = createFxContext({
|
|
107
|
+
flow: "stripe.pull",
|
|
108
|
+
effects: { fetches: ["api.stripe.com"] },
|
|
109
|
+
});
|
|
110
|
+
const winner = await fx.race([
|
|
111
|
+
() => fx.fetch("https://api.stripe.com/v1/charges").then(() => "slow"),
|
|
112
|
+
async () => {
|
|
113
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
114
|
+
return "fast" as const;
|
|
115
|
+
},
|
|
116
|
+
]);
|
|
117
|
+
expect(winner).toBe("fast");
|
|
118
|
+
await new Promise((r) => setTimeout(r, 15));
|
|
119
|
+
expect(signal?.aborted).toBe(true);
|
|
120
|
+
} finally {
|
|
121
|
+
globalThis.fetch = originalFetch;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
88
124
|
});
|
|
89
125
|
|
|
90
126
|
describe("Channel failover — winning provider on EffectEntry", () => {
|
package/src/kernel/flow.test.ts
CHANGED
|
@@ -46,9 +46,8 @@ describe("flow — one species", () => {
|
|
|
46
46
|
on(signal, shared);
|
|
47
47
|
|
|
48
48
|
const app = oke({ autoBoot: false, name: "one-species" });
|
|
49
|
-
|
|
50
|
-
expect(
|
|
51
|
-
expect(app.bindings[1]?.flow).toBe(shared);
|
|
49
|
+
const sharedBindings = app.bindings.filter((binding) => binding.flow === shared);
|
|
50
|
+
expect(sharedBindings).toHaveLength(2);
|
|
52
51
|
|
|
53
52
|
const httpResult = await app.execute(shared, { n: 3 }, shared.triggers[0]!);
|
|
54
53
|
const signalResults = await app.dispatchSignal("order-placed", { n: 4 });
|
package/src/kernel/flow.ts
CHANGED
|
@@ -54,6 +54,16 @@ export interface FlowOptions<I = unknown, O = unknown> {
|
|
|
54
54
|
* (`"30s"`) adds a TTL on top of write invalidation.
|
|
55
55
|
*/
|
|
56
56
|
readonly cache?: boolean | string;
|
|
57
|
+
/**
|
|
58
|
+
* HTTP `Idempotency-Key` handling.
|
|
59
|
+
* Omitted is auto: the header is honored on an eligible mutating flow.
|
|
60
|
+
* `"required"` rejects a missing header. `false` ignores the header.
|
|
61
|
+
* A TTL string (`"24h"`) overrides the 24 hour default.
|
|
62
|
+
*/
|
|
63
|
+
readonly idempotency?:
|
|
64
|
+
| false
|
|
65
|
+
| "required"
|
|
66
|
+
| { readonly required?: boolean; readonly ttl?: string };
|
|
57
67
|
/** Declared service-level objective. */
|
|
58
68
|
readonly slo?: Slo;
|
|
59
69
|
/**
|
|
@@ -168,6 +178,19 @@ export interface FlowDef<
|
|
|
168
178
|
readonly liveCustomMatch: boolean;
|
|
169
179
|
/** Cache option. */
|
|
170
180
|
readonly cache: boolean | string | undefined;
|
|
181
|
+
/** Author idempotency option. */
|
|
182
|
+
readonly idempotency:
|
|
183
|
+
| false
|
|
184
|
+
| "required"
|
|
185
|
+
| { readonly required?: boolean; readonly ttl?: string }
|
|
186
|
+
| undefined;
|
|
187
|
+
/**
|
|
188
|
+
* Extracted idempotency stamp. Boot copies this from the Manifest.
|
|
189
|
+
* Runtime resolves it when extract has not run.
|
|
190
|
+
*/
|
|
191
|
+
resolvedIdempotency?: { readonly mode: "off" | "auto" | "required"; readonly ttl: string };
|
|
192
|
+
/** True when extract saw `fx.raw`. A throw then completes the idempotency row. */
|
|
193
|
+
usesRaw?: boolean;
|
|
171
194
|
/** SLO. */
|
|
172
195
|
readonly slo: Slo | undefined;
|
|
173
196
|
/** Plane (user vs operator). */
|
|
@@ -305,6 +328,7 @@ export function flow(
|
|
|
305
328
|
live: undefined,
|
|
306
329
|
liveCustomMatch: false,
|
|
307
330
|
cache: options.cache,
|
|
331
|
+
idempotency: options.idempotency,
|
|
308
332
|
slo: options.slo,
|
|
309
333
|
plane: options.plane,
|
|
310
334
|
breaking: false,
|