@etavioxy/wocingflow-mcp-server 0.0.4 → 0.0.5-fix.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/bin/wocingflow-mcp-server.js +208 -208
- package/package.json +19 -19
- package/vendor/mcp_server.exe +0 -0
- package/vendor/service-data/workflows/baseline-workflow/01-start-feature.sh +18 -18
- package/vendor/service-data/workflows/baseline-workflow/02-select-minimal-patch.sh +9 -9
- package/vendor/service-data/workflows/baseline-workflow/03-patch-sink.sh +26 -26
- package/vendor/service-data/workflows/baseline-workflow/04-patch-broadcast.sh +24 -24
- package/vendor/service-data/workflows/baseline-workflow/05-squash-feature.sh +18 -18
- package/vendor/service-data/workflows/baseline-workflow/06-feature-retract.sh +28 -28
- package/vendor/service-data/workflows/baseline-workflow/07-rebase-origin.sh +27 -27
- package/vendor/service-data/workflows/baseline-workflow/08-push-origin.sh +5 -5
- package/vendor/service-data/workflows/baseline-workflow/09-generate-patches.sh +11 -11
- package/vendor/service-data/workflows/baseline-workflow/profile.json +215 -215
- package/vendor/service-data/workflows/commit-merge-split-lab/01-show-recent-commits.sh +3 -3
- package/vendor/service-data/workflows/commit-merge-split-lab/02-merge-commits-in-range.sh +5 -5
- package/vendor/service-data/workflows/commit-merge-split-lab/03-split-commit-to-working-tree.sh +6 -6
- package/vendor/service-data/workflows/commit-merge-split-lab/04-recommit-selected-path.sh +6 -6
- package/vendor/service-data/workflows/commit-merge-split-lab/05-continue-rewrite.sh +3 -3
- package/vendor/service-data/workflows/patch-export-for-review/01-ensure-patch-out-dir.sh +4 -4
- package/vendor/service-data/workflows/patch-export-for-review/02-format-patch-by-folder.sh +6 -6
- package/vendor/service-data/workflows/patch-export-for-review/03-list-generated-patches.sh +7 -7
|
@@ -1,208 +1,208 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const fs = require("node:fs");
|
|
3
|
-
const path = require("node:path");
|
|
4
|
-
const net = require("node:net");
|
|
5
|
-
const { spawn } = require("node:child_process");
|
|
6
|
-
const packageMeta = require("../package.json");
|
|
7
|
-
|
|
8
|
-
function sleep(ms) {
|
|
9
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function isWindows() {
|
|
13
|
-
return process.platform === "win32";
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function fileExists(filePath) {
|
|
17
|
-
try {
|
|
18
|
-
return fs.existsSync(filePath);
|
|
19
|
-
} catch {
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function candidateRoots() {
|
|
25
|
-
const cwd = process.cwd();
|
|
26
|
-
return [cwd, path.resolve(cwd, ".."), path.resolve(cwd, "..", "..")];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function resolveServiceDataDir() {
|
|
30
|
-
const bundledData = path.join(__dirname, "..", "vendor", "service-data");
|
|
31
|
-
if (fileExists(bundledData)) {
|
|
32
|
-
return bundledData;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (process.env.WF_SERVICE_DATA_DIR && fileExists(process.env.WF_SERVICE_DATA_DIR)) {
|
|
36
|
-
return process.env.WF_SERVICE_DATA_DIR;
|
|
37
|
-
}
|
|
38
|
-
for (const root of candidateRoots()) {
|
|
39
|
-
const candidate = path.join(root, "service", "data");
|
|
40
|
-
if (fileExists(candidate)) {
|
|
41
|
-
return candidate;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return "";
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function resolveServerLaunch() {
|
|
48
|
-
if (process.env.WF_MCP_SERVER_BIN && fileExists(process.env.WF_MCP_SERVER_BIN)) {
|
|
49
|
-
return { command: process.env.WF_MCP_SERVER_BIN, args: [] };
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const exeName = isWindows() ? "mcp_server.exe" : "mcp_server";
|
|
53
|
-
const bundledPath = path.join(__dirname, "..", "vendor", exeName);
|
|
54
|
-
if (fileExists(bundledPath)) {
|
|
55
|
-
return { command: bundledPath, args: [] };
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
for (const root of candidateRoots()) {
|
|
59
|
-
const debugPath = path.join(root, "service", "target", "debug", exeName);
|
|
60
|
-
const releasePath = path.join(root, "service", "target", "release", exeName);
|
|
61
|
-
if (fileExists(debugPath)) return { command: debugPath, args: [] };
|
|
62
|
-
if (fileExists(releasePath)) return { command: releasePath, args: [] };
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
for (const root of candidateRoots()) {
|
|
66
|
-
const manifestPath = path.join(root, "service", "Cargo.toml");
|
|
67
|
-
if (fileExists(manifestPath)) {
|
|
68
|
-
return {
|
|
69
|
-
command: "cargo",
|
|
70
|
-
args: ["run", "--manifest-path", manifestPath, "--bin", "mcp_server", "--"],
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
throw new Error(
|
|
76
|
-
"Cannot locate wocingflow mcp_server. Build service/bin/mcp_server or set WF_MCP_SERVER_BIN."
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async function resolvePort() {
|
|
81
|
-
if (process.env.WF_MCP_HTTP_PORT) {
|
|
82
|
-
return String(process.env.WF_MCP_HTTP_PORT);
|
|
83
|
-
}
|
|
84
|
-
return String(
|
|
85
|
-
await new Promise((resolve, reject) => {
|
|
86
|
-
const server = net.createServer();
|
|
87
|
-
server.listen(0, "127.0.0.1", () => {
|
|
88
|
-
const address = server.address();
|
|
89
|
-
if (!address || typeof address === "string") {
|
|
90
|
-
server.close();
|
|
91
|
-
reject(new Error("Failed to allocate free TCP port."));
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
const freePort = address.port;
|
|
95
|
-
server.close(() => resolve(freePort));
|
|
96
|
-
});
|
|
97
|
-
server.on("error", reject);
|
|
98
|
-
})
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
async function waitHealth(endpoint, timeoutMs) {
|
|
103
|
-
const started = Date.now();
|
|
104
|
-
while (Date.now() - started < timeoutMs) {
|
|
105
|
-
try {
|
|
106
|
-
const response = await fetch(`${endpoint}/health`);
|
|
107
|
-
if (response.ok) return;
|
|
108
|
-
} catch {
|
|
109
|
-
// keep waiting
|
|
110
|
-
}
|
|
111
|
-
await sleep(300);
|
|
112
|
-
}
|
|
113
|
-
throw new Error(`mcp_server health check timeout: ${endpoint}/health`);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function spawnBackend(command, args, env) {
|
|
117
|
-
const child = spawn(command, args, {
|
|
118
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
119
|
-
env,
|
|
120
|
-
shell: false,
|
|
121
|
-
windowsHide: true,
|
|
122
|
-
});
|
|
123
|
-
child.stdout.on("data", (chunk) => {
|
|
124
|
-
process.stderr.write(String(chunk));
|
|
125
|
-
});
|
|
126
|
-
child.stderr.on("data", (chunk) => {
|
|
127
|
-
process.stderr.write(String(chunk));
|
|
128
|
-
});
|
|
129
|
-
return child;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function spawnBridge(env, endpoint) {
|
|
133
|
-
let command;
|
|
134
|
-
let args;
|
|
135
|
-
if (isWindows()) {
|
|
136
|
-
command = "cmd.exe";
|
|
137
|
-
args = ["/d", "/s", "/c", `npx -y mcp-remote@latest ${endpoint}`];
|
|
138
|
-
} else {
|
|
139
|
-
command = "npx";
|
|
140
|
-
args = ["-y", "mcp-remote@latest", endpoint];
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const child = spawn(command, args, {
|
|
144
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
145
|
-
env,
|
|
146
|
-
shell: false,
|
|
147
|
-
windowsHide: true,
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
process.stdin.pipe(child.stdin);
|
|
151
|
-
child.stdout.pipe(process.stdout);
|
|
152
|
-
child.stderr.pipe(process.stderr);
|
|
153
|
-
return child;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
async function main() {
|
|
157
|
-
const host = process.env.WF_MCP_HTTP_HOST || "127.0.0.1";
|
|
158
|
-
const port = await resolvePort();
|
|
159
|
-
const endpoint = `http://${host}:${port}`;
|
|
160
|
-
const serviceDataDir = resolveServiceDataDir();
|
|
161
|
-
const launch = resolveServerLaunch();
|
|
162
|
-
|
|
163
|
-
const backendEnv = { ...process.env };
|
|
164
|
-
if (serviceDataDir) {
|
|
165
|
-
backendEnv.WF_SERVICE_DATA_DIR = serviceDataDir;
|
|
166
|
-
}
|
|
167
|
-
backendEnv.WF_MCP_NPM_PACKAGE = packageMeta.name || "@etavioxy/wocingflow-mcp-server";
|
|
168
|
-
backendEnv.WF_MCP_NPM_VERSION = packageMeta.version || "";
|
|
169
|
-
|
|
170
|
-
const backend = spawnBackend(
|
|
171
|
-
launch.command,
|
|
172
|
-
[...launch.args, "--host", host, "--port", String(port)],
|
|
173
|
-
backendEnv
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
let shuttingDown = false;
|
|
177
|
-
const shutdown = () => {
|
|
178
|
-
if (shuttingDown) return;
|
|
179
|
-
shuttingDown = true;
|
|
180
|
-
if (!backend.killed) {
|
|
181
|
-
backend.kill();
|
|
182
|
-
}
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
process.on("SIGINT", shutdown);
|
|
186
|
-
process.on("SIGTERM", shutdown);
|
|
187
|
-
process.on("exit", shutdown);
|
|
188
|
-
|
|
189
|
-
backend.on("exit", (code) => {
|
|
190
|
-
if (!shuttingDown && code !== 0) {
|
|
191
|
-
console.error(`[wocingflow-mcp] backend exited early with code ${code}`);
|
|
192
|
-
process.exit(code || 1);
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
await waitHealth(endpoint, 20000);
|
|
197
|
-
|
|
198
|
-
const bridge = spawnBridge(process.env, endpoint);
|
|
199
|
-
bridge.on("exit", (code) => {
|
|
200
|
-
shutdown();
|
|
201
|
-
process.exit(code || 0);
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
main().catch((error) => {
|
|
206
|
-
console.error(`[wocingflow-mcp] ${error.message}`);
|
|
207
|
-
process.exit(1);
|
|
208
|
-
});
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const fs = require("node:fs");
|
|
3
|
+
const path = require("node:path");
|
|
4
|
+
const net = require("node:net");
|
|
5
|
+
const { spawn } = require("node:child_process");
|
|
6
|
+
const packageMeta = require("../package.json");
|
|
7
|
+
|
|
8
|
+
function sleep(ms) {
|
|
9
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function isWindows() {
|
|
13
|
+
return process.platform === "win32";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function fileExists(filePath) {
|
|
17
|
+
try {
|
|
18
|
+
return fs.existsSync(filePath);
|
|
19
|
+
} catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function candidateRoots() {
|
|
25
|
+
const cwd = process.cwd();
|
|
26
|
+
return [cwd, path.resolve(cwd, ".."), path.resolve(cwd, "..", "..")];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function resolveServiceDataDir() {
|
|
30
|
+
const bundledData = path.join(__dirname, "..", "vendor", "service-data");
|
|
31
|
+
if (fileExists(bundledData)) {
|
|
32
|
+
return bundledData;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (process.env.WF_SERVICE_DATA_DIR && fileExists(process.env.WF_SERVICE_DATA_DIR)) {
|
|
36
|
+
return process.env.WF_SERVICE_DATA_DIR;
|
|
37
|
+
}
|
|
38
|
+
for (const root of candidateRoots()) {
|
|
39
|
+
const candidate = path.join(root, "service", "data");
|
|
40
|
+
if (fileExists(candidate)) {
|
|
41
|
+
return candidate;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return "";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function resolveServerLaunch() {
|
|
48
|
+
if (process.env.WF_MCP_SERVER_BIN && fileExists(process.env.WF_MCP_SERVER_BIN)) {
|
|
49
|
+
return { command: process.env.WF_MCP_SERVER_BIN, args: [] };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const exeName = isWindows() ? "mcp_server.exe" : "mcp_server";
|
|
53
|
+
const bundledPath = path.join(__dirname, "..", "vendor", exeName);
|
|
54
|
+
if (fileExists(bundledPath)) {
|
|
55
|
+
return { command: bundledPath, args: [] };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
for (const root of candidateRoots()) {
|
|
59
|
+
const debugPath = path.join(root, "service", "target", "debug", exeName);
|
|
60
|
+
const releasePath = path.join(root, "service", "target", "release", exeName);
|
|
61
|
+
if (fileExists(debugPath)) return { command: debugPath, args: [] };
|
|
62
|
+
if (fileExists(releasePath)) return { command: releasePath, args: [] };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
for (const root of candidateRoots()) {
|
|
66
|
+
const manifestPath = path.join(root, "service", "Cargo.toml");
|
|
67
|
+
if (fileExists(manifestPath)) {
|
|
68
|
+
return {
|
|
69
|
+
command: "cargo",
|
|
70
|
+
args: ["run", "--manifest-path", manifestPath, "--bin", "mcp_server", "--"],
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
throw new Error(
|
|
76
|
+
"Cannot locate wocingflow mcp_server. Build service/bin/mcp_server or set WF_MCP_SERVER_BIN."
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function resolvePort() {
|
|
81
|
+
if (process.env.WF_MCP_HTTP_PORT) {
|
|
82
|
+
return String(process.env.WF_MCP_HTTP_PORT);
|
|
83
|
+
}
|
|
84
|
+
return String(
|
|
85
|
+
await new Promise((resolve, reject) => {
|
|
86
|
+
const server = net.createServer();
|
|
87
|
+
server.listen(0, "127.0.0.1", () => {
|
|
88
|
+
const address = server.address();
|
|
89
|
+
if (!address || typeof address === "string") {
|
|
90
|
+
server.close();
|
|
91
|
+
reject(new Error("Failed to allocate free TCP port."));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const freePort = address.port;
|
|
95
|
+
server.close(() => resolve(freePort));
|
|
96
|
+
});
|
|
97
|
+
server.on("error", reject);
|
|
98
|
+
})
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async function waitHealth(endpoint, timeoutMs) {
|
|
103
|
+
const started = Date.now();
|
|
104
|
+
while (Date.now() - started < timeoutMs) {
|
|
105
|
+
try {
|
|
106
|
+
const response = await fetch(`${endpoint}/health`);
|
|
107
|
+
if (response.ok) return;
|
|
108
|
+
} catch {
|
|
109
|
+
// keep waiting
|
|
110
|
+
}
|
|
111
|
+
await sleep(300);
|
|
112
|
+
}
|
|
113
|
+
throw new Error(`mcp_server health check timeout: ${endpoint}/health`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function spawnBackend(command, args, env) {
|
|
117
|
+
const child = spawn(command, args, {
|
|
118
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
119
|
+
env,
|
|
120
|
+
shell: false,
|
|
121
|
+
windowsHide: true,
|
|
122
|
+
});
|
|
123
|
+
child.stdout.on("data", (chunk) => {
|
|
124
|
+
process.stderr.write(String(chunk));
|
|
125
|
+
});
|
|
126
|
+
child.stderr.on("data", (chunk) => {
|
|
127
|
+
process.stderr.write(String(chunk));
|
|
128
|
+
});
|
|
129
|
+
return child;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function spawnBridge(env, endpoint) {
|
|
133
|
+
let command;
|
|
134
|
+
let args;
|
|
135
|
+
if (isWindows()) {
|
|
136
|
+
command = "cmd.exe";
|
|
137
|
+
args = ["/d", "/s", "/c", `npx -y mcp-remote@latest ${endpoint}`];
|
|
138
|
+
} else {
|
|
139
|
+
command = "npx";
|
|
140
|
+
args = ["-y", "mcp-remote@latest", endpoint];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const child = spawn(command, args, {
|
|
144
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
145
|
+
env,
|
|
146
|
+
shell: false,
|
|
147
|
+
windowsHide: true,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
process.stdin.pipe(child.stdin);
|
|
151
|
+
child.stdout.pipe(process.stdout);
|
|
152
|
+
child.stderr.pipe(process.stderr);
|
|
153
|
+
return child;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async function main() {
|
|
157
|
+
const host = process.env.WF_MCP_HTTP_HOST || "127.0.0.1";
|
|
158
|
+
const port = await resolvePort();
|
|
159
|
+
const endpoint = `http://${host}:${port}`;
|
|
160
|
+
const serviceDataDir = resolveServiceDataDir();
|
|
161
|
+
const launch = resolveServerLaunch();
|
|
162
|
+
|
|
163
|
+
const backendEnv = { ...process.env };
|
|
164
|
+
if (serviceDataDir) {
|
|
165
|
+
backendEnv.WF_SERVICE_DATA_DIR = serviceDataDir;
|
|
166
|
+
}
|
|
167
|
+
backendEnv.WF_MCP_NPM_PACKAGE = packageMeta.name || "@etavioxy/wocingflow-mcp-server";
|
|
168
|
+
backendEnv.WF_MCP_NPM_VERSION = packageMeta.version || "";
|
|
169
|
+
|
|
170
|
+
const backend = spawnBackend(
|
|
171
|
+
launch.command,
|
|
172
|
+
[...launch.args, "--host", host, "--port", String(port)],
|
|
173
|
+
backendEnv
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
let shuttingDown = false;
|
|
177
|
+
const shutdown = () => {
|
|
178
|
+
if (shuttingDown) return;
|
|
179
|
+
shuttingDown = true;
|
|
180
|
+
if (!backend.killed) {
|
|
181
|
+
backend.kill();
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
process.on("SIGINT", shutdown);
|
|
186
|
+
process.on("SIGTERM", shutdown);
|
|
187
|
+
process.on("exit", shutdown);
|
|
188
|
+
|
|
189
|
+
backend.on("exit", (code) => {
|
|
190
|
+
if (!shuttingDown && code !== 0) {
|
|
191
|
+
console.error(`[wocingflow-mcp] backend exited early with code ${code}`);
|
|
192
|
+
process.exit(code || 1);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
await waitHealth(endpoint, 20000);
|
|
197
|
+
|
|
198
|
+
const bridge = spawnBridge(process.env, endpoint);
|
|
199
|
+
bridge.on("exit", (code) => {
|
|
200
|
+
shutdown();
|
|
201
|
+
process.exit(code || 0);
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
main().catch((error) => {
|
|
206
|
+
console.error(`[wocingflow-mcp] ${error.message}`);
|
|
207
|
+
process.exit(1);
|
|
208
|
+
});
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@etavioxy/wocingflow-mcp-server",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "MCP stdio launcher for WocingFlow service mcp_server",
|
|
5
|
-
"type": "commonjs",
|
|
6
|
-
"bin": {
|
|
7
|
-
"wocingflow-mcp-server": "bin/wocingflow-mcp-server.js"
|
|
8
|
-
},
|
|
9
|
-
"engines": {
|
|
10
|
-
"node": ">=18"
|
|
11
|
-
},
|
|
12
|
-
"scripts": {
|
|
13
|
-
"prepack": "node scripts/prepack.js"
|
|
14
|
-
},
|
|
15
|
-
"files": [
|
|
16
|
-
"bin",
|
|
17
|
-
"vendor"
|
|
18
|
-
]
|
|
19
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@etavioxy/wocingflow-mcp-server",
|
|
3
|
+
"version": "0.0.5-fix.1",
|
|
4
|
+
"description": "MCP stdio launcher for WocingFlow service mcp_server",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"bin": {
|
|
7
|
+
"wocingflow-mcp-server": "bin/wocingflow-mcp-server.js"
|
|
8
|
+
},
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=18"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"prepack": "node scripts/prepack.js"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"bin",
|
|
17
|
+
"vendor"
|
|
18
|
+
]
|
|
19
|
+
}
|
package/vendor/mcp_server.exe
CHANGED
|
Binary file
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
wf require WF_TARGET_FOLDER
|
|
3
|
-
wf require WF_SHARED_REPO_PATH
|
|
4
|
-
echo "[Status] Copying shared repo snapshot from: $WF_SHARED_REPO_PATH"
|
|
5
|
-
wf test is-git-repo "$WF_SHARED_REPO_PATH"
|
|
6
|
-
if wf test is-path-exists "$WF_TARGET_FOLDER"; then
|
|
7
|
-
wf test is-dir "$WF_TARGET_FOLDER"
|
|
8
|
-
wf test is-empty-dir "$WF_TARGET_FOLDER"
|
|
9
|
-
else
|
|
10
|
-
mkdir -p "$WF_TARGET_FOLDER"
|
|
11
|
-
fi
|
|
12
|
-
cp -a "$WF_SHARED_REPO_PATH/." "$WF_TARGET_FOLDER/"
|
|
13
|
-
branch_name="feature/$(basename "$WF_TARGET_FOLDER")"
|
|
14
|
-
if git -C "$WF_TARGET_FOLDER" rev-parse --verify --quiet "refs/heads/$branch_name" >/dev/null; then
|
|
15
|
-
git -C "$WF_TARGET_FOLDER" checkout "$branch_name"
|
|
16
|
-
else
|
|
17
|
-
git -C "$WF_TARGET_FOLDER" checkout -b "$branch_name"
|
|
18
|
-
fi
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
wf require WF_TARGET_FOLDER
|
|
3
|
+
wf require WF_SHARED_REPO_PATH
|
|
4
|
+
echo "[Status] Copying shared repo snapshot from: $WF_SHARED_REPO_PATH"
|
|
5
|
+
wf test is-git-repo "$WF_SHARED_REPO_PATH"
|
|
6
|
+
if wf test is-path-exists "$WF_TARGET_FOLDER"; then
|
|
7
|
+
wf test is-dir "$WF_TARGET_FOLDER"
|
|
8
|
+
wf test is-empty-dir "$WF_TARGET_FOLDER"
|
|
9
|
+
else
|
|
10
|
+
mkdir -p "$WF_TARGET_FOLDER"
|
|
11
|
+
fi
|
|
12
|
+
cp -a "$WF_SHARED_REPO_PATH/." "$WF_TARGET_FOLDER/"
|
|
13
|
+
branch_name="feature/$(basename "$WF_TARGET_FOLDER")"
|
|
14
|
+
if git -C "$WF_TARGET_FOLDER" rev-parse --verify --quiet "refs/heads/$branch_name" >/dev/null; then
|
|
15
|
+
git -C "$WF_TARGET_FOLDER" checkout "$branch_name"
|
|
16
|
+
else
|
|
17
|
+
git -C "$WF_TARGET_FOLDER" checkout -b "$branch_name"
|
|
18
|
+
fi
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
wf require WF_TARGET_FOLDER
|
|
3
|
-
wf require WF_PATCH_COMMITS
|
|
4
|
-
first="$(printf '%s\n' "$WF_PATCH_COMMITS" | awk '{print $1}')"
|
|
5
|
-
wf test is-git-repo "$WF_TARGET_FOLDER"
|
|
6
|
-
wf test is-git-commit "$WF_TARGET_FOLDER" "$first"
|
|
7
|
-
echo "[Status] Open rebase todo from: $first^"
|
|
8
|
-
echo "[Hint] Keep earliest hash as pick, change later selected hashes to squash."
|
|
9
|
-
git -C "$WF_TARGET_FOLDER" rebase -i "$first^"
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
wf require WF_TARGET_FOLDER
|
|
3
|
+
wf require WF_PATCH_COMMITS
|
|
4
|
+
first="$(printf '%s\n' "$WF_PATCH_COMMITS" | awk '{print $1}')"
|
|
5
|
+
wf test is-git-repo "$WF_TARGET_FOLDER"
|
|
6
|
+
wf test is-git-commit "$WF_TARGET_FOLDER" "$first"
|
|
7
|
+
echo "[Status] Open rebase todo from: $first^"
|
|
8
|
+
echo "[Hint] Keep earliest hash as pick, change later selected hashes to squash."
|
|
9
|
+
git -C "$WF_TARGET_FOLDER" rebase -i "$first^"
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
wf require WF_TARGET_FOLDER
|
|
3
|
-
wf require WF_SHARED_REPO_PATH
|
|
4
|
-
wf require WF_COMMIT_HASH
|
|
5
|
-
# Validate repositories and selected commit before rewriting history.
|
|
6
|
-
wf test is-git-repo "$WF_TARGET_FOLDER"
|
|
7
|
-
wf test is-git-repo "$WF_SHARED_REPO_PATH"
|
|
8
|
-
wf test is-git-commit "$WF_TARGET_FOLDER" "$WF_COMMIT_HASH"
|
|
9
|
-
|
|
10
|
-
# Use merge-base(target HEAD, shared HEAD) as the rebase base.
|
|
11
|
-
shared_head="$(git -C "$WF_SHARED_REPO_PATH" rev-parse HEAD)"
|
|
12
|
-
lcp="$(git -C "$WF_TARGET_FOLDER" merge-base HEAD "$shared_head")"
|
|
13
|
-
if [ "$lcp" != "$shared_head" ]; then
|
|
14
|
-
echo "[Error] LCP mismatch: lcp($lcp) != shared_head($shared_head)"
|
|
15
|
-
exit 1
|
|
16
|
-
fi
|
|
17
|
-
selected_short="$(git -C "$WF_TARGET_FOLDER" rev-parse --short "$WF_COMMIT_HASH")"
|
|
18
|
-
|
|
19
|
-
# Reorder rebase todo: move selected commit line to the top.
|
|
20
|
-
editor_cmd="sh -c 'f=\"\$1\"; awk -v s=\"$selected_short\" '\''/^pick / { h=\$2; if (index(h, s)==1 || index(s, h)==1) { x=\$0; next } } { r = r \$0 ORS } END { if (!x) { print \"[Error] commit not in todo.\" > \"/dev/stderr\"; exit 3 } print x; printf \"%s\", r }'\'' \"\$f\" > \"\$f.tmp\" && mv \"\$f.tmp\" \"\$f\"' _"
|
|
21
|
-
GIT_SEQUENCE_EDITOR="$editor_cmd" git -C "$WF_TARGET_FOLDER" rebase -i "$lcp"
|
|
22
|
-
|
|
23
|
-
# Sync selected patch to shared branch.
|
|
24
|
-
git -C "$WF_SHARED_REPO_PATH" fetch "$WF_TARGET_FOLDER" "$WF_COMMIT_HASH"
|
|
25
|
-
git -C "$WF_SHARED_REPO_PATH" cherry-pick FETCH_HEAD
|
|
26
|
-
echo "[Status] Patch sink completed."
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
wf require WF_TARGET_FOLDER
|
|
3
|
+
wf require WF_SHARED_REPO_PATH
|
|
4
|
+
wf require WF_COMMIT_HASH
|
|
5
|
+
# Validate repositories and selected commit before rewriting history.
|
|
6
|
+
wf test is-git-repo "$WF_TARGET_FOLDER"
|
|
7
|
+
wf test is-git-repo "$WF_SHARED_REPO_PATH"
|
|
8
|
+
wf test is-git-commit "$WF_TARGET_FOLDER" "$WF_COMMIT_HASH"
|
|
9
|
+
|
|
10
|
+
# Use merge-base(target HEAD, shared HEAD) as the rebase base.
|
|
11
|
+
shared_head="$(git -C "$WF_SHARED_REPO_PATH" rev-parse HEAD)"
|
|
12
|
+
lcp="$(git -C "$WF_TARGET_FOLDER" merge-base HEAD "$shared_head")"
|
|
13
|
+
if [ "$lcp" != "$shared_head" ]; then
|
|
14
|
+
echo "[Error] LCP mismatch: lcp($lcp) != shared_head($shared_head)"
|
|
15
|
+
exit 1
|
|
16
|
+
fi
|
|
17
|
+
selected_short="$(git -C "$WF_TARGET_FOLDER" rev-parse --short "$WF_COMMIT_HASH")"
|
|
18
|
+
|
|
19
|
+
# Reorder rebase todo: move selected commit line to the top.
|
|
20
|
+
editor_cmd="sh -c 'f=\"\$1\"; awk -v s=\"$selected_short\" '\''/^pick / { h=\$2; if (index(h, s)==1 || index(s, h)==1) { x=\$0; next } } { r = r \$0 ORS } END { if (!x) { print \"[Error] commit not in todo.\" > \"/dev/stderr\"; exit 3 } print x; printf \"%s\", r }'\'' \"\$f\" > \"\$f.tmp\" && mv \"\$f.tmp\" \"\$f\"' _"
|
|
21
|
+
GIT_SEQUENCE_EDITOR="$editor_cmd" git -C "$WF_TARGET_FOLDER" rebase -i "$lcp"
|
|
22
|
+
|
|
23
|
+
# Sync selected patch to shared branch.
|
|
24
|
+
git -C "$WF_SHARED_REPO_PATH" fetch "$WF_TARGET_FOLDER" "$WF_COMMIT_HASH"
|
|
25
|
+
git -C "$WF_SHARED_REPO_PATH" cherry-pick FETCH_HEAD
|
|
26
|
+
echo "[Status] Patch sink completed."
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
# Rebase target repos onto latest shared head.
|
|
3
|
-
wf require WF_SHARED_REPO_PATH
|
|
4
|
-
wf require WF_TARGET_REPOS
|
|
5
|
-
wf test is-git-repo "$WF_SHARED_REPO_PATH"
|
|
6
|
-
shared_head="$(git -C "$WF_SHARED_REPO_PATH" rev-parse HEAD)"
|
|
7
|
-
|
|
8
|
-
# Validate all target repos first (fail fast before any mutation).
|
|
9
|
-
for repo_path in $WF_TARGET_REPOS; do
|
|
10
|
-
[ "$repo_path" = "$WF_SHARED_REPO_PATH" ] && continue
|
|
11
|
-
wf test is-git-repo "$repo_path"
|
|
12
|
-
done
|
|
13
|
-
|
|
14
|
-
# Rebase each validated target repo onto shared latest base.
|
|
15
|
-
for repo_path in $WF_TARGET_REPOS; do
|
|
16
|
-
[ "$repo_path" = "$WF_SHARED_REPO_PATH" ] && continue
|
|
17
|
-
git -C "$repo_path" fetch "$WF_SHARED_REPO_PATH" "$shared_head"
|
|
18
|
-
fetched_shared_head="$(git -C "$repo_path" rev-parse FETCH_HEAD)"
|
|
19
|
-
lcp="$(git -C "$repo_path" merge-base HEAD "$fetched_shared_head")"
|
|
20
|
-
[ "$lcp" = "$fetched_shared_head" ] && continue
|
|
21
|
-
git -C "$repo_path" rebase --onto "$fetched_shared_head" "$lcp"
|
|
22
|
-
done
|
|
23
|
-
|
|
24
|
-
echo "[Status] Broadcast completed."
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Rebase target repos onto latest shared head.
|
|
3
|
+
wf require WF_SHARED_REPO_PATH
|
|
4
|
+
wf require WF_TARGET_REPOS
|
|
5
|
+
wf test is-git-repo "$WF_SHARED_REPO_PATH"
|
|
6
|
+
shared_head="$(git -C "$WF_SHARED_REPO_PATH" rev-parse HEAD)"
|
|
7
|
+
|
|
8
|
+
# Validate all target repos first (fail fast before any mutation).
|
|
9
|
+
for repo_path in $WF_TARGET_REPOS; do
|
|
10
|
+
[ "$repo_path" = "$WF_SHARED_REPO_PATH" ] && continue
|
|
11
|
+
wf test is-git-repo "$repo_path"
|
|
12
|
+
done
|
|
13
|
+
|
|
14
|
+
# Rebase each validated target repo onto shared latest base.
|
|
15
|
+
for repo_path in $WF_TARGET_REPOS; do
|
|
16
|
+
[ "$repo_path" = "$WF_SHARED_REPO_PATH" ] && continue
|
|
17
|
+
git -C "$repo_path" fetch "$WF_SHARED_REPO_PATH" "$shared_head"
|
|
18
|
+
fetched_shared_head="$(git -C "$repo_path" rev-parse FETCH_HEAD)"
|
|
19
|
+
lcp="$(git -C "$repo_path" merge-base HEAD "$fetched_shared_head")"
|
|
20
|
+
[ "$lcp" = "$fetched_shared_head" ] && continue
|
|
21
|
+
git -C "$repo_path" rebase --onto "$fetched_shared_head" "$lcp"
|
|
22
|
+
done
|
|
23
|
+
|
|
24
|
+
echo "[Status] Broadcast completed."
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
wf require WF_TARGET_FOLDER
|
|
3
|
-
wf require WF_SHARED_REPO_PATH
|
|
4
|
-
echo "[Status] Squashing commits from source branch into shared as one commit..."
|
|
5
|
-
wf test is-git-repo "$WF_TARGET_FOLDER"
|
|
6
|
-
wf test is-git-repo "$WF_SHARED_REPO_PATH"
|
|
7
|
-
shared_head="$(git -C "$WF_SHARED_REPO_PATH" rev-parse HEAD)"
|
|
8
|
-
source_head="$(git -C "$WF_TARGET_FOLDER" rev-parse HEAD)"
|
|
9
|
-
git -C "$WF_SHARED_REPO_PATH" fetch "$WF_TARGET_FOLDER" "$source_head"
|
|
10
|
-
fetched_source_head="$(git -C "$WF_SHARED_REPO_PATH" rev-parse FETCH_HEAD)"
|
|
11
|
-
commit_count="$(git -C "$WF_SHARED_REPO_PATH" rev-list --count "${shared_head}..${fetched_source_head}")"
|
|
12
|
-
if [ "$commit_count" -lt 1 ]; then
|
|
13
|
-
echo "[Error] No commits after shared base to squash."
|
|
14
|
-
exit 1
|
|
15
|
-
fi
|
|
16
|
-
git -C "$WF_SHARED_REPO_PATH" cherry-pick --no-commit "${shared_head}..${fetched_source_head}"
|
|
17
|
-
git -C "$WF_SHARED_REPO_PATH" commit -m "squash: from $(basename "$WF_TARGET_FOLDER") after shared base"
|
|
18
|
-
echo "[Status] Shared squash commit created."
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
wf require WF_TARGET_FOLDER
|
|
3
|
+
wf require WF_SHARED_REPO_PATH
|
|
4
|
+
echo "[Status] Squashing commits from source branch into shared as one commit..."
|
|
5
|
+
wf test is-git-repo "$WF_TARGET_FOLDER"
|
|
6
|
+
wf test is-git-repo "$WF_SHARED_REPO_PATH"
|
|
7
|
+
shared_head="$(git -C "$WF_SHARED_REPO_PATH" rev-parse HEAD)"
|
|
8
|
+
source_head="$(git -C "$WF_TARGET_FOLDER" rev-parse HEAD)"
|
|
9
|
+
git -C "$WF_SHARED_REPO_PATH" fetch "$WF_TARGET_FOLDER" "$source_head"
|
|
10
|
+
fetched_source_head="$(git -C "$WF_SHARED_REPO_PATH" rev-parse FETCH_HEAD)"
|
|
11
|
+
commit_count="$(git -C "$WF_SHARED_REPO_PATH" rev-list --count "${shared_head}..${fetched_source_head}")"
|
|
12
|
+
if [ "$commit_count" -lt 1 ]; then
|
|
13
|
+
echo "[Error] No commits after shared base to squash."
|
|
14
|
+
exit 1
|
|
15
|
+
fi
|
|
16
|
+
git -C "$WF_SHARED_REPO_PATH" cherry-pick --no-commit "${shared_head}..${fetched_source_head}"
|
|
17
|
+
git -C "$WF_SHARED_REPO_PATH" commit -m "squash: from $(basename "$WF_TARGET_FOLDER") after shared base"
|
|
18
|
+
echo "[Status] Shared squash commit created."
|