@pikku/core 0.12.72 → 0.12.77
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/CHANGELOG.md +1171 -0
- package/dist/column-form.d.ts +32 -0
- package/dist/column-form.js +42 -0
- package/dist/crypto-utils.d.ts +43 -7
- package/dist/crypto-utils.js +163 -42
- package/dist/data-classification.d.ts +44 -0
- package/dist/dev/hot-reload.js +11 -30
- package/dist/dev/module-runner.d.ts +3 -7
- package/dist/dev/module-runner.js +4 -10
- package/dist/dev/reload-meta.d.ts +8 -20
- package/dist/dev/reload-meta.js +9 -29
- package/dist/errors/error-handler.d.ts +5 -30
- package/dist/errors/error-handler.js +16 -32
- package/dist/errors/errors.d.ts +32 -151
- package/dist/errors/errors.js +55 -157
- package/dist/function/abort-scope.d.ts +47 -0
- package/dist/function/abort-scope.js +63 -0
- package/dist/function/function-runner.js +37 -32
- package/dist/function/functions.types.d.ts +57 -136
- package/dist/function/functions.types.js +0 -58
- package/dist/function/index.d.ts +1 -1
- package/dist/function/list.types.d.ts +12 -62
- package/dist/function/list.types.js +4 -25
- package/dist/handle-error.d.ts +0 -13
- package/dist/handle-error.js +0 -18
- package/dist/index.d.ts +11 -5
- package/dist/index.js +7 -2
- package/dist/middleware/auth-apikey.d.ts +3 -18
- package/dist/middleware/auth-apikey.js +0 -17
- package/dist/middleware/auth-bearer.d.ts +6 -41
- package/dist/middleware/auth-bearer.js +5 -41
- package/dist/middleware/auth-cookie.d.ts +5 -27
- package/dist/middleware/auth-cookie.js +2 -26
- package/dist/middleware/cors.d.ts +7 -34
- package/dist/middleware/cors.js +7 -34
- package/dist/middleware/remote-auth.d.ts +3 -1
- package/dist/middleware/remote-auth.js +4 -3
- package/dist/middleware/telemetry.d.ts +8 -33
- package/dist/middleware/telemetry.js +2 -31
- package/dist/middleware-runner.d.ts +4 -55
- package/dist/middleware-runner.js +5 -74
- package/dist/permissions.d.ts +3 -44
- package/dist/permissions.js +19 -71
- package/dist/pikku-request.d.ts +0 -6
- package/dist/pikku-request.js +0 -6
- package/dist/pikku-state.d.ts +0 -26
- package/dist/pikku-state.js +2 -30
- package/dist/remote.d.ts +3 -5
- package/dist/remote.js +9 -8
- package/dist/schema.d.ts +5 -39
- package/dist/schema.js +5 -39
- package/dist/scopes.d.ts +4 -23
- package/dist/scopes.js +7 -48
- package/dist/secret-value.d.ts +56 -0
- package/dist/secret-value.js +46 -0
- package/dist/services/ai-agent-runner-service.d.ts +20 -0
- package/dist/services/ai-embedding-service.d.ts +2 -25
- package/dist/services/audit-service.d.ts +74 -4
- package/dist/services/audit-service.js +8 -7
- package/dist/services/content-service.d.ts +1 -46
- package/dist/services/credential-service.d.ts +3 -40
- package/dist/services/credential-wire-service.d.ts +5 -0
- package/dist/services/credential-wire-service.js +9 -1
- package/dist/services/deployment-service.d.ts +3 -9
- package/dist/services/email-service.d.ts +2 -1
- package/dist/services/gateway-service.d.ts +0 -15
- package/dist/services/http-personas.d.ts +80 -0
- package/dist/services/http-personas.js +233 -0
- package/dist/services/in-memory-queue-service.d.ts +0 -14
- package/dist/services/in-memory-queue-service.js +1 -15
- package/dist/services/in-memory-trigger-service.d.ts +0 -18
- package/dist/services/in-memory-trigger-service.js +1 -18
- package/dist/services/in-memory-workflow-service.d.ts +0 -16
- package/dist/services/in-memory-workflow-service.js +4 -33
- package/dist/services/index.d.ts +8 -9
- package/dist/services/index.js +3 -6
- package/dist/services/istanbul-coverage-service.d.ts +1 -5
- package/dist/services/istanbul-coverage-service.js +2 -8
- package/dist/services/jwt-service.d.ts +1 -16
- package/dist/services/local-content-request-handler.d.ts +29 -0
- package/dist/services/local-content-request-handler.js +176 -0
- package/dist/services/local-content.d.ts +13 -2
- package/dist/services/local-content.js +40 -13
- package/dist/services/local-gateway-service.d.ts +0 -16
- package/dist/services/local-gateway-service.js +2 -17
- package/dist/services/local-secrets.d.ts +4 -7
- package/dist/services/local-secrets.js +7 -7
- package/dist/services/logger-console.d.ts +3 -7
- package/dist/services/logger-console.js +3 -7
- package/dist/services/logger.d.ts +22 -40
- package/dist/services/meta-service.d.ts +23 -26
- package/dist/services/meta-service.js +22 -36
- package/dist/services/personas-service.d.ts +134 -0
- package/dist/services/personas-service.js +40 -0
- package/dist/services/pikku-user-id.js +0 -4
- package/dist/services/queue-webhook-service.d.ts +2 -36
- package/dist/services/queue-webhook-service.js +10 -42
- package/dist/services/scheduler-service.d.ts +1 -50
- package/dist/services/scheduler-service.js +0 -10
- package/dist/services/schema-service.d.ts +1 -24
- package/dist/services/scope-service.d.ts +49 -34
- package/dist/services/scoped-secret-service.d.ts +4 -7
- package/dist/services/scoped-secret-service.js +0 -4
- package/dist/services/secret-host-binding.d.ts +8 -0
- package/dist/services/secret-host-binding.js +36 -0
- package/dist/services/secret-service.d.ts +12 -35
- package/dist/services/secretless.d.ts +6 -0
- package/dist/services/secretless.js +21 -0
- package/dist/services/stub-tracker.d.ts +7 -18
- package/dist/services/stub-tracker.js +8 -18
- package/dist/services/system-role-guard.d.ts +33 -0
- package/dist/services/system-role-guard.js +38 -0
- package/dist/services/trigger-service.d.ts +0 -12
- package/dist/services/typed-secret-service.d.ts +5 -11
- package/dist/services/typed-secret-service.js +1 -7
- package/dist/services/v8-coverage-service.d.ts +2 -3
- package/dist/services/v8-coverage-service.js +1 -2
- package/dist/services/variables-service.d.ts +1 -8
- package/dist/services/webhook-service.d.ts +21 -64
- package/dist/services/webhook-service.js +6 -20
- package/dist/services/workflow-service.d.ts +3 -15
- package/dist/testing/service-tests.js +6 -23
- package/dist/time-utils.d.ts +0 -16
- package/dist/time-utils.js +1 -19
- package/dist/types/core.types.d.ts +120 -219
- package/dist/types/core.types.js +0 -42
- package/dist/types/state.types.d.ts +4 -9
- package/dist/utils/hmac.d.ts +4 -10
- package/dist/utils/hmac.js +4 -10
- package/dist/utils/safe-fetch.d.ts +7 -35
- package/dist/utils/safe-fetch.js +13 -53
- package/dist/utils.d.ts +1 -6
- package/dist/utils.js +6 -15
- package/dist/wirings/actor-flow/actor-flow.types.d.ts +1 -34
- package/dist/wirings/actor-flow/index.d.ts +0 -9
- package/dist/wirings/actor-flow/run-conversation.d.ts +5 -5
- package/dist/wirings/actor-flow/run-conversation.js +14 -7
- package/dist/wirings/ai-agent/ai-agent-agui.d.ts +0 -5
- package/dist/wirings/ai-agent/ai-agent-agui.js +46 -12
- package/dist/wirings/ai-agent/ai-agent-helpers.d.ts +7 -0
- package/dist/wirings/ai-agent/ai-agent-helpers.js +7 -0
- package/dist/wirings/ai-agent/ai-agent-interrupt.d.ts +153 -0
- package/dist/wirings/ai-agent/ai-agent-interrupt.js +256 -0
- package/dist/wirings/ai-agent/ai-agent-memory.js +0 -2
- package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +0 -9
- package/dist/wirings/ai-agent/ai-agent-model-config.js +1 -9
- package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +10 -99
- package/dist/wirings/ai-agent/ai-agent-prepare.js +65 -132
- package/dist/wirings/ai-agent/ai-agent-registry.d.ts +2 -1
- package/dist/wirings/ai-agent/ai-agent-registry.js +5 -1
- package/dist/wirings/ai-agent/ai-agent-runner.js +63 -22
- package/dist/wirings/ai-agent/ai-agent-stream.d.ts +25 -2
- package/dist/wirings/ai-agent/ai-agent-stream.js +180 -64
- package/dist/wirings/ai-agent/ai-agent.types.d.ts +124 -4
- package/dist/wirings/ai-agent/index.d.ts +6 -4
- package/dist/wirings/ai-agent/index.js +5 -4
- package/dist/wirings/ai-agent/voice-input.d.ts +59 -1
- package/dist/wirings/ai-agent/voice-input.js +90 -12
- package/dist/wirings/ai-agent/voice-output.d.ts +69 -1
- package/dist/wirings/ai-agent/voice-output.js +162 -50
- package/dist/wirings/channel/channel-common.d.ts +7 -20
- package/dist/wirings/channel/channel-common.js +7 -21
- package/dist/wirings/channel/channel-handler.js +25 -6
- package/dist/wirings/channel/channel-host-rpc.d.ts +25 -0
- package/dist/wirings/channel/channel-host-rpc.js +38 -0
- package/dist/wirings/channel/channel-middleware-runner.d.ts +0 -12
- package/dist/wirings/channel/channel-middleware-runner.js +0 -12
- package/dist/wirings/channel/channel-rpc-registry.d.ts +31 -0
- package/dist/wirings/channel/channel-rpc-registry.js +89 -0
- package/dist/wirings/channel/channel-rpc-responder.d.ts +15 -0
- package/dist/wirings/channel/channel-rpc-responder.js +71 -0
- package/dist/wirings/channel/channel-rpc-service.d.ts +40 -0
- package/dist/wirings/channel/channel-rpc-service.js +106 -0
- package/dist/wirings/channel/channel-rpc-validators.d.ts +14 -0
- package/dist/wirings/channel/channel-rpc-validators.js +30 -0
- package/dist/wirings/channel/channel-rpc.d.ts +5 -0
- package/dist/wirings/channel/channel-rpc.js +5 -0
- package/dist/wirings/channel/channel-rpc.types.d.ts +90 -0
- package/dist/wirings/channel/channel-rpc.types.js +50 -0
- package/dist/wirings/channel/channel-runner.d.ts +0 -4
- package/dist/wirings/channel/channel-runner.js +0 -14
- package/dist/wirings/channel/channel-store.d.ts +0 -10
- package/dist/wirings/channel/channel.types.d.ts +12 -1
- package/dist/wirings/channel/define-channel-routes.d.ts +0 -20
- package/dist/wirings/channel/define-channel-routes.js +0 -20
- package/dist/wirings/channel/eventhub-service.d.ts +0 -18
- package/dist/wirings/channel/index.d.ts +4 -1
- package/dist/wirings/channel/index.js +2 -0
- package/dist/wirings/channel/local/local-channel-runner.js +3 -1
- package/dist/wirings/channel/local/local-eventhub-service.d.ts +0 -33
- package/dist/wirings/channel/local/local-eventhub-service.js +2 -36
- package/dist/wirings/channel/log-channels.d.ts +0 -4
- package/dist/wirings/channel/log-channels.js +0 -4
- package/dist/wirings/channel/pikku-abstract-channel-handler.js +6 -0
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +2 -5
- package/dist/wirings/cli/channel/cli-approval.d.ts +41 -0
- package/dist/wirings/cli/channel/cli-approval.js +81 -0
- package/dist/wirings/cli/channel/cli-channel-runner.d.ts +0 -4
- package/dist/wirings/cli/channel/cli-channel-runner.js +3 -25
- package/dist/wirings/cli/channel/cli-raw-channel-runner.d.ts +47 -9
- package/dist/wirings/cli/channel/cli-raw-channel-runner.js +24 -16
- package/dist/wirings/cli/channel/cli-raw-client-runner.d.ts +38 -0
- package/dist/wirings/cli/channel/cli-raw-client-runner.js +129 -0
- package/dist/wirings/cli/channel/index.d.ts +5 -0
- package/dist/wirings/cli/channel/index.js +2 -0
- package/dist/wirings/cli/cli-runner.d.ts +20 -20
- package/dist/wirings/cli/cli-runner.js +28 -89
- package/dist/wirings/cli/cli.types.d.ts +14 -3
- package/dist/wirings/cli/command-parser.d.ts +1 -10
- package/dist/wirings/cli/command-parser.js +10 -87
- package/dist/wirings/cli/define-cli-commands.d.ts +1 -17
- package/dist/wirings/cli/define-cli-commands.js +1 -17
- package/dist/wirings/credential/credential.types.d.ts +0 -12
- package/dist/wirings/credential/define-credential.d.ts +48 -0
- package/dist/wirings/credential/define-credential.js +47 -0
- package/dist/wirings/credential/index.d.ts +1 -1
- package/dist/wirings/credential/index.js +1 -1
- package/dist/wirings/credential/validate-credential-definitions.d.ts +2 -4
- package/dist/wirings/gateway/gateway-runner.d.ts +1 -20
- package/dist/wirings/gateway/gateway-runner.js +8 -105
- package/dist/wirings/gateway/gateway.types.d.ts +7 -80
- package/dist/wirings/http/http-routes.d.ts +0 -63
- package/dist/wirings/http/http-routes.js +0 -63
- package/dist/wirings/http/http-runner.d.ts +0 -99
- package/dist/wirings/http/http-runner.js +9 -165
- package/dist/wirings/http/http.types.d.ts +14 -55
- package/dist/wirings/http/log-http-routes.d.ts +0 -4
- package/dist/wirings/http/log-http-routes.js +0 -4
- package/dist/wirings/http/pikku-fetch-http-request.d.ts +0 -40
- package/dist/wirings/http/pikku-fetch-http-request.js +0 -58
- package/dist/wirings/http/pikku-fetch-http-response.js +0 -3
- package/dist/wirings/http/routers/path-to-regex.js +2 -13
- package/dist/wirings/http/web-request.d.ts +0 -8
- package/dist/wirings/http/web-request.js +25 -17
- package/dist/wirings/mcp/mcp-runner.d.ts +1 -4
- package/dist/wirings/mcp/mcp-runner.js +1 -14
- package/dist/wirings/mcp/mcp.types.d.ts +2 -35
- package/dist/wirings/oauth2/oauth2.types.d.ts +0 -28
- package/dist/wirings/oauth2/oauth2.types.js +0 -3
- package/dist/wirings/persona/define-personas.d.ts +32 -0
- package/dist/wirings/persona/define-personas.js +31 -0
- package/dist/wirings/persona/index.d.ts +21 -0
- package/dist/wirings/persona/index.js +17 -0
- package/dist/wirings/persona/persona-email.d.ts +37 -0
- package/dist/wirings/persona/persona-email.js +69 -0
- package/dist/wirings/persona/persona-environments.d.ts +45 -0
- package/dist/wirings/persona/persona-environments.js +81 -0
- package/dist/wirings/persona/persona-mailbox.d.ts +101 -0
- package/dist/wirings/persona/persona-mailbox.js +53 -0
- package/dist/wirings/persona/persona.types.d.ts +136 -0
- package/dist/wirings/persona/persona.types.js +1 -0
- package/dist/wirings/persona/validate-personas.d.ts +53 -0
- package/dist/wirings/persona/validate-personas.js +94 -0
- package/dist/wirings/queue/index.d.ts +3 -0
- package/dist/wirings/queue/index.js +2 -3
- package/dist/wirings/queue/queue-identity.d.ts +28 -0
- package/dist/wirings/queue/queue-identity.js +103 -0
- package/dist/wirings/queue/queue-runner.d.ts +0 -19
- package/dist/wirings/queue/queue-runner.js +9 -30
- package/dist/wirings/queue/queue.types.d.ts +20 -90
- package/dist/wirings/queue/register-queue-helper.d.ts +0 -12
- package/dist/wirings/queue/register-queue-helper.js +0 -11
- package/dist/wirings/queue/signed-queue-service.d.ts +17 -0
- package/dist/wirings/queue/signed-queue-service.js +42 -0
- package/dist/wirings/queue/validate-worker-config.d.ts +2 -23
- package/dist/wirings/queue/validate-worker-config.js +0 -14
- package/dist/wirings/role/define-system-role.d.ts +32 -0
- package/dist/wirings/role/define-system-role.js +31 -0
- package/dist/wirings/role/index.d.ts +3 -0
- package/dist/wirings/role/index.js +2 -0
- package/dist/wirings/role/role.types.d.ts +43 -0
- package/dist/wirings/role/role.types.js +1 -0
- package/dist/wirings/role/validate-role-definitions.d.ts +21 -0
- package/dist/wirings/role/validate-role-definitions.js +71 -0
- package/dist/wirings/rpc/addon-runner.d.ts +0 -19
- package/dist/wirings/rpc/addon-runner.js +0 -51
- package/dist/wirings/rpc/remote-addon-auth.d.ts +3 -13
- package/dist/wirings/rpc/remote-addon-auth.js +7 -11
- package/dist/wirings/rpc/rpc-runner.d.ts +11 -18
- package/dist/wirings/rpc/rpc-runner.js +88 -105
- package/dist/wirings/rpc/rpc-types.d.ts +7 -6
- package/dist/wirings/rpc/wire-addon.d.ts +25 -0
- package/dist/wirings/rpc/wire-addon.js +62 -0
- package/dist/wirings/rpc/wire-remote-addon.d.ts +3 -28
- package/dist/wirings/rpc/wire-remote-addon.js +0 -8
- package/dist/wirings/scheduler/log-schedulers.d.ts +0 -4
- package/dist/wirings/scheduler/log-schedulers.js +0 -4
- package/dist/wirings/scheduler/scheduler-runner.d.ts +0 -1
- package/dist/wirings/scheduler/scheduler-runner.js +0 -1
- package/dist/wirings/scheduler/scheduler.types.d.ts +1 -14
- package/dist/wirings/scope/define-scope.d.ts +32 -0
- package/dist/wirings/scope/define-scope.js +31 -0
- package/dist/wirings/scope/index.d.ts +1 -1
- package/dist/wirings/scope/index.js +1 -1
- package/dist/wirings/scope/scope.types.d.ts +7 -9
- package/dist/wirings/scope/validate-scope-definitions.d.ts +2 -21
- package/dist/wirings/scope/validate-scope-definitions.js +3 -21
- package/dist/wirings/secret/index.d.ts +1 -1
- package/dist/wirings/secret/index.js +1 -1
- package/dist/wirings/secret/secret.types.d.ts +19 -15
- package/dist/wirings/secret/secret.types.js +1 -1
- package/dist/wirings/secret/validate-secret-definitions.d.ts +2 -4
- package/dist/wirings/trigger/trigger-runner.d.ts +0 -27
- package/dist/wirings/trigger/trigger-runner.js +1 -24
- package/dist/wirings/trigger/trigger.types.d.ts +1 -82
- package/dist/wirings/trigger/trigger.types.js +0 -34
- package/dist/wirings/variable/index.d.ts +1 -1
- package/dist/wirings/variable/index.js +1 -1
- package/dist/wirings/variable/validate-variable-definitions.d.ts +2 -4
- package/dist/wirings/variable/variable.types.d.ts +1 -13
- package/dist/wirings/variable/variable.types.js +1 -1
- package/dist/wirings/virtual-user/index.d.ts +30 -0
- package/dist/wirings/virtual-user/index.js +10 -0
- package/dist/wirings/virtual-user/prepare-virtual-user-run.d.ts +54 -0
- package/dist/wirings/virtual-user/prepare-virtual-user-run.js +49 -0
- package/dist/wirings/virtual-user/run-virtual-user.d.ts +92 -0
- package/dist/wirings/virtual-user/run-virtual-user.js +478 -0
- package/dist/wirings/virtual-user/virtual-user-agents.d.ts +38 -0
- package/dist/wirings/virtual-user/virtual-user-agents.js +24 -0
- package/dist/wirings/virtual-user/virtual-user-catalogue.d.ts +92 -0
- package/dist/wirings/virtual-user/virtual-user-catalogue.js +134 -0
- package/dist/wirings/virtual-user/virtual-user-derive.d.ts +26 -0
- package/dist/wirings/virtual-user/virtual-user-derive.js +137 -0
- package/dist/wirings/virtual-user/virtual-user-dispositions.d.ts +79 -0
- package/dist/wirings/virtual-user/virtual-user-dispositions.js +128 -0
- package/dist/wirings/virtual-user/virtual-user-intents.d.ts +78 -0
- package/dist/wirings/virtual-user/virtual-user-intents.js +142 -0
- package/dist/wirings/virtual-user/virtual-user-rng.d.ts +24 -0
- package/dist/wirings/virtual-user/virtual-user-rng.js +44 -0
- package/dist/wirings/virtual-user/virtual-user-run-store.d.ts +90 -0
- package/dist/wirings/virtual-user/virtual-user-run-store.js +1 -0
- package/dist/wirings/virtual-user/virtual-user-target.d.ts +21 -0
- package/dist/wirings/virtual-user/virtual-user-target.js +34 -0
- package/dist/wirings/virtual-user/virtual-user.types.d.ts +199 -0
- package/dist/wirings/virtual-user/virtual-user.types.js +8 -0
- package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +19 -15
- package/dist/wirings/workflow/dsl/workflow-runner.d.ts +0 -4
- package/dist/wirings/workflow/dsl/workflow-runner.js +0 -4
- package/dist/wirings/workflow/feature.d.ts +0 -19
- package/dist/wirings/workflow/feature.js +0 -19
- package/dist/wirings/workflow/graph/graph-node.d.ts +0 -98
- package/dist/wirings/workflow/graph/graph-node.js +0 -34
- package/dist/wirings/workflow/graph/graph-runner.js +6 -41
- package/dist/wirings/workflow/graph/wire-workflow-graph.d.ts +0 -4
- package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +0 -58
- package/dist/wirings/workflow/graph/workflow-graph.types.js +0 -6
- package/dist/wirings/workflow/index.d.ts +5 -7
- package/dist/wirings/workflow/index.js +3 -17
- package/dist/wirings/workflow/pikku-scenario-service.d.ts +87 -5
- package/dist/wirings/workflow/pikku-scenario-service.js +204 -43
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +7 -459
- package/dist/wirings/workflow/pikku-workflow-service.js +58 -551
- package/dist/wirings/workflow/run-timeline.d.ts +0 -47
- package/dist/wirings/workflow/run-timeline.js +0 -22
- package/dist/wirings/workflow/scenario-cookie-jar.d.ts +0 -23
- package/dist/wirings/workflow/scenario-cookie-jar.js +0 -16
- package/dist/wirings/workflow/scenario-poll.d.ts +0 -15
- package/dist/wirings/workflow/scenario-poll.js +0 -12
- package/dist/wirings/workflow/scenario-prose.d.ts +0 -28
- package/dist/wirings/workflow/scenario-prose.js +1 -19
- package/dist/wirings/workflow/scenario-step-guards.d.ts +0 -13
- package/dist/wirings/workflow/scenario-step-guards.js +1 -14
- package/dist/wirings/workflow/scenario-step.types.d.ts +84 -12
- package/dist/wirings/workflow/scenario-step.types.js +5 -1
- package/dist/wirings/workflow/scenario-surface.d.ts +16 -0
- package/dist/wirings/workflow/scenario-surface.js +56 -0
- package/dist/wirings/workflow/workflow-invocation-id.d.ts +0 -18
- package/dist/wirings/workflow/workflow-invocation-id.js +2 -22
- package/dist/wirings/workflow/workflow-queue-workers.d.ts +0 -20
- package/dist/wirings/workflow/workflow-queue-workers.js +0 -19
- package/dist/wirings/workflow/workflow.types.d.ts +5 -195
- package/knowledge/decisions/index.md +19 -0
- package/knowledge/decisions/internals/a-secret-that-fails-to-decrypt-fails-the-whole-read.md +49 -0
- package/knowledge/decisions/internals/a-virtual-user-run-is-not-a-workflow-and-not-a-queued-job.md +48 -0
- package/knowledge/decisions/internals/actor-flow-conversations-seed-a-hidden-kickoff-message.md +23 -0
- package/knowledge/decisions/internals/actor-flow-drives-the-target-through-a-transport-seam.md +24 -0
- package/knowledge/decisions/internals/actor-flow-verdicts-are-llm-self-evaluations.md +25 -0
- package/knowledge/decisions/internals/addon-package-roots-resolve-by-walking-node-module-search-paths.md +26 -0
- package/knowledge/decisions/internals/addon-singleton-services-are-cached-per-namespace-not-per-package.md +33 -0
- package/knowledge/decisions/internals/addon-workflow-names-are-prefixed-with-the-consumer-namespace.md +28 -0
- package/knowledge/decisions/internals/ai-agent-agui-bridge-obeys-the-client-ordering-contract.md +29 -0
- package/knowledge/decisions/internals/ai-agent-audio-chunks-carry-the-format-the-provider-returned.md +20 -0
- package/knowledge/decisions/internals/ai-agent-credential-suspensions-hide-the-tool-result.md +26 -0
- package/knowledge/decisions/internals/ai-agent-delegate-and-supervise-hide-different-text.md +26 -0
- package/knowledge/decisions/internals/ai-agent-llm-tool-arguments-have-nulls-stripped.md +23 -0
- package/knowledge/decisions/internals/ai-agent-model-config-stays-a-single-resolution-seam.md +25 -0
- package/knowledge/decisions/internals/ai-agent-onerror-hooks-cannot-change-the-failure.md +22 -0
- package/knowledge/decisions/internals/ai-agent-runner-methods-must-keep-their-receiver.md +22 -0
- package/knowledge/decisions/internals/ai-agent-stream-persistence-is-best-effort.md +27 -0
- package/knowledge/decisions/internals/ai-agent-sub-agents-inherit-the-parent-context-block.md +26 -0
- package/knowledge/decisions/internals/ai-agent-tool-execute-failures-are-logged-unconditionally.md +25 -0
- package/knowledge/decisions/internals/ai-agent-voice-input-transcribes-audio-parts-in-place.md +22 -0
- package/knowledge/decisions/internals/ai-agent-working-memory-is-persisted-only-when-valid.md +25 -0
- package/knowledge/decisions/internals/channel-message-handlers-accept-three-config-shapes.md +30 -0
- package/knowledge/decisions/internals/channel-middleware-caches-only-statically-resolved-middleware.md +31 -0
- package/knowledge/decisions/internals/channel-state-is-per-socket-session-state-is-per-user.md +29 -0
- package/knowledge/decisions/internals/channel-user-id-is-persisted-after-onconnect-middleware-runs.md +28 -0
- package/knowledge/decisions/internals/cli-option-names-are-camelcase-in-state-and-kebab-on-the-command-line.md +27 -0
- package/knowledge/decisions/internals/cli-parse-errors-are-routed-by-message-prefix.md +28 -0
- package/knowledge/decisions/internals/cli-stdout-is-reserved-for-machine-readable-output.md +34 -0
- package/knowledge/decisions/internals/cli-unknown-long-options-warn-instead-of-failing.md +29 -0
- package/knowledge/decisions/internals/core-column-form-is-an-axis-of-its-own.md +84 -0
- package/knowledge/decisions/internals/core-data-classification-brand-is-an-optional-property.md +41 -0
- package/knowledge/decisions/internals/core-function-runner-restores-the-wire-fields-it-overwrites.md +44 -0
- package/knowledge/decisions/internals/core-hot-reload-merges-generated-meta-never-replaces-it.md +39 -0
- package/knowledge/decisions/internals/core-hot-reload-owns-its-module-registry.md +42 -0
- package/knowledge/decisions/internals/core-middleware-order-is-scope-then-priority.md +39 -0
- package/knowledge/decisions/internals/core-schema-defaults-apply-on-every-transport.md +43 -0
- package/knowledge/decisions/internals/core-scopes-are-an-and-gate-separate-from-permissions.md +38 -0
- package/knowledge/decisions/internals/core-state-is-a-global-map-written-only-at-registration-time.md +44 -0
- package/knowledge/decisions/internals/email-meta-is-read-uncached-because-codegen-rewrites-it-mid-session.md +27 -0
- package/knowledge/decisions/internals/gateway-adapters-resolve-lazily-and-are-promise-cached.md +32 -0
- package/knowledge/decisions/internals/gateway-webhook-challenges-echo-bytes-not-json.md +28 -0
- package/knowledge/decisions/internals/gateway-wiring-is-a-meta-wiring-over-http-and-channels.md +31 -0
- package/knowledge/decisions/internals/generated-src-paths-in-pikku-meta-are-absolute.md +26 -0
- package/knowledge/decisions/internals/http-request-bodies-are-read-once-and-shared.md +32 -0
- package/knowledge/decisions/internals/http-route-groups-cascade-config-in-a-fixed-order.md +28 -0
- package/knowledge/decisions/internals/http-router-matches-normalized-paths-but-returns-registered-ones.md +30 -0
- package/knowledge/decisions/internals/http-runner-logs-through-a-trace-scoped-logger-functions-do-not.md +26 -0
- package/knowledge/decisions/internals/http-set-cookie-headers-are-appended-never-joined.md +28 -0
- package/knowledge/decisions/internals/http-sse-streams-flush-headers-only-after-middleware.md +32 -0
- package/knowledge/decisions/internals/http-wiring-without-metadata-is-skipped-not-fatal.md +26 -0
- package/knowledge/decisions/internals/in-a-scenario-a-4xx-is-data-not-an-exception.md +25 -0
- package/knowledge/decisions/internals/in-memory-workflow-history-aliases-the-live-step-object.md +26 -0
- package/knowledge/decisions/internals/index.md +117 -0
- package/knowledge/decisions/internals/istanbul-statement-counts-attach-to-the-start-line-only.md +25 -0
- package/knowledge/decisions/internals/local-trigger-and-gateway-services-assume-a-single-process.md +26 -0
- package/knowledge/decisions/internals/node-only-builtins-are-imported-dynamically.md +24 -0
- package/knowledge/decisions/internals/one-project-shape-check-two-validators.md +53 -0
- package/knowledge/decisions/internals/queue-group-concurrency-keeps-one-shared-queue-fair.md +28 -0
- package/knowledge/decisions/internals/queue-jobs-always-carry-an-explicit-attempts-count.md +27 -0
- package/knowledge/decisions/internals/remote-addons-dispatch-over-http-instead-of-local-meta.md +31 -0
- package/knowledge/decisions/internals/rpc-names-resolve-through-package-scope-before-root.md +32 -0
- package/knowledge/decisions/internals/scenario-agent-calls-sign-in-on-401-only.md +27 -0
- package/knowledge/decisions/internals/scenario-meta-lives-apart-from-app-meta-but-merges-when-read-off-disk.md +26 -0
- package/knowledge/decisions/internals/scenario-steps-return-drained-response-records.md +27 -0
- package/knowledge/decisions/internals/scenarios-live-in-files-named-for-them.md +48 -0
- package/knowledge/decisions/internals/scope-roots-may-be-co-declared-by-an-addon-and-its-host-app.md +30 -0
- package/knowledge/decisions/internals/serverless-channel-disconnect-must-tolerate-a-missing-channel.md +28 -0
- package/knowledge/decisions/internals/the-dev-queue-copies-prod-timing-and-serialization-semantics.md +30 -0
- package/knowledge/decisions/internals/the-embedding-model-is-pinned-per-service-and-doc-query-embedding-is-split.md +29 -0
- package/knowledge/decisions/internals/the-in-memory-workflow-service-is-inline-only-and-single-process.md +27 -0
- package/knowledge/decisions/internals/the-kek-salt-is-scoped-to-the-key-version.md +40 -0
- package/knowledge/decisions/internals/the-schema-service-is-never-stubbed.md +26 -0
- package/knowledge/decisions/internals/trigger-declaration-is-split-from-trigger-source.md +33 -0
- package/knowledge/decisions/internals/typed-secret-service-caches-for-the-process-lifetime.md +26 -0
- package/knowledge/decisions/internals/validate-checks-personas-through-a-shared-module.md +43 -0
- package/knowledge/decisions/internals/webhook-delivery-history-records-every-attempt-best-effort.md +26 -0
- package/knowledge/decisions/internals/webhook-service-collaborators-are-constructor-args-not-locator-lookups.md +25 -0
- package/knowledge/decisions/internals/whether-a-run-is-inline-is-read-from-the-run-record.md +58 -0
- package/knowledge/decisions/internals/workflow-approval-expiry-is-decided-from-a-recorded-deadline.md +34 -0
- package/knowledge/decisions/internals/workflow-core-never-imports-a-browser-driver.md +42 -0
- package/knowledge/decisions/internals/workflow-dsl-meta-separates-runtime-expressions-from-literals.md +38 -0
- package/knowledge/decisions/internals/workflow-features-resolve-scenarios-by-object-identity.md +29 -0
- package/knowledge/decisions/internals/workflow-graph-inline-and-queued-runs-share-one-planner.md +42 -0
- package/knowledge/decisions/internals/workflow-graph-node-notes-are-excluded-from-the-graph-hash.md +25 -0
- package/knowledge/decisions/internals/workflow-inline-runs-report-their-run-id-before-they-can-fail.md +29 -0
- package/knowledge/decisions/internals/workflow-invocation-id-is-the-dedupe-key-not-step-id.md +43 -0
- package/knowledge/decisions/internals/workflow-queued-step-dispatch-requires-an-explicit-opt-in.md +29 -0
- package/knowledge/decisions/internals/workflow-queues-are-per-workflow-by-default.md +42 -0
- package/knowledge/decisions/internals/workflow-repeated-step-names-get-an-ordinal-suffix.md +33 -0
- package/knowledge/decisions/internals/workflow-replay-reads-its-steps-once-and-caches-only-the-immutable-half.md +32 -0
- package/knowledge/decisions/internals/workflow-retries-are-owned-by-the-workflow-not-the-queue.md +31 -0
- package/knowledge/decisions/internals/workflow-run-capabilities-are-extensions-not-subclasses.md +39 -0
- package/knowledge/decisions/internals/workflow-run-mirror-is-never-a-source-of-truth.md +29 -0
- package/knowledge/decisions/internals/workflow-run-polling-backs-off-to-the-callers-ceiling.md +33 -0
- package/knowledge/decisions/internals/workflow-run-timeline-is-a-pure-fold-over-durable-history.md +37 -0
- package/knowledge/decisions/internals/workflow-scenario-assertions-never-retry-and-record-one-step.md +50 -0
- package/knowledge/decisions/internals/workflow-scenario-hooks-are-a-scenario-only-affordance.md +43 -0
- package/knowledge/decisions/internals/workflow-scenario-prose-is-rendered-from-typed-calls-not-parsed-from-english.md +32 -0
- package/knowledge/decisions/internals/workflow-scenario-quarantine-reason-lives-in-code.md +18 -0
- package/knowledge/decisions/internals/workflow-scenario-step-targets-are-string-literals-for-the-inspector.md +34 -0
- package/knowledge/decisions/internals/workflow-step-compensation-runs-as-its-own-durable-step.md +26 -0
- package/knowledge/decisions/internals/workflow-step-dispatch-failure-is-transient-not-a-run-failure.md +33 -0
- package/knowledge/decisions/internals/workflow-step-lock-is-held-only-to-claim-the-step.md +27 -0
- package/knowledge/decisions/internals/workflow-step-rpc-name-is-provenance-only.md +34 -0
- package/knowledge/decisions/internals/workflow-suspend-and-approval-reasons-are-durable-step-identities.md +38 -0
- package/knowledge/decisions/internals/workflow-suspended-runs-keep-their-in-process-context.md +30 -0
- package/knowledge/decisions/security/a-dropped-audit-write-is-always-logged.md +26 -0
- package/knowledge/decisions/security/actor-flow-missing-approval-decisions-default-to-denied.md +22 -0
- package/knowledge/decisions/security/actor-sign-in-is-proven-by-set-cookie-not-a-non-empty-jar.md +27 -0
- package/knowledge/decisions/security/actor-sign-in-only-works-for-actor-flagged-users.md +27 -0
- package/knowledge/decisions/security/addon-auth-and-tags-only-tighten.md +43 -0
- package/knowledge/decisions/security/addon-config-gates-apply-only-at-the-namespaced-rpc-boundary.md +52 -0
- package/knowledge/decisions/security/addon-scopes-are-resolved-where-the-function-runs.md +46 -0
- package/knowledge/decisions/security/ai-agent-approval-forwarding-requires-a-symbol-brand.md +27 -0
- package/knowledge/decisions/security/ai-agent-credential-requests-are-symbol-branded.md +37 -0
- package/knowledge/decisions/security/ai-agent-gate-requires-a-session-only-when-auth-is-true.md +31 -0
- package/knowledge/decisions/security/ai-agent-ownership-failures-never-echo-the-resource.md +23 -0
- package/knowledge/decisions/security/ai-agent-resume-re-runs-the-authorization-gate.md +22 -0
- package/knowledge/decisions/security/ai-agent-sessionless-deployments-have-no-thread-ownership.md +39 -0
- package/knowledge/decisions/security/ai-agent-thread-ownership-composes-the-session-principal.md +30 -0
- package/knowledge/decisions/security/ai-agent-tool-filtering-reads-the-live-function-config.md +24 -0
- package/knowledge/decisions/security/an-empty-owners-constraint-matches-nothing.md +30 -0
- package/knowledge/decisions/security/an-exposed-ungated-function-is-a-codegen-warning.md +49 -0
- package/knowledge/decisions/security/console-addon-privileged-functions-gate-themselves.md +76 -0
- package/knowledge/decisions/security/core-safe-fetch-blocks-ssrf-by-host-literal-not-dns.md +39 -0
- package/knowledge/decisions/security/core-secrets-use-a-per-secret-dek-wrapped-by-a-kek.md +37 -0
- package/knowledge/decisions/security/gateway-handlers-run-through-the-function-runner-gate.md +31 -0
- package/knowledge/decisions/security/gateway-middleware-sessions-must-be-bridged-onto-the-wire.md +30 -0
- package/knowledge/decisions/security/global-permissions-and-function-permissions-are-independent-gates.md +40 -0
- package/knowledge/decisions/security/http-error-detail-is-withheld-from-clients-in-production.md +33 -0
- package/knowledge/decisions/security/http-request-bodies-are-bounded-before-they-are-buffered.md +46 -0
- package/knowledge/decisions/security/index.md +55 -0
- package/knowledge/decisions/security/mcp-internal-error-details-are-double-gated-on-production.md +27 -0
- package/knowledge/decisions/security/passphrases-are-stretched-key-material-is-expanded.md +40 -0
- package/knowledge/decisions/security/permission-auth-filtering-requires-live-permission-functions.md +31 -0
- package/knowledge/decisions/security/pikku-carries-actor-scopes-as-data-and-the-app-grants-them.md +26 -0
- package/knowledge/decisions/security/queue-job-identities-are-signed-at-enqueue.md +69 -0
- package/knowledge/decisions/security/queue-jobs-carry-the-producers-pikku-user-id.md +39 -0
- package/knowledge/decisions/security/remote-addon-tokens-are-client-credentials-not-mesh-trust.md +34 -0
- package/knowledge/decisions/security/scaffold-features-are-authenticated-unless-opted-out.md +49 -0
- package/knowledge/decisions/security/scenario-step-functions-are-never-externally-invocable.md +30 -0
- package/knowledge/decisions/security/scope-resolution-happens-at-the-session-boundary-and-sync-never-deletes.md +28 -0
- package/knowledge/decisions/security/self-authentication-is-declared-not-detected.md +34 -0
- package/knowledge/decisions/security/signed-content-urls-bind-the-request-path.md +37 -0
- package/knowledge/decisions/security/webhook-bodies-are-signed-before-they-are-enqueued.md +25 -0
- package/knowledge/decisions/security/workflow-actor-steps-always-use-the-real-transport.md +34 -0
- package/knowledge/decisions/security/workflow-approval-payloads-are-validated-on-replay-inside-the-workflow.md +40 -0
- package/knowledge/decisions/security/workflow-queued-steps-rehydrate-their-session-from-the-run-wire.md +32 -0
- package/knowledge/decisions/security/workflow-scenario-sessions-are-isolated-per-actor-and-per-scenario.md +32 -0
- package/knowledge/decisions/security/workflow-scenario-steps-are-never-network-invocable.md +31 -0
- package/knowledge/index.md +24 -0
- package/knowledge/questions/index.md +15 -0
- package/package.json +6 -2
- package/run-tests.sh +0 -0
- package/src/column-form.test.ts +97 -0
- package/src/column-form.ts +58 -0
- package/src/crypto-utils.test.ts +460 -19
- package/src/crypto-utils.ts +306 -59
- package/src/data-classification.ts +45 -7
- package/src/dev/hot-reload.test.ts +0 -4
- package/src/dev/hot-reload.ts +11 -30
- package/src/dev/module-runner.ts +7 -32
- package/src/dev/reload-meta.ts +9 -29
- package/src/errors/error-handler.ts +20 -35
- package/src/errors/error.test.ts +30 -1
- package/src/errors/errors.ts +73 -157
- package/src/function/abort-scope.test.ts +97 -0
- package/src/function/abort-scope.ts +80 -0
- package/src/function/function-runner.test.ts +0 -7
- package/src/function/function-runner.ts +62 -32
- package/src/function/functions.types.ts +95 -138
- package/src/function/index.ts +1 -0
- package/src/function/list.types.test.ts +3 -25
- package/src/function/list.types.ts +12 -62
- package/src/handle-error.ts +0 -18
- package/src/index.ts +84 -3
- package/src/middleware/auth-apikey.test.ts +0 -1
- package/src/middleware/auth-apikey.ts +0 -17
- package/src/middleware/auth-bearer.test.ts +3 -5
- package/src/middleware/auth-bearer.ts +5 -41
- package/src/middleware/auth-cookie.test.ts +0 -6
- package/src/middleware/auth-cookie.ts +2 -26
- package/src/middleware/cors.test.ts +34 -0
- package/src/middleware/cors.ts +12 -33
- package/src/middleware/remote-auth.test.ts +26 -10
- package/src/middleware/remote-auth.ts +11 -3
- package/src/middleware/telemetry.ts +2 -31
- package/src/middleware-runner.test.ts +0 -2
- package/src/middleware-runner.ts +5 -74
- package/src/permissions.test.ts +30 -0
- package/src/permissions.ts +24 -74
- package/src/pikku-request.ts +0 -6
- package/src/pikku-state.ts +2 -30
- package/src/production-barrels-stay-lean.test.ts +110 -0
- package/src/remote.test.ts +173 -0
- package/src/remote.ts +18 -8
- package/src/schema.ts +5 -39
- package/src/scopes.ts +7 -48
- package/src/secret-value.test.ts +204 -0
- package/src/secret-value.ts +111 -0
- package/src/services/ai-agent-runner-service.ts +20 -0
- package/src/services/ai-embedding-service.ts +3 -25
- package/src/services/audit-service.ts +88 -11
- package/src/services/content-service.ts +1 -46
- package/src/services/credential-service.ts +3 -40
- package/src/services/credential-wire-service.test.ts +0 -2
- package/src/services/credential-wire-service.ts +9 -1
- package/src/services/deployment-service.ts +3 -9
- package/src/services/email-service.ts +3 -1
- package/src/services/gateway-service.ts +0 -15
- package/src/services/{http-scenario-actors-converse.test.ts → http-personas-converse.test.ts} +38 -9
- package/src/services/{http-scenario-actors.test.ts → http-personas.test.ts} +39 -22
- package/src/services/{http-scenario-actors.ts → http-personas.ts} +85 -45
- package/src/services/in-memory-queue-service.ts +1 -15
- package/src/services/in-memory-trigger-service.ts +1 -18
- package/src/services/in-memory-workflow-service.test.ts +0 -13
- package/src/services/in-memory-workflow-service.ts +4 -38
- package/src/services/index.ts +23 -18
- package/src/services/istanbul-coverage-service.ts +2 -8
- package/src/services/jwt-service.ts +1 -16
- package/src/services/local-content-request-handler.test.ts +202 -0
- package/src/services/local-content-request-handler.ts +267 -0
- package/src/services/local-content.test.ts +159 -27
- package/src/services/local-content.ts +55 -23
- package/src/services/local-gateway-service.ts +2 -17
- package/src/services/local-secrets.test.ts +20 -5
- package/src/services/local-secrets.ts +15 -11
- package/src/services/logger-console.test.ts +0 -1
- package/src/services/logger-console.ts +3 -7
- package/src/services/logger.ts +31 -46
- package/src/services/meta-service.test.ts +1 -5
- package/src/services/meta-service.ts +41 -61
- package/src/services/{scenario-actors-service.ts → personas-service.ts} +48 -43
- package/src/services/pikku-user-id.ts +0 -4
- package/src/services/queue-webhook-service.test.ts +2 -1
- package/src/services/queue-webhook-service.ts +10 -42
- package/src/services/scheduler-service.ts +1 -50
- package/src/services/schema-service.ts +1 -24
- package/src/services/scope-service.ts +50 -34
- package/src/services/scoped-secret-service.ts +4 -7
- package/src/services/secret-host-binding.test.ts +138 -0
- package/src/services/secret-host-binding.ts +51 -0
- package/src/services/secret-service.ts +12 -35
- package/src/services/secretless.test.ts +54 -0
- package/src/services/secretless.ts +29 -0
- package/src/services/stub-tracker.ts +8 -18
- package/src/services/system-role-guard.test.ts +93 -0
- package/src/services/system-role-guard.ts +71 -0
- package/src/services/trigger-service.ts +0 -12
- package/src/services/typed-secret-service.ts +12 -14
- package/src/services/v8-coverage-service.ts +3 -6
- package/src/services/variables-service.ts +1 -8
- package/src/services/webhook-service.ts +23 -64
- package/src/services/workflow-service.ts +3 -20
- package/src/testing/service-tests.ts +6 -32
- package/src/time-utils.ts +1 -19
- package/src/types/core.types.ts +137 -229
- package/src/types/state.types.ts +7 -9
- package/src/utils/hmac.ts +4 -10
- package/src/utils/safe-fetch.ts +13 -54
- package/src/utils.test.ts +11 -2
- package/src/utils.ts +6 -15
- package/src/wirings/actor-flow/actor-flow.types.ts +1 -34
- package/src/wirings/actor-flow/index.ts +0 -9
- package/src/wirings/actor-flow/run-conversation.test.ts +11 -6
- package/src/wirings/actor-flow/run-conversation.ts +19 -12
- package/src/wirings/ai-agent/ai-agent-agui.test.ts +91 -10
- package/src/wirings/ai-agent/ai-agent-agui.ts +49 -17
- package/src/wirings/ai-agent/ai-agent-helpers.ts +20 -0
- package/src/wirings/ai-agent/ai-agent-interrupt.test.ts +842 -0
- package/src/wirings/ai-agent/ai-agent-interrupt.ts +399 -0
- package/src/wirings/ai-agent/ai-agent-memory.ts +0 -2
- package/src/wirings/ai-agent/ai-agent-model-config.ts +1 -9
- package/src/wirings/ai-agent/ai-agent-prepare.test.ts +202 -31
- package/src/wirings/ai-agent/ai-agent-prepare.ts +89 -139
- package/src/wirings/ai-agent/ai-agent-registry.test.ts +191 -6
- package/src/wirings/ai-agent/ai-agent-registry.ts +18 -1
- package/src/wirings/ai-agent/ai-agent-resume-authorization.test.ts +0 -2
- package/src/wirings/ai-agent/ai-agent-runner.test.ts +11 -9
- package/src/wirings/ai-agent/ai-agent-runner.ts +85 -35
- package/src/wirings/ai-agent/ai-agent-stream.test.ts +205 -103
- package/src/wirings/ai-agent/ai-agent-stream.ts +224 -76
- package/src/wirings/ai-agent/ai-agent-thread-ownership.test.ts +301 -0
- package/src/wirings/ai-agent/ai-agent.types.ts +130 -5
- package/src/wirings/ai-agent/index.ts +37 -3
- package/src/wirings/ai-agent/voice-input.test.ts +137 -7
- package/src/wirings/ai-agent/voice-input.ts +96 -12
- package/src/wirings/ai-agent/voice-output.test.ts +512 -0
- package/src/wirings/ai-agent/voice-output.ts +243 -56
- package/src/wirings/channel/channel-common.ts +15 -20
- package/src/wirings/channel/channel-handler.test.ts +50 -0
- package/src/wirings/channel/channel-handler.ts +32 -11
- package/src/wirings/channel/channel-host-rpc.test.ts +150 -0
- package/src/wirings/channel/channel-host-rpc.ts +69 -0
- package/src/wirings/channel/channel-middleware-runner.test.ts +0 -1
- package/src/wirings/channel/channel-middleware-runner.ts +0 -12
- package/src/wirings/channel/channel-rpc-registry.ts +116 -0
- package/src/wirings/channel/channel-rpc-responder.ts +117 -0
- package/src/wirings/channel/channel-rpc-service.ts +146 -0
- package/src/wirings/channel/channel-rpc-validators.ts +65 -0
- package/src/wirings/channel/channel-rpc.test.ts +820 -0
- package/src/wirings/channel/channel-rpc.ts +5 -0
- package/src/wirings/channel/channel-rpc.types.ts +150 -0
- package/src/wirings/channel/channel-runner.ts +0 -14
- package/src/wirings/channel/channel-store.ts +0 -10
- package/src/wirings/channel/channel.types.ts +19 -8
- package/src/wirings/channel/define-channel-routes.ts +0 -20
- package/src/wirings/channel/eventhub-service.ts +0 -18
- package/src/wirings/channel/index.ts +35 -0
- package/src/wirings/channel/local/local-channel-handler.ts +3 -1
- package/src/wirings/channel/local/local-channel-runner.test.ts +0 -10
- package/src/wirings/channel/local/local-channel-runner.ts +3 -1
- package/src/wirings/channel/local/local-eventhub-service.test.ts +0 -13
- package/src/wirings/channel/local/local-eventhub-service.ts +2 -37
- package/src/wirings/channel/log-channels.ts +0 -4
- package/src/wirings/channel/pikku-abstract-channel-handler.test.ts +83 -2
- package/src/wirings/channel/pikku-abstract-channel-handler.ts +7 -0
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +2 -5
- package/src/wirings/cli/channel/cli-approval.test.ts +177 -0
- package/src/wirings/cli/channel/cli-approval.ts +135 -0
- package/src/wirings/cli/channel/cli-channel-runner.ts +4 -26
- package/src/wirings/cli/channel/cli-raw-channel-runner.test.ts +169 -0
- package/src/wirings/cli/channel/cli-raw-channel-runner.ts +59 -16
- package/src/wirings/cli/channel/cli-raw-client-runner.test.ts +480 -0
- package/src/wirings/cli/channel/cli-raw-client-runner.ts +185 -0
- package/src/wirings/cli/channel/index.ts +13 -0
- package/src/wirings/cli/cli-runner.test.ts +0 -1
- package/src/wirings/cli/cli-runner.ts +46 -88
- package/src/wirings/cli/cli.types.ts +14 -3
- package/src/wirings/cli/command-parser.test.ts +0 -4
- package/src/wirings/cli/command-parser.ts +11 -91
- package/src/wirings/cli/define-cli-commands.ts +1 -17
- package/src/wirings/credential/credential.types.ts +0 -12
- package/src/wirings/credential/{wire-credential.ts → define-credential.ts} +7 -7
- package/src/wirings/credential/index.ts +1 -1
- package/src/wirings/credential/validate-credential-definitions.ts +2 -4
- package/src/wirings/gateway/gateway-runner.test.ts +1 -21
- package/src/wirings/gateway/gateway-runner.ts +8 -110
- package/src/wirings/gateway/gateway.types.ts +7 -80
- package/src/wirings/http/http-routes.test.ts +0 -3
- package/src/wirings/http/http-routes.ts +0 -86
- package/src/wirings/http/http-runner.test.ts +0 -1
- package/src/wirings/http/http-runner.ts +8 -167
- package/src/wirings/http/http.types.ts +15 -62
- package/src/wirings/http/log-http-routes.ts +0 -4
- package/src/wirings/http/pikku-fetch-http-request.test.ts +2 -10
- package/src/wirings/http/pikku-fetch-http-request.ts +0 -58
- package/src/wirings/http/pikku-fetch-http-response.test.ts +1 -1
- package/src/wirings/http/pikku-fetch-http-response.ts +0 -3
- package/src/wirings/http/routers/path-to-regex.test.ts +4 -17
- package/src/wirings/http/routers/path-to-regex.ts +2 -13
- package/src/wirings/http/web-request.test.ts +33 -2
- package/src/wirings/http/web-request.ts +30 -17
- package/src/wirings/mcp/mcp-endpoint-registry.test.ts +0 -1
- package/src/wirings/mcp/mcp-runner.ts +2 -17
- package/src/wirings/mcp/mcp.types.ts +7 -42
- package/src/wirings/oauth2/oauth2.types.ts +0 -30
- package/src/wirings/persona/define-personas.ts +33 -0
- package/src/wirings/persona/index.ts +62 -0
- package/src/wirings/persona/persona-email.ts +87 -0
- package/src/wirings/persona/persona-environments.test.ts +183 -0
- package/src/wirings/persona/persona-environments.ts +138 -0
- package/src/wirings/persona/persona-mailbox.ts +156 -0
- package/src/wirings/persona/persona.test.ts +220 -0
- package/src/wirings/persona/persona.types.ts +142 -0
- package/src/wirings/persona/validate-personas.ts +133 -0
- package/src/wirings/queue/index.ts +13 -3
- package/src/wirings/queue/queue-identity.test.ts +454 -0
- package/src/wirings/queue/queue-identity.ts +176 -0
- package/src/wirings/queue/queue-runner.ts +12 -31
- package/src/wirings/queue/queue.types.ts +25 -90
- package/src/wirings/queue/register-queue-helper.ts +0 -14
- package/src/wirings/queue/signed-queue-service.ts +60 -0
- package/src/wirings/queue/validate-worker-config.ts +2 -28
- package/src/wirings/role/define-system-role.ts +33 -0
- package/src/wirings/role/index.ts +13 -0
- package/src/wirings/role/role.test.ts +104 -0
- package/src/wirings/role/role.types.ts +47 -0
- package/src/wirings/role/validate-role-definitions.ts +93 -0
- package/src/wirings/rpc/addon-auth-tags.test.ts +223 -0
- package/src/wirings/rpc/addon-runner.ts +0 -56
- package/src/wirings/rpc/addon-scopes.test.ts +225 -0
- package/src/wirings/rpc/remote-addon-auth.ts +9 -16
- package/src/wirings/rpc/rpc-runner.test.ts +192 -6
- package/src/wirings/rpc/rpc-runner.ts +145 -127
- package/src/wirings/rpc/rpc-types.ts +11 -6
- package/src/wirings/rpc/wire-addon.test.ts +43 -1
- package/src/wirings/rpc/wire-addon.ts +99 -0
- package/src/wirings/rpc/wire-remote-addon.ts +9 -29
- package/src/wirings/scheduler/log-schedulers.ts +0 -4
- package/src/wirings/scheduler/scheduler-runner.test.ts +1 -8
- package/src/wirings/scheduler/scheduler-runner.ts +0 -2
- package/src/wirings/scheduler/scheduler.types.ts +1 -14
- package/src/wirings/scope/{wire-scope.ts → define-scope.ts} +5 -6
- package/src/wirings/scope/index.ts +1 -1
- package/src/wirings/scope/scope.test.ts +1 -2
- package/src/wirings/scope/scope.types.ts +7 -9
- package/src/wirings/scope/validate-scope-definitions.ts +3 -21
- package/src/wirings/secret/index.ts +1 -1
- package/src/wirings/secret/secret.types.ts +19 -15
- package/src/wirings/secret/validate-secret-definitions.ts +2 -4
- package/src/wirings/trigger/trigger-runner.ts +1 -27
- package/src/wirings/trigger/trigger.types.ts +1 -82
- package/src/wirings/variable/index.ts +1 -1
- package/src/wirings/variable/validate-variable-definitions.ts +2 -4
- package/src/wirings/variable/variable.types.ts +1 -13
- package/src/wirings/virtual-user/index.ts +88 -0
- package/src/wirings/virtual-user/prepare-virtual-user-run.test.ts +115 -0
- package/src/wirings/virtual-user/prepare-virtual-user-run.ts +95 -0
- package/src/wirings/virtual-user/run-virtual-user.test.ts +765 -0
- package/src/wirings/virtual-user/run-virtual-user.ts +671 -0
- package/src/wirings/virtual-user/virtual-user-agents.test.ts +65 -0
- package/src/wirings/virtual-user/virtual-user-agents.ts +57 -0
- package/src/wirings/virtual-user/virtual-user-catalogue.test.ts +215 -0
- package/src/wirings/virtual-user/virtual-user-catalogue.ts +184 -0
- package/src/wirings/virtual-user/virtual-user-derive.test.ts +398 -0
- package/src/wirings/virtual-user/virtual-user-derive.ts +173 -0
- package/src/wirings/virtual-user/virtual-user-dispositions.test.ts +63 -0
- package/src/wirings/virtual-user/virtual-user-dispositions.ts +213 -0
- package/src/wirings/virtual-user/virtual-user-intents.test.ts +208 -0
- package/src/wirings/virtual-user/virtual-user-intents.ts +185 -0
- package/src/wirings/virtual-user/virtual-user-rng.test.ts +72 -0
- package/src/wirings/virtual-user/virtual-user-rng.ts +50 -0
- package/src/wirings/virtual-user/virtual-user-run-store.ts +98 -0
- package/src/wirings/virtual-user/virtual-user-target.ts +47 -0
- package/src/wirings/virtual-user/virtual-user.types.ts +219 -0
- package/src/wirings/workflow/dsl/workflow-dsl.types.ts +19 -20
- package/src/wirings/workflow/dsl/workflow-runner.ts +0 -4
- package/src/wirings/workflow/feature.ts +0 -19
- package/src/wirings/workflow/graph/graph-node.ts +0 -136
- package/src/wirings/workflow/graph/graph-runner.test.ts +20 -19
- package/src/wirings/workflow/graph/graph-runner.ts +6 -41
- package/src/wirings/workflow/graph/wire-workflow-graph.ts +0 -4
- package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -58
- package/src/wirings/workflow/index.ts +10 -44
- package/src/wirings/workflow/pikku-scenario-service.ts +235 -61
- package/src/wirings/workflow/pikku-workflow-service.test.ts +0 -39
- package/src/wirings/workflow/pikku-workflow-service.ts +77 -674
- package/src/wirings/workflow/run-timeline.test.ts +7 -19
- package/src/wirings/workflow/run-timeline.ts +0 -56
- package/src/wirings/workflow/scenario-cookie-jar.test.ts +0 -1
- package/src/wirings/workflow/scenario-cookie-jar.ts +0 -25
- package/src/wirings/workflow/scenario-expectations.test.ts +2 -7
- package/src/wirings/workflow/scenario-hooks.test.ts +2 -7
- package/src/wirings/workflow/scenario-poll.test.ts +0 -2
- package/src/wirings/workflow/scenario-poll.ts +0 -15
- package/src/wirings/workflow/scenario-prose.test.ts +5 -7
- package/src/wirings/workflow/scenario-prose.ts +1 -29
- package/src/wirings/workflow/scenario-service.test.ts +2 -10
- package/src/wirings/workflow/scenario-step-guards.ts +1 -14
- package/src/wirings/workflow/scenario-step.test.ts +163 -19
- package/src/wirings/workflow/scenario-step.types.ts +94 -12
- package/src/wirings/workflow/scenario-surface.test.ts +146 -0
- package/src/wirings/workflow/scenario-surface.ts +71 -0
- package/src/wirings/workflow/workflow-dispatch-durability.test.ts +14 -15
- package/src/wirings/workflow/workflow-dispatch-payload.test.ts +0 -4
- package/src/wirings/workflow/workflow-inline-authority.test.ts +169 -0
- package/src/wirings/workflow/workflow-invocation-id.test.ts +0 -2
- package/src/wirings/workflow/workflow-invocation-id.ts +2 -22
- package/src/wirings/workflow/workflow-mirror.test.ts +0 -7
- package/src/wirings/workflow/workflow-on-error.test.ts +0 -9
- package/src/wirings/workflow/workflow-queue-workers.ts +0 -21
- package/src/wirings/workflow/workflow-replay-snapshot.test.ts +8 -7
- package/src/wirings/workflow/workflow-retry-policy.test.ts +0 -5
- package/src/wirings/workflow/workflow-run-context.test.ts +5 -10
- package/src/wirings/workflow/workflow-run-polling.test.ts +0 -5
- package/src/wirings/workflow/workflow-step-ordinal.test.ts +19 -4
- package/src/wirings/workflow/workflow-step-session.test.ts +0 -7
- package/src/wirings/workflow/workflow.types.ts +5 -201
- package/tsconfig.tsbuildinfo +1 -1
- package/tsconfig.type-tests.json +12 -0
- package/src/middleware/timeout.ts +0 -22
- package/src/pikku-response.ts +0 -5
- package/src/wirings/mcp/mcp-endpoint-registry.test.d.ts +0 -1
- package/src/wirings/workflow/dsl/index.ts +0 -36
- package/src/wirings/workflow/graph/index.ts +0 -15
package/src/types/state.types.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
PikkuErrorConstructor,
|
|
3
|
+
ErrorDetails,
|
|
4
|
+
} from '../errors/error-handler.js'
|
|
2
5
|
import type {
|
|
3
6
|
CorePikkuFunctionConfig,
|
|
4
7
|
CorePermissionGroup,
|
|
@@ -63,9 +66,6 @@ import type {
|
|
|
63
66
|
} from './core.types.js'
|
|
64
67
|
import type { CorePikkuChannelMiddleware } from '../wirings/channel/channel.types.js'
|
|
65
68
|
|
|
66
|
-
/**
|
|
67
|
-
* State structure for an individual package
|
|
68
|
-
*/
|
|
69
69
|
export interface PikkuPackageState {
|
|
70
70
|
function: {
|
|
71
71
|
meta: FunctionsMeta
|
|
@@ -90,6 +90,8 @@ export interface PikkuPackageState {
|
|
|
90
90
|
rpcEndpoint?: string
|
|
91
91
|
auth?: boolean
|
|
92
92
|
tags?: string[]
|
|
93
|
+
/** Required of every function in this package, on top of the function's own */
|
|
94
|
+
scopes?: string[]
|
|
93
95
|
/** Per-instance name-aliases: logical name the addon reads -> actual project secret name */
|
|
94
96
|
secretOverrides?: Record<string, string>
|
|
95
97
|
/** Per-instance name-aliases: logical name the addon reads -> actual project variable name */
|
|
@@ -172,14 +174,13 @@ export interface PikkuPackageState {
|
|
|
172
174
|
global: (CorePermissionGroup | CorePikkuPermission)[]
|
|
173
175
|
}
|
|
174
176
|
misc: {
|
|
175
|
-
errors: Map<
|
|
177
|
+
errors: Map<PikkuErrorConstructor, ErrorDetails>
|
|
176
178
|
schemas: Map<string, any>
|
|
177
179
|
middleware: Record<string, CorePikkuMiddleware[]>
|
|
178
180
|
channelMiddleware: Record<string, CorePikkuChannelMiddleware[]>
|
|
179
181
|
permissions: Record<string, CorePermissionGroup | CorePikkuPermission[]>
|
|
180
182
|
}
|
|
181
183
|
package: {
|
|
182
|
-
/** Service factory functions for addon packages */
|
|
183
184
|
factories: {
|
|
184
185
|
createConfig?: CreateConfig<CoreConfig>
|
|
185
186
|
createSingletonServices?: CreateSingletonServices<
|
|
@@ -192,19 +193,16 @@ export interface PikkuPackageState {
|
|
|
192
193
|
CoreUserSession
|
|
193
194
|
>
|
|
194
195
|
} | null
|
|
195
|
-
/** Cached singleton services for this package */
|
|
196
196
|
singletonServices: CoreSingletonServices | null
|
|
197
197
|
/** The pikkuBetterAuth factory, self-registered when auth.ts is evaluated.
|
|
198
198
|
* pikkuServices reads it to build and inject the `auth` singleton. */
|
|
199
199
|
authFactory:
|
|
200
200
|
| ((services: CoreSingletonServices) => unknown | Promise<unknown>)
|
|
201
201
|
| null
|
|
202
|
-
/** Credential metadata for this addon package */
|
|
203
202
|
credentialsMeta: Record<
|
|
204
203
|
string,
|
|
205
204
|
{ name: string; displayName: string; type: string; oauth2?: boolean }
|
|
206
205
|
> | null
|
|
207
|
-
/** Services this addon needs from the parent project */
|
|
208
206
|
requiredParentServices: string[] | null
|
|
209
207
|
}
|
|
210
208
|
}
|
package/src/utils/hmac.ts
CHANGED
|
@@ -1,22 +1,16 @@
|
|
|
1
1
|
import { createHmac, timingSafeEqual } from 'node:crypto'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* HMAC-SHA256 a payload, hex-encoded.
|
|
5
|
-
*
|
|
6
|
-
* Senders wrap this in their own scheme prefix (`sha256=`, `v0=`, …).
|
|
7
|
-
*
|
|
8
|
-
* @param secret - The signing key shared with the other side
|
|
9
|
-
* @param payload - The exact bytes that were signed
|
|
4
|
+
* HMAC-SHA256 of a payload, hex-encoded. Senders wrap this in their own scheme
|
|
5
|
+
* prefix (`sha256=`, `v0=`, …).
|
|
10
6
|
*/
|
|
11
7
|
export function hmacSha256Hex(secret: string, payload: string): string {
|
|
12
8
|
return createHmac('sha256', secret).update(payload).digest('hex')
|
|
13
9
|
}
|
|
14
10
|
|
|
15
11
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* Returns false rather than throwing on a length mismatch, which is what
|
|
19
|
-
* `timingSafeEqual` does when the buffers differ in size.
|
|
12
|
+
* Constant-time signature comparison. Returns false on a length mismatch,
|
|
13
|
+
* where `timingSafeEqual` itself throws.
|
|
20
14
|
*/
|
|
21
15
|
export function timingSafeStringEqual(a: string, b: string): boolean {
|
|
22
16
|
try {
|
package/src/utils/safe-fetch.ts
CHANGED
|
@@ -1,20 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* so we cannot resolve hostnames to check for private targets. We reject the
|
|
6
|
-
* obvious internal literals and, crucially, re-validate every redirect hop —
|
|
7
|
-
* a public URL that 302s to `169.254.169.254` is the common bypass. This does
|
|
8
|
-
* NOT defend against a public hostname that itself resolves to a private IP
|
|
9
|
-
* (DNS rebinding), which is out of reach without DNS resolution.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Parse the many textual encodings of an IPv4 address that `fetch`/`undici`
|
|
14
|
-
* (and `inet_aton`-style parsers) accept — a dotted quad whose octets may be
|
|
15
|
-
* decimal, octal (`0177`) or hex (`0x7f`), or the whole address as a single
|
|
16
|
-
* 32-bit integer (decimal `2130706433`, hex `0x7f000001`). Returns the four
|
|
17
|
-
* octets, or `null` when the host is not a numeric IPv4 literal.
|
|
2
|
+
* Parses the textual IPv4 encodings `fetch`/`undici` accept — a dotted quad
|
|
3
|
+
* whose octets may be decimal, octal (`0177`) or hex (`0x7f`), or the whole
|
|
4
|
+
* address as a single 32-bit integer. `null` when not an IPv4 literal.
|
|
18
5
|
*/
|
|
19
6
|
function parseIPv4Octets(
|
|
20
7
|
host: string
|
|
@@ -46,15 +33,9 @@ function parseIPv4Octets(
|
|
|
46
33
|
}
|
|
47
34
|
|
|
48
35
|
/**
|
|
49
|
-
* Whether a hostname is an obvious internal
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* Alias/encoded forms that resolve to the same targets are also rejected: a
|
|
53
|
-
* trailing-dot FQDN (`localhost.`), the `*.localhost` reserved name, IPv4-mapped
|
|
54
|
-
* IPv6 (`::ffff:127.0.0.1`), and octal/decimal/hex-encoded IPv4. This is
|
|
55
|
-
* best-effort literal matching only — it cannot catch a public hostname that
|
|
56
|
-
* *resolves* to a private IP (DNS rebinding), which needs DNS resolution
|
|
57
|
-
* unavailable in edge runtimes.
|
|
36
|
+
* Whether a hostname is an obvious internal target. Best-effort literal
|
|
37
|
+
* matching only: it cannot catch a public hostname that *resolves* to a
|
|
38
|
+
* private IP.
|
|
58
39
|
*/
|
|
59
40
|
export function isPrivateHost(hostname: string): boolean {
|
|
60
41
|
const host = hostname
|
|
@@ -102,11 +83,6 @@ export interface SafeFetchOptions {
|
|
|
102
83
|
maxRedirects?: number
|
|
103
84
|
}
|
|
104
85
|
|
|
105
|
-
/**
|
|
106
|
-
* Parse and validate a URL for outbound fetching: only http(s), and — unless an
|
|
107
|
-
* `allowedHosts` allowlist is supplied — not an obvious private/internal host.
|
|
108
|
-
* Returns the parsed URL or throws.
|
|
109
|
-
*/
|
|
110
86
|
export function assertFetchableUrl(
|
|
111
87
|
url: string,
|
|
112
88
|
options: SafeFetchOptions = {}
|
|
@@ -127,17 +103,9 @@ export function assertFetchableUrl(
|
|
|
127
103
|
return parsed
|
|
128
104
|
}
|
|
129
105
|
|
|
130
|
-
/**
|
|
131
|
-
* The only 3xx statuses that request a redirect be followed. `300` (Multiple
|
|
132
|
-
* Choices), `304` (Not Modified), `305` (Use Proxy) and `306` are returned to
|
|
133
|
-
* the caller as-is rather than followed.
|
|
134
|
-
*/
|
|
106
|
+
/** The only 3xx statuses followed; every other 3xx is returned to the caller. */
|
|
135
107
|
const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308])
|
|
136
108
|
|
|
137
|
-
/**
|
|
138
|
-
* Drop credential-bearing headers (`Authorization`, `Cookie`) so they are not
|
|
139
|
-
* replayed to a different origin across a redirect.
|
|
140
|
-
*/
|
|
141
109
|
function stripCredentialHeaders(init: RequestInit): RequestInit {
|
|
142
110
|
if (!init.headers) return init
|
|
143
111
|
const headers = new Headers(init.headers)
|
|
@@ -147,10 +115,8 @@ function stripCredentialHeaders(init: RequestInit): RequestInit {
|
|
|
147
115
|
}
|
|
148
116
|
|
|
149
117
|
/**
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
* original method and body. When the method changes to `GET` the request body
|
|
153
|
-
* and its `Content-*` headers are dropped.
|
|
118
|
+
* The WHATWG method/body transform for a redirect: `303` (and `301`/`302` on
|
|
119
|
+
* a `POST`) becomes a bodyless `GET`; `307`/`308` preserve method and body.
|
|
154
120
|
*/
|
|
155
121
|
function redirectInit(status: number, init: RequestInit): RequestInit {
|
|
156
122
|
const method = (init.method ?? 'GET').toUpperCase()
|
|
@@ -165,17 +131,10 @@ function redirectInit(status: number, init: RequestInit): RequestInit {
|
|
|
165
131
|
}
|
|
166
132
|
|
|
167
133
|
/**
|
|
168
|
-
* `fetch` with SSRF protection
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
* followed, and the method/body are transformed per {@link redirectInit}. Each
|
|
173
|
-
* intermediate redirect response body is cancelled before the next hop so it is
|
|
174
|
-
* not left dangling. When a redirect cannot or should not be followed (no
|
|
175
|
-
* `Location`, or the hop budget is exhausted) the raw redirect response is
|
|
176
|
-
* returned for the caller to handle by status. Credential headers
|
|
177
|
-
* (`Authorization`, `Cookie`) are stripped whenever a redirect crosses origin,
|
|
178
|
-
* so they never leak to a redirected host.
|
|
134
|
+
* `fetch` with SSRF protection on the initial URL and every redirect hop.
|
|
135
|
+
* When a redirect cannot be followed (no `Location`, or the hop budget is
|
|
136
|
+
* spent) the raw redirect response is returned for the caller to handle by
|
|
137
|
+
* status.
|
|
179
138
|
*/
|
|
180
139
|
export async function safeFetch(
|
|
181
140
|
url: string,
|
package/src/utils.test.ts
CHANGED
|
@@ -34,6 +34,17 @@ describe('createWeakUID', () => {
|
|
|
34
34
|
const uid = createWeakUID()
|
|
35
35
|
assert.ok(uid.includes('-'))
|
|
36
36
|
})
|
|
37
|
+
|
|
38
|
+
test('separate module instances get different prefixes', async () => {
|
|
39
|
+
const [a, b] = await Promise.all([
|
|
40
|
+
import('./utils.js?instance=a'),
|
|
41
|
+
import('./utils.js?instance=b'),
|
|
42
|
+
])
|
|
43
|
+
assert.notStrictEqual(
|
|
44
|
+
a.createWeakUID().split('-')[0],
|
|
45
|
+
b.createWeakUID().split('-')[0]
|
|
46
|
+
)
|
|
47
|
+
})
|
|
37
48
|
})
|
|
38
49
|
|
|
39
50
|
describe('isSerializable', () => {
|
|
@@ -238,7 +249,6 @@ describe('closeWireServices', () => {
|
|
|
238
249
|
}
|
|
239
250
|
|
|
240
251
|
await closeWireServices(mockLogger as any, wireServices as any)
|
|
241
|
-
// Should not throw
|
|
242
252
|
})
|
|
243
253
|
})
|
|
244
254
|
|
|
@@ -295,7 +305,6 @@ describe('stopSingletonServices', () => {
|
|
|
295
305
|
pikkuState(null, 'package', 'singletonServices', mockServices as any)
|
|
296
306
|
|
|
297
307
|
await stopSingletonServices()
|
|
298
|
-
// Should not throw
|
|
299
308
|
})
|
|
300
309
|
|
|
301
310
|
test('should handle errors during stop gracefully', async () => {
|
package/src/utils.ts
CHANGED
|
@@ -23,9 +23,12 @@ export const closeWireServices = async (
|
|
|
23
23
|
)
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
let _uidPrefix: string | undefined
|
|
27
27
|
let _uidCounter = 0
|
|
28
|
-
export const createWeakUID = () =>
|
|
28
|
+
export const createWeakUID = () => {
|
|
29
|
+
_uidPrefix ??= globalThis.crypto.randomUUID().slice(0, 8)
|
|
30
|
+
return `${_uidPrefix}-${++_uidCounter}`
|
|
31
|
+
}
|
|
29
32
|
|
|
30
33
|
export const isSerializable = (data: any): boolean => {
|
|
31
34
|
return !(
|
|
@@ -78,9 +81,6 @@ export const freezeDedupe = <T>(
|
|
|
78
81
|
return Object.freeze(out)
|
|
79
82
|
}
|
|
80
83
|
|
|
81
|
-
/**
|
|
82
|
-
* Stop a single service by calling its stop method if it exists
|
|
83
|
-
*/
|
|
84
84
|
const stopService = async (
|
|
85
85
|
logger: Logger,
|
|
86
86
|
name: string,
|
|
@@ -97,21 +97,14 @@ const stopService = async (
|
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
/**
|
|
101
|
-
* Stop all singleton services, including addon package services.
|
|
102
|
-
* Addon package services are stopped first, then the parent services.
|
|
103
|
-
*
|
|
104
|
-
* @param singletonServices - The parent singleton services to stop
|
|
105
|
-
*/
|
|
100
|
+
/** Stops addon package services first, then the parent singleton services. */
|
|
106
101
|
export const stopSingletonServices = async (): Promise<void> => {
|
|
107
102
|
const singletonServices = getSingletonServices()
|
|
108
103
|
const logger = singletonServices.logger
|
|
109
104
|
|
|
110
|
-
// Stop all addon package singleton services
|
|
111
105
|
const stateMap = getAllPackageStates()
|
|
112
106
|
if (stateMap.size > 0) {
|
|
113
107
|
for (const [packageName, packageState] of stateMap) {
|
|
114
|
-
// Skip main package - we handle it separately
|
|
115
108
|
if (packageName === '__main__') continue
|
|
116
109
|
|
|
117
110
|
const packageServices = packageState.package?.singletonServices
|
|
@@ -120,13 +113,11 @@ export const stopSingletonServices = async (): Promise<void> => {
|
|
|
120
113
|
for (const [name, service] of Object.entries(packageServices)) {
|
|
121
114
|
await stopService(logger, `${packageName}/${name}`, service)
|
|
122
115
|
}
|
|
123
|
-
// Clear the cached services
|
|
124
116
|
packageState.package.singletonServices = null
|
|
125
117
|
}
|
|
126
118
|
}
|
|
127
119
|
}
|
|
128
120
|
|
|
129
|
-
// Then stop the parent singleton services
|
|
130
121
|
for (const [name, service] of Object.entries(singletonServices)) {
|
|
131
122
|
await stopService(logger, name, service)
|
|
132
123
|
}
|
|
@@ -1,47 +1,22 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* How an actor agent answers the target agent's tool-approval requests during
|
|
3
|
-
* a conversation.
|
|
4
|
-
* - `'in-persona'` — the actor agent decides as the persona would (default).
|
|
5
|
-
* - `'always'` — approve every request (stress the happy path).
|
|
6
|
-
* - `'never'` — deny every request (exercise refusal handling).
|
|
7
|
-
*/
|
|
8
1
|
export type ActorFlowApprovalPolicy = 'in-persona' | 'always' | 'never'
|
|
9
2
|
|
|
10
|
-
/**
|
|
11
|
-
* Options for `actor.converse(...)` — a dynamic conversation an actor holds
|
|
12
|
-
* with a target Pikku AI agent, in the actor's own persona. `TAgentName` is
|
|
13
|
-
* bound to the generated union of agent names in a typed project.
|
|
14
|
-
*/
|
|
15
3
|
export interface ConverseOptions<TAgentName extends string = string> {
|
|
16
|
-
/** Target Pikku AI agent name to converse with. */
|
|
17
4
|
agent: TAgentName
|
|
18
5
|
/** What the actor is trying to get the agent to accomplish. */
|
|
19
6
|
task: string
|
|
20
|
-
/** Natural-language success criterion the actor
|
|
7
|
+
/** Natural-language success criterion the actor judges the conversation against. */
|
|
21
8
|
evaluate: string
|
|
22
|
-
/** How the actor answers the agent's tool-approval requests. Default `'in-persona'`. */
|
|
23
9
|
approvals?: ActorFlowApprovalPolicy
|
|
24
|
-
/** Model the actor uses for its own turns/decisions. Falls back to the actor service default. */
|
|
25
10
|
model?: string
|
|
26
|
-
/** Hard cap on conversation turns before forcing evaluation. Default 12. */
|
|
27
11
|
maxTurns?: number
|
|
28
12
|
}
|
|
29
13
|
|
|
30
|
-
/**
|
|
31
|
-
* The verdict a conversation produces: the persona's LLM self-evaluation of
|
|
32
|
-
* whether the task was met. Deterministic checks are the caller's job — they
|
|
33
|
-
* already hold the actor and can `actor.invoke(...)` afterwards.
|
|
34
|
-
*/
|
|
35
14
|
export interface ActorFlowVerdict {
|
|
36
|
-
/** Whether the actor judged the task accomplished. */
|
|
37
15
|
passed: boolean
|
|
38
|
-
/** The actor's reasoning for its verdict. */
|
|
39
16
|
reasoning: string
|
|
40
|
-
/** The conversation transcript, for debugging/reporting. */
|
|
41
17
|
transcript: string[]
|
|
42
18
|
}
|
|
43
19
|
|
|
44
|
-
/** A pending tool-approval request surfaced by the target agent. */
|
|
45
20
|
export interface TargetPendingApproval {
|
|
46
21
|
toolCallId: string
|
|
47
22
|
toolName: string
|
|
@@ -49,7 +24,6 @@ export interface TargetPendingApproval {
|
|
|
49
24
|
reason?: string
|
|
50
25
|
}
|
|
51
26
|
|
|
52
|
-
/** A normalized reply from the target agent, independent of transport. */
|
|
53
27
|
export interface TargetAgentReply {
|
|
54
28
|
text: string
|
|
55
29
|
runId: string
|
|
@@ -57,15 +31,8 @@ export interface TargetAgentReply {
|
|
|
57
31
|
pendingApprovals?: TargetPendingApproval[]
|
|
58
32
|
}
|
|
59
33
|
|
|
60
|
-
/**
|
|
61
|
-
* Drives the target agent. In production this is HTTP-backed (the actor's
|
|
62
|
-
* `agentRun` / `agentApprove` calls as the signed-in actor); the conversation
|
|
63
|
-
* engine only sees this transport-agnostic contract.
|
|
64
|
-
*/
|
|
65
34
|
export interface TargetAgentDriver {
|
|
66
|
-
/** Send a message, starting or continuing the target agent's run. */
|
|
67
35
|
run(message: string): Promise<TargetAgentReply>
|
|
68
|
-
/** Answer the target agent's pending approvals and continue its run. */
|
|
69
36
|
approve(
|
|
70
37
|
runId: string,
|
|
71
38
|
decisions: { toolCallId: string; approved: boolean }[]
|
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Actor flow module exports.
|
|
3
|
-
*
|
|
4
|
-
* An actor holds a dynamic conversation with a target Pikku AI agent via
|
|
5
|
-
* `actor.converse(...)` — playing its own persona, approving the agent's tool
|
|
6
|
-
* requests in-persona, and evaluating whether the task was accomplished. The
|
|
7
|
-
* conversation engine here is transport-agnostic; the actor drives the target
|
|
8
|
-
* over HTTP.
|
|
9
|
-
*/
|
|
10
1
|
export type {
|
|
11
2
|
ActorFlowApprovalPolicy,
|
|
12
3
|
ActorFlowVerdict,
|
|
@@ -18,7 +18,6 @@ const stepResult = (object: unknown): AIAgentStepResult => ({
|
|
|
18
18
|
finishReason: 'stop',
|
|
19
19
|
})
|
|
20
20
|
|
|
21
|
-
/** A persona LLM scripted by the outputSchema it's asked for. */
|
|
22
21
|
const scriptedLLM = (script: {
|
|
23
22
|
turns: Array<{ message: string; done: boolean }>
|
|
24
23
|
decisions: Array<{ toolCallId: string; approved: boolean }>
|
|
@@ -31,7 +30,6 @@ const scriptedLLM = (script: {
|
|
|
31
30
|
(params.outputSchema as { properties?: Record<string, unknown> })
|
|
32
31
|
?.properties ?? {}
|
|
33
32
|
if ('message' in props) {
|
|
34
|
-
// Providers reject an empty prompt — every persona turn must carry messages.
|
|
35
33
|
assert.ok(
|
|
36
34
|
params.messages.length > 0,
|
|
37
35
|
'persona turn requested with empty messages'
|
|
@@ -54,7 +52,6 @@ const scriptedLLM = (script: {
|
|
|
54
52
|
return { llm, calls }
|
|
55
53
|
}
|
|
56
54
|
|
|
57
|
-
/** A target that suspends once for approval, then completes. */
|
|
58
55
|
const suspendingTarget = (): {
|
|
59
56
|
target: TargetAgentDriver
|
|
60
57
|
approvedWith: Array<{ toolCallId: string; approved: boolean }[]>
|
|
@@ -84,7 +81,6 @@ const suspendingTarget = (): {
|
|
|
84
81
|
return { target, approvedWith }
|
|
85
82
|
}
|
|
86
83
|
|
|
87
|
-
/** A target that never completes — always re-suspends for the same approval. */
|
|
88
84
|
const alwaysSuspendingTarget = (): {
|
|
89
85
|
target: TargetAgentDriver
|
|
90
86
|
approveCalls: () => number
|
|
@@ -109,8 +105,17 @@ const alwaysSuspendingTarget = (): {
|
|
|
109
105
|
}
|
|
110
106
|
|
|
111
107
|
const base = {
|
|
112
|
-
|
|
113
|
-
|
|
108
|
+
persona: {
|
|
109
|
+
id: 'priya',
|
|
110
|
+
email: 'priya@personas.local',
|
|
111
|
+
name: 'Priya',
|
|
112
|
+
personality: 'concise',
|
|
113
|
+
roles: [],
|
|
114
|
+
goals: [],
|
|
115
|
+
tags: [],
|
|
116
|
+
runnable: true,
|
|
117
|
+
},
|
|
118
|
+
personaId: 'priya',
|
|
114
119
|
agentName: 'todoBot',
|
|
115
120
|
task: 'Get a todo created',
|
|
116
121
|
evaluate: 'A todo now exists',
|
|
@@ -4,7 +4,7 @@ import type {
|
|
|
4
4
|
TargetAgentDriver,
|
|
5
5
|
TargetPendingApproval,
|
|
6
6
|
} from './actor-flow.types.js'
|
|
7
|
-
import type {
|
|
7
|
+
import type { ResolvedPersona } from '../../services/personas-service.js'
|
|
8
8
|
import type { AIMessage } from '../ai-agent/ai-agent.types.js'
|
|
9
9
|
import type {
|
|
10
10
|
AIAgentRunnerParams,
|
|
@@ -61,10 +61,10 @@ export type ActorLLM = (
|
|
|
61
61
|
) => Promise<AIAgentStepResult>
|
|
62
62
|
|
|
63
63
|
export interface RunConversationParams {
|
|
64
|
-
/** The
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
|
|
64
|
+
/** The person being played — name, job title, personality. */
|
|
65
|
+
persona: ResolvedPersona
|
|
66
|
+
/** The id they were declared under (for transcript labelling). */
|
|
67
|
+
personaId: string
|
|
68
68
|
/** What the actor is trying to get the target agent to accomplish. */
|
|
69
69
|
task: string
|
|
70
70
|
/** Natural-language success criterion the actor evaluates at the end. */
|
|
@@ -109,16 +109,23 @@ function readObject<T>(result: { object?: unknown; text?: string }): T | null {
|
|
|
109
109
|
return null
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
function actorInstructions(
|
|
112
|
+
function actorInstructions(persona: ResolvedPersona, task: string): string {
|
|
113
113
|
return [
|
|
114
114
|
`You are role-playing a real user interacting with an AI assistant. Stay in character at all times — you are the user, not the assistant.`,
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
? `Your personality and communication style: ${
|
|
115
|
+
`Your name is ${persona.name}.`,
|
|
116
|
+
persona.jobTitle ? `Your role: ${persona.jobTitle}.` : '',
|
|
117
|
+
persona.personality
|
|
118
|
+
? `Your personality and communication style: ${persona.personality}. Match this tone, vocabulary, and level of detail exactly.`
|
|
119
119
|
: '',
|
|
120
120
|
`Your goal in this conversation: ${task}.`,
|
|
121
121
|
`Send one message at a time. Set "done" to true only once your goal is clearly accomplished, or clearly impossible.`,
|
|
122
|
+
// Every call the actor makes wants a schema'd object back, and a gateway
|
|
123
|
+
// that cannot take a JSON *schema* degrades to OpenAI's `json_object`
|
|
124
|
+
// mode — which refuses the request outright unless the word "json" appears
|
|
125
|
+
// somewhere in the prompt. Saying it once here covers all three call sites
|
|
126
|
+
// (turn, approvals, verdict), since each builds on these instructions, and
|
|
127
|
+
// it costs nothing on providers that never needed telling.
|
|
128
|
+
`Reply with json matching the schema you are given, and nothing else.`,
|
|
122
129
|
]
|
|
123
130
|
.filter(Boolean)
|
|
124
131
|
.join('\n')
|
|
@@ -215,7 +222,7 @@ export async function runConversation(
|
|
|
215
222
|
params: RunConversationParams
|
|
216
223
|
): Promise<ActorFlowVerdict> {
|
|
217
224
|
const maxTurns = params.maxTurns ?? DEFAULT_MAX_TURNS
|
|
218
|
-
const instructions = actorInstructions(params.
|
|
225
|
+
const instructions = actorInstructions(params.persona, params.task)
|
|
219
226
|
// Seed a kickoff so the very first actor turn has a non-empty message list
|
|
220
227
|
// (providers reject an empty prompt). It's an instruction TO the actor, so
|
|
221
228
|
// it never appears in the transcript.
|
|
@@ -245,7 +252,7 @@ export async function runConversation(
|
|
|
245
252
|
}
|
|
246
253
|
|
|
247
254
|
actorMessages.push(msg('assistant', actorMessage))
|
|
248
|
-
transcript.push(`${params.
|
|
255
|
+
transcript.push(`${params.persona.name}: ${actorMessage}`)
|
|
249
256
|
|
|
250
257
|
const reply = await converseWithTarget(params, instructions, actorMessage)
|
|
251
258
|
actorMessages.push(msg('user', reply.text ?? ''))
|
|
@@ -562,8 +562,8 @@ describe('wrapChannelWithAGUI — Pikku CUSTOM events', () => {
|
|
|
562
562
|
})
|
|
563
563
|
})
|
|
564
564
|
|
|
565
|
-
describe('wrapChannelWithAGUI —
|
|
566
|
-
it('
|
|
565
|
+
describe('wrapChannelWithAGUI — speech', () => {
|
|
566
|
+
it('forwards audio-delta as a CUSTOM event', () => {
|
|
567
567
|
const { channel, events } = makeChannel()
|
|
568
568
|
const wrapped = wrapChannelWithAGUI(channel)
|
|
569
569
|
|
|
@@ -573,16 +573,57 @@ describe('wrapChannelWithAGUI — silently dropped events', () => {
|
|
|
573
573
|
format: 'mp3',
|
|
574
574
|
} as AIStreamEvent)
|
|
575
575
|
|
|
576
|
-
|
|
576
|
+
// AG-UI has no speech event, but dropping it makes a voice agent reached
|
|
577
|
+
// over HTTP inaudible: every sentence is synthesized and billed, then
|
|
578
|
+
// thrown away here.
|
|
579
|
+
const custom = find(events, 'CUSTOM', 'pikku:audio-delta')
|
|
580
|
+
assert.ok(custom)
|
|
581
|
+
assert.deepEqual(custom.value, { data: 'base64abc', format: 'mp3' })
|
|
577
582
|
})
|
|
578
583
|
|
|
579
|
-
it('
|
|
584
|
+
it('forwards audio-done as a CUSTOM event', () => {
|
|
580
585
|
const { channel, events } = makeChannel()
|
|
581
586
|
const wrapped = wrapChannelWithAGUI(channel)
|
|
582
587
|
|
|
583
588
|
wrapped.send({ type: 'audio-done' } as AIStreamEvent)
|
|
584
589
|
|
|
585
|
-
assert.
|
|
590
|
+
assert.ok(find(events, 'CUSTOM', 'pikku:audio-done'))
|
|
591
|
+
})
|
|
592
|
+
|
|
593
|
+
it('forwards the transcript as a CUSTOM event', () => {
|
|
594
|
+
const { channel, events } = makeChannel()
|
|
595
|
+
const wrapped = wrapChannelWithAGUI(channel)
|
|
596
|
+
|
|
597
|
+
wrapped.send({
|
|
598
|
+
type: 'transcript',
|
|
599
|
+
text: 'what the user said',
|
|
600
|
+
} as AIStreamEvent)
|
|
601
|
+
|
|
602
|
+
// The client sent audio, so this is the only way it learns what its own
|
|
603
|
+
// turn was. Dropped, the user's message renders as an empty bubble.
|
|
604
|
+
const custom = find(events, 'CUSTOM', 'pikku:transcript')
|
|
605
|
+
assert.ok(custom)
|
|
606
|
+
assert.deepEqual(custom.value, { text: 'what the user said' })
|
|
607
|
+
})
|
|
608
|
+
|
|
609
|
+
it('leaves an open text message open, so speech cannot split a reply', () => {
|
|
610
|
+
const { channel, events } = makeChannel()
|
|
611
|
+
const wrapped = wrapChannelWithAGUI(channel)
|
|
612
|
+
|
|
613
|
+
wrapped.send({ type: 'text-delta', text: 'hello' } as AIStreamEvent)
|
|
614
|
+
wrapped.send({
|
|
615
|
+
type: 'audio-delta',
|
|
616
|
+
data: 'abc',
|
|
617
|
+
format: 'mp3',
|
|
618
|
+
} as AIStreamEvent)
|
|
619
|
+
wrapped.send({ type: 'text-delta', text: ' there' } as AIStreamEvent)
|
|
620
|
+
|
|
621
|
+
// Audio arrives interleaved with the text it is saying. Ending the message
|
|
622
|
+
// around it would render one reply as several.
|
|
623
|
+
const starts = events.filter(
|
|
624
|
+
(event: any) => event.type === 'TEXT_MESSAGE_START'
|
|
625
|
+
)
|
|
626
|
+
assert.equal(starts.length, 1)
|
|
586
627
|
})
|
|
587
628
|
})
|
|
588
629
|
|
|
@@ -642,11 +683,6 @@ describe('wrapChannelWithAGUI — channel proxy', () => {
|
|
|
642
683
|
})
|
|
643
684
|
})
|
|
644
685
|
|
|
645
|
-
/**
|
|
646
|
-
* Replicates the ordering rules enforced by @ag-ui/client's verifyEvents so
|
|
647
|
-
* the bridge's output is checked against the same contract the browser
|
|
648
|
-
* applies. Throws on the first violation.
|
|
649
|
-
*/
|
|
650
686
|
function assertClientAcceptsStream(events: any[]): void {
|
|
651
687
|
let started = false
|
|
652
688
|
let finished = false
|
|
@@ -1109,3 +1145,48 @@ describe('wrapChannelWithAGUI — late-bound runId', () => {
|
|
|
1109
1145
|
assert.equal(started.runId, find(fallback.events, 'RUN_FINISHED').runId)
|
|
1110
1146
|
})
|
|
1111
1147
|
})
|
|
1148
|
+
|
|
1149
|
+
describe('wrapChannelWithAGUI — interruption', () => {
|
|
1150
|
+
it('closes the open text message and forwards the fragment as a custom event', () => {
|
|
1151
|
+
const { channel, events } = makeChannel()
|
|
1152
|
+
const wrapped = wrapChannelWithAGUI(channel, { threadId: 't', runId: 'r' })
|
|
1153
|
+
|
|
1154
|
+
wrapped.send({
|
|
1155
|
+
type: 'text-delta',
|
|
1156
|
+
text: 'I will delete the ',
|
|
1157
|
+
} as AIStreamEvent)
|
|
1158
|
+
wrapped.send({
|
|
1159
|
+
type: 'interrupted',
|
|
1160
|
+
runId: 'r',
|
|
1161
|
+
text: 'I will delete the ',
|
|
1162
|
+
reason: 'speech',
|
|
1163
|
+
} as AIStreamEvent)
|
|
1164
|
+
|
|
1165
|
+
// Leaving TEXT_MESSAGE_END unsent would strand the assistant bubble in a
|
|
1166
|
+
// streaming state that never resolves.
|
|
1167
|
+
assert.ok(types(events).includes('TEXT_MESSAGE_END'))
|
|
1168
|
+
const custom = find(events, 'CUSTOM', 'pikku:interrupted')
|
|
1169
|
+
assert.deepEqual(custom.value, {
|
|
1170
|
+
runId: 'r',
|
|
1171
|
+
text: 'I will delete the ',
|
|
1172
|
+
reason: 'speech',
|
|
1173
|
+
})
|
|
1174
|
+
})
|
|
1175
|
+
|
|
1176
|
+
it('still ends the run exactly once, so an interrupted run is not terminal on its own', () => {
|
|
1177
|
+
const { channel, events } = makeChannel()
|
|
1178
|
+
const wrapped = wrapChannelWithAGUI(channel, { threadId: 't', runId: 'r' })
|
|
1179
|
+
|
|
1180
|
+
wrapped.send({ type: 'text-delta', text: 'partial' } as AIStreamEvent)
|
|
1181
|
+
wrapped.send({
|
|
1182
|
+
type: 'interrupted',
|
|
1183
|
+
runId: 'r',
|
|
1184
|
+
text: 'partial',
|
|
1185
|
+
reason: 'speech',
|
|
1186
|
+
} as AIStreamEvent)
|
|
1187
|
+
wrapped.send({ type: 'done' } as AIStreamEvent)
|
|
1188
|
+
|
|
1189
|
+
assert.equal(events.filter((e: any) => e.type === 'RUN_FINISHED').length, 1)
|
|
1190
|
+
assert.equal(events.filter((e: any) => e.type === 'RUN_ERROR').length, 0)
|
|
1191
|
+
})
|
|
1192
|
+
})
|