@oh-my-pi/pi-ai 18.2.8 → 18.2.9
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 +33 -18
- package/dist/types/auth-gateway/types.d.ts +5 -0
- package/dist/types/auth-storage.d.ts +35 -32
- package/dist/types/index.d.ts +1 -0
- package/dist/types/providers/amazon-bedrock.d.ts +7 -0
- package/dist/types/providers/claude-code-fingerprint.d.ts +22 -3
- package/dist/types/providers/google-gemini-cli.d.ts +0 -2
- package/dist/types/providers/openai-chat-server-schema.d.ts +2 -2
- package/dist/types/usage/claude-api.d.ts +22 -0
- package/dist/types/usage/claude-reset.d.ts +44 -0
- package/dist/types/usage.d.ts +111 -5
- package/dist/types/utils/schema/json-schema-validator.d.ts +5 -2
- package/dist/types/utils/tool-call-loop-guard.d.ts +1 -1
- package/package.json +6 -6
- package/src/auth/sqlite-credential-store.ts +44 -1
- package/src/auth-broker/remote-store.ts +6 -6
- package/src/auth-broker/wire-schemas.ts +14 -0
- package/src/auth-gateway/server.ts +4 -0
- package/src/auth-gateway/types.ts +5 -0
- package/src/auth-storage.ts +263 -140
- package/src/error/flags.ts +10 -0
- package/src/index.ts +1 -0
- package/src/providers/amazon-bedrock.ts +55 -5
- package/src/providers/anthropic.ts +45 -11
- package/src/providers/aws-credentials.ts +124 -11
- package/src/providers/claude-code-fingerprint.ts +55 -3
- package/src/providers/gitlab-duo.ts +20 -4
- package/src/providers/google-gemini-cli.ts +0 -8
- package/src/providers/google-shared.ts +1 -18
- package/src/providers/openai-chat-server-schema.ts +1 -1
- package/src/providers/openai-chat-server.ts +3 -1
- package/src/providers/openai-codex-responses.ts +27 -5
- package/src/providers/openai-completions.ts +122 -19
- package/src/providers/pi-native-server.ts +1 -0
- package/src/registry/oauth/anthropic.ts +2 -3
- package/src/stream.ts +13 -4
- package/src/usage/alibaba-token-plan.ts +7 -1
- package/src/usage/claude-api.ts +66 -0
- package/src/usage/claude-reset.ts +638 -0
- package/src/usage/claude.ts +37 -59
- package/src/usage/kimi.ts +32 -1
- package/src/usage.ts +52 -5
- package/src/utils/schema/json-schema-validator.ts +23 -10
- package/src/utils/tool-call-loop-guard.ts +2 -2
- package/src/utils/validation.ts +145 -50
|
@@ -88,7 +88,7 @@ type SerializedCredentialRecord = {
|
|
|
88
88
|
identityKey: string | null;
|
|
89
89
|
};
|
|
90
90
|
|
|
91
|
-
const AUTH_SCHEMA_VERSION =
|
|
91
|
+
const AUTH_SCHEMA_VERSION = 8;
|
|
92
92
|
const SQLITE_NOW_EPOCH = "CAST(strftime('%s','now') AS INTEGER)";
|
|
93
93
|
const LEGACY_CODEX_BLOCK_PROVIDER_KEY = "openai-codex:oauth";
|
|
94
94
|
const LEGACY_CODEX_BLOCK_SCOPE = "shared";
|
|
@@ -970,6 +970,9 @@ export class SqliteAuthCredentialStore implements AuthCredentialStore {
|
|
|
970
970
|
if (fromVersion < 7) {
|
|
971
971
|
this.#migrateAuthSchemaV6ToV7();
|
|
972
972
|
}
|
|
973
|
+
if (fromVersion < 8) {
|
|
974
|
+
this.#migrateAuthSchemaV7ToV8();
|
|
975
|
+
}
|
|
973
976
|
}
|
|
974
977
|
|
|
975
978
|
#migrateAuthSchemaV0ToV1(): void {
|
|
@@ -1141,6 +1144,46 @@ export class SqliteAuthCredentialStore implements AuthCredentialStore {
|
|
|
1141
1144
|
migrate.immediate();
|
|
1142
1145
|
}
|
|
1143
1146
|
|
|
1147
|
+
#migrateAuthSchemaV7ToV8(): void {
|
|
1148
|
+
const migrate = this.#db.transaction(() => {
|
|
1149
|
+
// SingularityAPI split into two providers — the pay-as-you-go universal
|
|
1150
|
+
// gateway and the slot-reserved lanes — and keys stored under the
|
|
1151
|
+
// retired shared id belong to one or the other by format: the gateway
|
|
1152
|
+
// issues `sk-sapi-...` while the lanes issue plain `sk-...` (both
|
|
1153
|
+
// observed live 2026-09-22), and neither key is accepted by the other
|
|
1154
|
+
// host. Route each stored credential to the product that serves it
|
|
1155
|
+
// instead of orphaning it under an id nothing reads anymore.
|
|
1156
|
+
const select = this.#db.prepare(
|
|
1157
|
+
"SELECT id, credential_type, data FROM auth_credentials WHERE provider = 'singularityapi'",
|
|
1158
|
+
);
|
|
1159
|
+
let rows: Array<{ id: number; credential_type: string; data: string }>;
|
|
1160
|
+
try {
|
|
1161
|
+
rows = select.all() as Array<{ id: number; credential_type: string; data: string }>;
|
|
1162
|
+
} finally {
|
|
1163
|
+
select.finalize();
|
|
1164
|
+
}
|
|
1165
|
+
for (const row of rows) {
|
|
1166
|
+
let provider = "singularityapi-tech";
|
|
1167
|
+
try {
|
|
1168
|
+
const parsed = JSON.parse(row.data) as { key?: unknown };
|
|
1169
|
+
if (typeof parsed.key === "string" && parsed.key.startsWith("sk-sapi-")) {
|
|
1170
|
+
provider = "singularityapi-dev";
|
|
1171
|
+
}
|
|
1172
|
+
} catch {
|
|
1173
|
+
// Unparsable payload takes the lane default; whichever product the
|
|
1174
|
+
// key really belongs to then answers 401 and the owner re-logs in.
|
|
1175
|
+
}
|
|
1176
|
+
this.#db.run("UPDATE auth_credentials SET provider = ? WHERE id = ?", [provider, row.id]);
|
|
1177
|
+
this.#db.run(
|
|
1178
|
+
"UPDATE auth_credential_blocks SET provider_key = ? WHERE credential_id = ? AND provider_key = ?",
|
|
1179
|
+
[`${provider}:${row.credential_type}`, row.id, `singularityapi:${row.credential_type}`],
|
|
1180
|
+
);
|
|
1181
|
+
}
|
|
1182
|
+
this.#writeAuthSchemaVersion(8);
|
|
1183
|
+
});
|
|
1184
|
+
migrate.immediate();
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1144
1187
|
#backfillCredentialIdentityKeys(): void {
|
|
1145
1188
|
const selectRowsStmt = this.#db.prepare(
|
|
1146
1189
|
"SELECT id, provider, credential_type, data, disabled_cause, identity_key FROM auth_credentials WHERE identity_key IS NULL ORDER BY id ASC",
|
|
@@ -175,8 +175,8 @@ function usageOverlayKey(
|
|
|
175
175
|
const accountId = ids.accountId?.trim().toLowerCase();
|
|
176
176
|
const email = ids.email?.trim().toLowerCase();
|
|
177
177
|
const projectId = ids.projectId?.trim().toLowerCase();
|
|
178
|
-
if (
|
|
179
|
-
else if (
|
|
178
|
+
if (email) base = `email:${email}`;
|
|
179
|
+
else if (accountId) base = `account:${accountId}`;
|
|
180
180
|
else if (projectId) base = `project:${projectId}`;
|
|
181
181
|
const orgId = ids.orgId?.trim().toLowerCase();
|
|
182
182
|
if (orgId) return base ? `${provider}\0org:${orgId}|${base}` : `${provider}\0org:${orgId}`;
|
|
@@ -1556,6 +1556,10 @@ function reportMatchesIdentity(
|
|
|
1556
1556
|
projectId: string | undefined,
|
|
1557
1557
|
): boolean {
|
|
1558
1558
|
const metadata = (report.metadata ?? {}) as Record<string, unknown>;
|
|
1559
|
+
const metaEmail = readMetadataString(metadata, "email")?.toLowerCase();
|
|
1560
|
+
// Email identifies the member within shared Team workspace account/org ids.
|
|
1561
|
+
// When both sides provide it, a mismatch is decisive.
|
|
1562
|
+
if (email && metaEmail) return metaEmail === email;
|
|
1559
1563
|
if (accountId) {
|
|
1560
1564
|
const metaAccount = readMetadataString(metadata, "accountId") ?? readMetadataString(metadata, "account_id");
|
|
1561
1565
|
if (metaAccount && metaAccount.toLowerCase() === accountId) return true;
|
|
@@ -1563,10 +1567,6 @@ function reportMatchesIdentity(
|
|
|
1563
1567
|
if (limit.scope.accountId?.toLowerCase() === accountId) return true;
|
|
1564
1568
|
}
|
|
1565
1569
|
}
|
|
1566
|
-
if (email) {
|
|
1567
|
-
const metaEmail = readMetadataString(metadata, "email");
|
|
1568
|
-
if (metaEmail && metaEmail.toLowerCase() === email) return true;
|
|
1569
|
-
}
|
|
1570
1570
|
if (projectId) {
|
|
1571
1571
|
const metaProject = readMetadataString(metadata, "projectId") ?? readMetadataString(metadata, "project_id");
|
|
1572
1572
|
if (metaProject && metaProject.toLowerCase() === projectId) return true;
|
|
@@ -235,7 +235,21 @@ const usageLimitSchema = type({
|
|
|
235
235
|
|
|
236
236
|
const usageResetCreditsSchema = type({
|
|
237
237
|
availableCount: "number",
|
|
238
|
+
"redeemableCount?": "number",
|
|
239
|
+
"nextCreditId?": "string",
|
|
240
|
+
"eligible?": "boolean",
|
|
241
|
+
"reason?": "string",
|
|
242
|
+
"cooldownUntil?": "string",
|
|
238
243
|
"credits?": type({
|
|
244
|
+
"id?": "string",
|
|
245
|
+
"title?": "string",
|
|
246
|
+
"program?": "string",
|
|
247
|
+
"remainingCount?": "number",
|
|
248
|
+
"usable?": "boolean",
|
|
249
|
+
"requiresLimit?": "boolean",
|
|
250
|
+
"clears?": "string[]",
|
|
251
|
+
"blocking?": "string[]",
|
|
252
|
+
"usedFractions?": { "[string]": "number" },
|
|
239
253
|
"grantedAt?": "string",
|
|
240
254
|
"expiresAt?": "string",
|
|
241
255
|
"status?": "string",
|
|
@@ -161,6 +161,10 @@ function buildStreamOptions(parsed: ParsedFormatRequest, api: Api, signal: Abort
|
|
|
161
161
|
}
|
|
162
162
|
if (options.reasoning !== undefined) opts.reasoning = options.reasoning;
|
|
163
163
|
if (options.disableReasoning !== undefined) opts.disableReasoning = options.disableReasoning;
|
|
164
|
+
if (options.forceReasoningOff !== undefined) {
|
|
165
|
+
opts.disableReasoning = options.forceReasoningOff;
|
|
166
|
+
opts.forceReasoningOff = options.forceReasoningOff;
|
|
167
|
+
}
|
|
164
168
|
if (options.hideThinkingSummary !== undefined) opts.hideThinkingSummary = options.hideThinkingSummary;
|
|
165
169
|
if (options.taskBudget !== undefined) opts.taskBudget = options.taskBudget;
|
|
166
170
|
if (options.anthropicPrefixMismatchBehavior !== undefined) {
|
|
@@ -59,6 +59,11 @@ export interface AuthGatewayParsedRequestOptions {
|
|
|
59
59
|
reasoning?: Effort;
|
|
60
60
|
/** Force-disable reasoning (Anthropic `thinking: { type: "disabled" }`). */
|
|
61
61
|
disableReasoning?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Preserve an explicit wire-level reasoning-off request through providers
|
|
64
|
+
* that distinguish it from the generic disable hint.
|
|
65
|
+
*/
|
|
66
|
+
forceReasoningOff?: boolean;
|
|
62
67
|
/**
|
|
63
68
|
* Explicit Anthropic `thinking.budget_tokens`. Mirrors Rust's
|
|
64
69
|
* `resolve_thinking_budget`: pins onto whichever effort the client
|