feat(ai): add schema-constrained structured completion - #19
Draft
jordanrinke wants to merge 23 commits into
Draft
Conversation
this supports BUN_CONFIG_HTTP_IDLE_TIMEOUT related to earendil-works#6476
This adds cache-friendly dynamic tool loading anchored to tool results. Purely additive active-tool changes are recorded with `addedToolNames`, allowing supported Anthropic and OpenAI Responses models to load tool definitions at the point they become available instead of placing them in the cached prompt prefix. It retains safe fallback behavior for unsupported models and non-additive changes but it will wipe caches.
Do not treat Pi’s internal ambient-auth marker as a Bedrock bearer token. This preserves SigV4 signing for AWS profiles, IAM credentials, and roles while retaining bearer authentication for real Bedrock API keys.\n\nFixes earendil-works#6531
…entials (earendil-works#6292) Cloudflare Workers AI / AI Gateway resolved provider config from the credential only, never consulting ambient env for a field the credential omitted. The coding-agent /login flow stores just the API key, so CLOUDFLARE_ACCOUNT_ID lives only in the environment; the key-only credential short-circuited the env lookup, the account id stayed unresolved, and requests hit the literal {CLOUDFLARE_ACCOUNT_ID} base URL -> 404. resolveValue now merges per field: prefer the credential value, fall back to ctx.env(name). closes earendil-works#6021 Signed-off-by: Mark Phelps <209477+markphelps@users.noreply.github.com> Co-authored-by: Mario Zechner <badlogicgames@gmail.com>
…n per tool (#21) Tool.strict is a new opt-in boolean. OpenAI Chat Completions, shared OpenAI/Azure Responses (including deferred tools), and Anthropic Messages now strictify a tool's schema only when tool.strict === true. Ordinary tools keep their original schema and reprompt-loop validation. PI_STRICT_TOOLS=0 remains a global emergency kill switch that forces every tool non-strict, including opted-in ones. Provider/model compat (supportsStrictMode) remains a capability gate. Codex and Mistral are unchanged (they already pass strict: null / false explicitly). completeStructured()'s internal fallback output tool is marked strict: true so existing structured-output behavior via context.tools is preserved. Propagate strict through coding-agent's ToolDefinition and both tool-definition-wrapper conversions (wrapToolDefinition, createToolDefinitionFromAgentTool) so extension-registered tools do not silently lose the flag. Tests: - packages/ai/test/per-tool-strict.test.ts: ordinary vs opted-in vs mixed batches for OpenAI Chat, OpenAI Responses, Azure Responses, and Anthropic, plus PI_STRICT_TOOLS=0 kill-switch coverage. - packages/ai/test/deferred-tools.test.ts: updated ordinary-tool expectations to non-strict; added opted-in immediate/deferred coverage for Anthropic and OpenAI Responses tool search. - packages/coding-agent/test/tool-definition-wrapper.test.ts: strict flag propagation in both wrapper directions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the additive
completeStructured()API in@earendil-works/pi-ai/compat.It creates one internal schema-constrained output tool, forces that tool on builtin
providers where supported, validates the returned arguments against the original
schema, and never accepts assistant text as JSON. Existing
complete*/stream*APIs and normal agent tool calling remain unchanged.
Gemini follow-up required
A live typed probe of
google/gemini-3.1-pro-previewauthenticated successfully,but returned no function call even though the request contained one output tool and
Gemini
FunctionCallingConfig.mode = ANY.completeStructured()correctly failedclosed with:
The same schema-constrained probe passed for Bedrock Claude Fable 5, Azure GPT-5.6
Terra, and Bedrock Sonnet 5. Do not use Gemini 3.1 Pro as a structured-output
reviewer until this provider behavior is fixed and verified by a real probe.
Likely follow-up: determine whether Gemini 3.1 requires an explicit
allowedFunctionNames: ["submit_structured_output"], a different function schemafield, or native response-schema handling. That work is intentionally not included
in this PR; no speculative Gemini provider change is committed.
Verification
@earendil-works/pi-aitests: 24 passednpm run checkpassed