@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.
Files changed (160) hide show
  1. package/.wingman/agents/README.md +7 -1
  2. package/.wingman/agents/coding/agent.md +299 -201
  3. package/.wingman/agents/coding-v2/agent.md +127 -0
  4. package/.wingman/agents/coding-v2/implementor.md +89 -0
  5. package/.wingman/agents/main/agent.md +4 -0
  6. package/README.md +1 -0
  7. package/dist/agent/config/agentConfig.cjs +31 -17
  8. package/dist/agent/config/agentConfig.d.ts +23 -1
  9. package/dist/agent/config/agentConfig.js +30 -19
  10. package/dist/agent/config/agentLoader.cjs +26 -8
  11. package/dist/agent/config/agentLoader.d.ts +4 -2
  12. package/dist/agent/config/agentLoader.js +26 -8
  13. package/dist/agent/config/modelFactory.cjs +95 -25
  14. package/dist/agent/config/modelFactory.d.ts +13 -1
  15. package/dist/agent/config/modelFactory.js +95 -25
  16. package/dist/agent/config/toolRegistry.cjs +19 -6
  17. package/dist/agent/config/toolRegistry.d.ts +5 -2
  18. package/dist/agent/config/toolRegistry.js +19 -6
  19. package/dist/agent/middleware/hooks/types.cjs +13 -13
  20. package/dist/agent/middleware/hooks/types.d.ts +1 -1
  21. package/dist/agent/middleware/hooks/types.js +14 -14
  22. package/dist/agent/tests/agentConfig.test.cjs +22 -2
  23. package/dist/agent/tests/agentConfig.test.js +22 -2
  24. package/dist/agent/tests/agentLoader.test.cjs +38 -1
  25. package/dist/agent/tests/agentLoader.test.js +38 -1
  26. package/dist/agent/tests/backgroundTerminal.test.cjs +70 -0
  27. package/dist/agent/tests/backgroundTerminal.test.d.ts +1 -0
  28. package/dist/agent/tests/backgroundTerminal.test.js +64 -0
  29. package/dist/agent/tests/commandExecuteTool.test.cjs +29 -0
  30. package/dist/agent/tests/commandExecuteTool.test.d.ts +1 -0
  31. package/dist/agent/tests/commandExecuteTool.test.js +23 -0
  32. package/dist/agent/tests/modelFactory.test.cjs +47 -5
  33. package/dist/agent/tests/modelFactory.test.js +47 -5
  34. package/dist/agent/tests/terminalSessionManager.test.cjs +121 -0
  35. package/dist/agent/tests/terminalSessionManager.test.d.ts +1 -0
  36. package/dist/agent/tests/terminalSessionManager.test.js +115 -0
  37. package/dist/agent/tests/toolRegistry.test.cjs +14 -2
  38. package/dist/agent/tests/toolRegistry.test.js +14 -2
  39. package/dist/agent/tools/background_terminal.cjs +128 -0
  40. package/dist/agent/tools/background_terminal.d.ts +41 -0
  41. package/dist/agent/tools/background_terminal.js +94 -0
  42. package/dist/agent/tools/code_search.cjs +6 -6
  43. package/dist/agent/tools/code_search.d.ts +1 -1
  44. package/dist/agent/tools/code_search.js +7 -7
  45. package/dist/agent/tools/command_execute.cjs +22 -7
  46. package/dist/agent/tools/command_execute.d.ts +3 -2
  47. package/dist/agent/tools/command_execute.js +23 -8
  48. package/dist/agent/tools/git_status.cjs +3 -3
  49. package/dist/agent/tools/git_status.d.ts +1 -1
  50. package/dist/agent/tools/git_status.js +4 -4
  51. package/dist/agent/tools/internet_search.cjs +6 -6
  52. package/dist/agent/tools/internet_search.d.ts +1 -1
  53. package/dist/agent/tools/internet_search.js +7 -7
  54. package/dist/agent/tools/terminal_session_manager.cjs +321 -0
  55. package/dist/agent/tools/terminal_session_manager.d.ts +77 -0
  56. package/dist/agent/tools/terminal_session_manager.js +284 -0
  57. package/dist/agent/tools/think.cjs +4 -4
  58. package/dist/agent/tools/think.d.ts +1 -1
  59. package/dist/agent/tools/think.js +5 -5
  60. package/dist/agent/tools/ui_registry.cjs +13 -13
  61. package/dist/agent/tools/ui_registry.d.ts +4 -4
  62. package/dist/agent/tools/ui_registry.js +14 -14
  63. package/dist/agent/tools/web_crawler.cjs +4 -4
  64. package/dist/agent/tools/web_crawler.d.ts +1 -1
  65. package/dist/agent/tools/web_crawler.js +5 -5
  66. package/dist/agent/utils.cjs +2 -1
  67. package/dist/agent/utils.js +2 -1
  68. package/dist/cli/commands/init.cjs +7 -6
  69. package/dist/cli/commands/init.js +7 -6
  70. package/dist/cli/commands/provider.cjs +17 -3
  71. package/dist/cli/commands/provider.js +17 -3
  72. package/dist/cli/config/loader.cjs +27 -0
  73. package/dist/cli/config/loader.js +27 -0
  74. package/dist/cli/config/schema.cjs +146 -68
  75. package/dist/cli/config/schema.d.ts +89 -1
  76. package/dist/cli/config/schema.js +134 -68
  77. package/dist/cli/core/agentInvoker.cjs +344 -17
  78. package/dist/cli/core/agentInvoker.d.ts +63 -3
  79. package/dist/cli/core/agentInvoker.js +303 -12
  80. package/dist/cli/core/sessionManager.cjs +32 -5
  81. package/dist/cli/core/sessionManager.js +32 -5
  82. package/dist/cli/core/streamParser.cjs +15 -0
  83. package/dist/cli/core/streamParser.js +15 -0
  84. package/dist/cli/index.cjs +6 -5
  85. package/dist/cli/index.js +6 -5
  86. package/dist/cli/types.d.ts +32 -0
  87. package/dist/cli/ui/toolDisplayHelpers.cjs +2 -0
  88. package/dist/cli/ui/toolDisplayHelpers.js +2 -0
  89. package/dist/gateway/hooks/registry.cjs +2 -1
  90. package/dist/gateway/hooks/registry.d.ts +1 -1
  91. package/dist/gateway/hooks/registry.js +2 -1
  92. package/dist/gateway/hooks/types.cjs +11 -11
  93. package/dist/gateway/hooks/types.d.ts +1 -1
  94. package/dist/gateway/hooks/types.js +12 -12
  95. package/dist/gateway/http/agents.cjs +67 -4
  96. package/dist/gateway/http/agents.js +67 -4
  97. package/dist/gateway/http/sessions.cjs +7 -7
  98. package/dist/gateway/http/sessions.js +7 -7
  99. package/dist/gateway/http/types.d.ts +5 -3
  100. package/dist/gateway/http/webhooks.cjs +6 -5
  101. package/dist/gateway/http/webhooks.js +6 -5
  102. package/dist/gateway/server.cjs +198 -41
  103. package/dist/gateway/server.d.ts +9 -1
  104. package/dist/gateway/server.js +198 -41
  105. package/dist/gateway/types.d.ts +1 -0
  106. package/dist/gateway/validation.cjs +39 -39
  107. package/dist/gateway/validation.d.ts +1 -1
  108. package/dist/gateway/validation.js +40 -40
  109. package/dist/providers/codex.cjs +167 -0
  110. package/dist/providers/codex.d.ts +15 -0
  111. package/dist/providers/codex.js +127 -0
  112. package/dist/providers/credentials.cjs +8 -0
  113. package/dist/providers/credentials.js +8 -0
  114. package/dist/providers/registry.cjs +11 -0
  115. package/dist/providers/registry.d.ts +1 -1
  116. package/dist/providers/registry.js +11 -0
  117. package/dist/tests/additionalMessageMiddleware.test.cjs +3 -0
  118. package/dist/tests/additionalMessageMiddleware.test.js +3 -0
  119. package/dist/tests/agentInvokerSummarization.test.cjs +455 -0
  120. package/dist/tests/agentInvokerSummarization.test.d.ts +1 -0
  121. package/dist/tests/agentInvokerSummarization.test.js +449 -0
  122. package/dist/tests/agents-api.test.cjs +45 -5
  123. package/dist/tests/agents-api.test.js +45 -5
  124. package/dist/tests/cli-config-loader.test.cjs +88 -0
  125. package/dist/tests/cli-config-loader.test.js +88 -0
  126. package/dist/tests/cli-init.test.cjs +27 -3
  127. package/dist/tests/cli-init.test.js +27 -3
  128. package/dist/tests/codex-credentials-precedence.test.cjs +94 -0
  129. package/dist/tests/codex-credentials-precedence.test.d.ts +1 -0
  130. package/dist/tests/codex-credentials-precedence.test.js +88 -0
  131. package/dist/tests/codex-provider.test.cjs +210 -0
  132. package/dist/tests/codex-provider.test.d.ts +1 -0
  133. package/dist/tests/codex-provider.test.js +204 -0
  134. package/dist/tests/gateway.test.cjs +115 -8
  135. package/dist/tests/gateway.test.js +115 -8
  136. package/dist/tests/provider-command-codex.test.cjs +57 -0
  137. package/dist/tests/provider-command-codex.test.d.ts +1 -0
  138. package/dist/tests/provider-command-codex.test.js +51 -0
  139. package/dist/tests/sessionStateMessages.test.cjs +38 -0
  140. package/dist/tests/sessionStateMessages.test.js +38 -0
  141. package/dist/tests/toolDisplayHelpers.test.cjs +3 -0
  142. package/dist/tests/toolDisplayHelpers.test.js +3 -0
  143. package/dist/tools/mcp-finance.cjs +48 -48
  144. package/dist/tools/mcp-finance.js +48 -48
  145. package/dist/types/mcp.cjs +15 -15
  146. package/dist/types/mcp.d.ts +1 -1
  147. package/dist/types/mcp.js +16 -16
  148. package/dist/types/voice.cjs +21 -21
  149. package/dist/types/voice.d.ts +1 -1
  150. package/dist/types/voice.js +22 -22
  151. package/dist/webui/assets/index-DVWQluit.css +11 -0
  152. package/dist/webui/assets/index-Dlyzwalc.js +270 -0
  153. package/dist/webui/favicon-32x32.png +0 -0
  154. package/dist/webui/favicon-64x64.png +0 -0
  155. package/dist/webui/favicon.webp +0 -0
  156. package/dist/webui/index.html +4 -2
  157. package/package.json +13 -12
  158. package/.wingman/agents/coding/implementor.md +0 -79
  159. package/dist/webui/assets/index-CPhfGPHc.js +0 -182
  160. package/dist/webui/assets/index-DDsMIOTX.css +0 -11
