vibeman 0.0.3 → 0.0.5

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 (184) hide show
  1. package/dist/index.js +3 -3
  2. package/dist/runtime/api/.tsbuildinfo +1 -1
  3. package/dist/runtime/api/agent/agent-service.d.ts +4 -0
  4. package/dist/runtime/api/agent/agent-service.js +62 -3
  5. package/dist/runtime/api/agent/ai-providers/amp-cli-provider.d.ts +38 -0
  6. package/dist/runtime/api/agent/ai-providers/amp-cli-provider.js +268 -0
  7. package/dist/runtime/api/agent/ai-providers/codex-cli-provider.js +40 -12
  8. package/dist/runtime/api/agent/ai-providers/gemini-cli-provider.d.ts +24 -0
  9. package/dist/runtime/api/agent/ai-providers/gemini-cli-provider.js +291 -0
  10. package/dist/runtime/api/agent/ai-providers/index.d.ts +3 -3
  11. package/dist/runtime/api/agent/ai-providers/index.js +3 -1
  12. package/dist/runtime/api/agent/ai-providers/types.d.ts +5 -2
  13. package/dist/runtime/api/agent/amp-cli-provider.test.d.ts +1 -0
  14. package/dist/runtime/api/agent/amp-cli-provider.test.js +99 -0
  15. package/dist/runtime/api/agent/codex-cli-provider.test.js +10 -8
  16. package/dist/runtime/api/agent/prompt-service.js +108 -105
  17. package/dist/runtime/api/agent/prompt-service.test.js +35 -0
  18. package/dist/runtime/api/agent/routing-policy.d.ts +2 -2
  19. package/dist/runtime/api/agent/routing-policy.test.js +4 -4
  20. package/dist/runtime/api/api/routers/ai.d.ts +3 -3
  21. package/dist/runtime/api/api/routers/executions.d.ts +2 -7
  22. package/dist/runtime/api/api/routers/executions.js +2 -2
  23. package/dist/runtime/api/api/routers/provider-config.d.ts +34 -0
  24. package/dist/runtime/api/api/routers/settings.d.ts +19 -0
  25. package/dist/runtime/api/api/routers/settings.js +16 -0
  26. package/dist/runtime/api/api/routers/tasks.d.ts +9 -9
  27. package/dist/runtime/api/api/routers/workflows.d.ts +12 -12
  28. package/dist/runtime/api/api/routers/worktrees.d.ts +2 -2
  29. package/dist/runtime/api/api/trpc.d.ts +16 -16
  30. package/dist/runtime/api/lib/local-config.d.ts +94 -4
  31. package/dist/runtime/api/lib/local-config.js +16 -0
  32. package/dist/runtime/api/lib/provider-detection.d.ts +2 -0
  33. package/dist/runtime/api/lib/provider-detection.js +83 -1
  34. package/dist/runtime/api/lib/server/vibeman-info.d.ts +5 -0
  35. package/dist/runtime/api/lib/server/vibeman-info.js +85 -0
  36. package/dist/runtime/api/lib/trpc/server.d.ts +63 -33
  37. package/dist/runtime/api/persistence/execution-log-persistence.d.ts +1 -1
  38. package/dist/runtime/api/persistence/execution-log-persistence.js +19 -3
  39. package/dist/runtime/api/router.d.ts +63 -33
  40. package/dist/runtime/api/settings-service.js +31 -14
  41. package/dist/runtime/api/tasks/task-file-parser.d.ts +1 -0
  42. package/dist/runtime/api/tasks/task-file-parser.js +20 -1
  43. package/dist/runtime/api/tasks/task-updater.d.ts +62 -0
  44. package/dist/runtime/api/tasks/task-updater.js +260 -0
  45. package/dist/runtime/api/tasks/task-updater.test.d.ts +1 -0
  46. package/dist/runtime/api/tasks/task-updater.test.js +303 -0
  47. package/dist/runtime/api/types/index.d.ts +1 -1
  48. package/dist/runtime/api/types/settings.d.ts +17 -6
  49. package/dist/runtime/api/vcs/git-service.d.ts +9 -0
  50. package/dist/runtime/api/vcs/git-service.js +23 -0
  51. package/dist/runtime/api/vcs/worktree-service.d.ts +1 -1
  52. package/dist/runtime/api/vcs/worktree-service.js +22 -10
  53. package/dist/runtime/api/workflows/quality-pipeline.js +2 -1
  54. package/dist/runtime/api/workflows/vibing-orchestrator.d.ts +93 -5
  55. package/dist/runtime/api/workflows/vibing-orchestrator.js +774 -203
  56. package/dist/runtime/api/workflows/workflow-effects.d.ts +45 -0
  57. package/dist/runtime/api/workflows/workflow-effects.js +49 -0
  58. package/dist/runtime/api/workflows/workflow-reconciler.d.ts +65 -0
  59. package/dist/runtime/api/workflows/workflow-reconciler.js +226 -0
  60. package/dist/runtime/api/workflows/workflow-reducer.d.ts +26 -0
  61. package/dist/runtime/api/workflows/workflow-reducer.js +288 -0
  62. package/dist/runtime/api/workflows/workflow-reducer.test.d.ts +1 -0
  63. package/dist/runtime/api/workflows/workflow-reducer.test.js +247 -0
  64. package/dist/runtime/api/workflows/workflow-schema.d.ts +546 -0
  65. package/dist/runtime/api/workflows/workflow-schema.js +256 -0
  66. package/dist/runtime/web/.next/BUILD_ID +1 -1
  67. package/dist/runtime/web/.next/app-build-manifest.json +50 -50
  68. package/dist/runtime/web/.next/app-path-routes-manifest.json +1 -1
  69. package/dist/runtime/web/.next/build-manifest.json +14 -14
  70. package/dist/runtime/web/.next/prerender-manifest.json +3 -3
  71. package/dist/runtime/web/.next/react-loadable-manifest.json +2 -33
  72. package/dist/runtime/web/.next/required-server-files.json +5 -5
  73. package/dist/runtime/web/.next/server/app/.vibeman/assets/images/[...path]/route.js +1 -1
  74. package/dist/runtime/web/.next/server/app/.vibeman/assets/images/[...path]/route.js.nft.json +1 -1
  75. package/dist/runtime/web/.next/server/app/.vibeman/assets/images/[...path]/route_client-reference-manifest.js +1 -1
  76. package/dist/runtime/web/.next/server/app/_not-found/page.js +2 -2
  77. package/dist/runtime/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  78. package/dist/runtime/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  79. package/dist/runtime/web/.next/server/app/_not-found.html +2 -2
  80. package/dist/runtime/web/.next/server/app/_not-found.rsc +12 -12
  81. package/dist/runtime/web/.next/server/app/api/health/route.js +1 -1
  82. package/dist/runtime/web/.next/server/app/api/health/route.js.nft.json +1 -1
  83. package/dist/runtime/web/.next/server/app/api/health/route_client-reference-manifest.js +1 -1
  84. package/dist/runtime/web/.next/server/app/api/images/[...path]/route.js +1 -1
  85. package/dist/runtime/web/.next/server/app/api/images/[...path]/route.js.nft.json +1 -1
  86. package/dist/runtime/web/.next/server/app/api/images/[...path]/route_client-reference-manifest.js +1 -1
  87. package/dist/runtime/web/.next/server/app/api/upload/route.js +1 -1
  88. package/dist/runtime/web/.next/server/app/api/upload/route.js.nft.json +1 -1
  89. package/dist/runtime/web/.next/server/app/api/upload/route_client-reference-manifest.js +1 -1
  90. package/dist/runtime/web/.next/server/app/index.html +2 -2
  91. package/dist/runtime/web/.next/server/app/index.rsc +15 -15
  92. package/dist/runtime/web/.next/server/app/page.js +27 -62
  93. package/dist/runtime/web/.next/server/app/page.js.nft.json +1 -1
  94. package/dist/runtime/web/.next/server/app/page_client-reference-manifest.js +1 -1
  95. package/dist/runtime/web/.next/server/app-paths-manifest.json +1 -1
  96. package/dist/runtime/web/.next/server/chunks/210.js +1 -0
  97. package/dist/runtime/web/.next/server/chunks/291.js +18 -0
  98. package/dist/runtime/web/.next/server/chunks/552.js +22 -0
  99. package/dist/runtime/web/.next/server/chunks/780.js +1 -0
  100. package/dist/runtime/web/.next/server/chunks/905.js +6 -0
  101. package/dist/runtime/web/.next/server/chunks/98.js +1 -0
  102. package/dist/runtime/web/.next/server/middleware-build-manifest.js +1 -1
  103. package/dist/runtime/web/.next/server/middleware-react-loadable-manifest.js +1 -1
  104. package/dist/runtime/web/.next/server/pages/404.html +2 -2
  105. package/dist/runtime/web/.next/server/pages/500.html +1 -1
  106. package/dist/runtime/web/.next/server/pages/_app.js +1 -1
  107. package/dist/runtime/web/.next/server/pages/_app.js.nft.json +1 -1
  108. package/dist/runtime/web/.next/server/pages/_document.js +1 -1
  109. package/dist/runtime/web/.next/server/pages/_document.js.nft.json +1 -1
  110. package/dist/runtime/web/.next/server/pages/_error.js +9 -9
  111. package/dist/runtime/web/.next/server/pages/_error.js.nft.json +1 -1
  112. package/dist/runtime/web/.next/server/pages-manifest.json +1 -1
  113. package/dist/runtime/web/.next/server/server-reference-manifest.json +1 -1
  114. package/dist/runtime/web/.next/server/webpack-runtime.js +1 -1
  115. package/dist/runtime/web/.next/static/{5_15u1WQCxN1_eHZpldCv → LJFZk_8tvKFN_Ee4HqUuM}/_buildManifest.js +1 -1
  116. package/dist/runtime/web/.next/static/chunks/05c91ade-7d09b2b280adffd1.js +1 -0
  117. package/dist/runtime/web/.next/static/chunks/201-51bef3fa8c832e2e.js +1 -0
  118. package/dist/runtime/web/.next/static/chunks/524-89747ed9b0294f8a.js +1 -0
  119. package/dist/runtime/web/.next/static/chunks/554-8bec6e9cca6acc67.js +1 -0
  120. package/dist/runtime/web/.next/static/chunks/764.86e9503a69d45a85.js +1 -0
  121. package/dist/runtime/web/.next/static/chunks/{87c73c54-09e1ba5c70e60a51.js → 7ab4dc20-239138e0ae7af24a.js} +1 -1
  122. package/dist/runtime/web/.next/static/chunks/905-342391e3d3a3678f.js +20 -0
  123. package/dist/runtime/web/.next/static/chunks/a8a5ce16-4edea7df2d9b544a.js +79 -0
  124. package/dist/runtime/web/.next/static/chunks/{8bb4d8db-3e2aa02b0a2384b9.js → ad74d572-4c1b162e2c15acaa.js} +1 -1
  125. package/dist/runtime/web/.next/static/chunks/app/.vibeman/assets/images/[...path]/route-7b752a8641f96c1f.js +1 -0
  126. package/dist/runtime/web/.next/static/chunks/app/_not-found/page-34e66b251c2b5044.js +1 -0
  127. package/dist/runtime/web/.next/static/chunks/app/api/health/route-7b752a8641f96c1f.js +1 -0
  128. package/dist/runtime/web/.next/static/chunks/app/api/images/[...path]/route-7b752a8641f96c1f.js +1 -0
  129. package/dist/runtime/web/.next/static/chunks/app/api/upload/route-7b752a8641f96c1f.js +1 -0
  130. package/dist/runtime/web/.next/static/chunks/app/layout-df9ac93cb02b2385.js +1 -0
  131. package/dist/runtime/web/.next/static/chunks/app/page-6610743f7de5f92a.js +1 -0
  132. package/dist/runtime/web/.next/static/chunks/c25e0690-e9b798b8de667da1.js +1 -0
  133. package/dist/runtime/web/.next/static/chunks/framework-57157ec4d37f64aa.js +1 -0
  134. package/dist/runtime/web/.next/static/chunks/main-app-156cc0c60371bd78.js +1 -0
  135. package/dist/runtime/web/.next/static/chunks/main-df25d367c47b1fec.js +1 -0
  136. package/dist/runtime/web/.next/static/chunks/pages/_app-9f629a5e1131d19f.js +1 -0
  137. package/dist/runtime/web/.next/static/chunks/pages/_error-9238238274c7efcd.js +1 -0
  138. package/dist/runtime/web/.next/static/chunks/webpack-cd50e39b423d1808.js +1 -0
  139. package/dist/runtime/web/.next/static/css/4fbf378a264bd4ea.css +1 -0
  140. package/dist/runtime/web/package.json +8 -8
  141. package/dist/runtime/web/server.js +1 -1
  142. package/dist/tsconfig.tsbuildinfo +1 -1
  143. package/package.json +3 -37
  144. package/dist/runtime/api/lib/trpc/client.d.ts +0 -1
  145. package/dist/runtime/api/lib/trpc/client.js +0 -5
  146. package/dist/runtime/web/.next/server/chunks/217.js +0 -1
  147. package/dist/runtime/web/.next/server/chunks/383.js +0 -6
  148. package/dist/runtime/web/.next/server/chunks/458.js +0 -1
  149. package/dist/runtime/web/.next/server/chunks/576.js +0 -18
  150. package/dist/runtime/web/.next/server/chunks/635.js +0 -22
  151. package/dist/runtime/web/.next/server/chunks/761.js +0 -1
  152. package/dist/runtime/web/.next/server/chunks/777.js +0 -3
  153. package/dist/runtime/web/.next/server/chunks/825.js +0 -1
  154. package/dist/runtime/web/.next/server/chunks/838.js +0 -1
  155. package/dist/runtime/web/.next/server/chunks/973.js +0 -15
  156. package/dist/runtime/web/.next/static/chunks/18-15c10d3288afef2e.js +0 -1
  157. package/dist/runtime/web/.next/static/chunks/1c0ca389.537bbe362e3ffbd9.js +0 -3
  158. package/dist/runtime/web/.next/static/chunks/22747d63-ad5da0c19f4cfe41.js +0 -71
  159. package/dist/runtime/web/.next/static/chunks/355.056c2645878a799a.js +0 -1
  160. package/dist/runtime/web/.next/static/chunks/420.a5ccf151c9e2b2f1.js +0 -1
  161. package/dist/runtime/web/.next/static/chunks/439.1be0c6242fd248d5.js +0 -15
  162. package/dist/runtime/web/.next/static/chunks/440.c52e7c0f797e22b2.js +0 -1
  163. package/dist/runtime/web/.next/static/chunks/575-e2478287c27da87b.js +0 -1
  164. package/dist/runtime/web/.next/static/chunks/691.920d88c115087314.js +0 -1
  165. package/dist/runtime/web/.next/static/chunks/765-e838910065b50c3d.js +0 -1
  166. package/dist/runtime/web/.next/static/chunks/823-6f371a6e829adbba.js +0 -63
  167. package/dist/runtime/web/.next/static/chunks/891cff7f.0f71fc028f87e683.js +0 -1
  168. package/dist/runtime/web/.next/static/chunks/9af238c7-271a911d4e99ab18.js +0 -1
  169. package/dist/runtime/web/.next/static/chunks/app/.vibeman/assets/images/[...path]/route-751c9265a65409e5.js +0 -1
  170. package/dist/runtime/web/.next/static/chunks/app/_not-found/page-1cb74d1cba27d0ab.js +0 -1
  171. package/dist/runtime/web/.next/static/chunks/app/api/health/route-751c9265a65409e5.js +0 -1
  172. package/dist/runtime/web/.next/static/chunks/app/api/images/[...path]/route-751c9265a65409e5.js +0 -1
  173. package/dist/runtime/web/.next/static/chunks/app/api/upload/route-751c9265a65409e5.js +0 -1
  174. package/dist/runtime/web/.next/static/chunks/app/layout-8435322f09fd0975.js +0 -1
  175. package/dist/runtime/web/.next/static/chunks/app/page-9fe7d75095b4ccec.js +0 -1
  176. package/dist/runtime/web/.next/static/chunks/cac567b0-5b77dd12911823cd.js +0 -1
  177. package/dist/runtime/web/.next/static/chunks/framework-2518f1345b5b2806.js +0 -1
  178. package/dist/runtime/web/.next/static/chunks/main-17665e5e39de9a8a.js +0 -1
  179. package/dist/runtime/web/.next/static/chunks/main-app-c0b0f5ba4f7f9d75.js +0 -1
  180. package/dist/runtime/web/.next/static/chunks/pages/_app-d6f6b3bbc3d81ee1.js +0 -1
  181. package/dist/runtime/web/.next/static/chunks/pages/_error-75a96cf1997cc3b9.js +0 -1
  182. package/dist/runtime/web/.next/static/chunks/webpack-c8de37305b4635cf.js +0 -1
  183. package/dist/runtime/web/.next/static/css/08c950681f1a9a92.css +0 -1
  184. /package/dist/runtime/web/.next/static/{5_15u1WQCxN1_eHZpldCv → LJFZk_8tvKFN_Ee4HqUuM}/_ssgManifest.js +0 -0
