oasis_test_v2 2.2.31 → 2.2.32
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/index.js +579 -325
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1295,11 +1295,12 @@ var init_chat_session = __esm({
|
|
|
1295
1295
|
});
|
|
1296
1296
|
|
|
1297
1297
|
// ../contract/src/live-protocol.ts
|
|
1298
|
-
var NORMALIZED_PROVIDER_EVENT_VERSION;
|
|
1298
|
+
var NORMALIZED_PROVIDER_EVENT_VERSION, SUBAGENT_TASK_CODE;
|
|
1299
1299
|
var init_live_protocol = __esm({
|
|
1300
1300
|
"../contract/src/live-protocol.ts"() {
|
|
1301
1301
|
"use strict";
|
|
1302
1302
|
NORMALIZED_PROVIDER_EVENT_VERSION = 1;
|
|
1303
|
+
SUBAGENT_TASK_CODE = "subagent_task";
|
|
1303
1304
|
}
|
|
1304
1305
|
});
|
|
1305
1306
|
|
|
@@ -23127,14 +23128,132 @@ var init_filter_extra_args = __esm({
|
|
|
23127
23128
|
});
|
|
23128
23129
|
|
|
23129
23130
|
// ../adapters/src/claude-code/index.ts
|
|
23130
|
-
function createClaudeLiveParserState(streamId) {
|
|
23131
|
+
function createClaudeLiveParserState(streamId, opts = {}) {
|
|
23131
23132
|
return {
|
|
23132
23133
|
streamId,
|
|
23133
23134
|
turnNumber: 0,
|
|
23134
23135
|
turnId: `claude-turn:${streamId}:0`,
|
|
23135
|
-
blockIds: /* @__PURE__ */ new Map()
|
|
23136
|
+
blockIds: /* @__PURE__ */ new Map(),
|
|
23137
|
+
agentTasks: /* @__PURE__ */ new Map(),
|
|
23138
|
+
subagentCalls: /* @__PURE__ */ new Map(),
|
|
23139
|
+
...opts.readSubagentUsage ? { readSubagentUsage: opts.readSubagentUsage } : {}
|
|
23136
23140
|
};
|
|
23137
23141
|
}
|
|
23142
|
+
function numberOf(value2) {
|
|
23143
|
+
return typeof value2 === "number" && Number.isFinite(value2) ? value2 : void 0;
|
|
23144
|
+
}
|
|
23145
|
+
function subagentCallOf(message) {
|
|
23146
|
+
const id = stringOf(message?.id);
|
|
23147
|
+
const usage = parseResultUsage(message?.usage);
|
|
23148
|
+
if (!id || !usage) return void 0;
|
|
23149
|
+
return {
|
|
23150
|
+
id,
|
|
23151
|
+
call: {
|
|
23152
|
+
model: stringOf(message?.model) ?? "unknown",
|
|
23153
|
+
tokens: {
|
|
23154
|
+
inputTokens: usage.input ?? 0,
|
|
23155
|
+
outputTokens: usage.output ?? 0,
|
|
23156
|
+
cacheReadTokens: usage.cacheRead ?? 0,
|
|
23157
|
+
cacheCreationTokens: usage.cacheCreation ?? 0
|
|
23158
|
+
}
|
|
23159
|
+
}
|
|
23160
|
+
};
|
|
23161
|
+
}
|
|
23162
|
+
function recordSubagentCall(calls, id, call) {
|
|
23163
|
+
const prev = calls.get(id);
|
|
23164
|
+
calls.set(id, prev ? {
|
|
23165
|
+
model: call.model,
|
|
23166
|
+
tokens: {
|
|
23167
|
+
inputTokens: Math.max(prev.tokens.inputTokens, call.tokens.inputTokens),
|
|
23168
|
+
outputTokens: Math.max(prev.tokens.outputTokens, call.tokens.outputTokens),
|
|
23169
|
+
cacheReadTokens: Math.max(prev.tokens.cacheReadTokens, call.tokens.cacheReadTokens),
|
|
23170
|
+
cacheCreationTokens: Math.max(prev.tokens.cacheCreationTokens, call.tokens.cacheCreationTokens)
|
|
23171
|
+
}
|
|
23172
|
+
} : call);
|
|
23173
|
+
}
|
|
23174
|
+
function byModelOf(calls) {
|
|
23175
|
+
const out = {};
|
|
23176
|
+
for (const { model, tokens } of calls.values()) {
|
|
23177
|
+
const acc = out[model] ?? (out[model] = { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheCreationTokens: 0 });
|
|
23178
|
+
acc.inputTokens += tokens.inputTokens;
|
|
23179
|
+
acc.outputTokens += tokens.outputTokens;
|
|
23180
|
+
acc.cacheReadTokens += tokens.cacheReadTokens;
|
|
23181
|
+
acc.cacheCreationTokens += tokens.cacheCreationTokens;
|
|
23182
|
+
}
|
|
23183
|
+
return out;
|
|
23184
|
+
}
|
|
23185
|
+
function readSubagentTranscriptUsage(outputFile) {
|
|
23186
|
+
try {
|
|
23187
|
+
const stat3 = fs7.statSync(outputFile);
|
|
23188
|
+
if (!stat3.isFile() || stat3.size > SUBAGENT_TRANSCRIPT_MAX_BYTES) return void 0;
|
|
23189
|
+
const calls = /* @__PURE__ */ new Map();
|
|
23190
|
+
for (const line of fs7.readFileSync(outputFile, "utf8").split("\n")) {
|
|
23191
|
+
if (!line.includes('"assistant"') || !line.includes('"usage"')) continue;
|
|
23192
|
+
let parsed;
|
|
23193
|
+
try {
|
|
23194
|
+
parsed = JSON.parse(line);
|
|
23195
|
+
} catch {
|
|
23196
|
+
continue;
|
|
23197
|
+
}
|
|
23198
|
+
if (parsed.type !== "assistant") continue;
|
|
23199
|
+
const hit = subagentCallOf(objectOf(parsed.message));
|
|
23200
|
+
if (hit) recordSubagentCall(calls, hit.id, hit.call);
|
|
23201
|
+
}
|
|
23202
|
+
return calls.size > 0 ? byModelOf(calls) : void 0;
|
|
23203
|
+
} catch {
|
|
23204
|
+
return void 0;
|
|
23205
|
+
}
|
|
23206
|
+
}
|
|
23207
|
+
function subagentTaskEvents(parsed, state) {
|
|
23208
|
+
const taskId = stringOf(parsed.task_id);
|
|
23209
|
+
if (!taskId) return [];
|
|
23210
|
+
const emit = (toolUseId, task) => [
|
|
23211
|
+
liveEvent(state, `${SUBAGENT_TASK_CODE}:${toolUseId}:${task.status}`, "control", "completed", {
|
|
23212
|
+
code: SUBAGENT_TASK_CODE,
|
|
23213
|
+
toolCallId: toolUseId,
|
|
23214
|
+
task: jsonOf(task)
|
|
23215
|
+
})
|
|
23216
|
+
];
|
|
23217
|
+
if (parsed.subtype === "task_started") {
|
|
23218
|
+
const toolUseId = stringOf(parsed.tool_use_id);
|
|
23219
|
+
if (parsed.task_type !== "local_agent" || !toolUseId) return [];
|
|
23220
|
+
const description = stringOf(parsed.description);
|
|
23221
|
+
const subagentType = stringOf(parsed.subagent_type);
|
|
23222
|
+
const info = {
|
|
23223
|
+
...description ? { description } : {},
|
|
23224
|
+
...subagentType ? { subagentType } : {},
|
|
23225
|
+
background: parsed.is_backgrounded === true
|
|
23226
|
+
};
|
|
23227
|
+
state.agentTasks.set(taskId, { toolUseId, ...info });
|
|
23228
|
+
return emit(toolUseId, { status: "running", ...info });
|
|
23229
|
+
}
|
|
23230
|
+
if (parsed.subtype === "task_notification") {
|
|
23231
|
+
const known = state.agentTasks.get(taskId);
|
|
23232
|
+
if (!known) return [];
|
|
23233
|
+
state.agentTasks.delete(taskId);
|
|
23234
|
+
const { toolUseId, ...info } = known;
|
|
23235
|
+
const usage = objectOf(parsed.usage);
|
|
23236
|
+
const summary = stringOf(parsed.summary);
|
|
23237
|
+
const totalTokens = numberOf(usage?.total_tokens);
|
|
23238
|
+
const toolUses = numberOf(usage?.tool_uses);
|
|
23239
|
+
const durationMs3 = numberOf(usage?.duration_ms);
|
|
23240
|
+
const outputFile = stringOf(parsed.output_file);
|
|
23241
|
+
const fromTranscript = outputFile ? state.readSubagentUsage?.(outputFile) : void 0;
|
|
23242
|
+
const streamCalls = state.subagentCalls.get(toolUseId);
|
|
23243
|
+
state.subagentCalls.delete(toolUseId);
|
|
23244
|
+
const tokenUsage = fromTranscript && Object.keys(fromTranscript).length > 0 ? { byModel: fromTranscript, source: "transcript" } : streamCalls?.size ? { byModel: byModelOf(streamCalls), source: "stream" } : void 0;
|
|
23245
|
+
return emit(toolUseId, {
|
|
23246
|
+
...info,
|
|
23247
|
+
status: SUBAGENT_TERMINAL[stringOf(parsed.status) ?? ""] ?? "completed",
|
|
23248
|
+
...summary ? { summary } : {},
|
|
23249
|
+
...totalTokens !== void 0 ? { totalTokens } : {},
|
|
23250
|
+
...toolUses !== void 0 ? { toolUses } : {},
|
|
23251
|
+
...durationMs3 !== void 0 ? { durationMs: durationMs3 } : {},
|
|
23252
|
+
...tokenUsage ? { usage: tokenUsage } : {}
|
|
23253
|
+
});
|
|
23254
|
+
}
|
|
23255
|
+
return [];
|
|
23256
|
+
}
|
|
23138
23257
|
function objectOf(value2) {
|
|
23139
23258
|
return value2 !== null && typeof value2 === "object" && !Array.isArray(value2) ? value2 : void 0;
|
|
23140
23259
|
}
|
|
@@ -23167,6 +23286,18 @@ function normalizeClaudeLiveLine(line, state) {
|
|
|
23167
23286
|
const failed = parsed.is_error === true || parsed.subtype === "error";
|
|
23168
23287
|
return [liveEvent(state, itemId, "control", failed ? "turn_failed" : "turn_completed", jsonOf(parsed))];
|
|
23169
23288
|
}
|
|
23289
|
+
if (parsed.type === "system") return subagentTaskEvents(parsed, state);
|
|
23290
|
+
if (parsed.type === "assistant") {
|
|
23291
|
+
const parent = stringOf(parsed.parent_tool_use_id);
|
|
23292
|
+
const hit = parent ? subagentCallOf(objectOf(parsed.message)) : void 0;
|
|
23293
|
+
if (parent && hit) {
|
|
23294
|
+
const calls = state.subagentCalls.get(parent) ?? /* @__PURE__ */ new Map();
|
|
23295
|
+
recordSubagentCall(calls, hit.id, hit.call);
|
|
23296
|
+
state.subagentCalls.set(parent, calls);
|
|
23297
|
+
}
|
|
23298
|
+
return [];
|
|
23299
|
+
}
|
|
23300
|
+
if ((parsed.type === "user" || parsed.type === "stream_event") && stringOf(parsed.parent_tool_use_id)) return [];
|
|
23170
23301
|
if (parsed.type === "user") {
|
|
23171
23302
|
const content3 = Array.isArray(objectOf(parsed.message)?.content) ? objectOf(parsed.message).content : [];
|
|
23172
23303
|
return content3.flatMap((block) => {
|
|
@@ -23237,19 +23368,21 @@ function normalizeClaudeStreamLine(line) {
|
|
|
23237
23368
|
const message = parsed["message"];
|
|
23238
23369
|
const content3 = Array.isArray(message?.content) ? message.content : [];
|
|
23239
23370
|
const out = [];
|
|
23371
|
+
const parentToolCallId = stringOf(parsed["parent_tool_use_id"]);
|
|
23372
|
+
const sub = parentToolCallId ? { parentToolCallId } : {};
|
|
23240
23373
|
for (const block of content3) {
|
|
23241
23374
|
switch (block["type"]) {
|
|
23242
23375
|
case "text":
|
|
23243
|
-
if (type === "assistant") out.push({ kind: "message", payload: { text: block["text"] } });
|
|
23376
|
+
if (type === "assistant") out.push({ kind: "message", payload: { text: block["text"], ...sub } });
|
|
23244
23377
|
break;
|
|
23245
23378
|
case "thinking":
|
|
23246
|
-
out.push({ kind: "thought", payload: { text: block["thinking"] } });
|
|
23379
|
+
out.push({ kind: "thought", payload: { text: block["thinking"], ...sub } });
|
|
23247
23380
|
break;
|
|
23248
23381
|
case "tool_use":
|
|
23249
|
-
out.push({ kind: "tool_use", payload: { id: block["id"], name: block["name"], input: block["input"] } });
|
|
23382
|
+
out.push({ kind: "tool_use", payload: { id: block["id"], name: block["name"], input: block["input"], ...sub } });
|
|
23250
23383
|
break;
|
|
23251
23384
|
case "tool_result":
|
|
23252
|
-
out.push({ kind: "tool_result", payload: { tool_use_id: block["tool_use_id"], content: block["content"], is_error: block["is_error"] ?? false } });
|
|
23385
|
+
out.push({ kind: "tool_result", payload: { tool_use_id: block["tool_use_id"], content: block["content"], is_error: block["is_error"] ?? false, ...sub } });
|
|
23253
23386
|
break;
|
|
23254
23387
|
default:
|
|
23255
23388
|
break;
|
|
@@ -23400,7 +23533,7 @@ function classifyExit(result) {
|
|
|
23400
23533
|
if (status === 429 || status === 529) return "rate-limit";
|
|
23401
23534
|
return "error";
|
|
23402
23535
|
}
|
|
23403
|
-
var import_node_child_process3, import_node_crypto8, fs7, path7, readline, CLAUDE_BLOCKED_FLAGS, ONE_SHOT_UNSAFE_TOOLS, ClaudeCodeAdapter;
|
|
23536
|
+
var import_node_child_process3, import_node_crypto8, fs7, path7, readline, CLAUDE_BLOCKED_FLAGS, SUBAGENT_TRANSCRIPT_MAX_BYTES, SUBAGENT_TERMINAL, ONE_SHOT_UNSAFE_TOOLS, ClaudeCodeAdapter;
|
|
23404
23537
|
var init_claude_code = __esm({
|
|
23405
23538
|
"../adapters/src/claude-code/index.ts"() {
|
|
23406
23539
|
"use strict";
|
|
@@ -23415,6 +23548,7 @@ var init_claude_code = __esm({
|
|
|
23415
23548
|
init_resume_classify();
|
|
23416
23549
|
init_root_bypass();
|
|
23417
23550
|
init_session_paths();
|
|
23551
|
+
init_src();
|
|
23418
23552
|
init_transcript();
|
|
23419
23553
|
init_filter_extra_args();
|
|
23420
23554
|
CLAUDE_BLOCKED_FLAGS = /* @__PURE__ */ new Map([
|
|
@@ -23445,6 +23579,13 @@ var init_claude_code = __esm({
|
|
|
23445
23579
|
["--include-partial-messages", "boolean"]
|
|
23446
23580
|
// 同上
|
|
23447
23581
|
]);
|
|
23582
|
+
SUBAGENT_TRANSCRIPT_MAX_BYTES = 32 * 1024 * 1024;
|
|
23583
|
+
SUBAGENT_TERMINAL = {
|
|
23584
|
+
completed: "completed",
|
|
23585
|
+
failed: "failed",
|
|
23586
|
+
killed: "stopped",
|
|
23587
|
+
stopped: "stopped"
|
|
23588
|
+
};
|
|
23448
23589
|
ONE_SHOT_UNSAFE_TOOLS = ["ScheduleWakeup", "CronCreate", "CronDelete", "CronList"];
|
|
23449
23590
|
ClaudeCodeAdapter = class {
|
|
23450
23591
|
constructor(opts = {}) {
|
|
@@ -23670,7 +23811,7 @@ var init_claude_code = __esm({
|
|
|
23670
23811
|
const usageAcc = newClaudeUsageAcc();
|
|
23671
23812
|
let sessionModel;
|
|
23672
23813
|
const outputCbs = [];
|
|
23673
|
-
const liveParser = createClaudeLiveParserState(`claude-live:${id}
|
|
23814
|
+
const liveParser = createClaudeLiveParserState(`claude-live:${id}`, { readSubagentUsage: readSubagentTranscriptUsage });
|
|
23674
23815
|
if (this.opts.streamJson) {
|
|
23675
23816
|
const rl = readline.createInterface({ input: child.stdout });
|
|
23676
23817
|
rl.on("line", (line) => {
|
|
@@ -28919,6 +29060,14 @@ var init_keys = __esm({
|
|
|
28919
29060
|
});
|
|
28920
29061
|
|
|
28921
29062
|
// ../adapters/src/_core/normalizer/normalizer.ts
|
|
29063
|
+
function parentToolCallIdOf(payload) {
|
|
29064
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) return void 0;
|
|
29065
|
+
const id = payload.parentToolCallId;
|
|
29066
|
+
return typeof id === "string" && id !== "" ? id : void 0;
|
|
29067
|
+
}
|
|
29068
|
+
function textBlocksOf(blocks) {
|
|
29069
|
+
return blocks.map((b2) => b2 && typeof b2 === "object" && typeof b2.text === "string" ? b2.text : "").filter(Boolean).join("\n");
|
|
29070
|
+
}
|
|
28922
29071
|
var ProviderStreamNormalizer;
|
|
28923
29072
|
var init_normalizer = __esm({
|
|
28924
29073
|
"../adapters/src/_core/normalizer/normalizer.ts"() {
|
|
@@ -28955,6 +29104,8 @@ var init_normalizer = __esm({
|
|
|
28955
29104
|
producedAny = false;
|
|
28956
29105
|
/** Receipts wait for a whole output block; they never split its bytes. */
|
|
28957
29106
|
pendingInputs = /* @__PURE__ */ new Map();
|
|
29107
|
+
/** 子代理正文/思考块的序号(它们没有 provider id)。严格递增、turn 收尾清零。 */
|
|
29108
|
+
subagentBlocks = 0;
|
|
28958
29109
|
constructor(opts) {
|
|
28959
29110
|
this.providerName = opts.providerName;
|
|
28960
29111
|
this.hasLiveProtocol = opts.hasLiveProtocol === true;
|
|
@@ -28975,6 +29126,11 @@ var init_normalizer = __esm({
|
|
|
28975
29126
|
}
|
|
28976
29127
|
/** 遥测事件。 */
|
|
28977
29128
|
onTelemetry(event) {
|
|
29129
|
+
const parentToolCallId = parentToolCallIdOf(event.payload);
|
|
29130
|
+
if (parentToolCallId) {
|
|
29131
|
+
this.subagentItem(event, parentToolCallId);
|
|
29132
|
+
return;
|
|
29133
|
+
}
|
|
28978
29134
|
if (this.hasLiveProtocol && event.kind !== "tool_use") return;
|
|
28979
29135
|
if (event.kind === "message" && this.sawTextOutput) return;
|
|
28980
29136
|
const part = chatPartFromTrajectoryEvent(event);
|
|
@@ -29008,6 +29164,17 @@ var init_normalizer = __esm({
|
|
|
29008
29164
|
this.closeOpen("completed");
|
|
29009
29165
|
return;
|
|
29010
29166
|
}
|
|
29167
|
+
if (event.itemType === "control" && payload.code === SUBAGENT_TASK_CODE && typeof payload.toolCallId === "string" && payload.task && typeof payload.task === "object") {
|
|
29168
|
+
this.emitItem({
|
|
29169
|
+
key: providerItemKey(this.providerName, event.itemId),
|
|
29170
|
+
kind: "control",
|
|
29171
|
+
role: "assistant",
|
|
29172
|
+
origin: "live",
|
|
29173
|
+
opShape: { op: "set_status", status: "completed" },
|
|
29174
|
+
attrs: { code: SUBAGENT_TASK_CODE, toolCallId: payload.toolCallId, task: payload.task }
|
|
29175
|
+
});
|
|
29176
|
+
return;
|
|
29177
|
+
}
|
|
29011
29178
|
this.turnId = event.turnId || this.turnId;
|
|
29012
29179
|
if (event.operation === "turn_completed" || event.operation === "turn_failed") {
|
|
29013
29180
|
this.turnFinished(event.operation === "turn_failed" ? "failed" : "completed");
|
|
@@ -29041,11 +29208,52 @@ var init_normalizer = __esm({
|
|
|
29041
29208
|
}
|
|
29042
29209
|
if (event.operation === "completed" && event.itemType === "tool" && event.payload !== void 0) {
|
|
29043
29210
|
const id = typeof payload.tool_use_id === "string" ? payload.tool_use_id : event.itemId;
|
|
29044
|
-
const output = typeof payload.content === "string" ? payload.content : typeof payload.output === "string" ? payload.output : "";
|
|
29211
|
+
const output = typeof payload.content === "string" ? payload.content : Array.isArray(payload.content) ? textBlocksOf(payload.content) : typeof payload.output === "string" ? payload.output : "";
|
|
29045
29212
|
this.toolResult("live", id, void 0, output, payload.is_error === true);
|
|
29046
29213
|
return;
|
|
29047
29214
|
}
|
|
29048
29215
|
}
|
|
29216
|
+
/**
|
|
29217
|
+
* 子代理内部的一块(带 parentToolCallId 的 telemetry)。子代理没有 partial stream,每块到达时
|
|
29218
|
+
* 就是完整的,所以不走散文的「开一段 → 续写」,也不过认领闸、不关主线程开着的那段——后台子代理
|
|
29219
|
+
* 与主线程并发时,主线程正文不能被它切成几截。
|
|
29220
|
+
*/
|
|
29221
|
+
subagentItem(event, parentToolCallId) {
|
|
29222
|
+
const part = chatPartFromTrajectoryEvent(event);
|
|
29223
|
+
if (!part) return;
|
|
29224
|
+
const sub = { parentToolCallId };
|
|
29225
|
+
if (part.type === "text" || part.type === "thinking") {
|
|
29226
|
+
const kind = part.type;
|
|
29227
|
+
const key = providerItemKey(this.providerName, `sub:${parentToolCallId}:${kind}`, this.subagentBlocks++);
|
|
29228
|
+
this.emitItem({ key, kind, role: "assistant", origin: "telemetry", opShape: { op: "set_text", text: part.text ?? "" }, attrs: sub });
|
|
29229
|
+
this.emitItem({ key, kind, role: "assistant", origin: "telemetry", opShape: { op: "set_status", status: "completed" }, attrs: sub });
|
|
29230
|
+
return;
|
|
29231
|
+
}
|
|
29232
|
+
if (part.type === "tool_use") {
|
|
29233
|
+
const id = part.toolCallId;
|
|
29234
|
+
this.emitItem({
|
|
29235
|
+
key: id ? providerItemKey(this.providerName, `tool_use:${id}`) : this.nextFallbackKey("tool_call"),
|
|
29236
|
+
kind: "tool_call",
|
|
29237
|
+
role: "assistant",
|
|
29238
|
+
origin: "telemetry",
|
|
29239
|
+
opShape: { op: "patch_input", input: part.input ?? null },
|
|
29240
|
+
attrs: { toolName: part.toolName ?? "tool", ...id ? { toolCallId: id } : {}, ...sub }
|
|
29241
|
+
});
|
|
29242
|
+
return;
|
|
29243
|
+
}
|
|
29244
|
+
if (part.type === "tool_result") {
|
|
29245
|
+
const id = part.toolCallId;
|
|
29246
|
+
const output = part.output ?? "";
|
|
29247
|
+
this.emitItem({
|
|
29248
|
+
key: id ? providerItemKey(this.providerName, `tool_result:${id}`) : this.nextFallbackKey("tool_result"),
|
|
29249
|
+
kind: "tool_result",
|
|
29250
|
+
role: "assistant",
|
|
29251
|
+
origin: "telemetry",
|
|
29252
|
+
opShape: { op: "set_text", text: output },
|
|
29253
|
+
attrs: { output, isError: part.isError === true, ...id ? { toolCallId: id } : {}, ...sub }
|
|
29254
|
+
});
|
|
29255
|
+
}
|
|
29256
|
+
}
|
|
29049
29257
|
// ── turn 生命周期 ──────────────────────────────────────────────────────────
|
|
29050
29258
|
/** turn 收尾:关掉开着的散文、清兜底 index、报一条 turn 信号(服务端据此清 itemKeyMap)。 */
|
|
29051
29259
|
turnFinished(signal) {
|
|
@@ -29057,6 +29265,7 @@ var init_normalizer = __esm({
|
|
|
29057
29265
|
this.closedKeys.clear();
|
|
29058
29266
|
this.sawTextOutput = false;
|
|
29059
29267
|
this.producedAny = false;
|
|
29268
|
+
this.subagentBlocks = 0;
|
|
29060
29269
|
if (!produced) return;
|
|
29061
29270
|
this.emit({ normalizedVersion: NORMALIZED_PROVIDER_EVENT_VERSION, type: "turn", turnId: this.turnId, signal });
|
|
29062
29271
|
}
|
|
@@ -29282,6 +29491,341 @@ var init_src6 = __esm({
|
|
|
29282
29491
|
}
|
|
29283
29492
|
});
|
|
29284
29493
|
|
|
29494
|
+
// ../server/src/domains/actors/model-pricing.ts
|
|
29495
|
+
function lookupInMap(map, prefixKeys, candidates) {
|
|
29496
|
+
for (const candidate of candidates) {
|
|
29497
|
+
const exact = map instanceof Map ? map.get(candidate) : map[candidate];
|
|
29498
|
+
if (exact) return exact;
|
|
29499
|
+
}
|
|
29500
|
+
const prefix = prefixKeys.find((p2) => candidates.some((candidate) => candidate.startsWith(`${p2}-`) || candidate.startsWith(`${p2}:`)));
|
|
29501
|
+
if (!prefix) return null;
|
|
29502
|
+
return map instanceof Map ? map.get(prefix) ?? null : map[prefix] ?? null;
|
|
29503
|
+
}
|
|
29504
|
+
function stripBracketTier(model) {
|
|
29505
|
+
return model.replace(/\[[^\]]*\]/g, "").trim();
|
|
29506
|
+
}
|
|
29507
|
+
function modelCandidates(model) {
|
|
29508
|
+
const normalized4 = model.trim().toLowerCase();
|
|
29509
|
+
if (!normalized4) return [];
|
|
29510
|
+
const base = [
|
|
29511
|
+
normalized4,
|
|
29512
|
+
normalized4.includes(":") ? normalized4.slice(normalized4.lastIndexOf(":") + 1) : "",
|
|
29513
|
+
normalized4.includes("/") ? normalized4.slice(normalized4.lastIndexOf("/") + 1) : ""
|
|
29514
|
+
].filter(Boolean);
|
|
29515
|
+
const stripped = base.map(stripBracketTier).filter((m2) => m2 && !base.includes(m2));
|
|
29516
|
+
return [...base, ...new Set(stripped)];
|
|
29517
|
+
}
|
|
29518
|
+
function setModelPriceCacheLoader(loader) {
|
|
29519
|
+
cacheLoader = loader;
|
|
29520
|
+
}
|
|
29521
|
+
async function warmModelPriceCache() {
|
|
29522
|
+
if (!cacheLoader) return 0;
|
|
29523
|
+
try {
|
|
29524
|
+
const next = await cacheLoader();
|
|
29525
|
+
dbPrices = next;
|
|
29526
|
+
dbPrefixKeys = [...next.keys()].sort((a, b2) => b2.length - a.length);
|
|
29527
|
+
cacheLoadedAt = Date.now();
|
|
29528
|
+
return next.size;
|
|
29529
|
+
} catch (err) {
|
|
29530
|
+
console.warn(`[model-pricing] \u9884\u70ED\u4EF7\u683C\u7F13\u5B58\u5931\u8D25\uFF0C\u6CBF\u7528\u9759\u6001\u5FEB\u7167\uFF1A${String(err)}`);
|
|
29531
|
+
return 0;
|
|
29532
|
+
}
|
|
29533
|
+
}
|
|
29534
|
+
function maybeRefreshCache() {
|
|
29535
|
+
if (!cacheLoader) return;
|
|
29536
|
+
if (dbPrices && Date.now() - cacheLoadedAt < CACHE_TTL_MS2) return;
|
|
29537
|
+
if (cacheRefreshInFlight) return;
|
|
29538
|
+
cacheRefreshInFlight = warmModelPriceCache().catch(() => 0).then(() => {
|
|
29539
|
+
cacheRefreshInFlight = null;
|
|
29540
|
+
});
|
|
29541
|
+
}
|
|
29542
|
+
function priceForModel(model) {
|
|
29543
|
+
if (!model) return null;
|
|
29544
|
+
const candidates = modelCandidates(model);
|
|
29545
|
+
if (candidates.length === 0) return null;
|
|
29546
|
+
maybeRefreshCache();
|
|
29547
|
+
if (dbPrices && dbPrices.size > 0) {
|
|
29548
|
+
const fromDb = lookupInMap(dbPrices, dbPrefixKeys, candidates);
|
|
29549
|
+
if (fromDb) return fromDb;
|
|
29550
|
+
}
|
|
29551
|
+
return lookupInMap(MODEL_PRICES, STATIC_PREFIX_PRICES, candidates);
|
|
29552
|
+
}
|
|
29553
|
+
function estimateUsageCostBreakdown(model, usage) {
|
|
29554
|
+
const price = priceForModel(model);
|
|
29555
|
+
if (!price) return null;
|
|
29556
|
+
const inputTokens = Math.max(usage.inputTokens ?? 0, 0);
|
|
29557
|
+
const outputTokens = Math.max(usage.outputTokens ?? 0, 0);
|
|
29558
|
+
const cacheReadTokens = Math.max(usage.cacheReadTokens ?? 0, 0);
|
|
29559
|
+
const cacheCreationTokens = Math.max(usage.cacheCreationTokens ?? 0, 0);
|
|
29560
|
+
const cacheReadPrice = price.cachedInputPerMillion ?? price.inputPerMillion * 0.1;
|
|
29561
|
+
return {
|
|
29562
|
+
currency: price.currency,
|
|
29563
|
+
inputMicros: Math.round(inputTokens * price.inputPerMillion / 1e6 * 1e6),
|
|
29564
|
+
cacheMicros: Math.round(
|
|
29565
|
+
(cacheCreationTokens * price.inputPerMillion + cacheReadTokens * cacheReadPrice) / 1e6 * 1e6
|
|
29566
|
+
),
|
|
29567
|
+
outputMicros: Math.round(outputTokens * price.outputPerMillion / 1e6 * 1e6)
|
|
29568
|
+
};
|
|
29569
|
+
}
|
|
29570
|
+
function estimateUsageCost(model, usage) {
|
|
29571
|
+
const breakdown = estimateUsageCostBreakdown(model, usage);
|
|
29572
|
+
if (!breakdown) return null;
|
|
29573
|
+
return {
|
|
29574
|
+
currency: breakdown.currency,
|
|
29575
|
+
micros: breakdown.inputMicros + breakdown.cacheMicros + breakdown.outputMicros
|
|
29576
|
+
};
|
|
29577
|
+
}
|
|
29578
|
+
function displayCostUsdMicros(model, usage) {
|
|
29579
|
+
const stored = Math.max(usage.costUsdMicros ?? 0, 0);
|
|
29580
|
+
if (stored > 0) return stored;
|
|
29581
|
+
const estimated = estimateUsageCost(model, usage);
|
|
29582
|
+
if (!estimated || estimated.micros <= 0) return 0;
|
|
29583
|
+
if (estimated.currency === "USD") return estimated.micros;
|
|
29584
|
+
return Math.round(estimated.micros / DISPLAY_CNY_PER_USD);
|
|
29585
|
+
}
|
|
29586
|
+
var FOREIGN_MODEL_MARKUP, usd, cny, MODEL_PRICES, STATIC_PREFIX_PRICES, CACHE_TTL_MS2, dbPrices, dbPrefixKeys, cacheLoadedAt, cacheLoader, cacheRefreshInFlight;
|
|
29587
|
+
var init_model_pricing = __esm({
|
|
29588
|
+
"../server/src/domains/actors/model-pricing.ts"() {
|
|
29589
|
+
"use strict";
|
|
29590
|
+
init_src();
|
|
29591
|
+
FOREIGN_MODEL_MARKUP = 1.08;
|
|
29592
|
+
usd = (inputPerMillion, outputPerMillion, cachedInputPerMillion) => ({
|
|
29593
|
+
currency: "USD",
|
|
29594
|
+
inputPerMillion: inputPerMillion * FOREIGN_MODEL_MARKUP,
|
|
29595
|
+
outputPerMillion: outputPerMillion * FOREIGN_MODEL_MARKUP,
|
|
29596
|
+
...cachedInputPerMillion !== void 0 ? { cachedInputPerMillion: cachedInputPerMillion * FOREIGN_MODEL_MARKUP } : {}
|
|
29597
|
+
});
|
|
29598
|
+
cny = (inputPerMillion, outputPerMillion, cachedInputPerMillion) => ({
|
|
29599
|
+
currency: "CNY",
|
|
29600
|
+
inputPerMillion,
|
|
29601
|
+
outputPerMillion,
|
|
29602
|
+
...cachedInputPerMillion !== void 0 ? { cachedInputPerMillion } : {}
|
|
29603
|
+
});
|
|
29604
|
+
MODEL_PRICES = {
|
|
29605
|
+
"gpt-5.5": usd(5, 30, 0.5),
|
|
29606
|
+
"gpt-5.5-pro": usd(30, 180),
|
|
29607
|
+
"chat-latest": usd(5, 30, 0.5),
|
|
29608
|
+
"gpt-5.4-mini": usd(0.75, 4.5, 0.075),
|
|
29609
|
+
"gpt-5.4-nano": usd(0.2, 1.25, 0.02),
|
|
29610
|
+
"gpt-5.4": usd(2.5, 15, 0.25),
|
|
29611
|
+
"gpt-5.4-pro": usd(30, 180),
|
|
29612
|
+
"gpt-5.3-codex": usd(1.75, 14, 0.175),
|
|
29613
|
+
"gpt-5.2": usd(1.75, 14, 0.175),
|
|
29614
|
+
"gpt-5.2-chat-latest": usd(1.75, 14, 0.175),
|
|
29615
|
+
"gpt-5.2-pro": usd(21, 168),
|
|
29616
|
+
"gpt-5.2-codex": usd(1.75, 14, 0.175),
|
|
29617
|
+
"gpt-5.1": usd(1.25, 10, 0.125),
|
|
29618
|
+
"gpt-5.1-chat-latest": usd(1.25, 10, 0.125),
|
|
29619
|
+
"gpt-5.1-codex": usd(1.25, 10, 0.125),
|
|
29620
|
+
"gpt-5.1-codex-max": usd(1.25, 10, 0.125),
|
|
29621
|
+
"gpt-5.1-codex-mini": usd(0.25, 2, 0.025),
|
|
29622
|
+
"gpt-5-pro": usd(15, 120),
|
|
29623
|
+
"gpt-5-codex": usd(1.25, 10, 0.125),
|
|
29624
|
+
"gpt-5-search-api": usd(1.25, 10, 0.125),
|
|
29625
|
+
"gpt-5": usd(1.25, 10, 0.125),
|
|
29626
|
+
"gpt-5-mini": usd(0.25, 2, 0.025),
|
|
29627
|
+
"gpt-5-nano": usd(0.05, 0.4, 5e-3),
|
|
29628
|
+
"gpt-5-chat-latest": usd(1.25, 10, 0.125),
|
|
29629
|
+
"gpt-4.1": usd(2, 8, 0.5),
|
|
29630
|
+
"gpt-4.1-2025-04-14": usd(2, 8, 0.5),
|
|
29631
|
+
"gpt-4.1-mini": usd(0.4, 1.6, 0.1),
|
|
29632
|
+
"gpt-4.1-mini-2025-04-14": usd(0.4, 1.6, 0.1),
|
|
29633
|
+
"gpt-4.1-nano": usd(0.1, 0.4, 0.025),
|
|
29634
|
+
"gpt-4.1-nano-2025-04-14": usd(0.1, 0.4, 0.025),
|
|
29635
|
+
"o4-mini": usd(1.1, 4.4, 0.275),
|
|
29636
|
+
// o3 / o3-mini 在 codex 静态目录里可选,却一直不在价目快照里(费用记 0)。
|
|
29637
|
+
// 这两行按 OpenAI 公开价填,不是智增增快照里的行;供应商价目表同步到时以 DB 为准。
|
|
29638
|
+
"o3": usd(2, 8),
|
|
29639
|
+
"o3-mini": usd(1.1, 4.4),
|
|
29640
|
+
"claude-fable-5-1": usd(10, 50),
|
|
29641
|
+
"claude-fable-5": usd(10, 50),
|
|
29642
|
+
"claude-mythos-5-1": usd(10, 50),
|
|
29643
|
+
"claude-mythos-5": usd(10, 50),
|
|
29644
|
+
// claude-opus-5 是 Claude Code 当代默认款,却一直不在这张快照里:查不到价 → 费用记 0
|
|
29645
|
+
// (与 2026-09-04 那次 `claude-opus-5[1m]` 记 0 同一类坑)。按 Opus 档 $5/$25 补上。
|
|
29646
|
+
"claude-opus-5": usd(5, 25),
|
|
29647
|
+
"claude-opus-4-8": usd(5, 25),
|
|
29648
|
+
"claude-opus-4-7": usd(5, 25),
|
|
29649
|
+
"claude-sonnet-5": usd(2, 10),
|
|
29650
|
+
"claude-sonnet-4-6": usd(3, 15),
|
|
29651
|
+
"claude-opus-4-6": usd(5, 25),
|
|
29652
|
+
"claude-opus-4-5-20251101": usd(5, 25),
|
|
29653
|
+
"claude-opus-4-5": usd(5, 25),
|
|
29654
|
+
"claude-sonnet-4-5-20250929": usd(3, 15),
|
|
29655
|
+
// 短名同样要有:前缀比对是「表里的键是模型名的前缀」,带日期的那行匹配不上不带日期的短名。
|
|
29656
|
+
// claude-sonnet-4-5 从 2026-07-04 起就在目录里可选,却一直查不到价(费用记 0),本次一并补。
|
|
29657
|
+
"claude-sonnet-4-5": usd(3, 15),
|
|
29658
|
+
"claude-opus-4-1-20250805": usd(15, 75),
|
|
29659
|
+
"claude-opus-4-20250514": usd(15, 75),
|
|
29660
|
+
"claude-sonnet-4-20250514": usd(3, 15),
|
|
29661
|
+
"claude-3-7-sonnet-20250219": usd(3, 15),
|
|
29662
|
+
"claude-3-5-sonnet-20241022": usd(3, 15),
|
|
29663
|
+
"claude-3-5-sonnet-20240620": usd(3, 15),
|
|
29664
|
+
"claude-3-sonnet-20240229": usd(3, 15),
|
|
29665
|
+
"claude-haiku-4-5-20251001": usd(1, 5),
|
|
29666
|
+
// codebuddy 目录用点号写法(claude-sonnet-4.6),与上面的连字符写法是同一批模型,
|
|
29667
|
+
// 但字符串对不上就查不到价 → 记 0。同价另起别名行。
|
|
29668
|
+
"claude-sonnet-4.6": usd(3, 15),
|
|
29669
|
+
"claude-opus-4.7": usd(5, 25),
|
|
29670
|
+
"gemini-3.1-pro": usd(2, 12),
|
|
29671
|
+
"gemini-3-pro-preview": usd(2, 12),
|
|
29672
|
+
// Claude Code 回报的可能是不带日期的短名,短名匹配不上带日期的那行(前缀比对是「表里的键是模型名的前缀」)。
|
|
29673
|
+
"claude-haiku-4-5": usd(1, 5),
|
|
29674
|
+
"gemini-3.5-flash": usd(1.5, 9),
|
|
29675
|
+
"gemini-3.1-pro-preview": usd(2, 12),
|
|
29676
|
+
"gemini-3.1-pro-preview-customtools": usd(2, 12),
|
|
29677
|
+
"gemini-3.1-flash-lite-preview": usd(0.25, 1.5),
|
|
29678
|
+
"gemini-3-flash-preview": usd(0.5, 3),
|
|
29679
|
+
"gemini-2.5-pro": usd(1.25, 10),
|
|
29680
|
+
"gemini-2.5-flash": usd(0.3, 2.5),
|
|
29681
|
+
"gemini-2.5-flash-lite": usd(0.1, 0.4),
|
|
29682
|
+
"gemini-2.5-flash-preview-09-2025": usd(0.3, 2.5),
|
|
29683
|
+
"gemini-2.0-flash": usd(0.1, 0.4),
|
|
29684
|
+
"deepseek-v4-flash": cny(1, 2, 0.02),
|
|
29685
|
+
"deepseek-v4-pro": cny(3, 6, 0.025),
|
|
29686
|
+
"deepseek-chat": cny(2, 3),
|
|
29687
|
+
"deepseek-reasoner": cny(2, 3),
|
|
29688
|
+
"deepseek-v3.2": cny(2, 3),
|
|
29689
|
+
"deepseek-coder": cny(2, 3),
|
|
29690
|
+
"deepseek-r1": cny(4, 16),
|
|
29691
|
+
"deepseek-r1-0528": cny(4, 16),
|
|
29692
|
+
"deepseek-v3": cny(2, 8),
|
|
29693
|
+
"deepseek-v3-0324": cny(2, 8),
|
|
29694
|
+
"deepseek-v3.1": cny(4, 12),
|
|
29695
|
+
"qwen3-max": cny(6, 24),
|
|
29696
|
+
"qwen3-max-preview": cny(6, 24),
|
|
29697
|
+
"qwen3-coder-plus": cny(4, 16),
|
|
29698
|
+
"qwen3-235b-a22b": cny(4, 40),
|
|
29699
|
+
"qwen3-32b": cny(2, 20),
|
|
29700
|
+
"qwen3-30b-a3b": cny(1.5, 15),
|
|
29701
|
+
"qwen3-14b": cny(1, 10),
|
|
29702
|
+
"qwen3-8b": cny(0.5, 5),
|
|
29703
|
+
"qwen3-4b": cny(0.3, 3),
|
|
29704
|
+
"qwen3-1.7b": cny(0.3, 3),
|
|
29705
|
+
"qwen3-0.6b": cny(0.3, 3),
|
|
29706
|
+
"qwq-plus": cny(1.6, 4),
|
|
29707
|
+
"qwq-plus-latest": cny(1.6, 4),
|
|
29708
|
+
"qwq-plus-2025-03-05": cny(1.6, 4),
|
|
29709
|
+
"kimi-k2.7-code": cny(6.5, 27),
|
|
29710
|
+
"kimi-k2.6": cny(6.5, 27),
|
|
29711
|
+
"kimi-k2.5": cny(4, 21),
|
|
29712
|
+
"kimi-k2-0905-preview": cny(4, 16),
|
|
29713
|
+
"kimi-k2-0711-preview": cny(4, 16),
|
|
29714
|
+
"kimi-k2-turbo-preview": cny(8, 58)
|
|
29715
|
+
};
|
|
29716
|
+
STATIC_PREFIX_PRICES = Object.keys(MODEL_PRICES).sort((a, b2) => b2.length - a.length);
|
|
29717
|
+
CACHE_TTL_MS2 = 5 * 6e4;
|
|
29718
|
+
dbPrices = null;
|
|
29719
|
+
dbPrefixKeys = [];
|
|
29720
|
+
cacheLoadedAt = 0;
|
|
29721
|
+
cacheLoader = null;
|
|
29722
|
+
cacheRefreshInFlight = null;
|
|
29723
|
+
}
|
|
29724
|
+
});
|
|
29725
|
+
|
|
29726
|
+
// ../server/src/domains/usage/accounting.ts
|
|
29727
|
+
function nonNegative(v2) {
|
|
29728
|
+
return Math.max(v2 ?? 0, 0);
|
|
29729
|
+
}
|
|
29730
|
+
function resolvedModel(model) {
|
|
29731
|
+
const trimmed = model?.trim();
|
|
29732
|
+
return trimmed ? trimmed : null;
|
|
29733
|
+
}
|
|
29734
|
+
function splitByWeight(total, w2) {
|
|
29735
|
+
const sum = w2.input + w2.cache + w2.output;
|
|
29736
|
+
if (total === 0) return { input: 0, cache: 0, output: 0 };
|
|
29737
|
+
if (sum <= 0) return { input: 0, cache: 0, output: total };
|
|
29738
|
+
const input = Math.round(total * w2.input / sum);
|
|
29739
|
+
const cache = Math.round(total * w2.cache / sum);
|
|
29740
|
+
return { input, cache, output: total - input - cache };
|
|
29741
|
+
}
|
|
29742
|
+
function toDisplayUsd(currency, micros) {
|
|
29743
|
+
return currency === "USD" ? micros : Math.round(micros / DISPLAY_CNY_PER_USD);
|
|
29744
|
+
}
|
|
29745
|
+
function accountUsage(model, usage) {
|
|
29746
|
+
const resolved = resolvedModel(model);
|
|
29747
|
+
if (!resolved || !usage) return null;
|
|
29748
|
+
const input = nonNegative(usage.inputTokens);
|
|
29749
|
+
const output = nonNegative(usage.outputTokens);
|
|
29750
|
+
const cache = nonNegative(usage.cacheReadTokens) + nonNegative(usage.cacheCreationTokens);
|
|
29751
|
+
const tokens = { input, cache, output, total: input + cache + output };
|
|
29752
|
+
const estimated = estimateUsageCostBreakdown(resolved, usage);
|
|
29753
|
+
const weights = estimated ? { input: estimated.inputMicros, cache: estimated.cacheMicros, output: estimated.outputMicros } : null;
|
|
29754
|
+
const reported = Math.max(usage.costUsdMicros ?? 0, 0);
|
|
29755
|
+
if (reported > 0) {
|
|
29756
|
+
const parts = weights && estimated?.currency === "USD" ? splitByWeight(reported, weights) : { input: 0, cache: 0, output: reported };
|
|
29757
|
+
return {
|
|
29758
|
+
tokens,
|
|
29759
|
+
currency: "USD",
|
|
29760
|
+
amountMicros: reported,
|
|
29761
|
+
parts,
|
|
29762
|
+
displayUsdMicros: reported,
|
|
29763
|
+
displayParts: parts,
|
|
29764
|
+
source: "reported"
|
|
29765
|
+
};
|
|
29766
|
+
}
|
|
29767
|
+
if (estimated && weights) {
|
|
29768
|
+
const amount = weights.input + weights.cache + weights.output;
|
|
29769
|
+
const displayUsdMicros = toDisplayUsd(estimated.currency, amount);
|
|
29770
|
+
return {
|
|
29771
|
+
tokens,
|
|
29772
|
+
currency: estimated.currency,
|
|
29773
|
+
amountMicros: amount,
|
|
29774
|
+
parts: weights,
|
|
29775
|
+
displayUsdMicros,
|
|
29776
|
+
displayParts: estimated.currency === "USD" ? weights : splitByWeight(displayUsdMicros, weights),
|
|
29777
|
+
source: "estimated"
|
|
29778
|
+
};
|
|
29779
|
+
}
|
|
29780
|
+
return {
|
|
29781
|
+
tokens,
|
|
29782
|
+
currency: "USD",
|
|
29783
|
+
amountMicros: 0,
|
|
29784
|
+
parts: { input: 0, cache: 0, output: 0 },
|
|
29785
|
+
displayUsdMicros: 0,
|
|
29786
|
+
displayParts: { input: 0, cache: 0, output: 0 },
|
|
29787
|
+
source: "unpriced"
|
|
29788
|
+
};
|
|
29789
|
+
}
|
|
29790
|
+
function isUnpriced(account) {
|
|
29791
|
+
return account.source === "unpriced" && account.tokens.total > 0;
|
|
29792
|
+
}
|
|
29793
|
+
var init_accounting = __esm({
|
|
29794
|
+
"../server/src/domains/usage/accounting.ts"() {
|
|
29795
|
+
"use strict";
|
|
29796
|
+
init_model_pricing();
|
|
29797
|
+
}
|
|
29798
|
+
});
|
|
29799
|
+
|
|
29800
|
+
// ../server/src/subagent-cost.ts
|
|
29801
|
+
function estimateSubagentCostUsdMicros(usage) {
|
|
29802
|
+
if (!usage) return void 0;
|
|
29803
|
+
const models = Object.entries(usage.byModel);
|
|
29804
|
+
if (models.length === 0) return void 0;
|
|
29805
|
+
let total = 0;
|
|
29806
|
+
for (const [model, tokens] of models) {
|
|
29807
|
+
const account = accountUsage(model, { ...tokens, costUsdMicros: null });
|
|
29808
|
+
if (!account || account.source !== "estimated") return void 0;
|
|
29809
|
+
total += account.displayUsdMicros;
|
|
29810
|
+
}
|
|
29811
|
+
return total;
|
|
29812
|
+
}
|
|
29813
|
+
function withSubagentCostEstimate(event) {
|
|
29814
|
+
if (event.type !== "item" || event.attrs?.code !== SUBAGENT_TASK_CODE) return event;
|
|
29815
|
+
const task = event.attrs.task;
|
|
29816
|
+
if (!task?.usage || task.estimatedCostUsdMicros !== void 0) return event;
|
|
29817
|
+
const estimatedCostUsdMicros = estimateSubagentCostUsdMicros(task.usage);
|
|
29818
|
+
if (estimatedCostUsdMicros === void 0) return event;
|
|
29819
|
+
return { ...event, attrs: { ...event.attrs, task: { ...task, estimatedCostUsdMicros } } };
|
|
29820
|
+
}
|
|
29821
|
+
var init_subagent_cost = __esm({
|
|
29822
|
+
"../server/src/subagent-cost.ts"() {
|
|
29823
|
+
"use strict";
|
|
29824
|
+
init_src();
|
|
29825
|
+
init_accounting();
|
|
29826
|
+
}
|
|
29827
|
+
});
|
|
29828
|
+
|
|
29285
29829
|
// ../contract/src/chat-item.ts
|
|
29286
29830
|
var CHAT_ITEM_TERMINAL_STATUSES, isTerminalChatItemStatus, CHAT_ITEM_META_LEGACY_CONTENT;
|
|
29287
29831
|
var init_chat_item = __esm({
|
|
@@ -29305,8 +29849,9 @@ async function resolveChatItemsTurnId(items, messageId, fallback) {
|
|
|
29305
29849
|
const existing = await items.listItemsByMessage(messageId).catch(() => []);
|
|
29306
29850
|
return existing.length ? existing[existing.length - 1].turnId : fallback;
|
|
29307
29851
|
}
|
|
29308
|
-
function projectsIntoContent(kind, role, origin, telemetryTextInContent) {
|
|
29852
|
+
function projectsIntoContent(kind, role, origin, telemetryTextInContent, attrs = {}) {
|
|
29309
29853
|
if (kind !== "text" || role !== "assistant") return false;
|
|
29854
|
+
if (attrs.parentToolCallId) return false;
|
|
29310
29855
|
switch (origin) {
|
|
29311
29856
|
case "stdout":
|
|
29312
29857
|
case "live":
|
|
@@ -29322,6 +29867,7 @@ var init_chat_item_ledger = __esm({
|
|
|
29322
29867
|
"../server/src/chat-item-ledger.ts"() {
|
|
29323
29868
|
"use strict";
|
|
29324
29869
|
init_src();
|
|
29870
|
+
init_subagent_cost();
|
|
29325
29871
|
init_chat_item();
|
|
29326
29872
|
import_node_crypto15 = require("node:crypto");
|
|
29327
29873
|
CHAT_ITEMS_DOUBLE_WRITE_ENV = "OASIS_CHAT_ITEMS_DOUBLE_WRITE";
|
|
@@ -29422,7 +29968,8 @@ var init_chat_item_ledger = __esm({
|
|
|
29422
29968
|
* 应用一条归一层事件。**这是 provider 正文进入系统的唯一入口**(ADR D4(b))——
|
|
29423
29969
|
* `LiveChatRegistry.applyNormalizedEvent` 与两条恢复路都经它,别再开第二个口子。
|
|
29424
29970
|
*/
|
|
29425
|
-
apply(
|
|
29971
|
+
apply(raw) {
|
|
29972
|
+
const event = withSubagentCostEstimate(raw);
|
|
29426
29973
|
if (event.type === "turn") {
|
|
29427
29974
|
this.itemKeyMap.clear();
|
|
29428
29975
|
this.lastTurnId = null;
|
|
@@ -29661,7 +30208,7 @@ var init_chat_item_ledger = __esm({
|
|
|
29661
30208
|
// ── 内部:建行与应用 op ────────────────────────────────────────────────────
|
|
29662
30209
|
createFrom(event) {
|
|
29663
30210
|
const attrs = event.attrs ?? {};
|
|
29664
|
-
const inContent = projectsIntoContent(event.kind, event.role, event.origin, this.telemetryTextInContent);
|
|
30211
|
+
const inContent = projectsIntoContent(event.kind, event.role, event.origin, this.telemetryTextInContent, attrs);
|
|
29665
30212
|
const text5 = event.opShape.op === "append_text" || event.opShape.op === "set_text" ? event.opShape.text : "";
|
|
29666
30213
|
const status = event.kind === "text" || event.kind === "thinking" ? "streaming" : "completed";
|
|
29667
30214
|
const id = this.insert({
|
|
@@ -29733,25 +30280,33 @@ var init_chat_item_ledger = __esm({
|
|
|
29733
30280
|
}
|
|
29734
30281
|
/** 按 kind 折出落库 payload。**唯一一处** payload 形状定义,别在别处再拼一遍。 */
|
|
29735
30282
|
payloadOf(row) {
|
|
30283
|
+
const parent = row.attrs.parentToolCallId ? { parentToolCallId: row.attrs.parentToolCallId } : {};
|
|
29736
30284
|
switch (row.kind) {
|
|
29737
30285
|
case "text":
|
|
29738
30286
|
case "thinking":
|
|
29739
|
-
return { text: row.text };
|
|
30287
|
+
return { text: row.text, ...parent };
|
|
29740
30288
|
case "tool_call":
|
|
29741
30289
|
return {
|
|
29742
30290
|
toolName: row.attrs.toolName ?? "tool",
|
|
29743
30291
|
...row.attrs.toolCallId ? { toolCallId: row.attrs.toolCallId } : {},
|
|
29744
|
-
input: row.attrs.input ?? null
|
|
30292
|
+
input: row.attrs.input ?? null,
|
|
30293
|
+
...parent
|
|
29745
30294
|
};
|
|
29746
30295
|
case "tool_result":
|
|
29747
30296
|
return {
|
|
29748
30297
|
...row.attrs.toolCallId ? { toolCallId: row.attrs.toolCallId } : {},
|
|
29749
30298
|
...row.attrs.toolName ? { toolName: row.attrs.toolName } : {},
|
|
29750
30299
|
output: row.attrs.output ?? row.text,
|
|
29751
|
-
...row.attrs.isError === true ? { isError: true } : {}
|
|
30300
|
+
...row.attrs.isError === true ? { isError: true } : {},
|
|
30301
|
+
...parent
|
|
29752
30302
|
};
|
|
29753
30303
|
case "control":
|
|
29754
|
-
return {
|
|
30304
|
+
return {
|
|
30305
|
+
code: row.attrs.code ?? "control",
|
|
30306
|
+
...row.attrs.note ? { note: row.attrs.note } : {},
|
|
30307
|
+
...row.attrs.code === SUBAGENT_TASK_CODE && row.attrs.toolCallId ? { toolCallId: row.attrs.toolCallId } : {},
|
|
30308
|
+
...row.attrs.code === SUBAGENT_TASK_CODE && row.attrs.task ? { task: row.attrs.task } : {}
|
|
30309
|
+
};
|
|
29755
30310
|
}
|
|
29756
30311
|
}
|
|
29757
30312
|
insert(input) {
|
|
@@ -160569,7 +161124,9 @@ function v3StartedPayload(role, attrs, itemType, kind) {
|
|
|
160569
161124
|
if (attrs?.input !== void 0) base.input = attrs.input;
|
|
160570
161125
|
if (attrs?.output !== void 0) base.output = attrs.output;
|
|
160571
161126
|
if (attrs?.isError !== void 0) base.isError = attrs.isError;
|
|
161127
|
+
if (attrs?.parentToolCallId) base.parentToolCallId = attrs.parentToolCallId;
|
|
160572
161128
|
if (itemType === "control" && kind === "control" && attrs?.code) base.code = attrs.code;
|
|
161129
|
+
if (itemType === "control" && attrs?.task) base.task = attrs.task;
|
|
160573
161130
|
return base;
|
|
160574
161131
|
}
|
|
160575
161132
|
var DEFAULT_BUFFER_MAX, DEFAULT_GRACE_MS, DEFAULT_LIVE_COALESCE_MS, DEFAULT_LIVE_COALESCE_MAX_CHUNKS, DEFAULT_LIVE_COALESCE_MAX_CHARS, LiveChatRegistry;
|
|
@@ -160577,6 +161134,7 @@ var init_live_chat = __esm({
|
|
|
160577
161134
|
"../server/src/live-chat.ts"() {
|
|
160578
161135
|
"use strict";
|
|
160579
161136
|
init_chat_item_ledger();
|
|
161137
|
+
init_subagent_cost();
|
|
160580
161138
|
DEFAULT_BUFFER_MAX = 4e3;
|
|
160581
161139
|
DEFAULT_GRACE_MS = 6e4;
|
|
160582
161140
|
DEFAULT_LIVE_COALESCE_MS = 24;
|
|
@@ -160744,7 +161302,8 @@ var init_live_chat = __esm({
|
|
|
160744
161302
|
*
|
|
160745
161303
|
* 账本坏掉不影响对话;v3 emit 抛异常也不影响 v2 通路与账本落盘——两条独立通路。
|
|
160746
161304
|
*/
|
|
160747
|
-
applyNormalizedEvent(turn,
|
|
161305
|
+
applyNormalizedEvent(turn, raw) {
|
|
161306
|
+
const event = withSubagentCostEstimate(raw);
|
|
160748
161307
|
if (event.type === "item" && event.kind === "control" && event.attrs?.code === "input_consumed") {
|
|
160749
161308
|
const key = event.attrs.clientMessageKey;
|
|
160750
161309
|
if (key) turn.inputReceipts.get(key)?.consume();
|
|
@@ -207537,6 +208096,7 @@ ${composed}`;
|
|
|
207537
208096
|
session.onTelemetry?.((event) => {
|
|
207538
208097
|
if (hasLiveProtocol && event.kind !== "tool_use") return;
|
|
207539
208098
|
if (event.kind === "message" && sawTextOutput) return;
|
|
208099
|
+
if (typeof event.payload?.parentToolCallId === "string") return;
|
|
207540
208100
|
if (liveProtocol && live && !hasLiveProtocol) {
|
|
207541
208101
|
const payload = event.payload && typeof event.payload === "object" && !Array.isArray(event.payload) ? event.payload : {};
|
|
207542
208102
|
const itemId = event.kind === "tool_use" ? typeof payload.id === "string" ? payload.id : `${liveTurnId}:tool` : event.kind === "tool_result" ? typeof payload.tool_use_id === "string" ? payload.tool_use_id : `${liveTurnId}:tool` : event.kind === "thought" ? `${liveTurnId}:thinking` : `${liveTurnId}:message`;
|
|
@@ -211986,312 +212546,6 @@ var init_uncategorized_project = __esm({
|
|
|
211986
212546
|
}
|
|
211987
212547
|
});
|
|
211988
212548
|
|
|
211989
|
-
// ../server/src/domains/actors/model-pricing.ts
|
|
211990
|
-
function lookupInMap(map, prefixKeys, candidates) {
|
|
211991
|
-
for (const candidate of candidates) {
|
|
211992
|
-
const exact = map instanceof Map ? map.get(candidate) : map[candidate];
|
|
211993
|
-
if (exact) return exact;
|
|
211994
|
-
}
|
|
211995
|
-
const prefix = prefixKeys.find((p2) => candidates.some((candidate) => candidate.startsWith(`${p2}-`) || candidate.startsWith(`${p2}:`)));
|
|
211996
|
-
if (!prefix) return null;
|
|
211997
|
-
return map instanceof Map ? map.get(prefix) ?? null : map[prefix] ?? null;
|
|
211998
|
-
}
|
|
211999
|
-
function stripBracketTier(model) {
|
|
212000
|
-
return model.replace(/\[[^\]]*\]/g, "").trim();
|
|
212001
|
-
}
|
|
212002
|
-
function modelCandidates(model) {
|
|
212003
|
-
const normalized4 = model.trim().toLowerCase();
|
|
212004
|
-
if (!normalized4) return [];
|
|
212005
|
-
const base = [
|
|
212006
|
-
normalized4,
|
|
212007
|
-
normalized4.includes(":") ? normalized4.slice(normalized4.lastIndexOf(":") + 1) : "",
|
|
212008
|
-
normalized4.includes("/") ? normalized4.slice(normalized4.lastIndexOf("/") + 1) : ""
|
|
212009
|
-
].filter(Boolean);
|
|
212010
|
-
const stripped = base.map(stripBracketTier).filter((m2) => m2 && !base.includes(m2));
|
|
212011
|
-
return [...base, ...new Set(stripped)];
|
|
212012
|
-
}
|
|
212013
|
-
function setModelPriceCacheLoader(loader) {
|
|
212014
|
-
cacheLoader = loader;
|
|
212015
|
-
}
|
|
212016
|
-
async function warmModelPriceCache() {
|
|
212017
|
-
if (!cacheLoader) return 0;
|
|
212018
|
-
try {
|
|
212019
|
-
const next = await cacheLoader();
|
|
212020
|
-
dbPrices = next;
|
|
212021
|
-
dbPrefixKeys = [...next.keys()].sort((a, b2) => b2.length - a.length);
|
|
212022
|
-
cacheLoadedAt = Date.now();
|
|
212023
|
-
return next.size;
|
|
212024
|
-
} catch (err) {
|
|
212025
|
-
console.warn(`[model-pricing] \u9884\u70ED\u4EF7\u683C\u7F13\u5B58\u5931\u8D25\uFF0C\u6CBF\u7528\u9759\u6001\u5FEB\u7167\uFF1A${String(err)}`);
|
|
212026
|
-
return 0;
|
|
212027
|
-
}
|
|
212028
|
-
}
|
|
212029
|
-
function maybeRefreshCache() {
|
|
212030
|
-
if (!cacheLoader) return;
|
|
212031
|
-
if (dbPrices && Date.now() - cacheLoadedAt < CACHE_TTL_MS2) return;
|
|
212032
|
-
if (cacheRefreshInFlight) return;
|
|
212033
|
-
cacheRefreshInFlight = warmModelPriceCache().catch(() => 0).then(() => {
|
|
212034
|
-
cacheRefreshInFlight = null;
|
|
212035
|
-
});
|
|
212036
|
-
}
|
|
212037
|
-
function priceForModel(model) {
|
|
212038
|
-
if (!model) return null;
|
|
212039
|
-
const candidates = modelCandidates(model);
|
|
212040
|
-
if (candidates.length === 0) return null;
|
|
212041
|
-
maybeRefreshCache();
|
|
212042
|
-
if (dbPrices && dbPrices.size > 0) {
|
|
212043
|
-
const fromDb = lookupInMap(dbPrices, dbPrefixKeys, candidates);
|
|
212044
|
-
if (fromDb) return fromDb;
|
|
212045
|
-
}
|
|
212046
|
-
return lookupInMap(MODEL_PRICES, STATIC_PREFIX_PRICES, candidates);
|
|
212047
|
-
}
|
|
212048
|
-
function estimateUsageCostBreakdown(model, usage) {
|
|
212049
|
-
const price = priceForModel(model);
|
|
212050
|
-
if (!price) return null;
|
|
212051
|
-
const inputTokens = Math.max(usage.inputTokens ?? 0, 0);
|
|
212052
|
-
const outputTokens = Math.max(usage.outputTokens ?? 0, 0);
|
|
212053
|
-
const cacheReadTokens = Math.max(usage.cacheReadTokens ?? 0, 0);
|
|
212054
|
-
const cacheCreationTokens = Math.max(usage.cacheCreationTokens ?? 0, 0);
|
|
212055
|
-
const cacheReadPrice = price.cachedInputPerMillion ?? price.inputPerMillion * 0.1;
|
|
212056
|
-
return {
|
|
212057
|
-
currency: price.currency,
|
|
212058
|
-
inputMicros: Math.round(inputTokens * price.inputPerMillion / 1e6 * 1e6),
|
|
212059
|
-
cacheMicros: Math.round(
|
|
212060
|
-
(cacheCreationTokens * price.inputPerMillion + cacheReadTokens * cacheReadPrice) / 1e6 * 1e6
|
|
212061
|
-
),
|
|
212062
|
-
outputMicros: Math.round(outputTokens * price.outputPerMillion / 1e6 * 1e6)
|
|
212063
|
-
};
|
|
212064
|
-
}
|
|
212065
|
-
function estimateUsageCost(model, usage) {
|
|
212066
|
-
const breakdown = estimateUsageCostBreakdown(model, usage);
|
|
212067
|
-
if (!breakdown) return null;
|
|
212068
|
-
return {
|
|
212069
|
-
currency: breakdown.currency,
|
|
212070
|
-
micros: breakdown.inputMicros + breakdown.cacheMicros + breakdown.outputMicros
|
|
212071
|
-
};
|
|
212072
|
-
}
|
|
212073
|
-
function displayCostUsdMicros(model, usage) {
|
|
212074
|
-
const stored = Math.max(usage.costUsdMicros ?? 0, 0);
|
|
212075
|
-
if (stored > 0) return stored;
|
|
212076
|
-
const estimated = estimateUsageCost(model, usage);
|
|
212077
|
-
if (!estimated || estimated.micros <= 0) return 0;
|
|
212078
|
-
if (estimated.currency === "USD") return estimated.micros;
|
|
212079
|
-
return Math.round(estimated.micros / DISPLAY_CNY_PER_USD);
|
|
212080
|
-
}
|
|
212081
|
-
var FOREIGN_MODEL_MARKUP, usd, cny, MODEL_PRICES, STATIC_PREFIX_PRICES, CACHE_TTL_MS2, dbPrices, dbPrefixKeys, cacheLoadedAt, cacheLoader, cacheRefreshInFlight;
|
|
212082
|
-
var init_model_pricing = __esm({
|
|
212083
|
-
"../server/src/domains/actors/model-pricing.ts"() {
|
|
212084
|
-
"use strict";
|
|
212085
|
-
init_src();
|
|
212086
|
-
FOREIGN_MODEL_MARKUP = 1.08;
|
|
212087
|
-
usd = (inputPerMillion, outputPerMillion, cachedInputPerMillion) => ({
|
|
212088
|
-
currency: "USD",
|
|
212089
|
-
inputPerMillion: inputPerMillion * FOREIGN_MODEL_MARKUP,
|
|
212090
|
-
outputPerMillion: outputPerMillion * FOREIGN_MODEL_MARKUP,
|
|
212091
|
-
...cachedInputPerMillion !== void 0 ? { cachedInputPerMillion: cachedInputPerMillion * FOREIGN_MODEL_MARKUP } : {}
|
|
212092
|
-
});
|
|
212093
|
-
cny = (inputPerMillion, outputPerMillion, cachedInputPerMillion) => ({
|
|
212094
|
-
currency: "CNY",
|
|
212095
|
-
inputPerMillion,
|
|
212096
|
-
outputPerMillion,
|
|
212097
|
-
...cachedInputPerMillion !== void 0 ? { cachedInputPerMillion } : {}
|
|
212098
|
-
});
|
|
212099
|
-
MODEL_PRICES = {
|
|
212100
|
-
"gpt-5.5": usd(5, 30, 0.5),
|
|
212101
|
-
"gpt-5.5-pro": usd(30, 180),
|
|
212102
|
-
"chat-latest": usd(5, 30, 0.5),
|
|
212103
|
-
"gpt-5.4-mini": usd(0.75, 4.5, 0.075),
|
|
212104
|
-
"gpt-5.4-nano": usd(0.2, 1.25, 0.02),
|
|
212105
|
-
"gpt-5.4": usd(2.5, 15, 0.25),
|
|
212106
|
-
"gpt-5.4-pro": usd(30, 180),
|
|
212107
|
-
"gpt-5.3-codex": usd(1.75, 14, 0.175),
|
|
212108
|
-
"gpt-5.2": usd(1.75, 14, 0.175),
|
|
212109
|
-
"gpt-5.2-chat-latest": usd(1.75, 14, 0.175),
|
|
212110
|
-
"gpt-5.2-pro": usd(21, 168),
|
|
212111
|
-
"gpt-5.2-codex": usd(1.75, 14, 0.175),
|
|
212112
|
-
"gpt-5.1": usd(1.25, 10, 0.125),
|
|
212113
|
-
"gpt-5.1-chat-latest": usd(1.25, 10, 0.125),
|
|
212114
|
-
"gpt-5.1-codex": usd(1.25, 10, 0.125),
|
|
212115
|
-
"gpt-5.1-codex-max": usd(1.25, 10, 0.125),
|
|
212116
|
-
"gpt-5.1-codex-mini": usd(0.25, 2, 0.025),
|
|
212117
|
-
"gpt-5-pro": usd(15, 120),
|
|
212118
|
-
"gpt-5-codex": usd(1.25, 10, 0.125),
|
|
212119
|
-
"gpt-5-search-api": usd(1.25, 10, 0.125),
|
|
212120
|
-
"gpt-5": usd(1.25, 10, 0.125),
|
|
212121
|
-
"gpt-5-mini": usd(0.25, 2, 0.025),
|
|
212122
|
-
"gpt-5-nano": usd(0.05, 0.4, 5e-3),
|
|
212123
|
-
"gpt-5-chat-latest": usd(1.25, 10, 0.125),
|
|
212124
|
-
"gpt-4.1": usd(2, 8, 0.5),
|
|
212125
|
-
"gpt-4.1-2025-04-14": usd(2, 8, 0.5),
|
|
212126
|
-
"gpt-4.1-mini": usd(0.4, 1.6, 0.1),
|
|
212127
|
-
"gpt-4.1-mini-2025-04-14": usd(0.4, 1.6, 0.1),
|
|
212128
|
-
"gpt-4.1-nano": usd(0.1, 0.4, 0.025),
|
|
212129
|
-
"gpt-4.1-nano-2025-04-14": usd(0.1, 0.4, 0.025),
|
|
212130
|
-
"o4-mini": usd(1.1, 4.4, 0.275),
|
|
212131
|
-
// o3 / o3-mini 在 codex 静态目录里可选,却一直不在价目快照里(费用记 0)。
|
|
212132
|
-
// 这两行按 OpenAI 公开价填,不是智增增快照里的行;供应商价目表同步到时以 DB 为准。
|
|
212133
|
-
"o3": usd(2, 8),
|
|
212134
|
-
"o3-mini": usd(1.1, 4.4),
|
|
212135
|
-
"claude-fable-5-1": usd(10, 50),
|
|
212136
|
-
"claude-fable-5": usd(10, 50),
|
|
212137
|
-
"claude-mythos-5-1": usd(10, 50),
|
|
212138
|
-
"claude-mythos-5": usd(10, 50),
|
|
212139
|
-
// claude-opus-5 是 Claude Code 当代默认款,却一直不在这张快照里:查不到价 → 费用记 0
|
|
212140
|
-
// (与 2026-09-04 那次 `claude-opus-5[1m]` 记 0 同一类坑)。按 Opus 档 $5/$25 补上。
|
|
212141
|
-
"claude-opus-5": usd(5, 25),
|
|
212142
|
-
"claude-opus-4-8": usd(5, 25),
|
|
212143
|
-
"claude-opus-4-7": usd(5, 25),
|
|
212144
|
-
"claude-sonnet-5": usd(2, 10),
|
|
212145
|
-
"claude-sonnet-4-6": usd(3, 15),
|
|
212146
|
-
"claude-opus-4-6": usd(5, 25),
|
|
212147
|
-
"claude-opus-4-5-20251101": usd(5, 25),
|
|
212148
|
-
"claude-opus-4-5": usd(5, 25),
|
|
212149
|
-
"claude-sonnet-4-5-20250929": usd(3, 15),
|
|
212150
|
-
// 短名同样要有:前缀比对是「表里的键是模型名的前缀」,带日期的那行匹配不上不带日期的短名。
|
|
212151
|
-
// claude-sonnet-4-5 从 2026-07-04 起就在目录里可选,却一直查不到价(费用记 0),本次一并补。
|
|
212152
|
-
"claude-sonnet-4-5": usd(3, 15),
|
|
212153
|
-
"claude-opus-4-1-20250805": usd(15, 75),
|
|
212154
|
-
"claude-opus-4-20250514": usd(15, 75),
|
|
212155
|
-
"claude-sonnet-4-20250514": usd(3, 15),
|
|
212156
|
-
"claude-3-7-sonnet-20250219": usd(3, 15),
|
|
212157
|
-
"claude-3-5-sonnet-20241022": usd(3, 15),
|
|
212158
|
-
"claude-3-5-sonnet-20240620": usd(3, 15),
|
|
212159
|
-
"claude-3-sonnet-20240229": usd(3, 15),
|
|
212160
|
-
"claude-haiku-4-5-20251001": usd(1, 5),
|
|
212161
|
-
// codebuddy 目录用点号写法(claude-sonnet-4.6),与上面的连字符写法是同一批模型,
|
|
212162
|
-
// 但字符串对不上就查不到价 → 记 0。同价另起别名行。
|
|
212163
|
-
"claude-sonnet-4.6": usd(3, 15),
|
|
212164
|
-
"claude-opus-4.7": usd(5, 25),
|
|
212165
|
-
"gemini-3.1-pro": usd(2, 12),
|
|
212166
|
-
"gemini-3-pro-preview": usd(2, 12),
|
|
212167
|
-
// Claude Code 回报的可能是不带日期的短名,短名匹配不上带日期的那行(前缀比对是「表里的键是模型名的前缀」)。
|
|
212168
|
-
"claude-haiku-4-5": usd(1, 5),
|
|
212169
|
-
"gemini-3.5-flash": usd(1.5, 9),
|
|
212170
|
-
"gemini-3.1-pro-preview": usd(2, 12),
|
|
212171
|
-
"gemini-3.1-pro-preview-customtools": usd(2, 12),
|
|
212172
|
-
"gemini-3.1-flash-lite-preview": usd(0.25, 1.5),
|
|
212173
|
-
"gemini-3-flash-preview": usd(0.5, 3),
|
|
212174
|
-
"gemini-2.5-pro": usd(1.25, 10),
|
|
212175
|
-
"gemini-2.5-flash": usd(0.3, 2.5),
|
|
212176
|
-
"gemini-2.5-flash-lite": usd(0.1, 0.4),
|
|
212177
|
-
"gemini-2.5-flash-preview-09-2025": usd(0.3, 2.5),
|
|
212178
|
-
"gemini-2.0-flash": usd(0.1, 0.4),
|
|
212179
|
-
"deepseek-v4-flash": cny(1, 2, 0.02),
|
|
212180
|
-
"deepseek-v4-pro": cny(3, 6, 0.025),
|
|
212181
|
-
"deepseek-chat": cny(2, 3),
|
|
212182
|
-
"deepseek-reasoner": cny(2, 3),
|
|
212183
|
-
"deepseek-v3.2": cny(2, 3),
|
|
212184
|
-
"deepseek-coder": cny(2, 3),
|
|
212185
|
-
"deepseek-r1": cny(4, 16),
|
|
212186
|
-
"deepseek-r1-0528": cny(4, 16),
|
|
212187
|
-
"deepseek-v3": cny(2, 8),
|
|
212188
|
-
"deepseek-v3-0324": cny(2, 8),
|
|
212189
|
-
"deepseek-v3.1": cny(4, 12),
|
|
212190
|
-
"qwen3-max": cny(6, 24),
|
|
212191
|
-
"qwen3-max-preview": cny(6, 24),
|
|
212192
|
-
"qwen3-coder-plus": cny(4, 16),
|
|
212193
|
-
"qwen3-235b-a22b": cny(4, 40),
|
|
212194
|
-
"qwen3-32b": cny(2, 20),
|
|
212195
|
-
"qwen3-30b-a3b": cny(1.5, 15),
|
|
212196
|
-
"qwen3-14b": cny(1, 10),
|
|
212197
|
-
"qwen3-8b": cny(0.5, 5),
|
|
212198
|
-
"qwen3-4b": cny(0.3, 3),
|
|
212199
|
-
"qwen3-1.7b": cny(0.3, 3),
|
|
212200
|
-
"qwen3-0.6b": cny(0.3, 3),
|
|
212201
|
-
"qwq-plus": cny(1.6, 4),
|
|
212202
|
-
"qwq-plus-latest": cny(1.6, 4),
|
|
212203
|
-
"qwq-plus-2025-03-05": cny(1.6, 4),
|
|
212204
|
-
"kimi-k2.7-code": cny(6.5, 27),
|
|
212205
|
-
"kimi-k2.6": cny(6.5, 27),
|
|
212206
|
-
"kimi-k2.5": cny(4, 21),
|
|
212207
|
-
"kimi-k2-0905-preview": cny(4, 16),
|
|
212208
|
-
"kimi-k2-0711-preview": cny(4, 16),
|
|
212209
|
-
"kimi-k2-turbo-preview": cny(8, 58)
|
|
212210
|
-
};
|
|
212211
|
-
STATIC_PREFIX_PRICES = Object.keys(MODEL_PRICES).sort((a, b2) => b2.length - a.length);
|
|
212212
|
-
CACHE_TTL_MS2 = 5 * 6e4;
|
|
212213
|
-
dbPrices = null;
|
|
212214
|
-
dbPrefixKeys = [];
|
|
212215
|
-
cacheLoadedAt = 0;
|
|
212216
|
-
cacheLoader = null;
|
|
212217
|
-
cacheRefreshInFlight = null;
|
|
212218
|
-
}
|
|
212219
|
-
});
|
|
212220
|
-
|
|
212221
|
-
// ../server/src/domains/usage/accounting.ts
|
|
212222
|
-
function nonNegative(v2) {
|
|
212223
|
-
return Math.max(v2 ?? 0, 0);
|
|
212224
|
-
}
|
|
212225
|
-
function resolvedModel(model) {
|
|
212226
|
-
const trimmed = model?.trim();
|
|
212227
|
-
return trimmed ? trimmed : null;
|
|
212228
|
-
}
|
|
212229
|
-
function splitByWeight(total, w2) {
|
|
212230
|
-
const sum = w2.input + w2.cache + w2.output;
|
|
212231
|
-
if (total === 0) return { input: 0, cache: 0, output: 0 };
|
|
212232
|
-
if (sum <= 0) return { input: 0, cache: 0, output: total };
|
|
212233
|
-
const input = Math.round(total * w2.input / sum);
|
|
212234
|
-
const cache = Math.round(total * w2.cache / sum);
|
|
212235
|
-
return { input, cache, output: total - input - cache };
|
|
212236
|
-
}
|
|
212237
|
-
function toDisplayUsd(currency, micros) {
|
|
212238
|
-
return currency === "USD" ? micros : Math.round(micros / DISPLAY_CNY_PER_USD);
|
|
212239
|
-
}
|
|
212240
|
-
function accountUsage(model, usage) {
|
|
212241
|
-
const resolved = resolvedModel(model);
|
|
212242
|
-
if (!resolved || !usage) return null;
|
|
212243
|
-
const input = nonNegative(usage.inputTokens);
|
|
212244
|
-
const output = nonNegative(usage.outputTokens);
|
|
212245
|
-
const cache = nonNegative(usage.cacheReadTokens) + nonNegative(usage.cacheCreationTokens);
|
|
212246
|
-
const tokens = { input, cache, output, total: input + cache + output };
|
|
212247
|
-
const estimated = estimateUsageCostBreakdown(resolved, usage);
|
|
212248
|
-
const weights = estimated ? { input: estimated.inputMicros, cache: estimated.cacheMicros, output: estimated.outputMicros } : null;
|
|
212249
|
-
const reported = Math.max(usage.costUsdMicros ?? 0, 0);
|
|
212250
|
-
if (reported > 0) {
|
|
212251
|
-
const parts = weights && estimated?.currency === "USD" ? splitByWeight(reported, weights) : { input: 0, cache: 0, output: reported };
|
|
212252
|
-
return {
|
|
212253
|
-
tokens,
|
|
212254
|
-
currency: "USD",
|
|
212255
|
-
amountMicros: reported,
|
|
212256
|
-
parts,
|
|
212257
|
-
displayUsdMicros: reported,
|
|
212258
|
-
displayParts: parts,
|
|
212259
|
-
source: "reported"
|
|
212260
|
-
};
|
|
212261
|
-
}
|
|
212262
|
-
if (estimated && weights) {
|
|
212263
|
-
const amount = weights.input + weights.cache + weights.output;
|
|
212264
|
-
const displayUsdMicros = toDisplayUsd(estimated.currency, amount);
|
|
212265
|
-
return {
|
|
212266
|
-
tokens,
|
|
212267
|
-
currency: estimated.currency,
|
|
212268
|
-
amountMicros: amount,
|
|
212269
|
-
parts: weights,
|
|
212270
|
-
displayUsdMicros,
|
|
212271
|
-
displayParts: estimated.currency === "USD" ? weights : splitByWeight(displayUsdMicros, weights),
|
|
212272
|
-
source: "estimated"
|
|
212273
|
-
};
|
|
212274
|
-
}
|
|
212275
|
-
return {
|
|
212276
|
-
tokens,
|
|
212277
|
-
currency: "USD",
|
|
212278
|
-
amountMicros: 0,
|
|
212279
|
-
parts: { input: 0, cache: 0, output: 0 },
|
|
212280
|
-
displayUsdMicros: 0,
|
|
212281
|
-
displayParts: { input: 0, cache: 0, output: 0 },
|
|
212282
|
-
source: "unpriced"
|
|
212283
|
-
};
|
|
212284
|
-
}
|
|
212285
|
-
function isUnpriced(account) {
|
|
212286
|
-
return account.source === "unpriced" && account.tokens.total > 0;
|
|
212287
|
-
}
|
|
212288
|
-
var init_accounting = __esm({
|
|
212289
|
-
"../server/src/domains/usage/accounting.ts"() {
|
|
212290
|
-
"use strict";
|
|
212291
|
-
init_model_pricing();
|
|
212292
|
-
}
|
|
212293
|
-
});
|
|
212294
|
-
|
|
212295
212549
|
// ../server/src/domains/actors/stats.ts
|
|
212296
212550
|
function emptyCostBreakdown() {
|
|
212297
212551
|
return {
|
|
@@ -274183,7 +274437,7 @@ function shimScript() {
|
|
|
274183
274437
|
}
|
|
274184
274438
|
|
|
274185
274439
|
// src/index.ts
|
|
274186
|
-
var PKG_VERSION = true ? "2.2.
|
|
274440
|
+
var PKG_VERSION = true ? "2.2.32" : "dev";
|
|
274187
274441
|
var LOCAL_BIN = localBin();
|
|
274188
274442
|
var NPM_PREFIX = npmPrefix();
|
|
274189
274443
|
var INSTANCE = DEFAULT_INSTANCE;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oasis_test_v2",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.32",
|
|
4
4
|
"description": "Oasis node daemon + CLI — background daemon, auto-start, full server CLI",
|
|
5
5
|
"bin": {
|
|
6
6
|
"oasis": "./dist/index.js"
|
|
@@ -26,6 +26,6 @@
|
|
|
26
26
|
"node": ">=20"
|
|
27
27
|
},
|
|
28
28
|
"oasisRelease": {
|
|
29
|
-
"sourceHead": "
|
|
29
|
+
"sourceHead": "7e66896a0213e95be3142f0ac6972054b10ea1e3"
|
|
30
30
|
}
|
|
31
31
|
}
|