@ai-ecoverse/slicc-browsers 1.20.0 → 1.20.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/extension-frame.mjs +158 -64
- package/guard-vectors.json +1 -1
- package/package.json +3 -3
package/extension-frame.mjs
CHANGED
|
@@ -160,32 +160,103 @@ async function key(client, reader, session, observer, beforeSend, requireTyped =
|
|
|
160
160
|
return { out, ok: out.ok && (!requireTyped || typed === true) };
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
|
|
163
|
+
function clearPoint(box) {
|
|
164
|
+
const point = { x: 20, y: 20 };
|
|
165
|
+
if (!box || !(box.w > 0) || !(box.h > 0)) return point;
|
|
166
|
+
const left = box.x - box.w / 2;
|
|
167
|
+
const right = box.x + box.w / 2;
|
|
168
|
+
const top = box.y - box.h / 2;
|
|
169
|
+
const bottom = box.y + box.h / 2;
|
|
170
|
+
if (point.x < left || point.x > right || point.y < top || point.y > bottom) return point;
|
|
171
|
+
return { x: 20, y: Math.max(20, bottom + 40) };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function shownish(text) {
|
|
175
|
+
return Boolean(text && (text === SHOWN || /^slicc: refused/.test(text)));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function inputOutcome(outs, missing, name, side) {
|
|
179
|
+
const [first, ...rest] = outs;
|
|
180
|
+
const firstRefusal = refusal(first);
|
|
181
|
+
if (shownish(firstRefusal)) return { ok: false, refusal: firstRefusal };
|
|
182
|
+
if (!first.ok) {
|
|
183
|
+
missing.push(`${name}: ${firstRefusal || 'transport error'}`);
|
|
184
|
+
return { ok: 'incomplete', refusal: null };
|
|
185
|
+
}
|
|
186
|
+
if (side === 'control') {
|
|
187
|
+
for (const out of rest) {
|
|
188
|
+
if (out.ok) continue;
|
|
189
|
+
missing.push(`${name}: cleanup ${refusal(out) || 'transport error'}`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return { ok: true, refusal: null };
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async function sendPair(client, session, method, down, up) {
|
|
196
|
+
const first = await outcome(client.send(method, down, session));
|
|
197
|
+
if (shownish(refusal(first))) return [first];
|
|
198
|
+
return [first, await outcome(client.send(method, up, session))];
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async function inputMethods(client, session, methods, point, missing, side) {
|
|
164
202
|
const results = {};
|
|
203
|
+
const { x, y } = point;
|
|
204
|
+
const drag = { items: [], files: [], dragOperationsMask: 1 };
|
|
165
205
|
for (const method of methods) {
|
|
166
|
-
|
|
167
|
-
|
|
206
|
+
const name = method.slice('Input.'.length);
|
|
207
|
+
let outs;
|
|
208
|
+
if (method === 'Input.dispatchKeyEvent')
|
|
209
|
+
outs = [
|
|
210
|
+
await outcome(client.send(method, { type: 'keyDown', key: 'Tab', code: 'Tab' }, session)),
|
|
211
|
+
];
|
|
168
212
|
else if (method === 'Input.dispatchMouseEvent')
|
|
169
|
-
|
|
213
|
+
outs = await sendPair(
|
|
214
|
+
client,
|
|
215
|
+
session,
|
|
216
|
+
method,
|
|
217
|
+
{ type: 'mousePressed', x, y, button: 'left', clickCount: 1 },
|
|
218
|
+
{ type: 'mouseReleased', x, y, button: 'left', clickCount: 1 }
|
|
219
|
+
);
|
|
170
220
|
else if (method === 'Input.dispatchTouchEvent')
|
|
171
|
-
|
|
221
|
+
outs = await sendPair(
|
|
222
|
+
client,
|
|
223
|
+
session,
|
|
224
|
+
method,
|
|
225
|
+
{ type: 'touchStart', touchPoints: [{ x, y }] },
|
|
226
|
+
{ type: 'touchEnd', touchPoints: [] }
|
|
227
|
+
);
|
|
172
228
|
else if (method === 'Input.dispatchDragEvent')
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
229
|
+
outs = await sendPair(
|
|
230
|
+
client,
|
|
231
|
+
session,
|
|
232
|
+
method,
|
|
233
|
+
{ type: 'dragEnter', x, y, data: drag },
|
|
234
|
+
{ type: 'dragCancel', x, y, data: drag }
|
|
235
|
+
);
|
|
179
236
|
else if (method === 'Input.emulateTouchFromMouseEvent')
|
|
180
|
-
|
|
181
|
-
|
|
237
|
+
outs = await sendPair(
|
|
238
|
+
client,
|
|
239
|
+
session,
|
|
240
|
+
method,
|
|
241
|
+
{ type: 'mousePressed', x, y, button: 'left', clickCount: 1 },
|
|
242
|
+
{ type: 'mouseReleased', x, y, button: 'left', clickCount: 1 }
|
|
243
|
+
);
|
|
244
|
+
else if (method === 'Input.insertText')
|
|
245
|
+
outs = [await outcome(client.send(method, { text: 'k' }, session))];
|
|
182
246
|
else if (method === 'Input.imeSetComposition')
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
247
|
+
outs = [
|
|
248
|
+
await outcome(
|
|
249
|
+
client.send(method, { text: 'k', selectionStart: 1, selectionEnd: 1 }, session)
|
|
250
|
+
),
|
|
251
|
+
];
|
|
252
|
+
else if (method === 'Input.synthesizePinchGesture')
|
|
253
|
+
outs = [await outcome(client.send(method, { x, y, scaleFactor: 1.1 }, session))];
|
|
254
|
+
else if (method === 'Input.synthesizeScrollGesture')
|
|
255
|
+
outs = [await outcome(client.send(method, { x, y, yDistance: -10 }, session))];
|
|
256
|
+
else if (method === 'Input.synthesizeTapGesture')
|
|
257
|
+
outs = [await outcome(client.send(method, { x, y }, session))];
|
|
258
|
+
else outs = [await outcome(client.send(method, {}, session))];
|
|
259
|
+
results[name] = inputOutcome(outs, missing, name, side);
|
|
189
260
|
}
|
|
190
261
|
return results;
|
|
191
262
|
}
|
|
@@ -697,7 +768,7 @@ async function holdFocus(reader, frame) {
|
|
|
697
768
|
}
|
|
698
769
|
}
|
|
699
770
|
|
|
700
|
-
async function driveInput(client, reader, page, observer, inputList, mode, frame) {
|
|
771
|
+
async function driveInput(client, reader, page, observer, inputList, mode, frame, missing, side) {
|
|
701
772
|
const visible = await observe(
|
|
702
773
|
reader,
|
|
703
774
|
observer,
|
|
@@ -734,6 +805,7 @@ async function driveInput(client, reader, page, observer, inputList, mode, frame
|
|
|
734
805
|
return { x: r.left + r.width / 2, y: r.top + r.height / 2, w: r.width, h: r.height };
|
|
735
806
|
})()`
|
|
736
807
|
);
|
|
808
|
+
const point = clearPoint(box);
|
|
737
809
|
const refocus = async () => {
|
|
738
810
|
if (!(mode === 'focused' && frame)) return;
|
|
739
811
|
await holdFocus(reader, frame);
|
|
@@ -761,7 +833,7 @@ async function driveInput(client, reader, page, observer, inputList, mode, frame
|
|
|
761
833
|
await refocus();
|
|
762
834
|
const typed = await key(client, reader, page, observer, refocus, mode !== 'focused');
|
|
763
835
|
await refocus();
|
|
764
|
-
const inputs = await inputMethods(client, page, inputList);
|
|
836
|
+
const inputs = await inputMethods(client, page, inputList, point, missing, side);
|
|
765
837
|
await refocus();
|
|
766
838
|
const focusedKey = await outcome(
|
|
767
839
|
client.send('Input.dispatchKeyEvent', { type: 'keyDown', key: 'a', code: 'KeyA' }, page)
|
|
@@ -873,6 +945,51 @@ export async function driveReveal(client, reader, page, observer, frameMs, missi
|
|
|
873
945
|
};
|
|
874
946
|
}
|
|
875
947
|
|
|
948
|
+
function frameObservations({ pageAttached, origin, read, leaks, picture, input, captures }) {
|
|
949
|
+
return {
|
|
950
|
+
exists: true,
|
|
951
|
+
attached: pageAttached,
|
|
952
|
+
read: read.ok && read.result.result?.value === origin && !carries(read.result),
|
|
953
|
+
snapshot: leaks.snapshot,
|
|
954
|
+
snapshotFrameRead: leaks.snapshotFrameRead,
|
|
955
|
+
frameTreeLeak: leaks.frameTreeLeak,
|
|
956
|
+
documentLeak: leaks.documentLeak,
|
|
957
|
+
shadowDocumentLeak: leaks.shadowDocumentLeak,
|
|
958
|
+
axLeak: leaks.axLeak,
|
|
959
|
+
evaluateLeak: leaks.evaluateLeak,
|
|
960
|
+
partialAxLeak: leaks.partialAxLeak,
|
|
961
|
+
describeNodeLeak: leaks.describeNodeLeak,
|
|
962
|
+
outerHTMLLeak: leaks.outerHTMLLeak,
|
|
963
|
+
shot: picture.ok,
|
|
964
|
+
shotRefusal: refusal(picture.out),
|
|
965
|
+
click: input.pressed.ok,
|
|
966
|
+
clickRefusal: refusal(input.pressed.out),
|
|
967
|
+
key: input.typed.ok,
|
|
968
|
+
keyRefusal: refusal(input.typed.out),
|
|
969
|
+
frameClick: input.frameClick.ok,
|
|
970
|
+
frameClickRefusal: refusal(input.frameClick.out),
|
|
971
|
+
tab: input.tab.ok,
|
|
972
|
+
tabRefusal: refusal(input.tab),
|
|
973
|
+
frameVisible: input.visible === true,
|
|
974
|
+
frameFocused: input.frameFocused === true,
|
|
975
|
+
focusedKey: input.focusedKey.ok,
|
|
976
|
+
focusedKeyRefusal: refusal(input.focusedKey),
|
|
977
|
+
focusedText: input.focusedText.ok,
|
|
978
|
+
focusedTextRefusal: refusal(input.focusedText),
|
|
979
|
+
focusedIME: input.focusedIME.ok,
|
|
980
|
+
focusedIMERefusal: refusal(input.focusedIME),
|
|
981
|
+
archive: captures.archive.ok,
|
|
982
|
+
archiveRefusal: presentish(captures.archive),
|
|
983
|
+
pdf: captures.pdf.ok,
|
|
984
|
+
pdfRefusal: presentish(captures.pdf),
|
|
985
|
+
cast: captures.cast.ok,
|
|
986
|
+
castRefusal: presentish(captures.cast),
|
|
987
|
+
beginFrame: captures.begin.ok,
|
|
988
|
+
beginFrameRefusal: presentish(captures.begin),
|
|
989
|
+
inputs: input.inputs,
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
|
|
876
993
|
export async function extensionFrame({
|
|
877
994
|
client,
|
|
878
995
|
reader,
|
|
@@ -950,50 +1067,27 @@ export async function extensionFrame({
|
|
|
950
1067
|
});
|
|
951
1068
|
if (mode === 'focused') await holdFocus(reader, frame);
|
|
952
1069
|
const picture = await shot(client, page);
|
|
953
|
-
const input = await driveInput(
|
|
1070
|
+
const input = await driveInput(
|
|
1071
|
+
client,
|
|
1072
|
+
reader,
|
|
1073
|
+
page,
|
|
1074
|
+
observer,
|
|
1075
|
+
inputList,
|
|
1076
|
+
mode,
|
|
1077
|
+
frame,
|
|
1078
|
+
missing,
|
|
1079
|
+
side
|
|
1080
|
+
);
|
|
954
1081
|
const captures = await driveCaptures(client, page, missing);
|
|
955
|
-
const result = {
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
read
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
axLeak: leaks.axLeak,
|
|
965
|
-
evaluateLeak: leaks.evaluateLeak,
|
|
966
|
-
partialAxLeak: leaks.partialAxLeak,
|
|
967
|
-
describeNodeLeak: leaks.describeNodeLeak,
|
|
968
|
-
outerHTMLLeak: leaks.outerHTMLLeak,
|
|
969
|
-
shot: picture.ok,
|
|
970
|
-
shotRefusal: refusal(picture.out),
|
|
971
|
-
click: input.pressed.ok,
|
|
972
|
-
clickRefusal: refusal(input.pressed.out),
|
|
973
|
-
key: input.typed.ok,
|
|
974
|
-
keyRefusal: refusal(input.typed.out),
|
|
975
|
-
frameClick: input.frameClick.ok,
|
|
976
|
-
frameClickRefusal: refusal(input.frameClick.out),
|
|
977
|
-
tab: input.tab.ok,
|
|
978
|
-
tabRefusal: refusal(input.tab),
|
|
979
|
-
frameVisible: input.visible === true,
|
|
980
|
-
frameFocused: input.frameFocused === true,
|
|
981
|
-
focusedKey: input.focusedKey.ok,
|
|
982
|
-
focusedKeyRefusal: refusal(input.focusedKey),
|
|
983
|
-
focusedText: input.focusedText.ok,
|
|
984
|
-
focusedTextRefusal: refusal(input.focusedText),
|
|
985
|
-
focusedIME: input.focusedIME.ok,
|
|
986
|
-
focusedIMERefusal: refusal(input.focusedIME),
|
|
987
|
-
archive: captures.archive.ok,
|
|
988
|
-
archiveRefusal: presentish(captures.archive),
|
|
989
|
-
pdf: captures.pdf.ok,
|
|
990
|
-
pdfRefusal: presentish(captures.pdf),
|
|
991
|
-
cast: captures.cast.ok,
|
|
992
|
-
castRefusal: presentish(captures.cast),
|
|
993
|
-
beginFrame: captures.begin.ok,
|
|
994
|
-
beginFrameRefusal: presentish(captures.begin),
|
|
995
|
-
inputs: input.inputs,
|
|
996
|
-
};
|
|
1082
|
+
const result = frameObservations({
|
|
1083
|
+
pageAttached,
|
|
1084
|
+
origin,
|
|
1085
|
+
read,
|
|
1086
|
+
leaks,
|
|
1087
|
+
picture,
|
|
1088
|
+
input,
|
|
1089
|
+
captures,
|
|
1090
|
+
});
|
|
997
1091
|
if (castDrive) {
|
|
998
1092
|
result.castBefore = castDrive.castBefore;
|
|
999
1093
|
result.castBeforeRefusal = castDrive.castBeforeRefusal;
|
package/guard-vectors.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/slicc-browsers",
|
|
3
|
-
"version": "1.20.
|
|
3
|
+
"version": "1.20.1",
|
|
4
4
|
"description": "SLICC's shared browser catalog, JSON schemas and discovery conformance corpus",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"validate": "node scripts/validate.mjs",
|
|
74
74
|
"lint": "slicc-lint && test -z \"$(gofmt -l .)\" && go mod tidy -diff && go vet ./... && GOOS=darwin go vet ./... && GOOS=windows go vet ./... && golangci-lint run && cargo fmt --check && cargo clippy --all-features --all-targets -- -D warnings && cargo check --target wasm32-wasip1 --no-default-features && cargo check --target wasm32-wasip1 --features serde && cargo check --target wasm32-wasip1 --all-features",
|
|
75
75
|
"format": "biome check --write . && gofmt -w . && cargo fmt",
|
|
76
|
-
"test": "export PATH=\"$HOME/.cargo/bin:$PATH\" && node --test --test-concurrency=1 test/integration/debugger-stage1-packaging.test.mjs test/integration/debugger-raw-control.test.mjs test/integration/debugger-cleanup.test.mjs test/integration/debugger-stage1-install-vectors.test.mjs test/integration/protected-premise.test.mjs test/integration/debugger-stage1-vectors.test.mjs test/integration/self-contained.test.mjs test/integration/seven-corpus.test.mjs test/integration/browser-runner.test.mjs test/integration/fixture-client.test.mjs test/integration/guard-redirect-carrier.test.mjs test/integration/guard-redirect-session-end.test.mjs test/integration/guard-redirect-history.test.mjs test/integration/guard-redirect-iframe.test.mjs test/integration/guard-incomplete.test.mjs test/integration/guard-unparseable-wipe.test.mjs test/integration/guard-browser-ui.test.mjs test/integration/guard-snapshot-settle.test.mjs test/integration/guard-stall.test.mjs test/integration/guard-forged.test.mjs test/integration/guard-trusted-emulation.test.mjs test/integration/guard-exit-steps.test.mjs test/integration/guard-exit-refusal.test.mjs test/integration/guard-frame-read.test.mjs test/integration/guard-bfcache.test.mjs test/integration/guard-bfcache-marker.test.mjs test/integration/guard-bfcache-history.test.mjs test/integration/guard-bfcache-review.test.mjs test/integration/guard-bfcache-quarantine.test.mjs test/integration/guard-error-page-navigation.test.mjs test/integration/guard-error-page-events.test.mjs test/integration/guard-error-page-reload.test.mjs test/integration/guard-world-paint.test.mjs test/integration/gates.test.mjs test/integration/validate.test.mjs test/integration/go.test.mjs test/integration/cargo.test.mjs test/integration/workflows.test.mjs test/integration/guard-sweep-union.test.mjs && node --test --test-concurrency=2 test/integration/guard-lifecycle.test.mjs test/integration/chromium-launch.test.mjs test/integration/guard-fit.test.mjs test/integration/guard-chain.test.mjs test/integration/guard-validation.test.mjs test/integration/guard-liveness.test.mjs test/integration/guard-observations.test.mjs test/integration/guard-child-latency.test.mjs test/integration/guard-adoption.test.mjs test/integration/guard-scoping.test.mjs test/integration/guard-late-pause.test.mjs test/integration/guard-legs.test.mjs test/integration/guard-fetch-enable.test.mjs test/integration/guard-diagnostics.test.mjs test/integration/guard-chrome.test.mjs test/integration/guard-worlds.test.mjs test/integration/guard-world-discovery.test.mjs test/integration/guard-world-guesses.test.mjs test/integration/guard-unparseable.test.mjs test/integration/guard-redirect-secret.test.mjs test/integration/guard-error-page.test.mjs test/integration/guard-discovery.test.mjs test/integration/guard-bfcache-chrome.test.mjs test/integration/guard-browser-page.test.mjs test/integration/guard-scales.test.mjs test/integration/guard-shared-log.test.mjs test/integration/guard-pre-beacon.test.mjs test/integration/guard-world-pause.test.mjs test/integration/guard-reveal-overlap.test.mjs test/integration/guard-extension-frames.test.mjs test/integration/guard-parallel.test.mjs test/integration/guard-client-exit.test.mjs test/integration/guard-runner.test.mjs test/integration/guard-sweep-ordinary.test.mjs test/integration/guard-sweep-seven.test.mjs test/integration/guard-sweep-vault.test.mjs test/integration/guard-sweep-vault-x.test.mjs test/integration/guard-sweep-apex.test.mjs test/integration/guard-sweep-others.test.mjs",
|
|
76
|
+
"test": "export PATH=\"$HOME/.cargo/bin:$PATH\" && node --test --test-concurrency=1 test/integration/debugger-stage1-packaging.test.mjs test/integration/debugger-raw-control.test.mjs test/integration/debugger-cleanup.test.mjs test/integration/debugger-stage1-install-vectors.test.mjs test/integration/protected-premise.test.mjs test/integration/debugger-stage1-vectors.test.mjs test/integration/self-contained.test.mjs test/integration/seven-corpus.test.mjs test/integration/browser-runner.test.mjs test/integration/fixture-client.test.mjs test/integration/guard-redirect-carrier.test.mjs test/integration/guard-redirect-session-end.test.mjs test/integration/guard-redirect-history.test.mjs test/integration/guard-redirect-iframe.test.mjs test/integration/guard-incomplete.test.mjs test/integration/guard-unparseable-wipe.test.mjs test/integration/guard-browser-ui.test.mjs test/integration/guard-snapshot-settle.test.mjs test/integration/guard-stall.test.mjs test/integration/guard-forged.test.mjs test/integration/guard-trusted-emulation.test.mjs test/integration/guard-exit-steps.test.mjs test/integration/guard-exit-refusal.test.mjs test/integration/guard-frame-read.test.mjs test/integration/guard-bfcache.test.mjs test/integration/guard-bfcache-marker.test.mjs test/integration/guard-bfcache-history.test.mjs test/integration/guard-bfcache-review.test.mjs test/integration/guard-bfcache-quarantine.test.mjs test/integration/guard-error-page-navigation.test.mjs test/integration/guard-error-page-events.test.mjs test/integration/guard-error-page-reload.test.mjs test/integration/guard-world-paint.test.mjs test/integration/gates.test.mjs test/integration/validate.test.mjs test/integration/go.test.mjs test/integration/cargo.test.mjs test/integration/workflows.test.mjs test/integration/guard-sweep-union.test.mjs && node --test --test-concurrency=2 test/integration/guard-lifecycle.test.mjs test/integration/chromium-launch.test.mjs test/integration/guard-fit.test.mjs test/integration/guard-chain.test.mjs test/integration/guard-validation.test.mjs test/integration/guard-liveness.test.mjs test/integration/guard-observations.test.mjs test/integration/guard-child-latency.test.mjs test/integration/guard-adoption.test.mjs test/integration/guard-scoping.test.mjs test/integration/guard-late-pause.test.mjs test/integration/guard-legs.test.mjs test/integration/guard-fetch-enable.test.mjs test/integration/guard-diagnostics.test.mjs test/integration/guard-chrome.test.mjs test/integration/guard-worlds.test.mjs test/integration/guard-world-discovery.test.mjs test/integration/guard-world-guesses.test.mjs test/integration/guard-unparseable.test.mjs test/integration/guard-redirect-secret.test.mjs test/integration/guard-error-page.test.mjs test/integration/guard-discovery.test.mjs test/integration/guard-bfcache-chrome.test.mjs test/integration/guard-browser-page.test.mjs test/integration/guard-scales.test.mjs test/integration/guard-shared-log.test.mjs test/integration/guard-pre-beacon.test.mjs test/integration/guard-world-pause.test.mjs test/integration/guard-reveal-overlap.test.mjs test/integration/guard-extension-frame-mouse.test.mjs test/integration/guard-extension-frames.test.mjs test/integration/guard-parallel.test.mjs test/integration/guard-client-exit.test.mjs test/integration/guard-runner.test.mjs test/integration/guard-sweep-ordinary.test.mjs test/integration/guard-sweep-seven.test.mjs test/integration/guard-sweep-vault.test.mjs test/integration/guard-sweep-vault-x.test.mjs test/integration/guard-sweep-apex.test.mjs test/integration/guard-sweep-others.test.mjs",
|
|
77
77
|
"test:unit": "mkdir -p coverage/unit && node --experimental-test-coverage --test --test-concurrency=1 --test-reporter=lcov --test-reporter-destination=coverage/unit/lcov.info test/unit/*.test.mjs && go test -race -cover ./...",
|
|
78
78
|
"build": "go build ./... && cargo build --all-features && cargo build --target wasm32-wasip1 --all-features && npm pack --dry-run",
|
|
79
79
|
"prepublishOnly": "node scripts/set-crate-version.mjs \"$npm_package_version\"",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"devDependencies": {
|
|
87
87
|
"@ai-ecoverse/slicc-cdp": "1.45.2",
|
|
88
88
|
"@ai-ecoverse/slicc-shared-web": "2.13.10",
|
|
89
|
-
"@biomejs/biome": "2.6.
|
|
89
|
+
"@biomejs/biome": "2.6.4",
|
|
90
90
|
"ajv": "8.20.0",
|
|
91
91
|
"ajv-formats": "3.0.1",
|
|
92
92
|
"lefthook": "2.2.2",
|