vibeman 0.0.1 → 0.0.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 (102) hide show
  1. package/dist/index.js +5 -7
  2. package/dist/runtime/api/.tsbuildinfo +1 -1
  3. package/dist/runtime/api/agent/agent-service.d.ts +18 -19
  4. package/dist/runtime/api/agent/agent-service.js +61 -58
  5. package/dist/runtime/api/agent/ai-providers/claude-code-adapter.d.ts +2 -2
  6. package/dist/runtime/api/agent/ai-providers/claude-code-adapter.js +25 -36
  7. package/dist/runtime/api/agent/ai-providers/codex-cli-provider.d.ts +2 -0
  8. package/dist/runtime/api/agent/ai-providers/codex-cli-provider.js +109 -43
  9. package/dist/runtime/api/agent/ai-providers/types.d.ts +2 -0
  10. package/dist/runtime/api/agent/codex-cli-provider.test.js +83 -1
  11. package/dist/runtime/api/agent/parsers.d.ts +1 -0
  12. package/dist/runtime/api/agent/parsers.js +75 -8
  13. package/dist/runtime/api/agent/prompt-service.d.ts +14 -1
  14. package/dist/runtime/api/agent/prompt-service.js +123 -14
  15. package/dist/runtime/api/agent/prompt-service.test.js +230 -0
  16. package/dist/runtime/api/agent/routing-policy.d.ts +25 -42
  17. package/dist/runtime/api/agent/routing-policy.js +82 -132
  18. package/dist/runtime/api/agent/routing-policy.test.js +63 -0
  19. package/dist/runtime/api/api/routers/ai.d.ts +19 -7
  20. package/dist/runtime/api/api/routers/ai.js +9 -23
  21. package/dist/runtime/api/api/routers/executions.d.ts +4 -4
  22. package/dist/runtime/api/api/routers/executions.js +12 -21
  23. package/dist/runtime/api/api/routers/provider-config.d.ts +165 -0
  24. package/dist/runtime/api/api/routers/provider-config.js +252 -0
  25. package/dist/runtime/api/api/routers/tasks.d.ts +9 -9
  26. package/dist/runtime/api/api/routers/workflows.d.ts +23 -16
  27. package/dist/runtime/api/api/routers/workflows.js +30 -27
  28. package/dist/runtime/api/api/routers/worktrees.d.ts +4 -5
  29. package/dist/runtime/api/api/routers/worktrees.js +11 -11
  30. package/dist/runtime/api/api/trpc.d.ts +16 -16
  31. package/dist/runtime/api/index.js +2 -10
  32. package/dist/runtime/api/lib/local-config.d.ts +245 -0
  33. package/dist/runtime/api/lib/local-config.js +288 -0
  34. package/dist/runtime/api/lib/provider-detection.d.ts +59 -0
  35. package/dist/runtime/api/lib/provider-detection.js +244 -0
  36. package/dist/runtime/api/lib/server/bootstrap.d.ts +38 -0
  37. package/dist/runtime/api/lib/server/bootstrap.js +197 -0
  38. package/dist/runtime/api/lib/server/project-root.js +24 -1
  39. package/dist/runtime/api/lib/trpc/server.d.ts +143 -30
  40. package/dist/runtime/api/lib/trpc/server.js +8 -8
  41. package/dist/runtime/api/lib/trpc/ws-server.js +2 -2
  42. package/dist/runtime/api/router.d.ts +144 -31
  43. package/dist/runtime/api/router.js +9 -31
  44. package/dist/runtime/api/settings-service.js +51 -1
  45. package/dist/runtime/api/types/index.d.ts +8 -1
  46. package/dist/runtime/api/types/settings.d.ts +15 -2
  47. package/dist/runtime/api/workflows/vibing-orchestrator.d.ts +8 -3
  48. package/dist/runtime/api/workflows/vibing-orchestrator.js +214 -184
  49. package/dist/runtime/web/.next/BUILD_ID +1 -1
  50. package/dist/runtime/web/.next/app-build-manifest.json +19 -12
  51. package/dist/runtime/web/.next/app-path-routes-manifest.json +2 -1
  52. package/dist/runtime/web/.next/build-manifest.json +2 -2
  53. package/dist/runtime/web/.next/prerender-manifest.json +10 -10
  54. package/dist/runtime/web/.next/routes-manifest.json +8 -0
  55. package/dist/runtime/web/.next/server/app/.vibeman/assets/images/[...path]/route.js +1 -0
  56. package/dist/runtime/web/.next/server/app/.vibeman/assets/images/[...path]/route.js.nft.json +1 -0
  57. package/dist/runtime/web/.next/server/app/.vibeman/assets/images/[...path]/route_client-reference-manifest.js +1 -0
  58. package/dist/runtime/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  59. package/dist/runtime/web/.next/server/app/_not-found.html +2 -2
  60. package/dist/runtime/web/.next/server/app/_not-found.rsc +5 -5
  61. package/dist/runtime/web/.next/server/app/api/health/route.js +1 -1
  62. package/dist/runtime/web/.next/server/app/api/health/route_client-reference-manifest.js +1 -1
  63. package/dist/runtime/web/.next/server/app/api/images/[...path]/route.js +1 -1
  64. package/dist/runtime/web/.next/server/app/api/images/[...path]/route_client-reference-manifest.js +1 -1
  65. package/dist/runtime/web/.next/server/app/api/upload/route.js +1 -1
  66. package/dist/runtime/web/.next/server/app/api/upload/route_client-reference-manifest.js +1 -1
  67. package/dist/runtime/web/.next/server/app/index.html +2 -2
  68. package/dist/runtime/web/.next/server/app/index.rsc +6 -6
  69. package/dist/runtime/web/.next/server/app/page.js +21 -21
  70. package/dist/runtime/web/.next/server/app/page_client-reference-manifest.js +1 -1
  71. package/dist/runtime/web/.next/server/app-paths-manifest.json +2 -1
  72. package/dist/runtime/web/.next/server/chunks/458.js +1 -1
  73. package/dist/runtime/web/.next/server/pages/404.html +2 -2
  74. package/dist/runtime/web/.next/server/pages/500.html +1 -1
  75. package/dist/runtime/web/.next/server/pages-manifest.json +1 -1
  76. package/dist/runtime/web/.next/server/server-reference-manifest.json +1 -1
  77. package/dist/runtime/web/.next/static/5_15u1WQCxN1_eHZpldCv/_buildManifest.js +1 -0
  78. package/dist/runtime/web/.next/static/chunks/{277-0142a939f08738c3.js → 823-6f371a6e829adbba.js} +1 -1
  79. package/dist/runtime/web/.next/static/chunks/app/.vibeman/assets/images/[...path]/route-751c9265a65409e5.js +1 -0
  80. package/dist/runtime/web/.next/static/chunks/app/api/health/route-751c9265a65409e5.js +1 -0
  81. package/dist/runtime/web/.next/static/chunks/app/api/images/[...path]/route-751c9265a65409e5.js +1 -0
  82. package/dist/runtime/web/.next/static/chunks/app/api/upload/route-751c9265a65409e5.js +1 -0
  83. package/dist/runtime/web/.next/static/chunks/app/{layout-dc0cfd29075b2160.js → layout-8435322f09fd0975.js} +1 -1
  84. package/dist/runtime/web/.next/static/chunks/app/page-9fe7d75095b4ccec.js +1 -0
  85. package/dist/tsconfig.tsbuildinfo +1 -1
  86. package/package.json +5 -1
  87. package/dist/runtime/api/lib/image-paste-drop-extension.d.ts +0 -26
  88. package/dist/runtime/api/lib/image-paste-drop-extension.js +0 -125
  89. package/dist/runtime/api/lib/markdown-utils.d.ts +0 -8
  90. package/dist/runtime/api/lib/markdown-utils.js +0 -282
  91. package/dist/runtime/api/lib/markdown-utils.test.js +0 -348
  92. package/dist/runtime/api/lib/tiptap-utils.clamp-selection.test.js +0 -27
  93. package/dist/runtime/api/lib/tiptap-utils.d.ts +0 -130
  94. package/dist/runtime/api/lib/tiptap-utils.js +0 -327
  95. package/dist/runtime/web/.next/static/1HR8N0rJkCvFRtbTPJMyH/_buildManifest.js +0 -1
  96. package/dist/runtime/web/.next/static/chunks/app/api/health/route-105a61ae865ba536.js +0 -1
  97. package/dist/runtime/web/.next/static/chunks/app/api/images/[...path]/route-105a61ae865ba536.js +0 -1
  98. package/dist/runtime/web/.next/static/chunks/app/api/upload/route-105a61ae865ba536.js +0 -1
  99. package/dist/runtime/web/.next/static/chunks/app/page-f34a8b196b18850b.js +0 -1
  100. /package/dist/runtime/api/{lib/markdown-utils.test.d.ts → agent/prompt-service.test.d.ts} +0 -0
  101. /package/dist/runtime/api/{lib/tiptap-utils.clamp-selection.test.d.ts → agent/routing-policy.test.d.ts} +0 -0
  102. /package/dist/runtime/web/.next/static/{1HR8N0rJkCvFRtbTPJMyH → 5_15u1WQCxN1_eHZpldCv}/_ssgManifest.js +0 -0
