@pikku/core 0.12.79 → 0.12.82
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 +473 -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/errors/index.d.ts +1 -1
- package/dist/errors/index.js +1 -1
- package/dist/function/function-runner.js +22 -47
- package/dist/function/functions.types.d.ts +9 -5
- package/dist/function/index.d.ts +1 -1
- package/dist/index.d.ts +14 -19
- package/dist/index.js +6 -11
- 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 +16 -5
- package/dist/schema.js +35 -1
- package/dist/services/ai-agent-runner-service.d.ts +7 -0
- package/dist/services/ai-run-state-service.d.ts +17 -1
- package/dist/services/in-memory-ai-run-state-service.d.ts +6 -2
- package/dist/services/in-memory-ai-run-state-service.js +11 -1
- package/dist/services/in-memory-workflow-service.js +2 -0
- package/dist/services/index.d.ts +15 -15
- package/dist/services/index.js +5 -5
- 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/scoped-credential-service.d.ts +21 -0
- package/dist/services/scoped-credential-service.js +53 -0
- 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 +302 -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 -3
- package/dist/types/state.types.d.ts +14 -1
- package/dist/wirings/actor-flow/index.d.ts +1 -1
- 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-finalize.d.ts +58 -0
- package/dist/wirings/ai-agent/ai-agent-finalize.js +138 -0
- package/dist/wirings/ai-agent/ai-agent-interrupt.js +1 -0
- package/dist/wirings/ai-agent/ai-agent-memory.d.ts +2 -8
- package/dist/wirings/ai-agent/ai-agent-memory.js +37 -18
- package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +7 -0
- package/dist/wirings/ai-agent/ai-agent-model-config.js +44 -1
- package/dist/wirings/ai-agent/ai-agent-prepare.js +5 -9
- package/dist/wirings/ai-agent/ai-agent-runner.js +89 -147
- package/dist/wirings/ai-agent/ai-agent-stream.js +109 -97
- package/dist/wirings/ai-agent/ai-agent-turn.d.ts +57 -0
- package/dist/wirings/ai-agent/ai-agent-turn.js +82 -0
- package/dist/wirings/ai-agent/ai-agent.types.d.ts +47 -2
- package/dist/wirings/ai-agent/index.d.ts +8 -7
- package/dist/wirings/ai-agent/index.js +5 -4
- package/dist/wirings/ai-agent/voice-input.js +1 -6
- package/dist/wirings/ai-agent/voice-output.js +2 -12
- package/dist/wirings/ai-scorer/ai-scorer-grade.d.ts +26 -0
- package/dist/wirings/ai-scorer/ai-scorer-grade.js +33 -0
- package/dist/wirings/ai-scorer/ai-scorer-judge.d.ts +17 -0
- package/dist/wirings/ai-scorer/ai-scorer-judge.js +92 -0
- package/dist/wirings/ai-scorer/ai-scorer-live.d.ts +15 -0
- package/dist/wirings/ai-scorer/ai-scorer-live.js +38 -0
- package/dist/wirings/ai-scorer/ai-scorer-registry.d.ts +18 -0
- package/dist/wirings/ai-scorer/ai-scorer-registry.js +46 -0
- package/dist/wirings/ai-scorer/ai-scorer-sampling.d.ts +8 -0
- package/dist/wirings/ai-scorer/ai-scorer-sampling.js +31 -0
- package/dist/wirings/ai-scorer/ai-scorer-snapshots.d.ts +10 -0
- package/dist/wirings/ai-scorer/ai-scorer-snapshots.js +40 -0
- package/dist/wirings/ai-scorer/ai-scorer-worker.d.ts +15 -0
- package/dist/wirings/ai-scorer/ai-scorer-worker.js +58 -0
- package/dist/wirings/ai-scorer/ai-scorer.d.ts +39 -0
- package/dist/wirings/ai-scorer/ai-scorer.js +40 -0
- package/dist/wirings/ai-scorer/ai-scorer.types.d.ts +90 -0
- package/dist/wirings/ai-scorer/ai-scorer.types.js +4 -0
- package/dist/wirings/ai-scorer/index.d.ts +6 -0
- package/dist/wirings/ai-scorer/index.js +5 -0
- 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/index.d.ts +5 -6
- package/dist/wirings/channel/index.js +3 -4
- package/dist/wirings/channel/local/local-channel-runner.js +8 -1
- 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/channel/cli-raw-channel-runner.js +9 -1
- package/dist/wirings/cli/channel/index.d.ts +1 -2
- package/dist/wirings/cli/channel/index.js +0 -1
- package/dist/wirings/cli/cli-runner.js +17 -3
- package/dist/wirings/cli/cli.types.d.ts +0 -8
- package/dist/wirings/cli/command-parser.js +13 -0
- package/dist/wirings/credential/index.d.ts +1 -1
- package/dist/wirings/gateway/gateway-runner.js +9 -2
- package/dist/wirings/gateway/index.d.ts +1 -1
- 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 +14 -15
- package/dist/wirings/http/http.types.d.ts +0 -10
- package/dist/wirings/http/index.d.ts +2 -3
- package/dist/wirings/http/index.js +1 -1
- package/dist/wirings/mcp/index.d.ts +1 -1
- package/dist/wirings/mcp/mcp-runner.d.ts +15 -7
- package/dist/wirings/mcp/mcp-runner.js +18 -11
- package/dist/wirings/persona/index.d.ts +3 -4
- package/dist/wirings/persona/index.js +2 -3
- package/dist/wirings/queue/index.d.ts +1 -3
- package/dist/wirings/queue/index.js +1 -3
- package/dist/wirings/rpc/addon-runner.d.ts +4 -0
- package/dist/wirings/rpc/addon-runner.js +19 -3
- package/dist/wirings/rpc/rpc-runner.d.ts +8 -51
- package/dist/wirings/rpc/rpc-runner.js +55 -86
- package/dist/wirings/rpc/rpc-types.d.ts +7 -0
- package/dist/wirings/rpc/wire-addon.d.ts +13 -0
- package/dist/wirings/rpc/wire-addon.js +4 -0
- package/dist/wirings/scheduler/index.d.ts +1 -1
- package/dist/wirings/secret/validate-secret-definitions.js +2 -2
- package/dist/wirings/trigger/index.d.ts +1 -1
- 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/index.d.ts +5 -6
- package/dist/wirings/virtual-user/index.js +2 -4
- 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 +100 -3
- 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 +12 -7
- package/dist/wirings/workflow/index.js +7 -3
- package/dist/wirings/workflow/pikku-scenario-service.d.ts +17 -3
- package/dist/wirings/workflow/pikku-scenario-service.js +64 -10
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +28 -147
- package/dist/wirings/workflow/pikku-workflow-service.js +85 -493
- package/dist/wirings/workflow/scenario-step.types.d.ts +8 -0
- package/dist/wirings/workflow/workflow-approval-audit.d.ts +16 -0
- package/dist/wirings/workflow/workflow-approval-audit.js +40 -0
- package/dist/wirings/workflow/workflow-approval-policy.d.ts +20 -0
- package/dist/wirings/workflow/workflow-approval-policy.js +48 -0
- package/dist/wirings/workflow/workflow-approval.d.ts +67 -0
- package/dist/wirings/workflow/workflow-approval.js +177 -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-ownership.d.ts +17 -0
- package/dist/wirings/workflow/workflow-run-ownership.js +30 -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 +8 -1
- 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/addon-pikku-meta-ships-at-the-package-root-or-under-dist.md +32 -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-addon-scope-root-loses-to-a-root-the-host-already-declares.md +39 -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 +42 -3
- 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/validate-runs-checks-by-precondition.md +115 -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-function-never-receives-the-secret-service.md +37 -0
- 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 +50 -0
- package/knowledge/decisions/security/an-agent-approval-is-claimed-before-the-tool-runs.md +33 -0
- package/knowledge/decisions/security/an-approval-answer-outlives-the-run-it-answered.md +59 -0
- package/knowledge/decisions/security/an-upload-is-counted-as-it-arrives-not-buffered-then-measured.md +24 -0
- package/knowledge/decisions/security/index.md +9 -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 +15 -3
- package/scripts/generate-api-report.d.mts +1 -0
- package/scripts/generate-api-report.mjs +89 -0
- package/scripts/generate-api-report.mts +343 -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/errors/index.ts +1 -1
- package/src/function/function-runner.test.ts +53 -1
- package/src/function/function-runner.ts +33 -48
- package/src/function/functions.types.ts +15 -9
- package/src/function/index.ts +0 -2
- package/src/handle-error.ts +1 -1
- package/src/index.ts +3 -57
- 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 +22 -6
- package/src/public-surface.json +554 -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-agent-runner-service.ts +12 -1
- package/src/services/ai-run-state-service.ts +18 -1
- package/src/services/audit-service.ts +2 -2
- package/src/services/in-memory-ai-run-state-service.ts +16 -2
- package/src/services/in-memory-workflow-service.ts +2 -0
- package/src/services/index.ts +4 -47
- 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/scoped-credential-service.test.ts +86 -0
- package/src/services/scoped-credential-service.ts +63 -0
- 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 +379 -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 +14 -3
- package/src/types/state.types.ts +17 -1
- package/src/wirings/actor-flow/index.ts +0 -3
- 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-finalize.test.ts +186 -0
- package/src/wirings/ai-agent/ai-agent-finalize.ts +197 -0
- package/src/wirings/ai-agent/ai-agent-interrupt.test.ts +2 -1
- package/src/wirings/ai-agent/ai-agent-interrupt.ts +1 -0
- package/src/wirings/ai-agent/ai-agent-memory.ts +62 -39
- package/src/wirings/ai-agent/ai-agent-model-config.test.ts +72 -3
- package/src/wirings/ai-agent/ai-agent-model-config.ts +49 -1
- package/src/wirings/ai-agent/ai-agent-prepare.ts +12 -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 +120 -160
- package/src/wirings/ai-agent/ai-agent-stream-output-hooks.test.ts +353 -0
- package/src/wirings/ai-agent/ai-agent-stream.test.ts +2 -0
- package/src/wirings/ai-agent/ai-agent-stream.ts +152 -117
- package/src/wirings/ai-agent/ai-agent-thread-ownership.test.ts +1 -1
- package/src/wirings/ai-agent/ai-agent-turn.test.ts +67 -0
- package/src/wirings/ai-agent/ai-agent-turn.ts +122 -0
- package/src/wirings/ai-agent/ai-agent.types.ts +65 -5
- package/src/wirings/ai-agent/index.ts +2 -16
- package/src/wirings/ai-agent/voice-input.ts +1 -6
- package/src/wirings/ai-agent/voice-output.ts +2 -12
- package/src/wirings/ai-scorer/ai-scorer-grade.test.ts +106 -0
- package/src/wirings/ai-scorer/ai-scorer-grade.ts +55 -0
- package/src/wirings/ai-scorer/ai-scorer-judge.test.ts +143 -0
- package/src/wirings/ai-scorer/ai-scorer-judge.ts +120 -0
- package/src/wirings/ai-scorer/ai-scorer-live.test.ts +174 -0
- package/src/wirings/ai-scorer/ai-scorer-live.ts +56 -0
- package/src/wirings/ai-scorer/ai-scorer-registry.ts +63 -0
- package/src/wirings/ai-scorer/ai-scorer-sampling.test.ts +34 -0
- package/src/wirings/ai-scorer/ai-scorer-sampling.ts +36 -0
- package/src/wirings/ai-scorer/ai-scorer-snapshots.test.ts +49 -0
- package/src/wirings/ai-scorer/ai-scorer-snapshots.ts +46 -0
- package/src/wirings/ai-scorer/ai-scorer-worker.test.ts +122 -0
- package/src/wirings/ai-scorer/ai-scorer-worker.ts +69 -0
- package/src/wirings/ai-scorer/ai-scorer.ts +76 -0
- package/src/wirings/ai-scorer/ai-scorer.types.ts +107 -0
- package/src/wirings/ai-scorer/index.ts +24 -0
- 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/index.ts +1 -20
- package/src/wirings/channel/local/local-channel-runner.test.ts +68 -0
- package/src/wirings/channel/local/local-channel-runner.ts +9 -2
- 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-channel-runner.test.ts +23 -0
- package/src/wirings/cli/channel/cli-raw-channel-runner.ts +12 -1
- package/src/wirings/cli/channel/cli-raw-client-runner.ts +4 -1
- package/src/wirings/cli/channel/index.ts +0 -7
- package/src/wirings/cli/cli-runner.test.ts +68 -0
- package/src/wirings/cli/cli-runner.ts +25 -5
- 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/credential/index.ts +0 -1
- package/src/wirings/gateway/gateway-channel-meta.test.ts +44 -0
- package/src/wirings/gateway/gateway-runner.ts +27 -19
- package/src/wirings/gateway/index.ts +0 -3
- package/src/wirings/http/http-routes.ts +4 -1
- package/src/wirings/http/http-runner.test.ts +66 -0
- package/src/wirings/http/http-runner.ts +21 -28
- package/src/wirings/http/http.types.ts +0 -15
- package/src/wirings/http/index.ts +2 -8
- package/src/wirings/http/pikku-fetch-http-request.ts +2 -2
- package/src/wirings/http/web-request.ts +1 -1
- package/src/wirings/mcp/index.ts +0 -1
- package/src/wirings/mcp/mcp-runner.test.ts +181 -0
- package/src/wirings/mcp/mcp-runner.ts +37 -21
- package/src/wirings/persona/index.ts +0 -8
- 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/index.ts +0 -14
- package/src/wirings/queue/queue-runner.ts +1 -1
- package/src/wirings/rpc/addon-auth-tags.test.ts +1 -5
- package/src/wirings/rpc/addon-runner.ts +34 -3
- package/src/wirings/rpc/addon-secrets.test.ts +261 -0
- package/src/wirings/rpc/rpc-runner.test.ts +2 -0
- package/src/wirings/rpc/rpc-runner.ts +60 -136
- package/src/wirings/rpc/rpc-types.ts +11 -0
- package/src/wirings/rpc/wire-addon.ts +20 -1
- package/src/wirings/scheduler/index.ts +0 -1
- package/src/wirings/secret/validate-secret-definitions.test.ts +22 -0
- package/src/wirings/secret/validate-secret-definitions.ts +2 -2
- package/src/wirings/trigger/index.ts +0 -1
- package/src/wirings/trigger/pikku-trigger-service.ts +0 -5
- package/src/wirings/trigger/trigger-runner.ts +7 -5
- package/src/wirings/virtual-user/index.ts +0 -16
- 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 +117 -4
- 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 +76 -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 +14 -24
- package/src/wirings/workflow/pikku-scenario-service.ts +101 -27
- package/src/wirings/workflow/pikku-workflow-service.test.ts +15 -14
- package/src/wirings/workflow/pikku-workflow-service.ts +214 -743
- package/src/wirings/workflow/scenario-expectations.test.ts +75 -0
- package/src/wirings/workflow/scenario-hooks.test.ts +52 -0
- package/src/wirings/workflow/scenario-step.types.ts +8 -0
- package/src/wirings/workflow/workflow-approval-audit.ts +47 -0
- package/src/wirings/workflow/workflow-approval-policy.test.ts +524 -0
- package/src/wirings/workflow/workflow-approval-policy.ts +68 -0
- package/src/wirings/workflow/workflow-approval.ts +289 -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-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 +212 -0
- package/src/wirings/workflow/workflow-run-engine.types.ts +91 -0
- package/src/wirings/workflow/workflow-run-ownership.ts +37 -0
- package/src/wirings/workflow/workflow-suspend.ts +61 -0
- package/src/wirings/workflow/workflow.types.ts +7 -9
- package/src/wirings-stay-decoupled.test.ts +127 -0
- package/tsconfig.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/internal.d.ts +0 -3
- package/dist/internal.js +0 -2
- package/dist/middleware/timeout.d.ts +0 -9
- package/dist/middleware/timeout.js +0 -15
- package/dist/pikku-response.d.ts +0 -6
- package/dist/pikku-response.js +0 -6
- package/dist/services/gopass-secrets.d.ts +0 -15
- package/dist/services/gopass-secrets.js +0 -76
- package/dist/services/http-scenario-actors.d.ts +0 -75
- package/dist/services/http-scenario-actors.js +0 -195
- package/dist/services/http-user-flow-actors.d.ts +0 -67
- package/dist/services/http-user-flow-actors.js +0 -193
- package/dist/services/scenario-actors-service.d.ts +0 -127
- package/dist/services/scenario-actors-service.js +0 -40
- package/dist/services/user-flow-actors-service.d.ts +0 -39
- package/dist/wirings/credential/wire-credential.d.ts +0 -48
- package/dist/wirings/credential/wire-credential.js +0 -47
- package/dist/wirings/oauth2/oauth2-client.d.ts +0 -47
- package/dist/wirings/oauth2/oauth2-client.js +0 -263
- package/dist/wirings/oauth2/oauth2-routes.d.ts +0 -35
- package/dist/wirings/oauth2/oauth2-routes.js +0 -146
- package/dist/wirings/scope/wire-scope.d.ts +0 -33
- package/dist/wirings/scope/wire-scope.js +0 -32
- package/dist/wirings/workflow/dsl/index.d.ts +0 -5
- package/dist/wirings/workflow/dsl/index.js +0 -4
- package/dist/wirings/workflow/graph/index.d.ts +0 -5
- package/dist/wirings/workflow/graph/index.js +0 -4
- package/src/internal.ts +0 -10
- /package/dist/{services/user-flow-actors-service.js → wirings/workflow/workflow-run-engine.types.js} +0 -0
|
@@ -31,23 +31,9 @@ export const deriveCatalogue = (
|
|
|
31
31
|
): ApiCatalogueEntry[] => {
|
|
32
32
|
const entries: ApiCatalogueEntry[] = []
|
|
33
33
|
for (const [name, meta] of Object.entries(functions ?? {})) {
|
|
34
|
-
//
|
|
35
|
-
// held out of every deployed unit — so offering one would only ever waste
|
|
36
|
-
// a turn on a 404.
|
|
37
|
-
//
|
|
38
|
-
// For a platform or addon step this is not an efficiency argument but the
|
|
39
|
-
// oracle: a virtual user's findings are worth something only because it
|
|
40
|
-
// cannot manufacture the outcomes it is meant to discover. One that could
|
|
41
|
-
// invoke "Stripe's webhook arrives" would forge its own payment success,
|
|
42
|
-
// and every finding downstream of that is worthless. Same class of argument
|
|
43
|
-
// as `allowApprovalRequired` defaulting to false — and enforced here, at
|
|
44
|
-
// derivation, rather than by convention.
|
|
34
|
+
// knowledge: decisions/security/a-virtual-user-is-never-offered-a-step-that-would-forge-its-own-oracle.md
|
|
45
35
|
if (meta.scenario || meta.scenarioStep || meta.scenarioStepKind) continue
|
|
46
|
-
//
|
|
47
|
-
// what the shipped target calls over. Absent is not permissive: an unexposed
|
|
48
|
-
// function 404s, and offering one spends a step to learn nothing about the
|
|
49
|
-
// product. Measured on the e2e app, 34 of its 72 functions are in exactly
|
|
50
|
-
// that state — nearly half a catalogue that cannot be called.
|
|
36
|
+
// knowledge: decisions/internals/only-exposed-functions-enter-a-virtual-user-catalogue.md
|
|
51
37
|
if (meta.expose !== true) continue
|
|
52
38
|
|
|
53
39
|
const inputSchema = meta.inputSchemaName
|
|
@@ -103,10 +89,7 @@ const scenarioSteps = (meta: {
|
|
|
103
89
|
)
|
|
104
90
|
}
|
|
105
91
|
|
|
106
|
-
//
|
|
107
|
-
// the scenario declares them. Following `next` instead would buy an ordering
|
|
108
|
-
// that is already true and cost a traversal that has to decide what a branch
|
|
109
|
-
// means to a reader who will never take one.
|
|
92
|
+
// knowledge: decisions/internals/virtual-user-step-order-comes-from-insertion-order.md
|
|
110
93
|
return Object.values(meta.nodes ?? {}).flatMap((node) => {
|
|
111
94
|
const { rpcName, scenarioStepPhase, actor } = (node ?? {}) as {
|
|
112
95
|
rpcName?: string
|
|
@@ -149,11 +132,7 @@ export const deriveIntents = (
|
|
|
149
132
|
steps.push(
|
|
150
133
|
composeStepProse({
|
|
151
134
|
phase: step.phase,
|
|
152
|
-
//
|
|
153
|
-
// placeholders from a run that happened; there is no run yet, and
|
|
154
|
-
// "invites {email}" tells a user to pick someone where the filled-in
|
|
155
|
-
// form would have told it whom — which is the scenario's answer, not
|
|
156
|
-
// the user's own.
|
|
135
|
+
// knowledge: decisions/internals/a-scenario-step-template-is-offered-unfilled.md
|
|
157
136
|
description: template ?? description ?? '',
|
|
158
137
|
actor: step.actor,
|
|
159
138
|
})
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { strict as assert } from 'assert'
|
|
2
2
|
import { describe, test } from 'node:test'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
DISPOSITIONS,
|
|
5
|
+
dispositionProfile,
|
|
6
|
+
} from './virtual-user-dispositions.js'
|
|
4
7
|
|
|
5
8
|
describe('resolving a disposition profile', () => {
|
|
6
9
|
test('an unknown disposition falls back to realistic rather than throwing', () => {
|
|
@@ -46,7 +49,9 @@ describe('resolving a disposition profile', () => {
|
|
|
46
49
|
const profile = dispositionProfile('careless', {
|
|
47
50
|
instructions: 'Paste ids from other tabs.',
|
|
48
51
|
})
|
|
49
|
-
assert.ok(
|
|
52
|
+
assert.ok(
|
|
53
|
+
profile.instructions.startsWith(DISPOSITIONS.careless.instructions)
|
|
54
|
+
)
|
|
50
55
|
assert.ok(profile.instructions.endsWith('Paste ids from other tabs.'))
|
|
51
56
|
})
|
|
52
57
|
|
|
@@ -154,10 +154,7 @@ export const DISPOSITIONS: Readonly<
|
|
|
154
154
|
invertedOracle: true,
|
|
155
155
|
},
|
|
156
156
|
|
|
157
|
-
//
|
|
158
|
-
// it abandons rarely, runs cool, and is told to stop and say so rather than
|
|
159
|
-
// guess — the failure mode here is a wrong action nobody asked for, not a
|
|
160
|
-
// missed bug.
|
|
157
|
+
// knowledge: decisions/internals/the-worker-disposition-is-the-one-that-is-not-testing.md
|
|
161
158
|
accountable: {
|
|
162
159
|
...REALISTIC,
|
|
163
160
|
instructions: [
|
|
@@ -3,7 +3,10 @@ import assert from 'node:assert/strict'
|
|
|
3
3
|
|
|
4
4
|
import { IntentStack, intentsForPersona } from './virtual-user-intents.js'
|
|
5
5
|
import { createRng } from './virtual-user-rng.js'
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
DISPOSITIONS,
|
|
8
|
+
type DispositionProfile,
|
|
9
|
+
} from './virtual-user-dispositions.js'
|
|
7
10
|
import type { IntentSource } from './virtual-user.types.js'
|
|
8
11
|
|
|
9
12
|
const profileWith = (
|
|
@@ -182,7 +185,11 @@ describe('intents for an actor', () => {
|
|
|
182
185
|
const catalogue: IntentSource[] = [
|
|
183
186
|
{ id: 'a', title: 'invite a teammate', personas: ['orgAdmin'] },
|
|
184
187
|
{ id: 'b', title: 'read the dashboard' },
|
|
185
|
-
{
|
|
188
|
+
{
|
|
189
|
+
id: 'c',
|
|
190
|
+
title: 'deploy a stage',
|
|
191
|
+
personas: ['platformAdmin', 'orgAdmin'],
|
|
192
|
+
},
|
|
186
193
|
]
|
|
187
194
|
|
|
188
195
|
test('an actor gets what names it, plus anything that names nobody', () => {
|
|
@@ -201,7 +208,10 @@ describe('intents for an actor', () => {
|
|
|
201
208
|
|
|
202
209
|
test('an empty actor list means everyone', () => {
|
|
203
210
|
assert.deepEqual(
|
|
204
|
-
intentsForPersona(
|
|
211
|
+
intentsForPersona(
|
|
212
|
+
[{ id: 'x', title: 'anything', personas: [] }],
|
|
213
|
+
'nobody'
|
|
214
|
+
),
|
|
205
215
|
[{ id: 'x', title: 'anything', personas: [] }]
|
|
206
216
|
)
|
|
207
217
|
})
|
|
@@ -65,6 +65,20 @@ export interface WorkflowExpectServiceOptions extends WorkflowStepOptions {
|
|
|
65
65
|
times?: number
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/** Options for workflow.expectScore() */
|
|
69
|
+
export interface WorkflowExpectScoreOptions extends WorkflowStepOptions {
|
|
70
|
+
/** Fail below this score. Defaults to 0.5 — a scorer that answered at all. */
|
|
71
|
+
atLeast?: number
|
|
72
|
+
/** Fail above this score, for a scorer where high is the failure. */
|
|
73
|
+
atMost?: number
|
|
74
|
+
/**
|
|
75
|
+
* The known-correct answer, which is what a reference-based judge grades
|
|
76
|
+
* against. Live traffic has no answer key, so a judge declared
|
|
77
|
+
* `requiresReference` is only ever reachable from a scenario.
|
|
78
|
+
*/
|
|
79
|
+
reference?: string
|
|
80
|
+
}
|
|
81
|
+
|
|
68
82
|
/**
|
|
69
83
|
* Type signature for workflow.do() RPC form - used by inspector
|
|
70
84
|
*/
|
|
@@ -114,12 +128,55 @@ export type WorkflowWireSleep = (
|
|
|
114
128
|
*/
|
|
115
129
|
export type WorkflowWireSuspend = (reason: string) => Promise<void>
|
|
116
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Who is allowed to answer an approval gate, relative to the user who started
|
|
133
|
+
* the run.
|
|
134
|
+
*
|
|
135
|
+
* - `any` — anyone the approve entrypoint lets through. The gate is a pause for
|
|
136
|
+
* a decision, not an authorization boundary.
|
|
137
|
+
* - `owner` — only the user who started the run, so a gate can be used to
|
|
138
|
+
* confirm an action against the same person who requested it.
|
|
139
|
+
* - `not-initiator` — anyone *except* the user who started the run: four-eyes.
|
|
140
|
+
* A run with no recorded initiator has nobody to exclude, so this degrades to
|
|
141
|
+
* requiring a signed-in decider.
|
|
142
|
+
*/
|
|
143
|
+
export type WorkflowApprovalApprovers = 'any' | 'owner' | 'not-initiator'
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Who may answer an approval gate. Declared on the gate rather than the
|
|
147
|
+
* entrypoint because it is a property of the decision being made, and because
|
|
148
|
+
* one workflow can hold several gates with different requirements.
|
|
149
|
+
*/
|
|
150
|
+
export interface WorkflowApprovalPolicy {
|
|
151
|
+
/**
|
|
152
|
+
* Defaults to `any`. See {@link WorkflowApprovalApprovers}.
|
|
153
|
+
*/
|
|
154
|
+
approvers?: WorkflowApprovalApprovers
|
|
155
|
+
/**
|
|
156
|
+
* Additionally require the decider's session to hold this scope, so
|
|
157
|
+
* "a second pair of eyes" can be narrowed to "a second pair of *senior*
|
|
158
|
+
* eyes". Combines with `approvers` — both must pass.
|
|
159
|
+
*/
|
|
160
|
+
approverScope?: string
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* The decider, reduced to the two facts a policy can be expressed in terms of.
|
|
165
|
+
* Recorded alongside the decision so the gate can be judged on replay — the
|
|
166
|
+
* session itself is long gone by then — and carried into the settled outcome so
|
|
167
|
+
* the answer keeps its provenance.
|
|
168
|
+
*/
|
|
169
|
+
export interface ApprovalDecider {
|
|
170
|
+
userId?: string
|
|
171
|
+
scopes?: string[]
|
|
172
|
+
}
|
|
173
|
+
|
|
117
174
|
/**
|
|
118
175
|
* Options for workflow.approval().
|
|
119
176
|
*/
|
|
120
177
|
export interface WorkflowApprovalOptions<
|
|
121
178
|
TSchema extends StandardSchemaV1 = StandardSchemaV1,
|
|
122
|
-
> {
|
|
179
|
+
> extends WorkflowApprovalPolicy {
|
|
123
180
|
/**
|
|
124
181
|
* Schema the decision payload is validated against. This is a VALUE, not a
|
|
125
182
|
* type generic: the payload arrives from an untrusted caller over the approve
|
|
@@ -142,7 +199,18 @@ export interface WorkflowApprovalOptions<
|
|
|
142
199
|
* carried in `data` and is the application's business, not the framework's.
|
|
143
200
|
*/
|
|
144
201
|
export type ApprovalOutcome<T> =
|
|
145
|
-
| {
|
|
202
|
+
| {
|
|
203
|
+
status: 'decided'
|
|
204
|
+
data: T
|
|
205
|
+
/**
|
|
206
|
+
* Who answered, and when. Run state holds the decision only while the gate
|
|
207
|
+
* is open — it is overwritten by the next write and cleared outright when a
|
|
208
|
+
* decision is refused — so the settled answer carries its own provenance
|
|
209
|
+
* into the step result, which is append-only.
|
|
210
|
+
*/
|
|
211
|
+
decidedBy?: ApprovalDecider
|
|
212
|
+
decidedAt?: string
|
|
213
|
+
}
|
|
146
214
|
| { status: 'expired' }
|
|
147
215
|
|
|
148
216
|
/**
|
|
@@ -311,7 +379,7 @@ export interface ReturnStepMeta {
|
|
|
311
379
|
}
|
|
312
380
|
|
|
313
381
|
/**
|
|
314
|
-
* Inline step metadata
|
|
382
|
+
* Inline step metadata
|
|
315
383
|
*/
|
|
316
384
|
export interface InlineStepMeta {
|
|
317
385
|
/** Inline form - local execution */
|
|
@@ -416,6 +484,10 @@ export interface ApprovalStepMeta {
|
|
|
416
484
|
outputVar?: string
|
|
417
485
|
/** Expiry duration, when one was given */
|
|
418
486
|
expiry?: string | number
|
|
487
|
+
/** Who may answer the gate, when the default was not used */
|
|
488
|
+
approvers?: WorkflowApprovalApprovers
|
|
489
|
+
/** Scope the decider must hold, when one was required */
|
|
490
|
+
approverScope?: string
|
|
419
491
|
}
|
|
420
492
|
|
|
421
493
|
/**
|
|
@@ -528,7 +600,36 @@ export interface PikkuWorkflowWire {
|
|
|
528
600
|
approval: WorkflowWireApproval
|
|
529
601
|
}
|
|
530
602
|
|
|
531
|
-
|
|
603
|
+
/**
|
|
604
|
+
* What a scenario has accumulated so far, shared by its body and its hooks.
|
|
605
|
+
*
|
|
606
|
+
* `Partial` because a scenario can fail at any step: `Out` describes what a
|
|
607
|
+
* *completed* run produces, and the context holds however much of it this run
|
|
608
|
+
* reached.
|
|
609
|
+
*
|
|
610
|
+
* The `0 extends 1 & Out` branch keeps `any` collapsing to `any` rather than to
|
|
611
|
+
* the union of the other two. `PikkuWire` and `PikkuFunctionConfig` both use
|
|
612
|
+
* this type as a generic *constraint*, and a constraint carrying a concrete
|
|
613
|
+
* context would reject every wire whose scenario output differs from it.
|
|
614
|
+
*/
|
|
615
|
+
export type ScenarioContext<Out = unknown> = 0 extends 1 & Out
|
|
616
|
+
? any
|
|
617
|
+
: Out extends object
|
|
618
|
+
? Partial<Out>
|
|
619
|
+
: Record<string, unknown>
|
|
620
|
+
|
|
621
|
+
export interface PikkuScenarioWire<Out = unknown> extends PikkuWorkflowWire {
|
|
622
|
+
/**
|
|
623
|
+
* Scratch the body writes and the `before`/`after` hooks read. A hook is a
|
|
624
|
+
* separate function and cannot see the body's locals, so this is how teardown
|
|
625
|
+
* learns the ids the body minted.
|
|
626
|
+
*
|
|
627
|
+
* Deliberately *not* a world: it is scoped to one run, and scenario steps
|
|
628
|
+
* cannot reach it. Steps stay pure functions of their declared inputs, so the
|
|
629
|
+
* ladder in the report remains a complete account of what a step saw.
|
|
630
|
+
*/
|
|
631
|
+
context: ScenarioContext<Out>
|
|
632
|
+
|
|
532
633
|
/**
|
|
533
634
|
* Durable polling step: invoke `rpcName` (as an actor when `options.actor`
|
|
534
635
|
* is set) until `predicate` passes or `options.within` elapses.
|
|
@@ -556,6 +657,18 @@ export interface PikkuScenarioWire extends PikkuWorkflowWire {
|
|
|
556
657
|
options?: WorkflowExpectServiceOptions
|
|
557
658
|
) => Promise<void>
|
|
558
659
|
|
|
660
|
+
/**
|
|
661
|
+
* Grade-assertion step: runs one declared scorer against a finished agent run
|
|
662
|
+
* and asserts the score. Returns the grade, so a scenario can report the
|
|
663
|
+
* reason a judge gave rather than only that it fell short.
|
|
664
|
+
*/
|
|
665
|
+
expectScore: (
|
|
666
|
+
stepName: string,
|
|
667
|
+
runId: string,
|
|
668
|
+
scorerName: string,
|
|
669
|
+
options?: WorkflowExpectScoreOptions
|
|
670
|
+
) => Promise<{ score: number; reason?: string }>
|
|
671
|
+
|
|
559
672
|
/**
|
|
560
673
|
* Run a registered scenario step, as the setup the scenario starts from.
|
|
561
674
|
*
|
|
@@ -32,9 +32,11 @@ export const resolveFeatureScenarios = (
|
|
|
32
32
|
const scenarios = feature.scenarios ?? []
|
|
33
33
|
for (let index = 0; index < scenarios.length; index++) {
|
|
34
34
|
const entry = scenarios[index]!
|
|
35
|
-
const
|
|
35
|
+
const pairing =
|
|
36
36
|
typeof entry === 'object' && entry !== null && 'scenario' in entry
|
|
37
|
-
|
|
37
|
+
? (entry as { scenario: unknown; data?: unknown })
|
|
38
|
+
: undefined
|
|
39
|
+
const config = pairing ? pairing.scenario : entry
|
|
38
40
|
const scenarioName = nameByConfig.get(config)
|
|
39
41
|
if (!scenarioName) {
|
|
40
42
|
unresolved.push({ featureId, index })
|
|
@@ -44,10 +46,11 @@ export const resolveFeatureScenarios = (
|
|
|
44
46
|
featureId,
|
|
45
47
|
featureName: feature.name ?? featureId,
|
|
46
48
|
scenarioName,
|
|
47
|
-
data:
|
|
49
|
+
data: pairing?.data,
|
|
48
50
|
tags: [
|
|
49
51
|
...new Set([
|
|
50
|
-
...((registrations.get(scenarioName)?.func as
|
|
52
|
+
...((registrations.get(scenarioName)?.func as { tags?: string[] })
|
|
53
|
+
?.tags ?? []),
|
|
51
54
|
...(feature.tags ?? []),
|
|
52
55
|
]),
|
|
53
56
|
],
|
|
@@ -65,7 +65,7 @@ export function createGraph<RPCMap extends Record<string, RPCHandler>>() {
|
|
|
65
65
|
for (const [nodeId, def] of Object.entries(nodes) as [string, any][]) {
|
|
66
66
|
result[nodeId] = {
|
|
67
67
|
func: funcMap[nodeId] as string,
|
|
68
|
-
input: def?.input
|
|
68
|
+
input: def?.input,
|
|
69
69
|
next: def?.next,
|
|
70
70
|
onError: def?.onError,
|
|
71
71
|
retries: def?.retries,
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
import type { WorkflowRuntimeMeta } from '../workflow.types.js'
|
|
11
11
|
import { pikkuState } from '../../../pikku-state.js'
|
|
12
12
|
import { RPCNotFoundError } from '../../rpc/rpc-runner.js'
|
|
13
|
-
import { DEFAULT_STEP_RETRIES } from '../
|
|
13
|
+
import { DEFAULT_STEP_RETRIES } from '../workflow-constants.js'
|
|
14
14
|
|
|
15
15
|
describe('graph-runner bugs', () => {
|
|
16
16
|
test('continueGraph should NOT mark workflow completed while nodes are still running', async () => {
|
|
@@ -54,6 +54,78 @@ describe('graph-runner bugs', () => {
|
|
|
54
54
|
assert.equal(run?.status, 'running')
|
|
55
55
|
})
|
|
56
56
|
|
|
57
|
+
test('startWorkflow rejects a startNode that is not a declared entry node', async () => {
|
|
58
|
+
const ws = new InMemoryWorkflowService()
|
|
59
|
+
const metaState = pikkuState(null, 'workflows', 'meta')
|
|
60
|
+
metaState['testStartNodeGate'] = {
|
|
61
|
+
name: 'testStartNodeGate',
|
|
62
|
+
pikkuFuncId: 'testStartNodeGate',
|
|
63
|
+
source: 'graph',
|
|
64
|
+
entryNodeIds: ['gate'],
|
|
65
|
+
graphHash: 'startnode-hash',
|
|
66
|
+
nodes: {
|
|
67
|
+
// 'charge' reads only trigger input, so it is dependency-free and would
|
|
68
|
+
// otherwise be directly startable — skipping the 'gate' entry node.
|
|
69
|
+
gate: { nodeId: 'gate', rpcName: 'checkEligibility', next: 'charge' },
|
|
70
|
+
charge: { nodeId: 'charge', rpcName: 'capturePayment' },
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
await assert.rejects(
|
|
75
|
+
() =>
|
|
76
|
+
ws.startWorkflow(
|
|
77
|
+
'testStartNodeGate',
|
|
78
|
+
{},
|
|
79
|
+
{ type: 'test' },
|
|
80
|
+
{ rpcWithWire: async () => ({}) },
|
|
81
|
+
{ startNode: 'charge', inline: true }
|
|
82
|
+
),
|
|
83
|
+
/not a declared entry node/
|
|
84
|
+
)
|
|
85
|
+
assert.equal(
|
|
86
|
+
[...(ws as any).runs.keys()].length,
|
|
87
|
+
0,
|
|
88
|
+
'no run should be created for a non-entry startNode'
|
|
89
|
+
)
|
|
90
|
+
delete metaState['testStartNodeGate']
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
test('startWorkflow accepts a startNode that is a declared entry node', async () => {
|
|
94
|
+
const ws = new InMemoryWorkflowService()
|
|
95
|
+
const metaState = pikkuState(null, 'workflows', 'meta')
|
|
96
|
+
// 'b' is a declared entry but carries an unknown input ref, so it clears the
|
|
97
|
+
// startNode gate and then throws at reference validation — proving the gate
|
|
98
|
+
// admitted it, without dispatching real work.
|
|
99
|
+
metaState['testStartNodeAllowed'] = {
|
|
100
|
+
name: 'testStartNodeAllowed',
|
|
101
|
+
pikkuFuncId: 'testStartNodeAllowed',
|
|
102
|
+
source: 'graph',
|
|
103
|
+
entryNodeIds: ['a', 'b'],
|
|
104
|
+
graphHash: 'startnode-ok-hash',
|
|
105
|
+
nodes: {
|
|
106
|
+
a: { nodeId: 'a', rpcName: 'doA' },
|
|
107
|
+
b: {
|
|
108
|
+
nodeId: 'b',
|
|
109
|
+
rpcName: 'doB',
|
|
110
|
+
input: { dep: { $ref: 'missingNode', path: 'value' } },
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
}
|
|
114
|
+
await assert.rejects(
|
|
115
|
+
() =>
|
|
116
|
+
ws.startWorkflow(
|
|
117
|
+
'testStartNodeAllowed',
|
|
118
|
+
{},
|
|
119
|
+
{ type: 'test' },
|
|
120
|
+
{ rpcWithWire: async () => ({}) },
|
|
121
|
+
{ startNode: 'b', inline: true }
|
|
122
|
+
),
|
|
123
|
+
/references unknown node 'missingNode'/,
|
|
124
|
+
'a declared entry node must pass the startNode gate (reaching ref validation)'
|
|
125
|
+
)
|
|
126
|
+
delete metaState['testStartNodeAllowed']
|
|
127
|
+
})
|
|
128
|
+
|
|
57
129
|
test('runWorkflowGraph should throw and not create a run for unknown input refs', async () => {
|
|
58
130
|
const ws = new InMemoryWorkflowService()
|
|
59
131
|
|
|
@@ -828,7 +900,9 @@ describe('graph-runner bugs', () => {
|
|
|
828
900
|
name: 'testRetries',
|
|
829
901
|
pikkuFuncId: 'testRetries',
|
|
830
902
|
source: 'graph',
|
|
831
|
-
|
|
903
|
+
// All three are dependency-free, so all three are entry nodes — a
|
|
904
|
+
// `startNode` may only name one the graph declared.
|
|
905
|
+
entryNodeIds: ['a', 'b', 'c'],
|
|
832
906
|
graphHash: 'retries-hash',
|
|
833
907
|
nodes: {
|
|
834
908
|
a: {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import type { PikkuWorkflowService } from '../pikku-workflow-service.js'
|
|
1
2
|
import {
|
|
2
|
-
type PikkuWorkflowService,
|
|
3
3
|
WorkflowAsyncException,
|
|
4
4
|
WorkflowSuspendedException,
|
|
5
|
-
|
|
6
|
-
} from '../
|
|
5
|
+
} from '../workflow-errors.js'
|
|
6
|
+
import { DEFAULT_STEP_RETRIES } from '../workflow-constants.js'
|
|
7
7
|
import type { GraphWireState, PikkuGraphWire } from './workflow-graph.types.js'
|
|
8
8
|
import { pikkuState, getSingletonServices } from '../../../pikku-state.js'
|
|
9
9
|
import type { WorkflowRuntimeMeta, WorkflowRunWire } from '../workflow.types.js'
|
|
@@ -211,7 +211,7 @@ function isDataRef(value: unknown): value is { $ref: string; path?: string } {
|
|
|
211
211
|
typeof value === 'object' &&
|
|
212
212
|
value !== null &&
|
|
213
213
|
'$ref' in value &&
|
|
214
|
-
typeof (value as
|
|
214
|
+
typeof (value as { $ref?: unknown }).$ref === 'string'
|
|
215
215
|
)
|
|
216
216
|
}
|
|
217
217
|
|
|
@@ -227,7 +227,7 @@ function isTemplate(value: unknown): value is TemplateValue {
|
|
|
227
227
|
typeof value === 'object' &&
|
|
228
228
|
value !== null &&
|
|
229
229
|
'$template' in value &&
|
|
230
|
-
typeof (value as
|
|
230
|
+
typeof (value as { $template?: unknown }).$template === 'object'
|
|
231
231
|
)
|
|
232
232
|
}
|
|
233
233
|
|
|
@@ -695,14 +695,6 @@ export async function executeGraphStep(
|
|
|
695
695
|
}
|
|
696
696
|
}
|
|
697
697
|
|
|
698
|
-
export async function onGraphNodeComplete(
|
|
699
|
-
workflowService: PikkuWorkflowService,
|
|
700
|
-
runId: string,
|
|
701
|
-
graphName: string
|
|
702
|
-
): Promise<void> {
|
|
703
|
-
await continueGraph(workflowService, runId, graphName)
|
|
704
|
-
}
|
|
705
|
-
|
|
706
698
|
export async function runFromMeta(
|
|
707
699
|
workflowService: PikkuWorkflowService,
|
|
708
700
|
runId: string,
|
|
@@ -928,9 +920,14 @@ export async function runWorkflowGraph(
|
|
|
928
920
|
}
|
|
929
921
|
|
|
930
922
|
const nodes = meta.nodes
|
|
931
|
-
const
|
|
932
|
-
|
|
933
|
-
|
|
923
|
+
const declaredEntryNodes = meta.entryNodeIds ?? []
|
|
924
|
+
// knowledge: decisions/security/a-graph-run-starts-at-an-entry-node-the-graph-declared.md
|
|
925
|
+
if (startNode && !declaredEntryNodes.includes(startNode)) {
|
|
926
|
+
throw new Error(
|
|
927
|
+
`Workflow graph '${graphName}': '${startNode}' is not an entry node`
|
|
928
|
+
)
|
|
929
|
+
}
|
|
930
|
+
const entryNodes: string[] = startNode ? [startNode] : declaredEntryNodes
|
|
934
931
|
validateGraphReferences(graphName, nodes, entryNodes)
|
|
935
932
|
|
|
936
933
|
if (entryNodes.length === 0) {
|
|
@@ -16,11 +16,6 @@ export const isRef = (value: unknown): value is RefValue =>
|
|
|
16
16
|
'__isRef' in value &&
|
|
17
17
|
(value as RefValue).__isRef === true
|
|
18
18
|
|
|
19
|
-
export interface InputRef {
|
|
20
|
-
nodeId: string
|
|
21
|
-
path?: string
|
|
22
|
-
}
|
|
23
|
-
|
|
24
19
|
export type RefFn<NodeIds extends string = string> = (
|
|
25
20
|
nodeId: NodeIds,
|
|
26
21
|
path?: string
|
|
@@ -1,20 +1,28 @@
|
|
|
1
|
+
export { PikkuWorkflowService } from './pikku-workflow-service.js'
|
|
1
2
|
export {
|
|
2
|
-
PikkuWorkflowService,
|
|
3
3
|
WorkflowCancelledException,
|
|
4
4
|
WorkflowSuspendedException,
|
|
5
5
|
WorkflowDispatchException,
|
|
6
6
|
WorkflowNotFoundError,
|
|
7
7
|
WorkflowRunNotFoundError,
|
|
8
8
|
WorkflowApprovalResolvedError,
|
|
9
|
-
|
|
10
|
-
} from './
|
|
9
|
+
WorkflowStepFunctionMismatchError,
|
|
10
|
+
} from './workflow-errors.js'
|
|
11
|
+
export { DEFAULT_STEP_RETRIES } from './workflow-constants.js'
|
|
12
|
+
export {
|
|
13
|
+
assertWorkflowRunOwner,
|
|
14
|
+
WorkflowRunForbiddenError,
|
|
15
|
+
} from './workflow-run-ownership.js'
|
|
16
|
+
export { WorkflowApprovalForbiddenError } from './workflow-approval-policy.js'
|
|
11
17
|
export type {
|
|
12
|
-
RunLifecycleContext,
|
|
13
18
|
WorkflowRunEngine,
|
|
14
19
|
WorkflowRunExtension,
|
|
15
|
-
} from './
|
|
20
|
+
} from './workflow-run-engine.types.js'
|
|
16
21
|
export { deriveInvocationId, uuidv5 } from './workflow-invocation-id.js'
|
|
17
22
|
|
|
23
|
+
export { isRef } from './graph/workflow-graph.types.js'
|
|
24
|
+
export type { RefValue } from './graph/workflow-graph.types.js'
|
|
25
|
+
|
|
18
26
|
export {
|
|
19
27
|
buildRunTimeline,
|
|
20
28
|
reconstructStateAt,
|
|
@@ -22,10 +30,7 @@ export {
|
|
|
22
30
|
} from './run-timeline.js'
|
|
23
31
|
export type {
|
|
24
32
|
RunTimeline,
|
|
25
|
-
RunTimelineEvent,
|
|
26
33
|
ReconstructedRunState,
|
|
27
|
-
ReconstructedStep,
|
|
28
|
-
RunPhase,
|
|
29
34
|
} from './run-timeline.js'
|
|
30
35
|
|
|
31
36
|
export { addWorkflow } from './dsl/workflow-runner.js'
|
|
@@ -37,12 +42,6 @@ export {
|
|
|
37
42
|
type PikkuWorkflowGraphConfig,
|
|
38
43
|
type PikkuWorkflowGraphResult,
|
|
39
44
|
} from './graph/wire-workflow-graph.js'
|
|
40
|
-
|
|
41
|
-
export {
|
|
42
|
-
pikkuWorkflowWorkerFunc,
|
|
43
|
-
pikkuWorkflowOrchestratorFunc,
|
|
44
|
-
pikkuWorkflowSleeperFunc,
|
|
45
|
-
} from './workflow-queue-workers.js'
|
|
46
45
|
export type {
|
|
47
46
|
WorkflowStepInput as WorkflowStepQueueInput,
|
|
48
47
|
PikkuWorkflowOrchestratorInput,
|
|
@@ -65,34 +64,25 @@ export type {
|
|
|
65
64
|
WorkflowRunMirror,
|
|
66
65
|
CoreWorkflow,
|
|
67
66
|
CoreFeature,
|
|
68
|
-
CoreFeatureScenario,
|
|
69
67
|
FeatureMeta,
|
|
70
|
-
FeatureMetaEntry,
|
|
71
68
|
FeaturesMeta,
|
|
72
69
|
FeaturePlanEntry,
|
|
73
70
|
PikkuWorkflow,
|
|
74
71
|
ContextVariable,
|
|
75
72
|
WorkflowContext,
|
|
76
73
|
WorkflowsMeta,
|
|
77
|
-
WorkflowRuntimeMeta,
|
|
78
74
|
WorkflowsRuntimeMeta,
|
|
79
75
|
} from './workflow.types.js'
|
|
80
76
|
|
|
81
77
|
export type {
|
|
82
78
|
WorkflowStepOptions,
|
|
83
79
|
WorkflowWireDoRPC,
|
|
84
|
-
WorkflowWireDoInline,
|
|
85
|
-
WorkflowWireSleep,
|
|
86
|
-
WorkflowWireSuspend,
|
|
87
|
-
WorkflowWireApproval,
|
|
88
80
|
WorkflowApprovalOptions,
|
|
89
81
|
ApprovalOutcome,
|
|
90
82
|
InputSource,
|
|
91
83
|
OutputBinding,
|
|
92
84
|
RpcStepMeta,
|
|
93
|
-
SimpleCondition,
|
|
94
85
|
Condition,
|
|
95
|
-
BranchCase,
|
|
96
86
|
BranchStepMeta,
|
|
97
87
|
ParallelGroupStepMeta,
|
|
98
88
|
FanoutStepMeta,
|
|
@@ -127,7 +117,7 @@ export type {
|
|
|
127
117
|
export { SCENARIO_SURFACES } from './scenario-step.types.js'
|
|
128
118
|
|
|
129
119
|
// Which of a step's bindings run: one for an action, every witness for a `then`
|
|
130
|
-
export { resolveScenarioSurfaces
|
|
120
|
+
export { resolveScenarioSurfaces } from './scenario-surface.js'
|
|
131
121
|
|
|
132
122
|
export { requireActor, requireScenarioEnv } from './scenario-step-guards.js'
|
|
133
123
|
|