@snipcodeit/mgw 0.3.0 → 0.6.0
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 +1 -0
- package/bin/mgw-install.cjs +121 -24
- package/commands/board/create.md +192 -0
- package/commands/board/sync.md +44 -0
- package/commands/board/views.md +23 -0
- package/commands/context.md +183 -0
- package/commands/handoff.md +169 -0
- package/commands/issue.md +62 -0
- package/commands/milestone.md +37 -5
- package/commands/project.md +19 -0
- package/commands/run/execute.md +604 -27
- package/commands/run/pr-create.md +88 -0
- package/commands/run/triage.md +199 -2
- package/commands/run/worktree.md +41 -0
- package/commands/sync.md +69 -0
- package/commands/workflows/gsd.md +71 -0
- package/commands/workflows/state.md +340 -1
- package/dist/bin/mgw.cjs +14 -11
- package/dist/{index-s7v-ifd0.cjs → index-CHrVAIMY.cjs} +414 -23
- package/dist/lib/index.cjs +997 -20
- package/package.json +9 -4
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var require$$
|
|
3
|
+
var require$$2 = require('fs');
|
|
4
4
|
var require$$1 = require('path');
|
|
5
|
-
var require$$0
|
|
6
|
-
var require$$
|
|
5
|
+
var require$$0 = require('child_process');
|
|
6
|
+
var require$$3 = require('os');
|
|
7
|
+
var require$$0$1 = require('events');
|
|
7
8
|
|
|
8
9
|
function getDefaultExportFromCjs(x) {
|
|
9
10
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
@@ -15,7 +16,7 @@ var hasRequiredState;
|
|
|
15
16
|
function requireState () {
|
|
16
17
|
if (hasRequiredState) return state;
|
|
17
18
|
hasRequiredState = 1;
|
|
18
|
-
const fs = require$$
|
|
19
|
+
const fs = require$$2;
|
|
19
20
|
const path = require$$1;
|
|
20
21
|
function getMgwDir() {
|
|
21
22
|
return path.join(process.cwd(), ".mgw");
|
|
@@ -140,6 +141,10 @@ function requireState () {
|
|
|
140
141
|
issueState.dead_letter = false;
|
|
141
142
|
issueChanged = true;
|
|
142
143
|
}
|
|
144
|
+
if (!issueState.hasOwnProperty("checkpoint")) {
|
|
145
|
+
issueState.checkpoint = null;
|
|
146
|
+
issueChanged = true;
|
|
147
|
+
}
|
|
143
148
|
if (issueChanged) {
|
|
144
149
|
try {
|
|
145
150
|
fs.writeFileSync(filePath, JSON.stringify(issueState, null, 2), "utf-8");
|
|
@@ -164,6 +169,148 @@ function requireState () {
|
|
|
164
169
|
}
|
|
165
170
|
return -1;
|
|
166
171
|
}
|
|
172
|
+
const CHECKPOINT_SCHEMA_VERSION = 1;
|
|
173
|
+
const CHECKPOINT_STEP_ORDER = ["triage", "plan", "execute", "verify", "pr"];
|
|
174
|
+
function initCheckpoint(pipelineStep) {
|
|
175
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
176
|
+
return {
|
|
177
|
+
schema_version: CHECKPOINT_SCHEMA_VERSION,
|
|
178
|
+
pipeline_step: pipelineStep || "triage",
|
|
179
|
+
step_progress: {},
|
|
180
|
+
last_agent_output: null,
|
|
181
|
+
artifacts: [],
|
|
182
|
+
resume: {
|
|
183
|
+
action: null,
|
|
184
|
+
context: {}
|
|
185
|
+
},
|
|
186
|
+
started_at: now,
|
|
187
|
+
updated_at: now,
|
|
188
|
+
step_history: []
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function detectCheckpoint(issueNumber) {
|
|
192
|
+
const issueState = loadActiveIssue(issueNumber);
|
|
193
|
+
if (!issueState) return null;
|
|
194
|
+
const cp = issueState.checkpoint;
|
|
195
|
+
if (!cp || typeof cp !== "object") return null;
|
|
196
|
+
const step = cp.pipeline_step || "triage";
|
|
197
|
+
const stepIndex = CHECKPOINT_STEP_ORDER.indexOf(step);
|
|
198
|
+
if (stepIndex <= 0) return null;
|
|
199
|
+
return {
|
|
200
|
+
pipeline_step: cp.pipeline_step,
|
|
201
|
+
step_progress: cp.step_progress || {},
|
|
202
|
+
artifacts: cp.artifacts || [],
|
|
203
|
+
resume: cp.resume || { action: null, context: {} },
|
|
204
|
+
started_at: cp.started_at || null,
|
|
205
|
+
updated_at: cp.updated_at || null,
|
|
206
|
+
step_history: cp.step_history || []
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function resumeFromCheckpoint(issueNumber) {
|
|
210
|
+
const cp = detectCheckpoint(issueNumber);
|
|
211
|
+
if (!cp) return null;
|
|
212
|
+
const action = cp.resume && cp.resume.action || null;
|
|
213
|
+
const actionToStage = {
|
|
214
|
+
"run-plan-checker": "planning",
|
|
215
|
+
"spawn-executor": "executing",
|
|
216
|
+
"continue-execution": "executing",
|
|
217
|
+
"spawn-verifier": "verifying",
|
|
218
|
+
"create-pr": "pr-pending",
|
|
219
|
+
"begin-execution": "planning"
|
|
220
|
+
};
|
|
221
|
+
const resumeStage = actionToStage[action] || "planning";
|
|
222
|
+
const completedSteps = (cp.step_history || []).map((entry) => entry.step).filter(Boolean);
|
|
223
|
+
return {
|
|
224
|
+
checkpoint: cp,
|
|
225
|
+
resumeStage,
|
|
226
|
+
resumeAction: action || "unknown",
|
|
227
|
+
completedSteps
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
function atomicWriteJson(filePath, data) {
|
|
231
|
+
const tmpPath = filePath + ".tmp";
|
|
232
|
+
const content = JSON.stringify(data, null, 2);
|
|
233
|
+
fs.writeFileSync(tmpPath, content, "utf-8");
|
|
234
|
+
fs.renameSync(tmpPath, filePath);
|
|
235
|
+
}
|
|
236
|
+
function clearCheckpoint(issueNumber) {
|
|
237
|
+
const activeDir = getActiveDir();
|
|
238
|
+
if (!fs.existsSync(activeDir)) {
|
|
239
|
+
throw new Error(`No active directory found. Cannot clear checkpoint for #${issueNumber}.`);
|
|
240
|
+
}
|
|
241
|
+
const prefix = String(issueNumber) + "-";
|
|
242
|
+
let entries;
|
|
243
|
+
try {
|
|
244
|
+
entries = fs.readdirSync(activeDir);
|
|
245
|
+
} catch (err) {
|
|
246
|
+
throw new Error(`Cannot read active directory: ${err.message}`, { cause: err });
|
|
247
|
+
}
|
|
248
|
+
const match = entries.find((f) => f.startsWith(prefix) && f.endsWith(".json"));
|
|
249
|
+
if (!match) {
|
|
250
|
+
throw new Error(`No state file found for issue #${issueNumber}.`);
|
|
251
|
+
}
|
|
252
|
+
const filePath = path.join(activeDir, match);
|
|
253
|
+
let issueState;
|
|
254
|
+
try {
|
|
255
|
+
issueState = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
256
|
+
} catch (err) {
|
|
257
|
+
throw new Error(`Cannot parse state file for #${issueNumber}: ${err.message}`, { cause: err });
|
|
258
|
+
}
|
|
259
|
+
const hadCheckpoint = issueState.checkpoint != null;
|
|
260
|
+
issueState.checkpoint = null;
|
|
261
|
+
atomicWriteJson(filePath, issueState);
|
|
262
|
+
return { cleared: hadCheckpoint };
|
|
263
|
+
}
|
|
264
|
+
function updateCheckpoint(issueNumber, data) {
|
|
265
|
+
const activeDir = getActiveDir();
|
|
266
|
+
if (!fs.existsSync(activeDir)) {
|
|
267
|
+
throw new Error(`No active directory found. Cannot update checkpoint for #${issueNumber}.`);
|
|
268
|
+
}
|
|
269
|
+
const prefix = String(issueNumber) + "-";
|
|
270
|
+
let entries;
|
|
271
|
+
try {
|
|
272
|
+
entries = fs.readdirSync(activeDir);
|
|
273
|
+
} catch (err) {
|
|
274
|
+
throw new Error(`Cannot read active directory: ${err.message}`, { cause: err });
|
|
275
|
+
}
|
|
276
|
+
const match = entries.find((f) => f.startsWith(prefix) && f.endsWith(".json"));
|
|
277
|
+
if (!match) {
|
|
278
|
+
throw new Error(`No state file found for issue #${issueNumber}.`);
|
|
279
|
+
}
|
|
280
|
+
const filePath = path.join(activeDir, match);
|
|
281
|
+
let issueState;
|
|
282
|
+
try {
|
|
283
|
+
issueState = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
284
|
+
} catch (err) {
|
|
285
|
+
throw new Error(`Cannot parse state file for #${issueNumber}: ${err.message}`, { cause: err });
|
|
286
|
+
}
|
|
287
|
+
if (!issueState.checkpoint || typeof issueState.checkpoint !== "object") {
|
|
288
|
+
issueState.checkpoint = initCheckpoint();
|
|
289
|
+
}
|
|
290
|
+
const cp = issueState.checkpoint;
|
|
291
|
+
if (data.pipeline_step !== void 0) {
|
|
292
|
+
cp.pipeline_step = data.pipeline_step;
|
|
293
|
+
}
|
|
294
|
+
if (data.last_agent_output !== void 0) {
|
|
295
|
+
cp.last_agent_output = data.last_agent_output;
|
|
296
|
+
}
|
|
297
|
+
if (data.step_progress && typeof data.step_progress === "object") {
|
|
298
|
+
cp.step_progress = Object.assign({}, cp.step_progress, data.step_progress);
|
|
299
|
+
}
|
|
300
|
+
if (data.resume && typeof data.resume === "object") {
|
|
301
|
+
cp.resume = data.resume;
|
|
302
|
+
}
|
|
303
|
+
if (Array.isArray(data.artifacts) && data.artifacts.length > 0) {
|
|
304
|
+
cp.artifacts = (cp.artifacts || []).concat(data.artifacts);
|
|
305
|
+
}
|
|
306
|
+
if (Array.isArray(data.step_history) && data.step_history.length > 0) {
|
|
307
|
+
cp.step_history = (cp.step_history || []).concat(data.step_history);
|
|
308
|
+
}
|
|
309
|
+
cp.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
310
|
+
issueState.checkpoint = cp;
|
|
311
|
+
atomicWriteJson(filePath, issueState);
|
|
312
|
+
return { updated: true, checkpoint: cp };
|
|
313
|
+
}
|
|
167
314
|
const VALID_LINK_TYPES = /* @__PURE__ */ new Set(["related", "implements", "tracks", "maps-to", "blocked-by"]);
|
|
168
315
|
function loadCrossRefs() {
|
|
169
316
|
const filePath = path.join(getMgwDir(), "cross-refs.json");
|
|
@@ -317,6 +464,47 @@ function requireState () {
|
|
|
317
464
|
}
|
|
318
465
|
return sorted;
|
|
319
466
|
}
|
|
467
|
+
function detectProjectState(options = {}) {
|
|
468
|
+
const repoRoot = options.repoRoot || process.cwd();
|
|
469
|
+
const G = typeof options.githubMilestoneCount === "number" ? options.githubMilestoneCount : 0;
|
|
470
|
+
const P = fs.existsSync(path.join(repoRoot, ".planning", "PROJECT.md"));
|
|
471
|
+
const R = fs.existsSync(path.join(repoRoot, ".planning", "ROADMAP.md"));
|
|
472
|
+
const S = fs.existsSync(path.join(repoRoot, ".planning", "STATE.md"));
|
|
473
|
+
const M = fs.existsSync(path.join(repoRoot, ".mgw", "project.json"));
|
|
474
|
+
const signals = { P, R, S, M, G };
|
|
475
|
+
if (M && G > 0) {
|
|
476
|
+
let projectData;
|
|
477
|
+
try {
|
|
478
|
+
const raw = fs.readFileSync(path.join(repoRoot, ".mgw", "project.json"), "utf-8");
|
|
479
|
+
projectData = JSON.parse(raw);
|
|
480
|
+
} catch (_e) {
|
|
481
|
+
return { stateClass: "Diverged", signals };
|
|
482
|
+
}
|
|
483
|
+
const milestones = Array.isArray(projectData.milestones) ? projectData.milestones : [];
|
|
484
|
+
const currentMilestone = typeof projectData.current_milestone === "number" ? projectData.current_milestone : 1;
|
|
485
|
+
const allComplete = milestones.length > 0 && currentMilestone > milestones.length;
|
|
486
|
+
if (allComplete) {
|
|
487
|
+
return { stateClass: "Extend", signals };
|
|
488
|
+
}
|
|
489
|
+
const localCount = milestones.length;
|
|
490
|
+
const countDiff = Math.abs(localCount - G);
|
|
491
|
+
if (countDiff <= 1) {
|
|
492
|
+
return { stateClass: "Aligned", signals };
|
|
493
|
+
} else {
|
|
494
|
+
return { stateClass: "Diverged", signals };
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
if (!M && G === 0) {
|
|
498
|
+
if (P && (R || S)) {
|
|
499
|
+
return { stateClass: "GSD-Mid-Exec", signals };
|
|
500
|
+
}
|
|
501
|
+
if (P) {
|
|
502
|
+
return { stateClass: "GSD-Only", signals };
|
|
503
|
+
}
|
|
504
|
+
return { stateClass: "Fresh", signals };
|
|
505
|
+
}
|
|
506
|
+
return { stateClass: "Fresh", signals };
|
|
507
|
+
}
|
|
320
508
|
state = {
|
|
321
509
|
getMgwDir,
|
|
322
510
|
getActiveDir,
|
|
@@ -327,11 +515,20 @@ function requireState () {
|
|
|
327
515
|
mergeProjectState,
|
|
328
516
|
migrateProjectState,
|
|
329
517
|
resolveActiveMilestoneIndex,
|
|
518
|
+
CHECKPOINT_SCHEMA_VERSION,
|
|
519
|
+
CHECKPOINT_STEP_ORDER,
|
|
520
|
+
initCheckpoint,
|
|
521
|
+
atomicWriteJson,
|
|
522
|
+
detectCheckpoint,
|
|
523
|
+
resumeFromCheckpoint,
|
|
524
|
+
clearCheckpoint,
|
|
525
|
+
updateCheckpoint,
|
|
330
526
|
loadCrossRefs,
|
|
331
527
|
VALID_LINK_TYPES,
|
|
332
528
|
parseDependencies,
|
|
333
529
|
storeDependencies,
|
|
334
|
-
topologicalSort
|
|
530
|
+
topologicalSort,
|
|
531
|
+
detectProjectState
|
|
335
532
|
};
|
|
336
533
|
return state;
|
|
337
534
|
}
|
|
@@ -586,7 +783,7 @@ var hasRequiredGithub;
|
|
|
586
783
|
function requireGithub () {
|
|
587
784
|
if (hasRequiredGithub) return github;
|
|
588
785
|
hasRequiredGithub = 1;
|
|
589
|
-
const { execSync } = require$$0
|
|
786
|
+
const { execSync } = require$$0;
|
|
590
787
|
const { TimeoutError, GitHubApiError } = requireErrors();
|
|
591
788
|
const { withRetry } = requireRetry();
|
|
592
789
|
const GH_TIMEOUT_MS = 3e4;
|
|
@@ -957,16 +1154,17 @@ function requireOutput () {
|
|
|
957
1154
|
return output;
|
|
958
1155
|
}
|
|
959
1156
|
|
|
960
|
-
var
|
|
961
|
-
var
|
|
1157
|
+
var providerClaude;
|
|
1158
|
+
var hasRequiredProviderClaude;
|
|
962
1159
|
|
|
963
|
-
function
|
|
964
|
-
if (
|
|
965
|
-
|
|
966
|
-
const { execSync, spawn } = require$$0
|
|
1160
|
+
function requireProviderClaude () {
|
|
1161
|
+
if (hasRequiredProviderClaude) return providerClaude;
|
|
1162
|
+
hasRequiredProviderClaude = 1;
|
|
1163
|
+
const { execSync, spawn } = require$$0;
|
|
967
1164
|
const path = require$$1;
|
|
968
|
-
const fs = require$$
|
|
1165
|
+
const fs = require$$2;
|
|
969
1166
|
const { ClaudeNotAvailableError, TimeoutError } = requireErrors();
|
|
1167
|
+
const PROVIDER_ID = "claude";
|
|
970
1168
|
function getCommandsDir() {
|
|
971
1169
|
const dir = path.join(__dirname, "..", "commands");
|
|
972
1170
|
if (!fs.existsSync(dir)) {
|
|
@@ -977,7 +1175,7 @@ This may indicate a corrupted installation. Try reinstalling mgw.`
|
|
|
977
1175
|
}
|
|
978
1176
|
return dir;
|
|
979
1177
|
}
|
|
980
|
-
function
|
|
1178
|
+
function assertAvailable() {
|
|
981
1179
|
try {
|
|
982
1180
|
execSync("claude --version", {
|
|
983
1181
|
encoding: "utf-8",
|
|
@@ -1021,7 +1219,7 @@ This may indicate a corrupted installation. Try reinstalling mgw.`
|
|
|
1021
1219
|
);
|
|
1022
1220
|
}
|
|
1023
1221
|
}
|
|
1024
|
-
function
|
|
1222
|
+
function invoke(commandFile, userPrompt, opts) {
|
|
1025
1223
|
const o = opts || {};
|
|
1026
1224
|
const args = ["-p"];
|
|
1027
1225
|
if (commandFile) {
|
|
@@ -1071,12 +1269,204 @@ This may indicate a corrupted installation. Try reinstalling mgw.`
|
|
|
1071
1269
|
});
|
|
1072
1270
|
});
|
|
1073
1271
|
}
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1272
|
+
providerClaude = { PROVIDER_ID, assertAvailable, invoke, getCommandsDir };
|
|
1273
|
+
return providerClaude;
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
var providerGemini;
|
|
1277
|
+
var hasRequiredProviderGemini;
|
|
1278
|
+
|
|
1279
|
+
function requireProviderGemini () {
|
|
1280
|
+
if (hasRequiredProviderGemini) return providerGemini;
|
|
1281
|
+
hasRequiredProviderGemini = 1;
|
|
1282
|
+
const { execSync, spawn } = require$$0;
|
|
1283
|
+
const path = require$$1;
|
|
1284
|
+
const fs = require$$2;
|
|
1285
|
+
const os = require$$3;
|
|
1286
|
+
const PROVIDER_ID = "gemini";
|
|
1287
|
+
function getCommandsDir() {
|
|
1288
|
+
const dir = path.join(os.homedir(), ".gemini", "commands", "mgw");
|
|
1289
|
+
if (!fs.existsSync(dir)) {
|
|
1290
|
+
throw new Error(
|
|
1291
|
+
`Commands directory not found at: ${dir}
|
|
1292
|
+
Run: node bin/mgw-install.cjs --provider gemini
|
|
1293
|
+
(or reinstall the mgw package to trigger postinstall)`
|
|
1294
|
+
);
|
|
1295
|
+
}
|
|
1296
|
+
return dir;
|
|
1297
|
+
}
|
|
1298
|
+
function assertAvailable() {
|
|
1299
|
+
try {
|
|
1300
|
+
execSync("gemini --version", {
|
|
1301
|
+
encoding: "utf-8",
|
|
1302
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
1303
|
+
});
|
|
1304
|
+
} catch (err) {
|
|
1305
|
+
if (err.code === "ENOENT") {
|
|
1306
|
+
console.error(
|
|
1307
|
+
"Error: gemini CLI is not installed.\n\nInstall it with:\n npm install -g @google/gemini-cli\n\nThen run:\n gemini auth"
|
|
1308
|
+
);
|
|
1309
|
+
} else {
|
|
1310
|
+
console.error(
|
|
1311
|
+
"Error: gemini CLI check failed.\nEnsure gemini is installed and on your PATH."
|
|
1312
|
+
);
|
|
1313
|
+
}
|
|
1314
|
+
process.exit(1);
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
function invoke(commandFile, userPrompt, opts) {
|
|
1318
|
+
const o = opts || {};
|
|
1319
|
+
if (o.dryRun) {
|
|
1320
|
+
const dryArgs = ["-p"];
|
|
1321
|
+
if (o.model) dryArgs.push("--model", o.model);
|
|
1322
|
+
dryArgs.push(commandFile ? "<system>" + commandFile + "</system> " + (userPrompt || "run") : userPrompt || "run");
|
|
1323
|
+
console.log("Would invoke: gemini " + dryArgs.join(" "));
|
|
1324
|
+
return Promise.resolve({ exitCode: 0, output: "" });
|
|
1325
|
+
}
|
|
1326
|
+
let effectivePrompt = userPrompt || "run";
|
|
1327
|
+
if (commandFile) {
|
|
1328
|
+
const fileContents = fs.readFileSync(commandFile, "utf-8");
|
|
1329
|
+
effectivePrompt = "<system>\n" + fileContents + "\n</system>\n\n" + effectivePrompt;
|
|
1330
|
+
}
|
|
1331
|
+
const args = ["-p"];
|
|
1332
|
+
if (o.model) {
|
|
1333
|
+
args.push("--model", o.model);
|
|
1334
|
+
}
|
|
1335
|
+
args.push(effectivePrompt);
|
|
1336
|
+
return new Promise((resolve, reject) => {
|
|
1337
|
+
const stdio = o.quiet ? ["pipe", "pipe", "pipe"] : ["inherit", "inherit", "inherit"];
|
|
1338
|
+
const child = spawn("gemini", args, { stdio });
|
|
1339
|
+
let output = "";
|
|
1340
|
+
if (o.quiet) {
|
|
1341
|
+
child.stdout.on("data", function(chunk) {
|
|
1342
|
+
output += chunk.toString();
|
|
1343
|
+
});
|
|
1344
|
+
child.stderr.on("data", function(chunk) {
|
|
1345
|
+
output += chunk.toString();
|
|
1346
|
+
});
|
|
1347
|
+
}
|
|
1348
|
+
child.on("error", function(err) {
|
|
1349
|
+
if (err.code === "ENOENT") {
|
|
1350
|
+
reject(new Error("gemini CLI not found. Install with: npm install -g @google/gemini-cli"));
|
|
1351
|
+
} else {
|
|
1352
|
+
reject(err);
|
|
1353
|
+
}
|
|
1354
|
+
});
|
|
1355
|
+
child.on("close", function(code) {
|
|
1356
|
+
resolve({ exitCode: code || 0, output });
|
|
1357
|
+
});
|
|
1358
|
+
});
|
|
1359
|
+
}
|
|
1360
|
+
providerGemini = { PROVIDER_ID, assertAvailable, invoke, getCommandsDir };
|
|
1361
|
+
return providerGemini;
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
var providerOpencode;
|
|
1365
|
+
var hasRequiredProviderOpencode;
|
|
1366
|
+
|
|
1367
|
+
function requireProviderOpencode () {
|
|
1368
|
+
if (hasRequiredProviderOpencode) return providerOpencode;
|
|
1369
|
+
hasRequiredProviderOpencode = 1;
|
|
1370
|
+
const { execSync, spawn } = require$$0;
|
|
1371
|
+
const path = require$$1;
|
|
1372
|
+
const fs = require$$2;
|
|
1373
|
+
const os = require$$3;
|
|
1374
|
+
const PROVIDER_ID = "opencode";
|
|
1375
|
+
function getCommandsDir() {
|
|
1376
|
+
const dir = path.join(os.homedir(), ".opencode", "commands", "mgw");
|
|
1377
|
+
if (!fs.existsSync(dir)) {
|
|
1378
|
+
throw new Error(
|
|
1379
|
+
"Commands directory not found at: " + dir + "\nRun: node bin/mgw-install.cjs --provider opencode\n(or reinstall the mgw package to trigger postinstall)"
|
|
1380
|
+
);
|
|
1381
|
+
}
|
|
1382
|
+
return dir;
|
|
1383
|
+
}
|
|
1384
|
+
function assertAvailable() {
|
|
1385
|
+
try {
|
|
1386
|
+
execSync("opencode --version", {
|
|
1387
|
+
encoding: "utf-8",
|
|
1388
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
1389
|
+
});
|
|
1390
|
+
} catch (err) {
|
|
1391
|
+
if (err.code === "ENOENT") {
|
|
1392
|
+
console.error(
|
|
1393
|
+
"Error: opencode CLI is not installed.\n\nInstall it with:\n npm install -g opencode-ai\n\n(or see https://opencode.ai for installation instructions)"
|
|
1394
|
+
);
|
|
1395
|
+
} else {
|
|
1396
|
+
console.error(
|
|
1397
|
+
"Error: opencode CLI check failed.\nEnsure opencode is installed and on your PATH."
|
|
1398
|
+
);
|
|
1399
|
+
}
|
|
1400
|
+
process.exit(1);
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
function invoke(commandFile, userPrompt, opts) {
|
|
1404
|
+
const o = opts || {};
|
|
1405
|
+
const args = ["run"];
|
|
1406
|
+
if (commandFile) {
|
|
1407
|
+
args.push("--system-prompt", commandFile);
|
|
1408
|
+
}
|
|
1409
|
+
if (o.model) {
|
|
1410
|
+
args.push("--model", o.model);
|
|
1411
|
+
}
|
|
1412
|
+
args.push(userPrompt || "run");
|
|
1413
|
+
if (o.dryRun) {
|
|
1414
|
+
console.log("Would invoke: opencode " + args.join(" "));
|
|
1415
|
+
return Promise.resolve({ exitCode: 0, output: "" });
|
|
1416
|
+
}
|
|
1417
|
+
return new Promise(function(resolve, reject) {
|
|
1418
|
+
const stdio = o.quiet ? ["pipe", "pipe", "pipe"] : ["inherit", "inherit", "inherit"];
|
|
1419
|
+
const child = spawn("opencode", args, { stdio });
|
|
1420
|
+
let output = "";
|
|
1421
|
+
if (o.quiet) {
|
|
1422
|
+
child.stdout.on("data", function(chunk) {
|
|
1423
|
+
output += chunk.toString();
|
|
1424
|
+
});
|
|
1425
|
+
child.stderr.on("data", function(chunk) {
|
|
1426
|
+
output += chunk.toString();
|
|
1427
|
+
});
|
|
1428
|
+
}
|
|
1429
|
+
child.on("error", function(err) {
|
|
1430
|
+
if (err.code === "ENOENT") {
|
|
1431
|
+
reject(new Error("opencode CLI not found. See https://opencode.ai for installation instructions."));
|
|
1432
|
+
} else {
|
|
1433
|
+
reject(err);
|
|
1434
|
+
}
|
|
1435
|
+
});
|
|
1436
|
+
child.on("close", function(code) {
|
|
1437
|
+
resolve({ exitCode: code || 0, output });
|
|
1438
|
+
});
|
|
1439
|
+
});
|
|
1440
|
+
}
|
|
1441
|
+
providerOpencode = { PROVIDER_ID, assertAvailable, invoke, getCommandsDir };
|
|
1442
|
+
return providerOpencode;
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
var providerManager;
|
|
1446
|
+
var hasRequiredProviderManager;
|
|
1447
|
+
|
|
1448
|
+
function requireProviderManager () {
|
|
1449
|
+
if (hasRequiredProviderManager) return providerManager;
|
|
1450
|
+
hasRequiredProviderManager = 1;
|
|
1451
|
+
const registry = {
|
|
1452
|
+
claude: requireProviderClaude(),
|
|
1453
|
+
gemini: requireProviderGemini(),
|
|
1454
|
+
opencode: requireProviderOpencode()
|
|
1078
1455
|
};
|
|
1079
|
-
|
|
1456
|
+
function getProvider(providerId) {
|
|
1457
|
+
const id = providerId || "claude";
|
|
1458
|
+
const provider = registry[id];
|
|
1459
|
+
if (!provider) {
|
|
1460
|
+
const available = Object.keys(registry).join(", ");
|
|
1461
|
+
throw new Error(`Unknown provider: "${id}". Available: ${available}`);
|
|
1462
|
+
}
|
|
1463
|
+
return provider;
|
|
1464
|
+
}
|
|
1465
|
+
function listProviders() {
|
|
1466
|
+
return Object.keys(registry);
|
|
1467
|
+
}
|
|
1468
|
+
providerManager = { ProviderManager: { getProvider, listProviders } };
|
|
1469
|
+
return providerManager;
|
|
1080
1470
|
}
|
|
1081
1471
|
|
|
1082
1472
|
var spinner;
|
|
@@ -1187,7 +1577,7 @@ function requireLogger () {
|
|
|
1187
1577
|
if (hasRequiredLogger) return logger;
|
|
1188
1578
|
hasRequiredLogger = 1;
|
|
1189
1579
|
const path = require$$1;
|
|
1190
|
-
const fs = require$$
|
|
1580
|
+
const fs = require$$2;
|
|
1191
1581
|
function getLogDir(repoRoot) {
|
|
1192
1582
|
const root = repoRoot || process.cwd();
|
|
1193
1583
|
const logDir = path.join(root, ".mgw", "logs");
|
|
@@ -1807,7 +2197,7 @@ var hasRequiredKeyboard;
|
|
|
1807
2197
|
function requireKeyboard () {
|
|
1808
2198
|
if (hasRequiredKeyboard) return keyboard;
|
|
1809
2199
|
hasRequiredKeyboard = 1;
|
|
1810
|
-
const { EventEmitter } = require$$0$
|
|
2200
|
+
const { EventEmitter } = require$$0$1;
|
|
1811
2201
|
const DEFAULT_BINDINGS = {
|
|
1812
2202
|
// Scroll
|
|
1813
2203
|
"j": "scroll-down",
|
|
@@ -2426,11 +2816,12 @@ function requireTui () {
|
|
|
2426
2816
|
}
|
|
2427
2817
|
|
|
2428
2818
|
exports.getDefaultExportFromCjs = getDefaultExportFromCjs;
|
|
2429
|
-
exports.requireClaude = requireClaude;
|
|
2430
2819
|
exports.requireErrors = requireErrors;
|
|
2431
2820
|
exports.requireGithub = requireGithub;
|
|
2432
2821
|
exports.requireLogger = requireLogger;
|
|
2433
2822
|
exports.requireOutput = requireOutput;
|
|
2823
|
+
exports.requireProviderClaude = requireProviderClaude;
|
|
2824
|
+
exports.requireProviderManager = requireProviderManager;
|
|
2434
2825
|
exports.requireRetry = requireRetry;
|
|
2435
2826
|
exports.requireSpinner = requireSpinner;
|
|
2436
2827
|
exports.requireState = requireState;
|