@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,11 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { createCommandExecuteTool } from "../tools/command_execute.js";
|
|
4
|
-
import { createThinkingTool } from "../tools/think.js";
|
|
1
|
+
import { createLogger } from "../../logger.js";
|
|
2
|
+
import { createBackgroundTerminalTool } from "../tools/background_terminal.js";
|
|
5
3
|
import { createCodeSearchTool } from "../tools/code_search.js";
|
|
4
|
+
import { createCommandExecuteTool } from "../tools/command_execute.js";
|
|
6
5
|
import { createGitStatusTool } from "../tools/git_status.js";
|
|
6
|
+
import { createInternetSearchTool } from "../tools/internet_search.js";
|
|
7
|
+
import { getSharedTerminalSessionManager } from "../tools/terminal_session_manager.js";
|
|
8
|
+
import { createThinkingTool } from "../tools/think.js";
|
|
7
9
|
import { createUiPresentTool, createUiRegistryGetTool, createUiRegistryListTool } from "../tools/ui_registry.js";
|
|
8
|
-
import {
|
|
10
|
+
import { webCrawler } from "../tools/web_crawler.js";
|
|
9
11
|
import { MCPClientManager } from "./mcpClientManager.js";
|
|
10
12
|
const logger = createLogger();
|
|
11
13
|
const UI_TOOL_NAMES = [
|
|
@@ -14,7 +16,7 @@ const UI_TOOL_NAMES = [
|
|
|
14
16
|
"ui_present"
|
|
15
17
|
];
|
|
16
18
|
function createTool(name, options = {}) {
|
|
17
|
-
const { workspace = process.cwd(), executionWorkspace, blockedCommands, allowScriptExecution = true, timeout = 300000, searchConfig = {
|
|
19
|
+
const { workspace = process.cwd(), executionWorkspace, blockedCommands, allowScriptExecution = true, timeout = 300000, terminalOwnerId = "default", terminalSessionManager = getSharedTerminalSessionManager(), searchConfig = {
|
|
18
20
|
provider: "duckduckgo",
|
|
19
21
|
maxResults: 5
|
|
20
22
|
}, skillsDirectory = "skills", dynamicUiEnabled = true } = options;
|
|
@@ -34,6 +36,16 @@ function createTool(name, options = {}) {
|
|
|
34
36
|
return webCrawler;
|
|
35
37
|
case "command_execute":
|
|
36
38
|
return createCommandExecuteTool(runtimeWorkspace, process.env, blockedCommands, allowScriptExecution, timeout);
|
|
39
|
+
case "background_terminal":
|
|
40
|
+
return createBackgroundTerminalTool({
|
|
41
|
+
workspace: runtimeWorkspace,
|
|
42
|
+
ownerId: terminalOwnerId,
|
|
43
|
+
sessionManager: terminalSessionManager,
|
|
44
|
+
envVariables: process.env,
|
|
45
|
+
blockedCommands,
|
|
46
|
+
allowScriptExecution,
|
|
47
|
+
commandTimeout: timeout
|
|
48
|
+
});
|
|
37
49
|
case "think":
|
|
38
50
|
return createThinkingTool();
|
|
39
51
|
case "code_search":
|
|
@@ -77,6 +89,7 @@ function getAvailableTools() {
|
|
|
77
89
|
"internet_search",
|
|
78
90
|
"web_crawler",
|
|
79
91
|
"command_execute",
|
|
92
|
+
"background_terminal",
|
|
80
93
|
"think",
|
|
81
94
|
"code_search",
|
|
82
95
|
"git_status",
|
|
@@ -30,22 +30,22 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
30
30
|
HooksConfigSchema: ()=>HooksConfigSchema
|
|
31
31
|
});
|
|
32
32
|
const external_zod_namespaceObject = require("zod");
|
|
33
|
-
const HookSchema = external_zod_namespaceObject.
|
|
34
|
-
type: external_zod_namespaceObject.
|
|
35
|
-
command: external_zod_namespaceObject.
|
|
36
|
-
timeout: external_zod_namespaceObject.
|
|
33
|
+
const HookSchema = external_zod_namespaceObject.object({
|
|
34
|
+
type: external_zod_namespaceObject.literal("command").describe("Type of hook - currently only 'command' is supported"),
|
|
35
|
+
command: external_zod_namespaceObject.string().min(1).describe("Shell command to execute"),
|
|
36
|
+
timeout: external_zod_namespaceObject.number().positive().optional().default(60).describe("Timeout in seconds (default: 60)")
|
|
37
37
|
});
|
|
38
|
-
const HookMatcherSchema = external_zod_namespaceObject.
|
|
39
|
-
matcher: external_zod_namespaceObject.
|
|
40
|
-
hooks: external_zod_namespaceObject.
|
|
38
|
+
const HookMatcherSchema = external_zod_namespaceObject.object({
|
|
39
|
+
matcher: external_zod_namespaceObject.string().optional().describe("Pattern to match tool names (pipe-separated, wildcard, or regex)"),
|
|
40
|
+
hooks: external_zod_namespaceObject.array(HookSchema).min(1).describe("Array of hooks to execute when pattern matches")
|
|
41
41
|
});
|
|
42
|
-
const StopHookSchema = external_zod_namespaceObject.
|
|
43
|
-
hooks: external_zod_namespaceObject.
|
|
42
|
+
const StopHookSchema = external_zod_namespaceObject.object({
|
|
43
|
+
hooks: external_zod_namespaceObject.array(HookSchema).min(1).describe("Array of hooks to execute when agent stops")
|
|
44
44
|
});
|
|
45
|
-
const HooksConfigSchema = external_zod_namespaceObject.
|
|
46
|
-
PreToolUse: external_zod_namespaceObject.
|
|
47
|
-
PostToolUse: external_zod_namespaceObject.
|
|
48
|
-
Stop: external_zod_namespaceObject.
|
|
45
|
+
const HooksConfigSchema = external_zod_namespaceObject.object({
|
|
46
|
+
PreToolUse: external_zod_namespaceObject.array(HookMatcherSchema).optional().describe("Hooks that fire before tool execution (can block)"),
|
|
47
|
+
PostToolUse: external_zod_namespaceObject.array(HookMatcherSchema).optional().describe("Hooks that fire after tool completes (non-blocking)"),
|
|
48
|
+
Stop: external_zod_namespaceObject.array(StopHookSchema).optional().describe("Hooks that fire when agent completes (non-blocking)")
|
|
49
49
|
});
|
|
50
50
|
exports.HookMatcherSchema = __webpack_exports__.HookMatcherSchema;
|
|
51
51
|
exports.HookSchema = __webpack_exports__.HookSchema;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
const HookSchema =
|
|
3
|
-
type:
|
|
4
|
-
command:
|
|
5
|
-
timeout:
|
|
1
|
+
import { array, literal, number, object, string } from "zod";
|
|
2
|
+
const HookSchema = object({
|
|
3
|
+
type: literal("command").describe("Type of hook - currently only 'command' is supported"),
|
|
4
|
+
command: string().min(1).describe("Shell command to execute"),
|
|
5
|
+
timeout: number().positive().optional().default(60).describe("Timeout in seconds (default: 60)")
|
|
6
6
|
});
|
|
7
|
-
const HookMatcherSchema =
|
|
8
|
-
matcher:
|
|
9
|
-
hooks:
|
|
7
|
+
const HookMatcherSchema = object({
|
|
8
|
+
matcher: string().optional().describe("Pattern to match tool names (pipe-separated, wildcard, or regex)"),
|
|
9
|
+
hooks: array(HookSchema).min(1).describe("Array of hooks to execute when pattern matches")
|
|
10
10
|
});
|
|
11
|
-
const StopHookSchema =
|
|
12
|
-
hooks:
|
|
11
|
+
const StopHookSchema = object({
|
|
12
|
+
hooks: array(HookSchema).min(1).describe("Array of hooks to execute when agent stops")
|
|
13
13
|
});
|
|
14
|
-
const HooksConfigSchema =
|
|
15
|
-
PreToolUse:
|
|
16
|
-
PostToolUse:
|
|
17
|
-
Stop:
|
|
14
|
+
const HooksConfigSchema = object({
|
|
15
|
+
PreToolUse: array(HookMatcherSchema).optional().describe("Hooks that fire before tool execution (can block)"),
|
|
16
|
+
PostToolUse: array(HookMatcherSchema).optional().describe("Hooks that fire after tool completes (non-blocking)"),
|
|
17
|
+
Stop: array(StopHookSchema).optional().describe("Hooks that fire when agent completes (non-blocking)")
|
|
18
18
|
});
|
|
19
19
|
export { HookMatcherSchema, HookSchema, HooksConfigSchema, StopHookSchema };
|
|
@@ -28,6 +28,7 @@ const agentConfig_cjs_namespaceObject = require("../config/agentConfig.cjs");
|
|
|
28
28
|
"think"
|
|
29
29
|
],
|
|
30
30
|
model: "anthropic:claude-opus-4-5",
|
|
31
|
+
reasoningEffort: "high",
|
|
31
32
|
blockedCommands: [
|
|
32
33
|
"rm",
|
|
33
34
|
"mv"
|
|
@@ -43,6 +44,7 @@ const agentConfig_cjs_namespaceObject = require("../config/agentConfig.cjs");
|
|
|
43
44
|
"think"
|
|
44
45
|
]);
|
|
45
46
|
(0, external_vitest_namespaceObject.expect)(result.data.model).toBe("anthropic:claude-opus-4-5");
|
|
47
|
+
(0, external_vitest_namespaceObject.expect)(result.data.reasoningEffort).toBe("high");
|
|
46
48
|
(0, external_vitest_namespaceObject.expect)(result.data.blockedCommands).toEqual([
|
|
47
49
|
"rm",
|
|
48
50
|
"mv"
|
|
@@ -61,13 +63,17 @@ const agentConfig_cjs_namespaceObject = require("../config/agentConfig.cjs");
|
|
|
61
63
|
name: "research-agent",
|
|
62
64
|
description: "Researches topics",
|
|
63
65
|
systemPrompt: "You are a researcher",
|
|
64
|
-
model: "openai:gpt-4o"
|
|
66
|
+
model: "openai:gpt-4o",
|
|
67
|
+
reasoningEffort: "low"
|
|
65
68
|
}
|
|
66
69
|
]
|
|
67
70
|
};
|
|
68
71
|
const result = (0, agentConfig_cjs_namespaceObject.validateAgentConfig)(config);
|
|
69
72
|
(0, external_vitest_namespaceObject.expect)(result.success).toBe(true);
|
|
70
|
-
if (result.success)
|
|
73
|
+
if (result.success) {
|
|
74
|
+
(0, external_vitest_namespaceObject.expect)(result.data.subAgents?.[0].model).toBe("openai:gpt-4o");
|
|
75
|
+
(0, external_vitest_namespaceObject.expect)(result.data.subAgents?.[0].reasoningEffort).toBe("low");
|
|
76
|
+
}
|
|
71
77
|
});
|
|
72
78
|
(0, external_vitest_namespaceObject.it)("should fail when a sub-agent shares the same name as its parent", ()=>{
|
|
73
79
|
const config = {
|
|
@@ -131,6 +137,17 @@ const agentConfig_cjs_namespaceObject = require("../config/agentConfig.cjs");
|
|
|
131
137
|
const result = (0, agentConfig_cjs_namespaceObject.validateAgentConfig)(config);
|
|
132
138
|
(0, external_vitest_namespaceObject.expect)(result.success).toBe(false);
|
|
133
139
|
});
|
|
140
|
+
(0, external_vitest_namespaceObject.it)("should fail validation for invalid reasoning effort", ()=>{
|
|
141
|
+
const config = {
|
|
142
|
+
name: "test-agent",
|
|
143
|
+
description: "Test",
|
|
144
|
+
systemPrompt: "Test",
|
|
145
|
+
reasoningEffort: "extreme"
|
|
146
|
+
};
|
|
147
|
+
const result = (0, agentConfig_cjs_namespaceObject.validateAgentConfig)(config);
|
|
148
|
+
(0, external_vitest_namespaceObject.expect)(result.success).toBe(false);
|
|
149
|
+
if (!result.success) (0, external_vitest_namespaceObject.expect)(result.error).toContain("reasoningEffort");
|
|
150
|
+
});
|
|
134
151
|
(0, external_vitest_namespaceObject.it)("should apply default values for optional fields", ()=>{
|
|
135
152
|
const config = {
|
|
136
153
|
name: "test-agent",
|
|
@@ -173,7 +190,10 @@ const agentConfig_cjs_namespaceObject = require("../config/agentConfig.cjs");
|
|
|
173
190
|
"internet_search",
|
|
174
191
|
"web_crawler",
|
|
175
192
|
"command_execute",
|
|
193
|
+
"background_terminal",
|
|
176
194
|
"think",
|
|
195
|
+
"code_search",
|
|
196
|
+
"git_status",
|
|
177
197
|
"ui_registry_list",
|
|
178
198
|
"ui_registry_get",
|
|
179
199
|
"ui_present"
|
|
@@ -26,6 +26,7 @@ describe("Agent Configuration Schema", ()=>{
|
|
|
26
26
|
"think"
|
|
27
27
|
],
|
|
28
28
|
model: "anthropic:claude-opus-4-5",
|
|
29
|
+
reasoningEffort: "high",
|
|
29
30
|
blockedCommands: [
|
|
30
31
|
"rm",
|
|
31
32
|
"mv"
|
|
@@ -41,6 +42,7 @@ describe("Agent Configuration Schema", ()=>{
|
|
|
41
42
|
"think"
|
|
42
43
|
]);
|
|
43
44
|
expect(result.data.model).toBe("anthropic:claude-opus-4-5");
|
|
45
|
+
expect(result.data.reasoningEffort).toBe("high");
|
|
44
46
|
expect(result.data.blockedCommands).toEqual([
|
|
45
47
|
"rm",
|
|
46
48
|
"mv"
|
|
@@ -59,13 +61,17 @@ describe("Agent Configuration Schema", ()=>{
|
|
|
59
61
|
name: "research-agent",
|
|
60
62
|
description: "Researches topics",
|
|
61
63
|
systemPrompt: "You are a researcher",
|
|
62
|
-
model: "openai:gpt-4o"
|
|
64
|
+
model: "openai:gpt-4o",
|
|
65
|
+
reasoningEffort: "low"
|
|
63
66
|
}
|
|
64
67
|
]
|
|
65
68
|
};
|
|
66
69
|
const result = validateAgentConfig(config);
|
|
67
70
|
expect(result.success).toBe(true);
|
|
68
|
-
if (result.success)
|
|
71
|
+
if (result.success) {
|
|
72
|
+
expect(result.data.subAgents?.[0].model).toBe("openai:gpt-4o");
|
|
73
|
+
expect(result.data.subAgents?.[0].reasoningEffort).toBe("low");
|
|
74
|
+
}
|
|
69
75
|
});
|
|
70
76
|
it("should fail when a sub-agent shares the same name as its parent", ()=>{
|
|
71
77
|
const config = {
|
|
@@ -129,6 +135,17 @@ describe("Agent Configuration Schema", ()=>{
|
|
|
129
135
|
const result = validateAgentConfig(config);
|
|
130
136
|
expect(result.success).toBe(false);
|
|
131
137
|
});
|
|
138
|
+
it("should fail validation for invalid reasoning effort", ()=>{
|
|
139
|
+
const config = {
|
|
140
|
+
name: "test-agent",
|
|
141
|
+
description: "Test",
|
|
142
|
+
systemPrompt: "Test",
|
|
143
|
+
reasoningEffort: "extreme"
|
|
144
|
+
};
|
|
145
|
+
const result = validateAgentConfig(config);
|
|
146
|
+
expect(result.success).toBe(false);
|
|
147
|
+
if (!result.success) expect(result.error).toContain("reasoningEffort");
|
|
148
|
+
});
|
|
132
149
|
it("should apply default values for optional fields", ()=>{
|
|
133
150
|
const config = {
|
|
134
151
|
name: "test-agent",
|
|
@@ -171,7 +188,10 @@ describe("Agent Configuration Schema", ()=>{
|
|
|
171
188
|
"internet_search",
|
|
172
189
|
"web_crawler",
|
|
173
190
|
"command_execute",
|
|
191
|
+
"background_terminal",
|
|
174
192
|
"think",
|
|
193
|
+
"code_search",
|
|
194
|
+
"git_status",
|
|
175
195
|
"ui_registry_list",
|
|
176
196
|
"ui_registry_get",
|
|
177
197
|
"ui_present"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __webpack_exports__ = {};
|
|
3
|
-
const external_vitest_namespaceObject = require("vitest");
|
|
4
3
|
const external_node_fs_namespaceObject = require("node:fs");
|
|
5
4
|
const external_node_path_namespaceObject = require("node:path");
|
|
5
|
+
const external_vitest_namespaceObject = require("vitest");
|
|
6
6
|
const agentLoader_cjs_namespaceObject = require("../config/agentLoader.cjs");
|
|
7
7
|
const TEST_CONFIG_DIR = ".wingman-test";
|
|
8
8
|
(0, external_vitest_namespaceObject.describe)("AgentConfigLoader", ()=>{
|
|
@@ -244,6 +244,43 @@ Markdown agent`;
|
|
|
244
244
|
(0, external_vitest_namespaceObject.expect)(agent).toBeDefined();
|
|
245
245
|
(0, external_vitest_namespaceObject.expect)(agent?.systemPrompt).toContain("[[wingman:prompt-refinement]]");
|
|
246
246
|
(0, external_vitest_namespaceObject.expect)(agent?.systemPrompt).toContain("/memories/agents/refiner-agent/instructions.md");
|
|
247
|
+
(0, external_vitest_namespaceObject.expect)(agent?.systemPrompt).toContain("overlay as secondary preference memory");
|
|
248
|
+
});
|
|
249
|
+
(0, external_vitest_namespaceObject.it)("should apply reasoningEffort when model supports it", async ()=>{
|
|
250
|
+
const agentDir = (0, external_node_path_namespaceObject.join)(TEST_CONFIG_DIR, "agents", "reasoning-agent");
|
|
251
|
+
(0, external_node_fs_namespaceObject.mkdirSync)(agentDir, {
|
|
252
|
+
recursive: true
|
|
253
|
+
});
|
|
254
|
+
const config = {
|
|
255
|
+
name: "reasoning-agent",
|
|
256
|
+
description: "Agent with reasoning effort",
|
|
257
|
+
systemPrompt: "You are a reasoner",
|
|
258
|
+
model: "openai:gpt-5.2-codex",
|
|
259
|
+
reasoningEffort: "high"
|
|
260
|
+
};
|
|
261
|
+
(0, external_node_fs_namespaceObject.writeFileSync)((0, external_node_path_namespaceObject.join)(agentDir, "agent.json"), JSON.stringify(config));
|
|
262
|
+
const loader = new agentLoader_cjs_namespaceObject.AgentLoader(TEST_CONFIG_DIR);
|
|
263
|
+
const agent = await loader.loadAgent("reasoning-agent");
|
|
264
|
+
const model = agent?.model;
|
|
265
|
+
(0, external_vitest_namespaceObject.expect)(model.reasoning?.effort).toBe("high");
|
|
266
|
+
});
|
|
267
|
+
(0, external_vitest_namespaceObject.it)("should normalize thinkingEffort alias to reasoningEffort", async ()=>{
|
|
268
|
+
const agentDir = (0, external_node_path_namespaceObject.join)(TEST_CONFIG_DIR, "agents", "legacy-thinking-agent");
|
|
269
|
+
(0, external_node_fs_namespaceObject.mkdirSync)(agentDir, {
|
|
270
|
+
recursive: true
|
|
271
|
+
});
|
|
272
|
+
const config = {
|
|
273
|
+
name: "legacy-thinking-agent",
|
|
274
|
+
description: "Agent with legacy thinking effort field",
|
|
275
|
+
systemPrompt: "You are a reasoner",
|
|
276
|
+
model: "openai:gpt-5.2-codex",
|
|
277
|
+
thinkingEffort: "medium"
|
|
278
|
+
};
|
|
279
|
+
(0, external_node_fs_namespaceObject.writeFileSync)((0, external_node_path_namespaceObject.join)(agentDir, "agent.json"), JSON.stringify(config));
|
|
280
|
+
const loader = new agentLoader_cjs_namespaceObject.AgentLoader(TEST_CONFIG_DIR);
|
|
281
|
+
const agent = await loader.loadAgent("legacy-thinking-agent");
|
|
282
|
+
const model = agent?.model;
|
|
283
|
+
(0, external_vitest_namespaceObject.expect)(model.reasoning?.effort).toBe("medium");
|
|
247
284
|
});
|
|
248
285
|
});
|
|
249
286
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
2
1
|
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
3
2
|
import { join } from "node:path";
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
4
4
|
import { AgentLoader } from "../config/agentLoader.js";
|
|
5
5
|
const TEST_CONFIG_DIR = ".wingman-test";
|
|
6
6
|
describe("AgentConfigLoader", ()=>{
|
|
@@ -242,6 +242,43 @@ Markdown agent`;
|
|
|
242
242
|
expect(agent).toBeDefined();
|
|
243
243
|
expect(agent?.systemPrompt).toContain("[[wingman:prompt-refinement]]");
|
|
244
244
|
expect(agent?.systemPrompt).toContain("/memories/agents/refiner-agent/instructions.md");
|
|
245
|
+
expect(agent?.systemPrompt).toContain("overlay as secondary preference memory");
|
|
246
|
+
});
|
|
247
|
+
it("should apply reasoningEffort when model supports it", async ()=>{
|
|
248
|
+
const agentDir = join(TEST_CONFIG_DIR, "agents", "reasoning-agent");
|
|
249
|
+
mkdirSync(agentDir, {
|
|
250
|
+
recursive: true
|
|
251
|
+
});
|
|
252
|
+
const config = {
|
|
253
|
+
name: "reasoning-agent",
|
|
254
|
+
description: "Agent with reasoning effort",
|
|
255
|
+
systemPrompt: "You are a reasoner",
|
|
256
|
+
model: "openai:gpt-5.2-codex",
|
|
257
|
+
reasoningEffort: "high"
|
|
258
|
+
};
|
|
259
|
+
writeFileSync(join(agentDir, "agent.json"), JSON.stringify(config));
|
|
260
|
+
const loader = new AgentLoader(TEST_CONFIG_DIR);
|
|
261
|
+
const agent = await loader.loadAgent("reasoning-agent");
|
|
262
|
+
const model = agent?.model;
|
|
263
|
+
expect(model.reasoning?.effort).toBe("high");
|
|
264
|
+
});
|
|
265
|
+
it("should normalize thinkingEffort alias to reasoningEffort", async ()=>{
|
|
266
|
+
const agentDir = join(TEST_CONFIG_DIR, "agents", "legacy-thinking-agent");
|
|
267
|
+
mkdirSync(agentDir, {
|
|
268
|
+
recursive: true
|
|
269
|
+
});
|
|
270
|
+
const config = {
|
|
271
|
+
name: "legacy-thinking-agent",
|
|
272
|
+
description: "Agent with legacy thinking effort field",
|
|
273
|
+
systemPrompt: "You are a reasoner",
|
|
274
|
+
model: "openai:gpt-5.2-codex",
|
|
275
|
+
thinkingEffort: "medium"
|
|
276
|
+
};
|
|
277
|
+
writeFileSync(join(agentDir, "agent.json"), JSON.stringify(config));
|
|
278
|
+
const loader = new AgentLoader(TEST_CONFIG_DIR);
|
|
279
|
+
const agent = await loader.loadAgent("legacy-thinking-agent");
|
|
280
|
+
const model = agent?.model;
|
|
281
|
+
expect(model.reasoning?.effort).toBe("medium");
|
|
245
282
|
});
|
|
246
283
|
});
|
|
247
284
|
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_exports__ = {};
|
|
3
|
+
const external_vitest_namespaceObject = require("vitest");
|
|
4
|
+
const background_terminal_cjs_namespaceObject = require("../tools/background_terminal.cjs");
|
|
5
|
+
const terminal_session_manager_cjs_namespaceObject = require("../tools/terminal_session_manager.cjs");
|
|
6
|
+
(0, external_vitest_namespaceObject.describe)("background terminal tools", ()=>{
|
|
7
|
+
(0, external_vitest_namespaceObject.it)("describes long-running tasks in the tool description", ()=>{
|
|
8
|
+
const manager = new terminal_session_manager_cjs_namespaceObject.TerminalSessionManager();
|
|
9
|
+
try {
|
|
10
|
+
const tool = (0, background_terminal_cjs_namespaceObject.createBackgroundTerminalTool)({
|
|
11
|
+
workspace: process.cwd(),
|
|
12
|
+
ownerId: "description-owner",
|
|
13
|
+
sessionManager: manager
|
|
14
|
+
});
|
|
15
|
+
const description = String(tool.description);
|
|
16
|
+
(0, external_vitest_namespaceObject.expect)(description).toContain("may not exit on their own");
|
|
17
|
+
(0, external_vitest_namespaceObject.expect)(description).toContain("web servers");
|
|
18
|
+
(0, external_vitest_namespaceObject.expect)(description).toContain("test watchers");
|
|
19
|
+
} finally{
|
|
20
|
+
manager.dispose();
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
(0, external_vitest_namespaceObject.it)("rejects blocked commands", async ()=>{
|
|
24
|
+
const manager = new terminal_session_manager_cjs_namespaceObject.TerminalSessionManager();
|
|
25
|
+
try {
|
|
26
|
+
const tool = (0, background_terminal_cjs_namespaceObject.createBackgroundTerminalTool)({
|
|
27
|
+
workspace: process.cwd(),
|
|
28
|
+
ownerId: "test-owner",
|
|
29
|
+
sessionManager: manager,
|
|
30
|
+
blockedCommands: [
|
|
31
|
+
"rm"
|
|
32
|
+
]
|
|
33
|
+
});
|
|
34
|
+
const result = await tool.invoke({
|
|
35
|
+
command: "rm -rf ./tmp"
|
|
36
|
+
});
|
|
37
|
+
(0, external_vitest_namespaceObject.expect)(result.error).toContain("rejected");
|
|
38
|
+
} finally{
|
|
39
|
+
manager.dispose();
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
(0, external_vitest_namespaceObject.it)("supports start and write/poll flow", async ()=>{
|
|
43
|
+
const manager = new terminal_session_manager_cjs_namespaceObject.TerminalSessionManager();
|
|
44
|
+
try {
|
|
45
|
+
const tool = (0, background_terminal_cjs_namespaceObject.createBackgroundTerminalTool)({
|
|
46
|
+
workspace: process.cwd(),
|
|
47
|
+
ownerId: "owner-flow",
|
|
48
|
+
sessionManager: manager
|
|
49
|
+
});
|
|
50
|
+
const started = await tool.invoke({
|
|
51
|
+
command: "cat",
|
|
52
|
+
wait_ms: 10
|
|
53
|
+
});
|
|
54
|
+
(0, external_vitest_namespaceObject.expect)(typeof started.session_id).toBe("string");
|
|
55
|
+
const sessionId = String(started.session_id);
|
|
56
|
+
const writeResult = await tool.invoke({
|
|
57
|
+
session_id: sessionId,
|
|
58
|
+
chars: "hello\n",
|
|
59
|
+
wait_ms: 1000
|
|
60
|
+
});
|
|
61
|
+
(0, external_vitest_namespaceObject.expect)(String(writeResult.output || "")).toContain("hello");
|
|
62
|
+
} finally{
|
|
63
|
+
manager.dispose();
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
68
|
+
Object.defineProperty(exports, '__esModule', {
|
|
69
|
+
value: true
|
|
70
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { createBackgroundTerminalTool } from "../tools/background_terminal.js";
|
|
3
|
+
import { TerminalSessionManager } from "../tools/terminal_session_manager.js";
|
|
4
|
+
describe("background terminal tools", ()=>{
|
|
5
|
+
it("describes long-running tasks in the tool description", ()=>{
|
|
6
|
+
const manager = new TerminalSessionManager();
|
|
7
|
+
try {
|
|
8
|
+
const tool = createBackgroundTerminalTool({
|
|
9
|
+
workspace: process.cwd(),
|
|
10
|
+
ownerId: "description-owner",
|
|
11
|
+
sessionManager: manager
|
|
12
|
+
});
|
|
13
|
+
const description = String(tool.description);
|
|
14
|
+
expect(description).toContain("may not exit on their own");
|
|
15
|
+
expect(description).toContain("web servers");
|
|
16
|
+
expect(description).toContain("test watchers");
|
|
17
|
+
} finally{
|
|
18
|
+
manager.dispose();
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
it("rejects blocked commands", async ()=>{
|
|
22
|
+
const manager = new TerminalSessionManager();
|
|
23
|
+
try {
|
|
24
|
+
const tool = createBackgroundTerminalTool({
|
|
25
|
+
workspace: process.cwd(),
|
|
26
|
+
ownerId: "test-owner",
|
|
27
|
+
sessionManager: manager,
|
|
28
|
+
blockedCommands: [
|
|
29
|
+
"rm"
|
|
30
|
+
]
|
|
31
|
+
});
|
|
32
|
+
const result = await tool.invoke({
|
|
33
|
+
command: "rm -rf ./tmp"
|
|
34
|
+
});
|
|
35
|
+
expect(result.error).toContain("rejected");
|
|
36
|
+
} finally{
|
|
37
|
+
manager.dispose();
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
it("supports start and write/poll flow", async ()=>{
|
|
41
|
+
const manager = new TerminalSessionManager();
|
|
42
|
+
try {
|
|
43
|
+
const tool = createBackgroundTerminalTool({
|
|
44
|
+
workspace: process.cwd(),
|
|
45
|
+
ownerId: "owner-flow",
|
|
46
|
+
sessionManager: manager
|
|
47
|
+
});
|
|
48
|
+
const started = await tool.invoke({
|
|
49
|
+
command: "cat",
|
|
50
|
+
wait_ms: 10
|
|
51
|
+
});
|
|
52
|
+
expect(typeof started.session_id).toBe("string");
|
|
53
|
+
const sessionId = String(started.session_id);
|
|
54
|
+
const writeResult = await tool.invoke({
|
|
55
|
+
session_id: sessionId,
|
|
56
|
+
chars: "hello\n",
|
|
57
|
+
wait_ms: 1000
|
|
58
|
+
});
|
|
59
|
+
expect(String(writeResult.output || "")).toContain("hello");
|
|
60
|
+
} finally{
|
|
61
|
+
manager.dispose();
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_exports__ = {};
|
|
3
|
+
const external_vitest_namespaceObject = require("vitest");
|
|
4
|
+
const command_execute_cjs_namespaceObject = require("../tools/command_execute.cjs");
|
|
5
|
+
(0, external_vitest_namespaceObject.describe)("command_execute tool", ()=>{
|
|
6
|
+
(0, external_vitest_namespaceObject.it)("rejects blocked commands", async ()=>{
|
|
7
|
+
const tool = (0, command_execute_cjs_namespaceObject.createCommandExecuteTool)(process.cwd(), void 0, [
|
|
8
|
+
"rm"
|
|
9
|
+
]);
|
|
10
|
+
const result = await tool.invoke({
|
|
11
|
+
command: "rm -rf ./tmp"
|
|
12
|
+
});
|
|
13
|
+
(0, external_vitest_namespaceObject.expect)(String(result)).toContain("rejected");
|
|
14
|
+
});
|
|
15
|
+
(0, external_vitest_namespaceObject.it)("truncates oversized output to avoid oversized tool payloads", async ()=>{
|
|
16
|
+
const tool = (0, command_execute_cjs_namespaceObject.createCommandExecuteTool)(process.cwd(), void 0, [], true, 30000, 120);
|
|
17
|
+
const result = await tool.invoke({
|
|
18
|
+
command: "node -e \"process.stdout.write('x'.repeat(400))\""
|
|
19
|
+
});
|
|
20
|
+
const output = String(result);
|
|
21
|
+
(0, external_vitest_namespaceObject.expect)(output).toContain("completed successfully");
|
|
22
|
+
(0, external_vitest_namespaceObject.expect)(output).toContain("output truncated");
|
|
23
|
+
(0, external_vitest_namespaceObject.expect)(output.length).toBeLessThan(800);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
27
|
+
Object.defineProperty(exports, '__esModule', {
|
|
28
|
+
value: true
|
|
29
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { createCommandExecuteTool } from "../tools/command_execute.js";
|
|
3
|
+
describe("command_execute tool", ()=>{
|
|
4
|
+
it("rejects blocked commands", async ()=>{
|
|
5
|
+
const tool = createCommandExecuteTool(process.cwd(), void 0, [
|
|
6
|
+
"rm"
|
|
7
|
+
]);
|
|
8
|
+
const result = await tool.invoke({
|
|
9
|
+
command: "rm -rf ./tmp"
|
|
10
|
+
});
|
|
11
|
+
expect(String(result)).toContain("rejected");
|
|
12
|
+
});
|
|
13
|
+
it("truncates oversized output to avoid oversized tool payloads", async ()=>{
|
|
14
|
+
const tool = createCommandExecuteTool(process.cwd(), void 0, [], true, 30000, 120);
|
|
15
|
+
const result = await tool.invoke({
|
|
16
|
+
command: "node -e \"process.stdout.write('x'.repeat(400))\""
|
|
17
|
+
});
|
|
18
|
+
const output = String(result);
|
|
19
|
+
expect(output).toContain("completed successfully");
|
|
20
|
+
expect(output).toContain("output truncated");
|
|
21
|
+
expect(output.length).toBeLessThan(800);
|
|
22
|
+
});
|
|
23
|
+
});
|