@@ -20,6 +20,7 @@ export declare class AgentService extends EventEmitter {
20
20
  private initialized;
21
21
  private routingPolicyManager;
22
22
  private genericStates;
23
+ private completionInterceptors;
23
24
  private readonly defaultTools;
24
25
  private readonly systemPrompts;
25
26
  constructor(taskService: TaskService, projectRoot?: string, worktreeService?: WorktreeService);
@@ -38,6 +39,9 @@ export declare class AgentService extends EventEmitter {
38
39
  private getAgentConfig;
39
40
  private initialize;
40
41
  private setupEventForwarding;
42
+ registerCompletionInterceptor(executionId: string, handler: (data: any) => Promise<boolean>): void;
43
+ clearCompletionInterceptor(executionId: string): void;
44
+ finalizeExecution(executionId: string, status: AgentExecution['status'], error?: string, logs?: string[]): Promise<void>;
41
45
  /**
42
46
  * Create a concise, human-readable line from a structured execution message
43
47
  */
@@ -5,7 +5,7 @@ import { log } from '../lib/logger.js';
5
5
  import { generateId } from '../lib/id-generator.js';
6
6
  import { getProjectRoot } from '../lib/server/project-root.js';
7
7
  import { CoreAgentService } from './core-agent-service.js';
8
- import { ClaudeCodeAdapter, CodexCliProvider } from './ai-providers/index.js';
8
+ import { ClaudeCodeAdapter, CodexCliProvider, GeminiCliProvider, AmpCliProvider, } from './ai-providers/index.js';
9
9
  import { PromptService } from './prompt-service.js';
10
10
  import { RoutingPolicyManager, } from './routing-policy.js';
11
11
  import { isTestEnv } from '../utils/env.js';
@@ -36,6 +36,7 @@ export class AgentService extends EventEmitter {
36
36
  this.initialized = false;
37
37
  // Track lightweight status for generic (non-core) executions
38
38
  this.genericStates = new Map();
39
+ this.completionInterceptors = new Map();
39
40
  // Centralized default tool sets per operation
40
41
  // TODO: need to be more granular, based on the task type and the toolset available for the AI provider
41
42
  this.defaultTools = {
@@ -51,7 +52,7 @@ export class AgentService extends EventEmitter {
51
52
  base: 'You are an expert software engineer. Follow best practices, write clean maintainable code, and ensure your implementation is robust and well-tested.',
52
53
  rerun: 'You are continuing a rerun of this task. Use prior context and focus on fixes.',
53
54
  },
54
- improve_task: 'You are an expert at improving task specifications. Respond with ONLY a valid JSON object containing type, priority, and content fields. No additional text or formatting.',
55
+ improve_task: 'You are an expert at improving task specifications. Detect the language of the input task content and respond in that SAME language for all markdown sections. Keep enum fields (type, priority) in English. Respond with ONLY a valid JSON object containing type, priority, and content fields. No additional text or formatting.',
55
56
  ai_codereview: 'You are a senior developer performing thorough code review. Focus on quality, security, and best practices. Respond with ONLY a valid JSON object. Ultrathink.',
56
57
  ai_merge: 'You are an expert at resolving merge conflicts and integrating code changes. Ensure clean merges that maintain code consistency and functionality.',
57
58
  };
@@ -151,6 +152,16 @@ export class AgentService extends EventEmitter {
151
152
  defaultWorkingDirectory: this.projectRoot,
152
153
  });
153
154
  this.coreAgentService.registerProvider('codex', codexProvider);
155
+ // Register Gemini CLI provider (not default)
156
+ const geminiProvider = new GeminiCliProvider({
157
+ defaultWorkingDirectory: this.projectRoot,
158
+ });
159
+ this.coreAgentService.registerProvider('gemini', geminiProvider);
160
+ // Register Amp CLI provider (not default)
161
+ const ampProvider = new AmpCliProvider({
162
+ defaultWorkingDirectory: this.projectRoot,
163
+ });
164
+ this.coreAgentService.registerProvider('amp', ampProvider);
154
165
  // Initialize prompt service
155
166
  this.promptService = new PromptService(this.projectRoot, this.taskService);
156
167
  // Initialize routing policy manager
@@ -176,6 +187,26 @@ export class AgentService extends EventEmitter {
176
187
  });
177
188
  });
