@oh-my-pi/pi-ai 16.3.5 → 16.3.6
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 +11 -0
- package/dist/types/auth-broker/client.d.ts +3 -1
- package/dist/types/auth-broker/remote-store.d.ts +6 -1
- package/dist/types/auth-broker/types.d.ts +13 -1
- package/dist/types/auth-broker/wire-schemas.d.ts +46 -0
- package/dist/types/auth-storage.d.ts +38 -0
- package/dist/types/types.d.ts +16 -0
- package/dist/types/utils/schema/normalize.d.ts +5 -0
- package/package.json +4 -4
- package/src/auth-broker/client.ts +41 -12
- package/src/auth-broker/remote-store.ts +189 -9
- package/src/auth-broker/server.ts +109 -7
- package/src/auth-broker/types.ts +22 -1
- package/src/auth-broker/wire-schemas.ts +22 -0
- package/src/auth-storage.ts +292 -22
- package/src/providers/ollama.ts +2 -2
- package/src/types.ts +18 -0
- package/src/usage/claude.ts +28 -8
- package/src/utils/schema/normalize.ts +131 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [16.3.6] - 2026-07-04
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Persisted credential rate-limit blocks across processes: `auth_credential_blocks` (auth schema v5) stores per-credential blocks keyed by row id + provider key + block scope with MAX-upsert semantics, `AuthStorage` merges persisted and in-memory blocks on read, and auth-broker snapshots/SSE carry per-entry blocks with `POST /v1/credential/:id/block` and `DELETE /v1/credential/:id/blocks` endpoints so gateway and sibling omp processes stop re-discovering exhausted accounts by burning a 429 each.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Fixed Anthropic credential selection sampling Fable/Mythos-exhausted accounts on every new session: a Fable/Mythos weekly cap now proactively hard-blocks the credential when confirmed exhausted (server `exhausted` status or used fraction >= 1) with a live `resetsAt`, and a live Fable 429 extends the reactive block to the confirmed tier reset instead of the 60s default. Unconfirmed rows (missing/expired reset, below cap) remain ranking hints only, preserving the false-100% guard.
|
|
14
|
+
- Fixed Ollama/Ollama Cloud tool requests failing with HTTP 400 by rewriting boolean subschemas (`true`/`false`) into a value-widening `anyOf` union of primitive types, stripping boolean `additionalProperties`/`unevaluatedProperties`, and flattening nullable `type` arrays before serializing tool parameters, so unconstrained fields still advertise "any JSON value" to grammar-constrained samplers (llama.cpp) instead of collapsing to an empty object. ([#4488](https://github.com/can1357/oh-my-pi/issues/4488))
|
|
15
|
+
|
|
5
16
|
## [16.3.5] - 2026-07-04
|
|
6
17
|
|
|
7
18
|
### Added
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AuthCredential } from "../auth-storage";
|
|
2
|
-
import type { CredentialDisableResponse, CredentialRefreshResponse, CredentialUploadResponse, HealthzResponse, SnapshotResponse, SnapshotStreamEvent, UsageResponse } from "./types";
|
|
2
|
+
import type { CredentialBlockRequest, CredentialBlockResponse, CredentialBlocksDeleteResponse, CredentialDisableResponse, CredentialRefreshResponse, CredentialUploadResponse, HealthzResponse, SnapshotResponse, SnapshotStreamEvent, UsageResponse } from "./types";
|
|
3
3
|
export interface AuthBrokerClientOptions {
|
|
4
4
|
/** Base URL (e.g. `https://broker.tailnet:8765`). Trailing slashes are trimmed. */
|
|
5
5
|
url: string;
|
|
@@ -63,4 +63,6 @@ export declare class AuthBrokerClient {
|
|
|
63
63
|
refreshCredential(id: number, signal?: AbortSignal): Promise<CredentialRefreshResponse>;
|
|
64
64
|
disableCredential(id: number, cause: string, signal?: AbortSignal): Promise<CredentialDisableResponse>;
|
|
65
65
|
uploadCredential(provider: string, credential: AuthCredential, signal?: AbortSignal): Promise<CredentialUploadResponse>;
|
|
66
|
+
upsertCredentialBlock(id: number, block: CredentialBlockRequest, signal?: AbortSignal): Promise<CredentialBlockResponse>;
|
|
67
|
+
deleteCredentialBlocks(id: number, signal?: AbortSignal): Promise<CredentialBlocksDeleteResponse>;
|
|
66
68
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AuthCredential, type AuthCredentialStore, type OAuthCredential, type StoredAuthCredential } from "../auth-storage";
|
|
1
|
+
import { type AuthCredential, type AuthCredentialStore, type OAuthCredential, type StoredAuthCredential, type StoredCredentialBlock } from "../auth-storage";
|
|
2
2
|
import type { OAuthCredentials } from "../registry/oauth/types";
|
|
3
3
|
import type { Provider } from "../types";
|
|
4
4
|
import type { UsageReport } from "../usage";
|
|
@@ -30,6 +30,11 @@ export declare class RemoteAuthCredentialStore implements AuthCredentialStore {
|
|
|
30
30
|
/** Re-hydrate the in-memory snapshot from the broker. */
|
|
31
31
|
refreshSnapshot(): Promise<SnapshotResponse>;
|
|
32
32
|
listAuthCredentials(provider?: string): StoredAuthCredential[];
|
|
33
|
+
getCredentialBlock(credentialId: number, providerKey: string, blockScope: string): number | undefined;
|
|
34
|
+
listCredentialBlocks(credentialIds: readonly number[]): StoredCredentialBlock[];
|
|
35
|
+
upsertCredentialBlock(block: StoredCredentialBlock): void;
|
|
36
|
+
deleteCredentialBlocks(credentialId: number): void;
|
|
37
|
+
cleanExpiredCredentialBlocks(nowMs: number): void;
|
|
33
38
|
/**
|
|
34
39
|
* In-memory update from a successful refresh through the broker. AuthStorage
|
|
35
40
|
* calls this after `#replaceCredentialAt`; the broker already persisted the
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* clients use `access` tokens directly and call back to the broker when a
|
|
6
6
|
* credential expires or a 401 surfaces on a supposedly-fresh credential.
|
|
7
7
|
*/
|
|
8
|
-
import type { AuthCredential, AuthCredentialSnapshot, AuthCredentialSnapshotEntry } from "../auth-storage";
|
|
8
|
+
import type { AuthCredential, AuthCredentialSnapshot, AuthCredentialSnapshotEntry, StoredCredentialBlock } from "../auth-storage";
|
|
9
9
|
import type { UsageReport } from "../usage";
|
|
10
10
|
/** GET /v1/healthz response body. */
|
|
11
11
|
export interface HealthzResponse {
|
|
@@ -18,8 +18,10 @@ export interface RefresherSchedule {
|
|
|
18
18
|
skewMs: number;
|
|
19
19
|
nextSweepInMs: number;
|
|
20
20
|
}
|
|
21
|
+
export type CredentialBlockSnapshot = Omit<StoredCredentialBlock, "credentialId">;
|
|
21
22
|
export type SnapshotEntry = AuthCredentialSnapshotEntry & {
|
|
22
23
|
rotatesInMs: number | null;
|
|
24
|
+
blocks?: CredentialBlockSnapshot[];
|
|
23
25
|
};
|
|
24
26
|
/** GET /v1/snapshot response body. */
|
|
25
27
|
export interface SnapshotResponse extends Omit<AuthCredentialSnapshot, "credentials"> {
|
|
@@ -44,6 +46,16 @@ export interface CredentialDisableRequest {
|
|
|
44
46
|
export interface CredentialDisableResponse {
|
|
45
47
|
ok: boolean;
|
|
46
48
|
}
|
|
49
|
+
/** POST /v1/credential/:id/block request body. */
|
|
50
|
+
export type CredentialBlockRequest = CredentialBlockSnapshot;
|
|
51
|
+
/** POST /v1/credential/:id/block response body. */
|
|
52
|
+
export interface CredentialBlockResponse {
|
|
53
|
+
ok: boolean;
|
|
54
|
+
}
|
|
55
|
+
/** DELETE /v1/credential/:id/blocks response body. */
|
|
56
|
+
export interface CredentialBlocksDeleteResponse {
|
|
57
|
+
ok: boolean;
|
|
58
|
+
}
|
|
47
59
|
/**
|
|
48
60
|
* POST /v1/credential request body. The OAuth `refresh` must be the *real*
|
|
49
61
|
* refresh token (not the sentinel) — the broker is the canonical writer.
|
|
@@ -75,6 +75,11 @@ export declare const credentialSnapshotEntrySchema: import("arktype/internal/var
|
|
|
75
75
|
};
|
|
76
76
|
identityKey: string | null;
|
|
77
77
|
}, {}>;
|
|
78
|
+
export declare const credentialBlockSnapshotSchema: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
79
|
+
providerKey: string;
|
|
80
|
+
blockScope: string;
|
|
81
|
+
blockedUntilMs: number;
|
|
82
|
+
}, {}>;
|
|
78
83
|
export declare const snapshotEntrySchema: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
79
84
|
id: number;
|
|
80
85
|
provider: string;
|
|
@@ -94,6 +99,11 @@ export declare const snapshotEntrySchema: import("arktype/internal/variants/obje
|
|
|
94
99
|
};
|
|
95
100
|
identityKey: string | null;
|
|
96
101
|
rotatesInMs: number | null;
|
|
102
|
+
blocks?: {
|
|
103
|
+
providerKey: string;
|
|
104
|
+
blockScope: string;
|
|
105
|
+
blockedUntilMs: number;
|
|
106
|
+
}[] | undefined;
|
|
97
107
|
}, {}>;
|
|
98
108
|
export declare const refresherScheduleSchema: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
99
109
|
enabled: boolean;
|
|
@@ -130,6 +140,11 @@ export declare const snapshotResponseSchema: import("arktype/internal/variants/o
|
|
|
130
140
|
};
|
|
131
141
|
identityKey: string | null;
|
|
132
142
|
rotatesInMs: number | null;
|
|
143
|
+
blocks?: {
|
|
144
|
+
providerKey: string;
|
|
145
|
+
blockScope: string;
|
|
146
|
+
blockedUntilMs: number;
|
|
147
|
+
}[] | undefined;
|
|
133
148
|
}[];
|
|
134
149
|
}, {}>;
|
|
135
150
|
/** First frame on connect — full snapshot embedded inline with a `kind` tag. */
|
|
@@ -162,6 +177,11 @@ export declare const snapshotStreamSnapshotEventSchema: import("arktype/internal
|
|
|
162
177
|
};
|
|
163
178
|
identityKey: string | null;
|
|
164
179
|
rotatesInMs: number | null;
|
|
180
|
+
blocks?: {
|
|
181
|
+
providerKey: string;
|
|
182
|
+
blockScope: string;
|
|
183
|
+
blockedUntilMs: number;
|
|
184
|
+
}[] | undefined;
|
|
165
185
|
}[];
|
|
166
186
|
kind: "snapshot";
|
|
167
187
|
}, {}>;
|
|
@@ -195,6 +215,11 @@ export declare const snapshotStreamEntryEventSchema: import("arktype/internal/va
|
|
|
195
215
|
};
|
|
196
216
|
identityKey: string | null;
|
|
197
217
|
rotatesInMs: number | null;
|
|
218
|
+
blocks?: {
|
|
219
|
+
providerKey: string;
|
|
220
|
+
blockScope: string;
|
|
221
|
+
blockedUntilMs: number;
|
|
222
|
+
}[] | undefined;
|
|
198
223
|
};
|
|
199
224
|
}, {}>;
|
|
200
225
|
/** Per-credential delete delta. */
|
|
@@ -240,6 +265,11 @@ export declare const snapshotStreamEventSchema: import("arktype/internal/variant
|
|
|
240
265
|
};
|
|
241
266
|
identityKey: string | null;
|
|
242
267
|
rotatesInMs: number | null;
|
|
268
|
+
blocks?: {
|
|
269
|
+
providerKey: string;
|
|
270
|
+
blockScope: string;
|
|
271
|
+
blockedUntilMs: number;
|
|
272
|
+
}[] | undefined;
|
|
243
273
|
}[];
|
|
244
274
|
kind: "snapshot";
|
|
245
275
|
} | {
|
|
@@ -271,6 +301,11 @@ export declare const snapshotStreamEventSchema: import("arktype/internal/variant
|
|
|
271
301
|
};
|
|
272
302
|
identityKey: string | null;
|
|
273
303
|
rotatesInMs: number | null;
|
|
304
|
+
blocks?: {
|
|
305
|
+
providerKey: string;
|
|
306
|
+
blockScope: string;
|
|
307
|
+
blockedUntilMs: number;
|
|
308
|
+
}[] | undefined;
|
|
274
309
|
};
|
|
275
310
|
} | {
|
|
276
311
|
kind: "removed";
|
|
@@ -371,6 +406,17 @@ export declare const credentialDisableRequestSchema: import("arktype/internal/va
|
|
|
371
406
|
export declare const credentialDisableResponseSchema: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
372
407
|
ok: boolean;
|
|
373
408
|
}, {}>;
|
|
409
|
+
export declare const credentialBlockRequestSchema: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
410
|
+
providerKey: string;
|
|
411
|
+
blockScope: string;
|
|
412
|
+
blockedUntilMs: number;
|
|
413
|
+
}, {}>;
|
|
414
|
+
export declare const credentialBlockResponseSchema: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
415
|
+
ok: boolean;
|
|
416
|
+
}, {}>;
|
|
417
|
+
export declare const credentialBlocksDeleteResponseSchema: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
418
|
+
ok: boolean;
|
|
419
|
+
}, {}>;
|
|
374
420
|
export declare const credentialUploadRequestSchema: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
375
421
|
provider: string;
|
|
376
422
|
credential: {
|
|
@@ -61,6 +61,17 @@ export interface StoredAuthCredential {
|
|
|
61
61
|
credential: AuthCredential;
|
|
62
62
|
disabledCause: string | null;
|
|
63
63
|
}
|
|
64
|
+
/** One persisted rate-limit block: credential row id + provider-type key + optional scope. */
|
|
65
|
+
export interface StoredCredentialBlock {
|
|
66
|
+
/** SQLite row id of the credential (auth_credentials.id). */
|
|
67
|
+
credentialId: number;
|
|
68
|
+
/** `${provider}:${credentialType}` — same value as AuthStorage's in-memory providerKey. */
|
|
69
|
+
providerKey: string;
|
|
70
|
+
/** Block scope (e.g. "tier:fable"); empty string = unscoped. Never NUL-delimited. */
|
|
71
|
+
blockScope: string;
|
|
72
|
+
/** Epoch milliseconds. */
|
|
73
|
+
blockedUntilMs: number;
|
|
74
|
+
}
|
|
64
75
|
/**
|
|
65
76
|
* Per-credential health record returned by {@link AuthStorage.checkCredentials}.
|
|
66
77
|
*
|
|
@@ -227,6 +238,16 @@ export interface AuthCredentialStore {
|
|
|
227
238
|
}): string | null;
|
|
228
239
|
setCache(key: string, value: string, expiresAtSec: number): void;
|
|
229
240
|
cleanExpiredCache(): void;
|
|
241
|
+
/** Non-expired block for one (credential, providerKey, scope) key, or undefined. */
|
|
242
|
+
getCredentialBlock?(credentialId: number, providerKey: string, blockScope: string): number | undefined;
|
|
243
|
+
/** Upsert with MAX semantics: keep the later blockedUntilMs on conflict. */
|
|
244
|
+
upsertCredentialBlock?(block: StoredCredentialBlock): void;
|
|
245
|
+
/** Drop every block row for a credential (all providerKeys/scopes). */
|
|
246
|
+
deleteCredentialBlocks?(credentialId: number): void;
|
|
247
|
+
/** Prune rows with blocked_until_ms <= nowMs. */
|
|
248
|
+
cleanExpiredCredentialBlocks?(nowMs: number): void;
|
|
249
|
+
/** List non-expired blocks for broker snapshots. */
|
|
250
|
+
listCredentialBlocks?(credentialIds: readonly number[]): StoredCredentialBlock[];
|
|
230
251
|
/**
|
|
231
252
|
* Append usage-limit snapshots for trend history. Optional: stores without
|
|
232
253
|
* durable storage (e.g. the broker remote store) omit it and recording is
|
|
@@ -946,6 +967,18 @@ export declare class AuthStorage {
|
|
|
946
967
|
* the existing row instead of inserting a duplicate.
|
|
947
968
|
*/
|
|
948
969
|
upsertCredential(provider: string, credential: AuthCredential): AuthCredentialSnapshotEntry[];
|
|
970
|
+
/**
|
|
971
|
+
* Broker-server seam: list non-expired persisted blocks for snapshot entries.
|
|
972
|
+
*/
|
|
973
|
+
listCredentialBlocks(credentialIds: readonly number[]): StoredCredentialBlock[];
|
|
974
|
+
/**
|
|
975
|
+
* Broker-server seam: persist one credential block and notify snapshot waiters.
|
|
976
|
+
*/
|
|
977
|
+
upsertCredentialBlock(block: StoredCredentialBlock): void;
|
|
978
|
+
/**
|
|
979
|
+
* Broker-server seam: clear all persisted blocks for one credential and notify snapshot waiters.
|
|
980
|
+
*/
|
|
981
|
+
deleteCredentialBlocks(credentialId: number): void;
|
|
949
982
|
/**
|
|
950
983
|
* Describe where the active credential for a provider came from.
|
|
951
984
|
*
|
|
@@ -997,6 +1030,11 @@ export declare class SqliteAuthCredentialStore implements AuthCredentialStore {
|
|
|
997
1030
|
}): string | null;
|
|
998
1031
|
setCache(key: string, value: string, expiresAtSec: number): void;
|
|
999
1032
|
cleanExpiredCache(): void;
|
|
1033
|
+
getCredentialBlock(credentialId: number, providerKey: string, blockScope: string): number | undefined;
|
|
1034
|
+
upsertCredentialBlock(block: StoredCredentialBlock): void;
|
|
1035
|
+
deleteCredentialBlocks(credentialId: number): void;
|
|
1036
|
+
cleanExpiredCredentialBlocks(nowMs: number): void;
|
|
1037
|
+
listCredentialBlocks(credentialIds: readonly number[]): StoredCredentialBlock[];
|
|
1000
1038
|
recordUsageSnapshots(entries: UsageHistoryEntry[]): void;
|
|
1001
1039
|
listUsageHistory(query?: UsageHistoryQuery): UsageHistoryEntry[];
|
|
1002
1040
|
recordUsageCosts(entries: UsageCostHistoryEntry[]): void;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -493,6 +493,21 @@ export interface DeveloperMessage {
|
|
|
493
493
|
providerPayload?: ProviderPayload;
|
|
494
494
|
timestamp: number;
|
|
495
495
|
}
|
|
496
|
+
export type AssistantRetryRecoveryKind = "credential" | "model" | "wait" | "plain";
|
|
497
|
+
export interface AssistantRetryRecovery {
|
|
498
|
+
kind: "auto-retry";
|
|
499
|
+
status: "recovered";
|
|
500
|
+
attempt: number;
|
|
501
|
+
recoveredAt: string;
|
|
502
|
+
recovery: AssistantRetryRecoveryKind;
|
|
503
|
+
note: string;
|
|
504
|
+
supersededBy?: {
|
|
505
|
+
timestamp: number;
|
|
506
|
+
responseId?: string;
|
|
507
|
+
provider: string;
|
|
508
|
+
model: string;
|
|
509
|
+
};
|
|
510
|
+
}
|
|
496
511
|
export interface ContextSnapshot {
|
|
497
512
|
promptTokens: number;
|
|
498
513
|
nonMessageTokens: number;
|
|
@@ -505,6 +520,7 @@ export interface AssistantMessage {
|
|
|
505
520
|
provider: Provider;
|
|
506
521
|
model: string;
|
|
507
522
|
contextSnapshot?: ContextSnapshot;
|
|
523
|
+
retryRecovery?: AssistantRetryRecovery;
|
|
508
524
|
responseId?: string;
|
|
509
525
|
/**
|
|
510
526
|
* Name of the upstream provider an aggregator routed this request to, as
|
|
@@ -66,6 +66,11 @@ export declare function normalizeSchemaForMCP(value: unknown): unknown;
|
|
|
66
66
|
* and the depth-10 limit.
|
|
67
67
|
*/
|
|
68
68
|
export declare function normalizeSchemaForMoonshot(value: unknown): unknown;
|
|
69
|
+
/**
|
|
70
|
+
* Rewrites standard JSON Schema forms that Ollama's Go `/api/chat` tool parser
|
|
71
|
+
* cannot unmarshal into its object-shaped `Schema` struct.
|
|
72
|
+
*/
|
|
73
|
+
export declare function sanitizeSchemaForOllama(schema: JsonObject): JsonObject;
|
|
69
74
|
/**
|
|
70
75
|
* OpenAI Responses rejects `oneOf` in tool schemas even when strict mode is
|
|
71
76
|
* disabled, and rejects every schema node with `type: "object"` unless it has
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-ai",
|
|
4
|
-
"version": "16.3.
|
|
4
|
+
"version": "16.3.6",
|
|
5
5
|
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@bufbuild/protobuf": "^2.12.0",
|
|
41
|
-
"@oh-my-pi/pi-catalog": "16.3.
|
|
42
|
-
"@oh-my-pi/pi-utils": "16.3.
|
|
43
|
-
"@oh-my-pi/pi-wire": "16.3.
|
|
41
|
+
"@oh-my-pi/pi-catalog": "16.3.6",
|
|
42
|
+
"@oh-my-pi/pi-utils": "16.3.6",
|
|
43
|
+
"@oh-my-pi/pi-wire": "16.3.6",
|
|
44
44
|
"arktype": "^2.2.0",
|
|
45
45
|
"zod": "^4"
|
|
46
46
|
},
|
|
@@ -9,6 +9,9 @@ import { readSseEvents } from "@oh-my-pi/pi-utils";
|
|
|
9
9
|
import { type } from "arktype";
|
|
10
10
|
import type { AuthCredential } from "../auth-storage";
|
|
11
11
|
import type {
|
|
12
|
+
CredentialBlockRequest,
|
|
13
|
+
CredentialBlockResponse,
|
|
14
|
+
CredentialBlocksDeleteResponse,
|
|
12
15
|
CredentialDisableRequest,
|
|
13
16
|
CredentialDisableResponse,
|
|
14
17
|
CredentialRefreshResponse,
|
|
@@ -20,6 +23,8 @@ import type {
|
|
|
20
23
|
UsageResponse,
|
|
21
24
|
} from "./types";
|
|
22
25
|
import {
|
|
26
|
+
credentialBlockResponseSchema,
|
|
27
|
+
credentialBlocksDeleteResponseSchema,
|
|
23
28
|
credentialDisableResponseSchema,
|
|
24
29
|
credentialRefreshResponseSchema,
|
|
25
30
|
credentialUploadResponseSchema,
|
|
@@ -106,7 +111,11 @@ export class AuthBrokerClient {
|
|
|
106
111
|
}
|
|
107
112
|
|
|
108
113
|
healthz(signal?: AbortSignal): Promise<HealthzResponse> {
|
|
109
|
-
return this.#request("GET", "/v1/healthz", {
|
|
114
|
+
return this.#request<HealthzResponse>("GET", "/v1/healthz", {
|
|
115
|
+
schema: healthzResponseSchema,
|
|
116
|
+
auth: false,
|
|
117
|
+
signal,
|
|
118
|
+
});
|
|
110
119
|
}
|
|
111
120
|
|
|
112
121
|
async fetchSnapshot(opts: FetchSnapshotOptions = {}): Promise<FetchSnapshotResult> {
|
|
@@ -230,19 +239,19 @@ export class AuthBrokerClient {
|
|
|
230
239
|
// `metadata`) but leaves provider-specific extension fields permissive so
|
|
231
240
|
// the broker can ship new shapes ahead of the client. `raw` is accepted
|
|
232
241
|
// but normally stripped by the broker before send.
|
|
233
|
-
return this.#request("GET", "/v1/usage", { schema: usageResponseSchema, signal })
|
|
242
|
+
return this.#request<UsageResponse>("GET", "/v1/usage", { schema: usageResponseSchema, signal });
|
|
234
243
|
}
|
|
235
244
|
|
|
236
245
|
async refreshCredential(id: number, signal?: AbortSignal): Promise<CredentialRefreshResponse> {
|
|
237
|
-
return this.#request("POST", `/v1/credential/${id}/refresh`, {
|
|
246
|
+
return this.#request<CredentialRefreshResponse>("POST", `/v1/credential/${id}/refresh`, {
|
|
238
247
|
schema: credentialRefreshResponseSchema,
|
|
239
248
|
signal,
|
|
240
|
-
})
|
|
249
|
+
});
|
|
241
250
|
}
|
|
242
251
|
|
|
243
252
|
async disableCredential(id: number, cause: string, signal?: AbortSignal): Promise<CredentialDisableResponse> {
|
|
244
253
|
const body: CredentialDisableRequest = { cause };
|
|
245
|
-
return this.#request("POST", `/v1/credential/${id}/disable`, {
|
|
254
|
+
return this.#request<CredentialDisableResponse>("POST", `/v1/credential/${id}/disable`, {
|
|
246
255
|
body,
|
|
247
256
|
schema: credentialDisableResponseSchema,
|
|
248
257
|
signal,
|
|
@@ -255,18 +264,38 @@ export class AuthBrokerClient {
|
|
|
255
264
|
signal?: AbortSignal,
|
|
256
265
|
): Promise<CredentialUploadResponse> {
|
|
257
266
|
const body: CredentialUploadRequest = { provider, credential };
|
|
258
|
-
return this.#request("POST", "/v1/credential", {
|
|
267
|
+
return this.#request<CredentialUploadResponse>("POST", "/v1/credential", {
|
|
259
268
|
body,
|
|
260
269
|
schema: credentialUploadResponseSchema,
|
|
261
270
|
signal,
|
|
262
|
-
})
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async upsertCredentialBlock(
|
|
275
|
+
id: number,
|
|
276
|
+
block: CredentialBlockRequest,
|
|
277
|
+
signal?: AbortSignal,
|
|
278
|
+
): Promise<CredentialBlockResponse> {
|
|
279
|
+
const body: CredentialBlockRequest = block;
|
|
280
|
+
return this.#request<CredentialBlockResponse>("POST", `/v1/credential/${id}/block`, {
|
|
281
|
+
body,
|
|
282
|
+
schema: credentialBlockResponseSchema,
|
|
283
|
+
signal,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
async deleteCredentialBlocks(id: number, signal?: AbortSignal): Promise<CredentialBlocksDeleteResponse> {
|
|
288
|
+
return this.#request<CredentialBlocksDeleteResponse>("DELETE", `/v1/credential/${id}/blocks`, {
|
|
289
|
+
schema: credentialBlocksDeleteResponseSchema,
|
|
290
|
+
signal,
|
|
291
|
+
});
|
|
263
292
|
}
|
|
264
293
|
|
|
265
|
-
async #request(
|
|
266
|
-
method: "GET" | "POST",
|
|
294
|
+
async #request<t>(
|
|
295
|
+
method: "GET" | "POST" | "DELETE",
|
|
267
296
|
path: string,
|
|
268
297
|
opts: { schema: (input: unknown) => unknown; auth?: boolean; body?: unknown; signal?: AbortSignal },
|
|
269
|
-
): Promise<
|
|
298
|
+
): Promise<t> {
|
|
270
299
|
const response = await this.#fetchRaw(method, path, opts);
|
|
271
300
|
const text = await response.text();
|
|
272
301
|
const raw = this.#parseJson(text, response.status);
|
|
@@ -277,7 +306,7 @@ export class AuthBrokerClient {
|
|
|
277
306
|
body: validated.summary,
|
|
278
307
|
});
|
|
279
308
|
}
|
|
280
|
-
return validated;
|
|
309
|
+
return validated as t;
|
|
281
310
|
}
|
|
282
311
|
|
|
283
312
|
#parseJson(text: string, status: number): unknown {
|
|
@@ -293,7 +322,7 @@ export class AuthBrokerClient {
|
|
|
293
322
|
}
|
|
294
323
|
|
|
295
324
|
async #fetchRaw(
|
|
296
|
-
method: "GET" | "POST",
|
|
325
|
+
method: "GET" | "POST" | "DELETE",
|
|
297
326
|
path: string,
|
|
298
327
|
opts: {
|
|
299
328
|
auth?: boolean;
|