@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
|
@@ -20,6 +20,7 @@ import { pikkuState, getSingletonServices } from '../../pikku-state.js'
|
|
|
20
20
|
import { createMiddlewareSessionWireProps } from '../../services/user-session-service.js'
|
|
21
21
|
import type { SessionService } from '../../services/user-session-service.js'
|
|
22
22
|
import { randomUUID } from './ai-agent-utils.js'
|
|
23
|
+
import { awaitPendingInterruptNote } from './ai-agent-interrupt.js'
|
|
23
24
|
import { streamAIAgent } from './ai-agent-stream.js'
|
|
24
25
|
import { runAIAgent } from './ai-agent-runner.js'
|
|
25
26
|
import {
|
|
@@ -38,44 +39,38 @@ export type RunAIAgentParams = {
|
|
|
38
39
|
sessionService?: SessionService<CoreUserSession>
|
|
39
40
|
/** Credential accessor for the current request — used to read per-user overrides (e.g. AI_API_KEY). */
|
|
40
41
|
getCredential?: <T = unknown>(name: string) => T | null | Promise<T | null>
|
|
42
|
+
/** Ephemeral owner identity minted for a sessionless request; never client-supplied, never reused across requests. */
|
|
43
|
+
anonymousOwnerResourceId?: string
|
|
41
44
|
}
|
|
42
45
|
|
|
43
|
-
|
|
44
|
-
* The ownership key for a thread/run: the trusted principal (the authenticated
|
|
45
|
-
* `session.userId` for `'user'` scope, or `session.orgId` for `'org'` scope)
|
|
46
|
-
* composed with the client-supplied `resourceId` as a sub-partition —
|
|
47
|
-
* `principal:resourceId`. Because the principal is always the prefix, a client
|
|
48
|
-
* `resourceId` can sub-divide within the caller's own boundary but can never
|
|
49
|
-
* widen access to another user's or org's threads.
|
|
50
|
-
*
|
|
51
|
-
* Idempotent: a value that is already within the caller's namespace (top-level
|
|
52
|
-
* re-entry, sub-agent recursion, or resume, which all pass an already-composite
|
|
53
|
-
* `resourceId`) is returned unchanged rather than double-composed.
|
|
54
|
-
*
|
|
55
|
-
* `'org'` scope with no session org throws {@link ForbiddenError} — falling back
|
|
56
|
-
* to a bare/shared key would leak across organizations. Sessionless `'user'`
|
|
57
|
-
* wirings have no trusted principal and fall back to the requested `resourceId`
|
|
58
|
-
* as a best-effort partition key.
|
|
59
|
-
*/
|
|
60
|
-
export function resolveOwnerResourceId(
|
|
46
|
+
export function resolveSessionPrincipal(
|
|
61
47
|
params: RunAIAgentParams,
|
|
62
|
-
sessionScope: SessionScope | undefined
|
|
63
|
-
|
|
64
|
-
): string {
|
|
48
|
+
sessionScope: SessionScope | undefined
|
|
49
|
+
): string | undefined {
|
|
65
50
|
const session = params.sessionService?.get()
|
|
66
|
-
let principal: string | undefined
|
|
67
51
|
if ((sessionScope ?? 'user') === 'org') {
|
|
68
52
|
if (!session?.orgId) {
|
|
69
53
|
throw new ForbiddenError(
|
|
70
54
|
'This agent is org-scoped but the session has no organization'
|
|
71
55
|
)
|
|
72
56
|
}
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
|
|
57
|
+
return session.orgId
|
|
58
|
+
}
|
|
59
|
+
return session?.userId
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function resolveOwnerResourceId(
|
|
63
|
+
params: RunAIAgentParams,
|
|
64
|
+
sessionScope: SessionScope | undefined,
|
|
65
|
+
requestedResourceId: string
|
|
66
|
+
): string {
|
|
67
|
+
const principal = resolveSessionPrincipal(params, sessionScope)
|
|
68
|
+
|
|
69
|
+
if (!principal) {
|
|
70
|
+
params.anonymousOwnerResourceId ??= `anon-${randomUUID()}`
|
|
71
|
+
return params.anonymousOwnerResourceId
|
|
76
72
|
}
|
|
77
73
|
|
|
78
|
-
if (!principal) return requestedResourceId
|
|
79
74
|
if (
|
|
80
75
|
requestedResourceId === principal ||
|
|
81
76
|
requestedResourceId.startsWith(`${principal}:`)
|
|
@@ -85,16 +80,22 @@ export function resolveOwnerResourceId(
|
|
|
85
80
|
return `${principal}:${requestedResourceId}`
|
|
86
81
|
}
|
|
87
82
|
|
|
88
|
-
|
|
83
|
+
export function assertResourcePrincipalOwner(
|
|
84
|
+
params: RunAIAgentParams,
|
|
85
|
+
sessionScope: SessionScope | undefined,
|
|
86
|
+
storedResourceId: string,
|
|
87
|
+
kind: 'thread' | 'run'
|
|
88
|
+
): void {
|
|
89
|
+
const principal = resolveSessionPrincipal(params, sessionScope)
|
|
90
|
+
if (!principal || !isOwnedByPrincipal(storedResourceId, principal)) {
|
|
91
|
+
throw new ForbiddenError(`Not authorized to access this ${kind}`)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
89
95
|
export function agentSessionScope(agentName: string): SessionScope {
|
|
90
96
|
return resolveAgent(agentName).agent.sessionScope ?? 'user'
|
|
91
97
|
}
|
|
92
98
|
|
|
93
|
-
/**
|
|
94
|
-
* Enforce that a stored thread/run belongs to the caller's owner resource,
|
|
95
|
-
* throwing {@link ForbiddenError} (without echoing the id, to avoid an
|
|
96
|
-
* existence oracle) on a mismatch.
|
|
97
|
-
*/
|
|
98
99
|
export function assertResourceOwner(
|
|
99
100
|
ownerResourceId: string,
|
|
100
101
|
storedResourceId: string,
|
|
@@ -105,7 +106,6 @@ export function assertResourceOwner(
|
|
|
105
106
|
}
|
|
106
107
|
}
|
|
107
108
|
|
|
108
|
-
/** A session's trusted principals, in the order they may be read as. */
|
|
109
109
|
export function sessionPrincipals(
|
|
110
110
|
session: { userId?: string; orgId?: string } | undefined
|
|
111
111
|
): string[] {
|
|
@@ -114,12 +114,6 @@ export function sessionPrincipals(
|
|
|
114
114
|
)
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
/**
|
|
118
|
-
* Whether `storedResourceId` belongs to `principal` under the composition
|
|
119
|
-
* {@link resolveOwnerResourceId} performs — either the bare principal or one of
|
|
120
|
-
* its `principal:` sub-partitions. The `:` is required so that `alice` does not
|
|
121
|
-
* match a `alice-evil:…` lookalike.
|
|
122
|
-
*/
|
|
123
117
|
export function isOwnedByPrincipal(
|
|
124
118
|
storedResourceId: string,
|
|
125
119
|
principal: string
|
|
@@ -130,42 +124,18 @@ export function isOwnedByPrincipal(
|
|
|
130
124
|
)
|
|
131
125
|
}
|
|
132
126
|
|
|
133
|
-
/**
|
|
134
|
-
* The `owners` constraint to pass to `AgentRunService.listThreads` for a caller.
|
|
135
|
-
*
|
|
136
|
-
* Returns `undefined` — not `[]` — for a session with no principal, because an
|
|
137
|
-
* empty list means "match nothing" whereas a sessionless deployment (agent
|
|
138
|
-
* `no-auth`) has no ownership model to constrain by. Keeping that carve-out here
|
|
139
|
-
* rather than at each call site stops it from being re-derived inconsistently.
|
|
140
|
-
*/
|
|
141
127
|
export function threadOwnerConstraint(
|
|
142
128
|
session: { userId?: string; orgId?: string } | undefined
|
|
143
|
-
): string[]
|
|
144
|
-
|
|
145
|
-
return principals.length > 0 ? principals : undefined
|
|
129
|
+
): string[] {
|
|
130
|
+
return sessionPrincipals(session)
|
|
146
131
|
}
|
|
147
132
|
|
|
148
|
-
/**
|
|
149
|
-
* Whether a stored thread/run may be read by the caller. Shaped as a predicate
|
|
150
|
-
* so it can back a `pikkuPermission` — authorization belongs in a function's
|
|
151
|
-
* `permissions` field, never in its body.
|
|
152
|
-
*
|
|
153
|
-
* Unlike {@link assertResourceOwner}, which compares against a single composed
|
|
154
|
-
* owner key on the run path, this guards the thread-management reads where the
|
|
155
|
-
* caller supplies only a `threadId` — so ownership has to be derived from the
|
|
156
|
-
* session rather than from the request.
|
|
157
|
-
*
|
|
158
|
-
* A session with no principal means the deployment opted out of authorization
|
|
159
|
-
* (agent `no-auth`), so there is no ownership model to enforce and access is not
|
|
160
|
-
* gated — mirroring {@link resolveOwnerResourceId}'s sessionless fallback to a
|
|
161
|
-
* bare resourceId.
|
|
162
|
-
*/
|
|
163
133
|
export function canAccessThread(
|
|
164
134
|
storedResourceId: string,
|
|
165
135
|
session: { userId?: string; orgId?: string } | undefined
|
|
166
136
|
): boolean {
|
|
167
137
|
const principals = sessionPrincipals(session)
|
|
168
|
-
if (principals.length === 0) return
|
|
138
|
+
if (principals.length === 0) return false
|
|
169
139
|
return principals.some((principal) =>
|
|
170
140
|
isOwnedByPrincipal(storedResourceId, principal)
|
|
171
141
|
)
|
|
@@ -173,24 +143,22 @@ export function canAccessThread(
|
|
|
173
143
|
|
|
174
144
|
export type StreamAIAgentOptions = {
|
|
175
145
|
requiresToolApproval?: 'all' | 'explicit' | false
|
|
176
|
-
/**
|
|
177
|
-
* Invoked as soon as the run's AIRunStateService id exists, so transport
|
|
178
|
-
* wrappers (e.g. the AG-UI bridge) can stamp the real runId on RUN_STARTED.
|
|
179
|
-
*/
|
|
180
146
|
onRunCreated?: (runId: string) => void
|
|
181
147
|
}
|
|
182
148
|
|
|
183
|
-
/**
|
|
184
|
-
* Non-forgeable brand for the sub-agent approval marker. Only framework code
|
|
185
|
-
* (the delegating sub-agent tools below) sets this Symbol on a tool result; a
|
|
186
|
-
* sub-agent's LLM-shaped `result.object` — plain JSON — cannot carry a Symbol,
|
|
187
|
-
* so `checkForApprovals` trusts the brand rather than the `__approvalRequired`
|
|
188
|
-
* string key to decide an approval must be surfaced.
|
|
189
|
-
*/
|
|
190
149
|
export const APPROVAL_REQUIRED: unique symbol = Symbol(
|
|
191
150
|
'pikku.ai.approvalRequired'
|
|
192
151
|
)
|
|
193
152
|
|
|
153
|
+
/**
|
|
154
|
+
* In-process brand proving a credential request was produced by pikku itself and
|
|
155
|
+
* not by tool output an attacker can influence. Never serialized — a value that
|
|
156
|
+
* has crossed a JSON boundary has lost the brand and is treated as untrusted.
|
|
157
|
+
*/
|
|
158
|
+
export const CREDENTIAL_REQUIRED: unique symbol = Symbol(
|
|
159
|
+
'pikku.ai.credentialRequired'
|
|
160
|
+
)
|
|
161
|
+
|
|
194
162
|
export class ToolApprovalRequired extends PikkuError {
|
|
195
163
|
public readonly toolCallId: string
|
|
196
164
|
public readonly toolName: string
|
|
@@ -254,10 +222,6 @@ export interface AddonCredentialRequirement {
|
|
|
254
222
|
oauth2: boolean
|
|
255
223
|
}
|
|
256
224
|
|
|
257
|
-
/**
|
|
258
|
-
* Given a list of tool names (e.g. ["oauth-api:getProfile"]),
|
|
259
|
-
* returns the wire OAuth credentials required by their addons.
|
|
260
|
-
*/
|
|
261
225
|
export function getAddonCredentialRequirements(
|
|
262
226
|
toolNames: string[]
|
|
263
227
|
): AddonCredentialRequirement[] {
|
|
@@ -333,26 +297,6 @@ export const resolveAgent = (
|
|
|
333
297
|
throw new Error(`AI agent not found: ${agentName}`)
|
|
334
298
|
}
|
|
335
299
|
|
|
336
|
-
/**
|
|
337
|
-
* Enforces an agent's own authorization before it runs: session presence
|
|
338
|
-
* (`auth`), then `scopes`, then `permissions`.
|
|
339
|
-
*
|
|
340
|
-
* The ordering mirrors the function runner — scopes are an AND gate checked
|
|
341
|
-
* first, so they can only ever narrow access, and a missing scope short-circuits
|
|
342
|
-
* before any permission function does I/O.
|
|
343
|
-
*
|
|
344
|
-
* `auth` follows `pikkuSessionlessFunc` rather than `pikkuFunc`: a session is
|
|
345
|
-
* required only when `auth: true` is set explicitly. An agent is normally
|
|
346
|
-
* reached from a function that has already enforced its own auth, and agents are
|
|
347
|
-
* also run from genuinely sessionless contexts (crons, queue workers), so
|
|
348
|
-
* requiring a session by default would reject those without adding a meaningful
|
|
349
|
-
* gate. `scopes` and `permissions` are always enforced when declared.
|
|
350
|
-
*
|
|
351
|
-
* Globals are evaluated here too (via {@link runPermissions}) rather than being
|
|
352
|
-
* assumed to have already run: an agent is reachable from entry points that do
|
|
353
|
-
* not go through the function runner, and re-evaluating an AND gate of
|
|
354
|
-
* side-effect-free predicates is idempotent.
|
|
355
|
-
*/
|
|
356
300
|
export async function assertAgentAuthorized(
|
|
357
301
|
agent: CoreAIAgent,
|
|
358
302
|
params: RunAIAgentParams,
|
|
@@ -472,20 +416,10 @@ export function createScopedChannel(
|
|
|
472
416
|
setState: (s) => parent.setState(s),
|
|
473
417
|
getState: () => parent.getState(),
|
|
474
418
|
clearState: () => parent.clearState(),
|
|
419
|
+
remote: (funcName: string, data?: unknown) => parent.remote(funcName, data),
|
|
475
420
|
}
|
|
476
421
|
}
|
|
477
422
|
|
|
478
|
-
/**
|
|
479
|
-
* Build the run input for a delegated sub-agent.
|
|
480
|
-
*
|
|
481
|
-
* `context` is the PARENT run's identifier block (the "Current context" text
|
|
482
|
-
* with organizationId, project/stage ids). A sub-agent's tool-call schema only
|
|
483
|
-
* carries { message, session }, so unless the sub-agent inherits the parent's
|
|
484
|
-
* context it never sees the authoritative ids — it depends on the model
|
|
485
|
-
* re-typing them into `message`, which weak models botch, causing
|
|
486
|
-
* schema/permission rejections and retry loops. Forwarding it here is the
|
|
487
|
-
* regression this seam guards.
|
|
488
|
-
*/
|
|
489
423
|
export function buildSubAgentRunInput(
|
|
490
424
|
message: string,
|
|
491
425
|
threadId: string,
|
|
@@ -504,13 +438,6 @@ export async function buildToolDefs(
|
|
|
504
438
|
streamContext?: StreamContext,
|
|
505
439
|
aiMiddlewares?: PikkuAIMiddlewareHooks[],
|
|
506
440
|
agentMode?: 'delegate' | 'supervise',
|
|
507
|
-
// The parent run's `context` (the "Current context" identifier block). A
|
|
508
|
-
// delegated sub-agent's tool-call input schema only carries { message,
|
|
509
|
-
// session }, so without inheriting this the sub-agent never sees the
|
|
510
|
-
// authoritative ids (organizationId, project/stage ids) — it depends on the
|
|
511
|
-
// model re-typing them into `message`, which weak models botch, causing
|
|
512
|
-
// schema/permission rejections and retry loops. Forward it so the sub-agent
|
|
513
|
-
// gets the same context block in its instructions.
|
|
514
441
|
parentContext?: string
|
|
515
442
|
): Promise<{ tools: AIAgentToolDef[]; missingRpcs: string[] }> {
|
|
516
443
|
const singletonServices = getSingletonServices()
|
|
@@ -522,7 +449,23 @@ export async function buildToolDefs(
|
|
|
522
449
|
const meta = pikkuState(packageName, 'agent', 'agentsMeta')[agentName]
|
|
523
450
|
if (!meta) return { tools, missingRpcs }
|
|
524
451
|
|
|
525
|
-
|
|
452
|
+
/**
|
|
453
|
+
* A tool's description is what the model is told it does, and the main thing
|
|
454
|
+
* it chooses between tools on. It does not survive into the meta registered at
|
|
455
|
+
* boot: `description` is classed as a verbose field, so the bundled copy has
|
|
456
|
+
* it stripped and `fnMeta.description` is always undefined — every tool was
|
|
457
|
+
* being offered under its own bare name regardless of what its author wrote.
|
|
458
|
+
*
|
|
459
|
+
* `getFunctionsMeta` reads the verbose file and falls back to the minimal one,
|
|
460
|
+
* recovering the authored description wherever the generated `.pikku`
|
|
461
|
+
* directory is readable. Where it is not — no `metaService`, or a deployment
|
|
462
|
+
* shipping only the stripped copy — tools fall back to their name, which is
|
|
463
|
+
* what they did before this lookup existed.
|
|
464
|
+
*/
|
|
465
|
+
const describedFunctions = await singletonServices.metaService
|
|
466
|
+
?.getFunctionsMeta()
|
|
467
|
+
.catch(() => undefined)
|
|
468
|
+
|
|
526
469
|
const session = params.sessionService
|
|
527
470
|
? await params.sessionService.get()
|
|
528
471
|
: null
|
|
@@ -563,10 +506,6 @@ export async function buildToolDefs(
|
|
|
563
506
|
continue
|
|
564
507
|
}
|
|
565
508
|
|
|
566
|
-
// Filter out tools the user doesn't have auth for. The `pikkuAuth` brand
|
|
567
|
-
// only survives on the live permission objects in the function config, so
|
|
568
|
-
// the check reads those rather than the metadata (whose by-name registry
|
|
569
|
-
// is never populated, which would let every gated tool through).
|
|
570
509
|
if (fnMeta.permissions?.length) {
|
|
571
510
|
if (!session) continue
|
|
572
511
|
const funcConfig = pikkuFuncId
|
|
@@ -598,7 +537,6 @@ export async function buildToolDefs(
|
|
|
598
537
|
approvalPolicy === 'all' ||
|
|
599
538
|
(approvalPolicy === 'explicit' && fnMeta?.approvalRequired)
|
|
600
539
|
|
|
601
|
-
// Build approvalDescriptionFn if the function has an approvalDescription configured
|
|
602
540
|
let approvalDescriptionFn:
|
|
603
541
|
| ((input: unknown) => Promise<string>)
|
|
604
542
|
| undefined
|
|
@@ -638,10 +576,14 @@ export async function buildToolDefs(
|
|
|
638
576
|
|
|
639
577
|
tools.push({
|
|
640
578
|
name: toolName.replaceAll('@', '_').replaceAll(':', '__'),
|
|
641
|
-
description:
|
|
579
|
+
description:
|
|
580
|
+
describedFunctions?.[pikkuFuncId]?.description ||
|
|
581
|
+
fnMeta?.description ||
|
|
582
|
+
toolName,
|
|
642
583
|
inputSchema,
|
|
643
584
|
needsApproval: needsApproval || undefined,
|
|
644
585
|
approvalDescriptionFn,
|
|
586
|
+
readonly: fnMeta?.readonly || undefined,
|
|
645
587
|
execute: async (toolInput: unknown) => {
|
|
646
588
|
const wire: PikkuRawWire = params.sessionService
|
|
647
589
|
? { ...createMiddlewareSessionWireProps(params.sessionService) }
|
|
@@ -669,8 +611,6 @@ export async function buildToolDefs(
|
|
|
669
611
|
continue
|
|
670
612
|
}
|
|
671
613
|
|
|
672
|
-
// Filter out sub-agents the user doesn't have auth for, reading the live
|
|
673
|
-
// agent config for the same reason the tool path does.
|
|
674
614
|
if (subMeta.permissions?.length) {
|
|
675
615
|
if (!session) continue
|
|
676
616
|
const subAgent = pikkuState(null, 'agent', 'agents').get(subAgentName)
|
|
@@ -726,8 +666,6 @@ export async function buildToolDefs(
|
|
|
726
666
|
subAgentName,
|
|
727
667
|
session
|
|
728
668
|
)
|
|
729
|
-
// In supervise mode, suppress sub-agent text from reaching the client.
|
|
730
|
-
// Approvals still flow through normally.
|
|
731
669
|
const effectiveChannel = isDelegate
|
|
732
670
|
? subChannel
|
|
733
671
|
: {
|
|
@@ -773,7 +711,6 @@ export async function buildToolDefs(
|
|
|
773
711
|
return resultText
|
|
774
712
|
}
|
|
775
713
|
|
|
776
|
-
// No stream context: sub-agent runs non-streaming
|
|
777
714
|
const result = await runAIAgent(
|
|
778
715
|
subAgentName,
|
|
779
716
|
buildSubAgentRunInput(message, threadId, resourceId, parentContext),
|
|
@@ -863,17 +800,19 @@ export async function buildToolDefs(
|
|
|
863
800
|
}
|
|
864
801
|
}
|
|
865
802
|
|
|
866
|
-
// A tool's execute() can throw (bad input, RPC failure, DB error, ...). The AI
|
|
867
|
-
// SDK catches that at the tool-call boundary and turns it into a conversational
|
|
868
|
-
// "tool error" reply — without this, the exception never reaches pikku's own
|
|
869
|
-
// logger, so a failing tool is undiagnosable server-side. Log unconditionally,
|
|
870
|
-
// even when no aiMiddleware afterToolCall hook is registered to see it.
|
|
871
803
|
for (const tool of tools) {
|
|
872
804
|
const originalExecute = tool.execute
|
|
873
805
|
tool.execute = async (toolInput: unknown) => {
|
|
874
806
|
try {
|
|
875
807
|
return await originalExecute(toolInput)
|
|
876
|
-
} catch (err) {
|
|
808
|
+
} catch (err: any) {
|
|
809
|
+
if (err?.payload?.error === 'missing_credential') {
|
|
810
|
+
return {
|
|
811
|
+
[CREDENTIAL_REQUIRED]: true,
|
|
812
|
+
__credentialRequired: true,
|
|
813
|
+
...err.payload,
|
|
814
|
+
}
|
|
815
|
+
}
|
|
877
816
|
singletonServices.logger.error(
|
|
878
817
|
`AI agent tool '${tool.name}' threw during execute()`,
|
|
879
818
|
err
|
|
@@ -1001,6 +940,11 @@ export async function prepareAgentRun(
|
|
|
1001
940
|
|
|
1002
941
|
let messages: AIMessage[] = []
|
|
1003
942
|
if (storage) {
|
|
943
|
+
// A tool whose run was interrupted may still be writing its result to this
|
|
944
|
+
// thread. In voice the next turn lands within a second or two, so without
|
|
945
|
+
// this the model would load context that is missing the very thing it is
|
|
946
|
+
// about to be asked about.
|
|
947
|
+
await awaitPendingInterruptNote(threadId)
|
|
1004
948
|
messages = await storage.getMessages(threadId, {
|
|
1005
949
|
lastN: memoryConfig?.lastMessages ?? 20,
|
|
1006
950
|
})
|
|
@@ -1015,7 +959,13 @@ export async function prepareAgentRun(
|
|
|
1015
959
|
|
|
1016
960
|
const userContent: AIMessage['content'] = input.attachments?.length
|
|
1017
961
|
? [
|
|
1018
|
-
|
|
962
|
+
// Omitted when there is nothing to say. An attachment on its own is a
|
|
963
|
+
// real turn — a spoken one carries audio and no text at all — and an
|
|
964
|
+
// empty text part alongside it is a part providers are entitled to
|
|
965
|
+
// reject, for a caller who never wrote one.
|
|
966
|
+
...(input.message
|
|
967
|
+
? [{ type: 'text' as const, text: input.message }]
|
|
968
|
+
: []),
|
|
1019
969
|
...input.attachments.map(
|
|
1020
970
|
(a) =>
|
|
1021
971
|
({
|
|
@@ -1060,7 +1010,6 @@ export async function prepareAgentRun(
|
|
|
1060
1010
|
|
|
1061
1011
|
const resolved = resolveModelConfig(resolvedName, agent)
|
|
1062
1012
|
|
|
1063
|
-
// Per-request overrides
|
|
1064
1013
|
if (input.model) {
|
|
1065
1014
|
resolved.model = resolveModelConfig(resolvedName, {
|
|
1066
1015
|
...agent,
|
|
@@ -1081,6 +1030,7 @@ export async function prepareAgentRun(
|
|
|
1081
1030
|
tools,
|
|
1082
1031
|
maxSteps: 1,
|
|
1083
1032
|
toolChoice: agent.toolChoice ?? 'auto',
|
|
1033
|
+
providerOptions: agent.providerOptions,
|
|
1084
1034
|
outputSchema,
|
|
1085
1035
|
}
|
|
1086
1036
|
|
|
@@ -1,16 +1,56 @@
|
|
|
1
1
|
import { beforeEach, describe, test } from 'node:test'
|
|
2
2
|
import assert from 'node:assert/strict'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
resetPikkuState,
|
|
6
|
+
pikkuState,
|
|
7
|
+
setSingletonServices,
|
|
8
|
+
} from '../../pikku-state.js'
|
|
5
9
|
import {
|
|
6
10
|
addAIAgent,
|
|
7
11
|
approveAIAgent,
|
|
8
12
|
getAIAgents,
|
|
9
13
|
getAIAgentsMeta,
|
|
10
14
|
} from './ai-agent-registry.js'
|
|
15
|
+
import { clearPermissionsCache } from '../../permissions.js'
|
|
16
|
+
import { ForbiddenError, MissingScopeError } from '../../errors/errors.js'
|
|
17
|
+
import type { CoreAIAgent } from './ai-agent.types.js'
|
|
18
|
+
import type { CoreUserSession } from '../../types/core.types.js'
|
|
19
|
+
|
|
20
|
+
const logger = {
|
|
21
|
+
debug: () => {},
|
|
22
|
+
info: () => {},
|
|
23
|
+
warn: () => {},
|
|
24
|
+
error: () => {},
|
|
25
|
+
} as any
|
|
26
|
+
|
|
27
|
+
const registerAgent = (
|
|
28
|
+
agentName: string,
|
|
29
|
+
overrides: Partial<CoreAIAgent> = {}
|
|
30
|
+
) => {
|
|
31
|
+
const agent = {
|
|
32
|
+
name: agentName,
|
|
33
|
+
description: `${agentName} description`,
|
|
34
|
+
goal: `${agentName} goal`,
|
|
35
|
+
model: 'test/test-model',
|
|
36
|
+
...overrides,
|
|
37
|
+
} as CoreAIAgent
|
|
38
|
+
pikkuState(null, 'agent', 'agents').set(agentName, agent)
|
|
39
|
+
pikkuState(null, 'agent', 'agentsMeta')[agentName] = { ...agent } as any
|
|
40
|
+
return agent
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const sessionService = (session: CoreUserSession | undefined) =>
|
|
44
|
+
({
|
|
45
|
+
get: () => session,
|
|
46
|
+
setInitial: () => {},
|
|
47
|
+
sessionChanged: false,
|
|
48
|
+
}) as any
|
|
11
49
|
|
|
12
50
|
beforeEach(() => {
|
|
13
51
|
resetPikkuState()
|
|
52
|
+
clearPermissionsCache()
|
|
53
|
+
setSingletonServices({ logger } as any)
|
|
14
54
|
})
|
|
15
55
|
|
|
16
56
|
describe('addAIAgent', () => {
|
|
@@ -70,7 +110,13 @@ describe('addAIAgent', () => {
|
|
|
70
110
|
})
|
|
71
111
|
|
|
72
112
|
describe('approveAIAgent', () => {
|
|
113
|
+
const ownerParams = {
|
|
114
|
+
sessionService: sessionService({ userId: 'resource-1' } as CoreUserSession),
|
|
115
|
+
} as any
|
|
116
|
+
|
|
73
117
|
test('throws when run state service is missing, run is missing, or run is not suspended', async () => {
|
|
118
|
+
registerAgent('agent')
|
|
119
|
+
|
|
74
120
|
await assert.rejects(() => approveAIAgent(null as any, 'run-1', []), {
|
|
75
121
|
message: 'AIRunStateService not available',
|
|
76
122
|
})
|
|
@@ -83,7 +129,9 @@ describe('approveAIAgent', () => {
|
|
|
83
129
|
updateRun: async () => {},
|
|
84
130
|
} as any,
|
|
85
131
|
'run-1',
|
|
86
|
-
[]
|
|
132
|
+
[],
|
|
133
|
+
undefined,
|
|
134
|
+
ownerParams
|
|
87
135
|
),
|
|
88
136
|
{
|
|
89
137
|
message: 'Run not found: run-1',
|
|
@@ -111,7 +159,9 @@ describe('approveAIAgent', () => {
|
|
|
111
159
|
updateRun: async () => {},
|
|
112
160
|
} as any,
|
|
113
161
|
'run-1',
|
|
114
|
-
[]
|
|
162
|
+
[],
|
|
163
|
+
undefined,
|
|
164
|
+
ownerParams
|
|
115
165
|
),
|
|
116
166
|
{
|
|
117
167
|
message: 'Run is not suspended: completed',
|
|
@@ -120,6 +170,7 @@ describe('approveAIAgent', () => {
|
|
|
120
170
|
})
|
|
121
171
|
|
|
122
172
|
test('rejects approval when run agent does not match expected agent', async () => {
|
|
173
|
+
registerAgent('internal-agent')
|
|
123
174
|
const aiRunState = {
|
|
124
175
|
getRun: async () => ({
|
|
125
176
|
runId: 'run-1',
|
|
@@ -141,7 +192,8 @@ describe('approveAIAgent', () => {
|
|
|
141
192
|
aiRunState,
|
|
142
193
|
'run-1',
|
|
143
194
|
[{ toolCallId: 'call-1', approved: true }],
|
|
144
|
-
'public-agent'
|
|
195
|
+
'public-agent',
|
|
196
|
+
ownerParams
|
|
145
197
|
),
|
|
146
198
|
{
|
|
147
199
|
message:
|
|
@@ -151,6 +203,7 @@ describe('approveAIAgent', () => {
|
|
|
151
203
|
})
|
|
152
204
|
|
|
153
205
|
test('marks run resumed when at least one approval is granted', async () => {
|
|
206
|
+
registerAgent('assistant')
|
|
154
207
|
const updates: any[] = []
|
|
155
208
|
const result = await approveAIAgent(
|
|
156
209
|
{
|
|
@@ -186,7 +239,9 @@ describe('approveAIAgent', () => {
|
|
|
186
239
|
[
|
|
187
240
|
{ toolCallId: 'call-1', approved: true },
|
|
188
241
|
{ toolCallId: 'call-3', approved: false },
|
|
189
|
-
]
|
|
242
|
+
],
|
|
243
|
+
undefined,
|
|
244
|
+
ownerParams
|
|
190
245
|
)
|
|
191
246
|
|
|
192
247
|
assert.deepEqual(updates, [
|
|
@@ -207,6 +262,7 @@ describe('approveAIAgent', () => {
|
|
|
207
262
|
})
|
|
208
263
|
|
|
209
264
|
test('keeps run suspended when nothing is approved', async () => {
|
|
265
|
+
registerAgent('assistant')
|
|
210
266
|
const updates: any[] = []
|
|
211
267
|
const result = await approveAIAgent(
|
|
212
268
|
{
|
|
@@ -233,7 +289,9 @@ describe('approveAIAgent', () => {
|
|
|
233
289
|
},
|
|
234
290
|
} as any,
|
|
235
291
|
'run-3',
|
|
236
|
-
[{ toolCallId: 'call-1', approved: false }]
|
|
292
|
+
[{ toolCallId: 'call-1', approved: false }],
|
|
293
|
+
undefined,
|
|
294
|
+
ownerParams
|
|
237
295
|
)
|
|
238
296
|
|
|
239
297
|
assert.deepEqual(updates, [
|
|
@@ -252,6 +310,133 @@ describe('approveAIAgent', () => {
|
|
|
252
310
|
})
|
|
253
311
|
})
|
|
254
312
|
|
|
313
|
+
describe('approveAIAgent authorization', () => {
|
|
314
|
+
const suspendedRun = (agentName: string, resourceId: string) => ({
|
|
315
|
+
runId: 'run-auth',
|
|
316
|
+
agentName,
|
|
317
|
+
threadId: 'thread-1',
|
|
318
|
+
resourceId,
|
|
319
|
+
status: 'suspended',
|
|
320
|
+
pendingApprovals: [
|
|
321
|
+
{ type: 'tool-call', toolCallId: 'call-1', toolName: 'refund', args: {} },
|
|
322
|
+
],
|
|
323
|
+
usage: { inputTokens: 0, outputTokens: 0, model: 'test/test-model' },
|
|
324
|
+
createdAt: new Date(),
|
|
325
|
+
updatedAt: new Date(),
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
const runStateFor = (agentName: string, resourceId: string) => {
|
|
329
|
+
const updates: any[] = []
|
|
330
|
+
return {
|
|
331
|
+
updates,
|
|
332
|
+
aiRunState: {
|
|
333
|
+
getRun: async () => suspendedRun(agentName, resourceId),
|
|
334
|
+
updateRun: async (_runId: string, patch: any) => {
|
|
335
|
+
updates.push(patch)
|
|
336
|
+
},
|
|
337
|
+
} as any,
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
test('rejects when the run belongs to another session principal', async () => {
|
|
342
|
+
registerAgent('owned-agent')
|
|
343
|
+
const { updates, aiRunState } = runStateFor('owned-agent', 'user-a:default')
|
|
344
|
+
|
|
345
|
+
await assert.rejects(
|
|
346
|
+
() =>
|
|
347
|
+
approveAIAgent(
|
|
348
|
+
aiRunState,
|
|
349
|
+
'run-auth',
|
|
350
|
+
[{ toolCallId: 'call-1', approved: true }],
|
|
351
|
+
undefined,
|
|
352
|
+
{ sessionService: sessionService({ userId: 'user-b' }) } as any
|
|
353
|
+
),
|
|
354
|
+
ForbiddenError
|
|
355
|
+
)
|
|
356
|
+
assert.deepEqual(updates, [], 'run state must not be mutated')
|
|
357
|
+
})
|
|
358
|
+
|
|
359
|
+
test('rejects when the agent permissions deny', async () => {
|
|
360
|
+
registerAgent('denied-agent', {
|
|
361
|
+
permissions: { denied: async () => false },
|
|
362
|
+
} as Partial<CoreAIAgent>)
|
|
363
|
+
const { updates, aiRunState } = runStateFor('denied-agent', 'u1')
|
|
364
|
+
|
|
365
|
+
await assert.rejects(
|
|
366
|
+
() =>
|
|
367
|
+
approveAIAgent(
|
|
368
|
+
aiRunState,
|
|
369
|
+
'run-auth',
|
|
370
|
+
[{ toolCallId: 'call-1', approved: true }],
|
|
371
|
+
undefined,
|
|
372
|
+
{ sessionService: sessionService({ userId: 'u1' }) } as any
|
|
373
|
+
),
|
|
374
|
+
ForbiddenError
|
|
375
|
+
)
|
|
376
|
+
assert.deepEqual(updates, [], 'run state must not be mutated')
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
test('rejects when a required scope is no longer held', async () => {
|
|
380
|
+
registerAgent('scoped-agent', { scopes: ['admin:refund'] })
|
|
381
|
+
const { updates, aiRunState } = runStateFor('scoped-agent', 'u1')
|
|
382
|
+
|
|
383
|
+
await assert.rejects(
|
|
384
|
+
() =>
|
|
385
|
+
approveAIAgent(
|
|
386
|
+
aiRunState,
|
|
387
|
+
'run-auth',
|
|
388
|
+
[{ toolCallId: 'call-1', approved: true }],
|
|
389
|
+
undefined,
|
|
390
|
+
{
|
|
391
|
+
sessionService: sessionService({
|
|
392
|
+
userId: 'u1',
|
|
393
|
+
scopes: ['support'],
|
|
394
|
+
}),
|
|
395
|
+
} as any
|
|
396
|
+
),
|
|
397
|
+
MissingScopeError
|
|
398
|
+
)
|
|
399
|
+
assert.deepEqual(updates, [])
|
|
400
|
+
})
|
|
401
|
+
|
|
402
|
+
test('rejects when auth is required and the session is gone', async () => {
|
|
403
|
+
registerAgent('auth-agent', { auth: true })
|
|
404
|
+
const { updates, aiRunState } = runStateFor('auth-agent', 'resource-1')
|
|
405
|
+
|
|
406
|
+
await assert.rejects(
|
|
407
|
+
() =>
|
|
408
|
+
approveAIAgent(aiRunState, 'run-auth', [
|
|
409
|
+
{ toolCallId: 'call-1', approved: true },
|
|
410
|
+
]),
|
|
411
|
+
ForbiddenError
|
|
412
|
+
)
|
|
413
|
+
assert.deepEqual(updates, [])
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
test('allows the owning session through the gate', async () => {
|
|
417
|
+
registerAgent('owned-agent', { scopes: ['admin:refund'] })
|
|
418
|
+
const { updates, aiRunState } = runStateFor('owned-agent', 'user-a:default')
|
|
419
|
+
|
|
420
|
+
const result = await approveAIAgent(
|
|
421
|
+
aiRunState,
|
|
422
|
+
'run-auth',
|
|
423
|
+
[{ toolCallId: 'call-1', approved: true }],
|
|
424
|
+
undefined,
|
|
425
|
+
{
|
|
426
|
+
sessionService: sessionService({
|
|
427
|
+
userId: 'user-a',
|
|
428
|
+
scopes: ['admin:refund'],
|
|
429
|
+
}),
|
|
430
|
+
} as any
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
assert.equal(result.status, 'resumed')
|
|
434
|
+
assert.deepEqual(updates, [
|
|
435
|
+
{ status: 'running', pendingApprovals: undefined },
|
|
436
|
+
])
|
|
437
|
+
})
|
|
438
|
+
})
|
|
439
|
+
|
|
255
440
|
describe('getAIAgentsMeta', () => {
|
|
256
441
|
test('returns the shared metadata registry', () => {
|
|
257
442
|
const meta = getAIAgentsMeta()
|