@tuanhung303/opencode-acp 2.2.0 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +131 -71
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/commands/budget.d.ts +15 -0
- package/dist/lib/commands/budget.d.ts.map +1 -0
- package/dist/lib/commands/budget.js +120 -0
- package/dist/lib/commands/budget.js.map +1 -0
- package/dist/lib/commands/context.d.ts +1 -1
- package/dist/lib/commands/context.js +4 -4
- package/dist/lib/commands/context.js.map +1 -1
- package/dist/lib/commands/help.d.ts.map +1 -1
- package/dist/lib/commands/help.js +2 -0
- package/dist/lib/commands/help.js.map +1 -1
- package/dist/lib/commands/protected.d.ts +17 -0
- package/dist/lib/commands/protected.d.ts.map +1 -0
- package/dist/lib/commands/protected.js +50 -0
- package/dist/lib/commands/protected.js.map +1 -0
- package/dist/lib/commands/stats.d.ts +1 -1
- package/dist/lib/commands/stats.d.ts.map +1 -1
- package/dist/lib/commands/stats.js +24 -4
- package/dist/lib/commands/stats.js.map +1 -1
- package/dist/lib/commands/sweep.d.ts.map +1 -1
- package/dist/lib/commands/sweep.js +5 -2
- package/dist/lib/commands/sweep.js.map +1 -1
- package/dist/lib/config-schema.d.ts +119 -0
- package/dist/lib/config-schema.d.ts.map +1 -0
- package/dist/lib/config-schema.js +97 -0
- package/dist/lib/config-schema.js.map +1 -0
- package/dist/lib/config.d.ts +7 -30
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +45 -483
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/hooks.d.ts +14 -0
- package/dist/lib/hooks.d.ts.map +1 -1
- package/dist/lib/hooks.js +120 -13
- package/dist/lib/hooks.js.map +1 -1
- package/dist/lib/logger.d.ts +25 -1
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +45 -4
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/messages/index.d.ts +1 -1
- package/dist/lib/messages/index.d.ts.map +1 -1
- package/dist/lib/messages/index.js +1 -1
- package/dist/lib/messages/index.js.map +1 -1
- package/dist/lib/messages/inject.d.ts +6 -1
- package/dist/lib/messages/inject.d.ts.map +1 -1
- package/dist/lib/messages/inject.js +8 -125
- package/dist/lib/messages/inject.js.map +1 -1
- package/dist/lib/messages/prune.d.ts +8 -0
- package/dist/lib/messages/prune.d.ts.map +1 -1
- package/dist/lib/messages/prune.js +89 -2
- package/dist/lib/messages/prune.js.map +1 -1
- package/dist/lib/messages/utils.d.ts +12 -0
- package/dist/lib/messages/utils.d.ts.map +1 -1
- package/dist/lib/messages/utils.js +34 -0
- package/dist/lib/messages/utils.js.map +1 -1
- package/dist/lib/prompts/discard-tool-spec.d.ts +1 -1
- package/dist/lib/prompts/discard-tool-spec.d.ts.map +1 -1
- package/dist/lib/prompts/discard-tool-spec.js +30 -17
- package/dist/lib/prompts/discard-tool-spec.js.map +1 -1
- package/dist/lib/prompts/extract-tool-spec.d.ts +1 -1
- package/dist/lib/prompts/extract-tool-spec.d.ts.map +1 -1
- package/dist/lib/prompts/extract-tool-spec.js +19 -11
- package/dist/lib/prompts/extract-tool-spec.js.map +1 -1
- package/dist/lib/prompts/index.d.ts.map +1 -1
- package/dist/lib/prompts/index.js +2 -7
- package/dist/lib/prompts/index.js.map +1 -1
- package/dist/lib/prompts/restore-tool-spec.d.ts +2 -0
- package/dist/lib/prompts/restore-tool-spec.d.ts.map +1 -0
- package/dist/lib/prompts/restore-tool-spec.js +37 -0
- package/dist/lib/prompts/restore-tool-spec.js.map +1 -0
- package/dist/lib/prompts/system/both.d.ts +1 -1
- package/dist/lib/prompts/system/both.d.ts.map +1 -1
- package/dist/lib/prompts/system/both.js +20 -16
- package/dist/lib/prompts/system/both.js.map +1 -1
- package/dist/lib/prompts/system/discard.d.ts +1 -1
- package/dist/lib/prompts/system/discard.d.ts.map +1 -1
- package/dist/lib/prompts/system/discard.js +19 -16
- package/dist/lib/prompts/system/discard.js.map +1 -1
- package/dist/lib/prompts/system/extract.d.ts +1 -1
- package/dist/lib/prompts/system/extract.d.ts.map +1 -1
- package/dist/lib/prompts/system/extract.js +19 -16
- package/dist/lib/prompts/system/extract.js.map +1 -1
- package/dist/lib/protected-file-patterns.js +1 -1
- package/dist/lib/protected-file-patterns.js.map +1 -1
- package/dist/lib/safe-execute.d.ts +20 -0
- package/dist/lib/safe-execute.d.ts.map +1 -0
- package/dist/lib/safe-execute.js +38 -0
- package/dist/lib/safe-execute.js.map +1 -0
- package/dist/lib/shared-utils.js +1 -1
- package/dist/lib/shared-utils.js.map +1 -1
- package/dist/lib/state/persistence.d.ts +6 -1
- package/dist/lib/state/persistence.d.ts.map +1 -1
- package/dist/lib/state/persistence.js +59 -1
- package/dist/lib/state/persistence.js.map +1 -1
- package/dist/lib/state/state.d.ts.map +1 -1
- package/dist/lib/state/state.js +54 -3
- package/dist/lib/state/state.js.map +1 -1
- package/dist/lib/state/tool-cache.d.ts +2 -0
- package/dist/lib/state/tool-cache.d.ts.map +1 -1
- package/dist/lib/state/tool-cache.js +34 -12
- package/dist/lib/state/tool-cache.js.map +1 -1
- package/dist/lib/state/types.d.ts +50 -5
- package/dist/lib/state/types.d.ts.map +1 -1
- package/dist/lib/strategies/deduplication.d.ts +1 -0
- package/dist/lib/strategies/deduplication.d.ts.map +1 -1
- package/dist/lib/strategies/deduplication.js +87 -3
- package/dist/lib/strategies/deduplication.js.map +1 -1
- package/dist/lib/strategies/index.d.ts +1 -5
- package/dist/lib/strategies/index.d.ts.map +1 -1
- package/dist/lib/strategies/index.js +1 -5
- package/dist/lib/strategies/index.js.map +1 -1
- package/dist/lib/strategies/purge-errors.d.ts.map +1 -1
- package/dist/lib/strategies/purge-errors.js +4 -1
- package/dist/lib/strategies/purge-errors.js.map +1 -1
- package/dist/lib/strategies/supersede-writes.d.ts.map +1 -1
- package/dist/lib/strategies/supersede-writes.js +7 -1
- package/dist/lib/strategies/supersede-writes.js.map +1 -1
- package/dist/lib/strategies/tools.d.ts +1 -0
- package/dist/lib/strategies/tools.d.ts.map +1 -1
- package/dist/lib/strategies/tools.js +215 -62
- package/dist/lib/strategies/tools.js.map +1 -1
- package/dist/lib/ui/notification.d.ts +5 -2
- package/dist/lib/ui/notification.d.ts.map +1 -1
- package/dist/lib/ui/notification.js +10 -6
- package/dist/lib/ui/notification.js.map +1 -1
- package/dist/lib/ui/utils.d.ts +3 -3
- package/dist/lib/ui/utils.d.ts.map +1 -1
- package/dist/lib/ui/utils.js +38 -12
- package/dist/lib/ui/utils.js.map +1 -1
- package/package.json +7 -12
- package/dist/lib/prompts/nudge/both.d.ts +0 -2
- package/dist/lib/prompts/nudge/both.d.ts.map +0 -1
- package/dist/lib/prompts/nudge/both.js +0 -11
- package/dist/lib/prompts/nudge/both.js.map +0 -1
- package/dist/lib/prompts/nudge/discard.d.ts +0 -2
- package/dist/lib/prompts/nudge/discard.d.ts.map +0 -1
- package/dist/lib/prompts/nudge/discard.js +0 -10
- package/dist/lib/prompts/nudge/discard.js.map +0 -1
- package/dist/lib/prompts/nudge/extract.d.ts +0 -2
- package/dist/lib/prompts/nudge/extract.d.ts.map +0 -1
- package/dist/lib/prompts/nudge/extract.js +0 -10
- package/dist/lib/prompts/nudge/extract.js.map +0 -1
- package/dist/lib/strategies/head-tail-truncation.d.ts +0 -15
- package/dist/lib/strategies/head-tail-truncation.d.ts.map +0 -1
- package/dist/lib/strategies/head-tail-truncation.js +0 -144
- package/dist/lib/strategies/head-tail-truncation.js.map +0 -1
- package/dist/lib/strategies/placeholder-compression.d.ts +0 -5
- package/dist/lib/strategies/placeholder-compression.d.ts.map +0 -1
- package/dist/lib/strategies/placeholder-compression.js +0 -148
- package/dist/lib/strategies/placeholder-compression.js.map +0 -1
- package/dist/lib/strategies/prune-thinking.d.ts +0 -15
- package/dist/lib/strategies/prune-thinking.d.ts.map +0 -1
- package/dist/lib/strategies/prune-thinking.js +0 -79
- package/dist/lib/strategies/prune-thinking.js.map +0 -1
- package/dist/lib/strategies/read-consolidation.d.ts +0 -21
- package/dist/lib/strategies/read-consolidation.d.ts.map +0 -1
- package/dist/lib/strategies/read-consolidation.js +0 -155
- package/dist/lib/strategies/read-consolidation.js.map +0 -1
package/dist/lib/config.js
CHANGED
|
@@ -2,7 +2,17 @@ import { readFileSync, writeFileSync, existsSync, mkdirSync, statSync } from "fs
|
|
|
2
2
|
import { join, dirname } from "path";
|
|
3
3
|
import { homedir } from "os";
|
|
4
4
|
import { parse } from "jsonc-parser";
|
|
5
|
+
import { validateConfig, getUnknownKeys } from "./config-schema";
|
|
6
|
+
/**
|
|
7
|
+
* Tools that should never be pruned.
|
|
8
|
+
*
|
|
9
|
+
* - `context_info`: Synthetic tool used to inject prunable-tools context
|
|
10
|
+
* for DeepSeek/Kimi models. Must be protected to prevent self-pruning
|
|
11
|
+
* which would break the context management feedback loop.
|
|
12
|
+
* See lib/messages/utils.ts createSyntheticToolPart()
|
|
13
|
+
*/
|
|
5
14
|
const DEFAULT_PROTECTED_TOOLS = [
|
|
15
|
+
"context_info", // Synthetic tool for context injection
|
|
6
16
|
"task",
|
|
7
17
|
"todowrite",
|
|
8
18
|
"todoread",
|
|
@@ -14,417 +24,26 @@ const DEFAULT_PROTECTED_TOOLS = [
|
|
|
14
24
|
"plan_enter",
|
|
15
25
|
"plan_exit",
|
|
16
26
|
];
|
|
17
|
-
//
|
|
18
|
-
export const VALID_CONFIG_KEYS = new Set([
|
|
19
|
-
// Top-level keys
|
|
20
|
-
"$schema",
|
|
21
|
-
"enabled",
|
|
22
|
-
"debug",
|
|
23
|
-
"showUpdateToasts", // Deprecated but kept for backwards compatibility
|
|
24
|
-
"pruneNotification",
|
|
25
|
-
"turnProtection",
|
|
26
|
-
"turnProtection.enabled",
|
|
27
|
-
"turnProtection.turns",
|
|
28
|
-
"protectedFilePatterns",
|
|
29
|
-
"commands",
|
|
30
|
-
"commands.enabled",
|
|
31
|
-
"commands.protectedTools",
|
|
32
|
-
"tools",
|
|
33
|
-
"tools.settings",
|
|
34
|
-
"tools.settings.nudgeEnabled",
|
|
35
|
-
"tools.settings.nudgeFrequency",
|
|
36
|
-
"tools.settings.protectedTools",
|
|
37
|
-
"tools.discard",
|
|
38
|
-
"tools.discard.enabled",
|
|
39
|
-
"tools.extract",
|
|
40
|
-
"tools.extract.enabled",
|
|
41
|
-
"tools.extract.showDistillation",
|
|
42
|
-
"strategies",
|
|
43
|
-
// strategies.deduplication
|
|
44
|
-
"strategies.deduplication",
|
|
45
|
-
"strategies.deduplication.enabled",
|
|
46
|
-
"strategies.deduplication.protectedTools",
|
|
47
|
-
// strategies.supersedeWrites
|
|
48
|
-
"strategies.supersedeWrites",
|
|
49
|
-
"strategies.supersedeWrites.enabled",
|
|
50
|
-
// strategies.purgeErrors
|
|
51
|
-
"strategies.purgeErrors",
|
|
52
|
-
"strategies.purgeErrors.enabled",
|
|
53
|
-
"strategies.purgeErrors.turns",
|
|
54
|
-
"strategies.purgeErrors.protectedTools",
|
|
55
|
-
// strategies.pruneThinking
|
|
56
|
-
"strategies.pruneThinking",
|
|
57
|
-
"strategies.pruneThinking.enabled",
|
|
58
|
-
"strategies.pruneThinking.delayTurns",
|
|
59
|
-
// strategies.placeholderCompression
|
|
60
|
-
"strategies.placeholderCompression",
|
|
61
|
-
"strategies.placeholderCompression.enabled",
|
|
62
|
-
"strategies.placeholderCompression.delayTurns",
|
|
63
|
-
"strategies.placeholderCompression.minOutputTokens",
|
|
64
|
-
"strategies.placeholderCompression.protectedTools",
|
|
65
|
-
// strategies.headTailTruncation
|
|
66
|
-
"strategies.headTailTruncation",
|
|
67
|
-
"strategies.headTailTruncation.enabled",
|
|
68
|
-
"strategies.headTailTruncation.delayTurns",
|
|
69
|
-
"strategies.headTailTruncation.headRatio",
|
|
70
|
-
"strategies.headTailTruncation.tailRatio",
|
|
71
|
-
"strategies.headTailTruncation.protectedTools",
|
|
72
|
-
// strategies.readConsolidation
|
|
73
|
-
"strategies.readConsolidation",
|
|
74
|
-
"strategies.readConsolidation.enabled",
|
|
75
|
-
"strategies.readConsolidation.tools",
|
|
76
|
-
]);
|
|
77
|
-
// Extract all key paths from a config object for validation
|
|
78
|
-
function getConfigKeyPaths(obj, prefix = "") {
|
|
79
|
-
const keys = [];
|
|
80
|
-
for (const key of Object.keys(obj)) {
|
|
81
|
-
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
82
|
-
keys.push(fullKey);
|
|
83
|
-
if (obj[key] && typeof obj[key] === "object" && !Array.isArray(obj[key])) {
|
|
84
|
-
keys.push(...getConfigKeyPaths(obj[key], fullKey));
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
return keys;
|
|
88
|
-
}
|
|
89
|
-
// Returns invalid keys found in user config
|
|
90
|
-
export function getInvalidConfigKeys(userConfig) {
|
|
91
|
-
const userKeys = getConfigKeyPaths(userConfig);
|
|
92
|
-
return userKeys.filter((key) => !VALID_CONFIG_KEYS.has(key));
|
|
93
|
-
}
|
|
94
|
-
function validateConfigTypes(config) {
|
|
95
|
-
const errors = [];
|
|
96
|
-
// Top-level validators
|
|
97
|
-
if (config.enabled !== undefined && typeof config.enabled !== "boolean") {
|
|
98
|
-
errors.push({ key: "enabled", expected: "boolean", actual: typeof config.enabled });
|
|
99
|
-
}
|
|
100
|
-
if (config.debug !== undefined && typeof config.debug !== "boolean") {
|
|
101
|
-
errors.push({ key: "debug", expected: "boolean", actual: typeof config.debug });
|
|
102
|
-
}
|
|
103
|
-
if (config.pruneNotification !== undefined) {
|
|
104
|
-
const validValues = ["off", "minimal", "detailed"];
|
|
105
|
-
if (!validValues.includes(config.pruneNotification)) {
|
|
106
|
-
errors.push({
|
|
107
|
-
key: "pruneNotification",
|
|
108
|
-
expected: '"off" | "minimal" | "detailed"',
|
|
109
|
-
actual: JSON.stringify(config.pruneNotification),
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
if (config.protectedFilePatterns !== undefined) {
|
|
114
|
-
if (!Array.isArray(config.protectedFilePatterns)) {
|
|
115
|
-
errors.push({
|
|
116
|
-
key: "protectedFilePatterns",
|
|
117
|
-
expected: "string[]",
|
|
118
|
-
actual: typeof config.protectedFilePatterns,
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
else if (!config.protectedFilePatterns.every((v) => typeof v === "string")) {
|
|
122
|
-
errors.push({
|
|
123
|
-
key: "protectedFilePatterns",
|
|
124
|
-
expected: "string[]",
|
|
125
|
-
actual: "non-string entries",
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
// Top-level turnProtection validator
|
|
130
|
-
if (config.turnProtection) {
|
|
131
|
-
if (config.turnProtection.enabled !== undefined &&
|
|
132
|
-
typeof config.turnProtection.enabled !== "boolean") {
|
|
133
|
-
errors.push({
|
|
134
|
-
key: "turnProtection.enabled",
|
|
135
|
-
expected: "boolean",
|
|
136
|
-
actual: typeof config.turnProtection.enabled,
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
if (config.turnProtection.turns !== undefined &&
|
|
140
|
-
typeof config.turnProtection.turns !== "number") {
|
|
141
|
-
errors.push({
|
|
142
|
-
key: "turnProtection.turns",
|
|
143
|
-
expected: "number",
|
|
144
|
-
actual: typeof config.turnProtection.turns,
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
// Commands validator
|
|
149
|
-
const commands = config.commands;
|
|
150
|
-
if (commands !== undefined) {
|
|
151
|
-
if (typeof commands === "object") {
|
|
152
|
-
if (commands.enabled !== undefined && typeof commands.enabled !== "boolean") {
|
|
153
|
-
errors.push({
|
|
154
|
-
key: "commands.enabled",
|
|
155
|
-
expected: "boolean",
|
|
156
|
-
actual: typeof commands.enabled,
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
if (commands.protectedTools !== undefined && !Array.isArray(commands.protectedTools)) {
|
|
160
|
-
errors.push({
|
|
161
|
-
key: "commands.protectedTools",
|
|
162
|
-
expected: "string[]",
|
|
163
|
-
actual: typeof commands.protectedTools,
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
errors.push({
|
|
169
|
-
key: "commands",
|
|
170
|
-
expected: "{ enabled: boolean, protectedTools: string[] }",
|
|
171
|
-
actual: typeof commands,
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
// Tools validators
|
|
176
|
-
const tools = config.tools;
|
|
177
|
-
if (tools) {
|
|
178
|
-
if (tools.settings) {
|
|
179
|
-
if (tools.settings.nudgeEnabled !== undefined &&
|
|
180
|
-
typeof tools.settings.nudgeEnabled !== "boolean") {
|
|
181
|
-
errors.push({
|
|
182
|
-
key: "tools.settings.nudgeEnabled",
|
|
183
|
-
expected: "boolean",
|
|
184
|
-
actual: typeof tools.settings.nudgeEnabled,
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
if (tools.settings.nudgeFrequency !== undefined &&
|
|
188
|
-
typeof tools.settings.nudgeFrequency !== "number") {
|
|
189
|
-
errors.push({
|
|
190
|
-
key: "tools.settings.nudgeFrequency",
|
|
191
|
-
expected: "number",
|
|
192
|
-
actual: typeof tools.settings.nudgeFrequency,
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
if (tools.settings.protectedTools !== undefined &&
|
|
196
|
-
!Array.isArray(tools.settings.protectedTools)) {
|
|
197
|
-
errors.push({
|
|
198
|
-
key: "tools.settings.protectedTools",
|
|
199
|
-
expected: "string[]",
|
|
200
|
-
actual: typeof tools.settings.protectedTools,
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
if (tools.discard) {
|
|
205
|
-
if (tools.discard.enabled !== undefined && typeof tools.discard.enabled !== "boolean") {
|
|
206
|
-
errors.push({
|
|
207
|
-
key: "tools.discard.enabled",
|
|
208
|
-
expected: "boolean",
|
|
209
|
-
actual: typeof tools.discard.enabled,
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
if (tools.extract) {
|
|
214
|
-
if (tools.extract.enabled !== undefined && typeof tools.extract.enabled !== "boolean") {
|
|
215
|
-
errors.push({
|
|
216
|
-
key: "tools.extract.enabled",
|
|
217
|
-
expected: "boolean",
|
|
218
|
-
actual: typeof tools.extract.enabled,
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
if (tools.extract.showDistillation !== undefined &&
|
|
222
|
-
typeof tools.extract.showDistillation !== "boolean") {
|
|
223
|
-
errors.push({
|
|
224
|
-
key: "tools.extract.showDistillation",
|
|
225
|
-
expected: "boolean",
|
|
226
|
-
actual: typeof tools.extract.showDistillation,
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
// Strategies validators
|
|
232
|
-
const strategies = config.strategies;
|
|
233
|
-
if (strategies) {
|
|
234
|
-
// deduplication
|
|
235
|
-
if (strategies.deduplication?.enabled !== undefined &&
|
|
236
|
-
typeof strategies.deduplication.enabled !== "boolean") {
|
|
237
|
-
errors.push({
|
|
238
|
-
key: "strategies.deduplication.enabled",
|
|
239
|
-
expected: "boolean",
|
|
240
|
-
actual: typeof strategies.deduplication.enabled,
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
if (strategies.deduplication?.protectedTools !== undefined &&
|
|
244
|
-
!Array.isArray(strategies.deduplication.protectedTools)) {
|
|
245
|
-
errors.push({
|
|
246
|
-
key: "strategies.deduplication.protectedTools",
|
|
247
|
-
expected: "string[]",
|
|
248
|
-
actual: typeof strategies.deduplication.protectedTools,
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
// supersedeWrites
|
|
252
|
-
if (strategies.supersedeWrites) {
|
|
253
|
-
if (strategies.supersedeWrites.enabled !== undefined &&
|
|
254
|
-
typeof strategies.supersedeWrites.enabled !== "boolean") {
|
|
255
|
-
errors.push({
|
|
256
|
-
key: "strategies.supersedeWrites.enabled",
|
|
257
|
-
expected: "boolean",
|
|
258
|
-
actual: typeof strategies.supersedeWrites.enabled,
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
// purgeErrors
|
|
263
|
-
if (strategies.purgeErrors) {
|
|
264
|
-
if (strategies.purgeErrors.enabled !== undefined &&
|
|
265
|
-
typeof strategies.purgeErrors.enabled !== "boolean") {
|
|
266
|
-
errors.push({
|
|
267
|
-
key: "strategies.purgeErrors.enabled",
|
|
268
|
-
expected: "boolean",
|
|
269
|
-
actual: typeof strategies.purgeErrors.enabled,
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
if (strategies.purgeErrors.turns !== undefined &&
|
|
273
|
-
typeof strategies.purgeErrors.turns !== "number") {
|
|
274
|
-
errors.push({
|
|
275
|
-
key: "strategies.purgeErrors.turns",
|
|
276
|
-
expected: "number",
|
|
277
|
-
actual: typeof strategies.purgeErrors.turns,
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
if (strategies.purgeErrors.protectedTools !== undefined &&
|
|
281
|
-
!Array.isArray(strategies.purgeErrors.protectedTools)) {
|
|
282
|
-
errors.push({
|
|
283
|
-
key: "strategies.purgeErrors.protectedTools",
|
|
284
|
-
expected: "string[]",
|
|
285
|
-
actual: typeof strategies.purgeErrors.protectedTools,
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
// pruneThinking
|
|
290
|
-
if (strategies.pruneThinking) {
|
|
291
|
-
if (strategies.pruneThinking.enabled !== undefined &&
|
|
292
|
-
typeof strategies.pruneThinking.enabled !== "boolean") {
|
|
293
|
-
errors.push({
|
|
294
|
-
key: "strategies.pruneThinking.enabled",
|
|
295
|
-
expected: "boolean",
|
|
296
|
-
actual: typeof strategies.pruneThinking.enabled,
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
if (strategies.pruneThinking.delayTurns !== undefined &&
|
|
300
|
-
typeof strategies.pruneThinking.delayTurns !== "number") {
|
|
301
|
-
errors.push({
|
|
302
|
-
key: "strategies.pruneThinking.delayTurns",
|
|
303
|
-
expected: "number",
|
|
304
|
-
actual: typeof strategies.pruneThinking.delayTurns,
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
// placeholderCompression
|
|
309
|
-
if (strategies.placeholderCompression) {
|
|
310
|
-
if (strategies.placeholderCompression.enabled !== undefined &&
|
|
311
|
-
typeof strategies.placeholderCompression.enabled !== "boolean") {
|
|
312
|
-
errors.push({
|
|
313
|
-
key: "strategies.placeholderCompression.enabled",
|
|
314
|
-
expected: "boolean",
|
|
315
|
-
actual: typeof strategies.placeholderCompression.enabled,
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
if (strategies.placeholderCompression.delayTurns !== undefined &&
|
|
319
|
-
typeof strategies.placeholderCompression.delayTurns !== "number") {
|
|
320
|
-
errors.push({
|
|
321
|
-
key: "strategies.placeholderCompression.delayTurns",
|
|
322
|
-
expected: "number",
|
|
323
|
-
actual: typeof strategies.placeholderCompression.delayTurns,
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
if (strategies.placeholderCompression.minOutputTokens !== undefined &&
|
|
327
|
-
typeof strategies.placeholderCompression.minOutputTokens !== "number") {
|
|
328
|
-
errors.push({
|
|
329
|
-
key: "strategies.placeholderCompression.minOutputTokens",
|
|
330
|
-
expected: "number",
|
|
331
|
-
actual: typeof strategies.placeholderCompression.minOutputTokens,
|
|
332
|
-
});
|
|
333
|
-
}
|
|
334
|
-
if (strategies.placeholderCompression.protectedTools !== undefined &&
|
|
335
|
-
!Array.isArray(strategies.placeholderCompression.protectedTools)) {
|
|
336
|
-
errors.push({
|
|
337
|
-
key: "strategies.placeholderCompression.protectedTools",
|
|
338
|
-
expected: "string[]",
|
|
339
|
-
actual: typeof strategies.placeholderCompression.protectedTools,
|
|
340
|
-
});
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
// headTailTruncation
|
|
344
|
-
if (strategies.headTailTruncation) {
|
|
345
|
-
if (strategies.headTailTruncation.enabled !== undefined &&
|
|
346
|
-
typeof strategies.headTailTruncation.enabled !== "boolean") {
|
|
347
|
-
errors.push({
|
|
348
|
-
key: "strategies.headTailTruncation.enabled",
|
|
349
|
-
expected: "boolean",
|
|
350
|
-
actual: typeof strategies.headTailTruncation.enabled,
|
|
351
|
-
});
|
|
352
|
-
}
|
|
353
|
-
if (strategies.headTailTruncation.delayTurns !== undefined &&
|
|
354
|
-
typeof strategies.headTailTruncation.delayTurns !== "number") {
|
|
355
|
-
errors.push({
|
|
356
|
-
key: "strategies.headTailTruncation.delayTurns",
|
|
357
|
-
expected: "number",
|
|
358
|
-
actual: typeof strategies.headTailTruncation.delayTurns,
|
|
359
|
-
});
|
|
360
|
-
}
|
|
361
|
-
if (strategies.headTailTruncation.headRatio !== undefined &&
|
|
362
|
-
typeof strategies.headTailTruncation.headRatio !== "number") {
|
|
363
|
-
errors.push({
|
|
364
|
-
key: "strategies.headTailTruncation.headRatio",
|
|
365
|
-
expected: "number",
|
|
366
|
-
actual: typeof strategies.headTailTruncation.headRatio,
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
if (strategies.headTailTruncation.tailRatio !== undefined &&
|
|
370
|
-
typeof strategies.headTailTruncation.tailRatio !== "number") {
|
|
371
|
-
errors.push({
|
|
372
|
-
key: "strategies.headTailTruncation.tailRatio",
|
|
373
|
-
expected: "number",
|
|
374
|
-
actual: typeof strategies.headTailTruncation.tailRatio,
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
if (strategies.headTailTruncation.protectedTools !== undefined &&
|
|
378
|
-
!Array.isArray(strategies.headTailTruncation.protectedTools)) {
|
|
379
|
-
errors.push({
|
|
380
|
-
key: "strategies.headTailTruncation.protectedTools",
|
|
381
|
-
expected: "string[]",
|
|
382
|
-
actual: typeof strategies.headTailTruncation.protectedTools,
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
// readConsolidation
|
|
387
|
-
if (strategies.readConsolidation) {
|
|
388
|
-
if (strategies.readConsolidation.enabled !== undefined &&
|
|
389
|
-
typeof strategies.readConsolidation.enabled !== "boolean") {
|
|
390
|
-
errors.push({
|
|
391
|
-
key: "strategies.readConsolidation.enabled",
|
|
392
|
-
expected: "boolean",
|
|
393
|
-
actual: typeof strategies.readConsolidation.enabled,
|
|
394
|
-
});
|
|
395
|
-
}
|
|
396
|
-
if (strategies.readConsolidation.tools !== undefined &&
|
|
397
|
-
!Array.isArray(strategies.readConsolidation.tools)) {
|
|
398
|
-
errors.push({
|
|
399
|
-
key: "strategies.readConsolidation.tools",
|
|
400
|
-
expected: "string[]",
|
|
401
|
-
actual: typeof strategies.readConsolidation.tools,
|
|
402
|
-
});
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
return errors;
|
|
407
|
-
}
|
|
408
|
-
// Show validation warnings for a config file
|
|
27
|
+
// Show validation warnings for a config file using Zod schema
|
|
409
28
|
function showConfigValidationWarnings(ctx, configPath, configData, isProject) {
|
|
410
|
-
const
|
|
411
|
-
const
|
|
412
|
-
if (
|
|
29
|
+
const validationErrors = validateConfig(configData);
|
|
30
|
+
const unknownKeys = getUnknownKeys(configData);
|
|
31
|
+
if (validationErrors.length === 0 && unknownKeys.length === 0) {
|
|
413
32
|
return;
|
|
414
33
|
}
|
|
415
34
|
const configType = isProject ? "project config" : "config";
|
|
416
35
|
const messages = [];
|
|
417
|
-
if (
|
|
418
|
-
const keyList =
|
|
419
|
-
const suffix =
|
|
36
|
+
if (unknownKeys.length > 0) {
|
|
37
|
+
const keyList = unknownKeys.slice(0, 3).join(", ");
|
|
38
|
+
const suffix = unknownKeys.length > 3 ? ` (+${unknownKeys.length - 3} more)` : "";
|
|
420
39
|
messages.push(`Unknown keys: ${keyList}${suffix}`);
|
|
421
40
|
}
|
|
422
|
-
if (
|
|
423
|
-
for (const err of
|
|
424
|
-
messages.push(
|
|
41
|
+
if (validationErrors.length > 0) {
|
|
42
|
+
for (const err of validationErrors.slice(0, 2)) {
|
|
43
|
+
messages.push(err);
|
|
425
44
|
}
|
|
426
|
-
if (
|
|
427
|
-
messages.push(`(+${
|
|
45
|
+
if (validationErrors.length > 2) {
|
|
46
|
+
messages.push(`(+${validationErrors.length - 2} more validation errors)`);
|
|
428
47
|
}
|
|
429
48
|
}
|
|
430
49
|
setTimeout(() => {
|
|
@@ -441,10 +60,11 @@ function showConfigValidationWarnings(ctx, configPath, configData, isProject) {
|
|
|
441
60
|
catch { }
|
|
442
61
|
}, 7000);
|
|
443
62
|
}
|
|
444
|
-
|
|
63
|
+
const defaultConfig = {
|
|
445
64
|
enabled: true,
|
|
446
65
|
debug: false,
|
|
447
66
|
pruneNotification: "detailed",
|
|
67
|
+
autoPruneAfterTool: true,
|
|
448
68
|
commands: {
|
|
449
69
|
enabled: true,
|
|
450
70
|
protectedTools: [...DEFAULT_PROTECTED_TOOLS],
|
|
@@ -453,11 +73,22 @@ export const DEFAULT_CONFIG = {
|
|
|
453
73
|
enabled: false,
|
|
454
74
|
turns: 4,
|
|
455
75
|
},
|
|
456
|
-
protectedFilePatterns: [
|
|
76
|
+
protectedFilePatterns: [
|
|
77
|
+
// Environment and secrets
|
|
78
|
+
"**/.env",
|
|
79
|
+
"**/.env.*",
|
|
80
|
+
"**/credentials.json",
|
|
81
|
+
"**/secrets.json",
|
|
82
|
+
"**/*.pem",
|
|
83
|
+
"**/*.key",
|
|
84
|
+
// Config files users likely want to keep visible
|
|
85
|
+
"**/package.json",
|
|
86
|
+
"**/tsconfig.json",
|
|
87
|
+
"**/pyproject.toml",
|
|
88
|
+
"**/Cargo.toml",
|
|
89
|
+
],
|
|
457
90
|
tools: {
|
|
458
91
|
settings: {
|
|
459
|
-
nudgeEnabled: true,
|
|
460
|
-
nudgeFrequency: 5,
|
|
461
92
|
protectedTools: [...DEFAULT_PROTECTED_TOOLS],
|
|
462
93
|
},
|
|
463
94
|
discard: {
|
|
@@ -474,34 +105,13 @@ export const DEFAULT_CONFIG = {
|
|
|
474
105
|
protectedTools: [],
|
|
475
106
|
},
|
|
476
107
|
supersedeWrites: {
|
|
477
|
-
enabled: true,
|
|
478
|
-
},
|
|
479
|
-
purgeErrors: {
|
|
480
|
-
enabled: true,
|
|
481
|
-
turns: 2,
|
|
482
|
-
protectedTools: [],
|
|
483
|
-
},
|
|
484
|
-
pruneThinking: {
|
|
485
|
-
enabled: true,
|
|
486
|
-
delayTurns: 1,
|
|
487
|
-
},
|
|
488
|
-
placeholderCompression: {
|
|
489
108
|
enabled: false,
|
|
490
|
-
delayTurns: 2,
|
|
491
|
-
minOutputTokens: 100,
|
|
492
|
-
protectedTools: [],
|
|
493
109
|
},
|
|
494
|
-
|
|
110
|
+
purgeErrors: {
|
|
495
111
|
enabled: true,
|
|
496
|
-
|
|
497
|
-
headRatio: 0.2,
|
|
498
|
-
tailRatio: 0.3,
|
|
112
|
+
turns: 4,
|
|
499
113
|
protectedTools: [],
|
|
500
114
|
},
|
|
501
|
-
readConsolidation: {
|
|
502
|
-
enabled: true,
|
|
503
|
-
tools: ["read", "glob", "grep", "webfetch", "bash"],
|
|
504
|
-
},
|
|
505
115
|
},
|
|
506
116
|
};
|
|
507
117
|
const GLOBAL_CONFIG_DIR = join(homedir(), ".config", "opencode");
|
|
@@ -565,7 +175,7 @@ function createDefaultConfig() {
|
|
|
565
175
|
mkdirSync(GLOBAL_CONFIG_DIR, { recursive: true });
|
|
566
176
|
}
|
|
567
177
|
const configContent = `{
|
|
568
|
-
"$schema": "https://raw.githubusercontent.com/
|
|
178
|
+
"$schema": "https://raw.githubusercontent.com/opencode-acp/opencode-acp/master/acp.schema.json"
|
|
569
179
|
}
|
|
570
180
|
`;
|
|
571
181
|
writeFileSync(GLOBAL_CONFIG_PATH_JSONC, configContent, "utf-8");
|
|
@@ -616,39 +226,6 @@ function mergeStrategies(base, override) {
|
|
|
616
226
|
]),
|
|
617
227
|
],
|
|
618
228
|
},
|
|
619
|
-
pruneThinking: {
|
|
620
|
-
enabled: override.pruneThinking?.enabled ?? base.pruneThinking.enabled,
|
|
621
|
-
delayTurns: override.pruneThinking?.delayTurns ?? base.pruneThinking.delayTurns,
|
|
622
|
-
},
|
|
623
|
-
placeholderCompression: {
|
|
624
|
-
enabled: override.placeholderCompression?.enabled ?? base.placeholderCompression.enabled,
|
|
625
|
-
delayTurns: override.placeholderCompression?.delayTurns ??
|
|
626
|
-
base.placeholderCompression.delayTurns,
|
|
627
|
-
minOutputTokens: override.placeholderCompression?.minOutputTokens ??
|
|
628
|
-
base.placeholderCompression.minOutputTokens,
|
|
629
|
-
protectedTools: [
|
|
630
|
-
...new Set([
|
|
631
|
-
...base.placeholderCompression.protectedTools,
|
|
632
|
-
...(override.placeholderCompression?.protectedTools ?? []),
|
|
633
|
-
]),
|
|
634
|
-
],
|
|
635
|
-
},
|
|
636
|
-
headTailTruncation: {
|
|
637
|
-
enabled: override.headTailTruncation?.enabled ?? base.headTailTruncation.enabled,
|
|
638
|
-
delayTurns: override.headTailTruncation?.delayTurns ?? base.headTailTruncation.delayTurns,
|
|
639
|
-
headRatio: override.headTailTruncation?.headRatio ?? base.headTailTruncation.headRatio,
|
|
640
|
-
tailRatio: override.headTailTruncation?.tailRatio ?? base.headTailTruncation.tailRatio,
|
|
641
|
-
protectedTools: [
|
|
642
|
-
...new Set([
|
|
643
|
-
...base.headTailTruncation.protectedTools,
|
|
644
|
-
...(override.headTailTruncation?.protectedTools ?? []),
|
|
645
|
-
]),
|
|
646
|
-
],
|
|
647
|
-
},
|
|
648
|
-
readConsolidation: {
|
|
649
|
-
enabled: override.readConsolidation?.enabled ?? base.readConsolidation.enabled,
|
|
650
|
-
tools: override.readConsolidation?.tools ?? base.readConsolidation.tools,
|
|
651
|
-
},
|
|
652
229
|
};
|
|
653
230
|
}
|
|
654
231
|
function mergeTools(base, override) {
|
|
@@ -656,8 +233,6 @@ function mergeTools(base, override) {
|
|
|
656
233
|
return base;
|
|
657
234
|
return {
|
|
658
235
|
settings: {
|
|
659
|
-
nudgeEnabled: override.settings?.nudgeEnabled ?? base.settings.nudgeEnabled,
|
|
660
|
-
nudgeFrequency: override.settings?.nudgeFrequency ?? base.settings.nudgeFrequency,
|
|
661
236
|
protectedTools: [
|
|
662
237
|
...new Set([
|
|
663
238
|
...base.settings.protectedTools,
|
|
@@ -693,7 +268,6 @@ function deepCloneConfig(config) {
|
|
|
693
268
|
protectedFilePatterns: [...config.protectedFilePatterns],
|
|
694
269
|
tools: {
|
|
695
270
|
settings: {
|
|
696
|
-
...config.tools.settings,
|
|
697
271
|
protectedTools: [...config.tools.settings.protectedTools],
|
|
698
272
|
},
|
|
699
273
|
discard: { ...config.tools.discard },
|
|
@@ -711,26 +285,11 @@ function deepCloneConfig(config) {
|
|
|
711
285
|
...config.strategies.purgeErrors,
|
|
712
286
|
protectedTools: [...config.strategies.purgeErrors.protectedTools],
|
|
713
287
|
},
|
|
714
|
-
pruneThinking: {
|
|
715
|
-
...config.strategies.pruneThinking,
|
|
716
|
-
},
|
|
717
|
-
placeholderCompression: {
|
|
718
|
-
...config.strategies.placeholderCompression,
|
|
719
|
-
protectedTools: [...config.strategies.placeholderCompression.protectedTools],
|
|
720
|
-
},
|
|
721
|
-
headTailTruncation: {
|
|
722
|
-
...config.strategies.headTailTruncation,
|
|
723
|
-
protectedTools: [...config.strategies.headTailTruncation.protectedTools],
|
|
724
|
-
},
|
|
725
|
-
readConsolidation: {
|
|
726
|
-
...config.strategies.readConsolidation,
|
|
727
|
-
tools: [...config.strategies.readConsolidation.tools],
|
|
728
|
-
},
|
|
729
288
|
},
|
|
730
289
|
};
|
|
731
290
|
}
|
|
732
291
|
export function getConfig(ctx) {
|
|
733
|
-
let config = deepCloneConfig(
|
|
292
|
+
let config = deepCloneConfig(defaultConfig);
|
|
734
293
|
const configPaths = getConfigPaths(ctx);
|
|
735
294
|
// Load and merge global config
|
|
736
295
|
if (configPaths.global) {
|
|
@@ -757,6 +316,7 @@ export function getConfig(ctx) {
|
|
|
757
316
|
enabled: result.data.enabled ?? config.enabled,
|
|
758
317
|
debug: result.data.debug ?? config.debug,
|
|
759
318
|
pruneNotification: result.data.pruneNotification ?? config.pruneNotification,
|
|
319
|
+
autoPruneAfterTool: result.data.autoPruneAfterTool ?? config.autoPruneAfterTool,
|
|
760
320
|
commands: mergeCommands(config.commands, result.data.commands),
|
|
761
321
|
turnProtection: {
|
|
762
322
|
enabled: result.data.turnProtection?.enabled ?? config.turnProtection.enabled,
|
|
@@ -802,6 +362,7 @@ export function getConfig(ctx) {
|
|
|
802
362
|
enabled: result.data.enabled ?? config.enabled,
|
|
803
363
|
debug: result.data.debug ?? config.debug,
|
|
804
364
|
pruneNotification: result.data.pruneNotification ?? config.pruneNotification,
|
|
365
|
+
autoPruneAfterTool: result.data.autoPruneAfterTool ?? config.autoPruneAfterTool,
|
|
805
366
|
commands: mergeCommands(config.commands, result.data.commands),
|
|
806
367
|
turnProtection: {
|
|
807
368
|
enabled: result.data.turnProtection?.enabled ?? config.turnProtection.enabled,
|
|
@@ -843,6 +404,7 @@ export function getConfig(ctx) {
|
|
|
843
404
|
enabled: result.data.enabled ?? config.enabled,
|
|
844
405
|
debug: result.data.debug ?? config.debug,
|
|
845
406
|
pruneNotification: result.data.pruneNotification ?? config.pruneNotification,
|
|
407
|
+
autoPruneAfterTool: result.data.autoPruneAfterTool ?? config.autoPruneAfterTool,
|
|
846
408
|
commands: mergeCommands(config.commands, result.data.commands),
|
|
847
409
|
turnProtection: {
|
|
848
410
|
enabled: result.data.turnProtection?.enabled ?? config.turnProtection.enabled,
|