@mysten-incubation/devstack 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/dashboard-ui/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/dashboard-ui/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/dashboard-ui/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dashboard-ui/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-cyrillic-ext-wght-normal-I4S5GZfc.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-cyrillic-wght-normal-BmXc_FBt.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-latin-ext-wght-normal-DrnZ1wKl.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-latin-wght-normal-B_7UjwxQ.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-symbols2-wght-normal-GZpp1pK2.woff2 +0 -0
- package/dashboard-ui/assets/geist-mono-vietnamese-wght-normal-D8KDMBhC.woff2 +0 -0
- package/dashboard-ui/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/dashboard-ui/assets/index-Bmi1UtAg.js +1356 -0
- package/dashboard-ui/assets/index-D5EShVt4.js +3 -0
- package/dashboard-ui/assets/index-Deml9drg.css +1 -0
- package/dashboard-ui/index.html +13 -0
- package/dist/api/define-capabilities.d.mts +14 -3
- package/dist/api/define-capabilities.mjs +18 -1
- package/dist/api/define-capabilities.mjs.map +1 -1
- package/dist/api/define-devstack.d.mts +1 -1
- package/dist/api/define-devstack.mjs +6 -26
- package/dist/api/define-devstack.mjs.map +1 -1
- package/dist/api/define-plugin.d.mts +1 -0
- package/dist/api/define-plugin.mjs +2 -0
- package/dist/api/inference-network.d.mts +132 -0
- package/dist/api/inference-network.mjs +105 -16
- package/dist/api/inference-network.mjs.map +1 -1
- package/dist/api/plugin-errors.d.mts +7 -0
- package/dist/api/run-stack.d.mts +20 -9
- package/dist/api/run-stack.mjs +56 -29
- package/dist/api/run-stack.mjs.map +1 -1
- package/dist/build-integrations/playwright/config.d.mts +6 -4
- package/dist/build-integrations/playwright/config.mjs +5 -3
- package/dist/build-integrations/playwright/config.mjs.map +1 -1
- package/dist/build-integrations/playwright/errors.d.mts +1 -1
- package/dist/build-integrations/playwright/global-setup.d.mts +43 -17
- package/dist/build-integrations/playwright/global-setup.mjs +250 -13
- package/dist/build-integrations/playwright/global-setup.mjs.map +1 -1
- package/dist/build-integrations/playwright/index.d.mts +5 -3
- package/dist/build-integrations/playwright/index.mjs +4 -2
- package/dist/build-integrations/playwright/stack-context.d.mts +0 -1
- package/dist/build-integrations/playwright/stack-context.mjs +24 -63
- package/dist/build-integrations/playwright/stack-context.mjs.map +1 -1
- package/dist/build-integrations/playwright/wallet-context.d.mts +7 -10
- package/dist/build-integrations/playwright/wallet-context.mjs +8 -13
- package/dist/build-integrations/playwright/wallet-context.mjs.map +1 -1
- package/dist/build-integrations/runtime/cold-start-url.d.mts +5 -0
- package/dist/build-integrations/runtime/cold-start-url.mjs +4 -3
- package/dist/build-integrations/runtime/cold-start-url.mjs.map +1 -1
- package/dist/build-integrations/runtime/conventional-routes.d.mts +51 -0
- package/dist/build-integrations/runtime/conventional-routes.mjs +92 -0
- package/dist/build-integrations/runtime/conventional-routes.mjs.map +1 -0
- package/dist/build-integrations/runtime/discover.d.mts +38 -30
- package/dist/build-integrations/runtime/discover.mjs +73 -70
- package/dist/build-integrations/runtime/discover.mjs.map +1 -1
- package/dist/build-integrations/runtime/endpoint-registry.d.mts +3 -1
- package/dist/build-integrations/runtime/endpoint-registry.mjs +3 -1
- package/dist/build-integrations/runtime/endpoint-registry.mjs.map +1 -1
- package/dist/build-integrations/runtime/index.d.mts +7 -2
- package/dist/build-integrations/runtime/index.mjs +9 -2
- package/dist/build-integrations/runtime/manifest-types.d.mts +2 -0
- package/dist/build-integrations/runtime/manifest-types.mjs +3 -0
- package/dist/build-integrations/runtime/playwright-stack-context-slot.d.mts +29 -0
- package/dist/build-integrations/runtime/playwright-stack-context-slot.mjs +10 -0
- package/dist/build-integrations/runtime/playwright-stack-context-slot.mjs.map +1 -0
- package/dist/build-integrations/runtime/read-stack-context.d.mts +1 -1
- package/dist/build-integrations/runtime/read-stack-context.mjs +10 -4
- package/dist/build-integrations/runtime/read-stack-context.mjs.map +1 -1
- package/dist/build-integrations/runtime/resolve-discovery-env.d.mts +48 -0
- package/dist/build-integrations/runtime/resolve-discovery-env.mjs +42 -0
- package/dist/build-integrations/runtime/resolve-discovery-env.mjs.map +1 -0
- package/dist/build-integrations/runtime/stack-context.d.mts +1 -1
- package/dist/build-integrations/runtime/wallet-paths.mjs +2 -0
- package/dist/build-integrations/vite/index.d.mts +51 -0
- package/dist/build-integrations/vite/index.mjs +73 -0
- package/dist/build-integrations/vite/index.mjs.map +1 -0
- package/dist/build-integrations/vitest/env.d.mts +4 -3
- package/dist/build-integrations/vitest/env.mjs +6 -4
- package/dist/build-integrations/vitest/env.mjs.map +1 -1
- package/dist/build-integrations/vitest/errors.d.mts +25 -4
- package/dist/build-integrations/vitest/errors.mjs +15 -2
- package/dist/build-integrations/vitest/errors.mjs.map +1 -1
- package/dist/build-integrations/vitest/index.d.mts +2 -2
- package/dist/build-integrations/vitest/index.mjs +3 -3
- package/dist/build-integrations/vitest/setup.d.mts +4 -2
- package/dist/build-integrations/vitest/setup.mjs +2 -2
- package/dist/build-integrations/vitest/setup.mjs.map +1 -1
- package/dist/build-integrations/vitest/stack-context.d.mts +0 -1
- package/dist/build-integrations/vitest/stack-context.mjs +33 -13
- package/dist/build-integrations/vitest/stack-context.mjs.map +1 -1
- package/dist/cli/bail.mjs +23 -0
- package/dist/cli/bail.mjs.map +1 -0
- package/dist/{surfaces/cli/commands → cli}/doctor-probes.mjs +26 -16
- package/dist/cli/doctor-probes.mjs.map +1 -0
- package/dist/cli/main.d.mts +15 -1
- package/dist/cli/main.mjs +166 -482
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/prune-direct.mjs +31 -201
- package/dist/cli/prune-direct.mjs.map +1 -1
- package/dist/cli/snapshot-reader.mjs +14 -11
- package/dist/cli/snapshot-reader.mjs.map +1 -1
- package/dist/cli/up-lifecycle.mjs +4 -1
- package/dist/cli/up-lifecycle.mjs.map +1 -1
- package/dist/cli/wirings/apply.mjs +95 -0
- package/dist/cli/wirings/apply.mjs.map +1 -0
- package/dist/cli/wirings/build-verb-layers.mjs +42 -0
- package/dist/cli/wirings/build-verb-layers.mjs.map +1 -0
- package/dist/cli/wirings/config-loader.mjs +69 -0
- package/dist/cli/wirings/config-loader.mjs.map +1 -0
- package/dist/cli/wirings/engine-command.mjs +30 -0
- package/dist/cli/wirings/engine-command.mjs.map +1 -0
- package/dist/cli/wirings/identity.mjs +72 -0
- package/dist/cli/wirings/identity.mjs.map +1 -0
- package/dist/cli/wirings/provide-file-system.mjs +7 -0
- package/dist/cli/wirings/provide-file-system.mjs.map +1 -0
- package/dist/cli/wirings/snapshot.mjs +177 -0
- package/dist/cli/wirings/snapshot.mjs.map +1 -0
- package/dist/cli/wirings/up.mjs +287 -0
- package/dist/cli/wirings/up.mjs.map +1 -0
- package/dist/cli/wirings/wipe.mjs +40 -0
- package/dist/cli/wirings/wipe.mjs.map +1 -0
- package/dist/contracts/capability-decl.d.mts +0 -2
- package/dist/contracts/codegenable.d.mts +43 -0
- package/dist/contracts/container-runtime.d.mts +26 -1
- package/dist/contracts/faucet-strategy.d.mts +25 -0
- package/dist/contracts/funding-strategy.d.mts +42 -0
- package/dist/contracts/plugin-expander.mjs +60 -0
- package/dist/contracts/plugin-expander.mjs.map +1 -0
- package/dist/contracts/projection.d.mts +5 -3
- package/dist/contracts/renderer.d.mts +23 -0
- package/dist/contracts/routable.d.mts +14 -1
- package/dist/contracts/snapshotable.d.mts +25 -3
- package/dist/contracts/wallet-protocol.d.mts +52 -0
- package/dist/contracts/wallet-protocol.mjs +52 -0
- package/dist/contracts/wallet-protocol.mjs.map +1 -0
- package/dist/index.d.mts +26 -25
- package/dist/index.mjs +20 -13
- package/dist/{runtime → orchestrators}/built-in-plugin-layers.mjs +10 -5
- package/dist/orchestrators/built-in-plugin-layers.mjs.map +1 -0
- package/dist/orchestrators/codegen/bindings.d.mts +1 -2
- package/dist/orchestrators/codegen/bindings.mjs +52 -186
- package/dist/orchestrators/codegen/bindings.mjs.map +1 -1
- package/dist/orchestrators/codegen/emit.mjs +19 -1
- package/dist/orchestrators/codegen/emit.mjs.map +1 -1
- package/dist/orchestrators/codegen/errors.mjs +8 -3
- package/dist/orchestrators/codegen/errors.mjs.map +1 -1
- package/dist/orchestrators/codegen/format.mjs +47 -39
- package/dist/orchestrators/codegen/format.mjs.map +1 -1
- package/dist/orchestrators/codegen/gitignore.mjs +3 -1
- package/dist/orchestrators/codegen/gitignore.mjs.map +1 -1
- package/dist/orchestrators/codegen/output-location.mjs +40 -0
- package/dist/orchestrators/codegen/output-location.mjs.map +1 -0
- package/dist/orchestrators/codegen/paths.d.mts +1 -1
- package/dist/orchestrators/codegen/paths.mjs +40 -14
- package/dist/orchestrators/codegen/paths.mjs.map +1 -1
- package/dist/orchestrators/codegen/permissions.mjs +3 -1
- package/dist/orchestrators/codegen/permissions.mjs.map +1 -1
- package/dist/orchestrators/codegen/service.mjs +157 -105
- package/dist/orchestrators/codegen/service.mjs.map +1 -1
- package/dist/orchestrators/lifecycle-prune/errors.mjs +31 -0
- package/dist/orchestrators/lifecycle-prune/errors.mjs.map +1 -0
- package/dist/orchestrators/lifecycle-prune/index.mjs +350 -0
- package/dist/orchestrators/lifecycle-prune/index.mjs.map +1 -0
- package/dist/orchestrators/router/cleanup.mjs +26 -27
- package/dist/orchestrators/router/cleanup.mjs.map +1 -1
- package/dist/orchestrators/router/entrypoints.mjs +2 -2
- package/dist/orchestrators/router/entrypoints.mjs.map +1 -1
- package/dist/orchestrators/router/file-provider.mjs +14 -5
- package/dist/orchestrators/router/file-provider.mjs.map +1 -1
- package/dist/orchestrators/router/hostname.mjs +19 -55
- package/dist/orchestrators/router/hostname.mjs.map +1 -1
- package/dist/orchestrators/router/index.mjs +11 -0
- package/dist/orchestrators/router/profile.mjs +2 -2
- package/dist/orchestrators/router/sentinels.mjs +26 -0
- package/dist/orchestrators/router/sentinels.mjs.map +1 -0
- package/dist/orchestrators/router/service.mjs +40 -37
- package/dist/orchestrators/router/service.mjs.map +1 -1
- package/dist/orchestrators/router/traefik-container.mjs +27 -16
- package/dist/orchestrators/router/traefik-container.mjs.map +1 -1
- package/dist/{substrate/runtime → orchestrators}/run.mjs +26 -21
- package/dist/orchestrators/run.mjs.map +1 -0
- package/dist/orchestrators/runtime-composition.d.mts +1 -1
- package/dist/orchestrators/runtime-composition.mjs +123 -39
- package/dist/orchestrators/runtime-composition.mjs.map +1 -1
- package/dist/orchestrators/snapshot/capture-command.d.mts +1 -0
- package/dist/orchestrators/snapshot/capture-command.mjs +25 -0
- package/dist/orchestrators/snapshot/capture-command.mjs.map +1 -0
- package/dist/orchestrators/snapshot/capture.mjs +42 -28
- package/dist/orchestrators/snapshot/capture.mjs.map +1 -1
- package/dist/orchestrators/snapshot/descriptor.mjs +35 -10
- package/dist/orchestrators/snapshot/descriptor.mjs.map +1 -1
- package/dist/orchestrators/snapshot/identity-guard.mjs +1 -1
- package/dist/orchestrators/snapshot/index.mjs +13 -0
- package/dist/orchestrators/snapshot/integrity.d.mts +1 -1
- package/dist/orchestrators/snapshot/integrity.mjs +73 -17
- package/dist/orchestrators/snapshot/integrity.mjs.map +1 -1
- package/dist/orchestrators/snapshot/pending-marker.d.mts +1 -0
- package/dist/orchestrators/snapshot/pending-marker.mjs +99 -0
- package/dist/orchestrators/snapshot/pending-marker.mjs.map +1 -0
- package/dist/orchestrators/snapshot/phase-error.mjs +23 -0
- package/dist/orchestrators/snapshot/phase-error.mjs.map +1 -0
- package/dist/orchestrators/snapshot/prune.mjs +20 -55
- package/dist/orchestrators/snapshot/prune.mjs.map +1 -1
- package/dist/orchestrators/snapshot/recover-pending.d.mts +1 -0
- package/dist/orchestrators/snapshot/recover-pending.mjs +223 -0
- package/dist/orchestrators/snapshot/recover-pending.mjs.map +1 -0
- package/dist/orchestrators/snapshot/restore.mjs +118 -84
- package/dist/orchestrators/snapshot/restore.mjs.map +1 -1
- package/dist/orchestrators/snapshot/service.mjs +53 -56
- package/dist/orchestrators/snapshot/service.mjs.map +1 -1
- package/dist/orchestrators/snapshot/state-document.d.mts +1 -0
- package/dist/orchestrators/snapshot/state-document.mjs +47 -7
- package/dist/orchestrators/snapshot/state-document.mjs.map +1 -1
- package/dist/orchestrators/snapshot/wipe.mjs +67 -10
- package/dist/orchestrators/snapshot/wipe.mjs.map +1 -1
- package/dist/plugins/account/codegen.mjs +9 -8
- package/dist/plugins/account/codegen.mjs.map +1 -1
- package/dist/plugins/account/errors.d.mts +33 -6
- package/dist/plugins/account/errors.mjs.map +1 -1
- package/dist/plugins/account/funding.d.mts +29 -19
- package/dist/plugins/account/funding.mjs +84 -66
- package/dist/plugins/account/funding.mjs.map +1 -1
- package/dist/plugins/account/index.d.mts +2 -4
- package/dist/plugins/account/index.mjs +64 -31
- package/dist/plugins/account/index.mjs.map +1 -1
- package/dist/plugins/account/keypair.mjs +6 -9
- package/dist/plugins/account/keypair.mjs.map +1 -1
- package/dist/plugins/account/lease.mjs +1 -0
- package/dist/plugins/account/lease.mjs.map +1 -1
- package/dist/plugins/account/registry.d.mts +14 -1
- package/dist/plugins/account/registry.mjs +18 -18
- package/dist/plugins/account/registry.mjs.map +1 -1
- package/dist/plugins/account/service.d.mts +23 -4
- package/dist/plugins/account/service.mjs +83 -45
- package/dist/plugins/account/service.mjs.map +1 -1
- package/dist/plugins/account/snapshot.mjs +2 -5
- package/dist/plugins/account/snapshot.mjs.map +1 -1
- package/dist/plugins/account/spans.mjs +16 -0
- package/dist/plugins/account/spans.mjs.map +1 -0
- package/dist/plugins/account/variants/keystore.mjs +6 -8
- package/dist/plugins/account/variants/keystore.mjs.map +1 -1
- package/dist/plugins/action/build-context.d.mts +3 -2
- package/dist/plugins/action/errors.d.mts +16 -12
- package/dist/plugins/action/errors.mjs.map +1 -1
- package/dist/plugins/action/execute.mjs +65 -103
- package/dist/plugins/action/execute.mjs.map +1 -1
- package/dist/plugins/action/index.d.mts +0 -2
- package/dist/plugins/action/index.mjs +17 -13
- package/dist/plugins/action/index.mjs.map +1 -1
- package/dist/plugins/action/service.mjs +38 -35
- package/dist/plugins/action/service.mjs.map +1 -1
- package/dist/plugins/action/spans.mjs +11 -0
- package/dist/plugins/action/spans.mjs.map +1 -0
- package/dist/plugins/coin/codegen.mjs +9 -8
- package/dist/plugins/coin/codegen.mjs.map +1 -1
- package/dist/plugins/coin/discovery.mjs +8 -4
- package/dist/plugins/coin/discovery.mjs.map +1 -1
- package/dist/plugins/coin/index.d.mts +11 -29
- package/dist/plugins/coin/index.mjs +56 -27
- package/dist/plugins/coin/index.mjs.map +1 -1
- package/dist/plugins/coin/metadata.mjs +8 -15
- package/dist/plugins/coin/metadata.mjs.map +1 -1
- package/dist/plugins/coin/mint.d.mts +30 -11
- package/dist/plugins/coin/mint.mjs +78 -74
- package/dist/plugins/coin/mint.mjs.map +1 -1
- package/dist/plugins/coin/registry.mjs +4 -7
- package/dist/plugins/coin/registry.mjs.map +1 -1
- package/dist/plugins/coin/service.d.mts +39 -1
- package/dist/plugins/coin/service.mjs +11 -4
- package/dist/plugins/coin/service.mjs.map +1 -1
- package/dist/plugins/coin/spans.mjs +20 -0
- package/dist/plugins/coin/spans.mjs.map +1 -0
- package/dist/plugins/dashboard/domain.mjs +402 -0
- package/dist/plugins/dashboard/domain.mjs.map +1 -0
- package/dist/plugins/dashboard/index.d.mts +29 -0
- package/dist/plugins/dashboard/index.mjs +91 -0
- package/dist/plugins/dashboard/index.mjs.map +1 -0
- package/dist/plugins/dashboard/origin-policy.mjs +36 -0
- package/dist/plugins/dashboard/origin-policy.mjs.map +1 -0
- package/dist/plugins/dashboard/routable.mjs +27 -0
- package/dist/plugins/dashboard/routable.mjs.map +1 -0
- package/dist/plugins/dashboard/schema/builder.mjs +21 -0
- package/dist/plugins/dashboard/schema/builder.mjs.map +1 -0
- package/dist/plugins/dashboard/schema/enums.mjs +72 -0
- package/dist/plugins/dashboard/schema/enums.mjs.map +1 -0
- package/dist/plugins/dashboard/schema/root.mjs +351 -0
- package/dist/plugins/dashboard/schema/root.mjs.map +1 -0
- package/dist/plugins/dashboard/schema/types.mjs +508 -0
- package/dist/plugins/dashboard/schema/types.mjs.map +1 -0
- package/dist/plugins/dashboard/schema.mjs +11 -0
- package/dist/plugins/dashboard/schema.mjs.map +1 -0
- package/dist/plugins/dashboard/server.mjs +166 -0
- package/dist/plugins/dashboard/server.mjs.map +1 -0
- package/dist/plugins/deepbook/deploy.mjs +53 -115
- package/dist/plugins/deepbook/deploy.mjs.map +1 -1
- package/dist/plugins/deepbook/errors.mjs +1 -0
- package/dist/plugins/deepbook/errors.mjs.map +1 -1
- package/dist/plugins/deepbook/faucet-strategy.mjs +47 -34
- package/dist/plugins/deepbook/faucet-strategy.mjs.map +1 -1
- package/dist/plugins/deepbook/hash.mjs +9 -0
- package/dist/plugins/deepbook/hash.mjs.map +1 -0
- package/dist/plugins/deepbook/index.d.mts +1 -10
- package/dist/plugins/deepbook/index.mjs +25 -22
- package/dist/plugins/deepbook/index.mjs.map +1 -1
- package/dist/plugins/deepbook/pyth/index.mjs +26 -55
- package/dist/plugins/deepbook/pyth/index.mjs.map +1 -1
- package/dist/plugins/deepbook/snapshot.mjs +17 -29
- package/dist/plugins/deepbook/snapshot.mjs.map +1 -1
- package/dist/plugins/deepbook/spans.mjs +18 -0
- package/dist/plugins/deepbook/spans.mjs.map +1 -0
- package/dist/plugins/deepbook/type-strings.mjs +65 -0
- package/dist/plugins/deepbook/type-strings.mjs.map +1 -0
- package/dist/plugins/deepbook/types.d.mts +2 -3
- package/dist/plugins/deepbook/types.mjs.map +1 -1
- package/dist/plugins/faucet/dispatcher.d.mts +21 -2
- package/dist/plugins/faucet/dispatcher.mjs +1 -2
- package/dist/plugins/faucet/dispatcher.mjs.map +1 -1
- package/dist/plugins/faucet/errors.d.mts +11 -24
- package/dist/plugins/faucet/errors.mjs.map +1 -1
- package/dist/plugins/faucet/http.mjs +33 -14
- package/dist/plugins/faucet/http.mjs.map +1 -1
- package/dist/plugins/faucet/index.d.mts +15 -5
- package/dist/plugins/faucet/index.mjs +3 -0
- package/dist/plugins/faucet/index.mjs.map +1 -1
- package/dist/plugins/faucet/spans.mjs +12 -0
- package/dist/plugins/faucet/spans.mjs.map +1 -0
- package/dist/plugins/host-service/errors.d.mts +1 -1
- package/dist/plugins/host-service/index.mjs +34 -8
- package/dist/plugins/host-service/index.mjs.map +1 -1
- package/dist/plugins/host-service/routable.mjs +2 -1
- package/dist/plugins/host-service/routable.mjs.map +1 -1
- package/dist/plugins/host-service/service.d.mts +21 -0
- package/dist/plugins/host-service/service.mjs +136 -81
- package/dist/plugins/host-service/service.mjs.map +1 -1
- package/dist/plugins/internal/acquire-on-chain-artifact.mjs +23 -0
- package/dist/plugins/internal/acquire-on-chain-artifact.mjs.map +1 -0
- package/dist/plugins/internal/codegen-helpers.mjs +18 -0
- package/dist/plugins/internal/codegen-helpers.mjs.map +1 -0
- package/dist/plugins/internal/funding-failure-error.mjs +32 -0
- package/dist/plugins/internal/funding-failure-error.mjs.map +1 -0
- package/dist/plugins/package/build.mjs +1 -1
- package/dist/plugins/package/build.mjs.map +1 -1
- package/dist/plugins/package/codegen.mjs +26 -0
- package/dist/plugins/package/codegen.mjs.map +1 -1
- package/dist/plugins/package/errors.d.mts +16 -6
- package/dist/plugins/package/errors.mjs.map +1 -1
- package/dist/plugins/package/index.d.mts +0 -4
- package/dist/plugins/package/index.mjs +27 -21
- package/dist/plugins/package/index.mjs.map +1 -1
- package/dist/plugins/package/mode-known.mjs +26 -12
- package/dist/plugins/package/mode-known.mjs.map +1 -1
- package/dist/plugins/package/mode-local.mjs +47 -41
- package/dist/plugins/package/mode-local.mjs.map +1 -1
- package/dist/plugins/package/publish-executor.mjs +55 -114
- package/dist/plugins/package/publish-executor.mjs.map +1 -1
- package/dist/plugins/package/registry.mjs +2 -1
- package/dist/plugins/package/registry.mjs.map +1 -1
- package/dist/plugins/package/service.mjs.map +1 -1
- package/dist/plugins/package/spans.mjs +14 -0
- package/dist/plugins/package/spans.mjs.map +1 -0
- package/dist/plugins/postgres/db-ensure.mjs +19 -12
- package/dist/plugins/postgres/db-ensure.mjs.map +1 -1
- package/dist/plugins/postgres/errors.d.mts +5 -0
- package/dist/plugins/postgres/errors.mjs.map +1 -1
- package/dist/plugins/postgres/index.mjs +10 -17
- package/dist/plugins/postgres/index.mjs.map +1 -1
- package/dist/plugins/postgres/service.mjs +58 -24
- package/dist/plugins/postgres/service.mjs.map +1 -1
- package/dist/plugins/postgres/snapshot.mjs.map +1 -1
- package/dist/plugins/postgres/spans.mjs +11 -0
- package/dist/plugins/postgres/spans.mjs.map +1 -0
- package/dist/plugins/router-entrypoints.mjs +4 -4
- package/dist/plugins/router-entrypoints.mjs.map +1 -1
- package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs +15 -13
- package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs.map +1 -1
- package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs +15 -19
- package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs.map +1 -1
- package/dist/plugins/seal/codegen.d.mts +2 -3
- package/dist/plugins/seal/codegen.mjs.map +1 -1
- package/dist/plugins/seal/config-render.mjs +35 -8
- package/dist/plugins/seal/config-render.mjs.map +1 -1
- package/dist/plugins/seal/deploy.mjs +31 -39
- package/dist/plugins/seal/deploy.mjs.map +1 -1
- package/dist/plugins/seal/errors.d.mts +1 -3
- package/dist/plugins/seal/errors.mjs +7 -1
- package/dist/plugins/seal/errors.mjs.map +1 -1
- package/dist/plugins/seal/index.d.mts +1 -6
- package/dist/plugins/seal/index.mjs +40 -14
- package/dist/plugins/seal/index.mjs.map +1 -1
- package/dist/plugins/seal/key-manager.d.mts +1 -9
- package/dist/plugins/seal/key-manager.mjs +2 -18
- package/dist/plugins/seal/key-manager.mjs.map +1 -1
- package/dist/plugins/seal/key-server.mjs +37 -36
- package/dist/plugins/seal/key-server.mjs.map +1 -1
- package/dist/plugins/seal/keygen.mjs +16 -17
- package/dist/plugins/seal/keygen.mjs.map +1 -1
- package/dist/plugins/seal/mode/fork-known.mjs +36 -14
- package/dist/plugins/seal/mode/fork-known.mjs.map +1 -1
- package/dist/plugins/seal/mode/live.d.mts +6 -4
- package/dist/plugins/seal/mode/live.mjs +14 -21
- package/dist/plugins/seal/mode/live.mjs.map +1 -1
- package/dist/plugins/seal/mode/local-keygen.mjs +57 -21
- package/dist/plugins/seal/mode/local-keygen.mjs.map +1 -1
- package/dist/plugins/seal/registry-publish.mjs +1 -0
- package/dist/plugins/seal/registry-publish.mjs.map +1 -1
- package/dist/plugins/seal/routable.mjs.map +1 -1
- package/dist/plugins/seal/service.mjs.map +1 -1
- package/dist/plugins/seal/spans.mjs +18 -0
- package/dist/plugins/seal/spans.mjs.map +1 -0
- package/dist/plugins/sui/auto-tick.mjs +17 -23
- package/dist/plugins/sui/auto-tick.mjs.map +1 -1
- package/dist/plugins/sui/chain-build-container.mjs +18 -0
- package/dist/plugins/sui/chain-build-container.mjs.map +1 -0
- package/dist/plugins/sui/chain-probe.d.mts +5 -5
- package/dist/plugins/sui/chain-probe.mjs +28 -58
- package/dist/plugins/sui/chain-probe.mjs.map +1 -1
- package/dist/plugins/sui/codegen.mjs +26 -0
- package/dist/plugins/sui/codegen.mjs.map +1 -1
- package/dist/plugins/sui/errors.d.mts +2 -29
- package/dist/plugins/sui/errors.mjs +1 -3
- package/dist/plugins/sui/errors.mjs.map +1 -1
- package/dist/plugins/sui/fork-faucet-strategy.d.mts +1 -0
- package/dist/plugins/sui/fork-faucet-strategy.mjs +55 -0
- package/dist/plugins/sui/fork-faucet-strategy.mjs.map +1 -0
- package/dist/plugins/sui/fork-orchestration.d.mts +1 -0
- package/dist/plugins/sui/fork-orchestration.mjs +170 -2
- package/dist/plugins/sui/fork-orchestration.mjs.map +1 -1
- package/dist/plugins/sui/fork-transaction.d.mts +2 -0
- package/dist/plugins/sui/fork-transaction.mjs +92 -28
- package/dist/plugins/sui/fork-transaction.mjs.map +1 -1
- package/dist/plugins/sui/index.d.mts +33 -70
- package/dist/plugins/sui/index.mjs +58 -35
- package/dist/plugins/sui/index.mjs.map +1 -1
- package/dist/plugins/{faucet/strategies/sui-local.mjs → sui/local-faucet-strategy.mjs} +10 -7
- package/dist/plugins/sui/local-faucet-strategy.mjs.map +1 -0
- package/dist/plugins/sui/mode/external.mjs +7 -13
- package/dist/plugins/sui/mode/external.mjs.map +1 -1
- package/dist/plugins/sui/mode/fork.mjs +136 -59
- package/dist/plugins/sui/mode/fork.mjs.map +1 -1
- package/dist/plugins/sui/mode/live.mjs +10 -16
- package/dist/plugins/sui/mode/live.mjs.map +1 -1
- package/dist/plugins/sui/mode/local.mjs +37 -36
- package/dist/plugins/sui/mode/local.mjs.map +1 -1
- package/dist/plugins/sui/mode/shared-boot.mjs +38 -115
- package/dist/plugins/sui/mode/shared-boot.mjs.map +1 -1
- package/dist/plugins/sui/mode/shared.d.mts +1 -5
- package/dist/plugins/sui/mode/shared.mjs.map +1 -1
- package/dist/plugins/sui/mode/spec.d.mts +18 -0
- package/dist/plugins/sui/move-summary-runner.mjs +207 -0
- package/dist/plugins/sui/move-summary-runner.mjs.map +1 -0
- package/dist/plugins/sui/network-resolver.d.mts +4 -3
- package/dist/plugins/sui/service.mjs.map +1 -1
- package/dist/plugins/sui/snapshot.mjs +3 -0
- package/dist/plugins/sui/snapshot.mjs.map +1 -1
- package/dist/plugins/sui/spans.mjs +17 -0
- package/dist/plugins/sui/spans.mjs.map +1 -0
- package/dist/plugins/wallet/codegen.d.mts +0 -1
- package/dist/plugins/wallet/codegen.mjs +8 -9
- package/dist/plugins/wallet/codegen.mjs.map +1 -1
- package/dist/plugins/wallet/index.d.mts +6 -8
- package/dist/plugins/wallet/index.mjs +46 -35
- package/dist/plugins/wallet/index.mjs.map +1 -1
- package/dist/plugins/wallet/origin-policy.mjs +12 -28
- package/dist/plugins/wallet/origin-policy.mjs.map +1 -1
- package/dist/plugins/wallet/pairing.mjs +6 -4
- package/dist/plugins/wallet/pairing.mjs.map +1 -1
- package/dist/plugins/wallet/protocol.d.mts +1 -0
- package/dist/plugins/wallet/protocol.mjs +5 -44
- package/dist/plugins/wallet/protocol.mjs.map +1 -1
- package/dist/plugins/wallet/routable.mjs +2 -8
- package/dist/plugins/wallet/routable.mjs.map +1 -1
- package/dist/plugins/wallet/server.mjs +36 -44
- package/dist/plugins/wallet/server.mjs.map +1 -1
- package/dist/plugins/wallet/service.d.mts +1 -5
- package/dist/plugins/wallet/service.mjs +22 -18
- package/dist/plugins/wallet/service.mjs.map +1 -1
- package/dist/plugins/wallet/spans.mjs +22 -0
- package/dist/plugins/wallet/spans.mjs.map +1 -0
- package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs +33 -8
- package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs.map +1 -1
- package/dist/plugins/walrus/codegen.d.mts +3 -3
- package/dist/plugins/walrus/codegen.mjs.map +1 -1
- package/dist/plugins/walrus/deploy-paths.mjs +21 -5
- package/dist/plugins/walrus/deploy-paths.mjs.map +1 -1
- package/dist/plugins/walrus/deploy.mjs +67 -69
- package/dist/plugins/walrus/deploy.mjs.map +1 -1
- package/dist/plugins/walrus/errors.mjs +1 -0
- package/dist/plugins/walrus/errors.mjs.map +1 -1
- package/dist/plugins/walrus/faucet-strategy.mjs +12 -7
- package/dist/plugins/walrus/faucet-strategy.mjs.map +1 -1
- package/dist/plugins/walrus/index.d.mts +2 -13
- package/dist/plugins/walrus/index.mjs +18 -23
- package/dist/plugins/walrus/index.mjs.map +1 -1
- package/dist/plugins/walrus/mode/known-deploy.mjs +7 -5
- package/dist/plugins/walrus/mode/known-deploy.mjs.map +1 -1
- package/dist/plugins/walrus/mode/local-cluster.mjs +26 -7
- package/dist/plugins/walrus/mode/local-cluster.mjs.map +1 -1
- package/dist/plugins/walrus/registry-publish.mjs.map +1 -1
- package/dist/plugins/walrus/routable.mjs +7 -23
- package/dist/plugins/walrus/routable.mjs.map +1 -1
- package/dist/plugins/walrus/service.mjs.map +1 -1
- package/dist/plugins/walrus/spans.mjs +18 -0
- package/dist/plugins/walrus/spans.mjs.map +1 -0
- package/dist/plugins/walrus/storage-nodes.d.mts +6 -2
- package/dist/plugins/walrus/storage-nodes.mjs +15 -8
- package/dist/plugins/walrus/storage-nodes.mjs.map +1 -1
- package/dist/plugins/walrus/wal-swap.mjs +58 -15
- package/dist/plugins/walrus/wal-swap.mjs.map +1 -1
- package/dist/primitives/artifact-publisher.d.mts +1 -1
- package/dist/primitives/artifact-publisher.mjs +15 -0
- package/dist/primitives/artifact-publisher.mjs.map +1 -0
- package/dist/runtime/docker/client.mjs +17 -4
- package/dist/runtime/docker/client.mjs.map +1 -1
- package/dist/runtime/docker/container.mjs +219 -132
- package/dist/runtime/docker/container.mjs.map +1 -1
- package/dist/runtime/docker/errors.mjs +0 -6
- package/dist/runtime/docker/errors.mjs.map +1 -1
- package/dist/runtime/docker/exec.mjs +21 -18
- package/dist/runtime/docker/exec.mjs.map +1 -1
- package/dist/runtime/docker/image.mjs +36 -13
- package/dist/runtime/docker/image.mjs.map +1 -1
- package/dist/runtime/docker/index.mjs +14 -0
- package/dist/runtime/docker/inspect-and-decode.mjs +51 -0
- package/dist/runtime/docker/inspect-and-decode.mjs.map +1 -0
- package/dist/runtime/docker/inventory.mjs +14 -11
- package/dist/runtime/docker/inventory.mjs.map +1 -1
- package/dist/runtime/docker/labels.mjs +38 -5
- package/dist/runtime/docker/labels.mjs.map +1 -1
- package/dist/runtime/docker/logs.d.mts +1 -1
- package/dist/runtime/docker/logs.mjs.map +1 -1
- package/dist/runtime/docker/network.mjs +83 -47
- package/dist/runtime/docker/network.mjs.map +1 -1
- package/dist/runtime/docker/render-run-args.mjs +82 -0
- package/dist/runtime/docker/render-run-args.mjs.map +1 -0
- package/dist/runtime/docker/service.d.mts +1 -1
- package/dist/runtime/docker/service.mjs +12 -7
- package/dist/runtime/docker/service.mjs.map +1 -1
- package/dist/runtime/docker/sweep.mjs +118 -43
- package/dist/runtime/docker/sweep.mjs.map +1 -1
- package/dist/runtime/docker/volume.mjs +2 -0
- package/dist/runtime/docker/volume.mjs.map +1 -1
- package/dist/runtime/docker/wrap.mjs +30 -1
- package/dist/runtime/docker/wrap.mjs.map +1 -1
- package/dist/substrate/cross-process.mjs +14 -8
- package/dist/substrate/cross-process.mjs.map +1 -1
- package/dist/substrate/event-time.mjs +33 -0
- package/dist/substrate/event-time.mjs.map +1 -0
- package/dist/substrate/events.d.mts +28 -8
- package/dist/substrate/identity.d.mts +2 -1
- package/dist/substrate/manifest.d.mts +68 -5
- package/dist/substrate/manifest.mjs +34 -5
- package/dist/substrate/manifest.mjs.map +1 -1
- package/dist/substrate/network.d.mts +3 -5
- package/dist/substrate/options.d.mts +0 -2
- package/dist/substrate/plugin.d.mts +13 -0
- package/dist/substrate/plugin.mjs +4 -2
- package/dist/substrate/plugin.mjs.map +1 -1
- package/dist/substrate/projection.d.mts +35 -3
- package/dist/substrate/runtime/artifact-publisher/index.mjs +19 -9
- package/dist/substrate/runtime/artifact-publisher/index.mjs.map +1 -1
- package/dist/substrate/runtime/atomic-write.mjs +97 -32
- package/dist/substrate/runtime/atomic-write.mjs.map +1 -1
- package/dist/substrate/runtime/cache/index.mjs +3 -0
- package/dist/substrate/runtime/cache/schema.mjs +2 -2
- package/dist/substrate/runtime/cache/schema.mjs.map +1 -1
- package/dist/substrate/runtime/cache/service.mjs +9 -7
- package/dist/substrate/runtime/cache/service.mjs.map +1 -1
- package/dist/substrate/runtime/capability-sinks/index.d.mts +1 -1
- package/dist/substrate/runtime/capability-sinks/index.mjs +3 -0
- package/dist/substrate/runtime/capability-sinks/layer.mjs +1 -1
- package/dist/substrate/runtime/capability-sinks/service.d.mts +61 -2
- package/dist/substrate/runtime/capability-sinks/service.mjs +21 -26
- package/dist/substrate/runtime/capability-sinks/service.mjs.map +1 -1
- package/dist/substrate/runtime/config-validation.d.mts +1 -13
- package/dist/substrate/runtime/config-validation.mjs +2 -91
- package/dist/substrate/runtime/config-validation.mjs.map +1 -1
- package/dist/substrate/runtime/container-runtime.d.mts +1 -0
- package/dist/substrate/runtime/container-runtime.mjs +2 -0
- package/dist/substrate/runtime/control-plane/domain.mjs +101 -0
- package/dist/substrate/runtime/control-plane/domain.mjs.map +1 -0
- package/dist/substrate/runtime/control-plane/service.mjs +7 -0
- package/dist/substrate/runtime/control-plane/service.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/command-channel/channel.mjs +46 -19
- package/dist/substrate/runtime/cross-process/command-channel/channel.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs +30 -12
- package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/command-channel/index.mjs +5 -0
- package/dist/substrate/runtime/cross-process/command-channel/protocol.mjs +11 -2
- package/dist/substrate/runtime/cross-process/command-channel/protocol.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/command-channel/runtime-control-lock.mjs +1 -1
- package/dist/substrate/runtime/cross-process/index.mjs +11 -0
- package/dist/substrate/runtime/cross-process/live-clock.mjs +34 -0
- package/dist/substrate/runtime/cross-process/live-clock.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/liveness.mjs +52 -10
- package/dist/substrate/runtime/cross-process/liveness.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/lock.d.mts +1 -0
- package/dist/substrate/runtime/cross-process/lock.mjs +23 -0
- package/dist/substrate/runtime/cross-process/lock.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs +64 -0
- package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/roster.mjs +97 -83
- package/dist/substrate/runtime/cross-process/roster.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/self-pid.mjs +8 -0
- package/dist/substrate/runtime/cross-process/self-pid.mjs.map +1 -0
- package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs +24 -28
- package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs.map +1 -1
- package/dist/substrate/runtime/cross-process/stack-lock.mjs +41 -20
- package/dist/substrate/runtime/cross-process/stack-lock.mjs.map +1 -1
- package/dist/substrate/runtime/current-plugin.mjs +2 -2
- package/dist/substrate/runtime/current-plugin.mjs.map +1 -1
- package/dist/substrate/runtime/errors.mjs +12 -6
- package/dist/substrate/runtime/errors.mjs.map +1 -1
- package/dist/substrate/runtime/format-unknown-error.mjs +30 -0
- package/dist/substrate/runtime/format-unknown-error.mjs.map +1 -0
- package/dist/substrate/runtime/host-bind-mount-owner.mjs +10 -0
- package/dist/substrate/runtime/host-bind-mount-owner.mjs.map +1 -0
- package/dist/substrate/runtime/host-gateway.mjs +20 -0
- package/dist/substrate/runtime/host-gateway.mjs.map +1 -0
- package/dist/substrate/runtime/host-tree-tar/index.mjs +61 -50
- package/dist/substrate/runtime/host-tree-tar/index.mjs.map +1 -1
- package/dist/substrate/runtime/http-probe.d.mts +1 -1
- package/dist/substrate/runtime/index.mjs +14 -0
- package/dist/substrate/runtime/lease-broker/index.d.mts +1 -1
- package/dist/substrate/runtime/lease-broker/index.mjs +2 -0
- package/dist/substrate/runtime/lease-broker/service.d.mts +1 -64
- package/dist/substrate/runtime/lease-broker/service.mjs +1 -1
- package/dist/substrate/runtime/lease-broker/service.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/dep-graph.mjs +22 -3
- package/dist/substrate/runtime/lifecycle/dep-graph.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/index.mjs +9 -0
- package/dist/substrate/runtime/lifecycle/lifecycle-fact.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/plugin-registry.mjs +20 -3
- package/dist/substrate/runtime/lifecycle/plugin-registry.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/selective-restart.mjs +1 -1
- package/dist/substrate/runtime/lifecycle/signals.mjs +5 -5
- package/dist/substrate/runtime/lifecycle/signals.mjs.map +1 -1
- package/dist/substrate/runtime/lifecycle/state-machine.mjs +1 -1
- package/dist/substrate/runtime/managed-container.d.mts +19 -1
- package/dist/substrate/runtime/managed-container.mjs +20 -1
- package/dist/substrate/runtime/managed-container.mjs.map +1 -1
- package/dist/substrate/runtime/manifest/index.mjs +3 -0
- package/dist/substrate/runtime/manifest/manifest.mjs +15 -11
- package/dist/substrate/runtime/manifest/manifest.mjs.map +1 -1
- package/dist/substrate/runtime/mode-errors.mjs +20 -0
- package/dist/substrate/runtime/mode-errors.mjs.map +1 -0
- package/dist/substrate/runtime/observability/cascade-formatter.mjs +9 -13
- package/dist/substrate/runtime/observability/cascade-formatter.mjs.map +1 -1
- package/dist/substrate/runtime/observability/formatter-registry.mjs +19 -36
- package/dist/substrate/runtime/observability/formatter-registry.mjs.map +1 -1
- package/dist/substrate/runtime/observability/ignore-with-log.d.mts +1 -0
- package/dist/substrate/runtime/observability/ignore-with-log.mjs +17 -0
- package/dist/substrate/runtime/observability/ignore-with-log.mjs.map +1 -0
- package/dist/substrate/runtime/observability/index.d.mts +1 -1
- package/dist/substrate/runtime/observability/index.mjs +13 -0
- package/dist/substrate/runtime/observability/log-store.d.mts +1 -0
- package/dist/substrate/runtime/observability/log-store.mjs +175 -0
- package/dist/substrate/runtime/observability/log-store.mjs.map +1 -0
- package/dist/substrate/runtime/observability/logger.d.mts +2 -1
- package/dist/substrate/runtime/observability/logger.mjs +5 -9
- package/dist/substrate/runtime/observability/logger.mjs.map +1 -1
- package/dist/substrate/runtime/observability/output-truncate.mjs +35 -0
- package/dist/substrate/runtime/observability/output-truncate.mjs.map +1 -0
- package/dist/substrate/runtime/observability/pretty-error.mjs +9 -12
- package/dist/substrate/runtime/observability/pretty-error.mjs.map +1 -1
- package/dist/substrate/runtime/observability/redaction.d.mts +2 -13
- package/dist/substrate/runtime/observability/redaction.mjs +8 -14
- package/dist/substrate/runtime/observability/redaction.mjs.map +1 -1
- package/dist/substrate/runtime/observability/span-store.d.mts +1 -0
- package/dist/substrate/runtime/observability/span-store.mjs +110 -0
- package/dist/substrate/runtime/observability/span-store.mjs.map +1 -0
- package/dist/substrate/runtime/observability/spans.mjs +14 -14
- package/dist/substrate/runtime/observability/spans.mjs.map +1 -1
- package/dist/substrate/runtime/observability/subprocess-capture.mjs +1 -1
- package/dist/substrate/runtime/passthrough-or-wrap.mjs +33 -0
- package/dist/substrate/runtime/passthrough-or-wrap.mjs.map +1 -0
- package/dist/substrate/runtime/paths.d.mts +1 -1
- package/dist/substrate/runtime/paths.mjs +4 -3
- package/dist/substrate/runtime/paths.mjs.map +1 -1
- package/dist/substrate/runtime/phase-preserving-produce.mjs +40 -0
- package/dist/substrate/runtime/phase-preserving-produce.mjs.map +1 -0
- package/dist/substrate/runtime/port-broker/index.mjs +3 -0
- package/dist/substrate/runtime/port-broker/service.mjs +170 -126
- package/dist/substrate/runtime/port-broker/service.mjs.map +1 -1
- package/dist/substrate/runtime/post-acquire-tasks.mjs +1 -1
- package/dist/substrate/runtime/post-acquire-tasks.mjs.map +1 -1
- package/dist/substrate/runtime/probes.d.mts +7 -5
- package/dist/substrate/runtime/probes.mjs +3 -1
- package/dist/substrate/runtime/probes.mjs.map +1 -1
- package/dist/substrate/runtime/projection/index.mjs +4 -0
- package/dist/substrate/runtime/projection/operational-endpoints.mjs +1 -2
- package/dist/substrate/runtime/projection/operational-endpoints.mjs.map +1 -1
- package/dist/substrate/runtime/projection/persisted.mjs +33 -15
- package/dist/substrate/runtime/projection/persisted.mjs.map +1 -1
- package/dist/substrate/runtime/projection/state-ref.mjs +26 -2
- package/dist/substrate/runtime/projection/state-ref.mjs.map +1 -1
- package/dist/substrate/runtime/projection/update.mjs +88 -24
- package/dist/substrate/runtime/projection/update.mjs.map +1 -1
- package/dist/substrate/runtime/random-suffix.mjs +11 -0
- package/dist/substrate/runtime/random-suffix.mjs.map +1 -0
- package/dist/substrate/runtime/retry-policy.d.mts +59 -1
- package/dist/substrate/runtime/retry-policy.mjs +66 -1
- package/dist/substrate/runtime/retry-policy.mjs.map +1 -1
- package/dist/substrate/runtime/routed-url.d.mts +1 -0
- package/dist/substrate/runtime/routed-url.mjs +79 -0
- package/dist/substrate/runtime/routed-url.mjs.map +1 -0
- package/dist/substrate/runtime/runtime-decode.d.mts +1 -1
- package/dist/substrate/runtime/runtime-decode.mjs.map +1 -1
- package/dist/substrate/runtime/scoped-http-server.mjs +2 -3
- package/dist/substrate/runtime/scoped-http-server.mjs.map +1 -1
- package/dist/substrate/runtime/scoped-multimap/index.mjs +2 -0
- package/dist/substrate/runtime/scoped-multimap/service.mjs +52 -0
- package/dist/substrate/runtime/scoped-multimap/service.mjs.map +1 -0
- package/dist/substrate/runtime/scoped-ref-map/index.mjs +2 -0
- package/dist/substrate/runtime/scoped-ref-map/service.mjs +2 -2
- package/dist/substrate/runtime/scoped-ref-map/service.mjs.map +1 -1
- package/dist/substrate/runtime/stage-and-swap/index.mjs +72 -4
- package/dist/substrate/runtime/stage-and-swap/index.mjs.map +1 -1
- package/dist/substrate/runtime/state-store/index.d.mts +1 -0
- package/dist/substrate/runtime/state-store/index.mjs +3 -0
- package/dist/substrate/runtime/state-store/schema.d.mts +1 -0
- package/dist/substrate/runtime/state-store/schema.mjs +19 -14
- package/dist/substrate/runtime/state-store/schema.mjs.map +1 -1
- package/dist/substrate/runtime/state-store/service.d.mts +1 -0
- package/dist/substrate/runtime/state-store/service.mjs +145 -0
- package/dist/substrate/runtime/state-store/service.mjs.map +1 -0
- package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.d.mts +1 -0
- package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.mjs +33 -0
- package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.mjs.map +1 -0
- package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs +1 -1
- package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs.map +1 -1
- package/dist/substrate/runtime/strategy-registry/index.mjs +4 -0
- package/dist/substrate/runtime/strategy-registry/service.mjs +19 -33
- package/dist/substrate/runtime/strategy-registry/service.mjs.map +1 -1
- package/dist/substrate/runtime/subnet-broker.mjs +60 -0
- package/dist/substrate/runtime/subnet-broker.mjs.map +1 -0
- package/dist/substrate/runtime/sui-execute/index.d.mts +21 -1
- package/dist/substrate/runtime/sui-execute/index.mjs +84 -20
- package/dist/substrate/runtime/sui-execute/index.mjs.map +1 -1
- package/dist/substrate/runtime/sui-execute/sign-and-dispatch.d.mts +1 -0
- package/dist/substrate/runtime/sui-execute/sign-and-dispatch.mjs +32 -0
- package/dist/substrate/runtime/sui-execute/sign-and-dispatch.mjs.map +1 -0
- package/dist/substrate/runtime/sui-ledger/object-ref.mjs +32 -0
- package/dist/substrate/runtime/sui-ledger/object-ref.mjs.map +1 -0
- package/dist/substrate/runtime/sui-move-build/index.mjs +93 -19
- package/dist/substrate/runtime/sui-move-build/index.mjs.map +1 -1
- package/dist/substrate/runtime/supervisor/acquire-node.mjs +181 -0
- package/dist/substrate/runtime/supervisor/acquire-node.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/background-tasks.mjs +144 -0
- package/dist/substrate/runtime/supervisor/background-tasks.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/command-loop.mjs +68 -0
- package/dist/substrate/runtime/supervisor/command-loop.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs +151 -0
- package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/errors.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/errors.mjs +9 -0
- package/dist/substrate/runtime/supervisor/errors.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/index.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/index.mjs +3 -0
- package/dist/substrate/runtime/supervisor/shutdown.mjs +51 -0
- package/dist/substrate/runtime/supervisor/shutdown.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/start-supervisor.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/start-supervisor.mjs +250 -0
- package/dist/substrate/runtime/supervisor/start-supervisor.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/state.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/state.mjs +22 -0
- package/dist/substrate/runtime/supervisor/state.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/teardown.mjs +57 -0
- package/dist/substrate/runtime/supervisor/teardown.mjs.map +1 -0
- package/dist/substrate/runtime/supervisor/types.d.mts +1 -0
- package/dist/substrate/runtime/supervisor/wiring.mjs +133 -0
- package/dist/substrate/runtime/supervisor/wiring.mjs.map +1 -0
- package/dist/substrate/runtime/typed-env.mjs +8 -0
- package/dist/substrate/runtime/typed-env.mjs.map +1 -0
- package/dist/substrate/state-store.d.mts +1 -0
- package/dist/substrate/versioned-doc-schema.mjs +17 -0
- package/dist/substrate/versioned-doc-schema.mjs.map +1 -0
- package/dist/substrate/versioned-doc-sync.mjs +94 -0
- package/dist/substrate/versioned-doc-sync.mjs.map +1 -0
- package/dist/surfaces/cli/command-tree.mjs.map +1 -1
- package/dist/surfaces/cli/commands/index.mjs +9 -0
- package/dist/surfaces/cli/commands/prune-picker-entry.mjs +13 -0
- package/dist/surfaces/cli/commands/prune-picker-entry.mjs.map +1 -0
- package/dist/surfaces/cli/commands/prune-picker.mjs +3 -2
- package/dist/surfaces/cli/commands/prune-picker.mjs.map +1 -1
- package/dist/surfaces/cli/commands/prune.mjs +34 -17
- package/dist/surfaces/cli/commands/prune.mjs.map +1 -1
- package/dist/surfaces/cli/commands/status.mjs +2 -2
- package/dist/surfaces/cli/commands/status.mjs.map +1 -1
- package/dist/surfaces/cli/commands/supervisor-presence.mjs +5 -3
- package/dist/surfaces/cli/commands/supervisor-presence.mjs.map +1 -1
- package/dist/surfaces/cli/commands/wipe.mjs +38 -4
- package/dist/surfaces/cli/commands/wipe.mjs.map +1 -1
- package/dist/surfaces/cli/errors.mjs +1 -1
- package/dist/surfaces/cli/errors.mjs.map +1 -1
- package/dist/surfaces/cli/flags.mjs +0 -1
- package/dist/surfaces/cli/flags.mjs.map +1 -1
- package/dist/surfaces/cli/index.mjs +98 -18
- package/dist/surfaces/cli/index.mjs.map +1 -1
- package/dist/surfaces/cli/output.mjs +1 -0
- package/dist/surfaces/cli/output.mjs.map +1 -1
- package/dist/surfaces/cli/sysexits.mjs +2 -1
- package/dist/surfaces/cli/sysexits.mjs.map +1 -1
- package/dist/surfaces/tui/app.mjs +25 -3
- package/dist/surfaces/tui/app.mjs.map +1 -1
- package/dist/surfaces/tui/display-derivation.mjs +23 -74
- package/dist/surfaces/tui/display-derivation.mjs.map +1 -1
- package/dist/surfaces/tui/event-log.mjs +35 -23
- package/dist/surfaces/tui/event-log.mjs.map +1 -1
- package/dist/surfaces/tui/input.mjs +5 -1
- package/dist/surfaces/tui/input.mjs.map +1 -1
- package/dist/surfaces/tui/plain-renderer.mjs +70 -34
- package/dist/surfaces/tui/plain-renderer.mjs.map +1 -1
- package/package.json +24 -4
- package/dist/contracts/liveness-classifier.d.mts +0 -19
- package/dist/contracts/network-resolver.d.mts +0 -15
- package/dist/contracts/network-resolver.mjs +0 -7
- package/dist/contracts/network-resolver.mjs.map +0 -1
- package/dist/orchestrators/codegen/extras.mjs +0 -16
- package/dist/orchestrators/codegen/extras.mjs.map +0 -1
- package/dist/plugins/deepbook/routable.mjs +0 -21
- package/dist/plugins/deepbook/routable.mjs.map +0 -1
- package/dist/plugins/faucet/service.d.mts +0 -20
- package/dist/plugins/faucet/strategies/sui-local.d.mts +0 -23
- package/dist/plugins/faucet/strategies/sui-local.mjs.map +0 -1
- package/dist/plugins/sui/seed-objects.d.mts +0 -18
- package/dist/plugins/sui/seed-objects.mjs +0 -25
- package/dist/plugins/sui/seed-objects.mjs.map +0 -1
- package/dist/runtime/built-in-plugin-layers.mjs.map +0 -1
- package/dist/substrate/runtime/context-helpers.mjs +0 -32
- package/dist/substrate/runtime/context-helpers.mjs.map +0 -1
- package/dist/substrate/runtime/run.mjs.map +0 -1
- package/dist/substrate/runtime/strategy-registry/faucet-capability-for.mjs +0 -30
- package/dist/substrate/runtime/strategy-registry/faucet-capability-for.mjs.map +0 -1
- package/dist/substrate/runtime/supervisor.d.mts +0 -1
- package/dist/substrate/runtime/supervisor.mjs +0 -831
- package/dist/substrate/runtime/supervisor.mjs.map +0 -1
- package/dist/surfaces/cli/commands/doctor-probes.mjs.map +0 -1
- /package/dist/{substrate/runtime/strategy-registry/faucet-capability-for.d.mts → plugins/faucet/http.d.mts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatter-registry.mjs","names":[],"sources":["../../../../src/substrate/runtime/observability/formatter-registry.ts"],"sourcesContent":["// Formatter registry service.\n//\n// Architecture § L0 Observability: the cascade formatter consults a\n// per-tag `FormatterRegistry` for custom renderers. The registry is\n// substrate-owned and populated by the supervisor's harvest loop from\n// each acquired plugin's `errorContributions` field. The substrate\n// stays name-blind: it dispatches on `_tag` strings the plugins\n// declare, never on plugin identifiers.\n//\n// Two surfaces:\n// - `register(contribution)` — adds tags + optional formatter for a\n// single `PluginErrorContribution`. Idempotent on the tag set\n// when no formatter is provided; last-write-wins on the formatter\n// slot when one is.\n// - `snapshot()` — returns an immutable `FormatterRegistry` the\n// cascade formatter consumes.\n//\n// Scope-bound: callers `register` inside a plugin's scope so the\n// contribution dies with the plugin (selective restart, shutdown).\n// The supervisor uses `Effect.addFinalizer` at the dispatch site;\n// this service exposes the unregister side as a complement.\n\nimport { Context, Effect, Layer,
|
|
1
|
+
{"version":3,"file":"formatter-registry.mjs","names":[],"sources":["../../../../src/substrate/runtime/observability/formatter-registry.ts"],"sourcesContent":["// Formatter registry service.\n//\n// Architecture § L0 Observability: the cascade formatter consults a\n// per-tag `FormatterRegistry` for custom renderers. The registry is\n// substrate-owned and populated by the supervisor's harvest loop from\n// each acquired plugin's `errorContributions` field. The substrate\n// stays name-blind: it dispatches on `_tag` strings the plugins\n// declare, never on plugin identifiers.\n//\n// Two surfaces:\n// - `register(contribution)` — adds tags + optional formatter for a\n// single `PluginErrorContribution`. Idempotent on the tag set\n// when no formatter is provided; last-write-wins on the formatter\n// slot when one is.\n// - `snapshot()` — returns an immutable `FormatterRegistry` the\n// cascade formatter consumes.\n//\n// Scope-bound: callers `register` inside a plugin's scope so the\n// contribution dies with the plugin (selective restart, shutdown).\n// The supervisor uses `Effect.addFinalizer` at the dispatch site;\n// this service exposes the unregister side as a complement.\n\nimport { Context, Effect, Layer, Scope } from 'effect';\n\nimport type { PluginErrorContribution } from '../../plugin.ts';\nimport { makeScopedMultimap } from '../scoped-multimap/index.ts';\nimport {\n\temptyFormatterRegistry,\n\ttype FormatterRegistry,\n\ttype TagFormatter,\n} from './cascade-formatter.ts';\n\n/** Public shape of the formatter-registry service. */\nexport interface FormatterRegistryShape {\n\t/** Register a plugin's contribution. Scope-bound: the contribution\n\t * is reaped when the surrounding `Scope` closes. The supervisor\n\t * calls this inside each plugin's scope so selective-restart\n\t * cleans up the plugin's formatters automatically. */\n\treadonly register: (\n\t\tcontribution: PluginErrorContribution,\n\t) => Effect.Effect<void, never, Scope.Scope>;\n\t/** Snapshot the live registry as an immutable `FormatterRegistry`\n\t * the cascade formatter consumes. */\n\treadonly snapshot: Effect.Effect<FormatterRegistry>;\n\t/** Diagnostic: list every tag the registry currently tracks. */\n\treadonly tags: Effect.Effect<ReadonlyArray<string>>;\n}\n\nexport class FormatterRegistryService extends Context.Service<\n\tFormatterRegistryService,\n\tFormatterRegistryShape\n>()('@devstack/substrate/FormatterRegistry') {}\n\n/** Layer constructing the per-stack formatter registry. Stateful;\n * the substrate provides one per supervisor scope.\n *\n * Storage is the shared scoped-multimap keyed by tag. The per-entry\n * value is the (optional) formatter — the registry may track a tag\n * with NO formatter (default rendering is enough), so `null` is a\n * legitimate value and the seq still tracks the registration. */\nexport const layerFormatterRegistry: Layer.Layer<FormatterRegistryService> = Layer.effect(\n\tFormatterRegistryService,\n\tEffect.gen(function* () {\n\t\tconst store = yield* makeScopedMultimap<string, TagFormatter | null>();\n\n\t\tconst register = (\n\t\t\tcontribution: PluginErrorContribution,\n\t\t): Effect.Effect<void, never, Scope.Scope> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\t// Wrap the optional formatter so the cascade-formatter's\n\t\t\t\t// `TagFormatter` shape is consistent regardless of whether\n\t\t\t\t// the plugin provided one.\n\t\t\t\tconst fmt: TagFormatter | null =\n\t\t\t\t\tcontribution.formatter !== undefined\n\t\t\t\t\t\t? (value, recurse) => contribution.formatter!(value, recurse)\n\t\t\t\t\t\t: null;\n\t\t\t\t// One entry per declared tag, all sharing the multimap's\n\t\t\t\t// seq + finalizer — parallel plugin registrations stay\n\t\t\t\t// isolated and only drop what they added.\n\t\t\t\tyield* store.register(contribution.errorTags.map((tag) => ({ key: tag, value: fmt })));\n\t\t\t}).pipe(Effect.withSpan('substrate.formatterRegistry.register'));\n\n\t\tconst snapshot: Effect.Effect<FormatterRegistry> = Effect.gen(function* () {\n\t\t\tconst current = yield* store.snapshot;\n\t\t\tif (current.size === 0) return emptyFormatterRegistry;\n\t\t\tconst out = new Map<string, TagFormatter>();\n\t\t\tfor (const [tag, entries] of current) {\n\t\t\t\t// Last registration wins on the formatter slot — tags\n\t\t\t\t// without a custom formatter are still tracked so callers\n\t\t\t\t// can introspect via `tags()` even when no override is\n\t\t\t\t// registered.\n\t\t\t\tlet chosen: TagFormatter | null = null;\n\t\t\t\tlet chosenSeq = -1;\n\t\t\t\tfor (const e of entries) {\n\t\t\t\t\tif (e.value !== null && e.seq > chosenSeq) {\n\t\t\t\t\t\tchosen = e.value;\n\t\t\t\t\t\tchosenSeq = e.seq;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (chosen !== null) out.set(tag, chosen);\n\t\t\t}\n\t\t\treturn out as FormatterRegistry;\n\t\t});\n\n\t\tconst tags: Effect.Effect<ReadonlyArray<string>> = store.keys;\n\n\t\treturn FormatterRegistryService.of({ register, snapshot, tags });\n\t}),\n);\n"],"mappings":";;;;;AAgDA,IAAa,2BAAb,cAA8C,QAAQ,SAGnD,CAAC,wCAAwC,CAAC;;;;;;;;AAS7C,MAAa,yBAAgE,MAAM,OAClF,0BACA,OAAO,IAAI,aAAa;CACvB,MAAM,QAAQ,OAAO,oBAAiD;CAEtE,MAAM,YACL,iBAEA,OAAO,IAAI,aAAa;EAIvB,MAAM,MACL,aAAa,cAAc,KAAA,KACvB,OAAO,YAAY,aAAa,UAAW,OAAO,QAAQ,GAC3D;AAIJ,SAAO,MAAM,SAAS,aAAa,UAAU,KAAK,SAAS;GAAE,KAAK;GAAK,OAAO;GAAK,EAAE,CAAC;GACrF,CAAC,KAAK,OAAO,SAAS,uCAAuC,CAAC;CAEjE,MAAM,WAA6C,OAAO,IAAI,aAAa;EAC1E,MAAM,UAAU,OAAO,MAAM;AAC7B,MAAI,QAAQ,SAAS,EAAG,QAAO;EAC/B,MAAM,sBAAM,IAAI,KAA2B;AAC3C,OAAK,MAAM,CAAC,KAAK,YAAY,SAAS;GAKrC,IAAI,SAA8B;GAClC,IAAI,YAAY;AAChB,QAAK,MAAM,KAAK,QACf,KAAI,EAAE,UAAU,QAAQ,EAAE,MAAM,WAAW;AAC1C,aAAS,EAAE;AACX,gBAAY,EAAE;;AAGhB,OAAI,WAAW,KAAM,KAAI,IAAI,KAAK,OAAO;;AAE1C,SAAO;GACN;CAEF,MAAM,OAA6C,MAAM;AAEzD,QAAO,yBAAyB,GAAG;EAAE;EAAU;EAAU;EAAM,CAAC;EAC/D,CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
//#region src/substrate/runtime/observability/ignore-with-log.ts
|
|
3
|
+
const mergeAttrs = (attrs, cause) => attrs === void 0 ? { cause } : {
|
|
4
|
+
...attrs,
|
|
5
|
+
cause
|
|
6
|
+
};
|
|
7
|
+
/** Tap the cause through `Effect.logWarning`, then collapse to `void`.
|
|
8
|
+
* For best-effort cleanup that COULD indicate a real leak / drop. */
|
|
9
|
+
const logWarningAndIgnore = (message, attrs) => (self) => self.pipe(Effect.tapCause((cause) => Effect.logWarning(message, mergeAttrs(attrs, cause))), Effect.ignore);
|
|
10
|
+
/** Tap the cause through `Effect.logDebug`, then catch into a fallback
|
|
11
|
+
* value. For diagnostic-only failures whose downstream call needs a
|
|
12
|
+
* concrete value (e.g. roster read collapses to empty live-pid set). */
|
|
13
|
+
const logDebugAndFallback = (fallback, message, attrs) => (self) => self.pipe(Effect.tapCause((cause) => Effect.logDebug(message, mergeAttrs(attrs, cause))), Effect.catch(() => Effect.succeed(fallback)));
|
|
14
|
+
//#endregion
|
|
15
|
+
export { logDebugAndFallback, logWarningAndIgnore };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=ignore-with-log.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ignore-with-log.mjs","names":[],"sources":["../../../../src/substrate/runtime/observability/ignore-with-log.ts"],"sourcesContent":["// Best-effort with diagnostic breadcrumb — pipe-fn helpers.\n//\n// STYLE_GUIDE §18 calls out the \"best-effort cleanup must still leave\n// a visible breadcrumb\" rule:\n//\n// `.pipe(Effect.ignore)` on a best-effort effect silently swallows\n// the failure. Cleanup paths (router scope-close, lifecycle-prune\n// roster reads, faucet warm-up retries) tolerate the failure but\n// must NOT lose the cause — the cause has to land in the log\n// stream so a leaked dispatch file / stale roster / dead faucet\n// doesn't go silent.\n//\n// Two surfaces:\n//\n// - `logWarningAndIgnore(message, attrs?)` — for failures that\n// COULD indicate a real problem (a scope-close cleanup that\n// could leak a file, contention on a lock we expected to hold)\n// but which the local call site can't act on. Routes the cause\n// through `Effect.logWarning` so it appears in operator output.\n// - `logDebugAndFallback(fallback, message, attrs?)` — for\n// diagnostic-only failures whose downstream call needs a concrete\n// fallback value (e.g. roster read collapses to empty live-pid).\n//\n// Both helpers use `Effect.tapCause` so the full Cause (defects,\n// interruptions, error stacks) is preserved in the `cause` log\n// annotation; the underlying `Effect.ignore` / `Effect.catch` then\n// erases the error channel.\n\nimport { Effect } from 'effect';\n\ntype LogAttrs = Readonly<Record<string, unknown>>;\n\nconst mergeAttrs = (attrs: LogAttrs | undefined, cause: unknown): LogAttrs =>\n\tattrs === undefined ? { cause } : { ...attrs, cause };\n\n/** Tap the cause through `Effect.logWarning`, then collapse to `void`.\n * For best-effort cleanup that COULD indicate a real leak / drop. */\nexport const logWarningAndIgnore =\n\t(message: string, attrs?: LogAttrs) =>\n\t<A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<void, never, R> =>\n\t\tself.pipe(\n\t\t\tEffect.tapCause((cause) => Effect.logWarning(message, mergeAttrs(attrs, cause))),\n\t\t\tEffect.ignore,\n\t\t);\n\n/** Tap the cause through `Effect.logDebug`, then catch into a fallback\n * value. For diagnostic-only failures whose downstream call needs a\n * concrete value (e.g. roster read collapses to empty live-pid set). */\nexport const logDebugAndFallback =\n\t<F>(fallback: F, message: string, attrs?: LogAttrs) =>\n\t<A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A | F, never, R> =>\n\t\tself.pipe(\n\t\t\tEffect.tapCause((cause) => Effect.logDebug(message, mergeAttrs(attrs, cause))),\n\t\t\tEffect.catch(() => Effect.succeed(fallback)),\n\t\t);\n"],"mappings":";;AAgCA,MAAM,cAAc,OAA6B,UAChD,UAAU,KAAA,IAAY,EAAE,OAAO,GAAG;CAAE,GAAG;CAAO;CAAO;;;AAItD,MAAa,uBACX,SAAiB,WACR,SACT,KAAK,KACJ,OAAO,UAAU,UAAU,OAAO,WAAW,SAAS,WAAW,OAAO,MAAM,CAAC,CAAC,EAChF,OAAO,OACP;;;;AAKH,MAAa,uBACR,UAAa,SAAiB,WACxB,SACT,KAAK,KACJ,OAAO,UAAU,UAAU,OAAO,SAAS,SAAS,WAAW,OAAO,MAAM,CAAC,CAAC,EAC9E,OAAO,YAAY,OAAO,QAAQ,SAAS,CAAC,CAC5C"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { RedactionRule,
|
|
1
|
+
import { RedactionRule, redactText, redactValue } from "./redaction.mjs";
|
|
2
2
|
import { LogLevel, LogLine, LogPayload, Logger, LoggerShape, TagBuffer } from "./logger.mjs";
|
|
3
3
|
import { ObserveProcessLinesOptions, ObservedProcessLine, ProcessByteStream, ProcessOutputStream, observeProcessLines, readableToByteStream, splitUtf8Lines } from "./process-lines.mjs";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import "./spans.mjs";
|
|
2
|
+
import "./redaction.mjs";
|
|
3
|
+
import "./cascade-formatter.mjs";
|
|
4
|
+
import "./formatter-registry.mjs";
|
|
5
|
+
import "./ignore-with-log.mjs";
|
|
6
|
+
import "./logger.mjs";
|
|
7
|
+
import "./log-store.mjs";
|
|
8
|
+
import "./span-store.mjs";
|
|
9
|
+
import "./pretty-error.mjs";
|
|
10
|
+
import "./process-lines.mjs";
|
|
11
|
+
import "./subprocess-capture.mjs";
|
|
12
|
+
import "./output-truncate.mjs";
|
|
13
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { Context, Effect, Layer, Ref } from "effect";
|
|
2
|
+
//#region src/substrate/runtime/observability/log-store.ts
|
|
3
|
+
/** Per-service retention. Each service ring keeps at most this many records;
|
|
4
|
+
* a chatty service evicts only its own oldest lines. */
|
|
5
|
+
const DEFAULT_PER_SERVICE_CAPACITY = 2e3;
|
|
6
|
+
/** Env-var names for zero-config tuning. Read once when `makeLogStore` is
|
|
7
|
+
* called with no explicit config (the supervisor wiring site). Non-numeric
|
|
8
|
+
* or non-positive values fall back to the defaults. */
|
|
9
|
+
const ENV_PER_SERVICE_CAPACITY = "DEVSTACK_DASHBOARD_LOG_CAPACITY";
|
|
10
|
+
const ENV_MAX_SERVICES = "DEVSTACK_DASHBOARD_LOG_MAX_SERVICES";
|
|
11
|
+
const positiveIntOr = (raw, fallback) => {
|
|
12
|
+
if (raw === void 0) return fallback;
|
|
13
|
+
const n = Number(raw);
|
|
14
|
+
return Number.isFinite(n) && n >= 1 ? Math.floor(n) : fallback;
|
|
15
|
+
};
|
|
16
|
+
/** Resolve the effective config: explicit options win, then env vars, then
|
|
17
|
+
* module defaults. Pure given an `env` bag (defaults to `process.env`). */
|
|
18
|
+
const resolveLogStoreConfig = (config = {}, env = process.env) => ({
|
|
19
|
+
perServiceCapacity: config.perServiceCapacity !== void 0 && config.perServiceCapacity >= 1 ? Math.floor(config.perServiceCapacity) : positiveIntOr(env[ENV_PER_SERVICE_CAPACITY], DEFAULT_PER_SERVICE_CAPACITY),
|
|
20
|
+
maxServices: config.maxServices !== void 0 && config.maxServices >= 1 ? Math.floor(config.maxServices) : positiveIntOr(env[ENV_MAX_SERVICES], 256)
|
|
21
|
+
});
|
|
22
|
+
var LogStore = class extends Context.Service()("@devstack/substrate/LogStore") {};
|
|
23
|
+
const isErrorLevel = (level) => level === "error" || level === "fatal";
|
|
24
|
+
/** Choose which service ring to evict when `maxServices` is reached and a new
|
|
25
|
+
* service appears. Policy (documented in the file header):
|
|
26
|
+
* 1. Prefer to RETAIN rings that hold an `error`/`fatal` record — never
|
|
27
|
+
* drop a crashed/quiet service's only error trail while a chatty
|
|
28
|
+
* all-`info` ring exists. So victims are drawn from the error-free
|
|
29
|
+
* rings first; only if EVERY ring carries an error do we consider
|
|
30
|
+
* error-bearing ones.
|
|
31
|
+
* 2. Within the candidate pool, evict the ring whose NEWEST record is
|
|
32
|
+
* oldest (LRU on most-recent activity) — the least recently active
|
|
33
|
+
* service. Ties broken by lowest newest-seq.
|
|
34
|
+
* Returns the service key to drop, or null when there are no rings. */
|
|
35
|
+
const pickEvictionVictim = (rings) => {
|
|
36
|
+
let victim = null;
|
|
37
|
+
let victimNewestMillis = Number.POSITIVE_INFINITY;
|
|
38
|
+
let victimNewestSeq = Number.POSITIVE_INFINITY;
|
|
39
|
+
let victimHasError = true;
|
|
40
|
+
for (const [service, ring] of rings) {
|
|
41
|
+
const newest = ring.records[ring.records.length - 1];
|
|
42
|
+
const newestMillis = newest?.timestampMillis ?? Number.NEGATIVE_INFINITY;
|
|
43
|
+
const newestSeq = newest?.seq ?? Number.NEGATIVE_INFINITY;
|
|
44
|
+
const hasError = ring.hasError;
|
|
45
|
+
if (victimHasError && !hasError) {
|
|
46
|
+
victim = service;
|
|
47
|
+
victimNewestMillis = newestMillis;
|
|
48
|
+
victimNewestSeq = newestSeq;
|
|
49
|
+
victimHasError = hasError;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (!victimHasError && hasError) continue;
|
|
53
|
+
if (newestMillis < victimNewestMillis || newestMillis === victimNewestMillis && newestSeq < victimNewestSeq) {
|
|
54
|
+
victim = service;
|
|
55
|
+
victimNewestMillis = newestMillis;
|
|
56
|
+
victimNewestSeq = newestSeq;
|
|
57
|
+
victimHasError = hasError;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return victim;
|
|
61
|
+
};
|
|
62
|
+
/** Build a `LogStoreShape` over a freshly-created `Ref`. The supervisor calls
|
|
63
|
+
* this (not the Layer) so the rings are process-scoped alongside the
|
|
64
|
+
* projection ref. `config` is injectable for tests; with no `config` the
|
|
65
|
+
* env-var defaults apply. */
|
|
66
|
+
const makeLogStore = (config = {}) => Effect.gen(function* () {
|
|
67
|
+
const { perServiceCapacity, maxServices } = resolveLogStoreConfig(config);
|
|
68
|
+
const ref = yield* Ref.make({
|
|
69
|
+
rings: /* @__PURE__ */ new Map(),
|
|
70
|
+
nextSeq: 0
|
|
71
|
+
});
|
|
72
|
+
const append = (record) => Ref.update(ref, (state) => {
|
|
73
|
+
const next = {
|
|
74
|
+
seq: state.nextSeq,
|
|
75
|
+
timestampMillis: record.timestampMillis ?? Date.now(),
|
|
76
|
+
level: record.level,
|
|
77
|
+
service: record.service,
|
|
78
|
+
message: record.message,
|
|
79
|
+
fields: record.fields ?? {}
|
|
80
|
+
};
|
|
81
|
+
const rings = new Map(state.rings);
|
|
82
|
+
const existing = rings.get(record.service);
|
|
83
|
+
if (existing === void 0) {
|
|
84
|
+
if (rings.size >= maxServices) {
|
|
85
|
+
const victim = pickEvictionVictim(rings);
|
|
86
|
+
if (victim !== null) rings.delete(victim);
|
|
87
|
+
}
|
|
88
|
+
rings.set(record.service, {
|
|
89
|
+
records: [next],
|
|
90
|
+
hasError: isErrorLevel(next.level)
|
|
91
|
+
});
|
|
92
|
+
} else {
|
|
93
|
+
const merged = [...existing.records, next];
|
|
94
|
+
const trimmed = merged.length > perServiceCapacity ? merged.slice(-perServiceCapacity) : merged;
|
|
95
|
+
const hasError = trimmed.length < merged.length ? trimmed.some((r) => isErrorLevel(r.level)) : existing.hasError || isErrorLevel(next.level);
|
|
96
|
+
rings.set(record.service, {
|
|
97
|
+
records: trimmed,
|
|
98
|
+
hasError
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
rings,
|
|
103
|
+
nextSeq: state.nextSeq + 1
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
const query = (filter) => Ref.get(ref).pipe(Effect.map((state) => queryRings(state.rings, filter, perServiceCapacity)));
|
|
107
|
+
const services = Ref.get(ref).pipe(Effect.map((state) => [...state.rings.keys()].sort()));
|
|
108
|
+
return LogStore.of({
|
|
109
|
+
append,
|
|
110
|
+
query,
|
|
111
|
+
services
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
const compileFilter = (filter, defaultLimit) => {
|
|
115
|
+
const search = filter?.search?.trim().toLowerCase();
|
|
116
|
+
return {
|
|
117
|
+
serviceSet: filter?.services && filter.services.length > 0 ? new Set(filter.services) : null,
|
|
118
|
+
levelSet: filter?.levels && filter.levels.length > 0 ? new Set(filter.levels) : null,
|
|
119
|
+
search: search !== void 0 && search.length > 0 ? search : null,
|
|
120
|
+
since: filter?.sinceMillis,
|
|
121
|
+
limit: filter?.limit ?? defaultLimit
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
const matches = (r, f) => {
|
|
125
|
+
if (f.serviceSet !== null && !f.serviceSet.has(r.service)) return false;
|
|
126
|
+
if (f.levelSet !== null && !f.levelSet.has(r.level)) return false;
|
|
127
|
+
if (f.since !== void 0 && r.timestampMillis < f.since) return false;
|
|
128
|
+
if (f.search !== null && !r.message.toLowerCase().includes(f.search) && !r.service.toLowerCase().includes(f.search)) return false;
|
|
129
|
+
return true;
|
|
130
|
+
};
|
|
131
|
+
/** Merge all per-service rings into a single newest-first result. Each ring
|
|
132
|
+
* is oldest-first, so we run a k-way merge from the tail of each ring,
|
|
133
|
+
* emitting the globally-highest `seq` first and stopping once `limit` is
|
|
134
|
+
* filled. This is O(matched-prefix × ringCount) without materializing the
|
|
135
|
+
* whole universe — important when `limit` is small relative to total volume.
|
|
136
|
+
* Exported for tests. */
|
|
137
|
+
const queryRings = (rings, filter, perServiceCapacity) => {
|
|
138
|
+
const f = compileFilter(filter, perServiceCapacity * Math.max(rings.size, 1));
|
|
139
|
+
if (f.limit <= 0) return [];
|
|
140
|
+
const arrays = [];
|
|
141
|
+
const cursors = [];
|
|
142
|
+
for (const ring of rings.values()) if (ring.records.length > 0) {
|
|
143
|
+
arrays.push(ring.records);
|
|
144
|
+
cursors.push(ring.records.length - 1);
|
|
145
|
+
}
|
|
146
|
+
const out = [];
|
|
147
|
+
while (out.length < f.limit) {
|
|
148
|
+
let bestRing = -1;
|
|
149
|
+
let bestSeq = Number.NEGATIVE_INFINITY;
|
|
150
|
+
for (let k = 0; k < arrays.length; k += 1) {
|
|
151
|
+
const c = cursors[k];
|
|
152
|
+
if (c < 0) continue;
|
|
153
|
+
const seq = arrays[k][c].seq;
|
|
154
|
+
if (seq > bestSeq) {
|
|
155
|
+
bestSeq = seq;
|
|
156
|
+
bestRing = k;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (bestRing === -1) break;
|
|
160
|
+
const c = cursors[bestRing];
|
|
161
|
+
const r = arrays[bestRing][c];
|
|
162
|
+
cursors[bestRing] = c - 1;
|
|
163
|
+
if (matches(r, f)) out.push(r);
|
|
164
|
+
}
|
|
165
|
+
return out;
|
|
166
|
+
};
|
|
167
|
+
Layer.effect(LogStore, makeLogStore());
|
|
168
|
+
/** Coerce an arbitrary `pluginKey` (the upstream `Logger.log` tag carries an
|
|
169
|
+
* optional `PluginKey`) to the store's `service` string, falling back to the
|
|
170
|
+
* bare log tag when no plugin key is present. */
|
|
171
|
+
const serviceKeyFor = (tag, pluginKey) => pluginKey === null ? tag : String(pluginKey);
|
|
172
|
+
//#endregion
|
|
173
|
+
export { DEFAULT_PER_SERVICE_CAPACITY, ENV_MAX_SERVICES, ENV_PER_SERVICE_CAPACITY, LogStore, makeLogStore, pickEvictionVictim, queryRings, resolveLogStoreConfig, serviceKeyFor };
|
|
174
|
+
|
|
175
|
+
//# sourceMappingURL=log-store.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-store.mjs","names":[],"sources":["../../../../src/substrate/runtime/observability/log-store.ts"],"sourcesContent":["// Cross-service queryable log store.\n//\n// The `Logger` service (logger.ts) keeps a bounded PER-TAG ring buffer that\n// feeds the projection's per-row `logTail`. That surface is renderer-facing:\n// one short tail per plugin row, no cross-service merge, no history, no\n// server-side level/source filtering. The dashboard's Console \"Logs\" tab\n// needs the opposite shape — a single append-only, cross-service stream the\n// browser can filter by service / level / substring / time window.\n//\n// This store is that second surface. It is fed from the SAME source as the\n// projection tail (the supervisor's `withEventPublishingLogger` wrapper taps\n// every `Logger.log` call into here), so we do NOT double-spawn log readers\n// or re-capture container output: there is one log-production path\n// (`Logger.log`) and two consumers hang off it.\n//\n// Shape: ONE BOUNDED RING PER SERVICE, keyed by the `service` string, plus a\n// shared monotonic `seq` counter so cross-service queries order correctly.\n// A single global ring (the previous design) let a chatty service evict\n// everyone else — a crash loop spamming retries would push a quiet service's\n// only error line out of the buffer before anyone could read it. Per-service\n// rings give every service an independent retention window: a noisy service\n// can only ever evict ITS OWN old lines.\n//\n// To keep total memory bounded under an unbounded set of distinct service\n// keys, the number of rings is capped (`maxServices`). When that cap is hit\n// and a brand-new service appears, one existing ring is evicted. Eviction is\n// ERROR-AWARE: rings that contain an `error`/`fatal` record are preferred for\n// RETENTION, so a crashed service's error trail is the last thing dropped.\n// Among equally-(un)important rings we evict the one whose NEWEST record is\n// oldest (LRU on most-recent activity). See `pickEvictionVictim`.\n//\n// Process-scoped — the backing `Ref` is created in the supervisor alongside\n// `hub`/`commands`, so it survives `stack.restart` (only `cycle.id` bumps)\n// exactly like the projection ref.\n//\n// Hot-path discipline: append is a single `Ref.update` that pushes onto the\n// target service's array and trims when it overflows. No I/O, no redaction\n// (the upstream `Logger.log` already redacted the message + fields before\n// calling here). Ring eviction only runs on the FIRST sight of a new service\n// once the cap is reached — not per-append.\n\nimport { Context, Effect, Layer, Ref } from 'effect';\n\nimport type { PluginKey } from '../../brand.ts';\nimport type { LogLevel } from './logger.ts';\n\n// -----------------------------------------------------------------------------\n// Record shape\n// -----------------------------------------------------------------------------\n\n/** One queryable, cross-service log record. Plain data — the dashboard\n * schema projects this directly. `service` is the resource/plugin key the\n * line was logged under (or the bare tag when no plugin key was attached,\n * e.g. the supervisor's own lines). */\nexport interface LogRecord {\n\t/** Monotonic per-process sequence. Stable cursor for the dashboard. */\n\treadonly seq: number;\n\treadonly timestampMillis: number;\n\treadonly level: LogLevel;\n\t/** Resource/plugin key (`postgres`, `deepbook/SUI_USDC`, …) or the bare\n\t * log tag when the line carried no plugin key. */\n\treadonly service: string;\n\treadonly message: string;\n\t/** Structured fields (already redacted upstream). */\n\treadonly fields: Readonly<Record<string, unknown>>;\n}\n\n/** Filter applied server-side before the records cross to the browser. Every\n * field is optional; an absent field means \"don't constrain on this axis\". */\nexport interface LogFilter {\n\t/** Keep only records whose `service` is in this set (exact match). */\n\treadonly services?: ReadonlyArray<string>;\n\t/** Keep only records at one of these levels. */\n\treadonly levels?: ReadonlyArray<LogLevel>;\n\t/** Case-insensitive substring match against the message (and service). */\n\treadonly search?: string;\n\t/** Keep only records at/after this epoch-ms. */\n\treadonly sinceMillis?: number;\n\t/** Cap on returned records (most recent first). Defaults to the merged\n\t * capacity (perServiceCapacity × maxServices). */\n\treadonly limit?: number;\n}\n\n// -----------------------------------------------------------------------------\n// Capacity policy\n// -----------------------------------------------------------------------------\n\n/** Per-service retention. Each service ring keeps at most this many records;\n * a chatty service evicts only its own oldest lines. */\nexport const DEFAULT_PER_SERVICE_CAPACITY = 2000;\n\n/** Max distinct service rings kept simultaneously. Caps total memory at\n * `perServiceCapacity × maxServices` records. When exceeded, one ring is\n * evicted (error-bearing rings preferred for retention — see\n * `pickEvictionVictim`). */\nexport const DEFAULT_MAX_SERVICES = 256;\n\n/** Env-var names for zero-config tuning. Read once when `makeLogStore` is\n * called with no explicit config (the supervisor wiring site). Non-numeric\n * or non-positive values fall back to the defaults. */\nexport const ENV_PER_SERVICE_CAPACITY = 'DEVSTACK_DASHBOARD_LOG_CAPACITY';\nexport const ENV_MAX_SERVICES = 'DEVSTACK_DASHBOARD_LOG_MAX_SERVICES';\n\n/** Tunables for the per-service log store. Both optional; absent fields take\n * the module defaults (or the corresponding env var, when resolved via\n * `resolveLogStoreConfig`). */\nexport interface LogStoreConfig {\n\t/** Max records kept per service ring. Default {@link DEFAULT_PER_SERVICE_CAPACITY}. */\n\treadonly perServiceCapacity?: number;\n\t/** Max distinct service rings. Default {@link DEFAULT_MAX_SERVICES}. */\n\treadonly maxServices?: number;\n}\n\ninterface ResolvedLogStoreConfig {\n\treadonly perServiceCapacity: number;\n\treadonly maxServices: number;\n}\n\nconst positiveIntOr = (raw: string | undefined, fallback: number): number => {\n\tif (raw === undefined) return fallback;\n\tconst n = Number(raw);\n\treturn Number.isFinite(n) && n >= 1 ? Math.floor(n) : fallback;\n};\n\n/** Resolve the effective config: explicit options win, then env vars, then\n * module defaults. Pure given an `env` bag (defaults to `process.env`). */\nexport const resolveLogStoreConfig = (\n\tconfig: LogStoreConfig = {},\n\tenv: Record<string, string | undefined> = process.env,\n): ResolvedLogStoreConfig => ({\n\tperServiceCapacity:\n\t\tconfig.perServiceCapacity !== undefined && config.perServiceCapacity >= 1\n\t\t\t? Math.floor(config.perServiceCapacity)\n\t\t\t: positiveIntOr(env[ENV_PER_SERVICE_CAPACITY], DEFAULT_PER_SERVICE_CAPACITY),\n\tmaxServices:\n\t\tconfig.maxServices !== undefined && config.maxServices >= 1\n\t\t\t? Math.floor(config.maxServices)\n\t\t\t: positiveIntOr(env[ENV_MAX_SERVICES], DEFAULT_MAX_SERVICES),\n});\n\n// -----------------------------------------------------------------------------\n// Service\n// -----------------------------------------------------------------------------\n\nexport interface LogStoreShape {\n\t/** Append a record. Called from the supervisor's logger tap on the hot\n\t * path — a single `Ref.update`, no I/O. Routes to the per-service ring\n\t * (created on first sight of a service). */\n\treadonly append: (record: {\n\t\treadonly level: LogLevel;\n\t\treadonly service: string;\n\t\treadonly message: string;\n\t\treadonly fields?: Readonly<Record<string, unknown>>;\n\t\treadonly timestampMillis?: number;\n\t}) => Effect.Effect<void>;\n\t/** Query across all per-service rings with a filter. Returns\n\t * most-recent-first by `seq`, capped by `filter.limit`. Never fails. */\n\treadonly query: (filter?: LogFilter) => Effect.Effect<ReadonlyArray<LogRecord>>;\n\t/** Distinct service keys with a live ring (for filter dropdowns). */\n\treadonly services: Effect.Effect<ReadonlyArray<string>>;\n}\n\nexport class LogStore extends Context.Service<LogStore, LogStoreShape>()(\n\t'@devstack/substrate/LogStore',\n) {}\n\n/** One service's bounded ring. `records` is oldest-first; `hasError` is a\n * cached flag so eviction doesn't rescan the array (set when any\n * `error`/`fatal` record is present after trimming). */\ninterface ServiceRing {\n\treadonly records: ReadonlyArray<LogRecord>;\n\treadonly hasError: boolean;\n}\n\ninterface StoreState {\n\t/** Per-service rings. A `Map` so first-sight insertion / eviction is O(1)\n\t * and iteration order is insertion order (irrelevant — query sorts by\n\t * seq). */\n\treadonly rings: ReadonlyMap<string, ServiceRing>;\n\treadonly nextSeq: number;\n}\n\nconst isErrorLevel = (level: LogLevel): boolean => level === 'error' || level === 'fatal';\n\n/** Choose which service ring to evict when `maxServices` is reached and a new\n * service appears. Policy (documented in the file header):\n * 1. Prefer to RETAIN rings that hold an `error`/`fatal` record — never\n * drop a crashed/quiet service's only error trail while a chatty\n * all-`info` ring exists. So victims are drawn from the error-free\n * rings first; only if EVERY ring carries an error do we consider\n * error-bearing ones.\n * 2. Within the candidate pool, evict the ring whose NEWEST record is\n * oldest (LRU on most-recent activity) — the least recently active\n * service. Ties broken by lowest newest-seq.\n * Returns the service key to drop, or null when there are no rings. */\nexport const pickEvictionVictim = (rings: ReadonlyMap<string, ServiceRing>): string | null => {\n\tlet victim: string | null = null;\n\tlet victimNewestMillis = Number.POSITIVE_INFINITY;\n\tlet victimNewestSeq = Number.POSITIVE_INFINITY;\n\tlet victimHasError = true;\n\n\tfor (const [service, ring] of rings) {\n\t\tconst newest = ring.records[ring.records.length - 1];\n\t\t// An empty ring should never exist (we only create on append), but be\n\t\t// defensive: treat it as the most-evictable.\n\t\tconst newestMillis = newest?.timestampMillis ?? Number.NEGATIVE_INFINITY;\n\t\tconst newestSeq = newest?.seq ?? Number.NEGATIVE_INFINITY;\n\t\tconst hasError = ring.hasError;\n\n\t\t// An error-free ring always beats an error-bearing one as a victim.\n\t\tif (victimHasError && !hasError) {\n\t\t\tvictim = service;\n\t\t\tvictimNewestMillis = newestMillis;\n\t\t\tvictimNewestSeq = newestSeq;\n\t\t\tvictimHasError = hasError;\n\t\t\tcontinue;\n\t\t}\n\t\t// Don't replace an error-free candidate with an error-bearing one.\n\t\tif (!victimHasError && hasError) continue;\n\n\t\t// Same error-class: prefer the one whose newest record is oldest.\n\t\tif (\n\t\t\tnewestMillis < victimNewestMillis ||\n\t\t\t(newestMillis === victimNewestMillis && newestSeq < victimNewestSeq)\n\t\t) {\n\t\t\tvictim = service;\n\t\t\tvictimNewestMillis = newestMillis;\n\t\t\tvictimNewestSeq = newestSeq;\n\t\t\tvictimHasError = hasError;\n\t\t}\n\t}\n\treturn victim;\n};\n\n/** Build a `LogStoreShape` over a freshly-created `Ref`. The supervisor calls\n * this (not the Layer) so the rings are process-scoped alongside the\n * projection ref. `config` is injectable for tests; with no `config` the\n * env-var defaults apply. */\nexport const makeLogStore = (config: LogStoreConfig = {}): Effect.Effect<LogStoreShape> =>\n\tEffect.gen(function* () {\n\t\tconst { perServiceCapacity, maxServices } = resolveLogStoreConfig(config);\n\t\tconst ref = yield* Ref.make<StoreState>({ rings: new Map(), nextSeq: 0 });\n\n\t\tconst append: LogStoreShape['append'] = (record) =>\n\t\t\tRef.update(ref, (state) => {\n\t\t\t\tconst next: LogRecord = {\n\t\t\t\t\tseq: state.nextSeq,\n\t\t\t\t\ttimestampMillis: record.timestampMillis ?? Date.now(),\n\t\t\t\t\tlevel: record.level,\n\t\t\t\t\tservice: record.service,\n\t\t\t\t\tmessage: record.message,\n\t\t\t\t\tfields: record.fields ?? {},\n\t\t\t\t};\n\n\t\t\t\tconst rings = new Map(state.rings);\n\t\t\t\tconst existing = rings.get(record.service);\n\n\t\t\t\tif (existing === undefined) {\n\t\t\t\t\t// First sight of this service — may need to evict to stay\n\t\t\t\t\t// under `maxServices`. Eviction runs ONLY here, not per\n\t\t\t\t\t// append.\n\t\t\t\t\tif (rings.size >= maxServices) {\n\t\t\t\t\t\tconst victim = pickEvictionVictim(rings);\n\t\t\t\t\t\tif (victim !== null) rings.delete(victim);\n\t\t\t\t\t}\n\t\t\t\t\trings.set(record.service, {\n\t\t\t\t\t\trecords: [next],\n\t\t\t\t\t\thasError: isErrorLevel(next.level),\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tconst merged = [...existing.records, next];\n\t\t\t\t\tconst trimmed =\n\t\t\t\t\t\tmerged.length > perServiceCapacity ? merged.slice(-perServiceCapacity) : merged;\n\t\t\t\t\t// Recompute `hasError` only when the trim could have dropped\n\t\t\t\t\t// the last error (i.e. an actual trim happened); otherwise the\n\t\t\t\t\t// flag only ever grows true.\n\t\t\t\t\tconst hasError =\n\t\t\t\t\t\ttrimmed.length < merged.length\n\t\t\t\t\t\t\t? trimmed.some((r) => isErrorLevel(r.level))\n\t\t\t\t\t\t\t: existing.hasError || isErrorLevel(next.level);\n\t\t\t\t\trings.set(record.service, { records: trimmed, hasError });\n\t\t\t\t}\n\n\t\t\t\treturn { rings, nextSeq: state.nextSeq + 1 };\n\t\t\t});\n\n\t\tconst query: LogStoreShape['query'] = (filter) =>\n\t\t\tRef.get(ref).pipe(Effect.map((state) => queryRings(state.rings, filter, perServiceCapacity)));\n\n\t\tconst services: LogStoreShape['services'] = Ref.get(ref).pipe(\n\t\t\tEffect.map((state) => [...state.rings.keys()].sort()),\n\t\t);\n\n\t\treturn LogStore.of({ append, query, services });\n\t});\n\n// -----------------------------------------------------------------------------\n// Query\n// -----------------------------------------------------------------------------\n\ninterface CompiledFilter {\n\treadonly serviceSet: ReadonlySet<string> | null;\n\treadonly levelSet: ReadonlySet<LogLevel> | null;\n\treadonly search: string | null;\n\treadonly since: number | undefined;\n\treadonly limit: number;\n}\n\nconst compileFilter = (filter: LogFilter | undefined, defaultLimit: number): CompiledFilter => {\n\tconst search = filter?.search?.trim().toLowerCase();\n\treturn {\n\t\tserviceSet:\n\t\t\tfilter?.services && filter.services.length > 0 ? new Set(filter.services) : null,\n\t\tlevelSet: filter?.levels && filter.levels.length > 0 ? new Set(filter.levels) : null,\n\t\tsearch: search !== undefined && search.length > 0 ? search : null,\n\t\tsince: filter?.sinceMillis,\n\t\tlimit: filter?.limit ?? defaultLimit,\n\t};\n};\n\nconst matches = (r: LogRecord, f: CompiledFilter): boolean => {\n\tif (f.serviceSet !== null && !f.serviceSet.has(r.service)) return false;\n\tif (f.levelSet !== null && !f.levelSet.has(r.level)) return false;\n\tif (f.since !== undefined && r.timestampMillis < f.since) return false;\n\tif (\n\t\tf.search !== null &&\n\t\t!r.message.toLowerCase().includes(f.search) &&\n\t\t!r.service.toLowerCase().includes(f.search)\n\t) {\n\t\treturn false;\n\t}\n\treturn true;\n};\n\n/** Merge all per-service rings into a single newest-first result. Each ring\n * is oldest-first, so we run a k-way merge from the tail of each ring,\n * emitting the globally-highest `seq` first and stopping once `limit` is\n * filled. This is O(matched-prefix × ringCount) without materializing the\n * whole universe — important when `limit` is small relative to total volume.\n * Exported for tests. */\nexport const queryRings = (\n\trings: ReadonlyMap<string, ServiceRing>,\n\tfilter: LogFilter | undefined,\n\tperServiceCapacity: number,\n): ReadonlyArray<LogRecord> => {\n\tconst f = compileFilter(filter, perServiceCapacity * Math.max(rings.size, 1));\n\tif (f.limit <= 0) return [];\n\n\t// Cursor per ring, walking newest→oldest (from the end of each array).\n\tconst arrays: ReadonlyArray<LogRecord>[] = [];\n\tconst cursors: number[] = [];\n\tfor (const ring of rings.values()) {\n\t\tif (ring.records.length > 0) {\n\t\t\tarrays.push(ring.records);\n\t\t\tcursors.push(ring.records.length - 1);\n\t\t}\n\t}\n\n\tconst out: LogRecord[] = [];\n\twhile (out.length < f.limit) {\n\t\t// Find the ring whose current cursor points at the highest seq.\n\t\tlet bestRing = -1;\n\t\tlet bestSeq = Number.NEGATIVE_INFINITY;\n\t\tfor (let k = 0; k < arrays.length; k += 1) {\n\t\t\tconst c = cursors[k]!;\n\t\t\tif (c < 0) continue;\n\t\t\tconst seq = arrays[k]![c]!.seq;\n\t\t\tif (seq > bestSeq) {\n\t\t\t\tbestSeq = seq;\n\t\t\t\tbestRing = k;\n\t\t\t}\n\t\t}\n\t\tif (bestRing === -1) break; // all rings exhausted\n\n\t\tconst c = cursors[bestRing]!;\n\t\tconst r = arrays[bestRing]![c]!;\n\t\tcursors[bestRing] = c - 1;\n\t\tif (matches(r, f)) out.push(r);\n\t}\n\treturn out;\n};\n\n/** Pure filter application over a flat oldest-first record array — retained\n * for direct use / tests. Returns newest-first, capped to `limit`. */\nexport const applyLogFilter = (\n\trecords: ReadonlyArray<LogRecord>,\n\tfilter: LogFilter | undefined,\n\tcapacity: number,\n): ReadonlyArray<LogRecord> => {\n\tconst f = compileFilter(filter, capacity);\n\tconst out: LogRecord[] = [];\n\tfor (let i = records.length - 1; i >= 0 && out.length < f.limit; i -= 1) {\n\t\tconst r = records[i]!;\n\t\tif (matches(r, f)) out.push(r);\n\t}\n\treturn out;\n};\n\n/** Layer form (for any caller that wants the store via a Layer rather than\n * the supervisor-scoped `makeLogStore`). Uses the default/env config. */\nexport const layerLogStore: Layer.Layer<LogStore> = Layer.effect(LogStore, makeLogStore());\n\n/** Coerce an arbitrary `pluginKey` (the upstream `Logger.log` tag carries an\n * optional `PluginKey`) to the store's `service` string, falling back to the\n * bare log tag when no plugin key is present. */\nexport const serviceKeyFor = (tag: string, pluginKey: PluginKey | null): string =>\n\tpluginKey === null ? tag : String(pluginKey);\n"],"mappings":";;;;AAyFA,MAAa,+BAA+B;;;;AAW5C,MAAa,2BAA2B;AACxC,MAAa,mBAAmB;AAiBhC,MAAM,iBAAiB,KAAyB,aAA6B;AAC5E,KAAI,QAAQ,KAAA,EAAW,QAAO;CAC9B,MAAM,IAAI,OAAO,IAAI;AACrB,QAAO,OAAO,SAAS,EAAE,IAAI,KAAK,IAAI,KAAK,MAAM,EAAE,GAAG;;;;AAKvD,MAAa,yBACZ,SAAyB,EAAE,EAC3B,MAA0C,QAAQ,SACrB;CAC7B,oBACC,OAAO,uBAAuB,KAAA,KAAa,OAAO,sBAAsB,IACrE,KAAK,MAAM,OAAO,mBAAmB,GACrC,cAAc,IAAI,2BAA2B,6BAA6B;CAC9E,aACC,OAAO,gBAAgB,KAAA,KAAa,OAAO,eAAe,IACvD,KAAK,MAAM,OAAO,YAAY,GAC9B,cAAc,IAAI,mBAAA,IAAwC;CAC9D;AAwBD,IAAa,WAAb,cAA8B,QAAQ,SAAkC,CACvE,+BACA,CAAC;AAkBF,MAAM,gBAAgB,UAA6B,UAAU,WAAW,UAAU;;;;;;;;;;;;AAalF,MAAa,sBAAsB,UAA2D;CAC7F,IAAI,SAAwB;CAC5B,IAAI,qBAAqB,OAAO;CAChC,IAAI,kBAAkB,OAAO;CAC7B,IAAI,iBAAiB;AAErB,MAAK,MAAM,CAAC,SAAS,SAAS,OAAO;EACpC,MAAM,SAAS,KAAK,QAAQ,KAAK,QAAQ,SAAS;EAGlD,MAAM,eAAe,QAAQ,mBAAmB,OAAO;EACvD,MAAM,YAAY,QAAQ,OAAO,OAAO;EACxC,MAAM,WAAW,KAAK;AAGtB,MAAI,kBAAkB,CAAC,UAAU;AAChC,YAAS;AACT,wBAAqB;AACrB,qBAAkB;AAClB,oBAAiB;AACjB;;AAGD,MAAI,CAAC,kBAAkB,SAAU;AAGjC,MACC,eAAe,sBACd,iBAAiB,sBAAsB,YAAY,iBACnD;AACD,YAAS;AACT,wBAAqB;AACrB,qBAAkB;AAClB,oBAAiB;;;AAGnB,QAAO;;;;;;AAOR,MAAa,gBAAgB,SAAyB,EAAE,KACvD,OAAO,IAAI,aAAa;CACvB,MAAM,EAAE,oBAAoB,gBAAgB,sBAAsB,OAAO;CACzE,MAAM,MAAM,OAAO,IAAI,KAAiB;EAAE,uBAAO,IAAI,KAAK;EAAE,SAAS;EAAG,CAAC;CAEzE,MAAM,UAAmC,WACxC,IAAI,OAAO,MAAM,UAAU;EAC1B,MAAM,OAAkB;GACvB,KAAK,MAAM;GACX,iBAAiB,OAAO,mBAAmB,KAAK,KAAK;GACrD,OAAO,OAAO;GACd,SAAS,OAAO;GAChB,SAAS,OAAO;GAChB,QAAQ,OAAO,UAAU,EAAE;GAC3B;EAED,MAAM,QAAQ,IAAI,IAAI,MAAM,MAAM;EAClC,MAAM,WAAW,MAAM,IAAI,OAAO,QAAQ;AAE1C,MAAI,aAAa,KAAA,GAAW;AAI3B,OAAI,MAAM,QAAQ,aAAa;IAC9B,MAAM,SAAS,mBAAmB,MAAM;AACxC,QAAI,WAAW,KAAM,OAAM,OAAO,OAAO;;AAE1C,SAAM,IAAI,OAAO,SAAS;IACzB,SAAS,CAAC,KAAK;IACf,UAAU,aAAa,KAAK,MAAM;IAClC,CAAC;SACI;GACN,MAAM,SAAS,CAAC,GAAG,SAAS,SAAS,KAAK;GAC1C,MAAM,UACL,OAAO,SAAS,qBAAqB,OAAO,MAAM,CAAC,mBAAmB,GAAG;GAI1E,MAAM,WACL,QAAQ,SAAS,OAAO,SACrB,QAAQ,MAAM,MAAM,aAAa,EAAE,MAAM,CAAC,GAC1C,SAAS,YAAY,aAAa,KAAK,MAAM;AACjD,SAAM,IAAI,OAAO,SAAS;IAAE,SAAS;IAAS;IAAU,CAAC;;AAG1D,SAAO;GAAE;GAAO,SAAS,MAAM,UAAU;GAAG;GAC3C;CAEH,MAAM,SAAiC,WACtC,IAAI,IAAI,IAAI,CAAC,KAAK,OAAO,KAAK,UAAU,WAAW,MAAM,OAAO,QAAQ,mBAAmB,CAAC,CAAC;CAE9F,MAAM,WAAsC,IAAI,IAAI,IAAI,CAAC,KACxD,OAAO,KAAK,UAAU,CAAC,GAAG,MAAM,MAAM,MAAM,CAAC,CAAC,MAAM,CAAC,CACrD;AAED,QAAO,SAAS,GAAG;EAAE;EAAQ;EAAO;EAAU,CAAC;EAC9C;AAcH,MAAM,iBAAiB,QAA+B,iBAAyC;CAC9F,MAAM,SAAS,QAAQ,QAAQ,MAAM,CAAC,aAAa;AACnD,QAAO;EACN,YACC,QAAQ,YAAY,OAAO,SAAS,SAAS,IAAI,IAAI,IAAI,OAAO,SAAS,GAAG;EAC7E,UAAU,QAAQ,UAAU,OAAO,OAAO,SAAS,IAAI,IAAI,IAAI,OAAO,OAAO,GAAG;EAChF,QAAQ,WAAW,KAAA,KAAa,OAAO,SAAS,IAAI,SAAS;EAC7D,OAAO,QAAQ;EACf,OAAO,QAAQ,SAAS;EACxB;;AAGF,MAAM,WAAW,GAAc,MAA+B;AAC7D,KAAI,EAAE,eAAe,QAAQ,CAAC,EAAE,WAAW,IAAI,EAAE,QAAQ,CAAE,QAAO;AAClE,KAAI,EAAE,aAAa,QAAQ,CAAC,EAAE,SAAS,IAAI,EAAE,MAAM,CAAE,QAAO;AAC5D,KAAI,EAAE,UAAU,KAAA,KAAa,EAAE,kBAAkB,EAAE,MAAO,QAAO;AACjE,KACC,EAAE,WAAW,QACb,CAAC,EAAE,QAAQ,aAAa,CAAC,SAAS,EAAE,OAAO,IAC3C,CAAC,EAAE,QAAQ,aAAa,CAAC,SAAS,EAAE,OAAO,CAE3C,QAAO;AAER,QAAO;;;;;;;;AASR,MAAa,cACZ,OACA,QACA,uBAC8B;CAC9B,MAAM,IAAI,cAAc,QAAQ,qBAAqB,KAAK,IAAI,MAAM,MAAM,EAAE,CAAC;AAC7E,KAAI,EAAE,SAAS,EAAG,QAAO,EAAE;CAG3B,MAAM,SAAqC,EAAE;CAC7C,MAAM,UAAoB,EAAE;AAC5B,MAAK,MAAM,QAAQ,MAAM,QAAQ,CAChC,KAAI,KAAK,QAAQ,SAAS,GAAG;AAC5B,SAAO,KAAK,KAAK,QAAQ;AACzB,UAAQ,KAAK,KAAK,QAAQ,SAAS,EAAE;;CAIvC,MAAM,MAAmB,EAAE;AAC3B,QAAO,IAAI,SAAS,EAAE,OAAO;EAE5B,IAAI,WAAW;EACf,IAAI,UAAU,OAAO;AACrB,OAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK,GAAG;GAC1C,MAAM,IAAI,QAAQ;AAClB,OAAI,IAAI,EAAG;GACX,MAAM,MAAM,OAAO,GAAI,GAAI;AAC3B,OAAI,MAAM,SAAS;AAClB,cAAU;AACV,eAAW;;;AAGb,MAAI,aAAa,GAAI;EAErB,MAAM,IAAI,QAAQ;EAClB,MAAM,IAAI,OAAO,UAAW;AAC5B,UAAQ,YAAY,IAAI;AACxB,MAAI,QAAQ,GAAG,EAAE,CAAE,KAAI,KAAK,EAAE;;AAE/B,QAAO;;AAqB4C,MAAM,OAAO,UAAU,cAAc,CAAC;;;;AAK1F,MAAa,iBAAiB,KAAa,cAC1C,cAAc,OAAO,MAAM,OAAO,UAAU"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { PluginKey } from "../../brand.mjs";
|
|
2
2
|
import { Context, Effect, Layer } from "effect";
|
|
3
|
+
|
|
3
4
|
//#region src/substrate/runtime/observability/logger.d.ts
|
|
4
5
|
/** Closed level set. Mirrors the projection's row.logTail.level
|
|
5
6
|
* vocabulary, plus `debug` / `trace` for lifecycle diagnostics that
|
|
@@ -51,7 +52,7 @@ interface LoggerShape {
|
|
|
51
52
|
readonly readAll: Effect.Effect<ReadonlyMap<string, TagBuffer>>;
|
|
52
53
|
readonly clearTag: (tag: string) => Effect.Effect<void>;
|
|
53
54
|
}
|
|
54
|
-
declare const Logger_base: Context.ServiceClass<Logger$1, "@devstack
|
|
55
|
+
declare const Logger_base: Context.ServiceClass<Logger$1, "@devstack/substrate/Logger", LoggerShape>;
|
|
55
56
|
declare class Logger$1 extends Logger_base {}
|
|
56
57
|
//#endregion
|
|
57
58
|
export { LogLevel, LogLine, LogPayload, Logger$1 as Logger, LoggerShape, TagBuffer };
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import { SpanAttr } from "./spans.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { Context, Data, Effect, Layer, Ref } from "effect";
|
|
4
|
-
Data.TaggedError("LoggerError");
|
|
2
|
+
import { Context, Effect, Layer, Ref } from "effect";
|
|
5
3
|
/** Hard cap on a single log line in bytes (UTF-8). Lines past this
|
|
6
4
|
* are truncated with an ellipsis. */
|
|
7
5
|
const MAX_LINE_BYTES = 16 * 1024;
|
|
8
|
-
var Logger$1 = class extends Context.Service()("@devstack
|
|
6
|
+
var Logger$1 = class extends Context.Service()("@devstack/substrate/Logger") {};
|
|
9
7
|
/** Layer that constructs the per-stack Logger. Stateful (holds the
|
|
10
8
|
* per-tag ring buffers in a Ref); the substrate provides one per
|
|
11
9
|
* stack-scope. */
|
|
12
10
|
const layerLogger = Layer.effect(Logger$1, Effect.gen(function* () {
|
|
13
|
-
const redactor = yield* Redactor;
|
|
14
11
|
const buffers = yield* Ref.make(/* @__PURE__ */ new Map());
|
|
15
12
|
const truncateLine = (s) => s.length > 16384 ? `${s.slice(0, MAX_LINE_BYTES)}…[truncated]` : s;
|
|
16
13
|
const appendInternal = (line) => Ref.update(buffers, (map) => {
|
|
@@ -30,13 +27,12 @@ const layerLogger = Layer.effect(Logger$1, Effect.gen(function* () {
|
|
|
30
27
|
});
|
|
31
28
|
/** Log a line under `tag`. Atomic per-tag. */
|
|
32
29
|
const log = Effect.fn("Logger.log")(function* (tag, pluginKey, payload) {
|
|
33
|
-
const redactionRules = yield* redactor.rules;
|
|
34
30
|
const line = {
|
|
35
31
|
tag,
|
|
36
32
|
pluginKey,
|
|
37
33
|
level: payload.level,
|
|
38
|
-
message: truncateLine(
|
|
39
|
-
fields:
|
|
34
|
+
message: truncateLine(payload.message),
|
|
35
|
+
fields: payload.fields ?? {},
|
|
40
36
|
at: Date.now()
|
|
41
37
|
};
|
|
42
38
|
yield* appendInternal(line);
|
|
@@ -84,6 +80,6 @@ const logViaEffect = (line) => {
|
|
|
84
80
|
}
|
|
85
81
|
};
|
|
86
82
|
//#endregion
|
|
87
|
-
export { Logger$1 as Logger, layerLogger };
|
|
83
|
+
export { Logger$1 as Logger, MAX_LINE_BYTES, layerLogger };
|
|
88
84
|
|
|
89
85
|
//# sourceMappingURL=logger.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.mjs","names":["Logger"],"sources":["../../../../src/substrate/runtime/observability/logger.ts"],"sourcesContent":["// Structured per-tag log buffer.\n//\n// Architecture § L0 Observability primitives: \"structured log buffer,\n// span/annotation conventions, cause walker (shared with renderers,\n// not duplicated)\".\n//\n// Replaces the ad-hoc `appendTagLog` shape on the legacy `EngineHandle`\n// with a typed Service. Plugins acquire a `Logger` and publish lines;\n// the substrate keeps each line in a bounded per-tag ring buffer and\n// mirrors it into Effect's structured logging via `Effect.log*`.\n// Operator-level lines are also projected into the typed event stream\n// by the supervisor wrapper.\n//\n// Per-tag atomicity is guaranteed by `Ref.update` on the per-tag\n// buffer — single-fiber updates are linearizable and the buffer\n// reads are snapshot-consistent. Cross-process atomicity (when the\n// same log lands in two devstack processes via a shared file)\n// is delegated to the cross-process lock primitive in\n// `../cross-process-lock.ts`.\n\nimport { Context, Effect, Layer, Ref } from 'effect';\nimport { Data } from 'effect';\n\nimport type { PluginKey } from '../../brand.ts';\nimport { Redactor, redactValue } from './redaction.ts';\nimport { SpanAttr } from './spans.ts';\n\n// -----------------------------------------------------------------------------\n// Errors\n// -----------------------------------------------------------------------------\n\n/** Single tagged error class for every logger failure mode.\n *\n * The architecture says service-specific errors do NOT live in L0\n * (§ L0). `LoggerError` is engine-level — the only failure modes are\n * buffer-write contention (defected up) and over-large lines that\n * the bounded buffer refused to truncate. */\nexport class LoggerError extends Data.TaggedError('LoggerError')<{\n\treadonly reason: 'buffer-write-failed' | 'line-too-large';\n\treadonly tag: string;\n\treadonly cause?: unknown;\n}> {}\n\n// -----------------------------------------------------------------------------\n// Public types\n// -----------------------------------------------------------------------------\n\n/** Closed level set. Mirrors the projection's row.logTail.level\n * vocabulary, plus `debug` / `trace` for lifecycle diagnostics that\n * should stay in buffers / Effect logs rather than the renderer's\n * operator event stream. */\nexport type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\n/** A buffered log line. Plain data; the projection's `Row.logTail`\n * derives from this. Structured fields live in `fields` for\n * observability consumers that want richer than a string. */\nexport interface LogLine {\n\treadonly tag: string;\n\treadonly pluginKey: PluginKey | null;\n\treadonly level: LogLevel;\n\treadonly message: string;\n\treadonly fields: Readonly<Record<string, unknown>>;\n\treadonly at: number;\n}\n\nexport interface LogPayload {\n\treadonly level: LogLevel;\n\treadonly message: string;\n\treadonly fields?: Readonly<Record<string, unknown>>;\n}\n\n/** Bounded ring-buffer for a single tag. */\nexport interface TagBuffer {\n\treadonly lines: ReadonlyArray<LogLine>;\n\treadonly truncated: boolean;\n}\n\n// -----------------------------------------------------------------------------\n// Capacity policy\n// -----------------------------------------------------------------------------\n\n/** Per-tag retention. Matches the projection's\n * `MAX_ROW_LOG_LINES` default. */\nexport const DEFAULT_MAX_LINES_PER_TAG = 100;\n\n/** Hard cap on a single log line in bytes (UTF-8). Lines past this\n * are truncated with an ellipsis. */\nexport const MAX_LINE_BYTES = 16 * 1024;\n\n// -----------------------------------------------------------------------------\n// Logger service\n// -----------------------------------------------------------------------------\n\n/**\n * Structured per-tag logger. One instance per stack (or per process —\n * provided via `layerLogger`). Plugins acquire it from Context.\n *\n * Discipline:\n * - The tag is the only thing the logger discriminates on. It is\n * not a service name; it's whatever the publishing fiber picked\n * (typically `pluginKey + '/' + sub-tag`).\n * - Atomic per-tag writes: `Ref.update` on a `ReadonlyMap` of\n * `tag → TagBuffer`. Two fibers logging to the same tag interleave\n * by Ref linearization, not by lost updates.\n * - Structured fields: anything serializable. The cascade formatter\n * (see `cascade-formatter.ts`) renders the fields verbatim.\n */\n/**\n * Public shape of the Logger service. Plugins / supervisor depend on\n * this interface; the concrete Layer below builds an instance.\n */\nexport interface LoggerShape {\n\treadonly log: (\n\t\ttag: string,\n\t\tpluginKey: PluginKey | null,\n\t\tpayload: LogPayload,\n\t) => Effect.Effect<void>;\n\treadonly readTag: (tag: string) => Effect.Effect<TagBuffer>;\n\treadonly readAll: Effect.Effect<ReadonlyMap<string, TagBuffer>>;\n\treadonly clearTag: (tag: string) => Effect.Effect<void>;\n}\n\nexport class Logger extends Context.Service<Logger, LoggerShape>()(\n\t'@devstack-rewrite/substrate/Logger',\n) {}\n\n/** Layer that constructs the per-stack Logger. Stateful (holds the\n * per-tag ring buffers in a Ref); the substrate provides one per\n * stack-scope. */\nexport const layerLogger: Layer.Layer<Logger, never, Redactor> = Layer.effect(\n\tLogger,\n\tEffect.gen(function* () {\n\t\tconst redactor = yield* Redactor;\n\t\tconst buffers = yield* Ref.make<ReadonlyMap<string, TagBuffer>>(new Map());\n\n\t\tconst truncateLine = (s: string): string =>\n\t\t\ts.length > MAX_LINE_BYTES ? `${s.slice(0, MAX_LINE_BYTES)}…[truncated]` : s;\n\n\t\tconst appendInternal = (line: LogLine): Effect.Effect<void> =>\n\t\t\tRef.update(buffers, (map) => {\n\t\t\t\tconst prev = map.get(line.tag) ?? { lines: [], truncated: false };\n\t\t\t\tconst nextLines = [...prev.lines, line];\n\t\t\t\tconst overflow = nextLines.length > DEFAULT_MAX_LINES_PER_TAG;\n\t\t\t\tconst trimmed = overflow ? nextLines.slice(-DEFAULT_MAX_LINES_PER_TAG) : nextLines;\n\t\t\t\tconst nextMap = new Map(map);\n\t\t\t\tnextMap.set(line.tag, { lines: trimmed, truncated: prev.truncated || overflow });\n\t\t\t\treturn nextMap;\n\t\t\t});\n\n\t\t/** Log a line under `tag`. Atomic per-tag. */\n\t\tconst log = Effect.fn('Logger.log')(function* (\n\t\t\ttag: string,\n\t\t\tpluginKey: PluginKey | null,\n\t\t\tpayload: LogPayload,\n\t\t) {\n\t\t\tconst redactionRules = yield* redactor.rules;\n\t\t\tconst line: LogLine = {\n\t\t\t\ttag,\n\t\t\t\tpluginKey,\n\t\t\t\tlevel: payload.level,\n\t\t\t\tmessage: truncateLine(yield* redactor.redact(payload.message)),\n\t\t\t\tfields: redactValue(payload.fields ?? {}, redactionRules) as Readonly<\n\t\t\t\t\tRecord<string, unknown>\n\t\t\t\t>,\n\t\t\t\tat: Date.now(),\n\t\t\t};\n\t\t\tyield* appendInternal(line);\n\t\t\t// Mirror to Effect's structured logger so OTEL exporters see\n\t\t\t// the line too. The bounded buffer is the renderer-facing\n\t\t\t// surface; Effect's logger is the observability-pipeline\n\t\t\t// surface.\n\t\t\tyield* logViaEffect(line);\n\t\t});\n\n\t\t/** Read the current snapshot of a single tag's buffer. Used by\n\t\t * the projection updater when a row is created mid-stack. */\n\t\tconst readTag = (tag: string): Effect.Effect<TagBuffer> =>\n\t\t\tRef.get(buffers).pipe(Effect.map((map) => map.get(tag) ?? { lines: [], truncated: false }));\n\n\t\t/** Read every tag's current snapshot. Used by snapshot capture\n\t\t * + diagnostics. Bounded by aggregate retention. */\n\t\tconst readAll = Ref.get(buffers);\n\n\t\t/** Drop the buffer for a tag. Used when a plugin row is removed. */\n\t\tconst clearTag = (tag: string): Effect.Effect<void> =>\n\t\t\tRef.update(buffers, (map) => {\n\t\t\t\tif (!map.has(tag)) return map;\n\t\t\t\tconst next = new Map(map);\n\t\t\t\tnext.delete(tag);\n\t\t\t\treturn next;\n\t\t\t});\n\n\t\treturn Logger.of({ log, readTag, readAll, clearTag });\n\t}),\n);\n\n// -----------------------------------------------------------------------------\n// Effect-logger bridge\n// -----------------------------------------------------------------------------\n\nconst logViaEffect = (line: LogLine): Effect.Effect<void> => {\n\tconst annotated = Effect.annotateLogs({\n\t\t[SpanAttr.logTag]: line.tag,\n\t\t[SpanAttr.plugin]: line.pluginKey ?? '(none)',\n\t\t...line.fields,\n\t});\n\tswitch (line.level) {\n\t\tcase 'trace':\n\t\t\treturn Effect.logTrace(line.message).pipe(annotated);\n\t\tcase 'debug':\n\t\t\treturn Effect.logDebug(line.message).pipe(annotated);\n\t\tcase 'info':\n\t\t\treturn Effect.logInfo(line.message).pipe(annotated);\n\t\tcase 'warn':\n\t\t\treturn Effect.logWarning(line.message).pipe(annotated);\n\t\tcase 'error':\n\t\t\treturn Effect.logError(line.message).pipe(annotated);\n\t\tcase 'fatal':\n\t\t\treturn Effect.logFatal(line.message).pipe(annotated);\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = line.level;\n\t\t\tvoid _exhaustive;\n\t\t\treturn Effect.void;\n\t\t}\n\t}\n};\n"],"mappings":";;;AAqCiC,KAAK,YAAY,cAAc;;;AAkDhE,MAAa,iBAAiB,KAAK;AAmCnC,IAAaA,WAAb,cAA4B,QAAQ,SAA8B,CACjE,qCACA,CAAC;;;;AAKF,MAAa,cAAoD,MAAM,OACtEA,UACA,OAAO,IAAI,aAAa;CACvB,MAAM,WAAW,OAAO;CACxB,MAAM,UAAU,OAAO,IAAI,qBAAqC,IAAI,KAAK,CAAC;CAE1E,MAAM,gBAAgB,MACrB,EAAE,SAAA,QAA0B,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC,gBAAgB;CAE3E,MAAM,kBAAkB,SACvB,IAAI,OAAO,UAAU,QAAQ;EAC5B,MAAM,OAAO,IAAI,IAAI,KAAK,IAAI,IAAI;GAAE,OAAO,EAAE;GAAE,WAAW;GAAO;EACjE,MAAM,YAAY,CAAC,GAAG,KAAK,OAAO,KAAK;EACvC,MAAM,WAAW,UAAU,SAAA;EAC3B,MAAM,UAAU,WAAW,UAAU,MAAM,KAA2B,GAAG;EACzE,MAAM,UAAU,IAAI,IAAI,IAAI;AAC5B,UAAQ,IAAI,KAAK,KAAK;GAAE,OAAO;GAAS,WAAW,KAAK,aAAa;GAAU,CAAC;AAChF,SAAO;GACN;;CAGH,MAAM,MAAM,OAAO,GAAG,aAAa,CAAC,WACnC,KACA,WACA,SACC;EACD,MAAM,iBAAiB,OAAO,SAAS;EACvC,MAAM,OAAgB;GACrB;GACA;GACA,OAAO,QAAQ;GACf,SAAS,aAAa,OAAO,SAAS,OAAO,QAAQ,QAAQ,CAAC;GAC9D,QAAQ,YAAY,QAAQ,UAAU,EAAE,EAAE,eAAe;GAGzD,IAAI,KAAK,KAAK;GACd;AACD,SAAO,eAAe,KAAK;AAK3B,SAAO,aAAa,KAAK;GACxB;;;CAIF,MAAM,WAAW,QAChB,IAAI,IAAI,QAAQ,CAAC,KAAK,OAAO,KAAK,QAAQ,IAAI,IAAI,IAAI,IAAI;EAAE,OAAO,EAAE;EAAE,WAAW;EAAO,CAAC,CAAC;;;CAI5F,MAAM,UAAU,IAAI,IAAI,QAAQ;;CAGhC,MAAM,YAAY,QACjB,IAAI,OAAO,UAAU,QAAQ;AAC5B,MAAI,CAAC,IAAI,IAAI,IAAI,CAAE,QAAO;EAC1B,MAAM,OAAO,IAAI,IAAI,IAAI;AACzB,OAAK,OAAO,IAAI;AAChB,SAAO;GACN;AAEH,QAAOA,SAAO,GAAG;EAAE;EAAK;EAAS;EAAS;EAAU,CAAC;EACpD,CACF;AAMD,MAAM,gBAAgB,SAAuC;CAC5D,MAAM,YAAY,OAAO,aAAa;GACpC,SAAS,SAAS,KAAK;GACvB,SAAS,SAAS,KAAK,aAAa;EACrC,GAAG,KAAK;EACR,CAAC;AACF,SAAQ,KAAK,OAAb;EACC,KAAK,QACJ,QAAO,OAAO,SAAS,KAAK,QAAQ,CAAC,KAAK,UAAU;EACrD,KAAK,QACJ,QAAO,OAAO,SAAS,KAAK,QAAQ,CAAC,KAAK,UAAU;EACrD,KAAK,OACJ,QAAO,OAAO,QAAQ,KAAK,QAAQ,CAAC,KAAK,UAAU;EACpD,KAAK,OACJ,QAAO,OAAO,WAAW,KAAK,QAAQ,CAAC,KAAK,UAAU;EACvD,KAAK,QACJ,QAAO,OAAO,SAAS,KAAK,QAAQ,CAAC,KAAK,UAAU;EACrD,KAAK,QACJ,QAAO,OAAO,SAAS,KAAK,QAAQ,CAAC,KAAK,UAAU;EACrD;AAC4B,QAAK;AAEhC,UAAO,OAAO"}
|
|
1
|
+
{"version":3,"file":"logger.mjs","names":["Logger"],"sources":["../../../../src/substrate/runtime/observability/logger.ts"],"sourcesContent":["// Structured per-tag log buffer.\n//\n// Architecture § L0 Observability primitives: \"structured log buffer,\n// span/annotation conventions, cause walker (shared with renderers,\n// not duplicated)\".\n//\n// Replaces the ad-hoc `appendTagLog` shape on the legacy `EngineHandle`\n// with a typed Service. Plugins acquire a `Logger` and publish lines;\n// the substrate keeps each line in a bounded per-tag ring buffer and\n// mirrors it into Effect's structured logging via `Effect.log*`.\n// Operator-level lines are also projected into the typed event stream\n// by the supervisor wrapper.\n//\n// Per-tag atomicity is guaranteed by `Ref.update` on the per-tag\n// buffer — single-fiber updates are linearizable and the buffer\n// reads are snapshot-consistent. Cross-process atomicity (when the\n// same log lands in two devstack processes via a shared file)\n// is delegated to the cross-process lock primitive in\n// `../cross-process/lock.ts`.\n\nimport { Context, Effect, Layer, Ref } from 'effect';\n\nimport type { PluginKey } from '../../brand.ts';\nimport { SpanAttr } from './spans.ts';\n\n// -----------------------------------------------------------------------------\n// Public types\n// -----------------------------------------------------------------------------\n\n/** Closed level set. Mirrors the projection's row.logTail.level\n * vocabulary, plus `debug` / `trace` for lifecycle diagnostics that\n * should stay in buffers / Effect logs rather than the renderer's\n * operator event stream. */\nexport type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\n/** A buffered log line. Plain data; the projection's `Row.logTail`\n * derives from this. Structured fields live in `fields` for\n * observability consumers that want richer than a string. */\nexport interface LogLine {\n\treadonly tag: string;\n\treadonly pluginKey: PluginKey | null;\n\treadonly level: LogLevel;\n\treadonly message: string;\n\treadonly fields: Readonly<Record<string, unknown>>;\n\treadonly at: number;\n}\n\nexport interface LogPayload {\n\treadonly level: LogLevel;\n\treadonly message: string;\n\treadonly fields?: Readonly<Record<string, unknown>>;\n}\n\n/** Bounded ring-buffer for a single tag. */\nexport interface TagBuffer {\n\treadonly lines: ReadonlyArray<LogLine>;\n\treadonly truncated: boolean;\n}\n\n// -----------------------------------------------------------------------------\n// Capacity policy\n// -----------------------------------------------------------------------------\n\n/** Per-tag retention. Matches the projection's\n * `MAX_ROW_LOG_LINES` default. */\nexport const DEFAULT_MAX_LINES_PER_TAG = 100;\n\n/** Hard cap on a single log line in bytes (UTF-8). Lines past this\n * are truncated with an ellipsis. */\nexport const MAX_LINE_BYTES = 16 * 1024;\n\n// -----------------------------------------------------------------------------\n// Logger service\n// -----------------------------------------------------------------------------\n\n/**\n * Structured per-tag logger. One instance per stack (or per process —\n * provided via `layerLogger`). Plugins acquire it from Context.\n *\n * Discipline:\n * - The tag is the only thing the logger discriminates on. It is\n * not a service name; it's whatever the publishing fiber picked\n * (typically `pluginKey + '/' + sub-tag`).\n * - Atomic per-tag writes: `Ref.update` on a `ReadonlyMap` of\n * `tag → TagBuffer`. Two fibers logging to the same tag interleave\n * by Ref linearization, not by lost updates.\n * - Structured fields: anything serializable. The cascade formatter\n * (see `cascade-formatter.ts`) renders the fields verbatim.\n */\n/**\n * Public shape of the Logger service. Plugins / supervisor depend on\n * this interface; the concrete Layer below builds an instance.\n */\nexport interface LoggerShape {\n\treadonly log: (\n\t\ttag: string,\n\t\tpluginKey: PluginKey | null,\n\t\tpayload: LogPayload,\n\t) => Effect.Effect<void>;\n\treadonly readTag: (tag: string) => Effect.Effect<TagBuffer>;\n\treadonly readAll: Effect.Effect<ReadonlyMap<string, TagBuffer>>;\n\treadonly clearTag: (tag: string) => Effect.Effect<void>;\n}\n\nexport class Logger extends Context.Service<Logger, LoggerShape>()('@devstack/substrate/Logger') {}\n\n/** Layer that constructs the per-stack Logger. Stateful (holds the\n * per-tag ring buffers in a Ref); the substrate provides one per\n * stack-scope. */\nexport const layerLogger: Layer.Layer<Logger> = Layer.effect(\n\tLogger,\n\tEffect.gen(function* () {\n\t\tconst buffers = yield* Ref.make<ReadonlyMap<string, TagBuffer>>(new Map());\n\n\t\tconst truncateLine = (s: string): string =>\n\t\t\ts.length > MAX_LINE_BYTES ? `${s.slice(0, MAX_LINE_BYTES)}…[truncated]` : s;\n\n\t\tconst appendInternal = (line: LogLine): Effect.Effect<void> =>\n\t\t\tRef.update(buffers, (map) => {\n\t\t\t\tconst prev = map.get(line.tag) ?? { lines: [], truncated: false };\n\t\t\t\tconst nextLines = [...prev.lines, line];\n\t\t\t\tconst overflow = nextLines.length > DEFAULT_MAX_LINES_PER_TAG;\n\t\t\t\tconst trimmed = overflow ? nextLines.slice(-DEFAULT_MAX_LINES_PER_TAG) : nextLines;\n\t\t\t\tconst nextMap = new Map(map);\n\t\t\t\tnextMap.set(line.tag, { lines: trimmed, truncated: prev.truncated || overflow });\n\t\t\t\treturn nextMap;\n\t\t\t});\n\n\t\t/** Log a line under `tag`. Atomic per-tag. */\n\t\tconst log = Effect.fn('Logger.log')(function* (\n\t\t\ttag: string,\n\t\t\tpluginKey: PluginKey | null,\n\t\t\tpayload: LogPayload,\n\t\t) {\n\t\t\tconst line: LogLine = {\n\t\t\t\ttag,\n\t\t\t\tpluginKey,\n\t\t\t\tlevel: payload.level,\n\t\t\t\tmessage: truncateLine(payload.message),\n\t\t\t\tfields: payload.fields ?? {},\n\t\t\t\tat: Date.now(),\n\t\t\t};\n\t\t\tyield* appendInternal(line);\n\t\t\t// Mirror to Effect's structured logger so OTEL exporters see\n\t\t\t// the line too. The bounded buffer is the renderer-facing\n\t\t\t// surface; Effect's logger is the observability-pipeline\n\t\t\t// surface.\n\t\t\tyield* logViaEffect(line);\n\t\t});\n\n\t\t/** Read the current snapshot of a single tag's buffer. Used by\n\t\t * the projection updater when a row is created mid-stack. */\n\t\tconst readTag = (tag: string): Effect.Effect<TagBuffer> =>\n\t\t\tRef.get(buffers).pipe(Effect.map((map) => map.get(tag) ?? { lines: [], truncated: false }));\n\n\t\t/** Read every tag's current snapshot. Used by snapshot capture\n\t\t * + diagnostics. Bounded by aggregate retention. */\n\t\tconst readAll = Ref.get(buffers);\n\n\t\t/** Drop the buffer for a tag. Used when a plugin row is removed. */\n\t\tconst clearTag = (tag: string): Effect.Effect<void> =>\n\t\t\tRef.update(buffers, (map) => {\n\t\t\t\tif (!map.has(tag)) return map;\n\t\t\t\tconst next = new Map(map);\n\t\t\t\tnext.delete(tag);\n\t\t\t\treturn next;\n\t\t\t});\n\n\t\treturn Logger.of({ log, readTag, readAll, clearTag });\n\t}),\n);\n\n// -----------------------------------------------------------------------------\n// Effect-logger bridge\n// -----------------------------------------------------------------------------\n\nconst logViaEffect = (line: LogLine): Effect.Effect<void> => {\n\tconst annotated = Effect.annotateLogs({\n\t\t[SpanAttr.logTag]: line.tag,\n\t\t[SpanAttr.plugin]: line.pluginKey ?? '(none)',\n\t\t...line.fields,\n\t});\n\tswitch (line.level) {\n\t\tcase 'trace':\n\t\t\treturn Effect.logTrace(line.message).pipe(annotated);\n\t\tcase 'debug':\n\t\t\treturn Effect.logDebug(line.message).pipe(annotated);\n\t\tcase 'info':\n\t\t\treturn Effect.logInfo(line.message).pipe(annotated);\n\t\tcase 'warn':\n\t\t\treturn Effect.logWarning(line.message).pipe(annotated);\n\t\tcase 'error':\n\t\t\treturn Effect.logError(line.message).pipe(annotated);\n\t\tcase 'fatal':\n\t\t\treturn Effect.logFatal(line.message).pipe(annotated);\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = line.level;\n\t\t\tvoid _exhaustive;\n\t\t\treturn Effect.void;\n\t\t}\n\t}\n};\n"],"mappings":";;;;AAqEA,MAAa,iBAAiB,KAAK;AAmCnC,IAAaA,WAAb,cAA4B,QAAQ,SAA8B,CAAC,6BAA6B,CAAC;;;;AAKjG,MAAa,cAAmC,MAAM,OACrDA,UACA,OAAO,IAAI,aAAa;CACvB,MAAM,UAAU,OAAO,IAAI,qBAAqC,IAAI,KAAK,CAAC;CAE1E,MAAM,gBAAgB,MACrB,EAAE,SAAA,QAA0B,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC,gBAAgB;CAE3E,MAAM,kBAAkB,SACvB,IAAI,OAAO,UAAU,QAAQ;EAC5B,MAAM,OAAO,IAAI,IAAI,KAAK,IAAI,IAAI;GAAE,OAAO,EAAE;GAAE,WAAW;GAAO;EACjE,MAAM,YAAY,CAAC,GAAG,KAAK,OAAO,KAAK;EACvC,MAAM,WAAW,UAAU,SAAA;EAC3B,MAAM,UAAU,WAAW,UAAU,MAAM,KAA2B,GAAG;EACzE,MAAM,UAAU,IAAI,IAAI,IAAI;AAC5B,UAAQ,IAAI,KAAK,KAAK;GAAE,OAAO;GAAS,WAAW,KAAK,aAAa;GAAU,CAAC;AAChF,SAAO;GACN;;CAGH,MAAM,MAAM,OAAO,GAAG,aAAa,CAAC,WACnC,KACA,WACA,SACC;EACD,MAAM,OAAgB;GACrB;GACA;GACA,OAAO,QAAQ;GACf,SAAS,aAAa,QAAQ,QAAQ;GACtC,QAAQ,QAAQ,UAAU,EAAE;GAC5B,IAAI,KAAK,KAAK;GACd;AACD,SAAO,eAAe,KAAK;AAK3B,SAAO,aAAa,KAAK;GACxB;;;CAIF,MAAM,WAAW,QAChB,IAAI,IAAI,QAAQ,CAAC,KAAK,OAAO,KAAK,QAAQ,IAAI,IAAI,IAAI,IAAI;EAAE,OAAO,EAAE;EAAE,WAAW;EAAO,CAAC,CAAC;;;CAI5F,MAAM,UAAU,IAAI,IAAI,QAAQ;;CAGhC,MAAM,YAAY,QACjB,IAAI,OAAO,UAAU,QAAQ;AAC5B,MAAI,CAAC,IAAI,IAAI,IAAI,CAAE,QAAO;EAC1B,MAAM,OAAO,IAAI,IAAI,IAAI;AACzB,OAAK,OAAO,IAAI;AAChB,SAAO;GACN;AAEH,QAAOA,SAAO,GAAG;EAAE;EAAK;EAAS;EAAS;EAAU,CAAC;EACpD,CACF;AAMD,MAAM,gBAAgB,SAAuC;CAC5D,MAAM,YAAY,OAAO,aAAa;GACpC,SAAS,SAAS,KAAK;GACvB,SAAS,SAAS,KAAK,aAAa;EACrC,GAAG,KAAK;EACR,CAAC;AACF,SAAQ,KAAK,OAAb;EACC,KAAK,QACJ,QAAO,OAAO,SAAS,KAAK,QAAQ,CAAC,KAAK,UAAU;EACrD,KAAK,QACJ,QAAO,OAAO,SAAS,KAAK,QAAQ,CAAC,KAAK,UAAU;EACrD,KAAK,OACJ,QAAO,OAAO,QAAQ,KAAK,QAAQ,CAAC,KAAK,UAAU;EACpD,KAAK,OACJ,QAAO,OAAO,WAAW,KAAK,QAAQ,CAAC,KAAK,UAAU;EACvD,KAAK,QACJ,QAAO,OAAO,SAAS,KAAK,QAAQ,CAAC,KAAK,UAAU;EACrD,KAAK,QACJ,QAAO,OAAO,SAAS,KAAK,QAAQ,CAAC,KAAK,UAAU;EACrD;AAC4B,QAAK;AAEhC,UAAO,OAAO"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
//#region src/substrate/runtime/observability/output-truncate.ts
|
|
2
|
+
/** Return the trailing `maxChars` characters of `value`, or `value`
|
|
3
|
+
* unchanged if shorter. Used at error-construction sites that want to
|
|
4
|
+
* surface the most-recent output (typically where the failure cause
|
|
5
|
+
* appears at the END of a long stream — e.g. a git clone trace whose
|
|
6
|
+
* fatal line is the last one). Defaults to 1000 chars, the source-fetch
|
|
7
|
+
* call sites' original budget. */
|
|
8
|
+
const tailOutput = (value, maxChars = 1e3) => value.length > maxChars ? value.slice(-maxChars) : value;
|
|
9
|
+
/** Render `value` as a labelled, JSON-quoted suffix (` <label>=<json>`)
|
|
10
|
+
* for inline error messages. Empty / whitespace-only input collapses to
|
|
11
|
+
* the empty string so the caller can unconditionally concatenate the
|
|
12
|
+
* result without producing dangling labels.
|
|
13
|
+
*
|
|
14
|
+
* Oversize input is mid-truncated: a head slice + literal
|
|
15
|
+
* `...<truncated N chars>...` + a tail slice, keeping both the leading
|
|
16
|
+
* context (which often identifies the command) AND the trailing context
|
|
17
|
+
* (which often identifies the cause). Defaults size the output so a
|
|
18
|
+
* combined stdout + stderr fits inside an L4-level log line without
|
|
19
|
+
* overflowing typical terminal scroll buffers.
|
|
20
|
+
*
|
|
21
|
+
* @param maxChars - total budget before mid-truncation kicks in (default
|
|
22
|
+
* 2400). Below this the body is emitted verbatim.
|
|
23
|
+
* @param windowChars - per-side window kept when truncating (default
|
|
24
|
+
* 1100). Total kept output is roughly `2 * windowChars` plus the
|
|
25
|
+
* truncation marker. */
|
|
26
|
+
const labelledExcerpt = (label, value, maxChars = 2400, windowChars = 1100) => {
|
|
27
|
+
const trimmed = value.trim();
|
|
28
|
+
if (trimmed.length === 0) return "";
|
|
29
|
+
const body = trimmed.length > maxChars ? `${trimmed.slice(0, windowChars)}...<truncated ${trimmed.length - 2 * windowChars} chars>...${trimmed.slice(-windowChars)}` : trimmed;
|
|
30
|
+
return ` ${label}=${JSON.stringify(body)}`;
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
33
|
+
export { labelledExcerpt, tailOutput };
|
|
34
|
+
|
|
35
|
+
//# sourceMappingURL=output-truncate.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output-truncate.mjs","names":[],"sources":["../../../../src/substrate/runtime/observability/output-truncate.ts"],"sourcesContent":["// Bounded stdout/stderr trimming for error-message tails.\n//\n// Two failure-message shapes converged on the same primitive:\n// - `walrus/deploy.ts::excerpt` — emit a labelled, JSON-quoted body\n// (` stdout=\"...\"`) with mid-truncation when oversize (head + tail\n// window with a `<truncated N chars>` marker), elided when empty.\n// - `seal/bootstrap-assets/source-fetch.ts::outputTail` — emit just\n// the last N chars of the raw stream, passed as the `stdout:` /\n// `stderr:` field of a typed error.\n//\n// Both are stdout/stderr bound-the-blast-radius helpers. Both used to\n// inline ad-hoc constants. Folded into one module so the\n// boundedness-policy lives in ONE place and the per-call-site shape\n// (label-wrapped vs raw tail) is just an output decision.\n\n/** Return the trailing `maxChars` characters of `value`, or `value`\n * unchanged if shorter. Used at error-construction sites that want to\n * surface the most-recent output (typically where the failure cause\n * appears at the END of a long stream — e.g. a git clone trace whose\n * fatal line is the last one). Defaults to 1000 chars, the source-fetch\n * call sites' original budget. */\nexport const tailOutput = (value: string, maxChars: number = 1_000): string =>\n\tvalue.length > maxChars ? value.slice(-maxChars) : value;\n\n/** Render `value` as a labelled, JSON-quoted suffix (` <label>=<json>`)\n * for inline error messages. Empty / whitespace-only input collapses to\n * the empty string so the caller can unconditionally concatenate the\n * result without producing dangling labels.\n *\n * Oversize input is mid-truncated: a head slice + literal\n * `...<truncated N chars>...` + a tail slice, keeping both the leading\n * context (which often identifies the command) AND the trailing context\n * (which often identifies the cause). Defaults size the output so a\n * combined stdout + stderr fits inside an L4-level log line without\n * overflowing typical terminal scroll buffers.\n *\n * @param maxChars - total budget before mid-truncation kicks in (default\n * 2400). Below this the body is emitted verbatim.\n * @param windowChars - per-side window kept when truncating (default\n * 1100). Total kept output is roughly `2 * windowChars` plus the\n * truncation marker. */\nexport const labelledExcerpt = (\n\tlabel: string,\n\tvalue: string,\n\tmaxChars: number = 2_400,\n\twindowChars: number = 1_100,\n): string => {\n\tconst trimmed = value.trim();\n\tif (trimmed.length === 0) return '';\n\tconst body =\n\t\ttrimmed.length > maxChars\n\t\t\t? `${trimmed.slice(0, windowChars)}...<truncated ${trimmed.length - 2 * windowChars} chars>...${trimmed.slice(-windowChars)}`\n\t\t\t: trimmed;\n\treturn ` ${label}=${JSON.stringify(body)}`;\n};\n"],"mappings":";;;;;;;AAqBA,MAAa,cAAc,OAAe,WAAmB,QAC5D,MAAM,SAAS,WAAW,MAAM,MAAM,CAAC,SAAS,GAAG;;;;;;;;;;;;;;;;;;AAmBpD,MAAa,mBACZ,OACA,OACA,WAAmB,MACnB,cAAsB,SACV;CACZ,MAAM,UAAU,MAAM,MAAM;AAC5B,KAAI,QAAQ,WAAW,EAAG,QAAO;CACjC,MAAM,OACL,QAAQ,SAAS,WACd,GAAG,QAAQ,MAAM,GAAG,YAAY,CAAC,gBAAgB,QAAQ,SAAS,IAAI,YAAY,YAAY,QAAQ,MAAM,CAAC,YAAY,KACzH;AACJ,QAAO,IAAI,MAAM,GAAG,KAAK,UAAU,KAAK"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isTaggedError } from "./cascade-formatter.mjs";
|
|
2
|
+
import { Cause } from "effect";
|
|
2
3
|
//#region src/substrate/runtime/observability/pretty-error.ts
|
|
3
4
|
/**
|
|
4
5
|
* Render a Cause as a `StructuredError` suitable for the projection's
|
|
@@ -26,9 +27,8 @@ const prettyErrorStructured = (cause, options) => {
|
|
|
26
27
|
/** Walk the cause's first `Fail` reason and pull out the outermost
|
|
27
28
|
* tag + message for projection.summary. */
|
|
28
29
|
const extractHeadline = (cause) => {
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
if (reason._tag === "Fail") {
|
|
30
|
+
for (const reason of cause.reasons) {
|
|
31
|
+
if (Cause.isFailReason(reason)) {
|
|
32
32
|
const error = reason.error;
|
|
33
33
|
if (isTaggedError(error)) return {
|
|
34
34
|
tag: error._tag,
|
|
@@ -43,7 +43,7 @@ const extractHeadline = (cause) => {
|
|
|
43
43
|
summary: String(error)
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
|
-
if (reason
|
|
46
|
+
if (Cause.isDieReason(reason)) {
|
|
47
47
|
const defect = reason.defect;
|
|
48
48
|
if (isTaggedError(defect)) return {
|
|
49
49
|
tag: `Defect[${defect._tag}]`,
|
|
@@ -58,7 +58,7 @@ const extractHeadline = (cause) => {
|
|
|
58
58
|
summary: String(defect)
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
|
-
|
|
61
|
+
return {
|
|
62
62
|
tag: "Interrupt",
|
|
63
63
|
summary: "fiber interrupted"
|
|
64
64
|
};
|
|
@@ -82,17 +82,14 @@ const headlineText = (value) => {
|
|
|
82
82
|
/** Walk every layer of the cause's outermost `Fail` chain and build a
|
|
83
83
|
* list of `<tag>: <message>` strings — one per nested layer. */
|
|
84
84
|
const extractChain = (cause) => {
|
|
85
|
-
const reasons = cause.reasons;
|
|
86
85
|
const out = [];
|
|
87
|
-
for (const reason of reasons) walkChainFromReason(reason, out, /* @__PURE__ */ new WeakSet());
|
|
86
|
+
for (const reason of cause.reasons) walkChainFromReason(reason, out, /* @__PURE__ */ new WeakSet());
|
|
88
87
|
return out;
|
|
89
88
|
};
|
|
90
89
|
const walkChainFromReason = (reason, out, visited) => {
|
|
91
|
-
if (
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
else if (r._tag === "Die") walkChainFromValue(r.defect, out, visited);
|
|
95
|
-
else if (r._tag === "Interrupt") out.push("Interrupt");
|
|
90
|
+
if (Cause.isFailReason(reason)) walkChainFromValue(reason.error, out, visited);
|
|
91
|
+
else if (Cause.isDieReason(reason)) walkChainFromValue(reason.defect, out, visited);
|
|
92
|
+
else out.push("Interrupt");
|
|
96
93
|
};
|
|
97
94
|
const walkChainFromValue = (value, out, visited) => {
|
|
98
95
|
if (value === void 0 || value === null) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pretty-error.mjs","names":[],"sources":["../../../../src/substrate/runtime/observability/pretty-error.ts"],"sourcesContent":["// Pretty-error renderer.\n//\n// Architecture § L0 Observability: one cause walker, shared with\n// renderers. The cascade-formatter is the pure walk; this module is\n// the IO + convenience layer:\n// - `prettyError(unknown)` — convenience for \"I have a thrown value\"\n// and don't want to thread a Cause.\n// - `prettyCause(cause)` — the supervisor's path: the engine\n// catches via `Effect.catchCause` and renders.\n// - `prettyErrorStructured` — render to a `StructuredError` shape\n// suitable for the projection's `errors` field.\n//\n// This module is *thin* — all real formatting logic is in\n// `cascade-formatter.ts`. Splitting them keeps the formatter pure\n// + reusable while letting this module evolve IO conventions.\n\nimport
|
|
1
|
+
{"version":3,"file":"pretty-error.mjs","names":[],"sources":["../../../../src/substrate/runtime/observability/pretty-error.ts"],"sourcesContent":["// Pretty-error renderer.\n//\n// Architecture § L0 Observability: one cause walker, shared with\n// renderers. The cascade-formatter is the pure walk; this module is\n// the IO + convenience layer:\n// - `prettyError(unknown)` — convenience for \"I have a thrown value\"\n// and don't want to thread a Cause.\n// - `prettyCause(cause)` — the supervisor's path: the engine\n// catches via `Effect.catchCause` and renders.\n// - `prettyErrorStructured` — render to a `StructuredError` shape\n// suitable for the projection's `errors` field.\n//\n// This module is *thin* — all real formatting logic is in\n// `cascade-formatter.ts`. Splitting them keeps the formatter pure\n// + reusable while letting this module evolve IO conventions.\n\nimport { Cause } from 'effect';\n\nimport type { PluginKey } from '../../brand.ts';\nimport type { StructuredError } from '../../projection.ts';\n\nimport {\n\ttype FormatOptions,\n\ttype FormatterRegistry,\n\ttype TaggedErrorLike,\n\tformatCause,\n\tformatValue,\n\tisTaggedError,\n} from './cascade-formatter.ts';\n\nexport type { FormatOptions, FormatterRegistry, TaggedErrorLike };\n\n/** Render any value (Cause, tagged error, plain Error, anything)\n * using the cascade rules. The pretty-error variant exists so\n * callers don't have to know whether they have a Cause or an Error. */\nexport const prettyError = (value: unknown, options?: FormatOptions): string =>\n\tformatValue(value, options);\n\n/** Render an Effect `Cause.Cause<E>` directly. The supervisor's preferred\n * entry point (it has a Cause from `Effect.catchCause`). */\nexport const prettyCause = <E>(cause: Cause.Cause<E>, options?: FormatOptions): string =>\n\tformatCause(cause, options);\n\n// -----------------------------------------------------------------------------\n// Structured projection\n// -----------------------------------------------------------------------------\n\nexport interface StructureOptions extends FormatOptions {\n\treadonly at?: number;\n\treadonly pluginKey?: PluginKey | null;\n\treadonly severity?: StructuredError['severity'];\n}\n\n/**\n * Render a Cause as a `StructuredError` suitable for the projection's\n * `errors` field. The `chain` array carries the per-layer summaries\n * (header lines only — the full multi-line render is what `prettyCause`\n * returns).\n *\n * Use the projection-shaped variant when building an `error.reported`\n * event; use `prettyCause` when rendering for human display.\n */\nexport const prettyErrorStructured = <E>(\n\tcause: Cause.Cause<E>,\n\toptions?: StructureOptions,\n): StructuredError => {\n\tconst at = options?.at ?? Date.now();\n\tconst pluginKey = options?.pluginKey ?? null;\n\tconst severity = options?.severity ?? 'error';\n\n\tconst { tag, summary } = extractHeadline(cause);\n\tconst chain = extractChain(cause);\n\n\treturn { at, pluginKey, tag, summary, chain, severity };\n};\n\n/** Walk the cause's first `Fail` reason and pull out the outermost\n * tag + message for projection.summary. */\nconst extractHeadline = (cause: Cause.Cause<unknown>): { tag: string; summary: string } => {\n\tfor (const reason of cause.reasons) {\n\t\tif (Cause.isFailReason(reason)) {\n\t\t\tconst error = reason.error;\n\t\t\tif (isTaggedError(error)) {\n\t\t\t\treturn {\n\t\t\t\t\ttag: error._tag,\n\t\t\t\t\tsummary: headlineText(error) ?? error._tag,\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (error instanceof Error) {\n\t\t\t\treturn { tag: error.name, summary: error.message };\n\t\t\t}\n\t\t\treturn { tag: 'UnknownFailure', summary: String(error) };\n\t\t}\n\t\tif (Cause.isDieReason(reason)) {\n\t\t\tconst defect = reason.defect;\n\t\t\tif (isTaggedError(defect)) {\n\t\t\t\treturn {\n\t\t\t\t\ttag: `Defect[${defect._tag}]`,\n\t\t\t\t\tsummary: headlineText(defect) ?? defect._tag,\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (defect instanceof Error) {\n\t\t\t\treturn { tag: 'Defect', summary: defect.message };\n\t\t\t}\n\t\t\treturn { tag: 'Defect', summary: String(defect) };\n\t\t}\n\t\t// Cause.isInterruptReason(reason)\n\t\treturn { tag: 'Interrupt', summary: 'fiber interrupted' };\n\t}\n\treturn { tag: 'EmptyCause', summary: '(empty cause)' };\n};\n\nconst headlineText = (value: TaggedErrorLike): string | null => {\n\tfor (const key of ['message', 'detail', 'stderr'] as const) {\n\t\tconst field = value[key];\n\t\tif (typeof field === 'string' && field.trim().length > 0) return field.trim();\n\t}\n\treturn null;\n};\n\n/** Walk every layer of the cause's outermost `Fail` chain and build a\n * list of `<tag>: <message>` strings — one per nested layer. */\nconst extractChain = (cause: Cause.Cause<unknown>): ReadonlyArray<string> => {\n\tconst out: Array<string> = [];\n\tfor (const reason of cause.reasons) {\n\t\twalkChainFromReason(reason, out, new WeakSet());\n\t}\n\treturn out;\n};\n\nconst walkChainFromReason = (\n\treason: Cause.Reason<unknown>,\n\tout: Array<string>,\n\tvisited: WeakSet<object>,\n): void => {\n\tif (Cause.isFailReason(reason)) walkChainFromValue(reason.error, out, visited);\n\telse if (Cause.isDieReason(reason)) walkChainFromValue(reason.defect, out, visited);\n\telse out.push('Interrupt');\n};\n\nconst walkChainFromValue = (value: unknown, out: Array<string>, visited: WeakSet<object>): void => {\n\tif (value === undefined || value === null) return;\n\tif (typeof value === 'object') {\n\t\tif (visited.has(value as object)) return;\n\t\tvisited.add(value as object);\n\t}\n\tif (isTaggedError(value)) {\n\t\tconst tag = value._tag;\n\t\tconst msg = headlineText(value) ?? '';\n\t\tout.push(msg ? `${tag}: ${msg}` : tag);\n\t\tif (value.cause !== undefined && value.cause !== null) {\n\t\t\twalkChainFromValue(value.cause, out, visited);\n\t\t}\n\t\treturn;\n\t}\n\tif (value instanceof Error) {\n\t\tout.push(`${value.name}: ${value.message}`);\n\t\treturn;\n\t}\n\tout.push(String(value));\n};\n"],"mappings":";;;;;;;;;;;;AA8DA,MAAa,yBACZ,OACA,YACqB;CACrB,MAAM,KAAK,SAAS,MAAM,KAAK,KAAK;CACpC,MAAM,YAAY,SAAS,aAAa;CACxC,MAAM,WAAW,SAAS,YAAY;CAEtC,MAAM,EAAE,KAAK,YAAY,gBAAgB,MAAM;AAG/C,QAAO;EAAE;EAAI;EAAW;EAAK;EAAS,OAFxB,aAAa,MAEgB;EAAE;EAAU;;;;AAKxD,MAAM,mBAAmB,UAAkE;AAC1F,MAAK,MAAM,UAAU,MAAM,SAAS;AACnC,MAAI,MAAM,aAAa,OAAO,EAAE;GAC/B,MAAM,QAAQ,OAAO;AACrB,OAAI,cAAc,MAAM,CACvB,QAAO;IACN,KAAK,MAAM;IACX,SAAS,aAAa,MAAM,IAAI,MAAM;IACtC;AAEF,OAAI,iBAAiB,MACpB,QAAO;IAAE,KAAK,MAAM;IAAM,SAAS,MAAM;IAAS;AAEnD,UAAO;IAAE,KAAK;IAAkB,SAAS,OAAO,MAAM;IAAE;;AAEzD,MAAI,MAAM,YAAY,OAAO,EAAE;GAC9B,MAAM,SAAS,OAAO;AACtB,OAAI,cAAc,OAAO,CACxB,QAAO;IACN,KAAK,UAAU,OAAO,KAAK;IAC3B,SAAS,aAAa,OAAO,IAAI,OAAO;IACxC;AAEF,OAAI,kBAAkB,MACrB,QAAO;IAAE,KAAK;IAAU,SAAS,OAAO;IAAS;AAElD,UAAO;IAAE,KAAK;IAAU,SAAS,OAAO,OAAO;IAAE;;AAGlD,SAAO;GAAE,KAAK;GAAa,SAAS;GAAqB;;AAE1D,QAAO;EAAE,KAAK;EAAc,SAAS;EAAiB;;AAGvD,MAAM,gBAAgB,UAA0C;AAC/D,MAAK,MAAM,OAAO;EAAC;EAAW;EAAU;EAAS,EAAW;EAC3D,MAAM,QAAQ,MAAM;AACpB,MAAI,OAAO,UAAU,YAAY,MAAM,MAAM,CAAC,SAAS,EAAG,QAAO,MAAM,MAAM;;AAE9E,QAAO;;;;AAKR,MAAM,gBAAgB,UAAuD;CAC5E,MAAM,MAAqB,EAAE;AAC7B,MAAK,MAAM,UAAU,MAAM,QAC1B,qBAAoB,QAAQ,qBAAK,IAAI,SAAS,CAAC;AAEhD,QAAO;;AAGR,MAAM,uBACL,QACA,KACA,YACU;AACV,KAAI,MAAM,aAAa,OAAO,CAAE,oBAAmB,OAAO,OAAO,KAAK,QAAQ;UACrE,MAAM,YAAY,OAAO,CAAE,oBAAmB,OAAO,QAAQ,KAAK,QAAQ;KAC9E,KAAI,KAAK,YAAY;;AAG3B,MAAM,sBAAsB,OAAgB,KAAoB,YAAmC;AAClG,KAAI,UAAU,KAAA,KAAa,UAAU,KAAM;AAC3C,KAAI,OAAO,UAAU,UAAU;AAC9B,MAAI,QAAQ,IAAI,MAAgB,CAAE;AAClC,UAAQ,IAAI,MAAgB;;AAE7B,KAAI,cAAc,MAAM,EAAE;EACzB,MAAM,MAAM,MAAM;EAClB,MAAM,MAAM,aAAa,MAAM,IAAI;AACnC,MAAI,KAAK,MAAM,GAAG,IAAI,IAAI,QAAQ,IAAI;AACtC,MAAI,MAAM,UAAU,KAAA,KAAa,MAAM,UAAU,KAChD,oBAAmB,MAAM,OAAO,KAAK,QAAQ;AAE9C;;AAED,KAAI,iBAAiB,OAAO;AAC3B,MAAI,KAAK,GAAG,MAAM,KAAK,IAAI,MAAM,UAAU;AAC3C;;AAED,KAAI,KAAK,OAAO,MAAM,CAAC"}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import { Context, Effect, Layer } from "effect";
|
|
2
|
-
|
|
3
|
-
//#region src/substrate/runtime/observability/redaction.d.ts
|
|
4
1
|
declare namespace redaction_d_exports {
|
|
5
|
-
export { RedactionRule,
|
|
2
|
+
export { RedactionRule, redactText, redactValue };
|
|
6
3
|
}
|
|
7
4
|
type RedactionRule = {
|
|
8
5
|
readonly kind: 'literal';
|
|
@@ -13,16 +10,8 @@ type RedactionRule = {
|
|
|
13
10
|
readonly pattern: RegExp;
|
|
14
11
|
readonly replacement?: string;
|
|
15
12
|
};
|
|
16
|
-
interface RedactorShape {
|
|
17
|
-
readonly register: (rule: RedactionRule) => Effect.Effect<void>;
|
|
18
|
-
readonly redact: (text: string) => Effect.Effect<string>;
|
|
19
|
-
readonly rules: Effect.Effect<ReadonlyArray<RedactionRule>>;
|
|
20
|
-
}
|
|
21
|
-
declare const Redactor_base: Context.ServiceClass<Redactor, "@devstack-rewrite/substrate/Redactor", RedactorShape>;
|
|
22
|
-
declare class Redactor extends Redactor_base {}
|
|
23
13
|
declare const redactText: (text: string, rules: ReadonlyArray<RedactionRule>) => string;
|
|
24
14
|
declare const redactValue: (value: unknown, rules: ReadonlyArray<RedactionRule>, visited?: WeakSet<object>) => unknown;
|
|
25
|
-
declare const layerRedactor: Layer.Layer<Redactor>;
|
|
26
15
|
//#endregion
|
|
27
|
-
export { RedactionRule,
|
|
16
|
+
export { RedactionRule, redactText, redactValue, redaction_d_exports };
|
|
28
17
|
//# sourceMappingURL=redaction.d.mts.map
|