fix: show native Claude CLI usage as unpriced

This commit is contained in:
amosblomqvist
2026-10-28 19:58:07 +02:00
parent 5093809ea0
commit 17c94be327
11 changed files with 64 additions and 13 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
export const CLAUDE_CODE_PROVIDER = "claude-code";
export { CLAUDE_CODE_PROVIDER } from "../../core/contracts/claude-code.ts";
export const CLAUDE_CODE_API = "claude-code-cli";
+2 -2
View File
@@ -7,8 +7,8 @@ const SHARED_MODEL_FIELDS = {
provider: CLAUDE_CODE_PROVIDER,
baseUrl: "",
input: ["text", "image"],
// Placeholder rates, not a billing guarantee: the CLI's own auth/routing
// determines charges. Cost presentation remains a separate product decision.
// Pi-required placeholders, not prices: the CLI's own auth/routing
// determines charges. Server pricing and the client catalog report unpriced.
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
reasoning: true,
// The CLI has no thinking-off switch; effort low is the floor.
+2
View File
@@ -1,3 +1,5 @@
export const CLAUDE_CODE_PROVIDER = "claude-code";
/** Installation/version only. Never an authentication, quota, or billing verdict. */
export interface ClaudeCodeStatus {
state: "not-found" | "meets-minimum" | "update-required" | "version-unchecked";
+2 -1
View File
@@ -21,7 +21,8 @@ export interface ModelCatalogEntry {
* thinkingLevelMap — e.g. GLM-5.3-flash: low|high|max). The thinking
* picker lists exactly these; anything else is a lie. */
supportedLevels: ThinkingLevel[];
cost: { input: number; output: number; cacheRead: number; cacheWrite: number };
/** Null when LearnHarness cannot estimate prices for this connection. */
cost: { input: number; output: number; cacheRead: number; cacheWrite: number } | null;
contextWindow: number;
maxTokens: number;
}
+1 -1
View File
@@ -54,7 +54,7 @@ export type { ChatGPTStatus, ChatGPTControlBridge } from "./contracts/chatgpt.ts
export { NATIVE_SUBSCRIPTIONS } from "./contracts/subscriptions.ts";
export type { NativeSubscriptionProviderId, NativeSubscriptionLogicalId, NativeSubscriptionStatus, NativeSubscriptionSnapshot, NativeSubscriptionScope, NativeSubscriptionControlBridge, SubscriptionInteraction, SubscriptionPrompt } from "./contracts/subscriptions.ts";
export * from "./cost-summary.ts";
export { CLAUDE_CODE_MINIMUM_VERSION, type ClaudeCodeStatus } from "./contracts/claude-code.ts";
export { CLAUDE_CODE_PROVIDER, CLAUDE_CODE_MINIMUM_VERSION, type ClaudeCodeStatus } from "./contracts/claude-code.ts";
export * from "./fuzzy.ts";
// settings.ts + settings-resolution.ts (settings-storage wave, 2026-09-19):
// the user-settings record's shape/sanitizer (pure) and its fully-resolved
+1 -1
View File
@@ -164,7 +164,7 @@ export function toModelDto(model: Model<Api>): ModelDto {
reasoning: model.reasoning,
input: [...model.input],
supportedLevels: getSupportedThinkingLevels(model),
cost: {
cost: model.provider === CLAUDE_CODE_PROVIDER ? null : {
input: model.cost.input,
output: model.cost.output,
cacheRead: model.cost.cacheRead,
+4 -1
View File
@@ -4,12 +4,15 @@
*/
import { calculateCost, type Usage } from "@earendil-works/pi-ai";
import { piModels } from "../agent/models.ts";
import { CLAUDE_CODE_PROVIDER } from "../core/contracts/claude-code.ts";
import type { CallUsage, ChatRecord, JobRecord, TurnUsage } from "../core/contracts.ts";
import { isSubscriptionModel, sessionCost as foldSessionCost, turnCost as foldTurnCost, jobCost as foldJobCost } from "../core/prices.ts";
function catalogModel(id: string) {
const colon = id.indexOf(":");
if (colon < 0 || isSubscriptionModel(id)) return undefined;
// Native CLI routing determines billing. Adapter zero-rate placeholders
// must never become an apparent $0 estimate or subscription classification.
if (colon < 0 || isSubscriptionModel(id) || id.slice(0, colon) === CLAUDE_CODE_PROVIDER) return undefined;
return piModels().getModel(id.slice(0, colon), id.slice(colon + 1));
}