@gajae-code/ai 0.9.0 → 0.9.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 +8 -0
- package/dist/types/providers/cursor/client-version.d.ts +10 -0
- package/dist/types/providers/cursor.d.ts +2 -1
- package/package.json +3 -6
- package/src/providers/cursor/client-version.ts +10 -0
- package/src/providers/cursor.ts +2 -1
- package/src/rate-limit-utils.ts +4 -2
- package/src/utils/discovery/cursor.ts +2 -2
- package/src/utils/oauth/fugu.ts +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.9.1] - 2026-07-08
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Unified the Cursor client version used across provider requests and discovery.
|
|
10
|
+
- Detected ZAI weekly limit exhaustion as a structured rate-limit condition.
|
|
11
|
+
- Pointed Sakana Fugu OAuth/login guidance at the Sakana platform console and documented the `fish_` key prefix expectation.
|
|
12
|
+
|
|
5
13
|
## [0.9.0] - 2026-07-07
|
|
6
14
|
|
|
7
15
|
### Fixed
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Cursor client version reported to api2.cursor.sh.
|
|
3
|
+
*
|
|
4
|
+
* Every call against the Cursor backend must send the same
|
|
5
|
+
* x-cursor-client-version: the backend gates features and minimum versions on
|
|
6
|
+
* it, so a drift between the agent Run path and model discovery makes one of
|
|
7
|
+
* them fail while the other keeps working. Keep this as the single source of
|
|
8
|
+
* truth for the header value.
|
|
9
|
+
*/
|
|
10
|
+
export declare const CURSOR_CLIENT_VERSION = "cli-2026.02.13-41ac335";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type JsonValue } from "@bufbuild/protobuf";
|
|
2
2
|
import type { CursorExecHandlerResult, CursorExecHandlers, CursorToolResultHandler, Message, StreamFunction, StreamOptions, ToolResultMessage } from "../types";
|
|
3
|
+
import { CURSOR_CLIENT_VERSION } from "./cursor/client-version";
|
|
3
4
|
export declare const CURSOR_API_URL = "https://api2.cursor.sh";
|
|
4
|
-
export
|
|
5
|
+
export { CURSOR_CLIENT_VERSION };
|
|
5
6
|
/** Drop all cached state + blob bytes for a conversation (F15 bound + session-teardown hook). */
|
|
6
7
|
export declare function disposeCursorConversation(conversationId: string): void;
|
|
7
8
|
export interface CursorOptions extends StreamOptions {
|
package/package.json
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@gajae-code/ai",
|
|
4
|
-
"version": "0.9.
|
|
4
|
+
"version": "0.9.1",
|
|
5
5
|
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
|
6
6
|
"homepage": "https://gajae-code.com",
|
|
7
|
-
"author": "Yeachan-Heo",
|
|
8
|
-
"contributors": [
|
|
9
|
-
"Mario Zechner"
|
|
10
|
-
],
|
|
7
|
+
"author": "Yeachan-Heo and Gajae Code Contributors",
|
|
11
8
|
"license": "MIT",
|
|
12
9
|
"repository": {
|
|
13
10
|
"type": "git",
|
|
@@ -43,7 +40,7 @@
|
|
|
43
40
|
"dependencies": {
|
|
44
41
|
"@anthropic-ai/sdk": "^0.94.0",
|
|
45
42
|
"@bufbuild/protobuf": "^2.12.0",
|
|
46
|
-
"@gajae-code/utils": "0.9.
|
|
43
|
+
"@gajae-code/utils": "0.9.1",
|
|
47
44
|
"openai": "^6.36.0",
|
|
48
45
|
"partial-json": "^0.1.7",
|
|
49
46
|
"zod": "4.4.3"
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Cursor client version reported to api2.cursor.sh.
|
|
3
|
+
*
|
|
4
|
+
* Every call against the Cursor backend must send the same
|
|
5
|
+
* x-cursor-client-version: the backend gates features and minimum versions on
|
|
6
|
+
* it, so a drift between the agent Run path and model discovery makes one of
|
|
7
|
+
* them fail while the other keeps working. Keep this as the single source of
|
|
8
|
+
* truth for the header value.
|
|
9
|
+
*/
|
|
10
|
+
export const CURSOR_CLIENT_VERSION = "cli-2026.02.13-41ac335";
|
package/src/providers/cursor.ts
CHANGED
|
@@ -31,6 +31,7 @@ import { parseStreamingJson } from "../utils/json-parse";
|
|
|
31
31
|
import { formatErrorMessageWithRetryAfter } from "../utils/retry-after";
|
|
32
32
|
import { flattenToolRootCombinators, toolWireSchema } from "../utils/schema";
|
|
33
33
|
import { COMPOSER_EDIT_DISCIPLINE_PROMPT, isComposerHarnessModel } from "./composer-discipline";
|
|
34
|
+
import { CURSOR_CLIENT_VERSION } from "./cursor/client-version";
|
|
34
35
|
import type { McpToolDefinition } from "./cursor/gen/agent_pb";
|
|
35
36
|
import {
|
|
36
37
|
AgentClientMessageSchema,
|
|
@@ -131,7 +132,7 @@ import {
|
|
|
131
132
|
} from "./cursor/gen/agent_pb";
|
|
132
133
|
|
|
133
134
|
export const CURSOR_API_URL = "https://api2.cursor.sh";
|
|
134
|
-
export
|
|
135
|
+
export { CURSOR_CLIENT_VERSION };
|
|
135
136
|
|
|
136
137
|
const conversationStateCache = new Map<string, ConversationStateStructure>();
|
|
137
138
|
const conversationBlobStores = new Map<string, Map<string, Uint8Array>>();
|
package/src/rate-limit-utils.ts
CHANGED
|
@@ -13,7 +13,7 @@ export type RateLimitReason =
|
|
|
13
13
|
const QUOTA_EXHAUSTED_BACKOFF_MS = 30 * 60 * 1000; // 30 min
|
|
14
14
|
const RATE_LIMIT_EXCEEDED_BACKOFF_MS = 30 * 1000; // 30s
|
|
15
15
|
const MODEL_CAPACITY_BASE_MS = 45 * 1000; // 45s base
|
|
16
|
-
const MODEL_CAPACITY_JITTER_MS = 30 * 1000; //
|
|
16
|
+
const MODEL_CAPACITY_JITTER_MS = 30 * 1000; // uniform +0–30s above base → 45–75s total
|
|
17
17
|
const SERVER_ERROR_BACKOFF_MS = 20 * 1000; // 20s
|
|
18
18
|
|
|
19
19
|
/**
|
|
@@ -93,8 +93,10 @@ export function calculateRateLimitBackoffMs(reason: RateLimitReason): number {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
/** Detect usage/quota limit errors in error messages (persistent, requires credential switch). */
|
|
96
|
+
// ZAI reports durable token exhaustion as "[1310][Weekly/Monthly Limit Exhausted...]".
|
|
97
|
+
// Keep this explicit so generic "rate limit exhausted, retry..." throttles remain retryable.
|
|
96
98
|
const USAGE_LIMIT_PATTERN =
|
|
97
|
-
/usage.?limit|usage_limit_reached|usage_not_included|limit_reached|model.?limit|model_limit_reached|message.?limit|message_limit_reached|limit for this model|quota.?exceeded|out_of_credits|request would exceed your account.?s rate limit|resource has been exhausted[^\n]*(?:quota|limit)/i;
|
|
99
|
+
/usage.?limit|usage_limit_reached|usage_not_included|limit_reached|model.?limit|model_limit_reached|message.?limit|message_limit_reached|limit for this model|weekly\/monthly\s+limit\s+exhausted|quota.?exceeded|out_of_credits|request would exceed your account.?s rate limit|resource has been exhausted[^\n]*(?:quota|limit)/i;
|
|
98
100
|
export function isUsageLimitError(errorMessage: string): boolean {
|
|
99
101
|
return USAGE_LIMIT_PATTERN.test(errorMessage);
|
|
100
102
|
}
|
|
@@ -2,11 +2,11 @@ import * as http2 from "node:http2";
|
|
|
2
2
|
import { create, fromBinary, toBinary } from "@bufbuild/protobuf";
|
|
3
3
|
import * as z from "zod/v4";
|
|
4
4
|
import { getBundledModels } from "../../models";
|
|
5
|
+
import { CURSOR_CLIENT_VERSION } from "../../providers/cursor/client-version";
|
|
5
6
|
import { GetUsableModelsRequestSchema, GetUsableModelsResponseSchema } from "../../providers/cursor/gen/agent_pb";
|
|
6
7
|
import type { Model } from "../../types";
|
|
7
8
|
|
|
8
9
|
const CURSOR_DEFAULT_BASE_URL = "https://api2.cursor.sh";
|
|
9
|
-
const CURSOR_DEFAULT_CLIENT_VERSION = "cli-2026.02.13-41ac335";
|
|
10
10
|
const CURSOR_GET_USABLE_MODELS_PATH = "/agent.v1.AgentService/GetUsableModels";
|
|
11
11
|
|
|
12
12
|
const DEFAULT_CONTEXT_WINDOW = 200_000;
|
|
@@ -91,7 +91,7 @@ function buildRequestHeaders(options: CursorModelDiscoveryOptions): Record<strin
|
|
|
91
91
|
te: "trailers",
|
|
92
92
|
authorization: `Bearer ${options.apiKey}`,
|
|
93
93
|
"x-ghost-mode": "true",
|
|
94
|
-
"x-cursor-client-version": options.clientVersion ??
|
|
94
|
+
"x-cursor-client-version": options.clientVersion ?? CURSOR_CLIENT_VERSION,
|
|
95
95
|
"x-cursor-client-type": "cli",
|
|
96
96
|
};
|
|
97
97
|
}
|
package/src/utils/oauth/fugu.ts
CHANGED
|
@@ -3,10 +3,10 @@ import { createApiKeyLogin } from "./api-key-login";
|
|
|
3
3
|
|
|
4
4
|
export const loginFugu = createApiKeyLogin({
|
|
5
5
|
providerLabel: "Sakana Fugu",
|
|
6
|
-
authUrl: "https://
|
|
6
|
+
authUrl: "https://console.sakana.ai/api-keys",
|
|
7
7
|
instructions: "Create or copy your Sakana Fugu API key",
|
|
8
8
|
promptMessage: "Paste your Sakana Fugu API key",
|
|
9
|
-
placeholder: "
|
|
9
|
+
placeholder: "fish_...",
|
|
10
10
|
validation: {
|
|
11
11
|
kind: "models-endpoint",
|
|
12
12
|
provider: "Sakana Fugu",
|