178
189
  this.coreAgentService.on('executionCompleted', (data) => {
190
+ const interceptor = this.completionInterceptors.get(data.executionId);
191
+ if (interceptor) {
192
+ this.completionInterceptors.delete(data.executionId);
193
+ Promise.resolve(interceptor(data))
194
+ .then((handled) => {
195
+ if (handled)
196
+ return;
197
+ void this.logPersistence.completeExecution(data.executionId, 'completed');
198
+ const logs = this.coreAgentService
199
+ .getExecutionMessages(data.executionId)
200
+ .map((m) => this.summarizeMessage(m));
201
+ this.emit('executionUpdated', {
202
+ executionId: data.executionId,
203
+ status: 'completed',
204
+ logs,
205
+ });
206
+ })
207
+ .catch((error) => log.error('Completion interceptor failed', error, 'agent-service'));
208
+ return;
209
+ }
179
210
  void this.logPersistence.completeExecution(data.executionId, 'completed');
180
211
  const logs = this.coreAgentService
181
212
  .getExecutionMessages(data.executionId)
@@ -187,6 +218,7 @@ export class AgentService extends EventEmitter {
187
218
  });
188
219
  });
189
220
  this.coreAgentService.on('executionFailed', (data) => {
221
+ this.completionInterceptors.delete(data.executionId);
190
222
  void this.logPersistence.completeExecution(data.executionId, 'failed', data.error);
191
223
  const logs = this.coreAgentService
192
224
  .getExecutionMessages(data.executionId)
@@ -199,6 +231,7 @@ export class AgentService extends EventEmitter {
199
231
  });
200
232
  });
