@wingman-ai/gateway 0.2.4 → 0.3.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/.wingman/agents/coding/agent.md +5 -0
- package/.wingman/agents/coding-v2/agent.md +58 -0
- package/.wingman/agents/game-dev/agent.md +94 -0
- package/.wingman/agents/game-dev/art-generation.md +37 -0
- package/.wingman/agents/game-dev/asset-refinement.md +17 -0
- package/.wingman/agents/game-dev/planning-idea.md +17 -0
- package/.wingman/agents/game-dev/ui-specialist.md +17 -0
- package/.wingman/agents/main/agent.md +2 -0
- package/README.md +1 -0
- package/dist/agent/config/agentConfig.d.ts +4 -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 +3 -1
- package/dist/agent/config/toolRegistry.js +3 -1
- 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/tools/command_execute.cjs +1 -1
- package/dist/agent/tools/command_execute.js +1 -1
- package/dist/cli/config/schema.d.ts +2 -0
- 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/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/http/fs.cjs +19 -0
- package/dist/gateway/http/fs.js +19 -0
- package/dist/gateway/http/sessions.cjs +25 -5
- package/dist/gateway/http/sessions.js +25 -5
- package/dist/gateway/server.cjs +112 -11
- package/dist/gateway/server.d.ts +2 -0
- package/dist/gateway/server.js +112 -11
- package/dist/providers/codex.cjs +230 -37
- package/dist/providers/codex.d.ts +2 -0
- package/dist/providers/codex.js +231 -38
- 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/cli-init.test.cjs +36 -0
- package/dist/tests/cli-init.test.js +36 -0
- package/dist/tests/codex-provider.test.cjs +173 -0
- package/dist/tests/codex-provider.test.js +174 -1
- 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/gateway.test.cjs +109 -1
- package/dist/tests/gateway.test.js +109 -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/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-0nUBsUUq.js +278 -0
- package/dist/webui/assets/index-kk7OrD-G.css +11 -0
- package/dist/webui/index.html +2 -2
- package/package.json +16 -13
- package/dist/webui/assets/index-DVWQluit.css +0 -11
- package/dist/webui/assets/index-Dlyzwalc.js +0 -270
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
TERMINAL_PROBE_GATEWAY_TOKEN_ENV: ()=>TERMINAL_PROBE_GATEWAY_TOKEN_ENV,
|
|
28
|
+
resolveTerminalProbeAuth: ()=>resolveTerminalProbeAuth,
|
|
29
|
+
formatTerminalProbeHandshakeFailure: ()=>formatTerminalProbeHandshakeFailure,
|
|
30
|
+
TERMINAL_PROBE_GATEWAY_PASSWORD_ENV: ()=>TERMINAL_PROBE_GATEWAY_PASSWORD_ENV
|
|
31
|
+
});
|
|
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 TERMINAL_PROBE_GATEWAY_TOKEN_ENV = "WINGMAN_GATEWAY_TOKEN";
|
|
36
|
+
const TERMINAL_PROBE_GATEWAY_PASSWORD_ENV = "WINGMAN_GATEWAY_PASSWORD";
|
|
37
|
+
function normalizeSecret(raw) {
|
|
38
|
+
if ("string" != typeof raw) return;
|
|
39
|
+
const value = raw.trim();
|
|
40
|
+
return value.length > 0 ? value : void 0;
|
|
41
|
+
}
|
|
42
|
+
function parseGatewayAuthConfig(rawConfig) {
|
|
43
|
+
if (!rawConfig || "object" != typeof rawConfig || Array.isArray(rawConfig)) return null;
|
|
44
|
+
const config = rawConfig;
|
|
45
|
+
const gateway = config.gateway;
|
|
46
|
+
if (!gateway || "object" != typeof gateway || Array.isArray(gateway)) return null;
|
|
47
|
+
const auth = gateway.auth;
|
|
48
|
+
if (!auth || "object" != typeof auth || Array.isArray(auth)) return null;
|
|
49
|
+
const authConfig = auth;
|
|
50
|
+
const mode = "string" == typeof authConfig.mode ? authConfig.mode.toLowerCase() : "";
|
|
51
|
+
const token = normalizeSecret(authConfig.token);
|
|
52
|
+
const password = normalizeSecret(authConfig.password);
|
|
53
|
+
if ("token" === mode && token) return {
|
|
54
|
+
token
|
|
55
|
+
};
|
|
56
|
+
if ("password" === mode && password) return {
|
|
57
|
+
password
|
|
58
|
+
};
|
|
59
|
+
if (!mode && (token || password)) return {
|
|
60
|
+
token,
|
|
61
|
+
password
|
|
62
|
+
};
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
function unique(values) {
|
|
66
|
+
return Array.from(new Set(values));
|
|
67
|
+
}
|
|
68
|
+
function resolveConfigCandidates(options) {
|
|
69
|
+
if (options.configFileCandidates?.length) return unique(options.configFileCandidates);
|
|
70
|
+
const cwd = options.cwd ?? process.cwd();
|
|
71
|
+
const homeDir = options.homeDir ?? (0, external_node_os_namespaceObject.homedir)();
|
|
72
|
+
return unique([
|
|
73
|
+
(0, external_node_path_namespaceObject.join)(cwd, ".wingman", "wingman.config.json"),
|
|
74
|
+
(0, external_node_path_namespaceObject.join)(homeDir, ".wingman", "wingman.config.json")
|
|
75
|
+
]);
|
|
76
|
+
}
|
|
77
|
+
function resolveAuthFromConfig(options) {
|
|
78
|
+
for (const configPath of resolveConfigCandidates(options))if ((0, external_node_fs_namespaceObject.existsSync)(configPath)) try {
|
|
79
|
+
const raw = (0, external_node_fs_namespaceObject.readFileSync)(configPath, "utf-8");
|
|
80
|
+
const parsed = JSON.parse(raw);
|
|
81
|
+
const auth = parseGatewayAuthConfig(parsed);
|
|
82
|
+
if (auth) return {
|
|
83
|
+
...auth,
|
|
84
|
+
configPath
|
|
85
|
+
};
|
|
86
|
+
} catch {}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
function resolveTerminalProbeAuth(options = {}) {
|
|
90
|
+
const cliToken = normalizeSecret(options.cliToken);
|
|
91
|
+
const cliPassword = normalizeSecret(options.cliPassword);
|
|
92
|
+
if (cliToken || cliPassword) return {
|
|
93
|
+
token: cliToken,
|
|
94
|
+
password: cliPassword,
|
|
95
|
+
source: "cli"
|
|
96
|
+
};
|
|
97
|
+
const env = options.env ?? process.env;
|
|
98
|
+
const envToken = normalizeSecret(env[TERMINAL_PROBE_GATEWAY_TOKEN_ENV]);
|
|
99
|
+
const envPassword = normalizeSecret(env[TERMINAL_PROBE_GATEWAY_PASSWORD_ENV]);
|
|
100
|
+
if (envToken || envPassword) return {
|
|
101
|
+
token: envToken,
|
|
102
|
+
password: envPassword,
|
|
103
|
+
source: "env"
|
|
104
|
+
};
|
|
105
|
+
const fromConfig = resolveAuthFromConfig(options);
|
|
106
|
+
if (fromConfig?.token || fromConfig?.password) return {
|
|
107
|
+
token: fromConfig.token,
|
|
108
|
+
password: fromConfig.password,
|
|
109
|
+
source: "config",
|
|
110
|
+
configPath: fromConfig.configPath
|
|
111
|
+
};
|
|
112
|
+
return {
|
|
113
|
+
source: "none"
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function formatTerminalProbeHandshakeFailure(payload) {
|
|
117
|
+
if ("string" == typeof payload) {
|
|
118
|
+
const value = payload.trim();
|
|
119
|
+
return value.length > 0 ? value : "unknown";
|
|
120
|
+
}
|
|
121
|
+
if (null == payload) return "unknown";
|
|
122
|
+
try {
|
|
123
|
+
return JSON.stringify(payload);
|
|
124
|
+
} catch {
|
|
125
|
+
return "unknown";
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
exports.TERMINAL_PROBE_GATEWAY_PASSWORD_ENV = __webpack_exports__.TERMINAL_PROBE_GATEWAY_PASSWORD_ENV;
|
|
129
|
+
exports.TERMINAL_PROBE_GATEWAY_TOKEN_ENV = __webpack_exports__.TERMINAL_PROBE_GATEWAY_TOKEN_ENV;
|
|
130
|
+
exports.formatTerminalProbeHandshakeFailure = __webpack_exports__.formatTerminalProbeHandshakeFailure;
|
|
131
|
+
exports.resolveTerminalProbeAuth = __webpack_exports__.resolveTerminalProbeAuth;
|
|
132
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
133
|
+
"TERMINAL_PROBE_GATEWAY_PASSWORD_ENV",
|
|
134
|
+
"TERMINAL_PROBE_GATEWAY_TOKEN_ENV",
|
|
135
|
+
"formatTerminalProbeHandshakeFailure",
|
|
136
|
+
"resolveTerminalProbeAuth"
|
|
137
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
138
|
+
Object.defineProperty(exports, '__esModule', {
|
|
139
|
+
value: true
|
|
140
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const TERMINAL_PROBE_GATEWAY_TOKEN_ENV = "WINGMAN_GATEWAY_TOKEN";
|
|
2
|
+
export declare const TERMINAL_PROBE_GATEWAY_PASSWORD_ENV = "WINGMAN_GATEWAY_PASSWORD";
|
|
3
|
+
type TerminalProbeAuthSource = "cli" | "env" | "config" | "none";
|
|
4
|
+
export type TerminalProbeAuth = {
|
|
5
|
+
token?: string;
|
|
6
|
+
password?: string;
|
|
7
|
+
source: TerminalProbeAuthSource;
|
|
8
|
+
configPath?: string;
|
|
9
|
+
};
|
|
10
|
+
type ResolveTerminalProbeAuthOptions = {
|
|
11
|
+
cliToken?: string;
|
|
12
|
+
cliPassword?: string;
|
|
13
|
+
env?: Record<string, string | undefined>;
|
|
14
|
+
cwd?: string;
|
|
15
|
+
homeDir?: string;
|
|
16
|
+
configFileCandidates?: string[];
|
|
17
|
+
};
|
|
18
|
+
export declare function resolveTerminalProbeAuth(options?: ResolveTerminalProbeAuthOptions): TerminalProbeAuth;
|
|
19
|
+
export declare function formatTerminalProbeHandshakeFailure(payload: unknown): string;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
const TERMINAL_PROBE_GATEWAY_TOKEN_ENV = "WINGMAN_GATEWAY_TOKEN";
|
|
5
|
+
const TERMINAL_PROBE_GATEWAY_PASSWORD_ENV = "WINGMAN_GATEWAY_PASSWORD";
|
|
6
|
+
function normalizeSecret(raw) {
|
|
7
|
+
if ("string" != typeof raw) return;
|
|
8
|
+
const value = raw.trim();
|
|
9
|
+
return value.length > 0 ? value : void 0;
|
|
10
|
+
}
|
|
11
|
+
function parseGatewayAuthConfig(rawConfig) {
|
|
12
|
+
if (!rawConfig || "object" != typeof rawConfig || Array.isArray(rawConfig)) return null;
|
|
13
|
+
const config = rawConfig;
|
|
14
|
+
const gateway = config.gateway;
|
|
15
|
+
if (!gateway || "object" != typeof gateway || Array.isArray(gateway)) return null;
|
|
16
|
+
const auth = gateway.auth;
|
|
17
|
+
if (!auth || "object" != typeof auth || Array.isArray(auth)) return null;
|
|
18
|
+
const authConfig = auth;
|
|
19
|
+
const mode = "string" == typeof authConfig.mode ? authConfig.mode.toLowerCase() : "";
|
|
20
|
+
const token = normalizeSecret(authConfig.token);
|
|
21
|
+
const password = normalizeSecret(authConfig.password);
|
|
22
|
+
if ("token" === mode && token) return {
|
|
23
|
+
token
|
|
24
|
+
};
|
|
25
|
+
if ("password" === mode && password) return {
|
|
26
|
+
password
|
|
27
|
+
};
|
|
28
|
+
if (!mode && (token || password)) return {
|
|
29
|
+
token,
|
|
30
|
+
password
|
|
31
|
+
};
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
function unique(values) {
|
|
35
|
+
return Array.from(new Set(values));
|
|
36
|
+
}
|
|
37
|
+
function resolveConfigCandidates(options) {
|
|
38
|
+
if (options.configFileCandidates?.length) return unique(options.configFileCandidates);
|
|
39
|
+
const cwd = options.cwd ?? process.cwd();
|
|
40
|
+
const homeDir = options.homeDir ?? homedir();
|
|
41
|
+
return unique([
|
|
42
|
+
join(cwd, ".wingman", "wingman.config.json"),
|
|
43
|
+
join(homeDir, ".wingman", "wingman.config.json")
|
|
44
|
+
]);
|
|
45
|
+
}
|
|
46
|
+
function resolveAuthFromConfig(options) {
|
|
47
|
+
for (const configPath of resolveConfigCandidates(options))if (existsSync(configPath)) try {
|
|
48
|
+
const raw = readFileSync(configPath, "utf-8");
|
|
49
|
+
const parsed = JSON.parse(raw);
|
|
50
|
+
const auth = parseGatewayAuthConfig(parsed);
|
|
51
|
+
if (auth) return {
|
|
52
|
+
...auth,
|
|
53
|
+
configPath
|
|
54
|
+
};
|
|
55
|
+
} catch {}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
function resolveTerminalProbeAuth(options = {}) {
|
|
59
|
+
const cliToken = normalizeSecret(options.cliToken);
|
|
60
|
+
const cliPassword = normalizeSecret(options.cliPassword);
|
|
61
|
+
if (cliToken || cliPassword) return {
|
|
62
|
+
token: cliToken,
|
|
63
|
+
password: cliPassword,
|
|
64
|
+
source: "cli"
|
|
65
|
+
};
|
|
66
|
+
const env = options.env ?? process.env;
|
|
67
|
+
const envToken = normalizeSecret(env[TERMINAL_PROBE_GATEWAY_TOKEN_ENV]);
|
|
68
|
+
const envPassword = normalizeSecret(env[TERMINAL_PROBE_GATEWAY_PASSWORD_ENV]);
|
|
69
|
+
if (envToken || envPassword) return {
|
|
70
|
+
token: envToken,
|
|
71
|
+
password: envPassword,
|
|
72
|
+
source: "env"
|
|
73
|
+
};
|
|
74
|
+
const fromConfig = resolveAuthFromConfig(options);
|
|
75
|
+
if (fromConfig?.token || fromConfig?.password) return {
|
|
76
|
+
token: fromConfig.token,
|
|
77
|
+
password: fromConfig.password,
|
|
78
|
+
source: "config",
|
|
79
|
+
configPath: fromConfig.configPath
|
|
80
|
+
};
|
|
81
|
+
return {
|
|
82
|
+
source: "none"
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function formatTerminalProbeHandshakeFailure(payload) {
|
|
86
|
+
if ("string" == typeof payload) {
|
|
87
|
+
const value = payload.trim();
|
|
88
|
+
return value.length > 0 ? value : "unknown";
|
|
89
|
+
}
|
|
90
|
+
if (null == payload) return "unknown";
|
|
91
|
+
try {
|
|
92
|
+
return JSON.stringify(payload);
|
|
93
|
+
} catch {
|
|
94
|
+
return "unknown";
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
export { TERMINAL_PROBE_GATEWAY_PASSWORD_ENV, TERMINAL_PROBE_GATEWAY_TOKEN_ENV, formatTerminalProbeHandshakeFailure, resolveTerminalProbeAuth };
|
package/dist/gateway/http/fs.cjs
CHANGED
|
@@ -70,6 +70,25 @@ const handleFsApi = async (ctx, req, url)=>{
|
|
|
70
70
|
}
|
|
71
71
|
});
|
|
72
72
|
}
|
|
73
|
+
if ("/api/fs/file" === url.pathname && "GET" === req.method) {
|
|
74
|
+
const rawPath = url.searchParams.get("path");
|
|
75
|
+
if (!rawPath) return new Response("path required", {
|
|
76
|
+
status: 400
|
|
77
|
+
});
|
|
78
|
+
const resolved = ctx.resolveFsPath(rawPath);
|
|
79
|
+
const roots = ctx.resolveFsRoots();
|
|
80
|
+
if (!ctx.isPathWithinRoots(resolved, roots)) return new Response("path not allowed", {
|
|
81
|
+
status: 403
|
|
82
|
+
});
|
|
83
|
+
if (!(0, external_node_fs_namespaceObject.existsSync)(resolved) || !(0, external_node_fs_namespaceObject.statSync)(resolved).isFile()) return new Response("path not found", {
|
|
84
|
+
status: 404
|
|
85
|
+
});
|
|
86
|
+
return new Response(Bun.file(resolved), {
|
|
87
|
+
headers: {
|
|
88
|
+
"Cache-Control": "no-store"
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
73
92
|
return null;
|
|
74
93
|
};
|
|
75
94
|
exports.handleFsApi = __webpack_exports__.handleFsApi;
|
package/dist/gateway/http/fs.js
CHANGED
|
@@ -42,6 +42,25 @@ const handleFsApi = async (ctx, req, url)=>{
|
|
|
42
42
|
}
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
|
+
if ("/api/fs/file" === url.pathname && "GET" === req.method) {
|
|
46
|
+
const rawPath = url.searchParams.get("path");
|
|
47
|
+
if (!rawPath) return new Response("path required", {
|
|
48
|
+
status: 400
|
|
49
|
+
});
|
|
50
|
+
const resolved = ctx.resolveFsPath(rawPath);
|
|
51
|
+
const roots = ctx.resolveFsRoots();
|
|
52
|
+
if (!ctx.isPathWithinRoots(resolved, roots)) return new Response("path not allowed", {
|
|
53
|
+
status: 403
|
|
54
|
+
});
|
|
55
|
+
if (!existsSync(resolved) || !statSync(resolved).isFile()) return new Response("path not found", {
|
|
56
|
+
status: 404
|
|
57
|
+
});
|
|
58
|
+
return new Response(Bun.file(resolved), {
|
|
59
|
+
headers: {
|
|
60
|
+
"Cache-Control": "no-store"
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
45
64
|
return null;
|
|
46
65
|
};
|
|
47
66
|
export { handleFsApi };
|
|
@@ -28,17 +28,37 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
28
28
|
});
|
|
29
29
|
const external_node_crypto_namespaceObject = require("node:crypto");
|
|
30
30
|
const external_node_fs_namespaceObject = require("node:fs");
|
|
31
|
+
const agentLoader_cjs_namespaceObject = require("../../agent/config/agentLoader.cjs");
|
|
32
|
+
const getSessionAgents = (ctx, explicitAgentId)=>{
|
|
33
|
+
if (explicitAgentId) return [
|
|
34
|
+
explicitAgentId
|
|
35
|
+
];
|
|
36
|
+
const config = ctx.getWingmanConfig();
|
|
37
|
+
const configuredAgents = config.agents?.list?.map((agent)=>agent.id?.trim()).filter((id)=>Boolean(id)) ?? [];
|
|
38
|
+
let discoveredAgents = [];
|
|
39
|
+
try {
|
|
40
|
+
const loader = new agentLoader_cjs_namespaceObject.AgentLoader(ctx.configDir, ctx.workspace, config);
|
|
41
|
+
discoveredAgents = loader.loadAllAgentConfigs().map((agent)=>agent.name?.trim()).filter((id)=>Boolean(id));
|
|
42
|
+
} catch (error) {
|
|
43
|
+
if ("function" == typeof ctx.logger?.warn) ctx.logger.warn("Failed to load discovered agents while listing sessions", error);
|
|
44
|
+
}
|
|
45
|
+
const agents = [
|
|
46
|
+
...new Set([
|
|
47
|
+
...configuredAgents,
|
|
48
|
+
...discoveredAgents
|
|
49
|
+
])
|
|
50
|
+
];
|
|
51
|
+
return agents.length > 0 ? agents : [
|
|
52
|
+
"main"
|
|
53
|
+
];
|
|
54
|
+
};
|
|
31
55
|
const handleSessionsApi = async (ctx, req, url)=>{
|
|
32
56
|
if ("/api/sessions" === url.pathname) {
|
|
33
57
|
if ("GET" === req.method) {
|
|
34
58
|
const limit = Number(url.searchParams.get("limit") || "100");
|
|
35
59
|
const status = url.searchParams.get("status") || "active";
|
|
36
60
|
const agentId = url.searchParams.get("agentId") || void 0;
|
|
37
|
-
const agents = agentId
|
|
38
|
-
agentId
|
|
39
|
-
] : ctx.getWingmanConfig().agents?.list?.map((agent)=>agent.id) || [
|
|
40
|
-
"main"
|
|
41
|
-
];
|
|
61
|
+
const agents = getSessionAgents(ctx, agentId);
|
|
42
62
|
const sessions = [];
|
|
43
63
|
for (const agent of agents){
|
|
44
64
|
const manager = await ctx.getSessionManager(agent);
|
|
@@ -1,16 +1,36 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { existsSync, statSync } from "node:fs";
|
|
3
|
+
import { AgentLoader } from "../../agent/config/agentLoader.js";
|
|
4
|
+
const getSessionAgents = (ctx, explicitAgentId)=>{
|
|
5
|
+
if (explicitAgentId) return [
|
|
6
|
+
explicitAgentId
|
|
7
|
+
];
|
|
8
|
+
const config = ctx.getWingmanConfig();
|
|
9
|
+
const configuredAgents = config.agents?.list?.map((agent)=>agent.id?.trim()).filter((id)=>Boolean(id)) ?? [];
|
|
10
|
+
let discoveredAgents = [];
|
|
11
|
+
try {
|
|
12
|
+
const loader = new AgentLoader(ctx.configDir, ctx.workspace, config);
|
|
13
|
+
discoveredAgents = loader.loadAllAgentConfigs().map((agent)=>agent.name?.trim()).filter((id)=>Boolean(id));
|
|
14
|
+
} catch (error) {
|
|
15
|
+
if ("function" == typeof ctx.logger?.warn) ctx.logger.warn("Failed to load discovered agents while listing sessions", error);
|
|
16
|
+
}
|
|
17
|
+
const agents = [
|
|
18
|
+
...new Set([
|
|
19
|
+
...configuredAgents,
|
|
20
|
+
...discoveredAgents
|
|
21
|
+
])
|
|
22
|
+
];
|
|
23
|
+
return agents.length > 0 ? agents : [
|
|
24
|
+
"main"
|
|
25
|
+
];
|
|
26
|
+
};
|
|
3
27
|
const handleSessionsApi = async (ctx, req, url)=>{
|
|
4
28
|
if ("/api/sessions" === url.pathname) {
|
|
5
29
|
if ("GET" === req.method) {
|
|
6
30
|
const limit = Number(url.searchParams.get("limit") || "100");
|
|
7
31
|
const status = url.searchParams.get("status") || "active";
|
|
8
32
|
const agentId = url.searchParams.get("agentId") || void 0;
|
|
9
|
-
const agents = agentId
|
|
10
|
-
agentId
|
|
11
|
-
] : ctx.getWingmanConfig().agents?.list?.map((agent)=>agent.id) || [
|
|
12
|
-
"main"
|
|
13
|
-
];
|
|
33
|
+
const agents = getSessionAgents(ctx, agentId);
|
|
14
34
|
const sessions = [];
|
|
15
35
|
for (const agent of agents){
|
|
16
36
|
const manager = await ctx.getSessionManager(agent);
|
package/dist/gateway/server.cjs
CHANGED
|
@@ -367,12 +367,29 @@ class GatewayServer {
|
|
|
367
367
|
const sessionManager = await this.getSessionManager(agentId);
|
|
368
368
|
const existingSession = sessionManager.getSession(sessionKey);
|
|
369
369
|
const session = existingSession || sessionManager.getOrCreateSession(sessionKey, agentId);
|
|
370
|
+
const requestId = msg.id || `req-${Date.now()}`;
|
|
370
371
|
const workdir = session.metadata?.workdir ?? null;
|
|
371
372
|
const defaultOutputDir = this.resolveDefaultOutputDir(agentId);
|
|
372
373
|
const preview = hasContent ? content.trim() : buildAttachmentPreview(attachments);
|
|
373
374
|
sessionManager.updateSession(session.id, {
|
|
375
|
+
messageCount: (session.messageCount ?? 0) + 1,
|
|
374
376
|
lastMessagePreview: preview.substring(0, 200)
|
|
375
377
|
});
|
|
378
|
+
try {
|
|
379
|
+
sessionManager.persistPendingMessage({
|
|
380
|
+
sessionId: sessionKey,
|
|
381
|
+
requestId,
|
|
382
|
+
message: {
|
|
383
|
+
id: `user-${requestId}`,
|
|
384
|
+
role: "user",
|
|
385
|
+
content,
|
|
386
|
+
attachments: attachments.length > 0 ? mapAttachmentsForPendingMessage(attachments) : void 0,
|
|
387
|
+
createdAt: Date.now()
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
} catch (error) {
|
|
391
|
+
this.logger.warn("Failed to persist pending user message", error);
|
|
392
|
+
}
|
|
376
393
|
if (!existingSession) this.internalHooks?.emit({
|
|
377
394
|
type: "session",
|
|
378
395
|
action: "start",
|
|
@@ -475,9 +492,15 @@ class GatewayServer {
|
|
|
475
492
|
this.activeSessionRequests.set(sessionQueueKey, msg.id);
|
|
476
493
|
const outputManager = new outputManager_cjs_namespaceObject.OutputManager("interactive");
|
|
477
494
|
let emittedAgentError = false;
|
|
495
|
+
let streamedCompletionResult;
|
|
478
496
|
const outputHandler = (event)=>{
|
|
479
497
|
const payloadWithSession = this.attachSessionContext(event, sessionKey, agentId);
|
|
480
|
-
|
|
498
|
+
const payloadType = payloadWithSession && "object" == typeof payloadWithSession && !Array.isArray(payloadWithSession) && "string" == typeof payloadWithSession.type ? payloadWithSession.type : "";
|
|
499
|
+
if ("agent-complete" === payloadType) {
|
|
500
|
+
if (payloadWithSession && "object" == typeof payloadWithSession && !Array.isArray(payloadWithSession)) streamedCompletionResult = payloadWithSession.result;
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
if ("agent-error" === payloadType) emittedAgentError = true;
|
|
481
504
|
const baseMessage = {
|
|
482
505
|
type: "event:agent",
|
|
483
506
|
id: msg.id,
|
|
@@ -508,17 +531,43 @@ class GatewayServer {
|
|
|
508
531
|
abortController
|
|
509
532
|
});
|
|
510
533
|
try {
|
|
511
|
-
await invoker.invokeAgent(agentId, content, sessionKey, attachments, {
|
|
534
|
+
const invocationResult = await invoker.invokeAgent(agentId, content, sessionKey, attachments, {
|
|
512
535
|
signal: abortController.signal
|
|
513
536
|
});
|
|
514
|
-
|
|
515
|
-
if (
|
|
516
|
-
|
|
537
|
+
if (msg.id) sessionManager.clearPendingMessagesForRequest(sessionKey, msg.id);
|
|
538
|
+
if (emittedAgentError) return;
|
|
539
|
+
const invocationCancelled = abortController.signal.aborted || "object" == typeof invocationResult && null !== invocationResult && !Array.isArray(invocationResult) && true === invocationResult.cancelled;
|
|
540
|
+
if (invocationCancelled) return void this.sendAgentError(ws, msg.id, "Request cancelled", {
|
|
541
|
+
sessionId: sessionKey,
|
|
542
|
+
agentId,
|
|
543
|
+
broadcastToSession: true,
|
|
544
|
+
exclude: ws
|
|
545
|
+
});
|
|
546
|
+
const completionResult = void 0 === streamedCompletionResult ? invocationResult : streamedCompletionResult;
|
|
547
|
+
this.sendAgentComplete(ws, msg.id, completionResult, {
|
|
548
|
+
sessionId: sessionKey,
|
|
549
|
+
agentId,
|
|
550
|
+
broadcastToSession: true,
|
|
551
|
+
exclude: ws
|
|
517
552
|
});
|
|
518
553
|
} catch (error) {
|
|
519
554
|
this.logger.error("Agent invocation failed", error);
|
|
555
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
556
|
+
if (msg.id) try {
|
|
557
|
+
sessionManager.persistPendingMessage({
|
|
558
|
+
sessionId: sessionKey,
|
|
559
|
+
requestId: msg.id,
|
|
560
|
+
message: {
|
|
561
|
+
id: msg.id,
|
|
562
|
+
role: "assistant",
|
|
563
|
+
content: message,
|
|
564
|
+
createdAt: Date.now()
|
|
565
|
+
}
|
|
566
|
+
});
|
|
567
|
+
} catch (persistError) {
|
|
568
|
+
this.logger.warn("Failed to persist pending assistant error message", persistError);
|
|
569
|
+
}
|
|
520
570
|
if (!emittedAgentError) {
|
|
521
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
522
571
|
const stack = error instanceof Error ? error.stack : void 0;
|
|
523
572
|
this.sendAgentError(ws, msg.id, message, {
|
|
524
573
|
sessionId: sessionKey,
|
|
@@ -594,6 +643,12 @@ class GatewayServer {
|
|
|
594
643
|
},
|
|
595
644
|
timestamp: Date.now()
|
|
596
645
|
});
|
|
646
|
+
this.sendAgentError(ws, requestId, "Request cancelled", {
|
|
647
|
+
sessionId: queued.sessionKey,
|
|
648
|
+
agentId: queued.agentId,
|
|
649
|
+
broadcastToSession: true,
|
|
650
|
+
exclude: ws
|
|
651
|
+
});
|
|
597
652
|
return;
|
|
598
653
|
}
|
|
599
654
|
this.sendMessage(ws, {
|
|
@@ -768,11 +823,25 @@ class GatewayServer {
|
|
|
768
823
|
}
|
|
769
824
|
sendMessage(ws, message) {
|
|
770
825
|
try {
|
|
771
|
-
ws.send(JSON.stringify(message));
|
|
826
|
+
const result = ws.send(JSON.stringify(message));
|
|
827
|
+
if ("number" == typeof result && result <= 0) return false;
|
|
828
|
+
return true;
|
|
772
829
|
} catch (error) {
|
|
773
830
|
this.log("error", "Failed to send message", error);
|
|
831
|
+
return false;
|
|
774
832
|
}
|
|
775
833
|
}
|
|
834
|
+
sendMessageWithRetry(ws, message, attempt = 0) {
|
|
835
|
+
if (this.sendMessage(ws, message)) return;
|
|
836
|
+
if (attempt >= 2) return void this.log("warn", "Dropping websocket message after retry attempts", {
|
|
837
|
+
type: message.type,
|
|
838
|
+
id: message.id
|
|
839
|
+
});
|
|
840
|
+
const delayMs = 25 * (attempt + 1);
|
|
841
|
+
setTimeout(()=>{
|
|
842
|
+
this.sendMessageWithRetry(ws, message, attempt + 1);
|
|
843
|
+
}, delayMs);
|
|
844
|
+
}
|
|
776
845
|
sendError(ws, code, message) {
|
|
777
846
|
const errorPayload = {
|
|
778
847
|
code,
|
|
@@ -784,6 +853,25 @@ class GatewayServer {
|
|
|
784
853
|
timestamp: Date.now()
|
|
785
854
|
});
|
|
786
855
|
}
|
|
856
|
+
sendAgentComplete(ws, requestId, result, options) {
|
|
857
|
+
let payload = {
|
|
858
|
+
type: "agent-complete",
|
|
859
|
+
result: result ?? null,
|
|
860
|
+
timestamp: new Date().toISOString()
|
|
861
|
+
};
|
|
862
|
+
if (options?.sessionId && options?.agentId) payload = this.attachSessionContext(payload, options.sessionId, options.agentId);
|
|
863
|
+
const baseMessage = {
|
|
864
|
+
type: "event:agent",
|
|
865
|
+
id: requestId,
|
|
866
|
+
payload,
|
|
867
|
+
timestamp: Date.now()
|
|
868
|
+
};
|
|
869
|
+
this.sendMessageWithRetry(ws, {
|
|
870
|
+
...baseMessage,
|
|
871
|
+
clientId: ws.data.clientId
|
|
872
|
+
});
|
|
873
|
+
if (options?.broadcastToSession && options.sessionId) this.broadcastSessionEvent(options.sessionId, baseMessage, options.exclude, true);
|
|
874
|
+
}
|
|
787
875
|
sendAgentError(ws, requestId, message, options) {
|
|
788
876
|
let payload = {
|
|
789
877
|
type: "agent-error",
|
|
@@ -798,11 +886,11 @@ class GatewayServer {
|
|
|
798
886
|
payload,
|
|
799
887
|
timestamp: Date.now()
|
|
800
888
|
};
|
|
801
|
-
this.
|
|
889
|
+
this.sendMessageWithRetry(ws, {
|
|
802
890
|
...baseMessage,
|
|
803
891
|
clientId: ws.data.clientId
|
|
804
892
|
});
|
|
805
|
-
if (options?.broadcastToSession && options.sessionId) this.broadcastSessionEvent(options.sessionId, baseMessage, options.exclude);
|
|
893
|
+
if (options?.broadcastToSession && options.sessionId) this.broadcastSessionEvent(options.sessionId, baseMessage, options.exclude, true);
|
|
806
894
|
}
|
|
807
895
|
cancelSocketAgentRequests(ws) {
|
|
808
896
|
for (const [requestId, active] of this.activeAgentRequests)if (active.socket === ws) {
|
|
@@ -831,12 +919,13 @@ class GatewayServer {
|
|
|
831
919
|
agentId
|
|
832
920
|
};
|
|
833
921
|
}
|
|
834
|
-
broadcastSessionEvent(sessionId, message, exclude) {
|
|
922
|
+
broadcastSessionEvent(sessionId, message, exclude, reliable = false) {
|
|
835
923
|
const subscribers = this.sessionSubscriptions.get(sessionId);
|
|
836
924
|
if (!subscribers || 0 === subscribers.size) return 0;
|
|
837
925
|
let sent = 0;
|
|
838
926
|
for (const ws of subscribers)if (!exclude || ws !== exclude) {
|
|
839
|
-
this.
|
|
927
|
+
if (reliable) this.sendMessageWithRetry(ws, message);
|
|
928
|
+
else this.sendMessage(ws, message);
|
|
840
929
|
sent++;
|
|
841
930
|
}
|
|
842
931
|
return sent;
|
|
@@ -1410,6 +1499,18 @@ function buildAttachmentPreview(attachments) {
|
|
|
1410
1499
|
if (hasAudio) return count > 1 ? "Audio attachments" : "Audio attachment";
|
|
1411
1500
|
return count > 1 ? "Image attachments" : "Image attachment";
|
|
1412
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
|
+
}
|
|
1413
1514
|
function isAudioAttachment(attachment) {
|
|
1414
1515
|
if ("audio" === attachment.kind) return true;
|
|
1415
1516
|
if (attachment.mimeType?.startsWith("audio/")) return true;
|
package/dist/gateway/server.d.ts
CHANGED
|
@@ -129,10 +129,12 @@ export declare class GatewayServer {
|
|
|
129
129
|
* Send a message to a WebSocket
|
|
130
130
|
*/
|
|
131
131
|
private sendMessage;
|
|
132
|
+
private sendMessageWithRetry;
|
|
132
133
|
/**
|
|
133
134
|
* Send an error message
|
|
134
135
|
*/
|
|
135
136
|
private sendError;
|
|
137
|
+
private sendAgentComplete;
|
|
136
138
|
private sendAgentError;
|
|
137
139
|
private cancelSocketAgentRequests;
|
|
138
140
|
private attachSessionContext;
|