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