@linxiraos/pi-ai 1.1.8 → 1.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -20
- package/README.md +66 -66
- package/dist/types/auth-storage.d.ts +1 -1
- package/dist/types/providers/amazon-bedrock.d.ts +7 -0
- package/dist/types/providers/anthropic.d.ts +1 -1
- package/dist/types/providers/cursor.d.ts +2 -2
- package/dist/types/providers/inference-headers.d.ts +24 -0
- package/dist/types/providers/openai-codex/request-transformer.d.ts +7 -10
- package/dist/types/providers/openai-codex-responses.d.ts +6 -10
- package/dist/types/providers/openai-configuration-update.d.ts +64 -0
- package/dist/types/providers/openai-responses-wire.d.ts +15 -1
- package/dist/types/providers/openai-responses.d.ts +6 -1
- package/dist/types/providers/openai-shared.d.ts +13 -1
- package/dist/types/registry/engine/oauth-code.d.ts +1 -1
- package/dist/types/registry/oauth/callback-server.d.ts +2 -0
- package/dist/types/registry/oauth/native-scheme-callback.d.ts +13 -0
- package/dist/types/registry/oauth/types.d.ts +2 -1
- package/dist/types/types.d.ts +7 -0
- package/dist/types/utils/proxy.d.ts +7 -0
- package/dist/types/utils/request-debug.d.ts +6 -5
- package/dist/types/utils/transport-fetch.d.ts +18 -0
- package/dist/types/utils.d.ts +8 -0
- package/package.json +109 -111
- package/src/auth-storage.ts +11 -10
- package/src/error/rate-limit.ts +9 -1
- package/src/providers/amazon-bedrock.ts +72 -5
- package/src/providers/anthropic.ts +94 -21
- package/src/providers/cursor.ts +16 -19
- package/src/providers/google.ts +6 -0
- package/src/providers/inference-headers.ts +80 -0
- package/src/providers/openai-codex/request-transformer.ts +9 -15
- package/src/providers/openai-codex-responses.ts +57 -13
- package/src/providers/openai-completions.ts +3 -0
- package/src/providers/openai-configuration-update.ts +170 -0
- package/src/providers/openai-responses-wire.ts +15 -0
- package/src/providers/openai-responses.ts +42 -1
- package/src/providers/openai-shared.ts +30 -19
- package/src/providers/pi-native-server.ts +1 -0
- package/src/providers/transform-messages.ts +10 -6
- package/src/registry/engine/oauth-code.ts +3 -1
- package/src/registry/oauth/callback-server.ts +152 -24
- package/src/registry/oauth/native-scheme-callback.ts +62 -0
- package/src/registry/oauth/types.ts +2 -1
- package/src/stream.ts +52 -29
- package/src/types.ts +7 -0
- package/src/usage/google-antigravity.ts +236 -42
- package/src/utils/proxy.ts +37 -31
- package/src/utils/request-debug.ts +6 -29
- package/src/utils/transport-fetch.ts +50 -0
- package/src/utils.ts +21 -24
package/CHANGELOG.md
CHANGED
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
-
## [1.1.
|
|
5
|
+
## [1.1.10] - 2026-09-07
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
7
|
+
- GitHub Copilot sign-in now requests only basic profile access, restoring login for Enterprise organizations that reject repository, gist, and Codespaces permissions.
|
|
8
|
+
- Transient gateway stream failures are now retried instead of surfacing as session errors.
|
|
9
|
+
|
|
10
|
+
## [1.1.9] - 2026-09-05
|
|
11
|
+
|
|
12
|
+
- Z.ai OAuth key name sends zeta (merge restored the upstream oh-my-pi literal in tests); xAI/OpenAI-compatible requests send the zeta User-Agent again.
|
|
9
13
|
|
|
10
14
|
## [1.1.6] - 2026-08-30
|
|
11
15
|
|
|
@@ -43,20 +47,3 @@
|
|
|
43
47
|
|
|
44
48
|
- Reset the version to 1.0.0 and republished under the `@linxiraos/*` scope, breaking from the `@linxiraos` version lineage.
|
|
45
49
|
- Fixed Gemini thought summaries occasionally leaking a raw `` ```thinking `` / `` ``````thinking `` fence delimiter into the reasoning block, so it no longer shows up as fence spam in the thinking display or persisted transcripts ([#8719](https://github.com/can1357/oh-my-pi/issues/8719)).
|
|
46
|
-
- Fixed the OpenCode Go login prompting for an "OpenCode Zen API key": the shared login flow now names the provider you selected, so connecting OpenCode Go asks for an OpenCode Go key (the `opencode.ai/auth` console is still shared, as documented upstream) ([#8738](https://github.com/can1357/oh-my-pi/issues/8738)).
|
|
47
|
-
- Fixed Anthropic-compatible endpoints with strict prompt validation (e.g. Z.AI GLM `api.z.ai/api/anthropic`, which rejects the whole request with `400 code 1213 "The prompt parameter was not received normally"`) failing sessions once a tool returned empty output on a vision-capable model: empty successful `tool_result` blocks now encode as `content: ""` instead of `content: []`, which both the official API and strict compatible endpoints accept.
|
|
48
|
-
- Fixed `retry.usageReservePct` (Reserve Margin) ignoring Claude Fable/Mythos weekly tier usage until it hit 100%, so a Fable model kept serving turns past the configured reserve; reserve health now honors the mapped tier row while credential-wide hard blocks still require confirmed exhaustion ([#8773](https://github.com/can1357/oh-my-pi/issues/8773)).
|
|
49
|
-
- Fixed `cursor-agent` streams stalling with "Provider stream stalled while waiting for the next event" when Cursor asked the client to approve a hosted WebFetch / web search (reproduced on `cursor-grok-4.6-xhigh` after "I'll fetch the page…"). Those `interaction_query` frames — including the newer WebFetch field 9 this proto did not name — were dropped, so the server waited forever and the idle watchdog aborted a live connection. Permission queries are now answered; hosted search/fetch is approved, unnamed permission fields get an `approved` reply on the same field number, and prompts this client cannot serve are rejected so the turn can continue.
|
|
50
|
-
|
|
51
|
-
### Fixed
|
|
52
|
-
|
|
53
|
-
- Fixed thinking effort selections being ignored for local Qwen 3.8+ models on llama.cpp and vLLM: the Qwen chat-completions dialects only toggled `enable_thinking`, so the chat template always reasoned at its `xhigh` default no matter which level was selected. The encoder now routes the requested effort onto the template's `reasoning_effort` kwarg (`chat_template_kwargs` for both Qwen dialects, plus the top-level field newer llama.cpp builds map natively).
|
|
54
|
-
- Fixed OpenAI Completions, Amazon Bedrock, and Cursor providers ignoring `onPayload` replacement payloads. The hook now transforms the actual request body sent upstream on these providers, matching the Anthropic/Gemini/OpenAI Responses replacement contract. `devin-agent` still does not fire the hook (its payload is a protobuf object).
|
|
55
|
-
- Fixed Codex requests failing outright when the signed-in ChatGPT account is not entitled to the requested model; the exact model denial is now classified as an account-policy error so credential rotation can reach an entitled sibling account
|
|
56
|
-
- Fixed Perplexity email-OTP login after its verification response renamed the encrypted session token from `token` to `challenge_token`.
|
|
57
|
-
- Cloud Code Assist Gemini 3.6/3.7 Flash requests at `minimal` now send `thinkingLevel: LOW` on the aliased `-low` SKU instead of `MINIMAL`, which the API rejects with HTTP 400.
|
|
58
|
-
- Answer Cursor `interaction_query` permission gates (hosted web search, Exa, unnamed field-9 WebFetch) so the Run RPC continues instead of sitting silent until the 300s idle watchdog.
|
|
59
|
-
- Fixed provider tool calls arriving with flattened array argument paths (e.g. Gemini's `questions[0].id`) being stripped and rejected by argument validation; well-formed flattened paths are now rebuilt into the nested arrays the tool schema expects ([#8886](https://github.com/can1357/oh-my-pi/issues/8886)).
|
|
60
|
-
- Fixed opencode-go (Console Go) rejecting Responses turns with `400 No tool output found for tool call …` (naming a random call of the batch on each retry) when a model streamed a trailing text/thinking block after its tool calls: `buildResponsesInput` emitted that block as an assistant `message` item wedged between the `function_call` batch and its `function_call_output` items. Such interleaved messages are now hoisted ahead of their call batch (canonical `message(s) → calls → outputs`), which the strict gateway validator accepts; content is unchanged ([#8789](https://github.com/can1357/oh-my-pi/issues/8789)).
|
|
61
|
-
- Fixed the OpenAI-wire transport sleeping on a LiteLLM concurrency-admission 429 (`rate_limit_type: max_parallel_requests`, `Retry-After: 60`) and retrying it up to 6 times (~300s) before session recovery saw the error. Because a 60s hint equals the transport's `maxDelayMs` cap, `fetchWithRetry` kept sleeping and retrying; the request now surfaces on the first attempt so `TurnRecovery`'s concurrency backoff/model fallback runs promptly. Genuine RPM/quota 429s (no such marker) still honor `Retry-After` ([#8854](https://github.com/can1357/oh-my-pi/issues/8854)).
|
|
62
|
-
- Fixed OAuth login (Codex `localhost:1455`, and any `localhost` callback flow) failing on hosts with IPv6 disabled at the kernel (`ipv6.disable=1`). The `::1` companion listener added in #8081 fails there with Bun's generic "Is port X in use?" message (oven-sh/bun#7187), which the in-use check misread as a real collision — tearing down the healthy IPv4 listener and surfacing a bogus "port 1455 is in use" error. The dual-bind path now detects the missing IPv6 loopback up front and serves IPv4 alone ([#8814](https://github.com/can1357/oh-my-pi/issues/8814)).
|
package/README.md
CHANGED
|
@@ -10,38 +10,38 @@ Unified LLM API with automatic model discovery, provider configuration, token an
|
|
|
10
10
|
- [Installation](#installation)
|
|
11
11
|
- [Quick Start](#quick-start)
|
|
12
12
|
- [Tools](#tools)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
- [Defining Tools](#defining-tools)
|
|
14
|
+
- [Handling Tool Calls](#handling-tool-calls)
|
|
15
|
+
- [Streaming Tool Calls with Partial JSON](#streaming-tool-calls-with-partial-json)
|
|
16
|
+
- [Validating Tool Arguments](#validating-tool-arguments)
|
|
17
|
+
- [Complete Event Reference](#complete-event-reference)
|
|
18
18
|
- [Image Input](#image-input)
|
|
19
19
|
- [Thinking/Reasoning](#thinkingreasoning)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
- [Unified Interface](#unified-interface-streamsimplecompletesimple)
|
|
21
|
+
- [Provider-Specific Options](#provider-specific-options-streamcomplete)
|
|
22
|
+
- [Streaming Thinking Content](#streaming-thinking-content)
|
|
23
23
|
- [Stop Reasons](#stop-reasons)
|
|
24
24
|
- [Error Handling](#error-handling)
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
- [Aborting Requests](#aborting-requests)
|
|
26
|
+
- [Continuing After Abort](#continuing-after-abort)
|
|
27
27
|
- [APIs, Models, and Providers](#apis-models-and-providers)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
- [Providers and Models](#providers-and-models)
|
|
29
|
+
- [Querying Providers and Models](#querying-providers-and-models)
|
|
30
|
+
- [Custom Models](#custom-models)
|
|
31
|
+
- [OpenAI Compatibility Settings](#openai-compatibility-settings)
|
|
32
|
+
- [Type Safety](#type-safety)
|
|
33
33
|
- [Cross-Provider Handoffs](#cross-provider-handoffs)
|
|
34
34
|
- [Context Serialization](#context-serialization)
|
|
35
35
|
- [Browser Usage](#browser-usage)
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
- [Environment Variables](#environment-variables-nodejs-only)
|
|
37
|
+
- [Checking Environment Variables](#checking-environment-variables)
|
|
38
38
|
- [OAuth Providers](#oauth-providers)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
- [Vertex AI (ADC)](#vertex-ai-adc)
|
|
40
|
+
- [CLI Login](#cli-login)
|
|
41
|
+
- [Programmatic OAuth](#programmatic-oauth)
|
|
42
|
+
- [Login Flow Example](#login-flow-example)
|
|
43
|
+
- [Using OAuth Tokens](#using-oauth-tokens)
|
|
44
|
+
- [Provider Notes](#provider-notes)
|
|
45
45
|
- [License](#license)
|
|
46
46
|
|
|
47
47
|
## Supported Providers
|
|
@@ -172,7 +172,7 @@ const finalMessage = await s.result();
|
|
|
172
172
|
context.messages.push(finalMessage);
|
|
173
173
|
|
|
174
174
|
// Handle tool calls if any
|
|
175
|
-
const toolCalls = finalMessage.content.filter(
|
|
175
|
+
const toolCalls = finalMessage.content.filter(b => b.type === "toolCall");
|
|
176
176
|
for (const call of toolCalls) {
|
|
177
177
|
// Execute the tool
|
|
178
178
|
const result =
|
|
@@ -464,7 +464,7 @@ const response = await completeSimple(
|
|
|
464
464
|
},
|
|
465
465
|
{
|
|
466
466
|
reasoning: "medium", // 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' (xhigh maps to high on non-OpenAI providers)
|
|
467
|
-
}
|
|
467
|
+
},
|
|
468
468
|
);
|
|
469
469
|
|
|
470
470
|
// Access thinking and text blocks
|
|
@@ -583,7 +583,7 @@ const s = stream(
|
|
|
583
583
|
},
|
|
584
584
|
{
|
|
585
585
|
signal,
|
|
586
|
-
}
|
|
586
|
+
},
|
|
587
587
|
);
|
|
588
588
|
|
|
589
589
|
for await (const event of s) {
|
|
@@ -643,7 +643,7 @@ Example:
|
|
|
643
643
|
const response = await complete(model, context, {
|
|
644
644
|
apiKey: "sk-live",
|
|
645
645
|
headers: { "X-Debug-Trace": "true" },
|
|
646
|
-
onPayload:
|
|
646
|
+
onPayload: payload => {
|
|
647
647
|
console.log("request payload", payload);
|
|
648
648
|
},
|
|
649
649
|
});
|
|
@@ -918,7 +918,7 @@ const response = await complete(
|
|
|
918
918
|
},
|
|
919
919
|
{
|
|
920
920
|
apiKey: "your-api-key",
|
|
921
|
-
}
|
|
921
|
+
},
|
|
922
922
|
);
|
|
923
923
|
```
|
|
924
924
|
|
|
@@ -928,40 +928,40 @@ const response = await complete(
|
|
|
928
928
|
|
|
929
929
|
In Node.js environments, you can set environment variables to avoid passing API keys:
|
|
930
930
|
|
|
931
|
-
| Provider
|
|
932
|
-
|
|
|
933
|
-
| OpenAI
|
|
934
|
-
| Anthropic
|
|
935
|
-
| Google
|
|
936
|
-
| Vertex AI
|
|
937
|
-
| Mistral
|
|
938
|
-
| Groq
|
|
939
|
-
| Cerebras
|
|
940
|
-
| Together
|
|
941
|
-
| Qianfan
|
|
942
|
-
| Hugging Face
|
|
943
|
-
| Synthetic
|
|
944
|
-
| NVIDIA
|
|
945
|
-
| NanoGPT
|
|
946
|
-
| Novita
|
|
947
|
-
| DeepInfra
|
|
948
|
-
| Venice
|
|
949
|
-
| Moonshot
|
|
950
|
-
| xAI
|
|
951
|
-
| OpenRouter
|
|
952
|
-
| LiteLLM
|
|
953
|
-
| Ollama
|
|
954
|
-
| Ollama Cloud
|
|
955
|
-
| Qwen Portal
|
|
956
|
-
| QwenCloud Token Plan
|
|
957
|
-
| zAI
|
|
958
|
-
| Umans AI Coding Plan
|
|
959
|
-
| MiniMax Code
|
|
960
|
-
| Xiaomi MiMo
|
|
961
|
-
| ZenMux
|
|
962
|
-
| vLLM
|
|
963
|
-
| Cloudflare AI Gateway | `CLOUDFLARE_AI_GATEWAY_API_KEY` + `CLOUDFLARE_ACCOUNT_ID` + `CLOUDFLARE_GATEWAY_ID`
|
|
964
|
-
| GitHub Copilot
|
|
931
|
+
| Provider | Environment Variable(s) |
|
|
932
|
+
| --------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
933
|
+
| OpenAI | `OPENAI_API_KEY` |
|
|
934
|
+
| Anthropic | `ANTHROPIC_API_KEY` or `ANTHROPIC_OAUTH_TOKEN` (or `ANTHROPIC_FOUNDRY_API_KEY` when `CLAUDE_CODE_USE_FOUNDRY=true`) |
|
|
935
|
+
| Google | `GEMINI_API_KEY` |
|
|
936
|
+
| Vertex AI | `GOOGLE_CLOUD_PROJECT` (or `GCLOUD_PROJECT`) + `GOOGLE_CLOUD_LOCATION` + ADC |
|
|
937
|
+
| Mistral | `MISTRAL_API_KEY` |
|
|
938
|
+
| Groq | `GROQ_API_KEY` |
|
|
939
|
+
| Cerebras | `CEREBRAS_API_KEY` |
|
|
940
|
+
| Together | `TOGETHER_API_KEY` |
|
|
941
|
+
| Qianfan | `QIANFAN_API_KEY` |
|
|
942
|
+
| Hugging Face | `HUGGINGFACE_HUB_TOKEN` or `HF_TOKEN` |
|
|
943
|
+
| Synthetic | `SYNTHETIC_API_KEY` |
|
|
944
|
+
| NVIDIA | `NVIDIA_API_KEY` |
|
|
945
|
+
| NanoGPT | `NANO_GPT_API_KEY` |
|
|
946
|
+
| Novita | `NOVITA_API_KEY` |
|
|
947
|
+
| DeepInfra | `DEEPINFRA_API_KEY` |
|
|
948
|
+
| Venice | `VENICE_API_KEY` |
|
|
949
|
+
| Moonshot | `MOONSHOT_API_KEY` |
|
|
950
|
+
| xAI | `XAI_API_KEY` |
|
|
951
|
+
| OpenRouter | `OPENROUTER_API_KEY` |
|
|
952
|
+
| LiteLLM | `LITELLM_API_KEY` |
|
|
953
|
+
| Ollama | `OLLAMA_API_KEY` (optional for local deployments) |
|
|
954
|
+
| Ollama Cloud | `OLLAMA_CLOUD_API_KEY` |
|
|
955
|
+
| Qwen Portal | `QWEN_OAUTH_TOKEN` or `QWEN_PORTAL_API_KEY` |
|
|
956
|
+
| QwenCloud Token Plan | `ALIBABA_TOKEN_PLAN_API_KEY` or `BAILIAN_TOKEN_PLAN_API_KEY` |
|
|
957
|
+
| zAI | `ZAI_API_KEY` |
|
|
958
|
+
| Umans AI Coding Plan | `UMANS_AI_CODING_PLAN_API_KEY` |
|
|
959
|
+
| MiniMax Code | `MINIMAX_CODE_API_KEY` (international) or `MINIMAX_CODE_CN_API_KEY` (China) |
|
|
960
|
+
| Xiaomi MiMo | `XIAOMI_API_KEY` |
|
|
961
|
+
| ZenMux | `ZENMUX_API_KEY` |
|
|
962
|
+
| vLLM | `VLLM_API_KEY` |
|
|
963
|
+
| Cloudflare AI Gateway | `CLOUDFLARE_AI_GATEWAY_API_KEY` + `CLOUDFLARE_ACCOUNT_ID` + `CLOUDFLARE_GATEWAY_ID` |
|
|
964
|
+
| GitHub Copilot | `COPILOT_GITHUB_TOKEN` or `GH_TOKEN` or `GITHUB_TOKEN` |
|
|
965
965
|
|
|
966
966
|
`/login cloudflare-ai-gateway` collects and stores the gateway token, account ID, and gateway ID. For environment configuration, set all three Cloudflare values above. OMP derives provider endpoints from the account and gateway IDs.
|
|
967
967
|
|
|
@@ -997,7 +997,7 @@ Provider endpoint defaults for the current OpenAI-compatible integrations:
|
|
|
997
997
|
- LiteLLM: `http://localhost:4000/v1`
|
|
998
998
|
- Cloudflare AI Gateway: native Anthropic, OpenAI, and Workers AI routes under `https://gateway.ai.cloudflare.com/v1/<account>/<gateway>`
|
|
999
999
|
- Qwen Portal: `https://portal.qwen.ai/v1`
|
|
1000
|
-
When set, the library automatically uses these keys:
|
|
1000
|
+
When set, the library automatically uses these keys:
|
|
1001
1001
|
|
|
1002
1002
|
```typescript
|
|
1003
1003
|
// Uses OPENAI_API_KEY from environment
|
|
@@ -1143,10 +1143,10 @@ const credentials = await loginGitHubCopilot({
|
|
|
1143
1143
|
console.log(`Open: ${url}`);
|
|
1144
1144
|
if (instructions) console.log(instructions);
|
|
1145
1145
|
},
|
|
1146
|
-
onPrompt: async
|
|
1146
|
+
onPrompt: async prompt => {
|
|
1147
1147
|
return await getUserInput(prompt.message);
|
|
1148
1148
|
},
|
|
1149
|
-
onProgress:
|
|
1149
|
+
onProgress: message => console.log(message),
|
|
1150
1150
|
});
|
|
1151
1151
|
|
|
1152
1152
|
// Store credentials yourself
|
|
@@ -1180,7 +1180,7 @@ const response = await complete(
|
|
|
1180
1180
|
{
|
|
1181
1181
|
messages: [{ role: "user", content: "Hello!" }],
|
|
1182
1182
|
},
|
|
1183
|
-
{ apiKey: result.apiKey }
|
|
1183
|
+
{ apiKey: result.apiKey },
|
|
1184
1184
|
);
|
|
1185
1185
|
```
|
|
1186
1186
|
|
|
@@ -468,7 +468,7 @@ export type AuthStorageOptions = {
|
|
|
468
468
|
* so the TUI can show where a token came from (broker URL or local SQLite path).
|
|
469
469
|
*
|
|
470
470
|
* Examples:
|
|
471
|
-
* - `"local ~/.
|
|
471
|
+
* - `"local ~/.zeta/agent/agent.db"`
|
|
472
472
|
* - `"broker http://omp.internal:8765"`
|
|
473
473
|
*/
|
|
474
474
|
sourceLabel?: string;
|
|
@@ -47,5 +47,12 @@ export interface BedrockOptions extends StreamOptions {
|
|
|
47
47
|
* we omit it for them.
|
|
48
48
|
*/
|
|
49
49
|
thinkingDisplay?: BedrockThinkingDisplay;
|
|
50
|
+
/**
|
|
51
|
+
* Per-request Bedrock invocation-log tags. Merged over `model.requestMetadata`
|
|
52
|
+
* (per-call entries win on key collision). AWS caps the result at 16 entries;
|
|
53
|
+
* keys 1-256 chars, values 0-256 chars, both limited to
|
|
54
|
+
* `[a-zA-Z0-9\s:_@$#=/+,-.]`. Entries outside those limits are dropped.
|
|
55
|
+
*/
|
|
56
|
+
requestMetadata?: Record<string, string>;
|
|
50
57
|
}
|
|
51
58
|
export declare const streamBedrock: StreamFunction<"bedrock-converse-stream">;
|
|
@@ -164,7 +164,7 @@ export type AnthropicClientOptionsArgs = {
|
|
|
164
164
|
disableStrictTools?: boolean;
|
|
165
165
|
fetch?: FetchImpl;
|
|
166
166
|
maxRetryDelayMs?: number;
|
|
167
|
-
|
|
167
|
+
sessionId?: string;
|
|
168
168
|
};
|
|
169
169
|
export type AnthropicClientOptionsResult = {
|
|
170
170
|
isOAuthToken: boolean;
|
|
@@ -122,8 +122,8 @@ export declare function handleServerMessage(msg: AgentServerMessage, output: Ass
|
|
|
122
122
|
* and nullable for the one caller whose block is NOT pre-resolved: MCP without
|
|
123
123
|
* an `mcp` handler, which `agent-loop.ts` runs locally and pairs itself.
|
|
124
124
|
*/
|
|
125
|
-
export declare function resolveExecHandler<TArgs,
|
|
126
|
-
execResult:
|
|
125
|
+
export declare function resolveExecHandler<TArgs, R>(args: TArgs, handler: ((args: TArgs) => Promise<CursorExecHandlerResult<R>>) | undefined, onToolResult: CursorToolResultHandler | undefined, buildFromToolResult: (toolResult: ToolResultMessage) => R, buildRejected: (reason: string) => R, buildError: (error: string) => R, pairing: CursorExecPairing | null): Promise<{
|
|
126
|
+
execResult: R;
|
|
127
127
|
toolResult?: ToolResultMessage;
|
|
128
128
|
}>;
|
|
129
129
|
/**
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Shared inference request identity headers. */
|
|
2
|
+
/** Options controlling provider and protocol inference headers. */
|
|
3
|
+
export interface InferenceHeaderOptions {
|
|
4
|
+
provider: string;
|
|
5
|
+
protocol: "anthropic" | "google" | "openai";
|
|
6
|
+
sessionId?: string;
|
|
7
|
+
}
|
|
8
|
+
/** Set a header unless the map already contains that field under any casing. */
|
|
9
|
+
export declare function setHeaderIfAbsent(headers: Record<string, string>, name: string, value: string): void;
|
|
10
|
+
/**
|
|
11
|
+
* Project omp's identity and authoritative conversation id onto the headers
|
|
12
|
+
* understood by the active inference protocol and host.
|
|
13
|
+
*/
|
|
14
|
+
export declare function applyInferenceHeaders(headers: Record<string, string>, options: InferenceHeaderOptions): void;
|
|
15
|
+
/**
|
|
16
|
+
* Return `init` with omp's process-wide inference User-Agent default applied.
|
|
17
|
+
* Any explicit header, including Anthropic and Codex OAuth fingerprints,
|
|
18
|
+
* remains authoritative. Called per request by `transportFetch`.
|
|
19
|
+
*
|
|
20
|
+
* Plain-object headers stay plain objects: custom `fetch` implementations
|
|
21
|
+
* (proxies, tests) index `init.headers` by name and must not be handed a
|
|
22
|
+
* `Headers` instance instead.
|
|
23
|
+
*/
|
|
24
|
+
export declare function withInferenceUserAgent(input: string | URL | Request, init: RequestInit | undefined): RequestInit | undefined;
|
|
@@ -21,10 +21,8 @@ export interface CodexRequestOptions {
|
|
|
21
21
|
textVerbosity?: "low" | "medium" | "high";
|
|
22
22
|
include?: string[];
|
|
23
23
|
/**
|
|
24
|
-
* Responses Lite transport
|
|
25
|
-
*
|
|
26
|
-
* strips image detail, and disables parallel tool calling (codex-rs
|
|
27
|
-
* `use_responses_lite`).
|
|
24
|
+
* Responses Lite transport opt-in. Normal inference defaults to full
|
|
25
|
+
* Responses so the model can emit independent tool calls in parallel.
|
|
28
26
|
*/
|
|
29
27
|
responsesLite?: boolean;
|
|
30
28
|
}
|
|
@@ -70,13 +68,12 @@ export interface RequestBody {
|
|
|
70
68
|
[key: string]: unknown;
|
|
71
69
|
}
|
|
72
70
|
/**
|
|
73
|
-
* Resolve whether a Codex request
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* decides.
|
|
71
|
+
* Resolve whether a Codex request explicitly opts into Responses Lite.
|
|
72
|
+
*
|
|
73
|
+
* Provider-native compaction passes the model's `useResponsesLite` flag as an
|
|
74
|
+
* explicit option; normal inference defaults to the full Responses contract.
|
|
78
75
|
*/
|
|
79
|
-
export declare function resolveCodexResponsesLite(
|
|
76
|
+
export declare function resolveCodexResponsesLite(requested: boolean | undefined): boolean;
|
|
80
77
|
/**
|
|
81
78
|
* Structural view of a Responses-style body mutated by the Lite rewrite.
|
|
82
79
|
* Loose (`unknown`) property types let the turn transformer (`RequestBody`)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CodexCompactionContext, CodexCompactionRequestContext, Context, Model, ProviderSessionState, ServiceTier, StreamFunction, StreamOptions, Tool, ToolChoice } from "../types.js";
|
|
2
|
-
import { type CodexLiteShapedBody, type CodexReasoningContext, type RequestBody } from "./openai-codex/request-transformer.js";
|
|
2
|
+
import { type CodexLiteShapedBody, type CodexReasoningContext, type InputItem, type RequestBody } from "./openai-codex/request-transformer.js";
|
|
3
3
|
import type { ResponseInput } from "./openai-responses-wire.js";
|
|
4
4
|
export interface OpenAICodexResponsesOptions extends StreamOptions {
|
|
5
5
|
reasoning?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
|
|
@@ -12,13 +12,9 @@ export interface OpenAICodexResponsesOptions extends StreamOptions {
|
|
|
12
12
|
preferWebsockets?: boolean;
|
|
13
13
|
serviceTier?: ServiceTier;
|
|
14
14
|
/**
|
|
15
|
-
* Responses Lite transport
|
|
16
|
-
*
|
|
17
|
-
* `
|
|
18
|
-
* WebSocket upgrade (the marker is connection-scoped there, so lite and
|
|
19
|
-
* non-lite turns never share a pooled socket), moves instructions/tools
|
|
20
|
-
* into input items, strips image detail, and disables parallel tool
|
|
21
|
-
* calling — mirroring codex-rs.
|
|
15
|
+
* Responses Lite transport opt-in. Normal inference defaults to full
|
|
16
|
+
* Responses; provider-native compaction explicitly follows the model's
|
|
17
|
+
* `useResponsesLite` flag.
|
|
22
18
|
*/
|
|
23
19
|
responsesLite?: boolean;
|
|
24
20
|
/**
|
|
@@ -168,8 +164,8 @@ export declare function createOpenAICodexCompatibilityMetadata(options: OpenAICo
|
|
|
168
164
|
export declare function resetOpenAICodexHistoryAfterCompaction(options: OpenAICodexCompactionResetOptions): void;
|
|
169
165
|
/** @internal Exported for tests. */
|
|
170
166
|
export declare function normalizeCodexToolChoice(choice: ToolChoice | undefined, tools?: Tool[], model?: Model<"openai-codex-responses">): string | Record<string, unknown> | undefined;
|
|
171
|
-
/**
|
|
172
|
-
export declare function buildTransformedCodexRequestBody(model: Model<"openai-codex-responses">, context: Context, options: OpenAICodexResponsesOptions | undefined, promptCacheKey?: string | undefined): Promise<RequestBody>;
|
|
167
|
+
/** Serialize normal Codex turns and V2 compaction with the same cacheable prefix. */
|
|
168
|
+
export declare function buildTransformedCodexRequestBody(model: Model<"openai-codex-responses">, context: Context, options: OpenAICodexResponsesOptions | undefined, promptCacheKey?: string | undefined, inputPrefix?: InputItem[]): Promise<RequestBody>;
|
|
173
169
|
/**
|
|
174
170
|
* Open a provider-native V2 compaction stream through Codex's WebSocket-first
|
|
175
171
|
* transport, replaying WebSocket transport failures over SSE.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mid-conversation reasoning effort via `configuration_update` input items
|
|
3
|
+
* (GPT-6 Astra; `model.compat.supportsConfigurationUpdate`).
|
|
4
|
+
*
|
|
5
|
+
* The request-level `reasoning.effort` is pinned to the value of the session's
|
|
6
|
+
* first request so the cached prompt prefix survives an effort change. Each
|
|
7
|
+
* later change is carried as a `configuration_update` item inserted at the
|
|
8
|
+
* tail of the transcript — before the user message it takes effect on, or
|
|
9
|
+
* after the latest tool result when the level changes inside a tool loop — and
|
|
10
|
+
* replayed at that position on every subsequent request until another update
|
|
11
|
+
* overrides it. Mirrors the Anthropic provider's stable `output_config.effort`
|
|
12
|
+
* planning.
|
|
13
|
+
*
|
|
14
|
+
* Used by both the platform Responses provider and the Codex provider; the
|
|
15
|
+
* state lives in each provider's session state, keyed per conversation.
|
|
16
|
+
*
|
|
17
|
+
* Wire constraints (verified against the Codex backend): only `gpt-6-astra`
|
|
18
|
+
* accepts the item type, consecutive updates are rejected, and
|
|
19
|
+
* `/responses/compact` rejects histories containing them — compaction
|
|
20
|
+
* requests are built outside this planner and never carry the items.
|
|
21
|
+
*/
|
|
22
|
+
/** `configuration_update` input item; only `reasoning.effort` is updatable. */
|
|
23
|
+
export interface ConfigurationUpdateItem {
|
|
24
|
+
type: "configuration_update";
|
|
25
|
+
reasoning: {
|
|
26
|
+
effort: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
interface EffortTransition<TEffort extends string> {
|
|
30
|
+
/** Input-array position the item is spliced into (before `input[index]`). */
|
|
31
|
+
index: number;
|
|
32
|
+
/** Fingerprint of `input[index - 1]` at record time; a mismatch means the history was rewritten. */
|
|
33
|
+
anchor: string;
|
|
34
|
+
effort: TEffort;
|
|
35
|
+
}
|
|
36
|
+
/** Per-conversation effort baseline and recorded transitions. */
|
|
37
|
+
export interface OpenAIEffortControlState<TEffort extends string = string> {
|
|
38
|
+
baseEffort?: TEffort;
|
|
39
|
+
currentEffort?: TEffort;
|
|
40
|
+
transitions: EffortTransition<TEffort>[];
|
|
41
|
+
}
|
|
42
|
+
export declare function createOpenAIEffortControlState<TEffort extends string>(): OpenAIEffortControlState<TEffort>;
|
|
43
|
+
/**
|
|
44
|
+
* Fetch (or create) the control state for one conversation from a provider's
|
|
45
|
+
* bounded per-session map, refreshing its LRU slot.
|
|
46
|
+
*/
|
|
47
|
+
export declare function getOpenAIEffortControlState<TEffort extends string>(states: Map<string, OpenAIEffortControlState<TEffort>>, key: string): OpenAIEffortControlState<TEffort>;
|
|
48
|
+
interface AnchorableItem {
|
|
49
|
+
type?: string | null;
|
|
50
|
+
role?: string;
|
|
51
|
+
id?: string | null;
|
|
52
|
+
status?: string | null;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Pin the request-level effort to the session baseline and splice pending
|
|
56
|
+
* `configuration_update` items into `input` (mutated in place).
|
|
57
|
+
*
|
|
58
|
+
* `input` is the freshly built transcript for this request, without any
|
|
59
|
+
* `configuration_update` items. `requested` is the wire effort the caller
|
|
60
|
+
* would otherwise send at the request level. Returns the effort to send at the
|
|
61
|
+
* request level (`requested` on the first request, the baseline afterwards).
|
|
62
|
+
*/
|
|
63
|
+
export declare function planStableOpenAIEffort<TItem extends AnchorableItem, TEffort extends string>(state: OpenAIEffortControlState<TEffort>, input: Array<TItem | ConfigurationUpdateItem>, requested: TEffort): TEffort;
|
|
64
|
+
export {};
|
|
@@ -2918,7 +2918,7 @@ export interface ResponseInputImageContent {
|
|
|
2918
2918
|
* `assistant` role are presumed to have been generated by the model in previous
|
|
2919
2919
|
* interactions.
|
|
2920
2920
|
*/
|
|
2921
|
-
export type ResponseInputItem = EasyInputMessage | ResponseInputItem.Message | ResponseOutputMessage | ResponseFileSearchToolCall | ResponseComputerToolCall | ResponseInputItem.ComputerCallOutput | ResponseFunctionWebSearch | ResponseFunctionToolCall | ResponseInputItem.FunctionCallOutput | ResponseInputItem.ToolSearchCall | ResponseToolSearchOutputItemParam | ResponseInputItem.AdditionalTools | ResponseReasoningItem | ResponseCompactionItemParam | ResponseInputItem.ImageGenerationCall | ResponseCodeInterpreterToolCall | ResponseInputItem.LocalShellCall | ResponseInputItem.LocalShellCallOutput | ResponseInputItem.ShellCall | ResponseInputItem.ShellCallOutput | ResponseInputItem.ApplyPatchCall | ResponseInputItem.ApplyPatchCallOutput | ResponseInputItem.McpListTools | ResponseInputItem.McpApprovalRequest | ResponseInputItem.McpApprovalResponse | ResponseInputItem.McpCall | ResponseCustomToolCallOutput | ResponseCustomToolCall | ResponseInputItem.CompactionTrigger | ResponseInputItem.ItemReference;
|
|
2921
|
+
export type ResponseInputItem = EasyInputMessage | ResponseInputItem.Message | ResponseOutputMessage | ResponseFileSearchToolCall | ResponseComputerToolCall | ResponseInputItem.ComputerCallOutput | ResponseFunctionWebSearch | ResponseFunctionToolCall | ResponseInputItem.FunctionCallOutput | ResponseInputItem.ToolSearchCall | ResponseToolSearchOutputItemParam | ResponseInputItem.AdditionalTools | ResponseReasoningItem | ResponseCompactionItemParam | ResponseInputItem.ImageGenerationCall | ResponseCodeInterpreterToolCall | ResponseInputItem.LocalShellCall | ResponseInputItem.LocalShellCallOutput | ResponseInputItem.ShellCall | ResponseInputItem.ShellCallOutput | ResponseInputItem.ApplyPatchCall | ResponseInputItem.ApplyPatchCallOutput | ResponseInputItem.McpListTools | ResponseInputItem.McpApprovalRequest | ResponseInputItem.McpApprovalResponse | ResponseInputItem.McpCall | ResponseCustomToolCallOutput | ResponseCustomToolCall | ResponseInputItem.CompactionTrigger | ResponseInputItem.ConfigurationUpdate | ResponseInputItem.ItemReference;
|
|
2922
2922
|
export declare namespace ResponseInputItem {
|
|
2923
2923
|
/**
|
|
2924
2924
|
* A message input to the model with a role indicating instruction following
|
|
@@ -3504,6 +3504,20 @@ export declare namespace ResponseInputItem {
|
|
|
3504
3504
|
*/
|
|
3505
3505
|
type: "compaction_trigger";
|
|
3506
3506
|
}
|
|
3507
|
+
/**
|
|
3508
|
+
* Changes reasoning effort for subsequent responses without touching the
|
|
3509
|
+
* request-level `reasoning.effort` (GPT-6 Astra). Must not be adjacent to
|
|
3510
|
+
* another `configuration_update`.
|
|
3511
|
+
*/
|
|
3512
|
+
interface ConfigurationUpdate {
|
|
3513
|
+
/**
|
|
3514
|
+
* The type of the item. Always `configuration_update`.
|
|
3515
|
+
*/
|
|
3516
|
+
type: "configuration_update";
|
|
3517
|
+
reasoning: {
|
|
3518
|
+
effort: string;
|
|
3519
|
+
};
|
|
3520
|
+
}
|
|
3507
3521
|
/**
|
|
3508
3522
|
* An internal identifier for an item to reference.
|
|
3509
3523
|
*/
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Context, Model, OpenAICompat, ProviderSessionState, ServiceTier, StreamFunction, StreamOptions, Tool, ToolChoice } from "../types.js";
|
|
2
2
|
import { type OpenAIResponsesToolChoice } from "../utils/tool-choice.js";
|
|
3
|
+
import { type OpenAIEffortControlState } from "./openai-configuration-update.js";
|
|
3
4
|
import { type OpenAIReasoningEffortFallbackState } from "./openai-reasoning-fallback.js";
|
|
4
|
-
import type { Tool as OpenAITool, ResponseCreateParamsStreaming, ResponseInput } from "./openai-responses-wire.js";
|
|
5
|
+
import type { Tool as OpenAITool, ReasoningEffort, ResponseCreateParamsStreaming, ResponseInput } from "./openai-responses-wire.js";
|
|
5
6
|
import { type OpenAIPromptCacheOptions, type OpenAIStrictToolsScope, type OpenAIStrictToolsState } from "./openai-shared.js";
|
|
6
7
|
export interface OpenAIResponsesOptions extends StreamOptions {
|
|
7
8
|
reasoning?: "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
|
|
@@ -63,7 +64,11 @@ interface OpenAIResponsesProviderSessionState extends ProviderSessionState, Open
|
|
|
63
64
|
nativeHistoryReplayWarmed: boolean;
|
|
64
65
|
/** Stateful `previous_response_id` chain baselines, keyed by baseUrl/model/session. */
|
|
65
66
|
chains: Map<string, OpenAIResponsesChainState>;
|
|
67
|
+
/** `configuration_update` effort baselines, keyed by baseUrl/model/session. */
|
|
68
|
+
effortControls: Map<string, OpenAIEffortControlState<ResponsesStableEffort>>;
|
|
66
69
|
}
|
|
70
|
+
/** Wire efforts a `configuration_update` can carry: every real tier, never `none`/null. */
|
|
71
|
+
type ResponsesStableEffort = Exclude<ReasoningEffort, "none" | null>;
|
|
67
72
|
interface OpenAIResponsesChainState {
|
|
68
73
|
/**
|
|
69
74
|
* Wire params of the last successful turn; never carries
|
|
@@ -56,7 +56,7 @@ export interface OpenAIRequestSetupOptions {
|
|
|
56
56
|
apiVersion: string;
|
|
57
57
|
deploymentName: string;
|
|
58
58
|
};
|
|
59
|
-
|
|
59
|
+
sessionId?: string;
|
|
60
60
|
promptCacheSessionId?: string;
|
|
61
61
|
}
|
|
62
62
|
export interface OpenAIRequestSetup {
|
|
@@ -493,6 +493,18 @@ export interface BuildResponsesInputOptions<TApi extends Api> {
|
|
|
493
493
|
*/
|
|
494
494
|
export declare function escapeReplayedControlTokens(items: ResponseInput): ResponseInput;
|
|
495
495
|
export declare function buildResponsesInput<TApi extends Api>(options: BuildResponsesInputOptions<TApi>): ResponseInput;
|
|
496
|
+
/**
|
|
497
|
+
* Non-empty `reasoning_text` shipped for a synthesized reasoning item when no
|
|
498
|
+
* thinking text survived history reconstruction. DeepSeek-family Responses
|
|
499
|
+
* targets (e.g. opencode-go) reject BOTH a missing reasoning item and one whose
|
|
500
|
+
* `reasoning_text` is empty — "The reasoning_text in the thinking mode must be
|
|
501
|
+
* passed back to the API" (#8248 covered the missing case, #10690 the empty
|
|
502
|
+
* one). The item's presence plus a non-empty payload is what satisfies the
|
|
503
|
+
* contract; the exact text is immaterial once the source turn's reasoning is
|
|
504
|
+
* gone. Kept out of `reasoning_content="."`-territory since DeepSeek rejects the
|
|
505
|
+
* bare-dot synthetic placeholder on the chat-completions path.
|
|
506
|
+
*/
|
|
507
|
+
export declare const SYNTHETIC_REASONING_REPLAY_PLACEHOLDER = "reasoning unavailable";
|
|
496
508
|
export declare function convertResponsesAssistantMessage<TApi extends Api>(assistantMsg: AssistantMessage, model: Model<TApi>, msgIndex: number, knownCallIds: Set<string>, includeThinkingSignatures?: boolean, customCallIds?: Set<string>, preserveMessageIds?: boolean, supportsCustomToolCalls?: boolean, customToolWireNameMap?: ReadonlyMap<string, string>, computerCallIds?: Set<string>, requiresReasoningReplayForAllTurns?: boolean, requiresReasoningReplayForToolCalls?: boolean): ResponseInput;
|
|
497
509
|
/**
|
|
498
510
|
* Responses wire output for a tool result plus its text-only fallback.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `login "oauth-code"` engine: authorization-code grant (optionally PKCE)
|
|
3
|
-
* through the
|
|
3
|
+
* through the configured callback transport, followed by the declared token
|
|
4
4
|
* exchange, credential projection, userinfo enrichment and after-exchange hook.
|
|
5
5
|
*/
|
|
6
6
|
import type { CompiledAuthProvider, CompiledCallback, CompiledOAuthCodeLogin } from "@linxiraos/pi-catalog/compat/types";
|
|
@@ -25,6 +25,8 @@ export interface OAuthCallbackFlowOptions {
|
|
|
25
25
|
allowPortFallback?: boolean;
|
|
26
26
|
/** Skip the local callback server entirely; the user pastes the code or redirect URL back. */
|
|
27
27
|
manualInputOnly?: boolean;
|
|
28
|
+
/** Receive a custom-scheme redirect through the native OS handler when supported. */
|
|
29
|
+
nativeScheme?: boolean;
|
|
28
30
|
}
|
|
29
31
|
/**
|
|
30
32
|
* Abstract base class for OAuth flows with local callback servers.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Native callback lifetime exposed to the provider-independent OAuth flow. */
|
|
2
|
+
export interface NativeSchemeCallbackReceiver {
|
|
3
|
+
/** Restore owned settings; native recovery data remains intact on failure. */
|
|
4
|
+
dispose(): Promise<void>;
|
|
5
|
+
/** Wait for a complete URL while forwarding cancellation to native execution. */
|
|
6
|
+
waitForCallback(signal?: AbortSignal, timeoutMs?: number): Promise<string>;
|
|
7
|
+
}
|
|
8
|
+
/** Cancellation for native callback registration and its active lifetime. */
|
|
9
|
+
export interface NativeSchemeCallbackOptions {
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
}
|
|
12
|
+
/** Connect OAuth's AbortSignals to the native, recoverable desktop callback receiver. */
|
|
13
|
+
export declare function createNativeSchemeCallbackReceiver(scheme: string, options?: NativeSchemeCallbackOptions): Promise<NativeSchemeCallbackReceiver | undefined>;
|
|
@@ -66,7 +66,8 @@ export interface OAuthProviderInfo {
|
|
|
66
66
|
export interface OAuthController {
|
|
67
67
|
onAuth?(info: OAuthAuthInfo): void;
|
|
68
68
|
onProgress?(message: string): void;
|
|
69
|
-
|
|
69
|
+
/** Request pasted callback input; stop any visible prompt when `signal` aborts. */
|
|
70
|
+
onManualCodeInput?(signal?: AbortSignal): Promise<string>;
|
|
70
71
|
onPrompt?(prompt: OAuthPrompt): Promise<string>;
|
|
71
72
|
signal?: AbortSignal;
|
|
72
73
|
fetch?: FetchImpl;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -463,6 +463,13 @@ export interface SimpleStreamOptions extends Omit<StreamOptions, "apiKey"> {
|
|
|
463
463
|
guardrailIdentifier?: string;
|
|
464
464
|
guardrailVersion?: string;
|
|
465
465
|
guardrailTrace?: "enabled" | "disabled" | "enabled_full";
|
|
466
|
+
/**
|
|
467
|
+
* Bedrock invocation-log tags forwarded through transports that do not dispatch
|
|
468
|
+
* directly to the Bedrock provider. Unlike the guardrail fields above, these
|
|
469
|
+
* MERGE per key with the model's own `requestMetadata` (these win) rather than
|
|
470
|
+
* replacing it wholesale — they are independent attribution tags, not one value.
|
|
471
|
+
*/
|
|
472
|
+
requestMetadata?: Record<string, string>;
|
|
466
473
|
/** Optional tool choice override for compatible providers */
|
|
467
474
|
toolChoice?: ToolChoice;
|
|
468
475
|
/** OpenAI service tier for processing priority/cost control. Ignored by non-OpenAI providers. */
|