Skip to content

feat: spill Pydantic BaseModel tool results - #11

Open
thomwebb wants to merge 1 commit into
mpfaffenberger:mainfrom
thomwebb:feat/spill-base-models
Open

feat: spill Pydantic BaseModel tool results#11
thomwebb wants to merge 1 commit into
mpfaffenberger:mainfrom
thomwebb:feat/spill-base-models

Conversation

@thomwebb

Copy link
Copy Markdown
Collaborator

What

The spill plugin now also bounds Pydantic BaseModel tool results, not just dicts.

This closes the plugin's biggest practical gap: most big-output built-in tools return models, not dicts — agent_run_shell_commandShellCommandOutput, list_filesListFileOutput, invoke_agentAgentInvokeOutput — and until now those all passed through spill untouched. (The dict-returning tools, e.g. create_file's {"path", "message"}, were the small ones.)

How (small on purpose)

  • _field_map() — a dict(result) view for models; the existing planner/notice/store machinery is reused verbatim, operating on field names instead of dict keys.
  • _commit_replacements() — item assignment for dicts, setattr for models; on a rejected assignment (frozen model, validate_assignment validator) it restores already-applied fields and re-raises, and the outer hook's existing fail-open path keeps the result byte-identical inline.
  • No allowlists, no contract pinning, no new config: any BaseModel with oversized plain-string top-level fields is eligible; exotic cases (frozen, rejecting validators) simply stay inline.

Verified end-to-end against current app main: a ShellCommandOutput with 4 KB stdout at a 500-byte cap becomes head/tail preview + retrieval notice, file written verbatim.

Tests (tests/test_spill_models.py, local models — no app-tool imports)

  • oversized field spilled in place; file verbatim; notice contains path; other fields untouched
  • under-cap model untouched
  • frozen model fails open, stays inline
  • commit rollback restores prior fields when a validate_assignment validator rejects a preview

Full spill suite on app main: 21 passed, 4 skipped (the 4 skips are the per-agent tests gated on the runtime execution-context seam, from #9). Ruff clean.

@WSxDemise

Copy link
Copy Markdown
Contributor

[Wes's CodePuppy Agent Review]

Adds mutable Pydantic BaseModel handling to spill, with documentation and focused unit coverage.

Qodo Merge Triage

Qodo: not configured for OSS/public GitHub.

Really Should Fix These

None.

Nits

None.

Scope observations — not changes requested on this PR

  • [P0] [UNIMPLEMENTED] Hook-context BaseModel results remain unbounded — code_puppy_core_plugins/code_puppy_agent/SYSTEM_PROMPT_CONFIG_AND_I18N.md:83
    • Impact: When Emoji Filter strips an emoji from a shell command (on by default), core converts ShellCommandOutput to str before spill, leaving large stdout in model context.
    • Fix: File a companion code_puppy core PR to preserve structured results while prepending hook context, with an integration test for an emoji-filtered shell result.

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