@usepowerplant/cli 0.3.1 → 0.3.2
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 +264 -122
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -36252,7 +36252,7 @@ ${captureLines}` : capture.stack;
|
|
|
36252
36252
|
});
|
|
36253
36253
|
|
|
36254
36254
|
// src/cli.ts
|
|
36255
|
-
import { spawnSync as
|
|
36255
|
+
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
36256
36256
|
import { existsSync as existsSync7, realpathSync as realpathSync2 } from "node:fs";
|
|
36257
36257
|
import { parseArgs } from "node:util";
|
|
36258
36258
|
|
|
@@ -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.2" : "0.0.0-checkout";
|
|
78656
78656
|
function cliVersionHeaders() {
|
|
78657
78657
|
return { [CLI_VERSION_HEADER]: cliVersion, "user-agent": `powerplant-cli/${cliVersion}` };
|
|
78658
78658
|
}
|
|
@@ -78729,30 +78729,78 @@ import os5 from "node:os";
|
|
|
78729
78729
|
import path3 from "node:path";
|
|
78730
78730
|
|
|
78731
78731
|
// ../../apps/collector/src/gitOwner.ts
|
|
78732
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
78732
78733
|
import { readFileSync as readFileSync3, statSync } from "node:fs";
|
|
78733
78734
|
import os4 from "node:os";
|
|
78734
78735
|
import path2 from "node:path";
|
|
78735
|
-
|
|
78736
|
+
var GITHUB_HOSTS = /* @__PURE__ */ new Set(["github.com", "ssh.github.com"]);
|
|
78737
|
+
function parseRemoteUrl(remoteUrl) {
|
|
78736
78738
|
const trimmed = remoteUrl.trim();
|
|
78737
|
-
const
|
|
78738
|
-
if (
|
|
78739
|
-
const
|
|
78740
|
-
|
|
78741
|
-
if (authority === "github.com" && owner && rawRepo && extra === void 0) {
|
|
78742
|
-
const repo = rawRepo.toLowerCase().endsWith(".git") ? rawRepo.slice(0, -4) : rawRepo;
|
|
78743
|
-
return `${owner.toLowerCase()}/${repo}`;
|
|
78744
|
-
}
|
|
78739
|
+
const colon = trimmed.indexOf(":");
|
|
78740
|
+
if (!trimmed.includes("://") && colon > 0 && !trimmed.slice(0, colon).includes("/")) {
|
|
78741
|
+
const host = trimmed.slice(0, colon).split("@").at(-1) ?? "";
|
|
78742
|
+
return { host: host.toLowerCase(), path: trimmed.slice(colon + 1), overSsh: true };
|
|
78745
78743
|
}
|
|
78746
78744
|
try {
|
|
78747
78745
|
const url2 = new URL(trimmed);
|
|
78748
|
-
if (url2.hostname
|
|
78749
|
-
const
|
|
78750
|
-
|
|
78751
|
-
|
|
78746
|
+
if (!url2.hostname) return null;
|
|
78747
|
+
const scheme = url2.protocol.slice(0, -1).toLowerCase();
|
|
78748
|
+
return {
|
|
78749
|
+
host: url2.hostname.toLowerCase(),
|
|
78750
|
+
path: url2.pathname,
|
|
78751
|
+
overSsh: scheme === "ssh" || scheme === "git+ssh"
|
|
78752
|
+
};
|
|
78752
78753
|
} catch {
|
|
78753
78754
|
return null;
|
|
78754
78755
|
}
|
|
78755
78756
|
}
|
|
78757
|
+
function parseGithubRepo(remoteUrl, sshHostnameOf = sshEffectiveHostname) {
|
|
78758
|
+
const remote = parseRemoteUrl(remoteUrl);
|
|
78759
|
+
if (!remote) return null;
|
|
78760
|
+
const host = remote.overSsh && !GITHUB_HOSTS.has(remote.host) ? sshHostnameOf(remote.host)?.toLowerCase() : remote.host;
|
|
78761
|
+
if (!host || !GITHUB_HOSTS.has(host)) return null;
|
|
78762
|
+
const [owner, rawRepo, extra] = remote.path.split("/").filter(Boolean);
|
|
78763
|
+
if (!owner || !rawRepo || extra !== void 0) return null;
|
|
78764
|
+
return `${owner.toLowerCase()}/${rawRepo.replace(/\.git$/i, "")}`;
|
|
78765
|
+
}
|
|
78766
|
+
var SSH_PROBE_TIMEOUT_MS = 2e3;
|
|
78767
|
+
var SSH_PROBE_CACHE_TTL_MS = 5 * 6e4;
|
|
78768
|
+
var SSH_HOST_PATTERN = /^[a-z0-9][a-z0-9._-]*$/i;
|
|
78769
|
+
var sshProbeCache = /* @__PURE__ */ new Map();
|
|
78770
|
+
function sshEffectiveHostname(host, options = {}) {
|
|
78771
|
+
if (!SSH_HOST_PATTERN.test(host)) return null;
|
|
78772
|
+
const key = `${options.configFile ?? ""}\0${host}`;
|
|
78773
|
+
const cached3 = sshProbeCache.get(key);
|
|
78774
|
+
const now = Date.now();
|
|
78775
|
+
if (cached3 && cached3.expiresAt > now) return cached3.hostname;
|
|
78776
|
+
const hostname4 = probeSshHostname(host, options);
|
|
78777
|
+
sshProbeCache.set(key, { hostname: hostname4, expiresAt: now + SSH_PROBE_CACHE_TTL_MS });
|
|
78778
|
+
return hostname4;
|
|
78779
|
+
}
|
|
78780
|
+
function probeSshHostname(host, options) {
|
|
78781
|
+
try {
|
|
78782
|
+
const dump = execFileSync2(
|
|
78783
|
+
"ssh",
|
|
78784
|
+
["-G", ...options.configFile ? ["-F", options.configFile] : [], host],
|
|
78785
|
+
{
|
|
78786
|
+
encoding: "utf8",
|
|
78787
|
+
timeout: options.timeoutMs ?? SSH_PROBE_TIMEOUT_MS,
|
|
78788
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
78789
|
+
windowsHide: true
|
|
78790
|
+
}
|
|
78791
|
+
);
|
|
78792
|
+
return hostnameFromSshConfigDump(dump);
|
|
78793
|
+
} catch {
|
|
78794
|
+
return null;
|
|
78795
|
+
}
|
|
78796
|
+
}
|
|
78797
|
+
function hostnameFromSshConfigDump(dump) {
|
|
78798
|
+
for (const line of dump.split("\n")) {
|
|
78799
|
+
const match = /^hostname\s+(\S+)$/i.exec(line.trim());
|
|
78800
|
+
if (match?.[1]) return match[1];
|
|
78801
|
+
}
|
|
78802
|
+
return null;
|
|
78803
|
+
}
|
|
78756
78804
|
function parseOriginUrl(configText) {
|
|
78757
78805
|
let inOrigin = false;
|
|
78758
78806
|
for (const raw of configText.split("\n")) {
|
|
@@ -78818,17 +78866,17 @@ function findGitConfigPath(cwd, environment = {}) {
|
|
|
78818
78866
|
const dirs = resolveGitDirs(cwd, environment);
|
|
78819
78867
|
return dirs ? path2.join(dirs.commonDir, "config") : null;
|
|
78820
78868
|
}
|
|
78821
|
-
function resolveGithubRepo(cwd, environment = {}) {
|
|
78869
|
+
function resolveGithubRepo(cwd, environment = {}, sshHostnameOf = sshEffectiveHostname) {
|
|
78822
78870
|
const configPath = findGitConfigPath(cwd, environment);
|
|
78823
78871
|
const configText = configPath ? readIfExists(configPath) : null;
|
|
78824
78872
|
const remoteUrl = configText ? parseOriginUrl(configText) : null;
|
|
78825
|
-
return remoteUrl ? parseGithubRepo(remoteUrl) : null;
|
|
78873
|
+
return remoteUrl ? parseGithubRepo(remoteUrl, sshHostnameOf) : null;
|
|
78826
78874
|
}
|
|
78827
|
-
function repoResolver(environment = {}) {
|
|
78875
|
+
function repoResolver(environment = {}, sshHostnameOf = sshEffectiveHostname) {
|
|
78828
78876
|
const cache = /* @__PURE__ */ new Map();
|
|
78829
78877
|
return (cwd) => {
|
|
78830
78878
|
const key = path2.resolve(cwd);
|
|
78831
|
-
if (!cache.has(key)) cache.set(key, resolveGithubRepo(key, environment));
|
|
78879
|
+
if (!cache.has(key)) cache.set(key, resolveGithubRepo(key, environment, sshHostnameOf));
|
|
78832
78880
|
return cache.get(key);
|
|
78833
78881
|
};
|
|
78834
78882
|
}
|
|
@@ -78860,17 +78908,18 @@ var captureEverythingUnresolved = {
|
|
|
78860
78908
|
function captureDecision(cwd, policy) {
|
|
78861
78909
|
switch (policy.mode) {
|
|
78862
78910
|
case "scope":
|
|
78863
|
-
|
|
78911
|
+
if (cwd === void 0) return { capture: false, reason: "no-cwd" };
|
|
78912
|
+
return isWithinScope(cwd, policy.scopePaths, policy.environment) ? memberChoice(cwd, policy) : { capture: false, reason: "outside-policy" };
|
|
78864
78913
|
case "org-repos": {
|
|
78865
|
-
if (cwd === void 0) return { capture: false };
|
|
78914
|
+
if (cwd === void 0) return { capture: false, reason: "no-cwd" };
|
|
78866
78915
|
if (policy.memberFolders.length > 0 && isWithinScope(cwd, policy.memberFolders, policy.environment)) {
|
|
78867
78916
|
return memberChoice(cwd, policy);
|
|
78868
78917
|
}
|
|
78869
78918
|
const repoFullName = policy.repoOf(cwd);
|
|
78870
|
-
if (repoFullName === null) return { capture: false };
|
|
78919
|
+
if (repoFullName === null) return { capture: false, reason: "no-github-repo" };
|
|
78871
78920
|
const repo = repoFullName.toLowerCase();
|
|
78872
78921
|
const admitted = policy.allowedRepos !== null ? policy.allowedRepos.includes(repo) : policy.allowedOwners.length > 0 && policy.allowedOwners.includes(ownerOfRepo(repo));
|
|
78873
|
-
return admitted ? { capture: true, via: "org-policy", repoFullName } : { capture: false };
|
|
78922
|
+
return admitted ? { capture: true, via: "org-policy", repoFullName } : { capture: false, reason: "outside-policy" };
|
|
78874
78923
|
}
|
|
78875
78924
|
}
|
|
78876
78925
|
}
|
|
@@ -78893,7 +78942,7 @@ function describeCapturePolicy(policy) {
|
|
|
78893
78942
|
case "scope":
|
|
78894
78943
|
return `sessions under ${policy.scopePaths.join(", ")}`;
|
|
78895
78944
|
case "org-repos": {
|
|
78896
|
-
const repoPart = policy.allowedRepos !== null ? policy.allowedRepos.length > 0 ? `sessions in the org's
|
|
78945
|
+
const repoPart = policy.allowedRepos !== null ? policy.allowedRepos.length > 0 ? `sessions in the org's allowlisted repos: ${listSome(policy.allowedRepos)}` : "the org's repo allowlist is empty \u2014 no repo-based uploads" : policy.allowedOwners.length > 0 ? `sessions in GitHub repos owned by ${policy.allowedOwners.join(", ")}` : "org-owned GitHub repos \u2014 but the org has no GitHub integration, so nothing uploads";
|
|
78897
78946
|
return policy.memberFolders.length > 0 ? `${repoPart}, plus folders you added: ${policy.memberFolders.join(", ")}` : repoPart;
|
|
78898
78947
|
}
|
|
78899
78948
|
}
|
|
@@ -78914,10 +78963,17 @@ function describeStoredCapture(credentials) {
|
|
|
78914
78963
|
repoOf: () => null
|
|
78915
78964
|
});
|
|
78916
78965
|
}
|
|
78917
|
-
function
|
|
78966
|
+
function countCaptureSkip(skips, reason) {
|
|
78967
|
+
if (reason === "outside-policy") skips.skippedOutOfScope += 1;
|
|
78968
|
+
else skips.skippedNoRepo += 1;
|
|
78969
|
+
}
|
|
78970
|
+
function describeSkipReason(policy) {
|
|
78918
78971
|
if (policy.mode !== "org-repos") return "outside the sync boundary, stayed local";
|
|
78919
|
-
|
|
78920
|
-
|
|
78972
|
+
return policy.allowedRepos !== null ? "outside the org's allowlisted repos, stayed local" : "not in org-owned repos, stayed local";
|
|
78973
|
+
}
|
|
78974
|
+
function describeNoRepoSkipReason(policy, platform2 = process.platform) {
|
|
78975
|
+
if (policy.mode !== "org-repos") return "with no working directory recorded, stayed local";
|
|
78976
|
+
return platform2 === "darwin" ? "with no readable GitHub repo or in macOS-protected folders, stayed local (run `powerplant init` to review Git repository scanning)" : "with no readable GitHub repo, stayed local";
|
|
78921
78977
|
}
|
|
78922
78978
|
function normalizeScopePath(raw) {
|
|
78923
78979
|
const expanded = raw === "~" || raw.startsWith("~/") ? path3.join(os5.homedir(), raw.slice(1)) : raw;
|
|
@@ -78939,6 +78995,37 @@ function isPathWithinScopes(resolved, scopePaths) {
|
|
|
78939
78995
|
);
|
|
78940
78996
|
}
|
|
78941
78997
|
|
|
78998
|
+
// ../../apps/collector/src/syncWindow.ts
|
|
78999
|
+
var STEADY_SYNC_WINDOW_DAYS = 3;
|
|
79000
|
+
var DEEP_FIRST_SYNC_DAYS = 90;
|
|
79001
|
+
var DEEP_FIRST_SYNC_MAX_SESSIONS = 100;
|
|
79002
|
+
function resolveSyncWindow(explicitSince, deepSyncedAt) {
|
|
79003
|
+
if (explicitSince !== void 0) {
|
|
79004
|
+
const days = Number(explicitSince);
|
|
79005
|
+
if (!Number.isFinite(days) || days <= 0) {
|
|
79006
|
+
throw new ExpectedCliError(`--since must be a positive number of days, got "${explicitSince}"`);
|
|
79007
|
+
}
|
|
79008
|
+
return { days, deepSweep: false };
|
|
79009
|
+
}
|
|
79010
|
+
if (deepSyncedAt === void 0) return { days: DEEP_FIRST_SYNC_DAYS, deepSweep: true };
|
|
79011
|
+
return { days: STEADY_SYNC_WINDOW_DAYS, deepSweep: false };
|
|
79012
|
+
}
|
|
79013
|
+
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
79014
|
+
function resolveScanFloor(window2, nowMs, narrowSinceMs) {
|
|
79015
|
+
if (window2.deepSweep || narrowSinceMs === void 0) return nowMs - window2.days * DAY_MS;
|
|
79016
|
+
return narrowSinceMs;
|
|
79017
|
+
}
|
|
79018
|
+
function rawShipFloorMs(appEnv, nowMs, explicitSince) {
|
|
79019
|
+
if (appEnv !== "development" || explicitSince !== void 0) return null;
|
|
79020
|
+
return nowMs - STEADY_SYNC_WINDOW_DAYS * DAY_MS;
|
|
79021
|
+
}
|
|
79022
|
+
function describeScanReach(window2, narrowSinceMs) {
|
|
79023
|
+
if (window2.deepSweep || narrowSinceMs === void 0) {
|
|
79024
|
+
return `from the last ${window2.days} day(s)`;
|
|
79025
|
+
}
|
|
79026
|
+
return `changed since ${new Date(narrowSinceMs).toISOString()}`;
|
|
79027
|
+
}
|
|
79028
|
+
|
|
78942
79029
|
// ../../apps/collector/src/upload.ts
|
|
78943
79030
|
import { readFileSync as readFileSync4 } from "node:fs";
|
|
78944
79031
|
import { gzipSync } from "node:zlib";
|
|
@@ -79257,6 +79344,9 @@ async function runEnrollment(config2, options) {
|
|
|
79257
79344
|
log3(`Enrolled "${result.machine.name}" (${result.machine.id}) into org "${result.org.name}".`);
|
|
79258
79345
|
log3(`Machine token stored in ${location}.`);
|
|
79259
79346
|
log3(`Syncing: ${describeCapturePolicy(policy)}.`);
|
|
79347
|
+
log3(
|
|
79348
|
+
`First sync backfills up to the ${DEEP_FIRST_SYNC_MAX_SESSIONS} most recently active of those sessions from the last ${DEEP_FIRST_SYNC_DAYS} days; later syncs cover the last ${STEADY_SYNC_WINDOW_DAYS} days.`
|
|
79349
|
+
);
|
|
79260
79350
|
return credentials;
|
|
79261
79351
|
}
|
|
79262
79352
|
async function enroll(config2, options, createAuthClient = gotrueAuthClient) {
|
|
@@ -79453,7 +79543,7 @@ function addFolder(config2, rawPath, enrollCommand, log3, deps = defaultDeps) {
|
|
|
79453
79543
|
});
|
|
79454
79544
|
const org = credentials.orgName ?? "your org";
|
|
79455
79545
|
log3(
|
|
79456
|
-
credentials.captureMode === "org-repos" ? `Sessions under ${folder} will now upload to ${org} \u2014 even outside the org's
|
|
79546
|
+
credentials.captureMode === "org-repos" ? `Sessions under ${folder} will now upload to ${org} \u2014 even outside the org's allowlisted repos.` : `Added ${folder} to this machine's sync boundary.`
|
|
79457
79547
|
);
|
|
79458
79548
|
log3("Takes effect on the next sync pass; run the sync command to apply now.");
|
|
79459
79549
|
}
|
|
@@ -79570,6 +79660,10 @@ function readIfExists2(file2) {
|
|
|
79570
79660
|
throw error52;
|
|
79571
79661
|
}
|
|
79572
79662
|
}
|
|
79663
|
+
var MAX_TRANSCRIPT_FILE_BYTES = 256 * 1024 * 1024;
|
|
79664
|
+
function describeReadError(error52) {
|
|
79665
|
+
return error52 instanceof Error ? error52.message : String(error52);
|
|
79666
|
+
}
|
|
79573
79667
|
|
|
79574
79668
|
// ../../apps/collector/src/lifecycleJournal.ts
|
|
79575
79669
|
var LIFECYCLE_JOURNAL_FILENAME = "session-lifecycle.jsonl";
|
|
@@ -79660,7 +79754,7 @@ async function collectClaudeCodeSessions(options = {}) {
|
|
|
79660
79754
|
const capture = options.capture ?? captureEverythingUnresolved;
|
|
79661
79755
|
const projectsDir = path5.join(claudeDir, "projects");
|
|
79662
79756
|
const items = [];
|
|
79663
|
-
|
|
79757
|
+
const skips = { skippedOutOfScope: 0, skippedNoRepo: 0 };
|
|
79664
79758
|
const home = path5.dirname(claudeDir);
|
|
79665
79759
|
const lifecycle = options.lifecycle ?? readLifecycleJournal(home);
|
|
79666
79760
|
for (const projectDir of listDirs(projectsDir)) {
|
|
@@ -79677,7 +79771,7 @@ async function collectClaudeCodeSessions(options = {}) {
|
|
|
79677
79771
|
const cwd = transcriptCwd(transcriptPath);
|
|
79678
79772
|
const decision2 = captureDecision(cwd, capture);
|
|
79679
79773
|
if (!decision2.capture) {
|
|
79680
|
-
|
|
79774
|
+
countCaptureSkip(skips, decision2.reason);
|
|
79681
79775
|
continue;
|
|
79682
79776
|
}
|
|
79683
79777
|
items.push({
|
|
@@ -79694,7 +79788,7 @@ async function collectClaudeCodeSessions(options = {}) {
|
|
|
79694
79788
|
if (!summary) continue;
|
|
79695
79789
|
const decision = captureDecision(summary.cwd, capture);
|
|
79696
79790
|
if (!decision.capture) {
|
|
79697
|
-
|
|
79791
|
+
countCaptureSkip(skips, decision.reason);
|
|
79698
79792
|
continue;
|
|
79699
79793
|
}
|
|
79700
79794
|
const usage = addSubagentUsage(summary.usage, path5.join(projectDir, sessionId, "subagents"));
|
|
@@ -79731,7 +79825,7 @@ async function collectClaudeCodeSessions(options = {}) {
|
|
|
79731
79825
|
}
|
|
79732
79826
|
return {
|
|
79733
79827
|
sessions: items.sort((a, b2) => b2.mtimeMs - a.mtimeMs),
|
|
79734
|
-
|
|
79828
|
+
...skips
|
|
79735
79829
|
};
|
|
79736
79830
|
}
|
|
79737
79831
|
function transcriptCwd(transcriptPath) {
|
|
@@ -79875,54 +79969,95 @@ async function collectCodexSessions(options = {}) {
|
|
|
79875
79969
|
const sessionsDir = options.codexDir ?? path6.join(os8.homedir(), ".codex", "sessions");
|
|
79876
79970
|
const now = options.now ?? Date.now();
|
|
79877
79971
|
const capture = options.capture ?? captureEverythingUnresolved;
|
|
79878
|
-
const
|
|
79972
|
+
const maxBytes = options.maxTranscriptBytes ?? MAX_TRANSCRIPT_FILE_BYTES;
|
|
79879
79973
|
const items = [];
|
|
79880
|
-
|
|
79974
|
+
const candidates = [];
|
|
79975
|
+
const unreadable = [];
|
|
79976
|
+
const skips = { skippedOutOfScope: 0, skippedNoRepo: 0 };
|
|
79881
79977
|
let skippedSubagentThreads = 0;
|
|
79882
|
-
|
|
79978
|
+
let skippedTooLarge = 0;
|
|
79979
|
+
const externalIdOf = (rolloutPath) => path6.basename(rolloutPath, ".jsonl");
|
|
79980
|
+
const admitFrom = async (rootDir, archived) => {
|
|
79883
79981
|
for (const rolloutPath of rolloutFiles(rootDir)) {
|
|
79884
79982
|
await yieldToEventLoop2();
|
|
79885
79983
|
const stat = statIfExists(rolloutPath);
|
|
79886
79984
|
if (!stat) continue;
|
|
79887
79985
|
if (options.sinceMs !== void 0 && Math.max(stat.mtimeMs, stat.ctimeMs) < options.sinceMs)
|
|
79888
79986
|
continue;
|
|
79889
|
-
|
|
79890
|
-
|
|
79891
|
-
if (summary.kind === "subagent") {
|
|
79892
|
-
skippedSubagentThreads += 1;
|
|
79893
|
-
continue;
|
|
79894
|
-
}
|
|
79895
|
-
const decision = captureDecision(summary.cwd, capture);
|
|
79896
|
-
if (!decision.capture) {
|
|
79897
|
-
skippedOutOfScope += 1;
|
|
79987
|
+
if (stat.size > maxBytes) {
|
|
79988
|
+
skippedTooLarge += 1;
|
|
79898
79989
|
continue;
|
|
79899
79990
|
}
|
|
79900
|
-
|
|
79901
|
-
|
|
79991
|
+
try {
|
|
79992
|
+
const location = rolloutLocation(rolloutPath);
|
|
79993
|
+
if (location.kind === "subagent") {
|
|
79994
|
+
skippedSubagentThreads += 1;
|
|
79995
|
+
continue;
|
|
79996
|
+
}
|
|
79997
|
+
const decision = captureDecision(location.cwd, capture);
|
|
79998
|
+
if (!decision.capture) {
|
|
79999
|
+
countCaptureSkip(skips, decision.reason);
|
|
80000
|
+
continue;
|
|
80001
|
+
}
|
|
80002
|
+
if (options.locationsOnly) {
|
|
80003
|
+
items.push({
|
|
80004
|
+
mtimeMs: stat.mtimeMs,
|
|
80005
|
+
transcriptPath: rolloutPath,
|
|
80006
|
+
...location.cwd && { cwd: location.cwd },
|
|
80007
|
+
item: {
|
|
80008
|
+
source: "codex",
|
|
80009
|
+
externalId: externalIdOf(rolloutPath),
|
|
80010
|
+
status: now - stat.mtimeMs < ACTIVE_GRACE_MS ? "active" : "inactive",
|
|
80011
|
+
archived,
|
|
80012
|
+
capturedVia: decision.via
|
|
80013
|
+
}
|
|
80014
|
+
});
|
|
80015
|
+
continue;
|
|
80016
|
+
}
|
|
80017
|
+
candidates.push({
|
|
80018
|
+
rolloutPath,
|
|
80019
|
+
archived,
|
|
79902
80020
|
mtimeMs: stat.mtimeMs,
|
|
79903
|
-
|
|
79904
|
-
|
|
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
|
-
}
|
|
80021
|
+
...location.cwd && { cwd: location.cwd },
|
|
80022
|
+
decision
|
|
79912
80023
|
});
|
|
79913
|
-
|
|
80024
|
+
} catch (error52) {
|
|
80025
|
+
unreadable.push(`${externalIdOf(rolloutPath)}: ${describeReadError(error52)}`);
|
|
79914
80026
|
}
|
|
79915
|
-
|
|
80027
|
+
}
|
|
80028
|
+
};
|
|
80029
|
+
await admitFrom(sessionsDir, false);
|
|
80030
|
+
await admitFrom(codexArchivedSessionsDir(sessionsDir), true);
|
|
80031
|
+
if (options.locationsOnly) {
|
|
80032
|
+
return {
|
|
80033
|
+
sessions: items.sort((a, b2) => b2.mtimeMs - a.mtimeMs),
|
|
80034
|
+
...skips,
|
|
80035
|
+
skippedSubagentThreads,
|
|
80036
|
+
skippedTooLarge,
|
|
80037
|
+
unreadable,
|
|
80038
|
+
heldBack: 0
|
|
80039
|
+
};
|
|
80040
|
+
}
|
|
80041
|
+
candidates.sort((a, b2) => b2.mtimeMs - a.mtimeMs);
|
|
80042
|
+
const chosen = options.maxSessions === void 0 ? candidates : candidates.slice(0, options.maxSessions);
|
|
80043
|
+
const threadNames = chosen.length > 0 ? loadThreadNames(sessionsDir) : /* @__PURE__ */ new Map();
|
|
80044
|
+
for (const candidate of chosen) {
|
|
80045
|
+
await yieldToEventLoop2();
|
|
80046
|
+
const { rolloutPath, archived, mtimeMs, cwd, decision } = candidate;
|
|
80047
|
+
try {
|
|
80048
|
+
const summary = parseRolloutFile(rolloutPath);
|
|
80049
|
+
if (!summary) continue;
|
|
80050
|
+
const repoDir = summary.repoName ?? (cwd ? path6.basename(cwd) : void 0);
|
|
79916
80051
|
const repoFullName = decision.repoFullName ?? summary.repoFullName;
|
|
79917
80052
|
const title = summary.sessionId ? threadNames.get(summary.sessionId) : void 0;
|
|
79918
80053
|
items.push({
|
|
79919
|
-
mtimeMs
|
|
80054
|
+
mtimeMs,
|
|
79920
80055
|
transcriptPath: rolloutPath,
|
|
79921
|
-
...
|
|
80056
|
+
...cwd && { cwd },
|
|
79922
80057
|
item: {
|
|
79923
80058
|
source: "codex",
|
|
79924
|
-
externalId:
|
|
79925
|
-
status: now -
|
|
80059
|
+
externalId: externalIdOf(rolloutPath),
|
|
80060
|
+
status: now - mtimeMs < ACTIVE_GRACE_MS ? "active" : "inactive",
|
|
79926
80061
|
archived,
|
|
79927
80062
|
...summary.startedAt && { startedAt: summary.startedAt },
|
|
79928
80063
|
...summary.endedAt && { endedAt: summary.endedAt },
|
|
@@ -79940,14 +80075,17 @@ async function collectCodexSessions(options = {}) {
|
|
|
79940
80075
|
capturedVia: decision.via
|
|
79941
80076
|
}
|
|
79942
80077
|
});
|
|
80078
|
+
} catch (error52) {
|
|
80079
|
+
unreadable.push(`${externalIdOf(rolloutPath)}: ${describeReadError(error52)}`);
|
|
79943
80080
|
}
|
|
79944
|
-
}
|
|
79945
|
-
await collectFrom(sessionsDir, false);
|
|
79946
|
-
await collectFrom(codexArchivedSessionsDir(sessionsDir), true);
|
|
80081
|
+
}
|
|
79947
80082
|
return {
|
|
79948
80083
|
sessions: items.sort((a, b2) => b2.mtimeMs - a.mtimeMs),
|
|
79949
|
-
|
|
79950
|
-
skippedSubagentThreads
|
|
80084
|
+
...skips,
|
|
80085
|
+
skippedSubagentThreads,
|
|
80086
|
+
skippedTooLarge,
|
|
80087
|
+
unreadable,
|
|
80088
|
+
heldBack: candidates.length - chosen.length
|
|
79951
80089
|
};
|
|
79952
80090
|
}
|
|
79953
80091
|
|
|
@@ -79975,6 +80113,7 @@ function cursorSpoolDir(home) {
|
|
|
79975
80113
|
var emptyResult = () => ({
|
|
79976
80114
|
sessions: [],
|
|
79977
80115
|
skippedOutOfScope: 0,
|
|
80116
|
+
skippedNoRepo: 0,
|
|
79978
80117
|
skippedSubagentComposers: 0,
|
|
79979
80118
|
skippedNonLocalComposers: 0,
|
|
79980
80119
|
skippedUnreadable: 0,
|
|
@@ -80225,7 +80364,7 @@ function collectFromStore(db, userDir, options, result) {
|
|
|
80225
80364
|
const cwd = facts.workspacePath ?? workspaceFolderOf(userDir, workspaceId);
|
|
80226
80365
|
const decision = captureDecision(cwd, capture);
|
|
80227
80366
|
if (!decision.capture) {
|
|
80228
|
-
result.
|
|
80367
|
+
countCaptureSkip(result, decision.reason);
|
|
80229
80368
|
continue;
|
|
80230
80369
|
}
|
|
80231
80370
|
if (options.locationsOnly) {
|
|
@@ -80306,36 +80445,6 @@ function collectFromStore(db, userDir, options, result) {
|
|
|
80306
80445
|
}
|
|
80307
80446
|
}
|
|
80308
80447
|
|
|
80309
|
-
// ../../apps/collector/src/syncWindow.ts
|
|
80310
|
-
var STEADY_SYNC_WINDOW_DAYS = 3;
|
|
80311
|
-
var DEEP_FIRST_SYNC_DAYS = 90;
|
|
80312
|
-
function resolveSyncWindow(explicitSince, deepSyncedAt) {
|
|
80313
|
-
if (explicitSince !== void 0) {
|
|
80314
|
-
const days = Number(explicitSince);
|
|
80315
|
-
if (!Number.isFinite(days) || days <= 0) {
|
|
80316
|
-
throw new ExpectedCliError(`--since must be a positive number of days, got "${explicitSince}"`);
|
|
80317
|
-
}
|
|
80318
|
-
return { days, deepSweep: false };
|
|
80319
|
-
}
|
|
80320
|
-
if (deepSyncedAt === void 0) return { days: DEEP_FIRST_SYNC_DAYS, deepSweep: true };
|
|
80321
|
-
return { days: STEADY_SYNC_WINDOW_DAYS, deepSweep: false };
|
|
80322
|
-
}
|
|
80323
|
-
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
80324
|
-
function resolveScanFloor(window2, nowMs, narrowSinceMs) {
|
|
80325
|
-
if (window2.deepSweep || narrowSinceMs === void 0) return nowMs - window2.days * DAY_MS;
|
|
80326
|
-
return narrowSinceMs;
|
|
80327
|
-
}
|
|
80328
|
-
function rawShipFloorMs(appEnv, nowMs, explicitSince) {
|
|
80329
|
-
if (appEnv !== "development" || explicitSince !== void 0) return null;
|
|
80330
|
-
return nowMs - STEADY_SYNC_WINDOW_DAYS * DAY_MS;
|
|
80331
|
-
}
|
|
80332
|
-
function describeScanReach(window2, narrowSinceMs) {
|
|
80333
|
-
if (window2.deepSweep || narrowSinceMs === void 0) {
|
|
80334
|
-
return `from the last ${window2.days} day(s)`;
|
|
80335
|
-
}
|
|
80336
|
-
return `changed since ${new Date(narrowSinceMs).toISOString()}`;
|
|
80337
|
-
}
|
|
80338
|
-
|
|
80339
80448
|
// ../../apps/collector/src/protectedRepoDiscovery.ts
|
|
80340
80449
|
var defaultDiscoveryDeps = {
|
|
80341
80450
|
collectClaude: collectClaudeCodeSessions,
|
|
@@ -80512,7 +80621,7 @@ function installCollectorHooks(homeDir = os11.homedir()) {
|
|
|
80512
80621
|
}
|
|
80513
80622
|
|
|
80514
80623
|
// ../../apps/collector/src/service.ts
|
|
80515
|
-
import { execFileSync as
|
|
80624
|
+
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
80516
80625
|
import { chmodSync as chmodSync2, existsSync as existsSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync7, rmSync, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
80517
80626
|
import os12 from "node:os";
|
|
80518
80627
|
import path10 from "node:path";
|
|
@@ -80660,7 +80769,7 @@ function restartService(config2) {
|
|
|
80660
80769
|
}
|
|
80661
80770
|
function runLaunchctl(args) {
|
|
80662
80771
|
try {
|
|
80663
|
-
|
|
80772
|
+
execFileSync3("launchctl", args, { stdio: ["ignore", "ignore", "pipe"], encoding: "utf8" });
|
|
80664
80773
|
} catch (cause) {
|
|
80665
80774
|
throw new Error(launchctlFailureMessage(args[0] ?? "", cause), { cause });
|
|
80666
80775
|
}
|
|
@@ -80675,7 +80784,7 @@ function launchctlFailureMessage(subcommand, cause) {
|
|
|
80675
80784
|
}
|
|
80676
80785
|
function isLoaded(appEnv) {
|
|
80677
80786
|
try {
|
|
80678
|
-
|
|
80787
|
+
execFileSync3("launchctl", ["print", `gui/${uid()}/${label(appEnv)}`], { stdio: "ignore" });
|
|
80679
80788
|
return true;
|
|
80680
80789
|
} catch {
|
|
80681
80790
|
return false;
|
|
@@ -80683,7 +80792,7 @@ function isLoaded(appEnv) {
|
|
|
80683
80792
|
}
|
|
80684
80793
|
function bootout(appEnv) {
|
|
80685
80794
|
try {
|
|
80686
|
-
|
|
80795
|
+
execFileSync3("launchctl", ["bootout", `gui/${uid()}/${label(appEnv)}`], { stdio: "ignore" });
|
|
80687
80796
|
return true;
|
|
80688
80797
|
} catch {
|
|
80689
80798
|
return false;
|
|
@@ -81014,7 +81123,7 @@ async function resolveCapturePolicy(config2, credentials, log3, deps = defaultPo
|
|
|
81014
81123
|
}
|
|
81015
81124
|
if (repos !== null && repos.length === 0) {
|
|
81016
81125
|
log3(
|
|
81017
|
-
"\u26A0 The org's
|
|
81126
|
+
"\u26A0 The org's repo allowlist is empty \u2014 no repo-based uploads" + (memberFolders.length > 0 ? "; only folders you added upload." : ".")
|
|
81018
81127
|
);
|
|
81019
81128
|
} else if (repos === null && owners.length === 0 && !ownersUnresolved) {
|
|
81020
81129
|
log3(
|
|
@@ -81041,26 +81150,31 @@ async function runSyncPass(config2, options = {}) {
|
|
|
81041
81150
|
const window2 = resolveSyncWindow(options.explicitSince, credentials.deepSyncedAt);
|
|
81042
81151
|
if (window2.deepSweep) {
|
|
81043
81152
|
log3(
|
|
81044
|
-
`First sync for this enrollment \u2014 sweeping the last ${window2.days} days to
|
|
81153
|
+
`First sync for this enrollment \u2014 sweeping the last ${window2.days} days and backfilling up to the ${DEEP_FIRST_SYNC_MAX_SESSIONS} most recently active sessions already on this machine (later syncs cover ${STEADY_SYNC_WINDOW_DAYS} days).`
|
|
81045
81154
|
);
|
|
81046
81155
|
}
|
|
81047
81156
|
const capture = await resolveCapturePolicy(config2, credentials, log3);
|
|
81048
81157
|
const sinceMs = resolveScanFloor(window2, Date.now(), options.narrowSinceMs);
|
|
81158
|
+
const maxSessions = window2.deepSweep ? DEEP_FIRST_SYNC_MAX_SESSIONS : void 0;
|
|
81049
81159
|
const claude = await collectClaudeCodeSessions({ sinceMs, capture });
|
|
81050
|
-
const codex = await collectCodexSessions({ sinceMs, capture });
|
|
81160
|
+
const codex = await collectCodexSessions({ sinceMs, capture, maxSessions });
|
|
81051
81161
|
const cursor = await collectCursorSessions({ sinceMs, capture });
|
|
81052
81162
|
if (cursor.unavailable !== null) {
|
|
81053
81163
|
log3(`\u26A0 Cursor sessions skipped this pass \u2014 ${cursor.unavailable}. Other syncing is unaffected.`);
|
|
81054
81164
|
}
|
|
81055
|
-
const
|
|
81165
|
+
const inWindow = [...claude.sessions, ...codex.sessions, ...cursor.sessions].sort(
|
|
81056
81166
|
(a, b2) => b2.mtimeMs - a.mtimeMs
|
|
81057
81167
|
);
|
|
81168
|
+
const collected = maxSessions === void 0 ? inWindow : inWindow.slice(0, maxSessions);
|
|
81169
|
+
const heldBack = inWindow.length - collected.length + codex.heldBack;
|
|
81058
81170
|
const skippedOutOfScope = claude.skippedOutOfScope + codex.skippedOutOfScope + cursor.skippedOutOfScope;
|
|
81171
|
+
const skippedNoRepo = claude.skippedNoRepo + codex.skippedNoRepo + cursor.skippedNoRepo;
|
|
81059
81172
|
const items = collected.map((c) => c.item);
|
|
81060
81173
|
const active = items.filter((s) => s.status === "active").length;
|
|
81061
81174
|
log3(
|
|
81062
|
-
`Found ${
|
|
81175
|
+
`Found ${inWindow.length} local session(s) (${claude.sessions.length} claude, ${codex.sessions.length} codex, ${cursor.sessions.length} cursor) ` + describeScanReach(window2, options.narrowSinceMs) + (active > 0 ? ` (${active} still active)` : "") + (skippedOutOfScope > 0 ? ` \xB7 ${skippedOutOfScope} ${describeSkipReason(capture)}` : "") + (skippedNoRepo > 0 ? ` \xB7 ${skippedNoRepo} ${describeNoRepoSkipReason(capture)}` : "") + (codex.skippedSubagentThreads > 0 ? ` \xB7 ${codex.skippedSubagentThreads} codex subagent thread(s) skipped (spend unmeasured)` : "") + (cursor.skippedSubagentComposers > 0 ? ` \xB7 ${cursor.skippedSubagentComposers} cursor subagent thread(s) skipped` : "") + (cursor.skippedNonLocalComposers > 0 ? ` \xB7 ${cursor.skippedNonLocalComposers} cursor session(s) skipped (not local to this machine)` : "") + (cursor.skippedUnreadable > 0 ? ` \xB7 ${cursor.skippedUnreadable} cursor session(s) unreadable, skipped` : "") + (codex.skippedTooLarge > 0 ? ` \xB7 ${codex.skippedTooLarge} codex rollout(s) skipped (over ${MAX_TRANSCRIPT_FILE_BYTES / (1024 * 1024)}MB \u2014 too large to read)` : "") + (codex.unreadable.length > 0 ? ` \xB7 ${codex.unreadable.length} codex rollout(s) unreadable, skipped` : "") + (heldBack > 0 ? ` \xB7 ${heldBack} older session(s) held back \u2014 the first sync backfills the ${DEEP_FIRST_SYNC_MAX_SESSIONS} most recently active` : "") + "."
|
|
81063
81176
|
);
|
|
81177
|
+
for (const failure of codex.unreadable) log3(` codex rollout skipped \u2014 ${failure}`);
|
|
81064
81178
|
if (options.dryRun) {
|
|
81065
81179
|
for (const s of items.slice(0, 10)) {
|
|
81066
81180
|
log3(` ${s.externalId} ${s.model ?? "model unmeasured"} ${s.title ?? "(untitled)"}`);
|
|
@@ -81198,7 +81312,7 @@ import os14 from "node:os";
|
|
|
81198
81312
|
import path14 from "node:path";
|
|
81199
81313
|
|
|
81200
81314
|
// ../../apps/collector/src/wake.ts
|
|
81201
|
-
import { execFile as execFile2, execFileSync as
|
|
81315
|
+
import { execFile as execFile2, execFileSync as execFileSync4 } from "node:child_process";
|
|
81202
81316
|
import { existsSync as existsSync3 } from "node:fs";
|
|
81203
81317
|
import path13 from "node:path";
|
|
81204
81318
|
var WAKE_POLL_MS = 5e3;
|
|
@@ -81300,7 +81414,7 @@ function resolveClaudeBin(homeDir, env = process.env) {
|
|
|
81300
81414
|
const found = candidates.find((candidate) => existsSync3(candidate));
|
|
81301
81415
|
if (found) return found;
|
|
81302
81416
|
try {
|
|
81303
|
-
const fromPath =
|
|
81417
|
+
const fromPath = execFileSync4("which", ["claude"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
81304
81418
|
return fromPath === "" ? null : fromPath;
|
|
81305
81419
|
} catch {
|
|
81306
81420
|
return null;
|
|
@@ -81322,7 +81436,7 @@ function versionAtLeast(version2, floor) {
|
|
|
81322
81436
|
return true;
|
|
81323
81437
|
}
|
|
81324
81438
|
function execClaudeVersion(claudeBin) {
|
|
81325
|
-
return
|
|
81439
|
+
return execFileSync4(claudeBin, ["--version"], {
|
|
81326
81440
|
stdio: ["ignore", "pipe", "ignore"],
|
|
81327
81441
|
timeout: VERSION_TIMEOUT_MS
|
|
81328
81442
|
}).toString();
|
|
@@ -81896,7 +82010,7 @@ function describeError3(error52) {
|
|
|
81896
82010
|
}
|
|
81897
82011
|
|
|
81898
82012
|
// src/connect.ts
|
|
81899
|
-
import { execFileSync as
|
|
82013
|
+
import { execFileSync as execFileSync5, spawnSync } from "node:child_process";
|
|
81900
82014
|
import {
|
|
81901
82015
|
existsSync as existsSync5,
|
|
81902
82016
|
mkdirSync as mkdirSync6,
|
|
@@ -82122,7 +82236,7 @@ function desktopClaudeBinaries(homeDir) {
|
|
|
82122
82236
|
}
|
|
82123
82237
|
function defaultWhichAll(name) {
|
|
82124
82238
|
try {
|
|
82125
|
-
return
|
|
82239
|
+
return execFileSync5("which", ["-a", name], { encoding: "utf8" }).split("\n").map((line) => line.trim()).filter(Boolean);
|
|
82126
82240
|
} catch {
|
|
82127
82241
|
return [];
|
|
82128
82242
|
}
|
|
@@ -82915,7 +83029,7 @@ function realRunInteractive(bin, args, env) {
|
|
|
82915
83029
|
}
|
|
82916
83030
|
|
|
82917
83031
|
// src/connections.ts
|
|
82918
|
-
import { execFileSync as
|
|
83032
|
+
import { execFileSync as execFileSync6, spawnSync as spawnSync2 } from "node:child_process";
|
|
82919
83033
|
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync7 } from "node:fs";
|
|
82920
83034
|
import path16 from "node:path";
|
|
82921
83035
|
function probeConnections(clients, deps) {
|
|
@@ -83118,7 +83232,7 @@ function runWithPath(pathValue, budget = UNLIMITED_TIME_BUDGET) {
|
|
|
83118
83232
|
function whichAllWith(pathValue) {
|
|
83119
83233
|
return (name) => {
|
|
83120
83234
|
try {
|
|
83121
|
-
return
|
|
83235
|
+
return execFileSync6("which", ["-a", name], {
|
|
83122
83236
|
encoding: "utf8",
|
|
83123
83237
|
env: { ...process.env, PATH: pathValue }
|
|
83124
83238
|
}).split("\n").map((line) => line.trim()).filter(Boolean);
|
|
@@ -83136,7 +83250,7 @@ function renderStatus(i) {
|
|
|
83136
83250
|
const lines = [];
|
|
83137
83251
|
lines.push(`Environment: ${i.config.appEnv} (API ${i.config.apiUrl})`);
|
|
83138
83252
|
lines.push(
|
|
83139
|
-
`CLI: powerplant ${i.cliVersion}` + (i.latestVersion !== null && i.latestVersion !== i.cliVersion ? ` \u2014 ${i.latestVersion} is available:
|
|
83253
|
+
`CLI: powerplant ${i.cliVersion}` + (i.latestVersion !== null && i.latestVersion !== i.cliVersion ? ` \u2014 ${i.latestVersion} is available: powerplant update` : "")
|
|
83140
83254
|
);
|
|
83141
83255
|
const unsupported = unsupportedVersionNotice(i.cliVersion, i.oldestSupportedVersion);
|
|
83142
83256
|
if (unsupported !== null) lines.push(unsupported);
|
|
@@ -83607,7 +83721,7 @@ async function realPromptLine(question) {
|
|
|
83607
83721
|
}
|
|
83608
83722
|
|
|
83609
83723
|
// src/memberSessions.ts
|
|
83610
|
-
import { execFileSync as
|
|
83724
|
+
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
83611
83725
|
import { existsSync as existsSync6 } from "node:fs";
|
|
83612
83726
|
import os16 from "node:os";
|
|
83613
83727
|
import path17 from "node:path";
|
|
@@ -83682,7 +83796,7 @@ function detectCodexDesktop(probe = { exists: existsSync6, readUrlSchemes: realR
|
|
|
83682
83796
|
function realReadUrlSchemes(bundlePath) {
|
|
83683
83797
|
if (process.platform !== "darwin") return [];
|
|
83684
83798
|
try {
|
|
83685
|
-
const json2 =
|
|
83799
|
+
const json2 = execFileSync7(
|
|
83686
83800
|
"plutil",
|
|
83687
83801
|
["-extract", "CFBundleURLTypes", "json", "-o", "-", path17.join(bundlePath, "Contents", "Info.plist")],
|
|
83688
83802
|
{ stdio: ["ignore", "pipe", "ignore"] }
|
|
@@ -84139,8 +84253,38 @@ function createTerminalOutput(options) {
|
|
|
84139
84253
|
return { log: log3, activity };
|
|
84140
84254
|
}
|
|
84141
84255
|
|
|
84256
|
+
// src/update.ts
|
|
84257
|
+
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
84258
|
+
var npmLsSchema = external_exports.object({
|
|
84259
|
+
dependencies: external_exports.record(external_exports.string(), external_exports.object({ version: external_exports.string().min(1) })).optional()
|
|
84260
|
+
});
|
|
84261
|
+
function runCapturing(command, args) {
|
|
84262
|
+
const result = spawnSync4(command, args, {
|
|
84263
|
+
encoding: "utf8",
|
|
84264
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
84265
|
+
});
|
|
84266
|
+
return { stdout: result.stdout ?? "" };
|
|
84267
|
+
}
|
|
84268
|
+
function installedGlobalVersion(packageName, run = runCapturing) {
|
|
84269
|
+
const { stdout } = run("npm", ["ls", "-g", packageName, "--json"]);
|
|
84270
|
+
try {
|
|
84271
|
+
const parsed = npmLsSchema.safeParse(JSON.parse(stdout));
|
|
84272
|
+
return parsed.success ? parsed.data.dependencies?.[packageName]?.version ?? null : null;
|
|
84273
|
+
} catch {
|
|
84274
|
+
return null;
|
|
84275
|
+
}
|
|
84276
|
+
}
|
|
84277
|
+
var RESTART_NOTE = "Sync service will restart within minutes. (You can do this now with powerplant restart.)";
|
|
84278
|
+
function updatedMessage(version2) {
|
|
84279
|
+
if (version2 === null) {
|
|
84280
|
+
return `Updated, but could not read the installed version from npm. Check with: powerplant status
|
|
84281
|
+
${RESTART_NOTE}`;
|
|
84282
|
+
}
|
|
84283
|
+
return `Updated to v${version2}. ${RESTART_NOTE}`;
|
|
84284
|
+
}
|
|
84285
|
+
|
|
84142
84286
|
// src/version.ts
|
|
84143
|
-
var CLI_VERSION = true ? "0.3.
|
|
84287
|
+
var CLI_VERSION = true ? "0.3.2" : "0.0.0-checkout";
|
|
84144
84288
|
var CLI_PACKAGE_NAME = "@usepowerplant/cli";
|
|
84145
84289
|
|
|
84146
84290
|
// src/workspace.ts
|
|
@@ -84261,7 +84405,7 @@ Commands:
|
|
|
84261
84405
|
sync Run one sync pass in the foreground [--since <days>] [--dry-run].
|
|
84262
84406
|
folders The folders you explicitly sync on this machine:
|
|
84263
84407
|
powerplant folders [add <path> | remove <path>]. Additions on
|
|
84264
|
-
top of your org's
|
|
84408
|
+
top of your org's allowlisted repos \u2014 no re-enroll needed.
|
|
84265
84409
|
workspace Your workspaces, and which one Powerplant and your connected
|
|
84266
84410
|
agents use: powerplant workspace [<name>] switches to <name>.
|
|
84267
84411
|
resume-session Reopen a synced session in its own CLI, right here in
|
|
@@ -84573,7 +84717,7 @@ The access you granted these agents stays on your Powerplant account until you r
|
|
|
84573
84717
|
}
|
|
84574
84718
|
case "update": {
|
|
84575
84719
|
console.log(`Updating ${CLI_PACKAGE_NAME} via npm\u2026`);
|
|
84576
|
-
const npm =
|
|
84720
|
+
const npm = spawnSync5("npm", ["install", "-g", CLI_PACKAGE_NAME], { stdio: "inherit" });
|
|
84577
84721
|
if (npm.error) {
|
|
84578
84722
|
throw new ExpectedCliError(
|
|
84579
84723
|
`Could not run npm (${npm.error.message}) \u2014 update by hand: npm install -g ${CLI_PACKAGE_NAME}`
|
|
@@ -84582,9 +84726,7 @@ The access you granted these agents stays on your Powerplant account until you r
|
|
|
84582
84726
|
if (npm.status !== 0) {
|
|
84583
84727
|
throw new ExpectedCliError("npm install failed \u2014 see the output above.");
|
|
84584
84728
|
}
|
|
84585
|
-
console.log(
|
|
84586
|
-
"Updated. The background service restarts itself onto the new version within minutes (or now: powerplant restart)."
|
|
84587
|
-
);
|
|
84729
|
+
console.log(updatedMessage(installedGlobalVersion(CLI_PACKAGE_NAME)));
|
|
84588
84730
|
return;
|
|
84589
84731
|
}
|
|
84590
84732
|
case "restart": {
|