mirror of
https://github.com/only-cli/oc.git
synced 2026-09-15 10:40:56 +02:00
Merge pull request #47 from only-cli/feat/find-in-footer
feat: offer find in every actions footer
This commit is contained in:
@@ -12,7 +12,7 @@ $ oc open news.ycombinator.com
|
||||
[1] Show HN: I built a tiny CSV toolkit
|
||||
[2] 312 comments
|
||||
...
|
||||
actions: do <n> | read <n> | next | raw
|
||||
actions: do <n> | find <query> | read <n> | next | raw
|
||||
|
||||
$ oc do 1
|
||||
```
|
||||
|
||||
+4
-2
@@ -234,7 +234,7 @@ export function find(query, { session = DEFAULT_SESSION, budget = 500 } = {}) {
|
||||
return [
|
||||
`1 match for "${query}"${separately}, region [${only.n}]`,
|
||||
read(only.n, { session, budget: budget * FINISH }),
|
||||
`actions: ${follow}read <n> | next | raw`,
|
||||
`actions: ${follow}find <query> | read <n> | next | raw`,
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
@@ -264,7 +264,9 @@ export function find(query, { session = DEFAULT_SESSION, budget = 500 } = {}) {
|
||||
if (shown < hits.length) {
|
||||
lines.push(`... ${hits.length - shown} more matches, narrow the query or raise --budget`);
|
||||
}
|
||||
lines.push(`actions: ${[hasLinks && 'do <n>', 'read <n>', 'next', 'raw'].filter(Boolean).join(' | ')}`);
|
||||
// Offering find on its own output is what makes "narrow the query" above an
|
||||
// action rather than advice.
|
||||
lines.push(`actions: ${[hasLinks && 'do <n>', 'find <query>', 'read <n>', 'next', 'raw'].filter(Boolean).join(' | ')}`);
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
|
||||
@@ -141,8 +141,15 @@ export function render(page, { budget = 500, from = 0 } = {}) {
|
||||
// An input on the page adds no action. 'fill' and 'submit' are still stubs
|
||||
// that throw, and this footer is the line an agent trusts for what to run
|
||||
// next, so naming one of them costs a turn and returns nothing.
|
||||
//
|
||||
// 'find' comes before 'read' because it is the cheaper way to go deeper: one
|
||||
// command lands on the block that matters, where 'read' needs the right
|
||||
// number first and 'next' pages toward it. The entry costs about three
|
||||
// tokens on every render, and skipping one 'next' on a long page pays for
|
||||
// a hundred of them.
|
||||
const actions = [
|
||||
hasLinks && 'do <n>',
|
||||
'find <query>',
|
||||
'read <n>',
|
||||
rest.length && 'next',
|
||||
'raw',
|
||||
|
||||
@@ -282,3 +282,23 @@ test('no footer names a command that is not available yet', async () => {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('every footer offers find, the cheapest way to go deeper on a page', () => {
|
||||
// SKILL.md lists find first under "going further, cheapest first", and the
|
||||
// footer is what an agent actually reads, so the two have to agree. Same
|
||||
// three footer sites as the stub probe above: a render, and both of find's
|
||||
// paths.
|
||||
open();
|
||||
const outputs = [
|
||||
render(page(), { budget: 500 }).text,
|
||||
find('postgres'),
|
||||
find('a'),
|
||||
];
|
||||
const footers = outputs.map((out) => out.split('\n').find((line) => line.startsWith('actions:')));
|
||||
assert.equal(footers.filter(Boolean).length, outputs.length, `every output should carry a footer:\n${footers.join('\n')}`);
|
||||
for (const footer of footers) {
|
||||
assert.ok(footer.includes('find <query>'), `footer should offer find:\n${footer}`);
|
||||
// Cheapest first: find is listed ahead of read.
|
||||
assert.ok(footer.indexOf('find <query>') < footer.indexOf('read <n>'), `find should come before read:\n${footer}`);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user