@demicodes/provider 0.10.3 → 0.12.0
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/README.md +13 -1
- package/dist/credentials-pool.d.mts +60 -0
- package/dist/credentials-pool.mjs +206 -0
- package/dist/index.d.mts +14 -4
- package/dist/index.mjs +50 -10
- package/dist/testing.d.mts +2 -2
- package/dist/testing.mjs +6 -0
- package/dist/{types-jho3Wgsx.d.mts → types-Uczx0xBQ.d.mts} +143 -6
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -11,9 +11,21 @@ writing providers.
|
|
|
11
11
|
`withProviderId`.
|
|
12
12
|
- **HTTP helpers** — `redactSecretText`, `httpErrorCode`, `normalizeErrorCode`,
|
|
13
13
|
`providerErrorFromUnknown`, `authStatusFromKey`, `httpRequestFailedEvent`.
|
|
14
|
+
- **Quota** — optional `Provider.quota` (`ProviderQuota` / `ProviderQuotaSnapshot`),
|
|
15
|
+
`createProviderQuota`, `ensureQuota`. See
|
|
16
|
+
[docs/provider-quota.md](../../docs/provider-quota.md).
|
|
17
|
+
- **Credentials** — optional `Provider.credentials` for multi-account pool + global
|
|
18
|
+
`setActive` (subscription CLIs). See
|
|
19
|
+
[docs/provider-global-credentials.md](../../docs/provider-global-credentials.md).
|
|
14
20
|
|
|
15
21
|
```ts
|
|
16
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
defineProvider,
|
|
24
|
+
createProviderQuota,
|
|
25
|
+
ensureQuota,
|
|
26
|
+
type ProviderCredentials,
|
|
27
|
+
type ProviderQuota,
|
|
28
|
+
} from '@demicodes/provider'
|
|
17
29
|
```
|
|
18
30
|
|
|
19
31
|
See [Add a Provider](../../docs/guides/add-a-provider.md). Part of
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { d as ProviderCredentialInfo } from "./types-Uczx0xBQ.mjs";
|
|
2
|
+
//#region src/credentials-pool.d.ts
|
|
3
|
+
interface CredentialEntryMeta {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
detail?: string | null;
|
|
7
|
+
updatedAt: string;
|
|
8
|
+
source?: string | null;
|
|
9
|
+
/** Stable account key for upsert on re-import (email, accountId, entryKey, …). */
|
|
10
|
+
identityKey?: string | null;
|
|
11
|
+
}
|
|
12
|
+
interface FileCredentialPoolOptions {
|
|
13
|
+
/** Demi state root ($DEMI_HOME / ~/.demi). */
|
|
14
|
+
stateDir?: string;
|
|
15
|
+
/** Subdir under credentials/ (e.g. codex, grok-build, claude-code). */
|
|
16
|
+
providerKey: string;
|
|
17
|
+
/** Secret filename inside each entry (auth.json, oauth.json). */
|
|
18
|
+
secretFileName: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Demi local state root (`$DEMI_HOME` / `~/.demi`). Canonical copy — host-local
|
|
22
|
+
* re-exports this for its bridge layout.
|
|
23
|
+
*/
|
|
24
|
+
declare function resolveDemiHome(explicit?: string): string;
|
|
25
|
+
declare function credentialIdFromIdentity(identityKey: string | null | undefined, fallbackLabel: string): string;
|
|
26
|
+
declare function newCredentialId(): string;
|
|
27
|
+
declare class FileCredentialPool {
|
|
28
|
+
readonly root: string;
|
|
29
|
+
readonly secretFileName: string;
|
|
30
|
+
constructor(options: FileCredentialPoolOptions);
|
|
31
|
+
entriesDir(): string;
|
|
32
|
+
entryDir(id: string): string;
|
|
33
|
+
metaPath(id: string): string;
|
|
34
|
+
secretPath(id: string): string;
|
|
35
|
+
activePath(): string;
|
|
36
|
+
list(): Promise<ProviderCredentialInfo[]>;
|
|
37
|
+
listMeta(): Promise<CredentialEntryMeta[]>;
|
|
38
|
+
readMeta(id: string): Promise<CredentialEntryMeta | null>;
|
|
39
|
+
getActiveId(): Promise<string | null>;
|
|
40
|
+
setActiveId(id: string): Promise<void>;
|
|
41
|
+
clearActive(): Promise<void>;
|
|
42
|
+
writeEntry(meta: CredentialEntryMeta, secretText: string): Promise<CredentialEntryMeta>;
|
|
43
|
+
readSecretText(id: string): Promise<string>;
|
|
44
|
+
remove(id: string): Promise<void>;
|
|
45
|
+
private tmpPath;
|
|
46
|
+
/**
|
|
47
|
+
* Serializes pool mutations across processes with a create-exclusive lock
|
|
48
|
+
* file; stale locks (mtime older than 30s) are removed.
|
|
49
|
+
*/
|
|
50
|
+
private withWriteLock;
|
|
51
|
+
findByIdentityKey(identityKey: string): Promise<CredentialEntryMeta | null>;
|
|
52
|
+
/** If active missing but entries exist, pick first and repair active pointer. */
|
|
53
|
+
ensureActivePointer(): Promise<string | null>;
|
|
54
|
+
}
|
|
55
|
+
declare class CredentialPoolError extends Error {
|
|
56
|
+
readonly code: 'credential_not_found' | 'credential_invalid';
|
|
57
|
+
constructor(code: 'credential_not_found' | 'credential_invalid', message: string);
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
60
|
+
export { CredentialEntryMeta, CredentialPoolError, FileCredentialPool, FileCredentialPoolOptions, credentialIdFromIdentity, newCredentialId, resolveDemiHome };
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { errorCode, isRecord, nonEmptyString } from "@demicodes/utils";
|
|
2
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
3
|
+
import { chmod, mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { join, resolve } from "node:path";
|
|
6
|
+
//#region src/credentials-pool.ts
|
|
7
|
+
/**
|
|
8
|
+
* Demi multi-credential pool on disk:
|
|
9
|
+
* <stateDir>/credentials/<providerKey>/{active,entries/<id>/{meta.json,secret}}
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Demi local state root (`$DEMI_HOME` / `~/.demi`). Canonical copy — host-local
|
|
13
|
+
* re-exports this for its bridge layout.
|
|
14
|
+
*/
|
|
15
|
+
function resolveDemiHome(explicit) {
|
|
16
|
+
if (explicit && explicit.trim()) return resolve(explicit.trim());
|
|
17
|
+
const fromEnv = process.env.DEMI_HOME;
|
|
18
|
+
if (fromEnv && fromEnv.trim()) return resolve(fromEnv.trim());
|
|
19
|
+
return join(homedir(), ".demi");
|
|
20
|
+
}
|
|
21
|
+
function credentialIdFromIdentity(identityKey, fallbackLabel) {
|
|
22
|
+
const basis = nonEmptyString(identityKey) ?? fallbackLabel;
|
|
23
|
+
return `cred-${createHash("sha256").update(basis).digest("hex").slice(0, 16)}`;
|
|
24
|
+
}
|
|
25
|
+
function newCredentialId() {
|
|
26
|
+
return `cred-${randomUUID().replace(/-/g, "").slice(0, 16)}`;
|
|
27
|
+
}
|
|
28
|
+
var FileCredentialPool = class {
|
|
29
|
+
root;
|
|
30
|
+
secretFileName;
|
|
31
|
+
constructor(options) {
|
|
32
|
+
const stateDir = resolveDemiHome(options.stateDir);
|
|
33
|
+
this.root = join(stateDir, "credentials", options.providerKey);
|
|
34
|
+
this.secretFileName = options.secretFileName;
|
|
35
|
+
}
|
|
36
|
+
entriesDir() {
|
|
37
|
+
return join(this.root, "entries");
|
|
38
|
+
}
|
|
39
|
+
entryDir(id) {
|
|
40
|
+
return join(this.entriesDir(), id);
|
|
41
|
+
}
|
|
42
|
+
metaPath(id) {
|
|
43
|
+
return join(this.entryDir(id), "meta.json");
|
|
44
|
+
}
|
|
45
|
+
secretPath(id) {
|
|
46
|
+
return join(this.entryDir(id), this.secretFileName);
|
|
47
|
+
}
|
|
48
|
+
activePath() {
|
|
49
|
+
return join(this.root, "active");
|
|
50
|
+
}
|
|
51
|
+
async list() {
|
|
52
|
+
return (await this.listMeta()).map((m) => ({
|
|
53
|
+
id: m.id,
|
|
54
|
+
label: m.label,
|
|
55
|
+
detail: m.detail ?? null,
|
|
56
|
+
updatedAt: m.updatedAt
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
async listMeta() {
|
|
60
|
+
let names;
|
|
61
|
+
try {
|
|
62
|
+
names = await readdir(this.entriesDir());
|
|
63
|
+
} catch {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
const out = [];
|
|
67
|
+
for (const name of names) {
|
|
68
|
+
const meta = await this.readMeta(name);
|
|
69
|
+
if (meta) out.push(meta);
|
|
70
|
+
}
|
|
71
|
+
out.sort((a, b) => a.id.localeCompare(b.id));
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
async readMeta(id) {
|
|
75
|
+
try {
|
|
76
|
+
const raw = JSON.parse(await readFile(this.metaPath(id), "utf8"));
|
|
77
|
+
if (!isRecord(raw)) return null;
|
|
78
|
+
const entryId = nonEmptyString(raw.id) ?? id;
|
|
79
|
+
const label = nonEmptyString(raw.label);
|
|
80
|
+
if (!label) return null;
|
|
81
|
+
return {
|
|
82
|
+
id: entryId,
|
|
83
|
+
label,
|
|
84
|
+
detail: nonEmptyString(raw.detail) ?? null,
|
|
85
|
+
updatedAt: nonEmptyString(raw.updatedAt) ?? (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
86
|
+
source: nonEmptyString(raw.source) ?? null,
|
|
87
|
+
identityKey: nonEmptyString(raw.identityKey) ?? null
|
|
88
|
+
};
|
|
89
|
+
} catch {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async getActiveId() {
|
|
94
|
+
try {
|
|
95
|
+
const id = (await readFile(this.activePath(), "utf8")).trim();
|
|
96
|
+
if (!id) return null;
|
|
97
|
+
return await this.readMeta(id) ? id : null;
|
|
98
|
+
} catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async setActiveId(id) {
|
|
103
|
+
if (!await this.readMeta(id)) throw new CredentialPoolError("credential_not_found", `Credential "${id}" not found`);
|
|
104
|
+
try {
|
|
105
|
+
await readFile(this.secretPath(id), "utf8");
|
|
106
|
+
} catch {
|
|
107
|
+
throw new CredentialPoolError("credential_not_found", `Credential "${id}" has no secret material`);
|
|
108
|
+
}
|
|
109
|
+
await this.withWriteLock(async () => {
|
|
110
|
+
const tmp = this.tmpPath(this.activePath());
|
|
111
|
+
await writeFile(tmp, `${id}\n`, { mode: 384 });
|
|
112
|
+
await rename(tmp, this.activePath());
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
async clearActive() {
|
|
116
|
+
await rm(this.activePath(), { force: true }).catch(() => void 0);
|
|
117
|
+
}
|
|
118
|
+
async writeEntry(meta, secretText) {
|
|
119
|
+
return this.withWriteLock(async () => {
|
|
120
|
+
const dir = this.entryDir(meta.id);
|
|
121
|
+
await mkdir(dir, {
|
|
122
|
+
recursive: true,
|
|
123
|
+
mode: 448
|
|
124
|
+
});
|
|
125
|
+
const secretTmp = this.tmpPath(this.secretPath(meta.id));
|
|
126
|
+
const metaTmp = this.tmpPath(this.metaPath(meta.id));
|
|
127
|
+
await writeFile(secretTmp, secretText, { mode: 384 });
|
|
128
|
+
await chmod(secretTmp, 384).catch(() => void 0);
|
|
129
|
+
await rename(secretTmp, this.secretPath(meta.id));
|
|
130
|
+
await writeFile(metaTmp, `${JSON.stringify(meta, null, 2)}\n`, { mode: 384 });
|
|
131
|
+
await rename(metaTmp, this.metaPath(meta.id));
|
|
132
|
+
return meta;
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
async readSecretText(id) {
|
|
136
|
+
return readFile(this.secretPath(id), "utf8");
|
|
137
|
+
}
|
|
138
|
+
async remove(id) {
|
|
139
|
+
await this.withWriteLock(async () => {
|
|
140
|
+
const active = await this.getActiveId();
|
|
141
|
+
await rm(this.entryDir(id), {
|
|
142
|
+
recursive: true,
|
|
143
|
+
force: true
|
|
144
|
+
});
|
|
145
|
+
if (active === id) await this.clearActive();
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
tmpPath(target) {
|
|
149
|
+
return `${target}.${process.pid}.${randomUUID().slice(0, 8)}.tmp`;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Serializes pool mutations across processes with a create-exclusive lock
|
|
153
|
+
* file; stale locks (mtime older than 30s) are removed.
|
|
154
|
+
*/
|
|
155
|
+
async withWriteLock(fn) {
|
|
156
|
+
await mkdir(this.root, {
|
|
157
|
+
recursive: true,
|
|
158
|
+
mode: 448
|
|
159
|
+
});
|
|
160
|
+
const lockPath = join(this.root, ".lock");
|
|
161
|
+
const started = Date.now();
|
|
162
|
+
while (true) try {
|
|
163
|
+
await writeFile(lockPath, `${process.pid}\n`, {
|
|
164
|
+
flag: "wx",
|
|
165
|
+
mode: 384
|
|
166
|
+
});
|
|
167
|
+
break;
|
|
168
|
+
} catch (error) {
|
|
169
|
+
if (errorCode(error) !== "EEXIST") throw error;
|
|
170
|
+
const info = await stat(lockPath).catch(() => null);
|
|
171
|
+
if (info && Date.now() - info.mtimeMs > 3e4) {
|
|
172
|
+
await rm(lockPath, { force: true }).catch(() => void 0);
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (Date.now() - started > 5e3) throw new CredentialPoolError("credential_invalid", `Timed out waiting for credential pool lock ${lockPath}`);
|
|
176
|
+
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
177
|
+
}
|
|
178
|
+
try {
|
|
179
|
+
return await fn();
|
|
180
|
+
} finally {
|
|
181
|
+
await rm(lockPath, { force: true }).catch(() => void 0);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
async findByIdentityKey(identityKey) {
|
|
185
|
+
return (await this.listMeta()).find((m) => m.identityKey === identityKey) ?? null;
|
|
186
|
+
}
|
|
187
|
+
/** If active missing but entries exist, pick first and repair active pointer. */
|
|
188
|
+
async ensureActivePointer() {
|
|
189
|
+
const active = await this.getActiveId();
|
|
190
|
+
if (active) return active;
|
|
191
|
+
const all = await this.listMeta();
|
|
192
|
+
if (all.length === 0) return null;
|
|
193
|
+
await this.setActiveId(all[0].id);
|
|
194
|
+
return all[0].id;
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
var CredentialPoolError = class extends Error {
|
|
198
|
+
code;
|
|
199
|
+
constructor(code, message) {
|
|
200
|
+
super(message);
|
|
201
|
+
this.code = code;
|
|
202
|
+
this.name = "CredentialPoolError";
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
//#endregion
|
|
206
|
+
export { CredentialPoolError, FileCredentialPool, credentialIdFromIdentity, newCredentialId, resolveDemiHome };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
import { FileExtension, ModelSelection, ThinkingCapability, ThinkingConfig } from "@demicodes/core";
|
|
3
|
-
|
|
1
|
+
import { A as ProviderQuota, B as ProviderQuotaUnsupportedError, C as ProviderRuntimeFactory, D as ToolDefinition, E as ProviderServiceTier, F as ProviderQuotaProbeOptions, G as ensureQuota, H as ProviderQuotaWindowUnit, I as ProviderQuotaProbeResult, J as usedPercentFromRatio, K as severityFromUsedPercent, L as ProviderQuotaSeverity, M as ProviderQuotaObserveInput, N as ProviderQuotaPlan, O as CreateProviderQuotaOptions, P as ProviderQuotaProbeCost, R as ProviderQuotaSnapshot, S as ProviderRun, T as ProviderSelection, U as clampUsedPercent, V as ProviderQuotaWindow, W as createProviderQuota, _ as ProviderEvent, a as ModelPolicy, b as ProviderModelCost, c as ProviderAuthState, d as ProviderCredentialInfo, f as ProviderCredentialLoginOptions, g as ProviderCredentialsCapability, h as ProviderCredentials, i as InferenceSteer, j as ProviderQuotaCapability, k as EnsureQuotaOptions, l as ProviderCredentialActive, m as ProviderCredentialLoginResult, n as InferenceItem, o as Provider, p as ProviderCredentialLoginPending, q as unixSecondsToIso, r as InferenceRequest, s as ProviderAuth, t as AgentProvider, u as ProviderCredentialAddInput, v as ProviderFactoryDefinition, w as ProviderRuntimeState, x as ProviderModelList, y as ProviderModel, z as ProviderQuotaSource } from "./types-Uczx0xBQ.mjs";
|
|
2
|
+
import { FileExtension, ModelSelection, ThinkingCapability, ThinkingConfig, ToolResultContentBlock } from "@demicodes/core";
|
|
3
|
+
//#region src/content.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Flattens a tool result to plain text for wire formats without native media
|
|
6
|
+
* blocks; non-text blocks become `[<type>:<mediaType>]` placeholders.
|
|
7
|
+
*/
|
|
8
|
+
declare function toolResultContentToText(output: ToolResultContentBlock[]): string;
|
|
9
|
+
//#endregion
|
|
4
10
|
//#region src/provider.d.ts
|
|
5
11
|
declare function defineProvider(definition: ProviderFactoryDefinition): Provider;
|
|
6
12
|
declare function providerRuntime(provider: Provider, selection: ProviderSelection): Promise<AgentProvider> | AgentProvider;
|
|
@@ -41,6 +47,8 @@ type HeadersResolver = () => Record<string, string> | Promise<Record<string, str
|
|
|
41
47
|
declare function clampPromptCacheKey(value: string): string;
|
|
42
48
|
/** Replaces every occurrence of `secret` in `value` with a redaction marker. */
|
|
43
49
|
declare function redactSecretText(value: string, secret: string | null | undefined): string;
|
|
50
|
+
/** Masks bearer tokens and named credential fields in free-form auth error text. */
|
|
51
|
+
declare function redactCredentialText(text: string, extraFieldPatterns?: readonly string[]): string;
|
|
44
52
|
/** Maps an HTTP status (and response text) to a coarse provider error code. */
|
|
45
53
|
declare function httpErrorCode(status: number, message: string): string | null;
|
|
46
54
|
/** Classifies a provider error code/message into a coarse category, falling back to `code`. */
|
|
@@ -51,7 +59,9 @@ declare function providerErrorFromUnknown(error: unknown, secret: string | null
|
|
|
51
59
|
declare function authStatusFromKey(resolveKey: SecretResolver, resolveHeaders: HeadersResolver | undefined, authHeader: string, providerLabel: string): Promise<ProviderAuthState>;
|
|
52
60
|
/** Parses a Retry-After header (delta-seconds or HTTP-date) into milliseconds. */
|
|
53
61
|
declare function retryAfterMsFromHeader(value: string | null): number | undefined;
|
|
62
|
+
/** Reads a header as a finite number, or null when absent/blank/non-numeric. */
|
|
63
|
+
declare function numberHeader(headers: Headers, name: string): number | null;
|
|
54
64
|
/** Builds a redacted provider `error` event from a failed HTTP response. */
|
|
55
65
|
declare function httpRequestFailedEvent(response: Response, secret: string | null | undefined, providerLabel: string): Promise<ProviderEvent>;
|
|
56
66
|
//#endregion
|
|
57
|
-
export { AgentProvider, type CreateProviderQuotaOptions, DEFAULT_ATTACHMENT_EXTENSIONS, type EnsureQuotaOptions, InferenceItem, InferenceRequest, InferenceSteer, ModelPolicy, type ModelSelectionFromCatalogOptions, Provider, ProviderAuth, ProviderAuthState, ProviderEvent, ProviderFactoryDefinition, ProviderModel, ProviderModelCost, ProviderModelList, type ProviderQuota, type ProviderQuotaCapability, type ProviderQuotaObserveInput, type ProviderQuotaPlan, type ProviderQuotaProbeCost, type ProviderQuotaProbeOptions, type ProviderQuotaProbeResult, type ProviderQuotaSeverity, type ProviderQuotaSnapshot, type ProviderQuotaSource, ProviderQuotaUnsupportedError, type ProviderQuotaWindow, type ProviderQuotaWindowUnit, ProviderRun, ProviderRuntimeFactory, ProviderRuntimeState, ProviderSelection, ProviderServiceTier, ToolDefinition, applyModelPolicy, authStatusFromKey, clampPromptCacheKey, clampUsedPercent, createProviderQuota, defineProvider, ensureQuota, httpErrorCode, httpRequestFailedEvent, modelSelectionFromCatalog, normalizeErrorCode, providerErrorFromUnknown, providerRuntime, redactSecretText, retryAfterMsFromHeader, severityFromUsedPercent, thinkingCapabilitiesFromProviderModel, unixSecondsToIso, usedPercentFromRatio, withProviderId };
|
|
67
|
+
export { AgentProvider, type CreateProviderQuotaOptions, DEFAULT_ATTACHMENT_EXTENSIONS, type EnsureQuotaOptions, InferenceItem, InferenceRequest, InferenceSteer, ModelPolicy, type ModelSelectionFromCatalogOptions, Provider, ProviderAuth, ProviderAuthState, ProviderCredentialActive, ProviderCredentialAddInput, ProviderCredentialInfo, ProviderCredentialLoginOptions, ProviderCredentialLoginPending, ProviderCredentialLoginResult, ProviderCredentials, ProviderCredentialsCapability, ProviderEvent, ProviderFactoryDefinition, ProviderModel, ProviderModelCost, ProviderModelList, type ProviderQuota, type ProviderQuotaCapability, type ProviderQuotaObserveInput, type ProviderQuotaPlan, type ProviderQuotaProbeCost, type ProviderQuotaProbeOptions, type ProviderQuotaProbeResult, type ProviderQuotaSeverity, type ProviderQuotaSnapshot, type ProviderQuotaSource, ProviderQuotaUnsupportedError, type ProviderQuotaWindow, type ProviderQuotaWindowUnit, ProviderRun, ProviderRuntimeFactory, ProviderRuntimeState, ProviderSelection, ProviderServiceTier, ToolDefinition, applyModelPolicy, authStatusFromKey, clampPromptCacheKey, clampUsedPercent, createProviderQuota, defineProvider, ensureQuota, httpErrorCode, httpRequestFailedEvent, modelSelectionFromCatalog, normalizeErrorCode, numberHeader, providerErrorFromUnknown, providerRuntime, redactCredentialText, redactSecretText, retryAfterMsFromHeader, severityFromUsedPercent, thinkingCapabilitiesFromProviderModel, toolResultContentToText, unixSecondsToIso, usedPercentFromRatio, withProviderId };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
|
+
import { VIDEO_FILE_EXTENSIONS } from "@demicodes/core";
|
|
1
2
|
import { shortHash } from "@demicodes/utils";
|
|
3
|
+
//#region src/content.ts
|
|
4
|
+
/**
|
|
5
|
+
* Flattens a tool result to plain text for wire formats without native media
|
|
6
|
+
* blocks; non-text blocks become `[<type>:<mediaType>]` placeholders.
|
|
7
|
+
*/
|
|
8
|
+
function toolResultContentToText(output) {
|
|
9
|
+
return output.map((block) => block.type === "text" ? block.text : `[${block.type}:${block.source.mediaType}]`).join("\n");
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
2
12
|
//#region src/provider.ts
|
|
3
13
|
const runtimeFactorySymbol = Symbol("demi.provider.runtimeFactory");
|
|
4
14
|
function defineProvider(definition) {
|
|
@@ -89,7 +99,7 @@ function modelSelectionFromCatalog(providerId, model, options = {}) {
|
|
|
89
99
|
contextWindow: model?.contextWindow ?? 0,
|
|
90
100
|
inputLimit: null,
|
|
91
101
|
thinking: thinkingCapabilitiesFromProviderModel(model),
|
|
92
|
-
acceptedExtensions: model?.supportsAttachments ? [
|
|
102
|
+
acceptedExtensions: [...model?.supportsAttachments ? accepted : [], ...model?.supportsVideo ? VIDEO_FILE_EXTENSIONS : []]
|
|
93
103
|
},
|
|
94
104
|
thinking: options.thinking ?? null,
|
|
95
105
|
serviceTierId: options.serviceTierId ?? null
|
|
@@ -108,10 +118,21 @@ function clampPromptCacheKey(value) {
|
|
|
108
118
|
function redactSecretText(value, secret) {
|
|
109
119
|
return secret ? value.split(secret).join("[redacted]") : value;
|
|
110
120
|
}
|
|
121
|
+
/** Masks bearer tokens and named credential fields in free-form auth error text. */
|
|
122
|
+
function redactCredentialText(text, extraFieldPatterns = []) {
|
|
123
|
+
const fields = [
|
|
124
|
+
"access_token",
|
|
125
|
+
"refresh_token",
|
|
126
|
+
"id_token",
|
|
127
|
+
...extraFieldPatterns
|
|
128
|
+
];
|
|
129
|
+
return text.replace(/Bearer\s+[A-Za-z0-9._~+/=-]+/g, "Bearer [REDACTED]").replace(new RegExp(`(${fields.join("|")})["'=:\\s]+[A-Za-z0-9._~+/=-]+`, "gi"), "$1=[REDACTED]");
|
|
130
|
+
}
|
|
111
131
|
/** Maps an HTTP status (and response text) to a coarse provider error code. */
|
|
112
132
|
function httpErrorCode(status, message) {
|
|
113
133
|
if (status === 401 || status === 403) return "auth_expired";
|
|
114
|
-
if (status ===
|
|
134
|
+
if (status === 429) return "rate_limit";
|
|
135
|
+
if (status === 408 || status === 409 || status === 425 || status >= 500) return "overloaded";
|
|
115
136
|
if (status === 400 && /context|too long|token/i.test(message)) return "context_length_exceeded";
|
|
116
137
|
return null;
|
|
117
138
|
}
|
|
@@ -119,9 +140,9 @@ function httpErrorCode(status, message) {
|
|
|
119
140
|
function normalizeErrorCode(code, message) {
|
|
120
141
|
const value = `${code ?? ""} ${message}`.toLowerCase();
|
|
121
142
|
if (/context|too long|max.*token/.test(value)) return "context_length_exceeded";
|
|
122
|
-
if (/rate|quota|billing|limit/.test(value)) return "rate_limit";
|
|
123
|
-
if (/auth|
|
|
124
|
-
if (/overload|unavailable|
|
|
143
|
+
if (/rate|quota|usage|billing|balance|limit/.test(value)) return "rate_limit";
|
|
144
|
+
if (/\bauth(?:entication|orization)?\b/.test(value) || /(?:invalid|expired).*(?:api|access|auth)[_\s-]*(?:key|token)/.test(value) || /(?:api|access|auth)[_\s-]*(?:key|token).*(?:invalid|expired)/.test(value)) return "auth_expired";
|
|
145
|
+
if (/overload|unavailable|(?:server|internal|api)[_\s-]*error|timed?\s?out|fetch failed|network|socket|econn/.test(value)) return "overloaded";
|
|
125
146
|
return code;
|
|
126
147
|
}
|
|
127
148
|
/** Builds a provider `error` event from an unknown thrown value, redacting `secret`. */
|
|
@@ -150,6 +171,13 @@ function retryAfterMsFromHeader(value) {
|
|
|
150
171
|
const dateMs = Date.parse(value);
|
|
151
172
|
if (Number.isFinite(dateMs)) return Math.max(0, dateMs - Date.now());
|
|
152
173
|
}
|
|
174
|
+
/** Reads a header as a finite number, or null when absent/blank/non-numeric. */
|
|
175
|
+
function numberHeader(headers, name) {
|
|
176
|
+
const raw = headers.get(name);
|
|
177
|
+
if (raw == null || raw === "") return null;
|
|
178
|
+
const n = Number(raw);
|
|
179
|
+
return Number.isFinite(n) ? n : null;
|
|
180
|
+
}
|
|
153
181
|
/** Builds a redacted provider `error` event from a failed HTTP response. */
|
|
154
182
|
async function httpRequestFailedEvent(response, secret, providerLabel) {
|
|
155
183
|
const text = await response.text().catch(() => "");
|
|
@@ -207,13 +235,14 @@ function createProviderQuota(options) {
|
|
|
207
235
|
};
|
|
208
236
|
};
|
|
209
237
|
const materialize = (partial, source) => {
|
|
238
|
+
const previous = source === "observation" ? latest : null;
|
|
210
239
|
const snapshot = {
|
|
211
240
|
providerId: options.providerId,
|
|
212
241
|
observedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
213
242
|
source,
|
|
214
|
-
plan: partial.plan ?? null,
|
|
215
|
-
accountLabel: partial.accountLabel ?? null,
|
|
216
|
-
windows: partial.windows,
|
|
243
|
+
plan: partial.plan === void 0 ? previous?.plan ?? null : partial.plan,
|
|
244
|
+
accountLabel: partial.accountLabel === void 0 ? previous?.accountLabel ?? null : partial.accountLabel,
|
|
245
|
+
windows: previous ? mergeQuotaWindows(previous.windows, partial.windows) : partial.windows,
|
|
217
246
|
raw: partial.raw
|
|
218
247
|
};
|
|
219
248
|
latest = snapshot;
|
|
@@ -222,9 +251,13 @@ function createProviderQuota(options) {
|
|
|
222
251
|
const quota = {
|
|
223
252
|
capability,
|
|
224
253
|
latest: () => latest,
|
|
254
|
+
clearLatest: () => {
|
|
255
|
+
latest = null;
|
|
256
|
+
},
|
|
225
257
|
async probe(probeOptions = {}) {
|
|
226
258
|
if (!options.canProbe) throw new ProviderQuotaUnsupportedError(options.providerId);
|
|
227
|
-
|
|
259
|
+
const partial = await options.probe(probeOptions);
|
|
260
|
+
return materialize(partial, "probe");
|
|
228
261
|
}
|
|
229
262
|
};
|
|
230
263
|
if (options.observe) {
|
|
@@ -237,6 +270,13 @@ function createProviderQuota(options) {
|
|
|
237
270
|
}
|
|
238
271
|
return quota;
|
|
239
272
|
}
|
|
273
|
+
function mergeQuotaWindows(previous, observed) {
|
|
274
|
+
const observedById = new Map(observed.map((window) => [window.id, window]));
|
|
275
|
+
const merged = previous.map((window) => observedById.get(window.id) ?? window);
|
|
276
|
+
const previousIds = new Set(previous.map((window) => window.id));
|
|
277
|
+
for (const window of observed) if (!previousIds.has(window.id)) merged.push(window);
|
|
278
|
+
return merged;
|
|
279
|
+
}
|
|
240
280
|
/** Clamp percent into 0–100 or null. */
|
|
241
281
|
function clampUsedPercent(value) {
|
|
242
282
|
if (typeof value !== "number" || !Number.isFinite(value)) return null;
|
|
@@ -269,4 +309,4 @@ function severityFromUsedPercent(usedPercent) {
|
|
|
269
309
|
return "normal";
|
|
270
310
|
}
|
|
271
311
|
//#endregion
|
|
272
|
-
export { DEFAULT_ATTACHMENT_EXTENSIONS, ProviderQuotaUnsupportedError, applyModelPolicy, authStatusFromKey, clampPromptCacheKey, clampUsedPercent, createProviderQuota, defineProvider, ensureQuota, httpErrorCode, httpRequestFailedEvent, modelSelectionFromCatalog, normalizeErrorCode, providerErrorFromUnknown, providerRuntime, redactSecretText, retryAfterMsFromHeader, severityFromUsedPercent, thinkingCapabilitiesFromProviderModel, unixSecondsToIso, usedPercentFromRatio, withProviderId };
|
|
312
|
+
export { DEFAULT_ATTACHMENT_EXTENSIONS, ProviderQuotaUnsupportedError, applyModelPolicy, authStatusFromKey, clampPromptCacheKey, clampUsedPercent, createProviderQuota, defineProvider, ensureQuota, httpErrorCode, httpRequestFailedEvent, modelSelectionFromCatalog, normalizeErrorCode, numberHeader, providerErrorFromUnknown, providerRuntime, redactCredentialText, redactSecretText, retryAfterMsFromHeader, severityFromUsedPercent, thinkingCapabilitiesFromProviderModel, toolResultContentToText, unixSecondsToIso, usedPercentFromRatio, withProviderId };
|
package/dist/testing.d.mts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { S as ProviderRun, _ as ProviderEvent, i as InferenceSteer, r as InferenceRequest, t as AgentProvider } from "./types-Uczx0xBQ.mjs";
|
|
3
2
|
//#region src/testing.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* Scripted provider for testing. Each "turn" is a list of events to yield.
|
|
@@ -20,6 +19,7 @@ declare class StubProvider implements AgentProvider {
|
|
|
20
19
|
private turns;
|
|
21
20
|
private cursor;
|
|
22
21
|
constructor(turns: TurnScript[]);
|
|
22
|
+
clone(): AgentProvider;
|
|
23
23
|
run(request: InferenceRequest): AsyncIterable<ProviderEvent>;
|
|
24
24
|
/** Number of turns consumed so far. Useful for assertions. */
|
|
25
25
|
get consumedTurns(): number;
|
package/dist/testing.mjs
CHANGED
|
@@ -20,6 +20,12 @@ var StubProvider = class {
|
|
|
20
20
|
constructor(turns) {
|
|
21
21
|
this.turns = turns;
|
|
22
22
|
}
|
|
23
|
+
clone() {
|
|
24
|
+
return {
|
|
25
|
+
run: (request) => this.run(request),
|
|
26
|
+
clone: () => this.clone()
|
|
27
|
+
};
|
|
28
|
+
}
|
|
23
29
|
async *run(request) {
|
|
24
30
|
const turn = this.turns[this.cursor];
|
|
25
31
|
this.cursor += 1;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { ModelSelection, ThinkingConfig, ThinkingEffort, TokenUsage, ToolResultContentBlock, UserContentBlock } from "@demicodes/core";
|
|
2
|
-
|
|
1
|
+
import { ModelSelection, ProviderErrorDiagnostics, ThinkingConfig, ThinkingEffort, TokenUsage, ToolResultContentBlock, UserContentBlock } from "@demicodes/core";
|
|
3
2
|
//#region src/quota.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* Unified subscription / rate-limit quota surface for concrete providers.
|
|
@@ -50,7 +49,8 @@ type ProviderQuotaCapability = {
|
|
|
50
49
|
} | {
|
|
51
50
|
mode: 'supported';
|
|
52
51
|
canProbe: boolean;
|
|
53
|
-
canObserve: boolean;
|
|
52
|
+
canObserve: boolean;
|
|
53
|
+
/** free = dedicated usage API; minimal_request = burns a tiny inference */
|
|
54
54
|
probeCost?: ProviderQuotaProbeCost;
|
|
55
55
|
staleAfterMs?: number;
|
|
56
56
|
};
|
|
@@ -73,6 +73,11 @@ interface ProviderQuota {
|
|
|
73
73
|
capability(): ProviderQuotaCapability;
|
|
74
74
|
probe(options?: ProviderQuotaProbeOptions): Promise<ProviderQuotaSnapshot>;
|
|
75
75
|
latest(): ProviderQuotaSnapshot | null;
|
|
76
|
+
/**
|
|
77
|
+
* Drop the in-memory latest snapshot (e.g. after credentials.setActive so the
|
|
78
|
+
* next ensureQuota/probe does not show the previous account).
|
|
79
|
+
*/
|
|
80
|
+
clearLatest?(): void;
|
|
76
81
|
/**
|
|
77
82
|
* Optional passive update from a vendor HTTP response (headers, etc.).
|
|
78
83
|
* Returns the new snapshot when observation succeeded; otherwise null.
|
|
@@ -201,13 +206,24 @@ type ProviderEvent = {
|
|
|
201
206
|
toolUseId: string;
|
|
202
207
|
toolName: string;
|
|
203
208
|
input: unknown;
|
|
204
|
-
} |
|
|
209
|
+
} |
|
|
210
|
+
/**
|
|
211
|
+
* End of a model response. `usage` MUST be the usage of a single API request
|
|
212
|
+
* — the final one when the provider made several internally (e.g. a CLI turn
|
|
213
|
+
* with tool calls). The agent anchors its context-size estimation on it
|
|
214
|
+
* (input + output + cache reads/writes ≈ the context the next request will
|
|
215
|
+
* carry), so a turn-cumulative total here inflates the estimate and triggers
|
|
216
|
+
* spurious compaction.
|
|
217
|
+
*/
|
|
218
|
+
{
|
|
205
219
|
type: 'response';
|
|
206
220
|
usage: TokenUsage;
|
|
207
221
|
} | {
|
|
208
222
|
type: 'error';
|
|
209
223
|
message: string;
|
|
210
|
-
code: string | null;
|
|
224
|
+
code: string | null;
|
|
225
|
+
diagnostics?: ProviderErrorDiagnostics;
|
|
226
|
+
/** Server-suggested retry delay (e.g. from a Retry-After header), if any. */
|
|
211
227
|
retryAfterMs?: number;
|
|
212
228
|
} | {
|
|
213
229
|
type: 'abort';
|
|
@@ -223,6 +239,14 @@ interface ProviderRun extends AsyncIterable<ProviderEvent> {
|
|
|
223
239
|
}
|
|
224
240
|
interface AgentProvider {
|
|
225
241
|
run(request: InferenceRequest): ProviderRun;
|
|
242
|
+
/**
|
|
243
|
+
* Creates an independent runtime with the same provider configuration.
|
|
244
|
+
*
|
|
245
|
+
* Configuration dependencies such as auth stores and quota observers may be
|
|
246
|
+
* shared, but mutable per-session execution state (subprocesses, sockets,
|
|
247
|
+
* pending tool calls, and continuation state) must not be shared.
|
|
248
|
+
*/
|
|
249
|
+
clone(): AgentProvider;
|
|
226
250
|
/**
|
|
227
251
|
* Releases any resources the provider holds open across turns — e.g. a long-lived CLI
|
|
228
252
|
* subprocess kept alive for a whole session. Called once when the owning session closes.
|
|
@@ -249,6 +273,113 @@ type ProviderAuthState = {
|
|
|
249
273
|
interface ProviderAuth {
|
|
250
274
|
status(): Promise<ProviderAuthState> | ProviderAuthState;
|
|
251
275
|
}
|
|
276
|
+
/** Public metadata only — never tokens, cookies, or raw auth files. */
|
|
277
|
+
interface ProviderCredentialInfo {
|
|
278
|
+
/** Stable id within this provider (not globally unique across providers). */
|
|
279
|
+
id: string;
|
|
280
|
+
/** Human label: email, account id, or import tag. */
|
|
281
|
+
label: string;
|
|
282
|
+
/** Optional secondary display (plan name, issuer, …). */
|
|
283
|
+
detail?: string | null;
|
|
284
|
+
/** ISO-8601 when this entry was last imported or refreshed in the pool. */
|
|
285
|
+
updatedAt?: string | null;
|
|
286
|
+
}
|
|
287
|
+
interface ProviderCredentialActive {
|
|
288
|
+
credentialId: string | null;
|
|
289
|
+
/** Same shape as auth status, for the active credential. */
|
|
290
|
+
status: ProviderAuthState;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* User-facing material issued mid-flow by a device-code login: the product
|
|
294
|
+
* relays it to the user, who completes login from any browser on any device.
|
|
295
|
+
*/
|
|
296
|
+
interface ProviderCredentialLoginPending {
|
|
297
|
+
/** URL the user opens to confirm the login. */
|
|
298
|
+
verificationUrl: string;
|
|
299
|
+
/** One-time code the user enters at the verification URL (device-code flows). */
|
|
300
|
+
userCode?: string | null;
|
|
301
|
+
/** ISO-8601 expiry of the code, when the vendor exposes one. */
|
|
302
|
+
expiresAt?: string | null;
|
|
303
|
+
/**
|
|
304
|
+
* True when the vendor displays a code AFTER approval that the user must
|
|
305
|
+
* bring back; the product collects it via `promptForCode`.
|
|
306
|
+
*/
|
|
307
|
+
requiresCodeInput?: boolean;
|
|
308
|
+
}
|
|
309
|
+
interface ProviderCredentialLoginOptions {
|
|
310
|
+
/** Abort the login flow. */
|
|
311
|
+
signal?: AbortSignal;
|
|
312
|
+
/** Fires once when the flow issues user-facing material (device-code login). */
|
|
313
|
+
onPending?: (pending: ProviderCredentialLoginPending) => void;
|
|
314
|
+
/** Collects the code the user copied back from the vendor page (`requiresCodeInput` flows). */
|
|
315
|
+
promptForCode?: () => Promise<string>;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Login invoke result. Every login flow runs the vendor's public protocol
|
|
319
|
+
* natively, imports the resulting material into the pool, and returns the
|
|
320
|
+
* pool `credentialId`.
|
|
321
|
+
*/
|
|
322
|
+
type ProviderCredentialLoginResult = {
|
|
323
|
+
status: 'completed';
|
|
324
|
+
credentialId: string;
|
|
325
|
+
} | {
|
|
326
|
+
status: 'cancelled';
|
|
327
|
+
} | {
|
|
328
|
+
status: 'unavailable';
|
|
329
|
+
message: string;
|
|
330
|
+
} | {
|
|
331
|
+
status: 'failed';
|
|
332
|
+
message: string;
|
|
333
|
+
};
|
|
334
|
+
/**
|
|
335
|
+
* Provider-specific add payloads. Concrete packages document accepted variants.
|
|
336
|
+
* Do not put secrets on browser-visible control protocols.
|
|
337
|
+
*/
|
|
338
|
+
type ProviderCredentialAddInput = {
|
|
339
|
+
[key: string]: unknown;
|
|
340
|
+
};
|
|
341
|
+
type ProviderCredentialsCapability = {
|
|
342
|
+
mode: 'none';
|
|
343
|
+
} | {
|
|
344
|
+
mode: 'supported';
|
|
345
|
+
/** Can run the vendor's native login flow (`beginLogin`). */
|
|
346
|
+
canBeginLogin?: boolean;
|
|
347
|
+
/** Can import from the vendor default location into the pool. */
|
|
348
|
+
canImportDefault?: boolean;
|
|
349
|
+
/** Can register externally supplied material (`add`). */
|
|
350
|
+
canAdd?: boolean;
|
|
351
|
+
/** Pool can hold more than one credential. */
|
|
352
|
+
multi?: boolean;
|
|
353
|
+
};
|
|
354
|
+
/**
|
|
355
|
+
* Multi-credential pool + process-global active switch.
|
|
356
|
+
* See `docs/provider-global-credentials.md`.
|
|
357
|
+
*/
|
|
358
|
+
interface ProviderCredentials {
|
|
359
|
+
capability(): ProviderCredentialsCapability;
|
|
360
|
+
list(): Promise<ProviderCredentialInfo[]> | ProviderCredentialInfo[];
|
|
361
|
+
getActive(): Promise<ProviderCredentialActive> | ProviderCredentialActive;
|
|
362
|
+
/**
|
|
363
|
+
* Make `credentialId` the process-global active credential for this provider.
|
|
364
|
+
* Subsequent auth / quota / inference use it.
|
|
365
|
+
*/
|
|
366
|
+
setActive(credentialId: string): Promise<ProviderCredentialActive> | ProviderCredentialActive;
|
|
367
|
+
/**
|
|
368
|
+
* Run the vendor's public login protocol natively (device code or copy-back
|
|
369
|
+
* OAuth), surfacing user-facing material via `onPending`. On completion the
|
|
370
|
+
* material is imported into the pool and its `credentialId` is returned.
|
|
371
|
+
*/
|
|
372
|
+
beginLogin?(options?: ProviderCredentialLoginOptions): Promise<ProviderCredentialLoginResult>;
|
|
373
|
+
/**
|
|
374
|
+
* Snapshot current vendor-default material into the demi pool.
|
|
375
|
+
* Assigns a stable `id` and returns public metadata (no secrets).
|
|
376
|
+
*/
|
|
377
|
+
importDefault?(): Promise<ProviderCredentialInfo>;
|
|
378
|
+
/** Register material supplied by the product. */
|
|
379
|
+
add?(input: ProviderCredentialAddInput): Promise<ProviderCredentialInfo>;
|
|
380
|
+
/** Remove a pool entry. */
|
|
381
|
+
remove?(credentialId: string): Promise<void>;
|
|
382
|
+
}
|
|
252
383
|
type ProviderRuntimeState = {
|
|
253
384
|
status: 'unknown';
|
|
254
385
|
message?: string;
|
|
@@ -268,6 +399,8 @@ interface Provider {
|
|
|
268
399
|
auth?: ProviderAuth;
|
|
269
400
|
/** Optional subscription / rate-limit quota surface (`@demicodes/provider` quota helpers). */
|
|
270
401
|
quota?: ProviderQuota;
|
|
402
|
+
/** Optional multi-credential pool + global active switch. */
|
|
403
|
+
credentials?: ProviderCredentials;
|
|
271
404
|
state?(): Promise<ProviderRuntimeState> | ProviderRuntimeState;
|
|
272
405
|
listModels?(): Promise<ProviderModelList> | ProviderModelList;
|
|
273
406
|
}
|
|
@@ -297,6 +430,10 @@ interface ProviderModel {
|
|
|
297
430
|
outputLimit: number | null;
|
|
298
431
|
supportsTools: boolean | null;
|
|
299
432
|
supportsAttachments: boolean | null;
|
|
433
|
+
/** Whether the model accepts native video input (not frame extraction). Most models
|
|
434
|
+
* (all current Anthropic/Claude Code models) do not — their API has no video block.
|
|
435
|
+
* Optional: unset/undefined means "no video", so existing catalogs need no change. */
|
|
436
|
+
supportsVideo?: boolean | null;
|
|
300
437
|
supportsReasoning: boolean | null;
|
|
301
438
|
supportedThinkingEfforts: ThinkingEffort[] | null;
|
|
302
439
|
defaultThinkingEffort: ThinkingEffort | null;
|
|
@@ -324,4 +461,4 @@ type ModelPolicy = {
|
|
|
324
461
|
default?: string;
|
|
325
462
|
};
|
|
326
463
|
//#endregion
|
|
327
|
-
export {
|
|
464
|
+
export { ProviderQuota as A, ProviderQuotaUnsupportedError as B, ProviderRuntimeFactory as C, ToolDefinition as D, ProviderServiceTier as E, ProviderQuotaProbeOptions as F, ensureQuota as G, ProviderQuotaWindowUnit as H, ProviderQuotaProbeResult as I, usedPercentFromRatio as J, severityFromUsedPercent as K, ProviderQuotaSeverity as L, ProviderQuotaObserveInput as M, ProviderQuotaPlan as N, CreateProviderQuotaOptions as O, ProviderQuotaProbeCost as P, ProviderQuotaSnapshot as R, ProviderRun as S, ProviderSelection as T, clampUsedPercent as U, ProviderQuotaWindow as V, createProviderQuota as W, ProviderEvent as _, ModelPolicy as a, ProviderModelCost as b, ProviderAuthState as c, ProviderCredentialInfo as d, ProviderCredentialLoginOptions as f, ProviderCredentialsCapability as g, ProviderCredentials as h, InferenceSteer as i, ProviderQuotaCapability as j, EnsureQuotaOptions as k, ProviderCredentialActive as l, ProviderCredentialLoginResult as m, InferenceItem as n, Provider as o, ProviderCredentialLoginPending as p, unixSecondsToIso as q, InferenceRequest as r, ProviderAuth as s, AgentProvider as t, ProviderCredentialAddInput as u, ProviderFactoryDefinition as v, ProviderRuntimeState as w, ProviderModelList as x, ProviderModel as y, ProviderQuotaSource as z };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@demicodes/provider",
|
|
3
3
|
"description": "Provider contract and shared building blocks for Demi inference adapters.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.12.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
@@ -12,11 +12,15 @@
|
|
|
12
12
|
"./testing": {
|
|
13
13
|
"types": "./dist/testing.d.mts",
|
|
14
14
|
"import": "./dist/testing.mjs"
|
|
15
|
+
},
|
|
16
|
+
"./credentials-pool": {
|
|
17
|
+
"types": "./dist/credentials-pool.d.mts",
|
|
18
|
+
"import": "./dist/credentials-pool.mjs"
|
|
15
19
|
}
|
|
16
20
|
},
|
|
17
21
|
"dependencies": {
|
|
18
|
-
"@demicodes/core": "^0.
|
|
19
|
-
"@demicodes/utils": "^0.
|
|
22
|
+
"@demicodes/core": "^0.12.0",
|
|
23
|
+
"@demicodes/utils": "^0.12.0"
|
|
20
24
|
},
|
|
21
25
|
"license": "Apache-2.0",
|
|
22
26
|
"main": "./dist/index.mjs",
|