vibeman 0.0.0 → 0.0.1
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.
- package/README.md +12 -0
- package/dist/index.js +116 -0
- package/dist/runtime/api/.tsbuildinfo +1 -0
- package/dist/runtime/api/agent/agent-service.d.ts +226 -0
- package/dist/runtime/api/agent/agent-service.js +901 -0
- package/dist/runtime/api/agent/ai-providers/claude-code-adapter.d.ts +61 -0
- package/dist/runtime/api/agent/ai-providers/claude-code-adapter.js +373 -0
- package/dist/runtime/api/agent/ai-providers/codex-cli-provider.d.ts +34 -0
- package/dist/runtime/api/agent/ai-providers/codex-cli-provider.js +281 -0
- package/dist/runtime/api/agent/ai-providers/index.d.ts +9 -0
- package/dist/runtime/api/agent/ai-providers/index.js +7 -0
- package/dist/runtime/api/agent/ai-providers/types.d.ts +180 -0
- package/dist/runtime/api/agent/ai-providers/types.js +5 -0
- package/dist/runtime/api/agent/codex-cli-provider.test.d.ts +1 -0
- package/dist/runtime/api/agent/codex-cli-provider.test.js +88 -0
- package/dist/runtime/api/agent/core-agent-service.d.ts +119 -0
- package/dist/runtime/api/agent/core-agent-service.js +267 -0
- package/dist/runtime/api/agent/parsers.d.ts +15 -0
- package/dist/runtime/api/agent/parsers.js +241 -0
- package/dist/runtime/api/agent/prompt-service.d.ts +17 -0
- package/dist/runtime/api/agent/prompt-service.js +340 -0
- package/dist/runtime/api/agent/routing-policy.d.ts +188 -0
- package/dist/runtime/api/agent/routing-policy.js +246 -0
- package/dist/runtime/api/api/router-helpers.d.ts +32 -0
- package/dist/runtime/api/api/router-helpers.js +31 -0
- package/dist/runtime/api/api/routers/ai.d.ts +188 -0
- package/dist/runtime/api/api/routers/ai.js +410 -0
- package/dist/runtime/api/api/routers/executions.d.ts +98 -0
- package/dist/runtime/api/api/routers/executions.js +103 -0
- package/dist/runtime/api/api/routers/git.d.ts +45 -0
- package/dist/runtime/api/api/routers/git.js +35 -0
- package/dist/runtime/api/api/routers/settings.d.ts +139 -0
- package/dist/runtime/api/api/routers/settings.js +113 -0
- package/dist/runtime/api/api/routers/tasks.d.ts +141 -0
- package/dist/runtime/api/api/routers/tasks.js +238 -0
- package/dist/runtime/api/api/routers/workflows.d.ts +268 -0
- package/dist/runtime/api/api/routers/workflows.js +308 -0
- package/dist/runtime/api/api/routers/worktrees.d.ts +102 -0
- package/dist/runtime/api/api/routers/worktrees.js +80 -0
- package/dist/runtime/api/api/trpc.d.ts +118 -0
- package/dist/runtime/api/api/trpc.js +34 -0
- package/dist/runtime/api/index.d.ts +9 -0
- package/dist/runtime/api/index.js +125 -0
- package/dist/runtime/api/lib/id-generator.d.ts +70 -0
- package/dist/runtime/api/lib/id-generator.js +123 -0
- package/dist/runtime/api/lib/image-paste-drop-extension.d.ts +26 -0
- package/dist/runtime/api/lib/image-paste-drop-extension.js +125 -0
- package/dist/runtime/api/lib/logger.d.ts +11 -0
- package/dist/runtime/api/lib/logger.js +188 -0
- package/dist/runtime/api/lib/markdown-utils.d.ts +8 -0
- package/dist/runtime/api/lib/markdown-utils.js +282 -0
- package/dist/runtime/api/lib/markdown-utils.test.d.ts +1 -0
- package/dist/runtime/api/lib/markdown-utils.test.js +348 -0
- package/dist/runtime/api/lib/server/agent-service-singleton.d.ts +6 -0
- package/dist/runtime/api/lib/server/agent-service-singleton.js +27 -0
- package/dist/runtime/api/lib/server/git-service-singleton.d.ts +6 -0
- package/dist/runtime/api/lib/server/git-service-singleton.js +47 -0
- package/dist/runtime/api/lib/server/project-root.d.ts +2 -0
- package/dist/runtime/api/lib/server/project-root.js +38 -0
- package/dist/runtime/api/lib/server/task-service-singleton.d.ts +7 -0
- package/dist/runtime/api/lib/server/task-service-singleton.js +58 -0
- package/dist/runtime/api/lib/server/vibing-orchestrator-singleton.d.ts +7 -0
- package/dist/runtime/api/lib/server/vibing-orchestrator-singleton.js +57 -0
- package/dist/runtime/api/lib/tiptap-utils.clamp-selection.test.d.ts +1 -0
- package/dist/runtime/api/lib/tiptap-utils.clamp-selection.test.js +27 -0
- package/dist/runtime/api/lib/tiptap-utils.d.ts +130 -0
- package/dist/runtime/api/lib/tiptap-utils.js +327 -0
- package/dist/runtime/api/lib/trpc/client.d.ts +1 -0
- package/dist/runtime/api/lib/trpc/client.js +5 -0
- package/dist/runtime/api/lib/trpc/server.d.ts +822 -0
- package/dist/runtime/api/lib/trpc/server.js +11 -0
- package/dist/runtime/api/lib/trpc/ws-server.d.ts +8 -0
- package/dist/runtime/api/lib/trpc/ws-server.js +33 -0
- package/dist/runtime/api/persistence/database-service.d.ts +14 -0
- package/dist/runtime/api/persistence/database-service.js +74 -0
- package/dist/runtime/api/persistence/execution-log-persistence.d.ts +90 -0
- package/dist/runtime/api/persistence/execution-log-persistence.js +410 -0
- package/dist/runtime/api/persistence/execution-log-persistence.test.d.ts +1 -0
- package/dist/runtime/api/persistence/execution-log-persistence.test.js +170 -0
- package/dist/runtime/api/router.d.ts +825 -0
- package/dist/runtime/api/router.js +56 -0
- package/dist/runtime/api/settings-service.d.ts +110 -0
- package/dist/runtime/api/settings-service.js +611 -0
- package/dist/runtime/api/tasks/file-watcher.d.ts +23 -0
- package/dist/runtime/api/tasks/file-watcher.js +88 -0
- package/dist/runtime/api/tasks/task-file-parser.d.ts +13 -0
- package/dist/runtime/api/tasks/task-file-parser.js +161 -0
- package/dist/runtime/api/tasks/task-service.d.ts +36 -0
- package/dist/runtime/api/tasks/task-service.js +173 -0
- package/dist/runtime/api/types/index.d.ts +179 -0
- package/dist/runtime/api/types/index.js +1 -0
- package/dist/runtime/api/types/settings.d.ts +81 -0
- package/dist/runtime/api/types/settings.js +2 -0
- package/dist/runtime/api/types.d.ts +2 -0
- package/dist/runtime/api/types.js +1 -0
- package/dist/runtime/api/utils/env.d.ts +6 -0
- package/dist/runtime/api/utils/env.js +12 -0
- package/dist/runtime/api/utils/stripNextEnv.d.ts +7 -0
- package/dist/runtime/api/utils/stripNextEnv.js +22 -0
- package/dist/runtime/api/utils/title-slug.d.ts +6 -0
- package/dist/runtime/api/utils/title-slug.js +77 -0
- package/dist/runtime/api/utils/url.d.ts +2 -0
- package/dist/runtime/api/utils/url.js +19 -0
- package/dist/runtime/api/vcs/git-history-service.d.ts +57 -0
- package/dist/runtime/api/vcs/git-history-service.js +228 -0
- package/dist/runtime/api/vcs/git-service.d.ts +127 -0
- package/dist/runtime/api/vcs/git-service.js +284 -0
- package/dist/runtime/api/vcs/worktree-service.d.ts +93 -0
- package/dist/runtime/api/vcs/worktree-service.js +506 -0
- package/dist/runtime/api/vcs/worktree-service.test.d.ts +1 -0
- package/dist/runtime/api/vcs/worktree-service.test.js +20 -0
- package/dist/runtime/api/workflows/quality-pipeline.d.ts +58 -0
- package/dist/runtime/api/workflows/quality-pipeline.js +400 -0
- package/dist/runtime/api/workflows/vibing-orchestrator.d.ts +313 -0
- package/dist/runtime/api/workflows/vibing-orchestrator.js +1861 -0
- package/dist/runtime/web/.next/BUILD_ID +1 -0
- package/dist/runtime/web/.next/app-build-manifest.json +59 -0
- package/dist/runtime/web/.next/app-path-routes-manifest.json +7 -0
- package/dist/runtime/web/.next/build-manifest.json +33 -0
- package/dist/runtime/web/.next/package.json +1 -0
- package/dist/runtime/web/.next/prerender-manifest.json +61 -0
- package/dist/runtime/web/.next/react-loadable-manifest.json +39 -0
- package/dist/runtime/web/.next/required-server-files.json +334 -0
- package/dist/runtime/web/.next/routes-manifest.json +62 -0
- package/dist/runtime/web/.next/server/app/_not-found/page.js +2 -0
- package/dist/runtime/web/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/dist/runtime/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
- package/dist/runtime/web/.next/server/app/_not-found.html +7 -0
- package/dist/runtime/web/.next/server/app/_not-found.meta +8 -0
- package/dist/runtime/web/.next/server/app/_not-found.rsc +22 -0
- package/dist/runtime/web/.next/server/app/api/health/route.js +1 -0
- package/dist/runtime/web/.next/server/app/api/health/route.js.nft.json +1 -0
- package/dist/runtime/web/.next/server/app/api/health/route_client-reference-manifest.js +1 -0
- package/dist/runtime/web/.next/server/app/api/images/[...path]/route.js +1 -0
- package/dist/runtime/web/.next/server/app/api/images/[...path]/route.js.nft.json +1 -0
- package/dist/runtime/web/.next/server/app/api/images/[...path]/route_client-reference-manifest.js +1 -0
- package/dist/runtime/web/.next/server/app/api/upload/route.js +1 -0
- package/dist/runtime/web/.next/server/app/api/upload/route.js.nft.json +1 -0
- package/dist/runtime/web/.next/server/app/api/upload/route_client-reference-manifest.js +1 -0
- package/dist/runtime/web/.next/server/app/index.html +7 -0
- package/dist/runtime/web/.next/server/app/index.meta +7 -0
- package/dist/runtime/web/.next/server/app/index.rsc +27 -0
- package/dist/runtime/web/.next/server/app/page.js +147 -0
- package/dist/runtime/web/.next/server/app/page.js.nft.json +1 -0
- package/dist/runtime/web/.next/server/app/page_client-reference-manifest.js +1 -0
- package/dist/runtime/web/.next/server/app-paths-manifest.json +7 -0
- package/dist/runtime/web/.next/server/chunks/217.js +1 -0
- package/dist/runtime/web/.next/server/chunks/383.js +6 -0
- package/dist/runtime/web/.next/server/chunks/458.js +1 -0
- package/dist/runtime/web/.next/server/chunks/576.js +18 -0
- package/dist/runtime/web/.next/server/chunks/635.js +22 -0
- package/dist/runtime/web/.next/server/chunks/761.js +1 -0
- package/dist/runtime/web/.next/server/chunks/777.js +3 -0
- package/dist/runtime/web/.next/server/chunks/825.js +1 -0
- package/dist/runtime/web/.next/server/chunks/838.js +1 -0
- package/dist/runtime/web/.next/server/chunks/973.js +15 -0
- package/dist/runtime/web/.next/server/functions-config-manifest.json +4 -0
- package/dist/runtime/web/.next/server/middleware-build-manifest.js +1 -0
- package/dist/runtime/web/.next/server/middleware-manifest.json +6 -0
- package/dist/runtime/web/.next/server/middleware-react-loadable-manifest.js +1 -0
- package/dist/runtime/web/.next/server/next-font-manifest.js +1 -0
- package/dist/runtime/web/.next/server/next-font-manifest.json +1 -0
- package/dist/runtime/web/.next/server/pages/404.html +7 -0
- package/dist/runtime/web/.next/server/pages/500.html +1 -0
- package/dist/runtime/web/.next/server/pages/_app.js +1 -0
- package/dist/runtime/web/.next/server/pages/_app.js.nft.json +1 -0
- package/dist/runtime/web/.next/server/pages/_document.js +1 -0
- package/dist/runtime/web/.next/server/pages/_document.js.nft.json +1 -0
- package/dist/runtime/web/.next/server/pages/_error.js +19 -0
- package/dist/runtime/web/.next/server/pages/_error.js.nft.json +1 -0
- package/dist/runtime/web/.next/server/pages-manifest.json +6 -0
- package/dist/runtime/web/.next/server/server-reference-manifest.js +1 -0
- package/dist/runtime/web/.next/server/server-reference-manifest.json +1 -0
- package/dist/runtime/web/.next/server/webpack-runtime.js +1 -0
- package/dist/runtime/web/.next/static/1HR8N0rJkCvFRtbTPJMyH/_buildManifest.js +1 -0
- package/dist/runtime/web/.next/static/1HR8N0rJkCvFRtbTPJMyH/_ssgManifest.js +1 -0
- package/dist/runtime/web/.next/static/chunks/18-15c10d3288afef2e.js +1 -0
- package/dist/runtime/web/.next/static/chunks/1c0ca389.537bbe362e3ffbd9.js +3 -0
- package/dist/runtime/web/.next/static/chunks/22747d63-ad5da0c19f4cfe41.js +71 -0
- package/dist/runtime/web/.next/static/chunks/277-0142a939f08738c3.js +63 -0
- package/dist/runtime/web/.next/static/chunks/355.056c2645878a799a.js +1 -0
- package/dist/runtime/web/.next/static/chunks/420.a5ccf151c9e2b2f1.js +1 -0
- package/dist/runtime/web/.next/static/chunks/439.1be0c6242fd248d5.js +15 -0
- package/dist/runtime/web/.next/static/chunks/440.c52e7c0f797e22b2.js +1 -0
- package/dist/runtime/web/.next/static/chunks/575-e2478287c27da87b.js +1 -0
- package/dist/runtime/web/.next/static/chunks/691.920d88c115087314.js +1 -0
- package/dist/runtime/web/.next/static/chunks/765-e838910065b50c3d.js +1 -0
- package/dist/runtime/web/.next/static/chunks/87c73c54-09e1ba5c70e60a51.js +1 -0
- package/dist/runtime/web/.next/static/chunks/891cff7f.0f71fc028f87e683.js +1 -0
- package/dist/runtime/web/.next/static/chunks/8bb4d8db-3e2aa02b0a2384b9.js +1 -0
- package/dist/runtime/web/.next/static/chunks/9af238c7-271a911d4e99ab18.js +1 -0
- package/dist/runtime/web/.next/static/chunks/app/_not-found/page-1cb74d1cba27d0ab.js +1 -0
- package/dist/runtime/web/.next/static/chunks/app/api/health/route-105a61ae865ba536.js +1 -0
- package/dist/runtime/web/.next/static/chunks/app/api/images/[...path]/route-105a61ae865ba536.js +1 -0
- package/dist/runtime/web/.next/static/chunks/app/api/upload/route-105a61ae865ba536.js +1 -0
- package/dist/runtime/web/.next/static/chunks/app/layout-dc0cfd29075b2160.js +1 -0
- package/dist/runtime/web/.next/static/chunks/app/page-f34a8b196b18850b.js +1 -0
- package/dist/runtime/web/.next/static/chunks/cac567b0-5b77dd12911823cd.js +1 -0
- package/dist/runtime/web/.next/static/chunks/framework-2518f1345b5b2806.js +1 -0
- package/dist/runtime/web/.next/static/chunks/main-17665e5e39de9a8a.js +1 -0
- package/dist/runtime/web/.next/static/chunks/main-app-c0b0f5ba4f7f9d75.js +1 -0
- package/dist/runtime/web/.next/static/chunks/pages/_app-d6f6b3bbc3d81ee1.js +1 -0
- package/dist/runtime/web/.next/static/chunks/pages/_error-75a96cf1997cc3b9.js +1 -0
- package/dist/runtime/web/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/dist/runtime/web/.next/static/chunks/webpack-c8de37305b4635cf.js +1 -0
- package/dist/runtime/web/.next/static/css/08c950681f1a9a92.css +1 -0
- package/dist/runtime/web/.next/static/css/2728291c68f99cb1.css +3 -0
- package/dist/runtime/web/.next/static/css/521bd69cc298cd1a.css +1 -0
- package/dist/runtime/web/.next/static/css/537e22821e101b87.css +1 -0
- package/dist/runtime/web/.next/static/media/19cfc7226ec3afaa-s.woff2 +0 -0
- package/dist/runtime/web/.next/static/media/21350d82a1f187e9-s.woff2 +0 -0
- package/dist/runtime/web/.next/static/media/8e9860b6e62d6359-s.woff2 +0 -0
- package/dist/runtime/web/.next/static/media/ba9851c3c22cd980-s.woff2 +0 -0
- package/dist/runtime/web/.next/static/media/c5fe6dc8356a8c31-s.woff2 +0 -0
- package/dist/runtime/web/.next/static/media/df0a9ae256c0569c-s.woff2 +0 -0
- package/dist/runtime/web/.next/static/media/e4af272ccee01ff0-s.p.woff2 +0 -0
- package/dist/runtime/web/package.json +65 -0
- package/dist/runtime/web/server.js +44 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +80 -7
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Routing Policy Management
|
|
3
|
+
* Handles provider selection per operation with fallbacks and configuration
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import fs from 'fs/promises';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { log } from '../lib/logger.js';
|
|
9
|
+
import { getSettingsService } from '../settings-service.js';
|
|
10
|
+
import { getVibeDir } from '../lib/server/project-root.js';
|
|
11
|
+
/**
|
|
12
|
+
* Generation options for AI execution
|
|
13
|
+
*/
|
|
14
|
+
export const GenerationOptionsSchema = z.object({
|
|
15
|
+
temperature: z.number().min(0).max(2).optional(),
|
|
16
|
+
maxTokens: z.number().positive().optional(),
|
|
17
|
+
tools: z.array(z.string()).optional(),
|
|
18
|
+
});
|
|
19
|
+
/**
|
|
20
|
+
* Per-operation routing configuration
|
|
21
|
+
*/
|
|
22
|
+
export const OperationConfigSchema = z.object({
|
|
23
|
+
provider: z.string(),
|
|
24
|
+
model: z.string().optional(),
|
|
25
|
+
options: GenerationOptionsSchema.optional(),
|
|
26
|
+
fallback: z.array(z.string()).optional(),
|
|
27
|
+
});
|
|
28
|
+
/**
|
|
29
|
+
* Complete routing policy schema
|
|
30
|
+
*/
|
|
31
|
+
export const RoutingPolicySchema = z.object({
|
|
32
|
+
defaultProvider: z.string(),
|
|
33
|
+
operations: z
|
|
34
|
+
.record(z.enum(['execute_task', 'improve_task', 'ai_codereview', 'ai_merge']), OperationConfigSchema)
|
|
35
|
+
.optional(),
|
|
36
|
+
});
|
|
37
|
+
/**
|
|
38
|
+
* Routing Policy Manager
|
|
39
|
+
* Manages AI provider routing policies with hot-reload capability
|
|
40
|
+
*/
|
|
41
|
+
export class RoutingPolicyManager {
|
|
42
|
+
constructor() {
|
|
43
|
+
this.policy = null;
|
|
44
|
+
this.lastModified = 0;
|
|
45
|
+
this.policyFilePath = path.join(getVibeDir(), 'ai-routing.json');
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get current effective policy with hot-reload
|
|
49
|
+
*/
|
|
50
|
+
async getPolicy() {
|
|
51
|
+
await this.loadPolicyIfChanged();
|
|
52
|
+
// Return default policy if none exists
|
|
53
|
+
if (!this.policy) {
|
|
54
|
+
const settings = getSettingsService().getSettings();
|
|
55
|
+
return {
|
|
56
|
+
defaultProvider: settings.agents.defaultProvider || 'claude-code',
|
|
57
|
+
operations: {},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return this.policy;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Update routing policy and persist to disk
|
|
64
|
+
*/
|
|
65
|
+
async updatePolicy(updates) {
|
|
66
|
+
const currentPolicy = await this.getPolicy();
|
|
67
|
+
const newPolicy = {
|
|
68
|
+
defaultProvider: updates.defaultProvider || currentPolicy.defaultProvider,
|
|
69
|
+
operations: {
|
|
70
|
+
...currentPolicy.operations,
|
|
71
|
+
...updates.operations,
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
// Validate the new policy
|
|
75
|
+
const validated = RoutingPolicySchema.parse(newPolicy);
|
|
76
|
+
// Ensure .vibeman directory exists
|
|
77
|
+
const vibemanDir = path.dirname(this.policyFilePath);
|
|
78
|
+
await fs.mkdir(vibemanDir, { recursive: true });
|
|
79
|
+
// Write to file
|
|
80
|
+
await fs.writeFile(this.policyFilePath, JSON.stringify(validated, null, 2), 'utf-8');
|
|
81
|
+
// Update in-memory policy
|
|
82
|
+
this.policy = validated;
|
|
83
|
+
this.lastModified = Date.now();
|
|
84
|
+
log.info('Updated AI routing policy', { policy: validated }, 'routing-policy');
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Resolve provider for a specific operation
|
|
88
|
+
*/
|
|
89
|
+
async resolveProviderForOperation(operation, overrides) {
|
|
90
|
+
const policy = await this.getPolicy();
|
|
91
|
+
const operationConfig = policy.operations?.[operation];
|
|
92
|
+
// Pull provider/model defaults from settings per operation
|
|
93
|
+
const settings = getSettingsService().getSettings();
|
|
94
|
+
const coding = settings.agents?.codingAgent;
|
|
95
|
+
const judge = settings.agents?.judgeAgent;
|
|
96
|
+
const settingsProviderModel = (() => {
|
|
97
|
+
switch (operation) {
|
|
98
|
+
case 'ai_codereview':
|
|
99
|
+
return { provider: judge?.provider, model: judge?.model };
|
|
100
|
+
case 'execute_task':
|
|
101
|
+
case 'improve_task':
|
|
102
|
+
case 'ai_merge':
|
|
103
|
+
default:
|
|
104
|
+
return { provider: coding?.provider, model: coding?.model };
|
|
105
|
+
}
|
|
106
|
+
})();
|
|
107
|
+
// Start with operation-specific config or fall back to settings, then default policy
|
|
108
|
+
const baseProvider = operationConfig?.provider || settingsProviderModel.provider || policy.defaultProvider;
|
|
109
|
+
const baseModel = operationConfig?.model || settingsProviderModel.model;
|
|
110
|
+
const baseOptions = operationConfig?.options;
|
|
111
|
+
const baseFallbacks = operationConfig?.fallback || [];
|
|
112
|
+
// Apply overrides
|
|
113
|
+
const resolved = {
|
|
114
|
+
provider: overrides?.provider || baseProvider,
|
|
115
|
+
model: overrides?.model || baseModel,
|
|
116
|
+
options: overrides?.options || baseOptions,
|
|
117
|
+
fallbacks: overrides?.fallbacks || baseFallbacks,
|
|
118
|
+
};
|
|
119
|
+
log.debug(`Resolved provider for ${operation}`, { operation, resolved }, 'routing-policy');
|
|
120
|
+
return resolved;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Set default provider
|
|
124
|
+
*/
|
|
125
|
+
async setDefaultProvider(provider) {
|
|
126
|
+
await this.updatePolicy({ defaultProvider: provider });
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Set operation-specific routing
|
|
130
|
+
*/
|
|
131
|
+
async setOperationConfig(operation, config) {
|
|
132
|
+
const currentPolicy = await this.getPolicy();
|
|
133
|
+
await this.updatePolicy({
|
|
134
|
+
operations: {
|
|
135
|
+
...currentPolicy.operations,
|
|
136
|
+
[operation]: config,
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Validate policy against available providers
|
|
142
|
+
*/
|
|
143
|
+
validatePolicy(policy, availableProviders) {
|
|
144
|
+
const errors = [];
|
|
145
|
+
// Check default provider
|
|
146
|
+
if (!availableProviders.has(policy.defaultProvider)) {
|
|
147
|
+
errors.push(`Default provider '${policy.defaultProvider}' is not available`);
|
|
148
|
+
}
|
|
149
|
+
// Check operation providers
|
|
150
|
+
if (policy.operations) {
|
|
151
|
+
for (const [operation, config] of Object.entries(policy.operations)) {
|
|
152
|
+
if (!availableProviders.has(config.provider)) {
|
|
153
|
+
errors.push(`Provider '${config.provider}' for operation '${operation}' is not available`);
|
|
154
|
+
}
|
|
155
|
+
// Check fallback providers
|
|
156
|
+
if (config.fallback) {
|
|
157
|
+
for (const fallbackProvider of config.fallback) {
|
|
158
|
+
if (!availableProviders.has(fallbackProvider)) {
|
|
159
|
+
errors.push(`Fallback provider '${fallbackProvider}' for operation '${operation}' is not available`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return errors;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Load policy from file if it has changed
|
|
169
|
+
*/
|
|
170
|
+
async loadPolicyIfChanged() {
|
|
171
|
+
try {
|
|
172
|
+
const stats = await fs.stat(this.policyFilePath);
|
|
173
|
+
const fileModified = stats.mtime.getTime();
|
|
174
|
+
// Only reload if file has changed
|
|
175
|
+
if (fileModified <= this.lastModified) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const content = await fs.readFile(this.policyFilePath, 'utf-8');
|
|
179
|
+
const parsed = JSON.parse(content);
|
|
180
|
+
const validated = RoutingPolicySchema.parse(parsed);
|
|
181
|
+
this.policy = validated;
|
|
182
|
+
this.lastModified = fileModified;
|
|
183
|
+
log.info('Loaded AI routing policy', { policy: validated }, 'routing-policy');
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
if (error.code === 'ENOENT') {
|
|
187
|
+
// File doesn't exist yet, use default
|
|
188
|
+
this.policy = null;
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
log.warn('Failed to load routing policy, using defaults', error, 'routing-policy');
|
|
192
|
+
this.policy = null;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Create example policy file if it doesn't exist
|
|
197
|
+
*/
|
|
198
|
+
async createExamplePolicy() {
|
|
199
|
+
const examplePath = path.join(getVibeDir(), 'ai-routing.example.json');
|
|
200
|
+
// Do not recreate if it already exists
|
|
201
|
+
try {
|
|
202
|
+
await fs.stat(examplePath);
|
|
203
|
+
return; // already exists; avoid noisy logs
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
if (err?.code && err.code !== 'ENOENT') {
|
|
207
|
+
log.warn('Unable to stat example AI routing policy', err, 'routing-policy');
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
const settings = getSettingsService().getSettings();
|
|
212
|
+
const example = {
|
|
213
|
+
defaultProvider: settings.agents.defaultProvider || 'claude-code',
|
|
214
|
+
operations: {
|
|
215
|
+
execute_task: {
|
|
216
|
+
provider: settings.agents.defaultProvider || 'claude-code',
|
|
217
|
+
model: 'claude-sonnet-4-20250514',
|
|
218
|
+
fallback: ['codex'],
|
|
219
|
+
},
|
|
220
|
+
improve_task: {
|
|
221
|
+
provider: settings.agents.defaultProvider || 'claude-code',
|
|
222
|
+
model: 'claude-sonnet-4-20250514',
|
|
223
|
+
},
|
|
224
|
+
ai_codereview: {
|
|
225
|
+
provider: 'codex',
|
|
226
|
+
model: 'gpt-5',
|
|
227
|
+
},
|
|
228
|
+
ai_merge: {
|
|
229
|
+
provider: settings.agents.defaultProvider || 'claude-code',
|
|
230
|
+
model: 'claude-sonnet-4-20250514',
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
// Ensure .vibeman directory exists
|
|
235
|
+
const vibemanDir = path.dirname(examplePath);
|
|
236
|
+
await fs.mkdir(vibemanDir, { recursive: true });
|
|
237
|
+
await fs.writeFile(examplePath, JSON.stringify(example, null, 2), 'utf-8');
|
|
238
|
+
log.info('Created example AI routing policy', { path: examplePath }, 'routing-policy');
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Get policy file path for external access
|
|
242
|
+
*/
|
|
243
|
+
getPolicyFilePath() {
|
|
244
|
+
return this.policyFilePath;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { TaskService } from '../tasks/task-service.js';
|
|
3
|
+
export declare const TaskIdSchema: z.ZodObject<{
|
|
4
|
+
taskId: z.ZodString;
|
|
5
|
+
}, "strip", z.ZodTypeAny, {
|
|
6
|
+
taskId: string;
|
|
7
|
+
}, {
|
|
8
|
+
taskId: string;
|
|
9
|
+
}>;
|
|
10
|
+
export declare const ExecutionIdSchema: z.ZodObject<{
|
|
11
|
+
executionId: z.ZodString;
|
|
12
|
+
}, "strip", z.ZodTypeAny, {
|
|
13
|
+
executionId: string;
|
|
14
|
+
}, {
|
|
15
|
+
executionId: string;
|
|
16
|
+
}>;
|
|
17
|
+
export declare const WorkflowIdSchema: z.ZodObject<{
|
|
18
|
+
workflowId: z.ZodString;
|
|
19
|
+
}, "strip", z.ZodTypeAny, {
|
|
20
|
+
workflowId: string;
|
|
21
|
+
}, {
|
|
22
|
+
workflowId: string;
|
|
23
|
+
}>;
|
|
24
|
+
export declare const WorktreePathSchema: z.ZodObject<{
|
|
25
|
+
worktreePath: z.ZodString;
|
|
26
|
+
}, "strip", z.ZodTypeAny, {
|
|
27
|
+
worktreePath: string;
|
|
28
|
+
}, {
|
|
29
|
+
worktreePath: string;
|
|
30
|
+
}>;
|
|
31
|
+
export declare const withErrors: <TArgs extends any[], TRes>(action: string, tag: string, fn: (...args: TArgs) => Promise<TRes>) => (...args: TArgs) => Promise<TRes>;
|
|
32
|
+
export declare function makeAssertTaskActive(taskService: TaskService): (id: string) => import("../types/index.js").Task;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { log } from '../lib/logger.js';
|
|
3
|
+
// Shared input schemas
|
|
4
|
+
export const TaskIdSchema = z.object({ taskId: z.string() });
|
|
5
|
+
export const ExecutionIdSchema = z.object({ executionId: z.string() });
|
|
6
|
+
export const WorkflowIdSchema = z.object({ workflowId: z.string() });
|
|
7
|
+
export const WorktreePathSchema = z.object({ worktreePath: z.string() });
|
|
8
|
+
// Centralized error formatter for consistent messages
|
|
9
|
+
export const withErrors = (action, tag, fn) => {
|
|
10
|
+
return async (...args) => {
|
|
11
|
+
try {
|
|
12
|
+
return await fn(...args);
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
log.error(`Error in ${action}`, error, tag);
|
|
16
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
17
|
+
throw new Error(`Failed to ${action}: ${msg}`);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
// Factory for active-task assertion to avoid repeating checks
|
|
22
|
+
export function makeAssertTaskActive(taskService) {
|
|
23
|
+
return (id) => {
|
|
24
|
+
const t = taskService.getTask(id);
|
|
25
|
+
if (!t)
|
|
26
|
+
throw new Error(`Task ${id} not found`);
|
|
27
|
+
if (t.deleted_at)
|
|
28
|
+
throw new Error(`Task ${id} is deleted`);
|
|
29
|
+
return t;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Router - Multi-Model Orchestration API
|
|
3
|
+
* Provides tRPC endpoints for managing AI providers and routing policies
|
|
4
|
+
*/
|
|
5
|
+
import type { AgentService } from '../../agent/agent-service.js';
|
|
6
|
+
import { type RoutingPolicy, type RoutableOperation } from '../../agent/routing-policy.js';
|
|
7
|
+
/**
|
|
8
|
+
* Build AI router with required dependencies
|
|
9
|
+
*/
|
|
10
|
+
export declare function buildAIRoutes(options: {
|
|
11
|
+
requireAgentService: () => AgentService;
|
|
12
|
+
}): {
|
|
13
|
+
/**
|
|
14
|
+
* List all registered AI providers with health status
|
|
15
|
+
*/
|
|
16
|
+
listProviders: import("@trpc/server").TRPCQueryProcedure<{
|
|
17
|
+
input: void;
|
|
18
|
+
output: {
|
|
19
|
+
name: string;
|
|
20
|
+
displayName: string;
|
|
21
|
+
available: boolean;
|
|
22
|
+
error: string | undefined;
|
|
23
|
+
capabilities: import("../../agent/ai-providers/types.js").ProviderCapabilities;
|
|
24
|
+
models: import("../../agent/ai-providers/types.js").ModelInfo[];
|
|
25
|
+
}[];
|
|
26
|
+
meta: object;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* List available models from providers
|
|
30
|
+
*/
|
|
31
|
+
listModels: import("@trpc/server").TRPCQueryProcedure<{
|
|
32
|
+
input: {
|
|
33
|
+
provider?: string | undefined;
|
|
34
|
+
} | undefined;
|
|
35
|
+
output: import("../../agent/ai-providers/types.js").ModelInfo[];
|
|
36
|
+
meta: object;
|
|
37
|
+
}>;
|
|
38
|
+
/**
|
|
39
|
+
* Get current routing policy
|
|
40
|
+
*/
|
|
41
|
+
getRoutingPolicy: import("@trpc/server").TRPCQueryProcedure<{
|
|
42
|
+
input: void;
|
|
43
|
+
output: any;
|
|
44
|
+
meta: object;
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Update routing policy
|
|
48
|
+
*/
|
|
49
|
+
updateRoutingPolicy: import("@trpc/server").TRPCMutationProcedure<{
|
|
50
|
+
input: {
|
|
51
|
+
policy: {
|
|
52
|
+
defaultProvider?: string | undefined;
|
|
53
|
+
operations?: Partial<Record<"execute_task" | "improve_task" | "ai_codereview" | "ai_merge", {
|
|
54
|
+
provider: string;
|
|
55
|
+
options?: {
|
|
56
|
+
maxTokens?: number | undefined;
|
|
57
|
+
tools?: string[] | undefined;
|
|
58
|
+
temperature?: number | undefined;
|
|
59
|
+
} | undefined;
|
|
60
|
+
model?: string | undefined;
|
|
61
|
+
fallback?: string[] | undefined;
|
|
62
|
+
}>> | undefined;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
output: {
|
|
66
|
+
success: boolean;
|
|
67
|
+
policy: any;
|
|
68
|
+
};
|
|
69
|
+
meta: object;
|
|
70
|
+
}>;
|
|
71
|
+
/**
|
|
72
|
+
* Set default provider
|
|
73
|
+
*/
|
|
74
|
+
setDefaultProvider: import("@trpc/server").TRPCMutationProcedure<{
|
|
75
|
+
input: {
|
|
76
|
+
provider: string;
|
|
77
|
+
};
|
|
78
|
+
output: {
|
|
79
|
+
success: boolean;
|
|
80
|
+
provider: string;
|
|
81
|
+
};
|
|
82
|
+
meta: object;
|
|
83
|
+
}>;
|
|
84
|
+
/**
|
|
85
|
+
* Set operation-specific configuration
|
|
86
|
+
*/
|
|
87
|
+
setOperationConfig: import("@trpc/server").TRPCMutationProcedure<{
|
|
88
|
+
input: {
|
|
89
|
+
config: {
|
|
90
|
+
provider: string;
|
|
91
|
+
options?: {
|
|
92
|
+
maxTokens?: number | undefined;
|
|
93
|
+
tools?: string[] | undefined;
|
|
94
|
+
temperature?: number | undefined;
|
|
95
|
+
} | undefined;
|
|
96
|
+
model?: string | undefined;
|
|
97
|
+
fallback?: string[] | undefined;
|
|
98
|
+
};
|
|
99
|
+
operation: "execute_task" | "improve_task" | "ai_codereview" | "ai_merge";
|
|
100
|
+
};
|
|
101
|
+
output: {
|
|
102
|
+
success: boolean;
|
|
103
|
+
};
|
|
104
|
+
meta: object;
|
|
105
|
+
}>;
|
|
106
|
+
/**
|
|
107
|
+
* Validate provider setup and refresh health status
|
|
108
|
+
*/
|
|
109
|
+
validateProviders: import("@trpc/server").TRPCMutationProcedure<{
|
|
110
|
+
input: {
|
|
111
|
+
force?: boolean | undefined;
|
|
112
|
+
} | undefined;
|
|
113
|
+
output: {
|
|
114
|
+
success: boolean;
|
|
115
|
+
results: {
|
|
116
|
+
provider: string;
|
|
117
|
+
available: boolean;
|
|
118
|
+
error: string | undefined;
|
|
119
|
+
modelCount: number;
|
|
120
|
+
capabilities: import("../../agent/ai-providers/types.js").ProviderCapabilities;
|
|
121
|
+
}[];
|
|
122
|
+
totalProviders: number;
|
|
123
|
+
availableProviders: number;
|
|
124
|
+
};
|
|
125
|
+
meta: object;
|
|
126
|
+
}>;
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* Test-friendly plain handlers mirroring the AI routes, without tRPC wrappers.
|
|
130
|
+
* Useful for unit tests that call functions directly.
|
|
131
|
+
*/
|
|
132
|
+
export declare function buildAIRouteHandlers(options: {
|
|
133
|
+
requireAgentService: () => AgentService;
|
|
134
|
+
}): {
|
|
135
|
+
readonly listProviders: () => Promise<{
|
|
136
|
+
name: string;
|
|
137
|
+
displayName: any;
|
|
138
|
+
available: boolean;
|
|
139
|
+
error: string | undefined;
|
|
140
|
+
capabilities: any;
|
|
141
|
+
models: import("../../agent/ai-providers/types.js").ModelInfo[];
|
|
142
|
+
}[]>;
|
|
143
|
+
readonly listModels: (input?: {
|
|
144
|
+
provider?: string;
|
|
145
|
+
}) => Promise<any>;
|
|
146
|
+
readonly getRoutingPolicy: () => Promise<any>;
|
|
147
|
+
readonly updateRoutingPolicy: (input: {
|
|
148
|
+
policy: Partial<RoutingPolicy>;
|
|
149
|
+
}) => Promise<{
|
|
150
|
+
readonly success: true;
|
|
151
|
+
readonly policy: any;
|
|
152
|
+
}>;
|
|
153
|
+
readonly setDefaultProvider: (input: {
|
|
154
|
+
provider: string;
|
|
155
|
+
}) => Promise<{
|
|
156
|
+
readonly success: true;
|
|
157
|
+
readonly provider: string;
|
|
158
|
+
}>;
|
|
159
|
+
readonly setOperationConfig: (input: {
|
|
160
|
+
operation: RoutableOperation;
|
|
161
|
+
config: any;
|
|
162
|
+
}) => Promise<{
|
|
163
|
+
readonly success: true;
|
|
164
|
+
}>;
|
|
165
|
+
readonly validateProviders: () => Promise<{
|
|
166
|
+
success: true;
|
|
167
|
+
results: {
|
|
168
|
+
provider: string;
|
|
169
|
+
available: boolean;
|
|
170
|
+
error: string | undefined;
|
|
171
|
+
modelCount: number;
|
|
172
|
+
capabilities: import("../../agent/ai-providers/types.js").ProviderCapabilities;
|
|
173
|
+
}[];
|
|
174
|
+
totalProviders: number;
|
|
175
|
+
availableProviders: number;
|
|
176
|
+
}>;
|
|
177
|
+
readonly getProviderHealth: () => Promise<{
|
|
178
|
+
totalProviders: number;
|
|
179
|
+
availableProviders: number;
|
|
180
|
+
unavailableProviders: number;
|
|
181
|
+
providers: Array<{
|
|
182
|
+
name: string;
|
|
183
|
+
available: boolean;
|
|
184
|
+
error?: string;
|
|
185
|
+
modelCount: number;
|
|
186
|
+
}>;
|
|
187
|
+
}>;
|
|
188
|
+
};
|