@copilotkit/runtime 1.56.4-canary.1777538870 → 1.56.5
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/agent/converters/tanstack.cjs +6 -0
- package/dist/agent/converters/tanstack.cjs.map +1 -1
- package/dist/agent/converters/tanstack.mjs +6 -0
- package/dist/agent/converters/tanstack.mjs.map +1 -1
- package/dist/agent/index.cjs +8 -37
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts +27 -52
- package/dist/agent/index.d.cts.map +1 -1
- package/dist/agent/index.d.mts +27 -52
- package/dist/agent/index.d.mts.map +1 -1
- package/dist/agent/index.mjs +9 -38
- package/dist/agent/index.mjs.map +1 -1
- package/dist/lib/runtime/agent-integrations/langgraph/agent.cjs +8 -1
- package/dist/lib/runtime/agent-integrations/langgraph/agent.cjs.map +1 -1
- package/dist/lib/runtime/agent-integrations/langgraph/agent.d.cts.map +1 -1
- package/dist/lib/runtime/agent-integrations/langgraph/agent.d.mts.map +1 -1
- package/dist/lib/runtime/agent-integrations/langgraph/agent.mjs +8 -1
- package/dist/lib/runtime/agent-integrations/langgraph/agent.mjs.map +1 -1
- package/dist/package.cjs +5 -5
- package/dist/package.mjs +5 -5
- package/dist/v2/index.cjs +0 -2
- package/dist/v2/index.d.cts +5 -6
- package/dist/v2/index.d.mts +5 -6
- package/dist/v2/index.mjs +1 -2
- package/dist/v2/runtime/core/runtime.d.cts +0 -1
- package/dist/v2/runtime/core/runtime.d.cts.map +1 -1
- package/dist/v2/runtime/core/runtime.d.mts +0 -1
- package/dist/v2/runtime/core/runtime.d.mts.map +1 -1
- package/dist/v2/runtime/endpoints/express.cjs +5 -5
- package/dist/v2/runtime/endpoints/express.cjs.map +1 -1
- package/dist/v2/runtime/endpoints/express.mjs +5 -5
- package/dist/v2/runtime/endpoints/express.mjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/run.cjs +0 -4
- package/dist/v2/runtime/handlers/intelligence/run.cjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/run.mjs +0 -4
- package/dist/v2/runtime/handlers/intelligence/run.mjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/agent-utils.cjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/agent-utils.mjs.map +1 -1
- package/dist/v2/runtime/index.d.cts +1 -3
- package/dist/v2/runtime/index.d.cts.map +1 -1
- package/dist/v2/runtime/index.d.mts +1 -3
- package/dist/v2/runtime/index.d.mts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.cjs +0 -52
- package/dist/v2/runtime/intelligence-platform/client.cjs.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.d.cts +0 -41
- package/dist/v2/runtime/intelligence-platform/client.d.cts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.d.mts +0 -41
- package/dist/v2/runtime/intelligence-platform/client.d.mts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.mjs +0 -52
- package/dist/v2/runtime/intelligence-platform/client.mjs.map +1 -1
- package/package.json +6 -6
- package/src/agent/__tests__/mcp-clients.test.ts +25 -11
- package/src/agent/__tests__/mcp-servers-integration.test.ts +1 -355
- package/src/agent/converters/tanstack.ts +18 -0
- package/src/agent/index.ts +65 -128
- package/src/lib/runtime/agent-integrations/langgraph/agent.ts +8 -1
- package/src/v2/runtime/__tests__/express-fetch-bridge.test.ts +1 -1
- package/src/v2/runtime/endpoints/express.ts +9 -3
- package/src/v2/runtime/handlers/intelligence/run.ts +0 -9
- package/src/v2/runtime/handlers/shared/agent-utils.ts +0 -1
- package/src/v2/runtime/index.ts +0 -5
- package/src/v2/runtime/intelligence-platform/client.ts +0 -67
- package/dist/agent/mcp-transport.cjs +0 -94
- package/dist/agent/mcp-transport.cjs.map +0 -1
- package/dist/agent/mcp-transport.d.cts +0 -51
- package/dist/agent/mcp-transport.d.cts.map +0 -1
- package/dist/agent/mcp-transport.d.mts +0 -52
- package/dist/agent/mcp-transport.d.mts.map +0 -1
- package/dist/agent/mcp-transport.mjs +0 -92
- package/dist/agent/mcp-transport.mjs.map +0 -1
- package/dist/v2/runtime/intelligence-platform/index.d.cts +0 -2
- package/dist/v2/runtime/intelligence-platform/index.d.mts +0 -2
- package/src/agent/mcp-transport.ts +0 -190
- package/src/v2/runtime/intelligence-platform/__tests__/intelligence-mcp-helper.test.ts +0 -188
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import type { RunAgentInput } from "@ag-ui/client";
|
|
2
|
-
import type { JSONRPCMessage, MCPTransport } from "@ai-sdk/mcp";
|
|
3
|
-
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
4
|
-
import type { StreamableHTTPClientTransportOptions } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
5
|
-
import type { FetchLike } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* The end-user identity resolved by the runtime's `identifyUser` callback for
|
|
9
|
-
* the current request. Surfaced on {@link MCPRequestContext} so MCP header
|
|
10
|
-
* resolvers can read it without re-doing auth work.
|
|
11
|
-
*/
|
|
12
|
-
export interface MCPRuntimeUser {
|
|
13
|
-
id: string;
|
|
14
|
-
name: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Context handed to {@link MCPClientConfigHTTP.getHeaders} on every outbound
|
|
19
|
-
* MCP HTTP request. The resolver is invoked fresh per request — initialize,
|
|
20
|
-
* tools/list, tools/call, and reconnects — so values it depends on are never
|
|
21
|
-
* cached across calls.
|
|
22
|
-
*/
|
|
23
|
-
export interface MCPRequestContext {
|
|
24
|
-
/**
|
|
25
|
-
* Headers forwarded onto the agent for this run. Populated by the runtime's
|
|
26
|
-
* `extractForwardableHeaders` (`authorization` + every `x-*` header from the
|
|
27
|
-
* incoming HTTP request). Keys are lower-cased.
|
|
28
|
-
*/
|
|
29
|
-
requestHeaders: Record<string, string>;
|
|
30
|
-
/** The {@link RunAgentInput} the agent is currently running. */
|
|
31
|
-
input: RunAgentInput;
|
|
32
|
-
/** URL of the MCP server this request is going to. */
|
|
33
|
-
mcpServerUrl: string;
|
|
34
|
-
/**
|
|
35
|
-
* The end-user identity for this run, resolved by the runtime's
|
|
36
|
-
* `identifyUser` callback (only populated when the agent is run via a
|
|
37
|
-
* `CopilotRuntime` configured with `identifyUser`). Snapshotted at
|
|
38
|
-
* run-start.
|
|
39
|
-
*/
|
|
40
|
-
user?: MCPRuntimeUser;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Thrown when an MCP {@link MCPClientConfigHTTP.getHeaders} resolver throws.
|
|
45
|
-
* Wraps the underlying error so `RUN_ERROR` carries clear attribution instead
|
|
46
|
-
* of a generic transport failure. The original error is preserved on the
|
|
47
|
-
* standard ES2022 `Error.cause` chain.
|
|
48
|
-
*/
|
|
49
|
-
export class MCPHeaderResolverError extends Error {
|
|
50
|
-
constructor(message: string, cause: unknown) {
|
|
51
|
-
super(message, { cause });
|
|
52
|
-
this.name = "MCPHeaderResolverError";
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export interface CopilotKitMCPTransportOptions {
|
|
57
|
-
/** URL of the MCP server. */
|
|
58
|
-
url: string;
|
|
59
|
-
/** Static HTTP headers, merged into every outbound request. */
|
|
60
|
-
headers?: Record<string, string>;
|
|
61
|
-
/**
|
|
62
|
-
* Per-call header resolver. Invoked on **every** outbound HTTP request to
|
|
63
|
-
* this server (initialize, tools/list, tools/call, reconnects). Returned
|
|
64
|
-
* headers are merged on top of `headers`, so a resolver can override either.
|
|
65
|
-
*/
|
|
66
|
-
getHeaders?: (
|
|
67
|
-
ctx: MCPRequestContext,
|
|
68
|
-
) => Record<string, string> | Promise<Record<string, string>>;
|
|
69
|
-
/**
|
|
70
|
-
* Pre-existing escape hatch: low-level options for the underlying
|
|
71
|
-
* `StreamableHTTPClientTransport`. Forwarded as-is, except `fetch` is
|
|
72
|
-
* wrapped so static `headers` and `getHeaders` resolution still apply.
|
|
73
|
-
*/
|
|
74
|
-
options?: StreamableHTTPClientTransportOptions;
|
|
75
|
-
/** Snapshot of the agent's per-run forwarded headers, captured at run-start. */
|
|
76
|
-
requestHeaders: Record<string, string>;
|
|
77
|
-
/** RunAgentInput for the current run, exposed to the resolver via context. */
|
|
78
|
-
input: RunAgentInput;
|
|
79
|
-
/** Per-run end-user identity from the runtime's `identifyUser`, if set. */
|
|
80
|
-
user?: MCPRuntimeUser;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* MCP transport for CopilotKit's BuiltInAgent that adds per-call header
|
|
85
|
-
* resolution on top of the standard Streamable HTTP transport.
|
|
86
|
-
*
|
|
87
|
-
* Implements `@ai-sdk/mcp`'s {@link MCPTransport} interface so it can be
|
|
88
|
-
* passed straight to `createMCPClient({ transport })`. Internally delegates
|
|
89
|
-
* to `@modelcontextprotocol/sdk`'s `StreamableHTTPClientTransport` with a
|
|
90
|
-
* wrapped `fetch` that runs the static-header + per-call resolver pipeline
|
|
91
|
-
* before each outbound request.
|
|
92
|
-
*/
|
|
93
|
-
export class CopilotKitMCPTransport implements MCPTransport {
|
|
94
|
-
private readonly inner: StreamableHTTPClientTransport;
|
|
95
|
-
|
|
96
|
-
constructor(options: CopilotKitMCPTransportOptions) {
|
|
97
|
-
const transportOptions: StreamableHTTPClientTransportOptions = {
|
|
98
|
-
...options.options,
|
|
99
|
-
fetch: buildWrappedFetch(options),
|
|
100
|
-
};
|
|
101
|
-
this.inner = new StreamableHTTPClientTransport(
|
|
102
|
-
new URL(options.url),
|
|
103
|
-
transportOptions,
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
get onclose(): (() => void) | undefined {
|
|
108
|
-
return this.inner.onclose;
|
|
109
|
-
}
|
|
110
|
-
set onclose(handler: (() => void) | undefined) {
|
|
111
|
-
this.inner.onclose = handler;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
get onerror(): ((error: Error) => void) | undefined {
|
|
115
|
-
return this.inner.onerror;
|
|
116
|
-
}
|
|
117
|
-
set onerror(handler: ((error: Error) => void) | undefined) {
|
|
118
|
-
this.inner.onerror = handler;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
get onmessage(): ((message: JSONRPCMessage) => void) | undefined {
|
|
122
|
-
return this.inner.onmessage as
|
|
123
|
-
| ((message: JSONRPCMessage) => void)
|
|
124
|
-
| undefined;
|
|
125
|
-
}
|
|
126
|
-
set onmessage(handler: ((message: JSONRPCMessage) => void) | undefined) {
|
|
127
|
-
this.inner.onmessage = handler as
|
|
128
|
-
| ((message: JSONRPCMessage) => void)
|
|
129
|
-
| undefined;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
start(): Promise<void> {
|
|
133
|
-
return this.inner.start();
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
send(message: JSONRPCMessage): Promise<void> {
|
|
137
|
-
return this.inner.send(message as Parameters<typeof this.inner.send>[0]);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
close(): Promise<void> {
|
|
141
|
-
return this.inner.close();
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function buildWrappedFetch(options: CopilotKitMCPTransportOptions): FetchLike {
|
|
146
|
-
const {
|
|
147
|
-
headers: staticHeaders,
|
|
148
|
-
getHeaders,
|
|
149
|
-
requestHeaders,
|
|
150
|
-
input,
|
|
151
|
-
url: mcpServerUrl,
|
|
152
|
-
user,
|
|
153
|
-
options: transportOptions,
|
|
154
|
-
} = options;
|
|
155
|
-
const baseFetch: FetchLike = transportOptions?.fetch ?? globalThis.fetch;
|
|
156
|
-
|
|
157
|
-
return async (fetchUrl, init) => {
|
|
158
|
-
// SDK passes a Headers instance via init.headers — start fresh from it so
|
|
159
|
-
// we don't mutate the SDK's object, then layer headers on top via .set()
|
|
160
|
-
// (last write wins).
|
|
161
|
-
const merged = new Headers(init?.headers);
|
|
162
|
-
if (staticHeaders) {
|
|
163
|
-
for (const [key, value] of Object.entries(staticHeaders)) {
|
|
164
|
-
merged.set(key, value);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
if (getHeaders) {
|
|
168
|
-
let resolved: Record<string, string>;
|
|
169
|
-
try {
|
|
170
|
-
resolved = await getHeaders({
|
|
171
|
-
requestHeaders,
|
|
172
|
-
input,
|
|
173
|
-
mcpServerUrl,
|
|
174
|
-
user,
|
|
175
|
-
});
|
|
176
|
-
} catch (err) {
|
|
177
|
-
throw new MCPHeaderResolverError(
|
|
178
|
-
`MCP header resolver for ${mcpServerUrl} threw: ${
|
|
179
|
-
err instanceof Error ? err.message : String(err)
|
|
180
|
-
}`,
|
|
181
|
-
err,
|
|
182
|
-
);
|
|
183
|
-
}
|
|
184
|
-
for (const [key, value] of Object.entries(resolved)) {
|
|
185
|
-
merged.set(key, value);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
return baseFetch(fetchUrl, { ...init, headers: merged });
|
|
189
|
-
};
|
|
190
|
-
}
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { CopilotKitIntelligence } from "../client";
|
|
3
|
-
import { BasicAgent } from "../../../../agent";
|
|
4
|
-
import { EventType } from "@ag-ui/client";
|
|
5
|
-
import { LLMock, MCPMock } from "@copilotkit/aimock";
|
|
6
|
-
import { streamText } from "ai";
|
|
7
|
-
import {
|
|
8
|
-
mockStreamTextResponse,
|
|
9
|
-
textDelta,
|
|
10
|
-
finish,
|
|
11
|
-
collectEvents,
|
|
12
|
-
} from "../../../../agent/__tests__/test-helpers";
|
|
13
|
-
|
|
14
|
-
vi.mock("ai", () => ({
|
|
15
|
-
streamText: vi.fn(),
|
|
16
|
-
tool: vi.fn((config) => config),
|
|
17
|
-
stepCountIs: vi.fn((count: number) => ({ type: "stepCount", count })),
|
|
18
|
-
}));
|
|
19
|
-
|
|
20
|
-
vi.mock("@ai-sdk/openai", () => ({
|
|
21
|
-
createOpenAI: vi.fn(() => (modelId: string) => ({
|
|
22
|
-
modelId,
|
|
23
|
-
provider: "openai",
|
|
24
|
-
})),
|
|
25
|
-
}));
|
|
26
|
-
|
|
27
|
-
async function startMcpMock(): Promise<{ url: string; server: LLMock }> {
|
|
28
|
-
const mock = new MCPMock();
|
|
29
|
-
mock.addTool({
|
|
30
|
-
name: "bash",
|
|
31
|
-
description: "Run a bash command",
|
|
32
|
-
inputSchema: {
|
|
33
|
-
type: "object",
|
|
34
|
-
properties: { command: { type: "string" } },
|
|
35
|
-
},
|
|
36
|
-
});
|
|
37
|
-
mock.onToolCall("bash", () => "ok");
|
|
38
|
-
const server = new LLMock({ port: 0 });
|
|
39
|
-
server.mount("/mcp", mock);
|
|
40
|
-
await server.start();
|
|
41
|
-
return { url: server.url, server };
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* aimock redacts `Authorization` to `[REDACTED]` in its journal. Spy on
|
|
46
|
-
* `globalThis.fetch` to read unredacted headers off each outbound request to
|
|
47
|
-
* `mcpUrl`. The spy delegates to the real fetch so the round-trip completes.
|
|
48
|
-
*/
|
|
49
|
-
function spyOnFetch(mcpUrl: string): {
|
|
50
|
-
records: Array<Record<string, string>>;
|
|
51
|
-
restore: () => void;
|
|
52
|
-
} {
|
|
53
|
-
const records: Array<Record<string, string>> = [];
|
|
54
|
-
const realFetch = globalThis.fetch;
|
|
55
|
-
const spy = vi
|
|
56
|
-
.spyOn(globalThis, "fetch")
|
|
57
|
-
.mockImplementation(async (input, init) => {
|
|
58
|
-
const url =
|
|
59
|
-
typeof input === "string"
|
|
60
|
-
? input
|
|
61
|
-
: input instanceof URL
|
|
62
|
-
? input.toString()
|
|
63
|
-
: input.url;
|
|
64
|
-
if (url.startsWith(mcpUrl)) {
|
|
65
|
-
const seen: Record<string, string> = {};
|
|
66
|
-
new Headers(init?.headers ?? {}).forEach((value, key) => {
|
|
67
|
-
seen[key.toLowerCase()] = value;
|
|
68
|
-
});
|
|
69
|
-
records.push(seen);
|
|
70
|
-
}
|
|
71
|
-
return realFetch(input, init);
|
|
72
|
-
});
|
|
73
|
-
return { records, restore: () => spy.mockRestore() };
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
describe("CopilotKitIntelligence.toMCPServer()", () => {
|
|
77
|
-
const baseInput = {
|
|
78
|
-
threadId: "thread1",
|
|
79
|
-
runId: "run1",
|
|
80
|
-
messages: [],
|
|
81
|
-
tools: [],
|
|
82
|
-
context: [],
|
|
83
|
-
state: {},
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
let llm: LLMock | undefined;
|
|
87
|
-
const originalEnv = process.env;
|
|
88
|
-
|
|
89
|
-
beforeEach(() => {
|
|
90
|
-
vi.clearAllMocks();
|
|
91
|
-
process.env = { ...originalEnv };
|
|
92
|
-
process.env.OPENAI_API_KEY = "test-key";
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
afterEach(async () => {
|
|
96
|
-
process.env = originalEnv;
|
|
97
|
-
if (llm) {
|
|
98
|
-
await llm.stop().catch(() => {});
|
|
99
|
-
llm = undefined;
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it("emits Authorization (Bearer apiKey) and X-Cpki-User-Id (resolved user) on every MCP request", async () => {
|
|
104
|
-
const { url, server } = await startMcpMock();
|
|
105
|
-
llm = server;
|
|
106
|
-
|
|
107
|
-
const intelligence = new CopilotKitIntelligence({
|
|
108
|
-
apiUrl: url,
|
|
109
|
-
wsUrl: "wss://unused.example.com/socket",
|
|
110
|
-
apiKey: "cpk-proj_short_long",
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
const recorder = spyOnFetch(url);
|
|
114
|
-
try {
|
|
115
|
-
const agent = new BasicAgent({
|
|
116
|
-
model: "openai/gpt-4o",
|
|
117
|
-
mcpServers: [intelligence.toMCPServer()],
|
|
118
|
-
});
|
|
119
|
-
// The runtime would normally populate this via `identifyUser` after
|
|
120
|
-
// resolveIntelligenceUser. Simulate the same outcome here.
|
|
121
|
-
agent.user = { id: "jordan-beamson", name: "Jordan Beamson" };
|
|
122
|
-
|
|
123
|
-
vi.mocked(streamText).mockReturnValue(
|
|
124
|
-
mockStreamTextResponse([textDelta("hi"), finish()]) as any,
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
await collectEvents(agent["run"](baseInput));
|
|
128
|
-
|
|
129
|
-
expect(recorder.records.length).toBeGreaterThan(0);
|
|
130
|
-
for (const headers of recorder.records) {
|
|
131
|
-
expect(headers["authorization"]).toBe("Bearer cpk-proj_short_long");
|
|
132
|
-
expect(headers["x-cpki-user-id"]).toBe("jordan-beamson");
|
|
133
|
-
}
|
|
134
|
-
} finally {
|
|
135
|
-
recorder.restore();
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
it("throws when no user has been resolved (runtime missing identifyUser)", async () => {
|
|
140
|
-
const { url, server } = await startMcpMock();
|
|
141
|
-
llm = server;
|
|
142
|
-
|
|
143
|
-
const intelligence = new CopilotKitIntelligence({
|
|
144
|
-
apiUrl: url,
|
|
145
|
-
wsUrl: "wss://unused.example.com/socket",
|
|
146
|
-
apiKey: "cpk-proj_short_long",
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
const agent = new BasicAgent({
|
|
150
|
-
model: "openai/gpt-4o",
|
|
151
|
-
mcpServers: [intelligence.toMCPServer()],
|
|
152
|
-
});
|
|
153
|
-
// Deliberately leave `agent.user` unset — this is the case the helper
|
|
154
|
-
// must reject loudly so a misconfigured runtime doesn't silently collapse
|
|
155
|
-
// every browser session into one shared bash sandbox.
|
|
156
|
-
|
|
157
|
-
vi.mocked(streamText).mockReturnValue(
|
|
158
|
-
mockStreamTextResponse([finish()]) as any,
|
|
159
|
-
);
|
|
160
|
-
|
|
161
|
-
const events: any[] = [];
|
|
162
|
-
try {
|
|
163
|
-
await new Promise((resolve, reject) => {
|
|
164
|
-
agent["run"](baseInput).subscribe({
|
|
165
|
-
next: (event) => events.push(event),
|
|
166
|
-
error: (err) => reject(err),
|
|
167
|
-
complete: () => resolve(events),
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
} catch {
|
|
171
|
-
// expected
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const runError = events.find((e: any) => e.type === EventType.RUN_ERROR);
|
|
175
|
-
expect(runError).toBeDefined();
|
|
176
|
-
expect(runError?.message).toContain("no user resolved");
|
|
177
|
-
expect(runError?.message).toContain("identifyUser");
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it("URL is composed from apiUrl + /mcp (trailing slash on apiUrl is normalized)", () => {
|
|
181
|
-
const intelligence = new CopilotKitIntelligence({
|
|
182
|
-
apiUrl: "https://api.example.com/",
|
|
183
|
-
wsUrl: "wss://ws.example.com",
|
|
184
|
-
apiKey: "k",
|
|
185
|
-
});
|
|
186
|
-
expect(intelligence.toMCPServer().url).toBe("https://api.example.com/mcp");
|
|
187
|
-
});
|
|
188
|
-
});
|