billion-context-pi 0.1.39 → 0.1.40

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.
@@ -81,6 +81,11 @@ export declare function makeEventApplier(opts: {
81
81
  onUsage?: (usage: Usage) => void;
82
82
  onSettled?: () => void;
83
83
  }, writers: EventApplierWriters): EventApplier;
84
+ /** Resolve a wait timeout to ms. Agents frequently pass seconds (e.g. 180)
85
+ * instead of milliseconds; values below the 1s floor make no sense as a wait
86
+ * duration, so rescale them to seconds before clamping — otherwise 180 clamps
87
+ * to 1000ms and the wait times out in 1s. */
88
+ export declare function resolveWaitTimeoutMs(raw: number | undefined): number;
84
89
  declare const DelegateParams: Type.TObject<{
85
90
  agent: Type.TString;
86
91
  task: Type.TString;
package/dist/index.js CHANGED
@@ -3341,6 +3341,64 @@ function mergeInitialState(parsed) {
3341
3341
  };
3342
3342
  }
3343
3343
 
3344
+ // src/user-config.ts
3345
+ import { promises as fs2 } from "fs";
3346
+ import * as path3 from "path";
3347
+ import { homedir as homedir2 } from "os";
3348
+ import { CONFIG_DIR_NAME as CONFIG_DIR_NAME2 } from "@earendil-works/pi-coding-agent";
3349
+ async function loadUserConfig(cwd) {
3350
+ const home = homedir2();
3351
+ const merged = {};
3352
+ for (const base of [join4(home, CONFIG_DIR_NAME2), join4(cwd, CONFIG_DIR_NAME2)]) {
3353
+ const file = join4(base, "acp.json");
3354
+ try {
3355
+ const raw = await fs2.readFile(file, "utf8");
3356
+ const parsed = JSON.parse(raw);
3357
+ if (parsed && typeof parsed === "object") {
3358
+ Object.assign(merged, pickKnown(parsed));
3359
+ debug.event("config-loaded", { file });
3360
+ }
3361
+ } catch (e) {
3362
+ const code = e.code;
3363
+ if (code !== "ENOENT") {
3364
+ logWarn("config", { event: "load-failed", file, error: e instanceof Error ? e.message : String(e) });
3365
+ }
3366
+ }
3367
+ }
3368
+ return merged;
3369
+ }
3370
+ function join4(...parts) {
3371
+ return path3.join(...parts);
3372
+ }
3373
+ var KNOWN = /* @__PURE__ */ new Set([
3374
+ "debug",
3375
+ "autoUpdate",
3376
+ "modelContextLimit",
3377
+ "toolBashDefaultTimeout",
3378
+ "toolOutputMaxBytes",
3379
+ "delegate",
3380
+ "compress",
3381
+ "displayUsage",
3382
+ "prompts",
3383
+ "acknowledgePromptsRisk"
3384
+ ]);
3385
+ function pickKnown(parsed) {
3386
+ const out = {};
3387
+ for (const [k, v] of Object.entries(parsed)) {
3388
+ if (KNOWN.has(k)) out[k] = v;
3389
+ }
3390
+ return out;
3391
+ }
3392
+ function applyUserConfig(adapter, user) {
3393
+ return {
3394
+ ...adapter,
3395
+ ...user,
3396
+ coreOverrides: adapter.coreOverrides,
3397
+ protectedTools: adapter.protectedTools,
3398
+ preserveRecentMessages: adapter.preserveRecentMessages
3399
+ };
3400
+ }
3401
+
3344
3402
  // src/sequence-match.ts
