You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit c627c48
Browse filesBrowse the repository at this point in the historyBrowse files
Paginate tools.search and tools.executor.sources.list (#492)
PR #265 reported a real symptom — `tools.executor.sources.list()` silently
returns the first 12 sources, so a model that calls it past alphabetical
position 12 mistakes the page for the full inventory. The proposed fix
returned `{ sources, totalSources }` from `sources.list` only, which:
- Tells the model truncation happened, but provides no way to act on it —
no offset/cursor parameter exists, so the model can only retry with
`limit: 999` (defeating pagination).
- Leaves `tools.search` untouched — same truncation hazard, same model.
- Introduces an inconsistent shape: `search` returns a bare array,
`sources.list` returns an object.
This change paginates both with a single shared shape:
{ items, total, hasMore, nextOffset }
Both helpers accept `{ limit?, offset? }`. `nextOffset` is concrete (the
exact number to pass next) so the model doesn't have to compute
`offset + items.length`. Engine arg validation rejects negative offsets.
The `tools.search` description now teaches the paginated shape and shows
the second-page call.
Default `limit` for `sources.list` drops from 200 to 50; the engine layer
still applies 12 by default for both. The off-by-one ergonomics matter
more than the headroom — most users have well under 50 sources.
Tests cover:
- single-page and empty-query results carry the new shape
- pagination across pages with limit + offset, including offset past end
- source listing pagination via the engine
- negative offsets rejected with a clear message
Closes#265.
"- `tools.search()` returns ranked matches, best-first. Use short intent phrases like `github issues`, `repo details`, or `create calendar event`.",
46
+
"- `tools.search()` returns paginated, ranked matches: `{ items, total, hasMore, nextOffset }`. Best-first. Use short intent phrases like `github issues`, `repo details`, or `create calendar event`.",
47
47
'- When you already know the namespace, narrow with `tools.search({ namespace: "github", query: "issues" })`.',
48
-
"- Use `tools.executor.sources.list()` to inspect configured sources and their tool counts. Returns `[{ id, toolCount, ... }]`.",
48
+
"- `tools.executor.sources.list()` returns the same paged shape: `{ items: [{ id, toolCount, ... }], total, hasMore, nextOffset }`.",
49
+
"- If `hasMore` is true and you didn't find what you need, fetch the next page: `tools.search({ query, offset: nextOffset, limit })`. Same `offset` parameter on `tools.executor.sources.list({ offset, limit })`.",
49
50
"- Always use the namespace prefix when calling tools: `tools.<namespace>.<tool>(args)`. Example: `tools.home_assistant_rest_api.states.getState(...)` — not `tools.states.getState(...)`.",
50
51
"- The `tools` object is a lazy proxy — `Object.keys(tools)` won't work. Use `tools.search()` or `tools.executor.sources.list()` instead.",
51
52
'- Pass an object to system tools, e.g. `tools.search({ query: "..." })`, `tools.executor.sources.list()`, and `tools.describe.tool({ path })`.',
0 commit comments