hanoman 0.1.27 → 0.1.29

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.1.27",
3
- "sha": "8a20917",
4
- "builtAt": "2026-08-13T09:09:39.069Z"
2
+ "version": "0.1.29",
3
+ "sha": "a8b5c1a",
4
+ "builtAt": "2026-08-13T14:32:58.079Z"
5
5
  }
package/dist/cli.js CHANGED
@@ -5649,6 +5649,9 @@ var init_api = __esm({
5649
5649
  // SPEC-233 · drop commit isolasi
5650
5650
  fsBrowse: (path) => `${API}/fs/browse${path ? `?path=${encodeURIComponent(path)}` : ""}`,
5651
5651
  terminalSessions: `${API}/terminal/sessions`,
5652
+ // SPEC-742 · ADR-0116 · pembersihan worktree yang masih tertunda sesudah sesi ditutup. Di bawah
5653
+ // prefix /terminal supaya ikut capability `sessions` yang sudah ada (cermin sessionHistory).
5654
+ terminalCleanups: `${API}/terminal/cleanups`,
5652
5655
  terminalSession: (id) => `${API}/terminal/sessions/${id}`,
5653
5656
  terminalSteer: (id) => `${API}/terminal/sessions/${id}/steer`,
5654
5657
  terminalInterrupt: (id) => `${API}/terminal/sessions/${id}/interrupt`,
@@ -7381,7 +7384,7 @@ var init_paths = __esm({
7381
7384
 
7382
7385
  // ../runner/src/skills.ts
7383
7386
  import { homedir as homedir2 } from "node:os";
7384
- import { join as join2 } from "node:path";
7387
+ import { basename, dirname as dirname2, join as join2, resolve as resolve2 } from "node:path";
7385
7388
  import { existsSync, readdirSync, readFileSync } from "node:fs";
7386
7389
  function agentSkillHome(agent, env = process.env, osHome = homedir2()) {
7387
7390
  const own = (agent === "codex" ? env.HANOMAN_CODEX_HOME : env.HANOMAN_CLAUDE_HOME)?.trim();
@@ -7392,6 +7395,9 @@ function agentSkillHome(agent, env = process.env, osHome = homedir2()) {
7392
7395
  }
7393
7396
  return join2(osHome, agent === "codex" ? ".codex" : ".claude");
7394
7397
  }
7398
+ function agentsSkillHome(env = process.env, osHome = homedir2()) {
7399
+ return env.HANOMAN_AGENTS_HOME?.trim() || join2(osHome, ".agents");
7400
+ }
7395
7401
  function dirsIn(dir) {
7396
7402
  try {
7397
7403
  return readdirSync(dir, { withFileTypes: true }).filter((e) => (e.isDirectory() || e.isSymbolicLink()) && !e.name.startsWith(".")).map((e) => e.name);
@@ -7406,8 +7412,51 @@ function readJson(file) {
7406
7412
  return null;
7407
7413
  }
7408
7414
  }
7409
- function skillsUnder(dir, pkg) {
7410
- return dirsIn(dir).filter((name) => existsSync(join2(dir, name, "SKILL.md"))).map((name) => ({ id: pkg ? `${pkg}:${name}` : name, name, pkg, dir: join2(dir, name) }));
7415
+ function isSkillDir(dir) {
7416
+ return existsSync(join2(dir, "SKILL.md"));
7417
+ }
7418
+ function asSkill(dir, pkg, name = basename(dir)) {
7419
+ return { id: pkg ? `${pkg}:${name}` : name, name, pkg, dir };
7420
+ }
7421
+ function skillsUnder(dir, pkg, depth = 2) {
7422
+ const out = [];
7423
+ for (const name of dirsIn(dir)) {
7424
+ const sub = join2(dir, name);
7425
+ if (isSkillDir(sub)) out.push(asSkill(sub, pkg, name));
7426
+ else if (depth > 1) out.push(...skillsUnder(sub, pkg, depth - 1));
7427
+ }
7428
+ return out;
7429
+ }
7430
+ function manifestSkills(installPath, pkg) {
7431
+ for (const marker of [".claude-plugin", ".codex-plugin"]) {
7432
+ const j = readJson(join2(installPath, marker, "plugin.json"));
7433
+ const declared = j?.skills;
7434
+ if (!Array.isArray(declared)) continue;
7435
+ const out = [];
7436
+ for (const rel of declared) {
7437
+ if (typeof rel !== "string" || !rel) continue;
7438
+ const p = resolve2(installPath, rel);
7439
+ const dir = basename(p) === "SKILL.md" ? dirname2(p) : p;
7440
+ if (isSkillDir(dir)) out.push(asSkill(dir, pkg));
7441
+ }
7442
+ if (out.length) return out;
7443
+ }
7444
+ return [];
7445
+ }
7446
+ function pluginSkills(installPath, pkg) {
7447
+ const declared = manifestSkills(installPath, pkg);
7448
+ return declared.length ? declared : skillsUnder(join2(installPath, "skills"), pkg);
7449
+ }
7450
+ function lockPluginNames(agentsHome) {
7451
+ const out = /* @__PURE__ */ new Map();
7452
+ const j = readJson(join2(agentsHome, ".skill-lock.json"));
7453
+ const skills = j?.skills;
7454
+ if (!skills || typeof skills !== "object") return out;
7455
+ for (const [name, entry] of Object.entries(skills)) {
7456
+ const pkg = entry?.pluginName;
7457
+ if (typeof pkg === "string" && pkg.trim()) out.set(name, pkg.trim());
7458
+ }
7459
+ return out;
7411
7460
  }
7412
7461
  function splitPluginKey(key) {
7413
7462
  const at = key.lastIndexOf("@");
@@ -7487,11 +7536,23 @@ function scanAgentSkills(agent, env = process.env, osHome = homedir2()) {
7487
7536
  add(userDir, skillsUnder(userDir, null));
7488
7537
  for (const r of [...manifestRoots(home), ...cacheRoots(home)]) {
7489
7538
  if (disabled.has(`${r.pkg}@${r.marketplace}`)) continue;
7490
- const dir = join2(r.dir, "skills");
7491
- const found = skillsUnder(dir, r.pkg);
7539
+ const found = pluginSkills(r.dir, r.pkg);
7492
7540
  if (!found.length) continue;
7493
7541
  packages.add(r.pkg);
7494
- add(dir, found);
7542
+ add(join2(r.dir, "skills"), found);
7543
+ }
7544
+ if (agent === "codex") {
7545
+ const agentsHome = agentsSkillHome(env, osHome);
7546
+ const dir = join2(agentsHome, "skills");
7547
+ const names = lockPluginNames(agentsHome);
7548
+ const flat = skillsUnder(dir, null);
7549
+ const withPkg = flat.flatMap((s2) => {
7550
+ const pkg = names.get(s2.name);
7551
+ if (!pkg) return [s2];
7552
+ packages.add(pkg);
7553
+ return [asSkill(s2.dir, pkg, s2.name), s2];
7554
+ });
7555
+ add(dir, withPkg);
7495
7556
  }
7496
7557
  return { agent, home, roots, skills, packages: [...packages] };
7497
7558
  }
@@ -7531,9 +7592,9 @@ var init_src2 = __esm({
7531
7592
  });
7532
7593
 
7533
7594
  // src/layout.ts
7534
- import { join as join3, resolve as resolve2 } from "node:path";
7595
+ import { join as join3, resolve as resolve3 } from "node:path";
7535
7596
  function resolveLayout(distDir2, exists) {
7536
- const pkg = resolve2(distDir2, "..");
7597
+ const pkg = resolve3(distDir2, "..");
7537
7598
  if (exists(join3(pkg, "prisma", "schema.prisma"))) {
7538
7599
  return {
7539
7600
  root: pkg,
@@ -7542,7 +7603,7 @@ function resolveLayout(distDir2, exists) {
7542
7603
  web: exists(join3(pkg, "web")) ? join3(pkg, "web") : null
7543
7604
  };
7544
7605
  }
7545
- const repo = resolve2(distDir2, "../..");
7606
+ const repo = resolve3(distDir2, "../..");
7546
7607
  if (exists(join3(repo, "server", "prisma", "schema.prisma"))) {
7547
7608
  return {
7548
7609
  root: repo,
@@ -7647,7 +7708,7 @@ __export(start_exports, {
7647
7708
  import { spawn, execFileSync as execFileSync2 } from "node:child_process";
7648
7709
  import { createRequire } from "node:module";
7649
7710
  import { existsSync as existsSync2, mkdirSync, readdirSync as readdirSync2, statSync, chmodSync } from "node:fs";
7650
- import { dirname as dirname2, join as join4, resolve as resolvePath } from "node:path";
7711
+ import { dirname as dirname3, join as join4, resolve as resolvePath } from "node:path";
7651
7712
  import { fileURLToPath } from "node:url";
7652
7713
  function parseStartArgs(argv) {
7653
7714
  const out = { port: null, host: null, db: null, migrate: true };
@@ -7688,7 +7749,7 @@ function parseStartArgs(argv) {
7688
7749
  return out;
7689
7750
  }
7690
7751
  function distDir() {
7691
- return dirname2(fileURLToPath(import.meta.url));
7752
+ return dirname3(fileURLToPath(import.meta.url));
7692
7753
  }
7693
7754
  function runPrisma(args, dbUrl) {
7694
7755
  const prismaCli = prismaCliPath(createRequire(import.meta.url).resolve);
@@ -7760,7 +7821,7 @@ function ensureSpawnHelpersExecutable(paths2, ops) {
7760
7821
  function repairSpawnHelper(ctx) {
7761
7822
  let ptyDir;
7762
7823
  try {
7763
- ptyDir = dirname2(createRequire(import.meta.url).resolve("node-pty/package.json"));
7824
+ ptyDir = dirname3(createRequire(import.meta.url).resolve("node-pty/package.json"));
7764
7825
  } catch {
7765
7826
  return;
7766
7827
  }
@@ -7823,7 +7884,7 @@ async function start(argv, ctx) {
7823
7884
  let dbUrl;
7824
7885
  try {
7825
7886
  layout = resolveLayout(distDir(), existsSync2);
7826
- dbUrl = opts.db ? `file:${resolvePath(opts.db)}` : resolveDbUrl(ctx.env, dirname2(layout.schema));
7887
+ dbUrl = opts.db ? `file:${resolvePath(opts.db)}` : resolveDbUrl(ctx.env, dirname3(layout.schema));
7827
7888
  } catch (e) {
7828
7889
  ctx.stderr(`${e.message}
7829
7890
  `);
@@ -7834,7 +7895,7 @@ async function start(argv, ctx) {
7834
7895
  `);
7835
7896
  const home = resolveHome(ctx.env);
7836
7897
  mkdirSync(home, { recursive: true });
7837
- mkdirSync(dirname2(dbFilePath(dbUrl)), { recursive: true });
7898
+ mkdirSync(dirname3(dbFilePath(dbUrl)), { recursive: true });
7838
7899
  if (!existsSync2(layout.server)) {
7839
7900
  ctx.stderr(`hanoman: bundle server tak ada di ${layout.server} \u2014 jalankan \`pnpm build\` dulu
7840
7901
  `);
@@ -7920,7 +7981,7 @@ __export(doctor_exports, {
7920
7981
  });
7921
7982
  import { execFileSync as execFileSync3 } from "node:child_process";
7922
7983
  import { accessSync, constants, existsSync as existsSync3 } from "node:fs";
7923
- import { dirname as dirname3 } from "node:path";
7984
+ import { dirname as dirname4 } from "node:path";
7924
7985
  function doctorReport(p) {
7925
7986
  const major = Number(/^v?(\d+)/.exec(p.node)?.[1] ?? 0);
7926
7987
  const rows = [
@@ -7965,7 +8026,7 @@ async function doctor(_argv, ctx) {
7965
8026
  let db;
7966
8027
  try {
7967
8028
  layout = resolveLayout(distDir(), existsSync3);
7968
- db = dbFilePath(resolveDbUrl(ctx.env, dirname3(layout.schema)));
8029
+ db = dbFilePath(resolveDbUrl(ctx.env, dirname4(layout.schema)));
7969
8030
  } catch (e) {
7970
8031
  ctx.stderr(`${e.message}
7971
8032
  `);
@@ -7974,7 +8035,7 @@ async function doctor(_argv, ctx) {
7974
8035
  const home = resolveHome(ctx.env);
7975
8036
  let homeWritable = false;
7976
8037
  try {
7977
- accessSync(existsSync3(home) ? home : dirname3(home), constants.W_OK);
8038
+ accessSync(existsSync3(home) ? home : dirname4(home), constants.W_OK);
7978
8039
  homeWritable = true;
7979
8040
  } catch {
7980
8041
  }
@@ -17379,14 +17440,14 @@ function inputRequiredRoundsExceededMessage(method, maxRounds) {
17379
17440
  return `Multi-round-trip request '${method}' still required input after ${maxRounds} rounds (inputRequired.maxRounds)`;
17380
17441
  }
17381
17442
  function sleep(ms, signal) {
17382
- return new Promise((resolve3, reject) => {
17443
+ return new Promise((resolve4, reject) => {
17383
17444
  if (signal?.aborted) {
17384
17445
  reject(signal.reason instanceof SdkError ? signal.reason : new SdkError(SdkErrorCode.RequestTimeout, String(signal.reason)));
17385
17446
  return;
17386
17447
  }
17387
17448
  const timer = setTimeout(() => {
17388
17449
  signal?.removeEventListener("abort", onAbort);
17389
- resolve3();
17450
+ resolve4();
17390
17451
  }, ms);
17391
17452
  const onAbort = () => {
17392
17453
  clearTimeout(timer);
@@ -19197,7 +19258,7 @@ var init_src_CX2iR2pK = __esm({
19197
19258
  const flowStartedAt = Date.now();
19198
19259
  let onAbort;
19199
19260
  let cleanupMessageId;
19200
- return new Promise((resolve3, reject) => {
19261
+ return new Promise((resolve4, reject) => {
19201
19262
  const earlyReject = (error2) => {
19202
19263
  reject(error2);
19203
19264
  };
@@ -19265,7 +19326,7 @@ var init_src_CX2iR2pK = __esm({
19265
19326
  }
19266
19327
  if (decoded.kind === "invalid") return reject(decoded.error);
19267
19328
  if (decoded.kind === "input_required") {
19268
- if (options?.allowInputRequired === true) return resolve3(manualInputRequiredValue(decoded));
19329
+ if (options?.allowInputRequired === true) return resolve4(manualInputRequiredValue(decoded));
19269
19330
  const flow = {
19270
19331
  codec,
19271
19332
  request,
@@ -19277,11 +19338,11 @@ var init_src_CX2iR2pK = __esm({
19277
19338
  params
19278
19339
  }, resultSchema, legOptions)
19279
19340
  };
19280
- return resolve3(this._resolveNonCompleteResult(decoded, flow));
19341
+ return resolve4(this._resolveNonCompleteResult(decoded, flow));
19281
19342
  }
19282
19343
  const result = decoded.result;
19283
19344
  validateStandardSchema(resultSchema, result).then((parseResult) => {
19284
- if (parseResult.success) resolve3(parseResult.data);
19345
+ if (parseResult.success) resolve4(parseResult.data);
19285
19346
  else reject(new SdkError(SdkErrorCode.InvalidResult, `Invalid result for ${request.method}: ${parseResult.error}`));
19286
19347
  }, reject);
19287
19348
  });
@@ -22097,7 +22158,7 @@ var init_ajvProvider_CEoC_sr = __esm({
22097
22158
  ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, ref);
22098
22159
  const schOrFunc = root.refs[ref];
22099
22160
  if (schOrFunc) return schOrFunc;
22100
- let _sch = resolve3.call(this, root, ref);
22161
+ let _sch = resolve4.call(this, root, ref);
22101
22162
  if (_sch === void 0) {
22102
22163
  const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
22103
22164
  const { schemaId } = this.opts;
@@ -22123,7 +22184,7 @@ var init_ajvProvider_CEoC_sr = __esm({
22123
22184
  function sameSchemaEnv(s1, s2) {
22124
22185
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
22125
22186
  }
22126
- function resolve3(root, ref) {
22187
+ function resolve4(root, ref) {
22127
22188
  let sch;
22128
22189
  while (typeof (sch = this.refs[ref]) == "string") ref = sch;
22129
22190
  return sch || this.schemas[ref] || resolveSchema.call(this, root, ref);
@@ -22573,7 +22634,7 @@ var init_ajvProvider_CEoC_sr = __esm({
22573
22634
  else if (typeof uri === "object") uri = parse4(serialize(uri, options), options);
22574
22635
  return uri;
22575
22636
  }
22576
- function resolve3(baseURI, relativeURI, options) {
22637
+ function resolve4(baseURI, relativeURI, options) {
22577
22638
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
22578
22639
  const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
22579
22640
  schemelessOptions.skipEscape = true;
@@ -22747,7 +22808,7 @@ var init_ajvProvider_CEoC_sr = __esm({
22747
22808
  const fastUri = {
22748
22809
  SCHEMES,
22749
22810
  normalize,
22750
- resolve: resolve3,
22811
+ resolve: resolve4,
22751
22812
  resolveComponent,
22752
22813
  equal,
22753
22814
  serialize,
@@ -28439,7 +28500,7 @@ var init_stdio = __esm({
28439
28500
  }
28440
28501
  send(message) {
28441
28502
  if (this._closed) return Promise.reject(/* @__PURE__ */ new Error("StdioServerTransport is closed"));
28442
- return new Promise((resolve3, reject) => {
28503
+ return new Promise((resolve4, reject) => {
28443
28504
  const json = serializeMessage(message);
28444
28505
  let settled = false;
28445
28506
  const onError = (error2) => {
@@ -28454,14 +28515,14 @@ var init_stdio = __esm({
28454
28515
  settled = true;
28455
28516
  this._stdout.off("error", onError);
28456
28517
  this._stdout.off("drain", onDrain);
28457
- resolve3();
28518
+ resolve4();
28458
28519
  };
28459
28520
  this._stdout.once("error", onError);
28460
28521
  if (this._stdout.write(json)) {
28461
28522
  if (settled) return;
28462
28523
  settled = true;
28463
28524
  this._stdout.off("error", onError);
28464
- resolve3();
28525
+ resolve4();
28465
28526
  } else if (!settled) this._stdout.once("drain", onDrain);
28466
28527
  });
28467
28528
  }
@@ -28515,14 +28576,14 @@ var init_stdio = __esm({
28515
28576
  */
28516
28577
  async whenRequestsAnswered(timeoutMs) {
28517
28578
  if (this._closed || this._pendingRequests.size === 0) return true;
28518
- return await new Promise((resolve3) => {
28579
+ return await new Promise((resolve4) => {
28519
28580
  const waiter = () => {
28520
28581
  clearTimeout(timer);
28521
- resolve3(true);
28582
+ resolve4(true);
28522
28583
  };
28523
28584
  const timer = setTimeout(() => {
28524
28585
  this._drainWaiters = this._drainWaiters.filter((pending) => pending !== waiter);
28525
- resolve3(false);
28586
+ resolve4(false);
28526
28587
  }, timeoutMs);
28527
28588
  this._drainWaiters.push(waiter);
28528
28589
  });
@@ -28817,9 +28878,9 @@ async function mcp(argv, ctx) {
28817
28878
  await handle.close();
28818
28879
  return 0;
28819
28880
  }
28820
- await new Promise((resolve3) => {
28821
- process.stdin.once("close", resolve3);
28822
- process.stdin.once("end", resolve3);
28881
+ await new Promise((resolve4) => {
28882
+ process.stdin.once("close", resolve4);
28883
+ process.stdin.once("end", resolve4);
28823
28884
  });
28824
28885
  return 0;
28825
28886
  }
@@ -28857,7 +28918,7 @@ __export(migrate_pg_exports, {
28857
28918
  parseMigrateArgs: () => parseMigrateArgs
28858
28919
  });
28859
28920
  import { existsSync as existsSync4 } from "node:fs";
28860
- import { dirname as dirname4, resolve as resolvePath2 } from "node:path";
28921
+ import { dirname as dirname5, resolve as resolvePath2 } from "node:path";
28861
28922
  function coerceInt8(rows, fields, model) {
28862
28923
  const cols = fields.filter((f) => f.dataTypeID === INT8_OID).map((f) => f.name);
28863
28924
  if (!cols.length) return rows;
@@ -28925,7 +28986,7 @@ async function migratePg(argv, ctx) {
28925
28986
  let dbUrl;
28926
28987
  try {
28927
28988
  layout = resolveLayout(distDir(), existsSync4);
28928
- dbUrl = opts.to ? `file:${resolvePath2(opts.to)}` : resolveDbUrl(ctx.env, dirname4(layout.schema));
28989
+ dbUrl = opts.to ? `file:${resolvePath2(opts.to)}` : resolveDbUrl(ctx.env, dirname5(layout.schema));
28929
28990
  } catch (e) {
28930
28991
  ctx.stderr(`${e.message}
28931
28992
  `);
@@ -29392,7 +29453,7 @@ __export(pack_exports, {
29392
29453
  default: () => pack
29393
29454
  });
29394
29455
  import { cpSync, existsSync as existsSync8, mkdirSync as mkdirSync2, readFileSync as readFileSync8, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
29395
- import { dirname as dirname5, join as join12 } from "node:path";
29456
+ import { dirname as dirname6, join as join12 } from "node:path";
29396
29457
  function depVersions(repo) {
29397
29458
  const read = (p) => JSON.parse(readFileSync8(join12(repo, p), "utf8"));
29398
29459
  const server = read("server/package.json"), cli = read("cli/package.json");
@@ -29442,7 +29503,7 @@ async function pack(argv, ctx) {
29442
29503
  return 1;
29443
29504
  }
29444
29505
  const dest = join12(out, item.to);
29445
- mkdirSync2(dirname5(dest), { recursive: true });
29506
+ mkdirSync2(dirname6(dest), { recursive: true });
29446
29507
  cpSync(item.from, dest, item.dir ? { recursive: true } : {});
29447
29508
  }
29448
29509
  writeFileSync2(join12(out, "bin/hanoman.mjs"), BIN_SHIM);