hanoman 0.9.31 → 0.9.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-info.json +3 -3
- package/dist/cli.js +50 -24
- package/dist/server.js +148 -101
- package/package.json +1 -1
package/dist/build-info.json
CHANGED
package/dist/cli.js
CHANGED
|
@@ -6783,7 +6783,11 @@ var init_session_admission = __esm({
|
|
|
6783
6783
|
});
|
|
6784
6784
|
|
|
6785
6785
|
// ../shared/src/dto.ts
|
|
6786
|
-
|
|
6786
|
+
function parseExitIntent(text) {
|
|
6787
|
+
const m = /^(\d+) (\d+)\s*$/.exec(text ?? "");
|
|
6788
|
+
return m ? { pid: Number(m[1]), code: Number(m[2]) } : null;
|
|
6789
|
+
}
|
|
6790
|
+
var zIssueDeviceToken, zSessionResult, zSessionHistory, zCreateProject, zProjectId, zRenameProject, zUpdateProject, zCreateSpec, zPatchSpec, zChangeSpecSource, zMarkSpecDone, zMarkSpecReviewed, zIntegrate, zSessionSummary, zProjectView, zSchedulerQueueItem, zSchedulerSourceView, zSchedulerSessionView, zSchedulerQueueCounts, zSchedulerState, zLeadDecisionView, zLeadFlowView, zLeadAnswer, zLeadProjectStatus, zLeadStatusView, zFlow, zPrdBrief, zPrdDoc, zBreakdownItem, zBreakdownDoc, zBatchCreateSpec, zEscalationTarget, zEscalationPrefill, zAuditEscalation, zAuditEscalationView, zTerminalSession, zDocFileContent, zDocIndexCat, zDocIndex, HOST_RE, USER_RE, zCreateVps, zPatchVps, USER_ROLES, zUserRole, zLogin, zSignup, zSetup, zSetupApply, zChangePassword, zAdminPasswordReset, zCreateClientAccount, zUpdateClientAccount, zVpsCheck, zMarkNa, zMarkNaBulk, zAttest, zRemediate, PROVISION_PROFILES, COMPONENT_IDS, zProvision, UPDATE_RESTART_EXIT, CONFIG_RESTART_EXIT, MANUAL_RESTART_EXIT, EXIT_INTENT_FILE, zUpdateApplyBody, MAX_SUBS, zSubPage, zSubLimit, zTopicParams, zEventsClientMsg, zTicketView, zTicketAttachmentView, zSpecAttachmentView, zTicketDetail, zTicketEditInput, zHelpInfo, zPublicTicketStatus, zCronExpr, zCreateCron, zPatchCron, zSchedulerCron, zSchedulerCronRun;
|
|
6787
6791
|
var init_dto = __esm({
|
|
6788
6792
|
"../shared/src/dto.ts"() {
|
|
6789
6793
|
"use strict";
|
|
@@ -7317,6 +7321,7 @@ var init_dto = __esm({
|
|
|
7317
7321
|
UPDATE_RESTART_EXIT = 75;
|
|
7318
7322
|
CONFIG_RESTART_EXIT = 76;
|
|
7319
7323
|
MANUAL_RESTART_EXIT = 77;
|
|
7324
|
+
EXIT_INTENT_FILE = "exit-intent";
|
|
7320
7325
|
zUpdateApplyBody = external_exports.object({ confirm: external_exports.boolean().optional() });
|
|
7321
7326
|
MAX_SUBS = 16;
|
|
7322
7327
|
zSubPage = external_exports.number().int().min(1).max(1e4);
|
|
@@ -16187,13 +16192,14 @@ __export(start_exports, {
|
|
|
16187
16192
|
parseStartArgs: () => parseStartArgs,
|
|
16188
16193
|
planSupervisorStep: () => planSupervisorStep,
|
|
16189
16194
|
prismaClientUsable: () => prismaClientUsable,
|
|
16195
|
+
resolveChildExit: () => resolveChildExit,
|
|
16190
16196
|
serverEnv: () => serverEnv,
|
|
16191
16197
|
spawnEnv: () => spawnEnv
|
|
16192
16198
|
});
|
|
16193
16199
|
import { spawn, execFileSync as execFileSync3 } from "node:child_process";
|
|
16194
16200
|
import { createRequire as createRequire2 } from "node:module";
|
|
16195
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync2, chmodSync as chmodSync3 } from "node:fs";
|
|
16196
|
-
import { dirname as dirname4, resolve as resolvePath } from "node:path";
|
|
16201
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, chmodSync as chmodSync3, readFileSync as readFileSync3, rmSync } from "node:fs";
|
|
16202
|
+
import { dirname as dirname4, join as join6, resolve as resolvePath } from "node:path";
|
|
16197
16203
|
import { fileURLToPath } from "node:url";
|
|
16198
16204
|
function parseStartArgs(argv) {
|
|
16199
16205
|
const out = { port: null, host: null, db: null, migrate: true };
|
|
@@ -16318,6 +16324,23 @@ function installLatest() {
|
|
|
16318
16324
|
function spawnEnv(fileEnv, processEnv, server) {
|
|
16319
16325
|
return { ...fileEnv, ...processEnv, ...server };
|
|
16320
16326
|
}
|
|
16327
|
+
function resolveChildExit(exit, intentText) {
|
|
16328
|
+
const intent = parseExitIntent(intentText);
|
|
16329
|
+
if (exit.signal === "SIGKILL" && intent && exit.pid !== void 0 && intent.pid === exit.pid) {
|
|
16330
|
+
return { code: intent.code, forced: true };
|
|
16331
|
+
}
|
|
16332
|
+
return { code: exit.code ?? 0, forced: false };
|
|
16333
|
+
}
|
|
16334
|
+
function takeExitIntent(home) {
|
|
16335
|
+
const path = join6(home, EXIT_INTENT_FILE);
|
|
16336
|
+
try {
|
|
16337
|
+
const text = readFileSync3(path, "utf8");
|
|
16338
|
+
rmSync(path, { force: true });
|
|
16339
|
+
return text;
|
|
16340
|
+
} catch {
|
|
16341
|
+
return null;
|
|
16342
|
+
}
|
|
16343
|
+
}
|
|
16321
16344
|
function runServer(serverJs, env, fileEnv) {
|
|
16322
16345
|
const child = spawn(process.execPath, [serverJs], {
|
|
16323
16346
|
stdio: "inherit",
|
|
@@ -16325,9 +16348,9 @@ function runServer(serverJs, env, fileEnv) {
|
|
|
16325
16348
|
});
|
|
16326
16349
|
const handlers = ["SIGINT", "SIGTERM"].map((sig) => [sig, () => child.kill(sig)]);
|
|
16327
16350
|
for (const [sig, h] of handlers) process.on(sig, h);
|
|
16328
|
-
return new Promise((res) => child.on("exit", (code) => {
|
|
16351
|
+
return new Promise((res) => child.on("exit", (code, signal) => {
|
|
16329
16352
|
for (const [sig, h] of handlers) process.off(sig, h);
|
|
16330
|
-
res(code
|
|
16353
|
+
res({ code, signal, pid: child.pid });
|
|
16331
16354
|
}));
|
|
16332
16355
|
}
|
|
16333
16356
|
async function start(argv, ctx) {
|
|
@@ -16386,7 +16409,10 @@ ${hint}
|
|
|
16386
16409
|
let restartsUsed = 0;
|
|
16387
16410
|
let configRestartsUsed = 0;
|
|
16388
16411
|
for (; ; ) {
|
|
16389
|
-
const
|
|
16412
|
+
const exit = await runServer(layout.server, env, readConfigEnv(home));
|
|
16413
|
+
const { code, forced } = resolveChildExit(exit, takeExitIntent(home));
|
|
16414
|
+
if (forced) ctx.stderr(`hanoman: server macet saat keluar \u2014 dihentikan watchdog; dilanjutkan sebagai exit ${code} (ADR-0227)
|
|
16415
|
+
`);
|
|
16390
16416
|
const step = planSupervisorStep(code, restartsUsed, configRestartsUsed);
|
|
16391
16417
|
if (step.action === "exit") {
|
|
16392
16418
|
if (code === UPDATE_RESTART_EXIT) {
|
|
@@ -37833,7 +37859,7 @@ __export(mcp_exports, {
|
|
|
37833
37859
|
agentTokenPath: () => agentTokenPath,
|
|
37834
37860
|
default: () => mcp
|
|
37835
37861
|
});
|
|
37836
|
-
import { readFileSync as
|
|
37862
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
37837
37863
|
import { join as join8 } from "node:path";
|
|
37838
37864
|
async function mcp(argv, ctx) {
|
|
37839
37865
|
const cfg = resolveMcpConfig(argv, ctx.env, () => tokenFile(ctx.env));
|
|
@@ -37868,7 +37894,7 @@ var init_mcp2 = __esm({
|
|
|
37868
37894
|
agentTokenPath = (env) => join8(resolveHome(env), "agent-token");
|
|
37869
37895
|
tokenFile = (env) => {
|
|
37870
37896
|
try {
|
|
37871
|
-
return
|
|
37897
|
+
return readFileSync4(agentTokenPath(env), "utf8");
|
|
37872
37898
|
} catch {
|
|
37873
37899
|
return null;
|
|
37874
37900
|
}
|
|
@@ -38209,11 +38235,11 @@ var init_migrate_pg = __esm({
|
|
|
38209
38235
|
});
|
|
38210
38236
|
|
|
38211
38237
|
// src/config.ts
|
|
38212
|
-
import { readFileSync as
|
|
38238
|
+
import { readFileSync as readFileSync5, existsSync as existsSync7 } from "node:fs";
|
|
38213
38239
|
import { join as join10 } from "node:path";
|
|
38214
38240
|
function loadConfig(repoRoot) {
|
|
38215
38241
|
const p3 = join10(repoRoot, "hanoman.config.json");
|
|
38216
|
-
const raw = existsSync7(p3) ? JSON.parse(
|
|
38242
|
+
const raw = existsSync7(p3) ? JSON.parse(readFileSync5(p3, "utf8")) : {};
|
|
38217
38243
|
return zHanomanConfig.parse(raw);
|
|
38218
38244
|
}
|
|
38219
38245
|
var init_config3 = __esm({
|
|
@@ -38240,10 +38266,10 @@ var init_repo = __esm({
|
|
|
38240
38266
|
});
|
|
38241
38267
|
|
|
38242
38268
|
// src/docs-model.ts
|
|
38243
|
-
import { readFileSync as
|
|
38269
|
+
import { readFileSync as readFileSync6, readdirSync as readdirSync3, statSync as statSync2 } from "node:fs";
|
|
38244
38270
|
import { join as join12, relative as relative2 } from "node:path";
|
|
38245
38271
|
function parseIndex(indexPath) {
|
|
38246
|
-
const md =
|
|
38272
|
+
const md = readFileSync6(indexPath, "utf8");
|
|
38247
38273
|
const out = /* @__PURE__ */ new Set();
|
|
38248
38274
|
for (const m of md.matchAll(LINK_RE2)) {
|
|
38249
38275
|
let t = m[1].trim();
|
|
@@ -38291,7 +38317,7 @@ var init_docs_model = __esm({
|
|
|
38291
38317
|
|
|
38292
38318
|
// src/verify.ts
|
|
38293
38319
|
import { join as join13 } from "node:path";
|
|
38294
|
-
import { existsSync as existsSync8, readFileSync as
|
|
38320
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7 } from "node:fs";
|
|
38295
38321
|
function scanCoverage(cwd) {
|
|
38296
38322
|
const { root, docsDir, indexPath } = resolveRepo(cwd);
|
|
38297
38323
|
const docsRoot = join13(root, docsDir);
|
|
@@ -38300,7 +38326,7 @@ function scanCoverage(cwd) {
|
|
|
38300
38326
|
const corpus = walkDocs(docsRoot);
|
|
38301
38327
|
const read = (rel) => {
|
|
38302
38328
|
try {
|
|
38303
|
-
return
|
|
38329
|
+
return readFileSync7(join13(docsRoot, rel), "utf8");
|
|
38304
38330
|
} catch {
|
|
38305
38331
|
return null;
|
|
38306
38332
|
}
|
|
@@ -38343,9 +38369,9 @@ var init_docs_scan = __esm({
|
|
|
38343
38369
|
});
|
|
38344
38370
|
|
|
38345
38371
|
// src/index-edit.ts
|
|
38346
|
-
import { readFileSync as
|
|
38372
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync2 } from "node:fs";
|
|
38347
38373
|
function addLink(indexPath, relPath, category) {
|
|
38348
|
-
let md =
|
|
38374
|
+
let md = readFileSync8(indexPath, "utf8");
|
|
38349
38375
|
if (md.includes(`(${relPath})`)) return;
|
|
38350
38376
|
const base2 = relPath.split("/").pop().replace(/\.md$/, "");
|
|
38351
38377
|
const line = `- [${base2}](${relPath})`;
|
|
@@ -38375,7 +38401,7 @@ __export(docs_index_exports, {
|
|
|
38375
38401
|
});
|
|
38376
38402
|
import { parseArgs as parseArgs2 } from "node:util";
|
|
38377
38403
|
import { join as join14 } from "node:path";
|
|
38378
|
-
import { existsSync as existsSync9, readFileSync as
|
|
38404
|
+
import { existsSync as existsSync9, readFileSync as readFileSync9 } from "node:fs";
|
|
38379
38405
|
async function docs_index_default(args, ctx) {
|
|
38380
38406
|
const { values } = parseArgs2({ args, options: { check: { type: "boolean" }, fix: { type: "boolean" } }, allowPositionals: true });
|
|
38381
38407
|
const { root, docsDir, indexPath } = resolveRepo(ctx.cwd);
|
|
@@ -38383,7 +38409,7 @@ async function docs_index_default(args, ctx) {
|
|
|
38383
38409
|
const corpus = walkDocs(docsRoot);
|
|
38384
38410
|
const read = (rel) => {
|
|
38385
38411
|
try {
|
|
38386
|
-
return
|
|
38412
|
+
return readFileSync9(join14(docsRoot, rel), "utf8");
|
|
38387
38413
|
} catch {
|
|
38388
38414
|
return null;
|
|
38389
38415
|
}
|
|
@@ -38548,10 +38574,10 @@ var pack_exports = {};
|
|
|
38548
38574
|
__export(pack_exports, {
|
|
38549
38575
|
default: () => pack
|
|
38550
38576
|
});
|
|
38551
|
-
import { cpSync, existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as
|
|
38577
|
+
import { cpSync, existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync10, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
38552
38578
|
import { dirname as dirname8, join as join16 } from "node:path";
|
|
38553
38579
|
function depVersions(repo) {
|
|
38554
|
-
const read = (p3) => JSON.parse(
|
|
38580
|
+
const read = (p3) => JSON.parse(readFileSync10(join16(repo, p3), "utf8"));
|
|
38555
38581
|
const server = read("server/package.json"), cli = read("cli/package.json");
|
|
38556
38582
|
const pools = [server.dependencies, server.devDependencies, cli.dependencies, cli.devDependencies];
|
|
38557
38583
|
const out = {};
|
|
@@ -38577,7 +38603,7 @@ async function pack(argv, ctx) {
|
|
|
38577
38603
|
}
|
|
38578
38604
|
const outIdx = argv.indexOf("--out");
|
|
38579
38605
|
const out = outIdx === -1 ? join16(repo, "dist-npm") : join16(repo, argv[outIdx + 1] ?? "dist-npm");
|
|
38580
|
-
const version2 = JSON.parse(
|
|
38606
|
+
const version2 = JSON.parse(readFileSync10(join16(repo, "package.json"), "utf8")).version;
|
|
38581
38607
|
if (!version2) {
|
|
38582
38608
|
ctx.stderr("pack: root package.json tanpa field version\n");
|
|
38583
38609
|
return 1;
|
|
@@ -38590,7 +38616,7 @@ async function pack(argv, ctx) {
|
|
|
38590
38616
|
`);
|
|
38591
38617
|
return 1;
|
|
38592
38618
|
}
|
|
38593
|
-
|
|
38619
|
+
rmSync2(out, { recursive: true, force: true });
|
|
38594
38620
|
mkdirSync3(join16(out, "bin"), { recursive: true });
|
|
38595
38621
|
for (const item of copyPlan(repo)) {
|
|
38596
38622
|
if (!existsSync10(item.from)) {
|
|
@@ -38629,13 +38655,13 @@ var verify_packed_exports = {};
|
|
|
38629
38655
|
__export(verify_packed_exports, {
|
|
38630
38656
|
default: () => verifyPacked
|
|
38631
38657
|
});
|
|
38632
|
-
import { readFileSync as
|
|
38658
|
+
import { readFileSync as readFileSync11 } from "node:fs";
|
|
38633
38659
|
import { join as join17 } from "node:path";
|
|
38634
38660
|
function verifyPacked(_argv, ctx) {
|
|
38635
38661
|
const path = join17(process.cwd(), "package.json");
|
|
38636
38662
|
let pkg;
|
|
38637
38663
|
try {
|
|
38638
|
-
pkg = JSON.parse(
|
|
38664
|
+
pkg = JSON.parse(readFileSync11(path, "utf8"));
|
|
38639
38665
|
} catch {
|
|
38640
38666
|
ctx.stderr(`verify: tak bisa membaca ${path}
|
|
38641
38667
|
`);
|
package/dist/server.js
CHANGED
|
@@ -7615,12 +7615,16 @@ var init_session_admission = __esm({
|
|
|
7615
7615
|
function flowForSource(source) {
|
|
7616
7616
|
return source === "qa" ? "qa" : source === "audit" ? "audit" : source === "goal" ? "goal" : source === "no_effort" ? "no_effort" : "feature";
|
|
7617
7617
|
}
|
|
7618
|
+
function formatExitIntent(pid, code) {
|
|
7619
|
+
return `${pid} ${code}
|
|
7620
|
+
`;
|
|
7621
|
+
}
|
|
7618
7622
|
function subKey(topic, params) {
|
|
7619
7623
|
const canon = {};
|
|
7620
7624
|
for (const k of Object.keys(params).sort()) if (params[k] !== void 0) canon[k] = params[k];
|
|
7621
7625
|
return `${topic}|${JSON.stringify(canon)}`;
|
|
7622
7626
|
}
|
|
7623
|
-
var zIssueDeviceToken, zSessionResult, zSessionHistory, zCreateProject, zProjectId, zRenameProject, zUpdateProject, zCreateSpec, zPatchSpec, zChangeSpecSource, zMarkSpecDone, zMarkSpecReviewed, zIntegrate, zSessionSummary, zProjectView, zSchedulerQueueItem, zSchedulerSourceView, zSchedulerSessionView, zSchedulerQueueCounts, zSchedulerState, zLeadDecisionView, zLeadFlowView, zLeadAnswer, zLeadProjectStatus, zLeadStatusView, zFlow, isGoalShapedFlow, zPrdBrief, zPrdDoc, zBreakdownItem, zBreakdownDoc, zBatchCreateSpec, zEscalationTarget, zEscalationPrefill, zAuditEscalation, zAuditEscalationView, zTerminalSession, zDocFileContent, zDocIndexCat, zDocIndex, HOST_RE, USER_RE, zCreateVps, zPatchVps, USER_ROLES, zUserRole, zLogin, zSignup, zSetup, zSetupApply, zChangePassword, zAdminPasswordReset, zCreateClientAccount, zUpdateClientAccount, zVpsCheck, zMarkNa, zMarkNaBulk, zAttest, zRemediate, PROVISION_PROFILES, COMPONENT_IDS, zProvision, UPDATE_RESTART_EXIT, CONFIG_RESTART_EXIT, MANUAL_RESTART_EXIT, zUpdateApplyBody, MAX_SUBS, zSubPage, zSubLimit, zTopicParams, zEventsClientMsg, zTicketView, zTicketAttachmentView, zSpecAttachmentView, zTicketDetail, zTicketEditInput, zHelpInfo, zPublicTicketStatus, zCronExpr, zCreateCron, zPatchCron, zSchedulerCron, zSchedulerCronRun;
|
|
7627
|
+
var zIssueDeviceToken, zSessionResult, zSessionHistory, zCreateProject, zProjectId, zRenameProject, zUpdateProject, zCreateSpec, zPatchSpec, zChangeSpecSource, zMarkSpecDone, zMarkSpecReviewed, zIntegrate, zSessionSummary, zProjectView, zSchedulerQueueItem, zSchedulerSourceView, zSchedulerSessionView, zSchedulerQueueCounts, zSchedulerState, zLeadDecisionView, zLeadFlowView, zLeadAnswer, zLeadProjectStatus, zLeadStatusView, zFlow, isGoalShapedFlow, zPrdBrief, zPrdDoc, zBreakdownItem, zBreakdownDoc, zBatchCreateSpec, zEscalationTarget, zEscalationPrefill, zAuditEscalation, zAuditEscalationView, zTerminalSession, zDocFileContent, zDocIndexCat, zDocIndex, HOST_RE, USER_RE, zCreateVps, zPatchVps, USER_ROLES, zUserRole, zLogin, zSignup, zSetup, zSetupApply, zChangePassword, zAdminPasswordReset, zCreateClientAccount, zUpdateClientAccount, zVpsCheck, zMarkNa, zMarkNaBulk, zAttest, zRemediate, PROVISION_PROFILES, COMPONENT_IDS, zProvision, UPDATE_RESTART_EXIT, CONFIG_RESTART_EXIT, MANUAL_RESTART_EXIT, EXIT_INTENT_FILE, zUpdateApplyBody, MAX_SUBS, zSubPage, zSubLimit, zTopicParams, zEventsClientMsg, zTicketView, zTicketAttachmentView, zSpecAttachmentView, zTicketDetail, zTicketEditInput, zHelpInfo, zPublicTicketStatus, zCronExpr, zCreateCron, zPatchCron, zSchedulerCron, zSchedulerCronRun;
|
|
7624
7628
|
var init_dto = __esm({
|
|
7625
7629
|
"../shared/src/dto.ts"() {
|
|
7626
7630
|
"use strict";
|
|
@@ -8155,6 +8159,7 @@ var init_dto = __esm({
|
|
|
8155
8159
|
UPDATE_RESTART_EXIT = 75;
|
|
8156
8160
|
CONFIG_RESTART_EXIT = 76;
|
|
8157
8161
|
MANUAL_RESTART_EXIT = 77;
|
|
8162
|
+
EXIT_INTENT_FILE = "exit-intent";
|
|
8158
8163
|
zUpdateApplyBody = external_exports.object({ confirm: external_exports.boolean().optional() });
|
|
8159
8164
|
MAX_SUBS = 16;
|
|
8160
8165
|
zSubPage = external_exports.number().int().min(1).max(1e4);
|
|
@@ -56479,6 +56484,45 @@ var init_device_sockets = __esm({
|
|
|
56479
56484
|
}
|
|
56480
56485
|
});
|
|
56481
56486
|
|
|
56487
|
+
// src/services/exit-guard.ts
|
|
56488
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
56489
|
+
import { writeFileSync as writeFileSync15 } from "node:fs";
|
|
56490
|
+
import { join as join29 } from "node:path";
|
|
56491
|
+
function watchdogScript(pid, graceMs) {
|
|
56492
|
+
const secs = Math.max(1, Math.ceil(graceMs / 1e3));
|
|
56493
|
+
return `s=$(ps -o lstart= -p ${pid}); sleep ${secs}; [ -n "$s" ] && [ "$(ps -o lstart= -p ${pid})" = "$s" ] && kill -9 ${pid}`;
|
|
56494
|
+
}
|
|
56495
|
+
function launchWatchdog(script2, env = process.env) {
|
|
56496
|
+
if (env.VITEST) return false;
|
|
56497
|
+
const child = spawn3("/bin/sh", ["-c", script2], { detached: true, stdio: "ignore" });
|
|
56498
|
+
child.on("error", () => {
|
|
56499
|
+
});
|
|
56500
|
+
child.unref();
|
|
56501
|
+
return true;
|
|
56502
|
+
}
|
|
56503
|
+
function exitGuarded(code, d = {}) {
|
|
56504
|
+
const pid = d.pid ?? process.pid;
|
|
56505
|
+
try {
|
|
56506
|
+
const write2 = d.writeIntent ?? ((p3, t) => writeFileSync15(p3, t, { mode: 384 }));
|
|
56507
|
+
write2(join29(d.home ?? resolveHome(), EXIT_INTENT_FILE), formatExitIntent(pid, code));
|
|
56508
|
+
} catch {
|
|
56509
|
+
}
|
|
56510
|
+
try {
|
|
56511
|
+
(d.launch ?? launchWatchdog)(watchdogScript(pid, d.graceMs ?? EXIT_WATCHDOG_MS));
|
|
56512
|
+
} catch {
|
|
56513
|
+
}
|
|
56514
|
+
(d.exit ?? ((c) => process.exit(c)))(code);
|
|
56515
|
+
}
|
|
56516
|
+
var EXIT_WATCHDOG_MS;
|
|
56517
|
+
var init_exit_guard = __esm({
|
|
56518
|
+
"src/services/exit-guard.ts"() {
|
|
56519
|
+
"use strict";
|
|
56520
|
+
init_src();
|
|
56521
|
+
init_src2();
|
|
56522
|
+
EXIT_WATCHDOG_MS = 5e3;
|
|
56523
|
+
}
|
|
56524
|
+
});
|
|
56525
|
+
|
|
56482
56526
|
// src/services/update.ts
|
|
56483
56527
|
import { readFileSync as readFileSync16 } from "node:fs";
|
|
56484
56528
|
import { resolve as resolve20, dirname as dirname13 } from "node:path";
|
|
@@ -56514,7 +56558,7 @@ function supervised() {
|
|
|
56514
56558
|
}
|
|
56515
56559
|
function requestRestartForUpdate() {
|
|
56516
56560
|
const delay2 = effectiveInt("HANOMAN_UPDATE_RESTART_DELAY_MS") ?? 250;
|
|
56517
|
-
setTimeout(() => (exiter ??
|
|
56561
|
+
setTimeout(() => (exiter ?? exitGuarded)(UPDATE_RESTART_EXIT), delay2);
|
|
56518
56562
|
}
|
|
56519
56563
|
async function maybeFetch() {
|
|
56520
56564
|
if (!effectiveBool("HANOMAN_UPDATE_FETCH")) return;
|
|
@@ -56560,6 +56604,7 @@ var init_update = __esm({
|
|
|
56560
56604
|
"use strict";
|
|
56561
56605
|
init_src();
|
|
56562
56606
|
init_config2();
|
|
56607
|
+
init_exit_guard();
|
|
56563
56608
|
UPDATE_COMMAND = "npm i -g hanoman@latest --prefer-online";
|
|
56564
56609
|
RESULT_TTL_MS = 15e3;
|
|
56565
56610
|
FETCH_TTL_MS = 5 * 6e4;
|
|
@@ -62836,15 +62881,15 @@ var init_client2 = __esm({
|
|
|
62836
62881
|
|
|
62837
62882
|
// src/services/logs/spool.ts
|
|
62838
62883
|
import { appendFile, mkdir as mkdir7, readFile as readFile7, readdir as readdir7, rm as rm6, stat as stat6 } from "node:fs/promises";
|
|
62839
|
-
import { join as
|
|
62884
|
+
import { join as join33 } from "node:path";
|
|
62840
62885
|
function spoolDir(lane) {
|
|
62841
|
-
return
|
|
62886
|
+
return join33(resolveDataDirs().home, "log-spool", lane);
|
|
62842
62887
|
}
|
|
62843
62888
|
async function currentSegment(lane) {
|
|
62844
62889
|
const dir2 = spoolDir(lane);
|
|
62845
62890
|
await mkdir7(dir2, { recursive: true, mode: 448 });
|
|
62846
62891
|
if (currentFile && currentBytes < LOG_SPOOL_SEGMENT_BYTES) return currentFile;
|
|
62847
|
-
currentFile =
|
|
62892
|
+
currentFile = join33(dir2, `${Date.now()}-${++segCounter}.ndjson`);
|
|
62848
62893
|
currentBytes = 0;
|
|
62849
62894
|
return currentFile;
|
|
62850
62895
|
}
|
|
@@ -62866,7 +62911,7 @@ async function readSpoolSegments(lane) {
|
|
|
62866
62911
|
const files2 = names.filter((n2) => n2.endsWith(".ndjson")).sort();
|
|
62867
62912
|
const out4 = [];
|
|
62868
62913
|
for (const name2 of files2) {
|
|
62869
|
-
const file =
|
|
62914
|
+
const file = join33(dir2, name2);
|
|
62870
62915
|
const raw = await readFile7(file, "utf8").catch(() => "");
|
|
62871
62916
|
const entries4 = raw.split("\n").filter(Boolean).map((l) => JSON.parse(l));
|
|
62872
62917
|
out4.push({ file, entries: entries4 });
|
|
@@ -63553,15 +63598,15 @@ var init_codex_version = __esm({
|
|
|
63553
63598
|
// src/services/agent-tool-catalog.ts
|
|
63554
63599
|
import { readFileSync as readFileSync26 } from "node:fs";
|
|
63555
63600
|
import { homedir as homedir13 } from "node:os";
|
|
63556
|
-
import { join as
|
|
63601
|
+
import { join as join49 } from "node:path";
|
|
63557
63602
|
function mcpServerNames(repoDir) {
|
|
63558
63603
|
const names = [];
|
|
63559
|
-
const claudeJson = readJson2(
|
|
63604
|
+
const claudeJson = readJson2(join49(home(), ".claude.json"));
|
|
63560
63605
|
names.push(...serversOf(claudeJson));
|
|
63561
63606
|
if (repoDir) {
|
|
63562
63607
|
const projects = claudeJson?.projects;
|
|
63563
63608
|
if (projects && typeof projects === "object") names.push(...serversOf(projects[repoDir]));
|
|
63564
|
-
names.push(...serversOf(readJson2(
|
|
63609
|
+
names.push(...serversOf(readJson2(join49(repoDir, ".mcp.json"))));
|
|
63565
63610
|
}
|
|
63566
63611
|
names.push(...codexServers());
|
|
63567
63612
|
return [...new Set(names.filter(Boolean))].sort((a, b) => a.localeCompare(b));
|
|
@@ -63590,7 +63635,7 @@ var init_agent_tool_catalog = __esm({
|
|
|
63590
63635
|
codexServers = () => {
|
|
63591
63636
|
let text2;
|
|
63592
63637
|
try {
|
|
63593
|
-
text2 = readFileSync26(
|
|
63638
|
+
text2 = readFileSync26(join49(home(), ".codex", "config.toml"), "utf8");
|
|
63594
63639
|
} catch {
|
|
63595
63640
|
return [];
|
|
63596
63641
|
}
|
|
@@ -70533,8 +70578,8 @@ init_local_binding();
|
|
|
70533
70578
|
init_session_id();
|
|
70534
70579
|
init_uploads();
|
|
70535
70580
|
import { mkdir as mkdir6, readdir as readdir5, readFile as readFile6, rm as rm4, writeFile as writeFile5 } from "node:fs/promises";
|
|
70536
|
-
import { join as
|
|
70537
|
-
var specAttachmentsDir = (repoDir, sessionId2) =>
|
|
70581
|
+
import { join as join30 } from "node:path";
|
|
70582
|
+
var specAttachmentsDir = (repoDir, sessionId2) => join30(repoDir, ".worktrees", ".attachments", sessionId2);
|
|
70538
70583
|
var INDEX = "INDEX.md";
|
|
70539
70584
|
var humanSize = (n2) => n2 >= 1024 * 1024 ? `${(n2 / 1024 / 1024).toFixed(1)} MB` : n2 >= 1024 ? `${Math.round(n2 / 1024)} KB` : `${n2} B`;
|
|
70540
70585
|
function uniqueName(taken, filename) {
|
|
@@ -70584,19 +70629,19 @@ async function syncSpecAttachmentsDir(specId, projectId) {
|
|
|
70584
70629
|
for (const a of rows) {
|
|
70585
70630
|
let bytes;
|
|
70586
70631
|
try {
|
|
70587
|
-
bytes = await readFile6(
|
|
70632
|
+
bytes = await readFile6(join30(uploadDir(), a.storageKey));
|
|
70588
70633
|
} catch {
|
|
70589
70634
|
continue;
|
|
70590
70635
|
}
|
|
70591
70636
|
const filename = uniqueName(taken, a.filename);
|
|
70592
|
-
const path =
|
|
70637
|
+
const path = join30(dir2, filename);
|
|
70593
70638
|
await writeFile5(path, bytes, { mode: 384 });
|
|
70594
70639
|
items.push({ filename, mimeType: a.mimeType, size: a.size, path });
|
|
70595
70640
|
}
|
|
70596
|
-
await writeFile5(
|
|
70641
|
+
await writeFile5(join30(dir2, INDEX), renderIndex(specId, items), { mode: 384 });
|
|
70597
70642
|
const keep = /* @__PURE__ */ new Set([INDEX, ...items.map((a) => a.filename)]);
|
|
70598
70643
|
for (const name2 of await readdir5(dir2)) {
|
|
70599
|
-
if (!keep.has(name2)) await rm4(
|
|
70644
|
+
if (!keep.has(name2)) await rm4(join30(dir2, name2), { recursive: true, force: true }).catch(() => {
|
|
70600
70645
|
});
|
|
70601
70646
|
}
|
|
70602
70647
|
return items;
|
|
@@ -74042,7 +74087,7 @@ async function docs_default(app3) {
|
|
|
74042
74087
|
// src/routes/ide.ts
|
|
74043
74088
|
init_src2();
|
|
74044
74089
|
import { basename as basename10 } from "node:path";
|
|
74045
|
-
import { spawn as
|
|
74090
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
74046
74091
|
|
|
74047
74092
|
// src/services/git-remotes.ts
|
|
74048
74093
|
import { execFile as execFile14 } from "node:child_process";
|
|
@@ -74112,7 +74157,7 @@ init_codex_trust();
|
|
|
74112
74157
|
// src/services/repo-fs.ts
|
|
74113
74158
|
import { lstat as lstat2, rename as rename4, rm as rm5 } from "node:fs/promises";
|
|
74114
74159
|
import { createWriteStream } from "node:fs";
|
|
74115
|
-
import { join as
|
|
74160
|
+
import { join as join31 } from "node:path";
|
|
74116
74161
|
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
74117
74162
|
import { pipeline } from "node:stream/promises";
|
|
74118
74163
|
var EntryExistsError = class extends Error {
|
|
@@ -74173,7 +74218,7 @@ async function saveUpload2(repoDir, rel, source, opts2 = {}) {
|
|
|
74173
74218
|
if (current && !opts2.overwrite) return { status: "exists" };
|
|
74174
74219
|
if (current && !current.isFile())
|
|
74175
74220
|
throw new PathContainmentError("repository path ditolak: target bukan file regular");
|
|
74176
|
-
const temp =
|
|
74221
|
+
const temp = join31(entry2.parent, `.hanoman-${randomUUID11()}.tmp`);
|
|
74177
74222
|
try {
|
|
74178
74223
|
await pipeline(source, createWriteStream(temp, { flags: "wx", mode: 384 }));
|
|
74179
74224
|
if (opts2.isTruncated?.()) {
|
|
@@ -74457,7 +74502,7 @@ async function ide_default(app3) {
|
|
|
74457
74502
|
const ref = q2.ref || "HEAD";
|
|
74458
74503
|
if (!/^[\w./@{}-]+$/.test(ref)) return reply.code(400).send({ error: "ref tidak valid" });
|
|
74459
74504
|
const fmt = q2.format === "tar" ? "tar" : "zip";
|
|
74460
|
-
const child =
|
|
74505
|
+
const child = spawn4("git", ["archive", `--format=${fmt}`, "--end-of-options", ref], { cwd: repoDir });
|
|
74461
74506
|
reply.header("content-type", fmt === "zip" ? "application/zip" : "application/x-tar");
|
|
74462
74507
|
reply.header("content-disposition", `attachment; filename="${basename10(repoDir)}-${ref.replace(/[^\w.-]/g, "_")}.${fmt}"`);
|
|
74463
74508
|
return reply.send(child.stdout);
|
|
@@ -74664,14 +74709,14 @@ async function finishGraphOp(reply, id2, repoDir, r, verb) {
|
|
|
74664
74709
|
// src/routes/fs.ts
|
|
74665
74710
|
import { readdir as readdir6 } from "node:fs/promises";
|
|
74666
74711
|
import { homedir as homedir6 } from "node:os";
|
|
74667
|
-
import { resolve as resolve22, dirname as dirname14, join as
|
|
74712
|
+
import { resolve as resolve22, dirname as dirname14, join as join32 } from "node:path";
|
|
74668
74713
|
async function fs_default(app3) {
|
|
74669
74714
|
app3.get("/fs/browse", async (req, reply) => {
|
|
74670
74715
|
const q2 = req.query.path;
|
|
74671
74716
|
const dir2 = q2 && q2.trim() ? resolve22(q2.trim()) : homedir6();
|
|
74672
74717
|
try {
|
|
74673
74718
|
const ents = await readdir6(dir2, { withFileTypes: true });
|
|
74674
|
-
const entries4 = ents.filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => ({ name: e.name, path:
|
|
74719
|
+
const entries4 = ents.filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => ({ name: e.name, path: join32(dir2, e.name) })).sort((a, b) => a.name.localeCompare(b.name));
|
|
74675
74720
|
const parent = dirname14(dir2);
|
|
74676
74721
|
return { path: dir2, parent: parent === dir2 ? null : parent, entries: entries4 };
|
|
74677
74722
|
} catch {
|
|
@@ -74700,11 +74745,11 @@ init_src2();
|
|
|
74700
74745
|
init_db();
|
|
74701
74746
|
import { execFile as execFile15, spawnSync as spawnSync4 } from "node:child_process";
|
|
74702
74747
|
import { existsSync as existsSync16, readdirSync as readdirSync8, rmSync as rmSync9 } from "node:fs";
|
|
74703
|
-
import { join as
|
|
74748
|
+
import { join as join34 } from "node:path";
|
|
74704
74749
|
import { promisify as promisify14 } from "node:util";
|
|
74705
74750
|
|
|
74706
74751
|
// src/services/git-auth.ts
|
|
74707
|
-
import { chmodSync as chmodSync8, mkdirSync as mkdirSync15, writeFileSync as
|
|
74752
|
+
import { chmodSync as chmodSync8, mkdirSync as mkdirSync15, writeFileSync as writeFileSync16 } from "node:fs";
|
|
74708
74753
|
import { tmpdir as tmpdir6 } from "node:os";
|
|
74709
74754
|
import { dirname as dirname15 } from "node:path";
|
|
74710
74755
|
var gitAskpassPath = () => `${tmpdir6()}/hanoman-askpass/token.sh`;
|
|
@@ -74725,7 +74770,7 @@ var isGithubHttps = (remote) => /^https:\/\/github\.com\//.test(remote);
|
|
|
74725
74770
|
function gitAuthEnv(token) {
|
|
74726
74771
|
const path = gitAskpassPath();
|
|
74727
74772
|
mkdirSync15(dirname15(path), { recursive: true, mode: 448 });
|
|
74728
|
-
|
|
74773
|
+
writeFileSync16(path, ASKPASS_TOKEN, { mode: 448 });
|
|
74729
74774
|
chmodSync8(path, 448);
|
|
74730
74775
|
return { GIT_ASKPASS: path, GIT_TERMINAL_PROMPT: "0", HANOMAN_GIT_TOKEN: token };
|
|
74731
74776
|
}
|
|
@@ -74767,7 +74812,7 @@ var CheckoutError = class extends Error {
|
|
|
74767
74812
|
var CLONE_TIMEOUT_MS = 10 * 6e4;
|
|
74768
74813
|
var FETCH_TIMEOUT_MS = 2 * 6e4;
|
|
74769
74814
|
var AUTH_RE = /Authentication failed|could not read (Username|Password)|Invalid username or password|HTTP 40[13]|returned error: 40[13]|Repository not found|Permission denied \(publickey\)/i;
|
|
74770
|
-
var checkoutRoot = () =>
|
|
74815
|
+
var checkoutRoot = () => join34(resolveHome(), "projects");
|
|
74771
74816
|
var slug = (id2) => id2.toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "") || "project";
|
|
74772
74817
|
var sameRemote = (a, b) => {
|
|
74773
74818
|
const norm5 = (u) => httpsRemote(u).replace(/\.git$/, "").replace(/\/+$/, "").toLowerCase();
|
|
@@ -74801,7 +74846,7 @@ async function doClone(projectId, opts2) {
|
|
|
74801
74846
|
if (!project) throw new CheckoutError(`project "${projectId}" tidak ada`, "not-found");
|
|
74802
74847
|
if (!project.gitRemote) throw new CheckoutError(`project "${projectId}" tidak punya gitRemote untuk di-clone`, "no-remote");
|
|
74803
74848
|
const remote = project.gitRemote;
|
|
74804
|
-
const dest = opts2.dir ??
|
|
74849
|
+
const dest = opts2.dir ?? join34(checkoutRoot(), slug(project.id));
|
|
74805
74850
|
if (existsSync16(dest) && !isEmptyDir(dest)) {
|
|
74806
74851
|
const origin = originOf2(dest);
|
|
74807
74852
|
if (origin && sameRemote(origin, remote)) {
|
|
@@ -75385,13 +75430,13 @@ init_local_binding();
|
|
|
75385
75430
|
|
|
75386
75431
|
// src/services/terminal-diag.ts
|
|
75387
75432
|
import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync16, statSync as statSync4, rmSync as rmSync10 } from "node:fs";
|
|
75388
|
-
import { join as
|
|
75433
|
+
import { join as join35 } from "node:path";
|
|
75389
75434
|
var DIAG_MAX_BYTES = 2 * 1024 * 1024;
|
|
75390
75435
|
var KINDS = /* @__PURE__ */ new Set(["key", "comp", "data", "ack", "pred"]);
|
|
75391
75436
|
var ID = /^[A-Za-z0-9_-]{1,64}$/;
|
|
75392
75437
|
function diagFile(home3, sessionId2) {
|
|
75393
75438
|
if (!ID.test(sessionId2)) throw new Error(`id sesi tak sah untuk diag: ${sessionId2}`);
|
|
75394
|
-
return
|
|
75439
|
+
return join35(home3, "diag", `${sessionId2}.jsonl`);
|
|
75395
75440
|
}
|
|
75396
75441
|
function usable(ev) {
|
|
75397
75442
|
if (!ev || typeof ev !== "object") return false;
|
|
@@ -75402,7 +75447,7 @@ function appendDiag(home3, sessionId2, events) {
|
|
|
75402
75447
|
const file = diagFile(home3, sessionId2);
|
|
75403
75448
|
const rows = events.filter(usable);
|
|
75404
75449
|
if (!rows.length) return;
|
|
75405
|
-
mkdirSync16(
|
|
75450
|
+
mkdirSync16(join35(home3, "diag"), { recursive: true });
|
|
75406
75451
|
try {
|
|
75407
75452
|
if (statSync4(file).size > DIAG_MAX_BYTES) rmSync10(file);
|
|
75408
75453
|
} catch {
|
|
@@ -75496,7 +75541,7 @@ init_session_event_spool();
|
|
|
75496
75541
|
init_ingress_policy();
|
|
75497
75542
|
import { constants as constants4 } from "node:fs";
|
|
75498
75543
|
import { mkdir as mkdir8, open as open3, readdir as readdir8, rm as rm7 } from "node:fs/promises";
|
|
75499
|
-
import { join as
|
|
75544
|
+
import { join as join36 } from "node:path";
|
|
75500
75545
|
var MAX_EVENT_BYTES = 1e6;
|
|
75501
75546
|
var MAX_FILES_PER_DRAIN = 1e3;
|
|
75502
75547
|
var SESSION_ID_RE = /^[a-z0-9_-]+$/;
|
|
@@ -75547,7 +75592,7 @@ async function drainSpool(app3, root, observation, host2) {
|
|
|
75547
75592
|
let readBuffer;
|
|
75548
75593
|
for (const session of await readdir8(root, { withFileTypes: true })) {
|
|
75549
75594
|
if (!session.isDirectory() || !SESSION_ID_RE.test(session.name)) continue;
|
|
75550
|
-
const dir2 =
|
|
75595
|
+
const dir2 = join36(root, session.name);
|
|
75551
75596
|
let entries4;
|
|
75552
75597
|
try {
|
|
75553
75598
|
entries4 = await readdir8(dir2, { withFileTypes: true });
|
|
@@ -75559,7 +75604,7 @@ async function drainSpool(app3, root, observation, host2) {
|
|
|
75559
75604
|
if (!entry2.isFile() || !entry2.name.endsWith(".json")) continue;
|
|
75560
75605
|
const eventAt = /^(\d{1,15})-/.exec(entry2.name)?.[1];
|
|
75561
75606
|
if (++examined > MAX_FILES_PER_DRAIN) return delivered;
|
|
75562
|
-
const path =
|
|
75607
|
+
const path = join36(dir2, entry2.name);
|
|
75563
75608
|
let payload;
|
|
75564
75609
|
let handle;
|
|
75565
75610
|
try {
|
|
@@ -76586,9 +76631,9 @@ init_session_sandbox();
|
|
|
76586
76631
|
init_session_sandbox();
|
|
76587
76632
|
import { execFile as execFile16 } from "node:child_process";
|
|
76588
76633
|
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
76589
|
-
import { mkdirSync as mkdirSync17, rmSync as rmSync11, writeFileSync as
|
|
76634
|
+
import { mkdirSync as mkdirSync17, rmSync as rmSync11, writeFileSync as writeFileSync17 } from "node:fs";
|
|
76590
76635
|
import { constants as constants5, tmpdir as tmpdir7 } from "node:os";
|
|
76591
|
-
import { join as
|
|
76636
|
+
import { join as join37 } from "node:path";
|
|
76592
76637
|
var binFor = (agent) => agent === "antigravity" ? antigravityBin() : agent === "codex" ? effectiveStr("HANOMAN_CODEX_BIN") ?? "codex" : effectiveStr("HANOMAN_CLAUDE_BIN") ?? "claude";
|
|
76593
76638
|
function leadArgv(o) {
|
|
76594
76639
|
if (o.agent === "antigravity") return [
|
|
@@ -76626,11 +76671,11 @@ function leadProcess(prompt, o, env = process.env) {
|
|
|
76626
76671
|
const mode = env.HANOMAN_SESSION_SANDBOX ?? (resolveHardening(env) ? "required" : "off");
|
|
76627
76672
|
if (mode === "off") return { file, args: directArgs, cwd: o.cwd, cleanup: () => {
|
|
76628
76673
|
} };
|
|
76629
|
-
const promptDir =
|
|
76674
|
+
const promptDir = join37(tmpdir7(), "hanoman-prompts");
|
|
76630
76675
|
mkdirSync17(promptDir, { recursive: true, mode: 448 });
|
|
76631
|
-
const promptFile =
|
|
76632
|
-
|
|
76633
|
-
const workspace = o.cwd ??
|
|
76676
|
+
const promptFile = join37(promptDir, `oneshot-${randomUUID13()}`);
|
|
76677
|
+
writeFileSync17(promptFile, prompt, { flag: "wx", mode: 384 });
|
|
76678
|
+
const workspace = o.cwd ?? join37(tmpdir7(), `hanoman-oneshot-${randomUUID13()}`);
|
|
76634
76679
|
if (!o.cwd) mkdirSync17(workspace, { recursive: false, mode: 448 });
|
|
76635
76680
|
try {
|
|
76636
76681
|
const argsWithoutPrompt = directArgs.slice(0, -1);
|
|
@@ -77489,13 +77534,13 @@ async function run2(sessionId2, deps) {
|
|
|
77489
77534
|
// src/services/decision-guard.ts
|
|
77490
77535
|
init_src2();
|
|
77491
77536
|
init_db();
|
|
77492
|
-
import { mkdirSync as mkdirSync18, readFileSync as readFileSync18, readdirSync as readdirSync9, rmSync as rmSync12, statSync as statSync6, writeFileSync as
|
|
77493
|
-
import { join as
|
|
77537
|
+
import { mkdirSync as mkdirSync18, readFileSync as readFileSync18, readdirSync as readdirSync9, rmSync as rmSync12, statSync as statSync6, writeFileSync as writeFileSync18 } from "node:fs";
|
|
77538
|
+
import { join as join38 } from "node:path";
|
|
77494
77539
|
var SESSION_HEADER = "x-hanoman-session";
|
|
77495
77540
|
var SAFE_ID = /^[A-Za-z0-9._-]{1,200}$/;
|
|
77496
77541
|
var launchers = /* @__PURE__ */ new Map();
|
|
77497
77542
|
var STALE_MS = 30 * 24 * 60 * 6e4;
|
|
77498
|
-
var launcherDir = (env = process.env) =>
|
|
77543
|
+
var launcherDir = (env = process.env) => join38(resolveHome(env), "session-launchers");
|
|
77499
77544
|
function recordLauncher(sessionId2, agentId, env = process.env) {
|
|
77500
77545
|
if (!SAFE_ID.test(sessionId2)) return;
|
|
77501
77546
|
const known2 = launchersFor(sessionId2, env);
|
|
@@ -77503,11 +77548,11 @@ function recordLauncher(sessionId2, agentId, env = process.env) {
|
|
|
77503
77548
|
try {
|
|
77504
77549
|
const dir2 = launcherDir(env);
|
|
77505
77550
|
mkdirSync18(dir2, { recursive: true, mode: 448 });
|
|
77506
|
-
|
|
77551
|
+
writeFileSync18(join38(dir2, sessionId2), [...known2].join("\n"), { mode: 384 });
|
|
77507
77552
|
const now = Date.now();
|
|
77508
77553
|
for (const f of readdirSync9(dir2)) {
|
|
77509
77554
|
try {
|
|
77510
|
-
if (now - statSync6(
|
|
77555
|
+
if (now - statSync6(join38(dir2, f)).mtimeMs > STALE_MS) rmSync12(join38(dir2, f), { force: true });
|
|
77511
77556
|
} catch {
|
|
77512
77557
|
}
|
|
77513
77558
|
}
|
|
@@ -77519,7 +77564,7 @@ function launchersFor(sessionId2, env) {
|
|
|
77519
77564
|
if (hot) return hot;
|
|
77520
77565
|
const ids = /* @__PURE__ */ new Set();
|
|
77521
77566
|
try {
|
|
77522
|
-
for (const l of readFileSync18(
|
|
77567
|
+
for (const l of readFileSync18(join38(launcherDir(env), sessionId2), "utf8").split("\n")) if (l.trim()) ids.add(l.trim());
|
|
77523
77568
|
} catch {
|
|
77524
77569
|
}
|
|
77525
77570
|
launchers.set(sessionId2, ids);
|
|
@@ -78417,10 +78462,10 @@ import { readFileSync as readFileSync20 } from "node:fs";
|
|
|
78417
78462
|
|
|
78418
78463
|
// src/services/vps-ssh.ts
|
|
78419
78464
|
init_config2();
|
|
78420
|
-
import { spawn as
|
|
78421
|
-
import { mkdtempSync as mkdtempSync4, rmSync as rmSync13, writeFileSync as
|
|
78465
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
78466
|
+
import { mkdtempSync as mkdtempSync4, rmSync as rmSync13, writeFileSync as writeFileSync19 } from "node:fs";
|
|
78422
78467
|
import { tmpdir as tmpdir8 } from "node:os";
|
|
78423
|
-
import { dirname as dirname16, join as
|
|
78468
|
+
import { dirname as dirname16, join as join39 } from "node:path";
|
|
78424
78469
|
var sshBin = () => effectiveStr("HANOMAN_SSH_BIN") ?? "ssh";
|
|
78425
78470
|
function consoleArgv(t) {
|
|
78426
78471
|
return [
|
|
@@ -78435,9 +78480,9 @@ function consoleArgv(t) {
|
|
|
78435
78480
|
];
|
|
78436
78481
|
}
|
|
78437
78482
|
function askpassScript() {
|
|
78438
|
-
const dir2 = mkdtempSync4(
|
|
78439
|
-
const path =
|
|
78440
|
-
|
|
78483
|
+
const dir2 = mkdtempSync4(join39(tmpdir8(), "hanoman-askpass-"));
|
|
78484
|
+
const path = join39(dir2, "askpass.sh");
|
|
78485
|
+
writeFileSync19(path, `#!/bin/sh
|
|
78441
78486
|
printf '%s' "$HANOMAN_SSH_PASSWORD"
|
|
78442
78487
|
`, { mode: 448 });
|
|
78443
78488
|
return path;
|
|
@@ -78471,7 +78516,7 @@ function sshExec(t, remoteCmd, opts2 = {}) {
|
|
|
78471
78516
|
HANOMAN_SSH_PASSWORD: opts2.password
|
|
78472
78517
|
} : process.env;
|
|
78473
78518
|
return new Promise((resolve25) => {
|
|
78474
|
-
const p3 =
|
|
78519
|
+
const p3 = spawn5(sshBin(), args, { stdio: ["pipe", "pipe", "pipe"], env });
|
|
78475
78520
|
let out4 = "";
|
|
78476
78521
|
const timer11 = setTimeout(() => p3.kill("SIGKILL"), opts2.timeoutMs ?? 6e4);
|
|
78477
78522
|
const done = (r) => {
|
|
@@ -78497,16 +78542,16 @@ function sshExec(t, remoteCmd, opts2 = {}) {
|
|
|
78497
78542
|
// src/services/vps-audit.ts
|
|
78498
78543
|
init_db();
|
|
78499
78544
|
import { existsSync as existsSync20, readFileSync as readFileSync19 } from "node:fs";
|
|
78500
|
-
import { join as
|
|
78545
|
+
import { join as join41 } from "node:path";
|
|
78501
78546
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
78502
78547
|
|
|
78503
78548
|
// src/runner/deps.ts
|
|
78504
78549
|
import { existsSync as existsSync19 } from "node:fs";
|
|
78505
|
-
import { dirname as dirname17, join as
|
|
78550
|
+
import { dirname as dirname17, join as join40 } from "node:path";
|
|
78506
78551
|
function repoRootFrom(startDir) {
|
|
78507
78552
|
let dir2 = startDir;
|
|
78508
78553
|
for (let i = 0; i < 8; i++) {
|
|
78509
|
-
if (existsSync19(
|
|
78554
|
+
if (existsSync19(join40(dir2, "pnpm-workspace.yaml"))) return dir2;
|
|
78510
78555
|
const parent = dirname17(dir2);
|
|
78511
78556
|
if (parent === dir2) break;
|
|
78512
78557
|
dir2 = parent;
|
|
@@ -78619,7 +78664,7 @@ var packagedScript = (f) => fileURLToPath4(new URL(`../scripts/vps/${f}`, import
|
|
|
78619
78664
|
var moduleDir = () => fileURLToPath4(new URL(".", import.meta.url));
|
|
78620
78665
|
var scriptPath = (f) => {
|
|
78621
78666
|
const packed = packagedScript(f);
|
|
78622
|
-
return existsSync20(packed) ? packed :
|
|
78667
|
+
return existsSync20(packed) ? packed : join41(repoRoot(moduleDir()), "server", "scripts", "vps", f);
|
|
78623
78668
|
};
|
|
78624
78669
|
async function itemStatesOf(vpsId) {
|
|
78625
78670
|
const rows = await prisma.vpsItemState.findMany({ where: { vpsId } });
|
|
@@ -78866,25 +78911,25 @@ init_config2();
|
|
|
78866
78911
|
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
78867
78912
|
import { chmodSync as chmodSync9, copyFileSync, existsSync as existsSync21, mkdirSync as mkdirSync19, readFileSync as readFileSync22, unlinkSync as unlinkSync5 } from "node:fs";
|
|
78868
78913
|
import { homedir as homedir8 } from "node:os";
|
|
78869
|
-
import { join as
|
|
78914
|
+
import { join as join42 } from "node:path";
|
|
78870
78915
|
var keyDir = () => effectiveStr("HANOMAN_SSH_KEY_DIR") ?? resolveDataDirs().sshKeys;
|
|
78871
78916
|
var KEY_FILES = ["id_ed25519", "id_ed25519.pub"];
|
|
78872
78917
|
function adoptLegacyKey(dir2) {
|
|
78873
78918
|
if (effectiveStr("HANOMAN_SSH_KEY_DIR")) return;
|
|
78874
|
-
const legacy =
|
|
78919
|
+
const legacy = join42(homedir8(), ".hanoman");
|
|
78875
78920
|
if (legacy === dir2) return;
|
|
78876
|
-
if (!KEY_FILES.every((f) => existsSync21(
|
|
78921
|
+
if (!KEY_FILES.every((f) => existsSync21(join42(legacy, f)))) return;
|
|
78877
78922
|
mkdirSync19(dir2, { recursive: true, mode: 448 });
|
|
78878
78923
|
for (const f of KEY_FILES) {
|
|
78879
|
-
copyFileSync(
|
|
78880
|
-
chmodSync9(
|
|
78924
|
+
copyFileSync(join42(legacy, f), join42(dir2, f));
|
|
78925
|
+
chmodSync9(join42(dir2, f), 384);
|
|
78881
78926
|
}
|
|
78882
|
-
for (const f of KEY_FILES) unlinkSync5(
|
|
78927
|
+
for (const f of KEY_FILES) unlinkSync5(join42(legacy, f));
|
|
78883
78928
|
console.log(`vps: key SSH dipindah dari ${legacy} ke ${dir2} (SPEC-846 \u2014 satu batas backup)`);
|
|
78884
78929
|
}
|
|
78885
78930
|
function ensureHanomanKey() {
|
|
78886
78931
|
const dir2 = keyDir();
|
|
78887
|
-
const privPath =
|
|
78932
|
+
const privPath = join42(dir2, KEY_FILES[0]);
|
|
78888
78933
|
const pubPath = `${privPath}.pub`;
|
|
78889
78934
|
if (!existsSync21(privPath)) adoptLegacyKey(dir2);
|
|
78890
78935
|
if (!existsSync21(privPath)) {
|
|
@@ -79197,7 +79242,7 @@ init_config2();
|
|
|
79197
79242
|
import { execFileSync as execFileSync8 } from "node:child_process";
|
|
79198
79243
|
import { readFileSync as readFileSync24 } from "node:fs";
|
|
79199
79244
|
import { homedir as homedir10, userInfo } from "node:os";
|
|
79200
|
-
import { join as
|
|
79245
|
+
import { join as join43 } from "node:path";
|
|
79201
79246
|
var USAGE_URL = "https://api.anthropic.com/api/oauth/usage";
|
|
79202
79247
|
var TTL_MS2 = 3e4;
|
|
79203
79248
|
var lastOk = null;
|
|
@@ -79210,7 +79255,7 @@ var LABELS = {
|
|
|
79210
79255
|
var humanize = (k) => k.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
79211
79256
|
var nowIso = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
79212
79257
|
function credsFile() {
|
|
79213
|
-
return
|
|
79258
|
+
return join43(effectiveStr("CLAUDE_CONFIG_DIR") ?? join43(homedir10(), ".claude"), ".credentials.json");
|
|
79214
79259
|
}
|
|
79215
79260
|
var securityRun = (args) => execFileSync8("security", args, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
|
|
79216
79261
|
var osAccount = () => {
|
|
@@ -79295,14 +79340,14 @@ async function getLimits() {
|
|
|
79295
79340
|
// src/services/codex-limits.ts
|
|
79296
79341
|
import { open as open4, readdir as readdir9, stat as stat7 } from "node:fs/promises";
|
|
79297
79342
|
import { homedir as homedir11 } from "node:os";
|
|
79298
|
-
import { join as
|
|
79343
|
+
import { join as join44 } from "node:path";
|
|
79299
79344
|
var TTL_MS3 = 3e4;
|
|
79300
79345
|
var STALE_AFTER_MS = 12 * 36e5;
|
|
79301
79346
|
var TAIL_BYTES = 512 * 1024;
|
|
79302
79347
|
var MAX_FILES = 8;
|
|
79303
79348
|
var cache2 = null;
|
|
79304
79349
|
var freshUntil2 = 0;
|
|
79305
|
-
var codexSessionsDir = () =>
|
|
79350
|
+
var codexSessionsDir = () => join44(process.env.CODEX_HOME ?? join44(homedir11(), ".codex"), "sessions");
|
|
79306
79351
|
var UNAVAILABLE = { status: "unavailable", windows: [], fetchedAt: null, plan: null };
|
|
79307
79352
|
function windowLabel(minutes) {
|
|
79308
79353
|
if (minutes === 300) return "Sesi 5 jam";
|
|
@@ -79335,7 +79380,7 @@ async function recentRollouts(dir2) {
|
|
|
79335
79380
|
return [];
|
|
79336
79381
|
}
|
|
79337
79382
|
const stamped = await Promise.all(entries4.map(async (rel) => {
|
|
79338
|
-
const full =
|
|
79383
|
+
const full = join44(dir2, rel);
|
|
79339
79384
|
try {
|
|
79340
79385
|
return { full, mtime: (await stat7(full)).mtimeMs };
|
|
79341
79386
|
} catch {
|
|
@@ -79411,7 +79456,7 @@ init_config2();
|
|
|
79411
79456
|
import { execFileSync as execFileSync9 } from "node:child_process";
|
|
79412
79457
|
import { readFileSync as readFileSync25 } from "node:fs";
|
|
79413
79458
|
import { homedir as homedir12 } from "node:os";
|
|
79414
|
-
import { join as
|
|
79459
|
+
import { join as join45 } from "node:path";
|
|
79415
79460
|
var QUOTA_URL = "https://cloudcode-pa.googleapis.com/v1internal:retrieveUserQuotaSummary";
|
|
79416
79461
|
var USER_AGENT = "antigravity (hanoman)";
|
|
79417
79462
|
var TTL_MS4 = 6e4;
|
|
@@ -79433,10 +79478,10 @@ function readAgyToken(run6 = securityRun2) {
|
|
|
79433
79478
|
return null;
|
|
79434
79479
|
}
|
|
79435
79480
|
}
|
|
79436
|
-
var agyHome = () =>
|
|
79481
|
+
var agyHome = () => join45(homedir12(), ".gemini", "antigravity-cli");
|
|
79437
79482
|
function defaultProject() {
|
|
79438
79483
|
try {
|
|
79439
|
-
return readFileSync25(
|
|
79484
|
+
return readFileSync25(join45(agyHome(), "cache", "default_project_id.txt"), "utf8").trim() || null;
|
|
79440
79485
|
} catch {
|
|
79441
79486
|
return null;
|
|
79442
79487
|
}
|
|
@@ -79624,7 +79669,7 @@ init_src2();
|
|
|
79624
79669
|
init_src();
|
|
79625
79670
|
import { randomUUID as randomUUID14 } from "node:crypto";
|
|
79626
79671
|
import { readFile as readFile8, writeFile as writeFile6, rename as rename5, mkdir as mkdir9, rm as rm9 } from "node:fs/promises";
|
|
79627
|
-
import { dirname as dirname18, join as
|
|
79672
|
+
import { dirname as dirname18, join as join47 } from "node:path";
|
|
79628
79673
|
|
|
79629
79674
|
// src/services/model-catalog-parser.ts
|
|
79630
79675
|
init_zod();
|
|
@@ -79728,10 +79773,10 @@ init_src2();
|
|
|
79728
79773
|
init_antigravity_runtime();
|
|
79729
79774
|
init_config2();
|
|
79730
79775
|
init_session_sandbox();
|
|
79731
|
-
import { spawn as
|
|
79776
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
79732
79777
|
import { mkdtemp as mkdtemp2, rm as rm8 } from "node:fs/promises";
|
|
79733
79778
|
import { tmpdir as tmpdir9 } from "node:os";
|
|
79734
|
-
import { join as
|
|
79779
|
+
import { join as join46 } from "node:path";
|
|
79735
79780
|
var MAX_BYTES = 4 * 1024 * 1024;
|
|
79736
79781
|
var TIMEOUT_MS = 2e4;
|
|
79737
79782
|
var quote3 = (s2) => "'" + s2.replaceAll("'", "'\\''") + "'";
|
|
@@ -79768,7 +79813,7 @@ function catalogCommand(agent, cwd, env) {
|
|
|
79768
79813
|
function runCatalogCommand(command, agent, cwd, env, timeoutMs = TIMEOUT_MS) {
|
|
79769
79814
|
return new Promise((resolve25, reject2) => {
|
|
79770
79815
|
assertAntigravityLaunch(agent, void 0, env);
|
|
79771
|
-
const child =
|
|
79816
|
+
const child = spawn6(command.bin, command.args, { cwd, env: agentEnvironment(agent, env), stdio: ["pipe", "pipe", "pipe"] });
|
|
79772
79817
|
let buffer = "", bytes = 0, settled = false;
|
|
79773
79818
|
let killTimer;
|
|
79774
79819
|
const finish = (error, result) => {
|
|
@@ -79830,7 +79875,7 @@ function runCatalogCommand(command, agent, cwd, env, timeoutMs = TIMEOUT_MS) {
|
|
|
79830
79875
|
}
|
|
79831
79876
|
async function probeModelCatalog(agent) {
|
|
79832
79877
|
assertAntigravityLaunch(agent);
|
|
79833
|
-
const cwd = await mkdtemp2(
|
|
79878
|
+
const cwd = await mkdtemp2(join46(tmpdir9(), "hanoman-models-"));
|
|
79834
79879
|
const env = agentEnvironment(agent, process.env);
|
|
79835
79880
|
for (const key of ["HANOMAN_CLAUDE_BIN", "HANOMAN_CODEX_BIN", "HANOMAN_PODMAN_BIN", "HANOMAN_ANTIGRAVITY_BIN"]) {
|
|
79836
79881
|
const value = effectiveStr(key);
|
|
@@ -79941,7 +79986,7 @@ async function writeModelCatalogCache(file, catalog, current = () => true) {
|
|
|
79941
79986
|
await rm9(temp, { force: true });
|
|
79942
79987
|
}
|
|
79943
79988
|
}
|
|
79944
|
-
var cacheFile = () =>
|
|
79989
|
+
var cacheFile = () => join47(resolveHome(), "model-catalog.json");
|
|
79945
79990
|
var modelCatalogService = createModelCatalogService({
|
|
79946
79991
|
probe: probeModelCatalog,
|
|
79947
79992
|
key: catalogProbeKey,
|
|
@@ -79980,8 +80025,9 @@ init_pty();
|
|
|
79980
80025
|
|
|
79981
80026
|
// src/services/restart.ts
|
|
79982
80027
|
init_src();
|
|
80028
|
+
init_exit_guard();
|
|
79983
80029
|
function requestConfigRestart(delayMs = 50) {
|
|
79984
|
-
setTimeout(() =>
|
|
80030
|
+
setTimeout(() => exitGuarded(CONFIG_RESTART_EXIT), delayMs);
|
|
79985
80031
|
}
|
|
79986
80032
|
function afterReplyFlushed(raw, fn, maxWaitMs = 5e3) {
|
|
79987
80033
|
let done = false;
|
|
@@ -79999,7 +80045,7 @@ function afterReplyFlushed(raw, fn, maxWaitMs = 5e3) {
|
|
|
79999
80045
|
timer11 = setTimeout(run6, maxWaitMs);
|
|
80000
80046
|
}
|
|
80001
80047
|
function requestManualRestart(delayMs = 250) {
|
|
80002
|
-
setTimeout(() =>
|
|
80048
|
+
setTimeout(() => exitGuarded(MANUAL_RESTART_EXIT), delayMs);
|
|
80003
80049
|
}
|
|
80004
80050
|
|
|
80005
80051
|
// src/routes/update.ts
|
|
@@ -81868,7 +81914,7 @@ init_src();
|
|
|
81868
81914
|
init_db();
|
|
81869
81915
|
import { gunzipSync, gzipSync } from "node:zlib";
|
|
81870
81916
|
import { mkdir as mkdir10, rename as rename6, writeFile as writeFile7 } from "node:fs/promises";
|
|
81871
|
-
import { join as
|
|
81917
|
+
import { join as join48 } from "node:path";
|
|
81872
81918
|
|
|
81873
81919
|
// src/services/device-auth.ts
|
|
81874
81920
|
function bearerToken2(req) {
|
|
@@ -82124,9 +82170,9 @@ async function sync_default(app3) {
|
|
|
82124
82170
|
const deviceId = req.device.id;
|
|
82125
82171
|
const withTranscriptKey = await Promise.all(parsed.data.entries.map(async (e) => {
|
|
82126
82172
|
if (!e.transcript) return e;
|
|
82127
|
-
const dir2 =
|
|
82173
|
+
const dir2 = join48(resolveDataDirs().home, "remote-transcripts", deviceId);
|
|
82128
82174
|
await mkdir10(dir2, { recursive: true, mode: 448 });
|
|
82129
|
-
const final =
|
|
82175
|
+
const final = join48(dir2, `${e.seq}.txt`);
|
|
82130
82176
|
const tmp = `${final}.tmp`;
|
|
82131
82177
|
await writeFile7(tmp, e.transcript, { encoding: "utf8", mode: 384 });
|
|
82132
82178
|
await rename6(tmp, final);
|
|
@@ -85413,7 +85459,7 @@ init_qa_attachment_transfer();
|
|
|
85413
85459
|
init_uploads();
|
|
85414
85460
|
import { createHash as createHash21 } from "node:crypto";
|
|
85415
85461
|
import { execFileSync as execFileSync10 } from "node:child_process";
|
|
85416
|
-
import { join as
|
|
85462
|
+
import { join as join50 } from "node:path";
|
|
85417
85463
|
var QaSessionError = class extends Error {
|
|
85418
85464
|
constructor(code, message, needsBind = false) {
|
|
85419
85465
|
super(message);
|
|
@@ -85440,7 +85486,7 @@ async function startQaFindingSession(d, fid) {
|
|
|
85440
85486
|
const saved = await saveSessionUpload(id2, bytes, a.mimeType);
|
|
85441
85487
|
files2.push(`${JSON.stringify(a.filename)} (${a.mimeType}): ${saved.path}`);
|
|
85442
85488
|
}
|
|
85443
|
-
const wt =
|
|
85489
|
+
const wt = join50(repoDir, ".worktrees", id2);
|
|
85444
85490
|
const branch = `qa/${id2.slice(3)}`;
|
|
85445
85491
|
const reused = realGit.worktreeAlive(wt);
|
|
85446
85492
|
try {
|
|
@@ -86979,9 +87025,9 @@ ${baru}`;
|
|
|
86979
87025
|
// src/services/portal-chat/workspace.ts
|
|
86980
87026
|
init_src();
|
|
86981
87027
|
init_db();
|
|
86982
|
-
import { mkdirSync as mkdirSync20, mkdtempSync as mkdtempSync5, rmSync as rmSync14, writeFileSync as
|
|
87028
|
+
import { mkdirSync as mkdirSync20, mkdtempSync as mkdtempSync5, rmSync as rmSync14, writeFileSync as writeFileSync20 } from "node:fs";
|
|
86983
87029
|
import { tmpdir as tmpdir10 } from "node:os";
|
|
86984
|
-
import { join as
|
|
87030
|
+
import { join as join51 } from "node:path";
|
|
86985
87031
|
var STAGE_LABEL = {
|
|
86986
87032
|
brainstorming: "Dirumuskan",
|
|
86987
87033
|
objective: "Dirumuskan",
|
|
@@ -87024,7 +87070,7 @@ function renderTicketDoc(tickets2) {
|
|
|
87024
87070
|
${baris.join("\n")}`;
|
|
87025
87071
|
}
|
|
87026
87072
|
async function buildChatWorkspace(projectId) {
|
|
87027
|
-
const dir2 = mkdtempSync5(
|
|
87073
|
+
const dir2 = mkdtempSync5(join51(tmpdir10(), "hanoman-portal-chat-"));
|
|
87028
87074
|
try {
|
|
87029
87075
|
const project = await prisma.project.findUnique({
|
|
87030
87076
|
where: { id: projectId },
|
|
@@ -87039,7 +87085,7 @@ async function buildChatWorkspace(projectId) {
|
|
|
87039
87085
|
});
|
|
87040
87086
|
const files2 = [];
|
|
87041
87087
|
const tulis = (rel, isi) => {
|
|
87042
|
-
|
|
87088
|
+
writeFileSync20(join51(dir2, rel), isi, { mode: 384 });
|
|
87043
87089
|
files2.push(rel);
|
|
87044
87090
|
};
|
|
87045
87091
|
tulis("project.md", renderProjectDoc(project));
|
|
@@ -87047,11 +87093,11 @@ async function buildChatWorkspace(projectId) {
|
|
|
87047
87093
|
tulis("laporan.md", renderTicketDoc(tickets2.map((t) => toPortalTicket(t, null))));
|
|
87048
87094
|
const prds = await listPrds(projectId);
|
|
87049
87095
|
if (prds.length) {
|
|
87050
|
-
mkdirSync20(
|
|
87096
|
+
mkdirSync20(join51(dir2, "dokumen"), { mode: 448 });
|
|
87051
87097
|
for (const prd of prds) {
|
|
87052
87098
|
const isi = await readPrd(projectId, prd.path);
|
|
87053
87099
|
if (!isi) continue;
|
|
87054
|
-
tulis(
|
|
87100
|
+
tulis(join51("dokumen", `${prd.slug.replaceAll("/", "-")}.md`), isi);
|
|
87055
87101
|
}
|
|
87056
87102
|
}
|
|
87057
87103
|
return { dir: dir2, files: files2, cleanup: () => rmSync14(dir2, { recursive: true, force: true }) };
|
|
@@ -87578,13 +87624,13 @@ init_db();
|
|
|
87578
87624
|
// src/services/bootstrap.ts
|
|
87579
87625
|
import { createHash as createHash22, randomBytes as randomBytes11, timingSafeEqual as timingSafeEqual5 } from "node:crypto";
|
|
87580
87626
|
import { chmod as chmod2, lstat as lstat3, mkdir as mkdir11, readFile as readFile9, unlink as unlink5, writeFile as writeFile8 } from "node:fs/promises";
|
|
87581
|
-
import { join as
|
|
87627
|
+
import { join as join52 } from "node:path";
|
|
87582
87628
|
var TTL_MS7 = 15 * 6e4;
|
|
87583
87629
|
var SETUP_TOKEN_FILE = "setup.token";
|
|
87584
87630
|
var BootstrapError = class extends Error {
|
|
87585
87631
|
code = "BOOTSTRAP_PROOF";
|
|
87586
87632
|
};
|
|
87587
|
-
var tokenPath = (home3) =>
|
|
87633
|
+
var tokenPath = (home3) => join52(home3, SETUP_TOKEN_FILE);
|
|
87588
87634
|
async function readStored(home3) {
|
|
87589
87635
|
try {
|
|
87590
87636
|
const info = await lstat3(tokenPath(home3));
|
|
@@ -88422,7 +88468,7 @@ init_event_log();
|
|
|
88422
88468
|
init_transcript_store();
|
|
88423
88469
|
init_src2();
|
|
88424
88470
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
88425
|
-
import { join as
|
|
88471
|
+
import { join as join53 } from "node:path";
|
|
88426
88472
|
function decodeCursor(c) {
|
|
88427
88473
|
if (!c) return null;
|
|
88428
88474
|
try {
|
|
@@ -88460,7 +88506,7 @@ async function readRemoteTranscript(id2) {
|
|
|
88460
88506
|
const row = await prisma.logEntry.findUnique({ where: { id: id2 } });
|
|
88461
88507
|
if (!row || row.lane !== "transcript" || !row.transcriptKey) return null;
|
|
88462
88508
|
if (row.deviceId === "local") return readTranscript(row.transcriptKey);
|
|
88463
|
-
const path =
|
|
88509
|
+
const path = join53(resolveDataDirs().home, "remote-transcripts", row.transcriptKey);
|
|
88464
88510
|
try {
|
|
88465
88511
|
return await readFile10(path, "utf8");
|
|
88466
88512
|
} catch {
|
|
@@ -89727,9 +89773,9 @@ async function pruneLogs(now, retention, opts2 = {}) {
|
|
|
89727
89773
|
}
|
|
89728
89774
|
async function reconcileRemoteTranscripts() {
|
|
89729
89775
|
const { readdir: readdir10, unlink: unlink6, stat: stat8 } = await import("node:fs/promises");
|
|
89730
|
-
const { join:
|
|
89776
|
+
const { join: join54 } = await import("node:path");
|
|
89731
89777
|
const { resolveDataDirs: resolveDataDirs2 } = await Promise.resolve().then(() => (init_src2(), src_exports));
|
|
89732
|
-
const root =
|
|
89778
|
+
const root = join54(resolveDataDirs2().home, "remote-transcripts");
|
|
89733
89779
|
let deviceDirs;
|
|
89734
89780
|
try {
|
|
89735
89781
|
deviceDirs = await readdir10(root);
|
|
@@ -89743,16 +89789,16 @@ async function reconcileRemoteTranscripts() {
|
|
|
89743
89789
|
for (const dev of deviceDirs) {
|
|
89744
89790
|
let files2;
|
|
89745
89791
|
try {
|
|
89746
|
-
files2 = await readdir10(
|
|
89792
|
+
files2 = await readdir10(join54(root, dev));
|
|
89747
89793
|
} catch {
|
|
89748
89794
|
continue;
|
|
89749
89795
|
}
|
|
89750
89796
|
for (const f of files2) {
|
|
89751
89797
|
const key = `${dev}/${f}`;
|
|
89752
89798
|
if (referenced.has(key)) continue;
|
|
89753
|
-
const st = await stat8(
|
|
89799
|
+
const st = await stat8(join54(root, dev, f)).catch(() => null);
|
|
89754
89800
|
if (!st || Date.now() - st.mtimeMs < gracePeriodMs) continue;
|
|
89755
|
-
await unlink6(
|
|
89801
|
+
await unlink6(join54(root, dev, f)).catch(() => {
|
|
89756
89802
|
});
|
|
89757
89803
|
orphans++;
|
|
89758
89804
|
}
|
|
@@ -89939,6 +89985,7 @@ init_transcript_store();
|
|
|
89939
89985
|
init_client2();
|
|
89940
89986
|
init_dispatcher();
|
|
89941
89987
|
init_safe_outbound_request();
|
|
89988
|
+
init_exit_guard();
|
|
89942
89989
|
installSafeGlobalFetch();
|
|
89943
89990
|
var app2 = buildApp();
|
|
89944
89991
|
var port = Number(process.env.PORT ?? 8787);
|
|
@@ -89957,7 +90004,7 @@ var shutdown = createShutdown({
|
|
|
89957
90004
|
await app2.close();
|
|
89958
90005
|
await prisma.$disconnect();
|
|
89959
90006
|
},
|
|
89960
|
-
exit: (code) =>
|
|
90007
|
+
exit: (code) => exitGuarded(code)
|
|
89961
90008
|
});
|
|
89962
90009
|
process.on("SIGTERM", () => void shutdown("SIGTERM"));
|
|
89963
90010
|
process.on("SIGINT", () => void shutdown("SIGINT"));
|
|
@@ -90033,7 +90080,7 @@ bootstrapReady.then(async () => {
|
|
|
90033
90080
|
startOverviewRecorder();
|
|
90034
90081
|
}).catch((err) => {
|
|
90035
90082
|
console.error("listen gagal:", err);
|
|
90036
|
-
|
|
90083
|
+
exitGuarded(1);
|
|
90037
90084
|
});
|
|
90038
90085
|
/*! Bundled license information:
|
|
90039
90086
|
|