Skip to content

perf(agent): memoize toolSetDigest per tool set - #1410

Merged
corbits-triage[bot] merged 3 commits into
mainfrom
cl-10536-toolset-digest
Oct 13, 2026
Merged

corbits-triage[bot] merged 3 commits into
mainfrom
cl-10536-toolset-digest

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Collaborator

Summary

toolSetDigest (src/agent/director.ts) re-hashed the full tool array on every call. Memoize the digest per stable tool-set identity.

Fix approach — cache semantics

  • Cache is a module-level WeakMap<readonly ToolDefinition[], string> keyed by array identity.
  • Why this is safe: the director owns stable tool arrays and swaps them wholesale (constructor, updateToolDefinitions) — callers pass freshly computed arrays (computeAdvertised, currentDefinitions) and _toolDefinitions is never mutated in place. So the same reference always means the same content, and a new reference (tools changed) misses the WeakMap and recomputes.
  • WeakMap (not Map) so cached arrays are not retained once the director drops them.
  • Output is byte-identical for the same tool set; existing digest tests pass unchanged.

Proof test

src/agent/tool-set-digest.test.ts spies on node:crypto createHash (via withMockedModule from testkit/mock-module.ts) and asserts:

  • 3 repeated toolSetDigest(tools) calls with the same array run sha256 exactly once.
  • A new tool-set array runs it again (recompute on change).

Verification

  • bun test src/agent/director.test.ts src/agent/director-compaction.test.ts src/agent/tool-set-digest.test.ts → 93 pass, 0 fail
  • bun run typecheck → exit 0
  • oxfmt --check + oxlint on changed files → clean
  • pre-commit (typecheck + build) → ok

Diff stat

 src/agent/director.ts              | 13 ++++++++++++-
 src/agent/tool-set-digest.test.ts  | 53 ++++++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+), 1 deletion(-)

toolSetDigest re-hashed the full tool array on every call. Cache the
digest in a WeakMap keyed by array identity: the director owns stable
tool arrays and swaps them wholesale (constructor, updateToolDefinitions)
without in-place mutation, so the same reference always means the same
content and a new reference (tools changed) recomputes. A WeakMap also
avoids retaining arrays the director has dropped. Output is byte-identical
for the same tool set.

Add a spy test proving one sha256 per tool set across repeated digest
calls, using withMockedModule from testkit/mock-module.ts.
@linear-code

linear-code Bot commented Oct 12, 2026

Copy link
Copy Markdown

CL-10536

@corbits-triage

Copy link
Copy Markdown
Contributor

No changes needed from you. A maintainer will review this pull request.

@TheGreatAxios TheGreatAxios changed the title CL-10536: Memoize toolSetDigest instead of re-hashing every call perf(agent): memoize toolSetDigest per tool set Oct 12, 2026
The digest is only ever consumed by ChatDirectorImpl.updateToolDefinitions,
so a module-level WeakMap keyed by array identity is heavier than the call
pattern needs. Move the memoization onto the director as a last-digest
field: the incoming set is hashed once when installed and the previous
set's digest is reused from the field on the next update. toolSetDigest
becomes a pure function with identical digest values; the proof test now
spies through updateToolDefinitions to show one hash per installed tool
set per director.

@TheGreatAxios TheGreatAxios left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review · Comment

Memoizes toolSetDigest on the director. Incoming tool sets are hashed when installed; the previous digest is an instance field used only to skip a repeat debug log.

Findings

No findings. bun test src/agent/tool-set-digest.test.ts src/agent/director.test.ts — 88 pass, 0 fail.

Commit bodies on this branch wrap past 72 characters and walk the implementation (perf(agent): memoize toolSetDigest per director, not per module). Subjects are within the limit. Not a code defect.

@corbits-triage
corbits-triage Bot merged commit d88ebad into main Oct 13, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant