@wingman-ai/gateway 0.2.5 → 0.3.1
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 +9 -0
- package/dist/agent/config/agentConfig.cjs +12 -0
- package/dist/agent/config/agentConfig.d.ts +26 -0
- package/dist/agent/config/agentConfig.js +10 -1
- package/dist/agent/config/agentLoader.cjs +9 -0
- package/dist/agent/config/agentLoader.js +9 -0
- package/dist/agent/config/mcpClientManager.cjs +44 -10
- package/dist/agent/config/mcpClientManager.d.ts +6 -2
- package/dist/agent/config/mcpClientManager.js +44 -10
- package/dist/agent/config/toolRegistry.cjs +20 -1
- package/dist/agent/config/toolRegistry.d.ts +15 -0
- package/dist/agent/config/toolRegistry.js +20 -1
- package/dist/agent/tests/agentConfig.test.cjs +6 -1
- package/dist/agent/tests/agentConfig.test.js +6 -1
- package/dist/agent/tests/browserControlHelpers.test.cjs +35 -0
- package/dist/agent/tests/browserControlHelpers.test.d.ts +1 -0
- package/dist/agent/tests/browserControlHelpers.test.js +29 -0
- package/dist/agent/tests/browserControlTool.test.cjs +2117 -0
- package/dist/agent/tests/browserControlTool.test.d.ts +1 -0
- package/dist/agent/tests/browserControlTool.test.js +2111 -0
- package/dist/agent/tests/mcpClientManager.test.cjs +124 -0
- package/dist/agent/tests/mcpClientManager.test.d.ts +1 -0
- package/dist/agent/tests/mcpClientManager.test.js +118 -0
- package/dist/agent/tests/toolRegistry.test.cjs +6 -0
- package/dist/agent/tests/toolRegistry.test.js +6 -0
- package/dist/agent/tools/browser_control.cjs +1282 -0
- package/dist/agent/tools/browser_control.d.ts +478 -0
- package/dist/agent/tools/browser_control.js +1242 -0
- package/dist/agent/tools/command_execute.cjs +1 -1
- package/dist/agent/tools/command_execute.js +1 -1
- package/dist/cli/commands/agent.cjs +16 -2
- package/dist/cli/commands/agent.js +16 -2
- package/dist/cli/commands/browser.cjs +603 -0
- package/dist/cli/commands/browser.d.ts +13 -0
- package/dist/cli/commands/browser.js +566 -0
- package/dist/cli/commands/gateway.cjs +18 -7
- package/dist/cli/commands/gateway.d.ts +5 -1
- package/dist/cli/commands/gateway.js +18 -7
- package/dist/cli/commands/init.cjs +134 -45
- package/dist/cli/commands/init.js +134 -45
- package/dist/cli/commands/skill.cjs +3 -2
- package/dist/cli/commands/skill.js +3 -2
- package/dist/cli/config/loader.cjs +15 -0
- package/dist/cli/config/loader.js +15 -0
- package/dist/cli/config/schema.cjs +51 -2
- package/dist/cli/config/schema.d.ts +51 -0
- package/dist/cli/config/schema.js +44 -1
- package/dist/cli/core/agentInvoker.cjs +55 -66
- package/dist/cli/core/agentInvoker.d.ts +10 -13
- package/dist/cli/core/agentInvoker.js +42 -62
- package/dist/cli/core/imagePersistence.cjs +125 -0
- package/dist/cli/core/imagePersistence.d.ts +24 -0
- package/dist/cli/core/imagePersistence.js +85 -0
- package/dist/cli/core/sessionManager.cjs +297 -40
- package/dist/cli/core/sessionManager.d.ts +9 -0
- package/dist/cli/core/sessionManager.js +297 -40
- package/dist/cli/core/workspace.cjs +89 -0
- package/dist/cli/core/workspace.d.ts +1 -0
- package/dist/cli/core/workspace.js +55 -0
- package/dist/cli/index.cjs +53 -5
- package/dist/cli/index.js +53 -5
- package/dist/cli/types/browser.cjs +18 -0
- package/dist/cli/types/browser.d.ts +9 -0
- package/dist/cli/types/browser.js +0 -0
- package/dist/debug/terminalProbe.cjs +57 -0
- package/dist/debug/terminalProbe.d.ts +10 -0
- package/dist/debug/terminalProbe.js +20 -0
- package/dist/debug/terminalProbeAuth.cjs +140 -0
- package/dist/debug/terminalProbeAuth.d.ts +20 -0
- package/dist/debug/terminalProbeAuth.js +97 -0
- package/dist/gateway/browserRelayServer.cjs +338 -0
- package/dist/gateway/browserRelayServer.d.ts +38 -0
- package/dist/gateway/browserRelayServer.js +301 -0
- package/dist/gateway/http/agents.cjs +22 -0
- package/dist/gateway/http/agents.js +22 -0
- package/dist/gateway/http/fs.cjs +76 -0
- package/dist/gateway/http/fs.js +77 -1
- package/dist/gateway/http/sessions.cjs +25 -5
- package/dist/gateway/http/sessions.js +25 -5
- package/dist/gateway/server.cjs +155 -17
- package/dist/gateway/server.d.ts +6 -1
- package/dist/gateway/server.js +148 -16
- package/dist/gateway/transport/websocket.cjs +45 -10
- package/dist/gateway/transport/websocket.d.ts +1 -0
- package/dist/gateway/transport/websocket.js +41 -9
- package/dist/gateway/types.d.ts +4 -0
- package/dist/tests/agentInvokerSummarization.test.cjs +56 -37
- package/dist/tests/agentInvokerSummarization.test.js +58 -39
- package/dist/tests/agentInvokerWorkdir.test.cjs +50 -0
- package/dist/tests/agentInvokerWorkdir.test.js +52 -2
- package/dist/tests/agents-api.test.cjs +52 -0
- package/dist/tests/agents-api.test.js +53 -1
- package/dist/tests/browser-command.test.cjs +264 -0
- package/dist/tests/browser-command.test.d.ts +1 -0
- package/dist/tests/browser-command.test.js +258 -0
- package/dist/tests/browser-relay-server.test.cjs +20 -0
- package/dist/tests/browser-relay-server.test.d.ts +1 -0
- package/dist/tests/browser-relay-server.test.js +14 -0
- package/dist/tests/cli-config-loader.test.cjs +43 -0
- package/dist/tests/cli-config-loader.test.js +43 -0
- package/dist/tests/cli-init.test.cjs +61 -2
- package/dist/tests/cli-init.test.js +61 -2
- package/dist/tests/cli-workspace-root.test.cjs +114 -0
- package/dist/tests/cli-workspace-root.test.d.ts +1 -0
- package/dist/tests/cli-workspace-root.test.js +108 -0
- package/dist/tests/falRuntime.test.cjs +78 -0
- package/dist/tests/falRuntime.test.d.ts +1 -0
- package/dist/tests/falRuntime.test.js +72 -0
- package/dist/tests/falSummary.test.cjs +51 -0
- package/dist/tests/falSummary.test.d.ts +1 -0
- package/dist/tests/falSummary.test.js +45 -0
- package/dist/tests/fs-api.test.cjs +138 -0
- package/dist/tests/fs-api.test.d.ts +1 -0
- package/dist/tests/fs-api.test.js +132 -0
- package/dist/tests/gateway-command-workspace.test.cjs +150 -0
- package/dist/tests/gateway-command-workspace.test.d.ts +1 -0
- package/dist/tests/gateway-command-workspace.test.js +144 -0
- package/dist/tests/gateway-request-execution-overrides.test.cjs +42 -0
- package/dist/tests/gateway-request-execution-overrides.test.d.ts +1 -0
- package/dist/tests/gateway-request-execution-overrides.test.js +36 -0
- package/dist/tests/gateway.test.cjs +140 -1
- package/dist/tests/gateway.test.js +140 -1
- package/dist/tests/imagePersistence.test.cjs +143 -0
- package/dist/tests/imagePersistence.test.d.ts +1 -0
- package/dist/tests/imagePersistence.test.js +137 -0
- package/dist/tests/sessionMessageAttachments.test.cjs +30 -0
- package/dist/tests/sessionMessageAttachments.test.js +30 -0
- package/dist/tests/sessionStateMessages.test.cjs +126 -0
- package/dist/tests/sessionStateMessages.test.js +126 -0
- package/dist/tests/sessions-api.test.cjs +117 -3
- package/dist/tests/sessions-api.test.js +118 -4
- package/dist/tests/terminalProbe.test.cjs +45 -0
- package/dist/tests/terminalProbe.test.d.ts +1 -0
- package/dist/tests/terminalProbe.test.js +39 -0
- package/dist/tests/terminalProbeAuth.test.cjs +85 -0
- package/dist/tests/terminalProbeAuth.test.d.ts +1 -0
- package/dist/tests/terminalProbeAuth.test.js +79 -0
- package/dist/tests/websocket-transport.test.cjs +31 -0
- package/dist/tests/websocket-transport.test.d.ts +1 -0
- package/dist/tests/websocket-transport.test.js +25 -0
- package/dist/tools/fal/runtime.cjs +103 -0
- package/dist/tools/fal/runtime.d.ts +10 -0
- package/dist/tools/fal/runtime.js +60 -0
- package/dist/tools/fal/summary.cjs +78 -0
- package/dist/tools/fal/summary.d.ts +22 -0
- package/dist/tools/fal/summary.js +41 -0
- package/dist/tools/mcp-fal-ai.cjs +1041 -0
- package/dist/tools/mcp-fal-ai.d.ts +1 -0
- package/dist/tools/mcp-fal-ai.js +1025 -0
- package/dist/types/mcp.cjs +2 -0
- package/dist/types/mcp.d.ts +8 -0
- package/dist/types/mcp.js +3 -1
- package/dist/webui/assets/index-BW9nM0J2.css +11 -0
- package/dist/webui/assets/index-C8-oboEC.js +278 -0
- package/dist/webui/index.html +2 -2
- package/extensions/wingman-browser-extension/README.md +27 -0
- package/extensions/wingman-browser-extension/background.js +416 -0
- package/extensions/wingman-browser-extension/manifest.json +19 -0
- package/extensions/wingman-browser-extension/options.html +156 -0
- package/extensions/wingman-browser-extension/options.js +106 -0
- package/package.json +18 -13
- package/{.wingman → templates}/agents/README.md +2 -1
- package/{.wingman → templates}/agents/coding/agent.md +5 -1
- package/{.wingman → templates}/agents/coding-v2/agent.md +58 -1
- package/templates/agents/game-dev/agent.md +101 -0
- package/templates/agents/game-dev/art-generation.md +38 -0
- package/templates/agents/game-dev/asset-refinement.md +17 -0
- package/templates/agents/game-dev/planning-idea.md +17 -0
- package/templates/agents/game-dev/ui-specialist.md +17 -0
- package/templates/agents/main/agent.md +29 -0
- package/{.wingman → templates}/agents/researcher/agent.md +9 -0
- package/{.wingman → templates}/agents/stock-trader/agent.md +1 -0
- package/.wingman/agents/main/agent.md +0 -22
- package/dist/webui/assets/index-C7EuTbnE.js +0 -270
- package/dist/webui/assets/index-DVWQluit.css +0 -11
- /package/{.wingman → templates}/agents/coding-v2/implementor.md +0 -0
- /package/{.wingman → templates}/agents/stock-trader/chain-curator.md +0 -0
- /package/{.wingman → templates}/agents/stock-trader/goal-translator.md +0 -0
- /package/{.wingman → templates}/agents/stock-trader/guardrails-veto.md +0 -0
- /package/{.wingman → templates}/agents/stock-trader/path-planner.md +0 -0
- /package/{.wingman → templates}/agents/stock-trader/regime-analyst.md +0 -0
- /package/{.wingman → templates}/agents/stock-trader/risk.md +0 -0
- /package/{.wingman → templates}/agents/stock-trader/selection.md +0 -0
- /package/{.wingman → templates}/agents/stock-trader/strategy-composer.md +0 -0
package/dist/gateway/server.js
CHANGED
|
@@ -10,6 +10,7 @@ import { SessionManager } from "../cli/core/sessionManager.js";
|
|
|
10
10
|
import { createLogger } from "../logger.js";
|
|
11
11
|
import { DiscordGatewayAdapter } from "./adapters/discord.js";
|
|
12
12
|
import { GatewayAuth } from "./auth.js";
|
|
13
|
+
import { BrowserRelayServer } from "./browserRelayServer.js";
|
|
13
14
|
import { BroadcastGroupManager } from "./broadcast.js";
|
|
14
15
|
import { MDNSDiscoveryService, TailscaleDiscoveryService } from "./discovery/index.js";
|
|
15
16
|
import { getGatewayTokenFromEnv } from "./env.js";
|
|
@@ -49,6 +50,19 @@ function withApiCors(response) {
|
|
|
49
50
|
headers
|
|
50
51
|
});
|
|
51
52
|
}
|
|
53
|
+
function resolveExecutionWorkspaceOverride(payload) {
|
|
54
|
+
const rawWorkspace = payload?.execution?.workspace;
|
|
55
|
+
if ("string" != typeof rawWorkspace) return null;
|
|
56
|
+
const trimmed = rawWorkspace.trim();
|
|
57
|
+
if (!trimmed || !isAbsolute(trimmed)) return null;
|
|
58
|
+
return normalize(trimmed);
|
|
59
|
+
}
|
|
60
|
+
function resolveExecutionConfigDirOverride(payload) {
|
|
61
|
+
const rawConfigDir = payload?.execution?.configDir;
|
|
62
|
+
if ("string" != typeof rawConfigDir) return null;
|
|
63
|
+
const trimmed = rawConfigDir.trim();
|
|
64
|
+
return trimmed || null;
|
|
65
|
+
}
|
|
52
66
|
class GatewayServer {
|
|
53
67
|
async start() {
|
|
54
68
|
if (void 0 === globalThis.Bun) throw new Error("Gateway server requires Bun runtime. Start with `bun ./bin/wingman gateway start`.");
|
|
@@ -106,6 +120,7 @@ class GatewayServer {
|
|
|
106
120
|
if (!this.uiDistDir) this.log("warn", "Control UI is enabled but build assets were not found. Run `bun run webui:build`.");
|
|
107
121
|
this.log("info", `Control UI available on ${this.config.host}:${this.config.port}`);
|
|
108
122
|
}
|
|
123
|
+
this.browserRelayServer?.start();
|
|
109
124
|
if (this.config.discovery?.enabled) await this.startDiscovery();
|
|
110
125
|
await this.startAdapters();
|
|
111
126
|
this.log("info", `Gateway started on ${this.config.host}:${this.config.port}`);
|
|
@@ -134,6 +149,7 @@ class GatewayServer {
|
|
|
134
149
|
this.uiServer.stop();
|
|
135
150
|
this.uiServer = null;
|
|
136
151
|
}
|
|
152
|
+
if (this.browserRelayServer) this.browserRelayServer.stop();
|
|
137
153
|
this.terminalSessionManager.dispose();
|
|
138
154
|
this.log("info", "Gateway stopped");
|
|
139
155
|
}
|
|
@@ -326,6 +342,8 @@ class GatewayServer {
|
|
|
326
342
|
const payload = msg.payload;
|
|
327
343
|
const content = "string" == typeof payload?.content ? payload.content : "";
|
|
328
344
|
const attachments = Array.isArray(payload?.attachments) ? payload.attachments : [];
|
|
345
|
+
const workspaceOverride = resolveExecutionWorkspaceOverride(payload);
|
|
346
|
+
const configDirOverride = resolveExecutionConfigDirOverride(payload);
|
|
329
347
|
const hasContent = content.trim().length > 0;
|
|
330
348
|
const hasAttachments = attachments.length > 0;
|
|
331
349
|
if (!hasContent && !hasAttachments) return void this.sendAgentError(ws, msg.id, "Missing agent content");
|
|
@@ -336,12 +354,29 @@ class GatewayServer {
|
|
|
336
354
|
const sessionManager = await this.getSessionManager(agentId);
|
|
337
355
|
const existingSession = sessionManager.getSession(sessionKey);
|
|
338
356
|
const session = existingSession || sessionManager.getOrCreateSession(sessionKey, agentId);
|
|
357
|
+
const requestId = msg.id || `req-${Date.now()}`;
|
|
339
358
|
const workdir = session.metadata?.workdir ?? null;
|
|
340
359
|
const defaultOutputDir = this.resolveDefaultOutputDir(agentId);
|
|
341
360
|
const preview = hasContent ? content.trim() : buildAttachmentPreview(attachments);
|
|
342
361
|
sessionManager.updateSession(session.id, {
|
|
362
|
+
messageCount: (session.messageCount ?? 0) + 1,
|
|
343
363
|
lastMessagePreview: preview.substring(0, 200)
|
|
344
364
|
});
|
|
365
|
+
try {
|
|
366
|
+
sessionManager.persistPendingMessage({
|
|
367
|
+
sessionId: sessionKey,
|
|
368
|
+
requestId,
|
|
369
|
+
message: {
|
|
370
|
+
id: `user-${requestId}`,
|
|
371
|
+
role: "user",
|
|
372
|
+
content,
|
|
373
|
+
attachments: attachments.length > 0 ? mapAttachmentsForPendingMessage(attachments) : void 0,
|
|
374
|
+
createdAt: Date.now()
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
} catch (error) {
|
|
378
|
+
this.logger.warn("Failed to persist pending user message", error);
|
|
379
|
+
}
|
|
345
380
|
if (!existingSession) this.internalHooks?.emit({
|
|
346
381
|
type: "session",
|
|
347
382
|
action: "start",
|
|
@@ -394,7 +429,9 @@ class GatewayServer {
|
|
|
394
429
|
attachments,
|
|
395
430
|
sessionManager,
|
|
396
431
|
workdir,
|
|
397
|
-
defaultOutputDir
|
|
432
|
+
defaultOutputDir,
|
|
433
|
+
workspaceOverride,
|
|
434
|
+
configDirOverride
|
|
398
435
|
};
|
|
399
436
|
this.requestSessionKeys.set(msg.id, sessionQueueKey);
|
|
400
437
|
const queueIfBusy = false !== payload.queueIfBusy;
|
|
@@ -440,13 +477,19 @@ class GatewayServer {
|
|
|
440
477
|
this.executeAgentRequest(request);
|
|
441
478
|
}
|
|
442
479
|
async executeAgentRequest(request) {
|
|
443
|
-
const { ws, msg, agentId, sessionKey, sessionQueueKey, content, attachments, sessionManager, workdir, defaultOutputDir } = request;
|
|
480
|
+
const { ws, msg, agentId, sessionKey, sessionQueueKey, content, attachments, sessionManager, workdir, defaultOutputDir, workspaceOverride, configDirOverride } = request;
|
|
444
481
|
this.activeSessionRequests.set(sessionQueueKey, msg.id);
|
|
445
482
|
const outputManager = new OutputManager("interactive");
|
|
446
483
|
let emittedAgentError = false;
|
|
484
|
+
let streamedCompletionResult;
|
|
447
485
|
const outputHandler = (event)=>{
|
|
448
486
|
const payloadWithSession = this.attachSessionContext(event, sessionKey, agentId);
|
|
449
|
-
|
|
487
|
+
const payloadType = payloadWithSession && "object" == typeof payloadWithSession && !Array.isArray(payloadWithSession) && "string" == typeof payloadWithSession.type ? payloadWithSession.type : "";
|
|
488
|
+
if ("agent-complete" === payloadType) {
|
|
489
|
+
if (payloadWithSession && "object" == typeof payloadWithSession && !Array.isArray(payloadWithSession)) streamedCompletionResult = payloadWithSession.result;
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
if ("agent-error" === payloadType) emittedAgentError = true;
|
|
450
493
|
const baseMessage = {
|
|
451
494
|
type: "event:agent",
|
|
452
495
|
id: msg.id,
|
|
@@ -460,10 +503,11 @@ class GatewayServer {
|
|
|
460
503
|
this.broadcastSessionEvent(sessionKey, baseMessage, ws);
|
|
461
504
|
};
|
|
462
505
|
outputManager.on("output-event", outputHandler);
|
|
463
|
-
const workspace = this.resolveAgentWorkspace(agentId);
|
|
506
|
+
const workspace = workspaceOverride || this.resolveAgentWorkspace(agentId);
|
|
507
|
+
const configDir = configDirOverride || this.configDir;
|
|
464
508
|
const invoker = new AgentInvoker({
|
|
465
509
|
workspace,
|
|
466
|
-
configDir
|
|
510
|
+
configDir,
|
|
467
511
|
outputManager,
|
|
468
512
|
logger: this.logger,
|
|
469
513
|
sessionManager,
|
|
@@ -477,17 +521,43 @@ class GatewayServer {
|
|
|
477
521
|
abortController
|
|
478
522
|
});
|
|
479
523
|
try {
|
|
480
|
-
await invoker.invokeAgent(agentId, content, sessionKey, attachments, {
|
|
524
|
+
const invocationResult = await invoker.invokeAgent(agentId, content, sessionKey, attachments, {
|
|
481
525
|
signal: abortController.signal
|
|
482
526
|
});
|
|
483
|
-
|
|
484
|
-
if (
|
|
485
|
-
|
|
527
|
+
if (msg.id) sessionManager.clearPendingMessagesForRequest(sessionKey, msg.id);
|
|
528
|
+
if (emittedAgentError) return;
|
|
529
|
+
const invocationCancelled = abortController.signal.aborted || "object" == typeof invocationResult && null !== invocationResult && !Array.isArray(invocationResult) && true === invocationResult.cancelled;
|
|
530
|
+
if (invocationCancelled) return void this.sendAgentError(ws, msg.id, "Request cancelled", {
|
|
531
|
+
sessionId: sessionKey,
|
|
532
|
+
agentId,
|
|
533
|
+
broadcastToSession: true,
|
|
534
|
+
exclude: ws
|
|
535
|
+
});
|
|
536
|
+
const completionResult = void 0 === streamedCompletionResult ? invocationResult : streamedCompletionResult;
|
|
537
|
+
this.sendAgentComplete(ws, msg.id, completionResult, {
|
|
538
|
+
sessionId: sessionKey,
|
|
539
|
+
agentId,
|
|
540
|
+
broadcastToSession: true,
|
|
541
|
+
exclude: ws
|
|
486
542
|
});
|
|
487
543
|
} catch (error) {
|
|
488
544
|
this.logger.error("Agent invocation failed", error);
|
|
545
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
546
|
+
if (msg.id) try {
|
|
547
|
+
sessionManager.persistPendingMessage({
|
|
548
|
+
sessionId: sessionKey,
|
|
549
|
+
requestId: msg.id,
|
|
550
|
+
message: {
|
|
551
|
+
id: msg.id,
|
|
552
|
+
role: "assistant",
|
|
553
|
+
content: message,
|
|
554
|
+
createdAt: Date.now()
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
} catch (persistError) {
|
|
558
|
+
this.logger.warn("Failed to persist pending assistant error message", persistError);
|
|
559
|
+
}
|
|
489
560
|
if (!emittedAgentError) {
|
|
490
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
491
561
|
const stack = error instanceof Error ? error.stack : void 0;
|
|
492
562
|
this.sendAgentError(ws, msg.id, message, {
|
|
493
563
|
sessionId: sessionKey,
|
|
@@ -563,6 +633,12 @@ class GatewayServer {
|
|
|
563
633
|
},
|
|
564
634
|
timestamp: Date.now()
|
|
565
635
|
});
|
|
636
|
+
this.sendAgentError(ws, requestId, "Request cancelled", {
|
|
637
|
+
sessionId: queued.sessionKey,
|
|
638
|
+
agentId: queued.agentId,
|
|
639
|
+
broadcastToSession: true,
|
|
640
|
+
exclude: ws
|
|
641
|
+
});
|
|
566
642
|
return;
|
|
567
643
|
}
|
|
568
644
|
this.sendMessage(ws, {
|
|
@@ -737,11 +813,25 @@ class GatewayServer {
|
|
|
737
813
|
}
|
|
738
814
|
sendMessage(ws, message) {
|
|
739
815
|
try {
|
|
740
|
-
ws.send(JSON.stringify(message));
|
|
816
|
+
const result = ws.send(JSON.stringify(message));
|
|
817
|
+
if ("number" == typeof result && result <= 0) return false;
|
|
818
|
+
return true;
|
|
741
819
|
} catch (error) {
|
|
742
820
|
this.log("error", "Failed to send message", error);
|
|
821
|
+
return false;
|
|
743
822
|
}
|
|
744
823
|
}
|
|
824
|
+
sendMessageWithRetry(ws, message, attempt = 0) {
|
|
825
|
+
if (this.sendMessage(ws, message)) return;
|
|
826
|
+
if (attempt >= 2) return void this.log("warn", "Dropping websocket message after retry attempts", {
|
|
827
|
+
type: message.type,
|
|
828
|
+
id: message.id
|
|
829
|
+
});
|
|
830
|
+
const delayMs = 25 * (attempt + 1);
|
|
831
|
+
setTimeout(()=>{
|
|
832
|
+
this.sendMessageWithRetry(ws, message, attempt + 1);
|
|
833
|
+
}, delayMs);
|
|
834
|
+
}
|
|
745
835
|
sendError(ws, code, message) {
|
|
746
836
|
const errorPayload = {
|
|
747
837
|
code,
|
|
@@ -753,6 +843,25 @@ class GatewayServer {
|
|
|
753
843
|
timestamp: Date.now()
|
|
754
844
|
});
|
|
755
845
|
}
|
|
846
|
+
sendAgentComplete(ws, requestId, result, options) {
|
|
847
|
+
let payload = {
|
|
848
|
+
type: "agent-complete",
|
|
849
|
+
result: result ?? null,
|
|
850
|
+
timestamp: new Date().toISOString()
|
|
851
|
+
};
|
|
852
|
+
if (options?.sessionId && options?.agentId) payload = this.attachSessionContext(payload, options.sessionId, options.agentId);
|
|
853
|
+
const baseMessage = {
|
|
854
|
+
type: "event:agent",
|
|
855
|
+
id: requestId,
|
|
856
|
+
payload,
|
|
857
|
+
timestamp: Date.now()
|
|
858
|
+
};
|
|
859
|
+
this.sendMessageWithRetry(ws, {
|
|
860
|
+
...baseMessage,
|
|
861
|
+
clientId: ws.data.clientId
|
|
862
|
+
});
|
|
863
|
+
if (options?.broadcastToSession && options.sessionId) this.broadcastSessionEvent(options.sessionId, baseMessage, options.exclude, true);
|
|
864
|
+
}
|
|
756
865
|
sendAgentError(ws, requestId, message, options) {
|
|
757
866
|
let payload = {
|
|
758
867
|
type: "agent-error",
|
|
@@ -767,11 +876,11 @@ class GatewayServer {
|
|
|
767
876
|
payload,
|
|
768
877
|
timestamp: Date.now()
|
|
769
878
|
};
|
|
770
|
-
this.
|
|
879
|
+
this.sendMessageWithRetry(ws, {
|
|
771
880
|
...baseMessage,
|
|
772
881
|
clientId: ws.data.clientId
|
|
773
882
|
});
|
|
774
|
-
if (options?.broadcastToSession && options.sessionId) this.broadcastSessionEvent(options.sessionId, baseMessage, options.exclude);
|
|
883
|
+
if (options?.broadcastToSession && options.sessionId) this.broadcastSessionEvent(options.sessionId, baseMessage, options.exclude, true);
|
|
775
884
|
}
|
|
776
885
|
cancelSocketAgentRequests(ws) {
|
|
777
886
|
for (const [requestId, active] of this.activeAgentRequests)if (active.socket === ws) {
|
|
@@ -800,12 +909,13 @@ class GatewayServer {
|
|
|
800
909
|
agentId
|
|
801
910
|
};
|
|
802
911
|
}
|
|
803
|
-
broadcastSessionEvent(sessionId, message, exclude) {
|
|
912
|
+
broadcastSessionEvent(sessionId, message, exclude, reliable = false) {
|
|
804
913
|
const subscribers = this.sessionSubscriptions.get(sessionId);
|
|
805
914
|
if (!subscribers || 0 === subscribers.size) return 0;
|
|
806
915
|
let sent = 0;
|
|
807
916
|
for (const ws of subscribers)if (!exclude || ws !== exclude) {
|
|
808
|
-
this.
|
|
917
|
+
if (reliable) this.sendMessageWithRetry(ws, message);
|
|
918
|
+
else this.sendMessage(ws, message);
|
|
809
919
|
sent++;
|
|
810
920
|
}
|
|
811
921
|
return sent;
|
|
@@ -1294,6 +1404,7 @@ class GatewayServer {
|
|
|
1294
1404
|
_define_property(this, "controlUiPort", 18790);
|
|
1295
1405
|
_define_property(this, "controlUiSamePort", false);
|
|
1296
1406
|
_define_property(this, "uiDistDir", null);
|
|
1407
|
+
_define_property(this, "browserRelayServer", null);
|
|
1297
1408
|
_define_property(this, "webhookStore", void 0);
|
|
1298
1409
|
_define_property(this, "routineStore", void 0);
|
|
1299
1410
|
_define_property(this, "internalHooks", null);
|
|
@@ -1356,6 +1467,15 @@ class GatewayServer {
|
|
|
1356
1467
|
this.controlUiPort = controlUi?.port || 18790;
|
|
1357
1468
|
this.controlUiSamePort = this.controlUiEnabled && this.controlUiPort === this.config.port;
|
|
1358
1469
|
this.uiDistDir = this.controlUiEnabled ? this.resolveControlUiDir() : null;
|
|
1470
|
+
const relayConfig = this.wingmanConfig.browser?.relay;
|
|
1471
|
+
if (relayConfig?.enabled) this.browserRelayServer = new BrowserRelayServer({
|
|
1472
|
+
enabled: relayConfig.enabled,
|
|
1473
|
+
host: relayConfig.host || "127.0.0.1",
|
|
1474
|
+
port: relayConfig.port || 18792,
|
|
1475
|
+
requireAuth: relayConfig.requireAuth ?? true,
|
|
1476
|
+
authToken: relayConfig.authToken,
|
|
1477
|
+
maxMessageBytes: relayConfig.maxMessageBytes || 262144
|
|
1478
|
+
}, this.logger);
|
|
1359
1479
|
this.terminalSessionManager = new TerminalSessionManager();
|
|
1360
1480
|
}
|
|
1361
1481
|
}
|
|
@@ -1379,6 +1499,18 @@ function buildAttachmentPreview(attachments) {
|
|
|
1379
1499
|
if (hasAudio) return count > 1 ? "Audio attachments" : "Audio attachment";
|
|
1380
1500
|
return count > 1 ? "Image attachments" : "Image attachment";
|
|
1381
1501
|
}
|
|
1502
|
+
function mapAttachmentsForPendingMessage(attachments) {
|
|
1503
|
+
return attachments.map((attachment)=>{
|
|
1504
|
+
const kind = isFileAttachment(attachment) ? "file" : isAudioAttachment(attachment) ? "audio" : "image";
|
|
1505
|
+
return {
|
|
1506
|
+
kind,
|
|
1507
|
+
dataUrl: attachment.dataUrl,
|
|
1508
|
+
name: attachment.name,
|
|
1509
|
+
mimeType: attachment.mimeType,
|
|
1510
|
+
size: attachment.size
|
|
1511
|
+
};
|
|
1512
|
+
});
|
|
1513
|
+
}
|
|
1382
1514
|
function isAudioAttachment(attachment) {
|
|
1383
1515
|
if ("audio" === attachment.kind) return true;
|
|
1384
1516
|
if (attachment.mimeType?.startsWith("audio/")) return true;
|
|
@@ -1389,4 +1521,4 @@ function isFileAttachment(attachment) {
|
|
|
1389
1521
|
if ("file" === attachment.kind) return true;
|
|
1390
1522
|
return "string" == typeof attachment.textContent;
|
|
1391
1523
|
}
|
|
1392
|
-
export { GatewayServer };
|
|
1524
|
+
export { GatewayServer, resolveExecutionConfigDirOverride, resolveExecutionWorkspaceOverride };
|
|
@@ -24,7 +24,8 @@ var __webpack_require__ = {};
|
|
|
24
24
|
var __webpack_exports__ = {};
|
|
25
25
|
__webpack_require__.r(__webpack_exports__);
|
|
26
26
|
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
-
WebSocketTransport: ()=>WebSocketTransport
|
|
27
|
+
WebSocketTransport: ()=>WebSocketTransport,
|
|
28
|
+
describeWebSocketError: ()=>describeWebSocketError
|
|
28
29
|
});
|
|
29
30
|
const external_logger_cjs_namespaceObject = require("../../logger.cjs");
|
|
30
31
|
function _define_property(obj, key, value) {
|
|
@@ -38,19 +39,47 @@ function _define_property(obj, key, value) {
|
|
|
38
39
|
return obj;
|
|
39
40
|
}
|
|
40
41
|
const logger = (0, external_logger_cjs_namespaceObject.createLogger)();
|
|
42
|
+
function describeWebSocketError(error, url) {
|
|
43
|
+
if (error instanceof Error) {
|
|
44
|
+
const message = error.message.trim();
|
|
45
|
+
return message ? `WebSocket connection failed to ${url}: ${message}` : `WebSocket connection failed to ${url}.`;
|
|
46
|
+
}
|
|
47
|
+
if ("string" == typeof error && error.trim()) return `WebSocket connection failed to ${url}: ${error.trim()}`;
|
|
48
|
+
if (error && "object" == typeof error) {
|
|
49
|
+
const typed = error;
|
|
50
|
+
const eventType = "string" == typeof typed.type && typed.type.trim() ? typed.type.trim() : "error";
|
|
51
|
+
const message = "string" == typeof typed.message && typed.message.trim() ? typed.message.trim() : null;
|
|
52
|
+
const reason = "string" == typeof typed.reason && typed.reason.trim() ? typed.reason.trim() : null;
|
|
53
|
+
const detail = message || reason;
|
|
54
|
+
return detail ? `WebSocket ${eventType} while connecting to ${url}: ${detail}` : `WebSocket ${eventType} while connecting to ${url}.`;
|
|
55
|
+
}
|
|
56
|
+
return `WebSocket connection failed to ${url}.`;
|
|
57
|
+
}
|
|
41
58
|
class WebSocketTransport {
|
|
42
59
|
async connect() {
|
|
43
60
|
return new Promise((resolve, reject)=>{
|
|
61
|
+
let settled = false;
|
|
62
|
+
const rejectOnce = (reason)=>{
|
|
63
|
+
if (settled) return;
|
|
64
|
+
settled = true;
|
|
65
|
+
clearTimeout(timeout);
|
|
66
|
+
reject(reason);
|
|
67
|
+
};
|
|
68
|
+
const resolveOnce = ()=>{
|
|
69
|
+
if (settled) return;
|
|
70
|
+
settled = true;
|
|
71
|
+
clearTimeout(timeout);
|
|
72
|
+
resolve();
|
|
73
|
+
};
|
|
44
74
|
const timeout = setTimeout(()=>{
|
|
45
75
|
if (this.ws) this.ws.close();
|
|
46
|
-
|
|
76
|
+
rejectOnce(new Error(`WebSocket connection timeout after ${this.options.connectionTimeout}ms (${this.url}).`));
|
|
47
77
|
}, this.options.connectionTimeout);
|
|
48
78
|
try {
|
|
49
79
|
this.ws = new WebSocket(this.url);
|
|
50
80
|
this.ws.onopen = ()=>{
|
|
51
|
-
clearTimeout(timeout);
|
|
52
81
|
this.reconnectAttempts = 0;
|
|
53
|
-
|
|
82
|
+
resolveOnce();
|
|
54
83
|
};
|
|
55
84
|
this.ws.onmessage = (event)=>{
|
|
56
85
|
try {
|
|
@@ -61,16 +90,20 @@ class WebSocketTransport {
|
|
|
61
90
|
}
|
|
62
91
|
};
|
|
63
92
|
this.ws.onerror = (error)=>{
|
|
64
|
-
|
|
65
|
-
reject(error);
|
|
93
|
+
rejectOnce(new Error(describeWebSocketError(error, this.url)));
|
|
66
94
|
};
|
|
67
|
-
this.ws.onclose = ()=>{
|
|
95
|
+
this.ws.onclose = (event)=>{
|
|
96
|
+
if (!settled) {
|
|
97
|
+
const code = event && "number" == typeof event.code ? String(event.code) : "unknown";
|
|
98
|
+
const reason = event && "string" == typeof event.reason && event.reason.trim() ? ` (${event.reason.trim()})` : "";
|
|
99
|
+
rejectOnce(new Error(`WebSocket closed before connection was established (${this.url}, code=${code})${reason}.`));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
68
102
|
this.ws = null;
|
|
69
103
|
if (this.options.autoReconnect && this.reconnectAttempts < (this.options.maxReconnectAttempts || 5)) this.scheduleReconnect();
|
|
70
104
|
};
|
|
71
105
|
} catch (error) {
|
|
72
|
-
|
|
73
|
-
reject(error);
|
|
106
|
+
rejectOnce(new Error(describeWebSocketError(error, this.url)));
|
|
74
107
|
}
|
|
75
108
|
});
|
|
76
109
|
}
|
|
@@ -124,8 +157,10 @@ class WebSocketTransport {
|
|
|
124
157
|
}
|
|
125
158
|
}
|
|
126
159
|
exports.WebSocketTransport = __webpack_exports__.WebSocketTransport;
|
|
160
|
+
exports.describeWebSocketError = __webpack_exports__.describeWebSocketError;
|
|
127
161
|
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
128
|
-
"WebSocketTransport"
|
|
162
|
+
"WebSocketTransport",
|
|
163
|
+
"describeWebSocketError"
|
|
129
164
|
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
130
165
|
Object.defineProperty(exports, '__esModule', {
|
|
131
166
|
value: true
|
|
@@ -10,19 +10,47 @@ function _define_property(obj, key, value) {
|
|
|
10
10
|
return obj;
|
|
11
11
|
}
|
|
12
12
|
const logger = createLogger();
|
|
13
|
+
function describeWebSocketError(error, url) {
|
|
14
|
+
if (error instanceof Error) {
|
|
15
|
+
const message = error.message.trim();
|
|
16
|
+
return message ? `WebSocket connection failed to ${url}: ${message}` : `WebSocket connection failed to ${url}.`;
|
|
17
|
+
}
|
|
18
|
+
if ("string" == typeof error && error.trim()) return `WebSocket connection failed to ${url}: ${error.trim()}`;
|
|
19
|
+
if (error && "object" == typeof error) {
|
|
20
|
+
const typed = error;
|
|
21
|
+
const eventType = "string" == typeof typed.type && typed.type.trim() ? typed.type.trim() : "error";
|
|
22
|
+
const message = "string" == typeof typed.message && typed.message.trim() ? typed.message.trim() : null;
|
|
23
|
+
const reason = "string" == typeof typed.reason && typed.reason.trim() ? typed.reason.trim() : null;
|
|
24
|
+
const detail = message || reason;
|
|
25
|
+
return detail ? `WebSocket ${eventType} while connecting to ${url}: ${detail}` : `WebSocket ${eventType} while connecting to ${url}.`;
|
|
26
|
+
}
|
|
27
|
+
return `WebSocket connection failed to ${url}.`;
|
|
28
|
+
}
|
|
13
29
|
class WebSocketTransport {
|
|
14
30
|
async connect() {
|
|
15
31
|
return new Promise((resolve, reject)=>{
|
|
32
|
+
let settled = false;
|
|
33
|
+
const rejectOnce = (reason)=>{
|
|
34
|
+
if (settled) return;
|
|
35
|
+
settled = true;
|
|
36
|
+
clearTimeout(timeout);
|
|
37
|
+
reject(reason);
|
|
38
|
+
};
|
|
39
|
+
const resolveOnce = ()=>{
|
|
40
|
+
if (settled) return;
|
|
41
|
+
settled = true;
|
|
42
|
+
clearTimeout(timeout);
|
|
43
|
+
resolve();
|
|
44
|
+
};
|
|
16
45
|
const timeout = setTimeout(()=>{
|
|
17
46
|
if (this.ws) this.ws.close();
|
|
18
|
-
|
|
47
|
+
rejectOnce(new Error(`WebSocket connection timeout after ${this.options.connectionTimeout}ms (${this.url}).`));
|
|
19
48
|
}, this.options.connectionTimeout);
|
|
20
49
|
try {
|
|
21
50
|
this.ws = new WebSocket(this.url);
|
|
22
51
|
this.ws.onopen = ()=>{
|
|
23
|
-
clearTimeout(timeout);
|
|
24
52
|
this.reconnectAttempts = 0;
|
|
25
|
-
|
|
53
|
+
resolveOnce();
|
|
26
54
|
};
|
|
27
55
|
this.ws.onmessage = (event)=>{
|
|
28
56
|
try {
|
|
@@ -33,16 +61,20 @@ class WebSocketTransport {
|
|
|
33
61
|
}
|
|
34
62
|
};
|
|
35
63
|
this.ws.onerror = (error)=>{
|
|
36
|
-
|
|
37
|
-
reject(error);
|
|
64
|
+
rejectOnce(new Error(describeWebSocketError(error, this.url)));
|
|
38
65
|
};
|
|
39
|
-
this.ws.onclose = ()=>{
|
|
66
|
+
this.ws.onclose = (event)=>{
|
|
67
|
+
if (!settled) {
|
|
68
|
+
const code = event && "number" == typeof event.code ? String(event.code) : "unknown";
|
|
69
|
+
const reason = event && "string" == typeof event.reason && event.reason.trim() ? ` (${event.reason.trim()})` : "";
|
|
70
|
+
rejectOnce(new Error(`WebSocket closed before connection was established (${this.url}, code=${code})${reason}.`));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
40
73
|
this.ws = null;
|
|
41
74
|
if (this.options.autoReconnect && this.reconnectAttempts < (this.options.maxReconnectAttempts || 5)) this.scheduleReconnect();
|
|
42
75
|
};
|
|
43
76
|
} catch (error) {
|
|
44
|
-
|
|
45
|
-
reject(error);
|
|
77
|
+
rejectOnce(new Error(describeWebSocketError(error, this.url)));
|
|
46
78
|
}
|
|
47
79
|
});
|
|
48
80
|
}
|
|
@@ -95,4 +127,4 @@ class WebSocketTransport {
|
|
|
95
127
|
};
|
|
96
128
|
}
|
|
97
129
|
}
|
|
98
|
-
export { WebSocketTransport };
|
|
130
|
+
export { WebSocketTransport, describeWebSocketError };
|
package/dist/gateway/types.d.ts
CHANGED
|
@@ -58,6 +58,10 @@ export interface AgentRequestPayload {
|
|
|
58
58
|
agentId?: string;
|
|
59
59
|
content?: string;
|
|
60
60
|
attachments?: MediaAttachment[];
|
|
61
|
+
execution?: {
|
|
62
|
+
workspace?: string;
|
|
63
|
+
configDir?: string;
|
|
64
|
+
};
|
|
61
65
|
routing?: RoutingInfo;
|
|
62
66
|
sessionKey?: string;
|
|
63
67
|
queueIfBusy?: boolean;
|
|
@@ -348,42 +348,6 @@ const parseConfig = (input)=>{
|
|
|
348
348
|
})).toBeUndefined();
|
|
349
349
|
});
|
|
350
350
|
});
|
|
351
|
-
(0, external_vitest_namespaceObject.describe)("evaluateStreamingCompletion", ()=>{
|
|
352
|
-
(0, external_vitest_namespaceObject.it)("blocks with stream_error when no assistant text and stream error exists", ()=>{
|
|
353
|
-
const result = (0, agentInvoker_cjs_namespaceObject.evaluateStreamingCompletion)({
|
|
354
|
-
sawAssistantText: false,
|
|
355
|
-
fallbackText: void 0,
|
|
356
|
-
streamErrorMessage: "provider timeout"
|
|
357
|
-
});
|
|
358
|
-
(0, external_vitest_namespaceObject.expect)(result).toEqual({
|
|
359
|
-
status: "blocked",
|
|
360
|
-
reason: "stream_error",
|
|
361
|
-
message: "Model call failed: provider timeout"
|
|
362
|
-
});
|
|
363
|
-
});
|
|
364
|
-
(0, external_vitest_namespaceObject.it)("blocks with empty_stream_response when no text or fallback is present", ()=>{
|
|
365
|
-
const result = (0, agentInvoker_cjs_namespaceObject.evaluateStreamingCompletion)({
|
|
366
|
-
sawAssistantText: false,
|
|
367
|
-
fallbackText: void 0,
|
|
368
|
-
streamErrorMessage: void 0
|
|
369
|
-
});
|
|
370
|
-
(0, external_vitest_namespaceObject.expect)(result).toEqual({
|
|
371
|
-
status: "blocked",
|
|
372
|
-
reason: "empty_stream_response",
|
|
373
|
-
message: "Model completed without a response. Check provider logs for request errors."
|
|
374
|
-
});
|
|
375
|
-
});
|
|
376
|
-
(0, external_vitest_namespaceObject.it)("returns ok when assistant text exists", ()=>{
|
|
377
|
-
const result = (0, agentInvoker_cjs_namespaceObject.evaluateStreamingCompletion)({
|
|
378
|
-
sawAssistantText: true,
|
|
379
|
-
fallbackText: void 0,
|
|
380
|
-
streamErrorMessage: void 0
|
|
381
|
-
});
|
|
382
|
-
(0, external_vitest_namespaceObject.expect)(result).toEqual({
|
|
383
|
-
status: "ok"
|
|
384
|
-
});
|
|
385
|
-
});
|
|
386
|
-
});
|
|
387
351
|
(0, external_vitest_namespaceObject.describe)("LangGraph lifecycle termination", ()=>{
|
|
388
352
|
(0, external_vitest_namespaceObject.it)("tracks root LangGraph run id from parentless on_chain_start", ()=>{
|
|
389
353
|
const rootRunId = (0, agentInvoker_cjs_namespaceObject.trackRootLangGraphRunId)(void 0, {
|
|
@@ -441,12 +405,67 @@ const parseConfig = (input)=>{
|
|
|
441
405
|
run_id: "root-run",
|
|
442
406
|
parent_ids: []
|
|
443
407
|
}, "root-run")).toBe(false);
|
|
408
|
+
});
|
|
409
|
+
(0, external_vitest_namespaceObject.it)("treats root LangGraph on_chain_end as terminal even without tracked run id", ()=>{
|
|
444
410
|
(0, external_vitest_namespaceObject.expect)((0, agentInvoker_cjs_namespaceObject.isRootLangGraphTerminalEvent)({
|
|
445
411
|
event: "on_chain_end",
|
|
446
412
|
name: "LangGraph",
|
|
447
413
|
run_id: "root-run",
|
|
448
414
|
parent_ids: []
|
|
449
|
-
}, void 0)).toBe(
|
|
415
|
+
}, void 0)).toBe(true);
|
|
416
|
+
});
|
|
417
|
+
(0, external_vitest_namespaceObject.it)("treats root LangGraph on_chain_end as terminal when run id is missing", ()=>{
|
|
418
|
+
(0, external_vitest_namespaceObject.expect)((0, agentInvoker_cjs_namespaceObject.isRootLangGraphTerminalEvent)({
|
|
419
|
+
event: "on_chain_end",
|
|
420
|
+
name: "LangGraph",
|
|
421
|
+
parent_ids: []
|
|
422
|
+
}, "root-run")).toBe(true);
|
|
423
|
+
});
|
|
424
|
+
});
|
|
425
|
+
(0, external_vitest_namespaceObject.describe)("emitCompletionAndContinuePostProcessing", ()=>{
|
|
426
|
+
(0, external_vitest_namespaceObject.it)("emits completion before post-processing resolves", ()=>{
|
|
427
|
+
const callOrder = [];
|
|
428
|
+
let resolvePostProcess;
|
|
429
|
+
const postProcess = ()=>new Promise((resolve)=>{
|
|
430
|
+
callOrder.push("post-process-start");
|
|
431
|
+
resolvePostProcess = resolve;
|
|
432
|
+
});
|
|
433
|
+
(0, agentInvoker_cjs_namespaceObject.emitCompletionAndContinuePostProcessing)({
|
|
434
|
+
outputManager: {
|
|
435
|
+
emitAgentComplete: ()=>{
|
|
436
|
+
callOrder.push("emit-complete");
|
|
437
|
+
}
|
|
438
|
+
},
|
|
439
|
+
result: {
|
|
440
|
+
ok: true
|
|
441
|
+
},
|
|
442
|
+
postProcess
|
|
443
|
+
});
|
|
444
|
+
(0, external_vitest_namespaceObject.expect)(callOrder).toEqual([
|
|
445
|
+
"emit-complete",
|
|
446
|
+
"post-process-start"
|
|
447
|
+
]);
|
|
448
|
+
resolvePostProcess?.();
|
|
449
|
+
});
|
|
450
|
+
(0, external_vitest_namespaceObject.it)("logs and swallows post-processing failures", async ()=>{
|
|
451
|
+
const debug = external_vitest_namespaceObject.vi.fn();
|
|
452
|
+
(0, agentInvoker_cjs_namespaceObject.emitCompletionAndContinuePostProcessing)({
|
|
453
|
+
outputManager: {
|
|
454
|
+
emitAgentComplete: external_vitest_namespaceObject.vi.fn()
|
|
455
|
+
},
|
|
456
|
+
result: {
|
|
457
|
+
ok: true
|
|
458
|
+
},
|
|
459
|
+
postProcess: async ()=>{
|
|
460
|
+
throw new Error("materialization failed");
|
|
461
|
+
},
|
|
462
|
+
logger: {
|
|
463
|
+
debug
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
await Promise.resolve();
|
|
467
|
+
await Promise.resolve();
|
|
468
|
+
(0, external_vitest_namespaceObject.expect)(debug).toHaveBeenCalledWith("Failed post-completion processing for streamed agent response", external_vitest_namespaceObject.expect.any(Error));
|
|
450
469
|
});
|
|
451
470
|
});
|
|
452
471
|
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|