opencode-acp 1.14.27 → 1.15.0-pr.376.118
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 +9 -0
- package/README.zh-CN.md +8 -0
- package/dist/index.js +450 -75
- package/dist/index.js.map +1 -1
- package/dist/lib/config-validation.d.ts.map +1 -1
- package/dist/lib/config.d.ts +51 -3
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/hooks.d.ts.map +1 -1
- package/dist/lib/messages/index.d.ts +1 -1
- package/dist/lib/messages/index.d.ts.map +1 -1
- package/dist/lib/messages/inject/utils.d.ts.map +1 -1
- package/dist/lib/messages/reasoning-strip.d.ts +24 -0
- package/dist/lib/messages/reasoning-strip.d.ts.map +1 -1
- package/dist/lib/state/fork-transfer.d.ts +42 -0
- package/dist/lib/state/fork-transfer.d.ts.map +1 -0
- package/dist/lib/state/persistence.d.ts +14 -3
- package/dist/lib/state/persistence.d.ts.map +1 -1
- package/dist/lib/state/state.d.ts +3 -2
- package/dist/lib/state/state.d.ts.map +1 -1
- package/dist/lib/state/types.d.ts +6 -0
- package/dist/lib/state/types.d.ts.map +1 -1
- package/dist/lib/state/utils.d.ts +1 -0
- package/dist/lib/state/utils.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -869,6 +869,7 @@ var VALID_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
869
869
|
"autoUpdate",
|
|
870
870
|
"debug",
|
|
871
871
|
"logLevel",
|
|
872
|
+
"storagePath",
|
|
872
873
|
"showUpdateToasts",
|
|
873
874
|
"allowSubAgents",
|
|
874
875
|
"pruneNotification",
|
|
@@ -909,6 +910,9 @@ var VALID_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
909
910
|
"compress.preserveRecentMessages",
|
|
910
911
|
"compress.preserveRecentTokens",
|
|
911
912
|
"compress.preserveLastUserMessage",
|
|
913
|
+
"compress.reasoning",
|
|
914
|
+
"compress.reasoning.drop",
|
|
915
|
+
"compress.reasoning.threshold",
|
|
912
916
|
"gc",
|
|
913
917
|
"gc.algorithm",
|
|
914
918
|
"gc.promotionThreshold",
|
|
@@ -956,6 +960,9 @@ function validateConfigTypes(config) {
|
|
|
956
960
|
if (config.debug !== void 0 && typeof config.debug !== "boolean") {
|
|
957
961
|
errors.push({ key: "debug", expected: "boolean", actual: typeof config.debug });
|
|
958
962
|
}
|
|
963
|
+
if (config.storagePath !== void 0 && typeof config.storagePath !== "string") {
|
|
964
|
+
errors.push({ key: "storagePath", expected: "string", actual: typeof config.storagePath });
|
|
965
|
+
}
|
|
959
966
|
if (config.allowSubAgents !== void 0 && typeof config.allowSubAgents !== "boolean") {
|
|
960
967
|
errors.push({ key: "allowSubAgents", expected: "boolean", actual: typeof config.allowSubAgents });
|
|
961
968
|
}
|
|
@@ -1262,6 +1269,30 @@ function validateConfigTypes(config) {
|
|
|
1262
1269
|
actual: typeof compress.preserveLastUserMessage
|
|
1263
1270
|
});
|
|
1264
1271
|
}
|
|
1272
|
+
if (compress.reasoning !== void 0) {
|
|
1273
|
+
if (typeof compress.reasoning !== "object" || compress.reasoning === null || Array.isArray(compress.reasoning)) {
|
|
1274
|
+
errors.push({
|
|
1275
|
+
key: "compress.reasoning",
|
|
1276
|
+
expected: "object { drop?: boolean; threshold?: integer (>= 0) }",
|
|
1277
|
+
actual: JSON.stringify(compress.reasoning)
|
|
1278
|
+
});
|
|
1279
|
+
} else {
|
|
1280
|
+
if (compress.reasoning.drop !== void 0 && typeof compress.reasoning.drop !== "boolean") {
|
|
1281
|
+
errors.push({
|
|
1282
|
+
key: "compress.reasoning.drop",
|
|
1283
|
+
expected: "boolean",
|
|
1284
|
+
actual: typeof compress.reasoning.drop
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1287
|
+
if (compress.reasoning.threshold !== void 0 && (typeof compress.reasoning.threshold !== "number" || !Number.isInteger(compress.reasoning.threshold) || compress.reasoning.threshold < 0)) {
|
|
1288
|
+
errors.push({
|
|
1289
|
+
key: "compress.reasoning.threshold",
|
|
1290
|
+
expected: "integer (>= 0)",
|
|
1291
|
+
actual: JSON.stringify(compress.reasoning.threshold)
|
|
1292
|
+
});
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1265
1296
|
if (typeof compress.iterationNudgeThreshold === "number" && compress.iterationNudgeThreshold < 1) {
|
|
1266
1297
|
errors.push({
|
|
1267
1298
|
key: "compress.iterationNudgeThreshold",
|
|
@@ -1347,7 +1378,8 @@ function validateConfigTypes(config) {
|
|
|
1347
1378
|
maxVisibleSegments: "positiveNumber",
|
|
1348
1379
|
keepEmbedMaxChars: "nonNegativeNumber",
|
|
1349
1380
|
preserveRecentMessages: "nonNegativeNumber",
|
|
1350
|
-
preserveRecentTokens: "nonNegativeNumber"
|
|
1381
|
+
preserveRecentTokens: "nonNegativeNumber",
|
|
1382
|
+
reasoning: "reasoningConfig"
|
|
1351
1383
|
};
|
|
1352
1384
|
const validateOverrideField = (key, type, value) => {
|
|
1353
1385
|
if (value === void 0) {
|
|
@@ -1387,6 +1419,31 @@ function validateConfigTypes(config) {
|
|
|
1387
1419
|
errors.push({ key, expected: "string[]", actual: JSON.stringify(value) });
|
|
1388
1420
|
}
|
|
1389
1421
|
break;
|
|
1422
|
+
case "reasoningConfig":
|
|
1423
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
1424
|
+
errors.push({
|
|
1425
|
+
key,
|
|
1426
|
+
expected: "object { drop?: boolean; threshold?: integer (>= 0) }",
|
|
1427
|
+
actual: JSON.stringify(value)
|
|
1428
|
+
});
|
|
1429
|
+
break;
|
|
1430
|
+
}
|
|
1431
|
+
const reasoning = value;
|
|
1432
|
+
if (reasoning.drop !== void 0 && typeof reasoning.drop !== "boolean") {
|
|
1433
|
+
errors.push({
|
|
1434
|
+
key: `${key}.drop`,
|
|
1435
|
+
expected: "boolean",
|
|
1436
|
+
actual: typeof reasoning.drop
|
|
1437
|
+
});
|
|
1438
|
+
}
|
|
1439
|
+
if (reasoning.threshold !== void 0 && (typeof reasoning.threshold !== "number" || !Number.isInteger(reasoning.threshold) || reasoning.threshold < 0)) {
|
|
1440
|
+
errors.push({
|
|
1441
|
+
key: `${key}.threshold`,
|
|
1442
|
+
expected: "integer (>= 0)",
|
|
1443
|
+
actual: JSON.stringify(reasoning.threshold)
|
|
1444
|
+
});
|
|
1445
|
+
}
|
|
1446
|
+
break;
|
|
1390
1447
|
}
|
|
1391
1448
|
};
|
|
1392
1449
|
const validateOverrideObject = (prefix, overrides) => {
|
|
@@ -1565,6 +1622,10 @@ function validateConfigTypes(config) {
|
|
|
1565
1622
|
}
|
|
1566
1623
|
|
|
1567
1624
|
// lib/config.ts
|
|
1625
|
+
var DEFAULT_COMPRESS_REASONING = {
|
|
1626
|
+
drop: true,
|
|
1627
|
+
threshold: 2048
|
|
1628
|
+
};
|
|
1568
1629
|
var DEFAULT_PROTECTED_TOOLS = [
|
|
1569
1630
|
"task",
|
|
1570
1631
|
"skill",
|
|
@@ -1659,7 +1720,8 @@ var defaultConfig = {
|
|
|
1659
1720
|
lastSegmentSoftBlock: true,
|
|
1660
1721
|
preserveRecentMessages: 5,
|
|
1661
1722
|
preserveRecentTokens: 5e3,
|
|
1662
|
-
preserveLastUserMessage: true
|
|
1723
|
+
preserveLastUserMessage: true,
|
|
1724
|
+
reasoning: { ...DEFAULT_COMPRESS_REASONING }
|
|
1663
1725
|
},
|
|
1664
1726
|
gc: {
|
|
1665
1727
|
algorithm: "truncate",
|
|
@@ -1829,7 +1891,11 @@ function mergeCompress(base, override) {
|
|
|
1829
1891
|
lastSegmentSoftBlock: override.lastSegmentSoftBlock ?? base.lastSegmentSoftBlock,
|
|
1830
1892
|
preserveRecentMessages: override.preserveRecentMessages ?? base.preserveRecentMessages,
|
|
1831
1893
|
preserveRecentTokens: override.preserveRecentTokens ?? base.preserveRecentTokens,
|
|
1832
|
-
preserveLastUserMessage: override.preserveLastUserMessage ?? base.preserveLastUserMessage
|
|
1894
|
+
preserveLastUserMessage: override.preserveLastUserMessage ?? base.preserveLastUserMessage,
|
|
1895
|
+
reasoning: {
|
|
1896
|
+
drop: override.reasoning?.drop ?? base.reasoning?.drop ?? DEFAULT_COMPRESS_REASONING.drop,
|
|
1897
|
+
threshold: override.reasoning?.threshold ?? base.reasoning?.threshold ?? DEFAULT_COMPRESS_REASONING.threshold
|
|
1898
|
+
}
|
|
1833
1899
|
};
|
|
1834
1900
|
}
|
|
1835
1901
|
function mergeCommands(base, override) {
|
|
@@ -1933,6 +1999,7 @@ function mergeLayer(config, data) {
|
|
|
1933
1999
|
autoUpdate: data.autoUpdate ?? config.autoUpdate,
|
|
1934
2000
|
debug: data.debug ?? config.debug,
|
|
1935
2001
|
logLevel: data.logLevel ?? config.logLevel,
|
|
2002
|
+
storagePath: data.storagePath ?? config.storagePath,
|
|
1936
2003
|
allowSubAgents: data.allowSubAgents ?? data.experimental?.allowSubAgents ?? config.allowSubAgents,
|
|
1937
2004
|
pruneNotification: data.pruneNotification ?? config.pruneNotification,
|
|
1938
2005
|
pruneNotificationType: data.pruneNotificationType ?? config.pruneNotificationType,
|
|
@@ -2287,7 +2354,7 @@ Each entry needs a topic \u2014 either its own or the top-level fallback.`;
|
|
|
2287
2354
|
import * as fs from "fs/promises";
|
|
2288
2355
|
import { existsSync as existsSync2 } from "fs";
|
|
2289
2356
|
import { homedir as homedir2 } from "os";
|
|
2290
|
-
import { join as join2 } from "path";
|
|
2357
|
+
import { isAbsolute, join as join2 } from "path";
|
|
2291
2358
|
|
|
2292
2359
|
// lib/state/utils.ts
|
|
2293
2360
|
var isMessageCompacted = (state, msg) => {
|
|
@@ -2323,12 +2390,12 @@ function serializePruneMessagesState(messagesState) {
|
|
|
2323
2390
|
markedForCleanup: Array.from(messagesState.markedForCleanup)
|
|
2324
2391
|
};
|
|
2325
2392
|
}
|
|
2326
|
-
async function
|
|
2393
|
+
async function getForkParentId(client, sessionID) {
|
|
2327
2394
|
try {
|
|
2328
2395
|
const result = await client.session.get({ path: { id: sessionID } });
|
|
2329
|
-
return
|
|
2396
|
+
return result.data?.parentID ?? null;
|
|
2330
2397
|
} catch (error) {
|
|
2331
|
-
return
|
|
2398
|
+
return null;
|
|
2332
2399
|
}
|
|
2333
2400
|
}
|
|
2334
2401
|
function findLastCompactionTimestamp(messages) {
|
|
@@ -2570,7 +2637,7 @@ function resetOnCompaction(state) {
|
|
|
2570
2637
|
}
|
|
2571
2638
|
|
|
2572
2639
|
// lib/state/persistence.ts
|
|
2573
|
-
function
|
|
2640
|
+
function getDefaultStorageDir() {
|
|
2574
2641
|
return join2(
|
|
2575
2642
|
process.env.XDG_DATA_HOME || join2(homedir2(), ".local", "share"),
|
|
2576
2643
|
"opencode",
|
|
@@ -2579,14 +2646,33 @@ function getStorageDir() {
|
|
|
2579
2646
|
"acp"
|
|
2580
2647
|
);
|
|
2581
2648
|
}
|
|
2582
|
-
function
|
|
2583
|
-
|
|
2649
|
+
function resolveStorageDir(configured, projectDir) {
|
|
2650
|
+
const trimmed = configured?.trim();
|
|
2651
|
+
if (!trimmed) {
|
|
2652
|
+
return getDefaultStorageDir();
|
|
2653
|
+
}
|
|
2654
|
+
if (trimmed === "~") {
|
|
2655
|
+
return homedir2();
|
|
2656
|
+
}
|
|
2657
|
+
if (trimmed.startsWith("~/")) {
|
|
2658
|
+
return join2(homedir2(), trimmed.slice(2));
|
|
2659
|
+
}
|
|
2660
|
+
if (isAbsolute(trimmed)) {
|
|
2661
|
+
return trimmed;
|
|
2662
|
+
}
|
|
2663
|
+
return join2(projectDir, trimmed);
|
|
2664
|
+
}
|
|
2665
|
+
function getStorageDir(override) {
|
|
2666
|
+
return override || getDefaultStorageDir();
|
|
2584
2667
|
}
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2668
|
+
function getSessionFilePath(sessionId, storageDir) {
|
|
2669
|
+
return join2(getStorageDir(storageDir), `${sessionId}.json`);
|
|
2670
|
+
}
|
|
2671
|
+
async function writePersistedSessionState(sessionId, state, logger, storageDir) {
|
|
2672
|
+
const filePath = getSessionFilePath(sessionId, storageDir);
|
|
2673
|
+
const dir = getStorageDir(storageDir);
|
|
2674
|
+
if (!existsSync2(dir)) {
|
|
2675
|
+
await fs.mkdir(dir, { recursive: true });
|
|
2590
2676
|
}
|
|
2591
2677
|
const content = JSON.stringify(state, null, 2);
|
|
2592
2678
|
await fs.writeFile(filePath, content, "utf-8");
|
|
@@ -2628,11 +2714,11 @@ async function saveSessionState(sessionState, logger, sessionName) {
|
|
|
2628
2714
|
modelProviderID: sessionState.modelProviderID,
|
|
2629
2715
|
modelID: sessionState.modelID
|
|
2630
2716
|
};
|
|
2631
|
-
await writePersistedSessionState(sessionState.sessionId, state, logger);
|
|
2717
|
+
await writePersistedSessionState(sessionState.sessionId, state, logger, sessionState.storageDir);
|
|
2632
2718
|
}
|
|
2633
|
-
async function loadSessionState(sessionId, logger) {
|
|
2719
|
+
async function loadSessionState(sessionId, logger, storageDir) {
|
|
2634
2720
|
try {
|
|
2635
|
-
const filePath = getSessionFilePath(sessionId);
|
|
2721
|
+
const filePath = getSessionFilePath(sessionId, storageDir);
|
|
2636
2722
|
if (!existsSync2(filePath)) {
|
|
2637
2723
|
return null;
|
|
2638
2724
|
}
|
|
@@ -2708,6 +2794,11 @@ async function loadSessionState(sessionId, logger) {
|
|
|
2708
2794
|
}
|
|
2709
2795
|
}
|
|
2710
2796
|
|
|
2797
|
+
// lib/state/state.ts
|
|
2798
|
+
import { existsSync as existsSync3 } from "fs";
|
|
2799
|
+
import { join as join3 } from "path";
|
|
2800
|
+
import { cwd } from "process";
|
|
2801
|
+
|
|
2711
2802
|
// lib/message-ids.ts
|
|
2712
2803
|
var MESSAGE_REF_REGEX = /^m(\d{4,5})$/;
|
|
2713
2804
|
var BLOCK_REF_REGEX = /^b([1-9]\d*)$/;
|
|
@@ -4365,6 +4456,205 @@ function rebuildCompressionState(state, messages, config, logger) {
|
|
|
4365
4456
|
return rebuilt;
|
|
4366
4457
|
}
|
|
4367
4458
|
|
|
4459
|
+
// lib/state/fork-transfer.ts
|
|
4460
|
+
function extractIdentity(message) {
|
|
4461
|
+
const id = message?.info?.id;
|
|
4462
|
+
if (typeof id !== "string" || id.length === 0) {
|
|
4463
|
+
return null;
|
|
4464
|
+
}
|
|
4465
|
+
if (isSyntheticMessage(message)) {
|
|
4466
|
+
return null;
|
|
4467
|
+
}
|
|
4468
|
+
const role = message.info.role;
|
|
4469
|
+
const created = message.info.time?.created;
|
|
4470
|
+
if (typeof created !== "number") {
|
|
4471
|
+
return null;
|
|
4472
|
+
}
|
|
4473
|
+
return { id, role, created };
|
|
4474
|
+
}
|
|
4475
|
+
function buildSharedPrefixMapping(parentMessages, forkMessages) {
|
|
4476
|
+
const parentIds = parentMessages.map(extractIdentity).filter((x) => x !== null);
|
|
4477
|
+
const forkIds = forkMessages.map(extractIdentity).filter((x) => x !== null);
|
|
4478
|
+
const mapping = /* @__PURE__ */ new Map();
|
|
4479
|
+
const limit = Math.min(parentIds.length, forkIds.length);
|
|
4480
|
+
for (let i = 0; i < limit; i++) {
|
|
4481
|
+
const p = parentIds[i];
|
|
4482
|
+
const f = forkIds[i];
|
|
4483
|
+
if (p.created === f.created && p.role === f.role) {
|
|
4484
|
+
mapping.set(p.id, f.id);
|
|
4485
|
+
} else {
|
|
4486
|
+
break;
|
|
4487
|
+
}
|
|
4488
|
+
}
|
|
4489
|
+
return mapping;
|
|
4490
|
+
}
|
|
4491
|
+
function remapBoundaryRef(ref, mapping, forkByRawId, parentByRef) {
|
|
4492
|
+
const parsed = parseBoundaryId(ref);
|
|
4493
|
+
if (!parsed) {
|
|
4494
|
+
return ref;
|
|
4495
|
+
}
|
|
4496
|
+
if (parsed.kind === "compressed-block") {
|
|
4497
|
+
return parsed.ref;
|
|
4498
|
+
}
|
|
4499
|
+
const parentRawId = parentByRef.get(parsed.ref);
|
|
4500
|
+
if (!parentRawId) {
|
|
4501
|
+
return ref;
|
|
4502
|
+
}
|
|
4503
|
+
const forkRawId = mapping.get(parentRawId);
|
|
4504
|
+
if (!forkRawId) {
|
|
4505
|
+
return ref;
|
|
4506
|
+
}
|
|
4507
|
+
const forkRef = forkByRawId.get(forkRawId);
|
|
4508
|
+
return forkRef ?? ref;
|
|
4509
|
+
}
|
|
4510
|
+
function translateBlock(block, mapping, forkByRawId, parentByRef) {
|
|
4511
|
+
const anchorForkId = mapping.get(block.anchorMessageId);
|
|
4512
|
+
if (!anchorForkId) {
|
|
4513
|
+
return null;
|
|
4514
|
+
}
|
|
4515
|
+
const compressForkId = mapping.get(block.compressMessageId);
|
|
4516
|
+
if (!compressForkId) {
|
|
4517
|
+
return null;
|
|
4518
|
+
}
|
|
4519
|
+
const translateList = (ids) => ids.map((id) => mapping.get(id)).filter((id) => id !== void 0);
|
|
4520
|
+
const preserveList = (ids) => [...new Set(ids)];
|
|
4521
|
+
return {
|
|
4522
|
+
...block,
|
|
4523
|
+
anchorMessageId: anchorForkId,
|
|
4524
|
+
compressMessageId: compressForkId,
|
|
4525
|
+
directMessageIds: translateList(block.directMessageIds),
|
|
4526
|
+
effectiveMessageIds: translateList(block.effectiveMessageIds),
|
|
4527
|
+
directToolIds: preserveList(block.directToolIds),
|
|
4528
|
+
effectiveToolIds: preserveList(block.effectiveToolIds),
|
|
4529
|
+
startId: remapBoundaryRef(block.startId, mapping, forkByRawId, parentByRef),
|
|
4530
|
+
endId: remapBoundaryRef(block.endId, mapping, forkByRawId, parentByRef)
|
|
4531
|
+
};
|
|
4532
|
+
}
|
|
4533
|
+
function translateByMessageId(parentByMessageId, mapping, translatedBlockIds) {
|
|
4534
|
+
const result = /* @__PURE__ */ new Map();
|
|
4535
|
+
for (const [parentMsgId, entry] of Object.entries(parentByMessageId)) {
|
|
4536
|
+
if (!entry || typeof entry !== "object") {
|
|
4537
|
+
continue;
|
|
4538
|
+
}
|
|
4539
|
+
const forkMsgId = mapping.get(parentMsgId);
|
|
4540
|
+
if (!forkMsgId) {
|
|
4541
|
+
continue;
|
|
4542
|
+
}
|
|
4543
|
+
const allBlockIds = (entry.allBlockIds ?? []).filter((id) => translatedBlockIds.has(id));
|
|
4544
|
+
const activeBlockIds = (entry.activeBlockIds ?? []).filter(
|
|
4545
|
+
(id) => translatedBlockIds.has(id)
|
|
4546
|
+
);
|
|
4547
|
+
result.set(forkMsgId, {
|
|
4548
|
+
tokenCount: typeof entry.tokenCount === "number" ? entry.tokenCount : 0,
|
|
4549
|
+
allBlockIds,
|
|
4550
|
+
activeBlockIds
|
|
4551
|
+
});
|
|
4552
|
+
}
|
|
4553
|
+
return result;
|
|
4554
|
+
}
|
|
4555
|
+
async function recoverFromParentState(client, state, forkMessages, parentId, logger) {
|
|
4556
|
+
const parentState = await loadSessionState(parentId, logger);
|
|
4557
|
+
if (!parentState) {
|
|
4558
|
+
logger.info("fork-transfer: no parent state found, falling back to replay", {
|
|
4559
|
+
parentId
|
|
4560
|
+
});
|
|
4561
|
+
return 0;
|
|
4562
|
+
}
|
|
4563
|
+
const parentMessagesState = parentState.prune?.messages;
|
|
4564
|
+
const parentBlocks = parentMessagesState?.blocksById;
|
|
4565
|
+
if (!parentBlocks) {
|
|
4566
|
+
logger.info("fork-transfer: parent state has no blocks, falling back to replay", {
|
|
4567
|
+
parentId
|
|
4568
|
+
});
|
|
4569
|
+
return 0;
|
|
4570
|
+
}
|
|
4571
|
+
const parentBlockEntries = Object.entries(parentBlocks).filter(
|
|
4572
|
+
([id, block]) => Number.isInteger(Number.parseInt(id, 10)) && Number.parseInt(id, 10) >= 1 && !!block
|
|
4573
|
+
);
|
|
4574
|
+
if (parentBlockEntries.length === 0) {
|
|
4575
|
+
logger.info("fork-transfer: parent state has no blocks, falling back to replay", {
|
|
4576
|
+
parentId
|
|
4577
|
+
});
|
|
4578
|
+
return 0;
|
|
4579
|
+
}
|
|
4580
|
+
let parentMessages;
|
|
4581
|
+
try {
|
|
4582
|
+
const response = await client.session.messages({ path: { id: parentId } });
|
|
4583
|
+
parentMessages = filterMessages(response?.data || response);
|
|
4584
|
+
} catch (error) {
|
|
4585
|
+
logger.warn("fork-transfer: failed to fetch parent messages, falling back to replay", {
|
|
4586
|
+
parentId,
|
|
4587
|
+
error: error?.message || String(error)
|
|
4588
|
+
});
|
|
4589
|
+
return 0;
|
|
4590
|
+
}
|
|
4591
|
+
const mapping = buildSharedPrefixMapping(parentMessages, forkMessages);
|
|
4592
|
+
if (mapping.size === 0) {
|
|
4593
|
+
logger.info("fork-transfer: no shared prefix detected, falling back to replay", {
|
|
4594
|
+
parentId
|
|
4595
|
+
});
|
|
4596
|
+
return 0;
|
|
4597
|
+
}
|
|
4598
|
+
assignMessageRefs(state, forkMessages);
|
|
4599
|
+
const forkByRawId = state.messageIds.byRawId;
|
|
4600
|
+
const parentByRef = new Map(Object.entries(parentState.messageIds?.byRef ?? {}));
|
|
4601
|
+
const translatedBlocks = /* @__PURE__ */ new Map();
|
|
4602
|
+
let skipped = 0;
|
|
4603
|
+
for (const [blockIdStr, block] of parentBlockEntries) {
|
|
4604
|
+
const blockId = Number.parseInt(blockIdStr, 10);
|
|
4605
|
+
const translated = translateBlock(block, mapping, forkByRawId, parentByRef);
|
|
4606
|
+
if (translated) {
|
|
4607
|
+
translatedBlocks.set(blockId, translated);
|
|
4608
|
+
} else {
|
|
4609
|
+
skipped++;
|
|
4610
|
+
}
|
|
4611
|
+
}
|
|
4612
|
+
if (translatedBlocks.size === 0) {
|
|
4613
|
+
logger.info("fork-transfer: no blocks translatable, falling back to replay", {
|
|
4614
|
+
parentId,
|
|
4615
|
+
parentBlockCount: parentBlockEntries.length,
|
|
4616
|
+
mappingSize: mapping.size
|
|
4617
|
+
});
|
|
4618
|
+
return 0;
|
|
4619
|
+
}
|
|
4620
|
+
const activeCount = Array.from(translatedBlocks.values()).filter((b) => b.active).length;
|
|
4621
|
+
if (activeCount === 0) {
|
|
4622
|
+
logger.info("fork-transfer: no active blocks translatable, falling back to replay", {
|
|
4623
|
+
parentId,
|
|
4624
|
+
recoveredBlocks: translatedBlocks.size,
|
|
4625
|
+
skippedBlocks: skipped,
|
|
4626
|
+
mappingSize: mapping.size
|
|
4627
|
+
});
|
|
4628
|
+
return 0;
|
|
4629
|
+
}
|
|
4630
|
+
const translatedByMessageId = translateByMessageId(
|
|
4631
|
+
parentMessagesState.byMessageId ?? {},
|
|
4632
|
+
mapping,
|
|
4633
|
+
new Set(translatedBlocks.keys())
|
|
4634
|
+
);
|
|
4635
|
+
state.prune.messages = loadPruneMessagesState({
|
|
4636
|
+
byMessageId: Object.fromEntries(translatedByMessageId),
|
|
4637
|
+
blocksById: Object.fromEntries(
|
|
4638
|
+
Array.from(translatedBlocks.entries()).map(
|
|
4639
|
+
([id, block]) => [String(id), block]
|
|
4640
|
+
)
|
|
4641
|
+
),
|
|
4642
|
+
activeBlockIds: [],
|
|
4643
|
+
activeByAnchorMessageId: {},
|
|
4644
|
+
nextBlockId: 1,
|
|
4645
|
+
nextRunId: 1,
|
|
4646
|
+
markedForCleanup: []
|
|
4647
|
+
});
|
|
4648
|
+
logger.info("fork-transfer: recovered compression state from parent", {
|
|
4649
|
+
parentId,
|
|
4650
|
+
recoveredBlocks: translatedBlocks.size,
|
|
4651
|
+
activeBlocks: activeCount,
|
|
4652
|
+
skippedBlocks: skipped,
|
|
4653
|
+
mappingSize: mapping.size
|
|
4654
|
+
});
|
|
4655
|
+
return activeCount;
|
|
4656
|
+
}
|
|
4657
|
+
|
|
4368
4658
|
// lib/state/state.ts
|
|
4369
4659
|
async function updatePerTurnState(state, logger, messages) {
|
|
4370
4660
|
const lastCompactionTimestamp = findLastCompactionTimestamp(messages);
|
|
@@ -4384,10 +4674,12 @@ async function updatePerTurnState(state, logger, messages) {
|
|
|
4384
4674
|
}
|
|
4385
4675
|
var REGISTRY_SOFT_CAP = 32;
|
|
4386
4676
|
var SessionStateRegistry = class {
|
|
4387
|
-
constructor(logger) {
|
|
4677
|
+
constructor(logger, projectDir) {
|
|
4388
4678
|
this.logger = logger;
|
|
4679
|
+
this.projectDir = projectDir;
|
|
4389
4680
|
}
|
|
4390
4681
|
logger;
|
|
4682
|
+
projectDir;
|
|
4391
4683
|
states = /* @__PURE__ */ new Map();
|
|
4392
4684
|
compressionTiming = {
|
|
4393
4685
|
startsByCallId: /* @__PURE__ */ new Map(),
|
|
@@ -4440,7 +4732,8 @@ var SessionStateRegistry = class {
|
|
|
4440
4732
|
sessionId,
|
|
4441
4733
|
this.logger,
|
|
4442
4734
|
messages,
|
|
4443
|
-
config
|
|
4735
|
+
config,
|
|
4736
|
+
this.projectDir
|
|
4444
4737
|
);
|
|
4445
4738
|
} catch (err) {
|
|
4446
4739
|
this.logger.error("Failed to initialize session state", {
|
|
@@ -4504,6 +4797,7 @@ function createSessionState() {
|
|
|
4504
4797
|
modelProviderID: void 0,
|
|
4505
4798
|
modelID: void 0,
|
|
4506
4799
|
systemPromptTokens: void 0,
|
|
4800
|
+
storageDir: void 0,
|
|
4507
4801
|
qualityGateRetryPending: false
|
|
4508
4802
|
};
|
|
4509
4803
|
}
|
|
@@ -4545,24 +4839,39 @@ function resetSessionState(state) {
|
|
|
4545
4839
|
state.modelProviderID = void 0;
|
|
4546
4840
|
state.modelID = void 0;
|
|
4547
4841
|
state.systemPromptTokens = void 0;
|
|
4842
|
+
state.storageDir = void 0;
|
|
4548
4843
|
state.qualityGateRetryPending = false;
|
|
4549
4844
|
}
|
|
4550
|
-
async function ensureSessionInitialized(client, state, sessionId, logger, messages, config) {
|
|
4845
|
+
async function ensureSessionInitialized(client, state, sessionId, logger, messages, config, projectDir) {
|
|
4551
4846
|
if (state.sessionId === sessionId) {
|
|
4552
4847
|
return;
|
|
4553
4848
|
}
|
|
4554
4849
|
resetSessionState(state);
|
|
4555
4850
|
state.sessionId = sessionId;
|
|
4556
|
-
|
|
4557
|
-
|
|
4851
|
+
state.storageDir = config?.storagePath ? resolveStorageDir(config.storagePath, projectDir ?? cwd()) : void 0;
|
|
4852
|
+
const parentId = await getForkParentId(client, sessionId);
|
|
4853
|
+
state.isSubAgent = parentId !== null;
|
|
4558
4854
|
state.lastCompaction = findLastCompactionTimestamp(messages);
|
|
4559
4855
|
state.currentTurn = countTurns(state, messages);
|
|
4560
4856
|
state.nudges.turnNudgeAnchors = collectTurnNudgeAnchors(messages);
|
|
4561
|
-
const persisted = await loadSessionState(sessionId, logger);
|
|
4857
|
+
const persisted = await loadSessionState(sessionId, logger, state.storageDir);
|
|
4562
4858
|
if (persisted === null) {
|
|
4859
|
+
const defaultPath = join3(getDefaultStorageDir(), `${sessionId}.json`);
|
|
4860
|
+
if (state.storageDir && existsSync3(defaultPath)) {
|
|
4861
|
+
logger.warn(
|
|
4862
|
+
"storagePath is set but no valid state was found there; a state file exists at the default location \u2014 move it manually to keep history",
|
|
4863
|
+
{ sessionId, storageDir: state.storageDir, defaultPath }
|
|
4864
|
+
);
|
|
4865
|
+
}
|
|
4563
4866
|
if (config) {
|
|
4564
|
-
|
|
4565
|
-
if (
|
|
4867
|
+
let recovered = 0;
|
|
4868
|
+
if (parentId) {
|
|
4869
|
+
recovered = await recoverFromParentState(client, state, messages, parentId, logger);
|
|
4870
|
+
}
|
|
4871
|
+
if (recovered === 0) {
|
|
4872
|
+
recovered = rebuildCompressionState(state, messages, config, logger);
|
|
4873
|
+
}
|
|
4874
|
+
if (recovered > 0) {
|
|
4566
4875
|
await saveSessionState(state, logger);
|
|
4567
4876
|
}
|
|
4568
4877
|
}
|
|
@@ -6647,10 +6956,11 @@ function resolveCompressOverrides(config, providerId, modelId) {
|
|
|
6647
6956
|
}
|
|
6648
6957
|
const { models: _models, ...providerFields } = providerEntry;
|
|
6649
6958
|
const modelEntry = modelId !== void 0 ? providerEntry.models?.[modelId] : void 0;
|
|
6650
|
-
|
|
6651
|
-
|
|
6959
|
+
const merged = modelEntry ? { ...providerFields, ...modelEntry } : providerFields;
|
|
6960
|
+
if (providerFields.reasoning !== void 0 || modelEntry?.reasoning !== void 0) {
|
|
6961
|
+
merged.reasoning = { ...providerFields.reasoning, ...modelEntry?.reasoning };
|
|
6652
6962
|
}
|
|
6653
|
-
return
|
|
6963
|
+
return merged;
|
|
6654
6964
|
}
|
|
6655
6965
|
function resolveMinNudgeContextPercent(config, providerId, modelId) {
|
|
6656
6966
|
const overrides = resolveCompressOverrides(config, providerId, modelId);
|
|
@@ -6667,19 +6977,26 @@ function resolveMinNudgeFloorTokens(config, modelContextLimit, providerId, model
|
|
|
6667
6977
|
const clamped = Math.min(100, Math.max(0, percent));
|
|
6668
6978
|
return Math.round(clamped / 100 * modelContextLimit);
|
|
6669
6979
|
}
|
|
6670
|
-
var OVERRIDE_BLANKET_APPLY_EXCLUDE = /* @__PURE__ */ new Set([
|
|
6980
|
+
var OVERRIDE_BLANKET_APPLY_EXCLUDE = /* @__PURE__ */ new Set([
|
|
6981
|
+
"maxContextLimit",
|
|
6982
|
+
"reasoning"
|
|
6983
|
+
]);
|
|
6671
6984
|
function applyCompressOverrides(config, providerId, modelId) {
|
|
6672
6985
|
const overrides = resolveCompressOverrides(config, providerId, modelId);
|
|
6673
6986
|
const applied = Object.keys(overrides).filter(
|
|
6674
6987
|
(key) => !OVERRIDE_BLANKET_APPLY_EXCLUDE.has(key)
|
|
6675
6988
|
);
|
|
6676
|
-
|
|
6989
|
+
const reasoningOverride = overrides.reasoning;
|
|
6990
|
+
if (applied.length === 0 && reasoningOverride === void 0 || !config.compress) {
|
|
6677
6991
|
return config;
|
|
6678
6992
|
}
|
|
6679
6993
|
const effectiveCompress = { ...config.compress };
|
|
6680
6994
|
for (const key of applied) {
|
|
6681
6995
|
effectiveCompress[key] = overrides[key];
|
|
6682
6996
|
}
|
|
6997
|
+
if (reasoningOverride !== void 0) {
|
|
6998
|
+
effectiveCompress.reasoning = { ...config.compress.reasoning, ...reasoningOverride };
|
|
6999
|
+
}
|
|
6683
7000
|
return { ...config, compress: effectiveCompress };
|
|
6684
7001
|
}
|
|
6685
7002
|
function addAnchor(anchorMessageIds, anchorMessageId, anchorMessageIndex, messages, interval) {
|
|
@@ -8262,6 +8579,46 @@ function stripStaleMetadata(messages) {
|
|
|
8262
8579
|
});
|
|
8263
8580
|
});
|
|
8264
8581
|
}
|
|
8582
|
+
function dropCompressReasoning(messages, threshold) {
|
|
8583
|
+
const lastUserMessage = getLastUserMessage(messages);
|
|
8584
|
+
if (!lastUserMessage || lastUserMessage.info.role !== "user") {
|
|
8585
|
+
return 0;
|
|
8586
|
+
}
|
|
8587
|
+
const lastUserIndex = messages.lastIndexOf(lastUserMessage);
|
|
8588
|
+
if (lastUserIndex <= 0) {
|
|
8589
|
+
return 0;
|
|
8590
|
+
}
|
|
8591
|
+
let removed = 0;
|
|
8592
|
+
for (let i = 0; i < lastUserIndex; i++) {
|
|
8593
|
+
const message = messages[i];
|
|
8594
|
+
if (!message || message.info.role !== "assistant") {
|
|
8595
|
+
continue;
|
|
8596
|
+
}
|
|
8597
|
+
const parts = Array.isArray(message.parts) ? message.parts : [];
|
|
8598
|
+
let hasCompressTool = false;
|
|
8599
|
+
let reasoningLength = 0;
|
|
8600
|
+
for (const part of parts) {
|
|
8601
|
+
if (part.type === "tool" && part.tool === "compress") {
|
|
8602
|
+
hasCompressTool = true;
|
|
8603
|
+
} else if (part.type === "reasoning") {
|
|
8604
|
+
reasoningLength += part.text.length;
|
|
8605
|
+
}
|
|
8606
|
+
}
|
|
8607
|
+
if (!hasCompressTool) {
|
|
8608
|
+
continue;
|
|
8609
|
+
}
|
|
8610
|
+
if (reasoningLength <= threshold) {
|
|
8611
|
+
continue;
|
|
8612
|
+
}
|
|
8613
|
+
const filtered = parts.filter((part) => part.type !== "reasoning");
|
|
8614
|
+
if (filtered.length === parts.length) {
|
|
8615
|
+
continue;
|
|
8616
|
+
}
|
|
8617
|
+
message.parts = filtered;
|
|
8618
|
+
removed += parts.length - filtered.length;
|
|
8619
|
+
}
|
|
8620
|
+
return removed;
|
|
8621
|
+
}
|
|
8265
8622
|
|
|
8266
8623
|
// lib/messages/priority.ts
|
|
8267
8624
|
function buildPriorityMap(_config, _state, _messages) {
|
|
@@ -9375,10 +9732,10 @@ function hideFailedCompressCalls(messages) {
|
|
|
9375
9732
|
|
|
9376
9733
|
// lib/logger.ts
|
|
9377
9734
|
import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
9378
|
-
import { join as
|
|
9379
|
-
import { existsSync as
|
|
9735
|
+
import { join as join4 } from "path";
|
|
9736
|
+
import { existsSync as existsSync4 } from "fs";
|
|
9380
9737
|
import { homedir as homedir3 } from "os";
|
|
9381
|
-
var LOG_VERSION = true ? "1.
|
|
9738
|
+
var LOG_VERSION = true ? "1.15.0-pr.376.118" : "dev";
|
|
9382
9739
|
var LEVEL_RANK = {
|
|
9383
9740
|
debug: 10,
|
|
9384
9741
|
info: 20,
|
|
@@ -9398,8 +9755,8 @@ var Logger = class {
|
|
|
9398
9755
|
constructor(enabled, level) {
|
|
9399
9756
|
const resolved = level !== void 0 && LEVEL_RANK[level] !== void 0 ? level : void 0;
|
|
9400
9757
|
this.level = resolved ?? (enabled ? "debug" : "warn");
|
|
9401
|
-
const configHome = process.env.XDG_CONFIG_HOME ||
|
|
9402
|
-
this.logDir =
|
|
9758
|
+
const configHome = process.env.XDG_CONFIG_HOME || join4(homedir3(), ".config");
|
|
9759
|
+
this.logDir = join4(configHome, "opencode", "logs", "acp");
|
|
9403
9760
|
}
|
|
9404
9761
|
/** Back-compat view of the old flag: true only at full debug verbosity. */
|
|
9405
9762
|
get enabled() {
|
|
@@ -9409,7 +9766,7 @@ var Logger = class {
|
|
|
9409
9766
|
return LEVEL_RANK[level] >= LEVEL_RANK[this.level];
|
|
9410
9767
|
}
|
|
9411
9768
|
async ensureLogDir() {
|
|
9412
|
-
if (!
|
|
9769
|
+
if (!existsSync4(this.logDir)) {
|
|
9413
9770
|
await mkdir2(this.logDir, { recursive: true });
|
|
9414
9771
|
}
|
|
9415
9772
|
}
|
|
@@ -9461,11 +9818,11 @@ var Logger = class {
|
|
|
9461
9818
|
const dataStr = this.formatData(data);
|
|
9462
9819
|
const logLine = `${timestamp} ${level.padEnd(5)} ${component}: ${message}${dataStr ? " | " + dataStr : ""} | v=${LOG_VERSION}
|
|
9463
9820
|
`;
|
|
9464
|
-
const dailyLogDir =
|
|
9465
|
-
if (!
|
|
9821
|
+
const dailyLogDir = join4(this.logDir, "daily");
|
|
9822
|
+
if (!existsSync4(dailyLogDir)) {
|
|
9466
9823
|
await mkdir2(dailyLogDir, { recursive: true });
|
|
9467
9824
|
}
|
|
9468
|
-
const logFile =
|
|
9825
|
+
const logFile = join4(dailyLogDir, `${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.log`);
|
|
9469
9826
|
await writeFile2(logFile, logLine, { flag: "a" });
|
|
9470
9827
|
} catch (error) {
|
|
9471
9828
|
}
|
|
@@ -9576,18 +9933,18 @@ var Logger = class {
|
|
|
9576
9933
|
async saveContext(sessionId, messages) {
|
|
9577
9934
|
if (this.level !== "debug") return;
|
|
9578
9935
|
try {
|
|
9579
|
-
const contextDir =
|
|
9580
|
-
if (!
|
|
9936
|
+
const contextDir = join4(this.logDir, "context", sessionId);
|
|
9937
|
+
if (!existsSync4(contextDir)) {
|
|
9581
9938
|
await mkdir2(contextDir, { recursive: true });
|
|
9582
9939
|
}
|
|
9583
9940
|
const minimized = this.minimizeForDebug(messages).filter(
|
|
9584
9941
|
(msg) => msg.parts && msg.parts.length > 0
|
|
9585
9942
|
);
|
|
9586
9943
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
9587
|
-
const contextFile =
|
|
9944
|
+
const contextFile = join4(contextDir, `${timestamp}.json`);
|
|
9588
9945
|
await writeFile2(contextFile, JSON.stringify(minimized, null, 2));
|
|
9589
|
-
const versionFile =
|
|
9590
|
-
if (!
|
|
9946
|
+
const versionFile = join4(contextDir, "_version");
|
|
9947
|
+
if (!existsSync4(versionFile)) {
|
|
9591
9948
|
await writeFile2(versionFile, LOG_VERSION);
|
|
9592
9949
|
}
|
|
9593
9950
|
} catch (error) {
|
|
@@ -9596,8 +9953,8 @@ var Logger = class {
|
|
|
9596
9953
|
};
|
|
9597
9954
|
|
|
9598
9955
|
// lib/prompts/store.ts
|
|
9599
|
-
import { existsSync as
|
|
9600
|
-
import { join as
|
|
9956
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, statSync as statSync2 } from "fs";
|
|
9957
|
+
import { join as join5, dirname as dirname2 } from "path";
|
|
9601
9958
|
import { homedir as homedir4 } from "os";
|
|
9602
9959
|
|
|
9603
9960
|
// lib/prompts/system.ts
|
|
@@ -9927,8 +10284,8 @@ function createBundledRuntimePrompts() {
|
|
|
9927
10284
|
function findOpencodeDir2(startDir) {
|
|
9928
10285
|
let current = startDir;
|
|
9929
10286
|
while (current !== "/") {
|
|
9930
|
-
const candidate =
|
|
9931
|
-
if (
|
|
10287
|
+
const candidate = join5(current, ".opencode");
|
|
10288
|
+
if (existsSync5(candidate)) {
|
|
9932
10289
|
try {
|
|
9933
10290
|
if (statSync2(candidate).isDirectory()) {
|
|
9934
10291
|
return candidate;
|
|
@@ -9945,13 +10302,13 @@ function findOpencodeDir2(startDir) {
|
|
|
9945
10302
|
return null;
|
|
9946
10303
|
}
|
|
9947
10304
|
function resolvePromptPaths(workingDirectory) {
|
|
9948
|
-
const configHome = process.env.XDG_CONFIG_HOME ||
|
|
9949
|
-
const globalRoot =
|
|
9950
|
-
const defaultsDir =
|
|
9951
|
-
const globalOverridesDir =
|
|
9952
|
-
const configDirOverridesDir = process.env.OPENCODE_CONFIG_DIR ?
|
|
10305
|
+
const configHome = process.env.XDG_CONFIG_HOME || join5(homedir4(), ".config");
|
|
10306
|
+
const globalRoot = join5(configHome, "opencode", "acp-prompts");
|
|
10307
|
+
const defaultsDir = join5(globalRoot, "defaults");
|
|
10308
|
+
const globalOverridesDir = join5(globalRoot, "overrides");
|
|
10309
|
+
const configDirOverridesDir = process.env.OPENCODE_CONFIG_DIR ? join5(process.env.OPENCODE_CONFIG_DIR, "acp-prompts", "overrides") : null;
|
|
9953
10310
|
const opencodeDir = findOpencodeDir2(workingDirectory);
|
|
9954
|
-
const projectOverridesDir = opencodeDir ?
|
|
10311
|
+
const projectOverridesDir = opencodeDir ? join5(opencodeDir, "acp-prompts", "overrides") : null;
|
|
9955
10312
|
return {
|
|
9956
10313
|
defaultsDir,
|
|
9957
10314
|
globalOverridesDir,
|
|
@@ -10051,7 +10408,7 @@ function buildDefaultsReadmeContent() {
|
|
|
10051
10408
|
`;
|
|
10052
10409
|
}
|
|
10053
10410
|
function readFileIfExists(filePath) {
|
|
10054
|
-
if (!
|
|
10411
|
+
if (!existsSync5(filePath)) {
|
|
10055
10412
|
return null;
|
|
10056
10413
|
}
|
|
10057
10414
|
try {
|
|
@@ -10122,16 +10479,16 @@ var PromptStore = class {
|
|
|
10122
10479
|
const candidates = [];
|
|
10123
10480
|
if (this.paths.projectOverridesDir) {
|
|
10124
10481
|
candidates.push({
|
|
10125
|
-
path:
|
|
10482
|
+
path: join5(this.paths.projectOverridesDir, fileName)
|
|
10126
10483
|
});
|
|
10127
10484
|
}
|
|
10128
10485
|
if (this.paths.configDirOverridesDir) {
|
|
10129
10486
|
candidates.push({
|
|
10130
|
-
path:
|
|
10487
|
+
path: join5(this.paths.configDirOverridesDir, fileName)
|
|
10131
10488
|
});
|
|
10132
10489
|
}
|
|
10133
10490
|
candidates.push({
|
|
10134
|
-
path:
|
|
10491
|
+
path: join5(this.paths.globalOverridesDir, fileName)
|
|
10135
10492
|
});
|
|
10136
10493
|
return candidates;
|
|
10137
10494
|
}
|
|
@@ -10154,7 +10511,7 @@ var PromptStore = class {
|
|
|
10154
10511
|
const managedContent = buildDefaultPromptFileContent(
|
|
10155
10512
|
bundledEditable || BUNDLED_EDITABLE_PROMPTS[definition.runtimeField]
|
|
10156
10513
|
);
|
|
10157
|
-
const filePath =
|
|
10514
|
+
const filePath = join5(this.paths.defaultsDir, definition.fileName);
|
|
10158
10515
|
try {
|
|
10159
10516
|
const existing = readFileIfExists(filePath);
|
|
10160
10517
|
if (existing === managedContent) {
|
|
@@ -10168,7 +10525,7 @@ var PromptStore = class {
|
|
|
10168
10525
|
});
|
|
10169
10526
|
}
|
|
10170
10527
|
}
|
|
10171
|
-
const readmePath =
|
|
10528
|
+
const readmePath = join5(this.paths.defaultsDir, DEFAULTS_README_FILE);
|
|
10172
10529
|
const readmeContent = buildDefaultsReadmeContent();
|
|
10173
10530
|
try {
|
|
10174
10531
|
const existing = readFileIfExists(readmePath);
|
|
@@ -10465,8 +10822,8 @@ ${report}`;
|
|
|
10465
10822
|
|
|
10466
10823
|
// lib/commands/export.ts
|
|
10467
10824
|
import * as fs2 from "fs/promises";
|
|
10468
|
-
import { existsSync as
|
|
10469
|
-
import { dirname as dirname3, isAbsolute, join as
|
|
10825
|
+
import { existsSync as existsSync6 } from "fs";
|
|
10826
|
+
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join6, resolve } from "path";
|
|
10470
10827
|
var ALL_TIERS = [1, 2, 3];
|
|
10471
10828
|
var TIER_NAMES = {
|
|
10472
10829
|
1: "Tier 1 \u2014 Capture",
|
|
@@ -10577,9 +10934,9 @@ function parseTiers(raw) {
|
|
|
10577
10934
|
}
|
|
10578
10935
|
return result;
|
|
10579
10936
|
}
|
|
10580
|
-
function resolveDefaultOutputPath(sessionId,
|
|
10937
|
+
function resolveDefaultOutputPath(sessionId, cwd2) {
|
|
10581
10938
|
const short = (sessionId || "session").slice(0, 8);
|
|
10582
|
-
return
|
|
10939
|
+
return join6(cwd2, ".opencode", `acp-export-${short}.md`);
|
|
10583
10940
|
}
|
|
10584
10941
|
function formatTokens2(n) {
|
|
10585
10942
|
if (!Number.isFinite(n) || n <= 0) return "0";
|
|
@@ -10706,15 +11063,15 @@ async function handleExportCommand(ctx, args) {
|
|
|
10706
11063
|
await sendExportNotice(client, sessionId, ctx, markdown);
|
|
10707
11064
|
return;
|
|
10708
11065
|
}
|
|
10709
|
-
const
|
|
10710
|
-
const targetPath = options.outputPath !== "" ?
|
|
11066
|
+
const cwd2 = ctx.workingDirectory || process.cwd();
|
|
11067
|
+
const targetPath = options.outputPath !== "" ? isAbsolute2(options.outputPath) ? options.outputPath : resolve(cwd2, options.outputPath) : resolveDefaultOutputPath(sessionId, cwd2);
|
|
10711
11068
|
try {
|
|
10712
11069
|
const dir = dirname3(targetPath);
|
|
10713
|
-
if (!
|
|
11070
|
+
if (!existsSync6(dir)) {
|
|
10714
11071
|
await fs2.mkdir(dir, { recursive: true });
|
|
10715
11072
|
}
|
|
10716
11073
|
const flag = options.append ? "a" : "w";
|
|
10717
|
-
if (options.append &&
|
|
11074
|
+
if (options.append && existsSync6(targetPath)) {
|
|
10718
11075
|
await fs2.appendFile(targetPath, `
|
|
10719
11076
|
|
|
10720
11077
|
---
|
|
@@ -11370,6 +11727,24 @@ function createChatMessageTransformHandler(client, registry4, logger, config, pr
|
|
|
11370
11727
|
return;
|
|
11371
11728
|
}
|
|
11372
11729
|
stripHallucinations(output.messages);
|
|
11730
|
+
const dropReasoningModel = lastUserMessage?.info?.model;
|
|
11731
|
+
const reasoningConfig = applyCompressOverrides(
|
|
11732
|
+
config,
|
|
11733
|
+
dropReasoningModel?.providerID ?? state.modelProviderID,
|
|
11734
|
+
dropReasoningModel?.modelID ?? state.modelID
|
|
11735
|
+
).compress.reasoning;
|
|
11736
|
+
if (reasoningConfig?.drop !== false) {
|
|
11737
|
+
const droppedReasoning = dropCompressReasoning(
|
|
11738
|
+
output.messages,
|
|
11739
|
+
reasoningConfig?.threshold ?? DEFAULT_COMPRESS_REASONING.threshold
|
|
11740
|
+
);
|
|
11741
|
+
if (droppedReasoning > 0) {
|
|
11742
|
+
logger.debug("compress.reasoning: dropped oversized reasoning parts", {
|
|
11743
|
+
dropped: droppedReasoning,
|
|
11744
|
+
threshold: reasoningConfig?.threshold ?? DEFAULT_COMPRESS_REASONING.threshold
|
|
11745
|
+
});
|
|
11746
|
+
}
|
|
11747
|
+
}
|
|
11373
11748
|
ensureBuiltinFiltersRegistered();
|
|
11374
11749
|
applyMessageFilters(output.messages, config.messageFilters, logger, {
|
|
11375
11750
|
sessionId: state.sessionId ?? "",
|
|
@@ -11639,7 +12014,7 @@ function findBiliProxyProviders(provider) {
|
|
|
11639
12014
|
|
|
11640
12015
|
// lib/update.ts
|
|
11641
12016
|
import { readFile as readFile2, rm } from "fs/promises";
|
|
11642
|
-
import { basename, dirname as dirname4, join as
|
|
12017
|
+
import { basename, dirname as dirname4, join as join7 } from "path";
|
|
11643
12018
|
import { fileURLToPath } from "url";
|
|
11644
12019
|
var PACKAGE_NAME = "opencode-acp";
|
|
11645
12020
|
function startAutoUpdate(ctx, enabled, logger) {
|
|
@@ -11686,7 +12061,7 @@ async function checkAutoUpdate(signal, logger) {
|
|
|
11686
12061
|
logger?.info("Auto-update skipped: package dir not found");
|
|
11687
12062
|
return { updated: false };
|
|
11688
12063
|
}
|
|
11689
|
-
const pkg = await readPackageJson(
|
|
12064
|
+
const pkg = await readPackageJson(join7(packageDir, "package.json"));
|
|
11690
12065
|
if (!pkg?.name || !pkg.version) {
|
|
11691
12066
|
logger?.info("Auto-update skipped: package.json unreadable", { packageDir });
|
|
11692
12067
|
return { updated: false };
|
|
@@ -11727,7 +12102,7 @@ async function checkAutoUpdate(signal, logger) {
|
|
|
11727
12102
|
async function findPackageDir(name) {
|
|
11728
12103
|
let dir = dirname4(fileURLToPath(import.meta.url));
|
|
11729
12104
|
for (; ; ) {
|
|
11730
|
-
const pkg = await readPackageJson(
|
|
12105
|
+
const pkg = await readPackageJson(join7(dir, "package.json"));
|
|
11731
12106
|
if (pkg?.name === name) return dir;
|
|
11732
12107
|
const parent = dirname4(dir);
|
|
11733
12108
|
if (parent === dir) return void 0;
|
|
@@ -11739,7 +12114,7 @@ async function updateTarget(packageDir, name) {
|
|
|
11739
12114
|
const nodeModulesDir = basename(packageParent).startsWith("@") ? dirname4(packageParent) : packageParent;
|
|
11740
12115
|
if (basename(nodeModulesDir) !== "node_modules") return void 0;
|
|
11741
12116
|
const wrapperDir = dirname4(nodeModulesDir);
|
|
11742
|
-
const wrapperPkg = await readPackageJson(
|
|
12117
|
+
const wrapperPkg = await readPackageJson(join7(wrapperDir, "package.json"));
|
|
11743
12118
|
const spec = wrapperSpec(wrapperDir, name) ?? wrapperPkg?.dependencies?.[name];
|
|
11744
12119
|
if (!spec || !isAutoUpdatableSpec(spec)) return void 0;
|
|
11745
12120
|
return { removeDir: wrapperDir, spec };
|
|
@@ -11851,14 +12226,14 @@ var server = (async (ctx) => {
|
|
|
11851
12226
|
}
|
|
11852
12227
|
const logger = new Logger(config.debug, config.debug ? "debug" : config.logLevel);
|
|
11853
12228
|
logger.info("ACP plugin initialized", {
|
|
11854
|
-
version: true ? "1.
|
|
12229
|
+
version: true ? "1.15.0-pr.376.118" : "dev",
|
|
11855
12230
|
workspace: ctx.directory,
|
|
11856
12231
|
logLevel: logger.level,
|
|
11857
12232
|
debug: config.debug,
|
|
11858
12233
|
autoUpdate: config.autoUpdate,
|
|
11859
12234
|
secureMode: isSecureMode()
|
|
11860
12235
|
});
|
|
11861
|
-
const registry4 = new SessionStateRegistry(logger);
|
|
12236
|
+
const registry4 = new SessionStateRegistry(logger, ctx.directory);
|
|
11862
12237
|
const prompts = new PromptStore(logger, ctx.directory, config.experimental.customPrompts);
|
|
11863
12238
|
const hostPermissions = {
|
|
11864
12239
|
global: void 0,
|