@wingman-ai/gateway 0.2.1 → 0.2.3

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 (72) hide show
  1. package/.wingman/agents/README.md +1 -0
  2. package/.wingman/agents/coding/agent.md +179 -112
  3. package/.wingman/agents/coding/implementor.md +50 -3
  4. package/.wingman/agents/main/agent.md +4 -0
  5. package/README.md +1 -0
  6. package/dist/agent/config/agentConfig.cjs +30 -1
  7. package/dist/agent/config/agentConfig.js +30 -1
  8. package/dist/agent/config/modelFactory.cjs +22 -2
  9. package/dist/agent/config/modelFactory.d.ts +2 -0
  10. package/dist/agent/config/modelFactory.js +22 -2
  11. package/dist/agent/tests/agentConfig.test.cjs +39 -0
  12. package/dist/agent/tests/agentConfig.test.js +39 -0
  13. package/dist/agent/tests/modelFactory.test.cjs +12 -5
  14. package/dist/agent/tests/modelFactory.test.js +12 -5
  15. package/dist/cli/commands/init.cjs +7 -6
  16. package/dist/cli/commands/init.js +7 -6
  17. package/dist/cli/commands/provider.cjs +17 -3
  18. package/dist/cli/commands/provider.js +17 -3
  19. package/dist/cli/config/loader.cjs +27 -0
  20. package/dist/cli/config/loader.js +27 -0
  21. package/dist/cli/config/schema.cjs +80 -2
  22. package/dist/cli/config/schema.d.ts +88 -0
  23. package/dist/cli/config/schema.js +67 -1
  24. package/dist/cli/core/agentInvoker.cjs +242 -17
  25. package/dist/cli/core/agentInvoker.d.ts +46 -4
  26. package/dist/cli/core/agentInvoker.js +214 -13
  27. package/dist/cli/core/sessionManager.cjs +32 -5
  28. package/dist/cli/core/sessionManager.js +32 -5
  29. package/dist/cli/index.cjs +6 -5
  30. package/dist/cli/index.js +6 -5
  31. package/dist/cli/types.d.ts +32 -0
  32. package/dist/gateway/http/sessions.cjs +7 -7
  33. package/dist/gateway/http/sessions.js +7 -7
  34. package/dist/gateway/server.cjs +230 -28
  35. package/dist/gateway/server.d.ts +11 -1
  36. package/dist/gateway/server.js +230 -28
  37. package/dist/gateway/types.d.ts +5 -1
  38. package/dist/gateway/validation.cjs +1 -0
  39. package/dist/gateway/validation.d.ts +2 -0
  40. package/dist/gateway/validation.js +1 -0
  41. package/dist/providers/codex.cjs +167 -0
  42. package/dist/providers/codex.d.ts +15 -0
  43. package/dist/providers/codex.js +127 -0
  44. package/dist/providers/credentials.cjs +8 -0
  45. package/dist/providers/credentials.js +8 -0
  46. package/dist/providers/registry.cjs +11 -0
  47. package/dist/providers/registry.d.ts +1 -1
  48. package/dist/providers/registry.js +11 -0
  49. package/dist/tests/agentInvokerSummarization.test.cjs +296 -0
  50. package/dist/tests/agentInvokerSummarization.test.d.ts +1 -0
  51. package/dist/tests/agentInvokerSummarization.test.js +290 -0
  52. package/dist/tests/cli-config-loader.test.cjs +88 -0
  53. package/dist/tests/cli-config-loader.test.js +88 -0
  54. package/dist/tests/codex-credentials-precedence.test.cjs +94 -0
  55. package/dist/tests/codex-credentials-precedence.test.d.ts +1 -0
  56. package/dist/tests/codex-credentials-precedence.test.js +88 -0
  57. package/dist/tests/codex-provider.test.cjs +186 -0
  58. package/dist/tests/codex-provider.test.d.ts +1 -0
  59. package/dist/tests/codex-provider.test.js +180 -0
  60. package/dist/tests/gateway.test.cjs +173 -1
  61. package/dist/tests/gateway.test.js +173 -1
  62. package/dist/tests/provider-command-codex.test.cjs +57 -0
  63. package/dist/tests/provider-command-codex.test.d.ts +1 -0
  64. package/dist/tests/provider-command-codex.test.js +51 -0
  65. package/dist/tests/sessionStateMessages.test.cjs +38 -0
  66. package/dist/tests/sessionStateMessages.test.js +38 -0
  67. package/dist/webui/assets/index-BVMavpud.css +11 -0
  68. package/dist/webui/assets/index-DCB2aVVf.js +182 -0
  69. package/dist/webui/index.html +2 -2
  70. package/package.json +3 -1
  71. package/dist/webui/assets/index-BytPznA_.css +0 -1
  72. package/dist/webui/assets/index-u_5qlVip.js +0 -176
@@ -14,6 +14,52 @@ export declare const SkillsConfigSchema: z.ZodObject<{
14
14
  skillsDirectory: z.ZodDefault<z.ZodString>;
15
15
  }, z.core.$strip>;
16
16
  export type SkillsConfig = z.infer<typeof SkillsConfigSchema>;
