@snipcodeit/mgw 0.3.0 → 0.4.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/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 +150 -5
- package/commands/run/pr-create.md +42 -0
- package/commands/run/worktree.md +41 -0
- package/commands/sync.md +69 -0
- package/dist/bin/mgw.cjs +14 -11
- package/dist/{index-s7v-ifd0.cjs → index-B-_JvYpz.cjs} +217 -22
- package/dist/lib/index.cjs +474 -19
- package/package.json +1 -1
package/commands/run/worktree.md
CHANGED
|
@@ -12,6 +12,47 @@ BRANCH_NAME="issue/${ISSUE_NUMBER}-${slug}"
|
|
|
12
12
|
WORKTREE_DIR="${REPO_ROOT}/.worktrees/${BRANCH_NAME}"
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
**Check for active work on this issue by another developer:**
|
|
16
|
+
```bash
|
|
17
|
+
# Check 1: Remote branch already exists (another machine pushed work)
|
|
18
|
+
REMOTE_BRANCHES=$(git ls-remote --heads origin "issue/${ISSUE_NUMBER}-*" 2>/dev/null | awk '{print $2}' | sed 's|refs/heads/||')
|
|
19
|
+
if [ -n "$REMOTE_BRANCHES" ]; then
|
|
20
|
+
echo "WARNING: Remote branch(es) already exist for issue #${ISSUE_NUMBER}:"
|
|
21
|
+
echo "$REMOTE_BRANCHES" | sed 's/^/ /'
|
|
22
|
+
echo ""
|
|
23
|
+
AskUserQuestion(
|
|
24
|
+
header: "Active Work Detected",
|
|
25
|
+
question: "Remote branch exists for #${ISSUE_NUMBER}. Another developer may be working on this. Proceed anyway?",
|
|
26
|
+
options: [
|
|
27
|
+
{ label: "Proceed", description: "Create a new worktree anyway (may cause conflicts)" },
|
|
28
|
+
{ label: "Abort", description: "Stop pipeline — coordinate with the other developer first" }
|
|
29
|
+
]
|
|
30
|
+
)
|
|
31
|
+
if [ "$USER_CHOICE" = "Abort" ]; then
|
|
32
|
+
echo "Pipeline aborted — coordinate with the developer who owns the existing branch."
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
# Check 2: Open PR already exists for this issue
|
|
38
|
+
EXISTING_PR=$(gh pr list --search "issue/${ISSUE_NUMBER}-" --state open --json number,headRefName --jq '.[0].number' 2>/dev/null || echo "")
|
|
39
|
+
if [ -n "$EXISTING_PR" ]; then
|
|
40
|
+
echo "WARNING: Open PR #${EXISTING_PR} already exists for issue #${ISSUE_NUMBER}."
|
|
41
|
+
echo "Creating a new worktree will produce a conflicting PR."
|
|
42
|
+
AskUserQuestion(
|
|
43
|
+
header: "Open PR Exists",
|
|
44
|
+
question: "PR #${EXISTING_PR} is already open for this issue. Proceed with a new worktree?",
|
|
45
|
+
options: [
|
|
46
|
+
{ label: "Proceed", description: "Create new worktree anyway" },
|
|
47
|
+
{ label: "Abort", description: "Stop — review the existing PR first" }
|
|
48
|
+
]
|
|
49
|
+
)
|
|
50
|
+
if [ "$USER_CHOICE" = "Abort" ]; then
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
fi
|
|
54
|
+
```
|
|
55
|
+
|
|
15
56
|
Ensure .worktrees/ is gitignored:
|
|
16
57
|
```bash
|
|
17
58
|
mkdir -p "$(dirname "${WORKTREE_DIR}")"
|
package/commands/sync.md
CHANGED
|
@@ -33,6 +33,18 @@ Run periodically or when starting a new session to get a clean view.
|
|
|
33
33
|
|
|
34
34
|
<process>
|
|
35
35
|
|
|
36
|
+
<step name="parse_arguments">
|
|
37
|
+
**Parse sync flags:**
|
|
38
|
+
```bash
|
|
39
|
+
FULL_SYNC=false
|
|
40
|
+
for arg in "$@"; do
|
|
41
|
+
case "$arg" in
|
|
42
|
+
--full) FULL_SYNC=true ;;
|
|
43
|
+
esac
|
|
44
|
+
done
|
|
45
|
+
```
|
|
46
|
+
</step>
|
|
47
|
+
|
|
36
48
|
<step name="pull_board_state">
|
|
37
49
|
**Pull board state to reconstruct missing local .mgw/active/ files.**
|
|
38
50
|
|
|
@@ -348,6 +360,63 @@ rebuilt from board data — triage results and GSD artifacts will need to be re-
|
|
|
348
360
|
issue advances to `planning` or beyond.
|
|
349
361
|
</step>
|
|
350
362
|
|
|
363
|
+
<step name="rebuild_from_committed">
|
|
364
|
+
**Rebuild project context from committed planning files (--full only):**
|
|
365
|
+
|
|
366
|
+
Only runs when `--full` flag is passed. This is the multi-machine context rebuild:
|
|
367
|
+
after `git pull`, a developer runs `mgw:sync --full` to reconstruct full project
|
|
368
|
+
context from committed `.planning/` files and the board.
|
|
369
|
+
|
|
370
|
+
```bash
|
|
371
|
+
if [ "$FULL_SYNC" = "true" ]; then
|
|
372
|
+
echo "Full sync: rebuilding project context from committed planning files..."
|
|
373
|
+
|
|
374
|
+
# 1. Check for committed ROADMAP.md
|
|
375
|
+
if [ -f ".planning/ROADMAP.md" ]; then
|
|
376
|
+
echo " Found committed ROADMAP.md"
|
|
377
|
+
ROADMAP_ANALYSIS=$(node ~/.claude/get-shit-done/bin/gsd-tools.cjs roadmap analyze 2>/dev/null || echo '{}')
|
|
378
|
+
PHASE_COUNT=$(echo "$ROADMAP_ANALYSIS" | python3 -c "import json,sys; print(len(json.load(sys.stdin).get('phases',[])))" 2>/dev/null || echo "0")
|
|
379
|
+
echo " ROADMAP.md contains ${PHASE_COUNT} phases"
|
|
380
|
+
else
|
|
381
|
+
echo " No committed ROADMAP.md found — planning context unavailable"
|
|
382
|
+
echo " (This is expected if the project hasn't run a milestone yet)"
|
|
383
|
+
fi
|
|
384
|
+
|
|
385
|
+
# 2. Scan for committed phase artifacts
|
|
386
|
+
COMMITTED_PLANS=$(find .planning -name '*-PLAN.md' -not -path '.planning/quick/*' 2>/dev/null | wc -l)
|
|
387
|
+
COMMITTED_SUMMARIES=$(find .planning -name '*-SUMMARY.md' -not -path '.planning/quick/*' 2>/dev/null | wc -l)
|
|
388
|
+
echo " Committed phase plans: ${COMMITTED_PLANS}"
|
|
389
|
+
echo " Committed phase summaries: ${COMMITTED_SUMMARIES}"
|
|
390
|
+
|
|
391
|
+
# 3. If project.json is missing but board + ROADMAP exist, offer to reconstruct
|
|
392
|
+
if [ ! -f "${MGW_DIR}/project.json" ] && [ -f ".planning/ROADMAP.md" ] && [ -n "$BOARD_NODE_ID" ]; then
|
|
393
|
+
echo ""
|
|
394
|
+
echo " project.json is missing but ROADMAP.md and board are available."
|
|
395
|
+
echo " Run /mgw:project to reconstruct full project state."
|
|
396
|
+
echo " (Board state has been pulled — active issues are available)"
|
|
397
|
+
fi
|
|
398
|
+
|
|
399
|
+
# 4. Rebuild context cache from GitHub issue comments
|
|
400
|
+
echo " Rebuilding context cache from GitHub issue comments..."
|
|
401
|
+
node -e "
|
|
402
|
+
const ic = require('${REPO_ROOT}/lib/issue-context.cjs');
|
|
403
|
+
ic.rebuildContextCache()
|
|
404
|
+
.then(stats => console.log(' Cached summaries for', stats.issueCount, 'issues across', stats.milestoneCount, 'milestones'))
|
|
405
|
+
.catch(e => console.error(' Cache rebuild failed:', e.message));
|
|
406
|
+
" 2>/dev/null || echo " Context cache rebuild skipped (issue-context module not available)"
|
|
407
|
+
|
|
408
|
+
# 5. Refresh Project README with current milestone progress
|
|
409
|
+
echo " Refreshing Project README..."
|
|
410
|
+
node -e "
|
|
411
|
+
const ic = require('${REPO_ROOT}/lib/issue-context.cjs');
|
|
412
|
+
ic.updateProjectReadme()
|
|
413
|
+
.then(ok => console.log(ok ? ' Project README updated' : ' Project README skipped (no board configured)'))
|
|
414
|
+
.catch(() => console.log(' Project README refresh skipped'));
|
|
415
|
+
" 2>/dev/null || true
|
|
416
|
+
fi
|
|
417
|
+
```
|
|
418
|
+
</step>
|
|
419
|
+
|
|
351
420
|
<step name="scan_active">
|
|
352
421
|
**Scan all active issue states:**
|
|
353
422
|
|
package/dist/bin/mgw.cjs
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var index = require('../index-
|
|
4
|
+
var index = require('../index-B-_JvYpz.cjs');
|
|
5
5
|
var require$$0 = require('commander');
|
|
6
6
|
var require$$1 = require('path');
|
|
7
|
-
var require$$
|
|
7
|
+
var require$$2 = require('fs');
|
|
8
8
|
var require$$0$1 = require('child_process');
|
|
9
|
+
require('os');
|
|
9
10
|
require('events');
|
|
10
11
|
|
|
11
12
|
var mgw$1 = {};
|
|
12
13
|
|
|
13
|
-
var version = "0.
|
|
14
|
+
var version = "0.4.0";
|
|
14
15
|
var require$$11 = {
|
|
15
16
|
version: version};
|
|
16
17
|
|
|
@@ -21,9 +22,9 @@ function requireMgw () {
|
|
|
21
22
|
hasRequiredMgw = 1;
|
|
22
23
|
const { Command } = require$$0;
|
|
23
24
|
const path = require$$1;
|
|
24
|
-
const fs = require$$
|
|
25
|
+
const fs = require$$2;
|
|
25
26
|
const { execSync } = require$$0$1;
|
|
26
|
-
const {
|
|
27
|
+
const { ProviderManager } = index.requireProviderManager();
|
|
27
28
|
const { log, error, formatJson, verbose } = index.requireOutput();
|
|
28
29
|
const { getActiveDir, getCompletedDir, getMgwDir } = index.requireState();
|
|
29
30
|
const { getIssue, listIssues } = index.requireGithub();
|
|
@@ -32,7 +33,7 @@ function requireMgw () {
|
|
|
32
33
|
const { startTimer } = index.requireLogger();
|
|
33
34
|
const pkg = require$$11;
|
|
34
35
|
const program = new Command();
|
|
35
|
-
program.name("mgw").description("GitHub issue pipeline automation \u2014 Day 1 idea to Go Live").version(pkg.version).option("--dry-run", "show what would happen without executing").option("--json", "output structured JSON").option("-v, --verbose", "show API calls and file writes").option("--debug", "full payloads and timings").option("--model <model>", "Claude model override");
|
|
36
|
+
program.name("mgw").description("GitHub issue pipeline automation \u2014 Day 1 idea to Go Live").version(pkg.version).option("--dry-run", "show what would happen without executing").option("--json", "output structured JSON").option("-v, --verbose", "show API calls and file writes").option("--debug", "full payloads and timings").option("--model <model>", "Claude model override").option("--provider <provider>", "AI provider override (default: claude)");
|
|
36
37
|
const STAGE_LABELS = {
|
|
37
38
|
run: "pipeline",
|
|
38
39
|
init: "init",
|
|
@@ -44,8 +45,9 @@ function requireMgw () {
|
|
|
44
45
|
next: "next"
|
|
45
46
|
};
|
|
46
47
|
async function runAiCommand(commandName, userPrompt, opts) {
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
const provider = ProviderManager.getProvider(opts.provider);
|
|
49
|
+
provider.assertAvailable();
|
|
50
|
+
const cmdFile = path.join(provider.getCommandsDir(), `${commandName}.md`);
|
|
49
51
|
const stageLabel = STAGE_LABELS[commandName] || commandName;
|
|
50
52
|
const issueMatch = String(userPrompt).match(/^\d+/);
|
|
51
53
|
const timer = startTimer({
|
|
@@ -57,7 +59,7 @@ function requireMgw () {
|
|
|
57
59
|
spinner.start();
|
|
58
60
|
let result;
|
|
59
61
|
try {
|
|
60
|
-
result = await
|
|
62
|
+
result = await provider.invoke(cmdFile, userPrompt, {
|
|
61
63
|
model: opts.model,
|
|
62
64
|
quiet: true,
|
|
63
65
|
dryRun: opts.dryRun,
|
|
@@ -84,7 +86,7 @@ function requireMgw () {
|
|
|
84
86
|
spinner.start();
|
|
85
87
|
await new Promise((r) => setTimeout(r, 80));
|
|
86
88
|
spinner.stop();
|
|
87
|
-
const result = await
|
|
89
|
+
const result = await provider.invoke(cmdFile, userPrompt, {
|
|
88
90
|
model: opts.model,
|
|
89
91
|
quiet: false,
|
|
90
92
|
dryRun: opts.dryRun,
|
|
@@ -433,7 +435,8 @@ function requireMgw () {
|
|
|
433
435
|
}
|
|
434
436
|
});
|
|
435
437
|
program.command("help").description("Show command reference").action(function() {
|
|
436
|
-
const
|
|
438
|
+
const opts = this.optsWithGlobals();
|
|
439
|
+
const helpMdPath = path.join(ProviderManager.getProvider(opts.provider).getCommandsDir(), "help.md");
|
|
437
440
|
let helpText;
|
|
438
441
|
try {
|
|
439
442
|
const raw = fs.readFileSync(helpMdPath, "utf-8");
|
|
@@ -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");
|
|
@@ -586,7 +587,7 @@ var hasRequiredGithub;
|
|
|
586
587
|
function requireGithub () {
|
|
587
588
|
if (hasRequiredGithub) return github;
|
|
588
589
|
hasRequiredGithub = 1;
|
|
589
|
-
const { execSync } = require$$0
|
|
590
|
+
const { execSync } = require$$0;
|
|
590
591
|
const { TimeoutError, GitHubApiError } = requireErrors();
|
|
591
592
|
const { withRetry } = requireRetry();
|
|
592
593
|
const GH_TIMEOUT_MS = 3e4;
|
|
@@ -957,16 +958,17 @@ function requireOutput () {
|
|
|
957
958
|
return output;
|
|
958
959
|
}
|
|
959
960
|
|
|
960
|
-
var
|
|
961
|
-
var
|
|
961
|
+
var providerClaude;
|
|
962
|
+
var hasRequiredProviderClaude;
|
|
962
963
|
|
|
963
|
-
function
|
|
964
|
-
if (
|
|
965
|
-
|
|
966
|
-
const { execSync, spawn } = require$$0
|
|
964
|
+
function requireProviderClaude () {
|
|
965
|
+
if (hasRequiredProviderClaude) return providerClaude;
|
|
966
|
+
hasRequiredProviderClaude = 1;
|
|
967
|
+
const { execSync, spawn } = require$$0;
|
|
967
968
|
const path = require$$1;
|
|
968
|
-
const fs = require$$
|
|
969
|
+
const fs = require$$2;
|
|
969
970
|
const { ClaudeNotAvailableError, TimeoutError } = requireErrors();
|
|
971
|
+
const PROVIDER_ID = "claude";
|
|
970
972
|
function getCommandsDir() {
|
|
971
973
|
const dir = path.join(__dirname, "..", "commands");
|
|
972
974
|
if (!fs.existsSync(dir)) {
|
|
@@ -977,7 +979,7 @@ This may indicate a corrupted installation. Try reinstalling mgw.`
|
|
|
977
979
|
}
|
|
978
980
|
return dir;
|
|
979
981
|
}
|
|
980
|
-
function
|
|
982
|
+
function assertAvailable() {
|
|
981
983
|
try {
|
|
982
984
|
execSync("claude --version", {
|
|
983
985
|
encoding: "utf-8",
|
|
@@ -1021,7 +1023,7 @@ This may indicate a corrupted installation. Try reinstalling mgw.`
|
|
|
1021
1023
|
);
|
|
1022
1024
|
}
|
|
1023
1025
|
}
|
|
1024
|
-
function
|
|
1026
|
+
function invoke(commandFile, userPrompt, opts) {
|
|
1025
1027
|
const o = opts || {};
|
|
1026
1028
|
const args = ["-p"];
|
|
1027
1029
|
if (commandFile) {
|
|
@@ -1071,12 +1073,204 @@ This may indicate a corrupted installation. Try reinstalling mgw.`
|
|
|
1071
1073
|
});
|
|
1072
1074
|
});
|
|
1073
1075
|
}
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1076
|
+
providerClaude = { PROVIDER_ID, assertAvailable, invoke, getCommandsDir };
|
|
1077
|
+
return providerClaude;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
var providerGemini;
|
|
1081
|
+
var hasRequiredProviderGemini;
|
|
1082
|
+
|
|
1083
|
+
function requireProviderGemini () {
|
|
1084
|
+
if (hasRequiredProviderGemini) return providerGemini;
|
|
1085
|
+
hasRequiredProviderGemini = 1;
|
|
1086
|
+
const { execSync, spawn } = require$$0;
|
|
1087
|
+
const path = require$$1;
|
|
1088
|
+
const fs = require$$2;
|
|
1089
|
+
const os = require$$3;
|
|
1090
|
+
const PROVIDER_ID = "gemini";
|
|
1091
|
+
function getCommandsDir() {
|
|
1092
|
+
const dir = path.join(os.homedir(), ".gemini", "commands", "mgw");
|
|
1093
|
+
if (!fs.existsSync(dir)) {
|
|
1094
|
+
throw new Error(
|
|
1095
|
+
`Commands directory not found at: ${dir}
|
|
1096
|
+
Run: node bin/mgw-install.cjs --provider gemini
|
|
1097
|
+
(or reinstall the mgw package to trigger postinstall)`
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1100
|
+
return dir;
|
|
1101
|
+
}
|
|
1102
|
+
function assertAvailable() {
|
|
1103
|
+
try {
|
|
1104
|
+
execSync("gemini --version", {
|
|
1105
|
+
encoding: "utf-8",
|
|
1106
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
1107
|
+
});
|
|
1108
|
+
} catch (err) {
|
|
1109
|
+
if (err.code === "ENOENT") {
|
|
1110
|
+
console.error(
|
|
1111
|
+
"Error: gemini CLI is not installed.\n\nInstall it with:\n npm install -g @google/gemini-cli\n\nThen run:\n gemini auth"
|
|
1112
|
+
);
|
|
1113
|
+
} else {
|
|
1114
|
+
console.error(
|
|
1115
|
+
"Error: gemini CLI check failed.\nEnsure gemini is installed and on your PATH."
|
|
1116
|
+
);
|
|
1117
|
+
}
|
|
1118
|
+
process.exit(1);
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
function invoke(commandFile, userPrompt, opts) {
|
|
1122
|
+
const o = opts || {};
|
|
1123
|
+
if (o.dryRun) {
|
|
1124
|
+
const dryArgs = ["-p"];
|
|
1125
|
+
if (o.model) dryArgs.push("--model", o.model);
|
|
1126
|
+
dryArgs.push(commandFile ? "<system>" + commandFile + "</system> " + (userPrompt || "run") : userPrompt || "run");
|
|
1127
|
+
console.log("Would invoke: gemini " + dryArgs.join(" "));
|
|
1128
|
+
return Promise.resolve({ exitCode: 0, output: "" });
|
|
1129
|
+
}
|
|
1130
|
+
let effectivePrompt = userPrompt || "run";
|
|
1131
|
+
if (commandFile) {
|
|
1132
|
+
const fileContents = fs.readFileSync(commandFile, "utf-8");
|
|
1133
|
+
effectivePrompt = "<system>\n" + fileContents + "\n</system>\n\n" + effectivePrompt;
|
|
1134
|
+
}
|
|
1135
|
+
const args = ["-p"];
|
|
1136
|
+
if (o.model) {
|
|
1137
|
+
args.push("--model", o.model);
|
|
1138
|
+
}
|
|
1139
|
+
args.push(effectivePrompt);
|
|
1140
|
+
return new Promise((resolve, reject) => {
|
|
1141
|
+
const stdio = o.quiet ? ["pipe", "pipe", "pipe"] : ["inherit", "inherit", "inherit"];
|
|
1142
|
+
const child = spawn("gemini", args, { stdio });
|
|
1143
|
+
let output = "";
|
|
1144
|
+
if (o.quiet) {
|
|
1145
|
+
child.stdout.on("data", function(chunk) {
|
|
1146
|
+
output += chunk.toString();
|
|
1147
|
+
});
|
|
1148
|
+
child.stderr.on("data", function(chunk) {
|
|
1149
|
+
output += chunk.toString();
|
|
1150
|
+
});
|
|
1151
|
+
}
|
|
1152
|
+
child.on("error", function(err) {
|
|
1153
|
+
if (err.code === "ENOENT") {
|
|
1154
|
+
reject(new Error("gemini CLI not found. Install with: npm install -g @google/gemini-cli"));
|
|
1155
|
+
} else {
|
|
1156
|
+
reject(err);
|
|
1157
|
+
}
|
|
1158
|
+
});
|
|
1159
|
+
child.on("close", function(code) {
|
|
1160
|
+
resolve({ exitCode: code || 0, output });
|
|
1161
|
+
});
|
|
1162
|
+
});
|
|
1163
|
+
}
|
|
1164
|
+
providerGemini = { PROVIDER_ID, assertAvailable, invoke, getCommandsDir };
|
|
1165
|
+
return providerGemini;
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
var providerOpencode;
|
|
1169
|
+
var hasRequiredProviderOpencode;
|
|
1170
|
+
|
|
1171
|
+
function requireProviderOpencode () {
|
|
1172
|
+
if (hasRequiredProviderOpencode) return providerOpencode;
|
|
1173
|
+
hasRequiredProviderOpencode = 1;
|
|
1174
|
+
const { execSync, spawn } = require$$0;
|
|
1175
|
+
const path = require$$1;
|
|
1176
|
+
const fs = require$$2;
|
|
1177
|
+
const os = require$$3;
|
|
1178
|
+
const PROVIDER_ID = "opencode";
|
|
1179
|
+
function getCommandsDir() {
|
|
1180
|
+
const dir = path.join(os.homedir(), ".opencode", "commands", "mgw");
|
|
1181
|
+
if (!fs.existsSync(dir)) {
|
|
1182
|
+
throw new Error(
|
|
1183
|
+
"Commands directory not found at: " + dir + "\nRun: node bin/mgw-install.cjs --provider opencode\n(or reinstall the mgw package to trigger postinstall)"
|
|
1184
|
+
);
|
|
1185
|
+
}
|
|
1186
|
+
return dir;
|
|
1187
|
+
}
|
|
1188
|
+
function assertAvailable() {
|
|
1189
|
+
try {
|
|
1190
|
+
execSync("opencode --version", {
|
|
1191
|
+
encoding: "utf-8",
|
|
1192
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
1193
|
+
});
|
|
1194
|
+
} catch (err) {
|
|
1195
|
+
if (err.code === "ENOENT") {
|
|
1196
|
+
console.error(
|
|
1197
|
+
"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)"
|
|
1198
|
+
);
|
|
1199
|
+
} else {
|
|
1200
|
+
console.error(
|
|
1201
|
+
"Error: opencode CLI check failed.\nEnsure opencode is installed and on your PATH."
|
|
1202
|
+
);
|
|
1203
|
+
}
|
|
1204
|
+
process.exit(1);
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
function invoke(commandFile, userPrompt, opts) {
|
|
1208
|
+
const o = opts || {};
|
|
1209
|
+
const args = ["run"];
|
|
1210
|
+
if (commandFile) {
|
|
1211
|
+
args.push("--system-prompt", commandFile);
|
|
1212
|
+
}
|
|
1213
|
+
if (o.model) {
|
|
1214
|
+
args.push("--model", o.model);
|
|
1215
|
+
}
|
|
1216
|
+
args.push(userPrompt || "run");
|
|
1217
|
+
if (o.dryRun) {
|
|
1218
|
+
console.log("Would invoke: opencode " + args.join(" "));
|
|
1219
|
+
return Promise.resolve({ exitCode: 0, output: "" });
|
|
1220
|
+
}
|
|
1221
|
+
return new Promise(function(resolve, reject) {
|
|
1222
|
+
const stdio = o.quiet ? ["pipe", "pipe", "pipe"] : ["inherit", "inherit", "inherit"];
|
|
1223
|
+
const child = spawn("opencode", args, { stdio });
|
|
1224
|
+
let output = "";
|
|
1225
|
+
if (o.quiet) {
|
|
1226
|
+
child.stdout.on("data", function(chunk) {
|
|
1227
|
+
output += chunk.toString();
|
|
1228
|
+
});
|
|
1229
|
+
child.stderr.on("data", function(chunk) {
|
|
1230
|
+
output += chunk.toString();
|
|
1231
|
+
});
|
|
1232
|
+
}
|
|
1233
|
+
child.on("error", function(err) {
|
|
1234
|
+
if (err.code === "ENOENT") {
|
|
1235
|
+
reject(new Error("opencode CLI not found. See https://opencode.ai for installation instructions."));
|
|
1236
|
+
} else {
|
|
1237
|
+
reject(err);
|
|
1238
|
+
}
|
|
1239
|
+
});
|
|
1240
|
+
child.on("close", function(code) {
|
|
1241
|
+
resolve({ exitCode: code || 0, output });
|
|
1242
|
+
});
|
|
1243
|
+
});
|
|
1244
|
+
}
|
|
1245
|
+
providerOpencode = { PROVIDER_ID, assertAvailable, invoke, getCommandsDir };
|
|
1246
|
+
return providerOpencode;
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
var providerManager;
|
|
1250
|
+
var hasRequiredProviderManager;
|
|
1251
|
+
|
|
1252
|
+
function requireProviderManager () {
|
|
1253
|
+
if (hasRequiredProviderManager) return providerManager;
|
|
1254
|
+
hasRequiredProviderManager = 1;
|
|
1255
|
+
const registry = {
|
|
1256
|
+
claude: requireProviderClaude(),
|
|
1257
|
+
gemini: requireProviderGemini(),
|
|
1258
|
+
opencode: requireProviderOpencode()
|
|
1078
1259
|
};
|
|
1079
|
-
|
|
1260
|
+
function getProvider(providerId) {
|
|
1261
|
+
const id = providerId || "claude";
|
|
1262
|
+
const provider = registry[id];
|
|
1263
|
+
if (!provider) {
|
|
1264
|
+
const available = Object.keys(registry).join(", ");
|
|
1265
|
+
throw new Error(`Unknown provider: "${id}". Available: ${available}`);
|
|
1266
|
+
}
|
|
1267
|
+
return provider;
|
|
1268
|
+
}
|
|
1269
|
+
function listProviders() {
|
|
1270
|
+
return Object.keys(registry);
|
|
1271
|
+
}
|
|
1272
|
+
providerManager = { ProviderManager: { getProvider, listProviders } };
|
|
1273
|
+
return providerManager;
|
|
1080
1274
|
}
|
|
1081
1275
|
|
|
1082
1276
|
var spinner;
|
|
@@ -1187,7 +1381,7 @@ function requireLogger () {
|
|
|
1187
1381
|
if (hasRequiredLogger) return logger;
|
|
1188
1382
|
hasRequiredLogger = 1;
|
|
1189
1383
|
const path = require$$1;
|
|
1190
|
-
const fs = require$$
|
|
1384
|
+
const fs = require$$2;
|
|
1191
1385
|
function getLogDir(repoRoot) {
|
|
1192
1386
|
const root = repoRoot || process.cwd();
|
|
1193
1387
|
const logDir = path.join(root, ".mgw", "logs");
|
|
@@ -1807,7 +2001,7 @@ var hasRequiredKeyboard;
|
|
|
1807
2001
|
function requireKeyboard () {
|
|
1808
2002
|
if (hasRequiredKeyboard) return keyboard;
|
|
1809
2003
|
hasRequiredKeyboard = 1;
|
|
1810
|
-
const { EventEmitter } = require$$0$
|
|
2004
|
+
const { EventEmitter } = require$$0$1;
|
|
1811
2005
|
const DEFAULT_BINDINGS = {
|
|
1812
2006
|
// Scroll
|
|
1813
2007
|
"j": "scroll-down",
|
|
@@ -2426,11 +2620,12 @@ function requireTui () {
|
|
|
2426
2620
|
}
|
|
2427
2621
|
|
|
2428
2622
|
exports.getDefaultExportFromCjs = getDefaultExportFromCjs;
|
|
2429
|
-
exports.requireClaude = requireClaude;
|
|
2430
2623
|
exports.requireErrors = requireErrors;
|
|
2431
2624
|
exports.requireGithub = requireGithub;
|
|
2432
2625
|
exports.requireLogger = requireLogger;
|
|
2433
2626
|
exports.requireOutput = requireOutput;
|
|
2627
|
+
exports.requireProviderClaude = requireProviderClaude;
|
|
2628
|
+
exports.requireProviderManager = requireProviderManager;
|
|
2434
2629
|
exports.requireRetry = requireRetry;
|
|
2435
2630
|
exports.requireSpinner = requireSpinner;
|
|
2436
2631
|
exports.requireState = requireState;
|