@wingman-ai/gateway 0.2.3 → 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 (124) hide show
  1. package/.wingman/agents/README.md +7 -1
  2. package/.wingman/agents/coding/agent.md +295 -202
  3. package/.wingman/agents/coding-v2/agent.md +127 -0
  4. package/.wingman/agents/coding-v2/implementor.md +89 -0
  5. package/dist/agent/config/agentConfig.cjs +31 -17
  6. package/dist/agent/config/agentConfig.d.ts +23 -1
  7. package/dist/agent/config/agentConfig.js +30 -19
  8. package/dist/agent/config/agentLoader.cjs +26 -8
  9. package/dist/agent/config/agentLoader.d.ts +4 -2
  10. package/dist/agent/config/agentLoader.js +26 -8
  11. package/dist/agent/config/modelFactory.cjs +77 -27
  12. package/dist/agent/config/modelFactory.d.ts +11 -1
  13. package/dist/agent/config/modelFactory.js +77 -27
  14. package/dist/agent/config/toolRegistry.cjs +19 -6
  15. package/dist/agent/config/toolRegistry.d.ts +5 -2
  16. package/dist/agent/config/toolRegistry.js +19 -6
  17. package/dist/agent/middleware/hooks/types.cjs +13 -13
  18. package/dist/agent/middleware/hooks/types.d.ts +1 -1
  19. package/dist/agent/middleware/hooks/types.js +14 -14
  20. package/dist/agent/tests/agentConfig.test.cjs +22 -2
  21. package/dist/agent/tests/agentConfig.test.js +22 -2
  22. package/dist/agent/tests/agentLoader.test.cjs +38 -1
  23. package/dist/agent/tests/agentLoader.test.js +38 -1
  24. package/dist/agent/tests/backgroundTerminal.test.cjs +70 -0
  25. package/dist/agent/tests/backgroundTerminal.test.d.ts +1 -0
  26. package/dist/agent/tests/backgroundTerminal.test.js +64 -0
  27. package/dist/agent/tests/commandExecuteTool.test.cjs +29 -0
  28. package/dist/agent/tests/commandExecuteTool.test.d.ts +1 -0
  29. package/dist/agent/tests/commandExecuteTool.test.js +23 -0
  30. package/dist/agent/tests/modelFactory.test.cjs +35 -0
  31. package/dist/agent/tests/modelFactory.test.js +35 -0
  32. package/dist/agent/tests/terminalSessionManager.test.cjs +121 -0
  33. package/dist/agent/tests/terminalSessionManager.test.d.ts +1 -0
  34. package/dist/agent/tests/terminalSessionManager.test.js +115 -0
  35. package/dist/agent/tests/toolRegistry.test.cjs +14 -2
  36. package/dist/agent/tests/toolRegistry.test.js +14 -2
  37. package/dist/agent/tools/background_terminal.cjs +128 -0
  38. package/dist/agent/tools/background_terminal.d.ts +41 -0
  39. package/dist/agent/tools/background_terminal.js +94 -0
  40. package/dist/agent/tools/code_search.cjs +6 -6
  41. package/dist/agent/tools/code_search.d.ts +1 -1
  42. package/dist/agent/tools/code_search.js +7 -7
  43. package/dist/agent/tools/command_execute.cjs +22 -7
  44. package/dist/agent/tools/command_execute.d.ts +3 -2
  45. package/dist/agent/tools/command_execute.js +23 -8
  46. package/dist/agent/tools/git_status.cjs +3 -3
  47. package/dist/agent/tools/git_status.d.ts +1 -1
  48. package/dist/agent/tools/git_status.js +4 -4
  49. package/dist/agent/tools/internet_search.cjs +6 -6
  50. package/dist/agent/tools/internet_search.d.ts +1 -1
  51. package/dist/agent/tools/internet_search.js +7 -7
  52. package/dist/agent/tools/terminal_session_manager.cjs +321 -0
  53. package/dist/agent/tools/terminal_session_manager.d.ts +77 -0
  54. package/dist/agent/tools/terminal_session_manager.js +284 -0
  55. package/dist/agent/tools/think.cjs +4 -4
  56. package/dist/agent/tools/think.d.ts +1 -1
  57. package/dist/agent/tools/think.js +5 -5
  58. package/dist/agent/tools/ui_registry.cjs +13 -13
  59. package/dist/agent/tools/ui_registry.d.ts +4 -4
  60. package/dist/agent/tools/ui_registry.js +14 -14
  61. package/dist/agent/tools/web_crawler.cjs +4 -4
  62. package/dist/agent/tools/web_crawler.d.ts +1 -1
  63. package/dist/agent/tools/web_crawler.js +5 -5
  64. package/dist/agent/utils.cjs +2 -1
  65. package/dist/agent/utils.js +2 -1
  66. package/dist/cli/config/schema.cjs +89 -89
  67. package/dist/cli/config/schema.d.ts +1 -1
  68. package/dist/cli/config/schema.js +90 -90
  69. package/dist/cli/core/agentInvoker.cjs +170 -21
  70. package/dist/cli/core/agentInvoker.d.ts +25 -4
  71. package/dist/cli/core/agentInvoker.js +157 -20
  72. package/dist/cli/core/streamParser.cjs +15 -0
  73. package/dist/cli/core/streamParser.js +15 -0
  74. package/dist/cli/ui/toolDisplayHelpers.cjs +2 -0
  75. package/dist/cli/ui/toolDisplayHelpers.js +2 -0
  76. package/dist/gateway/hooks/registry.cjs +2 -1
  77. package/dist/gateway/hooks/registry.d.ts +1 -1
  78. package/dist/gateway/hooks/registry.js +2 -1
  79. package/dist/gateway/hooks/types.cjs +11 -11
  80. package/dist/gateway/hooks/types.d.ts +1 -1
  81. package/dist/gateway/hooks/types.js +12 -12
  82. package/dist/gateway/http/agents.cjs +67 -4
  83. package/dist/gateway/http/agents.js +67 -4
  84. package/dist/gateway/http/types.d.ts +5 -3
  85. package/dist/gateway/http/webhooks.cjs +6 -5
  86. package/dist/gateway/http/webhooks.js +6 -5
  87. package/dist/gateway/server.cjs +7 -0
  88. package/dist/gateway/server.d.ts +1 -0
  89. package/dist/gateway/server.js +7 -0
  90. package/dist/gateway/validation.cjs +39 -39
  91. package/dist/gateway/validation.d.ts +1 -1
  92. package/dist/gateway/validation.js +40 -40
  93. package/dist/tests/additionalMessageMiddleware.test.cjs +3 -0
  94. package/dist/tests/additionalMessageMiddleware.test.js +3 -0
  95. package/dist/tests/agentInvokerSummarization.test.cjs +171 -12
  96. package/dist/tests/agentInvokerSummarization.test.js +172 -13
  97. package/dist/tests/agents-api.test.cjs +45 -5
  98. package/dist/tests/agents-api.test.js +45 -5
  99. package/dist/tests/cli-init.test.cjs +27 -3
  100. package/dist/tests/cli-init.test.js +27 -3
  101. package/dist/tests/codex-provider.test.cjs +24 -0
  102. package/dist/tests/codex-provider.test.js +24 -0
  103. package/dist/tests/gateway.test.cjs +7 -7
  104. package/dist/tests/gateway.test.js +7 -7
  105. package/dist/tests/toolDisplayHelpers.test.cjs +3 -0
  106. package/dist/tests/toolDisplayHelpers.test.js +3 -0
  107. package/dist/tools/mcp-finance.cjs +48 -48
  108. package/dist/tools/mcp-finance.js +48 -48
  109. package/dist/types/mcp.cjs +15 -15
  110. package/dist/types/mcp.d.ts +1 -1
  111. package/dist/types/mcp.js +16 -16
  112. package/dist/types/voice.cjs +21 -21
  113. package/dist/types/voice.d.ts +1 -1
  114. package/dist/types/voice.js +22 -22
  115. package/dist/webui/assets/index-DVWQluit.css +11 -0
  116. package/dist/webui/assets/index-Dlyzwalc.js +270 -0
  117. package/dist/webui/favicon-32x32.png +0 -0
  118. package/dist/webui/favicon-64x64.png +0 -0
  119. package/dist/webui/favicon.webp +0 -0
  120. package/dist/webui/index.html +4 -2
  121. package/package.json +13 -12
  122. package/.wingman/agents/coding/implementor.md +0 -103
  123. package/dist/webui/assets/index-BVMavpud.css +0 -11
  124. package/dist/webui/assets/index-DCB2aVVf.js +0 -182
