Skip to content

refactor: make tool registry plugin-primary and harden duplicate registration#16

Open
iamthehobbit wants to merge 8 commits intoShinMegamiBoson:mainfrom
iamthehobbit:op-pr2-plugin-primary
Open

refactor: make tool registry plugin-primary and harden duplicate registration#16
iamthehobbit wants to merge 8 commits intoShinMegamiBoson:mainfrom
iamthehobbit:op-pr2-plugin-primary

Conversation

@iamthehobbit
Copy link

Summary

This PR completes the built-in plugin migration and makes plugin/registry definitions the primary source for tool export (with compatibility fallback retained during transition).

It also hardens duplicate plugin registration behavior.

What’s included

  • Migrates all built-in tools to registry-first dispatch (legacy fallback still retained)
  • Makes tool-definition export plugin/registry-primary
  • Adds standalone pedagogical built-in plugin module example (list_files)
  • Hardens duplicate plugin registration:
    • duplicate names rejected by default
    • explicit override allowed only when metadata matches exactly
  • Adds/updates tests for duplicate behavior and plugin parity

Tests Added / Coverage

  • tests/test_tool_registry.py
    • duplicate plugin registration raises by default
    • explicit override path with metadata match
    • conflicting duplicate metadata/policy raises
  • tests/test_builtin_tool_plugins.py
    • full built-in plugin set parity after migration
  • tests/test_tool_defs.py
    • plugin-primary export path remains active and falls back safely
  • tests/test_engine.py
    • registry dispatch coverage extended to migrated built-ins

Why

This makes the tool system reliably extensible and safer for future plugin-based integrations.

Risk / compatibility

  • Intended behavior is unchanged for existing built-in tools
  • Duplicate semantics are stricter (by tool name + metadata consistency)

ShinMegamiBoson and others added 8 commits February 21, 2026 19:58
… and tests

New data sources cataloged with fetch scripts and validation tests:
- FEC federal campaign finance (API + bulk)
- USASpending.gov federal contracts (API)
- SAM.gov contractor registrations (API)
- SEC EDGAR public company filings (API)
- FDIC BankFind institution data (API)
- ProPublica Nonprofit Explorer / IRS 990 (API)
- Senate lobbying disclosures LD-1/LD-2 (bulk XML)
- EPA ECHO enforcement & compliance (API)
- OSHA inspection data (API)
- OFAC SDN sanctions list (bulk CSV)
- ICIJ Offshore Leaks database (bulk CSV)
- US Census Bureau ACS (API)

All scripts use Python stdlib only. 104 new tests pass (18 skip
without API keys or network). Wiki index updated with new categories.
- Replace _ThinkingDisplay with _ActivityDisplay supporting three modes:
  thinking (cyan), streaming response (green), tool execution (yellow)
- Auto-transition from thinking→streaming on first text delta
- Show step counter (Step N/max) in activity spinner
- Show tool name and key argument during tool execution
- Add engine cancellation via threading.Event (_cancel flag)
- Run agent in background thread so user can type next question
- Queue typed input during agent execution (FIFO)
- ESC key binding cancels the running agent
- Add 13 tests covering ActivityDisplay, cancellation, and queuing
Extends ToolResult with optional ImageData payload and adds a read_image
tool that reads PNG/JPEG/GIF/WebP files, base64-encodes them, and passes
them through to the model layer in provider-specific formats (Anthropic
content blocks, OpenAI data URI in user messages).
Add 5 reusable analysis scripts:
- quickstart_investigation.py: starter template for investigations
- scripts/entity_resolution.py: entity linking pipeline
- scripts/cross_link_analysis.py: cross-referencing engine
- scripts/build_findings_json.py: report synthesis utility
- scripts/timing_analysis.py: statistical timing correlation

Fix TUI flicker by making _ActivityDisplay a Rich renderable (__rich__
protocol) so Live's 8fps auto-refresh polls state instead of feed()
forcing update() on every token delta.
Tell the agent about replay.jsonl, events.jsonl, and state.json in its
session directory so it can read its own prior transcripts and recall
earlier work within a session.
…ape sequences

Root cause: prompt_toolkit's patch_stdout() wraps sys.stdout with StdoutProxy
which corrupts Rich's ANSI escape sequences — replacing ESC bytes (0x1b) with
'?' (0x3f). This caused raw escape codes like ?[2K?[1A?[2K to appear as
visible text instead of being interpreted by the terminal.

Fix: scope patch_stdout() to only wrap session.prompt(), not the entire main
loop. During agent execution, Rich's Live writes directly to the real stdout
with correct escape sequences. Also remove the secondary prompt loop (which
compounded the issue) and switch cancellation from ESC to Ctrl+C.

Verified via PTY test: 36 correct ESC sequences, 0 corrupted (was 0/16).
@iamthehobbit
Copy link
Author

This PR is part of a tested integration series. Suggested review/merge order: #14 -> #16 -> #15 -> #17.\n\nRecommended to review after #14. Opened against due upstream base-branch constraints for fork-only stacked branches.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants