@pikku/core 0.12.82 → 0.12.84
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 +101 -0
- package/README.md +1 -1
- package/dist/ecosystem/agent-scorer.d.ts +12 -0
- package/dist/ecosystem/agent-scorer.js +5 -0
- package/dist/ecosystem/agent.d.ts +18 -0
- package/dist/ecosystem/agent.js +6 -0
- package/dist/ecosystem/ai-agent.d.ts +18 -0
- package/dist/ecosystem/ai-agent.js +6 -0
- package/dist/ecosystem/ai-scorer.d.ts +12 -0
- package/dist/ecosystem/ai-scorer.js +5 -0
- package/dist/ecosystem/channel/local.d.ts +1 -0
- package/dist/ecosystem/channel/local.js +1 -0
- package/dist/ecosystem/channel.d.ts +12 -0
- package/dist/ecosystem/channel.js +4 -0
- package/dist/ecosystem/cli/channel.d.ts +16 -0
- package/dist/ecosystem/cli/channel.js +2 -0
- package/dist/ecosystem/cli.d.ts +9 -0
- package/dist/ecosystem/cli.js +2 -0
- package/dist/ecosystem/credential.d.ts +9 -0
- package/dist/ecosystem/credential.js +1 -0
- package/dist/ecosystem/dev.d.ts +8 -0
- package/dist/ecosystem/dev.js +1 -0
- package/dist/ecosystem/function.d.ts +13 -0
- package/dist/ecosystem/function.js +2 -0
- package/dist/ecosystem/gateway.d.ts +1 -0
- package/dist/ecosystem/gateway.js +1 -0
- package/dist/ecosystem/hmac.d.ts +1 -0
- package/dist/ecosystem/hmac.js +1 -0
- package/dist/ecosystem/http.d.ts +11 -0
- package/dist/ecosystem/http.js +3 -0
- package/dist/ecosystem/mcp.d.ts +3 -0
- package/dist/ecosystem/mcp.js +2 -0
- package/dist/ecosystem/middleware.d.ts +17 -0
- package/dist/ecosystem/middleware.js +6 -0
- package/dist/ecosystem/node-host-resolver.d.ts +1 -0
- package/dist/ecosystem/node-host-resolver.js +1 -0
- package/dist/ecosystem/node.d.ts +1 -0
- package/dist/ecosystem/node.js +1 -0
- package/dist/ecosystem/oauth2.d.ts +1 -0
- package/dist/ecosystem/oauth2.js +1 -0
- package/dist/ecosystem/persona.d.ts +15 -0
- package/dist/ecosystem/persona.js +4 -0
- package/dist/ecosystem/queue.d.ts +11 -0
- package/dist/ecosystem/queue.js +2 -0
- package/dist/ecosystem/remote.d.ts +8 -0
- package/dist/ecosystem/remote.js +1 -0
- package/dist/ecosystem/role.d.ts +3 -0
- package/dist/ecosystem/role.js +2 -0
- package/dist/ecosystem/rpc.d.ts +4 -0
- package/dist/ecosystem/rpc.js +2 -0
- package/dist/ecosystem/safe-fetch.d.ts +7 -0
- package/dist/ecosystem/safe-fetch.js +1 -0
- package/dist/ecosystem/scenario.d.ts +15 -0
- package/dist/ecosystem/scenario.js +4 -0
- package/dist/ecosystem/scheduler.d.ts +2 -0
- package/dist/ecosystem/scheduler.js +1 -0
- package/dist/ecosystem/schema.d.ts +1 -0
- package/dist/ecosystem/schema.js +1 -0
- package/dist/ecosystem/scope.d.ts +3 -0
- package/dist/ecosystem/scope.js +2 -0
- package/dist/ecosystem/secret.d.ts +9 -0
- package/dist/ecosystem/secret.js +1 -0
- package/dist/ecosystem/services/istanbul-coverage.d.ts +1 -0
- package/dist/ecosystem/services/istanbul-coverage.js +1 -0
- package/dist/ecosystem/services/local-content-request-handler.d.ts +9 -0
- package/dist/ecosystem/services/local-content-request-handler.js +1 -0
- package/dist/ecosystem/services/local-content.d.ts +1 -0
- package/dist/ecosystem/services/local-content.js +1 -0
- package/dist/ecosystem/services/v8-coverage.d.ts +1 -0
- package/dist/ecosystem/services/v8-coverage.js +1 -0
- package/dist/ecosystem/services.d.ts +28 -0
- package/dist/ecosystem/services.js +6 -0
- package/dist/ecosystem/testing.d.ts +7 -0
- package/dist/ecosystem/testing.js +1 -0
- package/dist/ecosystem/trigger.d.ts +1 -0
- package/dist/ecosystem/trigger.js +1 -0
- package/dist/ecosystem/types.d.ts +9 -0
- package/dist/ecosystem/types.js +5 -0
- package/dist/ecosystem/variable.d.ts +8 -0
- package/dist/ecosystem/variable.js +1 -0
- package/dist/ecosystem/virtual-user.d.ts +21 -0
- package/dist/ecosystem/virtual-user.js +5 -0
- package/dist/ecosystem/workflow.d.ts +18 -0
- package/dist/ecosystem/workflow.js +4 -0
- package/dist/index.d.ts +8 -8
- package/dist/index.js +3 -3
- package/dist/middleware/auth-apikey.d.ts +1 -1
- package/dist/middleware/auth-bearer.d.ts +1 -1
- package/dist/middleware/auth-cookie.d.ts +1 -1
- package/dist/middleware/cors.d.ts +1 -1
- package/dist/middleware/remote-auth.d.ts +1 -1
- package/dist/middleware/telemetry.d.ts +2 -2
- package/dist/services/agent-run-state-service.d.ts +29 -0
- package/dist/services/agent-run-state-service.js +1 -0
- package/dist/services/agent-runner-service.d.ts +220 -0
- package/dist/services/agent-runner-service.js +1 -0
- package/dist/services/agent-storage-service.d.ts +18 -0
- package/dist/services/agent-storage-service.js +1 -0
- package/dist/services/http-personas.d.ts +1 -1
- package/dist/services/http-personas.js +3 -3
- package/dist/services/in-memory-agent-run-state-service.d.ts +19 -0
- package/dist/services/in-memory-agent-run-state-service.js +54 -0
- package/dist/services/index.d.ts +9 -10
- package/dist/services/index.js +3 -3
- package/dist/services/meta-service.d.ts +5 -4
- package/dist/testing/service-tests/agent-run-service-tests.d.ts +1 -1
- package/dist/testing/service-tests/agent-run-service-tests.js +3 -3
- package/dist/testing/service-tests/agent-storage-service-tests.d.ts +3 -0
- package/dist/testing/service-tests/agent-storage-service-tests.js +302 -0
- package/dist/testing/service-tests.d.ts +4 -4
- package/dist/testing/service-tests.js +4 -4
- package/dist/types/core.types.d.ts +12 -11
- package/dist/types/core.types.js +1 -1
- package/dist/types/state.types.d.ts +11 -6
- package/dist/wirings/actor-flow/run-conversation.d.ts +2 -2
- package/dist/wirings/agent/agent-agui.d.ts +79 -0
- package/dist/wirings/agent/agent-agui.js +327 -0
- package/dist/wirings/agent/agent-finalize.d.ts +58 -0
- package/dist/wirings/agent/agent-finalize.js +138 -0
- package/dist/wirings/agent/agent-helpers.d.ts +35 -0
- package/dist/wirings/agent/agent-helpers.js +47 -0
- package/dist/wirings/agent/agent-interrupt.d.ts +153 -0
- package/dist/wirings/agent/agent-interrupt.js +257 -0
- package/dist/wirings/agent/agent-memory.d.ts +42 -0
- package/dist/wirings/agent/agent-memory.js +333 -0
- package/dist/wirings/agent/agent-model-config.d.ts +16 -0
- package/dist/wirings/agent/agent-model-config.js +51 -0
- package/dist/wirings/agent/agent-prepare.d.ts +117 -0
- package/dist/wirings/agent/agent-prepare.js +728 -0
- package/dist/wirings/agent/agent-registry.d.ts +16 -0
- package/dist/wirings/agent/agent-registry.js +51 -0
- package/dist/wirings/agent/agent-rpc.d.ts +15 -0
- package/dist/wirings/agent/agent-rpc.js +53 -0
- package/dist/wirings/agent/agent-runner.d.ts +7 -0
- package/dist/wirings/agent/agent-runner.js +580 -0
- package/dist/wirings/agent/agent-stream.d.ts +41 -0
- package/dist/wirings/agent/agent-stream.js +1029 -0
- package/dist/wirings/agent/agent-turn.d.ts +57 -0
- package/dist/wirings/agent/agent-turn.js +82 -0
- package/dist/wirings/agent/agent-utils.d.ts +1 -0
- package/dist/wirings/agent/agent-utils.js +1 -0
- package/dist/wirings/agent/agent.types.d.ts +625 -0
- package/dist/wirings/agent/agent.types.js +1 -0
- package/dist/wirings/agent/index.d.ts +12 -0
- package/dist/wirings/agent/index.js +10 -0
- package/dist/wirings/agent/voice-input.d.ts +69 -0
- package/dist/wirings/agent/voice-input.js +150 -0
- package/dist/wirings/agent/voice-output.d.ts +85 -0
- package/dist/wirings/agent/voice-output.js +196 -0
- package/dist/wirings/agent-scorer/agent-scorer-grade.d.ts +26 -0
- package/dist/wirings/agent-scorer/agent-scorer-grade.js +33 -0
- package/dist/wirings/agent-scorer/agent-scorer-judge.d.ts +17 -0
- package/dist/wirings/agent-scorer/agent-scorer-judge.js +92 -0
- package/dist/wirings/agent-scorer/agent-scorer-live.d.ts +15 -0
- package/dist/wirings/agent-scorer/agent-scorer-live.js +38 -0
- package/dist/wirings/agent-scorer/agent-scorer-registry.d.ts +18 -0
- package/dist/wirings/agent-scorer/agent-scorer-registry.js +46 -0
- package/dist/wirings/agent-scorer/agent-scorer-sampling.d.ts +8 -0
- package/dist/wirings/agent-scorer/agent-scorer-sampling.js +31 -0
- package/dist/wirings/agent-scorer/agent-scorer-snapshots.d.ts +10 -0
- package/dist/wirings/agent-scorer/agent-scorer-snapshots.js +40 -0
- package/dist/wirings/agent-scorer/agent-scorer-worker.d.ts +15 -0
- package/dist/wirings/agent-scorer/agent-scorer-worker.js +60 -0
- package/dist/wirings/agent-scorer/agent-scorer.d.ts +39 -0
- package/dist/wirings/agent-scorer/agent-scorer.js +40 -0
- package/dist/wirings/agent-scorer/agent-scorer.types.d.ts +90 -0
- package/dist/wirings/agent-scorer/agent-scorer.types.js +4 -0
- package/dist/wirings/agent-scorer/index.d.ts +6 -0
- package/dist/wirings/agent-scorer/index.js +5 -0
- package/dist/wirings/ai-agent/ai-agent-prepare.js +2 -0
- package/dist/wirings/ai-agent/voice-output.d.ts +1 -2
- package/dist/wirings/channel/channel-rpc.types.d.ts +2 -2
- package/dist/wirings/rpc/addon-runner.d.ts +4 -0
- package/dist/wirings/rpc/addon-runner.js +14 -2
- package/dist/wirings/rpc/rpc-runner.d.ts +1 -1
- package/dist/wirings/rpc/rpc-runner.js +4 -2
- package/dist/wirings/rpc/rpc-types.d.ts +5 -1
- package/dist/wirings/rpc/wire-addon.d.ts +12 -0
- package/dist/wirings/rpc/wire-addon.js +4 -0
- package/dist/wirings/virtual-user/prepare-virtual-user-run.js +1 -1
- package/dist/wirings/virtual-user/virtual-user-agents.d.ts +1 -1
- package/dist/wirings/workflow/feature.d.ts +2 -1
- package/dist/wirings/workflow/index.d.ts +3 -14
- package/dist/wirings/workflow/index.js +0 -8
- package/dist/wirings/workflow/pikku-scenario-service.d.ts +10 -0
- package/dist/wirings/workflow/pikku-scenario-service.js +9 -0
- package/dist/wirings/workflow/run-timeline.d.ts +1 -2
- package/dist/wirings/workflow/scenario.types.d.ts +37 -0
- package/dist/wirings/workflow/scenario.types.js +1 -0
- package/dist/wirings/workflow/workflow.types.d.ts +2 -37
- package/knowledge/decisions/internals/{a-non-streaming-agent-run-registers-with-airunstate-too.md → a-non-streaming-agent-run-registers-with-agentrunstate-too.md} +6 -6
- package/knowledge/decisions/internals/a-resumed-agent-turn-is-as-interruptible-as-the-first.md +1 -1
- package/knowledge/decisions/internals/actor-flow-drives-the-target-through-a-transport-seam.md +1 -1
- package/knowledge/decisions/internals/{ai-agent-agui-bridge-obeys-the-client-ordering-contract.md → agent-agui-bridge-obeys-the-client-ordering-contract.md} +5 -5
- package/knowledge/decisions/internals/{ai-agent-audio-chunks-carry-the-format-the-provider-returned.md → agent-audio-chunks-carry-the-format-the-provider-returned.md} +2 -2
- package/knowledge/decisions/internals/agent-context-waits-for-a-tool-result-still-being-written.md +1 -1
- package/knowledge/decisions/internals/{ai-agent-credential-suspensions-hide-the-tool-result.md → agent-credential-suspensions-hide-the-tool-result.md} +2 -2
- package/knowledge/decisions/internals/{ai-agent-delegate-and-supervise-hide-different-text.md → agent-delegate-and-supervise-hide-different-text.md} +4 -4
- package/knowledge/decisions/internals/{ai-agent-llm-tool-arguments-have-nulls-stripped.md → agent-llm-tool-arguments-have-nulls-stripped.md} +3 -3
- package/knowledge/decisions/internals/{ai-agent-model-config-stays-a-single-resolution-seam.md → agent-model-config-stays-a-single-resolution-seam.md} +3 -3
- package/knowledge/decisions/internals/{ai-agent-onerror-hooks-cannot-change-the-failure.md → agent-onerror-hooks-cannot-change-the-failure.md} +6 -6
- package/knowledge/decisions/internals/{ai-agent-runner-methods-must-keep-their-receiver.md → agent-runner-methods-must-keep-their-receiver.md} +4 -4
- package/knowledge/decisions/internals/agent-speech-travels-as-a-custom-agui-event.md +1 -1
- package/knowledge/decisions/internals/{ai-agent-stream-persistence-is-best-effort.md → agent-stream-persistence-is-best-effort.md} +4 -4
- package/knowledge/decisions/internals/{ai-agent-sub-agents-inherit-the-parent-context-block.md → agent-sub-agents-inherit-the-parent-context-block.md} +3 -3
- package/knowledge/decisions/internals/{ai-agent-tool-execute-failures-are-logged-unconditionally.md → agent-tool-execute-failures-are-logged-unconditionally.md} +3 -3
- package/knowledge/decisions/internals/{ai-agent-voice-input-transcribes-audio-parts-in-place.md → agent-voice-input-transcribes-audio-parts-in-place.md} +2 -2
- package/knowledge/decisions/internals/{ai-agent-working-memory-is-persisted-only-when-valid.md → agent-working-memory-is-persisted-only-when-valid.md} +2 -2
- package/knowledge/decisions/internals/an-agent-interrupt-is-not-a-failure.md +2 -2
- package/knowledge/decisions/internals/an-agent-run-owned-by-another-instance-says-so.md +3 -3
- package/knowledge/decisions/internals/an-agent-stream-send-must-return-the-inner-sends-promise.md +2 -2
- package/knowledge/decisions/internals/an-empty-text-part-is-omitted-from-an-agent-message.md +1 -1
- package/knowledge/decisions/internals/an-empty-transcript-is-not-recorded.md +1 -1
- package/knowledge/decisions/internals/speech-synthesis-picks-a-voice-per-sentence-and-warns-once.md +1 -1
- package/knowledge/decisions/internals/the-agent-done-event-goes-through-the-middleware-and-is-awaited.md +1 -1
- package/knowledge/decisions/internals/the-embedding-model-is-pinned-per-service-and-doc-query-embedding-is-split.md +1 -1
- package/knowledge/decisions/internals/the-per-invocation-rpc-view-is-a-class.md +5 -5
- package/knowledge/decisions/internals/the-transcript-event-is-sent-ahead-of-the-run.md +2 -2
- package/knowledge/decisions/internals/thread-history-records-the-transcript-not-the-audio.md +2 -2
- package/knowledge/decisions/internals/voice-output-speaks-unless-voice-input-explicitly-says-otherwise.md +1 -1
- package/knowledge/decisions/security/{ai-agent-approval-forwarding-requires-a-symbol-brand.md → agent-approval-forwarding-requires-a-symbol-brand.md} +3 -3
- package/knowledge/decisions/security/{ai-agent-credential-requests-are-symbol-branded.md → agent-credential-requests-are-symbol-branded.md} +4 -4
- package/knowledge/decisions/security/{ai-agent-gate-requires-a-session-only-when-auth-is-true.md → agent-gate-requires-a-session-only-when-auth-is-true.md} +3 -3
- package/knowledge/decisions/security/{ai-agent-ownership-failures-never-echo-the-resource.md → agent-ownership-failures-never-echo-the-resource.md} +2 -2
- package/knowledge/decisions/security/{ai-agent-resume-re-runs-the-authorization-gate.md → agent-resume-re-runs-the-authorization-gate.md} +4 -4
- package/knowledge/decisions/security/{ai-agent-sessionless-deployments-have-no-thread-ownership.md → agent-sessionless-deployments-have-no-thread-ownership.md} +5 -5
- package/knowledge/decisions/security/{ai-agent-thread-ownership-composes-the-session-principal.md → agent-thread-ownership-composes-the-session-principal.md} +2 -2
- package/knowledge/decisions/security/{ai-agent-tool-filtering-reads-the-live-function-config.md → agent-tool-filtering-reads-the-live-function-config.md} +2 -2
- package/knowledge/decisions/security/an-agent-approval-is-claimed-before-the-tool-runs.md +3 -3
- package/knowledge/decisions/security/an-empty-owners-constraint-matches-nothing.md +3 -3
- package/knowledge/decisions/security/console-addon-privileged-functions-gate-themselves.md +20 -13
- package/knowledge/decisions/security/index.md +1 -2
- package/package.json +4 -4
- package/scripts/generate-api-report.mts +32 -8
- package/src/agent-naming.test.ts +68 -0
- package/src/ecosystem/agent-scorer.ts +24 -0
- package/src/ecosystem/agent.ts +42 -0
- package/src/ecosystem/channel/local.ts +1 -0
- package/src/ecosystem/channel.ts +22 -0
- package/src/ecosystem/cli/channel.ts +25 -0
- package/src/ecosystem/cli.ts +21 -0
- package/src/ecosystem/credential.ts +10 -0
- package/src/ecosystem/dev.ts +12 -0
- package/src/ecosystem/function.ts +28 -0
- package/src/ecosystem/gateway.ts +4 -0
- package/src/ecosystem/hmac.ts +1 -0
- package/src/ecosystem/http.ts +22 -0
- package/src/ecosystem/mcp.ts +17 -0
- package/src/ecosystem/middleware.ts +27 -0
- package/src/ecosystem/node-host-resolver.ts +1 -0
- package/src/ecosystem/node.ts +5 -0
- package/src/ecosystem/oauth2.ts +4 -0
- package/src/ecosystem/persona.ts +30 -0
- package/src/ecosystem/queue.ts +23 -0
- package/src/ecosystem/remote.ts +9 -0
- package/src/ecosystem/role.ts +13 -0
- package/src/ecosystem/rpc.ts +7 -0
- package/src/ecosystem/safe-fetch.ts +8 -0
- package/src/ecosystem/scenario.ts +32 -0
- package/src/ecosystem/scheduler.ts +5 -0
- package/src/ecosystem/schema.ts +1 -0
- package/src/ecosystem/scope.ts +14 -0
- package/src/ecosystem/secret.ts +15 -0
- package/src/ecosystem/services/istanbul-coverage.ts +1 -0
- package/src/ecosystem/services/local-content-request-handler.ts +16 -0
- package/src/ecosystem/services/local-content.ts +1 -0
- package/src/ecosystem/services/v8-coverage.ts +1 -0
- package/src/ecosystem/services.ts +82 -0
- package/src/ecosystem/testing.ts +8 -0
- package/src/ecosystem/trigger.ts +7 -0
- package/src/ecosystem/types.ts +34 -0
- package/src/ecosystem/variable.ts +14 -0
- package/src/ecosystem/virtual-user.ts +48 -0
- package/src/ecosystem/workflow.ts +68 -0
- package/src/index.ts +8 -19
- package/src/pikku-state.ts +3 -3
- package/src/public-surface.json +183 -91
- package/src/public-surface.json.README +20 -2
- package/src/public-surface.test.ts +31 -3
- package/src/services/{ai-run-state-service.ts → agent-run-state-service.ts} +5 -5
- package/src/services/{ai-agent-runner-service.ts → agent-runner-service.ts} +18 -18
- package/src/services/{ai-storage-service.ts → agent-storage-service.ts} +7 -7
- package/src/services/http-personas-converse.test.ts +3 -3
- package/src/services/http-personas.ts +4 -4
- package/src/services/{in-memory-ai-run-state-service.ts → in-memory-agent-run-state-service.ts} +7 -7
- package/src/services/index.ts +13 -24
- package/src/services/meta-service.ts +5 -7
- package/src/testing/service-tests/agent-run-service-tests.ts +4 -4
- package/src/testing/service-tests/{ai-storage-service-tests.ts → agent-storage-service-tests.ts} +8 -8
- package/src/testing/service-tests.ts +10 -8
- package/src/types/core.types.ts +13 -13
- package/src/types/state.types.ts +11 -10
- package/src/wirings/actor-flow/run-conversation.test.ts +2 -2
- package/src/wirings/actor-flow/run-conversation.ts +7 -9
- package/src/wirings/{ai-agent/ai-agent-agui.test.ts → agent/agent-agui.test.ts} +126 -105
- package/src/wirings/{ai-agent/ai-agent-agui.ts → agent/agent-agui.ts} +7 -7
- package/src/wirings/{ai-agent/ai-agent-authorization.test.ts → agent/agent-authorization.test.ts} +6 -6
- package/src/wirings/{ai-agent/ai-agent-finalize.test.ts → agent/agent-finalize.test.ts} +17 -16
- package/src/wirings/{ai-agent/ai-agent-finalize.ts → agent/agent-finalize.ts} +22 -22
- package/src/wirings/{ai-agent/ai-agent-helpers.test.ts → agent/agent-helpers.test.ts} +1 -1
- package/src/wirings/{ai-agent/ai-agent-helpers.ts → agent/agent-helpers.ts} +1 -1
- package/src/wirings/{ai-agent/ai-agent-interrupt.test.ts → agent/agent-interrupt.test.ts} +67 -77
- package/src/wirings/{ai-agent/ai-agent-interrupt.ts → agent/agent-interrupt.ts} +5 -5
- package/src/wirings/{ai-agent/ai-agent-memory.test.ts → agent/agent-memory.test.ts} +12 -12
- package/src/wirings/{ai-agent/ai-agent-memory.ts → agent/agent-memory.ts} +36 -36
- package/src/wirings/{ai-agent/ai-agent-model-config.test.ts → agent/agent-model-config.test.ts} +2 -5
- package/src/wirings/{ai-agent/ai-agent-model-config.ts → agent/agent-model-config.ts} +1 -1
- package/src/wirings/{ai-agent/ai-agent-prepare.test.ts → agent/agent-prepare.test.ts} +18 -18
- package/src/wirings/{ai-agent/ai-agent-prepare.ts → agent/agent-prepare.ts} +54 -51
- package/src/wirings/{ai-agent/ai-agent-registry.test.ts → agent/agent-registry.test.ts} +49 -43
- package/src/wirings/{ai-agent/ai-agent-registry.ts → agent/agent-registry.ts} +14 -14
- package/src/wirings/{ai-agent/ai-agent-resume-authorization.test.ts → agent/agent-resume-authorization.test.ts} +18 -18
- package/src/wirings/{ai-agent → agent}/agent-rpc.ts +16 -20
- package/src/wirings/{ai-agent/ai-agent-runner.test.ts → agent/agent-runner.test.ts} +105 -106
- package/src/wirings/{ai-agent/ai-agent-runner.ts → agent/agent-runner.ts} +90 -80
- package/src/wirings/{ai-agent/ai-agent-stream-output-hooks.test.ts → agent/agent-stream-output-hooks.test.ts} +25 -25
- package/src/wirings/{ai-agent/ai-agent-stream.test.ts → agent/agent-stream.test.ts} +147 -143
- package/src/wirings/{ai-agent/ai-agent-stream.ts → agent/agent-stream.ts} +147 -146
- package/src/wirings/{ai-agent/ai-agent-thread-ownership.test.ts → agent/agent-thread-ownership.test.ts} +24 -28
- package/src/wirings/{ai-agent/ai-agent-turn.test.ts → agent/agent-turn.test.ts} +3 -5
- package/src/wirings/{ai-agent/ai-agent-turn.ts → agent/agent-turn.ts} +7 -7
- package/src/wirings/{ai-agent/ai-agent.types.ts → agent/agent.types.ts} +51 -48
- package/src/wirings/agent/index.ts +56 -0
- package/src/wirings/{ai-agent → agent}/voice-input.test.ts +15 -15
- package/src/wirings/{ai-agent → agent}/voice-input.ts +11 -11
- package/src/wirings/{ai-agent → agent}/voice-output.test.ts +23 -23
- package/src/wirings/{ai-agent → agent}/voice-output.ts +11 -11
- package/src/wirings/{ai-scorer/ai-scorer-grade.test.ts → agent-scorer/agent-scorer-grade.test.ts} +8 -8
- package/src/wirings/{ai-scorer/ai-scorer-grade.ts → agent-scorer/agent-scorer-grade.ts} +9 -9
- package/src/wirings/{ai-scorer/ai-scorer-judge.test.ts → agent-scorer/agent-scorer-judge.test.ts} +11 -14
- package/src/wirings/{ai-scorer/ai-scorer-judge.ts → agent-scorer/agent-scorer-judge.ts} +11 -11
- package/src/wirings/{ai-scorer/ai-scorer-live.test.ts → agent-scorer/agent-scorer-live.test.ts} +11 -11
- package/src/wirings/{ai-scorer/ai-scorer-live.ts → agent-scorer/agent-scorer-live.ts} +3 -3
- package/src/wirings/{ai-scorer/ai-scorer-registry.ts → agent-scorer/agent-scorer-registry.ts} +11 -8
- package/src/wirings/{ai-scorer/ai-scorer-sampling.test.ts → agent-scorer/agent-scorer-sampling.test.ts} +1 -1
- package/src/wirings/{ai-scorer/ai-scorer-snapshots.test.ts → agent-scorer/agent-scorer-snapshots.test.ts} +2 -2
- package/src/wirings/{ai-scorer/ai-scorer-snapshots.ts → agent-scorer/agent-scorer-snapshots.ts} +1 -1
- package/src/wirings/{ai-scorer/ai-scorer-worker.test.ts → agent-scorer/agent-scorer-worker.test.ts} +15 -15
- package/src/wirings/{ai-scorer/ai-scorer-worker.ts → agent-scorer/agent-scorer-worker.ts} +9 -7
- package/src/wirings/{ai-scorer/ai-scorer.ts → agent-scorer/agent-scorer.ts} +7 -7
- package/src/wirings/{ai-scorer/ai-scorer.types.ts → agent-scorer/agent-scorer.types.ts} +6 -6
- package/src/wirings/agent-scorer/index.ts +22 -0
- package/src/wirings/channel/channel-rpc.types.ts +2 -2
- package/src/wirings/rpc/addon-runner.ts +31 -3
- package/src/wirings/rpc/addon-secrets.test.ts +130 -0
- package/src/wirings/rpc/rpc-runner.ts +4 -2
- package/src/wirings/rpc/rpc-types.ts +5 -1
- package/src/wirings/rpc/wire-addon.ts +16 -0
- package/src/wirings/virtual-user/prepare-virtual-user-run.ts +1 -1
- package/src/wirings/virtual-user/run-virtual-user.test.ts +2 -2
- package/src/wirings/virtual-user/run-virtual-user.ts +3 -3
- package/src/wirings/virtual-user/virtual-user-agents.ts +1 -1
- package/src/wirings/workflow/feature.ts +2 -5
- package/src/wirings/workflow/index.ts +1 -49
- package/src/wirings/workflow/pikku-scenario-service.ts +21 -1
- package/src/wirings/workflow/run-timeline.ts +1 -1
- package/src/wirings/workflow/scenario.types.ts +63 -0
- package/src/wirings/workflow/workflow.types.ts +1 -54
- package/src/wirings-stay-decoupled.test.ts +3 -3
- package/tsconfig.tsbuildinfo +1 -1
- package/src/wirings/ai-agent/index.ts +0 -65
- package/src/wirings/ai-scorer/index.ts +0 -24
- /package/src/wirings/{ai-agent/ai-agent-utils.ts → agent/agent-utils.ts} +0 -0
- /package/src/wirings/{ai-scorer/ai-scorer-sampling.ts → agent-scorer/agent-scorer-sampling.ts} +0 -0
|
@@ -2,12 +2,8 @@ import { beforeEach, describe, test } from 'node:test'
|
|
|
2
2
|
import assert from 'node:assert/strict'
|
|
3
3
|
|
|
4
4
|
import { resetPikkuState, pikkuState } from '../../pikku-state.js'
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
resumeAIAgent,
|
|
8
|
-
streamAIAgent,
|
|
9
|
-
} from './ai-agent-stream.js'
|
|
10
|
-
import { runAIAgent, resumeAIAgentSync } from './ai-agent-runner.js'
|
|
5
|
+
import { interruptAgent, resumeAgent, streamAgent } from './agent-stream.js'
|
|
6
|
+
import { runAgent, resumeAgentSync } from './agent-runner.js'
|
|
11
7
|
import {
|
|
12
8
|
AgentInterruptedError,
|
|
13
9
|
awaitPendingInterruptNote,
|
|
@@ -17,25 +13,25 @@ import {
|
|
|
17
13
|
registerInterruptibleRun,
|
|
18
14
|
signalRunInterrupt,
|
|
19
15
|
trackToolExecution,
|
|
20
|
-
} from './
|
|
16
|
+
} from './agent-interrupt.js'
|
|
21
17
|
import { AbandonedError, beginChanges } from '../../function/abort-scope.js'
|
|
22
18
|
import type {
|
|
23
19
|
AgentRunState,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
} from './
|
|
20
|
+
AgentMessage,
|
|
21
|
+
AgentStreamEvent,
|
|
22
|
+
CoreAgent,
|
|
23
|
+
} from './agent.types.js'
|
|
28
24
|
import type {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
} from '../../services/
|
|
25
|
+
AgentRunnerParams,
|
|
26
|
+
AgentStepResult,
|
|
27
|
+
} from '../../services/agent-runner-service.js'
|
|
32
28
|
|
|
33
29
|
beforeEach(() => {
|
|
34
30
|
resetPikkuState()
|
|
35
31
|
})
|
|
36
32
|
|
|
37
33
|
const addTestAgent = (agentName: string) => {
|
|
38
|
-
const agent:
|
|
34
|
+
const agent: CoreAgent = {
|
|
39
35
|
name: agentName,
|
|
40
36
|
description: 'test agent',
|
|
41
37
|
goal: 'be helpful',
|
|
@@ -62,9 +58,9 @@ const abortError = () => {
|
|
|
62
58
|
*/
|
|
63
59
|
const interruptingRunner = (getRunId: () => string | undefined) => ({
|
|
64
60
|
stream: async (
|
|
65
|
-
params:
|
|
66
|
-
channel: { send: (event:
|
|
67
|
-
): Promise<
|
|
61
|
+
params: AgentRunnerParams,
|
|
62
|
+
channel: { send: (event: AgentStreamEvent) => void }
|
|
63
|
+
): Promise<AgentStepResult> => {
|
|
68
64
|
channel.send({ type: 'text-delta', text: 'I will delete the staging ' })
|
|
69
65
|
const runId = getRunId()
|
|
70
66
|
assert.ok(runId, 'run should exist before the model call')
|
|
@@ -80,7 +76,7 @@ describe('agent interruption', () => {
|
|
|
80
76
|
addTestAgent('interrupted-agent')
|
|
81
77
|
|
|
82
78
|
const updates: Array<{ runId: string; patch: unknown }> = []
|
|
83
|
-
const events:
|
|
79
|
+
const events: AgentStreamEvent[] = []
|
|
84
80
|
let runId: string | undefined
|
|
85
81
|
|
|
86
82
|
pikkuState(null, 'package', 'singletonServices', {
|
|
@@ -90,8 +86,8 @@ describe('agent interruption', () => {
|
|
|
90
86
|
error: () => {},
|
|
91
87
|
debug: () => {},
|
|
92
88
|
},
|
|
93
|
-
|
|
94
|
-
|
|
89
|
+
agentRunner: interruptingRunner(() => runId),
|
|
90
|
+
agentRunState: {
|
|
95
91
|
createRun: async () => 'run-interrupted',
|
|
96
92
|
updateRun: async (id: string, patch: unknown) => {
|
|
97
93
|
updates.push({ runId: id, patch })
|
|
@@ -99,7 +95,7 @@ describe('agent interruption', () => {
|
|
|
99
95
|
},
|
|
100
96
|
} as any)
|
|
101
97
|
|
|
102
|
-
const text = await
|
|
98
|
+
const text = await streamAgent(
|
|
103
99
|
'interrupted-agent',
|
|
104
100
|
{
|
|
105
101
|
message: 'delete staging',
|
|
@@ -110,7 +106,7 @@ describe('agent interruption', () => {
|
|
|
110
106
|
channelId: 'channel-int',
|
|
111
107
|
openingData: undefined,
|
|
112
108
|
state: 'open',
|
|
113
|
-
send: (event:
|
|
109
|
+
send: (event: AgentStreamEvent) => events.push(event),
|
|
114
110
|
close: () => {},
|
|
115
111
|
} as any,
|
|
116
112
|
{},
|
|
@@ -144,7 +140,7 @@ describe('agent interruption', () => {
|
|
|
144
140
|
test('persists the truncated reply marked as interrupted', async () => {
|
|
145
141
|
addTestAgent('interrupted-persisting-agent')
|
|
146
142
|
|
|
147
|
-
const saved:
|
|
143
|
+
const saved: AgentMessage[] = []
|
|
148
144
|
let runId: string | undefined
|
|
149
145
|
|
|
150
146
|
pikkuState(null, 'package', 'singletonServices', {
|
|
@@ -154,21 +150,21 @@ describe('agent interruption', () => {
|
|
|
154
150
|
error: () => {},
|
|
155
151
|
debug: () => {},
|
|
156
152
|
},
|
|
157
|
-
|
|
158
|
-
|
|
153
|
+
agentRunner: interruptingRunner(() => runId),
|
|
154
|
+
agentRunState: {
|
|
159
155
|
createRun: async () => 'run-persist-int',
|
|
160
156
|
updateRun: async () => {},
|
|
161
157
|
},
|
|
162
|
-
|
|
158
|
+
agentStorage: {
|
|
163
159
|
createThread: async () => {},
|
|
164
160
|
getMessages: async () => [],
|
|
165
|
-
saveMessages: async (_threadId: string, messages:
|
|
161
|
+
saveMessages: async (_threadId: string, messages: AgentMessage[]) => {
|
|
166
162
|
saved.push(...messages)
|
|
167
163
|
},
|
|
168
164
|
},
|
|
169
165
|
} as any)
|
|
170
166
|
|
|
171
|
-
await
|
|
167
|
+
await streamAgent(
|
|
172
168
|
'interrupted-persisting-agent',
|
|
173
169
|
{
|
|
174
170
|
message: 'delete staging',
|
|
@@ -209,8 +205,8 @@ describe('agent interruption', () => {
|
|
|
209
205
|
error: () => {},
|
|
210
206
|
debug: () => {},
|
|
211
207
|
},
|
|
212
|
-
|
|
213
|
-
stream: async (): Promise<
|
|
208
|
+
agentRunner: {
|
|
209
|
+
stream: async (): Promise<AgentStepResult> => ({
|
|
214
210
|
text: 'done',
|
|
215
211
|
toolCalls: [],
|
|
216
212
|
toolResults: [],
|
|
@@ -218,13 +214,13 @@ describe('agent interruption', () => {
|
|
|
218
214
|
finishReason: 'stop',
|
|
219
215
|
}),
|
|
220
216
|
},
|
|
221
|
-
|
|
217
|
+
agentRunState: {
|
|
222
218
|
createRun: async () => 'run-released',
|
|
223
219
|
updateRun: async () => {},
|
|
224
220
|
},
|
|
225
221
|
} as any)
|
|
226
222
|
|
|
227
|
-
await
|
|
223
|
+
await streamAgent(
|
|
228
224
|
'released-agent',
|
|
229
225
|
{ message: 'hi', threadId: 't', resourceId: 'r' },
|
|
230
226
|
{
|
|
@@ -279,7 +275,7 @@ describe('tool results that outlive an interrupt', () => {
|
|
|
279
275
|
test('a tool still running when the user cuts in is kept, not dropped', async () => {
|
|
280
276
|
addTestAgent('tool-interrupt-agent')
|
|
281
277
|
|
|
282
|
-
const saved:
|
|
278
|
+
const saved: AgentMessage[] = []
|
|
283
279
|
let runId: string | undefined
|
|
284
280
|
let releaseTool: (value: string) => void
|
|
285
281
|
const toolFinished = new Promise<string>((resolve) => {
|
|
@@ -294,11 +290,11 @@ describe('tool results that outlive an interrupt', () => {
|
|
|
294
290
|
error: () => {},
|
|
295
291
|
debug: () => {},
|
|
296
292
|
},
|
|
297
|
-
|
|
293
|
+
agentRunner: {
|
|
298
294
|
stream: async (
|
|
299
|
-
params:
|
|
300
|
-
channel: { send: (event:
|
|
301
|
-
): Promise<
|
|
295
|
+
params: AgentRunnerParams,
|
|
296
|
+
channel: { send: (event: AgentStreamEvent) => void }
|
|
297
|
+
): Promise<AgentStepResult> => {
|
|
302
298
|
// The agent kicks off a deploy and starts narrating it; the user talks
|
|
303
299
|
// over the narration while the deploy is still running.
|
|
304
300
|
const tool = params.tools[0]
|
|
@@ -311,20 +307,20 @@ describe('tool results that outlive an interrupt', () => {
|
|
|
311
307
|
throw abortError()
|
|
312
308
|
},
|
|
313
309
|
},
|
|
314
|
-
|
|
310
|
+
agentRunState: {
|
|
315
311
|
createRun: async () => 'run-tool-int',
|
|
316
312
|
updateRun: async () => {},
|
|
317
313
|
},
|
|
318
|
-
|
|
314
|
+
agentStorage: {
|
|
319
315
|
createThread: async () => {},
|
|
320
316
|
getMessages: async () => [],
|
|
321
|
-
saveMessages: async (_threadId: string, messages:
|
|
317
|
+
saveMessages: async (_threadId: string, messages: AgentMessage[]) => {
|
|
322
318
|
saved.push(...messages)
|
|
323
319
|
},
|
|
324
320
|
},
|
|
325
321
|
} as any)
|
|
326
322
|
|
|
327
|
-
await
|
|
323
|
+
await streamAgent(
|
|
328
324
|
'tool-interrupt-agent',
|
|
329
325
|
{ message: 'deploy staging', threadId: 'thread-tool', resourceId: 'r' },
|
|
330
326
|
{
|
|
@@ -457,7 +453,7 @@ describe('tool results that outlive an interrupt', () => {
|
|
|
457
453
|
|
|
458
454
|
/**
|
|
459
455
|
* The non-streaming path (`rpc.agent.run` / `rpc.agent.approve`) creates runs
|
|
460
|
-
* through the same `
|
|
456
|
+
* through the same `agentRunState`, so `interruptAgent` resolves and authorizes
|
|
461
457
|
* them either way. If it did not also register an abort controller, that call
|
|
462
458
|
* would pass the ownership check, fail to stop anything, and — because the run
|
|
463
459
|
* is still marked `running` — report it as executing on another instance.
|
|
@@ -471,7 +467,7 @@ describe('non-streaming agent interruption', () => {
|
|
|
471
467
|
}
|
|
472
468
|
|
|
473
469
|
const interruptingSyncRunner = (runId: string) => ({
|
|
474
|
-
run: async (params:
|
|
470
|
+
run: async (params: AgentRunnerParams): Promise<AgentStepResult> => {
|
|
475
471
|
assert.ok(params.abortSignal, 'the runner must receive an abort signal')
|
|
476
472
|
assert.equal(
|
|
477
473
|
isRunInterruptible(runId),
|
|
@@ -484,14 +480,14 @@ describe('non-streaming agent interruption', () => {
|
|
|
484
480
|
},
|
|
485
481
|
})
|
|
486
482
|
|
|
487
|
-
test('
|
|
483
|
+
test('runAgent reports an interrupt as an interrupt, not a failure', async () => {
|
|
488
484
|
addTestAgent('sync-agent')
|
|
489
485
|
|
|
490
486
|
const updates: unknown[] = []
|
|
491
487
|
pikkuState(null, 'package', 'singletonServices', {
|
|
492
488
|
logger,
|
|
493
|
-
|
|
494
|
-
|
|
489
|
+
agentRunner: interruptingSyncRunner('run-sync-int'),
|
|
490
|
+
agentRunState: {
|
|
495
491
|
createRun: async () => 'run-sync-int',
|
|
496
492
|
updateRun: async (_runId: string, patch: unknown) => {
|
|
497
493
|
updates.push(patch)
|
|
@@ -501,7 +497,7 @@ describe('non-streaming agent interruption', () => {
|
|
|
501
497
|
|
|
502
498
|
await assert.rejects(
|
|
503
499
|
() =>
|
|
504
|
-
|
|
500
|
+
runAgent(
|
|
505
501
|
'sync-agent',
|
|
506
502
|
{ message: 'delete staging', threadId: 't', resourceId: 'r' },
|
|
507
503
|
{}
|
|
@@ -525,8 +521,8 @@ describe('non-streaming agent interruption', () => {
|
|
|
525
521
|
|
|
526
522
|
pikkuState(null, 'package', 'singletonServices', {
|
|
527
523
|
logger,
|
|
528
|
-
|
|
529
|
-
run: async (): Promise<
|
|
524
|
+
agentRunner: {
|
|
525
|
+
run: async (): Promise<AgentStepResult> => ({
|
|
530
526
|
text: 'done',
|
|
531
527
|
toolCalls: [],
|
|
532
528
|
toolResults: [],
|
|
@@ -534,13 +530,13 @@ describe('non-streaming agent interruption', () => {
|
|
|
534
530
|
finishReason: 'stop',
|
|
535
531
|
}),
|
|
536
532
|
},
|
|
537
|
-
|
|
533
|
+
agentRunState: {
|
|
538
534
|
createRun: async () => 'run-sync-clean',
|
|
539
535
|
updateRun: async () => {},
|
|
540
536
|
},
|
|
541
537
|
} as any)
|
|
542
538
|
|
|
543
|
-
await
|
|
539
|
+
await runAgent(
|
|
544
540
|
'sync-clean-agent',
|
|
545
541
|
{ message: 'hi', threadId: 't', resourceId: 'r' },
|
|
546
542
|
{}
|
|
@@ -567,8 +563,8 @@ describe('non-streaming agent interruption', () => {
|
|
|
567
563
|
const updates: unknown[] = []
|
|
568
564
|
pikkuState(null, 'package', 'singletonServices', {
|
|
569
565
|
logger,
|
|
570
|
-
|
|
571
|
-
|
|
566
|
+
agentRunner: interruptingSyncRunner('run-sync-resume'),
|
|
567
|
+
agentRunState: {
|
|
572
568
|
getRun: async () => run,
|
|
573
569
|
createRun: async () => 'unused',
|
|
574
570
|
updateRun: async (_runId: string, patch: unknown) => {
|
|
@@ -580,7 +576,7 @@ describe('non-streaming agent interruption', () => {
|
|
|
580
576
|
|
|
581
577
|
await assert.rejects(
|
|
582
578
|
() =>
|
|
583
|
-
|
|
579
|
+
resumeAgentSync('run-sync-resume', [], {
|
|
584
580
|
sessionService: { get: () => ({ userId: 'resource-sync-resume' }) },
|
|
585
581
|
} as any),
|
|
586
582
|
(error: unknown) => error instanceof AgentInterruptedError
|
|
@@ -628,7 +624,7 @@ describe('streaming resume interruption', () => {
|
|
|
628
624
|
}
|
|
629
625
|
|
|
630
626
|
const updates: unknown[] = []
|
|
631
|
-
const events:
|
|
627
|
+
const events: AgentStreamEvent[] = []
|
|
632
628
|
|
|
633
629
|
pikkuState(null, 'package', 'singletonServices', {
|
|
634
630
|
logger: {
|
|
@@ -637,8 +633,8 @@ describe('streaming resume interruption', () => {
|
|
|
637
633
|
error: () => {},
|
|
638
634
|
debug: () => {},
|
|
639
635
|
},
|
|
640
|
-
|
|
641
|
-
|
|
636
|
+
agentRunner: interruptingRunner(() => run.runId),
|
|
637
|
+
agentRunState: {
|
|
642
638
|
getRun: async () => run,
|
|
643
639
|
createRun: async () => run.runId,
|
|
644
640
|
updateRun: async (_runId: string, patch: unknown) => {
|
|
@@ -653,13 +649,13 @@ describe('streaming resume interruption', () => {
|
|
|
653
649
|
},
|
|
654
650
|
} as any)
|
|
655
651
|
|
|
656
|
-
await
|
|
652
|
+
await resumeAgent(
|
|
657
653
|
{ runId: run.runId, toolCallId: 'call-1', approved: true },
|
|
658
654
|
{
|
|
659
655
|
channelId: 'channel-resume',
|
|
660
656
|
openingData: undefined,
|
|
661
657
|
state: 'open',
|
|
662
|
-
send: (event:
|
|
658
|
+
send: (event: AgentStreamEvent) => events.push(event),
|
|
663
659
|
close: () => {},
|
|
664
660
|
} as any,
|
|
665
661
|
{
|
|
@@ -685,7 +681,7 @@ describe('streaming resume interruption', () => {
|
|
|
685
681
|
})
|
|
686
682
|
})
|
|
687
683
|
|
|
688
|
-
describe('
|
|
684
|
+
describe('interruptAgent authorization', () => {
|
|
689
685
|
const withRun = (run: Record<string, unknown> | null) => {
|
|
690
686
|
pikkuState(null, 'package', 'singletonServices', {
|
|
691
687
|
logger: {
|
|
@@ -694,7 +690,7 @@ describe('interruptAIAgent authorization', () => {
|
|
|
694
690
|
error: () => {},
|
|
695
691
|
debug: () => {},
|
|
696
692
|
},
|
|
697
|
-
|
|
693
|
+
agentRunState: { getRun: async () => run },
|
|
698
694
|
} as any)
|
|
699
695
|
}
|
|
700
696
|
|
|
@@ -713,7 +709,7 @@ describe('interruptAIAgent authorization', () => {
|
|
|
713
709
|
|
|
714
710
|
const handle = registerInterruptibleRun('run-alice')
|
|
715
711
|
await assert.rejects(
|
|
716
|
-
() =>
|
|
712
|
+
() => interruptAgent({ runId: 'run-alice' }, session('mallory') as any),
|
|
717
713
|
/Not authorized to access this run/
|
|
718
714
|
)
|
|
719
715
|
// The gate has to hold before the abort, not after it.
|
|
@@ -732,7 +728,7 @@ describe('interruptAIAgent authorization', () => {
|
|
|
732
728
|
|
|
733
729
|
const handle = registerInterruptibleRun('run-alice-2')
|
|
734
730
|
await assert.rejects(
|
|
735
|
-
() =>
|
|
731
|
+
() => interruptAgent({ runId: 'run-alice-2' }, session('alice') as any),
|
|
736
732
|
/Not authorized to access this run/
|
|
737
733
|
)
|
|
738
734
|
assert.equal(handle.signal.aborted, false)
|
|
@@ -749,7 +745,7 @@ describe('interruptAIAgent authorization', () => {
|
|
|
749
745
|
})
|
|
750
746
|
|
|
751
747
|
const handle = registerInterruptibleRun('run-mine')
|
|
752
|
-
const result = await
|
|
748
|
+
const result = await interruptAgent(
|
|
753
749
|
{ runId: 'run-mine', reason: 'speech' },
|
|
754
750
|
session('alice') as any
|
|
755
751
|
)
|
|
@@ -769,10 +765,7 @@ describe('interruptAIAgent authorization', () => {
|
|
|
769
765
|
})
|
|
770
766
|
|
|
771
767
|
assert.deepEqual(
|
|
772
|
-
await
|
|
773
|
-
{ runId: 'run-finished' },
|
|
774
|
-
session('alice') as any
|
|
775
|
-
),
|
|
768
|
+
await interruptAgent({ runId: 'run-finished' }, session('alice') as any),
|
|
776
769
|
{ stopped: false, inFlightTools: [] }
|
|
777
770
|
)
|
|
778
771
|
})
|
|
@@ -787,7 +780,7 @@ describe('interruptAIAgent authorization', () => {
|
|
|
787
780
|
error: () => {},
|
|
788
781
|
debug: () => {},
|
|
789
782
|
},
|
|
790
|
-
|
|
783
|
+
agentRunState: {
|
|
791
784
|
getRun: async () => ({
|
|
792
785
|
runId: 'run-elsewhere',
|
|
793
786
|
agentName: 'remote-agent',
|
|
@@ -799,10 +792,7 @@ describe('interruptAIAgent authorization', () => {
|
|
|
799
792
|
} as any)
|
|
800
793
|
|
|
801
794
|
assert.deepEqual(
|
|
802
|
-
await
|
|
803
|
-
{ runId: 'run-elsewhere' },
|
|
804
|
-
session('alice') as any
|
|
805
|
-
),
|
|
795
|
+
await interruptAgent({ runId: 'run-elsewhere' }, session('alice') as any),
|
|
806
796
|
{ stopped: false, inFlightTools: [] }
|
|
807
797
|
)
|
|
808
798
|
assert.equal(warnings.length, 1)
|
|
@@ -819,7 +809,7 @@ describe('interruptAIAgent authorization', () => {
|
|
|
819
809
|
error: () => {},
|
|
820
810
|
debug: () => {},
|
|
821
811
|
},
|
|
822
|
-
|
|
812
|
+
agentRunState: {
|
|
823
813
|
getRun: async () => ({
|
|
824
814
|
runId: 'run-done',
|
|
825
815
|
agentName: 'done-agent',
|
|
@@ -829,14 +819,14 @@ describe('interruptAIAgent authorization', () => {
|
|
|
829
819
|
},
|
|
830
820
|
} as any)
|
|
831
821
|
|
|
832
|
-
await
|
|
822
|
+
await interruptAgent({ runId: 'run-done' }, session('alice') as any)
|
|
833
823
|
assert.deepEqual(warnings, [])
|
|
834
824
|
})
|
|
835
825
|
|
|
836
826
|
test('rejects an unknown runId', async () => {
|
|
837
827
|
withRun(null)
|
|
838
828
|
await assert.rejects(
|
|
839
|
-
() =>
|
|
829
|
+
() => interruptAgent({ runId: 'nope' }, session('alice') as any),
|
|
840
830
|
/No run found for runId nope/
|
|
841
831
|
)
|
|
842
832
|
})
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { randomUUID } from './
|
|
1
|
+
import { randomUUID } from './agent-utils.js'
|
|
2
2
|
import {
|
|
3
3
|
AbandonedError,
|
|
4
4
|
runInAbortScope,
|
|
5
5
|
type AbortScope,
|
|
6
6
|
} from '../../function/abort-scope.js'
|
|
7
|
-
import type {
|
|
7
|
+
import type { AgentStorageService } from '../../services/agent-storage-service.js'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Why an in-flight agent run was cut short.
|
|
@@ -12,7 +12,7 @@ import type { AIStorageService } from '../../services/ai-storage-service.js'
|
|
|
12
12
|
* Deliberately carries no interjection text. A voice interruption is not a
|
|
13
13
|
* cancel button — it is the user starting to talk — but what they said arrives
|
|
14
14
|
* a second later as an ordinary next turn on the same thread, and that turn
|
|
15
|
-
* already has a working path through `
|
|
15
|
+
* already has a working path through `streamAgent`. The model then sees its
|
|
16
16
|
* own truncated message (marked `interrupted`) followed by the interjection and
|
|
17
17
|
* decides for itself whether to resume, correct itself or drop the thread.
|
|
18
18
|
* Nothing here classifies the interjection; a second delivery path for the same
|
|
@@ -219,7 +219,7 @@ export const registerInterruptibleRun = (
|
|
|
219
219
|
* Stop a run that is generating right now.
|
|
220
220
|
*
|
|
221
221
|
* Plumbing: this performs NO authorization, so anyone holding a runId can stop
|
|
222
|
-
* it. Reach for {@link
|
|
222
|
+
* it. Reach for {@link interruptAgent} instead unless the caller has already
|
|
223
223
|
* established that the run belongs to the session — which in practice means
|
|
224
224
|
* only the runner itself and code already inside an authorized run.
|
|
225
225
|
*
|
|
@@ -359,7 +359,7 @@ export const awaitPendingInterruptNote = async (
|
|
|
359
359
|
*/
|
|
360
360
|
export const persistOrphanedToolResults = async (
|
|
361
361
|
handle: InterruptibleRunHandle,
|
|
362
|
-
storage:
|
|
362
|
+
storage: AgentStorageService,
|
|
363
363
|
threadId: string
|
|
364
364
|
): Promise<void> => {
|
|
365
365
|
let orphaned: OrphanedToolResult[]
|
|
@@ -12,14 +12,14 @@ import {
|
|
|
12
12
|
saveMessages,
|
|
13
13
|
stripWorkingMemoryTags,
|
|
14
14
|
trimMessages,
|
|
15
|
-
} from './
|
|
16
|
-
import type {
|
|
15
|
+
} from './agent-memory.js'
|
|
16
|
+
import type { AgentMessage, CoreAgent } from './agent.types.js'
|
|
17
17
|
|
|
18
18
|
beforeEach(() => {
|
|
19
19
|
resetPikkuState()
|
|
20
20
|
})
|
|
21
21
|
|
|
22
|
-
const makeMessage = (overrides: Partial<
|
|
22
|
+
const makeMessage = (overrides: Partial<AgentMessage>): AgentMessage => ({
|
|
23
23
|
id: 'msg',
|
|
24
24
|
role: 'user',
|
|
25
25
|
content: 'hello',
|
|
@@ -27,19 +27,19 @@ const makeMessage = (overrides: Partial<AIMessage>): AIMessage => ({
|
|
|
27
27
|
...overrides,
|
|
28
28
|
})
|
|
29
29
|
|
|
30
|
-
describe('
|
|
31
|
-
test('resolveMemoryServices prefers named storage and falls back to
|
|
30
|
+
describe('agent-memory', () => {
|
|
31
|
+
test('resolveMemoryServices prefers named storage and falls back to agentStorage', () => {
|
|
32
32
|
const singletonServices = {
|
|
33
|
-
|
|
33
|
+
agentStorage: { kind: 'default' },
|
|
34
34
|
customStorage: { kind: 'custom' },
|
|
35
35
|
} as any
|
|
36
36
|
|
|
37
|
-
const defaultAgent = {} as
|
|
38
|
-
const namedAgent = { memory: { storage: 'customStorage' } } as
|
|
37
|
+
const defaultAgent = {} as CoreAgent
|
|
38
|
+
const namedAgent = { memory: { storage: 'customStorage' } } as CoreAgent
|
|
39
39
|
|
|
40
40
|
assert.equal(
|
|
41
41
|
resolveMemoryServices(defaultAgent, singletonServices).storage,
|
|
42
|
-
singletonServices.
|
|
42
|
+
singletonServices.agentStorage
|
|
43
43
|
)
|
|
44
44
|
assert.equal(
|
|
45
45
|
resolveMemoryServices(namedAgent, singletonServices).storage,
|
|
@@ -139,10 +139,10 @@ describe('ai-agent-memory', () => {
|
|
|
139
139
|
})
|
|
140
140
|
|
|
141
141
|
test('saveMessages persists tool calls and strips working memory tags from returned text', async () => {
|
|
142
|
-
const savedMessages:
|
|
142
|
+
const savedMessages: AgentMessage[][] = []
|
|
143
143
|
|
|
144
144
|
const storage = {
|
|
145
|
-
saveMessages: async (_threadId: string, messages:
|
|
145
|
+
saveMessages: async (_threadId: string, messages: AgentMessage[]) => {
|
|
146
146
|
savedMessages.push(messages)
|
|
147
147
|
},
|
|
148
148
|
} as any
|
|
@@ -265,7 +265,7 @@ describe('ai-agent-memory', () => {
|
|
|
265
265
|
})
|
|
266
266
|
|
|
267
267
|
test('trimMessages sanitizes orphaned tool messages and keeps first user/system boundary', () => {
|
|
268
|
-
const messages:
|
|
268
|
+
const messages: AgentMessage[] = [
|
|
269
269
|
makeMessage({
|
|
270
270
|
id: 'assistant-1',
|
|
271
271
|
role: 'assistant',
|