@tarquinen/opencode-dcp 2.1.7 → 2.2.0-beta0
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 +30 -49
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -29
- package/dist/index.js.map +1 -1
- package/dist/lib/commands/context.d.ts.map +1 -1
- package/dist/lib/commands/context.js +36 -8
- 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 -6
- package/dist/lib/commands/help.js.map +1 -1
- package/dist/lib/commands/manual.d.ts +1 -3
- package/dist/lib/commands/manual.d.ts.map +1 -1
- package/dist/lib/commands/manual.js +4 -43
- package/dist/lib/commands/manual.js.map +1 -1
- package/dist/lib/commands/sweep.d.ts.map +1 -1
- package/dist/lib/commands/sweep.js +2 -12
- package/dist/lib/commands/sweep.js.map +1 -1
- package/dist/lib/compress-logger.d.ts +15 -0
- package/dist/lib/compress-logger.d.ts.map +1 -0
- package/dist/lib/compress-logger.js +132 -0
- package/dist/lib/compress-logger.js.map +1 -0
- package/dist/lib/config.d.ts +5 -20
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +172 -348
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/hooks.d.ts +7 -0
- package/dist/lib/hooks.d.ts.map +1 -1
- package/dist/lib/hooks.js +23 -17
- package/dist/lib/hooks.js.map +1 -1
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +6 -0
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/messages/index.d.ts +2 -3
- package/dist/lib/messages/index.d.ts.map +1 -1
- package/dist/lib/messages/index.js +2 -3
- package/dist/lib/messages/index.js.map +1 -1
- package/dist/lib/messages/inject/inject.d.ts +6 -0
- package/dist/lib/messages/inject/inject.d.ts.map +1 -0
- package/dist/lib/messages/inject/inject.js +99 -0
- package/dist/lib/messages/inject/inject.js.map +1 -0
- package/dist/lib/messages/inject/utils.d.ts +20 -0
- package/dist/lib/messages/inject/utils.d.ts.map +1 -0
- package/dist/lib/messages/inject/utils.js +137 -0
- package/dist/lib/messages/inject/utils.js.map +1 -0
- package/dist/lib/messages/utils.d.ts +7 -11
- package/dist/lib/messages/utils.d.ts.map +1 -1
- package/dist/lib/messages/utils.js +33 -132
- package/dist/lib/messages/utils.js.map +1 -1
- package/dist/lib/prompts/_codegen/system.generated.d.ts +1 -1
- package/dist/lib/prompts/_codegen/system.generated.d.ts.map +1 -1
- package/dist/lib/prompts/_codegen/system.generated.js +36 -32
- package/dist/lib/prompts/_codegen/system.generated.js.map +1 -1
- package/dist/lib/prompts/compress.d.ts +2 -0
- package/dist/lib/prompts/compress.d.ts.map +1 -0
- package/dist/lib/prompts/compress.js +122 -0
- package/dist/lib/prompts/compress.js.map +1 -0
- package/dist/lib/prompts/index.d.ts +6 -10
- package/dist/lib/prompts/index.d.ts.map +1 -1
- package/dist/lib/prompts/index.js +17 -40
- package/dist/lib/prompts/index.js.map +1 -1
- package/dist/lib/prompts/iteration-nudge.d.ts +2 -0
- package/dist/lib/prompts/iteration-nudge.d.ts.map +1 -0
- package/dist/lib/prompts/iteration-nudge.js +9 -0
- package/dist/lib/prompts/iteration-nudge.js.map +1 -0
- package/dist/lib/prompts/nudge.d.ts +2 -0
- package/dist/lib/prompts/nudge.d.ts.map +1 -0
- package/dist/lib/prompts/nudge.js +40 -0
- package/dist/lib/prompts/nudge.js.map +1 -0
- package/dist/lib/prompts/turn-nudge.d.ts +2 -0
- package/dist/lib/prompts/turn-nudge.d.ts.map +1 -0
- package/dist/lib/prompts/turn-nudge.js +12 -0
- package/dist/lib/prompts/turn-nudge.js.map +1 -0
- package/dist/lib/state/persistence.d.ts +7 -2
- package/dist/lib/state/persistence.d.ts.map +1 -1
- package/dist/lib/state/persistence.js +58 -39
- 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 +20 -8
- package/dist/lib/state/state.js.map +1 -1
- package/dist/lib/state/tool-cache.d.ts.map +1 -1
- package/dist/lib/state/tool-cache.js +3 -17
- package/dist/lib/state/tool-cache.js.map +1 -1
- package/dist/lib/state/types.d.ts +7 -8
- package/dist/lib/state/types.d.ts.map +1 -1
- package/dist/lib/state/utils.d.ts +2 -2
- package/dist/lib/state/utils.d.ts.map +1 -1
- package/dist/lib/state/utils.js +29 -19
- package/dist/lib/state/utils.js.map +1 -1
- package/dist/lib/strategies/deduplication.d.ts.map +1 -1
- package/dist/lib/strategies/deduplication.js +0 -11
- package/dist/lib/strategies/deduplication.js.map +1 -1
- package/dist/lib/strategies/index.d.ts +0 -1
- package/dist/lib/strategies/index.d.ts.map +1 -1
- package/dist/lib/strategies/index.js +0 -1
- 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 +0 -11
- 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 +0 -11
- package/dist/lib/strategies/supersede-writes.js.map +1 -1
- package/dist/lib/strategies/utils.d.ts +1 -0
- package/dist/lib/strategies/utils.d.ts.map +1 -1
- package/dist/lib/strategies/utils.js +15 -0
- package/dist/lib/strategies/utils.js.map +1 -1
- package/dist/lib/tools/compress-utils.d.ts +7 -4
- package/dist/lib/tools/compress-utils.d.ts.map +1 -1
- package/dist/lib/tools/compress-utils.js +34 -25
- package/dist/lib/tools/compress-utils.js.map +1 -1
- package/dist/lib/tools/compress.d.ts +2 -2
- package/dist/lib/tools/compress.d.ts.map +1 -1
- package/dist/lib/tools/compress.js +21 -58
- package/dist/lib/tools/compress.js.map +1 -1
- package/dist/lib/tools/index.d.ts +1 -3
- package/dist/lib/tools/index.d.ts.map +1 -1
- package/dist/lib/tools/index.js +0 -2
- package/dist/lib/tools/index.js.map +1 -1
- package/dist/lib/tools/types.d.ts +1 -1
- package/dist/lib/tools/types.d.ts.map +1 -1
- package/dist/lib/ui/notification.d.ts +2 -2
- package/dist/lib/ui/notification.d.ts.map +1 -1
- package/dist/lib/ui/notification.js +31 -28
- package/dist/lib/ui/notification.js.map +1 -1
- package/dist/lib/ui/utils.d.ts +3 -4
- package/dist/lib/ui/utils.d.ts.map +1 -1
- package/dist/lib/ui/utils.js +165 -24
- package/dist/lib/ui/utils.js.map +1 -1
- package/package.json +2 -1
- package/dist/lib/messages/inject.d.ts +0 -14
- package/dist/lib/messages/inject.d.ts.map +0 -1
- package/dist/lib/messages/inject.js +0 -266
- package/dist/lib/messages/inject.js.map +0 -1
- package/dist/lib/messages/sync.d.ts +0 -4
- package/dist/lib/messages/sync.d.ts.map +0 -1
- package/dist/lib/messages/sync.js +0 -29
- package/dist/lib/messages/sync.js.map +0 -1
- package/dist/lib/prompts/_codegen/compress-nudge.generated.d.ts +0 -2
- package/dist/lib/prompts/_codegen/compress-nudge.generated.d.ts.map +0 -1
- package/dist/lib/prompts/_codegen/compress-nudge.generated.js +0 -15
- package/dist/lib/prompts/_codegen/compress-nudge.generated.js.map +0 -1
- package/dist/lib/prompts/_codegen/compress.generated.d.ts +0 -2
- package/dist/lib/prompts/_codegen/compress.generated.d.ts.map +0 -1
- package/dist/lib/prompts/_codegen/compress.generated.js +0 -66
- package/dist/lib/prompts/_codegen/compress.generated.js.map +0 -1
- package/dist/lib/prompts/_codegen/distill.generated.d.ts +0 -2
- package/dist/lib/prompts/_codegen/distill.generated.d.ts.map +0 -1
- package/dist/lib/prompts/_codegen/distill.generated.js +0 -33
- package/dist/lib/prompts/_codegen/distill.generated.js.map +0 -1
- package/dist/lib/prompts/_codegen/nudge.generated.d.ts +0 -2
- package/dist/lib/prompts/_codegen/nudge.generated.d.ts.map +0 -1
- package/dist/lib/prompts/_codegen/nudge.generated.js +0 -17
- package/dist/lib/prompts/_codegen/nudge.generated.js.map +0 -1
- package/dist/lib/prompts/_codegen/prune.generated.d.ts +0 -2
- package/dist/lib/prompts/_codegen/prune.generated.d.ts.map +0 -1
- package/dist/lib/prompts/_codegen/prune.generated.js +0 -23
- package/dist/lib/prompts/_codegen/prune.generated.js.map +0 -1
- package/dist/lib/tools/distill.d.ts +0 -4
- package/dist/lib/tools/distill.d.ts.map +0 -1
- package/dist/lib/tools/distill.js +0 -41
- package/dist/lib/tools/distill.js.map +0 -1
- package/dist/lib/tools/prune-shared.d.ts +0 -8
- package/dist/lib/tools/prune-shared.d.ts.map +0 -1
- package/dist/lib/tools/prune-shared.js +0 -127
- package/dist/lib/tools/prune-shared.js.map +0 -1
- package/dist/lib/tools/prune.d.ts +0 -4
- package/dist/lib/tools/prune.d.ts.map +0 -1
- package/dist/lib/tools/prune.js +0 -28
- package/dist/lib/tools/prune.js.map +0 -1
package/dist/lib/config.js
CHANGED
|
@@ -6,22 +6,16 @@ const DEFAULT_PROTECTED_TOOLS = [
|
|
|
6
6
|
"task",
|
|
7
7
|
"todowrite",
|
|
8
8
|
"todoread",
|
|
9
|
-
"distill",
|
|
10
9
|
"compress",
|
|
11
|
-
"prune",
|
|
12
10
|
"batch",
|
|
13
11
|
"plan_enter",
|
|
14
12
|
"plan_exit",
|
|
15
|
-
"write",
|
|
16
|
-
"edit",
|
|
17
13
|
];
|
|
18
|
-
// Valid config keys for validation against user config
|
|
19
14
|
export const VALID_CONFIG_KEYS = new Set([
|
|
20
|
-
// Top-level keys
|
|
21
15
|
"$schema",
|
|
22
16
|
"enabled",
|
|
23
17
|
"debug",
|
|
24
|
-
"showUpdateToasts",
|
|
18
|
+
"showUpdateToasts",
|
|
25
19
|
"pruneNotification",
|
|
26
20
|
"pruneNotificationType",
|
|
27
21
|
"turnProtection",
|
|
@@ -34,43 +28,31 @@ export const VALID_CONFIG_KEYS = new Set([
|
|
|
34
28
|
"manualMode",
|
|
35
29
|
"manualMode.enabled",
|
|
36
30
|
"manualMode.automaticStrategies",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"tools.distill",
|
|
45
|
-
"tools.distill.permission",
|
|
46
|
-
"tools.distill.showDistillation",
|
|
47
|
-
"tools.compress",
|
|
48
|
-
"tools.compress.permission",
|
|
49
|
-
"tools.compress.showCompression",
|
|
50
|
-
"tools.prune",
|
|
51
|
-
"tools.prune.permission",
|
|
31
|
+
"compress",
|
|
32
|
+
"compress.permission",
|
|
33
|
+
"compress.showCompression",
|
|
34
|
+
"compress.contextLimit",
|
|
35
|
+
"compress.modelLimits",
|
|
36
|
+
"compress.nudgeFrequency",
|
|
37
|
+
"compress.iterationNudgeThreshold",
|
|
52
38
|
"strategies",
|
|
53
|
-
// strategies.deduplication
|
|
54
39
|
"strategies.deduplication",
|
|
55
40
|
"strategies.deduplication.enabled",
|
|
56
41
|
"strategies.deduplication.protectedTools",
|
|
57
|
-
// strategies.supersedeWrites
|
|
58
42
|
"strategies.supersedeWrites",
|
|
59
43
|
"strategies.supersedeWrites.enabled",
|
|
60
|
-
// strategies.purgeErrors
|
|
61
44
|
"strategies.purgeErrors",
|
|
62
45
|
"strategies.purgeErrors.enabled",
|
|
63
46
|
"strategies.purgeErrors.turns",
|
|
64
47
|
"strategies.purgeErrors.protectedTools",
|
|
65
48
|
]);
|
|
66
|
-
// Extract all key paths from a config object for validation
|
|
67
49
|
function getConfigKeyPaths(obj, prefix = "") {
|
|
68
50
|
const keys = [];
|
|
69
51
|
for (const key of Object.keys(obj)) {
|
|
70
52
|
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
71
53
|
keys.push(fullKey);
|
|
72
54
|
// modelLimits is a dynamic map keyed by providerID/modelID; do not recurse into arbitrary IDs.
|
|
73
|
-
if (fullKey === "
|
|
55
|
+
if (fullKey === "compress.modelLimits") {
|
|
74
56
|
continue;
|
|
75
57
|
}
|
|
76
58
|
if (obj[key] && typeof obj[key] === "object" && !Array.isArray(obj[key])) {
|
|
@@ -79,14 +61,12 @@ function getConfigKeyPaths(obj, prefix = "") {
|
|
|
79
61
|
}
|
|
80
62
|
return keys;
|
|
81
63
|
}
|
|
82
|
-
// Returns invalid keys found in user config
|
|
83
64
|
export function getInvalidConfigKeys(userConfig) {
|
|
84
65
|
const userKeys = getConfigKeyPaths(userConfig);
|
|
85
66
|
return userKeys.filter((key) => !VALID_CONFIG_KEYS.has(key));
|
|
86
67
|
}
|
|
87
68
|
export function validateConfigTypes(config) {
|
|
88
69
|
const errors = [];
|
|
89
|
-
// Top-level validators
|
|
90
70
|
if (config.enabled !== undefined && typeof config.enabled !== "boolean") {
|
|
91
71
|
errors.push({ key: "enabled", expected: "boolean", actual: typeof config.enabled });
|
|
92
72
|
}
|
|
@@ -129,7 +109,6 @@ export function validateConfigTypes(config) {
|
|
|
129
109
|
});
|
|
130
110
|
}
|
|
131
111
|
}
|
|
132
|
-
// Top-level turnProtection validator
|
|
133
112
|
if (config.turnProtection) {
|
|
134
113
|
if (config.turnProtection.enabled !== undefined &&
|
|
135
114
|
typeof config.turnProtection.enabled !== "boolean") {
|
|
@@ -155,10 +134,16 @@ export function validateConfigTypes(config) {
|
|
|
155
134
|
});
|
|
156
135
|
}
|
|
157
136
|
}
|
|
158
|
-
// Commands validator
|
|
159
137
|
const commands = config.commands;
|
|
160
138
|
if (commands !== undefined) {
|
|
161
|
-
if (typeof commands
|
|
139
|
+
if (typeof commands !== "object" || commands === null || Array.isArray(commands)) {
|
|
140
|
+
errors.push({
|
|
141
|
+
key: "commands",
|
|
142
|
+
expected: "object",
|
|
143
|
+
actual: typeof commands,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
162
147
|
if (commands.enabled !== undefined && typeof commands.enabled !== "boolean") {
|
|
163
148
|
errors.push({
|
|
164
149
|
key: "commands.enabled",
|
|
@@ -174,18 +159,17 @@ export function validateConfigTypes(config) {
|
|
|
174
159
|
});
|
|
175
160
|
}
|
|
176
161
|
}
|
|
177
|
-
else {
|
|
178
|
-
errors.push({
|
|
179
|
-
key: "commands",
|
|
180
|
-
expected: "{ enabled: boolean, protectedTools: string[] }",
|
|
181
|
-
actual: typeof commands,
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
162
|
}
|
|
185
|
-
// Manual mode validator
|
|
186
163
|
const manualMode = config.manualMode;
|
|
187
164
|
if (manualMode !== undefined) {
|
|
188
|
-
if (typeof manualMode
|
|
165
|
+
if (typeof manualMode !== "object" || manualMode === null || Array.isArray(manualMode)) {
|
|
166
|
+
errors.push({
|
|
167
|
+
key: "manualMode",
|
|
168
|
+
expected: "object",
|
|
169
|
+
actual: typeof manualMode,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
189
173
|
if (manualMode.enabled !== undefined && typeof manualMode.enabled !== "boolean") {
|
|
190
174
|
errors.push({
|
|
191
175
|
key: "manualMode.enabled",
|
|
@@ -202,78 +186,76 @@ export function validateConfigTypes(config) {
|
|
|
202
186
|
});
|
|
203
187
|
}
|
|
204
188
|
}
|
|
205
|
-
|
|
189
|
+
}
|
|
190
|
+
const compress = config.compress;
|
|
191
|
+
if (compress !== undefined) {
|
|
192
|
+
if (typeof compress !== "object" || compress === null || Array.isArray(compress)) {
|
|
206
193
|
errors.push({
|
|
207
|
-
key: "
|
|
208
|
-
expected: "
|
|
209
|
-
actual: typeof
|
|
194
|
+
key: "compress",
|
|
195
|
+
expected: "object",
|
|
196
|
+
actual: typeof compress,
|
|
210
197
|
});
|
|
211
198
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
if (tools) {
|
|
216
|
-
if (tools.settings) {
|
|
217
|
-
if (tools.settings.nudgeEnabled !== undefined &&
|
|
218
|
-
typeof tools.settings.nudgeEnabled !== "boolean") {
|
|
199
|
+
else {
|
|
200
|
+
if (compress.nudgeFrequency !== undefined &&
|
|
201
|
+
typeof compress.nudgeFrequency !== "number") {
|
|
219
202
|
errors.push({
|
|
220
|
-
key: "
|
|
221
|
-
expected: "
|
|
222
|
-
actual: typeof
|
|
203
|
+
key: "compress.nudgeFrequency",
|
|
204
|
+
expected: "number",
|
|
205
|
+
actual: typeof compress.nudgeFrequency,
|
|
223
206
|
});
|
|
224
207
|
}
|
|
225
|
-
if (
|
|
226
|
-
typeof tools.settings.nudgeFrequency !== "number") {
|
|
208
|
+
if (typeof compress.nudgeFrequency === "number" && compress.nudgeFrequency < 1) {
|
|
227
209
|
errors.push({
|
|
228
|
-
key: "
|
|
229
|
-
expected: "number",
|
|
230
|
-
actual:
|
|
210
|
+
key: "compress.nudgeFrequency",
|
|
211
|
+
expected: "positive number (>= 1)",
|
|
212
|
+
actual: `${compress.nudgeFrequency} (will be clamped to 1)`,
|
|
231
213
|
});
|
|
232
214
|
}
|
|
233
|
-
if (
|
|
234
|
-
|
|
215
|
+
if (compress.iterationNudgeThreshold !== undefined &&
|
|
216
|
+
typeof compress.iterationNudgeThreshold !== "number") {
|
|
235
217
|
errors.push({
|
|
236
|
-
key: "
|
|
237
|
-
expected: "
|
|
238
|
-
actual:
|
|
218
|
+
key: "compress.iterationNudgeThreshold",
|
|
219
|
+
expected: "number",
|
|
220
|
+
actual: typeof compress.iterationNudgeThreshold,
|
|
239
221
|
});
|
|
240
222
|
}
|
|
241
|
-
if (
|
|
242
|
-
|
|
223
|
+
if (typeof compress.iterationNudgeThreshold === "number" &&
|
|
224
|
+
compress.iterationNudgeThreshold < 1) {
|
|
243
225
|
errors.push({
|
|
244
|
-
key: "
|
|
245
|
-
expected: "
|
|
246
|
-
actual:
|
|
226
|
+
key: "compress.iterationNudgeThreshold",
|
|
227
|
+
expected: "positive number (>= 1)",
|
|
228
|
+
actual: `${compress.iterationNudgeThreshold} (will be clamped to 1)`,
|
|
247
229
|
});
|
|
248
230
|
}
|
|
249
|
-
if (
|
|
250
|
-
const isValidNumber = typeof
|
|
251
|
-
const isPercentString = typeof
|
|
252
|
-
tools.settings.contextLimit.endsWith("%");
|
|
231
|
+
if (compress.contextLimit !== undefined) {
|
|
232
|
+
const isValidNumber = typeof compress.contextLimit === "number";
|
|
233
|
+
const isPercentString = typeof compress.contextLimit === "string" && compress.contextLimit.endsWith("%");
|
|
253
234
|
if (!isValidNumber && !isPercentString) {
|
|
254
235
|
errors.push({
|
|
255
|
-
key: "
|
|
236
|
+
key: "compress.contextLimit",
|
|
256
237
|
expected: 'number | "${number}%"',
|
|
257
|
-
actual: JSON.stringify(
|
|
238
|
+
actual: JSON.stringify(compress.contextLimit),
|
|
258
239
|
});
|
|
259
240
|
}
|
|
260
241
|
}
|
|
261
|
-
if (
|
|
262
|
-
if (typeof
|
|
263
|
-
|
|
242
|
+
if (compress.modelLimits !== undefined) {
|
|
243
|
+
if (typeof compress.modelLimits !== "object" ||
|
|
244
|
+
compress.modelLimits === null ||
|
|
245
|
+
Array.isArray(compress.modelLimits)) {
|
|
264
246
|
errors.push({
|
|
265
|
-
key: "
|
|
247
|
+
key: "compress.modelLimits",
|
|
266
248
|
expected: "Record<string, number | ${number}%>",
|
|
267
|
-
actual: typeof
|
|
249
|
+
actual: typeof compress.modelLimits,
|
|
268
250
|
});
|
|
269
251
|
}
|
|
270
252
|
else {
|
|
271
|
-
for (const [providerModelKey, limit] of Object.entries(
|
|
253
|
+
for (const [providerModelKey, limit] of Object.entries(compress.modelLimits)) {
|
|
272
254
|
const isValidNumber = typeof limit === "number";
|
|
273
255
|
const isPercentString = typeof limit === "string" && /^\d+(?:\.\d+)?%$/.test(limit);
|
|
274
256
|
if (!isValidNumber && !isPercentString) {
|
|
275
257
|
errors.push({
|
|
276
|
-
key: `
|
|
258
|
+
key: `compress.modelLimits.${providerModelKey}`,
|
|
277
259
|
expected: 'number | "${number}%"',
|
|
278
260
|
actual: JSON.stringify(limit),
|
|
279
261
|
});
|
|
@@ -281,64 +263,26 @@ export function validateConfigTypes(config) {
|
|
|
281
263
|
}
|
|
282
264
|
}
|
|
283
265
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
actual: JSON.stringify(tools.distill.permission),
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
if (tools.distill.showDistillation !== undefined &&
|
|
296
|
-
typeof tools.distill.showDistillation !== "boolean") {
|
|
297
|
-
errors.push({
|
|
298
|
-
key: "tools.distill.showDistillation",
|
|
299
|
-
expected: "boolean",
|
|
300
|
-
actual: typeof tools.distill.showDistillation,
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
if (tools.compress) {
|
|
306
|
-
if (tools.compress.permission !== undefined) {
|
|
307
|
-
const validValues = ["ask", "allow", "deny"];
|
|
308
|
-
if (!validValues.includes(tools.compress.permission)) {
|
|
309
|
-
errors.push({
|
|
310
|
-
key: "tools.compress.permission",
|
|
311
|
-
expected: '"ask" | "allow" | "deny"',
|
|
312
|
-
actual: JSON.stringify(tools.compress.permission),
|
|
313
|
-
});
|
|
314
|
-
}
|
|
266
|
+
const validValues = ["ask", "allow", "deny"];
|
|
267
|
+
if (compress.permission !== undefined && !validValues.includes(compress.permission)) {
|
|
268
|
+
errors.push({
|
|
269
|
+
key: "compress.permission",
|
|
270
|
+
expected: '"ask" | "allow" | "deny"',
|
|
271
|
+
actual: JSON.stringify(compress.permission),
|
|
272
|
+
});
|
|
315
273
|
}
|
|
316
|
-
if (
|
|
317
|
-
typeof
|
|
274
|
+
if (compress.showCompression !== undefined &&
|
|
275
|
+
typeof compress.showCompression !== "boolean") {
|
|
318
276
|
errors.push({
|
|
319
|
-
key: "
|
|
277
|
+
key: "compress.showCompression",
|
|
320
278
|
expected: "boolean",
|
|
321
|
-
actual: typeof
|
|
279
|
+
actual: typeof compress.showCompression,
|
|
322
280
|
});
|
|
323
281
|
}
|
|
324
282
|
}
|
|
325
|
-
if (tools.prune) {
|
|
326
|
-
if (tools.prune.permission !== undefined) {
|
|
327
|
-
const validValues = ["ask", "allow", "deny"];
|
|
328
|
-
if (!validValues.includes(tools.prune.permission)) {
|
|
329
|
-
errors.push({
|
|
330
|
-
key: "tools.prune.permission",
|
|
331
|
-
expected: '"ask" | "allow" | "deny"',
|
|
332
|
-
actual: JSON.stringify(tools.prune.permission),
|
|
333
|
-
});
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
283
|
}
|
|
338
|
-
// Strategies validators
|
|
339
284
|
const strategies = config.strategies;
|
|
340
285
|
if (strategies) {
|
|
341
|
-
// deduplication
|
|
342
286
|
if (strategies.deduplication?.enabled !== undefined &&
|
|
343
287
|
typeof strategies.deduplication.enabled !== "boolean") {
|
|
344
288
|
errors.push({
|
|
@@ -355,7 +299,6 @@ export function validateConfigTypes(config) {
|
|
|
355
299
|
actual: typeof strategies.deduplication.protectedTools,
|
|
356
300
|
});
|
|
357
301
|
}
|
|
358
|
-
// supersedeWrites
|
|
359
302
|
if (strategies.supersedeWrites) {
|
|
360
303
|
if (strategies.supersedeWrites.enabled !== undefined &&
|
|
361
304
|
typeof strategies.supersedeWrites.enabled !== "boolean") {
|
|
@@ -366,7 +309,6 @@ export function validateConfigTypes(config) {
|
|
|
366
309
|
});
|
|
367
310
|
}
|
|
368
311
|
}
|
|
369
|
-
// purgeErrors
|
|
370
312
|
if (strategies.purgeErrors) {
|
|
371
313
|
if (strategies.purgeErrors.enabled !== undefined &&
|
|
372
314
|
typeof strategies.purgeErrors.enabled !== "boolean") {
|
|
@@ -405,7 +347,6 @@ export function validateConfigTypes(config) {
|
|
|
405
347
|
}
|
|
406
348
|
return errors;
|
|
407
349
|
}
|
|
408
|
-
// Show validation warnings for a config file
|
|
409
350
|
function showConfigValidationWarnings(ctx, configPath, configData, isProject) {
|
|
410
351
|
const invalidKeys = getInvalidConfigKeys(configData);
|
|
411
352
|
const typeErrors = validateConfigTypes(configData);
|
|
@@ -431,7 +372,7 @@ function showConfigValidationWarnings(ctx, configPath, configData, isProject) {
|
|
|
431
372
|
try {
|
|
432
373
|
ctx.client.tui.showToast({
|
|
433
374
|
body: {
|
|
434
|
-
title: `DCP:
|
|
375
|
+
title: `DCP: ${configType} warning`,
|
|
435
376
|
message: `${configPath}\n${messages.join("\n")}`,
|
|
436
377
|
variant: "warning",
|
|
437
378
|
duration: 7000,
|
|
@@ -459,24 +400,12 @@ const defaultConfig = {
|
|
|
459
400
|
turns: 4,
|
|
460
401
|
},
|
|
461
402
|
protectedFilePatterns: [],
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
},
|
|
469
|
-
distill: {
|
|
470
|
-
permission: "allow",
|
|
471
|
-
showDistillation: false,
|
|
472
|
-
},
|
|
473
|
-
compress: {
|
|
474
|
-
permission: "deny",
|
|
475
|
-
showCompression: false,
|
|
476
|
-
},
|
|
477
|
-
prune: {
|
|
478
|
-
permission: "allow",
|
|
479
|
-
},
|
|
403
|
+
compress: {
|
|
404
|
+
permission: "allow",
|
|
405
|
+
showCompression: false,
|
|
406
|
+
contextLimit: 100000,
|
|
407
|
+
nudgeFrequency: 5,
|
|
408
|
+
iterationNudgeThreshold: 15,
|
|
480
409
|
},
|
|
481
410
|
strategies: {
|
|
482
411
|
deduplication: {
|
|
@@ -506,50 +435,44 @@ function findOpencodeDir(startDir) {
|
|
|
506
435
|
return candidate;
|
|
507
436
|
}
|
|
508
437
|
const parent = dirname(current);
|
|
509
|
-
if (parent === current)
|
|
438
|
+
if (parent === current) {
|
|
510
439
|
break;
|
|
440
|
+
}
|
|
511
441
|
current = parent;
|
|
512
442
|
}
|
|
513
443
|
return null;
|
|
514
444
|
}
|
|
515
445
|
function getConfigPaths(ctx) {
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
globalPath = GLOBAL_CONFIG_PATH_JSON;
|
|
523
|
-
}
|
|
524
|
-
// Custom config directory: $OPENCODE_CONFIG_DIR/dcp.jsonc|json
|
|
525
|
-
let configDirPath = null;
|
|
446
|
+
const global = existsSync(GLOBAL_CONFIG_PATH_JSONC)
|
|
447
|
+
? GLOBAL_CONFIG_PATH_JSONC
|
|
448
|
+
: existsSync(GLOBAL_CONFIG_PATH_JSON)
|
|
449
|
+
? GLOBAL_CONFIG_PATH_JSON
|
|
450
|
+
: null;
|
|
451
|
+
let configDir = null;
|
|
526
452
|
const opencodeConfigDir = process.env.OPENCODE_CONFIG_DIR;
|
|
527
453
|
if (opencodeConfigDir) {
|
|
528
454
|
const configJsonc = join(opencodeConfigDir, "dcp.jsonc");
|
|
529
455
|
const configJson = join(opencodeConfigDir, "dcp.json");
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
}
|
|
456
|
+
configDir = existsSync(configJsonc)
|
|
457
|
+
? configJsonc
|
|
458
|
+
: existsSync(configJson)
|
|
459
|
+
? configJson
|
|
460
|
+
: null;
|
|
536
461
|
}
|
|
537
|
-
|
|
538
|
-
let projectPath = null;
|
|
462
|
+
let project = null;
|
|
539
463
|
if (ctx?.directory) {
|
|
540
464
|
const opencodeDir = findOpencodeDir(ctx.directory);
|
|
541
465
|
if (opencodeDir) {
|
|
542
466
|
const projectJsonc = join(opencodeDir, "dcp.jsonc");
|
|
543
467
|
const projectJson = join(opencodeDir, "dcp.json");
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
}
|
|
468
|
+
project = existsSync(projectJsonc)
|
|
469
|
+
? projectJsonc
|
|
470
|
+
: existsSync(projectJson)
|
|
471
|
+
? projectJson
|
|
472
|
+
: null;
|
|
550
473
|
}
|
|
551
474
|
}
|
|
552
|
-
return { global
|
|
475
|
+
return { global, configDir, project };
|
|
553
476
|
}
|
|
554
477
|
function createDefaultConfig() {
|
|
555
478
|
if (!existsSync(GLOBAL_CONFIG_DIR)) {
|
|
@@ -562,16 +485,15 @@ function createDefaultConfig() {
|
|
|
562
485
|
writeFileSync(GLOBAL_CONFIG_PATH_JSONC, configContent, "utf-8");
|
|
563
486
|
}
|
|
564
487
|
function loadConfigFile(configPath) {
|
|
565
|
-
let fileContent;
|
|
488
|
+
let fileContent = "";
|
|
566
489
|
try {
|
|
567
490
|
fileContent = readFileSync(configPath, "utf-8");
|
|
568
491
|
}
|
|
569
492
|
catch {
|
|
570
|
-
// File doesn't exist or can't be read - not a parse error
|
|
571
493
|
return { data: null };
|
|
572
494
|
}
|
|
573
495
|
try {
|
|
574
|
-
const parsed = parse(fileContent);
|
|
496
|
+
const parsed = parse(fileContent, undefined, { allowTrailingComma: true });
|
|
575
497
|
if (parsed === undefined || parsed === null) {
|
|
576
498
|
return { data: null, parseError: "Config file is empty or invalid" };
|
|
577
499
|
}
|
|
@@ -582,8 +504,9 @@ function loadConfigFile(configPath) {
|
|
|
582
504
|
}
|
|
583
505
|
}
|
|
584
506
|
function mergeStrategies(base, override) {
|
|
585
|
-
if (!override)
|
|
507
|
+
if (!override) {
|
|
586
508
|
return base;
|
|
509
|
+
}
|
|
587
510
|
return {
|
|
588
511
|
deduplication: {
|
|
589
512
|
enabled: override.deduplication?.enabled ?? base.deduplication.enabled,
|
|
@@ -609,38 +532,23 @@ function mergeStrategies(base, override) {
|
|
|
609
532
|
},
|
|
610
533
|
};
|
|
611
534
|
}
|
|
612
|
-
function
|
|
613
|
-
if (!override)
|
|
535
|
+
function mergeCompress(base, override) {
|
|
536
|
+
if (!override) {
|
|
614
537
|
return base;
|
|
538
|
+
}
|
|
615
539
|
return {
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
...(override.settings?.protectedTools ?? []),
|
|
623
|
-
]),
|
|
624
|
-
],
|
|
625
|
-
contextLimit: override.settings?.contextLimit ?? base.settings.contextLimit,
|
|
626
|
-
modelLimits: override.settings?.modelLimits ?? base.settings.modelLimits,
|
|
627
|
-
},
|
|
628
|
-
distill: {
|
|
629
|
-
permission: override.distill?.permission ?? base.distill.permission,
|
|
630
|
-
showDistillation: override.distill?.showDistillation ?? base.distill.showDistillation,
|
|
631
|
-
},
|
|
632
|
-
compress: {
|
|
633
|
-
permission: override.compress?.permission ?? base.compress.permission,
|
|
634
|
-
showCompression: override.compress?.showCompression ?? base.compress.showCompression,
|
|
635
|
-
},
|
|
636
|
-
prune: {
|
|
637
|
-
permission: override.prune?.permission ?? base.prune.permission,
|
|
638
|
-
},
|
|
540
|
+
permission: override.permission ?? base.permission,
|
|
541
|
+
showCompression: override.showCompression ?? base.showCompression,
|
|
542
|
+
contextLimit: override.contextLimit ?? base.contextLimit,
|
|
543
|
+
modelLimits: override.modelLimits ?? base.modelLimits,
|
|
544
|
+
nudgeFrequency: override.nudgeFrequency ?? base.nudgeFrequency,
|
|
545
|
+
iterationNudgeThreshold: override.iterationNudgeThreshold ?? base.iterationNudgeThreshold,
|
|
639
546
|
};
|
|
640
547
|
}
|
|
641
548
|
function mergeCommands(base, override) {
|
|
642
|
-
if (override
|
|
549
|
+
if (!override) {
|
|
643
550
|
return base;
|
|
551
|
+
}
|
|
644
552
|
return {
|
|
645
553
|
enabled: override.enabled ?? base.enabled,
|
|
646
554
|
protectedTools: [...new Set([...base.protectedTools, ...(override.protectedTools ?? [])])],
|
|
@@ -667,24 +575,16 @@ function deepCloneConfig(config) {
|
|
|
667
575
|
},
|
|
668
576
|
turnProtection: { ...config.turnProtection },
|
|
669
577
|
protectedFilePatterns: [...config.protectedFilePatterns],
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
protectedTools: [...config.tools.settings.protectedTools],
|
|
674
|
-
modelLimits: { ...config.tools.settings.modelLimits },
|
|
675
|
-
},
|
|
676
|
-
distill: { ...config.tools.distill },
|
|
677
|
-
compress: { ...config.tools.compress },
|
|
678
|
-
prune: { ...config.tools.prune },
|
|
578
|
+
compress: {
|
|
579
|
+
...config.compress,
|
|
580
|
+
modelLimits: { ...config.compress.modelLimits },
|
|
679
581
|
},
|
|
680
582
|
strategies: {
|
|
681
583
|
deduplication: {
|
|
682
584
|
...config.strategies.deduplication,
|
|
683
585
|
protectedTools: [...config.strategies.deduplication.protectedTools],
|
|
684
586
|
},
|
|
685
|
-
supersedeWrites: {
|
|
686
|
-
...config.strategies.supersedeWrites,
|
|
687
|
-
},
|
|
587
|
+
supersedeWrites: { ...config.strategies.supersedeWrites },
|
|
688
588
|
purgeErrors: {
|
|
689
589
|
...config.strategies.purgeErrors,
|
|
690
590
|
protectedTools: [...config.strategies.purgeErrors.protectedTools],
|
|
@@ -692,141 +592,65 @@ function deepCloneConfig(config) {
|
|
|
692
592
|
},
|
|
693
593
|
};
|
|
694
594
|
}
|
|
595
|
+
function mergeLayer(config, data) {
|
|
596
|
+
return {
|
|
597
|
+
enabled: data.enabled ?? config.enabled,
|
|
598
|
+
debug: data.debug ?? config.debug,
|
|
599
|
+
pruneNotification: data.pruneNotification ?? config.pruneNotification,
|
|
600
|
+
pruneNotificationType: data.pruneNotificationType ?? config.pruneNotificationType,
|
|
601
|
+
commands: mergeCommands(config.commands, data.commands),
|
|
602
|
+
manualMode: mergeManualMode(config.manualMode, data.manualMode),
|
|
603
|
+
turnProtection: {
|
|
604
|
+
enabled: data.turnProtection?.enabled ?? config.turnProtection.enabled,
|
|
605
|
+
turns: data.turnProtection?.turns ?? config.turnProtection.turns,
|
|
606
|
+
},
|
|
607
|
+
protectedFilePatterns: [
|
|
608
|
+
...new Set([...config.protectedFilePatterns, ...(data.protectedFilePatterns ?? [])]),
|
|
609
|
+
],
|
|
610
|
+
compress: mergeCompress(config.compress, data.compress),
|
|
611
|
+
strategies: mergeStrategies(config.strategies, data.strategies),
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
function scheduleParseWarning(ctx, title, message) {
|
|
615
|
+
setTimeout(() => {
|
|
616
|
+
try {
|
|
617
|
+
ctx.client.tui.showToast({
|
|
618
|
+
body: {
|
|
619
|
+
title,
|
|
620
|
+
message,
|
|
621
|
+
variant: "warning",
|
|
622
|
+
duration: 7000,
|
|
623
|
+
},
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
catch { }
|
|
627
|
+
}, 7000);
|
|
628
|
+
}
|
|
695
629
|
export function getConfig(ctx) {
|
|
696
630
|
let config = deepCloneConfig(defaultConfig);
|
|
697
631
|
const configPaths = getConfigPaths(ctx);
|
|
698
|
-
|
|
699
|
-
if (configPaths.global) {
|
|
700
|
-
const result = loadConfigFile(configPaths.global);
|
|
701
|
-
if (result.parseError) {
|
|
702
|
-
setTimeout(async () => {
|
|
703
|
-
try {
|
|
704
|
-
ctx.client.tui.showToast({
|
|
705
|
-
body: {
|
|
706
|
-
title: "DCP: Invalid config",
|
|
707
|
-
message: `${configPaths.global}\n${result.parseError}\nUsing default values`,
|
|
708
|
-
variant: "warning",
|
|
709
|
-
duration: 7000,
|
|
710
|
-
},
|
|
711
|
-
});
|
|
712
|
-
}
|
|
713
|
-
catch { }
|
|
714
|
-
}, 7000);
|
|
715
|
-
}
|
|
716
|
-
else if (result.data) {
|
|
717
|
-
// Validate config keys and types
|
|
718
|
-
showConfigValidationWarnings(ctx, configPaths.global, result.data, false);
|
|
719
|
-
config = {
|
|
720
|
-
enabled: result.data.enabled ?? config.enabled,
|
|
721
|
-
debug: result.data.debug ?? config.debug,
|
|
722
|
-
pruneNotification: result.data.pruneNotification ?? config.pruneNotification,
|
|
723
|
-
pruneNotificationType: result.data.pruneNotificationType ?? config.pruneNotificationType,
|
|
724
|
-
commands: mergeCommands(config.commands, result.data.commands),
|
|
725
|
-
manualMode: mergeManualMode(config.manualMode, result.data.manualMode),
|
|
726
|
-
turnProtection: {
|
|
727
|
-
enabled: result.data.turnProtection?.enabled ?? config.turnProtection.enabled,
|
|
728
|
-
turns: result.data.turnProtection?.turns ?? config.turnProtection.turns,
|
|
729
|
-
},
|
|
730
|
-
protectedFilePatterns: [
|
|
731
|
-
...new Set([
|
|
732
|
-
...config.protectedFilePatterns,
|
|
733
|
-
...(result.data.protectedFilePatterns ?? []),
|
|
734
|
-
]),
|
|
735
|
-
],
|
|
736
|
-
tools: mergeTools(config.tools, result.data.tools),
|
|
737
|
-
strategies: mergeStrategies(config.strategies, result.data.strategies),
|
|
738
|
-
};
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
else {
|
|
742
|
-
// No config exists, create default
|
|
632
|
+
if (!configPaths.global) {
|
|
743
633
|
createDefaultConfig();
|
|
744
634
|
}
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
title: "DCP: Invalid configDir config",
|
|
754
|
-
message: `${configPaths.configDir}\n${result.parseError}\nUsing global/default values`,
|
|
755
|
-
variant: "warning",
|
|
756
|
-
duration: 7000,
|
|
757
|
-
},
|
|
758
|
-
});
|
|
759
|
-
}
|
|
760
|
-
catch { }
|
|
761
|
-
}, 7000);
|
|
762
|
-
}
|
|
763
|
-
else if (result.data) {
|
|
764
|
-
// Validate config keys and types
|
|
765
|
-
showConfigValidationWarnings(ctx, configPaths.configDir, result.data, true);
|
|
766
|
-
config = {
|
|
767
|
-
enabled: result.data.enabled ?? config.enabled,
|
|
768
|
-
debug: result.data.debug ?? config.debug,
|
|
769
|
-
pruneNotification: result.data.pruneNotification ?? config.pruneNotification,
|
|
770
|
-
pruneNotificationType: result.data.pruneNotificationType ?? config.pruneNotificationType,
|
|
771
|
-
commands: mergeCommands(config.commands, result.data.commands),
|
|
772
|
-
manualMode: mergeManualMode(config.manualMode, result.data.manualMode),
|
|
773
|
-
turnProtection: {
|
|
774
|
-
enabled: result.data.turnProtection?.enabled ?? config.turnProtection.enabled,
|
|
775
|
-
turns: result.data.turnProtection?.turns ?? config.turnProtection.turns,
|
|
776
|
-
},
|
|
777
|
-
protectedFilePatterns: [
|
|
778
|
-
...new Set([
|
|
779
|
-
...config.protectedFilePatterns,
|
|
780
|
-
...(result.data.protectedFilePatterns ?? []),
|
|
781
|
-
]),
|
|
782
|
-
],
|
|
783
|
-
tools: mergeTools(config.tools, result.data.tools),
|
|
784
|
-
strategies: mergeStrategies(config.strategies, result.data.strategies),
|
|
785
|
-
};
|
|
635
|
+
const layers = [
|
|
636
|
+
{ path: configPaths.global, name: "config", isProject: false },
|
|
637
|
+
{ path: configPaths.configDir, name: "configDir config", isProject: true },
|
|
638
|
+
{ path: configPaths.project, name: "project config", isProject: true },
|
|
639
|
+
];
|
|
640
|
+
for (const layer of layers) {
|
|
641
|
+
if (!layer.path) {
|
|
642
|
+
continue;
|
|
786
643
|
}
|
|
787
|
-
|
|
788
|
-
// Load and merge project config (overrides global)
|
|
789
|
-
if (configPaths.project) {
|
|
790
|
-
const result = loadConfigFile(configPaths.project);
|
|
644
|
+
const result = loadConfigFile(layer.path);
|
|
791
645
|
if (result.parseError) {
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
ctx.client.tui.showToast({
|
|
795
|
-
body: {
|
|
796
|
-
title: "DCP: Invalid project config",
|
|
797
|
-
message: `${configPaths.project}\n${result.parseError}\nUsing global/default values`,
|
|
798
|
-
variant: "warning",
|
|
799
|
-
duration: 7000,
|
|
800
|
-
},
|
|
801
|
-
});
|
|
802
|
-
}
|
|
803
|
-
catch { }
|
|
804
|
-
}, 7000);
|
|
646
|
+
scheduleParseWarning(ctx, `DCP: Invalid ${layer.name}`, `${layer.path}\n${result.parseError}\nUsing previous/default values`);
|
|
647
|
+
continue;
|
|
805
648
|
}
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
showConfigValidationWarnings(ctx, configPaths.project, result.data, true);
|
|
809
|
-
config = {
|
|
810
|
-
enabled: result.data.enabled ?? config.enabled,
|
|
811
|
-
debug: result.data.debug ?? config.debug,
|
|
812
|
-
pruneNotification: result.data.pruneNotification ?? config.pruneNotification,
|
|
813
|
-
pruneNotificationType: result.data.pruneNotificationType ?? config.pruneNotificationType,
|
|
814
|
-
commands: mergeCommands(config.commands, result.data.commands),
|
|
815
|
-
manualMode: mergeManualMode(config.manualMode, result.data.manualMode),
|
|
816
|
-
turnProtection: {
|
|
817
|
-
enabled: result.data.turnProtection?.enabled ?? config.turnProtection.enabled,
|
|
818
|
-
turns: result.data.turnProtection?.turns ?? config.turnProtection.turns,
|
|
819
|
-
},
|
|
820
|
-
protectedFilePatterns: [
|
|
821
|
-
...new Set([
|
|
822
|
-
...config.protectedFilePatterns,
|
|
823
|
-
...(result.data.protectedFilePatterns ?? []),
|
|
824
|
-
]),
|
|
825
|
-
],
|
|
826
|
-
tools: mergeTools(config.tools, result.data.tools),
|
|
827
|
-
strategies: mergeStrategies(config.strategies, result.data.strategies),
|
|
828
|
-
};
|
|
649
|
+
if (!result.data) {
|
|
650
|
+
continue;
|
|
829
651
|
}
|
|
652
|
+
showConfigValidationWarnings(ctx, layer.path, result.data, layer.isProject);
|
|
653
|
+
config = mergeLayer(config, result.data);
|
|
830
654
|
}
|
|
831
655
|
return config;
|
|
832
656
|
}
|