hanoman 0.1.32 → 0.1.34
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 +3 -1
- package/dist/build-info.json +3 -3
- package/dist/cli.js +128 -117
- package/dist/server.js +198 -119
- package/package.json +1 -1
- package/web/assets/{index-CFtKJvO8.js → index-Ce9LtSUQ.js} +50 -50
- package/web/index.html +1 -1
package/dist/server.js
CHANGED
|
@@ -8929,6 +8929,61 @@ var init_telegram_operator = __esm({
|
|
|
8929
8929
|
}
|
|
8930
8930
|
});
|
|
8931
8931
|
|
|
8932
|
+
// ../runner/src/spawn-helper.ts
|
|
8933
|
+
import { readdirSync as readdirSync2, existsSync as existsSync4, statSync, chmodSync } from "node:fs";
|
|
8934
|
+
import { dirname as dirname4, join as join3 } from "node:path";
|
|
8935
|
+
function spawnHelperPaths(ptyDir, listDir, exists) {
|
|
8936
|
+
const dirs = [join3(ptyDir, "build", "Release")];
|
|
8937
|
+
for (const name2 of listDir(join3(ptyDir, "prebuilds"))) dirs.push(join3(ptyDir, "prebuilds", name2));
|
|
8938
|
+
return dirs.map((d) => join3(d, "spawn-helper")).filter(exists);
|
|
8939
|
+
}
|
|
8940
|
+
function ensureSpawnHelpersExecutable(paths2, ops) {
|
|
8941
|
+
const fixed = [];
|
|
8942
|
+
for (const p of paths2) {
|
|
8943
|
+
try {
|
|
8944
|
+
const mode = ops.mode(p) & 4095;
|
|
8945
|
+
if ((mode & 73) === 73) continue;
|
|
8946
|
+
ops.chmod(p, mode | 73);
|
|
8947
|
+
fixed.push(p);
|
|
8948
|
+
} catch {
|
|
8949
|
+
}
|
|
8950
|
+
}
|
|
8951
|
+
return fixed;
|
|
8952
|
+
}
|
|
8953
|
+
function repairSpawnHelper(resolve19, notify) {
|
|
8954
|
+
let ptyDir;
|
|
8955
|
+
try {
|
|
8956
|
+
ptyDir = dirname4(resolve19("node-pty/package.json"));
|
|
8957
|
+
} catch {
|
|
8958
|
+
return [];
|
|
8959
|
+
}
|
|
8960
|
+
const paths2 = spawnHelperPaths(ptyDir, (d) => {
|
|
8961
|
+
try {
|
|
8962
|
+
return readdirSync2(d);
|
|
8963
|
+
} catch {
|
|
8964
|
+
return [];
|
|
8965
|
+
}
|
|
8966
|
+
}, existsSync4);
|
|
8967
|
+
const fixed = ensureSpawnHelpersExecutable(paths2, {
|
|
8968
|
+
mode: (p) => statSync(p).mode,
|
|
8969
|
+
chmod: (p, m) => chmodSync(p, m)
|
|
8970
|
+
});
|
|
8971
|
+
if (fixed.length) notify?.("hanoman \xB7 memperbaiki izin `spawn-helper` node-pty (sekali per instalasi)\n");
|
|
8972
|
+
return fixed;
|
|
8973
|
+
}
|
|
8974
|
+
function ensureSpawnHelperOnce(resolve19, notify) {
|
|
8975
|
+
if (repaired) return [];
|
|
8976
|
+
repaired = true;
|
|
8977
|
+
return repairSpawnHelper(resolve19, notify);
|
|
8978
|
+
}
|
|
8979
|
+
var repaired;
|
|
8980
|
+
var init_spawn_helper = __esm({
|
|
8981
|
+
"../runner/src/spawn-helper.ts"() {
|
|
8982
|
+
"use strict";
|
|
8983
|
+
repaired = false;
|
|
8984
|
+
}
|
|
8985
|
+
});
|
|
8986
|
+
|
|
8932
8987
|
// ../runner/src/index.ts
|
|
8933
8988
|
var init_src2 = __esm({
|
|
8934
8989
|
"../runner/src/index.ts"() {
|
|
@@ -8948,6 +9003,7 @@ var init_src2 = __esm({
|
|
|
8948
9003
|
init_paths();
|
|
8949
9004
|
init_skills();
|
|
8950
9005
|
init_telegram_operator();
|
|
9006
|
+
init_spawn_helper();
|
|
8951
9007
|
}
|
|
8952
9008
|
});
|
|
8953
9009
|
|
|
@@ -9083,7 +9139,7 @@ var init_tap = __esm({
|
|
|
9083
9139
|
|
|
9084
9140
|
// src/db.ts
|
|
9085
9141
|
import { mkdirSync as mkdirSync2 } from "node:fs";
|
|
9086
|
-
import { dirname as
|
|
9142
|
+
import { dirname as dirname5, resolve as resolve7 } from "node:path";
|
|
9087
9143
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
9088
9144
|
import { PrismaClient } from "@prisma/client";
|
|
9089
9145
|
var schemaDir, notice, url, base, prisma;
|
|
@@ -9093,13 +9149,13 @@ var init_db = __esm({
|
|
|
9093
9149
|
init_env();
|
|
9094
9150
|
init_src2();
|
|
9095
9151
|
init_tap();
|
|
9096
|
-
schemaDir = resolve7(
|
|
9152
|
+
schemaDir = resolve7(dirname5(fileURLToPath2(import.meta.url)), "../prisma");
|
|
9097
9153
|
process.umask(63);
|
|
9098
9154
|
notice = dbUrlNotice(process.env);
|
|
9099
9155
|
if (notice) console.warn(notice);
|
|
9100
9156
|
url = resolveDbUrl(process.env, schemaDir);
|
|
9101
9157
|
process.env.DATABASE_URL = url;
|
|
9102
|
-
mkdirSync2(
|
|
9158
|
+
mkdirSync2(dirname5(dbFilePath(url)), { recursive: true, mode: 448 });
|
|
9103
9159
|
base = new PrismaClient();
|
|
9104
9160
|
prisma = base.$extends(webhookTap(base));
|
|
9105
9161
|
}
|
|
@@ -9115,7 +9171,7 @@ var init_stage_machine = __esm({
|
|
|
9115
9171
|
});
|
|
9116
9172
|
|
|
9117
9173
|
// src/services/session-phases.ts
|
|
9118
|
-
import { readFileSync as readFileSync3, readdirSync as
|
|
9174
|
+
import { readFileSync as readFileSync3, readdirSync as readdirSync3 } from "node:fs";
|
|
9119
9175
|
function recorded(file) {
|
|
9120
9176
|
const out3 = /* @__PURE__ */ new Map();
|
|
9121
9177
|
let raw2;
|
|
@@ -9163,7 +9219,7 @@ function planComplete(worktree, specId) {
|
|
|
9163
9219
|
const dir2 = `${worktree}/${rel}`;
|
|
9164
9220
|
let names;
|
|
9165
9221
|
try {
|
|
9166
|
-
names =
|
|
9222
|
+
names = readdirSync3(dir2);
|
|
9167
9223
|
} catch {
|
|
9168
9224
|
continue;
|
|
9169
9225
|
}
|
|
@@ -9453,9 +9509,9 @@ var init_tui_dialog = __esm({
|
|
|
9453
9509
|
});
|
|
9454
9510
|
|
|
9455
9511
|
// src/services/secret-box.ts
|
|
9456
|
-
import { chmodSync, existsSync as
|
|
9512
|
+
import { chmodSync as chmodSync2, existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync } from "node:fs";
|
|
9457
9513
|
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
|
|
9458
|
-
import { dirname as
|
|
9514
|
+
import { dirname as dirname6, join as join4 } from "node:path";
|
|
9459
9515
|
function isEncrypted(value) {
|
|
9460
9516
|
return value.startsWith(ENC_PREFIX);
|
|
9461
9517
|
}
|
|
@@ -9487,7 +9543,7 @@ function fromEnv(raw2) {
|
|
|
9487
9543
|
return null;
|
|
9488
9544
|
}
|
|
9489
9545
|
function secretKeyPath() {
|
|
9490
|
-
return
|
|
9546
|
+
return join4(resolveHome(), "secret.key");
|
|
9491
9547
|
}
|
|
9492
9548
|
function secretKey() {
|
|
9493
9549
|
if (cached) return cached;
|
|
@@ -9499,16 +9555,16 @@ function secretKey() {
|
|
|
9499
9555
|
return key2;
|
|
9500
9556
|
}
|
|
9501
9557
|
const path2 = secretKeyPath();
|
|
9502
|
-
if (
|
|
9558
|
+
if (existsSync5(path2)) {
|
|
9503
9559
|
const key2 = Buffer.from(readFileSync4(path2, "utf8").trim(), "base64url");
|
|
9504
9560
|
if (key2.length !== KEY_BYTES) throw new Error(`kunci di ${path2} rusak \u2014 panjangnya bukan 32 byte`);
|
|
9505
9561
|
cached = key2;
|
|
9506
9562
|
return key2;
|
|
9507
9563
|
}
|
|
9508
9564
|
const key = randomBytes(KEY_BYTES);
|
|
9509
|
-
mkdirSync3(
|
|
9565
|
+
mkdirSync3(dirname6(path2), { recursive: true });
|
|
9510
9566
|
writeFileSync(path2, key.toString("base64url"), { mode: 384 });
|
|
9511
|
-
|
|
9567
|
+
chmodSync2(path2, 384);
|
|
9512
9568
|
cached = key;
|
|
9513
9569
|
return key;
|
|
9514
9570
|
}
|
|
@@ -9693,9 +9749,10 @@ var init_session_sandbox = __esm({
|
|
|
9693
9749
|
// src/services/pty.ts
|
|
9694
9750
|
import { spawn } from "node-pty";
|
|
9695
9751
|
import { execFileSync } from "node:child_process";
|
|
9752
|
+
import { createRequire } from "node:module";
|
|
9696
9753
|
import { randomUUID } from "node:crypto";
|
|
9697
|
-
import { mkdirSync as mkdirSync4, statSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
9698
|
-
import { dirname as
|
|
9754
|
+
import { mkdirSync as mkdirSync4, statSync as statSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
9755
|
+
import { dirname as dirname7 } from "node:path";
|
|
9699
9756
|
import { tmpdir } from "node:os";
|
|
9700
9757
|
function tmux(...args) {
|
|
9701
9758
|
try {
|
|
@@ -9778,7 +9835,7 @@ function createSession(projectId, cwd, opts = {}) {
|
|
|
9778
9835
|
let promptFile;
|
|
9779
9836
|
if (!opts.command && opts.prompt) {
|
|
9780
9837
|
promptFile = promptFilePath(id);
|
|
9781
|
-
mkdirSync4(
|
|
9838
|
+
mkdirSync4(dirname7(promptFile), { recursive: true, mode: 448 });
|
|
9782
9839
|
writeFileSync2(promptFile, opts.prompt + rosterBlock, { mode: 384 });
|
|
9783
9840
|
promptArg = `"$(cat ${sq(promptFile)})"`;
|
|
9784
9841
|
}
|
|
@@ -9790,7 +9847,7 @@ function createSession(projectId, cwd, opts = {}) {
|
|
|
9790
9847
|
let goalGate;
|
|
9791
9848
|
if (agent === "codex" && opts.goal && opts.flow && opts.specId) {
|
|
9792
9849
|
goalGate = goalGatePath(id);
|
|
9793
|
-
mkdirSync4(
|
|
9850
|
+
mkdirSync4(dirname7(goalGate), { recursive: true, mode: 448 });
|
|
9794
9851
|
writeFileSync2(goalGate, codexGoalScript({
|
|
9795
9852
|
flow: opts.flow,
|
|
9796
9853
|
specId: opts.specId,
|
|
@@ -9806,7 +9863,7 @@ function createSession(projectId, cwd, opts = {}) {
|
|
|
9806
9863
|
const json = renderAgentsJson(customDefs);
|
|
9807
9864
|
if (json) {
|
|
9808
9865
|
agentsFile = agentsFilePath(id);
|
|
9809
|
-
mkdirSync4(
|
|
9866
|
+
mkdirSync4(dirname7(agentsFile), { recursive: true, mode: 448 });
|
|
9810
9867
|
writeFileSync2(agentsFile, json, { mode: 384 });
|
|
9811
9868
|
}
|
|
9812
9869
|
}
|
|
@@ -9826,7 +9883,7 @@ function createSession(projectId, cwd, opts = {}) {
|
|
|
9826
9883
|
for (const [k, v] of Object.entries(rootBypassEnv())) envPairs.push(`${k}=${sq(v)}`);
|
|
9827
9884
|
}
|
|
9828
9885
|
if (opts.phaseFile) {
|
|
9829
|
-
mkdirSync4(
|
|
9886
|
+
mkdirSync4(dirname7(opts.phaseFile), { recursive: true });
|
|
9830
9887
|
envPairs.push(`HANOMAN_PHASE_FILE=${sq(opts.phaseFile)}`);
|
|
9831
9888
|
}
|
|
9832
9889
|
for (const [k, v] of Object.entries(opts.env ?? {})) envPairs.push(`${k}=${sq(v)}`);
|
|
@@ -9837,7 +9894,7 @@ function createSession(projectId, cwd, opts = {}) {
|
|
|
9837
9894
|
phaseFile: opts.phaseFile,
|
|
9838
9895
|
promptFile
|
|
9839
9896
|
});
|
|
9840
|
-
if (opts.decisionFile) mkdirSync4(
|
|
9897
|
+
if (opts.decisionFile) mkdirSync4(dirname7(opts.decisionFile), { recursive: true });
|
|
9841
9898
|
tmux(
|
|
9842
9899
|
"set-option",
|
|
9843
9900
|
"-g",
|
|
@@ -10132,6 +10189,7 @@ function detachAll() {
|
|
|
10132
10189
|
for (const id of [...attached.keys()]) drop(id);
|
|
10133
10190
|
}
|
|
10134
10191
|
function spawnPty(...args) {
|
|
10192
|
+
ensureSpawnHelperOnce(createRequire(import.meta.url).resolve, (m) => process.stdout.write(m));
|
|
10135
10193
|
try {
|
|
10136
10194
|
return spawn("tmux", ["-L", socket(), "-f", "/dev/null", ...args], {
|
|
10137
10195
|
name: "xterm-256color",
|
|
@@ -10164,7 +10222,7 @@ var init_pty = __esm({
|
|
|
10164
10222
|
POLL_MS = 500;
|
|
10165
10223
|
markerFilled = (f) => {
|
|
10166
10224
|
try {
|
|
10167
|
-
return
|
|
10225
|
+
return statSync2(f).size > 0;
|
|
10168
10226
|
} catch {
|
|
10169
10227
|
return false;
|
|
10170
10228
|
}
|
|
@@ -24258,8 +24316,8 @@ import fastifyStatic from "@fastify/static";
|
|
|
24258
24316
|
import websocket from "@fastify/websocket";
|
|
24259
24317
|
import cookie from "@fastify/cookie";
|
|
24260
24318
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
24261
|
-
import { dirname as
|
|
24262
|
-
import { existsSync as
|
|
24319
|
+
import { dirname as dirname13 } from "node:path";
|
|
24320
|
+
import { existsSync as existsSync16 } from "node:fs";
|
|
24263
24321
|
|
|
24264
24322
|
// src/web-dir.ts
|
|
24265
24323
|
import { resolve } from "node:path";
|
|
@@ -24322,13 +24380,13 @@ init_stage_machine();
|
|
|
24322
24380
|
init_src();
|
|
24323
24381
|
import { execFile } from "node:child_process";
|
|
24324
24382
|
import { promisify } from "node:util";
|
|
24325
|
-
import { existsSync as
|
|
24383
|
+
import { existsSync as existsSync6, rmSync as rmSync2 } from "node:fs";
|
|
24326
24384
|
import { resolve as resolve9 } from "node:path";
|
|
24327
24385
|
|
|
24328
24386
|
// src/services/safe-repo-path.ts
|
|
24329
24387
|
import { constants } from "node:fs";
|
|
24330
24388
|
import { lstat, mkdir, open as open2, realpath, rename, unlink } from "node:fs/promises";
|
|
24331
|
-
import { isAbsolute as isAbsolute3, join as
|
|
24389
|
+
import { isAbsolute as isAbsolute3, join as join5, relative, resolve as resolve8, sep as sep2 } from "node:path";
|
|
24332
24390
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
24333
24391
|
import { closeSync, fstatSync, lstatSync, mkdirSync as mkdirSync5, openSync, readFileSync as readFileSync5, realpathSync as realpathSync2, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
24334
24392
|
var PathContainmentError = class extends Error {
|
|
@@ -24358,7 +24416,7 @@ async function ensureRepoParents(root, rel) {
|
|
|
24358
24416
|
const parts = components(rel).slice(0, -1);
|
|
24359
24417
|
let current = base2;
|
|
24360
24418
|
for (const part of parts) {
|
|
24361
|
-
current =
|
|
24419
|
+
current = join5(current, part);
|
|
24362
24420
|
try {
|
|
24363
24421
|
await mkdir(current, { mode: 448 });
|
|
24364
24422
|
} catch (error) {
|
|
@@ -24375,7 +24433,7 @@ function ensureRepoParentsSync(root, rel) {
|
|
|
24375
24433
|
const parts = components(rel).slice(0, -1);
|
|
24376
24434
|
let current = base2;
|
|
24377
24435
|
for (const part of parts) {
|
|
24378
|
-
current =
|
|
24436
|
+
current = join5(current, part);
|
|
24379
24437
|
try {
|
|
24380
24438
|
mkdirSync5(current, { mode: 448 });
|
|
24381
24439
|
} catch (error) {
|
|
@@ -24391,7 +24449,7 @@ async function resolveRepoEntry(root, rel, opts = {}) {
|
|
|
24391
24449
|
const parts = components(rel);
|
|
24392
24450
|
let current = base2;
|
|
24393
24451
|
for (let i = 0; i < parts.length; i++) {
|
|
24394
|
-
current =
|
|
24452
|
+
current = join5(current, parts[i]);
|
|
24395
24453
|
const stat2 = await lstat(current).catch((error) => {
|
|
24396
24454
|
if (error.code === "ENOENT" && opts.allowMissingFinal && i === parts.length - 1) return null;
|
|
24397
24455
|
return denied("komponen tidak ada");
|
|
@@ -24411,7 +24469,7 @@ function assertSafeRepoPathSync(root, rel, allowMissingFinal = false, allowMissi
|
|
|
24411
24469
|
const parts = components(rel);
|
|
24412
24470
|
let current = base2;
|
|
24413
24471
|
for (let i = 0; i < parts.length; i++) {
|
|
24414
|
-
current =
|
|
24472
|
+
current = join5(current, parts[i]);
|
|
24415
24473
|
try {
|
|
24416
24474
|
const stat2 = lstatSync(current);
|
|
24417
24475
|
if (stat2.isSymbolicLink()) denied("symlink");
|
|
@@ -24441,7 +24499,7 @@ function writeRepoFileAtomicSync(root, rel, data) {
|
|
|
24441
24499
|
const parent = resolve8(path2, "..");
|
|
24442
24500
|
const parentRel = relative(realpathSync2(root), parent);
|
|
24443
24501
|
if (parentRel) assertSafeRepoPathSync(root, parentRel);
|
|
24444
|
-
const temp =
|
|
24502
|
+
const temp = join5(parent, `.hanoman-${randomUUID2()}.tmp`);
|
|
24445
24503
|
const fd = openSync(temp, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (constants.O_NOFOLLOW ?? 0), 384);
|
|
24446
24504
|
try {
|
|
24447
24505
|
writeFileSync3(fd, data);
|
|
@@ -24488,7 +24546,7 @@ async function writeRepoFileAtomic(root, rel, data) {
|
|
|
24488
24546
|
await mkdir(entry.parent, { recursive: false, mode: 448 }).catch((error) => {
|
|
24489
24547
|
if (error.code !== "EEXIST") throw error;
|
|
24490
24548
|
});
|
|
24491
|
-
const temp =
|
|
24549
|
+
const temp = join5(entry.parent, `.hanoman-${randomUUID2()}.tmp`);
|
|
24492
24550
|
const handle = await open2(temp, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (constants.O_NOFOLLOW ?? 0), 384);
|
|
24493
24551
|
try {
|
|
24494
24552
|
await handle.writeFile(data);
|
|
@@ -24533,12 +24591,12 @@ function docsDirOf(repoDir) {
|
|
|
24533
24591
|
}
|
|
24534
24592
|
function resolveIndex(repoDir, docsDir) {
|
|
24535
24593
|
const rel = `${docsDir}/README.md`;
|
|
24536
|
-
return
|
|
24594
|
+
return existsSync6(resolve9(repoDir, rel)) ? rel : "";
|
|
24537
24595
|
}
|
|
24538
24596
|
var catOf = (rel) => rel.includes("/") ? rel.slice(0, rel.lastIndexOf("/")) : ".";
|
|
24539
24597
|
var nameOf = (rel) => rel.includes("/") ? rel.slice(rel.lastIndexOf("/") + 1) : rel;
|
|
24540
24598
|
async function scanRepoDocs(repoDir) {
|
|
24541
|
-
if (!repoDir || !
|
|
24599
|
+
if (!repoDir || !existsSync6(repoDir)) return { coverage: 0, tree: [] };
|
|
24542
24600
|
const files = await listRepoDocs(repoDir);
|
|
24543
24601
|
const docsDir = docsDirOf(repoDir);
|
|
24544
24602
|
const index = resolveIndex(repoDir, docsDir);
|
|
@@ -24586,7 +24644,7 @@ function writeDocFile(repoDir, rel, content) {
|
|
|
24586
24644
|
}
|
|
24587
24645
|
function deleteDocFile(repoDir, rel) {
|
|
24588
24646
|
const abs = docAbsPath(repoDir, rel);
|
|
24589
|
-
if (!
|
|
24647
|
+
if (!existsSync6(abs)) return false;
|
|
24590
24648
|
rmSync2(abs);
|
|
24591
24649
|
return true;
|
|
24592
24650
|
}
|
|
@@ -24873,13 +24931,13 @@ async function projects_default(app2) {
|
|
|
24873
24931
|
// src/routes/specs.ts
|
|
24874
24932
|
init_src();
|
|
24875
24933
|
init_src2();
|
|
24876
|
-
import { existsSync as
|
|
24934
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
24877
24935
|
|
|
24878
24936
|
// src/services/integrate.ts
|
|
24879
24937
|
import { execFile as execFile3 } from "node:child_process";
|
|
24880
24938
|
import { promisify as promisify3 } from "node:util";
|
|
24881
24939
|
import { rmSync as rmSync3 } from "node:fs";
|
|
24882
|
-
import { join as
|
|
24940
|
+
import { join as join6 } from "node:path";
|
|
24883
24941
|
var sanitize = (id) => id.toLowerCase().replace(/[^a-z0-9_-]/g, "_");
|
|
24884
24942
|
var sourceBranch = (specId) => `hanoman/${sanitize(specId)}`;
|
|
24885
24943
|
var exec3 = promisify3(execFile3);
|
|
@@ -24923,7 +24981,7 @@ async function integrateBranch(repoDir, src, op, target2) {
|
|
|
24923
24981
|
const tgt = await resolveTarget(repoDir, target2);
|
|
24924
24982
|
if (!tgt) return { status: "error", code: 400, error: `target "${target2}" tidak dikenal` };
|
|
24925
24983
|
await sh(repoDir, ["fetch", "origin"]);
|
|
24926
|
-
const wt =
|
|
24984
|
+
const wt = join6(repoDir, ".worktrees", `merge-${sanitize(src.mergeId)}`);
|
|
24927
24985
|
await reclaim(repoDir, wt);
|
|
24928
24986
|
const baseRef = op === "merge" ? tgt.ref : source;
|
|
24929
24987
|
const baseSha = await out(repoDir, ["rev-parse", "--verify", "--end-of-options", `${baseRef}^{commit}`]);
|
|
@@ -24984,7 +25042,7 @@ async function mergeIntoCurrent(repoDir, source, opts = {}) {
|
|
|
24984
25042
|
const src = await resolveGraphSource(repoDir, source);
|
|
24985
25043
|
if (!src) return { status: "error", code: 400, error: `source "${source}" tak dikenal` };
|
|
24986
25044
|
await sh(repoDir, ["fetch", "origin"]);
|
|
24987
|
-
const wt =
|
|
25045
|
+
const wt = join6(repoDir, ".worktrees", `merge-${sanitize(current)}`);
|
|
24988
25046
|
await reclaim(repoDir, wt);
|
|
24989
25047
|
const baseSha = await out(repoDir, ["rev-parse", "--verify", "--end-of-options", `refs/heads/${current}^{commit}`]);
|
|
24990
25048
|
if (!await ok(repoDir, ["worktree", "add", "--detach", "-q", wt, baseSha]))
|
|
@@ -25022,7 +25080,7 @@ async function replayCurrent(repoDir, source, cmd) {
|
|
|
25022
25080
|
const current = await out(repoDir, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
25023
25081
|
if (!current || current === "HEAD")
|
|
25024
25082
|
return { status: "error", code: 409, error: "HEAD detached \u2014 checkout sebuah branch dulu" };
|
|
25025
|
-
const wt =
|
|
25083
|
+
const wt = join6(repoDir, ".worktrees", `merge-${sanitize(current)}`);
|
|
25026
25084
|
await reclaim(repoDir, wt);
|
|
25027
25085
|
const baseSha = await out(repoDir, ["rev-parse", "--verify", "--end-of-options", `refs/heads/${current}^{commit}`]);
|
|
25028
25086
|
if (!await ok(repoDir, ["worktree", "add", "--detach", "-q", wt, baseSha]))
|
|
@@ -25071,15 +25129,15 @@ import { execFile as execFile4 } from "node:child_process";
|
|
|
25071
25129
|
import { promisify as promisify4 } from "node:util";
|
|
25072
25130
|
import { mkdtemp, copyFile, rm } from "node:fs/promises";
|
|
25073
25131
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
25074
|
-
import { join as
|
|
25132
|
+
import { join as join7, resolve as resolve10 } from "node:path";
|
|
25075
25133
|
var exec4 = promisify4(execFile4);
|
|
25076
25134
|
var GIT3 = { maxBuffer: 1 << 24 };
|
|
25077
25135
|
var MAX = 256 * 1024;
|
|
25078
|
-
var worktreeDir = (repoDir, specId) =>
|
|
25136
|
+
var worktreeDir = (repoDir, specId) => join7(repoDir, ".worktrees", specId.toLowerCase().replace(/[^a-z0-9_-]/g, "_"));
|
|
25079
25137
|
async function withTempIndex(wt, fn2) {
|
|
25080
25138
|
const idx = (await exec4("git", ["rev-parse", "--git-path", "index"], { cwd: wt, ...GIT3 })).stdout.trim();
|
|
25081
|
-
const dir2 = await mkdtemp(
|
|
25082
|
-
const tmp =
|
|
25139
|
+
const dir2 = await mkdtemp(join7(tmpdir2(), "hanoman-idx-"));
|
|
25140
|
+
const tmp = join7(dir2, "index");
|
|
25083
25141
|
await copyFile(resolve10(wt, idx), tmp);
|
|
25084
25142
|
const env = { ...process.env, GIT_INDEX_FILE: tmp };
|
|
25085
25143
|
try {
|
|
@@ -28388,7 +28446,7 @@ ${item.context}` : item.context;
|
|
|
28388
28446
|
});
|
|
28389
28447
|
const specWithProject = (id) => prisma.spec.findUnique({ where: { id }, include: { project: true } });
|
|
28390
28448
|
const resolveReview = async (repoDir, spec) => {
|
|
28391
|
-
if (
|
|
28449
|
+
if (existsSync7(worktreeDir(repoDir, spec.id))) return { wt: true };
|
|
28392
28450
|
if (spec.baseSha && spec.headSha && await shaResolvable(repoDir, spec.baseSha) && await shaResolvable(repoDir, spec.headSha))
|
|
28393
28451
|
return { wt: false, base: spec.baseSha, head: spec.headSha };
|
|
28394
28452
|
const r = await specCommitRange(repoDir, spec.id);
|
|
@@ -28629,7 +28687,7 @@ import { spawn as spawn2 } from "node:child_process";
|
|
|
28629
28687
|
// src/services/git-remotes.ts
|
|
28630
28688
|
import { execFile as execFile5 } from "node:child_process";
|
|
28631
28689
|
import { promisify as promisify5 } from "node:util";
|
|
28632
|
-
import { existsSync as
|
|
28690
|
+
import { existsSync as existsSync8 } from "node:fs";
|
|
28633
28691
|
var exec5 = promisify5(execFile5);
|
|
28634
28692
|
var GIT4 = { maxBuffer: 1 << 24, encoding: "utf8" };
|
|
28635
28693
|
function parseRemote(url2) {
|
|
@@ -28648,7 +28706,7 @@ function prUrl(remoteUrl, branch, base2 = "main") {
|
|
|
28648
28706
|
return null;
|
|
28649
28707
|
}
|
|
28650
28708
|
async function listRemotes(repoDir) {
|
|
28651
|
-
if (!repoDir || !
|
|
28709
|
+
if (!repoDir || !existsSync8(repoDir)) return [];
|
|
28652
28710
|
try {
|
|
28653
28711
|
const { stdout } = await exec5("git", ["remote", "-v"], { cwd: repoDir, ...GIT4 });
|
|
28654
28712
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -28689,7 +28747,7 @@ import { promisify as promisify7 } from "node:util";
|
|
|
28689
28747
|
// src/services/git-ide.ts
|
|
28690
28748
|
import { execFile as execFile6 } from "node:child_process";
|
|
28691
28749
|
import { promisify as promisify6 } from "node:util";
|
|
28692
|
-
import { existsSync as
|
|
28750
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
28693
28751
|
import { resolve as resolve11 } from "node:path";
|
|
28694
28752
|
var exec6 = promisify6(execFile6);
|
|
28695
28753
|
var GIT5 = { maxBuffer: 1 << 24 };
|
|
@@ -28701,7 +28759,7 @@ function repoAbsPath(repoDir, rel, allowMissingFinal = false) {
|
|
|
28701
28759
|
return resolve11(repoDir, rel);
|
|
28702
28760
|
}
|
|
28703
28761
|
async function listRepoTree(repoDir, ref = "") {
|
|
28704
|
-
if (!repoDir || !
|
|
28762
|
+
if (!repoDir || !existsSync9(repoDir)) return [];
|
|
28705
28763
|
try {
|
|
28706
28764
|
const { stdout } = ref ? await exec6("git", ["ls-tree", "-r", "--name-only", "-z", ref], { cwd: repoDir, ...GIT5 }) : await exec6("git", ["ls-files", "--cached", "--others", "--exclude-standard", "-z"], { cwd: repoDir, ...GIT5 });
|
|
28707
28765
|
return [...new Set(splitZ2(stdout))].sort();
|
|
@@ -28727,7 +28785,7 @@ async function currentBranch(repoDir) {
|
|
|
28727
28785
|
}
|
|
28728
28786
|
async function repoStatus(repoDir) {
|
|
28729
28787
|
const empty = { branch: "", ahead: 0, behind: 0, staged: [], unstaged: [], untracked: [], clean: true };
|
|
28730
|
-
if (!repoDir || !
|
|
28788
|
+
if (!repoDir || !existsSync9(repoDir)) return empty;
|
|
28731
28789
|
try {
|
|
28732
28790
|
const { stdout } = await exec6("git", ["status", "--porcelain=v1", "-z", "-b"], { cwd: repoDir, ...GIT5 });
|
|
28733
28791
|
const parts = stdout.split("\0");
|
|
@@ -28760,7 +28818,7 @@ async function repoStatus(repoDir) {
|
|
|
28760
28818
|
}
|
|
28761
28819
|
}
|
|
28762
28820
|
async function listStashes(repoDir) {
|
|
28763
|
-
if (!repoDir || !
|
|
28821
|
+
if (!repoDir || !existsSync9(repoDir)) return [];
|
|
28764
28822
|
try {
|
|
28765
28823
|
const { stdout } = await exec6("git", ["stash", "list", `--format=%gd${US}%s${US}%aI`], { cwd: repoDir, ...GIT5 });
|
|
28766
28824
|
return stdout.split("\n").filter(Boolean).map((line) => {
|
|
@@ -28772,7 +28830,7 @@ async function listStashes(repoDir) {
|
|
|
28772
28830
|
}
|
|
28773
28831
|
}
|
|
28774
28832
|
async function listGraph(repoDir, limit = 200, opts = {}) {
|
|
28775
|
-
if (!repoDir || !
|
|
28833
|
+
if (!repoDir || !existsSync9(repoDir)) return { commits: [], current: "", total: 0 };
|
|
28776
28834
|
try {
|
|
28777
28835
|
const fmt = ["%H", "%P", "%an", "%aI", "%s", "%D"].join(US);
|
|
28778
28836
|
const refArgs = opts.branches?.length ? ["--end-of-options", ...opts.branches] : [
|
|
@@ -28842,7 +28900,7 @@ async function changedOf(repoDir, sha) {
|
|
|
28842
28900
|
}
|
|
28843
28901
|
async function compareCommits(repoDir, from, to) {
|
|
28844
28902
|
const empty = { from, to, changed: [] };
|
|
28845
|
-
if (!repoDir || !
|
|
28903
|
+
if (!repoDir || !existsSync9(repoDir)) return empty;
|
|
28846
28904
|
try {
|
|
28847
28905
|
const [num, name2] = await Promise.all([
|
|
28848
28906
|
exec6("git", ["diff", "--numstat", "-z", "--no-renames", "--end-of-options", from, to], { cwd: repoDir, ...GIT5 }),
|
|
@@ -28854,7 +28912,7 @@ async function compareCommits(repoDir, from, to) {
|
|
|
28854
28912
|
}
|
|
28855
28913
|
}
|
|
28856
28914
|
async function searchCommits(repoDir, q, by = "all") {
|
|
28857
|
-
if (!repoDir || !
|
|
28915
|
+
if (!repoDir || !existsSync9(repoDir) || !q) return [];
|
|
28858
28916
|
const run2 = async (extra) => {
|
|
28859
28917
|
try {
|
|
28860
28918
|
return (await exec6("git", ["log", "--all", "--format=%H", ...extra], { cwd: repoDir, ...GIT5 })).stdout.split("\n").filter(Boolean);
|
|
@@ -29101,7 +29159,7 @@ async function runGitOp(repoDir, op) {
|
|
|
29101
29159
|
}
|
|
29102
29160
|
}
|
|
29103
29161
|
async function workingStatus(repoDir) {
|
|
29104
|
-
if (!repoDir || !
|
|
29162
|
+
if (!repoDir || !existsSync9(repoDir)) return { branch: "", staged: [], unstaged: [] };
|
|
29105
29163
|
const [branch, staged, unstaged] = await Promise.all([
|
|
29106
29164
|
currentBranch(repoDir),
|
|
29107
29165
|
changedFiles(repoDir, ["--cached"]),
|
|
@@ -29110,7 +29168,7 @@ async function workingStatus(repoDir) {
|
|
|
29110
29168
|
return { branch, staged, unstaged };
|
|
29111
29169
|
}
|
|
29112
29170
|
async function workingFileDiff(repoDir, path2, staged) {
|
|
29113
|
-
if (!repoDir || !
|
|
29171
|
+
if (!repoDir || !existsSync9(repoDir)) return null;
|
|
29114
29172
|
repoAbsPath(repoDir, path2, true);
|
|
29115
29173
|
const changed = staged ? await changedFiles(repoDir, ["--cached"]) : await withTempIndex(repoDir, (env) => changedFiles(repoDir, [], env));
|
|
29116
29174
|
const cf = changed.find((c) => c.path === path2);
|
|
@@ -29588,15 +29646,15 @@ async function finishGraphOp(reply, id, repoDir, r, verb) {
|
|
|
29588
29646
|
// src/routes/fs.ts
|
|
29589
29647
|
import { readdir } from "node:fs/promises";
|
|
29590
29648
|
import { homedir as homedir4 } from "node:os";
|
|
29591
|
-
import { resolve as resolve12, dirname as
|
|
29649
|
+
import { resolve as resolve12, dirname as dirname9, join as join8 } from "node:path";
|
|
29592
29650
|
async function fs_default(app2) {
|
|
29593
29651
|
app2.get("/fs/browse", async (req, reply) => {
|
|
29594
29652
|
const q = req.query.path;
|
|
29595
29653
|
const dir2 = q && q.trim() ? resolve12(q.trim()) : homedir4();
|
|
29596
29654
|
try {
|
|
29597
29655
|
const ents = await readdir(dir2, { withFileTypes: true });
|
|
29598
|
-
const entries = ents.filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => ({ name: e.name, path:
|
|
29599
|
-
const parent =
|
|
29656
|
+
const entries = ents.filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => ({ name: e.name, path: join8(dir2, e.name) })).sort((a, b) => a.name.localeCompare(b.name));
|
|
29657
|
+
const parent = dirname9(dir2);
|
|
29600
29658
|
return { path: dir2, parent: parent === dir2 ? null : parent, entries };
|
|
29601
29659
|
} catch {
|
|
29602
29660
|
return reply.code(400).send({ error: `tak bisa membaca folder "${dir2}"` });
|
|
@@ -29609,7 +29667,7 @@ init_db();
|
|
|
29609
29667
|
init_src();
|
|
29610
29668
|
init_src2();
|
|
29611
29669
|
init_session_phases();
|
|
29612
|
-
import { existsSync as
|
|
29670
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
29613
29671
|
init_settings2();
|
|
29614
29672
|
init_codex_trust();
|
|
29615
29673
|
|
|
@@ -29930,11 +29988,32 @@ function wsControlOrigins(env) {
|
|
|
29930
29988
|
function assertWsOrigin(origin, allowed) {
|
|
29931
29989
|
if (!origin || !allowed.has(origin)) throw new Error("WebSocket Origin rejected");
|
|
29932
29990
|
}
|
|
29991
|
+
function wsAllowlistFor(configured, host2, env) {
|
|
29992
|
+
if (configured.size > 0 || env.NODE_ENV === "production") return configured;
|
|
29993
|
+
const value = host2?.trim().toLowerCase();
|
|
29994
|
+
if (!value) return configured;
|
|
29995
|
+
let parsed;
|
|
29996
|
+
try {
|
|
29997
|
+
parsed = new URL(`http://${value}`);
|
|
29998
|
+
} catch {
|
|
29999
|
+
return configured;
|
|
30000
|
+
}
|
|
30001
|
+
if (!parsed.host || parsed.username || parsed.password || parsed.pathname !== "/" || parsed.search || parsed.hash) return configured;
|
|
30002
|
+
const hosts = /* @__PURE__ */ new Set([parsed.host]);
|
|
30003
|
+
if (parsed.port === "80" || parsed.port === "443") hosts.add(parsed.hostname);
|
|
30004
|
+
const allowed = /* @__PURE__ */ new Set();
|
|
30005
|
+
for (const candidate of hosts) {
|
|
30006
|
+
allowed.add(`http://${candidate}`);
|
|
30007
|
+
allowed.add(`https://${candidate}`);
|
|
30008
|
+
}
|
|
30009
|
+
return allowed;
|
|
30010
|
+
}
|
|
29933
30011
|
function admitBrowserWs(req, target2, allowedOrigins) {
|
|
29934
30012
|
const origin = typeof req.headers.origin === "string" ? req.headers.origin : void 0;
|
|
29935
30013
|
if (!origin && process.env.NODE_ENV === "test" && allowedOrigins.size === 0)
|
|
29936
30014
|
return { kind: "test", id: "test" };
|
|
29937
|
-
|
|
30015
|
+
const host2 = typeof req.headers.host === "string" ? req.headers.host : void 0;
|
|
30016
|
+
assertWsOrigin(origin, wsAllowlistFor(allowedOrigins, host2, process.env));
|
|
29938
30017
|
const token = ticketFromProtocol(req.headers["sec-websocket-protocol"]);
|
|
29939
30018
|
if (!token) throw new Error("WebSocket ticket required");
|
|
29940
30019
|
const principal = consumeWsTicket(token, target2);
|
|
@@ -30022,7 +30101,7 @@ init_db();
|
|
|
30022
30101
|
import { execFile as execFile8 } from "node:child_process";
|
|
30023
30102
|
import { readdir as readdir2, rm as rm2 } from "node:fs/promises";
|
|
30024
30103
|
import { promisify as promisify9 } from "node:util";
|
|
30025
|
-
import { join as
|
|
30104
|
+
import { join as join9, resolve as resolve14 } from "node:path";
|
|
30026
30105
|
var TICK_MS = 6e4;
|
|
30027
30106
|
var trashDirOf = (repoDir) => resolve14(repoDir, ".worktrees", ".trash");
|
|
30028
30107
|
var exec8 = promisify9(execFile8);
|
|
@@ -30081,7 +30160,7 @@ async function sweepRepo(repoDir, projectId, deps = prodReaperDeps) {
|
|
|
30081
30160
|
}
|
|
30082
30161
|
let removed = 0;
|
|
30083
30162
|
for (const entry of entries) {
|
|
30084
|
-
const path2 =
|
|
30163
|
+
const path2 = join9(dir2, entry);
|
|
30085
30164
|
const known = pending.get(path2);
|
|
30086
30165
|
const row = known ?? { path: path2, repoDir, projectId, entry, sessionId: sessionIdOf(entry), since: Date.now() };
|
|
30087
30166
|
pending.set(path2, row);
|
|
@@ -30401,7 +30480,7 @@ async function terminal_default(app2, opts) {
|
|
|
30401
30480
|
if (!s2) return { ok: false, code: 404, msg: "not found" };
|
|
30402
30481
|
const repoDir = await resolveRepoDir(s2.projectId);
|
|
30403
30482
|
if (!repoDir) return { ok: false, code: 409, msg: "project belum punya repoDir" };
|
|
30404
|
-
if (!s2.cwd.includes("/.worktrees/") || !
|
|
30483
|
+
if (!s2.cwd.includes("/.worktrees/") || !existsSync10(s2.cwd))
|
|
30405
30484
|
return { ok: false, code: 409, msg: "belum ada worktree untuk di-review \u2014 jalankan/lanjutkan sesi dulu" };
|
|
30406
30485
|
return { ok: true, id: s2.id, repoDir };
|
|
30407
30486
|
};
|
|
@@ -30533,7 +30612,7 @@ async function terminal_default(app2, opts) {
|
|
|
30533
30612
|
// src/routes/vps.ts
|
|
30534
30613
|
init_db();
|
|
30535
30614
|
init_src();
|
|
30536
|
-
import { readFileSync as readFileSync10, existsSync as
|
|
30615
|
+
import { readFileSync as readFileSync10, existsSync as existsSync13 } from "node:fs";
|
|
30537
30616
|
import { homedir as homedir6 } from "node:os";
|
|
30538
30617
|
|
|
30539
30618
|
// src/vps/catalog/catalog.data.ts
|
|
@@ -30623,7 +30702,7 @@ init_config2();
|
|
|
30623
30702
|
import { spawn as spawn3 } from "node:child_process";
|
|
30624
30703
|
import { mkdtempSync, rmSync as rmSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
30625
30704
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
30626
|
-
import { dirname as
|
|
30705
|
+
import { dirname as dirname10, join as join10 } from "node:path";
|
|
30627
30706
|
var sshBin = () => effectiveStr("HANOMAN_SSH_BIN") ?? "ssh";
|
|
30628
30707
|
function consoleArgv(t) {
|
|
30629
30708
|
return [
|
|
@@ -30638,8 +30717,8 @@ function consoleArgv(t) {
|
|
|
30638
30717
|
];
|
|
30639
30718
|
}
|
|
30640
30719
|
function askpassScript() {
|
|
30641
|
-
const dir2 = mkdtempSync(
|
|
30642
|
-
const path2 =
|
|
30720
|
+
const dir2 = mkdtempSync(join10(tmpdir3(), "hanoman-askpass-"));
|
|
30721
|
+
const path2 = join10(dir2, "askpass.sh");
|
|
30643
30722
|
writeFileSync4(path2, `#!/bin/sh
|
|
30644
30723
|
printf '%s' "$HANOMAN_SSH_PASSWORD"
|
|
30645
30724
|
`, { mode: 448 });
|
|
@@ -30679,7 +30758,7 @@ function sshExec(t, remoteCmd, opts = {}) {
|
|
|
30679
30758
|
const timer9 = setTimeout(() => p.kill("SIGKILL"), opts.timeoutMs ?? 6e4);
|
|
30680
30759
|
const done = (r) => {
|
|
30681
30760
|
clearTimeout(timer9);
|
|
30682
|
-
if (askpass) rmSync4(
|
|
30761
|
+
if (askpass) rmSync4(dirname10(askpass), { recursive: true, force: true });
|
|
30683
30762
|
resolve19(r);
|
|
30684
30763
|
};
|
|
30685
30764
|
p.stdout.on("data", (d) => {
|
|
@@ -30700,16 +30779,16 @@ function sshExec(t, remoteCmd, opts = {}) {
|
|
|
30700
30779
|
// src/services/vps-audit.ts
|
|
30701
30780
|
init_db();
|
|
30702
30781
|
import { readFileSync as readFileSync7 } from "node:fs";
|
|
30703
|
-
import { join as
|
|
30782
|
+
import { join as join12 } from "node:path";
|
|
30704
30783
|
|
|
30705
30784
|
// src/runner/deps.ts
|
|
30706
|
-
import { existsSync as
|
|
30707
|
-
import { dirname as
|
|
30785
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
30786
|
+
import { dirname as dirname11, join as join11 } from "node:path";
|
|
30708
30787
|
function repoRootFrom(startDir) {
|
|
30709
30788
|
let dir2 = startDir;
|
|
30710
30789
|
for (let i = 0; i < 8; i++) {
|
|
30711
|
-
if (
|
|
30712
|
-
const parent =
|
|
30790
|
+
if (existsSync11(join11(dir2, "pnpm-workspace.yaml"))) return dir2;
|
|
30791
|
+
const parent = dirname11(dir2);
|
|
30713
30792
|
if (parent === dir2) break;
|
|
30714
30793
|
dir2 = parent;
|
|
30715
30794
|
}
|
|
@@ -30813,7 +30892,7 @@ function parseHealth(out3) {
|
|
|
30813
30892
|
return { uptime: h.uptime ?? "", disk: h.disk ?? "", mem: h.mem ?? "", load: h.load ?? "" };
|
|
30814
30893
|
}
|
|
30815
30894
|
var target = (v) => ({ host: v.host, port: v.port, user: v.user, keyPath: v.keyPath });
|
|
30816
|
-
var scriptPath = (f) =>
|
|
30895
|
+
var scriptPath = (f) => join12(repoRoot(), "server", "scripts", "vps", f);
|
|
30817
30896
|
async function itemStatesOf(vpsId) {
|
|
30818
30897
|
const rows = await prisma.vpsItemState.findMany({ where: { vpsId } });
|
|
30819
30898
|
return Object.fromEntries(rows.map((s2) => [s2.itemId, { na: s2.na, attested: s2.attested }]));
|
|
@@ -30960,15 +31039,15 @@ async function buildChecklist(vpsId) {
|
|
|
30960
31039
|
// src/services/vps-key.ts
|
|
30961
31040
|
init_config2();
|
|
30962
31041
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
30963
|
-
import { existsSync as
|
|
31042
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync9 } from "node:fs";
|
|
30964
31043
|
import { homedir as homedir5 } from "node:os";
|
|
30965
|
-
import { join as
|
|
30966
|
-
var keyDir = () => effectiveStr("HANOMAN_SSH_KEY_DIR") ??
|
|
31044
|
+
import { join as join13 } from "node:path";
|
|
31045
|
+
var keyDir = () => effectiveStr("HANOMAN_SSH_KEY_DIR") ?? join13(homedir5(), ".hanoman");
|
|
30967
31046
|
function ensureHanomanKey() {
|
|
30968
31047
|
const dir2 = keyDir();
|
|
30969
|
-
const privPath =
|
|
31048
|
+
const privPath = join13(dir2, "id_ed25519");
|
|
30970
31049
|
const pubPath = `${privPath}.pub`;
|
|
30971
|
-
if (!
|
|
31050
|
+
if (!existsSync12(privPath)) {
|
|
30972
31051
|
mkdirSync8(dir2, { recursive: true, mode: 448 });
|
|
30973
31052
|
execFileSync2(
|
|
30974
31053
|
"ssh-keygen",
|
|
@@ -30995,7 +31074,7 @@ async function bootstrapKey(t, password) {
|
|
|
30995
31074
|
init_pty();
|
|
30996
31075
|
init_settings2();
|
|
30997
31076
|
function keyMissing(v) {
|
|
30998
|
-
return !!v.keyPath && !
|
|
31077
|
+
return !!v.keyPath && !existsSync13(v.keyPath);
|
|
30999
31078
|
}
|
|
31000
31079
|
async function vps_default(app2) {
|
|
31001
31080
|
app2.get("/vps", async () => prisma.vps.findMany({ orderBy: { createdAt: "asc" } }));
|
|
@@ -31207,7 +31286,7 @@ init_config2();
|
|
|
31207
31286
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
31208
31287
|
import { readFileSync as readFileSync11 } from "node:fs";
|
|
31209
31288
|
import { homedir as homedir7 } from "node:os";
|
|
31210
|
-
import { join as
|
|
31289
|
+
import { join as join14 } from "node:path";
|
|
31211
31290
|
var USAGE_URL = "https://api.anthropic.com/api/oauth/usage";
|
|
31212
31291
|
var TTL_MS2 = 3e4;
|
|
31213
31292
|
var lastOk = null;
|
|
@@ -31220,7 +31299,7 @@ var LABELS = {
|
|
|
31220
31299
|
var humanize = (k) => k.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
31221
31300
|
var nowIso = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
31222
31301
|
function credsFile() {
|
|
31223
|
-
return
|
|
31302
|
+
return join14(effectiveStr("CLAUDE_CONFIG_DIR") ?? join14(homedir7(), ".claude"), ".credentials.json");
|
|
31224
31303
|
}
|
|
31225
31304
|
function readAccessToken() {
|
|
31226
31305
|
if (process.platform === "darwin" && !effectiveStr("CLAUDE_CONFIG_DIR")) {
|
|
@@ -31294,14 +31373,14 @@ async function getLimits() {
|
|
|
31294
31373
|
// src/services/codex-limits.ts
|
|
31295
31374
|
import { open as open3, readdir as readdir3, stat } from "node:fs/promises";
|
|
31296
31375
|
import { homedir as homedir8 } from "node:os";
|
|
31297
|
-
import { join as
|
|
31376
|
+
import { join as join15 } from "node:path";
|
|
31298
31377
|
var TTL_MS3 = 3e4;
|
|
31299
31378
|
var STALE_AFTER_MS = 12 * 36e5;
|
|
31300
31379
|
var TAIL_BYTES = 512 * 1024;
|
|
31301
31380
|
var MAX_FILES = 8;
|
|
31302
31381
|
var cache2 = null;
|
|
31303
31382
|
var freshUntil2 = 0;
|
|
31304
|
-
var codexSessionsDir = () =>
|
|
31383
|
+
var codexSessionsDir = () => join15(process.env.CODEX_HOME ?? join15(homedir8(), ".codex"), "sessions");
|
|
31305
31384
|
var UNAVAILABLE = { status: "unavailable", windows: [], fetchedAt: null, plan: null };
|
|
31306
31385
|
function windowLabel(minutes) {
|
|
31307
31386
|
if (minutes === 300) return "Sesi 5 jam";
|
|
@@ -31334,7 +31413,7 @@ async function recentRollouts(dir2) {
|
|
|
31334
31413
|
return [];
|
|
31335
31414
|
}
|
|
31336
31415
|
const stamped = await Promise.all(entries.map(async (rel) => {
|
|
31337
|
-
const full =
|
|
31416
|
+
const full = join15(dir2, rel);
|
|
31338
31417
|
try {
|
|
31339
31418
|
return { full, mtime: (await stat(full)).mtimeMs };
|
|
31340
31419
|
} catch {
|
|
@@ -31462,7 +31541,7 @@ init_src();
|
|
|
31462
31541
|
init_src();
|
|
31463
31542
|
init_config2();
|
|
31464
31543
|
import { readFileSync as readFileSync12 } from "node:fs";
|
|
31465
|
-
import { resolve as resolve15, dirname as
|
|
31544
|
+
import { resolve as resolve15, dirname as dirname12 } from "node:path";
|
|
31466
31545
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
31467
31546
|
var UPDATE_COMMAND = "npm i -g hanoman@latest";
|
|
31468
31547
|
function composeUpdate(x) {
|
|
@@ -31487,7 +31566,7 @@ var lastFetchAt = 0;
|
|
|
31487
31566
|
var lastLatest = null;
|
|
31488
31567
|
var lastStatus = "unavailable";
|
|
31489
31568
|
function runningVersion() {
|
|
31490
|
-
const here =
|
|
31569
|
+
const here = dirname12(fileURLToPath3(import.meta.url));
|
|
31491
31570
|
for (const p of [resolve15(here, "build-info.json"), resolve15(here, "../package.json")]) {
|
|
31492
31571
|
try {
|
|
31493
31572
|
const v = JSON.parse(readFileSync12(p, "utf8")).version;
|
|
@@ -31844,17 +31923,17 @@ init_config2();
|
|
|
31844
31923
|
init_safe_outbound_request();
|
|
31845
31924
|
init_src2();
|
|
31846
31925
|
import { mkdir as mkdir2, writeFile, readFile as readFile2, unlink as unlink2 } from "node:fs/promises";
|
|
31847
|
-
import { join as
|
|
31926
|
+
import { join as join16, resolve as resolve16 } from "node:path";
|
|
31848
31927
|
function uploadDir() {
|
|
31849
|
-
return resolve16(effectiveStr("HANOMAN_UPLOAD_DIR") ??
|
|
31928
|
+
return resolve16(effectiveStr("HANOMAN_UPLOAD_DIR") ?? join16(resolveHome(), "uploads"));
|
|
31850
31929
|
}
|
|
31851
31930
|
async function readUpload(storageKey) {
|
|
31852
31931
|
const safe = storageKey.replace(/[/\\]/g, "");
|
|
31853
|
-
return readFile2(
|
|
31932
|
+
return readFile2(join16(uploadDir(), safe));
|
|
31854
31933
|
}
|
|
31855
31934
|
async function readUploadOrFetch(storageKey) {
|
|
31856
31935
|
const safe = storageKey.replace(/[/\\]/g, "");
|
|
31857
|
-
const target2 =
|
|
31936
|
+
const target2 = join16(uploadDir(), safe);
|
|
31858
31937
|
try {
|
|
31859
31938
|
return await readFile2(target2);
|
|
31860
31939
|
} catch {
|
|
@@ -31881,7 +31960,7 @@ async function readUploadOrFetch(storageKey) {
|
|
|
31881
31960
|
}
|
|
31882
31961
|
async function deleteUpload(storageKey) {
|
|
31883
31962
|
const safe = storageKey.replace(/[/\\]/g, "");
|
|
31884
|
-
await unlink2(
|
|
31963
|
+
await unlink2(join16(uploadDir(), safe)).catch(() => {
|
|
31885
31964
|
});
|
|
31886
31965
|
}
|
|
31887
31966
|
|
|
@@ -32034,10 +32113,10 @@ init_config2();
|
|
|
32034
32113
|
init_src2();
|
|
32035
32114
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
32036
32115
|
import { mkdir as mkdir3, writeFile as writeFile2, readFile as readFile3, unlink as unlink3 } from "node:fs/promises";
|
|
32037
|
-
import { join as
|
|
32116
|
+
import { join as join17, resolve as resolve17, basename as basename4 } from "node:path";
|
|
32038
32117
|
var MAX_TRANSCRIPT_BYTES = 1024 * 1024;
|
|
32039
32118
|
function transcriptDir() {
|
|
32040
|
-
return resolve17(effectiveStr("HANOMAN_TRANSCRIPT_DIR") ??
|
|
32119
|
+
return resolve17(effectiveStr("HANOMAN_TRANSCRIPT_DIR") ?? join17(resolveHome(), "transcripts"));
|
|
32041
32120
|
}
|
|
32042
32121
|
function clamp(text) {
|
|
32043
32122
|
const buf = Buffer.from(text, "utf8");
|
|
@@ -32055,20 +32134,20 @@ async function saveTranscript(text) {
|
|
|
32055
32134
|
const dir2 = transcriptDir();
|
|
32056
32135
|
await mkdir3(dir2, { recursive: true, mode: 448 });
|
|
32057
32136
|
const key = `${randomUUID4()}.log`;
|
|
32058
|
-
await writeFile2(
|
|
32137
|
+
await writeFile2(join17(dir2, key), body, { encoding: "utf8", mode: 384 });
|
|
32059
32138
|
return { key, bytes: Buffer.byteLength(body, "utf8"), truncated };
|
|
32060
32139
|
}
|
|
32061
32140
|
async function readTranscript(key) {
|
|
32062
32141
|
if (!key) return null;
|
|
32063
32142
|
try {
|
|
32064
|
-
return await readFile3(
|
|
32143
|
+
return await readFile3(join17(transcriptDir(), basename4(key)), "utf8");
|
|
32065
32144
|
} catch {
|
|
32066
32145
|
return null;
|
|
32067
32146
|
}
|
|
32068
32147
|
}
|
|
32069
32148
|
async function deleteTranscript(key) {
|
|
32070
32149
|
if (!key) return;
|
|
32071
|
-
await unlink3(
|
|
32150
|
+
await unlink3(join17(transcriptDir(), basename4(key))).catch(() => {
|
|
32072
32151
|
});
|
|
32073
32152
|
}
|
|
32074
32153
|
|
|
@@ -32354,7 +32433,7 @@ init_db();
|
|
|
32354
32433
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
32355
32434
|
import { spawn as spawn4 } from "node:child_process";
|
|
32356
32435
|
import { mkdir as mkdir4, rename as rename2, unlink as unlink4, writeFile as writeFile3 } from "node:fs/promises";
|
|
32357
|
-
import { basename as basename5, isAbsolute as isAbsolute4, join as
|
|
32436
|
+
import { basename as basename5, isAbsolute as isAbsolute4, join as join18 } from "node:path";
|
|
32358
32437
|
|
|
32359
32438
|
// ../node_modules/.pnpm/strtok3@10.3.5/node_modules/strtok3/lib/stream/Errors.js
|
|
32360
32439
|
var defaultMessages = "End-Of-Stream";
|
|
@@ -36280,7 +36359,7 @@ var is_default = {
|
|
|
36280
36359
|
|
|
36281
36360
|
// ../node_modules/.pnpm/sharp@0.35.3_@types+node@20.19.43/node_modules/sharp/dist/sharp.mjs
|
|
36282
36361
|
var import_detect_libc2 = __toESM(require_detect_libc(), 1);
|
|
36283
|
-
import { createRequire } from "node:module";
|
|
36362
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
36284
36363
|
|
|
36285
36364
|
// ../node_modules/.pnpm/sharp@0.35.3_@types+node@20.19.43/node_modules/sharp/dist/libvips.mjs
|
|
36286
36365
|
var import_semver = __toESM(require_semver2(), 1);
|
|
@@ -36704,7 +36783,7 @@ var libvips_default = {
|
|
|
36704
36783
|
};
|
|
36705
36784
|
|
|
36706
36785
|
// ../node_modules/.pnpm/sharp@0.35.3_@types+node@20.19.43/node_modules/sharp/dist/sharp.mjs
|
|
36707
|
-
var require2 =
|
|
36786
|
+
var require2 = createRequire2(import.meta.url);
|
|
36708
36787
|
var { version } = package_default;
|
|
36709
36788
|
var { runtimePlatformArch: runtimePlatformArch2, isUnsupportedNodeRuntime: isUnsupportedNodeRuntime2, prebuiltPlatforms: prebuiltPlatforms2, minimumLibvipsVersion: minimumLibvipsVersion2 } = libvips_default;
|
|
36710
36789
|
var runtimePlatform = runtimePlatformArch2();
|
|
@@ -39585,9 +39664,9 @@ var output_default = (Sharp2) => {
|
|
|
39585
39664
|
// ../node_modules/.pnpm/sharp@0.35.3_@types+node@20.19.43/node_modules/sharp/dist/utility.mjs
|
|
39586
39665
|
var import_detect_libc3 = __toESM(require_detect_libc(), 1);
|
|
39587
39666
|
import events from "node:events";
|
|
39588
|
-
import { createRequire as
|
|
39667
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
39589
39668
|
import { availableParallelism } from "node:os";
|
|
39590
|
-
var require3 =
|
|
39669
|
+
var require3 = createRequire3(import.meta.url);
|
|
39591
39670
|
var runtimePlatform2 = libvips_default.runtimePlatformArch();
|
|
39592
39671
|
var libvipsVersion = sharp_default.libvipsVersion();
|
|
39593
39672
|
var format = sharp_default.format();
|
|
@@ -39817,10 +39896,10 @@ async function processUpload(input, deps = {}) {
|
|
|
39817
39896
|
if (usage2.project + normalized.byteLength > UPLOAD_LIMITS.projectBytes || usage2.global + normalized.byteLength > UPLOAD_LIMITS.globalBytes)
|
|
39818
39897
|
throw new UploadError("UPLOAD_QUOTA", "storage quota exceeded");
|
|
39819
39898
|
const storageDir = deps.storageDir ?? uploadDir();
|
|
39820
|
-
const quarantineDir =
|
|
39899
|
+
const quarantineDir = join18(storageDir, ".quarantine");
|
|
39821
39900
|
await mkdir4(quarantineDir, { recursive: true, mode: 448 });
|
|
39822
39901
|
await mkdir4(storageDir, { recursive: true, mode: 448 });
|
|
39823
|
-
const quarantine =
|
|
39902
|
+
const quarantine = join18(quarantineDir, `${randomUUID6()}.upload`);
|
|
39824
39903
|
const storageKey = `${randomUUID6()}${type.extension}`;
|
|
39825
39904
|
await writeFile3(quarantine, normalized, { mode: 384, flag: "wx" });
|
|
39826
39905
|
try {
|
|
@@ -39828,7 +39907,7 @@ async function processUpload(input, deps = {}) {
|
|
|
39828
39907
|
const finalUsage = await (deps.usage ?? defaultUsage)(input.projectId);
|
|
39829
39908
|
if (finalUsage.project + normalized.byteLength > UPLOAD_LIMITS.projectBytes || finalUsage.global + normalized.byteLength > UPLOAD_LIMITS.globalBytes)
|
|
39830
39909
|
throw new UploadError("UPLOAD_QUOTA", "storage quota exceeded");
|
|
39831
|
-
await rename2(quarantine,
|
|
39910
|
+
await rename2(quarantine, join18(storageDir, storageKey));
|
|
39832
39911
|
} catch (error) {
|
|
39833
39912
|
await unlink4(quarantine).catch(() => {
|
|
39834
39913
|
});
|
|
@@ -40753,7 +40832,7 @@ function leadPrompt(q, c) {
|
|
|
40753
40832
|
|
|
40754
40833
|
// src/services/lead/verdict.ts
|
|
40755
40834
|
init_src();
|
|
40756
|
-
import { existsSync as
|
|
40835
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
40757
40836
|
import { isAbsolute as isAbsolute5, resolve as resolvePath, relative as relative2 } from "node:path";
|
|
40758
40837
|
function extractJsonBlock(raw2) {
|
|
40759
40838
|
const re = /```json\s*\n([\s\S]*?)```/g;
|
|
@@ -40791,7 +40870,7 @@ function keepExistingRefs(refs2, repoDir) {
|
|
|
40791
40870
|
const full = resolvePath(repoDir, ref);
|
|
40792
40871
|
const rel = relative2(repoDir, full);
|
|
40793
40872
|
if (rel.startsWith("..")) continue;
|
|
40794
|
-
if (
|
|
40873
|
+
if (existsSync14(full)) out3.push(ref);
|
|
40795
40874
|
}
|
|
40796
40875
|
return [...new Set(out3)];
|
|
40797
40876
|
}
|
|
@@ -40946,7 +41025,7 @@ import { execFile as execFile10 } from "node:child_process";
|
|
|
40946
41025
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
40947
41026
|
import { mkdirSync as mkdirSync9, rmSync as rmSync5, writeFileSync as writeFileSync5 } from "node:fs";
|
|
40948
41027
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
40949
|
-
import { join as
|
|
41028
|
+
import { join as join19 } from "node:path";
|
|
40950
41029
|
var binFor = (agent) => agent === "codex" ? effectiveStr("HANOMAN_CODEX_BIN") ?? "codex" : effectiveStr("HANOMAN_CLAUDE_BIN") ?? "claude";
|
|
40951
41030
|
function leadArgv(o) {
|
|
40952
41031
|
if (o.agent === "codex") {
|
|
@@ -40974,11 +41053,11 @@ function leadProcess(prompt, o, env = process.env) {
|
|
|
40974
41053
|
const mode = env.HANOMAN_SESSION_SANDBOX ?? (env.NODE_ENV === "production" ? "required" : "off");
|
|
40975
41054
|
if (mode === "off") return { file, args: directArgs, cwd: o.cwd, cleanup: () => {
|
|
40976
41055
|
} };
|
|
40977
|
-
const promptDir =
|
|
41056
|
+
const promptDir = join19(tmpdir4(), "hanoman-prompts");
|
|
40978
41057
|
mkdirSync9(promptDir, { recursive: true, mode: 448 });
|
|
40979
|
-
const promptFile =
|
|
41058
|
+
const promptFile = join19(promptDir, `oneshot-${randomUUID7()}`);
|
|
40980
41059
|
writeFileSync5(promptFile, prompt, { flag: "wx", mode: 384 });
|
|
40981
|
-
const workspace = o.cwd ??
|
|
41060
|
+
const workspace = o.cwd ?? join19(tmpdir4(), `hanoman-oneshot-${randomUUID7()}`);
|
|
40982
41061
|
if (!o.cwd) mkdirSync9(workspace, { recursive: false, mode: 448 });
|
|
40983
41062
|
try {
|
|
40984
41063
|
const argsWithoutPrompt = directArgs.slice(0, -1);
|
|
@@ -42433,7 +42512,7 @@ init_db();
|
|
|
42433
42512
|
init_db();
|
|
42434
42513
|
import { execFile as execFile11 } from "node:child_process";
|
|
42435
42514
|
import { promisify as promisify11 } from "node:util";
|
|
42436
|
-
import { existsSync as
|
|
42515
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
42437
42516
|
|
|
42438
42517
|
// src/services/changelog/scrub.ts
|
|
42439
42518
|
var MERGE = /^merge\s+(branch|pull request|remote-tracking branch|tag)\b/i;
|
|
@@ -42500,7 +42579,7 @@ var US2 = "";
|
|
|
42500
42579
|
var RS = "";
|
|
42501
42580
|
var NO_REPO = "project ini belum ditautkan ke repo di mesin ini";
|
|
42502
42581
|
var NO_TAG = "repo project ini belum punya tag rilis";
|
|
42503
|
-
var usable = (repoDir) => !!repoDir &&
|
|
42582
|
+
var usable = (repoDir) => !!repoDir && existsSync15(repoDir);
|
|
42504
42583
|
async function listTags(repoDir) {
|
|
42505
42584
|
if (!usable(repoDir)) return { tags: [], head: null, reason: NO_REPO };
|
|
42506
42585
|
try {
|
|
@@ -42763,7 +42842,7 @@ init_db();
|
|
|
42763
42842
|
init_src();
|
|
42764
42843
|
import { readFileSync as readFileSync13 } from "node:fs";
|
|
42765
42844
|
import { homedir as homedir9 } from "node:os";
|
|
42766
|
-
import { join as
|
|
42845
|
+
import { join as join20 } from "node:path";
|
|
42767
42846
|
var home = () => process.env.HOME || homedir9();
|
|
42768
42847
|
var readJson2 = (path2) => {
|
|
42769
42848
|
try {
|
|
@@ -42780,7 +42859,7 @@ var serversOf = (node) => {
|
|
|
42780
42859
|
var codexServers = () => {
|
|
42781
42860
|
let text;
|
|
42782
42861
|
try {
|
|
42783
|
-
text = readFileSync13(
|
|
42862
|
+
text = readFileSync13(join20(home(), ".codex", "config.toml"), "utf8");
|
|
42784
42863
|
} catch {
|
|
42785
42864
|
return [];
|
|
42786
42865
|
}
|
|
@@ -42793,12 +42872,12 @@ var codexServers = () => {
|
|
|
42793
42872
|
};
|
|
42794
42873
|
function mcpServerNames(repoDir) {
|
|
42795
42874
|
const names = [];
|
|
42796
|
-
const claudeJson = readJson2(
|
|
42875
|
+
const claudeJson = readJson2(join20(home(), ".claude.json"));
|
|
42797
42876
|
names.push(...serversOf(claudeJson));
|
|
42798
42877
|
if (repoDir) {
|
|
42799
42878
|
const projects = claudeJson?.projects;
|
|
42800
42879
|
if (projects && typeof projects === "object") names.push(...serversOf(projects[repoDir]));
|
|
42801
|
-
names.push(...serversOf(readJson2(
|
|
42880
|
+
names.push(...serversOf(readJson2(join20(repoDir, ".mcp.json"))));
|
|
42802
42881
|
}
|
|
42803
42882
|
names.push(...codexServers());
|
|
42804
42883
|
return [...new Set(names.filter(Boolean))].sort((a, b) => a.localeCompare(b));
|
|
@@ -44252,13 +44331,13 @@ init_db();
|
|
|
44252
44331
|
// src/services/bootstrap.ts
|
|
44253
44332
|
import { createHash as createHash9, randomBytes as randomBytes9, timingSafeEqual as timingSafeEqual3 } from "node:crypto";
|
|
44254
44333
|
import { chmod, lstat as lstat2, mkdir as mkdir5, readFile as readFile4, unlink as unlink5, writeFile as writeFile4 } from "node:fs/promises";
|
|
44255
|
-
import { join as
|
|
44334
|
+
import { join as join21 } from "node:path";
|
|
44256
44335
|
var TTL_MS5 = 15 * 6e4;
|
|
44257
44336
|
var SETUP_TOKEN_FILE = "setup.token";
|
|
44258
44337
|
var BootstrapError = class extends Error {
|
|
44259
44338
|
code = "BOOTSTRAP_PROOF";
|
|
44260
44339
|
};
|
|
44261
|
-
var tokenPath = (home3) =>
|
|
44340
|
+
var tokenPath = (home3) => join21(home3, SETUP_TOKEN_FILE);
|
|
44262
44341
|
async function readStored(home3) {
|
|
44263
44342
|
try {
|
|
44264
44343
|
const info = await lstat2(tokenPath(home3));
|
|
@@ -44693,7 +44772,7 @@ var PUBLIC = /* @__PURE__ */ new Set([
|
|
|
44693
44772
|
"GET /api/agent-integration.md"
|
|
44694
44773
|
]);
|
|
44695
44774
|
function buildApp({ requireAuth = true, agentDocFile, env = process.env } = {}) {
|
|
44696
|
-
const docFile = agentDocFile !== void 0 ? agentDocFile : pickGuideFile(
|
|
44775
|
+
const docFile = agentDocFile !== void 0 ? agentDocFile : pickGuideFile(dirname13(fileURLToPath4(import.meta.url)), env, existsSync16);
|
|
44697
44776
|
const ingress = loadIngressPolicy(env);
|
|
44698
44777
|
const app2 = Fastify({ logger: false, trustProxy: trustProxyFromEnv(env) });
|
|
44699
44778
|
app2.addHook("onRequest", async (req, reply) => {
|
|
@@ -44791,7 +44870,7 @@ function buildApp({ requireAuth = true, agentDocFile, env = process.env } = {})
|
|
|
44791
44870
|
await api.register(client_accounts_default);
|
|
44792
44871
|
}, { prefix: "/api" });
|
|
44793
44872
|
if (shouldServeWeb(env)) {
|
|
44794
|
-
const dist = pickWebDir(
|
|
44873
|
+
const dist = pickWebDir(dirname13(fileURLToPath4(import.meta.url)), env, existsSync16);
|
|
44795
44874
|
if (dist) {
|
|
44796
44875
|
app2.register(fastifyStatic, { root: dist });
|
|
44797
44876
|
app2.setNotFoundHandler((req, reply) => req.url.startsWith("/api") ? reply.code(404).send({ error: "not found" }) : reply.sendFile("index.html"));
|