@mcpstack/agent-sdk 1.0.0-pr.18.bbb0c016bc21.17.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -46
- package/dist/app/index.d.mts +9 -25
- package/dist/app/index.d.ts +9 -25
- package/dist/app/index.js +95 -403
- package/dist/app/index.js.map +1 -1
- package/dist/app/index.mjs +95 -403
- package/dist/app/index.mjs.map +1 -1
- package/dist/index.d.mts +9 -25
- package/dist/index.d.ts +9 -25
- package/dist/index.js +95 -403
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +95 -403
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.d.mts +9 -25
- package/dist/react/index.d.ts +9 -25
- package/dist/react/index.js +95 -403
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +95 -403
- package/dist/react/index.mjs.map +1 -1
- package/dist/react-embed/index.js +95 -403
- package/dist/react-embed/index.js.map +1 -1
- package/dist/react-embed/index.mjs +95 -403
- package/dist/react-embed/index.mjs.map +1 -1
- package/dist/react-native/index.d.mts +9 -25
- package/dist/react-native/index.d.ts +9 -25
- package/dist/react-native/index.js +95 -403
- package/dist/react-native/index.js.map +1 -1
- package/dist/react-native/index.mjs +95 -403
- package/dist/react-native/index.mjs.map +1 -1
- package/package.json +3 -6
package/dist/app/index.js
CHANGED
|
@@ -62,15 +62,12 @@ function* parseEventBlocks(input) {
|
|
|
62
62
|
dataLines.push("");
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
-
if (dataLines.length === 0) {
|
|
65
|
+
if (!eventType || dataLines.length === 0) {
|
|
66
66
|
continue;
|
|
67
67
|
}
|
|
68
68
|
try {
|
|
69
69
|
const parsed = JSON.parse(dataLines.join("\n"));
|
|
70
|
-
|
|
71
|
-
const resolvedType = eventType || parsedType;
|
|
72
|
-
if (!resolvedType) continue;
|
|
73
|
-
yield { type: resolvedType, data: parsed };
|
|
70
|
+
yield { type: eventType, data: parsed };
|
|
74
71
|
} catch {
|
|
75
72
|
}
|
|
76
73
|
}
|
|
@@ -354,20 +351,6 @@ function buildScopedOAuthTokenStorageKey(cacheKey, authSessionKey) {
|
|
|
354
351
|
}
|
|
355
352
|
|
|
356
353
|
// src/core/EmcyAgent.ts
|
|
357
|
-
var AG_UI_EVENT = {
|
|
358
|
-
RUN_STARTED: "RUN_STARTED",
|
|
359
|
-
RUN_FINISHED: "RUN_FINISHED",
|
|
360
|
-
RUN_ERROR: "RUN_ERROR",
|
|
361
|
-
TEXT_MESSAGE_START: "TEXT_MESSAGE_START",
|
|
362
|
-
TEXT_MESSAGE_CONTENT: "TEXT_MESSAGE_CONTENT",
|
|
363
|
-
TEXT_MESSAGE_END: "TEXT_MESSAGE_END",
|
|
364
|
-
TOOL_CALL_START: "TOOL_CALL_START",
|
|
365
|
-
TOOL_CALL_ARGS: "TOOL_CALL_ARGS",
|
|
366
|
-
TOOL_CALL_END: "TOOL_CALL_END",
|
|
367
|
-
TOOL_CALL_RESULT: "TOOL_CALL_RESULT",
|
|
368
|
-
STATE_SNAPSHOT: "STATE_SNAPSHOT",
|
|
369
|
-
CUSTOM: "CUSTOM"
|
|
370
|
-
};
|
|
371
354
|
var DEFAULT_MCP_PROTOCOL_VERSION = "2025-11-25";
|
|
372
355
|
var DEFAULT_LOCAL_PUBLIC_APP_PORT = "3100";
|
|
373
356
|
var DEFAULT_OAUTH_CALLBACK_URL = "https://mcpstack.com/oauth/callback";
|
|
@@ -861,69 +844,6 @@ var McpStackAgent = class {
|
|
|
861
844
|
selection: def.selection
|
|
862
845
|
}));
|
|
863
846
|
}
|
|
864
|
-
clientToolsToAgUiTools() {
|
|
865
|
-
if (!this.config.clientTools) return [];
|
|
866
|
-
return Object.entries(this.config.clientTools).map(([name, def]) => {
|
|
867
|
-
const metadata = {};
|
|
868
|
-
if (def.selection) {
|
|
869
|
-
metadata.mcpstack = { selection: def.selection };
|
|
870
|
-
metadata["x-mcpstack-selection"] = def.selection;
|
|
871
|
-
}
|
|
872
|
-
return {
|
|
873
|
-
name,
|
|
874
|
-
description: def.description,
|
|
875
|
-
parameters: parametersToJsonSchema(def.parameters),
|
|
876
|
-
metadata: Object.keys(metadata).length > 0 ? metadata : void 0
|
|
877
|
-
};
|
|
878
|
-
});
|
|
879
|
-
}
|
|
880
|
-
buildAgUiContext() {
|
|
881
|
-
if (!this.config.context) return [];
|
|
882
|
-
return Object.entries(this.config.context).filter(([, value]) => value != null).map(([key, value]) => ({
|
|
883
|
-
description: key,
|
|
884
|
-
value: typeof value === "string" ? value : JSON.stringify(value)
|
|
885
|
-
}));
|
|
886
|
-
}
|
|
887
|
-
buildAgUiForwardedProps() {
|
|
888
|
-
const externalUser = this.buildExternalUserContext();
|
|
889
|
-
const mcpstack = {
|
|
890
|
-
conversationId: this.conversationId ?? void 0,
|
|
891
|
-
externalUserId: this.resolveExternalUserId(),
|
|
892
|
-
context: this.config.context
|
|
893
|
-
};
|
|
894
|
-
if (externalUser) {
|
|
895
|
-
mcpstack.externalUser = externalUser;
|
|
896
|
-
}
|
|
897
|
-
return { mcpstack };
|
|
898
|
-
}
|
|
899
|
-
buildAgUiUserRunInput(message) {
|
|
900
|
-
return {
|
|
901
|
-
threadId: this.conversationId ?? `thread_${crypto.randomUUID()}`,
|
|
902
|
-
runId: `run_${crypto.randomUUID()}`,
|
|
903
|
-
state: this.config.context ?? {},
|
|
904
|
-
messages: [{ id: crypto.randomUUID(), role: "user", content: message }],
|
|
905
|
-
tools: this.clientToolsToAgUiTools(),
|
|
906
|
-
context: this.buildAgUiContext(),
|
|
907
|
-
forwardedProps: this.buildAgUiForwardedProps()
|
|
908
|
-
};
|
|
909
|
-
}
|
|
910
|
-
buildAgUiToolResultRunInput(toolCall, content, error) {
|
|
911
|
-
return {
|
|
912
|
-
threadId: this.conversationId ?? `thread_${crypto.randomUUID()}`,
|
|
913
|
-
runId: `run_${crypto.randomUUID()}`,
|
|
914
|
-
state: this.config.context ?? {},
|
|
915
|
-
messages: [{
|
|
916
|
-
id: crypto.randomUUID(),
|
|
917
|
-
role: "tool",
|
|
918
|
-
toolCallId: toolCall.toolCallId,
|
|
919
|
-
content,
|
|
920
|
-
error
|
|
921
|
-
}],
|
|
922
|
-
tools: this.clientToolsToAgUiTools(),
|
|
923
|
-
context: this.buildAgUiContext(),
|
|
924
|
-
forwardedProps: this.buildAgUiForwardedProps()
|
|
925
|
-
};
|
|
926
|
-
}
|
|
927
847
|
resolveExternalUserId() {
|
|
928
848
|
const hostIdentity = this.config.embeddedAuth?.hostIdentity;
|
|
929
849
|
return this.config.externalUserId ?? hostIdentity?.subject ?? hostIdentity?.email ?? void 0;
|
|
@@ -2166,44 +2086,109 @@ var McpStackAgent = class {
|
|
|
2166
2086
|
// ================================================================
|
|
2167
2087
|
/**
|
|
2168
2088
|
* The core orchestration loop:
|
|
2169
|
-
* 1. Send message to
|
|
2170
|
-
* 2. Stream
|
|
2171
|
-
* 3. If
|
|
2172
|
-
* 4.
|
|
2089
|
+
* 1. Send message to chat API
|
|
2090
|
+
* 2. Stream response
|
|
2091
|
+
* 3. If tool_call → execute tool via MCP → send result → continue
|
|
2092
|
+
* 4. If message_end → done
|
|
2173
2093
|
*/
|
|
2174
2094
|
async runChatLoop(message) {
|
|
2175
2095
|
this.abortController = new AbortController();
|
|
2176
2096
|
this.emit("thinking", true);
|
|
2177
|
-
|
|
2097
|
+
const chatBody = {
|
|
2098
|
+
agentId: this.config.agentId,
|
|
2099
|
+
conversationId: this.conversationId,
|
|
2100
|
+
message,
|
|
2101
|
+
externalUserId: this.resolveExternalUserId(),
|
|
2102
|
+
context: this.config.context
|
|
2103
|
+
};
|
|
2104
|
+
const externalUser = this.buildExternalUserContext();
|
|
2105
|
+
if (externalUser) {
|
|
2106
|
+
chatBody.externalUser = externalUser;
|
|
2107
|
+
}
|
|
2108
|
+
const clientToolSchemas = this.clientToolsToSchemas();
|
|
2109
|
+
if (clientToolSchemas.length > 0) {
|
|
2110
|
+
chatBody.clientTools = clientToolSchemas;
|
|
2111
|
+
}
|
|
2112
|
+
let response = await this.callChatApi(chatBody, "chat");
|
|
2178
2113
|
while (true) {
|
|
2179
|
-
const result = await this.
|
|
2180
|
-
if (result.type === "
|
|
2114
|
+
const result = await this.processSseStream(response);
|
|
2115
|
+
if (result.type === "message_end") {
|
|
2181
2116
|
break;
|
|
2182
2117
|
}
|
|
2183
|
-
if (result.type === "
|
|
2118
|
+
if (result.type === "tool_call") {
|
|
2184
2119
|
const toolCall = result.data;
|
|
2185
2120
|
const startTime = Date.now();
|
|
2186
2121
|
try {
|
|
2187
|
-
const toolResult = await this.
|
|
2122
|
+
const toolResult = await this.executeTool(toolCall);
|
|
2188
2123
|
const duration = Date.now() - startTime;
|
|
2189
|
-
this.
|
|
2124
|
+
const toolCallMsg = this.messages.find(
|
|
2125
|
+
(m) => m.role === "tool_call" && m.toolCallId === toolCall.toolCallId
|
|
2126
|
+
);
|
|
2127
|
+
if (toolCallMsg) {
|
|
2128
|
+
toolCallMsg.toolCallStatus = "completed";
|
|
2129
|
+
toolCallMsg.toolCallDuration = duration;
|
|
2130
|
+
toolCallMsg.toolResult = typeof toolResult === "string" ? toolResult : JSON.stringify(toolResult);
|
|
2131
|
+
}
|
|
2132
|
+
this.emit("tool_result", { toolCallId: toolCall.toolCallId, result: toolResult, duration });
|
|
2133
|
+
const toolResultMsg = {
|
|
2134
|
+
id: crypto.randomUUID(),
|
|
2135
|
+
role: "tool_result",
|
|
2136
|
+
content: typeof toolResult === "string" ? toolResult : JSON.stringify(toolResult),
|
|
2137
|
+
toolCallId: toolCall.toolCallId,
|
|
2138
|
+
toolName: toolCall.toolName,
|
|
2139
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
2140
|
+
};
|
|
2141
|
+
this.messages.push(toolResultMsg);
|
|
2190
2142
|
this.emit("thinking", true);
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2143
|
+
const toolResultBody = {
|
|
2144
|
+
conversationId: this.conversationId,
|
|
2145
|
+
toolCallId: toolCall.toolCallId,
|
|
2146
|
+
result: toolResult,
|
|
2147
|
+
durationMs: duration,
|
|
2148
|
+
context: this.config.context
|
|
2149
|
+
};
|
|
2150
|
+
const clientToolSchemas2 = this.clientToolsToSchemas();
|
|
2151
|
+
if (clientToolSchemas2.length > 0) {
|
|
2152
|
+
toolResultBody.clientTools = clientToolSchemas2;
|
|
2153
|
+
}
|
|
2154
|
+
response = await this.callChatApi(toolResultBody, "chat/tool-result");
|
|
2195
2155
|
} catch (err) {
|
|
2196
2156
|
const duration = Date.now() - startTime;
|
|
2197
2157
|
const errorMsg = err instanceof Error ? err.message : "Tool execution failed";
|
|
2158
|
+
const toolCallMsg = this.messages.find(
|
|
2159
|
+
(m) => m.role === "tool_call" && m.toolCallId === toolCall.toolCallId
|
|
2160
|
+
);
|
|
2161
|
+
if (toolCallMsg) {
|
|
2162
|
+
toolCallMsg.toolCallStatus = "error";
|
|
2163
|
+
toolCallMsg.toolCallDuration = duration;
|
|
2164
|
+
toolCallMsg.toolError = errorMsg;
|
|
2165
|
+
}
|
|
2166
|
+
this.emit("tool_error", { toolCallId: toolCall.toolCallId, error: errorMsg, duration });
|
|
2198
2167
|
const errorResult = `Error: ${errorMsg}`;
|
|
2199
|
-
|
|
2168
|
+
const toolResultMsg = {
|
|
2169
|
+
id: crypto.randomUUID(),
|
|
2170
|
+
role: "tool_result",
|
|
2171
|
+
content: errorResult,
|
|
2172
|
+
toolCallId: toolCall.toolCallId,
|
|
2173
|
+
toolName: toolCall.toolName,
|
|
2174
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
2175
|
+
};
|
|
2176
|
+
this.messages.push(toolResultMsg);
|
|
2200
2177
|
this.emit("thinking", true);
|
|
2201
2178
|
try {
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2179
|
+
const toolResultBody = {
|
|
2180
|
+
conversationId: this.conversationId,
|
|
2181
|
+
toolCallId: toolCall.toolCallId,
|
|
2182
|
+
result: errorResult,
|
|
2183
|
+
isError: true,
|
|
2184
|
+
durationMs: duration,
|
|
2185
|
+
context: this.config.context
|
|
2186
|
+
};
|
|
2187
|
+
const clientToolSchemas2 = this.clientToolsToSchemas();
|
|
2188
|
+
if (clientToolSchemas2.length > 0) {
|
|
2189
|
+
toolResultBody.clientTools = clientToolSchemas2;
|
|
2190
|
+
}
|
|
2191
|
+
response = await this.callChatApi(toolResultBody, "chat/tool-result");
|
|
2207
2192
|
} catch {
|
|
2208
2193
|
this.emit("error", { code: "tool_error", message: errorMsg });
|
|
2209
2194
|
break;
|
|
@@ -2215,35 +2200,17 @@ var McpStackAgent = class {
|
|
|
2215
2200
|
}
|
|
2216
2201
|
}
|
|
2217
2202
|
}
|
|
2218
|
-
async
|
|
2219
|
-
const def = this.config.clientTools?.[toolCall.toolName];
|
|
2220
|
-
if (!def) {
|
|
2221
|
-
throw new Error(`Unknown client tool: ${toolCall.toolName}`);
|
|
2222
|
-
}
|
|
2223
|
-
return def.execute(toolCall.arguments ?? {});
|
|
2224
|
-
}
|
|
2225
|
-
async callAgUiApi(input) {
|
|
2203
|
+
async callChatApi(body, endpoint) {
|
|
2226
2204
|
const token = await this.resolveAuthToken();
|
|
2227
|
-
const headers = {
|
|
2228
|
-
"Content-Type": "application/json",
|
|
2229
|
-
Accept: "text/event-stream",
|
|
2230
|
-
Authorization: `Bearer ${token}`
|
|
2231
|
-
};
|
|
2232
|
-
if (this.config.auth?.mode === "app-token") {
|
|
2233
|
-
const appToken = await this.config.auth.getToken();
|
|
2234
|
-
if (appToken?.trim()) {
|
|
2235
|
-
headers["X-MCPStack-App-Token"] = appToken.trim();
|
|
2236
|
-
}
|
|
2237
|
-
if (this.config.auth.appId?.trim()) {
|
|
2238
|
-
headers["X-MCPStack-Embedded-App-Id"] = this.config.auth.appId.trim();
|
|
2239
|
-
}
|
|
2240
|
-
}
|
|
2241
2205
|
const response = await fetch(
|
|
2242
|
-
`${this.config.agentServiceUrl}/api/v1
|
|
2206
|
+
`${this.config.agentServiceUrl}/api/v1/${endpoint}`,
|
|
2243
2207
|
{
|
|
2244
2208
|
method: "POST",
|
|
2245
|
-
headers
|
|
2246
|
-
|
|
2209
|
+
headers: {
|
|
2210
|
+
"Content-Type": "application/json",
|
|
2211
|
+
Authorization: `Bearer ${token}`
|
|
2212
|
+
},
|
|
2213
|
+
body: JSON.stringify(body),
|
|
2247
2214
|
signal: this.abortController?.signal
|
|
2248
2215
|
}
|
|
2249
2216
|
);
|
|
@@ -2252,281 +2219,6 @@ var McpStackAgent = class {
|
|
|
2252
2219
|
}
|
|
2253
2220
|
return response;
|
|
2254
2221
|
}
|
|
2255
|
-
async processAgUiStream(response) {
|
|
2256
|
-
let assistantContent = "";
|
|
2257
|
-
let emittedThinkingFalse = false;
|
|
2258
|
-
let pendingFrontendTool = null;
|
|
2259
|
-
const toolCalls = /* @__PURE__ */ new Map();
|
|
2260
|
-
const stopThinking = () => {
|
|
2261
|
-
if (!emittedThinkingFalse) {
|
|
2262
|
-
this.emit("thinking", false);
|
|
2263
|
-
emittedThinkingFalse = true;
|
|
2264
|
-
}
|
|
2265
|
-
};
|
|
2266
|
-
const flushAssistantMessage = () => {
|
|
2267
|
-
if (!assistantContent) {
|
|
2268
|
-
return;
|
|
2269
|
-
}
|
|
2270
|
-
const assistantMsg = {
|
|
2271
|
-
id: crypto.randomUUID(),
|
|
2272
|
-
role: "assistant",
|
|
2273
|
-
content: assistantContent,
|
|
2274
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
2275
|
-
};
|
|
2276
|
-
this.messages.push(assistantMsg);
|
|
2277
|
-
this.emit("message", assistantMsg);
|
|
2278
|
-
assistantContent = "";
|
|
2279
|
-
};
|
|
2280
|
-
for await (const event of parseSseStream(response, this.abortController?.signal)) {
|
|
2281
|
-
const data = event.data;
|
|
2282
|
-
switch (event.type) {
|
|
2283
|
-
case AG_UI_EVENT.RUN_STARTED: {
|
|
2284
|
-
const threadId = this.getStringField(data, "threadId");
|
|
2285
|
-
if (threadId) {
|
|
2286
|
-
this.conversationId = threadId;
|
|
2287
|
-
}
|
|
2288
|
-
break;
|
|
2289
|
-
}
|
|
2290
|
-
case AG_UI_EVENT.STATE_SNAPSHOT: {
|
|
2291
|
-
const snapshot = this.getRecordField(data, "snapshot");
|
|
2292
|
-
const conversationId = snapshot ? this.getStringField(snapshot, "conversationId") : void 0;
|
|
2293
|
-
if (conversationId) {
|
|
2294
|
-
this.conversationId = conversationId;
|
|
2295
|
-
}
|
|
2296
|
-
const budget = snapshot?.budget;
|
|
2297
|
-
if (budget && typeof budget === "object") {
|
|
2298
|
-
this.budgetSnapshot = budget;
|
|
2299
|
-
this.emit("budget_snapshot", this.budgetSnapshot);
|
|
2300
|
-
}
|
|
2301
|
-
break;
|
|
2302
|
-
}
|
|
2303
|
-
case AG_UI_EVENT.TEXT_MESSAGE_CONTENT: {
|
|
2304
|
-
stopThinking();
|
|
2305
|
-
const delta = this.getStringField(data, "delta") ?? "";
|
|
2306
|
-
assistantContent += delta;
|
|
2307
|
-
this.emit("content_delta", { text: delta });
|
|
2308
|
-
break;
|
|
2309
|
-
}
|
|
2310
|
-
case AG_UI_EVENT.TOOL_CALL_START: {
|
|
2311
|
-
stopThinking();
|
|
2312
|
-
const toolCallId = this.getStringField(data, "toolCallId");
|
|
2313
|
-
const toolName = this.getStringField(data, "toolCallName");
|
|
2314
|
-
if (!toolCallId || !toolName) {
|
|
2315
|
-
break;
|
|
2316
|
-
}
|
|
2317
|
-
const mcpstack = this.getRecordField(data, "mcpstack");
|
|
2318
|
-
const sourceValue = mcpstack ? this.getStringField(mcpstack, "source") : void 0;
|
|
2319
|
-
const source = sourceValue === "mcp" ? "mcp" : sourceValue === "client" ? "client" : void 0;
|
|
2320
|
-
toolCalls.set(toolCallId, {
|
|
2321
|
-
toolCallId,
|
|
2322
|
-
toolName,
|
|
2323
|
-
toolLabel: mcpstack ? this.getStringField(mcpstack, "label") : void 0,
|
|
2324
|
-
mcpServerName: mcpstack ? this.getStringField(mcpstack, "mcpServerName") : void 0,
|
|
2325
|
-
source,
|
|
2326
|
-
argumentsJson: "",
|
|
2327
|
-
startedAt: Date.now()
|
|
2328
|
-
});
|
|
2329
|
-
break;
|
|
2330
|
-
}
|
|
2331
|
-
case AG_UI_EVENT.TOOL_CALL_ARGS: {
|
|
2332
|
-
const toolCallId = this.getStringField(data, "toolCallId");
|
|
2333
|
-
const state = toolCallId ? toolCalls.get(toolCallId) : void 0;
|
|
2334
|
-
if (state) {
|
|
2335
|
-
state.argumentsJson += this.getStringField(data, "delta") ?? "";
|
|
2336
|
-
}
|
|
2337
|
-
break;
|
|
2338
|
-
}
|
|
2339
|
-
case AG_UI_EVENT.TOOL_CALL_END: {
|
|
2340
|
-
const toolCallId = this.getStringField(data, "toolCallId");
|
|
2341
|
-
const state = toolCallId ? toolCalls.get(toolCallId) : void 0;
|
|
2342
|
-
if (!state) {
|
|
2343
|
-
break;
|
|
2344
|
-
}
|
|
2345
|
-
flushAssistantMessage();
|
|
2346
|
-
const toolCall = {
|
|
2347
|
-
toolCallId: state.toolCallId,
|
|
2348
|
-
toolName: state.toolName,
|
|
2349
|
-
toolLabel: state.toolLabel,
|
|
2350
|
-
mcpServerName: state.mcpServerName,
|
|
2351
|
-
source: state.source,
|
|
2352
|
-
arguments: this.parseToolArguments(state.argumentsJson)
|
|
2353
|
-
};
|
|
2354
|
-
const toolCallMsg = {
|
|
2355
|
-
id: crypto.randomUUID(),
|
|
2356
|
-
role: "tool_call",
|
|
2357
|
-
content: `Calling ${toolCall.toolLabel ?? toolCall.toolName}...`,
|
|
2358
|
-
toolName: toolCall.toolName,
|
|
2359
|
-
toolLabel: toolCall.toolLabel,
|
|
2360
|
-
toolCallId: toolCall.toolCallId,
|
|
2361
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
2362
|
-
toolCallStatus: "calling",
|
|
2363
|
-
toolCallStartTime: state.startedAt
|
|
2364
|
-
};
|
|
2365
|
-
this.messages.push(toolCallMsg);
|
|
2366
|
-
this.emit("tool_call", toolCall);
|
|
2367
|
-
if (state.source !== "mcp") {
|
|
2368
|
-
pendingFrontendTool = toolCall;
|
|
2369
|
-
}
|
|
2370
|
-
break;
|
|
2371
|
-
}
|
|
2372
|
-
case AG_UI_EVENT.TOOL_CALL_RESULT: {
|
|
2373
|
-
const toolCallId = this.getStringField(data, "toolCallId");
|
|
2374
|
-
const state = toolCallId ? toolCalls.get(toolCallId) : void 0;
|
|
2375
|
-
if (!toolCallId) {
|
|
2376
|
-
break;
|
|
2377
|
-
}
|
|
2378
|
-
const content = this.getStringField(data, "content") ?? "";
|
|
2379
|
-
const toolCall = {
|
|
2380
|
-
toolCallId,
|
|
2381
|
-
toolName: state?.toolName ?? this.getStringField(data, "toolCallName") ?? toolCallId,
|
|
2382
|
-
toolLabel: state?.toolLabel,
|
|
2383
|
-
mcpServerName: state?.mcpServerName,
|
|
2384
|
-
source: state?.source,
|
|
2385
|
-
arguments: state ? this.parseToolArguments(state.argumentsJson) : {}
|
|
2386
|
-
};
|
|
2387
|
-
const duration = state ? Date.now() - state.startedAt : 0;
|
|
2388
|
-
this.recordToolResult(toolCall, this.parseToolContent(content), duration);
|
|
2389
|
-
if (pendingFrontendTool?.toolCallId === toolCallId) {
|
|
2390
|
-
pendingFrontendTool = null;
|
|
2391
|
-
}
|
|
2392
|
-
break;
|
|
2393
|
-
}
|
|
2394
|
-
case AG_UI_EVENT.CUSTOM: {
|
|
2395
|
-
const name = this.getStringField(data, "name");
|
|
2396
|
-
if (name === "mcpstack.budget_snapshot") {
|
|
2397
|
-
const value = data.value;
|
|
2398
|
-
if (value && typeof value === "object") {
|
|
2399
|
-
this.budgetSnapshot = value;
|
|
2400
|
-
this.emit("budget_snapshot", this.budgetSnapshot);
|
|
2401
|
-
}
|
|
2402
|
-
}
|
|
2403
|
-
break;
|
|
2404
|
-
}
|
|
2405
|
-
case AG_UI_EVENT.RUN_FINISHED: {
|
|
2406
|
-
const result = this.getRecordField(data, "result");
|
|
2407
|
-
const conversationId = result ? this.getStringField(result, "conversationId") : void 0;
|
|
2408
|
-
if (conversationId) {
|
|
2409
|
-
this.conversationId = conversationId;
|
|
2410
|
-
}
|
|
2411
|
-
if (pendingFrontendTool) {
|
|
2412
|
-
return { type: "frontend_tool", data: pendingFrontendTool };
|
|
2413
|
-
}
|
|
2414
|
-
flushAssistantMessage();
|
|
2415
|
-
const messageEnd2 = {
|
|
2416
|
-
inputTokens: this.getNumberField(result, "inputTokens") ?? 0,
|
|
2417
|
-
outputTokens: this.getNumberField(result, "outputTokens") ?? 0,
|
|
2418
|
-
toolCalls: this.getNumberField(result, "toolCalls") ?? toolCalls.size
|
|
2419
|
-
};
|
|
2420
|
-
this.emit("message_end", messageEnd2);
|
|
2421
|
-
return { type: "done" };
|
|
2422
|
-
}
|
|
2423
|
-
case AG_UI_EVENT.RUN_ERROR: {
|
|
2424
|
-
const error = {
|
|
2425
|
-
code: this.getStringField(data, "code") ?? "run_error",
|
|
2426
|
-
message: this.getStringField(data, "message") ?? "Agent run failed."
|
|
2427
|
-
};
|
|
2428
|
-
const errorMsg = {
|
|
2429
|
-
id: crypto.randomUUID(),
|
|
2430
|
-
role: "error",
|
|
2431
|
-
content: error.message,
|
|
2432
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
2433
|
-
errorCode: error.code
|
|
2434
|
-
};
|
|
2435
|
-
this.messages.push(errorMsg);
|
|
2436
|
-
this.emit("message", errorMsg);
|
|
2437
|
-
this.emit("error", error);
|
|
2438
|
-
return { type: "error", data: error };
|
|
2439
|
-
}
|
|
2440
|
-
}
|
|
2441
|
-
}
|
|
2442
|
-
flushAssistantMessage();
|
|
2443
|
-
const messageEnd = {
|
|
2444
|
-
inputTokens: 0,
|
|
2445
|
-
outputTokens: 0,
|
|
2446
|
-
toolCalls: toolCalls.size
|
|
2447
|
-
};
|
|
2448
|
-
this.emit("message_end", messageEnd);
|
|
2449
|
-
return { type: "done" };
|
|
2450
|
-
}
|
|
2451
|
-
recordToolResult(toolCall, result, duration) {
|
|
2452
|
-
const toolCallMsg = this.messages.find(
|
|
2453
|
-
(m) => m.role === "tool_call" && m.toolCallId === toolCall.toolCallId
|
|
2454
|
-
);
|
|
2455
|
-
if (toolCallMsg) {
|
|
2456
|
-
toolCallMsg.toolCallStatus = "completed";
|
|
2457
|
-
toolCallMsg.toolCallDuration = duration;
|
|
2458
|
-
toolCallMsg.toolResult = this.serializeToolContent(result);
|
|
2459
|
-
}
|
|
2460
|
-
this.emit("tool_result", { toolCallId: toolCall.toolCallId, result, duration });
|
|
2461
|
-
const toolResultMsg = {
|
|
2462
|
-
id: crypto.randomUUID(),
|
|
2463
|
-
role: "tool_result",
|
|
2464
|
-
content: this.serializeToolContent(result),
|
|
2465
|
-
toolCallId: toolCall.toolCallId,
|
|
2466
|
-
toolName: toolCall.toolName,
|
|
2467
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
2468
|
-
};
|
|
2469
|
-
this.messages.push(toolResultMsg);
|
|
2470
|
-
}
|
|
2471
|
-
recordToolError(toolCall, error, resultContent, duration) {
|
|
2472
|
-
const toolCallMsg = this.messages.find(
|
|
2473
|
-
(m) => m.role === "tool_call" && m.toolCallId === toolCall.toolCallId
|
|
2474
|
-
);
|
|
2475
|
-
if (toolCallMsg) {
|
|
2476
|
-
toolCallMsg.toolCallStatus = "error";
|
|
2477
|
-
toolCallMsg.toolCallDuration = duration;
|
|
2478
|
-
toolCallMsg.toolError = error;
|
|
2479
|
-
}
|
|
2480
|
-
this.emit("tool_error", { toolCallId: toolCall.toolCallId, error, duration });
|
|
2481
|
-
const toolResultMsg = {
|
|
2482
|
-
id: crypto.randomUUID(),
|
|
2483
|
-
role: "tool_result",
|
|
2484
|
-
content: resultContent,
|
|
2485
|
-
toolCallId: toolCall.toolCallId,
|
|
2486
|
-
toolName: toolCall.toolName,
|
|
2487
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
2488
|
-
};
|
|
2489
|
-
this.messages.push(toolResultMsg);
|
|
2490
|
-
}
|
|
2491
|
-
serializeToolContent(result) {
|
|
2492
|
-
if (result == null) {
|
|
2493
|
-
return "";
|
|
2494
|
-
}
|
|
2495
|
-
return typeof result === "string" ? result : JSON.stringify(result);
|
|
2496
|
-
}
|
|
2497
|
-
parseToolContent(content) {
|
|
2498
|
-
if (!content) {
|
|
2499
|
-
return "";
|
|
2500
|
-
}
|
|
2501
|
-
try {
|
|
2502
|
-
return JSON.parse(content);
|
|
2503
|
-
} catch {
|
|
2504
|
-
return content;
|
|
2505
|
-
}
|
|
2506
|
-
}
|
|
2507
|
-
parseToolArguments(argumentsJson) {
|
|
2508
|
-
if (!argumentsJson.trim()) {
|
|
2509
|
-
return {};
|
|
2510
|
-
}
|
|
2511
|
-
try {
|
|
2512
|
-
const parsed = JSON.parse(argumentsJson);
|
|
2513
|
-
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
2514
|
-
} catch {
|
|
2515
|
-
return {};
|
|
2516
|
-
}
|
|
2517
|
-
}
|
|
2518
|
-
getRecordField(record, key) {
|
|
2519
|
-
const value = record?.[key];
|
|
2520
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
2521
|
-
}
|
|
2522
|
-
getStringField(record, key) {
|
|
2523
|
-
const value = record?.[key];
|
|
2524
|
-
return typeof value === "string" && value ? value : void 0;
|
|
2525
|
-
}
|
|
2526
|
-
getNumberField(record, key) {
|
|
2527
|
-
const value = record?.[key];
|
|
2528
|
-
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
2529
|
-
}
|
|
2530
2222
|
async fetchConversationMessages(conversationId, cursor, pageSize = 50) {
|
|
2531
2223
|
const token = await this.resolveAuthToken();
|
|
2532
2224
|
const params = new URLSearchParams();
|
|
@@ -2574,7 +2266,7 @@ var McpStackAgent = class {
|
|
|
2574
2266
|
};
|
|
2575
2267
|
}
|
|
2576
2268
|
/**
|
|
2577
|
-
* Process
|
|
2269
|
+
* Process an SSE stream from the chat API.
|
|
2578
2270
|
* Returns when the stream ends (either message_end or tool_call).
|
|
2579
2271
|
*/
|
|
2580
2272
|
async processSseStream(response) {
|