vibe-coding-master 0.0.5 → 0.0.7
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 +168 -63
- package/dist/backend/adapters/translation-provider.js +145 -0
- package/dist/backend/api/artifact-routes.js +3 -0
- package/dist/backend/api/harness-routes.js +22 -0
- package/dist/backend/api/project-routes.js +3 -8
- package/dist/backend/api/translation-routes.js +70 -0
- package/dist/backend/runtime/node-pty-runtime.js +20 -18
- package/dist/backend/server.js +31 -1
- package/dist/backend/services/app-settings-service.js +128 -0
- package/dist/backend/services/artifact-service.js +7 -4
- package/dist/backend/services/claude-transcript-service.js +509 -0
- package/dist/backend/services/harness-service.js +178 -0
- package/dist/backend/services/project-service.js +4 -0
- package/dist/backend/services/session-service.js +7 -5
- package/dist/backend/services/status-service.js +76 -0
- package/dist/backend/services/translation-prompts.js +173 -0
- package/dist/backend/services/translation-queue.js +39 -0
- package/dist/backend/services/translation-service.js +546 -0
- package/dist/backend/templates/handoff.js +32 -0
- package/dist/backend/templates/harness/architect-agent.js +12 -0
- package/dist/backend/templates/harness/claude-root.js +14 -0
- package/dist/backend/templates/harness/coder-agent.js +11 -0
- package/dist/backend/templates/harness/project-manager-agent.js +14 -0
- package/dist/backend/templates/harness/reviewer-agent.js +13 -0
- package/dist/backend/ws/translation-ws.js +35 -0
- package/dist/shared/types/harness.js +1 -0
- package/dist/shared/types/translation.js +5 -0
- package/dist/shared/validation/artifact-check.js +15 -1
- package/dist/shared/validation/language-detect.js +46 -0
- package/dist-frontend/assets/index-BNASqKEK.css +32 -0
- package/dist-frontend/assets/index-Bp49_End.js +58 -0
- package/dist-frontend/index.html +2 -2
- package/docs/cc-best-practices.md +93 -36
- package/docs/product-design.md +313 -1408
- package/docs/v1-architecture-design.md +500 -1153
- package/docs/v1-implementation-plan.md +783 -1604
- package/package.json +3 -1
- package/scripts/verify-package.mjs +121 -0
- package/dist/backend/templates/role-messaging-context.js +0 -44
- package/dist-frontend/assets/index-Bah6k-Ix.css +0 -32
- package/dist-frontend/assets/index-EMaQuIB6.js +0 -58
- package/docs/v1-message-bus-orchestration-design.md +0 -534
package/dist/backend/server.js
CHANGED
|
@@ -8,20 +8,28 @@ import { createClaudeAdapter } from "./adapters/claude-adapter.js";
|
|
|
8
8
|
import { createCommandRunner } from "./adapters/command-runner.js";
|
|
9
9
|
import { createCommandDispatcher } from "./services/command-dispatcher.js";
|
|
10
10
|
import { createGitAdapter } from "./adapters/git-adapter.js";
|
|
11
|
+
import { createAppSettingsService } from "./services/app-settings-service.js";
|
|
12
|
+
import { createClaudeTranscriptService } from "./services/claude-transcript-service.js";
|
|
13
|
+
import { createHarnessService } from "./services/harness-service.js";
|
|
11
14
|
import { createNodeFileSystemAdapter } from "./adapters/filesystem.js";
|
|
12
15
|
import { createNodePtyTerminalRuntime } from "./runtime/node-pty-runtime.js";
|
|
16
|
+
import { createOpenAiCompatibleTranslationProvider } from "./adapters/translation-provider.js";
|
|
13
17
|
import { createProjectService } from "./services/project-service.js";
|
|
14
18
|
import { createSessionRegistry } from "./runtime/session-registry.js";
|
|
15
19
|
import { createSessionService } from "./services/session-service.js";
|
|
16
20
|
import { createMessageService } from "./services/message-service.js";
|
|
17
21
|
import { createStatusService } from "./services/status-service.js";
|
|
18
22
|
import { createTaskService } from "./services/task-service.js";
|
|
23
|
+
import { createTranslationService } from "./services/translation-service.js";
|
|
19
24
|
import { registerArtifactRoutes } from "./api/artifact-routes.js";
|
|
25
|
+
import { registerHarnessRoutes } from "./api/harness-routes.js";
|
|
20
26
|
import { registerMessageRoutes } from "./api/message-routes.js";
|
|
21
27
|
import { registerProjectRoutes } from "./api/project-routes.js";
|
|
22
28
|
import { registerSessionRoutes } from "./api/session-routes.js";
|
|
23
29
|
import { registerTaskRoutes } from "./api/task-routes.js";
|
|
30
|
+
import { registerTranslationRoutes } from "./api/translation-routes.js";
|
|
24
31
|
import { registerTerminalWs } from "./ws/terminal-ws.js";
|
|
32
|
+
import { registerTranslationWs } from "./ws/translation-ws.js";
|
|
25
33
|
import { toVcmError } from "./errors.js";
|
|
26
34
|
export async function createServer(deps, options = {}) {
|
|
27
35
|
const app = Fastify({
|
|
@@ -38,6 +46,10 @@ export async function createServer(deps, options = {}) {
|
|
|
38
46
|
});
|
|
39
47
|
});
|
|
40
48
|
registerProjectRoutes(app, { projectService: deps.projectService });
|
|
49
|
+
registerHarnessRoutes(app, {
|
|
50
|
+
projectService: deps.projectService,
|
|
51
|
+
harnessService: deps.harnessService
|
|
52
|
+
});
|
|
41
53
|
registerTaskRoutes(app, {
|
|
42
54
|
projectService: deps.projectService,
|
|
43
55
|
taskService: deps.taskService,
|
|
@@ -58,7 +70,13 @@ export async function createServer(deps, options = {}) {
|
|
|
58
70
|
taskService: deps.taskService,
|
|
59
71
|
messageService: deps.messageService
|
|
60
72
|
});
|
|
73
|
+
registerTranslationRoutes(app, {
|
|
74
|
+
projectService: deps.projectService,
|
|
75
|
+
taskService: deps.taskService,
|
|
76
|
+
translationService: deps.translationService
|
|
77
|
+
});
|
|
61
78
|
registerTerminalWs(app, { runtime: deps.runtime });
|
|
79
|
+
registerTranslationWs(app, { translationService: deps.translationService });
|
|
62
80
|
if (options.staticDir) {
|
|
63
81
|
await app.register(fastifyStatic, {
|
|
64
82
|
root: options.staticDir,
|
|
@@ -90,10 +108,12 @@ export function createDefaultServerDeps(options = {}) {
|
|
|
90
108
|
const runner = createCommandRunner();
|
|
91
109
|
const git = createGitAdapter(runner);
|
|
92
110
|
const claude = createClaudeAdapter(runner);
|
|
111
|
+
const appSettings = createAppSettingsService({ fs });
|
|
93
112
|
const runtime = createNodePtyTerminalRuntime({ fs });
|
|
94
113
|
const registry = createSessionRegistry();
|
|
95
114
|
const artifactService = createArtifactService(fs);
|
|
96
|
-
const
|
|
115
|
+
const harnessService = createHarnessService({ fs });
|
|
116
|
+
const projectService = createProjectService({ fs, git, claude, appSettings });
|
|
97
117
|
const taskService = createTaskService({ fs, git, artifactService, projectService });
|
|
98
118
|
const sessionService = createSessionService({
|
|
99
119
|
fs,
|
|
@@ -123,14 +143,24 @@ export function createDefaultServerDeps(options = {}) {
|
|
|
123
143
|
sessionService,
|
|
124
144
|
taskService
|
|
125
145
|
});
|
|
146
|
+
const translationService = createTranslationService({
|
|
147
|
+
runtime,
|
|
148
|
+
sessionRegistry: registry,
|
|
149
|
+
transcripts: createClaudeTranscriptService(),
|
|
150
|
+
sessionService,
|
|
151
|
+
appSettings,
|
|
152
|
+
provider: createOpenAiCompatibleTranslationProvider()
|
|
153
|
+
});
|
|
126
154
|
return {
|
|
127
155
|
projectService,
|
|
128
156
|
taskService,
|
|
129
157
|
sessionService,
|
|
130
158
|
artifactService,
|
|
159
|
+
harnessService,
|
|
131
160
|
commandDispatcher,
|
|
132
161
|
messageService,
|
|
133
162
|
statusService,
|
|
163
|
+
translationService,
|
|
134
164
|
runtime
|
|
135
165
|
};
|
|
136
166
|
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
const MAX_RECENT_REPOSITORIES = 5;
|
|
4
|
+
export function createAppSettingsService(deps) {
|
|
5
|
+
const settingsPath = deps.settingsPath ?? path.join(homedir(), ".vcm", "settings.json");
|
|
6
|
+
const legacySettingsPath = deps.legacySettingsPath
|
|
7
|
+
?? path.join(homedir(), ".vibe-coding-master", "settings.json");
|
|
8
|
+
const legacyTranslationPath = deps.legacyTranslationPath
|
|
9
|
+
?? path.join(homedir(), ".vibe-coding-master", "translation.json");
|
|
10
|
+
let cachedSettings = null;
|
|
11
|
+
async function loadSettings() {
|
|
12
|
+
if (cachedSettings) {
|
|
13
|
+
return cachedSettings;
|
|
14
|
+
}
|
|
15
|
+
let raw = {};
|
|
16
|
+
let shouldSave = false;
|
|
17
|
+
if (await deps.fs.pathExists(settingsPath)) {
|
|
18
|
+
raw = await deps.fs.readJson(settingsPath);
|
|
19
|
+
}
|
|
20
|
+
else if (await deps.fs.pathExists(legacySettingsPath)) {
|
|
21
|
+
raw = await deps.fs.readJson(legacySettingsPath);
|
|
22
|
+
shouldSave = true;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
shouldSave = true;
|
|
26
|
+
}
|
|
27
|
+
if (!raw.translation && await deps.fs.pathExists(legacyTranslationPath)) {
|
|
28
|
+
raw = {
|
|
29
|
+
...raw,
|
|
30
|
+
translation: normalizeTranslationConfig(await deps.fs.readJson(legacyTranslationPath))
|
|
31
|
+
};
|
|
32
|
+
shouldSave = true;
|
|
33
|
+
}
|
|
34
|
+
cachedSettings = normalizeSettingsFile(raw);
|
|
35
|
+
if (shouldSave) {
|
|
36
|
+
await saveSettings(cachedSettings);
|
|
37
|
+
}
|
|
38
|
+
return cachedSettings;
|
|
39
|
+
}
|
|
40
|
+
async function saveSettings(settings) {
|
|
41
|
+
cachedSettings = settings;
|
|
42
|
+
await deps.fs.writeJsonAtomic(settingsPath, settings);
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
loadSettings,
|
|
46
|
+
async updateTranslationConfig(config) {
|
|
47
|
+
const current = await loadSettings();
|
|
48
|
+
const translation = normalizeTranslationConfig(config) ?? { settings: {}, secrets: {} };
|
|
49
|
+
await saveSettings({
|
|
50
|
+
...current,
|
|
51
|
+
translation
|
|
52
|
+
});
|
|
53
|
+
return translation;
|
|
54
|
+
},
|
|
55
|
+
async getTranslationConfig() {
|
|
56
|
+
return (await loadSettings()).translation;
|
|
57
|
+
},
|
|
58
|
+
async getRecentRepositoryPaths() {
|
|
59
|
+
return (await loadSettings()).recentRepositoryPaths;
|
|
60
|
+
},
|
|
61
|
+
async recordRecentRepositoryPath(repoRoot) {
|
|
62
|
+
const normalizedPath = repoRoot.trim();
|
|
63
|
+
if (!normalizedPath) {
|
|
64
|
+
return (await loadSettings()).recentRepositoryPaths;
|
|
65
|
+
}
|
|
66
|
+
const current = await loadSettings();
|
|
67
|
+
const recentRepositoryPaths = normalizeRecentRepositoryPaths([
|
|
68
|
+
normalizedPath,
|
|
69
|
+
...current.recentRepositoryPaths
|
|
70
|
+
]);
|
|
71
|
+
await saveSettings({
|
|
72
|
+
...current,
|
|
73
|
+
recentRepositoryPaths
|
|
74
|
+
});
|
|
75
|
+
return recentRepositoryPaths;
|
|
76
|
+
},
|
|
77
|
+
getSettingsPath() {
|
|
78
|
+
return settingsPath;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function normalizeSettingsFile(input) {
|
|
83
|
+
return {
|
|
84
|
+
version: 1,
|
|
85
|
+
translation: normalizeTranslationConfig(input.translation),
|
|
86
|
+
recentRepositoryPaths: normalizeRecentRepositoryPaths(input.recentRepositoryPaths)
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function normalizeTranslationConfig(input) {
|
|
90
|
+
if (!input || typeof input !== "object") {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
const candidate = input;
|
|
94
|
+
const rawSettings = isObject(candidate.settings) ? candidate.settings : {};
|
|
95
|
+
const rawSecrets = isObject(candidate.secrets) ? candidate.secrets : {};
|
|
96
|
+
const { apiKey: settingsApiKey, ...settings } = rawSettings;
|
|
97
|
+
const apiKey = rawSecrets.apiKey ?? settingsApiKey;
|
|
98
|
+
return {
|
|
99
|
+
settings,
|
|
100
|
+
secrets: {
|
|
101
|
+
...rawSecrets,
|
|
102
|
+
...(apiKey !== undefined ? { apiKey } : {})
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function normalizeRecentRepositoryPaths(input) {
|
|
107
|
+
const paths = Array.isArray(input) ? input : [];
|
|
108
|
+
const seen = new Set();
|
|
109
|
+
const normalized = [];
|
|
110
|
+
for (const value of paths) {
|
|
111
|
+
if (typeof value !== "string") {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
const repoPath = value.trim();
|
|
115
|
+
if (!repoPath || seen.has(repoPath)) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
seen.add(repoPath);
|
|
119
|
+
normalized.push(repoPath);
|
|
120
|
+
if (normalized.length >= MAX_RECENT_REPOSITORIES) {
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return normalized;
|
|
125
|
+
}
|
|
126
|
+
function isObject(value) {
|
|
127
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
128
|
+
}
|
|
@@ -3,13 +3,14 @@ import { DISPATCHABLE_ROLES, ROLE_NAMES } from "../../shared/constants.js";
|
|
|
3
3
|
import { checkMarkdownArtifact } from "../../shared/validation/artifact-check.js";
|
|
4
4
|
import { VcmError } from "../errors.js";
|
|
5
5
|
import { resolveRepoPath } from "../adapters/filesystem.js";
|
|
6
|
-
import { renderArchitecturePlanTemplate, renderImplementationLogTemplate, renderReviewReportTemplate, renderValidationLogTemplate } from "../templates/handoff.js";
|
|
6
|
+
import { renderArchitecturePlanTemplate, renderDocsSyncReportTemplate, renderImplementationLogTemplate, renderReviewReportTemplate, renderValidationLogTemplate } from "../templates/handoff.js";
|
|
7
7
|
import { renderRoleCommandTemplate } from "../templates/role-command.js";
|
|
8
8
|
const ARTIFACT_PATH_KEYS = [
|
|
9
9
|
["architecture-plan", "architecturePlanPath"],
|
|
10
10
|
["implementation-log", "implementationLogPath"],
|
|
11
11
|
["validation-log", "validationLogPath"],
|
|
12
|
-
["review-report", "reviewReportPath"]
|
|
12
|
+
["review-report", "reviewReportPath"],
|
|
13
|
+
["docs-sync-report", "docsSyncReportPath"]
|
|
13
14
|
];
|
|
14
15
|
const ROLE_COMMAND_PLACEHOLDER_PATTERN = /(^|\n)\s*(TBD|status:\s*draft)\s*(\n|$)/i;
|
|
15
16
|
export function createArtifactService(fs) {
|
|
@@ -35,7 +36,8 @@ export function createArtifactService(fs) {
|
|
|
35
36
|
architecturePlanPath: path.posix.join(handoffDir, "architecture-plan.md"),
|
|
36
37
|
implementationLogPath: path.posix.join(handoffDir, "implementation-log.md"),
|
|
37
38
|
validationLogPath: path.posix.join(handoffDir, "validation-log.md"),
|
|
38
|
-
reviewReportPath: path.posix.join(handoffDir, "review-report.md")
|
|
39
|
+
reviewReportPath: path.posix.join(handoffDir, "review-report.md"),
|
|
40
|
+
docsSyncReportPath: path.posix.join(handoffDir, "docs-sync-report.md")
|
|
39
41
|
};
|
|
40
42
|
},
|
|
41
43
|
async ensureHandoffStructure(input) {
|
|
@@ -54,7 +56,8 @@ export function createArtifactService(fs) {
|
|
|
54
56
|
[paths.architecturePlanPath, renderArchitecturePlanTemplate(input.taskSlug)],
|
|
55
57
|
[paths.implementationLogPath, renderImplementationLogTemplate(input.taskSlug)],
|
|
56
58
|
[paths.validationLogPath, renderValidationLogTemplate(input.taskSlug)],
|
|
57
|
-
[paths.reviewReportPath, renderReviewReportTemplate(input.taskSlug)]
|
|
59
|
+
[paths.reviewReportPath, renderReviewReportTemplate(input.taskSlug)],
|
|
60
|
+
[paths.docsSyncReportPath, renderDocsSyncReportTemplate(input.taskSlug)]
|
|
58
61
|
];
|
|
59
62
|
const created = [];
|
|
60
63
|
for (const [artifactPath, content] of files) {
|