@lexwdex-org/opencode-dcp 3.4.8 → 3.4.9
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.en.md +2 -2
- package/README.md +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +702 -348
- package/dist/index.js.map +1 -1
- package/dist/lib/commands/context.d.ts +2 -1
- package/dist/lib/commands/context.d.ts.map +1 -1
- package/dist/lib/commands/decompress.d.ts +2 -1
- package/dist/lib/commands/decompress.d.ts.map +1 -1
- package/dist/lib/commands/help.d.ts +2 -1
- package/dist/lib/commands/help.d.ts.map +1 -1
- package/dist/lib/commands/manual.d.ts +2 -1
- package/dist/lib/commands/manual.d.ts.map +1 -1
- package/dist/lib/commands/recompress.d.ts +2 -1
- package/dist/lib/commands/recompress.d.ts.map +1 -1
- package/dist/lib/commands/stats.d.ts +2 -1
- package/dist/lib/commands/stats.d.ts.map +1 -1
- package/dist/lib/commands/sweep.d.ts +2 -1
- package/dist/lib/commands/sweep.d.ts.map +1 -1
- package/dist/lib/compress/external-content.d.ts +4 -0
- package/dist/lib/compress/external-content.d.ts.map +1 -0
- package/dist/lib/compress/external-inference.d.ts.map +1 -1
- package/dist/lib/compress/message.d.ts.map +1 -1
- package/dist/lib/compress/pipeline.d.ts +3 -2
- package/dist/lib/compress/pipeline.d.ts.map +1 -1
- package/dist/lib/compress/protected-content.d.ts +2 -1
- package/dist/lib/compress/protected-content.d.ts.map +1 -1
- package/dist/lib/compress/range.d.ts.map +1 -1
- package/dist/lib/compress/search.d.ts +2 -1
- package/dist/lib/compress/search.d.ts.map +1 -1
- package/dist/lib/compress/timing.d.ts +2 -0
- package/dist/lib/compress/timing.d.ts.map +1 -1
- package/dist/lib/compress/types.d.ts +4 -3
- package/dist/lib/compress/types.d.ts.map +1 -1
- package/dist/lib/compress-permission.d.ts.map +1 -1
- package/dist/lib/concurrency.d.ts +2 -0
- package/dist/lib/concurrency.d.ts.map +1 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/hooks.d.ts +6 -5
- package/dist/lib/hooks.d.ts.map +1 -1
- package/dist/lib/messages/inject/inject.d.ts.map +1 -1
- package/dist/lib/messages/inject/subagent-results.d.ts +2 -1
- package/dist/lib/messages/inject/subagent-results.d.ts.map +1 -1
- package/dist/lib/messages/inject/utils.d.ts +2 -2
- package/dist/lib/messages/inject/utils.d.ts.map +1 -1
- package/dist/lib/messages/utils.d.ts.map +1 -1
- package/dist/lib/opencode-client.d.ts +3 -0
- package/dist/lib/opencode-client.d.ts.map +1 -0
- package/dist/lib/prompts/context-limit-nudge.d.ts +1 -1
- package/dist/lib/prompts/context-limit-nudge.d.ts.map +1 -1
- package/dist/lib/prompts/iteration-nudge.d.ts +1 -1
- package/dist/lib/prompts/iteration-nudge.d.ts.map +1 -1
- package/dist/lib/prompts/store.d.ts +1 -0
- package/dist/lib/prompts/store.d.ts.map +1 -1
- package/dist/lib/prompts/system.d.ts +1 -1
- package/dist/lib/prompts/system.d.ts.map +1 -1
- package/dist/lib/prompts/turn-nudge.d.ts +1 -1
- package/dist/lib/prompts/turn-nudge.d.ts.map +1 -1
- package/dist/lib/state/index.d.ts +1 -0
- package/dist/lib/state/index.d.ts.map +1 -1
- package/dist/lib/state/persistence.d.ts.map +1 -1
- package/dist/lib/state/state.d.ts +5 -2
- package/dist/lib/state/state.d.ts.map +1 -1
- package/dist/lib/state/store.d.ts +37 -0
- package/dist/lib/state/store.d.ts.map +1 -0
- package/dist/lib/state/tool-cache.d.ts.map +1 -1
- package/dist/lib/state/types.d.ts +1 -1
- package/dist/lib/state/types.d.ts.map +1 -1
- package/dist/lib/state/utils.d.ts +4 -1
- package/dist/lib/state/utils.d.ts.map +1 -1
- package/dist/lib/strategies/deduplication.d.ts.map +1 -1
- package/dist/lib/token-utils.d.ts +0 -1
- package/dist/lib/token-utils.d.ts.map +1 -1
- package/dist/lib/ui/notification.d.ts +4 -3
- package/dist/lib/ui/notification.d.ts.map +1 -1
- package/dist/lib/update.d.ts +3 -9
- package/dist/lib/update.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/lib/auth.d.ts +0 -4
- package/dist/lib/auth.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -912,7 +912,6 @@ var VALID_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
912
912
|
"enabled",
|
|
913
913
|
"autoUpdate",
|
|
914
914
|
"debug",
|
|
915
|
-
"showUpdateToasts",
|
|
916
915
|
"pruneNotification",
|
|
917
916
|
"pruneNotificationType",
|
|
918
917
|
"turnProtection",
|
|
@@ -944,6 +943,11 @@ var VALID_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
944
943
|
"compress.protectTags",
|
|
945
944
|
"compress.protectUserMessages",
|
|
946
945
|
"compress.externalModel",
|
|
946
|
+
"compress.externalModel.url",
|
|
947
|
+
"compress.externalModel.model",
|
|
948
|
+
"compress.externalModel.apiKey",
|
|
949
|
+
"compress.externalModel.timeout",
|
|
950
|
+
"compress.externalModel.retries",
|
|
947
951
|
"strategies",
|
|
948
952
|
"strategies.deduplication",
|
|
949
953
|
"strategies.deduplication.enabled",
|
|
@@ -1259,6 +1263,12 @@ function validateConfigTypes(config) {
|
|
|
1259
1263
|
expected: "string",
|
|
1260
1264
|
actual: typeof compress.externalModel.url
|
|
1261
1265
|
});
|
|
1266
|
+
} else if (compress.externalModel.url.trim().length === 0) {
|
|
1267
|
+
errors.push({
|
|
1268
|
+
key: "compress.externalModel.url",
|
|
1269
|
+
expected: "non-empty string",
|
|
1270
|
+
actual: "empty string"
|
|
1271
|
+
});
|
|
1262
1272
|
}
|
|
1263
1273
|
if (typeof compress.externalModel.model !== "string") {
|
|
1264
1274
|
errors.push({
|
|
@@ -1266,6 +1276,33 @@ function validateConfigTypes(config) {
|
|
|
1266
1276
|
expected: "string",
|
|
1267
1277
|
actual: typeof compress.externalModel.model
|
|
1268
1278
|
});
|
|
1279
|
+
} else if (compress.externalModel.model.trim().length === 0) {
|
|
1280
|
+
errors.push({
|
|
1281
|
+
key: "compress.externalModel.model",
|
|
1282
|
+
expected: "non-empty string",
|
|
1283
|
+
actual: "empty string"
|
|
1284
|
+
});
|
|
1285
|
+
}
|
|
1286
|
+
if (compress.externalModel.apiKey !== void 0 && typeof compress.externalModel.apiKey !== "string") {
|
|
1287
|
+
errors.push({
|
|
1288
|
+
key: "compress.externalModel.apiKey",
|
|
1289
|
+
expected: "string",
|
|
1290
|
+
actual: typeof compress.externalModel.apiKey
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
if (compress.externalModel.timeout !== void 0 && (typeof compress.externalModel.timeout !== "number" || !Number.isFinite(compress.externalModel.timeout) || compress.externalModel.timeout <= 0)) {
|
|
1294
|
+
errors.push({
|
|
1295
|
+
key: "compress.externalModel.timeout",
|
|
1296
|
+
expected: "positive finite number",
|
|
1297
|
+
actual: JSON.stringify(compress.externalModel.timeout)
|
|
1298
|
+
});
|
|
1299
|
+
}
|
|
1300
|
+
if (compress.externalModel.retries !== void 0 && (!Number.isInteger(compress.externalModel.retries) || compress.externalModel.retries < 0)) {
|
|
1301
|
+
errors.push({
|
|
1302
|
+
key: "compress.externalModel.retries",
|
|
1303
|
+
expected: "non-negative integer",
|
|
1304
|
+
actual: JSON.stringify(compress.externalModel.retries)
|
|
1305
|
+
});
|
|
1269
1306
|
}
|
|
1270
1307
|
}
|
|
1271
1308
|
}
|
|
@@ -1746,6 +1783,8 @@ function isProtectedUserMessage(config, message) {
|
|
|
1746
1783
|
// lib/token-utils.ts
|
|
1747
1784
|
var anthropicCountTokens = _anthropicTokenizer.countTokens ?? _anthropicTokenizer.default?.countTokens;
|
|
1748
1785
|
function getCurrentTokenUsage(state, messages) {
|
|
1786
|
+
let reportedTokens = 0;
|
|
1787
|
+
let lastReportedIndex = -1;
|
|
1749
1788
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1750
1789
|
const msg = messages[i];
|
|
1751
1790
|
if (msg.info.role !== "assistant") {
|
|
@@ -1756,16 +1795,23 @@ function getCurrentTokenUsage(state, messages) {
|
|
|
1756
1795
|
continue;
|
|
1757
1796
|
}
|
|
1758
1797
|
if (state.lastCompaction > 0 && (msg.info.time.created < state.lastCompaction || msg.info.summary === true && msg.info.time.created === state.lastCompaction)) {
|
|
1759
|
-
|
|
1798
|
+
lastReportedIndex = i;
|
|
1799
|
+
break;
|
|
1760
1800
|
}
|
|
1761
1801
|
const input = assistantInfo.tokens?.input || 0;
|
|
1762
1802
|
const output = assistantInfo.tokens?.output || 0;
|
|
1763
1803
|
const reasoning = assistantInfo.tokens?.reasoning || 0;
|
|
1764
1804
|
const cacheRead = assistantInfo.tokens?.cache?.read || 0;
|
|
1765
1805
|
const cacheWrite = assistantInfo.tokens?.cache?.write || 0;
|
|
1766
|
-
|
|
1806
|
+
reportedTokens = input + output + reasoning + cacheRead + cacheWrite;
|
|
1807
|
+
lastReportedIndex = i;
|
|
1808
|
+
break;
|
|
1767
1809
|
}
|
|
1768
|
-
|
|
1810
|
+
let unreportedTokens = 0;
|
|
1811
|
+
for (let i = lastReportedIndex + 1; i < messages.length; i++) {
|
|
1812
|
+
unreportedTokens += countAllMessageTokens(messages[i]);
|
|
1813
|
+
}
|
|
1814
|
+
return reportedTokens + unreportedTokens;
|
|
1769
1815
|
}
|
|
1770
1816
|
function getCurrentParams(state, messages, logger) {
|
|
1771
1817
|
const userMsg = getLastUserMessage(messages);
|
|
@@ -1774,16 +1820,14 @@ function getCurrentParams(state, messages, logger) {
|
|
|
1774
1820
|
return {
|
|
1775
1821
|
providerId: void 0,
|
|
1776
1822
|
modelId: void 0,
|
|
1777
|
-
agent: void 0
|
|
1778
|
-
variant: void 0
|
|
1823
|
+
agent: void 0
|
|
1779
1824
|
};
|
|
1780
1825
|
}
|
|
1781
1826
|
const userInfo = userMsg.info;
|
|
1782
1827
|
const agent = userInfo.agent;
|
|
1783
1828
|
const providerId = userInfo.model.providerID;
|
|
1784
1829
|
const modelId = userInfo.model.modelID;
|
|
1785
|
-
|
|
1786
|
-
return { providerId, modelId, agent, variant };
|
|
1830
|
+
return { providerId, modelId, agent };
|
|
1787
1831
|
}
|
|
1788
1832
|
function countTokens2(text) {
|
|
1789
1833
|
if (!text) return 0;
|
|
@@ -1828,7 +1872,8 @@ function extractToolContent(part) {
|
|
|
1828
1872
|
}
|
|
1829
1873
|
function countToolTokens(part) {
|
|
1830
1874
|
const contents = extractToolContent(part);
|
|
1831
|
-
|
|
1875
|
+
if (contents.length === 0) return 0;
|
|
1876
|
+
return Math.ceil(Buffer.byteLength(contents.join(" "), "utf-8") / 4);
|
|
1832
1877
|
}
|
|
1833
1878
|
function getTotalToolTokens(state, toolIds) {
|
|
1834
1879
|
let total = 0;
|
|
@@ -1910,7 +1955,7 @@ var MESSAGE_REF_MAX_INDEX = 9999;
|
|
|
1910
1955
|
function formatMessageRef(index) {
|
|
1911
1956
|
if (!Number.isInteger(index) || index < MESSAGE_REF_MIN_INDEX || index > MESSAGE_REF_MAX_INDEX) {
|
|
1912
1957
|
throw new Error(
|
|
1913
|
-
`Message ID index out of bounds: ${index}. Supported range is
|
|
1958
|
+
`Message ID index out of bounds: ${index}. Supported range is ${MESSAGE_REF_MIN_INDEX}-${MESSAGE_REF_MAX_INDEX}.`
|
|
1914
1959
|
);
|
|
1915
1960
|
}
|
|
1916
1961
|
return `m${index.toString().padStart(MESSAGE_REF_WIDTH, "0")}`;
|
|
@@ -2011,14 +2056,16 @@ function assignMessageRefs(state, messages) {
|
|
|
2011
2056
|
return assigned;
|
|
2012
2057
|
}
|
|
2013
2058
|
function allocateNextMessageRef(state) {
|
|
2014
|
-
|
|
2015
|
-
|
|
2059
|
+
const capacity = MESSAGE_REF_MAX_INDEX - MESSAGE_REF_MIN_INDEX + 1;
|
|
2060
|
+
const requested = Number.isInteger(state.messageIds.nextRef) ? state.messageIds.nextRef : MESSAGE_REF_MIN_INDEX;
|
|
2061
|
+
const start = requested >= MESSAGE_REF_MIN_INDEX && requested <= MESSAGE_REF_MAX_INDEX ? requested : MESSAGE_REF_MIN_INDEX;
|
|
2062
|
+
for (let offset = 0; offset < capacity; offset++) {
|
|
2063
|
+
const candidate = MESSAGE_REF_MIN_INDEX + (start - MESSAGE_REF_MIN_INDEX + offset) % capacity;
|
|
2016
2064
|
const ref = formatMessageRef(candidate);
|
|
2017
2065
|
if (!state.messageIds.byRef.has(ref)) {
|
|
2018
|
-
state.messageIds.nextRef = candidate + 1;
|
|
2066
|
+
state.messageIds.nextRef = candidate === MESSAGE_REF_MAX_INDEX ? MESSAGE_REF_MIN_INDEX : candidate + 1;
|
|
2019
2067
|
return ref;
|
|
2020
2068
|
}
|
|
2021
|
-
candidate++;
|
|
2022
2069
|
}
|
|
2023
2070
|
throw new Error(
|
|
2024
2071
|
`Message ID alias capacity exceeded. Cannot allocate more than ${formatMessageRef(MESSAGE_REF_MAX_INDEX)} aliases in this session.`
|
|
@@ -2694,6 +2741,7 @@ function resolveMessage(entry, searchContext, state, config) {
|
|
|
2694
2741
|
// lib/state/persistence.ts
|
|
2695
2742
|
import * as fs from "fs/promises";
|
|
2696
2743
|
import { existsSync as existsSync2 } from "fs";
|
|
2744
|
+
import { randomUUID } from "crypto";
|
|
2697
2745
|
import { homedir as homedir2 } from "os";
|
|
2698
2746
|
import { join as join2 } from "path";
|
|
2699
2747
|
|
|
@@ -2932,78 +2980,148 @@ function getActiveSummaryTokenUsage(state) {
|
|
|
2932
2980
|
}
|
|
2933
2981
|
return total;
|
|
2934
2982
|
}
|
|
2983
|
+
var MAX_SUBAGENT_CACHE_ENTRIES = 64;
|
|
2984
|
+
var MAX_SUBAGENT_CACHE_CHARS = 5e5;
|
|
2985
|
+
var MAX_SUBAGENT_CACHE_TOTAL_CHARS = 2e6;
|
|
2986
|
+
function getCachedSubAgentResult(state, callId) {
|
|
2987
|
+
const cached = state.subAgentResultCache.get(callId);
|
|
2988
|
+
if (cached === void 0) return void 0;
|
|
2989
|
+
state.subAgentResultCache.delete(callId);
|
|
2990
|
+
state.subAgentResultCache.set(callId, cached);
|
|
2991
|
+
return cached;
|
|
2992
|
+
}
|
|
2993
|
+
function cacheSubAgentResult(state, callId, result) {
|
|
2994
|
+
const cached = result.length <= MAX_SUBAGENT_CACHE_CHARS ? result : result.slice(0, MAX_SUBAGENT_CACHE_CHARS) + "\n[\u5B50\u4EE3\u7406\u7ED3\u679C\u56E0\u957F\u5EA6\u9650\u5236\u88AB\u622A\u65AD]";
|
|
2995
|
+
state.subAgentResultCache.delete(callId);
|
|
2996
|
+
state.subAgentResultCache.set(callId, cached);
|
|
2997
|
+
let totalChars = Array.from(state.subAgentResultCache.values()).reduce(
|
|
2998
|
+
(total, value) => total + value.length,
|
|
2999
|
+
0
|
|
3000
|
+
);
|
|
3001
|
+
while (state.subAgentResultCache.size > MAX_SUBAGENT_CACHE_ENTRIES || totalChars > MAX_SUBAGENT_CACHE_TOTAL_CHARS) {
|
|
3002
|
+
const oldest = state.subAgentResultCache.keys().next().value;
|
|
3003
|
+
if (typeof oldest !== "string") break;
|
|
3004
|
+
totalChars -= state.subAgentResultCache.get(oldest)?.length ?? 0;
|
|
3005
|
+
state.subAgentResultCache.delete(oldest);
|
|
3006
|
+
}
|
|
3007
|
+
return cached;
|
|
3008
|
+
}
|
|
2935
3009
|
function resetOnCompaction(state, messages = []) {
|
|
2936
3010
|
state.toolParameters.clear();
|
|
2937
3011
|
if (messages.length === 0) {
|
|
2938
3012
|
return;
|
|
2939
3013
|
}
|
|
2940
3014
|
const liveMessageIds = new Set(messages.map((msg) => msg.info.id));
|
|
3015
|
+
const liveToolIds = new Set(
|
|
3016
|
+
messages.flatMap(
|
|
3017
|
+
(message) => message.parts.flatMap(
|
|
3018
|
+
(part) => part.type === "tool" && part.callID ? [part.callID] : []
|
|
3019
|
+
)
|
|
3020
|
+
)
|
|
3021
|
+
);
|
|
2941
3022
|
for (const [ref, rawId] of state.messageIds.byRef) {
|
|
2942
3023
|
if (!liveMessageIds.has(rawId)) {
|
|
2943
3024
|
state.messageIds.byRef.delete(ref);
|
|
2944
3025
|
state.messageIds.byRawId.delete(rawId);
|
|
2945
3026
|
}
|
|
2946
3027
|
}
|
|
3028
|
+
for (const callId of state.subAgentResultCache.keys()) {
|
|
3029
|
+
if (!liveToolIds.has(callId)) state.subAgentResultCache.delete(callId);
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
|
|
3033
|
+
// lib/concurrency.ts
|
|
3034
|
+
async function runWithConcurrency(items, concurrency, task) {
|
|
3035
|
+
let nextIndex = 0;
|
|
3036
|
+
const workerCount = Math.min(items.length, Math.max(1, Math.floor(concurrency)));
|
|
3037
|
+
const workers = Array.from({ length: workerCount }, async () => {
|
|
3038
|
+
for (; ; ) {
|
|
3039
|
+
const index = nextIndex++;
|
|
3040
|
+
if (index >= items.length) return;
|
|
3041
|
+
await task(items[index]);
|
|
3042
|
+
}
|
|
3043
|
+
});
|
|
3044
|
+
await Promise.all(workers);
|
|
2947
3045
|
}
|
|
2948
3046
|
|
|
2949
3047
|
// lib/state/persistence.ts
|
|
2950
|
-
var
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
3048
|
+
var saveQueues = /* @__PURE__ */ new Map();
|
|
3049
|
+
function getStorageDir() {
|
|
3050
|
+
return join2(
|
|
3051
|
+
process.env.XDG_DATA_HOME || join2(homedir2(), ".local", "share"),
|
|
3052
|
+
"opencode",
|
|
3053
|
+
"storage",
|
|
3054
|
+
"plugin",
|
|
3055
|
+
"dcp"
|
|
3056
|
+
);
|
|
3057
|
+
}
|
|
2957
3058
|
async function ensureStorageDir() {
|
|
2958
|
-
|
|
2959
|
-
|
|
3059
|
+
const storageDir = getStorageDir();
|
|
3060
|
+
if (!existsSync2(storageDir)) {
|
|
3061
|
+
await fs.mkdir(storageDir, { recursive: true });
|
|
2960
3062
|
}
|
|
2961
3063
|
}
|
|
2962
3064
|
function getSessionFilePath(sessionId) {
|
|
2963
|
-
return join2(
|
|
3065
|
+
return join2(getStorageDir(), `${sessionId}.json`);
|
|
2964
3066
|
}
|
|
2965
3067
|
async function writePersistedSessionState(sessionId, state, logger) {
|
|
2966
3068
|
await ensureStorageDir();
|
|
2967
3069
|
const filePath = getSessionFilePath(sessionId);
|
|
3070
|
+
const temporaryPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;
|
|
2968
3071
|
const content = JSON.stringify(state, null, 2);
|
|
2969
|
-
|
|
3072
|
+
try {
|
|
3073
|
+
await fs.writeFile(temporaryPath, content, "utf-8");
|
|
3074
|
+
await fs.rename(temporaryPath, filePath);
|
|
3075
|
+
} catch (error) {
|
|
3076
|
+
await fs.unlink(temporaryPath).catch(() => void 0);
|
|
3077
|
+
throw error;
|
|
3078
|
+
}
|
|
2970
3079
|
logger.info("Saved session state to disk", {
|
|
2971
3080
|
sessionId,
|
|
2972
3081
|
totalTokensSaved: state.stats.totalPruneTokens
|
|
2973
3082
|
});
|
|
2974
3083
|
}
|
|
2975
3084
|
async function saveSessionState(sessionState, logger, sessionName) {
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
3085
|
+
if (!sessionState.sessionId) {
|
|
3086
|
+
return;
|
|
3087
|
+
}
|
|
3088
|
+
const sessionId = sessionState.sessionId;
|
|
3089
|
+
const state = {
|
|
3090
|
+
sessionName,
|
|
3091
|
+
manualMode: !!sessionState.manualMode,
|
|
3092
|
+
prune: {
|
|
3093
|
+
tools: Object.fromEntries(sessionState.prune.tools),
|
|
3094
|
+
messages: serializePruneMessagesState(sessionState.prune.messages)
|
|
3095
|
+
},
|
|
3096
|
+
nudges: {
|
|
3097
|
+
contextLimitAnchors: Array.from(sessionState.nudges.contextLimitAnchors),
|
|
3098
|
+
turnNudgeAnchors: Array.from(sessionState.nudges.turnNudgeAnchors),
|
|
3099
|
+
iterationNudgeAnchors: Array.from(sessionState.nudges.iterationNudgeAnchors)
|
|
3100
|
+
},
|
|
3101
|
+
stats: { ...sessionState.stats },
|
|
3102
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3103
|
+
lastCompaction: sessionState.lastCompaction,
|
|
3104
|
+
messageIds: {
|
|
3105
|
+
byRawId: Object.fromEntries(sessionState.messageIds.byRawId),
|
|
3106
|
+
byRef: Object.fromEntries(sessionState.messageIds.byRef),
|
|
3107
|
+
nextRef: sessionState.messageIds.nextRef
|
|
2979
3108
|
}
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
},
|
|
2987
|
-
nudges: {
|
|
2988
|
-
contextLimitAnchors: Array.from(sessionState.nudges.contextLimitAnchors),
|
|
2989
|
-
turnNudgeAnchors: Array.from(sessionState.nudges.turnNudgeAnchors),
|
|
2990
|
-
iterationNudgeAnchors: Array.from(sessionState.nudges.iterationNudgeAnchors)
|
|
2991
|
-
},
|
|
2992
|
-
stats: sessionState.stats,
|
|
2993
|
-
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2994
|
-
lastCompaction: sessionState.lastCompaction,
|
|
2995
|
-
messageIds: {
|
|
2996
|
-
byRawId: Object.fromEntries(sessionState.messageIds.byRawId),
|
|
2997
|
-
byRef: Object.fromEntries(sessionState.messageIds.byRef),
|
|
2998
|
-
nextRef: sessionState.messageIds.nextRef
|
|
2999
|
-
}
|
|
3000
|
-
};
|
|
3001
|
-
await writePersistedSessionState(sessionState.sessionId, state, logger);
|
|
3109
|
+
};
|
|
3110
|
+
const previous = saveQueues.get(sessionId) ?? Promise.resolve();
|
|
3111
|
+
const current = previous.catch(() => void 0).then(() => writePersistedSessionState(sessionId, state, logger));
|
|
3112
|
+
saveQueues.set(sessionId, current);
|
|
3113
|
+
try {
|
|
3114
|
+
await current;
|
|
3002
3115
|
} catch (error) {
|
|
3003
3116
|
logger.error("Failed to save session state", {
|
|
3004
|
-
sessionId
|
|
3117
|
+
sessionId,
|
|
3005
3118
|
error: error?.message
|
|
3006
3119
|
});
|
|
3120
|
+
throw error;
|
|
3121
|
+
} finally {
|
|
3122
|
+
if (saveQueues.get(sessionId) === current) {
|
|
3123
|
+
saveQueues.delete(sessionId);
|
|
3124
|
+
}
|
|
3007
3125
|
}
|
|
3008
3126
|
}
|
|
3009
3127
|
async function loadSessionState(sessionId, logger) {
|
|
@@ -3082,14 +3200,15 @@ async function loadAllSessionStats(logger) {
|
|
|
3082
3200
|
sessionCount: 0
|
|
3083
3201
|
};
|
|
3084
3202
|
try {
|
|
3085
|
-
|
|
3203
|
+
const storageDir = getStorageDir();
|
|
3204
|
+
if (!existsSync2(storageDir)) {
|
|
3086
3205
|
return result;
|
|
3087
3206
|
}
|
|
3088
|
-
const files = await fs.readdir(
|
|
3207
|
+
const files = await fs.readdir(storageDir);
|
|
3089
3208
|
const jsonFiles = files.filter((f) => f.endsWith(".json"));
|
|
3090
|
-
|
|
3209
|
+
await runWithConcurrency(jsonFiles, 16, async (file) => {
|
|
3091
3210
|
try {
|
|
3092
|
-
const filePath = join2(
|
|
3211
|
+
const filePath = join2(storageDir, file);
|
|
3093
3212
|
const content = await fs.readFile(filePath, "utf-8");
|
|
3094
3213
|
const state = JSON.parse(content);
|
|
3095
3214
|
if (state?.stats?.totalPruneTokens && state?.prune) {
|
|
@@ -3100,7 +3219,7 @@ async function loadAllSessionStats(logger) {
|
|
|
3100
3219
|
}
|
|
3101
3220
|
} catch {
|
|
3102
3221
|
}
|
|
3103
|
-
}
|
|
3222
|
+
});
|
|
3104
3223
|
logger.debug("Loaded all-time stats", result);
|
|
3105
3224
|
} catch (error) {
|
|
3106
3225
|
logger.warn("Failed to load all-time stats", { error: error?.message });
|
|
@@ -3109,6 +3228,8 @@ async function loadAllSessionStats(logger) {
|
|
|
3109
3228
|
}
|
|
3110
3229
|
|
|
3111
3230
|
// lib/compress/timing.ts
|
|
3231
|
+
var MAX_TIMING_ENTRIES = 2048;
|
|
3232
|
+
var TIMING_TTL_MS = 30 * 60 * 1e3;
|
|
3112
3233
|
function buildCompressionTimingKey(messageId, callId) {
|
|
3113
3234
|
return `${messageId}:${callId}`;
|
|
3114
3235
|
}
|
|
@@ -3116,8 +3237,26 @@ function consumeCompressionStart(state, messageId, callId) {
|
|
|
3116
3237
|
const key = buildCompressionTimingKey(messageId, callId);
|
|
3117
3238
|
const start = state.compressionTiming.startsByCallId.get(key);
|
|
3118
3239
|
state.compressionTiming.startsByCallId.delete(key);
|
|
3240
|
+
state.compressionTiming.recordedAtByCallId.delete(key);
|
|
3119
3241
|
return start;
|
|
3120
3242
|
}
|
|
3243
|
+
function pruneCompressionTiming(state, now = Date.now()) {
|
|
3244
|
+
const timing = state.compressionTiming;
|
|
3245
|
+
const cutoff = now - TIMING_TTL_MS;
|
|
3246
|
+
for (const [key, recordedAt] of timing.recordedAtByCallId) {
|
|
3247
|
+
if (recordedAt >= cutoff) continue;
|
|
3248
|
+
timing.recordedAtByCallId.delete(key);
|
|
3249
|
+
timing.startsByCallId.delete(key);
|
|
3250
|
+
timing.pendingByCallId.delete(key);
|
|
3251
|
+
}
|
|
3252
|
+
while (timing.recordedAtByCallId.size > MAX_TIMING_ENTRIES) {
|
|
3253
|
+
const oldest = timing.recordedAtByCallId.keys().next().value;
|
|
3254
|
+
if (typeof oldest !== "string") break;
|
|
3255
|
+
timing.recordedAtByCallId.delete(oldest);
|
|
3256
|
+
timing.startsByCallId.delete(oldest);
|
|
3257
|
+
timing.pendingByCallId.delete(oldest);
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3121
3260
|
function resolveCompressionDuration(startedAt, eventTime, partTime) {
|
|
3122
3261
|
const runningAt = typeof partTime?.start === "number" && Number.isFinite(partTime.start) ? partTime.start : eventTime;
|
|
3123
3262
|
const pendingToRunningMs = typeof startedAt === "number" && typeof runningAt === "number" ? Math.max(0, runningAt - startedAt) : void 0;
|
|
@@ -3141,24 +3280,165 @@ function applyPendingCompressionDurations(state) {
|
|
|
3141
3280
|
if (applied > 0) {
|
|
3142
3281
|
updates += applied;
|
|
3143
3282
|
state.compressionTiming.pendingByCallId.delete(key);
|
|
3283
|
+
state.compressionTiming.recordedAtByCallId.delete(key);
|
|
3144
3284
|
}
|
|
3145
3285
|
}
|
|
3146
3286
|
return updates;
|
|
3147
3287
|
}
|
|
3148
3288
|
|
|
3289
|
+
// lib/state/store.ts
|
|
3290
|
+
var MAX_RESIDENT_SESSIONS = 64;
|
|
3291
|
+
var MAX_MESSAGE_OWNERS = 2e4;
|
|
3292
|
+
var MAX_TIMING_ENTRIES2 = 2048;
|
|
3293
|
+
var TIMING_TTL_MS2 = 30 * 60 * 1e3;
|
|
3294
|
+
var SessionStateStore = class {
|
|
3295
|
+
constructor(createState) {
|
|
3296
|
+
this.createState = createState;
|
|
3297
|
+
}
|
|
3298
|
+
states = /* @__PURE__ */ new Map();
|
|
3299
|
+
initializationQueues = /* @__PURE__ */ new Map();
|
|
3300
|
+
messageOwners = /* @__PURE__ */ new Map();
|
|
3301
|
+
orphanStarts = /* @__PURE__ */ new Map();
|
|
3302
|
+
orphanPending = /* @__PURE__ */ new Map();
|
|
3303
|
+
get(sessionId) {
|
|
3304
|
+
const existing = this.states.get(sessionId);
|
|
3305
|
+
if (existing) {
|
|
3306
|
+
this.touch(sessionId, existing);
|
|
3307
|
+
return existing;
|
|
3308
|
+
}
|
|
3309
|
+
const state = this.createState();
|
|
3310
|
+
this.states.set(sessionId, state);
|
|
3311
|
+
this.trimSessions();
|
|
3312
|
+
return state;
|
|
3313
|
+
}
|
|
3314
|
+
peek(sessionId) {
|
|
3315
|
+
return this.states.get(sessionId);
|
|
3316
|
+
}
|
|
3317
|
+
async initialize(sessionId, initializer) {
|
|
3318
|
+
const state = this.get(sessionId);
|
|
3319
|
+
const previous = this.initializationQueues.get(sessionId) ?? Promise.resolve();
|
|
3320
|
+
const current = previous.catch(() => void 0).then(() => initializer(state));
|
|
3321
|
+
this.initializationQueues.set(sessionId, current);
|
|
3322
|
+
try {
|
|
3323
|
+
await current;
|
|
3324
|
+
} finally {
|
|
3325
|
+
if (this.initializationQueues.get(sessionId) === current) {
|
|
3326
|
+
this.initializationQueues.delete(sessionId);
|
|
3327
|
+
}
|
|
3328
|
+
}
|
|
3329
|
+
return state;
|
|
3330
|
+
}
|
|
3331
|
+
registerMessages(sessionId, messages) {
|
|
3332
|
+
const state = this.get(sessionId);
|
|
3333
|
+
for (const message of messages) {
|
|
3334
|
+
const messageId = message.info?.id;
|
|
3335
|
+
if (typeof messageId !== "string") continue;
|
|
3336
|
+
this.messageOwners.delete(messageId);
|
|
3337
|
+
this.messageOwners.set(messageId, sessionId);
|
|
3338
|
+
this.moveOrphanTiming(messageId, state.compressionTiming);
|
|
3339
|
+
}
|
|
3340
|
+
while (this.messageOwners.size > MAX_MESSAGE_OWNERS) {
|
|
3341
|
+
const oldest = this.messageOwners.keys().next().value;
|
|
3342
|
+
if (typeof oldest !== "string") break;
|
|
3343
|
+
this.messageOwners.delete(oldest);
|
|
3344
|
+
}
|
|
3345
|
+
return state;
|
|
3346
|
+
}
|
|
3347
|
+
resolveEventState(sessionId, messageId) {
|
|
3348
|
+
const resolvedSessionId = sessionId ?? this.messageOwners.get(messageId);
|
|
3349
|
+
if (!resolvedSessionId) return void 0;
|
|
3350
|
+
this.messageOwners.set(messageId, resolvedSessionId);
|
|
3351
|
+
return this.get(resolvedSessionId);
|
|
3352
|
+
}
|
|
3353
|
+
recordOrphanStart(key, startedAt) {
|
|
3354
|
+
this.pruneOrphanTiming();
|
|
3355
|
+
if (this.orphanStarts.has(key)) return;
|
|
3356
|
+
this.orphanStarts.set(key, { startedAt, recordedAt: Date.now() });
|
|
3357
|
+
this.trimMap(this.orphanStarts);
|
|
3358
|
+
}
|
|
3359
|
+
consumeOrphanStart(key) {
|
|
3360
|
+
const entry = this.orphanStarts.get(key);
|
|
3361
|
+
this.orphanStarts.delete(key);
|
|
3362
|
+
return entry?.startedAt;
|
|
3363
|
+
}
|
|
3364
|
+
recordOrphanPending(key, entry) {
|
|
3365
|
+
this.pruneOrphanTiming();
|
|
3366
|
+
this.orphanPending.set(key, { ...entry, recordedAt: Date.now() });
|
|
3367
|
+
this.trimMap(this.orphanPending);
|
|
3368
|
+
}
|
|
3369
|
+
deleteOrphanStart(key) {
|
|
3370
|
+
this.orphanStarts.delete(key);
|
|
3371
|
+
}
|
|
3372
|
+
moveOrphanTiming(messageId, timing) {
|
|
3373
|
+
const prefix = `${messageId}:`;
|
|
3374
|
+
for (const [key, entry] of this.orphanStarts) {
|
|
3375
|
+
if (!key.startsWith(prefix)) continue;
|
|
3376
|
+
if (!timing.startsByCallId.has(key)) {
|
|
3377
|
+
timing.startsByCallId.set(key, entry.startedAt);
|
|
3378
|
+
}
|
|
3379
|
+
timing.recordedAtByCallId.set(key, entry.recordedAt);
|
|
3380
|
+
this.orphanStarts.delete(key);
|
|
3381
|
+
}
|
|
3382
|
+
for (const [key, entry] of this.orphanPending) {
|
|
3383
|
+
if (!key.startsWith(prefix)) continue;
|
|
3384
|
+
timing.pendingByCallId.set(key, {
|
|
3385
|
+
messageId: entry.messageId,
|
|
3386
|
+
callId: entry.callId,
|
|
3387
|
+
durationMs: entry.durationMs
|
|
3388
|
+
});
|
|
3389
|
+
timing.recordedAtByCallId.set(key, entry.recordedAt);
|
|
3390
|
+
this.orphanPending.delete(key);
|
|
3391
|
+
}
|
|
3392
|
+
}
|
|
3393
|
+
touch(sessionId, state) {
|
|
3394
|
+
this.states.delete(sessionId);
|
|
3395
|
+
this.states.set(sessionId, state);
|
|
3396
|
+
}
|
|
3397
|
+
trimSessions() {
|
|
3398
|
+
while (this.states.size > MAX_RESIDENT_SESSIONS) {
|
|
3399
|
+
const oldest = Array.from(this.states.keys()).find(
|
|
3400
|
+
(sessionId) => !this.initializationQueues.has(sessionId)
|
|
3401
|
+
);
|
|
3402
|
+
if (!oldest) return;
|
|
3403
|
+
this.states.delete(oldest);
|
|
3404
|
+
for (const [messageId, owner] of this.messageOwners) {
|
|
3405
|
+
if (owner === oldest) this.messageOwners.delete(messageId);
|
|
3406
|
+
}
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
pruneOrphanTiming() {
|
|
3410
|
+
const cutoff = Date.now() - TIMING_TTL_MS2;
|
|
3411
|
+
for (const [key, entry] of this.orphanStarts) {
|
|
3412
|
+
if (entry.recordedAt < cutoff) this.orphanStarts.delete(key);
|
|
3413
|
+
}
|
|
3414
|
+
for (const [key, entry] of this.orphanPending) {
|
|
3415
|
+
if (entry.recordedAt < cutoff) this.orphanPending.delete(key);
|
|
3416
|
+
}
|
|
3417
|
+
}
|
|
3418
|
+
trimMap(map) {
|
|
3419
|
+
while (map.size > MAX_TIMING_ENTRIES2) {
|
|
3420
|
+
const oldest = map.keys().next().value;
|
|
3421
|
+
if (typeof oldest !== "string") return;
|
|
3422
|
+
map.delete(oldest);
|
|
3423
|
+
}
|
|
3424
|
+
}
|
|
3425
|
+
};
|
|
3426
|
+
function resolveSessionState(target, sessionId) {
|
|
3427
|
+
return target instanceof SessionStateStore ? target.get(sessionId) : target;
|
|
3428
|
+
}
|
|
3429
|
+
|
|
3149
3430
|
// lib/state/state.ts
|
|
3150
|
-
var checkSession = async (client,
|
|
3431
|
+
var checkSession = async (client, target, logger, messages, manualModeDefault) => {
|
|
3151
3432
|
const lastUserMessage = getLastUserMessage(messages);
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
const lastSessionId = lastUserMessage.info.sessionID;
|
|
3433
|
+
const lastSessionId = lastUserMessage?.info.sessionID ?? messages.findLast((message) => typeof message.info?.sessionID === "string")?.info.sessionID;
|
|
3434
|
+
if (!lastSessionId) return target instanceof SessionStateStore ? void 0 : target;
|
|
3435
|
+
const state = target instanceof SessionStateStore ? target.registerMessages(lastSessionId, messages) : resolveSessionState(target, lastSessionId);
|
|
3156
3436
|
if (state.sessionId === null || state.sessionId !== lastSessionId) {
|
|
3157
3437
|
logger.info(`Session changed: ${state.sessionId} -> ${lastSessionId}`);
|
|
3158
3438
|
try {
|
|
3159
|
-
await
|
|
3439
|
+
await initializeSessionState(
|
|
3160
3440
|
client,
|
|
3161
|
-
|
|
3441
|
+
target,
|
|
3162
3442
|
lastSessionId,
|
|
3163
3443
|
logger,
|
|
3164
3444
|
messages,
|
|
@@ -3182,6 +3462,7 @@ var checkSession = async (client, state, logger, messages, manualModeDefault) =>
|
|
|
3182
3462
|
});
|
|
3183
3463
|
}
|
|
3184
3464
|
state.currentTurn = countTurns(state, messages);
|
|
3465
|
+
return state;
|
|
3185
3466
|
};
|
|
3186
3467
|
function createSessionState() {
|
|
3187
3468
|
return {
|
|
@@ -3205,7 +3486,8 @@ function createSessionState() {
|
|
|
3205
3486
|
},
|
|
3206
3487
|
compressionTiming: {
|
|
3207
3488
|
startsByCallId: /* @__PURE__ */ new Map(),
|
|
3208
|
-
pendingByCallId: /* @__PURE__ */ new Map()
|
|
3489
|
+
pendingByCallId: /* @__PURE__ */ new Map(),
|
|
3490
|
+
recordedAtByCallId: /* @__PURE__ */ new Map()
|
|
3209
3491
|
},
|
|
3210
3492
|
toolParameters: /* @__PURE__ */ new Map(),
|
|
3211
3493
|
subAgentResultCache: /* @__PURE__ */ new Map(),
|
|
@@ -3222,6 +3504,7 @@ function createSessionState() {
|
|
|
3222
3504
|
};
|
|
3223
3505
|
}
|
|
3224
3506
|
function resetSessionState(state) {
|
|
3507
|
+
const modelContextLimit = state.modelContextLimit;
|
|
3225
3508
|
state.sessionId = null;
|
|
3226
3509
|
state.isSubAgent = false;
|
|
3227
3510
|
state.manualMode = false;
|
|
@@ -3250,9 +3533,20 @@ function resetSessionState(state) {
|
|
|
3250
3533
|
};
|
|
3251
3534
|
state.lastCompaction = 0;
|
|
3252
3535
|
state.currentTurn = 0;
|
|
3253
|
-
state.modelContextLimit =
|
|
3536
|
+
state.modelContextLimit = modelContextLimit;
|
|
3254
3537
|
state.systemPromptTokens = void 0;
|
|
3255
3538
|
}
|
|
3539
|
+
async function initializeSessionState(client, target, sessionId, logger, messages, manualModeEnabled) {
|
|
3540
|
+
if (target instanceof SessionStateStore) {
|
|
3541
|
+
target.registerMessages(sessionId, messages);
|
|
3542
|
+
return target.initialize(
|
|
3543
|
+
sessionId,
|
|
3544
|
+
(state) => ensureSessionInitialized(client, state, sessionId, logger, messages, manualModeEnabled)
|
|
3545
|
+
);
|
|
3546
|
+
}
|
|
3547
|
+
await ensureSessionInitialized(client, target, sessionId, logger, messages, manualModeEnabled);
|
|
3548
|
+
return target;
|
|
3549
|
+
}
|
|
3256
3550
|
async function ensureSessionInitialized(client, state, sessionId, logger, messages, manualModeEnabled) {
|
|
3257
3551
|
if (state.sessionId === sessionId) {
|
|
3258
3552
|
return;
|
|
@@ -3316,6 +3610,7 @@ function syncToolCache(state, config, logger, messages) {
|
|
|
3316
3610
|
try {
|
|
3317
3611
|
logger.info("Syncing tool parameters from OpenCode messages");
|
|
3318
3612
|
let turnCounter = 0;
|
|
3613
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
3319
3614
|
for (const msg of messages) {
|
|
3320
3615
|
if (isMessageCompacted(state, msg)) {
|
|
3321
3616
|
continue;
|
|
@@ -3329,26 +3624,35 @@ function syncToolCache(state, config, logger, messages) {
|
|
|
3329
3624
|
if (part.type !== "tool" || !part.callID) {
|
|
3330
3625
|
continue;
|
|
3331
3626
|
}
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3627
|
+
candidates.delete(part.callID);
|
|
3628
|
+
candidates.set(part.callID, { part, turn: turnCounter });
|
|
3629
|
+
}
|
|
3630
|
+
}
|
|
3631
|
+
const recentCandidates = Array.from(candidates.entries()).filter(([, candidate]) => {
|
|
3632
|
+
const turnProtectionEnabled = config.turnProtection.enabled;
|
|
3633
|
+
const turnProtectionTurns = config.turnProtection.turns;
|
|
3634
|
+
return !(turnProtectionEnabled && turnProtectionTurns > 0 && state.currentTurn - candidate.turn < turnProtectionTurns);
|
|
3635
|
+
}).slice(-MAX_TOOL_CACHE_SIZE);
|
|
3636
|
+
const retainedIds = new Set(recentCandidates.map(([callId]) => callId));
|
|
3637
|
+
for (const callId of state.toolParameters.keys()) {
|
|
3638
|
+
if (!retainedIds.has(callId)) state.toolParameters.delete(callId);
|
|
3639
|
+
}
|
|
3640
|
+
for (const [callId, { part, turn }] of recentCandidates) {
|
|
3641
|
+
const status = part.state.status;
|
|
3642
|
+
const cached = state.toolParameters.get(callId);
|
|
3643
|
+
if (cached?.status === status) continue;
|
|
3644
|
+
const tokenCount = countToolTokens(part);
|
|
3645
|
+
state.toolParameters.set(callId, {
|
|
3646
|
+
tool: part.tool,
|
|
3647
|
+
parameters: part.state?.input ?? {},
|
|
3648
|
+
status,
|
|
3649
|
+
error: part.state.status === "error" ? part.state.error : void 0,
|
|
3650
|
+
turn,
|
|
3651
|
+
tokenCount
|
|
3652
|
+
});
|
|
3653
|
+
if (!cached) {
|
|
3350
3654
|
logger.info(
|
|
3351
|
-
`Cached tool id: ${
|
|
3655
|
+
`Cached tool id: ${callId} (turn ${turn}${tokenCount !== void 0 ? `, ${tokenCount} tokens` : ""})`
|
|
3352
3656
|
);
|
|
3353
3657
|
}
|
|
3354
3658
|
}
|
|
@@ -3494,6 +3798,9 @@ var deduplicate = (state, logger, config, messages) => {
|
|
|
3494
3798
|
if (!metadata) {
|
|
3495
3799
|
continue;
|
|
3496
3800
|
}
|
|
3801
|
+
if (metadata.status !== void 0 && metadata.status !== "completed" && metadata.status !== "success") {
|
|
3802
|
+
continue;
|
|
3803
|
+
}
|
|
3497
3804
|
if (isToolNameProtected(metadata.tool, protectedTools)) {
|
|
3498
3805
|
continue;
|
|
3499
3806
|
}
|
|
@@ -3991,7 +4298,6 @@ ${progressBar}`;
|
|
|
3991
4298
|
}
|
|
3992
4299
|
async function sendIgnoredMessage(client, sessionID, text, params, logger) {
|
|
3993
4300
|
const agent = params.agent || void 0;
|
|
3994
|
-
const variant = params.variant || void 0;
|
|
3995
4301
|
const model = params.providerId && params.modelId ? {
|
|
3996
4302
|
providerID: params.providerId,
|
|
3997
4303
|
modelID: params.modelId
|
|
@@ -4005,7 +4311,6 @@ async function sendIgnoredMessage(client, sessionID, text, params, logger) {
|
|
|
4005
4311
|
noReply: true,
|
|
4006
4312
|
agent,
|
|
4007
4313
|
model,
|
|
4008
|
-
variant,
|
|
4009
4314
|
parts: [
|
|
4010
4315
|
{
|
|
4011
4316
|
type: "text",
|
|
@@ -4022,7 +4327,18 @@ async function sendIgnoredMessage(client, sessionID, text, params, logger) {
|
|
|
4022
4327
|
|
|
4023
4328
|
// lib/compress/pipeline.ts
|
|
4024
4329
|
async function prepareSession(ctx, toolCtx, title) {
|
|
4025
|
-
|
|
4330
|
+
const state = resolveSessionState(ctx.state, toolCtx.sessionID);
|
|
4331
|
+
toolCtx.metadata({ title });
|
|
4332
|
+
const rawMessages = await fetchSessionMessages(ctx.client, toolCtx.sessionID);
|
|
4333
|
+
await initializeSessionState(
|
|
4334
|
+
ctx.client,
|
|
4335
|
+
ctx.state,
|
|
4336
|
+
toolCtx.sessionID,
|
|
4337
|
+
ctx.logger,
|
|
4338
|
+
rawMessages,
|
|
4339
|
+
ctx.config.manualMode.enabled
|
|
4340
|
+
);
|
|
4341
|
+
if (state.manualMode && state.manualMode !== "compress-pending") {
|
|
4026
4342
|
throw new Error(
|
|
4027
4343
|
"Manual mode: compress blocked. Do not retry until `<compress triggered manually>` appears in user context."
|
|
4028
4344
|
);
|
|
@@ -4033,35 +4349,26 @@ async function prepareSession(ctx, toolCtx, title) {
|
|
|
4033
4349
|
always: ["*"],
|
|
4034
4350
|
metadata: {}
|
|
4035
4351
|
});
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
ctx.client,
|
|
4040
|
-
ctx.state,
|
|
4041
|
-
toolCtx.sessionID,
|
|
4042
|
-
ctx.logger,
|
|
4043
|
-
rawMessages,
|
|
4044
|
-
ctx.config.manualMode.enabled
|
|
4045
|
-
);
|
|
4046
|
-
assignMessageRefs(ctx.state, rawMessages);
|
|
4047
|
-
deduplicate(ctx.state, ctx.logger, ctx.config, rawMessages);
|
|
4048
|
-
purgeErrors(ctx.state, ctx.logger, ctx.config, rawMessages);
|
|
4352
|
+
assignMessageRefs(state, rawMessages);
|
|
4353
|
+
deduplicate(state, ctx.logger, ctx.config, rawMessages);
|
|
4354
|
+
purgeErrors(state, ctx.logger, ctx.config, rawMessages);
|
|
4049
4355
|
return {
|
|
4356
|
+
state,
|
|
4050
4357
|
rawMessages,
|
|
4051
|
-
searchContext: buildSearchContext(
|
|
4358
|
+
searchContext: buildSearchContext(state, rawMessages)
|
|
4052
4359
|
};
|
|
4053
4360
|
}
|
|
4054
|
-
async function finalizeSession(ctx, toolCtx, rawMessages, entries, batchTopic) {
|
|
4055
|
-
|
|
4056
|
-
applyPendingCompressionDurations(
|
|
4057
|
-
await saveSessionState(
|
|
4058
|
-
const params = getCurrentParams(
|
|
4361
|
+
async function finalizeSession(ctx, state, toolCtx, rawMessages, entries, batchTopic) {
|
|
4362
|
+
state.manualMode = state.manualMode ? "active" : false;
|
|
4363
|
+
applyPendingCompressionDurations(state);
|
|
4364
|
+
await saveSessionState(state, ctx.logger);
|
|
4365
|
+
const params = getCurrentParams(state, rawMessages, ctx.logger);
|
|
4059
4366
|
const sessionMessageIds = rawMessages.filter((msg) => !isIgnoredUserMessage(msg)).map((msg) => msg.info.id);
|
|
4060
4367
|
await sendCompressNotification(
|
|
4061
4368
|
ctx.client,
|
|
4062
4369
|
ctx.logger,
|
|
4063
4370
|
ctx.config,
|
|
4064
|
-
|
|
4371
|
+
state,
|
|
4065
4372
|
toolCtx.sessionID,
|
|
4066
4373
|
entries,
|
|
4067
4374
|
batchTopic,
|
|
@@ -4220,7 +4527,7 @@ async function appendProtectedTools(client, state, allowSubAgents, summary, sele
|
|
|
4220
4527
|
output = typeof part.state.output === "string" ? part.state.output : JSON.stringify(part.state.output);
|
|
4221
4528
|
}
|
|
4222
4529
|
if (allowSubAgents && part.tool === "task" && part.state?.status === "completed" && typeof part.state?.output === "string") {
|
|
4223
|
-
const cachedSubAgentResult = state
|
|
4530
|
+
const cachedSubAgentResult = getCachedSubAgentResult(state, part.callID);
|
|
4224
4531
|
if (cachedSubAgentResult !== void 0) {
|
|
4225
4532
|
if (cachedSubAgentResult) {
|
|
4226
4533
|
output = mergeSubagentResult(
|
|
@@ -4242,7 +4549,11 @@ async function appendProtectedTools(client, state, allowSubAgents, summary, sele
|
|
|
4242
4549
|
subAgentResultText = "";
|
|
4243
4550
|
}
|
|
4244
4551
|
if (subAgentResultText) {
|
|
4245
|
-
|
|
4552
|
+
subAgentResultText = cacheSubAgentResult(
|
|
4553
|
+
state,
|
|
4554
|
+
part.callID,
|
|
4555
|
+
subAgentResultText
|
|
4556
|
+
);
|
|
4246
4557
|
output = mergeSubagentResult(
|
|
4247
4558
|
part.state.output,
|
|
4248
4559
|
subAgentResultText
|
|
@@ -4350,6 +4661,21 @@ async function callExternalModel(endpoint, cfg, req) {
|
|
|
4350
4661
|
return content;
|
|
4351
4662
|
}
|
|
4352
4663
|
async function generateSummaryViaExternal(cfg, req) {
|
|
4664
|
+
if (typeof cfg.url !== "string" || cfg.url.trim().length === 0) {
|
|
4665
|
+
throw new Error("\u5916\u90E8\u538B\u7F29\u6A21\u578B url \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");
|
|
4666
|
+
}
|
|
4667
|
+
if (typeof cfg.model !== "string" || cfg.model.trim().length === 0) {
|
|
4668
|
+
throw new Error("\u5916\u90E8\u538B\u7F29\u6A21\u578B model \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");
|
|
4669
|
+
}
|
|
4670
|
+
if (cfg.apiKey !== void 0 && typeof cfg.apiKey !== "string") {
|
|
4671
|
+
throw new Error("\u5916\u90E8\u538B\u7F29\u6A21\u578B apiKey \u5FC5\u987B\u662F\u5B57\u7B26\u4E32");
|
|
4672
|
+
}
|
|
4673
|
+
if (cfg.timeout !== void 0 && (!Number.isFinite(cfg.timeout) || cfg.timeout <= 0)) {
|
|
4674
|
+
throw new Error("\u5916\u90E8\u538B\u7F29\u6A21\u578B timeout \u5FC5\u987B\u662F\u6B63\u6570");
|
|
4675
|
+
}
|
|
4676
|
+
if (cfg.retries !== void 0 && (!Number.isInteger(cfg.retries) || cfg.retries < 0)) {
|
|
4677
|
+
throw new Error("\u5916\u90E8\u538B\u7F29\u6A21\u578B retries \u5FC5\u987B\u662F\u975E\u8D1F\u6574\u6570");
|
|
4678
|
+
}
|
|
4353
4679
|
const endpoint = resolveCompressBaseUrl(cfg.url);
|
|
4354
4680
|
const maxRetries = cfg.retries ?? 1;
|
|
4355
4681
|
let lastError;
|
|
@@ -4363,18 +4689,57 @@ async function generateSummaryViaExternal(cfg, req) {
|
|
|
4363
4689
|
throw lastError;
|
|
4364
4690
|
}
|
|
4365
4691
|
|
|
4366
|
-
// lib/compress/
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4692
|
+
// lib/compress/external-content.ts
|
|
4693
|
+
var MAX_PART_CHARS = 1e5;
|
|
4694
|
+
var MAX_TOTAL_CHARS = 1e6;
|
|
4695
|
+
var TRUNCATED_MARKER = "\n[\u5185\u5BB9\u56E0\u957F\u5EA6\u9650\u5236\u88AB\u622A\u65AD]";
|
|
4696
|
+
function stringify(value) {
|
|
4697
|
+
if (typeof value === "string") return value;
|
|
4698
|
+
try {
|
|
4699
|
+
return JSON.stringify(value, null, 2) ?? String(value);
|
|
4700
|
+
} catch {
|
|
4701
|
+
return String(value);
|
|
4702
|
+
}
|
|
4703
|
+
}
|
|
4704
|
+
function truncate2(value, limit = MAX_PART_CHARS) {
|
|
4705
|
+
if (value.length <= limit) return value;
|
|
4706
|
+
return value.slice(0, limit) + TRUNCATED_MARKER;
|
|
4707
|
+
}
|
|
4708
|
+
function serializePart(part) {
|
|
4709
|
+
if (part.type === "text" && typeof part.text === "string") {
|
|
4710
|
+
return [truncate2(part.text)];
|
|
4711
|
+
}
|
|
4712
|
+
if (part.type !== "tool") return [];
|
|
4713
|
+
const chunks = [`[\u5DE5\u5177\uFF1A${part.tool}\uFF1B\u72B6\u6001\uFF1A${part.state.status}]`];
|
|
4714
|
+
if (part.state.input !== void 0) {
|
|
4715
|
+
chunks.push("\u8F93\u5165\uFF1A\n" + truncate2(stringify(part.state.input)));
|
|
4716
|
+
}
|
|
4717
|
+
if (part.state.status === "completed" && part.state.output !== void 0) {
|
|
4718
|
+
chunks.push("\u8F93\u51FA\uFF1A\n" + truncate2(stringify(part.state.output)));
|
|
4719
|
+
} else if (part.state.status === "error" && part.state.error !== void 0) {
|
|
4720
|
+
chunks.push("\u9519\u8BEF\uFF1A\n" + truncate2(stringify(part.state.error)));
|
|
4721
|
+
}
|
|
4722
|
+
return chunks;
|
|
4723
|
+
}
|
|
4724
|
+
function serializeMessagesForExternalSummary(messages) {
|
|
4725
|
+
const chunks = [];
|
|
4726
|
+
let length = 0;
|
|
4727
|
+
for (const message of messages) {
|
|
4728
|
+
const header = `[\u6D88\u606F\uFF1A${message.info.id}\uFF1B\u89D2\u8272\uFF1A${message.info.role}]`;
|
|
4729
|
+
const content = [header, ...message.parts.flatMap(serializePart)].join("\n");
|
|
4730
|
+
if (length + content.length > MAX_TOTAL_CHARS) {
|
|
4731
|
+
const remaining = Math.max(0, MAX_TOTAL_CHARS - length);
|
|
4732
|
+
if (remaining > 0) chunks.push(content.slice(0, remaining));
|
|
4733
|
+
chunks.push(TRUNCATED_MARKER.trim());
|
|
4734
|
+
break;
|
|
4374
4735
|
}
|
|
4736
|
+
chunks.push(content);
|
|
4737
|
+
length += content.length;
|
|
4375
4738
|
}
|
|
4376
|
-
return
|
|
4739
|
+
return chunks.join("\n\n");
|
|
4377
4740
|
}
|
|
4741
|
+
|
|
4742
|
+
// lib/compress/message.ts
|
|
4378
4743
|
function buildSchema(externalModelEnabled) {
|
|
4379
4744
|
const summaryField = externalModelEnabled ? tool.schema.string().optional().describe(
|
|
4380
4745
|
"Complete technical summary replacing that one message (optional when external model is configured)"
|
|
@@ -4403,7 +4768,7 @@ function createCompressMessageTool(ctx) {
|
|
|
4403
4768
|
const input = args;
|
|
4404
4769
|
validateArgs(input);
|
|
4405
4770
|
const callId = typeof toolCtx.callID === "string" ? toolCtx.callID : void 0;
|
|
4406
|
-
const { rawMessages, searchContext } = await prepareSession(
|
|
4771
|
+
const { state, rawMessages, searchContext } = await prepareSession(
|
|
4407
4772
|
ctx,
|
|
4408
4773
|
toolCtx,
|
|
4409
4774
|
`Compress Message: ${input.topic}`
|
|
@@ -4411,26 +4776,27 @@ function createCompressMessageTool(ctx) {
|
|
|
4411
4776
|
const { plans, skippedIssues, skippedCount } = resolveMessages(
|
|
4412
4777
|
input,
|
|
4413
4778
|
searchContext,
|
|
4414
|
-
|
|
4779
|
+
state,
|
|
4415
4780
|
ctx.config
|
|
4416
4781
|
);
|
|
4417
4782
|
if (plans.length === 0 && skippedCount > 0) {
|
|
4418
4783
|
throw new Error(formatIssues(skippedIssues, skippedCount));
|
|
4419
4784
|
}
|
|
4420
|
-
|
|
4421
|
-
|
|
4785
|
+
const externalModel = ctx.config.compress.externalModel;
|
|
4786
|
+
if (externalModel) {
|
|
4787
|
+
await runWithConcurrency(plans, 3, async (plan) => {
|
|
4422
4788
|
if (plan.entry.summary === void 0) {
|
|
4423
|
-
const
|
|
4424
|
-
const
|
|
4425
|
-
|
|
4426
|
-
{
|
|
4427
|
-
systemPrompt: runtimePrompts.compressMessage,
|
|
4428
|
-
userContent
|
|
4429
|
-
}
|
|
4789
|
+
const message = searchContext.rawMessagesById.get(plan.entry.messageId);
|
|
4790
|
+
const userContent = serializeMessagesForExternalSummary(
|
|
4791
|
+
message ? [message] : []
|
|
4430
4792
|
);
|
|
4793
|
+
const generated = await generateSummaryViaExternal(externalModel, {
|
|
4794
|
+
systemPrompt: runtimePrompts.compressMessage,
|
|
4795
|
+
userContent
|
|
4796
|
+
});
|
|
4431
4797
|
plan.entry.summary = generated;
|
|
4432
4798
|
}
|
|
4433
|
-
}
|
|
4799
|
+
});
|
|
4434
4800
|
}
|
|
4435
4801
|
const notifications = [];
|
|
4436
4802
|
const preparedPlans = [];
|
|
@@ -4444,12 +4810,12 @@ function createCompressMessageTool(ctx) {
|
|
|
4444
4810
|
plan.entry.summary,
|
|
4445
4811
|
plan.selection,
|
|
4446
4812
|
searchContext,
|
|
4447
|
-
|
|
4813
|
+
state,
|
|
4448
4814
|
ctx.config.compress.protectTags
|
|
4449
4815
|
);
|
|
4450
4816
|
const summaryWithTools = await appendProtectedTools(
|
|
4451
4817
|
ctx.client,
|
|
4452
|
-
|
|
4818
|
+
state,
|
|
4453
4819
|
ctx.config.experimental.allowSubAgents,
|
|
4454
4820
|
summaryWithPromptInfo,
|
|
4455
4821
|
plan.selection,
|
|
@@ -4462,13 +4828,13 @@ function createCompressMessageTool(ctx) {
|
|
|
4462
4828
|
summaryWithTools
|
|
4463
4829
|
});
|
|
4464
4830
|
}
|
|
4465
|
-
const runId = allocateRunId(
|
|
4831
|
+
const runId = allocateRunId(state);
|
|
4466
4832
|
for (const { plan, summaryWithTools } of preparedPlans) {
|
|
4467
|
-
const blockId = allocateBlockId(
|
|
4833
|
+
const blockId = allocateBlockId(state);
|
|
4468
4834
|
const storedSummary = wrapCompressedSummary(blockId, summaryWithTools);
|
|
4469
4835
|
const summaryTokens = countTokens2(storedSummary);
|
|
4470
4836
|
applyCompressionState(
|
|
4471
|
-
|
|
4837
|
+
state,
|
|
4472
4838
|
{
|
|
4473
4839
|
topic: plan.entry.topic,
|
|
4474
4840
|
batchTopic: input.topic,
|
|
@@ -4493,7 +4859,7 @@ function createCompressMessageTool(ctx) {
|
|
|
4493
4859
|
summaryTokens
|
|
4494
4860
|
});
|
|
4495
4861
|
}
|
|
4496
|
-
await finalizeSession(ctx, toolCtx, rawMessages, notifications, input.topic);
|
|
4862
|
+
await finalizeSession(ctx, state, toolCtx, rawMessages, notifications, input.topic);
|
|
4497
4863
|
return formatResult(plans.length, skippedIssues, skippedCount);
|
|
4498
4864
|
}
|
|
4499
4865
|
});
|
|
@@ -4729,19 +5095,6 @@ ${right}`;
|
|
|
4729
5095
|
}
|
|
4730
5096
|
|
|
4731
5097
|
// lib/compress/range.ts
|
|
4732
|
-
function extractRangeText(selection, searchContext) {
|
|
4733
|
-
const parts = [];
|
|
4734
|
-
for (const messageId of selection.messageIds) {
|
|
4735
|
-
const msg = searchContext.rawMessagesById.get(messageId);
|
|
4736
|
-
if (!msg) continue;
|
|
4737
|
-
for (const part of msg.parts) {
|
|
4738
|
-
if (part.type === "text" && typeof part.text === "string") {
|
|
4739
|
-
parts.push(part.text);
|
|
4740
|
-
}
|
|
4741
|
-
}
|
|
4742
|
-
}
|
|
4743
|
-
return parts.join("\n\n");
|
|
4744
|
-
}
|
|
4745
5098
|
function buildSchema2(externalModelEnabled) {
|
|
4746
5099
|
const summaryField = externalModelEnabled ? tool2.schema.string().optional().describe(
|
|
4747
5100
|
"Complete technical summary replacing all content in range (optional when external model is configured)"
|
|
@@ -4774,27 +5127,29 @@ function createCompressRangeTool(ctx) {
|
|
|
4774
5127
|
const input = args;
|
|
4775
5128
|
validateArgs2(input);
|
|
4776
5129
|
const callId = typeof toolCtx.callID === "string" ? toolCtx.callID : void 0;
|
|
4777
|
-
const { rawMessages, searchContext } = await prepareSession(
|
|
5130
|
+
const { state, rawMessages, searchContext } = await prepareSession(
|
|
4778
5131
|
ctx,
|
|
4779
5132
|
toolCtx,
|
|
4780
5133
|
`Compress Range: ${input.topic}`
|
|
4781
5134
|
);
|
|
4782
|
-
const resolvedPlans = resolveRanges(input, searchContext,
|
|
5135
|
+
const resolvedPlans = resolveRanges(input, searchContext, state);
|
|
4783
5136
|
validateNonOverlapping(resolvedPlans);
|
|
4784
|
-
|
|
4785
|
-
|
|
5137
|
+
const externalModel = ctx.config.compress.externalModel;
|
|
5138
|
+
if (externalModel) {
|
|
5139
|
+
await runWithConcurrency(resolvedPlans, 3, async (plan) => {
|
|
4786
5140
|
if (plan.entry.summary === void 0) {
|
|
4787
|
-
const
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
5141
|
+
const selectedMessages = plan.selection.messageIds.flatMap((messageId) => {
|
|
5142
|
+
const message = searchContext.rawMessagesById.get(messageId);
|
|
5143
|
+
return message ? [message] : [];
|
|
5144
|
+
});
|
|
5145
|
+
const userContent = serializeMessagesForExternalSummary(selectedMessages);
|
|
5146
|
+
const generated = await generateSummaryViaExternal(externalModel, {
|
|
5147
|
+
systemPrompt: runtimePrompts.compressRange,
|
|
5148
|
+
userContent
|
|
5149
|
+
});
|
|
4795
5150
|
plan.entry.summary = generated;
|
|
4796
5151
|
}
|
|
4797
|
-
}
|
|
5152
|
+
});
|
|
4798
5153
|
}
|
|
4799
5154
|
const notifications = [];
|
|
4800
5155
|
const preparedPlans = [];
|
|
@@ -4824,19 +5179,19 @@ function createCompressRangeTool(ctx) {
|
|
|
4824
5179
|
injected.expandedSummary,
|
|
4825
5180
|
plan.selection,
|
|
4826
5181
|
searchContext,
|
|
4827
|
-
|
|
5182
|
+
state,
|
|
4828
5183
|
ctx.config.compress.protectUserMessages
|
|
4829
5184
|
);
|
|
4830
5185
|
const summaryWithPromptInfo = appendProtectedPromptInfo(
|
|
4831
5186
|
summaryWithUsers,
|
|
4832
5187
|
plan.selection,
|
|
4833
5188
|
searchContext,
|
|
4834
|
-
|
|
5189
|
+
state,
|
|
4835
5190
|
ctx.config.compress.protectTags
|
|
4836
5191
|
);
|
|
4837
5192
|
const summaryWithTools = await appendProtectedTools(
|
|
4838
5193
|
ctx.client,
|
|
4839
|
-
|
|
5194
|
+
state,
|
|
4840
5195
|
ctx.config.experimental.allowSubAgents,
|
|
4841
5196
|
summaryWithPromptInfo,
|
|
4842
5197
|
plan.selection,
|
|
@@ -4858,13 +5213,13 @@ function createCompressRangeTool(ctx) {
|
|
|
4858
5213
|
consumedBlockIds: completedSummary.consumedBlockIds
|
|
4859
5214
|
});
|
|
4860
5215
|
}
|
|
4861
|
-
const runId = allocateRunId(
|
|
5216
|
+
const runId = allocateRunId(state);
|
|
4862
5217
|
for (const preparedPlan of preparedPlans) {
|
|
4863
|
-
const blockId = allocateBlockId(
|
|
5218
|
+
const blockId = allocateBlockId(state);
|
|
4864
5219
|
const storedSummary = wrapCompressedSummary(blockId, preparedPlan.finalSummary);
|
|
4865
5220
|
const summaryTokens = countTokens2(storedSummary);
|
|
4866
5221
|
const applied = applyCompressionState(
|
|
4867
|
-
|
|
5222
|
+
state,
|
|
4868
5223
|
{
|
|
4869
5224
|
topic: input.topic,
|
|
4870
5225
|
batchTopic: input.topic,
|
|
@@ -4890,7 +5245,7 @@ function createCompressRangeTool(ctx) {
|
|
|
4890
5245
|
summaryTokens
|
|
4891
5246
|
});
|
|
4892
5247
|
}
|
|
4893
|
-
await finalizeSession(ctx, toolCtx, rawMessages, notifications, input.topic);
|
|
5248
|
+
await finalizeSession(ctx, state, toolCtx, rawMessages, notifications, input.topic);
|
|
4894
5249
|
return `Compressed ${totalCompressedMessages} messages into ${COMPRESSED_BLOCK_HEADER}.`;
|
|
4895
5250
|
}
|
|
4896
5251
|
});
|
|
@@ -5156,51 +5511,51 @@ import { homedir as homedir4 } from "os";
|
|
|
5156
5511
|
|
|
5157
5512
|
// lib/prompts/system.ts
|
|
5158
5513
|
var SYSTEM = `
|
|
5159
|
-
|
|
5514
|
+
\u4F60\u5728\u4E0A\u4E0B\u6587\u957F\u5EA6\u53D7\u9650\u7684\u73AF\u5883\u4E2D\u8FD0\u884C\u3002\u4E3B\u52A8\u7BA1\u7406\u4E0A\u4E0B\u6587\uFF0C\u907F\u514D\u65E0\u6548\u7D2F\u79EF\u5E76\u4FDD\u6301\u8F83\u9AD8\u7684\u68C0\u7D22\u8D28\u91CF\u3002
|
|
5160
5515
|
|
|
5161
|
-
|
|
5516
|
+
\u552F\u4E00\u7684\u4E0A\u4E0B\u6587\u7BA1\u7406\u5DE5\u5177\u662F \`compress\`\u3002\u5B83\u4F1A\u7528\u4F60\u751F\u6210\u7684\u6280\u672F\u6458\u8981\u66FF\u6362\u8F83\u65E9\u7684\u5BF9\u8BDD\u5185\u5BB9\u3002
|
|
5162
5517
|
|
|
5163
|
-
|
|
5164
|
-
-
|
|
5165
|
-
-
|
|
5166
|
-
-
|
|
5167
|
-
-
|
|
5518
|
+
\u786C\u6027\u7EA6\u675F
|
|
5519
|
+
- \u53EA\u80FD\u901A\u8FC7\u8C03\u7528 \`compress\` \u7BA1\u7406\u4E0A\u4E0B\u6587\uFF0C\u7EDD\u4E0D\u80FD\u5728\u666E\u901A\u6587\u672C\u4E2D\u76F4\u63A5\u751F\u6210\u538B\u7F29\u6458\u8981\u3002
|
|
5520
|
+
- \u6587\u672C\u56DE\u590D\u4E2D\u7EDD\u4E0D\u80FD\u8F93\u51FA \`<summary>\` \u6216 \`<analysis>\` XML \u6807\u7B7E\uFF0C\u5B83\u4EEC\u4F1A\u5BFC\u81F4\u7CFB\u7EDF\u9519\u8BEF\u3002
|
|
5521
|
+
- \u9700\u8981\u538B\u7F29\u65F6\u8C03\u7528 \`compress\`\uFF0C\u4E0D\u8981\u5728\u56DE\u590D\u4E2D\u5185\u8054\u7F16\u5199\u6458\u8981\u3002
|
|
5522
|
+
- \u4F7F\u7528 Markdown \u6807\u9898\uFF08\u4F8B\u5982 \`## \u5206\u6790\`\u3001\`## \u6458\u8981\`\uFF09\u7EC4\u7EC7\u4FE1\u606F\uFF0C\u7EDD\u4E0D\u80FD\u4F7F\u7528 XML \u6807\u7B7E\u3002
|
|
5168
5523
|
|
|
5169
|
-
\`<dcp-message-id>\`
|
|
5524
|
+
\`<dcp-message-id>\` \u548C \`<dcp-system-reminder>\` \u662F\u73AF\u5883\u6CE8\u5165\u7684\u5143\u6570\u636E\uFF0C\u4E0D\u8981\u8F93\u51FA\u5B83\u4EEC\u3002
|
|
5170
5525
|
|
|
5171
|
-
|
|
5526
|
+
\u4F55\u65F6\u538B\u7F29
|
|
5172
5527
|
|
|
5173
|
-
|
|
5528
|
+
\u6700\u9AD8\u4F18\u5148\u7EA7\u7684\u5F3A\u5236\u89E6\u53D1\u6761\u4EF6\uFF1A\u53EA\u8981\u5BF9\u8BDD\u4E3B\u9898\u53D1\u751F\u53D8\u5316\uFF0C\u7ACB\u5373\u8C03\u7528 \`compress\`\uFF0C\u628A\u4E0A\u4E00\u4E3B\u9898\u5DF2\u7ECF\u5B8C\u6210\u7684\u4E0A\u4E0B\u6587\u538B\u7F29\u4E3A\u6458\u8981\u3002
|
|
5174
5529
|
|
|
5175
|
-
|
|
5530
|
+
\u4E3B\u9898\u53D8\u5316\u662F\u5BA2\u89C2\u4E14\u4E0D\u9700\u8981\u590D\u6742\u5224\u65AD\u7684\u4FE1\u53F7\u3002\u4EE5\u4E0B\u4EFB\u4E00\u60C5\u51B5\u90FD\u7B97\u4E3B\u9898\u53D8\u5316\uFF1A
|
|
5176
5531
|
|
|
5177
|
-
-
|
|
5178
|
-
-
|
|
5179
|
-
-
|
|
5180
|
-
-
|
|
5532
|
+
- \u7528\u6237\u63D0\u51FA\u4E0E\u4E0A\u4E00\u4EFB\u52A1\u65E0\u5173\u7684\u95EE\u9898
|
|
5533
|
+
- \u5DE5\u4F5C\u91CD\u70B9\u4ECE\u4E00\u4E2A\u6A21\u5757\u3001\u6587\u4EF6\u6216\u529F\u80FD\u8F6C\u79FB\u5230\u53E6\u4E00\u4E2A
|
|
5534
|
+
- \u76EE\u6807\u4ECE\u63A2\u7D22/\u7814\u7A76\u8F6C\u4E3A\u5B9E\u73B0\uFF0C\u6216\u4ECE\u5B9E\u73B0\u8F6C\u4E3A\u8C03\u8BD5/\u9A8C\u8BC1
|
|
5535
|
+
- \u4E00\u4E2A\u72EC\u7ACB\u95EE\u9898\u5DF2\u7ECF\u89E3\u51B3\uFF0C\u5F00\u59CB\u5904\u7406\u4E0B\u4E00\u4E2A\u95EE\u9898
|
|
5181
5536
|
|
|
5182
|
-
|
|
5537
|
+
\u51FA\u73B0\u4EFB\u4E00\u60C5\u51B5\u65F6\uFF0C\u7ACB\u5373\u538B\u7F29\u4E0A\u4E00\u4E3B\u9898\u5DF2\u7ECF\u5B8C\u6210\u7684\u8303\u56F4\uFF0C\u4E0D\u8981\u7B49\u5F85\u3002\u8FD9\u662F\u4FDD\u6301\u4E0A\u4E0B\u6587\u6E05\u6670\u6700\u6709\u6548\u7684\u65B9\u6CD5\u3002
|
|
5183
5538
|
|
|
5184
|
-
|
|
5539
|
+
\u5373\u4F7F\u4E3B\u9898\u6CA1\u6709\u53D8\u5316\uFF0C\u5728\u4EE5\u4E0B\u9636\u6BB5\u786E\u5B9E\u7ED3\u675F\u65F6\u4E5F\u5E94\u538B\u7F29\uFF1A
|
|
5185
5540
|
|
|
5186
|
-
-
|
|
5187
|
-
-
|
|
5188
|
-
-
|
|
5189
|
-
-
|
|
5541
|
+
- \u7814\u7A76\u5B8C\u6210\uFF0C\u7ED3\u8BBA\u5DF2\u7ECF\u786E\u5B9A
|
|
5542
|
+
- \u5B9E\u73B0\u5B8C\u6210\u5E76\u901A\u8FC7\u9A8C\u8BC1
|
|
5543
|
+
- \u63A2\u7D22\u5DF2\u7ECF\u5145\u5206\uFF0C\u76F8\u5173\u89C4\u5F8B\u5DF2\u7ECF\u660E\u786E
|
|
5544
|
+
- \u5DF2\u786E\u8BA4\u65E0\u6548\u7684\u65B9\u5411\u53EF\u4EE5\u4E22\u5F03\uFF0C\u65E0\u9700\u7B49\u5F85\u6574\u4E2A\u9636\u6BB5\u7ED3\u675F
|
|
5190
5545
|
|
|
5191
|
-
|
|
5546
|
+
\u4EE5\u4E0B\u60C5\u51B5\u4E0D\u8981\u538B\u7F29\uFF1A
|
|
5192
5547
|
|
|
5193
|
-
-
|
|
5194
|
-
-
|
|
5195
|
-
-
|
|
5548
|
+
- \u7F16\u8F91\u6216\u7CBE\u786E\u5F15\u7528\u4ECD\u9700\u8981\u539F\u59CB\u4E0A\u4E0B\u6587
|
|
5549
|
+
- \u76EE\u6807\u5DE5\u4F5C\u4ECD\u5728\u8FDB\u884C
|
|
5550
|
+
- \u540E\u7EED\u6B65\u9AA4\u53EF\u80FD\u9700\u8981\u7CBE\u786E\u7684\u4EE3\u7801\u3001\u9519\u8BEF\u4FE1\u606F\u6216\u6587\u4EF6\u5185\u5BB9
|
|
5196
5551
|
|
|
5197
|
-
|
|
5552
|
+
\u538B\u7F29\u524D\u5148\u95EE\u81EA\u5DF1\uFF1A_\u201C\u8FD9\u4E00\u90E8\u5206\u662F\u5426\u5DF2\u7ECF\u7ED3\u675F\uFF0C\u53EF\u4EE5\u53EA\u4FDD\u7559\u6458\u8981\uFF1F\u201D_
|
|
5198
5553
|
|
|
5199
|
-
|
|
5554
|
+
\u5982\u679C\u60C5\u51B5\u662F\u201C\u4E3B\u9898\u5DF2\u7ECF\u5207\u6362\uFF0C\u4E0D\u518D\u9700\u8981\u65E7\u5185\u5BB9\u201D\uFF0C\u7B54\u6848\u59CB\u7EC8\u662F\u201C\u53EF\u4EE5\u201D\u3002
|
|
5200
5555
|
|
|
5201
|
-
|
|
5556
|
+
\u5B9A\u671F\u8BC4\u4F30\u5BF9\u8BDD\u7684\u6709\u6548\u4FE1\u606F\u6BD4\u4F8B\u3002\u8C28\u614E\u4F7F\u7528 \`compress\` \u5E76\u751F\u6210\u9AD8\u8D28\u91CF\u6458\u8981\uFF0C\u4F18\u5148\u5904\u7406\u8FC7\u671F\u5185\u5BB9\uFF0C\u4FDD\u6301\u9AD8\u8D28\u91CF\u4E0A\u4E0B\u6587\u3002
|
|
5202
5557
|
|
|
5203
|
-
|
|
5558
|
+
\u4F60\u6709\u8D23\u4EFB\u7EF4\u62A4\u7CBE\u786E\u3001\u9AD8\u8D28\u91CF\u7684\u4E0A\u4E0B\u6587\uFF0C\u4EE5\u83B7\u5F97\u6700\u4F73\u8868\u73B0\u3002
|
|
5204
5559
|
`;
|
|
5205
5560
|
|
|
5206
5561
|
// lib/prompts/compress-range.ts
|
|
@@ -5337,44 +5692,44 @@ var COMPRESS_MESSAGE = `\u5C06\u5BF9\u8BDD\u4E2D\u9009\u5B9A\u7684\u5355\u6761\u
|
|
|
5337
5692
|
|
|
5338
5693
|
// lib/prompts/context-limit-nudge.ts
|
|
5339
5694
|
var CONTEXT_LIMIT_NUDGE = `<dcp-system-reminder>
|
|
5340
|
-
|
|
5695
|
+
\u7D27\u6025\uFF1A\u5DF2\u8FBE\u5230\u4E0A\u4E0B\u6587\u4E0A\u9650\u3002
|
|
5341
5696
|
|
|
5342
|
-
|
|
5697
|
+
\u5F53\u524D\u4E0A\u4E0B\u6587\u5DF2\u8FBE\u5230\u6216\u8D85\u8FC7\u914D\u7F6E\u7684\u6700\u5927\u9608\u503C\uFF0C\u5FC5\u987B\u7ACB\u5373\u56DE\u6536\u4E0A\u4E0B\u6587\u3002
|
|
5343
5698
|
|
|
5344
|
-
|
|
5699
|
+
\u4F60\u5FC5\u987B\u73B0\u5728\u8C03\u7528 \`compress\`\u3002\u538B\u7F29\u5B8C\u6210\u524D\u4E0D\u8981\u7EE7\u7EED\u5E38\u89C4\u63A2\u7D22\u3002
|
|
5345
5700
|
|
|
5346
|
-
|
|
5701
|
+
\u5982\u679C\u6B63\u5728\u6267\u884C\u4E00\u4E2A\u4E0D\u53EF\u4E2D\u65AD\u7684\u6B65\u9AA4\uFF0C\u53EA\u5B8C\u6210\u8BE5\u6B65\u9AA4\uFF0C\u968F\u540E\u7ACB\u523B\u538B\u7F29\u3002
|
|
5347
5702
|
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5703
|
+
\u9009\u62E9\u8303\u56F4
|
|
5704
|
+
\u4ECE\u8F83\u65E9\u4E14\u5DF2\u7ECF\u5B8C\u6210\u7684\u5386\u53F2\u5F00\u59CB\uFF0C\u4E00\u6B21\u8986\u76D6\u5C3D\u53EF\u80FD\u591A\u7684\u8FC7\u671F\u4E0A\u4E0B\u6587\u3002
|
|
5705
|
+
\u9664\u975E\u6700\u65B0\u5DE5\u4F5C\u5DF2\u7ECF\u660E\u786E\u7ED3\u675F\uFF0C\u5426\u5219\u4E0D\u8981\u9009\u62E9\u6700\u8FD1\u7684\u5DE5\u4F5C\u6D88\u606F\u3002
|
|
5351
5706
|
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5707
|
+
\u6458\u8981\u8981\u6C42
|
|
5708
|
+
\u6458\u8981\u5FC5\u987B\u8986\u76D6\u6240\u9009\u6D88\u606F\u4E2D\u7684\u6240\u6709\u5173\u952E\u4FE1\u606F\uFF0C\u786E\u4FDD\u540E\u7EED\u5DE5\u4F5C\u53EF\u4EE5\u7EE7\u7EED\u3002
|
|
5709
|
+
\u5982\u679C\u8303\u56F4\u5305\u542B\u7528\u6237\u6D88\u606F\uFF0C\u5FC5\u987B\u5B8C\u6574\u4FDD\u7559\u7528\u6237\u610F\u56FE\u3002\u5BF9\u4E8E\u8F83\u77ED\u7684\u7528\u6237\u6D88\u606F\uFF0C\u4F18\u5148\u76F4\u63A5\u5F15\u7528\uFF0C\u907F\u514D\u8BED\u4E49\u504F\u79FB\u3002
|
|
5355
5710
|
</dcp-system-reminder>
|
|
5356
5711
|
`;
|
|
5357
5712
|
|
|
5358
5713
|
// lib/prompts/turn-nudge.ts
|
|
5359
5714
|
var TURN_NUDGE = `
|
|
5360
|
-
|
|
5715
|
+
\u7528\u6237\u5F00\u59CB\u4E86\u65B0\u4E00\u8F6E\u5BF9\u8BDD\uFF0C\u6B64\u65F6\u6700\u5BB9\u6613\u53D1\u751F\u4E3B\u9898\u53D8\u5316\u3002
|
|
5361
5716
|
|
|
5362
|
-
|
|
5363
|
-
-
|
|
5364
|
-
-
|
|
5717
|
+
\u672C\u8F6E\u8BF7\u6C42\u662F\u5426\u4E0E\u4E0A\u4E00\u8F6E\u5C5E\u4E8E\u4E0D\u540C\u4E3B\u9898\u6216\u4EFB\u52A1\uFF1F
|
|
5718
|
+
- \u65B0\u4E3B\u9898\u6216\u72EC\u7ACB\u4EFB\u52A1\uFF1A\u73B0\u5728\u8C03\u7528 \`compress\`\uFF0C\u628A\u4E0A\u4E00\u4E3B\u9898\u5DF2\u7ECF\u5B8C\u6210\u7684\u4E0A\u4E0B\u6587\u538B\u7F29\u4E3A\u6458\u8981\uFF0C\u4E0D\u518D\u9010\u5B57\u4FDD\u7559\u7EC6\u8282\u3002
|
|
5719
|
+
- \u540C\u4E00\u4E3B\u9898\u7684\u5EF6\u7EED\uFF1A\u53EF\u4EE5\u4FDD\u7559\uFF0C\u4F46\u4ECD\u9700\u6CE8\u610F\u8FC7\u671F\u5185\u5BB9\u7684\u7D2F\u79EF\u3002
|
|
5365
5720
|
|
|
5366
|
-
|
|
5721
|
+
\u4E3B\u9898\u53D8\u5316\u662F\u6700\u660E\u786E\u3001\u6700\u5BA2\u89C2\u7684\u538B\u7F29\u89E6\u53D1\u6761\u4EF6\uFF0C\u4E0D\u8981\u9057\u6F0F\u3002
|
|
5367
5722
|
`;
|
|
5368
5723
|
|
|
5369
5724
|
// lib/prompts/iteration-nudge.ts
|
|
5370
5725
|
var ITERATION_NUDGE = `
|
|
5371
|
-
|
|
5726
|
+
\u5728\u6CA1\u6709\u65B0\u7528\u6237\u8F93\u5165\u7684\u60C5\u51B5\u4E0B\u5DF2\u7ECF\u6267\u884C\u4E86\u591A\u8F6E\u3002
|
|
5372
5727
|
|
|
5373
|
-
|
|
5374
|
-
-
|
|
5375
|
-
-
|
|
5728
|
+
\u5F53\u524D\u4EFB\u52A1\u662F\u5426\u5DF2\u7ECF\u5B8C\u6210\uFF0C\u6216\u8005\u5F53\u524D\u4E3B\u9898\u662F\u5426\u5DF2\u7ECF\u504F\u79BB\u65E9\u671F\u6B65\u9AA4\uFF1F
|
|
5729
|
+
- \u5982\u679C\u65E9\u671F\u6B65\u9AA4\u5C5E\u4E8E\u5DF2\u7ECF\u89E3\u51B3\u7684\u95EE\u9898\u6216\u5DF2\u88AB\u66FF\u4EE3\u7684\u63A2\u7D22\uFF0C\u73B0\u5728\u8C03\u7528 \`compress\` \u5C06\u5B83\u4EEC\u538B\u7F29\u4E3A\u6458\u8981\u3002
|
|
5730
|
+
- \u5982\u679C\u4ECD\u5728\u7EE7\u7EED\u540C\u4E00\u4E2A\u672A\u5B8C\u6210\u76EE\u6807\uFF0C\u800C\u4E14\u8FD8\u9700\u8981\u65E9\u671F\u4E0A\u4E0B\u6587\uFF0C\u5219\u4FDD\u7559\u8FD9\u4E9B\u5185\u5BB9\u3002
|
|
5376
5731
|
|
|
5377
|
-
|
|
5732
|
+
\u4E0D\u8981\u8BA9\u5DF2\u7ECF\u7ED3\u675F\u7684\u63A2\u7D22\u65B9\u5411\u7EE7\u7EED\u5360\u7528\u4E0A\u4E0B\u6587\u3002\u4E3B\u9898\u53D1\u751F\u504F\u79FB\u65F6\u6700\u9002\u5408\u538B\u7F29\u3002
|
|
5378
5733
|
`;
|
|
5379
5734
|
|
|
5380
5735
|
// lib/prompts/extensions/system.ts
|
|
@@ -5613,6 +5968,7 @@ var PromptStore = class {
|
|
|
5613
5968
|
paths;
|
|
5614
5969
|
customPromptsEnabled;
|
|
5615
5970
|
runtimePrompts;
|
|
5971
|
+
lastReloadAt = 0;
|
|
5616
5972
|
constructor(logger, workingDirectory, customPromptsEnabled = false) {
|
|
5617
5973
|
this.logger = logger;
|
|
5618
5974
|
this.paths = resolvePromptPaths(workingDirectory);
|
|
@@ -5627,6 +5983,9 @@ var PromptStore = class {
|
|
|
5627
5983
|
return { ...this.runtimePrompts };
|
|
5628
5984
|
}
|
|
5629
5985
|
reload() {
|
|
5986
|
+
const now = Date.now();
|
|
5987
|
+
if (now - this.lastReloadAt < 1e3) return;
|
|
5988
|
+
this.lastReloadAt = now;
|
|
5630
5989
|
const nextPrompts = createBundledRuntimePrompts();
|
|
5631
5990
|
if (!this.customPromptsEnabled) {
|
|
5632
5991
|
this.runtimePrompts = nextPrompts;
|
|
@@ -5865,13 +6224,13 @@ var stripHallucinationsFromString = (text) => {
|
|
|
5865
6224
|
};
|
|
5866
6225
|
var stripHallucinations = (messages) => {
|
|
5867
6226
|
for (const message of messages) {
|
|
6227
|
+
if (message.info.role !== "assistant") {
|
|
6228
|
+
continue;
|
|
6229
|
+
}
|
|
5868
6230
|
for (const part of message.parts) {
|
|
5869
6231
|
if (part.type === "text" && typeof part.text === "string") {
|
|
5870
6232
|
part.text = stripHallucinationsFromString(part.text);
|
|
5871
6233
|
}
|
|
5872
|
-
if (part.type === "tool" && part.state?.status === "completed" && typeof part.state.output === "string") {
|
|
5873
|
-
part.state.output = stripHallucinationsFromString(part.state.output);
|
|
5874
|
-
}
|
|
5875
6234
|
}
|
|
5876
6235
|
}
|
|
5877
6236
|
};
|
|
@@ -5966,7 +6325,8 @@ var filterCompressedRanges = (state, logger, config, messages) => {
|
|
|
5966
6325
|
return;
|
|
5967
6326
|
}
|
|
5968
6327
|
const result = [];
|
|
5969
|
-
for (
|
|
6328
|
+
for (let msgIndex = 0; msgIndex < messages.length; msgIndex++) {
|
|
6329
|
+
const msg = messages[msgIndex];
|
|
5970
6330
|
const msgId = msg.info.id;
|
|
5971
6331
|
const blockId = state.prune.messages.activeByAnchorMessageId.get(msgId);
|
|
5972
6332
|
const summary = blockId !== void 0 ? state.prune.messages.blocksById.get(blockId) : void 0;
|
|
@@ -5978,7 +6338,6 @@ var filterCompressedRanges = (state, logger, config, messages) => {
|
|
|
5978
6338
|
blockId: summary.blockId
|
|
5979
6339
|
});
|
|
5980
6340
|
} else {
|
|
5981
|
-
const msgIndex = messages.indexOf(msg);
|
|
5982
6341
|
const userMessage = getLastUserMessage(messages, msgIndex);
|
|
5983
6342
|
if (userMessage) {
|
|
5984
6343
|
const userInfo = userMessage.info;
|
|
@@ -6105,7 +6464,7 @@ var compressPermission = (state, config) => {
|
|
|
6105
6464
|
return state.compressPermission ?? config.compress.permission;
|
|
6106
6465
|
};
|
|
6107
6466
|
var syncCompressPermissionState = (state, config, hostPermissions, messages) => {
|
|
6108
|
-
const activeAgent = getLastUserMessage(messages)?.info
|
|
6467
|
+
const activeAgent = getLastUserMessage(messages)?.info?.agent;
|
|
6109
6468
|
state.compressPermission = resolveEffectiveCompressPermission(
|
|
6110
6469
|
config.compress.permission,
|
|
6111
6470
|
hostPermissions,
|
|
@@ -6243,11 +6602,13 @@ function listPriorityRefsBeforeIndex(messages, priorities, anchorIndex, priority
|
|
|
6243
6602
|
|
|
6244
6603
|
// lib/messages/inject/utils.ts
|
|
6245
6604
|
var MESSAGE_MODE_NUDGE_PRIORITY = "high";
|
|
6246
|
-
function getNudgeFrequency(
|
|
6247
|
-
|
|
6605
|
+
function getNudgeFrequency(config) {
|
|
6606
|
+
const value = config.compress.nudgeFrequency;
|
|
6607
|
+
return Number.isFinite(value) ? Math.max(1, Math.floor(value)) : 1;
|
|
6248
6608
|
}
|
|
6249
|
-
function getIterationNudgeThreshold(
|
|
6250
|
-
|
|
6609
|
+
function getIterationNudgeThreshold(config) {
|
|
6610
|
+
const value = config.compress.iterationNudgeThreshold;
|
|
6611
|
+
return Number.isFinite(value) ? Math.max(1, Math.floor(value)) : 1;
|
|
6251
6612
|
}
|
|
6252
6613
|
function findLastNonIgnoredMessage(messages) {
|
|
6253
6614
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
@@ -6523,7 +6884,11 @@ var injectCompressNudges = (state, config, logger, messages, prompts, compressio
|
|
|
6523
6884
|
state.nudges.contextLimitAnchors.clear();
|
|
6524
6885
|
state.nudges.turnNudgeAnchors.clear();
|
|
6525
6886
|
state.nudges.iterationNudgeAnchors.clear();
|
|
6526
|
-
void saveSessionState(state, logger)
|
|
6887
|
+
void saveSessionState(state, logger).catch(
|
|
6888
|
+
(error) => logger.warn("Failed to persist context-limit nudge", {
|
|
6889
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6890
|
+
})
|
|
6891
|
+
);
|
|
6527
6892
|
return;
|
|
6528
6893
|
}
|
|
6529
6894
|
const { providerId, modelId } = getModelInfo(messages);
|
|
@@ -6594,7 +6959,11 @@ var injectCompressNudges = (state, config, logger, messages, prompts, compressio
|
|
|
6594
6959
|
}
|
|
6595
6960
|
applyAnchoredNudges(state, config, messages, prompts, compressionPriorities);
|
|
6596
6961
|
if (anchorsChanged) {
|
|
6597
|
-
void saveSessionState(state, logger)
|
|
6962
|
+
void saveSessionState(state, logger).catch(
|
|
6963
|
+
(error) => logger.warn("Failed to persist compression nudge", {
|
|
6964
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6965
|
+
})
|
|
6966
|
+
);
|
|
6598
6967
|
}
|
|
6599
6968
|
};
|
|
6600
6969
|
var injectMessageIds = (state, config, messages, compressionPriorities) => {
|
|
@@ -6661,6 +7030,7 @@ var injectExtendedSubAgentResults = async (client, state, logger, messages, allo
|
|
|
6661
7030
|
if (!allowSubAgents) {
|
|
6662
7031
|
return;
|
|
6663
7032
|
}
|
|
7033
|
+
const tasks = [];
|
|
6664
7034
|
for (const message of messages) {
|
|
6665
7035
|
const parts = Array.isArray(message.parts) ? message.parts : [];
|
|
6666
7036
|
for (const part of parts) {
|
|
@@ -6673,40 +7043,43 @@ var injectExtendedSubAgentResults = async (client, state, logger, messages, allo
|
|
|
6673
7043
|
if (part.state?.status !== "completed" || typeof part.state.output !== "string") {
|
|
6674
7044
|
continue;
|
|
6675
7045
|
}
|
|
6676
|
-
|
|
6677
|
-
if (cachedResult !== void 0) {
|
|
6678
|
-
if (cachedResult) {
|
|
6679
|
-
part.state.output = stripHallucinationsFromString(
|
|
6680
|
-
mergeSubagentResult(part.state.output, cachedResult)
|
|
6681
|
-
);
|
|
6682
|
-
}
|
|
6683
|
-
continue;
|
|
6684
|
-
}
|
|
6685
|
-
const subAgentSessionId = getSubAgentId(part);
|
|
6686
|
-
if (!subAgentSessionId) {
|
|
6687
|
-
continue;
|
|
6688
|
-
}
|
|
6689
|
-
let subAgentMessages = [];
|
|
6690
|
-
try {
|
|
6691
|
-
subAgentMessages = await fetchSubAgentMessages(client, subAgentSessionId);
|
|
6692
|
-
} catch (error) {
|
|
6693
|
-
logger.warn("Failed to fetch subagent session for output expansion", {
|
|
6694
|
-
subAgentSessionId,
|
|
6695
|
-
callID: part.callID,
|
|
6696
|
-
error: error instanceof Error ? error.message : String(error)
|
|
6697
|
-
});
|
|
6698
|
-
continue;
|
|
6699
|
-
}
|
|
6700
|
-
const subAgentResultText = buildSubagentResultText(subAgentMessages);
|
|
6701
|
-
if (!subAgentResultText) {
|
|
6702
|
-
continue;
|
|
6703
|
-
}
|
|
6704
|
-
state.subAgentResultCache.set(part.callID, subAgentResultText);
|
|
6705
|
-
part.state.output = stripHallucinationsFromString(
|
|
6706
|
-
mergeSubagentResult(part.state.output, subAgentResultText)
|
|
6707
|
-
);
|
|
7046
|
+
tasks.push({ part });
|
|
6708
7047
|
}
|
|
6709
7048
|
}
|
|
7049
|
+
await runWithConcurrency(tasks, 4, async ({ part }) => {
|
|
7050
|
+
const cachedResult = getCachedSubAgentResult(state, part.callID);
|
|
7051
|
+
if (cachedResult !== void 0) {
|
|
7052
|
+
if (cachedResult) {
|
|
7053
|
+
part.state.output = stripHallucinationsFromString(
|
|
7054
|
+
mergeSubagentResult(part.state.output, cachedResult)
|
|
7055
|
+
);
|
|
7056
|
+
}
|
|
7057
|
+
return;
|
|
7058
|
+
}
|
|
7059
|
+
const subAgentSessionId = getSubAgentId(part);
|
|
7060
|
+
if (!subAgentSessionId) {
|
|
7061
|
+
return;
|
|
7062
|
+
}
|
|
7063
|
+
let subAgentMessages = [];
|
|
7064
|
+
try {
|
|
7065
|
+
subAgentMessages = await fetchSubAgentMessages(client, subAgentSessionId);
|
|
7066
|
+
} catch (error) {
|
|
7067
|
+
logger.warn("Failed to fetch subagent session for output expansion", {
|
|
7068
|
+
subAgentSessionId,
|
|
7069
|
+
callID: part.callID,
|
|
7070
|
+
error: error instanceof Error ? error.message : String(error)
|
|
7071
|
+
});
|
|
7072
|
+
return;
|
|
7073
|
+
}
|
|
7074
|
+
const subAgentResultText = buildSubagentResultText(subAgentMessages);
|
|
7075
|
+
if (!subAgentResultText) {
|
|
7076
|
+
return;
|
|
7077
|
+
}
|
|
7078
|
+
const cached = cacheSubAgentResult(state, part.callID, subAgentResultText);
|
|
7079
|
+
part.state.output = stripHallucinationsFromString(
|
|
7080
|
+
mergeSubagentResult(part.state.output, cached)
|
|
7081
|
+
);
|
|
7082
|
+
});
|
|
6710
7083
|
};
|
|
6711
7084
|
|
|
6712
7085
|
// lib/messages/reasoning-strip.ts
|
|
@@ -7294,11 +7667,7 @@ var COMPRESS_TRIGGER_PROMPT = [
|
|
|
7294
7667
|
function getTriggerPrompt(tool3, state, config, messages, userFocus) {
|
|
7295
7668
|
const base = COMPRESS_TRIGGER_PROMPT;
|
|
7296
7669
|
const compressedBlockGuidance = config.compress.mode === "message" ? "" : buildCompressedBlockGuidance(state);
|
|
7297
|
-
const availableMessageIdGuidance = buildAvailableMessageIdGuidance(
|
|
7298
|
-
state,
|
|
7299
|
-
config,
|
|
7300
|
-
messages
|
|
7301
|
-
);
|
|
7670
|
+
const availableMessageIdGuidance = buildAvailableMessageIdGuidance(state, config, messages);
|
|
7302
7671
|
const sections = [base, availableMessageIdGuidance, compressedBlockGuidance];
|
|
7303
7672
|
if (userFocus && userFocus.trim().length > 0) {
|
|
7304
7673
|
sections.push(`Additional user focus:
|
|
@@ -7811,13 +8180,14 @@ var INTERNAL_AGENT_SIGNATURES = [
|
|
|
7811
8180
|
"You are an anchored context summarization assistant for coding sessions",
|
|
7812
8181
|
"Summarize what was done in this conversation"
|
|
7813
8182
|
];
|
|
7814
|
-
function createSystemPromptHandler(
|
|
8183
|
+
function createSystemPromptHandler(target, logger, config, prompts) {
|
|
7815
8184
|
return async (input, output) => {
|
|
7816
|
-
|
|
8185
|
+
const state = input.sessionID ? resolveSessionState(target, input.sessionID) : target instanceof SessionStateStore ? void 0 : target;
|
|
8186
|
+
if (state && input.model?.limit?.context) {
|
|
7817
8187
|
state.modelContextLimit = input.model.limit.context;
|
|
7818
8188
|
logger.debug("Cached model context limit", { limit: state.modelContextLimit });
|
|
7819
8189
|
}
|
|
7820
|
-
if (state
|
|
8190
|
+
if (state?.isSubAgent && !config.experimental.allowSubAgents) {
|
|
7821
8191
|
return;
|
|
7822
8192
|
}
|
|
7823
8193
|
const systemText = output.system.join("\n");
|
|
@@ -7825,7 +8195,7 @@ function createSystemPromptHandler(state, logger, config, prompts) {
|
|
|
7825
8195
|
logger.info("Skipping DCP system prompt injection for internal agent");
|
|
7826
8196
|
return;
|
|
7827
8197
|
}
|
|
7828
|
-
const effectivePermission = input.sessionID && state
|
|
8198
|
+
const effectivePermission = input.sessionID && state?.sessionId === input.sessionID ? compressPermission(state, config) : config.compress.permission;
|
|
7829
8199
|
if (effectivePermission === "deny") {
|
|
7830
8200
|
return;
|
|
7831
8201
|
}
|
|
@@ -7834,8 +8204,8 @@ function createSystemPromptHandler(state, logger, config, prompts) {
|
|
|
7834
8204
|
const newPrompt = renderSystemPrompt(
|
|
7835
8205
|
runtimePrompts,
|
|
7836
8206
|
buildProtectedToolsExtension(config.compress.protectedTools),
|
|
7837
|
-
!!state
|
|
7838
|
-
state
|
|
8207
|
+
!!state?.manualMode,
|
|
8208
|
+
!!state?.isSubAgent && config.experimental.allowSubAgents
|
|
7839
8209
|
);
|
|
7840
8210
|
if (output.system.length > 0) {
|
|
7841
8211
|
output.system[output.system.length - 1] += "\n\n" + newPrompt;
|
|
@@ -7844,7 +8214,7 @@ function createSystemPromptHandler(state, logger, config, prompts) {
|
|
|
7844
8214
|
}
|
|
7845
8215
|
};
|
|
7846
8216
|
}
|
|
7847
|
-
function createChatMessageTransformHandler(client,
|
|
8217
|
+
function createChatMessageTransformHandler(client, target, logger, config, prompts, hostPermissions) {
|
|
7848
8218
|
return async (input, output) => {
|
|
7849
8219
|
const receivedMessages = Array.isArray(output.messages) ? output.messages.length : 0;
|
|
7850
8220
|
const messages = filterMessagesInPlace(output.messages);
|
|
@@ -7854,7 +8224,14 @@ function createChatMessageTransformHandler(client, state, logger, config, prompt
|
|
|
7854
8224
|
usable: messages.length
|
|
7855
8225
|
});
|
|
7856
8226
|
}
|
|
7857
|
-
|
|
8227
|
+
const state = await checkSession(
|
|
8228
|
+
client,
|
|
8229
|
+
target,
|
|
8230
|
+
logger,
|
|
8231
|
+
output.messages,
|
|
8232
|
+
config.manualMode.enabled
|
|
8233
|
+
);
|
|
8234
|
+
if (!state) return;
|
|
7858
8235
|
syncCompressPermissionState(state, config, hostPermissions, output.messages);
|
|
7859
8236
|
if (state.isSubAgent && !config.experimental.allowSubAgents) {
|
|
7860
8237
|
return;
|
|
@@ -7900,7 +8277,7 @@ function createChatMessageTransformHandler(client, state, logger, config, prompt
|
|
|
7900
8277
|
}
|
|
7901
8278
|
};
|
|
7902
8279
|
}
|
|
7903
|
-
function createCommandExecuteHandler(client,
|
|
8280
|
+
function createCommandExecuteHandler(client, target, logger, config, workingDirectory, hostPermissions) {
|
|
7904
8281
|
return async (input, output) => {
|
|
7905
8282
|
if (!config.commands.enabled) {
|
|
7906
8283
|
return;
|
|
@@ -7910,9 +8287,9 @@ function createCommandExecuteHandler(client, state, logger, config, workingDirec
|
|
|
7910
8287
|
path: { id: input.sessionID }
|
|
7911
8288
|
});
|
|
7912
8289
|
const messages = filterMessages(messagesResponse.data || messagesResponse);
|
|
7913
|
-
await
|
|
8290
|
+
const state = await initializeSessionState(
|
|
7914
8291
|
client,
|
|
7915
|
-
|
|
8292
|
+
target,
|
|
7916
8293
|
input.sessionID,
|
|
7917
8294
|
logger,
|
|
7918
8295
|
messages,
|
|
@@ -7997,7 +8374,7 @@ function createTextCompleteHandler() {
|
|
|
7997
8374
|
output.text = stripHallucinationsFromString(output.text);
|
|
7998
8375
|
};
|
|
7999
8376
|
}
|
|
8000
|
-
function createEventHandler(
|
|
8377
|
+
function createEventHandler(target, logger) {
|
|
8001
8378
|
return async (input) => {
|
|
8002
8379
|
const eventTime = typeof input.event?.time === "number" && Number.isFinite(input.event.time) ? input.event.time : typeof input.event?.properties?.time === "number" && Number.isFinite(input.event.properties.time) ? input.event.properties.time : void 0;
|
|
8003
8380
|
if (input.event.type !== "message.part.updated") {
|
|
@@ -8007,16 +8384,25 @@ function createEventHandler(state, logger) {
|
|
|
8007
8384
|
if (part?.type !== "tool" || part.tool !== "compress") {
|
|
8008
8385
|
return;
|
|
8009
8386
|
}
|
|
8387
|
+
if (typeof part.callID !== "string" || typeof part.messageID !== "string") {
|
|
8388
|
+
return;
|
|
8389
|
+
}
|
|
8390
|
+
const eventSessionId = typeof input.event.properties?.sessionID === "string" ? input.event.properties.sessionID : typeof part.sessionID === "string" ? part.sessionID : void 0;
|
|
8391
|
+
const state = target instanceof SessionStateStore ? target.resolveEventState(eventSessionId, part.messageID) : target;
|
|
8392
|
+
const key = buildCompressionTimingKey(part.messageID, part.callID);
|
|
8393
|
+
if (state) pruneCompressionTiming(state);
|
|
8010
8394
|
if (part.state.status === "pending") {
|
|
8011
|
-
|
|
8395
|
+
const startedAt = eventTime ?? Date.now();
|
|
8396
|
+
if (!state && target instanceof SessionStateStore) {
|
|
8397
|
+
target.recordOrphanStart(key, startedAt);
|
|
8012
8398
|
return;
|
|
8013
8399
|
}
|
|
8014
|
-
|
|
8015
|
-
const key = buildCompressionTimingKey(part.messageID, part.callID);
|
|
8400
|
+
if (!state) return;
|
|
8016
8401
|
if (state.compressionTiming.startsByCallId.has(key)) {
|
|
8017
8402
|
return;
|
|
8018
8403
|
}
|
|
8019
8404
|
state.compressionTiming.startsByCallId.set(key, startedAt);
|
|
8405
|
+
state.compressionTiming.recordedAtByCallId.set(key, Date.now());
|
|
8020
8406
|
logger.debug("Recorded compression start", {
|
|
8021
8407
|
messageID: part.messageID,
|
|
8022
8408
|
callID: part.callID,
|
|
@@ -8025,20 +8411,26 @@ function createEventHandler(state, logger) {
|
|
|
8025
8411
|
return;
|
|
8026
8412
|
}
|
|
8027
8413
|
if (part.state.status === "completed") {
|
|
8028
|
-
|
|
8029
|
-
return;
|
|
8030
|
-
}
|
|
8031
|
-
const key = buildCompressionTimingKey(part.messageID, part.callID);
|
|
8032
|
-
const start = consumeCompressionStart(state, part.messageID, part.callID);
|
|
8414
|
+
const start = state ? consumeCompressionStart(state, part.messageID, part.callID) : target instanceof SessionStateStore ? target.consumeOrphanStart(key) : void 0;
|
|
8033
8415
|
const durationMs = resolveCompressionDuration(start, eventTime, part.state.time);
|
|
8034
8416
|
if (typeof durationMs !== "number") {
|
|
8035
8417
|
return;
|
|
8036
8418
|
}
|
|
8419
|
+
if (!state && target instanceof SessionStateStore) {
|
|
8420
|
+
target.recordOrphanPending(key, {
|
|
8421
|
+
messageId: part.messageID,
|
|
8422
|
+
callId: part.callID,
|
|
8423
|
+
durationMs
|
|
8424
|
+
});
|
|
8425
|
+
return;
|
|
8426
|
+
}
|
|
8427
|
+
if (!state) return;
|
|
8037
8428
|
state.compressionTiming.pendingByCallId.set(key, {
|
|
8038
8429
|
messageId: part.messageID,
|
|
8039
8430
|
callId: part.callID,
|
|
8040
8431
|
durationMs
|
|
8041
8432
|
});
|
|
8433
|
+
state.compressionTiming.recordedAtByCallId.set(key, Date.now());
|
|
8042
8434
|
const updates = applyPendingCompressionDurations(state);
|
|
8043
8435
|
if (updates === 0) {
|
|
8044
8436
|
return;
|
|
@@ -8055,44 +8447,19 @@ function createEventHandler(state, logger) {
|
|
|
8055
8447
|
if (part.state.status === "running") {
|
|
8056
8448
|
return;
|
|
8057
8449
|
}
|
|
8058
|
-
if (
|
|
8450
|
+
if (state) {
|
|
8059
8451
|
state.compressionTiming.startsByCallId.delete(
|
|
8060
8452
|
buildCompressionTimingKey(part.messageID, part.callID)
|
|
8061
8453
|
);
|
|
8454
|
+
state.compressionTiming.recordedAtByCallId.delete(key);
|
|
8455
|
+
} else if (target instanceof SessionStateStore) {
|
|
8456
|
+
target.deleteOrphanStart(key);
|
|
8062
8457
|
}
|
|
8063
8458
|
};
|
|
8064
8459
|
}
|
|
8065
8460
|
|
|
8066
|
-
// lib/auth.ts
|
|
8067
|
-
function isSecureMode() {
|
|
8068
|
-
return !!process.env.OPENCODE_SERVER_PASSWORD;
|
|
8069
|
-
}
|
|
8070
|
-
function getAuthorizationHeader() {
|
|
8071
|
-
const password = process.env.OPENCODE_SERVER_PASSWORD;
|
|
8072
|
-
if (!password) return void 0;
|
|
8073
|
-
const username = process.env.OPENCODE_SERVER_USERNAME ?? "opencode";
|
|
8074
|
-
const credentials = Buffer.from(`${username}:${password}`).toString("base64");
|
|
8075
|
-
return `Basic ${credentials}`;
|
|
8076
|
-
}
|
|
8077
|
-
function configureClientAuth(client) {
|
|
8078
|
-
const authHeader = getAuthorizationHeader();
|
|
8079
|
-
if (!authHeader) {
|
|
8080
|
-
return client;
|
|
8081
|
-
}
|
|
8082
|
-
const innerClient = client._client || client.client;
|
|
8083
|
-
if (innerClient?.interceptors?.request) {
|
|
8084
|
-
innerClient.interceptors.request.use((request) => {
|
|
8085
|
-
if (!request.headers.has("Authorization")) {
|
|
8086
|
-
request.headers.set("Authorization", authHeader);
|
|
8087
|
-
}
|
|
8088
|
-
return request;
|
|
8089
|
-
});
|
|
8090
|
-
}
|
|
8091
|
-
return client;
|
|
8092
|
-
}
|
|
8093
|
-
|
|
8094
8461
|
// lib/update.ts
|
|
8095
|
-
import { readFile as readFile2
|
|
8462
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
8096
8463
|
import { basename, dirname as dirname3, join as join5 } from "path";
|
|
8097
8464
|
import { fileURLToPath } from "url";
|
|
8098
8465
|
var PACKAGE_NAME = "@lexwdex-org/opencode-dcp";
|
|
@@ -8101,15 +8468,16 @@ function startAutoUpdate(ctx, enabled) {
|
|
|
8101
8468
|
const controller = new AbortController();
|
|
8102
8469
|
const timeout = setTimeout(() => controller.abort(), 1e4);
|
|
8103
8470
|
void checkAutoUpdate(controller.signal).then((result) => {
|
|
8104
|
-
if (!result.
|
|
8471
|
+
if (!result.available) return;
|
|
8105
8472
|
setTimeout(() => {
|
|
8106
|
-
ctx.client.tui.showToast({
|
|
8473
|
+
void ctx.client.tui.showToast({
|
|
8107
8474
|
body: {
|
|
8108
|
-
title: "DCP update
|
|
8109
|
-
message:
|
|
8475
|
+
title: "DCP update available",
|
|
8476
|
+
message: `${result.name} ${result.latest} is available (current ${result.current}). Reinstall the plugin to update.`,
|
|
8110
8477
|
variant: "info",
|
|
8111
8478
|
duration: 7e3
|
|
8112
8479
|
}
|
|
8480
|
+
}).catch(() => {
|
|
8113
8481
|
});
|
|
8114
8482
|
}, 5e3);
|
|
8115
8483
|
}).catch(() => {
|
|
@@ -8117,25 +8485,14 @@ function startAutoUpdate(ctx, enabled) {
|
|
|
8117
8485
|
}
|
|
8118
8486
|
async function checkAutoUpdate(signal) {
|
|
8119
8487
|
const packageDir = await findPackageDir(PACKAGE_NAME);
|
|
8120
|
-
if (!packageDir) return {
|
|
8488
|
+
if (!packageDir) return { available: false };
|
|
8121
8489
|
const pkg = await readPackageJson(join5(packageDir, "package.json"));
|
|
8122
|
-
if (!pkg?.name || !pkg.version) return {
|
|
8490
|
+
if (!pkg?.name || !pkg.version) return { available: false };
|
|
8123
8491
|
const latest = await fetchLatestVersion(pkg.name, signal);
|
|
8124
|
-
if (!latest || !isVersionNewer(latest, pkg.version)) return {
|
|
8125
|
-
const
|
|
8126
|
-
if (!
|
|
8127
|
-
|
|
8128
|
-
await rm(removeDir, { recursive: true, force: true });
|
|
8129
|
-
} catch {
|
|
8130
|
-
return {
|
|
8131
|
-
updated: false,
|
|
8132
|
-
error: "remove_failed",
|
|
8133
|
-
name: pkg.name,
|
|
8134
|
-
current: pkg.version,
|
|
8135
|
-
latest
|
|
8136
|
-
};
|
|
8137
|
-
}
|
|
8138
|
-
return { updated: true, name: pkg.name, current: pkg.version, latest };
|
|
8492
|
+
if (!latest || !isVersionNewer(latest, pkg.version)) return { available: false };
|
|
8493
|
+
const wrapperDir = await findAutoUpdateWrapperDir(packageDir, pkg.name);
|
|
8494
|
+
if (!wrapperDir) return { available: false };
|
|
8495
|
+
return { available: true, name: pkg.name, current: pkg.version, latest };
|
|
8139
8496
|
}
|
|
8140
8497
|
async function findPackageDir(name) {
|
|
8141
8498
|
let dir = dirname3(fileURLToPath(import.meta.url));
|
|
@@ -8147,7 +8504,7 @@ async function findPackageDir(name) {
|
|
|
8147
8504
|
dir = parent;
|
|
8148
8505
|
}
|
|
8149
8506
|
}
|
|
8150
|
-
async function
|
|
8507
|
+
async function findAutoUpdateWrapperDir(packageDir, name) {
|
|
8151
8508
|
const packageParent = dirname3(packageDir);
|
|
8152
8509
|
const nodeModulesDir = basename(packageParent).startsWith("@") ? dirname3(packageParent) : packageParent;
|
|
8153
8510
|
if (basename(nodeModulesDir) !== "node_modules") return void 0;
|
|
@@ -8243,36 +8600,33 @@ var server = (async (ctx) => {
|
|
|
8243
8600
|
return {};
|
|
8244
8601
|
}
|
|
8245
8602
|
const logger = new Logger(config.debug);
|
|
8246
|
-
const
|
|
8603
|
+
const states = new SessionStateStore(createSessionState);
|
|
8247
8604
|
const prompts = new PromptStore(logger, ctx.directory, config.experimental.customPrompts);
|
|
8248
8605
|
const hostPermissions = {
|
|
8249
8606
|
global: void 0,
|
|
8250
8607
|
agents: {}
|
|
8251
8608
|
};
|
|
8252
|
-
if (isSecureMode()) {
|
|
8253
|
-
configureClientAuth(ctx.client);
|
|
8254
|
-
}
|
|
8255
8609
|
logger.info("DCP initialized", {
|
|
8256
8610
|
strategies: config.strategies
|
|
8257
8611
|
});
|
|
8258
8612
|
startAutoUpdate(ctx, config.autoUpdate);
|
|
8259
8613
|
const compressToolContext = {
|
|
8260
8614
|
client: ctx.client,
|
|
8261
|
-
state,
|
|
8615
|
+
state: states,
|
|
8262
8616
|
logger,
|
|
8263
8617
|
config,
|
|
8264
8618
|
prompts
|
|
8265
8619
|
};
|
|
8266
8620
|
return {
|
|
8267
8621
|
"experimental.chat.system.transform": createSystemPromptHandler(
|
|
8268
|
-
|
|
8622
|
+
states,
|
|
8269
8623
|
logger,
|
|
8270
8624
|
config,
|
|
8271
8625
|
prompts
|
|
8272
8626
|
),
|
|
8273
8627
|
"experimental.chat.messages.transform": createChatMessageTransformHandler(
|
|
8274
8628
|
ctx.client,
|
|
8275
|
-
|
|
8629
|
+
states,
|
|
8276
8630
|
logger,
|
|
8277
8631
|
config,
|
|
8278
8632
|
prompts,
|
|
@@ -8281,13 +8635,13 @@ var server = (async (ctx) => {
|
|
|
8281
8635
|
"experimental.text.complete": createTextCompleteHandler(),
|
|
8282
8636
|
"command.execute.before": createCommandExecuteHandler(
|
|
8283
8637
|
ctx.client,
|
|
8284
|
-
|
|
8638
|
+
states,
|
|
8285
8639
|
logger,
|
|
8286
8640
|
config,
|
|
8287
8641
|
ctx.directory,
|
|
8288
8642
|
hostPermissions
|
|
8289
8643
|
),
|
|
8290
|
-
event: createEventHandler(
|
|
8644
|
+
event: createEventHandler(states, logger),
|
|
8291
8645
|
tool: {
|
|
8292
8646
|
...config.compress.permission !== "deny" && {
|
|
8293
8647
|
compress: config.compress.mode === "message" ? createCompressMessageTool(compressToolContext) : createCompressRangeTool(compressToolContext)
|