Tool surface: preset / tools / excludeTools filtering (core preset: 11,815 B vs 107,157 B) #49
Labels
No labels
area/dsh
area/forgejo
experiment
priority/later
priority/next
priority/now
type/bug
type/task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
dsh-plugins/dsh-gitea#49
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
Every registered tool's schema is bound into every request. dsh-gitea contributes 133 names / 107,157 B — 61.5 % of a 174,372 B tool payload — including in sessions that never call a gitea tool.
Measurements (2026-10-24, dsh-gitea 0.8.4, DSH 0.2.1-rc.2)
Corpus: 28 session logs under
~/.dsh/sessions, calls deduplicated by call id (1,020 unique gitea calls).Payload by subset (canonical names; aliases excluded):
core(15 most-used)reposissuesprsopsfull(canonical)full+ aliases (today)The 15 hot tools by call count:
issue_create,labels,issue_comment,issue_get,issue_close,ci,issue_list,wiki,repo_contents,branches,org,releases,whoami,issue_search,issue_set_labels.Context share: 191 tools ≈ 47k tokens ≈ 70 % of a 67,048-token first-turn prompt (~3.7 bytes/token, cross-checked against the session
usagerecord).Impact
full, so existing installs see no behaviour change.Proposal
Mirror the interface already shipped in
dsh-resend-mcpso operators carry one mental model:fullis today's canonical set (byte-identical) and stays the default.missingPatternshandling).TOOL_DEFSso it cannot drift from the code.coreplus explicittoolsadditions;issues/prs/opsfor focused workspaces.legacyAliasesflag (#48) is independent: presets filter canonical definitions, the flag controls whether the 37 aliases are advertised at all.Why this before any lazy loading
Presets are decided at mount: zero runtime cost, no request-prefix change, no KV-cache invalidation, and they survive DSH upgrades as a config edit. They are also the only lever that helps the 12/28 sessions that never call a gitea tool.
Acceptance criteria
preset,tools,excludeTools; an invalid preset is rejected at mount with a clear messagefullproduces a tool set byte-identical to 0.8.4 canonicalpresetincordis.patch.ymltakes effect via HMR without a restartVerification Plan
Same
request/headermeasurement as #48, run once per preset:Plus a live session with
preset: coreexercising the hot path (issue create, comment, close, label set, CI status).Scope
experimentissues.Dependencies
Improved by #48 (baseline 65,159 B) but not blocked by it.
Fixed in
3d3537b, released as 0.8.5.Implemented as proposed, with the
dsh-resend-mcpinterface as the reference (lib/selection.js, pure module; glob*only, unmatched patterns reported viamissingPatterns/missingExcludePatterns, never fatal):preset:core|issues|prs|repos|ops|full|none|custom.fullis the default and resolves inTOOL_DEFSorder, so it is byte-identical to 0.8.4. The four domain presets are disjoint and their union is exactly the 96 canonical tools —test/selection.test.mjsfails if a tool is renamed or dropped, so the table cannot drift.tools: non-empty replaces the preset (customrequires it);excludeToolssubtracts after. An unknown preset fails at mount with the accepted names; the settings route answers 400.noneas proposed in the design discussion: the 12/28 sessions that never call a Gitea tool can opt out with one word instead ofexcludeTools: ["*"].baseUrl) does not re-register, so the model-facing prefix stays stable. A real surface change disposes and re-registers through the disposertools.register()returns — live, no restart./dsh-gitea/configreturnstoolSurfacefor the same data.Measured on the live wire schema (bytes per preset):
core11,640 / 15 tools,issues15,586 / 22,prs17,480 / 27,repos12,026 / 17,ops20,067 / 30,none0,full65,159 / 96. Recorded in the README table.npm run check: 180 tests, leak scan and syntax clean.