@livx.cc/agentx 0.99.5 → 0.99.6

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/cli.js CHANGED
@@ -1959,7 +1959,7 @@ var init_tools_shell = __esm({
1959
1959
  // cli/cli.ts
1960
1960
  import { createInterface } from "readline/promises";
1961
1961
  import { existsSync as existsSync9, readFileSync as readFileSync8, appendFileSync, mkdirSync as mkdirSync11, writeFileSync as writeFileSync9, readdirSync as readdirSync4, statSync as statSync4, unlinkSync as unlinkSync5 } from "fs";
1962
- import { homedir as homedir9, tmpdir as tmpdir3 } from "os";
1962
+ import { homedir as homedir10, tmpdir as tmpdir3 } from "os";
1963
1963
  import { spawnSync as spawnSync6 } from "child_process";
1964
1964
 
1965
1965
  // cli/clipboard.ts
@@ -8433,22 +8433,29 @@ ${formatDiff(ops)}`);
8433
8433
  import { execFile as execFile3 } from "child_process";
8434
8434
  import { promisify } from "util";
8435
8435
  import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync7 } from "fs";
8436
- import { join as join9, resolve as resolve2, sep as sep2 } from "path";
8436
+ import { homedir as homedir6 } from "os";
8437
+ import { join as join9, resolve as resolve2, sep as sep2, parse as parsePath } from "path";
8437
8438
  var log20 = forComponent("checkpoints");
8438
8439
  var exec = promisify(execFile3);
8439
8440
  var DEFAULT_EXCLUDE = [".agent/", ".git/", "node_modules/", "dist/", "build/", ".next/", "target/", ".venv/", "__pycache__/", "*.log"];
8441
+ function isBroadRoot(p) {
8442
+ const abs = resolve2(p);
8443
+ return abs === resolve2(homedir6()) || abs === parsePath(abs).root;
8444
+ }
8440
8445
  var ShadowRepo = class {
8441
8446
  // undefined = unprobed; false = git/this root unusable
8442
- constructor(workTree, gitDir, exclude, git2) {
8447
+ constructor(workTree, gitDir, exclude, git2, timeoutMs) {
8443
8448
  this.workTree = workTree;
8444
8449
  this.gitDir = gitDir;
8445
8450
  this.exclude = exclude;
8446
8451
  this.git = git2;
8452
+ this.timeoutMs = timeoutMs;
8447
8453
  }
8448
8454
  workTree;
8449
8455
  gitDir;
8450
8456
  exclude;
8451
8457
  git;
8458
+ timeoutMs;
8452
8459
  ready;
8453
8460
  /** Absolute work-tree root — used to route force-tracked paths to the repo that contains them. */
8454
8461
  get root() {
@@ -8457,7 +8464,9 @@ var ShadowRepo = class {
8457
8464
  async run(...args) {
8458
8465
  const { stdout } = await exec(this.git, ["-c", "core.hooksPath=/dev/null", ...args], {
8459
8466
  env: { ...process.env, GIT_DIR: this.gitDir, GIT_WORK_TREE: this.workTree },
8460
- maxBuffer: 64 * 1024 * 1024
8467
+ maxBuffer: 64 * 1024 * 1024,
8468
+ timeout: this.timeoutMs,
8469
+ killSignal: "SIGKILL"
8461
8470
  });
8462
8471
  return stdout;
8463
8472
  }
@@ -8570,7 +8579,7 @@ var GitCheckpoints = class {
8570
8579
  constructor(options) {
8571
8580
  this.options = { ...new GitCheckpointsOptions(), ...options };
8572
8581
  this.session = this.options.sessionId;
8573
- this.repos = this.roots().map((r) => new ShadowRepo(r.workTree, r.gitDir, this.options.exclude, this.options.git));
8582
+ this.repos = this.roots().map((r) => new ShadowRepo(r.workTree, r.gitDir, this.options.exclude, this.options.git, this.options.opTimeoutMs));
8574
8583
  this.caches = this.repos.map(() => []);
8575
8584
  }
8576
8585
  ref() {
@@ -8595,14 +8604,23 @@ var GitCheckpoints = class {
8595
8604
  const usable = [];
8596
8605
  const caches = [];
8597
8606
  const cutoff = Math.floor(Date.now() / 1e3) - this.options.retainDays * 86400;
8607
+ let gitFailed = false;
8598
8608
  for (const r of this.repos) {
8599
- if (!await r.init()) continue;
8609
+ if (isBroadRoot(r.root)) {
8610
+ process.stderr.write(`\x1B[2m checkpoints: '${r.root}' is too broad (home/root) \u2014 file rewind disabled here\x1B[0m
8611
+ `);
8612
+ continue;
8613
+ }
8614
+ if (!await r.init()) {
8615
+ gitFailed = true;
8616
+ continue;
8617
+ }
8600
8618
  await r.point(this.ref());
8601
8619
  await r.prune(cutoff, this.ref());
8602
8620
  usable.push(r);
8603
8621
  caches.push([]);
8604
8622
  }
8605
- if (!usable.length && this.repos.length)
8623
+ if (!usable.length && gitFailed)
8606
8624
  process.stderr.write("\x1B[2m checkpoints: git unavailable \u2014 file rewind disabled (conversation rewind still works)\x1B[0m\n");
8607
8625
  this.repos = usable;
8608
8626
  this.caches = caches;
@@ -8618,15 +8636,28 @@ var GitCheckpoints = class {
8618
8636
  const msg = sanitizeLabel(label, 72) || "(turn)";
8619
8637
  let slow;
8620
8638
  if (!this.snapshotted) slow = setTimeout(() => process.stderr.write("\x1B[2m checkpointing initial workspace snapshot\u2026\x1B[0m\n"), 1500);
8639
+ const survivors = [], survivorCaches = [];
8621
8640
  for (let i = 0; i < this.repos.length; i++) {
8622
8641
  const forced = [...this.forced].filter((p) => this.repoIndexFor(p) === i);
8623
8642
  try {
8624
8643
  await this.repos[i].commit(msg, forced);
8644
+ survivors.push(this.repos[i]);
8645
+ survivorCaches.push(this.caches[i] ?? []);
8625
8646
  } catch (e) {
8626
- log20.debug("checkpoint commit failed", e);
8647
+ const timedOut = e?.killed;
8648
+ if (!this.snapshotted && timedOut) {
8649
+ process.stderr.write(`\x1B[2m checkpoints: '${this.repos[i].root}' too large to snapshot in ${Math.round(this.options.opTimeoutMs / 1e3)}s \u2014 file rewind disabled here\x1B[0m
8650
+ `);
8651
+ } else {
8652
+ log20.debug("checkpoint commit failed", e);
8653
+ survivors.push(this.repos[i]);
8654
+ survivorCaches.push(this.caches[i] ?? []);
8655
+ }
8627
8656
  }
8628
8657
  }
8629
8658
  if (slow) clearTimeout(slow);
8659
+ this.repos = survivors;
8660
+ this.caches = survivorCaches;
8630
8661
  this.snapshotted = true;
8631
8662
  }
8632
8663
  /** Index of the repo whose work-tree contains `abs` (longest-prefix wins for nested roots); -1 if none. */
@@ -8714,13 +8745,15 @@ var GitCheckpointsOptions = class {
8714
8745
  retainDays = 30;
8715
8746
  /** Paths the shadow repos always ignore (heavy/derived/VCS), beyond the user's own .gitignore. */
8716
8747
  exclude = [...DEFAULT_EXCLUDE];
8748
+ /** Per-git-op wall-clock cap (ms). A root that can't snapshot within this is dropped, not left to hang. */
8749
+ opTimeoutMs = 3e4;
8717
8750
  /** git executable. */
8718
8751
  git = "git";
8719
8752
  };
8720
8753
 
8721
8754
  // cli/permissions.ts
8722
8755
  import { writeFileSync as writeFileSync6, mkdirSync as mkdirSync8 } from "fs";
8723
- import { homedir as homedir6 } from "os";
8756
+ import { homedir as homedir7 } from "os";
8724
8757
  import { join as join10 } from "path";
8725
8758
  var RULE_RE = /^(\w+)(?:\((.+)\))?$/;
8726
8759
  function parseOne(raw, decision) {
@@ -8748,7 +8781,7 @@ function loadPersistedRules(cwd) {
8748
8781
  const j = readJsonFile(PERM_FILE(cwd), null);
8749
8782
  return j ? { allow: j.allow ?? [], ask: j.ask ?? [], deny: j.deny ?? [] } : {};
8750
8783
  }
8751
- function loadClaudeSettings(cwd, home = homedir6()) {
8784
+ function loadClaudeSettings(cwd, home = homedir7()) {
8752
8785
  const files = [join10(home, ".claude", "settings.json"), join10(cwd, ".claude", "settings.json"), join10(cwd, ".claude", "settings.local.json")];
8753
8786
  let out = {};
8754
8787
  for (const p of files) {
@@ -8776,7 +8809,7 @@ function mergePerms(a, b) {
8776
8809
  }
8777
8810
  return Object.keys(out).length ? out : void 0;
8778
8811
  }
8779
- var TRUST_FILE = join10(homedir6(), ".agent", "trusted.json");
8812
+ var TRUST_FILE = join10(homedir7(), ".agent", "trusted.json");
8780
8813
  function isTrusted(cwd, file = TRUST_FILE) {
8781
8814
  const list = readJsonFile(file, []);
8782
8815
  return Array.isArray(list) && list.includes(cwd);
@@ -10368,7 +10401,7 @@ function readPlainLine() {
10368
10401
  // cli/osScheduler.ts
10369
10402
  import { spawnSync as spawnSync5 } from "child_process";
10370
10403
  import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync9, readdirSync as readdirSync2, unlinkSync as unlinkSync3, chmodSync, existsSync as existsSync7 } from "fs";
10371
- import { homedir as homedir7 } from "os";
10404
+ import { homedir as homedir8 } from "os";
10372
10405
  import { join as join12 } from "path";
10373
10406
  var log21 = forComponent("os-sched");
10374
10407
  var OsScheduler = class {
@@ -10525,7 +10558,7 @@ ${expr} /bin/sh ${script} # agentx-sched-${spec.id}
10525
10558
  };
10526
10559
  var OsSchedulerOptions = class {
10527
10560
  platform = process.platform;
10528
- home = homedir7();
10561
+ home = homedir8();
10529
10562
  /** How the fired job invokes the CLI — a RAW shell snippet (may be `bun /path/cli.ts`). Default: `agentx` on PATH. */
10530
10563
  agentx = "agentx";
10531
10564
  /** Injectable executor for tests. Returns stdout+stderr merged — `at` reports "job N" on STDERR,
@@ -10547,10 +10580,10 @@ function routeTrigger(trigger, backendHint, now5 = Date.now()) {
10547
10580
  import { createServer as createServer2, createConnection } from "net";
10548
10581
  import { spawn as spawn3 } from "child_process";
10549
10582
  import { existsSync as existsSync8, mkdirSync as mkdirSync10, unlinkSync as unlinkSync4, readdirSync as readdirSync3 } from "fs";
10550
- import { homedir as homedir8 } from "os";
10583
+ import { homedir as homedir9 } from "os";
10551
10584
  import { join as join13 } from "path";
10552
10585
  var log22 = forComponent("remote-trigger");
10553
- var TRIGGER_DIR = () => join13(homedir8(), ".agent", "triggers");
10586
+ var TRIGGER_DIR = () => join13(homedir9(), ".agent", "triggers");
10554
10587
  var sockPath = (sessionId, dir = TRIGGER_DIR()) => join13(dir, `${sessionId}.sock`);
10555
10588
  var TriggerServer = class {
10556
10589
  constructor(onTrigger) {
@@ -10980,7 +11013,7 @@ function loadInstallEnv() {
10980
11013
  for (let i = 0; i < 5 && !existsSync9(join14(dir, "package.json")); i++) dir = dirname4(dir);
10981
11014
  for (const name of [".env", ".env.local"]) {
10982
11015
  loadEnvFile(join14(dir, name));
10983
- loadEnvFile(join14(homedir9(), ".agent", name));
11016
+ loadEnvFile(join14(homedir10(), ".agent", name));
10984
11017
  }
10985
11018
  }
10986
11019
  async function loadBodifySecrets() {
@@ -11636,7 +11669,7 @@ var IMG_EXT = { ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg"
11636
11669
  function mentionRefs(line) {
11637
11670
  return [...line.matchAll(/(?:^|\s)@(?:"([^"]+)"|(\S+))/g)].map((m) => m[1] ?? m[2].replace(/[?!.,;:)\]}'">]+$/, "")).filter(Boolean);
11638
11671
  }
11639
- var untilde = (p) => p.startsWith("~/") ? join14(homedir9(), p.slice(2)) : p;
11672
+ var untilde = (p) => p.startsWith("~/") ? join14(homedir10(), p.slice(2)) : p;
11640
11673
  function readImageParts(cwd, line) {
11641
11674
  const refs = mentionRefs(line);
11642
11675
  const parts = [];
@@ -12735,7 +12768,7 @@ ${task}`;
12735
12768
  }
12736
12769
  const info = getModelInfo(work.model);
12737
12770
  info?.pricing ? ok(`model ${work.model} \u2014 priced (${info.pricing.inputCostPer1K}/${info.pricing.outputCostPer1K} per 1k in/out)`) : warn(`model ${work.model} \u2014 no pricing in the catalog (costs will show ~$0; verify the id)`);
12738
- const cfgFiles = ["ts", "js", "json"].flatMap((e) => [`${cwd}/.agent/config.${e}`, `${homedir9()}/.agent/config.${e}`]).filter((p) => existsSync9(p));
12771
+ const cfgFiles = ["ts", "js", "json"].flatMap((e) => [`${cwd}/.agent/config.${e}`, `${homedir10()}/.agent/config.${e}`]).filter((p) => existsSync9(p));
12739
12772
  cfgFiles.length ? ok(`config: ${cfgFiles.join(", ")}`) : warn("no .agent/config.* found (project or ~) \u2014 running on defaults");
12740
12773
  try {
12741
12774
  const probe = `${cwd}/.agent/sessions/.doctor-probe`;