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