@usepowerplant/cli 0.3.0 → 0.3.1
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/cli.js +155 -25
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -78652,7 +78652,7 @@ import os6 from "node:os";
|
|
|
78652
78652
|
// ../../apps/collector/src/http.ts
|
|
78653
78653
|
var import_undici = __toESM(require_undici(), 1);
|
|
78654
78654
|
var CLI_VERSION_HEADER = "x-powerplant-cli-version";
|
|
78655
|
-
var cliVersion = true ? "0.3.
|
|
78655
|
+
var cliVersion = true ? "0.3.1" : "0.0.0-checkout";
|
|
78656
78656
|
function cliVersionHeaders() {
|
|
78657
78657
|
return { [CLI_VERSION_HEADER]: cliVersion, "user-agent": `powerplant-cli/${cliVersion}` };
|
|
78658
78658
|
}
|
|
@@ -79492,18 +79492,53 @@ import { setImmediate as yieldToEventLoop } from "node:timers/promises";
|
|
|
79492
79492
|
import path4 from "node:path";
|
|
79493
79493
|
|
|
79494
79494
|
// ../../apps/collector/src/scan.ts
|
|
79495
|
-
import { readdirSync, readFileSync as readFileSync5, statSync as statSync2 } from "node:fs";
|
|
79495
|
+
import { closeSync, openSync, readdirSync, readFileSync as readFileSync5, readSync, statSync as statSync2 } from "node:fs";
|
|
79496
|
+
import { StringDecoder } from "node:string_decoder";
|
|
79496
79497
|
var ACTIVE_GRACE_MS = SESSION_ACTIVE_WINDOW_MS;
|
|
79497
79498
|
var jsonObjectSchema = external_exports.record(external_exports.string(), external_exports.unknown());
|
|
79498
79499
|
function* parseJsonl(text) {
|
|
79499
79500
|
for (const line of text.split("\n")) {
|
|
79500
|
-
|
|
79501
|
-
|
|
79502
|
-
|
|
79503
|
-
|
|
79504
|
-
|
|
79505
|
-
|
|
79506
|
-
|
|
79501
|
+
const record2 = parseJsonlLine(line);
|
|
79502
|
+
if (record2 !== null) yield record2;
|
|
79503
|
+
}
|
|
79504
|
+
}
|
|
79505
|
+
function parseJsonlLine(line) {
|
|
79506
|
+
if (!line.trim()) return null;
|
|
79507
|
+
try {
|
|
79508
|
+
const value = JSON.parse(line);
|
|
79509
|
+
const parsed = jsonObjectSchema.safeParse(value);
|
|
79510
|
+
return parsed.success ? parsed.data : null;
|
|
79511
|
+
} catch {
|
|
79512
|
+
return null;
|
|
79513
|
+
}
|
|
79514
|
+
}
|
|
79515
|
+
var READ_CHUNK_BYTES = 64 * 1024;
|
|
79516
|
+
function readFirstRecord(file2, matches) {
|
|
79517
|
+
let fd;
|
|
79518
|
+
try {
|
|
79519
|
+
fd = openSync(file2, "r");
|
|
79520
|
+
} catch (error52) {
|
|
79521
|
+
if (error52.code === "ENOENT") return null;
|
|
79522
|
+
throw error52;
|
|
79523
|
+
}
|
|
79524
|
+
const buffer = Buffer.alloc(READ_CHUNK_BYTES);
|
|
79525
|
+
const decoder = new StringDecoder("utf8");
|
|
79526
|
+
let carry = "";
|
|
79527
|
+
try {
|
|
79528
|
+
for (; ; ) {
|
|
79529
|
+
const bytes = readSync(fd, buffer, 0, buffer.length, null);
|
|
79530
|
+
if (bytes === 0) break;
|
|
79531
|
+
const lines = (carry + decoder.write(buffer.subarray(0, bytes))).split("\n");
|
|
79532
|
+
carry = lines.pop() ?? "";
|
|
79533
|
+
for (const line of lines) {
|
|
79534
|
+
const record2 = parseJsonlLine(line);
|
|
79535
|
+
if (record2 !== null && matches(record2)) return record2;
|
|
79536
|
+
}
|
|
79537
|
+
}
|
|
79538
|
+
const last = parseJsonlLine(carry + decoder.end());
|
|
79539
|
+
return last !== null && matches(last) ? last : null;
|
|
79540
|
+
} finally {
|
|
79541
|
+
closeSync(fd);
|
|
79507
79542
|
}
|
|
79508
79543
|
}
|
|
79509
79544
|
function listDirs(dir) {
|
|
@@ -79635,6 +79670,24 @@ async function collectClaudeCodeSessions(options = {}) {
|
|
|
79635
79670
|
const stat = statIfExists(transcriptPath);
|
|
79636
79671
|
if (!stat) continue;
|
|
79637
79672
|
if (options.sinceMs !== void 0 && stat.mtimeMs < options.sinceMs) continue;
|
|
79673
|
+
const sessionId = path5.basename(entry, ".jsonl");
|
|
79674
|
+
const endObservedAt = observedSessionEnd(lifecycle.get(sessionId), stat.mtimeMs);
|
|
79675
|
+
const status = endObservedAt === null && now - stat.mtimeMs < ACTIVE_GRACE_MS ? "active" : "inactive";
|
|
79676
|
+
if (options.locationsOnly) {
|
|
79677
|
+
const cwd = transcriptCwd(transcriptPath);
|
|
79678
|
+
const decision2 = captureDecision(cwd, capture);
|
|
79679
|
+
if (!decision2.capture) {
|
|
79680
|
+
skippedOutOfScope += 1;
|
|
79681
|
+
continue;
|
|
79682
|
+
}
|
|
79683
|
+
items.push({
|
|
79684
|
+
mtimeMs: stat.mtimeMs,
|
|
79685
|
+
transcriptPath,
|
|
79686
|
+
...cwd && { cwd },
|
|
79687
|
+
item: { source: "claude-code", externalId: sessionId, status, capturedVia: decision2.via }
|
|
79688
|
+
});
|
|
79689
|
+
continue;
|
|
79690
|
+
}
|
|
79638
79691
|
const text = readIfExists2(transcriptPath);
|
|
79639
79692
|
if (text === null) continue;
|
|
79640
79693
|
const summary = parseClaudeCodeTranscript(text);
|
|
@@ -79644,9 +79697,7 @@ async function collectClaudeCodeSessions(options = {}) {
|
|
|
79644
79697
|
skippedOutOfScope += 1;
|
|
79645
79698
|
continue;
|
|
79646
79699
|
}
|
|
79647
|
-
const sessionId = path5.basename(entry, ".jsonl");
|
|
79648
79700
|
const usage = addSubagentUsage(summary.usage, path5.join(projectDir, sessionId, "subagents"));
|
|
79649
|
-
const endObservedAt = observedSessionEnd(lifecycle.get(sessionId), stat.mtimeMs);
|
|
79650
79701
|
const endedAt = endObservedAt ?? summary.endedAt;
|
|
79651
79702
|
items.push({
|
|
79652
79703
|
mtimeMs: stat.mtimeMs,
|
|
@@ -79655,7 +79706,7 @@ async function collectClaudeCodeSessions(options = {}) {
|
|
|
79655
79706
|
item: {
|
|
79656
79707
|
source: "claude-code",
|
|
79657
79708
|
externalId: sessionId,
|
|
79658
|
-
status
|
|
79709
|
+
status,
|
|
79659
79710
|
...summary.startedAt && { startedAt: summary.startedAt },
|
|
79660
79711
|
...endedAt && { endedAt },
|
|
79661
79712
|
...summary.model && { model: summary.model },
|
|
@@ -79683,6 +79734,13 @@ async function collectClaudeCodeSessions(options = {}) {
|
|
|
79683
79734
|
skippedOutOfScope
|
|
79684
79735
|
};
|
|
79685
79736
|
}
|
|
79737
|
+
function transcriptCwd(transcriptPath) {
|
|
79738
|
+
const record2 = readFirstRecord(
|
|
79739
|
+
transcriptPath,
|
|
79740
|
+
(candidate) => typeof candidate.cwd === "string" && candidate.cwd !== ""
|
|
79741
|
+
);
|
|
79742
|
+
return typeof record2?.cwd === "string" ? record2.cwd : void 0;
|
|
79743
|
+
}
|
|
79686
79744
|
function toUsage(u) {
|
|
79687
79745
|
const n = (value) => typeof value === "number" ? value : 0;
|
|
79688
79746
|
return {
|
|
@@ -79765,6 +79823,21 @@ function parseCodexRollout(text) {
|
|
|
79765
79823
|
...typeof git?.repository_url === "string" && repoFullNameFrom(git.repository_url)
|
|
79766
79824
|
};
|
|
79767
79825
|
}
|
|
79826
|
+
function parseRolloutFile(rolloutPath) {
|
|
79827
|
+
const text = readIfExists2(rolloutPath);
|
|
79828
|
+
return text === null ? null : parseCodexRollout(text);
|
|
79829
|
+
}
|
|
79830
|
+
function rolloutLocation(rolloutPath) {
|
|
79831
|
+
const record2 = readFirstRecord(rolloutPath, (candidate) => candidate.type === "session_meta");
|
|
79832
|
+
const meta3 = record2?.payload;
|
|
79833
|
+
if (!meta3 || typeof meta3 !== "object" || Array.isArray(meta3)) return { kind: "session", totals: null };
|
|
79834
|
+
const { thread_source: threadSource, cwd } = meta3;
|
|
79835
|
+
return {
|
|
79836
|
+
kind: threadSource === "subagent" ? "subagent" : "session",
|
|
79837
|
+
totals: null,
|
|
79838
|
+
...typeof cwd === "string" && cwd !== "" && { cwd }
|
|
79839
|
+
};
|
|
79840
|
+
}
|
|
79768
79841
|
function repoFullNameFrom(url2) {
|
|
79769
79842
|
const fullName = parseGithubRepo(url2);
|
|
79770
79843
|
return fullName ? { repoFullName: fullName } : {};
|
|
@@ -79802,7 +79875,7 @@ async function collectCodexSessions(options = {}) {
|
|
|
79802
79875
|
const sessionsDir = options.codexDir ?? path6.join(os8.homedir(), ".codex", "sessions");
|
|
79803
79876
|
const now = options.now ?? Date.now();
|
|
79804
79877
|
const capture = options.capture ?? captureEverythingUnresolved;
|
|
79805
|
-
const threadNames = loadThreadNames(sessionsDir);
|
|
79878
|
+
const threadNames = options.locationsOnly ? /* @__PURE__ */ new Map() : loadThreadNames(sessionsDir);
|
|
79806
79879
|
const items = [];
|
|
79807
79880
|
let skippedOutOfScope = 0;
|
|
79808
79881
|
let skippedSubagentThreads = 0;
|
|
@@ -79813,9 +79886,7 @@ async function collectCodexSessions(options = {}) {
|
|
|
79813
79886
|
if (!stat) continue;
|
|
79814
79887
|
if (options.sinceMs !== void 0 && Math.max(stat.mtimeMs, stat.ctimeMs) < options.sinceMs)
|
|
79815
79888
|
continue;
|
|
79816
|
-
const
|
|
79817
|
-
if (text === null) continue;
|
|
79818
|
-
const summary = parseCodexRollout(text);
|
|
79889
|
+
const summary = options.locationsOnly ? rolloutLocation(rolloutPath) : parseRolloutFile(rolloutPath);
|
|
79819
79890
|
if (!summary) continue;
|
|
79820
79891
|
if (summary.kind === "subagent") {
|
|
79821
79892
|
skippedSubagentThreads += 1;
|
|
@@ -79826,6 +79897,21 @@ async function collectCodexSessions(options = {}) {
|
|
|
79826
79897
|
skippedOutOfScope += 1;
|
|
79827
79898
|
continue;
|
|
79828
79899
|
}
|
|
79900
|
+
if (options.locationsOnly) {
|
|
79901
|
+
items.push({
|
|
79902
|
+
mtimeMs: stat.mtimeMs,
|
|
79903
|
+
transcriptPath: rolloutPath,
|
|
79904
|
+
...summary.cwd && { cwd: summary.cwd },
|
|
79905
|
+
item: {
|
|
79906
|
+
source: "codex",
|
|
79907
|
+
externalId: path6.basename(rolloutPath, ".jsonl"),
|
|
79908
|
+
status: now - stat.mtimeMs < ACTIVE_GRACE_MS ? "active" : "inactive",
|
|
79909
|
+
archived,
|
|
79910
|
+
capturedVia: decision.via
|
|
79911
|
+
}
|
|
79912
|
+
});
|
|
79913
|
+
continue;
|
|
79914
|
+
}
|
|
79829
79915
|
const repoDir = summary.repoName ?? (summary.cwd ? path6.basename(summary.cwd) : void 0);
|
|
79830
79916
|
const repoFullName = decision.repoFullName ?? summary.repoFullName;
|
|
79831
79917
|
const title = summary.sessionId ? threadNames.get(summary.sessionId) : void 0;
|
|
@@ -79894,8 +79980,29 @@ var emptyResult = () => ({
|
|
|
79894
79980
|
skippedUnreadable: 0,
|
|
79895
79981
|
unavailable: null
|
|
79896
79982
|
});
|
|
79983
|
+
var SQLITE_EXPERIMENTAL_WARNING = "SQLite is an experimental feature and might change at any time";
|
|
79984
|
+
async function withSqliteExperimentalWarningSuppressed(load) {
|
|
79985
|
+
const forward = process.emitWarning.bind(process);
|
|
79986
|
+
process.emitWarning = (warning2, ...rest) => {
|
|
79987
|
+
const message = typeof warning2 === "string" ? warning2 : warning2.message;
|
|
79988
|
+
if (message === SQLITE_EXPERIMENTAL_WARNING) return;
|
|
79989
|
+
Reflect.apply(forward, process, [warning2, ...rest]);
|
|
79990
|
+
};
|
|
79991
|
+
try {
|
|
79992
|
+
return await load();
|
|
79993
|
+
} finally {
|
|
79994
|
+
process.emitWarning = forward;
|
|
79995
|
+
}
|
|
79996
|
+
}
|
|
79997
|
+
var sqliteModule;
|
|
79998
|
+
function loadSqlite() {
|
|
79999
|
+
sqliteModule ??= withSqliteExperimentalWarningSuppressed(
|
|
80000
|
+
() => import("node:sqlite")
|
|
80001
|
+
);
|
|
80002
|
+
return sqliteModule;
|
|
80003
|
+
}
|
|
79897
80004
|
async function openCursorDatabase(dbPath) {
|
|
79898
|
-
const sqlite = await
|
|
80005
|
+
const sqlite = await loadSqlite();
|
|
79899
80006
|
return new sqlite.DatabaseSync(dbPath, { readOnly: true });
|
|
79900
80007
|
}
|
|
79901
80008
|
function describeError(error52) {
|
|
@@ -80240,8 +80347,8 @@ async function findRecentProtectedSessions(options = {}, deps = defaultDiscovery
|
|
|
80240
80347
|
const sinceMs = now - DEEP_FIRST_SYNC_DAYS * 24 * 60 * 60 * 1e3;
|
|
80241
80348
|
const capture = captureEverythingUnresolved;
|
|
80242
80349
|
const results = [
|
|
80243
|
-
await deps.collectClaude({ sinceMs, capture }),
|
|
80244
|
-
await deps.collectCodex({ sinceMs, capture }),
|
|
80350
|
+
await deps.collectClaude({ sinceMs, capture, locationsOnly: true }),
|
|
80351
|
+
await deps.collectCodex({ sinceMs, capture, locationsOnly: true }),
|
|
80245
80352
|
await deps.collectCursor({ sinceMs, capture, locationsOnly: true })
|
|
80246
80353
|
];
|
|
80247
80354
|
return groupProtectedSessions(
|
|
@@ -80478,17 +80585,40 @@ function installerPathValue() {
|
|
|
80478
80585
|
}
|
|
80479
80586
|
function installService(config2, command) {
|
|
80480
80587
|
requireMacos();
|
|
80588
|
+
bootout(config2.appEnv);
|
|
80589
|
+
if (!waitForUnload(() => isLoaded(config2.appEnv))) {
|
|
80590
|
+
const service = `gui/${uid()}/${label(config2.appEnv)}`;
|
|
80591
|
+
throw new Error(
|
|
80592
|
+
`launchd is still unloading ${label(config2.appEnv)} after ${UNLOAD_WAIT_MS / 1e3}s \u2014 re-run powerplant init, or unload it by hand first: launchctl bootout ${service}`
|
|
80593
|
+
);
|
|
80594
|
+
}
|
|
80481
80595
|
const launcher = launcherPath(config2.appEnv);
|
|
80482
80596
|
mkdirSync4(path10.dirname(launcher), { recursive: true });
|
|
80483
80597
|
writeFileSync4(launcher, buildLauncherScript(command));
|
|
80484
80598
|
chmodSync2(launcher, 493);
|
|
80485
80599
|
const file2 = plistPath(config2.appEnv);
|
|
80486
80600
|
mkdirSync4(path10.dirname(file2), { recursive: true });
|
|
80487
|
-
bootout(config2.appEnv);
|
|
80488
80601
|
writeFileSync4(file2, buildLaunchdPlist(config2.appEnv, installerPathValue()));
|
|
80489
80602
|
runLaunchctl(["bootstrap", `gui/${uid()}`, file2]);
|
|
80490
80603
|
return `${file2} (watching for session changes; log: ${logPath(config2.appEnv)})`;
|
|
80491
80604
|
}
|
|
80605
|
+
var UNLOAD_WAIT_MS = 1e4;
|
|
80606
|
+
var UNLOAD_POLL_MS = 100;
|
|
80607
|
+
function waitForUnload(loaded, options = {}) {
|
|
80608
|
+
const deadlineMs = options.deadlineMs ?? UNLOAD_WAIT_MS;
|
|
80609
|
+
const pollMs = options.pollMs ?? UNLOAD_POLL_MS;
|
|
80610
|
+
const sleep = options.sleep ?? sleepSync;
|
|
80611
|
+
const now = options.now ?? Date.now;
|
|
80612
|
+
const deadline = now() + deadlineMs;
|
|
80613
|
+
while (loaded()) {
|
|
80614
|
+
if (now() >= deadline) return false;
|
|
80615
|
+
sleep(pollMs);
|
|
80616
|
+
}
|
|
80617
|
+
return true;
|
|
80618
|
+
}
|
|
80619
|
+
function sleepSync(ms) {
|
|
80620
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
80621
|
+
}
|
|
80492
80622
|
function serviceUpToDate(config2, command) {
|
|
80493
80623
|
if (process.platform !== "darwin") return false;
|
|
80494
80624
|
const launcher = launcherPath(config2.appEnv);
|
|
@@ -82999,7 +83129,7 @@ function whichAllWith(pathValue) {
|
|
|
82999
83129
|
}
|
|
83000
83130
|
|
|
83001
83131
|
// src/doctor.ts
|
|
83002
|
-
import { closeSync, fstatSync, openSync, readSync } from "node:fs";
|
|
83132
|
+
import { closeSync as closeSync2, fstatSync, openSync as openSync2, readSync as readSync2 } from "node:fs";
|
|
83003
83133
|
|
|
83004
83134
|
// src/statusReport.ts
|
|
83005
83135
|
function renderStatus(i) {
|
|
@@ -83158,7 +83288,7 @@ function redactedLogTail(raw) {
|
|
|
83158
83288
|
function readDoctorLogTail(path19) {
|
|
83159
83289
|
let fd;
|
|
83160
83290
|
try {
|
|
83161
|
-
fd =
|
|
83291
|
+
fd = openSync2(path19, "r");
|
|
83162
83292
|
} catch (error52) {
|
|
83163
83293
|
if (error52.code === "ENOENT") return { path: path19, lines: null };
|
|
83164
83294
|
return { path: path19, lines: null, readError: error52 instanceof Error ? error52.message : String(error52) };
|
|
@@ -83167,14 +83297,14 @@ function readDoctorLogTail(path19) {
|
|
|
83167
83297
|
const size = fstatSync(fd).size;
|
|
83168
83298
|
const offset = Math.max(0, size - LOG_TAIL_READ_BYTES);
|
|
83169
83299
|
const buffer = Buffer.alloc(Math.min(size, LOG_TAIL_READ_BYTES));
|
|
83170
|
-
|
|
83300
|
+
readSync2(fd, buffer, 0, buffer.length, offset);
|
|
83171
83301
|
let text = buffer.toString("utf8");
|
|
83172
83302
|
if (offset > 0) text = text.slice(text.indexOf("\n") + 1);
|
|
83173
83303
|
return { path: path19, lines: redactedLogTail(text) };
|
|
83174
83304
|
} catch (error52) {
|
|
83175
83305
|
return { path: path19, lines: null, readError: error52 instanceof Error ? error52.message : String(error52) };
|
|
83176
83306
|
} finally {
|
|
83177
|
-
|
|
83307
|
+
closeSync2(fd);
|
|
83178
83308
|
}
|
|
83179
83309
|
}
|
|
83180
83310
|
function renderDoctorReport(i) {
|
|
@@ -84010,7 +84140,7 @@ function createTerminalOutput(options) {
|
|
|
84010
84140
|
}
|
|
84011
84141
|
|
|
84012
84142
|
// src/version.ts
|
|
84013
|
-
var CLI_VERSION = true ? "0.3.
|
|
84143
|
+
var CLI_VERSION = true ? "0.3.1" : "0.0.0-checkout";
|
|
84014
84144
|
var CLI_PACKAGE_NAME = "@usepowerplant/cli";
|
|
84015
84145
|
|
|
84016
84146
|
// src/workspace.ts
|