@tekmidian/pai 0.66.47 → 0.66.49

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.
Files changed (76) hide show
  1. package/dist/auto-route-CMARQbQ4.mjs +8 -0
  2. package/dist/{auto-route-DrncbMaz.mjs → auto-route-Dpm6nZ6X.mjs} +2 -2
  3. package/dist/{auto-route-DrncbMaz.mjs.map → auto-route-Dpm6nZ6X.mjs.map} +1 -1
  4. package/dist/{chain-Bba4Y8A8.mjs → chain-xSc3-u0X.mjs} +5 -5
  5. package/dist/{chain-Bba4Y8A8.mjs.map → chain-xSc3-u0X.mjs.map} +1 -1
  6. package/dist/cli/index.mjs +14 -14
  7. package/dist/cli/program.mjs +14 -14
  8. package/dist/{config-2pR0RqHM.mjs → config-CYjjGSWq.mjs} +41 -4
  9. package/dist/config-CYjjGSWq.mjs.map +1 -0
  10. package/dist/config-IuOG1W92.mjs +4 -0
  11. package/dist/daemon/index.mjs +10 -10
  12. package/dist/{daemon-C25MKGD8.mjs → daemon-BIG7XcqE.mjs} +10 -10
  13. package/dist/{daemon-C6K3kikA.mjs → daemon-CiSmbylJ.mjs} +7 -7
  14. package/dist/{daemon-C6K3kikA.mjs.map → daemon-CiSmbylJ.mjs.map} +1 -1
  15. package/dist/daemon-mcp/index.mjs +8 -8
  16. package/dist/{fallback-DyhAZAOe.mjs → fallback-BgAukP8r.mjs} +6 -5
  17. package/dist/fallback-BgAukP8r.mjs.map +1 -0
  18. package/dist/hooks/block-sleep-poll.mjs.map +2 -2
  19. package/dist/hooks/load-project-context.mjs +26 -2
  20. package/dist/hooks/load-project-context.mjs.map +2 -2
  21. package/dist/hooks/route-agents-to-worker.mjs +26 -2
  22. package/dist/hooks/route-agents-to-worker.mjs.map +2 -2
  23. package/dist/hooks/security-validator.mjs +26 -2
  24. package/dist/hooks/security-validator.mjs.map +2 -2
  25. package/dist/hooks/worker-guard.mjs +26 -2
  26. package/dist/hooks/worker-guard.mjs.map +2 -2
  27. package/dist/hooks/worker-pool-host.mjs +242 -14
  28. package/dist/hooks/worker-pool-host.mjs.map +4 -4
  29. package/dist/hooks/worker-proxy.mjs +26 -2
  30. package/dist/hooks/worker-proxy.mjs.map +2 -2
  31. package/dist/hooks/worker-status-line.mjs +26 -2
  32. package/dist/hooks/worker-status-line.mjs.map +2 -2
  33. package/dist/hooks/worker-supervision.mjs +26 -2
  34. package/dist/hooks/worker-supervision.mjs.map +2 -2
  35. package/dist/index.mjs +4 -4
  36. package/dist/{local-EmOjw5jq.mjs → local-Bt-7L0oB.mjs} +3 -3
  37. package/dist/{local-EmOjw5jq.mjs.map → local-Bt-7L0oB.mjs.map} +1 -1
  38. package/dist/local-oqPQEmhb.mjs +7 -0
  39. package/dist/{local-tiers-BIINbhkY.mjs → local-tiers-C0QSQcP1.mjs} +2 -2
  40. package/dist/{local-tiers-8fmjiySw.mjs → local-tiers-_ZOTbjeP.mjs} +2 -2
  41. package/dist/{local-tiers-8fmjiySw.mjs.map → local-tiers-_ZOTbjeP.mjs.map} +1 -1
  42. package/dist/{main-resolver-DBXvnYKp.mjs → main-resolver-BwjexuSA.mjs} +3 -3
  43. package/dist/{main-resolver-B10-lsU0.mjs → main-resolver-CVo0ab7j.mjs} +3 -3
  44. package/dist/{main-resolver-B10-lsU0.mjs.map → main-resolver-CVo0ab7j.mjs.map} +1 -1
  45. package/dist/{pai-marker-CDwQOpQ8.mjs → pai-marker-CJ6WMt05.mjs} +4 -4
  46. package/dist/{pai-marker-CDwQOpQ8.mjs.map → pai-marker-CJ6WMt05.mjs.map} +1 -1
  47. package/dist/{planner-dO-3PLjD.mjs → planner-ZKXZf9JS.mjs} +8 -8
  48. package/dist/{planner-dO-3PLjD.mjs.map → planner-ZKXZf9JS.mjs.map} +1 -1
  49. package/dist/{pool-DLhqOY3P.mjs → pool-CgsnP3La.mjs} +3 -3
  50. package/dist/{pool-DLhqOY3P.mjs.map → pool-CgsnP3La.mjs.map} +1 -1
  51. package/dist/{pool-cli-DerrWWpP.mjs → pool-cli-kGGuZCzJ.mjs} +4 -4
  52. package/dist/{pool-cli-DerrWWpP.mjs.map → pool-cli-kGGuZCzJ.mjs.map} +1 -1
  53. package/dist/{program-B7gVKc-u.mjs → program-DgcwJN6Z.mjs} +25 -463
  54. package/dist/program-DgcwJN6Z.mjs.map +1 -0
  55. package/dist/{run-a_JzcVwv.mjs → run-CsrBbtj_.mjs} +686 -21
  56. package/dist/run-CsrBbtj_.mjs.map +1 -0
  57. package/dist/{run-env-DyFZ8C1s.mjs → run-env-Cyw2iwBh.mjs} +15 -5
  58. package/dist/{run-env-DyFZ8C1s.mjs.map → run-env-Cyw2iwBh.mjs.map} +1 -1
  59. package/dist/{status-C3fBJKU_.mjs → status-B0br9zV0.mjs} +2 -2
  60. package/dist/status-B0br9zV0.mjs.map +1 -0
  61. package/dist/{supervisor-B_2JKYxe.mjs → supervisor-BZA0KICt.mjs} +7 -7
  62. package/dist/{supervisor-B_2JKYxe.mjs.map → supervisor-BZA0KICt.mjs.map} +1 -1
  63. package/dist/workers-config-BifEz8ns.mjs +4 -0
  64. package/dist/{worktree-lnmAOFQv.mjs → worktree-B6d-1uIn.mjs} +2 -2
  65. package/dist/{worktree-lnmAOFQv.mjs.map → worktree-B6d-1uIn.mjs.map} +1 -1
  66. package/docs/worker.md +22 -0
  67. package/package.json +1 -1
  68. package/dist/auto-route-DYuVfXwc.mjs +0 -8
  69. package/dist/config-2pR0RqHM.mjs.map +0 -1
  70. package/dist/config-CQWpEdXb.mjs +0 -4
  71. package/dist/fallback-DyhAZAOe.mjs.map +0 -1
  72. package/dist/local-B5SekWOC.mjs +0 -7
  73. package/dist/program-B7gVKc-u.mjs.map +0 -1
  74. package/dist/run-a_JzcVwv.mjs.map +0 -1
  75. package/dist/status-C3fBJKU_.mjs.map +0 -1
  76. package/dist/workers-config-nXSiW07z.mjs +0 -4
