@copilotkit/runtime 1.55.0-next.9 → 1.55.1-next.0
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 +31 -2
- package/dist/agent/index.cjs +101 -12
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts.map +1 -1
- package/dist/agent/index.d.mts.map +1 -1
- package/dist/agent/index.mjs +102 -13
- package/dist/agent/index.mjs.map +1 -1
- package/dist/lib/runtime/agent-integrations/langgraph/agent.cjs.map +1 -1
- package/dist/lib/runtime/agent-integrations/langgraph/agent.d.cts +4 -841
- package/dist/lib/runtime/agent-integrations/langgraph/agent.d.cts.map +1 -1
- package/dist/lib/runtime/agent-integrations/langgraph/agent.d.mts +4 -841
- package/dist/lib/runtime/agent-integrations/langgraph/agent.d.mts.map +1 -1
- package/dist/lib/runtime/agent-integrations/langgraph/agent.mjs.map +1 -1
- package/dist/lib/runtime/copilot-runtime.cjs +3 -2
- package/dist/lib/runtime/copilot-runtime.cjs.map +1 -1
- package/dist/lib/runtime/copilot-runtime.d.cts +1 -1
- package/dist/lib/runtime/copilot-runtime.d.cts.map +1 -1
- package/dist/lib/runtime/copilot-runtime.d.mts +3 -3
- package/dist/lib/runtime/copilot-runtime.d.mts.map +1 -1
- package/dist/lib/runtime/copilot-runtime.mjs +3 -2
- package/dist/lib/runtime/copilot-runtime.mjs.map +1 -1
- package/dist/package.cjs +70 -47
- package/dist/package.mjs +70 -47
- package/dist/v2/express.cjs +8 -0
- package/dist/v2/express.d.cts +5 -0
- package/dist/v2/express.d.mts +5 -0
- package/dist/v2/express.mjs +5 -0
- package/dist/v2/hono.cjs +9 -0
- package/dist/v2/hono.d.cts +5 -0
- package/dist/v2/hono.d.mts +5 -0
- package/dist/v2/hono.mjs +5 -0
- package/dist/v2/index.cjs +8 -3
- package/dist/v2/index.d.cts +8 -5
- package/dist/v2/index.d.mts +8 -5
- package/dist/v2/index.mjs +5 -4
- package/dist/v2/node.cjs +8 -0
- package/dist/v2/node.d.cts +5 -0
- package/dist/v2/node.d.mts +5 -0
- package/dist/v2/node.mjs +5 -0
- package/dist/v2/runtime/core/fetch-cors.cjs +72 -0
- package/dist/v2/runtime/core/fetch-cors.cjs.map +1 -0
- package/dist/v2/runtime/core/fetch-cors.d.cts +20 -0
- package/dist/v2/runtime/core/fetch-cors.d.cts.map +1 -0
- package/dist/v2/runtime/core/fetch-cors.d.mts +20 -0
- package/dist/v2/runtime/core/fetch-cors.d.mts.map +1 -0
- package/dist/v2/runtime/core/fetch-cors.mjs +70 -0
- package/dist/v2/runtime/core/fetch-cors.mjs.map +1 -0
- package/dist/v2/runtime/core/fetch-handler.cjs +232 -0
- package/dist/v2/runtime/core/fetch-handler.cjs.map +1 -0
- package/dist/v2/runtime/core/fetch-handler.d.cts +40 -0
- package/dist/v2/runtime/core/fetch-handler.d.cts.map +1 -0
- package/dist/v2/runtime/core/fetch-handler.d.mts +40 -0
- package/dist/v2/runtime/core/fetch-handler.d.mts.map +1 -0
- package/dist/v2/runtime/core/fetch-handler.mjs +231 -0
- package/dist/v2/runtime/core/fetch-handler.mjs.map +1 -0
- package/dist/v2/runtime/core/fetch-router.cjs +68 -0
- package/dist/v2/runtime/core/fetch-router.cjs.map +1 -0
- package/dist/v2/runtime/core/fetch-router.mjs +67 -0
- package/dist/v2/runtime/core/fetch-router.mjs.map +1 -0
- package/dist/v2/runtime/core/hooks.cjs +29 -0
- package/dist/v2/runtime/core/hooks.cjs.map +1 -0
- package/dist/v2/runtime/core/hooks.d.cts +78 -0
- package/dist/v2/runtime/core/hooks.d.cts.map +1 -0
- package/dist/v2/runtime/core/hooks.d.mts +78 -0
- package/dist/v2/runtime/core/hooks.d.mts.map +1 -0
- package/dist/v2/runtime/core/hooks.mjs +25 -0
- package/dist/v2/runtime/core/hooks.mjs.map +1 -0
- package/dist/v2/runtime/{middleware-sse-parser.cjs → core/middleware-sse-parser.cjs} +2 -2
- package/dist/v2/runtime/core/middleware-sse-parser.cjs.map +1 -0
- package/dist/v2/runtime/{middleware-sse-parser.d.cts → core/middleware-sse-parser.d.cts} +1 -1
- package/dist/v2/runtime/core/middleware-sse-parser.d.cts.map +1 -0
- package/dist/v2/runtime/{middleware-sse-parser.d.mts → core/middleware-sse-parser.d.mts} +1 -1
- package/dist/v2/runtime/core/middleware-sse-parser.d.mts.map +1 -0
- package/dist/v2/runtime/{middleware-sse-parser.mjs → core/middleware-sse-parser.mjs} +1 -1
- package/dist/v2/runtime/core/middleware-sse-parser.mjs.map +1 -0
- package/dist/v2/runtime/{middleware.cjs → core/middleware.cjs} +2 -2
- package/dist/v2/runtime/core/middleware.cjs.map +1 -0
- package/dist/v2/runtime/{middleware.d.cts → core/middleware.d.cts} +1 -1
- package/dist/v2/runtime/core/middleware.d.cts.map +1 -0
- package/dist/v2/runtime/{middleware.d.mts → core/middleware.d.mts} +1 -1
- package/dist/v2/runtime/core/middleware.d.mts.map +1 -0
- package/dist/v2/runtime/{middleware.mjs → core/middleware.mjs} +1 -1
- package/dist/v2/runtime/core/middleware.mjs.map +1 -0
- package/dist/v2/runtime/{runtime.cjs → core/runtime.cjs} +35 -10
- package/dist/v2/runtime/core/runtime.cjs.map +1 -0
- package/dist/v2/runtime/{runtime.d.cts → core/runtime.d.cts} +41 -7
- package/dist/v2/runtime/core/runtime.d.cts.map +1 -0
- package/dist/v2/runtime/{runtime.d.mts → core/runtime.d.mts} +42 -8
- package/dist/v2/runtime/core/runtime.d.mts.map +1 -0
- package/dist/v2/runtime/{runtime.mjs → core/runtime.mjs} +36 -11
- package/dist/v2/runtime/core/runtime.mjs.map +1 -0
- package/dist/v2/runtime/endpoints/express-fetch-bridge.cjs +83 -0
- package/dist/v2/runtime/endpoints/express-fetch-bridge.cjs.map +1 -0
- package/dist/v2/runtime/endpoints/express-fetch-bridge.mjs +82 -0
- package/dist/v2/runtime/endpoints/express-fetch-bridge.mjs.map +1 -0
- package/dist/v2/runtime/endpoints/express-single.cjs +35 -181
- package/dist/v2/runtime/endpoints/express-single.cjs.map +1 -1
- package/dist/v2/runtime/endpoints/express-single.d.cts +35 -2
- package/dist/v2/runtime/endpoints/express-single.d.cts.map +1 -1
- package/dist/v2/runtime/endpoints/express-single.d.mts +35 -2
- package/dist/v2/runtime/endpoints/express-single.d.mts.map +1 -1
- package/dist/v2/runtime/endpoints/express-single.mjs +35 -178
- package/dist/v2/runtime/endpoints/express-single.mjs.map +1 -1
- package/dist/v2/runtime/endpoints/express.cjs +41 -195
- package/dist/v2/runtime/endpoints/express.cjs.map +1 -1
- package/dist/v2/runtime/endpoints/express.d.cts +26 -4
- package/dist/v2/runtime/endpoints/express.d.cts.map +1 -1
- package/dist/v2/runtime/endpoints/express.d.mts +26 -4
- package/dist/v2/runtime/endpoints/express.d.mts.map +1 -1
- package/dist/v2/runtime/endpoints/express.mjs +41 -195
- package/dist/v2/runtime/endpoints/express.mjs.map +1 -1
- package/dist/v2/runtime/endpoints/hono-single.cjs +11 -123
- package/dist/v2/runtime/endpoints/hono-single.cjs.map +1 -1
- package/dist/v2/runtime/endpoints/hono-single.d.cts +14 -11
- package/dist/v2/runtime/endpoints/hono-single.d.cts.map +1 -1
- package/dist/v2/runtime/endpoints/hono-single.d.mts +14 -11
- package/dist/v2/runtime/endpoints/hono-single.d.mts.map +1 -1
- package/dist/v2/runtime/endpoints/hono-single.mjs +11 -123
- package/dist/v2/runtime/endpoints/hono-single.mjs.map +1 -1
- package/dist/v2/runtime/endpoints/hono.cjs +23 -237
- package/dist/v2/runtime/endpoints/hono.cjs.map +1 -1
- package/dist/v2/runtime/endpoints/hono.d.cts +29 -120
- package/dist/v2/runtime/endpoints/hono.d.cts.map +1 -1
- package/dist/v2/runtime/endpoints/hono.d.mts +29 -120
- package/dist/v2/runtime/endpoints/hono.d.mts.map +1 -1
- package/dist/v2/runtime/endpoints/hono.mjs +22 -238
- package/dist/v2/runtime/endpoints/hono.mjs.map +1 -1
- package/dist/v2/runtime/endpoints/index.d.cts +2 -2
- package/dist/v2/runtime/endpoints/index.d.mts +2 -2
- package/dist/v2/runtime/endpoints/node-fetch-handler.cjs +26 -0
- package/dist/v2/runtime/endpoints/node-fetch-handler.cjs.map +1 -0
- package/dist/v2/runtime/endpoints/node-fetch-handler.d.cts +12 -0
- package/dist/v2/runtime/endpoints/node-fetch-handler.d.cts.map +1 -0
- package/dist/v2/runtime/endpoints/node-fetch-handler.d.mts +12 -0
- package/dist/v2/runtime/endpoints/node-fetch-handler.d.mts.map +1 -0
- package/dist/v2/runtime/endpoints/node-fetch-handler.mjs +24 -0
- package/dist/v2/runtime/endpoints/node-fetch-handler.mjs.map +1 -0
- package/dist/v2/runtime/endpoints/node.cjs +30 -0
- package/dist/v2/runtime/endpoints/node.cjs.map +1 -0
- package/dist/v2/runtime/endpoints/node.d.cts +27 -0
- package/dist/v2/runtime/endpoints/node.d.cts.map +1 -0
- package/dist/v2/runtime/endpoints/node.d.mts +27 -0
- package/dist/v2/runtime/endpoints/node.d.mts.map +1 -0
- package/dist/v2/runtime/endpoints/node.mjs +30 -0
- package/dist/v2/runtime/endpoints/node.mjs.map +1 -0
- package/dist/v2/runtime/express.d.cts +3 -0
- package/dist/v2/runtime/express.d.mts +3 -0
- package/dist/v2/runtime/handlers/get-runtime-info.cjs +2 -1
- package/dist/v2/runtime/handlers/get-runtime-info.cjs.map +1 -1
- package/dist/v2/runtime/handlers/get-runtime-info.mjs +2 -1
- package/dist/v2/runtime/handlers/get-runtime-info.mjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-connect.cjs +6 -3
- package/dist/v2/runtime/handlers/handle-connect.cjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-connect.mjs +6 -3
- package/dist/v2/runtime/handlers/handle-connect.mjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-run.cjs +6 -3
- package/dist/v2/runtime/handlers/handle-run.cjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-run.mjs +6 -3
- package/dist/v2/runtime/handlers/handle-run.mjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-stop.cjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-stop.mjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-transcribe.cjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-transcribe.mjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/connect.cjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/connect.mjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/run.cjs +22 -1
- package/dist/v2/runtime/handlers/intelligence/run.cjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/run.mjs +22 -1
- package/dist/v2/runtime/handlers/intelligence/run.mjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/thread-names.cjs +1 -1
- package/dist/v2/runtime/handlers/intelligence/thread-names.cjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/thread-names.mjs +1 -1
- package/dist/v2/runtime/handlers/intelligence/thread-names.mjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/agent-utils.cjs +21 -6
- package/dist/v2/runtime/handlers/shared/agent-utils.cjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/agent-utils.mjs +21 -6
- package/dist/v2/runtime/handlers/shared/agent-utils.mjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/json-response.cjs +4 -1
- package/dist/v2/runtime/handlers/shared/json-response.cjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/json-response.mjs +4 -1
- package/dist/v2/runtime/handlers/shared/json-response.mjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/resolve-intelligence-user.cjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/resolve-intelligence-user.mjs.map +1 -1
- package/dist/v2/runtime/handlers/sse/connect.cjs.map +1 -1
- package/dist/v2/runtime/handlers/sse/connect.mjs.map +1 -1
- package/dist/v2/runtime/handlers/sse/run.cjs.map +1 -1
- package/dist/v2/runtime/handlers/sse/run.mjs.map +1 -1
- package/dist/v2/runtime/hono.d.cts +3 -0
- package/dist/v2/runtime/hono.d.mts +3 -0
- package/dist/v2/runtime/index.d.cts +16 -4
- package/dist/v2/runtime/index.d.cts.map +1 -0
- package/dist/v2/runtime/index.d.mts +16 -4
- package/dist/v2/runtime/index.d.mts.map +1 -0
- package/dist/v2/runtime/intelligence-platform/client.cjs +10 -1
- package/dist/v2/runtime/intelligence-platform/client.cjs.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.d.cts +22 -0
- package/dist/v2/runtime/intelligence-platform/client.d.cts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.d.mts +22 -0
- package/dist/v2/runtime/intelligence-platform/client.d.mts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.mjs +10 -1
- package/dist/v2/runtime/intelligence-platform/client.mjs.map +1 -1
- package/dist/v2/runtime/node.d.cts +3 -0
- package/dist/v2/runtime/node.d.mts +3 -0
- package/dist/v2/runtime/open-generative-ui-middleware.cjs +282 -0
- package/dist/v2/runtime/open-generative-ui-middleware.cjs.map +1 -0
- package/dist/v2/runtime/open-generative-ui-middleware.mjs +280 -0
- package/dist/v2/runtime/open-generative-ui-middleware.mjs.map +1 -0
- package/dist/v2/runtime/runner/intelligence.cjs +4 -4
- package/dist/v2/runtime/runner/intelligence.cjs.map +1 -1
- package/dist/v2/runtime/runner/intelligence.d.cts +6 -2
- package/dist/v2/runtime/runner/intelligence.d.cts.map +1 -1
- package/dist/v2/runtime/runner/intelligence.d.mts +6 -2
- package/dist/v2/runtime/runner/intelligence.d.mts.map +1 -1
- package/dist/v2/runtime/runner/intelligence.mjs +4 -4
- package/dist/v2/runtime/runner/intelligence.mjs.map +1 -1
- package/dist/v2/runtime/telemetry/telemetry-client.cjs +37 -0
- package/dist/v2/runtime/telemetry/telemetry-client.cjs.map +1 -1
- package/dist/v2/runtime/telemetry/telemetry-client.mjs +36 -0
- package/dist/v2/runtime/telemetry/telemetry-client.mjs.map +1 -1
- package/dist/v2/runtime/telemetry/utils.cjs +15 -0
- package/dist/v2/runtime/telemetry/utils.cjs.map +1 -0
- package/dist/v2/runtime/telemetry/utils.mjs +14 -0
- package/dist/v2/runtime/telemetry/utils.mjs.map +1 -0
- package/package.json +81 -48
- package/src/agent/__tests__/multimodal.test.ts +176 -0
- package/src/agent/index.ts +130 -19
- package/src/lib/runtime/agent-integrations/langgraph/agent.ts +3 -3
- package/src/lib/runtime/copilot-runtime.ts +1 -0
- package/src/v2/express.ts +1 -0
- package/src/v2/hono.ts +1 -0
- package/src/v2/node.ts +1 -0
- package/src/v2/runtime/__tests__/backward-compat.test.ts +261 -0
- package/src/v2/runtime/__tests__/code-review-fixes.test.ts +500 -0
- package/src/v2/runtime/__tests__/cors-credentials.test.ts +2 -2
- package/src/v2/runtime/__tests__/express-adapter.test.ts +188 -0
- package/src/v2/runtime/__tests__/express-body-order.test.ts +1 -1
- package/src/v2/runtime/__tests__/express-fetch-bridge.test.ts +344 -0
- package/src/v2/runtime/__tests__/express-single-sse.test.ts +1 -1
- package/src/v2/runtime/__tests__/fetch-cors.test.ts +205 -0
- package/src/v2/runtime/__tests__/fetch-handler-validation.test.ts +372 -0
- package/src/v2/runtime/__tests__/fetch-handler.test.ts +456 -0
- package/src/v2/runtime/__tests__/fetch-router.test.ts +132 -0
- package/src/v2/runtime/__tests__/get-runtime-info.test.ts +4 -1
- package/src/v2/runtime/__tests__/handle-connect.test.ts +15 -13
- package/src/v2/runtime/__tests__/handle-run.test.ts +21 -17
- package/src/v2/runtime/__tests__/handle-threads.test.ts +1 -1
- package/src/v2/runtime/__tests__/handle-transcribe.test.ts +1 -1
- package/src/v2/runtime/__tests__/hono-adapter.test.ts +150 -0
- package/src/v2/runtime/__tests__/hooks-edge-cases.test.ts +457 -0
- package/src/v2/runtime/__tests__/hooks.test.ts +557 -0
- package/src/v2/runtime/__tests__/integration/bun/bun-servers.integration.test.ts +27 -0
- package/src/v2/runtime/__tests__/integration/bun/elysia-multi.ts +32 -0
- package/src/v2/runtime/__tests__/integration/bun/elysia-single.ts +33 -0
- package/src/v2/runtime/__tests__/integration/bun/hono-bun-multi.ts +25 -0
- package/src/v2/runtime/__tests__/integration/bun/hono-bun-single.ts +32 -0
- package/src/v2/runtime/__tests__/integration/helpers/create-test-runtime.ts +15 -0
- package/src/v2/runtime/__tests__/integration/helpers/sse-reader.ts +45 -0
- package/src/v2/runtime/__tests__/integration/helpers/test-agent.ts +58 -0
- package/src/v2/runtime/__tests__/integration/node-servers.integration.test.ts +39 -0
- package/src/v2/runtime/__tests__/integration/servers/express-multi.ts +35 -0
- package/src/v2/runtime/__tests__/integration/servers/express-single.ts +36 -0
- package/src/v2/runtime/__tests__/integration/servers/fetch-direct.ts +39 -0
- package/src/v2/runtime/__tests__/integration/servers/hono-multi.ts +30 -0
- package/src/v2/runtime/__tests__/integration/servers/hono-single.ts +37 -0
- package/src/v2/runtime/__tests__/integration/servers/node-multi.ts +45 -0
- package/src/v2/runtime/__tests__/integration/servers/node-single.ts +46 -0
- package/src/v2/runtime/__tests__/integration/servers/types.ts +18 -0
- package/src/v2/runtime/__tests__/integration/suites/multi-endpoint.suite.ts +358 -0
- package/src/v2/runtime/__tests__/integration/suites/single-endpoint.suite.ts +363 -0
- package/src/v2/runtime/__tests__/middleware-express.test.ts +1 -1
- package/src/v2/runtime/__tests__/middleware-single-express.test.ts +1 -1
- package/src/v2/runtime/__tests__/middleware-single.test.ts +1 -1
- package/src/v2/runtime/__tests__/middleware-sse-parser.test.ts +1 -1
- package/src/v2/runtime/__tests__/middleware.test.ts +1 -2
- package/src/v2/runtime/__tests__/node-fetch-handler.test.ts +157 -0
- package/src/v2/runtime/__tests__/open-generative-ui-middleware.e2e.test.ts +728 -0
- package/src/v2/runtime/__tests__/router-edge-cases.test.ts +217 -0
- package/src/v2/runtime/__tests__/routing-express.test.ts +1 -1
- package/src/v2/runtime/__tests__/routing-single-express.test.ts +1 -1
- package/src/v2/runtime/__tests__/routing-single.test.ts +1 -1
- package/src/v2/runtime/__tests__/routing.test.ts +1 -1
- package/src/v2/runtime/__tests__/runtime.test.ts +110 -1
- package/src/v2/runtime/__tests__/telemetry.test.ts +62 -1
- package/src/v2/runtime/core/fetch-cors.ts +136 -0
- package/src/v2/runtime/core/fetch-handler.ts +415 -0
- package/src/v2/runtime/core/fetch-router.ts +112 -0
- package/src/v2/runtime/core/hooks.ts +151 -0
- package/src/v2/runtime/{runtime.ts → core/runtime.ts} +79 -10
- package/src/v2/runtime/endpoints/express-fetch-bridge.ts +137 -0
- package/src/v2/runtime/endpoints/express-single.ts +42 -219
- package/src/v2/runtime/endpoints/express.ts +128 -230
- package/src/v2/runtime/endpoints/hono-single.ts +19 -171
- package/src/v2/runtime/endpoints/hono.ts +45 -270
- package/src/v2/runtime/endpoints/node-fetch-handler.ts +48 -0
- package/src/v2/runtime/endpoints/node.ts +28 -0
- package/src/v2/runtime/handlers/get-runtime-info.ts +3 -2
- package/src/v2/runtime/handlers/handle-connect.ts +7 -4
- package/src/v2/runtime/handlers/handle-run.ts +7 -4
- package/src/v2/runtime/handlers/handle-stop.ts +1 -1
- package/src/v2/runtime/handlers/handle-transcribe.ts +1 -1
- package/src/v2/runtime/handlers/intelligence/connect.ts +1 -1
- package/src/v2/runtime/handlers/intelligence/run.ts +31 -1
- package/src/v2/runtime/handlers/intelligence/thread-names.ts +2 -2
- package/src/v2/runtime/handlers/intelligence/threads.ts +1 -1
- package/src/v2/runtime/handlers/shared/agent-utils.ts +29 -10
- package/src/v2/runtime/handlers/shared/json-response.ts +4 -1
- package/src/v2/runtime/handlers/shared/resolve-intelligence-user.ts +1 -1
- package/src/v2/runtime/handlers/sse/connect.ts +1 -1
- package/src/v2/runtime/handlers/sse/run.ts +1 -1
- package/src/v2/runtime/hono.ts +2 -0
- package/src/v2/runtime/index.ts +27 -1
- package/src/v2/runtime/intelligence-platform/client.ts +50 -1
- package/src/v2/runtime/node.ts +6 -0
- package/src/v2/runtime/open-generative-ui-middleware.ts +373 -0
- package/src/v2/runtime/runner/intelligence.ts +14 -4
- package/src/v2/runtime/telemetry/telemetry-client.ts +56 -0
- package/src/v2/runtime/telemetry/utils.ts +15 -0
- package/tsdown.config.ts +8 -1
- package/vitest.config.mjs +2 -5
- package/.eslintrc.js +0 -7
- package/dist/v2/runtime/endpoints/express-utils.cjs +0 -119
- package/dist/v2/runtime/endpoints/express-utils.cjs.map +0 -1
- package/dist/v2/runtime/endpoints/express-utils.mjs +0 -117
- package/dist/v2/runtime/endpoints/express-utils.mjs.map +0 -1
- package/dist/v2/runtime/handlers/intelligence/threads.cjs +0 -159
- package/dist/v2/runtime/handlers/intelligence/threads.cjs.map +0 -1
- package/dist/v2/runtime/handlers/intelligence/threads.mjs +0 -154
- package/dist/v2/runtime/handlers/intelligence/threads.mjs.map +0 -1
- package/dist/v2/runtime/middleware-sse-parser.cjs.map +0 -1
- package/dist/v2/runtime/middleware-sse-parser.d.cts.map +0 -1
- package/dist/v2/runtime/middleware-sse-parser.d.mts.map +0 -1
- package/dist/v2/runtime/middleware-sse-parser.mjs.map +0 -1
- package/dist/v2/runtime/middleware.cjs.map +0 -1
- package/dist/v2/runtime/middleware.d.cts.map +0 -1
- package/dist/v2/runtime/middleware.d.mts.map +0 -1
- package/dist/v2/runtime/middleware.mjs.map +0 -1
- package/dist/v2/runtime/runtime.cjs.map +0 -1
- package/dist/v2/runtime/runtime.d.cts.map +0 -1
- package/dist/v2/runtime/runtime.d.mts.map +0 -1
- package/dist/v2/runtime/runtime.mjs.map +0 -1
- package/src/v2/runtime/__tests__/express-abort-signal.test.ts +0 -25
- package/src/v2/runtime/endpoints/express-utils.ts +0 -182
- package/src/v2/runtime/handler.ts +0 -3
- /package/src/v2/runtime/{middleware-sse-parser.ts → core/middleware-sse-parser.ts} +0 -0
- /package/src/v2/runtime/{middleware.ts → core/middleware.ts} +0 -0
|
@@ -0,0 +1,728 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
AbstractAgent,
|
|
4
|
+
BaseEvent,
|
|
5
|
+
EventType,
|
|
6
|
+
RunAgentInput,
|
|
7
|
+
ActivitySnapshotEvent,
|
|
8
|
+
ActivityDeltaEvent,
|
|
9
|
+
} from "@ag-ui/client";
|
|
10
|
+
import { Observable, firstValueFrom } from "rxjs";
|
|
11
|
+
import { toArray } from "rxjs/operators";
|
|
12
|
+
import {
|
|
13
|
+
OpenGenerativeUIMiddleware,
|
|
14
|
+
ArgsParser,
|
|
15
|
+
} from "../open-generative-ui-middleware";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A minimal agent that records the input it receives and emits scripted events.
|
|
19
|
+
*/
|
|
20
|
+
class MockAgent extends AbstractAgent {
|
|
21
|
+
public receivedInput: RunAgentInput | null = null;
|
|
22
|
+
|
|
23
|
+
constructor(private readonly events: BaseEvent[]) {
|
|
24
|
+
super();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
run(input: RunAgentInput): Observable<BaseEvent> {
|
|
28
|
+
this.receivedInput = input;
|
|
29
|
+
return new Observable<BaseEvent>((subscriber) => {
|
|
30
|
+
for (const event of this.events) {
|
|
31
|
+
subscriber.next(event);
|
|
32
|
+
}
|
|
33
|
+
subscriber.complete();
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
clone(): AbstractAgent {
|
|
38
|
+
return new MockAgent([...this.events]);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
protected connect(): ReturnType<AbstractAgent["connect"]> {
|
|
42
|
+
throw new Error("not used");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function createRunInput(overrides: Partial<RunAgentInput> = {}): RunAgentInput {
|
|
47
|
+
return {
|
|
48
|
+
threadId: "thread-1",
|
|
49
|
+
runId: "run-1",
|
|
50
|
+
state: {},
|
|
51
|
+
messages: [],
|
|
52
|
+
tools: [],
|
|
53
|
+
context: [],
|
|
54
|
+
forwardedProps: undefined,
|
|
55
|
+
...overrides,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function collectEvents(
|
|
60
|
+
observable: Observable<BaseEvent>,
|
|
61
|
+
): Promise<BaseEvent[]> {
|
|
62
|
+
return firstValueFrom(observable.pipe(toArray()));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
describe("OpenGenerativeUIMiddleware e2e", () => {
|
|
66
|
+
describe("Tool passthrough", () => {
|
|
67
|
+
it("does not modify the tools list", async () => {
|
|
68
|
+
const middleware = new OpenGenerativeUIMiddleware();
|
|
69
|
+
const agent = new MockAgent([
|
|
70
|
+
{
|
|
71
|
+
type: EventType.RUN_STARTED,
|
|
72
|
+
threadId: "thread-1",
|
|
73
|
+
runId: "run-1",
|
|
74
|
+
} as BaseEvent,
|
|
75
|
+
{
|
|
76
|
+
type: EventType.RUN_FINISHED,
|
|
77
|
+
threadId: "thread-1",
|
|
78
|
+
runId: "run-1",
|
|
79
|
+
} as BaseEvent,
|
|
80
|
+
]);
|
|
81
|
+
|
|
82
|
+
const input = createRunInput();
|
|
83
|
+
await collectEvents(middleware.run(input, agent));
|
|
84
|
+
|
|
85
|
+
expect(agent.receivedInput!.tools).toEqual(input.tools);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
describe("ArgsParser (streaming JSON via clarinet)", () => {
|
|
90
|
+
const noop = () => {};
|
|
91
|
+
|
|
92
|
+
it("parses a complete JSON object in one chunk", () => {
|
|
93
|
+
const parser = new ArgsParser("tc-1", noop);
|
|
94
|
+
parser.write(
|
|
95
|
+
'{"initialHeight":400,"html":"<div>hi</div>","jsFunctions":"function foo(){}","jsExpressions":["expr1","expr2"]}',
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
expect(parser.params).toEqual({
|
|
99
|
+
initialHeight: 400,
|
|
100
|
+
html: "<div>hi</div>",
|
|
101
|
+
jsFunctions: "function foo(){}",
|
|
102
|
+
jsExpressions: ["expr1", "expr2"],
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("streams html as incremental chunks via textNode", () => {
|
|
107
|
+
const emitted: BaseEvent[] = [];
|
|
108
|
+
const parser = new ArgsParser("tc-1", (e) => emitted.push(e));
|
|
109
|
+
|
|
110
|
+
parser.write('{"initialHeight":200,');
|
|
111
|
+
emitted.length = 0; // clear snapshot
|
|
112
|
+
|
|
113
|
+
// Start streaming html — first chunk
|
|
114
|
+
parser.write('"html":"<div');
|
|
115
|
+
const htmlDeltas1 = emitted.filter(
|
|
116
|
+
(e) => e.type === EventType.ACTIVITY_DELTA,
|
|
117
|
+
) as ActivityDeltaEvent[];
|
|
118
|
+
// Should have array creation + first chunk
|
|
119
|
+
expect(htmlDeltas1.length).toBeGreaterThanOrEqual(1);
|
|
120
|
+
expect(htmlDeltas1[0].patch).toEqual([
|
|
121
|
+
{ op: "add", path: "/html", value: [] },
|
|
122
|
+
]);
|
|
123
|
+
|
|
124
|
+
emitted.length = 0;
|
|
125
|
+
// More html content — note: clarinet needs a delimiter after the
|
|
126
|
+
// closing quote to emit onvalue, so include the trailing }
|
|
127
|
+
parser.write('>hello</div>"}');
|
|
128
|
+
// Should have more chunk(s) + htmlComplete
|
|
129
|
+
const completeDelta = emitted.find(
|
|
130
|
+
(e) =>
|
|
131
|
+
e.type === EventType.ACTIVITY_DELTA &&
|
|
132
|
+
(e as ActivityDeltaEvent).patch.some(
|
|
133
|
+
(p) => p.path === "/htmlComplete",
|
|
134
|
+
),
|
|
135
|
+
);
|
|
136
|
+
expect(completeDelta).toBeDefined();
|
|
137
|
+
|
|
138
|
+
// Final params should have the complete html
|
|
139
|
+
expect(parser.params.html).toBe("<div>hello</div>");
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("parses JSON streamed in small chunks", () => {
|
|
143
|
+
const parser = new ArgsParser("tc-1", noop);
|
|
144
|
+
const json = '{"initialHeight":300,"html":"<p>hello</p>"}';
|
|
145
|
+
|
|
146
|
+
for (const ch of json) {
|
|
147
|
+
parser.write(ch);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
expect(parser.params.initialHeight).toBe(300);
|
|
151
|
+
expect(parser.params.html).toBe("<p>hello</p>");
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it("parses jsExpressions array streamed incrementally", () => {
|
|
155
|
+
const parser = new ArgsParser("tc-1", noop);
|
|
156
|
+
|
|
157
|
+
parser.write('{"jsExpressions":');
|
|
158
|
+
expect(parser.params.jsExpressions).toBeUndefined();
|
|
159
|
+
|
|
160
|
+
parser.write('["alert(1)",');
|
|
161
|
+
expect(parser.params.jsExpressions).toEqual(["alert(1)"]);
|
|
162
|
+
|
|
163
|
+
parser.write('"console.log(2)",');
|
|
164
|
+
expect(parser.params.jsExpressions).toEqual([
|
|
165
|
+
"alert(1)",
|
|
166
|
+
"console.log(2)",
|
|
167
|
+
]);
|
|
168
|
+
|
|
169
|
+
parser.write('"document.title"]}');
|
|
170
|
+
expect(parser.params.jsExpressions).toEqual([
|
|
171
|
+
"alert(1)",
|
|
172
|
+
"console.log(2)",
|
|
173
|
+
"document.title",
|
|
174
|
+
]);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("handles partial chunks that split across keys and values", () => {
|
|
178
|
+
const parser = new ArgsParser("tc-1", noop);
|
|
179
|
+
|
|
180
|
+
parser.write('{"ini');
|
|
181
|
+
parser.write('tialHeight":');
|
|
182
|
+
parser.write("25");
|
|
183
|
+
parser.write('0,"ht');
|
|
184
|
+
parser.write('ml":"<div');
|
|
185
|
+
parser.write('>test</div>"}');
|
|
186
|
+
|
|
187
|
+
expect(parser.params.initialHeight).toBe(250);
|
|
188
|
+
expect(parser.params.html).toBe("<div>test</div>");
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it("ignores unknown keys", () => {
|
|
192
|
+
const parser = new ArgsParser("tc-1", noop);
|
|
193
|
+
parser.write(
|
|
194
|
+
'{"initialHeight":100,"unknown_field":"ignored","html":"ok"}',
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
expect(parser.params.initialHeight).toBe(100);
|
|
198
|
+
expect(parser.params.html).toBe("ok");
|
|
199
|
+
expect(parser.params).not.toHaveProperty("unknown_field");
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
describe("Activity event emission", () => {
|
|
204
|
+
it("emits ACTIVITY_SNAPSHOT when initialHeight finishes", () => {
|
|
205
|
+
const emitted: BaseEvent[] = [];
|
|
206
|
+
const parser = new ArgsParser("tc-1", (e) => emitted.push(e));
|
|
207
|
+
|
|
208
|
+
parser.write('{"initialHeight":400}');
|
|
209
|
+
|
|
210
|
+
expect(emitted).toHaveLength(1);
|
|
211
|
+
const snapshot = emitted[0] as ActivitySnapshotEvent;
|
|
212
|
+
expect(snapshot.type).toBe(EventType.ACTIVITY_SNAPSHOT);
|
|
213
|
+
expect(snapshot.messageId).toBe("tc-1-activity");
|
|
214
|
+
expect(snapshot.activityType).toBe("open-generative-ui");
|
|
215
|
+
expect(snapshot.content).toEqual({
|
|
216
|
+
initialHeight: 400,
|
|
217
|
+
generating: true,
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it("emits ACTIVITY_DELTA array for html and single delta for jsFunctions", () => {
|
|
222
|
+
const emitted: BaseEvent[] = [];
|
|
223
|
+
const parser = new ArgsParser("tc-1", (e) => emitted.push(e));
|
|
224
|
+
|
|
225
|
+
parser.write('{"initialHeight":200,');
|
|
226
|
+
emitted.length = 0; // clear snapshot
|
|
227
|
+
|
|
228
|
+
parser.write('"html":"<div/>",');
|
|
229
|
+
// Should have: array creation, chunk(s), htmlComplete
|
|
230
|
+
const htmlDeltas = emitted.filter(
|
|
231
|
+
(e) => e.type === EventType.ACTIVITY_DELTA,
|
|
232
|
+
) as ActivityDeltaEvent[];
|
|
233
|
+
expect(htmlDeltas[0].patch).toEqual([
|
|
234
|
+
{ op: "add", path: "/html", value: [] },
|
|
235
|
+
]);
|
|
236
|
+
// Last html delta should be htmlComplete
|
|
237
|
+
const completeIdx = htmlDeltas.findIndex((d) =>
|
|
238
|
+
d.patch.some((p) => p.path === "/htmlComplete"),
|
|
239
|
+
);
|
|
240
|
+
expect(completeIdx).toBeGreaterThan(0);
|
|
241
|
+
|
|
242
|
+
emitted.length = 0;
|
|
243
|
+
parser.write('"jsFunctions":"fn(){}"}');
|
|
244
|
+
const fnDeltas = emitted.filter(
|
|
245
|
+
(e) => e.type === EventType.ACTIVITY_DELTA,
|
|
246
|
+
) as ActivityDeltaEvent[];
|
|
247
|
+
expect(fnDeltas).toHaveLength(2);
|
|
248
|
+
expect(fnDeltas[0].patch).toEqual([
|
|
249
|
+
{ op: "add", path: "/jsFunctions", value: "fn(){}" },
|
|
250
|
+
]);
|
|
251
|
+
expect(fnDeltas[1].patch).toEqual([
|
|
252
|
+
{ op: "add", path: "/jsFunctionsComplete", value: true },
|
|
253
|
+
]);
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
it("emits ACTIVITY_DELTA with add op for each jsExpressions item", () => {
|
|
257
|
+
const emitted: BaseEvent[] = [];
|
|
258
|
+
const parser = new ArgsParser("tc-1", (e) => emitted.push(e));
|
|
259
|
+
|
|
260
|
+
parser.write('{"initialHeight":100,');
|
|
261
|
+
emitted.length = 0; // clear snapshot
|
|
262
|
+
|
|
263
|
+
parser.write('"jsExpressions":["expr1",');
|
|
264
|
+
// First: array-creation delta, then the first item append
|
|
265
|
+
expect(emitted).toHaveLength(2);
|
|
266
|
+
const arrayCreate = emitted[0] as ActivityDeltaEvent;
|
|
267
|
+
expect(arrayCreate.type).toBe(EventType.ACTIVITY_DELTA);
|
|
268
|
+
expect(arrayCreate.patch).toEqual([
|
|
269
|
+
{ op: "add", path: "/jsExpressions", value: [] },
|
|
270
|
+
]);
|
|
271
|
+
const delta1 = emitted[1] as ActivityDeltaEvent;
|
|
272
|
+
expect(delta1.type).toBe(EventType.ACTIVITY_DELTA);
|
|
273
|
+
expect(delta1.patch).toEqual([
|
|
274
|
+
{ op: "add", path: "/jsExpressions/-", value: "expr1" },
|
|
275
|
+
]);
|
|
276
|
+
|
|
277
|
+
emitted.length = 0;
|
|
278
|
+
parser.write('"expr2",');
|
|
279
|
+
expect(emitted).toHaveLength(1);
|
|
280
|
+
const delta2 = emitted[0] as ActivityDeltaEvent;
|
|
281
|
+
expect(delta2.patch).toEqual([
|
|
282
|
+
{ op: "add", path: "/jsExpressions/-", value: "expr2" },
|
|
283
|
+
]);
|
|
284
|
+
|
|
285
|
+
emitted.length = 0;
|
|
286
|
+
parser.write('"expr3"]}');
|
|
287
|
+
expect(emitted).toHaveLength(2);
|
|
288
|
+
const delta3 = emitted[0] as ActivityDeltaEvent;
|
|
289
|
+
expect(delta3.patch).toEqual([
|
|
290
|
+
{ op: "add", path: "/jsExpressions/-", value: "expr3" },
|
|
291
|
+
]);
|
|
292
|
+
expect((emitted[1] as ActivityDeltaEvent).patch).toEqual([
|
|
293
|
+
{ op: "add", path: "/jsExpressionsComplete", value: true },
|
|
294
|
+
]);
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
it("emits html chunks immediately without throttling", () => {
|
|
298
|
+
const emitted: BaseEvent[] = [];
|
|
299
|
+
const parser = new ArgsParser("tc-1", (e) => emitted.push(e));
|
|
300
|
+
|
|
301
|
+
parser.write('{"initialHeight":200,');
|
|
302
|
+
emitted.length = 0;
|
|
303
|
+
|
|
304
|
+
// Start html streaming — first write should emit
|
|
305
|
+
parser.write('"html":"chunk1');
|
|
306
|
+
const firstDeltas = emitted.filter(
|
|
307
|
+
(e) => e.type === EventType.ACTIVITY_DELTA,
|
|
308
|
+
) as ActivityDeltaEvent[];
|
|
309
|
+
// Should have array creation + first chunk
|
|
310
|
+
expect(firstDeltas.length).toBeGreaterThanOrEqual(1);
|
|
311
|
+
|
|
312
|
+
// Immediate second write should also emit (no throttle)
|
|
313
|
+
emitted.length = 0;
|
|
314
|
+
parser.write("chunk2");
|
|
315
|
+
const secondDeltas = emitted.filter(
|
|
316
|
+
(e) => e.type === EventType.ACTIVITY_DELTA,
|
|
317
|
+
) as ActivityDeltaEvent[];
|
|
318
|
+
expect(secondDeltas).toHaveLength(1);
|
|
319
|
+
expect(secondDeltas[0].patch[0].value).toContain("chunk2");
|
|
320
|
+
|
|
321
|
+
// Completing the html string should flush remaining + htmlComplete
|
|
322
|
+
emitted.length = 0;
|
|
323
|
+
parser.write('",');
|
|
324
|
+
const completeDeltas = emitted.filter(
|
|
325
|
+
(e) => e.type === EventType.ACTIVITY_DELTA,
|
|
326
|
+
) as ActivityDeltaEvent[];
|
|
327
|
+
const completeDelta = completeDeltas.find((d) =>
|
|
328
|
+
d.patch.some((p) => p.path === "/htmlComplete"),
|
|
329
|
+
);
|
|
330
|
+
expect(completeDelta).toBeDefined();
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
it("emits snapshot only once even with multiple params", () => {
|
|
334
|
+
const emitted: BaseEvent[] = [];
|
|
335
|
+
const parser = new ArgsParser("tc-1", (e) => emitted.push(e));
|
|
336
|
+
|
|
337
|
+
parser.write('{"initialHeight":100,"html":"a","jsFunctions":"b"}');
|
|
338
|
+
|
|
339
|
+
const snapshots = emitted.filter(
|
|
340
|
+
(e) => e.type === EventType.ACTIVITY_SNAPSHOT,
|
|
341
|
+
);
|
|
342
|
+
expect(snapshots).toHaveLength(1);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it("produces patches that build complete content when applied sequentially", () => {
|
|
346
|
+
const emitted: BaseEvent[] = [];
|
|
347
|
+
const parser = new ArgsParser("tc-1", (e) => emitted.push(e));
|
|
348
|
+
|
|
349
|
+
// Simulate a full tool call with all parameter types
|
|
350
|
+
parser.write(
|
|
351
|
+
'{"initialHeight":400,"html":"<body>game</body>","jsFunctions":"function init(){}","jsExpressions":["init()","update()"]}',
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
// Reconstruct content by applying snapshot + deltas in order
|
|
355
|
+
let content: Record<string, unknown> = {};
|
|
356
|
+
for (const event of emitted) {
|
|
357
|
+
if (event.type === EventType.ACTIVITY_SNAPSHOT) {
|
|
358
|
+
content = { ...(event as ActivitySnapshotEvent).content } as Record<
|
|
359
|
+
string,
|
|
360
|
+
unknown
|
|
361
|
+
>;
|
|
362
|
+
} else if (event.type === EventType.ACTIVITY_DELTA) {
|
|
363
|
+
const delta = event as ActivityDeltaEvent;
|
|
364
|
+
for (const op of delta.patch) {
|
|
365
|
+
if (op.op === "add") {
|
|
366
|
+
if (op.path.endsWith("/-")) {
|
|
367
|
+
// Array append: path like "/jsExpressions/-" or "/html/-"
|
|
368
|
+
const arrayKey = op.path.slice(1, -2);
|
|
369
|
+
(content[arrayKey] as unknown[]).push(op.value);
|
|
370
|
+
} else {
|
|
371
|
+
// Direct property: path like "/htmlComplete"
|
|
372
|
+
content[op.path.slice(1)] = op.value;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// html is now an array of chunks; join to verify full content
|
|
380
|
+
expect(Array.isArray(content.html)).toBe(true);
|
|
381
|
+
expect((content.html as string[]).join("")).toBe("<body>game</body>");
|
|
382
|
+
expect(content.htmlComplete).toBe(true);
|
|
383
|
+
expect(content.jsFunctions).toBe("function init(){}");
|
|
384
|
+
expect(content.jsExpressions).toEqual(["init()", "update()"]);
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
it("produces patches that build content correctly when streamed in chunks", () => {
|
|
388
|
+
const emitted: BaseEvent[] = [];
|
|
389
|
+
const parser = new ArgsParser("tc-1", (e) => emitted.push(e));
|
|
390
|
+
|
|
391
|
+
// Stream in small chunks like a real LLM would
|
|
392
|
+
parser.write('{"initialHeight":300,');
|
|
393
|
+
parser.write('"html":"<div>hi</div>",');
|
|
394
|
+
parser.write('"jsFunctions":"function go(){}",');
|
|
395
|
+
parser.write('"jsExpressions":["go()",');
|
|
396
|
+
parser.write('"render()","done()"]}');
|
|
397
|
+
|
|
398
|
+
// Reconstruct content
|
|
399
|
+
let content: Record<string, unknown> = {};
|
|
400
|
+
for (const event of emitted) {
|
|
401
|
+
if (event.type === EventType.ACTIVITY_SNAPSHOT) {
|
|
402
|
+
content = { ...(event as ActivitySnapshotEvent).content } as Record<
|
|
403
|
+
string,
|
|
404
|
+
unknown
|
|
405
|
+
>;
|
|
406
|
+
} else if (event.type === EventType.ACTIVITY_DELTA) {
|
|
407
|
+
const delta = event as ActivityDeltaEvent;
|
|
408
|
+
for (const op of delta.patch) {
|
|
409
|
+
if (op.op === "add") {
|
|
410
|
+
if (op.path.endsWith("/-")) {
|
|
411
|
+
const arrayKey = op.path.slice(1, -2);
|
|
412
|
+
(content[arrayKey] as unknown[]).push(op.value);
|
|
413
|
+
} else {
|
|
414
|
+
content[op.path.slice(1)] = op.value;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// html is now an array of chunks
|
|
422
|
+
expect(Array.isArray(content.html)).toBe(true);
|
|
423
|
+
expect((content.html as string[]).join("")).toBe("<div>hi</div>");
|
|
424
|
+
expect(content.htmlComplete).toBe(true);
|
|
425
|
+
expect(content.jsFunctions).toBe("function go(){}");
|
|
426
|
+
expect(content.jsExpressions).toEqual(["go()", "render()", "done()"]);
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
it("emits array-creation delta before first jsExpressions item", () => {
|
|
430
|
+
const emitted: BaseEvent[] = [];
|
|
431
|
+
const parser = new ArgsParser("tc-1", (e) => emitted.push(e));
|
|
432
|
+
|
|
433
|
+
parser.write('{"initialHeight":100,');
|
|
434
|
+
emitted.length = 0; // clear snapshot
|
|
435
|
+
|
|
436
|
+
// Trailing comma needed — clarinet fires onvalue after a delimiter
|
|
437
|
+
parser.write('"jsExpressions":["first",');
|
|
438
|
+
|
|
439
|
+
// Should get array creation delta followed by item delta
|
|
440
|
+
expect(emitted).toHaveLength(2);
|
|
441
|
+
expect((emitted[0] as ActivityDeltaEvent).patch).toEqual([
|
|
442
|
+
{ op: "add", path: "/jsExpressions", value: [] },
|
|
443
|
+
]);
|
|
444
|
+
expect((emitted[1] as ActivityDeltaEvent).patch).toEqual([
|
|
445
|
+
{ op: "add", path: "/jsExpressions/-", value: "first" },
|
|
446
|
+
]);
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
it("holds genui tool call events and flushes after first activity event", async () => {
|
|
450
|
+
const middleware = new OpenGenerativeUIMiddleware();
|
|
451
|
+
const toolCallId = "tc-stream";
|
|
452
|
+
const parentMessageId = "msg-1";
|
|
453
|
+
|
|
454
|
+
const agent = new MockAgent([
|
|
455
|
+
{
|
|
456
|
+
type: EventType.RUN_STARTED,
|
|
457
|
+
threadId: "thread-1",
|
|
458
|
+
runId: "run-1",
|
|
459
|
+
} as BaseEvent,
|
|
460
|
+
{
|
|
461
|
+
type: EventType.TEXT_MESSAGE_START,
|
|
462
|
+
messageId: parentMessageId,
|
|
463
|
+
role: "assistant",
|
|
464
|
+
} as BaseEvent,
|
|
465
|
+
{
|
|
466
|
+
type: EventType.TEXT_MESSAGE_END,
|
|
467
|
+
messageId: parentMessageId,
|
|
468
|
+
} as BaseEvent,
|
|
469
|
+
{
|
|
470
|
+
type: EventType.TOOL_CALL_START,
|
|
471
|
+
toolCallId,
|
|
472
|
+
toolCallName: "generateSandboxedUi",
|
|
473
|
+
parentMessageId,
|
|
474
|
+
} as BaseEvent,
|
|
475
|
+
{
|
|
476
|
+
type: EventType.TOOL_CALL_ARGS,
|
|
477
|
+
toolCallId,
|
|
478
|
+
delta: '{"initialHeight":300,',
|
|
479
|
+
} as BaseEvent,
|
|
480
|
+
{
|
|
481
|
+
type: EventType.TOOL_CALL_ARGS,
|
|
482
|
+
toolCallId,
|
|
483
|
+
delta: '"html":"<p>hi</p>"}',
|
|
484
|
+
} as BaseEvent,
|
|
485
|
+
{
|
|
486
|
+
type: EventType.TOOL_CALL_END,
|
|
487
|
+
toolCallId,
|
|
488
|
+
} as BaseEvent,
|
|
489
|
+
{
|
|
490
|
+
type: EventType.RUN_FINISHED,
|
|
491
|
+
threadId: "thread-1",
|
|
492
|
+
runId: "run-1",
|
|
493
|
+
} as BaseEvent,
|
|
494
|
+
]);
|
|
495
|
+
|
|
496
|
+
const events = await collectEvents(
|
|
497
|
+
middleware.run(createRunInput(), agent),
|
|
498
|
+
);
|
|
499
|
+
|
|
500
|
+
// ACTIVITY_SNAPSHOT should appear before any tool call events
|
|
501
|
+
const snapshotIdx = events.findIndex(
|
|
502
|
+
(e) => e.type === EventType.ACTIVITY_SNAPSHOT,
|
|
503
|
+
);
|
|
504
|
+
const toolCallStartIdx = events.findIndex(
|
|
505
|
+
(e) => e.type === EventType.TOOL_CALL_START,
|
|
506
|
+
);
|
|
507
|
+
expect(snapshotIdx).toBeGreaterThan(-1);
|
|
508
|
+
expect(toolCallStartIdx).toBeGreaterThan(-1);
|
|
509
|
+
expect(snapshotIdx).toBeLessThan(toolCallStartIdx);
|
|
510
|
+
|
|
511
|
+
// Activity content is correct
|
|
512
|
+
const snapshots = events.filter(
|
|
513
|
+
(e) => e.type === EventType.ACTIVITY_SNAPSHOT,
|
|
514
|
+
) as ActivitySnapshotEvent[];
|
|
515
|
+
expect(snapshots).toHaveLength(1);
|
|
516
|
+
expect(snapshots[0].content).toEqual({
|
|
517
|
+
initialHeight: 300,
|
|
518
|
+
generating: true,
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
const deltas = events.filter(
|
|
522
|
+
(e) => e.type === EventType.ACTIVITY_DELTA,
|
|
523
|
+
) as ActivityDeltaEvent[];
|
|
524
|
+
// html deltas: array creation, chunk(s), htmlComplete, then generating: false
|
|
525
|
+
expect(deltas.length).toBeGreaterThanOrEqual(3);
|
|
526
|
+
expect(deltas[0].patch).toEqual([
|
|
527
|
+
{ op: "add", path: "/html", value: [] },
|
|
528
|
+
]);
|
|
529
|
+
// Last delta should be generating: false
|
|
530
|
+
expect(deltas[deltas.length - 1].patch).toEqual([
|
|
531
|
+
{ op: "add", path: "/generating", value: false },
|
|
532
|
+
]);
|
|
533
|
+
// htmlComplete should be emitted
|
|
534
|
+
const htmlCompleteDelta = deltas.find((d) =>
|
|
535
|
+
d.patch.some((p) => p.path === "/htmlComplete" && p.value === true),
|
|
536
|
+
);
|
|
537
|
+
expect(htmlCompleteDelta).toBeDefined();
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
it("passes through tool call events for non-genui tools", async () => {
|
|
541
|
+
const middleware = new OpenGenerativeUIMiddleware();
|
|
542
|
+
const toolCallId = "tc-other";
|
|
543
|
+
const parentMessageId = "msg-1";
|
|
544
|
+
|
|
545
|
+
const agent = new MockAgent([
|
|
546
|
+
{
|
|
547
|
+
type: EventType.RUN_STARTED,
|
|
548
|
+
threadId: "thread-1",
|
|
549
|
+
runId: "run-1",
|
|
550
|
+
} as BaseEvent,
|
|
551
|
+
{
|
|
552
|
+
type: EventType.TEXT_MESSAGE_START,
|
|
553
|
+
messageId: parentMessageId,
|
|
554
|
+
role: "assistant",
|
|
555
|
+
} as BaseEvent,
|
|
556
|
+
{
|
|
557
|
+
type: EventType.TEXT_MESSAGE_END,
|
|
558
|
+
messageId: parentMessageId,
|
|
559
|
+
} as BaseEvent,
|
|
560
|
+
{
|
|
561
|
+
type: EventType.TOOL_CALL_START,
|
|
562
|
+
toolCallId,
|
|
563
|
+
toolCallName: "some_other_tool",
|
|
564
|
+
parentMessageId,
|
|
565
|
+
} as BaseEvent,
|
|
566
|
+
{
|
|
567
|
+
type: EventType.TOOL_CALL_ARGS,
|
|
568
|
+
toolCallId,
|
|
569
|
+
delta: "{}",
|
|
570
|
+
} as BaseEvent,
|
|
571
|
+
{
|
|
572
|
+
type: EventType.TOOL_CALL_END,
|
|
573
|
+
toolCallId,
|
|
574
|
+
} as BaseEvent,
|
|
575
|
+
{
|
|
576
|
+
type: EventType.RUN_FINISHED,
|
|
577
|
+
threadId: "thread-1",
|
|
578
|
+
runId: "run-1",
|
|
579
|
+
} as BaseEvent,
|
|
580
|
+
]);
|
|
581
|
+
|
|
582
|
+
const events = await collectEvents(
|
|
583
|
+
middleware.run(createRunInput(), agent),
|
|
584
|
+
);
|
|
585
|
+
|
|
586
|
+
const types = events.map((e) => e.type);
|
|
587
|
+
expect(types).toEqual([
|
|
588
|
+
EventType.RUN_STARTED,
|
|
589
|
+
EventType.TEXT_MESSAGE_START,
|
|
590
|
+
EventType.TEXT_MESSAGE_END,
|
|
591
|
+
EventType.TOOL_CALL_START,
|
|
592
|
+
EventType.TOOL_CALL_ARGS,
|
|
593
|
+
EventType.TOOL_CALL_END,
|
|
594
|
+
EventType.RUN_FINISHED,
|
|
595
|
+
]);
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
it("emits full activity events for jsFunctions and jsExpressions through middleware", async () => {
|
|
599
|
+
const middleware = new OpenGenerativeUIMiddleware();
|
|
600
|
+
const toolCallId = "tc-js";
|
|
601
|
+
const parentMessageId = "msg-1";
|
|
602
|
+
|
|
603
|
+
const agent = new MockAgent([
|
|
604
|
+
{
|
|
605
|
+
type: EventType.RUN_STARTED,
|
|
606
|
+
threadId: "thread-1",
|
|
607
|
+
runId: "run-1",
|
|
608
|
+
} as BaseEvent,
|
|
609
|
+
{
|
|
610
|
+
type: EventType.TEXT_MESSAGE_START,
|
|
611
|
+
messageId: parentMessageId,
|
|
612
|
+
role: "assistant",
|
|
613
|
+
} as BaseEvent,
|
|
614
|
+
{
|
|
615
|
+
type: EventType.TEXT_MESSAGE_END,
|
|
616
|
+
messageId: parentMessageId,
|
|
617
|
+
} as BaseEvent,
|
|
618
|
+
{
|
|
619
|
+
type: EventType.TOOL_CALL_START,
|
|
620
|
+
toolCallId,
|
|
621
|
+
toolCallName: "generateSandboxedUi",
|
|
622
|
+
parentMessageId,
|
|
623
|
+
} as BaseEvent,
|
|
624
|
+
{
|
|
625
|
+
type: EventType.TOOL_CALL_ARGS,
|
|
626
|
+
toolCallId,
|
|
627
|
+
delta: '{"initialHeight":400,',
|
|
628
|
+
} as BaseEvent,
|
|
629
|
+
{
|
|
630
|
+
type: EventType.TOOL_CALL_ARGS,
|
|
631
|
+
toolCallId,
|
|
632
|
+
delta: '"html":"<body>game</body>",',
|
|
633
|
+
} as BaseEvent,
|
|
634
|
+
{
|
|
635
|
+
type: EventType.TOOL_CALL_ARGS,
|
|
636
|
+
toolCallId,
|
|
637
|
+
delta: '"jsFunctions":"function init(){}",',
|
|
638
|
+
} as BaseEvent,
|
|
639
|
+
{
|
|
640
|
+
type: EventType.TOOL_CALL_ARGS,
|
|
641
|
+
toolCallId,
|
|
642
|
+
delta: '"jsExpressions":["init()",',
|
|
643
|
+
} as BaseEvent,
|
|
644
|
+
{
|
|
645
|
+
type: EventType.TOOL_CALL_ARGS,
|
|
646
|
+
toolCallId,
|
|
647
|
+
delta: '"render()"]}',
|
|
648
|
+
} as BaseEvent,
|
|
649
|
+
{
|
|
650
|
+
type: EventType.TOOL_CALL_END,
|
|
651
|
+
toolCallId,
|
|
652
|
+
} as BaseEvent,
|
|
653
|
+
{
|
|
654
|
+
type: EventType.RUN_FINISHED,
|
|
655
|
+
threadId: "thread-1",
|
|
656
|
+
runId: "run-1",
|
|
657
|
+
} as BaseEvent,
|
|
658
|
+
]);
|
|
659
|
+
|
|
660
|
+
const events = await collectEvents(
|
|
661
|
+
middleware.run(createRunInput(), agent),
|
|
662
|
+
);
|
|
663
|
+
|
|
664
|
+
// Verify snapshot
|
|
665
|
+
const snapshots = events.filter(
|
|
666
|
+
(e) => e.type === EventType.ACTIVITY_SNAPSHOT,
|
|
667
|
+
) as ActivitySnapshotEvent[];
|
|
668
|
+
expect(snapshots).toHaveLength(1);
|
|
669
|
+
expect(snapshots[0].content).toEqual({
|
|
670
|
+
initialHeight: 400,
|
|
671
|
+
generating: true,
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
// Verify deltas
|
|
675
|
+
const deltas = events.filter(
|
|
676
|
+
(e) => e.type === EventType.ACTIVITY_DELTA,
|
|
677
|
+
) as ActivityDeltaEvent[];
|
|
678
|
+
|
|
679
|
+
// html is now streamed as array: creation, chunk(s), htmlComplete
|
|
680
|
+
// Then: jsFunctions, jsExpressions array creation, items, generating: false
|
|
681
|
+
// Verify key structural deltas exist
|
|
682
|
+
expect(deltas[0].patch).toEqual([
|
|
683
|
+
{ op: "add", path: "/html", value: [] },
|
|
684
|
+
]);
|
|
685
|
+
const htmlCompleteDelta = deltas.find((d) =>
|
|
686
|
+
d.patch.some((p) => p.path === "/htmlComplete" && p.value === true),
|
|
687
|
+
);
|
|
688
|
+
expect(htmlCompleteDelta).toBeDefined();
|
|
689
|
+
const jsFuncDelta = deltas.find((d) =>
|
|
690
|
+
d.patch.some((p) => p.path === "/jsFunctions"),
|
|
691
|
+
);
|
|
692
|
+
expect(jsFuncDelta).toBeDefined();
|
|
693
|
+
expect(deltas[deltas.length - 1].patch).toEqual([
|
|
694
|
+
{ op: "add", path: "/generating", value: false },
|
|
695
|
+
]);
|
|
696
|
+
|
|
697
|
+
// Reconstruct content to prove patches work end-to-end
|
|
698
|
+
let content: Record<string, unknown> = {};
|
|
699
|
+
for (const event of events) {
|
|
700
|
+
if (event.type === EventType.ACTIVITY_SNAPSHOT) {
|
|
701
|
+
content = { ...(event as ActivitySnapshotEvent).content } as Record<
|
|
702
|
+
string,
|
|
703
|
+
unknown
|
|
704
|
+
>;
|
|
705
|
+
} else if (event.type === EventType.ACTIVITY_DELTA) {
|
|
706
|
+
for (const op of (event as ActivityDeltaEvent).patch) {
|
|
707
|
+
if (op.op === "add") {
|
|
708
|
+
if (op.path.endsWith("/-")) {
|
|
709
|
+
const arrayKey = op.path.slice(1, -2);
|
|
710
|
+
(content[arrayKey] as unknown[]).push(op.value);
|
|
711
|
+
} else {
|
|
712
|
+
content[op.path.slice(1)] = op.value;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// html is now an array of chunks
|
|
720
|
+
expect(Array.isArray(content.html)).toBe(true);
|
|
721
|
+
expect((content.html as string[]).join("")).toBe("<body>game</body>");
|
|
722
|
+
expect(content.htmlComplete).toBe(true);
|
|
723
|
+
expect(content.generating).toBe(false);
|
|
724
|
+
expect(content.jsFunctions).toBe("function init(){}");
|
|
725
|
+
expect(content.jsExpressions).toEqual(["init()", "render()"]);
|
|
726
|
+
});
|
|
727
|
+
});
|
|
728
|
+
});
|