vibe-coding-master 0.3.10 → 0.3.12
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 +2 -1
- package/dist/backend/api/codex-hook-routes.js +7 -0
- package/dist/backend/api/codex-translation-routes.js +50 -0
- package/dist/backend/cli/install-vcm-harness.js +29 -1
- package/dist/backend/server.js +17 -2
- package/dist/backend/services/artifact-service.js +2 -1
- package/dist/backend/services/codex-hook-service.js +12 -9
- package/dist/backend/services/codex-translation-service.js +964 -0
- package/dist/backend/services/harness-service.js +28 -1
- package/dist/backend/services/session-service.js +128 -36
- package/dist/backend/services/translation-service.js +120 -35
- package/dist/backend/templates/harness/codex-review.js +68 -3
- package/dist/shared/constants.js +15 -1
- package/dist-frontend/assets/index-B13y-ZM8.css +32 -0
- package/dist-frontend/assets/index-C7Nb1xPJ.js +92 -0
- package/dist-frontend/index.html +2 -2
- package/docs/codex-review-gates.md +24 -5
- package/docs/codex-translation-plan.md +1184 -0
- package/package.json +1 -1
- package/dist-frontend/assets/index-CR1EOe-w.css +0 -32
- package/dist-frontend/assets/index-D-6FVz_K.js +0 -92
- package/docs/codex-file-translation-plan.md +0 -618
package/README.md
CHANGED
|
@@ -142,6 +142,7 @@ Important container notes:
|
|
|
142
142
|
- Make sure the container has network access to Claude services and to the translation provider if translation is enabled.
|
|
143
143
|
- VCM accepts normal Git repositories by checking `.git` directly. It also supports `.git` files that point to worktree gitdirs.
|
|
144
144
|
- VCM uses per-command `git -c safe.directory=...` for Git metadata reads and does not require global `git config --global --add safe.directory`.
|
|
145
|
+
- Set `VCM_SANDBOX=devcontainer` so VCM-managed Codex Reviewer sessions rely on the container boundary and do not start Codex's nested Linux sandbox.
|
|
145
146
|
- Treat the container as the sandbox boundary, especially when using relaxed Claude Code permission modes.
|
|
146
147
|
|
|
147
148
|
## Basic Usage
|
|
@@ -389,7 +390,7 @@ Translation settings are local and stored in:
|
|
|
389
390
|
|
|
390
391
|
The same file stores recent repository paths. The translation API key is stored locally under `translation.secrets.apiKey`; it is not written to the connected repository, `.ai/vcm/handoffs`, raw terminal logs, or git diffs.
|
|
391
392
|
|
|
392
|
-
VCM resolves `vcmDataDir` from `VCM_DATA_DIR`. If `VCM_DATA_DIR` is unset or empty, VCM uses `~/.vcm`. In Dev Containers, set `VCM_DATA_DIR=/workspace/.ai/vcm` through `containerEnv` so VCM app state survives container rebuilds.
|
|
393
|
+
VCM resolves `vcmDataDir` from `VCM_DATA_DIR`. If `VCM_DATA_DIR` is unset or empty, VCM uses `~/.vcm`. In Dev Containers, set `VCM_DATA_DIR=/workspace/.ai/vcm` and `VCM_SANDBOX=devcontainer` through `containerEnv` so VCM app state survives container rebuilds and VCM-managed Codex Reviewer sessions do not run a nested Codex sandbox.
|
|
393
394
|
|
|
394
395
|
The sidebar `Settings` section also stores the UI theme preference in this file. The default is `system`, which follows the OS/browser color-scheme preference; users can cycle between `System`, `Light`, and `Dark`.
|
|
395
396
|
|
|
@@ -6,4 +6,11 @@ export function registerCodexHookRoutes(app, deps) {
|
|
|
6
6
|
await deps.codexHookService.handleStopHook(request.body);
|
|
7
7
|
return {};
|
|
8
8
|
});
|
|
9
|
+
app.post("/api/hooks/codex-translator", async (request) => {
|
|
10
|
+
return deps.codexHookService.handleHook(request.body);
|
|
11
|
+
});
|
|
12
|
+
app.post("/api/hooks/codex-translator/stop", async (request) => {
|
|
13
|
+
await deps.codexHookService.handleStopHook(request.body);
|
|
14
|
+
return {};
|
|
15
|
+
});
|
|
9
16
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { VcmError } from "../errors.js";
|
|
2
|
+
export function registerCodexTranslationRoutes(app, deps) {
|
|
3
|
+
app.get("/api/translation/codex/state", async () => {
|
|
4
|
+
const project = await requireCurrentProject(deps.projectService);
|
|
5
|
+
return deps.codexTranslationService.getState(project.repoRoot);
|
|
6
|
+
});
|
|
7
|
+
app.get("/api/translation/codex/source-files", async (request) => {
|
|
8
|
+
const project = await requireCurrentProject(deps.projectService);
|
|
9
|
+
return deps.codexTranslationService.browseSourceFiles(project.repoRoot, {
|
|
10
|
+
path: request.query.path,
|
|
11
|
+
query: request.query.query,
|
|
12
|
+
limit: request.query.limit === undefined ? undefined : Number(request.query.limit)
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
app.post("/api/translation/codex/files", async (request) => {
|
|
16
|
+
const project = await requireCurrentProject(deps.projectService);
|
|
17
|
+
return deps.codexTranslationService.createFileJob(project.repoRoot, request.body);
|
|
18
|
+
});
|
|
19
|
+
app.post("/api/translation/codex/bootstrap", async (request) => {
|
|
20
|
+
const project = await requireCurrentProject(deps.projectService);
|
|
21
|
+
return deps.codexTranslationService.createBootstrapRun(project.repoRoot, request.body);
|
|
22
|
+
});
|
|
23
|
+
app.get("/api/translation/codex/files/:jobId", async (request) => {
|
|
24
|
+
const project = await requireCurrentProject(deps.projectService);
|
|
25
|
+
return deps.codexTranslationService.readFileJobOutput(project.repoRoot, request.params.jobId);
|
|
26
|
+
});
|
|
27
|
+
app.post("/api/translation/codex/files/:jobId/promote", async (request) => {
|
|
28
|
+
const project = await requireCurrentProject(deps.projectService);
|
|
29
|
+
const targetPath = request.body?.targetPath?.trim();
|
|
30
|
+
if (!targetPath) {
|
|
31
|
+
throw new VcmError({
|
|
32
|
+
code: "TRANSLATION_PROMOTE_TARGET_REQUIRED",
|
|
33
|
+
message: "Promote target path is required.",
|
|
34
|
+
statusCode: 400
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return deps.codexTranslationService.promoteFileJob(project.repoRoot, request.params.jobId, targetPath);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
async function requireCurrentProject(projectService) {
|
|
41
|
+
const project = await projectService.getCurrentProject();
|
|
42
|
+
if (!project) {
|
|
43
|
+
throw new VcmError({
|
|
44
|
+
code: "PROJECT_NOT_CONNECTED",
|
|
45
|
+
message: "Connect a repository first.",
|
|
46
|
+
statusCode: 409
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return project;
|
|
50
|
+
}
|
|
@@ -6,7 +6,7 @@ import process from "node:process";
|
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { renderArchitectHarnessRules } from "../templates/harness/architect-agent.js";
|
|
8
8
|
import { renderCoderHarnessRules } from "../templates/harness/coder-agent.js";
|
|
9
|
-
import { renderCodexAgentsHarnessRules, renderCodexArchitecturePlanPrompt, renderCodexCliConfigHarnessRules, renderCodexConfigHarnessRules, renderCodexFinalDiffPrompt, renderCodexHooksHarnessRules, renderCodexReviewResultSchema, renderCodexValidationAdequacyPrompt, renderRequestCodexReviewTool, renderVcmCodexReviewGateSkillRules } from "../templates/harness/codex-review.js";
|
|
9
|
+
import { renderCodexAgentsHarnessRules, renderCodexArchitecturePlanPrompt, renderCodexCliConfigHarnessRules, renderCodexConfigHarnessRules, renderCodexFinalDiffPrompt, renderCodexHooksHarnessRules, renderCodexReviewResultSchema, renderCodexTranslatorAgentsHarnessRules, renderCodexTranslatorConfigHarnessRules, renderCodexValidationAdequacyPrompt, renderRequestCodexReviewTool, renderVcmCodexReviewGateSkillRules } from "../templates/harness/codex-review.js";
|
|
10
10
|
import { renderRootClaudeHarnessRules } from "../templates/harness/claude-root.js";
|
|
11
11
|
import { renderGitignoreHarnessRules } from "../templates/harness/gitignore.js";
|
|
12
12
|
import { renderProjectManagerHarnessRules } from "../templates/harness/project-manager-agent.js";
|
|
@@ -109,6 +109,13 @@ const MANAGED_FILES = [
|
|
|
109
109
|
commentStyle: "html",
|
|
110
110
|
category: "codex-reviewer-agent",
|
|
111
111
|
content: renderCodexAgentsHarnessRules()
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
path: ".ai/codex-translator/AGENTS.md",
|
|
115
|
+
title: "VCM Codex Translator",
|
|
116
|
+
commentStyle: "html",
|
|
117
|
+
category: "codex-translator-agent",
|
|
118
|
+
content: renderCodexTranslatorAgentsHarnessRules()
|
|
112
119
|
}
|
|
113
120
|
];
|
|
114
121
|
const DURABLE_DOC_TEMPLATES = [
|
|
@@ -186,6 +193,24 @@ const WHOLE_FILES = [
|
|
|
186
193
|
mode: 0o644,
|
|
187
194
|
content: renderCodexHooksHarnessRules()
|
|
188
195
|
},
|
|
196
|
+
{
|
|
197
|
+
path: ".ai/codex-translator/config.toml",
|
|
198
|
+
category: "codex-translator-config",
|
|
199
|
+
mode: 0o644,
|
|
200
|
+
content: renderCodexTranslatorConfigHarnessRules()
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
path: ".ai/codex-translator/.codex/config.toml",
|
|
204
|
+
category: "codex-translator-hooks",
|
|
205
|
+
mode: 0o644,
|
|
206
|
+
content: renderCodexCliConfigHarnessRules()
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
path: ".ai/codex-translator/.codex/hooks.json",
|
|
210
|
+
category: "codex-translator-hooks",
|
|
211
|
+
mode: 0o644,
|
|
212
|
+
content: renderCodexHooksHarnessRules("codex-translator")
|
|
213
|
+
},
|
|
189
214
|
{
|
|
190
215
|
path: ".ai/codex/prompts/architecture-plan-gate.md",
|
|
191
216
|
category: "codex-review-prompt",
|
|
@@ -432,6 +457,9 @@ function fixedDirectories() {
|
|
|
432
457
|
".ai/codex/.codex/",
|
|
433
458
|
".ai/codex/prompts/",
|
|
434
459
|
".ai/codex/schemas/",
|
|
460
|
+
".ai/codex-translator/",
|
|
461
|
+
".ai/codex-translator/.codex/",
|
|
462
|
+
".ai/vcm/translations/",
|
|
435
463
|
".ai/vcm/codex-reviews/",
|
|
436
464
|
".ai/tools/",
|
|
437
465
|
".ai/generated/"
|
package/dist/backend/server.js
CHANGED
|
@@ -12,6 +12,7 @@ import { createGitAdapter } from "./adapters/git-adapter.js";
|
|
|
12
12
|
import { createAppSettingsService } from "./services/app-settings-service.js";
|
|
13
13
|
import { createClaudeTranscriptService } from "./services/claude-transcript-service.js";
|
|
14
14
|
import { createCodexReviewService } from "./services/codex-review-service.js";
|
|
15
|
+
import { createCodexTranslationService } from "./services/codex-translation-service.js";
|
|
15
16
|
import { createHarnessService, createScriptFixedHarnessInstaller } from "./services/harness-service.js";
|
|
16
17
|
import { createNodeFileSystemAdapter } from "./adapters/filesystem.js";
|
|
17
18
|
import { createNodePtyTerminalRuntime } from "./runtime/node-pty-runtime.js";
|
|
@@ -37,6 +38,7 @@ import { registerArtifactRoutes } from "./api/artifact-routes.js";
|
|
|
37
38
|
import { registerClaudeHookRoutes } from "./api/claude-hook-routes.js";
|
|
38
39
|
import { registerCodexHookRoutes } from "./api/codex-hook-routes.js";
|
|
39
40
|
import { registerCodexReviewRoutes } from "./api/codex-review-routes.js";
|
|
41
|
+
import { registerCodexTranslationRoutes } from "./api/codex-translation-routes.js";
|
|
40
42
|
import { registerHarnessRoutes } from "./api/harness-routes.js";
|
|
41
43
|
import { registerMessageRoutes } from "./api/message-routes.js";
|
|
42
44
|
import { registerProjectRoutes } from "./api/project-routes.js";
|
|
@@ -69,6 +71,10 @@ export async function createServer(deps, options = {}) {
|
|
|
69
71
|
projectService: deps.projectService,
|
|
70
72
|
codexReviewService: deps.codexReviewService
|
|
71
73
|
});
|
|
74
|
+
registerCodexTranslationRoutes(app, {
|
|
75
|
+
projectService: deps.projectService,
|
|
76
|
+
codexTranslationService: deps.codexTranslationService
|
|
77
|
+
});
|
|
72
78
|
registerProjectRoutes(app, { projectService: deps.projectService });
|
|
73
79
|
registerHarnessRoutes(app, {
|
|
74
80
|
projectService: deps.projectService,
|
|
@@ -169,7 +175,8 @@ export function createDefaultServerDeps(options = {}) {
|
|
|
169
175
|
artifactService,
|
|
170
176
|
projectService,
|
|
171
177
|
taskService,
|
|
172
|
-
apiUrl: options.apiUrl
|
|
178
|
+
apiUrl: options.apiUrl,
|
|
179
|
+
sandboxMode: process.env.VCM_SANDBOX
|
|
173
180
|
});
|
|
174
181
|
const commandDispatcher = createCommandDispatcher({
|
|
175
182
|
runtime,
|
|
@@ -205,12 +212,18 @@ export function createDefaultServerDeps(options = {}) {
|
|
|
205
212
|
sessionService,
|
|
206
213
|
roundService
|
|
207
214
|
});
|
|
215
|
+
const codexTranslationService = createCodexTranslationService({
|
|
216
|
+
fs,
|
|
217
|
+
runtime,
|
|
218
|
+
sessionService
|
|
219
|
+
});
|
|
208
220
|
const transcripts = createClaudeTranscriptService();
|
|
209
221
|
const translationService = createTranslationService({
|
|
210
222
|
runtime,
|
|
211
223
|
sessionRegistry: registry,
|
|
212
224
|
transcripts,
|
|
213
225
|
sessionService,
|
|
226
|
+
codexTranslationService,
|
|
214
227
|
fs,
|
|
215
228
|
projectService,
|
|
216
229
|
appSettings,
|
|
@@ -250,7 +263,8 @@ export function createDefaultServerDeps(options = {}) {
|
|
|
250
263
|
projectService,
|
|
251
264
|
taskService,
|
|
252
265
|
sessionService,
|
|
253
|
-
roundService
|
|
266
|
+
roundService,
|
|
267
|
+
codexTranslationService
|
|
254
268
|
});
|
|
255
269
|
const diagnosticsService = createDiagnosticsService({
|
|
256
270
|
appRoot: getAppRoot(),
|
|
@@ -270,6 +284,7 @@ export function createDefaultServerDeps(options = {}) {
|
|
|
270
284
|
codexHookService,
|
|
271
285
|
messageService,
|
|
272
286
|
codexReviewService,
|
|
287
|
+
codexTranslationService,
|
|
273
288
|
roundService,
|
|
274
289
|
statusService,
|
|
275
290
|
translationService,
|
|
@@ -42,7 +42,8 @@ export function createArtifactService(fs) {
|
|
|
42
42
|
architect: path.posix.join(logsDir, "architect.log"),
|
|
43
43
|
coder: path.posix.join(logsDir, "coder.log"),
|
|
44
44
|
reviewer: path.posix.join(logsDir, "reviewer.log"),
|
|
45
|
-
"codex-reviewer": path.posix.join(logsDir, "codex-reviewer.log")
|
|
45
|
+
"codex-reviewer": path.posix.join(logsDir, "codex-reviewer.log"),
|
|
46
|
+
"codex-translator": path.posix.join(logsDir, "codex-translator.log")
|
|
46
47
|
},
|
|
47
48
|
messageRoutePaths: getDefaultMessageRoutePaths(messagesDir),
|
|
48
49
|
architecturePlanPath: path.posix.join(handoffDir, "architecture-plan.md"),
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { isCodexRoleName } from "../../shared/constants.js";
|
|
1
2
|
import { VcmError } from "../errors.js";
|
|
2
3
|
import { getTaskRuntimeRepoRoot } from "./task-service.js";
|
|
3
|
-
const CODEX_REVIEWER_ROLE = "codex-reviewer";
|
|
4
4
|
export function createCodexHookService(deps) {
|
|
5
5
|
async function getHookContext(input) {
|
|
6
|
-
if (input.role
|
|
6
|
+
if (!isCodexRoleName(input.role)) {
|
|
7
7
|
throw new VcmError({
|
|
8
8
|
code: "CODEX_HOOK_ROLE_INVALID",
|
|
9
9
|
message: `Unknown Codex hook role: ${input.role}`,
|
|
@@ -14,7 +14,7 @@ export function createCodexHookService(deps) {
|
|
|
14
14
|
if (!project) {
|
|
15
15
|
throw new VcmError({
|
|
16
16
|
code: "PROJECT_NOT_CONNECTED",
|
|
17
|
-
message: "Connect a repository before accepting Codex
|
|
17
|
+
message: "Connect a repository before accepting Codex hooks.",
|
|
18
18
|
statusCode: 409
|
|
19
19
|
});
|
|
20
20
|
}
|
|
@@ -32,14 +32,14 @@ export function createCodexHookService(deps) {
|
|
|
32
32
|
if (eventName !== expectedEventName) {
|
|
33
33
|
throw new VcmError({
|
|
34
34
|
code: "CODEX_HOOK_EVENT_UNSUPPORTED",
|
|
35
|
-
message: `Unsupported Codex
|
|
35
|
+
message: `Unsupported Codex hook event for this endpoint: ${eventName}`,
|
|
36
36
|
statusCode: 400
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
const context = await getHookContext(input);
|
|
40
40
|
const session = await deps.sessionService.recordRoleHookEvent(context.project.repoRoot, {
|
|
41
41
|
taskSlug: input.taskSlug,
|
|
42
|
-
role:
|
|
42
|
+
role: input.role,
|
|
43
43
|
eventName,
|
|
44
44
|
sessionId: stringOrUndefined(input.event.session_id),
|
|
45
45
|
transcriptPath: stringOrUndefined(input.event.transcript_path),
|
|
@@ -51,14 +51,17 @@ export function createCodexHookService(deps) {
|
|
|
51
51
|
stateRepoRoot: context.taskRepoRoot,
|
|
52
52
|
stateRoot: context.config.stateRoot,
|
|
53
53
|
taskSlug: input.taskSlug,
|
|
54
|
-
role:
|
|
54
|
+
role: input.role,
|
|
55
55
|
eventName
|
|
56
56
|
});
|
|
57
|
+
if (input.role === "codex-translator") {
|
|
58
|
+
await deps.codexTranslationService?.handleCodexHook(context.project.repoRoot, eventName, input.taskSlug);
|
|
59
|
+
}
|
|
57
60
|
return {
|
|
58
61
|
ok: true,
|
|
59
62
|
eventName,
|
|
60
63
|
taskSlug: input.taskSlug,
|
|
61
|
-
role:
|
|
64
|
+
role: input.role,
|
|
62
65
|
sessionUpdated: Boolean(session)
|
|
63
66
|
};
|
|
64
67
|
}
|
|
@@ -77,9 +80,9 @@ function parseHookEvent(value) {
|
|
|
77
80
|
}
|
|
78
81
|
throw new VcmError({
|
|
79
82
|
code: "CODEX_HOOK_EVENT_UNSUPPORTED",
|
|
80
|
-
message: `Unsupported Codex
|
|
83
|
+
message: `Unsupported Codex hook event: ${String(value)}`,
|
|
81
84
|
statusCode: 400,
|
|
82
|
-
hint: "VCM accepts Codex
|
|
85
|
+
hint: "VCM accepts Codex UserPromptSubmit and Stop hooks only."
|
|
83
86
|
});
|
|
84
87
|
}
|
|
85
88
|
function stringOrUndefined(value) {
|