@gh-symphony/cli 0.0.14 → 0.0.15
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/dist/chunk-5NV3LSAJ.js +11 -0
- package/dist/chunk-6HBZC3BE.js +468 -0
- package/dist/chunk-76QPITKI.js +109 -0
- package/dist/chunk-IWR4UQEJ.js +2250 -0
- package/dist/chunk-JO3AXHQI.js +130 -0
- package/dist/chunk-M7OSMUTN.js +874 -0
- package/dist/chunk-MVRF7BES.js +68 -0
- package/dist/chunk-RNWX7DQU.js +4617 -0
- package/dist/chunk-ROGRTUFI.js +108 -0
- package/dist/chunk-TH5QPO3Y.js +67 -0
- package/dist/config-cmd-AZ7POMAA.js +110 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +568 -356
- package/dist/init-EZXQAXZM.js +17 -0
- package/dist/logs-6LNGT2GF.js +188 -0
- package/dist/project-3ELXQ35D.js +678 -0
- package/dist/recover-T6ME6C56.js +130 -0
- package/dist/repo-R3XBIVAX.js +121 -0
- package/dist/run-DYINRZHK.js +107 -0
- package/dist/start-PIFQMIC2.js +15 -0
- package/dist/status-3WK5BWRZ.js +11 -0
- package/dist/stop-AA3AP5M6.js +9 -0
- package/dist/version-VBB62JWI.js +30 -0
- package/package.json +9 -4
- package/dist/ansi.d.ts +0 -15
- package/dist/ansi.js +0 -53
- package/dist/commands/config-cmd.d.ts +0 -3
- package/dist/commands/config-cmd.js +0 -90
- package/dist/commands/help.d.ts +0 -3
- package/dist/commands/help.js +0 -55
- package/dist/commands/init.d.ts +0 -34
- package/dist/commands/init.js +0 -477
- package/dist/commands/logs.d.ts +0 -3
- package/dist/commands/logs.js +0 -184
- package/dist/commands/project.d.ts +0 -3
- package/dist/commands/project.js +0 -649
- package/dist/commands/recover.d.ts +0 -3
- package/dist/commands/recover.js +0 -119
- package/dist/commands/repo.d.ts +0 -3
- package/dist/commands/repo.js +0 -103
- package/dist/commands/run.d.ts +0 -3
- package/dist/commands/run.js +0 -95
- package/dist/commands/start.d.ts +0 -20
- package/dist/commands/start.js +0 -344
- package/dist/commands/status-refresh.d.ts +0 -9
- package/dist/commands/status-refresh.js +0 -27
- package/dist/commands/status.d.ts +0 -3
- package/dist/commands/status.js +0 -237
- package/dist/commands/stop.d.ts +0 -3
- package/dist/commands/stop.js +0 -92
- package/dist/commands/version.d.ts +0 -3
- package/dist/commands/version.js +0 -21
- package/dist/completion.d.ts +0 -1
- package/dist/completion.js +0 -204
- package/dist/config.d.ts +0 -38
- package/dist/config.js +0 -82
- package/dist/context/context-types.d.ts +0 -36
- package/dist/context/context-types.js +0 -1
- package/dist/context/generate-context-yaml.d.ts +0 -15
- package/dist/context/generate-context-yaml.js +0 -129
- package/dist/dashboard/renderer.d.ts +0 -9
- package/dist/dashboard/renderer.js +0 -220
- package/dist/detection/environment-detector.d.ts +0 -11
- package/dist/detection/environment-detector.js +0 -140
- package/dist/github/client.d.ts +0 -71
- package/dist/github/client.js +0 -348
- package/dist/github/gh-auth.d.ts +0 -34
- package/dist/github/gh-auth.js +0 -110
- package/dist/mapping/smart-defaults.d.ts +0 -17
- package/dist/mapping/smart-defaults.js +0 -86
- package/dist/orchestrator-runtime.d.ts +0 -1
- package/dist/orchestrator-runtime.js +0 -4
- package/dist/orchestrator-status-endpoint.d.ts +0 -5
- package/dist/orchestrator-status-endpoint.js +0 -27
- package/dist/project-selection.d.ts +0 -8
- package/dist/project-selection.js +0 -56
- package/dist/skills/skill-writer.d.ts +0 -14
- package/dist/skills/skill-writer.js +0 -62
- package/dist/skills/templates/commit.d.ts +0 -2
- package/dist/skills/templates/commit.js +0 -45
- package/dist/skills/templates/document.d.ts +0 -7
- package/dist/skills/templates/document.js +0 -16
- package/dist/skills/templates/gh-project.d.ts +0 -2
- package/dist/skills/templates/gh-project.js +0 -88
- package/dist/skills/templates/gh-symphony.d.ts +0 -2
- package/dist/skills/templates/gh-symphony.js +0 -125
- package/dist/skills/templates/index.d.ts +0 -8
- package/dist/skills/templates/index.js +0 -28
- package/dist/skills/templates/land.d.ts +0 -2
- package/dist/skills/templates/land.js +0 -59
- package/dist/skills/templates/pull.d.ts +0 -2
- package/dist/skills/templates/pull.js +0 -41
- package/dist/skills/templates/push.d.ts +0 -2
- package/dist/skills/templates/push.js +0 -36
- package/dist/skills/types.d.ts +0 -23
- package/dist/skills/types.js +0 -1
- package/dist/workflow/generate-reference-workflow.d.ts +0 -9
- package/dist/workflow/generate-reference-workflow.js +0 -261
- package/dist/workflow/generate-workflow-md.d.ts +0 -12
- package/dist/workflow/generate-workflow-md.js +0 -134
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
runCli
|
|
4
|
+
} from "./chunk-RNWX7DQU.js";
|
|
5
|
+
import {
|
|
6
|
+
resolveRuntimeRoot
|
|
7
|
+
} from "./chunk-5NV3LSAJ.js";
|
|
8
|
+
import {
|
|
9
|
+
handleMissingManagedProjectConfig,
|
|
10
|
+
resolveManagedProjectConfig
|
|
11
|
+
} from "./chunk-TH5QPO3Y.js";
|
|
12
|
+
import "./chunk-ROGRTUFI.js";
|
|
13
|
+
|
|
14
|
+
// src/commands/recover.ts
|
|
15
|
+
import { readFile, readdir } from "fs/promises";
|
|
16
|
+
import { join } from "path";
|
|
17
|
+
function parseRecoverArgs(args) {
|
|
18
|
+
const parsed = { dryRun: false };
|
|
19
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
20
|
+
const arg = args[i];
|
|
21
|
+
if (arg === "--dry-run") {
|
|
22
|
+
parsed.dryRun = true;
|
|
23
|
+
}
|
|
24
|
+
if (arg === "--project" || arg === "--project-id") {
|
|
25
|
+
parsed.projectId = args[i + 1];
|
|
26
|
+
i += 1;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return parsed;
|
|
30
|
+
}
|
|
31
|
+
var handler = async (args, options) => {
|
|
32
|
+
const parsed = parseRecoverArgs(args);
|
|
33
|
+
const projectConfig = await resolveManagedProjectConfig({
|
|
34
|
+
configDir: options.configDir,
|
|
35
|
+
requestedProjectId: parsed.projectId
|
|
36
|
+
});
|
|
37
|
+
if (!projectConfig) {
|
|
38
|
+
handleMissingManagedProjectConfig();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const runtimeRoot = resolveRuntimeRoot(options.configDir);
|
|
42
|
+
const projectId = projectConfig.projectId;
|
|
43
|
+
if (parsed.dryRun) {
|
|
44
|
+
process.stdout.write("Dry run \u2014 scanning for stalled runs...\n");
|
|
45
|
+
const candidates = await listRecoverCandidates(runtimeRoot, projectId);
|
|
46
|
+
if (options.json) {
|
|
47
|
+
process.stdout.write(JSON.stringify(candidates, null, 2) + "\n");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (candidates.length === 0) {
|
|
51
|
+
process.stdout.write("No recoverable runs found.\n");
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
for (const candidate of candidates) {
|
|
55
|
+
process.stdout.write(
|
|
56
|
+
`${candidate.issueIdentifier} (${candidate.runId}) \u2014 ${candidate.reason}
|
|
57
|
+
`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
process.stdout.write("Recovering stalled runs...\n");
|
|
63
|
+
await runCli([
|
|
64
|
+
"recover",
|
|
65
|
+
"--runtime-root",
|
|
66
|
+
runtimeRoot,
|
|
67
|
+
"--project-id",
|
|
68
|
+
projectId
|
|
69
|
+
]);
|
|
70
|
+
};
|
|
71
|
+
var recover_default = handler;
|
|
72
|
+
async function listRecoverCandidates(runtimeRoot, projectId) {
|
|
73
|
+
const runsDir = join(runtimeRoot, "projects", projectId, "runs");
|
|
74
|
+
const candidates = [];
|
|
75
|
+
let entries = [];
|
|
76
|
+
try {
|
|
77
|
+
entries = await readdir(runsDir);
|
|
78
|
+
} catch {
|
|
79
|
+
return candidates;
|
|
80
|
+
}
|
|
81
|
+
for (const entry of entries) {
|
|
82
|
+
const runPath = join(runsDir, entry, "run.json");
|
|
83
|
+
try {
|
|
84
|
+
const raw = await readFile(runPath, "utf8");
|
|
85
|
+
const run = JSON.parse(raw);
|
|
86
|
+
if (run.projectId !== projectId) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const reason = detectRecoveryReason(run);
|
|
90
|
+
if (!reason) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
candidates.push({
|
|
94
|
+
runId: run.runId,
|
|
95
|
+
issueIdentifier: run.issueIdentifier,
|
|
96
|
+
status: run.status,
|
|
97
|
+
reason
|
|
98
|
+
});
|
|
99
|
+
} catch {
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return candidates;
|
|
103
|
+
}
|
|
104
|
+
function detectRecoveryReason(run) {
|
|
105
|
+
if (run.processId) {
|
|
106
|
+
const startedAt = run.startedAt ? new Date(run.startedAt).getTime() : 0;
|
|
107
|
+
const runningForMs = Date.now() - startedAt;
|
|
108
|
+
if (isProcessRunning(run.processId) && runningForMs > 30 * 60 * 1e3) {
|
|
109
|
+
return "worker appears stuck";
|
|
110
|
+
}
|
|
111
|
+
if (!isProcessRunning(run.processId)) {
|
|
112
|
+
return "worker process is no longer running";
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (run.status === "retrying" && run.nextRetryAt && new Date(run.nextRetryAt).getTime() <= Date.now()) {
|
|
116
|
+
return "retry window has elapsed";
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
function isProcessRunning(pid) {
|
|
121
|
+
try {
|
|
122
|
+
process.kill(pid, 0);
|
|
123
|
+
return true;
|
|
124
|
+
} catch {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
export {
|
|
129
|
+
recover_default as default
|
|
130
|
+
};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
loadActiveProjectConfig,
|
|
4
|
+
loadGlobalConfig,
|
|
5
|
+
saveProjectConfig
|
|
6
|
+
} from "./chunk-ROGRTUFI.js";
|
|
7
|
+
|
|
8
|
+
// src/commands/repo.ts
|
|
9
|
+
var handler = async (args, options) => {
|
|
10
|
+
const [subcommand, ...rest] = args;
|
|
11
|
+
switch (subcommand) {
|
|
12
|
+
case "list":
|
|
13
|
+
await repoList(options);
|
|
14
|
+
break;
|
|
15
|
+
case "add":
|
|
16
|
+
await repoAdd(rest, options);
|
|
17
|
+
break;
|
|
18
|
+
case "remove":
|
|
19
|
+
await repoRemove(rest, options);
|
|
20
|
+
break;
|
|
21
|
+
default:
|
|
22
|
+
process.stderr.write(
|
|
23
|
+
"Usage: gh-symphony repo <list|add|remove> [repo]\n"
|
|
24
|
+
);
|
|
25
|
+
process.exitCode = 2;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
var repo_default = handler;
|
|
29
|
+
async function repoList(options) {
|
|
30
|
+
const ws = await loadActiveProjectConfig(options.configDir);
|
|
31
|
+
if (!ws) {
|
|
32
|
+
process.stderr.write("No project configured.\n");
|
|
33
|
+
process.exitCode = 1;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (options.json) {
|
|
37
|
+
process.stdout.write(JSON.stringify(ws.repositories, null, 2) + "\n");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
process.stdout.write("Repositories:\n");
|
|
41
|
+
for (const repo of ws.repositories) {
|
|
42
|
+
process.stdout.write(` ${repo.owner}/${repo.name}
|
|
43
|
+
`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async function repoAdd(args, options) {
|
|
47
|
+
const [repoSpec] = args;
|
|
48
|
+
if (!repoSpec || !repoSpec.includes("/")) {
|
|
49
|
+
process.stderr.write("Usage: gh-symphony repo add <owner/name>\n");
|
|
50
|
+
process.exitCode = 2;
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const global = await loadGlobalConfig(options.configDir);
|
|
54
|
+
if (!global?.activeProject) {
|
|
55
|
+
process.stderr.write("No active project.\n");
|
|
56
|
+
process.exitCode = 1;
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const ws = await loadActiveProjectConfig(options.configDir);
|
|
60
|
+
if (!ws) {
|
|
61
|
+
process.stderr.write("Project config missing.\n");
|
|
62
|
+
process.exitCode = 1;
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const [owner, name] = repoSpec.split("/");
|
|
66
|
+
if (!owner || !name) {
|
|
67
|
+
process.stderr.write("Invalid repo format. Use: owner/name\n");
|
|
68
|
+
process.exitCode = 2;
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (ws.repositories.some((r) => r.owner === owner && r.name === name)) {
|
|
72
|
+
process.stdout.write(`Repository ${repoSpec} is already configured.
|
|
73
|
+
`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
ws.repositories.push({
|
|
77
|
+
owner,
|
|
78
|
+
name,
|
|
79
|
+
cloneUrl: `https://github.com/${owner}/${name}.git`
|
|
80
|
+
});
|
|
81
|
+
await saveProjectConfig(options.configDir, global.activeProject, ws);
|
|
82
|
+
process.stdout.write(`Added repository: ${repoSpec}
|
|
83
|
+
`);
|
|
84
|
+
}
|
|
85
|
+
async function repoRemove(args, options) {
|
|
86
|
+
const [repoSpec] = args;
|
|
87
|
+
if (!repoSpec || !repoSpec.includes("/")) {
|
|
88
|
+
process.stderr.write("Usage: gh-symphony repo remove <owner/name>\n");
|
|
89
|
+
process.exitCode = 2;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const global = await loadGlobalConfig(options.configDir);
|
|
93
|
+
if (!global?.activeProject) {
|
|
94
|
+
process.stderr.write("No active project.\n");
|
|
95
|
+
process.exitCode = 1;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const ws = await loadActiveProjectConfig(options.configDir);
|
|
99
|
+
if (!ws) {
|
|
100
|
+
process.stderr.write("Project config missing.\n");
|
|
101
|
+
process.exitCode = 1;
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const [owner, name] = repoSpec.split("/");
|
|
105
|
+
const idx = ws.repositories.findIndex(
|
|
106
|
+
(r) => r.owner === owner && r.name === name
|
|
107
|
+
);
|
|
108
|
+
if (idx === -1) {
|
|
109
|
+
process.stderr.write(`Repository ${repoSpec} is not configured.
|
|
110
|
+
`);
|
|
111
|
+
process.exitCode = 1;
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
ws.repositories.splice(idx, 1);
|
|
115
|
+
await saveProjectConfig(options.configDir, global.activeProject, ws);
|
|
116
|
+
process.stdout.write(`Removed repository: ${repoSpec}
|
|
117
|
+
`);
|
|
118
|
+
}
|
|
119
|
+
export {
|
|
120
|
+
repo_default as default
|
|
121
|
+
};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
runCli
|
|
4
|
+
} from "./chunk-RNWX7DQU.js";
|
|
5
|
+
import {
|
|
6
|
+
resolveRuntimeRoot
|
|
7
|
+
} from "./chunk-5NV3LSAJ.js";
|
|
8
|
+
import {
|
|
9
|
+
handleMissingManagedProjectConfig,
|
|
10
|
+
resolveManagedProjectConfig
|
|
11
|
+
} from "./chunk-TH5QPO3Y.js";
|
|
12
|
+
import "./chunk-ROGRTUFI.js";
|
|
13
|
+
|
|
14
|
+
// src/commands/run.ts
|
|
15
|
+
function parseRunArgs(args) {
|
|
16
|
+
const parsed = {
|
|
17
|
+
watch: false
|
|
18
|
+
};
|
|
19
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
20
|
+
const arg = args[i];
|
|
21
|
+
if (arg === "--watch" || arg === "-w") {
|
|
22
|
+
parsed.watch = true;
|
|
23
|
+
} else if (arg === "--project" || arg === "--project-id") {
|
|
24
|
+
const value = args[i + 1];
|
|
25
|
+
if (!value || value.startsWith("-")) {
|
|
26
|
+
parsed.error = `Option '${arg}' argument missing`;
|
|
27
|
+
return parsed;
|
|
28
|
+
}
|
|
29
|
+
parsed.projectId = value;
|
|
30
|
+
i += 1;
|
|
31
|
+
} else if (arg === "--log-level") {
|
|
32
|
+
const value = args[i + 1];
|
|
33
|
+
if (!value || value.startsWith("-")) {
|
|
34
|
+
parsed.error = `Option '${arg}' argument missing`;
|
|
35
|
+
return parsed;
|
|
36
|
+
}
|
|
37
|
+
parsed.logLevel = value;
|
|
38
|
+
i += 1;
|
|
39
|
+
} else if (!arg?.startsWith("-")) {
|
|
40
|
+
parsed.issue = arg;
|
|
41
|
+
} else {
|
|
42
|
+
parsed.error = `Unknown option '${arg}'`;
|
|
43
|
+
return parsed;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return parsed;
|
|
47
|
+
}
|
|
48
|
+
var handler = async (args, options) => {
|
|
49
|
+
const parsed = parseRunArgs(args);
|
|
50
|
+
if (parsed.error) {
|
|
51
|
+
process.stderr.write(`${parsed.error}
|
|
52
|
+
`);
|
|
53
|
+
process.exitCode = 2;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (!parsed.issue) {
|
|
57
|
+
process.stderr.write("Usage: gh-symphony run <owner/repo#number>\n");
|
|
58
|
+
process.exitCode = 2;
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const projectConfig = await resolveManagedProjectConfig({
|
|
62
|
+
configDir: options.configDir,
|
|
63
|
+
requestedProjectId: parsed.projectId
|
|
64
|
+
});
|
|
65
|
+
if (!projectConfig) {
|
|
66
|
+
handleMissingManagedProjectConfig();
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const runtimeRoot = resolveRuntimeRoot(options.configDir);
|
|
70
|
+
const projectId = projectConfig.projectId;
|
|
71
|
+
const [repoSpec] = parsed.issue.split("#");
|
|
72
|
+
if (repoSpec && !projectConfig.repositories.some((r) => `${r.owner}/${r.name}` === repoSpec)) {
|
|
73
|
+
process.stderr.write(
|
|
74
|
+
`Repository "${repoSpec}" is not configured in this project.
|
|
75
|
+
Configured repos: ${projectConfig.repositories.map((r) => `${r.owner}/${r.name}`).join(", ")}
|
|
76
|
+
`
|
|
77
|
+
);
|
|
78
|
+
process.exitCode = 1;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
process.stdout.write(`Dispatching issue: ${parsed.issue}
|
|
82
|
+
`);
|
|
83
|
+
await runCli([
|
|
84
|
+
"run-issue",
|
|
85
|
+
"--runtime-root",
|
|
86
|
+
runtimeRoot,
|
|
87
|
+
"--project-id",
|
|
88
|
+
projectId,
|
|
89
|
+
"--issue",
|
|
90
|
+
parsed.issue,
|
|
91
|
+
...parsed.logLevel ? ["--log-level", parsed.logLevel] : []
|
|
92
|
+
]);
|
|
93
|
+
if (parsed.watch) {
|
|
94
|
+
process.stdout.write("\nWatching for status changes...\n");
|
|
95
|
+
await runCli([
|
|
96
|
+
"status",
|
|
97
|
+
"--runtime-root",
|
|
98
|
+
runtimeRoot,
|
|
99
|
+
"--project-id",
|
|
100
|
+
projectId
|
|
101
|
+
]);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
var run_default = handler;
|
|
105
|
+
export {
|
|
106
|
+
run_default as default
|
|
107
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
shutdownForegroundOrchestrator,
|
|
4
|
+
start_default
|
|
5
|
+
} from "./chunk-M7OSMUTN.js";
|
|
6
|
+
import "./chunk-JO3AXHQI.js";
|
|
7
|
+
import "./chunk-MVRF7BES.js";
|
|
8
|
+
import "./chunk-RNWX7DQU.js";
|
|
9
|
+
import "./chunk-5NV3LSAJ.js";
|
|
10
|
+
import "./chunk-TH5QPO3Y.js";
|
|
11
|
+
import "./chunk-ROGRTUFI.js";
|
|
12
|
+
export {
|
|
13
|
+
start_default as default,
|
|
14
|
+
shutdownForegroundOrchestrator
|
|
15
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/commands/version.ts
|
|
4
|
+
import { readFile } from "fs/promises";
|
|
5
|
+
import { resolve, dirname } from "path";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
var handler = async (_args, options) => {
|
|
8
|
+
let version = "0.0.0";
|
|
9
|
+
try {
|
|
10
|
+
const pkgPath = resolve(
|
|
11
|
+
dirname(fileURLToPath(import.meta.url)),
|
|
12
|
+
"..",
|
|
13
|
+
"..",
|
|
14
|
+
"package.json"
|
|
15
|
+
);
|
|
16
|
+
const pkg = JSON.parse(await readFile(pkgPath, "utf8"));
|
|
17
|
+
version = pkg.version ?? version;
|
|
18
|
+
} catch {
|
|
19
|
+
}
|
|
20
|
+
if (options.json) {
|
|
21
|
+
process.stdout.write(JSON.stringify({ version }) + "\n");
|
|
22
|
+
} else {
|
|
23
|
+
process.stdout.write(`gh-symphony v${version}
|
|
24
|
+
`);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
var version_default = handler;
|
|
28
|
+
export {
|
|
29
|
+
version_default as default
|
|
30
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gh-symphony/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.15",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "hojinzs",
|
|
6
6
|
"description": "Interactive CLI for GitHub Symphony orchestration",
|
|
@@ -37,13 +37,18 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@clack/prompts": "^0.9.1",
|
|
39
39
|
"commander": "^14.0.1",
|
|
40
|
+
"liquidjs": "^10.25.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"tsup": "^8.5.1",
|
|
40
44
|
"@gh-symphony/core": "0.0.14",
|
|
41
|
-
"@gh-symphony/tracker-github": "0.0.14",
|
|
42
45
|
"@gh-symphony/orchestrator": "0.0.14",
|
|
43
|
-
"@gh-symphony/
|
|
46
|
+
"@gh-symphony/dashboard": "0.0.14",
|
|
47
|
+
"@gh-symphony/worker": "0.0.14",
|
|
48
|
+
"@gh-symphony/tracker-github": "0.0.14"
|
|
44
49
|
},
|
|
45
50
|
"scripts": {
|
|
46
|
-
"build": "
|
|
51
|
+
"build": "tsup",
|
|
47
52
|
"lint": "eslint src --ext .ts",
|
|
48
53
|
"test": "vitest run --passWithNoTests",
|
|
49
54
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
package/dist/ansi.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export declare const ESC = "\u001B[";
|
|
2
|
-
export declare function bold(s: string): string;
|
|
3
|
-
export declare function dim(s: string): string;
|
|
4
|
-
export declare function green(s: string): string;
|
|
5
|
-
export declare function red(s: string): string;
|
|
6
|
-
export declare function yellow(s: string): string;
|
|
7
|
-
export declare function cyan(s: string): string;
|
|
8
|
-
export declare function magenta(s: string): string;
|
|
9
|
-
export declare function blue(s: string): string;
|
|
10
|
-
export declare function stripAnsi(s: string): string;
|
|
11
|
-
export declare function setNoColor(value: boolean): void;
|
|
12
|
-
export declare function getNoColor(): boolean;
|
|
13
|
-
export declare function clearScreen(): string;
|
|
14
|
-
export declare function hideCursor(): string;
|
|
15
|
-
export declare function showCursor(): string;
|
package/dist/ansi.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
// ── ANSI color and formatting utilities ────────────────────────────────────
|
|
2
|
-
export const ESC = "\x1b[";
|
|
3
|
-
let noColor = false;
|
|
4
|
-
const _bold = (s) => `${ESC}1m${s}${ESC}0m`;
|
|
5
|
-
const _dim = (s) => `${ESC}2m${s}${ESC}0m`;
|
|
6
|
-
const _green = (s) => `${ESC}32m${s}${ESC}0m`;
|
|
7
|
-
const _red = (s) => `${ESC}31m${s}${ESC}0m`;
|
|
8
|
-
const _yellow = (s) => `${ESC}33m${s}${ESC}0m`;
|
|
9
|
-
const _cyan = (s) => `${ESC}36m${s}${ESC}0m`;
|
|
10
|
-
const _magenta = (s) => `${ESC}35m${s}${ESC}0m`;
|
|
11
|
-
const _blue = (s) => `${ESC}34m${s}${ESC}0m`;
|
|
12
|
-
export function bold(s) {
|
|
13
|
-
return noColor ? s : _bold(s);
|
|
14
|
-
}
|
|
15
|
-
export function dim(s) {
|
|
16
|
-
return noColor ? s : _dim(s);
|
|
17
|
-
}
|
|
18
|
-
export function green(s) {
|
|
19
|
-
return noColor ? s : _green(s);
|
|
20
|
-
}
|
|
21
|
-
export function red(s) {
|
|
22
|
-
return noColor ? s : _red(s);
|
|
23
|
-
}
|
|
24
|
-
export function yellow(s) {
|
|
25
|
-
return noColor ? s : _yellow(s);
|
|
26
|
-
}
|
|
27
|
-
export function cyan(s) {
|
|
28
|
-
return noColor ? s : _cyan(s);
|
|
29
|
-
}
|
|
30
|
-
export function magenta(s) {
|
|
31
|
-
return noColor ? s : _magenta(s);
|
|
32
|
-
}
|
|
33
|
-
export function blue(s) {
|
|
34
|
-
return noColor ? s : _blue(s);
|
|
35
|
-
}
|
|
36
|
-
export function stripAnsi(s) {
|
|
37
|
-
return s.replace(new RegExp(`${ESC}\\[[0-9;]*m`, "g"), "");
|
|
38
|
-
}
|
|
39
|
-
export function setNoColor(value) {
|
|
40
|
-
noColor = value;
|
|
41
|
-
}
|
|
42
|
-
export function getNoColor() {
|
|
43
|
-
return noColor;
|
|
44
|
-
}
|
|
45
|
-
export function clearScreen() {
|
|
46
|
-
return "\x1b[2J\x1b[H";
|
|
47
|
-
}
|
|
48
|
-
export function hideCursor() {
|
|
49
|
-
return "\x1b[?25l";
|
|
50
|
-
}
|
|
51
|
-
export function showCursor() {
|
|
52
|
-
return "\x1b[?25h";
|
|
53
|
-
}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
import { loadGlobalConfig, saveGlobalConfig, configFilePath, } from "../config.js";
|
|
3
|
-
const handler = async (args, options) => {
|
|
4
|
-
const [subcommand, ...rest] = args;
|
|
5
|
-
switch (subcommand) {
|
|
6
|
-
case "show":
|
|
7
|
-
await configShow(options);
|
|
8
|
-
break;
|
|
9
|
-
case "set":
|
|
10
|
-
await configSet(rest, options);
|
|
11
|
-
break;
|
|
12
|
-
case "edit":
|
|
13
|
-
await configEdit(options);
|
|
14
|
-
break;
|
|
15
|
-
default:
|
|
16
|
-
process.stderr.write("Usage: gh-symphony config <show|set|edit>\n");
|
|
17
|
-
process.exitCode = 2;
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
export default handler;
|
|
21
|
-
// ── 7.1: config show ─────────────────────────────────────────────────────────
|
|
22
|
-
async function configShow(options) {
|
|
23
|
-
const config = await loadGlobalConfig(options.configDir);
|
|
24
|
-
if (!config) {
|
|
25
|
-
process.stderr.write("No configuration found. Run 'gh-symphony init'.\n");
|
|
26
|
-
process.exitCode = 1;
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
if (options.json) {
|
|
30
|
-
process.stdout.write(JSON.stringify(config, null, 2) + "\n");
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
process.stdout.write(`Config: ${configFilePath(options.configDir)}\n\n`);
|
|
34
|
-
process.stdout.write(`Active project: ${config.activeProject ?? "none"}\n`);
|
|
35
|
-
process.stdout.write(`Projects: ${config.projects.join(", ") || "none"}\n`);
|
|
36
|
-
}
|
|
37
|
-
// ── 7.2: config set ──────────────────────────────────────────────────────────
|
|
38
|
-
const VALID_KEYS = {
|
|
39
|
-
"active-project": { type: "string" },
|
|
40
|
-
};
|
|
41
|
-
async function configSet(args, options) {
|
|
42
|
-
const [key, value] = args;
|
|
43
|
-
if (!key || value === undefined) {
|
|
44
|
-
process.stderr.write("Usage: gh-symphony config set <key> <value>\n");
|
|
45
|
-
process.stderr.write(`Valid keys: ${Object.keys(VALID_KEYS).join(", ")}\n`);
|
|
46
|
-
process.exitCode = 2;
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
const keyDef = VALID_KEYS[key];
|
|
50
|
-
if (!keyDef) {
|
|
51
|
-
process.stderr.write(`Unknown config key: ${key}\nValid keys: ${Object.keys(VALID_KEYS).join(", ")}\n`);
|
|
52
|
-
process.exitCode = 2;
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
const config = (await loadGlobalConfig(options.configDir)) ??
|
|
56
|
-
{
|
|
57
|
-
activeProject: null,
|
|
58
|
-
projects: [],
|
|
59
|
-
};
|
|
60
|
-
switch (key) {
|
|
61
|
-
case "active-project":
|
|
62
|
-
if (!config.projects.includes(value)) {
|
|
63
|
-
process.stderr.write(`Project "${value}" not found. Available: ${config.projects.join(", ")}\n`);
|
|
64
|
-
process.exitCode = 1;
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
config.activeProject = value;
|
|
68
|
-
break;
|
|
69
|
-
}
|
|
70
|
-
await saveGlobalConfig(options.configDir, config);
|
|
71
|
-
process.stdout.write(`Set ${key} = ${value}\n`);
|
|
72
|
-
}
|
|
73
|
-
// ── 7.3: config edit ─────────────────────────────────────────────────────────
|
|
74
|
-
async function configEdit(options) {
|
|
75
|
-
const editor = process.env.EDITOR || process.env.VISUAL || "vi";
|
|
76
|
-
const path = configFilePath(options.configDir);
|
|
77
|
-
const child = spawn(editor, [path], {
|
|
78
|
-
stdio: "inherit",
|
|
79
|
-
});
|
|
80
|
-
await new Promise((resolve, reject) => {
|
|
81
|
-
child.on("close", (code) => {
|
|
82
|
-
if (code === 0) {
|
|
83
|
-
resolve();
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
reject(new Error(`Editor exited with code ${code}`));
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
}
|
package/dist/commands/help.d.ts
DELETED
package/dist/commands/help.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
const HELP_TEXT = `
|
|
2
|
-
gh-symphony — AI Coding Agent Orchestrator
|
|
3
|
-
|
|
4
|
-
Usage: gh-symphony <command> [options]
|
|
5
|
-
|
|
6
|
-
Setup:
|
|
7
|
-
init Interactive project setup wizard
|
|
8
|
-
config show Show current configuration
|
|
9
|
-
config set Set a configuration value
|
|
10
|
-
config edit Open config in $EDITOR
|
|
11
|
-
|
|
12
|
-
Orchestration:
|
|
13
|
-
start Start the orchestrator (foreground)
|
|
14
|
-
start --daemon Start the orchestrator (background)
|
|
15
|
-
stop Stop the background orchestrator
|
|
16
|
-
status Show orchestrator status
|
|
17
|
-
run <issue> Dispatch a single issue
|
|
18
|
-
recover Recover stalled runs
|
|
19
|
-
logs View orchestrator logs
|
|
20
|
-
|
|
21
|
-
Project Management:
|
|
22
|
-
project add Add a new project (interactive wizard)
|
|
23
|
-
project list List all configured projects
|
|
24
|
-
project remove Remove a project
|
|
25
|
-
|
|
26
|
-
Project / Repo:
|
|
27
|
-
project list List projects
|
|
28
|
-
project switch Switch active project
|
|
29
|
-
project status Show orchestrator status for a project
|
|
30
|
-
repo list List configured repositories
|
|
31
|
-
repo add Add a repository
|
|
32
|
-
repo remove Remove a repository
|
|
33
|
-
|
|
34
|
-
Global Options:
|
|
35
|
-
--config <dir> Config directory (default: ~/.gh-symphony)
|
|
36
|
-
--verbose Enable verbose output
|
|
37
|
-
--json Output in JSON format
|
|
38
|
-
--no-color Disable color output
|
|
39
|
-
--help, -h Show this help message
|
|
40
|
-
--version, -V Show version
|
|
41
|
-
|
|
42
|
-
Examples:
|
|
43
|
-
gh-symphony project add # Add a project (interactive)
|
|
44
|
-
gh-symphony project add --non-interactive --project <id> --workspace-dir <path>
|
|
45
|
-
gh-symphony project list # List all projects
|
|
46
|
-
gh-symphony project remove <id> # Remove a project
|
|
47
|
-
gh-symphony start # Start orchestrator
|
|
48
|
-
gh-symphony start --daemon # Start in background
|
|
49
|
-
gh-symphony run org/repo#123 # Dispatch a specific issue
|
|
50
|
-
gh-symphony status --watch # Watch status in real-time
|
|
51
|
-
`.trimStart();
|
|
52
|
-
const handler = async (_args, _options) => {
|
|
53
|
-
process.stdout.write(HELP_TEXT);
|
|
54
|
-
};
|
|
55
|
-
export default handler;
|