@@ -1,11 +1,13 @@
1
- import { createInternetSearchTool } from "../tools/internet_search.js";
2
- import { webCrawler } from "../tools/web_crawler.js";
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 { createLogger } from "../../logger.js";
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.z.object({
34
- type: external_zod_namespaceObject.z.literal("command").describe("Type of hook - currently only 'command' is supported"),
35
- command: external_zod_namespaceObject.z.string().min(1).describe("Shell command to execute"),
36
- timeout: external_zod_namespaceObject.z.number().positive().optional().default(60).describe("Timeout in seconds (default: 60)")
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.z.object({
39
- matcher: external_zod_namespaceObject.z.string().optional().describe("Pattern to match tool names (pipe-separated, wildcard, or regex)"),
40
- hooks: external_zod_namespaceObject.z.array(HookSchema).min(1).describe("Array of hooks to execute when pattern matches")
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.z.object({
43
- hooks: external_zod_namespaceObject.z.array(HookSchema).min(1).describe("Array of hooks to execute when agent stops")
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.z.object({
46
- PreToolUse: external_zod_namespaceObject.z.array(HookMatcherSchema).optional().describe("Hooks that fire before tool execution (can block)"),
47
- PostToolUse: external_zod_namespaceObject.z.array(HookMatcherSchema).optional().describe("Hooks that fire after tool completes (non-blocking)"),
48
- Stop: external_zod_namespaceObject.z.array(StopHookSchema).optional().describe("Hooks that fire when agent completes (non-blocking)")
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;
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Validation schemas for hook configurations and runtime execution context
5
5
  */
6
- import { z } from "zod";
6
+ import * as z from "zod";
7
7
  import type { ToolCallRequest, ToolMessage } from "langchain";
8
8
  /**
9
9
  * Zod schema for individual hook configuration
@@ -1,19 +1,19 @@
1
- import { z } from "zod";
2
- const HookSchema = z.object({
3
- type: z.literal("command").describe("Type of hook - currently only 'command' is supported"),
4
- command: z.string().min(1).describe("Shell command to execute"),
5
- timeout: z.number().positive().optional().default(60).describe("Timeout in seconds (default: 60)")
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 = z.object({
8
- matcher: z.string().optional().describe("Pattern to match tool names (pipe-separated, wildcard, or regex)"),
9
- hooks: z.array(HookSchema).min(1).describe("Array of hooks to execute when pattern matches")
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 = z.object({
12
- hooks: z.array(HookSchema).min(1).describe("Array of hooks to execute when agent stops")
11
+ const StopHookSchema = object({
12
+ hooks: array(HookSchema).min(1).describe("Array of hooks to execute when agent stops")
13
13
  });
14
- const HooksConfigSchema = z.object({
15
- PreToolUse: z.array(HookMatcherSchema).optional().describe("Hooks that fire before tool execution (can block)"),
16
- PostToolUse: z.array(HookMatcherSchema).optional().describe("Hooks that fire after tool completes (non-blocking)"),
17
- Stop: z.array(StopHookSchema).optional().describe("Hooks that fire when agent completes (non-blocking)")
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) (0, external_vitest_namespaceObject.expect)(result.data.subAgents?.[0].model).toBe("openai:gpt-4o");
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) expect(result.data.subAgents?.[0].model).toBe("openai:gpt-4o");
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
+ });