@aplaytest/llm 0.1.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/dist/.tsbuildinfo +1 -0
- package/dist/budget.d.ts +46 -0
- package/dist/budget.d.ts.map +1 -0
- package/dist/budget.js +71 -0
- package/dist/budget.js.map +1 -0
- package/dist/client.d.ts +73 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +21 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +36 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +56 -0
- package/dist/errors.js.map +1 -0
- package/dist/factory.d.ts +48 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +58 -0
- package/dist/factory.js.map +1 -0
- package/dist/fake.d.ts +29 -0
- package/dist/fake.d.ts.map +1 -0
- package/dist/fake.js +68 -0
- package/dist/fake.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/pricing.d.ts +60 -0
- package/dist/pricing.d.ts.map +1 -0
- package/dist/pricing.js +100 -0
- package/dist/pricing.js.map +1 -0
- package/dist/providers/anthropic.d.ts +51 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +150 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/unavailable.d.ts +19 -0
- package/dist/providers/unavailable.d.ts.map +1 -0
- package/dist/providers/unavailable.js +27 -0
- package/dist/providers/unavailable.js.map +1 -0
- package/package.json +38 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAsB,KAAK,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAG3F,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,MAAM,CAAC;AAE5C,MAAM,WAAW,mBAAoB,SAAQ,sBAAsB;IACjE,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IACzC,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG,SAAS,CAAC;CACzE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,mBAAwB,GAAG,SAAS,CAgB5E;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,SAAS,EAAE,GAAG,MAAM,CAG3F"}
|
package/dist/factory.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client construction.
|
|
3
|
+
*
|
|
4
|
+
* Resolving to an UnavailableLlmClient rather than throwing at startup is the
|
|
5
|
+
* point: every deterministic feature keeps working, and only the code paths
|
|
6
|
+
* that genuinely need a model fail — with a reason that names itself.
|
|
7
|
+
*/
|
|
8
|
+
import { AnthropicLlmClient } from './providers/anthropic.js';
|
|
9
|
+
import { UnavailableLlmClient } from './providers/unavailable.js';
|
|
10
|
+
/**
|
|
11
|
+
* Build an {@link LlmClient} from options and the environment.
|
|
12
|
+
*
|
|
13
|
+
* Resolves to {@link UnavailableLlmClient} rather than throwing: every
|
|
14
|
+
* deterministic feature keeps working, and only paths that genuinely need a
|
|
15
|
+
* model fail — with a reason that names itself.
|
|
16
|
+
*
|
|
17
|
+
* @param options - Provider, API key, and an optional `env` override (tests
|
|
18
|
+
* inject this so they never touch `process.env`).
|
|
19
|
+
* @returns A live Anthropic client, or an unavailable client whose
|
|
20
|
+
* `complete()` rejects with `LlmUnavailableError`.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const llm = createLlmClient(); // unavailable when ANTHROPIC_API_KEY is unset
|
|
25
|
+
* if (!llm.available) {
|
|
26
|
+
* // heal, flaky, impact still run
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export function createLlmClient(options = {}) {
|
|
31
|
+
if (options.disabled === true) {
|
|
32
|
+
return new UnavailableLlmClient('disabled by --no-llm');
|
|
33
|
+
}
|
|
34
|
+
if (options.provider === 'none') {
|
|
35
|
+
return new UnavailableLlmClient('provider is set to "none"');
|
|
36
|
+
}
|
|
37
|
+
const env = options.env ?? process.env;
|
|
38
|
+
const apiKey = options.apiKey ?? env['ANTHROPIC_API_KEY'];
|
|
39
|
+
if (apiKey === undefined || apiKey === '') {
|
|
40
|
+
return new UnavailableLlmClient('ANTHROPIC_API_KEY is not set');
|
|
41
|
+
}
|
|
42
|
+
return new AnthropicLlmClient({ ...options, apiKey });
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* One-line description of which roles a client can serve, for `aplaytest doctor`
|
|
46
|
+
* and CLI banners.
|
|
47
|
+
*
|
|
48
|
+
* @param client - The client to describe.
|
|
49
|
+
* @param roles - Roles to include in the description.
|
|
50
|
+
* @returns `"no model — deterministic tier only"` when unavailable, otherwise
|
|
51
|
+
* a `role: model-id` list.
|
|
52
|
+
*/
|
|
53
|
+
export function describeAvailability(client, roles) {
|
|
54
|
+
if (!client.available)
|
|
55
|
+
return 'no model — deterministic tier only';
|
|
56
|
+
return roles.map(role => `${role}: ${client.modelFor(role)}`).join(' · ');
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,kBAAkB,EAA+B,MAAM,0BAA0B,CAAC;AAC3F,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAWlE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,eAAe,CAAC,UAA+B,EAAE;IAC/D,IAAI,OAAO,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC9B,OAAO,IAAI,oBAAoB,CAAC,sBAAsB,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;QAChC,OAAO,IAAI,oBAAoB,CAAC,2BAA2B,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACvC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAE1D,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;QAC1C,OAAO,IAAI,oBAAoB,CAAC,8BAA8B,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,IAAI,kBAAkB,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;AACxD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,KAA2B;IACjF,IAAI,CAAC,MAAM,CAAC,SAAS;QAAE,OAAO,oCAAoC,CAAC;IACnE,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,KAAK,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5E,CAAC"}
|
package/dist/fake.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A scripted client for tests.
|
|
3
|
+
*
|
|
4
|
+
* Exported from the package, not hidden in a test folder, because the agent
|
|
5
|
+
* runtime in @aplaytest/agent needs it too — and because an agent loop that can
|
|
6
|
+
* only be exercised with a live API key is an agent loop nobody will test.
|
|
7
|
+
*/
|
|
8
|
+
import type { z } from 'zod';
|
|
9
|
+
import { type CompleteRequest, type CompleteResponse, type LlmClient, type ModelRole, type StructuredResponse, type Usage } from './client.js';
|
|
10
|
+
export interface ScriptedTurn {
|
|
11
|
+
/** Text the model "returns". Objects are serialised. */
|
|
12
|
+
readonly reply: string | object;
|
|
13
|
+
readonly refused?: boolean;
|
|
14
|
+
readonly refusalCategory?: string;
|
|
15
|
+
readonly usage?: Partial<Usage>;
|
|
16
|
+
}
|
|
17
|
+
export declare class FakeLlmClient implements LlmClient {
|
|
18
|
+
private readonly script;
|
|
19
|
+
readonly available = true;
|
|
20
|
+
/** Every request made, in order — assert against these. */
|
|
21
|
+
readonly requests: CompleteRequest[];
|
|
22
|
+
private turn;
|
|
23
|
+
constructor(script: readonly ScriptedTurn[]);
|
|
24
|
+
modelFor(role: ModelRole): string;
|
|
25
|
+
get callCount(): number;
|
|
26
|
+
complete(request: CompleteRequest): Promise<CompleteResponse>;
|
|
27
|
+
completeStructured<T>(request: CompleteRequest, schema: z.ZodType<T>): Promise<StructuredResponse<T>>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=fake.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake.d.ts","sourceRoot":"","sources":["../src/fake.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,kBAAkB,EACvB,KAAK,KAAK,EACX,MAAM,aAAa,CAAC;AAIrB,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;CACjC;AAED,qBAAa,aAAc,YAAW,SAAS;IAMjC,OAAO,CAAC,QAAQ,CAAC,MAAM;IALnC,QAAQ,CAAC,SAAS,QAAQ;IAC1B,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,EAAE,eAAe,EAAE,CAAM;IAC1C,OAAO,CAAC,IAAI,CAAK;gBAEY,MAAM,EAAE,SAAS,YAAY,EAAE;IAE5D,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM;IAIjC,IAAI,SAAS,IAAI,MAAM,CAEtB;IAEK,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAsB7D,kBAAkB,CAAC,CAAC,EACxB,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;CAmBlC"}
|
package/dist/fake.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A scripted client for tests.
|
|
3
|
+
*
|
|
4
|
+
* Exported from the package, not hidden in a test folder, because the agent
|
|
5
|
+
* runtime in @aplaytest/agent needs it too — and because an agent loop that can
|
|
6
|
+
* only be exercised with a live API key is an agent loop nobody will test.
|
|
7
|
+
*/
|
|
8
|
+
import { EMPTY_USAGE, } from './client.js';
|
|
9
|
+
import { RefusalError, StructuredOutputError } from './errors.js';
|
|
10
|
+
import { DEFAULT_MODELS } from './pricing.js';
|
|
11
|
+
export class FakeLlmClient {
|
|
12
|
+
script;
|
|
13
|
+
available = true;
|
|
14
|
+
/** Every request made, in order — assert against these. */
|
|
15
|
+
requests = [];
|
|
16
|
+
turn = 0;
|
|
17
|
+
constructor(script) {
|
|
18
|
+
this.script = script;
|
|
19
|
+
}
|
|
20
|
+
modelFor(role) {
|
|
21
|
+
return DEFAULT_MODELS[role];
|
|
22
|
+
}
|
|
23
|
+
get callCount() {
|
|
24
|
+
return this.turn;
|
|
25
|
+
}
|
|
26
|
+
async complete(request) {
|
|
27
|
+
this.requests.push(request);
|
|
28
|
+
const scripted = this.script[this.turn];
|
|
29
|
+
this.turn += 1;
|
|
30
|
+
if (scripted === undefined) {
|
|
31
|
+
throw new Error(`FakeLlmClient ran out of script at call ${this.turn} — the code under test made ` +
|
|
32
|
+
'more model calls than expected.');
|
|
33
|
+
}
|
|
34
|
+
const text = typeof scripted.reply === 'string' ? scripted.reply : JSON.stringify(scripted.reply);
|
|
35
|
+
return {
|
|
36
|
+
text: scripted.refused === true ? '' : text,
|
|
37
|
+
usage: { ...EMPTY_USAGE, outputTokens: text.length, ...scripted.usage },
|
|
38
|
+
model: this.modelFor(request.role),
|
|
39
|
+
refused: scripted.refused === true,
|
|
40
|
+
refusalCategory: scripted.refusalCategory ?? null,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
async completeStructured(request, schema) {
|
|
44
|
+
const first = await this.complete(request);
|
|
45
|
+
if (first.refused)
|
|
46
|
+
throw new RefusalError(first.refusalCategory);
|
|
47
|
+
const parsed = schema.safeParse(safeJson(first.text));
|
|
48
|
+
if (parsed.success)
|
|
49
|
+
return { ...first, value: parsed.data, raw: first.text, repaired: false };
|
|
50
|
+
const retry = await this.complete(request);
|
|
51
|
+
if (retry.refused)
|
|
52
|
+
throw new RefusalError(retry.refusalCategory);
|
|
53
|
+
const second = schema.safeParse(safeJson(retry.text));
|
|
54
|
+
if (!second.success) {
|
|
55
|
+
throw new StructuredOutputError(second.error.issues.map(i => i.message).join(', '), retry.text);
|
|
56
|
+
}
|
|
57
|
+
return { ...retry, value: second.data, raw: retry.text, repaired: true };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function safeJson(text) {
|
|
61
|
+
try {
|
|
62
|
+
return JSON.parse(text);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return text;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=fake.js.map
|
package/dist/fake.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake.js","sourceRoot":"","sources":["../src/fake.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @aplaytest/llm — the only package that talks to a model.
|
|
3
|
+
*
|
|
4
|
+
* Everything else takes an injected `LlmClient`, which is what keeps a model
|
|
5
|
+
* SDK out of the reporter (running in every test worker) and lets the agent
|
|
6
|
+
* loop be tested against a scripted fake.
|
|
7
|
+
*/
|
|
8
|
+
export type { LlmClient, ModelRole, Effort, Message, Usage, CompleteRequest, CompleteResponse, StructuredResponse, } from './client.js';
|
|
9
|
+
export { EMPTY_USAGE } from './client.js';
|
|
10
|
+
export { createLlmClient, describeAvailability } from './factory.js';
|
|
11
|
+
export type { CreateClientOptions, Provider } from './factory.js';
|
|
12
|
+
export { AnthropicLlmClient } from './providers/anthropic.js';
|
|
13
|
+
export { UnavailableLlmClient } from './providers/unavailable.js';
|
|
14
|
+
export { FakeLlmClient } from './fake.js';
|
|
15
|
+
export type { ScriptedTurn } from './fake.js';
|
|
16
|
+
export { BudgetGuard, DEFAULT_BUDGET } from './budget.js';
|
|
17
|
+
export type { BudgetLimits, BudgetState } from './budget.js';
|
|
18
|
+
export { MODELS, DEFAULT_MODELS, DEFAULT_EFFORT, specFor, costUsd, checkCacheable, estimateTokens, } from './pricing.js';
|
|
19
|
+
export type { ModelSpec, TokenCounts, CacheWarning } from './pricing.js';
|
|
20
|
+
export { LlmUnavailableError, BudgetExceededError, RefusalError, StructuredOutputError, } from './errors.js';
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,YAAY,EACV,SAAS,EACT,SAAS,EACT,MAAM,EACN,OAAO,EACP,KAAK,EACL,eAAe,EACf,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACrE,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAElE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC1D,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,EACL,MAAM,EACN,cAAc,EACd,cAAc,EACd,OAAO,EACP,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEzE,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,YAAY,EACZ,qBAAqB,GACtB,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @aplaytest/llm — the only package that talks to a model.
|
|
3
|
+
*
|
|
4
|
+
* Everything else takes an injected `LlmClient`, which is what keeps a model
|
|
5
|
+
* SDK out of the reporter (running in every test worker) and lets the agent
|
|
6
|
+
* loop be tested against a scripted fake.
|
|
7
|
+
*/
|
|
8
|
+
export { EMPTY_USAGE } from './client.js';
|
|
9
|
+
export { createLlmClient, describeAvailability } from './factory.js';
|
|
10
|
+
export { AnthropicLlmClient } from './providers/anthropic.js';
|
|
11
|
+
export { UnavailableLlmClient } from './providers/unavailable.js';
|
|
12
|
+
export { FakeLlmClient } from './fake.js';
|
|
13
|
+
export { BudgetGuard, DEFAULT_BUDGET } from './budget.js';
|
|
14
|
+
export { MODELS, DEFAULT_MODELS, DEFAULT_EFFORT, specFor, costUsd, checkCacheable, estimateTokens, } from './pricing.js';
|
|
15
|
+
export { LlmUnavailableError, BudgetExceededError, RefusalError, StructuredOutputError, } from './errors.js';
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAGrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG1D,OAAO,EACL,MAAM,EACN,cAAc,EACd,cAAc,EACd,OAAO,EACP,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,YAAY,EACZ,qBAAqB,GACtB,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model selection, pricing, and the cache-prefix rules.
|
|
3
|
+
*
|
|
4
|
+
* Cost is computed from real per-token rates rather than estimated, so the
|
|
5
|
+
* CLI can always disclose what a run actually spent. A user must never have
|
|
6
|
+
* to wonder whether a number came from a model or a measurement.
|
|
7
|
+
*/
|
|
8
|
+
import type { Effort, ModelRole } from './client.js';
|
|
9
|
+
export interface ModelSpec {
|
|
10
|
+
readonly id: string;
|
|
11
|
+
/** USD per million input tokens. */
|
|
12
|
+
readonly inputPerMTok: number;
|
|
13
|
+
readonly outputPerMTok: number;
|
|
14
|
+
/**
|
|
15
|
+
* Minimum cacheable prefix, in tokens.
|
|
16
|
+
*
|
|
17
|
+
* NOT monotonic across generations, which is the trap: 512 on Opus 5 but
|
|
18
|
+
* 4096 on Haiku 4.5. A conventions block that caches fine on the heal path
|
|
19
|
+
* can silently fail to cache on the classify path, with no error — just
|
|
20
|
+
* `cache_creation_input_tokens: 0` forever.
|
|
21
|
+
*/
|
|
22
|
+
readonly minCacheablePrefix: number;
|
|
23
|
+
readonly contextWindow: number;
|
|
24
|
+
}
|
|
25
|
+
export declare const MODELS: Readonly<Record<string, ModelSpec>>;
|
|
26
|
+
/**
|
|
27
|
+
* Role → model. Split by JOB SHAPE, not by a vague quality axis.
|
|
28
|
+
*
|
|
29
|
+
* classify — taxonomy tie-breaks and phrasing. High volume, low stakes, and
|
|
30
|
+
* the deterministic tier has already done the real work.
|
|
31
|
+
* heal — ranking pre-verified candidates by intent. A judgement call
|
|
32
|
+
* between a handful of options, not a research task.
|
|
33
|
+
* author — planning, browser exploration, code synthesis.
|
|
34
|
+
*/
|
|
35
|
+
export declare const DEFAULT_MODELS: Readonly<Record<ModelRole, string>>;
|
|
36
|
+
export declare const DEFAULT_EFFORT: Readonly<Record<ModelRole, Effort>>;
|
|
37
|
+
export declare function specFor(modelId: string): ModelSpec | null;
|
|
38
|
+
export interface TokenCounts {
|
|
39
|
+
readonly inputTokens: number;
|
|
40
|
+
readonly outputTokens: number;
|
|
41
|
+
readonly cacheReadTokens: number;
|
|
42
|
+
readonly cacheWriteTokens: number;
|
|
43
|
+
}
|
|
44
|
+
export declare function costUsd(modelId: string, counts: TokenCounts): number;
|
|
45
|
+
export interface CacheWarning {
|
|
46
|
+
readonly model: string;
|
|
47
|
+
readonly prefixTokens: number;
|
|
48
|
+
readonly minimum: number;
|
|
49
|
+
readonly message: string;
|
|
50
|
+
}
|
|
51
|
+
/** Rough token estimate. Only used to warn, never to bill. */
|
|
52
|
+
export declare function estimateTokens(text: string): number;
|
|
53
|
+
/**
|
|
54
|
+
* Warn when a prefix is too short to cache on this model.
|
|
55
|
+
*
|
|
56
|
+
* Silent is the problem: below the minimum the API simply does not cache and
|
|
57
|
+
* reports nothing, so the first sign is a bill.
|
|
58
|
+
*/
|
|
59
|
+
export declare function checkCacheable(modelId: string, systemPrompt: string): CacheWarning | null;
|
|
60
|
+
//# sourceMappingURL=pricing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B;;;;;;;OAOG;IACH,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,eAAO,MAAM,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAsBtD,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAK9D,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAM9D,CAAC;AAEF,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAEzD;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AAUD,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,MAAM,CAapE;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,8DAA8D;AAC9D,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAgBzF"}
|
package/dist/pricing.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model selection, pricing, and the cache-prefix rules.
|
|
3
|
+
*
|
|
4
|
+
* Cost is computed from real per-token rates rather than estimated, so the
|
|
5
|
+
* CLI can always disclose what a run actually spent. A user must never have
|
|
6
|
+
* to wonder whether a number came from a model or a measurement.
|
|
7
|
+
*/
|
|
8
|
+
export const MODELS = {
|
|
9
|
+
'claude-opus-5': {
|
|
10
|
+
id: 'claude-opus-5',
|
|
11
|
+
inputPerMTok: 5,
|
|
12
|
+
outputPerMTok: 25,
|
|
13
|
+
minCacheablePrefix: 512,
|
|
14
|
+
contextWindow: 1_000_000,
|
|
15
|
+
},
|
|
16
|
+
'claude-sonnet-5': {
|
|
17
|
+
id: 'claude-sonnet-5',
|
|
18
|
+
inputPerMTok: 3,
|
|
19
|
+
outputPerMTok: 15,
|
|
20
|
+
minCacheablePrefix: 1024,
|
|
21
|
+
contextWindow: 1_000_000,
|
|
22
|
+
},
|
|
23
|
+
'claude-haiku-4-5': {
|
|
24
|
+
id: 'claude-haiku-4-5',
|
|
25
|
+
inputPerMTok: 1,
|
|
26
|
+
outputPerMTok: 5,
|
|
27
|
+
minCacheablePrefix: 4096,
|
|
28
|
+
contextWindow: 200_000,
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Role → model. Split by JOB SHAPE, not by a vague quality axis.
|
|
33
|
+
*
|
|
34
|
+
* classify — taxonomy tie-breaks and phrasing. High volume, low stakes, and
|
|
35
|
+
* the deterministic tier has already done the real work.
|
|
36
|
+
* heal — ranking pre-verified candidates by intent. A judgement call
|
|
37
|
+
* between a handful of options, not a research task.
|
|
38
|
+
* author — planning, browser exploration, code synthesis.
|
|
39
|
+
*/
|
|
40
|
+
export const DEFAULT_MODELS = {
|
|
41
|
+
classify: 'claude-haiku-4-5',
|
|
42
|
+
heal: 'claude-sonnet-5',
|
|
43
|
+
author: 'claude-opus-5',
|
|
44
|
+
vision: 'claude-sonnet-5',
|
|
45
|
+
};
|
|
46
|
+
export const DEFAULT_EFFORT = {
|
|
47
|
+
classify: 'low',
|
|
48
|
+
heal: 'medium',
|
|
49
|
+
// The documented setting for coding and agentic work.
|
|
50
|
+
author: 'xhigh',
|
|
51
|
+
vision: 'medium',
|
|
52
|
+
};
|
|
53
|
+
export function specFor(modelId) {
|
|
54
|
+
return MODELS[modelId] ?? null;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Cache reads cost ~0.1× base input; writes cost 1.25× (5-minute TTL).
|
|
58
|
+
* Two requests break even, so an analyze pass over several failures is well
|
|
59
|
+
* past the threshold on its second call.
|
|
60
|
+
*/
|
|
61
|
+
const CACHE_READ_MULTIPLIER = 0.1;
|
|
62
|
+
const CACHE_WRITE_MULTIPLIER = 1.25;
|
|
63
|
+
export function costUsd(modelId, counts) {
|
|
64
|
+
const spec = specFor(modelId);
|
|
65
|
+
if (spec === null)
|
|
66
|
+
return 0;
|
|
67
|
+
const perInputToken = spec.inputPerMTok / 1_000_000;
|
|
68
|
+
const perOutputToken = spec.outputPerMTok / 1_000_000;
|
|
69
|
+
return (counts.inputTokens * perInputToken +
|
|
70
|
+
counts.outputTokens * perOutputToken +
|
|
71
|
+
counts.cacheReadTokens * perInputToken * CACHE_READ_MULTIPLIER +
|
|
72
|
+
counts.cacheWriteTokens * perInputToken * CACHE_WRITE_MULTIPLIER);
|
|
73
|
+
}
|
|
74
|
+
/** Rough token estimate. Only used to warn, never to bill. */
|
|
75
|
+
export function estimateTokens(text) {
|
|
76
|
+
return Math.ceil(text.length / 4);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Warn when a prefix is too short to cache on this model.
|
|
80
|
+
*
|
|
81
|
+
* Silent is the problem: below the minimum the API simply does not cache and
|
|
82
|
+
* reports nothing, so the first sign is a bill.
|
|
83
|
+
*/
|
|
84
|
+
export function checkCacheable(modelId, systemPrompt) {
|
|
85
|
+
const spec = specFor(modelId);
|
|
86
|
+
if (spec === null)
|
|
87
|
+
return null;
|
|
88
|
+
const prefixTokens = estimateTokens(systemPrompt);
|
|
89
|
+
if (prefixTokens >= spec.minCacheablePrefix)
|
|
90
|
+
return null;
|
|
91
|
+
return {
|
|
92
|
+
model: modelId,
|
|
93
|
+
prefixTokens,
|
|
94
|
+
minimum: spec.minCacheablePrefix,
|
|
95
|
+
message: `Cache prefix is ~${prefixTokens} tokens, below the ${spec.minCacheablePrefix}-token ` +
|
|
96
|
+
`minimum for ${modelId}. cache_control will be silently ignored — no error, just no ` +
|
|
97
|
+
'caching. Note the minimum is not monotonic across models.',
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=pricing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAqBH,MAAM,CAAC,MAAM,MAAM,GAAwC;IACzD,eAAe,EAAE;QACf,EAAE,EAAE,eAAe;QACnB,YAAY,EAAE,CAAC;QACf,aAAa,EAAE,EAAE;QACjB,kBAAkB,EAAE,GAAG;QACvB,aAAa,EAAE,SAAS;KACzB;IACD,iBAAiB,EAAE;QACjB,EAAE,EAAE,iBAAiB;QACrB,YAAY,EAAE,CAAC;QACf,aAAa,EAAE,EAAE;QACjB,kBAAkB,EAAE,IAAI;QACxB,aAAa,EAAE,SAAS;KACzB;IACD,kBAAkB,EAAE;QAClB,EAAE,EAAE,kBAAkB;QACtB,YAAY,EAAE,CAAC;QACf,aAAa,EAAE,CAAC;QAChB,kBAAkB,EAAE,IAAI;QACxB,aAAa,EAAE,OAAO;KACvB;CACF,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,cAAc,GAAwC;IACjE,QAAQ,EAAE,kBAAkB;IAC5B,IAAI,EAAE,iBAAiB;IACvB,MAAM,EAAE,eAAe;IACvB,MAAM,EAAE,iBAAiB;CAC1B,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAwC;IACjE,QAAQ,EAAE,KAAK;IACf,IAAI,EAAE,QAAQ;IACd,sDAAsD;IACtD,MAAM,EAAE,OAAO;IACf,MAAM,EAAE,QAAQ;CACjB,CAAC;AAEF,MAAM,UAAU,OAAO,CAAC,OAAe;IACrC,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;AACjC,CAAC;AASD;;;;GAIG;AACH,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAClC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAEpC,MAAM,UAAU,OAAO,CAAC,OAAe,EAAE,MAAmB;IAC1D,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,CAAC,CAAC;IAE5B,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;IACpD,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;IAEtD,OAAO,CACL,MAAM,CAAC,WAAW,GAAG,aAAa;QAClC,MAAM,CAAC,YAAY,GAAG,cAAc;QACpC,MAAM,CAAC,eAAe,GAAG,aAAa,GAAG,qBAAqB;QAC9D,MAAM,CAAC,gBAAgB,GAAG,aAAa,GAAG,sBAAsB,CACjE,CAAC;AACJ,CAAC;AASD,8DAA8D;AAC9D,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACpC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,YAAoB;IAClE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAE/B,MAAM,YAAY,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IAClD,IAAI,YAAY,IAAI,IAAI,CAAC,kBAAkB;QAAE,OAAO,IAAI,CAAC;IAEzD,OAAO;QACL,KAAK,EAAE,OAAO;QACd,YAAY;QACZ,OAAO,EAAE,IAAI,CAAC,kBAAkB;QAChC,OAAO,EACL,oBAAoB,YAAY,sBAAsB,IAAI,CAAC,kBAAkB,SAAS;YACtF,eAAe,OAAO,+DAA+D;YACrF,2DAA2D;KAC9D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Anthropic provider.
|
|
3
|
+
*
|
|
4
|
+
* Three things here are deliberate and easy to get wrong:
|
|
5
|
+
*
|
|
6
|
+
* 1. NO sampling parameters. `temperature`, `top_p` and `top_k` are rejected
|
|
7
|
+
* with a 400 on current Opus and Sonnet models. Depth is `effort`.
|
|
8
|
+
* 2. The system prompt is a cacheable block, ordered first. It is the only
|
|
9
|
+
* part guaranteed byte-identical across a run, so it is the cache prefix.
|
|
10
|
+
* 3. `stop_reason: "refusal"` arrives as a normal HTTP 200. Reading
|
|
11
|
+
* `content[0]` without checking it will break.
|
|
12
|
+
*/
|
|
13
|
+
import type { z } from 'zod';
|
|
14
|
+
import { EMPTY_USAGE, type CompleteRequest, type CompleteResponse, type LlmClient, type ModelRole, type StructuredResponse, type Usage } from '../client.js';
|
|
15
|
+
export interface AnthropicClientOptions {
|
|
16
|
+
readonly apiKey?: string | undefined;
|
|
17
|
+
readonly models?: Partial<Record<ModelRole, string>> | undefined;
|
|
18
|
+
readonly maxTokens?: number | undefined;
|
|
19
|
+
/** Emitted for each call so the CLI can disclose model usage inline. */
|
|
20
|
+
onUsage?: ((usage: Usage, model: string) => void) | undefined;
|
|
21
|
+
}
|
|
22
|
+
export declare class AnthropicLlmClient implements LlmClient {
|
|
23
|
+
private readonly options;
|
|
24
|
+
readonly available = true;
|
|
25
|
+
private readonly anthropic;
|
|
26
|
+
private readonly models;
|
|
27
|
+
constructor(options?: AnthropicClientOptions);
|
|
28
|
+
modelFor(role: ModelRole): string;
|
|
29
|
+
complete(request: CompleteRequest): Promise<CompleteResponse>;
|
|
30
|
+
/**
|
|
31
|
+
* Structured output via the API's own schema constraint, not prompting.
|
|
32
|
+
*
|
|
33
|
+
* The earlier implementation asked for JSON in prose and re-parsed the text,
|
|
34
|
+
* with one repair round when that failed. Measured against the live model,
|
|
35
|
+
* that is not a robustness question — it is a correctness one. The author
|
|
36
|
+
* agent's prompt asked for a test plan and never mentioned JSON, so the model
|
|
37
|
+
* returned an excellent Markdown plan; every field parsed as `undefined`, the
|
|
38
|
+
* repair round produced more prose, and the run failed after 100 seconds and
|
|
39
|
+
* $0.19. The repair agent only worked because its prompt happened to carry
|
|
40
|
+
* "Reply with JSON only, matching this shape:".
|
|
41
|
+
*
|
|
42
|
+
* `output_config.format` constrains the response at the API level, so the
|
|
43
|
+
* schema is enforced rather than requested and the repair round has nothing
|
|
44
|
+
* left to do.
|
|
45
|
+
*/
|
|
46
|
+
completeStructured<T>(request: CompleteRequest, schema: z.ZodType<T>): Promise<StructuredResponse<T>>;
|
|
47
|
+
private toUsage;
|
|
48
|
+
}
|
|
49
|
+
export declare function mergeUsage(a: Usage, b: Usage): Usage;
|
|
50
|
+
export { EMPTY_USAGE };
|
|
51
|
+
//# sourceMappingURL=anthropic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,EACL,WAAW,EACX,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,kBAAkB,EACvB,KAAK,KAAK,EACX,MAAM,cAAc,CAAC;AAItB,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC;IACjE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,wEAAwE;IACxE,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAC/D;AAyBD,qBAAa,kBAAmB,YAAW,SAAS;IAKtC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,QAAQ,CAAC,SAAS,QAAQ;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;gBAEtB,OAAO,GAAE,sBAA2B;IAMjE,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM;IAI3B,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAoCnE;;;;;;;;;;;;;;;OAeG;IACG,kBAAkB,CAAC,CAAC,EACxB,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;IAsDjC,OAAO,CAAC,OAAO;CAShB;AAGD,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG,KAAK,CAQpD;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Anthropic provider.
|
|
3
|
+
*
|
|
4
|
+
* Three things here are deliberate and easy to get wrong:
|
|
5
|
+
*
|
|
6
|
+
* 1. NO sampling parameters. `temperature`, `top_p` and `top_k` are rejected
|
|
7
|
+
* with a 400 on current Opus and Sonnet models. Depth is `effort`.
|
|
8
|
+
* 2. The system prompt is a cacheable block, ordered first. It is the only
|
|
9
|
+
* part guaranteed byte-identical across a run, so it is the cache prefix.
|
|
10
|
+
* 3. `stop_reason: "refusal"` arrives as a normal HTTP 200. Reading
|
|
11
|
+
* `content[0]` without checking it will break.
|
|
12
|
+
*/
|
|
13
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
14
|
+
import { zodOutputFormat } from '@anthropic-ai/sdk/helpers/zod';
|
|
15
|
+
import { EMPTY_USAGE, } from '../client.js';
|
|
16
|
+
import { RefusalError, StructuredOutputError } from '../errors.js';
|
|
17
|
+
import { DEFAULT_EFFORT, DEFAULT_MODELS, costUsd } from '../pricing.js';
|
|
18
|
+
const DEFAULT_MAX_TOKENS = 16_000;
|
|
19
|
+
function extractText(response) {
|
|
20
|
+
return response.content
|
|
21
|
+
.filter(block => block.type === 'text')
|
|
22
|
+
.map(block => block.text ?? '')
|
|
23
|
+
.join('');
|
|
24
|
+
}
|
|
25
|
+
export class AnthropicLlmClient {
|
|
26
|
+
options;
|
|
27
|
+
available = true;
|
|
28
|
+
anthropic;
|
|
29
|
+
models;
|
|
30
|
+
constructor(options = {}) {
|
|
31
|
+
this.options = options;
|
|
32
|
+
this.anthropic =
|
|
33
|
+
options.apiKey === undefined ? new Anthropic() : new Anthropic({ apiKey: options.apiKey });
|
|
34
|
+
this.models = { ...DEFAULT_MODELS, ...options.models };
|
|
35
|
+
}
|
|
36
|
+
modelFor(role) {
|
|
37
|
+
return this.models[role];
|
|
38
|
+
}
|
|
39
|
+
async complete(request) {
|
|
40
|
+
const model = this.modelFor(request.role);
|
|
41
|
+
const response = (await this.anthropic.messages.create({
|
|
42
|
+
model,
|
|
43
|
+
max_tokens: request.maxTokens ?? this.options.maxTokens ?? DEFAULT_MAX_TOKENS,
|
|
44
|
+
// The cache prefix: marked cacheable, and rendered before `messages`.
|
|
45
|
+
system: [
|
|
46
|
+
{
|
|
47
|
+
type: 'text',
|
|
48
|
+
text: request.system,
|
|
49
|
+
cache_control: { type: 'ephemeral' },
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
messages: request.messages.map(m => ({ role: m.role, content: m.content })),
|
|
53
|
+
// Depth, not sampling. `temperature` here would be a 400.
|
|
54
|
+
output_config: { effort: request.effort ?? DEFAULT_EFFORT[request.role] },
|
|
55
|
+
thinking: { type: 'adaptive' },
|
|
56
|
+
}));
|
|
57
|
+
const usage = this.toUsage(response, model);
|
|
58
|
+
this.options.onUsage?.(usage, model);
|
|
59
|
+
const refused = response.stop_reason === 'refusal';
|
|
60
|
+
return {
|
|
61
|
+
// Empty on refusal rather than whatever partial text exists: callers
|
|
62
|
+
// that ignore `refused` should get nothing, not something plausible.
|
|
63
|
+
text: refused ? '' : extractText(response),
|
|
64
|
+
usage,
|
|
65
|
+
model: response.model ?? model,
|
|
66
|
+
refused,
|
|
67
|
+
refusalCategory: response.stop_details?.category ?? null,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Structured output via the API's own schema constraint, not prompting.
|
|
72
|
+
*
|
|
73
|
+
* The earlier implementation asked for JSON in prose and re-parsed the text,
|
|
74
|
+
* with one repair round when that failed. Measured against the live model,
|
|
75
|
+
* that is not a robustness question — it is a correctness one. The author
|
|
76
|
+
* agent's prompt asked for a test plan and never mentioned JSON, so the model
|
|
77
|
+
* returned an excellent Markdown plan; every field parsed as `undefined`, the
|
|
78
|
+
* repair round produced more prose, and the run failed after 100 seconds and
|
|
79
|
+
* $0.19. The repair agent only worked because its prompt happened to carry
|
|
80
|
+
* "Reply with JSON only, matching this shape:".
|
|
81
|
+
*
|
|
82
|
+
* `output_config.format` constrains the response at the API level, so the
|
|
83
|
+
* schema is enforced rather than requested and the repair round has nothing
|
|
84
|
+
* left to do.
|
|
85
|
+
*/
|
|
86
|
+
async completeStructured(request, schema) {
|
|
87
|
+
const model = this.modelFor(request.role);
|
|
88
|
+
const response = (await this.anthropic.messages.parse({
|
|
89
|
+
model,
|
|
90
|
+
max_tokens: request.maxTokens ?? this.options.maxTokens ?? DEFAULT_MAX_TOKENS,
|
|
91
|
+
system: [
|
|
92
|
+
{
|
|
93
|
+
type: 'text',
|
|
94
|
+
text: request.system,
|
|
95
|
+
cache_control: { type: 'ephemeral' },
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
messages: request.messages.map(m => ({ role: m.role, content: m.content })),
|
|
99
|
+
output_config: {
|
|
100
|
+
effort: request.effort ?? DEFAULT_EFFORT[request.role],
|
|
101
|
+
format: zodOutputFormat(schema),
|
|
102
|
+
},
|
|
103
|
+
thinking: { type: 'adaptive' },
|
|
104
|
+
}));
|
|
105
|
+
const usage = this.toUsage(response, model);
|
|
106
|
+
this.options.onUsage?.(usage, model);
|
|
107
|
+
if (response.stop_reason === 'refusal') {
|
|
108
|
+
throw new RefusalError(response.stop_details?.category ?? null);
|
|
109
|
+
}
|
|
110
|
+
const text = extractText(response);
|
|
111
|
+
if (response.parsed_output === null || response.parsed_output === undefined) {
|
|
112
|
+
// Reached when the response is schema-shaped but fails a constraint the
|
|
113
|
+
// API does not enforce (string lengths, array bounds — the SDK strips
|
|
114
|
+
// those from the wire schema and checks them client-side), or when the
|
|
115
|
+
// turn was truncated. Nothing a retry would fix, so it fails loudly.
|
|
116
|
+
throw new StructuredOutputError(response.stop_reason === 'max_tokens'
|
|
117
|
+
? 'response hit max_tokens before the schema was satisfied'
|
|
118
|
+
: 'response did not satisfy the schema', text);
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
usage,
|
|
122
|
+
model: response.model ?? model,
|
|
123
|
+
refused: false,
|
|
124
|
+
refusalCategory: null,
|
|
125
|
+
value: response.parsed_output,
|
|
126
|
+
raw: text,
|
|
127
|
+
repaired: false,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
toUsage(response, model) {
|
|
131
|
+
const counts = {
|
|
132
|
+
inputTokens: response.usage?.input_tokens ?? 0,
|
|
133
|
+
outputTokens: response.usage?.output_tokens ?? 0,
|
|
134
|
+
cacheReadTokens: response.usage?.cache_read_input_tokens ?? 0,
|
|
135
|
+
cacheWriteTokens: response.usage?.cache_creation_input_tokens ?? 0,
|
|
136
|
+
};
|
|
137
|
+
return { ...counts, usd: costUsd(model, counts) };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
export function mergeUsage(a, b) {
|
|
141
|
+
return {
|
|
142
|
+
inputTokens: a.inputTokens + b.inputTokens,
|
|
143
|
+
outputTokens: a.outputTokens + b.outputTokens,
|
|
144
|
+
cacheReadTokens: a.cacheReadTokens + b.cacheReadTokens,
|
|
145
|
+
cacheWriteTokens: a.cacheWriteTokens + b.cacheWriteTokens,
|
|
146
|
+
usd: a.usd + b.usd,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
export { EMPTY_USAGE };
|
|
150
|
+
//# sourceMappingURL=anthropic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The no-model client.
|
|
3
|
+
*
|
|
4
|
+
* Every call throws a NAMED error rather than returning empty output. That is
|
|
5
|
+
* the degradation contract: a command either works, works with reduced scope,
|
|
6
|
+
* or exits non-zero saying which. What it must never do is quietly produce a
|
|
7
|
+
* worse answer that looks like a normal one.
|
|
8
|
+
*/
|
|
9
|
+
import type { z } from 'zod';
|
|
10
|
+
import type { CompleteRequest, CompleteResponse, LlmClient, ModelRole, StructuredResponse } from '../client.js';
|
|
11
|
+
export declare class UnavailableLlmClient implements LlmClient {
|
|
12
|
+
private readonly reason;
|
|
13
|
+
readonly available = false;
|
|
14
|
+
constructor(reason: string);
|
|
15
|
+
modelFor(role: ModelRole): string;
|
|
16
|
+
complete(_request: CompleteRequest): Promise<CompleteResponse>;
|
|
17
|
+
completeStructured<T>(_request: CompleteRequest, _schema: z.ZodType<T>): Promise<StructuredResponse<T>>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=unavailable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unavailable.d.ts","sourceRoot":"","sources":["../../src/providers/unavailable.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EAChB,SAAS,EACT,SAAS,EACT,kBAAkB,EACnB,MAAM,cAAc,CAAC;AAItB,qBAAa,oBAAqB,YAAW,SAAS;IAGxC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,QAAQ,CAAC,SAAS,SAAS;gBAEE,MAAM,EAAE,MAAM;IAE3C,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM;IAI3B,QAAQ,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAI9D,kBAAkB,CAAC,CAAC,EACxB,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GACpB,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;CAGlC"}
|