- Fixed response body reuse error when handling 429 rate limit responses by cloning response before reading error body.
- Added test case to verify 429 errors surface correctly without body reuse failures.
- Added graceful schema validation fallback mechanism that degrades to unconstrained schemas on repeated validation failures.
- Enhanced schema enforcement across AI providers to use try-catch pattern with automatic fallback to non-strict mode on validation errors.
- Improved handling of circular, deeply nested, and non-object output schemas with stack overflow prevention and type conversion fallbacks.
- Added `tryEnforceStrictSchema()` utility function providing error-resilient schema validation with strict mode flag tracking.
- Add Sonnet 4.6 to Bedrock supportsAdaptiveThinking check (was Opus-only,
causing thinking to be silently disabled for Sonnet 4.6 on Bedrock)
- Clamp 'max' effort to 'high' for Sonnet 4.6 on Bedrock (max is
Opus 4.6 only per Anthropic API docs)
- Add output_config effort support for Opus 4.5 alongside budget-based
thinking (Opus 4.5 supports effort per Anthropic docs but was not
sending it)
Co-authored-by: Miroslav Drbal <miroslav.drbal@gendigital.com>
- Added `sanitizeSchemaForStrictMode` function to normalize JSON schemas by removing non-structural keys for strict mode compatibility.
- Enhanced `enforceStrictSchema` to handle union types with object variants and type arrays containing object.
- Fixed `enforceStrictSchema` to properly handle malformed object schemas with required keys.
- Integrated schema sanitization in coding-agent submit-result tool with fallback to non-strict mode on validation errors.
- Fixed `enforceStrictSchema` to properly handle malformed object schemas with required keys but missing properties.
- Fixed `enforceStrictSchema` to correctly process nested object schemas within `anyOf`, `allOf`, and `oneOf` combinators.
- Added type guards to validate schema entries before recursive processing to prevent incorrect transformations.
- Added 2 test cases covering malformed object normalization and nested schema repair scenarios.
- Added support for four new exec message types: listMcpResources, readMcpResource, recordScreen, and computerUse.
- Imported four new result schemas to handle responses for MCP resource operations and computer use capabilities.
- Updated bash execution handler to use standardized 'cwd' parameter name instead of 'workdir'.
- Added topP, topK, minP, presencePenalty, and repetitionPenalty sampling control options to StreamOptions and AgentOptions interfaces.
- Implemented getter and setter properties on Agent class for runtime configuration of model sampling parameters.
- Added UI configuration and preset value providers for five new sampling parameters in coding-agent settings schema and components.
- Integrated sampling control parameters through proxy layer and agent session configuration for end-to-end provider support.
* fix(ai): coerce string-to-number for Optional<number> parameters
When a tool schema uses Type.Optional(Type.Number()), TypeBox generates
an anyOf:[{type:"number"},{type:"null"}] schema. AJV reports validation
failures against this as keyword:"anyOf" errors rather than
keyword:"type" errors.
coerceArgsFromErrors only processes keyword:"type" errors, so Optional
numeric fields were invisible to the coercion loop. normalizeOptionalNullsForSchema
traverses anyOf branches recursively but returned early at primitive-type
branches (type !== "object") without attempting string coercion, so the
anyOf traversal produced no change and the string was left uncoerced.
Fix: add a string-to-number coercion guard in normalizeOptionalNullsForSchema
before the early return, covering schema branches that declare
type:"number" or type:"integer". This allows the existing anyOf
traversal to coerce "1.0" -> 1.0 when the schema is Optional<number>.
Required numeric fields (Type.Number()) were unaffected as they produce
keyword:"type" errors handled by the existing path.
Reproducer: any MCP tool with an optional float parameter (e.g. tick_size:
Option<f64> in Rust/schemars) receives the value as a string from the
LLM and fails deserialization despite the coercion infrastructure being
designed to handle exactly this case.
* style: biome format validation.ts and coercion test
---------
Co-authored-by: Miroslav Drbal <miroslav.drbal@gendigital.com>
- Consolidated @oh-my-pi/pi-utils subpath imports into single package root import across 100+ files.
- Moved tryParseJson utility from local web scrapers module to @oh-my-pi/pi-utils package for centralized JSON parsing.
- Renamed loadSkillsFromDir to scanSkillsFromDir and refactored skill discovery to use fs.promises.readdir instead of glob-based approach.
- Replaced custom parseJSON with tryParseJson across discovery modules for consistent error handling.
- Removed emitCustomToolSessionEvent method and cleanupSshResources function, consolidating shutdown logic into dispose method.
- Updated glob pattern construction to use GlobBuilder with literal_separator(true) for improved path handling.
- Added fallback empty string for undefined tool descriptions across all AI providers to prevent runtime errors.
- Made `description` field required in CustomTool interface and normalized tool descriptions in agent-loop.
- Refactored tool normalization in agent-loop by renaming `injectIntentIntoTools()` to `normalizeTools()` with conditional intent injection.
- Added comprehensive description metadata to todo-write tool schema fields for improved clarity.
- Added GitHub Copilot provider support for strict mode in openai-completions and openai-responses tool schemas.
- Updated detectStrictModeSupport() and supportsStrictMode() functions to recognize github-copilot as a strict mode compatible provider.
- Added test coverage for GitHub Copilot strict mode support in both openai-completions and openai-responses tool schemas.
- Introduced OAuthManualInputManager and routed callback-server logins to await pasted redirect URLs with a visible tip.
- Extended /login slash command to submit redirect URLs, block overlapping logins, and covered manual callbacks in tests.
- Propagated onManualCodeInput through OAuth provider login helpers with a default authorization prompt.
- Resolved docs index generation paths using path.resolve relative to the script directory.
- Consolidated developer message role conversion.
- Removed dedicated developer role processing blocks.
- Mapped developer role to user if not explicitly supported.
- Eliminated developer role fallback to system.
- Exported `isProviderRetryableError` function for detecting rate-limit and transient stream errors.
- Expanded retry detection to include JSON parse errors (unterminated strings, unexpected end of input) from Anthropic-compatible proxy endpoints.
- Added comprehensive test suite for retry detection covering rate-limit, stream parse, and validation errors.
- Enhanced GitLab Duo model mapping to support canonical model IDs with fallback lookup.
- Simplified Anthropic auth resolution from 4-tier to 3-tier priority system.
- Fixed artifact manager cache invalidation by validating session file before reuse.
- Improved JSONL parsing in stats package with streaming parser and error handling.
- Migrated AuthCredentialStore and AuthStorage to shared modules, standardizing credential management and soft deletion.
- Consolidated Anthropic authentication and various other formatting/utility helpers into shared modules.
- Improved unicode normalization in patch logic with regex for efficiency and correctness.
- Enhanced JTD type guards for robust schema validation.
- Extracted credential storage to shared @oh-my-pi/pi-ai package with AuthCredentialStore and AuthStorage classes.
- Consolidated UI formatting logic from ToolUIKit class into standalone utility functions across render-utils and output-meta modules.
- Moved utility functions (parseCommandArgs, substituteArgs, expandPath, normalizeUnicode) to dedicated modules for improved code reuse.
- Extracted JTD type definitions and type guards to jtd-utils module for shared use across schema conversion tools.
- Updated Claude model pricing and added cache read costs in models.json for accurate billing calculations.
- Refactored agent-storage to delegate credential management to AuthCredentialStore instead of direct SQLite operations.
- Added GitLab Duo provider with support for Claude, GPT-5, and Duo Chat models via GitLab AI Gateway.
- Added OAuth authentication for GitLab Duo with automatic token refresh, PKCE security, and 25-minute token caching.
- Added 16 new GitLab Duo models including Claude Opus/Sonnet/Haiku and GPT-5 variants with reasoning and multimodal support.
- Added `isOAuth` option to Anthropic provider for OAuth bearer token authentication mode.
- Exported `streamGitLabDuo`, `getGitLabDuoModels`, and `clearGitLabDuoDirectAccessCache` functions for GitLab Duo integration.
- Consolidated Gemini CLI and Antigravity headers into central definitions.
- Split Antigravity headers into distinct authentication and streaming sets.
- Enabled User-Agent configuration via environment variables.
- Ensured consistent header usage across relevant services.
Export getAntigravityHeaders() from pi-ai and replace duplicated
ANTIGRAVITY_HEADERS constants in gemini-image tool and Gemini search
provider with calls to the centralized function.
Fixes#132
- Fixed persistent shell session state not being reset after command abort or hard timeout.
- Fixed hard timeout handling to properly interrupt long-running commands exceeding grace period.
- Introduced hard timeout mechanism with Promise.race() to enforce absolute timeout limit and prevent command hangs.
- Replaced shell command execution with explicit timeout and SIGKILL signal handling in shell-snapshot.
- Simplified bash command normalization to use only explicit head/tail parameters from tool input.
- Exported getAntigravityUserAgent() function for centralized User-Agent header construction.
- Exported getAntigravityUserAgent() function for centralized User-Agent header construction.
- Updated default Antigravity version from 1.15.8 to 1.18.3.
- Unified User-Agent header generation across Antigravity API calls to use centralized function.
Pass execHandlers?.read?.bind(execHandlers) (and same for ls, grep, write,
delete, shell, diagnostics, mcp) so handler methods keep correct 'this'
context when invoked by the Cursor exec protocol.
- Added configurable model refresh strategies (online, online-if-uncached) to control model discovery behavior.
- Implemented global model.dev fallback resolution with context window and token prioritization for improved model attribute consistency.
- Incremented model cache schema version to support improved global model fallback resolution.
- Enhanced model generation script with dedicated functions for building model reference maps and applying fallback attributes.
- Improved GitHub Copilot model resolution to inherit provider-specific definitions over global references when context window is larger, ensuring optimal model capabilities.
- Refactored bundled and global model reference map creation into dedicated helper functions for clarity.
- Added compatibility flags for openai-completions API variant to disable unsupported features (store, developer role, reasoning effort).
- Exported readModelCache and writeModelCache functions for SQLite-backed model cache access.
- Migrated model cache storage from per-provider JSON files to unified SQLite database (models.db).
- Renamed cachePath option to cacheDbPath in ModelManagerOptions for database-backed storage.
- Improved non-authoritative cache handling with 5-minute retry backoff instead of per-startup retries.
- Added peekApiKey method to AuthStorage for non-blocking API key retrieval during model discovery.
- Added <turn_aborted> guidance marker as synthetic user message for aborted/errored assistant messages.
- Added `<turn_aborted>` guidance marker as synthetic user message when assistant messages are aborted or errored, informing the model that tools may have partially executed.
- Modified handling of aborted/errored assistant messages to preserve tool call structure instead of converting to text summaries, with synthetic 'aborted' tool results injected.
- Updated tool call tracking to use status map (Resolved/Aborted) instead of separate sets for better handling of duplicate and aborted tool results.
- Added comprehensive test suite for Codex-style abort handling with 4 test cases covering tool call preservation, guidance markers, synthetic results, and existing result skipping.
- Added raw HTTP request dumps to error messages for 400 status codes.
- Implemented client-side retry for Anthropic streaming on transient errors.
- Preserved context by converting aborted assistant tool calls to text.
- Optimized model registry refresh in coding agent sessions.
- Added time-budget-based retry strategy for Google Gemini 429 rate limit errors with 5-minute window.
- Set default maxRetries to 5 for Anthropic, Azure OpenAI, and OpenAI clients.
- Implemented separate 429 rate limit handling with cumulative time budget tracking instead of bounded retry attempts.
Split Codex error handling: usage_limit_reached/usage_not_included show
"usage limit" message, while rate_limit_exceeded/bare 429 show "rate
limit exceeded" — so transient throttling no longer looks like a
subscription cap.
Changed 429 retry strategy: when the server provides a retry delay
(retry-after header or body hint), use a 5-minute time budget instead
of the fixed 5-attempt cap. Transient rate limits now wait and retry
rather than giving up after a few seconds.