17
+ export declare const SummarizationConfigSchema: z.ZodObject<{
18
+ enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
19
+ maxTokensBeforeSummary: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
20
+ messagesToKeep: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
21
+ }, z.core.$strip>;
22
+ export type SummarizationConfig = z.infer<typeof SummarizationConfigSchema>;
23
+ export declare const ModelRetryConfigSchema: z.ZodObject<{
24
+ enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
25
+ maxRetries: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
26
+ backoffFactor: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
27
+ initialDelayMs: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
28
+ maxDelayMs: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
29
+ jitter: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
30
+ onFailure: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
31
+ error: "error";
32
+ continue: "continue";
33
+ }>>>;
34
+ }, z.core.$strip>;
35
+ export type ModelRetryConfig = z.infer<typeof ModelRetryConfigSchema>;
36
+ export declare const ToolRetryConfigSchema: z.ZodObject<{
37
+ enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
38
+ maxRetries: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
39
+ backoffFactor: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
40
+ initialDelayMs: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
41
+ maxDelayMs: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
42
+ jitter: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
43
+ onFailure: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
44
+ error: "error";
45
+ continue: "continue";
46
+ }>>>;
47
+ tools: z.ZodOptional<z.ZodArray<z.ZodString>>;
48
+ }, z.core.$strip>;
49
+ export type ToolRetryConfig = z.infer<typeof ToolRetryConfigSchema>;
50
+ export declare const HumanInTheLoopConfigSchema: z.ZodObject<{
51
+ enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
52
+ interruptOn: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
53
+ allowedDecisions: z.ZodArray<z.ZodEnum<{
54
+ approve: "approve";
55
+ edit: "edit";
56
+ reject: "reject";
57
+ }>>;
58
+ description: z.ZodOptional<z.ZodString>;
59
+ argsSchema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
60
+ }, z.core.$strip>]>>>>;
61
+ }, z.core.$strip>;
62
+ export type HumanInTheLoopConfig = z.infer<typeof HumanInTheLoopConfigSchema>;
17
63
  export declare const GatewayConfigSchema: z.ZodDefault<z.ZodObject<{
18
64
  host: z.ZodDefault<z.ZodString>;
19
65
  port: z.ZodDefault<z.ZodNumber>;
@@ -92,6 +138,48 @@ export declare const WingmanConfigSchema: z.ZodObject<{
92
138
  }>>>;
93
139
  defaultAgent: z.ZodOptional<z.ZodString>;
94
140
  recursionLimit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
141
+ summarization: z.ZodDefault<z.ZodOptional<z.ZodObject<{
142
+ enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
143
+ maxTokensBeforeSummary: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
144
+ messagesToKeep: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
145
+ }, z.core.$strip>>>;
146
+ modelRetry: z.ZodDefault<z.ZodOptional<z.ZodObject<{
147
+ enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
148
+ maxRetries: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
149
+ backoffFactor: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
150
+ initialDelayMs: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
151
+ maxDelayMs: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
152
+ jitter: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
153
+ onFailure: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
154
+ error: "error";
155
+ continue: "continue";
156
+ }>>>;
157
+ }, z.core.$strip>>>;
158
+ toolRetry: z.ZodDefault<z.ZodOptional<z.ZodObject<{
159
+ enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
160
+ maxRetries: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
161
+ backoffFactor: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
162
+ initialDelayMs: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
163
+ maxDelayMs: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
164
+ jitter: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
165
+ onFailure: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
166
+ error: "error";
167
+ continue: "continue";
168
+ }>>>;
169
+ tools: z.ZodOptional<z.ZodArray<z.ZodString>>;
170
+ }, z.core.$strip>>>;
171
+ humanInTheLoop: z.ZodDefault<z.ZodOptional<z.ZodObject<{
172
+ enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
173
+ interruptOn: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
174
+ allowedDecisions: z.ZodArray<z.ZodEnum<{
175
+ approve: "approve";
176
+ edit: "edit";
177
+ reject: "reject";
178
+ }>>;
179
+ description: z.ZodOptional<z.ZodString>;
180
+ argsSchema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
181
+ }, z.core.$strip>]>>>>;
182
+ }, z.core.$strip>>>;
95
183
  toolHooks: z.ZodOptional<z.ZodObject<{
96
184
  PreToolUse: z.ZodOptional<z.ZodArray<z.ZodObject<{
97
185
  matcher: z.ZodOptional<z.ZodString>;
@@ -16,6 +16,45 @@ const SkillsConfigSchema = z.object({
16
16
  githubToken: z.string().optional().describe("GitHub personal access token for higher API rate limits"),
17
17
  skillsDirectory: z.string().default("skills").describe("Directory to install skills in")
18
18
  });
19
+ const SummarizationConfigSchema = z.object({
20
+ enabled: z.boolean().optional().default(true).describe("Enable conversation history summarization"),
21
+ maxTokensBeforeSummary: z.number().min(1000).max(1000000).optional().default(12000).describe("Token threshold before summarizing conversation history"),
22
+ messagesToKeep: z.number().min(2).max(100).optional().default(8).describe("How many most recent messages to keep after summarization")
23
+ });
24
+ const RetryOnFailureSchema = z["enum"]([
25
+ "continue",
26
+ "error"
27
+ ]);
28
+ const BaseRetryConfigSchema = z.object({
29
+ enabled: z.boolean().optional().default(false).describe("Enable retry middleware"),
30
+ maxRetries: z.number().min(0).max(20).optional().default(2).describe("Maximum number of retry attempts"),
31
+ backoffFactor: z.number().min(0).max(10).optional().default(2).describe("Exponential backoff multiplier"),
32
+ initialDelayMs: z.number().min(0).max(120000).optional().default(1000).describe("Initial delay before first retry in milliseconds"),
33
+ maxDelayMs: z.number().min(0).max(300000).optional().default(60000).describe("Maximum backoff delay in milliseconds"),
34
+ jitter: z.boolean().optional().default(true).describe("Add randomized jitter to retry delays"),
35
+ onFailure: RetryOnFailureSchema.optional().default("continue").describe("Behavior when retries are exhausted")
36
+ });
37
+ const ModelRetryConfigSchema = BaseRetryConfigSchema;
38
+ const ToolRetryConfigSchema = BaseRetryConfigSchema.extend({
39
+ tools: z.array(z.string().min(1)).optional().describe("Optional list of tool names to apply retry logic to")
40
+ });
41
+ const AllowedDecisionSchema = z["enum"]([
42
+ "approve",
43
+ "edit",
44
+ "reject"
45
+ ]);
46
+ const InterruptOnToolConfigSchema = z.union([
47
+ z.boolean(),
48
+ z.object({
49
+ allowedDecisions: z.array(AllowedDecisionSchema).min(1).describe("Allowed decisions for this tool"),
50
+ description: z.string().optional().describe("Optional custom review prompt for this tool"),
51
+ argsSchema: z.record(z.string(), z.any()).optional().describe("Optional argument schema for edit decisions")
52
+ })
53
+ ]);
54
+ const HumanInTheLoopConfigSchema = z.object({
55
+ enabled: z.boolean().optional().default(false).describe("Enable human-in-the-loop tool approval"),
56
+ interruptOn: z.record(z.string(), InterruptOnToolConfigSchema).optional().default({}).describe("Per-tool approval policy mapping")
57
+ });
19
58
  const GatewayAuthSchema = z.object({
20
59
  mode: z["enum"]([
21
60
  "token",
@@ -144,6 +183,33 @@ const WingmanConfigSchema = z.object({
144
183
  ]).optional().default("info"),
145
184
  defaultAgent: z.string().optional(),
146
185
  recursionLimit: z.number().min(1).max(1000000).optional().default(5000),
186
+ summarization: SummarizationConfigSchema.optional().default({
187
+ enabled: true,
188
+ maxTokensBeforeSummary: 12000,
189
+ messagesToKeep: 8
190
+ }),
191
+ modelRetry: ModelRetryConfigSchema.optional().default({
192
+ enabled: true,
193
+ maxRetries: 2,
194
+ backoffFactor: 2,
195
+ initialDelayMs: 1000,
196
+ maxDelayMs: 60000,
197
+ jitter: true,
198
+ onFailure: "continue"
199
+ }),
200
+ toolRetry: ToolRetryConfigSchema.optional().default({
201
+ enabled: false,
202
+ maxRetries: 2,
203
+ backoffFactor: 2,
204
+ initialDelayMs: 1000,
205
+ maxDelayMs: 60000,
206
+ jitter: true,
207
+ onFailure: "continue"
208
+ }),
209
+ humanInTheLoop: HumanInTheLoopConfigSchema.optional().default({
210
+ enabled: false,
211
+ interruptOn: {}
212
+ }),
147
213
  toolHooks: HooksConfigSchema.optional().describe("Global tool hooks configuration"),
148
214
  hooks: InternalHooksConfigSchema.optional().describe("Internal hook configuration"),
149
215
  search: SearchConfigSchema.optional().default({
@@ -213,4 +279,4 @@ function validateConfig(data) {
213
279
  };
214
280
  }
215
281
  }
216
- export { AgentsConfigSchema, GatewayConfigSchema, SearchConfigSchema, SkillsConfigSchema, WingmanConfigSchema, validateConfig };
282
+ export { AgentsConfigSchema, GatewayConfigSchema, HumanInTheLoopConfigSchema, ModelRetryConfigSchema, SearchConfigSchema, SkillsConfigSchema, SummarizationConfigSchema, ToolRetryConfigSchema, WingmanConfigSchema, validateConfig };
@@ -24,26 +24,35 @@ var __webpack_require__ = {};
24
24
  var __webpack_exports__ = {};
25
25
  __webpack_require__.r(__webpack_exports__);
26
26
  __webpack_require__.d(__webpack_exports__, {
27
- resolveExternalOutputMount: ()=>resolveExternalOutputMount,
28
- toWorkspaceAliasVirtualPath: ()=>toWorkspaceAliasVirtualPath,
27
+ resolveToolRetryMiddlewareSettings: ()=>resolveToolRetryMiddlewareSettings,
28
+ resolveSummarizationMiddlewareSettings: ()=>resolveSummarizationMiddlewareSettings,
29
29
  OUTPUT_VIRTUAL_PATH: ()=>OUTPUT_VIRTUAL_PATH,
30
- WORKDIR_VIRTUAL_PATH: ()=>WORKDIR_VIRTUAL_PATH,
31
- AgentInvoker: ()=>AgentInvoker,
30
+ resolveExecutionWorkspace: ()=>resolveExecutionWorkspace,
32
31
  buildUserContent: ()=>buildUserContent,
33
- resolveExecutionWorkspace: ()=>resolveExecutionWorkspace
32
+ toWorkspaceAliasVirtualPath: ()=>toWorkspaceAliasVirtualPath,
33
+ chunkHasAssistantText: ()=>chunkHasAssistantText,
34
+ resolveModelRetryMiddlewareSettings: ()=>resolveModelRetryMiddlewareSettings,
35
+ AgentInvoker: ()=>AgentInvoker,
36
+ detectToolEventContext: ()=>detectToolEventContext,
37
+ WORKDIR_VIRTUAL_PATH: ()=>WORKDIR_VIRTUAL_PATH,
38
+ configureDeepAgentSummarizationMiddleware: ()=>configureDeepAgentSummarizationMiddleware,
39
+ resolveExternalOutputMount: ()=>resolveExternalOutputMount,
40
+ resolveHumanInTheLoopSettings: ()=>resolveHumanInTheLoopSettings,
41
+ selectStreamingFallbackText: ()=>selectStreamingFallbackText
34
42
  });
35
- const external_deepagents_namespaceObject = require("deepagents");
36
43
  const external_node_fs_namespaceObject = require("node:fs");
37
44
  const external_node_path_namespaceObject = require("node:path");
45
+ const external_deepagents_namespaceObject = require("deepagents");
46
+ const external_langchain_namespaceObject = require("langchain");
38
47
  const external_uuid_namespaceObject = require("uuid");
39
- const agentLoader_cjs_namespaceObject = require("../../agent/config/agentLoader.cjs");
40
- const loader_cjs_namespaceObject = require("../config/loader.cjs");
48
+ const mcpClientManager_cjs_namespaceObject = require("../../agent/config/mcpClientManager.cjs");
41
49
  const additional_messages_cjs_namespaceObject = require("../../agent/middleware/additional-messages.cjs");
42
- const hooks_cjs_namespaceObject = require("../../agent/middleware/hooks.cjs");
43
50
  const merger_cjs_namespaceObject = require("../../agent/middleware/hooks/merger.cjs");
51
+ const hooks_cjs_namespaceObject = require("../../agent/middleware/hooks.cjs");
44
52
  const media_compat_cjs_namespaceObject = require("../../agent/middleware/media-compat.cjs");
45
- const mcpClientManager_cjs_namespaceObject = require("../../agent/config/mcpClientManager.cjs");
46
53
  const uiRegistry_cjs_namespaceObject = require("../../agent/uiRegistry.cjs");
54
+ const agentLoader_cjs_namespaceObject = require("../../agent/config/agentLoader.cjs");
55
+ const loader_cjs_namespaceObject = require("../config/loader.cjs");
47
56
  function _define_property(obj, key, value) {
48
57
  if (key in obj) Object.defineProperty(obj, key, {
49
58
  value: value,
@@ -56,6 +65,7 @@ function _define_property(obj, key, value) {
56
65
  }
57
66
  const WORKDIR_VIRTUAL_PATH = "/workdir/";
58
67
  const OUTPUT_VIRTUAL_PATH = "/output/";
68
+ const DEFAULT_DEEPAGENT_MODEL = "claude-sonnet-4-5-20250929";
59
69
  const isPathWithinRoot = (targetPath, rootPath)=>{
60
70
  const normalizedTarget = (0, external_node_path_namespaceObject.normalize)(targetPath);
61
71
  const normalizedRoot = (0, external_node_path_namespaceObject.normalize)(rootPath);
@@ -88,6 +98,101 @@ const resolveExternalOutputMount = (workspace, workdir, defaultOutputDir)=>{
88
98
  absolutePath: null
89
99
  };
90
100
  };
101
+ const resolveSummarizationMiddlewareSettings = (config)=>{
102
+ if (!config.summarization?.enabled) return null;
103
+ return {
104
+ maxTokensBeforeSummary: config.summarization.maxTokensBeforeSummary,
105
+ messagesToKeep: config.summarization.messagesToKeep
106
+ };
107
+ };
108
+ const resolveModelRetryMiddlewareSettings = (config)=>{
109
+ if (!config.modelRetry?.enabled) return null;
110
+ return {
111
+ maxRetries: config.modelRetry.maxRetries,
112
+ backoffFactor: config.modelRetry.backoffFactor,
113
+ initialDelayMs: config.modelRetry.initialDelayMs,
114
+ maxDelayMs: config.modelRetry.maxDelayMs,
115
+ jitter: config.modelRetry.jitter,
116
+ onFailure: config.modelRetry.onFailure
117
+ };
118
+ };
119
+ const resolveToolRetryMiddlewareSettings = (config)=>{
120
+ if (!config.toolRetry?.enabled) return null;
121
+ return {
122
+ maxRetries: config.toolRetry.maxRetries,
123
+ backoffFactor: config.toolRetry.backoffFactor,
124
+ initialDelayMs: config.toolRetry.initialDelayMs,
125
+ maxDelayMs: config.toolRetry.maxDelayMs,
126
+ jitter: config.toolRetry.jitter,
127
+ onFailure: config.toolRetry.onFailure,
128
+ ...config.toolRetry.tools && config.toolRetry.tools.length > 0 ? {
129
+ tools: config.toolRetry.tools
130
+ } : {}
131
+ };
132
+ };
133
+ const resolveHumanInTheLoopSettings = (config)=>{
134
+ if (!config.humanInTheLoop?.enabled) return null;
135
+ const interruptOn = config.humanInTheLoop.interruptOn || {};
136
+ if (0 === Object.keys(interruptOn).length) return null;
137
+ return {
138
+ interruptOn
139
+ };
140
+ };
141
+ const configureDeepAgentSummarizationMiddleware = (agent, settings, model)=>{
142
+ const middleware = agent?.options?.middleware;
143
+ if (!Array.isArray(middleware)) return;
144
+ const index = middleware.findIndex((entry)=>entry?.name === "SummarizationMiddleware");
145
+ if (index < 0) return;
146
+ if (!settings) return void middleware.splice(index, 1);
147
+ middleware[index] = (0, external_langchain_namespaceObject.summarizationMiddleware)({
148
+ model: model || DEFAULT_DEEPAGENT_MODEL,
149
+ trigger: {
150
+ tokens: settings.maxTokensBeforeSummary
151
+ },
152
+ keep: {
153
+ messages: settings.messagesToKeep
154
+ }
155
+ });
156
+ };
157
+ const detectToolEventContext = (chunk)=>{
158
+ if (!chunk || "object" != typeof chunk || Array.isArray(chunk)) return null;
159
+ const eventChunk = chunk;
160
+ if ("on_tool_start" !== eventChunk.event && "on_tool_end" !== eventChunk.event) return null;
161
+ const toolName = "string" == typeof eventChunk.name && eventChunk.name.trim() ? eventChunk.name.trim() : "unknown";
162
+ return {
163
+ event: eventChunk.event,
164
+ toolName
165
+ };
166
+ };
167
+ const chunkHasAssistantText = (chunk)=>{
168
+ if (!chunk || "object" != typeof chunk || Array.isArray(chunk)) return false;
169
+ const eventChunk = chunk;
170
+ const eventName = "string" == typeof eventChunk.event ? eventChunk.event : void 0;
171
+ if ("on_chat_model_stream" === eventName) {
172
+ const data = eventChunk.data && "object" == typeof eventChunk.data ? eventChunk.data : null;
173
+ const messageChunk = data?.chunk || data?.message;
174
+ const content = messageChunk?.content;
175
+ if ("string" == typeof content) return content.length > 0;
176
+ if (Array.isArray(content)) return content.some((part)=>part && "object" == typeof part && "text" === part.type && "string" == typeof part.text && part.text.length > 0);
177
+ }
178
+ if ("on_llm_stream" === eventName) {
179
+ const data = eventChunk.data && "object" == typeof eventChunk.data ? eventChunk.data : null;
180
+ const llmChunk = data?.chunk && "object" == typeof data.chunk ? data.chunk : null;
181
+ return "string" == typeof llmChunk?.text && llmChunk.text.length > 0;
182
+ }
183
+ return false;
184
+ };
185
+ const selectStreamingFallbackText = (sessionMessages, invocationStartedAt, windowMs = 1000)=>{
186
+ for(let i = sessionMessages.length - 1; i >= 0; i -= 1){
187
+ const message = sessionMessages[i];
188
+ if (!message || "object" != typeof message) continue;
189
+ if ("assistant" === message.role) {
190
+ if ("number" == typeof message.createdAt && !(message.createdAt < invocationStartedAt - windowMs)) {
191
+ if ("string" == typeof message.content && message.content.trim()) return message.content;
192
+ }
193
+ }
194
+ }
195
+ };
91
196
  class AgentInvoker {
92
197
  findAllAgents() {
93
198
  const agentConfigs = this.loader.loadAllAgentConfigs();
@@ -96,7 +201,13 @@ class AgentInvoker {
96
201
  async findAgent(name) {
97
202
  return await this.loader.loadAgent(name);
98
203
  }
99
- async invokeAgent(agentName, prompt, sessionId, attachments) {
204
+ async invokeAgent(agentName, prompt, sessionId, attachments, options) {
205
+ const invocationStartedAt = Date.now();
206
+ let cancellationHandled = false;
207
+ let activeToolName = null;
208
+ let lastToolName = null;
209
+ let sawAssistantText = false;
210
+ const isCancelled = ()=>options?.signal?.aborted === true;
100
211
  try {
101
212
  const executionWorkspace = resolveExecutionWorkspace(this.workspace, this.workdir);
102
213
  const effectiveWorkdir = this.workdir ? executionWorkspace : null;
@@ -145,6 +256,29 @@ class AgentInvoker {
145
256
  skillsDirectory
146
257
  })
147
258
  ];
259
+ const summarizationSettings = resolveSummarizationMiddlewareSettings(this.wingmanConfig);
260
+ const modelRetrySettings = resolveModelRetryMiddlewareSettings(this.wingmanConfig);
261
+ if (modelRetrySettings) middleware.push((0, external_langchain_namespaceObject.modelRetryMiddleware)({
262
+ maxRetries: modelRetrySettings.maxRetries,
263
+ backoffFactor: modelRetrySettings.backoffFactor,
264
+ initialDelayMs: modelRetrySettings.initialDelayMs,
265
+ maxDelayMs: modelRetrySettings.maxDelayMs,
266
+ jitter: modelRetrySettings.jitter,
267
+ onFailure: modelRetrySettings.onFailure
268
+ }));
269
+ const toolRetrySettings = resolveToolRetryMiddlewareSettings(this.wingmanConfig);
270
+ if (toolRetrySettings) middleware.push((0, external_langchain_namespaceObject.toolRetryMiddleware)({
271
+ maxRetries: toolRetrySettings.maxRetries,
272
+ backoffFactor: toolRetrySettings.backoffFactor,
273
+ initialDelayMs: toolRetrySettings.initialDelayMs,
274
+ maxDelayMs: toolRetrySettings.maxDelayMs,
275
+ jitter: toolRetrySettings.jitter,
276
+ onFailure: toolRetrySettings.onFailure,
277
+ ...toolRetrySettings.tools ? {
278
+ tools: toolRetrySettings.tools
279
+ } : {}
280
+ }));
281
+ const hitlSettings = resolveHumanInTheLoopSettings(this.wingmanConfig);
148
282
  if (mergedHooks) {
149
283
  this.logger.debug(`Adding hooks middleware with ${mergedHooks.PreToolUse?.length || 0} PreToolUse hooks, ${mergedHooks.PostToolUse?.length || 0} PostToolUse hooks, and ${mergedHooks.Stop?.length || 0} Stop hooks`);
150
284
  middleware.push((0, hooks_cjs_namespaceObject.createHooksMiddleware)(mergedHooks, executionWorkspace, hookSessionId, this.logger));
@@ -191,10 +325,12 @@ class AgentInvoker {
191
325
  virtualMode: true
192
326
  }), backendOverrides),
193
327
  middleware: middleware,
328
+ interruptOn: hitlSettings?.interruptOn,
194
329
  skills: skillsSources,
195
330
  subagents: targetAgent.subagents || [],
196
331
  checkpointer: checkpointer
197
332
  });
333
+ configureDeepAgentSummarizationMiddleware(standaloneAgent, summarizationSettings, targetAgent.model);
198
334
  this.logger.debug("Agent created, sending message");
199
335
  const userContent = buildUserContent(prompt, attachments, targetAgent.model);
200
336
  if (this.sessionManager && sessionId) {
@@ -211,12 +347,58 @@ class AgentInvoker {
211
347
  configurable: {
212
348
  thread_id: sessionId
213
349
  },
214
- version: "v2"
350
+ version: "v2",
351
+ signal: options?.signal
215
352
  });
216
- for await (const chunk of stream)this.outputManager.emitAgentStream(chunk);
353
+ for await (const chunk of stream){
354
+ if (!sawAssistantText && chunkHasAssistantText(chunk)) sawAssistantText = true;
355
+ const toolEvent = detectToolEventContext(chunk);
356
+ if (toolEvent) {
357
+ lastToolName = toolEvent.toolName;
358
+ if ("on_tool_start" === toolEvent.event) activeToolName = toolEvent.toolName;
359
+ else if (activeToolName === toolEvent.toolName) activeToolName = null;
360
+ }
361
+ if (isCancelled()) {
362
+ cancellationHandled = true;
363
+ this.logger.info("Agent invocation cancelled");
364
+ this.outputManager.emitAgentError("Request cancelled");
365
+ if ("function" == typeof stream?.return) await stream.return();
366
+ return {
367
+ cancelled: true
368
+ };
369
+ }
370
+ this.outputManager.emitAgentStream(chunk);
371
+ }
372
+ if (isCancelled()) {
373
+ cancellationHandled = true;
374
+ this.logger.info("Agent invocation cancelled");
375
+ this.outputManager.emitAgentError("Request cancelled");
376
+ return {
377
+ cancelled: true
378
+ };
379
+ }
217
380
  this.logger.info("Agent streaming completed successfully");
381
+ let fallbackText;
382
+ if (!sawAssistantText && this.sessionManager && sessionId) try {
383
+ const sessionMessages = await this.sessionManager.listMessages(sessionId);
384
+ fallbackText = selectStreamingFallbackText(sessionMessages, invocationStartedAt);
385
+ } catch (stateError) {
386
+ this.logger.debug("Failed to derive streaming fallback text from session state", stateError);
387
+ }
388
+ if (!sawAssistantText && !fallbackText) {
389
+ const emptyResponseMessage = "Model completed without a response. Check provider logs for request errors.";
390
+ this.logger.warn(emptyResponseMessage);
391
+ this.outputManager.emitAgentError(emptyResponseMessage);
392
+ return {
393
+ blocked: true,
394
+ reason: "empty_stream_response"
395
+ };
396
+ }
218
397
  this.outputManager.emitAgentComplete({
219
- streaming: true
398
+ streaming: true,
399
+ ...fallbackText ? {
400
+ fallbackText
401
+ } : {}
220
402
  });
221
403
  return {
222
404
  streaming: true
@@ -224,6 +406,14 @@ class AgentInvoker {
224
406
  }
225
407
  {
226
408
  this.logger.debug("Using blocking invoke (no session manager)");
409
+ if (isCancelled()) {
410
+ cancellationHandled = true;
411
+ this.logger.info("Agent invocation cancelled");
412
+ this.outputManager.emitAgentError("Request cancelled");
413
+ return {
414
+ cancelled: true
415
+ };
416
+ }
227
417
  const result = await standaloneAgent.invoke({
228
418
  messages: [
229
419
  {
@@ -232,15 +422,34 @@ class AgentInvoker {
232
422
  }
233
423
  ]
234
424
  }, {
235
- recursionLimit: this.wingmanConfig.recursionLimit
425
+ recursionLimit: this.wingmanConfig.recursionLimit,
426
+ signal: options?.signal
236
427
  });
428
+ if (isCancelled()) {
429
+ cancellationHandled = true;
430
+ this.logger.info("Agent invocation cancelled");
431
+ this.outputManager.emitAgentError("Request cancelled");
432
+ return {
433
+ cancelled: true
434
+ };
435
+ }
237
436
  this.logger.info("Agent completed successfully");
238
437
  this.outputManager.emitAgentComplete(result);
239
438
  return result;
240
439
  }
241
440
  } catch (error) {
242
- this.logger.error(`Agent invocation failed: ${error instanceof Error ? error.message : String(error)}`);
243
- this.outputManager.emitAgentError(error);
441
+ const abortError = isCancelled() || error instanceof Error && ("AbortError" === error.name || "CancelledError" === error.name || /abort|cancel/i.test(error.message));
442
+ if (abortError) {
443
+ if (!cancellationHandled) this.outputManager.emitAgentError("Request cancelled");
444
+ this.logger.info("Agent invocation cancelled");
445
+ return {
446
+ cancelled: true
447
+ };
448
+ }
449
+ this.logger.error(`Agent invocation failed: ${error instanceof Error ? error.message : String(error)}${activeToolName ? ` (while running tool "${activeToolName}")` : lastToolName ? ` (last tool: "${lastToolName}")` : ""}`);
450
+ const errorMessage = error instanceof Error ? error.message : String(error);
451
+ const errorWithToolContext = activeToolName ? `${errorMessage} (while running tool "${activeToolName}")` : lastToolName ? `${errorMessage} (last tool: "${lastToolName}")` : errorMessage;
452
+ this.outputManager.emitAgentError(errorWithToolContext);
244
453
  throw error;
245
454
  } finally{
246
455
  if (this.mcpManager) {
@@ -469,16 +678,32 @@ exports.AgentInvoker = __webpack_exports__.AgentInvoker;
469
678
  exports.OUTPUT_VIRTUAL_PATH = __webpack_exports__.OUTPUT_VIRTUAL_PATH;
470
679
  exports.WORKDIR_VIRTUAL_PATH = __webpack_exports__.WORKDIR_VIRTUAL_PATH;
471
680
  exports.buildUserContent = __webpack_exports__.buildUserContent;
681
+ exports.chunkHasAssistantText = __webpack_exports__.chunkHasAssistantText;
682
+ exports.configureDeepAgentSummarizationMiddleware = __webpack_exports__.configureDeepAgentSummarizationMiddleware;
683
+ exports.detectToolEventContext = __webpack_exports__.detectToolEventContext;
472
684
  exports.resolveExecutionWorkspace = __webpack_exports__.resolveExecutionWorkspace;
473
685
  exports.resolveExternalOutputMount = __webpack_exports__.resolveExternalOutputMount;
686
+ exports.resolveHumanInTheLoopSettings = __webpack_exports__.resolveHumanInTheLoopSettings;
687
+ exports.resolveModelRetryMiddlewareSettings = __webpack_exports__.resolveModelRetryMiddlewareSettings;
688
+ exports.resolveSummarizationMiddlewareSettings = __webpack_exports__.resolveSummarizationMiddlewareSettings;
689
+ exports.resolveToolRetryMiddlewareSettings = __webpack_exports__.resolveToolRetryMiddlewareSettings;
690
+ exports.selectStreamingFallbackText = __webpack_exports__.selectStreamingFallbackText;
474
691
  exports.toWorkspaceAliasVirtualPath = __webpack_exports__.toWorkspaceAliasVirtualPath;
475
692
  for(var __rspack_i in __webpack_exports__)if (-1 === [
476
693
  "AgentInvoker",
477
694
  "OUTPUT_VIRTUAL_PATH",
478
695
  "WORKDIR_VIRTUAL_PATH",
479
696
  "buildUserContent",
697
+ "chunkHasAssistantText",
698
+ "configureDeepAgentSummarizationMiddleware",
699
+ "detectToolEventContext",
480
700
  "resolveExecutionWorkspace",
481
701
  "resolveExternalOutputMount",
702
+ "resolveHumanInTheLoopSettings",
703
+ "resolveModelRetryMiddlewareSettings",
704
+ "resolveSummarizationMiddlewareSettings",
705
+ "resolveToolRetryMiddlewareSettings",
706
+ "selectStreamingFallbackText",
482
707
  "toWorkspaceAliasVirtualPath"
483
708
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
484
709
  Object.defineProperty(exports, '__esModule', {
@@ -1,8 +1,9 @@
1
- import type { OutputManager } from "./outputManager.js";
2
- import type { Logger } from "../../logger.js";
3
1
  import type { WingmanAgentConfig } from "@/agent/config/agentConfig.js";
4
2
  import type { WingmanAgent } from "@/types/agents.js";
5
- import { SessionManager } from "./sessionManager.js";
3
+ import type { Logger } from "../../logger.js";
4
+ import type { WingmanConfigType } from "../config/schema.js";
5
+ import type { OutputManager } from "./outputManager.js";
6
+ import type { SessionManager } from "./sessionManager.js";
6
7
  export interface AgentInvokerOptions {
7
8
  workspace?: string;
8
9
  configDir?: string;
@@ -12,6 +13,9 @@ export interface AgentInvokerOptions {
12
13
  workdir?: string | null;
13
14
  defaultOutputDir?: string | null;
14
15
  }
16
+ export interface InvokeAgentOptions {
17
+ signal?: AbortSignal;
18
+ }
15
19
  export type ImageAttachment = {
16
20
  kind?: "image";
17
21
  dataUrl: string;
@@ -76,9 +80,47 @@ export type ExternalOutputMount = {
76
80
  virtualPath: string | null;
77
81
  absolutePath: string | null;
78
82
  };
83
+ export type SummarizationMiddlewareSettings = {
84
+ maxTokensBeforeSummary: number;
85
+ messagesToKeep: number;
86
+ };
87
+ export type ModelRetryMiddlewareSettings = {
88
+ maxRetries: number;
89
+ backoffFactor: number;
90
+ initialDelayMs: number;
91
+ maxDelayMs: number;
92
+ jitter: boolean;
93
+ onFailure: "continue" | "error";
94
+ };
95
+ export type ToolRetryMiddlewareSettings = ModelRetryMiddlewareSettings & {
96
+ tools?: string[];
97
+ };
98
+ export type HumanInTheLoopSettings = {
99
+ interruptOn: Record<string, boolean | {
100
+ allowedDecisions: Array<"approve" | "edit" | "reject">;
101
+ description?: string;
102
+ argsSchema?: Record<string, any>;
103
+ }>;
104
+ };
79
105
  export declare const resolveExecutionWorkspace: (workspace: string, workdir?: string | null) => string;
80
106
  export declare const toWorkspaceAliasVirtualPath: (absolutePath: string) => string | null;
81
107
  export declare const resolveExternalOutputMount: (workspace: string, workdir?: string | null, defaultOutputDir?: string | null) => ExternalOutputMount;
108
+ export declare const resolveSummarizationMiddlewareSettings: (config: WingmanConfigType) => SummarizationMiddlewareSettings | null;
109
+ export declare const resolveModelRetryMiddlewareSettings: (config: WingmanConfigType) => ModelRetryMiddlewareSettings | null;
110
+ export declare const resolveToolRetryMiddlewareSettings: (config: WingmanConfigType) => ToolRetryMiddlewareSettings | null;
111
+ export declare const resolveHumanInTheLoopSettings: (config: WingmanConfigType) => HumanInTheLoopSettings | null;
112
+ export declare const configureDeepAgentSummarizationMiddleware: (agent: any, settings: SummarizationMiddlewareSettings | null, model?: any) => void;
113
+ type ToolEventContext = {
114
+ event: "on_tool_start" | "on_tool_end";
115
+ toolName: string;
116
+ };
117
+ export declare const detectToolEventContext: (chunk: unknown) => ToolEventContext | null;
118
+ export declare const chunkHasAssistantText: (chunk: unknown) => boolean;
119
+ export declare const selectStreamingFallbackText: (sessionMessages: Array<{
120
+ role?: unknown;
121
+ createdAt?: unknown;
122
+ content?: unknown;
123
+ }>, invocationStartedAt: number, windowMs?: number) => string | undefined;
82
124
  export declare class AgentInvoker {
83
125
  private loader;
84
126
  private outputManager;
@@ -99,7 +141,7 @@ export declare class AgentInvoker {
99
141
  /**
100
142
  * Invoke a specific agent directly (bypassing main orchestration)
101
143
  */
102
- invokeAgent(agentName: string, prompt: string, sessionId?: string, attachments?: MediaAttachment[]): Promise<any>;
144
+ invokeAgent(agentName: string, prompt: string, sessionId?: string, attachments?: MediaAttachment[], options?: InvokeAgentOptions): Promise<any>;
103
145
  /**
104
146
  * List all available agents with their descriptions
105
147
  */