hanoman 0.1.27 → 0.1.28
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 +98 -40
- package/dist/server.js +134 -76
- package/package.json +1 -1
- package/web/assets/{index-D6bmQt7Y.js → index-CJNgL7_5.js} +1543 -1543
- package/web/index.html +1 -1
package/dist/server.js
CHANGED
|
@@ -8657,7 +8657,7 @@ var init_paths = __esm({
|
|
|
8657
8657
|
|
|
8658
8658
|
// ../runner/src/skills.ts
|
|
8659
8659
|
import { homedir as homedir2 } from "node:os";
|
|
8660
|
-
import { join as join2 } from "node:path";
|
|
8660
|
+
import { basename, dirname as dirname3, join as join2, resolve as resolve6 } from "node:path";
|
|
8661
8661
|
import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync2 } from "node:fs";
|
|
8662
8662
|
function agentSkillHome(agent, env = process.env, osHome = homedir2()) {
|
|
8663
8663
|
const own = (agent === "codex" ? env.HANOMAN_CODEX_HOME : env.HANOMAN_CLAUDE_HOME)?.trim();
|
|
@@ -8668,6 +8668,9 @@ function agentSkillHome(agent, env = process.env, osHome = homedir2()) {
|
|
|
8668
8668
|
}
|
|
8669
8669
|
return join2(osHome, agent === "codex" ? ".codex" : ".claude");
|
|
8670
8670
|
}
|
|
8671
|
+
function agentsSkillHome(env = process.env, osHome = homedir2()) {
|
|
8672
|
+
return env.HANOMAN_AGENTS_HOME?.trim() || join2(osHome, ".agents");
|
|
8673
|
+
}
|
|
8671
8674
|
function dirsIn(dir2) {
|
|
8672
8675
|
try {
|
|
8673
8676
|
return readdirSync(dir2, { withFileTypes: true }).filter((e) => (e.isDirectory() || e.isSymbolicLink()) && !e.name.startsWith(".")).map((e) => e.name);
|
|
@@ -8682,8 +8685,51 @@ function readJson(file) {
|
|
|
8682
8685
|
return null;
|
|
8683
8686
|
}
|
|
8684
8687
|
}
|
|
8685
|
-
function
|
|
8686
|
-
return
|
|
8688
|
+
function isSkillDir(dir2) {
|
|
8689
|
+
return existsSync2(join2(dir2, "SKILL.md"));
|
|
8690
|
+
}
|
|
8691
|
+
function asSkill(dir2, pkg, name2 = basename(dir2)) {
|
|
8692
|
+
return { id: pkg ? `${pkg}:${name2}` : name2, name: name2, pkg, dir: dir2 };
|
|
8693
|
+
}
|
|
8694
|
+
function skillsUnder(dir2, pkg, depth = 2) {
|
|
8695
|
+
const out3 = [];
|
|
8696
|
+
for (const name2 of dirsIn(dir2)) {
|
|
8697
|
+
const sub = join2(dir2, name2);
|
|
8698
|
+
if (isSkillDir(sub)) out3.push(asSkill(sub, pkg, name2));
|
|
8699
|
+
else if (depth > 1) out3.push(...skillsUnder(sub, pkg, depth - 1));
|
|
8700
|
+
}
|
|
8701
|
+
return out3;
|
|
8702
|
+
}
|
|
8703
|
+
function manifestSkills(installPath, pkg) {
|
|
8704
|
+
for (const marker of [".claude-plugin", ".codex-plugin"]) {
|
|
8705
|
+
const j = readJson(join2(installPath, marker, "plugin.json"));
|
|
8706
|
+
const declared = j?.skills;
|
|
8707
|
+
if (!Array.isArray(declared)) continue;
|
|
8708
|
+
const out3 = [];
|
|
8709
|
+
for (const rel of declared) {
|
|
8710
|
+
if (typeof rel !== "string" || !rel) continue;
|
|
8711
|
+
const p = resolve6(installPath, rel);
|
|
8712
|
+
const dir2 = basename(p) === "SKILL.md" ? dirname3(p) : p;
|
|
8713
|
+
if (isSkillDir(dir2)) out3.push(asSkill(dir2, pkg));
|
|
8714
|
+
}
|
|
8715
|
+
if (out3.length) return out3;
|
|
8716
|
+
}
|
|
8717
|
+
return [];
|
|
8718
|
+
}
|
|
8719
|
+
function pluginSkills(installPath, pkg) {
|
|
8720
|
+
const declared = manifestSkills(installPath, pkg);
|
|
8721
|
+
return declared.length ? declared : skillsUnder(join2(installPath, "skills"), pkg);
|
|
8722
|
+
}
|
|
8723
|
+
function lockPluginNames(agentsHome) {
|
|
8724
|
+
const out3 = /* @__PURE__ */ new Map();
|
|
8725
|
+
const j = readJson(join2(agentsHome, ".skill-lock.json"));
|
|
8726
|
+
const skills = j?.skills;
|
|
8727
|
+
if (!skills || typeof skills !== "object") return out3;
|
|
8728
|
+
for (const [name2, entry] of Object.entries(skills)) {
|
|
8729
|
+
const pkg = entry?.pluginName;
|
|
8730
|
+
if (typeof pkg === "string" && pkg.trim()) out3.set(name2, pkg.trim());
|
|
8731
|
+
}
|
|
8732
|
+
return out3;
|
|
8687
8733
|
}
|
|
8688
8734
|
function splitPluginKey(key) {
|
|
8689
8735
|
const at = key.lastIndexOf("@");
|
|
@@ -8763,11 +8809,23 @@ function scanAgentSkills(agent, env = process.env, osHome = homedir2()) {
|
|
|
8763
8809
|
add(userDir, skillsUnder(userDir, null));
|
|
8764
8810
|
for (const r of [...manifestRoots(home2), ...cacheRoots(home2)]) {
|
|
8765
8811
|
if (disabled.has(`${r.pkg}@${r.marketplace}`)) continue;
|
|
8766
|
-
const
|
|
8767
|
-
const found = skillsUnder(dir2, r.pkg);
|
|
8812
|
+
const found = pluginSkills(r.dir, r.pkg);
|
|
8768
8813
|
if (!found.length) continue;
|
|
8769
8814
|
packages.add(r.pkg);
|
|
8770
|
-
add(
|
|
8815
|
+
add(join2(r.dir, "skills"), found);
|
|
8816
|
+
}
|
|
8817
|
+
if (agent === "codex") {
|
|
8818
|
+
const agentsHome = agentsSkillHome(env, osHome);
|
|
8819
|
+
const dir2 = join2(agentsHome, "skills");
|
|
8820
|
+
const names = lockPluginNames(agentsHome);
|
|
8821
|
+
const flat = skillsUnder(dir2, null);
|
|
8822
|
+
const withPkg = flat.flatMap((s2) => {
|
|
8823
|
+
const pkg = names.get(s2.name);
|
|
8824
|
+
if (!pkg) return [s2];
|
|
8825
|
+
packages.add(pkg);
|
|
8826
|
+
return [asSkill(s2.dir, pkg, s2.name), s2];
|
|
8827
|
+
});
|
|
8828
|
+
add(dir2, withPkg);
|
|
8771
8829
|
}
|
|
8772
8830
|
return { agent, home: home2, roots, skills, packages: [...packages] };
|
|
8773
8831
|
}
|
|
@@ -9002,7 +9060,7 @@ var init_tap = __esm({
|
|
|
9002
9060
|
|
|
9003
9061
|
// src/db.ts
|
|
9004
9062
|
import { mkdirSync as mkdirSync2 } from "node:fs";
|
|
9005
|
-
import { dirname as
|
|
9063
|
+
import { dirname as dirname4, resolve as resolve7 } from "node:path";
|
|
9006
9064
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
9007
9065
|
import { PrismaClient } from "@prisma/client";
|
|
9008
9066
|
var schemaDir, notice, url, base, prisma;
|
|
@@ -9012,12 +9070,12 @@ var init_db = __esm({
|
|
|
9012
9070
|
init_env();
|
|
9013
9071
|
init_src2();
|
|
9014
9072
|
init_tap();
|
|
9015
|
-
schemaDir =
|
|
9073
|
+
schemaDir = resolve7(dirname4(fileURLToPath2(import.meta.url)), "../prisma");
|
|
9016
9074
|
notice = dbUrlNotice(process.env);
|
|
9017
9075
|
if (notice) console.warn(notice);
|
|
9018
9076
|
url = resolveDbUrl(process.env, schemaDir);
|
|
9019
9077
|
process.env.DATABASE_URL = url;
|
|
9020
|
-
mkdirSync2(
|
|
9078
|
+
mkdirSync2(dirname4(dbFilePath(url)), { recursive: true });
|
|
9021
9079
|
base = new PrismaClient();
|
|
9022
9080
|
prisma = base.$extends(webhookTap(base));
|
|
9023
9081
|
}
|
|
@@ -9373,7 +9431,7 @@ var init_tui_dialog = __esm({
|
|
|
9373
9431
|
// src/services/secret-box.ts
|
|
9374
9432
|
import { chmodSync, existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync } from "node:fs";
|
|
9375
9433
|
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
|
|
9376
|
-
import { dirname as
|
|
9434
|
+
import { dirname as dirname5, join as join3 } from "node:path";
|
|
9377
9435
|
function isEncrypted(value) {
|
|
9378
9436
|
return value.startsWith(ENC_PREFIX);
|
|
9379
9437
|
}
|
|
@@ -9424,7 +9482,7 @@ function secretKey() {
|
|
|
9424
9482
|
return key2;
|
|
9425
9483
|
}
|
|
9426
9484
|
const key = randomBytes(KEY_BYTES);
|
|
9427
|
-
mkdirSync3(
|
|
9485
|
+
mkdirSync3(dirname5(path), { recursive: true });
|
|
9428
9486
|
writeFileSync(path, key.toString("base64url"), { mode: 384 });
|
|
9429
9487
|
chmodSync(path, 384);
|
|
9430
9488
|
cached = key;
|
|
@@ -9523,7 +9581,7 @@ import { spawn } from "node-pty";
|
|
|
9523
9581
|
import { execFileSync } from "node:child_process";
|
|
9524
9582
|
import { randomUUID } from "node:crypto";
|
|
9525
9583
|
import { mkdirSync as mkdirSync4, statSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
9526
|
-
import { dirname as
|
|
9584
|
+
import { dirname as dirname6 } from "node:path";
|
|
9527
9585
|
import { tmpdir } from "node:os";
|
|
9528
9586
|
function tmux(...args) {
|
|
9529
9587
|
try {
|
|
@@ -9605,7 +9663,7 @@ function createSession(projectId, cwd, opts = {}) {
|
|
|
9605
9663
|
let promptArg = "";
|
|
9606
9664
|
if (!opts.command && opts.prompt) {
|
|
9607
9665
|
const promptFile = promptFilePath(id);
|
|
9608
|
-
mkdirSync4(
|
|
9666
|
+
mkdirSync4(dirname6(promptFile), { recursive: true });
|
|
9609
9667
|
writeFileSync2(promptFile, opts.prompt + rosterBlock);
|
|
9610
9668
|
promptArg = `"$(cat ${sq(promptFile)})"`;
|
|
9611
9669
|
}
|
|
@@ -9617,7 +9675,7 @@ function createSession(projectId, cwd, opts = {}) {
|
|
|
9617
9675
|
let goalGate;
|
|
9618
9676
|
if (agent === "codex" && opts.goal && opts.flow && opts.specId) {
|
|
9619
9677
|
goalGate = goalGatePath(id);
|
|
9620
|
-
mkdirSync4(
|
|
9678
|
+
mkdirSync4(dirname6(goalGate), { recursive: true });
|
|
9621
9679
|
writeFileSync2(goalGate, codexGoalScript({
|
|
9622
9680
|
flow: opts.flow,
|
|
9623
9681
|
specId: opts.specId,
|
|
@@ -9633,7 +9691,7 @@ function createSession(projectId, cwd, opts = {}) {
|
|
|
9633
9691
|
const json = renderAgentsJson(customDefs);
|
|
9634
9692
|
if (json) {
|
|
9635
9693
|
agentsFile = agentsFilePath(id);
|
|
9636
|
-
mkdirSync4(
|
|
9694
|
+
mkdirSync4(dirname6(agentsFile), { recursive: true });
|
|
9637
9695
|
writeFileSync2(agentsFile, json);
|
|
9638
9696
|
}
|
|
9639
9697
|
}
|
|
@@ -9653,12 +9711,12 @@ function createSession(projectId, cwd, opts = {}) {
|
|
|
9653
9711
|
for (const [k, v] of Object.entries(rootBypassEnv())) envPairs.push(`${k}=${sq(v)}`);
|
|
9654
9712
|
}
|
|
9655
9713
|
if (opts.phaseFile) {
|
|
9656
|
-
mkdirSync4(
|
|
9714
|
+
mkdirSync4(dirname6(opts.phaseFile), { recursive: true });
|
|
9657
9715
|
envPairs.push(`HANOMAN_PHASE_FILE=${sq(opts.phaseFile)}`);
|
|
9658
9716
|
}
|
|
9659
9717
|
for (const [k, v] of Object.entries(opts.env ?? {})) envPairs.push(`${k}=${sq(v)}`);
|
|
9660
9718
|
const cmd = envPairs.length ? `${envPairs.join(" ")} ${argv}` : argv;
|
|
9661
|
-
if (opts.decisionFile) mkdirSync4(
|
|
9719
|
+
if (opts.decisionFile) mkdirSync4(dirname6(opts.decisionFile), { recursive: true });
|
|
9662
9720
|
tmux(
|
|
9663
9721
|
"set-option",
|
|
9664
9722
|
"-g",
|
|
@@ -11169,7 +11227,7 @@ var init_gateway = __esm({
|
|
|
11169
11227
|
const message = sanitizeTelegramOutput(error.message, this.deps.exactSecrets).slice(0, 500);
|
|
11170
11228
|
updateTelegramRuntimeStatus({ running: false, readiness: "error", lastError: message });
|
|
11171
11229
|
if (error instanceof TelegramApiError && error.code === 409) return;
|
|
11172
|
-
await new Promise((
|
|
11230
|
+
await new Promise((resolve16) => setTimeout(resolve16, 1e3));
|
|
11173
11231
|
}
|
|
11174
11232
|
}
|
|
11175
11233
|
}
|
|
@@ -17179,7 +17237,7 @@ var require_parseParams = __commonJS({
|
|
|
17179
17237
|
var require_basename = __commonJS({
|
|
17180
17238
|
"../node_modules/.pnpm/@fastify+busboy@3.2.0/node_modules/@fastify/busboy/lib/utils/basename.js"(exports, module) {
|
|
17181
17239
|
"use strict";
|
|
17182
|
-
module.exports = function
|
|
17240
|
+
module.exports = function basename4(path) {
|
|
17183
17241
|
if (typeof path !== "string") {
|
|
17184
17242
|
return "";
|
|
17185
17243
|
}
|
|
@@ -17206,7 +17264,7 @@ var require_multipart = __commonJS({
|
|
|
17206
17264
|
var Dicer = require_Dicer();
|
|
17207
17265
|
var parseParams = require_parseParams();
|
|
17208
17266
|
var decodeText = require_decodeText();
|
|
17209
|
-
var
|
|
17267
|
+
var basename4 = require_basename();
|
|
17210
17268
|
var getLimit = require_getLimit();
|
|
17211
17269
|
var RE_BOUNDARY = /^boundary$/i;
|
|
17212
17270
|
var RE_FIELD = /^form-data$/i;
|
|
@@ -17323,7 +17381,7 @@ var require_multipart = __commonJS({
|
|
|
17323
17381
|
} else if (RE_FILENAME.test(parsed[i][0])) {
|
|
17324
17382
|
filename = parsed[i][1];
|
|
17325
17383
|
if (!preservePath) {
|
|
17326
|
-
filename =
|
|
17384
|
+
filename = basename4(filename);
|
|
17327
17385
|
}
|
|
17328
17386
|
}
|
|
17329
17387
|
}
|
|
@@ -18407,17 +18465,17 @@ var require_stream_wormhole = __commonJS({
|
|
|
18407
18465
|
"../node_modules/.pnpm/stream-wormhole@1.1.0/node_modules/stream-wormhole/index.js"(exports, module) {
|
|
18408
18466
|
"use strict";
|
|
18409
18467
|
module.exports = (stream, throwError) => {
|
|
18410
|
-
return new Promise((
|
|
18468
|
+
return new Promise((resolve16, reject2) => {
|
|
18411
18469
|
if (typeof stream.resume !== "function") {
|
|
18412
|
-
return
|
|
18470
|
+
return resolve16();
|
|
18413
18471
|
}
|
|
18414
18472
|
stream.unpipe && stream.unpipe();
|
|
18415
18473
|
stream.resume();
|
|
18416
18474
|
if (stream._readableState && stream._readableState.ended) {
|
|
18417
|
-
return
|
|
18475
|
+
return resolve16();
|
|
18418
18476
|
}
|
|
18419
18477
|
if (!stream.readable || stream.destroyed) {
|
|
18420
|
-
return
|
|
18478
|
+
return resolve16();
|
|
18421
18479
|
}
|
|
18422
18480
|
function cleanup() {
|
|
18423
18481
|
stream.removeListener("end", onEnd);
|
|
@@ -18426,14 +18484,14 @@ var require_stream_wormhole = __commonJS({
|
|
|
18426
18484
|
}
|
|
18427
18485
|
function onEnd() {
|
|
18428
18486
|
cleanup();
|
|
18429
|
-
|
|
18487
|
+
resolve16();
|
|
18430
18488
|
}
|
|
18431
18489
|
function onError(err) {
|
|
18432
18490
|
cleanup();
|
|
18433
18491
|
if (throwError) {
|
|
18434
18492
|
reject2(err);
|
|
18435
18493
|
} else {
|
|
18436
|
-
|
|
18494
|
+
resolve16();
|
|
18437
18495
|
}
|
|
18438
18496
|
}
|
|
18439
18497
|
stream.on("end", onEnd);
|
|
@@ -18868,16 +18926,16 @@ var require_multipart2 = __commonJS({
|
|
|
18868
18926
|
}
|
|
18869
18927
|
};
|
|
18870
18928
|
const parts = () => {
|
|
18871
|
-
return new Promise((
|
|
18929
|
+
return new Promise((resolve16, reject2) => {
|
|
18872
18930
|
handle((val) => {
|
|
18873
18931
|
if (val instanceof Error) {
|
|
18874
18932
|
if (val.message === "Unexpected end of multipart data") {
|
|
18875
|
-
|
|
18933
|
+
resolve16(null);
|
|
18876
18934
|
} else {
|
|
18877
18935
|
reject2(val);
|
|
18878
18936
|
}
|
|
18879
18937
|
} else {
|
|
18880
|
-
|
|
18938
|
+
resolve16(val);
|
|
18881
18939
|
}
|
|
18882
18940
|
});
|
|
18883
18941
|
});
|
|
@@ -19143,7 +19201,7 @@ import fastifyStatic from "@fastify/static";
|
|
|
19143
19201
|
import websocket from "@fastify/websocket";
|
|
19144
19202
|
import cookie from "@fastify/cookie";
|
|
19145
19203
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
19146
|
-
import { dirname as
|
|
19204
|
+
import { dirname as dirname14 } from "node:path";
|
|
19147
19205
|
import { existsSync as existsSync14 } from "node:fs";
|
|
19148
19206
|
|
|
19149
19207
|
// src/web-dir.ts
|
|
@@ -19207,7 +19265,7 @@ init_src();
|
|
|
19207
19265
|
import { execFile } from "node:child_process";
|
|
19208
19266
|
import { promisify } from "node:util";
|
|
19209
19267
|
import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync4, rmSync as rmSync2, mkdirSync as mkdirSync5 } from "node:fs";
|
|
19210
|
-
import { resolve as
|
|
19268
|
+
import { resolve as resolve8, dirname as dirname7, sep } from "node:path";
|
|
19211
19269
|
var exec = promisify(execFile);
|
|
19212
19270
|
async function listRepoDocs(repoDir) {
|
|
19213
19271
|
try {
|
|
@@ -19223,7 +19281,7 @@ async function listRepoDocs(repoDir) {
|
|
|
19223
19281
|
}
|
|
19224
19282
|
function docsDirOf(repoDir) {
|
|
19225
19283
|
try {
|
|
19226
|
-
const raw = readFileSync5(
|
|
19284
|
+
const raw = readFileSync5(resolve8(repoDir, "hanoman.config.json"), "utf8");
|
|
19227
19285
|
return zHanomanConfig.parse(JSON.parse(raw)).docsDir;
|
|
19228
19286
|
} catch {
|
|
19229
19287
|
return zHanomanConfig.parse({}).docsDir;
|
|
@@ -19231,7 +19289,7 @@ function docsDirOf(repoDir) {
|
|
|
19231
19289
|
}
|
|
19232
19290
|
function resolveIndex(repoDir, docsDir) {
|
|
19233
19291
|
const rel = `${docsDir}/README.md`;
|
|
19234
|
-
return existsSync4(
|
|
19292
|
+
return existsSync4(resolve8(repoDir, rel)) ? rel : "";
|
|
19235
19293
|
}
|
|
19236
19294
|
var catOf = (rel) => rel.includes("/") ? rel.slice(0, rel.lastIndexOf("/")) : ".";
|
|
19237
19295
|
var nameOf = (rel) => rel.includes("/") ? rel.slice(rel.lastIndexOf("/") + 1) : rel;
|
|
@@ -19242,7 +19300,7 @@ async function scanRepoDocs(repoDir) {
|
|
|
19242
19300
|
const index = resolveIndex(repoDir, docsDir);
|
|
19243
19301
|
const read = (rel) => {
|
|
19244
19302
|
try {
|
|
19245
|
-
return readFileSync5(
|
|
19303
|
+
return readFileSync5(resolve8(repoDir, rel), "utf8");
|
|
19246
19304
|
} catch {
|
|
19247
19305
|
return null;
|
|
19248
19306
|
}
|
|
@@ -19265,7 +19323,7 @@ async function scanRepoDocs(repoDir) {
|
|
|
19265
19323
|
function docAbsPath(repoDir, rel) {
|
|
19266
19324
|
if (!rel.endsWith(".md")) throw new Error("hanya file .md yang diizinkan");
|
|
19267
19325
|
if (rel.split("/").includes(".git")) throw new Error("tidak boleh menyentuh .git");
|
|
19268
|
-
const abs =
|
|
19326
|
+
const abs = resolve8(repoDir, rel);
|
|
19269
19327
|
if (abs !== repoDir && !abs.startsWith(repoDir + sep)) throw new Error("path keluar dari repo");
|
|
19270
19328
|
return abs;
|
|
19271
19329
|
}
|
|
@@ -19278,7 +19336,7 @@ function readDocFile(repoDir, rel) {
|
|
|
19278
19336
|
}
|
|
19279
19337
|
function writeDocFile(repoDir, rel, content) {
|
|
19280
19338
|
const abs = docAbsPath(repoDir, rel);
|
|
19281
|
-
mkdirSync5(
|
|
19339
|
+
mkdirSync5(dirname7(abs), { recursive: true });
|
|
19282
19340
|
writeFileSync3(abs, content);
|
|
19283
19341
|
}
|
|
19284
19342
|
function deleteDocFile(repoDir, rel) {
|
|
@@ -19768,7 +19826,7 @@ import { execFile as execFile4 } from "node:child_process";
|
|
|
19768
19826
|
import { promisify as promisify4 } from "node:util";
|
|
19769
19827
|
import { readFile as readFile2, mkdtemp, copyFile, rm } from "node:fs/promises";
|
|
19770
19828
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
19771
|
-
import { join as join5, resolve as
|
|
19829
|
+
import { join as join5, resolve as resolve9 } from "node:path";
|
|
19772
19830
|
var exec4 = promisify4(execFile4);
|
|
19773
19831
|
var GIT3 = { maxBuffer: 1 << 24 };
|
|
19774
19832
|
var MAX = 256 * 1024;
|
|
@@ -19777,7 +19835,7 @@ async function withTempIndex(wt, fn) {
|
|
|
19777
19835
|
const idx = (await exec4("git", ["rev-parse", "--git-path", "index"], { cwd: wt, ...GIT3 })).stdout.trim();
|
|
19778
19836
|
const dir2 = await mkdtemp(join5(tmpdir2(), "hanoman-idx-"));
|
|
19779
19837
|
const tmp = join5(dir2, "index");
|
|
19780
|
-
await copyFile(
|
|
19838
|
+
await copyFile(resolve9(wt, idx), tmp);
|
|
19781
19839
|
const env = { ...process.env, GIT_INDEX_FILE: tmp };
|
|
19782
19840
|
try {
|
|
19783
19841
|
await exec4("git", ["add", "-A", "-N"], { cwd: wt, env, ...GIT3 });
|
|
@@ -22666,7 +22724,7 @@ function renderDocPdf(text, name2, meta) {
|
|
|
22666
22724
|
});
|
|
22667
22725
|
const chunks = [];
|
|
22668
22726
|
doc.on("data", (c) => chunks.push(c));
|
|
22669
|
-
const done = new Promise((
|
|
22727
|
+
const done = new Promise((resolve16) => doc.on("end", () => resolve16(Buffer.concat(chunks))));
|
|
22670
22728
|
doc.font("Helvetica-Bold").fontSize(8).fillColor(BRASS).text(toWinAnsi(meta.eyebrow.toUpperCase()), { characterSpacing: 0.8 });
|
|
22671
22729
|
doc.moveDown(0.25);
|
|
22672
22730
|
doc.font("Helvetica-Bold").fontSize(17).fillColor(STRONG).text(toWinAnsi(name2.split("/").pop() ?? name2));
|
|
@@ -23283,7 +23341,7 @@ async function docs_default(app2) {
|
|
|
23283
23341
|
|
|
23284
23342
|
// src/routes/ide.ts
|
|
23285
23343
|
init_src2();
|
|
23286
|
-
import { basename } from "node:path";
|
|
23344
|
+
import { basename as basename2 } from "node:path";
|
|
23287
23345
|
import { spawn as spawn2 } from "node:child_process";
|
|
23288
23346
|
|
|
23289
23347
|
// src/services/git-remotes.ts
|
|
@@ -23351,14 +23409,14 @@ import { execFile as execFile6 } from "node:child_process";
|
|
|
23351
23409
|
import { promisify as promisify6 } from "node:util";
|
|
23352
23410
|
import { readFile as readFile3, writeFile, mkdir } from "node:fs/promises";
|
|
23353
23411
|
import { existsSync as existsSync7 } from "node:fs";
|
|
23354
|
-
import { resolve as
|
|
23412
|
+
import { resolve as resolve10, sep as sep2, dirname as dirname9 } from "node:path";
|
|
23355
23413
|
var exec6 = promisify6(execFile6);
|
|
23356
23414
|
var GIT5 = { maxBuffer: 1 << 24 };
|
|
23357
23415
|
var MAX2 = 256 * 1024;
|
|
23358
23416
|
var splitZ2 = (s2) => s2.split("\0").filter(Boolean);
|
|
23359
23417
|
function repoAbsPath(repoDir, rel) {
|
|
23360
23418
|
if (rel.split(/[\\/]/).includes(".git")) throw new Error("tidak boleh menyentuh .git");
|
|
23361
|
-
const abs =
|
|
23419
|
+
const abs = resolve10(repoDir, rel);
|
|
23362
23420
|
if (abs !== repoDir && !abs.startsWith(repoDir + sep2)) throw new Error("path keluar dari repo");
|
|
23363
23421
|
return abs;
|
|
23364
23422
|
}
|
|
@@ -23597,7 +23655,7 @@ async function commitFileDiff(repoDir, sha, rel) {
|
|
|
23597
23655
|
async function writeRepoFile(repoDir, rel, content) {
|
|
23598
23656
|
if (!repoDir) throw new Error("project tidak punya repoDir");
|
|
23599
23657
|
const abs = repoAbsPath(repoDir, rel);
|
|
23600
|
-
await mkdir(
|
|
23658
|
+
await mkdir(dirname9(abs), { recursive: true });
|
|
23601
23659
|
await writeFile(abs, content);
|
|
23602
23660
|
}
|
|
23603
23661
|
function validateGitOp(op) {
|
|
@@ -24093,7 +24151,7 @@ async function ide_default(app2) {
|
|
|
24093
24151
|
const fmt = q.format === "tar" ? "tar" : "zip";
|
|
24094
24152
|
const child = spawn2("git", ["archive", `--format=${fmt}`, "--end-of-options", ref], { cwd: repoDir });
|
|
24095
24153
|
reply.header("content-type", fmt === "zip" ? "application/zip" : "application/x-tar");
|
|
24096
|
-
reply.header("content-disposition", `attachment; filename="${
|
|
24154
|
+
reply.header("content-disposition", `attachment; filename="${basename2(repoDir)}-${ref.replace(/[^\w.-]/g, "_")}.${fmt}"`);
|
|
24097
24155
|
return reply.send(child.stdout);
|
|
24098
24156
|
});
|
|
24099
24157
|
app2.get("/projects/:id/commit/:sha", async (req, reply) => {
|
|
@@ -24245,22 +24303,22 @@ async function finishGraphOp(reply, id, repoDir, r, verb) {
|
|
|
24245
24303
|
CODE_STYLE_CLAUSE,
|
|
24246
24304
|
`${verb} via git graph project ${id}.`
|
|
24247
24305
|
].join("\n\n");
|
|
24248
|
-
const s2 = createSession(id, r.worktree, { id:
|
|
24306
|
+
const s2 = createSession(id, r.worktree, { id: basename2(r.worktree), model, effort, agent, prompt });
|
|
24249
24307
|
return { status: "conflict", sessionId: s2.id };
|
|
24250
24308
|
}
|
|
24251
24309
|
|
|
24252
24310
|
// src/routes/fs.ts
|
|
24253
24311
|
import { readdir } from "node:fs/promises";
|
|
24254
24312
|
import { homedir as homedir4 } from "node:os";
|
|
24255
|
-
import { resolve as
|
|
24313
|
+
import { resolve as resolve11, dirname as dirname10, join as join6 } from "node:path";
|
|
24256
24314
|
async function fs_default(app2) {
|
|
24257
24315
|
app2.get("/fs/browse", async (req, reply) => {
|
|
24258
24316
|
const q = req.query.path;
|
|
24259
|
-
const dir2 = q && q.trim() ?
|
|
24317
|
+
const dir2 = q && q.trim() ? resolve11(q.trim()) : homedir4();
|
|
24260
24318
|
try {
|
|
24261
24319
|
const ents = await readdir(dir2, { withFileTypes: true });
|
|
24262
24320
|
const entries = ents.filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => ({ name: e.name, path: join6(dir2, e.name) })).sort((a, b) => a.name.localeCompare(b.name));
|
|
24263
|
-
const parent =
|
|
24321
|
+
const parent = dirname10(dir2);
|
|
24264
24322
|
return { path: dir2, parent: parent === dir2 ? null : parent, entries };
|
|
24265
24323
|
} catch {
|
|
24266
24324
|
return reply.code(400).send({ error: `tak bisa membaca folder "${dir2}"` });
|
|
@@ -24418,11 +24476,11 @@ function installCommand(m, agent, shell = shellBin()) {
|
|
|
24418
24476
|
}
|
|
24419
24477
|
|
|
24420
24478
|
// src/services/session-worktree.ts
|
|
24421
|
-
import { resolve as
|
|
24479
|
+
import { resolve as resolve12, sep as sep3 } from "node:path";
|
|
24422
24480
|
function ownsWorktree(repoDir, cwd) {
|
|
24423
|
-
const base2 =
|
|
24424
|
-
const dir2 =
|
|
24425
|
-
const container =
|
|
24481
|
+
const base2 = resolve12(repoDir);
|
|
24482
|
+
const dir2 = resolve12(cwd);
|
|
24483
|
+
const container = resolve12(base2, ".worktrees");
|
|
24426
24484
|
return dir2 !== base2 && dir2 !== container && dir2.startsWith(container + sep3);
|
|
24427
24485
|
}
|
|
24428
24486
|
|
|
@@ -24884,7 +24942,7 @@ init_config2();
|
|
|
24884
24942
|
import { spawn as spawn3 } from "node:child_process";
|
|
24885
24943
|
import { mkdtempSync, rmSync as rmSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
24886
24944
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
24887
|
-
import { dirname as
|
|
24945
|
+
import { dirname as dirname11, join as join7 } from "node:path";
|
|
24888
24946
|
var sshBin = () => effectiveStr("HANOMAN_SSH_BIN") ?? "ssh";
|
|
24889
24947
|
function consoleArgv(t) {
|
|
24890
24948
|
return [
|
|
@@ -24934,14 +24992,14 @@ function sshExec(t, remoteCmd, opts = {}) {
|
|
|
24934
24992
|
SSH_ASKPASS_REQUIRE: "force",
|
|
24935
24993
|
HANOMAN_SSH_PASSWORD: opts.password
|
|
24936
24994
|
} : process.env;
|
|
24937
|
-
return new Promise((
|
|
24995
|
+
return new Promise((resolve16) => {
|
|
24938
24996
|
const p = spawn3(sshBin(), args, { stdio: ["pipe", "pipe", "pipe"], env });
|
|
24939
24997
|
let out3 = "";
|
|
24940
24998
|
const timer7 = setTimeout(() => p.kill("SIGKILL"), opts.timeoutMs ?? 6e4);
|
|
24941
24999
|
const done = (r) => {
|
|
24942
25000
|
clearTimeout(timer7);
|
|
24943
|
-
if (askpass) rmSync4(
|
|
24944
|
-
|
|
25001
|
+
if (askpass) rmSync4(dirname11(askpass), { recursive: true, force: true });
|
|
25002
|
+
resolve16(r);
|
|
24945
25003
|
};
|
|
24946
25004
|
p.stdout.on("data", (d) => {
|
|
24947
25005
|
out3 += d;
|
|
@@ -24965,12 +25023,12 @@ import { join as join9 } from "node:path";
|
|
|
24965
25023
|
|
|
24966
25024
|
// src/runner/deps.ts
|
|
24967
25025
|
import { existsSync as existsSync9 } from "node:fs";
|
|
24968
|
-
import { dirname as
|
|
25026
|
+
import { dirname as dirname12, join as join8 } from "node:path";
|
|
24969
25027
|
function repoRootFrom(startDir) {
|
|
24970
25028
|
let dir2 = startDir;
|
|
24971
25029
|
for (let i = 0; i < 8; i++) {
|
|
24972
25030
|
if (existsSync9(join8(dir2, "pnpm-workspace.yaml"))) return dir2;
|
|
24973
|
-
const parent =
|
|
25031
|
+
const parent = dirname12(dir2);
|
|
24974
25032
|
if (parent === dir2) break;
|
|
24975
25033
|
dir2 = parent;
|
|
24976
25034
|
}
|
|
@@ -25723,7 +25781,7 @@ init_src();
|
|
|
25723
25781
|
init_src();
|
|
25724
25782
|
init_config2();
|
|
25725
25783
|
import { readFileSync as readFileSync12 } from "node:fs";
|
|
25726
|
-
import { resolve as
|
|
25784
|
+
import { resolve as resolve13, dirname as dirname13 } from "node:path";
|
|
25727
25785
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
25728
25786
|
var UPDATE_COMMAND = "npm i -g hanoman@latest";
|
|
25729
25787
|
function composeUpdate(x) {
|
|
@@ -25748,8 +25806,8 @@ var lastFetchAt = 0;
|
|
|
25748
25806
|
var lastLatest = null;
|
|
25749
25807
|
var lastStatus = "unavailable";
|
|
25750
25808
|
function runningVersion() {
|
|
25751
|
-
const here =
|
|
25752
|
-
for (const p of [
|
|
25809
|
+
const here = dirname13(fileURLToPath3(import.meta.url));
|
|
25810
|
+
for (const p of [resolve13(here, "build-info.json"), resolve13(here, "../package.json")]) {
|
|
25753
25811
|
try {
|
|
25754
25812
|
const v = JSON.parse(readFileSync12(p, "utf8")).version;
|
|
25755
25813
|
if (typeof v === "string" && v) return v;
|
|
@@ -26099,7 +26157,7 @@ init_conflicts();
|
|
|
26099
26157
|
init_config2();
|
|
26100
26158
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
26101
26159
|
import { mkdir as mkdir2, writeFile as writeFile2, readFile as readFile4, unlink } from "node:fs/promises";
|
|
26102
|
-
import { join as join13, resolve as
|
|
26160
|
+
import { join as join13, resolve as resolve14 } from "node:path";
|
|
26103
26161
|
var EXT = {
|
|
26104
26162
|
"image/png": ".png",
|
|
26105
26163
|
"image/jpeg": ".jpg",
|
|
@@ -26109,7 +26167,7 @@ function extFor(mimeType) {
|
|
|
26109
26167
|
return EXT[mimeType] ?? ".bin";
|
|
26110
26168
|
}
|
|
26111
26169
|
function uploadDir() {
|
|
26112
|
-
return
|
|
26170
|
+
return resolve14(effectiveStr("HANOMAN_UPLOAD_DIR") ?? join13(process.cwd(), "data", "uploads"));
|
|
26113
26171
|
}
|
|
26114
26172
|
async function saveUpload(buf, mimeType) {
|
|
26115
26173
|
const dir2 = uploadDir();
|
|
@@ -26274,10 +26332,10 @@ import { randomUUID as randomUUID5 } from "node:crypto";
|
|
|
26274
26332
|
init_config2();
|
|
26275
26333
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
26276
26334
|
import { mkdir as mkdir3, writeFile as writeFile3, readFile as readFile5, unlink as unlink2 } from "node:fs/promises";
|
|
26277
|
-
import { join as join14, resolve as
|
|
26335
|
+
import { join as join14, resolve as resolve15, basename as basename3 } from "node:path";
|
|
26278
26336
|
var MAX_TRANSCRIPT_BYTES = 1024 * 1024;
|
|
26279
26337
|
function transcriptDir() {
|
|
26280
|
-
return
|
|
26338
|
+
return resolve15(effectiveStr("HANOMAN_TRANSCRIPT_DIR") ?? join14(process.cwd(), "data", "transcripts"));
|
|
26281
26339
|
}
|
|
26282
26340
|
function clamp(text) {
|
|
26283
26341
|
const buf = Buffer.from(text, "utf8");
|
|
@@ -26301,14 +26359,14 @@ async function saveTranscript(text) {
|
|
|
26301
26359
|
async function readTranscript(key) {
|
|
26302
26360
|
if (!key) return null;
|
|
26303
26361
|
try {
|
|
26304
|
-
return await readFile5(join14(transcriptDir(),
|
|
26362
|
+
return await readFile5(join14(transcriptDir(), basename3(key)), "utf8");
|
|
26305
26363
|
} catch {
|
|
26306
26364
|
return null;
|
|
26307
26365
|
}
|
|
26308
26366
|
}
|
|
26309
26367
|
async function deleteTranscript(key) {
|
|
26310
26368
|
if (!key) return;
|
|
26311
|
-
await unlink2(join14(transcriptDir(),
|
|
26369
|
+
await unlink2(join14(transcriptDir(), basename3(key))).catch(() => {
|
|
26312
26370
|
});
|
|
26313
26371
|
}
|
|
26314
26372
|
|
|
@@ -27696,7 +27754,7 @@ function leadFailureReason(agent, timeoutMs, err, stdout, stderr) {
|
|
|
27696
27754
|
function think(prompt, o) {
|
|
27697
27755
|
const bin = binFor(o.agent);
|
|
27698
27756
|
const args = leadArgv({ agent: o.agent, model: o.model, effort: o.effort, prompt });
|
|
27699
|
-
return new Promise((
|
|
27757
|
+
return new Promise((resolve16, reject2) => {
|
|
27700
27758
|
const child = execFile9(bin, args, {
|
|
27701
27759
|
cwd: o.cwd,
|
|
27702
27760
|
timeout: o.timeoutMs,
|
|
@@ -27709,7 +27767,7 @@ function think(prompt, o) {
|
|
|
27709
27767
|
reject2(new Error(leadFailureReason(o.agent, o.timeoutMs, err, stdout, stderr)));
|
|
27710
27768
|
return;
|
|
27711
27769
|
}
|
|
27712
|
-
|
|
27770
|
+
resolve16(stdout);
|
|
27713
27771
|
});
|
|
27714
27772
|
child.stdin?.end();
|
|
27715
27773
|
});
|
|
@@ -27746,9 +27804,9 @@ function acquire(cap, waitMs) {
|
|
|
27746
27804
|
return Promise.resolve();
|
|
27747
27805
|
}
|
|
27748
27806
|
const startedAt = Date.now();
|
|
27749
|
-
return new Promise((
|
|
27807
|
+
return new Promise((resolve16, reject2) => {
|
|
27750
27808
|
const w = {
|
|
27751
|
-
grant:
|
|
27809
|
+
grant: resolve16,
|
|
27752
27810
|
deny: reject2,
|
|
27753
27811
|
timer: setTimeout(() => {
|
|
27754
27812
|
const i = queue.indexOf(w);
|
|
@@ -29812,7 +29870,7 @@ function issuesFromRest(raw) {
|
|
|
29812
29870
|
}
|
|
29813
29871
|
var GH_FIELDS = "number,title,body,author,labels,url,state,createdAt,updatedAt";
|
|
29814
29872
|
var API2 = "https://api.github.com";
|
|
29815
|
-
var defaultRunGh = (args, env) => new Promise((
|
|
29873
|
+
var defaultRunGh = (args, env) => new Promise((resolve16, reject2) => {
|
|
29816
29874
|
execFile11(
|
|
29817
29875
|
args[0],
|
|
29818
29876
|
args.slice(1),
|
|
@@ -29820,7 +29878,7 @@ var defaultRunGh = (args, env) => new Promise((resolve15, reject2) => {
|
|
|
29820
29878
|
(err, stdout, stderr) => {
|
|
29821
29879
|
const e = err;
|
|
29822
29880
|
if (e && (e.code === "ENOENT" || e.code === "EACCES")) return reject2(e);
|
|
29823
|
-
|
|
29881
|
+
resolve16({ code: err ? Number(err.code ?? 1) : 0, stdout, stderr });
|
|
29824
29882
|
}
|
|
29825
29883
|
);
|
|
29826
29884
|
});
|
|
@@ -31359,7 +31417,7 @@ var PUBLIC = /* @__PURE__ */ new Set([
|
|
|
31359
31417
|
"GET /api/agent-integration.md"
|
|
31360
31418
|
]);
|
|
31361
31419
|
function buildApp({ requireAuth = true, agentDocFile } = {}) {
|
|
31362
|
-
const docFile = agentDocFile !== void 0 ? agentDocFile : pickGuideFile(
|
|
31420
|
+
const docFile = agentDocFile !== void 0 ? agentDocFile : pickGuideFile(dirname14(fileURLToPath4(import.meta.url)), process.env, existsSync14);
|
|
31363
31421
|
const app2 = Fastify({ logger: false, trustProxy: true });
|
|
31364
31422
|
app2.addContentTypeParser("application/json", { parseAs: "string" }, (_req, body, done) => {
|
|
31365
31423
|
if (!body) return done(null, void 0);
|
|
@@ -31450,7 +31508,7 @@ function buildApp({ requireAuth = true, agentDocFile } = {}) {
|
|
|
31450
31508
|
await api.register(client_accounts_default);
|
|
31451
31509
|
}, { prefix: "/api" });
|
|
31452
31510
|
if (process.env.NODE_ENV === "production") {
|
|
31453
|
-
const dist = pickWebDir(
|
|
31511
|
+
const dist = pickWebDir(dirname14(fileURLToPath4(import.meta.url)), process.env, existsSync14);
|
|
31454
31512
|
if (dist) {
|
|
31455
31513
|
app2.register(fastifyStatic, { root: dist });
|
|
31456
31514
|
app2.setNotFoundHandler((req, reply) => req.url.startsWith("/api") ? reply.code(404).send({ error: "not found" }) : reply.sendFile("index.html"));
|