@gajae-code/ai 0.15.6 → 0.16.1
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 +43 -0
- package/dist/types/adapter-internals/aws-region.d.ts +7 -0
- package/dist/types/core.d.ts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/provider-models/openai-compat.d.ts +1 -0
- package/dist/types/providers/anthropic.d.ts +1 -1
- package/dist/types/providers/cursor.d.ts +27 -1
- package/dist/types/providers/google-gemini-headers.d.ts +1 -1
- package/dist/types/providers/openai-codex-responses.d.ts +6 -0
- package/dist/types/utils/discovery/openai-compatible.d.ts +21 -0
- package/dist/types/utils/h2-fetch.d.ts +7 -0
- package/dist/types/utils/schema/normalize.d.ts +0 -5
- package/dist/types/utils/sqlite-errors.d.ts +4 -0
- package/package.json +3 -3
- package/src/adapter-internals/aws-region.d.ts +7 -0
- package/src/adapter-internals/aws-region.ts +14 -0
- package/src/auth-broker/server.ts +10 -1
- package/src/auth-storage.ts +14 -14
- package/src/core.ts +1 -0
- package/src/index.ts +1 -0
- package/src/model-thinking.ts +8 -0
- package/src/models.json +201 -3
- package/src/provider-models/openai-compat.ts +93 -8
- package/src/providers/amazon-bedrock.ts +5 -1
- package/src/providers/anthropic.d.ts +1 -1
- package/src/providers/anthropic.ts +1 -1
- package/src/providers/aws-credentials.ts +6 -0
- package/src/providers/cursor.d.ts +27 -1
- package/src/providers/cursor.ts +234 -17
- package/src/providers/google-gemini-headers.d.ts +1 -1
- package/src/providers/google-gemini-headers.ts +1 -1
- package/src/providers/kiro-api-key.ts +33 -8
- package/src/providers/kiro-codewhisperer.ts +4 -1
- package/src/providers/openai-codex-responses.d.ts +6 -0
- package/src/providers/openai-codex-responses.ts +17 -2
- package/src/providers/pi-native-client.ts +24 -1
- package/src/utils/discovery/antigravity.ts +10 -1
- package/src/utils/discovery/openai-compatible.ts +38 -0
- package/src/utils/h2-fetch.ts +10 -0
- package/src/utils/oauth/callback-server.ts +8 -1
- package/src/utils/oauth/glm-zcode.ts +1 -1
- package/src/utils/oauth/kiro.ts +91 -22
- package/src/utils/schema/dereference.ts +169 -49
- package/src/utils/schema/draft.ts +46 -23
- package/src/utils/schema/normalize.d.ts +0 -5
- package/src/utils/schema/normalize.ts +396 -119
- package/src/utils/schema/types.ts +3 -1
- package/src/utils/schema/zod-decontaminate.ts +83 -29
- package/src/utils/sqlite-errors.d.ts +4 -0
- package/src/utils/sqlite-errors.ts +13 -0
- package/src/utils/tool-choice-capability.ts +2 -3
|
@@ -59,15 +59,39 @@ function toInputCapabilities(value: unknown): ("text" | "image")[] {
|
|
|
59
59
|
return supportsImage ? ["text", "image"] : ["text"];
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
/**
|
|
63
|
+
* models.dev serves one catalog document describing every provider, and a
|
|
64
|
+
* discovery pass resolves several providers from it. Downloads are coalesced
|
|
65
|
+
* per fetch implementation so one pass transfers the catalog once instead of
|
|
66
|
+
* once per provider; the window is short enough that a later refresh still
|
|
67
|
+
* observes catalog updates.
|
|
68
|
+
*/
|
|
69
|
+
const MODELS_DEV_PAYLOAD_TTL_MS = 60_000;
|
|
70
|
+
const modelsDevPayloadCache = new WeakMap<typeof fetch, { at: number; payload: Promise<unknown> }>();
|
|
71
|
+
|
|
72
|
+
export async function fetchModelsDevPayload(fetchImpl: typeof fetch = fetch): Promise<unknown> {
|
|
73
|
+
const now = Date.now();
|
|
74
|
+
const cached = modelsDevPayloadCache.get(fetchImpl);
|
|
75
|
+
if (cached && now - cached.at < MODELS_DEV_PAYLOAD_TTL_MS) return cached.payload;
|
|
76
|
+
const payload = (async () => {
|
|
77
|
+
const response = await fetchImpl(MODELS_DEV_URL, {
|
|
78
|
+
method: "GET",
|
|
79
|
+
headers: { Accept: "application/json" },
|
|
80
|
+
signal: AbortSignal.timeout(5_000),
|
|
81
|
+
});
|
|
82
|
+
if (!response.ok) {
|
|
83
|
+
throw new Error(`models.dev fetch failed: ${response.status}`);
|
|
84
|
+
}
|
|
85
|
+
return (await response.json()) as unknown;
|
|
86
|
+
})();
|
|
87
|
+
const entry = { at: now, payload };
|
|
88
|
+
modelsDevPayloadCache.set(fetchImpl, entry);
|
|
89
|
+
try {
|
|
90
|
+
return await payload;
|
|
91
|
+
} catch (error) {
|
|
92
|
+
if (modelsDevPayloadCache.get(fetchImpl) === entry) modelsDevPayloadCache.delete(fetchImpl);
|
|
93
|
+
throw error;
|
|
69
94
|
}
|
|
70
|
-
return response.json();
|
|
71
95
|
}
|
|
72
96
|
|
|
73
97
|
function anthropicToolChoiceCompat(modelId: string): Pick<Model<"anthropic-messages">, "compat"> {
|
|
@@ -2357,11 +2381,15 @@ const OPENCODE_GO_BASE_PATH = "https://opencode.ai/zen/go";
|
|
|
2357
2381
|
const OPENCODE_ZEN_API_RESOLUTION = createOpenCodeApiResolution("https://opencode.ai/zen");
|
|
2358
2382
|
const OPENCODE_GO_CHAT_COMPLETIONS_MODEL_IDS = [
|
|
2359
2383
|
"deepseek-v4-flash",
|
|
2384
|
+
"deepseek-v4-flash-vision-exp",
|
|
2360
2385
|
"deepseek-v4-pro",
|
|
2361
2386
|
"glm-5.1",
|
|
2362
2387
|
"glm-5.2",
|
|
2388
|
+
"glm-5.3-flash",
|
|
2363
2389
|
"kimi-k2.6",
|
|
2364
2390
|
"kimi-k2.7-code",
|
|
2391
|
+
"hy4-preview",
|
|
2392
|
+
"longcat-2.0",
|
|
2365
2393
|
"mimo-v2.5",
|
|
2366
2394
|
"mimo-v2.5-pro",
|
|
2367
2395
|
] as const;
|
|
@@ -2372,6 +2400,7 @@ const OPENCODE_GO_MESSAGES_MODEL_IDS = [
|
|
|
2372
2400
|
"qwen3.6-plus",
|
|
2373
2401
|
"qwen3.7-max",
|
|
2374
2402
|
"qwen3.7-plus",
|
|
2403
|
+
"qwen3.8-flash",
|
|
2375
2404
|
] as const;
|
|
2376
2405
|
const OPENCODE_GO_API_OVERRIDES: Readonly<Record<string, Api>> = {
|
|
2377
2406
|
...Object.fromEntries(OPENCODE_GO_CHAT_COMPLETIONS_MODEL_IDS.map(id => [id, "openai-completions"])),
|
|
@@ -2796,6 +2825,62 @@ const OPENCODE_GO_OFFICIAL_MODELS: Readonly<Record<string, OpenCodeGoOfficialMod
|
|
|
2796
2825
|
reasoning: true,
|
|
2797
2826
|
cost: { input: 0.066, output: 0.26, cacheRead: 0.029, cacheWrite: 0 },
|
|
2798
2827
|
},
|
|
2828
|
+
"deepseek-v4-flash-vision-exp": {
|
|
2829
|
+
name: "DeepSeek V4 Flash Vision Exp",
|
|
2830
|
+
contextWindow: 1_000_000,
|
|
2831
|
+
maxTokens: 384_000,
|
|
2832
|
+
input: ["text", "image"],
|
|
2833
|
+
reasoning: true,
|
|
2834
|
+
cost: { input: 0.22, output: 0.66, cacheRead: 0.007, cacheWrite: 0 },
|
|
2835
|
+
},
|
|
2836
|
+
"glm-5.3-flash": {
|
|
2837
|
+
name: "GLM-5.3-Flash (2x usage)",
|
|
2838
|
+
contextWindow: 1_000_000,
|
|
2839
|
+
maxTokens: 131_072,
|
|
2840
|
+
input: ["text", "image"],
|
|
2841
|
+
reasoning: true,
|
|
2842
|
+
cost: { input: 0.075, output: 0.25, cacheRead: 0.015, cacheWrite: 0 },
|
|
2843
|
+
},
|
|
2844
|
+
"grok-4.6": {
|
|
2845
|
+
name: "Grok 4.6",
|
|
2846
|
+
contextWindow: 500_000,
|
|
2847
|
+
maxTokens: 500_000,
|
|
2848
|
+
input: ["text", "image"],
|
|
2849
|
+
reasoning: true,
|
|
2850
|
+
cost: { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 },
|
|
2851
|
+
},
|
|
2852
|
+
"hy4-preview": {
|
|
2853
|
+
name: "Hy4 preview",
|
|
2854
|
+
contextWindow: 1_024_000,
|
|
2855
|
+
maxTokens: 64_000,
|
|
2856
|
+
input: ["text"],
|
|
2857
|
+
reasoning: true,
|
|
2858
|
+
cost: { input: 0.834, output: 2.501, cacheRead: 0.042, cacheWrite: 0 },
|
|
2859
|
+
},
|
|
2860
|
+
"longcat-2.0": {
|
|
2861
|
+
name: "LongCat-2.0",
|
|
2862
|
+
contextWindow: 1_000_000,
|
|
2863
|
+
maxTokens: 131_072,
|
|
2864
|
+
input: ["text"],
|
|
2865
|
+
reasoning: true,
|
|
2866
|
+
cost: { input: 0.3, output: 1.2, cacheRead: 0.006, cacheWrite: 0 },
|
|
2867
|
+
},
|
|
2868
|
+
"muse-spark-1.2-contributor": {
|
|
2869
|
+
name: "Muse Spark 1.2 Contributor",
|
|
2870
|
+
contextWindow: 1_048_576,
|
|
2871
|
+
maxTokens: 131_072,
|
|
2872
|
+
input: ["text", "image"],
|
|
2873
|
+
reasoning: true,
|
|
2874
|
+
cost: { input: 0.1, output: 0.2, cacheRead: 0.002, cacheWrite: 0 },
|
|
2875
|
+
},
|
|
2876
|
+
"qwen3.8-flash": {
|
|
2877
|
+
name: "Qwen3.8 Flash",
|
|
2878
|
+
contextWindow: 1_000_000,
|
|
2879
|
+
maxTokens: 131_072,
|
|
2880
|
+
input: ["text", "image"],
|
|
2881
|
+
reasoning: true,
|
|
2882
|
+
cost: { input: 0.15, output: 0.47, cacheRead: 0.016, cacheWrite: 0.2 },
|
|
2883
|
+
},
|
|
2799
2884
|
};
|
|
2800
2885
|
|
|
2801
2886
|
function applyOpenCodeGoOfficialMetadata<TApi extends Api>(model: Model<TApi>): Model<TApi> {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { $credentialEnv, $env, $flag, extractHttpStatusFromError, fetchWithRetry } from "@gajae-code/utils";
|
|
11
|
+
import { assertAwsRegionLabel } from "../adapter-internals/aws-region";
|
|
11
12
|
import type { Effort } from "../model-thinking";
|
|
12
13
|
import {
|
|
13
14
|
mapEffortToAnthropicAdaptiveEffort,
|
|
@@ -202,9 +203,10 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream"> = (
|
|
|
202
203
|
|
|
203
204
|
const blocks = output.content as Block[];
|
|
204
205
|
let rawRequestDump: RawHttpRequestDump | undefined;
|
|
205
|
-
const region = options.region
|
|
206
|
+
const region = options.region ?? $env.AWS_REGION ?? $env.AWS_DEFAULT_REGION ?? "us-east-1";
|
|
206
207
|
|
|
207
208
|
try {
|
|
209
|
+
assertAwsRegionLabel(region);
|
|
208
210
|
const cacheRetention = resolveCacheRetention(options.cacheRetention);
|
|
209
211
|
const resolvedToolChoice = resolveToolChoice(model, options.toolChoice);
|
|
210
212
|
const toolConfig = convertToolConfig(context.tools, resolvedToolChoice.resolvedChoice);
|
|
@@ -303,6 +305,7 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream"> = (
|
|
|
303
305
|
method: "POST",
|
|
304
306
|
headers: await buildRequestHeaders(retryBody),
|
|
305
307
|
body: retryBody,
|
|
308
|
+
redirect: "error",
|
|
306
309
|
signal: options.signal,
|
|
307
310
|
maxAttempts: 1,
|
|
308
311
|
});
|
|
@@ -312,6 +315,7 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream"> = (
|
|
|
312
315
|
method: "POST",
|
|
313
316
|
headers: requestHeaders,
|
|
314
317
|
body,
|
|
318
|
+
redirect: "error",
|
|
315
319
|
signal: options.signal,
|
|
316
320
|
maxAttempts: resolveRetryBudget(options.requestMaxRetries, 4) + 1,
|
|
317
321
|
});
|
|
@@ -107,7 +107,7 @@ export interface CpaToolAliasRestoreFailure {
|
|
|
107
107
|
*/
|
|
108
108
|
export declare function parseCpaToolAliasRestoreFailure(error: unknown): CpaToolAliasRestoreFailure | undefined;
|
|
109
109
|
export declare function isCpaToolAliasRestoreFailure(error: unknown): boolean;
|
|
110
|
-
export declare const claudeCodeVersion = "2.1.
|
|
110
|
+
export declare const claudeCodeVersion = "2.1.257";
|
|
111
111
|
export declare const claudeCodeEntrypoint = "sdk-cli";
|
|
112
112
|
export declare const claudeToolPrefix: string;
|
|
113
113
|
export declare const claudeCodeSystemInstruction = "You are a Claude agent, built on Anthropic's Claude Agent SDK.";
|
|
@@ -828,7 +828,7 @@ function getCacheControl(
|
|
|
828
828
|
}
|
|
829
829
|
|
|
830
830
|
// Stealth mode: Mimic Anthropic Code headers and tool prefixing.
|
|
831
|
-
export const claudeCodeVersion = "2.1.
|
|
831
|
+
export const claudeCodeVersion = "2.1.257";
|
|
832
832
|
export const claudeCodeEntrypoint = "sdk-cli";
|
|
833
833
|
export const claudeToolPrefix: string = "proxy_";
|
|
834
834
|
export const claudeCodeSystemInstruction = "You are a Claude agent, built on Anthropic's Claude Agent SDK.";
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
import * as fs from "node:fs";
|
|
23
23
|
import * as path from "node:path";
|
|
24
24
|
import { $env, getTrustedHomeDir, isEnoent, logger } from "@gajae-code/utils";
|
|
25
|
+
import { assertAwsRegionLabel } from "../adapter-internals/aws-region";
|
|
25
26
|
import {
|
|
26
27
|
type AwsIniFile,
|
|
27
28
|
classifyAwsProfileCapability,
|
|
@@ -155,6 +156,7 @@ async function readSsoCredentials(
|
|
|
155
156
|
}
|
|
156
157
|
}
|
|
157
158
|
if (!startUrl || !ssoRegion) return undefined;
|
|
159
|
+
assertAwsRegionLabel(ssoRegion);
|
|
158
160
|
|
|
159
161
|
const token = await loadSsoCachedToken(startUrl, sessionName);
|
|
160
162
|
if (!token?.accessToken) {
|
|
@@ -172,6 +174,7 @@ async function readSsoCredentials(
|
|
|
172
174
|
const response = await fetch(url, {
|
|
173
175
|
method: "GET",
|
|
174
176
|
headers: { "x-amz-sso_bearer_token": token.accessToken },
|
|
177
|
+
redirect: "error",
|
|
175
178
|
signal,
|
|
176
179
|
});
|
|
177
180
|
if (!response.ok) {
|
|
@@ -411,6 +414,7 @@ async function readImdsCredentials(parentSignal: AbortSignal | undefined): Promi
|
|
|
411
414
|
const tokenRes = await fetch(`http://${IMDS_HOST}/latest/api/token`, {
|
|
412
415
|
method: "PUT",
|
|
413
416
|
headers: { "x-aws-ec2-metadata-token-ttl-seconds": "21600" },
|
|
417
|
+
redirect: "error",
|
|
414
418
|
signal,
|
|
415
419
|
});
|
|
416
420
|
if (!tokenRes.ok) return undefined;
|
|
@@ -418,6 +422,7 @@ async function readImdsCredentials(parentSignal: AbortSignal | undefined): Promi
|
|
|
418
422
|
|
|
419
423
|
const roleRes = await fetch(`http://${IMDS_HOST}/latest/meta-data/iam/security-credentials/`, {
|
|
420
424
|
headers: { "x-aws-ec2-metadata-token": token },
|
|
425
|
+
redirect: "error",
|
|
421
426
|
signal,
|
|
422
427
|
});
|
|
423
428
|
if (!roleRes.ok) return undefined;
|
|
@@ -428,6 +433,7 @@ async function readImdsCredentials(parentSignal: AbortSignal | undefined): Promi
|
|
|
428
433
|
`http://${IMDS_HOST}/latest/meta-data/iam/security-credentials/${encodeURIComponent(role)}`,
|
|
429
434
|
{
|
|
430
435
|
headers: { "x-aws-ec2-metadata-token": token },
|
|
436
|
+
redirect: "error",
|
|
431
437
|
signal,
|
|
432
438
|
},
|
|
433
439
|
);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { type JsonValue } from "@bufbuild/protobuf";
|
|
2
|
-
import type { CursorExecHandlerResult, CursorExecHandlers, CursorToolResultHandler, Message, Model, StreamFunction, StreamOptions, ToolCall, ToolResultMessage } from "../types";
|
|
2
|
+
import type { AssistantMessage, CursorExecHandlerResult, CursorExecHandlers, CursorToolResultHandler, Message, Model, StreamFunction, StreamOptions, ToolCall, ToolResultMessage, Usage } from "../types";
|
|
3
3
|
import { kCursorExecResolved } from "../utils/block-symbols";
|
|
4
4
|
import { CURSOR_CLIENT_VERSION } from "./cursor/client-version";
|
|
5
5
|
import type { CursorRule, RequestedModel_ModelParameterbytes } from "./cursor/gen/agent_pb";
|
|
6
|
+
import { type ConversationStateStructure } from "./cursor/gen/agent_pb";
|
|
6
7
|
export declare const CURSOR_API_URL = "https://api2.cursor.sh";
|
|
7
8
|
export { CURSOR_CLIENT_VERSION };
|
|
8
9
|
/** Drop all cached state + blob bytes for a conversation (F15 bound + session-teardown hook). */
|
|
@@ -31,6 +32,19 @@ type ToolCallState = ToolCall & {
|
|
|
31
32
|
kind: "mcp" | "todo_write" | "native" | "cursor-exec";
|
|
32
33
|
[kCursorExecResolved]?: true;
|
|
33
34
|
};
|
|
35
|
+
interface UsageState {
|
|
36
|
+
sawTokenDelta: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Latest `ConversationTokenDetails.used_tokens`: the whole conversation's
|
|
39
|
+
* token consumption as counted by Cursor, not this turn's output.
|
|
40
|
+
*/
|
|
41
|
+
conversationUsedTokens: number;
|
|
42
|
+
/** Output tokens already included in the latest checkpoint snapshot. */
|
|
43
|
+
checkpointOutputTokens: number;
|
|
44
|
+
/** Whether the current stream received a checkpoint, including an explicit zero. */
|
|
45
|
+
hasConversationCheckpoint: boolean;
|
|
46
|
+
pendingCheckpoint?: ConversationStateStructure;
|
|
47
|
+
}
|
|
34
48
|
/** Exported for tests: verifies handler is invoked with correct `this` when passed as bound. */
|
|
35
49
|
export declare function resolveExecHandler<TArgs, TResult>(args: TArgs, handler: ((args: TArgs) => Promise<CursorExecHandlerResult<TResult>>) | undefined, onToolResult: CursorToolResultHandler | undefined, buildFromToolResult: (toolResult: ToolResultMessage) => TResult, buildRejected: (reason: string) => TResult, buildError: (error: string) => TResult): Promise<{
|
|
36
50
|
execResult: TResult;
|
|
@@ -44,6 +58,18 @@ export declare function createCursorMessageQueueForTest(onError?: (error: unknow
|
|
|
44
58
|
/** Exported for direct regression coverage of the JSON-safety boundary. */
|
|
45
59
|
export declare function cursorJsonSafeValueForTest(value: unknown): unknown;
|
|
46
60
|
export declare function buildNativeToolCallBlock(toolCall: Record<string, unknown>, callId: string, index: number): ToolCallState | null;
|
|
61
|
+
/**
|
|
62
|
+
* Cursor streams output tokens as deltas and reports whole-conversation
|
|
63
|
+
* consumption separately as `ConversationTokenDetails.used_tokens`. Derive
|
|
64
|
+
* prompt tokens from the difference so context accounting and compaction see a
|
|
65
|
+
* real prompt size instead of zero.
|
|
66
|
+
*/
|
|
67
|
+
export declare function finalizeCursorUsage(output: AssistantMessage, usageState: UsageState): void;
|
|
68
|
+
/** Exposes {@link finalizeCursorUsage} for tests without a live HTTP/2 stream. */
|
|
69
|
+
export declare function finalizeCursorUsageForTest(usedTokens: number, outputTokens: number, options?: {
|
|
70
|
+
checkpointOutputTokens?: number;
|
|
71
|
+
hasConversationCheckpoint?: boolean;
|
|
72
|
+
}): Usage;
|
|
47
73
|
/**
|
|
48
74
|
* Build `ConversationStateStructure.rootPromptMessagesJson` blob IDs for the
|
|
49
75
|
* system prompt plus prior conversation history, as JSON blobs matching
|