opencode-acp 1.17.0 → 1.17.1-pr.391.142
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 +8 -0
- package/README.zh-CN.md +8 -0
- package/dist/index.js +123 -31
- package/dist/index.js.map +1 -1
- package/dist/lib/compress/decompress-logic.d.ts.map +1 -1
- package/dist/lib/compress/hide-consumed.d.ts.map +1 -1
- package/dist/lib/compress/search.d.ts.map +1 -1
- package/dist/lib/compress/state.d.ts.map +1 -1
- package/dist/lib/compress/types.d.ts +6 -0
- package/dist/lib/compress/types.d.ts.map +1 -1
- package/dist/lib/config-validation.d.ts.map +1 -1
- package/dist/lib/gc/merge.d.ts.map +1 -1
- package/dist/lib/messages/inject/inject.d.ts.map +1 -1
- package/dist/lib/messages/sync.d.ts.map +1 -1
- package/dist/lib/state/persistence.d.ts.map +1 -1
- package/dist/lib/state/types.d.ts +23 -0
- package/dist/lib/state/types.d.ts.map +1 -1
- package/dist/lib/state/utils.d.ts +7 -0
- package/dist/lib/state/utils.d.ts.map +1 -1
- package/dist/lib/token-utils.d.ts +8 -0
- package/dist/lib/token-utils.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,6 +22,14 @@ The model decides <em>when</em> and <em>what</em> to compress — not a hard lim
|
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
25
|
+
## Community
|
|
26
|
+
|
|
27
|
+
Discussion, help, and updates on QQ — one group covers all three projects (`billion-context`, `billion-context-pi`, `opencode-acp`):
|
|
28
|
+
|
|
29
|
+
**QQ Group: 1056132097**
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
25
33
|
## Why ACP
|
|
26
34
|
|
|
27
35
|
ACP hands all context-management authority to the model itself — not relying on
|
package/README.zh-CN.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -938,7 +938,7 @@ function getConfigKeyPaths(obj, prefix = "") {
|
|
|
938
938
|
for (const key of Object.keys(obj)) {
|
|
939
939
|
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
940
940
|
keys.push(fullKey);
|
|
941
|
-
if (fullKey === "compress.modelMaxLimits" || fullKey === "compress.modelMinLimits" || fullKey === "compress.providers" || fullKey === "messageFilters.filters") {
|
|
941
|
+
if (fullKey === "compress.modelMaxLimits" || fullKey === "compress.modelMinLimits" || fullKey === "compress.providers" || fullKey === "messageFilters.filters" || fullKey === "qualityGate.algorithms") {
|
|
942
942
|
continue;
|
|
943
943
|
}
|
|
944
944
|
if (obj[key] && typeof obj[key] === "object" && !Array.isArray(obj[key])) {
|
|
@@ -2442,6 +2442,9 @@ function countMessageCharacters(msg) {
|
|
|
2442
2442
|
}
|
|
2443
2443
|
return total;
|
|
2444
2444
|
}
|
|
2445
|
+
function estimateAllMessageTokensFast(msg) {
|
|
2446
|
+
return Math.round(countMessageCharacters(msg) / 4);
|
|
2447
|
+
}
|
|
2445
2448
|
|
|
2446
2449
|
// lib/prompts/extensions/tool.ts
|
|
2447
2450
|
var RANGE_FORMAT_EXTENSION = `
|
|
@@ -2491,6 +2494,9 @@ var isMessageCompacted = (state, msg) => {
|
|
|
2491
2494
|
}
|
|
2492
2495
|
return false;
|
|
2493
2496
|
};
|
|
2497
|
+
function bumpPruneStructureVersion(messagesState) {
|
|
2498
|
+
messagesState.structureVersion = (messagesState.structureVersion ?? 0) + 1;
|
|
2499
|
+
}
|
|
2494
2500
|
function serializePruneMessagesState(messagesState) {
|
|
2495
2501
|
return {
|
|
2496
2502
|
byMessageId: Object.fromEntries(messagesState.byMessageId),
|
|
@@ -2808,9 +2814,13 @@ async function writePersistedSessionState(sessionId, state, logger, storageDir)
|
|
|
2808
2814
|
totalTokensSaved: state.stats.totalPruneTokens
|
|
2809
2815
|
});
|
|
2810
2816
|
}
|
|
2811
|
-
|
|
2817
|
+
var saveQueues = /* @__PURE__ */ new Map();
|
|
2818
|
+
function saveQueueKey(sessionId, storageDir) {
|
|
2819
|
+
return `${sessionId}\0${storageDir ?? ""}`;
|
|
2820
|
+
}
|
|
2821
|
+
function saveSessionState(sessionState, logger, sessionName) {
|
|
2812
2822
|
if (!sessionState.sessionId) {
|
|
2813
|
-
return;
|
|
2823
|
+
return Promise.resolve();
|
|
2814
2824
|
}
|
|
2815
2825
|
const state = {
|
|
2816
2826
|
sessionName,
|
|
@@ -2841,7 +2851,53 @@ async function saveSessionState(sessionState, logger, sessionName) {
|
|
|
2841
2851
|
modelProviderID: sessionState.modelProviderID,
|
|
2842
2852
|
modelID: sessionState.modelID
|
|
2843
2853
|
};
|
|
2844
|
-
|
|
2854
|
+
const key = saveQueueKey(sessionState.sessionId, sessionState.storageDir);
|
|
2855
|
+
let queue = saveQueues.get(key);
|
|
2856
|
+
if (!queue) {
|
|
2857
|
+
queue = { pending: [], waiters: [], draining: false };
|
|
2858
|
+
saveQueues.set(key, queue);
|
|
2859
|
+
}
|
|
2860
|
+
const promise = new Promise((resolve2, reject) => {
|
|
2861
|
+
queue.waiters.push({ resolve: resolve2, reject });
|
|
2862
|
+
});
|
|
2863
|
+
queue.pending.push({
|
|
2864
|
+
sessionId: sessionState.sessionId,
|
|
2865
|
+
state,
|
|
2866
|
+
storageDir: sessionState.storageDir,
|
|
2867
|
+
logger
|
|
2868
|
+
});
|
|
2869
|
+
if (!queue.draining) {
|
|
2870
|
+
queue.draining = true;
|
|
2871
|
+
setImmediate(() => drainSaveQueue(key));
|
|
2872
|
+
}
|
|
2873
|
+
return promise;
|
|
2874
|
+
}
|
|
2875
|
+
function drainSaveQueue(key) {
|
|
2876
|
+
const queue = saveQueues.get(key);
|
|
2877
|
+
if (!queue || queue.pending.length === 0) {
|
|
2878
|
+
if (queue) {
|
|
2879
|
+
queue.draining = false;
|
|
2880
|
+
if (queue.waiters.length === 0) saveQueues.delete(key);
|
|
2881
|
+
}
|
|
2882
|
+
return;
|
|
2883
|
+
}
|
|
2884
|
+
const batch = queue.pending.splice(0, queue.pending.length);
|
|
2885
|
+
const waiters = queue.waiters.splice(0, batch.length);
|
|
2886
|
+
const latest = batch[batch.length - 1];
|
|
2887
|
+
writePersistedSessionState(latest.sessionId, latest.state, latest.logger, latest.storageDir).then(() => {
|
|
2888
|
+
for (const waiter of waiters) waiter.resolve();
|
|
2889
|
+
}).catch((err) => {
|
|
2890
|
+
for (const waiter of waiters) waiter.reject(err);
|
|
2891
|
+
}).finally(() => {
|
|
2892
|
+
const q = saveQueues.get(key);
|
|
2893
|
+
if (!q) return;
|
|
2894
|
+
if (q.pending.length > 0) {
|
|
2895
|
+
drainSaveQueue(key);
|
|
2896
|
+
} else {
|
|
2897
|
+
q.draining = false;
|
|
2898
|
+
if (q.waiters.length === 0) saveQueues.delete(key);
|
|
2899
|
+
}
|
|
2900
|
+
});
|
|
2845
2901
|
}
|
|
2846
2902
|
async function loadSessionState(sessionId, logger, storageDir) {
|
|
2847
2903
|
try {
|
|
@@ -3335,6 +3391,7 @@ function applyCompressionState(state, input, selection, anchorMessageId, blockId
|
|
|
3335
3391
|
state.stats.pruneTokenCounter += compressedTokens;
|
|
3336
3392
|
state.stats.totalPruneTokens += state.stats.pruneTokenCounter;
|
|
3337
3393
|
state.stats.pruneTokenCounter = 0;
|
|
3394
|
+
bumpPruneStructureVersion(messagesState);
|
|
3338
3395
|
return {
|
|
3339
3396
|
compressedTokens,
|
|
3340
3397
|
messageIds: selection.messageIds,
|
|
@@ -3448,15 +3505,17 @@ function buildSearchContext(state, rawMessages) {
|
|
|
3448
3505
|
}
|
|
3449
3506
|
summaryByBlockId.set(blockId, block);
|
|
3450
3507
|
}
|
|
3451
|
-
|
|
3508
|
+
const context = {
|
|
3452
3509
|
rawMessages,
|
|
3453
3510
|
rawMessagesById,
|
|
3454
3511
|
rawIndexById,
|
|
3455
3512
|
summaryByBlockId
|
|
3456
3513
|
};
|
|
3514
|
+
context.boundaryLookup = buildBoundaryLookup(context, state);
|
|
3515
|
+
return context;
|
|
3457
3516
|
}
|
|
3458
3517
|
function resolveBoundaryIds(context, state, startId, endId, logger) {
|
|
3459
|
-
const lookup = buildBoundaryLookup(context, state);
|
|
3518
|
+
const lookup = context.boundaryLookup ?? (context.boundaryLookup = buildBoundaryLookup(context, state));
|
|
3460
3519
|
const issues = [];
|
|
3461
3520
|
const parsedStartId = parseBoundaryId(startId);
|
|
3462
3521
|
const parsedEndId = parseBoundaryId(endId);
|
|
@@ -3656,7 +3715,7 @@ function resolveSelection(context, startReference, endReference) {
|
|
|
3656
3715
|
messageIds.push(messageId);
|
|
3657
3716
|
}
|
|
3658
3717
|
if (!messageTokenById.has(messageId)) {
|
|
3659
|
-
messageTokenById.set(messageId,
|
|
3718
|
+
messageTokenById.set(messageId, estimateAllMessageTokensFast(rawMessage));
|
|
3660
3719
|
}
|
|
3661
3720
|
const parts = Array.isArray(rawMessage.parts) ? rawMessage.parts : [];
|
|
3662
3721
|
for (const part of parts) {
|
|
@@ -7863,6 +7922,23 @@ var syncCompressionBlocks = (state, logger, messages) => {
|
|
|
7863
7922
|
return;
|
|
7864
7923
|
}
|
|
7865
7924
|
const messageIds = new Set(messages.map((msg) => msg.info.id));
|
|
7925
|
+
const structureVersion = messagesState.structureVersion ?? 0;
|
|
7926
|
+
if (messagesState.lastSyncedStructureVersion === structureVersion) {
|
|
7927
|
+
const activeBlocks = [...messagesState.activeBlockIds].map((id) => messagesState.blocksById.get(id)).filter((b) => b !== void 0).sort(sortBlocksByCreation);
|
|
7928
|
+
const nextAnchorMap = /* @__PURE__ */ new Map();
|
|
7929
|
+
for (const block of activeBlocks) {
|
|
7930
|
+
if (!messageIds.has(block.anchorMessageId)) continue;
|
|
7931
|
+
nextAnchorMap.set(block.anchorMessageId, block.blockId);
|
|
7932
|
+
}
|
|
7933
|
+
const previous = messagesState.activeByAnchorMessageId;
|
|
7934
|
+
if (previous.size !== nextAnchorMap.size || ![...nextAnchorMap.entries()].every(([anchor, id]) => previous.get(anchor) === id)) {
|
|
7935
|
+
previous.clear();
|
|
7936
|
+
for (const [anchor, id] of nextAnchorMap) {
|
|
7937
|
+
previous.set(anchor, id);
|
|
7938
|
+
}
|
|
7939
|
+
}
|
|
7940
|
+
return;
|
|
7941
|
+
}
|
|
7866
7942
|
const previousActiveBlockIds = new Set(
|
|
7867
7943
|
Array.from(messagesState.blocksById.values()).filter((block) => block.active).map((block) => block.blockId)
|
|
7868
7944
|
);
|
|
@@ -7929,6 +8005,7 @@ var syncCompressionBlocks = (state, logger, messages) => {
|
|
|
7929
8005
|
reactivatedCount
|
|
7930
8006
|
});
|
|
7931
8007
|
}
|
|
8008
|
+
messagesState.lastSyncedStructureVersion = structureVersion;
|
|
7932
8009
|
};
|
|
7933
8010
|
|
|
7934
8011
|
// lib/host-permissions.ts
|
|
@@ -8182,20 +8259,23 @@ var injectCompressNudges = (state, config, logger, messages, prompts, compressio
|
|
|
8182
8259
|
state.nudges.lastPerMessageNudgeTokens = currentTokens;
|
|
8183
8260
|
baselineReEstablished = true;
|
|
8184
8261
|
}
|
|
8185
|
-
const
|
|
8262
|
+
const tierUsageEarly = getTierTokenUsage(state);
|
|
8263
|
+
const tierTriggerPossible = !!suffixMessage && (tierUsageEarly.tier1Tokens >= nudgeGrowthTokens || tierUsageEarly.tier2Tokens >= nudgeGrowthTokens);
|
|
8264
|
+
const needsNudgeAnalysis = nudgeAllowed || emergencyOverride || tierTriggerPossible;
|
|
8265
|
+
const composition = needsNudgeAnalysis ? estimateContextComposition(
|
|
8186
8266
|
messages,
|
|
8187
8267
|
state,
|
|
8188
8268
|
config.compress.protectedTools,
|
|
8189
8269
|
config.protectedFilePatterns
|
|
8190
|
-
);
|
|
8191
|
-
const protectedRefs = computeProtectedRefs(messages, state, config.compress);
|
|
8192
|
-
const contextRanges = buildCompressibleRanges(
|
|
8270
|
+
) : null;
|
|
8271
|
+
const protectedRefs = needsNudgeAnalysis ? computeProtectedRefs(messages, state, config.compress) : /* @__PURE__ */ new Set();
|
|
8272
|
+
const contextRanges = needsNudgeAnalysis ? buildCompressibleRanges(
|
|
8193
8273
|
messages,
|
|
8194
8274
|
state,
|
|
8195
8275
|
config.compress.protectedTools,
|
|
8196
8276
|
config.protectedFilePatterns,
|
|
8197
8277
|
protectedRefs
|
|
8198
|
-
);
|
|
8278
|
+
) : { compressible: [], protected: [] };
|
|
8199
8279
|
const unprotectedCompressible = excludeProtectedRanges(contextRanges.compressible, protectedRefs);
|
|
8200
8280
|
const recommendedRanges = filterRecommendedRanges(
|
|
8201
8281
|
unprotectedCompressible,
|
|
@@ -8220,7 +8300,7 @@ var injectCompressNudges = (state, config, logger, messages, prompts, compressio
|
|
|
8220
8300
|
baselineReEstablished = true;
|
|
8221
8301
|
}
|
|
8222
8302
|
if (suffixMessage && !shouldInject) {
|
|
8223
|
-
const tierUsage =
|
|
8303
|
+
const tierUsage = tierUsageEarly;
|
|
8224
8304
|
const tierChecks = [
|
|
8225
8305
|
{ triggerTier: 2, targetTier: 1, tokens: tierUsage.tier1Tokens, lastNudge: state.nudges.lastTier2NudgeTokens },
|
|
8226
8306
|
{ triggerTier: 3, targetTier: 2, tokens: tierUsage.tier2Tokens, lastNudge: state.nudges.lastTier3NudgeTokens }
|
|
@@ -8347,7 +8427,7 @@ ${rules}`;
|
|
|
8347
8427
|
}
|
|
8348
8428
|
let tipsText = null;
|
|
8349
8429
|
if (shouldInject) {
|
|
8350
|
-
if (suffixMessage && composition.total > 0) {
|
|
8430
|
+
if (suffixMessage && composition !== null && composition.total > 0) {
|
|
8351
8431
|
const fmt = (n) => n >= 1e3 ? `${(n / 1e3).toFixed(1)}K` : String(n);
|
|
8352
8432
|
const pct2 = (n) => n > 0 ? Math.max(1, Math.round(n / composition.total * 100)) : 0;
|
|
8353
8433
|
const growth = currentTokens !== void 0 && (state.nudges.lastNudgeShownTokens ?? state.nudges.lastPerMessageNudgeTokens) !== void 0 ? currentTokens - (state.nudges.lastNudgeShownTokens ?? state.nudges.lastPerMessageNudgeTokens) : 0;
|
|
@@ -8722,6 +8802,9 @@ function deactivateCompressionTarget(messagesState, target, options) {
|
|
|
8722
8802
|
}
|
|
8723
8803
|
}
|
|
8724
8804
|
}
|
|
8805
|
+
if (target.blocks.length > 0) {
|
|
8806
|
+
bumpPruneStructureVersion(messagesState);
|
|
8807
|
+
}
|
|
8725
8808
|
}
|
|
8726
8809
|
function computeRestoredMessages(messagesState, activeMessagesBefore) {
|
|
8727
8810
|
let restoredMessageCount = 0;
|
|
@@ -9103,21 +9186,29 @@ function rewriteCompressInput(part, liveKeys) {
|
|
|
9103
9186
|
};
|
|
9104
9187
|
}
|
|
9105
9188
|
function hideConsumedCompressCalls(state, messages) {
|
|
9106
|
-
const
|
|
9107
|
-
const
|
|
9108
|
-
|
|
9109
|
-
|
|
9110
|
-
|
|
9111
|
-
|
|
9112
|
-
|
|
9113
|
-
|
|
9114
|
-
|
|
9115
|
-
|
|
9116
|
-
|
|
9117
|
-
|
|
9118
|
-
|
|
9119
|
-
|
|
9120
|
-
|
|
9189
|
+
const messagesState = state.prune.messages;
|
|
9190
|
+
const version = messagesState.structureVersion ?? 0;
|
|
9191
|
+
let cached = messagesState.hideConsumedIndex;
|
|
9192
|
+
if (!cached || cached.version !== version) {
|
|
9193
|
+
const allBlockCallIds2 = /* @__PURE__ */ new Set();
|
|
9194
|
+
const liveRangeKeysByCallId2 = /* @__PURE__ */ new Map();
|
|
9195
|
+
const activeCallIds2 = /* @__PURE__ */ new Set();
|
|
9196
|
+
for (const block of messagesState.blocksById.values()) {
|
|
9197
|
+
if (!block.compressCallId) continue;
|
|
9198
|
+
allBlockCallIds2.add(block.compressCallId);
|
|
9199
|
+
if (!isLiveBlock(block)) continue;
|
|
9200
|
+
activeCallIds2.add(block.compressCallId);
|
|
9201
|
+
let keys = liveRangeKeysByCallId2.get(block.compressCallId);
|
|
9202
|
+
if (!keys) {
|
|
9203
|
+
keys = /* @__PURE__ */ new Set();
|
|
9204
|
+
liveRangeKeysByCallId2.set(block.compressCallId, keys);
|
|
9205
|
+
}
|
|
9206
|
+
keys.add(rangeKey(block.startId, block.endId));
|
|
9207
|
+
}
|
|
9208
|
+
cached = { version, allBlockCallIds: allBlockCallIds2, liveRangeKeysByCallId: liveRangeKeysByCallId2, activeCallIds: activeCallIds2 };
|
|
9209
|
+
messagesState.hideConsumedIndex = cached;
|
|
9210
|
+
}
|
|
9211
|
+
const { allBlockCallIds, liveRangeKeysByCallId, activeCallIds } = cached;
|
|
9121
9212
|
const lastOrphanedCallIds = [];
|
|
9122
9213
|
for (let i = messages.length - 1; i >= 0 && lastOrphanedCallIds.length < KEEP_LAST_ORPHANED; i--) {
|
|
9123
9214
|
const parts = Array.isArray(messages[i]?.parts) ? messages[i].parts : [];
|
|
@@ -9691,7 +9782,7 @@ import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
|
9691
9782
|
import { join as join4 } from "path";
|
|
9692
9783
|
import { existsSync as existsSync4 } from "fs";
|
|
9693
9784
|
import { homedir as homedir3 } from "os";
|
|
9694
|
-
var LOG_VERSION = true ? "1.17.
|
|
9785
|
+
var LOG_VERSION = true ? "1.17.1-pr.391.142" : "dev";
|
|
9695
9786
|
var LEVEL_RANK = {
|
|
9696
9787
|
debug: 10,
|
|
9697
9788
|
info: 20,
|
|
@@ -11691,6 +11782,7 @@ function mergeMarkedBlocks(state, markedIds, maxMergedLength) {
|
|
|
11691
11782
|
0
|
|
11692
11783
|
);
|
|
11693
11784
|
const savedTokens = Math.max(0, sourceTokens - newSummaryTokens);
|
|
11785
|
+
bumpPruneStructureVersion(messagesState);
|
|
11694
11786
|
return { mergedCount: sourceBlocks.length, savedTokens };
|
|
11695
11787
|
}
|
|
11696
11788
|
function runBatchCleanup(state, config, logger, messages) {
|
|
@@ -12386,7 +12478,7 @@ var server = (async (ctx) => {
|
|
|
12386
12478
|
}
|
|
12387
12479
|
const logger = new Logger(config.debug, config.debug ? "debug" : config.logLevel);
|
|
12388
12480
|
logger.info("ACP plugin initialized", {
|
|
12389
|
-
version: true ? "1.17.
|
|
12481
|
+
version: true ? "1.17.1-pr.391.142" : "dev",
|
|
12390
12482
|
workspace: ctx.directory,
|
|
12391
12483
|
logLevel: logger.level,
|
|
12392
12484
|
debug: config.debug,
|