201
233
  this.coreAgentService.on('executionCancelled', (data) => {
234
+ this.completionInterceptors.delete(data.executionId);
202
235
  void this.logPersistence.completeExecution(data.executionId, 'cancelled');
203
236
  const logs = this.coreAgentService
204
237
  .getExecutionMessages(data.executionId)
@@ -210,6 +243,28 @@ export class AgentService extends EventEmitter {
210
243
  });
211
244
  });
212
245
  }
246
+ registerCompletionInterceptor(executionId, handler) {
247
+ this.completionInterceptors.set(executionId, handler);
248
+ }
249
+ clearCompletionInterceptor(executionId) {
250
+ this.completionInterceptors.delete(executionId);
251
+ }
252
+ async finalizeExecution(executionId, status, error, logs) {
253
+ this.completionInterceptors.delete(executionId);
254
+ if (status === 'completed') {
255
+ await this.logPersistence.completeExecution(executionId, 'completed');
256
+ }
257
+ else {
258
+ await this.logPersistence.completeExecution(executionId, status, error);
259
+ }
260
+ const finalLogs = logs ?? this.getExecutionLogs(executionId);
261
+ this.emit('executionUpdated', {
262
+ executionId,
263
+ status,
264
+ logs: finalLogs,
265
+ error,
266
+ });
267
+ }
213
268
  /**
214
269
  * Create a concise, human-readable line from a structured execution message
215
270
  */
