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