okengine 0.2.6 → 0.2.8
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 +24 -23
- package/README.md +52 -346
- package/docs/spec/console.md +165 -142
- package/docs/spec/example.md +490 -312
- package/docs/spec/four-applications.md +495 -314
- package/docs/spec/unified-theory.md +184 -175
- package/package.json +45 -37
- package/spec/manifest.v1.schema.json +40 -9
- package/src/auth/api-keys.ts +2 -5
- package/src/auth/attenuation.ts +2 -6
- package/src/auth/auth.test.ts +53 -31
- package/src/auth/invoke-as.ts +1 -3
- package/src/auth/operator.ts +8 -26
- package/src/auth/planes.ts +2 -7
- package/src/auth/plugin.ts +4 -7
- package/src/auth/roles.ts +1 -5
- package/src/auth/sessions.ts +10 -39
- package/src/cli/args.ts +1 -5
- package/src/cli/ask-dev-mode.ts +40 -0
- package/src/cli/build.ts +1 -2
- package/src/cli/client-add.test.ts +8 -15
- package/src/cli/client-add.ts +5 -14
- package/src/cli/completion.test.ts +1 -5
- package/src/cli/completion.ts +4 -17
- package/src/cli/db-auto-push.test.ts +64 -0
- package/src/cli/db-auto-push.ts +72 -0
- package/src/cli/db.test.ts +189 -0
- package/src/cli/db.ts +386 -0
- package/src/cli/dev-app-runner.ts +2 -8
- package/src/cli/dev-db-push.test.ts +163 -0
- package/src/cli/dev-mode.test.ts +45 -0
- package/src/cli/dev-mode.ts +78 -0
- package/src/cli/dev.test.ts +148 -21
- package/src/cli/dev.ts +208 -134
- package/src/cli/doc-drift.test.ts +3 -2
- package/src/cli/doc-drift.ts +21 -50
- package/src/cli/doc-staleness.test.ts +69 -0
- package/src/cli/docker-cli.test.ts +7 -8
- package/src/cli/docker.ts +1 -3
- package/src/cli/doctor-diff-examples.ts +1 -3
- package/src/cli/doctor-diff.test.ts +1 -5
- package/src/cli/doctor-diff.ts +17 -46
- package/src/cli/doctor-pii.ts +2 -7
- package/src/cli/doctor.test.ts +26 -4
- package/src/cli/doctor.ts +35 -11
- package/src/cli/eval.ts +4 -14
- package/src/cli/gates-list.ts +1 -4
- package/src/cli/hero-meta.test.ts +17 -19
- package/src/cli/hero-meta.ts +20 -30
- package/src/cli/images.ts +3 -8
- package/src/cli/index.ts +11 -2
- package/src/cli/load-config.images.test.ts +14 -14
- package/src/cli/load-config.ts +41 -47
- package/src/cli/mcp-from-console.ts +1 -4
- package/src/cli/mode.ts +45 -0
- package/src/cli/ports.test.ts +4 -13
- package/src/cli/ports.ts +1 -3
- package/src/cli/privacy-erase.ts +1 -3
- package/src/cli/registry.ts +75 -25
- package/src/cli/schema.ts +3 -10
- package/src/cli/stack.ts +2 -7
- package/src/cli/start.ts +4 -15
- package/src/cli/upgrade.ts +1 -4
- package/src/client/budget-entry.ts +1 -6
- package/src/client/create.test.ts +6 -12
- package/src/client/create.ts +2 -8
- package/src/client/errors.ts +1 -4
- package/src/client/index.ts +1 -6
- package/src/client/notes-contract.test.ts +4 -13
- package/src/client/transport.ts +9 -30
- package/src/client/types.ts +8 -29
- package/src/compiler/aot.test.ts +2 -9
- package/src/compiler/aot.ts +1 -4
- package/src/compiler/differential.test.ts +3 -11
- package/src/compiler/dynamic.ts +1 -4
- package/src/compiler/effects-infer.ts +8 -34
- package/src/compiler/emit.ts +1 -3
- package/src/compiler/extract.test.ts +96 -30
- package/src/compiler/extract.ts +362 -156
- package/src/compiler/fixtures/skyport/oke.config.ts +1 -1
- package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -3
- package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +1 -3
- package/src/compiler/fixtures/skyport/src/flows/support/index.ts +4 -1
- package/src/compiler/fixtures/skyport.expected.json +24 -83
- package/src/compiler/fixtures/triggers/five-triggers.ts +1 -2
- package/src/compiler/http-parse.ts +2 -9
- package/src/compiler/index.ts +1 -5
- package/src/compiler/response.ts +4 -7
- package/src/compiler/sucrose.ts +11 -31
- package/src/config/define-config.test.ts +57 -34
- package/src/config/index.ts +181 -37
- package/src/config/resolve-driver.test.ts +28 -17
- package/src/console/budget.test.ts +1 -4
- package/src/console/index.ts +1 -4
- package/src/console/server/access.test.ts +15 -43
- package/src/console/server/access.ts +19 -49
- package/src/console/server/ai.test.ts +3 -11
- package/src/console/server/ai.ts +23 -46
- package/src/console/server/app.ts +14 -45
- package/src/console/server/auth-rate.test.ts +4 -12
- package/src/console/server/bind.ts +1 -5
- package/src/console/server/channels.test.ts +2 -6
- package/src/console/server/channels.ts +10 -35
- package/src/console/server/claim.ts +2 -8
- package/src/console/server/clock.test.ts +2 -6
- package/src/console/server/clock.ts +8 -26
- package/src/console/server/console.test.ts +1 -3
- package/src/console/server/diff.test.ts +5 -17
- package/src/console/server/diff.ts +10 -31
- package/src/console/server/dry-run.audit.test.ts +2 -8
- package/src/console/server/flows.ts +64 -233
- package/src/console/server/gates.test.ts +14 -50
- package/src/console/server/gates.ts +13 -48
- package/src/console/server/index.ts +2 -9
- package/src/console/server/live.ts +3 -12
- package/src/console/server/operator-db.test.ts +4 -15
- package/src/console/server/operator-db.ts +13 -32
- package/src/console/server/plugin.ts +50 -53
- package/src/console/server/plugins.test.ts +2 -6
- package/src/console/server/plugins.ts +17 -56
- package/src/console/server/runs-pii.ts +2 -7
- package/src/console/server/security.gate.test.ts +18 -40
- package/src/console/server/serve.ts +10 -25
- package/src/console/server/signals.test.ts +1 -3
- package/src/console/server/signals.ts +17 -40
- package/src/console/server/state.ts +21 -59
- package/src/console/server/store.test.ts +20 -22
- package/src/console/server/store.ts +31 -76
- package/src/console/server/vault.test.ts +12 -29
- package/src/console/server/vault.ts +23 -60
- package/src/console/ui/access/AccessA11yView.tsx +6 -21
- package/src/console/ui/access/a11y.test.tsx +3 -12
- package/src/console/ui/access/acknowledgement.test.ts +1 -4
- package/src/console/ui/access/acknowledgement.ts +1 -3
- package/src/console/ui/access/blast-radius.ts +1 -3
- package/src/console/ui/access/confirmation.test.ts +1 -5
- package/src/console/ui/access/confirmation.ts +1 -4
- package/src/console/ui/access/fixture.ts +1 -5
- package/src/console/ui/access/grantable.test.ts +1 -3
- package/src/console/ui/access/grantable.ts +2 -7
- package/src/console/ui/access/index.ts +2 -9
- package/src/console/ui/access/provenance.test.ts +1 -3
- package/src/console/ui/access/provenance.ts +2 -6
- package/src/console/ui/access/search.test.ts +1 -5
- package/src/console/ui/access/search.ts +2 -6
- package/src/console/ui/ai/AiA11yView.tsx +6 -17
- package/src/console/ui/ai/a11y.test.tsx +2 -5
- package/src/console/ui/ai/fixture.ts +2 -7
- package/src/console/ui/ai/format.ts +1 -3
- package/src/console/ui/ai/group.test.ts +1 -3
- package/src/console/ui/ai/group.ts +4 -12
- package/src/console/ui/ai/index.ts +2 -9
- package/src/console/ui/ai/promotion.test.ts +2 -7
- package/src/console/ui/ai/promotion.ts +4 -13
- package/src/console/ui/ai/search.test.ts +2 -11
- package/src/console/ui/ai/search.ts +3 -13
- package/src/console/ui/ai/types.ts +1 -8
- package/src/console/ui/architecture/ArchitectureA11yView.tsx +8 -29
- package/src/console/ui/architecture/a11y.test.tsx +1 -2
- package/src/console/ui/architecture/declared.ts +1 -5
- package/src/console/ui/architecture/index.ts +7 -35
- package/src/console/ui/architecture/layout.ts +1 -3
- package/src/console/ui/architecture/pathologies.ts +10 -19
- package/src/console/ui/architecture/search.ts +6 -15
- package/src/console/ui/architecture/traffic.ts +4 -14
- package/src/console/ui/architecture/types.ts +2 -10
- package/src/console/ui/architecture/view.test.ts +7 -19
- package/src/console/ui/architecture/view.ts +9 -36
- package/src/console/ui/channels/ChannelsA11yView.tsx +4 -13
- package/src/console/ui/channels/a11y.test.tsx +1 -2
- package/src/console/ui/channels/confirmation.test.ts +1 -4
- package/src/console/ui/channels/confirmation.ts +1 -4
- package/src/console/ui/channels/findings.ts +1 -5
- package/src/console/ui/channels/index.ts +2 -8
- package/src/console/ui/channels/locale.test.ts +1 -3
- package/src/console/ui/channels/locale.ts +2 -8
- package/src/console/ui/channels/search.ts +4 -13
- package/src/console/ui/channels/taxonomy.ts +1 -3
- package/src/console/ui/clock/ClockA11yView.tsx +9 -26
- package/src/console/ui/clock/a11y.test.tsx +2 -5
- package/src/console/ui/clock/confirmation.test.ts +1 -3
- package/src/console/ui/clock/confirmation.ts +1 -4
- package/src/console/ui/clock/findings.ts +1 -4
- package/src/console/ui/clock/health.ts +2 -7
- package/src/console/ui/clock/index.ts +2 -10
- package/src/console/ui/clock/search.test.ts +1 -3
- package/src/console/ui/clock/search.ts +2 -6
- package/src/console/ui/clock/timeline.test.ts +1 -3
- package/src/console/ui/clock/waiting-on.test.ts +1 -5
- package/src/console/ui/clock/waiting-on.ts +2 -7
- package/src/console/ui/diff/DiffA11yView.tsx +8 -17
- package/src/console/ui/diff/a11y.test.tsx +2 -5
- package/src/console/ui/diff/group.test.ts +3 -13
- package/src/console/ui/diff/group.ts +2 -8
- package/src/console/ui/diff/index.ts +2 -8
- package/src/console/ui/diff/search.test.ts +1 -5
- package/src/console/ui/diff/search.ts +4 -16
- package/src/console/ui/diff/summary.ts +1 -2
- package/src/console/ui/dist/assets/{index-Dy4jht9P.js → index-BWo8R7NR.js} +2 -2
- package/src/console/ui/dist/assets/{panel-access-Dd37LU2c.js → panel-access-C0J2D-a2.js} +1 -1
- package/src/console/ui/dist/assets/{panel-ai-CC7LR6-J.js → panel-ai-D_m6WQI8.js} +1 -1
- package/src/console/ui/dist/assets/{panel-architecture-B5b3iKCz.js → panel-architecture-CKnXFyUx.js} +1 -1
- package/src/console/ui/dist/assets/{panel-channels-CeNjTKXp.js → panel-channels-BOmQ-onL.js} +1 -1
- package/src/console/ui/dist/assets/{panel-clock-DgFTLoHV.js → panel-clock-giAq0Ccv.js} +1 -1
- package/src/console/ui/dist/assets/{panel-diff-DxehccqB.js → panel-diff-cdonmH8c.js} +1 -1
- package/src/console/ui/dist/assets/{panel-flows-BtrVn-Eg.js → panel-flows-DlCU5zjA.js} +2 -2
- package/src/console/ui/dist/assets/{panel-gates-Z9MKRGdH.js → panel-gates-XclZxWD5.js} +1 -1
- package/src/console/ui/dist/assets/{panel-overview-Dt_AeXgd.js → panel-overview-BznEOTnb.js} +1 -1
- package/src/console/ui/dist/assets/{panel-plugins-DWd0TowH.js → panel-plugins-CcGM1g64.js} +1 -1
- package/src/console/ui/dist/assets/{panel-runs-DGstFHeq.js → panel-runs-CGWNHLR4.js} +1 -1
- package/src/console/ui/dist/assets/{panel-signals-DzEa2Fnt.js → panel-signals-CNywkdak.js} +1 -1
- package/src/console/ui/dist/assets/{panel-store-BJkbNgxx.js → panel-store-KmTbFHMH.js} +1 -1
- package/src/console/ui/dist/assets/{panel-traces-BaRVO3gM.js → panel-traces-DBLx2ilD.js} +1 -1
- package/src/console/ui/dist/assets/panel-vault-CEnFc0dk.js +1 -0
- package/src/console/ui/dist/index.html +1 -1
- package/src/console/ui/flows/FlowsA11yView.tsx +7 -22
- package/src/console/ui/flows/a11y.test.tsx +2 -8
- package/src/console/ui/flows/buffer.test.ts +3 -11
- package/src/console/ui/flows/buffer.ts +4 -11
- package/src/console/ui/flows/confirmation.ts +1 -3
- package/src/console/ui/flows/contract.test.ts +3 -7
- package/src/console/ui/flows/contract.ts +12 -36
- package/src/console/ui/flows/graph.test.ts +3 -11
- package/src/console/ui/flows/graph.ts +5 -15
- package/src/console/ui/flows/index.ts +1 -6
- package/src/console/ui/flows/save-as-test.ts +1 -3
- package/src/console/ui/flows/search.ts +8 -25
- package/src/console/ui/flows/tiers.ts +2 -9
- package/src/console/ui/gates/GatesA11yView.tsx +4 -13
- package/src/console/ui/gates/a11y.test.tsx +2 -5
- package/src/console/ui/gates/audit.ts +1 -3
- package/src/console/ui/gates/denial.test.ts +1 -3
- package/src/console/ui/gates/denial.ts +4 -12
- package/src/console/ui/gates/findings.ts +1 -3
- package/src/console/ui/gates/group.test.ts +3 -3
- package/src/console/ui/gates/group.ts +3 -11
- package/src/console/ui/gates/index.ts +2 -10
- package/src/console/ui/gates/search.ts +3 -10
- package/src/console/ui/overview/OverviewA11yView.tsx +9 -27
- package/src/console/ui/overview/a11y.test.tsx +1 -2
- package/src/console/ui/overview/busiest.ts +1 -3
- package/src/console/ui/overview/compose.ts +1 -13
- package/src/console/ui/overview/cost.ts +34 -38
- package/src/console/ui/overview/fixture.ts +21 -26
- package/src/console/ui/overview/golden.ts +4 -14
- package/src/console/ui/overview/index.ts +2 -9
- package/src/console/ui/overview/rank.test.ts +3 -10
- package/src/console/ui/overview/rank.ts +2 -7
- package/src/console/ui/overview/slo.test.ts +5 -9
- package/src/console/ui/overview/slo.ts +6 -23
- package/src/console/ui/overview/verdict.ts +3 -10
- package/src/console/ui/plugins/PluginsA11yView.tsx +8 -18
- package/src/console/ui/plugins/a11y.test.tsx +1 -2
- package/src/console/ui/plugins/fixture.ts +2 -4
- package/src/console/ui/plugins/group.test.ts +1 -3
- package/src/console/ui/plugins/group.ts +1 -6
- package/src/console/ui/plugins/index.ts +3 -13
- package/src/console/ui/plugins/search.ts +7 -19
- package/src/console/ui/runs/RunsA11yView.tsx +5 -20
- package/src/console/ui/runs/a11y.test.tsx +2 -5
- package/src/console/ui/runs/explain.ts +2 -6
- package/src/console/ui/runs/group.ts +3 -12
- package/src/console/ui/runs/histogram.test.ts +2 -11
- package/src/console/ui/runs/histogram.ts +1 -4
- package/src/console/ui/runs/index.ts +4 -18
- package/src/console/ui/runs/project.ts +2 -6
- package/src/console/ui/runs/query.test.ts +1 -3
- package/src/console/ui/runs/query.ts +12 -35
- package/src/console/ui/runs/search.ts +5 -19
- package/src/console/ui/runs/trace-link.test.ts +2 -6
- package/src/console/ui/runs/trace-link.ts +4 -16
- package/src/console/ui/runs/types.ts +1 -3
- package/src/console/ui/shell/App.tsx +2 -10
- package/src/console/ui/shell/client.ts +22 -115
- package/src/console/ui/shell/components/ui.tsx +1 -4
- package/src/console/ui/shell/layout/Shell.tsx +2 -4
- package/src/console/ui/shell/main.tsx +31 -96
- package/src/console/ui/shell/panels/access/AccessPanel.tsx +34 -98
- package/src/console/ui/shell/panels/ai/AiPanel.tsx +35 -106
- package/src/console/ui/shell/panels/architecture/ArchitecturePanel.tsx +18 -66
- package/src/console/ui/shell/panels/channels/ChannelsPanel.tsx +20 -57
- package/src/console/ui/shell/panels/clock/ClockPanel.tsx +22 -54
- package/src/console/ui/shell/panels/diff/DiffPanel.tsx +20 -61
- package/src/console/ui/shell/panels/flows/ContractEditor.tsx +6 -23
- package/src/console/ui/shell/panels/flows/FlowDrawer.tsx +13 -28
- package/src/console/ui/shell/panels/flows/FlowsPanel.tsx +9 -29
- package/src/console/ui/shell/panels/gates/GatesPanel.tsx +24 -80
- package/src/console/ui/shell/panels/overview/OverviewPanel.tsx +20 -58
- package/src/console/ui/shell/panels/plugins/PluginsPanel.tsx +16 -41
- package/src/console/ui/shell/panels/runs/RunsPanel.tsx +31 -99
- package/src/console/ui/shell/panels/signals/SignalsPanel.tsx +38 -101
- package/src/console/ui/shell/panels/store/StorePanel.tsx +27 -66
- package/src/console/ui/shell/panels/traces/TracesPanel.tsx +28 -89
- package/src/console/ui/shell/panels/vault/VaultPanel.tsx +22 -53
- package/src/console/ui/shell/setup/Wizard.tsx +3 -5
- package/src/console/ui/shell/styles.css +1 -2
- package/src/console/ui/signals/SignalsA11yView.tsx +9 -33
- package/src/console/ui/signals/a11y.test.tsx +2 -5
- package/src/console/ui/signals/confirmation.test.ts +1 -5
- package/src/console/ui/signals/confirmation.ts +2 -6
- package/src/console/ui/signals/dry-run.ts +1 -3
- package/src/console/ui/signals/durable.ts +1 -3
- package/src/console/ui/signals/findings.ts +1 -3
- package/src/console/ui/signals/group.test.ts +2 -8
- package/src/console/ui/signals/group.ts +2 -10
- package/src/console/ui/signals/index.ts +1 -4
- package/src/console/ui/signals/monitor.ts +2 -7
- package/src/console/ui/signals/schema-form.test.ts +3 -14
- package/src/console/ui/signals/schema-form.ts +1 -4
- package/src/console/ui/signals/search.ts +4 -13
- package/src/console/ui/store/StoreA11yView.tsx +3 -9
- package/src/console/ui/store/a11y.test.tsx +2 -5
- package/src/console/ui/store/confirmation.test.ts +1 -3
- package/src/console/ui/store/confirmation.ts +1 -4
- package/src/console/ui/store/dry-run.ts +2 -5
- package/src/console/ui/store/fixture.ts +1 -2
- package/src/console/ui/store/group.test.ts +1 -6
- package/src/console/ui/store/group.ts +1 -4
- package/src/console/ui/store/index.ts +1 -5
- package/src/console/ui/store/search.ts +2 -6
- package/src/console/ui/store/will-not-fire.ts +1 -2
- package/src/console/ui/traces/TracesA11yView.tsx +10 -29
- package/src/console/ui/traces/a11y.test.tsx +1 -2
- package/src/console/ui/traces/chain.test.ts +5 -19
- package/src/console/ui/traces/chain.ts +1 -3
- package/src/console/ui/traces/critical-path.test.ts +1 -3
- package/src/console/ui/traces/critical-path.ts +2 -6
- package/src/console/ui/traces/filter.test.ts +2 -6
- package/src/console/ui/traces/filter.ts +5 -13
- package/src/console/ui/traces/fold.test.ts +4 -12
- package/src/console/ui/traces/fold.ts +1 -3
- package/src/console/ui/traces/mini.ts +1 -3
- package/src/console/ui/traces/replay.test.ts +1 -3
- package/src/console/ui/traces/replay.ts +1 -3
- package/src/console/ui/traces/sampling.ts +1 -4
- package/src/console/ui/traces/search.ts +4 -17
- package/src/console/ui/traces/tier.ts +1 -3
- package/src/console/ui/vault/VaultA11yView.tsx +5 -17
- package/src/console/ui/vault/a11y.test.tsx +1 -2
- package/src/console/ui/vault/blast-radius.ts +1 -3
- package/src/console/ui/vault/confirmation.test.ts +1 -5
- package/src/console/ui/vault/confirmation.ts +1 -4
- package/src/console/ui/vault/dormant.test.ts +1 -4
- package/src/console/ui/vault/export-safe.test.ts +1 -5
- package/src/console/ui/vault/export-safe.ts +1 -4
- package/src/console/ui/vault/fixture.ts +3 -3
- package/src/console/ui/vault/group.ts +1 -2
- package/src/console/ui/vault/index.ts +2 -10
- package/src/console/ui/vault/search.ts +2 -6
- package/src/console/ui/vault/types.ts +1 -1
- package/src/console/xss.gate.test.ts +1 -3
- package/src/docker/compose.ts +112 -20
- package/src/docker/derive.ts +5 -19
- package/src/docker/docker.test.ts +15 -15
- package/src/docker/dockerfile.integration.test.ts +12 -21
- package/src/docker/helpers.ts +5 -4
- package/src/docker/index.ts +4 -11
- package/src/docker/pin.ts +1 -9
- package/src/docker/recipes/index.ts +5 -6
- package/src/docker/recipes/mailpit.ts +22 -0
- package/src/docker/recipes/postgres.ts +17 -6
- package/src/docker/recipes/redis.ts +6 -1
- package/src/docker/recipes/rustfs.ts +33 -0
- package/src/docker/stack-id.test.ts +33 -0
- package/src/docker/stack-id.ts +25 -13
- package/src/docker/stack.integration.test.ts +6 -21
- package/src/docker/types.ts +13 -4
- package/src/drivers/ai-anthropic.ts +5 -14
- package/src/drivers/ai-mock.ts +2 -5
- package/src/drivers/ai-openai-compatible.ts +4 -10
- package/src/drivers/ai-providers.test.ts +6 -13
- package/src/drivers/bun-native-completeness.test.ts +6 -15
- package/src/drivers/channel-console.ts +6 -7
- package/src/drivers/channel-fcm.ts +20 -30
- package/src/drivers/channel-resend.ts +1 -3
- package/src/drivers/channel-smtp.ts +2 -6
- package/src/drivers/channel-types.ts +2 -12
- package/src/drivers/channel-unifonic.ts +2 -6
- package/src/drivers/channel-wa-cloud.ts +2 -6
- package/src/drivers/channel-webpush.ts +21 -60
- package/src/drivers/conformance.test.ts +2 -10
- package/src/drivers/conformance.ts +8 -21
- package/src/drivers/fs.ts +2 -8
- package/src/drivers/index.ts +12 -56
- package/src/drivers/memory.ts +14 -41
- package/src/drivers/pgvector.ts +7 -11
- package/src/drivers/postgres.ts +7 -13
- package/src/drivers/redis.ts +13 -37
- package/src/drivers/s3.ts +5 -17
- package/src/drivers/signal-engine.ts +12 -49
- package/src/drivers/signal-memory.ts +2 -8
- package/src/drivers/signal-nats.ts +4 -9
- package/src/drivers/signal-postgres.ts +62 -129
- package/src/drivers/signal-redis.ts +7 -21
- package/src/drivers/signal-types.ts +1 -4
- package/src/drivers/sqlite.ts +3 -12
- package/src/drivers/types.ts +4 -23
- package/src/drivers/vault-env.ts +2 -6
- package/src/drivers/vault-infisical.ts +1 -5
- package/src/drivers/vault-managed.ts +1 -5
- package/src/drivers/vault-memory.ts +1 -5
- package/src/drivers/vault-openbao.ts +1 -5
- package/src/drivers/vault-sops.ts +10 -35
- package/src/drivers/vault-types.ts +1 -7
- package/src/elements/ai/declare.ts +4 -14
- package/src/elements/ai/eval.ts +2 -6
- package/src/elements/ai/pii.ts +1 -3
- package/src/elements/ai/runtime.ts +12 -50
- package/src/elements/ai/schema.ts +4 -15
- package/src/elements/ai.test.ts +13 -24
- package/src/elements/ai.ts +1 -5
- package/src/elements/channel/consent.ts +3 -12
- package/src/elements/channel/costs.ts +4 -15
- package/src/elements/channel/declare.ts +1 -4
- package/src/elements/channel/email-auth.ts +1 -4
- package/src/elements/channel/locale.ts +2 -10
- package/src/elements/channel/mask.ts +1 -3
- package/src/elements/channel/mime.ts +2 -12
- package/src/elements/channel/outcomes.test.ts +1 -5
- package/src/elements/channel/outcomes.ts +5 -15
- package/src/elements/channel/receipts.ts +2 -7
- package/src/elements/channel/runtime.ts +28 -74
- package/src/elements/channel/suppression.ts +8 -14
- package/src/elements/channel.test.ts +8 -31
- package/src/elements/channel.ts +3 -14
- package/src/elements/clock/actions.ts +6 -18
- package/src/elements/clock/declare.ts +1 -3
- package/src/elements/clock/dst.ts +1 -5
- package/src/elements/clock/durable.ts +4 -16
- package/src/elements/clock/health.ts +2 -7
- package/src/elements/clock/leader.ts +2 -9
- package/src/elements/clock/reconcile.ts +4 -15
- package/src/elements/clock/runtime.ts +2 -5
- package/src/elements/clock/schedule.ts +4 -20
- package/src/elements/clock.test.ts +2 -7
- package/src/elements/clock.ts +5 -23
- package/src/elements/gate/permissions.ts +1 -4
- package/src/elements/gate/runtime.ts +7 -28
- package/src/elements/gate.ts +1 -5
- package/src/elements/index.ts +9 -7
- package/src/elements/signal/declare.ts +2 -7
- package/src/elements/signal/reconcile.test.ts +1 -4
- package/src/elements/signal/runtime.ts +1 -3
- package/src/elements/signal.test.ts +3 -15
- package/src/elements/signal.ts +2 -8
- package/src/elements/store/cache.test.ts +46 -0
- package/src/elements/store/cache.ts +3 -11
- package/src/elements/store/classify.ts +5 -22
- package/src/elements/store/declare.ts +8 -17
- package/src/elements/store/domain-ddl.test.ts +86 -0
- package/src/elements/store/emit-drizzle.ts +363 -0
- package/src/elements/store/files-policy.test.ts +1 -5
- package/src/elements/store/files-policy.ts +4 -12
- package/src/elements/store/load-plugin-tables.ts +103 -0
- package/src/elements/store/missing-relation.test.ts +83 -0
- package/src/elements/store/missing-relation.ts +38 -0
- package/src/elements/store/replica.ts +1 -4
- package/src/elements/store/runtime.ts +25 -28
- package/src/elements/store/schema-decl.test.ts +227 -0
- package/src/elements/store/schema-decl.ts +516 -0
- package/src/elements/store/sql-condition.ts +11 -21
- package/src/elements/store/sql-session.test.ts +50 -0
- package/src/elements/store/sql-session.ts +60 -63
- package/src/elements/store/table.ts +35 -19
- package/src/elements/store.test.ts +17 -39
- package/src/elements/store.ts +37 -31
- package/src/elements/vault/chain.ts +34 -0
- package/src/elements/vault/declare.ts +22 -32
- package/src/elements/vault/fingerprint.ts +2 -7
- package/src/elements/vault/redact.ts +2 -6
- package/src/elements/vault/runtime.ts +18 -32
- package/src/elements/vault.test.ts +12 -28
- package/src/elements/vault.ts +8 -12
- package/src/index.ts +5 -2
- package/src/kernel/adopt-routes.ts +15 -29
- package/src/kernel/app.ts +34 -94
- package/src/kernel/auth-resolve.ts +2 -9
- package/src/kernel/boot-bind/ai.ts +1 -4
- package/src/kernel/boot-bind/channel.ts +2 -8
- package/src/kernel/boot-bind/clock.ts +2 -6
- package/src/kernel/boot-bind/gate.ts +2 -8
- package/src/kernel/boot-bind/runs.ts +1 -3
- package/src/kernel/boot-bind/signal.ts +3 -10
- package/src/kernel/boot-bind/store.test.ts +17 -17
- package/src/kernel/boot-bind/store.ts +44 -50
- package/src/kernel/boot-bind/vault.ts +2 -8
- package/src/kernel/boot.test.ts +4 -9
- package/src/kernel/boot.ts +29 -76
- package/src/kernel/budget.test.ts +1 -3
- package/src/kernel/capability.ts +3 -10
- package/src/kernel/dry-run.test.ts +1 -4
- package/src/kernel/dry-run.ts +3 -11
- package/src/kernel/effects.test.ts +1 -5
- package/src/kernel/effects.ts +4 -11
- package/src/kernel/errors.registry.test.ts +2 -8
- package/src/kernel/errors.ts +23 -32
- package/src/kernel/flow.test.ts +12 -25
- package/src/kernel/flow.ts +5 -25
- package/src/kernel/fx.test.ts +15 -44
- package/src/kernel/fx.ts +27 -79
- package/src/kernel/hook-timing.test.ts +3 -6
- package/src/kernel/hook-timing.ts +5 -14
- package/src/kernel/hooks.test.ts +10 -10
- package/src/kernel/hooks.ts +3 -12
- package/src/kernel/index.ts +4 -17
- package/src/kernel/journal.ts +7 -31
- package/src/kernel/on.ts +1 -6
- package/src/kernel/pipeline.test.ts +10 -19
- package/src/kernel/pipeline.ts +5 -17
- package/src/kernel/plug.ts +4 -11
- package/src/kernel/plugin/conflicts.test.ts +13 -25
- package/src/kernel/plugin/decorate.test.ts +8 -13
- package/src/kernel/plugin/scoping.test.ts +4 -11
- package/src/kernel/plugin.ts +48 -24
- package/src/kernel/registry.ts +80 -29
- package/src/kernel/router.test.ts +15 -13
- package/src/kernel/router.ts +9 -29
- package/src/kernel/routing-budget.test.ts +1 -3
- package/src/kernel/run-telemetry.ts +1 -3
- package/src/kernel/triggers.ts +4 -21
- package/src/manifest/diff.test.ts +26 -91
- package/src/manifest/diff.ts +95 -225
- package/src/manifest/index.ts +2 -9
- package/src/manifest/types.ts +29 -5
- package/src/manifest/undeclared.test.ts +4 -12
- package/src/manifest/undeclared.ts +1 -2
- package/src/manifest/validate.test.ts +2 -6
- package/src/manifest/validate.ts +4 -14
- package/src/mcp/authorization.ts +8 -27
- package/src/mcp/confirmation.ts +3 -10
- package/src/mcp/data.ts +2 -6
- package/src/mcp/docs-index.ts +4 -7
- package/src/mcp/docs-mcp.test.ts +3 -12
- package/src/mcp/docs-server.ts +7 -27
- package/src/mcp/docs-tools.ts +2 -6
- package/src/mcp/index.ts +1 -6
- package/src/mcp/injection.gate.test.ts +4 -18
- package/src/mcp/mcp.test.ts +18 -49
- package/src/mcp/protocol.ts +3 -10
- package/src/mcp/server.ts +11 -52
- package/src/mcp/session.ts +4 -14
- package/src/mcp/tools.ts +14 -50
- package/src/plugins/catalogue.test.ts +3 -7
- package/src/plugins/catalogue.ts +1 -3
- package/src/plugins/node-import-scan.ts +2 -5
- package/src/plugins/supply-chain.ts +5 -17
- package/src/release/exports.ts +3 -8
- package/src/release/measure.exports.test.ts +1 -3
- package/src/release/measure.ts +15 -43
- package/src/runs/bench.test.ts +1 -3
- package/src/runs/collect.ts +8 -25
- package/src/runs/drivers/clickhouse.ts +2 -9
- package/src/runs/drivers/files.ts +9 -31
- package/src/runs/drivers/memory.ts +5 -22
- package/src/runs/drivers/postgres.ts +8 -20
- package/src/runs/duckdb.ts +2 -8
- package/src/runs/index.ts +3 -14
- package/src/runs/outlier.ts +3 -10
- package/src/runs/parquet.ts +8 -26
- package/src/runs/privacy.ts +2 -8
- package/src/runs/runs.test.ts +3 -9
- package/src/runs/runtime.ts +7 -32
- package/src/runs/shred.ts +10 -29
- package/src/runs/types.ts +1 -4
- package/src/runtime/bun.ts +4 -15
- package/src/runtime/cold-start.bench.ts +1 -3
- package/src/runtime/dev-request-log.test.ts +1 -4
- package/src/runtime/dev-request-log.ts +1 -4
- package/src/runtime/index.ts +1 -6
- package/src/runtime/primitives.ts +5 -4
- package/src/runtime/security.ts +3 -13
- package/src/runtime/serve.test.ts +4 -7
- package/src/runtime/types.ts +1 -4
- package/src/runtime/web-standard.ts +3 -15
- package/src/term.test.ts +4 -6
- package/src/term.ts +49 -98
- package/src/test/create-test-app.test.ts +4 -14
- package/src/test/create-test-app.ts +13 -31
- package/src/test/provisions.integration.test.ts +3 -11
- package/src/upgrade/codemods.test.ts +25 -6
- package/src/upgrade/codemods.ts +116 -3
- package/src/validation/standard-schema.test.ts +2 -5
- package/src/validation/standard-schema.ts +13 -33
- package/src/console/ui/dist/assets/panel-vault-BbfWdox0.js +0 -1
package/src/docker/stack-id.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Per-project local stack identity — unique compose project + host ports.
|
|
3
3
|
*
|
|
4
|
-
* `oke dev --
|
|
4
|
+
* `oke dev --docker` must not share one `oke-dev` Postgres across every app on
|
|
5
5
|
* the machine. Identity is a stable short hash of the project cwd.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { createHash } from "node:crypto";
|
|
9
9
|
import { resolve } from "node:path";
|
|
10
10
|
import type { ServiceCredentials } from "./types.ts";
|
|
11
|
+
import { DEFAULT_DOCKER_DIR } from "./types.ts";
|
|
11
12
|
import { defaultHostPort, envPrefix } from "./helpers.ts";
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -16,10 +17,7 @@ import { defaultHostPort, envPrefix } from "./helpers.ts";
|
|
|
16
17
|
* @param cwd - Project root
|
|
17
18
|
*/
|
|
18
19
|
export function stackInstanceId(cwd: string): string {
|
|
19
|
-
return createHash("sha256")
|
|
20
|
-
.update(resolve(cwd))
|
|
21
|
-
.digest("hex")
|
|
22
|
-
.slice(0, 6);
|
|
20
|
+
return createHash("sha256").update(resolve(cwd)).digest("hex").slice(0, 6);
|
|
23
21
|
}
|
|
24
22
|
|
|
25
23
|
/**
|
|
@@ -31,6 +29,15 @@ export function stackAppSlug(cwd: string): string {
|
|
|
31
29
|
return `dev-${stackInstanceId(cwd)}`;
|
|
32
30
|
}
|
|
33
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Stable 0–999 offset derived from a stack instance id.
|
|
34
|
+
*
|
|
35
|
+
* @param instanceId - 6-hex stack id
|
|
36
|
+
*/
|
|
37
|
+
export function instancePortOffset(instanceId: string): number {
|
|
38
|
+
return Number.parseInt(instanceId.slice(0, 4), 16) % 1000;
|
|
39
|
+
}
|
|
40
|
+
|
|
34
41
|
/**
|
|
35
42
|
* Host port for a role, offset by instance id so two stacks can run at once.
|
|
36
43
|
*
|
|
@@ -43,7 +50,7 @@ export function hostPortForInstance(
|
|
|
43
50
|
containerPort: number,
|
|
44
51
|
instanceId: string,
|
|
45
52
|
): number {
|
|
46
|
-
const n =
|
|
53
|
+
const n = instancePortOffset(instanceId);
|
|
47
54
|
if (role === "store.sql") return 15_000 + n;
|
|
48
55
|
if (role === "store.kv") return 16_000 + n;
|
|
49
56
|
if (role === "signal") return 17_000 + n;
|
|
@@ -51,7 +58,7 @@ export function hostPortForInstance(
|
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
/**
|
|
54
|
-
* Parse role credentials from an existing `.env.
|
|
61
|
+
* Parse role credentials from an existing `.env.docker` body (reuse on restart).
|
|
55
62
|
*
|
|
56
63
|
* @param text - Dotenv contents
|
|
57
64
|
* @param roles - Roles to look up
|
|
@@ -91,7 +98,9 @@ export function parseStackCredentials(
|
|
|
91
98
|
}
|
|
92
99
|
|
|
93
100
|
/**
|
|
94
|
-
* Load credentials from
|
|
101
|
+
* Load credentials from `docker/.env.docker` when present.
|
|
102
|
+
*
|
|
103
|
+
* Soft-compat: also reads legacy project-root `.env.docker`.
|
|
95
104
|
*
|
|
96
105
|
* @param cwd - Project root
|
|
97
106
|
* @param roles - Image roles
|
|
@@ -100,9 +109,12 @@ export async function loadExistingStackCredentials(
|
|
|
100
109
|
cwd: string,
|
|
101
110
|
roles: readonly string[],
|
|
102
111
|
): Promise<Readonly<Record<string, ServiceCredentials>> | undefined> {
|
|
103
|
-
const
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
112
|
+
const candidates = [resolve(cwd, DEFAULT_DOCKER_DIR, ".env.docker"), resolve(cwd, ".env.docker")];
|
|
113
|
+
for (const path of candidates) {
|
|
114
|
+
const file = Bun.file(path);
|
|
115
|
+
if (!(await file.exists())) continue;
|
|
116
|
+
const parsed = parseStackCredentials(await file.text(), roles);
|
|
117
|
+
if (Object.keys(parsed).length > 0) return parsed;
|
|
118
|
+
}
|
|
119
|
+
return undefined;
|
|
108
120
|
}
|
|
@@ -6,11 +6,7 @@ import { describe, expect, test } from "bun:test";
|
|
|
6
6
|
import { mkdtemp, rm } from "node:fs/promises";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
8
8
|
import { join } from "node:path";
|
|
9
|
-
import {
|
|
10
|
-
deriveInfrastructure,
|
|
11
|
-
formatStackEnv,
|
|
12
|
-
writeDerivedFiles,
|
|
13
|
-
} from "./index.ts";
|
|
9
|
+
import { deriveInfrastructure, formatStackEnv, writeDerivedFiles } from "./index.ts";
|
|
14
10
|
|
|
15
11
|
async function dockerAvailable(): Promise<boolean> {
|
|
16
12
|
try {
|
|
@@ -24,7 +20,7 @@ async function dockerAvailable(): Promise<boolean> {
|
|
|
24
20
|
}
|
|
25
21
|
}
|
|
26
22
|
|
|
27
|
-
describe("oke dev --
|
|
23
|
+
describe("oke dev --docker postgres integration", () => {
|
|
28
24
|
test("compose brings up postgres and the app talks to it", async () => {
|
|
29
25
|
if (!(await dockerAvailable())) {
|
|
30
26
|
console.warn("skipping: docker daemon not available");
|
|
@@ -51,21 +47,12 @@ describe("oke dev --stack postgres integration", () => {
|
|
|
51
47
|
});
|
|
52
48
|
await writeDerivedFiles(derived, dockerDir, {
|
|
53
49
|
writeStackEnv: true,
|
|
54
|
-
stackEnvDir: dir,
|
|
55
50
|
});
|
|
56
51
|
|
|
57
52
|
// Infra-only: network + role compose (no app build).
|
|
58
53
|
const composeFiles = ["compose.yml", "compose.store.sql.yml"];
|
|
59
54
|
const up = Bun.spawn(
|
|
60
|
-
[
|
|
61
|
-
"docker",
|
|
62
|
-
"compose",
|
|
63
|
-
"-p",
|
|
64
|
-
project,
|
|
65
|
-
...composeFiles.flatMap((f) => ["-f", f]),
|
|
66
|
-
"up",
|
|
67
|
-
"-d",
|
|
68
|
-
],
|
|
55
|
+
["docker", "compose", "-p", project, ...composeFiles.flatMap((f) => ["-f", f]), "up", "-d"],
|
|
69
56
|
{
|
|
70
57
|
cwd: dockerDir,
|
|
71
58
|
stdout: "pipe",
|
|
@@ -120,13 +107,11 @@ describe("oke dev --stack postgres integration", () => {
|
|
|
120
107
|
await sql.close();
|
|
121
108
|
}
|
|
122
109
|
|
|
123
|
-
// Prove credentials live in
|
|
110
|
+
// Prove credentials live in docker/.env.docker, not YAML.
|
|
124
111
|
const yml = await Bun.file(join(dockerDir, "compose.store.sql.yml")).text();
|
|
125
112
|
expect(yml).not.toContain("stack-integration-pass");
|
|
126
|
-
expect(formatStackEnv(derived.stackEnv)).toContain(
|
|
127
|
-
|
|
128
|
-
);
|
|
129
|
-
expect(await Bun.file(join(dir, ".env.stack")).exists()).toBe(true);
|
|
113
|
+
expect(formatStackEnv(derived.stackEnv)).toContain("stack-integration-pass");
|
|
114
|
+
expect(await Bun.file(join(dockerDir, ".env.docker")).exists()).toBe(true);
|
|
130
115
|
} finally {
|
|
131
116
|
await Bun.spawn(
|
|
132
117
|
[
|
package/src/docker/types.ts
CHANGED
|
@@ -37,7 +37,7 @@ export interface ServiceSpec {
|
|
|
37
37
|
readonly port: number;
|
|
38
38
|
/** Host port published in compose (dev defaults). */
|
|
39
39
|
readonly hostPort: number;
|
|
40
|
-
/** Credential placeholders (values live in `.env.
|
|
40
|
+
/** Credential placeholders (values live in `.env.docker`, not YAML). */
|
|
41
41
|
readonly credentials: ServiceCredentials;
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -50,6 +50,12 @@ export interface ComposeHealthcheck {
|
|
|
50
50
|
readonly start_period?: string;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
/** Extra published host↔container port pair from a recipe. */
|
|
54
|
+
export interface RecipeExtraPort {
|
|
55
|
+
readonly host: number;
|
|
56
|
+
readonly container: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
53
59
|
/** Image-specific compose fragment from {@link ImageRecipe.apply}. */
|
|
54
60
|
export interface RecipeApplyResult {
|
|
55
61
|
readonly environment?: Readonly<Record<string, string>>;
|
|
@@ -57,6 +63,8 @@ export interface RecipeApplyResult {
|
|
|
57
63
|
readonly healthcheck?: ComposeHealthcheck;
|
|
58
64
|
readonly volumes?: readonly string[];
|
|
59
65
|
readonly user?: string;
|
|
66
|
+
/** Additional published ports (e.g. Mailpit UI, RustFS console). */
|
|
67
|
+
readonly extraPorts?: readonly RecipeExtraPort[];
|
|
60
68
|
}
|
|
61
69
|
|
|
62
70
|
/**
|
|
@@ -102,12 +110,13 @@ export interface DeriveOptions {
|
|
|
102
110
|
readonly prod?: boolean;
|
|
103
111
|
/**
|
|
104
112
|
* Include the `app` service in `compose.yml` (default true).
|
|
105
|
-
* `oke dev --
|
|
113
|
+
* `oke dev --docker` sets false — host Bun runs the app; Docker is infra only.
|
|
106
114
|
*/
|
|
107
115
|
readonly includeApp?: boolean;
|
|
108
116
|
/**
|
|
109
117
|
* Compose artefact directory relative to the project root (default `docker`).
|
|
110
|
-
* Controls generated `env_file` / `build.context` paths (
|
|
118
|
+
* Controls generated `env_file` / `build.context` paths (`.env.docker` lives
|
|
119
|
+
* beside compose under this directory).
|
|
111
120
|
* Pass `"."` for legacy root-level layout.
|
|
112
121
|
*/
|
|
113
122
|
readonly composeDir?: string;
|
|
@@ -144,7 +153,7 @@ export interface DeriveResult {
|
|
|
144
153
|
/** Generated files (Dockerfile + compose layers). */
|
|
145
154
|
readonly files: readonly GeneratedFile[];
|
|
146
155
|
/**
|
|
147
|
-
* Stack env contents for `.env.
|
|
156
|
+
* Stack env contents for `.env.docker` — written by `oke dev --docker`,
|
|
148
157
|
* never embedded in YAML.
|
|
149
158
|
*/
|
|
150
159
|
readonly stackEnv: Readonly<Record<string, string>>;
|
|
@@ -21,9 +21,7 @@ const ANTHROPIC_VERSION = "2023-06-01";
|
|
|
21
21
|
*
|
|
22
22
|
* @param options - API key / model / base URL / injectable fetch
|
|
23
23
|
*/
|
|
24
|
-
export async function openAnthropic(
|
|
25
|
-
options: AiOpenOptions = {},
|
|
26
|
-
): Promise<AiModelClient> {
|
|
24
|
+
export async function openAnthropic(options: AiOpenOptions = {}): Promise<AiModelClient> {
|
|
27
25
|
const apiKey = options.apiKey ?? process.env.ANTHROPIC_API_KEY;
|
|
28
26
|
if (!apiKey) {
|
|
29
27
|
throw new Error("anthropic: apiKey is required (or ANTHROPIC_API_KEY)");
|
|
@@ -48,17 +46,14 @@ export async function openAnthropic(
|
|
|
48
46
|
body: JSON.stringify({
|
|
49
47
|
model: resolvedModel,
|
|
50
48
|
max_tokens: opts.maxTokens ?? 1024,
|
|
51
|
-
...(opts.temperature !== undefined
|
|
52
|
-
? { temperature: opts.temperature }
|
|
53
|
-
: {}),
|
|
49
|
+
...(opts.temperature !== undefined ? { temperature: opts.temperature } : {}),
|
|
54
50
|
...(system !== undefined ? { system } : {}),
|
|
55
51
|
messages,
|
|
56
52
|
}),
|
|
57
53
|
});
|
|
58
54
|
const raw = (await res.json().catch(() => ({}))) as AnthropicMessagesResponse;
|
|
59
55
|
if (!res.ok) {
|
|
60
|
-
const msg =
|
|
61
|
-
raw.error?.message ?? `anthropic HTTP ${res.status}`;
|
|
56
|
+
const msg = raw.error?.message ?? `anthropic HTTP ${res.status}`;
|
|
62
57
|
throw new Error(`anthropic: ${msg}`);
|
|
63
58
|
}
|
|
64
59
|
const text = textFromContent(raw.content);
|
|
@@ -92,9 +87,7 @@ interface AnthropicMessagesResponse {
|
|
|
92
87
|
readonly error?: { readonly message?: string };
|
|
93
88
|
}
|
|
94
89
|
|
|
95
|
-
function splitSystem(
|
|
96
|
-
messages: AiCompleteOptions["messages"],
|
|
97
|
-
): {
|
|
90
|
+
function splitSystem(messages: AiCompleteOptions["messages"]): {
|
|
98
91
|
system?: string;
|
|
99
92
|
messages: Array<{ role: "user" | "assistant"; content: string }>;
|
|
100
93
|
} {
|
|
@@ -117,9 +110,7 @@ function splitSystem(
|
|
|
117
110
|
};
|
|
118
111
|
}
|
|
119
112
|
|
|
120
|
-
function textFromContent(
|
|
121
|
-
content: AnthropicMessagesResponse["content"],
|
|
122
|
-
): string {
|
|
113
|
+
function textFromContent(content: AnthropicMessagesResponse["content"]): string {
|
|
123
114
|
if (!content?.length) return "";
|
|
124
115
|
return content
|
|
125
116
|
.filter((b) => b.type === "text" && typeof b.text === "string")
|
package/src/drivers/ai-mock.ts
CHANGED
|
@@ -39,8 +39,7 @@ export const mockAiDriver: AiDriver = {
|
|
|
39
39
|
if (payload === undefined) {
|
|
40
40
|
payload = canned["*"] ?? { ok: true, echo: last };
|
|
41
41
|
}
|
|
42
|
-
const text =
|
|
43
|
-
typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
42
|
+
const text = typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
44
43
|
return {
|
|
45
44
|
text,
|
|
46
45
|
raw: payload,
|
|
@@ -70,9 +69,7 @@ export const mockAiDriver: AiDriver = {
|
|
|
70
69
|
*
|
|
71
70
|
* @param responses - Key → JSON payload
|
|
72
71
|
*/
|
|
73
|
-
export function createMockAiDriver(
|
|
74
|
-
responses: Readonly<Record<string, unknown>>,
|
|
75
|
-
): AiDriver {
|
|
72
|
+
export function createMockAiDriver(responses: Readonly<Record<string, unknown>>): AiDriver {
|
|
76
73
|
return {
|
|
77
74
|
id: "mock",
|
|
78
75
|
open(options = {}) {
|
|
@@ -23,14 +23,10 @@ const DEFAULT_BASE = "https://api.openai.com/v1";
|
|
|
23
23
|
*
|
|
24
24
|
* @param options - API key / model / base URL / injectable fetch
|
|
25
25
|
*/
|
|
26
|
-
export async function openOpenaiCompatible(
|
|
27
|
-
options: AiOpenOptions = {},
|
|
28
|
-
): Promise<AiModelClient> {
|
|
26
|
+
export async function openOpenaiCompatible(options: AiOpenOptions = {}): Promise<AiModelClient> {
|
|
29
27
|
const apiKey = options.apiKey ?? process.env.OPENAI_API_KEY;
|
|
30
28
|
if (!apiKey) {
|
|
31
|
-
throw new Error(
|
|
32
|
-
"openai-compatible: apiKey is required (or OPENAI_API_KEY)",
|
|
33
|
-
);
|
|
29
|
+
throw new Error("openai-compatible: apiKey is required (or OPENAI_API_KEY)");
|
|
34
30
|
}
|
|
35
31
|
const model = options.model ?? "gpt-4o-mini";
|
|
36
32
|
const baseUrl = (options.baseUrl ?? DEFAULT_BASE).replace(/\/$/, "");
|
|
@@ -65,8 +61,7 @@ export async function openOpenaiCompatible(
|
|
|
65
61
|
});
|
|
66
62
|
const raw = (await res.json().catch(() => ({}))) as OpenAiChatResponse;
|
|
67
63
|
if (!res.ok) {
|
|
68
|
-
const msg =
|
|
69
|
-
raw.error?.message ?? `openai-compatible HTTP ${res.status}`;
|
|
64
|
+
const msg = raw.error?.message ?? `openai-compatible HTTP ${res.status}`;
|
|
70
65
|
throw new Error(`openai-compatible: ${msg}`);
|
|
71
66
|
}
|
|
72
67
|
const text = raw.choices?.[0]?.message?.content ?? "";
|
|
@@ -94,8 +89,7 @@ export async function openOpenaiCompatible(
|
|
|
94
89
|
});
|
|
95
90
|
const raw = (await res.json().catch(() => ({}))) as OpenAiEmbedResponse;
|
|
96
91
|
if (!res.ok) {
|
|
97
|
-
const msg =
|
|
98
|
-
raw.error?.message ?? `openai-compatible embed HTTP ${res.status}`;
|
|
92
|
+
const msg = raw.error?.message ?? `openai-compatible embed HTTP ${res.status}`;
|
|
99
93
|
throw new Error(`openai-compatible: ${msg}`);
|
|
100
94
|
}
|
|
101
95
|
const vectors = (raw.data ?? [])
|
|
@@ -4,10 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { describe, expect, test } from "bun:test";
|
|
6
6
|
import { anthropicAiDriver, openAnthropic } from "./ai-anthropic.ts";
|
|
7
|
-
import {
|
|
8
|
-
openaiCompatibleAiDriver,
|
|
9
|
-
openOpenaiCompatible,
|
|
10
|
-
} from "./ai-openai-compatible.ts";
|
|
7
|
+
import { openaiCompatibleAiDriver, openOpenaiCompatible } from "./ai-openai-compatible.ts";
|
|
11
8
|
import { mockAiDriver } from "./ai-mock.ts";
|
|
12
9
|
|
|
13
10
|
describe("anthropic driver", () => {
|
|
@@ -56,9 +53,7 @@ describe("anthropic driver", () => {
|
|
|
56
53
|
messages: Array<{ role: string }>;
|
|
57
54
|
};
|
|
58
55
|
expect(body.system).toBe("be brief");
|
|
59
|
-
expect(body.messages).toEqual([
|
|
60
|
-
{ role: "user", content: "hi" } as { role: string },
|
|
61
|
-
]);
|
|
56
|
+
expect(body.messages).toEqual([{ role: "user", content: "hi" } as { role: string }]);
|
|
62
57
|
});
|
|
63
58
|
|
|
64
59
|
test("HTTP error surfaces provider message", async () => {
|
|
@@ -73,18 +68,16 @@ describe("anthropic driver", () => {
|
|
|
73
68
|
apiKey: "sk-test",
|
|
74
69
|
fetch: fetchFn,
|
|
75
70
|
});
|
|
76
|
-
await expect(
|
|
77
|
-
|
|
78
|
-
)
|
|
71
|
+
await expect(client.complete({ messages: [{ role: "user", content: "x" }] })).rejects.toThrow(
|
|
72
|
+
"rate limited",
|
|
73
|
+
);
|
|
79
74
|
});
|
|
80
75
|
|
|
81
76
|
test("live Anthropic ask when ANTHROPIC_API_KEY is set", async () => {
|
|
82
77
|
const key = process.env.ANTHROPIC_API_KEY;
|
|
83
78
|
if (!key) {
|
|
84
79
|
// Clearly-marked skip — never fail CI for lack of credentials.
|
|
85
|
-
console.log(
|
|
86
|
-
"skip: live anthropic ask (ANTHROPIC_API_KEY not set)",
|
|
87
|
-
);
|
|
80
|
+
console.log("skip: live anthropic ask (ANTHROPIC_API_KEY not set)");
|
|
88
81
|
return;
|
|
89
82
|
}
|
|
90
83
|
const client = await anthropicAiDriver.open({
|
|
@@ -7,10 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { describe, expect, test } from "bun:test";
|
|
9
9
|
import { createBunRedisClient } from "./redis.ts";
|
|
10
|
-
import {
|
|
11
|
-
createBunSignalRedisClient,
|
|
12
|
-
parseXreadgroupReply,
|
|
13
|
-
} from "./signal-redis.ts";
|
|
10
|
+
import { createBunSignalRedisClient, parseXreadgroupReply } from "./signal-redis.ts";
|
|
14
11
|
|
|
15
12
|
/** One row in the completeness report. */
|
|
16
13
|
export interface BunNativeGapRow {
|
|
@@ -26,10 +23,7 @@ export interface BunNativeGapRow {
|
|
|
26
23
|
* Kept as a pure function so the gate test and human report share one source.
|
|
27
24
|
*/
|
|
28
25
|
export function bunNativeCompletenessReport(): readonly BunNativeGapRow[] {
|
|
29
|
-
const redisProto = Bun.RedisClient.prototype as unknown as Record<
|
|
30
|
-
string,
|
|
31
|
-
unknown
|
|
32
|
-
>;
|
|
26
|
+
const redisProto = Bun.RedisClient.prototype as unknown as Record<string, unknown>;
|
|
33
27
|
const hasTypedScan = typeof redisProto.scan === "function";
|
|
34
28
|
const hasTypedPublish = typeof redisProto.publish === "function";
|
|
35
29
|
const hasTypedSubscribe = typeof redisProto.subscribe === "function";
|
|
@@ -57,8 +51,7 @@ export function bunNativeCompletenessReport(): readonly BunNativeGapRow[] {
|
|
|
57
51
|
{
|
|
58
52
|
surface: "redis signal",
|
|
59
53
|
capability: "native Bun bind (publish/subscribe)",
|
|
60
|
-
status:
|
|
61
|
-
hasTypedPublish && hasTypedSubscribe ? "closed" : "bun_limitation",
|
|
54
|
+
status: hasTypedPublish && hasTypedSubscribe ? "closed" : "bun_limitation",
|
|
62
55
|
note:
|
|
63
56
|
hasTypedPublish && hasTypedSubscribe
|
|
64
57
|
? "createBunSignalRedisClient uses typed publish/subscribe"
|
|
@@ -107,9 +100,7 @@ describe("Bun native client completeness", () => {
|
|
|
107
100
|
expect(rows.length).toBe(8);
|
|
108
101
|
|
|
109
102
|
const closed = rows.filter((r) => r.status === "closed").map((r) => r.capability);
|
|
110
|
-
const limited = rows
|
|
111
|
-
.filter((r) => r.status === "bun_limitation")
|
|
112
|
-
.map((r) => r.capability);
|
|
103
|
+
const limited = rows.filter((r) => r.status === "bun_limitation").map((r) => r.capability);
|
|
113
104
|
|
|
114
105
|
// Closed on Bun 1.3.14
|
|
115
106
|
expect(closed).toContain("SCAN (typed)");
|
|
@@ -141,13 +132,13 @@ describe("Bun native client completeness", () => {
|
|
|
141
132
|
[
|
|
142
133
|
"oke:signal:order",
|
|
143
134
|
[
|
|
144
|
-
["1-0", ["payload",
|
|
135
|
+
["1-0", ["payload", '{"a":1}', "signal", "order"]],
|
|
145
136
|
["1-1", ["payload", "{}", "signal", "order"]],
|
|
146
137
|
],
|
|
147
138
|
],
|
|
148
139
|
]);
|
|
149
140
|
expect(parsed).toEqual([
|
|
150
|
-
{ id: "1-0", fields: { payload:
|
|
141
|
+
{ id: "1-0", fields: { payload: '{"a":1}', signal: "order" } },
|
|
151
142
|
{ id: "1-1", fields: { payload: "{}", signal: "order" } },
|
|
152
143
|
]);
|
|
153
144
|
expect(parseXreadgroupReply(null)).toEqual([]);
|
|
@@ -21,9 +21,7 @@ import { createChannelInbox } from "./channel-types.ts";
|
|
|
21
21
|
function formatAddressInput(input: AddressInput): string {
|
|
22
22
|
if (typeof input === "string") return input;
|
|
23
23
|
if (Array.isArray(input)) {
|
|
24
|
-
return input
|
|
25
|
-
.map((t) => (typeof t === "string" ? t : t.address))
|
|
26
|
-
.join(",");
|
|
24
|
+
return input.map((t) => (typeof t === "string" ? t : t.address)).join(",");
|
|
27
25
|
}
|
|
28
26
|
return input.address;
|
|
29
27
|
}
|
|
@@ -33,9 +31,7 @@ function formatAddressInput(input: AddressInput): string {
|
|
|
33
31
|
*
|
|
34
32
|
* @param options - Optional shared inbox
|
|
35
33
|
*/
|
|
36
|
-
export function openConsoleChannel(
|
|
37
|
-
options: ChannelOpenOptions = {},
|
|
38
|
-
): ChannelDriver {
|
|
34
|
+
export function openConsoleChannel(options: ChannelOpenOptions = {}): ChannelDriver {
|
|
39
35
|
const inbox = options.inbox ?? createChannelInbox();
|
|
40
36
|
|
|
41
37
|
const channel: ChannelTransport = {
|
|
@@ -88,7 +84,10 @@ export function openConsoleChannel(
|
|
|
88
84
|
template: mail.template,
|
|
89
85
|
at: Date.now(),
|
|
90
86
|
});
|
|
91
|
-
const recipients = to
|
|
87
|
+
const recipients = to
|
|
88
|
+
.split(",")
|
|
89
|
+
.map((s) => s.trim())
|
|
90
|
+
.filter(Boolean);
|
|
92
91
|
return {
|
|
93
92
|
messageId: id,
|
|
94
93
|
accepted: recipients,
|
|
@@ -15,9 +15,7 @@ import type {
|
|
|
15
15
|
*
|
|
16
16
|
* @param options - `token` (OAuth access token) + `from` (project id)
|
|
17
17
|
*/
|
|
18
|
-
export function openFcmChannel(
|
|
19
|
-
options: ChannelOpenOptions = {},
|
|
20
|
-
): ChannelDriver {
|
|
18
|
+
export function openFcmChannel(options: ChannelOpenOptions = {}): ChannelDriver {
|
|
21
19
|
const accessToken = options.token ?? options.apiKey;
|
|
22
20
|
const projectId = options.from;
|
|
23
21
|
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
@@ -30,31 +28,25 @@ export function openFcmChannel(
|
|
|
30
28
|
if (!accessToken || !projectId) {
|
|
31
29
|
throw new Error("fcm: token and from (project id) are required");
|
|
32
30
|
}
|
|
33
|
-
const res = await fetchFn(
|
|
34
|
-
|
|
35
|
-
{
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
Authorization: `Bearer ${accessToken}`,
|
|
39
|
-
"Content-Type": "application/json",
|
|
40
|
-
},
|
|
41
|
-
body: JSON.stringify({
|
|
42
|
-
message: {
|
|
43
|
-
token: message.to,
|
|
44
|
-
notification: {
|
|
45
|
-
title: message.subject ?? message.template ?? "notification",
|
|
46
|
-
body: message.text ?? "",
|
|
47
|
-
},
|
|
48
|
-
data: Object.fromEntries(
|
|
49
|
-
Object.entries(message.data ?? {}).map(([k, v]) => [
|
|
50
|
-
k,
|
|
51
|
-
String(v),
|
|
52
|
-
]),
|
|
53
|
-
),
|
|
54
|
-
},
|
|
55
|
-
}),
|
|
31
|
+
const res = await fetchFn(`${base}/v1/projects/${projectId}/messages:send`, {
|
|
32
|
+
method: "POST",
|
|
33
|
+
headers: {
|
|
34
|
+
Authorization: `Bearer ${accessToken}`,
|
|
35
|
+
"Content-Type": "application/json",
|
|
56
36
|
},
|
|
57
|
-
|
|
37
|
+
body: JSON.stringify({
|
|
38
|
+
message: {
|
|
39
|
+
token: message.to,
|
|
40
|
+
notification: {
|
|
41
|
+
title: message.subject ?? message.template ?? "notification",
|
|
42
|
+
body: message.text ?? "",
|
|
43
|
+
},
|
|
44
|
+
data: Object.fromEntries(
|
|
45
|
+
Object.entries(message.data ?? {}).map(([k, v]) => [k, String(v)]),
|
|
46
|
+
),
|
|
47
|
+
},
|
|
48
|
+
}),
|
|
49
|
+
});
|
|
58
50
|
const body = (await res.json().catch(() => ({}))) as {
|
|
59
51
|
name?: string;
|
|
60
52
|
error?: { message?: string };
|
|
@@ -79,9 +71,7 @@ export function openFcmChannel(
|
|
|
79
71
|
ok: true,
|
|
80
72
|
messageId: id,
|
|
81
73
|
driverId: "fcm",
|
|
82
|
-
attempts: [
|
|
83
|
-
{ driverId: "fcm", ok: true, at: Date.now(), messageId: id },
|
|
84
|
-
],
|
|
74
|
+
attempts: [{ driverId: "fcm", ok: true, at: Date.now(), messageId: id }],
|
|
85
75
|
};
|
|
86
76
|
},
|
|
87
77
|
};
|
|
@@ -10,9 +10,7 @@ import type { ChannelDriver, ChannelOpenOptions } from "./channel-types.ts";
|
|
|
10
10
|
*
|
|
11
11
|
* @param options - API key
|
|
12
12
|
*/
|
|
13
|
-
export function openResendChannel(
|
|
14
|
-
options: ChannelOpenOptions = {},
|
|
15
|
-
): ChannelDriver {
|
|
13
|
+
export function openResendChannel(options: ChannelOpenOptions = {}): ChannelDriver {
|
|
16
14
|
if (!options.apiKey) {
|
|
17
15
|
throw new Error("resend channel: apiKey is required");
|
|
18
16
|
}
|
|
@@ -10,18 +10,14 @@ import type { ChannelDriver, ChannelOpenOptions } from "./channel-types.ts";
|
|
|
10
10
|
*
|
|
11
11
|
* @param options - Host / port / auth
|
|
12
12
|
*/
|
|
13
|
-
export function openSmtpChannel(
|
|
14
|
-
options: ChannelOpenOptions = {},
|
|
15
|
-
): ChannelDriver {
|
|
13
|
+
export function openSmtpChannel(options: ChannelOpenOptions = {}): ChannelDriver {
|
|
16
14
|
if (!options.host) {
|
|
17
15
|
throw new Error("smtp channel: host is required");
|
|
18
16
|
}
|
|
19
17
|
const transport = new SMTPTransport({
|
|
20
18
|
host: options.host,
|
|
21
19
|
port: options.port ?? 587,
|
|
22
|
-
...(options.user && options.pass
|
|
23
|
-
? { auth: { user: options.user, pass: options.pass } }
|
|
24
|
-
: {}),
|
|
20
|
+
...(options.user && options.pass ? { auth: { user: options.user, pass: options.pass } } : {}),
|
|
25
21
|
});
|
|
26
22
|
return { id: "smtp", transport };
|
|
27
23
|
}
|
|
@@ -5,12 +5,7 @@
|
|
|
5
5
|
* run unchanged. Non-email media (sms / whatsapp / push) use {@link ChannelTransport}.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type {
|
|
9
|
-
MailOptions,
|
|
10
|
-
SendResult,
|
|
11
|
-
Transport,
|
|
12
|
-
VerifyResult,
|
|
13
|
-
} from "sently";
|
|
8
|
+
import type { MailOptions, SendResult, Transport, VerifyResult } from "sently";
|
|
14
9
|
|
|
15
10
|
export type {
|
|
16
11
|
Address,
|
|
@@ -35,12 +30,7 @@ export type ChannelDriverId =
|
|
|
35
30
|
| "webpush";
|
|
36
31
|
|
|
37
32
|
/** Channel medium. */
|
|
38
|
-
export type ChannelMediumId =
|
|
39
|
-
| "email"
|
|
40
|
-
| "sms"
|
|
41
|
-
| "whatsapp"
|
|
42
|
-
| "push"
|
|
43
|
-
| "any";
|
|
33
|
+
export type ChannelMediumId = "email" | "sms" | "whatsapp" | "push" | "any";
|
|
44
34
|
|
|
45
35
|
/** Unified outbound message (medium-agnostic). */
|
|
46
36
|
export interface ChannelMessage {
|
|
@@ -15,9 +15,7 @@ import type {
|
|
|
15
15
|
*
|
|
16
16
|
* @param options - `apiKey` + optional `from` (sender id)
|
|
17
17
|
*/
|
|
18
|
-
export function openUnifonicChannel(
|
|
19
|
-
options: ChannelOpenOptions = {},
|
|
20
|
-
): ChannelDriver {
|
|
18
|
+
export function openUnifonicChannel(options: ChannelOpenOptions = {}): ChannelDriver {
|
|
21
19
|
const apiKey = options.apiKey;
|
|
22
20
|
const from = options.from ?? "OKE";
|
|
23
21
|
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
@@ -62,9 +60,7 @@ export function openUnifonicChannel(
|
|
|
62
60
|
ok: true,
|
|
63
61
|
messageId: id,
|
|
64
62
|
driverId: "unifonic",
|
|
65
|
-
attempts: [
|
|
66
|
-
{ driverId: "unifonic", ok: true, at: Date.now(), messageId: id },
|
|
67
|
-
],
|
|
63
|
+
attempts: [{ driverId: "unifonic", ok: true, at: Date.now(), messageId: id }],
|
|
68
64
|
};
|
|
69
65
|
},
|
|
70
66
|
};
|
|
@@ -15,9 +15,7 @@ import type {
|
|
|
15
15
|
*
|
|
16
16
|
* @param options - `token` (access token) + `from` (phone number id)
|
|
17
17
|
*/
|
|
18
|
-
export function openWaCloudChannel(
|
|
19
|
-
options: ChannelOpenOptions = {},
|
|
20
|
-
): ChannelDriver {
|
|
18
|
+
export function openWaCloudChannel(options: ChannelOpenOptions = {}): ChannelDriver {
|
|
21
19
|
const token = options.token ?? options.apiKey;
|
|
22
20
|
const phoneNumberId = options.from;
|
|
23
21
|
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
@@ -67,9 +65,7 @@ export function openWaCloudChannel(
|
|
|
67
65
|
ok: true,
|
|
68
66
|
messageId: id,
|
|
69
67
|
driverId: "wa-cloud",
|
|
70
|
-
attempts: [
|
|
71
|
-
{ driverId: "wa-cloud", ok: true, at: Date.now(), messageId: id },
|
|
72
|
-
],
|
|
68
|
+
attempts: [{ driverId: "wa-cloud", ok: true, at: Date.now(), messageId: id }],
|
|
73
69
|
};
|
|
74
70
|
},
|
|
75
71
|
};
|