billion-context-pi 0.1.39 → 0.1.41
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/delegate-tool.d.ts +5 -0
- package/dist/index.js +163 -118
- package/dist/index.js.map +1 -1
- package/dist/runtime.d.ts +4 -1
- package/dist/tag-tokens.d.ts +3 -0
- package/package.json +1 -1
package/dist/delegate-tool.d.ts
CHANGED
|
@@ -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
|
@@ -2828,6 +2828,19 @@ function clamp(v, lo, hi) {
|
|
|
2828
2828
|
return v < lo ? lo : v > hi ? hi : v;
|
|
2829
2829
|
}
|
|
2830
2830
|
|
|
2831
|
+
// src/tag-tokens.ts
|
|
2832
|
+
function formatTokens3(tokens) {
|
|
2833
|
+
if (tokens < 1e3) return String(tokens);
|
|
2834
|
+
if (tokens < 1e4) return `${(tokens / 1e3).toFixed(1)}K`;
|
|
2835
|
+
return `${Math.round(tokens / 1e3)}K`;
|
|
2836
|
+
}
|
|
2837
|
+
function stableTagTokens(text) {
|
|
2838
|
+
return formatTokens3(defaultCountTokens(text));
|
|
2839
|
+
}
|
|
2840
|
+
function rewriteTagTokens(tag, body) {
|
|
2841
|
+
return tag.replace(/tokens="[^"]*"/, `tokens="${stableTagTokens(body)}"`);
|
|
2842
|
+
}
|
|
2843
|
+
|
|
2831
2844
|
// src/messages.ts
|
|
2832
2845
|
var REF_TAG_SOURCE = "(?:<acp\\s[^>]*>m\\d{5}</acp>|\\[m\\d{1,5}\\])";
|
|
2833
2846
|
var REF_TAG = new RegExp(`^${REF_TAG_SOURCE}\\s?\\n?`);
|
|
@@ -3037,6 +3050,7 @@ function reconstructToolCallMessage(original, firstCore, survivingCallIds) {
|
|
|
3037
3050
|
return true;
|
|
3038
3051
|
});
|
|
3039
3052
|
const peeled = peelRefTagBlocks(filtered);
|
|
3053
|
+
const stableTag = rewriteTagTokens(tag, coreBodyOf(firstCore.text ?? "", tag));
|
|
3040
3054
|
const lastTextIdx = [...peeled].reverse().findIndex((b) => b.type === "text");
|
|
3041
3055
|
if (lastTextIdx >= 0) {
|
|
3042
3056
|
const idx = peeled.length - 1 - lastTextIdx;
|
|
@@ -3044,10 +3058,16 @@ function reconstructToolCallMessage(original, firstCore, survivingCallIds) {
|
|
|
3044
3058
|
const baseText = lastBlock.text ?? "";
|
|
3045
3059
|
peeled[idx] = { ...lastBlock, text: baseText.length > 0 ? `${baseText}
|
|
3046
3060
|
|
|
3047
|
-
${
|
|
3061
|
+
${stableTag}` : stableTag };
|
|
3048
3062
|
return { ...original, content: peeled };
|
|
3049
3063
|
}
|
|
3050
|
-
return { ...original, content: [{ type: "text", text:
|
|
3064
|
+
return { ...original, content: [{ type: "text", text: stableTag }, ...peeled] };
|
|
3065
|
+
}
|
|
3066
|
+
function coreBodyOf(coreText, tag) {
|
|
3067
|
+
const tagCore = tag.replace(/\s+$/, "");
|
|
3068
|
+
let bodyStart = tagCore.length;
|
|
3069
|
+
if (coreText.charAt(bodyStart) === "\n") bodyStart += 1;
|
|
3070
|
+
return coreText.slice(bodyStart);
|
|
3051
3071
|
}
|
|
3052
3072
|
function patchRefTag(original, core) {
|
|
3053
3073
|
const match = core.text ? core.text.match(REF_TAG) : null;
|
|
@@ -3055,15 +3075,13 @@ function patchRefTag(original, core) {
|
|
|
3055
3075
|
if (!tag) return original;
|
|
3056
3076
|
const base = original;
|
|
3057
3077
|
if (base.role === "assistant") return original;
|
|
3058
|
-
const
|
|
3059
|
-
let bodyStart = tagCore.length;
|
|
3060
|
-
if (core.text && core.text.charAt(bodyStart) === "\n") bodyStart += 1;
|
|
3061
|
-
const coreBody = core.text ? core.text.slice(bodyStart) : "";
|
|
3078
|
+
const coreBody = coreBodyOf(core.text ?? "", tag);
|
|
3062
3079
|
const originalBody = extractText(base.content);
|
|
3063
3080
|
const trimEnd = (s) => s.replace(/\s+$/, "");
|
|
3064
3081
|
if (coreBody && trimEnd(coreBody) !== trimEnd(originalBody)) {
|
|
3065
|
-
return rebuildBodyFromCore(original, coreBody, tag);
|
|
3082
|
+
return rebuildBodyFromCore(original, coreBody, rewriteTagTokens(tag, coreBody));
|
|
3066
3083
|
}
|
|
3084
|
+
const stableTag = rewriteTagTokens(tag, originalBody);
|
|
3067
3085
|
const rawBlocks = Array.isArray(base.content) ? base.content : typeof base.content === "string" ? [{ type: "text", text: base.content }] : [];
|
|
3068
3086
|
const peeled = peelRefTagBlocks(rawBlocks);
|
|
3069
3087
|
const newBlocks = [...peeled];
|
|
@@ -3074,7 +3092,7 @@ function patchRefTag(original, core) {
|
|
|
3074
3092
|
const baseText = b.text.replace(/\n*$/, "");
|
|
3075
3093
|
newBlocks[i] = { ...b, text: `${baseText}
|
|
3076
3094
|
|
|
3077
|
-
${
|
|
3095
|
+
${stableTag}` };
|
|
3078
3096
|
injected = true;
|
|
3079
3097
|
break;
|
|
3080
3098
|
}
|
|
@@ -3084,7 +3102,7 @@ ${tag}` };
|
|
|
3084
3102
|
}
|
|
3085
3103
|
return {
|
|
3086
3104
|
...original,
|
|
3087
|
-
content: [...peeled, { type: "text", text:
|
|
3105
|
+
content: [...peeled, { type: "text", text: stableTag }]
|
|
3088
3106
|
};
|
|
3089
3107
|
}
|
|
3090
3108
|
function rebuildBodyFromCore(original, coreBody, tag) {
|
|
@@ -3341,6 +3359,64 @@ function mergeInitialState(parsed) {
|
|
|
3341
3359
|
};
|
|
3342
3360
|
}
|
|
3343
3361
|
|
|
3362
|
+
// src/user-config.ts
|
|
3363
|
+
import { promises as fs2 } from "fs";
|
|
3364
|
+
import * as path3 from "path";
|
|
3365
|
+
import { homedir as homedir2 } from "os";
|
|
3366
|
+
import { CONFIG_DIR_NAME as CONFIG_DIR_NAME2 } from "@earendil-works/pi-coding-agent";
|
|
3367
|
+
async function loadUserConfig(cwd) {
|
|
3368
|
+
const home = homedir2();
|
|
3369
|
+
const merged = {};
|
|
3370
|
+
for (const base of [join4(home, CONFIG_DIR_NAME2), join4(cwd, CONFIG_DIR_NAME2)]) {
|
|
3371
|
+
const file = join4(base, "acp.json");
|
|
3372
|
+
try {
|
|
3373
|
+
const raw = await fs2.readFile(file, "utf8");
|
|
3374
|
+
const parsed = JSON.parse(raw);
|
|
3375
|
+
if (parsed && typeof parsed === "object") {
|
|
3376
|
+
Object.assign(merged, pickKnown(parsed));
|
|
3377
|
+
debug.event("config-loaded", { file });
|
|
3378
|
+
}
|
|
3379
|
+
} catch (e) {
|
|
3380
|
+
const code = e.code;
|
|
3381
|
+
if (code !== "ENOENT") {
|
|
3382
|
+
logWarn("config", { event: "load-failed", file, error: e instanceof Error ? e.message : String(e) });
|
|
3383
|
+
}
|
|
3384
|
+
}
|
|
3385
|
+
}
|
|
3386
|
+
return merged;
|
|
3387
|
+
}
|
|
3388
|
+
function join4(...parts) {
|
|
3389
|
+
return path3.join(...parts);
|
|
3390
|
+
}
|
|
3391
|
+
var KNOWN = /* @__PURE__ */ new Set([
|
|
3392
|
+
"debug",
|
|
3393
|
+
"autoUpdate",
|
|
3394
|
+
"modelContextLimit",
|
|
3395
|
+
"toolBashDefaultTimeout",
|
|
3396
|
+
"toolOutputMaxBytes",
|
|
3397
|
+
"delegate",
|
|
3398
|
+
"compress",
|
|
3399
|
+
"displayUsage",
|
|
3400
|
+
"prompts",
|
|
3401
|
+
"acknowledgePromptsRisk"
|
|
3402
|
+
]);
|
|
3403
|
+
function pickKnown(parsed) {
|
|
3404
|
+
const out = {};
|
|
3405
|
+
for (const [k, v] of Object.entries(parsed)) {
|
|
3406
|
+
if (KNOWN.has(k)) out[k] = v;
|
|
3407
|
+
}
|
|
3408
|
+
return out;
|
|
3409
|
+
}
|
|
3410
|
+
function applyUserConfig(adapter, user) {
|
|
3411
|
+
return {
|
|
3412
|
+
...adapter,
|
|
3413
|
+
...user,
|
|
3414
|
+
coreOverrides: adapter.coreOverrides,
|
|
3415
|
+
protectedTools: adapter.protectedTools,
|
|
3416
|
+
preserveRecentMessages: adapter.preserveRecentMessages
|
|
3417
|
+
};
|
|
3418
|
+
}
|
|
3419
|
+
|
|
3344
3420
|
// src/sequence-match.ts
|
|
3345
3421
|
function findUniqueLongestRun(candidates, live) {
|
|
3346
3422
|
if (candidates.length === 0 || live.length === 0) return void 0;
|
|
@@ -3565,7 +3641,9 @@ function createRuntime(adapter) {
|
|
|
3565
3641
|
const store = new SessionStateStore();
|
|
3566
3642
|
const lastActiveBlockIds = /* @__PURE__ */ new Map();
|
|
3567
3643
|
const locks = /* @__PURE__ */ new Map();
|
|
3644
|
+
const factoryAdapter = adapter;
|
|
3568
3645
|
let adapterRef = adapter;
|
|
3646
|
+
let lastUserConfigKey;
|
|
3569
3647
|
let promptsRef = defaultPrompts;
|
|
3570
3648
|
const nudgeShownTurns = /* @__PURE__ */ new Set();
|
|
3571
3649
|
async function acquireLock(sid) {
|
|
@@ -3591,6 +3669,25 @@ function createRuntime(adapter) {
|
|
|
3591
3669
|
const m = ctx.model;
|
|
3592
3670
|
return resolveConfig(adapterRef, liveContextLimit(ctx), m?.provider, m?.id);
|
|
3593
3671
|
}
|
|
3672
|
+
async function reloadConfig(cwd) {
|
|
3673
|
+
let user;
|
|
3674
|
+
try {
|
|
3675
|
+
user = await loadUserConfig(cwd);
|
|
3676
|
+
} catch (e) {
|
|
3677
|
+
logWarn("runtime", { event: "config-reload-failed", error: e instanceof Error ? e.message : String(e) });
|
|
3678
|
+
return;
|
|
3679
|
+
}
|
|
3680
|
+
try {
|
|
3681
|
+
const key = JSON.stringify(user);
|
|
3682
|
+
if (key === lastUserConfigKey) return;
|
|
3683
|
+
lastUserConfigKey = key;
|
|
3684
|
+
adapterRef = applyUserConfig(factoryAdapter, user);
|
|
3685
|
+
if (adapterRef.debug !== void 0) setDebugEnabled(adapterRef.debug);
|
|
3686
|
+
logInfo("runtime", { event: "config-reloaded", limit: adapterRef.modelContextLimit ?? null });
|
|
3687
|
+
} catch (e) {
|
|
3688
|
+
logWarn("runtime", { event: "config-reload-failed", error: e instanceof Error ? e.message : String(e) });
|
|
3689
|
+
}
|
|
3690
|
+
}
|
|
3594
3691
|
async function stateFor(ctx, liveMessages) {
|
|
3595
3692
|
const sm = ctx.sessionManager;
|
|
3596
3693
|
const sessionFile = sm.getSessionFile() ?? void 0;
|
|
@@ -3626,8 +3723,6 @@ function createRuntime(adapter) {
|
|
|
3626
3723
|
countModelId = m;
|
|
3627
3724
|
}, noteActiveBlocks, clearSessionTracking, get adapter() {
|
|
3628
3725
|
return adapterRef;
|
|
3629
|
-
}, setAdapter: (a) => {
|
|
3630
|
-
adapterRef = a;
|
|
3631
3726
|
}, get prompts() {
|
|
3632
3727
|
return promptsRef;
|
|
3633
3728
|
}, setPrompts: (p) => {
|
|
@@ -3636,7 +3731,7 @@ function createRuntime(adapter) {
|
|
|
3636
3731
|
nudgeShownTurns.add(k);
|
|
3637
3732
|
}, nudgeShownFor: (k) => nudgeShownTurns.has(k), clearNudgeTracking: () => {
|
|
3638
3733
|
nudgeShownTurns.clear();
|
|
3639
|
-
}, liveContextLimit, configFor, stateFor, save, acquireLock };
|
|
3734
|
+
}, liveContextLimit, configFor, reloadConfig, stateFor, save, acquireLock };
|
|
3640
3735
|
}
|
|
3641
3736
|
|
|
3642
3737
|
// node_modules/typebox/build/system/memory/memory.mjs
|
|
@@ -8159,7 +8254,14 @@ async function handleCompress(args, runtime, ctx, toolCallId) {
|
|
|
8159
8254
|
});
|
|
8160
8255
|
await runtime.save(applied.state, ctx);
|
|
8161
8256
|
const { blocksCreated, tokensCompressed, errors, warnings } = applied.result;
|
|
8162
|
-
const
|
|
8257
|
+
const afterTurn = runtime.core.processTurn({
|
|
8258
|
+
messages: coreMessages,
|
|
8259
|
+
state: applied.state,
|
|
8260
|
+
config,
|
|
8261
|
+
tokenCount: calibrateTokens(sentTokens, density)
|
|
8262
|
+
});
|
|
8263
|
+
const afterTokens = calibrateTokens(estimateTokens(afterTurn.messages, collectCoveredMessageIds(applied.state)), density);
|
|
8264
|
+
const reclaimed = Math.max(0, beforeTokens - afterTokens);
|
|
8163
8265
|
const newBlocks = applied.state.blocks.slice(-blocksCreated);
|
|
8164
8266
|
debug.event("compress-out", {
|
|
8165
8267
|
sid: ctx.sessionManager.getSessionId(),
|
|
@@ -8190,9 +8292,9 @@ async function handleCompress(args, runtime, ctx, toolCallId) {
|
|
|
8190
8292
|
logError("compress", { sid: ctx.sessionManager.getSessionId(), event: "errors", count: errors.length, errors: errors.slice(0, 5) });
|
|
8191
8293
|
}
|
|
8192
8294
|
if (warnings.length > 0) {
|
|
8193
|
-
|
|
8295
|
+
logWarn("compress", { sid: ctx.sessionManager.getSessionId(), event: "warnings", count: warnings.length, warnings: warnings.slice(0, 5) });
|
|
8194
8296
|
}
|
|
8195
|
-
const lines = [`\u25A3 ACP | ${formatK2(beforeTokens)} \u2192 ${formatK2(afterTokens)} tokens (~${formatK2(
|
|
8297
|
+
const lines = [`\u25A3 ACP | ${formatK2(beforeTokens)} \u2192 ${formatK2(afterTokens)} tokens (~${formatK2(reclaimed)} reclaimed, ${blocksCreated} block${blocksCreated > 1 ? "s" : ""})`];
|
|
8196
8298
|
if (warnings.length > 0) lines.push("\u26A0\uFE0F " + warnings.join("; "));
|
|
8197
8299
|
if (errors.length > 0) lines.push("Errors: " + errors.join("; "));
|
|
8198
8300
|
return lines.join("\n");
|
|
@@ -8201,9 +8303,9 @@ async function handleCompress(args, runtime, ctx, toolCallId) {
|
|
|
8201
8303
|
// src/decompress-tool.ts
|
|
8202
8304
|
import { writeFile, mkdir } from "fs/promises";
|
|
8203
8305
|
import { existsSync as existsSync2, lstatSync, readlinkSync, realpathSync } from "fs";
|
|
8204
|
-
import { resolve, relative, isAbsolute, join as
|
|
8205
|
-
import { tmpdir, homedir as
|
|
8206
|
-
var AUTO_DIR =
|
|
8306
|
+
import { resolve, relative, isAbsolute, join as join5, basename as basename2, dirname as dirname3 } from "path";
|
|
8307
|
+
import { tmpdir, homedir as homedir3 } from "os";
|
|
8308
|
+
var AUTO_DIR = join5(homedir3() || tmpdir(), ".cache", "pi", "acp-decompress");
|
|
8207
8309
|
var PREVIEW_CHARS = 600;
|
|
8208
8310
|
var MESSAGE_INLINE_THRESHOLD = 2e3;
|
|
8209
8311
|
var DecompressParams = typebox_exports.Object({
|
|
@@ -8239,11 +8341,11 @@ function makeDecompressTool(runtime) {
|
|
|
8239
8341
|
}
|
|
8240
8342
|
var ALLOWED_DIRS = [
|
|
8241
8343
|
tmpdir(),
|
|
8242
|
-
|
|
8243
|
-
|
|
8344
|
+
join5(homedir3(), ".cache", "opencode"),
|
|
8345
|
+
join5(homedir3(), ".cache", "pi")
|
|
8244
8346
|
];
|
|
8245
8347
|
function resolveToFilePath(targetPath) {
|
|
8246
|
-
const expanded = targetPath.startsWith("~/") ?
|
|
8348
|
+
const expanded = targetPath.startsWith("~/") ? join5(homedir3(), targetPath.slice(2)) : targetPath;
|
|
8247
8349
|
const resolved = resolve(expanded);
|
|
8248
8350
|
let probe = resolved;
|
|
8249
8351
|
const suffix = [];
|
|
@@ -8254,7 +8356,7 @@ function resolveToFilePath(targetPath) {
|
|
|
8254
8356
|
const real = existsSync2(probe) ? realpathSync(probe) : probe;
|
|
8255
8357
|
let checked = real;
|
|
8256
8358
|
for (const part of suffix) {
|
|
8257
|
-
checked =
|
|
8359
|
+
checked = join5(checked, part);
|
|
8258
8360
|
try {
|
|
8259
8361
|
if (lstatSync(checked).isSymbolicLink()) {
|
|
8260
8362
|
const target = readlinkSync(checked);
|
|
@@ -8280,7 +8382,7 @@ function resolveToFilePath(targetPath) {
|
|
|
8280
8382
|
return checked;
|
|
8281
8383
|
}
|
|
8282
8384
|
function autoFilePath(blockId) {
|
|
8283
|
-
return
|
|
8385
|
+
return join5(AUTO_DIR, `${blockId}-${Date.now()}.txt`);
|
|
8284
8386
|
}
|
|
8285
8387
|
function headPreview(text) {
|
|
8286
8388
|
if (text.length <= PREVIEW_CHARS) return text;
|
|
@@ -8627,7 +8729,7 @@ import {
|
|
|
8627
8729
|
import { createWriteStream, existsSync as existsSync3 } from "fs";
|
|
8628
8730
|
import { mkdir as mkdir2, mkdtemp, writeFile as writeFile2, rm, appendFile } from "fs/promises";
|
|
8629
8731
|
import { tmpdir as tmpdir2 } from "os";
|
|
8630
|
-
import { dirname as dirname4, join as
|
|
8732
|
+
import { dirname as dirname4, join as join6, resolve as resolvePath } from "path";
|
|
8631
8733
|
|
|
8632
8734
|
// src/footer-status.ts
|
|
8633
8735
|
var FOOTER_STATUS_KEY = "billion-context-pi";
|
|
@@ -9031,7 +9133,7 @@ var IDLE_GRACE_MS = 5 * 6e4;
|
|
|
9031
9133
|
var ASYNC_TIMEOUT_MS = 30 * 6e4;
|
|
9032
9134
|
var KILL_GRACE_MS = 1e4;
|
|
9033
9135
|
var RESULT_SUMMARY_CHARS = 500;
|
|
9034
|
-
var OUT_DIR =
|
|
9136
|
+
var OUT_DIR = join6(tmpdir2(), "acp-delegate");
|
|
9035
9137
|
function delegateSpawnOptions(cwd, env) {
|
|
9036
9138
|
return {
|
|
9037
9139
|
cwd,
|
|
@@ -9041,11 +9143,11 @@ function delegateSpawnOptions(cwd, env) {
|
|
|
9041
9143
|
};
|
|
9042
9144
|
}
|
|
9043
9145
|
var PI_CLI_ENTRY_RE = /[\\/]pi-coding-agent[\\/]dist[\\/]cli\.js$/;
|
|
9044
|
-
var PI_PACKAGE_REL =
|
|
9146
|
+
var PI_PACKAGE_REL = join6("@earendil-works", "pi-coding-agent", "dist", "cli.js");
|
|
9045
9147
|
function probeUpFromArgv(argv1) {
|
|
9046
9148
|
let dir = resolvePath(dirname4(argv1) || process.cwd());
|
|
9047
9149
|
for (; ; ) {
|
|
9048
|
-
const candidate =
|
|
9150
|
+
const candidate = join6(dir, "node_modules", PI_PACKAGE_REL);
|
|
9049
9151
|
if (existsSync3(candidate)) return candidate;
|
|
9050
9152
|
const parent = dirname4(dir);
|
|
9051
9153
|
if (parent === dir) return null;
|
|
@@ -9055,12 +9157,12 @@ function probeUpFromArgv(argv1) {
|
|
|
9055
9157
|
function piCliGlobalCandidates(env) {
|
|
9056
9158
|
const candidates = [];
|
|
9057
9159
|
if (process.platform === "win32") {
|
|
9058
|
-
if (env.APPDATA) candidates.push(
|
|
9160
|
+
if (env.APPDATA) candidates.push(join6(env.APPDATA, "npm", "node_modules", PI_PACKAGE_REL));
|
|
9059
9161
|
} else {
|
|
9060
9162
|
const home = env.HOME ?? env.USERPROFILE;
|
|
9061
|
-
if (home) candidates.push(
|
|
9062
|
-
candidates.push(
|
|
9063
|
-
candidates.push(
|
|
9163
|
+
if (home) candidates.push(join6(home, ".local", "lib", "node_modules", PI_PACKAGE_REL));
|
|
9164
|
+
candidates.push(join6("/usr/local", "lib", "node_modules", PI_PACKAGE_REL));
|
|
9165
|
+
candidates.push(join6("/usr", "lib", "node_modules", PI_PACKAGE_REL));
|
|
9064
9166
|
}
|
|
9065
9167
|
return candidates;
|
|
9066
9168
|
}
|
|
@@ -9212,6 +9314,11 @@ function makeEventApplier(opts, writers) {
|
|
|
9212
9314
|
}
|
|
9213
9315
|
var WAIT_TIMEOUT_MS_DEFAULT = 1e4;
|
|
9214
9316
|
var WAIT_TIMEOUT_MS_MAX = 3e5;
|
|
9317
|
+
function resolveWaitTimeoutMs(raw) {
|
|
9318
|
+
if (raw === void 0) return WAIT_TIMEOUT_MS_DEFAULT;
|
|
9319
|
+
const ms = raw < 1e3 ? raw * 1e3 : raw;
|
|
9320
|
+
return Math.min(Math.max(ms, 1e3), WAIT_TIMEOUT_MS_MAX);
|
|
9321
|
+
}
|
|
9215
9322
|
var DelegateParams = typebox_exports.Object({
|
|
9216
9323
|
agent: typebox_exports.String({
|
|
9217
9324
|
description: `Role of the delegate. One of: ${AGENT_NAMES.join(", ")}. See tool description for what each does.`
|
|
@@ -9243,7 +9350,7 @@ var WaitParams = typebox_exports.Object({
|
|
|
9243
9350
|
runId: typebox_exports.String({ description: "The runId returned by acp_delegate to wait for." }),
|
|
9244
9351
|
timeout: typebox_exports.Optional(
|
|
9245
9352
|
typebox_exports.Integer({
|
|
9246
|
-
description: `Maximum
|
|
9353
|
+
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
9354
|
})
|
|
9248
9355
|
)
|
|
9249
9356
|
});
|
|
@@ -9402,10 +9509,7 @@ function makeDelegateWaitTool(_pi) {
|
|
|
9402
9509
|
}
|
|
9403
9510
|
return buildWaitResult(run, formatRunResult(run), displayMode);
|
|
9404
9511
|
}
|
|
9405
|
-
const timeoutMs =
|
|
9406
|
-
Math.max(args.timeout ?? WAIT_TIMEOUT_MS_DEFAULT, 1e3),
|
|
9407
|
-
WAIT_TIMEOUT_MS_MAX
|
|
9408
|
-
);
|
|
9512
|
+
const timeoutMs = resolveWaitTimeoutMs(args.timeout);
|
|
9409
9513
|
if (run.waiter) {
|
|
9410
9514
|
return { details: void 0, content: [{ type: "text", text: `Delegate \`${args.runId}\` already has a wait in progress; do not wait on it twice.` }] };
|
|
9411
9515
|
}
|
|
@@ -9526,8 +9630,8 @@ async function runDelegate(pi, args, ctx, signal) {
|
|
|
9526
9630
|
},
|
|
9527
9631
|
{ eofGraceMs: EOF_GRACE_MS, idleMs: IDLE_GRACE_MS, timeoutMs: ASYNC_TIMEOUT_MS, killGraceMs: KILL_GRACE_MS }
|
|
9528
9632
|
);
|
|
9529
|
-
const replyFile =
|
|
9530
|
-
const activityFile =
|
|
9633
|
+
const replyFile = join6(OUT_DIR, `${runId}.out`);
|
|
9634
|
+
const activityFile = join6(OUT_DIR, `${runId}.activity`);
|
|
9531
9635
|
await mkdir2(OUT_DIR, { recursive: true });
|
|
9532
9636
|
const replyStream = createWriteStream(replyFile, { flags: "a" });
|
|
9533
9637
|
const activityStream = useJsonStream ? createWriteStream(activityFile, { flags: "a" }) : null;
|
|
@@ -9677,8 +9781,8 @@ async function runDelegate(pi, args, ctx, signal) {
|
|
|
9677
9781
|
return formatSyncResult(args.agent, runId, args.task, result, file);
|
|
9678
9782
|
}
|
|
9679
9783
|
async function buildChildArgs(args, rolePrompt, ctx) {
|
|
9680
|
-
const tmpDir = await mkdtemp(
|
|
9681
|
-
const promptFile =
|
|
9784
|
+
const tmpDir = await mkdtemp(join6(tmpdir2(), "acp-delegate-"));
|
|
9785
|
+
const promptFile = join6(tmpDir, "role.md");
|
|
9682
9786
|
await writeFile2(promptFile, `${rolePrompt}
|
|
9683
9787
|
|
|
9684
9788
|
---
|
|
@@ -9815,7 +9919,7 @@ async function persistResult(runId, body) {
|
|
|
9815
9919
|
await mkdir2(OUT_DIR, { recursive: true });
|
|
9816
9920
|
} catch {
|
|
9817
9921
|
}
|
|
9818
|
-
const file =
|
|
9922
|
+
const file = join6(OUT_DIR, `${runId}.out`);
|
|
9819
9923
|
try {
|
|
9820
9924
|
await writeFile2(file, body, "utf8");
|
|
9821
9925
|
return file;
|
|
@@ -10002,7 +10106,7 @@ async function statusReport(runtime, ctx) {
|
|
|
10002
10106
|
const modelId = ctx.model?.id ?? "default";
|
|
10003
10107
|
const sentTokens = estimateTokens(coreMessages, coveredIds) + systemPromptTokens;
|
|
10004
10108
|
const turn = runtime.core.processTurn({ messages: coreMessages, state, config, tokenCount: calibrateTokens(sentTokens, runtime.density.densityFor(modelId)) });
|
|
10005
|
-
const versionStr = "0.1.
|
|
10109
|
+
const versionStr = "0.1.41" ? `billion-context-pi@${"0.1.41"}` : void 0;
|
|
10006
10110
|
let text = buildStatusPanel({
|
|
10007
10111
|
version: versionStr,
|
|
10008
10112
|
tokenCount: sessionTokens,
|
|
@@ -10215,16 +10319,16 @@ function wireToolGuardrails(pi, runtime) {
|
|
|
10215
10319
|
|
|
10216
10320
|
// src/update.ts
|
|
10217
10321
|
import { readFile, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
10218
|
-
import { join as
|
|
10322
|
+
import { join as join7, dirname as dirname5 } from "path";
|
|
10219
10323
|
import { fileURLToPath } from "url";
|
|
10220
10324
|
import { execFile } from "child_process";
|
|
10221
|
-
import { homedir as
|
|
10222
|
-
import { CONFIG_DIR_NAME as
|
|
10325
|
+
import { homedir as homedir4 } from "os";
|
|
10326
|
+
import { CONFIG_DIR_NAME as CONFIG_DIR_NAME3 } from "@earendil-works/pi-coding-agent";
|
|
10223
10327
|
var PACKAGE_NAME = "billion-context-pi";
|
|
10224
10328
|
var REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
|
|
10225
10329
|
var SEMVER_RE = /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/;
|
|
10226
10330
|
var CHECK_INTERVAL_MS = 3 * 60 * 1e3;
|
|
10227
|
-
var THROTTLE_FILE =
|
|
10331
|
+
var THROTTLE_FILE = join7(homedir4(), CONFIG_DIR_NAME3, "agent", ".billion-context-pi-update-check");
|
|
10228
10332
|
var updateInFlight = false;
|
|
10229
10333
|
function parseVersion(v) {
|
|
10230
10334
|
return v.replace(/^v/, "").split(".").map((n) => parseInt(n, 10) || 0);
|
|
@@ -10273,7 +10377,7 @@ function findNpmRoot(extDir) {
|
|
|
10273
10377
|
async function findExtensionDir() {
|
|
10274
10378
|
let dir = dirname5(fileURLToPath(import.meta.url));
|
|
10275
10379
|
for (; ; ) {
|
|
10276
|
-
const pkg = await readPackageJson(
|
|
10380
|
+
const pkg = await readPackageJson(join7(dir, "package.json"));
|
|
10277
10381
|
if (pkg?.name === PACKAGE_NAME) return dir;
|
|
10278
10382
|
const parent = dirname5(dir);
|
|
10279
10383
|
if (parent === dir) return void 0;
|
|
@@ -10324,7 +10428,7 @@ async function checkForUpdate(autoUpdate, notify) {
|
|
|
10324
10428
|
const data = await res.json();
|
|
10325
10429
|
const latest = data.version;
|
|
10326
10430
|
if (!latest) return;
|
|
10327
|
-
const current = runtimeVersion ?? "0.1.
|
|
10431
|
+
const current = runtimeVersion ?? "0.1.41";
|
|
10328
10432
|
const hasUpdate = isNewer(latest, current);
|
|
10329
10433
|
debug.event("update-check", {
|
|
10330
10434
|
current,
|
|
@@ -10354,16 +10458,16 @@ async function checkForUpdate(autoUpdate, notify) {
|
|
|
10354
10458
|
async function getRuntimeVersion() {
|
|
10355
10459
|
const extDir = await findExtensionDir();
|
|
10356
10460
|
if (!extDir) return void 0;
|
|
10357
|
-
const pkg = await readPackageJson(
|
|
10461
|
+
const pkg = await readPackageJson(join7(extDir, "package.json"));
|
|
10358
10462
|
return pkg?.version;
|
|
10359
10463
|
}
|
|
10360
10464
|
|
|
10361
10465
|
// src/setup-subagent-tools.ts
|
|
10362
10466
|
import { readFile as readFile2, writeFile as writeFile4, stat, copyFile, rename } from "fs/promises";
|
|
10363
10467
|
import { existsSync as existsSync4 } from "fs";
|
|
10364
|
-
import { homedir as
|
|
10365
|
-
import { join as
|
|
10366
|
-
import { CONFIG_DIR_NAME as
|
|
10468
|
+
import { homedir as homedir5 } from "os";
|
|
10469
|
+
import { join as join8 } from "path";
|
|
10470
|
+
import { CONFIG_DIR_NAME as CONFIG_DIR_NAME4 } from "@earendil-works/pi-coding-agent";
|
|
10367
10471
|
var ACP_TOOLS2 = ["compress", "decompress", "search_context", "acp_status"];
|
|
10368
10472
|
var BUILTIN_DEFAULT_TOOLS = {
|
|
10369
10473
|
advisor: ["read", "grep", "find", "ls", "bash", "intercom"],
|
|
@@ -10378,9 +10482,9 @@ var BUILTIN_DEFAULT_TOOLS = {
|
|
|
10378
10482
|
};
|
|
10379
10483
|
function resolveAgentDir() {
|
|
10380
10484
|
const configured = process.env.PI_CODING_AGENT_DIR;
|
|
10381
|
-
if (configured === "~") return
|
|
10382
|
-
if (configured?.startsWith("~/")) return
|
|
10383
|
-
return configured ||
|
|
10485
|
+
if (configured === "~") return homedir5();
|
|
10486
|
+
if (configured?.startsWith("~/")) return join8(homedir5(), configured.slice(2));
|
|
10487
|
+
return configured || join8(homedir5(), CONFIG_DIR_NAME4, "agent");
|
|
10384
10488
|
}
|
|
10385
10489
|
function desiredTools(existing, name) {
|
|
10386
10490
|
const base = Array.isArray(existing?.tools) && existing.tools.length > 0 ? [...existing.tools] : [...BUILTIN_DEFAULT_TOOLS[name] ?? []];
|
|
@@ -10390,7 +10494,7 @@ function desiredTools(existing, name) {
|
|
|
10390
10494
|
return { tools: base, changed: true };
|
|
10391
10495
|
}
|
|
10392
10496
|
async function ensureSubagentAcpTools(settingsPath) {
|
|
10393
|
-
const path4 = settingsPath ??
|
|
10497
|
+
const path4 = settingsPath ?? join8(resolveAgentDir(), "settings.json");
|
|
10394
10498
|
let raw;
|
|
10395
10499
|
let mtimeMs;
|
|
10396
10500
|
try {
|
|
@@ -10488,64 +10592,6 @@ async function runSetupAndNotify(notify) {
|
|
|
10488
10592
|
}
|
|
10489
10593
|
}
|
|
10490
10594
|
|
|
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
10595
|
// src/index.ts
|
|
10550
10596
|
function createAcpExtension(adapter = {}) {
|
|
10551
10597
|
return (pi) => {
|
|
@@ -10579,12 +10625,10 @@ function wireSessionLifecycle(pi, runtime) {
|
|
|
10579
10625
|
const sid = ctx.sessionManager.getSessionId();
|
|
10580
10626
|
runtime.clearSessionTracking(sid);
|
|
10581
10627
|
const modelInfo = ctx.model;
|
|
10582
|
-
logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.1.
|
|
10628
|
+
logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.1.41" : null, model: modelInfo?.id ?? null, modelApi: modelInfo?.api ?? null, contextWindow: modelInfo?.contextWindow ?? null });
|
|
10583
10629
|
try {
|
|
10584
|
-
|
|
10585
|
-
runtime.setAdapter(applyUserConfig(runtime.adapter, user));
|
|
10630
|
+
await runtime.reloadConfig(ctx.cwd);
|
|
10586
10631
|
setDelegateDisplayUsage(resolveDelegate(runtime.adapter).displayUsage);
|
|
10587
|
-
if (runtime.adapter.debug !== void 0) setDebugEnabled(runtime.adapter.debug);
|
|
10588
10632
|
} catch (e) {
|
|
10589
10633
|
logThrow("config", e, { sid, phase: "session_start" });
|
|
10590
10634
|
}
|
|
@@ -10615,6 +10659,7 @@ function wireContextTransform(pi, runtime) {
|
|
|
10615
10659
|
const sid = ctx.sessionManager.getSessionId();
|
|
10616
10660
|
const release = await runtime.acquireLock(sid);
|
|
10617
10661
|
try {
|
|
10662
|
+
await runtime.reloadConfig(ctx.cwd);
|
|
10618
10663
|
const modelId = ctx.model?.id ?? "default";
|
|
10619
10664
|
runtime.setCountModel(modelId);
|
|
10620
10665
|
const { state, coreMessages, entries } = await runtime.stateFor(ctx, event.messages);
|