@@ -7900,6 +7900,17 @@ var init_workers_config = __esm({
7900
7900
  import { existsSync as existsSync6, readFileSync as readFileSync5 } from "node:fs";
7901
7901
  import { homedir as homedir4 } from "node:os";
7902
7902
  import { join as join5 } from "node:path";
7903
+ function nativeAnthropicProvider(models = NATIVE_ANTHROPIC_MODELS) {
7904
+ return {
7905
+ enabled: true,
7906
+ protocol: "anthropic",
7907
+ baseUrl: "",
7908
+ keyFile: null,
7909
+ models: { ...models },
7910
+ env: {},
7911
+ native: true
7912
+ };
7913
+ }
7903
7914
  function isModelCapability(v) {
7904
7915
  return CAPABILITY_NAME_RE.test(v);
7905
7916
  }
@@ -8245,10 +8256,31 @@ function parseWorkersConfig(raw) {
8245
8256
  if (r.retryOnQuota !== void 0 && typeof r.retryOnQuota !== "boolean") {
8246
8257
  bad(".routing.retryOnQuota", "must be boolean");
8247
8258
  }
8259
+ if (r.policy !== void 0 && r.policy !== "budget" && r.policy !== "order") {
8260
+ bad(".routing.policy", 'must be "budget" or "order"');
8261
+ }
8262
+ if (r.priority !== void 0) {
8263
+ if (!Array.isArray(r.priority) || r.priority.some((x) => typeof x !== "string")) {
8264
+ bad(".routing.priority", "must be an array of provider names");
8265
+ }
8266
+ }
8267
+ if (r.budgetWalls !== void 0) {
8268
+ if (typeof r.budgetWalls !== "object" || r.budgetWalls === null || Array.isArray(r.budgetWalls)) {
8269
+ bad(".routing.budgetWalls", "must be an object of provider name \u2192 percent");
8270
+ }
8271
+ for (const [k, v] of Object.entries(r.budgetWalls)) {
8272
+ if (typeof v !== "number" || !Number.isFinite(v) || v < 0 || v > 100) {
8273
+ bad(`.routing.budgetWalls.${k}`, "must be a percent 0\u2013100");
8274
+ }
8275
+ }
8276
+ }
8248
8277
  routing = {
8249
8278
  order: routing.order,
8250
8279
  cooldownMinutes: r.cooldownMinutes === void 0 ? DEFAULT_ROUTING2.cooldownMinutes : r.cooldownMinutes,
8251
- retryOnQuota: r.retryOnQuota === void 0 ? DEFAULT_ROUTING2.retryOnQuota : r.retryOnQuota === true
8280
+ retryOnQuota: r.retryOnQuota === void 0 ? DEFAULT_ROUTING2.retryOnQuota : r.retryOnQuota === true,
8281
+ policy: r.policy ?? DEFAULT_ROUTING2.policy,
8282
+ priority: r.priority === void 0 ? [] : [...r.priority],
8283
+ budgetWalls: r.budgetWalls === void 0 ? {} : { ...r.budgetWalls }
8252
8284
  };
8253
8285
  }
8254
8286
  let tree = { ...DEFAULT_TREE };
@@ -8451,7 +8483,10 @@ var init_config2 = __esm({
8451
8483
  DEFAULT_ROUTING2 = {
8452
8484
  order: [],
8453
8485
  cooldownMinutes: 30,
8454
- retryOnQuota: true
8486
+ retryOnQuota: true,
8487
+ policy: "budget",
8488
+ priority: [],
8489
+ budgetWalls: {}
8455
8490
  };
8456
8491
  DEFAULT_TREE = {
8457
8492
  maxDepth: 2,
@@ -8835,7 +8870,7 @@ var init_router = __esm({
8835
8870
  // src/workers/run-env.ts
8836
8871
  import { existsSync as existsSync9 } from "node:fs";
8837
8872
  import { delimiter, join as join10 } from "node:path";
8838
- function buildRunEnv(provider, headless, proxyUrl, providerName) {
8873
+ function buildRunEnv(provider, headless, proxyUrl, providerName, routerEnabled) {
8839
8874
  const env = { ...process.env };
8840
8875
  delete env.ANTHROPIC_API_KEY;
8841
8876
  if (headless) {
@@ -8857,6 +8892,8 @@ function buildRunEnv(provider, headless, proxyUrl, providerName) {
8857
8892
  let token = "local";
8858
8893
  if (proxyUrl) {
8859
8894
  env.ANTHROPIC_BASE_URL = proxyUrl;
8895
+ } else if (routerEnabled) {
8896
+ env.ANTHROPIC_BASE_URL = routerUrl();
8860
8897
  } else {
8861
8898
  const resolved = resolveProviderKey(provider);
8862
8899
  if (resolved) token = resolved;
@@ -8878,6 +8915,9 @@ function buildRunEnv(provider, headless, proxyUrl, providerName) {
8878
8915
  }
8879
8916
  return env;
8880
8917
  }
8918
+ function routerUrl() {
8919
+ return `http://127.0.0.1:${ROUTER_PORT}`;
8920
+ }
8881
8921
  function claudeCommand(env, caveman, routerEnabled) {
8882
8922
  const route = env.ANTHROPIC_BASE_URL;
8883
8923
  if (!route && caveman) {
@@ -8888,7 +8928,7 @@ function claudeCommand(env, caveman, routerEnabled) {
8888
8928
  return ["claude", ...pinnedSettingsArgs(env, routerEnabled, extra)];
8889
8929
  }
8890
8930
  function pinnedSettingsArgs(env, routerEnabled = loadConfig().router.enabled, extra) {
8891
- const native = routerEnabled ? `http://127.0.0.1:${ROUTER_PORT}` : ANTHROPIC_FIRST_PARTY_URL;
8931
+ const native = routerEnabled ? routerUrl() : ANTHROPIC_FIRST_PARTY_URL;
8892
8932
  const pinned = { ANTHROPIC_BASE_URL: env.ANTHROPIC_BASE_URL || native };
8893
8933
  if (env.ANTHROPIC_BASE_URL) {
8894
8934
  for (const k of PINNED_KEYS) if (env[k]) pinned[k] = env[k];
@@ -9023,7 +9063,7 @@ function resolveToken() {
9023
9063
  function forgeClient(cwd, cfg, deps) {
9024
9064
  const token = deps.token ?? resolveToken();
9025
9065
  if (!token) throw new ForgeError("no forge token");
9026
- const http = deps.http ?? curlHttp;
9066
+ const http2 = deps.http ?? curlHttp;
9027
9067
  let origin = deps.originUrl;
9028
9068
  if (!origin) {
9029
9069
  try {
@@ -9045,7 +9085,7 @@ function forgeClient(cwd, cfg, deps) {
9045
9085
  if (left < 300) throw new ForgeError("time budget exhausted");
9046
9086
  let r;
9047
9087
  try {
9048
- r = http(method, `${derived.apiBase}/repos/${repo}/${path}`, token, body, left);
9088
+ r = http2(method, `${derived.apiBase}/repos/${repo}/${path}`, token, body, left);
9049
9089
  } catch (e) {
9050
9090
  throw e instanceof ForgeError ? e : new ForgeError(`request failed (${e.message})`);
9051
9091
  }
@@ -9359,11 +9399,196 @@ var init_controls = __esm({
9359
9399
  }
9360
9400
  });
9361
9401
 
9402
+ // src/router/limits.ts
9403
+ import { execFile, spawnSync as spawnSync2 } from "node:child_process";
9404
+ import http from "node:http";
9405
+ import https from "node:https";
9406
+ import { homedir as homedir9 } from "node:os";
9407
+ import { dirname as dirname8, join as join14 } from "node:path";
9408
+ function toMs(v, unit) {
9409
+ if (v === null || v === void 0 || v === "") return void 0;
9410
+ if (unit === "iso" || unit === void 0 && typeof v === "string" && !/^\d+(\.\d+)?$/.test(v)) {
9411
+ const t = Date.parse(String(v));
9412
+ return Number.isFinite(t) ? t : void 0;
9413
+ }
9414
+ const n = Number(v);
9415
+ if (!Number.isFinite(n)) return void 0;
9416
+ return unit === "s" ? n * 1e3 : n;
9417
+ }
9418
+ function jq(expr, input) {
9419
+ const r = spawnSync2("jq", ["-r", expr], { input, encoding: "utf8", timeout: 3e3 });
9420
+ if (r.status !== 0) return void 0;
9421
+ const out = r.stdout.trim().split("\n")[0];
9422
+ return out === void 0 || out === "" || out === "null" ? void 0 : out;
9423
+ }
9424
+ function windowsFromJson(body, cfg) {
9425
+ const out = [];
9426
+ for (const w of cfg.windows) {
9427
+ const pct = Number(jq(w.percent, body));
9428
+ if (!Number.isFinite(pct) || jq(w.percent, body) === void 0) continue;
9429
+ const reset = w.resetAt ? toMs(jq(w.resetAt, body), w.resetUnit) : void 0;
9430
+ out.push({ name: w.name, percent: Math.round(pct * 10) / 10, ...reset ? { resetAt: reset } : {} });
9431
+ }
9432
+ return out;
9433
+ }
9434
+ function parseAnthropicUsage(body) {
9435
+ let j;
9436
+ try {
9437
+ j = JSON.parse(body);
9438
+ } catch {
9439
+ return [];
9440
+ }
9441
+ const out = [];
9442
+ for (const [key, name] of [["five_hour", "5h"], ["seven_day", "7d"]]) {
9443
+ const w = j[key];
9444
+ if (!w || typeof w.utilization !== "number") continue;
9445
+ const reset = toMs(w.resets_at, "iso");
9446
+ out.push({ name, percent: w.utilization, ...reset ? { resetAt: reset } : {} });
9447
+ }
9448
+ return out;
9449
+ }
9450
+ function getJson(url, headers) {
9451
+ return new Promise((resolve, reject) => {
9452
+ const mod = url.protocol === "https:" ? https : http;
9453
+ const rq = mod.get(url, { headers, timeout: 5e3 }, (res) => {
9454
+ let t = "";
9455
+ res.on("data", (c) => t += c);
9456
+ res.on("end", () => res.statusCode === 200 ? resolve(t) : reject(new Error(`http ${res.statusCode}`)));
9457
+ });
9458
+ rq.on("timeout", () => rq.destroy(new Error("timeout")));
9459
+ rq.on("error", reject);
9460
+ });
9461
+ }
9462
+ function sh(cmd, args) {
9463
+ return new Promise((resolve) => execFile(cmd, args, { timeout: 4e3 }, (_e, out) => resolve(String(out ?? "").trim())));
9464
+ }
9465
+ async function anthropicToken() {
9466
+ for (const args of [["-a", process.env.USER ?? ""], []]) {
9467
+ const raw = await sh("security", ["find-generic-password", "-s", "Claude Code-credentials", ...args, "-w"]);
9468
+ try {
9469
+ const t = JSON.parse(raw).claudeAiOauth?.accessToken;
9470
+ if (t) return t;
9471
+ } catch {
9472
+ }
9473
+ }
9474
+ return void 0;
9475
+ }
9476
+ var ESTIMATE_FILE, ADVISOR_FILE, LASTGOOD_FILE, PLAN_LASTGOOD_MAX_AGE, BACKOFF_MAX, ANTHROPIC_USAGE_URL;
9477
+ var init_limits = __esm({
9478
+ "src/router/limits.ts"() {
9479
+ "use strict";
9480
+ init_config2();
9481
+ ESTIMATE_FILE = join14(homedir9(), ".claude", "pai", "router-limits.json");
9482
+ ADVISOR_FILE = join14(homedir9(), ".claude", "pai", "advisor-mode.json");
9483
+ LASTGOOD_FILE = join14(homedir9(), ".claude", "pai", "logs", "router-limits-last.json");
9484
+ PLAN_LASTGOOD_MAX_AGE = 2 * 36e5;
9485
+ BACKOFF_MAX = 30 * 6e4;
9486
+ ANTHROPIC_USAGE_URL = "https://api.anthropic.com/api/oauth/usage";
9487
+ }
9488
+ });
9489
+
9490
+ // src/workers/budget.ts
9491
+ function pickBudgetWindow(windows, now) {
9492
+ let best = null;
9493
+ for (const w of windows) if (!best || w.percent > best.percent) best = w;
9494
+ if (!best) return { percent: null, resetAt: null, fetchedAt: now };
9495
+ return { percent: best.percent, resetAt: best.resetAt ?? null, fetchedAt: now };
9496
+ }
9497
+ async function fetchBudgetReading(name, p) {
9498
+ const now = Date.now();
9499
+ try {
9500
+ if (p.native || name === "anthropic") {
9501
+ const token = await anthropicToken();
9502
+ if (!token) throw new Error("no OAuth token in keychain");
9503
+ const body2 = await getJson(new URL(ANTHROPIC_USAGE_URL), {
9504
+ authorization: `Bearer ${token}`,
9505
+ "anthropic-beta": "oauth-2025-04-20"
9506
+ });
9507
+ return pickBudgetWindow(parseAnthropicUsage(body2), now);
9508
+ }
9509
+ if (!p.usage) return { percent: null, resetAt: null, fetchedAt: now };
9510
+ const key = resolveProviderKey(p);
9511
+ const [hn, ...pre] = (p.usage.authHeader ?? "Authorization: Bearer").split(/:\s*/);
9512
+ const prefix = pre.join(": ");
9513
+ const body = await getJson(new URL(p.usage.url), {
9514
+ [hn.toLowerCase()]: prefix ? `${prefix} ${key}` : String(key)
9515
+ });
9516
+ return pickBudgetWindow(windowsFromJson(body, p.usage), now);
9517
+ } catch {
9518
+ return { percent: null, resetAt: null, fetchedAt: now };
9519
+ }
9520
+ }
9521
+ var BUDGET_TTL_MS, BudgetCache, budgetCache;
9522
+ var init_budget = __esm({
9523
+ "src/workers/budget.ts"() {
9524
+ "use strict";
9525
+ init_limits();
9526
+ init_config2();
9527
+ BUDGET_TTL_MS = 5 * 6e4;
9528
+ BudgetCache = class {
9529
+ constructor(ttlMs = BUDGET_TTL_MS, fetch2 = fetchBudgetReading) {
9530
+ this.ttlMs = ttlMs;
9531
+ this.fetch = fetch2;
9532
+ }
9533
+ value = {};
9534
+ at = 0;
9535
+ inflight;
9536
+ /** Refresh every stale provider of `config`; resolves to the full map. */
9537
+ async warm(config, now = Date.now()) {
9538
+ if (this.at && now - this.at < this.ttlMs) return this.value;
9539
+ this.inflight ??= this.poll(config).then((v) => {
9540
+ this.value = v;
9541
+ this.at = now;
9542
+ this.inflight = void 0;
9543
+ return v;
9544
+ });
9545
+ return this.inflight;
9546
+ }
9547
+ async poll(config) {
9548
+ const out = { ...this.value };
9549
+ const jobs = [
9550
+ // native anthropic has no config entry: probe it as the synthetic provider
9551
+ this.fetch("anthropic", nativeAnthropicProvider(config.nativeModels)).then((r) => {
9552
+ out.anthropic = r;
9553
+ })
9554
+ ];
9555
+ for (const [name, p] of Object.entries(config.providers)) {
9556
+ jobs.push(
9557
+ this.fetch(name, p).then((r) => {
9558
+ out[name] = r;
9559
+ })
9560
+ );
9561
+ }
9562
+ await Promise.all(jobs);
9563
+ return out;
9564
+ }
9565
+ /** Synchronous read for routing (possibly absent — absence is "unknown"). */
9566
+ get(name) {
9567
+ return this.value[name];
9568
+ }
9569
+ snapshot() {
9570
+ return { ...this.value };
9571
+ }
9572
+ seed(map, at = Date.now()) {
9573
+ this.value = { ...map };
9574
+ this.at = at;
9575
+ }
9576
+ clear() {
9577
+ this.value = {};
9578
+ this.at = 0;
9579
+ this.inflight = void 0;
9580
+ }
9581
+ };
9582
+ budgetCache = new BudgetCache();
9583
+ }
9584
+ });
9585
+
9362
9586
  // src/workers/routing.ts
9363
9587
  var init_routing = __esm({
9364
9588
  "src/workers/routing.ts"() {
9365
9589
  "use strict";
9366
9590
  init_config2();
9591
+ init_budget();
9367
9592
  init_paths();
9368
9593
  }
9369
9594
  });
@@ -15426,8 +15651,8 @@ var require_bindings = __commonJS({
15426
15651
  var fs = __require("fs");
15427
15652
  var path = __require("path");
15428
15653
  var fileURLToPath = require_file_uri_to_path();
15429
- var join14 = path.join;
15430
- var dirname8 = path.dirname;
15654
+ var join15 = path.join;
15655
+ var dirname9 = path.dirname;
15431
15656
  var exists = fs.accessSync && function(path2) {
15432
15657
  try {
15433
15658
  fs.accessSync(path2);
@@ -15486,7 +15711,7 @@ var require_bindings = __commonJS({
15486
15711
  var requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
15487
15712
  var tries = [], i = 0, l = opts.try.length, n, b, err;
15488
15713
  for (; i < l; i++) {
15489
- n = join14.apply(
15714
+ n = join15.apply(
15490
15715
  null,
15491
15716
  opts.try[i].map(function(p) {
15492
15717
  return opts[p] || p;
@@ -15542,12 +15767,12 @@ var require_bindings = __commonJS({
15542
15767
  return fileName;
15543
15768
  };
15544
15769
  exports.getRoot = function getRoot(file) {
15545
- var dir = dirname8(file), prev;
15770
+ var dir = dirname9(file), prev;
15546
15771
  while (true) {
15547
15772
  if (dir === ".") {
15548
15773
  dir = process.cwd();
15549
15774
  }
15550
- if (exists(join14(dir, "package.json")) || exists(join14(dir, "node_modules"))) {
15775
+ if (exists(join15(dir, "package.json")) || exists(join15(dir, "node_modules"))) {
15551
15776
  return dir;
15552
15777
  }
15553
15778
  if (prev === dir) {
@@ -15556,7 +15781,7 @@ var require_bindings = __commonJS({
15556
15781
  );
15557
15782
  }
15558
15783
  prev = dir;
15559
- dir = join14(dir, "..");
15784
+ dir = join15(dir, "..");
15560
15785
  }
15561
15786
  };
15562
15787
  }
@@ -16393,6 +16618,7 @@ var init_run = __esm({
16393
16618
  init_controls();
16394
16619
  init_policy();
16395
16620
  init_routing();
16621
+ init_budget();
16396
16622
  init_image();
16397
16623
  init_pane();
16398
16624
  init_tree();
@@ -16424,6 +16650,7 @@ init_pool();
16424
16650
  import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync8 } from "node:fs";
16425
16651
 
16426
16652
  // src/workers/pool-host.ts
16653
+ init_config();
16427
16654
  init_args();
16428
16655
  init_agentish();
16429
16656
  init_config2();
@@ -16618,8 +16845,9 @@ function createPoolHost(opts = {}) {
16618
16845
  const settings = poolSettings(config);
16619
16846
  const port2 = opts.port ?? poolPort(config);
16620
16847
  const spawner = opts.spawner ?? realSpawner;
16621
- const envFor = opts.envFor ?? ((name, p) => buildRunEnv(p, true, void 0, name));
16622
- const cmdHead = opts.cmdHead ?? ((env, caveman) => claudeCommand(env, caveman));
16848
+ const routerOn = opts.routerEnabled ?? loadConfig().router.enabled;
16849
+ const envFor = opts.envFor ?? ((name, p) => buildRunEnv(p, true, void 0, name, routerOn));
16850
+ const cmdHead = opts.cmdHead ?? ((env, caveman) => claudeCommand(env, caveman, routerOn));
16623
16851
  const now = opts.now ?? (() => /* @__PURE__ */ new Date());
16624
16852
  const ledger = ledgerPath(logDir2);
16625
16853
  mkdirSync9(logDir2, { recursive: true });