opencode-acp 1.15.0-pr.376.118 → 1.15.0-pr.378.113
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +67 -314
- package/dist/index.js.map +1 -1
- package/dist/lib/config-validation.d.ts.map +1 -1
- package/dist/lib/config.d.ts +0 -7
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/state/persistence.d.ts +3 -14
- package/dist/lib/state/persistence.d.ts.map +1 -1
- package/dist/lib/state/state.d.ts +2 -3
- package/dist/lib/state/state.d.ts.map +1 -1
- package/dist/lib/state/types.d.ts +0 -6
- package/dist/lib/state/types.d.ts.map +1 -1
- package/dist/lib/state/utils.d.ts +0 -1
- package/dist/lib/state/utils.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/lib/state/fork-transfer.d.ts +0 -42
- package/dist/lib/state/fork-transfer.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -869,7 +869,6 @@ var VALID_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
869
869
|
"autoUpdate",
|
|
870
870
|
"debug",
|
|
871
871
|
"logLevel",
|
|
872
|
-
"storagePath",
|
|
873
872
|
"showUpdateToasts",
|
|
874
873
|
"allowSubAgents",
|
|
875
874
|
"pruneNotification",
|
|
@@ -960,9 +959,6 @@ function validateConfigTypes(config) {
|
|
|
960
959
|
if (config.debug !== void 0 && typeof config.debug !== "boolean") {
|
|
961
960
|
errors.push({ key: "debug", expected: "boolean", actual: typeof config.debug });
|
|
962
961
|
}
|
|
963
|
-
if (config.storagePath !== void 0 && typeof config.storagePath !== "string") {
|
|
964
|
-
errors.push({ key: "storagePath", expected: "string", actual: typeof config.storagePath });
|
|
965
|
-
}
|
|
966
962
|
if (config.allowSubAgents !== void 0 && typeof config.allowSubAgents !== "boolean") {
|
|
967
963
|
errors.push({ key: "allowSubAgents", expected: "boolean", actual: typeof config.allowSubAgents });
|
|
968
964
|
}
|
|
@@ -1999,7 +1995,6 @@ function mergeLayer(config, data) {
|
|
|
1999
1995
|
autoUpdate: data.autoUpdate ?? config.autoUpdate,
|
|
2000
1996
|
debug: data.debug ?? config.debug,
|
|
2001
1997
|
logLevel: data.logLevel ?? config.logLevel,
|
|
2002
|
-
storagePath: data.storagePath ?? config.storagePath,
|
|
2003
1998
|
allowSubAgents: data.allowSubAgents ?? data.experimental?.allowSubAgents ?? config.allowSubAgents,
|
|
2004
1999
|
pruneNotification: data.pruneNotification ?? config.pruneNotification,
|
|
2005
2000
|
pruneNotificationType: data.pruneNotificationType ?? config.pruneNotificationType,
|
|
@@ -2354,7 +2349,7 @@ Each entry needs a topic \u2014 either its own or the top-level fallback.`;
|
|
|
2354
2349
|
import * as fs from "fs/promises";
|
|
2355
2350
|
import { existsSync as existsSync2 } from "fs";
|
|
2356
2351
|
import { homedir as homedir2 } from "os";
|
|
2357
|
-
import {
|
|
2352
|
+
import { join as join2 } from "path";
|
|
2358
2353
|
|
|
2359
2354
|
// lib/state/utils.ts
|
|
2360
2355
|
var isMessageCompacted = (state, msg) => {
|
|
@@ -2390,12 +2385,12 @@ function serializePruneMessagesState(messagesState) {
|
|
|
2390
2385
|
markedForCleanup: Array.from(messagesState.markedForCleanup)
|
|
2391
2386
|
};
|
|
2392
2387
|
}
|
|
2393
|
-
async function
|
|
2388
|
+
async function isSubAgentSession(client, sessionID) {
|
|
2394
2389
|
try {
|
|
2395
2390
|
const result = await client.session.get({ path: { id: sessionID } });
|
|
2396
|
-
return result.data?.parentID
|
|
2391
|
+
return !!result.data?.parentID;
|
|
2397
2392
|
} catch (error) {
|
|
2398
|
-
return
|
|
2393
|
+
return false;
|
|
2399
2394
|
}
|
|
2400
2395
|
}
|
|
2401
2396
|
function findLastCompactionTimestamp(messages) {
|
|
@@ -2637,7 +2632,7 @@ function resetOnCompaction(state) {
|
|
|
2637
2632
|
}
|
|
2638
2633
|
|
|
2639
2634
|
// lib/state/persistence.ts
|
|
2640
|
-
function
|
|
2635
|
+
function getStorageDir() {
|
|
2641
2636
|
return join2(
|
|
2642
2637
|
process.env.XDG_DATA_HOME || join2(homedir2(), ".local", "share"),
|
|
2643
2638
|
"opencode",
|
|
@@ -2646,33 +2641,14 @@ function getDefaultStorageDir() {
|
|
|
2646
2641
|
"acp"
|
|
2647
2642
|
);
|
|
2648
2643
|
}
|
|
2649
|
-
function
|
|
2650
|
-
|
|
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();
|
|
2667
|
-
}
|
|
2668
|
-
function getSessionFilePath(sessionId, storageDir) {
|
|
2669
|
-
return join2(getStorageDir(storageDir), `${sessionId}.json`);
|
|
2644
|
+
function getSessionFilePath(sessionId) {
|
|
2645
|
+
return join2(getStorageDir(), `${sessionId}.json`);
|
|
2670
2646
|
}
|
|
2671
|
-
async function writePersistedSessionState(sessionId, state, logger
|
|
2672
|
-
const filePath = getSessionFilePath(sessionId
|
|
2673
|
-
const
|
|
2674
|
-
if (!existsSync2(
|
|
2675
|
-
await fs.mkdir(
|
|
2647
|
+
async function writePersistedSessionState(sessionId, state, logger) {
|
|
2648
|
+
const filePath = getSessionFilePath(sessionId);
|
|
2649
|
+
const storageDir = getStorageDir();
|
|
2650
|
+
if (!existsSync2(storageDir)) {
|
|
2651
|
+
await fs.mkdir(storageDir, { recursive: true });
|
|
2676
2652
|
}
|
|
2677
2653
|
const content = JSON.stringify(state, null, 2);
|
|
2678
2654
|
await fs.writeFile(filePath, content, "utf-8");
|
|
@@ -2714,11 +2690,11 @@ async function saveSessionState(sessionState, logger, sessionName) {
|
|
|
2714
2690
|
modelProviderID: sessionState.modelProviderID,
|
|
2715
2691
|
modelID: sessionState.modelID
|
|
2716
2692
|
};
|
|
2717
|
-
await writePersistedSessionState(sessionState.sessionId, state, logger
|
|
2693
|
+
await writePersistedSessionState(sessionState.sessionId, state, logger);
|
|
2718
2694
|
}
|
|
2719
|
-
async function loadSessionState(sessionId, logger
|
|
2695
|
+
async function loadSessionState(sessionId, logger) {
|
|
2720
2696
|
try {
|
|
2721
|
-
const filePath = getSessionFilePath(sessionId
|
|
2697
|
+
const filePath = getSessionFilePath(sessionId);
|
|
2722
2698
|
if (!existsSync2(filePath)) {
|
|
2723
2699
|
return null;
|
|
2724
2700
|
}
|
|
@@ -2794,11 +2770,6 @@ async function loadSessionState(sessionId, logger, storageDir) {
|
|
|
2794
2770
|
}
|
|
2795
2771
|
}
|
|
2796
2772
|
|
|
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
|
-
|
|
2802
2773
|
// lib/message-ids.ts
|
|
2803
2774
|
var MESSAGE_REF_REGEX = /^m(\d{4,5})$/;
|
|
2804
2775
|
var BLOCK_REF_REGEX = /^b([1-9]\d*)$/;
|
|
@@ -4456,205 +4427,6 @@ function rebuildCompressionState(state, messages, config, logger) {
|
|
|
4456
4427
|
return rebuilt;
|
|
4457
4428
|
}
|
|
4458
4429
|
|
|
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
|
-
|
|
4658
4430
|
// lib/state/state.ts
|
|
4659
4431
|
async function updatePerTurnState(state, logger, messages) {
|
|
4660
4432
|
const lastCompactionTimestamp = findLastCompactionTimestamp(messages);
|
|
@@ -4674,12 +4446,10 @@ async function updatePerTurnState(state, logger, messages) {
|
|
|
4674
4446
|
}
|
|
4675
4447
|
var REGISTRY_SOFT_CAP = 32;
|
|
4676
4448
|
var SessionStateRegistry = class {
|
|
4677
|
-
constructor(logger
|
|
4449
|
+
constructor(logger) {
|
|
4678
4450
|
this.logger = logger;
|
|
4679
|
-
this.projectDir = projectDir;
|
|
4680
4451
|
}
|
|
4681
4452
|
logger;
|
|
4682
|
-
projectDir;
|
|
4683
4453
|
states = /* @__PURE__ */ new Map();
|
|
4684
4454
|
compressionTiming = {
|
|
4685
4455
|
startsByCallId: /* @__PURE__ */ new Map(),
|
|
@@ -4732,8 +4502,7 @@ var SessionStateRegistry = class {
|
|
|
4732
4502
|
sessionId,
|
|
4733
4503
|
this.logger,
|
|
4734
4504
|
messages,
|
|
4735
|
-
config
|
|
4736
|
-
this.projectDir
|
|
4505
|
+
config
|
|
4737
4506
|
);
|
|
4738
4507
|
} catch (err) {
|
|
4739
4508
|
this.logger.error("Failed to initialize session state", {
|
|
@@ -4797,7 +4566,6 @@ function createSessionState() {
|
|
|
4797
4566
|
modelProviderID: void 0,
|
|
4798
4567
|
modelID: void 0,
|
|
4799
4568
|
systemPromptTokens: void 0,
|
|
4800
|
-
storageDir: void 0,
|
|
4801
4569
|
qualityGateRetryPending: false
|
|
4802
4570
|
};
|
|
4803
4571
|
}
|
|
@@ -4839,39 +4607,24 @@ function resetSessionState(state) {
|
|
|
4839
4607
|
state.modelProviderID = void 0;
|
|
4840
4608
|
state.modelID = void 0;
|
|
4841
4609
|
state.systemPromptTokens = void 0;
|
|
4842
|
-
state.storageDir = void 0;
|
|
4843
4610
|
state.qualityGateRetryPending = false;
|
|
4844
4611
|
}
|
|
4845
|
-
async function ensureSessionInitialized(client, state, sessionId, logger, messages, config
|
|
4612
|
+
async function ensureSessionInitialized(client, state, sessionId, logger, messages, config) {
|
|
4846
4613
|
if (state.sessionId === sessionId) {
|
|
4847
4614
|
return;
|
|
4848
4615
|
}
|
|
4849
4616
|
resetSessionState(state);
|
|
4850
4617
|
state.sessionId = sessionId;
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
state.isSubAgent = parentId !== null;
|
|
4618
|
+
const isSubAgent = await isSubAgentSession(client, sessionId);
|
|
4619
|
+
state.isSubAgent = isSubAgent;
|
|
4854
4620
|
state.lastCompaction = findLastCompactionTimestamp(messages);
|
|
4855
4621
|
state.currentTurn = countTurns(state, messages);
|
|
4856
4622
|
state.nudges.turnNudgeAnchors = collectTurnNudgeAnchors(messages);
|
|
4857
|
-
const persisted = await loadSessionState(sessionId, logger
|
|
4623
|
+
const persisted = await loadSessionState(sessionId, logger);
|
|
4858
4624
|
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
|
-
}
|
|
4866
4625
|
if (config) {
|
|
4867
|
-
|
|
4868
|
-
if (
|
|
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) {
|
|
4626
|
+
const rebuilt = rebuildCompressionState(state, messages, config, logger);
|
|
4627
|
+
if (rebuilt > 0) {
|
|
4875
4628
|
await saveSessionState(state, logger);
|
|
4876
4629
|
}
|
|
4877
4630
|
}
|
|
@@ -9732,10 +9485,10 @@ function hideFailedCompressCalls(messages) {
|
|
|
9732
9485
|
|
|
9733
9486
|
// lib/logger.ts
|
|
9734
9487
|
import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
9735
|
-
import { join as
|
|
9736
|
-
import { existsSync as
|
|
9488
|
+
import { join as join3 } from "path";
|
|
9489
|
+
import { existsSync as existsSync3 } from "fs";
|
|
9737
9490
|
import { homedir as homedir3 } from "os";
|
|
9738
|
-
var LOG_VERSION = true ? "1.15.0-pr.
|
|
9491
|
+
var LOG_VERSION = true ? "1.15.0-pr.378.113" : "dev";
|
|
9739
9492
|
var LEVEL_RANK = {
|
|
9740
9493
|
debug: 10,
|
|
9741
9494
|
info: 20,
|
|
@@ -9755,8 +9508,8 @@ var Logger = class {
|
|
|
9755
9508
|
constructor(enabled, level) {
|
|
9756
9509
|
const resolved = level !== void 0 && LEVEL_RANK[level] !== void 0 ? level : void 0;
|
|
9757
9510
|
this.level = resolved ?? (enabled ? "debug" : "warn");
|
|
9758
|
-
const configHome = process.env.XDG_CONFIG_HOME ||
|
|
9759
|
-
this.logDir =
|
|
9511
|
+
const configHome = process.env.XDG_CONFIG_HOME || join3(homedir3(), ".config");
|
|
9512
|
+
this.logDir = join3(configHome, "opencode", "logs", "acp");
|
|
9760
9513
|
}
|
|
9761
9514
|
/** Back-compat view of the old flag: true only at full debug verbosity. */
|
|
9762
9515
|
get enabled() {
|
|
@@ -9766,7 +9519,7 @@ var Logger = class {
|
|
|
9766
9519
|
return LEVEL_RANK[level] >= LEVEL_RANK[this.level];
|
|
9767
9520
|
}
|
|
9768
9521
|
async ensureLogDir() {
|
|
9769
|
-
if (!
|
|
9522
|
+
if (!existsSync3(this.logDir)) {
|
|
9770
9523
|
await mkdir2(this.logDir, { recursive: true });
|
|
9771
9524
|
}
|
|
9772
9525
|
}
|
|
@@ -9818,11 +9571,11 @@ var Logger = class {
|
|
|
9818
9571
|
const dataStr = this.formatData(data);
|
|
9819
9572
|
const logLine = `${timestamp} ${level.padEnd(5)} ${component}: ${message}${dataStr ? " | " + dataStr : ""} | v=${LOG_VERSION}
|
|
9820
9573
|
`;
|
|
9821
|
-
const dailyLogDir =
|
|
9822
|
-
if (!
|
|
9574
|
+
const dailyLogDir = join3(this.logDir, "daily");
|
|
9575
|
+
if (!existsSync3(dailyLogDir)) {
|
|
9823
9576
|
await mkdir2(dailyLogDir, { recursive: true });
|
|
9824
9577
|
}
|
|
9825
|
-
const logFile =
|
|
9578
|
+
const logFile = join3(dailyLogDir, `${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.log`);
|
|
9826
9579
|
await writeFile2(logFile, logLine, { flag: "a" });
|
|
9827
9580
|
} catch (error) {
|
|
9828
9581
|
}
|
|
@@ -9933,18 +9686,18 @@ var Logger = class {
|
|
|
9933
9686
|
async saveContext(sessionId, messages) {
|
|
9934
9687
|
if (this.level !== "debug") return;
|
|
9935
9688
|
try {
|
|
9936
|
-
const contextDir =
|
|
9937
|
-
if (!
|
|
9689
|
+
const contextDir = join3(this.logDir, "context", sessionId);
|
|
9690
|
+
if (!existsSync3(contextDir)) {
|
|
9938
9691
|
await mkdir2(contextDir, { recursive: true });
|
|
9939
9692
|
}
|
|
9940
9693
|
const minimized = this.minimizeForDebug(messages).filter(
|
|
9941
9694
|
(msg) => msg.parts && msg.parts.length > 0
|
|
9942
9695
|
);
|
|
9943
9696
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
9944
|
-
const contextFile =
|
|
9697
|
+
const contextFile = join3(contextDir, `${timestamp}.json`);
|
|
9945
9698
|
await writeFile2(contextFile, JSON.stringify(minimized, null, 2));
|
|
9946
|
-
const versionFile =
|
|
9947
|
-
if (!
|
|
9699
|
+
const versionFile = join3(contextDir, "_version");
|
|
9700
|
+
if (!existsSync3(versionFile)) {
|
|
9948
9701
|
await writeFile2(versionFile, LOG_VERSION);
|
|
9949
9702
|
}
|
|
9950
9703
|
} catch (error) {
|
|
@@ -9953,8 +9706,8 @@ var Logger = class {
|
|
|
9953
9706
|
};
|
|
9954
9707
|
|
|
9955
9708
|
// lib/prompts/store.ts
|
|
9956
|
-
import { existsSync as
|
|
9957
|
-
import { join as
|
|
9709
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, statSync as statSync2 } from "fs";
|
|
9710
|
+
import { join as join4, dirname as dirname2 } from "path";
|
|
9958
9711
|
import { homedir as homedir4 } from "os";
|
|
9959
9712
|
|
|
9960
9713
|
// lib/prompts/system.ts
|
|
@@ -10284,8 +10037,8 @@ function createBundledRuntimePrompts() {
|
|
|
10284
10037
|
function findOpencodeDir2(startDir) {
|
|
10285
10038
|
let current = startDir;
|
|
10286
10039
|
while (current !== "/") {
|
|
10287
|
-
const candidate =
|
|
10288
|
-
if (
|
|
10040
|
+
const candidate = join4(current, ".opencode");
|
|
10041
|
+
if (existsSync4(candidate)) {
|
|
10289
10042
|
try {
|
|
10290
10043
|
if (statSync2(candidate).isDirectory()) {
|
|
10291
10044
|
return candidate;
|
|
@@ -10302,13 +10055,13 @@ function findOpencodeDir2(startDir) {
|
|
|
10302
10055
|
return null;
|
|
10303
10056
|
}
|
|
10304
10057
|
function resolvePromptPaths(workingDirectory) {
|
|
10305
|
-
const configHome = process.env.XDG_CONFIG_HOME ||
|
|
10306
|
-
const globalRoot =
|
|
10307
|
-
const defaultsDir =
|
|
10308
|
-
const globalOverridesDir =
|
|
10309
|
-
const configDirOverridesDir = process.env.OPENCODE_CONFIG_DIR ?
|
|
10058
|
+
const configHome = process.env.XDG_CONFIG_HOME || join4(homedir4(), ".config");
|
|
10059
|
+
const globalRoot = join4(configHome, "opencode", "acp-prompts");
|
|
10060
|
+
const defaultsDir = join4(globalRoot, "defaults");
|
|
10061
|
+
const globalOverridesDir = join4(globalRoot, "overrides");
|
|
10062
|
+
const configDirOverridesDir = process.env.OPENCODE_CONFIG_DIR ? join4(process.env.OPENCODE_CONFIG_DIR, "acp-prompts", "overrides") : null;
|
|
10310
10063
|
const opencodeDir = findOpencodeDir2(workingDirectory);
|
|
10311
|
-
const projectOverridesDir = opencodeDir ?
|
|
10064
|
+
const projectOverridesDir = opencodeDir ? join4(opencodeDir, "acp-prompts", "overrides") : null;
|
|
10312
10065
|
return {
|
|
10313
10066
|
defaultsDir,
|
|
10314
10067
|
globalOverridesDir,
|
|
@@ -10408,7 +10161,7 @@ function buildDefaultsReadmeContent() {
|
|
|
10408
10161
|
`;
|
|
10409
10162
|
}
|
|
10410
10163
|
function readFileIfExists(filePath) {
|
|
10411
|
-
if (!
|
|
10164
|
+
if (!existsSync4(filePath)) {
|
|
10412
10165
|
return null;
|
|
10413
10166
|
}
|
|
10414
10167
|
try {
|
|
@@ -10479,16 +10232,16 @@ var PromptStore = class {
|
|
|
10479
10232
|
const candidates = [];
|
|
10480
10233
|
if (this.paths.projectOverridesDir) {
|
|
10481
10234
|
candidates.push({
|
|
10482
|
-
path:
|
|
10235
|
+
path: join4(this.paths.projectOverridesDir, fileName)
|
|
10483
10236
|
});
|
|
10484
10237
|
}
|
|
10485
10238
|
if (this.paths.configDirOverridesDir) {
|
|
10486
10239
|
candidates.push({
|
|
10487
|
-
path:
|
|
10240
|
+
path: join4(this.paths.configDirOverridesDir, fileName)
|
|
10488
10241
|
});
|
|
10489
10242
|
}
|
|
10490
10243
|
candidates.push({
|
|
10491
|
-
path:
|
|
10244
|
+
path: join4(this.paths.globalOverridesDir, fileName)
|
|
10492
10245
|
});
|
|
10493
10246
|
return candidates;
|
|
10494
10247
|
}
|
|
@@ -10511,7 +10264,7 @@ var PromptStore = class {
|
|
|
10511
10264
|
const managedContent = buildDefaultPromptFileContent(
|
|
10512
10265
|
bundledEditable || BUNDLED_EDITABLE_PROMPTS[definition.runtimeField]
|
|
10513
10266
|
);
|
|
10514
|
-
const filePath =
|
|
10267
|
+
const filePath = join4(this.paths.defaultsDir, definition.fileName);
|
|
10515
10268
|
try {
|
|
10516
10269
|
const existing = readFileIfExists(filePath);
|
|
10517
10270
|
if (existing === managedContent) {
|
|
@@ -10525,7 +10278,7 @@ var PromptStore = class {
|
|
|
10525
10278
|
});
|
|
10526
10279
|
}
|
|
10527
10280
|
}
|
|
10528
|
-
const readmePath =
|
|
10281
|
+
const readmePath = join4(this.paths.defaultsDir, DEFAULTS_README_FILE);
|
|
10529
10282
|
const readmeContent = buildDefaultsReadmeContent();
|
|
10530
10283
|
try {
|
|
10531
10284
|
const existing = readFileIfExists(readmePath);
|
|
@@ -10822,8 +10575,8 @@ ${report}`;
|
|
|
10822
10575
|
|
|
10823
10576
|
// lib/commands/export.ts
|
|
10824
10577
|
import * as fs2 from "fs/promises";
|
|
10825
|
-
import { existsSync as
|
|
10826
|
-
import { dirname as dirname3, isAbsolute
|
|
10578
|
+
import { existsSync as existsSync5 } from "fs";
|
|
10579
|
+
import { dirname as dirname3, isAbsolute, join as join5, resolve } from "path";
|
|
10827
10580
|
var ALL_TIERS = [1, 2, 3];
|
|
10828
10581
|
var TIER_NAMES = {
|
|
10829
10582
|
1: "Tier 1 \u2014 Capture",
|
|
@@ -10934,9 +10687,9 @@ function parseTiers(raw) {
|
|
|
10934
10687
|
}
|
|
10935
10688
|
return result;
|
|
10936
10689
|
}
|
|
10937
|
-
function resolveDefaultOutputPath(sessionId,
|
|
10690
|
+
function resolveDefaultOutputPath(sessionId, cwd) {
|
|
10938
10691
|
const short = (sessionId || "session").slice(0, 8);
|
|
10939
|
-
return
|
|
10692
|
+
return join5(cwd, ".opencode", `acp-export-${short}.md`);
|
|
10940
10693
|
}
|
|
10941
10694
|
function formatTokens2(n) {
|
|
10942
10695
|
if (!Number.isFinite(n) || n <= 0) return "0";
|
|
@@ -11063,15 +10816,15 @@ async function handleExportCommand(ctx, args) {
|
|
|
11063
10816
|
await sendExportNotice(client, sessionId, ctx, markdown);
|
|
11064
10817
|
return;
|
|
11065
10818
|
}
|
|
11066
|
-
const
|
|
11067
|
-
const targetPath = options.outputPath !== "" ?
|
|
10819
|
+
const cwd = ctx.workingDirectory || process.cwd();
|
|
10820
|
+
const targetPath = options.outputPath !== "" ? isAbsolute(options.outputPath) ? options.outputPath : resolve(cwd, options.outputPath) : resolveDefaultOutputPath(sessionId, cwd);
|
|
11068
10821
|
try {
|
|
11069
10822
|
const dir = dirname3(targetPath);
|
|
11070
|
-
if (!
|
|
10823
|
+
if (!existsSync5(dir)) {
|
|
11071
10824
|
await fs2.mkdir(dir, { recursive: true });
|
|
11072
10825
|
}
|
|
11073
10826
|
const flag = options.append ? "a" : "w";
|
|
11074
|
-
if (options.append &&
|
|
10827
|
+
if (options.append && existsSync5(targetPath)) {
|
|
11075
10828
|
await fs2.appendFile(targetPath, `
|
|
11076
10829
|
|
|
11077
10830
|
---
|
|
@@ -12014,7 +11767,7 @@ function findBiliProxyProviders(provider) {
|
|
|
12014
11767
|
|
|
12015
11768
|
// lib/update.ts
|
|
12016
11769
|
import { readFile as readFile2, rm } from "fs/promises";
|
|
12017
|
-
import { basename, dirname as dirname4, join as
|
|
11770
|
+
import { basename, dirname as dirname4, join as join6 } from "path";
|
|
12018
11771
|
import { fileURLToPath } from "url";
|
|
12019
11772
|
var PACKAGE_NAME = "opencode-acp";
|
|
12020
11773
|
function startAutoUpdate(ctx, enabled, logger) {
|
|
@@ -12061,7 +11814,7 @@ async function checkAutoUpdate(signal, logger) {
|
|
|
12061
11814
|
logger?.info("Auto-update skipped: package dir not found");
|
|
12062
11815
|
return { updated: false };
|
|
12063
11816
|
}
|
|
12064
|
-
const pkg = await readPackageJson(
|
|
11817
|
+
const pkg = await readPackageJson(join6(packageDir, "package.json"));
|
|
12065
11818
|
if (!pkg?.name || !pkg.version) {
|
|
12066
11819
|
logger?.info("Auto-update skipped: package.json unreadable", { packageDir });
|
|
12067
11820
|
return { updated: false };
|
|
@@ -12102,7 +11855,7 @@ async function checkAutoUpdate(signal, logger) {
|
|
|
12102
11855
|
async function findPackageDir(name) {
|
|
12103
11856
|
let dir = dirname4(fileURLToPath(import.meta.url));
|
|
12104
11857
|
for (; ; ) {
|
|
12105
|
-
const pkg = await readPackageJson(
|
|
11858
|
+
const pkg = await readPackageJson(join6(dir, "package.json"));
|
|
12106
11859
|
if (pkg?.name === name) return dir;
|
|
12107
11860
|
const parent = dirname4(dir);
|
|
12108
11861
|
if (parent === dir) return void 0;
|
|
@@ -12114,7 +11867,7 @@ async function updateTarget(packageDir, name) {
|
|
|
12114
11867
|
const nodeModulesDir = basename(packageParent).startsWith("@") ? dirname4(packageParent) : packageParent;
|
|
12115
11868
|
if (basename(nodeModulesDir) !== "node_modules") return void 0;
|
|
12116
11869
|
const wrapperDir = dirname4(nodeModulesDir);
|
|
12117
|
-
const wrapperPkg = await readPackageJson(
|
|
11870
|
+
const wrapperPkg = await readPackageJson(join6(wrapperDir, "package.json"));
|
|
12118
11871
|
const spec = wrapperSpec(wrapperDir, name) ?? wrapperPkg?.dependencies?.[name];
|
|
12119
11872
|
if (!spec || !isAutoUpdatableSpec(spec)) return void 0;
|
|
12120
11873
|
return { removeDir: wrapperDir, spec };
|
|
@@ -12226,14 +11979,14 @@ var server = (async (ctx) => {
|
|
|
12226
11979
|
}
|
|
12227
11980
|
const logger = new Logger(config.debug, config.debug ? "debug" : config.logLevel);
|
|
12228
11981
|
logger.info("ACP plugin initialized", {
|
|
12229
|
-
version: true ? "1.15.0-pr.
|
|
11982
|
+
version: true ? "1.15.0-pr.378.113" : "dev",
|
|
12230
11983
|
workspace: ctx.directory,
|
|
12231
11984
|
logLevel: logger.level,
|
|
12232
11985
|
debug: config.debug,
|
|
12233
11986
|
autoUpdate: config.autoUpdate,
|
|
12234
11987
|
secureMode: isSecureMode()
|
|
12235
11988
|
});
|
|
12236
|
-
const registry4 = new SessionStateRegistry(logger
|
|
11989
|
+
const registry4 = new SessionStateRegistry(logger);
|
|
12237
11990
|
const prompts = new PromptStore(logger, ctx.directory, config.experimental.customPrompts);
|
|
12238
11991
|
const hostPermissions = {
|
|
12239
11992
|
global: void 0,
|