mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-22 10:14:22 +01:00
add cost
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
"ai": "^5.0.0-alpha.4",
|
"ai": "^5.0.0-alpha.4",
|
||||||
"cac": "^6.7.14",
|
"cac": "^6.7.14",
|
||||||
"clipanion": "^4.0.0-rc.4",
|
"clipanion": "^4.0.0-rc.4",
|
||||||
|
"decimal.js": "^10.5.0",
|
||||||
"diff": "^8.0.2",
|
"diff": "^8.0.2",
|
||||||
"env-paths": "^3.0.0",
|
"env-paths": "^3.0.0",
|
||||||
"hono": "^4.7.10",
|
"hono": "^4.7.10",
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
"ai": "^5.0.0-alpha.4",
|
"ai": "^5.0.0-alpha.4",
|
||||||
"cac": "^6.7.14",
|
"cac": "^6.7.14",
|
||||||
"clipanion": "^4.0.0-rc.4",
|
"clipanion": "^4.0.0-rc.4",
|
||||||
|
"decimal.js": "^10.5.0",
|
||||||
"diff": "^8.0.2",
|
"diff": "^8.0.2",
|
||||||
"env-paths": "^3.0.0",
|
"env-paths": "^3.0.0",
|
||||||
"hono": "^4.7.10",
|
"hono": "^4.7.10",
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export namespace Config {
|
|||||||
|
|
||||||
export const Provider = z.object({
|
export const Provider = z.object({
|
||||||
options: z.record(z.string(), z.any()).optional(),
|
options: z.record(z.string(), z.any()).optional(),
|
||||||
models: z.record(z.string(), Model).optional(),
|
models: z.record(z.string(), Model),
|
||||||
});
|
});
|
||||||
export type Provider = z.output<typeof Provider>;
|
export type Provider = z.output<typeof Provider>;
|
||||||
|
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ export namespace LLM {
|
|||||||
"claude-sonnet-4-20250514": {
|
"claude-sonnet-4-20250514": {
|
||||||
name: "Claude 4 Sonnet",
|
name: "Claude 4 Sonnet",
|
||||||
cost: {
|
cost: {
|
||||||
input: 3.0,
|
input: 3.0 / 1_000_000,
|
||||||
inputCached: 3.75,
|
inputCached: 3.75 / 1_000_000,
|
||||||
output: 15.0,
|
output: 15.0 / 1_000_000,
|
||||||
outputCached: 0.3,
|
outputCached: 0.3 / 1_000_000,
|
||||||
},
|
},
|
||||||
contextWindow: 200000,
|
contextWindow: 200000,
|
||||||
maxTokens: 50000,
|
maxTokens: 50000,
|
||||||
@@ -49,6 +49,10 @@ export namespace LLM {
|
|||||||
instance: Provider;
|
instance: Provider;
|
||||||
}
|
}
|
||||||
> = {};
|
> = {};
|
||||||
|
const models = new Map<
|
||||||
|
string,
|
||||||
|
{ info: Config.Model; instance: LanguageModel }
|
||||||
|
>();
|
||||||
|
|
||||||
const list = mergeDeep(NATIVE_PROVIDERS, app.config.providers ?? {});
|
const list = mergeDeep(NATIVE_PROVIDERS, app.config.providers ?? {});
|
||||||
|
|
||||||
@@ -82,7 +86,7 @@ export namespace LLM {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
models: new Map<string, LanguageModel>(),
|
models,
|
||||||
providers,
|
providers,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -101,11 +105,19 @@ export namespace LLM {
|
|||||||
providerID,
|
providerID,
|
||||||
modelID,
|
modelID,
|
||||||
});
|
});
|
||||||
|
const info = provider.info.models[modelID];
|
||||||
|
if (!info) throw new ModelNotFoundError(modelID);
|
||||||
try {
|
try {
|
||||||
const match = provider.instance.languageModel(modelID);
|
const match = provider.instance.languageModel(modelID);
|
||||||
log.info("found", { providerID, modelID });
|
log.info("found", { providerID, modelID });
|
||||||
s.models.set(key, match);
|
s.models.set(key, {
|
||||||
return match;
|
info,
|
||||||
|
instance: match,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
info,
|
||||||
|
instance: match,
|
||||||
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof NoSuchModelError) throw new ModelNotFoundError(modelID);
|
if (e instanceof NoSuchModelError) throw new ModelNotFoundError(modelID);
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
} from "ai";
|
} from "ai";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import * as tools from "../tool";
|
import * as tools from "../tool";
|
||||||
|
import { Decimal } from "decimal.js";
|
||||||
|
|
||||||
import PROMPT_ANTHROPIC from "./prompt/anthropic.txt";
|
import PROMPT_ANTHROPIC from "./prompt/anthropic.txt";
|
||||||
import PROMPT_TITLE from "./prompt/title.txt";
|
import PROMPT_TITLE from "./prompt/title.txt";
|
||||||
@@ -31,6 +32,7 @@ export namespace Session {
|
|||||||
id: Identifier.schema("session"),
|
id: Identifier.schema("session"),
|
||||||
shareID: z.string().optional(),
|
shareID: z.string().optional(),
|
||||||
title: z.string(),
|
title: z.string(),
|
||||||
|
cost: z.number().optional(),
|
||||||
tokens: z.object({
|
tokens: z.object({
|
||||||
input: z.number(),
|
input: z.number(),
|
||||||
output: z.number(),
|
output: z.number(),
|
||||||
@@ -188,7 +190,7 @@ export namespace Session {
|
|||||||
parts: input.parts,
|
parts: input.parts,
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
model,
|
model: model.instance,
|
||||||
}).then((result) => {
|
}).then((result) => {
|
||||||
return Session.update(input.sessionID, (draft) => {
|
return Session.update(input.sessionID, (draft) => {
|
||||||
draft.title = result.text;
|
draft.title = result.text;
|
||||||
@@ -226,16 +228,23 @@ export namespace Session {
|
|||||||
const result = streamText({
|
const result = streamText({
|
||||||
onStepFinish: (step) => {
|
onStepFinish: (step) => {
|
||||||
update(input.sessionID, (draft) => {
|
update(input.sessionID, (draft) => {
|
||||||
draft.tokens.input += step.usage.inputTokens || 0;
|
const input = step.usage.inputTokens ?? 0;
|
||||||
draft.tokens.output += step.usage.outputTokens || 0;
|
const output = step.usage.outputTokens ?? 0;
|
||||||
draft.tokens.reasoning += step.usage.reasoningTokens || 0;
|
const reasoning = step.usage.reasoningTokens ?? 0;
|
||||||
|
draft.tokens.input += input;
|
||||||
|
draft.tokens.output += output;
|
||||||
|
draft.tokens.reasoning += reasoning;
|
||||||
|
draft.cost = new Decimal(draft.cost ?? 0)
|
||||||
|
.add(new Decimal(input).mul(model.info.cost.input))
|
||||||
|
.add(new Decimal(output).mul(model.info.cost.output))
|
||||||
|
.toNumber();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
stopWhen: stepCountIs(1000),
|
stopWhen: stepCountIs(1000),
|
||||||
messages: convertToModelMessages(msgs),
|
messages: convertToModelMessages(msgs),
|
||||||
temperature: 0,
|
temperature: 0,
|
||||||
tools,
|
tools,
|
||||||
model,
|
model: model.instance,
|
||||||
});
|
});
|
||||||
|
|
||||||
msgs.push(next);
|
msgs.push(next);
|
||||||
|
|||||||
Reference in New Issue
Block a user