explorbot 0.1.28 → 0.1.29
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 +83 -245
- package/bin/explorbot-cli.ts +1 -0
- package/dist/bin/explorbot-cli.js +1 -0
- package/dist/package.json +8 -6
- package/dist/rules/navigator/verification-actions.md +2 -0
- package/dist/src/ai/fisherman.js +14 -3
- package/dist/src/ai/pilot.js +19 -4
- package/dist/src/ai/planner.js +16 -5
- package/dist/src/ai/provider.js +53 -18
- package/dist/src/ai/researcher.js +7 -1
- package/dist/src/ai/rules.js +44 -0
- package/dist/src/ai/tester.js +70 -7
- package/dist/src/ai/tools.js +67 -1
- package/dist/src/explorbot.js +7 -2
- package/dist/src/stats.js +16 -0
- package/dist/src/utils/aria.js +66 -6
- package/package.json +8 -6
- package/rules/navigator/verification-actions.md +2 -0
- package/src/ai/fisherman.ts +14 -3
- package/src/ai/pilot.ts +19 -4
- package/src/ai/planner.ts +16 -5
- package/src/ai/provider.ts +51 -19
- package/src/ai/researcher.ts +8 -1
- package/src/ai/rules.ts +46 -0
- package/src/ai/tester.ts +74 -7
- package/src/ai/tools.ts +80 -1
- package/src/config.ts +1 -0
- package/src/explorbot.ts +6 -2
- package/src/stats.ts +18 -0
- package/src/utils/aria.ts +63 -6
package/src/utils/aria.ts
CHANGED
|
@@ -334,6 +334,54 @@ const detectRenames = (prev: FlatEntry[], curr: FlatEntry[], prevTotals: Map<str
|
|
|
334
334
|
return { added, removed };
|
|
335
335
|
};
|
|
336
336
|
|
|
337
|
+
// Interactive controls keep a stable role+name across a state flip; only an ARIA state
|
|
338
|
+
// attribute changes. Report those flips on their own line so the model always sees
|
|
339
|
+
// "now checked / now collapsed", in both directions, regardless of other page churn.
|
|
340
|
+
const STATE_WORDS: Record<string, { on: string; off: string }> = {
|
|
341
|
+
checked: { on: 'checked', off: 'unchecked' },
|
|
342
|
+
selected: { on: 'selected', off: 'unselected' },
|
|
343
|
+
pressed: { on: 'pressed', off: 'unpressed' },
|
|
344
|
+
expanded: { on: 'expanded', off: 'collapsed' },
|
|
345
|
+
};
|
|
346
|
+
const STATE_ATTRS = Object.keys(STATE_WORDS);
|
|
347
|
+
|
|
348
|
+
const stateWord = (attr: string, value: unknown): string => {
|
|
349
|
+
if (attr === 'checked' && value === 'mixed') return 'partially checked';
|
|
350
|
+
const words = STATE_WORDS[attr];
|
|
351
|
+
if (value === true || value === 'true') return words.on;
|
|
352
|
+
return words.off;
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
// Pair entries by path; when role and name match but a state attr differs, it's a toggle.
|
|
356
|
+
const detectToggles = (prev: FlatEntry[], curr: FlatEntry[]): { toggled: string[]; togglePaths: Set<string> } => {
|
|
357
|
+
const toggled: string[] = [];
|
|
358
|
+
const togglePaths = new Set<string>();
|
|
359
|
+
const currByPath = new Map(curr.map((e) => [e.path, e]));
|
|
360
|
+
|
|
361
|
+
for (const before of prev) {
|
|
362
|
+
const after = currByPath.get(before.path);
|
|
363
|
+
if (!after) continue;
|
|
364
|
+
if (before.entry.role !== after.entry.role) continue;
|
|
365
|
+
if (before.entry.name !== after.entry.name) continue;
|
|
366
|
+
|
|
367
|
+
const transitions: string[] = [];
|
|
368
|
+
for (const attr of STATE_ATTRS) {
|
|
369
|
+
const was = stateWord(attr, before.entry[attr]);
|
|
370
|
+
const now = stateWord(attr, after.entry[attr]);
|
|
371
|
+
if (was === now) continue;
|
|
372
|
+
transitions.push(`${was} -> ${now}`);
|
|
373
|
+
}
|
|
374
|
+
if (transitions.length === 0) continue;
|
|
375
|
+
|
|
376
|
+
togglePaths.add(before.path);
|
|
377
|
+
let label = String(after.entry.role);
|
|
378
|
+
const name = after.entry.name;
|
|
379
|
+
if (typeof name === 'string' && name.trim()) label += ` "${name.trim()}"`;
|
|
380
|
+
toggled.push(`${label}: ${transitions.join(', ')}`);
|
|
381
|
+
}
|
|
382
|
+
return { toggled, togglePaths };
|
|
383
|
+
};
|
|
384
|
+
|
|
337
385
|
const TOP_DIFF_ITEMS = 10;
|
|
338
386
|
|
|
339
387
|
const formatDiffSection = (label: string, items: string[]): string[] => {
|
|
@@ -358,9 +406,15 @@ const formatDiffSection = (label: string, items: string[]): string[] => {
|
|
|
358
406
|
return lines;
|
|
359
407
|
};
|
|
360
408
|
|
|
361
|
-
const formatDiff = (added: string[], removed: string[]): string | null => {
|
|
362
|
-
if (added.length === 0 && removed.length === 0) return null;
|
|
363
|
-
|
|
409
|
+
const formatDiff = (added: string[], removed: string[], toggled: string[]): string | null => {
|
|
410
|
+
if (added.length === 0 && removed.length === 0 && toggled.length === 0) return null;
|
|
411
|
+
const sections = ['ariaDiff:'];
|
|
412
|
+
if (toggled.length > 0) {
|
|
413
|
+
sections.push(' toggled:');
|
|
414
|
+
for (const line of toggled) sections.push(` - ${line}`);
|
|
415
|
+
}
|
|
416
|
+
sections.push(...formatDiffSection('added', added), ...formatDiffSection('removed', removed));
|
|
417
|
+
return sections.join('\n');
|
|
364
418
|
};
|
|
365
419
|
|
|
366
420
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -437,13 +491,16 @@ export const diffAriaSnapshots = (previous: string | null, current: string | nul
|
|
|
437
491
|
tree = dropEmpty(tree);
|
|
438
492
|
return flatten(tree);
|
|
439
493
|
};
|
|
440
|
-
const
|
|
441
|
-
const
|
|
494
|
+
const prevAll = flat(previous);
|
|
495
|
+
const currAll = flat(current);
|
|
496
|
+
const { toggled, togglePaths } = detectToggles(prevAll, currAll);
|
|
497
|
+
const prev = prevAll.filter((e) => !togglePaths.has(e.path));
|
|
498
|
+
const curr = currAll.filter((e) => !togglePaths.has(e.path));
|
|
442
499
|
const prevTotals = countBy(prev.map((e) => e.summary));
|
|
443
500
|
const currTotals = countBy(curr.map((e) => e.summary));
|
|
444
501
|
const byCount = diffByCount(prevTotals, currTotals);
|
|
445
502
|
const renames = detectRenames(prev, curr, prevTotals, currTotals);
|
|
446
|
-
return formatDiff([...byCount.added, ...renames.added], [...byCount.removed, ...renames.removed]);
|
|
503
|
+
return formatDiff([...byCount.added, ...renames.added], [...byCount.removed, ...renames.removed], toggled);
|
|
447
504
|
};
|
|
448
505
|
|
|
449
506
|
export const detectFocusArea = (snapshot: string | null): FocusAreaResult => {
|