@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,8 +1,9 @@
|
|
|
1
1
|
import type { AIStreamChannel } from './ai-agent.types.js';
|
|
2
2
|
import type { AIAgentRunnerParams, AIAgentStepResult } from '../../services/ai-agent-runner-service.js';
|
|
3
3
|
import { ToolApprovalRequired, ToolCredentialRequired, type RunAIAgentParams, type StreamAIAgentOptions } from './ai-agent-prepare.js';
|
|
4
|
-
|
|
5
|
-
export declare function
|
|
4
|
+
import { type AgentInterruption, type AgentInterruptResult } from './ai-agent-interrupt.js';
|
|
5
|
+
export declare function checkForApprovals(stepResult: AIAgentStepResult, tools: AIAgentRunnerParams['tools']): ToolApprovalRequired[];
|
|
6
|
+
export declare function checkForCredentialRequests(stepResult: AIAgentStepResult): ToolCredentialRequired[];
|
|
6
7
|
export declare function appendStepMessages(runnerParams: AIAgentRunnerParams, stepResult: AIAgentStepResult): void;
|
|
7
8
|
export declare function streamAIAgent(agentName: string, input: {
|
|
8
9
|
message: string;
|
|
@@ -11,6 +12,28 @@ export declare function streamAIAgent(agentName: string, input: {
|
|
|
11
12
|
model?: string;
|
|
12
13
|
temperature?: number;
|
|
13
14
|
}, channel: AIStreamChannel, params: RunAIAgentParams, agentSessionMap?: Map<string, string>, options?: StreamAIAgentOptions): Promise<string>;
|
|
15
|
+
/**
|
|
16
|
+
* Stop an in-flight run on behalf of a caller, after checking the run is theirs.
|
|
17
|
+
*
|
|
18
|
+
* Unlike {@link resumeAIAgent} this needs no channel: it does not continue the
|
|
19
|
+
* stream, it ends one. The `interrupted` event and the truncated message are
|
|
20
|
+
* emitted by the original {@link streamAIAgent} call on its own channel, so this
|
|
21
|
+
* can be reached over a plain RPC while the stream is held open elsewhere —
|
|
22
|
+
* which is exactly the shape a voice barge-in needs.
|
|
23
|
+
*
|
|
24
|
+
* Ownership is the whole gate, deliberately without {@link assertAgentAuthorized}.
|
|
25
|
+
* Resuming re-enters the agent and approves a tool call, so a revoked grant must
|
|
26
|
+
* block it; stopping is the opposite — if a caller's access to an agent was
|
|
27
|
+
* revoked mid-run, being able to stop their own run is harmless and arguably
|
|
28
|
+
* what you want.
|
|
29
|
+
*
|
|
30
|
+
* Returns `false` when there was nothing to stop. Racing a run that finishes on
|
|
31
|
+
* its own is the normal case in voice, so it is not an error.
|
|
32
|
+
*/
|
|
33
|
+
export declare function interruptAIAgent(input: {
|
|
34
|
+
runId: string;
|
|
35
|
+
reason?: AgentInterruption['reason'];
|
|
36
|
+
}, params: RunAIAgentParams): Promise<AgentInterruptResult>;
|
|
14
37
|
export declare function resumeAIAgent(input: {
|
|
15
38
|
runId: string;
|
|
16
39
|
toolCallId: string;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { pikkuState, getSingletonServices } from '../../pikku-state.js';
|
|
2
2
|
import { AIProviderNotConfiguredError } from '../../errors/errors.js';
|
|
3
3
|
import { randomUUID } from './ai-agent-utils.js';
|
|
4
|
+
import { SPOKEN_TRANSCRIPT } from './voice-input.js';
|
|
4
5
|
import { combineChannelMiddleware, wrapChannelWithMiddleware, } from '../channel/channel-middleware-runner.js';
|
|
5
6
|
import { resolveMemoryServices, loadContextMessages, trimMessages, getWorkingMemoryMiddleware, } from './ai-agent-memory.js';
|
|
6
|
-
import { prepareAgentRun, resolveAgent, buildInstructions, buildToolDefs, createScopedChannel, resolveOwnerResourceId, agentSessionScope, assertResourceOwner, assertAgentAuthorized, ToolApprovalRequired, ToolCredentialRequired, APPROVAL_REQUIRED, } from './ai-agent-prepare.js';
|
|
7
|
+
import { prepareAgentRun, resolveAgent, buildInstructions, buildToolDefs, createScopedChannel, resolveOwnerResourceId, agentSessionScope, assertResourceOwner, assertResourcePrincipalOwner, assertAgentAuthorized, ToolApprovalRequired, ToolCredentialRequired, APPROVAL_REQUIRED, CREDENTIAL_REQUIRED, } from './ai-agent-prepare.js';
|
|
7
8
|
import { resolveModelConfig } from './ai-agent-model-config.js';
|
|
9
|
+
import { getInFlightTools, isAbortError, persistOrphanedToolResults, registerInterruptibleRun, signalRunInterrupt, trackInterruptNote, trackToolExecution, } from './ai-agent-interrupt.js';
|
|
8
10
|
function createPersistingChannel(parent, storage, threadId, logger) {
|
|
9
11
|
let fullText = '';
|
|
10
12
|
let stepText = '';
|
|
@@ -15,7 +17,7 @@ function createPersistingChannel(parent, storage, threadId, logger) {
|
|
|
15
17
|
inputTokens: 0,
|
|
16
18
|
outputTokens: 0,
|
|
17
19
|
};
|
|
18
|
-
const flushStep = async () => {
|
|
20
|
+
const flushStep = async (opts) => {
|
|
19
21
|
if (!storage)
|
|
20
22
|
return;
|
|
21
23
|
const text = stepText;
|
|
@@ -37,6 +39,7 @@ function createPersistingChannel(parent, storage, threadId, logger) {
|
|
|
37
39
|
]
|
|
38
40
|
: text || undefined,
|
|
39
41
|
toolCalls: calls.length > 0 ? calls : undefined,
|
|
42
|
+
...(opts?.interrupted ? { interrupted: true } : {}),
|
|
40
43
|
createdAt: new Date(),
|
|
41
44
|
};
|
|
42
45
|
const messages = [assistantMsg];
|
|
@@ -51,14 +54,6 @@ function createPersistingChannel(parent, storage, threadId, logger) {
|
|
|
51
54
|
await storage.saveMessages(threadId, messages);
|
|
52
55
|
}
|
|
53
56
|
};
|
|
54
|
-
/**
|
|
55
|
-
* `send` is synchronous and so cannot await the flush. A rejection would have
|
|
56
|
-
* nothing to propagate to and would take the process down as an unhandled
|
|
57
|
-
* rejection — a model reusing a toolCallId, which is a primary key in AI
|
|
58
|
-
* storage, is enough to trigger it. Persistence from inside `send` is
|
|
59
|
-
* therefore best-effort: the run carries on, and the awaited `flush()` on the
|
|
60
|
-
* suspend paths still surfaces failures to its caller.
|
|
61
|
-
*/
|
|
62
57
|
const flushDetached = () => {
|
|
63
58
|
void flushStep().catch((error) => {
|
|
64
59
|
logger?.error('Failed to persist agent messages', {
|
|
@@ -83,11 +78,15 @@ function createPersistingChannel(parent, storage, threadId, logger) {
|
|
|
83
78
|
close: () => parent.close(),
|
|
84
79
|
sendBinary: (data) => parent.sendBinary(data),
|
|
85
80
|
send: (event) => {
|
|
81
|
+
// Accumulated whether or not storage is configured: `fullText` is what
|
|
82
|
+
// the client was streamed, and an interrupted run has to be able to
|
|
83
|
+
// report the fragment it got through even with persistence turned off.
|
|
84
|
+
if (event.type === 'text-delta')
|
|
85
|
+
fullText += event.text;
|
|
86
86
|
if (storage) {
|
|
87
87
|
switch (event.type) {
|
|
88
88
|
case 'text-delta':
|
|
89
89
|
stepText += event.text;
|
|
90
|
-
fullText += event.text;
|
|
91
90
|
break;
|
|
92
91
|
case 'tool-call':
|
|
93
92
|
stepToolCalls.push({
|
|
@@ -125,6 +124,7 @@ function createPersistingChannel(parent, storage, threadId, logger) {
|
|
|
125
124
|
setState: (s) => parent.setState(s),
|
|
126
125
|
getState: () => parent.getState(),
|
|
127
126
|
clearState: () => parent.clearState(),
|
|
127
|
+
remote: (funcName, data) => parent.remote(funcName, data),
|
|
128
128
|
};
|
|
129
129
|
return channel;
|
|
130
130
|
}
|
|
@@ -161,7 +161,7 @@ async function postStreamCleanup(persistingChannel, aiMiddlewares, singletonServ
|
|
|
161
161
|
});
|
|
162
162
|
}
|
|
163
163
|
async function runStreamStepLoop(params) {
|
|
164
|
-
const { agent, runnerParams, maxSteps, agentRunner, streamChannel, channel,
|
|
164
|
+
const { agent, runnerParams, maxSteps, agentRunner, streamChannel, channel, aiMiddlewares, } = params;
|
|
165
165
|
const singletonServices = getSingletonServices();
|
|
166
166
|
for (let step = 0; step < maxSteps; step++) {
|
|
167
167
|
if (agent.prepareStep) {
|
|
@@ -195,25 +195,21 @@ async function runStreamStepLoop(params) {
|
|
|
195
195
|
}
|
|
196
196
|
if (stepResult.toolCalls.length === 0)
|
|
197
197
|
break;
|
|
198
|
-
const approvalsNeeded = checkForApprovals(stepResult, runnerParams.tools
|
|
198
|
+
const approvalsNeeded = checkForApprovals(stepResult, runnerParams.tools);
|
|
199
199
|
if (approvalsNeeded.length > 0) {
|
|
200
|
-
// For each approval, call approvalDescriptionFn if available
|
|
201
200
|
for (const approval of approvalsNeeded) {
|
|
202
201
|
const toolDef = runnerParams.tools.find((t) => t.name === approval.toolName);
|
|
203
202
|
if (toolDef?.approvalDescriptionFn && !approval.reason) {
|
|
204
203
|
try {
|
|
205
204
|
approval.reason = await toolDef.approvalDescriptionFn(approval.args);
|
|
206
205
|
}
|
|
207
|
-
catch {
|
|
208
|
-
// If description generation fails, continue without it
|
|
209
|
-
}
|
|
206
|
+
catch { }
|
|
210
207
|
}
|
|
211
208
|
}
|
|
212
209
|
return { outcome: 'approval', approvals: approvalsNeeded };
|
|
213
210
|
}
|
|
214
|
-
const credentialRequests = checkForCredentialRequests(stepResult
|
|
211
|
+
const credentialRequests = checkForCredentialRequests(stepResult);
|
|
215
212
|
if (credentialRequests.length > 0) {
|
|
216
|
-
// Append step messages so the tool result is preserved for resume
|
|
217
213
|
appendStepMessages(runnerParams, stepResult);
|
|
218
214
|
return { outcome: 'credential', credentialRequests };
|
|
219
215
|
}
|
|
@@ -221,7 +217,7 @@ async function runStreamStepLoop(params) {
|
|
|
221
217
|
}
|
|
222
218
|
return { outcome: 'done' };
|
|
223
219
|
}
|
|
224
|
-
export function checkForApprovals(stepResult, tools
|
|
220
|
+
export function checkForApprovals(stepResult, tools) {
|
|
225
221
|
const approvals = [];
|
|
226
222
|
for (const tc of stepResult.toolCalls) {
|
|
227
223
|
const toolDef = tools.find((t) => t.name === tc.toolName);
|
|
@@ -229,12 +225,6 @@ export function checkForApprovals(stepResult, tools, runId) {
|
|
|
229
225
|
approvals.push(new ToolApprovalRequired(tc.toolCallId, tc.toolName, tc.args));
|
|
230
226
|
continue;
|
|
231
227
|
}
|
|
232
|
-
// The approval marker is only trusted from a framework tool declared with
|
|
233
|
-
// `forwardsApproval` (the sub-agent delegating tools) AND carrying the
|
|
234
|
-
// non-forgeable `APPROVAL_REQUIRED` Symbol brand. A plain tool's output — or
|
|
235
|
-
// a delegating tool's LLM-shaped `result.object`, which an attacker can
|
|
236
|
-
// influence — is plain JSON and can never carry the Symbol, so it can never
|
|
237
|
-
// forge an approval/suspension.
|
|
238
228
|
if (!toolDef?.forwardsApproval) {
|
|
239
229
|
continue;
|
|
240
230
|
}
|
|
@@ -255,12 +245,13 @@ export function checkForApprovals(stepResult, tools, runId) {
|
|
|
255
245
|
}
|
|
256
246
|
return approvals;
|
|
257
247
|
}
|
|
258
|
-
export function checkForCredentialRequests(stepResult
|
|
248
|
+
export function checkForCredentialRequests(stepResult) {
|
|
259
249
|
const requests = [];
|
|
260
250
|
for (const tr of stepResult.toolResults) {
|
|
251
|
+
// knowledge: decisions/security/ai-agent-credential-requests-are-symbol-branded.md
|
|
261
252
|
if (tr.result &&
|
|
262
253
|
typeof tr.result === 'object' &&
|
|
263
|
-
|
|
254
|
+
CREDENTIAL_REQUIRED in tr.result) {
|
|
264
255
|
const r = tr.result;
|
|
265
256
|
const tc = stepResult.toolCalls.find((t) => t.toolCallId === tr.toolCallId);
|
|
266
257
|
requests.push(new ToolCredentialRequired(tr.toolCallId, tc?.toolName ?? 'unknown', tc?.args ?? {}, r.credentialName, r.credentialType, r.connectUrl));
|
|
@@ -366,10 +357,6 @@ function handleCredentialRequests(requests, runId, channel, aiRunState, persisti
|
|
|
366
357
|
suspendReason: 'credential',
|
|
367
358
|
pendingApprovals,
|
|
368
359
|
});
|
|
369
|
-
// The __credentialRequired tool result is suppressed from the stream, so
|
|
370
|
-
// credential-request events (with the runId needed for /resume) are the
|
|
371
|
-
// client's signal to show Connect/Ignore buttons — mirroring how
|
|
372
|
-
// approval-request suspensions work.
|
|
373
360
|
for (const req of requests) {
|
|
374
361
|
channel.send({
|
|
375
362
|
type: 'credential-request',
|
|
@@ -393,7 +380,6 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
|
|
|
393
380
|
resourceId: resolveOwnerResourceId(params, agentSessionScope(agentName), input.resourceId),
|
|
394
381
|
};
|
|
395
382
|
const streamContext = { channel, options };
|
|
396
|
-
// delegateState is attached after prepareAgentRun resolves the agent config
|
|
397
383
|
const { agent, packageName, resolvedName, agentRunner, storage, memoryConfig, threadId, userMessage, runnerParams, maxSteps, missingRpcs, workingMemorySchemaName, } = await prepareAgentRun(agentName, normalizedInput, params, sessionMap, streamContext);
|
|
398
384
|
runnerParams.agentId = agentName;
|
|
399
385
|
const singletonServices = getSingletonServices();
|
|
@@ -426,6 +412,8 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
|
|
|
426
412
|
}),
|
|
427
413
|
...(agent.aiMiddleware ?? []),
|
|
428
414
|
];
|
|
415
|
+
// One bag per run, shared by every middleware — see PikkuAIMiddlewareHooks.
|
|
416
|
+
const sharedNotes = {};
|
|
429
417
|
let modifiedMessages = runnerParams.messages;
|
|
430
418
|
let modifiedInstructions = runnerParams.instructions;
|
|
431
419
|
for (const mw of aiMiddlewares) {
|
|
@@ -433,6 +421,7 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
|
|
|
433
421
|
const result = await mw.modifyInput(singletonServices, {
|
|
434
422
|
messages: modifiedMessages,
|
|
435
423
|
instructions: modifiedInstructions,
|
|
424
|
+
shared: sharedNotes,
|
|
436
425
|
});
|
|
437
426
|
modifiedMessages = result.messages;
|
|
438
427
|
modifiedInstructions = result.instructions;
|
|
@@ -440,6 +429,23 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
|
|
|
440
429
|
}
|
|
441
430
|
runnerParams.messages = modifiedMessages;
|
|
442
431
|
runnerParams.instructions = modifiedInstructions;
|
|
432
|
+
// Sent on the raw channel, ahead of the run. A voice client sent audio and so
|
|
433
|
+
// has no idea what it said; until this arrives its own message is a blank
|
|
434
|
+
// bubble. Ahead of the run rather than alongside it because the answer starts
|
|
435
|
+
// streaming within a few hundred milliseconds, and a question that appears
|
|
436
|
+
// after its answer reads as the wrong question.
|
|
437
|
+
const transcript = sharedNotes[SPOKEN_TRANSCRIPT];
|
|
438
|
+
if (typeof transcript === 'string') {
|
|
439
|
+
channel.send({ type: 'transcript', text: transcript });
|
|
440
|
+
}
|
|
441
|
+
// What goes into thread history is what the model was actually asked. For a
|
|
442
|
+
// spoken turn that is not what arrived over the wire: the wire carried a
|
|
443
|
+
// base64 audio blob, and persisting it would write megabytes of unreadable
|
|
444
|
+
// data into the history while losing the only readable record of the turn.
|
|
445
|
+
// Identity-checked rather than assumed — a middleware is free to rewrite the
|
|
446
|
+
// message list into something with no relation to the turn.
|
|
447
|
+
const lastModified = modifiedMessages[modifiedMessages.length - 1];
|
|
448
|
+
const persistedUserMessage = lastModified?.id === userMessage.id ? lastModified : userMessage;
|
|
443
449
|
const runId = await aiRunState.createRun({
|
|
444
450
|
agentName,
|
|
445
451
|
threadId,
|
|
@@ -450,8 +456,14 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
|
|
|
450
456
|
updatedAt: new Date(),
|
|
451
457
|
});
|
|
452
458
|
options?.onRunCreated?.(runId);
|
|
459
|
+
// Registered before the first model call and released in `finally`, so the
|
|
460
|
+
// window in which an interrupt can land is exactly the window in which there
|
|
461
|
+
// is something to interrupt.
|
|
462
|
+
const interruptHandle = registerInterruptibleRun(runId);
|
|
463
|
+
runnerParams.abortSignal = interruptHandle.signal;
|
|
464
|
+
runnerParams.tools = trackToolExecution(runnerParams.tools, interruptHandle);
|
|
453
465
|
if (storage) {
|
|
454
|
-
await storage.saveMessages(threadId, [
|
|
466
|
+
await storage.saveMessages(threadId, [persistedUserMessage]);
|
|
455
467
|
}
|
|
456
468
|
const streamMiddleware = aiMiddlewares
|
|
457
469
|
.filter((mw) => mw.modifyOutputStream)
|
|
@@ -464,6 +476,11 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
|
|
|
464
476
|
event,
|
|
465
477
|
allEvents,
|
|
466
478
|
state,
|
|
479
|
+
shared: sharedNotes,
|
|
480
|
+
// Sends downstream directly, so a hook can hand back the fast event
|
|
481
|
+
// now and push the slow one when it is ready.
|
|
482
|
+
emit: next,
|
|
483
|
+
signal: interruptHandle.signal,
|
|
467
484
|
});
|
|
468
485
|
if (result == null)
|
|
469
486
|
return;
|
|
@@ -489,12 +506,12 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
|
|
|
489
506
|
const wrappedChannel = allChannelMiddleware.length > 0
|
|
490
507
|
? wrapChannelWithMiddleware({ channel: persistingChannel }, singletonServices, allChannelMiddleware).channel
|
|
491
508
|
: persistingChannel;
|
|
492
|
-
// Tool results carrying the __credentialRequired marker must never reach
|
|
493
|
-
// the client or persisted history: the run suspends with credential-request
|
|
494
|
-
// events instead (mirroring approvals), and leaving the tool call
|
|
495
|
-
// unresulted is what lets the client resume it after connecting.
|
|
496
509
|
const credentialFilteredChannel = {
|
|
497
510
|
...wrappedChannel,
|
|
511
|
+
// Returns what the inner send returns. Middleware runs asynchronously, so
|
|
512
|
+
// swallowing the promise here makes every `await channel.send(...)` upstream
|
|
513
|
+
// a no-op — including the one that waits for a buffering hook to flush
|
|
514
|
+
// before the channel closes.
|
|
498
515
|
send: (event) => {
|
|
499
516
|
if (event.type === 'tool-result' &&
|
|
500
517
|
event.result !== null &&
|
|
@@ -502,14 +519,10 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
|
|
|
502
519
|
'__credentialRequired' in event.result) {
|
|
503
520
|
return;
|
|
504
521
|
}
|
|
505
|
-
wrappedChannel.send(event);
|
|
522
|
+
return wrappedChannel.send(event);
|
|
506
523
|
},
|
|
507
524
|
};
|
|
508
|
-
|
|
509
|
-
// AFTER a sub-agent has been called. If the parent responds directly (no delegation),
|
|
510
|
-
// its text goes through normally. Sub-agent text bypasses this path entirely
|
|
511
|
-
// (goes through subChannel → channel directly).
|
|
512
|
-
const isDelegateMode = agent.agentMode !== 'supervise' && meta.agents?.length;
|
|
525
|
+
const isDelegateMode = agent.agentMode !== 'supervise' && meta?.agents?.length;
|
|
513
526
|
const delegateState = { delegated: false };
|
|
514
527
|
if (isDelegateMode) {
|
|
515
528
|
streamContext.delegateState = delegateState;
|
|
@@ -521,7 +534,7 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
|
|
|
521
534
|
if (delegateState.delegated &&
|
|
522
535
|
(event.type === 'text-delta' || event.type === 'reasoning-delta'))
|
|
523
536
|
return;
|
|
524
|
-
credentialFilteredChannel.send(event);
|
|
537
|
+
return credentialFilteredChannel.send(event);
|
|
525
538
|
},
|
|
526
539
|
delegateState,
|
|
527
540
|
}
|
|
@@ -535,7 +548,6 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
|
|
|
535
548
|
streamChannel: outputChannel,
|
|
536
549
|
persistingChannel,
|
|
537
550
|
channel,
|
|
538
|
-
runId,
|
|
539
551
|
aiMiddlewares,
|
|
540
552
|
});
|
|
541
553
|
if (loopResult.outcome === 'approval') {
|
|
@@ -547,11 +559,38 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
|
|
|
547
559
|
return persistingChannel.fullText;
|
|
548
560
|
}
|
|
549
561
|
await postStreamCleanup(persistingChannel, aiMiddlewares, singletonServices, runnerParams.messages, aiRunState, runId);
|
|
550
|
-
channel
|
|
562
|
+
// Through the middleware rather than straight at the channel, and awaited.
|
|
563
|
+
// `done` is the only signal a stream hook gets that the reply is over, and
|
|
564
|
+
// the ones that buffer need it: `voiceOutput` speaks a trailing fragment
|
|
565
|
+
// that never reached a full stop, and waits for audio it has already paid
|
|
566
|
+
// to synthesize. Sent raw, that work is discarded by the `close()` below.
|
|
567
|
+
await outputChannel.send({ type: 'done' });
|
|
551
568
|
channel.close();
|
|
552
569
|
return persistingChannel.fullText;
|
|
553
570
|
}
|
|
554
571
|
catch (err) {
|
|
572
|
+
// An interrupt is not a failure: the truncated text is real output the user
|
|
573
|
+
// already heard part of, so it is persisted and marked rather than dropped.
|
|
574
|
+
const interruption = interruptHandle.interruption;
|
|
575
|
+
if (interruption || isAbortError(err)) {
|
|
576
|
+
await persistingChannel.flush({ interrupted: true });
|
|
577
|
+
await aiRunState.updateRun(runId, { status: 'interrupted' });
|
|
578
|
+
// Deliberately not awaited. A tool still running must not hold the stream
|
|
579
|
+
// open — the whole point of barge-in is that the agent stops now — so the
|
|
580
|
+
// note lands later and the next run on this thread waits for it instead.
|
|
581
|
+
if (storage) {
|
|
582
|
+
trackInterruptNote(threadId, persistOrphanedToolResults(interruptHandle, storage, threadId));
|
|
583
|
+
}
|
|
584
|
+
channel.send({
|
|
585
|
+
type: 'interrupted',
|
|
586
|
+
runId,
|
|
587
|
+
text: persistingChannel.fullText,
|
|
588
|
+
reason: interruption?.reason ?? 'user',
|
|
589
|
+
});
|
|
590
|
+
channel.send({ type: 'done' });
|
|
591
|
+
channel.close();
|
|
592
|
+
return persistingChannel.fullText;
|
|
593
|
+
}
|
|
555
594
|
for (const mw of aiMiddlewares) {
|
|
556
595
|
if (mw.onError) {
|
|
557
596
|
try {
|
|
@@ -561,9 +600,7 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
|
|
|
561
600
|
messages: runnerParams.messages,
|
|
562
601
|
});
|
|
563
602
|
}
|
|
564
|
-
catch {
|
|
565
|
-
// onError hooks must not affect error flow
|
|
566
|
-
}
|
|
603
|
+
catch { }
|
|
567
604
|
}
|
|
568
605
|
}
|
|
569
606
|
await aiRunState.updateRun(runId, {
|
|
@@ -578,6 +615,54 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
|
|
|
578
615
|
channel.close();
|
|
579
616
|
return persistingChannel.fullText;
|
|
580
617
|
}
|
|
618
|
+
finally {
|
|
619
|
+
interruptHandle.release();
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Stop an in-flight run on behalf of a caller, after checking the run is theirs.
|
|
624
|
+
*
|
|
625
|
+
* Unlike {@link resumeAIAgent} this needs no channel: it does not continue the
|
|
626
|
+
* stream, it ends one. The `interrupted` event and the truncated message are
|
|
627
|
+
* emitted by the original {@link streamAIAgent} call on its own channel, so this
|
|
628
|
+
* can be reached over a plain RPC while the stream is held open elsewhere —
|
|
629
|
+
* which is exactly the shape a voice barge-in needs.
|
|
630
|
+
*
|
|
631
|
+
* Ownership is the whole gate, deliberately without {@link assertAgentAuthorized}.
|
|
632
|
+
* Resuming re-enters the agent and approves a tool call, so a revoked grant must
|
|
633
|
+
* block it; stopping is the opposite — if a caller's access to an agent was
|
|
634
|
+
* revoked mid-run, being able to stop their own run is harmless and arguably
|
|
635
|
+
* what you want.
|
|
636
|
+
*
|
|
637
|
+
* Returns `false` when there was nothing to stop. Racing a run that finishes on
|
|
638
|
+
* its own is the normal case in voice, so it is not an error.
|
|
639
|
+
*/
|
|
640
|
+
export async function interruptAIAgent(input, params) {
|
|
641
|
+
const { aiRunState, logger } = getSingletonServices();
|
|
642
|
+
if (!aiRunState) {
|
|
643
|
+
throw new Error('AIRunStateService not available in singletonServices');
|
|
644
|
+
}
|
|
645
|
+
const run = await aiRunState.getRun(input.runId);
|
|
646
|
+
if (!run) {
|
|
647
|
+
throw new Error(`No run found for runId ${input.runId}`);
|
|
648
|
+
}
|
|
649
|
+
assertResourceOwner(resolveOwnerResourceId(params, agentSessionScope(run.agentName), run.resourceId), run.resourceId, 'run');
|
|
650
|
+
const stopped = signalRunInterrupt(input.runId, {
|
|
651
|
+
reason: input.reason ?? 'user',
|
|
652
|
+
});
|
|
653
|
+
// A run still marked `running` that this process cannot abort is executing on
|
|
654
|
+
// another instance. Returning a bare `false` there is indistinguishable from
|
|
655
|
+
// "it already finished", so the one deployment shape this registry does not
|
|
656
|
+
// cover fails silently — an agent that simply refuses to shut up, with nothing
|
|
657
|
+
// in the logs. Say so instead. See `signalRunInterrupt` for the fix (fan the
|
|
658
|
+
// interrupt out over eventHub so every instance tries locally).
|
|
659
|
+
if (!stopped && run.status === 'running') {
|
|
660
|
+
logger?.warn(`Could not interrupt run ${input.runId}: it is running in another process. ` +
|
|
661
|
+
'Interrupts are process-local; fan them out over eventHub to support multiple instances.');
|
|
662
|
+
}
|
|
663
|
+
// Reported after the abort so it names what is *still* running: aborting the
|
|
664
|
+
// model call does nothing to a tool already executing.
|
|
665
|
+
return { stopped, inFlightTools: getInFlightTools(input.runId) };
|
|
581
666
|
}
|
|
582
667
|
export async function resumeAIAgent(input, channel, params, options) {
|
|
583
668
|
const singletonServices = getSingletonServices();
|
|
@@ -589,16 +674,12 @@ export async function resumeAIAgent(input, channel, params, options) {
|
|
|
589
674
|
if (!run) {
|
|
590
675
|
throw new Error(`No run found for runId ${input.runId}`);
|
|
591
676
|
}
|
|
592
|
-
|
|
677
|
+
assertResourcePrincipalOwner(params, agentSessionScope(run.agentName), run.resourceId, 'run');
|
|
593
678
|
const pending = run.pendingApprovals?.find((p) => p.toolCallId === input.toolCallId);
|
|
594
679
|
if (!pending) {
|
|
595
680
|
throw new Error(`No pending approval for toolCallId ${input.toolCallId} on run ${input.runId}`);
|
|
596
681
|
}
|
|
597
682
|
const { agent, packageName, resolvedName } = resolveAgent(run.agentName);
|
|
598
|
-
// Gate before resolving the approval: recording it is a persisted side
|
|
599
|
-
// effect, so an unauthorized caller must not reach it. Run ownership alone is
|
|
600
|
-
// not enough — a grant revoked while the run was suspended must stop the
|
|
601
|
-
// caller from approving its pending tool calls.
|
|
602
683
|
await assertAgentAuthorized(agent, params, packageName);
|
|
603
684
|
await aiRunState.resolveApproval(input.toolCallId, input.approved ? 'approved' : 'denied');
|
|
604
685
|
const { storage } = resolveMemoryServices(agent, singletonServices);
|
|
@@ -639,11 +720,9 @@ export async function resumeAIAgent(input, channel, params, options) {
|
|
|
639
720
|
: pending.agentName,
|
|
640
721
|
result: denialResult,
|
|
641
722
|
});
|
|
642
|
-
// Check remaining pending approvals
|
|
643
723
|
const updatedRun = await aiRunState.getRun(run.runId);
|
|
644
724
|
const remaining = updatedRun?.pendingApprovals ?? [];
|
|
645
725
|
if (remaining.length > 0) {
|
|
646
|
-
// Still waiting for more approvals - don't continue step loop
|
|
647
726
|
channel.send({ type: 'done' });
|
|
648
727
|
channel.close();
|
|
649
728
|
return;
|
|
@@ -748,11 +827,9 @@ export async function resumeAIAgent(input, channel, params, options) {
|
|
|
748
827
|
...(isError ? { isError: true } : {}),
|
|
749
828
|
});
|
|
750
829
|
}
|
|
751
|
-
// Check remaining pending approvals after processing this one
|
|
752
830
|
const updatedRun = await aiRunState.getRun(run.runId);
|
|
753
831
|
const remaining = updatedRun?.pendingApprovals ?? [];
|
|
754
832
|
if (remaining.length > 0) {
|
|
755
|
-
// Still waiting for more approvals - don't continue step loop
|
|
756
833
|
channel.send({ type: 'done' });
|
|
757
834
|
channel.close();
|
|
758
835
|
return;
|
|
@@ -786,6 +863,8 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
|
|
|
786
863
|
}),
|
|
787
864
|
...(agent.aiMiddleware ?? []),
|
|
788
865
|
];
|
|
866
|
+
// One bag per run, shared by every middleware — see PikkuAIMiddlewareHooks.
|
|
867
|
+
const sharedNotes = {};
|
|
789
868
|
let modifiedMessages = trimmedMessages;
|
|
790
869
|
let modifiedInstructions = instructions;
|
|
791
870
|
for (const mw of aiMiddlewares) {
|
|
@@ -793,11 +872,17 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
|
|
|
793
872
|
const result = await mw.modifyInput(singletonServices, {
|
|
794
873
|
messages: modifiedMessages,
|
|
795
874
|
instructions: modifiedInstructions,
|
|
875
|
+
shared: sharedNotes,
|
|
796
876
|
});
|
|
797
877
|
modifiedMessages = result.messages;
|
|
798
878
|
modifiedInstructions = result.instructions;
|
|
799
879
|
}
|
|
800
880
|
}
|
|
881
|
+
// Resuming is as interruptible as the first turn. It is the same person
|
|
882
|
+
// listening to the same voice, and after an approval it is where most of the
|
|
883
|
+
// reply actually gets spoken — an approved delete is followed by the agent
|
|
884
|
+
// talking about it, and that is a normal thing to talk over.
|
|
885
|
+
const interruptHandle = registerInterruptibleRun(run.runId);
|
|
801
886
|
const streamMiddleware = aiMiddlewares
|
|
802
887
|
.filter((mw) => mw.modifyOutputStream)
|
|
803
888
|
.map((mw) => {
|
|
@@ -809,6 +894,11 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
|
|
|
809
894
|
event,
|
|
810
895
|
allEvents,
|
|
811
896
|
state,
|
|
897
|
+
shared: sharedNotes,
|
|
898
|
+
// Sends downstream directly, so a hook can hand back the fast event
|
|
899
|
+
// now and push the slow one when it is ready.
|
|
900
|
+
emit: next,
|
|
901
|
+
signal: interruptHandle.signal,
|
|
812
902
|
});
|
|
813
903
|
if (result == null)
|
|
814
904
|
return;
|
|
@@ -844,10 +934,13 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
|
|
|
844
934
|
tools: resumeTools,
|
|
845
935
|
maxSteps: 1,
|
|
846
936
|
toolChoice: (agent.toolChoice ?? 'auto'),
|
|
937
|
+
providerOptions: agent.providerOptions,
|
|
847
938
|
outputSchema: meta?.outputSchema
|
|
848
939
|
? pikkuState(packageName, 'misc', 'schemas').get(meta.outputSchema)
|
|
849
940
|
: undefined,
|
|
850
941
|
};
|
|
942
|
+
runnerParams.abortSignal = interruptHandle.signal;
|
|
943
|
+
runnerParams.tools = trackToolExecution(runnerParams.tools, interruptHandle);
|
|
851
944
|
try {
|
|
852
945
|
const loopResult = await runStreamStepLoop({
|
|
853
946
|
agent,
|
|
@@ -857,7 +950,6 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
|
|
|
857
950
|
streamChannel: wrappedChannel,
|
|
858
951
|
persistingChannel,
|
|
859
952
|
channel,
|
|
860
|
-
runId: run.runId,
|
|
861
953
|
aiMiddlewares,
|
|
862
954
|
});
|
|
863
955
|
if (loopResult.outcome === 'approval') {
|
|
@@ -869,10 +961,33 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
|
|
|
869
961
|
return;
|
|
870
962
|
}
|
|
871
963
|
await postStreamCleanup(persistingChannel, aiMiddlewares, singletonServices, runnerParams.messages, aiRunState, run.runId);
|
|
872
|
-
|
|
964
|
+
// Through the middleware, for the same reason as the first turn — and it
|
|
965
|
+
// matters more here. After an approval, most of what gets spoken is the
|
|
966
|
+
// agent talking about what it just did, so this is the half of the reply a
|
|
967
|
+
// dropped flush would silence.
|
|
968
|
+
await wrappedChannel.send({ type: 'done' });
|
|
873
969
|
channel.close();
|
|
874
970
|
}
|
|
875
971
|
catch (err) {
|
|
972
|
+
// Same reasoning as the first turn: an interrupt is not a failure, and the
|
|
973
|
+
// part of the reply the user already heard is real output.
|
|
974
|
+
const interruption = interruptHandle.interruption;
|
|
975
|
+
if (interruption || isAbortError(err)) {
|
|
976
|
+
await persistingChannel.flush({ interrupted: true });
|
|
977
|
+
await aiRunState.updateRun(run.runId, { status: 'interrupted' });
|
|
978
|
+
if (storage) {
|
|
979
|
+
trackInterruptNote(run.threadId, persistOrphanedToolResults(interruptHandle, storage, run.threadId));
|
|
980
|
+
}
|
|
981
|
+
channel.send({
|
|
982
|
+
type: 'interrupted',
|
|
983
|
+
runId: run.runId,
|
|
984
|
+
text: persistingChannel.fullText,
|
|
985
|
+
reason: interruption?.reason ?? 'user',
|
|
986
|
+
});
|
|
987
|
+
channel.send({ type: 'done' });
|
|
988
|
+
channel.close();
|
|
989
|
+
return;
|
|
990
|
+
}
|
|
876
991
|
for (const mw of aiMiddlewares) {
|
|
877
992
|
if (mw.onError) {
|
|
878
993
|
try {
|
|
@@ -882,9 +997,7 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
|
|
|
882
997
|
messages: runnerParams.messages,
|
|
883
998
|
});
|
|
884
999
|
}
|
|
885
|
-
catch {
|
|
886
|
-
// onError hooks must not affect error flow
|
|
887
|
-
}
|
|
1000
|
+
catch { }
|
|
888
1001
|
}
|
|
889
1002
|
}
|
|
890
1003
|
await aiRunState.updateRun(run.runId, {
|
|
@@ -898,4 +1011,7 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
|
|
|
898
1011
|
channel.send({ type: 'done' });
|
|
899
1012
|
channel.close();
|
|
900
1013
|
}
|
|
1014
|
+
finally {
|
|
1015
|
+
interruptHandle.release();
|
|
1016
|
+
}
|
|
901
1017
|
}
|