Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions docs/src/content/docs/docs/QuickAddAPI.md
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,9 @@ const { text, steps, toolCalls } = await agent.generate({
- `system` - system prompt (defaults to your AI Assistant default system prompt).
- `tools` - an object map of tool name → tool (from `ai.tool()` and/or `ai.tools.*`).
- `toolChoice` - `"auto"` (default) | `"none"` | `"required"` | `{ type: "tool", toolName }`.
Some models can't be forced to call a tool: Claude Opus 5.5 and Claude Fable 5.1 reject
`"required"` and `{ type: "tool", toolName }`, and QuickAdd's error says so. Use
`"auto"` and say in the prompt when the tool applies, or pass a `schema` for a fixed JSON shape.
- `stopWhen` - one or more stop conditions from `ai.stepCountIs(n)` / `ai.hasToolCall(name)`.
- `maxSteps` - step budget (default 20, hard cap 100). Sugar for `stopWhen: ai.stepCountIs(n)`.
- `maxOutputTokens`, `modelOptions` - passed to the provider.
Expand Down Expand Up @@ -788,15 +791,16 @@ GPT-4o-class), Anthropic Claude 4.x, and Gemini 3.x; it can be combined with too
that do not support schema-constrained output (e.g. legacy OpenAI chat models) reject the request
outright with a provider error - use a current model rather than expecting a best-effort fallback.

:::note[OpenAI reasoning models (GPT-5.x, o-series)]
These accept only the default `temperature` (omit it from `modelOptions`), and QuickAdd
automatically sends `maxOutputTokens` as `max_completion_tokens` for them. The agent's default
path sets neither, so `quickAddApi.ai.agent({ model: "gpt-5" })` works as-is.
:::note[OpenAI reasoning models (GPT-5.x, GPT-6, o-series)]
These accept only the default `temperature` (omit it from `modelOptions`). The agent sends no
`temperature` unless you set one, so `quickAddApi.ai.agent({ model: "gpt-6-luna" })` works as-is.

GPT-5.6 and GPT-6 models reason by default, and OpenAI's Chat Completions API rejects function
tools for them unless reasoning is off. When a tool turn is rejected for that reason, QuickAdd
retries it once with `reasoning_effort: "none"`. If you set `reasoning_effort` yourself in
`modelOptions`, QuickAdd keeps it and shows the provider's error instead.
Agent turns to OpenAI's own API (`https://api.openai.com/v1`) use the Responses API, which lets
reasoning models such as GPT-5.6 and GPT-6 call tools with reasoning on. Other OpenAI-compatible
providers use Chat Completions. `modelOptions` keep their Chat Completions names either way:
QuickAdd sends `reasoning_effort` as `reasoning.effort` and `max_tokens` as `max_output_tokens`
on the Responses API, and sends `maxOutputTokens` as `max_completion_tokens` to reasoning models
on Chat Completions.
:::

### `getModels(): string[]`
Expand Down
13 changes: 12 additions & 1 deletion src/ai/OpenAIRequest.sampling.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,18 @@ describe("sampling parameter recovery (chat/tool path)", () => {
getModelProviderMock.mockReturnValue(openaiProvider);
requestUrlMock
.mockReturnValueOnce(Promise.resolve(unsupportedParamFailure("top_p")))
.mockReturnValueOnce(Promise.resolve(openaiSuccess("chat ok")));
// Chat turns on api.openai.com use the Responses API.
.mockReturnValueOnce(
Promise.resolve({
status: 200,
json: Promise.resolve({
id: "resp_1",
status: "completed",
output: [{ type: "message", content: [{ type: "output_text", text: "chat ok" }] }],
usage: { input_tokens: 1, output_tokens: 1, total_tokens: 2 },
}),
}),
);

const model: Model = { name: "o4-mini", maxTokens: 200000 };
const res = await chatRequest(makeApp(), "sk", model, currentProvider(), {
Expand Down
166 changes: 0 additions & 166 deletions src/ai/OpenAIRequest.toolReasoning.test.ts

This file was deleted.

Loading
Loading