@usepowerplant/cli 0.4.0 → 0.4.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 +571 -820
- package/package.json +1 -1
- package/dist/hooks/powerplant-inbox.mjs +0 -147
package/dist/cli.js
CHANGED
|
@@ -6877,19 +6877,19 @@ var require_module_details_from_path = __commonJS({
|
|
|
6877
6877
|
basedir += segments[i] + sep2;
|
|
6878
6878
|
}
|
|
6879
6879
|
}
|
|
6880
|
-
var
|
|
6880
|
+
var path18 = "";
|
|
6881
6881
|
var lastSegmentIndex = segments.length - 1;
|
|
6882
6882
|
for (var i2 = index + offset; i2 <= lastSegmentIndex; i2++) {
|
|
6883
6883
|
if (i2 === lastSegmentIndex) {
|
|
6884
|
-
|
|
6884
|
+
path18 += segments[i2];
|
|
6885
6885
|
} else {
|
|
6886
|
-
|
|
6886
|
+
path18 += segments[i2] + sep2;
|
|
6887
6887
|
}
|
|
6888
6888
|
}
|
|
6889
6889
|
return {
|
|
6890
6890
|
name,
|
|
6891
6891
|
basedir,
|
|
6892
|
-
path:
|
|
6892
|
+
path: path18
|
|
6893
6893
|
};
|
|
6894
6894
|
};
|
|
6895
6895
|
}
|
|
@@ -6899,7 +6899,7 @@ var require_module_details_from_path = __commonJS({
|
|
|
6899
6899
|
var require_require_in_the_middle = __commonJS({
|
|
6900
6900
|
"../../node_modules/.pnpm/require-in-the-middle@8.0.1/node_modules/require-in-the-middle/index.js"(exports, module2) {
|
|
6901
6901
|
"use strict";
|
|
6902
|
-
var
|
|
6902
|
+
var path18 = __require("path");
|
|
6903
6903
|
var Module = __require("module");
|
|
6904
6904
|
var debug2 = require_src3()("require-in-the-middle");
|
|
6905
6905
|
var moduleDetailsFromPath = require_module_details_from_path();
|
|
@@ -7044,7 +7044,7 @@ var require_require_in_the_middle = __commonJS({
|
|
|
7044
7044
|
}
|
|
7045
7045
|
moduleName = filename;
|
|
7046
7046
|
} else if (hasWhitelist === true && modules.includes(filename)) {
|
|
7047
|
-
const parsedPath =
|
|
7047
|
+
const parsedPath = path18.parse(filename);
|
|
7048
7048
|
moduleName = parsedPath.name;
|
|
7049
7049
|
basedir = parsedPath.dir;
|
|
7050
7050
|
} else {
|
|
@@ -7082,7 +7082,7 @@ var require_require_in_the_middle = __commonJS({
|
|
|
7082
7082
|
}
|
|
7083
7083
|
if (res !== filename) {
|
|
7084
7084
|
if (internals === true) {
|
|
7085
|
-
moduleName = moduleName +
|
|
7085
|
+
moduleName = moduleName + path18.sep + path18.relative(basedir, filename);
|
|
7086
7086
|
debug2("preparing to process require of internal file: %s", moduleName);
|
|
7087
7087
|
} else {
|
|
7088
7088
|
debug2("ignoring require of non-main module file: %s", res);
|
|
@@ -7118,8 +7118,8 @@ var require_require_in_the_middle = __commonJS({
|
|
|
7118
7118
|
}
|
|
7119
7119
|
};
|
|
7120
7120
|
function resolveModuleName(stat) {
|
|
7121
|
-
const normalizedPath =
|
|
7122
|
-
return
|
|
7121
|
+
const normalizedPath = path18.sep !== "/" ? stat.path.split(path18.sep).join("/") : stat.path;
|
|
7122
|
+
return path18.posix.join(stat.name, normalizedPath).replace(normalize3, "");
|
|
7123
7123
|
}
|
|
7124
7124
|
}
|
|
7125
7125
|
});
|
|
@@ -7204,7 +7204,7 @@ var require_RequireInTheMiddleSingleton = __commonJS({
|
|
|
7204
7204
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7205
7205
|
exports.RequireInTheMiddleSingleton = void 0;
|
|
7206
7206
|
var require_in_the_middle_1 = require_require_in_the_middle();
|
|
7207
|
-
var
|
|
7207
|
+
var path18 = __require("path");
|
|
7208
7208
|
var ModuleNameTrie_1 = require_ModuleNameTrie();
|
|
7209
7209
|
var isMocha = [
|
|
7210
7210
|
"afterEach",
|
|
@@ -7268,7 +7268,7 @@ var require_RequireInTheMiddleSingleton = __commonJS({
|
|
|
7268
7268
|
};
|
|
7269
7269
|
exports.RequireInTheMiddleSingleton = RequireInTheMiddleSingleton;
|
|
7270
7270
|
function normalizePathSeparators(moduleNameOrPath) {
|
|
7271
|
-
return
|
|
7271
|
+
return path18.sep !== ModuleNameTrie_1.ModuleNameSeparator ? moduleNameOrPath.split(path18.sep).join(ModuleNameTrie_1.ModuleNameSeparator) : moduleNameOrPath;
|
|
7272
7272
|
}
|
|
7273
7273
|
}
|
|
7274
7274
|
});
|
|
@@ -7434,7 +7434,7 @@ var require_register = __commonJS({
|
|
|
7434
7434
|
// ../../node_modules/.pnpm/import-in-the-middle@3.3.3/node_modules/import-in-the-middle/index.js
|
|
7435
7435
|
var require_import_in_the_middle = __commonJS({
|
|
7436
7436
|
"../../node_modules/.pnpm/import-in-the-middle@3.3.3/node_modules/import-in-the-middle/index.js"(exports, module2) {
|
|
7437
|
-
var
|
|
7437
|
+
var path18 = __require("path");
|
|
7438
7438
|
var moduleDetailsFromPath = require_module_details_from_path();
|
|
7439
7439
|
var { fileURLToPath: fileURLToPath3 } = __require("url");
|
|
7440
7440
|
var { MessageChannel } = __require("worker_threads");
|
|
@@ -7553,7 +7553,7 @@ var require_import_in_the_middle = __commonJS({
|
|
|
7553
7553
|
} else if (baseDir.endsWith(specifiers.get(loadUrl)) || isTurbopackSpecifier(specifiers.get(loadUrl), baseDir)) {
|
|
7554
7554
|
callHookFn(hookFn, namespace, name, baseDir);
|
|
7555
7555
|
} else if (internals) {
|
|
7556
|
-
const internalPath = name +
|
|
7556
|
+
const internalPath = name + path18.sep + path18.relative(baseDir, filePath);
|
|
7557
7557
|
callHookFn(hookFn, namespace, internalPath, baseDir);
|
|
7558
7558
|
}
|
|
7559
7559
|
} else if (matchArg === specifier) {
|
|
@@ -7628,7 +7628,7 @@ var require_instrumentation2 = __commonJS({
|
|
|
7628
7628
|
"use strict";
|
|
7629
7629
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7630
7630
|
exports.InstrumentationBase = void 0;
|
|
7631
|
-
var
|
|
7631
|
+
var path18 = __require("path");
|
|
7632
7632
|
var util_1 = __require("util");
|
|
7633
7633
|
var semver_1 = require_semver();
|
|
7634
7634
|
var shimmer_1 = require_shimmer();
|
|
@@ -7729,7 +7729,7 @@ var require_instrumentation2 = __commonJS({
|
|
|
7729
7729
|
}
|
|
7730
7730
|
_extractPackageVersion(baseDir) {
|
|
7731
7731
|
try {
|
|
7732
|
-
const json2 = (0, fs_1.readFileSync)(
|
|
7732
|
+
const json2 = (0, fs_1.readFileSync)(path18.join(baseDir, "package.json"), {
|
|
7733
7733
|
encoding: "utf8"
|
|
7734
7734
|
});
|
|
7735
7735
|
const version2 = JSON.parse(json2).version;
|
|
@@ -7771,7 +7771,7 @@ var require_instrumentation2 = __commonJS({
|
|
|
7771
7771
|
return exports2;
|
|
7772
7772
|
}
|
|
7773
7773
|
const files = module3.files ?? [];
|
|
7774
|
-
const normalizedName =
|
|
7774
|
+
const normalizedName = path18.normalize(name);
|
|
7775
7775
|
const supportedFileInstrumentations = files.filter((f) => f.name === normalizedName && isSupported(f.supportedVersions, version2, module3.includePrerelease));
|
|
7776
7776
|
return supportedFileInstrumentations.reduce((patchedExports, file2) => {
|
|
7777
7777
|
file2.moduleExports = patchedExports;
|
|
@@ -7817,8 +7817,8 @@ var require_instrumentation2 = __commonJS({
|
|
|
7817
7817
|
this._warnOnPreloadedModules();
|
|
7818
7818
|
for (const module3 of this._modules) {
|
|
7819
7819
|
const hookFn = (exports2, name, baseDir) => {
|
|
7820
|
-
if (!baseDir &&
|
|
7821
|
-
const parsedPath =
|
|
7820
|
+
if (!baseDir && path18.isAbsolute(name)) {
|
|
7821
|
+
const parsedPath = path18.parse(name);
|
|
7822
7822
|
name = parsedPath.name;
|
|
7823
7823
|
baseDir = parsedPath.dir;
|
|
7824
7824
|
}
|
|
@@ -7827,7 +7827,7 @@ var require_instrumentation2 = __commonJS({
|
|
|
7827
7827
|
const onRequire = (exports2, name, baseDir) => {
|
|
7828
7828
|
return this._onRequire(module3, exports2, name, baseDir);
|
|
7829
7829
|
};
|
|
7830
|
-
const hook =
|
|
7830
|
+
const hook = path18.isAbsolute(module3.name) ? new require_in_the_middle_1.Hook([module3.name], { internals: true }, onRequire) : this._requireInTheMiddleSingleton.register(module3.name, onRequire);
|
|
7831
7831
|
this._hooks.push(hook);
|
|
7832
7832
|
const esmHook = new import_in_the_middle_1.Hook([module3.name], { internals: true }, hookFn);
|
|
7833
7833
|
this._hooks.push(esmHook);
|
|
@@ -8435,9 +8435,9 @@ var require_getMachineId_linux = __commonJS({
|
|
|
8435
8435
|
var api_1 = (init_esm(), __toCommonJS(esm_exports));
|
|
8436
8436
|
async function getMachineId() {
|
|
8437
8437
|
const paths = ["/etc/machine-id", "/var/lib/dbus/machine-id"];
|
|
8438
|
-
for (const
|
|
8438
|
+
for (const path18 of paths) {
|
|
8439
8439
|
try {
|
|
8440
|
-
const result = await fs_1.promises.readFile(
|
|
8440
|
+
const result = await fs_1.promises.readFile(path18, { encoding: "utf8" });
|
|
8441
8441
|
return result.trim();
|
|
8442
8442
|
} catch (e) {
|
|
8443
8443
|
api_1.diag.debug(`error reading machine id: ${e}`);
|
|
@@ -11792,14 +11792,14 @@ var require_util = __commonJS({
|
|
|
11792
11792
|
}
|
|
11793
11793
|
const port = url2.port != null ? url2.port : url2.protocol === "https:" ? 443 : 80;
|
|
11794
11794
|
let origin = url2.origin != null ? url2.origin : `${url2.protocol || ""}//${url2.hostname || ""}:${port}`;
|
|
11795
|
-
let
|
|
11795
|
+
let path18 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`;
|
|
11796
11796
|
if (origin[origin.length - 1] === "/") {
|
|
11797
11797
|
origin = origin.slice(0, origin.length - 1);
|
|
11798
11798
|
}
|
|
11799
|
-
if (
|
|
11800
|
-
|
|
11799
|
+
if (path18 && path18[0] !== "/") {
|
|
11800
|
+
path18 = `/${path18}`;
|
|
11801
11801
|
}
|
|
11802
|
-
return new URL(`${origin}${
|
|
11802
|
+
return new URL(`${origin}${path18}`);
|
|
11803
11803
|
}
|
|
11804
11804
|
if (!isHttpOrHttpsPrefixed(url2.origin || url2.protocol)) {
|
|
11805
11805
|
throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
|
|
@@ -12620,9 +12620,9 @@ var require_diagnostics = __commonJS({
|
|
|
12620
12620
|
"undici:client:sendHeaders",
|
|
12621
12621
|
(evt) => {
|
|
12622
12622
|
const {
|
|
12623
|
-
request: { method, path:
|
|
12623
|
+
request: { method, path: path18, origin }
|
|
12624
12624
|
} = evt;
|
|
12625
|
-
debugLog3("sending request to %s %s%s", method, origin,
|
|
12625
|
+
debugLog3("sending request to %s %s%s", method, origin, path18);
|
|
12626
12626
|
}
|
|
12627
12627
|
);
|
|
12628
12628
|
}
|
|
@@ -12640,14 +12640,14 @@ var require_diagnostics = __commonJS({
|
|
|
12640
12640
|
"undici:request:headers",
|
|
12641
12641
|
(evt) => {
|
|
12642
12642
|
const {
|
|
12643
|
-
request: { method, path:
|
|
12643
|
+
request: { method, path: path18, origin },
|
|
12644
12644
|
response: { statusCode }
|
|
12645
12645
|
} = evt;
|
|
12646
12646
|
debugLog3(
|
|
12647
12647
|
"received response to %s %s%s - HTTP %d",
|
|
12648
12648
|
method,
|
|
12649
12649
|
origin,
|
|
12650
|
-
|
|
12650
|
+
path18,
|
|
12651
12651
|
statusCode
|
|
12652
12652
|
);
|
|
12653
12653
|
}
|
|
@@ -12656,23 +12656,23 @@ var require_diagnostics = __commonJS({
|
|
|
12656
12656
|
"undici:request:trailers",
|
|
12657
12657
|
(evt) => {
|
|
12658
12658
|
const {
|
|
12659
|
-
request: { method, path:
|
|
12659
|
+
request: { method, path: path18, origin }
|
|
12660
12660
|
} = evt;
|
|
12661
|
-
debugLog3("trailers received from %s %s%s", method, origin,
|
|
12661
|
+
debugLog3("trailers received from %s %s%s", method, origin, path18);
|
|
12662
12662
|
}
|
|
12663
12663
|
);
|
|
12664
12664
|
diagnosticsChannel9.subscribe(
|
|
12665
12665
|
"undici:request:error",
|
|
12666
12666
|
(evt) => {
|
|
12667
12667
|
const {
|
|
12668
|
-
request: { method, path:
|
|
12668
|
+
request: { method, path: path18, origin },
|
|
12669
12669
|
error: error52
|
|
12670
12670
|
} = evt;
|
|
12671
12671
|
debugLog3(
|
|
12672
12672
|
"request to %s %s%s errored - %s",
|
|
12673
12673
|
method,
|
|
12674
12674
|
origin,
|
|
12675
|
-
|
|
12675
|
+
path18,
|
|
12676
12676
|
error52.message
|
|
12677
12677
|
);
|
|
12678
12678
|
}
|
|
@@ -12787,7 +12787,7 @@ var require_request = __commonJS({
|
|
|
12787
12787
|
var kHandler = /* @__PURE__ */ Symbol("handler");
|
|
12788
12788
|
var Request2 = class {
|
|
12789
12789
|
constructor(origin, {
|
|
12790
|
-
path:
|
|
12790
|
+
path: path18,
|
|
12791
12791
|
method,
|
|
12792
12792
|
body,
|
|
12793
12793
|
headers,
|
|
@@ -12804,11 +12804,11 @@ var require_request = __commonJS({
|
|
|
12804
12804
|
maxRedirections,
|
|
12805
12805
|
typeOfService
|
|
12806
12806
|
}, handler) {
|
|
12807
|
-
if (typeof
|
|
12807
|
+
if (typeof path18 !== "string") {
|
|
12808
12808
|
throw new InvalidArgumentError("path must be a string");
|
|
12809
|
-
} else if (
|
|
12809
|
+
} else if (path18[0] !== "/" && !(path18.startsWith("http://") || path18.startsWith("https://")) && method !== "CONNECT") {
|
|
12810
12810
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
12811
|
-
} else if (invalidPathRegex.test(
|
|
12811
|
+
} else if (invalidPathRegex.test(path18)) {
|
|
12812
12812
|
throw new InvalidArgumentError("invalid request path");
|
|
12813
12813
|
}
|
|
12814
12814
|
if (typeof method !== "string") {
|
|
@@ -12883,7 +12883,7 @@ var require_request = __commonJS({
|
|
|
12883
12883
|
this.completed = false;
|
|
12884
12884
|
this.aborted = false;
|
|
12885
12885
|
this.upgrade = upgrade || null;
|
|
12886
|
-
this.path = query ? serializePathWithQuery(
|
|
12886
|
+
this.path = query ? serializePathWithQuery(path18, query) : path18;
|
|
12887
12887
|
this.origin = origin;
|
|
12888
12888
|
this.protocol = getProtocolFromUrlString(origin);
|
|
12889
12889
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
|
|
@@ -18066,7 +18066,7 @@ var require_client_h1 = __commonJS({
|
|
|
18066
18066
|
return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
|
|
18067
18067
|
}
|
|
18068
18068
|
function writeH1(client, request2) {
|
|
18069
|
-
const { method, path:
|
|
18069
|
+
const { method, path: path18, host, upgrade, blocking, reset } = request2;
|
|
18070
18070
|
let { body, headers, contentLength } = request2;
|
|
18071
18071
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
|
|
18072
18072
|
if (util2.isFormDataLike(body)) {
|
|
@@ -18144,7 +18144,7 @@ var require_client_h1 = __commonJS({
|
|
|
18144
18144
|
if (socket.setTypeOfService) {
|
|
18145
18145
|
socket.setTypeOfService(request2.typeOfService);
|
|
18146
18146
|
}
|
|
18147
|
-
let header = `${method} ${
|
|
18147
|
+
let header = `${method} ${path18} HTTP/1.1\r
|
|
18148
18148
|
`;
|
|
18149
18149
|
if (typeof host === "string") {
|
|
18150
18150
|
header += `host: ${host}\r
|
|
@@ -18797,7 +18797,7 @@ var require_client_h2 = __commonJS({
|
|
|
18797
18797
|
function writeH2(client, request2) {
|
|
18798
18798
|
const requestTimeout = request2.bodyTimeout ?? client[kBodyTimeout];
|
|
18799
18799
|
const session = client[kHTTP2Session];
|
|
18800
|
-
const { method, path:
|
|
18800
|
+
const { method, path: path18, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
|
|
18801
18801
|
let { body } = request2;
|
|
18802
18802
|
if (upgrade != null && upgrade !== "websocket") {
|
|
18803
18803
|
util2.errorRequest(client, request2, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
|
|
@@ -18865,7 +18865,7 @@ var require_client_h2 = __commonJS({
|
|
|
18865
18865
|
}
|
|
18866
18866
|
headers[HTTP2_HEADER_METHOD] = "CONNECT";
|
|
18867
18867
|
headers[HTTP2_HEADER_PROTOCOL] = "websocket";
|
|
18868
|
-
headers[HTTP2_HEADER_PATH] =
|
|
18868
|
+
headers[HTTP2_HEADER_PATH] = path18;
|
|
18869
18869
|
if (protocol === "ws:" || protocol === "wss:") {
|
|
18870
18870
|
headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
|
|
18871
18871
|
} else {
|
|
@@ -18906,7 +18906,7 @@ var require_client_h2 = __commonJS({
|
|
|
18906
18906
|
stream.setTimeout(requestTimeout);
|
|
18907
18907
|
return true;
|
|
18908
18908
|
}
|
|
18909
|
-
headers[HTTP2_HEADER_PATH] =
|
|
18909
|
+
headers[HTTP2_HEADER_PATH] = path18;
|
|
18910
18910
|
headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
|
|
18911
18911
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
18912
18912
|
if (body && typeof body.read === "function") {
|
|
@@ -21249,10 +21249,10 @@ var require_proxy_agent = __commonJS({
|
|
|
21249
21249
|
};
|
|
21250
21250
|
const {
|
|
21251
21251
|
origin,
|
|
21252
|
-
path:
|
|
21252
|
+
path: path18 = "/",
|
|
21253
21253
|
headers = {}
|
|
21254
21254
|
} = opts;
|
|
21255
|
-
opts.path = origin +
|
|
21255
|
+
opts.path = origin + path18;
|
|
21256
21256
|
if (!("host" in headers) && !("Host" in headers)) {
|
|
21257
21257
|
const { host } = new URL(origin);
|
|
21258
21258
|
headers.host = host;
|
|
@@ -23335,20 +23335,20 @@ var require_mock_utils = __commonJS({
|
|
|
23335
23335
|
}
|
|
23336
23336
|
return normalizedQp;
|
|
23337
23337
|
}
|
|
23338
|
-
function safeUrl(
|
|
23339
|
-
if (typeof
|
|
23340
|
-
return
|
|
23338
|
+
function safeUrl(path18) {
|
|
23339
|
+
if (typeof path18 !== "string") {
|
|
23340
|
+
return path18;
|
|
23341
23341
|
}
|
|
23342
|
-
const pathSegments =
|
|
23342
|
+
const pathSegments = path18.split("?", 3);
|
|
23343
23343
|
if (pathSegments.length !== 2) {
|
|
23344
|
-
return
|
|
23344
|
+
return path18;
|
|
23345
23345
|
}
|
|
23346
23346
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
23347
23347
|
qp.sort();
|
|
23348
23348
|
return [...pathSegments, qp.toString()].join("?");
|
|
23349
23349
|
}
|
|
23350
|
-
function matchKey(mockDispatch2, { path:
|
|
23351
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
23350
|
+
function matchKey(mockDispatch2, { path: path18, method, body, headers }) {
|
|
23351
|
+
const pathMatch = matchValue(mockDispatch2.path, path18);
|
|
23352
23352
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
23353
23353
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
23354
23354
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -23373,8 +23373,8 @@ var require_mock_utils = __commonJS({
|
|
|
23373
23373
|
const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path;
|
|
23374
23374
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
23375
23375
|
const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
|
|
23376
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
23377
|
-
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(
|
|
23376
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path18, ignoreTrailingSlash }) => {
|
|
23377
|
+
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path18)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path18), resolvedPath);
|
|
23378
23378
|
});
|
|
23379
23379
|
if (matchedMockDispatches.length === 0) {
|
|
23380
23380
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
@@ -23413,19 +23413,19 @@ var require_mock_utils = __commonJS({
|
|
|
23413
23413
|
mockDispatches.splice(index, 1);
|
|
23414
23414
|
}
|
|
23415
23415
|
}
|
|
23416
|
-
function removeTrailingSlash(
|
|
23417
|
-
while (
|
|
23418
|
-
|
|
23416
|
+
function removeTrailingSlash(path18) {
|
|
23417
|
+
while (path18.endsWith("/")) {
|
|
23418
|
+
path18 = path18.slice(0, -1);
|
|
23419
23419
|
}
|
|
23420
|
-
if (
|
|
23421
|
-
|
|
23420
|
+
if (path18.length === 0) {
|
|
23421
|
+
path18 = "/";
|
|
23422
23422
|
}
|
|
23423
|
-
return
|
|
23423
|
+
return path18;
|
|
23424
23424
|
}
|
|
23425
23425
|
function buildKey(opts) {
|
|
23426
|
-
const { path:
|
|
23426
|
+
const { path: path18, method, body, headers, query } = opts;
|
|
23427
23427
|
return {
|
|
23428
|
-
path:
|
|
23428
|
+
path: path18,
|
|
23429
23429
|
method,
|
|
23430
23430
|
body,
|
|
23431
23431
|
headers,
|
|
@@ -24115,10 +24115,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
24115
24115
|
}
|
|
24116
24116
|
format(pendingInterceptors) {
|
|
24117
24117
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
24118
|
-
({ method, path:
|
|
24118
|
+
({ method, path: path18, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
24119
24119
|
Method: method,
|
|
24120
24120
|
Origin: origin,
|
|
24121
|
-
Path:
|
|
24121
|
+
Path: path18,
|
|
24122
24122
|
"Status code": statusCode,
|
|
24123
24123
|
Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
|
|
24124
24124
|
Invocations: timesInvoked,
|
|
@@ -24200,9 +24200,9 @@ var require_mock_agent = __commonJS({
|
|
|
24200
24200
|
const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
|
|
24201
24201
|
const dispatchOpts = { ...opts };
|
|
24202
24202
|
if (acceptNonStandardSearchParameters && dispatchOpts.path) {
|
|
24203
|
-
const [
|
|
24203
|
+
const [path18, searchParams] = dispatchOpts.path.split("?");
|
|
24204
24204
|
const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
|
|
24205
|
-
dispatchOpts.path = `${
|
|
24205
|
+
dispatchOpts.path = `${path18}?${normalizedSearchParams}`;
|
|
24206
24206
|
}
|
|
24207
24207
|
return this[kAgent].dispatch(dispatchOpts, handler);
|
|
24208
24208
|
}
|
|
@@ -24603,12 +24603,12 @@ var require_snapshot_recorder = __commonJS({
|
|
|
24603
24603
|
* @return {Promise<void>} - Resolves when snapshots are loaded
|
|
24604
24604
|
*/
|
|
24605
24605
|
async loadSnapshots(filePath) {
|
|
24606
|
-
const
|
|
24607
|
-
if (!
|
|
24606
|
+
const path18 = filePath || this.#snapshotPath;
|
|
24607
|
+
if (!path18) {
|
|
24608
24608
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
24609
24609
|
}
|
|
24610
24610
|
try {
|
|
24611
|
-
const data = await readFile2(resolve2(
|
|
24611
|
+
const data = await readFile2(resolve2(path18), "utf8");
|
|
24612
24612
|
const parsed = JSON.parse(data);
|
|
24613
24613
|
if (Array.isArray(parsed)) {
|
|
24614
24614
|
this.#snapshots.clear();
|
|
@@ -24622,7 +24622,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
24622
24622
|
if (error52.code === "ENOENT") {
|
|
24623
24623
|
this.#snapshots.clear();
|
|
24624
24624
|
} else {
|
|
24625
|
-
throw new UndiciError(`Failed to load snapshots from ${
|
|
24625
|
+
throw new UndiciError(`Failed to load snapshots from ${path18}`, { cause: error52 });
|
|
24626
24626
|
}
|
|
24627
24627
|
}
|
|
24628
24628
|
}
|
|
@@ -24633,11 +24633,11 @@ var require_snapshot_recorder = __commonJS({
|
|
|
24633
24633
|
* @returns {Promise<void>} - Resolves when snapshots are saved
|
|
24634
24634
|
*/
|
|
24635
24635
|
async saveSnapshots(filePath) {
|
|
24636
|
-
const
|
|
24637
|
-
if (!
|
|
24636
|
+
const path18 = filePath || this.#snapshotPath;
|
|
24637
|
+
if (!path18) {
|
|
24638
24638
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
24639
24639
|
}
|
|
24640
|
-
const resolvedPath = resolve2(
|
|
24640
|
+
const resolvedPath = resolve2(path18);
|
|
24641
24641
|
await mkdir(dirname2(resolvedPath), { recursive: true });
|
|
24642
24642
|
const data = Array.from(this.#snapshots.entries()).map(([hash2, snapshot]) => ({
|
|
24643
24643
|
hash: hash2,
|
|
@@ -25269,15 +25269,15 @@ var require_redirect_handler = __commonJS({
|
|
|
25269
25269
|
return;
|
|
25270
25270
|
}
|
|
25271
25271
|
const { origin, pathname, search } = util2.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
25272
|
-
const
|
|
25273
|
-
const redirectUrlString = `${origin}${
|
|
25272
|
+
const path18 = search ? `${pathname}${search}` : pathname;
|
|
25273
|
+
const redirectUrlString = `${origin}${path18}`;
|
|
25274
25274
|
for (const historyUrl of this.history) {
|
|
25275
25275
|
if (historyUrl.toString() === redirectUrlString) {
|
|
25276
25276
|
throw new InvalidArgumentError(`Redirect loop detected. Cannot redirect to ${origin}. This typically happens when using a Client or Pool with cross-origin redirects. Use an Agent for cross-origin redirects.`);
|
|
25277
25277
|
}
|
|
25278
25278
|
}
|
|
25279
25279
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
|
|
25280
|
-
this.opts.path =
|
|
25280
|
+
this.opts.path = path18;
|
|
25281
25281
|
this.opts.origin = origin;
|
|
25282
25282
|
this.opts.query = null;
|
|
25283
25283
|
}
|
|
@@ -27046,10 +27046,10 @@ var require_cache_handler = __commonJS({
|
|
|
27046
27046
|
}
|
|
27047
27047
|
return locationUrl.pathname + locationUrl.search;
|
|
27048
27048
|
}
|
|
27049
|
-
function deleteCachedUri(store, cacheKey,
|
|
27049
|
+
function deleteCachedUri(store, cacheKey, path18) {
|
|
27050
27050
|
deleteCachedValue(store, {
|
|
27051
27051
|
...cacheKey,
|
|
27052
|
-
path:
|
|
27052
|
+
path: path18
|
|
27053
27053
|
});
|
|
27054
27054
|
for (let i = 0; i < util2.safeHTTPMethods.length; i++) {
|
|
27055
27055
|
const method = util2.safeHTTPMethods[i];
|
|
@@ -27057,7 +27057,7 @@ var require_cache_handler = __commonJS({
|
|
|
27057
27057
|
deleteCachedValue(store, {
|
|
27058
27058
|
...cacheKey,
|
|
27059
27059
|
method,
|
|
27060
|
-
path:
|
|
27060
|
+
path: path18
|
|
27061
27061
|
});
|
|
27062
27062
|
}
|
|
27063
27063
|
}
|
|
@@ -27068,9 +27068,9 @@ var require_cache_handler = __commonJS({
|
|
|
27068
27068
|
}
|
|
27069
27069
|
const values = Array.isArray(headerValue) ? headerValue : [headerValue];
|
|
27070
27070
|
for (let i = 0; i < values.length; i++) {
|
|
27071
|
-
const
|
|
27072
|
-
if (
|
|
27073
|
-
deleteCachedUri(store, cacheKey,
|
|
27071
|
+
const path18 = getSameOriginPath(cacheKey, values[i]);
|
|
27072
|
+
if (path18 !== void 0) {
|
|
27073
|
+
deleteCachedUri(store, cacheKey, path18);
|
|
27074
27074
|
}
|
|
27075
27075
|
}
|
|
27076
27076
|
}
|
|
@@ -31948,11 +31948,11 @@ var require_fetch = __commonJS({
|
|
|
31948
31948
|
function dispatch({ body }) {
|
|
31949
31949
|
const url2 = requestCurrentURL(request2);
|
|
31950
31950
|
const agent = fetchParams.controller.dispatcher;
|
|
31951
|
-
const
|
|
31951
|
+
const path18 = url2.pathname + url2.search;
|
|
31952
31952
|
const hasTrailingQuestionMark = url2.search.length === 0 && url2.href[url2.href.length - url2.hash.length - 1] === "?";
|
|
31953
31953
|
return new Promise((resolve2, reject) => agent.dispatch(
|
|
31954
31954
|
{
|
|
31955
|
-
path: hasTrailingQuestionMark ? `${
|
|
31955
|
+
path: hasTrailingQuestionMark ? `${path18}?` : path18,
|
|
31956
31956
|
origin: url2.origin,
|
|
31957
31957
|
method: request2.method,
|
|
31958
31958
|
body: agent.isMockActive ? request2.body && (request2.body.source || request2.body.stream) : body,
|
|
@@ -32899,9 +32899,9 @@ var require_util4 = __commonJS({
|
|
|
32899
32899
|
}
|
|
32900
32900
|
}
|
|
32901
32901
|
}
|
|
32902
|
-
function validateCookiePath(
|
|
32903
|
-
for (let i = 0; i <
|
|
32904
|
-
const code =
|
|
32902
|
+
function validateCookiePath(path18) {
|
|
32903
|
+
for (let i = 0; i < path18.length; ++i) {
|
|
32904
|
+
const code = path18.charCodeAt(i);
|
|
32905
32905
|
if (code < 32 || // exclude CTLs (0-31)
|
|
32906
32906
|
code > 126 || // exclude DEL and non-ascii
|
|
32907
32907
|
code === 59) {
|
|
@@ -36138,11 +36138,11 @@ var require_undici = __commonJS({
|
|
|
36138
36138
|
if (typeof opts.path !== "string") {
|
|
36139
36139
|
throw new InvalidArgumentError("invalid opts.path");
|
|
36140
36140
|
}
|
|
36141
|
-
let
|
|
36141
|
+
let path18 = opts.path;
|
|
36142
36142
|
if (!opts.path.startsWith("/")) {
|
|
36143
|
-
|
|
36143
|
+
path18 = `/${path18}`;
|
|
36144
36144
|
}
|
|
36145
|
-
url2 = new URL(util2.parseOrigin(url2).origin +
|
|
36145
|
+
url2 = new URL(util2.parseOrigin(url2).origin + path18);
|
|
36146
36146
|
} else {
|
|
36147
36147
|
if (!opts) {
|
|
36148
36148
|
opts = typeof url2 === "object" ? url2 : {};
|
|
@@ -36253,7 +36253,7 @@ ${captureLines}` : capture.stack;
|
|
|
36253
36253
|
|
|
36254
36254
|
// src/cli.ts
|
|
36255
36255
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
36256
|
-
import { existsSync as
|
|
36256
|
+
import { existsSync as existsSync6, realpathSync as realpathSync2 } from "node:fs";
|
|
36257
36257
|
import { parseArgs } from "node:util";
|
|
36258
36258
|
|
|
36259
36259
|
// ../../apps/collector/src/credentials.ts
|
|
@@ -37028,10 +37028,10 @@ function mergeDefs(...defs) {
|
|
|
37028
37028
|
function cloneDef(schema) {
|
|
37029
37029
|
return mergeDefs(schema._zod.def);
|
|
37030
37030
|
}
|
|
37031
|
-
function getElementAtPath(obj,
|
|
37032
|
-
if (!
|
|
37031
|
+
function getElementAtPath(obj, path18) {
|
|
37032
|
+
if (!path18)
|
|
37033
37033
|
return obj;
|
|
37034
|
-
return
|
|
37034
|
+
return path18.reduce((acc, key) => acc?.[key], obj);
|
|
37035
37035
|
}
|
|
37036
37036
|
function promiseAllObject(promisesObj) {
|
|
37037
37037
|
const keys = Object.keys(promisesObj);
|
|
@@ -37440,11 +37440,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
37440
37440
|
}
|
|
37441
37441
|
return false;
|
|
37442
37442
|
}
|
|
37443
|
-
function prefixIssues(
|
|
37443
|
+
function prefixIssues(path18, issues) {
|
|
37444
37444
|
return issues.map((iss) => {
|
|
37445
37445
|
var _a4;
|
|
37446
37446
|
(_a4 = iss).path ?? (_a4.path = []);
|
|
37447
|
-
iss.path.unshift(
|
|
37447
|
+
iss.path.unshift(path18);
|
|
37448
37448
|
return iss;
|
|
37449
37449
|
});
|
|
37450
37450
|
}
|
|
@@ -37591,16 +37591,16 @@ function flattenError(error52, mapper = (issue2) => issue2.message) {
|
|
|
37591
37591
|
}
|
|
37592
37592
|
function formatError(error52, mapper = (issue2) => issue2.message) {
|
|
37593
37593
|
const fieldErrors = { _errors: [] };
|
|
37594
|
-
const processError = (error53,
|
|
37594
|
+
const processError = (error53, path18 = []) => {
|
|
37595
37595
|
for (const issue2 of error53.issues) {
|
|
37596
37596
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
37597
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
37597
|
+
issue2.errors.map((issues) => processError({ issues }, [...path18, ...issue2.path]));
|
|
37598
37598
|
} else if (issue2.code === "invalid_key") {
|
|
37599
|
-
processError({ issues: issue2.issues }, [...
|
|
37599
|
+
processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
|
|
37600
37600
|
} else if (issue2.code === "invalid_element") {
|
|
37601
|
-
processError({ issues: issue2.issues }, [...
|
|
37601
|
+
processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
|
|
37602
37602
|
} else {
|
|
37603
|
-
const fullpath = [...
|
|
37603
|
+
const fullpath = [...path18, ...issue2.path];
|
|
37604
37604
|
if (fullpath.length === 0) {
|
|
37605
37605
|
fieldErrors._errors.push(mapper(issue2));
|
|
37606
37606
|
} else {
|
|
@@ -37627,17 +37627,17 @@ function formatError(error52, mapper = (issue2) => issue2.message) {
|
|
|
37627
37627
|
}
|
|
37628
37628
|
function treeifyError(error52, mapper = (issue2) => issue2.message) {
|
|
37629
37629
|
const result = { errors: [] };
|
|
37630
|
-
const processError = (error53,
|
|
37630
|
+
const processError = (error53, path18 = []) => {
|
|
37631
37631
|
var _a4, _b;
|
|
37632
37632
|
for (const issue2 of error53.issues) {
|
|
37633
37633
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
37634
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
37634
|
+
issue2.errors.map((issues) => processError({ issues }, [...path18, ...issue2.path]));
|
|
37635
37635
|
} else if (issue2.code === "invalid_key") {
|
|
37636
|
-
processError({ issues: issue2.issues }, [...
|
|
37636
|
+
processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
|
|
37637
37637
|
} else if (issue2.code === "invalid_element") {
|
|
37638
|
-
processError({ issues: issue2.issues }, [...
|
|
37638
|
+
processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
|
|
37639
37639
|
} else {
|
|
37640
|
-
const fullpath = [...
|
|
37640
|
+
const fullpath = [...path18, ...issue2.path];
|
|
37641
37641
|
if (fullpath.length === 0) {
|
|
37642
37642
|
result.errors.push(mapper(issue2));
|
|
37643
37643
|
continue;
|
|
@@ -37669,8 +37669,8 @@ function treeifyError(error52, mapper = (issue2) => issue2.message) {
|
|
|
37669
37669
|
}
|
|
37670
37670
|
function toDotPath(_path) {
|
|
37671
37671
|
const segs = [];
|
|
37672
|
-
const
|
|
37673
|
-
for (const seg of
|
|
37672
|
+
const path18 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
37673
|
+
for (const seg of path18) {
|
|
37674
37674
|
if (typeof seg === "number")
|
|
37675
37675
|
segs.push(`[${seg}]`);
|
|
37676
37676
|
else if (typeof seg === "symbol")
|
|
@@ -50362,13 +50362,13 @@ function resolveRef(ref, ctx) {
|
|
|
50362
50362
|
if (!ref.startsWith("#")) {
|
|
50363
50363
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
50364
50364
|
}
|
|
50365
|
-
const
|
|
50366
|
-
if (
|
|
50365
|
+
const path18 = ref.slice(1).split("/").filter(Boolean);
|
|
50366
|
+
if (path18.length === 0) {
|
|
50367
50367
|
return ctx.rootSchema;
|
|
50368
50368
|
}
|
|
50369
50369
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
50370
|
-
if (
|
|
50371
|
-
const key =
|
|
50370
|
+
if (path18[0] === defsKey) {
|
|
50371
|
+
const key = path18[1];
|
|
50372
50372
|
if (!key || !ctx.defs[key]) {
|
|
50373
50373
|
throw new Error(`Reference not found: ${ref}`);
|
|
50374
50374
|
}
|
|
@@ -51409,8 +51409,8 @@ function primaryArg(args) {
|
|
|
51409
51409
|
function readFilePath(name, primary) {
|
|
51410
51410
|
if (!primary || !READ_TOOLS.has(name)) return null;
|
|
51411
51411
|
if (ARTIFACT_PATH_RE.test(primary)) return null;
|
|
51412
|
-
const
|
|
51413
|
-
return
|
|
51412
|
+
const path18 = primary.startsWith("/workspace/") ? primary.slice("/workspace/".length) : primary;
|
|
51413
|
+
return path18.length > 0 ? path18 : null;
|
|
51414
51414
|
}
|
|
51415
51415
|
function asRecord3(value) {
|
|
51416
51416
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -51919,8 +51919,8 @@ function getFunctionName(fn) {
|
|
|
51919
51919
|
return defaultFunctionName;
|
|
51920
51920
|
}
|
|
51921
51921
|
}
|
|
51922
|
-
function normalizeStackTracePath(
|
|
51923
|
-
let filename =
|
|
51922
|
+
function normalizeStackTracePath(path18) {
|
|
51923
|
+
let filename = path18?.startsWith("file://") ? path18.slice(7) : path18;
|
|
51924
51924
|
if (filename?.match(/\/[A-Z]:/)) {
|
|
51925
51925
|
filename = filename.slice(1);
|
|
51926
51926
|
}
|
|
@@ -53730,8 +53730,8 @@ function isValidProtocol(protocol) {
|
|
|
53730
53730
|
return protocol === "http" || protocol === "https";
|
|
53731
53731
|
}
|
|
53732
53732
|
function dsnToString(dsn, withPassword = false) {
|
|
53733
|
-
const { host, path:
|
|
53734
|
-
return `${protocol}://${publicKey}${withPassword && pass ? `:${pass}` : ""}@${host}${port ? `:${port}` : ""}/${
|
|
53733
|
+
const { host, path: path18, pass, port, projectId, protocol, publicKey } = dsn;
|
|
53734
|
+
return `${protocol}://${publicKey}${withPassword && pass ? `:${pass}` : ""}@${host}${port ? `:${port}` : ""}/${path18 ? `${path18}/` : path18}${projectId}`;
|
|
53735
53735
|
}
|
|
53736
53736
|
function dsnFromString(str) {
|
|
53737
53737
|
const match = DSN_REGEX.exec(str);
|
|
@@ -53742,11 +53742,11 @@ function dsnFromString(str) {
|
|
|
53742
53742
|
return void 0;
|
|
53743
53743
|
}
|
|
53744
53744
|
const [protocol, publicKey, pass = "", host = "", port = "", lastPath = ""] = match.slice(1);
|
|
53745
|
-
let
|
|
53745
|
+
let path18 = "";
|
|
53746
53746
|
let projectId = lastPath;
|
|
53747
53747
|
const split = projectId.split("/");
|
|
53748
53748
|
if (split.length > 1) {
|
|
53749
|
-
|
|
53749
|
+
path18 = split.slice(0, -1).join("/");
|
|
53750
53750
|
projectId = split.pop();
|
|
53751
53751
|
}
|
|
53752
53752
|
if (projectId) {
|
|
@@ -53755,7 +53755,7 @@ function dsnFromString(str) {
|
|
|
53755
53755
|
projectId = projectMatch[0];
|
|
53756
53756
|
}
|
|
53757
53757
|
}
|
|
53758
|
-
return dsnFromComponents({ host, pass, path:
|
|
53758
|
+
return dsnFromComponents({ host, pass, path: path18, projectId, port, protocol, publicKey });
|
|
53759
53759
|
}
|
|
53760
53760
|
function dsnFromComponents(components) {
|
|
53761
53761
|
return {
|
|
@@ -58289,9 +58289,9 @@ function stripUrlQueryAndFragment(urlPath) {
|
|
|
58289
58289
|
return urlPath.split(/[?#]/, 1)[0];
|
|
58290
58290
|
}
|
|
58291
58291
|
function getSanitizedUrlString(url2) {
|
|
58292
|
-
const { protocol, host, path:
|
|
58292
|
+
const { protocol, host, path: path18 } = url2;
|
|
58293
58293
|
const filteredHost = host?.replace(/^.*@/, "[filtered]:[filtered]@").replace(/(:80)$/, "").replace(/(:443)$/, "") || "";
|
|
58294
|
-
return `${protocol ? `${protocol}://` : ""}${filteredHost}${
|
|
58294
|
+
return `${protocol ? `${protocol}://` : ""}${filteredHost}${path18}`;
|
|
58295
58295
|
}
|
|
58296
58296
|
function stripDataUrlContent(url2, includeDataPrefix = true) {
|
|
58297
58297
|
if (url2.startsWith("data:")) {
|
|
@@ -59234,8 +59234,8 @@ function splitPath(filename) {
|
|
|
59234
59234
|
const parts = splitPathRe.exec(truncated);
|
|
59235
59235
|
return parts ? parts.slice(1) : [];
|
|
59236
59236
|
}
|
|
59237
|
-
function dirname(
|
|
59238
|
-
const result = splitPath(
|
|
59237
|
+
function dirname(path18) {
|
|
59238
|
+
const result = splitPath(path18);
|
|
59239
59239
|
const root = result[0] || "";
|
|
59240
59240
|
let dir = result[1];
|
|
59241
59241
|
if (!root && !dir) {
|
|
@@ -63161,15 +63161,15 @@ var getLayerMetadata = (route, layer, layerPath) => {
|
|
|
63161
63161
|
};
|
|
63162
63162
|
}
|
|
63163
63163
|
};
|
|
63164
|
-
var getRouterPath = (
|
|
63164
|
+
var getRouterPath = (path18, layer) => {
|
|
63165
63165
|
const stackLayer = Array.isArray(layer.handle?.stack) ? layer.handle?.stack?.[0] : void 0;
|
|
63166
63166
|
if (stackLayer?.route?.path) {
|
|
63167
|
-
return `${
|
|
63167
|
+
return `${path18}${stackLayer.route.path}`;
|
|
63168
63168
|
}
|
|
63169
63169
|
if (stackLayer && Array.isArray(stackLayer?.handle?.stack)) {
|
|
63170
|
-
return getRouterPath(
|
|
63170
|
+
return getRouterPath(path18, stackLayer);
|
|
63171
63171
|
}
|
|
63172
|
-
return
|
|
63172
|
+
return path18;
|
|
63173
63173
|
};
|
|
63174
63174
|
var isLayerIgnored = (name, type, config2) => {
|
|
63175
63175
|
if (Array.isArray(config2?.ignoreLayersType) && config2?.ignoreLayersType?.includes(type)) {
|
|
@@ -63189,7 +63189,7 @@ function getActualMatchedRoute(req, constructedRoute) {
|
|
|
63189
63189
|
if (layersStore.length === 0) {
|
|
63190
63190
|
return void 0;
|
|
63191
63191
|
}
|
|
63192
|
-
if (layersStore.every((
|
|
63192
|
+
if (layersStore.every((path18) => path18 === "/")) {
|
|
63193
63193
|
return req.originalUrl === "/" ? "/" : void 0;
|
|
63194
63194
|
}
|
|
63195
63195
|
if (constructedRoute === "*") {
|
|
@@ -63205,11 +63205,11 @@ function getActualMatchedRoute(req, constructedRoute) {
|
|
|
63205
63205
|
function getConstructedRoute(req) {
|
|
63206
63206
|
const layersStore = getStoredLayers(req);
|
|
63207
63207
|
let constructedRoute = "";
|
|
63208
|
-
for (const
|
|
63209
|
-
if (
|
|
63208
|
+
for (const path18 of layersStore) {
|
|
63209
|
+
if (path18 === "/" || path18 === "/*") {
|
|
63210
63210
|
continue;
|
|
63211
63211
|
}
|
|
63212
|
-
constructedRoute += !constructedRoute || constructedRoute.endsWith("/") ?
|
|
63212
|
+
constructedRoute += !constructedRoute || constructedRoute.endsWith("/") ? path18 : `/${path18}`;
|
|
63213
63213
|
}
|
|
63214
63214
|
return constructedRoute.replace(/\/{2,}/g, "/");
|
|
63215
63215
|
}
|
|
@@ -63714,9 +63714,9 @@ function getRequestUrlObject(requestOptions) {
|
|
|
63714
63714
|
const hostHeader = requestOptions.headers?.host && String(requestOptions.headers?.host);
|
|
63715
63715
|
const hostname4 = hostHeader || requestOptions.hostname || requestOptions.host || "";
|
|
63716
63716
|
const port = !requestOptions.port || requestOptions.port === 80 || requestOptions.port === 443 || /^(.*):(\d+)$/.test(hostname4) ? "" : `:${requestOptions.port}`;
|
|
63717
|
-
const
|
|
63717
|
+
const path18 = requestOptions.path ? requestOptions.path : "/";
|
|
63718
63718
|
const base = `${protocol}//${hostname4}${port}`;
|
|
63719
|
-
return new URL(
|
|
63719
|
+
return new URL(path18.startsWith("//") ? `${base}${path18}` : path18, base);
|
|
63720
63720
|
}
|
|
63721
63721
|
function getRequestUrlFromClientRequest(request2) {
|
|
63722
63722
|
return String(getRequestUrl(getRequestOptions(request2)));
|
|
@@ -64389,11 +64389,11 @@ function shouldIgnoreSpansForIncomingRequest(request2, {
|
|
|
64389
64389
|
return false;
|
|
64390
64390
|
}
|
|
64391
64391
|
function isStaticAssetRequest(urlPath) {
|
|
64392
|
-
const
|
|
64393
|
-
if (
|
|
64392
|
+
const path18 = stripUrlQueryAndFragment(urlPath);
|
|
64393
|
+
if (path18.match(/\.(ico|png|jpg|jpeg|gif|svg|css|js|woff|woff2|ttf|eot|webp|avif)$/)) {
|
|
64394
64394
|
return true;
|
|
64395
64395
|
}
|
|
64396
|
-
if (
|
|
64396
|
+
if (path18.match(/^\/(robots\.txt|sitemap\.xml|manifest\.json|browserconfig\.xml)$/)) {
|
|
64397
64397
|
return true;
|
|
64398
64398
|
}
|
|
64399
64399
|
return false;
|
|
@@ -64634,11 +64634,11 @@ function isKnownPrefetchRequest2(req) {
|
|
|
64634
64634
|
return req.headers["next-router-prefetch"] === "1";
|
|
64635
64635
|
}
|
|
64636
64636
|
function isStaticAssetRequest2(urlPath) {
|
|
64637
|
-
const
|
|
64638
|
-
if (
|
|
64637
|
+
const path18 = stripUrlQueryAndFragment(urlPath);
|
|
64638
|
+
if (path18.match(/\.(ico|png|jpg|jpeg|gif|svg|css|js|woff|woff2|ttf|eot|webp|avif)$/)) {
|
|
64639
64639
|
return true;
|
|
64640
64640
|
}
|
|
64641
|
-
if (
|
|
64641
|
+
if (path18.match(/^\/(robots\.txt|sitemap\.xml|manifest\.json|browserconfig\.xml)$/)) {
|
|
64642
64642
|
return true;
|
|
64643
64643
|
}
|
|
64644
64644
|
return false;
|
|
@@ -64998,19 +64998,19 @@ function getBreadcrumbData(request2) {
|
|
|
64998
64998
|
return {};
|
|
64999
64999
|
}
|
|
65000
65000
|
}
|
|
65001
|
-
function getAbsoluteUrl2(origin,
|
|
65001
|
+
function getAbsoluteUrl2(origin, path18 = "/") {
|
|
65002
65002
|
try {
|
|
65003
|
-
const url2 = new URL(
|
|
65003
|
+
const url2 = new URL(path18, origin);
|
|
65004
65004
|
return url2.toString();
|
|
65005
65005
|
} catch {
|
|
65006
65006
|
const url2 = `${origin}`;
|
|
65007
|
-
if (url2.endsWith("/") &&
|
|
65008
|
-
return `${url2}${
|
|
65007
|
+
if (url2.endsWith("/") && path18.startsWith("/")) {
|
|
65008
|
+
return `${url2}${path18.slice(1)}`;
|
|
65009
65009
|
}
|
|
65010
|
-
if (!url2.endsWith("/") && !
|
|
65011
|
-
return `${url2}/${
|
|
65010
|
+
if (!url2.endsWith("/") && !path18.startsWith("/")) {
|
|
65011
|
+
return `${url2}/${path18}`;
|
|
65012
65012
|
}
|
|
65013
|
-
return `${url2}${
|
|
65013
|
+
return `${url2}${path18}`;
|
|
65014
65014
|
}
|
|
65015
65015
|
}
|
|
65016
65016
|
|
|
@@ -65255,15 +65255,15 @@ function getRequestMethod(original) {
|
|
|
65255
65255
|
}
|
|
65256
65256
|
return "_OTHER";
|
|
65257
65257
|
}
|
|
65258
|
-
function getAbsoluteUrl3(origin,
|
|
65258
|
+
function getAbsoluteUrl3(origin, path18 = "/") {
|
|
65259
65259
|
const url2 = `${origin}`;
|
|
65260
|
-
if (url2.endsWith("/") &&
|
|
65261
|
-
return `${url2}${
|
|
65260
|
+
if (url2.endsWith("/") && path18.startsWith("/")) {
|
|
65261
|
+
return `${url2}${path18.slice(1)}`;
|
|
65262
65262
|
}
|
|
65263
|
-
if (!url2.endsWith("/") && !
|
|
65264
|
-
return `${url2}/${
|
|
65263
|
+
if (!url2.endsWith("/") && !path18.startsWith("/")) {
|
|
65264
|
+
return `${url2}/${path18}`;
|
|
65265
65265
|
}
|
|
65266
|
-
return `${url2}${
|
|
65266
|
+
return `${url2}${path18}`;
|
|
65267
65267
|
}
|
|
65268
65268
|
|
|
65269
65269
|
// ../../node_modules/.pnpm/@sentry+node-core@10.71.0_@opentelemetry+api@1.9.1_@opentelemetry+core@2.10.0_@opentele_e57ddc8c682f93a270df4265a143e64e/node_modules/@sentry/node-core/build/esm/integrations/node-fetch/index.js
|
|
@@ -67749,12 +67749,12 @@ function emplace(map2, key, contents) {
|
|
|
67749
67749
|
}
|
|
67750
67750
|
return value;
|
|
67751
67751
|
}
|
|
67752
|
-
function shouldSkipContextLinesForFile(
|
|
67753
|
-
if (
|
|
67754
|
-
if (
|
|
67755
|
-
if (
|
|
67756
|
-
if (
|
|
67757
|
-
if (
|
|
67752
|
+
function shouldSkipContextLinesForFile(path18) {
|
|
67753
|
+
if (path18.startsWith("node:")) return true;
|
|
67754
|
+
if (path18.endsWith(".min.js")) return true;
|
|
67755
|
+
if (path18.endsWith(".min.cjs")) return true;
|
|
67756
|
+
if (path18.endsWith(".min.mjs")) return true;
|
|
67757
|
+
if (path18.startsWith("data:")) return true;
|
|
67758
67758
|
return false;
|
|
67759
67759
|
}
|
|
67760
67760
|
function shouldSkipContextLinesForFrame(frame) {
|
|
@@ -67802,9 +67802,9 @@ function makeLineReaderRanges(lines, linecontext) {
|
|
|
67802
67802
|
}
|
|
67803
67803
|
return out;
|
|
67804
67804
|
}
|
|
67805
|
-
function getContextLinesFromFile(
|
|
67805
|
+
function getContextLinesFromFile(path18, ranges, output) {
|
|
67806
67806
|
return new Promise((resolve2, _reject) => {
|
|
67807
|
-
const stream = createReadStream(
|
|
67807
|
+
const stream = createReadStream(path18);
|
|
67808
67808
|
const lineReaded = createInterface({
|
|
67809
67809
|
input: stream
|
|
67810
67810
|
});
|
|
@@ -67822,8 +67822,8 @@ function getContextLinesFromFile(path19, ranges, output) {
|
|
|
67822
67822
|
let rangeStart = range[0];
|
|
67823
67823
|
let rangeEnd = range[1];
|
|
67824
67824
|
function onStreamError(e) {
|
|
67825
|
-
LRU_FILE_CONTENTS_FS_READ_FAILED.set(
|
|
67826
|
-
DEBUG_BUILD2 && debug.error(`Failed to read file: ${
|
|
67825
|
+
LRU_FILE_CONTENTS_FS_READ_FAILED.set(path18, 1);
|
|
67826
|
+
DEBUG_BUILD2 && debug.error(`Failed to read file: ${path18}. Error: ${e}`);
|
|
67827
67827
|
lineReaded.close();
|
|
67828
67828
|
lineReaded.removeAllListeners();
|
|
67829
67829
|
destroyStreamAndResolve();
|
|
@@ -69262,8 +69262,8 @@ function getSpotlightConfig(optionsSpotlight) {
|
|
|
69262
69262
|
|
|
69263
69263
|
// ../../node_modules/.pnpm/@sentry+node-core@10.71.0_@opentelemetry+api@1.9.1_@opentelemetry+core@2.10.0_@opentele_e57ddc8c682f93a270df4265a143e64e/node_modules/@sentry/node-core/build/esm/utils/module.js
|
|
69264
69264
|
import { posix, sep } from "node:path";
|
|
69265
|
-
function normalizeWindowsPath(
|
|
69266
|
-
return
|
|
69265
|
+
function normalizeWindowsPath(path18) {
|
|
69266
|
+
return path18.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
|
|
69267
69267
|
}
|
|
69268
69268
|
function createGetModuleFromFilename(basePath = process.argv[1] ? dirname(process.argv[1]) : process.cwd(), isWindows = sep === "\\") {
|
|
69269
69269
|
const normalizedBase = isWindows ? normalizeWindowsPath(basePath) : basePath;
|
|
@@ -72135,22 +72135,22 @@ function addSpanSource(span, loc, start, end) {
|
|
|
72135
72135
|
span.setAttribute(AttributeNames2.SOURCE, source);
|
|
72136
72136
|
}
|
|
72137
72137
|
}
|
|
72138
|
-
function createFieldIfNotExists(contextValue, info,
|
|
72139
|
-
let field = getField(contextValue,
|
|
72138
|
+
function createFieldIfNotExists(contextValue, info, path18) {
|
|
72139
|
+
let field = getField(contextValue, path18);
|
|
72140
72140
|
if (field) {
|
|
72141
72141
|
return { field, spanAdded: false };
|
|
72142
72142
|
}
|
|
72143
|
-
const parentSpan = getParentFieldSpan(contextValue,
|
|
72143
|
+
const parentSpan = getParentFieldSpan(contextValue, path18);
|
|
72144
72144
|
field = {
|
|
72145
|
-
span: createResolverSpan(contextValue, info,
|
|
72145
|
+
span: createResolverSpan(contextValue, info, path18, parentSpan)
|
|
72146
72146
|
};
|
|
72147
|
-
addField(contextValue,
|
|
72147
|
+
addField(contextValue, path18, field);
|
|
72148
72148
|
return { field, spanAdded: true };
|
|
72149
72149
|
}
|
|
72150
|
-
function createResolverSpan(contextValue, info,
|
|
72150
|
+
function createResolverSpan(contextValue, info, path18, parentSpan) {
|
|
72151
72151
|
const attributes = {
|
|
72152
72152
|
[AttributeNames2.FIELD_NAME]: info.fieldName,
|
|
72153
|
-
[AttributeNames2.FIELD_PATH]:
|
|
72153
|
+
[AttributeNames2.FIELD_PATH]: path18.join("."),
|
|
72154
72154
|
[AttributeNames2.FIELD_TYPE]: info.returnType.toString(),
|
|
72155
72155
|
[AttributeNames2.PARENT_NAME]: info.parentType.name
|
|
72156
72156
|
};
|
|
@@ -72182,15 +72182,15 @@ function getOperation(document2, operationName) {
|
|
|
72182
72182
|
return document2.definitions.find((definition) => OPERATION_VALUES.indexOf(definition?.operation) !== -1);
|
|
72183
72183
|
}
|
|
72184
72184
|
}
|
|
72185
|
-
function addField(contextValue,
|
|
72186
|
-
return contextValue[OTEL_GRAPHQL_DATA_SYMBOL].fields[
|
|
72185
|
+
function addField(contextValue, path18, field) {
|
|
72186
|
+
return contextValue[OTEL_GRAPHQL_DATA_SYMBOL].fields[path18.join(".")] = field;
|
|
72187
72187
|
}
|
|
72188
|
-
function getField(contextValue,
|
|
72189
|
-
return contextValue[OTEL_GRAPHQL_DATA_SYMBOL].fields[
|
|
72188
|
+
function getField(contextValue, path18) {
|
|
72189
|
+
return contextValue[OTEL_GRAPHQL_DATA_SYMBOL].fields[path18.join(".")];
|
|
72190
72190
|
}
|
|
72191
|
-
function getParentFieldSpan(contextValue,
|
|
72192
|
-
for (let i =
|
|
72193
|
-
const field = getField(contextValue,
|
|
72191
|
+
function getParentFieldSpan(contextValue, path18) {
|
|
72192
|
+
for (let i = path18.length - 1; i > 0; i--) {
|
|
72193
|
+
const field = getField(contextValue, path18.slice(0, i));
|
|
72194
72194
|
if (field) {
|
|
72195
72195
|
return field.span;
|
|
72196
72196
|
}
|
|
@@ -72200,9 +72200,9 @@ function getParentFieldSpan(contextValue, path19) {
|
|
|
72200
72200
|
function getRootSpan2(contextValue) {
|
|
72201
72201
|
return contextValue[OTEL_GRAPHQL_DATA_SYMBOL].span;
|
|
72202
72202
|
}
|
|
72203
|
-
function pathToArray(
|
|
72203
|
+
function pathToArray(path18) {
|
|
72204
72204
|
const flattened = [];
|
|
72205
|
-
let curr =
|
|
72205
|
+
let curr = path18;
|
|
72206
72206
|
while (curr) {
|
|
72207
72207
|
flattened.push(String(curr.key));
|
|
72208
72208
|
curr = curr.prev;
|
|
@@ -72343,8 +72343,8 @@ function wrapFieldResolver(getConfig3, fieldResolver, isDefaultResolver = false)
|
|
|
72343
72343
|
if (!contextValue[OTEL_GRAPHQL_DATA_SYMBOL]) {
|
|
72344
72344
|
return fieldResolver.call(this, source, args, contextValue, info);
|
|
72345
72345
|
}
|
|
72346
|
-
const
|
|
72347
|
-
const { field, spanAdded } = createFieldIfNotExists(contextValue, info,
|
|
72346
|
+
const path18 = pathToArray(info?.path);
|
|
72347
|
+
const { field, spanAdded } = createFieldIfNotExists(contextValue, info, path18);
|
|
72348
72348
|
const span = field.span;
|
|
72349
72349
|
const shouldEndSpan = spanAdded;
|
|
72350
72350
|
return withActiveSpan(span, () => {
|
|
@@ -75327,10 +75327,10 @@ var PostgresJsInstrumentation = class extends import_instrumentation24.Instrumen
|
|
|
75327
75327
|
},
|
|
75328
75328
|
(exports) => exports
|
|
75329
75329
|
);
|
|
75330
|
-
["src", "cf/src", "cjs/src"].forEach((
|
|
75330
|
+
["src", "cf/src", "cjs/src"].forEach((path18) => {
|
|
75331
75331
|
module2.files.push(
|
|
75332
75332
|
new InstrumentationNodeModuleFile(
|
|
75333
|
-
`postgres/${
|
|
75333
|
+
`postgres/${path18}/query.js`,
|
|
75334
75334
|
SUPPORTED_VERSIONS4,
|
|
75335
75335
|
this._patchQueryPrototype.bind(this),
|
|
75336
75336
|
this._unpatchQueryPrototype.bind(this)
|
|
@@ -75961,13 +75961,13 @@ var HonoInstrumentation = class extends import_instrumentation27.Instrumentation
|
|
|
75961
75961
|
return function(original) {
|
|
75962
75962
|
return function wrappedHandler(...args) {
|
|
75963
75963
|
if (typeof args[0] === "string") {
|
|
75964
|
-
const
|
|
75964
|
+
const path18 = args[0];
|
|
75965
75965
|
if (args.length === 1) {
|
|
75966
|
-
return original.apply(this, [
|
|
75966
|
+
return original.apply(this, [path18]);
|
|
75967
75967
|
}
|
|
75968
75968
|
const handlers2 = args.slice(1);
|
|
75969
75969
|
return original.apply(this, [
|
|
75970
|
-
|
|
75970
|
+
path18,
|
|
75971
75971
|
...handlers2.map((handler) => instrumentation._wrapHandler(handler))
|
|
75972
75972
|
]);
|
|
75973
75973
|
}
|
|
@@ -76001,13 +76001,13 @@ var HonoInstrumentation = class extends import_instrumentation27.Instrumentation
|
|
|
76001
76001
|
return function(original) {
|
|
76002
76002
|
return function wrappedHandler(...args) {
|
|
76003
76003
|
if (typeof args[0] === "string") {
|
|
76004
|
-
const
|
|
76004
|
+
const path18 = args[0];
|
|
76005
76005
|
if (args.length === 1) {
|
|
76006
|
-
return original.apply(this, [
|
|
76006
|
+
return original.apply(this, [path18]);
|
|
76007
76007
|
}
|
|
76008
76008
|
const handlers2 = args.slice(1);
|
|
76009
76009
|
return original.apply(this, [
|
|
76010
|
-
|
|
76010
|
+
path18,
|
|
76011
76011
|
...handlers2.map((handler) => instrumentation._wrapHandler(handler))
|
|
76012
76012
|
]);
|
|
76013
76013
|
}
|
|
@@ -76027,8 +76027,8 @@ var HonoInstrumentation = class extends import_instrumentation27.Instrumentation
|
|
|
76027
76027
|
if (!instrumentation.isEnabled()) {
|
|
76028
76028
|
return handler.apply(this, [c, next]);
|
|
76029
76029
|
}
|
|
76030
|
-
const
|
|
76031
|
-
const span = instrumentation.tracer.startSpan(
|
|
76030
|
+
const path18 = c.req.path;
|
|
76031
|
+
const span = instrumentation.tracer.startSpan(path18);
|
|
76032
76032
|
return context.with(trace.setSpan(context.active(), span), () => {
|
|
76033
76033
|
return instrumentation._safeExecute(
|
|
76034
76034
|
() => {
|
|
@@ -76038,7 +76038,7 @@ var HonoInstrumentation = class extends import_instrumentation27.Instrumentation
|
|
|
76038
76038
|
const type = instrumentation._determineHandlerType(result2);
|
|
76039
76039
|
span.setAttributes({
|
|
76040
76040
|
[AttributeNames5.HONO_TYPE]: type,
|
|
76041
|
-
[AttributeNames5.HONO_NAME]: type === HonoTypes.REQUEST_HANDLER ?
|
|
76041
|
+
[AttributeNames5.HONO_NAME]: type === HonoTypes.REQUEST_HANDLER ? path18 : handler.name || "anonymous"
|
|
76042
76042
|
});
|
|
76043
76043
|
instrumentation.getConfig().responseHook?.(span);
|
|
76044
76044
|
return result2;
|
|
@@ -76047,7 +76047,7 @@ var HonoInstrumentation = class extends import_instrumentation27.Instrumentation
|
|
|
76047
76047
|
const type = instrumentation._determineHandlerType(result);
|
|
76048
76048
|
span.setAttributes({
|
|
76049
76049
|
[AttributeNames5.HONO_TYPE]: type,
|
|
76050
|
-
[AttributeNames5.HONO_NAME]: type === HonoTypes.REQUEST_HANDLER ?
|
|
76050
|
+
[AttributeNames5.HONO_NAME]: type === HonoTypes.REQUEST_HANDLER ? path18 : handler.name || "anonymous"
|
|
76051
76051
|
});
|
|
76052
76052
|
instrumentation.getConfig().responseHook?.(span);
|
|
76053
76053
|
return result;
|
|
@@ -76251,11 +76251,11 @@ var KoaInstrumentation = class extends import_instrumentation29.InstrumentationB
|
|
|
76251
76251
|
const router = dispatchLayer.router;
|
|
76252
76252
|
const routesStack = router?.stack ?? [];
|
|
76253
76253
|
for (const pathLayer of routesStack) {
|
|
76254
|
-
const
|
|
76254
|
+
const path18 = pathLayer.path;
|
|
76255
76255
|
const pathStack = pathLayer.stack;
|
|
76256
76256
|
for (let j = 0; j < pathStack.length; j++) {
|
|
76257
76257
|
const routedMiddleware = pathStack[j];
|
|
76258
|
-
pathStack[j] = this._patchLayer(routedMiddleware, true,
|
|
76258
|
+
pathStack[j] = this._patchLayer(routedMiddleware, true, path18);
|
|
76259
76259
|
}
|
|
76260
76260
|
}
|
|
76261
76261
|
return dispatchLayer;
|
|
@@ -78613,7 +78613,7 @@ function parseStoredCredentials(raw, appEnv) {
|
|
|
78613
78613
|
const parsed = storedCredentialsSchema.safeParse(json2);
|
|
78614
78614
|
if (!parsed.success) {
|
|
78615
78615
|
throw new InvalidStoredCredentialsError(
|
|
78616
|
-
`Stored sync service credentials for ${appEnv} are invalid (corrupted or from an incompatible version)
|
|
78616
|
+
`Stored sync service credentials for ${appEnv} are invalid (corrupted or from an incompatible version), re-enroll this machine (powerplant enroll, or pnpm collector enroll from the checkout)`
|
|
78617
78617
|
);
|
|
78618
78618
|
}
|
|
78619
78619
|
return parsed.data;
|
|
@@ -78675,14 +78675,14 @@ function fallbackFile(appEnv) {
|
|
|
78675
78675
|
|
|
78676
78676
|
// ../../apps/collector/src/enroll.ts
|
|
78677
78677
|
import { spawn } from "node:child_process";
|
|
78678
|
-
import { randomBytes } from "node:crypto";
|
|
78678
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
78679
78679
|
import http5 from "node:http";
|
|
78680
78680
|
import os6 from "node:os";
|
|
78681
78681
|
|
|
78682
78682
|
// ../../apps/collector/src/http.ts
|
|
78683
78683
|
var import_undici = __toESM(require_undici(), 1);
|
|
78684
78684
|
var CLI_VERSION_HEADER = "x-powerplant-cli-version";
|
|
78685
|
-
var cliVersion = true ? "0.4.
|
|
78685
|
+
var cliVersion = true ? "0.4.1" : "0.0.0-checkout";
|
|
78686
78686
|
function cliVersionHeaders() {
|
|
78687
78687
|
return { [CLI_VERSION_HEADER]: cliVersion, "user-agent": `powerplant-cli/${cliVersion}` };
|
|
78688
78688
|
}
|
|
@@ -78698,11 +78698,11 @@ function installHttp1Transport() {
|
|
|
78698
78698
|
}
|
|
78699
78699
|
async function fetchWithRetry(operation, url2, init3, options = {}) {
|
|
78700
78700
|
const settled = (status) => status < 500 || status === 503 && options.treat503AsFinal === true;
|
|
78701
|
-
const wrapped = (cause) => new Error(`${operation}: couldn't reach ${new URL(url2).host}
|
|
78701
|
+
const wrapped = (cause) => new Error(`${operation}: couldn't reach ${new URL(url2).host}, ${describeFetchFailure(cause)}`, {
|
|
78702
78702
|
cause
|
|
78703
78703
|
});
|
|
78704
78704
|
const request2 = withVersionHeader(init3);
|
|
78705
|
-
const delaysMs = [250, 1e3];
|
|
78705
|
+
const delaysMs = options.retry === false ? [] : [250, 1e3];
|
|
78706
78706
|
for (const delayMs of delaysMs) {
|
|
78707
78707
|
try {
|
|
78708
78708
|
const response = await fetch(url2, request2);
|
|
@@ -78970,7 +78970,7 @@ function describeCapturePolicy(policy) {
|
|
|
78970
78970
|
case "scope":
|
|
78971
78971
|
return `sessions under ${policy.scopePaths.join(", ")}`;
|
|
78972
78972
|
case "org-repos": {
|
|
78973
|
-
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
|
|
78973
|
+
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, no repo-based uploads" : policy.allowedOwners.length > 0 ? `sessions in GitHub repos owned by ${policy.allowedOwners.join(", ")}` : "org-owned GitHub repos, but the org has no GitHub integration, so nothing uploads";
|
|
78974
78974
|
const claiming = (policy.workspaceClaims ?? []).filter(workspaceClaimsAnyRepo);
|
|
78975
78975
|
const severalWorkspaces = (policy.workspaceClaims?.length ?? 0) > 1;
|
|
78976
78976
|
const withOthers = severalWorkspaces && claiming.length > 0 ? `${repoPart}, routing each repo to the workspace that syncs it (${listSome(claiming.map((workspace) => workspace.name))})` : repoPart;
|
|
@@ -79272,7 +79272,6 @@ async function uploadRawSessions(apiUrl, machineToken, collected, readTranscript
|
|
|
79272
79272
|
|
|
79273
79273
|
// ../../apps/collector/src/enroll.ts
|
|
79274
79274
|
var APPROVAL_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
79275
|
-
var MAX_DELIVERY_BYTES = 64 * 1024;
|
|
79276
79275
|
var gotrueTokenSchema = external_exports.object({ access_token: external_exports.string().min(1) });
|
|
79277
79276
|
var gotrueErrorSchema = external_exports.object({
|
|
79278
79277
|
error_description: external_exports.string().optional(),
|
|
@@ -79344,7 +79343,7 @@ async function runEnrollment(config2, options) {
|
|
|
79344
79343
|
if (config2.appEnv === "development") {
|
|
79345
79344
|
const home = normalizeScopePath(os6.homedir());
|
|
79346
79345
|
log3(
|
|
79347
|
-
`No GitHub integration on org "${result.org.name}"
|
|
79346
|
+
`No GitHub integration on org "${result.org.name}", syncing sessions under ${home} (your home folder, local DB only). Re-enroll with --scope <path> to narrow.`
|
|
79348
79347
|
);
|
|
79349
79348
|
captureMode = "scope";
|
|
79350
79349
|
scopePaths = [home];
|
|
@@ -79363,7 +79362,7 @@ async function runEnrollment(config2, options) {
|
|
|
79363
79362
|
throw new ExpectedCliError(
|
|
79364
79363
|
[
|
|
79365
79364
|
`Your org "${result.org.name}" has no GitHub integration yet, so "work = org-owned repos" can't be resolved.`,
|
|
79366
|
-
"If that isn't the org you expected, sign in with your work email
|
|
79365
|
+
"If that isn't the org you expected, sign in with your work email, org membership follows the email's domain.",
|
|
79367
79366
|
"Either:",
|
|
79368
79367
|
` \xB7 connect GitHub in Settings, then re-run: ${options.enrollCommand}`,
|
|
79369
79368
|
" \xB7 or choose the upload boundary by hand:",
|
|
@@ -79412,24 +79411,73 @@ async function runEnrollment(config2, options) {
|
|
|
79412
79411
|
);
|
|
79413
79412
|
return credentials;
|
|
79414
79413
|
}
|
|
79415
|
-
async function enroll(config2, options, createAuthClient = gotrueAuthClient) {
|
|
79414
|
+
async function enroll(config2, options, createAuthClient = gotrueAuthClient, listener = {}) {
|
|
79416
79415
|
if (options.email && options.password) {
|
|
79417
79416
|
return enrollWithPassword(config2, options.name, options.email, options.password, createAuthClient);
|
|
79418
79417
|
}
|
|
79419
79418
|
const state = randomBytes(16).toString("base64url");
|
|
79419
|
+
const verifier = randomBytes(32).toString("base64url");
|
|
79420
79420
|
return waitForApproval(
|
|
79421
|
-
enrollApprovalUrl(config2.webUrl,
|
|
79421
|
+
enrollApprovalUrl(config2.webUrl, {
|
|
79422
|
+
name: options.name,
|
|
79423
|
+
state,
|
|
79424
|
+
challenge: challengeFor(verifier),
|
|
79425
|
+
capture: options.capture
|
|
79426
|
+
}),
|
|
79422
79427
|
state,
|
|
79423
|
-
{ log: options.log }
|
|
79428
|
+
{ ...listener, log: options.log, redeem: (code) => redeemApproval(config2.apiUrl, code, verifier) }
|
|
79424
79429
|
);
|
|
79425
79430
|
}
|
|
79426
|
-
|
|
79431
|
+
var challengeFor = (verifier) => createHash("sha256").update(verifier).digest("hex");
|
|
79432
|
+
function enrollApprovalUrl(webUrl, {
|
|
79433
|
+
name,
|
|
79434
|
+
state,
|
|
79435
|
+
challenge,
|
|
79436
|
+
capture
|
|
79437
|
+
}) {
|
|
79427
79438
|
return `${webUrl}/enroll-machine?${new URLSearchParams({
|
|
79428
79439
|
name,
|
|
79429
79440
|
state,
|
|
79441
|
+
challenge,
|
|
79430
79442
|
...capture && { capture: capture.mode, folders: String(capture.folderCount) }
|
|
79431
79443
|
}).toString()}`;
|
|
79432
79444
|
}
|
|
79445
|
+
async function redeemApproval(apiUrl, code, verifier) {
|
|
79446
|
+
const response = await fetchWithRetry(
|
|
79447
|
+
"redeeming the enrollment approval",
|
|
79448
|
+
`${apiUrl}/api/machines/redeem`,
|
|
79449
|
+
{
|
|
79450
|
+
method: "POST",
|
|
79451
|
+
headers: { "content-type": "application/json" },
|
|
79452
|
+
body: JSON.stringify({ code, verifier })
|
|
79453
|
+
},
|
|
79454
|
+
{ retry: false }
|
|
79455
|
+
);
|
|
79456
|
+
if (response.status === 404) {
|
|
79457
|
+
throw new ExpectedCliError(
|
|
79458
|
+
"the API doesn't know how to redeem an enrollment approval yet. It is likely older than this CLI (deploy in progress?). Try again in a minute."
|
|
79459
|
+
);
|
|
79460
|
+
}
|
|
79461
|
+
if (response.status >= 400 && response.status < 500) {
|
|
79462
|
+
const body = await response.json().catch(() => null);
|
|
79463
|
+
throw new ExpectedCliError(`enrollment failed: ${body?.error ?? `the API answered ${response.status}`}`);
|
|
79464
|
+
}
|
|
79465
|
+
return readEnrollmentResponse(response);
|
|
79466
|
+
}
|
|
79467
|
+
async function readEnrollmentResponse(response) {
|
|
79468
|
+
if (response.status !== 201) {
|
|
79469
|
+
const body2 = await response.json().catch(() => null);
|
|
79470
|
+
throw new Error(`enrollment failed (${response.status}): ${body2?.error ?? "no detail"}`);
|
|
79471
|
+
}
|
|
79472
|
+
const body = await response.json().catch(() => null);
|
|
79473
|
+
const enrollment = body?.data;
|
|
79474
|
+
if (!isEnrollResult(enrollment)) {
|
|
79475
|
+
throw new ExpectedCliError(
|
|
79476
|
+
"enrollment answered 201 without the expected machine/org/token. The API is likely older than this CLI (deploy in progress?). Try again in a minute."
|
|
79477
|
+
);
|
|
79478
|
+
}
|
|
79479
|
+
return enrollment;
|
|
79480
|
+
}
|
|
79433
79481
|
async function enrollWithPassword(config2, name, email3, password, createAuthClient) {
|
|
79434
79482
|
const client = createAuthClient(config2.supabaseUrl, config2.supabasePublishableKey);
|
|
79435
79483
|
const { data, error: error52 } = await client.auth.signInWithPassword({ email: email3, password });
|
|
@@ -79441,18 +79489,7 @@ async function enrollWithPassword(config2, name, email3, password, createAuthCli
|
|
|
79441
79489
|
headers: { authorization: `Bearer ${data.session.access_token}`, "content-type": "application/json" },
|
|
79442
79490
|
body: JSON.stringify({ name })
|
|
79443
79491
|
});
|
|
79444
|
-
|
|
79445
|
-
const body2 = await response.json().catch(() => null);
|
|
79446
|
-
throw new Error(`enrollment failed (${response.status}): ${body2?.error ?? "no detail"}`);
|
|
79447
|
-
}
|
|
79448
|
-
const body = await response.json().catch(() => null);
|
|
79449
|
-
const enrollment = body?.data;
|
|
79450
|
-
if (!isEnrollResult(enrollment)) {
|
|
79451
|
-
throw new ExpectedCliError(
|
|
79452
|
-
"enrollment answered 201 without the expected machine/org/token \u2014 the API is likely older than this CLI (deploy in progress?). Try again in a minute."
|
|
79453
|
-
);
|
|
79454
|
-
}
|
|
79455
|
-
return enrollment;
|
|
79492
|
+
return await readEnrollmentResponse(response);
|
|
79456
79493
|
} finally {
|
|
79457
79494
|
await client.auth.signOut({ scope: "local" });
|
|
79458
79495
|
}
|
|
@@ -79461,61 +79498,84 @@ function isEnrollResult(value) {
|
|
|
79461
79498
|
const candidate = value;
|
|
79462
79499
|
return typeof candidate?.machine?.id === "string" && typeof candidate.machine.name === "string" && typeof candidate.org?.id === "string" && typeof candidate.org.name === "string" && typeof candidate.token === "string";
|
|
79463
79500
|
}
|
|
79464
|
-
function waitForApproval(approvalUrl, state, options
|
|
79501
|
+
function waitForApproval(approvalUrl, state, options) {
|
|
79465
79502
|
const {
|
|
79503
|
+
redeem,
|
|
79466
79504
|
port = MACHINE_ENROLL_CALLBACK_PORT,
|
|
79467
79505
|
open = openBrowser,
|
|
79506
|
+
onListening,
|
|
79468
79507
|
timeoutMs = APPROVAL_TIMEOUT_MS,
|
|
79469
79508
|
log: log3 = console.log
|
|
79470
79509
|
} = options;
|
|
79471
79510
|
return new Promise((resolve2, reject) => {
|
|
79472
79511
|
const baseHeaders = { connection: "close" };
|
|
79512
|
+
let redeeming = false;
|
|
79473
79513
|
const server = http5.createServer((request2, response) => {
|
|
79474
|
-
|
|
79514
|
+
const url2 = new URL(request2.url ?? "/", "http://127.0.0.1");
|
|
79515
|
+
if (request2.method !== "GET" || url2.pathname !== MACHINE_ENROLL_CALLBACK_PATH) {
|
|
79475
79516
|
response.writeHead(404, baseHeaders).end();
|
|
79476
79517
|
return;
|
|
79477
79518
|
}
|
|
79478
79519
|
const answer = (status, html, onFlushed) => {
|
|
79479
79520
|
response.writeHead(status, { ...baseHeaders, "content-type": "text/html; charset=utf-8" }).end(html, onFlushed);
|
|
79480
79521
|
};
|
|
79481
|
-
|
|
79482
|
-
|
|
79483
|
-
|
|
79484
|
-
|
|
79485
|
-
|
|
79486
|
-
|
|
79487
|
-
|
|
79488
|
-
|
|
79489
|
-
|
|
79490
|
-
|
|
79491
|
-
|
|
79492
|
-
|
|
79493
|
-
if (!isEnrollResult(delivery.data)) {
|
|
79494
|
-
answer(
|
|
79495
|
-
400,
|
|
79496
|
-
approvalAnswerPage(
|
|
79497
|
-
"The approval couldn't be read",
|
|
79498
|
-
"Close this tab and start over from the terminal."
|
|
79499
|
-
)
|
|
79500
|
-
);
|
|
79501
|
-
return;
|
|
79502
|
-
}
|
|
79503
|
-
const data = delivery.data;
|
|
79522
|
+
if (url2.searchParams.get("state") !== state) {
|
|
79523
|
+
answer(
|
|
79524
|
+
403,
|
|
79525
|
+
approvalAnswerPage(
|
|
79526
|
+
"This isn't the enrollment the terminal is waiting for",
|
|
79527
|
+
"Go back to the terminal that's waiting, open the link it printed, and approve from there."
|
|
79528
|
+
)
|
|
79529
|
+
);
|
|
79530
|
+
return;
|
|
79531
|
+
}
|
|
79532
|
+
const code = url2.searchParams.get("code");
|
|
79533
|
+
if (code === null || code === "") {
|
|
79504
79534
|
answer(
|
|
79535
|
+
400,
|
|
79536
|
+
approvalAnswerPage(
|
|
79537
|
+
"The approval couldn't be read",
|
|
79538
|
+
"Close this tab and start over from the terminal."
|
|
79539
|
+
)
|
|
79540
|
+
);
|
|
79541
|
+
return;
|
|
79542
|
+
}
|
|
79543
|
+
if (redeeming) {
|
|
79544
|
+
answer(
|
|
79545
|
+
409,
|
|
79546
|
+
approvalAnswerPage(
|
|
79547
|
+
"This approval is already being handled",
|
|
79548
|
+
"The terminal is finishing this enrollment. You can close this tab."
|
|
79549
|
+
)
|
|
79550
|
+
);
|
|
79551
|
+
return;
|
|
79552
|
+
}
|
|
79553
|
+
redeeming = true;
|
|
79554
|
+
clearTimeout(timeout);
|
|
79555
|
+
void redeem(code).then(
|
|
79556
|
+
(data) => answer(
|
|
79505
79557
|
200,
|
|
79506
79558
|
approvalAnswerPage(
|
|
79507
79559
|
`${data.machine.name} is enrolled in ${data.org.name}`,
|
|
79508
79560
|
"You can close this tab and return to the terminal."
|
|
79509
79561
|
),
|
|
79510
79562
|
() => finish(() => resolve2(data))
|
|
79511
|
-
)
|
|
79512
|
-
|
|
79563
|
+
),
|
|
79564
|
+
(cause) => answer(
|
|
79565
|
+
500,
|
|
79566
|
+
approvalAnswerPage(
|
|
79567
|
+
"The approval couldn't be completed",
|
|
79568
|
+
"Return to the terminal. It says what went wrong and how to retry."
|
|
79569
|
+
),
|
|
79570
|
+
() => finish(() => reject(cause instanceof Error ? cause : new Error(String(cause))))
|
|
79571
|
+
)
|
|
79572
|
+
);
|
|
79513
79573
|
});
|
|
79514
79574
|
const timeout = setTimeout(
|
|
79515
79575
|
() => finish(
|
|
79516
79576
|
() => reject(
|
|
79517
79577
|
new ExpectedCliError(
|
|
79518
|
-
"enrollment approval timed out after 5 minutes
|
|
79578
|
+
"enrollment approval timed out after 5 minutes, run the same command again to retry"
|
|
79519
79579
|
)
|
|
79520
79580
|
)
|
|
79521
79581
|
),
|
|
@@ -79529,41 +79589,16 @@ function waitForApproval(approvalUrl, state, options = {}) {
|
|
|
79529
79589
|
};
|
|
79530
79590
|
server.once("error", (cause) => finish(() => reject(cause)));
|
|
79531
79591
|
server.listen(port, "127.0.0.1", () => {
|
|
79592
|
+
const address = server.address();
|
|
79593
|
+
if (onListening && address !== null && typeof address === "object") onListening(address.port);
|
|
79532
79594
|
log3(`Open approval page: ${approvalUrl}`);
|
|
79533
79595
|
open(approvalUrl);
|
|
79534
79596
|
});
|
|
79535
79597
|
});
|
|
79536
79598
|
}
|
|
79537
|
-
|
|
79538
|
-
return new Promise((resolve2) => {
|
|
79539
|
-
const chunks = [];
|
|
79540
|
-
let size = 0;
|
|
79541
|
-
request2.on("data", (chunk) => {
|
|
79542
|
-
size += chunk.length;
|
|
79543
|
-
if (size > MAX_DELIVERY_BYTES) {
|
|
79544
|
-
request2.destroy();
|
|
79545
|
-
resolve2(null);
|
|
79546
|
-
return;
|
|
79547
|
-
}
|
|
79548
|
-
chunks.push(chunk);
|
|
79549
|
-
});
|
|
79550
|
-
request2.on("end", () => resolve2(Buffer.concat(chunks).toString("utf8")));
|
|
79551
|
-
request2.on("error", () => resolve2(null));
|
|
79552
|
-
});
|
|
79553
|
-
}
|
|
79554
|
-
function parseDelivery(raw) {
|
|
79555
|
-
if (raw === null) return null;
|
|
79556
|
-
const fields = new URLSearchParams(raw);
|
|
79557
|
-
let data;
|
|
79558
|
-
try {
|
|
79559
|
-
data = JSON.parse(fields.get("data") ?? "");
|
|
79560
|
-
} catch {
|
|
79561
|
-
data = void 0;
|
|
79562
|
-
}
|
|
79563
|
-
return { state: fields.get("state") ?? void 0, data };
|
|
79564
|
-
}
|
|
79599
|
+
var PPLOGO_SVG = '<svg width="20" height="20" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M35.4167 7.5H17.5L3.75 30L17.5 52.5L30 30H17.0833L35.4167 7.5Z" fill="#FFD17A"/><path d="M24.5833 52.5H42.5L56.25 30L42.5 7.5L30 30H42.9167L24.5833 52.5Z" fill="#FFA600"/></svg>';
|
|
79565
79600
|
function approvalAnswerPage(heading, detail) {
|
|
79566
|
-
return `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Powerplant</title
|
|
79601
|
+
return `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Powerplant</title><style>body{margin:0;min-height:100vh;display:flex;align-items:center;justify-content:center;background:oklch(98.7% 0.004 250);color:#232422;font-family:"Figtree",system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased}main{display:flex;flex-direction:column;align-items:center;gap:0.75rem;max-width:24rem;padding:1.5rem;text-align:center}.mark{display:flex;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;border:1px solid oklch(92.5% 0.006 250);border-radius:0.375rem;background:#ffffff}h1{margin:0;font-size:1.25rem;line-height:1.75rem;font-weight:700}p{margin:0;font-size:0.875rem;line-height:1.5;color:#6a6d69}</style></head><body><main><span class="mark">${PPLOGO_SVG}</span><h1>${escapeHtml(heading)}</h1><p>${escapeHtml(detail)}</p></main></body></html>`;
|
|
79567
79602
|
}
|
|
79568
79603
|
var escapeHtml = (text) => text.replace(/[&<>"']/g, (character) => `&#${character.charCodeAt(0)};`);
|
|
79569
79604
|
function openBrowser(url2) {
|
|
@@ -79577,7 +79612,7 @@ function requireEnrolled(config2, enrollCommand, deps) {
|
|
|
79577
79612
|
const credentials = deps.load(config2.appEnv);
|
|
79578
79613
|
if (!credentials) {
|
|
79579
79614
|
throw new ExpectedCliError(
|
|
79580
|
-
`This machine isn't enrolled for ${config2.appEnv}
|
|
79615
|
+
`This machine isn't enrolled for ${config2.appEnv}, run: ${enrollCommand}`
|
|
79581
79616
|
);
|
|
79582
79617
|
}
|
|
79583
79618
|
return credentials;
|
|
@@ -79606,7 +79641,7 @@ function addFolder(config2, rawPath, enrollCommand, log3, deps = defaultDeps) {
|
|
|
79606
79641
|
});
|
|
79607
79642
|
const org = credentials.orgName ?? "your org";
|
|
79608
79643
|
log3(
|
|
79609
|
-
credentials.captureMode === "org-repos" ? `Sessions under ${folder} will now upload to ${org}
|
|
79644
|
+
credentials.captureMode === "org-repos" ? `Sessions under ${folder} will now upload to ${org}, even outside the org's allowlisted repos.` : `Added ${folder} to this machine's sync boundary.`
|
|
79610
79645
|
);
|
|
79611
79646
|
log3("Takes effect on the next sync pass; run the sync command to apply now.");
|
|
79612
79647
|
}
|
|
@@ -79622,14 +79657,14 @@ function removeFolder(config2, rawPath, enrollCommand, log3, deps = defaultDeps)
|
|
|
79622
79657
|
const remaining = folders.filter((existing) => existing !== folder);
|
|
79623
79658
|
if (credentials.captureMode === "scope" && remaining.length === 0) {
|
|
79624
79659
|
throw new ExpectedCliError(
|
|
79625
|
-
"A --scope enrollment needs at least one folder
|
|
79660
|
+
"A --scope enrollment needs at least one folder, re-enroll to change the sync boundary instead."
|
|
79626
79661
|
);
|
|
79627
79662
|
}
|
|
79628
79663
|
deps.persist(config2.appEnv, {
|
|
79629
79664
|
...credentials,
|
|
79630
79665
|
scopePaths: remaining
|
|
79631
79666
|
});
|
|
79632
|
-
log3(`Removed ${folder}
|
|
79667
|
+
log3(`Removed ${folder}, sessions there stay local from the next sync pass.`);
|
|
79633
79668
|
}
|
|
79634
79669
|
|
|
79635
79670
|
// ../../apps/collector/src/protectedRepoDiscovery.ts
|
|
@@ -80295,7 +80330,7 @@ async function collectCodexSessions(options = {}) {
|
|
|
80295
80330
|
}
|
|
80296
80331
|
|
|
80297
80332
|
// ../../apps/collector/src/cursorLocal.ts
|
|
80298
|
-
import { createHash } from "node:crypto";
|
|
80333
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
80299
80334
|
import { mkdirSync as mkdirSync2, utimesSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
80300
80335
|
import os9 from "node:os";
|
|
80301
80336
|
import path7 from "node:path";
|
|
@@ -80364,7 +80399,7 @@ function safeJsonRecord2(text) {
|
|
|
80364
80399
|
}
|
|
80365
80400
|
function spoolFileName(composerId) {
|
|
80366
80401
|
const sanitized = composerId.replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 80);
|
|
80367
|
-
const hash2 =
|
|
80402
|
+
const hash2 = createHash2("sha256").update(composerId).digest("hex").slice(0, 8);
|
|
80368
80403
|
return `${sanitized}-${hash2}.jsonl`;
|
|
80369
80404
|
}
|
|
80370
80405
|
function workspaceFolderOf(cursorUserDir, workspaceId) {
|
|
@@ -80738,7 +80773,7 @@ function allowProtectedRepoDiscovery(config2, found, environment = {}, deps = de
|
|
|
80738
80773
|
const credentials = deps.load(config2.appEnv);
|
|
80739
80774
|
if (credentials === null || credentials.token !== enrollment.token || credentials.enrolledAt !== enrollment.enrolledAt) {
|
|
80740
80775
|
throw new ExpectedCliError(
|
|
80741
|
-
"This machine's enrollment changed while the folders were being reviewed, so the approval was not saved
|
|
80776
|
+
"This machine's enrollment changed while the folders were being reviewed, so the approval was not saved, run `powerplant init` again to review them."
|
|
80742
80777
|
);
|
|
80743
80778
|
}
|
|
80744
80779
|
const allowedProtectedRoots = [
|
|
@@ -80754,17 +80789,16 @@ function allowProtectedRepoDiscovery(config2, found, environment = {}, deps = de
|
|
|
80754
80789
|
}
|
|
80755
80790
|
|
|
80756
80791
|
// ../../apps/collector/src/hookInstall.ts
|
|
80757
|
-
import { existsSync, mkdirSync as mkdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync3 } from "node:fs";
|
|
80792
|
+
import { existsSync, mkdirSync as mkdirSync3, readFileSync as readFileSync6, rmSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
80758
80793
|
import os11 from "node:os";
|
|
80759
80794
|
import path9 from "node:path";
|
|
80760
80795
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
80761
|
-
var INBOX_HOOK_FILENAME = "powerplant-inbox.mjs";
|
|
80762
80796
|
var LIFECYCLE_HOOK_FILENAME = "powerplant-session-lifecycle.mjs";
|
|
80763
80797
|
var HOOK_WIRINGS = [
|
|
80764
|
-
{ event: "UserPromptSubmit", script: INBOX_HOOK_FILENAME },
|
|
80765
80798
|
{ event: "SessionStart", script: LIFECYCLE_HOOK_FILENAME },
|
|
80766
80799
|
{ event: "SessionEnd", script: LIFECYCLE_HOOK_FILENAME }
|
|
80767
80800
|
];
|
|
80801
|
+
var RETIRED_HOOK_WIRINGS = [{ event: "UserPromptSubmit", script: "powerplant-inbox.mjs" }];
|
|
80768
80802
|
var HOOK_SCRIPTS = [...new Set(HOOK_WIRINGS.map((wiring) => wiring.script))];
|
|
80769
80803
|
function isOurGroup(group, script) {
|
|
80770
80804
|
return Array.isArray(group.hooks) && group.hooks.some((hook) => typeof hook.command === "string" && hook.command.includes(script));
|
|
@@ -80785,9 +80819,10 @@ function mergeCollectorHooks(settingsText, commandFor) {
|
|
|
80785
80819
|
}
|
|
80786
80820
|
}
|
|
80787
80821
|
const hooks = settings.hooks !== null && typeof settings.hooks === "object" && !Array.isArray(settings.hooks) ? { ...settings.hooks } : {};
|
|
80822
|
+
const groupsOf = (event) => Array.isArray(hooks[event]) ? hooks[event] : [];
|
|
80788
80823
|
let changed = false;
|
|
80789
80824
|
for (const wiring of HOOK_WIRINGS) {
|
|
80790
|
-
const groups =
|
|
80825
|
+
const groups = groupsOf(wiring.event);
|
|
80791
80826
|
const ourGroup = {
|
|
80792
80827
|
hooks: [{ type: "command", command: commandFor(wiring.script), timeout: 5 }]
|
|
80793
80828
|
};
|
|
@@ -80796,6 +80831,14 @@ function mergeCollectorHooks(settingsText, commandFor) {
|
|
|
80796
80831
|
hooks[wiring.event] = [...groups.filter((group) => !isOurGroup(group, wiring.script)), ourGroup];
|
|
80797
80832
|
changed = true;
|
|
80798
80833
|
}
|
|
80834
|
+
for (const retired of RETIRED_HOOK_WIRINGS) {
|
|
80835
|
+
const groups = groupsOf(retired.event);
|
|
80836
|
+
const kept = groups.filter((group) => !isOurGroup(group, retired.script));
|
|
80837
|
+
if (kept.length === groups.length) continue;
|
|
80838
|
+
if (kept.length === 0) delete hooks[retired.event];
|
|
80839
|
+
else hooks[retired.event] = kept;
|
|
80840
|
+
changed = true;
|
|
80841
|
+
}
|
|
80799
80842
|
if (!changed) return { action: "unchanged" };
|
|
80800
80843
|
const next = { ...settings, hooks };
|
|
80801
80844
|
return { action: "write", text: `${JSON.stringify(next, null, 2)}
|
|
@@ -80833,6 +80876,11 @@ function installCollectorHooks(homeDir = os11.homedir()) {
|
|
|
80833
80876
|
mkdirSync3(settingsDir, { recursive: true });
|
|
80834
80877
|
writeFileSync3(settingsPath, merged.text);
|
|
80835
80878
|
}
|
|
80879
|
+
if (merged.action !== "skip") {
|
|
80880
|
+
for (const retired of RETIRED_HOOK_WIRINGS) {
|
|
80881
|
+
rmSync(path9.join(hookDir, retired.script), { force: true });
|
|
80882
|
+
}
|
|
80883
|
+
}
|
|
80836
80884
|
return {
|
|
80837
80885
|
hookDir,
|
|
80838
80886
|
settings: merged.action,
|
|
@@ -80842,7 +80890,7 @@ function installCollectorHooks(homeDir = os11.homedir()) {
|
|
|
80842
80890
|
|
|
80843
80891
|
// ../../apps/collector/src/service.ts
|
|
80844
80892
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
80845
|
-
import { chmodSync as chmodSync2, existsSync as existsSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync7, rmSync, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
80893
|
+
import { chmodSync as chmodSync2, existsSync as existsSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync7, rmSync as rmSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
80846
80894
|
import os12 from "node:os";
|
|
80847
80895
|
import path10 from "node:path";
|
|
80848
80896
|
var RESTART_THROTTLE_SECONDS = 60;
|
|
@@ -80873,7 +80921,7 @@ function refuseStaleAppEnvLauncher(env, readLauncher = readLauncherIfExists) {
|
|
|
80873
80921
|
const script = readLauncher(launcherPath(appEnv));
|
|
80874
80922
|
if (script === null || !script.includes("APP_ENV=") || script.includes("POWERPLANT_ENV=")) return;
|
|
80875
80923
|
throw new ExpectedCliError(
|
|
80876
|
-
`This background service was installed before the POWERPLANT_ENV rename and is no longer supported. Remove it with: powerplant uninstall --env ${appEnv}` + (appEnv === "production" ? "
|
|
80924
|
+
`This background service was installed before the POWERPLANT_ENV rename and is no longer supported. Remove it with: powerplant uninstall --env ${appEnv}` + (appEnv === "production" ? ", then powerplant init reinstalls it." : `, then powerplant init --env ${appEnv} reinstalls it if you still need it.`)
|
|
80877
80925
|
);
|
|
80878
80926
|
}
|
|
80879
80927
|
function readLauncherIfExists(launcherFile) {
|
|
@@ -80918,7 +80966,7 @@ function installService(config2, command) {
|
|
|
80918
80966
|
if (!waitForUnload(() => isLoaded(config2.appEnv))) {
|
|
80919
80967
|
const service = `gui/${uid()}/${label(config2.appEnv)}`;
|
|
80920
80968
|
throw new Error(
|
|
80921
|
-
`launchd is still unloading ${label(config2.appEnv)} after ${UNLOAD_WAIT_MS / 1e3}s
|
|
80969
|
+
`launchd is still unloading ${label(config2.appEnv)} after ${UNLOAD_WAIT_MS / 1e3}s, re-run powerplant init, or unload it by hand first: launchctl bootout ${service}`
|
|
80922
80970
|
);
|
|
80923
80971
|
}
|
|
80924
80972
|
const launcher = launcherPath(config2.appEnv);
|
|
@@ -80964,7 +81012,7 @@ function serviceUpToDate(config2, command) {
|
|
|
80964
81012
|
function uninstallService(config2) {
|
|
80965
81013
|
requireMacos();
|
|
80966
81014
|
const existed = bootout(config2.appEnv);
|
|
80967
|
-
|
|
81015
|
+
rmSync2(launcherPath(config2.appEnv), { force: true });
|
|
80968
81016
|
if (existsSync2(plistPath(config2.appEnv))) {
|
|
80969
81017
|
unlinkSync2(plistPath(config2.appEnv));
|
|
80970
81018
|
return true;
|
|
@@ -81034,7 +81082,7 @@ function xmlEscape(value) {
|
|
|
81034
81082
|
}
|
|
81035
81083
|
|
|
81036
81084
|
// ../../apps/collector/src/status.ts
|
|
81037
|
-
import { mkdirSync as mkdirSync5, readFileSync as readFileSync8, renameSync, rmSync as
|
|
81085
|
+
import { mkdirSync as mkdirSync5, readFileSync as readFileSync8, renameSync, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
81038
81086
|
import os13 from "node:os";
|
|
81039
81087
|
import path11 from "node:path";
|
|
81040
81088
|
var HEARTBEAT_INTERVAL_MS = 6e4;
|
|
@@ -81137,10 +81185,10 @@ function writeCollectorControl(appEnv, control, homeDir) {
|
|
|
81137
81185
|
writeAtomically(controlFilePath(appEnv, homeDir), JSON.stringify(control, null, 2));
|
|
81138
81186
|
}
|
|
81139
81187
|
function clearCollectorControl(appEnv, homeDir) {
|
|
81140
|
-
|
|
81188
|
+
rmSync3(controlFilePath(appEnv, homeDir), { force: true });
|
|
81141
81189
|
}
|
|
81142
81190
|
function clearCollectorStatus(appEnv, homeDir) {
|
|
81143
|
-
|
|
81191
|
+
rmSync3(statusFilePath(appEnv, homeDir), { force: true });
|
|
81144
81192
|
}
|
|
81145
81193
|
function describeDaemonState(read, probes = {}) {
|
|
81146
81194
|
if (read.file === "invalid") return { state: "unreadable" };
|
|
@@ -81360,14 +81408,14 @@ async function resolveCapturePolicy(config2, credentials, log3, deps = defaultPo
|
|
|
81360
81408
|
claimsUnresolved = true;
|
|
81361
81409
|
}
|
|
81362
81410
|
log3(
|
|
81363
|
-
`\u26A0 Couldn't refresh the org's repo sync policy (${describeSyncError(cause)})
|
|
81411
|
+
`\u26A0 Couldn't refresh the org's repo sync policy (${describeSyncError(cause)}), ` + (cachedCoversSomething ? "using the cached policy." : "nothing will upload this pass.")
|
|
81364
81412
|
);
|
|
81365
81413
|
}
|
|
81366
81414
|
const memberFolders = credentials.scopePaths ?? [];
|
|
81367
81415
|
if (ownersUnresolved && owners.length === 0 && repos === null) claimsUnresolved = true;
|
|
81368
81416
|
if (ownersUnresolved) {
|
|
81369
81417
|
log3(
|
|
81370
|
-
"\u26A0 The org's GitHub is connected, but its account couldn't be resolved just now
|
|
81418
|
+
"\u26A0 The org's GitHub is connected, but its account couldn't be resolved just now, " + (owners.length > 0 ? `using the cached owner list: ${owners.join(", ")}.` : "no owner-based uploads this pass. This is usually temporary; syncing resumes when it resolves.")
|
|
81371
81419
|
);
|
|
81372
81420
|
}
|
|
81373
81421
|
const homeOrgId = credentials.orgId ?? workspacePolicies?.[0]?.orgId;
|
|
@@ -81376,11 +81424,11 @@ async function resolveCapturePolicy(config2, credentials, log3, deps = defaultPo
|
|
|
81376
81424
|
);
|
|
81377
81425
|
if (repos !== null && repos.length === 0) {
|
|
81378
81426
|
log3(
|
|
81379
|
-
"\u26A0 The org's repo allowlist is empty
|
|
81427
|
+
"\u26A0 The org's repo allowlist is empty, no repo-based uploads for it" + (foreignClaims.length > 0 ? `; repos synced by ${foreignClaims.map((entry) => entry.name).join(", ")} still upload.` : memberFolders.length > 0 ? "; only folders you added upload." : ".")
|
|
81380
81428
|
);
|
|
81381
81429
|
} else if (repos === null && owners.length === 0 && !ownersUnresolved) {
|
|
81382
81430
|
log3(
|
|
81383
|
-
foreignClaims.length > 0 ? `Your home workspace has no GitHub integration
|
|
81431
|
+
foreignClaims.length > 0 ? `Your home workspace has no GitHub integration, syncing repos for ${foreignClaims.map((entry) => entry.name).join(", ")}.` : "\u26A0 Syncing is gated on org-owned GitHub repos, but the org has no GitHub integration, nothing uploads. Connect GitHub in Settings, or add folders with `powerplant folders add`."
|
|
81384
81432
|
);
|
|
81385
81433
|
}
|
|
81386
81434
|
return {
|
|
@@ -81399,13 +81447,13 @@ async function runSyncPass(config2, options = {}) {
|
|
|
81399
81447
|
const credentials = loadCredentials(config2.appEnv);
|
|
81400
81448
|
if (!credentials) {
|
|
81401
81449
|
throw new ExpectedCliError(
|
|
81402
|
-
`This machine isn't enrolled for ${config2.appEnv}
|
|
81450
|
+
`This machine isn't enrolled for ${config2.appEnv}, run: ${options.enrollCommand ?? "pnpm collector enroll"}`
|
|
81403
81451
|
);
|
|
81404
81452
|
}
|
|
81405
81453
|
const window2 = resolveSyncWindow(options.explicitSince, credentials.deepSyncedAt);
|
|
81406
81454
|
if (window2.deepSweep) {
|
|
81407
81455
|
log3(
|
|
81408
|
-
`First sync for this enrollment
|
|
81456
|
+
`First sync for this enrollment, 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).`
|
|
81409
81457
|
);
|
|
81410
81458
|
}
|
|
81411
81459
|
const capture = await resolveCapturePolicy(config2, credentials, log3);
|
|
@@ -81415,7 +81463,7 @@ async function runSyncPass(config2, options = {}) {
|
|
|
81415
81463
|
const codex = await collectCodexSessions({ sinceMs, capture, maxSessions });
|
|
81416
81464
|
const cursor = await collectCursorSessions({ sinceMs, capture });
|
|
81417
81465
|
if (cursor.unavailable !== null) {
|
|
81418
|
-
log3(`\u26A0 Cursor sessions skipped this pass
|
|
81466
|
+
log3(`\u26A0 Cursor sessions skipped this pass, ${cursor.unavailable}. Other syncing is unaffected.`);
|
|
81419
81467
|
}
|
|
81420
81468
|
const inWindow = [...claude.sessions, ...codex.sessions, ...cursor.sessions].sort(
|
|
81421
81469
|
(a, b2) => b2.mtimeMs - a.mtimeMs
|
|
@@ -81426,41 +81474,41 @@ async function runSyncPass(config2, options = {}) {
|
|
|
81426
81474
|
const skippedNoRepo = claude.skippedNoRepo + codex.skippedNoRepo + cursor.skippedNoRepo;
|
|
81427
81475
|
const items = collected.map((c) => c.item);
|
|
81428
81476
|
const active = items.filter((s) => s.status === "active").length;
|
|
81429
|
-
const tooLarge = (count, what) => count > 0 ? ` \xB7 ${count} ${what} skipped (over ${MAX_TRANSCRIPT_FILE_BYTES / (1024 * 1024)}MB
|
|
81477
|
+
const tooLarge = (count, what) => count > 0 ? ` \xB7 ${count} ${what} skipped (over ${MAX_TRANSCRIPT_FILE_BYTES / (1024 * 1024)}MB, too large to read)` : "";
|
|
81430
81478
|
log3(
|
|
81431
|
-
`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` : "") + tooLarge(claude.skippedTooLarge, "claude transcript(s)") + (claude.unreadable.length > 0 ? ` \xB7 ${claude.unreadable.length} claude transcript(s) unreadable, skipped` : "") + tooLarge(codex.skippedTooLarge, "codex rollout(s)") + (codex.unreadable.length > 0 ? ` \xB7 ${codex.unreadable.length} codex rollout(s) unreadable, skipped` : "") + tooLarge(cursor.skippedTooLarge, "cursor transcript(s)") + (cursor.truncatedTranscripts > 0 ? ` \xB7 ${cursor.truncatedTranscripts} cursor transcript(s) cut at ${MAX_TRANSCRIPT_FILE_BYTES / (1024 * 1024)}MB (the rest of the conversation stays local)` : "") + (heldBack > 0 ? ` \xB7 ${heldBack} older session(s) held back
|
|
81479
|
+
`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` : "") + tooLarge(claude.skippedTooLarge, "claude transcript(s)") + (claude.unreadable.length > 0 ? ` \xB7 ${claude.unreadable.length} claude transcript(s) unreadable, skipped` : "") + tooLarge(codex.skippedTooLarge, "codex rollout(s)") + (codex.unreadable.length > 0 ? ` \xB7 ${codex.unreadable.length} codex rollout(s) unreadable, skipped` : "") + tooLarge(cursor.skippedTooLarge, "cursor transcript(s)") + (cursor.truncatedTranscripts > 0 ? ` \xB7 ${cursor.truncatedTranscripts} cursor transcript(s) cut at ${MAX_TRANSCRIPT_FILE_BYTES / (1024 * 1024)}MB (the rest of the conversation stays local)` : "") + (heldBack > 0 ? ` \xB7 ${heldBack} older session(s) held back, the first sync backfills the ${DEEP_FIRST_SYNC_MAX_SESSIONS} most recently active` : "") + "."
|
|
81432
81480
|
);
|
|
81433
|
-
for (const failure of claude.unreadable) log3(` claude transcript skipped
|
|
81434
|
-
for (const failure of codex.unreadable) log3(` codex rollout skipped
|
|
81481
|
+
for (const failure of claude.unreadable) log3(` claude transcript skipped, ${failure}`);
|
|
81482
|
+
for (const failure of codex.unreadable) log3(` codex rollout skipped, ${failure}`);
|
|
81435
81483
|
if (options.dryRun) {
|
|
81436
81484
|
for (const s of items.slice(0, 10)) {
|
|
81437
81485
|
log3(` ${s.externalId} ${s.model ?? "model unmeasured"} ${s.title ?? "(untitled)"}`);
|
|
81438
81486
|
}
|
|
81439
81487
|
if (items.length > 10) log3(` ... and ${items.length - 10} more`);
|
|
81440
|
-
log3("Dry run
|
|
81488
|
+
log3("Dry run, nothing uploaded.");
|
|
81441
81489
|
return { sessions: collected, upserted: 0 };
|
|
81442
81490
|
}
|
|
81443
81491
|
const markDeepSynced = () => {
|
|
81444
81492
|
if (!window2.deepSweep) return;
|
|
81445
81493
|
const current = loadCredentials(config2.appEnv);
|
|
81446
81494
|
if (current === null) {
|
|
81447
|
-
log3("Deep sync finished, but this machine's credentials are gone
|
|
81495
|
+
log3("Deep sync finished, but this machine's credentials are gone, nothing to stamp.");
|
|
81448
81496
|
return;
|
|
81449
81497
|
}
|
|
81450
81498
|
if (current.token !== credentials.token || current.enrolledAt !== credentials.enrolledAt) {
|
|
81451
81499
|
log3(
|
|
81452
|
-
"Deep sync finished for a superseded enrollment
|
|
81500
|
+
"Deep sync finished for a superseded enrollment, the current enrollment still owes its own deep sweep."
|
|
81453
81501
|
);
|
|
81454
81502
|
return;
|
|
81455
81503
|
}
|
|
81456
81504
|
saveCredentials(config2.appEnv, { ...current, deepSyncedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
81457
|
-
log3(`Deep sync complete
|
|
81505
|
+
log3(`Deep sync complete, future syncs cover the last ${STEADY_SYNC_WINDOW_DAYS} days.`);
|
|
81458
81506
|
};
|
|
81459
81507
|
const claimsUnresolved = capture.mode === "org-repos" && capture.claimsUnresolved === true;
|
|
81460
81508
|
if (items.length === 0) {
|
|
81461
81509
|
if (claimsUnresolved) {
|
|
81462
81510
|
if (window2.deepSweep) {
|
|
81463
|
-
log3("Deep sync not stamped
|
|
81511
|
+
log3("Deep sync not stamped, a workspace's claims are unresolved; the sweep re-runs next pass.");
|
|
81464
81512
|
}
|
|
81465
81513
|
} else {
|
|
81466
81514
|
markDeepSynced();
|
|
@@ -81477,12 +81525,12 @@ async function runSyncPass(config2, options = {}) {
|
|
|
81477
81525
|
);
|
|
81478
81526
|
if (deferred > 0) {
|
|
81479
81527
|
log3(
|
|
81480
|
-
`\u26A0 ${deferred} session(s) deferred
|
|
81528
|
+
`\u26A0 ${deferred} session(s) deferred, a workspace's GitHub owners couldn't be resolved just now, so routing waited rather than guessing a workspace. They upload on a later pass.`
|
|
81481
81529
|
);
|
|
81482
81530
|
}
|
|
81483
81531
|
if (outOfPolicy > 0) {
|
|
81484
81532
|
log3(
|
|
81485
|
-
`\u26A0 ${outOfPolicy} session(s) refused by the org's repo sync policy
|
|
81533
|
+
`\u26A0 ${outOfPolicy} session(s) refused by the org's repo sync policy, they stayed out of Powerplant. The next pass refreshes the policy and stops offering them.`
|
|
81486
81534
|
);
|
|
81487
81535
|
}
|
|
81488
81536
|
const registerPreviews = options.registerPreviews ?? registerAnnouncedPreviews;
|
|
@@ -81497,13 +81545,13 @@ async function runSyncPass(config2, options = {}) {
|
|
|
81497
81545
|
}
|
|
81498
81546
|
for (const externalId of previewSummary.foreignOwned) {
|
|
81499
81547
|
log3(
|
|
81500
|
-
`Previews for ${externalId} are registered by another machine
|
|
81548
|
+
`Previews for ${externalId} are registered by another machine, leaving its list in place.`
|
|
81501
81549
|
);
|
|
81502
81550
|
}
|
|
81503
81551
|
for (const externalId of previewSummary.previewsOff) {
|
|
81504
|
-
log3(`Previews for ${externalId} refused
|
|
81552
|
+
log3(`Previews for ${externalId} refused, this organization has previews switched off.`);
|
|
81505
81553
|
}
|
|
81506
|
-
for (const failure of previewSummary.failed) log3(` preview registration failed
|
|
81554
|
+
for (const failure of previewSummary.failed) log3(` preview registration failed, ${failure}`);
|
|
81507
81555
|
try {
|
|
81508
81556
|
const observe = options.observeBranch ? options.observeBranch() : branchObserver({ allowedProtectedRoots: credentials.repoDiscoveryRoots ?? [] });
|
|
81509
81557
|
const facts = branchFactsOf(collected, observe);
|
|
@@ -81513,7 +81561,7 @@ async function runSyncPass(config2, options = {}) {
|
|
|
81513
81561
|
log3(`Branch facts: ${recorded} branch state(s) recorded.`);
|
|
81514
81562
|
}
|
|
81515
81563
|
} catch (cause) {
|
|
81516
|
-
log3(`\u26A0 Branch facts skipped this pass
|
|
81564
|
+
log3(`\u26A0 Branch facts skipped this pass, ${describeSyncError(cause)}`);
|
|
81517
81565
|
}
|
|
81518
81566
|
const rawFloor = rawShipFloorMs(config2.appEnv, Date.now(), options.explicitSince);
|
|
81519
81567
|
const rawEligible = rawFloor === null ? collected : collected.filter((c) => c.mtimeMs >= rawFloor);
|
|
@@ -81526,7 +81574,7 @@ async function runSyncPass(config2, options = {}) {
|
|
|
81526
81574
|
options.rawShipped
|
|
81527
81575
|
);
|
|
81528
81576
|
if (raw.unconfigured) {
|
|
81529
|
-
log3("Raw content: this environment has no raw storage yet
|
|
81577
|
+
log3("Raw content: this environment has no raw storage yet, skipped.");
|
|
81530
81578
|
} else {
|
|
81531
81579
|
const parts = [`${raw.uploaded} uploaded`];
|
|
81532
81580
|
if (raw.skippedUnchanged > 0) parts.push(`${raw.skippedUnchanged} unchanged`);
|
|
@@ -81534,20 +81582,20 @@ async function runSyncPass(config2, options = {}) {
|
|
|
81534
81582
|
if (raw.skippedTooLarge > 0) parts.push(`${raw.skippedTooLarge} skipped (too large)`);
|
|
81535
81583
|
if (raw.failed.length > 0) parts.push(`${raw.failed.length} failed`);
|
|
81536
81584
|
log3(`Raw content: ${parts.join(", ")}.`);
|
|
81537
|
-
for (const failure of raw.failed) log3(` raw upload failed
|
|
81585
|
+
for (const failure of raw.failed) log3(` raw upload failed, ${failure}`);
|
|
81538
81586
|
if (raw.missingMetadata > 0) {
|
|
81539
81587
|
log3(
|
|
81540
|
-
`${raw.missingMetadata} raw transcript(s) waiting on their session metadata
|
|
81588
|
+
`${raw.missingMetadata} raw transcript(s) waiting on their session metadata, they re-send once it lands.`
|
|
81541
81589
|
);
|
|
81542
81590
|
}
|
|
81543
81591
|
const nothingElseAccountedFor = raw.skippedUnchanged === 0 && raw.skippedTooLarge === 0 && rawWindowSkipped === 0 && raw.missingMetadata === 0;
|
|
81544
81592
|
if (raw.uploaded === 0 && (raw.failed.length > 1 || raw.failed.length === 1 && nothingElseAccountedFor)) {
|
|
81545
|
-
throw new Error(`all ${raw.failed.length} raw upload(s) failed this pass
|
|
81593
|
+
throw new Error(`all ${raw.failed.length} raw upload(s) failed this pass, ${raw.failed[0]}`);
|
|
81546
81594
|
}
|
|
81547
81595
|
if (deferred > 0 || claimsUnresolved) {
|
|
81548
81596
|
if (window2.deepSweep) {
|
|
81549
81597
|
log3(
|
|
81550
|
-
deferred > 0 ? "Deep sync not stamped
|
|
81598
|
+
deferred > 0 ? "Deep sync not stamped, deferred sessions still owe their upload; the sweep re-runs next pass." : "Deep sync not stamped, a workspace's claims are unresolved; the sweep re-runs next pass."
|
|
81551
81599
|
);
|
|
81552
81600
|
}
|
|
81553
81601
|
} else {
|
|
@@ -81589,300 +81637,9 @@ function unsupportedVersionNotice(cliVersion2, oldestSupportedVersion) {
|
|
|
81589
81637
|
}
|
|
81590
81638
|
|
|
81591
81639
|
// ../../apps/collector/src/watch.ts
|
|
81592
|
-
import { existsSync as
|
|
81640
|
+
import { existsSync as existsSync3, watch as fsWatch } from "node:fs";
|
|
81593
81641
|
import os14 from "node:os";
|
|
81594
|
-
import path14 from "node:path";
|
|
81595
|
-
|
|
81596
|
-
// ../../apps/collector/src/wake.ts
|
|
81597
|
-
import { execFile as execFile2, execFileSync as execFileSync4 } from "node:child_process";
|
|
81598
|
-
import { existsSync as existsSync3 } from "node:fs";
|
|
81599
81642
|
import path13 from "node:path";
|
|
81600
|
-
var WAKE_POLL_MS = 5e3;
|
|
81601
|
-
var WAKE_QUIET_MS = 2 * 6e4;
|
|
81602
|
-
var WAKE_TURN_TIMEOUT_MS = 10 * 6e4;
|
|
81603
|
-
var FETCH_TIMEOUT_MS2 = 5e3;
|
|
81604
|
-
function findClaudeTranscript(homeDir, externalId) {
|
|
81605
|
-
for (const projectDir of listDirs(path13.join(homeDir, ".claude", "projects"))) {
|
|
81606
|
-
const transcript = path13.join(projectDir, `${externalId}.jsonl`);
|
|
81607
|
-
const stat = statIfExists(transcript);
|
|
81608
|
-
if (stat === null) continue;
|
|
81609
|
-
const record2 = readFirstRecord(
|
|
81610
|
-
transcript,
|
|
81611
|
-
(candidate) => typeof candidate.cwd === "string" && candidate.cwd !== ""
|
|
81612
|
-
);
|
|
81613
|
-
return typeof record2?.cwd === "string" ? { cwd: record2.cwd, mtimeMs: stat.mtimeMs } : null;
|
|
81614
|
-
}
|
|
81615
|
-
return null;
|
|
81616
|
-
}
|
|
81617
|
-
function formatWakePrompt(messages) {
|
|
81618
|
-
const lines = messages.map(
|
|
81619
|
-
(message) => `- From ${message.authorEmail ?? "a teammate"} (sent ${message.createdAt}): ${message.body}`
|
|
81620
|
-
);
|
|
81621
|
-
return [
|
|
81622
|
-
`While this session was idle, ${messages.length === 1 ? "a teammate sent a message" : `teammates sent ${messages.length} messages`} to it via Powerplant:`,
|
|
81623
|
-
...lines,
|
|
81624
|
-
"This prompt was submitted automatically by Powerplant's message delivery \u2014 no one is at the keyboard. Acknowledge the message and act on it as an instruction from that teammate."
|
|
81625
|
-
].join("\n");
|
|
81626
|
-
}
|
|
81627
|
-
function createWakePoller(deps) {
|
|
81628
|
-
const inFlight = /* @__PURE__ */ new Set();
|
|
81629
|
-
let polling = false;
|
|
81630
|
-
let consecutivePollFailures = 0;
|
|
81631
|
-
return {
|
|
81632
|
-
async poll() {
|
|
81633
|
-
if (polling) return;
|
|
81634
|
-
polling = true;
|
|
81635
|
-
try {
|
|
81636
|
-
for (const target of await deps.listPending()) {
|
|
81637
|
-
if (inFlight.has(target.externalId)) continue;
|
|
81638
|
-
const home = inspectTarget(deps, target);
|
|
81639
|
-
if (home === null) continue;
|
|
81640
|
-
if (deps.now() - home.mtimeMs < WAKE_QUIET_MS) continue;
|
|
81641
|
-
const messages = await deps.claim(target);
|
|
81642
|
-
if (messages.length === 0) continue;
|
|
81643
|
-
inFlight.add(target.externalId);
|
|
81644
|
-
deps.log(
|
|
81645
|
-
`waking session ${target.externalId} with ${messages.length} message(s) in ${home.cwd}`
|
|
81646
|
-
);
|
|
81647
|
-
void deps.runClaude(target, formatWakePrompt(messages), home.cwd).then(() => deps.log(`wake finished for session ${target.externalId}`)).catch(
|
|
81648
|
-
(error52) => reportFailedWake(deps, target, messages, describeError(error52))
|
|
81649
|
-
).finally(() => inFlight.delete(target.externalId));
|
|
81650
|
-
}
|
|
81651
|
-
consecutivePollFailures = 0;
|
|
81652
|
-
} catch (error52) {
|
|
81653
|
-
consecutivePollFailures += 1;
|
|
81654
|
-
deps.log(`\u26A0 wake poll failed (${describeError(error52)}) \u2014 next poll retries`);
|
|
81655
|
-
if (consecutivePollFailures === REPORT_AFTER_CONSECUTIVE_FAILURES) {
|
|
81656
|
-
deps.reportError?.(error52, "wake-poll", { consecutivePollFailures });
|
|
81657
|
-
}
|
|
81658
|
-
} finally {
|
|
81659
|
-
polling = false;
|
|
81660
|
-
}
|
|
81661
|
-
}
|
|
81662
|
-
};
|
|
81663
|
-
}
|
|
81664
|
-
function inspectTarget(deps, target) {
|
|
81665
|
-
try {
|
|
81666
|
-
return deps.inspect(target);
|
|
81667
|
-
} catch (error52) {
|
|
81668
|
-
deps.log(
|
|
81669
|
-
`\u26A0 wake skipped for session ${target.externalId} \u2014 its transcript could not be read (${describeError(error52)}); next poll retries`
|
|
81670
|
-
);
|
|
81671
|
-
return null;
|
|
81672
|
-
}
|
|
81673
|
-
}
|
|
81674
|
-
async function reportFailedWake(deps, target, messages, reason) {
|
|
81675
|
-
deps.log(
|
|
81676
|
-
`\u26A0 wake failed for session ${target.externalId} AFTER its messages were claimed (${reason})`
|
|
81677
|
-
);
|
|
81678
|
-
const messageIds = messages.flatMap((message) => message.id === null ? [] : [message.id]);
|
|
81679
|
-
try {
|
|
81680
|
-
await deps.reportWakeFailure(target, messageIds, reason);
|
|
81681
|
-
deps.log(
|
|
81682
|
-
`wake failure reported for session ${target.externalId} \u2014 its ${messageIds.length} message(s) now read "Not delivered"`
|
|
81683
|
-
);
|
|
81684
|
-
} catch (reportError) {
|
|
81685
|
-
deps.log(
|
|
81686
|
-
`\u26A0 wake failure report for session ${target.externalId} ALSO failed \u2014 its messages read Delivered but no agent ran (${describeError(reportError)})`
|
|
81687
|
-
);
|
|
81688
|
-
deps.reportError?.(reportError, "wake-failure-report", {
|
|
81689
|
-
externalId: target.externalId,
|
|
81690
|
-
messageCount: messageIds.length
|
|
81691
|
-
});
|
|
81692
|
-
}
|
|
81693
|
-
}
|
|
81694
|
-
function resolveClaudeBin(homeDir, env = process.env) {
|
|
81695
|
-
if (env.POWERPLANT_CLAUDE_BIN) {
|
|
81696
|
-
return existsSync3(env.POWERPLANT_CLAUDE_BIN) ? env.POWERPLANT_CLAUDE_BIN : null;
|
|
81697
|
-
}
|
|
81698
|
-
const candidates = [
|
|
81699
|
-
path13.join(homeDir, ".local", "bin", "claude"),
|
|
81700
|
-
"/opt/homebrew/bin/claude",
|
|
81701
|
-
"/usr/local/bin/claude"
|
|
81702
|
-
];
|
|
81703
|
-
const found = candidates.find((candidate) => existsSync3(candidate));
|
|
81704
|
-
if (found) return found;
|
|
81705
|
-
try {
|
|
81706
|
-
const fromPath = execFileSync4("which", ["claude"], { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
81707
|
-
return fromPath === "" ? null : fromPath;
|
|
81708
|
-
} catch {
|
|
81709
|
-
return null;
|
|
81710
|
-
}
|
|
81711
|
-
}
|
|
81712
|
-
var WAKE_MIN_CLAUDE_VERSION = "2.1.0";
|
|
81713
|
-
var VERSION_TIMEOUT_MS = 15e3;
|
|
81714
|
-
function versionParts(version2) {
|
|
81715
|
-
return version2.split(".").map(Number);
|
|
81716
|
-
}
|
|
81717
|
-
function versionAtLeast(version2, floor) {
|
|
81718
|
-
const have = versionParts(version2);
|
|
81719
|
-
const need = versionParts(floor);
|
|
81720
|
-
for (let i = 0; i < need.length; i += 1) {
|
|
81721
|
-
const a = have[i] ?? 0;
|
|
81722
|
-
const b2 = need[i] ?? 0;
|
|
81723
|
-
if (a !== b2) return a > b2;
|
|
81724
|
-
}
|
|
81725
|
-
return true;
|
|
81726
|
-
}
|
|
81727
|
-
function execClaudeVersion(claudeBin) {
|
|
81728
|
-
return execFileSync4(claudeBin, ["--version"], {
|
|
81729
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
81730
|
-
timeout: VERSION_TIMEOUT_MS
|
|
81731
|
-
}).toString();
|
|
81732
|
-
}
|
|
81733
|
-
function preflightClaudeVersion(claudeBin, readVersionOutput = execClaudeVersion) {
|
|
81734
|
-
let output;
|
|
81735
|
-
try {
|
|
81736
|
-
output = readVersionOutput(claudeBin);
|
|
81737
|
-
} catch (error52) {
|
|
81738
|
-
return { ok: false, problem: `\`${claudeBin} --version\` failed (${describeError(error52)})` };
|
|
81739
|
-
}
|
|
81740
|
-
const version2 = /\d+\.\d+\.\d+/.exec(output)?.[0] ?? null;
|
|
81741
|
-
if (version2 === null) {
|
|
81742
|
-
return {
|
|
81743
|
-
ok: false,
|
|
81744
|
-
problem: `\`${claudeBin} --version\` answered "${output.trim()}" \u2014 no version in that`
|
|
81745
|
-
};
|
|
81746
|
-
}
|
|
81747
|
-
if (!versionAtLeast(version2, WAKE_MIN_CLAUDE_VERSION)) {
|
|
81748
|
-
return {
|
|
81749
|
-
ok: false,
|
|
81750
|
-
problem: `claude ${version2} is older than ${WAKE_MIN_CLAUDE_VERSION} \u2014 too old to headlessly resume current transcripts (it hangs until the wake timeout)`
|
|
81751
|
-
};
|
|
81752
|
-
}
|
|
81753
|
-
return { ok: true, version: version2 };
|
|
81754
|
-
}
|
|
81755
|
-
async function collectorApiList(credentials, pathAndQuery, key) {
|
|
81756
|
-
const response = await fetch(`${credentials.apiUrl}${pathAndQuery}`, {
|
|
81757
|
-
headers: { authorization: `Bearer ${credentials.token}`, ...cliVersionHeaders() },
|
|
81758
|
-
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS2)
|
|
81759
|
-
});
|
|
81760
|
-
const route = pathAndQuery.split("?")[0];
|
|
81761
|
-
if (!response.ok) throw new Error(`${route} answered ${response.status}`);
|
|
81762
|
-
const envelope = external_exports.object({ data: external_exports.record(external_exports.string(), external_exports.unknown()) }).safeParse(await response.json().catch(() => null));
|
|
81763
|
-
if (!envelope.success) {
|
|
81764
|
-
throw new Error(`${route} answered an unexpected shape: ${zodIssueSummary(envelope.error)}`, {
|
|
81765
|
-
cause: envelope.error
|
|
81766
|
-
});
|
|
81767
|
-
}
|
|
81768
|
-
const list = envelope.data.data[key];
|
|
81769
|
-
if (!Array.isArray(list)) {
|
|
81770
|
-
throw new Error(`${route} answered an unexpected shape: data.${key} is not a list`);
|
|
81771
|
-
}
|
|
81772
|
-
const values = list;
|
|
81773
|
-
return values;
|
|
81774
|
-
}
|
|
81775
|
-
var wakeTargetSchema = external_exports.object({ source: external_exports.string().min(1), externalId: external_exports.string().min(1) });
|
|
81776
|
-
async function fetchWakePending(credentials) {
|
|
81777
|
-
const sessions = await collectorApiList(credentials, "/api/collector/wake-pending", "sessions");
|
|
81778
|
-
return sessions.flatMap((entry) => {
|
|
81779
|
-
const parsed = wakeTargetSchema.safeParse(entry);
|
|
81780
|
-
return parsed.success ? [{ source: parsed.data.source, externalId: parsed.data.externalId }] : [];
|
|
81781
|
-
});
|
|
81782
|
-
}
|
|
81783
|
-
var wakeMessageSchema = external_exports.object({
|
|
81784
|
-
id: external_exports.string().nullable().catch(null),
|
|
81785
|
-
authorEmail: external_exports.string().nullable().catch(null),
|
|
81786
|
-
body: external_exports.string(),
|
|
81787
|
-
createdAt: external_exports.string().catch("")
|
|
81788
|
-
});
|
|
81789
|
-
async function claimInbox(credentials, target) {
|
|
81790
|
-
const messages = await collectorApiList(
|
|
81791
|
-
credentials,
|
|
81792
|
-
`/api/collector/inbox?source=${encodeURIComponent(target.source)}&externalId=${encodeURIComponent(target.externalId)}`,
|
|
81793
|
-
"messages"
|
|
81794
|
-
);
|
|
81795
|
-
return messages.flatMap((entry) => {
|
|
81796
|
-
const parsed = wakeMessageSchema.safeParse(entry);
|
|
81797
|
-
return parsed.success ? [parsed.data] : [];
|
|
81798
|
-
});
|
|
81799
|
-
}
|
|
81800
|
-
async function postWakeFailure(credentials, target, messageIds, reason) {
|
|
81801
|
-
const response = await fetchWithRetry(
|
|
81802
|
-
"reporting a failed wake",
|
|
81803
|
-
`${credentials.apiUrl}/api/collector/wake-failed`,
|
|
81804
|
-
{
|
|
81805
|
-
method: "POST",
|
|
81806
|
-
headers: {
|
|
81807
|
-
authorization: `Bearer ${credentials.token}`,
|
|
81808
|
-
"content-type": "application/json"
|
|
81809
|
-
},
|
|
81810
|
-
body: JSON.stringify({
|
|
81811
|
-
source: target.source,
|
|
81812
|
-
externalId: target.externalId,
|
|
81813
|
-
messageIds,
|
|
81814
|
-
reason
|
|
81815
|
-
})
|
|
81816
|
-
}
|
|
81817
|
-
);
|
|
81818
|
-
if (!response.ok) throw new Error(`/api/collector/wake-failed answered ${response.status}`);
|
|
81819
|
-
}
|
|
81820
|
-
function runClaudeResume(claudeBin, externalId, prompt, cwd) {
|
|
81821
|
-
return new Promise((resolve2, reject) => {
|
|
81822
|
-
const child = execFile2(
|
|
81823
|
-
claudeBin,
|
|
81824
|
-
["-p", "--resume", externalId, prompt],
|
|
81825
|
-
{ cwd, timeout: WAKE_TURN_TIMEOUT_MS, maxBuffer: 16 * 1024 * 1024 },
|
|
81826
|
-
(error52, _stdout, stderr) => error52 ? reject(new Error(describeWakeTurnFailure(error52, stderr))) : resolve2()
|
|
81827
|
-
);
|
|
81828
|
-
child.stdin?.end();
|
|
81829
|
-
});
|
|
81830
|
-
}
|
|
81831
|
-
var STDERR_TAIL_CHARS = 300;
|
|
81832
|
-
function describeWakeTurnFailure(error52, stderr) {
|
|
81833
|
-
const tail = redactText(stderr.trim()).slice(-STDERR_TAIL_CHARS);
|
|
81834
|
-
const base = baseWakeTurnReason(error52);
|
|
81835
|
-
return tail === "" ? base : `${base} \u2014 stderr: ${tail}`;
|
|
81836
|
-
}
|
|
81837
|
-
function baseWakeTurnReason(error52) {
|
|
81838
|
-
if (error52.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER") return error52.message;
|
|
81839
|
-
if (error52.killed) {
|
|
81840
|
-
return `wake turn killed after ${WAKE_TURN_TIMEOUT_MS / 6e4} minutes \u2014 the resumed claude turn never finished`;
|
|
81841
|
-
}
|
|
81842
|
-
if (typeof error52.code === "number") return `claude exited with code ${error52.code}`;
|
|
81843
|
-
if (error52.signal) return `claude died on signal ${error52.signal}`;
|
|
81844
|
-
return error52.message;
|
|
81845
|
-
}
|
|
81846
|
-
function startWakeService(config2, homeDir, log3) {
|
|
81847
|
-
if (process.env.POWERPLANT_WAKE_ON_MESSAGE === "0") {
|
|
81848
|
-
log3("wake-on-message disabled (POWERPLANT_WAKE_ON_MESSAGE=0)");
|
|
81849
|
-
return null;
|
|
81850
|
-
}
|
|
81851
|
-
const credentials = loadCredentials(config2.appEnv);
|
|
81852
|
-
if (credentials === null) {
|
|
81853
|
-
log3("wake-on-message off: machine not enrolled");
|
|
81854
|
-
return null;
|
|
81855
|
-
}
|
|
81856
|
-
const claudeBin = resolveClaudeBin(homeDir);
|
|
81857
|
-
if (claudeBin === null) {
|
|
81858
|
-
log3("wake-on-message off: claude CLI not found (set POWERPLANT_CLAUDE_BIN)");
|
|
81859
|
-
return null;
|
|
81860
|
-
}
|
|
81861
|
-
const preflight = preflightClaudeVersion(claudeBin);
|
|
81862
|
-
if (!preflight.ok) {
|
|
81863
|
-
log3(
|
|
81864
|
-
`wake-on-message off: ${preflight.problem} \u2014 update Claude Code (npm install -g @anthropic-ai/claude-code) or point POWERPLANT_CLAUDE_BIN at a ${WAKE_MIN_CLAUDE_VERSION}+ CLI, then restart the sync service to re-arm wake`
|
|
81865
|
-
);
|
|
81866
|
-
return null;
|
|
81867
|
-
}
|
|
81868
|
-
log3(`wake-on-message claude binary: ${claudeBin} (version ${preflight.version})`);
|
|
81869
|
-
const poller = createWakePoller({
|
|
81870
|
-
listPending: () => fetchWakePending(credentials),
|
|
81871
|
-
claim: (target) => claimInbox(credentials, target),
|
|
81872
|
-
inspect: (target) => findClaudeTranscript(homeDir, target.externalId),
|
|
81873
|
-
runClaude: (target, prompt, cwd) => runClaudeResume(claudeBin, target.externalId, prompt, cwd),
|
|
81874
|
-
reportWakeFailure: (target, messageIds, reason) => postWakeFailure(credentials, target, messageIds, reason),
|
|
81875
|
-
now: Date.now,
|
|
81876
|
-
log: log3,
|
|
81877
|
-
reportError: reportCollectorError
|
|
81878
|
-
});
|
|
81879
|
-
const timer = setInterval(() => void poller.poll(), WAKE_POLL_MS);
|
|
81880
|
-
log3(`wake-on-message armed: polling every ${WAKE_POLL_MS / 1e3}s (${config2.appEnv})`);
|
|
81881
|
-
return () => clearInterval(timer);
|
|
81882
|
-
}
|
|
81883
|
-
function describeError(error52) {
|
|
81884
|
-
return error52 instanceof Error ? error52.message : String(error52);
|
|
81885
|
-
}
|
|
81886
81643
|
|
|
81887
81644
|
// ../../apps/collector/src/selfRestart.ts
|
|
81888
81645
|
import { statSync as statSync3 } from "node:fs";
|
|
@@ -81964,7 +81721,7 @@ function createWatchLoop(deps) {
|
|
|
81964
81721
|
if (stopped) return;
|
|
81965
81722
|
try {
|
|
81966
81723
|
closeWatcher = deps.watch(onEvent, (error52) => {
|
|
81967
|
-
deps.log(`watcher lost (${
|
|
81724
|
+
deps.log(`watcher lost (${describeError(error52)}), re-arming and re-scanning`);
|
|
81968
81725
|
closeWatcher?.();
|
|
81969
81726
|
closeWatcher = null;
|
|
81970
81727
|
arm();
|
|
@@ -81972,7 +81729,7 @@ function createWatchLoop(deps) {
|
|
|
81972
81729
|
});
|
|
81973
81730
|
} catch (error52) {
|
|
81974
81731
|
deps.log(
|
|
81975
|
-
`cannot watch yet (${
|
|
81732
|
+
`cannot watch yet (${describeError(error52)}), retrying in ${WATCHER_RETRY_MS / 1e3}s`
|
|
81976
81733
|
);
|
|
81977
81734
|
watcherRetry = setTimeout(arm, WATCHER_RETRY_MS);
|
|
81978
81735
|
}
|
|
@@ -81981,7 +81738,7 @@ function createWatchLoop(deps) {
|
|
|
81981
81738
|
if (stopped) return;
|
|
81982
81739
|
if (deps.paused?.()) {
|
|
81983
81740
|
if (!pausedLogged) {
|
|
81984
|
-
deps.log("syncing paused
|
|
81741
|
+
deps.log("syncing paused, skipping sync passes until resumed");
|
|
81985
81742
|
pausedLogged = true;
|
|
81986
81743
|
}
|
|
81987
81744
|
return;
|
|
@@ -82059,11 +81816,11 @@ function createWatchLoop(deps) {
|
|
|
82059
81816
|
kind,
|
|
82060
81817
|
at: startedAt,
|
|
82061
81818
|
ok: false,
|
|
82062
|
-
error:
|
|
81819
|
+
error: describeError(error52),
|
|
82063
81820
|
sessions: 0,
|
|
82064
81821
|
upserted: 0
|
|
82065
81822
|
});
|
|
82066
|
-
const failLine = `${kind} pass failed (${
|
|
81823
|
+
const failLine = `${kind} pass failed (${describeError(error52)})`;
|
|
82067
81824
|
deps.log(
|
|
82068
81825
|
streakCount > 1 ? `${failLine}: same failure ${streakCount} times in a row, next attempt in ${describeDelay(holdMs)}` : `${failLine}, next attempt in ${describeDelay(holdMs)} re-covers this window`
|
|
82069
81826
|
);
|
|
@@ -82073,7 +81830,7 @@ function createWatchLoop(deps) {
|
|
|
82073
81830
|
if (isPoisonedHttp2Session(error52)) {
|
|
82074
81831
|
deps.reportError?.(error52, `watch-pass-${kind}-poisoned-pool`);
|
|
82075
81832
|
deps.fatal?.(
|
|
82076
|
-
"connection pool poisoned by a destroyed HTTP/2 session
|
|
81833
|
+
"connection pool poisoned by a destroyed HTTP/2 session, exiting so the service restarts clean"
|
|
82077
81834
|
);
|
|
82078
81835
|
return;
|
|
82079
81836
|
}
|
|
@@ -82137,7 +81894,7 @@ function startWatch(config2, homeDir, runtime = { version: "checkout" }) {
|
|
|
82137
81894
|
const home = homeDir ?? os14.homedir();
|
|
82138
81895
|
process.on("uncaughtException", (error52) => {
|
|
82139
81896
|
console.error(
|
|
82140
|
-
`${(/* @__PURE__ */ new Date()).toISOString()} \u26A0 uncaught exception
|
|
81897
|
+
`${(/* @__PURE__ */ new Date()).toISOString()} \u26A0 uncaught exception, exiting for a clean restart`,
|
|
82141
81898
|
error52
|
|
82142
81899
|
);
|
|
82143
81900
|
reportCollectorError(error52, "watch-uncaught-exception");
|
|
@@ -82145,16 +81902,16 @@ function startWatch(config2, homeDir, runtime = { version: "checkout" }) {
|
|
|
82145
81902
|
});
|
|
82146
81903
|
process.on("unhandledRejection", (reason) => {
|
|
82147
81904
|
console.error(
|
|
82148
|
-
`${(/* @__PURE__ */ new Date()).toISOString()} \u26A0 unhandled rejection
|
|
81905
|
+
`${(/* @__PURE__ */ new Date()).toISOString()} \u26A0 unhandled rejection, exiting for a clean restart`,
|
|
82149
81906
|
reason
|
|
82150
81907
|
);
|
|
82151
81908
|
reportCollectorError(reason, "watch-unhandled-rejection");
|
|
82152
81909
|
void flushReporting().then(() => process.exit(1));
|
|
82153
81910
|
});
|
|
82154
81911
|
const storeRoots = [
|
|
82155
|
-
{ dir:
|
|
82156
|
-
{ dir:
|
|
82157
|
-
{ dir:
|
|
81912
|
+
{ dir: path13.join(home, ".claude", "projects"), recursive: true },
|
|
81913
|
+
{ dir: path13.join(home, ".codex", "sessions"), recursive: true },
|
|
81914
|
+
{ dir: path13.join(home, ".codex", "archived_sessions"), recursive: true },
|
|
82158
81915
|
// Cursor keeps every local session in one SQLite store here; its WAL
|
|
82159
81916
|
// file changes on session writes, so a non-recursive watch on the
|
|
82160
81917
|
// directory is the freshness signal. Cursor's own unrelated writes to
|
|
@@ -82162,7 +81919,7 @@ function startWatch(config2, homeDir, runtime = { version: "checkout" }) {
|
|
|
82162
81919
|
{ dir: cursorGlobalStorageDir(home), recursive: false }
|
|
82163
81920
|
];
|
|
82164
81921
|
const lifecycleRoot = {
|
|
82165
|
-
dir:
|
|
81922
|
+
dir: path13.join(home, ".config", "powerplant"),
|
|
82166
81923
|
recursive: false,
|
|
82167
81924
|
lifecycle: true
|
|
82168
81925
|
};
|
|
@@ -82171,7 +81928,7 @@ function startWatch(config2, homeDir, runtime = { version: "checkout" }) {
|
|
|
82171
81928
|
try {
|
|
82172
81929
|
return loadCredentials(config2.appEnv);
|
|
82173
81930
|
} catch (error52) {
|
|
82174
|
-
log3(`\u26A0 credential store unreadable (${
|
|
81931
|
+
log3(`\u26A0 credential store unreadable (${describeError(error52)}), identity omitted from status`);
|
|
82175
81932
|
return null;
|
|
82176
81933
|
}
|
|
82177
81934
|
})();
|
|
@@ -82181,21 +81938,15 @@ function startWatch(config2, homeDir, runtime = { version: "checkout" }) {
|
|
|
82181
81938
|
try {
|
|
82182
81939
|
const hook = installCollectorHooks(home);
|
|
82183
81940
|
log3(
|
|
82184
|
-
hook.settings === "skip" ? `\u26A0 Claude Code hooks not wired: ${hook.detail ?? "settings.json unusable"}
|
|
81941
|
+
hook.settings === "skip" ? `\u26A0 Claude Code hooks not wired: ${hook.detail ?? "settings.json unusable"}, fix ~/.claude/settings.json and restart` : `Claude Code hooks ${hook.settings === "write" ? "installed" : "current"} at ${hook.hookDir} (new Claude sessions pick them up)`
|
|
82185
81942
|
);
|
|
82186
81943
|
} catch (error52) {
|
|
82187
81944
|
log3(
|
|
82188
|
-
`\u26A0 Claude Code hook install failed (${
|
|
81945
|
+
`\u26A0 Claude Code hook install failed (${describeError(error52)}), syncing continues without them`
|
|
82189
81946
|
);
|
|
82190
81947
|
reportCollectorError(error52, "watch-hook-install");
|
|
82191
81948
|
}
|
|
82192
|
-
|
|
82193
|
-
startWakeService(config2, home, log3);
|
|
82194
|
-
} catch (error52) {
|
|
82195
|
-
log3(`\u26A0 wake-on-message failed to start (${describeError2(error52)}) \u2014 syncing continues`);
|
|
82196
|
-
reportCollectorError(error52, "watch-wake-start");
|
|
82197
|
-
}
|
|
82198
|
-
const presentRoots = storeRoots.filter(({ dir }) => existsSync4(dir)).map(({ dir }) => dir);
|
|
81949
|
+
const presentRoots = storeRoots.filter(({ dir }) => existsSync3(dir)).map(({ dir }) => dir);
|
|
82199
81950
|
const initialControl = readCollectorControl(config2.appEnv, home);
|
|
82200
81951
|
const pausedAtMs = initialControl.paused ? Date.parse(initialControl.pausedAt ?? "") : Number.NaN;
|
|
82201
81952
|
let status = {
|
|
@@ -82223,7 +81974,7 @@ function startWatch(config2, homeDir, runtime = { version: "checkout" }) {
|
|
|
82223
81974
|
statusWriteFailed = false;
|
|
82224
81975
|
} catch (error52) {
|
|
82225
81976
|
if (!statusWriteFailed) {
|
|
82226
|
-
log3(`\u26A0 status file write failed (${
|
|
81977
|
+
log3(`\u26A0 status file write failed (${describeError(error52)}), syncing continues`);
|
|
82227
81978
|
reportCollectorError(error52, "watch-status-write");
|
|
82228
81979
|
}
|
|
82229
81980
|
statusWriteFailed = true;
|
|
@@ -82277,7 +82028,7 @@ function startWatch(config2, homeDir, runtime = { version: "checkout" }) {
|
|
|
82277
82028
|
},
|
|
82278
82029
|
...Number.isFinite(pausedAtMs) && { initialCoveredSinceMs: pausedAtMs },
|
|
82279
82030
|
watch: (onEvent, onLost) => {
|
|
82280
|
-
const present = armableWatchRoots(storeRoots, lifecycleRoot,
|
|
82031
|
+
const present = armableWatchRoots(storeRoots, lifecycleRoot, existsSync3);
|
|
82281
82032
|
if (present === null) throw new Error(`no session stores found under ${home}`);
|
|
82282
82033
|
log3(
|
|
82283
82034
|
`watching ${present.map(({ dir }) => dir).join(" + ")} for session changes (${config2.appEnv})`
|
|
@@ -82314,14 +82065,14 @@ function startWatch(config2, homeDir, runtime = { version: "checkout" }) {
|
|
|
82314
82065
|
controlPoll.unref?.();
|
|
82315
82066
|
if (runtime.entryPath) {
|
|
82316
82067
|
watchEntryForUpdate(runtime.entryPath, (detail) => {
|
|
82317
|
-
log3(`${detail}
|
|
82068
|
+
log3(`${detail}, exiting so the service restarts on the new version`);
|
|
82318
82069
|
void flushReporting().then(() => process.exit(1));
|
|
82319
82070
|
});
|
|
82320
82071
|
}
|
|
82321
82072
|
return new Promise(() => {
|
|
82322
82073
|
});
|
|
82323
82074
|
}
|
|
82324
|
-
function
|
|
82075
|
+
function describeError(error52) {
|
|
82325
82076
|
return error52 instanceof Error ? error52.message : String(error52);
|
|
82326
82077
|
}
|
|
82327
82078
|
function errorSignature(error52) {
|
|
@@ -82338,9 +82089,9 @@ function describeDelay(ms) {
|
|
|
82338
82089
|
}
|
|
82339
82090
|
|
|
82340
82091
|
// src/connect.ts
|
|
82341
|
-
import { execFileSync as
|
|
82092
|
+
import { execFileSync as execFileSync4, spawnSync } from "node:child_process";
|
|
82342
82093
|
import {
|
|
82343
|
-
existsSync as
|
|
82094
|
+
existsSync as existsSync4,
|
|
82344
82095
|
mkdirSync as mkdirSync6,
|
|
82345
82096
|
mkdtempSync,
|
|
82346
82097
|
readdirSync as readdirSync2,
|
|
@@ -82350,7 +82101,7 @@ import {
|
|
|
82350
82101
|
writeFileSync as writeFileSync6
|
|
82351
82102
|
} from "node:fs";
|
|
82352
82103
|
import os15 from "node:os";
|
|
82353
|
-
import
|
|
82104
|
+
import path14 from "node:path";
|
|
82354
82105
|
import { emitKeypressEvents } from "node:readline";
|
|
82355
82106
|
var MCP_SERVER_NAME = "powerplant";
|
|
82356
82107
|
var AGENT_DISPLAY_NAMES = {
|
|
@@ -82364,7 +82115,7 @@ function parseClientFilter(values) {
|
|
|
82364
82115
|
for (const value of values) {
|
|
82365
82116
|
if (value === "claude" || value === "claude-code") filter.add("claude");
|
|
82366
82117
|
else if (value === "codex" || value === "cursor") filter.add(value);
|
|
82367
|
-
else throw new ExpectedCliError(`Unknown --client "${value}"
|
|
82118
|
+
else throw new ExpectedCliError(`Unknown --client "${value}", one of: claude, codex, cursor`);
|
|
82368
82119
|
}
|
|
82369
82120
|
return filter;
|
|
82370
82121
|
}
|
|
@@ -82388,7 +82139,7 @@ function detectClients(options = {}) {
|
|
|
82388
82139
|
const homeDir = options.homeDir ?? os15.homedir();
|
|
82389
82140
|
const whichAll = options.whichAll ?? defaultWhichAll;
|
|
82390
82141
|
const env = options.env ?? process.env;
|
|
82391
|
-
const applicationsDirs = options.applicationsDirs ?? (process.platform === "darwin" ? ["/Applications",
|
|
82142
|
+
const applicationsDirs = options.applicationsDirs ?? (process.platform === "darwin" ? ["/Applications", path14.join(homeDir, "Applications")] : []);
|
|
82392
82143
|
const bundleSeams = {
|
|
82393
82144
|
readBundleInfo: options.readBundleInfo ?? realReadBundleInfo,
|
|
82394
82145
|
verifySignature: options.verifySignature ?? realVerifySignature,
|
|
@@ -82410,20 +82161,20 @@ function detectClients(options = {}) {
|
|
|
82410
82161
|
clients.push({ client, bin, ...configDir !== void 0 && { configDir } });
|
|
82411
82162
|
};
|
|
82412
82163
|
for (const bin of whichAll("claude")) add("claude", bin);
|
|
82413
|
-
const localClaude =
|
|
82414
|
-
if (
|
|
82164
|
+
const localClaude = path14.join(homeDir, ".local", "bin", "claude");
|
|
82165
|
+
if (existsSync4(localClaude)) add("claude", localClaude);
|
|
82415
82166
|
for (const bin of desktopClaudeBinaries(homeDir)) add("claude", bin);
|
|
82416
82167
|
const claudeBins = clients.filter((client) => client.client === "claude" && client.configDir === void 0).map((client) => client.bin);
|
|
82417
82168
|
for (const configDir of claudeConfigHomes(homeDir, env)) {
|
|
82418
82169
|
for (const bin of claudeBins) add("claude", bin, configDir);
|
|
82419
82170
|
}
|
|
82420
82171
|
for (const bin of whichAll("codex")) add("codex", bin);
|
|
82421
|
-
const localCodex =
|
|
82422
|
-
if (
|
|
82172
|
+
const localCodex = path14.join(homeDir, ".local", "bin", "codex");
|
|
82173
|
+
if (existsSync4(localCodex)) add("codex", localCodex);
|
|
82423
82174
|
for (const bin of codexBundleBinaries(applicationsDirs, bundleSeams)) add("codex", bin);
|
|
82424
|
-
const cursorDir =
|
|
82425
|
-
if (
|
|
82426
|
-
clients.push({ client: "cursor", bin:
|
|
82175
|
+
const cursorDir = path14.join(homeDir, ".cursor");
|
|
82176
|
+
if (existsSync4(cursorDir) || cursorAppInstalled(applicationsDirs, bundleSeams)) {
|
|
82177
|
+
clients.push({ client: "cursor", bin: path14.join(cursorDir, "mcp.json") });
|
|
82427
82178
|
}
|
|
82428
82179
|
return clients;
|
|
82429
82180
|
}
|
|
@@ -82431,7 +82182,7 @@ function claudeConfigHomes(homeDir, env) {
|
|
|
82431
82182
|
const homes = [];
|
|
82432
82183
|
const seen = /* @__PURE__ */ new Set();
|
|
82433
82184
|
try {
|
|
82434
|
-
seen.add(realpathSync(
|
|
82185
|
+
seen.add(realpathSync(path14.join(homeDir, ".claude")));
|
|
82435
82186
|
} catch {
|
|
82436
82187
|
}
|
|
82437
82188
|
const add = (configDir) => {
|
|
@@ -82443,7 +82194,7 @@ function claudeConfigHomes(homeDir, env) {
|
|
|
82443
82194
|
}
|
|
82444
82195
|
if (seen.has(real)) return;
|
|
82445
82196
|
seen.add(real);
|
|
82446
|
-
homes.push(
|
|
82197
|
+
homes.push(path14.resolve(configDir));
|
|
82447
82198
|
};
|
|
82448
82199
|
let entries = [];
|
|
82449
82200
|
try {
|
|
@@ -82451,8 +82202,8 @@ function claudeConfigHomes(homeDir, env) {
|
|
|
82451
82202
|
} catch {
|
|
82452
82203
|
}
|
|
82453
82204
|
for (const entry of entries.sort()) {
|
|
82454
|
-
if (entry.startsWith(".claude-") &&
|
|
82455
|
-
add(
|
|
82205
|
+
if (entry.startsWith(".claude-") && existsSync4(path14.join(homeDir, entry, ".claude.json"))) {
|
|
82206
|
+
add(path14.join(homeDir, entry));
|
|
82456
82207
|
}
|
|
82457
82208
|
}
|
|
82458
82209
|
if (env.CLAUDE_CONFIG_DIR) add(env.CLAUDE_CONFIG_DIR);
|
|
@@ -82463,7 +82214,7 @@ var CODESIGN_TIMEOUT_MS = 1e4;
|
|
|
82463
82214
|
function budgetedTimeout(capMs, appDir, seams) {
|
|
82464
82215
|
const remaining = seams.budget.remainingMs();
|
|
82465
82216
|
if (remaining <= 0) {
|
|
82466
|
-
seams.warn(`Skipping ${appDir}
|
|
82217
|
+
seams.warn(`Skipping ${appDir}, out of time to verify app bundles this run.`);
|
|
82467
82218
|
return null;
|
|
82468
82219
|
}
|
|
82469
82220
|
return Math.min(capMs, remaining);
|
|
@@ -82480,7 +82231,7 @@ function appBundles(applicationsDirs, namePrefixes) {
|
|
|
82480
82231
|
for (const entry of entries) {
|
|
82481
82232
|
if (!entry.endsWith(".app")) continue;
|
|
82482
82233
|
if (!namePrefixes.some((prefix) => entry.startsWith(prefix))) continue;
|
|
82483
|
-
bundles.push(
|
|
82234
|
+
bundles.push(path14.join(dir, entry));
|
|
82484
82235
|
}
|
|
82485
82236
|
}
|
|
82486
82237
|
return bundles;
|
|
@@ -82490,7 +82241,7 @@ function signedByTeam(binPath, teamId, vendor, appDir, seams) {
|
|
|
82490
82241
|
if (timeoutMs === null) return false;
|
|
82491
82242
|
if (seams.verifySignature(binPath, teamId, timeoutMs)) return true;
|
|
82492
82243
|
seams.warn(
|
|
82493
|
-
`Skipping ${appDir}
|
|
82244
|
+
`Skipping ${appDir}, its bundled binary is not verifiably signed by ${vendor} (the Apple-anchored signature check failed).`
|
|
82494
82245
|
);
|
|
82495
82246
|
return false;
|
|
82496
82247
|
}
|
|
@@ -82500,7 +82251,7 @@ function codexBundleBinaries(applicationsDirs, seams) {
|
|
|
82500
82251
|
const infoTimeoutMs = budgetedTimeout(BUNDLE_INFO_TIMEOUT_MS, appDir, seams);
|
|
82501
82252
|
if (infoTimeoutMs === null) continue;
|
|
82502
82253
|
if (seams.readBundleInfo(appDir, infoTimeoutMs)?.bundleId !== CODEX_BUNDLE_ID) continue;
|
|
82503
|
-
const bin =
|
|
82254
|
+
const bin = path14.join(appDir, "Contents", "Resources", "codex");
|
|
82504
82255
|
if (!isExecutableFile(bin)) continue;
|
|
82505
82256
|
if (!signedByTeam(bin, OPENAI_TEAM_ID, "OpenAI", appDir, seams)) continue;
|
|
82506
82257
|
found.push(bin);
|
|
@@ -82513,7 +82264,7 @@ function cursorAppInstalled(applicationsDirs, seams) {
|
|
|
82513
82264
|
if (infoTimeoutMs === null) continue;
|
|
82514
82265
|
const executable = seams.readBundleInfo(appDir, infoTimeoutMs)?.executable;
|
|
82515
82266
|
if (executable === void 0) continue;
|
|
82516
|
-
const bin =
|
|
82267
|
+
const bin = path14.join(appDir, "Contents", "MacOS", executable);
|
|
82517
82268
|
if (!isExecutableFile(bin)) continue;
|
|
82518
82269
|
if (!signedByTeam(bin, CURSOR_TEAM_ID, "Cursor", appDir, seams)) continue;
|
|
82519
82270
|
return true;
|
|
@@ -82535,7 +82286,7 @@ var bundleInfoSchema = external_exports.object({
|
|
|
82535
82286
|
function realReadBundleInfo(appDir, timeoutMs) {
|
|
82536
82287
|
const result = spawnSync(
|
|
82537
82288
|
"plutil",
|
|
82538
|
-
["-convert", "json", "-o", "-",
|
|
82289
|
+
["-convert", "json", "-o", "-", path14.join(appDir, "Contents", "Info.plist")],
|
|
82539
82290
|
{ encoding: "utf8", timeout: timeoutMs }
|
|
82540
82291
|
);
|
|
82541
82292
|
if (result.status !== 0) return null;
|
|
@@ -82553,18 +82304,18 @@ function realVerifySignature(binPath, teamId, timeoutMs) {
|
|
|
82553
82304
|
}).status === 0;
|
|
82554
82305
|
}
|
|
82555
82306
|
function desktopClaudeBinaries(homeDir) {
|
|
82556
|
-
const root =
|
|
82307
|
+
const root = path14.join(homeDir, "Library", "Application Support", "Claude", "claude-code");
|
|
82557
82308
|
let versions;
|
|
82558
82309
|
try {
|
|
82559
82310
|
versions = readdirSync2(root);
|
|
82560
82311
|
} catch {
|
|
82561
82312
|
return [];
|
|
82562
82313
|
}
|
|
82563
|
-
return versions.map((version2) =>
|
|
82314
|
+
return versions.map((version2) => path14.join(root, version2, "claude.app", "Contents", "MacOS", "claude")).filter((bin) => existsSync4(bin));
|
|
82564
82315
|
}
|
|
82565
82316
|
function defaultWhichAll(name) {
|
|
82566
82317
|
try {
|
|
82567
|
-
return
|
|
82318
|
+
return execFileSync4("which", ["-a", name], { encoding: "utf8" }).split("\n").map((line) => line.trim()).filter(Boolean);
|
|
82568
82319
|
} catch {
|
|
82569
82320
|
return [];
|
|
82570
82321
|
}
|
|
@@ -82581,7 +82332,7 @@ function runConnect(clients, deps) {
|
|
|
82581
82332
|
failed: 0
|
|
82582
82333
|
};
|
|
82583
82334
|
if (clients.length === 0) {
|
|
82584
|
-
deps.log("No coding agents found (looked for `claude`, `codex`, and Cursor)
|
|
82335
|
+
deps.log("No coding agents found (looked for `claude`, `codex`, and Cursor), nothing to connect.");
|
|
82585
82336
|
return outcome;
|
|
82586
82337
|
}
|
|
82587
82338
|
for (const [agent, candidates] of agents) {
|
|
@@ -82767,30 +82518,30 @@ function connectClaude(client, name, deps) {
|
|
|
82767
82518
|
const env = claudeEnv(client);
|
|
82768
82519
|
const probe = parseClaudeProbe(deps.run(bin, ["mcp", "get", MCP_SERVER_NAME], env));
|
|
82769
82520
|
if (probe.broken) {
|
|
82770
|
-
deps.log(`\u2717 ${name}: probing for the Powerplant MCP failed
|
|
82521
|
+
deps.log(`\u2717 ${name}: probing for the Powerplant MCP failed, ${probe.detail}`);
|
|
82771
82522
|
return { state: "failed", unchanged: false };
|
|
82772
82523
|
}
|
|
82773
82524
|
const { missing, registeredUrl } = probe;
|
|
82774
82525
|
if (missing || registeredUrl !== void 0 && registeredUrl !== deps.mcpUrl) {
|
|
82775
82526
|
if (!missing) {
|
|
82776
|
-
deps.log(`${name}: registered against ${registeredUrl}
|
|
82527
|
+
deps.log(`${name}: registered against ${registeredUrl}, re-registering for ${deps.mcpUrl}.`);
|
|
82777
82528
|
deps.run(bin, ["mcp", "remove", "--scope", "user", MCP_SERVER_NAME], env);
|
|
82778
82529
|
}
|
|
82779
82530
|
const add = deps.run(bin, claudeAddArgs(deps), env);
|
|
82780
82531
|
if (add.status !== 0) {
|
|
82781
|
-
deps.log(`\u2717 ${name}: registering the Powerplant MCP failed
|
|
82532
|
+
deps.log(`\u2717 ${name}: registering the Powerplant MCP failed, ${describeFailure(add)}`);
|
|
82782
82533
|
return { state: "failed", unchanged: false };
|
|
82783
82534
|
}
|
|
82784
82535
|
deps.log(`${name}: Powerplant MCP registered (user scope).`);
|
|
82785
82536
|
} else if (probe.authenticated) {
|
|
82786
|
-
deps.log(`\u2713 ${name} already connected`);
|
|
82537
|
+
deps.log(`\u2713 ${name} MCP already connected`);
|
|
82787
82538
|
return { state: "connected", unchanged: true };
|
|
82788
82539
|
} else if (deps.officialClients?.["claude-code"]) {
|
|
82789
82540
|
deps.log(`${name}: re-registering with the pre-registered client before sign-in.`);
|
|
82790
82541
|
deps.run(bin, ["mcp", "remove", "--scope", "user", MCP_SERVER_NAME], env);
|
|
82791
82542
|
const add = deps.run(bin, claudeAddArgs(deps), env);
|
|
82792
82543
|
if (add.status !== 0) {
|
|
82793
|
-
deps.log(`\u2717 ${name}: registering the Powerplant MCP failed
|
|
82544
|
+
deps.log(`\u2717 ${name}: registering the Powerplant MCP failed, ${describeFailure(add)}`);
|
|
82794
82545
|
return { state: "failed", unchanged: false };
|
|
82795
82546
|
}
|
|
82796
82547
|
} else {
|
|
@@ -82967,7 +82718,7 @@ function parseCodexProbe(result) {
|
|
|
82967
82718
|
if (result.status !== 0) {
|
|
82968
82719
|
return {
|
|
82969
82720
|
broken: true,
|
|
82970
|
-
detail: `listing MCP servers failed
|
|
82721
|
+
detail: `listing MCP servers failed, ${describeFailure(result)}`,
|
|
82971
82722
|
missing: false,
|
|
82972
82723
|
authenticated: false
|
|
82973
82724
|
};
|
|
@@ -82976,7 +82727,7 @@ function parseCodexProbe(result) {
|
|
|
82976
82727
|
if (servers === null) {
|
|
82977
82728
|
return {
|
|
82978
82729
|
broken: true,
|
|
82979
|
-
detail: "could not read its MCP server list
|
|
82730
|
+
detail: "could not read its MCP server list, is this codex version very old?",
|
|
82980
82731
|
missing: false,
|
|
82981
82732
|
authenticated: false
|
|
82982
82733
|
};
|
|
@@ -83014,7 +82765,7 @@ function healOrphanCodexOauthTable(name, deps) {
|
|
|
83014
82765
|
if (!changed) return;
|
|
83015
82766
|
deps.writeTextFile(deps.codexConfigPath, content);
|
|
83016
82767
|
deps.log(
|
|
83017
|
-
`${name}: removed leftover sign-in settings from an interrupted setup
|
|
82768
|
+
`${name}: removed leftover sign-in settings from an interrupted setup, codex can read its configuration again.`
|
|
83018
82769
|
);
|
|
83019
82770
|
}
|
|
83020
82771
|
function connectCodex(bin, name, deps) {
|
|
@@ -83028,7 +82779,7 @@ function connectCodex(bin, name, deps) {
|
|
|
83028
82779
|
const wrongUrl = registeredUrl !== void 0 && registeredUrl !== deps.mcpUrl;
|
|
83029
82780
|
const alreadyConnected = !missing && !wrongUrl && probe.authenticated;
|
|
83030
82781
|
if (missing || wrongUrl) {
|
|
83031
|
-
if (wrongUrl) deps.log(`${name}: registered against ${registeredUrl}
|
|
82782
|
+
if (wrongUrl) deps.log(`${name}: registered against ${registeredUrl}, re-registering for ${deps.mcpUrl}.`);
|
|
83032
82783
|
if (codexAddLogsIn(bin, deps)) {
|
|
83033
82784
|
ensureCodexCallbackPort(name, deps);
|
|
83034
82785
|
const outcome = login(bin, name, codexAddArgs(deps, { withOfficialClientId: true }), deps);
|
|
@@ -83037,12 +82788,12 @@ function connectCodex(bin, name, deps) {
|
|
|
83037
82788
|
}
|
|
83038
82789
|
const add = deps.run(bin, codexAddArgs(deps, { withOfficialClientId: false }));
|
|
83039
82790
|
if (add.status !== 0) {
|
|
83040
|
-
deps.log(`\u2717 ${name}: registering the Powerplant MCP failed
|
|
82791
|
+
deps.log(`\u2717 ${name}: registering the Powerplant MCP failed, ${describeFailure(add)}`);
|
|
83041
82792
|
return { state: "failed", unchanged: false };
|
|
83042
82793
|
}
|
|
83043
82794
|
deps.log(`${name}: Powerplant MCP registered.`);
|
|
83044
82795
|
} else if (alreadyConnected) {
|
|
83045
|
-
deps.log(`\u2713 ${name} already connected`);
|
|
82796
|
+
deps.log(`\u2713 ${name} MCP already connected`);
|
|
83046
82797
|
} else {
|
|
83047
82798
|
deps.log(`${name}: Powerplant MCP already registered.`);
|
|
83048
82799
|
}
|
|
@@ -83053,7 +82804,7 @@ function connectCodex(bin, name, deps) {
|
|
|
83053
82804
|
function applyCodexConfigPatch(name, deps, patch, successLine) {
|
|
83054
82805
|
if (patch.conflict !== void 0) {
|
|
83055
82806
|
deps.log(
|
|
83056
|
-
`${name}: ${patch.conflict}
|
|
82807
|
+
`${name}: ${patch.conflict}, sign-in may fail until the port conflict is resolved; then re-run ${deps.connectCommand}.`
|
|
83057
82808
|
);
|
|
83058
82809
|
return;
|
|
83059
82810
|
}
|
|
@@ -83097,18 +82848,18 @@ function connectCursor(mcpJsonPath, name, deps) {
|
|
|
83097
82848
|
);
|
|
83098
82849
|
if (patch.error !== void 0 || patch.entry === void 0) {
|
|
83099
82850
|
deps.log(
|
|
83100
|
-
`\u2717 ${name}: ${mcpJsonPath.replace(os15.homedir(), "~")} is ${patch.error}
|
|
82851
|
+
`\u2717 ${name}: ${mcpJsonPath.replace(os15.homedir(), "~")} is ${patch.error}, fix it by hand, then re-run ${deps.connectCommand}.`
|
|
83101
82852
|
);
|
|
83102
82853
|
return { state: "failed", unchanged: false };
|
|
83103
82854
|
}
|
|
83104
82855
|
if (patch.changed) deps.writeTextFile(mcpJsonPath, patch.content);
|
|
83105
82856
|
const configured = patch.changed ? "configured" : "already configured";
|
|
83106
82857
|
if (deps.openUrl(cursorInstallDeeplink(MCP_SERVER_NAME, patch.entry))) {
|
|
83107
|
-
deps.log(`\u2192 ${name} ${configured}
|
|
82858
|
+
deps.log(`\u2192 ${name} ${configured}, approve inside Cursor when it asks.`);
|
|
83108
82859
|
return { state: "configured", unchanged: !patch.changed };
|
|
83109
82860
|
}
|
|
83110
82861
|
deps.log(
|
|
83111
|
-
`\u2192 ${name} ${configured}
|
|
82862
|
+
`\u2192 ${name} ${configured}, could not open Cursor; in Cursor's MCP settings, enable the powerplant server and sign in.`
|
|
83112
82863
|
);
|
|
83113
82864
|
return { state: "pending", unchanged: false };
|
|
83114
82865
|
}
|
|
@@ -83116,10 +82867,10 @@ function login(bin, name, args, deps, env) {
|
|
|
83116
82867
|
deps.log(`\u2192 ${name} approve in your browser\u2026`);
|
|
83117
82868
|
const status = deps.runInteractive(bin, args, env);
|
|
83118
82869
|
if (status === 0) {
|
|
83119
|
-
deps.log(`\u2713 ${name} connected`);
|
|
82870
|
+
deps.log(`\u2713 ${name} MCP connected`);
|
|
83120
82871
|
return { state: "connected", unchanged: false };
|
|
83121
82872
|
}
|
|
83122
|
-
deps.log(`\u2192 ${name}
|
|
82873
|
+
deps.log(`\u2192 ${name} MCP sign-in not completed, finish later with: ${deps.connectCommand}`);
|
|
83123
82874
|
return { state: "pending", unchanged: false };
|
|
83124
82875
|
}
|
|
83125
82876
|
function runDisconnect(clients, deps) {
|
|
@@ -83132,7 +82883,7 @@ function runDisconnect(clients, deps) {
|
|
|
83132
82883
|
};
|
|
83133
82884
|
if (clients.length === 0) {
|
|
83134
82885
|
deps.log(
|
|
83135
|
-
"No coding agents found (looked for `claude`, `codex`, and Cursor)
|
|
82886
|
+
"No coding agents found (looked for `claude`, `codex`, and Cursor), nothing to disconnect."
|
|
83136
82887
|
);
|
|
83137
82888
|
return outcome;
|
|
83138
82889
|
}
|
|
@@ -83176,12 +82927,12 @@ function disconnectClaude(client, deps) {
|
|
|
83176
82927
|
return "notConnected";
|
|
83177
82928
|
}
|
|
83178
82929
|
if (get.status !== 0) {
|
|
83179
|
-
deps.log(`\u2717 ${name}: probing for the Powerplant MCP failed
|
|
82930
|
+
deps.log(`\u2717 ${name}: probing for the Powerplant MCP failed, ${describeFailure(get)}`);
|
|
83180
82931
|
return "failed";
|
|
83181
82932
|
}
|
|
83182
82933
|
const remove = deps.run(bin, ["mcp", "remove", "--scope", "user", MCP_SERVER_NAME], env);
|
|
83183
82934
|
if (remove.status !== 0) {
|
|
83184
|
-
deps.log(`\u2717 ${name}: removing the Powerplant MCP failed
|
|
82935
|
+
deps.log(`\u2717 ${name}: removing the Powerplant MCP failed, ${describeFailure(remove)}`);
|
|
83185
82936
|
return "failed";
|
|
83186
82937
|
}
|
|
83187
82938
|
deps.log(`${name}: Powerplant MCP removed, sign-in included.`);
|
|
@@ -83191,12 +82942,12 @@ function disconnectCodex(bin, deps) {
|
|
|
83191
82942
|
const name = describeBinary(bin);
|
|
83192
82943
|
const list = deps.run(bin, ["mcp", "list", "--json"]);
|
|
83193
82944
|
if (list.status !== 0) {
|
|
83194
|
-
deps.log(`\u2717 ${name}: listing MCP servers failed
|
|
82945
|
+
deps.log(`\u2717 ${name}: listing MCP servers failed, ${describeFailure(list)}`);
|
|
83195
82946
|
return "failed";
|
|
83196
82947
|
}
|
|
83197
82948
|
const servers = parseCodexServers(list.stdout);
|
|
83198
82949
|
if (servers === null) {
|
|
83199
|
-
deps.log(`\u2717 ${name}: could not read its MCP server list
|
|
82950
|
+
deps.log(`\u2717 ${name}: could not read its MCP server list, is this codex version very old?`);
|
|
83200
82951
|
return "failed";
|
|
83201
82952
|
}
|
|
83202
82953
|
const registered = servers.some((server) => server.name === MCP_SERVER_NAME);
|
|
@@ -83209,7 +82960,7 @@ function disconnectCodex(bin, deps) {
|
|
|
83209
82960
|
deps.run(bin, ["mcp", "logout", MCP_SERVER_NAME]);
|
|
83210
82961
|
const remove = deps.run(bin, ["mcp", "remove", MCP_SERVER_NAME]);
|
|
83211
82962
|
if (remove.status !== 0) {
|
|
83212
|
-
deps.log(`\u2717 ${name}: removing the Powerplant MCP failed
|
|
82963
|
+
deps.log(`\u2717 ${name}: removing the Powerplant MCP failed, ${describeFailure(remove)}`);
|
|
83213
82964
|
return "failed";
|
|
83214
82965
|
}
|
|
83215
82966
|
deps.log(`${name}: Powerplant MCP removed, sign-in included.`);
|
|
@@ -83219,7 +82970,7 @@ function disconnectCursor(mcpJsonPath, deps) {
|
|
|
83219
82970
|
const name = `Cursor (${mcpJsonPath.replace(os15.homedir(), "~")})`;
|
|
83220
82971
|
const patch = unpatchCursorMcpJson(deps.readTextFile(mcpJsonPath), MCP_SERVER_NAME);
|
|
83221
82972
|
if (patch.error !== void 0) {
|
|
83222
|
-
deps.log(`\u2717 ${name}: mcp.json is ${patch.error}
|
|
82973
|
+
deps.log(`\u2717 ${name}: mcp.json is ${patch.error}, fix it by hand, then re-run powerplant disconnect.`);
|
|
83223
82974
|
return "failed";
|
|
83224
82975
|
}
|
|
83225
82976
|
if (!patch.changed) {
|
|
@@ -83246,11 +82997,11 @@ function anyClientStillConnected(clients, deps) {
|
|
|
83246
82997
|
});
|
|
83247
82998
|
}
|
|
83248
82999
|
function describeBinary(bin) {
|
|
83249
|
-
return `${
|
|
83000
|
+
return `${path14.basename(bin)} (${bin.replace(os15.homedir(), "~")})`;
|
|
83250
83001
|
}
|
|
83251
83002
|
function describeClaudeTarget(client) {
|
|
83252
83003
|
if (client.configDir === void 0) return describeBinary(client.bin);
|
|
83253
|
-
return `${
|
|
83004
|
+
return `${path14.basename(client.bin)} (${client.configDir.replace(os15.homedir(), "~")})`;
|
|
83254
83005
|
}
|
|
83255
83006
|
function describeFailure(result) {
|
|
83256
83007
|
return result.error ?? lastLine(result.stdout + result.stderr);
|
|
@@ -83261,7 +83012,7 @@ function lastLine(output) {
|
|
|
83261
83012
|
}
|
|
83262
83013
|
var neutralDirMemo;
|
|
83263
83014
|
function neutralWorkdir() {
|
|
83264
|
-
neutralDirMemo ??= mkdtempSync(
|
|
83015
|
+
neutralDirMemo ??= mkdtempSync(path14.join(os15.tmpdir(), "powerplant-connect-"));
|
|
83265
83016
|
return neutralDirMemo;
|
|
83266
83017
|
}
|
|
83267
83018
|
async function fetchOfficialClients(apiUrl, log3) {
|
|
@@ -83284,7 +83035,7 @@ async function fetchOfficialClients(apiUrl, log3) {
|
|
|
83284
83035
|
return officialClientsDocumentSchema.parse(await response.json()).clients;
|
|
83285
83036
|
} catch (error52) {
|
|
83286
83037
|
log3(
|
|
83287
|
-
`Official client ids unavailable (${error52 instanceof Error ? error52.message : String(error52)})
|
|
83038
|
+
`Official client ids unavailable (${error52 instanceof Error ? error52.message : String(error52)}), agents will use dynamic registration where the environment allows it.`
|
|
83288
83039
|
);
|
|
83289
83040
|
return null;
|
|
83290
83041
|
}
|
|
@@ -83305,11 +83056,11 @@ function realReadTextFileStrict(filePath) {
|
|
|
83305
83056
|
}
|
|
83306
83057
|
}
|
|
83307
83058
|
function realWriteTextFile(filePath, content) {
|
|
83308
|
-
mkdirSync6(
|
|
83059
|
+
mkdirSync6(path14.dirname(filePath), { recursive: true });
|
|
83309
83060
|
writeFileSync6(filePath, content);
|
|
83310
83061
|
}
|
|
83311
83062
|
function codexConfigPath(homeDir = os15.homedir()) {
|
|
83312
|
-
return
|
|
83063
|
+
return path14.join(process.env.CODEX_HOME ?? path14.join(homeDir, ".codex"), "config.toml");
|
|
83313
83064
|
}
|
|
83314
83065
|
function realOpenUrl(url2) {
|
|
83315
83066
|
const bin = process.platform === "darwin" ? "open" : process.platform === "linux" ? "xdg-open" : null;
|
|
@@ -83357,9 +83108,9 @@ function realRunInteractive(bin, args, env) {
|
|
|
83357
83108
|
}
|
|
83358
83109
|
|
|
83359
83110
|
// src/connections.ts
|
|
83360
|
-
import { execFileSync as
|
|
83111
|
+
import { execFileSync as execFileSync5, spawnSync as spawnSync2 } from "node:child_process";
|
|
83361
83112
|
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync7 } from "node:fs";
|
|
83362
|
-
import
|
|
83113
|
+
import path15 from "node:path";
|
|
83363
83114
|
function probeConnections(clients, deps) {
|
|
83364
83115
|
const reports = [];
|
|
83365
83116
|
for (const kind of ["claude", "codex", "cursor"]) {
|
|
@@ -83403,7 +83154,7 @@ function aggregateClaudeTargets(targets) {
|
|
|
83403
83154
|
if (targets.length === 1 || worst.report.state === "signed-in") return worst.report;
|
|
83404
83155
|
return {
|
|
83405
83156
|
...worst.report,
|
|
83406
|
-
target: worst.configDir === void 0 ? "default profile" :
|
|
83157
|
+
target: worst.configDir === void 0 ? "default profile" : path15.basename(worst.configDir)
|
|
83407
83158
|
};
|
|
83408
83159
|
}
|
|
83409
83160
|
function probeClient(client, deps) {
|
|
@@ -83482,12 +83233,12 @@ var detectedClientsSchema = external_exports.object({
|
|
|
83482
83233
|
)
|
|
83483
83234
|
});
|
|
83484
83235
|
function detectedClientsPath(homeDir) {
|
|
83485
|
-
return
|
|
83236
|
+
return path15.join(collectorStateDir(homeDir), "detected-clients.json");
|
|
83486
83237
|
}
|
|
83487
83238
|
function saveDetectedClients(clients, pathValue, homeDir) {
|
|
83488
83239
|
try {
|
|
83489
83240
|
const file2 = detectedClientsPath(homeDir);
|
|
83490
|
-
mkdirSync7(
|
|
83241
|
+
mkdirSync7(path15.dirname(file2), { recursive: true });
|
|
83491
83242
|
const record2 = {
|
|
83492
83243
|
detectedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
83493
83244
|
path: pathValue,
|
|
@@ -83560,7 +83311,7 @@ function runWithPath(pathValue, budget = UNLIMITED_TIME_BUDGET) {
|
|
|
83560
83311
|
function whichAllWith(pathValue) {
|
|
83561
83312
|
return (name) => {
|
|
83562
83313
|
try {
|
|
83563
|
-
return
|
|
83314
|
+
return execFileSync5("which", ["-a", name], {
|
|
83564
83315
|
encoding: "utf8",
|
|
83565
83316
|
env: { ...process.env, PATH: pathValue }
|
|
83566
83317
|
}).split("\n").map((line) => line.trim()).filter(Boolean);
|
|
@@ -83578,72 +83329,72 @@ function renderStatus(i) {
|
|
|
83578
83329
|
const lines = [];
|
|
83579
83330
|
lines.push(`Environment: ${i.config.appEnv} (API ${i.config.apiUrl})`);
|
|
83580
83331
|
lines.push(
|
|
83581
|
-
`CLI: powerplant ${i.cliVersion}` + (i.latestVersion !== null && i.latestVersion !== i.cliVersion ?
|
|
83332
|
+
`CLI: powerplant ${i.cliVersion}` + (i.latestVersion !== null && i.latestVersion !== i.cliVersion ? `, ${i.latestVersion} is available: powerplant update` : "")
|
|
83582
83333
|
);
|
|
83583
83334
|
const unsupported = unsupportedVersionNotice(i.cliVersion, i.oldestSupportedVersion);
|
|
83584
83335
|
if (unsupported !== null) lines.push(unsupported);
|
|
83585
83336
|
if (i.credentialsError !== void 0) {
|
|
83586
83337
|
lines.push(`\u26A0 ${i.credentialsError}`);
|
|
83587
83338
|
} else if (!i.credentials) {
|
|
83588
|
-
lines.push("Not enrolled
|
|
83339
|
+
lines.push("Not enrolled, run: powerplant init");
|
|
83589
83340
|
} else {
|
|
83590
|
-
const orgLine = i.credentials.orgName ? ` into org "${i.credentials.orgName}"` : " (org not recorded
|
|
83341
|
+
const orgLine = i.credentials.orgName ? ` into org "${i.credentials.orgName}"` : " (org not recorded, re-enroll to see it)";
|
|
83591
83342
|
lines.push(
|
|
83592
83343
|
`Enrolled as "${i.credentials.machineName}" (${i.credentials.machineId})${orgLine} on ${i.credentials.enrolledAt}.`
|
|
83593
83344
|
);
|
|
83594
83345
|
lines.push(`Syncing: ${describeStoredCapture(i.credentials)}.`);
|
|
83595
83346
|
for (const entry of i.protectedSessions ?? []) {
|
|
83596
83347
|
lines.push(
|
|
83597
|
-
`\u26A0 Repository matching is not enabled for ${entry.sessionCount} recent agent session${entry.sessionCount === 1 ? "" : "s"} under ${entry.displayRoot}. Sessions outside folders you explicitly added are staying local
|
|
83348
|
+
`\u26A0 Repository matching is not enabled for ${entry.sessionCount} recent agent session${entry.sessionCount === 1 ? "" : "s"} under ${entry.displayRoot}. Sessions outside folders you explicitly added are staying local, run \`powerplant init\` to review Git repository scanning.`
|
|
83598
83349
|
);
|
|
83599
83350
|
}
|
|
83600
83351
|
}
|
|
83601
83352
|
switch (i.service) {
|
|
83602
83353
|
case "unsupported":
|
|
83603
83354
|
lines.push(
|
|
83604
|
-
"Background
|
|
83355
|
+
"Background sync: unsupported on this platform (macOS-only for now), run `powerplant sync` on a schedule instead."
|
|
83605
83356
|
);
|
|
83606
83357
|
break;
|
|
83607
83358
|
case "not-installed":
|
|
83608
|
-
lines.push("Background
|
|
83359
|
+
lines.push("Background sync: not installed, run: powerplant init");
|
|
83609
83360
|
break;
|
|
83610
83361
|
case "not-loaded":
|
|
83611
|
-
lines.push("Background
|
|
83362
|
+
lines.push("Background sync: installed but not loaded, run: powerplant restart");
|
|
83612
83363
|
break;
|
|
83613
83364
|
case "loaded":
|
|
83614
83365
|
lines.push(...renderDaemon(i));
|
|
83615
83366
|
break;
|
|
83616
83367
|
}
|
|
83617
83368
|
if (i.control.paused) {
|
|
83618
|
-
lines.push("\u23F8 Syncing is paused
|
|
83369
|
+
lines.push("\u23F8 Syncing is paused, resume with: powerplant resume");
|
|
83619
83370
|
}
|
|
83620
83371
|
return lines;
|
|
83621
83372
|
}
|
|
83622
83373
|
function renderDaemon(i) {
|
|
83623
83374
|
if (i.daemon.state === "unreadable") {
|
|
83624
83375
|
return [
|
|
83625
|
-
"Background
|
|
83376
|
+
"Background sync: loaded, but its status file is unreadable (written by a different version?), run: powerplant restart"
|
|
83626
83377
|
];
|
|
83627
83378
|
}
|
|
83628
83379
|
if (i.daemon.state === "not-running") {
|
|
83629
83380
|
return [
|
|
83630
|
-
`Background
|
|
83381
|
+
`Background sync: loaded, but no background sync status is available, starting up, or running a version from before status reporting. If this persists: powerplant restart. Log: ${serviceLogPath(i.config.appEnv)}`
|
|
83631
83382
|
];
|
|
83632
83383
|
}
|
|
83633
83384
|
const status = i.daemon.status;
|
|
83634
83385
|
const lines = [];
|
|
83635
83386
|
if (i.daemon.state === "stalled") {
|
|
83636
83387
|
lines.push(
|
|
83637
|
-
`\u26A0
|
|
83388
|
+
`\u26A0 Background sync stalled, no heartbeat for ${duration3(i.daemon.staleMs)} (pid ${status.pid}). Run: powerplant restart`
|
|
83638
83389
|
);
|
|
83639
83390
|
} else {
|
|
83640
83391
|
lines.push(
|
|
83641
|
-
`
|
|
83392
|
+
`Background sync: running (version ${status.version}, pid ${status.pid}, started ${status.startedAt}).`
|
|
83642
83393
|
);
|
|
83643
83394
|
}
|
|
83644
83395
|
if (status.version !== i.cliVersion) {
|
|
83645
83396
|
lines.push(
|
|
83646
|
-
` The daemon is on ${status.version}, this CLI is ${i.cliVersion}
|
|
83397
|
+
` The daemon is on ${status.version}, this CLI is ${i.cliVersion}, it restarts onto the installed version within minutes, or now via: powerplant restart`
|
|
83647
83398
|
);
|
|
83648
83399
|
}
|
|
83649
83400
|
lines.push(
|
|
@@ -83727,13 +83478,13 @@ function redactedLogTail(raw) {
|
|
|
83727
83478
|
while (lines.length > 0 && lines[lines.length - 1]?.trim() === "") lines.pop();
|
|
83728
83479
|
return lines.slice(-DOCTOR_LOG_TAIL_LINES);
|
|
83729
83480
|
}
|
|
83730
|
-
function readDoctorLogTail(
|
|
83481
|
+
function readDoctorLogTail(path18) {
|
|
83731
83482
|
let fd;
|
|
83732
83483
|
try {
|
|
83733
|
-
fd = openSync2(
|
|
83484
|
+
fd = openSync2(path18, "r");
|
|
83734
83485
|
} catch (error52) {
|
|
83735
|
-
if (error52.code === "ENOENT") return { path:
|
|
83736
|
-
return { path:
|
|
83486
|
+
if (error52.code === "ENOENT") return { path: path18, lines: null };
|
|
83487
|
+
return { path: path18, lines: null, readError: error52 instanceof Error ? error52.message : String(error52) };
|
|
83737
83488
|
}
|
|
83738
83489
|
try {
|
|
83739
83490
|
const size = fstatSync(fd).size;
|
|
@@ -83742,9 +83493,9 @@ function readDoctorLogTail(path19) {
|
|
|
83742
83493
|
readSync2(fd, buffer, 0, buffer.length, offset);
|
|
83743
83494
|
let text = buffer.toString("utf8");
|
|
83744
83495
|
if (offset > 0) text = text.slice(text.indexOf("\n") + 1);
|
|
83745
|
-
return { path:
|
|
83496
|
+
return { path: path18, lines: redactedLogTail(text) };
|
|
83746
83497
|
} catch (error52) {
|
|
83747
|
-
return { path:
|
|
83498
|
+
return { path: path18, lines: null, readError: error52 instanceof Error ? error52.message : String(error52) };
|
|
83748
83499
|
} finally {
|
|
83749
83500
|
closeSync2(fd);
|
|
83750
83501
|
}
|
|
@@ -83752,7 +83503,7 @@ function readDoctorLogTail(path19) {
|
|
|
83752
83503
|
function renderDoctorReport(i) {
|
|
83753
83504
|
const lines = [];
|
|
83754
83505
|
lines.push(
|
|
83755
|
-
"Powerplant diagnostics
|
|
83506
|
+
"Powerplant diagnostics, paste everything below into your email to support@forestwalk.ai."
|
|
83756
83507
|
);
|
|
83757
83508
|
lines.push(
|
|
83758
83509
|
`Collected ${new Date(i.now).toISOString()}. This command only prints; nothing was uploaded.`
|
|
@@ -83774,7 +83525,7 @@ function renderDoctorReport(i) {
|
|
|
83774
83525
|
}
|
|
83775
83526
|
function enrollmentLine(i) {
|
|
83776
83527
|
if (i.credentialsError !== void 0) {
|
|
83777
|
-
return `Enrollment: credential store unreadable
|
|
83528
|
+
return `Enrollment: credential store unreadable, ${i.credentialsError}`;
|
|
83778
83529
|
}
|
|
83779
83530
|
if (!i.credentials) return "Enrollment: not enrolled";
|
|
83780
83531
|
return `Enrollment: machine ${i.credentials.machineId}, org ${i.credentials.orgId ?? "not recorded"}, since ${i.credentials.enrolledAt}`;
|
|
@@ -83799,28 +83550,28 @@ function serviceLines(i) {
|
|
|
83799
83550
|
const status = i.daemon.status;
|
|
83800
83551
|
const out = [];
|
|
83801
83552
|
out.push(
|
|
83802
|
-
i.daemon.state === "stalled" ? `Sync service: stalled
|
|
83553
|
+
i.daemon.state === "stalled" ? `Sync service: stalled, no heartbeat for ${duration3(i.daemon.staleMs)} (version ${status.version}, pid ${status.pid})` : `Sync service: running (version ${status.version}, pid ${status.pid}, started ${status.startedAt})`
|
|
83803
83554
|
);
|
|
83804
83555
|
out.push(
|
|
83805
83556
|
status.lastSyncAt !== void 0 ? `Last successful sync: ${ago(i.now - Date.parse(status.lastSyncAt))} (${status.lastSyncAt})` : "No successful sync yet in this daemon run."
|
|
83806
83557
|
);
|
|
83807
83558
|
if (status.lastPass) {
|
|
83808
83559
|
out.push(
|
|
83809
|
-
status.lastPass.ok ? `Last pass: ok (${status.lastPass.kind}, ${status.lastPass.sessions} sessions, ${status.lastPass.upserted} uploaded, at ${status.lastPass.at})` : `Last pass: failed at ${status.lastPass.at}
|
|
83560
|
+
status.lastPass.ok ? `Last pass: ok (${status.lastPass.kind}, ${status.lastPass.sessions} sessions, ${status.lastPass.upserted} uploaded, at ${status.lastPass.at})` : `Last pass: failed at ${status.lastPass.at}, ${redactText(status.lastPass.error ?? "unknown error")} (${status.consecutiveFailures} consecutive failure${status.consecutiveFailures === 1 ? "" : "s"})`
|
|
83810
83561
|
);
|
|
83811
83562
|
}
|
|
83812
83563
|
return out;
|
|
83813
83564
|
}
|
|
83814
83565
|
function logLines(tail) {
|
|
83815
83566
|
if (tail.readError !== void 0) {
|
|
83816
|
-
return [`Sync service log: could not read ${tail.path}
|
|
83567
|
+
return [`Sync service log: could not read ${tail.path}, ${tail.readError}`];
|
|
83817
83568
|
}
|
|
83818
83569
|
if (tail.lines === null) {
|
|
83819
83570
|
return [`Sync service log: no file at ${tail.path} (the background service may never have run).`];
|
|
83820
83571
|
}
|
|
83821
83572
|
if (tail.lines.length === 0) return [`Sync service log: ${tail.path} is empty.`];
|
|
83822
83573
|
return [
|
|
83823
|
-
`Sync service log
|
|
83574
|
+
`Sync service log, last ${tail.lines.length} line${tail.lines.length === 1 ? "" : "s"} of ${tail.path}, credentials redacted:`,
|
|
83824
83575
|
...tail.lines
|
|
83825
83576
|
];
|
|
83826
83577
|
}
|
|
@@ -83864,13 +83615,13 @@ function isCliEnv(value) {
|
|
|
83864
83615
|
}
|
|
83865
83616
|
function describeEnvironment(config2, env, explicitEnv) {
|
|
83866
83617
|
const steeredByEnvVar = explicitEnv === void 0 && env.POWERPLANT_ENV !== void 0;
|
|
83867
|
-
return `Environment: ${config2.appEnv} (API ${config2.apiUrl})${steeredByEnvVar ? "
|
|
83618
|
+
return `Environment: ${config2.appEnv} (API ${config2.apiUrl})${steeredByEnvVar ? ", set by POWERPLANT_ENV" : ""}`;
|
|
83868
83619
|
}
|
|
83869
83620
|
function resolveCliConfig(env, explicitEnv) {
|
|
83870
83621
|
const name = explicitEnv ?? env.POWERPLANT_ENV ?? "production";
|
|
83871
83622
|
if (!isCliEnv(name)) {
|
|
83872
83623
|
throw new ExpectedCliError(
|
|
83873
|
-
explicitEnv === void 0 ? `Unknown environment "${name}" (from POWERPLANT_ENV in your shell)
|
|
83624
|
+
explicitEnv === void 0 ? `Unknown environment "${name}" (from POWERPLANT_ENV in your shell), unset POWERPLANT_ENV to use production.` : `Unknown environment "${name}", drop --env to use production.`
|
|
83874
83625
|
);
|
|
83875
83626
|
}
|
|
83876
83627
|
const base = CLI_ENVIRONMENTS[name];
|
|
@@ -83912,7 +83663,7 @@ async function runInit(deps) {
|
|
|
83912
83663
|
let repoDiscoveryEnabled = false;
|
|
83913
83664
|
let protectedFoldersNeedAttention = false;
|
|
83914
83665
|
let installed = false;
|
|
83915
|
-
log3("2/3 Start background
|
|
83666
|
+
log3("2/3 Start background sync");
|
|
83916
83667
|
if (deps.platform === "darwin") {
|
|
83917
83668
|
const protectedSessions = await deps.activity(
|
|
83918
83669
|
"Checking recent session locations\u2026",
|
|
@@ -83967,29 +83718,29 @@ async function runInit(deps) {
|
|
|
83967
83718
|
}
|
|
83968
83719
|
if (deps.platform !== "darwin") {
|
|
83969
83720
|
log3(
|
|
83970
|
-
"
|
|
83721
|
+
" Background sync is macOS-only for now. Run `powerplant sync` on a schedule of your choosing instead."
|
|
83971
83722
|
);
|
|
83972
83723
|
} else if (deps.serviceUpToDate()) {
|
|
83973
|
-
log3("\u2713 Background
|
|
83724
|
+
log3("\u2713 Background sync is running");
|
|
83974
83725
|
} else {
|
|
83975
|
-
await deps.activity("Installing
|
|
83976
|
-
log3(" \u2713
|
|
83726
|
+
await deps.activity("Installing background sync\u2026", deps.installService);
|
|
83727
|
+
log3(" \u2713 Background sync is running");
|
|
83977
83728
|
log3(
|
|
83978
83729
|
` Runs quietly and only uploads sessions inside ${orgName ? `${orgName}\u2019s` : "your organization\u2019s"} boundary.`
|
|
83979
83730
|
);
|
|
83980
83731
|
installed = true;
|
|
83981
83732
|
}
|
|
83982
83733
|
log3("");
|
|
83983
|
-
log3("3/3
|
|
83734
|
+
log3("3/3 Give your agents Powerplant MCP access");
|
|
83984
83735
|
let outcome = null;
|
|
83985
83736
|
try {
|
|
83986
83737
|
outcome = await deps.connect();
|
|
83987
83738
|
} catch (error52) {
|
|
83988
|
-
log3(` \u2717
|
|
83739
|
+
log3(` \u2717 Could not give your agents Powerplant MCP access, ${error52 instanceof Error ? error52.message : String(error52)}`);
|
|
83989
83740
|
}
|
|
83990
83741
|
if (outcome?.found === 0) {
|
|
83991
83742
|
log3(
|
|
83992
|
-
deps.platform === "darwin" ? ` This machine still syncs once one is installed
|
|
83743
|
+
deps.platform === "darwin" ? ` This machine still syncs once one is installed, then run: ${deps.connectCommand}` : ` Once one is installed, run: ${deps.connectCommand}`
|
|
83993
83744
|
);
|
|
83994
83745
|
}
|
|
83995
83746
|
log3("");
|
|
@@ -84017,7 +83768,7 @@ async function runInit(deps) {
|
|
|
84017
83768
|
log3(` Open Powerplant: ${deps.webUrl}`);
|
|
84018
83769
|
log3("");
|
|
84019
83770
|
log3(
|
|
84020
|
-
deps.platform === "darwin" ? ` Start a coding session in ${repository}
|
|
83771
|
+
deps.platform === "darwin" ? ` Start a coding session in ${repository}, watch it appear in Powerplant.` : ` Start a coding session in ${repository}, then run \`powerplant sync\` to see it in Powerplant.`
|
|
84021
83772
|
);
|
|
84022
83773
|
}
|
|
84023
83774
|
async function confirmProtectedRepoDiscovery(deps) {
|
|
@@ -84049,10 +83800,10 @@ async function realPromptLine(question) {
|
|
|
84049
83800
|
}
|
|
84050
83801
|
|
|
84051
83802
|
// src/memberSessions.ts
|
|
84052
|
-
import { execFileSync as
|
|
84053
|
-
import { existsSync as
|
|
83803
|
+
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
83804
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
84054
83805
|
import os16 from "node:os";
|
|
84055
|
-
import
|
|
83806
|
+
import path16 from "node:path";
|
|
84056
83807
|
var memberSessionSchema = external_exports.object({
|
|
84057
83808
|
id: external_exports.string().min(1),
|
|
84058
83809
|
source: external_exports.string().min(1),
|
|
@@ -84063,12 +83814,12 @@ var memberSessionSchema = external_exports.object({
|
|
|
84063
83814
|
lastActivityAt: external_exports.string().min(1),
|
|
84064
83815
|
providerUrl: external_exports.string().nullable()
|
|
84065
83816
|
});
|
|
84066
|
-
var
|
|
83817
|
+
var FETCH_TIMEOUT_MS2 = 3e3;
|
|
84067
83818
|
async function fetchMemberSessions(credentials, fetchImpl = fetch) {
|
|
84068
83819
|
try {
|
|
84069
83820
|
const response = await fetchImpl(`${credentials.apiUrl}/api/collector/member-sessions`, {
|
|
84070
83821
|
headers: { authorization: `Bearer ${credentials.token}`, ...cliVersionHeaders() },
|
|
84071
|
-
signal: AbortSignal.timeout(
|
|
83822
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS2)
|
|
84072
83823
|
});
|
|
84073
83824
|
if (!response.ok) return null;
|
|
84074
83825
|
const envelope = external_exports.object({ data: external_exports.object({ sessions: external_exports.array(memberSessionSchema) }) }).safeParse(await response.json());
|
|
@@ -84112,11 +83863,11 @@ function codexThreadId(externalId) {
|
|
|
84112
83863
|
}
|
|
84113
83864
|
var CODEX_APP_BUNDLES = ["ChatGPT.app", "Codex.app"];
|
|
84114
83865
|
var urlSchemesSchema = external_exports.array(external_exports.object({ CFBundleURLSchemes: external_exports.array(external_exports.string()).optional() }));
|
|
84115
|
-
function detectCodexDesktop(probe = { exists:
|
|
84116
|
-
const roots = ["/Applications",
|
|
83866
|
+
function detectCodexDesktop(probe = { exists: existsSync5, readUrlSchemes: realReadUrlSchemes }) {
|
|
83867
|
+
const roots = ["/Applications", path16.join(os16.homedir(), "Applications")];
|
|
84117
83868
|
return roots.some(
|
|
84118
83869
|
(root) => CODEX_APP_BUNDLES.some((bundle) => {
|
|
84119
|
-
const bundlePath =
|
|
83870
|
+
const bundlePath = path16.join(root, bundle);
|
|
84120
83871
|
return probe.exists(bundlePath) && probe.readUrlSchemes(bundlePath).includes("codex");
|
|
84121
83872
|
})
|
|
84122
83873
|
);
|
|
@@ -84124,9 +83875,9 @@ function detectCodexDesktop(probe = { exists: existsSync6, readUrlSchemes: realR
|
|
|
84124
83875
|
function realReadUrlSchemes(bundlePath) {
|
|
84125
83876
|
if (process.platform !== "darwin") return [];
|
|
84126
83877
|
try {
|
|
84127
|
-
const json2 =
|
|
83878
|
+
const json2 = execFileSync6(
|
|
84128
83879
|
"plutil",
|
|
84129
|
-
["-extract", "CFBundleURLTypes", "json", "-o", "-",
|
|
83880
|
+
["-extract", "CFBundleURLTypes", "json", "-o", "-", path16.join(bundlePath, "Contents", "Info.plist")],
|
|
84130
83881
|
{ stdio: ["ignore", "pipe", "ignore"] }
|
|
84131
83882
|
).toString();
|
|
84132
83883
|
const parsed = urlSchemesSchema.safeParse(JSON.parse(json2));
|
|
@@ -84138,7 +83889,7 @@ function realReadUrlSchemes(bundlePath) {
|
|
|
84138
83889
|
}
|
|
84139
83890
|
|
|
84140
83891
|
// src/menu.ts
|
|
84141
|
-
import
|
|
83892
|
+
import path17 from "node:path";
|
|
84142
83893
|
var MENU_CONTRACT = 1;
|
|
84143
83894
|
var CLIENT_NAMES = { claude: "Claude Code", codex: "Codex", cursor: "Cursor" };
|
|
84144
83895
|
function renderMenu(i) {
|
|
@@ -84184,7 +83935,7 @@ function renderMenu(i) {
|
|
|
84184
83935
|
}
|
|
84185
83936
|
if (i.connections.length > 0) {
|
|
84186
83937
|
items.push({ type: "separator" });
|
|
84187
|
-
items.push({ type: "section", title: "
|
|
83938
|
+
items.push({ type: "section", title: "Agents authorized for MCP" });
|
|
84188
83939
|
for (const connection of i.connections) {
|
|
84189
83940
|
const { row, action, warns } = connectionRow(connection, envArgs);
|
|
84190
83941
|
if (warns) attention = true;
|
|
@@ -84205,7 +83956,7 @@ function renderMenu(i) {
|
|
|
84205
83956
|
items.push({ type: "separator" });
|
|
84206
83957
|
items.push({ type: "action", title: "Open Powerplant", url: i.config.webUrl });
|
|
84207
83958
|
if (i.credentials !== null && i.service === "loaded" && !i.control.paused) {
|
|
84208
|
-
items.push({ type: "action", title: "Pause
|
|
83959
|
+
items.push({ type: "action", title: "Pause syncing", run: ["pause", ...envArgs] });
|
|
84209
83960
|
}
|
|
84210
83961
|
const icon = attention ? "attention" : i.control.paused ? "paused" : "running";
|
|
84211
83962
|
return {
|
|
@@ -84226,12 +83977,12 @@ function updateAction(i) {
|
|
|
84226
83977
|
function collectorBlock(i, envArgs, problem) {
|
|
84227
83978
|
const restart = {
|
|
84228
83979
|
type: "action",
|
|
84229
|
-
title: "Restart
|
|
83980
|
+
title: "Restart background sync",
|
|
84230
83981
|
run: ["restart", ...envArgs]
|
|
84231
83982
|
};
|
|
84232
83983
|
const viewLog = {
|
|
84233
83984
|
type: "action",
|
|
84234
|
-
title: "View
|
|
83985
|
+
title: "View background sync log",
|
|
84235
83986
|
file: serviceLogPath(i.config.appEnv)
|
|
84236
83987
|
};
|
|
84237
83988
|
switch (i.service) {
|
|
@@ -84240,19 +83991,19 @@ function collectorBlock(i, envArgs, problem) {
|
|
|
84240
83991
|
{
|
|
84241
83992
|
type: "status",
|
|
84242
83993
|
mark: "muted",
|
|
84243
|
-
title: "Background
|
|
83994
|
+
title: "Background sync isn't supported on this platform",
|
|
84244
83995
|
subtitle: "Sessions upload when you run: powerplant sync"
|
|
84245
83996
|
}
|
|
84246
83997
|
];
|
|
84247
83998
|
case "not-installed":
|
|
84248
83999
|
return [
|
|
84249
|
-
problem("Not uploading
|
|
84250
|
-
{ type: "action", title: "Set
|
|
84000
|
+
problem("Not uploading, the background sync isn't set up"),
|
|
84001
|
+
{ type: "action", title: "Set up background sync\u2026", terminal: ["init", ...envArgs] }
|
|
84251
84002
|
];
|
|
84252
84003
|
case "not-loaded":
|
|
84253
84004
|
return [
|
|
84254
|
-
problem("Not uploading
|
|
84255
|
-
{ type: "action", title: "Start
|
|
84005
|
+
problem("Not uploading, the background sync is stopped"),
|
|
84006
|
+
{ type: "action", title: "Start background sync", run: ["restart", ...envArgs] }
|
|
84256
84007
|
];
|
|
84257
84008
|
case "loaded":
|
|
84258
84009
|
break;
|
|
@@ -84261,15 +84012,15 @@ function collectorBlock(i, envArgs, problem) {
|
|
|
84261
84012
|
case "unreadable":
|
|
84262
84013
|
return [
|
|
84263
84014
|
problem(
|
|
84264
|
-
"
|
|
84265
|
-
"Its report was written by a different version
|
|
84015
|
+
"Background sync status can't be read",
|
|
84016
|
+
"Its report was written by a different version, restarting usually clears this."
|
|
84266
84017
|
),
|
|
84267
84018
|
restart
|
|
84268
84019
|
];
|
|
84269
84020
|
case "not-running":
|
|
84270
84021
|
return [
|
|
84271
84022
|
problem(
|
|
84272
|
-
"Not uploading
|
|
84023
|
+
"Not uploading, the background sync isn't running",
|
|
84273
84024
|
"It may be starting up. If this lasts, restart it."
|
|
84274
84025
|
),
|
|
84275
84026
|
restart
|
|
@@ -84277,7 +84028,7 @@ function collectorBlock(i, envArgs, problem) {
|
|
|
84277
84028
|
case "stalled":
|
|
84278
84029
|
return [
|
|
84279
84030
|
problem(
|
|
84280
|
-
`
|
|
84031
|
+
`Background sync quiet for ${duration3(i.daemon.staleMs)}, it may be stuck`,
|
|
84281
84032
|
lastUploadLine(i)
|
|
84282
84033
|
),
|
|
84283
84034
|
restart
|
|
@@ -84291,9 +84042,9 @@ function collectorBlock(i, envArgs, problem) {
|
|
|
84291
84042
|
type: "status",
|
|
84292
84043
|
mark: "paused",
|
|
84293
84044
|
title: "Syncing paused",
|
|
84294
|
-
subtitle: "The sync
|
|
84045
|
+
subtitle: "The background sync is running but uploads nothing."
|
|
84295
84046
|
},
|
|
84296
|
-
{ type: "action", title: "Resume
|
|
84047
|
+
{ type: "action", title: "Resume syncing", run: ["resume", ...envArgs] }
|
|
84297
84048
|
];
|
|
84298
84049
|
}
|
|
84299
84050
|
const status = i.daemon.status;
|
|
@@ -84307,7 +84058,7 @@ function collectorBlock(i, envArgs, problem) {
|
|
|
84307
84058
|
];
|
|
84308
84059
|
}
|
|
84309
84060
|
return [
|
|
84310
|
-
{ type: "status", mark: "ok", title: "
|
|
84061
|
+
{ type: "status", mark: "ok", title: "Background sync running", subtitle: lastUploadLine(i) }
|
|
84311
84062
|
];
|
|
84312
84063
|
}
|
|
84313
84064
|
var MAX_ACTIVE_AGENTS = 8;
|
|
@@ -84358,15 +84109,15 @@ function connectionRow(connection, envArgs) {
|
|
|
84358
84109
|
type: "connection",
|
|
84359
84110
|
mark,
|
|
84360
84111
|
name,
|
|
84361
|
-
state: connection.target === void 0 ? state : `${state}
|
|
84112
|
+
state: connection.target === void 0 ? state : `${state}, ${connection.target}`
|
|
84362
84113
|
});
|
|
84363
84114
|
switch (connection.state) {
|
|
84364
84115
|
case "signed-in":
|
|
84365
|
-
return { row: row("ok", "
|
|
84116
|
+
return { row: row("ok", "MCP access granted"), warns: false };
|
|
84366
84117
|
case "sign-in-needed":
|
|
84367
84118
|
return {
|
|
84368
|
-
row: row("warn", "
|
|
84369
|
-
action: fix(`
|
|
84119
|
+
row: row("warn", "MCP sign-in needed"),
|
|
84120
|
+
action: fix(`Give ${name} MCP access\u2026`),
|
|
84370
84121
|
warns: true
|
|
84371
84122
|
};
|
|
84372
84123
|
case "different-url":
|
|
@@ -84377,12 +84128,12 @@ function connectionRow(connection, envArgs) {
|
|
|
84377
84128
|
};
|
|
84378
84129
|
case "not-connected":
|
|
84379
84130
|
return {
|
|
84380
|
-
row: row("warn", connection.client === "cursor" ? "
|
|
84381
|
-
action: fix(connection.client === "cursor" ? "
|
|
84131
|
+
row: row("warn", connection.client === "cursor" ? "MCP not configured" : "Not connected"),
|
|
84132
|
+
action: fix(connection.client === "cursor" ? "Add Powerplant MCP to Cursor\u2026" : `Give ${name} MCP access\u2026`),
|
|
84382
84133
|
warns: true
|
|
84383
84134
|
};
|
|
84384
84135
|
case "configured":
|
|
84385
|
-
return { row: row("muted", "
|
|
84136
|
+
return { row: row("muted", "MCP configured in Cursor"), warns: false };
|
|
84386
84137
|
case "check-failed":
|
|
84387
84138
|
return { row: row("muted", "Can't check right now"), warns: false };
|
|
84388
84139
|
}
|
|
@@ -84402,13 +84153,13 @@ function moreItems(i) {
|
|
|
84402
84153
|
muted(`Enrolled ${i.credentials.enrolledAt.slice(0, 10)}`),
|
|
84403
84154
|
muted(`CLI ${i.cliVersion}`, daemonVersionNote(i))
|
|
84404
84155
|
];
|
|
84405
|
-
more.push({ type: "submenu", title: "
|
|
84156
|
+
more.push({ type: "submenu", title: "Background sync details", items: details });
|
|
84406
84157
|
}
|
|
84407
84158
|
more.push({ type: "action", title: "Copy Diagnostics", diagnostics: true });
|
|
84408
84159
|
if (i.config.appEnv !== "production") {
|
|
84409
84160
|
more.push({
|
|
84410
84161
|
type: "action",
|
|
84411
|
-
title: "View
|
|
84162
|
+
title: "View background sync log",
|
|
84412
84163
|
file: serviceLogPath(i.config.appEnv)
|
|
84413
84164
|
});
|
|
84414
84165
|
}
|
|
@@ -84420,18 +84171,18 @@ function captureLine(credentials) {
|
|
|
84420
84171
|
return `Syncs sessions under ${(credentials.scopePaths ?? []).join(", ")}`;
|
|
84421
84172
|
case "org-repos": {
|
|
84422
84173
|
const owners = credentials.allowedOwners ?? [];
|
|
84423
|
-
return owners.length > 0 ? `Syncs sessions in ${owners.join(", ")} repositories` : "Set to sync your organization's repositories, but none are linked yet
|
|
84174
|
+
return owners.length > 0 ? `Syncs sessions in ${owners.join(", ")} repositories` : "Set to sync your organization's repositories, but none are linked yet, nothing uploads";
|
|
84424
84175
|
}
|
|
84425
84176
|
}
|
|
84426
84177
|
}
|
|
84427
84178
|
function daemonVersionNote(i) {
|
|
84428
84179
|
if (!("status" in i.daemon)) return void 0;
|
|
84429
84180
|
const version2 = i.daemon.status.version;
|
|
84430
|
-
return version2 === i.cliVersion ? void 0 : `
|
|
84181
|
+
return version2 === i.cliVersion ? void 0 : `Background sync ${version2}`;
|
|
84431
84182
|
}
|
|
84432
84183
|
var VERSION_CACHE_TTL_MS = 60 * 6e4;
|
|
84433
84184
|
function versionCachePath(homeDir) {
|
|
84434
|
-
return
|
|
84185
|
+
return path17.join(collectorStateDir(homeDir), "version-check.json");
|
|
84435
84186
|
}
|
|
84436
84187
|
async function cachedLatestVersion(options) {
|
|
84437
84188
|
const raw = options.readTextFile(options.cacheFile);
|
|
@@ -84466,7 +84217,7 @@ function resumeSessionArgv(source, sessionId) {
|
|
|
84466
84217
|
const command = RESUME_COMMANDS[source];
|
|
84467
84218
|
if (command === void 0) {
|
|
84468
84219
|
throw new ExpectedCliError(
|
|
84469
|
-
`Sessions from "${source}" have no terminal to resume in
|
|
84220
|
+
`Sessions from "${source}" have no terminal to resume in, open them in Powerplant instead.`
|
|
84470
84221
|
);
|
|
84471
84222
|
}
|
|
84472
84223
|
return command(sessionId);
|
|
@@ -84479,7 +84230,7 @@ function runResumeSession(source, sessionId, spawn2 = spawnSync3) {
|
|
|
84479
84230
|
const result = spawn2(binary, args, { stdio: "inherit" });
|
|
84480
84231
|
if (result.error !== void 0) {
|
|
84481
84232
|
throw new ExpectedCliError(
|
|
84482
|
-
`Could not run ${binary} (${result.error.message})
|
|
84233
|
+
`Could not run ${binary} (${result.error.message}), is the ${binary} CLI installed on this machine?`
|
|
84483
84234
|
);
|
|
84484
84235
|
}
|
|
84485
84236
|
if (result.status !== null && result.status !== 0) {
|
|
@@ -84612,7 +84363,7 @@ ${RESTART_NOTE}`;
|
|
|
84612
84363
|
}
|
|
84613
84364
|
|
|
84614
84365
|
// src/version.ts
|
|
84615
|
-
var CLI_VERSION = true ? "0.4.
|
|
84366
|
+
var CLI_VERSION = true ? "0.4.1" : "0.0.0-checkout";
|
|
84616
84367
|
var CLI_PACKAGE_NAME = "@usepowerplant/cli";
|
|
84617
84368
|
|
|
84618
84369
|
// src/workspace.ts
|
|
@@ -84622,18 +84373,18 @@ var workspaceSchema = external_exports.object({
|
|
|
84622
84373
|
role: external_exports.string().min(1),
|
|
84623
84374
|
active: external_exports.boolean()
|
|
84624
84375
|
});
|
|
84625
|
-
var
|
|
84626
|
-
async function callApi(credentials,
|
|
84376
|
+
var FETCH_TIMEOUT_MS3 = 1e4;
|
|
84377
|
+
async function callApi(credentials, path18, init3, fetchImpl) {
|
|
84627
84378
|
let response;
|
|
84628
84379
|
try {
|
|
84629
|
-
response = await fetchImpl(`${credentials.apiUrl}${
|
|
84380
|
+
response = await fetchImpl(`${credentials.apiUrl}${path18}`, {
|
|
84630
84381
|
...init3,
|
|
84631
84382
|
headers: {
|
|
84632
84383
|
authorization: `Bearer ${credentials.token}`,
|
|
84633
84384
|
"content-type": "application/json",
|
|
84634
84385
|
...cliVersionHeaders()
|
|
84635
84386
|
},
|
|
84636
|
-
signal: AbortSignal.timeout(
|
|
84387
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS3)
|
|
84637
84388
|
});
|
|
84638
84389
|
} catch (error52) {
|
|
84639
84390
|
const detail = error52 instanceof Error ? error52.message : String(error52);
|
|
@@ -84641,11 +84392,11 @@ async function callApi(credentials, path19, init3, fetchImpl) {
|
|
|
84641
84392
|
}
|
|
84642
84393
|
if (response.status === 401) {
|
|
84643
84394
|
throw new ExpectedCliError(
|
|
84644
|
-
"Powerplant refused this machine's credentials
|
|
84395
|
+
"Powerplant refused this machine's credentials, run `powerplant enroll` to re-enroll it."
|
|
84645
84396
|
);
|
|
84646
84397
|
}
|
|
84647
84398
|
if (!response.ok) {
|
|
84648
|
-
throw new ExpectedCliError(`Powerplant answered ${response.status} for ${
|
|
84399
|
+
throw new ExpectedCliError(`Powerplant answered ${response.status} for ${path18}.`);
|
|
84649
84400
|
}
|
|
84650
84401
|
return response.json();
|
|
84651
84402
|
}
|
|
@@ -84653,7 +84404,7 @@ async function fetchWorkspaces(credentials, fetchImpl = fetch) {
|
|
|
84653
84404
|
const envelope = external_exports.object({ data: external_exports.object({ workspaces: external_exports.array(workspaceSchema) }) }).safeParse(await callApi(credentials, "/api/collector/workspaces", {}, fetchImpl));
|
|
84654
84405
|
if (!envelope.success) {
|
|
84655
84406
|
throw new ExpectedCliError(
|
|
84656
|
-
"Powerplant answered in a shape this CLI can't read
|
|
84407
|
+
"Powerplant answered in a shape this CLI can't read, run `powerplant update`."
|
|
84657
84408
|
);
|
|
84658
84409
|
}
|
|
84659
84410
|
return envelope.data.data.workspaces;
|
|
@@ -84668,7 +84419,7 @@ async function selectWorkspace(credentials, orgId, fetchImpl = fetch) {
|
|
|
84668
84419
|
}
|
|
84669
84420
|
function renderWorkspaces(workspaces) {
|
|
84670
84421
|
const lines = workspaces.map(
|
|
84671
|
-
(workspace) => `${workspace.active ? "*" : " "} ${workspace.name} (${workspace.role})${workspace.active ? "
|
|
84422
|
+
(workspace) => `${workspace.active ? "*" : " "} ${workspace.name} (${workspace.role})${workspace.active ? ", active" : ""}`
|
|
84672
84423
|
);
|
|
84673
84424
|
if (workspaces.length > 1) {
|
|
84674
84425
|
lines.push("", "Switch with: powerplant workspace <name>");
|
|
@@ -84687,7 +84438,7 @@ function matchWorkspace(workspaces, target) {
|
|
|
84687
84438
|
}
|
|
84688
84439
|
const ids = matches.map((workspace) => `${workspace.name} = ${workspace.id}`).join(", ");
|
|
84689
84440
|
throw new ExpectedCliError(
|
|
84690
|
-
`"${target}" names ${matches.length} of your workspaces
|
|
84441
|
+
`"${target}" names ${matches.length} of your workspaces, switch by id instead: ${ids}.`
|
|
84691
84442
|
);
|
|
84692
84443
|
}
|
|
84693
84444
|
async function runWorkspaceCommand(targetWords, credentials, print, fetchImpl = fetch) {
|
|
@@ -84708,39 +84459,39 @@ async function runWorkspaceCommand(targetWords, credentials, print, fetchImpl =
|
|
|
84708
84459
|
}
|
|
84709
84460
|
|
|
84710
84461
|
// src/cli.ts
|
|
84711
|
-
var USAGE = `powerplant
|
|
84462
|
+
var USAGE = `powerplant, the Powerplant background sync for this machine
|
|
84712
84463
|
|
|
84713
84464
|
Usage: powerplant <command> [options]
|
|
84714
84465
|
|
|
84715
84466
|
Commands:
|
|
84716
|
-
init
|
|
84717
|
-
|
|
84718
|
-
Safe to re-run
|
|
84719
|
-
connect
|
|
84720
|
-
Cursor)
|
|
84467
|
+
init Enroll this machine, start background sync, and give your
|
|
84468
|
+
coding agents Powerplant MCP access.
|
|
84469
|
+
Safe to re-run, finished steps are skipped.
|
|
84470
|
+
connect Give installed coding agents Powerplant MCP access (Claude Code,
|
|
84471
|
+
Codex, Cursor), also for later installs and re-authentication.
|
|
84721
84472
|
--client claude|codex|cursor adds just those (repeatable).
|
|
84722
84473
|
disconnect The inverse of connect: remove the Powerplant MCP entry (and
|
|
84723
84474
|
its sign-in) from every installed coding agent.
|
|
84724
84475
|
enroll (Re-)enroll this machine into your org (browser approval).
|
|
84725
|
-
status What the sync
|
|
84476
|
+
status What the background sync is doing on this machine (--json for tools).
|
|
84726
84477
|
doctor A diagnostics summary for support: status plus the redacted
|
|
84727
|
-
tail of the sync
|
|
84478
|
+
tail of the background sync log. Prints only, nothing is uploaded.
|
|
84728
84479
|
Paste the output into your email to support@forestwalk.ai.
|
|
84729
84480
|
update Update this CLI to the latest published version (via npm).
|
|
84730
|
-
restart Restart the background
|
|
84731
|
-
pause Pause syncing
|
|
84481
|
+
restart Restart the background sync.
|
|
84482
|
+
pause Pause syncing, the service keeps running, nothing uploads.
|
|
84732
84483
|
resume Resume syncing (runs a catch-up pass over the pause).
|
|
84733
84484
|
sync Run one sync pass in the foreground [--since <days>] [--dry-run].
|
|
84734
84485
|
folders The folders you explicitly sync on this machine:
|
|
84735
84486
|
powerplant folders [add <path> | remove <path>]. Additions on
|
|
84736
|
-
top of your org's allowlisted repos
|
|
84487
|
+
top of your org's allowlisted repos, no re-enroll needed.
|
|
84737
84488
|
workspace Your workspaces, and which one Powerplant and your connected
|
|
84738
84489
|
agents use: powerplant workspace [<name>] switches to <name>.
|
|
84739
84490
|
resume-session Reopen a synced session in its own CLI, right here in
|
|
84740
84491
|
this terminal: powerplant resume-session <claude-code|codex>
|
|
84741
84492
|
<session-id>.
|
|
84742
|
-
watch Run the sync
|
|
84743
|
-
uninstall Remove the background
|
|
84493
|
+
watch Run the background sync in the foreground.
|
|
84494
|
+
uninstall Remove the background sync [--forget also deletes this
|
|
84744
84495
|
machine's stored credentials].
|
|
84745
84496
|
|
|
84746
84497
|
Options:
|
|
@@ -84828,7 +84579,7 @@ ${USAGE}`);
|
|
|
84828
84579
|
let clients = clientFilter === void 0 ? detected : detected.filter((client) => clientFilter.has(client.client));
|
|
84829
84580
|
if (clientFilter !== void 0 && clients.length === 0) {
|
|
84830
84581
|
log3(
|
|
84831
|
-
`No ${[...clientFilter].join(" or ")} installation found on this machine
|
|
84582
|
+
`No ${[...clientFilter].join(" or ")} installation found on this machine, nothing to connect.`
|
|
84832
84583
|
);
|
|
84833
84584
|
return {
|
|
84834
84585
|
found: 0,
|
|
@@ -84845,7 +84596,7 @@ ${USAGE}`);
|
|
|
84845
84596
|
clients = await pickAgents(clients, { log: log3, promptCheckboxes: realCheckboxPrompt });
|
|
84846
84597
|
skipped = agentCount(detected) - agentCount(clients);
|
|
84847
84598
|
if (clients.length === 0) {
|
|
84848
|
-
log3(`MCP wasn't added
|
|
84599
|
+
log3(`Powerplant MCP wasn't added to any agents. Run any time: ${connectCommand}`);
|
|
84849
84600
|
return {
|
|
84850
84601
|
found: agentCount(detected),
|
|
84851
84602
|
connected: 0,
|
|
@@ -84903,7 +84654,7 @@ ${USAGE}`);
|
|
|
84903
84654
|
case "connect": {
|
|
84904
84655
|
const outcome = await connect3(console.log);
|
|
84905
84656
|
if (outcome.pending > 0) {
|
|
84906
|
-
console.log(`Some logins are unfinished
|
|
84657
|
+
console.log(`Some logins are unfinished, re-run \`${connectCommand}\` any time.`);
|
|
84907
84658
|
}
|
|
84908
84659
|
if (outcome.failed > 0) process.exitCode = 1;
|
|
84909
84660
|
return;
|
|
@@ -84990,7 +84741,7 @@ The access you granted these agents stays on your Powerplant account until you r
|
|
|
84990
84741
|
const clients = mergeDetectedClients(
|
|
84991
84742
|
detectClients({ whichAll: whichAllWith(probePath), budget }),
|
|
84992
84743
|
saved,
|
|
84993
|
-
|
|
84744
|
+
existsSync6
|
|
84994
84745
|
);
|
|
84995
84746
|
const [latestVersion, oldestSupportedVersion, memberSessions, grantedClientIds] = await Promise.all([
|
|
84996
84747
|
cachedLatestVersion({
|
|
@@ -85033,7 +84784,7 @@ The access you granted these agents stays on your Powerplant account until you r
|
|
|
85033
84784
|
const stored = loadCredentialsSafely(config2);
|
|
85034
84785
|
if (stored.credentials === null) {
|
|
85035
84786
|
throw new ExpectedCliError(
|
|
85036
|
-
`This machine isn't enrolled yet
|
|
84787
|
+
`This machine isn't enrolled yet, run \`powerplant init\` first.${stored.credentialsError ? ` (${stored.credentialsError})` : ""}`
|
|
85037
84788
|
);
|
|
85038
84789
|
}
|
|
85039
84790
|
await runWorkspaceCommand(positionals.slice(1), stored.credentials, console.log);
|
|
@@ -85048,31 +84799,31 @@ The access you granted these agents stays on your Powerplant account until you r
|
|
|
85048
84799
|
const npm = spawnSync5("npm", ["install", "-g", CLI_PACKAGE_NAME], { stdio: "inherit" });
|
|
85049
84800
|
if (npm.error) {
|
|
85050
84801
|
throw new ExpectedCliError(
|
|
85051
|
-
`Could not run npm (${npm.error.message})
|
|
84802
|
+
`Could not run npm (${npm.error.message}), update by hand: npm install -g ${CLI_PACKAGE_NAME}`
|
|
85052
84803
|
);
|
|
85053
84804
|
}
|
|
85054
84805
|
if (npm.status !== 0) {
|
|
85055
|
-
throw new ExpectedCliError("npm install failed
|
|
84806
|
+
throw new ExpectedCliError("npm install failed, see the output above.");
|
|
85056
84807
|
}
|
|
85057
84808
|
console.log(updatedMessage(installedGlobalVersion(CLI_PACKAGE_NAME)));
|
|
85058
84809
|
return;
|
|
85059
84810
|
}
|
|
85060
84811
|
case "restart": {
|
|
85061
84812
|
if (restartService(config2) === "not-installed") {
|
|
85062
|
-
throw new ExpectedCliError("No background
|
|
84813
|
+
throw new ExpectedCliError("No background sync installed, run: powerplant init");
|
|
85063
84814
|
}
|
|
85064
|
-
console.log("Background
|
|
84815
|
+
console.log("Background sync restarted.");
|
|
85065
84816
|
return;
|
|
85066
84817
|
}
|
|
85067
84818
|
case "pause": {
|
|
85068
84819
|
writeCollectorControl(config2.appEnv, { paused: true, pausedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
85069
|
-
console.log("Syncing paused
|
|
84820
|
+
console.log("Syncing paused, the background sync keeps running but uploads nothing.");
|
|
85070
84821
|
console.log("Resume with: powerplant resume");
|
|
85071
84822
|
return;
|
|
85072
84823
|
}
|
|
85073
84824
|
case "resume": {
|
|
85074
84825
|
writeCollectorControl(config2.appEnv, { paused: false, resumedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
85075
|
-
console.log("Syncing resumed
|
|
84826
|
+
console.log("Syncing resumed, the background sync runs a catch-up pass covering the pause.");
|
|
85076
84827
|
return;
|
|
85077
84828
|
}
|
|
85078
84829
|
case "sync": {
|
|
@@ -85111,18 +84862,18 @@ The access you granted these agents stays on your Powerplant account until you r
|
|
|
85111
84862
|
const removed = uninstallService(config2);
|
|
85112
84863
|
clearCollectorStatus(config2.appEnv);
|
|
85113
84864
|
clearCollectorControl(config2.appEnv);
|
|
85114
|
-
console.log(removed ? "Background
|
|
84865
|
+
console.log(removed ? "Background sync removed." : "No background sync was installed.");
|
|
85115
84866
|
if (values.forget) {
|
|
85116
84867
|
deleteCredentials(config2.appEnv);
|
|
85117
|
-
console.log("Stored credentials deleted
|
|
84868
|
+
console.log("Stored credentials deleted, this machine is no longer enrolled.");
|
|
85118
84869
|
} else {
|
|
85119
84870
|
console.log(
|
|
85120
|
-
"Credentials kept
|
|
84871
|
+
"Credentials kept, `powerplant init` re-installs without re-enrolling. (--forget deletes them.)"
|
|
85121
84872
|
);
|
|
85122
84873
|
}
|
|
85123
84874
|
if (anyClientStillConnected(detectClients(), { run: realRun, readTextFile: realReadTextFile })) {
|
|
85124
84875
|
console.log(
|
|
85125
|
-
"Your coding agents are still connected to the Powerplant MCP server
|
|
84876
|
+
"Your coding agents are still connected to the Powerplant MCP server, remove those connections with: powerplant disconnect"
|
|
85126
84877
|
);
|
|
85127
84878
|
}
|
|
85128
84879
|
return;
|