@wingman-ai/gateway 0.5.3 → 0.6.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/dist/agent/backend/filtered-backend.cjs +130 -0
- package/dist/agent/backend/filtered-backend.d.ts +10 -0
- package/dist/agent/backend/filtered-backend.js +87 -0
- package/dist/agent/config/agentConfig.cjs +4 -0
- package/dist/agent/config/agentConfig.d.ts +12 -0
- package/dist/agent/config/agentConfig.js +4 -0
- package/dist/agent/config/toolRegistry.cjs +75 -1
- package/dist/agent/config/toolRegistry.d.ts +3 -0
- package/dist/agent/config/toolRegistry.js +75 -1
- package/dist/agent/middleware/additional-messages.cjs +4 -1
- package/dist/agent/middleware/additional-messages.js +4 -1
- package/dist/agent/middleware/large-tool-results.cjs +207 -0
- package/dist/agent/middleware/large-tool-results.d.ts +16 -0
- package/dist/agent/middleware/large-tool-results.js +173 -0
- package/dist/agent/tools/browser_control.cjs +9 -1231
- package/dist/agent/tools/browser_control.d.ts +126 -234
- package/dist/agent/tools/browser_control.js +7 -1226
- package/dist/agent/tools/browser_runtime.cjs +1358 -0
- package/dist/agent/tools/browser_runtime.d.ts +617 -0
- package/dist/agent/tools/browser_runtime.js +1288 -0
- package/dist/agent/tools/browser_session.cjs +189 -0
- package/dist/agent/tools/browser_session.d.ts +686 -0
- package/dist/agent/tools/browser_session.js +146 -0
- package/dist/agent/tools/browser_session_manager.cjs +213 -0
- package/dist/agent/tools/browser_session_manager.d.ts +70 -0
- package/dist/agent/tools/browser_session_manager.js +176 -0
- package/dist/cli/commands/init.cjs +80 -98
- package/dist/cli/commands/init.js +80 -98
- package/dist/cli/config/loader.cjs +0 -5
- package/dist/cli/config/loader.js +0 -5
- package/dist/cli/config/schema.cjs +3 -7
- package/dist/cli/config/schema.d.ts +6 -6
- package/dist/cli/config/schema.js +3 -7
- package/dist/cli/core/agentInvoker.cjs +88 -22
- package/dist/cli/core/agentInvoker.d.ts +10 -3
- package/dist/cli/core/agentInvoker.js +88 -25
- package/dist/cli/core/outputManager.cjs +7 -2
- package/dist/cli/core/outputManager.d.ts +2 -2
- package/dist/cli/core/outputManager.js +7 -2
- package/dist/cli/core/sessionManager.cjs +208 -41
- package/dist/cli/core/sessionManager.d.ts +20 -0
- package/dist/cli/core/sessionManager.js +208 -41
- package/dist/cli/index.cjs +16 -1
- package/dist/cli/index.js +16 -1
- package/dist/cli/services/updateCheck.cjs +212 -0
- package/dist/cli/services/updateCheck.d.ts +26 -0
- package/dist/cli/services/updateCheck.js +166 -0
- package/dist/cli/types.d.ts +2 -1
- package/dist/gateway/server.cjs +7 -0
- package/dist/gateway/server.js +7 -0
- package/dist/webui/assets/index-D3x3G75t.css +11 -0
- package/dist/webui/assets/index-UpMmcU1f.js +215 -0
- package/dist/webui/index.html +2 -2
- package/package.json +12 -12
- package/templates/agents/README.md +3 -1
- package/templates/agents/coding/agent.md +6 -13
- package/templates/agents/coding-v2/agent.md +6 -1
- package/templates/agents/game-dev/agent.md +9 -2
- package/templates/agents/game-dev/game-designer.md +4 -0
- package/templates/agents/game-dev/scene-engineer.md +4 -0
- package/templates/agents/main/agent.md +7 -2
- package/templates/agents/researcher/agent.md +14 -3
- package/templates/agents/stock-trader/agent.md +4 -0
- package/dist/agent/tests/agentConfig.test.cjs +0 -224
- package/dist/agent/tests/agentConfig.test.d.ts +0 -1
- package/dist/agent/tests/agentConfig.test.js +0 -218
- package/dist/agent/tests/agentLoader.test.cjs +0 -335
- package/dist/agent/tests/agentLoader.test.d.ts +0 -1
- package/dist/agent/tests/agentLoader.test.js +0 -329
- package/dist/agent/tests/backgroundTerminal.test.cjs +0 -70
- package/dist/agent/tests/backgroundTerminal.test.d.ts +0 -1
- package/dist/agent/tests/backgroundTerminal.test.js +0 -64
- package/dist/agent/tests/browserControlHelpers.test.cjs +0 -35
- package/dist/agent/tests/browserControlHelpers.test.d.ts +0 -1
- package/dist/agent/tests/browserControlHelpers.test.js +0 -29
- package/dist/agent/tests/browserControlTool.test.cjs +0 -2117
- package/dist/agent/tests/browserControlTool.test.d.ts +0 -1
- package/dist/agent/tests/browserControlTool.test.js +0 -2111
- package/dist/agent/tests/commandExecuteTool.test.cjs +0 -29
- package/dist/agent/tests/commandExecuteTool.test.d.ts +0 -1
- package/dist/agent/tests/commandExecuteTool.test.js +0 -23
- package/dist/agent/tests/internet_search.test.cjs +0 -107
- package/dist/agent/tests/internet_search.test.d.ts +0 -1
- package/dist/agent/tests/internet_search.test.js +0 -101
- package/dist/agent/tests/mcpClientManager.test.cjs +0 -290
- package/dist/agent/tests/mcpClientManager.test.d.ts +0 -1
- package/dist/agent/tests/mcpClientManager.test.js +0 -284
- package/dist/agent/tests/mcpResourceTools.test.cjs +0 -101
- package/dist/agent/tests/mcpResourceTools.test.d.ts +0 -1
- package/dist/agent/tests/mcpResourceTools.test.js +0 -95
- package/dist/agent/tests/modelFactory.test.cjs +0 -190
- package/dist/agent/tests/modelFactory.test.d.ts +0 -1
- package/dist/agent/tests/modelFactory.test.js +0 -184
- package/dist/agent/tests/terminalSessionManager.test.cjs +0 -121
- package/dist/agent/tests/terminalSessionManager.test.d.ts +0 -1
- package/dist/agent/tests/terminalSessionManager.test.js +0 -115
- package/dist/agent/tests/test-agent-loader.cjs +0 -33
- package/dist/agent/tests/test-agent-loader.d.ts +0 -1
- package/dist/agent/tests/test-agent-loader.js +0 -27
- package/dist/agent/tests/test-subagent-loading.cjs +0 -99
- package/dist/agent/tests/test-subagent-loading.d.ts +0 -1
- package/dist/agent/tests/test-subagent-loading.js +0 -93
- package/dist/agent/tests/toolRegistry.test.cjs +0 -147
- package/dist/agent/tests/toolRegistry.test.d.ts +0 -1
- package/dist/agent/tests/toolRegistry.test.js +0 -141
- package/dist/agent/tests/uiRegistryTools.test.cjs +0 -114
- package/dist/agent/tests/uiRegistryTools.test.d.ts +0 -1
- package/dist/agent/tests/uiRegistryTools.test.js +0 -105
- package/dist/agent/tests/xaiImageModel.test.cjs +0 -194
- package/dist/agent/tests/xaiImageModel.test.d.ts +0 -1
- package/dist/agent/tests/xaiImageModel.test.js +0 -188
- package/dist/tests/additionalMessageMiddleware.test.cjs +0 -216
- package/dist/tests/additionalMessageMiddleware.test.d.ts +0 -1
- package/dist/tests/additionalMessageMiddleware.test.js +0 -188
- package/dist/tests/agent-config-voice.test.cjs +0 -25
- package/dist/tests/agent-config-voice.test.d.ts +0 -1
- package/dist/tests/agent-config-voice.test.js +0 -19
- package/dist/tests/agentInvokerAttachments.test.cjs +0 -190
- package/dist/tests/agentInvokerAttachments.test.d.ts +0 -1
- package/dist/tests/agentInvokerAttachments.test.js +0 -184
- package/dist/tests/agentInvokerSummarization.test.cjs +0 -613
- package/dist/tests/agentInvokerSummarization.test.d.ts +0 -1
- package/dist/tests/agentInvokerSummarization.test.js +0 -607
- package/dist/tests/agentInvokerTokenUsage.test.cjs +0 -124
- package/dist/tests/agentInvokerTokenUsage.test.d.ts +0 -1
- package/dist/tests/agentInvokerTokenUsage.test.js +0 -118
- package/dist/tests/agentInvokerWorkdir.test.cjs +0 -150
- package/dist/tests/agentInvokerWorkdir.test.d.ts +0 -1
- package/dist/tests/agentInvokerWorkdir.test.js +0 -122
- package/dist/tests/agents-api.test.cjs +0 -324
- package/dist/tests/agents-api.test.d.ts +0 -1
- package/dist/tests/agents-api.test.js +0 -318
- package/dist/tests/attachments-utils.test.cjs +0 -46
- package/dist/tests/attachments-utils.test.d.ts +0 -1
- package/dist/tests/attachments-utils.test.js +0 -40
- package/dist/tests/browser-command.test.cjs +0 -264
- package/dist/tests/browser-command.test.d.ts +0 -1
- package/dist/tests/browser-command.test.js +0 -258
- package/dist/tests/browser-relay-server.test.cjs +0 -20
- package/dist/tests/browser-relay-server.test.d.ts +0 -1
- package/dist/tests/browser-relay-server.test.js +0 -14
- package/dist/tests/bunSqliteAdapter.test.cjs +0 -265
- package/dist/tests/bunSqliteAdapter.test.d.ts +0 -1
- package/dist/tests/bunSqliteAdapter.test.js +0 -259
- package/dist/tests/candleRange.test.cjs +0 -48
- package/dist/tests/candleRange.test.d.ts +0 -1
- package/dist/tests/candleRange.test.js +0 -42
- package/dist/tests/cli-config-loader.test.cjs +0 -532
- package/dist/tests/cli-config-loader.test.d.ts +0 -1
- package/dist/tests/cli-config-loader.test.js +0 -526
- package/dist/tests/cli-config-warnings.test.cjs +0 -94
- package/dist/tests/cli-config-warnings.test.d.ts +0 -1
- package/dist/tests/cli-config-warnings.test.js +0 -88
- package/dist/tests/cli-init.test.cjs +0 -225
- package/dist/tests/cli-init.test.d.ts +0 -1
- package/dist/tests/cli-init.test.js +0 -219
- package/dist/tests/cli-workspace-root.test.cjs +0 -114
- package/dist/tests/cli-workspace-root.test.d.ts +0 -1
- package/dist/tests/cli-workspace-root.test.js +0 -108
- package/dist/tests/codex-credentials-precedence.test.cjs +0 -94
- package/dist/tests/codex-credentials-precedence.test.d.ts +0 -1
- package/dist/tests/codex-credentials-precedence.test.js +0 -88
- package/dist/tests/codex-provider.test.cjs +0 -383
- package/dist/tests/codex-provider.test.d.ts +0 -1
- package/dist/tests/codex-provider.test.js +0 -377
- package/dist/tests/config-json-schema.test.cjs +0 -37
- package/dist/tests/config-json-schema.test.d.ts +0 -1
- package/dist/tests/config-json-schema.test.js +0 -31
- package/dist/tests/discord-adapter.test.cjs +0 -89
- package/dist/tests/discord-adapter.test.d.ts +0 -1
- package/dist/tests/discord-adapter.test.js +0 -83
- package/dist/tests/falRuntime.test.cjs +0 -78
- package/dist/tests/falRuntime.test.d.ts +0 -1
- package/dist/tests/falRuntime.test.js +0 -72
- package/dist/tests/falSummary.test.cjs +0 -51
- package/dist/tests/falSummary.test.d.ts +0 -1
- package/dist/tests/falSummary.test.js +0 -45
- package/dist/tests/fs-api.test.cjs +0 -138
- package/dist/tests/fs-api.test.d.ts +0 -1
- package/dist/tests/fs-api.test.js +0 -132
- package/dist/tests/gateway-command-workspace.test.cjs +0 -150
- package/dist/tests/gateway-command-workspace.test.d.ts +0 -1
- package/dist/tests/gateway-command-workspace.test.js +0 -144
- package/dist/tests/gateway-http-security.test.cjs +0 -318
- package/dist/tests/gateway-http-security.test.d.ts +0 -1
- package/dist/tests/gateway-http-security.test.js +0 -312
- package/dist/tests/gateway-node-mode.test.cjs +0 -174
- package/dist/tests/gateway-node-mode.test.d.ts +0 -1
- package/dist/tests/gateway-node-mode.test.js +0 -168
- package/dist/tests/gateway-origin-policy.test.cjs +0 -82
- package/dist/tests/gateway-origin-policy.test.d.ts +0 -1
- package/dist/tests/gateway-origin-policy.test.js +0 -76
- package/dist/tests/gateway-request-execution-overrides.test.cjs +0 -42
- package/dist/tests/gateway-request-execution-overrides.test.d.ts +0 -1
- package/dist/tests/gateway-request-execution-overrides.test.js +0 -36
- package/dist/tests/gateway.test.cjs +0 -700
- package/dist/tests/gateway.test.d.ts +0 -1
- package/dist/tests/gateway.test.js +0 -694
- package/dist/tests/hooks-matcher.test.cjs +0 -309
- package/dist/tests/hooks-matcher.test.d.ts +0 -1
- package/dist/tests/hooks-matcher.test.js +0 -303
- package/dist/tests/hooks-merger.test.cjs +0 -528
- package/dist/tests/hooks-merger.test.d.ts +0 -1
- package/dist/tests/hooks-merger.test.js +0 -522
- package/dist/tests/imagePersistence.test.cjs +0 -169
- package/dist/tests/imagePersistence.test.d.ts +0 -1
- package/dist/tests/imagePersistence.test.js +0 -163
- package/dist/tests/integration/agent-invocation.integration.test.cjs +0 -264
- package/dist/tests/integration/agent-invocation.integration.test.d.ts +0 -1
- package/dist/tests/integration/agent-invocation.integration.test.js +0 -258
- package/dist/tests/integration/finnhub-candles.integration.test.cjs +0 -98
- package/dist/tests/integration/finnhub-candles.integration.test.d.ts +0 -1
- package/dist/tests/integration/finnhub-candles.integration.test.js +0 -92
- package/dist/tests/integration/summarization-e2e.integration.test.cjs +0 -127
- package/dist/tests/integration/summarization-e2e.integration.test.d.ts +0 -1
- package/dist/tests/integration/summarization-e2e.integration.test.js +0 -121
- package/dist/tests/logger.test.cjs +0 -353
- package/dist/tests/logger.test.d.ts +0 -1
- package/dist/tests/logger.test.js +0 -347
- package/dist/tests/mediaCompatibilityMiddleware.test.cjs +0 -106
- package/dist/tests/mediaCompatibilityMiddleware.test.d.ts +0 -1
- package/dist/tests/mediaCompatibilityMiddleware.test.js +0 -100
- package/dist/tests/node-tools.test.cjs +0 -77
- package/dist/tests/node-tools.test.d.ts +0 -1
- package/dist/tests/node-tools.test.js +0 -71
- package/dist/tests/nodes-api.test.cjs +0 -86
- package/dist/tests/nodes-api.test.d.ts +0 -1
- package/dist/tests/nodes-api.test.js +0 -80
- package/dist/tests/outputManagerContextSummarized.test.cjs +0 -43
- package/dist/tests/outputManagerContextSummarized.test.d.ts +0 -1
- package/dist/tests/outputManagerContextSummarized.test.js +0 -37
- package/dist/tests/provider-command-codex.test.cjs +0 -57
- package/dist/tests/provider-command-codex.test.d.ts +0 -1
- package/dist/tests/provider-command-codex.test.js +0 -51
- package/dist/tests/routines-api.test.cjs +0 -107
- package/dist/tests/routines-api.test.d.ts +0 -1
- package/dist/tests/routines-api.test.js +0 -101
- package/dist/tests/run-terminal-bench-official-script.test.cjs +0 -61
- package/dist/tests/run-terminal-bench-official-script.test.d.ts +0 -1
- package/dist/tests/run-terminal-bench-official-script.test.js +0 -55
- package/dist/tests/sessionManager-uionly.test.cjs +0 -50
- package/dist/tests/sessionManager-uionly.test.d.ts +0 -1
- package/dist/tests/sessionManager-uionly.test.js +0 -44
- package/dist/tests/sessionMessageAttachments.test.cjs +0 -197
- package/dist/tests/sessionMessageAttachments.test.d.ts +0 -1
- package/dist/tests/sessionMessageAttachments.test.js +0 -191
- package/dist/tests/sessionMessageRole.test.cjs +0 -44
- package/dist/tests/sessionMessageRole.test.d.ts +0 -1
- package/dist/tests/sessionMessageRole.test.js +0 -38
- package/dist/tests/sessionStateMessages.test.cjs +0 -236
- package/dist/tests/sessionStateMessages.test.d.ts +0 -1
- package/dist/tests/sessionStateMessages.test.js +0 -230
- package/dist/tests/sessions-api.test.cjs +0 -250
- package/dist/tests/sessions-api.test.d.ts +0 -1
- package/dist/tests/sessions-api.test.js +0 -244
- package/dist/tests/skill-activation.test.cjs +0 -86
- package/dist/tests/skill-activation.test.d.ts +0 -1
- package/dist/tests/skill-activation.test.js +0 -80
- package/dist/tests/skill-metadata.test.cjs +0 -119
- package/dist/tests/skill-metadata.test.d.ts +0 -1
- package/dist/tests/skill-metadata.test.js +0 -113
- package/dist/tests/skill-repository.test.cjs +0 -469
- package/dist/tests/skill-repository.test.d.ts +0 -1
- package/dist/tests/skill-repository.test.js +0 -463
- package/dist/tests/skill-security-scanner.test.cjs +0 -126
- package/dist/tests/skill-security-scanner.test.d.ts +0 -1
- package/dist/tests/skill-security-scanner.test.js +0 -120
- package/dist/tests/sms-api.test.cjs +0 -183
- package/dist/tests/sms-api.test.d.ts +0 -1
- package/dist/tests/sms-api.test.js +0 -177
- package/dist/tests/sms-commands.test.cjs +0 -90
- package/dist/tests/sms-commands.test.d.ts +0 -1
- package/dist/tests/sms-commands.test.js +0 -84
- package/dist/tests/sms-policy-store.test.cjs +0 -69
- package/dist/tests/sms-policy-store.test.d.ts +0 -1
- package/dist/tests/sms-policy-store.test.js +0 -63
- package/dist/tests/teams-adapter.test.cjs +0 -58
- package/dist/tests/teams-adapter.test.d.ts +0 -1
- package/dist/tests/teams-adapter.test.js +0 -52
- package/dist/tests/technicalIndicators.test.cjs +0 -82
- package/dist/tests/technicalIndicators.test.d.ts +0 -1
- package/dist/tests/technicalIndicators.test.js +0 -76
- package/dist/tests/terminal-bench-adapters-helpers.test.cjs +0 -64
- package/dist/tests/terminal-bench-adapters-helpers.test.d.ts +0 -1
- package/dist/tests/terminal-bench-adapters-helpers.test.js +0 -58
- package/dist/tests/terminal-bench-cleanup.test.cjs +0 -93
- package/dist/tests/terminal-bench-cleanup.test.d.ts +0 -1
- package/dist/tests/terminal-bench-cleanup.test.js +0 -87
- package/dist/tests/terminal-bench-config.test.cjs +0 -62
- package/dist/tests/terminal-bench-config.test.d.ts +0 -1
- package/dist/tests/terminal-bench-config.test.js +0 -56
- package/dist/tests/terminal-bench-official.test.cjs +0 -194
- package/dist/tests/terminal-bench-official.test.d.ts +0 -1
- package/dist/tests/terminal-bench-official.test.js +0 -188
- package/dist/tests/terminal-bench-runner.test.cjs +0 -82
- package/dist/tests/terminal-bench-runner.test.d.ts +0 -1
- package/dist/tests/terminal-bench-runner.test.js +0 -76
- package/dist/tests/terminal-bench-scoring.test.cjs +0 -128
- package/dist/tests/terminal-bench-scoring.test.d.ts +0 -1
- package/dist/tests/terminal-bench-scoring.test.js +0 -122
- package/dist/tests/terminalProbe.test.cjs +0 -45
- package/dist/tests/terminalProbe.test.d.ts +0 -1
- package/dist/tests/terminalProbe.test.js +0 -39
- package/dist/tests/terminalProbeAuth.test.cjs +0 -85
- package/dist/tests/terminalProbeAuth.test.d.ts +0 -1
- package/dist/tests/terminalProbeAuth.test.js +0 -79
- package/dist/tests/toolDisplayHelpers.test.cjs +0 -46
- package/dist/tests/toolDisplayHelpers.test.d.ts +0 -1
- package/dist/tests/toolDisplayHelpers.test.js +0 -40
- package/dist/tests/uv.test.cjs +0 -47
- package/dist/tests/uv.test.d.ts +0 -1
- package/dist/tests/uv.test.js +0 -41
- package/dist/tests/voice-config.test.cjs +0 -35
- package/dist/tests/voice-config.test.d.ts +0 -1
- package/dist/tests/voice-config.test.js +0 -29
- package/dist/tests/websocket-transport.test.cjs +0 -31
- package/dist/tests/websocket-transport.test.d.ts +0 -1
- package/dist/tests/websocket-transport.test.js +0 -25
- package/dist/tests/yahooCandles.test.cjs +0 -111
- package/dist/tests/yahooCandles.test.d.ts +0 -1
- package/dist/tests/yahooCandles.test.js +0 -105
- package/dist/tools/finance/optionsAnalytics.test.cjs +0 -128
- package/dist/tools/finance/optionsAnalytics.test.d.ts +0 -1
- package/dist/tools/finance/optionsAnalytics.test.js +0 -122
- package/dist/webui/assets/index-BMf95nv5.js +0 -215
- package/dist/webui/assets/index-DhJQ8Mbn.css +0 -11
- package/dist/webui/assets/wingman_logo-Cogyt3qm.webp +0 -0
|
@@ -1,694 +0,0 @@
|
|
|
1
|
-
import { mkdtempSync, rmSync } from "node:fs";
|
|
2
|
-
import { tmpdir } from "node:os";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
|
5
|
-
import { GatewayClient, GatewayServer } from "../gateway/index.js";
|
|
6
|
-
function _define_property(obj, key, value) {
|
|
7
|
-
if (key in obj) Object.defineProperty(obj, key, {
|
|
8
|
-
value: value,
|
|
9
|
-
enumerable: true,
|
|
10
|
-
configurable: true,
|
|
11
|
-
writable: true
|
|
12
|
-
});
|
|
13
|
-
else obj[key] = value;
|
|
14
|
-
return obj;
|
|
15
|
-
}
|
|
16
|
-
const isBun = void 0 !== globalThis.Bun;
|
|
17
|
-
const describeIfBun = isBun ? describe : describe.skip;
|
|
18
|
-
const invokerConstructOptions = [];
|
|
19
|
-
vi.mock("@/cli/core/agentInvoker.js", ()=>({
|
|
20
|
-
AgentInvoker: class {
|
|
21
|
-
async invokeAgent(_agentId, content, _sessionId, _attachments, options) {
|
|
22
|
-
if ("throw-no-event" === content) throw new Error("Synthetic invocation failure");
|
|
23
|
-
if ("stream-model-failure-no-error" === content) {
|
|
24
|
-
this.outputManager?.emitAgentStream?.({
|
|
25
|
-
event: "on_chain_end",
|
|
26
|
-
run_id: "model-failure-run-1",
|
|
27
|
-
name: "ChannelWrite<branch:to:todoListMiddleware.after_model>",
|
|
28
|
-
data: {
|
|
29
|
-
output: [
|
|
30
|
-
{
|
|
31
|
-
lg_name: "Command",
|
|
32
|
-
update: {
|
|
33
|
-
messages: [
|
|
34
|
-
{
|
|
35
|
-
type: "constructor",
|
|
36
|
-
id: [
|
|
37
|
-
"langchain_core",
|
|
38
|
-
"messages",
|
|
39
|
-
"AIMessage"
|
|
40
|
-
],
|
|
41
|
-
kwargs: {
|
|
42
|
-
id: "model-failure-msg-1",
|
|
43
|
-
content: "Model call failed after 3 attempts with Error: xAI image generation failed: Prompt len is larger than the maximum allowed length which is 8000"
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
]
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
],
|
|
50
|
-
input: {}
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
return {
|
|
54
|
-
streaming: true
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
const signal = options?.signal;
|
|
58
|
-
await new Promise((resolve)=>{
|
|
59
|
-
const timer = setTimeout(resolve, 75);
|
|
60
|
-
if (signal) {
|
|
61
|
-
const onAbort = ()=>{
|
|
62
|
-
clearTimeout(timer);
|
|
63
|
-
resolve();
|
|
64
|
-
};
|
|
65
|
-
if (signal.aborted) return void onAbort();
|
|
66
|
-
signal.addEventListener("abort", onAbort, {
|
|
67
|
-
once: true
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
if (signal?.aborted) {
|
|
72
|
-
this.outputManager?.emitAgentError?.("Request cancelled");
|
|
73
|
-
return {
|
|
74
|
-
cancelled: true
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
if ("return-no-event" === content) return {
|
|
78
|
-
streaming: true
|
|
79
|
-
};
|
|
80
|
-
this.outputManager?.emitAgentComplete?.({
|
|
81
|
-
streaming: true
|
|
82
|
-
});
|
|
83
|
-
return {
|
|
84
|
-
streaming: true
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
constructor(options){
|
|
88
|
-
_define_property(this, "outputManager", void 0);
|
|
89
|
-
this.outputManager = options?.outputManager;
|
|
90
|
-
invokerConstructOptions.push(options || {});
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}));
|
|
94
|
-
describeIfBun("Gateway", ()=>{
|
|
95
|
-
let server;
|
|
96
|
-
let port = 0;
|
|
97
|
-
let testWorkspace;
|
|
98
|
-
beforeAll(async ()=>{
|
|
99
|
-
invokerConstructOptions.length = 0;
|
|
100
|
-
testWorkspace = mkdtempSync(join(tmpdir(), "wingman-gateway-test-"));
|
|
101
|
-
const instance = new GatewayServer({
|
|
102
|
-
port: 0,
|
|
103
|
-
host: "localhost",
|
|
104
|
-
requireAuth: false,
|
|
105
|
-
auth: {
|
|
106
|
-
mode: "none"
|
|
107
|
-
},
|
|
108
|
-
logLevel: "silent",
|
|
109
|
-
workspace: testWorkspace,
|
|
110
|
-
configDir: ".wingman-test-config",
|
|
111
|
-
stateDir: ".wingman-test-state"
|
|
112
|
-
});
|
|
113
|
-
await instance.start();
|
|
114
|
-
server = instance;
|
|
115
|
-
port = server.getPort();
|
|
116
|
-
if (!port) throw new Error("Unable to determine gateway server port");
|
|
117
|
-
await new Promise((resolve)=>setTimeout(resolve, 500));
|
|
118
|
-
});
|
|
119
|
-
afterAll(async ()=>{
|
|
120
|
-
if (server) await server.stop();
|
|
121
|
-
if (testWorkspace) rmSync(testWorkspace, {
|
|
122
|
-
recursive: true,
|
|
123
|
-
force: true
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
const connectClient = (instanceId, clientType = "test")=>new Promise((resolve, reject)=>{
|
|
127
|
-
const ws = new WebSocket(`ws://localhost:${port}/ws`);
|
|
128
|
-
const connectId = `connect-${instanceId}-${Date.now()}`;
|
|
129
|
-
const timeout = setTimeout(()=>reject(new Error("Connect timeout")), 5000);
|
|
130
|
-
ws.addEventListener("open", ()=>{
|
|
131
|
-
const message = {
|
|
132
|
-
type: "connect",
|
|
133
|
-
id: connectId,
|
|
134
|
-
client: {
|
|
135
|
-
instanceId,
|
|
136
|
-
clientType
|
|
137
|
-
},
|
|
138
|
-
timestamp: Date.now()
|
|
139
|
-
};
|
|
140
|
-
ws.send(JSON.stringify(message));
|
|
141
|
-
});
|
|
142
|
-
ws.addEventListener("message", (event)=>{
|
|
143
|
-
const msg = JSON.parse(event.data);
|
|
144
|
-
if ("res" === msg.type && msg.id === connectId && msg.ok) {
|
|
145
|
-
clearTimeout(timeout);
|
|
146
|
-
resolve(ws);
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
ws.addEventListener("error", ()=>{
|
|
150
|
-
clearTimeout(timeout);
|
|
151
|
-
reject(new Error("WebSocket error"));
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
const waitForMessage = (ws, predicate, timeoutMs = 5000)=>new Promise((resolve, reject)=>{
|
|
155
|
-
const timeout = setTimeout(()=>reject(new Error("Message timeout")), timeoutMs);
|
|
156
|
-
const handler = (event)=>{
|
|
157
|
-
let msg;
|
|
158
|
-
try {
|
|
159
|
-
msg = JSON.parse(event.data);
|
|
160
|
-
} catch {
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
if (!predicate(msg)) return;
|
|
164
|
-
clearTimeout(timeout);
|
|
165
|
-
ws.removeEventListener("message", handler);
|
|
166
|
-
resolve(msg);
|
|
167
|
-
};
|
|
168
|
-
ws.addEventListener("message", handler);
|
|
169
|
-
});
|
|
170
|
-
const collectMessages = (ws, predicate, durationMs = 600)=>new Promise((resolve)=>{
|
|
171
|
-
const matches = [];
|
|
172
|
-
const handler = (event)=>{
|
|
173
|
-
let msg;
|
|
174
|
-
try {
|
|
175
|
-
msg = JSON.parse(event.data);
|
|
176
|
-
} catch {
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
if (!predicate(msg)) return;
|
|
180
|
-
matches.push(msg);
|
|
181
|
-
};
|
|
182
|
-
ws.addEventListener("message", handler);
|
|
183
|
-
setTimeout(()=>{
|
|
184
|
-
ws.removeEventListener("message", handler);
|
|
185
|
-
resolve(matches);
|
|
186
|
-
}, durationMs);
|
|
187
|
-
});
|
|
188
|
-
it("should start the gateway server", async ()=>{
|
|
189
|
-
const response = await fetch(`http://localhost:${port}/health`);
|
|
190
|
-
expect(response.ok).toBe(true);
|
|
191
|
-
const health = await response.json();
|
|
192
|
-
expect(health.status).toBe("healthy");
|
|
193
|
-
});
|
|
194
|
-
it("should connect a client", async ()=>new Promise((resolve, reject)=>{
|
|
195
|
-
const client = new GatewayClient(`ws://localhost:${port}/ws`, "test-client", {
|
|
196
|
-
events: {
|
|
197
|
-
connected: ()=>{
|
|
198
|
-
client.disconnect();
|
|
199
|
-
resolve();
|
|
200
|
-
},
|
|
201
|
-
error: (error)=>{
|
|
202
|
-
reject(new Error(error.message));
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
client.connect().catch(reject);
|
|
207
|
-
setTimeout(()=>reject(new Error("Connection timeout")), 5000);
|
|
208
|
-
}));
|
|
209
|
-
it("should register a client and receive node ID", async ()=>new Promise((resolve, reject)=>{
|
|
210
|
-
const client = new GatewayClient(`ws://localhost:${port}/ws`, "test-client-2", {
|
|
211
|
-
events: {
|
|
212
|
-
registered: (nodeId, name)=>{
|
|
213
|
-
expect(nodeId).toBeTruthy();
|
|
214
|
-
expect(name).toBe("test-client-2");
|
|
215
|
-
client.disconnect();
|
|
216
|
-
resolve();
|
|
217
|
-
},
|
|
218
|
-
error: (error)=>{
|
|
219
|
-
reject(new Error(error.message));
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
client.connect().catch(reject);
|
|
224
|
-
setTimeout(()=>reject(new Error("Registration timeout")), 5000);
|
|
225
|
-
}));
|
|
226
|
-
it("should join a broadcast group", async ()=>new Promise((resolve, reject)=>{
|
|
227
|
-
const client = new GatewayClient(`ws://localhost:${port}/ws`, "test-client-3", {
|
|
228
|
-
events: {
|
|
229
|
-
registered: async ()=>{
|
|
230
|
-
await client.joinGroup("test-group");
|
|
231
|
-
},
|
|
232
|
-
joinedGroup: (groupId, groupName)=>{
|
|
233
|
-
expect(groupName).toBe("test-group");
|
|
234
|
-
client.disconnect();
|
|
235
|
-
resolve();
|
|
236
|
-
},
|
|
237
|
-
error: (error)=>{
|
|
238
|
-
reject(new Error(error.message));
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
client.connect().catch(reject);
|
|
243
|
-
setTimeout(()=>reject(new Error("Join group timeout")), 5000);
|
|
244
|
-
}));
|
|
245
|
-
it("should broadcast messages to group members", async ()=>new Promise((resolve, reject)=>{
|
|
246
|
-
let client1NodeId = null;
|
|
247
|
-
let broadcastGroupId = null;
|
|
248
|
-
const client1 = new GatewayClient(`ws://localhost:${port}/ws`, "broadcaster", {
|
|
249
|
-
events: {
|
|
250
|
-
registered: async (nodeId)=>{
|
|
251
|
-
client1NodeId = nodeId;
|
|
252
|
-
await client1.joinGroup("broadcast-test");
|
|
253
|
-
},
|
|
254
|
-
joinedGroup: (groupId)=>{
|
|
255
|
-
broadcastGroupId = groupId;
|
|
256
|
-
client2.connect().catch(reject);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
});
|
|
260
|
-
const client2 = new GatewayClient(`ws://localhost:${port}/ws`, "receiver", {
|
|
261
|
-
events: {
|
|
262
|
-
registered: async ()=>{
|
|
263
|
-
await client2.joinGroup("broadcast-test");
|
|
264
|
-
},
|
|
265
|
-
joinedGroup: ()=>{
|
|
266
|
-
client1.broadcast(broadcastGroupId || "broadcast-test", {
|
|
267
|
-
message: "Hello from client 1"
|
|
268
|
-
});
|
|
269
|
-
},
|
|
270
|
-
broadcast: (message, fromNodeId)=>{
|
|
271
|
-
expect(fromNodeId).toBe(client1NodeId);
|
|
272
|
-
expect(message.message).toBe("Hello from client 1");
|
|
273
|
-
client1.disconnect();
|
|
274
|
-
client2.disconnect();
|
|
275
|
-
resolve();
|
|
276
|
-
},
|
|
277
|
-
error: (error)=>{
|
|
278
|
-
reject(new Error(error.message));
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
});
|
|
282
|
-
client1.connect().catch(reject);
|
|
283
|
-
setTimeout(()=>reject(new Error("Broadcast test timeout")), 10000);
|
|
284
|
-
}));
|
|
285
|
-
it("should handle ping/pong", async ()=>new Promise((resolve, reject)=>{
|
|
286
|
-
const client = new GatewayClient(`ws://localhost:${port}/ws`, "ping-test", {
|
|
287
|
-
events: {
|
|
288
|
-
registered: ()=>{
|
|
289
|
-
client.ping();
|
|
290
|
-
},
|
|
291
|
-
pong: ()=>{
|
|
292
|
-
client.disconnect();
|
|
293
|
-
resolve();
|
|
294
|
-
},
|
|
295
|
-
error: (error)=>{
|
|
296
|
-
reject(new Error(error.message));
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
});
|
|
300
|
-
client.connect().catch(reject);
|
|
301
|
-
setTimeout(()=>reject(new Error("Ping/pong timeout")), 5000);
|
|
302
|
-
}));
|
|
303
|
-
it("should stream agent events to session subscribers", async ()=>{
|
|
304
|
-
const subscriber = await connectClient("session-subscriber");
|
|
305
|
-
const sessionId = "session-test";
|
|
306
|
-
subscriber.send(JSON.stringify({
|
|
307
|
-
type: "session_subscribe",
|
|
308
|
-
payload: {
|
|
309
|
-
sessionId
|
|
310
|
-
},
|
|
311
|
-
timestamp: Date.now()
|
|
312
|
-
}));
|
|
313
|
-
await waitForMessage(subscriber, (msg)=>"ack" === msg.type && msg.payload?.action === "session_subscribe" && msg.payload?.sessionId === sessionId);
|
|
314
|
-
const eventPromise = waitForMessage(subscriber, (msg)=>"event:agent" === msg.type && "req-session" === msg.id);
|
|
315
|
-
const sent = server.broadcastSessionEvent(sessionId, {
|
|
316
|
-
type: "event:agent",
|
|
317
|
-
id: "req-session",
|
|
318
|
-
payload: {
|
|
319
|
-
type: "agent-stream",
|
|
320
|
-
sessionId,
|
|
321
|
-
agentId: "main",
|
|
322
|
-
chunk: {
|
|
323
|
-
content: "hello"
|
|
324
|
-
}
|
|
325
|
-
},
|
|
326
|
-
timestamp: Date.now()
|
|
327
|
-
});
|
|
328
|
-
expect(sent).toBe(1);
|
|
329
|
-
const eventMsg = await eventPromise;
|
|
330
|
-
expect(eventMsg.payload?.sessionId).toBe(sessionId);
|
|
331
|
-
subscriber.close();
|
|
332
|
-
});
|
|
333
|
-
it("should broadcast user messages to session subscribers", async ()=>{
|
|
334
|
-
const subscriber = await connectClient("session-input-subscriber");
|
|
335
|
-
const requester = await connectClient("session-input-requester");
|
|
336
|
-
const sessionId = "session-input-test";
|
|
337
|
-
subscriber.send(JSON.stringify({
|
|
338
|
-
type: "session_subscribe",
|
|
339
|
-
payload: {
|
|
340
|
-
sessionId
|
|
341
|
-
},
|
|
342
|
-
timestamp: Date.now()
|
|
343
|
-
}));
|
|
344
|
-
await waitForMessage(subscriber, (msg)=>"ack" === msg.type && msg.payload?.action === "session_subscribe" && msg.payload?.sessionId === sessionId);
|
|
345
|
-
const eventPromise = waitForMessage(subscriber, (msg)=>"event:agent" === msg.type && msg.payload?.type === "session-message" && msg.payload?.role === "user");
|
|
346
|
-
requester.send(JSON.stringify({
|
|
347
|
-
type: "req:agent",
|
|
348
|
-
id: "req-session-input",
|
|
349
|
-
payload: {
|
|
350
|
-
agentId: "main",
|
|
351
|
-
sessionKey: sessionId,
|
|
352
|
-
content: "Hello from test"
|
|
353
|
-
},
|
|
354
|
-
timestamp: Date.now()
|
|
355
|
-
}));
|
|
356
|
-
const eventMsg = await eventPromise;
|
|
357
|
-
expect(eventMsg.payload?.content).toBe("Hello from test");
|
|
358
|
-
expect(eventMsg.payload?.sessionId).toBe(sessionId);
|
|
359
|
-
expect(eventMsg.payload?.agentId).toBe("main");
|
|
360
|
-
subscriber.close();
|
|
361
|
-
requester.close();
|
|
362
|
-
});
|
|
363
|
-
it("should broadcast user messages to webui clients without session subscribe", async ()=>{
|
|
364
|
-
const webuiClient = await connectClient("session-webui-listener", "webui");
|
|
365
|
-
const requester = await connectClient("session-webui-requester");
|
|
366
|
-
const sessionId = "session-webui-test";
|
|
367
|
-
const eventPromise = waitForMessage(webuiClient, (msg)=>"event:agent" === msg.type && msg.payload?.type === "session-message" && msg.payload?.role === "user" && msg.payload?.sessionId === sessionId);
|
|
368
|
-
requester.send(JSON.stringify({
|
|
369
|
-
type: "req:agent",
|
|
370
|
-
id: "req-session-webui",
|
|
371
|
-
payload: {
|
|
372
|
-
agentId: "main",
|
|
373
|
-
sessionKey: sessionId,
|
|
374
|
-
content: "Hello webui"
|
|
375
|
-
},
|
|
376
|
-
timestamp: Date.now()
|
|
377
|
-
}));
|
|
378
|
-
const eventMsg = await eventPromise;
|
|
379
|
-
expect(eventMsg.payload?.content).toBe("Hello webui");
|
|
380
|
-
expect(eventMsg.payload?.agentId).toBe("main");
|
|
381
|
-
webuiClient.close();
|
|
382
|
-
requester.close();
|
|
383
|
-
});
|
|
384
|
-
it("should broadcast user messages to desktop clients without session subscribe", async ()=>{
|
|
385
|
-
const desktopClient = await connectClient("session-desktop-listener", "desktop");
|
|
386
|
-
const requester = await connectClient("session-desktop-requester");
|
|
387
|
-
const sessionId = "session-desktop-test";
|
|
388
|
-
const eventPromise = waitForMessage(desktopClient, (msg)=>"event:agent" === msg.type && msg.payload?.type === "session-message" && msg.payload?.role === "user" && msg.payload?.sessionId === sessionId);
|
|
389
|
-
requester.send(JSON.stringify({
|
|
390
|
-
type: "req:agent",
|
|
391
|
-
id: "req-session-desktop",
|
|
392
|
-
payload: {
|
|
393
|
-
agentId: "main",
|
|
394
|
-
sessionKey: sessionId,
|
|
395
|
-
content: "Hello desktop"
|
|
396
|
-
},
|
|
397
|
-
timestamp: Date.now()
|
|
398
|
-
}));
|
|
399
|
-
const eventMsg = await eventPromise;
|
|
400
|
-
expect(eventMsg.payload?.content).toBe("Hello desktop");
|
|
401
|
-
expect(eventMsg.payload?.agentId).toBe("main");
|
|
402
|
-
desktopClient.close();
|
|
403
|
-
requester.close();
|
|
404
|
-
});
|
|
405
|
-
it("should emit agent-error to requester when invocation throws without emitting", async ()=>{
|
|
406
|
-
const requester = await connectClient("session-error-requester");
|
|
407
|
-
const requestId = "req-invocation-error";
|
|
408
|
-
const sessionId = "session-error-test";
|
|
409
|
-
requester.send(JSON.stringify({
|
|
410
|
-
type: "req:agent",
|
|
411
|
-
id: requestId,
|
|
412
|
-
payload: {
|
|
413
|
-
agentId: "main",
|
|
414
|
-
sessionKey: sessionId,
|
|
415
|
-
content: "throw-no-event"
|
|
416
|
-
},
|
|
417
|
-
timestamp: Date.now()
|
|
418
|
-
}));
|
|
419
|
-
const errorMsg = await waitForMessage(requester, (msg)=>"event:agent" === msg.type && msg.id === requestId && msg.payload?.type === "agent-error");
|
|
420
|
-
expect(errorMsg.payload?.error).toContain("Synthetic invocation failure");
|
|
421
|
-
expect(errorMsg.payload?.sessionId).toBe(sessionId);
|
|
422
|
-
expect(errorMsg.payload?.agentId).toBe("main");
|
|
423
|
-
requester.close();
|
|
424
|
-
});
|
|
425
|
-
it("should emit agent-complete when invocation returns without terminal output events", async ()=>{
|
|
426
|
-
const requester = await connectClient("session-complete-fallback-requester");
|
|
427
|
-
const requestId = "req-complete-fallback";
|
|
428
|
-
const sessionId = "session-complete-fallback";
|
|
429
|
-
requester.send(JSON.stringify({
|
|
430
|
-
type: "req:agent",
|
|
431
|
-
id: requestId,
|
|
432
|
-
payload: {
|
|
433
|
-
agentId: "main",
|
|
434
|
-
sessionKey: sessionId,
|
|
435
|
-
content: "return-no-event"
|
|
436
|
-
},
|
|
437
|
-
timestamp: Date.now()
|
|
438
|
-
}));
|
|
439
|
-
const completeMsg = await waitForMessage(requester, (msg)=>"event:agent" === msg.type && msg.id === requestId && msg.payload?.type === "agent-complete");
|
|
440
|
-
expect(completeMsg.payload?.sessionId).toBe(sessionId);
|
|
441
|
-
expect(completeMsg.payload?.agentId).toBe("main");
|
|
442
|
-
expect(completeMsg.payload?.result).toEqual({
|
|
443
|
-
streaming: true
|
|
444
|
-
});
|
|
445
|
-
requester.close();
|
|
446
|
-
});
|
|
447
|
-
it("does not auto-convert streamed model failure text into agent-error", async ()=>{
|
|
448
|
-
const requester = await connectClient("session-streamed-failure-requester");
|
|
449
|
-
const requestId = "req-streamed-failure-no-error";
|
|
450
|
-
const sessionId = "session-streamed-failure-no-error";
|
|
451
|
-
requester.send(JSON.stringify({
|
|
452
|
-
type: "req:agent",
|
|
453
|
-
id: requestId,
|
|
454
|
-
payload: {
|
|
455
|
-
agentId: "main",
|
|
456
|
-
sessionKey: sessionId,
|
|
457
|
-
content: "stream-model-failure-no-error"
|
|
458
|
-
},
|
|
459
|
-
timestamp: Date.now()
|
|
460
|
-
}));
|
|
461
|
-
const streamMsg = await waitForMessage(requester, (msg)=>"event:agent" === msg.type && msg.id === requestId && msg.payload?.type === "agent-stream" && msg.payload?.chunk?.event === "on_chain_end", 10000);
|
|
462
|
-
expect(JSON.stringify(streamMsg.payload?.chunk?.data || {})).toContain("Model call failed after 3 attempts");
|
|
463
|
-
const completeMsg = await waitForMessage(requester, (msg)=>"event:agent" === msg.type && msg.id === requestId && msg.payload?.type === "agent-complete", 10000);
|
|
464
|
-
expect(completeMsg.payload?.sessionId).toBe(sessionId);
|
|
465
|
-
expect(completeMsg.payload?.agentId).toBe("main");
|
|
466
|
-
const terminalErrorEvents = await collectMessages(requester, (msg)=>"event:agent" === msg.type && msg.id === requestId && msg.payload?.type === "agent-error", 400);
|
|
467
|
-
expect(terminalErrorEvents).toHaveLength(0);
|
|
468
|
-
requester.close();
|
|
469
|
-
});
|
|
470
|
-
it("should emit a single agent-complete terminal event per request", async ()=>{
|
|
471
|
-
const requester = await connectClient("session-single-complete-requester");
|
|
472
|
-
const requestId = "req-single-complete";
|
|
473
|
-
const sessionId = "session-single-complete";
|
|
474
|
-
const completionEventsPromise = collectMessages(requester, (msg)=>"event:agent" === msg.type && msg.id === requestId && msg.payload?.type === "agent-complete", 1000);
|
|
475
|
-
requester.send(JSON.stringify({
|
|
476
|
-
type: "req:agent",
|
|
477
|
-
id: requestId,
|
|
478
|
-
payload: {
|
|
479
|
-
agentId: "main",
|
|
480
|
-
sessionKey: sessionId,
|
|
481
|
-
content: "single-complete"
|
|
482
|
-
},
|
|
483
|
-
timestamp: Date.now()
|
|
484
|
-
}));
|
|
485
|
-
const completionEvents = await completionEventsPromise;
|
|
486
|
-
expect(completionEvents).toHaveLength(1);
|
|
487
|
-
expect(completionEvents[0].payload?.sessionId).toBe(sessionId);
|
|
488
|
-
expect(completionEvents[0].payload?.agentId).toBe("main");
|
|
489
|
-
requester.close();
|
|
490
|
-
});
|
|
491
|
-
it("uses request execution workspace/configDir overrides for agent invocation", async ()=>{
|
|
492
|
-
const requester = await connectClient("session-workspace-override-requester");
|
|
493
|
-
const requestId = "req-workspace-override";
|
|
494
|
-
const sessionId = "session-workspace-override";
|
|
495
|
-
const workspaceOverride = "/tmp/wingman-override-workspace";
|
|
496
|
-
const configDirOverride = ".wingman-custom";
|
|
497
|
-
const beforeCount = invokerConstructOptions.length;
|
|
498
|
-
requester.send(JSON.stringify({
|
|
499
|
-
type: "req:agent",
|
|
500
|
-
id: requestId,
|
|
501
|
-
payload: {
|
|
502
|
-
agentId: "main",
|
|
503
|
-
sessionKey: sessionId,
|
|
504
|
-
content: "workspace override test",
|
|
505
|
-
execution: {
|
|
506
|
-
workspace: workspaceOverride,
|
|
507
|
-
configDir: configDirOverride
|
|
508
|
-
}
|
|
509
|
-
},
|
|
510
|
-
timestamp: Date.now()
|
|
511
|
-
}));
|
|
512
|
-
await waitForMessage(requester, (msg)=>"event:agent" === msg.type && msg.id === requestId && msg.payload?.type === "agent-complete", 10000);
|
|
513
|
-
expect(invokerConstructOptions.length).toBeGreaterThan(beforeCount);
|
|
514
|
-
const lastOptions = invokerConstructOptions.at(-1) || {};
|
|
515
|
-
expect(lastOptions.workspace).toBe(workspaceOverride);
|
|
516
|
-
expect(lastOptions.configDir).toBe(configDirOverride);
|
|
517
|
-
expect(typeof lastOptions.nodeInvoker).toBe("function");
|
|
518
|
-
requester.close();
|
|
519
|
-
});
|
|
520
|
-
it("should cancel an in-flight agent request", async ()=>{
|
|
521
|
-
const requester = await connectClient("session-cancel-requester");
|
|
522
|
-
const requestId = "req-cancel-test";
|
|
523
|
-
requester.send(JSON.stringify({
|
|
524
|
-
type: "req:agent",
|
|
525
|
-
id: requestId,
|
|
526
|
-
payload: {
|
|
527
|
-
agentId: "main",
|
|
528
|
-
sessionKey: "session-cancel-test",
|
|
529
|
-
content: "cancel me"
|
|
530
|
-
},
|
|
531
|
-
timestamp: Date.now()
|
|
532
|
-
}));
|
|
533
|
-
requester.send(JSON.stringify({
|
|
534
|
-
type: "req:agent:cancel",
|
|
535
|
-
id: "cancel-req-cancel-test",
|
|
536
|
-
payload: {
|
|
537
|
-
requestId
|
|
538
|
-
},
|
|
539
|
-
timestamp: Date.now()
|
|
540
|
-
}));
|
|
541
|
-
const ack = await waitForMessage(requester, (msg)=>"ack" === msg.type && msg.payload?.action === "req:agent:cancel" && msg.payload?.requestId === requestId);
|
|
542
|
-
expect([
|
|
543
|
-
"cancelled",
|
|
544
|
-
"not_found"
|
|
545
|
-
]).toContain(ack.payload?.status);
|
|
546
|
-
requester.close();
|
|
547
|
-
});
|
|
548
|
-
it("should queue and dequeue requests for the same session", async ()=>{
|
|
549
|
-
const requester = await connectClient("session-queue-requester");
|
|
550
|
-
const sessionId = `session-queue-${Date.now()}`;
|
|
551
|
-
const firstRequestId = `req-queue-first-${Date.now()}`;
|
|
552
|
-
const secondRequestId = `req-queue-second-${Date.now()}`;
|
|
553
|
-
const firstCompletePromise = waitForMessage(requester, (msg)=>"event:agent" === msg.type && msg.id === firstRequestId && msg.payload?.type === "agent-complete", 10000);
|
|
554
|
-
const queuedAckPromise = waitForMessage(requester, (msg)=>"ack" === msg.type && msg.id === secondRequestId && msg.payload?.action === "req:agent" && msg.payload?.status === "queued", 10000);
|
|
555
|
-
const queuedEventPromise = waitForMessage(requester, (msg)=>"event:agent" === msg.type && msg.id === secondRequestId && msg.payload?.type === "request-queued", 10000);
|
|
556
|
-
const dequeuedAckPromise = waitForMessage(requester, (msg)=>"ack" === msg.type && msg.id === secondRequestId && msg.payload?.action === "req:agent" && msg.payload?.status === "dequeued", 10000);
|
|
557
|
-
const secondCompletePromise = waitForMessage(requester, (msg)=>"event:agent" === msg.type && msg.id === secondRequestId && msg.payload?.type === "agent-complete", 10000);
|
|
558
|
-
requester.send(JSON.stringify({
|
|
559
|
-
type: "req:agent",
|
|
560
|
-
id: firstRequestId,
|
|
561
|
-
payload: {
|
|
562
|
-
agentId: "main",
|
|
563
|
-
sessionKey: sessionId,
|
|
564
|
-
content: "First queued request"
|
|
565
|
-
},
|
|
566
|
-
timestamp: Date.now()
|
|
567
|
-
}));
|
|
568
|
-
requester.send(JSON.stringify({
|
|
569
|
-
type: "req:agent",
|
|
570
|
-
id: secondRequestId,
|
|
571
|
-
payload: {
|
|
572
|
-
agentId: "main",
|
|
573
|
-
sessionKey: sessionId,
|
|
574
|
-
content: "Second queued request"
|
|
575
|
-
},
|
|
576
|
-
timestamp: Date.now()
|
|
577
|
-
}));
|
|
578
|
-
const queuedAck = await queuedAckPromise;
|
|
579
|
-
expect(queuedAck.payload?.position).toBe(1);
|
|
580
|
-
const queuedEvent = await queuedEventPromise;
|
|
581
|
-
expect(queuedEvent.payload?.position).toBe(1);
|
|
582
|
-
expect(queuedEvent.payload?.sessionId).toBe(sessionId);
|
|
583
|
-
await firstCompletePromise;
|
|
584
|
-
const dequeuedAck = await dequeuedAckPromise;
|
|
585
|
-
expect(dequeuedAck.payload?.remaining).toBe(0);
|
|
586
|
-
await secondCompletePromise;
|
|
587
|
-
requester.close();
|
|
588
|
-
});
|
|
589
|
-
it("should cancel a queued request", async ()=>{
|
|
590
|
-
const requester = await connectClient("session-cancel-queued-requester");
|
|
591
|
-
const sessionId = `session-cancel-queued-${Date.now()}`;
|
|
592
|
-
const firstRequestId = `req-cancel-queued-first-${Date.now()}`;
|
|
593
|
-
const secondRequestId = `req-cancel-queued-second-${Date.now()}`;
|
|
594
|
-
const queuedAckPromise = waitForMessage(requester, (msg)=>"ack" === msg.type && msg.id === secondRequestId && msg.payload?.action === "req:agent" && msg.payload?.status === "queued", 10000);
|
|
595
|
-
requester.send(JSON.stringify({
|
|
596
|
-
type: "req:agent",
|
|
597
|
-
id: firstRequestId,
|
|
598
|
-
payload: {
|
|
599
|
-
agentId: "main",
|
|
600
|
-
sessionKey: sessionId,
|
|
601
|
-
content: "First request"
|
|
602
|
-
},
|
|
603
|
-
timestamp: Date.now()
|
|
604
|
-
}));
|
|
605
|
-
requester.send(JSON.stringify({
|
|
606
|
-
type: "req:agent",
|
|
607
|
-
id: secondRequestId,
|
|
608
|
-
payload: {
|
|
609
|
-
agentId: "main",
|
|
610
|
-
sessionKey: sessionId,
|
|
611
|
-
content: "Second request"
|
|
612
|
-
},
|
|
613
|
-
timestamp: Date.now()
|
|
614
|
-
}));
|
|
615
|
-
await queuedAckPromise;
|
|
616
|
-
requester.send(JSON.stringify({
|
|
617
|
-
type: "req:agent:cancel",
|
|
618
|
-
id: `cancel-${secondRequestId}`,
|
|
619
|
-
payload: {
|
|
620
|
-
requestId: secondRequestId
|
|
621
|
-
},
|
|
622
|
-
timestamp: Date.now()
|
|
623
|
-
}));
|
|
624
|
-
const cancelAck = await waitForMessage(requester, (msg)=>"ack" === msg.type && msg.payload?.action === "req:agent:cancel" && msg.payload?.requestId === secondRequestId && msg.payload?.status === "cancelled_queued", 10000);
|
|
625
|
-
expect(cancelAck.payload?.status).toBe("cancelled_queued");
|
|
626
|
-
const cancelEvent = await waitForMessage(requester, (msg)=>"event:agent" === msg.type && msg.id === secondRequestId && msg.payload?.type === "agent-error" && /cancel/i.test(String(msg.payload?.error || "")), 10000);
|
|
627
|
-
expect(cancelEvent.payload?.sessionId).toBe(sessionId);
|
|
628
|
-
expect(cancelEvent.payload?.agentId).toBe("main");
|
|
629
|
-
await waitForMessage(requester, (msg)=>"event:agent" === msg.type && msg.id === firstRequestId && msg.payload?.type === "agent-complete", 10000);
|
|
630
|
-
const queuedRequests = server.queuedSessionRequests;
|
|
631
|
-
const isStillQueued = [
|
|
632
|
-
...queuedRequests.values()
|
|
633
|
-
].some((queue)=>queue.some((item)=>item.msg?.id === secondRequestId));
|
|
634
|
-
expect(isStillQueued).toBe(false);
|
|
635
|
-
requester.close();
|
|
636
|
-
});
|
|
637
|
-
it("should clear session messages via API", async ()=>{
|
|
638
|
-
const createRes = await fetch(`http://localhost:${port}/api/sessions`, {
|
|
639
|
-
method: "POST",
|
|
640
|
-
headers: {
|
|
641
|
-
"Content-Type": "application/json"
|
|
642
|
-
},
|
|
643
|
-
body: JSON.stringify({
|
|
644
|
-
name: "Clear Test"
|
|
645
|
-
})
|
|
646
|
-
});
|
|
647
|
-
expect(createRes.ok).toBe(true);
|
|
648
|
-
const session = await createRes.json();
|
|
649
|
-
const sessionAgentId = session.agentId || "main";
|
|
650
|
-
const manager = await server.getSessionManager(sessionAgentId);
|
|
651
|
-
manager.updateSession(session.id, {
|
|
652
|
-
messageCount: 3,
|
|
653
|
-
lastMessagePreview: "Hello"
|
|
654
|
-
});
|
|
655
|
-
const clearRes = await fetch(`http://localhost:${port}/api/sessions/${encodeURIComponent(session.id)}/messages?agentId=${encodeURIComponent(sessionAgentId)}`, {
|
|
656
|
-
method: "DELETE"
|
|
657
|
-
});
|
|
658
|
-
expect(clearRes.ok).toBe(true);
|
|
659
|
-
const cleared = await clearRes.json();
|
|
660
|
-
expect(cleared.messageCount).toBe(0);
|
|
661
|
-
const updated = manager.getSession(session.id);
|
|
662
|
-
expect(updated?.messageCount).toBe(0);
|
|
663
|
-
expect(updated?.lastMessagePreview).toBeNull();
|
|
664
|
-
});
|
|
665
|
-
it("persists failed first-turn messages so the thread survives reload", async ()=>{
|
|
666
|
-
const requester = await connectClient("persist-failed-turn-requester");
|
|
667
|
-
const sessionId = `session-persist-failed-${Date.now()}`;
|
|
668
|
-
const requestId = `req-persist-failed-${Date.now()}`;
|
|
669
|
-
requester.send(JSON.stringify({
|
|
670
|
-
type: "req:agent",
|
|
671
|
-
id: requestId,
|
|
672
|
-
payload: {
|
|
673
|
-
agentId: "main",
|
|
674
|
-
sessionKey: sessionId,
|
|
675
|
-
content: "throw-no-event"
|
|
676
|
-
},
|
|
677
|
-
timestamp: Date.now()
|
|
678
|
-
}));
|
|
679
|
-
await waitForMessage(requester, (msg)=>"event:agent" === msg.type && msg.id === requestId && msg.payload?.type === "agent-error", 10000);
|
|
680
|
-
const sessionsRes = await fetch(`http://localhost:${port}/api/sessions?limit=100`);
|
|
681
|
-
expect(sessionsRes.ok).toBe(true);
|
|
682
|
-
const sessions = await sessionsRes.json();
|
|
683
|
-
const created = sessions.find((session)=>session.id === sessionId);
|
|
684
|
-
expect(created).toBeTruthy();
|
|
685
|
-
expect(created?.messageCount).toBe(1);
|
|
686
|
-
const messagesRes = await fetch(`http://localhost:${port}/api/sessions/${encodeURIComponent(sessionId)}/messages?agentId=main`);
|
|
687
|
-
expect(messagesRes.ok).toBe(true);
|
|
688
|
-
const messages = await messagesRes.json();
|
|
689
|
-
expect(messages.some((message)=>"user" === message.role)).toBe(true);
|
|
690
|
-
expect(messages.some((message)=>"user" === message.role && message.content.includes("throw-no-event"))).toBe(true);
|
|
691
|
-
expect(messages.some((message)=>"assistant" === message.role && message.content.includes("Synthetic invocation failure"))).toBe(true);
|
|
692
|
-
requester.close();
|
|
693
|
-
});
|
|
694
|
-
});
|