@code-yeongyu/senpi-ai 2026.10.10 → 2026.10.11
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/dist/api/anthropic-messages.js +101 -38
- package/dist/api/anthropic-tool-references.js +24 -18
- package/dist/api/bedrock-converse-stream.js +5 -1
- package/dist/api/google-shared.js +101 -21
- package/dist/api/lazy.js +13 -0
- package/dist/api/mistral-conversations.js +18 -3
- package/dist/api/openai-codex-responses.js +2 -2
- package/dist/api/openai-completions.js +26 -2
- package/dist/api/openai-responses-allowed-tools.d.ts +33 -0
- package/dist/api/openai-responses-allowed-tools.js +108 -0
- package/dist/api/openai-responses.js +43 -58
- package/dist/auth/oauth/anthropic.js +4 -3
- package/dist/auth/oauth/chatgpt-subscription.js +3 -2
- package/dist/auth/oauth/cursor.js +3 -2
- package/dist/auth/oauth/devin-token.js +2 -1
- package/dist/auth/oauth/github-copilot.js +3 -2
- package/dist/auth/oauth/kimi-coding.js +5 -4
- package/dist/auth/oauth/openai-chatgpt.js +2 -1
- package/dist/auth/oauth/openrouter.js +2 -1
- package/dist/auth/oauth/radius.js +5 -5
- package/dist/auth/oauth/xai.js +7 -4
- package/dist/auth/oauth-refresh.js +10 -0
- package/dist/auth/resolve.js +5 -0
- package/dist/openai-responses-compat.d.ts +7 -2
- package/dist/openai-responses-compat.js +15 -2
- package/dist/providers/all.d.ts +1 -1
- package/dist/providers/data/.manifest.json +1 -1
- package/dist/providers/data/amazon-bedrock.json +1 -1
- package/dist/providers/data/anthropic.json +1 -1
- package/dist/providers/data/baseten.json +1 -1
- package/dist/providers/data/chatgpt-subscription.json +1 -1
- package/dist/providers/data/cloudflare-ai-gateway.json +1 -1
- package/dist/providers/data/cloudflare-workers-ai.json +1 -1
- package/dist/providers/data/github-copilot.json +1 -1
- package/dist/providers/data/google-vertex.json +1 -1
- package/dist/providers/data/huggingface.json +1 -1
- package/dist/providers/data/mistral.json +1 -1
- package/dist/providers/data/moonshotai-cn.json +1 -1
- package/dist/providers/data/moonshotai.json +1 -1
- package/dist/providers/data/opencode-go.json +1 -1
- package/dist/providers/data/opencode.json +1 -1
- package/dist/providers/data/opengateway.json +1 -1
- package/dist/providers/data/openrouter.json +1 -1
- package/dist/providers/data/radius.json +1 -1
- package/dist/providers/data/venice.json +1 -1
- package/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/dist/providers/kimi-coding.models.d.ts +1 -1
- package/dist/providers/kimi-coding.models.js +1 -1
- package/dist/providers/opengateway-refresh.js +2 -1
- package/dist/types.d.ts +3 -2
- package/dist/utils/oauth-refresh-error.d.ts +16 -0
- package/dist/utils/oauth-refresh-error.js +67 -0
- package/dist/utils/prompt-cache-ttl.js +3 -1
- package/dist/utils/retry.d.ts +6 -0
- package/dist/utils/retry.js +10 -0
- package/dist/utils/tool-choice-fallback.d.ts +11 -0
- package/dist/utils/tool-choice-fallback.js +69 -2
- package/package.json +2 -2
package/dist/auth/oauth/xai.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* xAI OAuth device-code flow.
|
|
3
3
|
*/
|
|
4
|
+
import { OAuthTokenEndpointError } from "../../utils/oauth-refresh-error.js";
|
|
4
5
|
import { pollOAuthDeviceCodeFlow } from "./device-code.js";
|
|
5
6
|
const XAI_CLIENT_ID = "b1a00492-073a-47ea-816f-4c329264a828";
|
|
6
7
|
const XAI_SCOPE = "openid profile email offline_access grok-cli:access api:access";
|
|
@@ -53,7 +54,7 @@ async function postForm(url, fields, signal) {
|
|
|
53
54
|
}
|
|
54
55
|
catch (error) {
|
|
55
56
|
if (signal.aborted) {
|
|
56
|
-
throw new Error("Login cancelled");
|
|
57
|
+
throw new Error("Login cancelled", { cause: signal.reason });
|
|
57
58
|
}
|
|
58
59
|
throw error;
|
|
59
60
|
}
|
|
@@ -64,9 +65,11 @@ async function postForm(url, fields, signal) {
|
|
|
64
65
|
}
|
|
65
66
|
catch {
|
|
66
67
|
if (signal.aborted) {
|
|
67
|
-
throw new Error("Login cancelled");
|
|
68
|
+
throw new Error("Login cancelled", { cause: signal.reason });
|
|
68
69
|
}
|
|
69
|
-
|
|
70
|
+
const message = `xAI OAuth returned invalid JSON (HTTP ${response.status})`;
|
|
71
|
+
// An error page (an HTML 503 from a proxy, say) still carries the status the retry decision needs.
|
|
72
|
+
throw response.ok ? new Error(message) : new OAuthTokenEndpointError(message, response.status);
|
|
70
73
|
}
|
|
71
74
|
return {
|
|
72
75
|
ok: response.ok,
|
|
@@ -78,7 +81,7 @@ function requestFailure(action, response) {
|
|
|
78
81
|
const error = typeof response.body.error === "string" ? response.body.error : undefined;
|
|
79
82
|
const description = typeof response.body.error_description === "string" ? response.body.error_description : undefined;
|
|
80
83
|
const detail = [error, description].filter(Boolean).join(": ");
|
|
81
|
-
return new
|
|
84
|
+
return new OAuthTokenEndpointError(`xAI OAuth ${action} failed (HTTP ${response.status})${detail ? `: ${detail}` : ""}`, response.status);
|
|
82
85
|
}
|
|
83
86
|
function parseDeviceCode(body) {
|
|
84
87
|
// RFC 8628 allows interval 0 (no minimum wait); fall back to the poller's
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* superseded catalog refresh stops waiting but never aborts the exchange.
|
|
16
16
|
*/
|
|
17
17
|
import { raceWithAbortSignal } from "../utils/abort.js";
|
|
18
|
+
import { oauthRefreshFailureCause } from "../utils/oauth-refresh-error.js";
|
|
18
19
|
import { mergeRefreshed, mergeRefreshedSlot, projectSlot } from "./pool/slots.js";
|
|
19
20
|
export const DEFAULT_OAUTH_REFRESH_TIMEOUT_MS = 15_000;
|
|
20
21
|
/** The provider rejected or timed out the token exchange. */
|
|
@@ -103,6 +104,15 @@ async function exchangeAndStore(request, signal) {
|
|
|
103
104
|
signal.throwIfAborted();
|
|
104
105
|
}
|
|
105
106
|
catch (error) {
|
|
107
|
+
signal.throwIfAborted();
|
|
108
|
+
const causeClass = oauthRefreshFailureCause(error);
|
|
109
|
+
if (causeClass !== undefined) {
|
|
110
|
+
console.warn("OAuth refresh unavailable", JSON.stringify({
|
|
111
|
+
provider: providerId,
|
|
112
|
+
...(slotName ? { slot: slotName } : {}),
|
|
113
|
+
cause: causeClass,
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
106
116
|
throw new OAuthRefreshExchangeError(error);
|
|
107
117
|
}
|
|
108
118
|
try {
|
package/dist/auth/resolve.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { operationSignal, raceWithAbortSignal } from "../utils/abort.js";
|
|
2
2
|
import { ModelsError } from "../utils/models-error.js";
|
|
3
|
+
import { classifyOAuthRefreshFailure, OAuthRefreshUnavailableError } from "../utils/oauth-refresh-error.js";
|
|
3
4
|
import { OAuthRefreshExchangeError, OAuthRefreshStoreError, projectOAuthSlot, refreshOAuthCredential, } from "./oauth-refresh.js";
|
|
4
5
|
import { projectSlot } from "./pool/slots.js";
|
|
5
6
|
export { ModelsError } from "../utils/models-error.js";
|
|
@@ -82,6 +83,9 @@ export function oauthRefreshModelsError(error, providerId) {
|
|
|
82
83
|
if (error instanceof ModelsError)
|
|
83
84
|
return error;
|
|
84
85
|
if (error instanceof OAuthRefreshExchangeError) {
|
|
86
|
+
if (classifyOAuthRefreshFailure(error.cause) === "transient") {
|
|
87
|
+
return new OAuthRefreshUnavailableError(providerId, error.cause);
|
|
88
|
+
}
|
|
85
89
|
return new ModelsError("oauth", `OAuth refresh failed for ${providerId}`, { cause: error.cause });
|
|
86
90
|
}
|
|
87
91
|
const cause = error instanceof OAuthRefreshStoreError ? error.cause : error;
|
|
@@ -112,6 +116,7 @@ async function resolveStoredOAuth(credentials, providerId, oauth, stored, authCo
|
|
|
112
116
|
});
|
|
113
117
|
}
|
|
114
118
|
catch (error) {
|
|
119
|
+
signal.throwIfAborted();
|
|
115
120
|
throw oauthRefreshModelsError(error, providerId);
|
|
116
121
|
}
|
|
117
122
|
if (post?.type !== "oauth")
|
|
@@ -42,10 +42,15 @@ export interface OpenAIResponsesCompat {
|
|
|
42
42
|
* Whether the model accepts `tool_choice: { type: "allowed_tools" }`. When set, callers keep every
|
|
43
43
|
* declared tool in `tools` and restrict the callable subset through `Context.activeToolNames`, so a
|
|
44
44
|
* shrinking tool set does not rewrite the cached prompt prefix. Honored by the `openai-responses`
|
|
45
|
-
* adapter.
|
|
45
|
+
* adapter, and only on the native OpenAI API hosts (`api.openai.com` and its regional `*.api.openai.com`
|
|
46
|
+
* hosts): Responses-compatible gateways reject the choice (senpi#3080), and since a provider `baseUrl`
|
|
47
|
+
* override keeps the catalog compat, the flag cannot opt a gateway in. Default: false.
|
|
46
48
|
*/
|
|
47
49
|
supportsAllowedTools?: boolean;
|
|
48
50
|
}
|
|
49
|
-
/**
|
|
51
|
+
/**
|
|
52
|
+
* Whether requests to `model` restrict tools through `allowed_tools`: its compat declares support and it is
|
|
53
|
+
* served by the native OpenAI endpoint (see {@link OpenAIResponsesCompat.supportsAllowedTools}).
|
|
54
|
+
*/
|
|
50
55
|
export declare function supportsAllowedToolChoice(model: Model<Api>): boolean;
|
|
51
56
|
//# sourceMappingURL=openai-responses-compat.d.ts.map
|
|
@@ -1,5 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
function isNativeOpenAIEndpoint(baseUrl) {
|
|
2
|
+
try {
|
|
3
|
+
const { hostname } = new URL(baseUrl || "https://api.openai.com/v1");
|
|
4
|
+
return hostname === "api.openai.com" || hostname.endsWith(".api.openai.com");
|
|
5
|
+
}
|
|
6
|
+
catch {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Whether requests to `model` restrict tools through `allowed_tools`: its compat declares support and it is
|
|
12
|
+
* served by the native OpenAI endpoint (see {@link OpenAIResponsesCompat.supportsAllowedTools}).
|
|
13
|
+
*/
|
|
2
14
|
export function supportsAllowedToolChoice(model) {
|
|
3
|
-
return model.compat?.supportsAllowedTools === true
|
|
15
|
+
return (model.compat?.supportsAllowedTools === true &&
|
|
16
|
+
isNativeOpenAIEndpoint(model.baseUrl));
|
|
4
17
|
}
|
|
5
18
|
//# sourceMappingURL=openai-responses-compat.js.map
|
package/dist/providers/all.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"schemaVersion":6,"generatedAt":"2026-10-
|
|
1
|
+
{"schemaVersion":6,"generatedAt":"2026-10-11T10:01:11.497Z","structureHash":"0989a1c88b40439cecf9d8a82fe466628aa29d2c7cc597ed79540d082d7890d6","files":{"alibaba-token-plan.json":"16b3c6c78d72c73ca34a1e79ce71c0cf36ba409d02e83a17396ce0949a1d5363","amazon-bedrock.json":"4a95e6bf974e5ca967d5c050df580262e13573e42b3186edb448fa11a302f09f","ant-ling.json":"628feab3ef6c7d80ce96f75999804e1d9f05fec3851e5302e30fff3b69db90f6","anthropic.json":"111384e9f5845e0247bd34edf2400ef7720fcbdac140b944cf8878192d8bd6ab","azure-openai-responses.json":"a3e52bd78f0220aa32bce519e13955b8e6e567860416343844cbe19902f4a682","bai.json":"7e6861aaf27d8af34e1771c6092602194fcec0a0046e6adfab9c3ee54d32b99f","baseten.json":"1fcdab8daf2881bd099eb08f9416f7df5bf39975937d2a63b841542bd032f2e6","cerebras.json":"3eccb58c5de3d0dc7ba49dc6e477ba29f00cb3150ce0a35cc90d59e6b5ab368e","chatgpt-subscription.json":"2fbeb0141b29c340542798bce53422b93bef026a13420986e87fca89353e0aa2","cloudflare-ai-gateway.json":"5c8782fdbf2477f620b238da4344b0bcc0948b8c177461e63e7e5ba256f769c7","cloudflare-workers-ai.json":"f351e80493dea7b7a2c31dceb086ee804a88d67c5f8a3c823ea907991fe5d659","deepseek.json":"10a296fb3e898f7715c80890c8af0af4f5fd58f22dbcd6612fdc5d762157ccdc","fireworks.json":"c3dc21dc2e95428fc9a38e3840c05bbf90f94e4c25dee0eedf0b385b49ff65a4","github-copilot.json":"2c5a84983477a7c4f6c001088a1e043ee959ce58c99fea6eb843e0286228664b","google-vertex.json":"96ecc19bf20a706f99ae658b021a0ee5438146119e1e99de5fd824a01fcfd81b","google.json":"c0f5a633e5e5a5044432db3e537f4bc674d4de18df09325c6349547fcc13cabe","groq.json":"910952ad9dad07856983459d63fce0148dba1203edd7b10d801a77c5824f3405","huggingface.json":"6399e958790a9d90c21fb55d1cbef8569427a1ceb28de86dadeb3b4454ecfade","meta.json":"0c7e9a370a7005c5a89dc94f0f93bc67b8935c3f802de324f11af6ff56fff429","minimax-cn.json":"f962c20ee6a6a342820f778e9dc363a18a524bf11998f6e2c57f2989915d62e5","minimax.json":"17a432f80d0ea6dd26eade80a4314250d3a855678601728a5f70dd8fa0d21dd2","mistral.json":"27aa66c71a0504b53dc87ec194286fa7e70b99747fc8df9b709b23b3548afe50","moonshotai-cn.json":"18954b55dc5edecc174d8a07a2c5993416dd9d3ce52e411438035c16ee982e8e","moonshotai.json":"62d08fd5beead025a56d5f2e4227d8516b9c5034275b1b36d761a8625918f2b9","nvidia.json":"a75e963dc81779e3eec01c051b12277c15ec37c5b94ab51ece9e9ccb3b16407c","openai.json":"9104538118053eed57f90852332b6ad274a4e4792389bdbc9cfca1ae400c705a","opencode-go.json":"48ff011f3e171f977cfed2928272667e9361f13a508e5994f00f2241f6a23419","opencode.json":"882b039f64ef266da7b02d30aee9255c191e16f0600ef5494022bc1ef746f749","opengateway.json":"dd4259885ea6045d723b3abaae06657dfcce07b9ce3c2b0300220ac661432859","openrouter.json":"9484c1583eb1d419e89ffe258cd4efb7bb793666ae09c94db545f400fe0d628e","qwen-token-plan-cn.json":"bd36a6d9cc2048deafacc85f7f0f2e51868c8b7aa09502e3e4e60e3e8b76f690","qwen-token-plan-individual.json":"35ffb0ba1a1ce3f68fc73262dd5e07fbcb5bf5911ad1e6e17bc0621e2894676a","qwen-token-plan.json":"ca27e49e62965221badead8e867b2007035c6b6a15a97c47219bd23d2c83c2b1","radius.json":"8214122385e8e4c4bc2e1d2a7d032f9e4c654da3bfd3ac8c5d4396e1b522e53a","together.json":"bbd7fad86cacfefe3d3d61f6638f22e9b6f5d575722fd1112a16aafe0485c46d","typesafe.json":"a4429a2f696d5cc5273969af61a7310bda07d6bdcd27bf9ac9c76c534cc43716","venice.json":"3604c88c46dd3e4151b833927c6f87bcc165d0999a4339b32db2ad74a9ff173f","vercel-ai-gateway.json":"9859481f690a9a9a8131af3abfadf5378b2d1ef51990041da4465de3f1e4ab78","xai.json":"d7771a1450b21c1f6aee887ca6fea61b6e7b3fc13b4dee5cf72a71134fe623bc","xiaomi-token-plan-ams.json":"4dd8f838e21d7aa7caf3122d0b0b1e5a02a33bc012b96e6a75bd119334152d7a","xiaomi-token-plan-cn.json":"46414ff49973b95a0c14bd33e8992cc1938a50ce2c7cea9e2e5cc02de8f1df31","xiaomi-token-plan-sgp.json":"f5b3f66bf7bb7238592d4a9667cad983a008d7539a66e9896b02422622800935","xiaomi.json":"8b62c158d55d5a165f35cd72c1fc82ab89ff8e73f08960105fc41b822f236f69","zai-coding-cn.json":"2a7f59d15f588a97d218997883f2506dfc52d3ee320697d39f14213a050fc912","zai.json":"e9cc408e1756de8abc70148d63d89d11a63c65b7ef06ad0661cd1328e4209ba3"}}
|