aisubs 0.3.3 → 0.3.5
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 +12 -0
- package/dist/auth.d.ts +2 -2
- package/dist/auth.js +7 -2
- package/dist/compatibility.js +37 -9
- package/dist/providers/chatgpt.js +20 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.5 - 2026-09-14
|
|
4
|
+
|
|
5
|
+
- Move ChatGPT Responses instructions into the developer input prefix so
|
|
6
|
+
stable subscription prompts participate in prompt caching.
|
|
7
|
+
|
|
8
|
+
## 0.3.4 - 2026-09-13
|
|
9
|
+
|
|
10
|
+
- Refresh account model catalogs on demand and update ChatGPT compatibility so
|
|
11
|
+
newly available subscription models appear without stale cached listings.
|
|
12
|
+
- Preserve prompt-cache routing and cache read/write usage when translating
|
|
13
|
+
between OpenAI, Anthropic, and Responses-compatible protocols.
|
|
14
|
+
|
|
3
15
|
## 0.3.3 - 2026-09-02
|
|
4
16
|
|
|
5
17
|
- Show remaining usage percentages in account meter values and progress bars,
|
package/dist/auth.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export interface SubscriptionAccount {
|
|
|
19
19
|
fetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;
|
|
20
20
|
proxy(path: string, init?: RequestInit): Promise<Response>;
|
|
21
21
|
getUsage(signal?: AbortSignal): Promise<ProviderUsage | null>;
|
|
22
|
-
getModels(signal?: AbortSignal): Promise<ProviderModels | null>;
|
|
22
|
+
getModels(signal?: AbortSignal, force?: boolean): Promise<ProviderModels | null>;
|
|
23
23
|
credentialSummary(): Promise<CredentialSummary>;
|
|
24
24
|
details(signal?: AbortSignal): Promise<SubscriptionAccountDetails>;
|
|
25
25
|
}
|
|
@@ -69,7 +69,7 @@ export declare class SubscriptionAuth {
|
|
|
69
69
|
/** Build an authorized direct-provider request for transports such as WebSocket. */
|
|
70
70
|
authorizeProxyRequest(provider: ProviderId, account: string, path: string, init?: RequestInit): Promise<Request>;
|
|
71
71
|
getUsage(provider: ProviderId, account?: string, callerSignal?: AbortSignal): Promise<ProviderUsage | null>;
|
|
72
|
-
getModels(provider: ProviderId, account?: string, callerSignal?: AbortSignal): Promise<ProviderModels | null>;
|
|
72
|
+
getModels(provider: ProviderId, account?: string, callerSignal?: AbortSignal, force?: boolean): Promise<ProviderModels | null>;
|
|
73
73
|
account(provider: ProviderId, account: string): SubscriptionAccount;
|
|
74
74
|
}
|
|
75
75
|
export declare function createSubscriptionAuth(options: {
|
package/dist/auth.js
CHANGED
|
@@ -459,12 +459,17 @@ export class SubscriptionAuth {
|
|
|
459
459
|
return data ? { provider, accountKey, asOf: Date.now(), ...data } : null;
|
|
460
460
|
});
|
|
461
461
|
}
|
|
462
|
-
async getModels(provider, account = DEFAULT_ACCOUNT, callerSignal) {
|
|
462
|
+
async getModels(provider, account = DEFAULT_ACCOUNT, callerSignal, force = false) {
|
|
463
463
|
const adapter = this.adapter(provider);
|
|
464
464
|
if (!adapter.getModels)
|
|
465
465
|
return null;
|
|
466
466
|
const accountKey = normalizeAccountKey(account);
|
|
467
467
|
const scope = credentialKey(provider, accountKey);
|
|
468
|
+
if (force) {
|
|
469
|
+
this.modelsCache.delete(scope);
|
|
470
|
+
this.modelsInflight.delete(scope);
|
|
471
|
+
this.metadataGenerations.set(scope, (this.metadataGenerations.get(scope) ?? 0) + 1);
|
|
472
|
+
}
|
|
468
473
|
return this.cachedMetadata(this.modelsCache, this.modelsInflight, scope, this.modelsCacheTtlMs, callerSignal, async () => {
|
|
469
474
|
const credential = await this.credential(provider, accountKey);
|
|
470
475
|
const timeout = AbortSignal.timeout(this.refreshTimeoutMs);
|
|
@@ -490,7 +495,7 @@ export class SubscriptionAuth {
|
|
|
490
495
|
fetch: (input, init) => this.fetch(provider, input, init, accountKey),
|
|
491
496
|
proxy: (path, init) => this.proxy(provider, accountKey, path, init),
|
|
492
497
|
getUsage: (signal) => this.getUsage(provider, accountKey, signal),
|
|
493
|
-
getModels: (signal) => this.getModels(provider, accountKey, signal),
|
|
498
|
+
getModels: (signal, force) => this.getModels(provider, accountKey, signal, force),
|
|
494
499
|
credentialSummary: () => this.credentialSummary(provider, accountKey),
|
|
495
500
|
details: (signal) => this.details(provider, accountKey, signal),
|
|
496
501
|
};
|
package/dist/compatibility.js
CHANGED
|
@@ -150,6 +150,7 @@ function parseChat(body) {
|
|
|
150
150
|
responseFormat: raw.response_format,
|
|
151
151
|
metadata: raw.metadata,
|
|
152
152
|
user: stringValue(raw.user),
|
|
153
|
+
promptCacheKey: stringValue(raw.prompt_cache_key),
|
|
153
154
|
};
|
|
154
155
|
}
|
|
155
156
|
function responseTools(value) {
|
|
@@ -243,6 +244,7 @@ function parseResponses(body) {
|
|
|
243
244
|
responseFormat,
|
|
244
245
|
metadata: raw.metadata,
|
|
245
246
|
user: stringValue(raw.user),
|
|
247
|
+
promptCacheKey: stringValue(raw.prompt_cache_key),
|
|
246
248
|
};
|
|
247
249
|
}
|
|
248
250
|
function anthropicParts(value) {
|
|
@@ -472,6 +474,7 @@ function toChat(request) {
|
|
|
472
474
|
...(request.responseFormat != null ? { response_format: request.responseFormat } : {}),
|
|
473
475
|
...(request.metadata != null ? { metadata: request.metadata } : {}),
|
|
474
476
|
...(request.user ? { user: request.user } : {}),
|
|
477
|
+
...(request.promptCacheKey ? { prompt_cache_key: request.promptCacheKey } : {}),
|
|
475
478
|
};
|
|
476
479
|
}
|
|
477
480
|
function responseContent(part, role) {
|
|
@@ -557,6 +560,7 @@ function toResponses(request) {
|
|
|
557
560
|
...(format != null ? { text: { format } } : {}),
|
|
558
561
|
...(request.metadata != null ? { metadata: request.metadata } : {}),
|
|
559
562
|
...(request.user ? { user: request.user } : {}),
|
|
563
|
+
...(request.promptCacheKey ? { prompt_cache_key: request.promptCacheKey } : {}),
|
|
560
564
|
};
|
|
561
565
|
}
|
|
562
566
|
function anthropicContent(message) {
|
|
@@ -703,7 +707,7 @@ function toGoogle(request) {
|
|
|
703
707
|
},
|
|
704
708
|
};
|
|
705
709
|
}
|
|
706
|
-
function usage(input, output, cached, reasoning) {
|
|
710
|
+
function usage(input, output, cached, reasoning, cacheWrite) {
|
|
707
711
|
if (input == null && output == null)
|
|
708
712
|
return undefined;
|
|
709
713
|
return {
|
|
@@ -711,6 +715,7 @@ function usage(input, output, cached, reasoning) {
|
|
|
711
715
|
output: output ?? 0,
|
|
712
716
|
total: (input ?? 0) + (output ?? 0),
|
|
713
717
|
...(cached != null ? { cached } : {}),
|
|
718
|
+
...(cacheWrite != null ? { cacheWrite } : {}),
|
|
714
719
|
...(reasoning != null ? { reasoning } : {}),
|
|
715
720
|
};
|
|
716
721
|
}
|
|
@@ -735,7 +740,7 @@ function parseChatResult(raw, model) {
|
|
|
735
740
|
finishReason: finish === "length" || finish === "tool_calls" || finish === "content_filter"
|
|
736
741
|
? finish
|
|
737
742
|
: "stop",
|
|
738
|
-
usage: usage(numberValue(details?.prompt_tokens), numberValue(details?.completion_tokens), numberValue(promptDetails?.cached_tokens), numberValue(completionDetails?.reasoning_tokens)),
|
|
743
|
+
usage: usage(numberValue(details?.prompt_tokens), numberValue(details?.completion_tokens), numberValue(promptDetails?.cached_tokens), numberValue(completionDetails?.reasoning_tokens), numberValue(promptDetails?.cache_write_tokens)),
|
|
739
744
|
};
|
|
740
745
|
}
|
|
741
746
|
function parseResponsesResult(raw, model) {
|
|
@@ -785,7 +790,7 @@ function parseResponsesResult(raw, model) {
|
|
|
785
790
|
: raw.status === "failed"
|
|
786
791
|
? "error"
|
|
787
792
|
: "stop",
|
|
788
|
-
usage: usage(numberValue(details?.input_tokens), numberValue(details?.output_tokens), numberValue(inputDetails?.cached_tokens), numberValue(outputDetails?.reasoning_tokens)),
|
|
793
|
+
usage: usage(numberValue(details?.input_tokens), numberValue(details?.output_tokens), numberValue(inputDetails?.cached_tokens), numberValue(outputDetails?.reasoning_tokens), numberValue(inputDetails?.cache_write_tokens)),
|
|
789
794
|
};
|
|
790
795
|
}
|
|
791
796
|
function parseAnthropicResult(raw, model) {
|
|
@@ -805,7 +810,11 @@ function parseAnthropicResult(raw, model) {
|
|
|
805
810
|
: stop === "refusal"
|
|
806
811
|
? "content_filter"
|
|
807
812
|
: "stop",
|
|
808
|
-
usage: usage(
|
|
813
|
+
usage: usage(rawUsage?.input_tokens != null
|
|
814
|
+
? (numberValue(rawUsage.input_tokens) ?? 0) +
|
|
815
|
+
(numberValue(rawUsage.cache_read_input_tokens) ?? 0) +
|
|
816
|
+
(numberValue(rawUsage.cache_creation_input_tokens) ?? 0)
|
|
817
|
+
: undefined, numberValue(rawUsage?.output_tokens), numberValue(rawUsage?.cache_read_input_tokens), undefined, numberValue(rawUsage?.cache_creation_input_tokens)),
|
|
809
818
|
};
|
|
810
819
|
}
|
|
811
820
|
function parseGoogleResult(raw, model) {
|
|
@@ -876,8 +885,15 @@ function resultToChat(result) {
|
|
|
876
885
|
prompt_tokens: result.usage.input,
|
|
877
886
|
completion_tokens: result.usage.output,
|
|
878
887
|
total_tokens: result.usage.total,
|
|
879
|
-
...(result.usage.cached != null
|
|
880
|
-
? {
|
|
888
|
+
...(result.usage.cached != null || result.usage.cacheWrite != null
|
|
889
|
+
? {
|
|
890
|
+
prompt_tokens_details: {
|
|
891
|
+
...(result.usage.cached != null ? { cached_tokens: result.usage.cached } : {}),
|
|
892
|
+
...(result.usage.cacheWrite != null
|
|
893
|
+
? { cache_write_tokens: result.usage.cacheWrite }
|
|
894
|
+
: {}),
|
|
895
|
+
},
|
|
896
|
+
}
|
|
881
897
|
: {}),
|
|
882
898
|
...(result.usage.reasoning != null
|
|
883
899
|
? { completion_tokens_details: { reasoning_tokens: result.usage.reasoning } }
|
|
@@ -935,7 +951,16 @@ function resultToResponses(result) {
|
|
|
935
951
|
input_tokens: result.usage.input,
|
|
936
952
|
output_tokens: result.usage.output,
|
|
937
953
|
total_tokens: result.usage.total,
|
|
938
|
-
|
|
954
|
+
...(result.usage.cached != null || result.usage.cacheWrite != null
|
|
955
|
+
? {
|
|
956
|
+
input_tokens_details: {
|
|
957
|
+
...(result.usage.cached != null ? { cached_tokens: result.usage.cached } : {}),
|
|
958
|
+
...(result.usage.cacheWrite != null
|
|
959
|
+
? { cache_write_tokens: result.usage.cacheWrite }
|
|
960
|
+
: {}),
|
|
961
|
+
},
|
|
962
|
+
}
|
|
963
|
+
: {}),
|
|
939
964
|
output_tokens_details: { reasoning_tokens: result.usage.reasoning ?? 0 },
|
|
940
965
|
},
|
|
941
966
|
}
|
|
@@ -965,11 +990,14 @@ function resultToAnthropic(result) {
|
|
|
965
990
|
...(result.usage
|
|
966
991
|
? {
|
|
967
992
|
usage: {
|
|
968
|
-
input_tokens: result.usage.input,
|
|
993
|
+
input_tokens: Math.max(0, result.usage.input - (result.usage.cached ?? 0) - (result.usage.cacheWrite ?? 0)),
|
|
969
994
|
output_tokens: result.usage.output,
|
|
970
995
|
...(result.usage.cached != null
|
|
971
996
|
? { cache_read_input_tokens: result.usage.cached }
|
|
972
997
|
: {}),
|
|
998
|
+
...(result.usage.cacheWrite != null
|
|
999
|
+
? { cache_creation_input_tokens: result.usage.cacheWrite }
|
|
1000
|
+
: {}),
|
|
973
1001
|
},
|
|
974
1002
|
}
|
|
975
1003
|
: {}),
|
|
@@ -1269,7 +1297,7 @@ function streamAnthropic(result) {
|
|
|
1269
1297
|
...message,
|
|
1270
1298
|
content: [],
|
|
1271
1299
|
stop_reason: null,
|
|
1272
|
-
usage
|
|
1300
|
+
...(message.usage ? { usage: { ...message.usage, output_tokens: 0 } } : {}),
|
|
1273
1301
|
},
|
|
1274
1302
|
});
|
|
1275
1303
|
for (const [index, block] of message.content.entries()) {
|
|
@@ -109,6 +109,25 @@ async function normalizeChatGptRequest(request) {
|
|
|
109
109
|
if (!isRecord(raw))
|
|
110
110
|
return request;
|
|
111
111
|
const body = { ...raw };
|
|
112
|
+
// The Codex endpoint places the implicit cache boundary after input
|
|
113
|
+
// messages. Move stable top-level instructions into that prefix so they
|
|
114
|
+
// participate in prompt caching for subscription requests.
|
|
115
|
+
if (typeof body.instructions === "string" && body.instructions.length > 0) {
|
|
116
|
+
const input = Array.isArray(body.input)
|
|
117
|
+
? body.input
|
|
118
|
+
: typeof body.input === "string"
|
|
119
|
+
? [{ type: "message", role: "user", content: body.input }]
|
|
120
|
+
: [];
|
|
121
|
+
body.input = [
|
|
122
|
+
{
|
|
123
|
+
type: "message",
|
|
124
|
+
role: "developer",
|
|
125
|
+
content: [{ type: "input_text", text: body.instructions }],
|
|
126
|
+
},
|
|
127
|
+
...input,
|
|
128
|
+
];
|
|
129
|
+
delete body.instructions;
|
|
130
|
+
}
|
|
112
131
|
delete body.prompt_cache_options;
|
|
113
132
|
delete body.prompt_cache_retention;
|
|
114
133
|
const stripBreakpoints = (value) => Array.isArray(value)
|
|
@@ -126,7 +145,7 @@ async function normalizeChatGptRequest(request) {
|
|
|
126
145
|
}
|
|
127
146
|
export function chatGptProvider(options = {}) {
|
|
128
147
|
const clientId = options.clientId ?? DEFAULT_CLIENT_ID;
|
|
129
|
-
const compatibilityVersion = options.compatibilityVersion ?? "0.
|
|
148
|
+
const compatibilityVersion = options.compatibilityVersion ?? "0.154.0";
|
|
130
149
|
const fetcher = options.fetch ?? globalThis.fetch;
|
|
131
150
|
async function startDeviceLogin(signal) {
|
|
132
151
|
const response = await fetcher(DEVICE_CODE_URL, {
|