log-llm-config-staging 1.3.93 → 1.3.94
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.
|
@@ -165,6 +165,21 @@ function deepEqual(a, b) {
|
|
|
165
165
|
function isStringArray(v) {
|
|
166
166
|
return Array.isArray(v) && v.every((x) => typeof x === 'string');
|
|
167
167
|
}
|
|
168
|
+
function escapeRegExp(s) {
|
|
169
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
170
|
+
}
|
|
171
|
+
/** Match Cursor yolo allowlist entries (same boundary idea as server filter_yolo_allowlist_entries). */
|
|
172
|
+
function allowlistEntryMatchesRemoveToken(entry, token) {
|
|
173
|
+
const valStr = String(entry).toLowerCase();
|
|
174
|
+
const t = token.toLowerCase().trim();
|
|
175
|
+
if (!t)
|
|
176
|
+
return false;
|
|
177
|
+
const first = valStr.trim().split(/\s+/)[0] ?? '';
|
|
178
|
+
if (first === t || valStr === t)
|
|
179
|
+
return true;
|
|
180
|
+
const pattern = new RegExp(`(^|[^a-z0-9_|])${escapeRegExp(t)}([^a-z0-9_|]|$)`);
|
|
181
|
+
return pattern.test(valStr);
|
|
182
|
+
}
|
|
168
183
|
function verifyOpsApplied(configJson, settingPath, ops) {
|
|
169
184
|
const parts = settingPath.split('.');
|
|
170
185
|
const leafKey = parts[parts.length - 1] ?? '';
|
|
@@ -186,7 +201,14 @@ function verifyOpsApplied(configJson, settingPath, ops) {
|
|
|
186
201
|
const curArr = Array.isArray(cur) ? cur : [];
|
|
187
202
|
const toAdd = add[k] ?? [];
|
|
188
203
|
const toRemove = remove[k] ?? [];
|
|
204
|
+
const isYoloAllowlist = leafKey === 'yoloCommandAllowlist' || targetPath.endsWith('.yoloCommandAllowlist');
|
|
189
205
|
for (const item of toRemove) {
|
|
206
|
+
if (isYoloAllowlist) {
|
|
207
|
+
if (curArr.some((entry) => allowlistEntryMatchesRemoveToken(entry, String(item)))) {
|
|
208
|
+
return { ok: false, expected: { op: 'remove', path: targetPath, value: item } };
|
|
209
|
+
}
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
190
212
|
if (curArr.some((curItem) => deepEqual(curItem, item))) {
|
|
191
213
|
return { ok: false, expected: { op: 'remove', path: targetPath, value: item } };
|
|
192
214
|
}
|
|
@@ -428,6 +428,23 @@ function applyCheck(configJson, check) {
|
|
|
428
428
|
}
|
|
429
429
|
setByPath(configJson, check.setting_path, value);
|
|
430
430
|
}
|
|
431
|
+
// ---------------------------------------------------------------------------
|
|
432
|
+
// SQLite remediation support
|
|
433
|
+
// ---------------------------------------------------------------------------
|
|
434
|
+
function escapeRegExpForAllowlist(s) {
|
|
435
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
436
|
+
}
|
|
437
|
+
function allowlistEntryMatchesRemoveToken(entry, token) {
|
|
438
|
+
const valStr = String(entry).toLowerCase();
|
|
439
|
+
const t = token.toLowerCase().trim();
|
|
440
|
+
if (!t)
|
|
441
|
+
return false;
|
|
442
|
+
const first = valStr.trim().split(/\s+/)[0] ?? '';
|
|
443
|
+
if (first === t || valStr === t)
|
|
444
|
+
return true;
|
|
445
|
+
const pattern = new RegExp(`(^|[^a-z0-9_|])${escapeRegExpForAllowlist(t)}([^a-z0-9_|]|$)`);
|
|
446
|
+
return pattern.test(valStr);
|
|
447
|
+
}
|
|
431
448
|
function mergePostApplyUploadIntoPayload(payload, hint) {
|
|
432
449
|
if (!hint)
|
|
433
450
|
return;
|
|
@@ -674,6 +691,30 @@ function mergeSqliteOpIntoJson(currentJson, sqliteOp) {
|
|
|
674
691
|
container[arrayKey] = existing.filter((x) => !removeSet.has(String(x)));
|
|
675
692
|
return;
|
|
676
693
|
}
|
|
694
|
+
if (sqliteOp.remove_commands?.length &&
|
|
695
|
+
(sqliteOp.json_path ?? '').includes('yoloCommandAllowlist') &&
|
|
696
|
+
!sqliteOp.array_remove?.length) {
|
|
697
|
+
const jp = (sqliteOp.json_path ?? '').trim();
|
|
698
|
+
const parts = jp.split('.').filter(Boolean);
|
|
699
|
+
if (parts.length === 0)
|
|
700
|
+
return;
|
|
701
|
+
let node = currentJson;
|
|
702
|
+
for (const p of parts.slice(0, -1)) {
|
|
703
|
+
if (node == null || typeof node !== 'object' || Array.isArray(node))
|
|
704
|
+
return;
|
|
705
|
+
node = node[p];
|
|
706
|
+
}
|
|
707
|
+
if (node == null || typeof node !== 'object' || Array.isArray(node))
|
|
708
|
+
return;
|
|
709
|
+
const container = node;
|
|
710
|
+
const arrayKey = parts[parts.length - 1];
|
|
711
|
+
const existing = container[arrayKey];
|
|
712
|
+
if (!Array.isArray(existing))
|
|
713
|
+
return;
|
|
714
|
+
const tokens = sqliteOp.remove_commands.map((t) => String(t).trim()).filter(Boolean);
|
|
715
|
+
container[arrayKey] = existing.filter((entry) => !tokens.some((t) => allowlistEntryMatchesRemoveToken(entry, t)));
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
677
718
|
const where = sqliteOp.array_item_where;
|
|
678
719
|
const jp = sqliteOp.json_path ?? '';
|
|
679
720
|
if (where && typeof where === 'object' && Object.keys(where).length > 0 && jp) {
|