3345
3403
  function findUniqueLongestRun(candidates, live) {
3346
3404
  if (candidates.length === 0 || live.length === 0) return void 0;
@@ -3565,7 +3623,9 @@ function createRuntime(adapter) {
3565
3623
  const store = new SessionStateStore();
3566
3624
  const lastActiveBlockIds = /* @__PURE__ */ new Map();
3567
3625
  const locks = /* @__PURE__ */ new Map();
3626
+ const factoryAdapter = adapter;
3568
3627
  let adapterRef = adapter;
3628
+ let lastUserConfigKey;
3569
3629
  let promptsRef = defaultPrompts;
3570
3630
  const nudgeShownTurns = /* @__PURE__ */ new Set();
3571
3631
  async function acquireLock(sid) {
@@ -3591,6 +3651,25 @@ function createRuntime(adapter) {
3591
3651
  const m = ctx.model;
3592
3652
  return resolveConfig(adapterRef, liveContextLimit(ctx), m?.provider, m?.id);
3593
3653
  }
3654
+ async function reloadConfig(cwd) {
3655
+ let user;
3656
+ try {
3657
+ user = await loadUserConfig(cwd);
3658
+ } catch (e) {
3659
+ logWarn("runtime", { event: "config-reload-failed", error: e instanceof Error ? e.message : String(e) });
3660
+ return;
3661
+ }
3662
+ try {
3663
+ const key = JSON.stringify(user);
3664
+ if (key === lastUserConfigKey) return;
3665
+ lastUserConfigKey = key;
3666
+ adapterRef = applyUserConfig(factoryAdapter, user);
3667
+ if (adapterRef.debug !== void 0) setDebugEnabled(adapterRef.debug);
3668
+ logInfo("runtime", { event: "config-reloaded", limit: adapterRef.modelContextLimit ?? null });
3669
+ } catch (e) {
3670
+ logWarn("runtime", { event: "config-reload-failed", error: e instanceof Error ? e.message : String(e) });
3671
+ }
3672
+ }
3594
3673
  async function stateFor(ctx, liveMessages) {
3595
3674
  const sm = ctx.sessionManager;
3596
3675
  const sessionFile = sm.getSessionFile() ?? void 0;
@@ -3626,8 +3705,6 @@ function createRuntime(adapter) {
3626
3705
  countModelId = m;
3627
3706
  }, noteActiveBlocks, clearSessionTracking, get adapter() {
3628
3707
  return adapterRef;
3629
- }, setAdapter: (a) => {
3630
- adapterRef = a;
3631
3708
  }, get prompts() {
3632
3709
  return promptsRef;
3633
3710
  }, setPrompts: (p) => {
@@ -3636,7 +3713,7 @@ function createRuntime(adapter) {
3636
3713
  nudgeShownTurns.add(k);
3637
3714
  }, nudgeShownFor: (k) => nudgeShownTurns.has(k), clearNudgeTracking: () => {
3638
3715
  nudgeShownTurns.clear();
3639
- }, liveContextLimit, configFor, stateFor, save, acquireLock };
3716
+ }, liveContextLimit, configFor, reloadConfig, stateFor, save, acquireLock };
3640
3717
  }
3641
3718
 
3642
3719
  // node_modules/typebox/build/system/memory/memory.mjs
@@ -8159,7 +8236,14 @@ async function handleCompress(args, runtime, ctx, toolCallId) {
8159
8236
  });
8160
8237
  await runtime.save(applied.state, ctx);
8161
8238
  const { blocksCreated, tokensCompressed, errors, warnings } = applied.result;
8162
- const afterTokens = Math.max(0, beforeTokens - tokensCompressed);
8239
+ const afterTurn = runtime.core.processTurn({
8240
+ messages: coreMessages,
8241
+ state: applied.state,
8242
+ config,
8243
+ tokenCount: calibrateTokens(sentTokens, density)
8244
+ });
8245
+ const afterTokens = calibrateTokens(estimateTokens(afterTurn.messages, collectCoveredMessageIds(applied.state)), density);
8246
+ const reclaimed = Math.max(0, beforeTokens - afterTokens);
8163
8247
  const newBlocks = applied.state.blocks.slice(-blocksCreated);
