lody 0.49.0 → 0.49.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/index.js +14 -178
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import require$$3$5, { randomUUID, randomBytes, createHash } from "crypto";
|
|
3
|
-
import require$$0$5, { inspect as inspect$1, types as types$6
|
|
3
|
+
import require$$0$5, { inspect as inspect$1, types as types$6 } from "util";
|
|
4
4
|
import require$$2$6 from "url";
|
|
5
5
|
import * as path$2 from "path";
|
|
6
6
|
import path__default, { normalize as normalize$1, resolve as resolve$1 } from "path";
|
|
@@ -20,7 +20,7 @@ import * as diagch from "diagnostics_channel";
|
|
|
20
20
|
import diagch__default from "diagnostics_channel";
|
|
21
21
|
import * as net from "node:net";
|
|
22
22
|
import require$$1$4 from "async_hooks";
|
|
23
|
-
import require$$1$5, { execFile
|
|
23
|
+
import require$$1$5, { execFile, spawn as spawn$1 } from "node:child_process";
|
|
24
24
|
import fs$6, { readdir, readFile, createReadStream, existsSync, readFileSync as readFileSync$1, promises } from "node:fs";
|
|
25
25
|
import * as os from "node:os";
|
|
26
26
|
import os__default$1 from "node:os";
|
|
@@ -45,7 +45,7 @@ import require$$1$6 from "string_decoder";
|
|
|
45
45
|
import * as http$2 from "http";
|
|
46
46
|
import http__default from "http";
|
|
47
47
|
import require$$1$7 from "https";
|
|
48
|
-
import require$$0$a, { execSync, exec, execFileSync, execFile as execFile$
|
|
48
|
+
import require$$0$a, { execSync, exec, execFileSync, execFile as execFile$1 } from "child_process";
|
|
49
49
|
import { randomFillSync, randomUUID as randomUUID$1, createHash as createHash$1 } from "node:crypto";
|
|
50
50
|
import require$$0$b from "net";
|
|
51
51
|
import require$$4$3 from "tls";
|
|
@@ -20576,7 +20576,7 @@ Event: ${getEventDescription(event)}`);
|
|
|
20576
20576
|
};
|
|
20577
20577
|
try {
|
|
20578
20578
|
const output = await new Promise((resolve2, reject) => {
|
|
20579
|
-
execFile
|
|
20579
|
+
execFile("/usr/bin/sw_vers", (error2, stdout) => {
|
|
20580
20580
|
if (error2) {
|
|
20581
20581
|
reject(error2);
|
|
20582
20582
|
return;
|
|
@@ -36821,7 +36821,7 @@ Mongoose Error Code: ${error2.code}` : ""}`
|
|
|
36821
36821
|
return client;
|
|
36822
36822
|
}
|
|
36823
36823
|
const name = "lody";
|
|
36824
|
-
const version$4 = "0.49.
|
|
36824
|
+
const version$4 = "0.49.1";
|
|
36825
36825
|
const description$1 = "Lody Agent CLI tool for managing remote command execution";
|
|
36826
36826
|
const type$2 = "module";
|
|
36827
36827
|
const main$3 = "dist/index.js";
|
|
@@ -104343,7 +104343,7 @@ stream:${scope2.streamId}`;
|
|
|
104343
104343
|
}
|
|
104344
104344
|
var outExports = requireOut();
|
|
104345
104345
|
const fastGlob = getDefaultExportFromCjs(outExports);
|
|
104346
|
-
promisify(execFile
|
|
104346
|
+
promisify(execFile);
|
|
104347
104347
|
function toPath(urlOrPath) {
|
|
104348
104348
|
return urlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath;
|
|
104349
104349
|
}
|
|
@@ -104677,7 +104677,7 @@ stream:${scope2.streamId}`;
|
|
|
104677
104677
|
}
|
|
104678
104678
|
var ignoreExports = requireIgnore();
|
|
104679
104679
|
const gitIgnore = getDefaultExportFromCjs(ignoreExports);
|
|
104680
|
-
function isPathInside
|
|
104680
|
+
function isPathInside(childPath, parentPath) {
|
|
104681
104681
|
const relation = path__default$1.relative(parentPath, childPath);
|
|
104682
104682
|
return Boolean(relation && relation !== ".." && !relation.startsWith(`..${path__default$1.sep}`) && relation !== path__default$1.resolve(childPath));
|
|
104683
104683
|
}
|
|
@@ -104824,7 +104824,7 @@ stream:${scope2.streamId}`;
|
|
|
104824
104824
|
const isWithinGitRoot = (gitRoot, cwd) => {
|
|
104825
104825
|
const resolvedGitRoot = path__default$1.resolve(gitRoot);
|
|
104826
104826
|
const resolvedCwd = path__default$1.resolve(cwd);
|
|
104827
|
-
return resolvedCwd === resolvedGitRoot || isPathInside
|
|
104827
|
+
return resolvedCwd === resolvedGitRoot || isPathInside(resolvedCwd, resolvedGitRoot);
|
|
104828
104828
|
};
|
|
104829
104829
|
const getParentGitignorePaths = (gitRoot, cwd) => {
|
|
104830
104830
|
if (gitRoot && typeof gitRoot !== "string") {
|
|
@@ -104957,7 +104957,7 @@ stream:${scope2.streamId}`;
|
|
|
104957
104957
|
const toRelativePath = (fileOrDirectory, cwd) => {
|
|
104958
104958
|
if (path__default$1.isAbsolute(fileOrDirectory)) {
|
|
104959
104959
|
const relativePath = path__default$1.relative(cwd, fileOrDirectory);
|
|
104960
|
-
if (relativePath && !isPathInside
|
|
104960
|
+
if (relativePath && !isPathInside(fileOrDirectory, cwd)) {
|
|
104961
104961
|
return void 0;
|
|
104962
104962
|
}
|
|
104963
104963
|
return relativePath;
|
|
@@ -129454,7 +129454,6 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
129454
129454
|
const PREVIEW_REGISTRY_LOCK_NAME = "preview-tunnels";
|
|
129455
129455
|
const PREVIEW_REGISTRY_FILE = path__default.join(os__default.homedir(), ".lody", "preview-tunnels.json");
|
|
129456
129456
|
const PREVIEW_REGISTRY_FUTURE_SKEW_MS = 6e4;
|
|
129457
|
-
const execFile = promisify$1(execFile$2);
|
|
129458
129457
|
const normalizeHost = (host) => {
|
|
129459
129458
|
const trimmed = host.trim().toLowerCase();
|
|
129460
129459
|
return trimmed.startsWith("[") && trimmed.endsWith("]") ? trimmed.slice(1, -1) : trimmed;
|
|
@@ -129565,96 +129564,6 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
129565
129564
|
clearTimeout(timeout2);
|
|
129566
129565
|
}
|
|
129567
129566
|
};
|
|
129568
|
-
const parseLsofOwners = (stdout) => {
|
|
129569
|
-
const owners = [];
|
|
129570
|
-
let current2 = null;
|
|
129571
|
-
for (const rawLine of stdout.split(/\r?\n/)) {
|
|
129572
|
-
const line3 = rawLine.trim();
|
|
129573
|
-
if (!line3) {
|
|
129574
|
-
continue;
|
|
129575
|
-
}
|
|
129576
|
-
const kind = line3[0];
|
|
129577
|
-
const value = line3.slice(1);
|
|
129578
|
-
if (kind === "p") {
|
|
129579
|
-
const pid = Number.parseInt(value, 10);
|
|
129580
|
-
if (Number.isInteger(pid) && pid > 0) {
|
|
129581
|
-
current2 = {
|
|
129582
|
-
pid,
|
|
129583
|
-
listenNames: []
|
|
129584
|
-
};
|
|
129585
|
-
owners.push(current2);
|
|
129586
|
-
} else {
|
|
129587
|
-
current2 = null;
|
|
129588
|
-
}
|
|
129589
|
-
continue;
|
|
129590
|
-
}
|
|
129591
|
-
if (!current2) {
|
|
129592
|
-
continue;
|
|
129593
|
-
}
|
|
129594
|
-
if (kind === "c") {
|
|
129595
|
-
current2.name = value;
|
|
129596
|
-
} else if (kind === "n") {
|
|
129597
|
-
current2.listenNames.push(value);
|
|
129598
|
-
}
|
|
129599
|
-
}
|
|
129600
|
-
return owners;
|
|
129601
|
-
};
|
|
129602
|
-
const getPortOwners = async (port) => {
|
|
129603
|
-
try {
|
|
129604
|
-
const { stdout } = await execFile("lsof", [
|
|
129605
|
-
"-nP",
|
|
129606
|
-
`-iTCP:${port}`,
|
|
129607
|
-
"-sTCP:LISTEN",
|
|
129608
|
-
"-Fpcn"
|
|
129609
|
-
], {
|
|
129610
|
-
timeout: 2e3,
|
|
129611
|
-
maxBuffer: 128 * 1024
|
|
129612
|
-
});
|
|
129613
|
-
return parseLsofOwners(stdout);
|
|
129614
|
-
} catch {
|
|
129615
|
-
return [];
|
|
129616
|
-
}
|
|
129617
|
-
};
|
|
129618
|
-
const isLoopbackListenName = (name2, port) => {
|
|
129619
|
-
const lower = name2.toLowerCase();
|
|
129620
|
-
if (lower.includes(`*:${port}`) || lower.includes(`0.0.0.0:${port}`)) {
|
|
129621
|
-
return false;
|
|
129622
|
-
}
|
|
129623
|
-
return lower.includes(`127.0.0.1:${port}`) || lower.includes(`localhost:${port}`) || lower.includes(`[::1]:${port}`) || lower.includes(`::1:${port}`);
|
|
129624
|
-
};
|
|
129625
|
-
const getProcessCwd = async (pid) => {
|
|
129626
|
-
if (process.platform === "linux") {
|
|
129627
|
-
try {
|
|
129628
|
-
return await fs__default$1.realpath(`/proc/${pid}/cwd`);
|
|
129629
|
-
} catch {
|
|
129630
|
-
return null;
|
|
129631
|
-
}
|
|
129632
|
-
}
|
|
129633
|
-
try {
|
|
129634
|
-
const { stdout } = await execFile("lsof", [
|
|
129635
|
-
"-a",
|
|
129636
|
-
"-p",
|
|
129637
|
-
String(pid),
|
|
129638
|
-
"-d",
|
|
129639
|
-
"cwd",
|
|
129640
|
-
"-Fn"
|
|
129641
|
-
], {
|
|
129642
|
-
timeout: 2e3,
|
|
129643
|
-
maxBuffer: 64 * 1024
|
|
129644
|
-
});
|
|
129645
|
-
const cwdLine = stdout.split(/\r?\n/).map((line3) => line3.trim()).find((line3) => line3.startsWith("n"));
|
|
129646
|
-
if (!cwdLine) {
|
|
129647
|
-
return null;
|
|
129648
|
-
}
|
|
129649
|
-
return await fs__default$1.realpath(cwdLine.slice(1));
|
|
129650
|
-
} catch {
|
|
129651
|
-
return null;
|
|
129652
|
-
}
|
|
129653
|
-
};
|
|
129654
|
-
const isPathInside = (child, parent) => {
|
|
129655
|
-
const relative2 = path__default.relative(parent, child);
|
|
129656
|
-
return relative2 === "" || !!relative2 && !relative2.startsWith("..") && !path__default.isAbsolute(relative2);
|
|
129657
|
-
};
|
|
129658
129567
|
const isProcessAlive$1 = (pid) => {
|
|
129659
129568
|
if (!Number.isInteger(pid) || pid <= 0) {
|
|
129660
129569
|
return false;
|
|
@@ -129840,7 +129749,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
129840
129749
|
});
|
|
129841
129750
|
return this.connectionResponse(request.sessionId, false, connection, failure);
|
|
129842
129751
|
}
|
|
129843
|
-
const validation2 = await this.validateTargetForCreate(
|
|
129752
|
+
const validation2 = await this.validateTargetForCreate(candidate.target);
|
|
129844
129753
|
if ("failure" in validation2) {
|
|
129845
129754
|
const connection = this.failedConnection("create", validation2.failure, now2, candidate.target);
|
|
129846
129755
|
await this.patchSessionPreview(request.sessionId, {
|
|
@@ -130066,7 +129975,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
130066
129975
|
connection: revoked
|
|
130067
129976
|
};
|
|
130068
129977
|
}
|
|
130069
|
-
async validateTargetForCreate(
|
|
129978
|
+
async validateTargetForCreate(target) {
|
|
130070
129979
|
const normalized = normalizeTarget(target);
|
|
130071
129980
|
if (isValidationFailure(normalized)) {
|
|
130072
129981
|
return {
|
|
@@ -130079,12 +129988,6 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
130079
129988
|
failure: tcpFailure
|
|
130080
129989
|
};
|
|
130081
129990
|
}
|
|
130082
|
-
const owner = await this.resolveOwnedPort(sessionId, normalized.port);
|
|
130083
|
-
if ("failure" in owner) {
|
|
130084
|
-
return {
|
|
130085
|
-
failure: owner.failure
|
|
130086
|
-
};
|
|
130087
|
-
}
|
|
130088
129991
|
const httpFailure = await probeHttp(normalized);
|
|
130089
129992
|
if (httpFailure) {
|
|
130090
129993
|
return {
|
|
@@ -130092,9 +129995,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
130092
129995
|
};
|
|
130093
129996
|
}
|
|
130094
129997
|
return {
|
|
130095
|
-
normalizedTarget: normalized
|
|
130096
|
-
ownerPid: owner.pid,
|
|
130097
|
-
ownerCwd: owner.cwd
|
|
129998
|
+
normalizedTarget: normalized
|
|
130098
129999
|
};
|
|
130099
130000
|
}
|
|
130100
130001
|
resolveGatewayUrl() {
|
|
@@ -130230,70 +130131,6 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
130230
130131
|
this.deps.logger.debug(`[${sessionId}] Failed to release preview machine slot: ${formatErrorMessage(error2)}`);
|
|
130231
130132
|
});
|
|
130232
130133
|
}
|
|
130233
|
-
async resolveOwnedPort(sessionId, port) {
|
|
130234
|
-
const session = this.deps.sessionManager.getSession(sessionId);
|
|
130235
|
-
const hostWorkdir = session?.getHostWorkdir();
|
|
130236
|
-
if (!hostWorkdir) {
|
|
130237
|
-
return {
|
|
130238
|
-
failure: {
|
|
130239
|
-
code: "process_not_owned_by_session",
|
|
130240
|
-
message: "Preview requires an active local session with a host working directory.",
|
|
130241
|
-
retryable: true
|
|
130242
|
-
}
|
|
130243
|
-
};
|
|
130244
|
-
}
|
|
130245
|
-
const owners = await getPortOwners(port);
|
|
130246
|
-
if (owners.length === 0) {
|
|
130247
|
-
return {
|
|
130248
|
-
failure: {
|
|
130249
|
-
code: "process_not_owned_by_session",
|
|
130250
|
-
message: `Unable to determine which process owns local port ${port}.`,
|
|
130251
|
-
retryable: true
|
|
130252
|
-
}
|
|
130253
|
-
};
|
|
130254
|
-
}
|
|
130255
|
-
const loopbackOwners = owners.filter((owner) => owner.listenNames.length > 0 && owner.listenNames.every((name2) => isLoopbackListenName(name2, port)));
|
|
130256
|
-
if (loopbackOwners.length === 0) {
|
|
130257
|
-
return {
|
|
130258
|
-
failure: {
|
|
130259
|
-
code: "host_not_loopback",
|
|
130260
|
-
message: `Port ${port} is not exclusively bound to a loopback interface.`,
|
|
130261
|
-
retryable: false
|
|
130262
|
-
}
|
|
130263
|
-
};
|
|
130264
|
-
}
|
|
130265
|
-
let realHostWorkdir;
|
|
130266
|
-
try {
|
|
130267
|
-
realHostWorkdir = await fs__default$1.realpath(hostWorkdir);
|
|
130268
|
-
} catch (error2) {
|
|
130269
|
-
return {
|
|
130270
|
-
failure: {
|
|
130271
|
-
code: "process_not_owned_by_session",
|
|
130272
|
-
message: `Unable to resolve session workdir: ${formatErrorMessage(error2)}`,
|
|
130273
|
-
retryable: true
|
|
130274
|
-
}
|
|
130275
|
-
};
|
|
130276
|
-
}
|
|
130277
|
-
for (const owner of loopbackOwners) {
|
|
130278
|
-
const ownerCwd = await getProcessCwd(owner.pid);
|
|
130279
|
-
if (!ownerCwd) {
|
|
130280
|
-
continue;
|
|
130281
|
-
}
|
|
130282
|
-
if (isPathInside(ownerCwd, realHostWorkdir)) {
|
|
130283
|
-
return {
|
|
130284
|
-
pid: owner.pid,
|
|
130285
|
-
cwd: ownerCwd
|
|
130286
|
-
};
|
|
130287
|
-
}
|
|
130288
|
-
}
|
|
130289
|
-
return {
|
|
130290
|
-
failure: {
|
|
130291
|
-
code: "process_not_owned_by_session",
|
|
130292
|
-
message: `Port ${port} is not owned by a process running inside this session workdir.`,
|
|
130293
|
-
retryable: true
|
|
130294
|
-
}
|
|
130295
|
-
};
|
|
130296
|
-
}
|
|
130297
130134
|
async getSessionMeta(sessionId) {
|
|
130298
130135
|
const record2 = await this.deps.workspaceDocument.repo.getDocMeta(getSessionRoomId(sessionId));
|
|
130299
130136
|
if (!record2?.meta || isLoroRepoDocDeleted(record2)) {
|
|
@@ -130528,7 +130365,6 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
130528
130365
|
this.previewService = new PreviewService({
|
|
130529
130366
|
logger: this.logger,
|
|
130530
130367
|
workspaceDocument: this.workspaceDocument,
|
|
130531
|
-
sessionManager: this.sessionManager,
|
|
130532
130368
|
machineId: this.machineId,
|
|
130533
130369
|
workspaceId: this.workspaceId,
|
|
130534
130370
|
userId: this.userId,
|
|
@@ -134296,7 +134132,7 @@ ${escapeHtmlScriptContent(VISUAL_ANNOTATION_INSPECTOR_BROWSER_SCRIPT)}
|
|
|
134296
134132
|
}
|
|
134297
134133
|
async function isGhCliAuthed(logger2) {
|
|
134298
134134
|
return new Promise((resolve2) => {
|
|
134299
|
-
const child = execFile$
|
|
134135
|
+
const child = execFile$1("gh", [
|
|
134300
134136
|
"auth",
|
|
134301
134137
|
"status"
|
|
134302
134138
|
], {
|
|
@@ -142041,7 +141877,7 @@ export PATH=${toSingleQuotedShellString(ghShimBinDir)}:"$PATH"
|
|
|
142041
141877
|
const DEFAULT_LOCAL_PROJECT_READ_MAX_BYTES = 64 * 1024;
|
|
142042
141878
|
const HARD_LOCAL_PROJECT_READ_MAX_BYTES = 1024 * 1024;
|
|
142043
141879
|
const GIT_COMMAND_MAX_BUFFER_BYTES = 64 * 1024 * 1024;
|
|
142044
|
-
const execFileAsync = promisify(execFile
|
|
141880
|
+
const execFileAsync = promisify(execFile);
|
|
142045
141881
|
function clampInteger(value, min2, max2, fallback2) {
|
|
142046
141882
|
if (typeof value !== "number" || Number.isNaN(value) || !Number.isFinite(value)) {
|
|
142047
141883
|
return fallback2;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lody",
|
|
3
|
-
"version": "0.49.
|
|
3
|
+
"version": "0.49.1",
|
|
4
4
|
"description": "Lody Agent CLI tool for managing remote command execution",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -74,8 +74,8 @@
|
|
|
74
74
|
"ws": "^8.18.3",
|
|
75
75
|
"zod": "^4.1.5",
|
|
76
76
|
"@lody/cli-supervisor": "0.0.1",
|
|
77
|
-
"@lody/loro-streams-rpc": "0.0.1",
|
|
78
77
|
"@lody/convex": "0.0.1",
|
|
78
|
+
"@lody/loro-streams-rpc": "0.0.1",
|
|
79
79
|
"@lody/shared": "0.0.1",
|
|
80
80
|
"loro-code": "0.0.1"
|
|
81
81
|
},
|