@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
|
@@ -74,15 +74,12 @@ function* parseEventBlocks(input) {
|
|
|
74
74
|
dataLines.push("");
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
-
if (dataLines.length === 0) {
|
|
77
|
+
if (!eventType || dataLines.length === 0) {
|
|
78
78
|
continue;
|
|
79
79
|
}
|
|
80
80
|
try {
|
|
81
81
|
const parsed = JSON.parse(dataLines.join("\n"));
|
|
82
|
-
|
|
83
|
-
const resolvedType = eventType || parsedType;
|
|
84
|
-
if (!resolvedType) continue;
|
|
85
|
-
yield { type: resolvedType, data: parsed };
|
|
82
|
+
yield { type: eventType, data: parsed };
|
|
86
83
|
} catch {
|
|
87
84
|
}
|
|
88
85
|
}
|
|
@@ -374,20 +371,6 @@ function buildScopedOAuthTokenStorageKey(cacheKey, authSessionKey) {
|
|
|
374
371
|
}
|
|
375
372
|
|
|
376
373
|
// src/core/EmcyAgent.ts
|
|
377
|
-
var AG_UI_EVENT = {
|
|
378
|
-
RUN_STARTED: "RUN_STARTED",
|
|
379
|
-
RUN_FINISHED: "RUN_FINISHED",
|
|
380
|
-
RUN_ERROR: "RUN_ERROR",
|
|
381
|
-
TEXT_MESSAGE_START: "TEXT_MESSAGE_START",
|
|
382
|
-
TEXT_MESSAGE_CONTENT: "TEXT_MESSAGE_CONTENT",
|
|
383
|
-
TEXT_MESSAGE_END: "TEXT_MESSAGE_END",
|
|
384
|
-
TOOL_CALL_START: "TOOL_CALL_START",
|
|
385
|
-
TOOL_CALL_ARGS: "TOOL_CALL_ARGS",
|
|
386
|
-
TOOL_CALL_END: "TOOL_CALL_END",
|
|
387
|
-
TOOL_CALL_RESULT: "TOOL_CALL_RESULT",
|
|
388
|
-
STATE_SNAPSHOT: "STATE_SNAPSHOT",
|
|
389
|
-
CUSTOM: "CUSTOM"
|
|
390
|
-
};
|
|
391
374
|
var DEFAULT_MCP_PROTOCOL_VERSION = "2025-11-25";
|
|
392
375
|
var DEFAULT_LOCAL_PUBLIC_APP_PORT = "3100";
|
|
393
376
|
var DEFAULT_OAUTH_CALLBACK_URL = "https://mcpstack.com/oauth/callback";
|
|
@@ -881,69 +864,6 @@ var McpStackAgent = class {
|
|
|
881
864
|
selection: def.selection
|
|
882
865
|
}));
|
|
883
866
|
}
|
|
884
|
-
clientToolsToAgUiTools() {
|
|
885
|
-
if (!this.config.clientTools) return [];
|
|
886
|
-
return Object.entries(this.config.clientTools).map(([name, def]) => {
|
|
887
|
-
const metadata = {};
|
|
888
|
-
if (def.selection) {
|
|
889
|
-
metadata.mcpstack = { selection: def.selection };
|
|
890
|
-
metadata["x-mcpstack-selection"] = def.selection;
|
|
891
|
-
}
|
|
892
|
-
return {
|
|
893
|
-
name,
|
|
894
|
-
description: def.description,
|
|
895
|
-
parameters: parametersToJsonSchema(def.parameters),
|
|
896
|
-
metadata: Object.keys(metadata).length > 0 ? metadata : void 0
|
|
897
|
-
};
|
|
898
|
-
});
|
|
899
|
-
}
|
|
900
|
-
buildAgUiContext() {
|
|
901
|
-
if (!this.config.context) return [];
|
|
902
|
-
return Object.entries(this.config.context).filter(([, value]) => value != null).map(([key, value]) => ({
|
|
903
|
-
description: key,
|
|
904
|
-
value: typeof value === "string" ? value : JSON.stringify(value)
|
|
905
|
-
}));
|
|
906
|
-
}
|
|
907
|
-
buildAgUiForwardedProps() {
|
|
908
|
-
const externalUser = this.buildExternalUserContext();
|
|
909
|
-
const mcpstack = {
|
|
910
|
-
conversationId: this.conversationId ?? void 0,
|
|
911
|
-
externalUserId: this.resolveExternalUserId(),
|
|
912
|
-
context: this.config.context
|
|
913
|
-
};
|
|
914
|
-
if (externalUser) {
|
|
915
|
-
mcpstack.externalUser = externalUser;
|
|
916
|
-
}
|
|
917
|
-
return { mcpstack };
|
|
918
|
-
}
|
|
919
|
-
buildAgUiUserRunInput(message) {
|
|
920
|
-
return {
|
|
921
|
-
threadId: this.conversationId ?? `thread_${crypto.randomUUID()}`,
|
|
922
|
-
runId: `run_${crypto.randomUUID()}`,
|
|
923
|
-
state: this.config.context ?? {},
|
|
924
|
-
messages: [{ id: crypto.randomUUID(), role: "user", content: message }],
|
|
925
|
-
tools: this.clientToolsToAgUiTools(),
|
|
926
|
-
context: this.buildAgUiContext(),
|
|
927
|
-
forwardedProps: this.buildAgUiForwardedProps()
|
|
928
|
-
};
|
|
929
|
-
}
|
|
930
|
-
buildAgUiToolResultRunInput(toolCall, content, error) {
|
|
931
|
-
return {
|
|
932
|
-
threadId: this.conversationId ?? `thread_${crypto.randomUUID()}`,
|
|
933
|
-
runId: `run_${crypto.randomUUID()}`,
|
|
934
|
-
state: this.config.context ?? {},
|
|
935
|
-
messages: [{
|
|
936
|
-
id: crypto.randomUUID(),
|
|
937
|
-
role: "tool",
|
|
938
|
-
toolCallId: toolCall.toolCallId,
|
|
939
|
-
content,
|
|
940
|
-
error
|
|
941
|
-
}],
|
|
942
|
-
tools: this.clientToolsToAgUiTools(),
|
|
943
|
-
context: this.buildAgUiContext(),
|
|
944
|
-
forwardedProps: this.buildAgUiForwardedProps()
|
|
945
|
-
};
|
|
946
|
-
}
|
|
947
867
|
resolveExternalUserId() {
|
|
948
868
|
const hostIdentity = this.config.embeddedAuth?.hostIdentity;
|
|
949
869
|
return this.config.externalUserId ?? hostIdentity?.subject ?? hostIdentity?.email ?? void 0;
|
|
@@ -2186,44 +2106,109 @@ var McpStackAgent = class {
|
|
|
2186
2106
|
// ================================================================
|
|
2187
2107
|
/**
|
|
2188
2108
|
* The core orchestration loop:
|
|
2189
|
-
* 1. Send message to
|
|
2190
|
-
* 2. Stream
|
|
2191
|
-
* 3. If
|
|
2192
|
-
* 4.
|
|
2109
|
+
* 1. Send message to chat API
|
|
2110
|
+
* 2. Stream response
|
|
2111
|
+
* 3. If tool_call → execute tool via MCP → send result → continue
|
|
2112
|
+
* 4. If message_end → done
|
|
2193
2113
|
*/
|
|
2194
2114
|
async runChatLoop(message) {
|
|
2195
2115
|
this.abortController = new AbortController();
|
|
2196
2116
|
this.emit("thinking", true);
|
|
2197
|
-
|
|
2117
|
+
const chatBody = {
|
|
2118
|
+
agentId: this.config.agentId,
|
|
2119
|
+
conversationId: this.conversationId,
|
|
2120
|
+
message,
|
|
2121
|
+
externalUserId: this.resolveExternalUserId(),
|
|
2122
|
+
context: this.config.context
|
|
2123
|
+
};
|
|
2124
|
+
const externalUser = this.buildExternalUserContext();
|
|
2125
|
+
if (externalUser) {
|
|
2126
|
+
chatBody.externalUser = externalUser;
|
|
2127
|
+
}
|
|
2128
|
+
const clientToolSchemas = this.clientToolsToSchemas();
|
|
2129
|
+
if (clientToolSchemas.length > 0) {
|
|
2130
|
+
chatBody.clientTools = clientToolSchemas;
|
|
2131
|
+
}
|
|
2132
|
+
let response = await this.callChatApi(chatBody, "chat");
|
|
2198
2133
|
while (true) {
|
|
2199
|
-
const result = await this.
|
|
2200
|
-
if (result.type === "
|
|
2134
|
+
const result = await this.processSseStream(response);
|
|
2135
|
+
if (result.type === "message_end") {
|
|
2201
2136
|
break;
|
|
2202
2137
|
}
|
|
2203
|
-
if (result.type === "
|
|
2138
|
+
if (result.type === "tool_call") {
|
|
2204
2139
|
const toolCall = result.data;
|
|
2205
2140
|
const startTime = Date.now();
|
|
2206
2141
|
try {
|
|
2207
|
-
const toolResult = await this.
|
|
2142
|
+
const toolResult = await this.executeTool(toolCall);
|
|
2208
2143
|
const duration = Date.now() - startTime;
|
|
2209
|
-
this.
|
|
2144
|
+
const toolCallMsg = this.messages.find(
|
|
2145
|
+
(m) => m.role === "tool_call" && m.toolCallId === toolCall.toolCallId
|
|
2146
|
+
);
|
|
2147
|
+
if (toolCallMsg) {
|
|
2148
|
+
toolCallMsg.toolCallStatus = "completed";
|
|
2149
|
+
toolCallMsg.toolCallDuration = duration;
|
|
2150
|
+
toolCallMsg.toolResult = typeof toolResult === "string" ? toolResult : JSON.stringify(toolResult);
|
|
2151
|
+
}
|
|
2152
|
+
this.emit("tool_result", { toolCallId: toolCall.toolCallId, result: toolResult, duration });
|
|
2153
|
+
const toolResultMsg = {
|
|
2154
|
+
id: crypto.randomUUID(),
|
|
2155
|
+
role: "tool_result",
|
|
2156
|
+
content: typeof toolResult === "string" ? toolResult : JSON.stringify(toolResult),
|
|
2157
|
+
toolCallId: toolCall.toolCallId,
|
|
2158
|
+
toolName: toolCall.toolName,
|
|
2159
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
2160
|
+
};
|
|
2161
|
+
this.messages.push(toolResultMsg);
|
|
2210
2162
|
this.emit("thinking", true);
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2163
|
+
const toolResultBody = {
|
|
2164
|
+
conversationId: this.conversationId,
|
|
2165
|
+
toolCallId: toolCall.toolCallId,
|
|
2166
|
+
result: toolResult,
|
|
2167
|
+
durationMs: duration,
|
|
2168
|
+
context: this.config.context
|
|
2169
|
+
};
|
|
2170
|
+
const clientToolSchemas2 = this.clientToolsToSchemas();
|
|
2171
|
+
if (clientToolSchemas2.length > 0) {
|
|
2172
|
+
toolResultBody.clientTools = clientToolSchemas2;
|
|
2173
|
+
}
|
|
2174
|
+
response = await this.callChatApi(toolResultBody, "chat/tool-result");
|
|
2215
2175
|
} catch (err) {
|
|
2216
2176
|
const duration = Date.now() - startTime;
|
|
2217
2177
|
const errorMsg = err instanceof Error ? err.message : "Tool execution failed";
|
|
2178
|
+
const toolCallMsg = this.messages.find(
|
|
2179
|
+
(m) => m.role === "tool_call" && m.toolCallId === toolCall.toolCallId
|
|
2180
|
+
);
|
|
2181
|
+
if (toolCallMsg) {
|
|
2182
|
+
toolCallMsg.toolCallStatus = "error";
|
|
2183
|
+
toolCallMsg.toolCallDuration = duration;
|
|
2184
|
+
toolCallMsg.toolError = errorMsg;
|
|
2185
|
+
}
|
|
2186
|
+
this.emit("tool_error", { toolCallId: toolCall.toolCallId, error: errorMsg, duration });
|
|
2218
2187
|
const errorResult = `Error: ${errorMsg}`;
|
|
2219
|
-
|
|
2188
|
+
const toolResultMsg = {
|
|
2189
|
+
id: crypto.randomUUID(),
|
|
2190
|
+
role: "tool_result",
|
|
2191
|
+
content: errorResult,
|
|
2192
|
+
toolCallId: toolCall.toolCallId,
|
|
2193
|
+
toolName: toolCall.toolName,
|
|
2194
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
2195
|
+
};
|
|
2196
|
+
this.messages.push(toolResultMsg);
|
|
2220
2197
|
this.emit("thinking", true);
|
|
2221
2198
|
try {
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2199
|
+
const toolResultBody = {
|
|
2200
|
+
conversationId: this.conversationId,
|
|
2201
|
+
toolCallId: toolCall.toolCallId,
|
|
2202
|
+
result: errorResult,
|
|
2203
|
+
isError: true,
|
|
2204
|
+
durationMs: duration,
|
|
2205
|
+
context: this.config.context
|
|
2206
|
+
};
|
|
2207
|
+
const clientToolSchemas2 = this.clientToolsToSchemas();
|
|
2208
|
+
if (clientToolSchemas2.length > 0) {
|
|
2209
|
+
toolResultBody.clientTools = clientToolSchemas2;
|
|
2210
|
+
}
|
|
2211
|
+
response = await this.callChatApi(toolResultBody, "chat/tool-result");
|
|
2227
2212
|
} catch {
|
|
2228
2213
|
this.emit("error", { code: "tool_error", message: errorMsg });
|
|
2229
2214
|
break;
|
|
@@ -2235,35 +2220,17 @@ var McpStackAgent = class {
|
|
|
2235
2220
|
}
|
|
2236
2221
|
}
|
|
2237
2222
|
}
|
|
2238
|
-
async
|
|
2239
|
-
const def = this.config.clientTools?.[toolCall.toolName];
|
|
2240
|
-
if (!def) {
|
|
2241
|
-
throw new Error(`Unknown client tool: ${toolCall.toolName}`);
|
|
2242
|
-
}
|
|
2243
|
-
return def.execute(toolCall.arguments ?? {});
|
|
2244
|
-
}
|
|
2245
|
-
async callAgUiApi(input) {
|
|
2223
|
+
async callChatApi(body, endpoint) {
|
|
2246
2224
|
const token = await this.resolveAuthToken();
|
|
2247
|
-
const headers = {
|
|
2248
|
-
"Content-Type": "application/json",
|
|
2249
|
-
Accept: "text/event-stream",
|
|
2250
|
-
Authorization: `Bearer ${token}`
|
|
2251
|
-
};
|
|
2252
|
-
if (this.config.auth?.mode === "app-token") {
|
|
2253
|
-
const appToken = await this.config.auth.getToken();
|
|
2254
|
-
if (appToken?.trim()) {
|
|
2255
|
-
headers["X-MCPStack-App-Token"] = appToken.trim();
|
|
2256
|
-
}
|
|
2257
|
-
if (this.config.auth.appId?.trim()) {
|
|
2258
|
-
headers["X-MCPStack-Embedded-App-Id"] = this.config.auth.appId.trim();
|
|
2259
|
-
}
|
|
2260
|
-
}
|
|
2261
2225
|
const response = await fetch(
|
|
2262
|
-
`${this.config.agentServiceUrl}/api/v1
|
|
2226
|
+
`${this.config.agentServiceUrl}/api/v1/${endpoint}`,
|
|
2263
2227
|
{
|
|
2264
2228
|
method: "POST",
|
|
2265
|
-
headers
|
|
2266
|
-
|
|
2229
|
+
headers: {
|
|
2230
|
+
"Content-Type": "application/json",
|
|
2231
|
+
Authorization: `Bearer ${token}`
|
|
2232
|
+
},
|
|
2233
|
+
body: JSON.stringify(body),
|
|
2267
2234
|
signal: this.abortController?.signal
|
|
2268
2235
|
}
|
|
2269
2236
|
);
|
|
@@ -2272,281 +2239,6 @@ var McpStackAgent = class {
|
|
|
2272
2239
|
}
|
|
2273
2240
|
return response;
|
|
2274
2241
|
}
|
|
2275
|
-
async processAgUiStream(response) {
|
|
2276
|
-
let assistantContent = "";
|
|
2277
|
-
let emittedThinkingFalse = false;
|
|
2278
|
-
let pendingFrontendTool = null;
|
|
2279
|
-
const toolCalls = /* @__PURE__ */ new Map();
|
|
2280
|
-
const stopThinking = () => {
|
|
2281
|
-
if (!emittedThinkingFalse) {
|
|
2282
|
-
this.emit("thinking", false);
|
|
2283
|
-
emittedThinkingFalse = true;
|
|
2284
|
-
}
|
|
2285
|
-
};
|
|
2286
|
-
const flushAssistantMessage = () => {
|
|
2287
|
-
if (!assistantContent) {
|
|
2288
|
-
return;
|
|
2289
|
-
}
|
|
2290
|
-
const assistantMsg = {
|
|
2291
|
-
id: crypto.randomUUID(),
|
|
2292
|
-
role: "assistant",
|
|
2293
|
-
content: assistantContent,
|
|
2294
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
2295
|
-
};
|
|
2296
|
-
this.messages.push(assistantMsg);
|
|
2297
|
-
this.emit("message", assistantMsg);
|
|
2298
|
-
assistantContent = "";
|
|
2299
|
-
};
|
|
2300
|
-
for await (const event of parseSseStream(response, this.abortController?.signal)) {
|
|
2301
|
-
const data = event.data;
|
|
2302
|
-
switch (event.type) {
|
|
2303
|
-
case AG_UI_EVENT.RUN_STARTED: {
|
|
2304
|
-
const threadId = this.getStringField(data, "threadId");
|
|
2305
|
-
if (threadId) {
|
|
2306
|
-
this.conversationId = threadId;
|
|
2307
|
-
}
|
|
2308
|
-
break;
|
|
2309
|
-
}
|
|
2310
|
-
case AG_UI_EVENT.STATE_SNAPSHOT: {
|
|
2311
|
-
const snapshot = this.getRecordField(data, "snapshot");
|
|
2312
|
-
const conversationId = snapshot ? this.getStringField(snapshot, "conversationId") : void 0;
|
|
2313
|
-
if (conversationId) {
|
|
2314
|
-
this.conversationId = conversationId;
|
|
2315
|
-
}
|
|
2316
|
-
const budget = snapshot?.budget;
|
|
2317
|
-
if (budget && typeof budget === "object") {
|
|
2318
|
-
this.budgetSnapshot = budget;
|
|
2319
|
-
this.emit("budget_snapshot", this.budgetSnapshot);
|
|
2320
|
-
}
|
|
2321
|
-
break;
|
|
2322
|
-
}
|
|
2323
|
-
case AG_UI_EVENT.TEXT_MESSAGE_CONTENT: {
|
|
2324
|
-
stopThinking();
|
|
2325
|
-
const delta = this.getStringField(data, "delta") ?? "";
|
|
2326
|
-
assistantContent += delta;
|
|
2327
|
-
this.emit("content_delta", { text: delta });
|
|
2328
|
-
break;
|
|
2329
|
-
}
|
|
2330
|
-
case AG_UI_EVENT.TOOL_CALL_START: {
|
|
2331
|
-
stopThinking();
|
|
2332
|
-
const toolCallId = this.getStringField(data, "toolCallId");
|
|
2333
|
-
const toolName = this.getStringField(data, "toolCallName");
|
|
2334
|
-
if (!toolCallId || !toolName) {
|
|
2335
|
-
break;
|
|
2336
|
-
}
|
|
2337
|
-
const mcpstack = this.getRecordField(data, "mcpstack");
|
|
2338
|
-
const sourceValue = mcpstack ? this.getStringField(mcpstack, "source") : void 0;
|
|
2339
|
-
const source = sourceValue === "mcp" ? "mcp" : sourceValue === "client" ? "client" : void 0;
|
|
2340
|
-
toolCalls.set(toolCallId, {
|
|
2341
|
-
toolCallId,
|
|
2342
|
-
toolName,
|
|
2343
|
-
toolLabel: mcpstack ? this.getStringField(mcpstack, "label") : void 0,
|
|
2344
|
-
mcpServerName: mcpstack ? this.getStringField(mcpstack, "mcpServerName") : void 0,
|
|
2345
|
-
source,
|
|
2346
|
-
argumentsJson: "",
|
|
2347
|
-
startedAt: Date.now()
|
|
2348
|
-
});
|
|
2349
|
-
break;
|
|
2350
|
-
}
|
|
2351
|
-
case AG_UI_EVENT.TOOL_CALL_ARGS: {
|
|
2352
|
-
const toolCallId = this.getStringField(data, "toolCallId");
|
|
2353
|
-
const state = toolCallId ? toolCalls.get(toolCallId) : void 0;
|
|
2354
|
-
if (state) {
|
|
2355
|
-
state.argumentsJson += this.getStringField(data, "delta") ?? "";
|
|
2356
|
-
}
|
|
2357
|
-
break;
|
|
2358
|
-
}
|
|
2359
|
-
case AG_UI_EVENT.TOOL_CALL_END: {
|
|
2360
|
-
const toolCallId = this.getStringField(data, "toolCallId");
|
|
2361
|
-
const state = toolCallId ? toolCalls.get(toolCallId) : void 0;
|
|
2362
|
-
if (!state) {
|
|
2363
|
-
break;
|
|
2364
|
-
}
|
|
2365
|
-
flushAssistantMessage();
|
|
2366
|
-
const toolCall = {
|
|
2367
|
-
toolCallId: state.toolCallId,
|
|
2368
|
-
toolName: state.toolName,
|
|
2369
|
-
toolLabel: state.toolLabel,
|
|
2370
|
-
mcpServerName: state.mcpServerName,
|
|
2371
|
-
source: state.source,
|
|
2372
|
-
arguments: this.parseToolArguments(state.argumentsJson)
|
|
2373
|
-
};
|
|
2374
|
-
const toolCallMsg = {
|
|
2375
|
-
id: crypto.randomUUID(),
|
|
2376
|
-
role: "tool_call",
|
|
2377
|
-
content: `Calling ${toolCall.toolLabel ?? toolCall.toolName}...`,
|
|
2378
|
-
toolName: toolCall.toolName,
|
|
2379
|
-
toolLabel: toolCall.toolLabel,
|
|
2380
|
-
toolCallId: toolCall.toolCallId,
|
|
2381
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
2382
|
-
toolCallStatus: "calling",
|
|
2383
|
-
toolCallStartTime: state.startedAt
|
|
2384
|
-
};
|
|
2385
|
-
this.messages.push(toolCallMsg);
|
|
2386
|
-
this.emit("tool_call", toolCall);
|
|
2387
|
-
if (state.source !== "mcp") {
|
|
2388
|
-
pendingFrontendTool = toolCall;
|
|
2389
|
-
}
|
|
2390
|
-
break;
|
|
2391
|
-
}
|
|
2392
|
-
case AG_UI_EVENT.TOOL_CALL_RESULT: {
|
|
2393
|
-
const toolCallId = this.getStringField(data, "toolCallId");
|
|
2394
|
-
const state = toolCallId ? toolCalls.get(toolCallId) : void 0;
|
|
2395
|
-
if (!toolCallId) {
|
|
2396
|
-
break;
|
|
2397
|
-
}
|
|
2398
|
-
const content = this.getStringField(data, "content") ?? "";
|
|
2399
|
-
const toolCall = {
|
|
2400
|
-
toolCallId,
|
|
2401
|
-
toolName: state?.toolName ?? this.getStringField(data, "toolCallName") ?? toolCallId,
|
|
2402
|
-
toolLabel: state?.toolLabel,
|
|
2403
|
-
mcpServerName: state?.mcpServerName,
|
|
2404
|
-
source: state?.source,
|
|
2405
|
-
arguments: state ? this.parseToolArguments(state.argumentsJson) : {}
|
|
2406
|
-
};
|
|
2407
|
-
const duration = state ? Date.now() - state.startedAt : 0;
|
|
2408
|
-
this.recordToolResult(toolCall, this.parseToolContent(content), duration);
|
|
2409
|
-
if (pendingFrontendTool?.toolCallId === toolCallId) {
|
|
2410
|
-
pendingFrontendTool = null;
|
|
2411
|
-
}
|
|
2412
|
-
break;
|
|
2413
|
-
}
|
|
2414
|
-
case AG_UI_EVENT.CUSTOM: {
|
|
2415
|
-
const name = this.getStringField(data, "name");
|
|
2416
|
-
if (name === "mcpstack.budget_snapshot") {
|
|
2417
|
-
const value = data.value;
|
|
2418
|
-
if (value && typeof value === "object") {
|
|
2419
|
-
this.budgetSnapshot = value;
|
|
2420
|
-
this.emit("budget_snapshot", this.budgetSnapshot);
|
|
2421
|
-
}
|
|
2422
|
-
}
|
|
2423
|
-
break;
|
|
2424
|
-
}
|
|
2425
|
-
case AG_UI_EVENT.RUN_FINISHED: {
|
|
2426
|
-
const result = this.getRecordField(data, "result");
|
|
2427
|
-
const conversationId = result ? this.getStringField(result, "conversationId") : void 0;
|
|
2428
|
-
if (conversationId) {
|
|
2429
|
-
this.conversationId = conversationId;
|
|
2430
|
-
}
|
|
2431
|
-
if (pendingFrontendTool) {
|
|
2432
|
-
return { type: "frontend_tool", data: pendingFrontendTool };
|
|
2433
|
-
}
|
|
2434
|
-
flushAssistantMessage();
|
|
2435
|
-
const messageEnd2 = {
|
|
2436
|
-
inputTokens: this.getNumberField(result, "inputTokens") ?? 0,
|
|
2437
|
-
outputTokens: this.getNumberField(result, "outputTokens") ?? 0,
|
|
2438
|
-
toolCalls: this.getNumberField(result, "toolCalls") ?? toolCalls.size
|
|
2439
|
-
};
|
|
2440
|
-
this.emit("message_end", messageEnd2);
|
|
2441
|
-
return { type: "done" };
|
|
2442
|
-
}
|
|
2443
|
-
case AG_UI_EVENT.RUN_ERROR: {
|
|
2444
|
-
const error = {
|
|
2445
|
-
code: this.getStringField(data, "code") ?? "run_error",
|
|
2446
|
-
message: this.getStringField(data, "message") ?? "Agent run failed."
|
|
2447
|
-
};
|
|
2448
|
-
const errorMsg = {
|
|
2449
|
-
id: crypto.randomUUID(),
|
|
2450
|
-
role: "error",
|
|
2451
|
-
content: error.message,
|
|
2452
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
2453
|
-
errorCode: error.code
|
|
2454
|
-
};
|
|
2455
|
-
this.messages.push(errorMsg);
|
|
2456
|
-
this.emit("message", errorMsg);
|
|
2457
|
-
this.emit("error", error);
|
|
2458
|
-
return { type: "error", data: error };
|
|
2459
|
-
}
|
|
2460
|
-
}
|
|
2461
|
-
}
|
|
2462
|
-
flushAssistantMessage();
|
|
2463
|
-
const messageEnd = {
|
|
2464
|
-
inputTokens: 0,
|
|
2465
|
-
outputTokens: 0,
|
|
2466
|
-
toolCalls: toolCalls.size
|
|
2467
|
-
};
|
|
2468
|
-
this.emit("message_end", messageEnd);
|
|
2469
|
-
return { type: "done" };
|
|
2470
|
-
}
|
|
2471
|
-
recordToolResult(toolCall, result, duration) {
|
|
2472
|
-
const toolCallMsg = this.messages.find(
|
|
2473
|
-
(m) => m.role === "tool_call" && m.toolCallId === toolCall.toolCallId
|
|
2474
|
-
);
|
|
2475
|
-
if (toolCallMsg) {
|
|
2476
|
-
toolCallMsg.toolCallStatus = "completed";
|
|
2477
|
-
toolCallMsg.toolCallDuration = duration;
|
|
2478
|
-
toolCallMsg.toolResult = this.serializeToolContent(result);
|
|
2479
|
-
}
|
|
2480
|
-
this.emit("tool_result", { toolCallId: toolCall.toolCallId, result, duration });
|
|
2481
|
-
const toolResultMsg = {
|
|
2482
|
-
id: crypto.randomUUID(),
|
|
2483
|
-
role: "tool_result",
|
|
2484
|
-
content: this.serializeToolContent(result),
|
|
2485
|
-
toolCallId: toolCall.toolCallId,
|
|
2486
|
-
toolName: toolCall.toolName,
|
|
2487
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
2488
|
-
};
|
|
2489
|
-
this.messages.push(toolResultMsg);
|
|
2490
|
-
}
|
|
2491
|
-
recordToolError(toolCall, error, resultContent, duration) {
|
|
2492
|
-
const toolCallMsg = this.messages.find(
|
|
2493
|
-
(m) => m.role === "tool_call" && m.toolCallId === toolCall.toolCallId
|
|
2494
|
-
);
|
|
2495
|
-
if (toolCallMsg) {
|
|
2496
|
-
toolCallMsg.toolCallStatus = "error";
|
|
2497
|
-
toolCallMsg.toolCallDuration = duration;
|
|
2498
|
-
toolCallMsg.toolError = error;
|
|
2499
|
-
}
|
|
2500
|
-
this.emit("tool_error", { toolCallId: toolCall.toolCallId, error, duration });
|
|
2501
|
-
const toolResultMsg = {
|
|
2502
|
-
id: crypto.randomUUID(),
|
|
2503
|
-
role: "tool_result",
|
|
2504
|
-
content: resultContent,
|
|
2505
|
-
toolCallId: toolCall.toolCallId,
|
|
2506
|
-
toolName: toolCall.toolName,
|
|
2507
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
2508
|
-
};
|
|
2509
|
-
this.messages.push(toolResultMsg);
|
|
2510
|
-
}
|
|
2511
|
-
serializeToolContent(result) {
|
|
2512
|
-
if (result == null) {
|
|
2513
|
-
return "";
|
|
2514
|
-
}
|
|
2515
|
-
return typeof result === "string" ? result : JSON.stringify(result);
|
|
2516
|
-
}
|
|
2517
|
-
parseToolContent(content) {
|
|
2518
|
-
if (!content) {
|
|
2519
|
-
return "";
|
|
2520
|
-
}
|
|
2521
|
-
try {
|
|
2522
|
-
return JSON.parse(content);
|
|
2523
|
-
} catch {
|
|
2524
|
-
return content;
|
|
2525
|
-
}
|
|
2526
|
-
}
|
|
2527
|
-
parseToolArguments(argumentsJson) {
|
|
2528
|
-
if (!argumentsJson.trim()) {
|
|
2529
|
-
return {};
|
|
2530
|
-
}
|
|
2531
|
-
try {
|
|
2532
|
-
const parsed = JSON.parse(argumentsJson);
|
|
2533
|
-
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
2534
|
-
} catch {
|
|
2535
|
-
return {};
|
|
2536
|
-
}
|
|
2537
|
-
}
|
|
2538
|
-
getRecordField(record, key) {
|
|
2539
|
-
const value = record?.[key];
|
|
2540
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
2541
|
-
}
|
|
2542
|
-
getStringField(record, key) {
|
|
2543
|
-
const value = record?.[key];
|
|
2544
|
-
return typeof value === "string" && value ? value : void 0;
|
|
2545
|
-
}
|
|
2546
|
-
getNumberField(record, key) {
|
|
2547
|
-
const value = record?.[key];
|
|
2548
|
-
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
2549
|
-
}
|
|
2550
2242
|
async fetchConversationMessages(conversationId, cursor, pageSize = 50) {
|
|
2551
2243
|
const token = await this.resolveAuthToken();
|
|
2552
2244
|
const params = new URLSearchParams();
|
|
@@ -2594,7 +2286,7 @@ var McpStackAgent = class {
|
|
|
2594
2286
|
};
|
|
2595
2287
|
}
|
|
2596
2288
|
/**
|
|
2597
|
-
* Process
|
|
2289
|
+
* Process an SSE stream from the chat API.
|
|
2598
2290
|
* Returns when the stream ends (either message_end or tool_call).
|
|
2599
2291
|
*/
|
|
2600
2292
|
async processSseStream(response) {
|