@spencer-kit/coder-studio 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +14 -79
- package/dist/esm/bin.mjs +572 -284
- package/dist/esm/bin.mjs.map +4 -4
- package/dist/esm/server-runner.mjs +450 -168
- package/dist/esm/server-runner.mjs.map +4 -4
- package/dist/web/assets/index-BjrMfcUG.js +111 -0
- package/dist/web/assets/index-BjrMfcUG.js.map +1 -0
- package/dist/web/assets/index-mL_Aq31j.css +1 -0
- package/dist/web/favicon.ico +0 -0
- package/dist/web/favicon.png +0 -0
- package/dist/web/favicon.svg +19 -0
- package/dist/web/index.html +4 -4
- package/package.json +2 -2
- package/src/bin.test.ts +1 -1
- package/src/bin.ts +6 -379
- package/src/browser.test.ts +50 -0
- package/src/browser.ts +1 -0
- package/src/cli.ts +347 -0
- package/src/package-manifest.test.ts +14 -0
- package/src/package-manifest.ts +28 -0
- package/src/pm2-control.test.ts +89 -1
- package/src/pm2-control.ts +99 -57
- package/src/server-control.test.ts +19 -0
- package/src/server-control.ts +1 -1
- package/src/server-runner.test.ts +14 -0
- package/src/server-runner.ts +2 -0
- package/dist/web/assets/index-A-2YPePM.js +0 -111
- package/dist/web/assets/index-A-2YPePM.js.map +0 -1
- package/dist/web/assets/index-BLMivSS1.css +0 -1
package/dist/esm/bin.mjs
CHANGED
|
@@ -115,8 +115,8 @@ var init_plugin = __esm({
|
|
|
115
115
|
init_web_ui_routing();
|
|
116
116
|
init_login_protection();
|
|
117
117
|
AUTH_COOKIE_NAME = "coder_studio_auth";
|
|
118
|
-
isPublicPath = (
|
|
119
|
-
const pathname = getRequestPathname(
|
|
118
|
+
isPublicPath = (path9) => {
|
|
119
|
+
const pathname = getRequestPathname(path9);
|
|
120
120
|
return pathname === "/" || pathname === "/login" || pathname === "/healthz" || pathname === "/auth/status" || pathname === "/auth/login" || pathname === "/auth/logout" || pathname.startsWith("/@") || isPublicStaticPath(pathname);
|
|
121
121
|
};
|
|
122
122
|
parseCookies = (cookieHeader) => {
|
|
@@ -307,6 +307,25 @@ function parseLogLevel(value) {
|
|
|
307
307
|
return void 0;
|
|
308
308
|
}
|
|
309
309
|
}
|
|
310
|
+
function resolveDefaultAppVersion() {
|
|
311
|
+
if (cachedAppVersion) {
|
|
312
|
+
return cachedAppVersion;
|
|
313
|
+
}
|
|
314
|
+
const packageJsonPath = [new URL("../../cli/package.json", import.meta.url)].find(
|
|
315
|
+
(candidate) => fs.existsSync(candidate)
|
|
316
|
+
);
|
|
317
|
+
if (!packageJsonPath) {
|
|
318
|
+
cachedAppVersion = "0.0.0";
|
|
319
|
+
return cachedAppVersion;
|
|
320
|
+
}
|
|
321
|
+
try {
|
|
322
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
323
|
+
cachedAppVersion = typeof pkg.version === "string" ? pkg.version : "0.0.0";
|
|
324
|
+
} catch {
|
|
325
|
+
cachedAppVersion = "0.0.0";
|
|
326
|
+
}
|
|
327
|
+
return cachedAppVersion;
|
|
328
|
+
}
|
|
310
329
|
function resolveDbPath(explicit) {
|
|
311
330
|
if (explicit) return explicit;
|
|
312
331
|
if (process.env.NODE_ENV !== "production") {
|
|
@@ -345,6 +364,7 @@ function parseServerConfig(overrides) {
|
|
|
345
364
|
uploadsDir,
|
|
346
365
|
logLevel: overrides?.logLevel ?? parseLogLevel(process.env.LOG_LEVEL) ?? "info",
|
|
347
366
|
webRoot: overrides?.webRoot,
|
|
367
|
+
appVersion: overrides?.appVersion ?? process.env.CODER_STUDIO_APP_VERSION ?? resolveDefaultAppVersion(),
|
|
348
368
|
auth: overrides?.auth || {
|
|
349
369
|
enabled: !noAuth && !!password,
|
|
350
370
|
password
|
|
@@ -357,7 +377,7 @@ function ensureDataDir(config) {
|
|
|
357
377
|
}
|
|
358
378
|
fs.mkdirSync(path.dirname(config.dataDir), { recursive: true });
|
|
359
379
|
}
|
|
360
|
-
var cachedTestUploadsDir;
|
|
380
|
+
var cachedTestUploadsDir, cachedAppVersion;
|
|
361
381
|
var init_config = __esm({
|
|
362
382
|
"packages/server/src/config.ts"() {
|
|
363
383
|
"use strict";
|
|
@@ -787,6 +807,190 @@ var init_src = __esm({
|
|
|
787
807
|
}
|
|
788
808
|
});
|
|
789
809
|
|
|
810
|
+
// packages/utils/src/direct-execution.ts
|
|
811
|
+
import { posix, resolve } from "node:path";
|
|
812
|
+
function isWindowsDrivePath(path9) {
|
|
813
|
+
return /^[A-Za-z]:\//.test(path9);
|
|
814
|
+
}
|
|
815
|
+
function normalizeComparablePath(path9) {
|
|
816
|
+
let normalized = path9.replace(/\\/g, "/");
|
|
817
|
+
if (/^\/[A-Za-z]:\//.test(normalized)) {
|
|
818
|
+
normalized = normalized.slice(1);
|
|
819
|
+
}
|
|
820
|
+
if (normalized.startsWith("//")) {
|
|
821
|
+
normalized = `//${posix.normalize(normalized.slice(2))}`;
|
|
822
|
+
} else {
|
|
823
|
+
normalized = posix.normalize(normalized);
|
|
824
|
+
}
|
|
825
|
+
if (isWindowsDrivePath(normalized) || normalized.startsWith("//")) {
|
|
826
|
+
normalized = normalized.toLowerCase();
|
|
827
|
+
}
|
|
828
|
+
return normalized;
|
|
829
|
+
}
|
|
830
|
+
function normalizeModuleUrlPath(moduleUrl) {
|
|
831
|
+
let url;
|
|
832
|
+
try {
|
|
833
|
+
url = new URL(moduleUrl);
|
|
834
|
+
} catch {
|
|
835
|
+
return null;
|
|
836
|
+
}
|
|
837
|
+
if (url.protocol !== "file:") {
|
|
838
|
+
return null;
|
|
839
|
+
}
|
|
840
|
+
const path9 = `${url.host ? `//${url.host}` : ""}${decodeURIComponent(url.pathname)}`;
|
|
841
|
+
return normalizeComparablePath(path9);
|
|
842
|
+
}
|
|
843
|
+
function normalizeArgvPath(argv1) {
|
|
844
|
+
const isAbsoluteWindowsPath = /^[A-Za-z]:[\\/]/.test(argv1) || /^\\\\/.test(argv1);
|
|
845
|
+
return normalizeComparablePath(isAbsoluteWindowsPath ? argv1 : resolve(argv1));
|
|
846
|
+
}
|
|
847
|
+
function isDirectExecution(moduleUrl, argv1 = process.argv[1]) {
|
|
848
|
+
if (argv1 === void 0) {
|
|
849
|
+
return false;
|
|
850
|
+
}
|
|
851
|
+
const modulePath = normalizeModuleUrlPath(moduleUrl);
|
|
852
|
+
if (modulePath === null) {
|
|
853
|
+
return false;
|
|
854
|
+
}
|
|
855
|
+
return modulePath === normalizeArgvPath(argv1);
|
|
856
|
+
}
|
|
857
|
+
var init_direct_execution = __esm({
|
|
858
|
+
"packages/utils/src/direct-execution.ts"() {
|
|
859
|
+
"use strict";
|
|
860
|
+
}
|
|
861
|
+
});
|
|
862
|
+
|
|
863
|
+
// packages/utils/src/windows-shim.ts
|
|
864
|
+
function shouldUseShellForCommand(command, platform = process.platform) {
|
|
865
|
+
return platform === "win32" && WINDOWS_CMD_SHIMS.has(command.toLowerCase());
|
|
866
|
+
}
|
|
867
|
+
var WINDOWS_CMD_SHIMS;
|
|
868
|
+
var init_windows_shim = __esm({
|
|
869
|
+
"packages/utils/src/windows-shim.ts"() {
|
|
870
|
+
"use strict";
|
|
871
|
+
WINDOWS_CMD_SHIMS = /* @__PURE__ */ new Set(["pnpm", "npm", "npx"]);
|
|
872
|
+
}
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
// packages/utils/src/windows-shim-resolver.ts
|
|
876
|
+
import * as fs2 from "node:fs";
|
|
877
|
+
import * as path2 from "node:path";
|
|
878
|
+
function resolveSpawnArgv(argv, deps = {}) {
|
|
879
|
+
const platform = deps.platform ?? process.platform;
|
|
880
|
+
if (platform !== "win32") {
|
|
881
|
+
return [...argv];
|
|
882
|
+
}
|
|
883
|
+
const command = argv[0];
|
|
884
|
+
if (command === void 0) {
|
|
885
|
+
return [];
|
|
886
|
+
}
|
|
887
|
+
const restArgs = argv.slice(1);
|
|
888
|
+
const readFileSync9 = deps.readFileSync ?? ((file) => fs2.readFileSync(file, "utf8"));
|
|
889
|
+
const existsSync12 = deps.existsSync ?? fs2.existsSync;
|
|
890
|
+
const pathEnv = deps.pathEnv ?? process.env.Path ?? process.env.PATH ?? "";
|
|
891
|
+
const pathExt = deps.pathExt ?? process.env.PATHEXT ?? DEFAULT_PATHEXT;
|
|
892
|
+
const resolved = resolveExecutablePath(command, pathEnv, pathExt, existsSync12);
|
|
893
|
+
if (!resolved) {
|
|
894
|
+
return [...argv];
|
|
895
|
+
}
|
|
896
|
+
const ext = path2.win32.extname(resolved).toLowerCase();
|
|
897
|
+
if (ext === ".exe" || ext === ".com") {
|
|
898
|
+
return [resolved, ...restArgs];
|
|
899
|
+
}
|
|
900
|
+
if (ext === ".cmd" || ext === ".bat") {
|
|
901
|
+
let content;
|
|
902
|
+
try {
|
|
903
|
+
content = readFileSync9(resolved);
|
|
904
|
+
} catch {
|
|
905
|
+
return ["cmd.exe", "/d", "/s", "/c", resolved, ...restArgs];
|
|
906
|
+
}
|
|
907
|
+
const parsed = parseCmdShim(resolved, content);
|
|
908
|
+
if (parsed) {
|
|
909
|
+
return [parsed.node, parsed.entry, ...restArgs];
|
|
910
|
+
}
|
|
911
|
+
return ["cmd.exe", "/d", "/s", "/c", resolved, ...restArgs];
|
|
912
|
+
}
|
|
913
|
+
return [...argv];
|
|
914
|
+
}
|
|
915
|
+
function parseCmdShim(shimPath, content) {
|
|
916
|
+
const dp0Dir = path2.win32.dirname(shimPath);
|
|
917
|
+
const entryMatch = content.match(/"([^"\r\n]+\.js)"\s+%\*/i);
|
|
918
|
+
const entryRaw = entryMatch?.[1];
|
|
919
|
+
if (!entryRaw) {
|
|
920
|
+
return null;
|
|
921
|
+
}
|
|
922
|
+
const entry = expandShimVars(entryRaw, dp0Dir);
|
|
923
|
+
const nodeMatch = content.match(/"([^"\r\n]*node\.exe)"/i) ?? content.match(/"([^"\r\n]*node)"/i);
|
|
924
|
+
const nodeRaw = nodeMatch?.[1];
|
|
925
|
+
const node = nodeRaw ? expandShimVars(nodeRaw, dp0Dir) : "node";
|
|
926
|
+
return { node, entry };
|
|
927
|
+
}
|
|
928
|
+
function expandShimVars(value, dp0Dir) {
|
|
929
|
+
const dp0WithSlash = dp0Dir.endsWith("\\") ? dp0Dir : `${dp0Dir}\\`;
|
|
930
|
+
let expanded = value;
|
|
931
|
+
expanded = expanded.replace(/%~dp0/gi, dp0WithSlash);
|
|
932
|
+
expanded = expanded.replace(/%dp0%/gi, dp0WithSlash);
|
|
933
|
+
if (path2.win32.isAbsolute(expanded)) {
|
|
934
|
+
return path2.win32.normalize(expanded);
|
|
935
|
+
}
|
|
936
|
+
return path2.win32.resolve(dp0Dir, expanded);
|
|
937
|
+
}
|
|
938
|
+
function parsePathExt(pathExt) {
|
|
939
|
+
return pathExt.split(";").map((entry) => entry.trim().toLowerCase()).filter((entry) => entry.length > 0);
|
|
940
|
+
}
|
|
941
|
+
function resolveExecutablePath(command, pathEnv, pathExt, existsSync12) {
|
|
942
|
+
const hasExt = path2.win32.extname(command).length > 0;
|
|
943
|
+
const extensions = parsePathExt(pathExt);
|
|
944
|
+
if (path2.win32.isAbsolute(command)) {
|
|
945
|
+
if (existsSync12(command)) {
|
|
946
|
+
return command;
|
|
947
|
+
}
|
|
948
|
+
if (!hasExt) {
|
|
949
|
+
for (const ext of extensions) {
|
|
950
|
+
const candidate = command + ext;
|
|
951
|
+
if (existsSync12(candidate)) {
|
|
952
|
+
return candidate;
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
return null;
|
|
957
|
+
}
|
|
958
|
+
const dirs = pathEnv.split(";").map((dir) => dir.trim()).filter((dir) => dir.length > 0);
|
|
959
|
+
for (const dir of dirs) {
|
|
960
|
+
if (hasExt) {
|
|
961
|
+
const candidate = path2.win32.join(dir, command);
|
|
962
|
+
if (existsSync12(candidate)) {
|
|
963
|
+
return candidate;
|
|
964
|
+
}
|
|
965
|
+
continue;
|
|
966
|
+
}
|
|
967
|
+
for (const ext of extensions) {
|
|
968
|
+
const candidate = path2.win32.join(dir, command + ext);
|
|
969
|
+
if (existsSync12(candidate)) {
|
|
970
|
+
return candidate;
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
return null;
|
|
975
|
+
}
|
|
976
|
+
var DEFAULT_PATHEXT;
|
|
977
|
+
var init_windows_shim_resolver = __esm({
|
|
978
|
+
"packages/utils/src/windows-shim-resolver.ts"() {
|
|
979
|
+
"use strict";
|
|
980
|
+
DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC";
|
|
981
|
+
}
|
|
982
|
+
});
|
|
983
|
+
|
|
984
|
+
// packages/utils/src/index.ts
|
|
985
|
+
var init_src2 = __esm({
|
|
986
|
+
"packages/utils/src/index.ts"() {
|
|
987
|
+
"use strict";
|
|
988
|
+
init_direct_execution();
|
|
989
|
+
init_windows_shim();
|
|
990
|
+
init_windows_shim_resolver();
|
|
991
|
+
}
|
|
992
|
+
});
|
|
993
|
+
|
|
790
994
|
// packages/server/src/fs/image.ts
|
|
791
995
|
import { extname } from "path";
|
|
792
996
|
function getImageTypeInfo(filePath) {
|
|
@@ -813,10 +1017,10 @@ var init_image = __esm({
|
|
|
813
1017
|
// packages/server/src/fs/file-io.ts
|
|
814
1018
|
import { createHash } from "crypto";
|
|
815
1019
|
import { readFile as fsReadFile, writeFile as fsWriteFile, mkdir, rm, stat } from "fs/promises";
|
|
816
|
-
import { dirname as dirname2, resolve } from "path";
|
|
817
|
-
async function statSafe(
|
|
1020
|
+
import { dirname as dirname2, resolve as resolve2 } from "path";
|
|
1021
|
+
async function statSafe(path9) {
|
|
818
1022
|
try {
|
|
819
|
-
return await stat(
|
|
1023
|
+
return await stat(path9);
|
|
820
1024
|
} catch {
|
|
821
1025
|
return null;
|
|
822
1026
|
}
|
|
@@ -847,8 +1051,8 @@ async function deleteEntry(rootPath, relPath) {
|
|
|
847
1051
|
await rm(abs, { recursive: true });
|
|
848
1052
|
}
|
|
849
1053
|
function resolveSafe(root, relPath) {
|
|
850
|
-
const absRoot =
|
|
851
|
-
const abs =
|
|
1054
|
+
const absRoot = resolve2(root);
|
|
1055
|
+
const abs = resolve2(absRoot, relPath);
|
|
852
1056
|
if (!abs.startsWith(absRoot + "/") && abs !== absRoot) {
|
|
853
1057
|
throw { code: "path_escape", message: "Path escapes workspace root" };
|
|
854
1058
|
}
|
|
@@ -986,7 +1190,7 @@ var init_constants = __esm({
|
|
|
986
1190
|
// packages/server/src/uploads/paths.ts
|
|
987
1191
|
import { randomUUID } from "node:crypto";
|
|
988
1192
|
import { lstat, mkdir as mkdir2 } from "node:fs/promises";
|
|
989
|
-
import
|
|
1193
|
+
import path3 from "node:path";
|
|
990
1194
|
function sanitizeOriginalName(input2) {
|
|
991
1195
|
let sanitized = "";
|
|
992
1196
|
for (const char of input2.trim()) {
|
|
@@ -1022,9 +1226,9 @@ async function assertDirectorySegmentSafe(segmentPath) {
|
|
|
1022
1226
|
}
|
|
1023
1227
|
}
|
|
1024
1228
|
async function ensureSafeUploadDir(rootDir, targetDir) {
|
|
1025
|
-
const resolvedRoot =
|
|
1026
|
-
const resolvedTarget =
|
|
1027
|
-
if (resolvedTarget !== resolvedRoot && !resolvedTarget.startsWith(`${resolvedRoot}${
|
|
1229
|
+
const resolvedRoot = path3.resolve(rootDir);
|
|
1230
|
+
const resolvedTarget = path3.resolve(targetDir);
|
|
1231
|
+
if (resolvedTarget !== resolvedRoot && !resolvedTarget.startsWith(`${resolvedRoot}${path3.sep}`)) {
|
|
1028
1232
|
throw new Error(`target dir escaped uploads root: ${resolvedTarget}`);
|
|
1029
1233
|
}
|
|
1030
1234
|
try {
|
|
@@ -1037,13 +1241,13 @@ async function ensureSafeUploadDir(rootDir, targetDir) {
|
|
|
1037
1241
|
await mkdir2(resolvedRoot, { recursive: true });
|
|
1038
1242
|
await assertDirectorySegmentSafe(resolvedRoot);
|
|
1039
1243
|
}
|
|
1040
|
-
const relative3 =
|
|
1244
|
+
const relative3 = path3.relative(resolvedRoot, resolvedTarget);
|
|
1041
1245
|
if (!relative3) {
|
|
1042
1246
|
return;
|
|
1043
1247
|
}
|
|
1044
1248
|
let current = resolvedRoot;
|
|
1045
|
-
for (const segment of relative3.split(
|
|
1046
|
-
current =
|
|
1249
|
+
for (const segment of relative3.split(path3.sep)) {
|
|
1250
|
+
current = path3.join(current, segment);
|
|
1047
1251
|
try {
|
|
1048
1252
|
await assertDirectorySegmentSafe(current);
|
|
1049
1253
|
continue;
|
|
@@ -1068,11 +1272,11 @@ function generateBucketPath(input2) {
|
|
|
1068
1272
|
validateWorkspaceId(input2.workspaceId);
|
|
1069
1273
|
const now = input2.now ?? /* @__PURE__ */ new Date();
|
|
1070
1274
|
const dateStr = now.toISOString().slice(0, 10);
|
|
1071
|
-
const dir =
|
|
1275
|
+
const dir = path3.join(input2.uploadsDir, input2.workspaceId, dateStr);
|
|
1072
1276
|
const sanitizedName = sanitizeOriginalName(input2.originalName);
|
|
1073
1277
|
const uuid8 = randomUUID().replace(/-/g, "").slice(0, 8);
|
|
1074
|
-
const absolutePath =
|
|
1075
|
-
const uploadsRoot = `${
|
|
1278
|
+
const absolutePath = path3.resolve(dir, `${uuid8}-${sanitizedName}`);
|
|
1279
|
+
const uploadsRoot = `${path3.resolve(input2.uploadsDir)}${path3.sep}`;
|
|
1076
1280
|
if (!absolutePath.startsWith(uploadsRoot)) {
|
|
1077
1281
|
throw new Error(`generated upload path escaped uploads root: ${absolutePath}`);
|
|
1078
1282
|
}
|
|
@@ -1095,7 +1299,7 @@ var init_paths = __esm({
|
|
|
1095
1299
|
|
|
1096
1300
|
// packages/server/src/uploads/cleanup.ts
|
|
1097
1301
|
import { readdir, rm as rm2, rmdir, stat as stat3, unlink } from "node:fs/promises";
|
|
1098
|
-
import
|
|
1302
|
+
import path4 from "node:path";
|
|
1099
1303
|
async function listFilesRecursive(root) {
|
|
1100
1304
|
let entries;
|
|
1101
1305
|
try {
|
|
@@ -1108,7 +1312,7 @@ async function listFilesRecursive(root) {
|
|
|
1108
1312
|
}
|
|
1109
1313
|
const files = [];
|
|
1110
1314
|
for (const entry of entries) {
|
|
1111
|
-
const childPath =
|
|
1315
|
+
const childPath = path4.join(root, entry.name);
|
|
1112
1316
|
if (entry.isDirectory()) {
|
|
1113
1317
|
files.push(...await listFilesRecursive(childPath));
|
|
1114
1318
|
continue;
|
|
@@ -1139,7 +1343,7 @@ async function pruneEmptyDirectories(root) {
|
|
|
1139
1343
|
if (!entry.isDirectory()) {
|
|
1140
1344
|
continue;
|
|
1141
1345
|
}
|
|
1142
|
-
await pruneEmptyDirectories(
|
|
1346
|
+
await pruneEmptyDirectories(path4.join(root, entry.name));
|
|
1143
1347
|
}
|
|
1144
1348
|
const remainingEntries = await readdir(root).catch(() => []);
|
|
1145
1349
|
if (remainingEntries.length === 0) {
|
|
@@ -1148,12 +1352,12 @@ async function pruneEmptyDirectories(root) {
|
|
|
1148
1352
|
}
|
|
1149
1353
|
async function deleteWorkspaceUploads(uploadsDir, workspaceId) {
|
|
1150
1354
|
validateWorkspaceId(workspaceId);
|
|
1151
|
-
const bucket =
|
|
1355
|
+
const bucket = path4.join(uploadsDir, workspaceId);
|
|
1152
1356
|
await rm2(bucket, { recursive: true, force: true });
|
|
1153
1357
|
}
|
|
1154
1358
|
async function enforceBucketCap(uploadsDir, workspaceId, capBytes, logger) {
|
|
1155
1359
|
validateWorkspaceId(workspaceId);
|
|
1156
|
-
const bucket =
|
|
1360
|
+
const bucket = path4.join(uploadsDir, workspaceId);
|
|
1157
1361
|
const files = await listFilesRecursive(bucket);
|
|
1158
1362
|
const totalBytes = files.reduce((sum, file) => sum + file.size, 0);
|
|
1159
1363
|
if (totalBytes <= capBytes) {
|
|
@@ -1193,7 +1397,7 @@ async function runStartupGc(uploadsDir, logger) {
|
|
|
1193
1397
|
if (!workspaceEntry.isDirectory()) {
|
|
1194
1398
|
continue;
|
|
1195
1399
|
}
|
|
1196
|
-
const workspaceDir =
|
|
1400
|
+
const workspaceDir = path4.join(uploadsDir, workspaceEntry.name);
|
|
1197
1401
|
const dateEntries = await readdir(workspaceDir, { withFileTypes: true }).catch(
|
|
1198
1402
|
() => []
|
|
1199
1403
|
);
|
|
@@ -1201,7 +1405,7 @@ async function runStartupGc(uploadsDir, logger) {
|
|
|
1201
1405
|
if (!dateEntry.isDirectory()) {
|
|
1202
1406
|
continue;
|
|
1203
1407
|
}
|
|
1204
|
-
const dateDir =
|
|
1408
|
+
const dateDir = path4.join(workspaceDir, dateEntry.name);
|
|
1205
1409
|
const files = await listFilesRecursive(dateDir);
|
|
1206
1410
|
for (const file of files) {
|
|
1207
1411
|
if (file.mtimeMs >= cutoffMs) {
|
|
@@ -1592,7 +1796,7 @@ var init_app = __esm({
|
|
|
1592
1796
|
});
|
|
1593
1797
|
|
|
1594
1798
|
// packages/server/src/config/codex-config-audit.ts
|
|
1595
|
-
import { existsSync as
|
|
1799
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, renameSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
1596
1800
|
import { homedir as homedir2 } from "node:os";
|
|
1597
1801
|
import { dirname as dirname3, join as join2 } from "node:path";
|
|
1598
1802
|
function resolveCodexConfigPath() {
|
|
@@ -1603,15 +1807,15 @@ function resolveCodexConfigPath() {
|
|
|
1603
1807
|
return join2(homedir2(), ".codex", "config.toml");
|
|
1604
1808
|
}
|
|
1605
1809
|
function auditCodexConfigToml(configPath) {
|
|
1606
|
-
const
|
|
1607
|
-
if (!
|
|
1608
|
-
return { configPath:
|
|
1810
|
+
const path9 = configPath ?? resolveCodexConfigPath();
|
|
1811
|
+
if (!existsSync3(path9)) {
|
|
1812
|
+
return { configPath: path9, exists: false, findings: [] };
|
|
1609
1813
|
}
|
|
1610
1814
|
let content;
|
|
1611
1815
|
try {
|
|
1612
|
-
content =
|
|
1816
|
+
content = readFileSync3(path9, "utf-8");
|
|
1613
1817
|
} catch {
|
|
1614
|
-
return { configPath:
|
|
1818
|
+
return { configPath: path9, exists: false, findings: [] };
|
|
1615
1819
|
}
|
|
1616
1820
|
const lines = content.split(/\r?\n/);
|
|
1617
1821
|
const findings = [];
|
|
@@ -1619,13 +1823,13 @@ function auditCodexConfigToml(configPath) {
|
|
|
1619
1823
|
if (notifyFinding) findings.push(notifyFinding);
|
|
1620
1824
|
const codexHooksFinding = detectCodexHooksFlag(lines);
|
|
1621
1825
|
if (codexHooksFinding) findings.push(codexHooksFinding);
|
|
1622
|
-
return { configPath:
|
|
1826
|
+
return { configPath: path9, exists: true, findings };
|
|
1623
1827
|
}
|
|
1624
1828
|
function cleanupCodexConfigToml(configPath, opts) {
|
|
1625
1829
|
if (opts.removeIds.length === 0) {
|
|
1626
1830
|
return { removed: [], backupPath: null, noop: true };
|
|
1627
1831
|
}
|
|
1628
|
-
if (!
|
|
1832
|
+
if (!existsSync3(configPath)) {
|
|
1629
1833
|
return { removed: [], backupPath: null, noop: true };
|
|
1630
1834
|
}
|
|
1631
1835
|
const audit = auditCodexConfigToml(configPath);
|
|
@@ -1633,7 +1837,7 @@ function cleanupCodexConfigToml(configPath, opts) {
|
|
|
1633
1837
|
if (selected.length === 0) {
|
|
1634
1838
|
return { removed: [], backupPath: null, noop: true };
|
|
1635
1839
|
}
|
|
1636
|
-
const original =
|
|
1840
|
+
const original = readFileSync3(configPath, "utf-8");
|
|
1637
1841
|
const backupPath = writeBackup(configPath, original, opts.backupDir);
|
|
1638
1842
|
const linesToDrop = /* @__PURE__ */ new Set();
|
|
1639
1843
|
for (const finding of selected) {
|
|
@@ -1735,7 +1939,7 @@ function countBrackets(s) {
|
|
|
1735
1939
|
}
|
|
1736
1940
|
function writeBackup(configPath, original, backupDir) {
|
|
1737
1941
|
const dir = backupDir ?? dirname3(configPath);
|
|
1738
|
-
if (!
|
|
1942
|
+
if (!existsSync3(dir)) {
|
|
1739
1943
|
mkdirSync2(dir, { recursive: true });
|
|
1740
1944
|
}
|
|
1741
1945
|
const ts = formatTimestamp(/* @__PURE__ */ new Date());
|
|
@@ -1776,35 +1980,78 @@ var init_codex_config_audit = __esm({
|
|
|
1776
1980
|
}
|
|
1777
1981
|
});
|
|
1778
1982
|
|
|
1983
|
+
// packages/server/src/provider-runtime/command-runner.ts
|
|
1984
|
+
import { spawn } from "node:child_process";
|
|
1985
|
+
async function runCommandAsString(file, args, options) {
|
|
1986
|
+
return new Promise((resolve4, reject) => {
|
|
1987
|
+
const child = spawn(file, args, {
|
|
1988
|
+
shell: shouldUseShellForCommand(file, process.platform),
|
|
1989
|
+
windowsHide: options?.windowsHide ?? true
|
|
1990
|
+
});
|
|
1991
|
+
const stdoutChunks = [];
|
|
1992
|
+
const stderrChunks = [];
|
|
1993
|
+
child.stdout?.on("data", (chunk) => {
|
|
1994
|
+
stdoutChunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
1995
|
+
});
|
|
1996
|
+
child.stderr?.on("data", (chunk) => {
|
|
1997
|
+
stderrChunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
1998
|
+
});
|
|
1999
|
+
child.on("error", (error) => {
|
|
2000
|
+
reject(
|
|
2001
|
+
Object.assign(error, {
|
|
2002
|
+
stdout: Buffer.concat(stdoutChunks).toString("utf8"),
|
|
2003
|
+
stderr: Buffer.concat(stderrChunks).toString("utf8")
|
|
2004
|
+
})
|
|
2005
|
+
);
|
|
2006
|
+
});
|
|
2007
|
+
child.on("close", (code) => {
|
|
2008
|
+
const stdout = Buffer.concat(stdoutChunks).toString("utf8");
|
|
2009
|
+
const stderr = Buffer.concat(stderrChunks).toString("utf8");
|
|
2010
|
+
if (code === 0) {
|
|
2011
|
+
resolve4({ stdout, stderr });
|
|
2012
|
+
return;
|
|
2013
|
+
}
|
|
2014
|
+
reject(
|
|
2015
|
+
Object.assign(new Error(`Command failed with exit code ${code ?? "unknown"}`), {
|
|
2016
|
+
exitCode: code ?? void 0,
|
|
2017
|
+
stdout,
|
|
2018
|
+
stderr
|
|
2019
|
+
})
|
|
2020
|
+
);
|
|
2021
|
+
});
|
|
2022
|
+
});
|
|
2023
|
+
}
|
|
2024
|
+
var init_command_runner = __esm({
|
|
2025
|
+
"packages/server/src/provider-runtime/command-runner.ts"() {
|
|
2026
|
+
"use strict";
|
|
2027
|
+
init_src2();
|
|
2028
|
+
}
|
|
2029
|
+
});
|
|
2030
|
+
|
|
1779
2031
|
// packages/server/src/provider-runtime/command-check.ts
|
|
1780
|
-
import { execFile as nodeExecFile } from "node:child_process";
|
|
1781
|
-
import { promisify } from "node:util";
|
|
1782
2032
|
function getCommandLookupExecutable(platform) {
|
|
1783
2033
|
return platform === "win32" ? "where" : "which";
|
|
1784
2034
|
}
|
|
1785
2035
|
async function checkCommandAvailable(command, deps = {}) {
|
|
1786
2036
|
const platform = deps.platform ?? process.platform;
|
|
1787
|
-
const
|
|
2037
|
+
const runCommand2 = deps.runCommand ?? runCommandAsString;
|
|
1788
2038
|
const lookup = getCommandLookupExecutable(platform);
|
|
1789
2039
|
try {
|
|
1790
|
-
await
|
|
1791
|
-
return
|
|
2040
|
+
const { stdout } = await runCommand2(lookup, [command], { windowsHide: true });
|
|
2041
|
+
return stdout.trim().length > 0;
|
|
1792
2042
|
} catch {
|
|
1793
2043
|
return false;
|
|
1794
2044
|
}
|
|
1795
2045
|
}
|
|
1796
|
-
var execFileAsync;
|
|
1797
2046
|
var init_command_check = __esm({
|
|
1798
2047
|
"packages/server/src/provider-runtime/command-check.ts"() {
|
|
1799
2048
|
"use strict";
|
|
1800
|
-
|
|
2049
|
+
init_command_runner();
|
|
1801
2050
|
}
|
|
1802
2051
|
});
|
|
1803
2052
|
|
|
1804
2053
|
// packages/server/src/provider-runtime/install-manager.ts
|
|
1805
|
-
import { execFile as nodeExecFile2 } from "node:child_process";
|
|
1806
2054
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
1807
|
-
import { promisify as promisify2 } from "node:util";
|
|
1808
2055
|
function getErrorDetails(error) {
|
|
1809
2056
|
if (error instanceof Error) {
|
|
1810
2057
|
const record = error;
|
|
@@ -1879,12 +2126,12 @@ function cloneFailure(failure) {
|
|
|
1879
2126
|
}
|
|
1880
2127
|
};
|
|
1881
2128
|
}
|
|
1882
|
-
var
|
|
2129
|
+
var EXCERPT_LIMIT, ProviderInstallManager;
|
|
1883
2130
|
var init_install_manager = __esm({
|
|
1884
2131
|
"packages/server/src/provider-runtime/install-manager.ts"() {
|
|
1885
2132
|
"use strict";
|
|
1886
2133
|
init_command_check();
|
|
1887
|
-
|
|
2134
|
+
init_command_runner();
|
|
1888
2135
|
EXCERPT_LIMIT = 400;
|
|
1889
2136
|
ProviderInstallManager = class {
|
|
1890
2137
|
providers = /* @__PURE__ */ new Map();
|
|
@@ -2069,7 +2316,7 @@ var init_install_manager = __esm({
|
|
|
2069
2316
|
};
|
|
2070
2317
|
}
|
|
2071
2318
|
async runPreparedJob(provider, job) {
|
|
2072
|
-
const
|
|
2319
|
+
const runCommand2 = this.deps.runCommand ?? runCommandAsString;
|
|
2073
2320
|
job.status = "running";
|
|
2074
2321
|
this.jobs.set(job.jobId, job);
|
|
2075
2322
|
for (const step of job.steps) {
|
|
@@ -2096,7 +2343,7 @@ var init_install_manager = __esm({
|
|
|
2096
2343
|
return;
|
|
2097
2344
|
}
|
|
2098
2345
|
} else {
|
|
2099
|
-
const result = await
|
|
2346
|
+
const result = await runCommand2(step.command, step.args, { windowsHide: true });
|
|
2100
2347
|
step.stdoutExcerpt = excerpt(result.stdout);
|
|
2101
2348
|
step.stderrExcerpt = excerpt(result.stderr);
|
|
2102
2349
|
}
|
|
@@ -2432,7 +2679,7 @@ var init_idle_heuristics2 = __esm({
|
|
|
2432
2679
|
});
|
|
2433
2680
|
|
|
2434
2681
|
// packages/core/src/index.ts
|
|
2435
|
-
var
|
|
2682
|
+
var init_src3 = __esm({
|
|
2436
2683
|
"packages/core/src/index.ts"() {
|
|
2437
2684
|
"use strict";
|
|
2438
2685
|
init_events();
|
|
@@ -2469,14 +2716,16 @@ var init_provider_config = __esm({
|
|
|
2469
2716
|
SUPPORTED_PROVIDER_IDS = ["claude", "codex"];
|
|
2470
2717
|
supportedProviderIds = new Set(SUPPORTED_PROVIDER_IDS);
|
|
2471
2718
|
ProviderLaunchConfigInputSchema = z4.object({
|
|
2472
|
-
additionalArgs: z4.array(z4.string()).optional()
|
|
2719
|
+
additionalArgs: z4.array(z4.string()).optional(),
|
|
2720
|
+
envVars: z4.record(z4.string(), z4.string()).optional()
|
|
2473
2721
|
}).strict();
|
|
2474
2722
|
ProviderSettingsSchema = z4.object({
|
|
2475
2723
|
claude: ProviderLaunchConfigInputSchema.optional(),
|
|
2476
2724
|
codex: ProviderLaunchConfigInputSchema.optional()
|
|
2477
2725
|
}).strict();
|
|
2478
2726
|
ProviderLaunchConfigSchema = z4.object({
|
|
2479
|
-
additionalArgs: z4.array(z4.string()).default([])
|
|
2727
|
+
additionalArgs: z4.array(z4.string()).default([]),
|
|
2728
|
+
envVars: z4.record(z4.string(), z4.string()).optional()
|
|
2480
2729
|
});
|
|
2481
2730
|
}
|
|
2482
2731
|
});
|
|
@@ -2742,7 +2991,7 @@ var NOOP_SESSION_LOGGER, SessionManager, ActiveSession;
|
|
|
2742
2991
|
var init_manager = __esm({
|
|
2743
2992
|
"packages/server/src/session/manager.ts"() {
|
|
2744
2993
|
"use strict";
|
|
2745
|
-
|
|
2994
|
+
init_src3();
|
|
2746
2995
|
init_provider_config();
|
|
2747
2996
|
init_session_repo();
|
|
2748
2997
|
init_pty_state_detector();
|
|
@@ -3283,7 +3532,7 @@ var init_database = __esm({
|
|
|
3283
3532
|
|
|
3284
3533
|
// packages/server/src/storage/db.ts
|
|
3285
3534
|
import { DatabaseSync } from "node:sqlite";
|
|
3286
|
-
import { readFileSync as
|
|
3535
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
3287
3536
|
import { join as join3 } from "path";
|
|
3288
3537
|
function normalizeSql(sql) {
|
|
3289
3538
|
return (sql ?? "").replace(/\s+/g, " ").trim();
|
|
@@ -3432,7 +3681,7 @@ var init_db = __esm({
|
|
|
3432
3681
|
"use strict";
|
|
3433
3682
|
init_database();
|
|
3434
3683
|
SCHEMA_PATH = join3(import.meta.dirname, "migrations", "001_init.sql");
|
|
3435
|
-
SCHEMA_SQL =
|
|
3684
|
+
SCHEMA_SQL = readFileSync4(SCHEMA_PATH, "utf-8");
|
|
3436
3685
|
LEGACY_TABLES = ["hook_registrations", "_migrations"];
|
|
3437
3686
|
LEGACY_SESSION_COLUMNS = ["resume_id", "transcript_path"];
|
|
3438
3687
|
EXPECTED_SCHEMA_ENTRIES = buildExpectedSchemaEntries();
|
|
@@ -3982,11 +4231,11 @@ function parseOrdinaryChangedEntry(record, staged, modified, deleted) {
|
|
|
3982
4231
|
if (!xy) {
|
|
3983
4232
|
return;
|
|
3984
4233
|
}
|
|
3985
|
-
const
|
|
3986
|
-
if (!
|
|
4234
|
+
const path9 = parts.slice(8).join(" ");
|
|
4235
|
+
if (!path9) {
|
|
3987
4236
|
return;
|
|
3988
4237
|
}
|
|
3989
|
-
pushChange({ path:
|
|
4238
|
+
pushChange({ path: path9 }, xy, staged, modified, deleted);
|
|
3990
4239
|
}
|
|
3991
4240
|
function parseRenamedEntry(record, oldPathRecord, staged, modified, deleted) {
|
|
3992
4241
|
const parts = record.split(" ");
|
|
@@ -3998,12 +4247,12 @@ function parseRenamedEntry(record, oldPathRecord, staged, modified, deleted) {
|
|
|
3998
4247
|
const pathAndMaybeOldPath = pathTokens.join(" ");
|
|
3999
4248
|
const inlinePathParts = pathAndMaybeOldPath.split(" ");
|
|
4000
4249
|
const fallbackPath = !oldPathRecord && inlinePathParts.length === 1 && pathTokens.length > 1 ? pathTokens.slice(0, -1).join(" ") : void 0;
|
|
4001
|
-
const
|
|
4002
|
-
if (!
|
|
4250
|
+
const path9 = fallbackPath ?? inlinePathParts[0];
|
|
4251
|
+
if (!path9) {
|
|
4003
4252
|
return;
|
|
4004
4253
|
}
|
|
4005
4254
|
const oldPath = (oldPathRecord && !oldPathRecord.startsWith("#") ? oldPathRecord : void 0) ?? inlinePathParts[1] ?? (pathTokens.length > 1 ? pathTokens[pathTokens.length - 1] : void 0);
|
|
4006
|
-
pushChange({ path:
|
|
4255
|
+
pushChange({ path: path9, oldPath }, xy, staged, modified, deleted);
|
|
4007
4256
|
}
|
|
4008
4257
|
function pushChange(change, xy, staged, modified, deleted) {
|
|
4009
4258
|
const indexStatus = xy[0];
|
|
@@ -4030,7 +4279,7 @@ var init_status_parser = __esm({
|
|
|
4030
4279
|
import { execFile } from "child_process";
|
|
4031
4280
|
import { mkdir as mkdir3, mkdtemp, rm as rm4, writeFile as writeFile3 } from "fs/promises";
|
|
4032
4281
|
import os2 from "os";
|
|
4033
|
-
import
|
|
4282
|
+
import path5 from "path";
|
|
4034
4283
|
async function runGit(cwd, args, options = {}) {
|
|
4035
4284
|
return new Promise((resolve4, reject) => {
|
|
4036
4285
|
const gitArgs = [
|
|
@@ -4052,7 +4301,8 @@ async function runGit(cwd, args, options = {}) {
|
|
|
4052
4301
|
...options.env
|
|
4053
4302
|
},
|
|
4054
4303
|
maxBuffer: 10 * 1024 * 1024,
|
|
4055
|
-
timeout: options.timeoutMs
|
|
4304
|
+
timeout: options.timeoutMs,
|
|
4305
|
+
windowsHide: true
|
|
4056
4306
|
},
|
|
4057
4307
|
(err, stdout, stderr) => {
|
|
4058
4308
|
if (err) {
|
|
@@ -4107,12 +4357,12 @@ async function discardChanges(cwd, paths) {
|
|
|
4107
4357
|
if (paths.length === 0) return;
|
|
4108
4358
|
const trackedPaths = [];
|
|
4109
4359
|
const untrackedPaths = [];
|
|
4110
|
-
for (const
|
|
4360
|
+
for (const path9 of paths) {
|
|
4111
4361
|
try {
|
|
4112
|
-
await runGit(cwd, ["ls-files", "--error-unmatch", "--",
|
|
4113
|
-
trackedPaths.push(
|
|
4362
|
+
await runGit(cwd, ["ls-files", "--error-unmatch", "--", path9]);
|
|
4363
|
+
trackedPaths.push(path9);
|
|
4114
4364
|
} catch {
|
|
4115
|
-
untrackedPaths.push(
|
|
4365
|
+
untrackedPaths.push(path9);
|
|
4116
4366
|
}
|
|
4117
4367
|
}
|
|
4118
4368
|
if (trackedPaths.length > 0) {
|
|
@@ -4380,9 +4630,9 @@ async function prepareGitAuthExecution(auth, remoteMetadata) {
|
|
|
4380
4630
|
}
|
|
4381
4631
|
};
|
|
4382
4632
|
}
|
|
4383
|
-
const tempDir = await mkdtemp(
|
|
4384
|
-
const hooksDir =
|
|
4385
|
-
const askPassPath =
|
|
4633
|
+
const tempDir = await mkdtemp(path5.join(os2.tmpdir(), "coder-studio-git-auth-"));
|
|
4634
|
+
const hooksDir = path5.join(tempDir, "hooks");
|
|
4635
|
+
const askPassPath = path5.join(tempDir, "askpass.sh");
|
|
4386
4636
|
await mkdir3(hooksDir, { recursive: true, mode: 448 });
|
|
4387
4637
|
await writeFile3(
|
|
4388
4638
|
askPassPath,
|
|
@@ -4736,9 +4986,9 @@ var init_context_builder = __esm({
|
|
|
4736
4986
|
});
|
|
4737
4987
|
|
|
4738
4988
|
// packages/server/src/terminal/pty-host.ts
|
|
4739
|
-
import { chmodSync, existsSync as
|
|
4989
|
+
import { chmodSync, existsSync as existsSync4, statSync } from "node:fs";
|
|
4740
4990
|
import { createRequire } from "node:module";
|
|
4741
|
-
import
|
|
4991
|
+
import path6 from "node:path";
|
|
4742
4992
|
function ensureNodePtySpawnHelperExecutable(deps = {}) {
|
|
4743
4993
|
const platform = deps.platform ?? process.platform;
|
|
4744
4994
|
if (platform !== "darwin") {
|
|
@@ -4746,7 +4996,7 @@ function ensureNodePtySpawnHelperExecutable(deps = {}) {
|
|
|
4746
4996
|
}
|
|
4747
4997
|
const arch = deps.arch ?? process.arch;
|
|
4748
4998
|
const resolve4 = deps.resolve ?? ((id) => require2.resolve(id));
|
|
4749
|
-
const fileExists = deps.existsSync ??
|
|
4999
|
+
const fileExists = deps.existsSync ?? existsSync4;
|
|
4750
5000
|
const stat7 = deps.statSync ?? statSync;
|
|
4751
5001
|
const chmod = deps.chmodSync ?? chmodSync;
|
|
4752
5002
|
let packageJsonPath;
|
|
@@ -4755,12 +5005,12 @@ function ensureNodePtySpawnHelperExecutable(deps = {}) {
|
|
|
4755
5005
|
} catch {
|
|
4756
5006
|
return;
|
|
4757
5007
|
}
|
|
4758
|
-
const packageDir =
|
|
5008
|
+
const packageDir = path6.dirname(packageJsonPath);
|
|
4759
5009
|
const helperDir = arch === "arm64" ? "darwin-arm64" : arch === "x64" ? "darwin-x64" : null;
|
|
4760
5010
|
if (!helperDir) {
|
|
4761
5011
|
return;
|
|
4762
5012
|
}
|
|
4763
|
-
const helperPath =
|
|
5013
|
+
const helperPath = path6.join(packageDir, "prebuilds", helperDir, "spawn-helper");
|
|
4764
5014
|
try {
|
|
4765
5015
|
if (!fileExists(helperPath)) {
|
|
4766
5016
|
return;
|
|
@@ -4828,6 +5078,7 @@ var require2, NODE_PTY_PKG, DEFAULT_POLL_INTERVAL_MS, DEFAULT_TIMEOUT_MS, NodePt
|
|
|
4828
5078
|
var init_pty_host = __esm({
|
|
4829
5079
|
"packages/server/src/terminal/pty-host.ts"() {
|
|
4830
5080
|
"use strict";
|
|
5081
|
+
init_src2();
|
|
4831
5082
|
require2 = createRequire(import.meta.url);
|
|
4832
5083
|
NODE_PTY_PKG = "node-pty/package.json";
|
|
4833
5084
|
DEFAULT_POLL_INTERVAL_MS = 50;
|
|
@@ -4842,7 +5093,13 @@ var init_pty_host = __esm({
|
|
|
4842
5093
|
const message = err instanceof Error ? err.message : String(err);
|
|
4843
5094
|
throw new Error(`node-pty native module not available. ${message}`);
|
|
4844
5095
|
}
|
|
4845
|
-
|
|
5096
|
+
if (argv.length === 0) {
|
|
5097
|
+
throw new Error("PTY spawn requires a command");
|
|
5098
|
+
}
|
|
5099
|
+
const [command, ...args] = resolveSpawnArgv(argv, {
|
|
5100
|
+
pathEnv: options.env.Path ?? options.env.PATH,
|
|
5101
|
+
pathExt: options.env.PATHEXT
|
|
5102
|
+
});
|
|
4846
5103
|
if (command === void 0) {
|
|
4847
5104
|
throw new Error("PTY spawn requires a command");
|
|
4848
5105
|
}
|
|
@@ -4903,13 +5160,13 @@ var SUPERVISOR_EVALUATION_TIMEOUT_SETTING_KEY;
|
|
|
4903
5160
|
var init_settings = __esm({
|
|
4904
5161
|
"packages/server/src/supervisor/settings.ts"() {
|
|
4905
5162
|
"use strict";
|
|
4906
|
-
|
|
5163
|
+
init_src3();
|
|
4907
5164
|
SUPERVISOR_EVALUATION_TIMEOUT_SETTING_KEY = "supervisor.evaluationTimeoutSec";
|
|
4908
5165
|
}
|
|
4909
5166
|
});
|
|
4910
5167
|
|
|
4911
5168
|
// packages/server/src/supervisor/evaluator.ts
|
|
4912
|
-
import { spawn } from "node:child_process";
|
|
5169
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
4913
5170
|
function buildPrompt(context) {
|
|
4914
5171
|
const agentOutput = context.transcriptExcerpt ?? context.terminalExcerpt ?? "";
|
|
4915
5172
|
const userInput = context.latestUserInput?.trim() ?? "";
|
|
@@ -4941,11 +5198,12 @@ async function runCommand(command, timeoutMs, options = {}) {
|
|
|
4941
5198
|
throw createSupervisorEvalAbortedError();
|
|
4942
5199
|
}
|
|
4943
5200
|
return await new Promise((resolve4, reject) => {
|
|
4944
|
-
const child =
|
|
5201
|
+
const child = spawn2(command.argv[0], command.argv.slice(1), {
|
|
4945
5202
|
cwd: command.cwd,
|
|
4946
5203
|
detached: process.platform !== "win32",
|
|
4947
5204
|
env: { ...process.env, ...command.env },
|
|
4948
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
5205
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
5206
|
+
windowsHide: true
|
|
4949
5207
|
});
|
|
4950
5208
|
const stdout = [];
|
|
4951
5209
|
const stderr = [];
|
|
@@ -5176,7 +5434,7 @@ var NOOP_LOGGER2, SupervisorEvaluator;
|
|
|
5176
5434
|
var init_evaluator = __esm({
|
|
5177
5435
|
"packages/server/src/supervisor/evaluator.ts"() {
|
|
5178
5436
|
"use strict";
|
|
5179
|
-
|
|
5437
|
+
init_src3();
|
|
5180
5438
|
init_provider_config();
|
|
5181
5439
|
init_pty_host();
|
|
5182
5440
|
init_settings();
|
|
@@ -5279,7 +5537,7 @@ var INJECTABLE_SESSION_STATES, SupervisorInjector;
|
|
|
5279
5537
|
var init_injector = __esm({
|
|
5280
5538
|
"packages/server/src/supervisor/injector.ts"() {
|
|
5281
5539
|
"use strict";
|
|
5282
|
-
|
|
5540
|
+
init_src3();
|
|
5283
5541
|
INJECTABLE_SESSION_STATES = /* @__PURE__ */ new Set([
|
|
5284
5542
|
"idle",
|
|
5285
5543
|
"running"
|
|
@@ -5391,7 +5649,7 @@ var NOOP_LOGGER3, SupervisorManager;
|
|
|
5391
5649
|
var init_manager2 = __esm({
|
|
5392
5650
|
"packages/server/src/supervisor/manager.ts"() {
|
|
5393
5651
|
"use strict";
|
|
5394
|
-
|
|
5652
|
+
init_src3();
|
|
5395
5653
|
init_context_builder();
|
|
5396
5654
|
init_evaluator();
|
|
5397
5655
|
init_injector();
|
|
@@ -6775,14 +7033,14 @@ var init_manager3 = __esm({
|
|
|
6775
7033
|
// packages/server/src/workspace/validator.ts
|
|
6776
7034
|
import { constants } from "fs";
|
|
6777
7035
|
import { access, stat as stat5 } from "fs/promises";
|
|
6778
|
-
async function validatePath(
|
|
7036
|
+
async function validatePath(path9) {
|
|
6779
7037
|
try {
|
|
6780
|
-
const stats = await stat5(
|
|
7038
|
+
const stats = await stat5(path9);
|
|
6781
7039
|
if (!stats.isDirectory()) {
|
|
6782
7040
|
return { valid: false, error: "Path is not a directory" };
|
|
6783
7041
|
}
|
|
6784
|
-
await access(
|
|
6785
|
-
await access(
|
|
7042
|
+
await access(path9, constants.R_OK);
|
|
7043
|
+
await access(path9, constants.W_OK);
|
|
6786
7044
|
return { valid: true };
|
|
6787
7045
|
} catch (error) {
|
|
6788
7046
|
if (error.code === "ENOENT") {
|
|
@@ -6799,8 +7057,8 @@ var init_validator = __esm({
|
|
|
6799
7057
|
"packages/server/src/workspace/validator.ts"() {
|
|
6800
7058
|
"use strict";
|
|
6801
7059
|
WorkspaceValidator = class {
|
|
6802
|
-
async validate(
|
|
6803
|
-
const result = await validatePath(
|
|
7060
|
+
async validate(path9) {
|
|
7061
|
+
const result = await validatePath(path9);
|
|
6804
7062
|
if (!result.valid) {
|
|
6805
7063
|
throw new Error(`Invalid workspace path: ${result.error}`);
|
|
6806
7064
|
}
|
|
@@ -6810,14 +7068,14 @@ var init_validator = __esm({
|
|
|
6810
7068
|
});
|
|
6811
7069
|
|
|
6812
7070
|
// packages/server/src/fs/gitignore.ts
|
|
6813
|
-
import { existsSync as
|
|
7071
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
|
|
6814
7072
|
import ignore from "ignore";
|
|
6815
7073
|
import { join as join4, relative } from "path";
|
|
6816
|
-
function normalizePath(
|
|
6817
|
-
return
|
|
7074
|
+
function normalizePath(path9) {
|
|
7075
|
+
return path9.replace(/\\/g, "/");
|
|
6818
7076
|
}
|
|
6819
|
-
function relativeToRoot(rootPath,
|
|
6820
|
-
return normalizePath(relative(rootPath,
|
|
7077
|
+
function relativeToRoot(rootPath, path9) {
|
|
7078
|
+
return normalizePath(relative(rootPath, path9));
|
|
6821
7079
|
}
|
|
6822
7080
|
function isDefaultTreeIgnored(name) {
|
|
6823
7081
|
return name.startsWith(".") || name === "node_modules" || name === ".git";
|
|
@@ -6825,18 +7083,18 @@ function isDefaultTreeIgnored(name) {
|
|
|
6825
7083
|
function isAlwaysTreeIgnored(name) {
|
|
6826
7084
|
return name === "node_modules" || name === ".git";
|
|
6827
7085
|
}
|
|
6828
|
-
function isIgnoredByGitignore(ig,
|
|
6829
|
-
if (!
|
|
7086
|
+
function isIgnoredByGitignore(ig, path9) {
|
|
7087
|
+
if (!path9 || path9.startsWith("..")) {
|
|
6830
7088
|
return false;
|
|
6831
7089
|
}
|
|
6832
|
-
return ig.ignores(
|
|
7090
|
+
return ig.ignores(path9) || ig.ignores(`${path9}/`);
|
|
6833
7091
|
}
|
|
6834
7092
|
function createGitignoreFilter(rootPath, dirPath) {
|
|
6835
7093
|
const gitignorePath = join4(rootPath, ".gitignore");
|
|
6836
|
-
if (!
|
|
7094
|
+
if (!existsSync5(gitignorePath)) {
|
|
6837
7095
|
return (name) => !isDefaultTreeIgnored(name);
|
|
6838
7096
|
}
|
|
6839
|
-
const gitignoreContent =
|
|
7097
|
+
const gitignoreContent = readFileSync5(gitignorePath, "utf-8");
|
|
6840
7098
|
const ig = ignore().add(gitignoreContent);
|
|
6841
7099
|
return (name) => {
|
|
6842
7100
|
if (isAlwaysTreeIgnored(name)) {
|
|
@@ -6848,17 +7106,17 @@ function createGitignoreFilter(rootPath, dirPath) {
|
|
|
6848
7106
|
}
|
|
6849
7107
|
function createWatcherIgnoreFilter(rootPath) {
|
|
6850
7108
|
const gitignorePath = join4(rootPath, ".gitignore");
|
|
6851
|
-
if (!
|
|
6852
|
-
return (
|
|
7109
|
+
if (!existsSync5(gitignorePath)) {
|
|
7110
|
+
return (path9) => DEFAULT_WATCHER_IGNORED_PATTERNS.some((p) => p.test(normalizePath(path9)));
|
|
6853
7111
|
}
|
|
6854
|
-
const gitignoreContent =
|
|
7112
|
+
const gitignoreContent = readFileSync5(gitignorePath, "utf-8");
|
|
6855
7113
|
const ig = ignore().add(gitignoreContent);
|
|
6856
|
-
return (
|
|
6857
|
-
const normalizedPath = normalizePath(
|
|
7114
|
+
return (path9) => {
|
|
7115
|
+
const normalizedPath = normalizePath(path9);
|
|
6858
7116
|
if (DEFAULT_WATCHER_IGNORED_PATTERNS.some((p) => p.test(normalizedPath))) {
|
|
6859
7117
|
return true;
|
|
6860
7118
|
}
|
|
6861
|
-
const relativePath = relativeToRoot(rootPath,
|
|
7119
|
+
const relativePath = relativeToRoot(rootPath, path9);
|
|
6862
7120
|
return isIgnoredByGitignore(ig, relativePath);
|
|
6863
7121
|
};
|
|
6864
7122
|
}
|
|
@@ -6881,7 +7139,7 @@ var WorkspaceWatcher;
|
|
|
6881
7139
|
var init_watcher = __esm({
|
|
6882
7140
|
"packages/server/src/fs/watcher.ts"() {
|
|
6883
7141
|
"use strict";
|
|
6884
|
-
|
|
7142
|
+
init_src3();
|
|
6885
7143
|
init_gitignore();
|
|
6886
7144
|
WorkspaceWatcher = class {
|
|
6887
7145
|
constructor(workspaceId, rootPath, broadcaster) {
|
|
@@ -7133,12 +7391,12 @@ var init_manager4 = __esm({
|
|
|
7133
7391
|
* @param path - Workspace path
|
|
7134
7392
|
* @returns Workspace or undefined
|
|
7135
7393
|
*/
|
|
7136
|
-
getByPath(
|
|
7394
|
+
getByPath(path9) {
|
|
7137
7395
|
const row = this.deps.db.prepare(
|
|
7138
7396
|
`SELECT id, path, target_runtime, wsl_distro, opened_at, last_active_at, ui_state
|
|
7139
7397
|
FROM workspaces
|
|
7140
7398
|
WHERE path = ?`
|
|
7141
|
-
).get(
|
|
7399
|
+
).get(path9);
|
|
7142
7400
|
if (!row) return void 0;
|
|
7143
7401
|
return {
|
|
7144
7402
|
id: row.id,
|
|
@@ -7527,7 +7785,7 @@ var TerminalInputActivitySchema, TerminalInputSchema, pendingTerminalInput, next
|
|
|
7527
7785
|
var init_terminal = __esm({
|
|
7528
7786
|
"packages/server/src/commands/terminal.ts"() {
|
|
7529
7787
|
"use strict";
|
|
7530
|
-
|
|
7788
|
+
init_src3();
|
|
7531
7789
|
init_dispatch();
|
|
7532
7790
|
TerminalInputActivitySchema = z5.enum(TERMINAL_INPUT_ACTIVITIES).optional();
|
|
7533
7791
|
TerminalInputSchema = z5.union([
|
|
@@ -8135,7 +8393,7 @@ var BINARY_PAYLOAD_TIMEOUT_MS, isBinaryTerminalInputArgs, WsHub;
|
|
|
8135
8393
|
var init_hub = __esm({
|
|
8136
8394
|
"packages/server/src/ws/hub.ts"() {
|
|
8137
8395
|
"use strict";
|
|
8138
|
-
|
|
8396
|
+
init_src3();
|
|
8139
8397
|
init_terminal();
|
|
8140
8398
|
init_client();
|
|
8141
8399
|
init_dispatch();
|
|
@@ -8174,7 +8432,10 @@ var init_hub = __esm({
|
|
|
8174
8432
|
status: "connected",
|
|
8175
8433
|
clientId: client.id,
|
|
8176
8434
|
authEnabled: this.deps.config.auth.enabled,
|
|
8177
|
-
binaryTerminalTransport: true
|
|
8435
|
+
binaryTerminalTransport: true,
|
|
8436
|
+
version: this.deps.config.appVersion ?? "0.0.0",
|
|
8437
|
+
serverInstanceId: `server-${process.pid}`,
|
|
8438
|
+
isWriter: false
|
|
8178
8439
|
});
|
|
8179
8440
|
client.onMessage((msg) => this.routeMessage(client, msg));
|
|
8180
8441
|
client.onClose(() => this.handleClose(client));
|
|
@@ -9047,7 +9308,7 @@ var init_file = __esm({
|
|
|
9047
9308
|
// packages/server/src/git/diff.ts
|
|
9048
9309
|
import { mkdtemp as mkdtemp2, rm as rm5 } from "fs/promises";
|
|
9049
9310
|
import os3 from "os";
|
|
9050
|
-
import
|
|
9311
|
+
import path7 from "path";
|
|
9051
9312
|
async function isTrackedPath(cwd, filePath) {
|
|
9052
9313
|
try {
|
|
9053
9314
|
await runGit(cwd, ["ls-files", "--error-unmatch", "--", filePath]);
|
|
@@ -9057,8 +9318,8 @@ async function isTrackedPath(cwd, filePath) {
|
|
|
9057
9318
|
}
|
|
9058
9319
|
}
|
|
9059
9320
|
async function getUntrackedFileDiff(cwd, filePath) {
|
|
9060
|
-
const tempDir = await mkdtemp2(
|
|
9061
|
-
const tempIndex =
|
|
9321
|
+
const tempDir = await mkdtemp2(path7.join(os3.tmpdir(), "coder-studio-git-diff-"));
|
|
9322
|
+
const tempIndex = path7.join(tempDir, "index");
|
|
9062
9323
|
try {
|
|
9063
9324
|
try {
|
|
9064
9325
|
await runGit(cwd, ["read-tree", "HEAD"], {
|
|
@@ -9083,11 +9344,11 @@ async function getUntrackedFileDiff(cwd, filePath) {
|
|
|
9083
9344
|
await rm5(tempDir, { recursive: true, force: true });
|
|
9084
9345
|
}
|
|
9085
9346
|
}
|
|
9086
|
-
async function getFileDiff(cwd,
|
|
9087
|
-
if (!staged && !await isTrackedPath(cwd,
|
|
9088
|
-
return getUntrackedFileDiff(cwd,
|
|
9347
|
+
async function getFileDiff(cwd, path9, staged = false) {
|
|
9348
|
+
if (!staged && !await isTrackedPath(cwd, path9)) {
|
|
9349
|
+
return getUntrackedFileDiff(cwd, path9);
|
|
9089
9350
|
}
|
|
9090
|
-
const args = staged ? ["diff", "--staged", "--",
|
|
9351
|
+
const args = staged ? ["diff", "--staged", "--", path9] : ["diff", "--", path9];
|
|
9091
9352
|
const result = await runGit(cwd, args);
|
|
9092
9353
|
return result.stdout;
|
|
9093
9354
|
}
|
|
@@ -9336,7 +9597,7 @@ var init_git2 = __esm({
|
|
|
9336
9597
|
});
|
|
9337
9598
|
|
|
9338
9599
|
// packages/server/src/config/config-io.ts
|
|
9339
|
-
import { existsSync as
|
|
9600
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync6, renameSync as renameSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
9340
9601
|
import { homedir as homedir4 } from "node:os";
|
|
9341
9602
|
import { basename as basename2, dirname as dirname4, join as join7 } from "node:path";
|
|
9342
9603
|
function resolveConfigPath(configType) {
|
|
@@ -9358,11 +9619,11 @@ function resolveConfigPath(configType) {
|
|
|
9358
9619
|
}
|
|
9359
9620
|
function readConfigFile(configType) {
|
|
9360
9621
|
const configPath = resolveConfigPath(configType);
|
|
9361
|
-
if (!
|
|
9622
|
+
if (!existsSync6(configPath)) {
|
|
9362
9623
|
return { configPath, content: "", exists: false };
|
|
9363
9624
|
}
|
|
9364
9625
|
try {
|
|
9365
|
-
const content =
|
|
9626
|
+
const content = readFileSync6(configPath, "utf-8");
|
|
9366
9627
|
return { configPath, content, exists: true };
|
|
9367
9628
|
} catch {
|
|
9368
9629
|
return { configPath, content: "", exists: false };
|
|
@@ -9372,11 +9633,11 @@ function writeConfigFile(configType, content) {
|
|
|
9372
9633
|
try {
|
|
9373
9634
|
const configPath = resolveConfigPath(configType);
|
|
9374
9635
|
const parentDir = dirname4(configPath);
|
|
9375
|
-
if (!
|
|
9636
|
+
if (!existsSync6(parentDir)) {
|
|
9376
9637
|
mkdirSync3(parentDir, { recursive: true });
|
|
9377
9638
|
}
|
|
9378
9639
|
let backupPath = null;
|
|
9379
|
-
if (
|
|
9640
|
+
if (existsSync6(configPath)) {
|
|
9380
9641
|
backupPath = createBackup(configPath);
|
|
9381
9642
|
}
|
|
9382
9643
|
const tempPath = `${configPath}.tmp`;
|
|
@@ -9392,7 +9653,7 @@ function writeConfigFile(configType, content) {
|
|
|
9392
9653
|
}
|
|
9393
9654
|
}
|
|
9394
9655
|
function createBackup(filePath) {
|
|
9395
|
-
const original =
|
|
9656
|
+
const original = readFileSync6(filePath, "utf-8");
|
|
9396
9657
|
const ext = filePath.split(".").pop() ?? "";
|
|
9397
9658
|
const base = basename2(filePath, `.${ext}`);
|
|
9398
9659
|
const dir = dirname4(filePath);
|
|
@@ -9430,7 +9691,7 @@ var EMPTY_CODEX_AUDIT, SettingsSchema;
|
|
|
9430
9691
|
var init_settings2 = __esm({
|
|
9431
9692
|
"packages/server/src/commands/settings.ts"() {
|
|
9432
9693
|
"use strict";
|
|
9433
|
-
|
|
9694
|
+
init_src3();
|
|
9434
9695
|
init_config_io();
|
|
9435
9696
|
init_provider_config();
|
|
9436
9697
|
init_provider_config_repo();
|
|
@@ -9710,9 +9971,9 @@ var init_supervisor2 = __esm({
|
|
|
9710
9971
|
});
|
|
9711
9972
|
|
|
9712
9973
|
// packages/server/src/git/worktree.ts
|
|
9713
|
-
import
|
|
9974
|
+
import path8 from "node:path";
|
|
9714
9975
|
function normalizeWorktreePath(worktreePath) {
|
|
9715
|
-
return
|
|
9976
|
+
return path8.resolve(worktreePath);
|
|
9716
9977
|
}
|
|
9717
9978
|
async function resolveWorktreePath(repoPath, worktreePath) {
|
|
9718
9979
|
const normalizedRequested = normalizeWorktreePath(worktreePath);
|
|
@@ -9799,19 +10060,19 @@ async function getWorktreeTree(worktreePath) {
|
|
|
9799
10060
|
for (const line of lines) {
|
|
9800
10061
|
const isDir = line.endsWith("/");
|
|
9801
10062
|
const name = isDir ? line.slice(0, -1) : line;
|
|
9802
|
-
const
|
|
10063
|
+
const path9 = `${worktreePath}/${name}`;
|
|
9803
10064
|
nodes.push({
|
|
9804
10065
|
name,
|
|
9805
|
-
path:
|
|
10066
|
+
path: path9,
|
|
9806
10067
|
kind: isDir ? "dir" : "file"
|
|
9807
10068
|
});
|
|
9808
10069
|
}
|
|
9809
10070
|
return nodes;
|
|
9810
10071
|
}
|
|
9811
|
-
async function createWorktree(repoPath, branch,
|
|
9812
|
-
await runGit(repoPath, ["worktree", "add",
|
|
10072
|
+
async function createWorktree(repoPath, branch, path9) {
|
|
10073
|
+
await runGit(repoPath, ["worktree", "add", path9, branch]);
|
|
9813
10074
|
const worktrees = await listWorktrees(repoPath);
|
|
9814
|
-
const created = worktrees.find((wt) => wt.path ===
|
|
10075
|
+
const created = worktrees.find((wt) => wt.path === path9);
|
|
9815
10076
|
if (!created) {
|
|
9816
10077
|
throw new Error("Failed to find created worktree");
|
|
9817
10078
|
}
|
|
@@ -10009,8 +10270,6 @@ var init_commands = __esm({
|
|
|
10009
10270
|
});
|
|
10010
10271
|
|
|
10011
10272
|
// packages/server/src/server.ts
|
|
10012
|
-
import { execFile as nodeExecFile3 } from "node:child_process";
|
|
10013
|
-
import { promisify as promisify3 } from "node:util";
|
|
10014
10273
|
function createCodexConfigAuditApi() {
|
|
10015
10274
|
return {
|
|
10016
10275
|
audit: () => ({ codex: auditCodexConfigToml() }),
|
|
@@ -10038,7 +10297,6 @@ async function logCodexConfigFindings(auditApi, logger) {
|
|
|
10038
10297
|
}
|
|
10039
10298
|
}
|
|
10040
10299
|
async function createServer(configOverrides) {
|
|
10041
|
-
const execFileAsync3 = promisify3(nodeExecFile3);
|
|
10042
10300
|
const config = parseServerConfig(configOverrides);
|
|
10043
10301
|
ensureDataDir(config);
|
|
10044
10302
|
const db = openDatabase(config.dataDir);
|
|
@@ -10120,7 +10378,7 @@ async function createServer(configOverrides) {
|
|
|
10120
10378
|
const providerRuntimeDeps = {};
|
|
10121
10379
|
const providerInstallMgr = new ProviderInstallManager(providerRegistry, {
|
|
10122
10380
|
...providerRuntimeDeps,
|
|
10123
|
-
|
|
10381
|
+
runCommand: runCommandAsString
|
|
10124
10382
|
});
|
|
10125
10383
|
const commandContext = {
|
|
10126
10384
|
workspaceMgr,
|
|
@@ -10283,10 +10541,12 @@ var init_server = __esm({
|
|
|
10283
10541
|
"use strict";
|
|
10284
10542
|
init_runtime();
|
|
10285
10543
|
init_src();
|
|
10544
|
+
init_src2();
|
|
10286
10545
|
init_app();
|
|
10287
10546
|
init_event_bus();
|
|
10288
10547
|
init_codex_config_audit();
|
|
10289
10548
|
init_config();
|
|
10549
|
+
init_command_runner();
|
|
10290
10550
|
init_install_manager();
|
|
10291
10551
|
init_manager();
|
|
10292
10552
|
init_db();
|
|
@@ -10306,7 +10566,7 @@ var init_server = __esm({
|
|
|
10306
10566
|
init_fencing();
|
|
10307
10567
|
init_hub();
|
|
10308
10568
|
init_commands();
|
|
10309
|
-
if (import.meta.url
|
|
10569
|
+
if (isDirectExecution(import.meta.url)) {
|
|
10310
10570
|
const server = await createServer();
|
|
10311
10571
|
process.on("SIGINT", async () => {
|
|
10312
10572
|
console.log("\nShutting down...");
|
|
@@ -10456,8 +10716,8 @@ var init_workspace_repo = __esm({
|
|
|
10456
10716
|
/**
|
|
10457
10717
|
* Finds a workspace by path
|
|
10458
10718
|
*/
|
|
10459
|
-
findByPath(
|
|
10460
|
-
const row = this.db.prepare("SELECT * FROM workspaces WHERE path = ?").get(
|
|
10719
|
+
findByPath(path9) {
|
|
10720
|
+
const row = this.db.prepare("SELECT * FROM workspaces WHERE path = ?").get(path9);
|
|
10461
10721
|
return row ? this.rowToWorkspace(row) : void 0;
|
|
10462
10722
|
}
|
|
10463
10723
|
/**
|
|
@@ -10578,7 +10838,7 @@ __export(src_exports, {
|
|
|
10578
10838
|
sessionToRow: () => sessionToRow,
|
|
10579
10839
|
withTransaction: () => withTransaction
|
|
10580
10840
|
});
|
|
10581
|
-
var
|
|
10841
|
+
var init_src4 = __esm({
|
|
10582
10842
|
async "packages/server/src/index.ts"() {
|
|
10583
10843
|
"use strict";
|
|
10584
10844
|
init_auth();
|
|
@@ -10591,16 +10851,16 @@ var init_src3 = __esm({
|
|
|
10591
10851
|
}
|
|
10592
10852
|
});
|
|
10593
10853
|
|
|
10594
|
-
// packages/cli/src/
|
|
10595
|
-
import { existsSync as
|
|
10596
|
-
import { dirname as dirname6, join as join10
|
|
10854
|
+
// packages/cli/src/cli.ts
|
|
10855
|
+
import { existsSync as existsSync11 } from "fs";
|
|
10856
|
+
import { dirname as dirname6, join as join10 } from "path";
|
|
10597
10857
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
10598
10858
|
|
|
10599
10859
|
// packages/cli/src/auth-control.ts
|
|
10600
|
-
await
|
|
10860
|
+
await init_src4();
|
|
10601
10861
|
|
|
10602
10862
|
// packages/cli/src/config-store.ts
|
|
10603
|
-
import { existsSync as
|
|
10863
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
|
|
10604
10864
|
import { homedir as homedir5 } from "os";
|
|
10605
10865
|
import { basename as basename3, join as join8 } from "path";
|
|
10606
10866
|
var DEFAULT_DB_FILE = "coder-studio.db";
|
|
@@ -10617,12 +10877,12 @@ function normalizeDataDir(input2) {
|
|
|
10617
10877
|
return join8(input2, DEFAULT_DB_FILE);
|
|
10618
10878
|
}
|
|
10619
10879
|
function readCliConfig() {
|
|
10620
|
-
const
|
|
10621
|
-
if (!
|
|
10880
|
+
const path9 = getCliConfigPath();
|
|
10881
|
+
if (!existsSync7(path9)) {
|
|
10622
10882
|
return null;
|
|
10623
10883
|
}
|
|
10624
10884
|
try {
|
|
10625
|
-
const parsed = JSON.parse(
|
|
10885
|
+
const parsed = JSON.parse(readFileSync7(path9, "utf-8"));
|
|
10626
10886
|
if (parsed.host !== void 0 && typeof parsed.host !== "string" || parsed.port !== void 0 && typeof parsed.port !== "number" || parsed.dataDir !== void 0 && typeof parsed.dataDir !== "string" || parsed.password !== void 0 && typeof parsed.password !== "string") {
|
|
10627
10887
|
return null;
|
|
10628
10888
|
}
|
|
@@ -10632,7 +10892,7 @@ function readCliConfig() {
|
|
|
10632
10892
|
}
|
|
10633
10893
|
}
|
|
10634
10894
|
function writeCliConfig(config) {
|
|
10635
|
-
const
|
|
10895
|
+
const path9 = getCliConfigPath();
|
|
10636
10896
|
const dir = join8(homedir5(), ".coder-studio");
|
|
10637
10897
|
const normalizedConfig = {
|
|
10638
10898
|
...config.host !== void 0 ? { host: config.host } : {},
|
|
@@ -10640,10 +10900,10 @@ function writeCliConfig(config) {
|
|
|
10640
10900
|
...config.dataDir !== void 0 ? { dataDir: normalizeDataDir(config.dataDir) } : {},
|
|
10641
10901
|
...config.password !== void 0 ? { password: config.password } : {}
|
|
10642
10902
|
};
|
|
10643
|
-
if (!
|
|
10903
|
+
if (!existsSync7(dir)) {
|
|
10644
10904
|
mkdirSync4(dir, { recursive: true });
|
|
10645
10905
|
}
|
|
10646
|
-
writeFileSync4(
|
|
10906
|
+
writeFileSync4(path9, JSON.stringify(normalizedConfig, null, 2), "utf-8");
|
|
10647
10907
|
}
|
|
10648
10908
|
|
|
10649
10909
|
// packages/cli/src/auth-control.ts
|
|
@@ -10679,7 +10939,7 @@ async function clearAuthBlockByIp(ip) {
|
|
|
10679
10939
|
}
|
|
10680
10940
|
|
|
10681
10941
|
// packages/cli/src/browser.ts
|
|
10682
|
-
import { spawn as
|
|
10942
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
10683
10943
|
function getOpenCommand(url) {
|
|
10684
10944
|
switch (process.platform) {
|
|
10685
10945
|
case "darwin":
|
|
@@ -10693,9 +10953,10 @@ function getOpenCommand(url) {
|
|
|
10693
10953
|
async function openBrowser(url) {
|
|
10694
10954
|
const { command, args } = getOpenCommand(url);
|
|
10695
10955
|
await new Promise((resolve4, reject) => {
|
|
10696
|
-
const child =
|
|
10956
|
+
const child = spawn3(command, args, {
|
|
10697
10957
|
detached: true,
|
|
10698
|
-
stdio: "ignore"
|
|
10958
|
+
stdio: "ignore",
|
|
10959
|
+
windowsHide: true
|
|
10699
10960
|
});
|
|
10700
10961
|
child.once("error", reject);
|
|
10701
10962
|
child.once("spawn", () => {
|
|
@@ -10706,30 +10967,30 @@ async function openBrowser(url) {
|
|
|
10706
10967
|
}
|
|
10707
10968
|
|
|
10708
10969
|
// packages/cli/src/log-excerpt.ts
|
|
10709
|
-
import { closeSync, existsSync as
|
|
10970
|
+
import { closeSync, existsSync as existsSync8, openSync, readSync, statSync as statSync2 } from "fs";
|
|
10710
10971
|
var DEFAULT_MAX_LINES = 40;
|
|
10711
10972
|
var DEFAULT_MAX_CHARS = 4e3;
|
|
10712
10973
|
var DEFAULT_MAX_BYTES = 16 * 1024;
|
|
10713
|
-
var getFileSize = (
|
|
10714
|
-
if (!
|
|
10974
|
+
var getFileSize = (path9) => {
|
|
10975
|
+
if (!existsSync8(path9)) {
|
|
10715
10976
|
return 0;
|
|
10716
10977
|
}
|
|
10717
10978
|
try {
|
|
10718
|
-
return statSync2(
|
|
10979
|
+
return statSync2(path9).size;
|
|
10719
10980
|
} catch {
|
|
10720
10981
|
return 0;
|
|
10721
10982
|
}
|
|
10722
10983
|
};
|
|
10723
|
-
var readLogExcerpt = (
|
|
10984
|
+
var readLogExcerpt = (path9, {
|
|
10724
10985
|
startOffset = 0,
|
|
10725
10986
|
maxBytes = DEFAULT_MAX_BYTES,
|
|
10726
10987
|
maxLines = DEFAULT_MAX_LINES,
|
|
10727
10988
|
maxChars = DEFAULT_MAX_CHARS
|
|
10728
10989
|
} = {}) => {
|
|
10729
|
-
if (!
|
|
10990
|
+
if (!existsSync8(path9)) {
|
|
10730
10991
|
return null;
|
|
10731
10992
|
}
|
|
10732
|
-
const fileSize = getFileSize(
|
|
10993
|
+
const fileSize = getFileSize(path9);
|
|
10733
10994
|
const safeOffset = startOffset > fileSize ? 0 : Math.max(0, startOffset);
|
|
10734
10995
|
if (fileSize === safeOffset) {
|
|
10735
10996
|
return null;
|
|
@@ -10737,7 +10998,7 @@ var readLogExcerpt = (path8, {
|
|
|
10737
10998
|
const bytesToRead = Math.min(fileSize - safeOffset, maxBytes);
|
|
10738
10999
|
const readStart = fileSize - bytesToRead;
|
|
10739
11000
|
const buffer = Buffer.allocUnsafe(bytesToRead);
|
|
10740
|
-
const fd = openSync(
|
|
11001
|
+
const fd = openSync(path9, "r");
|
|
10741
11002
|
let content = "";
|
|
10742
11003
|
let startsMidLine = false;
|
|
10743
11004
|
try {
|
|
@@ -10804,6 +11065,27 @@ function assertSupportedNodeVersion(version = process.versions.node) {
|
|
|
10804
11065
|
);
|
|
10805
11066
|
}
|
|
10806
11067
|
|
|
11068
|
+
// packages/cli/src/package-manifest.ts
|
|
11069
|
+
import { existsSync as existsSync9, readFileSync as readFileSync8 } from "fs";
|
|
11070
|
+
function resolveCliPackageManifestUrl(importMetaUrl) {
|
|
11071
|
+
const manifestUrl = [
|
|
11072
|
+
new URL("../package.json", importMetaUrl),
|
|
11073
|
+
new URL("../../package.json", importMetaUrl)
|
|
11074
|
+
].find((candidate) => existsSync9(candidate));
|
|
11075
|
+
if (!manifestUrl) {
|
|
11076
|
+
throw new Error("Unable to locate CLI package.json");
|
|
11077
|
+
}
|
|
11078
|
+
return manifestUrl;
|
|
11079
|
+
}
|
|
11080
|
+
function getCliPackageManifest(importMetaUrl) {
|
|
11081
|
+
return JSON.parse(
|
|
11082
|
+
readFileSync8(resolveCliPackageManifestUrl(importMetaUrl), "utf-8")
|
|
11083
|
+
);
|
|
11084
|
+
}
|
|
11085
|
+
function getCliVersion(importMetaUrl) {
|
|
11086
|
+
return getCliPackageManifest(importMetaUrl).version ?? "0.0.0";
|
|
11087
|
+
}
|
|
11088
|
+
|
|
10807
11089
|
// packages/cli/src/parse-args.ts
|
|
10808
11090
|
var RUNTIME_CONFIG_ERROR = "Host, port, data-dir, password, and auth settings must be configured via the config command";
|
|
10809
11091
|
function getActiveCommand(args) {
|
|
@@ -11013,6 +11295,8 @@ var MANAGED_SERVER_NAME = "coder-studio-server";
|
|
|
11013
11295
|
var PM2_RESTART_DELAY_MS = 2e3;
|
|
11014
11296
|
var PM2_MIN_UPTIME = "5s";
|
|
11015
11297
|
var PM2_MAX_RESTARTS = 10;
|
|
11298
|
+
var PM2_DELETE_WAIT_MS = 5e3;
|
|
11299
|
+
var PM2_DISCONNECT_WAIT_MS = 1e3;
|
|
11016
11300
|
var STARTUP_POLL_INTERVAL_MS = 100;
|
|
11017
11301
|
var STARTUP_FAILURE_GUIDANCE = "Run `coder-studio logs` for details or `coder-studio serve --foreground` for interactive debugging.";
|
|
11018
11302
|
var isMissingManagedServerError = (error) => {
|
|
@@ -11061,32 +11345,45 @@ var sleep = async (ms) => new Promise((resolve4) => {
|
|
|
11061
11345
|
});
|
|
11062
11346
|
var disconnectPm2 = async () => {
|
|
11063
11347
|
const pm2 = await loadPm2();
|
|
11064
|
-
|
|
11065
|
-
|
|
11066
|
-
|
|
11067
|
-
|
|
11068
|
-
return new Promise((resolve4, reject) => {
|
|
11069
|
-
pm2.describe(MANAGED_SERVER_NAME, (error, result) => {
|
|
11070
|
-
if (error) {
|
|
11071
|
-
reject(error);
|
|
11072
|
-
return;
|
|
11073
|
-
}
|
|
11074
|
-
resolve4(result ?? []);
|
|
11075
|
-
});
|
|
11076
|
-
});
|
|
11077
|
-
};
|
|
11078
|
-
var removeManagedServer = async () => {
|
|
11079
|
-
const pm2 = await loadPm2();
|
|
11080
|
-
return new Promise((resolve4, reject) => {
|
|
11081
|
-
pm2.delete(MANAGED_SERVER_NAME, (error) => {
|
|
11082
|
-
if (error) {
|
|
11083
|
-
reject(error);
|
|
11348
|
+
await new Promise((resolve4) => {
|
|
11349
|
+
let settled = false;
|
|
11350
|
+
const finish = () => {
|
|
11351
|
+
if (settled) {
|
|
11084
11352
|
return;
|
|
11085
11353
|
}
|
|
11354
|
+
settled = true;
|
|
11086
11355
|
resolve4();
|
|
11087
|
-
}
|
|
11356
|
+
};
|
|
11357
|
+
const timer = setTimeout(finish, PM2_DISCONNECT_WAIT_MS);
|
|
11358
|
+
try {
|
|
11359
|
+
pm2.disconnect(() => {
|
|
11360
|
+
clearTimeout(timer);
|
|
11361
|
+
finish();
|
|
11362
|
+
});
|
|
11363
|
+
} catch {
|
|
11364
|
+
clearTimeout(timer);
|
|
11365
|
+
finish();
|
|
11366
|
+
}
|
|
11088
11367
|
});
|
|
11089
11368
|
};
|
|
11369
|
+
var describeManagedServer = async (pm2) => new Promise((resolve4, reject) => {
|
|
11370
|
+
pm2.describe(MANAGED_SERVER_NAME, (error, result) => {
|
|
11371
|
+
if (error) {
|
|
11372
|
+
reject(error);
|
|
11373
|
+
return;
|
|
11374
|
+
}
|
|
11375
|
+
resolve4(result ?? []);
|
|
11376
|
+
});
|
|
11377
|
+
});
|
|
11378
|
+
var removeManagedServer = async (pm2) => new Promise((resolve4, reject) => {
|
|
11379
|
+
pm2.delete(MANAGED_SERVER_NAME, (error) => {
|
|
11380
|
+
if (error) {
|
|
11381
|
+
reject(error);
|
|
11382
|
+
return;
|
|
11383
|
+
}
|
|
11384
|
+
resolve4();
|
|
11385
|
+
});
|
|
11386
|
+
});
|
|
11090
11387
|
var killPm2Daemon = async () => {
|
|
11091
11388
|
const pm2 = await loadPm2();
|
|
11092
11389
|
return new Promise((resolve4) => {
|
|
@@ -11098,6 +11395,7 @@ var killPm2Daemon = async () => {
|
|
|
11098
11395
|
var connectWithRecovery = async () => {
|
|
11099
11396
|
try {
|
|
11100
11397
|
await connectPm2();
|
|
11398
|
+
return loadPm2();
|
|
11101
11399
|
} catch (error) {
|
|
11102
11400
|
if (isPm2BrokenStateError(error)) {
|
|
11103
11401
|
console.warn("PM2 daemon is in a stale state. Killing and reconnecting...");
|
|
@@ -11108,26 +11406,27 @@ var connectWithRecovery = async () => {
|
|
|
11108
11406
|
await sleep(1e3);
|
|
11109
11407
|
cachedPm2 = null;
|
|
11110
11408
|
await connectPm2();
|
|
11409
|
+
return loadPm2();
|
|
11111
11410
|
} else {
|
|
11112
11411
|
throw error;
|
|
11113
11412
|
}
|
|
11114
11413
|
}
|
|
11115
11414
|
};
|
|
11116
11415
|
var withPm2Connection = async (operation) => {
|
|
11117
|
-
await connectWithRecovery();
|
|
11416
|
+
const pm2 = await connectWithRecovery();
|
|
11118
11417
|
try {
|
|
11119
|
-
return await operation();
|
|
11418
|
+
return await operation(pm2);
|
|
11120
11419
|
} finally {
|
|
11121
11420
|
await disconnectPm2();
|
|
11122
11421
|
}
|
|
11123
11422
|
};
|
|
11124
|
-
var waitForRuntimeReady = async (waitMs, logOffsets) => {
|
|
11423
|
+
var waitForRuntimeReady = async (pm2, waitMs, logOffsets) => {
|
|
11125
11424
|
const deadline = Date.now() + waitMs;
|
|
11126
11425
|
while (Date.now() <= deadline) {
|
|
11127
11426
|
if (readRuntimeConfig()) {
|
|
11128
11427
|
return;
|
|
11129
11428
|
}
|
|
11130
|
-
const processes = await describeManagedServer();
|
|
11429
|
+
const processes = await describeManagedServer(pm2);
|
|
11131
11430
|
const process2 = processes[0];
|
|
11132
11431
|
if (!process2) {
|
|
11133
11432
|
throw createStartupError(
|
|
@@ -11147,14 +11446,39 @@ var waitForRuntimeReady = async (waitMs, logOffsets) => {
|
|
|
11147
11446
|
}
|
|
11148
11447
|
throw createStartupError(`runtime readiness timed out after ${waitMs}ms`, logOffsets);
|
|
11149
11448
|
};
|
|
11150
|
-
var
|
|
11151
|
-
|
|
11152
|
-
|
|
11449
|
+
var waitForManagedServerDeletion = async (pm2, waitMs) => {
|
|
11450
|
+
const deadline = Date.now() + waitMs;
|
|
11451
|
+
while (Date.now() <= deadline) {
|
|
11452
|
+
const processes = await describeManagedServer(pm2);
|
|
11153
11453
|
if (processes.length === 0) {
|
|
11154
11454
|
return;
|
|
11155
11455
|
}
|
|
11156
|
-
|
|
11456
|
+
const remainingMs = deadline - Date.now();
|
|
11457
|
+
if (remainingMs <= 0) {
|
|
11458
|
+
break;
|
|
11459
|
+
}
|
|
11460
|
+
await sleep(Math.min(STARTUP_POLL_INTERVAL_MS, remainingMs));
|
|
11157
11461
|
}
|
|
11462
|
+
throw new Error(`Timed out waiting for the managed server to stop after ${waitMs}ms.`);
|
|
11463
|
+
};
|
|
11464
|
+
var deleteManagedServerInSession = async (pm2, {
|
|
11465
|
+
ignoreMissing = false
|
|
11466
|
+
} = {}) => {
|
|
11467
|
+
const processes = await describeManagedServer(pm2);
|
|
11468
|
+
if (processes.length === 0) {
|
|
11469
|
+
return false;
|
|
11470
|
+
}
|
|
11471
|
+
try {
|
|
11472
|
+
await removeManagedServer(pm2);
|
|
11473
|
+
} catch (error) {
|
|
11474
|
+
if (ignoreMissing && isMissingManagedServerError(error)) {
|
|
11475
|
+
await waitForManagedServerDeletion(pm2, PM2_DELETE_WAIT_MS);
|
|
11476
|
+
return false;
|
|
11477
|
+
}
|
|
11478
|
+
throw error;
|
|
11479
|
+
}
|
|
11480
|
+
await waitForManagedServerDeletion(pm2, PM2_DELETE_WAIT_MS);
|
|
11481
|
+
return true;
|
|
11158
11482
|
};
|
|
11159
11483
|
var ensureLogDirectory = () => {
|
|
11160
11484
|
mkdirSync5(join9(homedir6(), ".coder-studio", "logs"), { recursive: true });
|
|
@@ -11196,69 +11520,51 @@ var createStartupError = (reason, offsets) => {
|
|
|
11196
11520
|
};
|
|
11197
11521
|
var deleteManagedServer = async ({
|
|
11198
11522
|
ignoreMissing = false
|
|
11199
|
-
} = {}) => withPm2Connection(
|
|
11200
|
-
const processes = await describeManagedServer();
|
|
11201
|
-
if (processes.length === 0) {
|
|
11202
|
-
return false;
|
|
11203
|
-
}
|
|
11204
|
-
try {
|
|
11205
|
-
await removeManagedServer();
|
|
11206
|
-
return true;
|
|
11207
|
-
} catch (error) {
|
|
11208
|
-
if (ignoreMissing && isMissingManagedServerError(error)) {
|
|
11209
|
-
return false;
|
|
11210
|
-
}
|
|
11211
|
-
throw error;
|
|
11212
|
-
}
|
|
11213
|
-
});
|
|
11523
|
+
} = {}) => withPm2Connection((pm2) => deleteManagedServerInSession(pm2, { ignoreMissing }));
|
|
11214
11524
|
var startManagedServer = async ({
|
|
11215
11525
|
script,
|
|
11216
11526
|
cwd,
|
|
11217
11527
|
waitMs,
|
|
11218
11528
|
args
|
|
11219
|
-
}) => {
|
|
11220
|
-
await
|
|
11221
|
-
await withPm2Connection(waitForManagedServerExit);
|
|
11529
|
+
}) => withPm2Connection(async (pm2) => {
|
|
11530
|
+
await deleteManagedServerInSession(pm2, { ignoreMissing: true });
|
|
11222
11531
|
if (readRuntimeConfig()) {
|
|
11223
11532
|
deleteRuntimeConfig();
|
|
11224
11533
|
}
|
|
11225
11534
|
ensureLogDirectory();
|
|
11226
11535
|
const { outFile, errFile } = getLogPaths();
|
|
11227
|
-
const
|
|
11228
|
-
await
|
|
11229
|
-
|
|
11230
|
-
|
|
11231
|
-
|
|
11232
|
-
|
|
11233
|
-
|
|
11234
|
-
|
|
11235
|
-
|
|
11236
|
-
...
|
|
11237
|
-
|
|
11238
|
-
...process.env,
|
|
11239
|
-
NODE_ENV: "production"
|
|
11240
|
-
},
|
|
11241
|
-
autorestart: true,
|
|
11242
|
-
restart_delay: PM2_RESTART_DELAY_MS,
|
|
11243
|
-
min_uptime: PM2_MIN_UPTIME,
|
|
11244
|
-
max_restarts: PM2_MAX_RESTARTS,
|
|
11245
|
-
out_file: outFile,
|
|
11246
|
-
error_file: errFile
|
|
11536
|
+
const logOffsets = captureStartupLogOffsets();
|
|
11537
|
+
await new Promise((resolve4, reject) => {
|
|
11538
|
+
pm2.start(
|
|
11539
|
+
{
|
|
11540
|
+
name: MANAGED_SERVER_NAME,
|
|
11541
|
+
script,
|
|
11542
|
+
cwd,
|
|
11543
|
+
...args !== void 0 ? { args } : {},
|
|
11544
|
+
env: {
|
|
11545
|
+
...process.env,
|
|
11546
|
+
NODE_ENV: "production"
|
|
11247
11547
|
},
|
|
11248
|
-
|
|
11249
|
-
|
|
11250
|
-
|
|
11251
|
-
|
|
11252
|
-
|
|
11253
|
-
|
|
11548
|
+
autorestart: true,
|
|
11549
|
+
restart_delay: PM2_RESTART_DELAY_MS,
|
|
11550
|
+
min_uptime: PM2_MIN_UPTIME,
|
|
11551
|
+
max_restarts: PM2_MAX_RESTARTS,
|
|
11552
|
+
out_file: outFile,
|
|
11553
|
+
error_file: errFile
|
|
11554
|
+
},
|
|
11555
|
+
(error) => {
|
|
11556
|
+
if (error) {
|
|
11557
|
+
reject(error);
|
|
11558
|
+
return;
|
|
11254
11559
|
}
|
|
11255
|
-
|
|
11256
|
-
|
|
11257
|
-
|
|
11560
|
+
resolve4();
|
|
11561
|
+
}
|
|
11562
|
+
);
|
|
11258
11563
|
});
|
|
11259
|
-
|
|
11260
|
-
|
|
11261
|
-
|
|
11564
|
+
await waitForRuntimeReady(pm2, waitMs, logOffsets);
|
|
11565
|
+
});
|
|
11566
|
+
var getManagedServerStatus = async () => withPm2Connection(async (pm2) => {
|
|
11567
|
+
const processes = await describeManagedServer(pm2);
|
|
11262
11568
|
const process2 = processes[0];
|
|
11263
11569
|
if (!process2) {
|
|
11264
11570
|
return {
|
|
@@ -11291,6 +11597,13 @@ var getManagedServerStatus = async () => withPm2Connection(async () => {
|
|
|
11291
11597
|
restartCount
|
|
11292
11598
|
};
|
|
11293
11599
|
}
|
|
11600
|
+
if (pm2Pid === null || pm2Pid === 0) {
|
|
11601
|
+
return {
|
|
11602
|
+
status: "stopped",
|
|
11603
|
+
pm2Pid: null,
|
|
11604
|
+
restartCount
|
|
11605
|
+
};
|
|
11606
|
+
}
|
|
11294
11607
|
return {
|
|
11295
11608
|
status: "errored",
|
|
11296
11609
|
pm2Pid,
|
|
@@ -11327,7 +11640,7 @@ async function getServerStatus() {
|
|
|
11327
11640
|
const managedStatus = await getManagedServerStatus();
|
|
11328
11641
|
const runtime = readRuntimeConfig();
|
|
11329
11642
|
const { outFile, errFile } = getLogPaths();
|
|
11330
|
-
if (managedStatus.status === "stopped") {
|
|
11643
|
+
if (managedStatus.status === "stopped" || managedStatus.pm2Pid === null && runtime === null) {
|
|
11331
11644
|
if (runtime) {
|
|
11332
11645
|
deleteRuntimeConfig();
|
|
11333
11646
|
}
|
|
@@ -11358,17 +11671,17 @@ async function getServerStatus() {
|
|
|
11358
11671
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
11359
11672
|
|
|
11360
11673
|
// packages/cli/src/embed.ts
|
|
11361
|
-
import { existsSync as
|
|
11362
|
-
import { dirname as dirname5, resolve as
|
|
11674
|
+
import { existsSync as existsSync10 } from "fs";
|
|
11675
|
+
import { dirname as dirname5, resolve as resolve3 } from "path";
|
|
11363
11676
|
import { fileURLToPath } from "url";
|
|
11364
11677
|
var __filename = fileURLToPath(import.meta.url);
|
|
11365
11678
|
var __dirname = dirname5(__filename);
|
|
11366
|
-
var WEB_ASSETS_DIR =
|
|
11679
|
+
var WEB_ASSETS_DIR = resolve3(__dirname, "../web");
|
|
11367
11680
|
function getStaticAssetsDir() {
|
|
11368
11681
|
return WEB_ASSETS_DIR;
|
|
11369
11682
|
}
|
|
11370
11683
|
function hasWebAssets() {
|
|
11371
|
-
return
|
|
11684
|
+
return existsSync10(WEB_ASSETS_DIR);
|
|
11372
11685
|
}
|
|
11373
11686
|
|
|
11374
11687
|
// packages/cli/src/server-runner.ts
|
|
@@ -11376,6 +11689,7 @@ var MISSING_WEB_ASSETS_WARNING = "Warning: Web assets not found. Frontend will n
|
|
|
11376
11689
|
var buildServerConfig = () => {
|
|
11377
11690
|
const savedConfig = readCliConfig();
|
|
11378
11691
|
const config = {
|
|
11692
|
+
appVersion: getCliVersion(import.meta.url),
|
|
11379
11693
|
...savedConfig?.host !== void 0 ? { host: savedConfig.host } : {},
|
|
11380
11694
|
...savedConfig?.port !== void 0 && savedConfig.port > 0 ? { port: savedConfig.port } : {},
|
|
11381
11695
|
...savedConfig?.dataDir !== void 0 ? { dataDir: savedConfig.dataDir } : {},
|
|
@@ -11418,7 +11732,7 @@ var runServerEntrypoint = async (moduleUrl, argvEntry) => {
|
|
|
11418
11732
|
};
|
|
11419
11733
|
var startServer = async () => {
|
|
11420
11734
|
assertSupportedNodeVersion();
|
|
11421
|
-
const { createServer: createServer2 } = await
|
|
11735
|
+
const { createServer: createServer2 } = await init_src4().then(() => src_exports);
|
|
11422
11736
|
const server = await createServer2(buildServerConfig());
|
|
11423
11737
|
const shutdown = createShutdownHandler(server);
|
|
11424
11738
|
process.on("SIGINT", shutdown);
|
|
@@ -11451,7 +11765,7 @@ function getBrowserUrl(status) {
|
|
|
11451
11765
|
return `http://${host}:${status.port}`;
|
|
11452
11766
|
}
|
|
11453
11767
|
|
|
11454
|
-
// packages/cli/src/
|
|
11768
|
+
// packages/cli/src/cli.ts
|
|
11455
11769
|
var MANAGED_SERVER_WAIT_MS = 5e3;
|
|
11456
11770
|
var DEFAULT_LOG_TAIL_LINES = 40;
|
|
11457
11771
|
function formatConfig(config) {
|
|
@@ -11480,8 +11794,8 @@ function showLogs(status, {
|
|
|
11480
11794
|
errorsOnly = false
|
|
11481
11795
|
} = {}) {
|
|
11482
11796
|
const paths = errorsOnly ? [status.errFile] : [status.outFile, status.errFile];
|
|
11483
|
-
const contents = paths.filter((
|
|
11484
|
-
const content = readLogExcerpt(
|
|
11797
|
+
const contents = paths.filter((path9, index, paths2) => paths2.indexOf(path9) === index).flatMap((path9) => {
|
|
11798
|
+
const content = readLogExcerpt(path9, { maxLines: tail, maxChars: null });
|
|
11485
11799
|
return content ? [content] : [];
|
|
11486
11800
|
});
|
|
11487
11801
|
console.log(contents.length === 0 ? "No logs available." : contents.join("\n"));
|
|
@@ -11559,16 +11873,7 @@ EXAMPLES:
|
|
|
11559
11873
|
`);
|
|
11560
11874
|
}
|
|
11561
11875
|
function showVersion() {
|
|
11562
|
-
|
|
11563
|
-
new URL("../package.json", import.meta.url),
|
|
11564
|
-
new URL("../../package.json", import.meta.url)
|
|
11565
|
-
].find((candidate) => existsSync9(candidate));
|
|
11566
|
-
if (!manifestPath) {
|
|
11567
|
-
throw new Error("Unable to locate CLI package.json");
|
|
11568
|
-
}
|
|
11569
|
-
const manifest = JSON.parse(readFileSync7(manifestPath, "utf-8"));
|
|
11570
|
-
const version = manifest.version ?? "0.0.0";
|
|
11571
|
-
console.log(`@spencer-kit/coder-studio v${version}`);
|
|
11876
|
+
console.log(`@spencer-kit/coder-studio v${getCliVersion(import.meta.url)}`);
|
|
11572
11877
|
}
|
|
11573
11878
|
function formatAuthBlocks(blocks) {
|
|
11574
11879
|
if (blocks.length === 0) {
|
|
@@ -11584,26 +11889,12 @@ function resolveManagedScriptPath() {
|
|
|
11584
11889
|
join10(currentDir, "server-runner.mjs"),
|
|
11585
11890
|
join10(currentDir, "../src/server-runner.ts")
|
|
11586
11891
|
];
|
|
11587
|
-
const scriptPath = candidates.find((candidate) =>
|
|
11892
|
+
const scriptPath = candidates.find((candidate) => existsSync11(candidate));
|
|
11588
11893
|
if (!scriptPath) {
|
|
11589
11894
|
throw new Error("Unable to locate the managed server entry script");
|
|
11590
11895
|
}
|
|
11591
11896
|
return scriptPath;
|
|
11592
11897
|
}
|
|
11593
|
-
function isCliEntrypoint() {
|
|
11594
|
-
if (process.argv[1] === void 0) {
|
|
11595
|
-
return false;
|
|
11596
|
-
}
|
|
11597
|
-
const currentFile = fileURLToPath3(import.meta.url);
|
|
11598
|
-
const currentDir = dirname6(currentFile);
|
|
11599
|
-
const entryScript = resolve3(process.argv[1]);
|
|
11600
|
-
const entryCandidates = /* @__PURE__ */ new Set([
|
|
11601
|
-
currentFile,
|
|
11602
|
-
join10(currentDir, "../bin.js"),
|
|
11603
|
-
join10(currentDir, "../dist/bin.js")
|
|
11604
|
-
]);
|
|
11605
|
-
return entryCandidates.has(entryScript);
|
|
11606
|
-
}
|
|
11607
11898
|
function isRunningStatus(status) {
|
|
11608
11899
|
return status.status === "running" || status.status === "starting";
|
|
11609
11900
|
}
|
|
@@ -11746,14 +12037,11 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
11746
12037
|
console.log("Coder Studio server started in background.");
|
|
11747
12038
|
console.log("Run `coder-studio status` to inspect the server.");
|
|
11748
12039
|
}
|
|
11749
|
-
|
|
11750
|
-
|
|
11751
|
-
|
|
11752
|
-
|
|
11753
|
-
|
|
11754
|
-
|
|
11755
|
-
}
|
|
11756
|
-
export {
|
|
11757
|
-
main
|
|
11758
|
-
};
|
|
12040
|
+
|
|
12041
|
+
// packages/cli/src/bin.ts
|
|
12042
|
+
void main().catch((error) => {
|
|
12043
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
12044
|
+
console.error("CLI error:", message);
|
|
12045
|
+
process.exit(1);
|
|
12046
|
+
});
|
|
11759
12047
|
//# sourceMappingURL=bin.mjs.map
|