@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
|
@@ -85,30 +85,65 @@ export function extractParametersFromSchema(
|
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
// Handle enums
|
|
88
|
+
// Handle enums — preserve as structured data for Zod conversion
|
|
89
|
+
let enumValues: string[] | undefined;
|
|
89
90
|
if (paramDef.enum && Array.isArray(paramDef.enum)) {
|
|
90
|
-
|
|
91
|
+
enumValues = paramDef.enum.map(String);
|
|
92
|
+
const enumDisplay = enumValues.join(" | ");
|
|
91
93
|
description =
|
|
92
94
|
description +
|
|
93
95
|
(description ? " " : "") +
|
|
94
|
-
`Allowed values: ${
|
|
96
|
+
`Allowed values: ${enumDisplay}`;
|
|
95
97
|
}
|
|
96
98
|
|
|
97
|
-
// Handle objects with properties
|
|
99
|
+
// Handle objects with properties — recurse to preserve nested structure
|
|
100
|
+
let attributes: Parameter[] | undefined;
|
|
98
101
|
if (type === "object" && paramDef.properties) {
|
|
99
102
|
const objectProperties = Object.keys(paramDef.properties).join(", ");
|
|
100
103
|
description =
|
|
101
104
|
description +
|
|
102
105
|
(description ? " " : "") +
|
|
103
106
|
`Object with properties: ${objectProperties}`;
|
|
107
|
+
// Recursively extract nested parameters
|
|
108
|
+
attributes = extractParametersFromSchema({
|
|
109
|
+
parameters: {
|
|
110
|
+
properties: paramDef.properties,
|
|
111
|
+
required: paramDef.required || [],
|
|
112
|
+
},
|
|
113
|
+
});
|
|
104
114
|
}
|
|
105
115
|
|
|
106
|
-
|
|
116
|
+
// Handle object arrays — recurse into item schema
|
|
117
|
+
if (type === "array" && paramDef.items?.type === "object" && paramDef.items?.properties) {
|
|
118
|
+
attributes = extractParametersFromSchema({
|
|
119
|
+
parameters: {
|
|
120
|
+
properties: paramDef.items.properties,
|
|
121
|
+
required: paramDef.items.required || [],
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const param: any = {
|
|
107
127
|
name: paramName,
|
|
108
128
|
type: type,
|
|
109
129
|
description: description,
|
|
110
130
|
required: requiredParams.has(paramName),
|
|
111
|
-
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// Preserve enum values for string parameters
|
|
134
|
+
if (type === "string" && enumValues) {
|
|
135
|
+
param.enum = enumValues;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Preserve nested attributes for object and object[] types
|
|
139
|
+
if (attributes && attributes.length > 0) {
|
|
140
|
+
param.attributes = attributes;
|
|
141
|
+
if (type === "array") {
|
|
142
|
+
param.type = "object[]";
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
parameters.push(param);
|
|
112
147
|
}
|
|
113
148
|
}
|
|
114
149
|
|
|
@@ -7,6 +7,8 @@ export const RETRY_CONFIG = {
|
|
|
7
7
|
maxDelayMs: 5000,
|
|
8
8
|
// HTTP status codes that should be retried
|
|
9
9
|
retryableStatusCodes: [502, 503, 504, 408, 429],
|
|
10
|
+
// Maximum Retry-After value (in seconds) we're willing to honor
|
|
11
|
+
maxRetryAfterSeconds: 60,
|
|
10
12
|
// Network error patterns that should be retried
|
|
11
13
|
retryableErrorMessages: [
|
|
12
14
|
"fetch failed",
|
|
@@ -44,6 +46,28 @@ export function sleep(ms: number): Promise<void> {
|
|
|
44
46
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
45
47
|
}
|
|
46
48
|
|
|
49
|
+
// Parse the Retry-After header value into milliseconds.
|
|
50
|
+
// Returns undefined if the header is missing or unparseable.
|
|
51
|
+
export function parseRetryAfter(response: Response): number | undefined {
|
|
52
|
+
const retryAfter = response.headers.get("Retry-After");
|
|
53
|
+
if (!retryAfter) return undefined;
|
|
54
|
+
|
|
55
|
+
// Try as seconds (integer)
|
|
56
|
+
const seconds = Number(retryAfter);
|
|
57
|
+
if (!Number.isNaN(seconds) && seconds >= 0) {
|
|
58
|
+
return seconds * 1000;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Try as HTTP-date
|
|
62
|
+
const date = Date.parse(retryAfter);
|
|
63
|
+
if (!Number.isNaN(date)) {
|
|
64
|
+
const delayMs = date - Date.now();
|
|
65
|
+
return delayMs > 0 ? delayMs : 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
|
|
47
71
|
// Calculate exponential backoff delay
|
|
48
72
|
export function calculateDelay(attempt: number): number {
|
|
49
73
|
const delay = RETRY_CONFIG.baseDelayMs * Math.pow(2, attempt);
|
|
@@ -67,7 +91,23 @@ export async function fetchWithRetry(
|
|
|
67
91
|
isRetryableError(null, response) &&
|
|
68
92
|
attempt < RETRY_CONFIG.maxRetries
|
|
69
93
|
) {
|
|
70
|
-
|
|
94
|
+
let delay = calculateDelay(attempt);
|
|
95
|
+
|
|
96
|
+
// Honor Retry-After header on 429 responses
|
|
97
|
+
if (response.status === 429) {
|
|
98
|
+
const retryAfterMs = parseRetryAfter(response);
|
|
99
|
+
if (retryAfterMs !== undefined) {
|
|
100
|
+
const maxMs = RETRY_CONFIG.maxRetryAfterSeconds * 1000;
|
|
101
|
+
if (retryAfterMs > maxMs) {
|
|
102
|
+
throw new Error(
|
|
103
|
+
`Server requested Retry-After of ${Math.ceil(retryAfterMs / 1000)}s ` +
|
|
104
|
+
`which exceeds the maximum of ${RETRY_CONFIG.maxRetryAfterSeconds}s`,
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
delay = retryAfterMs;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
71
111
|
logger?.warn(
|
|
72
112
|
`Request to ${url} failed with status ${response.status}. ` +
|
|
73
113
|
`Retrying attempt ${attempt + 1}/${RETRY_CONFIG.maxRetries + 1} in ${delay}ms.`,
|
|
@@ -70,12 +70,19 @@ export interface AnthropicAdapterParams {
|
|
|
70
70
|
* See: https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching
|
|
71
71
|
*/
|
|
72
72
|
promptCaching?: AnthropicPromptCachingConfig;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Optional maximum input token limit. Overrides the default limit
|
|
76
|
+
* used when trimming messages to fit the context window.
|
|
77
|
+
*/
|
|
78
|
+
maxInputTokens?: number;
|
|
73
79
|
}
|
|
74
80
|
|
|
75
81
|
export class AnthropicAdapter implements CopilotServiceAdapter {
|
|
76
82
|
public model: string = DEFAULT_MODEL;
|
|
77
83
|
public provider = "anthropic";
|
|
78
84
|
private promptCaching: AnthropicPromptCachingConfig;
|
|
85
|
+
private maxInputTokens?: number;
|
|
79
86
|
|
|
80
87
|
private _anthropic: Anthropic;
|
|
81
88
|
public get anthropic(): Anthropic {
|
|
@@ -94,6 +101,7 @@ export class AnthropicAdapter implements CopilotServiceAdapter {
|
|
|
94
101
|
this.model = params.model;
|
|
95
102
|
}
|
|
96
103
|
this.promptCaching = params?.promptCaching || { enabled: false };
|
|
104
|
+
this.maxInputTokens = params?.maxInputTokens;
|
|
97
105
|
}
|
|
98
106
|
|
|
99
107
|
getLanguageModel(): LanguageModel {
|
|
@@ -244,6 +252,7 @@ export class AnthropicAdapter implements CopilotServiceAdapter {
|
|
|
244
252
|
forwardedParameters,
|
|
245
253
|
} = request;
|
|
246
254
|
const tools = actions.map(convertActionInputToAnthropicTool);
|
|
255
|
+
const knownActionNames = new Set(actions.map((a) => a.name));
|
|
247
256
|
|
|
248
257
|
const messages = [...rawMessages];
|
|
249
258
|
|
|
@@ -322,6 +331,7 @@ export class AnthropicAdapter implements CopilotServiceAdapter {
|
|
|
322
331
|
anthropicMessages,
|
|
323
332
|
tools,
|
|
324
333
|
model,
|
|
334
|
+
this.maxInputTokens,
|
|
325
335
|
);
|
|
326
336
|
|
|
327
337
|
// Apply prompt caching if enabled
|
|
@@ -350,7 +360,7 @@ export class AnthropicAdapter implements CopilotServiceAdapter {
|
|
|
350
360
|
system: cachedSystemPrompt,
|
|
351
361
|
model: this.model,
|
|
352
362
|
messages: cachedMessages,
|
|
353
|
-
max_tokens: forwardedParameters?.maxTokens ||
|
|
363
|
+
max_tokens: forwardedParameters?.maxTokens || 4096,
|
|
354
364
|
...(forwardedParameters?.temperature
|
|
355
365
|
? { temperature: forwardedParameters.temperature }
|
|
356
366
|
: {}),
|
|
@@ -375,12 +385,18 @@ export class AnthropicAdapter implements CopilotServiceAdapter {
|
|
|
375
385
|
if (chunk.type === "message_start") {
|
|
376
386
|
currentMessageId = chunk.message.id;
|
|
377
387
|
} else if (chunk.type === "content_block_start") {
|
|
378
|
-
hasReceivedContent = true;
|
|
379
388
|
if (chunk.content_block.type === "text") {
|
|
389
|
+
hasReceivedContent = true;
|
|
380
390
|
didOutputText = false;
|
|
381
391
|
filterThinkingTextBuffer.reset();
|
|
382
392
|
mode = "message";
|
|
383
393
|
} else if (chunk.content_block.type === "tool_use") {
|
|
394
|
+
if (!knownActionNames.has(chunk.content_block.name)) {
|
|
395
|
+
// Unknown tool - skip execution to prevent crashes
|
|
396
|
+
mode = null;
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
hasReceivedContent = true;
|
|
384
400
|
currentToolCallId = chunk.content_block.id;
|
|
385
401
|
eventStream$.sendActionExecutionStart({
|
|
386
402
|
actionExecutionId: currentToolCallId,
|
|
@@ -390,6 +406,10 @@ export class AnthropicAdapter implements CopilotServiceAdapter {
|
|
|
390
406
|
mode = "function";
|
|
391
407
|
}
|
|
392
408
|
} else if (chunk.type === "content_block_delta") {
|
|
409
|
+
if (mode === null) {
|
|
410
|
+
// Skip deltas for unknown/skipped content blocks
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
393
413
|
if (chunk.delta.type === "text_delta") {
|
|
394
414
|
const text = filterThinkingTextBuffer.onTextChunk(
|
|
395
415
|
chunk.delta.text,
|
|
@@ -49,7 +49,66 @@ export function limitMessagesToTokenCount(
|
|
|
49
49
|
maxTokens -= numTokens;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
// Post-process: remove orphaned tool_result and tool_use blocks.
|
|
53
|
+
// Token trimming may have removed the assistant message containing tool_use
|
|
54
|
+
// while keeping the user message with tool_result (or vice versa),
|
|
55
|
+
// which Anthropic rejects.
|
|
56
|
+
|
|
57
|
+
// Collect all tool_use IDs from assistant messages
|
|
58
|
+
const toolUseIds = new Set<string>();
|
|
59
|
+
for (const msg of result) {
|
|
60
|
+
if (msg.role === "assistant" && Array.isArray(msg.content)) {
|
|
61
|
+
for (const block of msg.content) {
|
|
62
|
+
if (block.type === "tool_use") {
|
|
63
|
+
toolUseIds.add(block.id);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Collect all tool_result IDs from user messages
|
|
70
|
+
const toolResultIds = new Set<string>();
|
|
71
|
+
for (const msg of result) {
|
|
72
|
+
if (msg.role === "user" && Array.isArray(msg.content)) {
|
|
73
|
+
for (const block of msg.content) {
|
|
74
|
+
if (block.type === "tool_result") {
|
|
75
|
+
toolResultIds.add(block.tool_use_id);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Filter orphaned blocks without mutating the original messages
|
|
82
|
+
const filtered: any[] = [];
|
|
83
|
+
for (const msg of result) {
|
|
84
|
+
if (msg.role === "user" && Array.isArray(msg.content)) {
|
|
85
|
+
const remaining = msg.content.filter(
|
|
86
|
+
(block: any) =>
|
|
87
|
+
block.type !== "tool_result" || toolUseIds.has(block.tool_use_id),
|
|
88
|
+
);
|
|
89
|
+
if (remaining.length === 0) continue;
|
|
90
|
+
if (remaining.length !== msg.content.length) {
|
|
91
|
+
filtered.push({ ...msg, content: remaining });
|
|
92
|
+
} else {
|
|
93
|
+
filtered.push(msg);
|
|
94
|
+
}
|
|
95
|
+
} else if (msg.role === "assistant" && Array.isArray(msg.content)) {
|
|
96
|
+
const remaining = msg.content.filter(
|
|
97
|
+
(block: any) =>
|
|
98
|
+
block.type !== "tool_use" || toolResultIds.has(block.id),
|
|
99
|
+
);
|
|
100
|
+
if (remaining.length === 0) continue;
|
|
101
|
+
if (remaining.length !== msg.content.length) {
|
|
102
|
+
filtered.push({ ...msg, content: remaining });
|
|
103
|
+
} else {
|
|
104
|
+
filtered.push(msg);
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
filtered.push(msg);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return filtered;
|
|
53
112
|
}
|
|
54
113
|
|
|
55
114
|
const MAX_TOKENS = 128000;
|
|
@@ -269,7 +269,7 @@ export async function streamLangChainResponse({
|
|
|
269
269
|
});
|
|
270
270
|
} else if (content) {
|
|
271
271
|
mode = "message";
|
|
272
|
-
currentMessageId =
|
|
272
|
+
currentMessageId = randomId();
|
|
273
273
|
eventStream$.sendTextMessageStart({ messageId: currentMessageId });
|
|
274
274
|
}
|
|
275
275
|
}
|
|
@@ -97,6 +97,12 @@ export interface OpenAIAdapterParams {
|
|
|
97
97
|
* @default false
|
|
98
98
|
*/
|
|
99
99
|
keepSystemRole?: boolean;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Optional maximum input token limit. Overrides the default model-based limit
|
|
103
|
+
* used when trimming messages to fit the context window.
|
|
104
|
+
*/
|
|
105
|
+
maxInputTokens?: number;
|
|
100
106
|
}
|
|
101
107
|
|
|
102
108
|
export class OpenAIAdapter implements CopilotServiceAdapter {
|
|
@@ -106,6 +112,7 @@ export class OpenAIAdapter implements CopilotServiceAdapter {
|
|
|
106
112
|
private disableParallelToolCalls: boolean = false;
|
|
107
113
|
private _openai: OpenAI;
|
|
108
114
|
private keepSystemRole: boolean = false;
|
|
115
|
+
private maxInputTokens?: number;
|
|
109
116
|
|
|
110
117
|
public get openai(): OpenAI {
|
|
111
118
|
return this._openai;
|
|
@@ -125,6 +132,7 @@ export class OpenAIAdapter implements CopilotServiceAdapter {
|
|
|
125
132
|
}
|
|
126
133
|
this.disableParallelToolCalls = params?.disableParallelToolCalls || false;
|
|
127
134
|
this.keepSystemRole = params?.keepSystemRole ?? false;
|
|
135
|
+
this.maxInputTokens = params?.maxInputTokens;
|
|
128
136
|
}
|
|
129
137
|
|
|
130
138
|
getLanguageModel(): LanguageModel {
|
|
@@ -192,7 +200,12 @@ export class OpenAIAdapter implements CopilotServiceAdapter {
|
|
|
192
200
|
let openaiMessages = filteredMessages.map((m) =>
|
|
193
201
|
convertMessageToOpenAIMessage(m, { keepSystemRole: this.keepSystemRole }),
|
|
194
202
|
);
|
|
195
|
-
openaiMessages = limitMessagesToTokenCount(
|
|
203
|
+
openaiMessages = limitMessagesToTokenCount(
|
|
204
|
+
openaiMessages,
|
|
205
|
+
tools,
|
|
206
|
+
model,
|
|
207
|
+
this.maxInputTokens,
|
|
208
|
+
);
|
|
196
209
|
|
|
197
210
|
let toolChoice: any = forwardedParameters?.toolChoice;
|
|
198
211
|
if (forwardedParameters?.toolChoice === "function") {
|
|
@@ -135,6 +135,11 @@ describe("fetch-router", () => {
|
|
|
135
135
|
const result = matchRoute("/info", "/");
|
|
136
136
|
expect(result).toEqual({ method: "info" });
|
|
137
137
|
});
|
|
138
|
+
|
|
139
|
+
it("matches GET /cpk-debug-events", () => {
|
|
140
|
+
const result = matchRoute("/api/copilotkit/cpk-debug-events", basePath);
|
|
141
|
+
expect(result).toEqual({ method: "cpk-debug-events" });
|
|
142
|
+
});
|
|
138
143
|
});
|
|
139
144
|
|
|
140
145
|
describe("without basePath (suffix matching)", () => {
|
|
@@ -204,5 +209,22 @@ describe("fetch-router", () => {
|
|
|
204
209
|
const result = matchRoute("/api/v2/copilotkit/agent/a1/run");
|
|
205
210
|
expect(result).toEqual({ method: "agent/run", agentId: "a1" });
|
|
206
211
|
});
|
|
212
|
+
|
|
213
|
+
it("matches /cpk-debug-events suffix", () => {
|
|
214
|
+
const result = matchRoute("/api/copilotkit/cpk-debug-events");
|
|
215
|
+
expect(result).toEqual({ method: "cpk-debug-events" });
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it("matches bare /cpk-debug-events", () => {
|
|
219
|
+
const result = matchRoute("/cpk-debug-events");
|
|
220
|
+
expect(result).toEqual({ method: "cpk-debug-events" });
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
describe("cpk-debug-events route with basePath", () => {
|
|
225
|
+
it("matches /cpk-debug-events with /api basePath", () => {
|
|
226
|
+
const result = matchRoute("/api/cpk-debug-events", "/api");
|
|
227
|
+
expect(result).toEqual({ method: "cpk-debug-events" });
|
|
228
|
+
});
|
|
207
229
|
});
|
|
208
230
|
});
|
|
@@ -228,7 +228,9 @@ describe("handleConnectAgent", () => {
|
|
|
228
228
|
afterRequestMiddleware: undefined,
|
|
229
229
|
runner,
|
|
230
230
|
mode: "intelligence",
|
|
231
|
-
identifyUser: vi
|
|
231
|
+
identifyUser: vi
|
|
232
|
+
.fn()
|
|
233
|
+
.mockResolvedValue({ id: "user-1", name: "User One" }),
|
|
232
234
|
intelligence: platform,
|
|
233
235
|
} as unknown as CopilotRuntime;
|
|
234
236
|
};
|
|
@@ -262,6 +264,7 @@ describe("handleConnectAgent", () => {
|
|
|
262
264
|
expect(platform.ɵconnectThread).toHaveBeenCalledWith({
|
|
263
265
|
threadId: "thread-1",
|
|
264
266
|
userId: "user-1",
|
|
267
|
+
runId: "run-1",
|
|
265
268
|
lastSeenEventId: null,
|
|
266
269
|
});
|
|
267
270
|
});
|
|
@@ -271,7 +274,15 @@ describe("handleConnectAgent", () => {
|
|
|
271
274
|
ɵconnectThread: vi.fn().mockResolvedValue({
|
|
272
275
|
mode: "bootstrap",
|
|
273
276
|
latestEventId: "event-2",
|
|
274
|
-
events: [
|
|
277
|
+
events: [
|
|
278
|
+
{
|
|
279
|
+
type: "RUN_STARTED",
|
|
280
|
+
threadId: "thread-1",
|
|
281
|
+
run_id: "backend-run-1",
|
|
282
|
+
input: { messages: [] },
|
|
283
|
+
},
|
|
284
|
+
{ type: "RUN_FINISHED" },
|
|
285
|
+
],
|
|
275
286
|
}),
|
|
276
287
|
};
|
|
277
288
|
const runtime = createIntelligenceRuntime(platform);
|
|
@@ -287,7 +298,23 @@ describe("handleConnectAgent", () => {
|
|
|
287
298
|
expect(body).toEqual({
|
|
288
299
|
mode: "bootstrap",
|
|
289
300
|
latestEventId: "event-2",
|
|
290
|
-
events: [
|
|
301
|
+
events: [
|
|
302
|
+
{
|
|
303
|
+
type: "RUN_STARTED",
|
|
304
|
+
threadId: "thread-1",
|
|
305
|
+
runId: "run-1",
|
|
306
|
+
input: {
|
|
307
|
+
messages: [],
|
|
308
|
+
threadId: "thread-1",
|
|
309
|
+
runId: "run-1",
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
type: "RUN_FINISHED",
|
|
314
|
+
threadId: "thread-1",
|
|
315
|
+
runId: "run-1",
|
|
316
|
+
},
|
|
317
|
+
],
|
|
291
318
|
});
|
|
292
319
|
});
|
|
293
320
|
|
|
@@ -310,6 +337,7 @@ describe("handleConnectAgent", () => {
|
|
|
310
337
|
expect(platform.ɵconnectThread).toHaveBeenCalledWith({
|
|
311
338
|
threadId: "thread-1",
|
|
312
339
|
userId: "user-1",
|
|
340
|
+
runId: "run-1",
|
|
313
341
|
lastSeenEventId: null,
|
|
314
342
|
});
|
|
315
343
|
});
|
|
@@ -349,6 +377,7 @@ describe("handleConnectAgent", () => {
|
|
|
349
377
|
expect(platform.ɵconnectThread).toHaveBeenCalledWith({
|
|
350
378
|
threadId: "thread-1",
|
|
351
379
|
userId: "user-1",
|
|
380
|
+
runId: "run-1",
|
|
352
381
|
lastSeenEventId: "event-9",
|
|
353
382
|
});
|
|
354
383
|
});
|
|
@@ -357,7 +386,9 @@ describe("handleConnectAgent", () => {
|
|
|
357
386
|
const platform = {
|
|
358
387
|
ɵconnectThread: vi.fn().mockResolvedValue(null),
|
|
359
388
|
};
|
|
360
|
-
const identifyUser = vi
|
|
389
|
+
const identifyUser = vi
|
|
390
|
+
.fn()
|
|
391
|
+
.mockResolvedValue({ id: "resolved-user", name: "Resolved User" });
|
|
361
392
|
const runtime = createIntelligenceRuntime(platform);
|
|
362
393
|
runtime.identifyUser = identifyUser;
|
|
363
394
|
const request = createConnectRequest(
|
|
@@ -377,6 +408,7 @@ describe("handleConnectAgent", () => {
|
|
|
377
408
|
expect(platform.ɵconnectThread).toHaveBeenCalledWith({
|
|
378
409
|
threadId: "thread-1",
|
|
379
410
|
userId: "resolved-user",
|
|
411
|
+
runId: "run-1",
|
|
380
412
|
lastSeenEventId: "event-9",
|
|
381
413
|
});
|
|
382
414
|
});
|
|
@@ -386,7 +418,28 @@ describe("handleConnectAgent", () => {
|
|
|
386
418
|
ɵconnectThread: vi.fn(),
|
|
387
419
|
};
|
|
388
420
|
const runtime = createIntelligenceRuntime(platform);
|
|
389
|
-
runtime.identifyUser = vi
|
|
421
|
+
runtime.identifyUser = vi
|
|
422
|
+
.fn()
|
|
423
|
+
.mockResolvedValue({ id: "", name: "User" });
|
|
424
|
+
|
|
425
|
+
const response = await handleConnectAgent({
|
|
426
|
+
runtime,
|
|
427
|
+
request: createConnectRequest(),
|
|
428
|
+
agentId: "my-agent",
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
expect(response.status).toBe(400);
|
|
432
|
+
expect(platform.ɵconnectThread).not.toHaveBeenCalled();
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
it("returns 400 when identifyUser returns an invalid name", async () => {
|
|
436
|
+
const platform = {
|
|
437
|
+
ɵconnectThread: vi.fn(),
|
|
438
|
+
};
|
|
439
|
+
const runtime = createIntelligenceRuntime(platform);
|
|
440
|
+
runtime.identifyUser = vi
|
|
441
|
+
.fn()
|
|
442
|
+
.mockResolvedValue({ id: "user-1", name: "" });
|
|
390
443
|
|
|
391
444
|
const response = await handleConnectAgent({
|
|
392
445
|
runtime,
|
|
@@ -298,7 +298,9 @@ describe("handleRunAgent", () => {
|
|
|
298
298
|
generateThreadNames?: boolean;
|
|
299
299
|
identifyUser?: (
|
|
300
300
|
request: Request,
|
|
301
|
-
) =>
|
|
301
|
+
) =>
|
|
302
|
+
| { id: string; name: string }
|
|
303
|
+
| Promise<{ id: string; name: string }>;
|
|
302
304
|
},
|
|
303
305
|
) => {
|
|
304
306
|
const runner = Object.create(IntelligenceAgentRunner.prototype);
|
|
@@ -318,7 +320,8 @@ describe("handleRunAgent", () => {
|
|
|
318
320
|
generateThreadNames: options?.generateThreadNames ?? false,
|
|
319
321
|
intelligence: platform,
|
|
320
322
|
identifyUser:
|
|
321
|
-
options?.identifyUser ??
|
|
323
|
+
options?.identifyUser ??
|
|
324
|
+
vi.fn().mockResolvedValue({ id: "user-1", name: "User One" }),
|
|
322
325
|
} as unknown as CopilotRuntime;
|
|
323
326
|
};
|
|
324
327
|
|
|
@@ -395,7 +398,9 @@ describe("handleRunAgent", () => {
|
|
|
395
398
|
.fn()
|
|
396
399
|
.mockResolvedValue({ joinToken: "jt-123", joinCode: "jc-123" }),
|
|
397
400
|
};
|
|
398
|
-
const identifyUser = vi
|
|
401
|
+
const identifyUser = vi
|
|
402
|
+
.fn()
|
|
403
|
+
.mockResolvedValue({ id: "resolved-user", name: "Resolved User" });
|
|
399
404
|
const runtime = createIntelligenceRuntime(agent, platform, {
|
|
400
405
|
identifyUser,
|
|
401
406
|
});
|
|
@@ -870,7 +875,29 @@ describe("handleRunAgent", () => {
|
|
|
870
875
|
ɵacquireThreadLock: vi.fn(),
|
|
871
876
|
};
|
|
872
877
|
const runtime = createIntelligenceRuntime(agent, platform, {
|
|
873
|
-
identifyUser: vi.fn().mockResolvedValue({ id: "" }),
|
|
878
|
+
identifyUser: vi.fn().mockResolvedValue({ id: "", name: "User" }),
|
|
879
|
+
});
|
|
880
|
+
|
|
881
|
+
const response = await handleRunAgent({
|
|
882
|
+
runtime,
|
|
883
|
+
request: createRunRequest(),
|
|
884
|
+
agentId: "my-agent",
|
|
885
|
+
});
|
|
886
|
+
|
|
887
|
+
expect(response.status).toBe(400);
|
|
888
|
+
expect(platform.getOrCreateThread).not.toHaveBeenCalled();
|
|
889
|
+
expect(platform.ɵacquireThreadLock).not.toHaveBeenCalled();
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
it("returns 400 when identifyUser returns an invalid name", async () => {
|
|
893
|
+
const agent = createAgentForIntelligence();
|
|
894
|
+
const platform = {
|
|
895
|
+
getOrCreateThread: vi.fn(),
|
|
896
|
+
getThreadMessages: vi.fn(),
|
|
897
|
+
ɵacquireThreadLock: vi.fn(),
|
|
898
|
+
};
|
|
899
|
+
const runtime = createIntelligenceRuntime(agent, platform, {
|
|
900
|
+
identifyUser: vi.fn().mockResolvedValue({ id: "user-1", name: "" }),
|
|
874
901
|
});
|
|
875
902
|
|
|
876
903
|
const response = await handleRunAgent({
|
|
@@ -10,12 +10,13 @@ import {
|
|
|
10
10
|
import { CopilotRuntime } from "../core/runtime";
|
|
11
11
|
|
|
12
12
|
describe("thread handlers", () => {
|
|
13
|
-
const createIdentifyUser = () =>
|
|
13
|
+
const createIdentifyUser = () =>
|
|
14
|
+
vi.fn().mockResolvedValue({ id: "user-1", name: "User One" });
|
|
14
15
|
|
|
15
16
|
const createIntelligenceRuntime = (options?: {
|
|
16
17
|
identifyUser?: (
|
|
17
18
|
request: Request,
|
|
18
|
-
) => { id: string } | Promise<{ id: string }>;
|
|
19
|
+
) => { id: string; name: string } | Promise<{ id: string; name: string }>;
|
|
19
20
|
intelligence?: Record<string, unknown>;
|
|
20
21
|
}) =>
|
|
21
22
|
({
|
|
@@ -92,7 +93,25 @@ describe("thread handlers", () => {
|
|
|
92
93
|
};
|
|
93
94
|
const runtime = createIntelligenceRuntime({
|
|
94
95
|
intelligence,
|
|
95
|
-
identifyUser: vi.fn().mockResolvedValue({ id: "" }),
|
|
96
|
+
identifyUser: vi.fn().mockResolvedValue({ id: "", name: "User" }),
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const response = await handleListThreads({
|
|
100
|
+
runtime,
|
|
101
|
+
request: new Request("https://example.com/threads?agentId=agent-1"),
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
expect(response.status).toBe(400);
|
|
105
|
+
expect(intelligence.listThreads).not.toHaveBeenCalled();
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("returns 400 when identifyUser returns an invalid name for thread list", async () => {
|
|
109
|
+
const intelligence = {
|
|
110
|
+
listThreads: vi.fn(),
|
|
111
|
+
};
|
|
112
|
+
const runtime = createIntelligenceRuntime({
|
|
113
|
+
intelligence,
|
|
114
|
+
identifyUser: vi.fn().mockResolvedValue({ id: "user-1", name: "" }),
|
|
96
115
|
});
|
|
97
116
|
|
|
98
117
|
const response = await handleListThreads({
|
|
@@ -258,7 +277,50 @@ describe("thread handlers", () => {
|
|
|
258
277
|
};
|
|
259
278
|
const runtime = createIntelligenceRuntime({
|
|
260
279
|
intelligence,
|
|
261
|
-
identifyUser: vi.fn().mockResolvedValue({ id: "" }),
|
|
280
|
+
identifyUser: vi.fn().mockResolvedValue({ id: "", name: "User" }),
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
const updateResponse = await handleUpdateThread({
|
|
284
|
+
runtime,
|
|
285
|
+
request: createMutationRequest("/threads/thread-1", "PATCH", {
|
|
286
|
+
agentId: "agent-1",
|
|
287
|
+
}),
|
|
288
|
+
threadId: "thread-1",
|
|
289
|
+
});
|
|
290
|
+
expect(updateResponse.status).toBe(400);
|
|
291
|
+
|
|
292
|
+
const archiveResponse = await handleArchiveThread({
|
|
293
|
+
runtime,
|
|
294
|
+
request: createMutationRequest("/threads/thread-1/archive", "POST", {
|
|
295
|
+
agentId: "agent-1",
|
|
296
|
+
}),
|
|
297
|
+
threadId: "thread-1",
|
|
298
|
+
});
|
|
299
|
+
expect(archiveResponse.status).toBe(400);
|
|
300
|
+
|
|
301
|
+
const deleteResponse = await handleDeleteThread({
|
|
302
|
+
runtime,
|
|
303
|
+
request: createMutationRequest("/threads/thread-1", "DELETE", {
|
|
304
|
+
agentId: "agent-1",
|
|
305
|
+
}),
|
|
306
|
+
threadId: "thread-1",
|
|
307
|
+
});
|
|
308
|
+
expect(deleteResponse.status).toBe(400);
|
|
309
|
+
|
|
310
|
+
expect(intelligence.updateThread).not.toHaveBeenCalled();
|
|
311
|
+
expect(intelligence.archiveThread).not.toHaveBeenCalled();
|
|
312
|
+
expect(intelligence.deleteThread).not.toHaveBeenCalled();
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it("returns 400 when identifyUser returns an invalid name for thread mutations", async () => {
|
|
316
|
+
const intelligence = {
|
|
317
|
+
updateThread: vi.fn(),
|
|
318
|
+
archiveThread: vi.fn(),
|
|
319
|
+
deleteThread: vi.fn(),
|
|
320
|
+
};
|
|
321
|
+
const runtime = createIntelligenceRuntime({
|
|
322
|
+
intelligence,
|
|
323
|
+
identifyUser: vi.fn().mockResolvedValue({ id: "user-1", name: "" }),
|
|
262
324
|
});
|
|
263
325
|
|
|
264
326
|
const updateResponse = await handleUpdateThread({
|
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
|
|
11
11
|
import { multiEndpointSuite } from "./suites/multi-endpoint.suite";
|
|
12
12
|
import { singleEndpointSuite } from "./suites/single-endpoint.suite";
|
|
13
|
+
import {
|
|
14
|
+
debugEventsSuite,
|
|
15
|
+
debugEventsProductionGuardSuite,
|
|
16
|
+
} from "./suites/debug-events.suite";
|
|
13
17
|
|
|
14
18
|
// Server factories
|
|
15
19
|
import { createExpressMultiServer } from "./servers/express-multi";
|
|
@@ -37,3 +41,18 @@ singleEndpointSuite("Node", createNodeSingleServer);
|
|
|
37
41
|
singleEndpointSuite("Fetch", (opts) =>
|
|
38
42
|
Promise.resolve(createFetchDirectHandler("single-route", opts)),
|
|
39
43
|
);
|
|
44
|
+
|
|
45
|
+
// ─── Debug Events ───────────────────────────────────────────────────
|
|
46
|
+
|
|
47
|
+
debugEventsSuite("Express", createExpressMultiServer);
|
|
48
|
+
debugEventsSuite("Hono", createHonoMultiServer);
|
|
49
|
+
debugEventsSuite("Node", createNodeMultiServer);
|
|
50
|
+
debugEventsSuite("Fetch", (opts) =>
|
|
51
|
+
Promise.resolve(createFetchDirectHandler("multi-route", opts)),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
debugEventsProductionGuardSuite(
|
|
55
|
+
() => createFetchDirectHandler("multi-route"),
|
|
56
|
+
"http://localhost",
|
|
57
|
+
"/api/copilotkit",
|
|
58
|
+
);
|