@@ -297,7 +352,11 @@ export class AgentService extends EventEmitter {
297
352
  }
298
353
  }
299
354
  catch (error) {
300
- log.error('Failed to create worktree, using main directory', error, 'agent-service');
355
+ const msg = `Failed to create worktree for task ${taskId}: ${error instanceof Error ? error.message : String(error)}`;
356
+ log.error(msg, error, 'agent-service');
357
+ await this.logPersistence.logMessage(executionId, msg, 'error', { taskId, workflowId });
358
+ await this.completeGenericExecution(executionId, 'failed', msg);
359
+ throw new Error(msg);
301
360
  }
302
361
  // Generate task prompt with workflow configuration for dynamic instructions
303
362
  const prompt = await this.promptService.generateTaskPrompt(task, options?.workflowConfig);
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Amp CLI Provider
3
+ * Headless wrapper around the Amp CLI `amp -x` command.
4
+ */
5
+ import { AIProvider, ExecutionMessage, ExecutionOptions, ModelInfo, ProviderCapabilities, ProviderStatus } from './types.js';
6
+ export interface AmpCliConfig {
7
+ ampBinPath?: string;
8
+ defaultWorkingDirectory?: string;
9
+ /**
10
+ * Amp CLI does not support explicit model selection in this integration.
11
+ * Kept for backwards compatibility but ignored.
12
+ */
13
+ defaultModel?: string;
14
+ defaultTimeoutMs?: number;
15
+ }
16
+ export declare class AmpCliProvider implements AIProvider {
17
+ private config;
18
+ readonly name = "amp";
19
+ readonly displayName = "Amp CLI";
20
+ constructor(config?: AmpCliConfig);
21
+ private resolveExecutable;
22
+ execute(prompt: string, options?: ExecutionOptions): AsyncIterableIterator<ExecutionMessage>;
23
+ executeSync(prompt: string, options?: ExecutionOptions): Promise<{
24
+ id: string;
25
+ provider: string;
26
+ model: string;
27
+ content: string;
28
+ usage: {
29
+ promptTokens: number;
30
+ completionTokens: number;
31
+ totalTokens: number;
32
+ };
33
+ duration: number;
34
+ }>;
35
+ detectAvailableModels(): Promise<ModelInfo[]>;
36
+ validateSetup(): Promise<ProviderStatus>;
37
+ getCapabilities(): ProviderCapabilities;
38
+ }
@@ -0,0 +1,268 @@
1
+ /**
2
+ * Amp CLI Provider
3
+ * Headless wrapper around the Amp CLI `amp -x` command.
4
+ */
5
+ import { spawn } from 'child_process';
6
+ import { getSettingsService } from '../../settings-service.js';
7
+ import { getProviderDetectionService } from '../../lib/provider-detection.js';
8
+ import { logger } from '../../lib/logger.js';
9
+ export class AmpCliProvider {
10
+ constructor(config = {}) {
11
+ this.config = config;
12
+ this.name = 'amp';
13
+ this.displayName = 'Amp CLI';
14
+ }
15
+ async resolveExecutable() {
16
+ if (this.config.ampBinPath)
17
+ return this.config.ampBinPath;
18
+ // Use enhanced detection service
19
+ const detectionService = getProviderDetectionService();
20
+ const result = await detectionService.detectProvider('amp');
21
+ if (result.found && result.path) {
22
+ return result.path;
23
+ }
24
+ // Fallback: try old settings-based approach (though new for Amp, following pattern)
25
+ const settingsBinPath = (() => {
26
+ try {
27
+ const svc = getSettingsService();
28
+ const s = svc.getSettings();
29
+ return s?.agents?.providers?.amp?.binPath;
30
+ }
31
+ catch {
32
+ return undefined;
33
+ }
34
+ })();
35
+ if (settingsBinPath?.trim())
36
+ return settingsBinPath.trim();
37
+ // Default to binary name (resolve via PATH)
38
+ return 'amp';
39
+ }
40
+ async *execute(prompt, options) {
41
+ // Effective options
42
+ const cwd = options?.workingDirectory || this.config.defaultWorkingDirectory || process.cwd();
43
+ // Amp CLI runs in an automatic mode for model/tool selection in this integration.
44
+ // We intentionally ignore any requested model.
45
+ const requestedModel = options?.model || this.config.defaultModel;
46
+ const model = 'auto';
47
+ const timeoutMs = options?.timeout ?? this.config.defaultTimeoutMs ?? 10 * 60 * 1000; // 10m
48
+ const systemPrompt = options?.systemPrompt?.trim();
49
+ const appendSystemPrompt = options?.appendSystemPrompt?.trim();
50
+ // Construct effective prompt
51
+ const promptSegments = [];
52
+ if (systemPrompt) {
53
+ promptSegments.push(systemPrompt);
54
+ }
55
+ if (appendSystemPrompt) {
56
+ promptSegments.push(appendSystemPrompt);
57
+ }
58
+ promptSegments.push(prompt);
59
+ const effectivePrompt = promptSegments.join('\n\n');
60
+ // Build argv for `amp -x`
61
+ const argv = ['-x', effectivePrompt];
62
+ if (options?.dangerouslyBypassApprovalsAndSandbox) {
63
+ argv.push('--dangerously-allow-all');
64
+ }
65
+ const cmd = await this.resolveExecutable();
66
+ const child = spawn(cmd, argv, {
67
+ cwd,
68
+ env: { ...process.env },
69
+ stdio: ['ignore', 'pipe', 'pipe'],
70
+ });
71
+ // Emit an init/system message with effective command
72
+ const init = {
73
+ type: 'init',
74
+ timestamp: new Date().toISOString(),
75
+ sessionId: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
76
+ model,
77
+ provider: this.name,
78
+ };
79
+ yield init;
80
+ yield {
81
+ type: 'system',
82
+ timestamp: new Date().toISOString(),
83
+ content: `Running: ${cmd} ${argv
84
+ .map((a) => (a.includes(' ') ? '"' + a + '"' : a))
85
+ .join(' ')} (cwd=${cwd})`,
86
+ metadata: {
87
+ provider: this.name,
88
+ requestedModel,
89
+ systemPrompt,
90
+ appendSystemPrompt,
91
+ dangerouslyBypassApprovalsAndSandbox: !!options?.dangerouslyBypassApprovalsAndSandbox,
92
+ },
93
+ };
94
+ let stdoutBuf = '';
95
+ let finished = false;
96
+ let lastFlushedIndex = 0;
97
+ let lineCarry = '';
98
+ // Helper to push incremental stdout as assistant log lines
99
+ const flushNewOutput = () => {
100
+ const newChunk = stdoutBuf.slice(lastFlushedIndex);
101
+ if (!newChunk)
102
+ return;
103
+ lastFlushedIndex = stdoutBuf.length;
104
+ // Accumulate and split by line breaks, keep trailing partial
105
+ lineCarry += newChunk;
106
+ const parts = lineCarry.split(/\r?\n/);
107
+ lineCarry = parts.pop() || '';
108
+ return parts.map((l) => l.trimEnd()).filter(Boolean);
109
+ };
110
+ const onAbort = () => {
111
+ try {
112
+ child.kill('SIGTERM');
113
+ }
114
+ catch {
115
+ /* ignore */
116
+ }
117
+ setTimeout(() => {
118
+ if (!finished) {
119
+ try {
120
+ child.kill('SIGKILL');
121
+ }
122
+ catch {
123
+ /* ignore */
124
+ }
125
+ }
126
+ }, 3000);
127
+ };
128
+ if (options?.abortSignal) {
129
+ if (options.abortSignal.aborted)
130
+ onAbort();
131
+ else
132
+ options.abortSignal.addEventListener('abort', onAbort, { once: true });
133
+ }
134
+ const guard = setTimeout(() => {
135
+ onAbort();
136
+ }, timeoutMs);
137
+ child.stdout?.on('data', (data) => {
138
+ stdoutBuf += data.toString('utf8');
139
+ });
140
+ const exitPromise = new Promise((resolve) => {
141
+ child.on('exit', (code, signal) => resolve({ code, signal }));
142
+ });
143
+ // Poll for output until the process exits
144
+ let exitStatus;
145
+ while (!finished) {
146
+ const tick = new Promise((r) => setTimeout(r, 150));
147
+ const exit = await Promise.race([exitPromise, tick]);
148
+ if (exit && typeof exit.code !== 'undefined') {
149
+ const lines = flushNewOutput();
150
+ if (lines && lines.length) {
151
+ for (const text of lines) {
152
+ yield {
153
+ type: 'assistant',
154
+ timestamp: new Date().toISOString(),
155
+ content: text,
156
+ };
157
+ }
158
+ }
159
+ finished = true;
160
+ exitStatus = exit;
161
+ break;
162
+ }
163
+ const lines = flushNewOutput();
164
+ if (lines && lines.length) {
165
+ for (const text of lines) {
166
+ yield {
167
+ type: 'assistant',
168
+ timestamp: new Date().toISOString(),
169
+ content: text,
170
+ };
171
+ }
172
+ }
173
+ }
174
+ const exit = exitStatus ?? (await exitPromise);
175
+ finished = true;
176
+ clearTimeout(guard);
177
+ if (lineCarry.trim()) {
178
+ yield {
179
+ type: 'assistant',
180
+ timestamp: new Date().toISOString(),
181
+ content: lineCarry.trimEnd(),
182
+ };
183
+ lineCarry = '';
184
+ }
185
+ const success = (exit.code ?? 1) === 0 && !exit.signal;
186
+ const remainingStdout = stdoutBuf.trim();
187
+ const resultMsg = {
188
+ type: 'result',
189
+ timestamp: new Date().toISOString(),
190
+ success,
191
+ result: success ? (remainingStdout || '').toString() : undefined,
192
+ error: success
193
+ ? undefined
194
+ : `amp exited ${exit.signal ? 'by ' + exit.signal : 'with code ' + exit.code}`,
195
+ usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
196
+ };
197
+ yield resultMsg;
198
+ }
199
+ async executeSync(prompt, options) {
200
+ let content = '';
201
+ const start = Date.now();
202
+ for await (const msg of this.execute(prompt, options)) {
203
+ if (msg.type === 'assistant' && typeof msg.content === 'string') {
204
+ content += (content ? '\n' : '') + msg.content;
205
+ }
206
+ }
207
+ return {
208
+ id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
209
+ provider: this.name,
210
+ model: 'auto',
211
+ content,
212
+ usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
213
+ duration: Date.now() - start,
214
+ };
215
+ }
216
+ async detectAvailableModels() {
217
+ const capabilities = ['code', 'analysis', 'tools', 'vision', 'reasoning'];
218
+ const makeModel = (id, displayName) => ({
219
+ id,
220
+ name: id,
221
+ displayName,
222
+ provider: this.name,
223
+ contextWindow: 128000,
224
+ maxOutputTokens: 16384,
225
+ capabilities,
226
+ });
227
+ return [makeModel('auto', 'Auto (recommended)')];
228
+ }
229
+ async validateSetup() {
230
+ try {
231
+ const detectionService = getProviderDetectionService();
232
+ const result = await detectionService.detectProvider('amp');
233
+ if (!result.found) {
234
+ return {
235
+ available: false,
236
+ error: result.error || 'Amp CLI not found. Install Amp and ensure it is in your PATH.',
237
+ models: [],
238
+ capabilities: this.getCapabilities(),
239
+ };
240
+ }
241
+ return {
242
+ available: true,
243
+ models: await this.detectAvailableModels(),
244
+ capabilities: this.getCapabilities(),
245
+ };
246
+ }
247
+ catch (error) {
248
+ logger.error(error);
249
+ return {
250
+ available: false,
251
+ error: error instanceof Error ? error.message : String(error),
252
+ models: [],
253
+ capabilities: this.getCapabilities(),
254
+ };
255
+ }
256
+ }
257
+ getCapabilities() {
258
+ return {
259
+ streaming: true,
260
+ tools: true,
261
+ functionCalling: false,
262
+ vision: true,
263
+ codeExecution: true,
264
+ maxContextWindow: 128000,
265
+ maxOutputTokens: 8192,
266
+ };
267
+ }
268
+ }
@@ -6,6 +6,29 @@ import { spawn } from 'child_process';
6
6
  import { getSettingsService } from '../../settings-service.js';
