@vibecodetown/mcp-server 2.1.4 → 2.2.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 +10 -10
- package/build/auth/credential_store.js +146 -0
- package/build/auth/public_key.js +6 -4
- package/build/bootstrap/doctor.js +113 -5
- package/build/bootstrap/installer.js +85 -15
- package/build/bootstrap/registry.js +11 -6
- package/build/bootstrap/skills-installer.js +365 -0
- package/build/control_plane/gate.js +52 -70
- package/build/dx/activity.js +26 -3
- package/build/engine.js +151 -0
- package/build/errors.js +107 -0
- package/build/generated/bridge_build_seed_input.js +2 -0
- package/build/generated/bridge_build_seed_output.js +2 -0
- package/build/generated/bridge_confirm_reference_input.js +2 -0
- package/build/generated/bridge_confirm_reference_output.js +2 -0
- package/build/generated/bridge_confirmed_reference_file.js +2 -0
- package/build/generated/bridge_generate_references_input.js +2 -0
- package/build/generated/bridge_generate_references_output.js +2 -0
- package/build/generated/bridge_references_file.js +2 -0
- package/build/generated/bridge_work_order_seed_file.js +2 -0
- package/build/generated/contracts_bundle_info.js +3 -3
- package/build/generated/index.js +14 -0
- package/build/generated/ingress_input.js +2 -0
- package/build/generated/ingress_output.js +2 -0
- package/build/generated/ingress_resolution_file.js +2 -0
- package/build/generated/ingress_summary_file.js +2 -0
- package/build/generated/message_template_id_mapping_file.js +2 -0
- package/build/generated/run_app_input.js +1 -1
- package/build/index.js +4 -1
- package/build/local-mode/git.js +36 -22
- package/build/local-mode/paths.js +1 -0
- package/build/local-mode/project-state.js +176 -0
- package/build/local-mode/setup.js +21 -1
- package/build/local-mode/templates.js +3 -3
- package/build/path-utils.js +68 -0
- package/build/runtime/cli_invoker.js +416 -0
- package/build/tools/vibe_pm/advisory_review.js +5 -3
- package/build/tools/vibe_pm/bridge_build_seed.js +164 -0
- package/build/tools/vibe_pm/bridge_confirm_reference.js +91 -0
- package/build/tools/vibe_pm/bridge_generate_references.js +258 -0
- package/build/tools/vibe_pm/briefing.js +26 -1
- package/build/tools/vibe_pm/context.js +79 -0
- package/build/tools/vibe_pm/create_work_order.js +200 -3
- package/build/tools/vibe_pm/doctor.js +95 -0
- package/build/tools/vibe_pm/entity_gate/preflight.js +8 -3
- package/build/tools/vibe_pm/export_output.js +14 -13
- package/build/tools/vibe_pm/finalize_work.js +74 -0
- package/build/tools/vibe_pm/force_override.js +104 -0
- package/build/tools/vibe_pm/get_decision.js +2 -2
- package/build/tools/vibe_pm/index.js +160 -3
- package/build/tools/vibe_pm/ingress.js +645 -0
- package/build/tools/vibe_pm/ingress_gate.js +116 -0
- package/build/tools/vibe_pm/inspect_code.js +90 -20
- package/build/tools/vibe_pm/kce/doc_usage.js +4 -9
- package/build/tools/vibe_pm/kce/on_finalize.js +2 -2
- package/build/tools/vibe_pm/kce/preflight.js +11 -7
- package/build/tools/vibe_pm/list_rules.js +135 -0
- package/build/tools/vibe_pm/memory_status.js +11 -8
- package/build/tools/vibe_pm/memory_sync.js +11 -8
- package/build/tools/vibe_pm/pm_language.js +17 -16
- package/build/tools/vibe_pm/pre_commit_analysis.js +292 -0
- package/build/tools/vibe_pm/publish_mcp.js +271 -0
- package/build/tools/vibe_pm/python_error.js +115 -0
- package/build/tools/vibe_pm/run_app.js +215 -86
- package/build/tools/vibe_pm/run_app_podman.js +64 -2
- package/build/tools/vibe_pm/save_rule.js +120 -0
- package/build/tools/vibe_pm/search_oss.js +5 -3
- package/build/tools/vibe_pm/spec_rag.js +185 -0
- package/build/tools/vibe_pm/status.js +50 -3
- package/build/tools/vibe_pm/submit_decision.js +2 -2
- package/build/tools/vibe_pm/types.js +28 -0
- package/build/tools/vibe_pm/undo_last_task.js +23 -20
- package/build/tools/vibe_pm/waiter_mapping.js +155 -0
- package/build/tools/vibe_pm/zoekt_evidence.js +5 -3
- package/build/tools.js +13 -5
- package/build/version-check.js +5 -5
- package/build/vibe-cli.js +742 -39
- package/package.json +5 -4
- package/skills/VRIP_INSTALL_MANIFEST_DOCTOR.skill.md +288 -0
- package/skills/index.json +14 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// adapters/mcp-ts/src/tools/vibe_pm/waiter_mapping.ts
|
|
2
|
+
// Waiter(Front) rendering: message_template_id mapping + term dictionary (data-driven)
|
|
3
|
+
import * as fs from "node:fs";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { MessageTemplateIdMappingFileSchema } from "../../generated/message_template_id_mapping_file.js";
|
|
7
|
+
let cache = null;
|
|
8
|
+
function packageRoot() {
|
|
9
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
// src/tools/vibe_pm → package root
|
|
11
|
+
return path.resolve(here, "..", "..", "..");
|
|
12
|
+
}
|
|
13
|
+
function repoRoot(pkgRoot) {
|
|
14
|
+
// adapters/mcp-ts → repo root
|
|
15
|
+
return path.resolve(pkgRoot, "..", "..");
|
|
16
|
+
}
|
|
17
|
+
function existsFile(p) {
|
|
18
|
+
try {
|
|
19
|
+
return fs.existsSync(p) && fs.statSync(p).isFile();
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function readJsonFile(p) {
|
|
26
|
+
const raw = fs.readFileSync(p, "utf-8");
|
|
27
|
+
return JSON.parse(raw);
|
|
28
|
+
}
|
|
29
|
+
function safeLocaleList(mapping) {
|
|
30
|
+
const locales = mapping?.supported_locales;
|
|
31
|
+
return Array.isArray(locales) ? locales.map((x) => String(x).trim()).filter(Boolean) : [];
|
|
32
|
+
}
|
|
33
|
+
function safeDefaultLocale(mapping) {
|
|
34
|
+
const d = mapping?.default_locale;
|
|
35
|
+
return typeof d === "string" && d.trim() ? d.trim() : "ko";
|
|
36
|
+
}
|
|
37
|
+
function safeFallbackLocale(mapping) {
|
|
38
|
+
const f = mapping?.human_language_policy?.fallback_locale;
|
|
39
|
+
const s = typeof f === "string" && f.trim() ? f.trim() : "";
|
|
40
|
+
return s || safeDefaultLocale(mapping);
|
|
41
|
+
}
|
|
42
|
+
export function resetWaiterMappingCacheForTest() {
|
|
43
|
+
cache = null;
|
|
44
|
+
}
|
|
45
|
+
export function getWaiterMapping() {
|
|
46
|
+
const pkgRoot = packageRoot();
|
|
47
|
+
const candidates = [
|
|
48
|
+
path.join(pkgRoot, "assets", "message_template_id_mapping.v1.json"),
|
|
49
|
+
path.join(repoRoot(pkgRoot), "schemas", "message_template_id_mapping.v1.json")
|
|
50
|
+
];
|
|
51
|
+
for (const p of candidates) {
|
|
52
|
+
if (!existsFile(p))
|
|
53
|
+
continue;
|
|
54
|
+
const mtimeMs = fs.statSync(p).mtimeMs;
|
|
55
|
+
if (cache && cache.mappingPath === p && cache.mtimeMs === mtimeMs) {
|
|
56
|
+
return cache.mapping;
|
|
57
|
+
}
|
|
58
|
+
const raw = readJsonFile(p);
|
|
59
|
+
const parsed = MessageTemplateIdMappingFileSchema.parse(raw);
|
|
60
|
+
cache = { mappingPath: p, mtimeMs, mapping: parsed };
|
|
61
|
+
return parsed;
|
|
62
|
+
}
|
|
63
|
+
// Fail-closed is too harsh for user-facing rendering; fall back to a minimal internal default.
|
|
64
|
+
const fallback = MessageTemplateIdMappingFileSchema.parse({
|
|
65
|
+
version: "message_template_id_mapping.v1",
|
|
66
|
+
default_locale: "ko",
|
|
67
|
+
supported_locales: ["ko", "en"],
|
|
68
|
+
templates: {
|
|
69
|
+
"GO-01": { category: "GO", verdict: { ko: "진행 가능", en: "OK to proceed" }, next_action_prefix: { ko: "다음 단계:", en: "Next:" } },
|
|
70
|
+
"GO-02": { category: "GO", verdict: { ko: "진행 가능", en: "OK to proceed" }, next_action_prefix: { ko: "다음 단계:", en: "Next:" } },
|
|
71
|
+
"FIX-01": { category: "FIX", verdict: { ko: "보완 필요", en: "Needs changes" }, next_action_prefix: { ko: "다음 단계:", en: "Next:" } },
|
|
72
|
+
"FIX-02": { category: "FIX", verdict: { ko: "보완 필요", en: "Needs changes" }, next_action_prefix: { ko: "다음 단계:", en: "Next:" } },
|
|
73
|
+
"BLOCK-01": { category: "BLOCK", verdict: { ko: "반려", en: "Blocked" }, next_action_prefix: { ko: "다음 단계:", en: "Next:" } },
|
|
74
|
+
"BLOCK-02": { category: "BLOCK", verdict: { ko: "반려", en: "Blocked" }, next_action_prefix: { ko: "다음 단계:", en: "Next:" } },
|
|
75
|
+
"TRIAGE-SKIP-01": { category: "TRIAGE", verdict: { ko: "사전 점검 생략", en: "Pre-check skipped" }, next_action_prefix: { ko: "다음 단계:", en: "Next:" } },
|
|
76
|
+
"TRIAGE-RUN-01": { category: "TRIAGE", verdict: { ko: "사전 점검 실행", en: "Pre-check running" }, next_action_prefix: { ko: "다음 단계:", en: "Next:" } },
|
|
77
|
+
"TRIAGE-RUN-02": { category: "TRIAGE", verdict: { ko: "사전 점검 실행", en: "Pre-check running" }, next_action_prefix: { ko: "다음 단계:", en: "Next:" } },
|
|
78
|
+
"ADV-01": { category: "ADVICE", verdict: { ko: "참고", en: "Advice" }, next_action_prefix: { ko: "다음 단계:", en: "Next:" } },
|
|
79
|
+
"ADV-02": { category: "ADVICE", verdict: { ko: "참고", en: "Advice" }, next_action_prefix: { ko: "다음 단계:", en: "Next:" } },
|
|
80
|
+
"WARN-01": { category: "WARN", verdict: { ko: "주의", en: "Warning" }, next_action_prefix: { ko: "다음 단계:", en: "Next:" } },
|
|
81
|
+
"WARN-02": { category: "WARN", verdict: { ko: "주의", en: "Warning" }, next_action_prefix: { ko: "다음 단계:", en: "Next:" } },
|
|
82
|
+
"SOFTBLOCK-01": { category: "SOFTBLOCK", verdict: { ko: "잠깐 멈춤", en: "Pause" }, next_action_prefix: { ko: "다음 단계:", en: "Next:" } }
|
|
83
|
+
},
|
|
84
|
+
term_dictionary: { entries: [{ id: "ENGINE_RUN_ID", aliases: ["run_id"], replacement: { ko: "프로젝트", en: "project" }, category: "engine_term" }] }
|
|
85
|
+
});
|
|
86
|
+
cache = { mappingPath: "<fallback>", mtimeMs: 0, mapping: fallback };
|
|
87
|
+
return fallback;
|
|
88
|
+
}
|
|
89
|
+
export function resolveLocaleFromText(text, mapping = getWaiterMapping()) {
|
|
90
|
+
const env = (process.env.VIBECODE_LOCALE ?? "").trim();
|
|
91
|
+
const supported = safeLocaleList(mapping);
|
|
92
|
+
if (env && supported.includes(env))
|
|
93
|
+
return env;
|
|
94
|
+
const hasKo = /[가-힣]/.test(text);
|
|
95
|
+
if (hasKo && supported.includes("ko"))
|
|
96
|
+
return "ko";
|
|
97
|
+
if (!hasKo && supported.includes("en"))
|
|
98
|
+
return "en";
|
|
99
|
+
return safeFallbackLocale(mapping);
|
|
100
|
+
}
|
|
101
|
+
export function resolveLocaleFromData(data, mapping = getWaiterMapping()) {
|
|
102
|
+
const env = (process.env.VIBECODE_LOCALE ?? "").trim();
|
|
103
|
+
const supported = safeLocaleList(mapping);
|
|
104
|
+
if (env && supported.includes(env))
|
|
105
|
+
return env;
|
|
106
|
+
if (data && typeof data === "object") {
|
|
107
|
+
const obj = data;
|
|
108
|
+
const oneLine = obj.review_summary?.one_line_verdict;
|
|
109
|
+
const msg = typeof oneLine === "string" ? oneLine : typeof obj.message === "string" ? obj.message : "";
|
|
110
|
+
if (msg)
|
|
111
|
+
return resolveLocaleFromText(msg, mapping);
|
|
112
|
+
}
|
|
113
|
+
return safeFallbackLocale(mapping);
|
|
114
|
+
}
|
|
115
|
+
export function renderVerdictFromTemplateId(templateId, locale, mapping = getWaiterMapping()) {
|
|
116
|
+
const templates = mapping?.templates ?? {};
|
|
117
|
+
const t = templates[templateId];
|
|
118
|
+
if (!t || typeof t !== "object")
|
|
119
|
+
return null;
|
|
120
|
+
const verdict = t?.verdict;
|
|
121
|
+
if (!verdict || typeof verdict !== "object")
|
|
122
|
+
return null;
|
|
123
|
+
const v = verdict[locale];
|
|
124
|
+
if (typeof v === "string" && v.trim())
|
|
125
|
+
return v.trim();
|
|
126
|
+
const fallback = safeFallbackLocale(mapping);
|
|
127
|
+
const vf = verdict[fallback];
|
|
128
|
+
if (typeof vf === "string" && vf.trim())
|
|
129
|
+
return vf.trim();
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
function escapeRegex(s) {
|
|
133
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
134
|
+
}
|
|
135
|
+
export function applyTermDictionary(text, locale, mapping = getWaiterMapping()) {
|
|
136
|
+
let out = text;
|
|
137
|
+
const entries = mapping?.term_dictionary?.entries;
|
|
138
|
+
if (!Array.isArray(entries) || entries.length === 0)
|
|
139
|
+
return out;
|
|
140
|
+
for (const e of entries) {
|
|
141
|
+
const obj = e;
|
|
142
|
+
const aliases = Array.isArray(obj?.aliases) ? obj.aliases.map((a) => String(a)).filter(Boolean) : [];
|
|
143
|
+
const rep = obj?.replacement;
|
|
144
|
+
const replacement = typeof rep === "object" && rep !== null ? String(rep[locale] ?? "").trim() : "";
|
|
145
|
+
if (!replacement || aliases.length === 0)
|
|
146
|
+
continue;
|
|
147
|
+
for (const a of aliases) {
|
|
148
|
+
const alias = String(a).trim();
|
|
149
|
+
if (!alias)
|
|
150
|
+
continue;
|
|
151
|
+
out = out.replace(new RegExp(escapeRegex(alias), "gi"), replacement);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return out;
|
|
155
|
+
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// adapters/mcp-ts/src/tools/vibe_pm/zoekt_evidence.ts
|
|
2
2
|
// vibe_pm.zoekt_evidence - Collect pattern evidence across local roots (zoekt/rg/python_scan)
|
|
3
3
|
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
|
|
4
|
-
import {
|
|
4
|
+
import { runPythonCli } from "../../engine.js";
|
|
5
5
|
import { safeJsonParse } from "../../cli.js";
|
|
6
6
|
import { validateToolInput } from "../../security/input-validator.js";
|
|
7
7
|
import { resolveProjectId, resolveRunId } from "./context.js";
|
|
8
|
+
import { classifyPythonError } from "./python_error.js";
|
|
8
9
|
function toCsv(values) {
|
|
9
10
|
return values
|
|
10
11
|
.map((v) => (typeof v === "string" ? v.trim() : ""))
|
|
@@ -43,9 +44,10 @@ export async function zoektEvidence(input) {
|
|
|
43
44
|
const writeEvidence = input?.write_evidence !== false;
|
|
44
45
|
if (!writeEvidence)
|
|
45
46
|
cmd.push("--no-write-evidence");
|
|
46
|
-
const res = await
|
|
47
|
+
const res = await runPythonCli(cmd, { timeoutMs: 300_000 });
|
|
47
48
|
if (res.code !== 0) {
|
|
48
|
-
|
|
49
|
+
const classified = classifyPythonError(res.stderr ?? "", res.code, "패턴 증거 수집");
|
|
50
|
+
throw new Error(`${classified.issueCode}: ${classified.summary}`);
|
|
49
51
|
}
|
|
50
52
|
const parsed = safeJsonParse(res.stdout);
|
|
51
53
|
if (!parsed.ok) {
|
package/build/tools.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { safeJsonParse } from "./cli.js";
|
|
5
5
|
import { parseSelectionValidationResult } from "./contracts.js";
|
|
6
|
-
import { runEngine } from "./engine.js";
|
|
6
|
+
import { runEngine, runPythonCli } from "./engine.js";
|
|
7
7
|
import { doctor as doctorImpl } from "./bootstrap/doctor.js";
|
|
8
8
|
import { ToolErrorOutputSchema } from "./generated/tool_error_output.js";
|
|
9
9
|
function toolText(obj) {
|
|
@@ -45,7 +45,9 @@ export function defineTools() {
|
|
|
45
45
|
});
|
|
46
46
|
async function vibecodeOneLoop(input) {
|
|
47
47
|
try {
|
|
48
|
-
|
|
48
|
+
// [DEPRECATED] Use vibe_pm.inspect_code instead
|
|
49
|
+
// Changed from runEngine("vibecoding-helper") to runPythonCli for correct routing
|
|
50
|
+
const { code, stdout, stderr } = await runPythonCli(["one-loop", input.run_id, "--output", input.output], { timeoutMs: input.timeout_ms ?? 120_000 });
|
|
49
51
|
const parsed = safeJsonParse(stdout);
|
|
50
52
|
if (!parsed.ok) {
|
|
51
53
|
return err("invalid_json", {
|
|
@@ -148,7 +150,9 @@ export function defineTools() {
|
|
|
148
150
|
});
|
|
149
151
|
async function vibecodeShowAskQueue(input) {
|
|
150
152
|
try {
|
|
151
|
-
|
|
153
|
+
// [DEPRECATED] Use vibe_pm.get_decision instead
|
|
154
|
+
// Changed from runEngine("vibecoding-helper") to runPythonCli for correct routing
|
|
155
|
+
const { code, stdout, stderr } = await runPythonCli(["show-ask-queue", input.run_id], { timeoutMs: input.timeout_ms ?? 60_000 });
|
|
152
156
|
return toolText({
|
|
153
157
|
status: code === 0 ? "OK" : "FAIL",
|
|
154
158
|
exit_code: code,
|
|
@@ -168,7 +172,9 @@ export function defineTools() {
|
|
|
168
172
|
});
|
|
169
173
|
async function vibecodeShowDecisions(input) {
|
|
170
174
|
try {
|
|
171
|
-
|
|
175
|
+
// [DEPRECATED] Use vibe_pm.status instead
|
|
176
|
+
// Changed from runEngine("vibecoding-helper") to runPythonCli for correct routing
|
|
177
|
+
const { code, stdout, stderr } = await runPythonCli(["show-decisions", input.run_id], { timeoutMs: input.timeout_ms ?? 60_000 });
|
|
172
178
|
return toolText({
|
|
173
179
|
status: code === 0 ? "OK" : "FAIL",
|
|
174
180
|
exit_code: code,
|
|
@@ -189,7 +195,9 @@ export function defineTools() {
|
|
|
189
195
|
});
|
|
190
196
|
async function vibecodeAnswer(input) {
|
|
191
197
|
try {
|
|
192
|
-
|
|
198
|
+
// [DEPRECATED] Use vibe_pm.submit_decision instead
|
|
199
|
+
// Changed from runEngine("vibecoding-helper") to runPythonCli for correct routing
|
|
200
|
+
const { code, stdout, stderr } = await runPythonCli(["answer", input.run_id, "--text", input.text], { timeoutMs: input.timeout_ms ?? 120_000 });
|
|
193
201
|
return toolText({
|
|
194
202
|
status: code === 0 ? "OK" : "FAIL",
|
|
195
203
|
exit_code: code,
|
package/build/version-check.js
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
// 정책: 절대 실행을 막지 않는다 (모든 실패는 GO)
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
|
-
import { spawnSync } from "node:child_process";
|
|
7
6
|
import readline from "node:readline";
|
|
7
|
+
import { invokeGitSync } from "./runtime/cli_invoker.js";
|
|
8
8
|
function execGit(args, cwd) {
|
|
9
|
-
const
|
|
9
|
+
const result = invokeGitSync(args, cwd, { timeoutMs: 10000 });
|
|
10
10
|
return {
|
|
11
|
-
status:
|
|
12
|
-
stdout:
|
|
13
|
-
stderr:
|
|
11
|
+
status: result.exitCode,
|
|
12
|
+
stdout: result.stdout,
|
|
13
|
+
stderr: result.stderr,
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
function repoRootOrNull(cwd) {
|