billion-context-omp 0.3.2 → 0.3.3-pr.146.13
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/README.md +16 -7
- package/README.zh-CN.md +13 -8
- package/dist/index.js +330 -159
- package/dist/index.js.map +1 -1
- package/dist/messages.d.ts +4 -29
- package/dist/wire-fold.d.ts +4 -80
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { settings } from "@oh-my-pi/pi-coding-agent";
|
|
3
|
+
|
|
1
4
|
// node_modules/acp-kernel/dist/chunk-MWXUJVMN.js
|
|
2
5
|
import { createRequire } from "module";
|
|
3
6
|
var require2 = createRequire(import.meta.url);
|
|
@@ -1622,7 +1625,7 @@ function createCore(ports = {}) {
|
|
|
1622
1625
|
if (!hasBlockBoundaryRange && totalRangeChars < input.config.compress.minCompressRange) {
|
|
1623
1626
|
const live = activeBlocks(state).map((b) => b.blockId).sort((x, y) => numericBlockId(x) - numericBlockId(y));
|
|
1624
1627
|
const liveHint = live.length > 0 ? ` Current active blocks span ${live[0]}..${live[live.length - 1]} \u2014 retry with startId/endId set to active block IDs in that span.` : "";
|
|
1625
|
-
const gateMessage = resolvableCount === 0 && consumedRanges.length === 0 && unknownCount > 0 ? `None of the ${input.ranges.length} requested range(s) resolved \u2014 every ref failed with "does not exist in this session". Refs recorded before an earlier compress are stale: each successful compress renumbers the remaining refs. Run acp_status, then
|
|
1628
|
+
const gateMessage = resolvableCount === 0 && consumedRanges.length === 0 && unknownCount > 0 ? `None of the ${input.ranges.length} requested range(s) resolved \u2014 every ref failed with "does not exist in this session". Refs recorded before an earlier compress are stale: each successful compress renumbers the remaining refs. Run acp_status, then call the compress tool again using only the refs it reports.` : consumedRanges.length > 0 ? `Requested range(s) already compressed (e.g. ${consumedRanges[0].startRef}..${consumedRanges[0].endRef}) \u2014 your refs are stale: a prior compress renumbered the remaining refs, so this range now falls inside an active block. Run acp_status, then call the compress tool again using only the CURRENT compressible ranges it reports.${liveHint}` : `Total compressible content too small (${totalRangeChars} chars across ${countedRanges} range(s), min ${input.config.compress.minCompressRange}). Combine more messages into your range(s) to meet the threshold.`;
|
|
1626
1629
|
return {
|
|
1627
1630
|
state: input.state,
|
|
1628
1631
|
result: {
|
|
@@ -2348,6 +2351,144 @@ function countOccurrences(haystack, needle) {
|
|
|
2348
2351
|
}
|
|
2349
2352
|
return count;
|
|
2350
2353
|
}
|
|
2354
|
+
var COMPRESS_TOOL_NAME = "compress";
|
|
2355
|
+
var DECOMPRESS_TOOL_NAME = "decompress";
|
|
2356
|
+
var SEARCH_CONTEXT_TOOL_NAME = "search_context";
|
|
2357
|
+
var ACP_STATUS_TOOL_NAME = "acp_status";
|
|
2358
|
+
var COMPRESS_TOOL = {
|
|
2359
|
+
name: COMPRESS_TOOL_NAME,
|
|
2360
|
+
description: "Replace a contiguous range of older conversation with a detailed summary you write. Use when content is genuinely consumed. Batch form: content=[{startId,endId,summary,topic?}]. REQUIRED \u2014 compress without content is invalid.",
|
|
2361
|
+
input_schema: {
|
|
2362
|
+
type: "object",
|
|
2363
|
+
properties: {
|
|
2364
|
+
topic: { type: "string", description: "Optional short title for the compressed range" },
|
|
2365
|
+
content: {
|
|
2366
|
+
type: "array",
|
|
2367
|
+
description: "One or more ranges to compress into separate summary blocks",
|
|
2368
|
+
items: {
|
|
2369
|
+
type: "object",
|
|
2370
|
+
properties: {
|
|
2371
|
+
topic: { type: "string" },
|
|
2372
|
+
startId: { type: "string", description: "mNNNNN ref at the start of the range" },
|
|
2373
|
+
endId: { type: "string", description: "mNNNNN ref at the end of the range" },
|
|
2374
|
+
summary: { type: "string", description: "Self-contained summary replacing the range" }
|
|
2375
|
+
},
|
|
2376
|
+
required: ["startId", "endId", "summary"]
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
},
|
|
2380
|
+
required: ["content"]
|
|
2381
|
+
}
|
|
2382
|
+
};
|
|
2383
|
+
var COMPRESS_TOOL_OPENAI = {
|
|
2384
|
+
type: "function",
|
|
2385
|
+
function: {
|
|
2386
|
+
name: COMPRESS_TOOL_NAME,
|
|
2387
|
+
description: COMPRESS_TOOL.description,
|
|
2388
|
+
parameters: {
|
|
2389
|
+
type: "object",
|
|
2390
|
+
properties: {
|
|
2391
|
+
topic: { type: "string", description: "Optional short title for the compressed range" },
|
|
2392
|
+
content: {
|
|
2393
|
+
type: "array",
|
|
2394
|
+
description: "One or more ranges to compress into separate summary blocks. REQUIRED \u2014 compress without content is invalid.",
|
|
2395
|
+
items: {
|
|
2396
|
+
type: "object",
|
|
2397
|
+
properties: {
|
|
2398
|
+
topic: { type: "string" },
|
|
2399
|
+
startId: { type: "string", description: "mNNNNN ref at the start of the range" },
|
|
2400
|
+
endId: { type: "string", description: "mNNNNN ref at the end of the range" },
|
|
2401
|
+
summary: { type: "string", description: "Self-contained summary replacing the range" }
|
|
2402
|
+
},
|
|
2403
|
+
required: ["startId", "endId", "summary"]
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
},
|
|
2407
|
+
required: ["content"]
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
};
|
|
2411
|
+
var DECOMPRESS_TOOL_OPENAI = {
|
|
2412
|
+
type: "function",
|
|
2413
|
+
function: {
|
|
2414
|
+
name: DECOMPRESS_TOOL_NAME,
|
|
2415
|
+
description: "Restores previously compressed content. Use when you need exact details lost in compression. By default restores one tier up. Use full:true for all the way to original messages. Use toFile to write to file instead of inflating context.",
|
|
2416
|
+
parameters: {
|
|
2417
|
+
type: "object",
|
|
2418
|
+
properties: {
|
|
2419
|
+
blockId: { type: "string", description: "Block ID to decompress (e.g. b5)" },
|
|
2420
|
+
toFile: { type: "string", description: "Optional: write content to file instead of context" },
|
|
2421
|
+
full: { type: "boolean", description: "Restore all the way to original messages" }
|
|
2422
|
+
},
|
|
2423
|
+
required: ["blockId"]
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
};
|
|
2427
|
+
var SEARCH_CONTEXT_TOOL_OPENAI = {
|
|
2428
|
+
type: "function",
|
|
2429
|
+
function: {
|
|
2430
|
+
name: SEARCH_CONTEXT_TOOL_NAME,
|
|
2431
|
+
description: "Search through compressed block summaries by keyword. Use BEFORE decompressing to find the right block.",
|
|
2432
|
+
parameters: {
|
|
2433
|
+
type: "object",
|
|
2434
|
+
properties: {
|
|
2435
|
+
query: { type: "string", description: "Search query" },
|
|
2436
|
+
limit: { type: "number", description: "Max results (default 5)" }
|
|
2437
|
+
},
|
|
2438
|
+
required: ["query"]
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
};
|
|
2442
|
+
var ACP_STATUS_TOOL_OPENAI = {
|
|
2443
|
+
type: "function",
|
|
2444
|
+
function: {
|
|
2445
|
+
name: ACP_STATUS_TOOL_NAME,
|
|
2446
|
+
description: "Show context usage and compressible ranges. No args = overview. Use to find what to compress next.",
|
|
2447
|
+
parameters: {
|
|
2448
|
+
type: "object",
|
|
2449
|
+
properties: {}
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
};
|
|
2453
|
+
var DECOMPRESS_TOOL = {
|
|
2454
|
+
name: DECOMPRESS_TOOL_NAME,
|
|
2455
|
+
description: DECOMPRESS_TOOL_OPENAI.function.description,
|
|
2456
|
+
input_schema: DECOMPRESS_TOOL_OPENAI.function.parameters
|
|
2457
|
+
};
|
|
2458
|
+
var SEARCH_CONTEXT_TOOL = {
|
|
2459
|
+
name: SEARCH_CONTEXT_TOOL_NAME,
|
|
2460
|
+
description: SEARCH_CONTEXT_TOOL_OPENAI.function.description,
|
|
2461
|
+
input_schema: SEARCH_CONTEXT_TOOL_OPENAI.function.parameters
|
|
2462
|
+
};
|
|
2463
|
+
var ACP_STATUS_TOOL = {
|
|
2464
|
+
name: ACP_STATUS_TOOL_NAME,
|
|
2465
|
+
description: ACP_STATUS_TOOL_OPENAI.function.description,
|
|
2466
|
+
input_schema: ACP_STATUS_TOOL_OPENAI.function.parameters
|
|
2467
|
+
};
|
|
2468
|
+
var COMPRESS_TOOL_RESPONSES = {
|
|
2469
|
+
type: "function",
|
|
2470
|
+
name: COMPRESS_TOOL_NAME,
|
|
2471
|
+
description: COMPRESS_TOOL.description,
|
|
2472
|
+
parameters: COMPRESS_TOOL_OPENAI.function.parameters
|
|
2473
|
+
};
|
|
2474
|
+
var DECOMPRESS_TOOL_RESPONSES = {
|
|
2475
|
+
type: "function",
|
|
2476
|
+
name: DECOMPRESS_TOOL_OPENAI.function.name,
|
|
2477
|
+
description: DECOMPRESS_TOOL_OPENAI.function.description,
|
|
2478
|
+
parameters: DECOMPRESS_TOOL_OPENAI.function.parameters
|
|
2479
|
+
};
|
|
2480
|
+
var SEARCH_CONTEXT_TOOL_RESPONSES = {
|
|
2481
|
+
type: "function",
|
|
2482
|
+
name: SEARCH_CONTEXT_TOOL_OPENAI.function.name,
|
|
2483
|
+
description: SEARCH_CONTEXT_TOOL_OPENAI.function.description,
|
|
2484
|
+
parameters: SEARCH_CONTEXT_TOOL_OPENAI.function.parameters
|
|
2485
|
+
};
|
|
2486
|
+
var ACP_STATUS_TOOL_RESPONSES = {
|
|
2487
|
+
type: "function",
|
|
2488
|
+
name: ACP_STATUS_TOOL_OPENAI.function.name,
|
|
2489
|
+
description: ACP_STATUS_TOOL_OPENAI.function.description,
|
|
2490
|
+
parameters: ACP_STATUS_TOOL_OPENAI.function.parameters
|
|
2491
|
+
};
|
|
2351
2492
|
function parseBlockIdArg(arg) {
|
|
2352
2493
|
const normalized = arg.trim().toLowerCase();
|
|
2353
2494
|
const refMatch = /^b0*(\d+)$/.exec(normalized);
|
|
@@ -3529,6 +3670,7 @@ When context usage passes a threshold, the system appends a breakdown showing wh
|
|
|
3529
3670
|
|
|
3530
3671
|
// node_modules/acp-kernel/dist/wire/index.js
|
|
3531
3672
|
import { createHash as createHash2 } from "crypto";
|
|
3673
|
+
import { createHash as createHash22 } from "crypto";
|
|
3532
3674
|
function hashId(s) {
|
|
3533
3675
|
return createHash2("sha256").update(s, "utf8").digest("hex").slice(0, 16);
|
|
3534
3676
|
}
|
|
@@ -4359,12 +4501,6 @@ function mirrorResponsesToCore(view, systemText) {
|
|
|
4359
4501
|
});
|
|
4360
4502
|
return msgs;
|
|
4361
4503
|
}
|
|
4362
|
-
|
|
4363
|
-
// src/messages.ts
|
|
4364
|
-
import { createHash as createHash3 } from "crypto";
|
|
4365
|
-
var REF_TAG_SOURCE = "(?:<acp\\s[^>]*>m\\d+</acp>|\\[m\\d+\\])";
|
|
4366
|
-
var REF_TAG = new RegExp(`^${REF_TAG_SOURCE}\\s?\\n?`);
|
|
4367
|
-
var TRAILING_REF_TAG = new RegExp(`\\n*${REF_TAG_SOURCE}\\s*$`);
|
|
4368
4504
|
function compressToolArgs(call) {
|
|
4369
4505
|
let args = call.arguments;
|
|
4370
4506
|
if (typeof args === "string") {
|
|
@@ -4395,12 +4531,159 @@ function compressToolArgs(call) {
|
|
|
4395
4531
|
const ia = inner;
|
|
4396
4532
|
return Array.isArray(ia.content) ? { content: ia.content, topic: ia.topic, summaryMaxChars: ia.summaryMaxChars } : { content: [ia] };
|
|
4397
4533
|
}
|
|
4534
|
+
function toolCallNames(msgs) {
|
|
4535
|
+
const names = /* @__PURE__ */ new Map();
|
|
4536
|
+
for (const m of msgs) {
|
|
4537
|
+
if (m.contentType === "tool-call" && m.toolCallId && m.toolName) names.set(m.toolCallId, m.toolName);
|
|
4538
|
+
}
|
|
4539
|
+
return names;
|
|
4540
|
+
}
|
|
4541
|
+
function toolResultTextsCore(msgs) {
|
|
4542
|
+
const results = /* @__PURE__ */ new Map();
|
|
4543
|
+
for (const m of msgs) {
|
|
4544
|
+
if (m.contentType !== "tool-result" || !m.toolCallId) continue;
|
|
4545
|
+
results.set(m.toolCallId, m.text ?? "");
|
|
4546
|
+
}
|
|
4547
|
+
return results;
|
|
4548
|
+
}
|
|
4549
|
+
function findCompressCallsCore(msg) {
|
|
4550
|
+
if (msg.contentType !== "tool-call" || !msg.toolName) return [];
|
|
4551
|
+
const args = compressToolArgs({ name: msg.toolName, arguments: msg.text });
|
|
4552
|
+
if (!args) return [];
|
|
4553
|
+
const content = args.content;
|
|
4554
|
+
if (!Array.isArray(content)) return [];
|
|
4555
|
+
const ranges = [];
|
|
4556
|
+
const callTopic = typeof args.topic === "string" ? args.topic : void 0;
|
|
4557
|
+
for (const item of content) {
|
|
4558
|
+
const r = item;
|
|
4559
|
+
if (typeof r.startId !== "string" || typeof r.endId !== "string" || typeof r.summary !== "string" || r.summary.length === 0) continue;
|
|
4560
|
+
ranges.push({
|
|
4561
|
+
startRef: r.startId,
|
|
4562
|
+
endRef: r.endId,
|
|
4563
|
+
summary: r.summary,
|
|
4564
|
+
topic: typeof r.topic === "string" ? r.topic : callTopic,
|
|
4565
|
+
summaryMaxChars: typeof args.summaryMaxChars === "number" ? args.summaryMaxChars : void 0,
|
|
4566
|
+
compressCallId: msg.toolCallId ?? ""
|
|
4567
|
+
});
|
|
4568
|
+
}
|
|
4569
|
+
return ranges.length > 0 ? [{ id: msg.toolCallId ?? "", ranges }] : [];
|
|
4570
|
+
}
|
|
4571
|
+
function corePieceKey(cm) {
|
|
4572
|
+
return `${cm.role}|${cm.contentType}|${cm.toolName ?? ""}|${(cm.text ?? "").slice(0, 4096)}`;
|
|
4573
|
+
}
|
|
4574
|
+
function spanFingerprintCore(coreMessages, startId, endId) {
|
|
4575
|
+
const find = (id) => coreMessages.find((cm) => cm.id === id);
|
|
4576
|
+
const first = find(startId);
|
|
4577
|
+
const last = find(endId);
|
|
4578
|
+
if (!first || !last) return "";
|
|
4579
|
+
return createHash22("sha1").update(`${corePieceKey(first)}\0${corePieceKey(last)}`).digest("hex").slice(0, 8);
|
|
4580
|
+
}
|
|
4581
|
+
function spanFingerprintCoreIdx(coreMessages, startIdx, endIdx) {
|
|
4582
|
+
const first = coreMessages[startIdx];
|
|
4583
|
+
const last = coreMessages[endIdx];
|
|
4584
|
+
if (!first || !last) return "";
|
|
4585
|
+
return createHash22("sha1").update(`${corePieceKey(first)}\0${corePieceKey(last)}`).digest("hex").slice(0, 8);
|
|
4586
|
+
}
|
|
4587
|
+
function boundaryRawCore(ref, byRef, blocks, coreMessages, pick) {
|
|
4588
|
+
const raw = byRef[ref];
|
|
4589
|
+
if (raw) return raw;
|
|
4590
|
+
const m = /^b(\d+)$/i.exec(ref.trim());
|
|
4591
|
+
if (!m) return "";
|
|
4592
|
+
const block = blocks.find((b) => b.blockId.toLowerCase() === `b${m[1]}`);
|
|
4593
|
+
if (!block) return "";
|
|
4594
|
+
const idx = (id) => coreMessages.findIndex((cm) => cm.id === (byRef[id] ?? id));
|
|
4595
|
+
let best = -1;
|
|
4596
|
+
for (const id of block.effectiveMessageIds) {
|
|
4597
|
+
const i = idx(id);
|
|
4598
|
+
if (i < 0) continue;
|
|
4599
|
+
if (best < 0 || (pick === "min" ? i < best : i > best)) best = i;
|
|
4600
|
+
}
|
|
4601
|
+
return best < 0 ? "" : coreMessages[best]?.id ?? "";
|
|
4602
|
+
}
|
|
4603
|
+
function boundaryIndexCore(ref, byRef, blocks, coreMessages, pick, fallbackIdx = -1) {
|
|
4604
|
+
const id = boundaryRawCore(ref, byRef, blocks, coreMessages, pick);
|
|
4605
|
+
if (id) {
|
|
4606
|
+
const i = coreMessages.findIndex((cm) => cm.id === id);
|
|
4607
|
+
if (i >= 0) return i;
|
|
4608
|
+
}
|
|
4609
|
+
return fallbackIdx >= 0 && fallbackIdx < coreMessages.length ? fallbackIdx : -1;
|
|
4610
|
+
}
|
|
4611
|
+
function refOfPieceCore(coreMessages, idx, byRef) {
|
|
4612
|
+
const id = coreMessages[idx]?.id;
|
|
4613
|
+
if (!id) return "";
|
|
4614
|
+
for (const [ref, mapped] of Object.entries(byRef)) if (mapped === id) return ref;
|
|
4615
|
+
return "";
|
|
4616
|
+
}
|
|
4617
|
+
function staleRangeCore(r, rangeIndex, resultText, coreMessages, callIndex, byRef, blocks) {
|
|
4618
|
+
const pm = resultText.match(/\[pos=([0-9,-]+)\]/);
|
|
4619
|
+
const pair = pm ? pm[1].split(",")[rangeIndex] ?? "-" : "-";
|
|
4620
|
+
const hinted = pair !== "-";
|
|
4621
|
+
const [ps, pe] = pair === "-" ? ["", ""] : pair.split("-");
|
|
4622
|
+
const fbStart = ps && ps !== "" ? Number.parseInt(ps, 10) : -1;
|
|
4623
|
+
const fbEnd = pe && pe !== "" ? Number.parseInt(pe, 10) : -1;
|
|
4624
|
+
const startRaw = boundaryRawCore(r.startRef, byRef, blocks, coreMessages, "min");
|
|
4625
|
+
const endRaw = boundaryRawCore(r.endRef, byRef, blocks, coreMessages, "max");
|
|
4626
|
+
const rawStartIdx = startRaw ? coreMessages.findIndex((cm) => cm.id === startRaw) : -1;
|
|
4627
|
+
const rawEndIdx = endRaw ? coreMessages.findIndex((cm) => cm.id === endRaw) : -1;
|
|
4628
|
+
const startIdx = rawStartIdx >= 0 ? rawStartIdx : fbStart >= 0 && fbStart < coreMessages.length ? fbStart : -1;
|
|
4629
|
+
const endIdx = rawEndIdx >= 0 ? rawEndIdx : fbEnd >= 0 && fbEnd < coreMessages.length ? fbEnd : -1;
|
|
4630
|
+
if (startIdx < 0 || endIdx < 0) {
|
|
4631
|
+
if (!/^b\d+$/i.test(r.startRef.trim()) && !/^b\d+$/i.test(r.endRef.trim()))
|
|
4632
|
+
return { reject: `unresolved ${r.startRef}..${r.endRef} -> ${startIdx}..${endIdx}`, ...hinted ? { hint: true } : {} };
|
|
4633
|
+
return {};
|
|
4634
|
+
}
|
|
4635
|
+
if (endIdx > callIndex) return { reject: `end idx ${endIdx} > callIndex ${callIndex}`, ...hinted ? { hint: true } : {} };
|
|
4636
|
+
const m = resultText.match(/\[fp=([0-9a-f,-]+)\]/);
|
|
4637
|
+
if (m) {
|
|
4638
|
+
const want = m[1].split(",")[rangeIndex];
|
|
4639
|
+
if (want !== void 0 && want !== "-") {
|
|
4640
|
+
const got = spanFingerprintCoreIdx(coreMessages, startIdx, endIdx);
|
|
4641
|
+
if (want !== got) return { reject: `fp ${r.startRef}..${r.endRef} want ${want} got ${got} @${startIdx}..${endIdx}`, ...hinted ? { hint: true } : {} };
|
|
4642
|
+
}
|
|
4643
|
+
}
|
|
4644
|
+
const remap = {};
|
|
4645
|
+
if (/^m\d+$/i.test(r.startRef.trim()) && rawStartIdx < 0) {
|
|
4646
|
+
const ref = refOfPieceCore(coreMessages, startIdx, byRef);
|
|
4647
|
+
if (!ref) return { reject: `recovered ${r.startRef} @${startIdx} has no ref (protected piece)`, ...hinted ? { hint: true } : {} };
|
|
4648
|
+
remap.startRef = ref;
|
|
4649
|
+
}
|
|
4650
|
+
if (/^m\d+$/i.test(r.endRef.trim()) && rawEndIdx < 0) {
|
|
4651
|
+
const ref = refOfPieceCore(coreMessages, endIdx, byRef);
|
|
4652
|
+
if (!ref) return { reject: `recovered ${r.endRef} @${endIdx} has no ref (protected piece)`, ...hinted ? { hint: true } : {} };
|
|
4653
|
+
remap.endRef = ref;
|
|
4654
|
+
}
|
|
4655
|
+
if (!remap.startRef && !remap.endRef) return {};
|
|
4656
|
+
return { remap, recovered: { pos: pair, startIdx, endIdx } };
|
|
4657
|
+
}
|
|
4658
|
+
function rangeFingerprintsCore(ranges, coreMessages, byRef, blocks) {
|
|
4659
|
+
return ranges.map((r) => {
|
|
4660
|
+
const start = boundaryRawCore(r.startRef, byRef, blocks, coreMessages, "min");
|
|
4661
|
+
const end = start ? boundaryRawCore(r.endRef, byRef, blocks, coreMessages, "max") : "";
|
|
4662
|
+
if (start && end) {
|
|
4663
|
+
const fp = spanFingerprintCore(coreMessages, start, end);
|
|
4664
|
+
if (fp.length > 0) return fp;
|
|
4665
|
+
}
|
|
4666
|
+
return "-";
|
|
4667
|
+
});
|
|
4668
|
+
}
|
|
4669
|
+
function rangePositionsCore(ranges, coreMessages, byRef, blocks) {
|
|
4670
|
+
return ranges.map((r) => {
|
|
4671
|
+
const s = boundaryIndexCore(r.startRef, byRef, blocks, coreMessages, "min");
|
|
4672
|
+
const e = s >= 0 ? boundaryIndexCore(r.endRef, byRef, blocks, coreMessages, "max") : -1;
|
|
4673
|
+
return s >= 0 && e >= 0 ? `${s}-${e}` : "-";
|
|
4674
|
+
});
|
|
4675
|
+
}
|
|
4676
|
+
|
|
4677
|
+
// src/messages.ts
|
|
4678
|
+
import { createHash as createHash3 } from "crypto";
|
|
4679
|
+
var REF_TAG_SOURCE = "(?:<acp\\s[^>]*>m\\d+</acp>|\\[m\\d+\\])";
|
|
4680
|
+
var REF_TAG = new RegExp(`^${REF_TAG_SOURCE}\\s?\\n?`);
|
|
4681
|
+
var TRAILING_REF_TAG = new RegExp(`\\n*${REF_TAG_SOURCE}\\s*$`);
|
|
4398
4682
|
function stripRefTag(text) {
|
|
4399
4683
|
return text.replace(REF_TAG, "").replace(TRAILING_REF_TAG, "");
|
|
4400
4684
|
}
|
|
4401
4685
|
|
|
4402
4686
|
// src/wire-fold.ts
|
|
4403
|
-
import { createHash as createHash4 } from "crypto";
|
|
4404
4687
|
function detectProviderWireFormat(payload) {
|
|
4405
4688
|
const fmt2 = detectWireFormat(payload);
|
|
4406
4689
|
if (fmt2 === "anthropic" || fmt2 === "openai" || fmt2 === "responses") return fmt2;
|
|
@@ -4565,148 +4848,6 @@ function coreIdentity(msg) {
|
|
|
4565
4848
|
text: stripRefTag(msg.text ?? "")
|
|
4566
4849
|
});
|
|
4567
4850
|
}
|
|
4568
|
-
function toolCallNames(msgs) {
|
|
4569
|
-
const names = /* @__PURE__ */ new Map();
|
|
4570
|
-
for (const m of msgs) {
|
|
4571
|
-
if (m.contentType === "tool-call" && m.toolCallId && m.toolName) names.set(m.toolCallId, m.toolName);
|
|
4572
|
-
}
|
|
4573
|
-
return names;
|
|
4574
|
-
}
|
|
4575
|
-
function toolResultTextsCore(msgs) {
|
|
4576
|
-
const results = /* @__PURE__ */ new Map();
|
|
4577
|
-
for (const m of msgs) {
|
|
4578
|
-
if (m.contentType !== "tool-result" || !m.toolCallId) continue;
|
|
4579
|
-
results.set(m.toolCallId, m.text ?? "");
|
|
4580
|
-
}
|
|
4581
|
-
return results;
|
|
4582
|
-
}
|
|
4583
|
-
function findCompressCallsCore(msg) {
|
|
4584
|
-
if (msg.contentType !== "tool-call" || !msg.toolName) return [];
|
|
4585
|
-
const args = compressToolArgs({ name: msg.toolName, arguments: msg.text });
|
|
4586
|
-
if (!args) return [];
|
|
4587
|
-
const content = args.content;
|
|
4588
|
-
if (!Array.isArray(content)) return [];
|
|
4589
|
-
const ranges = [];
|
|
4590
|
-
const callTopic = typeof args.topic === "string" ? args.topic : void 0;
|
|
4591
|
-
for (const item of content) {
|
|
4592
|
-
const r = item;
|
|
4593
|
-
if (typeof r.startId !== "string" || typeof r.endId !== "string" || typeof r.summary !== "string" || r.summary.length === 0) continue;
|
|
4594
|
-
ranges.push({
|
|
4595
|
-
startRef: r.startId,
|
|
4596
|
-
endRef: r.endId,
|
|
4597
|
-
summary: r.summary,
|
|
4598
|
-
topic: typeof r.topic === "string" ? r.topic : callTopic,
|
|
4599
|
-
summaryMaxChars: typeof args.summaryMaxChars === "number" ? args.summaryMaxChars : void 0,
|
|
4600
|
-
compressCallId: msg.toolCallId ?? ""
|
|
4601
|
-
});
|
|
4602
|
-
}
|
|
4603
|
-
return ranges.length > 0 ? [{ id: msg.toolCallId ?? "", ranges }] : [];
|
|
4604
|
-
}
|
|
4605
|
-
function corePieceKey(cm) {
|
|
4606
|
-
return `${cm.role}|${cm.contentType}|${cm.toolName ?? ""}|${(cm.text ?? "").slice(0, 4096)}`;
|
|
4607
|
-
}
|
|
4608
|
-
function spanFingerprintCore(coreMessages, startId, endId) {
|
|
4609
|
-
const find = (id) => coreMessages.find((cm) => cm.id === id);
|
|
4610
|
-
const first = find(startId);
|
|
4611
|
-
const last = find(endId);
|
|
4612
|
-
if (!first || !last) return "";
|
|
4613
|
-
return createHash4("sha1").update(`${corePieceKey(first)}\0${corePieceKey(last)}`).digest("hex").slice(0, 8);
|
|
4614
|
-
}
|
|
4615
|
-
function spanFingerprintCoreIdx(coreMessages, startIdx, endIdx) {
|
|
4616
|
-
const first = coreMessages[startIdx];
|
|
4617
|
-
const last = coreMessages[endIdx];
|
|
4618
|
-
if (!first || !last) return "";
|
|
4619
|
-
return createHash4("sha1").update(`${corePieceKey(first)}\0${corePieceKey(last)}`).digest("hex").slice(0, 8);
|
|
4620
|
-
}
|
|
4621
|
-
function boundaryRawCore(ref, byRef, blocks, coreMessages, pick) {
|
|
4622
|
-
const raw = byRef[ref];
|
|
4623
|
-
if (raw) return raw;
|
|
4624
|
-
const m = /^b(\d+)$/i.exec(ref.trim());
|
|
4625
|
-
if (!m) return "";
|
|
4626
|
-
const block = blocks.find((b) => b.blockId.toLowerCase() === `b${m[1]}`);
|
|
4627
|
-
if (!block) return "";
|
|
4628
|
-
const idx = (id) => coreMessages.findIndex((cm) => cm.id === (byRef[id] ?? id));
|
|
4629
|
-
let best = -1;
|
|
4630
|
-
for (const id of block.effectiveMessageIds) {
|
|
4631
|
-
const i = idx(id);
|
|
4632
|
-
if (i < 0) continue;
|
|
4633
|
-
if (best < 0 || (pick === "min" ? i < best : i > best)) best = i;
|
|
4634
|
-
}
|
|
4635
|
-
return best < 0 ? "" : coreMessages[best]?.id ?? "";
|
|
4636
|
-
}
|
|
4637
|
-
function boundaryIndexCore(ref, byRef, blocks, coreMessages, pick, fallbackIdx = -1) {
|
|
4638
|
-
const id = boundaryRawCore(ref, byRef, blocks, coreMessages, pick);
|
|
4639
|
-
if (id) {
|
|
4640
|
-
const i = coreMessages.findIndex((cm) => cm.id === id);
|
|
4641
|
-
if (i >= 0) return i;
|
|
4642
|
-
}
|
|
4643
|
-
return fallbackIdx >= 0 && fallbackIdx < coreMessages.length ? fallbackIdx : -1;
|
|
4644
|
-
}
|
|
4645
|
-
function refOfPieceCore(coreMessages, idx, byRef) {
|
|
4646
|
-
const id = coreMessages[idx]?.id;
|
|
4647
|
-
if (!id) return "";
|
|
4648
|
-
for (const [ref, mapped] of Object.entries(byRef)) if (mapped === id) return ref;
|
|
4649
|
-
return "";
|
|
4650
|
-
}
|
|
4651
|
-
function staleRangeCore(r, rangeIndex, resultText, coreMessages, callIndex, byRef, blocks) {
|
|
4652
|
-
const pm = resultText.match(/\[pos=([0-9,-]+)\]/);
|
|
4653
|
-
const pair = pm ? pm[1].split(",")[rangeIndex] ?? "-" : "-";
|
|
4654
|
-
const hinted = pair !== "-";
|
|
4655
|
-
const [ps, pe] = pair === "-" ? ["", ""] : pair.split("-");
|
|
4656
|
-
const fbStart = ps && ps !== "" ? Number.parseInt(ps, 10) : -1;
|
|
4657
|
-
const fbEnd = pe && pe !== "" ? Number.parseInt(pe, 10) : -1;
|
|
4658
|
-
const startRaw = boundaryRawCore(r.startRef, byRef, blocks, coreMessages, "min");
|
|
4659
|
-
const endRaw = boundaryRawCore(r.endRef, byRef, blocks, coreMessages, "max");
|
|
4660
|
-
const rawStartIdx = startRaw ? coreMessages.findIndex((cm) => cm.id === startRaw) : -1;
|
|
4661
|
-
const rawEndIdx = endRaw ? coreMessages.findIndex((cm) => cm.id === endRaw) : -1;
|
|
4662
|
-
const startIdx = rawStartIdx >= 0 ? rawStartIdx : fbStart >= 0 && fbStart < coreMessages.length ? fbStart : -1;
|
|
4663
|
-
const endIdx = rawEndIdx >= 0 ? rawEndIdx : fbEnd >= 0 && fbEnd < coreMessages.length ? fbEnd : -1;
|
|
4664
|
-
if (startIdx < 0 || endIdx < 0) {
|
|
4665
|
-
if (!/^b\d+$/i.test(r.startRef.trim()) && !/^b\d+$/i.test(r.endRef.trim()))
|
|
4666
|
-
return { reject: `unresolved ${r.startRef}..${r.endRef} -> ${startIdx}..${endIdx}`, ...hinted ? { hint: true } : {} };
|
|
4667
|
-
return {};
|
|
4668
|
-
}
|
|
4669
|
-
if (endIdx > callIndex) return { reject: `end idx ${endIdx} > callIndex ${callIndex}`, ...hinted ? { hint: true } : {} };
|
|
4670
|
-
const m = resultText.match(/\[fp=([0-9a-f,-]+)\]/);
|
|
4671
|
-
if (m) {
|
|
4672
|
-
const want = m[1].split(",")[rangeIndex];
|
|
4673
|
-
if (want !== void 0 && want !== "-") {
|
|
4674
|
-
const got = spanFingerprintCoreIdx(coreMessages, startIdx, endIdx);
|
|
4675
|
-
if (want !== got) return { reject: `fp ${r.startRef}..${r.endRef} want ${want} got ${got} @${startIdx}..${endIdx}`, ...hinted ? { hint: true } : {} };
|
|
4676
|
-
}
|
|
4677
|
-
}
|
|
4678
|
-
const remap = {};
|
|
4679
|
-
if (/^m\d+$/i.test(r.startRef.trim()) && rawStartIdx < 0) {
|
|
4680
|
-
const ref = refOfPieceCore(coreMessages, startIdx, byRef);
|
|
4681
|
-
if (!ref) return { reject: `recovered ${r.startRef} @${startIdx} has no ref (protected piece)`, ...hinted ? { hint: true } : {} };
|
|
4682
|
-
remap.startRef = ref;
|
|
4683
|
-
}
|
|
4684
|
-
if (/^m\d+$/i.test(r.endRef.trim()) && rawEndIdx < 0) {
|
|
4685
|
-
const ref = refOfPieceCore(coreMessages, endIdx, byRef);
|
|
4686
|
-
if (!ref) return { reject: `recovered ${r.endRef} @${endIdx} has no ref (protected piece)`, ...hinted ? { hint: true } : {} };
|
|
4687
|
-
remap.endRef = ref;
|
|
4688
|
-
}
|
|
4689
|
-
if (!remap.startRef && !remap.endRef) return {};
|
|
4690
|
-
return { remap, recovered: { pos: pair, startIdx, endIdx } };
|
|
4691
|
-
}
|
|
4692
|
-
function rangeFingerprintsCore(ranges, coreMessages, byRef, blocks) {
|
|
4693
|
-
return ranges.map((r) => {
|
|
4694
|
-
const start = boundaryRawCore(r.startRef, byRef, blocks, coreMessages, "min");
|
|
4695
|
-
const end = start ? boundaryRawCore(r.endRef, byRef, blocks, coreMessages, "max") : "";
|
|
4696
|
-
if (start && end) {
|
|
4697
|
-
const fp = spanFingerprintCore(coreMessages, start, end);
|
|
4698
|
-
if (fp.length > 0) return fp;
|
|
4699
|
-
}
|
|
4700
|
-
return "-";
|
|
4701
|
-
});
|
|
4702
|
-
}
|
|
4703
|
-
function rangePositionsCore(ranges, coreMessages, byRef, blocks) {
|
|
4704
|
-
return ranges.map((r) => {
|
|
4705
|
-
const s = boundaryIndexCore(r.startRef, byRef, blocks, coreMessages, "min");
|
|
4706
|
-
const e = s >= 0 ? boundaryIndexCore(r.endRef, byRef, blocks, coreMessages, "max") : -1;
|
|
4707
|
-
return s >= 0 && e >= 0 ? `${s}-${e}` : "-";
|
|
4708
|
-
});
|
|
4709
|
-
}
|
|
4710
4851
|
function toMirrorView(view) {
|
|
4711
4852
|
const out = [];
|
|
4712
4853
|
for (const message of view) {
|
|
@@ -4769,7 +4910,7 @@ function isViewFlip(foldedLen, lcp) {
|
|
|
4769
4910
|
}
|
|
4770
4911
|
function preserveCompressedSlot(prev) {
|
|
4771
4912
|
const slot = freshSlot(prev);
|
|
4772
|
-
slot.state = { ...slot.state, blocks: prev.state.blocks, messageRefs: prev.state.messageRefs, stats: prev.state.stats };
|
|
4913
|
+
slot.state = { ...slot.state, blocks: prev.state.blocks, messageRefs: prev.state.messageRefs, stats: prev.state.stats, nextBlockId: prev.state.nextBlockId, nextRunId: prev.state.nextRunId };
|
|
4773
4914
|
slot.appliedCallIds = new Set(prev.appliedCallIds);
|
|
4774
4915
|
return slot;
|
|
4775
4916
|
}
|
|
@@ -4832,6 +4973,14 @@ function createRuntime(adapter) {
|
|
|
4832
4973
|
coreSlots.set(sid, slot);
|
|
4833
4974
|
lcp = 0;
|
|
4834
4975
|
}
|
|
4976
|
+
if (lcp === 0 && slot.state.blocks.length > 0) {
|
|
4977
|
+
const presentIds = new Set(stream.map((m) => m.id));
|
|
4978
|
+
const surviving = slot.state.blocks.filter((b) => b.active === false || b.effectiveMessageIds.some((id) => presentIds.has(id)));
|
|
4979
|
+
if (surviving.length < slot.state.blocks.length) {
|
|
4980
|
+
debug.event("fold-purge-stale-blocks", { sid, before: slot.state.blocks.length, after: surviving.length });
|
|
4981
|
+
slot.state = { ...slot.state, blocks: surviving };
|
|
4982
|
+
}
|
|
4983
|
+
}
|
|
4835
4984
|
const coreMessages = stream;
|
|
4836
4985
|
const config = configFor(ctx);
|
|
4837
4986
|
const names = toolCallNames(stream);
|
|
@@ -4967,17 +5116,31 @@ ${acp}`);
|
|
|
4967
5116
|
logInfo("fold", { sid, event: "fold-restore-empty" });
|
|
4968
5117
|
return false;
|
|
4969
5118
|
}
|
|
5119
|
+
const byId = /* @__PURE__ */ new Map();
|
|
5120
|
+
for (const b of r.state.blocks) {
|
|
5121
|
+
const prev = byId.get(b.blockId);
|
|
5122
|
+
if (!prev || b.createdAt > prev.createdAt) byId.set(b.blockId, b);
|
|
5123
|
+
}
|
|
5124
|
+
const blocks = [...byId.values()];
|
|
5125
|
+
if (blocks.length < r.state.blocks.length) {
|
|
5126
|
+
logInfo("fold", { sid, event: "fold-restore-dedup", before: r.state.blocks.length, after: blocks.length });
|
|
5127
|
+
}
|
|
5128
|
+
const maxId = blocks.reduce((m, b) => {
|
|
5129
|
+
const n = /^b(\d+)$/i.exec(b.blockId);
|
|
5130
|
+
return n ? Math.max(m, Number.parseInt(n[1], 10)) : m;
|
|
5131
|
+
}, 0);
|
|
5132
|
+
const state = { ...r.state, blocks, nextBlockId: Math.max(r.state.nextBlockId ?? 1, maxId + 1) };
|
|
4970
5133
|
coreSlots.set(sid, {
|
|
4971
5134
|
identities: r.identities,
|
|
4972
5135
|
foldedLen: r.foldedLen,
|
|
4973
5136
|
preview: false,
|
|
4974
5137
|
live: true,
|
|
4975
|
-
state
|
|
5138
|
+
state,
|
|
4976
5139
|
coreMessages: r.coreMessages,
|
|
4977
5140
|
appliedCallIds: r.appliedCallIds,
|
|
4978
5141
|
rejectStreak: r.rejectStreak
|
|
4979
5142
|
});
|
|
4980
|
-
logInfo("fold", { sid, event: "fold-restore", blocks:
|
|
5143
|
+
logInfo("fold", { sid, event: "fold-restore", blocks: state.blocks.length, foldedLen: r.foldedLen, nextBlockId: state.nextBlockId });
|
|
4981
5144
|
return true;
|
|
4982
5145
|
}
|
|
4983
5146
|
function snapshotOf(slot) {
|
|
@@ -5780,7 +5943,7 @@ async function statusReport(runtime, ctx) {
|
|
|
5780
5943
|
const coveredIds = collectCoveredMessageIds(state);
|
|
5781
5944
|
const sentTokens = estimateTokens(coreMessages, coveredIds) + systemPromptTokens;
|
|
5782
5945
|
const turn = runtime.core.processTurn({ messages: coreMessages, state, config, tokenCount: sentTokens });
|
|
5783
|
-
const versionStr = "0.3.
|
|
5946
|
+
const versionStr = "0.3.3" ? `billion-context-omp@${"0.3.3"}` : void 0;
|
|
5784
5947
|
return buildStatusPanel({
|
|
5785
5948
|
version: versionStr,
|
|
5786
5949
|
tokenCount: sessionTokens,
|
|
@@ -6131,7 +6294,7 @@ async function autoInstallLatest(latest, npmDirOverride) {
|
|
|
6131
6294
|
logWarn("update", { event: "install-abort", reason: "npmroot-not-found", extDir });
|
|
6132
6295
|
return "failed";
|
|
6133
6296
|
}
|
|
6134
|
-
const prevVersion = (await readPackageJson(join4(npmDir, "node_modules", PACKAGE_NAME, "package.json")))?.version ?? "0.3.
|
|
6297
|
+
const prevVersion = (await readPackageJson(join4(npmDir, "node_modules", PACKAGE_NAME, "package.json")))?.version ?? "0.3.3";
|
|
6135
6298
|
try {
|
|
6136
6299
|
const keepAlive = setInterval(() => {
|
|
6137
6300
|
}, 500);
|
|
@@ -6143,7 +6306,7 @@ async function autoInstallLatest(latest, npmDirOverride) {
|
|
|
6143
6306
|
}
|
|
6144
6307
|
const verify = await verifyInstall(npmDir, latest);
|
|
6145
6308
|
if (!verify.ok) {
|
|
6146
|
-
const rollbackTo = SEMVER_RE.test(prevVersion) ? prevVersion : "0.3.
|
|
6309
|
+
const rollbackTo = SEMVER_RE.test(prevVersion) ? prevVersion : "0.3.3";
|
|
6147
6310
|
logWarn("update", { event: "auto-install-verify-failed", latest, reason: verify.reason, rollbackTo });
|
|
6148
6311
|
const rb = await runNpm(installArgs(rollbackTo), npmDir);
|
|
6149
6312
|
logInfo("update", { event: "rollback", from: latest, to: rollbackTo, ok: rb.code === 0 });
|
|
@@ -6183,7 +6346,7 @@ async function checkForUpdate(autoUpdate, notify) {
|
|
|
6183
6346
|
const data = await res.json();
|
|
6184
6347
|
const latest = data.version;
|
|
6185
6348
|
if (!latest) return;
|
|
6186
|
-
const current = runtimeVersion ?? "0.3.
|
|
6349
|
+
const current = runtimeVersion ?? "0.3.3";
|
|
6187
6350
|
const hasUpdate = isNewer(latest, current);
|
|
6188
6351
|
debug.event("update-check", {
|
|
6189
6352
|
current,
|
|
@@ -6397,8 +6560,16 @@ function applyUserConfig(adapter, user) {
|
|
|
6397
6560
|
}
|
|
6398
6561
|
|
|
6399
6562
|
// src/index.ts
|
|
6563
|
+
function disableHostCompaction() {
|
|
6564
|
+
try {
|
|
6565
|
+
settings.override("compaction.enabled", false);
|
|
6566
|
+
settings.override("compaction.strategy", "off");
|
|
6567
|
+
} catch {
|
|
6568
|
+
}
|
|
6569
|
+
}
|
|
6400
6570
|
function createAcpExtension(adapter = {}) {
|
|
6401
6571
|
return (pi) => {
|
|
6572
|
+
disableHostCompaction();
|
|
6402
6573
|
const runtime = createRuntime(adapter);
|
|
6403
6574
|
const warnDelivery = makeDeliveryWarner();
|
|
6404
6575
|
wireSessionLifecycle(pi, runtime);
|
|
@@ -6438,7 +6609,7 @@ function wireSessionLifecycle(pi, runtime) {
|
|
|
6438
6609
|
pi.on("session_start", async (_event, ctx) => {
|
|
6439
6610
|
const sid = ctx.sessionManager.getSessionId();
|
|
6440
6611
|
const modelInfo = ctx.model;
|
|
6441
|
-
logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.3.
|
|
6612
|
+
logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.3.3" : null, model: modelInfo?.id ?? null, modelApi: modelInfo?.api ?? null, contextWindow: modelInfo?.contextWindow ?? null });
|
|
6442
6613
|
if (!hostMeetsMinimum()) {
|
|
6443
6614
|
logWarn("session", { event: "host-too-old", version: VERSION2, min: MIN_HOST_VERSION.join(".") });
|
|
6444
6615
|
try {
|
|
@@ -6449,7 +6620,7 @@ function wireSessionLifecycle(pi, runtime) {
|
|
|
6449
6620
|
}
|
|
6450
6621
|
}
|
|
6451
6622
|
const selfPath = import.meta.url;
|
|
6452
|
-
const conflict = stampAndDetect(selfPath, true ? "0.3.
|
|
6623
|
+
const conflict = stampAndDetect(selfPath, true ? "0.3.3" : null);
|
|
6453
6624
|
if (conflict) {
|
|
6454
6625
|
logWarn("instance", { event: "dual-instance", self: selfPath, other: conflict.path, otherPid: conflict.pid, otherVersion: conflict.version });
|
|
6455
6626
|
try {
|