leglas 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -380
- package/dist/bin.js +233 -132
- package/dist/index.js +173 -115
- package/dist/shell/assets/index-AbZOXGgP.js +14 -0
- package/dist/shell/assets/index-B1S34Qja.css +1 -0
- package/dist/shell/index.html +2 -2
- package/package.json +1 -1
- package/dist/shell/assets/index-BzaBzGEv.css +0 -1
- package/dist/shell/assets/index-CKmxj5gW.js +0 -14
package/dist/index.js
CHANGED
|
@@ -40,7 +40,10 @@ function parseNew(rest) {
|
|
|
40
40
|
return { kind: "error", message: `leglas new does not take ${argument}.` };
|
|
41
41
|
}
|
|
42
42
|
if (surface !== void 0) {
|
|
43
|
-
return {
|
|
43
|
+
return {
|
|
44
|
+
kind: "error",
|
|
45
|
+
message: `leglas new takes one surface name, received ${JSON.stringify(argument)} as well.`
|
|
46
|
+
};
|
|
44
47
|
}
|
|
45
48
|
surface = argument;
|
|
46
49
|
}
|
|
@@ -78,9 +81,16 @@ function parseAdd(rest) {
|
|
|
78
81
|
} else {
|
|
79
82
|
value = argument.slice(equals + 1);
|
|
80
83
|
}
|
|
81
|
-
if (![
|
|
82
|
-
|
|
83
|
-
|
|
84
|
+
if (![
|
|
85
|
+
"--title",
|
|
86
|
+
"--url",
|
|
87
|
+
"--note",
|
|
88
|
+
"--tag",
|
|
89
|
+
"--branch",
|
|
90
|
+
"--file",
|
|
91
|
+
"--based-on",
|
|
92
|
+
"--asked-for"
|
|
93
|
+
].includes(flag)) {
|
|
84
94
|
return { kind: "error", message: `leglas add does not take ${flag}.` };
|
|
85
95
|
}
|
|
86
96
|
if (value === void 0 || value === "") {
|
|
@@ -96,7 +106,10 @@ function parseAdd(rest) {
|
|
|
96
106
|
else tags.push(value);
|
|
97
107
|
}
|
|
98
108
|
if (title === void 0) {
|
|
99
|
-
return {
|
|
109
|
+
return {
|
|
110
|
+
kind: "error",
|
|
111
|
+
message: "leglas add needs --title, which is how the preview is identified."
|
|
112
|
+
};
|
|
100
113
|
}
|
|
101
114
|
if (url === void 0 && file === void 0) {
|
|
102
115
|
return {
|
|
@@ -203,7 +216,10 @@ function parseArgs(argv) {
|
|
|
203
216
|
if (argument === "--to" || argument.startsWith("--to=")) {
|
|
204
217
|
to = argument.includes("=") ? argument.split("=").slice(1).join("=") : rest[index += 1];
|
|
205
218
|
if (to === void 0 || to === "") {
|
|
206
|
-
return {
|
|
219
|
+
return {
|
|
220
|
+
kind: "error",
|
|
221
|
+
message: "--to needs a path, for example --to src/components/hero.tsx"
|
|
222
|
+
};
|
|
207
223
|
}
|
|
208
224
|
continue;
|
|
209
225
|
}
|
|
@@ -222,7 +238,10 @@ function parseArgs(argv) {
|
|
|
222
238
|
};
|
|
223
239
|
}
|
|
224
240
|
if (to === void 0) {
|
|
225
|
-
return {
|
|
241
|
+
return {
|
|
242
|
+
kind: "error",
|
|
243
|
+
message: "leglas keep needs --to, the path the winner should live at."
|
|
244
|
+
};
|
|
226
245
|
}
|
|
227
246
|
return { kind: "keep", title, to, json };
|
|
228
247
|
}
|
|
@@ -333,7 +352,10 @@ function parseArgs(argv) {
|
|
|
333
352
|
continue;
|
|
334
353
|
}
|
|
335
354
|
if (!/^\d+$/.test(raw)) {
|
|
336
|
-
return {
|
|
355
|
+
return {
|
|
356
|
+
kind: "error",
|
|
357
|
+
message: `--width needs a number, received ${JSON.stringify(raw)}.`
|
|
358
|
+
};
|
|
337
359
|
}
|
|
338
360
|
width = Number(raw);
|
|
339
361
|
if (width < MIN_SHOW_WIDTH || width > MAX_SHOW_WIDTH) {
|
|
@@ -592,7 +614,10 @@ function planNew(options) {
|
|
|
592
614
|
},
|
|
593
615
|
{
|
|
594
616
|
path: `${dir}/${slug}-a.tsx`,
|
|
595
|
-
contents: placeholder(
|
|
617
|
+
contents: placeholder(
|
|
618
|
+
`${name}A`,
|
|
619
|
+
`A first direction for ${slug}. Change it and watch it reload.`
|
|
620
|
+
)
|
|
596
621
|
}
|
|
597
622
|
];
|
|
598
623
|
const gitignore = ignoreEntry(options.gitignore);
|
|
@@ -890,7 +915,7 @@ function composeEntry(input) {
|
|
|
890
915
|
`, pictures };
|
|
891
916
|
}
|
|
892
917
|
|
|
893
|
-
// ../server/dist/config.js
|
|
918
|
+
// ../server/dist/config/config.js
|
|
894
919
|
var DEFAULT_DEV_SERVER = "http://localhost:3000";
|
|
895
920
|
var DEFAULT_INSTALL_COMMAND = "npm install";
|
|
896
921
|
var IMPLICIT_PREVIEW = { title: "App", url: "/" };
|
|
@@ -1035,7 +1060,7 @@ function normalizeConfig(raw, options = {}) {
|
|
|
1035
1060
|
};
|
|
1036
1061
|
}
|
|
1037
1062
|
|
|
1038
|
-
// ../server/dist/agent-command.js
|
|
1063
|
+
// ../server/dist/agents/agent-command.js
|
|
1039
1064
|
var WATCH_PATH = ".leglas/watch.json";
|
|
1040
1065
|
var PROMPT_TOKEN = "{prompt}";
|
|
1041
1066
|
var EXAMPLE = `npx leglas watch --run "claude -p ${PROMPT_TOKEN}"`;
|
|
@@ -1117,7 +1142,7 @@ function nextRequest(requests, failed) {
|
|
|
1117
1142
|
return requests.find((request) => request.status === "queued" && !failed.has(request.id)) ?? null;
|
|
1118
1143
|
}
|
|
1119
1144
|
|
|
1120
|
-
// ../server/dist/agents.js
|
|
1145
|
+
// ../server/dist/agents/agents.js
|
|
1121
1146
|
import { spawn } from "child_process";
|
|
1122
1147
|
import { constants, readdirSync } from "fs";
|
|
1123
1148
|
import { access, mkdir, readFile, writeFile } from "fs/promises";
|
|
@@ -1125,10 +1150,7 @@ import { delimiter, dirname, isAbsolute, join, relative } from "path";
|
|
|
1125
1150
|
var AGENT_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
1126
1151
|
var effortFlag = (effort) => effort === null ? [] : ["--effort", effort];
|
|
1127
1152
|
var codexEffortConfig = (effort) => effort === null ? [] : ["-c", `model_reasoning_effort=${effort}`];
|
|
1128
|
-
var CODEX_WORKSPACE_CONFIG = [
|
|
1129
|
-
"-c",
|
|
1130
|
-
"sandbox_workspace_write.network_access=true"
|
|
1131
|
-
];
|
|
1153
|
+
var CODEX_WORKSPACE_CONFIG = ["-c", "sandbox_workspace_write.network_access=true"];
|
|
1132
1154
|
var KNOWN_AGENTS = {
|
|
1133
1155
|
claude: {
|
|
1134
1156
|
name: "Claude",
|
|
@@ -1144,13 +1166,7 @@ var KNOWN_AGENTS = {
|
|
|
1144
1166
|
"acceptEdits",
|
|
1145
1167
|
...effortFlag(effort)
|
|
1146
1168
|
],
|
|
1147
|
-
terminalArgs: (prompt, effort = null, _images = []) => [
|
|
1148
|
-
"-p",
|
|
1149
|
-
prompt,
|
|
1150
|
-
"--permission-mode",
|
|
1151
|
-
"acceptEdits",
|
|
1152
|
-
...effortFlag(effort)
|
|
1153
|
-
],
|
|
1169
|
+
terminalArgs: (prompt, effort = null, _images = []) => ["-p", prompt, "--permission-mode", "acceptEdits", ...effortFlag(effort)],
|
|
1154
1170
|
resumeArgs: (sessionId, prompt, effort = null, _images = []) => [
|
|
1155
1171
|
"-p",
|
|
1156
1172
|
"--resume",
|
|
@@ -1254,13 +1270,7 @@ var KNOWN_AGENTS = {
|
|
|
1254
1270
|
// project is the one the user pointed Leglas at, which is the trust the
|
|
1255
1271
|
// flag grants. It is the only permission the run needs: with it alone,
|
|
1256
1272
|
// the edit and the shell command in the same run both executed.
|
|
1257
|
-
args: (prompt, _effort = null, _images = []) => [
|
|
1258
|
-
"-p",
|
|
1259
|
-
prompt,
|
|
1260
|
-
"--output-format",
|
|
1261
|
-
"stream-json",
|
|
1262
|
-
"--trust"
|
|
1263
|
-
],
|
|
1273
|
+
args: (prompt, _effort = null, _images = []) => ["-p", prompt, "--output-format", "stream-json", "--trust"],
|
|
1264
1274
|
terminalArgs: (prompt, _effort = null, _images = []) => ["-p", prompt, "--trust"],
|
|
1265
1275
|
// `--resume [chatId]` is documented alongside `--continue` in the CLI
|
|
1266
1276
|
// parameter reference, and every stream-json event carries the
|
|
@@ -1272,7 +1282,15 @@ var KNOWN_AGENTS = {
|
|
|
1272
1282
|
// Images are accepted and ignored, like its other argument builders:
|
|
1273
1283
|
// `cursor-agent` documents no flag for them, and the capture paths reach
|
|
1274
1284
|
// it as text in the prompt either way.
|
|
1275
|
-
resumeArgs: (sessionId, prompt, _effort = null, _images = []) => [
|
|
1285
|
+
resumeArgs: (sessionId, prompt, _effort = null, _images = []) => [
|
|
1286
|
+
"-p",
|
|
1287
|
+
"--resume",
|
|
1288
|
+
sessionId,
|
|
1289
|
+
prompt,
|
|
1290
|
+
"--output-format",
|
|
1291
|
+
"stream-json",
|
|
1292
|
+
"--trust"
|
|
1293
|
+
],
|
|
1276
1294
|
sessionFrom: (event) => typeof event.session_id === "string" && event.session_id !== "" ? event.session_id : null,
|
|
1277
1295
|
// Read against cursor-agent 2026.09.02: every event carries the id, a
|
|
1278
1296
|
// resume in this argument order answers under the same id and remembers
|
|
@@ -1600,7 +1618,7 @@ async function saveAgentChoice(cwd, choice) {
|
|
|
1600
1618
|
`, "utf8");
|
|
1601
1619
|
}
|
|
1602
1620
|
|
|
1603
|
-
// ../server/dist/classify.js
|
|
1621
|
+
// ../server/dist/branches/classify.js
|
|
1604
1622
|
var MANIFESTS = /* @__PURE__ */ new Set([
|
|
1605
1623
|
"package.json",
|
|
1606
1624
|
"pnpm-lock.yaml",
|
|
@@ -1645,7 +1663,11 @@ var IN_APP_STEPS = [
|
|
|
1645
1663
|
'Register it: npx leglas add --title "<title>" --url "/?v-<surface>=<direction>".'
|
|
1646
1664
|
];
|
|
1647
1665
|
function classifyDirection(input) {
|
|
1648
|
-
const checkout = (reason) => ({
|
|
1666
|
+
const checkout = (reason) => ({
|
|
1667
|
+
level: "checkout",
|
|
1668
|
+
reason,
|
|
1669
|
+
steps: CHECKOUT_STEPS
|
|
1670
|
+
});
|
|
1649
1671
|
const manifest = input.changes.find((change) => isManifest(change.path));
|
|
1650
1672
|
if (manifest !== void 0) {
|
|
1651
1673
|
return checkout(`${manifest.path} changes the dependency set, and one running server cannot hold two.`);
|
|
@@ -1665,7 +1687,7 @@ function classifyDirection(input) {
|
|
|
1665
1687
|
};
|
|
1666
1688
|
}
|
|
1667
1689
|
|
|
1668
|
-
// ../server/dist/find-config.js
|
|
1690
|
+
// ../server/dist/config/find-config.js
|
|
1669
1691
|
import { existsSync } from "fs";
|
|
1670
1692
|
import { dirname as dirname2, join as join2, parse } from "path";
|
|
1671
1693
|
var CONFIG_BASENAMES = [
|
|
@@ -1692,7 +1714,7 @@ function findConfigFile(startDir) {
|
|
|
1692
1714
|
}
|
|
1693
1715
|
}
|
|
1694
1716
|
|
|
1695
|
-
// ../server/dist/load-config.js
|
|
1717
|
+
// ../server/dist/config/load-config.js
|
|
1696
1718
|
import { readFile as readFile2 } from "fs/promises";
|
|
1697
1719
|
import { relative as relative2 } from "path";
|
|
1698
1720
|
import { pathToFileURL } from "url";
|
|
@@ -1725,7 +1747,7 @@ async function loadConfig(cwd) {
|
|
|
1725
1747
|
};
|
|
1726
1748
|
}
|
|
1727
1749
|
|
|
1728
|
-
// ../server/dist/local-previews.js
|
|
1750
|
+
// ../server/dist/config/local-previews.js
|
|
1729
1751
|
import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
|
|
1730
1752
|
import { dirname as dirname3, join as join3 } from "path";
|
|
1731
1753
|
var LOCAL_PREVIEWS_PATH = ".leglas/previews.json";
|
|
@@ -1759,7 +1781,10 @@ async function readLocalPreviews(cwd) {
|
|
|
1759
1781
|
}
|
|
1760
1782
|
const result = normalizeConfig(parsed, { requireDevCommand: false });
|
|
1761
1783
|
if (result.config === null) {
|
|
1762
|
-
return {
|
|
1784
|
+
return {
|
|
1785
|
+
previews: [],
|
|
1786
|
+
errors: result.errors.map((error) => `${LOCAL_PREVIEWS_PATH}: ${error}`)
|
|
1787
|
+
};
|
|
1763
1788
|
}
|
|
1764
1789
|
return {
|
|
1765
1790
|
previews: result.config.previews.map((preview) => ({ ...preview, local: true })),
|
|
@@ -1842,7 +1867,10 @@ function createProxyHandler(options) {
|
|
|
1842
1867
|
function rewriteLocation(location, publicOrigin2) {
|
|
1843
1868
|
if (location === void 0)
|
|
1844
1869
|
return void 0;
|
|
1845
|
-
for (const origin of [
|
|
1870
|
+
for (const origin of [
|
|
1871
|
+
`${target.protocol}//${authority}`,
|
|
1872
|
+
`${target.protocol}//localhost:${port}`
|
|
1873
|
+
]) {
|
|
1846
1874
|
if (location.startsWith(origin))
|
|
1847
1875
|
return publicOrigin2 + location.slice(origin.length);
|
|
1848
1876
|
}
|
|
@@ -1974,7 +2002,7 @@ function startProxyServer(options) {
|
|
|
1974
2002
|
});
|
|
1975
2003
|
}
|
|
1976
2004
|
|
|
1977
|
-
// ../server/dist/browser.js
|
|
2005
|
+
// ../server/dist/capture/browser.js
|
|
1978
2006
|
import { randomBytes } from "crypto";
|
|
1979
2007
|
import nodeProcess from "process";
|
|
1980
2008
|
import { spawn as nodeSpawn } from "child_process";
|
|
@@ -2024,8 +2052,20 @@ function firstOnPath(name, env) {
|
|
|
2024
2052
|
return null;
|
|
2025
2053
|
}
|
|
2026
2054
|
var FOR_TESTING = [
|
|
2027
|
-
[
|
|
2028
|
-
|
|
2055
|
+
[
|
|
2056
|
+
"chrome-mac-arm64",
|
|
2057
|
+
"Google Chrome for Testing.app",
|
|
2058
|
+
"Contents",
|
|
2059
|
+
"MacOS",
|
|
2060
|
+
"Google Chrome for Testing"
|
|
2061
|
+
],
|
|
2062
|
+
[
|
|
2063
|
+
"chrome-mac-x64",
|
|
2064
|
+
"Google Chrome for Testing.app",
|
|
2065
|
+
"Contents",
|
|
2066
|
+
"MacOS",
|
|
2067
|
+
"Google Chrome for Testing"
|
|
2068
|
+
],
|
|
2029
2069
|
["chrome-linux64", "chrome"],
|
|
2030
2070
|
["chrome-linux", "chrome"],
|
|
2031
2071
|
["chrome-win64", "chrome.exe"]
|
|
@@ -2627,7 +2667,7 @@ function createBrowserPool(options = {}) {
|
|
|
2627
2667
|
};
|
|
2628
2668
|
}
|
|
2629
2669
|
|
|
2630
|
-
// ../server/dist/hydration.js
|
|
2670
|
+
// ../server/dist/capture/hydration.js
|
|
2631
2671
|
function hydrationEvidence(messages) {
|
|
2632
2672
|
for (const raw of messages) {
|
|
2633
2673
|
const message2 = raw.split("\n", 1)[0]?.trim() ?? "";
|
|
@@ -2653,7 +2693,7 @@ function hydrationEvidence(messages) {
|
|
|
2653
2693
|
return null;
|
|
2654
2694
|
}
|
|
2655
2695
|
|
|
2656
|
-
// ../server/dist/capture.js
|
|
2696
|
+
// ../server/dist/capture/capture.js
|
|
2657
2697
|
var FRAME_MAX_HEIGHT = 4e3;
|
|
2658
2698
|
var MIN_WIDTH = 320;
|
|
2659
2699
|
var MAX_WIDTH = 3840;
|
|
@@ -2910,7 +2950,7 @@ async function capturePage(browser, input) {
|
|
|
2910
2950
|
return browser.withPage((page) => abortable(render(page, input), abortInput.signal));
|
|
2911
2951
|
}
|
|
2912
2952
|
|
|
2913
|
-
// ../server/dist/attachments.js
|
|
2953
|
+
// ../server/dist/requests/attachments.js
|
|
2914
2954
|
import { copyFile, lstat, mkdir as mkdir3, readdir as readdir2, readFile as readFile5, realpath, rename, rm as rm2, stat as stat2, unlink, writeFile as writeFile3 } from "fs/promises";
|
|
2915
2955
|
import { basename as basename2, extname, join as join5, resolve, sep } from "path";
|
|
2916
2956
|
var CAPTURES_DIR = ".leglas/captures";
|
|
@@ -3225,7 +3265,7 @@ async function pruneReferences(cwd) {
|
|
|
3225
3265
|
}
|
|
3226
3266
|
}
|
|
3227
3267
|
|
|
3228
|
-
// ../server/dist/worktree.js
|
|
3268
|
+
// ../server/dist/branches/worktree.js
|
|
3229
3269
|
import { execFile, spawn as spawn2 } from "child_process";
|
|
3230
3270
|
import { rm as rm3 } from "fs/promises";
|
|
3231
3271
|
import net2 from "net";
|
|
@@ -3372,7 +3412,7 @@ async function startAppProcess(options) {
|
|
|
3372
3412
|
throw new Error(`${options.label} did not start within ${Math.round(readyTimeoutMs / 1e3)}s. Check that its dev command serves the port it is given.`);
|
|
3373
3413
|
}
|
|
3374
3414
|
|
|
3375
|
-
// ../server/dist/branches.js
|
|
3415
|
+
// ../server/dist/branches/branches.js
|
|
3376
3416
|
var BRANCH_IDLE_MS = 10 * 60 * 1e3;
|
|
3377
3417
|
var BRANCH_SWEEP_MS = 3e4;
|
|
3378
3418
|
function publicBranchState(state) {
|
|
@@ -3507,7 +3547,7 @@ function createBranchRegistry(options) {
|
|
|
3507
3547
|
};
|
|
3508
3548
|
}
|
|
3509
3549
|
|
|
3510
|
-
// ../server/dist/failure.js
|
|
3550
|
+
// ../server/dist/agents/failure.js
|
|
3511
3551
|
var NEEDS_TRUST = /not inside a trusted directory|--skip-git-repo-check/i;
|
|
3512
3552
|
var MISSING_BINARY = /\b(ENOENT|EACCES|ENOTDIR)\b/;
|
|
3513
3553
|
var NOT_SIGNED_IN = /not logged in|not signed in|please (?:re-?)?(?:run|sign|log)\s*in|\/login\b|invalid api key|unauthorized|authentication_failed|\b401\b/i;
|
|
@@ -3574,7 +3614,7 @@ function sessionShaped(code) {
|
|
|
3574
3614
|
return code === "agent-error";
|
|
3575
3615
|
}
|
|
3576
3616
|
|
|
3577
|
-
// ../server/dist/annotations.js
|
|
3617
|
+
// ../server/dist/requests/annotations.js
|
|
3578
3618
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
3579
3619
|
import { mkdir as mkdir4, readFile as readFile6, writeFile as writeFile4 } from "fs/promises";
|
|
3580
3620
|
import { dirname as dirname4, join as join7 } from "path";
|
|
@@ -3738,7 +3778,7 @@ function describeAnnotations(annotations) {
|
|
|
3738
3778
|
}).join("\n\n");
|
|
3739
3779
|
}
|
|
3740
3780
|
|
|
3741
|
-
// ../server/dist/requests.js
|
|
3781
|
+
// ../server/dist/requests/requests.js
|
|
3742
3782
|
import { mkdir as mkdir5, readFile as readFile7, writeFile as writeFile5 } from "fs/promises";
|
|
3743
3783
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
3744
3784
|
import { dirname as dirname5, join as join8 } from "path";
|
|
@@ -3952,10 +3992,7 @@ async function writeQueue(cwd, requests) {
|
|
|
3952
3992
|
`, "utf8");
|
|
3953
3993
|
}
|
|
3954
3994
|
async function appendRequest(cwd, request, id = newRequestId()) {
|
|
3955
|
-
await writeQueue(cwd, [
|
|
3956
|
-
...await readRequests(cwd),
|
|
3957
|
-
{ ...request, id, status: "queued" }
|
|
3958
|
-
]);
|
|
3995
|
+
await writeQueue(cwd, [...await readRequests(cwd), { ...request, id, status: "queued" }]);
|
|
3959
3996
|
}
|
|
3960
3997
|
function newRequestId() {
|
|
3961
3998
|
return randomBytes3(6).toString("base64url");
|
|
@@ -4007,12 +4044,12 @@ async function clearRequests(cwd) {
|
|
|
4007
4044
|
return { cleared, pending: pending.length };
|
|
4008
4045
|
}
|
|
4009
4046
|
|
|
4010
|
-
// ../server/dist/runner.js
|
|
4047
|
+
// ../server/dist/agents/runner.js
|
|
4011
4048
|
import { spawn as nodeSpawn3 } from "child_process";
|
|
4012
4049
|
import { readFile as readFile9 } from "fs/promises";
|
|
4013
4050
|
import { join as join9, resolve as resolve2, sep as sep2 } from "path";
|
|
4014
4051
|
|
|
4015
|
-
// ../server/dist/claude-agent-session.js
|
|
4052
|
+
// ../server/dist/agents/claude-agent-session.js
|
|
4016
4053
|
import { EventEmitter } from "events";
|
|
4017
4054
|
import { readFile as readFile8, stat as stat3 } from "fs/promises";
|
|
4018
4055
|
import { extname as extname2 } from "path";
|
|
@@ -4423,7 +4460,7 @@ function createClaudeAgentSession(cwd, allowedCommands = [], startup = defaultSt
|
|
|
4423
4460
|
return new PersistentClaudeSession(cwd, allowedCommands, startup);
|
|
4424
4461
|
}
|
|
4425
4462
|
|
|
4426
|
-
// ../server/dist/codex-app-server.js
|
|
4463
|
+
// ../server/dist/agents/codex-app-server.js
|
|
4427
4464
|
import { spawn as nodeSpawn2 } from "child_process";
|
|
4428
4465
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
4429
4466
|
import { PassThrough as PassThrough2 } from "stream";
|
|
@@ -4846,17 +4883,11 @@ var PersistentCodexAppServer = class {
|
|
|
4846
4883
|
});
|
|
4847
4884
|
});
|
|
4848
4885
|
process2.kill("SIGTERM");
|
|
4849
|
-
await Promise.race([
|
|
4850
|
-
ended,
|
|
4851
|
-
new Promise((resolve5) => setTimeout(resolve5, 1e3))
|
|
4852
|
-
]);
|
|
4886
|
+
await Promise.race([ended, new Promise((resolve5) => setTimeout(resolve5, 1e3))]);
|
|
4853
4887
|
if (closed)
|
|
4854
4888
|
return;
|
|
4855
4889
|
process2.kill("SIGKILL");
|
|
4856
|
-
await Promise.race([
|
|
4857
|
-
ended,
|
|
4858
|
-
new Promise((resolve5) => setTimeout(resolve5, 1e3))
|
|
4859
|
-
]);
|
|
4890
|
+
await Promise.race([ended, new Promise((resolve5) => setTimeout(resolve5, 1e3))]);
|
|
4860
4891
|
}
|
|
4861
4892
|
failProcess(process2, error) {
|
|
4862
4893
|
if (this.process !== process2)
|
|
@@ -4901,7 +4932,7 @@ function createCodexAppServer(cwd, spawn4 = defaultSpawn, requestTimeoutMs = REQ
|
|
|
4901
4932
|
return new PersistentCodexAppServer(cwd, spawn4, requestTimeoutMs);
|
|
4902
4933
|
}
|
|
4903
4934
|
|
|
4904
|
-
// ../server/dist/runner.js
|
|
4935
|
+
// ../server/dist/agents/runner.js
|
|
4905
4936
|
var POLL_MS = 2e3;
|
|
4906
4937
|
var OUTPUT_LINES = 20;
|
|
4907
4938
|
var IDLE_RELEASE_MS = 5 * 6e4;
|
|
@@ -4978,10 +5009,7 @@ function defaultSpawn2(command, args, options) {
|
|
|
4978
5009
|
function startRunner(options) {
|
|
4979
5010
|
const spawn4 = options.spawn ?? defaultSpawn2;
|
|
4980
5011
|
const codexAppServer = options.codexAppServer === void 0 ? options.spawn === void 0 ? createCodexAppServer(options.cwd) : null : options.codexAppServer;
|
|
4981
|
-
const claudeAgentSession = options.claudeAgentSession === void 0 ? options.spawn === void 0 ? createClaudeAgentSession(options.cwd, options.leglasCommand === void 0 ? [] : [
|
|
4982
|
-
`${options.leglasCommand} show`,
|
|
4983
|
-
registrationCommand(options.leglasCommand)
|
|
4984
|
-
]) : null : options.claudeAgentSession;
|
|
5012
|
+
const claudeAgentSession = options.claudeAgentSession === void 0 ? options.spawn === void 0 ? createClaudeAgentSession(options.cwd, options.leglasCommand === void 0 ? [] : [`${options.leglasCommand} show`, registrationCommand(options.leglasCommand)]) : null : options.claudeAgentSession;
|
|
4985
5013
|
const setEvery = options.setInterval ?? ((callback, milliseconds) => setInterval(callback, milliseconds));
|
|
4986
5014
|
const clearEvery = options.clearInterval ?? ((handle2) => clearInterval(handle2));
|
|
4987
5015
|
const failed = /* @__PURE__ */ new Set();
|
|
@@ -5360,10 +5388,7 @@ function startRunner(options) {
|
|
|
5360
5388
|
clearEvery(timer);
|
|
5361
5389
|
cancel();
|
|
5362
5390
|
stopPromise = Promise.resolve(ticking).catch(() => {
|
|
5363
|
-
}).then(() => Promise.all([
|
|
5364
|
-
codexAppServer?.close(),
|
|
5365
|
-
claudeAgentSession?.close()
|
|
5366
|
-
])).then(() => {
|
|
5391
|
+
}).then(() => Promise.all([codexAppServer?.close(), claudeAgentSession?.close()])).then(() => {
|
|
5367
5392
|
});
|
|
5368
5393
|
return stopPromise;
|
|
5369
5394
|
};
|
|
@@ -5581,12 +5606,12 @@ Sec-WebSocket-Accept: ${accept}\r
|
|
|
5581
5606
|
};
|
|
5582
5607
|
}
|
|
5583
5608
|
|
|
5584
|
-
// ../server/dist/share.js
|
|
5609
|
+
// ../server/dist/share/share.js
|
|
5585
5610
|
import { randomBytes as randomBytes4, randomUUID, timingSafeEqual } from "crypto";
|
|
5586
5611
|
import http3 from "http";
|
|
5587
5612
|
import { posix } from "path";
|
|
5588
5613
|
|
|
5589
|
-
// ../server/dist/tunnel.js
|
|
5614
|
+
// ../server/dist/share/tunnel.js
|
|
5590
5615
|
import { spawn as spawnChild } from "child_process";
|
|
5591
5616
|
import { Resolver, lookup } from "dns/promises";
|
|
5592
5617
|
import http2 from "http";
|
|
@@ -5707,12 +5732,7 @@ function startTunnel(options, deps = {}) {
|
|
|
5707
5732
|
});
|
|
5708
5733
|
};
|
|
5709
5734
|
report(state);
|
|
5710
|
-
const args = options.provider === "cloudflared" ? [
|
|
5711
|
-
"tunnel",
|
|
5712
|
-
"--url",
|
|
5713
|
-
`http://127.0.0.1:${options.port}`,
|
|
5714
|
-
"--no-autoupdate"
|
|
5715
|
-
] : ["http", String(options.port), "--log", "stdout", "--log-format", "json"];
|
|
5735
|
+
const args = options.provider === "cloudflared" ? ["tunnel", "--url", `http://127.0.0.1:${options.port}`, "--no-autoupdate"] : ["http", String(options.port), "--log", "stdout", "--log-format", "json"];
|
|
5716
5736
|
let child;
|
|
5717
5737
|
try {
|
|
5718
5738
|
child = spawn4(options.provider, args, {
|
|
@@ -5874,7 +5894,7 @@ function startTunnel(options, deps = {}) {
|
|
|
5874
5894
|
};
|
|
5875
5895
|
}
|
|
5876
5896
|
|
|
5877
|
-
// ../server/dist/share.js
|
|
5897
|
+
// ../server/dist/share/share.js
|
|
5878
5898
|
var MAX_REFUSED = 40;
|
|
5879
5899
|
function routeAllowed(routes, url) {
|
|
5880
5900
|
const [rawPath = "/"] = url.split("?", 2);
|
|
@@ -6051,9 +6071,7 @@ function manifestFrom(value, previews) {
|
|
|
6051
6071
|
error: `Directions are not available to share: ${unknown.join(", ")}.`
|
|
6052
6072
|
};
|
|
6053
6073
|
}
|
|
6054
|
-
const branches = [
|
|
6055
|
-
...new Set(titles.filter((title) => byTitle.get(title)?.branch !== void 0))
|
|
6056
|
-
];
|
|
6074
|
+
const branches = [...new Set(titles.filter((title) => byTitle.get(title)?.branch !== void 0))];
|
|
6057
6075
|
if (branches.length > 0) {
|
|
6058
6076
|
return {
|
|
6059
6077
|
ok: false,
|
|
@@ -6898,7 +6916,7 @@ function createShareManager(options) {
|
|
|
6898
6916
|
};
|
|
6899
6917
|
}
|
|
6900
6918
|
|
|
6901
|
-
// ../server/dist/renames.js
|
|
6919
|
+
// ../server/dist/config/renames.js
|
|
6902
6920
|
import { mkdir as mkdir6, readFile as readFile10, writeFile as writeFile6 } from "fs/promises";
|
|
6903
6921
|
import { dirname as dirname6, join as join10 } from "path";
|
|
6904
6922
|
var RENAMES_PATH = ".leglas/renames.json";
|
|
@@ -8024,11 +8042,17 @@ async function startServer(options) {
|
|
|
8024
8042
|
return sendJson2(res, 400, { ok: false, error: "Body needs a known agent." });
|
|
8025
8043
|
}
|
|
8026
8044
|
if (parsed.run !== void 0 && typeof parsed.run !== "string") {
|
|
8027
|
-
return sendJson2(res, 400, {
|
|
8045
|
+
return sendJson2(res, 400, {
|
|
8046
|
+
ok: false,
|
|
8047
|
+
error: "The custom run command must be a string."
|
|
8048
|
+
});
|
|
8028
8049
|
}
|
|
8029
8050
|
const effort = parsed.effort === null || isAgentEffort(parsed.effort) ? parsed.effort : void 0;
|
|
8030
8051
|
if (parsed.effort !== void 0 && effort === void 0) {
|
|
8031
|
-
return sendJson2(res, 400, {
|
|
8052
|
+
return sendJson2(res, 400, {
|
|
8053
|
+
ok: false,
|
|
8054
|
+
error: "Effort must be a supported level or null."
|
|
8055
|
+
});
|
|
8032
8056
|
}
|
|
8033
8057
|
if (parsed.agent === "custom") {
|
|
8034
8058
|
if (effort !== void 0) {
|
|
@@ -8155,7 +8179,10 @@ async function startServer(options) {
|
|
|
8155
8179
|
return sendJson2(res, 404, { ok: false, error: "No such request." });
|
|
8156
8180
|
}
|
|
8157
8181
|
if (!isEnded(request, runner?.snapshot().failedIds ?? [])) {
|
|
8158
|
-
return sendJson2(res, 400, {
|
|
8182
|
+
return sendJson2(res, 400, {
|
|
8183
|
+
ok: false,
|
|
8184
|
+
error: "Only an ended request can be run again."
|
|
8185
|
+
});
|
|
8159
8186
|
}
|
|
8160
8187
|
try {
|
|
8161
8188
|
const retryId = newRequestId();
|
|
@@ -8287,7 +8314,10 @@ async function startServer(options) {
|
|
|
8287
8314
|
}
|
|
8288
8315
|
const target2 = (await readRequests(cwd)).find((entry) => entry.id === parsed.id);
|
|
8289
8316
|
if (target2 === void 0 || !isEnded(target2, runner?.snapshot().failedIds ?? [])) {
|
|
8290
|
-
return sendJson2(res, 400, {
|
|
8317
|
+
return sendJson2(res, 400, {
|
|
8318
|
+
ok: false,
|
|
8319
|
+
error: "Only an ended request can be dismissed."
|
|
8320
|
+
});
|
|
8291
8321
|
}
|
|
8292
8322
|
try {
|
|
8293
8323
|
if (!await removeRequest(cwd, parsed.id)) {
|
|
@@ -8331,7 +8361,10 @@ async function startServer(options) {
|
|
|
8331
8361
|
const serveMount = () => {
|
|
8332
8362
|
if (dir !== void 0 && relative6 !== "" && serveFrom(res, dir, relative6))
|
|
8333
8363
|
return;
|
|
8334
|
-
res.writeHead(404, {
|
|
8364
|
+
res.writeHead(404, {
|
|
8365
|
+
"content-type": "text/plain; charset=utf-8",
|
|
8366
|
+
"cache-control": "no-store"
|
|
8367
|
+
});
|
|
8335
8368
|
res.end("Leglas: no such preview file.");
|
|
8336
8369
|
};
|
|
8337
8370
|
if (!context.remote)
|
|
@@ -8352,11 +8385,17 @@ async function startServer(options) {
|
|
|
8352
8385
|
if (shellDir !== null && serveShellFile(res, shellDir, path))
|
|
8353
8386
|
return;
|
|
8354
8387
|
if (shellDir !== null) {
|
|
8355
|
-
res.writeHead(404, {
|
|
8388
|
+
res.writeHead(404, {
|
|
8389
|
+
"content-type": "text/plain; charset=utf-8",
|
|
8390
|
+
"cache-control": "no-store"
|
|
8391
|
+
});
|
|
8356
8392
|
res.end("Leglas: no such path.");
|
|
8357
8393
|
return;
|
|
8358
8394
|
}
|
|
8359
|
-
res.writeHead(200, {
|
|
8395
|
+
res.writeHead(200, {
|
|
8396
|
+
"content-type": "text/html; charset=utf-8",
|
|
8397
|
+
"cache-control": "no-store"
|
|
8398
|
+
});
|
|
8360
8399
|
res.end(PLACEHOLDER);
|
|
8361
8400
|
return;
|
|
8362
8401
|
}
|
|
@@ -8590,10 +8629,7 @@ function resolveOrExplain(input, titles, renames) {
|
|
|
8590
8629
|
function renameExport(source, to) {
|
|
8591
8630
|
const match = /export function ([A-Za-z0-9_]+)\s*\(/.exec(source);
|
|
8592
8631
|
if (!match || match[1] === void 0) return source;
|
|
8593
|
-
return source.replace(
|
|
8594
|
-
new RegExp(`\\b${match[1]}\\b`, "g"),
|
|
8595
|
-
to
|
|
8596
|
-
);
|
|
8632
|
+
return source.replace(new RegExp(`\\b${match[1]}\\b`, "g"), to);
|
|
8597
8633
|
}
|
|
8598
8634
|
async function writeLogEntry(options) {
|
|
8599
8635
|
const entry = composeEntry({
|
|
@@ -8736,7 +8772,14 @@ async function runNew(options, deps) {
|
|
|
8736
8772
|
}
|
|
8737
8773
|
if (options.print) {
|
|
8738
8774
|
if (options.json) {
|
|
8739
|
-
deps.log(
|
|
8775
|
+
deps.log(
|
|
8776
|
+
JSON.stringify({
|
|
8777
|
+
ok: true,
|
|
8778
|
+
files: plan.writes,
|
|
8779
|
+
instructions: plan.instructions,
|
|
8780
|
+
previews: plan.previews
|
|
8781
|
+
})
|
|
8782
|
+
);
|
|
8740
8783
|
return { exitCode: 0, written: [] };
|
|
8741
8784
|
}
|
|
8742
8785
|
for (const write2 of plan.writes) {
|
|
@@ -8748,7 +8791,9 @@ async function runNew(options, deps) {
|
|
|
8748
8791
|
}
|
|
8749
8792
|
const existing = plan.writes.filter((write2) => existsSync6(join16(options.cwd, write2.path)));
|
|
8750
8793
|
if (existing.length > 0) {
|
|
8751
|
-
return fail(
|
|
8794
|
+
return fail(
|
|
8795
|
+
`${existing[0]?.path} already exists. Delete it first, or pick another surface name.`
|
|
8796
|
+
);
|
|
8752
8797
|
}
|
|
8753
8798
|
const written = [];
|
|
8754
8799
|
for (const write2 of plan.writes) {
|
|
@@ -8763,7 +8808,12 @@ async function runNew(options, deps) {
|
|
|
8763
8808
|
}
|
|
8764
8809
|
if (options.json) {
|
|
8765
8810
|
deps.log(
|
|
8766
|
-
JSON.stringify({
|
|
8811
|
+
JSON.stringify({
|
|
8812
|
+
ok: true,
|
|
8813
|
+
written,
|
|
8814
|
+
instructions: plan.instructions,
|
|
8815
|
+
previews: plan.previews
|
|
8816
|
+
})
|
|
8767
8817
|
);
|
|
8768
8818
|
return { exitCode: 0, written };
|
|
8769
8819
|
}
|
|
@@ -8773,7 +8823,9 @@ async function runNew(options, deps) {
|
|
|
8773
8823
|
deps.log("Then register them so they appear in the interface:");
|
|
8774
8824
|
deps.log("");
|
|
8775
8825
|
for (const preview of plan.previews) {
|
|
8776
|
-
deps.log(
|
|
8826
|
+
deps.log(
|
|
8827
|
+
` npx leglas add --title ${JSON.stringify(preview.title)} --url ${JSON.stringify(preview.url)}`
|
|
8828
|
+
);
|
|
8777
8829
|
}
|
|
8778
8830
|
return { exitCode: 0, written };
|
|
8779
8831
|
}
|
|
@@ -8837,7 +8889,9 @@ async function runAdd(options, deps) {
|
|
|
8837
8889
|
...options.preview.branch === void 0 ? {} : { branch: options.preview.branch },
|
|
8838
8890
|
...options.preview.file === void 0 ? {} : { file: options.preview.file },
|
|
8839
8891
|
note: options.preview.branch === void 0 && options.preview.file === void 0 ? "A running interface picks this up within seconds." : "Restart Leglas to see this preview: branch checkouts and file mounts are built when Leglas starts.",
|
|
8840
|
-
...needsDevCommand ? {
|
|
8892
|
+
...needsDevCommand ? {
|
|
8893
|
+
warning: "The config sets no devCommand, so Leglas cannot start this branch yet. Add devCommand (with {port}) to the config."
|
|
8894
|
+
} : {}
|
|
8841
8895
|
});
|
|
8842
8896
|
} else {
|
|
8843
8897
|
deps.log(
|
|
@@ -9061,7 +9115,8 @@ async function runShow(options, deps) {
|
|
|
9061
9115
|
typeof captured.error === "string" ? captured.error : "The direction could not be captured."
|
|
9062
9116
|
);
|
|
9063
9117
|
}
|
|
9064
|
-
if (typeof captured.file !== "string" || typeof captured.width !== "number" || typeof captured.height !== "number" || typeof captured.viewport !== "number")
|
|
9118
|
+
if (typeof captured.file !== "string" || typeof captured.width !== "number" || typeof captured.height !== "number" || typeof captured.viewport !== "number")
|
|
9119
|
+
return fail("The direction could not be captured.");
|
|
9065
9120
|
envelope2.screenshot = {
|
|
9066
9121
|
file: captured.file,
|
|
9067
9122
|
width: captured.width,
|
|
@@ -9334,10 +9389,14 @@ function localDevServerPort(origin) {
|
|
|
9334
9389
|
}
|
|
9335
9390
|
}
|
|
9336
9391
|
function parseListeningPids(output) {
|
|
9337
|
-
return [
|
|
9338
|
-
|
|
9339
|
-
|
|
9340
|
-
|
|
9392
|
+
return [
|
|
9393
|
+
...new Set(
|
|
9394
|
+
output.split("\n").flatMap((line) => {
|
|
9395
|
+
if (!/^p\d+$/.test(line)) return [];
|
|
9396
|
+
return [Number(line.slice(1))];
|
|
9397
|
+
})
|
|
9398
|
+
)
|
|
9399
|
+
];
|
|
9341
9400
|
}
|
|
9342
9401
|
function parseOwnerCwds(output) {
|
|
9343
9402
|
const owners = [];
|
|
@@ -9360,11 +9419,10 @@ async function inspectLocalDevServer(origin) {
|
|
|
9360
9419
|
const port = localDevServerPort(origin);
|
|
9361
9420
|
if (port === null || process.platform === "win32") return [];
|
|
9362
9421
|
try {
|
|
9363
|
-
const listeners = await run2(
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
);
|
|
9422
|
+
const listeners = await run2("lsof", ["-nP", "-a", `-iTCP:${port}`, "-sTCP:LISTEN", "-Fp"], {
|
|
9423
|
+
maxBuffer: 64 * 1024,
|
|
9424
|
+
timeout: INSPECTION_TIMEOUT_MS
|
|
9425
|
+
});
|
|
9368
9426
|
const pids = parseListeningPids(String(listeners.stdout));
|
|
9369
9427
|
if (pids.length === 0) return [];
|
|
9370
9428
|
const directories = await run2(
|
|
@@ -9471,9 +9529,9 @@ async function run3(options, deps) {
|
|
|
9471
9529
|
}
|
|
9472
9530
|
const config = merged === null ? null : { ...merged, previews };
|
|
9473
9531
|
const configWarnings = [];
|
|
9474
|
-
const projectRoot = await realpath4(
|
|
9475
|
-
|
|
9476
|
-
);
|
|
9532
|
+
const projectRoot = await realpath4(
|
|
9533
|
+
loaded.path === null ? options.cwd : dirname13(loaded.path)
|
|
9534
|
+
).catch(() => resolve4(loaded.path === null ? options.cwd : dirname13(loaded.path)));
|
|
9477
9535
|
const ownerWarning = needsApp && app === null ? inspectLocalDevServer(devServer).then((owners) => devServerOwnerWarning(devServer, projectRoot, owners)).catch(() => null) : Promise.resolve(null);
|
|
9478
9536
|
const serverPromise = startServer({
|
|
9479
9537
|
config,
|