@copilotkit/runtime 1.56.0 → 1.56.2-canary.pin-to-send
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/index.cjs +2 -2
- 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 +2 -2
- package/dist/agent/index.mjs.map +1 -1
- package/dist/graphql/resolvers/copilot.resolver.cjs +2 -1
- package/dist/graphql/resolvers/copilot.resolver.cjs.map +1 -1
- package/dist/graphql/resolvers/copilot.resolver.mjs +2 -1
- package/dist/graphql/resolvers/copilot.resolver.mjs.map +1 -1
- package/dist/graphql/resolvers/resolve-message-id.cjs +19 -0
- package/dist/graphql/resolvers/resolve-message-id.cjs.map +1 -0
- package/dist/graphql/resolvers/resolve-message-id.mjs +18 -0
- package/dist/graphql/resolvers/resolve-message-id.mjs.map +1 -0
- package/dist/lib/integrations/node-http/index.cjs +4 -1
- package/dist/lib/integrations/node-http/index.cjs.map +1 -1
- package/dist/lib/integrations/node-http/index.d.cts.map +1 -1
- package/dist/lib/integrations/node-http/index.d.mts.map +1 -1
- package/dist/lib/integrations/node-http/index.mjs +4 -1
- package/dist/lib/integrations/node-http/index.mjs.map +1 -1
- package/dist/lib/runtime/copilot-runtime.cjs +15 -3
- 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 +15 -3
- package/dist/lib/runtime/copilot-runtime.mjs.map +1 -1
- package/dist/lib/runtime/mcp-tools-utils.cjs +21 -4
- package/dist/lib/runtime/mcp-tools-utils.cjs.map +1 -1
- package/dist/lib/runtime/mcp-tools-utils.d.cts.map +1 -1
- package/dist/lib/runtime/mcp-tools-utils.d.mts.map +1 -1
- package/dist/lib/runtime/mcp-tools-utils.mjs +21 -4
- package/dist/lib/runtime/mcp-tools-utils.mjs.map +1 -1
- package/dist/package.cjs +2 -2
- package/dist/package.mjs +2 -2
- package/dist/service-adapters/anthropic/anthropic-adapter.cjs +11 -3
- package/dist/service-adapters/anthropic/anthropic-adapter.cjs.map +1 -1
- package/dist/service-adapters/anthropic/anthropic-adapter.d.cts +6 -0
- package/dist/service-adapters/anthropic/anthropic-adapter.d.cts.map +1 -1
- package/dist/service-adapters/anthropic/anthropic-adapter.d.mts +6 -0
- package/dist/service-adapters/anthropic/anthropic-adapter.d.mts.map +1 -1
- package/dist/service-adapters/anthropic/anthropic-adapter.mjs +11 -3
- package/dist/service-adapters/anthropic/anthropic-adapter.mjs.map +1 -1
- package/dist/service-adapters/anthropic/utils.cjs +27 -1
- package/dist/service-adapters/anthropic/utils.cjs.map +1 -1
- package/dist/service-adapters/anthropic/utils.mjs +27 -1
- package/dist/service-adapters/anthropic/utils.mjs.map +1 -1
- package/dist/service-adapters/langchain/utils.cjs +1 -1
- package/dist/service-adapters/langchain/utils.cjs.map +1 -1
- package/dist/service-adapters/langchain/utils.mjs +1 -1
- package/dist/service-adapters/langchain/utils.mjs.map +1 -1
- package/dist/service-adapters/openai/openai-adapter.cjs +2 -1
- package/dist/service-adapters/openai/openai-adapter.cjs.map +1 -1
- package/dist/service-adapters/openai/openai-adapter.d.cts +6 -0
- package/dist/service-adapters/openai/openai-adapter.d.cts.map +1 -1
- package/dist/service-adapters/openai/openai-adapter.d.mts +6 -0
- package/dist/service-adapters/openai/openai-adapter.d.mts.map +1 -1
- package/dist/service-adapters/openai/openai-adapter.mjs +2 -1
- package/dist/service-adapters/openai/openai-adapter.mjs.map +1 -1
- package/dist/v2/runtime/core/debug-event-bus.cjs +36 -0
- package/dist/v2/runtime/core/debug-event-bus.cjs.map +1 -0
- package/dist/v2/runtime/core/debug-event-bus.d.cts +19 -0
- package/dist/v2/runtime/core/debug-event-bus.d.cts.map +1 -0
- package/dist/v2/runtime/core/debug-event-bus.d.mts +19 -0
- package/dist/v2/runtime/core/debug-event-bus.d.mts.map +1 -0
- package/dist/v2/runtime/core/debug-event-bus.mjs +35 -0
- package/dist/v2/runtime/core/debug-event-bus.mjs.map +1 -0
- package/dist/v2/runtime/core/fetch-handler.cjs +6 -0
- package/dist/v2/runtime/core/fetch-handler.cjs.map +1 -1
- package/dist/v2/runtime/core/fetch-handler.d.cts.map +1 -1
- package/dist/v2/runtime/core/fetch-handler.d.mts.map +1 -1
- package/dist/v2/runtime/core/fetch-handler.mjs +6 -0
- package/dist/v2/runtime/core/fetch-handler.mjs.map +1 -1
- package/dist/v2/runtime/core/fetch-router.cjs +1 -0
- package/dist/v2/runtime/core/fetch-router.cjs.map +1 -1
- package/dist/v2/runtime/core/fetch-router.mjs +1 -0
- package/dist/v2/runtime/core/fetch-router.mjs.map +1 -1
- package/dist/v2/runtime/core/hooks.cjs.map +1 -1
- package/dist/v2/runtime/core/hooks.d.cts +2 -0
- package/dist/v2/runtime/core/hooks.d.cts.map +1 -1
- package/dist/v2/runtime/core/hooks.d.mts +2 -0
- package/dist/v2/runtime/core/hooks.d.mts.map +1 -1
- package/dist/v2/runtime/core/hooks.mjs.map +1 -1
- package/dist/v2/runtime/core/middleware-sse-parser.cjs +5 -2
- package/dist/v2/runtime/core/middleware-sse-parser.cjs.map +1 -1
- package/dist/v2/runtime/core/middleware-sse-parser.mjs +5 -2
- package/dist/v2/runtime/core/middleware-sse-parser.mjs.map +1 -1
- package/dist/v2/runtime/core/runtime.cjs +5 -0
- package/dist/v2/runtime/core/runtime.cjs.map +1 -1
- package/dist/v2/runtime/core/runtime.d.cts +5 -0
- package/dist/v2/runtime/core/runtime.d.cts.map +1 -1
- package/dist/v2/runtime/core/runtime.d.mts +5 -0
- package/dist/v2/runtime/core/runtime.d.mts.map +1 -1
- package/dist/v2/runtime/core/runtime.mjs +5 -0
- package/dist/v2/runtime/core/runtime.mjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-connect.cjs +2 -0
- package/dist/v2/runtime/handlers/handle-connect.cjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-connect.mjs +2 -0
- package/dist/v2/runtime/handlers/handle-connect.mjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-debug-events.cjs +33 -0
- package/dist/v2/runtime/handlers/handle-debug-events.cjs.map +1 -0
- package/dist/v2/runtime/handlers/handle-debug-events.mjs +32 -0
- package/dist/v2/runtime/handlers/handle-debug-events.mjs.map +1 -0
- package/dist/v2/runtime/handlers/handle-run.cjs +1 -0
- package/dist/v2/runtime/handlers/handle-run.cjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-run.mjs +1 -0
- package/dist/v2/runtime/handlers/handle-run.mjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/connect.cjs +32 -2
- package/dist/v2/runtime/handlers/intelligence/connect.cjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/connect.mjs +31 -2
- package/dist/v2/runtime/handlers/intelligence/connect.mjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/resolve-intelligence-user.cjs +5 -1
- package/dist/v2/runtime/handlers/shared/resolve-intelligence-user.cjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/resolve-intelligence-user.mjs +5 -1
- package/dist/v2/runtime/handlers/shared/resolve-intelligence-user.mjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/sse-response.cjs +21 -1
- package/dist/v2/runtime/handlers/shared/sse-response.cjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/sse-response.mjs +21 -1
- package/dist/v2/runtime/handlers/shared/sse-response.mjs.map +1 -1
- package/dist/v2/runtime/handlers/sse/connect.cjs +3 -1
- package/dist/v2/runtime/handlers/sse/connect.cjs.map +1 -1
- package/dist/v2/runtime/handlers/sse/connect.mjs +3 -1
- package/dist/v2/runtime/handlers/sse/connect.mjs.map +1 -1
- package/dist/v2/runtime/handlers/sse/run.cjs +3 -1
- package/dist/v2/runtime/handlers/sse/run.cjs.map +1 -1
- package/dist/v2/runtime/handlers/sse/run.mjs +3 -1
- package/dist/v2/runtime/handlers/sse/run.mjs.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.cjs +2 -7
- package/dist/v2/runtime/intelligence-platform/client.cjs.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.d.cts +1 -4
- package/dist/v2/runtime/intelligence-platform/client.d.cts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.d.mts +1 -4
- package/dist/v2/runtime/intelligence-platform/client.d.mts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.mjs +2 -7
- package/dist/v2/runtime/intelligence-platform/client.mjs.map +1 -1
- package/dist/v2/runtime/runner/intelligence.cjs +17 -5
- package/dist/v2/runtime/runner/intelligence.cjs.map +1 -1
- package/dist/v2/runtime/runner/intelligence.d.cts +1 -0
- package/dist/v2/runtime/runner/intelligence.d.cts.map +1 -1
- package/dist/v2/runtime/runner/intelligence.d.mts +1 -0
- package/dist/v2/runtime/runner/intelligence.d.mts.map +1 -1
- package/dist/v2/runtime/runner/intelligence.mjs +17 -5
- package/dist/v2/runtime/runner/intelligence.mjs.map +1 -1
- package/package.json +3 -3
- package/src/agent/__tests__/provider-id-collision.test.ts +195 -0
- package/src/agent/index.ts +19 -11
- package/src/agents/langgraph/__tests__/event-source.test.ts +256 -0
- package/src/graphql/resolvers/__tests__/resolve-message-id.test.ts +25 -0
- package/src/graphql/resolvers/copilot.resolver.ts +2 -1
- package/src/graphql/resolvers/resolve-message-id.ts +14 -0
- package/src/lib/integrations/node-http/__tests__/request-duck-type.test.ts +66 -0
- package/src/lib/integrations/node-http/index.ts +15 -1
- package/src/lib/runtime/__tests__/handle-service-adapter.test.ts +108 -0
- package/src/lib/runtime/__tests__/mcp-tools-utils.test.ts +30 -1
- package/src/lib/runtime/__tests__/on-after-request.test.ts +122 -0
- package/src/lib/runtime/__tests__/retry-utils.test.ts +137 -0
- package/src/lib/runtime/agent-integrations/langgraph/__tests__/dispatch-event-filtering.test.ts +190 -0
- package/src/lib/runtime/copilot-runtime.ts +36 -7
- package/src/lib/runtime/mcp-tools-utils.ts +41 -6
- package/src/lib/runtime/retry-utils.ts +41 -1
- package/src/service-adapters/anthropic/anthropic-adapter.ts +22 -2
- package/src/service-adapters/anthropic/utils.ts +60 -1
- package/src/service-adapters/langchain/utils.ts +1 -1
- package/src/service-adapters/openai/openai-adapter.ts +14 -1
- package/src/v2/runtime/__tests__/fetch-router.test.ts +22 -0
- package/src/v2/runtime/__tests__/handle-connect.test.ts +58 -5
- package/src/v2/runtime/__tests__/handle-run.test.ts +31 -4
- package/src/v2/runtime/__tests__/handle-threads.test.ts +66 -4
- package/src/v2/runtime/__tests__/integration/node-servers.integration.test.ts +19 -0
- package/src/v2/runtime/__tests__/integration/suites/debug-events.suite.ts +253 -0
- package/src/v2/runtime/__tests__/middleware-sse-parser.test.ts +50 -0
- package/src/v2/runtime/__tests__/runtime.test.ts +3 -1
- package/src/v2/runtime/core/__tests__/debug-event-bus.test.ts +156 -0
- package/src/v2/runtime/core/debug-event-bus.ts +45 -0
- package/src/v2/runtime/core/fetch-handler.ts +4 -0
- package/src/v2/runtime/core/fetch-router.ts +11 -0
- package/src/v2/runtime/core/hooks.ts +2 -1
- package/src/v2/runtime/core/middleware-sse-parser.ts +12 -2
- package/src/v2/runtime/core/runtime.ts +12 -0
- package/src/v2/runtime/handlers/__tests__/handle-debug-events.test.ts +176 -0
- package/src/v2/runtime/handlers/handle-connect.ts +2 -0
- package/src/v2/runtime/handlers/handle-debug-events.ts +52 -0
- package/src/v2/runtime/handlers/handle-run.ts +1 -0
- package/src/v2/runtime/handlers/intelligence/connect.ts +58 -1
- package/src/v2/runtime/handlers/shared/resolve-intelligence-user.ts +4 -1
- package/src/v2/runtime/handlers/shared/sse-response.ts +46 -0
- package/src/v2/runtime/handlers/sse/__tests__/sse-connect-agent-id.test.ts +71 -0
- package/src/v2/runtime/handlers/sse/connect.ts +6 -0
- package/src/v2/runtime/handlers/sse/run.ts +4 -0
- package/src/v2/runtime/intelligence-platform/__tests__/client.test.ts +13 -11
- package/src/v2/runtime/intelligence-platform/client.ts +3 -11
- package/src/v2/runtime/runner/__tests__/intelligence-runner.test.ts +51 -1
- package/src/v2/runtime/runner/intelligence.ts +27 -9
- package/tests/service-adapters/anthropic/anthropic-adapter.test.ts +268 -0
- package/tests/service-adapters/anthropic/utils-token-trimming.test.ts +301 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { BuiltInAgent } from "../index";
|
|
3
|
+
import { EventType, type RunAgentInput } from "@ag-ui/client";
|
|
4
|
+
import { streamText } from "ai";
|
|
5
|
+
import {
|
|
6
|
+
mockStreamTextResponse,
|
|
7
|
+
textDelta,
|
|
8
|
+
finish,
|
|
9
|
+
collectEvents,
|
|
10
|
+
} from "./test-helpers";
|
|
11
|
+
|
|
12
|
+
// Mock the ai module
|
|
13
|
+
vi.mock("ai", () => ({
|
|
14
|
+
streamText: vi.fn(),
|
|
15
|
+
tool: vi.fn((config) => config),
|
|
16
|
+
stepCountIs: vi.fn((count: number) => ({ type: "stepCount", count })),
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
vi.mock("@ai-sdk/openai", () => ({
|
|
20
|
+
createOpenAI: vi.fn(() => (modelId: string) => ({
|
|
21
|
+
specificationVersion: "v3",
|
|
22
|
+
modelId,
|
|
23
|
+
provider: "openai",
|
|
24
|
+
})),
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
vi.mock("@ai-sdk/anthropic", () => ({
|
|
28
|
+
createAnthropic: vi.fn(() => (modelId: string) => ({
|
|
29
|
+
specificationVersion: "v3",
|
|
30
|
+
modelId,
|
|
31
|
+
provider: "anthropic",
|
|
32
|
+
})),
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
vi.mock("@ai-sdk/google", () => ({
|
|
36
|
+
createGoogleGenerativeAI: vi.fn(() => (modelId: string) => ({
|
|
37
|
+
specificationVersion: "v3",
|
|
38
|
+
modelId,
|
|
39
|
+
provider: "google",
|
|
40
|
+
})),
|
|
41
|
+
}));
|
|
42
|
+
|
|
43
|
+
describe("Provider ID collision (#3410, #3623)", () => {
|
|
44
|
+
const originalEnv = process.env;
|
|
45
|
+
|
|
46
|
+
beforeEach(() => {
|
|
47
|
+
vi.clearAllMocks();
|
|
48
|
+
process.env = { ...originalEnv };
|
|
49
|
+
process.env.OPENAI_API_KEY = "test-key";
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
afterEach(() => {
|
|
53
|
+
process.env = originalEnv;
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('should replace text-start providedId "txt-0" with a UUID', async () => {
|
|
57
|
+
const agent = new BuiltInAgent({ model: "openai:gpt-4o-mini" });
|
|
58
|
+
|
|
59
|
+
vi.mocked(streamText).mockReturnValue(
|
|
60
|
+
mockStreamTextResponse([
|
|
61
|
+
{ type: "text-start", id: "txt-0" },
|
|
62
|
+
textDelta("Hello"),
|
|
63
|
+
finish(),
|
|
64
|
+
]) as any,
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
const input: RunAgentInput = {
|
|
68
|
+
threadId: "thread-1",
|
|
69
|
+
runId: "run-1",
|
|
70
|
+
messages: [{ id: "1", role: "user", content: "Hi" }],
|
|
71
|
+
tools: [],
|
|
72
|
+
context: [],
|
|
73
|
+
state: {},
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const events = await collectEvents(agent["run"](input));
|
|
77
|
+
|
|
78
|
+
// Find the TEXT_MESSAGE_CHUNK event and check its messageId
|
|
79
|
+
const textChunks = events.filter(
|
|
80
|
+
(e) => e.type === EventType.TEXT_MESSAGE_CHUNK,
|
|
81
|
+
);
|
|
82
|
+
expect(textChunks.length).toBeGreaterThan(0);
|
|
83
|
+
const messageId = (textChunks[0] as any).messageId;
|
|
84
|
+
|
|
85
|
+
// The messageId should NOT be "txt-0" — it should be a UUID
|
|
86
|
+
expect(messageId).not.toBe("txt-0");
|
|
87
|
+
// UUID v4 pattern
|
|
88
|
+
expect(messageId).toMatch(
|
|
89
|
+
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('should replace reasoning-start providedId "reasoning-0" with a UUID', async () => {
|
|
94
|
+
const agent = new BuiltInAgent({ model: "openai:gpt-4o-mini" });
|
|
95
|
+
|
|
96
|
+
vi.mocked(streamText).mockReturnValue(
|
|
97
|
+
mockStreamTextResponse([
|
|
98
|
+
{ type: "reasoning-start", id: "reasoning-0" },
|
|
99
|
+
{ type: "reasoning-delta", text: "Thinking..." },
|
|
100
|
+
{ type: "reasoning-end" },
|
|
101
|
+
{ type: "text-start", id: "txt-0" },
|
|
102
|
+
textDelta("Answer"),
|
|
103
|
+
finish(),
|
|
104
|
+
]) as any,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
const input: RunAgentInput = {
|
|
108
|
+
threadId: "thread-2",
|
|
109
|
+
runId: "run-2",
|
|
110
|
+
messages: [{ id: "1", role: "user", content: "Hi" }],
|
|
111
|
+
tools: [],
|
|
112
|
+
context: [],
|
|
113
|
+
state: {},
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const events = await collectEvents(agent["run"](input));
|
|
117
|
+
|
|
118
|
+
// Find REASONING_START event
|
|
119
|
+
const reasoningStarts = events.filter(
|
|
120
|
+
(e) => e.type === EventType.REASONING_START,
|
|
121
|
+
);
|
|
122
|
+
expect(reasoningStarts.length).toBeGreaterThan(0);
|
|
123
|
+
const reasoningId = (reasoningStarts[0] as any).messageId;
|
|
124
|
+
|
|
125
|
+
// Should NOT be "reasoning-0"
|
|
126
|
+
expect(reasoningId).not.toBe("reasoning-0");
|
|
127
|
+
expect(reasoningId).toMatch(
|
|
128
|
+
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,
|
|
129
|
+
);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('should replace providedId "msg-0" with a UUID', async () => {
|
|
133
|
+
const agent = new BuiltInAgent({ model: "openai:gpt-4o-mini" });
|
|
134
|
+
|
|
135
|
+
vi.mocked(streamText).mockReturnValue(
|
|
136
|
+
mockStreamTextResponse([
|
|
137
|
+
{ type: "text-start", id: "msg-0" },
|
|
138
|
+
textDelta("Hello"),
|
|
139
|
+
finish(),
|
|
140
|
+
]) as any,
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
const input: RunAgentInput = {
|
|
144
|
+
threadId: "thread-3",
|
|
145
|
+
runId: "run-3",
|
|
146
|
+
messages: [{ id: "1", role: "user", content: "Hi" }],
|
|
147
|
+
tools: [],
|
|
148
|
+
context: [],
|
|
149
|
+
state: {},
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const events = await collectEvents(agent["run"](input));
|
|
153
|
+
|
|
154
|
+
const textChunks = events.filter(
|
|
155
|
+
(e) => e.type === EventType.TEXT_MESSAGE_CHUNK,
|
|
156
|
+
);
|
|
157
|
+
expect(textChunks.length).toBeGreaterThan(0);
|
|
158
|
+
const messageId = (textChunks[0] as any).messageId;
|
|
159
|
+
|
|
160
|
+
expect(messageId).not.toBe("msg-0");
|
|
161
|
+
expect(messageId).toMatch(
|
|
162
|
+
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,
|
|
163
|
+
);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it("should preserve legitimate provider IDs", async () => {
|
|
167
|
+
const agent = new BuiltInAgent({ model: "openai:gpt-4o-mini" });
|
|
168
|
+
|
|
169
|
+
vi.mocked(streamText).mockReturnValue(
|
|
170
|
+
mockStreamTextResponse([
|
|
171
|
+
{ type: "text-start", id: "custom-msg-id-123" },
|
|
172
|
+
textDelta("Hello"),
|
|
173
|
+
finish(),
|
|
174
|
+
]) as any,
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
const input: RunAgentInput = {
|
|
178
|
+
threadId: "thread-4",
|
|
179
|
+
runId: "run-4",
|
|
180
|
+
messages: [{ id: "1", role: "user", content: "Hi" }],
|
|
181
|
+
tools: [],
|
|
182
|
+
context: [],
|
|
183
|
+
state: {},
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const events = await collectEvents(agent["run"](input));
|
|
187
|
+
|
|
188
|
+
const textChunks = events.filter(
|
|
189
|
+
(e) => e.type === EventType.TEXT_MESSAGE_CHUNK,
|
|
190
|
+
);
|
|
191
|
+
expect(textChunks.length).toBeGreaterThan(0);
|
|
192
|
+
// Legitimate IDs should be preserved
|
|
193
|
+
expect((textChunks[0] as any).messageId).toBe("custom-msg-id-123");
|
|
194
|
+
});
|
|
195
|
+
});
|
package/src/agent/index.ts
CHANGED
|
@@ -1267,13 +1267,17 @@ export class BuiltInAgent extends AbstractAgent {
|
|
|
1267
1267
|
break;
|
|
1268
1268
|
}
|
|
1269
1269
|
case "reasoning-start": {
|
|
1270
|
-
// Use SDK-provided id, or generate a fresh UUID if id is falsy
|
|
1271
|
-
//
|
|
1270
|
+
// Use SDK-provided id, or generate a fresh UUID if the id is falsy,
|
|
1271
|
+
// "0", or matches the non-unique pattern emitted by @ai-sdk/openai-compatible
|
|
1272
|
+
// (e.g. "txt-0", "reasoning-0", "msg-0").
|
|
1272
1273
|
const providedId = "id" in part ? part.id : undefined;
|
|
1273
|
-
|
|
1274
|
-
providedId
|
|
1275
|
-
|
|
1276
|
-
|
|
1274
|
+
const isNonUniqueId =
|
|
1275
|
+
!providedId ||
|
|
1276
|
+
providedId === "0" ||
|
|
1277
|
+
/^(txt|reasoning|msg)-0$/.test(providedId);
|
|
1278
|
+
reasoningMessageId = isNonUniqueId
|
|
1279
|
+
? randomUUID()
|
|
1280
|
+
: (providedId as typeof reasoningMessageId);
|
|
1277
1281
|
const reasoningStartEvent: ReasoningStartEvent = {
|
|
1278
1282
|
type: EventType.REASONING_START,
|
|
1279
1283
|
messageId: reasoningMessageId,
|
|
@@ -1341,12 +1345,16 @@ export class BuiltInAgent extends AbstractAgent {
|
|
|
1341
1345
|
|
|
1342
1346
|
case "text-start": {
|
|
1343
1347
|
// New text message starting - use the SDK-provided id
|
|
1344
|
-
// Use randomUUID() if part.id is falsy
|
|
1348
|
+
// Use randomUUID() if part.id is falsy, "0", or matches the non-unique
|
|
1349
|
+
// pattern emitted by @ai-sdk/openai-compatible (e.g. "txt-0", "msg-0").
|
|
1345
1350
|
const providedId = "id" in part ? part.id : undefined;
|
|
1346
|
-
|
|
1347
|
-
providedId
|
|
1348
|
-
|
|
1349
|
-
|
|
1351
|
+
const isNonUniqueTextId =
|
|
1352
|
+
!providedId ||
|
|
1353
|
+
providedId === "0" ||
|
|
1354
|
+
/^(txt|reasoning|msg)-0$/.test(providedId);
|
|
1355
|
+
messageId = isNonUniqueTextId
|
|
1356
|
+
? randomUUID()
|
|
1357
|
+
: (providedId as typeof messageId);
|
|
1350
1358
|
break;
|
|
1351
1359
|
}
|
|
1352
1360
|
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { RemoteLangGraphEventSource } from "../event-source";
|
|
2
|
+
import { LangGraphEventTypes } from "../events";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Access private methods for testing via a helper.
|
|
6
|
+
* These are pure functions that extract data from LangGraph events.
|
|
7
|
+
*/
|
|
8
|
+
function getSource() {
|
|
9
|
+
return new RemoteLangGraphEventSource();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Helper to call private methods. Returns `any` — type safety is traded for
|
|
13
|
+
// access to private implementation details that have no public test surface.
|
|
14
|
+
function callPrivate(
|
|
15
|
+
source: RemoteLangGraphEventSource,
|
|
16
|
+
method: string,
|
|
17
|
+
...args: any[]
|
|
18
|
+
) {
|
|
19
|
+
return (source as any)[method](...args);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe("shouldEmitToolCall", () => {
|
|
23
|
+
const source = getSource();
|
|
24
|
+
|
|
25
|
+
it("returns true when shouldEmitToolCalls is true (boolean)", () => {
|
|
26
|
+
expect(callPrivate(source, "shouldEmitToolCall", true, "anyTool")).toBe(
|
|
27
|
+
true,
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("returns false when shouldEmitToolCalls is false (boolean)", () => {
|
|
32
|
+
expect(callPrivate(source, "shouldEmitToolCall", false, "anyTool")).toBe(
|
|
33
|
+
false,
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("returns true when tool name matches string", () => {
|
|
38
|
+
expect(
|
|
39
|
+
callPrivate(source, "shouldEmitToolCall", "SearchTool", "SearchTool"),
|
|
40
|
+
).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("returns false when tool name does not match string", () => {
|
|
44
|
+
expect(
|
|
45
|
+
callPrivate(source, "shouldEmitToolCall", "SearchTool", "OtherTool"),
|
|
46
|
+
).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("returns true when tool name is in array", () => {
|
|
50
|
+
expect(
|
|
51
|
+
callPrivate(
|
|
52
|
+
source,
|
|
53
|
+
"shouldEmitToolCall",
|
|
54
|
+
["SearchTool", "FetchTool"],
|
|
55
|
+
"FetchTool",
|
|
56
|
+
),
|
|
57
|
+
).toBe(true);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("returns false when tool name is not in array", () => {
|
|
61
|
+
expect(
|
|
62
|
+
callPrivate(
|
|
63
|
+
source,
|
|
64
|
+
"shouldEmitToolCall",
|
|
65
|
+
["SearchTool", "FetchTool"],
|
|
66
|
+
"OtherTool",
|
|
67
|
+
),
|
|
68
|
+
).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
describe("getCurrentMessageId", () => {
|
|
73
|
+
const source = getSource();
|
|
74
|
+
|
|
75
|
+
it("extracts id from standard kwargs layout", () => {
|
|
76
|
+
const event = {
|
|
77
|
+
event: LangGraphEventTypes.OnChatModelStream,
|
|
78
|
+
data: { chunk: { kwargs: { id: "msg-std-123" } } },
|
|
79
|
+
};
|
|
80
|
+
expect(callPrivate(source, "getCurrentMessageId", event)).toBe(
|
|
81
|
+
"msg-std-123",
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("extracts id from LangGraph Platform layout (no kwargs)", () => {
|
|
86
|
+
const event = {
|
|
87
|
+
event: LangGraphEventTypes.OnChatModelStream,
|
|
88
|
+
data: { chunk: { id: "msg-plat-456" } },
|
|
89
|
+
};
|
|
90
|
+
expect(callPrivate(source, "getCurrentMessageId", event)).toBe(
|
|
91
|
+
"msg-plat-456",
|
|
92
|
+
);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("prefers kwargs layout when both present", () => {
|
|
96
|
+
const event = {
|
|
97
|
+
event: LangGraphEventTypes.OnChatModelStream,
|
|
98
|
+
data: { chunk: { kwargs: { id: "kwargs-id" }, id: "direct-id" } },
|
|
99
|
+
};
|
|
100
|
+
expect(callPrivate(source, "getCurrentMessageId", event)).toBe("kwargs-id");
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("returns undefined when neither layout is present", () => {
|
|
104
|
+
const event = {
|
|
105
|
+
event: LangGraphEventTypes.OnChatModelStream,
|
|
106
|
+
data: { chunk: {} },
|
|
107
|
+
};
|
|
108
|
+
expect(callPrivate(source, "getCurrentMessageId", event)).toBeUndefined();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("handles missing data gracefully", () => {
|
|
112
|
+
const event = { event: LangGraphEventTypes.OnChatModelStream };
|
|
113
|
+
expect(callPrivate(source, "getCurrentMessageId", event)).toBeUndefined();
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe("getCurrentToolCallChunks", () => {
|
|
118
|
+
const source = getSource();
|
|
119
|
+
|
|
120
|
+
it("extracts chunks from standard kwargs layout", () => {
|
|
121
|
+
const chunks = [{ name: "tool1", args: "{}", id: "tc-1", index: 0 }];
|
|
122
|
+
const event = {
|
|
123
|
+
event: LangGraphEventTypes.OnChatModelStream,
|
|
124
|
+
data: { chunk: { kwargs: { tool_call_chunks: chunks } } },
|
|
125
|
+
};
|
|
126
|
+
expect(callPrivate(source, "getCurrentToolCallChunks", event)).toEqual(
|
|
127
|
+
chunks,
|
|
128
|
+
);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("extracts chunks from LangGraph Platform layout", () => {
|
|
132
|
+
const chunks = [{ name: "tool2", args: "{}", id: "tc-2", index: 0 }];
|
|
133
|
+
const event = {
|
|
134
|
+
event: LangGraphEventTypes.OnChatModelStream,
|
|
135
|
+
data: { chunk: { tool_call_chunks: chunks } },
|
|
136
|
+
};
|
|
137
|
+
expect(callPrivate(source, "getCurrentToolCallChunks", event)).toEqual(
|
|
138
|
+
chunks,
|
|
139
|
+
);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("returns undefined when no chunks present", () => {
|
|
143
|
+
const event = {
|
|
144
|
+
event: LangGraphEventTypes.OnChatModelStream,
|
|
145
|
+
data: { chunk: {} },
|
|
146
|
+
};
|
|
147
|
+
expect(
|
|
148
|
+
callPrivate(source, "getCurrentToolCallChunks", event),
|
|
149
|
+
).toBeUndefined();
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe("getResponseMetadata", () => {
|
|
154
|
+
const source = getSource();
|
|
155
|
+
|
|
156
|
+
it("extracts metadata from standard kwargs layout", () => {
|
|
157
|
+
const meta = { finish_reason: "stop" };
|
|
158
|
+
const event = {
|
|
159
|
+
event: LangGraphEventTypes.OnChatModelStream,
|
|
160
|
+
data: { chunk: { kwargs: { response_metadata: meta } } },
|
|
161
|
+
};
|
|
162
|
+
expect(callPrivate(source, "getResponseMetadata", event)).toEqual(meta);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it("extracts metadata from LangGraph Platform layout", () => {
|
|
166
|
+
const meta = { finish_reason: "tool_calls" };
|
|
167
|
+
const event = {
|
|
168
|
+
event: LangGraphEventTypes.OnChatModelStream,
|
|
169
|
+
data: { chunk: { response_metadata: meta } },
|
|
170
|
+
};
|
|
171
|
+
expect(callPrivate(source, "getResponseMetadata", event)).toEqual(meta);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it("returns undefined when no metadata present", () => {
|
|
175
|
+
const event = {
|
|
176
|
+
event: LangGraphEventTypes.OnChatModelStream,
|
|
177
|
+
data: { chunk: {} },
|
|
178
|
+
};
|
|
179
|
+
expect(callPrivate(source, "getResponseMetadata", event)).toBeUndefined();
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
describe("getCurrentContent", () => {
|
|
184
|
+
const source = getSource();
|
|
185
|
+
|
|
186
|
+
it("extracts string content from kwargs layout", () => {
|
|
187
|
+
const event = {
|
|
188
|
+
event: LangGraphEventTypes.OnChatModelStream,
|
|
189
|
+
data: { chunk: { kwargs: { content: "hello world" } } },
|
|
190
|
+
};
|
|
191
|
+
expect(callPrivate(source, "getCurrentContent", event)).toBe("hello world");
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it("extracts string content from Platform layout", () => {
|
|
195
|
+
const event = {
|
|
196
|
+
event: LangGraphEventTypes.OnChatModelStream,
|
|
197
|
+
data: { chunk: { content: "platform content" } },
|
|
198
|
+
};
|
|
199
|
+
expect(callPrivate(source, "getCurrentContent", event)).toBe(
|
|
200
|
+
"platform content",
|
|
201
|
+
);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it("extracts text from array content (Anthropic format)", () => {
|
|
205
|
+
const event = {
|
|
206
|
+
event: LangGraphEventTypes.OnChatModelStream,
|
|
207
|
+
data: {
|
|
208
|
+
chunk: {
|
|
209
|
+
kwargs: {
|
|
210
|
+
content: [{ text: "array text", type: "text", index: 0 }],
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
expect(callPrivate(source, "getCurrentContent", event)).toBe("array text");
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it("returns null when no content and no tool call chunks", () => {
|
|
219
|
+
const event = {
|
|
220
|
+
event: LangGraphEventTypes.OnChatModelStream,
|
|
221
|
+
data: { chunk: { kwargs: {} } },
|
|
222
|
+
};
|
|
223
|
+
expect(callPrivate(source, "getCurrentContent", event)).toBeNull();
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it("falls back to tool_call_chunks args when no content", () => {
|
|
227
|
+
const event = {
|
|
228
|
+
event: LangGraphEventTypes.OnChatModelStream,
|
|
229
|
+
data: {
|
|
230
|
+
chunk: {
|
|
231
|
+
kwargs: {
|
|
232
|
+
content: "",
|
|
233
|
+
tool_call_chunks: [{ args: '{"key":"val"}' }],
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
expect(callPrivate(source, "getCurrentContent", event)).toBe(
|
|
239
|
+
'{"key":"val"}',
|
|
240
|
+
);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it("handles missing data gracefully", () => {
|
|
244
|
+
const event = { event: LangGraphEventTypes.OnChatModelStream };
|
|
245
|
+
expect(callPrivate(source, "getCurrentContent", event)).toBeNull();
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it("returns empty string when content is empty string", () => {
|
|
249
|
+
const event = {
|
|
250
|
+
event: LangGraphEventTypes.OnChatModelStream,
|
|
251
|
+
data: { chunk: { kwargs: { content: "" } } },
|
|
252
|
+
};
|
|
253
|
+
// Empty string is a valid string, so typeof === "string" returns it as-is
|
|
254
|
+
expect(callPrivate(source, "getCurrentContent", event)).toBe("");
|
|
255
|
+
});
|
|
256
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { resolveMessageId } from "../resolve-message-id";
|
|
3
|
+
|
|
4
|
+
describe("resolveMessageId (#2118)", () => {
|
|
5
|
+
it("preserves a provided non-empty id verbatim", () => {
|
|
6
|
+
expect(resolveMessageId("msg-123")).toBe("msg-123");
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it.each(["", null, undefined] as const)(
|
|
10
|
+
"falls back to a generated id when the event id is %p",
|
|
11
|
+
(input) => {
|
|
12
|
+
const id = resolveMessageId(input);
|
|
13
|
+
// randomId() always produces the "ck-<uuid>" shape; the important
|
|
14
|
+
// contract for #2118 is that the returned value is a non-empty string,
|
|
15
|
+
// never null/undefined.
|
|
16
|
+
expect(id).toMatch(/^ck-[0-9a-f-]{36}$/);
|
|
17
|
+
},
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
it("generates a fresh id on each fallback call", () => {
|
|
21
|
+
const a = resolveMessageId(undefined);
|
|
22
|
+
const b = resolveMessageId(undefined);
|
|
23
|
+
expect(a).not.toBe(b);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -58,6 +58,7 @@ import {
|
|
|
58
58
|
} from "../types/converted";
|
|
59
59
|
import telemetry from "../../lib/telemetry-client";
|
|
60
60
|
import { randomId } from "@copilotkit/shared";
|
|
61
|
+
import { resolveMessageId } from "./resolve-message-id";
|
|
61
62
|
import { AgentsResponse } from "../types/agents-response.type";
|
|
62
63
|
import { LangGraphEventTypes } from "../../agents/langgraph/events";
|
|
63
64
|
import {
|
|
@@ -488,7 +489,7 @@ export class CopilotResolver {
|
|
|
488
489
|
typeof MessageStatusUnion
|
|
489
490
|
>();
|
|
490
491
|
|
|
491
|
-
const messageId = event.messageId;
|
|
492
|
+
const messageId = resolveMessageId(event.messageId);
|
|
492
493
|
// push the new message
|
|
493
494
|
pushMessage({
|
|
494
495
|
id: messageId,
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { randomId } from "@copilotkit/shared";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Resolve the id to use for a streamed TextMessageOutput.
|
|
5
|
+
*
|
|
6
|
+
* Upstream events occasionally arrive with `messageId` missing, null, or an
|
|
7
|
+
* empty string. We fall back to a freshly generated id in those cases so the
|
|
8
|
+
* resulting output never surfaces a null id to the GraphQL client (#2118).
|
|
9
|
+
*/
|
|
10
|
+
export function resolveMessageId(
|
|
11
|
+
eventMessageId: string | null | undefined,
|
|
12
|
+
): string {
|
|
13
|
+
return eventMessageId || randomId();
|
|
14
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Test for #2986: instanceof Request fails with @hono/node-server polyfill
|
|
5
|
+
*
|
|
6
|
+
* When Hono polyfills the Request class, `instanceof Request` fails because
|
|
7
|
+
* the polyfilled Request has a different prototype. We need duck-type checking.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Simulates a polyfilled Request object that does NOT pass instanceof Request
|
|
11
|
+
function createPolyfillRequest(url: string, method: string = "GET"): object {
|
|
12
|
+
return {
|
|
13
|
+
url,
|
|
14
|
+
method,
|
|
15
|
+
headers: new Headers({ "content-type": "application/json" }),
|
|
16
|
+
body: null,
|
|
17
|
+
clone: () => createPolyfillRequest(url, method),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// This is the duck-type check that should replace instanceof
|
|
22
|
+
function isRequestLike(obj: unknown): obj is Request {
|
|
23
|
+
return (
|
|
24
|
+
typeof obj === "object" &&
|
|
25
|
+
obj !== null &&
|
|
26
|
+
"url" in obj &&
|
|
27
|
+
"method" in obj &&
|
|
28
|
+
"headers" in obj &&
|
|
29
|
+
typeof (obj as any).url === "string" &&
|
|
30
|
+
typeof (obj as any).method === "string"
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
describe("Request duck-type detection (#2986)", () => {
|
|
35
|
+
it("should detect a native Request object", () => {
|
|
36
|
+
const req = new Request("http://localhost:3000/api/copilotkit", {
|
|
37
|
+
method: "POST",
|
|
38
|
+
});
|
|
39
|
+
expect(isRequestLike(req)).toBe(true);
|
|
40
|
+
expect(req instanceof Request).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should detect a polyfilled Request object that fails instanceof", () => {
|
|
44
|
+
const polyfilled = createPolyfillRequest(
|
|
45
|
+
"http://localhost:3000/api/copilotkit",
|
|
46
|
+
"POST",
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
// instanceof fails for polyfilled objects
|
|
50
|
+
expect(polyfilled instanceof Request).toBe(false);
|
|
51
|
+
|
|
52
|
+
// But duck-type check succeeds
|
|
53
|
+
expect(isRequestLike(polyfilled)).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("should NOT match null or undefined", () => {
|
|
57
|
+
expect(isRequestLike(null)).toBe(false);
|
|
58
|
+
expect(isRequestLike(undefined)).toBe(false);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("should NOT match an object missing required properties", () => {
|
|
62
|
+
expect(isRequestLike({ url: "http://test.com" })).toBe(false);
|
|
63
|
+
expect(isRequestLike({ method: "GET" })).toBe(false);
|
|
64
|
+
expect(isRequestLike({})).toBe(false);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -158,11 +158,25 @@ export function copilotRuntimeNodeHttpEndpoint(
|
|
|
158
158
|
}
|
|
159
159
|
};
|
|
160
160
|
|
|
161
|
+
// Duck-type check for Request-like objects (handles polyfilled Request from @hono/node-server)
|
|
162
|
+
function isRequestLike(obj: unknown): obj is Request {
|
|
163
|
+
return (
|
|
164
|
+
obj instanceof Request ||
|
|
165
|
+
(typeof obj === "object" &&
|
|
166
|
+
obj !== null &&
|
|
167
|
+
"url" in obj &&
|
|
168
|
+
"method" in obj &&
|
|
169
|
+
"headers" in obj &&
|
|
170
|
+
typeof (obj as any).url === "string" &&
|
|
171
|
+
typeof (obj as any).method === "string")
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
161
175
|
return function (
|
|
162
176
|
reqOrRequest: IncomingMessage | Request,
|
|
163
177
|
res?: ServerResponse,
|
|
164
178
|
): Promise<void> | Promise<Response> | Response {
|
|
165
|
-
if (reqOrRequest
|
|
179
|
+
if (isRequestLike(reqOrRequest) && !res) {
|
|
166
180
|
return honoApp.fetch(reqOrRequest as Request);
|
|
167
181
|
}
|
|
168
182
|
if (!res) {
|