8164
8248
  debug.event("compress-out", {
8165
8249
  sid: ctx.sessionManager.getSessionId(),
@@ -8190,9 +8274,9 @@ async function handleCompress(args, runtime, ctx, toolCallId) {
8190
8274
  logError("compress", { sid: ctx.sessionManager.getSessionId(), event: "errors", count: errors.length, errors: errors.slice(0, 5) });
8191
8275
  }
8192
8276
  if (warnings.length > 0) {
8193
- logError("compress", { sid: ctx.sessionManager.getSessionId(), event: "warnings", count: warnings.length, warnings: warnings.slice(0, 5) });
8277
+ logWarn("compress", { sid: ctx.sessionManager.getSessionId(), event: "warnings", count: warnings.length, warnings: warnings.slice(0, 5) });
8194
8278
  }
8195
- const lines = [`\u25A3 ACP | ${formatK2(beforeTokens)} \u2192 ${formatK2(afterTokens)} tokens (~${formatK2(tokensCompressed)} reclaimed, ${blocksCreated} block${blocksCreated > 1 ? "s" : ""})`];
8279
+ const lines = [`\u25A3 ACP | ${formatK2(beforeTokens)} \u2192 ${formatK2(afterTokens)} tokens (~${formatK2(reclaimed)} reclaimed, ${blocksCreated} block${blocksCreated > 1 ? "s" : ""})`];
8196
8280
  if (warnings.length > 0) lines.push("\u26A0\uFE0F " + warnings.join("; "));
8197
8281
  if (errors.length > 0) lines.push("Errors: " + errors.join("; "));
8198
8282
  return lines.join("\n");
@@ -8201,9 +8285,9 @@ async function handleCompress(args, runtime, ctx, toolCallId) {
8201
8285
  // src/decompress-tool.ts
8202
8286
  import { writeFile, mkdir } from "fs/promises";
8203
8287
  import { existsSync as existsSync2, lstatSync, readlinkSync, realpathSync } from "fs";
8204
- import { resolve, relative, isAbsolute, join as join3, basename as basename2, dirname as dirname3 } from "path";
8205
- import { tmpdir, homedir as homedir2 } from "os";
8206
- var AUTO_DIR = join3(homedir2() || tmpdir(), ".cache", "pi", "acp-decompress");
8288
+ import { resolve, relative, isAbsolute, join as join5, basename as basename2, dirname as dirname3 } from "path";
8289
+ import { tmpdir, homedir as homedir3 } from "os";
8290
+ var AUTO_DIR = join5(homedir3() || tmpdir(), ".cache", "pi", "acp-decompress");
8207
8291
  var PREVIEW_CHARS = 600;
8208
8292
  var MESSAGE_INLINE_THRESHOLD = 2e3;
8209
8293
  var DecompressParams = typebox_exports.Object({
@@ -8239,11 +8323,11 @@ function makeDecompressTool(runtime) {
8239
8323
  }
8240
8324
  var ALLOWED_DIRS = [
8241
8325
  tmpdir(),
8242
- join3(homedir2(), ".cache", "opencode"),
8243
- join3(homedir2(), ".cache", "pi")
8326
+ join5(homedir3(), ".cache", "opencode"),
8327
+ join5(homedir3(), ".cache", "pi")
8244
8328
  ];
8245
8329
  function resolveToFilePath(targetPath) {
8246
- const expanded = targetPath.startsWith("~/") ? join3(homedir2(), targetPath.slice(2)) : targetPath;
8330
+ const expanded = targetPath.startsWith("~/") ? join5(homedir3(), targetPath.slice(2)) : targetPath;
8247
8331
  const resolved = resolve(expanded);
8248
8332
  let probe = resolved;
8249
8333
  const suffix = [];
@@ -8254,7 +8338,7 @@ function resolveToFilePath(targetPath) {
8254
8338
  const real = existsSync2(probe) ? realpathSync(probe) : probe;
8255
8339
  let checked = real;
8256
8340
  for (const part of suffix) {
8257
- checked = join3(checked, part);
8341
+ checked = join5(checked, part);
8258
8342
  try {
8259
8343
  if (lstatSync(checked).isSymbolicLink()) {
8260
8344
  const target = readlinkSync(checked);
@@ -8280,7 +8364,7 @@ function resolveToFilePath(targetPath) {
8280
8364
  return checked;
8281
8365
  }
8282
8366
  function autoFilePath(blockId) {
8283
- return join3(AUTO_DIR, `${blockId}-${Date.now()}.txt`);
8367
+ return join5(AUTO_DIR, `${blockId}-${Date.now()}.txt`);
8284
8368
  }
8285
8369
  function headPreview(text) {
8286
8370
  if (text.length <= PREVIEW_CHARS) return text;
@@ -8627,7 +8711,7 @@ import {
8627
8711
  import { createWriteStream, existsSync as existsSync3 } from "fs";
8628
8712
  import { mkdir as mkdir2, mkdtemp, writeFile as writeFile2, rm, appendFile } from "fs/promises";
8629
8713
  import { tmpdir as tmpdir2 } from "os";
8630
- import { dirname as dirname4, join as join4, resolve as resolvePath } from "path";
8714
+ import { dirname as dirname4, join as join6, resolve as resolvePath } from "path";
8631
8715
 
8632
8716
  // src/footer-status.ts
8633
8717
  var FOOTER_STATUS_KEY = "billion-context-pi";
@@ -9031,7 +9115,7 @@ var IDLE_GRACE_MS = 5 * 6e4;
9031
9115
  var ASYNC_TIMEOUT_MS = 30 * 6e4;
9032
9116
  var KILL_GRACE_MS = 1e4;
9033
9117
  var RESULT_SUMMARY_CHARS = 500;
9034
- var OUT_DIR = join4(tmpdir2(), "acp-delegate");
9118
+ var OUT_DIR = join6(tmpdir2(), "acp-delegate");
9035
9119
  function delegateSpawnOptions(cwd, env) {
9036
9120
  return {
9037
9121
  cwd,
@@ -9041,11 +9125,11 @@ function delegateSpawnOptions(cwd, env) {
9041
9125
  };
9042
9126
  }
9043
9127
  var PI_CLI_ENTRY_RE = /[\\/]pi-coding-agent[\\/]dist[\\/]cli\.js$/;
9044
- var PI_PACKAGE_REL = join4("@earendil-works", "pi-coding-agent", "dist", "cli.js");
9128
+ var PI_PACKAGE_REL = join6("@earendil-works", "pi-coding-agent", "dist", "cli.js");
9045
9129
  function probeUpFromArgv(argv1) {
9046
9130
  let dir = resolvePath(dirname4(argv1) || process.cwd());
9047
9131
  for (; ; ) {
9048
- const candidate = join4(dir, "node_modules", PI_PACKAGE_REL);
9132
+ const candidate = join6(dir, "node_modules", PI_PACKAGE_REL);
9049
9133
  if (existsSync3(candidate)) return candidate;
9050
9134
  const parent = dirname4(dir);
9051
9135
  if (parent === dir) return null;
@@ -9055,12 +9139,12 @@ function probeUpFromArgv(argv1) {
9055
9139
  function piCliGlobalCandidates(env) {
9056
9140
  const candidates = [];
9057
9141
  if (process.platform === "win32") {
9058
- if (env.APPDATA) candidates.push(join4(env.APPDATA, "npm", "node_modules", PI_PACKAGE_REL));
9142
+ if (env.APPDATA) candidates.push(join6(env.APPDATA, "npm", "node_modules", PI_PACKAGE_REL));
9059
9143
  } else {
9060
9144
  const home = env.HOME ?? env.USERPROFILE;
9061
- if (home) candidates.push(join4(home, ".local", "lib", "node_modules", PI_PACKAGE_REL));
9062
- candidates.push(join4("/usr/local", "lib", "node_modules", PI_PACKAGE_REL));
9063
- candidates.push(join4("/usr", "lib", "node_modules", PI_PACKAGE_REL));
9145
+ if (home) candidates.push(join6(home, ".local", "lib", "node_modules", PI_PACKAGE_REL));
9146
+ candidates.push(join6("/usr/local", "lib", "node_modules", PI_PACKAGE_REL));
9147
+ candidates.push(join6("/usr", "lib", "node_modules", PI_PACKAGE_REL));
9064
9148
  }
9065
9149
  return candidates;
9066
9150
  }
@@ -9212,6 +9296,11 @@ function makeEventApplier(opts, writers) {
9212
9296
  }
9213
9297
  var WAIT_TIMEOUT_MS_DEFAULT = 1e4;
9214
9298
  var WAIT_TIMEOUT_MS_MAX = 3e5;
9299
+ function resolveWaitTimeoutMs(raw) {
9300
+ if (raw === void 0) return WAIT_TIMEOUT_MS_DEFAULT;
9301
+ const ms = raw < 1e3 ? raw * 1e3 : raw;
9302
+ return Math.min(Math.max(ms, 1e3), WAIT_TIMEOUT_MS_MAX);
9303
+ }
9215
9304
  var DelegateParams = typebox_exports.Object({
9216
9305
  agent: typebox_exports.String({
9217
9306
  description: `Role of the delegate. One of: ${AGENT_NAMES.join(", ")}. See tool description for what each does.`
@@ -9243,7 +9332,7 @@ var WaitParams = typebox_exports.Object({
9243
9332
  runId: typebox_exports.String({ description: "The runId returned by acp_delegate to wait for." }),
9244
9333
  timeout: typebox_exports.Optional(
9245
9334
  typebox_exports.Integer({
9246
- description: `Maximum milliseconds to block waiting for the result. Default ${WAIT_TIMEOUT_MS_DEFAULT} (10s); max ${WAIT_TIMEOUT_MS_MAX} (300s). If the delegate does not finish in time, returns "failed (not ready)" \u2014 do NOT keep waiting or retry; go do other work, and a completion notification will still be injected when it completes.`
9335
+ description: `Maximum time to block waiting for the result, in milliseconds. Default ${WAIT_TIMEOUT_MS_DEFAULT} (10s); max ${WAIT_TIMEOUT_MS_MAX} (300s). Values below 1000 are treated as seconds (so 180 means 180s, not 180ms). If the delegate does not finish in time, returns "failed (not ready)" \u2014 do NOT keep waiting or retry; go do other work, and a completion notification will still be injected when it completes.`
9247
9336
  })
9248
9337
  )
9249
9338
  });
@@ -9402,10 +9491,7 @@ function makeDelegateWaitTool(_pi) {
9402
9491
  }
9403
9492
  return buildWaitResult(run, formatRunResult(run), displayMode);
9404
9493
  }
9405
- const timeoutMs = Math.min(
9406
- Math.max(args.timeout ?? WAIT_TIMEOUT_MS_DEFAULT, 1e3),
9407
- WAIT_TIMEOUT_MS_MAX
9408
- );
9494
+ const timeoutMs = resolveWaitTimeoutMs(args.timeout);
9409
9495
  if (run.waiter) {
9410
9496
  return { details: void 0, content: [{ type: "text", text: `Delegate \`${args.runId}\` already has a wait in progress; do not wait on it twice.` }] };
9411
9497
  }
@@ -9526,8 +9612,8 @@ async function runDelegate(pi, args, ctx, signal) {
9526
9612
  },
9527
9613
  { eofGraceMs: EOF_GRACE_MS, idleMs: IDLE_GRACE_MS, timeoutMs: ASYNC_TIMEOUT_MS, killGraceMs: KILL_GRACE_MS }
9528
9614
  );
9529
- const replyFile = join4(OUT_DIR, `${runId}.out`);
9530
- const activityFile = join4(OUT_DIR, `${runId}.activity`);
9615
+ const replyFile = join6(OUT_DIR, `${runId}.out`);
9616
+ const activityFile = join6(OUT_DIR, `${runId}.activity`);
9531
9617
  await mkdir2(OUT_DIR, { recursive: true });
9532
9618
  const replyStream = createWriteStream(replyFile, { flags: "a" });
9533
9619
  const activityStream = useJsonStream ? createWriteStream(activityFile, { flags: "a" }) : null;
@@ -9677,8 +9763,8 @@ async function runDelegate(pi, args, ctx, signal) {
9677
9763
  return formatSyncResult(args.agent, runId, args.task, result, file);
9678
9764
  }
9679
9765
  async function buildChildArgs(args, rolePrompt, ctx) {
9680
- const tmpDir = await mkdtemp(join4(tmpdir2(), "acp-delegate-"));
9681
- const promptFile = join4(tmpDir, "role.md");
9766
+ const tmpDir = await mkdtemp(join6(tmpdir2(), "acp-delegate-"));
9767
+ const promptFile = join6(tmpDir, "role.md");
9682
9768
  await writeFile2(promptFile, `${rolePrompt}
9683
9769
 
9684
9770
  ---
@@ -9815,7 +9901,7 @@ async function persistResult(runId, body) {
9815
9901
  await mkdir2(OUT_DIR, { recursive: true });
9816
9902
  } catch {
9817
9903
  }
9818
- const file = join4(OUT_DIR, `${runId}.out`);
9904
+ const file = join6(OUT_DIR, `${runId}.out`);
9819
9905
  try {
9820
9906
  await writeFile2(file, body, "utf8");
9821
9907
  return file;
@@ -10002,7 +10088,7 @@ async function statusReport(runtime, ctx) {
10002
10088
  const modelId = ctx.model?.id ?? "default";
10003
10089
  const sentTokens = estimateTokens(coreMessages, coveredIds) + systemPromptTokens;
10004
10090
  const turn = runtime.core.processTurn({ messages: coreMessages, state, config, tokenCount: calibrateTokens(sentTokens, runtime.density.densityFor(modelId)) });
10005
- const versionStr = "0.1.39" ? `billion-context-pi@${"0.1.39"}` : void 0;
10091
+ const versionStr = "0.1.40" ? `billion-context-pi@${"0.1.40"}` : void 0;
10006
10092
  let text = buildStatusPanel({
10007
10093
  version: versionStr,
10008
10094
  tokenCount: sessionTokens,
@@ -10215,16 +10301,16 @@ function wireToolGuardrails(pi, runtime) {
10215
10301
 
10216
10302
  // src/update.ts
10217
10303
  import { readFile, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
10218
- import { join as join5, dirname as dirname5 } from "path";
10304
+ import { join as join7, dirname as dirname5 } from "path";
10219
10305
  import { fileURLToPath } from "url";
10220
10306
  import { execFile } from "child_process";
10221
- import { homedir as homedir3 } from "os";
10222
- import { CONFIG_DIR_NAME as CONFIG_DIR_NAME2 } from "@earendil-works/pi-coding-agent";
10307
+ import { homedir as homedir4 } from "os";
10308
+ import { CONFIG_DIR_NAME as CONFIG_DIR_NAME3 } from "@earendil-works/pi-coding-agent";
10223
10309
  var PACKAGE_NAME = "billion-context-pi";
10224
10310
  var REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
10225
10311
  var SEMVER_RE = /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/;
10226
10312
  var CHECK_INTERVAL_MS = 3 * 60 * 1e3;
10227
- var THROTTLE_FILE = join5(homedir3(), CONFIG_DIR_NAME2, "agent", ".billion-context-pi-update-check");
10313
+ var THROTTLE_FILE = join7(homedir4(), CONFIG_DIR_NAME3, "agent", ".billion-context-pi-update-check");
10228
10314
  var updateInFlight = false;
10229
10315
  function parseVersion(v) {
10230
10316
  return v.replace(/^v/, "").split(".").map((n) => parseInt(n, 10) || 0);
@@ -10273,7 +10359,7 @@ function findNpmRoot(extDir) {
10273
10359
  async function findExtensionDir() {
10274
10360
  let dir = dirname5(fileURLToPath(import.meta.url));
10275
10361
  for (; ; ) {
10276
- const pkg = await readPackageJson(join5(dir, "package.json"));
10362
+ const pkg = await readPackageJson(join7(dir, "package.json"));
10277
10363
  if (pkg?.name === PACKAGE_NAME) return dir;
10278
10364
  const parent = dirname5(dir);
10279
10365
  if (parent === dir) return void 0;
@@ -10324,7 +10410,7 @@ async function checkForUpdate(autoUpdate, notify) {
10324
10410
  const data = await res.json();
10325
10411
  const latest = data.version;
10326
10412
  if (!latest) return;
10327
- const current = runtimeVersion ?? "0.1.39";
10413
+ const current = runtimeVersion ?? "0.1.40";
10328
10414
  const hasUpdate = isNewer(latest, current);
10329
10415
  debug.event("update-check", {
10330
10416
  current,
@@ -10354,16 +10440,16 @@ async function checkForUpdate(autoUpdate, notify) {
10354
10440
  async function getRuntimeVersion() {
10355
10441
  const extDir = await findExtensionDir();
10356
10442
  if (!extDir) return void 0;
10357
- const pkg = await readPackageJson(join5(extDir, "package.json"));
10443
+ const pkg = await readPackageJson(join7(extDir, "package.json"));
10358
10444
  return pkg?.version;
10359
10445
  }
10360
10446
 
10361
10447
  // src/setup-subagent-tools.ts
10362
10448
  import { readFile as readFile2, writeFile as writeFile4, stat, copyFile, rename } from "fs/promises";
10363
10449
  import { existsSync as existsSync4 } from "fs";
10364
- import { homedir as homedir4 } from "os";
10365
- import { join as join6 } from "path";
10366
- import { CONFIG_DIR_NAME as CONFIG_DIR_NAME3 } from "@earendil-works/pi-coding-agent";
10450
+ import { homedir as homedir5 } from "os";
10451
+ import { join as join8 } from "path";
10452
+ import { CONFIG_DIR_NAME as CONFIG_DIR_NAME4 } from "@earendil-works/pi-coding-agent";
10367
10453
  var ACP_TOOLS2 = ["compress", "decompress", "search_context", "acp_status"];
10368
10454
  var BUILTIN_DEFAULT_TOOLS = {
10369
10455
  advisor: ["read", "grep", "find", "ls", "bash", "intercom"],
@@ -10378,9 +10464,9 @@ var BUILTIN_DEFAULT_TOOLS = {
10378
10464
  };
10379
10465
  function resolveAgentDir() {
10380
10466
  const configured = process.env.PI_CODING_AGENT_DIR;
10381
- if (configured === "~") return homedir4();
10382
- if (configured?.startsWith("~/")) return join6(homedir4(), configured.slice(2));
10383
- return configured || join6(homedir4(), CONFIG_DIR_NAME3, "agent");
10467
+ if (configured === "~") return homedir5();
10468
+ if (configured?.startsWith("~/")) return join8(homedir5(), configured.slice(2));
10469
+ return configured || join8(homedir5(), CONFIG_DIR_NAME4, "agent");
10384
10470
  }
10385
10471
  function desiredTools(existing, name) {
10386
10472
  const base = Array.isArray(existing?.tools) && existing.tools.length > 0 ? [...existing.tools] : [...BUILTIN_DEFAULT_TOOLS[name] ?? []];
@@ -10390,7 +10476,7 @@ function desiredTools(existing, name) {
10390
10476
  return { tools: base, changed: true };
10391
10477
  }
10392
10478
  async function ensureSubagentAcpTools(settingsPath) {
10393
- const path4 = settingsPath ?? join6(resolveAgentDir(), "settings.json");
10479
+ const path4 = settingsPath ?? join8(resolveAgentDir(), "settings.json");
10394
10480
  let raw;
10395
10481
  let mtimeMs;
10396
10482
  try {
@@ -10488,64 +10574,6 @@ async function runSetupAndNotify(notify) {
10488
10574
  }
10489
10575
  }
10490
10576
 
10491
- // src/user-config.ts
10492
- import { promises as fs2 } from "fs";
10493
- import * as path3 from "path";
10494
- import { homedir as homedir5 } from "os";
10495
- import { CONFIG_DIR_NAME as CONFIG_DIR_NAME4 } from "@earendil-works/pi-coding-agent";
10496
- async function loadUserConfig(cwd) {
10497
- const home = homedir5();
10498
- const merged = {};
10499
- for (const base of [join8(home, CONFIG_DIR_NAME4), join8(cwd, CONFIG_DIR_NAME4)]) {
10500
- const file = join8(base, "acp.json");
10501
- try {
10502
- const raw = await fs2.readFile(file, "utf8");
10503
- const parsed = JSON.parse(raw);
10504
- if (parsed && typeof parsed === "object") {
10505
- Object.assign(merged, pickKnown(parsed));
10506
- debug.event("config-loaded", { file });
10507
- }
10508
- } catch (e) {
10509
- const code = e.code;
10510
- if (code !== "ENOENT") {
10511
- logWarn("config", { event: "load-failed", file, error: e instanceof Error ? e.message : String(e) });
10512
- }
10513
- }
10514
- }
10515
- return merged;
10516
- }
10517
- function join8(...parts) {
10518
- return path3.join(...parts);
10519
- }
10520
- var KNOWN = /* @__PURE__ */ new Set([
10521
- "debug",
10522
- "autoUpdate",
10523
- "modelContextLimit",
10524
- "toolBashDefaultTimeout",
10525
- "toolOutputMaxBytes",
10526
- "delegate",
10527
- "compress",
10528
- "displayUsage",
10529
- "prompts",
10530
- "acknowledgePromptsRisk"
10531
- ]);
10532
- function pickKnown(parsed) {
10533
- const out = {};
10534
- for (const [k, v] of Object.entries(parsed)) {
10535
- if (KNOWN.has(k)) out[k] = v;
10536
- }
10537
- return out;
10538
- }
10539
- function applyUserConfig(adapter, user) {
10540
- return {
10541
- ...adapter,
10542
- ...user,
10543
- coreOverrides: adapter.coreOverrides,
10544
- protectedTools: adapter.protectedTools,
10545
- preserveRecentMessages: adapter.preserveRecentMessages
10546
- };
10547
- }
10548
-
10549
10577
  // src/index.ts
10550
10578
  function createAcpExtension(adapter = {}) {
10551
10579
  return (pi) => {
@@ -10579,12 +10607,10 @@ function wireSessionLifecycle(pi, runtime) {
10579
10607
  const sid = ctx.sessionManager.getSessionId();
10580
10608
  runtime.clearSessionTracking(sid);
10581
10609
  const modelInfo = ctx.model;
10582
- logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.1.39" : null, model: modelInfo?.id ?? null, modelApi: modelInfo?.api ?? null, contextWindow: modelInfo?.contextWindow ?? null });
10610
+ logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.1.40" : null, model: modelInfo?.id ?? null, modelApi: modelInfo?.api ?? null, contextWindow: modelInfo?.contextWindow ?? null });
10583
10611
  try {
10584
- const user = await loadUserConfig(ctx.cwd);
10585
- runtime.setAdapter(applyUserConfig(runtime.adapter, user));
10612
+ await runtime.reloadConfig(ctx.cwd);
10586
10613
  setDelegateDisplayUsage(resolveDelegate(runtime.adapter).displayUsage);
10587
- if (runtime.adapter.debug !== void 0) setDebugEnabled(runtime.adapter.debug);
10588
10614
  } catch (e) {
10589
10615
  logThrow("config", e, { sid, phase: "session_start" });
10590
10616
  }
@@ -10615,6 +10641,7 @@ function wireContextTransform(pi, runtime) {
10615
10641
  const sid = ctx.sessionManager.getSessionId();
10616
10642
  const release = await runtime.acquireLock(sid);
10617
10643
  try {
10644
+ await runtime.reloadConfig(ctx.cwd);
10618
10645
  const modelId = ctx.model?.id ?? "default";
10619
10646
  runtime.setCountModel(modelId);
10620
10647
  const { state, coreMessages, entries } = await runtime.stateFor(ctx, event.messages);