Skip to content

fix(agent): store parsed values and enforce object refinements in context setters - #161

Open
alexb-openrouter wants to merge 1 commit into
mainfrom
devin/1794488003-tool-context-store-parsed
Open

alexb-openrouter wants to merge 1 commit into
mainfrom
devin/1794488003-tool-context-store-parsed

Conversation

@alexb-openrouter

@alexb-openrouter alexb-openrouter commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Risk fixed: ctx.setContext() / ctx.setSharedContext() called z4.parse(fieldSchema, value) for each field but stored the raw input. Field transforms, defaults and coercions declared in contextSchema / sharedContextSchema were never applied to what later tools read. For example, with level: z.number().transform(n => Math.min(n, 0)), a tool could store level: 1, and the next tool would see 1. Object-level .refine() checks were also not run when writing. They were only enforced later, when the next tool's context was built.

Change in validatePartialAgainstSchema (tool-context.ts):

// before: z4.parse(keySchema, value); store value
// after:
parsedPartial[key] = z4.parse(keySchema, value);
z4.parse(schema, { ...existing, ...parsedPartial }); // whole-object check, throws on refine failure
store.mergeToolContext(key, parsedPartial);
  • The stored value is the schema's output for each updated field.
  • The merged context is validated against the full schema before it is stored. A failing update throws, and the stored context is left unchanged. This matches the invariant buildToolExecuteContext already enforces when it validates stored context eagerly, so the error now happens at the write instead of at the next tool call.

Tests: new cases in shared-context.test.ts cover the transform for setSharedContext and setContext, and an object-level refinement that rejects a write and then accepts it once the other field allows it. All three fail on main and pass with this change. Full unit suite, biome and typecheck pass.

Note: open PR #107 (Standard Schema support) rewrites this same function and keeps the old raw-value behavior on its Zod path. Whichever PR merges second needs a rebase, and that rebase should keep the parsed-output and whole-object checks.

…text setters

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

devin-ai-integration Bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access that start with 'Devin'.

  • Disable automatic comment, CI, and merge conflict monitoring

This branch has not been deployed

No deployments
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.

1 participant