@@ -2,7 +2,7 @@ import { EventEmitter } from 'events';
2
2
  import { Task, WorktreeInfo, AgentExecution, VibingPhase, QualityResults } from '../types/index.js';
3
3
  import { TaskService } from '../tasks/task-service.js';
4
4
  import { WorktreeService } from '../vcs/worktree-service.js';
5
- import { RoutingPolicyManager, type ResolvedProvider } from './routing-policy.js';
5
+ import { RoutingPolicyManager, type RoutableOperation, type ResolvedProvider } from './routing-policy.js';
6
6
  export interface AgentExecutionUpdate {
7
7
  executionId: string;
8
8
  status: AgentExecution['status'];
@@ -38,11 +38,6 @@ export declare class AgentService extends EventEmitter {
38
38
  private getAgentConfig;
39
39
  private initialize;
40
40
  private setupEventForwarding;
41
- /**
42
- * Map core agent update to legacy format
43
- * TODO: remove this later in a separate task, need to migrate the UI to handle raw message streaming
44
- */
45
- private mapToLegacyUpdate;
46
41
  /**
47
42
  * Create a concise, human-readable line from a structured execution message
48
43
  */
@@ -62,8 +57,14 @@ export declare class AgentService extends EventEmitter {
62
57
  qualityResults?: QualityResults;
63
58
  lastLogs?: string[];
64
59
  attempt?: number;
60
+ aiReview?: {
61
+ summary?: string;
62
+ recommendations?: string[];
63
+ score?: number;
64
+ };
65
65
  };
66
66
  providerOverride?: Partial<ResolvedProvider>;
67
+ workflowConfig?: import('../types/index.js').VibingConfig;
67
68
  }): Promise<string>;
