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