@gh-symphony/cli 0.0.6 → 0.0.7
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 +11 -11
- package/dist/commands/config-cmd.js +9 -9
- package/dist/commands/help.js +12 -12
- package/dist/commands/init.d.ts +3 -3
- package/dist/commands/init.js +27 -26
- package/dist/commands/logs.js +11 -5
- package/dist/commands/parse-cli-args.d.ts +6 -0
- package/dist/commands/parse-cli-args.js +20 -0
- package/dist/commands/project.js +592 -62
- package/dist/commands/recover.js +13 -13
- package/dist/commands/repo.js +13 -13
- package/dist/commands/run.js +15 -15
- package/dist/commands/start.d.ts +11 -0
- package/dist/commands/start.js +162 -129
- package/dist/commands/status-refresh.d.ts +1 -0
- package/dist/commands/status-refresh.js +7 -1
- package/dist/commands/status.js +41 -48
- package/dist/commands/stop.js +37 -7
- package/dist/config.d.ts +18 -16
- package/dist/config.js +29 -19
- package/dist/dashboard/renderer.d.ts +2 -2
- package/dist/dashboard/renderer.js +5 -5
- package/dist/index.js +0 -1
- package/dist/orchestrator-runtime.d.ts +4 -4
- package/dist/orchestrator-runtime.js +11 -11
- package/dist/orchestrator-status-endpoint.d.ts +5 -0
- package/dist/orchestrator-status-endpoint.js +27 -0
- package/dist/skills/types.d.ts +1 -1
- package/package.json +5 -5
package/dist/commands/status.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { resolveRuntimeRoot,
|
|
3
|
+
import { resolveRuntimeRoot, resolveProjectConfig, syncProjectToRuntime, } from "../orchestrator-runtime.js";
|
|
4
4
|
import { bold, dim, green, red, yellow, cyan, stripAnsi } from "../ansi.js";
|
|
5
5
|
import { clearScreen, showCursor, hideCursor } from "../ansi.js";
|
|
6
6
|
import { renderDashboard } from "../dashboard/renderer.js";
|
|
7
|
+
import { resolveProjectOrchestratorStatusBaseUrl } from "../orchestrator-status-endpoint.js";
|
|
7
8
|
import { requestOrchestratorRefresh } from "./status-refresh.js";
|
|
9
|
+
import { parseCliArgs } from "./parse-cli-args.js";
|
|
8
10
|
const WATCH_REFRESH_TIMEOUT_MS = 1_500;
|
|
9
11
|
function healthIcon(health) {
|
|
10
12
|
switch (health) {
|
|
@@ -107,22 +109,22 @@ function renderLegacyStatus(snapshot, noColor) {
|
|
|
107
109
|
return lines.join("\n");
|
|
108
110
|
}
|
|
109
111
|
function parseStatusArgs(args) {
|
|
110
|
-
const parsed = {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
112
|
+
const parsed = parseCliArgs(args, {
|
|
113
|
+
watch: { type: "boolean", short: "w" },
|
|
114
|
+
project: { type: "string" },
|
|
115
|
+
"project-id": { type: "string" },
|
|
116
|
+
});
|
|
117
|
+
if ("error" in parsed) {
|
|
118
|
+
return { watch: false, error: parsed.error };
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
watch: Boolean(parsed.values.watch),
|
|
122
|
+
projectId: (parsed.values["project-id"] ?? parsed.values.project),
|
|
123
|
+
};
|
|
122
124
|
}
|
|
123
|
-
async function readStatusSnapshot(runtimeRoot,
|
|
125
|
+
async function readStatusSnapshot(runtimeRoot, projectId) {
|
|
124
126
|
try {
|
|
125
|
-
const statusPath = join(runtimeRoot, "orchestrator", "
|
|
127
|
+
const statusPath = join(runtimeRoot, "orchestrator", "projects", projectId, "status.json");
|
|
126
128
|
const content = await readFile(statusPath, "utf-8");
|
|
127
129
|
return JSON.parse(content);
|
|
128
130
|
}
|
|
@@ -130,56 +132,47 @@ async function readStatusSnapshot(runtimeRoot, tenantId) {
|
|
|
130
132
|
return null;
|
|
131
133
|
}
|
|
132
134
|
}
|
|
133
|
-
async function readAllStatusSnapshots(runtimeRoot) {
|
|
134
|
-
try {
|
|
135
|
-
const tenantsDir = join(runtimeRoot, "orchestrator", "tenants");
|
|
136
|
-
const { readdir } = await import("node:fs/promises");
|
|
137
|
-
const entries = await readdir(tenantsDir, { withFileTypes: true });
|
|
138
|
-
const snapshots = [];
|
|
139
|
-
for (const entry of entries) {
|
|
140
|
-
if (!entry.isDirectory())
|
|
141
|
-
continue;
|
|
142
|
-
const statusPath = join(tenantsDir, entry.name, "status.json");
|
|
143
|
-
try {
|
|
144
|
-
const content = await readFile(statusPath, "utf-8");
|
|
145
|
-
snapshots.push(JSON.parse(content));
|
|
146
|
-
}
|
|
147
|
-
catch {
|
|
148
|
-
// skip missing/invalid files
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
return snapshots;
|
|
152
|
-
}
|
|
153
|
-
catch {
|
|
154
|
-
return [];
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
135
|
const handler = async (args, options) => {
|
|
158
136
|
const parsed = parseStatusArgs(args);
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
process.stderr.write("
|
|
137
|
+
if (parsed.error) {
|
|
138
|
+
process.stderr.write(`${parsed.error}\n`);
|
|
139
|
+
process.stderr.write("Usage: gh-symphony status [--project-id <project-id>] [--watch]\n");
|
|
140
|
+
process.exitCode = 2;
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const projectConfig = await resolveProjectConfig(options.configDir, parsed.projectId);
|
|
144
|
+
if (!projectConfig) {
|
|
145
|
+
process.stderr.write("No project configured. Run 'gh-symphony project add' first.\n");
|
|
162
146
|
process.exitCode = 1;
|
|
163
147
|
return;
|
|
164
148
|
}
|
|
165
149
|
const runtimeRoot = resolveRuntimeRoot(options.configDir);
|
|
166
|
-
const
|
|
167
|
-
await
|
|
150
|
+
const projectId = projectConfig.projectId;
|
|
151
|
+
await syncProjectToRuntime(options.configDir, projectConfig);
|
|
168
152
|
if (parsed.watch) {
|
|
169
153
|
const isTTY = process.stdout.isTTY === true;
|
|
170
154
|
let terminalWidth = process.stdout.columns ?? 115;
|
|
171
155
|
let runPromise = null;
|
|
172
156
|
const run = async () => {
|
|
157
|
+
const baseUrl = await resolveProjectOrchestratorStatusBaseUrl({
|
|
158
|
+
configDir: options.configDir,
|
|
159
|
+
projectId,
|
|
160
|
+
});
|
|
173
161
|
await requestOrchestratorRefresh({
|
|
162
|
+
baseUrl,
|
|
174
163
|
timeoutMs: WATCH_REFRESH_TIMEOUT_MS,
|
|
175
164
|
});
|
|
176
|
-
const
|
|
165
|
+
const snapshot = await readStatusSnapshot(runtimeRoot, projectId);
|
|
177
166
|
if (options.json || !isTTY) {
|
|
178
|
-
process.stdout.write(JSON.stringify(
|
|
167
|
+
process.stdout.write(JSON.stringify(snapshot, null, 2) + "\n");
|
|
179
168
|
}
|
|
180
169
|
else {
|
|
170
|
+
if (!snapshot) {
|
|
171
|
+
process.stdout.write(clearScreen() + "Unable to read status snapshot.\n");
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
181
174
|
process.stdout.write(clearScreen() +
|
|
182
|
-
renderDashboard(
|
|
175
|
+
renderDashboard([snapshot], {
|
|
183
176
|
terminalWidth,
|
|
184
177
|
noColor: options.noColor,
|
|
185
178
|
}) +
|
|
@@ -213,7 +206,7 @@ const handler = async (args, options) => {
|
|
|
213
206
|
await new Promise(() => { });
|
|
214
207
|
}
|
|
215
208
|
// Single status query
|
|
216
|
-
const snapshot = await readStatusSnapshot(runtimeRoot,
|
|
209
|
+
const snapshot = await readStatusSnapshot(runtimeRoot, projectId);
|
|
217
210
|
if (snapshot) {
|
|
218
211
|
if (options.json) {
|
|
219
212
|
process.stdout.write(JSON.stringify(snapshot, null, 2) + "\n");
|
package/dist/commands/stop.js
CHANGED
|
@@ -1,17 +1,43 @@
|
|
|
1
1
|
import { readFile, rm } from "node:fs/promises";
|
|
2
|
-
import { daemonPidPath } from "../config.js";
|
|
2
|
+
import { daemonPidPath, orchestratorPortPath } from "../config.js";
|
|
3
|
+
import { parseCliArgs } from "./parse-cli-args.js";
|
|
3
4
|
function parseStopArgs(args) {
|
|
4
|
-
|
|
5
|
+
const parsed = parseCliArgs(args, {
|
|
6
|
+
force: { type: "boolean" },
|
|
7
|
+
project: { type: "string" },
|
|
8
|
+
"project-id": { type: "string" },
|
|
9
|
+
});
|
|
10
|
+
if ("error" in parsed) {
|
|
11
|
+
return { force: false, error: parsed.error };
|
|
12
|
+
}
|
|
13
|
+
return {
|
|
14
|
+
force: Boolean(parsed.values.force),
|
|
15
|
+
projectId: (parsed.values["project-id"] ?? parsed.values.project),
|
|
16
|
+
};
|
|
5
17
|
}
|
|
6
18
|
const handler = async (args, options) => {
|
|
7
|
-
const
|
|
8
|
-
|
|
19
|
+
const parsed = parseStopArgs(args);
|
|
20
|
+
if (parsed.error) {
|
|
21
|
+
process.stderr.write(`${parsed.error}\n`);
|
|
22
|
+
process.stderr.write("Usage: gh-symphony stop --project-id <project-id> [--force]\n");
|
|
23
|
+
process.exitCode = 2;
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (!parsed.projectId) {
|
|
27
|
+
process.stderr.write("Usage: gh-symphony stop --project-id <project-id> [--force]\n");
|
|
28
|
+
process.exitCode = 2;
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const resolvedForce = parsed.force;
|
|
32
|
+
const resolvedProjectId = parsed.projectId;
|
|
33
|
+
const pidPath = daemonPidPath(options.configDir, resolvedProjectId);
|
|
34
|
+
const portPath = orchestratorPortPath(options.configDir, resolvedProjectId);
|
|
9
35
|
let pidStr;
|
|
10
36
|
try {
|
|
11
37
|
pidStr = await readFile(pidPath, "utf8");
|
|
12
38
|
}
|
|
13
39
|
catch {
|
|
14
|
-
process.stderr.write(
|
|
40
|
+
process.stderr.write(`No running daemon found for project "${resolvedProjectId}" (PID file missing).\n`);
|
|
15
41
|
process.exitCode = 1;
|
|
16
42
|
return;
|
|
17
43
|
}
|
|
@@ -26,11 +52,12 @@ const handler = async (args, options) => {
|
|
|
26
52
|
process.kill(pid, 0);
|
|
27
53
|
}
|
|
28
54
|
catch {
|
|
29
|
-
process.stdout.write(`Daemon (PID ${pid}) is not running. Cleaning up PID file.\n`);
|
|
55
|
+
process.stdout.write(`Daemon for project "${resolvedProjectId}" (PID ${pid}) is not running. Cleaning up PID file.\n`);
|
|
30
56
|
await rm(pidPath, { force: true });
|
|
57
|
+
await rm(portPath, { force: true });
|
|
31
58
|
return;
|
|
32
59
|
}
|
|
33
|
-
const signal =
|
|
60
|
+
const signal = resolvedForce ? "SIGKILL" : "SIGTERM";
|
|
34
61
|
try {
|
|
35
62
|
process.kill(pid, signal);
|
|
36
63
|
process.stdout.write(`Sent ${signal} to orchestrator (PID ${pid}).\n`);
|
|
@@ -41,6 +68,9 @@ const handler = async (args, options) => {
|
|
|
41
68
|
return;
|
|
42
69
|
}
|
|
43
70
|
await rm(pidPath, { force: true });
|
|
71
|
+
if (resolvedForce) {
|
|
72
|
+
await rm(portPath, { force: true });
|
|
73
|
+
}
|
|
44
74
|
process.stdout.write("Daemon stopped.\n");
|
|
45
75
|
};
|
|
46
76
|
export default handler;
|
package/dist/config.d.ts
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { OrchestratorProjectConfig } from "@gh-symphony/core";
|
|
2
2
|
export declare const DEFAULT_CONFIG_DIR: string;
|
|
3
3
|
export declare const CONFIG_FILE = "config.json";
|
|
4
4
|
export declare const DAEMON_PID_FILE = "daemon.pid";
|
|
5
|
-
export declare const
|
|
5
|
+
export declare const ORCHESTRATOR_LOG_FILE = "orchestrator.log";
|
|
6
|
+
export declare const ORCHESTRATOR_PORT_FILE = "port";
|
|
6
7
|
export type CliGlobalConfig = {
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
activeProject: string | null;
|
|
9
|
+
projects: string[];
|
|
9
10
|
};
|
|
10
|
-
export type
|
|
11
|
+
export type CliProjectTrackerSettings = Record<string, string | boolean> & {
|
|
11
12
|
projectId?: string;
|
|
12
13
|
assignedOnly?: boolean;
|
|
13
14
|
};
|
|
14
|
-
export type
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
export type CliProjectConfig = Omit<OrchestratorProjectConfig, "tracker"> & {
|
|
16
|
+
displayName?: string;
|
|
17
|
+
tracker: Omit<OrchestratorProjectConfig["tracker"], "settings"> & {
|
|
18
|
+
settings?: CliProjectTrackerSettings;
|
|
17
19
|
};
|
|
18
20
|
};
|
|
19
21
|
export type StateRole = "active" | "wait" | "terminal";
|
|
@@ -23,13 +25,13 @@ export type StateMapping = {
|
|
|
23
25
|
};
|
|
24
26
|
export declare function resolveConfigDir(override?: string): string;
|
|
25
27
|
export declare function configFilePath(configDir: string): string;
|
|
26
|
-
export declare function
|
|
27
|
-
export declare function
|
|
28
|
-
export declare function daemonPidPath(configDir: string): string;
|
|
29
|
-
export declare function
|
|
30
|
-
export declare function
|
|
28
|
+
export declare function projectConfigDir(configDir: string, projectId: string): string;
|
|
29
|
+
export declare function projectConfigPath(configDir: string, projectId: string): string;
|
|
30
|
+
export declare function daemonPidPath(configDir: string, projectId: string): string;
|
|
31
|
+
export declare function orchestratorLogPath(configDir: string, projectId: string): string;
|
|
32
|
+
export declare function orchestratorPortPath(configDir: string, projectId: string): string;
|
|
31
33
|
export declare function loadGlobalConfig(configDir: string): Promise<CliGlobalConfig | null>;
|
|
32
34
|
export declare function saveGlobalConfig(configDir: string, config: CliGlobalConfig): Promise<void>;
|
|
33
|
-
export declare function
|
|
34
|
-
export declare function
|
|
35
|
-
export declare function
|
|
35
|
+
export declare function loadProjectConfig(configDir: string, projectId: string): Promise<CliProjectConfig | null>;
|
|
36
|
+
export declare function saveProjectConfig(configDir: string, projectId: string, config: CliProjectConfig): Promise<void>;
|
|
37
|
+
export declare function loadActiveProjectConfig(configDir: string): Promise<CliProjectConfig | null>;
|
package/dist/config.js
CHANGED
|
@@ -4,46 +4,56 @@ import { homedir } from "node:os";
|
|
|
4
4
|
export const DEFAULT_CONFIG_DIR = join(homedir(), ".gh-symphony");
|
|
5
5
|
export const CONFIG_FILE = "config.json";
|
|
6
6
|
export const DAEMON_PID_FILE = "daemon.pid";
|
|
7
|
-
export const
|
|
7
|
+
export const ORCHESTRATOR_LOG_FILE = "orchestrator.log";
|
|
8
|
+
export const ORCHESTRATOR_PORT_FILE = "port";
|
|
8
9
|
export function resolveConfigDir(override) {
|
|
9
10
|
return override ?? process.env.GH_SYMPHONY_CONFIG_DIR ?? DEFAULT_CONFIG_DIR;
|
|
10
11
|
}
|
|
11
12
|
export function configFilePath(configDir) {
|
|
12
13
|
return join(configDir, CONFIG_FILE);
|
|
13
14
|
}
|
|
14
|
-
export function
|
|
15
|
-
return join(configDir, "
|
|
15
|
+
export function projectConfigDir(configDir, projectId) {
|
|
16
|
+
return join(configDir, "projects", projectId);
|
|
16
17
|
}
|
|
17
|
-
export function
|
|
18
|
-
return join(
|
|
18
|
+
export function projectConfigPath(configDir, projectId) {
|
|
19
|
+
return join(projectConfigDir(configDir, projectId), "project.json");
|
|
19
20
|
}
|
|
20
|
-
export function daemonPidPath(configDir) {
|
|
21
|
-
return join(configDir, DAEMON_PID_FILE);
|
|
21
|
+
export function daemonPidPath(configDir, projectId) {
|
|
22
|
+
return join(projectConfigDir(configDir, projectId), DAEMON_PID_FILE);
|
|
22
23
|
}
|
|
23
|
-
export function
|
|
24
|
-
return join(configDir,
|
|
24
|
+
export function orchestratorLogPath(configDir, projectId) {
|
|
25
|
+
return join(projectConfigDir(configDir, projectId), ORCHESTRATOR_LOG_FILE);
|
|
25
26
|
}
|
|
26
|
-
export function
|
|
27
|
-
return join(
|
|
27
|
+
export function orchestratorPortPath(configDir, projectId) {
|
|
28
|
+
return join(projectConfigDir(configDir, projectId), ORCHESTRATOR_PORT_FILE);
|
|
28
29
|
}
|
|
29
30
|
export async function loadGlobalConfig(configDir) {
|
|
30
|
-
|
|
31
|
+
const raw = await readJsonFile(configFilePath(configDir));
|
|
32
|
+
if (!raw) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
activeProject: typeof raw.activeProject === "string" ? raw.activeProject : null,
|
|
37
|
+
projects: Array.isArray(raw.projects)
|
|
38
|
+
? raw.projects.filter((projectId) => typeof projectId === "string")
|
|
39
|
+
: [],
|
|
40
|
+
};
|
|
31
41
|
}
|
|
32
42
|
export async function saveGlobalConfig(configDir, config) {
|
|
33
43
|
await writeJsonFile(configFilePath(configDir), config);
|
|
34
44
|
}
|
|
35
|
-
export async function
|
|
36
|
-
return readJsonFile(
|
|
45
|
+
export async function loadProjectConfig(configDir, projectId) {
|
|
46
|
+
return readJsonFile(projectConfigPath(configDir, projectId));
|
|
37
47
|
}
|
|
38
|
-
export async function
|
|
39
|
-
await writeJsonFile(
|
|
48
|
+
export async function saveProjectConfig(configDir, projectId, config) {
|
|
49
|
+
await writeJsonFile(projectConfigPath(configDir, projectId), config);
|
|
40
50
|
}
|
|
41
|
-
export async function
|
|
51
|
+
export async function loadActiveProjectConfig(configDir) {
|
|
42
52
|
const global = await loadGlobalConfig(configDir);
|
|
43
|
-
if (!global?.
|
|
53
|
+
if (!global?.activeProject) {
|
|
44
54
|
return null;
|
|
45
55
|
}
|
|
46
|
-
return
|
|
56
|
+
return loadProjectConfig(configDir, global.activeProject);
|
|
47
57
|
}
|
|
48
58
|
async function readJsonFile(path) {
|
|
49
59
|
try {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ProjectStatusSnapshot } from "@gh-symphony/core";
|
|
2
2
|
export type DashboardOptions = {
|
|
3
3
|
terminalWidth: number;
|
|
4
4
|
noColor: boolean;
|
|
@@ -6,4 +6,4 @@ export type DashboardOptions = {
|
|
|
6
6
|
/** Override Date.now() for deterministic testing */
|
|
7
7
|
now?: number;
|
|
8
8
|
};
|
|
9
|
-
export declare function renderDashboard(snapshots:
|
|
9
|
+
export declare function renderDashboard(snapshots: ProjectStatusSnapshot[], options: DashboardOptions): string;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { bold, dim, green, red, yellow, cyan, magenta, blue, stripAnsi, } from "../ansi.js";
|
|
3
3
|
// ── Column widths (from Elixir spec) ─────────────────────────────────────────
|
|
4
4
|
const COL_ID = 24;
|
|
5
|
-
const
|
|
5
|
+
const COL_STATUS = 14;
|
|
6
6
|
const COL_PID = 8;
|
|
7
7
|
const COL_AGE_TURN = 12;
|
|
8
8
|
const COL_TOKENS = 10;
|
|
@@ -81,7 +81,7 @@ const COL_SEPARATORS = 6;
|
|
|
81
81
|
function eventColWidth(termWidth) {
|
|
82
82
|
const fixed = 2 +
|
|
83
83
|
COL_ID_HEADER +
|
|
84
|
-
|
|
84
|
+
COL_STATUS +
|
|
85
85
|
COL_PID +
|
|
86
86
|
COL_AGE_TURN +
|
|
87
87
|
COL_TOKENS +
|
|
@@ -140,7 +140,7 @@ function buildSummaryLines(snapshots, options, c) {
|
|
|
140
140
|
function tableHeaderRow(c) {
|
|
141
141
|
const cols = [
|
|
142
142
|
pad("ID", COL_ID_HEADER),
|
|
143
|
-
pad("
|
|
143
|
+
pad("STATUS", COL_STATUS),
|
|
144
144
|
pad("PID", COL_PID),
|
|
145
145
|
pad("AGE/TURN", COL_AGE_TURN),
|
|
146
146
|
pad("TOKENS", COL_TOKENS),
|
|
@@ -152,7 +152,7 @@ function tableHeaderRow(c) {
|
|
|
152
152
|
function activeRunRow(run, now, evtWidth, c) {
|
|
153
153
|
const dot = statusDot(run, c);
|
|
154
154
|
const id = pad(run.issueIdentifier, COL_ID);
|
|
155
|
-
const
|
|
155
|
+
const status = pad(run.issueState ?? run.executionPhase ?? "\u2014", COL_STATUS);
|
|
156
156
|
const pid = pad(run.processId != null ? String(run.processId) : "\u2014", COL_PID);
|
|
157
157
|
const age = fmtAge(run.startedAt, now);
|
|
158
158
|
const turn = run.turnCount ?? 0;
|
|
@@ -161,7 +161,7 @@ function activeRunRow(run, now, evtWidth, c) {
|
|
|
161
161
|
const sessionId = run.runtimeSession?.sessionId ?? run.runtimeSession?.threadId ?? null;
|
|
162
162
|
const session = pad(compactSessionId(sessionId), COL_SESSION);
|
|
163
163
|
const event = pad(run.lastEvent ?? "\u2014", evtWidth);
|
|
164
|
-
const columns = [id,
|
|
164
|
+
const columns = [id, status, pid, ageTurn, tokens, session, event].join(" ");
|
|
165
165
|
return ` ${dot} ${columns}`;
|
|
166
166
|
}
|
|
167
167
|
function retryRow(entry, snapshot, now, c) {
|
package/dist/index.js
CHANGED
|
@@ -49,7 +49,6 @@ const COMMANDS = {
|
|
|
49
49
|
logs: () => import("./commands/logs.js"),
|
|
50
50
|
project: () => import("./commands/project.js"),
|
|
51
51
|
repo: () => import("./commands/repo.js"),
|
|
52
|
-
tenant: () => import("./commands/tenant.js"),
|
|
53
52
|
config: () => import("./commands/config-cmd.js"),
|
|
54
53
|
help: () => import("./commands/help.js"),
|
|
55
54
|
version: () => import("./commands/version.js"),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type CliProjectConfig } from "./config.js";
|
|
2
2
|
export declare function resolveRuntimeRoot(configDir: string): string;
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function
|
|
3
|
+
export declare function resolveProjectConfig(configDir: string, requestedProjectId?: string): Promise<CliProjectConfig | null>;
|
|
4
|
+
export declare function orchestratorProjectConfigPath(runtimeRoot: string, projectId: string): string;
|
|
5
|
+
export declare function syncProjectToRuntime(configDir: string, projectConfig: CliProjectConfig): Promise<string>;
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
2
|
import { dirname, join, resolve } from "node:path";
|
|
3
|
-
import { loadGlobalConfig,
|
|
3
|
+
import { loadGlobalConfig, loadProjectConfig, } from "./config.js";
|
|
4
4
|
export function resolveRuntimeRoot(configDir) {
|
|
5
5
|
return resolve(configDir);
|
|
6
6
|
}
|
|
7
|
-
export async function
|
|
8
|
-
if (
|
|
9
|
-
return
|
|
7
|
+
export async function resolveProjectConfig(configDir, requestedProjectId) {
|
|
8
|
+
if (requestedProjectId) {
|
|
9
|
+
return loadProjectConfig(configDir, requestedProjectId);
|
|
10
10
|
}
|
|
11
11
|
const global = await loadGlobalConfig(configDir);
|
|
12
|
-
if (!global?.
|
|
12
|
+
if (!global?.activeProject) {
|
|
13
13
|
return null;
|
|
14
14
|
}
|
|
15
|
-
return
|
|
15
|
+
return loadProjectConfig(configDir, global.activeProject);
|
|
16
16
|
}
|
|
17
|
-
export function
|
|
18
|
-
return join(runtimeRoot, "orchestrator", "
|
|
17
|
+
export function orchestratorProjectConfigPath(runtimeRoot, projectId) {
|
|
18
|
+
return join(runtimeRoot, "orchestrator", "projects", projectId, "config.json");
|
|
19
19
|
}
|
|
20
|
-
export async function
|
|
20
|
+
export async function syncProjectToRuntime(configDir, projectConfig) {
|
|
21
21
|
const runtimeRoot = resolveRuntimeRoot(configDir);
|
|
22
|
-
const configPath =
|
|
22
|
+
const configPath = orchestratorProjectConfigPath(runtimeRoot, projectConfig.projectId);
|
|
23
23
|
await mkdir(dirname(configPath), { recursive: true });
|
|
24
|
-
await writeFile(configPath, JSON.stringify(
|
|
24
|
+
await writeFile(configPath, JSON.stringify(projectConfig, null, 2) + "\n");
|
|
25
25
|
return runtimeRoot;
|
|
26
26
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { orchestratorPortPath } from "./config.js";
|
|
3
|
+
export async function resolveProjectOrchestratorStatusBaseUrl(input) {
|
|
4
|
+
const env = input.env ?? process.env;
|
|
5
|
+
const explicitBaseUrl = env.ORCHESTRATOR_STATUS_BASE_URL;
|
|
6
|
+
if (explicitBaseUrl) {
|
|
7
|
+
return explicitBaseUrl;
|
|
8
|
+
}
|
|
9
|
+
const host = env.ORCHESTRATOR_STATUS_HOST ?? "127.0.0.1";
|
|
10
|
+
const port = env.ORCHESTRATOR_STATUS_PORT ??
|
|
11
|
+
(await readProjectStatusPort(input.configDir, input.projectId));
|
|
12
|
+
if (!port) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const urlHost = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
|
|
16
|
+
return `http://${urlHost}:${port}`;
|
|
17
|
+
}
|
|
18
|
+
async function readProjectStatusPort(configDir, projectId) {
|
|
19
|
+
try {
|
|
20
|
+
const raw = await readFile(orchestratorPortPath(configDir, projectId), "utf8");
|
|
21
|
+
const port = raw.trim();
|
|
22
|
+
return port.length > 0 ? port : null;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
package/dist/skills/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gh-symphony/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "hojinzs",
|
|
6
6
|
"description": "Interactive CLI for GitHub Symphony orchestration",
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@clack/prompts": "^0.9.1",
|
|
39
|
-
"@gh-symphony/
|
|
40
|
-
"@gh-symphony/
|
|
41
|
-
"@gh-symphony/tracker-github": "0.0.
|
|
42
|
-
"@gh-symphony/worker": "0.0.
|
|
39
|
+
"@gh-symphony/orchestrator": "0.0.7",
|
|
40
|
+
"@gh-symphony/core": "0.0.7",
|
|
41
|
+
"@gh-symphony/tracker-github": "0.0.7",
|
|
42
|
+
"@gh-symphony/worker": "0.0.7"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|
|
45
45
|
"build": "tsc -p tsconfig.json",
|