@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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { pikkuAIMiddleware } from '../../types/core.types.js';
|
|
2
|
+
import { SPOKEN_TURN } from './voice-input.js';
|
|
2
3
|
function bufferToBase64(data) {
|
|
3
4
|
let binary = '';
|
|
4
5
|
for (let i = 0; i < data.length; i++) {
|
|
@@ -10,6 +11,76 @@ const SENTENCE_BOUNDARY = /[.!?]\s*$/;
|
|
|
10
11
|
function isSentenceBoundary(text) {
|
|
11
12
|
return SENTENCE_BOUNDARY.test(text);
|
|
12
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Scripts a speech model can pronounce, as named by {@link voiceOutput}'s
|
|
16
|
+
* `speakableScripts`.
|
|
17
|
+
*
|
|
18
|
+
* Script rather than language because script is what is decidable from the text
|
|
19
|
+
* alone. Spanish, French and English are one test, not three — and the models
|
|
20
|
+
* that handle one Latin-script language generally handle the others. What a
|
|
21
|
+
* model cannot do is invent a phoneme set it was never given.
|
|
22
|
+
*/
|
|
23
|
+
const SCRIPT_RANGES = {
|
|
24
|
+
latin: /[A-ɏ]/,
|
|
25
|
+
devanagari: /[ऀ-ॿ]/,
|
|
26
|
+
han: /[㐀-鿿]/,
|
|
27
|
+
kana: /[-ヿ]/,
|
|
28
|
+
arabic: /[-ۿݐ-ݿ]/,
|
|
29
|
+
cyrillic: /[Ѐ-ӿ]/,
|
|
30
|
+
hangul: /[가-ᄀ-ᇿ]/,
|
|
31
|
+
hebrew: /[-]/,
|
|
32
|
+
greek: /[Ͱ-Ͽ]/,
|
|
33
|
+
thai: /[-]/,
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Which script decides the voice when a sentence contains several.
|
|
37
|
+
*
|
|
38
|
+
* The ordering is by how much a script narrows down the language, not by
|
|
39
|
+
* preference. Kana appears only in Japanese, so a sentence holding any settles
|
|
40
|
+
* it — while Han is written in both Chinese and Japanese and so cannot, which
|
|
41
|
+
* matters because ordinary Japanese is mostly kanji. Latin comes last for the
|
|
42
|
+
* same reason from the other end: it turns up inside sentences in every other
|
|
43
|
+
* script, and it is the one whose voice is least often the one that counts. A
|
|
44
|
+
* Chinese voice reading an English word is accented; an English voice reading
|
|
45
|
+
* Chinese spells it out.
|
|
46
|
+
*
|
|
47
|
+
* Everything else — Han included — sits between the two in config order.
|
|
48
|
+
*/
|
|
49
|
+
const SCRIPT_PRECEDENCE = { kana: -1, latin: 1 };
|
|
50
|
+
const scriptRank = (name) => SCRIPT_PRECEDENCE[name] ?? 0;
|
|
51
|
+
const scriptNames = (speakable) => Array.isArray(speakable) ? speakable : Object.keys(speakable);
|
|
52
|
+
/**
|
|
53
|
+
* The scripts present in `text` that the model was not said to handle.
|
|
54
|
+
*
|
|
55
|
+
* Silence would be the wrong answer here and so would a best effort. Handed
|
|
56
|
+
* Arabic — which it has no voice for at all — Kokoro does not fail and does not
|
|
57
|
+
* stay quiet: it reads out the *letter names*, twenty-four seconds of "Arabic
|
|
58
|
+
* meem, Arabic ra" for a one-line sentence, which is worse than either. Naming
|
|
59
|
+
* the gap lets the caller say so instead.
|
|
60
|
+
*/
|
|
61
|
+
export const unspeakableScripts = (text, speakable) => {
|
|
62
|
+
const allowed = new Set(scriptNames(speakable));
|
|
63
|
+
return Object.entries(SCRIPT_RANGES)
|
|
64
|
+
.filter(([name, range]) => !allowed.has(name) && range.test(text))
|
|
65
|
+
.map(([name]) => name);
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* The voice to speak `text` in, or `fallback` if no mapped script appears.
|
|
69
|
+
*
|
|
70
|
+
* A sentence is regularly in more than one script, so which one decides is
|
|
71
|
+
* settled by {@link SCRIPT_PRECEDENCE} rather than by the order the config
|
|
72
|
+
* happens to be written in.
|
|
73
|
+
*/
|
|
74
|
+
export const voiceForText = (text, speakable, fallback) => {
|
|
75
|
+
if (Array.isArray(speakable))
|
|
76
|
+
return fallback;
|
|
77
|
+
const mapped = Object.entries(speakable).sort(([a], [b]) => scriptRank(a) - scriptRank(b));
|
|
78
|
+
for (const [name, voice] of mapped) {
|
|
79
|
+
if (SCRIPT_RANGES[name]?.test(text))
|
|
80
|
+
return voice;
|
|
81
|
+
}
|
|
82
|
+
return fallback;
|
|
83
|
+
};
|
|
13
84
|
async function synthesizeAudio(aiAgentRunner, input) {
|
|
14
85
|
const result = await aiAgentRunner.generateSpeech?.({
|
|
15
86
|
model: input.model,
|
|
@@ -19,76 +90,117 @@ async function synthesizeAudio(aiAgentRunner, input) {
|
|
|
19
90
|
instructions: input.instructions,
|
|
20
91
|
speed: input.speed,
|
|
21
92
|
language: input.language,
|
|
93
|
+
abortSignal: input.abortSignal,
|
|
22
94
|
});
|
|
23
95
|
if (!result) {
|
|
24
96
|
throw new Error('voiceOutput requires an aiAgentRunner with generateSpeech support');
|
|
25
97
|
}
|
|
26
|
-
// Label chunks with the format the provider actually returned (config.format
|
|
27
|
-
// is only a request), falling back to the requested format then pcm16.
|
|
28
98
|
return {
|
|
29
99
|
bytes: result.audio.uint8Array,
|
|
30
100
|
format: result.audio.format || input.format || 'pcm16',
|
|
31
101
|
};
|
|
32
102
|
}
|
|
33
103
|
export const voiceOutput = (config) => pikkuAIMiddleware({
|
|
34
|
-
modifyOutputStream: async (services, { event, state }) => {
|
|
35
|
-
const aiAgentRunner = services
|
|
104
|
+
modifyOutputStream: async (services, { event, state, shared, emit, signal }) => {
|
|
105
|
+
const { aiAgentRunner, logger } = services;
|
|
36
106
|
if (!aiAgentRunner?.generateSpeech)
|
|
37
107
|
return event;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
108
|
+
// Only an explicit `false` silences the reply. `voiceInput` sets this on
|
|
109
|
+
// every turn it handles, so `false` means a real user really typed; the
|
|
110
|
+
// key being absent means nothing reported either way — no voice input is
|
|
111
|
+
// wired — and that caller's replies are spoken exactly as they were before
|
|
112
|
+
// this option existed.
|
|
113
|
+
if (!config?.always && shared[SPOKEN_TURN] === false)
|
|
114
|
+
return event;
|
|
115
|
+
/**
|
|
116
|
+
* Queue a finished sentence for speech.
|
|
117
|
+
*
|
|
118
|
+
* Nothing here is awaited by the caller. Synthesis is kicked off at once
|
|
119
|
+
* and its emission is chained behind the previous sentence, which is
|
|
120
|
+
* what keeps the text flowing at the speed the model writes it instead
|
|
121
|
+
* of the speed the speech provider answers.
|
|
122
|
+
*/
|
|
123
|
+
const speak = (text) => {
|
|
124
|
+
if (!config?.model) {
|
|
125
|
+
throw new Error('voiceOutput requires a speech model (e.g. openai/tts-1)');
|
|
126
|
+
}
|
|
127
|
+
// Checked per sentence but announced once per reply: a bilingual answer
|
|
128
|
+
// should still speak the half it can, and repeating the notice for
|
|
129
|
+
// every sentence of a long one would bury the reply itself.
|
|
130
|
+
//
|
|
131
|
+
// Per sentence is also what makes the voice right. A reply that answers
|
|
132
|
+
// in English and then quotes a Chinese title is two sentences in two
|
|
133
|
+
// scripts, and each is synthesized in the voice its own script needs.
|
|
134
|
+
let voice = config.voice;
|
|
135
|
+
if (config.speakableScripts) {
|
|
136
|
+
const unspeakable = unspeakableScripts(text, config.speakableScripts);
|
|
137
|
+
voice = voiceForText(text, config.speakableScripts, config.voice);
|
|
138
|
+
if (unspeakable.length > 0) {
|
|
139
|
+
if (!state.reportedUnspeakable) {
|
|
140
|
+
state.reportedUnspeakable = true;
|
|
141
|
+
state.tail = (state.tail ?? Promise.resolve()).then(() => emit({
|
|
142
|
+
type: 'data',
|
|
143
|
+
name: 'voice-unsupported',
|
|
144
|
+
data: { model: config.model, scripts: unspeakable },
|
|
145
|
+
}));
|
|
146
|
+
}
|
|
147
|
+
return;
|
|
44
148
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
149
|
+
}
|
|
150
|
+
// Settled into a value rather than left as a rejectable promise: it
|
|
151
|
+
// sits unobserved until the chain reaches it, and an unhandled
|
|
152
|
+
// rejection in that window would take the process down.
|
|
153
|
+
const synthesis = synthesizeAudio(aiAgentRunner, {
|
|
154
|
+
model: config.model,
|
|
155
|
+
text,
|
|
156
|
+
voice,
|
|
157
|
+
format: config?.format,
|
|
158
|
+
instructions: config?.instructions,
|
|
159
|
+
speed: config?.speed,
|
|
160
|
+
language: config?.language,
|
|
161
|
+
// Barge-in should stop the bill, not just the playback. Without this
|
|
162
|
+
// every sentence already in flight is synthesized in full and paid
|
|
163
|
+
// for after the user has stopped listening.
|
|
164
|
+
abortSignal: signal,
|
|
165
|
+
}).then((audio) => ({ ok: true, audio }), (error) => ({ ok: false, error }));
|
|
166
|
+
state.tail = (state.tail ?? Promise.resolve()).then(async () => {
|
|
167
|
+
const result = await synthesis;
|
|
168
|
+
if (!result.ok) {
|
|
169
|
+
// One sentence going unspoken is better than the rest of the reply
|
|
170
|
+
// never arriving, so the chain carries on.
|
|
171
|
+
logger?.error(`voiceOutput could not synthesize a sentence: ${String(result.error)}`);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
await emit({
|
|
175
|
+
type: 'audio-delta',
|
|
176
|
+
data: bufferToBase64(result.audio.bytes),
|
|
177
|
+
format: result.audio.format,
|
|
178
|
+
text,
|
|
53
179
|
});
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
event,
|
|
62
|
-
];
|
|
180
|
+
});
|
|
181
|
+
};
|
|
182
|
+
if (event.type === 'done') {
|
|
183
|
+
const remaining = state.textBuffer ?? '';
|
|
184
|
+
state.textBuffer = '';
|
|
185
|
+
if (remaining.trim()) {
|
|
186
|
+
speak(remaining);
|
|
63
187
|
}
|
|
188
|
+
// The only place this hook waits. The reply is already over, so the
|
|
189
|
+
// wait costs the reader nothing, and it is what makes `audio-done`
|
|
190
|
+
// mean what it says rather than racing the last chunk.
|
|
191
|
+
await state.tail;
|
|
192
|
+
state.tail = undefined;
|
|
64
193
|
return [{ type: 'audio-done' }, event];
|
|
65
194
|
}
|
|
66
195
|
if (event.type !== 'text-delta')
|
|
67
196
|
return event;
|
|
68
197
|
state.textBuffer = `${state.textBuffer ?? ''}${event.text}`;
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (!config?.model) {
|
|
74
|
-
throw new Error('voiceOutput requires a speech model (e.g. openai/tts-1)');
|
|
198
|
+
if (isSentenceBoundary(state.textBuffer)) {
|
|
199
|
+
const text = state.textBuffer;
|
|
200
|
+
state.textBuffer = '';
|
|
201
|
+
speak(text);
|
|
75
202
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
text,
|
|
79
|
-
voice: config?.voice,
|
|
80
|
-
format: config?.format,
|
|
81
|
-
instructions: config?.instructions,
|
|
82
|
-
speed: config?.speed,
|
|
83
|
-
language: config?.language,
|
|
84
|
-
});
|
|
85
|
-
return [
|
|
86
|
-
event,
|
|
87
|
-
{
|
|
88
|
-
type: 'audio-delta',
|
|
89
|
-
data: bufferToBase64(audio.bytes),
|
|
90
|
-
format: audio.format,
|
|
91
|
-
},
|
|
92
|
-
];
|
|
203
|
+
// Returned without waiting for any audio — the entire point.
|
|
204
|
+
return event;
|
|
93
205
|
},
|
|
94
206
|
});
|
|
@@ -1,25 +1,7 @@
|
|
|
1
1
|
import type { CoreSingletonServices, MiddlewareMetadata } from '../../types/core.types.js';
|
|
2
2
|
import type { CoreChannel, ChannelMessageMeta } from './channel.types.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
*
|
|
6
|
-
* This function:
|
|
7
|
-
* 1. Extracts inline middleware from the lifecycle config if present
|
|
8
|
-
* 2. Combines metadata middleware with inline middleware using combineMiddleware()
|
|
9
|
-
* 3. Wraps the channel with channel middleware if present
|
|
10
|
-
* 4. Runs the lifecycle function with middleware support
|
|
11
|
-
*
|
|
12
|
-
* @param channelConfig - The channel configuration
|
|
13
|
-
* @param meta - Metadata for the lifecycle function (connect or disconnect)
|
|
14
|
-
* @param lifecycleConfig - The onConnect or onDisconnect config (can be function or object with middleware)
|
|
15
|
-
* @param lifecycleType - Type of lifecycle for cache key ('connect' or 'disconnect')
|
|
16
|
-
* @param services - All services (singleton + session)
|
|
17
|
-
* @param channel - The channel instance
|
|
18
|
-
* @param data - Optional data to pass to the lifecycle function (for onConnect)
|
|
19
|
-
* @param channelMiddlewareMeta - Optional channel middleware metadata for wrapping channel.send()
|
|
20
|
-
* @returns Promise<unknown> - Result from the lifecycle function (if any)
|
|
21
|
-
*/
|
|
22
|
-
export declare const runChannelLifecycleWithMiddleware: ({ channelConfig, meta, lifecycleConfig, lifecycleType, services, channel, data, channelMiddlewareMeta, }: {
|
|
3
|
+
import { type PikkuSessionService } from '../../services/user-session-service.js';
|
|
4
|
+
export declare const runChannelLifecycleWithMiddleware: ({ channelConfig, meta, lifecycleConfig, lifecycleType, services, channel, data, channelMiddlewareMeta, userSession, }: {
|
|
23
5
|
channelConfig: CoreChannel<unknown, any>;
|
|
24
6
|
meta: ChannelMessageMeta;
|
|
25
7
|
lifecycleConfig: any;
|
|
@@ -28,4 +10,9 @@ export declare const runChannelLifecycleWithMiddleware: ({ channelConfig, meta,
|
|
|
28
10
|
channel: any;
|
|
29
11
|
data?: unknown;
|
|
30
12
|
channelMiddlewareMeta?: MiddlewareMetadata[];
|
|
13
|
+
/**
|
|
14
|
+
* Established while the socket was upgrading, so `onConnect` can tell who
|
|
15
|
+
* just connected.
|
|
16
|
+
*/
|
|
17
|
+
userSession?: PikkuSessionService<any>;
|
|
31
18
|
}) => Promise<unknown>;
|
|
@@ -1,26 +1,8 @@
|
|
|
1
1
|
import { combineMiddleware, runMiddleware } from '../../middleware-runner.js';
|
|
2
2
|
import { runPikkuFunc } from '../../function/function-runner.js';
|
|
3
|
+
import { createMiddlewareSessionWireProps, } from '../../services/user-session-service.js';
|
|
3
4
|
import { combineChannelMiddleware, wrapChannelWithMiddleware, } from './channel-middleware-runner.js';
|
|
4
|
-
|
|
5
|
-
* Runs a channel lifecycle function (onConnect or onDisconnect) with proper middleware handling.
|
|
6
|
-
*
|
|
7
|
-
* This function:
|
|
8
|
-
* 1. Extracts inline middleware from the lifecycle config if present
|
|
9
|
-
* 2. Combines metadata middleware with inline middleware using combineMiddleware()
|
|
10
|
-
* 3. Wraps the channel with channel middleware if present
|
|
11
|
-
* 4. Runs the lifecycle function with middleware support
|
|
12
|
-
*
|
|
13
|
-
* @param channelConfig - The channel configuration
|
|
14
|
-
* @param meta - Metadata for the lifecycle function (connect or disconnect)
|
|
15
|
-
* @param lifecycleConfig - The onConnect or onDisconnect config (can be function or object with middleware)
|
|
16
|
-
* @param lifecycleType - Type of lifecycle for cache key ('connect' or 'disconnect')
|
|
17
|
-
* @param services - All services (singleton + session)
|
|
18
|
-
* @param channel - The channel instance
|
|
19
|
-
* @param data - Optional data to pass to the lifecycle function (for onConnect)
|
|
20
|
-
* @param channelMiddlewareMeta - Optional channel middleware metadata for wrapping channel.send()
|
|
21
|
-
* @returns Promise<unknown> - Result from the lifecycle function (if any)
|
|
22
|
-
*/
|
|
23
|
-
export const runChannelLifecycleWithMiddleware = async ({ channelConfig, meta, lifecycleConfig, lifecycleType, services, channel, data, channelMiddlewareMeta, }) => {
|
|
5
|
+
export const runChannelLifecycleWithMiddleware = async ({ channelConfig, meta, lifecycleConfig, lifecycleType, services, channel, data, channelMiddlewareMeta, userSession, }) => {
|
|
24
6
|
const lifecycleMiddleware = typeof lifecycleConfig === 'object' && 'middleware' in lifecycleConfig
|
|
25
7
|
? lifecycleConfig.middleware || []
|
|
26
8
|
: [];
|
|
@@ -32,7 +14,10 @@ export const runChannelLifecycleWithMiddleware = async ({ channelConfig, meta, l
|
|
|
32
14
|
wireInheritedChannelMiddleware: channelMiddlewareMeta,
|
|
33
15
|
wireChannelMiddleware: channelConfig.channelMiddleware,
|
|
34
16
|
});
|
|
35
|
-
let wire = {
|
|
17
|
+
let wire = {
|
|
18
|
+
channel,
|
|
19
|
+
...(userSession ? createMiddlewareSessionWireProps(userSession) : {}),
|
|
20
|
+
};
|
|
36
21
|
if (allChannelMiddleware.length > 0) {
|
|
37
22
|
wire = wrapChannelWithMiddleware(wire, services, allChannelMiddleware);
|
|
38
23
|
}
|
|
@@ -41,6 +26,7 @@ export const runChannelLifecycleWithMiddleware = async ({ channelConfig, meta, l
|
|
|
41
26
|
singletonServices: services,
|
|
42
27
|
data: () => data,
|
|
43
28
|
wire,
|
|
29
|
+
sessionService: userSession,
|
|
44
30
|
tags: meta.tags ?? [],
|
|
45
31
|
packageName: meta.packageName ?? null,
|
|
46
32
|
});
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { pikkuState } from '../../pikku-state.js';
|
|
2
2
|
import { runPikkuFunc } from '../../function/function-runner.js';
|
|
3
|
+
import { isChannelRPCPending, isChannelRPCResponse } from './channel-rpc.js';
|
|
4
|
+
import { handleChannelRPCResponse } from './channel-host-rpc.js';
|
|
3
5
|
import { createMiddlewareSessionWireProps } from '../../services/user-session-service.js';
|
|
4
6
|
const getChannelMeta = (channelName) => {
|
|
5
7
|
return pikkuState(null, 'channel', 'meta')[channelName];
|
|
@@ -95,15 +97,25 @@ export const processMessageHandlers = (services, channelConfig, channelHandler,
|
|
|
95
97
|
const onMessage = async (rawData) => {
|
|
96
98
|
let result;
|
|
97
99
|
let processed = false;
|
|
98
|
-
|
|
99
|
-
if (typeof rawData === 'string'
|
|
100
|
-
let messageData;
|
|
100
|
+
let frame;
|
|
101
|
+
if (typeof rawData === 'string') {
|
|
101
102
|
try {
|
|
102
|
-
|
|
103
|
+
frame = JSON.parse(rawData);
|
|
103
104
|
}
|
|
104
105
|
catch {
|
|
105
106
|
// Most likely a json error.. ignore
|
|
106
107
|
}
|
|
108
|
+
}
|
|
109
|
+
// Taken ahead of routing so every channel gets reverse RPC without
|
|
110
|
+
// declaring a route for replies, and so an answer to a call someone is
|
|
111
|
+
// still awaiting can never be mistaken for a new message.
|
|
112
|
+
if (isChannelRPCResponse(frame) || isChannelRPCPending(frame)) {
|
|
113
|
+
handleChannelRPCResponse(channelHandler.getChannel().channelId, frame);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
// Route-specific handling
|
|
117
|
+
if (typeof rawData === 'string' && channelConfig.onMessageWiring) {
|
|
118
|
+
const messageData = frame;
|
|
107
119
|
if (messageData) {
|
|
108
120
|
const entries = Object.entries(channelConfig.onMessageWiring);
|
|
109
121
|
for (const [routingProperty, routes] of entries) {
|
|
@@ -111,9 +123,16 @@ export const processMessageHandlers = (services, channelConfig, channelHandler,
|
|
|
111
123
|
if (routerValue && routes[routerValue]) {
|
|
112
124
|
const { [routingProperty]: _, ...data } = messageData;
|
|
113
125
|
processed = true;
|
|
126
|
+
const routeResult = await processMessage(data, routes[routerValue], routingProperty, routerValue);
|
|
127
|
+
// The routing key is echoed so the client can match the reply.
|
|
128
|
+
// Assigning it to a primitive throws under ESM strict mode, so a
|
|
129
|
+
// primitive result is wrapped rather than mutated.
|
|
114
130
|
result =
|
|
115
|
-
|
|
116
|
-
|
|
131
|
+
routeResult !== null && typeof routeResult === 'object'
|
|
132
|
+
? Object.assign(routeResult, { [routingProperty]: routerValue })
|
|
133
|
+
: routeResult === undefined
|
|
134
|
+
? { [routingProperty]: routerValue }
|
|
135
|
+
: { [routingProperty]: routerValue, result: routeResult };
|
|
117
136
|
break;
|
|
118
137
|
}
|
|
119
138
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ChannelDeploymentService } from './channel-rpc.js';
|
|
2
|
+
import type { ChannelRPCValidator } from './channel-rpc.js';
|
|
3
|
+
import type { PikkuChannel } from './channel.types.js';
|
|
4
|
+
/**
|
|
5
|
+
* The transport for a connection, created on first use. `options` apply only
|
|
6
|
+
* to the call that creates it — one connection has one transport, so the first
|
|
7
|
+
* caller's timeout and validators become the connection's.
|
|
8
|
+
*/
|
|
9
|
+
export declare const getChannelHostRPC: (channel: PikkuChannel<unknown, any>, options?: {
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
validateInput?: ChannelRPCValidator;
|
|
12
|
+
validateResult?: ChannelRPCValidator;
|
|
13
|
+
}) => ChannelDeploymentService;
|
|
14
|
+
/**
|
|
15
|
+
* Kept out of the channel handler so a channel nobody calls back on pays for no
|
|
16
|
+
* registry, and because a handler has no services to build a validator with.
|
|
17
|
+
*/
|
|
18
|
+
export declare const channelRemote: (channel: PikkuChannel<unknown, any, any>, funcName: string, data?: unknown) => Promise<unknown>;
|
|
19
|
+
/** False for an unknown connection or id, so a stray frame is dropped. */
|
|
20
|
+
export declare const handleChannelRPCResponse: (channelId: string, message: unknown) => boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Must run on disconnect: without it a caller waits out the full timeout on a
|
|
23
|
+
* dead socket, and the map grows for the life of the process.
|
|
24
|
+
*/
|
|
25
|
+
export declare const releaseChannelHostRPC: (channelId: string) => Promise<void>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ChannelDeploymentService, createChannelRPCInputValidator, createChannelRPCResultValidator, } from './channel-rpc.js';
|
|
2
|
+
import { getSingletonServices } from '../../pikku-state.js';
|
|
3
|
+
/** Reverse-RPC transports, one per open connection. */
|
|
4
|
+
const hostRPCByChannel = new Map();
|
|
5
|
+
/**
|
|
6
|
+
* The transport for a connection, created on first use. `options` apply only
|
|
7
|
+
* to the call that creates it — one connection has one transport, so the first
|
|
8
|
+
* caller's timeout and validators become the connection's.
|
|
9
|
+
*/
|
|
10
|
+
export const getChannelHostRPC = (channel, options = {}) => {
|
|
11
|
+
let service = hostRPCByChannel.get(channel.channelId);
|
|
12
|
+
if (!service) {
|
|
13
|
+
service = new ChannelDeploymentService((data) => channel.send(data), options);
|
|
14
|
+
hostRPCByChannel.set(channel.channelId, service);
|
|
15
|
+
}
|
|
16
|
+
return service;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Kept out of the channel handler so a channel nobody calls back on pays for no
|
|
20
|
+
* registry, and because a handler has no services to build a validator with.
|
|
21
|
+
*/
|
|
22
|
+
export const channelRemote = async (channel, funcName, data) => getChannelHostRPC(channel, {
|
|
23
|
+
validateInput: createChannelRPCInputValidator(getSingletonServices()),
|
|
24
|
+
validateResult: createChannelRPCResultValidator(getSingletonServices()),
|
|
25
|
+
}).invoke(funcName, data);
|
|
26
|
+
/** False for an unknown connection or id, so a stray frame is dropped. */
|
|
27
|
+
export const handleChannelRPCResponse = (channelId, message) => hostRPCByChannel.get(channelId)?.handleResponse(message) ?? false;
|
|
28
|
+
/**
|
|
29
|
+
* Must run on disconnect: without it a caller waits out the full timeout on a
|
|
30
|
+
* dead socket, and the map grows for the life of the process.
|
|
31
|
+
*/
|
|
32
|
+
export const releaseChannelHostRPC = async (channelId) => {
|
|
33
|
+
const service = hostRPCByChannel.get(channelId);
|
|
34
|
+
if (service) {
|
|
35
|
+
hostRPCByChannel.delete(channelId);
|
|
36
|
+
await service.stop();
|
|
37
|
+
}
|
|
38
|
+
};
|
|
@@ -2,18 +2,6 @@ import type { CoreSingletonServices, MiddlewareMetadata, PikkuRawWire } from '..
|
|
|
2
2
|
import type { CorePikkuChannelMiddleware } from './channel.types.js';
|
|
3
3
|
export declare const addChannelMiddleware: (tag: string, middleware: CorePikkuChannelMiddleware[], packageName?: string | null) => CorePikkuChannelMiddleware[];
|
|
4
4
|
export declare const clearChannelMiddlewareCache: () => void;
|
|
5
|
-
/**
|
|
6
|
-
* Combine the inherited (tag/named) channel middleware with any per-run
|
|
7
|
-
* middleware for a wiring.
|
|
8
|
-
*
|
|
9
|
-
* Only the statically-resolved inherited middleware is deterministic per `uid`
|
|
10
|
-
* and safe to cache. `wireChannelMiddleware` is a per-run set of closures (e.g.
|
|
11
|
-
* an AI agent's per-invocation stream middleware holding that run's
|
|
12
|
-
* thread/session state) and MUST NOT be cached — caching it lets a later run of
|
|
13
|
-
* the same `uid` reuse an earlier run's closures, leaking that run's state (and
|
|
14
|
-
* growing memory) across invocations. It is therefore appended fresh on every
|
|
15
|
-
* call after the cached inherited slice.
|
|
16
|
-
*/
|
|
17
5
|
export declare const combineChannelMiddleware: (wireType: string, uid: string, { wireInheritedChannelMiddleware, wireChannelMiddleware, packageName, }?: {
|
|
18
6
|
wireInheritedChannelMiddleware?: MiddlewareMetadata[];
|
|
19
7
|
wireChannelMiddleware?: CorePikkuChannelMiddleware[];
|
|
@@ -16,18 +16,6 @@ export const clearChannelMiddlewareCache = () => {
|
|
|
16
16
|
delete channelMiddlewareCache[key];
|
|
17
17
|
}
|
|
18
18
|
};
|
|
19
|
-
/**
|
|
20
|
-
* Combine the inherited (tag/named) channel middleware with any per-run
|
|
21
|
-
* middleware for a wiring.
|
|
22
|
-
*
|
|
23
|
-
* Only the statically-resolved inherited middleware is deterministic per `uid`
|
|
24
|
-
* and safe to cache. `wireChannelMiddleware` is a per-run set of closures (e.g.
|
|
25
|
-
* an AI agent's per-invocation stream middleware holding that run's
|
|
26
|
-
* thread/session state) and MUST NOT be cached — caching it lets a later run of
|
|
27
|
-
* the same `uid` reuse an earlier run's closures, leaking that run's state (and
|
|
28
|
-
* growing memory) across invocations. It is therefore appended fresh on every
|
|
29
|
-
* call after the cached inherited slice.
|
|
30
|
-
*/
|
|
31
19
|
export const combineChannelMiddleware = (wireType, uid, { wireInheritedChannelMiddleware, wireChannelMiddleware, packageName = null, } = {}) => {
|
|
32
20
|
const cacheKey = `${wireType}:${uid}`;
|
|
33
21
|
let inherited = channelMiddlewareCache[cacheKey];
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type ChannelRPCResponse } from './channel-rpc.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Tracks in-flight reverse RPC calls for one channel. One registry per
|
|
4
|
+
* connection: ids are only unique within a socket, and a dropped socket must
|
|
5
|
+
* reject exactly the calls that were riding on it.
|
|
6
|
+
*/
|
|
7
|
+
export declare class ChannelRPCRegistry {
|
|
8
|
+
private readonly timeoutMs;
|
|
9
|
+
private pending;
|
|
10
|
+
private nextId;
|
|
11
|
+
private closed;
|
|
12
|
+
constructor(timeoutMs?: number);
|
|
13
|
+
get inFlight(): number;
|
|
14
|
+
register(): {
|
|
15
|
+
id: string;
|
|
16
|
+
promise: Promise<unknown>;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Stops the clock on a call whose peer is asking a human. The timeout exists
|
|
20
|
+
* to bound a peer that has gone away, and a person reading a prompt is not
|
|
21
|
+
* that; `rejectAll` still fails the call the moment the socket drops.
|
|
22
|
+
*
|
|
23
|
+
* Returns false for an unknown id — a pending frame for a call that already
|
|
24
|
+
* timed out is stale, not an error.
|
|
25
|
+
*/
|
|
26
|
+
hold(id: string): boolean;
|
|
27
|
+
/** Returns false for an unknown id, so a late reply is dropped. */
|
|
28
|
+
settle(response: ChannelRPCResponse): boolean;
|
|
29
|
+
/** Without this a caller awaits the full timeout on a connection that is gone. */
|
|
30
|
+
rejectAll(reason?: string): void;
|
|
31
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { ChannelRPCError, } from './channel-rpc.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Tracks in-flight reverse RPC calls for one channel. One registry per
|
|
4
|
+
* connection: ids are only unique within a socket, and a dropped socket must
|
|
5
|
+
* reject exactly the calls that were riding on it.
|
|
6
|
+
*/
|
|
7
|
+
export class ChannelRPCRegistry {
|
|
8
|
+
timeoutMs;
|
|
9
|
+
pending = new Map();
|
|
10
|
+
nextId = 0;
|
|
11
|
+
closed = false;
|
|
12
|
+
constructor(timeoutMs = 30_000) {
|
|
13
|
+
this.timeoutMs = timeoutMs;
|
|
14
|
+
}
|
|
15
|
+
get inFlight() {
|
|
16
|
+
return this.pending.size;
|
|
17
|
+
}
|
|
18
|
+
register() {
|
|
19
|
+
if (this.closed) {
|
|
20
|
+
return {
|
|
21
|
+
id: '',
|
|
22
|
+
promise: Promise.reject(new ChannelRPCError('Channel is closed', 'closed')),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const id = `${++this.nextId}`;
|
|
26
|
+
const promise = new Promise((resolve, reject) => {
|
|
27
|
+
const timer = this.timeoutMs > 0
|
|
28
|
+
? setTimeout(() => {
|
|
29
|
+
this.pending.delete(id);
|
|
30
|
+
reject(new ChannelRPCError(`Channel RPC ${id} timed out after ${this.timeoutMs}ms`, 'timeout'));
|
|
31
|
+
}, this.timeoutMs)
|
|
32
|
+
: undefined;
|
|
33
|
+
// Never hold the process open waiting on a peer that may not answer.
|
|
34
|
+
timer?.unref?.();
|
|
35
|
+
this.pending.set(id, { resolve, reject, timer });
|
|
36
|
+
});
|
|
37
|
+
return { id, promise };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Stops the clock on a call whose peer is asking a human. The timeout exists
|
|
41
|
+
* to bound a peer that has gone away, and a person reading a prompt is not
|
|
42
|
+
* that; `rejectAll` still fails the call the moment the socket drops.
|
|
43
|
+
*
|
|
44
|
+
* Returns false for an unknown id — a pending frame for a call that already
|
|
45
|
+
* timed out is stale, not an error.
|
|
46
|
+
*/
|
|
47
|
+
hold(id) {
|
|
48
|
+
const call = this.pending.get(id);
|
|
49
|
+
if (!call || call.awaitingHuman) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
clearTimeout(call.timer);
|
|
53
|
+
call.timer = undefined;
|
|
54
|
+
call.awaitingHuman = true;
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
/** Returns false for an unknown id, so a late reply is dropped. */
|
|
58
|
+
settle(response) {
|
|
59
|
+
const call = this.pending.get(response.id);
|
|
60
|
+
if (!call) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
this.pending.delete(response.id);
|
|
64
|
+
clearTimeout(call.timer);
|
|
65
|
+
if (response.ok) {
|
|
66
|
+
call.resolve(response.result);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
// Peer input: a non-string name or message falls back rather than being
|
|
70
|
+
// attached to an Error, where it would surface as `[object Object]`.
|
|
71
|
+
const { name, message } = response.error ?? {};
|
|
72
|
+
const error = new ChannelRPCError(typeof message === 'string' ? message : 'Remote channel RPC failed', 'remote');
|
|
73
|
+
if (typeof name === 'string' && name.length > 0) {
|
|
74
|
+
error.name = name;
|
|
75
|
+
}
|
|
76
|
+
call.reject(error);
|
|
77
|
+
}
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
/** Without this a caller awaits the full timeout on a connection that is gone. */
|
|
81
|
+
rejectAll(reason = 'Channel closed') {
|
|
82
|
+
this.closed = true;
|
|
83
|
+
for (const [, call] of this.pending) {
|
|
84
|
+
clearTimeout(call.timer);
|
|
85
|
+
call.reject(new ChannelRPCError(reason, 'closed'));
|
|
86
|
+
}
|
|
87
|
+
this.pending.clear();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ApprovalRequester, type Capabilities } from './channel-rpc.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Answers reverse RPC requests arriving on a channel.
|
|
4
|
+
*
|
|
5
|
+
* `capabilities` is the authorisation boundary, not a convenience: the peer is
|
|
6
|
+
* asking this process to execute code, so only listed names run. An absent
|
|
7
|
+
* name is refused exactly like an unknown one, so the caller cannot probe for
|
|
8
|
+
* what this end can do.
|
|
9
|
+
*/
|
|
10
|
+
export declare const createChannelRPCResponder: ({ capabilities, send, approve, }: {
|
|
11
|
+
capabilities: Capabilities;
|
|
12
|
+
send: (data: unknown) => Promise<void> | void;
|
|
13
|
+
/** Omitted means there is nobody to ask, which refuses rather than runs. */
|
|
14
|
+
approve?: ApprovalRequester;
|
|
15
|
+
}) => (message: unknown) => Promise<boolean>;
|