@gh-symphony/cli 0.0.22 → 0.1.3
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 +72 -77
- package/dist/{chunk-HMLBBZNY.js → chunk-2YF7PQUC.js} +16 -71
- package/dist/{chunk-IWFX2FMA.js → chunk-6I753NYO.js} +4 -1
- package/dist/{chunk-2TSM3INR.js → chunk-HQ7A3C7K.js} +575 -12
- package/dist/{chunk-36KYEDEO.js → chunk-MVRF7BES.js} +1 -10
- package/dist/{workflow-L3KT6HB7.js → chunk-NESHTYXQ.js} +27 -19
- package/dist/{chunk-2UW7NQLX.js → chunk-PEZUBHWJ.js} +1 -1
- package/dist/chunk-PG332ZS4.js +238 -0
- package/dist/{chunk-EEQQWTXS.js → chunk-WCOIVNHH.js} +213 -82
- package/dist/{chunk-QIRE2VXS.js → chunk-WOVNN5NW.js} +16 -17
- package/dist/{chunk-C67H3OUL.js → chunk-Z3NZOPLZ.js} +0 -81
- package/dist/{config-cmd-Z3A7V6NC.js → config-cmd-2ADPUYWA.js} +1 -1
- package/dist/{doctor-EJUMPBMW.js → doctor-2AXHIEAP.js} +464 -40
- package/dist/index.js +340 -294
- package/dist/{chunk-PUDXVBSN.js → repo-SUXYT4OK.js} +6272 -2996
- package/dist/{setup-TZJSM3QV.js → setup-UBHOMXUG.js} +57 -92
- package/dist/{upgrade-O33S2SJK.js → upgrade-355SQJ5P.js} +2 -2
- package/dist/{version-CW54Q7BK.js → version-4ILSDZQH.js} +1 -1
- package/dist/worker-entry.js +10 -5
- package/dist/workflow-S6YSZPQT.js +22 -0
- package/package.json +4 -4
- package/dist/chunk-DDL4BWSL.js +0 -146
- package/dist/chunk-DFLXHNYQ.js +0 -482
- package/dist/chunk-E7HYEEZD.js +0 -1318
- package/dist/chunk-GDE6FYN4.js +0 -26
- package/dist/chunk-GSX2FV3M.js +0 -103
- package/dist/chunk-ZHOKYUO3.js +0 -1047
- package/dist/init-54HMKNYI.js +0 -38
- package/dist/logs-GTZ4U5JE.js +0 -188
- package/dist/project-RMYMZSFV.js +0 -25
- package/dist/recover-LTLKMTRX.js +0 -133
- package/dist/repo-WI7GF6XQ.js +0 -749
- package/dist/run-IHN3ZL35.js +0 -122
- package/dist/start-RTAHQMR2.js +0 -19
- package/dist/status-F4D52OVK.js +0 -12
- package/dist/stop-MDKMJPVR.js +0 -10
package/dist/chunk-DFLXHNYQ.js
DELETED
|
@@ -1,482 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
blue,
|
|
4
|
-
bold,
|
|
5
|
-
clearScreen,
|
|
6
|
-
cyan,
|
|
7
|
-
dim,
|
|
8
|
-
formatRepositoryDisplay,
|
|
9
|
-
green,
|
|
10
|
-
hideCursor,
|
|
11
|
-
magenta,
|
|
12
|
-
red,
|
|
13
|
-
showCursor,
|
|
14
|
-
stripAnsi,
|
|
15
|
-
yellow
|
|
16
|
-
} from "./chunk-36KYEDEO.js";
|
|
17
|
-
import {
|
|
18
|
-
resolveRuntimeRoot
|
|
19
|
-
} from "./chunk-IWFX2FMA.js";
|
|
20
|
-
import {
|
|
21
|
-
rejectRemovedProjectId
|
|
22
|
-
} from "./chunk-GDE6FYN4.js";
|
|
23
|
-
import {
|
|
24
|
-
handleMissingManagedProjectConfig,
|
|
25
|
-
resolveManagedProjectConfig
|
|
26
|
-
} from "./chunk-DDL4BWSL.js";
|
|
27
|
-
|
|
28
|
-
// src/commands/status.ts
|
|
29
|
-
import { readFile } from "fs/promises";
|
|
30
|
-
import { join } from "path";
|
|
31
|
-
|
|
32
|
-
// src/dashboard/renderer.ts
|
|
33
|
-
var COL_ID = 24;
|
|
34
|
-
var COL_STATUS = 14;
|
|
35
|
-
var COL_PID = 8;
|
|
36
|
-
var COL_AGE_TURN = 12;
|
|
37
|
-
var COL_TOKENS = 17;
|
|
38
|
-
var COL_SESSION = 14;
|
|
39
|
-
var COL_ID_HEADER = COL_ID + 2;
|
|
40
|
-
var identity = (s) => s;
|
|
41
|
-
function makeColors(noColor) {
|
|
42
|
-
if (noColor) {
|
|
43
|
-
return {
|
|
44
|
-
bold: identity,
|
|
45
|
-
dim: identity,
|
|
46
|
-
green: identity,
|
|
47
|
-
red: identity,
|
|
48
|
-
yellow: identity,
|
|
49
|
-
cyan: identity,
|
|
50
|
-
magenta: identity,
|
|
51
|
-
blue: identity
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
return { bold, dim, green, red, yellow, cyan, magenta, blue };
|
|
55
|
-
}
|
|
56
|
-
function pad(s, width, align = "left") {
|
|
57
|
-
const visible = stripAnsi(s);
|
|
58
|
-
if (visible.length >= width) return visible.slice(0, width);
|
|
59
|
-
const padding = " ".repeat(width - visible.length);
|
|
60
|
-
return align === "right" ? padding + s : s + padding;
|
|
61
|
-
}
|
|
62
|
-
function compactSessionId(id) {
|
|
63
|
-
if (!id) return "\u2014";
|
|
64
|
-
if (id.length <= 10) return id;
|
|
65
|
-
return `${id.slice(0, 4)}...${id.slice(-6)}`;
|
|
66
|
-
}
|
|
67
|
-
function fmtTokens(n) {
|
|
68
|
-
return n.toLocaleString("en-US");
|
|
69
|
-
}
|
|
70
|
-
function fmtTokenPair(delta, cumulative) {
|
|
71
|
-
const left = fmtTokens(delta ?? 0);
|
|
72
|
-
const right = fmtTokens(cumulative ?? delta ?? 0);
|
|
73
|
-
return `${left} / ${right}`;
|
|
74
|
-
}
|
|
75
|
-
function fmtAge(startedAt, now) {
|
|
76
|
-
if (!startedAt) return "0m";
|
|
77
|
-
const diffMs = now - new Date(startedAt).getTime();
|
|
78
|
-
if (diffMs < 0) return "0m";
|
|
79
|
-
const totalMin = Math.floor(diffMs / 6e4);
|
|
80
|
-
if (totalMin < 60) return `${totalMin}m`;
|
|
81
|
-
const h = Math.floor(totalMin / 60);
|
|
82
|
-
const m = totalMin % 60;
|
|
83
|
-
return `${h}h ${m}m`;
|
|
84
|
-
}
|
|
85
|
-
function fmtRuntime(ms) {
|
|
86
|
-
if (ms <= 0) return "0h 0m";
|
|
87
|
-
const totalMin = Math.floor(ms / 6e4);
|
|
88
|
-
const h = Math.floor(totalMin / 60);
|
|
89
|
-
const m = totalMin % 60;
|
|
90
|
-
return `${h}h ${m}m`;
|
|
91
|
-
}
|
|
92
|
-
function fmtRetryTime(nextRetryAt, now) {
|
|
93
|
-
if (!nextRetryAt) return "\u2014";
|
|
94
|
-
const diffMs = new Date(nextRetryAt).getTime() - now;
|
|
95
|
-
if (diffMs <= 0) return "now";
|
|
96
|
-
const totalSec = Math.ceil(diffMs / 1e3);
|
|
97
|
-
if (totalSec < 60) return `${totalSec}s`;
|
|
98
|
-
const m = Math.floor(totalSec / 60);
|
|
99
|
-
const s = totalSec % 60;
|
|
100
|
-
return s > 0 ? `${m}m ${s}s` : `${m}m`;
|
|
101
|
-
}
|
|
102
|
-
var COL_SEPARATORS = 6;
|
|
103
|
-
function eventColWidth(termWidth) {
|
|
104
|
-
const fixed = 2 + COL_ID_HEADER + COL_STATUS + COL_PID + COL_AGE_TURN + COL_TOKENS + COL_SESSION + COL_SEPARATORS;
|
|
105
|
-
return Math.max(5, termWidth - fixed);
|
|
106
|
-
}
|
|
107
|
-
function statusDot(run, c) {
|
|
108
|
-
const event = run.lastEvent;
|
|
109
|
-
if (event === null || event === void 0 || run.status === "failed")
|
|
110
|
-
return c.red("\u25CF");
|
|
111
|
-
if (event === "token_count") return c.yellow("\u25CF");
|
|
112
|
-
if (event === "task_started") return c.green("\u25CF");
|
|
113
|
-
if (event === "turn_completed") return c.magenta("\u25CF");
|
|
114
|
-
return c.blue("\u25CF");
|
|
115
|
-
}
|
|
116
|
-
function titleBar(width, c) {
|
|
117
|
-
const title = " gh-symphony ";
|
|
118
|
-
const side = Math.max(0, Math.floor((width - title.length) / 2));
|
|
119
|
-
const right = Math.max(0, width - side - title.length);
|
|
120
|
-
return c.bold("\u2550".repeat(side) + title + "\u2550".repeat(right));
|
|
121
|
-
}
|
|
122
|
-
function sectionDivider(label, width, c) {
|
|
123
|
-
const prefix = `\u2500\u2500 ${label} `;
|
|
124
|
-
const fill = "\u2500".repeat(Math.max(0, width - prefix.length));
|
|
125
|
-
return c.dim(prefix + fill);
|
|
126
|
-
}
|
|
127
|
-
function buildSummaryLines(snapshots, options, c) {
|
|
128
|
-
const now = options.now ?? Date.now();
|
|
129
|
-
const lines = [];
|
|
130
|
-
const totalActive = snapshots.reduce(
|
|
131
|
-
(sum, s) => sum + s.summary.activeRuns,
|
|
132
|
-
0
|
|
133
|
-
);
|
|
134
|
-
const agentStr = options.maxAgents != null ? `${totalActive}/${options.maxAgents}` : `${totalActive}`;
|
|
135
|
-
const totIn = snapshots.reduce(
|
|
136
|
-
(sum, s) => sum + (s.codexTotals?.inputTokens ?? 0),
|
|
137
|
-
0
|
|
138
|
-
);
|
|
139
|
-
const totOut = snapshots.reduce(
|
|
140
|
-
(sum, s) => sum + (s.codexTotals?.outputTokens ?? 0),
|
|
141
|
-
0
|
|
142
|
-
);
|
|
143
|
-
const totAll = snapshots.reduce(
|
|
144
|
-
(sum, s) => sum + (s.codexTotals?.totalTokens ?? 0),
|
|
145
|
-
0
|
|
146
|
-
);
|
|
147
|
-
const allStarts = snapshots.flatMap((s) => s.activeRuns).map((r) => r.startedAt).filter((t) => t != null).map((t) => new Date(t).getTime());
|
|
148
|
-
const runtimeMs = allStarts.length > 0 ? now - Math.min(...allStarts) : 0;
|
|
149
|
-
const runtime = fmtRuntime(runtimeMs);
|
|
150
|
-
lines.push(
|
|
151
|
-
` ${c.dim("Agents")} ${c.bold(agentStr)} ${c.dim("Runtime")} ${c.bold(runtime)} ${c.dim("Tokens")} ${fmtTokens(totIn)} in / ${fmtTokens(totOut)} out / ${c.bold(fmtTokens(totAll))} total`
|
|
152
|
-
);
|
|
153
|
-
const hasLimits = snapshots.some((s) => s.rateLimits != null);
|
|
154
|
-
const limitStr = hasLimits ? "active" : "standard";
|
|
155
|
-
lines.push(` ${c.dim("Rate Limits")} ${limitStr}`);
|
|
156
|
-
return lines;
|
|
157
|
-
}
|
|
158
|
-
function tableHeaderRow(c) {
|
|
159
|
-
const cols = [
|
|
160
|
-
pad("ID", COL_ID_HEADER),
|
|
161
|
-
pad("STATUS", COL_STATUS),
|
|
162
|
-
pad("PID", COL_PID),
|
|
163
|
-
pad("AGE/TURN", COL_AGE_TURN),
|
|
164
|
-
pad("TOKENS", COL_TOKENS),
|
|
165
|
-
pad("SESSION", COL_SESSION),
|
|
166
|
-
"EVENT"
|
|
167
|
-
].join(" ");
|
|
168
|
-
return ` ${c.dim(cols)}`;
|
|
169
|
-
}
|
|
170
|
-
function activeRunRow(run, now, evtWidth, c) {
|
|
171
|
-
const dot = statusDot(run, c);
|
|
172
|
-
const id = pad(run.issueIdentifier, COL_ID);
|
|
173
|
-
const status = pad(
|
|
174
|
-
run.issueState ?? run.executionPhase ?? "\u2014",
|
|
175
|
-
COL_STATUS
|
|
176
|
-
);
|
|
177
|
-
const pid = pad(
|
|
178
|
-
run.processId != null ? String(run.processId) : "\u2014",
|
|
179
|
-
COL_PID
|
|
180
|
-
);
|
|
181
|
-
const age = fmtAge(run.startedAt, now);
|
|
182
|
-
const turn = run.turnCount ?? 0;
|
|
183
|
-
const ageTurn = pad(`${age}/${turn}`, COL_AGE_TURN);
|
|
184
|
-
const tokens = pad(
|
|
185
|
-
fmtTokenPair(
|
|
186
|
-
run.tokenUsage?.totalTokens,
|
|
187
|
-
run.tokenUsage?.cumulativeTotalTokens
|
|
188
|
-
),
|
|
189
|
-
COL_TOKENS,
|
|
190
|
-
"right"
|
|
191
|
-
);
|
|
192
|
-
const sessionId = run.runtimeSession?.sessionId ?? run.runtimeSession?.threadId ?? null;
|
|
193
|
-
const session = pad(compactSessionId(sessionId), COL_SESSION);
|
|
194
|
-
const event = pad(run.lastEvent ?? "\u2014", evtWidth);
|
|
195
|
-
const columns = [id, status, pid, ageTurn, tokens, session, event].join(" ");
|
|
196
|
-
return ` ${dot} ${columns}`;
|
|
197
|
-
}
|
|
198
|
-
function retryRow(entry, snapshot, now, c) {
|
|
199
|
-
const id = entry.issueIdentifier;
|
|
200
|
-
const kind = entry.retryKind;
|
|
201
|
-
const timeStr = fmtRetryTime(entry.nextRetryAt, now);
|
|
202
|
-
const matchingRun = snapshot.activeRuns.find((r) => r.runId === entry.runId);
|
|
203
|
-
const errorHint = matchingRun?.lastEvent ?? "";
|
|
204
|
-
return ` ${c.yellow("\u21BB")} ${id} ${kind} retrying in ${timeStr}${errorHint ? " " + errorHint : ""}`;
|
|
205
|
-
}
|
|
206
|
-
function renderDashboard(snapshots, options) {
|
|
207
|
-
const width = options.terminalWidth || 115;
|
|
208
|
-
const now = options.now ?? Date.now();
|
|
209
|
-
const c = makeColors(options.noColor);
|
|
210
|
-
const evtWidth = eventColWidth(width);
|
|
211
|
-
const lines = [];
|
|
212
|
-
lines.push(titleBar(width, c));
|
|
213
|
-
lines.push(...buildSummaryLines(snapshots, options, c));
|
|
214
|
-
lines.push("");
|
|
215
|
-
for (const snap of snapshots) {
|
|
216
|
-
const hasActiveRuns = snap.activeRuns.length > 0;
|
|
217
|
-
const hasRetries = snap.retryQueue.length > 0;
|
|
218
|
-
if (!hasActiveRuns && !hasRetries) continue;
|
|
219
|
-
lines.push(
|
|
220
|
-
sectionDivider(formatRepositoryDisplay(snap), width, c)
|
|
221
|
-
);
|
|
222
|
-
if (hasActiveRuns) {
|
|
223
|
-
lines.push(tableHeaderRow(c));
|
|
224
|
-
for (const rawRun of snap.activeRuns) {
|
|
225
|
-
const run = rawRun;
|
|
226
|
-
lines.push(activeRunRow(run, now, evtWidth, c));
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
lines.push("");
|
|
230
|
-
}
|
|
231
|
-
const allRetries = [];
|
|
232
|
-
for (const snap of snapshots) {
|
|
233
|
-
for (const entry of snap.retryQueue) {
|
|
234
|
-
allRetries.push({ entry, snapshot: snap });
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
if (allRetries.length > 0) {
|
|
238
|
-
lines.push(sectionDivider("Backoff Queue", width, c));
|
|
239
|
-
for (const { entry, snapshot } of allRetries) {
|
|
240
|
-
lines.push(retryRow(entry, snapshot, now, c));
|
|
241
|
-
}
|
|
242
|
-
lines.push("");
|
|
243
|
-
}
|
|
244
|
-
const result = lines.map((line) => {
|
|
245
|
-
const visible = stripAnsi(line);
|
|
246
|
-
if (visible.length <= width) return line;
|
|
247
|
-
return visible.slice(0, width);
|
|
248
|
-
});
|
|
249
|
-
return result.join("\n");
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// src/commands/status.ts
|
|
253
|
-
function healthIcon(health) {
|
|
254
|
-
switch (health) {
|
|
255
|
-
case "idle":
|
|
256
|
-
case "running":
|
|
257
|
-
return green("\u25CF");
|
|
258
|
-
case "degraded":
|
|
259
|
-
return red("\u25CF");
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
function relativeTime(isoString) {
|
|
263
|
-
const now = /* @__PURE__ */ new Date();
|
|
264
|
-
const then = new Date(isoString);
|
|
265
|
-
const diffMs = now.getTime() - then.getTime();
|
|
266
|
-
const diffS = Math.floor(diffMs / 1e3);
|
|
267
|
-
const diffM = Math.floor(diffS / 60);
|
|
268
|
-
const diffH = Math.floor(diffM / 60);
|
|
269
|
-
if (diffS < 60) return `${diffS}s ago`;
|
|
270
|
-
if (diffM < 60) return `${diffM}m ago`;
|
|
271
|
-
return `${diffH}h ago`;
|
|
272
|
-
}
|
|
273
|
-
function truncate(s, len) {
|
|
274
|
-
if (s.length <= len) return s;
|
|
275
|
-
return s.slice(0, len - 3) + "...";
|
|
276
|
-
}
|
|
277
|
-
function formatTokenPair(delta, cumulative) {
|
|
278
|
-
return `${delta.toLocaleString("en-US")} / ${cumulative.toLocaleString("en-US")}`;
|
|
279
|
-
}
|
|
280
|
-
function resolveProjectTokenDelta(snapshot) {
|
|
281
|
-
return snapshot.activeRuns.reduce(
|
|
282
|
-
(sum, run) => sum + (run.tokenUsage?.totalTokens ?? 0),
|
|
283
|
-
0
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
function renderLegacyStatus(snapshot, noColor) {
|
|
287
|
-
const apply = noColor ? (s) => stripAnsi(s) : (s) => s;
|
|
288
|
-
const lines = [];
|
|
289
|
-
const headerTitle = `gh-symphony \u2219 ${formatRepositoryDisplay(snapshot)}`;
|
|
290
|
-
const headerWidth = 45;
|
|
291
|
-
const headerPadding = Math.max(
|
|
292
|
-
0,
|
|
293
|
-
headerWidth - stripAnsi(headerTitle).length
|
|
294
|
-
);
|
|
295
|
-
lines.push("\u256D" + "\u2500".repeat(headerWidth) + "\u256E");
|
|
296
|
-
lines.push(
|
|
297
|
-
"\u2502 " + apply(bold(headerTitle)) + " ".repeat(headerPadding) + "\u2502"
|
|
298
|
-
);
|
|
299
|
-
lines.push("\u2570" + "\u2500".repeat(headerWidth) + "\u256F");
|
|
300
|
-
lines.push("");
|
|
301
|
-
const healthStr = apply(
|
|
302
|
-
`${healthIcon(snapshot.health)} Health ${snapshot.health}`
|
|
303
|
-
);
|
|
304
|
-
const lastTickStr = apply(`Last tick ${relativeTime(snapshot.lastTickAt)}`);
|
|
305
|
-
lines.push(
|
|
306
|
-
` ${healthStr}${" ".repeat(Math.max(0, 30 - stripAnsi(healthStr).length))}${lastTickStr}`
|
|
307
|
-
);
|
|
308
|
-
lines.push("");
|
|
309
|
-
const dispatchedStr = apply(`Dispatched ${snapshot.summary.dispatched}`);
|
|
310
|
-
const activeRunsStr = apply(`Active Runs ${snapshot.summary.activeRuns}`);
|
|
311
|
-
const suppressedStr = apply(`Suppressed ${snapshot.summary.suppressed}`);
|
|
312
|
-
const recoveredStr = apply(`Recovered ${snapshot.summary.recovered}`);
|
|
313
|
-
lines.push(
|
|
314
|
-
` ${dispatchedStr}${" ".repeat(Math.max(0, 20 - stripAnsi(dispatchedStr).length))}${activeRunsStr}`
|
|
315
|
-
);
|
|
316
|
-
lines.push(
|
|
317
|
-
` ${suppressedStr}${" ".repeat(Math.max(0, 20 - stripAnsi(suppressedStr).length))}${recoveredStr}`
|
|
318
|
-
);
|
|
319
|
-
lines.push("");
|
|
320
|
-
if (snapshot.activeRuns.length > 0) {
|
|
321
|
-
lines.push(" Active Runs:");
|
|
322
|
-
for (const run of snapshot.activeRuns) {
|
|
323
|
-
const runIdDisplay = truncate(run.runId, 12);
|
|
324
|
-
const stateStr = apply(cyan(run.issueState));
|
|
325
|
-
const statusColor = run.status === "running" ? green : run.status === "failed" ? red : run.status === "succeeded" ? green : dim;
|
|
326
|
-
const statusStr = apply(statusColor(run.status));
|
|
327
|
-
lines.push(
|
|
328
|
-
` ${runIdDisplay} ${run.issueIdentifier} ${stateStr} ${statusStr}`
|
|
329
|
-
);
|
|
330
|
-
}
|
|
331
|
-
lines.push("");
|
|
332
|
-
} else {
|
|
333
|
-
lines.push(" No active runs.");
|
|
334
|
-
lines.push("");
|
|
335
|
-
}
|
|
336
|
-
if (snapshot.retryQueue.length > 0) {
|
|
337
|
-
lines.push(" Retry Queue:");
|
|
338
|
-
for (const retry of snapshot.retryQueue) {
|
|
339
|
-
const runIdDisplay = truncate(retry.runId, 12);
|
|
340
|
-
const nextRetryDisplay = retry.nextRetryAt ? relativeTime(retry.nextRetryAt) : "pending";
|
|
341
|
-
lines.push(
|
|
342
|
-
` ${runIdDisplay} ${retry.issueIdentifier} ${apply(yellow(retry.retryKind))} ${nextRetryDisplay}`
|
|
343
|
-
);
|
|
344
|
-
}
|
|
345
|
-
lines.push("");
|
|
346
|
-
}
|
|
347
|
-
if (snapshot.lastError) {
|
|
348
|
-
lines.push(apply(red(` \u2717 ${snapshot.lastError}`)));
|
|
349
|
-
lines.push("");
|
|
350
|
-
}
|
|
351
|
-
if (snapshot.codexTotals) {
|
|
352
|
-
const tokenDelta = resolveProjectTokenDelta(snapshot);
|
|
353
|
-
const tokenStr = apply(
|
|
354
|
-
`Tokens: ${formatTokenPair(tokenDelta, snapshot.codexTotals.totalTokens)} total`
|
|
355
|
-
);
|
|
356
|
-
lines.push(` ${tokenStr}`);
|
|
357
|
-
} else {
|
|
358
|
-
lines.push(" Tokens: 0 / 0 total");
|
|
359
|
-
}
|
|
360
|
-
return lines.join("\n");
|
|
361
|
-
}
|
|
362
|
-
function parseStatusArgs(args) {
|
|
363
|
-
const parsed = {
|
|
364
|
-
watch: false
|
|
365
|
-
};
|
|
366
|
-
for (let i = 0; i < args.length; i += 1) {
|
|
367
|
-
const arg = args[i];
|
|
368
|
-
if (arg === "--watch" || arg === "-w") {
|
|
369
|
-
parsed.watch = true;
|
|
370
|
-
continue;
|
|
371
|
-
}
|
|
372
|
-
if (arg?.startsWith("-")) {
|
|
373
|
-
parsed.error = `Unknown option '${arg}'`;
|
|
374
|
-
return parsed;
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
return parsed;
|
|
378
|
-
}
|
|
379
|
-
async function readStatusSnapshot(runtimeRoot, projectId) {
|
|
380
|
-
for (const statusPath of [
|
|
381
|
-
join(runtimeRoot, "status.json"),
|
|
382
|
-
join(runtimeRoot, "projects", projectId, "status.json")
|
|
383
|
-
]) {
|
|
384
|
-
try {
|
|
385
|
-
const content = await readFile(statusPath, "utf-8");
|
|
386
|
-
return JSON.parse(content);
|
|
387
|
-
} catch {
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
return null;
|
|
391
|
-
}
|
|
392
|
-
var handler = async (args, options) => {
|
|
393
|
-
if (rejectRemovedProjectId(args)) {
|
|
394
|
-
return;
|
|
395
|
-
}
|
|
396
|
-
const parsed = parseStatusArgs(args);
|
|
397
|
-
if (parsed.error) {
|
|
398
|
-
process.stderr.write(`${parsed.error}
|
|
399
|
-
`);
|
|
400
|
-
process.stderr.write("Usage: gh-symphony status [--watch]\n");
|
|
401
|
-
process.exitCode = 2;
|
|
402
|
-
return;
|
|
403
|
-
}
|
|
404
|
-
const projectConfig = await resolveManagedProjectConfig({
|
|
405
|
-
configDir: options.configDir,
|
|
406
|
-
requestedProjectId: void 0
|
|
407
|
-
});
|
|
408
|
-
if (!projectConfig) {
|
|
409
|
-
handleMissingManagedProjectConfig();
|
|
410
|
-
return;
|
|
411
|
-
}
|
|
412
|
-
const runtimeRoot = resolveRuntimeRoot(options.configDir);
|
|
413
|
-
const projectId = projectConfig.projectId;
|
|
414
|
-
if (parsed.watch) {
|
|
415
|
-
const isTTY = process.stdout.isTTY === true;
|
|
416
|
-
let terminalWidth = process.stdout.columns ?? 115;
|
|
417
|
-
let runPromise = null;
|
|
418
|
-
const run = async () => {
|
|
419
|
-
const snapshot2 = await readStatusSnapshot(runtimeRoot, projectId);
|
|
420
|
-
if (options.json || !isTTY) {
|
|
421
|
-
process.stdout.write(JSON.stringify(snapshot2, null, 2) + "\n");
|
|
422
|
-
} else {
|
|
423
|
-
if (!snapshot2) {
|
|
424
|
-
process.stdout.write(
|
|
425
|
-
clearScreen() + "Unable to read status snapshot.\n"
|
|
426
|
-
);
|
|
427
|
-
return;
|
|
428
|
-
}
|
|
429
|
-
process.stdout.write(
|
|
430
|
-
clearScreen() + renderDashboard([snapshot2], {
|
|
431
|
-
terminalWidth,
|
|
432
|
-
noColor: options.noColor
|
|
433
|
-
}) + "\n"
|
|
434
|
-
);
|
|
435
|
-
}
|
|
436
|
-
};
|
|
437
|
-
const tick = () => {
|
|
438
|
-
if (runPromise) {
|
|
439
|
-
return;
|
|
440
|
-
}
|
|
441
|
-
runPromise = run().finally(() => {
|
|
442
|
-
runPromise = null;
|
|
443
|
-
});
|
|
444
|
-
};
|
|
445
|
-
if (isTTY) {
|
|
446
|
-
process.stdout.write(hideCursor());
|
|
447
|
-
}
|
|
448
|
-
tick();
|
|
449
|
-
await runPromise;
|
|
450
|
-
const interval = setInterval(tick, 2e3);
|
|
451
|
-
process.on("SIGWINCH", () => {
|
|
452
|
-
terminalWidth = process.stdout.columns ?? terminalWidth;
|
|
453
|
-
});
|
|
454
|
-
const shutdown = () => {
|
|
455
|
-
clearInterval(interval);
|
|
456
|
-
process.stdout.write(showCursor() + "\n");
|
|
457
|
-
process.exit(0);
|
|
458
|
-
};
|
|
459
|
-
process.on("SIGINT", shutdown);
|
|
460
|
-
process.on("SIGTERM", shutdown);
|
|
461
|
-
await new Promise(() => {
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
const snapshot = await readStatusSnapshot(runtimeRoot, projectId);
|
|
465
|
-
if (snapshot) {
|
|
466
|
-
if (options.json) {
|
|
467
|
-
process.stdout.write(JSON.stringify(snapshot, null, 2) + "\n");
|
|
468
|
-
} else {
|
|
469
|
-
process.stdout.write(
|
|
470
|
-
renderLegacyStatus(snapshot, options.noColor) + "\n"
|
|
471
|
-
);
|
|
472
|
-
}
|
|
473
|
-
} else {
|
|
474
|
-
process.stderr.write("Unable to read status snapshot.\n");
|
|
475
|
-
process.exitCode = 1;
|
|
476
|
-
}
|
|
477
|
-
};
|
|
478
|
-
var status_default = handler;
|
|
479
|
-
|
|
480
|
-
export {
|
|
481
|
-
status_default
|
|
482
|
-
};
|