@@ -1,10 +1,10 @@
1
1
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
2
2
  import { isAbsolute, join } from "node:path";
3
3
  import { load } from "js-yaml";
4
+ import { createLogger } from "../../logger.js";
4
5
  import { WingmanDirectory, validateAgentConfig } from "./agentConfig.js";
5
- import { UI_TOOL_NAMES, createTools } from "./toolRegistry.js";
6
6
  import { ModelFactory } from "./modelFactory.js";
7
- import { createLogger } from "../../logger.js";
7
+ import { 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,
@@ -31,6 +31,7 @@ const buildPromptRefinementInstructions = (instructionsPath)=>[
31
31
  "Prompt Refinement:",
32
32
  `- Maintain a durable overlay at ${instructionsPath} for stable preferences and corrections.`,
33
33
  "- Read it at the start of each session and follow it in addition to this system prompt.",
34
+ "- Treat that overlay as secondary preference memory; if it conflicts with role, safety, or execution rules in this system prompt, follow this system prompt.",
34
35
  '- Only update it when the user gives explicit, lasting feedback (e.g., "always", "never", "prefer").',
35
36
  "- Keep entries short, stable, and avoid task-specific details.",
36
37
  "- If the file doesn't exist, create it with a short header and bullet list."
@@ -98,12 +99,18 @@ class AgentLoader {
98
99
  }
99
100
  }
100
101
  normalizeAgentConfig(config) {
102
+ const normalizeReasoningEffort = (target)=>{
103
+ if (void 0 === target.reasoningEffort && void 0 !== target.thinkingEffort) target.reasoningEffort = target.thinkingEffort;
104
+ if ("thinkingEffort" in target) delete target.thinkingEffort;
105
+ };
106
+ normalizeReasoningEffort(config);
101
107
  if (config.subagents && !config.subAgents) {
102
108
  config.subAgents = config.subagents;
103
109
  delete config.subagents;
104
110
  }
105
- if (Array.isArray(config.subAgents)) {
106
- for (const subagent of config.subAgents)if (subagent?.subagents && !subagent.subAgents) {
111
+ if (Array.isArray(config.subAgents)) for (const subagent of config.subAgents){
112
+ normalizeReasoningEffort(subagent);
113
+ if (subagent?.subagents && !subagent.subAgents) {
107
114
  subagent.subAgents = subagent.subagents;
108
115
  delete subagent.subagents;
109
116
  }
@@ -196,7 +203,8 @@ class AgentLoader {
196
203
  searchConfig: this.wingmanConfig?.search,
197
204
  mcpConfigs,
198
205
  skillsDirectory,
199
- dynamicUiEnabled
206
+ dynamicUiEnabled,
207
+ ...this.runtimeToolOptions
200
208
  };
201
209
  };
202
210
  if (config.tools && config.tools.length > 0) agent.tools = await createTools(config.tools, buildToolOptions(config));
@@ -212,12 +220,16 @@ class AgentLoader {
212
220
  if (config.mcp) agent.mcpConfig = config.mcp;
213
221
  if (config.mcpUseGlobal) agent.mcpUseGlobal = true;
214
222
  if (config.model) try {
215
- agent.model = ModelFactory.createModel(config.model);
223
+ agent.model = ModelFactory.createModel(config.model, {
224
+ reasoningEffort: config.reasoningEffort,
225
+ ownerLabel: `Agent "${config.name}"`
226
+ });
216
227
  logger.info(`Agent "${config.name}" using model: ${config.model}`);
217
228
  } catch (error) {
218
229
  logger.error(`Failed to create model for agent "${config.name}": ${error}`);
219
230
  logger.info(`Agent "${config.name}" will use default model`);
220
231
  }
232
+ else if (config.reasoningEffort) logger.warn(`Agent "${config.name}" set reasoningEffort="${config.reasoningEffort}" but has no model override. Ignoring.`);
221
233
  if (config.subAgents) {
222
234
  const subagents = [];
223
235
  for (const subagent of config.subAgents){
@@ -241,26 +253,32 @@ class AgentLoader {
241
253
  ];
242
254
  } else sub.tools = subUiTools;
243
255
  if (subagent.model) try {
244
- sub.model = ModelFactory.createModel(subagent.model);
256
+ sub.model = ModelFactory.createModel(subagent.model, {
257
+ reasoningEffort: subagent.reasoningEffort,
258
+ ownerLabel: `Subagent "${subagent.name}"`
259
+ });
245
260
  logger.info(`Subagent "${subagent.name}" using model: ${subagent.model}`);
246
261
  } catch (error) {
247
262
  logger.error(`Failed to create model for subagent "${subagent.name}": ${error}`);
248
263
  }
264
+ else if (subagent.reasoningEffort) logger.warn(`Subagent "${subagent.name}" set reasoningEffort="${subagent.reasoningEffort}" but has no model override. Ignoring.`);
249
265
  subagents.push(sub);
250
266
  }
251
267
  agent.subagents = subagents;
252
268
  }
253
269
  return agent;
254
270
  }
255
- constructor(configDir = WingmanDirectory, workspace = process.cwd(), wingmanConfig, executionWorkspace = workspace){
271
+ constructor(configDir = WingmanDirectory, workspace = process.cwd(), wingmanConfig, executionWorkspace = workspace, runtimeToolOptions = {}){
256
272
  _define_property(this, "configDir", void 0);
257
273
  _define_property(this, "workspace", void 0);
258
274
  _define_property(this, "wingmanConfig", void 0);
259
275
  _define_property(this, "executionWorkspace", void 0);
276
+ _define_property(this, "runtimeToolOptions", void 0);
260
277
  this.configDir = configDir;
261
278
  this.workspace = workspace;
262
279
  this.wingmanConfig = wingmanConfig;
263
280
  this.executionWorkspace = executionWorkspace;
281
+ this.runtimeToolOptions = runtimeToolOptions;
264
282
  }
265
283
  }
266
284
  export { AgentLoader };
@@ -35,8 +35,16 @@ const credentials_cjs_namespaceObject = require("../../providers/credentials.cjs
35
35
  const registry_cjs_namespaceObject = require("../../providers/registry.cjs");
36
36
  const external_logger_cjs_namespaceObject = require("../../logger.cjs");
37
37
  const logger = (0, external_logger_cjs_namespaceObject.createLogger)();
38
+ const OPENAI_REASONING_MODEL_PATTERN = /(^|[/:._-])(gpt-5|o1|o3|o4|codex)([/:._-]|$)/i;
39
+ const ANTHROPIC_THINKING_MODEL_PATTERN = /claude-(3-7|sonnet-4|opus-4|4)/i;
40
+ const ANTHROPIC_THINKING_BUDGETS = {
41
+ minimal: 1024,
42
+ low: 2048,
43
+ medium: 4096,
44
+ high: 8192
45
+ };
38
46
  class ModelFactory {
39
- static createModel(modelString) {
47
+ static createModel(modelString, options = {}) {
40
48
  const separatorIndex = modelString.indexOf(":");
41
49
  if (-1 === separatorIndex) throw new Error(`Invalid model format: "${modelString}". Expected format: "provider:model-name"`);
42
50
  const provider = modelString.slice(0, separatorIndex);
@@ -51,21 +59,21 @@ class ModelFactory {
51
59
  logger.debug(`Creating model: ${normalizedProvider}:${model}`);
52
60
  switch(providerSpec.name){
53
61
  case "anthropic":
54
- return ModelFactory.createAnthropicModel(model);
62
+ return ModelFactory.createAnthropicModel(model, options);
55
63
  case "openai":
56
- return ModelFactory.createOpenAIModel(model);
64
+ return ModelFactory.createOpenAIModel(model, options);
57
65
  case "codex":
58
- return ModelFactory.createCodexModel(model);
66
+ return ModelFactory.createCodexModel(model, options);
59
67
  case "openrouter":
60
- return ModelFactory.createOpenRouterModel(model);
68
+ return ModelFactory.createOpenRouterModel(model, options);
61
69
  case "copilot":
62
- return ModelFactory.createCopilotModel(model);
70
+ return ModelFactory.createCopilotModel(model, options);
63
71
  case "xai":
64
- return ModelFactory.createXAIModel(model);
72
+ return ModelFactory.createXAIModel(model, options);
65
73
  case "lmstudio":
66
- return ModelFactory.createLMStudioModel(model);
74
+ return ModelFactory.createLMStudioModel(model, options);
67
75
  case "ollama":
68
- return ModelFactory.createOllamaModel(model);
76
+ return ModelFactory.createOllamaModel(model, options);
69
77
  }
70
78
  }
71
79
  static validateModelString(modelString) {
@@ -93,16 +101,17 @@ class ModelFactory {
93
101
  valid: true
94
102
  };
95
103
  }
96
- static createAnthropicModel(model) {
104
+ static createAnthropicModel(model, options) {
97
105
  const token = (0, credentials_cjs_namespaceObject.resolveProviderToken)("anthropic").token;
98
106
  const params = {
99
107
  model,
100
108
  temperature: 1
101
109
  };
102
110
  if (token) params.apiKey = token;
111
+ ModelFactory.applyAnthropicThinkingEffort(params, "anthropic", model, options);
103
112
  return new anthropic_namespaceObject.ChatAnthropic(params);
104
113
  }
105
- static createOpenAIModel(model) {
114
+ static createOpenAIModel(model, options) {
106
115
  const token = (0, credentials_cjs_namespaceObject.resolveProviderToken)("openai").token;
107
116
  const params = {
108
117
  model,
@@ -110,15 +119,17 @@ class ModelFactory {
110
119
  useResponsesApi: true
111
120
  };
112
121
  if (token) params.apiKey = token;
122
+ ModelFactory.applyOpenAIReasoningEffort(params, "openai", model, options);
113
123
  return new openai_namespaceObject.ChatOpenAI(params);
114
124
  }
115
- static createCodexModel(model) {
125
+ static createCodexModel(model, options) {
116
126
  const provider = (0, registry_cjs_namespaceObject.getProviderSpec)("codex");
117
127
  const token = (0, credentials_cjs_namespaceObject.resolveProviderToken)("codex").token;
118
128
  const codexAuth = (0, codex_cjs_namespaceObject.resolveCodexAuthFromFile)();
119
- return new openai_namespaceObject.ChatOpenAI({
129
+ const params = {
120
130
  model,
121
131
  useResponsesApi: true,
132
+ zdrEnabled: true,
122
133
  apiKey: token ?? "codex",
123
134
  configuration: {
124
135
  baseURL: provider?.baseURL,
@@ -127,23 +138,27 @@ class ModelFactory {
127
138
  fallbackAccountId: codexAuth.accountId
128
139
  })
129
140
  }
130
- });
141
+ };
142
+ ModelFactory.applyOpenAIReasoningEffort(params, "codex", model, options);
143
+ return new openai_namespaceObject.ChatOpenAI(params);
131
144
  }
132
- static createOpenRouterModel(model) {
145
+ static createOpenRouterModel(model, options) {
133
146
  const token = (0, credentials_cjs_namespaceObject.resolveProviderToken)("openrouter").token ?? "";
134
147
  const provider = (0, registry_cjs_namespaceObject.getProviderSpec)("openrouter");
135
- return new openai_namespaceObject.ChatOpenAI({
148
+ const params = {
136
149
  model,
137
150
  temperature: 1,
138
151
  apiKey: token,
139
152
  configuration: {
140
153
  baseURL: provider?.baseURL
141
154
  }
142
- });
155
+ };
156
+ ModelFactory.applyOpenAIReasoningEffort(params, "openrouter", model, options);
157
+ return new openai_namespaceObject.ChatOpenAI(params);
143
158
  }
144
- static createCopilotModel(model) {
159
+ static createCopilotModel(model, options) {
145
160
  const provider = (0, registry_cjs_namespaceObject.getProviderSpec)("copilot");
146
- return new openai_namespaceObject.ChatOpenAI({
161
+ const params = {
147
162
  model,
148
163
  temperature: 1,
149
164
  apiKey: "copilot",
@@ -151,42 +166,77 @@ class ModelFactory {
151
166
  baseURL: provider?.baseURL,
152
167
  fetch: (0, copilot_cjs_namespaceObject.createCopilotFetch)()
153
168
  }
154
- });
169
+ };
170
+ ModelFactory.applyOpenAIReasoningEffort(params, "copilot", model, options);
171
+ return new openai_namespaceObject.ChatOpenAI(params);
155
172
  }
156
- static createXAIModel(model) {
173
+ static createXAIModel(model, options) {
157
174
  const token = (0, credentials_cjs_namespaceObject.resolveProviderToken)("xai").token;
158
175
  const params = {
159
176
  model,
160
177
  temperature: 1
161
178
  };
162
179
  if (token) params.apiKey = token;
180
+ if (options.reasoningEffort) ModelFactory.warnUnsupportedReasoningEffort("xai", model, options.reasoningEffort, options.ownerLabel);
163
181
  return new xai_namespaceObject.ChatXAI(params);
164
182
  }
165
- static createLMStudioModel(model) {
183
+ static createLMStudioModel(model, options) {
166
184
  const tokenResult = (0, credentials_cjs_namespaceObject.resolveProviderToken)("lmstudio");
167
185
  const provider = (0, registry_cjs_namespaceObject.getProviderSpec)("lmstudio");
168
186
  const apiKey = tokenResult.token ?? "lm-studio";
169
- return new openai_namespaceObject.ChatOpenAI({
187
+ const params = {
170
188
  model,
171
189
  temperature: 1,
172
190
  apiKey: apiKey,
173
191
  configuration: {
174
192
  baseURL: provider?.baseURL
175
193
  }
176
- });
194
+ };
195
+ ModelFactory.applyOpenAIReasoningEffort(params, "lmstudio", model, options);
196
+ return new openai_namespaceObject.ChatOpenAI(params);
177
197
  }
178
- static createOllamaModel(model) {
198
+ static createOllamaModel(model, options) {
179
199
  const tokenResult = (0, credentials_cjs_namespaceObject.resolveProviderToken)("ollama");
180
200
  const provider = (0, registry_cjs_namespaceObject.getProviderSpec)("ollama");
181
201
  const apiKey = tokenResult.token ?? "ollama";
182
- return new openai_namespaceObject.ChatOpenAI({
202
+ const params = {
183
203
  model,
184
204
  temperature: 1,
185
205
  apiKey: apiKey,
186
206
  configuration: {
187
207
  baseURL: provider?.baseURL
188
208
  }
189
- });
209
+ };
210
+ ModelFactory.applyOpenAIReasoningEffort(params, "ollama", model, options);
211
+ return new openai_namespaceObject.ChatOpenAI(params);
212
+ }
213
+ static applyOpenAIReasoningEffort(params, provider, model, options) {
214
+ const effort = options.reasoningEffort;
215
+ if (!effort) return;
216
+ if (!ModelFactory.supportsOpenAIReasoningEffort(provider, model)) return void ModelFactory.warnUnsupportedReasoningEffort(provider, model, effort, options.ownerLabel);
217
+ params.reasoning = {
218
+ effort
219
+ };
220
+ }
221
+ static applyAnthropicThinkingEffort(params, provider, model, options) {
222
+ const effort = options.reasoningEffort;
223
+ if (!effort) return;
224
+ if (!ModelFactory.supportsAnthropicThinking(model)) return void ModelFactory.warnUnsupportedReasoningEffort(provider, model, effort, options.ownerLabel);
225
+ params.thinking = {
226
+ type: "enabled",
227
+ budget_tokens: ANTHROPIC_THINKING_BUDGETS[effort]
228
+ };
229
+ }
230
+ static supportsOpenAIReasoningEffort(provider, model) {
231
+ if ("openai" !== provider && "codex" !== provider) return false;
232
+ return OPENAI_REASONING_MODEL_PATTERN.test(model.trim());
233
+ }
234
+ static supportsAnthropicThinking(model) {
235
+ return ANTHROPIC_THINKING_MODEL_PATTERN.test(model.trim().toLowerCase());
236
+ }
237
+ static warnUnsupportedReasoningEffort(provider, model, effort, ownerLabel) {
238
+ const prefix = ownerLabel ? `${ownerLabel}: ` : "";
239
+ logger.warn(`${prefix}model "${provider}:${model}" does not support reasoningEffort="${effort}". Ignoring and continuing.`);
190
240
  }
191
241
  }
192
242
  exports.ModelFactory = __webpack_exports__.ModelFactory;
@@ -1,4 +1,9 @@
1
1
  import type { BaseLanguageModel, BaseLanguageModelCallOptions } from "@langchain/core/language_models/base";
2
+ import type { ReasoningEffort } from "./agentConfig.js";
3
+ export type ModelCreationOptions = {
4
+ reasoningEffort?: ReasoningEffort;
5
+ ownerLabel?: string;
6
+ };
2
7
  /**
3
8
  * Create a LangChain model from a model string
4
9
  *
@@ -16,7 +21,7 @@ export declare class ModelFactory {
16
21
  /**
17
22
  * Parse and create a model from a string specification
18
23
  */
19
- static createModel(modelString: string): string | BaseLanguageModel<any, BaseLanguageModelCallOptions> | undefined;
24
+ static createModel(modelString: string, options?: ModelCreationOptions): string | BaseLanguageModel<any, BaseLanguageModelCallOptions> | undefined;
20
25
  /**
21
26
  * Validate model string format without creating the model
22
27
  */
@@ -32,4 +37,9 @@ export declare class ModelFactory {
32
37
  private static createXAIModel;
33
38
  private static createLMStudioModel;
34
39
  private static createOllamaModel;
40
+ private static applyOpenAIReasoningEffort;
41
+ private static applyAnthropicThinkingEffort;
42
+ private static supportsOpenAIReasoningEffort;
43
+ private static supportsAnthropicThinking;
44
+ private static warnUnsupportedReasoningEffort;
35
45
  }
@@ -7,8 +7,16 @@ import { resolveProviderToken } from "../../providers/credentials.js";
7
7
  import { getProviderSpec, listProviderSpecs, normalizeProviderName } from "../../providers/registry.js";
8
8
  import { createLogger } from "../../logger.js";
9
9
  const logger = createLogger();
10
+ const OPENAI_REASONING_MODEL_PATTERN = /(^|[/:._-])(gpt-5|o1|o3|o4|codex)([/:._-]|$)/i;
11
+ const ANTHROPIC_THINKING_MODEL_PATTERN = /claude-(3-7|sonnet-4|opus-4|4)/i;
12
+ const ANTHROPIC_THINKING_BUDGETS = {
13
+ minimal: 1024,
14
+ low: 2048,
15
+ medium: 4096,
16
+ high: 8192
17
+ };
10
18
  class ModelFactory {
11
- static createModel(modelString) {
19
+ static createModel(modelString, options = {}) {
12
20
  const separatorIndex = modelString.indexOf(":");
13
21
  if (-1 === separatorIndex) throw new Error(`Invalid model format: "${modelString}". Expected format: "provider:model-name"`);
14
22
  const provider = modelString.slice(0, separatorIndex);
@@ -23,21 +31,21 @@ class ModelFactory {
23
31
  logger.debug(`Creating model: ${normalizedProvider}:${model}`);
24
32
  switch(providerSpec.name){
25
33
  case "anthropic":
26
- return ModelFactory.createAnthropicModel(model);
34
+ return ModelFactory.createAnthropicModel(model, options);
27
35
  case "openai":
28
- return ModelFactory.createOpenAIModel(model);
36
+ return ModelFactory.createOpenAIModel(model, options);
29
37
  case "codex":
30
- return ModelFactory.createCodexModel(model);
38
+ return ModelFactory.createCodexModel(model, options);
31
39
  case "openrouter":
32
- return ModelFactory.createOpenRouterModel(model);
40
+ return ModelFactory.createOpenRouterModel(model, options);
33
41
  case "copilot":
34
- return ModelFactory.createCopilotModel(model);
42
+ return ModelFactory.createCopilotModel(model, options);
35
43
  case "xai":
36
- return ModelFactory.createXAIModel(model);
44
+ return ModelFactory.createXAIModel(model, options);
37
45
  case "lmstudio":
38
- return ModelFactory.createLMStudioModel(model);
46
+ return ModelFactory.createLMStudioModel(model, options);
39
47
  case "ollama":
40
- return ModelFactory.createOllamaModel(model);
48
+ return ModelFactory.createOllamaModel(model, options);
41
49
  }
42
50
  }
43
51
  static validateModelString(modelString) {
@@ -65,16 +73,17 @@ class ModelFactory {
65
73
  valid: true
66
74
  };
67
75
  }
68
- static createAnthropicModel(model) {
76
+ static createAnthropicModel(model, options) {
69
77
  const token = resolveProviderToken("anthropic").token;
70
78
  const params = {
71
79
  model,
72
80
  temperature: 1
73
81
  };
74
82
  if (token) params.apiKey = token;
83
+ ModelFactory.applyAnthropicThinkingEffort(params, "anthropic", model, options);
75
84
  return new ChatAnthropic(params);
76
85
  }
77
- static createOpenAIModel(model) {
86
+ static createOpenAIModel(model, options) {
78
87
  const token = resolveProviderToken("openai").token;
79
88
  const params = {
80
89
  model,
@@ -82,15 +91,17 @@ class ModelFactory {
82
91
  useResponsesApi: true
83
92
  };
84
93
  if (token) params.apiKey = token;
94
+ ModelFactory.applyOpenAIReasoningEffort(params, "openai", model, options);
85
95
  return new ChatOpenAI(params);
86
96
  }
87
- static createCodexModel(model) {
97
+ static createCodexModel(model, options) {
88
98
  const provider = getProviderSpec("codex");
89
99
  const token = resolveProviderToken("codex").token;
90
100
  const codexAuth = resolveCodexAuthFromFile();
91
- return new ChatOpenAI({
101
+ const params = {
92
102
  model,
93
103
  useResponsesApi: true,
104
+ zdrEnabled: true,
94
105
  apiKey: token ?? "codex",
95
106
  configuration: {
96
107
  baseURL: provider?.baseURL,
@@ -99,23 +110,27 @@ class ModelFactory {
99
110
  fallbackAccountId: codexAuth.accountId
100
111
  })
101
112
  }
102
- });
113
+ };
114
+ ModelFactory.applyOpenAIReasoningEffort(params, "codex", model, options);
115
+ return new ChatOpenAI(params);
103
116
  }
104
- static createOpenRouterModel(model) {
117
+ static createOpenRouterModel(model, options) {
105
118
  const token = resolveProviderToken("openrouter").token ?? "";
106
119
  const provider = getProviderSpec("openrouter");
107
- return new ChatOpenAI({
120
+ const params = {
108
121
  model,
109
122
  temperature: 1,
110
123
  apiKey: token,
111
124
  configuration: {
112
125
  baseURL: provider?.baseURL
113
126
  }
114
- });
127
+ };
128
+ ModelFactory.applyOpenAIReasoningEffort(params, "openrouter", model, options);
129
+ return new ChatOpenAI(params);
115
130
  }
116
- static createCopilotModel(model) {
131
+ static createCopilotModel(model, options) {
117
132
  const provider = getProviderSpec("copilot");
118
- return new ChatOpenAI({
133
+ const params = {
119
134
  model,
120
135
  temperature: 1,
121
136
  apiKey: "copilot",
@@ -123,42 +138,77 @@ class ModelFactory {
123
138
  baseURL: provider?.baseURL,
124
139
  fetch: createCopilotFetch()
125
140
  }
126
- });
141
+ };
142
+ ModelFactory.applyOpenAIReasoningEffort(params, "copilot", model, options);
143
+ return new ChatOpenAI(params);
127
144
  }
128
- static createXAIModel(model) {
145
+ static createXAIModel(model, options) {
129
146
  const token = resolveProviderToken("xai").token;
130
147
  const params = {
131
148
  model,
132
149
  temperature: 1
133
150
  };
134
151
  if (token) params.apiKey = token;
152
+ if (options.reasoningEffort) ModelFactory.warnUnsupportedReasoningEffort("xai", model, options.reasoningEffort, options.ownerLabel);
135
153
  return new ChatXAI(params);
136
154
  }
137
- static createLMStudioModel(model) {
155
+ static createLMStudioModel(model, options) {
138
156
  const tokenResult = resolveProviderToken("lmstudio");
139
157
  const provider = getProviderSpec("lmstudio");
140
158
  const apiKey = tokenResult.token ?? "lm-studio";
141
- return new ChatOpenAI({
159
+ const params = {
142
160
  model,
143
161
  temperature: 1,
144
162
  apiKey: apiKey,
145
163
  configuration: {
146
164
  baseURL: provider?.baseURL
147
165
  }
148
- });
166
+ };
167
+ ModelFactory.applyOpenAIReasoningEffort(params, "lmstudio", model, options);
168
+ return new ChatOpenAI(params);
149
169
  }
150
- static createOllamaModel(model) {
170
+ static createOllamaModel(model, options) {
151
171
  const tokenResult = resolveProviderToken("ollama");
152
172
  const provider = getProviderSpec("ollama");
153
173
  const apiKey = tokenResult.token ?? "ollama";
154
- return new ChatOpenAI({
174
+ const params = {
155
175
  model,
156
176
  temperature: 1,
157
177
  apiKey: apiKey,
158
178
  configuration: {
159
179
  baseURL: provider?.baseURL
160
180
  }
161
- });
181
+ };
182
+ ModelFactory.applyOpenAIReasoningEffort(params, "ollama", model, options);
183
+ return new ChatOpenAI(params);
184
+ }
185
+ static applyOpenAIReasoningEffort(params, provider, model, options) {
186
+ const effort = options.reasoningEffort;
187
+ if (!effort) return;
188
+ if (!ModelFactory.supportsOpenAIReasoningEffort(provider, model)) return void ModelFactory.warnUnsupportedReasoningEffort(provider, model, effort, options.ownerLabel);
189
+ params.reasoning = {
190
+ effort
191
+ };
192
+ }
193
+ static applyAnthropicThinkingEffort(params, provider, model, options) {
194
+ const effort = options.reasoningEffort;
195
+ if (!effort) return;
196
+ if (!ModelFactory.supportsAnthropicThinking(model)) return void ModelFactory.warnUnsupportedReasoningEffort(provider, model, effort, options.ownerLabel);
197
+ params.thinking = {
198
+ type: "enabled",
199
+ budget_tokens: ANTHROPIC_THINKING_BUDGETS[effort]
200
+ };
201
+ }
202
+ static supportsOpenAIReasoningEffort(provider, model) {
203
+ if ("openai" !== provider && "codex" !== provider) return false;
204
+ return OPENAI_REASONING_MODEL_PATTERN.test(model.trim());
205
+ }
206
+ static supportsAnthropicThinking(model) {
207
+ return ANTHROPIC_THINKING_MODEL_PATTERN.test(model.trim().toLowerCase());
208
+ }
209
+ static warnUnsupportedReasoningEffort(provider, model, effort, ownerLabel) {
210
+ const prefix = ownerLabel ? `${ownerLabel}: ` : "";
211
+ logger.warn(`${prefix}model "${provider}:${model}" does not support reasoningEffort="${effort}". Ignoring and continuing.`);
162
212
  }
163
213
  }
164
214
  export { ModelFactory };
@@ -29,14 +29,16 @@ __webpack_require__.d(__webpack_exports__, {
29
29
  getAvailableTools: ()=>getAvailableTools,
30
30
  createTool: ()=>createTool
31
31
  });
32
- const internet_search_cjs_namespaceObject = require("../tools/internet_search.cjs");
33
- const web_crawler_cjs_namespaceObject = require("../tools/web_crawler.cjs");
34
- const command_execute_cjs_namespaceObject = require("../tools/command_execute.cjs");
35
- const think_cjs_namespaceObject = require("../tools/think.cjs");
32
+ const external_logger_cjs_namespaceObject = require("../../logger.cjs");
33
+ const background_terminal_cjs_namespaceObject = require("../tools/background_terminal.cjs");
36
34
  const code_search_cjs_namespaceObject = require("../tools/code_search.cjs");
35
+ const command_execute_cjs_namespaceObject = require("../tools/command_execute.cjs");
37
36
  const git_status_cjs_namespaceObject = require("../tools/git_status.cjs");
37
+ const internet_search_cjs_namespaceObject = require("../tools/internet_search.cjs");
38
+ const terminal_session_manager_cjs_namespaceObject = require("../tools/terminal_session_manager.cjs");
39
+ const think_cjs_namespaceObject = require("../tools/think.cjs");
38
40
  const ui_registry_cjs_namespaceObject = require("../tools/ui_registry.cjs");
39
- const external_logger_cjs_namespaceObject = require("../../logger.cjs");
41
+ const web_crawler_cjs_namespaceObject = require("../tools/web_crawler.cjs");
40
42
  const external_mcpClientManager_cjs_namespaceObject = require("./mcpClientManager.cjs");
41
43
  const logger = (0, external_logger_cjs_namespaceObject.createLogger)();
42
44
  const UI_TOOL_NAMES = [
@@ -45,7 +47,7 @@ const UI_TOOL_NAMES = [
45
47
  "ui_present"
46
48
  ];
47
49
  function createTool(name, options = {}) {
48
- const { workspace = process.cwd(), executionWorkspace, blockedCommands, allowScriptExecution = true, timeout = 300000, searchConfig = {
50
+ const { workspace = process.cwd(), executionWorkspace, blockedCommands, allowScriptExecution = true, timeout = 300000, terminalOwnerId = "default", terminalSessionManager = (0, terminal_session_manager_cjs_namespaceObject.getSharedTerminalSessionManager)(), searchConfig = {
49
51
  provider: "duckduckgo",
50
52
  maxResults: 5
51
53
  }, skillsDirectory = "skills", dynamicUiEnabled = true } = options;
@@ -65,6 +67,16 @@ function createTool(name, options = {}) {
65
67
  return web_crawler_cjs_namespaceObject.webCrawler;
66
68
  case "command_execute":
67
69
  return (0, command_execute_cjs_namespaceObject.createCommandExecuteTool)(runtimeWorkspace, process.env, blockedCommands, allowScriptExecution, timeout);
70
+ case "background_terminal":
71
+ return (0, background_terminal_cjs_namespaceObject.createBackgroundTerminalTool)({
72
+ workspace: runtimeWorkspace,
73
+ ownerId: terminalOwnerId,
74
+ sessionManager: terminalSessionManager,
75
+ envVariables: process.env,
76
+ blockedCommands,
77
+ allowScriptExecution,
78
+ commandTimeout: timeout
79
+ });
68
80
  case "think":
69
81
  return (0, think_cjs_namespaceObject.createThinkingTool)();
70
82
  case "code_search":
@@ -108,6 +120,7 @@ function getAvailableTools() {
108
120
  "internet_search",
109
121
  "web_crawler",
110
122
  "command_execute",
123
+ "background_terminal",
111
124
  "think",
112
125
  "code_search",
113
126
  "git_status",
@@ -1,13 +1,16 @@
1
1
  import type { StructuredTool } from "@langchain/core/tools";
2
- import type { AvailableToolName } from "./agentConfig.js";
3
- import type { SearchConfig } from "../../cli/config/schema.js";
4
2
  import type { MCPServersConfig } from "@/types/mcp.js";
3
+ import type { SearchConfig } from "../../cli/config/schema.js";
4
+ import { type TerminalSessionManager } from "../tools/terminal_session_manager.js";
5
+ import type { AvailableToolName } from "./agentConfig.js";
5
6
  export interface ToolOptions {
6
7
  workspace?: string;
7
8
  executionWorkspace?: string;
8
9
  blockedCommands?: string[];
9
10
  allowScriptExecution?: boolean;
10
11
  timeout?: number;
12
+ terminalOwnerId?: string;
13
+ terminalSessionManager?: TerminalSessionManager;
11
14
  searchConfig?: SearchConfig;
12
15
  mcpConfigs?: MCPServersConfig[];
13
16
  skillsDirectory?: string;