explorbot 0.4.6 → 0.4.8
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/boat/api-tester/src/ai/chief.ts +3 -1
- package/boat/api-tester/src/ai/curler.ts +74 -66
- package/boat/api-tester/src/apibot.ts +1 -0
- package/boat/api-tester/src/cli.ts +2 -0
- package/boat/api-tester/src/config.ts +18 -1
- package/dist/boat/api-tester/src/ai/chief.js +3 -1
- package/dist/boat/api-tester/src/ai/curler.js +59 -56
- package/dist/boat/api-tester/src/apibot.js +1 -0
- package/dist/boat/api-tester/src/cli.js +2 -0
- package/dist/boat/api-tester/src/config.js +3 -1
- package/dist/package.json +2 -2
- package/dist/rules/chief/general.md +2 -0
- package/dist/rules/researcher/pagination.md +7 -0
- package/dist/src/action-result.d.ts +6 -0
- package/dist/src/action-result.js +12 -0
- package/dist/src/action.js +3 -2
- package/dist/src/ai/navigator.js +1 -4
- package/dist/src/ai/pilot.js +8 -12
- package/dist/src/ai/planner/session-dedup.d.ts +2 -1
- package/dist/src/ai/planner/session-dedup.js +18 -1
- package/dist/src/ai/planner.js +12 -4
- package/dist/src/ai/provider.js +18 -4
- package/dist/src/ai/researcher/locators.js +1 -1
- package/dist/src/ai/researcher/pagination.d.ts +16 -0
- package/dist/src/ai/researcher/pagination.js +62 -0
- package/dist/src/ai/researcher/parser.d.ts +3 -0
- package/dist/src/ai/researcher/parser.js +22 -6
- package/dist/src/ai/researcher/sections.js +1 -1
- package/dist/src/ai/researcher.js +7 -2
- package/dist/src/ai/rules.js +17 -0
- package/dist/src/ai/scout.js +8 -2
- package/dist/src/ai/tester.js +1 -1
- package/dist/src/ai/tools.js +12 -4
- package/dist/src/commands/options/ws-option.d.ts +7 -0
- package/dist/src/commands/options/ws-option.js +14 -0
- package/dist/src/config.d.ts +1 -0
- package/dist/src/config.js +14 -11
- package/dist/src/remote.d.ts +2 -0
- package/dist/src/remote.js +23 -16
- package/dist/src/utils/aria.d.ts +2 -0
- package/dist/src/utils/aria.js +6 -1
- package/dist/src/utils/code-extractor.js +6 -2
- package/dist/src/utils/markdown-query.d.ts +2 -0
- package/dist/src/utils/markdown-query.js +39 -0
- package/dist/src/utils/pagination.d.ts +16 -0
- package/dist/src/utils/pagination.js +20 -0
- package/docs/superpowers/plans/2026-09-10-pagination.md +1420 -0
- package/docs/superpowers/specs/2026-09-09-pagination-rule-design.md +125 -97
- package/package.json +2 -2
- package/rules/chief/general.md +2 -0
- package/rules/researcher/pagination.md +7 -0
- package/src/action-result.ts +16 -0
- package/src/action.ts +3 -2
- package/src/ai/navigator.ts +1 -4
- package/src/ai/pilot.ts +8 -12
- package/src/ai/planner/session-dedup.ts +16 -2
- package/src/ai/planner.ts +12 -4
- package/src/ai/provider.ts +18 -3
- package/src/ai/researcher/locators.ts +1 -1
- package/src/ai/researcher/pagination.ts +68 -0
- package/src/ai/researcher/parser.ts +23 -5
- package/src/ai/researcher/sections.ts +1 -1
- package/src/ai/researcher.ts +9 -3
- package/src/ai/rules.ts +17 -0
- package/src/ai/scout.ts +9 -2
- package/src/ai/tester.ts +1 -1
- package/src/ai/tools.ts +9 -4
- package/src/commands/options/ws-option.ts +14 -0
- package/src/config.ts +15 -11
- package/src/remote.ts +22 -15
- package/src/utils/aria.ts +8 -1
- package/src/utils/code-extractor.ts +6 -2
- package/src/utils/markdown-query.ts +39 -0
- package/src/utils/pagination.ts +36 -0
package/dist/src/utils/aria.js
CHANGED
|
@@ -511,7 +511,12 @@ export const diffAriaSnapshots = (previous, current) => {
|
|
|
511
511
|
const renames = detectRenames(prev, curr, prevTotals, currTotals);
|
|
512
512
|
const added = [...byCount.added, ...renames.added];
|
|
513
513
|
const removed = [...byCount.removed, ...renames.removed];
|
|
514
|
-
return {
|
|
514
|
+
return {
|
|
515
|
+
text: formatDiff(added, removed, toggled, typed),
|
|
516
|
+
count: added.length + removed.length + toggled.length + typed.length,
|
|
517
|
+
added: added.length,
|
|
518
|
+
removed: removed.length,
|
|
519
|
+
};
|
|
515
520
|
};
|
|
516
521
|
export const detectFocusArea = (snapshot) => {
|
|
517
522
|
let tree = parseSnapshot(snapshot);
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { createDebug } from './logger.js';
|
|
2
2
|
const debugLog = createDebug('explorbot:code-extractor');
|
|
3
|
+
const JS_LANGUAGES = new Set(['', 'js', 'javascript']);
|
|
3
4
|
export function extractCodeBlocks(aiResponse) {
|
|
4
|
-
const codeBlockRegex = /```(
|
|
5
|
+
const codeBlockRegex = /```([^\n`]*)\n([\s\S]*?)\n```/g;
|
|
5
6
|
const codeBlocks = [];
|
|
6
7
|
let match = null;
|
|
7
8
|
while ((match = codeBlockRegex.exec(aiResponse))) {
|
|
8
|
-
const
|
|
9
|
+
const language = match[1].trim().toLowerCase();
|
|
10
|
+
if (!JS_LANGUAGES.has(language))
|
|
11
|
+
continue;
|
|
12
|
+
const code = match[2].trim();
|
|
9
13
|
if (!code)
|
|
10
14
|
continue;
|
|
11
15
|
try {
|
|
@@ -29,6 +29,8 @@ export declare class MarkdownQuery {
|
|
|
29
29
|
text(): string;
|
|
30
30
|
get(): string;
|
|
31
31
|
toJson(): Record<string, string>[];
|
|
32
|
+
keyValue(): Record<string, string>;
|
|
33
|
+
setKeyValue(key: string, value: string | null): string;
|
|
32
34
|
replace(content: string): string;
|
|
33
35
|
replaceEach(replacer: (match: MarkdownQuery, index: number) => string): string;
|
|
34
36
|
count(): number;
|
|
@@ -129,6 +129,12 @@ function matchText(text, matcher) {
|
|
|
129
129
|
}
|
|
130
130
|
return matcher.negated ? !result : result;
|
|
131
131
|
}
|
|
132
|
+
function entryKey(line) {
|
|
133
|
+
const separator = line.indexOf(':');
|
|
134
|
+
if (separator < 1)
|
|
135
|
+
return null;
|
|
136
|
+
return line.slice(0, separator).trim().toLowerCase();
|
|
137
|
+
}
|
|
132
138
|
function getTokenText(token) {
|
|
133
139
|
const t = token;
|
|
134
140
|
switch (token.type) {
|
|
@@ -340,6 +346,39 @@ export class MarkdownQuery {
|
|
|
340
346
|
}
|
|
341
347
|
return results;
|
|
342
348
|
}
|
|
349
|
+
keyValue() {
|
|
350
|
+
const entries = {};
|
|
351
|
+
for (const range of this.matches) {
|
|
352
|
+
for (const line of getTokenText(range.token).split('\n')) {
|
|
353
|
+
const key = entryKey(line);
|
|
354
|
+
if (!key)
|
|
355
|
+
continue;
|
|
356
|
+
const value = line.slice(line.indexOf(':') + 1).trim();
|
|
357
|
+
if (value)
|
|
358
|
+
entries[key] = value;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return entries;
|
|
362
|
+
}
|
|
363
|
+
setKeyValue(key, value) {
|
|
364
|
+
return this.replaceEach((match) => {
|
|
365
|
+
const token = match.matches[0].token;
|
|
366
|
+
const lines = getTokenText(token)
|
|
367
|
+
.split('\n')
|
|
368
|
+
.map((line) => line.trim())
|
|
369
|
+
.filter(Boolean);
|
|
370
|
+
const index = lines.findIndex((line) => entryKey(line) === key.toLowerCase());
|
|
371
|
+
if (index < 0 && value)
|
|
372
|
+
lines.push(`${key}: ${value}`);
|
|
373
|
+
if (index >= 0 && value)
|
|
374
|
+
lines[index] = `${key}: ${value}`;
|
|
375
|
+
if (index >= 0 && !value)
|
|
376
|
+
lines.splice(index, 1);
|
|
377
|
+
if (token.type !== 'blockquote')
|
|
378
|
+
return lines.join('\n');
|
|
379
|
+
return lines.map((line) => `> ${line}`).join('\n');
|
|
380
|
+
});
|
|
381
|
+
}
|
|
343
382
|
replace(content) {
|
|
344
383
|
return this.replaceEach(() => content);
|
|
345
384
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare function inspectList(css: string): ListMeasure | null;
|
|
2
|
+
export declare function restoreScroll({ css, scrollTop, pageScrollY }: ScrollPosition): void;
|
|
3
|
+
export type PaginationStrategy = 'controls' | 'infinite';
|
|
4
|
+
export interface ListMeasure {
|
|
5
|
+
hasPagingControls: boolean;
|
|
6
|
+
isFeed: boolean;
|
|
7
|
+
scrolls: boolean;
|
|
8
|
+
items: number;
|
|
9
|
+
scrollTop: number;
|
|
10
|
+
pageScrollY: number;
|
|
11
|
+
}
|
|
12
|
+
export interface ScrollPosition {
|
|
13
|
+
css: string;
|
|
14
|
+
scrollTop: number;
|
|
15
|
+
pageScrollY: number;
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function inspectList(css) {
|
|
2
|
+
const element = document.querySelector(css);
|
|
3
|
+
if (!element)
|
|
4
|
+
return null;
|
|
5
|
+
const rect = element.getBoundingClientRect();
|
|
6
|
+
return {
|
|
7
|
+
hasPagingControls: !!element.querySelector('a[rel="next"], a[rel="prev"]'),
|
|
8
|
+
isFeed: element.matches('[role="feed"]') || !!element.querySelector('[role="feed"]'),
|
|
9
|
+
scrolls: element.scrollHeight > element.clientHeight + 1 || rect.bottom > window.innerHeight,
|
|
10
|
+
items: element.querySelectorAll(':scope > *').length,
|
|
11
|
+
scrollTop: element.scrollTop,
|
|
12
|
+
pageScrollY: window.scrollY,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function restoreScroll({ css, scrollTop, pageScrollY }) {
|
|
16
|
+
const element = document.querySelector(css);
|
|
17
|
+
if (element)
|
|
18
|
+
element.scrollTop = scrollTop;
|
|
19
|
+
window.scrollTo(0, pageScrollY);
|
|
20
|
+
}
|