68
69
  /**
69
70
  * Build an appended system prompt with rerun context (reason, logs, failed checks)
@@ -97,13 +98,18 @@ export declare class AgentService extends EventEmitter {
97
98
  type: string;
98
99
  priority: string;
99
100
  content: string;
101
+ title?: string;
100
102
  executionId: string;
101
103
  selectedModel?: string;
102
104
  }>;
103
105
  /**
104
106
  * Perform AI code review of changes in a worktree
105
107
  */
106
- aiReviewCode(taskId: string, reviewContext?: string, overrides?: Partial<ResolvedProvider>): Promise<{
108
+ aiReviewCode(taskId: string, reviewContext?: string, options?: {
109
+ overrides?: Partial<ResolvedProvider>;
110
+ executionId?: string;
111
+ workflowId?: string;
112
+ }): Promise<{
107
113
  executionId: string;
108
114
  reviewSummary: string;
109
115
  recommendations: string[];
@@ -114,19 +120,11 @@ export declare class AgentService extends EventEmitter {
114
120
  */
115
121
  aiMerge(taskId: string, options?: {
116
122
  baseBranch?: string;
117
- }, overrides?: Partial<ResolvedProvider>): Promise<{
118
- executionId: string;
119
- }>;
120
- /**
121
- * Compatibility alias for aiReviewCode
122
- * @deprecated Use aiReviewCode instead
123
- * TODO: migrate UI to use aiReviewCode directly and remove this
124
- */
125
- reviewCode(taskId: string, reviewContext?: string, overrides?: Partial<ResolvedProvider>): Promise<{
123
+ overrides?: Partial<ResolvedProvider>;
124
+ executionId?: string;
125
+ workflowId?: string;
126
+ }): Promise<{
126
127
  executionId: string;
127
- reviewSummary: string;
128
- recommendations: string[];
129
- qualityScore: number;
130
128
  }>;
131
129
  /**
132
130
  * Get persistent execution logs
@@ -215,6 +213,7 @@ export declare class AgentService extends EventEmitter {
215
213
  * Resolve provider for specific operation with failover support
216
214
  */
217
215
  private resolveProviderForOperation;
216
+ previewProviderForOperation(operation: RoutableOperation, overrides?: Partial<ResolvedProvider>): Promise<ResolvedProvider>;
218
217
  /**
219
218
  * Execute with provider resolution and failover
220
219
  */
@@ -40,6 +40,7 @@ export class AgentService extends EventEmitter {
40
40
  // TODO: need to be more granular, based on the task type and the toolset available for the AI provider
41
41
  this.defaultTools = {
42
42
  execute_task: fullTools,
43
+ quality_checks: fullTools,
43
44
  improve_task: fullTools,
44
45
  code_review: fullTools,
45
46
  ai_merge: fullTools,
@@ -154,16 +155,6 @@ export class AgentService extends EventEmitter {
154
155
  this.promptService = new PromptService(this.projectRoot, this.taskService);
155
156
  // Initialize routing policy manager
156
157
  this.routingPolicyManager = new RoutingPolicyManager();
157
- // Create example policy file if needed (guarded for mocked environments)
158
- try {
159
- const maybePromise = this.routingPolicyManager.createExamplePolicy?.();
160
- if (maybePromise && typeof maybePromise.catch === 'function') {
161
- maybePromise.catch((err) => log.warn('Failed to create example policy', err, 'agent-service'));
162
- }
163
- }
164
- catch (err) {
165
- log.warn('Failed to trigger example policy creation', err, 'agent-service');
166
- }
167
158
  // Set up event forwarding
168
159
  this.setupEventForwarding();
169
160
  this.initialized = true;
@@ -219,23 +210,6 @@ export class AgentService extends EventEmitter {
219
210
  });
220
211
  });
221
212
  }
222
- /**
223
- * Map core agent update to legacy format
224
- * TODO: remove this later in a separate task, need to migrate the UI to handle raw message streaming
225
- */
226
- mapToLegacyUpdate(data) {
227
- const messages = this.coreAgentService
228
- .getExecutionMessages(data.executionId)
229
- .map((m) => this.summarizeMessage(m));
230
- return {
231
- executionId: data.executionId,
232
- status: data.status ||
233
- this.coreAgentService.getExecutionStatus(data.executionId)?.status ||
234
- 'running',
235
- logs: messages,
236
- error: data.error,
237
- };
238
- }
239
213
  /**
240
214
  * Create a concise, human-readable line from a structured execution message
241
215
  */
@@ -325,8 +299,8 @@ export class AgentService extends EventEmitter {
325
299
  catch (error) {
326
300
  log.error('Failed to create worktree, using main directory', error, 'agent-service');
327
301
  }
328
- // Generate task prompt
329
- const prompt = await this.promptService.generateTaskPrompt(task);
302
+ // Generate task prompt with workflow configuration for dynamic instructions
303
+ const prompt = await this.promptService.generateTaskPrompt(task, options?.workflowConfig);
330
304
  // Build system prompt - use rerun context if available, otherwise base prompt
331
305
  let appendSystemPrompt;
332
306
  if (options?.rerunContext) {
@@ -349,6 +323,7 @@ export class AgentService extends EventEmitter {
349
323
  tools: this.defaultTools.execute_task,
350
324
  timeout: 30 * 60 * 1000,
351
325
  appendSystemPrompt,
326
+ dangerouslyBypassApprovalsAndSandbox: true,
352
327
  executionId,
353
328
  metadata: {
354
329
  operation: 'execute_task',
@@ -403,6 +378,28 @@ export class AgentService extends EventEmitter {
403
378
  }
404
379
  }
405
380
  }
381
+ const review = rerun.aiReview;
382
+ if (review) {
383
+ parts.push('AI code review feedback from previous attempt:');
384
+ if (typeof review.score === 'number') {
385
+ parts.push(`- Quality score: ${review.score}`);
386
+ }
387
+ if (review.summary) {
388
+ parts.push(`- Summary: ${review.summary}`);
389
+ }
390
+ const recs = Array.isArray(review.recommendations)
391
+ ? review.recommendations.filter((r) => typeof r === 'string' && r.trim().length)
392
+ : [];
393
+ if (recs.length) {
394
+ parts.push('Recommendations:');
395
+ for (const item of recs.slice(0, 5)) {
396
+ parts.push(` * ${item}`);
397
+ }
398
+ if (recs.length > 5) {
399
+ parts.push(` * ...and ${recs.length - 5} more recommendations`);
400
+ }
401
+ }
402
+ }
406
403
  parts.push('Instruction: Address the reasons above. Avoid repeating prior mistakes. Keep changes scoped and test thoroughly. ');
407
404
  return parts.join('\n');
408
405
  }
@@ -538,6 +535,7 @@ export class AgentService extends EventEmitter {
538
535
  appendSystemPrompt: this.systemPrompts.improve_task,
539
536
  tools: this.defaultTools.improve_task,
540
537
  timeout: 5 * 60 * 1000,
538
+ dangerouslyBypassApprovalsAndSandbox: false,
541
539
  executionId: finalExecutionId,
542
540
  metadata: {
543
541
  operation: 'improve_task',
@@ -559,7 +557,7 @@ export class AgentService extends EventEmitter {
559
557
  /**
560
558
  * Perform AI code review of changes in a worktree
561
559
  */
562
- async aiReviewCode(taskId, reviewContext, overrides) {
560
+ async aiReviewCode(taskId, reviewContext, options) {
563
561
  const task = this.taskService.getTask(taskId);
564
562
  if (!task) {
565
563
  throw new Error(`Task ${taskId} not found`);
@@ -568,7 +566,7 @@ export class AgentService extends EventEmitter {
568
566
  if (!worktree) {
569
567
  throw new Error(`No worktree found for task ${taskId}`);
570
568
  }
571
- const executionId = generateId('review');
569
+ const executionId = options?.executionId ?? generateId('review');
572
570
  try {
573
571
  // Pre-register execution for streaming/persistence
574
572
  if (!this.executionRegistry.has(executionId)) {
@@ -586,7 +584,7 @@ export class AgentService extends EventEmitter {
586
584
  logs: [],
587
585
  workingDirectory: this.projectRoot,
588
586
  };
589
- await this.logPersistence.startExecution(execRec);
587
+ await this.logPersistence.startExecution(execRec, options?.workflowId);
590
588
  }
591
589
  // Generate review prompt
592
590
  const reviewPrompt = await this.promptService.generateReviewPrompt(task, worktree, reviewContext);
@@ -606,7 +604,7 @@ export class AgentService extends EventEmitter {
606
604
  operation: 'ai_codereview',
607
605
  taskId,
608
606
  },
609
- }, overrides);
607
+ }, options?.overrides);
610
608
  // Parse review result
611
609
  const review = this.parseReviewResult(result);
612
610
  const payload = { executionId, ...review };
@@ -627,7 +625,7 @@ export class AgentService extends EventEmitter {
627
625
  /**
628
626
  * Perform AI-assisted merge of a task's worktree into the base project
629
627
  */
630
- async aiMerge(taskId, options, overrides) {
628
+ async aiMerge(taskId, options) {
631
629
  const task = this.taskService.getTask(taskId);
632
630
  if (!task) {
633
631
  throw new Error(`Task ${taskId} not found`);
@@ -636,14 +634,15 @@ export class AgentService extends EventEmitter {
636
634
  if (!worktree) {
637
635
  throw new Error(`No worktree found for task ${taskId}`);
638
636
  }
639
- const executionId = generateId('merge');
637
+ const executionId = options?.executionId ?? generateId('merge');
638
+ const workingDirectory = worktree.path || this.projectRoot;
640
639
  try {
641
640
  // Pre-register execution for streaming/persistence
642
641
  if (!this.executionRegistry.has(executionId)) {
643
642
  const startTime = new Date().toISOString();
644
643
  this.executionRegistry.set(executionId, {
645
644
  taskId,
646
- workingDirectory: this.projectRoot,
645
+ workingDirectory,
647
646
  startTime,
648
647
  });
649
648
  const execRec = {
@@ -652,21 +651,21 @@ export class AgentService extends EventEmitter {
652
651
  status: 'pending',
653
652
  startTime,
654
653
  logs: [],
655
- workingDirectory: this.projectRoot,
654
+ workingDirectory,
656
655
  };
657
- await this.logPersistence.startExecution(execRec);
656
+ await this.logPersistence.startExecution(execRec, options?.workflowId);
658
657
  }
659
658
  // Generate merge prompt
660
659
  const mergePrompt = await this.promptService.generateAIMergePrompt(task, worktree, options?.baseBranch);
661
660
  void this.logPersistence.logMessage(executionId, 'Merge prompt prepared', 'info', {
662
661
  prompt: mergePrompt,
663
- options: { workingDirectory: this.projectRoot, tools: this.defaultTools.ai_merge },
662
+ options: { workingDirectory, tools: this.defaultTools.ai_merge },
664
663
  taskId,
665
664
  baseBranch: options?.baseBranch,
666
665
  });
667
666
  // Execute merge with AI
668
667
  await this.executeWithRouting('ai_merge', mergePrompt, {
669
- workingDirectory: this.projectRoot,
668
+ workingDirectory,
670
669
  appendSystemPrompt: this.systemPrompts.ai_merge,
671
670
  tools: this.defaultTools.ai_merge,
672
671
  timeout: 15 * 60 * 1000,
@@ -676,29 +675,13 @@ export class AgentService extends EventEmitter {
676
675
  taskId,
677
676
  baseBranch: options?.baseBranch,
678
677
  },
679
- }, overrides);
680
- // Ensure registry exists for lookups (no-op otherwise)
681
- if (!this.executionRegistry.has(executionId)) {
682
- this.executionRegistry.set(executionId, {
683
- taskId,
684
- workingDirectory: this.projectRoot,
685
- startTime: new Date().toISOString(),
686
- });
687
- }
678
+ }, options?.overrides);
688
679
  return { executionId };
689
680
  }
690
681
  catch (error) {
691
682
  throw new Error(`AI merge failed: ${error instanceof Error ? error.message : String(error)}`);
692
683
  }
693
684
  }
694
- /**
695
- * Compatibility alias for aiReviewCode
696
- * @deprecated Use aiReviewCode instead
697
- * TODO: migrate UI to use aiReviewCode directly and remove this
698
- */
699
- async reviewCode(taskId, reviewContext, overrides) {
700
- return this.aiReviewCode(taskId, reviewContext, overrides);
701
- }
702
685
  /**
703
686
  * Get persistent execution logs
704
687
  */
@@ -814,6 +797,9 @@ export class AgentService extends EventEmitter {
814
797
  async resolveProviderForOperation(operation, overrides) {
815
798
  return await this.routingPolicyManager.resolveProviderForOperation(operation, overrides);
816
799
  }
800
+ async previewProviderForOperation(operation, overrides) {
801
+ return await this.resolveProviderForOperation(operation, overrides);
802
+ }
817
803
  /**
818
804
  * Execute with provider resolution and failover
819
805
  */
@@ -828,6 +814,16 @@ export class AgentService extends EventEmitter {
828
814
  workingDirectory: options.workingDirectory,
829
815
  timeout: options.timeout,
830
816
  };
817
+ // Persist a clear log line indicating chosen provider/model for this operation
818
+ try {
819
+ const execId = options?.executionId;
820
+ if (execId) {
821
+ await this.logPersistence.logMessage(execId, `Using provider: ${resolved.provider}${resolved.model ? ` (model: ${resolved.model})` : ''}`, 'info', { operation, resolved });
822
+ }
823
+ }
824
+ catch {
825
+ // best-effort logging; ignore
826
+ }
831
827
  // Default maxTokens from settings when not provided (unlimited if omitted)
832
828
  try {
833
829
  if (executionOptions.maxTokens === undefined) {
@@ -843,8 +839,15 @@ export class AgentService extends EventEmitter {
843
839
  catch {
844
840
  // best effort; ignore if settings unavailable
845
841
  }
846
- let lastError = null;
847
842
  const providersToTry = [resolved.provider, ...(resolved.fallbacks || [])];
843
+ // Ensure Codex executes with write permissions when it is in the routing set.
844
+ // Some overrides may omit the flag, so default it on for task execution.
845
+ if (operation === 'execute_task' &&
846
+ providersToTry.includes('codex') &&
847
+ executionOptions.dangerouslyBypassApprovalsAndSandbox === undefined) {
848
+ executionOptions.dangerouslyBypassApprovalsAndSandbox = true;
849
+ }
850
+ let lastError = null;
848
851
  for (let i = 0; i < providersToTry.length; i++) {
849
852
  const provider = providersToTry[i];
850
853
  const isLastProvider = i === providersToTry.length - 1;
@@ -43,7 +43,7 @@ export declare class ClaudeCodeAdapter implements AIProvider {
43
43
  */
44
44
  detectAvailableModels(): Promise<ModelInfo[]>;
45
45
  /**
46
- * Validate Claude Code setup
46
+ * Validate Claude Code setup using enhanced detection
47
47
  */
48
48
  validateSetup(): Promise<ProviderStatus>;
49
49
  /**
@@ -55,7 +55,7 @@ export declare class ClaudeCodeAdapter implements AIProvider {
55
55
  */
56
56
  private mapToClaudeOptions;
57
57
  /**
58
- * Resolve Claude CLI executable path
58
+ * Resolve Claude CLI executable path using enhanced detection
59
59
  */
60
60
  private getClaudeExecutablePath;
61
61
  }
@@ -3,10 +3,9 @@
3
3
  * Implements AIProvider interface for Claude Code SDK
4
4
  */
5
5
  import { query } from '@anthropic-ai/claude-code';
6
- import path from 'path';
7
- import os from 'os';
8
6
  import { generateId } from '../../lib/id-generator.js';
9
7
  import { getSettingsService } from '../../settings-service.js';
8
+ import { getProviderDetectionService } from '../../lib/provider-detection.js';
10
9
  /**
11
10
  * Claude Code Adapter
12
11
  * Wraps the Claude Code SDK to implement the AIProvider interface
@@ -21,7 +20,7 @@ export class ClaudeCodeAdapter {
21
20
  * Execute a prompt using Claude Code SDK
22
21
  */
23
22
  async *execute(prompt, options) {
24
- const claudeOptions = this.mapToClaudeOptions(options);
23
+ const claudeOptions = await this.mapToClaudeOptions(options);
25
24
  const co = claudeOptions;
26
25
  const startTime = Date.now();
27
26
  let sessionId;
@@ -249,30 +248,19 @@ export class ClaudeCodeAdapter {
249
248
  ];
250
249
  }
251
250
  /**
252
- * Validate Claude Code setup
251
+ * Validate Claude Code setup using enhanced detection
253
252
  */
254
253
  async validateSetup() {
255
254
  try {
256
- const claudePath = this.getClaudeExecutablePath();
257
- const fs = await import('fs/promises');
258
- // Check if Claude executable exists
259
- try {
260
- await fs.access(claudePath);
261
- }
262
- catch {
263
- // Try to execute claude directly (might be in PATH)
264
- const { execSync } = await import('child_process');
265
- try {
266
- execSync('claude --version', { stdio: 'ignore' });
267
- }
268
- catch {
269
- return {
270
- available: false,
271
- error: 'Claude CLI not found. Please install Claude Code CLI.',
272
- models: [],
273
- capabilities: this.getCapabilities(),
274
- };
275
- }
255
+ const detectionService = getProviderDetectionService();
256
+ const result = await detectionService.detectProvider('claude-code');
257
+ if (!result.found) {
258
+ return {
259
+ available: false,
260
+ error: result.error || 'Claude CLI not found. Please install Claude Code CLI.',
261
+ models: [],
262
+ capabilities: this.getCapabilities(),
263
+ };
276
264
  }
277
265
  const models = await this.detectAvailableModels();
278
266
  return {
@@ -307,11 +295,11 @@ export class ClaudeCodeAdapter {
307
295
  /**
308
296
  * Map ExecutionOptions to Claude Code Options
309
297
  */
310
- mapToClaudeOptions(options) {
298
+ async mapToClaudeOptions(options) {
311
299
  const claudeOptions = {
312
300
  cwd: options?.workingDirectory || this.config.defaultWorkingDirectory || process.cwd(),
313
301
  model: options?.model || this.config.defaultModel,
314
- pathToClaudeCodeExecutable: this.getClaudeExecutablePath(),
302
+ pathToClaudeCodeExecutable: await this.getClaudeExecutablePath(),
315
303
  };
316
304
  // Map temperature
317
305
  if (options?.temperature !== undefined) {
@@ -342,18 +330,20 @@ export class ClaudeCodeAdapter {
342
330
  return claudeOptions;
343
331
  }
344
332
  /**
345
- * Resolve Claude CLI executable path
333
+ * Resolve Claude CLI executable path using enhanced detection
346
334
  */
347
- getClaudeExecutablePath() {
348
- // Highest precedence: explicit env var (documented in README)
349
- const envPath = process.env.VIBEMAN_CLAUDE_BIN;
350
- if (envPath && envPath.trim()) {
351
- return envPath.trim();
352
- }
335
+ async getClaudeExecutablePath() {
336
+ // Highest precedence: explicit config option
353
337
  if (this.config.claudeBinPath) {
354
338
  return this.config.claudeBinPath;
355
339
  }
356
- // Check settings first
340
+ // Use enhanced detection service
341
+ const detectionService = getProviderDetectionService();
342
+ const result = await detectionService.detectProvider('claude-code');
343
+ if (result.found && result.path) {
344
+ return result.path;
345
+ }
346
+ // Fallback: try old settings-based approach for backwards compatibility
357
347
  const settingsBinPath = (() => {
358
348
  try {
359
349
  const svc = getSettingsService();
@@ -367,7 +357,6 @@ export class ClaudeCodeAdapter {
367
357
  if (settingsBinPath?.trim()) {
368
358
  return settingsBinPath.trim();
369
359
  }
370
- // Default to local installation
371
- return path.join(os.homedir(), '.claude', 'local', 'claude');
360
+ return 'claude';
372
361
  }
373
362
  }
@@ -15,6 +15,8 @@ export declare class CodexCliProvider implements AIProvider {
15
15
  readonly displayName = "Codex CLI";
16
16
  constructor(config?: CodexCliConfig);
17
17
  private resolveExecutable;
18
+ private normalizeReasoningEffort;
19
+ private resolveModelSpec;
18
20
  execute(prompt: string, options?: ExecutionOptions): AsyncIterableIterator<ExecutionMessage>;
19
21
  executeSync(prompt: string, options?: ExecutionOptions): Promise<{
20
22
  id: string;