7
7
  import { getProviderDetectionService } from '../../lib/provider-detection.js';
8
8
  import { logger } from '../../lib/logger.js';
9
+ const CODEX_BASE_MODELS = [
10
+ 'gpt-5.1-codex-max',
11
+ 'gpt-5.1-codex',
12
+ 'gpt-5.1-codex-mini',
13
+ 'gpt-5.2',
14
+ 'gpt-5.1',
15
+ ];
16
+ const CODEX_BASE_LABELS = {
17
+ 'gpt-5.1-codex-max': 'gpt-5.1 Codex Max (current)',
18
+ 'gpt-5.1-codex': 'gpt-5.1 Codex',
19
+ 'gpt-5.1-codex-mini': 'gpt-5.1 Codex Mini',
20
+ 'gpt-5.2': 'gpt-5.2',
21
+ 'gpt-5.1': 'gpt-5.1',
22
+ };
23
+ const REASONING_SUFFIXES = [
24
+ 'minimal',
25
+ 'low',
26
+ 'medium',
27
+ 'high',
28
+ 'extra',
29
+ 'extra-high',
30
+ 'extra_high',
31
+ ];
9
32
  export class CodexCliProvider {
10
33
  constructor(config = {}) {
11
34
  this.config = config;
@@ -40,9 +63,12 @@ export class CodexCliProvider {
40
63
  normalizeReasoningEffort(value) {
41
64
  if (!value)
42
65
  return undefined;
43
- const normalized = value.toLowerCase();
66
+ const normalized = value.toLowerCase().replace(/\s+/g, '-');
44
67
  if (normalized === 'minimal')
45
68
  return 'low';
69
+ if (normalized === 'extra-high' || normalized === 'extra_high' || normalized === 'extra') {
70
+ return 'extra_high';
71
+ }
46
72
  const allowed = ['low', 'medium', 'high'];
47
73
  return allowed.includes(normalized)
48
74
  ? normalized
@@ -55,7 +81,9 @@ export class CodexCliProvider {
55
81
  }
56
82
  const trimmed = model.trim();
57
83
  const normalized = trimmed.toLowerCase();
58
- const match = normalized.match(/^(gpt-5(?:-codex)?)(?:-(minimal|low|medium|high))?$/);
84
+ const basePattern = CODEX_BASE_MODELS.map((m) => m.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')).join('|');
85
+ const reasoningPattern = [...REASONING_SUFFIXES].join('|');
86
+ const match = normalized.match(new RegExp(`^(${basePattern})(?:-(${reasoningPattern}))?$`));
59
87
  if (!match) {
60
88
  return {
61
89
  cliModel: trimmed,
@@ -106,7 +134,9 @@ export class CodexCliProvider {
106
134
  argv.push('--image', images.join(','));
107
135
  }
108
136
  if (options?.dangerouslyBypassApprovalsAndSandbox) {
109
- argv.push('--dangerously-bypass-approvals-and-sandbox');
137
+ // Codex CLI >= 0.73.0 replaces the legacy bypass flag with --full-auto + sandbox selection
138
+ argv.push('--full-auto');
139
+ argv.push('--sandbox', 'danger-full-access');
110
140
  }
111
141
  const cmd = await this.resolveExecutable();
112
142
  const child = spawn(cmd, argv, {
@@ -292,16 +322,14 @@ export class CodexCliProvider {
292
322
  maxOutputTokens: 16384,
293
323
  capabilities,
294
324
  });
295
- return [
296
- makeModel('gpt-5', 'gpt‑5'),
297
- makeModel('gpt-5-low', 'gpt‑5 · low reasoning'),
298
- makeModel('gpt-5-medium', 'gpt‑5 · medium reasoning'),
299
- makeModel('gpt-5-high', 'gpt‑5 · high reasoning'),
300
- makeModel('gpt-5-codex', 'gpt‑5 Codex'),
301
- makeModel('gpt-5-codex-low', 'gpt‑5 Codex · low reasoning'),
302
- makeModel('gpt-5-codex-medium', 'gpt‑5 Codex · medium reasoning'),
303
- makeModel('gpt-5-codex-high', 'gpt‑5 Codex · high reasoning'),
325
+ const addReasoningVariants = (base, label) => [
326
+ makeModel(base, label),
327
+ makeModel(`${base}-low`, `${label} · low reasoning`),
328
+ makeModel(`${base}-medium`, `${label} · medium reasoning`),
329
+ makeModel(`${base}-high`, `${label} · high reasoning`),
330
+ makeModel(`${base}-extra-high`, `${label} · extra-high reasoning`),
304
331
  ];
332
+ return Object.entries(CODEX_BASE_LABELS).flatMap(([id, label]) => addReasoningVariants(id, label));
305
333
  }
306
334
  async validateSetup() {
307
335
  try {
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Gemini CLI Provider
3
+ * Headless wrapper around the Gemini CLI binary (default command `gemini`).
4
+ */
5
+ import { AIProvider, ExecutionMessage, ExecutionOptions, ModelInfo, ProviderCapabilities, ProviderStatus } from './types.js';
6
+ export interface GeminiCliConfig {
7
+ geminiBinPath?: string;
8
+ defaultWorkingDirectory?: string;
9
+ defaultModel?: string;
10
+ defaultTimeoutMs?: number;
11
+ }
12
+ export declare class GeminiCliProvider implements AIProvider {
13
+ private config;
14
+ readonly name = "gemini";
15
+ readonly displayName = "Gemini CLI";
16
+ constructor(config?: GeminiCliConfig);
17
+ private resolveExecutable;
18
+ private normalizeReasoningEffort;
19
+ private resolveModelSpec;
20
+ execute(prompt: string, options?: ExecutionOptions): AsyncIterableIterator<ExecutionMessage>;
21
+ detectAvailableModels(): Promise<ModelInfo[]>;
22
+ validateSetup(): Promise<ProviderStatus>;
23
+ getCapabilities(): ProviderCapabilities;
24
+ }