@wingman-ai/gateway 0.2.2 → 0.2.4
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/.wingman/agents/README.md +7 -1
- package/.wingman/agents/coding/agent.md +299 -201
- package/.wingman/agents/coding-v2/agent.md +127 -0
- package/.wingman/agents/coding-v2/implementor.md +89 -0
- package/.wingman/agents/main/agent.md +4 -0
- package/README.md +1 -0
- package/dist/agent/config/agentConfig.cjs +31 -17
- package/dist/agent/config/agentConfig.d.ts +23 -1
- package/dist/agent/config/agentConfig.js +30 -19
- package/dist/agent/config/agentLoader.cjs +26 -8
- package/dist/agent/config/agentLoader.d.ts +4 -2
- package/dist/agent/config/agentLoader.js +26 -8
- package/dist/agent/config/modelFactory.cjs +95 -25
- package/dist/agent/config/modelFactory.d.ts +13 -1
- package/dist/agent/config/modelFactory.js +95 -25
- package/dist/agent/config/toolRegistry.cjs +19 -6
- package/dist/agent/config/toolRegistry.d.ts +5 -2
- package/dist/agent/config/toolRegistry.js +19 -6
- package/dist/agent/middleware/hooks/types.cjs +13 -13
- package/dist/agent/middleware/hooks/types.d.ts +1 -1
- package/dist/agent/middleware/hooks/types.js +14 -14
- package/dist/agent/tests/agentConfig.test.cjs +22 -2
- package/dist/agent/tests/agentConfig.test.js +22 -2
- package/dist/agent/tests/agentLoader.test.cjs +38 -1
- package/dist/agent/tests/agentLoader.test.js +38 -1
- package/dist/agent/tests/backgroundTerminal.test.cjs +70 -0
- package/dist/agent/tests/backgroundTerminal.test.d.ts +1 -0
- package/dist/agent/tests/backgroundTerminal.test.js +64 -0
- package/dist/agent/tests/commandExecuteTool.test.cjs +29 -0
- package/dist/agent/tests/commandExecuteTool.test.d.ts +1 -0
- package/dist/agent/tests/commandExecuteTool.test.js +23 -0
- package/dist/agent/tests/modelFactory.test.cjs +47 -5
- package/dist/agent/tests/modelFactory.test.js +47 -5
- package/dist/agent/tests/terminalSessionManager.test.cjs +121 -0
- package/dist/agent/tests/terminalSessionManager.test.d.ts +1 -0
- package/dist/agent/tests/terminalSessionManager.test.js +115 -0
- package/dist/agent/tests/toolRegistry.test.cjs +14 -2
- package/dist/agent/tests/toolRegistry.test.js +14 -2
- package/dist/agent/tools/background_terminal.cjs +128 -0
- package/dist/agent/tools/background_terminal.d.ts +41 -0
- package/dist/agent/tools/background_terminal.js +94 -0
- package/dist/agent/tools/code_search.cjs +6 -6
- package/dist/agent/tools/code_search.d.ts +1 -1
- package/dist/agent/tools/code_search.js +7 -7
- package/dist/agent/tools/command_execute.cjs +22 -7
- package/dist/agent/tools/command_execute.d.ts +3 -2
- package/dist/agent/tools/command_execute.js +23 -8
- package/dist/agent/tools/git_status.cjs +3 -3
- package/dist/agent/tools/git_status.d.ts +1 -1
- package/dist/agent/tools/git_status.js +4 -4
- package/dist/agent/tools/internet_search.cjs +6 -6
- package/dist/agent/tools/internet_search.d.ts +1 -1
- package/dist/agent/tools/internet_search.js +7 -7
- package/dist/agent/tools/terminal_session_manager.cjs +321 -0
- package/dist/agent/tools/terminal_session_manager.d.ts +77 -0
- package/dist/agent/tools/terminal_session_manager.js +284 -0
- package/dist/agent/tools/think.cjs +4 -4
- package/dist/agent/tools/think.d.ts +1 -1
- package/dist/agent/tools/think.js +5 -5
- package/dist/agent/tools/ui_registry.cjs +13 -13
- package/dist/agent/tools/ui_registry.d.ts +4 -4
- package/dist/agent/tools/ui_registry.js +14 -14
- package/dist/agent/tools/web_crawler.cjs +4 -4
- package/dist/agent/tools/web_crawler.d.ts +1 -1
- package/dist/agent/tools/web_crawler.js +5 -5
- package/dist/agent/utils.cjs +2 -1
- package/dist/agent/utils.js +2 -1
- package/dist/cli/commands/init.cjs +7 -6
- package/dist/cli/commands/init.js +7 -6
- package/dist/cli/commands/provider.cjs +17 -3
- package/dist/cli/commands/provider.js +17 -3
- package/dist/cli/config/loader.cjs +27 -0
- package/dist/cli/config/loader.js +27 -0
- package/dist/cli/config/schema.cjs +146 -68
- package/dist/cli/config/schema.d.ts +89 -1
- package/dist/cli/config/schema.js +134 -68
- package/dist/cli/core/agentInvoker.cjs +344 -17
- package/dist/cli/core/agentInvoker.d.ts +63 -3
- package/dist/cli/core/agentInvoker.js +303 -12
- package/dist/cli/core/sessionManager.cjs +32 -5
- package/dist/cli/core/sessionManager.js +32 -5
- package/dist/cli/core/streamParser.cjs +15 -0
- package/dist/cli/core/streamParser.js +15 -0
- package/dist/cli/index.cjs +6 -5
- package/dist/cli/index.js +6 -5
- package/dist/cli/types.d.ts +32 -0
- package/dist/cli/ui/toolDisplayHelpers.cjs +2 -0
- package/dist/cli/ui/toolDisplayHelpers.js +2 -0
- package/dist/gateway/hooks/registry.cjs +2 -1
- package/dist/gateway/hooks/registry.d.ts +1 -1
- package/dist/gateway/hooks/registry.js +2 -1
- package/dist/gateway/hooks/types.cjs +11 -11
- package/dist/gateway/hooks/types.d.ts +1 -1
- package/dist/gateway/hooks/types.js +12 -12
- package/dist/gateway/http/agents.cjs +67 -4
- package/dist/gateway/http/agents.js +67 -4
- package/dist/gateway/http/sessions.cjs +7 -7
- package/dist/gateway/http/sessions.js +7 -7
- package/dist/gateway/http/types.d.ts +5 -3
- package/dist/gateway/http/webhooks.cjs +6 -5
- package/dist/gateway/http/webhooks.js +6 -5
- package/dist/gateway/server.cjs +198 -41
- package/dist/gateway/server.d.ts +9 -1
- package/dist/gateway/server.js +198 -41
- package/dist/gateway/types.d.ts +1 -0
- package/dist/gateway/validation.cjs +39 -39
- package/dist/gateway/validation.d.ts +1 -1
- package/dist/gateway/validation.js +40 -40
- package/dist/providers/codex.cjs +167 -0
- package/dist/providers/codex.d.ts +15 -0
- package/dist/providers/codex.js +127 -0
- package/dist/providers/credentials.cjs +8 -0
- package/dist/providers/credentials.js +8 -0
- package/dist/providers/registry.cjs +11 -0
- package/dist/providers/registry.d.ts +1 -1
- package/dist/providers/registry.js +11 -0
- package/dist/tests/additionalMessageMiddleware.test.cjs +3 -0
- package/dist/tests/additionalMessageMiddleware.test.js +3 -0
- package/dist/tests/agentInvokerSummarization.test.cjs +455 -0
- package/dist/tests/agentInvokerSummarization.test.d.ts +1 -0
- package/dist/tests/agentInvokerSummarization.test.js +449 -0
- package/dist/tests/agents-api.test.cjs +45 -5
- package/dist/tests/agents-api.test.js +45 -5
- package/dist/tests/cli-config-loader.test.cjs +88 -0
- package/dist/tests/cli-config-loader.test.js +88 -0
- package/dist/tests/cli-init.test.cjs +27 -3
- package/dist/tests/cli-init.test.js +27 -3
- package/dist/tests/codex-credentials-precedence.test.cjs +94 -0
- package/dist/tests/codex-credentials-precedence.test.d.ts +1 -0
- package/dist/tests/codex-credentials-precedence.test.js +88 -0
- package/dist/tests/codex-provider.test.cjs +210 -0
- package/dist/tests/codex-provider.test.d.ts +1 -0
- package/dist/tests/codex-provider.test.js +204 -0
- package/dist/tests/gateway.test.cjs +115 -8
- package/dist/tests/gateway.test.js +115 -8
- package/dist/tests/provider-command-codex.test.cjs +57 -0
- package/dist/tests/provider-command-codex.test.d.ts +1 -0
- package/dist/tests/provider-command-codex.test.js +51 -0
- package/dist/tests/sessionStateMessages.test.cjs +38 -0
- package/dist/tests/sessionStateMessages.test.js +38 -0
- package/dist/tests/toolDisplayHelpers.test.cjs +3 -0
- package/dist/tests/toolDisplayHelpers.test.js +3 -0
- package/dist/tools/mcp-finance.cjs +48 -48
- package/dist/tools/mcp-finance.js +48 -48
- package/dist/types/mcp.cjs +15 -15
- package/dist/types/mcp.d.ts +1 -1
- package/dist/types/mcp.js +16 -16
- package/dist/types/voice.cjs +21 -21
- package/dist/types/voice.d.ts +1 -1
- package/dist/types/voice.js +22 -22
- package/dist/webui/assets/index-DVWQluit.css +11 -0
- package/dist/webui/assets/index-Dlyzwalc.js +270 -0
- package/dist/webui/favicon-32x32.png +0 -0
- package/dist/webui/favicon-64x64.png +0 -0
- package/dist/webui/favicon.webp +0 -0
- package/dist/webui/index.html +4 -2
- package/package.json +13 -12
- package/.wingman/agents/coding/implementor.md +0 -79
- package/dist/webui/assets/index-CPhfGPHc.js +0 -182
- package/dist/webui/assets/index-DDsMIOTX.css +0 -11
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { GatewayAuth } from "../auth.js";
|
|
3
|
-
import type { Logger } from "@/logger.js";
|
|
1
|
+
import type { TerminalSessionManager } from "@/agent/tools/terminal_session_manager.js";
|
|
4
2
|
import type { WingmanConfigType } from "@/cli/config/schema.js";
|
|
5
3
|
import type { SessionManager } from "@/cli/core/sessionManager.js";
|
|
4
|
+
import type { Logger } from "@/logger.js";
|
|
5
|
+
import type { GatewayAuth } from "../auth.js";
|
|
6
|
+
import type { GatewayRouter } from "../router.js";
|
|
6
7
|
export type GatewayHttpContext = {
|
|
7
8
|
workspace: string;
|
|
8
9
|
configDir: string;
|
|
@@ -21,5 +22,6 @@ export type GatewayHttpContext = {
|
|
|
21
22
|
resolveFsRoots: () => string[];
|
|
22
23
|
resolveFsPath: (path: string) => string;
|
|
23
24
|
isPathWithinRoots: (path: string, roots: string[]) => boolean;
|
|
25
|
+
getTerminalSessionManager: () => TerminalSessionManager;
|
|
24
26
|
getBuiltInTools: () => string[];
|
|
25
27
|
};
|
|
@@ -28,12 +28,12 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
28
28
|
createWebhookStore: ()=>createWebhookStore,
|
|
29
29
|
handleWebhookInvoke: ()=>handleWebhookInvoke
|
|
30
30
|
});
|
|
31
|
-
const agentInvoker_cjs_namespaceObject = require("../../cli/core/agentInvoker.cjs");
|
|
32
|
-
const outputManager_cjs_namespaceObject = require("../../cli/core/outputManager.cjs");
|
|
33
|
-
const agentLoader_cjs_namespaceObject = require("../../agent/config/agentLoader.cjs");
|
|
34
31
|
const external_node_crypto_namespaceObject = require("node:crypto");
|
|
35
32
|
const external_node_fs_namespaceObject = require("node:fs");
|
|
36
33
|
const external_node_path_namespaceObject = require("node:path");
|
|
34
|
+
const agentLoader_cjs_namespaceObject = require("../../agent/config/agentLoader.cjs");
|
|
35
|
+
const agentInvoker_cjs_namespaceObject = require("../../cli/core/agentInvoker.cjs");
|
|
36
|
+
const outputManager_cjs_namespaceObject = require("../../cli/core/outputManager.cjs");
|
|
37
37
|
const WEBHOOK_PRESETS = new Set([
|
|
38
38
|
"gog-gmail"
|
|
39
39
|
]);
|
|
@@ -192,12 +192,12 @@ const handleWebhooksApi = async (ctx, store, req, url)=>{
|
|
|
192
192
|
if (!agentExists(ctx, nextAgentId)) return new Response("Invalid agentId", {
|
|
193
193
|
status: 400
|
|
194
194
|
});
|
|
195
|
-
const hasPreset = Object.
|
|
195
|
+
const hasPreset = Object.hasOwn(body ?? {}, "preset");
|
|
196
196
|
const presetValue = hasPreset ? normalizePreset(body?.preset) : webhook.preset;
|
|
197
197
|
if (hasPreset && body?.preset && !presetValue && "custom" !== body.preset.trim()) return new Response("Invalid preset", {
|
|
198
198
|
status: 400
|
|
199
199
|
});
|
|
200
|
-
const hasSessionId = Object.
|
|
200
|
+
const hasSessionId = Object.hasOwn(body ?? {}, "sessionId");
|
|
201
201
|
let nextSessionId = webhook.sessionId;
|
|
202
202
|
if (hasSessionId) {
|
|
203
203
|
const trimmed = body?.sessionId?.trim();
|
|
@@ -316,6 +316,7 @@ const handleWebhookInvoke = async (ctx, store, req, url)=>{
|
|
|
316
316
|
outputManager,
|
|
317
317
|
logger: ctx.logger,
|
|
318
318
|
sessionManager,
|
|
319
|
+
terminalSessionManager: ctx.getTerminalSessionManager(),
|
|
319
320
|
workdir,
|
|
320
321
|
defaultOutputDir
|
|
321
322
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { AgentInvoker } from "../../cli/core/agentInvoker.js";
|
|
2
|
-
import { OutputManager } from "../../cli/core/outputManager.js";
|
|
3
|
-
import { AgentLoader } from "../../agent/config/agentLoader.js";
|
|
4
1
|
import { randomUUID } from "node:crypto";
|
|
5
2
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
6
3
|
import { join } from "node:path";
|
|
4
|
+
import { AgentLoader } from "../../agent/config/agentLoader.js";
|
|
5
|
+
import { AgentInvoker } from "../../cli/core/agentInvoker.js";
|
|
6
|
+
import { OutputManager } from "../../cli/core/outputManager.js";
|
|
7
7
|
const WEBHOOK_PRESETS = new Set([
|
|
8
8
|
"gog-gmail"
|
|
9
9
|
]);
|
|
@@ -162,12 +162,12 @@ const handleWebhooksApi = async (ctx, store, req, url)=>{
|
|
|
162
162
|
if (!agentExists(ctx, nextAgentId)) return new Response("Invalid agentId", {
|
|
163
163
|
status: 400
|
|
164
164
|
});
|
|
165
|
-
const hasPreset = Object.
|
|
165
|
+
const hasPreset = Object.hasOwn(body ?? {}, "preset");
|
|
166
166
|
const presetValue = hasPreset ? normalizePreset(body?.preset) : webhook.preset;
|
|
167
167
|
if (hasPreset && body?.preset && !presetValue && "custom" !== body.preset.trim()) return new Response("Invalid preset", {
|
|
168
168
|
status: 400
|
|
169
169
|
});
|
|
170
|
-
const hasSessionId = Object.
|
|
170
|
+
const hasSessionId = Object.hasOwn(body ?? {}, "sessionId");
|
|
171
171
|
let nextSessionId = webhook.sessionId;
|
|
172
172
|
if (hasSessionId) {
|
|
173
173
|
const trimmed = body?.sessionId?.trim();
|
|
@@ -286,6 +286,7 @@ const handleWebhookInvoke = async (ctx, store, req, url)=>{
|
|
|
286
286
|
outputManager,
|
|
287
287
|
logger: ctx.logger,
|
|
288
288
|
sessionManager,
|
|
289
|
+
terminalSessionManager: ctx.getTerminalSessionManager(),
|
|
289
290
|
workdir,
|
|
290
291
|
defaultOutputDir
|
|
291
292
|
});
|
package/dist/gateway/server.cjs
CHANGED
|
@@ -29,31 +29,32 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
29
29
|
__webpack_require__.d(__webpack_exports__, {
|
|
30
30
|
GatewayServer: ()=>GatewayServer
|
|
31
31
|
});
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
const index_cjs_namespaceObject = require("./discovery/index.cjs");
|
|
38
|
-
const external_logger_cjs_namespaceObject = require("../logger.cjs");
|
|
32
|
+
const external_node_fs_namespaceObject = require("node:fs");
|
|
33
|
+
const external_node_os_namespaceObject = require("node:os");
|
|
34
|
+
const external_node_path_namespaceObject = require("node:path");
|
|
35
|
+
const external_node_url_namespaceObject = require("node:url");
|
|
36
|
+
const terminal_session_manager_cjs_namespaceObject = require("../agent/tools/terminal_session_manager.cjs");
|
|
39
37
|
const loader_cjs_namespaceObject = require("../cli/config/loader.cjs");
|
|
40
|
-
const external_router_cjs_namespaceObject = require("./router.cjs");
|
|
41
|
-
const outputManager_cjs_namespaceObject = require("../cli/core/outputManager.cjs");
|
|
42
38
|
const agentInvoker_cjs_namespaceObject = require("../cli/core/agentInvoker.cjs");
|
|
39
|
+
const outputManager_cjs_namespaceObject = require("../cli/core/outputManager.cjs");
|
|
43
40
|
const sessionManager_cjs_namespaceObject = require("../cli/core/sessionManager.cjs");
|
|
41
|
+
const external_logger_cjs_namespaceObject = require("../logger.cjs");
|
|
42
|
+
const discord_cjs_namespaceObject = require("./adapters/discord.cjs");
|
|
43
|
+
const external_auth_cjs_namespaceObject = require("./auth.cjs");
|
|
44
|
+
const external_broadcast_cjs_namespaceObject = require("./broadcast.cjs");
|
|
45
|
+
const index_cjs_namespaceObject = require("./discovery/index.cjs");
|
|
46
|
+
const external_env_cjs_namespaceObject = require("./env.cjs");
|
|
47
|
+
const registry_cjs_namespaceObject = require("./hooks/registry.cjs");
|
|
44
48
|
const agents_cjs_namespaceObject = require("./http/agents.cjs");
|
|
45
49
|
const fs_cjs_namespaceObject = require("./http/fs.cjs");
|
|
46
50
|
const providers_cjs_namespaceObject = require("./http/providers.cjs");
|
|
47
|
-
const
|
|
51
|
+
const routines_cjs_namespaceObject = require("./http/routines.cjs");
|
|
48
52
|
const sessions_cjs_namespaceObject = require("./http/sessions.cjs");
|
|
53
|
+
const voice_cjs_namespaceObject = require("./http/voice.cjs");
|
|
49
54
|
const webhooks_cjs_namespaceObject = require("./http/webhooks.cjs");
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
const external_node_os_namespaceObject = require("node:os");
|
|
54
|
-
const external_node_path_namespaceObject = require("node:path");
|
|
55
|
-
const external_node_fs_namespaceObject = require("node:fs");
|
|
56
|
-
const external_node_url_namespaceObject = require("node:url");
|
|
55
|
+
const external_node_cjs_namespaceObject = require("./node.cjs");
|
|
56
|
+
const external_router_cjs_namespaceObject = require("./router.cjs");
|
|
57
|
+
const external_validation_cjs_namespaceObject = require("./validation.cjs");
|
|
57
58
|
function _define_property(obj, key, value) {
|
|
58
59
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
59
60
|
value: value,
|
|
@@ -107,6 +108,7 @@ class GatewayServer {
|
|
|
107
108
|
});
|
|
108
109
|
return;
|
|
109
110
|
}
|
|
111
|
+
if (url.pathname.startsWith("/api/")) return this.handleUiRequest(req);
|
|
110
112
|
const webhookResponse = await (0, webhooks_cjs_namespaceObject.handleWebhookInvoke)(this.getHttpContext(), this.webhookStore, req, url);
|
|
111
113
|
if (webhookResponse) return webhookResponse;
|
|
112
114
|
if (this.controlUiSamePort) return this.handleUiRequest(req);
|
|
@@ -163,6 +165,7 @@ class GatewayServer {
|
|
|
163
165
|
this.uiServer.stop();
|
|
164
166
|
this.uiServer = null;
|
|
165
167
|
}
|
|
168
|
+
this.terminalSessionManager.dispose();
|
|
166
169
|
this.log("info", "Gateway stopped");
|
|
167
170
|
}
|
|
168
171
|
getPort() {
|
|
@@ -350,6 +353,7 @@ class GatewayServer {
|
|
|
350
353
|
existing?.abortController.abort();
|
|
351
354
|
this.activeAgentRequests.delete(msg.id);
|
|
352
355
|
}
|
|
356
|
+
this.removeQueuedRequestById(msg.id);
|
|
353
357
|
const payload = msg.payload;
|
|
354
358
|
const content = "string" == typeof payload?.content ? payload.content : "";
|
|
355
359
|
const attachments = Array.isArray(payload?.attachments) ? payload.attachments : [];
|
|
@@ -359,6 +363,7 @@ class GatewayServer {
|
|
|
359
363
|
const agentId = this.router.selectAgent(payload.agentId, payload.routing);
|
|
360
364
|
if (!agentId) return void this.sendAgentError(ws, msg.id, "No agent matched the request");
|
|
361
365
|
const sessionKey = payload.sessionKey || this.router.buildSessionKey(agentId, payload.routing);
|
|
366
|
+
const sessionQueueKey = this.buildSessionQueueKey(agentId, sessionKey);
|
|
362
367
|
const sessionManager = await this.getSessionManager(agentId);
|
|
363
368
|
const existingSession = sessionManager.getSession(sessionKey);
|
|
364
369
|
const session = existingSession || sessionManager.getOrCreateSession(sessionKey, agentId);
|
|
@@ -409,9 +414,70 @@ class GatewayServer {
|
|
|
409
414
|
],
|
|
410
415
|
skipSessionId: sessionKey
|
|
411
416
|
});
|
|
417
|
+
const request = {
|
|
418
|
+
ws,
|
|
419
|
+
msg,
|
|
420
|
+
payload,
|
|
421
|
+
agentId,
|
|
422
|
+
sessionKey,
|
|
423
|
+
sessionQueueKey,
|
|
424
|
+
content,
|
|
425
|
+
attachments,
|
|
426
|
+
sessionManager,
|
|
427
|
+
workdir,
|
|
428
|
+
defaultOutputDir
|
|
429
|
+
};
|
|
430
|
+
this.requestSessionKeys.set(msg.id, sessionQueueKey);
|
|
431
|
+
const queueIfBusy = false !== payload.queueIfBusy;
|
|
432
|
+
const activeRequestId = this.activeSessionRequests.get(sessionQueueKey);
|
|
433
|
+
if (activeRequestId && queueIfBusy) {
|
|
434
|
+
const queued = this.queuedSessionRequests.get(sessionQueueKey) || [];
|
|
435
|
+
queued.push(request);
|
|
436
|
+
this.queuedSessionRequests.set(sessionQueueKey, queued);
|
|
437
|
+
const position = queued.length;
|
|
438
|
+
this.sendMessage(ws, {
|
|
439
|
+
type: "ack",
|
|
440
|
+
id: msg.id,
|
|
441
|
+
payload: {
|
|
442
|
+
action: "req:agent",
|
|
443
|
+
status: "queued",
|
|
444
|
+
requestId: msg.id,
|
|
445
|
+
sessionId: sessionKey,
|
|
446
|
+
agentId,
|
|
447
|
+
position
|
|
448
|
+
},
|
|
449
|
+
timestamp: Date.now()
|
|
450
|
+
});
|
|
451
|
+
this.sendMessage(ws, {
|
|
452
|
+
type: "event:agent",
|
|
453
|
+
id: msg.id,
|
|
454
|
+
clientId: ws.data.clientId,
|
|
455
|
+
payload: this.attachSessionContext({
|
|
456
|
+
type: "request-queued",
|
|
457
|
+
position
|
|
458
|
+
}, sessionKey, agentId),
|
|
459
|
+
timestamp: Date.now()
|
|
460
|
+
});
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
if (activeRequestId && !queueIfBusy) {
|
|
464
|
+
this.requestSessionKeys.delete(msg.id);
|
|
465
|
+
this.sendAgentError(ws, msg.id, "Session already has an in-flight request. Set queueIfBusy=true to enqueue.", {
|
|
466
|
+
sessionId: sessionKey,
|
|
467
|
+
agentId
|
|
468
|
+
});
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
this.executeAgentRequest(request);
|
|
472
|
+
}
|
|
473
|
+
async executeAgentRequest(request) {
|
|
474
|
+
const { ws, msg, agentId, sessionKey, sessionQueueKey, content, attachments, sessionManager, workdir, defaultOutputDir } = request;
|
|
475
|
+
this.activeSessionRequests.set(sessionQueueKey, msg.id);
|
|
412
476
|
const outputManager = new outputManager_cjs_namespaceObject.OutputManager("interactive");
|
|
477
|
+
let emittedAgentError = false;
|
|
413
478
|
const outputHandler = (event)=>{
|
|
414
479
|
const payloadWithSession = this.attachSessionContext(event, sessionKey, agentId);
|
|
480
|
+
if (payloadWithSession && "object" == typeof payloadWithSession && !Array.isArray(payloadWithSession) && "agent-error" === payloadWithSession.type) emittedAgentError = true;
|
|
415
481
|
const baseMessage = {
|
|
416
482
|
type: "event:agent",
|
|
417
483
|
id: msg.id,
|
|
@@ -432,6 +498,7 @@ class GatewayServer {
|
|
|
432
498
|
outputManager,
|
|
433
499
|
logger: this.logger,
|
|
434
500
|
sessionManager,
|
|
501
|
+
terminalSessionManager: this.terminalSessionManager,
|
|
435
502
|
workdir,
|
|
436
503
|
defaultOutputDir
|
|
437
504
|
});
|
|
@@ -450,41 +517,111 @@ class GatewayServer {
|
|
|
450
517
|
});
|
|
451
518
|
} catch (error) {
|
|
452
519
|
this.logger.error("Agent invocation failed", error);
|
|
520
|
+
if (!emittedAgentError) {
|
|
521
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
522
|
+
const stack = error instanceof Error ? error.stack : void 0;
|
|
523
|
+
this.sendAgentError(ws, msg.id, message, {
|
|
524
|
+
sessionId: sessionKey,
|
|
525
|
+
agentId,
|
|
526
|
+
stack,
|
|
527
|
+
broadcastToSession: true,
|
|
528
|
+
exclude: ws
|
|
529
|
+
});
|
|
530
|
+
}
|
|
453
531
|
} finally{
|
|
454
532
|
this.activeAgentRequests.delete(msg.id);
|
|
533
|
+
this.activeSessionRequests.delete(sessionQueueKey);
|
|
534
|
+
this.requestSessionKeys.delete(msg.id);
|
|
455
535
|
outputManager.off("output-event", outputHandler);
|
|
536
|
+
this.processNextQueuedAgentRequest(sessionQueueKey);
|
|
456
537
|
}
|
|
457
538
|
}
|
|
539
|
+
processNextQueuedAgentRequest(sessionQueueKey) {
|
|
540
|
+
if (this.activeSessionRequests.has(sessionQueueKey)) return;
|
|
541
|
+
const queue = this.queuedSessionRequests.get(sessionQueueKey);
|
|
542
|
+
if (!queue || 0 === queue.length) return void this.queuedSessionRequests.delete(sessionQueueKey);
|
|
543
|
+
const next = queue.shift();
|
|
544
|
+
if (!next) return;
|
|
545
|
+
if (0 === queue.length) this.queuedSessionRequests.delete(sessionQueueKey);
|
|
546
|
+
else this.queuedSessionRequests.set(sessionQueueKey, queue);
|
|
547
|
+
this.sendMessage(next.ws, {
|
|
548
|
+
type: "ack",
|
|
549
|
+
id: next.msg.id,
|
|
550
|
+
payload: {
|
|
551
|
+
action: "req:agent",
|
|
552
|
+
status: "dequeued",
|
|
553
|
+
requestId: next.msg.id,
|
|
554
|
+
sessionId: next.sessionKey,
|
|
555
|
+
agentId: next.agentId,
|
|
556
|
+
remaining: queue.length
|
|
557
|
+
},
|
|
558
|
+
timestamp: Date.now()
|
|
559
|
+
});
|
|
560
|
+
this.executeAgentRequest(next);
|
|
561
|
+
}
|
|
458
562
|
handleAgentCancel(ws, msg) {
|
|
459
563
|
if (!ws.data.authenticated) return void this.sendError(ws, "AUTH_FAILED", "Client is not authenticated");
|
|
460
564
|
const payload = msg.payload;
|
|
461
565
|
const requestId = "string" == typeof payload?.requestId && payload.requestId || void 0;
|
|
462
566
|
if (!requestId) return void this.sendError(ws, "INVALID_REQUEST", "Missing requestId for cancellation");
|
|
463
567
|
const active = this.activeAgentRequests.get(requestId);
|
|
464
|
-
if (
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
568
|
+
if (active) {
|
|
569
|
+
if (active.socket !== ws) return void this.sendError(ws, "FORBIDDEN", "Cannot cancel a request started by another client");
|
|
570
|
+
active.abortController.abort();
|
|
571
|
+
this.activeAgentRequests.delete(requestId);
|
|
572
|
+
this.sendMessage(ws, {
|
|
573
|
+
type: "ack",
|
|
574
|
+
id: msg.id,
|
|
575
|
+
payload: {
|
|
576
|
+
action: "req:agent:cancel",
|
|
577
|
+
requestId,
|
|
578
|
+
status: "cancelled"
|
|
579
|
+
},
|
|
580
|
+
timestamp: Date.now()
|
|
581
|
+
});
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
const queued = this.removeQueuedRequestById(requestId);
|
|
585
|
+
if (queued) {
|
|
586
|
+
if (queued.ws !== ws) return void this.sendError(ws, "FORBIDDEN", "Cannot cancel a request started by another client");
|
|
587
|
+
this.sendMessage(ws, {
|
|
588
|
+
type: "ack",
|
|
589
|
+
id: msg.id,
|
|
590
|
+
payload: {
|
|
591
|
+
action: "req:agent:cancel",
|
|
592
|
+
requestId,
|
|
593
|
+
status: "cancelled_queued"
|
|
594
|
+
},
|
|
595
|
+
timestamp: Date.now()
|
|
596
|
+
});
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
477
599
|
this.sendMessage(ws, {
|
|
478
600
|
type: "ack",
|
|
479
601
|
id: msg.id,
|
|
480
602
|
payload: {
|
|
481
603
|
action: "req:agent:cancel",
|
|
482
604
|
requestId,
|
|
483
|
-
status: "
|
|
605
|
+
status: "not_found"
|
|
484
606
|
},
|
|
485
607
|
timestamp: Date.now()
|
|
486
608
|
});
|
|
487
609
|
}
|
|
610
|
+
buildSessionQueueKey(agentId, sessionKey) {
|
|
611
|
+
return `${agentId}:${sessionKey}`;
|
|
612
|
+
}
|
|
613
|
+
removeQueuedRequestById(requestId) {
|
|
614
|
+
for (const [queueKey, queue] of this.queuedSessionRequests){
|
|
615
|
+
const index = queue.findIndex((item)=>item.msg.id === requestId);
|
|
616
|
+
if (-1 === index) continue;
|
|
617
|
+
const [removed] = queue.splice(index, 1);
|
|
618
|
+
if (0 === queue.length) this.queuedSessionRequests.delete(queueKey);
|
|
619
|
+
else this.queuedSessionRequests.set(queueKey, queue);
|
|
620
|
+
this.requestSessionKeys.delete(requestId);
|
|
621
|
+
return removed || null;
|
|
622
|
+
}
|
|
623
|
+
return null;
|
|
624
|
+
}
|
|
488
625
|
handleRegister(ws, msg) {
|
|
489
626
|
const payload = msg.payload;
|
|
490
627
|
if (!this.auth.validate({
|
|
@@ -647,23 +784,39 @@ class GatewayServer {
|
|
|
647
784
|
timestamp: Date.now()
|
|
648
785
|
});
|
|
649
786
|
}
|
|
650
|
-
sendAgentError(ws, requestId, message) {
|
|
651
|
-
|
|
787
|
+
sendAgentError(ws, requestId, message, options) {
|
|
788
|
+
let payload = {
|
|
789
|
+
type: "agent-error",
|
|
790
|
+
error: message,
|
|
791
|
+
timestamp: new Date().toISOString()
|
|
792
|
+
};
|
|
793
|
+
if (options?.stack) payload.stack = options.stack;
|
|
794
|
+
if (options?.sessionId && options?.agentId) payload = this.attachSessionContext(payload, options.sessionId, options.agentId);
|
|
795
|
+
const baseMessage = {
|
|
652
796
|
type: "event:agent",
|
|
653
797
|
id: requestId,
|
|
654
|
-
payload
|
|
655
|
-
type: "agent-error",
|
|
656
|
-
error: message,
|
|
657
|
-
timestamp: new Date().toISOString()
|
|
658
|
-
},
|
|
798
|
+
payload,
|
|
659
799
|
timestamp: Date.now()
|
|
800
|
+
};
|
|
801
|
+
this.sendMessage(ws, {
|
|
802
|
+
...baseMessage,
|
|
803
|
+
clientId: ws.data.clientId
|
|
660
804
|
});
|
|
805
|
+
if (options?.broadcastToSession && options.sessionId) this.broadcastSessionEvent(options.sessionId, baseMessage, options.exclude);
|
|
661
806
|
}
|
|
662
807
|
cancelSocketAgentRequests(ws) {
|
|
663
808
|
for (const [requestId, active] of this.activeAgentRequests)if (active.socket === ws) {
|
|
664
809
|
active.abortController.abort();
|
|
665
810
|
this.activeAgentRequests.delete(requestId);
|
|
666
811
|
}
|
|
812
|
+
for (const [queueKey, queue] of this.queuedSessionRequests){
|
|
813
|
+
const nextQueue = queue.filter((request)=>request.ws !== ws);
|
|
814
|
+
if (nextQueue.length !== queue.length) {
|
|
815
|
+
for (const request of queue)if (request.ws === ws && request.msg.id) this.requestSessionKeys.delete(request.msg.id);
|
|
816
|
+
if (0 === nextQueue.length) this.queuedSessionRequests.delete(queueKey);
|
|
817
|
+
else this.queuedSessionRequests.set(queueKey, nextQueue);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
667
820
|
}
|
|
668
821
|
attachSessionContext(event, sessionId, agentId) {
|
|
669
822
|
if (event && "object" == typeof event && !Array.isArray(event)) return {
|
|
@@ -783,6 +936,7 @@ class GatewayServer {
|
|
|
783
936
|
resolveFsRoots: ()=>this.resolveFsRoots(),
|
|
784
937
|
resolveFsPath: (path)=>this.resolveFsPath(path),
|
|
785
938
|
isPathWithinRoots: (path, roots)=>this.isPathWithinRoots(path, roots),
|
|
939
|
+
getTerminalSessionManager: ()=>this.terminalSessionManager,
|
|
786
940
|
getBuiltInTools: ()=>this.getBuiltInTools()
|
|
787
941
|
};
|
|
788
942
|
}
|
|
@@ -855,9 +1009,7 @@ class GatewayServer {
|
|
|
855
1009
|
];
|
|
856
1010
|
for (const candidate of candidates)try {
|
|
857
1011
|
if ((0, external_node_fs_namespaceObject.existsSync)(candidate) && (0, external_node_fs_namespaceObject.statSync)(candidate).isDirectory() && (0, external_node_fs_namespaceObject.existsSync)((0, external_node_path_namespaceObject.join)(candidate, "index.html"))) return candidate;
|
|
858
|
-
} catch {
|
|
859
|
-
continue;
|
|
860
|
-
}
|
|
1012
|
+
} catch {}
|
|
861
1013
|
return null;
|
|
862
1014
|
}
|
|
863
1015
|
async getSessionManager(agentId) {
|
|
@@ -1181,6 +1333,10 @@ class GatewayServer {
|
|
|
1181
1333
|
_define_property(this, "socketSubscriptions", new Map());
|
|
1182
1334
|
_define_property(this, "connectedClients", new Set());
|
|
1183
1335
|
_define_property(this, "activeAgentRequests", new Map());
|
|
1336
|
+
_define_property(this, "activeSessionRequests", new Map());
|
|
1337
|
+
_define_property(this, "queuedSessionRequests", new Map());
|
|
1338
|
+
_define_property(this, "requestSessionKeys", new Map());
|
|
1339
|
+
_define_property(this, "terminalSessionManager", void 0);
|
|
1184
1340
|
_define_property(this, "bridgeQueues", new Map());
|
|
1185
1341
|
_define_property(this, "bridgePollWaiters", new Map());
|
|
1186
1342
|
this.workspace = config.workspace || process.cwd();
|
|
@@ -1231,6 +1387,7 @@ class GatewayServer {
|
|
|
1231
1387
|
this.controlUiPort = controlUi?.port || 18790;
|
|
1232
1388
|
this.controlUiSamePort = this.controlUiEnabled && this.controlUiPort === this.config.port;
|
|
1233
1389
|
this.uiDistDir = this.controlUiEnabled ? this.resolveControlUiDir() : null;
|
|
1390
|
+
this.terminalSessionManager = new terminal_session_manager_cjs_namespaceObject.TerminalSessionManager();
|
|
1234
1391
|
}
|
|
1235
1392
|
}
|
|
1236
1393
|
function buildAttachmentPreview(attachments) {
|
package/dist/gateway/server.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { GatewayConfig } from "./types.js";
|
|
2
1
|
import { GatewayAuth } from "./auth.js";
|
|
2
|
+
import type { GatewayConfig } from "./types.js";
|
|
3
3
|
/**
|
|
4
4
|
* Wingman Gateway Server
|
|
5
5
|
* Manages WebSocket connections for AI agent swarming
|
|
@@ -34,6 +34,10 @@ export declare class GatewayServer {
|
|
|
34
34
|
private socketSubscriptions;
|
|
35
35
|
private connectedClients;
|
|
36
36
|
private activeAgentRequests;
|
|
37
|
+
private activeSessionRequests;
|
|
38
|
+
private queuedSessionRequests;
|
|
39
|
+
private requestSessionKeys;
|
|
40
|
+
private terminalSessionManager;
|
|
37
41
|
private bridgeQueues;
|
|
38
42
|
private bridgePollWaiters;
|
|
39
43
|
constructor(config?: Partial<GatewayConfig>);
|
|
@@ -76,7 +80,11 @@ export declare class GatewayServer {
|
|
|
76
80
|
* Handle agent execution request
|
|
77
81
|
*/
|
|
78
82
|
private handleAgentRequest;
|
|
83
|
+
private executeAgentRequest;
|
|
84
|
+
private processNextQueuedAgentRequest;
|
|
79
85
|
private handleAgentCancel;
|
|
86
|
+
private buildSessionQueueKey;
|
|
87
|
+
private removeQueuedRequestById;
|
|
80
88
|
/**
|
|
81
89
|
* Handle node registration
|
|
82
90
|
*/
|