@pikku/core 0.12.78 → 0.12.80
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 +234 -0
- package/dist/dev/hot-reload.js +1 -6
- package/dist/ecosystem.d.ts +27 -0
- package/dist/ecosystem.js +26 -0
- package/dist/errors/error-handler.js +4 -2
- package/dist/function/function-runner.js +20 -42
- package/dist/function/functions.types.d.ts +9 -5
- package/dist/index.d.ts +4 -9
- package/dist/index.js +3 -8
- package/dist/middleware/auth-cookie.d.ts +0 -4
- package/dist/middleware/auth-cookie.js +38 -2
- package/dist/middleware/cors.js +1 -0
- package/dist/middleware/index.d.ts +1 -1
- package/dist/middleware/index.js +1 -1
- package/dist/middleware/remote-auth.js +14 -3
- package/dist/permissions.d.ts +8 -10
- package/dist/permissions.js +0 -11
- package/dist/pikku-state.js +12 -5
- package/dist/schema.js +35 -1
- package/dist/services/ai-run-state-service.d.ts +7 -1
- package/dist/services/in-memory-ai-run-state-service.d.ts +1 -1
- package/dist/services/in-memory-ai-run-state-service.js +2 -1
- package/dist/services/in-memory-workflow-service.d.ts +10 -0
- package/dist/services/in-memory-workflow-service.js +25 -0
- package/dist/services/local-content-request-handler.d.ts +21 -0
- package/dist/services/local-content-request-handler.js +72 -53
- package/dist/services/local-content.d.ts +6 -0
- package/dist/services/local-content.js +14 -1
- package/dist/services/workflow-service.d.ts +4 -2
- package/dist/testing/service-tests/agent-run-service-tests.d.ts +10 -0
- package/dist/testing/service-tests/agent-run-service-tests.js +72 -0
- package/dist/testing/service-tests/ai-storage-service-tests.d.ts +3 -0
- package/dist/testing/service-tests/ai-storage-service-tests.js +226 -0
- package/dist/testing/service-tests/channel-store-tests.d.ts +3 -0
- package/dist/testing/service-tests/channel-store-tests.js +72 -0
- package/dist/testing/service-tests/credential-service-tests.d.ts +3 -0
- package/dist/testing/service-tests/credential-service-tests.js +109 -0
- package/dist/testing/service-tests/deployment-service-tests.d.ts +3 -0
- package/dist/testing/service-tests/deployment-service-tests.js +21 -0
- package/dist/testing/service-tests/event-hub-store-tests.d.ts +3 -0
- package/dist/testing/service-tests/event-hub-store-tests.js +34 -0
- package/dist/testing/service-tests/secret-service-tests.d.ts +3 -0
- package/dist/testing/service-tests/secret-service-tests.js +80 -0
- package/dist/testing/service-tests/session-store-tests.d.ts +3 -0
- package/dist/testing/service-tests/session-store-tests.js +43 -0
- package/dist/testing/service-tests/workflow-run-service-tests.d.ts +3 -0
- package/dist/testing/service-tests/workflow-run-service-tests.js +42 -0
- package/dist/testing/service-tests/workflow-service-tests.d.ts +3 -0
- package/dist/testing/service-tests/workflow-service-tests.js +150 -0
- package/dist/testing/service-tests.d.ts +6 -0
- package/dist/testing/service-tests.js +26 -791
- package/dist/types/core.types.d.ts +11 -1
- package/dist/types/state.types.d.ts +1 -1
- package/dist/utils/node-host-resolver.d.ts +12 -0
- package/dist/utils/node-host-resolver.js +16 -0
- package/dist/utils/safe-fetch.d.ts +18 -0
- package/dist/utils/safe-fetch.js +167 -29
- package/dist/wirings/actor-flow/run-conversation.js +1 -6
- package/dist/wirings/ai-agent/agent-rpc.d.ts +15 -0
- package/dist/wirings/ai-agent/agent-rpc.js +53 -0
- package/dist/wirings/ai-agent/ai-agent-agui.js +1 -5
- package/dist/wirings/ai-agent/ai-agent-memory.js +3 -1
- package/dist/wirings/ai-agent/ai-agent-prepare.js +3 -9
- package/dist/wirings/ai-agent/ai-agent-runner.js +28 -107
- package/dist/wirings/ai-agent/ai-agent-stream.js +20 -61
- package/dist/wirings/ai-agent/ai-agent-turn.d.ts +56 -0
- package/dist/wirings/ai-agent/ai-agent-turn.js +81 -0
- package/dist/wirings/ai-agent/ai-agent.types.d.ts +1 -1
- package/dist/wirings/ai-agent/voice-input.js +1 -6
- package/dist/wirings/ai-agent/voice-output.js +2 -12
- package/dist/wirings/channel/channel-common.js +1 -0
- package/dist/wirings/channel/channel-handler.js +3 -5
- package/dist/wirings/channel/channel-rpc-service.d.ts +0 -6
- package/dist/wirings/channel/channel-rpc-service.js +0 -8
- package/dist/wirings/channel/channel-rpc.types.d.ts +6 -0
- package/dist/wirings/channel/channel-rpc.types.js +8 -0
- package/dist/wirings/channel/channel-runner.d.ts +1 -3
- package/dist/wirings/channel/channel-runner.js +16 -8
- package/dist/wirings/channel/channel.types.d.ts +2 -0
- package/dist/wirings/channel/pikku-abstract-channel-handler.js +1 -0
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +3 -0
- package/dist/wirings/cli/channel/cli-channel-runner.js +2 -0
- package/dist/wirings/cli/cli-runner.js +4 -2
- package/dist/wirings/cli/cli.types.d.ts +0 -8
- package/dist/wirings/cli/command-parser.js +13 -0
- package/dist/wirings/gateway/gateway-runner.js +41 -5
- package/dist/wirings/http/http-routes.js +2 -0
- package/dist/wirings/http/http-runner.d.ts +0 -10
- package/dist/wirings/http/http-runner.js +6 -13
- package/dist/wirings/http/http.types.d.ts +0 -10
- package/dist/wirings/http/index.d.ts +1 -1
- package/dist/wirings/http/index.js +1 -1
- package/dist/wirings/mcp/mcp-runner.d.ts +0 -7
- package/dist/wirings/mcp/mcp-runner.js +0 -6
- package/dist/wirings/rpc/rpc-runner.d.ts +8 -51
- package/dist/wirings/rpc/rpc-runner.js +53 -86
- package/dist/wirings/rpc/rpc-types.d.ts +3 -0
- package/dist/wirings/secret/validate-secret-definitions.js +2 -0
- package/dist/wirings/trigger/pikku-trigger-service.d.ts +0 -4
- package/dist/wirings/trigger/trigger-runner.js +1 -0
- package/dist/wirings/virtual-user/run-virtual-user.js +11 -11
- package/dist/wirings/virtual-user/virtual-user-derive.js +4 -25
- package/dist/wirings/virtual-user/virtual-user-dispositions.js +1 -4
- package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +29 -2
- package/dist/wirings/workflow/feature.js +7 -4
- package/dist/wirings/workflow/graph/graph-runner.d.ts +1 -2
- package/dist/wirings/workflow/graph/graph-runner.js +8 -7
- package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +0 -4
- package/dist/wirings/workflow/index.d.ts +7 -2
- package/dist/wirings/workflow/index.js +5 -1
- package/dist/wirings/workflow/pikku-scenario-service.d.ts +17 -3
- package/dist/wirings/workflow/pikku-scenario-service.js +38 -10
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +44 -111
- package/dist/wirings/workflow/pikku-workflow-service.js +86 -404
- package/dist/wirings/workflow/workflow-approval.d.ts +39 -0
- package/dist/wirings/workflow/workflow-approval.js +114 -0
- package/dist/wirings/workflow/workflow-constants.d.ts +26 -0
- package/dist/wirings/workflow/workflow-constants.js +35 -0
- package/dist/wirings/workflow/workflow-errors.d.ts +58 -0
- package/dist/wirings/workflow/workflow-errors.js +112 -0
- package/dist/wirings/workflow/workflow-meta-resolver.d.ts +11 -0
- package/dist/wirings/workflow/workflow-meta-resolver.js +31 -0
- package/dist/wirings/workflow/workflow-queue-routing.d.ts +8 -0
- package/dist/wirings/workflow/workflow-queue-routing.js +38 -0
- package/dist/wirings/workflow/workflow-queue-wiring.d.ts +20 -0
- package/dist/wirings/workflow/workflow-queue-wiring.js +79 -0
- package/dist/wirings/workflow/workflow-recovery.d.ts +68 -0
- package/dist/wirings/workflow/workflow-recovery.js +101 -0
- package/dist/wirings/workflow/workflow-run-engine.types.d.ts +54 -0
- package/dist/wirings/workflow/workflow-run-engine.types.js +1 -0
- package/dist/wirings/workflow/workflow-run-ownership.d.ts +16 -0
- package/dist/wirings/workflow/workflow-run-ownership.js +29 -0
- package/dist/wirings/workflow/workflow-suspend.d.ts +12 -0
- package/dist/wirings/workflow/workflow-suspend.js +33 -0
- package/dist/wirings/workflow/workflow.types.d.ts +7 -0
- package/knowledge/decisions/internals/a-non-streaming-agent-run-registers-with-airunstate-too.md +22 -0
- package/knowledge/decisions/internals/a-resumed-agent-turn-is-as-interruptible-as-the-first.md +20 -0
- package/knowledge/decisions/internals/a-scenario-step-template-is-offered-unfilled.md +21 -0
- package/knowledge/decisions/internals/a-virtual-user-decides-whether-to-trust-memory-once-per-turn.md +21 -0
- package/knowledge/decisions/internals/a-wall-clock-threshold-is-a-load-test-in-disguise.md +46 -0
- package/knowledge/decisions/internals/a-workflow-wire-is-built-from-the-run-not-from-the-rpc-service.md +45 -0
- package/knowledge/decisions/internals/agent-context-waits-for-a-tool-result-still-being-written.md +21 -0
- package/knowledge/decisions/internals/agent-speech-travels-as-a-custom-agui-event.md +22 -0
- package/knowledge/decisions/internals/an-agent-interrupt-is-not-a-failure.md +23 -0
- package/knowledge/decisions/internals/an-agent-run-owned-by-another-instance-says-so.md +25 -0
- package/knowledge/decisions/internals/an-agent-stream-send-must-return-the-inner-sends-promise.md +22 -0
- package/knowledge/decisions/internals/an-empty-text-part-is-omitted-from-an-agent-message.md +20 -0
- package/knowledge/decisions/internals/an-empty-transcript-is-not-recorded.md +22 -0
- package/knowledge/decisions/internals/an-unref-d-timer-cannot-be-awaited-under-node-test.md +66 -0
- package/knowledge/decisions/internals/channel-state-accessors-are-unsound-generics-that-every-implementation-asserts.md +33 -0
- package/knowledge/decisions/internals/gateway-listener-middleware-runs-without-an-rpc-on-the-wire.md +43 -0
- package/knowledge/decisions/internals/hot-reload-writes-into-the-function-map-captured-at-startup.md +26 -0
- package/knowledge/decisions/internals/index.md +38 -26
- package/knowledge/decisions/internals/only-exposed-functions-enter-a-virtual-user-catalogue.md +21 -0
- package/knowledge/decisions/internals/scenario-given-and-when-are-sugar-but-then-is-not.md +24 -0
- package/knowledge/decisions/internals/side-effects-are-an-allowlist-not-a-boolean.md +34 -0
- package/knowledge/decisions/internals/speech-synthesis-picks-a-voice-per-sentence-and-warns-once.md +24 -0
- package/knowledge/decisions/internals/the-actor-prompt-says-json-because-of-json-object-mode.md +22 -0
- package/knowledge/decisions/internals/the-agent-done-event-goes-through-the-middleware-and-is-awaited.md +26 -0
- package/knowledge/decisions/internals/the-api-report-pins-members-not-just-names.md +43 -0
- package/knowledge/decisions/internals/the-ecosystem-entry-point-carries-the-adapter-surface.md +58 -0
- package/knowledge/decisions/internals/the-middleware-resolution-cache-is-deliberately-unbounded.md +40 -0
- package/knowledge/decisions/internals/the-per-invocation-rpc-view-is-a-class.md +40 -0
- package/knowledge/decisions/internals/the-persona-runtime-is-exported-from-the-persona-entry-point.md +28 -0
- package/knowledge/decisions/internals/the-transcript-event-is-sent-ahead-of-the-run.md +25 -0
- package/knowledge/decisions/internals/the-virtual-user-catalogue-is-the-only-gate-on-what-may-be-called.md +21 -0
- package/knowledge/decisions/internals/the-worker-disposition-is-the-one-that-is-not-testing.md +22 -0
- package/knowledge/decisions/internals/thread-history-records-the-transcript-not-the-audio.md +25 -0
- package/knowledge/decisions/internals/virtual-user-step-order-comes-from-insertion-order.md +21 -0
- package/knowledge/decisions/internals/voice-output-speaks-unless-voice-input-explicitly-says-otherwise.md +24 -0
- package/knowledge/decisions/internals/wiring-registries-erase-the-generics-their-wire-functions-capture.md +35 -0
- package/knowledge/decisions/security/a-dropped-audit-write-is-always-logged.md +4 -2
- package/knowledge/decisions/security/a-graph-run-starts-at-an-entry-node-the-graph-declared.md +33 -0
- package/knowledge/decisions/security/a-permission-gets-a-wire-it-cannot-reply-on.md +33 -0
- package/knowledge/decisions/security/a-step-runs-the-function-the-workflow-dispatched-it-with.md +37 -0
- package/knowledge/decisions/security/a-virtual-user-is-never-offered-a-step-that-would-forge-its-own-oracle.md +28 -0
- package/knowledge/decisions/security/a-workflow-run-is-read-and-approved-by-its-owner.md +34 -0
- package/knowledge/decisions/security/an-agent-approval-is-claimed-before-the-tool-runs.md +33 -0
- package/knowledge/decisions/security/an-upload-is-counted-as-it-arrives-not-buffered-then-measured.md +24 -0
- package/knowledge/decisions/security/gateway-handlers-run-through-the-function-runner-gate.md +13 -3
- package/knowledge/decisions/security/index.md +7 -0
- package/knowledge/questions/channel-middleware-accepts-bare-factories-that-nothing-resolves.md +35 -0
- package/knowledge/questions/index.md +2 -1
- package/knowledge/questions/unauthorized-channel-replies-escape-the-declared-out-type.md +44 -0
- package/package.json +14 -3
- package/scripts/generate-api-report.d.mts +1 -0
- package/scripts/generate-api-report.mjs +89 -0
- package/scripts/generate-api-report.mts +218 -0
- package/src/api-report.test.ts +69 -0
- package/src/column-form.ts +1 -4
- package/src/crypto-utils.test.ts +15 -2
- package/src/dev/hot-reload.ts +2 -7
- package/src/ecosystem.ts +40 -0
- package/src/errors/error-handler.ts +5 -3
- package/src/errors/error.test.ts +4 -1
- package/src/function/function-runner.test.ts +1 -1
- package/src/function/function-runner.ts +28 -39
- package/src/function/functions.types.ts +15 -9
- package/src/handle-error.ts +1 -1
- package/src/index.ts +3 -22
- package/src/middleware/auth-cookie.test.ts +50 -0
- package/src/middleware/auth-cookie.ts +38 -2
- package/src/middleware/cors.ts +2 -1
- package/src/middleware/index.ts +1 -1
- package/src/middleware/remote-auth.test.ts +43 -0
- package/src/middleware/remote-auth.ts +17 -3
- package/src/middleware-runner.ts +4 -2
- package/src/no-any-casts.test.ts +57 -0
- package/src/permissions.test.ts +3 -1
- package/src/permissions.ts +22 -24
- package/src/pikku-state.ts +17 -6
- package/src/public-surface.json +578 -0
- package/src/public-surface.json.README +25 -0
- package/src/public-surface.test.ts +105 -0
- package/src/removed-legacy-exports.test.ts +62 -0
- package/src/schema.test.ts +78 -0
- package/src/schema.ts +36 -1
- package/src/services/ai-run-state-service.ts +7 -1
- package/src/services/audit-service.ts +2 -2
- package/src/services/in-memory-ai-run-state-service.ts +3 -2
- package/src/services/in-memory-workflow-service.ts +25 -0
- package/src/services/index.ts +1 -4
- package/src/services/local-content-request-handler.test.ts +43 -5
- package/src/services/local-content-request-handler.ts +103 -74
- package/src/services/local-content.ts +15 -1
- package/src/services/local-email-service.ts +5 -1
- package/src/services/system-role-guard.test.ts +4 -1
- package/src/services/workflow-service.ts +9 -2
- package/src/side-effects-are-declared.test.ts +84 -0
- package/src/source-files-stay-composable.test.ts +41 -0
- package/src/testing/service-tests/agent-run-service-tests.ts +98 -0
- package/src/testing/service-tests/ai-storage-service-tests.ts +286 -0
- package/src/testing/service-tests/channel-store-tests.ts +98 -0
- package/src/testing/service-tests/credential-service-tests.ts +143 -0
- package/src/testing/service-tests/deployment-service-tests.ts +33 -0
- package/src/testing/service-tests/event-hub-store-tests.ts +48 -0
- package/src/testing/service-tests/secret-service-tests.ts +105 -0
- package/src/testing/service-tests/session-store-tests.ts +62 -0
- package/src/testing/service-tests/workflow-run-service-tests.ts +59 -0
- package/src/testing/service-tests/workflow-service-tests.ts +308 -0
- package/src/testing/service-tests.ts +31 -1111
- package/src/types/core.types.ts +15 -1
- package/src/types/state.types.ts +1 -1
- package/src/utils/node-host-resolver.ts +20 -0
- package/src/utils/safe-fetch.test.ts +143 -1
- package/src/utils/safe-fetch.ts +200 -25
- package/src/wirings/actor-flow/run-conversation.ts +1 -6
- package/src/wirings/ai-agent/agent-rpc.ts +120 -0
- package/src/wirings/ai-agent/ai-agent-agui.ts +1 -5
- package/src/wirings/ai-agent/ai-agent-interrupt.test.ts +2 -1
- package/src/wirings/ai-agent/ai-agent-memory.ts +8 -1
- package/src/wirings/ai-agent/ai-agent-prepare.ts +10 -12
- package/src/wirings/ai-agent/ai-agent-resume-authorization.test.ts +1 -0
- package/src/wirings/ai-agent/ai-agent-runner.test.ts +82 -2
- package/src/wirings/ai-agent/ai-agent-runner.ts +49 -120
- package/src/wirings/ai-agent/ai-agent-stream.test.ts +2 -0
- package/src/wirings/ai-agent/ai-agent-stream.ts +36 -63
- package/src/wirings/ai-agent/ai-agent-thread-ownership.test.ts +1 -1
- package/src/wirings/ai-agent/ai-agent-turn.ts +121 -0
- package/src/wirings/ai-agent/ai-agent.types.ts +1 -1
- package/src/wirings/ai-agent/voice-input.ts +1 -6
- package/src/wirings/ai-agent/voice-output.ts +2 -12
- package/src/wirings/channel/channel-common.ts +5 -2
- package/src/wirings/channel/channel-handler-shapes.test.ts +72 -0
- package/src/wirings/channel/channel-handler.ts +7 -7
- package/src/wirings/channel/channel-rpc-service.ts +0 -14
- package/src/wirings/channel/channel-rpc.test.ts +25 -4
- package/src/wirings/channel/channel-rpc.types.ts +14 -0
- package/src/wirings/channel/channel-runner.ts +33 -20
- package/src/wirings/channel/channel.types.ts +2 -0
- package/src/wirings/channel/local/local-channel-runner.ts +1 -1
- package/src/wirings/channel/pikku-abstract-channel-handler.ts +2 -1
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +6 -3
- package/src/wirings/cli/channel/cli-channel-runner.ts +3 -1
- package/src/wirings/cli/channel/cli-raw-client-runner.ts +4 -1
- package/src/wirings/cli/cli-runner.ts +7 -4
- package/src/wirings/cli/cli.types.ts +0 -39
- package/src/wirings/cli/command-parser.test.ts +19 -0
- package/src/wirings/cli/command-parser.ts +17 -1
- package/src/wirings/gateway/gateway-authorization.test.ts +131 -0
- package/src/wirings/gateway/gateway-channel-meta.test.ts +44 -0
- package/src/wirings/gateway/gateway-runner.ts +62 -22
- package/src/wirings/http/http-routes.ts +4 -1
- package/src/wirings/http/http-runner.ts +11 -26
- package/src/wirings/http/http.types.ts +0 -15
- package/src/wirings/http/index.ts +1 -7
- package/src/wirings/http/pikku-fetch-http-request.ts +2 -2
- package/src/wirings/http/web-request.ts +1 -1
- package/src/wirings/mcp/mcp-runner.ts +2 -16
- package/src/wirings/persona/persona-environments.test.ts +14 -3
- package/src/wirings/persona/persona.test.ts +13 -3
- package/src/wirings/persona/validate-personas.ts +5 -1
- package/src/wirings/queue/queue-runner.ts +1 -1
- package/src/wirings/rpc/addon-auth-tags.test.ts +1 -5
- package/src/wirings/rpc/rpc-runner.ts +58 -136
- package/src/wirings/rpc/rpc-types.ts +7 -0
- package/src/wirings/rpc/wire-addon.ts +3 -1
- package/src/wirings/secret/validate-secret-definitions.test.ts +69 -0
- package/src/wirings/secret/validate-secret-definitions.ts +2 -0
- package/src/wirings/trigger/pikku-trigger-service.ts +0 -5
- package/src/wirings/trigger/trigger-runner.ts +7 -5
- package/src/wirings/virtual-user/run-virtual-user.test.ts +18 -9
- package/src/wirings/virtual-user/run-virtual-user.ts +28 -15
- package/src/wirings/virtual-user/virtual-user-agents.test.ts +4 -1
- package/src/wirings/virtual-user/virtual-user-derive.ts +4 -25
- package/src/wirings/virtual-user/virtual-user-dispositions.test.ts +7 -2
- package/src/wirings/virtual-user/virtual-user-dispositions.ts +1 -4
- package/src/wirings/virtual-user/virtual-user-intents.test.ts +13 -3
- package/src/wirings/workflow/dsl/workflow-dsl.types.ts +35 -2
- package/src/wirings/workflow/feature.ts +7 -4
- package/src/wirings/workflow/graph/graph-node.ts +1 -1
- package/src/wirings/workflow/graph/graph-runner.test.ts +4 -2
- package/src/wirings/workflow/graph/graph-runner.ts +13 -16
- package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -5
- package/src/wirings/workflow/index.ts +12 -4
- package/src/wirings/workflow/pikku-scenario-service.ts +54 -25
- package/src/wirings/workflow/pikku-workflow-service.test.ts +2 -2
- package/src/wirings/workflow/pikku-workflow-service.ts +208 -630
- package/src/wirings/workflow/scenario-hooks.test.ts +51 -0
- package/src/wirings/workflow/workflow-approval.ts +185 -0
- package/src/wirings/workflow/workflow-child-run-session.test.ts +89 -0
- package/src/wirings/workflow/workflow-constants.ts +47 -0
- package/src/wirings/workflow/workflow-dispatch-durability.test.ts +1 -1
- package/src/wirings/workflow/workflow-dispatch-relay.test.ts +128 -0
- package/src/wirings/workflow/workflow-errors.ts +128 -0
- package/src/wirings/workflow/workflow-inline-authority.test.ts +12 -6
- package/src/wirings/workflow/workflow-meta-resolver.ts +45 -0
- package/src/wirings/workflow/workflow-missing-meta.test.ts +92 -0
- package/src/wirings/workflow/workflow-queue-routing.ts +85 -0
- package/src/wirings/workflow/workflow-queue-wiring.ts +149 -0
- package/src/wirings/workflow/workflow-recovery.ts +162 -0
- package/src/wirings/workflow/workflow-retry-policy.test.ts +1 -1
- package/src/wirings/workflow/workflow-run-authority.test.ts +215 -0
- package/src/wirings/workflow/workflow-run-engine.types.ts +91 -0
- package/src/wirings/workflow/workflow-run-ownership.ts +36 -0
- package/src/wirings/workflow/workflow-suspend.ts +61 -0
- package/src/wirings/workflow/workflow.types.ts +7 -0
- package/src/wirings-stay-decoupled.test.ts +123 -0
- package/tsconfig.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/src/internal.ts +0 -10
|
@@ -6,13 +6,7 @@ export type { PikkuFetchHTTPRequestOptions } from './pikku-fetch-http-request.js
|
|
|
6
6
|
export { PikkuFetchHTTPResponse } from './pikku-fetch-http-response.js'
|
|
7
7
|
export { logRoutes } from './log-http-routes.js'
|
|
8
8
|
|
|
9
|
-
export {
|
|
10
|
-
fetch,
|
|
11
|
-
fetchData,
|
|
12
|
-
wireHTTP,
|
|
13
|
-
addHTTPMiddleware,
|
|
14
|
-
addHTTPPermission,
|
|
15
|
-
} from './http-runner.js'
|
|
9
|
+
export { fetch, fetchData, wireHTTP, addHTTPMiddleware } from './http-runner.js'
|
|
16
10
|
|
|
17
11
|
export { wireHTTPRoutes, defineHTTPRoutes } from './http-routes.js'
|
|
18
12
|
export { toWebRequest, applyWebResponse } from './web-request.js'
|
|
@@ -248,7 +248,7 @@ function valuesAreEquivalent(a: unknown, b: unknown): boolean {
|
|
|
248
248
|
return coerce(a) === coerce(b)
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
-
function coerce(value: unknown):
|
|
251
|
+
function coerce(value: unknown): unknown {
|
|
252
252
|
if (typeof value === 'boolean' || typeof value === 'number') return value
|
|
253
253
|
if (typeof value === 'string') {
|
|
254
254
|
if (value === 'true') return true
|
|
@@ -256,5 +256,5 @@ function coerce(value: unknown): string | number | boolean {
|
|
|
256
256
|
const num = Number(value)
|
|
257
257
|
return isNaN(num) ? value : num
|
|
258
258
|
}
|
|
259
|
-
return value
|
|
259
|
+
return value
|
|
260
260
|
}
|
|
@@ -40,7 +40,7 @@ export function toWebRequest(req: PikkuHTTPRequest, baseUrl?: string): Request {
|
|
|
40
40
|
if (
|
|
41
41
|
parsed &&
|
|
42
42
|
typeof parsed === 'object' &&
|
|
43
|
-
Object.keys(parsed as
|
|
43
|
+
Object.keys(parsed as object).length > 0
|
|
44
44
|
) {
|
|
45
45
|
let reconstructed: string
|
|
46
46
|
if (contentType.includes('application/x-www-form-urlencoded')) {
|
|
@@ -39,12 +39,6 @@ export type RunMCPEndpointParams<Tools extends string = any> = {
|
|
|
39
39
|
exposeErrors?: boolean
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
export type JsonRpcError = {
|
|
43
|
-
code: number
|
|
44
|
-
message: string
|
|
45
|
-
data?: any
|
|
46
|
-
}
|
|
47
|
-
|
|
48
42
|
export const wireMCPResource = <
|
|
49
43
|
PikkuFunctionConfig extends CorePikkuFunctionConfig<
|
|
50
44
|
CorePikkuFunctionSessionless<any, any>
|
|
@@ -60,7 +54,7 @@ export const wireMCPResource = <
|
|
|
60
54
|
)
|
|
61
55
|
return
|
|
62
56
|
}
|
|
63
|
-
addFunction(mcpResourceMeta.pikkuFuncId, mcpResource.func
|
|
57
|
+
addFunction(mcpResourceMeta.pikkuFuncId, mcpResource.func)
|
|
64
58
|
const resources = pikkuState(null, 'mcp', 'resources')
|
|
65
59
|
if (resources.has(mcpResource.uri)) {
|
|
66
60
|
throw new Error(`MCP resource already exists: ${mcpResource.uri}`)
|
|
@@ -83,7 +77,7 @@ export const wireMCPPrompt = <
|
|
|
83
77
|
)
|
|
84
78
|
return
|
|
85
79
|
}
|
|
86
|
-
addFunction(mcpPromptMeta.pikkuFuncId, mcpPrompt.func
|
|
80
|
+
addFunction(mcpPromptMeta.pikkuFuncId, mcpPrompt.func)
|
|
87
81
|
const prompts = pikkuState(null, 'mcp', 'prompts')
|
|
88
82
|
if (prompts.has(mcpPrompt.name)) {
|
|
89
83
|
throw new Error(`MCP prompt already exists: ${mcpPrompt.name}`)
|
|
@@ -293,10 +287,6 @@ async function runMCPPikkuFunc(
|
|
|
293
287
|
}
|
|
294
288
|
}
|
|
295
289
|
|
|
296
|
-
export const getMCPResources = () => {
|
|
297
|
-
return pikkuState(null, 'mcp', 'resources')
|
|
298
|
-
}
|
|
299
|
-
|
|
300
290
|
export const getMCPResourcesMeta = () => {
|
|
301
291
|
return pikkuState(null, 'mcp', 'resourcesMeta')
|
|
302
292
|
}
|
|
@@ -305,10 +295,6 @@ export const getMCPToolsMeta = () => {
|
|
|
305
295
|
return pikkuState(null, 'mcp', 'toolsMeta')
|
|
306
296
|
}
|
|
307
297
|
|
|
308
|
-
export const getMCPPrompts = () => {
|
|
309
|
-
return pikkuState(null, 'mcp', 'prompts')
|
|
310
|
-
}
|
|
311
|
-
|
|
312
298
|
export const getMCPPromptsMeta = () => {
|
|
313
299
|
return pikkuState(null, 'mcp', 'promptsMeta')
|
|
314
300
|
}
|
|
@@ -44,7 +44,11 @@ describe('resolvePersonaEnvironments', () => {
|
|
|
44
44
|
describe('personaEnvironmentErrors', () => {
|
|
45
45
|
test('a persona that declares nothing cannot be wrong', () => {
|
|
46
46
|
assert.deepEqual(
|
|
47
|
-
personaEnvironmentErrors(
|
|
47
|
+
personaEnvironmentErrors(
|
|
48
|
+
'shopper',
|
|
49
|
+
{ disposition: 'careless' },
|
|
50
|
+
ENVIRONMENTS
|
|
51
|
+
),
|
|
48
52
|
[]
|
|
49
53
|
)
|
|
50
54
|
})
|
|
@@ -106,8 +110,15 @@ describe('personaEnvironmentErrors', () => {
|
|
|
106
110
|
})
|
|
107
111
|
|
|
108
112
|
test('with nothing configured it says where environments go', () => {
|
|
109
|
-
const [error] = personaEnvironmentErrors(
|
|
110
|
-
|
|
113
|
+
const [error] = personaEnvironmentErrors(
|
|
114
|
+
'shopper',
|
|
115
|
+
{ environments: ['x'] },
|
|
116
|
+
{}
|
|
117
|
+
)
|
|
118
|
+
assert.match(
|
|
119
|
+
error!,
|
|
120
|
+
/Declare it under 'environments' in pikku\.config\.json/
|
|
121
|
+
)
|
|
111
122
|
})
|
|
112
123
|
})
|
|
113
124
|
|
|
@@ -23,7 +23,10 @@ describe('computed addresses', () => {
|
|
|
23
23
|
})
|
|
24
24
|
|
|
25
25
|
test('without a run id the address is the stable, seedable form', () => {
|
|
26
|
-
assert.equal(
|
|
26
|
+
assert.equal(
|
|
27
|
+
personaEmail('susan', 'mail.example.com'),
|
|
28
|
+
'susan@mail.example.com'
|
|
29
|
+
)
|
|
27
30
|
})
|
|
28
31
|
|
|
29
32
|
test('an id that is not address-shaped is reduced to one', () => {
|
|
@@ -34,7 +37,10 @@ describe('computed addresses', () => {
|
|
|
34
37
|
})
|
|
35
38
|
|
|
36
39
|
test('an id with nothing usable in it is refused rather than guessed at', () => {
|
|
37
|
-
assert.throws(
|
|
40
|
+
assert.throws(
|
|
41
|
+
() => personaEmail('...', 'example.com'),
|
|
42
|
+
/no usable email label/
|
|
43
|
+
)
|
|
38
44
|
})
|
|
39
45
|
|
|
40
46
|
// A synthetic domain was rejected precisely because it makes every
|
|
@@ -97,7 +103,11 @@ describe('verifying roles at sign-in', () => {
|
|
|
97
103
|
})
|
|
98
104
|
|
|
99
105
|
test('order and duplication are not drift', () => {
|
|
100
|
-
const v = verifyPersonaRoles(
|
|
106
|
+
const v = verifyPersonaRoles(
|
|
107
|
+
'yasser',
|
|
108
|
+
['admin', 'buyer'],
|
|
109
|
+
['buyer', 'admin', 'buyer']
|
|
110
|
+
)
|
|
101
111
|
assert.equal(v.ok, true)
|
|
102
112
|
})
|
|
103
113
|
|
|
@@ -58,7 +58,7 @@ export const wireQueueWorker = <
|
|
|
58
58
|
func: queueWorker.func.func,
|
|
59
59
|
auth: queueWorker.func.auth,
|
|
60
60
|
permissions: queueWorker.func.permissions,
|
|
61
|
-
middleware: queueWorker.func.middleware
|
|
61
|
+
middleware: queueWorker.func.middleware,
|
|
62
62
|
tags: queueWorker.func.tags,
|
|
63
63
|
})
|
|
64
64
|
|
|
@@ -8,11 +8,7 @@ import {
|
|
|
8
8
|
clearMiddlewareCache,
|
|
9
9
|
} from '../../middleware-runner.js'
|
|
10
10
|
import { ForbiddenError } from '../../errors/errors.js'
|
|
11
|
-
import {
|
|
12
|
-
resolveAddonAuth,
|
|
13
|
-
resolveAddonTags,
|
|
14
|
-
wireAddon,
|
|
15
|
-
} from './wire-addon.js'
|
|
11
|
+
import { resolveAddonAuth, resolveAddonTags, wireAddon } from './wire-addon.js'
|
|
16
12
|
|
|
17
13
|
const ADDON_PACKAGE = '@addon/console'
|
|
18
14
|
|
|
@@ -13,6 +13,14 @@ import { PikkuError, addError } from '../../errors/error-handler.js'
|
|
|
13
13
|
import type { PikkuRPC, ResolvedFunction } from './rpc-types.js'
|
|
14
14
|
import { parseVersionedId } from '../../version.js'
|
|
15
15
|
import { resolveRemoteAddonToken } from './remote-addon-auth.js'
|
|
16
|
+
import { createAgentRPC } from '../ai-agent/agent-rpc.js'
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The session for a wire: read through `getSession` when a runner attached one,
|
|
20
|
+
* otherwise whatever was placed on the wire directly.
|
|
21
|
+
*/
|
|
22
|
+
const resolveWireSession = async (wire: PikkuRawWire) =>
|
|
23
|
+
typeof wire.getSession === 'function' ? await wire.getSession() : wire.session
|
|
16
24
|
|
|
17
25
|
export class RPCNotFoundError extends PikkuError {
|
|
18
26
|
public readonly rpcName: string
|
|
@@ -55,16 +63,6 @@ addError(RemoteAddonRequestError, {
|
|
|
55
63
|
status: 502,
|
|
56
64
|
message: 'Remote addon request failed.',
|
|
57
65
|
})
|
|
58
|
-
import type { AIAgentInput } from '../ai-agent/ai-agent.types.js'
|
|
59
|
-
import type { AIStreamChannel } from '../ai-agent/ai-agent.types.js'
|
|
60
|
-
import type { StreamAIAgentOptions } from '../ai-agent/ai-agent-prepare.js'
|
|
61
|
-
import { runAIAgent, resumeAIAgentSync } from '../ai-agent/ai-agent-runner.js'
|
|
62
|
-
import {
|
|
63
|
-
streamAIAgent,
|
|
64
|
-
resumeAIAgent,
|
|
65
|
-
interruptAIAgent,
|
|
66
|
-
} from '../ai-agent/ai-agent-stream.js'
|
|
67
|
-
import { wrapChannelWithAGUI } from '../ai-agent/ai-agent-agui.js'
|
|
68
66
|
|
|
69
67
|
export const resolveNamespace = (
|
|
70
68
|
namespacedFunction: string
|
|
@@ -209,10 +207,7 @@ export class ContextAwareRPCService {
|
|
|
209
207
|
} catch (e) {
|
|
210
208
|
if (e instanceof RPCNotFoundError) {
|
|
211
209
|
if (this.services.deploymentService) {
|
|
212
|
-
const session =
|
|
213
|
-
this.wire.getSession && typeof this.wire.getSession === 'function'
|
|
214
|
-
? await this.wire.getSession()
|
|
215
|
-
: (this.wire as any).session
|
|
210
|
+
const session = await resolveWireSession(this.wire)
|
|
216
211
|
return this.services.deploymentService.invoke(
|
|
217
212
|
funcName,
|
|
218
213
|
data,
|
|
@@ -405,10 +400,7 @@ export class ContextAwareRPCService {
|
|
|
405
400
|
resolved = resolvePikkuFunction(rpcName, this.packageName)
|
|
406
401
|
} catch (e) {
|
|
407
402
|
if (e instanceof RPCNotFoundError && this.services.deploymentService) {
|
|
408
|
-
const session =
|
|
409
|
-
this.wire.getSession && typeof this.wire.getSession === 'function'
|
|
410
|
-
? await this.wire.getSession()
|
|
411
|
-
: (this.wire as any).session
|
|
403
|
+
const session = await resolveWireSession(this.wire)
|
|
412
404
|
return this.services.deploymentService.invoke(
|
|
413
405
|
rpcName,
|
|
414
406
|
data,
|
|
@@ -462,108 +454,15 @@ export class ContextAwareRPCService {
|
|
|
462
454
|
)
|
|
463
455
|
}
|
|
464
456
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
result: result.object ?? result.text,
|
|
475
|
-
usage: result.usage,
|
|
476
|
-
...(result.status === 'suspended' && {
|
|
477
|
-
status: 'suspended' as const,
|
|
478
|
-
pendingApprovals: result.pendingApprovals,
|
|
479
|
-
}),
|
|
480
|
-
}
|
|
481
|
-
},
|
|
482
|
-
stream: async (
|
|
483
|
-
agentName: string,
|
|
484
|
-
input: {
|
|
485
|
-
message: string
|
|
486
|
-
threadId: string
|
|
487
|
-
resourceId: string
|
|
488
|
-
model?: string
|
|
489
|
-
temperature?: number
|
|
490
|
-
},
|
|
491
|
-
options?: StreamAIAgentOptions
|
|
492
|
-
) => {
|
|
493
|
-
const channel = this.wire.channel as unknown as AIStreamChannel
|
|
494
|
-
if (!channel) throw new Error('No channel available for streaming')
|
|
495
|
-
let currentRunId: string | undefined
|
|
496
|
-
await streamAIAgent(
|
|
497
|
-
agentName,
|
|
498
|
-
input,
|
|
499
|
-
wrapChannelWithAGUI(channel, {
|
|
500
|
-
threadId: input.threadId,
|
|
501
|
-
getRunId: () => currentRunId,
|
|
502
|
-
}),
|
|
503
|
-
{
|
|
504
|
-
sessionService: this.options.sessionService,
|
|
505
|
-
getCredential: this.wire.getCredential?.bind(this.wire),
|
|
506
|
-
},
|
|
507
|
-
undefined,
|
|
508
|
-
{
|
|
509
|
-
...options,
|
|
510
|
-
onRunCreated: (runId) => {
|
|
511
|
-
currentRunId = runId
|
|
512
|
-
options?.onRunCreated?.(runId)
|
|
513
|
-
},
|
|
514
|
-
}
|
|
515
|
-
)
|
|
516
|
-
},
|
|
517
|
-
resume: async (
|
|
518
|
-
runId: string,
|
|
519
|
-
input: { toolCallId: string; approved: boolean },
|
|
520
|
-
options?: StreamAIAgentOptions
|
|
521
|
-
) => {
|
|
522
|
-
const channel = this.wire.channel as unknown as AIStreamChannel
|
|
523
|
-
if (!channel) throw new Error('No channel available for streaming')
|
|
524
|
-
await resumeAIAgent(
|
|
525
|
-
{ runId, ...input },
|
|
526
|
-
wrapChannelWithAGUI(channel, { runId }),
|
|
527
|
-
{
|
|
528
|
-
sessionService: this.options.sessionService,
|
|
529
|
-
getCredential: this.wire.getCredential?.bind(this.wire),
|
|
530
|
-
},
|
|
531
|
-
options
|
|
532
|
-
)
|
|
533
|
-
},
|
|
534
|
-
interrupt: async (
|
|
535
|
-
runId: string,
|
|
536
|
-
reason?: 'speech' | 'user' | 'timeout'
|
|
537
|
-
) => {
|
|
538
|
-
return interruptAIAgent(
|
|
539
|
-
{ runId, ...(reason ? { reason } : {}) },
|
|
540
|
-
{ sessionService: this.options.sessionService }
|
|
541
|
-
)
|
|
542
|
-
},
|
|
543
|
-
approve: async (
|
|
544
|
-
runId: string,
|
|
545
|
-
approvals: { toolCallId: string; approved: boolean }[],
|
|
546
|
-
expectedAgentName?: string
|
|
547
|
-
) => {
|
|
548
|
-
const result = await resumeAIAgentSync(
|
|
549
|
-
runId,
|
|
550
|
-
approvals,
|
|
551
|
-
{
|
|
552
|
-
sessionService: this.options.sessionService,
|
|
553
|
-
},
|
|
554
|
-
expectedAgentName
|
|
555
|
-
)
|
|
556
|
-
return {
|
|
557
|
-
runId: result.runId,
|
|
558
|
-
result: result.object ?? result.text,
|
|
559
|
-
usage: result.usage,
|
|
560
|
-
...(result.status === 'suspended' && {
|
|
561
|
-
status: 'suspended' as const,
|
|
562
|
-
pendingApprovals: result.pendingApprovals,
|
|
563
|
-
}),
|
|
564
|
-
}
|
|
565
|
-
},
|
|
566
|
-
}
|
|
457
|
+
/**
|
|
458
|
+
* The agent facade, built on access.
|
|
459
|
+
*
|
|
460
|
+
* The implementation lives in `ai-agent/agent-rpc.ts` so the agent surface is
|
|
461
|
+
* one file rather than a wing of this one; a getter rather than a field so a
|
|
462
|
+
* request that never touches an agent never builds it.
|
|
463
|
+
*/
|
|
464
|
+
public get agent(): PikkuRPC['agent'] {
|
|
465
|
+
return createAgentRPC(this.wire, this.options)
|
|
567
466
|
}
|
|
568
467
|
|
|
569
468
|
public async remote<In = any, Out = any>(
|
|
@@ -577,10 +476,7 @@ export class ContextAwareRPCService {
|
|
|
577
476
|
)
|
|
578
477
|
}
|
|
579
478
|
|
|
580
|
-
const session =
|
|
581
|
-
this.wire.getSession && typeof this.wire.getSession === 'function'
|
|
582
|
-
? await this.wire.getSession()
|
|
583
|
-
: (this.wire as any).session
|
|
479
|
+
const session = await resolveWireSession(this.wire)
|
|
584
480
|
|
|
585
481
|
return this.services.deploymentService.invoke(
|
|
586
482
|
funcName,
|
|
@@ -619,18 +515,44 @@ export class PikkuRPCService<
|
|
|
619
515
|
options,
|
|
620
516
|
packageName
|
|
621
517
|
)
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
518
|
+
// `TypedRPC` is named by the caller from its generated RPC map. Nothing
|
|
519
|
+
// concrete can satisfy a type the caller has not chosen yet.
|
|
520
|
+
return new ContextRPCView(serviceRPC, depth) as TypedRPC
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* The per-invocation `wire.rpc`.
|
|
526
|
+
*
|
|
527
|
+
* A class rather than an object literal because `agent` has to stay lazy — most
|
|
528
|
+
* requests never touch it — and an accessor declared on an object literal is
|
|
529
|
+
* defined per instance, which drops the literal off V8's fast construction
|
|
530
|
+
* path. Measured at ~1.15µs per request as a literal against ~0.47µs here, on
|
|
531
|
+
* the hot path every request takes.
|
|
532
|
+
*
|
|
533
|
+
* knowledge: decisions/internals/the-per-invocation-rpc-view-is-a-class.md
|
|
534
|
+
*/
|
|
535
|
+
class ContextRPCView {
|
|
536
|
+
public readonly global = false
|
|
537
|
+
public readonly invoke: ContextAwareRPCService['rpc']
|
|
538
|
+
public readonly remote: ContextAwareRPCService['remote']
|
|
539
|
+
public readonly exposed: ContextAwareRPCService['rpcExposed']
|
|
540
|
+
public readonly startWorkflow: ContextAwareRPCService['startWorkflow']
|
|
541
|
+
public readonly rpcWithWire: ContextAwareRPCService['rpcWithWire']
|
|
542
|
+
|
|
543
|
+
constructor(
|
|
544
|
+
private readonly serviceRPC: ContextAwareRPCService,
|
|
545
|
+
public readonly depth: number
|
|
546
|
+
) {
|
|
547
|
+
this.invoke = serviceRPC.rpc.bind(serviceRPC)
|
|
548
|
+
this.remote = serviceRPC.remote.bind(serviceRPC)
|
|
549
|
+
this.exposed = serviceRPC.rpcExposed.bind(serviceRPC)
|
|
550
|
+
this.startWorkflow = serviceRPC.startWorkflow.bind(serviceRPC)
|
|
551
|
+
this.rpcWithWire = serviceRPC.rpcWithWire.bind(serviceRPC)
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
get agent() {
|
|
555
|
+
return this.serviceRPC.agent
|
|
634
556
|
}
|
|
635
557
|
}
|
|
636
558
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PikkuRawWire } from '../../types/core.types.js'
|
|
1
2
|
import type { AgentInterruptResult } from '../ai-agent/ai-agent-interrupt.js'
|
|
2
3
|
|
|
3
4
|
export type PikkuRPC<
|
|
@@ -12,6 +13,12 @@ export type PikkuRPC<
|
|
|
12
13
|
invoke: Invoke
|
|
13
14
|
remote: Remote
|
|
14
15
|
exposed: (name: string, data: any) => Promise<any>
|
|
16
|
+
/** Invoke an RPC with explicit wire fields merged over the caller's. */
|
|
17
|
+
rpcWithWire: <In = any, Out = any>(
|
|
18
|
+
rpcName: string,
|
|
19
|
+
data: In,
|
|
20
|
+
wire: PikkuRawWire
|
|
21
|
+
) => Promise<Out>
|
|
15
22
|
startWorkflow: startWorkflow
|
|
16
23
|
agent: {
|
|
17
24
|
run: AgentRun
|
|
@@ -22,6 +22,28 @@ describe('validateAndBuildSecretDefinitionsMeta', () => {
|
|
|
22
22
|
assert.strictEqual(result['stripe'].displayName, 'Stripe')
|
|
23
23
|
})
|
|
24
24
|
|
|
25
|
+
test('carries allowedHosts into the meta so the egress binding is enforced', () => {
|
|
26
|
+
const definitions = [
|
|
27
|
+
{
|
|
28
|
+
name: 'notion',
|
|
29
|
+
displayName: 'Notion',
|
|
30
|
+
secretId: 'NOTION_KEY',
|
|
31
|
+
allowedHosts: ['api.notion.com', '*.notion.com'],
|
|
32
|
+
sourceFile: 'a.ts',
|
|
33
|
+
},
|
|
34
|
+
]
|
|
35
|
+
const result = validateAndBuildSecretDefinitionsMeta(
|
|
36
|
+
definitions as any,
|
|
37
|
+
new Map()
|
|
38
|
+
)
|
|
39
|
+
// assertSecretAllowedForHost reads allowedHosts off this meta; if it is
|
|
40
|
+
// dropped here the host binding silently permits every host.
|
|
41
|
+
assert.deepStrictEqual(result['notion']!.allowedHosts, [
|
|
42
|
+
'api.notion.com',
|
|
43
|
+
'*.notion.com',
|
|
44
|
+
])
|
|
45
|
+
})
|
|
46
|
+
|
|
25
47
|
test('should allow duplicate secretId with same schema', () => {
|
|
26
48
|
const schemaLookup = new Map([
|
|
27
49
|
['schema1', { variableName: 'Schema', sourceFile: 'types.ts' }],
|
|
@@ -108,6 +130,53 @@ describe('validateAndBuildSecretDefinitionsMeta', () => {
|
|
|
108
130
|
)
|
|
109
131
|
})
|
|
110
132
|
|
|
133
|
+
test('should carry allowedHosts into the meta', () => {
|
|
134
|
+
const definitions = [
|
|
135
|
+
{
|
|
136
|
+
name: 'example-api',
|
|
137
|
+
displayName: 'Example API',
|
|
138
|
+
secretId: 'EXAMPLE_API_CREDENTIALS',
|
|
139
|
+
allowedHosts: ['api.example.com', '*.example.com'],
|
|
140
|
+
sourceFile: 'a.ts',
|
|
141
|
+
},
|
|
142
|
+
]
|
|
143
|
+
const result = validateAndBuildSecretDefinitionsMeta(
|
|
144
|
+
definitions as any,
|
|
145
|
+
new Map()
|
|
146
|
+
)
|
|
147
|
+
assert.deepStrictEqual(result['example-api']!.allowedHosts, [
|
|
148
|
+
'api.example.com',
|
|
149
|
+
'*.example.com',
|
|
150
|
+
])
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
test('should carry allowedHosts into the meta for a shared secretId', () => {
|
|
154
|
+
const definitions = [
|
|
155
|
+
{
|
|
156
|
+
name: 'cred1',
|
|
157
|
+
displayName: 'Cred 1',
|
|
158
|
+
secretId: 'SHARED',
|
|
159
|
+
allowedHosts: ['first.example.com'],
|
|
160
|
+
sourceFile: 'a.ts',
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: 'cred2',
|
|
164
|
+
displayName: 'Cred 2',
|
|
165
|
+
secretId: 'SHARED',
|
|
166
|
+
allowedHosts: ['second.example.com'],
|
|
167
|
+
sourceFile: 'b.ts',
|
|
168
|
+
},
|
|
169
|
+
]
|
|
170
|
+
const result = validateAndBuildSecretDefinitionsMeta(
|
|
171
|
+
definitions as any,
|
|
172
|
+
new Map()
|
|
173
|
+
)
|
|
174
|
+
assert.deepStrictEqual(result['cred1']!.allowedHosts, ['first.example.com'])
|
|
175
|
+
assert.deepStrictEqual(result['cred2']!.allowedHosts, [
|
|
176
|
+
'second.example.com',
|
|
177
|
+
])
|
|
178
|
+
})
|
|
179
|
+
|
|
111
180
|
test('should handle empty definitions', () => {
|
|
112
181
|
const result = validateAndBuildSecretDefinitionsMeta([], new Map())
|
|
113
182
|
assert.deepStrictEqual(result, {})
|
|
@@ -56,6 +56,7 @@ export function validateAndBuildSecretDefinitionsMeta(
|
|
|
56
56
|
schema: def.schema,
|
|
57
57
|
oauth2: def.oauth2,
|
|
58
58
|
rotationPeriod: def.rotationPeriod,
|
|
59
|
+
allowedHosts: def.allowedHosts,
|
|
59
60
|
docsUrl: def.docsUrl,
|
|
60
61
|
sourceFile: def.sourceFile,
|
|
61
62
|
}
|
|
@@ -74,6 +75,7 @@ export function validateAndBuildSecretDefinitionsMeta(
|
|
|
74
75
|
schema: def.schema,
|
|
75
76
|
oauth2: def.oauth2,
|
|
76
77
|
rotationPeriod: def.rotationPeriod,
|
|
78
|
+
allowedHosts: def.allowedHosts,
|
|
77
79
|
docsUrl: def.docsUrl,
|
|
78
80
|
sourceFile: def.sourceFile,
|
|
79
81
|
}
|
|
@@ -14,11 +14,6 @@ export type TriggerTarget = {
|
|
|
14
14
|
startNode?: string
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export type TriggerSourceInfo = {
|
|
18
|
-
name: string
|
|
19
|
-
input: unknown
|
|
20
|
-
}
|
|
21
|
-
|
|
22
17
|
export abstract class PikkuTriggerService implements TriggerService {
|
|
23
18
|
protected activeTriggers = new Map<string, TriggerInstance>()
|
|
24
19
|
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
getCreateWireServices,
|
|
11
11
|
} from '../../pikku-state.js'
|
|
12
12
|
import { addFunction, runPikkuFunc } from '../../function/function-runner.js'
|
|
13
|
+
import type { CorePikkuFunctionConfig } from '../../function/functions.types.js'
|
|
13
14
|
import { PikkuMissingMetaError } from '../../errors/errors.js'
|
|
14
15
|
|
|
15
16
|
export const wireTrigger = (trigger: CoreTrigger) => {
|
|
@@ -22,10 +23,10 @@ export const wireTrigger = (trigger: CoreTrigger) => {
|
|
|
22
23
|
return
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
addFunction(triggerMeta.pikkuFuncId, trigger.func
|
|
26
|
+
addFunction(triggerMeta.pikkuFuncId, trigger.func)
|
|
26
27
|
|
|
27
28
|
const triggers = pikkuState(null, 'trigger', 'triggers')
|
|
28
|
-
triggers.set(trigger.name, trigger
|
|
29
|
+
triggers.set(trigger.name, trigger)
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
// knowledge: decisions/internals/trigger-declaration-is-split-from-trigger-source.md
|
|
@@ -45,11 +46,12 @@ export const wireTriggerSource = <TInput = unknown, TOutput = unknown>(
|
|
|
45
46
|
if (triggerSources.has(source.name)) {
|
|
46
47
|
throw new Error(`Trigger source already exists: ${source.name}`)
|
|
47
48
|
}
|
|
48
|
-
|
|
49
|
+
// knowledge: decisions/internals/wiring-registries-erase-the-generics-their-wire-functions-capture.md
|
|
50
|
+
triggerSources.set(source.name, source as CoreTriggerSource)
|
|
49
51
|
|
|
50
52
|
addFunction(
|
|
51
53
|
triggerSourceMeta.pikkuFuncId,
|
|
52
|
-
source.func as any,
|
|
54
|
+
source.func as CorePikkuFunctionConfig<any, any>,
|
|
53
55
|
triggerSourceMeta.packageName
|
|
54
56
|
)
|
|
55
57
|
}
|
|
@@ -94,7 +96,7 @@ export async function setupTrigger<TInput = unknown, TOutput = unknown>({
|
|
|
94
96
|
singletonServices,
|
|
95
97
|
createWireServices,
|
|
96
98
|
auth: false,
|
|
97
|
-
data: () => input
|
|
99
|
+
data: () => input,
|
|
98
100
|
wire,
|
|
99
101
|
packageName: sourceMeta.packageName || null,
|
|
100
102
|
})
|