opencode-acp 1.18.3-pr.477.211 → 1.18.3-pr.479.213
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 +45 -34
- package/README.zh-CN.md +43 -33
- package/dist/index.js +299 -133
- package/dist/index.js.map +1 -1
- package/dist/lib/compress/image-archive.d.ts +43 -0
- package/dist/lib/compress/image-archive.d.ts.map +1 -0
- package/dist/lib/compress/range.d.ts.map +1 -1
- package/dist/lib/compress/search.d.ts.map +1 -1
- package/dist/lib/config-validation.d.ts.map +1 -1
- package/dist/lib/config.d.ts +36 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/hooks.d.ts.map +1 -1
- package/dist/lib/messages/inject/inject.d.ts.map +1 -1
- package/dist/lib/state/persistence.d.ts +3 -6
- package/dist/lib/state/persistence.d.ts.map +1 -1
- package/dist/lib/state/state.d.ts.map +1 -1
- package/dist/lib/state/types.d.ts +24 -5
- package/dist/lib/state/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/lib/usage-sanity.d.ts +0 -60
- package/dist/lib/usage-sanity.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -916,6 +916,10 @@ var VALID_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
916
916
|
"compress.reasoning",
|
|
917
917
|
"compress.reasoning.drop",
|
|
918
918
|
"compress.reasoning.threshold",
|
|
919
|
+
"compress.images",
|
|
920
|
+
"compress.images.enabled",
|
|
921
|
+
"compress.images.minBytes",
|
|
922
|
+
"compress.images.ttlDays",
|
|
919
923
|
"compress.completionReserveTokens",
|
|
920
924
|
"gc",
|
|
921
925
|
"gc.algorithm",
|
|
@@ -1308,6 +1312,37 @@ function validateConfigTypes(config) {
|
|
|
1308
1312
|
}
|
|
1309
1313
|
}
|
|
1310
1314
|
}
|
|
1315
|
+
if (compress.images !== void 0) {
|
|
1316
|
+
if (typeof compress.images !== "object" || compress.images === null || Array.isArray(compress.images)) {
|
|
1317
|
+
errors.push({
|
|
1318
|
+
key: "compress.images",
|
|
1319
|
+
expected: "object { enabled?: boolean; minBytes?: integer (>= 0); ttlDays?: number (> 0) }",
|
|
1320
|
+
actual: JSON.stringify(compress.images)
|
|
1321
|
+
});
|
|
1322
|
+
} else {
|
|
1323
|
+
if (compress.images.enabled !== void 0 && typeof compress.images.enabled !== "boolean") {
|
|
1324
|
+
errors.push({
|
|
1325
|
+
key: "compress.images.enabled",
|
|
1326
|
+
expected: "boolean",
|
|
1327
|
+
actual: typeof compress.images.enabled
|
|
1328
|
+
});
|
|
1329
|
+
}
|
|
1330
|
+
if (compress.images.minBytes !== void 0 && (typeof compress.images.minBytes !== "number" || !Number.isInteger(compress.images.minBytes) || compress.images.minBytes < 0)) {
|
|
1331
|
+
errors.push({
|
|
1332
|
+
key: "compress.images.minBytes",
|
|
1333
|
+
expected: "integer (>= 0)",
|
|
1334
|
+
actual: JSON.stringify(compress.images.minBytes)
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1337
|
+
if (compress.images.ttlDays !== void 0 && (typeof compress.images.ttlDays !== "number" || !Number.isFinite(compress.images.ttlDays) || compress.images.ttlDays <= 0)) {
|
|
1338
|
+
errors.push({
|
|
1339
|
+
key: "compress.images.ttlDays",
|
|
1340
|
+
expected: "number (> 0)",
|
|
1341
|
+
actual: JSON.stringify(compress.images.ttlDays)
|
|
1342
|
+
});
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1311
1346
|
if (compress.completionReserveTokens !== void 0 && typeof compress.completionReserveTokens !== "number") {
|
|
1312
1347
|
errors.push({
|
|
1313
1348
|
key: "compress.completionReserveTokens",
|
|
@@ -1695,6 +1730,11 @@ var DEFAULT_COMPRESS_REASONING = {
|
|
|
1695
1730
|
drop: true,
|
|
1696
1731
|
threshold: 2048
|
|
1697
1732
|
};
|
|
1733
|
+
var DEFAULT_COMPRESS_IMAGES = {
|
|
1734
|
+
enabled: true,
|
|
1735
|
+
minBytes: 16384,
|
|
1736
|
+
ttlDays: 7
|
|
1737
|
+
};
|
|
1698
1738
|
var DEFAULT_PROTECTED_TOOLS = [
|
|
1699
1739
|
"task",
|
|
1700
1740
|
"skill",
|
|
@@ -1793,7 +1833,8 @@ var defaultConfig = {
|
|
|
1793
1833
|
preserveRecentMessages: 5,
|
|
1794
1834
|
preserveRecentTokens: 5e3,
|
|
1795
1835
|
preserveLastUserMessage: true,
|
|
1796
|
-
reasoning: { ...DEFAULT_COMPRESS_REASONING }
|
|
1836
|
+
reasoning: { ...DEFAULT_COMPRESS_REASONING },
|
|
1837
|
+
images: { ...DEFAULT_COMPRESS_IMAGES }
|
|
1797
1838
|
},
|
|
1798
1839
|
gc: {
|
|
1799
1840
|
algorithm: "truncate",
|
|
@@ -1971,6 +2012,11 @@ function mergeCompress(base, override) {
|
|
|
1971
2012
|
drop: override.reasoning?.drop ?? base.reasoning?.drop ?? DEFAULT_COMPRESS_REASONING.drop,
|
|
1972
2013
|
threshold: override.reasoning?.threshold ?? base.reasoning?.threshold ?? DEFAULT_COMPRESS_REASONING.threshold
|
|
1973
2014
|
},
|
|
2015
|
+
images: {
|
|
2016
|
+
enabled: override.images?.enabled ?? base.images?.enabled ?? DEFAULT_COMPRESS_IMAGES.enabled,
|
|
2017
|
+
minBytes: override.images?.minBytes ?? base.images?.minBytes ?? DEFAULT_COMPRESS_IMAGES.minBytes,
|
|
2018
|
+
ttlDays: override.images?.ttlDays ?? base.images?.ttlDays ?? DEFAULT_COMPRESS_IMAGES.ttlDays
|
|
2019
|
+
},
|
|
1974
2020
|
completionReserveTokens: override.completionReserveTokens ?? base.completionReserveTokens
|
|
1975
2021
|
};
|
|
1976
2022
|
}
|
|
@@ -2909,7 +2955,7 @@ function saveSessionState(sessionState, logger, sessionName) {
|
|
|
2909
2955
|
modelContextLimit: sessionState.modelContextLimit,
|
|
2910
2956
|
modelProviderID: sessionState.modelProviderID,
|
|
2911
2957
|
modelID: sessionState.modelID,
|
|
2912
|
-
|
|
2958
|
+
imageArchive: sessionState.imageArchive
|
|
2913
2959
|
};
|
|
2914
2960
|
const key = saveQueueKey(sessionState.sessionId, sessionState.storageDir);
|
|
2915
2961
|
let queue = saveQueues.get(key);
|
|
@@ -3764,32 +3810,18 @@ function adjustBoundariesForToolPairs(context, startIdx, endIdx) {
|
|
|
3764
3810
|
return { startIndex: newStartIdx, endIndex: newEndIdx };
|
|
3765
3811
|
}
|
|
3766
3812
|
function buildBoundaryRecoveryHint(context, state) {
|
|
3767
|
-
const
|
|
3813
|
+
const visibleRefs = [];
|
|
3768
3814
|
for (const [messageRef, messageId] of state.messageIds.byRef) {
|
|
3769
|
-
if (
|
|
3770
|
-
|
|
3771
|
-
|
|
3815
|
+
if (context.rawMessagesById.has(messageId)) {
|
|
3816
|
+
visibleRefs.push(messageRef);
|
|
3817
|
+
}
|
|
3772
3818
|
}
|
|
3773
|
-
visibleIndexes.sort((a, b) => a - b);
|
|
3774
|
-
const renderSpan = (start, end) => start === end ? formatMessageRef(start) : `${formatMessageRef(start)}\u2013${formatMessageRef(end)}`;
|
|
3775
3819
|
const parts = [];
|
|
3776
|
-
if (
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
const idx = visibleIndexes[i];
|
|
3782
|
-
if (idx !== spanPrev + 1) {
|
|
3783
|
-
spans.push(renderSpan(spanStart, spanPrev));
|
|
3784
|
-
spanStart = idx;
|
|
3785
|
-
}
|
|
3786
|
-
spanPrev = idx;
|
|
3787
|
-
}
|
|
3788
|
-
spans.push(renderSpan(spanStart, spanPrev));
|
|
3789
|
-
const MAX_SPANS = 8;
|
|
3790
|
-
const shown = spans.slice(0, MAX_SPANS);
|
|
3791
|
-
const overflow = spans.length - shown.length;
|
|
3792
|
-
parts.push(`Free ranges: ${shown.join(", ")}${overflow > 0 ? ` (+${overflow} more)` : ""}.`);
|
|
3820
|
+
if (visibleRefs.length > 0) {
|
|
3821
|
+
visibleRefs.sort();
|
|
3822
|
+
const first = visibleRefs[0];
|
|
3823
|
+
const last = visibleRefs[visibleRefs.length - 1];
|
|
3824
|
+
parts.push(`Current visible: ${first}\u2013${last} (${visibleRefs.length} msgs).`);
|
|
3793
3825
|
}
|
|
3794
3826
|
const blockCount = context.summaryByBlockId.size;
|
|
3795
3827
|
if (blockCount > 0) {
|
|
@@ -3798,7 +3830,7 @@ function buildBoundaryRecoveryHint(context, state) {
|
|
|
3798
3830
|
if (parts.length === 0) {
|
|
3799
3831
|
return "";
|
|
3800
3832
|
}
|
|
3801
|
-
return `${parts.join(" ")}
|
|
3833
|
+
return `${parts.join(" ")} Call acp_status() to see which blocks consumed which IDs, then retry with valid IDs.`;
|
|
3802
3834
|
}
|
|
3803
3835
|
function clampMessageRef(requested, context, state) {
|
|
3804
3836
|
if (state.messageIds.byRef.has(requested.ref)) return null;
|
|
@@ -5090,7 +5122,9 @@ function createSessionState() {
|
|
|
5090
5122
|
systemPromptTokens: void 0,
|
|
5091
5123
|
storageDir: void 0,
|
|
5092
5124
|
qualityGateRetryPending: false,
|
|
5093
|
-
noContextLimitWarned: false
|
|
5125
|
+
noContextLimitWarned: false,
|
|
5126
|
+
imageArchive: {},
|
|
5127
|
+
imagePruneDone: false
|
|
5094
5128
|
};
|
|
5095
5129
|
}
|
|
5096
5130
|
function resetSessionState(state) {
|
|
@@ -5134,6 +5168,8 @@ function resetSessionState(state) {
|
|
|
5134
5168
|
state.storageDir = void 0;
|
|
5135
5169
|
state.qualityGateRetryPending = false;
|
|
5136
5170
|
state.noContextLimitWarned = false;
|
|
5171
|
+
state.imageArchive = {};
|
|
5172
|
+
state.imagePruneDone = false;
|
|
5137
5173
|
}
|
|
5138
5174
|
async function ensureSessionInitialized(client, state, sessionId, logger, messages, config, projectDir) {
|
|
5139
5175
|
if (state.sessionId === sessionId) {
|
|
@@ -5212,8 +5248,21 @@ async function ensureSessionInitialized(client, state, sessionId, logger, messag
|
|
|
5212
5248
|
state.nudges.compressBaselineSet = persisted.nudges.compressBaselineSet ?? false;
|
|
5213
5249
|
state.stats = {
|
|
5214
5250
|
pruneTokenCounter: persisted.stats?.pruneTokenCounter || 0,
|
|
5215
|
-
totalPruneTokens: persisted.stats?.totalPruneTokens || 0
|
|
5251
|
+
totalPruneTokens: persisted.stats?.totalPruneTokens || 0,
|
|
5252
|
+
imagesArchived: persisted.stats?.imagesArchived,
|
|
5253
|
+
imageBytesArchived: persisted.stats?.imageBytesArchived
|
|
5216
5254
|
};
|
|
5255
|
+
if (persisted.imageArchive && typeof persisted.imageArchive === "object") {
|
|
5256
|
+
for (const [rawId, entries] of Object.entries(persisted.imageArchive)) {
|
|
5257
|
+
if (!Array.isArray(entries)) continue;
|
|
5258
|
+
const valid = entries.filter(
|
|
5259
|
+
(e) => !!e && typeof e.path === "string" && typeof e.mediaType === "string" && typeof e.bytes === "number"
|
|
5260
|
+
);
|
|
5261
|
+
if (valid.length > 0) {
|
|
5262
|
+
state.imageArchive[rawId] = valid;
|
|
5263
|
+
}
|
|
5264
|
+
}
|
|
5265
|
+
}
|
|
5217
5266
|
const persistedAny = persisted;
|
|
5218
5267
|
if (persistedAny._persistedMessageIds) {
|
|
5219
5268
|
state.messageIds = {
|
|
@@ -5247,14 +5296,6 @@ async function ensureSessionInitialized(client, state, sessionId, logger, messag
|
|
|
5247
5296
|
state.modelProviderID = persisted.modelProviderID;
|
|
5248
5297
|
state.modelID = persisted.modelID;
|
|
5249
5298
|
}
|
|
5250
|
-
if (persisted.usageSanity) {
|
|
5251
|
-
const { reported, estimated } = persisted.usageSanity;
|
|
5252
|
-
if (Number.isFinite(reported) && Number.isFinite(estimated) && reported >= 0 && estimated >= 0) {
|
|
5253
|
-
state.usageSanity = { reported, estimated };
|
|
5254
|
-
} else {
|
|
5255
|
-
state.usageSanity = void 0;
|
|
5256
|
-
}
|
|
5257
|
-
}
|
|
5258
5299
|
const applied = applyPendingCompressionDurations(state);
|
|
5259
5300
|
if (applied > 0) {
|
|
5260
5301
|
await saveSessionState(state, logger);
|
|
@@ -6634,6 +6675,156 @@ function buildPhantomSkipNotice(identification) {
|
|
|
6634
6675
|
return `Skipped ${identification.phantomIndices.length} already-compressed ${noun} (${skippedNums}) \u2014 they are no-ops; the remaining entries were compressed.`;
|
|
6635
6676
|
}
|
|
6636
6677
|
|
|
6678
|
+
// lib/compress/image-archive.ts
|
|
6679
|
+
import { createHash as createHash2 } from "crypto";
|
|
6680
|
+
import {
|
|
6681
|
+
existsSync as existsSync4,
|
|
6682
|
+
mkdirSync as mkdirSync2,
|
|
6683
|
+
readdirSync,
|
|
6684
|
+
rmdirSync,
|
|
6685
|
+
statSync as statSync2,
|
|
6686
|
+
unlinkSync,
|
|
6687
|
+
writeFileSync as writeFileSync2
|
|
6688
|
+
} from "fs";
|
|
6689
|
+
import { join as join4 } from "path";
|
|
6690
|
+
var DATA_URL_REGEX = /^data:(image\/[a-z0-9.+-]+);base64,(.+)$/is;
|
|
6691
|
+
var IMAGE_EXTENSIONS = {
|
|
6692
|
+
"image/png": "png",
|
|
6693
|
+
"image/jpeg": "jpg",
|
|
6694
|
+
"image/jpg": "jpg",
|
|
6695
|
+
"image/gif": "gif",
|
|
6696
|
+
"image/webp": "webp",
|
|
6697
|
+
"image/avif": "avif",
|
|
6698
|
+
"image/bmp": "bmp"
|
|
6699
|
+
};
|
|
6700
|
+
function sha8(input) {
|
|
6701
|
+
return createHash2("sha256").update(input).digest("hex").slice(0, 8);
|
|
6702
|
+
}
|
|
6703
|
+
function parseImageDataUrl(url) {
|
|
6704
|
+
if (typeof url !== "string") return void 0;
|
|
6705
|
+
const match = DATA_URL_REGEX.exec(url);
|
|
6706
|
+
if (!match) return void 0;
|
|
6707
|
+
return { mediaType: match[1].toLowerCase(), base64: match[2] };
|
|
6708
|
+
}
|
|
6709
|
+
function extForMediaType(mediaType) {
|
|
6710
|
+
return IMAGE_EXTENSIONS[mediaType.toLowerCase()];
|
|
6711
|
+
}
|
|
6712
|
+
function archiveDirName(sessionId) {
|
|
6713
|
+
let name = sessionId.replace(/[^a-zA-Z0-9_-]/g, "-").slice(0, 100);
|
|
6714
|
+
if (name !== sessionId) {
|
|
6715
|
+
name = `${name}-${sha8(sessionId)}`;
|
|
6716
|
+
}
|
|
6717
|
+
return name || "-";
|
|
6718
|
+
}
|
|
6719
|
+
function archiveRoot(storageDir, sessionId) {
|
|
6720
|
+
return join4(storageDir ?? getDefaultStorageDir(), "images", archiveDirName(sessionId));
|
|
6721
|
+
}
|
|
6722
|
+
function archiveSessionImages(state, messages, images, logger) {
|
|
6723
|
+
if (!images.enabled || !state.sessionId) return 0;
|
|
6724
|
+
const root = archiveRoot(state.storageDir, state.sessionId);
|
|
6725
|
+
let archived = 0;
|
|
6726
|
+
for (const message of messages) {
|
|
6727
|
+
const rawId = message.info.id;
|
|
6728
|
+
if (!rawId) continue;
|
|
6729
|
+
const parts = Array.isArray(message.parts) ? message.parts : [];
|
|
6730
|
+
for (let partIndex = 0; partIndex < parts.length; partIndex++) {
|
|
6731
|
+
const part = parts[partIndex];
|
|
6732
|
+
if (part.type !== "file") continue;
|
|
6733
|
+
const parsed = parseImageDataUrl(part.url);
|
|
6734
|
+
if (!parsed) continue;
|
|
6735
|
+
const ext = extForMediaType(parsed.mediaType);
|
|
6736
|
+
if (!ext) continue;
|
|
6737
|
+
const fileName = `${sha8(rawId)}-p${partIndex}-${sha8(parsed.base64)}.${ext}`;
|
|
6738
|
+
const filePath = join4(root, fileName);
|
|
6739
|
+
const existing = state.imageArchive[rawId]?.find((e) => e.path === filePath);
|
|
6740
|
+
if (existing) continue;
|
|
6741
|
+
let bytes;
|
|
6742
|
+
try {
|
|
6743
|
+
if (existsSync4(filePath)) {
|
|
6744
|
+
bytes = statSync2(filePath).size;
|
|
6745
|
+
} else {
|
|
6746
|
+
const buffer = Buffer.from(parsed.base64, "base64");
|
|
6747
|
+
bytes = buffer.byteLength;
|
|
6748
|
+
if (bytes < images.minBytes) continue;
|
|
6749
|
+
mkdirSync2(root, { recursive: true });
|
|
6750
|
+
writeFileSync2(filePath, buffer, { mode: 384 });
|
|
6751
|
+
}
|
|
6752
|
+
} catch (error) {
|
|
6753
|
+
logger.warn(
|
|
6754
|
+
`[#478] failed to archive image ${filePath}: ${error instanceof Error ? error.message : String(error)}`
|
|
6755
|
+
);
|
|
6756
|
+
continue;
|
|
6757
|
+
}
|
|
6758
|
+
const entry = {
|
|
6759
|
+
path: filePath,
|
|
6760
|
+
mediaType: parsed.mediaType,
|
|
6761
|
+
bytes
|
|
6762
|
+
};
|
|
6763
|
+
if (!state.imageArchive[rawId]) {
|
|
6764
|
+
state.imageArchive[rawId] = [];
|
|
6765
|
+
}
|
|
6766
|
+
state.imageArchive[rawId].push(entry);
|
|
6767
|
+
state.stats.imagesArchived = (state.stats.imagesArchived ?? 0) + 1;
|
|
6768
|
+
state.stats.imageBytesArchived = (state.stats.imageBytesArchived ?? 0) + bytes;
|
|
6769
|
+
archived++;
|
|
6770
|
+
}
|
|
6771
|
+
}
|
|
6772
|
+
return archived;
|
|
6773
|
+
}
|
|
6774
|
+
function pruneImageArchive(state, images, logger) {
|
|
6775
|
+
if (state.imagePruneDone || !state.sessionId) return;
|
|
6776
|
+
state.imagePruneDone = true;
|
|
6777
|
+
try {
|
|
6778
|
+
const root = archiveRoot(state.storageDir, state.sessionId);
|
|
6779
|
+
if (!existsSync4(root)) return;
|
|
6780
|
+
const cutoff = Date.now() - images.ttlDays * 864e5;
|
|
6781
|
+
const prunedPaths = /* @__PURE__ */ new Set();
|
|
6782
|
+
for (const name of readdirSync(root)) {
|
|
6783
|
+
const filePath = join4(root, name);
|
|
6784
|
+
try {
|
|
6785
|
+
if (statSync2(filePath).mtimeMs < cutoff) {
|
|
6786
|
+
unlinkSync(filePath);
|
|
6787
|
+
prunedPaths.add(filePath);
|
|
6788
|
+
}
|
|
6789
|
+
} catch {
|
|
6790
|
+
}
|
|
6791
|
+
}
|
|
6792
|
+
if (prunedPaths.size > 0) {
|
|
6793
|
+
for (const [rawId, entries] of Object.entries(state.imageArchive)) {
|
|
6794
|
+
const kept = entries.filter((e) => !prunedPaths.has(e.path));
|
|
6795
|
+
if (kept.length === 0) {
|
|
6796
|
+
delete state.imageArchive[rawId];
|
|
6797
|
+
} else if (kept.length !== entries.length) {
|
|
6798
|
+
state.imageArchive[rawId] = kept;
|
|
6799
|
+
}
|
|
6800
|
+
}
|
|
6801
|
+
logger.info(`[#478] TTL sweep removed ${prunedPaths.size} expired archived image(s)`);
|
|
6802
|
+
}
|
|
6803
|
+
if (readdirSync(root).length === 0) {
|
|
6804
|
+
rmdirSync(root);
|
|
6805
|
+
}
|
|
6806
|
+
} catch (error) {
|
|
6807
|
+
logger.warn(
|
|
6808
|
+
`[#478] image TTL sweep failed: ${error instanceof Error ? error.message : String(error)}`
|
|
6809
|
+
);
|
|
6810
|
+
}
|
|
6811
|
+
}
|
|
6812
|
+
function appendArchivedImagePointers(summary, selection, state, enabled) {
|
|
6813
|
+
if (!enabled) return summary;
|
|
6814
|
+
const lines = [];
|
|
6815
|
+
for (const messageId of selection.messageIds) {
|
|
6816
|
+
const entries = state.imageArchive[messageId];
|
|
6817
|
+
if (!entries || entries.length === 0) continue;
|
|
6818
|
+
const ref = state.messageIds.byRawId.get(messageId) ?? messageId;
|
|
6819
|
+
for (const entry of entries) {
|
|
6820
|
+
lines.push(`- ${ref}: ${entry.path} (${entry.mediaType}, ${entry.bytes} bytes)`);
|
|
6821
|
+
}
|
|
6822
|
+
}
|
|
6823
|
+
if (lines.length === 0) return summary;
|
|
6824
|
+
const heading = "\n\nImages captured in this range were archived to disk (their pixels are NOT summarized). Re-read them with your file tools if you need the pixels again:";
|
|
6825
|
+
return summary + heading + "\n" + lines.join("\n");
|
|
6826
|
+
}
|
|
6827
|
+
|
|
6637
6828
|
// lib/compress/keep-markers.ts
|
|
6638
6829
|
var KEEP_REGEX = /\[\[KEEP:(m\d+)\]\]/g;
|
|
6639
6830
|
var REF_REGEX = /\[\[REF:(m\d+)\|([^\]]+)\]\]/g;
|
|
@@ -6807,56 +6998,13 @@ ${guidance}
|
|
|
6807
6998
|
${afterClose}`;
|
|
6808
6999
|
}
|
|
6809
7000
|
|
|
6810
|
-
// lib/usage-sanity.ts
|
|
6811
|
-
var RELAY_INFLATION_RATIO = 1.5;
|
|
6812
|
-
var PAYLOAD_FLOOR_TOKENS = 5e3;
|
|
6813
|
-
function estimatePayloadTokens(messages) {
|
|
6814
|
-
let total = 0;
|
|
6815
|
-
for (const msg of messages) {
|
|
6816
|
-
if (isSyntheticMessage(msg)) continue;
|
|
6817
|
-
if (isIgnoredUserMessage(msg)) continue;
|
|
6818
|
-
total += estimateAllMessageTokensFast(msg);
|
|
6819
|
-
}
|
|
6820
|
-
return total;
|
|
6821
|
-
}
|
|
6822
|
-
function resolveCurrentUsage(state, messages, logger) {
|
|
6823
|
-
const reported = getCurrentTokenUsage(state, messages);
|
|
6824
|
-
if (reported === 0) {
|
|
6825
|
-
return { tokens: 0, source: "reported", inflationDetected: false };
|
|
6826
|
-
}
|
|
6827
|
-
const estimated = estimatePayloadTokens(messages) + (state.systemPromptTokens ?? 0);
|
|
6828
|
-
const prev = state.usageSanity;
|
|
6829
|
-
let inflationDetected = false;
|
|
6830
|
-
if (prev !== void 0 && prev.reported > 0 && prev.estimated >= PAYLOAD_FLOOR_TOKENS && estimated >= PAYLOAD_FLOOR_TOKENS) {
|
|
6831
|
-
const reportRatio = reported / prev.reported;
|
|
6832
|
-
const payloadRatio = estimated / prev.estimated;
|
|
6833
|
-
if (reportRatio > RELAY_INFLATION_RATIO && payloadRatio <= RELAY_INFLATION_RATIO) {
|
|
6834
|
-
inflationDetected = true;
|
|
6835
|
-
}
|
|
6836
|
-
}
|
|
6837
|
-
state.usageSanity = { reported, estimated };
|
|
6838
|
-
if (inflationDetected) {
|
|
6839
|
-
logger?.warn("Relay usage inflation detected \u2014 re-estimating context size", {
|
|
6840
|
-
session: state.sessionId,
|
|
6841
|
-
reported,
|
|
6842
|
-
previousReported: prev.reported,
|
|
6843
|
-
reportRatio: +(reported / prev.reported).toFixed(3),
|
|
6844
|
-
estimated,
|
|
6845
|
-
previousEstimated: prev.estimated,
|
|
6846
|
-
payloadRatio: +(estimated / prev.estimated).toFixed(3)
|
|
6847
|
-
});
|
|
6848
|
-
return { tokens: estimated, source: "reestimated", inflationDetected: true };
|
|
6849
|
-
}
|
|
6850
|
-
return { tokens: reported, source: "reported", inflationDetected: false };
|
|
6851
|
-
}
|
|
6852
|
-
|
|
6853
7001
|
// lib/messages/utils.ts
|
|
6854
|
-
import { createHash as
|
|
7002
|
+
import { createHash as createHash3 } from "crypto";
|
|
6855
7003
|
var SUMMARY_ID_HASH_LENGTH = 16;
|
|
6856
7004
|
var DCP_PAIRED_TAG_REGEX = /<(?:dcp|acp)[^>]*>[\s\S]*?<\/(?:dcp|acp)[^>]*>/gi;
|
|
6857
7005
|
var DCP_UNPAIRED_TAG_REGEX = /<\/?(?:dcp|acp)[^>]*>/gi;
|
|
6858
7006
|
var generateStableId = (prefix, seed) => {
|
|
6859
|
-
const hash =
|
|
7007
|
+
const hash = createHash3("sha256").update(seed).digest("hex").slice(0, SUMMARY_ID_HASH_LENGTH);
|
|
6860
7008
|
return `${prefix}_${hash}`;
|
|
6861
7009
|
};
|
|
6862
7010
|
var createSyntheticMessage = (baseMessage, content, stableSeed, role = "user") => {
|
|
@@ -7200,7 +7348,7 @@ function isContextOverLimits(config, state, providerId, modelId, messages) {
|
|
|
7200
7348
|
);
|
|
7201
7349
|
const maxContextLimit = resolvedMaxContextLimit === void 0 ? void 0 : resolvedMaxContextLimit + summaryTokenExtension;
|
|
7202
7350
|
const minContextLimit = resolveContextTokenLimit(config, state, providerId, modelId, "min");
|
|
7203
|
-
const currentTokens =
|
|
7351
|
+
const currentTokens = getCurrentTokenUsage(state, messages);
|
|
7204
7352
|
let overMaxLimit = maxContextLimit === void 0 ? false : currentTokens > maxContextLimit;
|
|
7205
7353
|
const overMinLimit = minContextLimit === void 0 ? false : currentTokens >= minContextLimit;
|
|
7206
7354
|
if (overMaxLimit) {
|
|
@@ -8123,7 +8271,12 @@ function createCompressRangeTool(factoryCtx) {
|
|
|
8123
8271
|
entry: plan.entry,
|
|
8124
8272
|
selection: plan.selection,
|
|
8125
8273
|
anchorMessageId: plan.anchorMessageId,
|
|
8126
|
-
finalSummary:
|
|
8274
|
+
finalSummary: appendArchivedImagePointers(
|
|
8275
|
+
completedSummary.expandedSummary,
|
|
8276
|
+
plan.selection,
|
|
8277
|
+
ctx.state,
|
|
8278
|
+
ctx.config.compress.images?.enabled !== false
|
|
8279
|
+
),
|
|
8127
8280
|
consumedBlockIds: mergeConsumedBlockIds
|
|
8128
8281
|
});
|
|
8129
8282
|
}
|
|
@@ -9352,8 +9505,7 @@ var injectCompressNudges = (state, config, logger, messages, prompts, compressio
|
|
|
9352
9505
|
const allInProtectedZone = protectedRefs.size > 0 && unprotectedCompressible.length === 0;
|
|
9353
9506
|
const allBelowMin = contextRanges.compressible.length > 0 && recommendedRanges.length === 0;
|
|
9354
9507
|
const noExecutableCandidates = candidatesEnabled && nudgeAllowed && candidateMessages !== void 0 && candidatePlan.candidates.length === 0;
|
|
9355
|
-
const
|
|
9356
|
-
const nothingToCompress = (candidatesEnabled && candidateMessages !== void 0 ? noExecutableCandidates : allProtected || allInProtectedZone || allBelowMin) || noRangesAtAll;
|
|
9508
|
+
const nothingToCompress = candidatesEnabled && candidateMessages !== void 0 ? noExecutableCandidates : allProtected || allInProtectedZone || allBelowMin;
|
|
9357
9509
|
const emergencyNoTargets = emergencyOverride && nothingToCompress;
|
|
9358
9510
|
const noticeCadenceMet = state.nudges.lastNudgeShownTokens === void 0 || growthSinceBaseline !== void 0 && growthSinceBaseline >= growthFloor;
|
|
9359
9511
|
let shouldInjectNudge = nudgeAllowed && !nothingToCompress;
|
|
@@ -9558,7 +9710,7 @@ ${rules}`;
|
|
|
9558
9710
|
} else if (nudgeAllowed && nothingToCompress) {
|
|
9559
9711
|
logger.info("Nudge suppressed: nothing to compress", {
|
|
9560
9712
|
session: state.sessionId,
|
|
9561
|
-
reason: allProtected ? "all_protected" : allInProtectedZone ? "in_protected_zone" : allBelowMin ? "below_effective_floor" :
|
|
9713
|
+
reason: allProtected ? "all_protected" : allInProtectedZone ? "in_protected_zone" : allBelowMin ? "below_effective_floor" : "no_executable_candidates",
|
|
9562
9714
|
currentTokens,
|
|
9563
9715
|
usagePct,
|
|
9564
9716
|
compressibleRanges: contextRanges.compressible.length
|
|
@@ -11173,10 +11325,10 @@ function hideFailedCompressCalls(messages) {
|
|
|
11173
11325
|
|
|
11174
11326
|
// lib/logger.ts
|
|
11175
11327
|
import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
11176
|
-
import { join as
|
|
11177
|
-
import { existsSync as
|
|
11328
|
+
import { join as join5 } from "path";
|
|
11329
|
+
import { existsSync as existsSync5 } from "fs";
|
|
11178
11330
|
import { homedir as homedir3 } from "os";
|
|
11179
|
-
var LOG_VERSION = true ? "1.18.3-pr.
|
|
11331
|
+
var LOG_VERSION = true ? "1.18.3-pr.479.213" : "dev";
|
|
11180
11332
|
var LEVEL_RANK = {
|
|
11181
11333
|
debug: 10,
|
|
11182
11334
|
info: 20,
|
|
@@ -11196,8 +11348,8 @@ var Logger = class {
|
|
|
11196
11348
|
constructor(enabled, level) {
|
|
11197
11349
|
const resolved = level !== void 0 && LEVEL_RANK[level] !== void 0 ? level : void 0;
|
|
11198
11350
|
this.level = resolved ?? (enabled ? "debug" : "warn");
|
|
11199
|
-
const configHome = process.env.XDG_CONFIG_HOME ||
|
|
11200
|
-
this.logDir =
|
|
11351
|
+
const configHome = process.env.XDG_CONFIG_HOME || join5(homedir3(), ".config");
|
|
11352
|
+
this.logDir = join5(configHome, "opencode", "logs", "acp");
|
|
11201
11353
|
}
|
|
11202
11354
|
/** Back-compat view of the old flag: true only at full debug verbosity. */
|
|
11203
11355
|
get enabled() {
|
|
@@ -11207,7 +11359,7 @@ var Logger = class {
|
|
|
11207
11359
|
return LEVEL_RANK[level] >= LEVEL_RANK[this.level];
|
|
11208
11360
|
}
|
|
11209
11361
|
async ensureLogDir() {
|
|
11210
|
-
if (!
|
|
11362
|
+
if (!existsSync5(this.logDir)) {
|
|
11211
11363
|
await mkdir2(this.logDir, { recursive: true });
|
|
11212
11364
|
}
|
|
11213
11365
|
}
|
|
@@ -11259,11 +11411,11 @@ var Logger = class {
|
|
|
11259
11411
|
const dataStr = this.formatData(data);
|
|
11260
11412
|
const logLine = `${timestamp} ${level.padEnd(5)} ${component}: ${message}${dataStr ? " | " + dataStr : ""} | v=${LOG_VERSION}
|
|
11261
11413
|
`;
|
|
11262
|
-
const dailyLogDir =
|
|
11263
|
-
if (!
|
|
11414
|
+
const dailyLogDir = join5(this.logDir, "daily");
|
|
11415
|
+
if (!existsSync5(dailyLogDir)) {
|
|
11264
11416
|
await mkdir2(dailyLogDir, { recursive: true });
|
|
11265
11417
|
}
|
|
11266
|
-
const logFile =
|
|
11418
|
+
const logFile = join5(dailyLogDir, `${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.log`);
|
|
11267
11419
|
await writeFile2(logFile, logLine, { flag: "a" });
|
|
11268
11420
|
} catch (error) {
|
|
11269
11421
|
}
|
|
@@ -11374,18 +11526,18 @@ var Logger = class {
|
|
|
11374
11526
|
async saveContext(sessionId, messages) {
|
|
11375
11527
|
if (this.level !== "debug") return;
|
|
11376
11528
|
try {
|
|
11377
|
-
const contextDir =
|
|
11378
|
-
if (!
|
|
11529
|
+
const contextDir = join5(this.logDir, "context", sessionId);
|
|
11530
|
+
if (!existsSync5(contextDir)) {
|
|
11379
11531
|
await mkdir2(contextDir, { recursive: true });
|
|
11380
11532
|
}
|
|
11381
11533
|
const minimized = this.minimizeForDebug(messages).filter(
|
|
11382
11534
|
(msg) => msg.parts && msg.parts.length > 0
|
|
11383
11535
|
);
|
|
11384
11536
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
11385
|
-
const contextFile =
|
|
11537
|
+
const contextFile = join5(contextDir, `${timestamp}.json`);
|
|
11386
11538
|
await writeFile2(contextFile, JSON.stringify(minimized, null, 2));
|
|
11387
|
-
const versionFile =
|
|
11388
|
-
if (!
|
|
11539
|
+
const versionFile = join5(contextDir, "_version");
|
|
11540
|
+
if (!existsSync5(versionFile)) {
|
|
11389
11541
|
await writeFile2(versionFile, LOG_VERSION);
|
|
11390
11542
|
}
|
|
11391
11543
|
} catch (error) {
|
|
@@ -11394,8 +11546,8 @@ var Logger = class {
|
|
|
11394
11546
|
};
|
|
11395
11547
|
|
|
11396
11548
|
// lib/prompts/store.ts
|
|
11397
|
-
import { existsSync as
|
|
11398
|
-
import { join as
|
|
11549
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync3, statSync as statSync3 } from "fs";
|
|
11550
|
+
import { join as join6, dirname as dirname2 } from "path";
|
|
11399
11551
|
import { homedir as homedir4 } from "os";
|
|
11400
11552
|
|
|
11401
11553
|
// lib/prompts/system.ts
|
|
@@ -11703,10 +11855,10 @@ function createBundledRuntimePrompts(candidatesEnabled) {
|
|
|
11703
11855
|
function findOpencodeDir2(startDir) {
|
|
11704
11856
|
let current = startDir;
|
|
11705
11857
|
while (current !== "/") {
|
|
11706
|
-
const candidate =
|
|
11707
|
-
if (
|
|
11858
|
+
const candidate = join6(current, ".opencode");
|
|
11859
|
+
if (existsSync6(candidate)) {
|
|
11708
11860
|
try {
|
|
11709
|
-
if (
|
|
11861
|
+
if (statSync3(candidate).isDirectory()) {
|
|
11710
11862
|
return candidate;
|
|
11711
11863
|
}
|
|
11712
11864
|
} catch {
|
|
@@ -11721,13 +11873,13 @@ function findOpencodeDir2(startDir) {
|
|
|
11721
11873
|
return null;
|
|
11722
11874
|
}
|
|
11723
11875
|
function resolvePromptPaths(workingDirectory) {
|
|
11724
|
-
const configHome = process.env.XDG_CONFIG_HOME ||
|
|
11725
|
-
const globalRoot =
|
|
11726
|
-
const defaultsDir =
|
|
11727
|
-
const globalOverridesDir =
|
|
11728
|
-
const configDirOverridesDir = process.env.OPENCODE_CONFIG_DIR ?
|
|
11876
|
+
const configHome = process.env.XDG_CONFIG_HOME || join6(homedir4(), ".config");
|
|
11877
|
+
const globalRoot = join6(configHome, "opencode", "acp-prompts");
|
|
11878
|
+
const defaultsDir = join6(globalRoot, "defaults");
|
|
11879
|
+
const globalOverridesDir = join6(globalRoot, "overrides");
|
|
11880
|
+
const configDirOverridesDir = process.env.OPENCODE_CONFIG_DIR ? join6(process.env.OPENCODE_CONFIG_DIR, "acp-prompts", "overrides") : null;
|
|
11729
11881
|
const opencodeDir = findOpencodeDir2(workingDirectory);
|
|
11730
|
-
const projectOverridesDir = opencodeDir ?
|
|
11882
|
+
const projectOverridesDir = opencodeDir ? join6(opencodeDir, "acp-prompts", "overrides") : null;
|
|
11731
11883
|
return {
|
|
11732
11884
|
defaultsDir,
|
|
11733
11885
|
globalOverridesDir,
|
|
@@ -11827,7 +11979,7 @@ function buildDefaultsReadmeContent() {
|
|
|
11827
11979
|
`;
|
|
11828
11980
|
}
|
|
11829
11981
|
function readFileIfExists(filePath) {
|
|
11830
|
-
if (!
|
|
11982
|
+
if (!existsSync6(filePath)) {
|
|
11831
11983
|
return null;
|
|
11832
11984
|
}
|
|
11833
11985
|
try {
|
|
@@ -11900,23 +12052,23 @@ var PromptStore = class {
|
|
|
11900
12052
|
const candidates = [];
|
|
11901
12053
|
if (this.paths.projectOverridesDir) {
|
|
11902
12054
|
candidates.push({
|
|
11903
|
-
path:
|
|
12055
|
+
path: join6(this.paths.projectOverridesDir, fileName)
|
|
11904
12056
|
});
|
|
11905
12057
|
}
|
|
11906
12058
|
if (this.paths.configDirOverridesDir) {
|
|
11907
12059
|
candidates.push({
|
|
11908
|
-
path:
|
|
12060
|
+
path: join6(this.paths.configDirOverridesDir, fileName)
|
|
11909
12061
|
});
|
|
11910
12062
|
}
|
|
11911
12063
|
candidates.push({
|
|
11912
|
-
path:
|
|
12064
|
+
path: join6(this.paths.globalOverridesDir, fileName)
|
|
11913
12065
|
});
|
|
11914
12066
|
return candidates;
|
|
11915
12067
|
}
|
|
11916
12068
|
ensureDefaultFiles() {
|
|
11917
12069
|
try {
|
|
11918
|
-
|
|
11919
|
-
|
|
12070
|
+
mkdirSync3(this.paths.defaultsDir, { recursive: true });
|
|
12071
|
+
mkdirSync3(this.paths.globalOverridesDir, { recursive: true });
|
|
11920
12072
|
} catch {
|
|
11921
12073
|
this.logger.warn("Failed to initialize prompt directories", {
|
|
11922
12074
|
defaultsDir: this.paths.defaultsDir,
|
|
@@ -11933,13 +12085,13 @@ var PromptStore = class {
|
|
|
11933
12085
|
const managedContent = buildDefaultPromptFileContent(
|
|
11934
12086
|
bundledEditable || bundledPrompts[definition.runtimeField]
|
|
11935
12087
|
);
|
|
11936
|
-
const filePath =
|
|
12088
|
+
const filePath = join6(this.paths.defaultsDir, definition.fileName);
|
|
11937
12089
|
try {
|
|
11938
12090
|
const existing = readFileIfExists(filePath);
|
|
11939
12091
|
if (existing === managedContent) {
|
|
11940
12092
|
continue;
|
|
11941
12093
|
}
|
|
11942
|
-
|
|
12094
|
+
writeFileSync3(filePath, managedContent, "utf-8");
|
|
11943
12095
|
} catch {
|
|
11944
12096
|
this.logger.warn("Failed to write default prompt file", {
|
|
11945
12097
|
key: definition.key,
|
|
@@ -11947,12 +12099,12 @@ var PromptStore = class {
|
|
|
11947
12099
|
});
|
|
11948
12100
|
}
|
|
11949
12101
|
}
|
|
11950
|
-
const readmePath =
|
|
12102
|
+
const readmePath = join6(this.paths.defaultsDir, DEFAULTS_README_FILE);
|
|
11951
12103
|
const readmeContent = buildDefaultsReadmeContent();
|
|
11952
12104
|
try {
|
|
11953
12105
|
const existing = readFileIfExists(readmePath);
|
|
11954
12106
|
if (existing !== readmeContent) {
|
|
11955
|
-
|
|
12107
|
+
writeFileSync3(readmePath, readmeContent, "utf-8");
|
|
11956
12108
|
}
|
|
11957
12109
|
} catch {
|
|
11958
12110
|
this.logger.warn("Failed to write defaults README", {
|
|
@@ -12420,8 +12572,8 @@ ${report}`;
|
|
|
12420
12572
|
|
|
12421
12573
|
// lib/commands/export.ts
|
|
12422
12574
|
import * as fs2 from "fs/promises";
|
|
12423
|
-
import { existsSync as
|
|
12424
|
-
import { dirname as dirname3, isAbsolute as isAbsolute2, join as
|
|
12575
|
+
import { existsSync as existsSync7 } from "fs";
|
|
12576
|
+
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join7, resolve } from "path";
|
|
12425
12577
|
var ALL_TIERS = [1, 2, 3];
|
|
12426
12578
|
var TIER_NAMES = {
|
|
12427
12579
|
1: "Tier 1 \u2014 Capture",
|
|
@@ -12534,7 +12686,7 @@ function parseTiers(raw) {
|
|
|
12534
12686
|
}
|
|
12535
12687
|
function resolveDefaultOutputPath(sessionId, cwd2) {
|
|
12536
12688
|
const short = (sessionId || "session").slice(0, 8);
|
|
12537
|
-
return
|
|
12689
|
+
return join7(cwd2, ".opencode", `acp-export-${short}.md`);
|
|
12538
12690
|
}
|
|
12539
12691
|
function formatTokens2(n) {
|
|
12540
12692
|
if (!Number.isFinite(n) || n <= 0) return "0";
|
|
@@ -12665,11 +12817,11 @@ async function handleExportCommand(ctx, args) {
|
|
|
12665
12817
|
const targetPath = options.outputPath !== "" ? isAbsolute2(options.outputPath) ? options.outputPath : resolve(cwd2, options.outputPath) : resolveDefaultOutputPath(sessionId, cwd2);
|
|
12666
12818
|
try {
|
|
12667
12819
|
const dir = dirname3(targetPath);
|
|
12668
|
-
if (!
|
|
12820
|
+
if (!existsSync7(dir)) {
|
|
12669
12821
|
await fs2.mkdir(dir, { recursive: true });
|
|
12670
12822
|
}
|
|
12671
12823
|
const flag = options.append ? "a" : "w";
|
|
12672
|
-
if (options.append &&
|
|
12824
|
+
if (options.append && existsSync7(targetPath)) {
|
|
12673
12825
|
await fs2.appendFile(targetPath, `
|
|
12674
12826
|
|
|
12675
12827
|
---
|
|
@@ -13384,6 +13536,20 @@ function createChatMessageTransformHandler(client, registry4, logger, config, pr
|
|
|
13384
13536
|
});
|
|
13385
13537
|
cacheSystemPromptTokens(state, output.messages);
|
|
13386
13538
|
assignMessageRefs(state, output.messages);
|
|
13539
|
+
const imagesConfig = config.compress.images ?? DEFAULT_COMPRESS_IMAGES;
|
|
13540
|
+
if (imagesConfig.enabled) {
|
|
13541
|
+
const archivedImages = archiveSessionImages(
|
|
13542
|
+
state,
|
|
13543
|
+
output.messages,
|
|
13544
|
+
imagesConfig,
|
|
13545
|
+
logger
|
|
13546
|
+
);
|
|
13547
|
+
if (archivedImages > 0) {
|
|
13548
|
+
saveSessionState(state, logger).catch(() => {
|
|
13549
|
+
});
|
|
13550
|
+
}
|
|
13551
|
+
pruneImageArchive(state, imagesConfig, logger);
|
|
13552
|
+
}
|
|
13387
13553
|
const activeBlockCountBefore = state.prune.messages.activeBlockIds.size;
|
|
13388
13554
|
const compressionStateChanged = syncCompressionBlocks(state, logger, output.messages);
|
|
13389
13555
|
if (compressionStateChanged || state.prune.messages.activeBlockIds.size !== activeBlockCountBefore) {
|
|
@@ -13397,7 +13563,7 @@ function createChatMessageTransformHandler(client, registry4, logger, config, pr
|
|
|
13397
13563
|
saveSessionState(state, logger).catch(() => {
|
|
13398
13564
|
});
|
|
13399
13565
|
}
|
|
13400
|
-
const prePruneTokens =
|
|
13566
|
+
const prePruneTokens = getCurrentTokenUsage(state, output.messages);
|
|
13401
13567
|
const candidateMessages = config.compress.candidates === true ? output.messages.slice() : void 0;
|
|
13402
13568
|
prune(state, logger, config, output.messages);
|
|
13403
13569
|
hideConsumedCompressCalls(state, output.messages);
|
|
@@ -13446,7 +13612,7 @@ ${text}`);
|
|
|
13446
13612
|
if (state.sessionId && smartPlanEnabled === true) {
|
|
13447
13613
|
recordVisibleMessages(state.sessionId, output.messages);
|
|
13448
13614
|
}
|
|
13449
|
-
const postTokens =
|
|
13615
|
+
const postTokens = getCurrentTokenUsage(state, output.messages);
|
|
13450
13616
|
if (postTokens !== void 0 && effectiveLimit) {
|
|
13451
13617
|
const budget = effectiveLimit.limit - (state.systemPromptTokens ?? 0) - OUTPUT_RESERVE_TOKENS;
|
|
13452
13618
|
if (postTokens > budget) {
|
|
@@ -13661,7 +13827,7 @@ function configureClientAuth(client) {
|
|
|
13661
13827
|
|
|
13662
13828
|
// lib/update.ts
|
|
13663
13829
|
import { readFile as readFile2, rm } from "fs/promises";
|
|
13664
|
-
import { basename, dirname as dirname4, join as
|
|
13830
|
+
import { basename, dirname as dirname4, join as join8 } from "path";
|
|
13665
13831
|
import { fileURLToPath } from "url";
|
|
13666
13832
|
var PACKAGE_NAME = "opencode-acp";
|
|
13667
13833
|
function startAutoUpdate(ctx, enabled, logger) {
|
|
@@ -13708,7 +13874,7 @@ async function checkAutoUpdate(signal, logger) {
|
|
|
13708
13874
|
logger?.info("Auto-update skipped: package dir not found");
|
|
13709
13875
|
return { updated: false };
|
|
13710
13876
|
}
|
|
13711
|
-
const pkg = await readPackageJson(
|
|
13877
|
+
const pkg = await readPackageJson(join8(packageDir, "package.json"));
|
|
13712
13878
|
if (!pkg?.name || !pkg.version) {
|
|
13713
13879
|
logger?.info("Auto-update skipped: package.json unreadable", { packageDir });
|
|
13714
13880
|
return { updated: false };
|
|
@@ -13749,7 +13915,7 @@ async function checkAutoUpdate(signal, logger) {
|
|
|
13749
13915
|
async function findPackageDir(name) {
|
|
13750
13916
|
let dir = dirname4(fileURLToPath(import.meta.url));
|
|
13751
13917
|
for (; ; ) {
|
|
13752
|
-
const pkg = await readPackageJson(
|
|
13918
|
+
const pkg = await readPackageJson(join8(dir, "package.json"));
|
|
13753
13919
|
if (pkg?.name === name) return dir;
|
|
13754
13920
|
const parent = dirname4(dir);
|
|
13755
13921
|
if (parent === dir) return void 0;
|
|
@@ -13761,7 +13927,7 @@ async function updateTarget(packageDir, name) {
|
|
|
13761
13927
|
const nodeModulesDir = basename(packageParent).startsWith("@") ? dirname4(packageParent) : packageParent;
|
|
13762
13928
|
if (basename(nodeModulesDir) !== "node_modules") return void 0;
|
|
13763
13929
|
const wrapperDir = dirname4(nodeModulesDir);
|
|
13764
|
-
const wrapperPkg = await readPackageJson(
|
|
13930
|
+
const wrapperPkg = await readPackageJson(join8(wrapperDir, "package.json"));
|
|
13765
13931
|
const spec = wrapperSpec(wrapperDir, name) ?? wrapperPkg?.dependencies?.[name];
|
|
13766
13932
|
if (!spec || !isAutoUpdatableSpec(spec)) return void 0;
|
|
13767
13933
|
return { removeDir: wrapperDir, spec };
|
|
@@ -13872,7 +14038,7 @@ var server = (async (ctx) => {
|
|
|
13872
14038
|
}
|
|
13873
14039
|
const logger = new Logger(config.debug, config.debug ? "debug" : config.logLevel);
|
|
13874
14040
|
logger.info("ACP plugin initialized", {
|
|
13875
|
-
version: true ? "1.18.3-pr.
|
|
14041
|
+
version: true ? "1.18.3-pr.479.213" : "dev",
|
|
13876
14042
|
workspace: ctx.directory,
|
|
13877
14043
|
logLevel: logger.level,
|
|
13878
14044
|
debug: config.debug,
|