@copilotkit/runtime 1.57.3 → 1.58.0-canary.thread-id-propagation
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/dist/lib/observability.d.cts +1 -1
- package/dist/lib/observability.d.cts.map +1 -1
- package/dist/lib/observability.d.mts +1 -1
- package/dist/lib/observability.d.mts.map +1 -1
- package/dist/lib/runtime/copilot-runtime.cjs +2 -0
- package/dist/lib/runtime/copilot-runtime.cjs.map +1 -1
- package/dist/lib/runtime/copilot-runtime.d.cts.map +1 -1
- package/dist/lib/runtime/copilot-runtime.d.mts.map +1 -1
- package/dist/lib/runtime/copilot-runtime.mjs +2 -0
- package/dist/lib/runtime/copilot-runtime.mjs.map +1 -1
- package/dist/package.cjs +5 -8
- package/dist/package.mjs +5 -8
- package/dist/v2/runtime/core/runtime.cjs +4 -1
- package/dist/v2/runtime/core/runtime.cjs.map +1 -1
- package/dist/v2/runtime/core/runtime.d.cts.map +1 -1
- package/dist/v2/runtime/core/runtime.d.mts.map +1 -1
- package/dist/v2/runtime/core/runtime.mjs +4 -1
- package/dist/v2/runtime/core/runtime.mjs.map +1 -1
- package/dist/v2/runtime/handlers/get-runtime-info.cjs +1 -1
- package/dist/v2/runtime/handlers/get-runtime-info.mjs +1 -1
- package/dist/v2/runtime/handlers/handle-connect.cjs +1 -1
- package/dist/v2/runtime/handlers/handle-connect.mjs +1 -1
- package/dist/v2/runtime/handlers/handle-run.cjs +1 -1
- package/dist/v2/runtime/handlers/handle-run.mjs +1 -1
- package/dist/v2/runtime/handlers/shared/agent-utils.cjs +1 -1
- package/dist/v2/runtime/handlers/shared/agent-utils.cjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/agent-utils.mjs +1 -1
- package/dist/v2/runtime/handlers/shared/agent-utils.mjs.map +1 -1
- package/dist/v2/runtime/telemetry/telemetry-client.cjs +22 -6
- package/dist/v2/runtime/telemetry/telemetry-client.cjs.map +1 -1
- package/dist/v2/runtime/telemetry/telemetry-client.mjs +27 -11
- package/dist/v2/runtime/telemetry/telemetry-client.mjs.map +1 -1
- package/package.json +9 -19
- package/skills/runtime/SKILL.md +98 -0
- package/skills/runtime/references/agent-runners-custom.md +161 -0
- package/skills/runtime/references/agent-runners-in-memory.md +64 -0
- package/skills/runtime/references/agent-runners-sqlite.md +90 -0
- package/skills/runtime/references/agent-runners.md +304 -0
- package/skills/runtime/references/built-in-agent-factory-modes.md +232 -0
- package/skills/runtime/references/built-in-agent-helper-utilities.md +123 -0
- package/skills/runtime/references/built-in-agent-model-identifiers.md +59 -0
- package/skills/runtime/references/built-in-agent.md +523 -0
- package/skills/runtime/references/intelligence-mode.md +336 -0
- package/skills/runtime/references/middleware.md +376 -0
- package/skills/runtime/references/server-side-tools.md +414 -0
- package/skills/runtime/references/setup-endpoint.md +503 -0
- package/skills/runtime/references/transcription.md +287 -0
- package/skills/runtime/references/wiring-a2a.md +40 -0
- package/skills/runtime/references/wiring-adk.md +45 -0
- package/skills/runtime/references/wiring-ag2.md +41 -0
- package/skills/runtime/references/wiring-agno.md +39 -0
- package/skills/runtime/references/wiring-aws-strands.md +59 -0
- package/skills/runtime/references/wiring-crewai-crews.md +51 -0
- package/skills/runtime/references/wiring-crewai-flows.md +45 -0
- package/skills/runtime/references/wiring-external-agents.md +348 -0
- package/skills/runtime/references/wiring-langgraph.md +50 -0
- package/skills/runtime/references/wiring-llamaindex.md +39 -0
- package/skills/runtime/references/wiring-mastra.md +70 -0
- package/skills/runtime/references/wiring-mcp-apps-middleware.md +68 -0
- package/skills/runtime/references/wiring-ms-agent-framework.md +41 -0
- package/skills/runtime/references/wiring-pydantic-ai.md +45 -0
- package/CHANGELOG.md +0 -3624
- package/__snapshots__/schema/schema.graphql +0 -371
- package/dist/v2/runtime/telemetry/scarf-client.cjs +0 -32
- package/dist/v2/runtime/telemetry/scarf-client.cjs.map +0 -1
- package/dist/v2/runtime/telemetry/scarf-client.mjs +0 -32
- package/dist/v2/runtime/telemetry/scarf-client.mjs.map +0 -1
- package/scripts/generate-gql-schema.ts +0 -16
- package/src/agent/__tests__/agent-test-helpers.ts +0 -476
- package/src/agent/__tests__/agent.test.ts +0 -593
- package/src/agent/__tests__/ai-sdk-v6-compat.test.ts +0 -116
- package/src/agent/__tests__/basic-agent.test.ts +0 -1698
- package/src/agent/__tests__/capabilities.test.ts +0 -81
- package/src/agent/__tests__/config-tools-execution.test.ts +0 -516
- package/src/agent/__tests__/converter-aisdk.test.ts +0 -692
- package/src/agent/__tests__/converter-custom.test.ts +0 -319
- package/src/agent/__tests__/converter-tanstack-input.test.ts +0 -211
- package/src/agent/__tests__/converter-tanstack.test.ts +0 -594
- package/src/agent/__tests__/mcp-clients.test.ts +0 -246
- package/src/agent/__tests__/mcp-servers-integration.test.ts +0 -373
- package/src/agent/__tests__/multimodal-tanstack.test.ts +0 -284
- package/src/agent/__tests__/multimodal.test.ts +0 -176
- package/src/agent/__tests__/property-overrides.test.ts +0 -598
- package/src/agent/__tests__/provider-id-collision.test.ts +0 -195
- package/src/agent/__tests__/standard-schema-tools.test.ts +0 -313
- package/src/agent/__tests__/standard-schema-types.test.ts +0 -158
- package/src/agent/__tests__/state-tools.test.ts +0 -436
- package/src/agent/__tests__/test-helpers.ts +0 -197
- package/src/agent/__tests__/utils.test.ts +0 -536
- package/src/agent/__tests__/zod-regression.test.ts +0 -350
- package/src/agent/converters/aisdk.ts +0 -326
- package/src/agent/converters/index.ts +0 -7
- package/src/agent/converters/tanstack.ts +0 -451
- package/src/agent/index.ts +0 -1743
- package/src/agents/langgraph/__tests__/event-source.test.ts +0 -256
- package/src/agents/langgraph/event-source.ts +0 -365
- package/src/agents/langgraph/events.ts +0 -394
- package/src/graphql/inputs/action.input.ts +0 -16
- package/src/graphql/inputs/agent-session.input.ts +0 -13
- package/src/graphql/inputs/agent-state.input.ts +0 -13
- package/src/graphql/inputs/cloud-guardrails.input.ts +0 -16
- package/src/graphql/inputs/cloud.input.ts +0 -8
- package/src/graphql/inputs/context-property.input.ts +0 -10
- package/src/graphql/inputs/copilot-context.input.ts +0 -10
- package/src/graphql/inputs/custom-property.input.ts +0 -15
- package/src/graphql/inputs/extensions.input.ts +0 -21
- package/src/graphql/inputs/forwarded-parameters.input.ts +0 -22
- package/src/graphql/inputs/frontend.input.ts +0 -14
- package/src/graphql/inputs/generate-copilot-response.input.ts +0 -59
- package/src/graphql/inputs/load-agent-state.input.ts +0 -10
- package/src/graphql/inputs/message.input.ts +0 -110
- package/src/graphql/inputs/meta-event.input.ts +0 -18
- package/src/graphql/message-conversion/agui-to-gql.test.ts +0 -1384
- package/src/graphql/message-conversion/agui-to-gql.ts +0 -384
- package/src/graphql/message-conversion/gql-to-agui.test.ts +0 -1653
- package/src/graphql/message-conversion/gql-to-agui.ts +0 -297
- package/src/graphql/message-conversion/index.ts +0 -2
- package/src/graphql/message-conversion/roundtrip-conversion.test.ts +0 -561
- package/src/graphql/resolvers/__tests__/resolve-message-id.test.ts +0 -25
- package/src/graphql/resolvers/copilot.resolver.ts +0 -785
- package/src/graphql/resolvers/resolve-message-id.ts +0 -14
- package/src/graphql/resolvers/state.resolver.ts +0 -30
- package/src/graphql/types/agents-response.type.ts +0 -19
- package/src/graphql/types/base/index.ts +0 -10
- package/src/graphql/types/converted/index.ts +0 -183
- package/src/graphql/types/copilot-response.type.ts +0 -141
- package/src/graphql/types/enums.ts +0 -38
- package/src/graphql/types/extensions-response.type.ts +0 -23
- package/src/graphql/types/guardrails-result.type.ts +0 -20
- package/src/graphql/types/load-agent-state-response.type.ts +0 -17
- package/src/graphql/types/message-status.type.ts +0 -48
- package/src/graphql/types/meta-events.type.ts +0 -78
- package/src/graphql/types/response-status.type.ts +0 -77
- package/src/index.ts +0 -3
- package/src/langgraph.ts +0 -1
- package/src/lib/__tests__/telemetry-disclosure.test.ts +0 -55
- package/src/lib/cloud/index.ts +0 -4
- package/src/lib/error-messages.ts +0 -211
- package/src/lib/index.ts +0 -52
- package/src/lib/integrations/index.ts +0 -6
- package/src/lib/integrations/nest/index.ts +0 -21
- package/src/lib/integrations/nextjs/app-router.ts +0 -47
- package/src/lib/integrations/nextjs/pages-router.ts +0 -45
- package/src/lib/integrations/node-express/index.ts +0 -21
- package/src/lib/integrations/node-http/__tests__/request-duck-type.test.ts +0 -66
- package/src/lib/integrations/node-http/index.ts +0 -187
- package/src/lib/integrations/node-http/request-handler.ts +0 -128
- package/src/lib/integrations/shared.ts +0 -112
- package/src/lib/logger.ts +0 -31
- package/src/lib/observability.ts +0 -167
- package/src/lib/runtime/__tests__/copilot-runtime-error.test.ts +0 -183
- package/src/lib/runtime/__tests__/handle-service-adapter.test.ts +0 -108
- package/src/lib/runtime/__tests__/mcp-tools-utils.test.ts +0 -499
- package/src/lib/runtime/__tests__/on-after-request.test.ts +0 -122
- package/src/lib/runtime/__tests__/retry-utils.test.ts +0 -137
- package/src/lib/runtime/__tests__/v1-agent-factory.test.ts +0 -109
- package/src/lib/runtime/agent-integrations/langgraph/__tests__/dispatch-event-filtering.test.ts +0 -345
- package/src/lib/runtime/agent-integrations/langgraph/__tests__/run-message-filtering.test.ts +0 -156
- package/src/lib/runtime/agent-integrations/langgraph/agent.ts +0 -263
- package/src/lib/runtime/agent-integrations/langgraph/consts.ts +0 -37
- package/src/lib/runtime/agent-integrations/langgraph/index.ts +0 -2
- package/src/lib/runtime/copilot-runtime.ts +0 -863
- package/src/lib/runtime/mcp-tools-utils.ts +0 -313
- package/src/lib/runtime/retry-utils.ts +0 -141
- package/src/lib/runtime/telemetry-agent-runner.ts +0 -151
- package/src/lib/runtime/types.ts +0 -48
- package/src/lib/runtime/utils.ts +0 -93
- package/src/lib/streaming.ts +0 -220
- package/src/lib/telemetry-client.ts +0 -66
- package/src/lib/telemetry-disclosure.ts +0 -53
- package/src/service-adapters/anthropic/anthropic-adapter.ts +0 -532
- package/src/service-adapters/anthropic/utils.ts +0 -219
- package/src/service-adapters/bedrock/bedrock-adapter.ts +0 -73
- package/src/service-adapters/conversion.test.ts +0 -56
- package/src/service-adapters/conversion.ts +0 -69
- package/src/service-adapters/empty/empty-adapter.ts +0 -38
- package/src/service-adapters/events.ts +0 -337
- package/src/service-adapters/experimental/ollama/ollama-adapter.ts +0 -84
- package/src/service-adapters/google/google-genai-adapter.test.ts +0 -151
- package/src/service-adapters/google/google-genai-adapter.ts +0 -95
- package/src/service-adapters/groq/groq-adapter.ts +0 -229
- package/src/service-adapters/index.ts +0 -18
- package/src/service-adapters/langchain/langchain-adapter.ts +0 -113
- package/src/service-adapters/langchain/langserve.ts +0 -88
- package/src/service-adapters/langchain/types.ts +0 -20
- package/src/service-adapters/langchain/utils.ts +0 -330
- package/src/service-adapters/openai/__tests__/openai-v5-compat.test.ts +0 -177
- package/src/service-adapters/openai/openai-adapter.ts +0 -324
- package/src/service-adapters/openai/openai-assistant-adapter.ts +0 -385
- package/src/service-adapters/openai/utils.ts +0 -305
- package/src/service-adapters/service-adapter.ts +0 -50
- package/src/service-adapters/shared/error-utils.ts +0 -64
- package/src/service-adapters/shared/index.ts +0 -2
- package/src/service-adapters/shared/sdk-client-utils.ts +0 -19
- package/src/service-adapters/unify/unify-adapter.ts +0 -165
- package/src/utils/failed-response-status-reasons.ts +0 -70
- package/src/utils/index.ts +0 -1
- package/src/v2/express.ts +0 -1
- package/src/v2/hono.ts +0 -1
- package/src/v2/index.ts +0 -5
- package/src/v2/node.ts +0 -1
- package/src/v2/runtime/__tests__/agents-factory.test.ts +0 -136
- package/src/v2/runtime/__tests__/backward-compat.test.ts +0 -261
- package/src/v2/runtime/__tests__/code-review-fixes.test.ts +0 -500
- package/src/v2/runtime/__tests__/cors-credentials.test.ts +0 -320
- package/src/v2/runtime/__tests__/debug-sse-response.test.ts +0 -302
- package/src/v2/runtime/__tests__/express-adapter.test.ts +0 -188
- package/src/v2/runtime/__tests__/express-body-order.test.ts +0 -76
- package/src/v2/runtime/__tests__/express-fetch-bridge.test.ts +0 -344
- package/src/v2/runtime/__tests__/express-single-sse.test.ts +0 -122
- package/src/v2/runtime/__tests__/express-single-telemetry.integration.test.ts +0 -65
- package/src/v2/runtime/__tests__/express-telemetry.integration.test.ts +0 -101
- package/src/v2/runtime/__tests__/fetch-cors.test.ts +0 -205
- package/src/v2/runtime/__tests__/fetch-handler-validation.test.ts +0 -440
- package/src/v2/runtime/__tests__/fetch-handler.test.ts +0 -456
- package/src/v2/runtime/__tests__/fetch-router.test.ts +0 -276
- package/src/v2/runtime/__tests__/get-runtime-info.test.ts +0 -335
- package/src/v2/runtime/__tests__/handle-connect.test.ts +0 -585
- package/src/v2/runtime/__tests__/handle-run.test.ts +0 -1388
- package/src/v2/runtime/__tests__/handle-threads.test.ts +0 -930
- package/src/v2/runtime/__tests__/handle-transcribe.test.ts +0 -301
- package/src/v2/runtime/__tests__/header-utils.test.ts +0 -88
- package/src/v2/runtime/__tests__/hono-adapter.test.ts +0 -150
- package/src/v2/runtime/__tests__/hono-single-telemetry.integration.test.ts +0 -46
- package/src/v2/runtime/__tests__/hono-telemetry.integration.test.ts +0 -99
- package/src/v2/runtime/__tests__/hooks-edge-cases.test.ts +0 -457
- package/src/v2/runtime/__tests__/hooks.test.ts +0 -557
- package/src/v2/runtime/__tests__/in-process-agent-runner-messages.test.ts +0 -230
- package/src/v2/runtime/__tests__/in-process-agent-runner.test.ts +0 -1030
- package/src/v2/runtime/__tests__/integration/bun/bun-servers.integration.test.ts +0 -27
- package/src/v2/runtime/__tests__/integration/bun/elysia-multi.ts +0 -32
- package/src/v2/runtime/__tests__/integration/bun/elysia-single.ts +0 -33
- package/src/v2/runtime/__tests__/integration/bun/hono-bun-multi.ts +0 -25
- package/src/v2/runtime/__tests__/integration/bun/hono-bun-single.ts +0 -32
- package/src/v2/runtime/__tests__/integration/helpers/create-test-runtime.ts +0 -15
- package/src/v2/runtime/__tests__/integration/helpers/sse-reader.ts +0 -45
- package/src/v2/runtime/__tests__/integration/helpers/test-agent.ts +0 -58
- package/src/v2/runtime/__tests__/integration/node-servers.integration.test.ts +0 -58
- package/src/v2/runtime/__tests__/integration/servers/express-multi.ts +0 -35
- package/src/v2/runtime/__tests__/integration/servers/express-single.ts +0 -36
- package/src/v2/runtime/__tests__/integration/servers/fetch-direct.ts +0 -39
- package/src/v2/runtime/__tests__/integration/servers/hono-multi.ts +0 -30
- package/src/v2/runtime/__tests__/integration/servers/hono-single.ts +0 -37
- package/src/v2/runtime/__tests__/integration/servers/node-multi.ts +0 -45
- package/src/v2/runtime/__tests__/integration/servers/node-single.ts +0 -46
- package/src/v2/runtime/__tests__/integration/servers/types.ts +0 -18
- package/src/v2/runtime/__tests__/integration/suites/debug-events.suite.ts +0 -253
- package/src/v2/runtime/__tests__/integration/suites/multi-endpoint.suite.ts +0 -358
- package/src/v2/runtime/__tests__/integration/suites/single-endpoint.suite.ts +0 -363
- package/src/v2/runtime/__tests__/intelligence-run-telemetry.test.ts +0 -194
- package/src/v2/runtime/__tests__/mcp-apps-middleware-integration.test.ts +0 -275
- package/src/v2/runtime/__tests__/middleware-express.test.ts +0 -208
- package/src/v2/runtime/__tests__/middleware-single-express.test.ts +0 -213
- package/src/v2/runtime/__tests__/middleware-single.test.ts +0 -225
- package/src/v2/runtime/__tests__/middleware-sse-parser.test.ts +0 -237
- package/src/v2/runtime/__tests__/middleware.test.ts +0 -250
- package/src/v2/runtime/__tests__/node-fetch-handler.test.ts +0 -157
- package/src/v2/runtime/__tests__/open-generative-ui-middleware.e2e.test.ts +0 -728
- package/src/v2/runtime/__tests__/router-edge-cases.test.ts +0 -217
- package/src/v2/runtime/__tests__/routing-express.test.ts +0 -174
- package/src/v2/runtime/__tests__/routing-single-express.test.ts +0 -168
- package/src/v2/runtime/__tests__/routing-single.test.ts +0 -193
- package/src/v2/runtime/__tests__/routing.test.ts +0 -257
- package/src/v2/runtime/__tests__/runtime.test.ts +0 -234
- package/src/v2/runtime/__tests__/sse-response-telemetry.test.ts +0 -108
- package/src/v2/runtime/__tests__/telemetry.test.ts +0 -167
- package/src/v2/runtime/__tests__/thread-names.test.ts +0 -188
- package/src/v2/runtime/core/__tests__/debug-event-bus.test.ts +0 -156
- package/src/v2/runtime/core/debug-event-bus.ts +0 -45
- package/src/v2/runtime/core/fetch-cors.ts +0 -136
- package/src/v2/runtime/core/fetch-handler.ts +0 -492
- package/src/v2/runtime/core/fetch-router.ts +0 -203
- package/src/v2/runtime/core/hooks.ts +0 -160
- package/src/v2/runtime/core/middleware-sse-parser.ts +0 -210
- package/src/v2/runtime/core/middleware.ts +0 -115
- package/src/v2/runtime/core/runtime.ts +0 -432
- package/src/v2/runtime/endpoints/express-fetch-bridge.ts +0 -137
- package/src/v2/runtime/endpoints/express-single.ts +0 -54
- package/src/v2/runtime/endpoints/express.ts +0 -179
- package/src/v2/runtime/endpoints/hono-single.ts +0 -60
- package/src/v2/runtime/endpoints/hono.ts +0 -89
- package/src/v2/runtime/endpoints/index.ts +0 -4
- package/src/v2/runtime/endpoints/node-fetch-handler.ts +0 -48
- package/src/v2/runtime/endpoints/node.ts +0 -28
- package/src/v2/runtime/endpoints/single-route-helpers.ts +0 -125
- package/src/v2/runtime/express.ts +0 -2
- package/src/v2/runtime/handlers/__tests__/handle-debug-events.test.ts +0 -176
- package/src/v2/runtime/handlers/get-runtime-info.ts +0 -101
- package/src/v2/runtime/handlers/handle-connect.ts +0 -80
- package/src/v2/runtime/handlers/handle-debug-events.ts +0 -52
- package/src/v2/runtime/handlers/handle-run.ts +0 -111
- package/src/v2/runtime/handlers/handle-stop.ts +0 -77
- package/src/v2/runtime/handlers/handle-threads.ts +0 -11
- package/src/v2/runtime/handlers/handle-transcribe.ts +0 -269
- package/src/v2/runtime/handlers/header-utils.ts +0 -24
- package/src/v2/runtime/handlers/intelligence/connect.ts +0 -102
- package/src/v2/runtime/handlers/intelligence/run.ts +0 -351
- package/src/v2/runtime/handlers/intelligence/thread-names.ts +0 -246
- package/src/v2/runtime/handlers/intelligence/threads.ts +0 -420
- package/src/v2/runtime/handlers/shared/agent-utils.ts +0 -154
- package/src/v2/runtime/handlers/shared/intelligence-utils.ts +0 -41
- package/src/v2/runtime/handlers/shared/json-response.ts +0 -9
- package/src/v2/runtime/handlers/shared/resolve-intelligence-user.ts +0 -28
- package/src/v2/runtime/handlers/shared/sse-response.ts +0 -215
- package/src/v2/runtime/handlers/sse/__tests__/sse-connect-agent-id.test.ts +0 -71
- package/src/v2/runtime/handlers/sse/connect.ts +0 -30
- package/src/v2/runtime/handlers/sse/run.ts +0 -40
- package/src/v2/runtime/hono.ts +0 -2
- package/src/v2/runtime/index.ts +0 -51
- package/src/v2/runtime/intelligence-platform/__tests__/client.test.ts +0 -601
- package/src/v2/runtime/intelligence-platform/__tests__/intelligence-mcp-helper.test.ts +0 -246
- package/src/v2/runtime/intelligence-platform/client.ts +0 -818
- package/src/v2/runtime/intelligence-platform/index.ts +0 -10
- package/src/v2/runtime/node.ts +0 -6
- package/src/v2/runtime/open-generative-ui-middleware.ts +0 -373
- package/src/v2/runtime/runner/__tests__/finalize-events.test.ts +0 -109
- package/src/v2/runtime/runner/__tests__/in-memory-runner.e2e.test.ts +0 -775
- package/src/v2/runtime/runner/__tests__/in-memory-runner.test.ts +0 -777
- package/src/v2/runtime/runner/__tests__/intelligence-runner.test.ts +0 -1039
- package/src/v2/runtime/runner/agent-runner.ts +0 -35
- package/src/v2/runtime/runner/in-memory.ts +0 -467
- package/src/v2/runtime/runner/index.ts +0 -4
- package/src/v2/runtime/runner/intelligence.ts +0 -498
- package/src/v2/runtime/telemetry/__tests__/instance-created.test.ts +0 -96
- package/src/v2/runtime/telemetry/events.ts +0 -35
- package/src/v2/runtime/telemetry/index.ts +0 -7
- package/src/v2/runtime/telemetry/instance-created.ts +0 -44
- package/src/v2/runtime/telemetry/scarf-client.ts +0 -39
- package/src/v2/runtime/telemetry/telemetry-client.ts +0 -70
- package/src/v2/runtime/transcription-service/transcription-service.ts +0 -11
- package/tests/global.d.ts +0 -1
- package/tests/service-adapters/anthropic/allowlist-approach.test.ts +0 -259
- package/tests/service-adapters/anthropic/anthropic-adapter-language-model.test.ts +0 -101
- package/tests/service-adapters/anthropic/anthropic-adapter.test.ts +0 -645
- package/tests/service-adapters/anthropic/utils-token-trimming.test.ts +0 -301
- package/tests/service-adapters/groq/groq-adapter-language-model.test.ts +0 -102
- package/tests/service-adapters/openai/allowlist-approach.test.ts +0 -294
- package/tests/service-adapters/openai/openai-adapter-language-model.test.ts +0 -122
- package/tests/service-adapters/openai/openai-adapter.test.ts +0 -291
- package/tests/service-adapters/shared/sdk-client-utils.test.ts +0 -36
- package/tests/setup.vitest.ts +0 -8
- package/tests/tsconfig.json +0 -10
- package/tsconfig.json +0 -20
- package/tsdown.config.ts +0 -45
- package/typedoc.json +0 -4
- package/vitest.config.mjs +0 -13
|
@@ -1,777 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach } from "vitest";
|
|
2
|
-
import { InMemoryAgentRunner } from "../in-memory";
|
|
3
|
-
import type { InMemoryThread } from "../in-memory";
|
|
4
|
-
import type {
|
|
5
|
-
BaseEvent,
|
|
6
|
-
Message,
|
|
7
|
-
RunAgentInput,
|
|
8
|
-
RunErrorEvent,
|
|
9
|
-
RunStartedEvent,
|
|
10
|
-
TextMessageContentEvent,
|
|
11
|
-
TextMessageEndEvent,
|
|
12
|
-
TextMessageStartEvent,
|
|
13
|
-
ToolCallResultEvent,
|
|
14
|
-
} from "@ag-ui/client";
|
|
15
|
-
import { AbstractAgent, EventType } from "@ag-ui/client";
|
|
16
|
-
import { EMPTY, firstValueFrom } from "rxjs";
|
|
17
|
-
import { toArray } from "rxjs/operators";
|
|
18
|
-
|
|
19
|
-
const stripTerminalEvents = (events: BaseEvent[]) =>
|
|
20
|
-
events.filter(
|
|
21
|
-
(event) =>
|
|
22
|
-
event.type !== EventType.RUN_FINISHED &&
|
|
23
|
-
event.type !== EventType.RUN_ERROR,
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
class TestAgent extends AbstractAgent {
|
|
27
|
-
constructor(
|
|
28
|
-
private readonly events: BaseEvent[] = [],
|
|
29
|
-
private readonly emitDefaultRunStarted = true,
|
|
30
|
-
) {
|
|
31
|
-
super();
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async runAgent(
|
|
35
|
-
input: RunAgentInput,
|
|
36
|
-
options: {
|
|
37
|
-
onEvent: (event: { event: BaseEvent }) => void;
|
|
38
|
-
onNewMessage?: (args: { message: Message }) => void;
|
|
39
|
-
onRunStartedEvent?: () => void;
|
|
40
|
-
},
|
|
41
|
-
): Promise<void> {
|
|
42
|
-
if (this.emitDefaultRunStarted) {
|
|
43
|
-
const runStarted: RunStartedEvent = {
|
|
44
|
-
type: EventType.RUN_STARTED,
|
|
45
|
-
threadId: input.threadId,
|
|
46
|
-
runId: input.runId,
|
|
47
|
-
};
|
|
48
|
-
options.onEvent({ event: runStarted });
|
|
49
|
-
options.onRunStartedEvent?.();
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
for (const event of this.events) {
|
|
53
|
-
options.onEvent({ event });
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
clone(): AbstractAgent {
|
|
58
|
-
return new TestAgent(this.events, this.emitDefaultRunStarted);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
protected run(): ReturnType<AbstractAgent["run"]> {
|
|
62
|
-
return EMPTY;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
protected connect(): ReturnType<AbstractAgent["connect"]> {
|
|
66
|
-
return EMPTY;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
class ThrowingAgent extends AbstractAgent {
|
|
71
|
-
constructor(private readonly error: Error) {
|
|
72
|
-
super();
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
async runAgent(): Promise<void> {
|
|
76
|
-
throw this.error;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
clone(): AbstractAgent {
|
|
80
|
-
return new ThrowingAgent(this.error);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
protected run(): ReturnType<AbstractAgent["run"]> {
|
|
84
|
-
return EMPTY;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
protected connect(): ReturnType<AbstractAgent["connect"]> {
|
|
88
|
-
return EMPTY;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
describe("InMemoryAgentRunner", () => {
|
|
93
|
-
let runner: InMemoryAgentRunner;
|
|
94
|
-
|
|
95
|
-
beforeEach(() => {
|
|
96
|
-
runner = new InMemoryAgentRunner();
|
|
97
|
-
runner.clearThreads();
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
describe("RunStarted payload", () => {
|
|
101
|
-
it("emits RUN_STARTED before agent events", async () => {
|
|
102
|
-
const threadId = "in-memory-basic";
|
|
103
|
-
const agent = new TestAgent([
|
|
104
|
-
{
|
|
105
|
-
type: EventType.TEXT_MESSAGE_START,
|
|
106
|
-
messageId: "msg-1",
|
|
107
|
-
role: "assistant",
|
|
108
|
-
} as TextMessageStartEvent,
|
|
109
|
-
{
|
|
110
|
-
type: EventType.TEXT_MESSAGE_CONTENT,
|
|
111
|
-
messageId: "msg-1",
|
|
112
|
-
delta: "Hello",
|
|
113
|
-
} as TextMessageContentEvent,
|
|
114
|
-
{
|
|
115
|
-
type: EventType.TEXT_MESSAGE_END,
|
|
116
|
-
messageId: "msg-1",
|
|
117
|
-
} as TextMessageEndEvent,
|
|
118
|
-
]);
|
|
119
|
-
|
|
120
|
-
const events = await firstValueFrom(
|
|
121
|
-
runner
|
|
122
|
-
.run({
|
|
123
|
-
threadId,
|
|
124
|
-
agent,
|
|
125
|
-
input: { threadId, runId: "run-1", messages: [], state: {} },
|
|
126
|
-
})
|
|
127
|
-
.pipe(toArray()),
|
|
128
|
-
);
|
|
129
|
-
|
|
130
|
-
const nonTerminalEvents = stripTerminalEvents(events);
|
|
131
|
-
expect(nonTerminalEvents).toHaveLength(4);
|
|
132
|
-
expect(nonTerminalEvents[0].type).toBe(EventType.RUN_STARTED);
|
|
133
|
-
const compacted = nonTerminalEvents.slice(1);
|
|
134
|
-
expect(compacted[0].type).toBe(EventType.TEXT_MESSAGE_START);
|
|
135
|
-
expect(compacted[1].type).toBe(EventType.TEXT_MESSAGE_CONTENT);
|
|
136
|
-
expect((compacted[1] as TextMessageContentEvent).delta).toBe("Hello");
|
|
137
|
-
expect(compacted[2].type).toBe(EventType.TEXT_MESSAGE_END);
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it("attaches only new messages to the RUN_STARTED input", async () => {
|
|
141
|
-
const threadId = "in-memory-new-messages";
|
|
142
|
-
const existing: Message = {
|
|
143
|
-
id: "existing-msg",
|
|
144
|
-
role: "user",
|
|
145
|
-
content: "Hi",
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
await firstValueFrom(
|
|
149
|
-
runner
|
|
150
|
-
.run({
|
|
151
|
-
threadId,
|
|
152
|
-
agent: new TestAgent(),
|
|
153
|
-
input: {
|
|
154
|
-
threadId,
|
|
155
|
-
runId: "run-0",
|
|
156
|
-
messages: [existing],
|
|
157
|
-
state: {},
|
|
158
|
-
},
|
|
159
|
-
})
|
|
160
|
-
.pipe(toArray()),
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
const newMessage: Message = {
|
|
164
|
-
id: "new-msg",
|
|
165
|
-
role: "user",
|
|
166
|
-
content: "Follow up",
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
const secondRun = await firstValueFrom(
|
|
170
|
-
runner
|
|
171
|
-
.run({
|
|
172
|
-
threadId,
|
|
173
|
-
agent: new TestAgent(),
|
|
174
|
-
input: {
|
|
175
|
-
threadId,
|
|
176
|
-
runId: "run-1",
|
|
177
|
-
messages: [existing, newMessage],
|
|
178
|
-
state: { counter: 1 },
|
|
179
|
-
},
|
|
180
|
-
})
|
|
181
|
-
.pipe(toArray()),
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
const runStarted = secondRun[0] as RunStartedEvent;
|
|
185
|
-
expect(runStarted.input?.messages?.map((m) => m.id)).toEqual(["new-msg"]);
|
|
186
|
-
expect(runStarted.input?.state).toEqual({ counter: 1 });
|
|
187
|
-
|
|
188
|
-
const connectEvents = await firstValueFrom(
|
|
189
|
-
runner.connect({ threadId }).pipe(toArray()),
|
|
190
|
-
);
|
|
191
|
-
const latestRunStarted = connectEvents
|
|
192
|
-
.filter(
|
|
193
|
-
(event): event is RunStartedEvent =>
|
|
194
|
-
event.type === EventType.RUN_STARTED,
|
|
195
|
-
)
|
|
196
|
-
.pop();
|
|
197
|
-
expect(latestRunStarted?.input?.messages?.map((m) => m.id)).toEqual([
|
|
198
|
-
"new-msg",
|
|
199
|
-
]);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
it("preserves agent-provided RUN_STARTED input", async () => {
|
|
203
|
-
const threadId = "in-memory-agent-input";
|
|
204
|
-
const providedInput: RunAgentInput = {
|
|
205
|
-
threadId,
|
|
206
|
-
runId: "run-preserve",
|
|
207
|
-
messages: [],
|
|
208
|
-
state: { fromAgent: true },
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
const agent = new TestAgent(
|
|
212
|
-
[
|
|
213
|
-
{
|
|
214
|
-
type: EventType.RUN_STARTED,
|
|
215
|
-
threadId,
|
|
216
|
-
runId: "run-preserve",
|
|
217
|
-
input: providedInput,
|
|
218
|
-
} as RunStartedEvent,
|
|
219
|
-
],
|
|
220
|
-
false,
|
|
221
|
-
);
|
|
222
|
-
|
|
223
|
-
const events = await firstValueFrom(
|
|
224
|
-
runner
|
|
225
|
-
.run({
|
|
226
|
-
threadId,
|
|
227
|
-
agent,
|
|
228
|
-
input: {
|
|
229
|
-
threadId,
|
|
230
|
-
runId: "run-preserve",
|
|
231
|
-
messages: [{ id: "extra", role: "user", content: "hi" }],
|
|
232
|
-
state: {},
|
|
233
|
-
},
|
|
234
|
-
})
|
|
235
|
-
.pipe(toArray()),
|
|
236
|
-
);
|
|
237
|
-
|
|
238
|
-
const nonTerminalEvents = stripTerminalEvents(events);
|
|
239
|
-
expect(nonTerminalEvents).toHaveLength(1);
|
|
240
|
-
const runStarted = nonTerminalEvents[0] as RunStartedEvent;
|
|
241
|
-
expect(runStarted.input).toBe(providedInput);
|
|
242
|
-
});
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
describe("Event propagation", () => {
|
|
246
|
-
it("replays agent events for new connections", async () => {
|
|
247
|
-
const threadId = "in-memory-replay";
|
|
248
|
-
const agent = new TestAgent([
|
|
249
|
-
{
|
|
250
|
-
type: EventType.TEXT_MESSAGE_START,
|
|
251
|
-
messageId: "msg-1",
|
|
252
|
-
role: "assistant",
|
|
253
|
-
} as TextMessageStartEvent,
|
|
254
|
-
{
|
|
255
|
-
type: EventType.TEXT_MESSAGE_CONTENT,
|
|
256
|
-
messageId: "msg-1",
|
|
257
|
-
delta: "Hello",
|
|
258
|
-
} as TextMessageContentEvent,
|
|
259
|
-
{
|
|
260
|
-
type: EventType.TEXT_MESSAGE_END,
|
|
261
|
-
messageId: "msg-1",
|
|
262
|
-
} as TextMessageEndEvent,
|
|
263
|
-
]);
|
|
264
|
-
|
|
265
|
-
await firstValueFrom(
|
|
266
|
-
runner
|
|
267
|
-
.run({
|
|
268
|
-
threadId,
|
|
269
|
-
agent,
|
|
270
|
-
input: { threadId, runId: "run-1", messages: [], state: {} },
|
|
271
|
-
})
|
|
272
|
-
.pipe(toArray()),
|
|
273
|
-
);
|
|
274
|
-
|
|
275
|
-
const connectEvents = await firstValueFrom(
|
|
276
|
-
runner.connect({ threadId }).pipe(toArray()),
|
|
277
|
-
);
|
|
278
|
-
|
|
279
|
-
const nonTerminalEvents = stripTerminalEvents(connectEvents);
|
|
280
|
-
expect(nonTerminalEvents).toHaveLength(4);
|
|
281
|
-
expect(nonTerminalEvents[0].type).toBe(EventType.RUN_STARTED);
|
|
282
|
-
expect(nonTerminalEvents.slice(1).map((event) => event.type)).toEqual([
|
|
283
|
-
EventType.TEXT_MESSAGE_START,
|
|
284
|
-
EventType.TEXT_MESSAGE_CONTENT,
|
|
285
|
-
EventType.TEXT_MESSAGE_END,
|
|
286
|
-
]);
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
it("keeps agent-generated tool results", async () => {
|
|
290
|
-
const threadId = "in-memory-tool-results";
|
|
291
|
-
const agent = new TestAgent([
|
|
292
|
-
{
|
|
293
|
-
type: EventType.TOOL_CALL_RESULT,
|
|
294
|
-
messageId: "tool-msg",
|
|
295
|
-
toolCallId: "tool-call",
|
|
296
|
-
content: "42",
|
|
297
|
-
role: "tool",
|
|
298
|
-
} as ToolCallResultEvent,
|
|
299
|
-
]);
|
|
300
|
-
|
|
301
|
-
const events = await firstValueFrom(
|
|
302
|
-
runner
|
|
303
|
-
.run({
|
|
304
|
-
threadId,
|
|
305
|
-
agent,
|
|
306
|
-
input: { threadId, runId: "run-1", messages: [], state: {} },
|
|
307
|
-
})
|
|
308
|
-
.pipe(toArray()),
|
|
309
|
-
);
|
|
310
|
-
|
|
311
|
-
const nonTerminalEvents = stripTerminalEvents(events);
|
|
312
|
-
expect(nonTerminalEvents).toHaveLength(2);
|
|
313
|
-
const [, toolResult] = nonTerminalEvents;
|
|
314
|
-
expect(toolResult.type).toBe(EventType.TOOL_CALL_RESULT);
|
|
315
|
-
});
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
describe("Error propagation", () => {
|
|
319
|
-
it("propagates the agent error message into the RUN_ERROR event", async () => {
|
|
320
|
-
const threadId = "in-memory-error-propagation";
|
|
321
|
-
const httpError = new Error("HTTP 401: Unauthorized");
|
|
322
|
-
const agent = new ThrowingAgent(httpError);
|
|
323
|
-
|
|
324
|
-
const events = await firstValueFrom(
|
|
325
|
-
runner
|
|
326
|
-
.run({
|
|
327
|
-
threadId,
|
|
328
|
-
agent,
|
|
329
|
-
input: { threadId, runId: "run-err", messages: [], state: {} },
|
|
330
|
-
})
|
|
331
|
-
.pipe(toArray()),
|
|
332
|
-
);
|
|
333
|
-
|
|
334
|
-
const errorEvent = events.find(
|
|
335
|
-
(event): event is RunErrorEvent => event.type === EventType.RUN_ERROR,
|
|
336
|
-
);
|
|
337
|
-
|
|
338
|
-
expect(errorEvent).toBeDefined();
|
|
339
|
-
expect(errorEvent!.message).toBe("HTTP 401: Unauthorized");
|
|
340
|
-
// RUN_ERROR must be the terminal event — the runner must not also emit
|
|
341
|
-
// RUN_FINISHED on the failure path, and nothing should follow the error.
|
|
342
|
-
expect(events[events.length - 1].type).toBe(EventType.RUN_ERROR);
|
|
343
|
-
expect(
|
|
344
|
-
events.filter((e) => e.type === EventType.RUN_FINISHED),
|
|
345
|
-
).toHaveLength(0);
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
it("propagates non-HTTP error messages into the RUN_ERROR event", async () => {
|
|
349
|
-
const threadId = "in-memory-error-generic";
|
|
350
|
-
const agent = new ThrowingAgent(new Error("Connection refused"));
|
|
351
|
-
|
|
352
|
-
const events = await firstValueFrom(
|
|
353
|
-
runner
|
|
354
|
-
.run({
|
|
355
|
-
threadId,
|
|
356
|
-
agent,
|
|
357
|
-
input: { threadId, runId: "run-err-2", messages: [], state: {} },
|
|
358
|
-
})
|
|
359
|
-
.pipe(toArray()),
|
|
360
|
-
);
|
|
361
|
-
|
|
362
|
-
const errorEvent = events.find(
|
|
363
|
-
(event): event is RunErrorEvent => event.type === EventType.RUN_ERROR,
|
|
364
|
-
);
|
|
365
|
-
|
|
366
|
-
expect(errorEvent).toBeDefined();
|
|
367
|
-
expect(errorEvent!.message).toBe("Connection refused");
|
|
368
|
-
});
|
|
369
|
-
});
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
// ---------------------------------------------------------------------------
|
|
373
|
-
// Agent that populates this.messages after a run — needed to test the
|
|
374
|
-
// listThreads / getThreadMessages fallback which reads agent.messages.
|
|
375
|
-
// ---------------------------------------------------------------------------
|
|
376
|
-
class MessagePopulatingTestAgent extends AbstractAgent {
|
|
377
|
-
constructor(
|
|
378
|
-
// Accept undefined so `clone()` can forward `this.agentId` losslessly.
|
|
379
|
-
// `AbstractAgent.agentId` is optional (`AgentConfig.agentId?: string`),
|
|
380
|
-
// so coercing undefined to "" would silently turn "no agent id" into
|
|
381
|
-
// "empty agent id" — a different state.
|
|
382
|
-
agentId: string | undefined,
|
|
383
|
-
private readonly inputMessages: Message[],
|
|
384
|
-
private readonly generatedMessages: Message[],
|
|
385
|
-
) {
|
|
386
|
-
super({ agentId });
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// Override runAgent to simulate what a real agent does: populate this.messages
|
|
390
|
-
// with the full conversation (input + generated) then call the subscriber callbacks.
|
|
391
|
-
// Aligns with TestAgent above — `onEvent` is required so the in-memory runner
|
|
392
|
-
// contract (always supply an event sink) is exercised exactly the same way.
|
|
393
|
-
// `onNewMessage` is declared optional to match TestAgent and the actual
|
|
394
|
-
// runner call site, which always passes it. Without the declaration the
|
|
395
|
-
// mock's options shape silently drifts from production and a regression
|
|
396
|
-
// that starts depending on `onNewMessage` here would compile cleanly.
|
|
397
|
-
async runAgent(
|
|
398
|
-
input: RunAgentInput,
|
|
399
|
-
options: {
|
|
400
|
-
onEvent: (params: { event: BaseEvent }) => void;
|
|
401
|
-
onNewMessage?: (args: { message: Message }) => void;
|
|
402
|
-
onRunStartedEvent?: () => void;
|
|
403
|
-
},
|
|
404
|
-
): Promise<{ result: unknown; newMessages: Message[] }> {
|
|
405
|
-
const runStarted: RunStartedEvent = {
|
|
406
|
-
type: EventType.RUN_STARTED,
|
|
407
|
-
threadId: input.threadId,
|
|
408
|
-
runId: input.runId,
|
|
409
|
-
};
|
|
410
|
-
options.onEvent({ event: runStarted });
|
|
411
|
-
options.onRunStartedEvent?.();
|
|
412
|
-
|
|
413
|
-
for (const msg of this.generatedMessages) {
|
|
414
|
-
const start = {
|
|
415
|
-
type: EventType.TEXT_MESSAGE_START,
|
|
416
|
-
messageId: msg.id,
|
|
417
|
-
role: (msg as { role: string }).role,
|
|
418
|
-
} as TextMessageStartEvent;
|
|
419
|
-
const content = {
|
|
420
|
-
type: EventType.TEXT_MESSAGE_CONTENT,
|
|
421
|
-
messageId: msg.id,
|
|
422
|
-
delta: (msg as { content?: string }).content ?? "",
|
|
423
|
-
} as TextMessageContentEvent;
|
|
424
|
-
const end = {
|
|
425
|
-
type: EventType.TEXT_MESSAGE_END,
|
|
426
|
-
messageId: msg.id,
|
|
427
|
-
} as TextMessageEndEvent;
|
|
428
|
-
options.onEvent({ event: start });
|
|
429
|
-
options.onEvent({ event: content });
|
|
430
|
-
options.onEvent({ event: end });
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
// Populate this.messages — this is what real AbstractAgent.runAgent does
|
|
434
|
-
this.messages = [...this.inputMessages, ...this.generatedMessages];
|
|
435
|
-
return { result: undefined, newMessages: this.generatedMessages };
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
clone(): AbstractAgent {
|
|
439
|
-
return new MessagePopulatingTestAgent(
|
|
440
|
-
this.agentId,
|
|
441
|
-
this.inputMessages,
|
|
442
|
-
this.generatedMessages,
|
|
443
|
-
);
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
protected run(): ReturnType<AbstractAgent["run"]> {
|
|
447
|
-
return EMPTY;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
// Mirror `TestAgent` and `ThrowingAgent` — `AbstractAgent.connect()` would
|
|
451
|
-
// otherwise inherit production behavior that may try to open a transport.
|
|
452
|
-
// Returning EMPTY keeps clones inert in tests.
|
|
453
|
-
protected connect(): ReturnType<AbstractAgent["connect"]> {
|
|
454
|
-
return EMPTY;
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
describe("InMemoryAgentRunner — listThreads / getThreadMessages", () => {
|
|
459
|
-
let runner: InMemoryAgentRunner;
|
|
460
|
-
|
|
461
|
-
const userMessage: Message = { id: "u1", role: "user", content: "Hello" };
|
|
462
|
-
const assistantMessage: Message = {
|
|
463
|
-
id: "a1",
|
|
464
|
-
role: "assistant",
|
|
465
|
-
content: "Hi there!",
|
|
466
|
-
};
|
|
467
|
-
|
|
468
|
-
beforeEach(async () => {
|
|
469
|
-
runner = new InMemoryAgentRunner();
|
|
470
|
-
// Reset the module-level GLOBAL_STORE singleton so tests don't leak into each other
|
|
471
|
-
runner.clearThreads();
|
|
472
|
-
|
|
473
|
-
// Run a single turn on a unique thread so each test starts fresh
|
|
474
|
-
const agent = new MessagePopulatingTestAgent(
|
|
475
|
-
"test-agent",
|
|
476
|
-
[userMessage],
|
|
477
|
-
[assistantMessage],
|
|
478
|
-
);
|
|
479
|
-
await firstValueFrom(
|
|
480
|
-
runner
|
|
481
|
-
.run({
|
|
482
|
-
threadId: "list-threads-thread-1",
|
|
483
|
-
agent,
|
|
484
|
-
input: {
|
|
485
|
-
threadId: "list-threads-thread-1",
|
|
486
|
-
runId: "run-lt-1",
|
|
487
|
-
messages: [userMessage],
|
|
488
|
-
state: {},
|
|
489
|
-
tools: [],
|
|
490
|
-
context: [],
|
|
491
|
-
},
|
|
492
|
-
})
|
|
493
|
-
.pipe(toArray()),
|
|
494
|
-
);
|
|
495
|
-
});
|
|
496
|
-
|
|
497
|
-
describe("listThreads", () => {
|
|
498
|
-
it("returns a summary for each completed thread", () => {
|
|
499
|
-
const threads = runner.listThreads();
|
|
500
|
-
const thread = threads.find(
|
|
501
|
-
(t: InMemoryThread) => t.id === "list-threads-thread-1",
|
|
502
|
-
);
|
|
503
|
-
expect(thread).toBeDefined();
|
|
504
|
-
expect(thread!.agentId).toBe("test-agent");
|
|
505
|
-
expect(thread!.name).toBeNull();
|
|
506
|
-
expect(thread!.archived).toBe(false);
|
|
507
|
-
expect(thread!.createdAt).toBeTruthy();
|
|
508
|
-
expect(thread!.updatedAt).toBeTruthy();
|
|
509
|
-
});
|
|
510
|
-
|
|
511
|
-
it("returns threads sorted most-recently-updated first", async () => {
|
|
512
|
-
// Run a second thread after a delay long enough that timer-resolution
|
|
513
|
-
// jitter on slow CI runners cannot collapse the two timestamps. 20ms
|
|
514
|
-
// sits comfortably above typical setTimeout granularity (~4ms in Node)
|
|
515
|
-
// and the file-system timestamp resolution we observed flakes around.
|
|
516
|
-
await new Promise((r) => setTimeout(r, 20));
|
|
517
|
-
const agent2 = new MessagePopulatingTestAgent(
|
|
518
|
-
"test-agent",
|
|
519
|
-
[userMessage],
|
|
520
|
-
[assistantMessage],
|
|
521
|
-
);
|
|
522
|
-
await firstValueFrom(
|
|
523
|
-
runner
|
|
524
|
-
.run({
|
|
525
|
-
threadId: "list-threads-thread-2",
|
|
526
|
-
agent: agent2,
|
|
527
|
-
input: {
|
|
528
|
-
threadId: "list-threads-thread-2",
|
|
529
|
-
runId: "run-lt-2",
|
|
530
|
-
messages: [userMessage],
|
|
531
|
-
state: {},
|
|
532
|
-
tools: [],
|
|
533
|
-
context: [],
|
|
534
|
-
},
|
|
535
|
-
})
|
|
536
|
-
.pipe(toArray()),
|
|
537
|
-
);
|
|
538
|
-
|
|
539
|
-
const threads = runner.listThreads();
|
|
540
|
-
const ids = threads.map((t: InMemoryThread) => t.id);
|
|
541
|
-
const idx1 = ids.indexOf("list-threads-thread-1");
|
|
542
|
-
const idx2 = ids.indexOf("list-threads-thread-2");
|
|
543
|
-
// thread-2 is more recent, should appear before thread-1
|
|
544
|
-
expect(idx2).toBeLessThan(idx1);
|
|
545
|
-
});
|
|
546
|
-
|
|
547
|
-
it("returns an empty array when no threads have been run", () => {
|
|
548
|
-
const freshRunner = new InMemoryAgentRunner();
|
|
549
|
-
freshRunner.clearThreads();
|
|
550
|
-
expect(freshRunner.listThreads()).toEqual([]);
|
|
551
|
-
});
|
|
552
|
-
});
|
|
553
|
-
|
|
554
|
-
describe("getThreadMessages", () => {
|
|
555
|
-
it("returns all messages for a completed thread", () => {
|
|
556
|
-
const messages = runner.getThreadMessages("list-threads-thread-1");
|
|
557
|
-
expect(messages).toHaveLength(2);
|
|
558
|
-
const roles = messages.map((m) => (m as { role: string }).role);
|
|
559
|
-
expect(roles).toContain("user");
|
|
560
|
-
expect(roles).toContain("assistant");
|
|
561
|
-
});
|
|
562
|
-
|
|
563
|
-
it("includes message content", () => {
|
|
564
|
-
const messages = runner.getThreadMessages("list-threads-thread-1");
|
|
565
|
-
const user = messages.find(
|
|
566
|
-
(m) => (m as { role: string }).role === "user",
|
|
567
|
-
) as {
|
|
568
|
-
content?: string;
|
|
569
|
-
};
|
|
570
|
-
const assistant = messages.find(
|
|
571
|
-
(m) => (m as { role: string }).role === "assistant",
|
|
572
|
-
) as { content?: string };
|
|
573
|
-
expect(user?.content).toBe("Hello");
|
|
574
|
-
expect(assistant?.content).toBe("Hi there!");
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
it("returns an empty array for an unknown threadId", () => {
|
|
578
|
-
const messages = runner.getThreadMessages("nonexistent-thread-xyz");
|
|
579
|
-
expect(messages).toEqual([]);
|
|
580
|
-
});
|
|
581
|
-
|
|
582
|
-
it("reflects the most recent run's full message history", async () => {
|
|
583
|
-
const followUp: Message = {
|
|
584
|
-
id: "u2",
|
|
585
|
-
role: "user",
|
|
586
|
-
content: "Follow up",
|
|
587
|
-
};
|
|
588
|
-
const followUpReply: Message = {
|
|
589
|
-
id: "a2",
|
|
590
|
-
role: "assistant",
|
|
591
|
-
content: "Sure!",
|
|
592
|
-
};
|
|
593
|
-
const agent2 = new MessagePopulatingTestAgent(
|
|
594
|
-
"test-agent",
|
|
595
|
-
[userMessage, assistantMessage, followUp],
|
|
596
|
-
[followUpReply],
|
|
597
|
-
);
|
|
598
|
-
await firstValueFrom(
|
|
599
|
-
runner
|
|
600
|
-
.run({
|
|
601
|
-
threadId: "list-threads-thread-1",
|
|
602
|
-
agent: agent2,
|
|
603
|
-
input: {
|
|
604
|
-
threadId: "list-threads-thread-1",
|
|
605
|
-
runId: "run-lt-turn-2",
|
|
606
|
-
messages: [userMessage, assistantMessage, followUp],
|
|
607
|
-
state: {},
|
|
608
|
-
tools: [],
|
|
609
|
-
context: [],
|
|
610
|
-
},
|
|
611
|
-
})
|
|
612
|
-
.pipe(toArray()),
|
|
613
|
-
);
|
|
614
|
-
|
|
615
|
-
const messages = runner.getThreadMessages("list-threads-thread-1");
|
|
616
|
-
// Should have all 4 messages from the second run's snapshot
|
|
617
|
-
expect(messages).toHaveLength(4);
|
|
618
|
-
});
|
|
619
|
-
});
|
|
620
|
-
|
|
621
|
-
describe("getThreadEvents", () => {
|
|
622
|
-
it("returns stored events for a completed thread", () => {
|
|
623
|
-
const events = runner.getThreadEvents("list-threads-thread-1");
|
|
624
|
-
// The beforeEach runs a single turn. The MessagePopulatingTestAgent
|
|
625
|
-
// emits RUN_STARTED + a TEXT_MESSAGE triple for the assistant reply
|
|
626
|
-
// and never emits a terminal event itself.
|
|
627
|
-
expect(events.length).toBeGreaterThan(0);
|
|
628
|
-
const types = events.map((e) => e.type);
|
|
629
|
-
expect(types).toContain(EventType.RUN_STARTED);
|
|
630
|
-
// Content events must be present so the inspector can replay full
|
|
631
|
-
// thread history — guard against a regression that strips them
|
|
632
|
-
// during compaction.
|
|
633
|
-
expect(types).toContain(EventType.TEXT_MESSAGE_START);
|
|
634
|
-
expect(types).toContain(EventType.TEXT_MESSAGE_CONTENT);
|
|
635
|
-
expect(types).toContain(EventType.TEXT_MESSAGE_END);
|
|
636
|
-
// finalizeRunEvents mutates the events array to append a synthetic
|
|
637
|
-
// terminal event when the agent does not emit one itself: a
|
|
638
|
-
// RUN_ERROR with code INCOMPLETE_STREAM. Asserting this explicitly
|
|
639
|
-
// guards against a regression where the synthetic event is dropped
|
|
640
|
-
// (the inspector would render an in-progress thread forever) or
|
|
641
|
-
// where the code is silently changed to something inspectors don't
|
|
642
|
-
// recognise.
|
|
643
|
-
const terminal = events.find(
|
|
644
|
-
(e): e is BaseEvent & { code?: string } =>
|
|
645
|
-
e.type === EventType.RUN_ERROR,
|
|
646
|
-
);
|
|
647
|
-
expect(terminal).toBeDefined();
|
|
648
|
-
expect((terminal as { code?: string }).code).toBe("INCOMPLETE_STREAM");
|
|
649
|
-
});
|
|
650
|
-
|
|
651
|
-
it("returns an empty array for an unknown threadId", () => {
|
|
652
|
-
expect(runner.getThreadEvents("nonexistent-thread-xyz")).toEqual([]);
|
|
653
|
-
});
|
|
654
|
-
|
|
655
|
-
it("flattens events across multiple historic runs", async () => {
|
|
656
|
-
const followUp: Message = {
|
|
657
|
-
id: "u2",
|
|
658
|
-
role: "user",
|
|
659
|
-
content: "Follow up",
|
|
660
|
-
};
|
|
661
|
-
const agent2 = new MessagePopulatingTestAgent(
|
|
662
|
-
"test-agent",
|
|
663
|
-
[userMessage, assistantMessage, followUp],
|
|
664
|
-
[{ id: "a2", role: "assistant", content: "Sure!" }],
|
|
665
|
-
);
|
|
666
|
-
await firstValueFrom(
|
|
667
|
-
runner
|
|
668
|
-
.run({
|
|
669
|
-
threadId: "list-threads-thread-1",
|
|
670
|
-
agent: agent2,
|
|
671
|
-
input: {
|
|
672
|
-
threadId: "list-threads-thread-1",
|
|
673
|
-
runId: "run-lt-turn-2",
|
|
674
|
-
messages: [userMessage, assistantMessage, followUp],
|
|
675
|
-
state: {},
|
|
676
|
-
tools: [],
|
|
677
|
-
context: [],
|
|
678
|
-
},
|
|
679
|
-
})
|
|
680
|
-
.pipe(toArray()),
|
|
681
|
-
);
|
|
682
|
-
|
|
683
|
-
const events = runner.getThreadEvents("list-threads-thread-1");
|
|
684
|
-
const runStartedCount = events.filter(
|
|
685
|
-
(e) => e.type === EventType.RUN_STARTED,
|
|
686
|
-
).length;
|
|
687
|
-
// Two runs means two RUN_STARTED events survive compaction.
|
|
688
|
-
expect(runStartedCount).toBe(2);
|
|
689
|
-
});
|
|
690
|
-
});
|
|
691
|
-
|
|
692
|
-
describe("getThreadState", () => {
|
|
693
|
-
it("returns null when the thread has never emitted a state snapshot", () => {
|
|
694
|
-
// The beforeEach agent doesn't emit STATE_SNAPSHOT events.
|
|
695
|
-
expect(runner.getThreadState("list-threads-thread-1")).toBeNull();
|
|
696
|
-
});
|
|
697
|
-
|
|
698
|
-
it("returns null for an unknown threadId", () => {
|
|
699
|
-
expect(runner.getThreadState("nonexistent-thread-xyz")).toBeNull();
|
|
700
|
-
});
|
|
701
|
-
|
|
702
|
-
it("returns the last STATE_SNAPSHOT payload after a run", async () => {
|
|
703
|
-
const snapshot = { counter: 7, name: "alpha" };
|
|
704
|
-
const stateAgent = new TestAgent(
|
|
705
|
-
[
|
|
706
|
-
{
|
|
707
|
-
type: EventType.STATE_SNAPSHOT,
|
|
708
|
-
snapshot,
|
|
709
|
-
} as BaseEvent,
|
|
710
|
-
],
|
|
711
|
-
true,
|
|
712
|
-
);
|
|
713
|
-
await firstValueFrom(
|
|
714
|
-
runner
|
|
715
|
-
.run({
|
|
716
|
-
threadId: "thread-with-state",
|
|
717
|
-
agent: stateAgent,
|
|
718
|
-
input: {
|
|
719
|
-
threadId: "thread-with-state",
|
|
720
|
-
runId: "run-state-1",
|
|
721
|
-
messages: [],
|
|
722
|
-
state: {},
|
|
723
|
-
tools: [],
|
|
724
|
-
context: [],
|
|
725
|
-
},
|
|
726
|
-
})
|
|
727
|
-
.pipe(toArray()),
|
|
728
|
-
);
|
|
729
|
-
|
|
730
|
-
expect(runner.getThreadState("thread-with-state")).toEqual(snapshot);
|
|
731
|
-
});
|
|
732
|
-
|
|
733
|
-
it("returns the most recent snapshot across multiple runs", async () => {
|
|
734
|
-
const first = { step: 1 };
|
|
735
|
-
const second = { step: 2 };
|
|
736
|
-
|
|
737
|
-
const run = async (threadId: string, runId: string, snapshot: object) => {
|
|
738
|
-
const agent = new TestAgent(
|
|
739
|
-
[{ type: EventType.STATE_SNAPSHOT, snapshot } as BaseEvent],
|
|
740
|
-
true,
|
|
741
|
-
);
|
|
742
|
-
await firstValueFrom(
|
|
743
|
-
runner
|
|
744
|
-
.run({
|
|
745
|
-
threadId,
|
|
746
|
-
agent,
|
|
747
|
-
input: {
|
|
748
|
-
threadId,
|
|
749
|
-
runId,
|
|
750
|
-
messages: [],
|
|
751
|
-
state: {},
|
|
752
|
-
tools: [],
|
|
753
|
-
context: [],
|
|
754
|
-
},
|
|
755
|
-
})
|
|
756
|
-
.pipe(toArray()),
|
|
757
|
-
);
|
|
758
|
-
};
|
|
759
|
-
|
|
760
|
-
await run("thread-multi-state", "run-a", first);
|
|
761
|
-
await run("thread-multi-state", "run-b", second);
|
|
762
|
-
|
|
763
|
-
expect(runner.getThreadState("thread-multi-state")).toEqual(second);
|
|
764
|
-
|
|
765
|
-
// Cross-thread isolation: a snapshot on a different thread must not
|
|
766
|
-
// bleed into the original thread's state. This guards against any
|
|
767
|
-
// accidental "last-write-wins" leak in the per-thread state store.
|
|
768
|
-
const otherThreadSnapshot = { step: 999 };
|
|
769
|
-
await run("thread-other", "run-other", otherThreadSnapshot);
|
|
770
|
-
|
|
771
|
-
expect(runner.getThreadState("thread-other")).toEqual(
|
|
772
|
-
otherThreadSnapshot,
|
|
773
|
-
);
|
|
774
|
-
expect(runner.getThreadState("thread-multi-state")).toEqual(second);
|
|
775
|
-
});
|
|
776
|
-
});
|
|
777
|
-
});
|