@wingman-ai/gateway 0.3.2 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -111
- package/dist/agent/config/agentConfig.cjs +2 -0
- package/dist/agent/config/agentConfig.d.ts +6 -0
- package/dist/agent/config/agentConfig.js +2 -0
- package/dist/agent/config/agentLoader.cjs +21 -18
- package/dist/agent/config/agentLoader.js +22 -19
- package/dist/agent/config/mcpClientManager.cjs +48 -9
- package/dist/agent/config/mcpClientManager.d.ts +12 -0
- package/dist/agent/config/mcpClientManager.js +48 -9
- package/dist/agent/config/toolRegistry.cjs +19 -0
- package/dist/agent/config/toolRegistry.d.ts +4 -0
- package/dist/agent/config/toolRegistry.js +17 -1
- package/dist/agent/middleware/additional-messages.cjs +115 -11
- package/dist/agent/middleware/additional-messages.d.ts +9 -0
- package/dist/agent/middleware/additional-messages.js +115 -11
- package/dist/agent/tests/agentLoader.test.cjs +45 -0
- package/dist/agent/tests/agentLoader.test.js +45 -0
- package/dist/agent/tests/mcpClientManager.test.cjs +50 -0
- package/dist/agent/tests/mcpClientManager.test.js +50 -0
- package/dist/agent/tests/toolRegistry.test.cjs +2 -0
- package/dist/agent/tests/toolRegistry.test.js +2 -0
- package/dist/agent/tools/node_invoke.cjs +146 -0
- package/dist/agent/tools/node_invoke.d.ts +86 -0
- package/dist/agent/tools/node_invoke.js +109 -0
- package/dist/cli/commands/gateway.cjs +1 -1
- package/dist/cli/commands/gateway.js +1 -1
- package/dist/cli/commands/skill.cjs +12 -4
- package/dist/cli/commands/skill.js +12 -4
- package/dist/cli/config/jsonSchema.cjs +55 -0
- package/dist/cli/config/jsonSchema.d.ts +2 -0
- package/dist/cli/config/jsonSchema.js +18 -0
- package/dist/cli/config/loader.cjs +33 -1
- package/dist/cli/config/loader.js +33 -1
- package/dist/cli/config/schema.cjs +119 -2
- package/dist/cli/config/schema.d.ts +40 -0
- package/dist/cli/config/schema.js +119 -2
- package/dist/cli/core/agentInvoker.cjs +25 -4
- package/dist/cli/core/agentInvoker.d.ts +13 -0
- package/dist/cli/core/agentInvoker.js +25 -4
- package/dist/cli/services/skillRepository.cjs +138 -20
- package/dist/cli/services/skillRepository.d.ts +10 -2
- package/dist/cli/services/skillRepository.js +138 -20
- package/dist/cli/services/skillSecurityScanner.cjs +158 -0
- package/dist/cli/services/skillSecurityScanner.d.ts +28 -0
- package/dist/cli/services/skillSecurityScanner.js +121 -0
- package/dist/cli/services/skillService.cjs +44 -12
- package/dist/cli/services/skillService.d.ts +2 -0
- package/dist/cli/services/skillService.js +46 -14
- package/dist/cli/types/skill.d.ts +9 -0
- package/dist/gateway/http/nodes.cjs +247 -0
- package/dist/gateway/http/nodes.d.ts +20 -0
- package/dist/gateway/http/nodes.js +210 -0
- package/dist/gateway/node.cjs +10 -1
- package/dist/gateway/node.d.ts +10 -1
- package/dist/gateway/node.js +10 -1
- package/dist/gateway/server.cjs +418 -27
- package/dist/gateway/server.d.ts +34 -0
- package/dist/gateway/server.js +412 -27
- package/dist/gateway/types.d.ts +15 -1
- package/dist/gateway/validation.cjs +2 -0
- package/dist/gateway/validation.d.ts +4 -0
- package/dist/gateway/validation.js +2 -0
- package/dist/tests/additionalMessageMiddleware.test.cjs +92 -0
- package/dist/tests/additionalMessageMiddleware.test.js +92 -0
- package/dist/tests/cli-config-loader.test.cjs +33 -1
- package/dist/tests/cli-config-loader.test.js +33 -1
- package/dist/tests/config-json-schema.test.cjs +25 -0
- package/dist/tests/config-json-schema.test.d.ts +1 -0
- package/dist/tests/config-json-schema.test.js +19 -0
- package/dist/tests/gateway-http-security.test.cjs +277 -0
- package/dist/tests/gateway-http-security.test.d.ts +1 -0
- package/dist/tests/gateway-http-security.test.js +271 -0
- package/dist/tests/gateway-node-mode.test.cjs +174 -0
- package/dist/tests/gateway-node-mode.test.d.ts +1 -0
- package/dist/tests/gateway-node-mode.test.js +168 -0
- package/dist/tests/gateway-origin-policy.test.cjs +60 -0
- package/dist/tests/gateway-origin-policy.test.d.ts +1 -0
- package/dist/tests/gateway-origin-policy.test.js +54 -0
- package/dist/tests/gateway.test.cjs +1 -0
- package/dist/tests/gateway.test.js +1 -0
- package/dist/tests/node-tools.test.cjs +77 -0
- package/dist/tests/node-tools.test.d.ts +1 -0
- package/dist/tests/node-tools.test.js +71 -0
- package/dist/tests/nodes-api.test.cjs +86 -0
- package/dist/tests/nodes-api.test.d.ts +1 -0
- package/dist/tests/nodes-api.test.js +80 -0
- package/dist/tests/skill-repository.test.cjs +106 -0
- package/dist/tests/skill-repository.test.d.ts +1 -0
- package/dist/tests/skill-repository.test.js +100 -0
- package/dist/tests/skill-security-scanner.test.cjs +126 -0
- package/dist/tests/skill-security-scanner.test.d.ts +1 -0
- package/dist/tests/skill-security-scanner.test.js +120 -0
- package/dist/tests/uv.test.cjs +47 -0
- package/dist/tests/uv.test.d.ts +1 -0
- package/dist/tests/uv.test.js +41 -0
- package/dist/utils/uv.cjs +64 -0
- package/dist/utils/uv.d.ts +3 -0
- package/dist/utils/uv.js +24 -0
- package/dist/webui/assets/{index-DHbfLOUR.js → index-BMekSELC.js} +106 -106
- package/dist/webui/index.html +1 -1
- package/package.json +2 -1
- package/skills/gog/SKILL.md +36 -0
- package/skills/weather/SKILL.md +49 -0
package/README.md
CHANGED
|
@@ -123,128 +123,46 @@ wingman provider login ollama # Optional
|
|
|
123
123
|
wingman agent --local --agent <id> "prompt"
|
|
124
124
|
```
|
|
125
125
|
|
|
126
|
-
##
|
|
126
|
+
## Secure Skills + MCP Proxy (TL;DR)
|
|
127
127
|
|
|
128
|
-
|
|
128
|
+
Main point: skill scanning and MCP proxy are separate toggles, both explicit, and `uv` checks only happen when the feature is enabled.
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
Key CLI commands:
|
|
131
131
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
- `gateway.auth.allowTailscale` - trust Tailscale identity headers so Tailnet users can access without tokens.
|
|
137
|
-
- `gateway.controlUi.enabled` / `gateway.controlUi.port` - enable/disable Control UI and choose its port.
|
|
138
|
-
- `gateway.controlUi.pairingRequired` - require pairing for Control UI clients (recommended).
|
|
139
|
-
- `gateway.controlUi.allowInsecureAuth` - only for local dev when testing auth flows.
|
|
140
|
-
- `gateway.adapters.discord.*` - Discord output adapter:
|
|
141
|
-
- `enabled`, `token`, `mentionOnly`, `allowBots`, `allowedGuilds`, `allowedChannels`
|
|
142
|
-
- `channelSessions` to pin channels to a session (or `agent:<id>:` to force routing)
|
|
143
|
-
- `sessionCommand` for ad-hoc session overrides
|
|
144
|
-
- `responseChunkSize` to fit Discord message limits
|
|
145
|
-
- Optional `gatewayUrl`, `gatewayToken`, `gatewayPassword` to point the adapter at a remote gateway
|
|
146
|
-
|
|
147
|
-
### 2) Runtime flags (`wingman gateway start` / `run`)
|
|
148
|
-
|
|
149
|
-
- `--host`, `--port` - override bind address + port for this run.
|
|
150
|
-
- `--auth`, `--auth-mode`, `--token`, `--password` - enable auth without editing config.
|
|
151
|
-
- `--discovery mdns|tailscale`, `--name` - advertise your gateway for LAN or Tailnet discovery.
|
|
152
|
-
- `--max-nodes`, `--ping-interval`, `--ping-timeout` - tune scale and heartbeat behavior.
|
|
153
|
-
- `--log-level` - dial verbosity for debugging or production.
|
|
154
|
-
|
|
155
|
-
### 3) Environment overrides
|
|
156
|
-
|
|
157
|
-
- `WINGMAN_GATEWAY_TOKEN` - supply a token at runtime so you don't store secrets in config.
|
|
158
|
-
|
|
159
|
-
### Related gateway behavior (configured elsewhere)
|
|
160
|
-
|
|
161
|
-
- `agents.bindings` - deterministic routing rules used by the gateway to select an agent per inbound channel/message.
|
|
162
|
-
- `voice` - gateway TTS defaults (provider + settings), with optional per-agent overrides for voice-enabled UIs.
|
|
163
|
-
|
|
164
|
-
### Example configs (common setups)
|
|
132
|
+
```bash
|
|
133
|
+
# gateway auth token
|
|
134
|
+
wingman gateway token --generate
|
|
135
|
+
export WINGMAN_GATEWAY_TOKEN="<token>"
|
|
165
136
|
|
|
166
|
-
|
|
137
|
+
# gateway runtime
|
|
138
|
+
wingman gateway start
|
|
167
139
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
"auth": { "mode": "none" },
|
|
174
|
-
"controlUi": { "enabled": true, "port": 18790 }
|
|
175
|
-
}
|
|
176
|
-
}
|
|
140
|
+
# skills
|
|
141
|
+
wingman skill browse
|
|
142
|
+
wingman skill install <skill-name>
|
|
143
|
+
wingman skill list
|
|
144
|
+
wingman skill remove <skill-name>
|
|
177
145
|
```
|
|
178
146
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
"gateway": {
|
|
184
|
-
"host": "0.0.0.0",
|
|
185
|
-
"port": 18789,
|
|
186
|
-
"fsRoots": ["~/Projects", "~/.wingman/outputs"],
|
|
187
|
-
"auth": { "mode": "token" },
|
|
188
|
-
"controlUi": { "enabled": true, "port": 18790, "pairingRequired": true }
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
```
|
|
147
|
+
- Skill scan runs on each `wingman skill install` only when `skills.security.scanOnInstall` is enabled.
|
|
148
|
+
- MCP proxy runs at agent runtime only when `gateway.mcpProxy.enabled` is enabled.
|
|
149
|
+
- If `uv` is missing for an enabled feature, Wingman fails with an error (no interactive prompt).
|
|
150
|
+
- Full config examples: `../docs-website/docs/configuration/skills.mdx`, `../docs-website/docs/configuration/gateway.mdx`, `../docs-website/docs/configuration/wingman-config.mdx`.
|
|
192
151
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
#### 3) Headless gateway + Discord output adapter
|
|
196
|
-
|
|
197
|
-
```json
|
|
198
|
-
{
|
|
199
|
-
"gateway": {
|
|
200
|
-
"host": "0.0.0.0",
|
|
201
|
-
"port": 18789,
|
|
202
|
-
"auth": { "mode": "token" },
|
|
203
|
-
"controlUi": { "enabled": false },
|
|
204
|
-
"adapters": {
|
|
205
|
-
"discord": {
|
|
206
|
-
"enabled": true,
|
|
207
|
-
"token": "DISCORD_BOT_TOKEN",
|
|
208
|
-
"mentionOnly": true,
|
|
209
|
-
"allowedGuilds": ["123456789012345678"],
|
|
210
|
-
"allowedChannels": ["987654321098765432"],
|
|
211
|
-
"channelSessions": {
|
|
212
|
-
"987654321098765432": "agent:support:discord:channel:987654321098765432"
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
```
|
|
152
|
+
## Configuration
|
|
219
153
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
```json
|
|
223
|
-
{
|
|
224
|
-
"gateway": {
|
|
225
|
-
"host": "0.0.0.0",
|
|
226
|
-
"port": 18789,
|
|
227
|
-
"auth": { "mode": "token", "allowTailscale": true },
|
|
228
|
-
"controlUi": { "enabled": true, "port": 18790, "pairingRequired": true }
|
|
229
|
-
},
|
|
230
|
-
"voice": {
|
|
231
|
-
"provider": "elevenlabs",
|
|
232
|
-
"defaultPolicy": "off",
|
|
233
|
-
"elevenlabs": {
|
|
234
|
-
"voiceId": "VOICE_ID",
|
|
235
|
-
"modelId": "eleven_multilingual_v2",
|
|
236
|
-
"stability": 0.4,
|
|
237
|
-
"similarityBoost": 0.7
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
```
|
|
154
|
+
Where to configure:
|
|
242
155
|
|
|
243
|
-
|
|
156
|
+
- Runtime flags: `wingman gateway start --help`
|
|
157
|
+
- Environment secret: `WINGMAN_GATEWAY_TOKEN`
|
|
158
|
+
- Persistent config: `.wingman/wingman.config.json`
|
|
159
|
+
- JSON schema: `https://getwingmanai.com/schemas/wingman.config.schema.json`
|
|
244
160
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
161
|
+
Docs (full examples):
|
|
162
|
+
|
|
163
|
+
- Gateway: `../docs-website/docs/configuration/gateway.mdx`
|
|
164
|
+
- Skills: `../docs-website/docs/configuration/skills.mdx`
|
|
165
|
+
- Full config: `../docs-website/docs/configuration/wingman-config.mdx`
|
|
248
166
|
|
|
249
167
|
## Core Concepts
|
|
250
168
|
|
|
@@ -9,6 +9,8 @@ export declare const AvailableToolNames: z.ZodEnum<{
|
|
|
9
9
|
browser_control: "browser_control";
|
|
10
10
|
command_execute: "command_execute";
|
|
11
11
|
background_terminal: "background_terminal";
|
|
12
|
+
node_notify: "node_notify";
|
|
13
|
+
node_run: "node_run";
|
|
12
14
|
think: "think";
|
|
13
15
|
code_search: "code_search";
|
|
14
16
|
git_status: "git_status";
|
|
@@ -44,6 +46,8 @@ export declare const AgentConfigSchema: z.ZodObject<{
|
|
|
44
46
|
browser_control: "browser_control";
|
|
45
47
|
command_execute: "command_execute";
|
|
46
48
|
background_terminal: "background_terminal";
|
|
49
|
+
node_notify: "node_notify";
|
|
50
|
+
node_run: "node_run";
|
|
47
51
|
think: "think";
|
|
48
52
|
code_search: "code_search";
|
|
49
53
|
git_status: "git_status";
|
|
@@ -148,6 +152,8 @@ export declare const AgentConfigSchema: z.ZodObject<{
|
|
|
148
152
|
browser_control: "browser_control";
|
|
149
153
|
command_execute: "command_execute";
|
|
150
154
|
background_terminal: "background_terminal";
|
|
155
|
+
node_notify: "node_notify";
|
|
156
|
+
node_run: "node_run";
|
|
151
157
|
think: "think";
|
|
152
158
|
code_search: "code_search";
|
|
153
159
|
git_status: "git_status";
|
|
@@ -45,6 +45,10 @@ function _define_property(obj, key, value) {
|
|
|
45
45
|
}
|
|
46
46
|
const logger = (0, external_logger_cjs_namespaceObject.createLogger)();
|
|
47
47
|
const PROMPT_REFINEMENT_MARKER = "[[wingman:prompt-refinement]]";
|
|
48
|
+
const ALWAYS_ON_TOOL_NAMES = [
|
|
49
|
+
...external_toolRegistry_cjs_namespaceObject.UI_TOOL_NAMES,
|
|
50
|
+
...external_toolRegistry_cjs_namespaceObject.NODE_TOOL_NAMES
|
|
51
|
+
];
|
|
48
52
|
const normalizePromptRefinementPath = (agentName, rawPath)=>{
|
|
49
53
|
const fallback = `/memories/agents/${agentName}/instructions.md`;
|
|
50
54
|
if (!rawPath) return fallback;
|
|
@@ -244,16 +248,23 @@ class AgentLoader {
|
|
|
244
248
|
...this.runtimeToolOptions
|
|
245
249
|
};
|
|
246
250
|
};
|
|
251
|
+
const addAlwaysOnTools = async (existingTools, source)=>{
|
|
252
|
+
const alwaysOnTools = await (0, external_toolRegistry_cjs_namespaceObject.createTools)([
|
|
253
|
+
...ALWAYS_ON_TOOL_NAMES
|
|
254
|
+
], buildToolOptions(source));
|
|
255
|
+
if (0 === alwaysOnTools.length) return existingTools || [];
|
|
256
|
+
if (existingTools && existingTools.length > 0) {
|
|
257
|
+
const existing = new Set(existingTools.map((tool)=>tool.name));
|
|
258
|
+
const uniqueAlwaysOnTools = alwaysOnTools.filter((tool)=>!existing.has(tool.name));
|
|
259
|
+
return [
|
|
260
|
+
...existingTools,
|
|
261
|
+
...uniqueAlwaysOnTools
|
|
262
|
+
];
|
|
263
|
+
}
|
|
264
|
+
return alwaysOnTools;
|
|
265
|
+
};
|
|
247
266
|
if (config.tools && config.tools.length > 0) agent.tools = await (0, external_toolRegistry_cjs_namespaceObject.createTools)(config.tools, buildToolOptions(config));
|
|
248
|
-
|
|
249
|
-
if (uiTools.length > 0) if (agent.tools && agent.tools.length > 0) {
|
|
250
|
-
const existing = new Set(agent.tools.map((tool)=>tool.name));
|
|
251
|
-
const uniqueUiTools = uiTools.filter((tool)=>!existing.has(tool.name));
|
|
252
|
-
agent.tools = [
|
|
253
|
-
...agent.tools,
|
|
254
|
-
...uniqueUiTools
|
|
255
|
-
];
|
|
256
|
-
} else agent.tools = uiTools;
|
|
267
|
+
agent.tools = await addAlwaysOnTools(agent.tools, config);
|
|
257
268
|
if (config.mcp) agent.mcpConfig = config.mcp;
|
|
258
269
|
if (config.mcpUseGlobal) agent.mcpUseGlobal = true;
|
|
259
270
|
if (config.model) try {
|
|
@@ -280,15 +291,7 @@ class AgentLoader {
|
|
|
280
291
|
sub.systemPrompt = applyPromptRefinement(sub.systemPrompt, subagent.name, subagent.promptRefinement);
|
|
281
292
|
}
|
|
282
293
|
if (subagent.tools && subagent.tools.length > 0) sub.tools = await (0, external_toolRegistry_cjs_namespaceObject.createTools)(subagent.tools, buildToolOptions(subagent));
|
|
283
|
-
|
|
284
|
-
if (subUiTools.length > 0) if (sub.tools && sub.tools.length > 0) {
|
|
285
|
-
const existing = new Set(sub.tools.map((tool)=>tool.name));
|
|
286
|
-
const uniqueUiTools = subUiTools.filter((tool)=>!existing.has(tool.name));
|
|
287
|
-
sub.tools = [
|
|
288
|
-
...sub.tools,
|
|
289
|
-
...uniqueUiTools
|
|
290
|
-
];
|
|
291
|
-
} else sub.tools = subUiTools;
|
|
294
|
+
sub.tools = await addAlwaysOnTools(sub.tools, subagent);
|
|
292
295
|
if (subagent.model) try {
|
|
293
296
|
sub.model = external_modelFactory_cjs_namespaceObject.ModelFactory.createModel(subagent.model, {
|
|
294
297
|
reasoningEffort: subagent.reasoningEffort,
|
|
@@ -4,7 +4,7 @@ import { load } from "js-yaml";
|
|
|
4
4
|
import { createLogger } from "../../logger.js";
|
|
5
5
|
import { WingmanDirectory, validateAgentConfig } from "./agentConfig.js";
|
|
6
6
|
import { ModelFactory } from "./modelFactory.js";
|
|
7
|
-
import { UI_TOOL_NAMES, createTools } from "./toolRegistry.js";
|
|
7
|
+
import { NODE_TOOL_NAMES, UI_TOOL_NAMES, createTools } from "./toolRegistry.js";
|
|
8
8
|
function _define_property(obj, key, value) {
|
|
9
9
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
10
10
|
value: value,
|
|
@@ -17,6 +17,10 @@ function _define_property(obj, key, value) {
|
|
|
17
17
|
}
|
|
18
18
|
const logger = createLogger();
|
|
19
19
|
const PROMPT_REFINEMENT_MARKER = "[[wingman:prompt-refinement]]";
|
|
20
|
+
const ALWAYS_ON_TOOL_NAMES = [
|
|
21
|
+
...UI_TOOL_NAMES,
|
|
22
|
+
...NODE_TOOL_NAMES
|
|
23
|
+
];
|
|
20
24
|
const normalizePromptRefinementPath = (agentName, rawPath)=>{
|
|
21
25
|
const fallback = `/memories/agents/${agentName}/instructions.md`;
|
|
22
26
|
if (!rawPath) return fallback;
|
|
@@ -216,16 +220,23 @@ class AgentLoader {
|
|
|
216
220
|
...this.runtimeToolOptions
|
|
217
221
|
};
|
|
218
222
|
};
|
|
223
|
+
const addAlwaysOnTools = async (existingTools, source)=>{
|
|
224
|
+
const alwaysOnTools = await createTools([
|
|
225
|
+
...ALWAYS_ON_TOOL_NAMES
|
|
226
|
+
], buildToolOptions(source));
|
|
227
|
+
if (0 === alwaysOnTools.length) return existingTools || [];
|
|
228
|
+
if (existingTools && existingTools.length > 0) {
|
|
229
|
+
const existing = new Set(existingTools.map((tool)=>tool.name));
|
|
230
|
+
const uniqueAlwaysOnTools = alwaysOnTools.filter((tool)=>!existing.has(tool.name));
|
|
231
|
+
return [
|
|
232
|
+
...existingTools,
|
|
233
|
+
...uniqueAlwaysOnTools
|
|
234
|
+
];
|
|
235
|
+
}
|
|
236
|
+
return alwaysOnTools;
|
|
237
|
+
};
|
|
219
238
|
if (config.tools && config.tools.length > 0) agent.tools = await createTools(config.tools, buildToolOptions(config));
|
|
220
|
-
|
|
221
|
-
if (uiTools.length > 0) if (agent.tools && agent.tools.length > 0) {
|
|
222
|
-
const existing = new Set(agent.tools.map((tool)=>tool.name));
|
|
223
|
-
const uniqueUiTools = uiTools.filter((tool)=>!existing.has(tool.name));
|
|
224
|
-
agent.tools = [
|
|
225
|
-
...agent.tools,
|
|
226
|
-
...uniqueUiTools
|
|
227
|
-
];
|
|
228
|
-
} else agent.tools = uiTools;
|
|
239
|
+
agent.tools = await addAlwaysOnTools(agent.tools, config);
|
|
229
240
|
if (config.mcp) agent.mcpConfig = config.mcp;
|
|
230
241
|
if (config.mcpUseGlobal) agent.mcpUseGlobal = true;
|
|
231
242
|
if (config.model) try {
|
|
@@ -252,15 +263,7 @@ class AgentLoader {
|
|
|
252
263
|
sub.systemPrompt = applyPromptRefinement(sub.systemPrompt, subagent.name, subagent.promptRefinement);
|
|
253
264
|
}
|
|
254
265
|
if (subagent.tools && subagent.tools.length > 0) sub.tools = await createTools(subagent.tools, buildToolOptions(subagent));
|
|
255
|
-
|
|
256
|
-
if (subUiTools.length > 0) if (sub.tools && sub.tools.length > 0) {
|
|
257
|
-
const existing = new Set(sub.tools.map((tool)=>tool.name));
|
|
258
|
-
const uniqueUiTools = subUiTools.filter((tool)=>!existing.has(tool.name));
|
|
259
|
-
sub.tools = [
|
|
260
|
-
...sub.tools,
|
|
261
|
-
...uniqueUiTools
|
|
262
|
-
];
|
|
263
|
-
} else sub.tools = subUiTools;
|
|
266
|
+
sub.tools = await addAlwaysOnTools(sub.tools, subagent);
|
|
264
267
|
if (subagent.model) try {
|
|
265
268
|
sub.model = ModelFactory.createModel(subagent.model, {
|
|
266
269
|
reasoningEffort: subagent.reasoningEffort,
|
|
@@ -52,15 +52,7 @@ class MCPClientManager {
|
|
|
52
52
|
for (const [key, value] of Object.entries(stdioServer.env || {}))resolvedEnv[key] = resolveEnvValue(value);
|
|
53
53
|
const runtimeEnv = this.applyRuntimeEnv(resolvedEnv);
|
|
54
54
|
const defaultToolTimeout = getDefaultToolTimeout(stdioServer);
|
|
55
|
-
mcpServers[server.name] =
|
|
56
|
-
transport: "stdio",
|
|
57
|
-
command: stdioServer.command,
|
|
58
|
-
args: stdioServer.args || [],
|
|
59
|
-
env: runtimeEnv,
|
|
60
|
-
...void 0 !== defaultToolTimeout ? {
|
|
61
|
-
defaultToolTimeout
|
|
62
|
-
} : {}
|
|
63
|
-
};
|
|
55
|
+
mcpServers[server.name] = this.buildStdioServerConfig(stdioServer, runtimeEnv, defaultToolTimeout);
|
|
64
56
|
} else if ("sse" === server.transport) {
|
|
65
57
|
const sseServer = server;
|
|
66
58
|
const defaultToolTimeout = getDefaultToolTimeout(sseServer);
|
|
@@ -83,6 +75,51 @@ class MCPClientManager {
|
|
|
83
75
|
}
|
|
84
76
|
};
|
|
85
77
|
}
|
|
78
|
+
buildStdioServerConfig(server, env, defaultToolTimeout) {
|
|
79
|
+
const baseConfig = {
|
|
80
|
+
transport: "stdio",
|
|
81
|
+
command: server.command,
|
|
82
|
+
args: server.args || [],
|
|
83
|
+
env,
|
|
84
|
+
...void 0 !== defaultToolTimeout ? {
|
|
85
|
+
defaultToolTimeout
|
|
86
|
+
} : {}
|
|
87
|
+
};
|
|
88
|
+
if (!this.proxyConfig?.enabled) return baseConfig;
|
|
89
|
+
const proxyCommand = this.proxyConfig.command?.trim() || "uvx";
|
|
90
|
+
const proxyBaseArgs = this.proxyConfig.baseArgs && this.proxyConfig.baseArgs.length > 0 ? this.proxyConfig.baseArgs : [
|
|
91
|
+
"invariant-gateway@latest",
|
|
92
|
+
"mcp"
|
|
93
|
+
];
|
|
94
|
+
const proxyEnv = {
|
|
95
|
+
...env
|
|
96
|
+
};
|
|
97
|
+
if (this.proxyConfig.apiKey) proxyEnv.INVARIANT_API_KEY = this.proxyConfig.apiKey;
|
|
98
|
+
if (this.proxyConfig.apiUrl) {
|
|
99
|
+
proxyEnv.INVARIANT_API_URL = this.proxyConfig.apiUrl;
|
|
100
|
+
proxyEnv.GUARDRAILS_API_URL = this.proxyConfig.apiUrl;
|
|
101
|
+
}
|
|
102
|
+
const proxyArgs = [
|
|
103
|
+
...proxyBaseArgs,
|
|
104
|
+
"--project-name",
|
|
105
|
+
this.proxyConfig.projectName || "wingman-gateway",
|
|
106
|
+
...this.proxyConfig.pushExplorer ? [
|
|
107
|
+
"--push-explorer"
|
|
108
|
+
] : [],
|
|
109
|
+
"--exec",
|
|
110
|
+
baseConfig.command,
|
|
111
|
+
...baseConfig.args || []
|
|
112
|
+
];
|
|
113
|
+
return {
|
|
114
|
+
transport: "stdio",
|
|
115
|
+
command: proxyCommand,
|
|
116
|
+
args: proxyArgs,
|
|
117
|
+
env: proxyEnv,
|
|
118
|
+
...void 0 !== defaultToolTimeout ? {
|
|
119
|
+
defaultToolTimeout
|
|
120
|
+
} : {}
|
|
121
|
+
};
|
|
122
|
+
}
|
|
86
123
|
applyRuntimeEnv(env) {
|
|
87
124
|
if (!this.executionWorkspace) return env;
|
|
88
125
|
const next = {
|
|
@@ -176,9 +213,11 @@ class MCPClientManager {
|
|
|
176
213
|
_define_property(this, "logger", void 0);
|
|
177
214
|
_define_property(this, "serverConfigs", void 0);
|
|
178
215
|
_define_property(this, "executionWorkspace", void 0);
|
|
216
|
+
_define_property(this, "proxyConfig", void 0);
|
|
179
217
|
this.logger = logger;
|
|
180
218
|
this.serverConfigs = this.mergeConfigs(configs);
|
|
181
219
|
this.executionWorkspace = options?.executionWorkspace?.trim() || null;
|
|
220
|
+
this.proxyConfig = options?.proxyConfig;
|
|
182
221
|
}
|
|
183
222
|
}
|
|
184
223
|
function resolveEnvValue(value) {
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import type { StructuredTool } from "@langchain/core/tools";
|
|
2
2
|
import type { Logger } from "@/logger.js";
|
|
3
3
|
import type { MCPServersConfig } from "@/types/mcp.js";
|
|
4
|
+
export type MCPProxyConfig = {
|
|
5
|
+
enabled?: boolean;
|
|
6
|
+
command?: string;
|
|
7
|
+
baseArgs?: string[];
|
|
8
|
+
projectName?: string;
|
|
9
|
+
pushExplorer?: boolean;
|
|
10
|
+
apiKey?: string;
|
|
11
|
+
apiUrl?: string;
|
|
12
|
+
};
|
|
4
13
|
/**
|
|
5
14
|
* Manages MCP server connections and tool retrieval
|
|
6
15
|
* Handles server lifecycle: initialization, tool loading, and cleanup
|
|
@@ -10,8 +19,10 @@ export declare class MCPClientManager {
|
|
|
10
19
|
private logger;
|
|
11
20
|
private serverConfigs;
|
|
12
21
|
private executionWorkspace;
|
|
22
|
+
private proxyConfig;
|
|
13
23
|
constructor(configs: MCPServersConfig[], logger: Logger, options?: {
|
|
14
24
|
executionWorkspace?: string | null;
|
|
25
|
+
proxyConfig?: MCPProxyConfig;
|
|
15
26
|
});
|
|
16
27
|
/**
|
|
17
28
|
* Merge multiple MCP configurations (global + agent-specific)
|
|
@@ -22,6 +33,7 @@ export declare class MCPClientManager {
|
|
|
22
33
|
* Convert Wingman MCP config to MultiServerMCPClient format
|
|
23
34
|
*/
|
|
24
35
|
private buildClientConfig;
|
|
36
|
+
private buildStdioServerConfig;
|
|
25
37
|
private applyRuntimeEnv;
|
|
26
38
|
/**
|
|
27
39
|
* Initialize MCP client and connect to servers
|
|
@@ -24,15 +24,7 @@ class MCPClientManager {
|
|
|
24
24
|
for (const [key, value] of Object.entries(stdioServer.env || {}))resolvedEnv[key] = resolveEnvValue(value);
|
|
25
25
|
const runtimeEnv = this.applyRuntimeEnv(resolvedEnv);
|
|
26
26
|
const defaultToolTimeout = getDefaultToolTimeout(stdioServer);
|
|
27
|
-
mcpServers[server.name] =
|
|
28
|
-
transport: "stdio",
|
|
29
|
-
command: stdioServer.command,
|
|
30
|
-
args: stdioServer.args || [],
|
|
31
|
-
env: runtimeEnv,
|
|
32
|
-
...void 0 !== defaultToolTimeout ? {
|
|
33
|
-
defaultToolTimeout
|
|
34
|
-
} : {}
|
|
35
|
-
};
|
|
27
|
+
mcpServers[server.name] = this.buildStdioServerConfig(stdioServer, runtimeEnv, defaultToolTimeout);
|
|
36
28
|
} else if ("sse" === server.transport) {
|
|
37
29
|
const sseServer = server;
|
|
38
30
|
const defaultToolTimeout = getDefaultToolTimeout(sseServer);
|
|
@@ -55,6 +47,51 @@ class MCPClientManager {
|
|
|
55
47
|
}
|
|
56
48
|
};
|
|
57
49
|
}
|
|
50
|
+
buildStdioServerConfig(server, env, defaultToolTimeout) {
|
|
51
|
+
const baseConfig = {
|
|
52
|
+
transport: "stdio",
|
|
53
|
+
command: server.command,
|
|
54
|
+
args: server.args || [],
|
|
55
|
+
env,
|
|
56
|
+
...void 0 !== defaultToolTimeout ? {
|
|
57
|
+
defaultToolTimeout
|
|
58
|
+
} : {}
|
|
59
|
+
};
|
|
60
|
+
if (!this.proxyConfig?.enabled) return baseConfig;
|
|
61
|
+
const proxyCommand = this.proxyConfig.command?.trim() || "uvx";
|
|
62
|
+
const proxyBaseArgs = this.proxyConfig.baseArgs && this.proxyConfig.baseArgs.length > 0 ? this.proxyConfig.baseArgs : [
|
|
63
|
+
"invariant-gateway@latest",
|
|
64
|
+
"mcp"
|
|
65
|
+
];
|
|
66
|
+
const proxyEnv = {
|
|
67
|
+
...env
|
|
68
|
+
};
|
|
69
|
+
if (this.proxyConfig.apiKey) proxyEnv.INVARIANT_API_KEY = this.proxyConfig.apiKey;
|
|
70
|
+
if (this.proxyConfig.apiUrl) {
|
|
71
|
+
proxyEnv.INVARIANT_API_URL = this.proxyConfig.apiUrl;
|
|
72
|
+
proxyEnv.GUARDRAILS_API_URL = this.proxyConfig.apiUrl;
|
|
73
|
+
}
|
|
74
|
+
const proxyArgs = [
|
|
75
|
+
...proxyBaseArgs,
|
|
76
|
+
"--project-name",
|
|
77
|
+
this.proxyConfig.projectName || "wingman-gateway",
|
|
78
|
+
...this.proxyConfig.pushExplorer ? [
|
|
79
|
+
"--push-explorer"
|
|
80
|
+
] : [],
|
|
81
|
+
"--exec",
|
|
82
|
+
baseConfig.command,
|
|
83
|
+
...baseConfig.args || []
|
|
84
|
+
];
|
|
85
|
+
return {
|
|
86
|
+
transport: "stdio",
|
|
87
|
+
command: proxyCommand,
|
|
88
|
+
args: proxyArgs,
|
|
89
|
+
env: proxyEnv,
|
|
90
|
+
...void 0 !== defaultToolTimeout ? {
|
|
91
|
+
defaultToolTimeout
|
|
92
|
+
} : {}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
58
95
|
applyRuntimeEnv(env) {
|
|
59
96
|
if (!this.executionWorkspace) return env;
|
|
60
97
|
const next = {
|
|
@@ -148,9 +185,11 @@ class MCPClientManager {
|
|
|
148
185
|
_define_property(this, "logger", void 0);
|
|
149
186
|
_define_property(this, "serverConfigs", void 0);
|
|
150
187
|
_define_property(this, "executionWorkspace", void 0);
|
|
188
|
+
_define_property(this, "proxyConfig", void 0);
|
|
151
189
|
this.logger = logger;
|
|
152
190
|
this.serverConfigs = this.mergeConfigs(configs);
|
|
153
191
|
this.executionWorkspace = options?.executionWorkspace?.trim() || null;
|
|
192
|
+
this.proxyConfig = options?.proxyConfig;
|
|
154
193
|
}
|
|
155
194
|
}
|
|
156
195
|
function resolveEnvValue(value) {
|
|
@@ -27,6 +27,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
27
27
|
createTools: ()=>createTools,
|
|
28
28
|
UI_TOOL_NAMES: ()=>UI_TOOL_NAMES,
|
|
29
29
|
getAvailableTools: ()=>getAvailableTools,
|
|
30
|
+
NODE_TOOL_NAMES: ()=>NODE_TOOL_NAMES,
|
|
30
31
|
createTool: ()=>createTool
|
|
31
32
|
});
|
|
32
33
|
const external_logger_cjs_namespaceObject = require("../../logger.cjs");
|
|
@@ -36,6 +37,7 @@ const code_search_cjs_namespaceObject = require("../tools/code_search.cjs");
|
|
|
36
37
|
const command_execute_cjs_namespaceObject = require("../tools/command_execute.cjs");
|
|
37
38
|
const git_status_cjs_namespaceObject = require("../tools/git_status.cjs");
|
|
38
39
|
const internet_search_cjs_namespaceObject = require("../tools/internet_search.cjs");
|
|
40
|
+
const node_invoke_cjs_namespaceObject = require("../tools/node_invoke.cjs");
|
|
39
41
|
const terminal_session_manager_cjs_namespaceObject = require("../tools/terminal_session_manager.cjs");
|
|
40
42
|
const think_cjs_namespaceObject = require("../tools/think.cjs");
|
|
41
43
|
const ui_registry_cjs_namespaceObject = require("../tools/ui_registry.cjs");
|
|
@@ -47,6 +49,10 @@ const UI_TOOL_NAMES = [
|
|
|
47
49
|
"ui_registry_get",
|
|
48
50
|
"ui_present"
|
|
49
51
|
];
|
|
52
|
+
const NODE_TOOL_NAMES = [
|
|
53
|
+
"node_notify",
|
|
54
|
+
"node_run"
|
|
55
|
+
];
|
|
50
56
|
function createTool(name, options = {}) {
|
|
51
57
|
const { workspace = process.cwd(), executionWorkspace, blockedCommands, allowScriptExecution = true, timeout = 300000, terminalOwnerId = "default", terminalSessionManager = (0, terminal_session_manager_cjs_namespaceObject.getSharedTerminalSessionManager)(), searchConfig = {
|
|
52
58
|
provider: "duckduckgo",
|
|
@@ -93,6 +99,16 @@ function createTool(name, options = {}) {
|
|
|
93
99
|
allowScriptExecution,
|
|
94
100
|
commandTimeout: timeout
|
|
95
101
|
});
|
|
102
|
+
case "node_notify":
|
|
103
|
+
return (0, node_invoke_cjs_namespaceObject.createNodeNotifyTool)({
|
|
104
|
+
nodeInvoker: options.nodeInvoker,
|
|
105
|
+
defaultTargetClientId: options.nodeDefaultTargetClientId
|
|
106
|
+
});
|
|
107
|
+
case "node_run":
|
|
108
|
+
return (0, node_invoke_cjs_namespaceObject.createNodeRunTool)({
|
|
109
|
+
nodeInvoker: options.nodeInvoker,
|
|
110
|
+
defaultTargetClientId: options.nodeDefaultTargetClientId
|
|
111
|
+
});
|
|
96
112
|
case "think":
|
|
97
113
|
return (0, think_cjs_namespaceObject.createThinkingTool)();
|
|
98
114
|
case "code_search":
|
|
@@ -140,17 +156,20 @@ function getAvailableTools() {
|
|
|
140
156
|
"browser_control",
|
|
141
157
|
"command_execute",
|
|
142
158
|
"background_terminal",
|
|
159
|
+
...NODE_TOOL_NAMES,
|
|
143
160
|
"think",
|
|
144
161
|
"code_search",
|
|
145
162
|
"git_status",
|
|
146
163
|
...UI_TOOL_NAMES
|
|
147
164
|
];
|
|
148
165
|
}
|
|
166
|
+
exports.NODE_TOOL_NAMES = __webpack_exports__.NODE_TOOL_NAMES;
|
|
149
167
|
exports.UI_TOOL_NAMES = __webpack_exports__.UI_TOOL_NAMES;
|
|
150
168
|
exports.createTool = __webpack_exports__.createTool;
|
|
151
169
|
exports.createTools = __webpack_exports__.createTools;
|
|
152
170
|
exports.getAvailableTools = __webpack_exports__.getAvailableTools;
|
|
153
171
|
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
172
|
+
"NODE_TOOL_NAMES",
|
|
154
173
|
"UI_TOOL_NAMES",
|
|
155
174
|
"createTool",
|
|
156
175
|
"createTools",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { StructuredTool } from "@langchain/core/tools";
|
|
2
2
|
import type { MCPServersConfig } from "@/types/mcp.js";
|
|
3
3
|
import type { SearchConfig } from "../../cli/config/schema.js";
|
|
4
|
+
import { type NodeInvokeRequest, type NodeInvokeResult } from "../tools/node_invoke.js";
|
|
4
5
|
import { type TerminalSessionManager } from "../tools/terminal_session_manager.js";
|
|
5
6
|
import type { AvailableToolName } from "./agentConfig.js";
|
|
6
7
|
export interface ToolOptions {
|
|
@@ -30,8 +31,11 @@ export interface ToolOptions {
|
|
|
30
31
|
mcpConfigs?: MCPServersConfig[];
|
|
31
32
|
skillsDirectory?: string;
|
|
32
33
|
dynamicUiEnabled?: boolean;
|
|
34
|
+
nodeInvoker?: (request: NodeInvokeRequest) => Promise<NodeInvokeResult>;
|
|
35
|
+
nodeDefaultTargetClientId?: string;
|
|
33
36
|
}
|
|
34
37
|
export declare const UI_TOOL_NAMES: AvailableToolName[];
|
|
38
|
+
export declare const NODE_TOOL_NAMES: AvailableToolName[];
|
|
35
39
|
/**
|
|
36
40
|
* Create a tool by name with optional configuration
|
|
37
41
|
*/
|
|
@@ -5,6 +5,7 @@ import { createCodeSearchTool } from "../tools/code_search.js";
|
|
|
5
5
|
import { createCommandExecuteTool } from "../tools/command_execute.js";
|
|
6
6
|
import { createGitStatusTool } from "../tools/git_status.js";
|
|
7
7
|
import { createInternetSearchTool } from "../tools/internet_search.js";
|
|
8
|
+
import { createNodeNotifyTool, createNodeRunTool } from "../tools/node_invoke.js";
|
|
8
9
|
import { getSharedTerminalSessionManager } from "../tools/terminal_session_manager.js";
|
|
9
10
|
import { createThinkingTool } from "../tools/think.js";
|
|
10
11
|
import { createUiPresentTool, createUiRegistryGetTool, createUiRegistryListTool } from "../tools/ui_registry.js";
|
|
@@ -16,6 +17,10 @@ const UI_TOOL_NAMES = [
|
|
|
16
17
|
"ui_registry_get",
|
|
17
18
|
"ui_present"
|
|
18
19
|
];
|
|
20
|
+
const NODE_TOOL_NAMES = [
|
|
21
|
+
"node_notify",
|
|
22
|
+
"node_run"
|
|
23
|
+
];
|
|
19
24
|
function createTool(name, options = {}) {
|
|
20
25
|
const { workspace = process.cwd(), executionWorkspace, blockedCommands, allowScriptExecution = true, timeout = 300000, terminalOwnerId = "default", terminalSessionManager = getSharedTerminalSessionManager(), searchConfig = {
|
|
21
26
|
provider: "duckduckgo",
|
|
@@ -62,6 +67,16 @@ function createTool(name, options = {}) {
|
|
|
62
67
|
allowScriptExecution,
|
|
63
68
|
commandTimeout: timeout
|
|
64
69
|
});
|
|
70
|
+
case "node_notify":
|
|
71
|
+
return createNodeNotifyTool({
|
|
72
|
+
nodeInvoker: options.nodeInvoker,
|
|
73
|
+
defaultTargetClientId: options.nodeDefaultTargetClientId
|
|
74
|
+
});
|
|
75
|
+
case "node_run":
|
|
76
|
+
return createNodeRunTool({
|
|
77
|
+
nodeInvoker: options.nodeInvoker,
|
|
78
|
+
defaultTargetClientId: options.nodeDefaultTargetClientId
|
|
79
|
+
});
|
|
65
80
|
case "think":
|
|
66
81
|
return createThinkingTool();
|
|
67
82
|
case "code_search":
|
|
@@ -109,10 +124,11 @@ function getAvailableTools() {
|
|
|
109
124
|
"browser_control",
|
|
110
125
|
"command_execute",
|
|
111
126
|
"background_terminal",
|
|
127
|
+
...NODE_TOOL_NAMES,
|
|
112
128
|
"think",
|
|
113
129
|
"code_search",
|
|
114
130
|
"git_status",
|
|
115
131
|
...UI_TOOL_NAMES
|
|
116
132
|
];
|
|
117
133
|
}
|
|
118
|
-
export { UI_TOOL_NAMES, createTool, createTools, getAvailableTools };
|
|
134
|
+
export { NODE_TOOL_NAMES, UI_TOOL_NAMES, createTool, createTools, getAvailableTools };
|