negotium 0.2.15 → 0.2.17
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/agent-helpers.js +220 -32
- package/dist/agent-helpers.js.map +12 -12
- package/dist/background-bash.js.map +1 -1
- package/dist/browser-runtime.js.map +1 -1
- package/dist/{chunk-5g5a63vv.js → chunk-5cpdbbeh.js} +56 -6
- package/dist/{chunk-5g5a63vv.js.map → chunk-5cpdbbeh.js.map} +5 -5
- package/dist/hosted-agent.js +119 -9
- package/dist/hosted-agent.js.map +8 -8
- package/dist/main.js +931 -419
- package/dist/main.js.map +25 -24
- package/dist/mcp-factories.js +289 -42
- package/dist/mcp-factories.js.map +13 -13
- package/dist/prompts.js.map +1 -1
- package/dist/query-runtime.js.map +1 -1
- package/dist/registry.js +3 -3
- package/dist/registry.js.map +2 -2
- package/dist/rollout.js +1 -1
- package/dist/runtime/src/agents/codex-provider.ts +53 -2
- package/dist/runtime/src/agents/compaction-support.ts +1 -1
- package/dist/runtime/src/agents/maestro-provider.ts +3 -0
- package/dist/runtime/src/agents/rollout/codex.ts +62 -0
- package/dist/runtime/src/index.ts +1 -0
- package/dist/runtime/src/mcp/factories/token-stats.ts +33 -11
- package/dist/runtime/src/mcp/runtime-spec.ts +58 -1
- package/dist/runtime/src/node-host.ts +1 -0
- package/dist/runtime/src/runtime/turn-event-stream.ts +43 -2
- package/dist/runtime/src/runtime/turn-runner.ts +20 -9
- package/dist/runtime/src/storage/token-stats.ts +200 -19
- package/dist/runtime/src/types.ts +6 -0
- package/dist/runtime/src/version.ts +1 -1
- package/dist/runtime-helpers.js.map +1 -1
- package/dist/storage.js +112 -11
- package/dist/storage.js.map +4 -4
- package/dist/types/packages/core/src/agents/codex-provider.d.ts +13 -0
- package/dist/types/packages/core/src/agents/compaction-support.d.ts +1 -0
- package/dist/types/packages/core/src/agents/rollout/codex.d.ts +9 -0
- package/dist/types/packages/core/src/mcp/factories/token-stats.d.ts +4 -2
- package/dist/types/packages/core/src/runtime/turn-runner.d.ts +4 -0
- package/dist/types/packages/core/src/storage/token-stats.d.ts +35 -6
- package/dist/types/packages/core/src/types.d.ts +6 -0
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/dist/vault.js.map +1 -1
- package/package.json +2 -2
package/dist/mcp-factories.js
CHANGED
|
@@ -952,7 +952,7 @@ var init_claude_registry = __esm(() => {
|
|
|
952
952
|
});
|
|
953
953
|
|
|
954
954
|
// ../../packages/core/src/version.ts
|
|
955
|
-
var NEGOTIUM_VERSION = "0.2.
|
|
955
|
+
var NEGOTIUM_VERSION = "0.2.17";
|
|
956
956
|
|
|
957
957
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
958
958
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -1292,7 +1292,7 @@ var init_canonical_bridge_config = __esm(() => {
|
|
|
1292
1292
|
});
|
|
1293
1293
|
|
|
1294
1294
|
// ../../packages/core/src/mcp/runtime-spec.ts
|
|
1295
|
-
import { createHmac, timingSafeEqual } from "crypto";
|
|
1295
|
+
import { createHash, createHmac, timingSafeEqual } from "crypto";
|
|
1296
1296
|
function encodeTokenPart(value2) {
|
|
1297
1297
|
return Buffer.from(JSON.stringify(value2), "utf-8").toString("base64url");
|
|
1298
1298
|
}
|
|
@@ -1325,19 +1325,69 @@ function buildRuntimeMcpSpec(agent, ctx) {
|
|
|
1325
1325
|
return {
|
|
1326
1326
|
type: "sse",
|
|
1327
1327
|
url: `${base}/sse?${query}`,
|
|
1328
|
-
timeout: CLAUDE_MCP_TOOL_TIMEOUT_MS
|
|
1328
|
+
timeout: CLAUDE_MCP_TOOL_TIMEOUT_MS,
|
|
1329
|
+
...agent === "maestro" ? { lifecycle: "turn" } : {}
|
|
1329
1330
|
};
|
|
1330
1331
|
}
|
|
1332
|
+
function hostedMcpCacheIdentity(surface, ctx) {
|
|
1333
|
+
let semanticContext;
|
|
1334
|
+
switch (surface) {
|
|
1335
|
+
case "system-health":
|
|
1336
|
+
semanticContext = {};
|
|
1337
|
+
break;
|
|
1338
|
+
case "token-stats":
|
|
1339
|
+
case "agent-health":
|
|
1340
|
+
semanticContext = { userId: ctx.userId };
|
|
1341
|
+
break;
|
|
1342
|
+
case "task":
|
|
1343
|
+
semanticContext = {
|
|
1344
|
+
userId: ctx.userId,
|
|
1345
|
+
topicTitle: ctx.topicTitle,
|
|
1346
|
+
topicId: ctx.topicId ?? null
|
|
1347
|
+
};
|
|
1348
|
+
break;
|
|
1349
|
+
case "wiki":
|
|
1350
|
+
case "skills":
|
|
1351
|
+
semanticContext = {
|
|
1352
|
+
userId: ctx.userId,
|
|
1353
|
+
topicId: ctx.wikiTopicId ?? ctx.topicId ?? null
|
|
1354
|
+
};
|
|
1355
|
+
break;
|
|
1356
|
+
case "vault":
|
|
1357
|
+
semanticContext = { userId: ctx.userId, cwd: ctx.cwd, agent: ctx.agent };
|
|
1358
|
+
break;
|
|
1359
|
+
case "session-comm":
|
|
1360
|
+
semanticContext = {
|
|
1361
|
+
userId: ctx.userId,
|
|
1362
|
+
topicTitle: ctx.topicTitle,
|
|
1363
|
+
topicId: ctx.topicId ?? null,
|
|
1364
|
+
subagentParentTopicId: ctx.subagentParentTopicId ?? null,
|
|
1365
|
+
depth: ctx.depth ?? 0,
|
|
1366
|
+
silent: ctx.silent ?? false,
|
|
1367
|
+
agent: ctx.agent,
|
|
1368
|
+
peerBridge: ctx.peerBridge ?? null
|
|
1369
|
+
};
|
|
1370
|
+
break;
|
|
1371
|
+
}
|
|
1372
|
+
const digest = createHash("sha256").update(JSON.stringify([surface, semanticContext])).digest("hex").slice(0, 24);
|
|
1373
|
+
return `hosted:${surface}:${digest}`;
|
|
1374
|
+
}
|
|
1331
1375
|
function buildHostedMcpSpec(agent, surface, ctx) {
|
|
1332
1376
|
const token = issueHostedMcpToken(surface, ctx);
|
|
1333
1377
|
const base = `http://127.0.0.1:${runtimePort}${RUNTIME_MCP_BASE_PATH}/${surface}`;
|
|
1334
1378
|
const query = `token=${encodeURIComponent(token)}`;
|
|
1335
1379
|
if (agent === "codex")
|
|
1336
1380
|
return { url: `${base}/mcp?${query}` };
|
|
1381
|
+
const queryBound = surface === "session-comm" && (ctx.silent === true || ctx.peerBridge !== undefined);
|
|
1382
|
+
const lifecycle = queryBound ? "turn" : surface === "session-comm" ? "session" : "process";
|
|
1337
1383
|
return {
|
|
1338
1384
|
type: "sse",
|
|
1339
1385
|
url: `${base}/sse?${query}`,
|
|
1340
|
-
timeout: CLAUDE_MCP_TOOL_TIMEOUT_MS
|
|
1386
|
+
timeout: CLAUDE_MCP_TOOL_TIMEOUT_MS,
|
|
1387
|
+
...agent === "maestro" ? {
|
|
1388
|
+
lifecycle,
|
|
1389
|
+
cacheKey: hostedMcpCacheIdentity(surface, ctx)
|
|
1390
|
+
} : {}
|
|
1341
1391
|
};
|
|
1342
1392
|
}
|
|
1343
1393
|
var RUNTIME_MCP_KEY = "runtime", RUNTIME_MCP_BASE_PATH = "/mcp/runtime", TOKEN_TTL_MS, CLAUDE_MCP_TOOL_TIMEOUT_MS = 600000, runtimePort;
|
|
@@ -2190,9 +2240,9 @@ var init_sqlite = __esm(async () => {
|
|
|
2190
2240
|
});
|
|
2191
2241
|
|
|
2192
2242
|
// ../../packages/core/src/storage/vault-crypto-core.ts
|
|
2193
|
-
import { createCipheriv, createDecipheriv, createHash, randomBytes as randomBytes3 } from "crypto";
|
|
2243
|
+
import { createCipheriv, createDecipheriv, createHash as createHash2, randomBytes as randomBytes3 } from "crypto";
|
|
2194
2244
|
function encryptionKey(masterKey) {
|
|
2195
|
-
return
|
|
2245
|
+
return createHash2("sha256").update("otium-vault-value-v1\x00", "utf8").update(masterKey, "utf8").digest().subarray(0, KEY_BYTES);
|
|
2196
2246
|
}
|
|
2197
2247
|
function aad(userId, key) {
|
|
2198
2248
|
return Buffer.from(`${userId}\x00${key.toUpperCase()}`, "utf8");
|
|
@@ -2674,6 +2724,36 @@ function extractLatestCodexContextUsage(jsonl) {
|
|
|
2674
2724
|
}
|
|
2675
2725
|
return;
|
|
2676
2726
|
}
|
|
2727
|
+
function extractLatestCodexTokenTotals(jsonl) {
|
|
2728
|
+
const lines = jsonl.trimEnd().split(`
|
|
2729
|
+
`);
|
|
2730
|
+
for (let index = lines.length - 1;index >= 0; index -= 1) {
|
|
2731
|
+
try {
|
|
2732
|
+
const entry = JSON.parse(lines[index] ?? "");
|
|
2733
|
+
if (entry.type !== "event_msg" || entry.payload?.type !== "token_count")
|
|
2734
|
+
continue;
|
|
2735
|
+
const usage = entry.payload.info?.total_token_usage;
|
|
2736
|
+
if (!usage)
|
|
2737
|
+
continue;
|
|
2738
|
+
const values = [
|
|
2739
|
+
usage.input_tokens,
|
|
2740
|
+
usage.output_tokens,
|
|
2741
|
+
usage.cached_input_tokens,
|
|
2742
|
+
usage.cache_write_input_tokens
|
|
2743
|
+
];
|
|
2744
|
+
if (values.some((value2) => value2 !== undefined && (!Number.isFinite(value2) || value2 < 0))) {
|
|
2745
|
+
continue;
|
|
2746
|
+
}
|
|
2747
|
+
return {
|
|
2748
|
+
inputTokens: usage.input_tokens ?? 0,
|
|
2749
|
+
outputTokens: usage.output_tokens ?? 0,
|
|
2750
|
+
cachedInputTokens: usage.cached_input_tokens ?? 0,
|
|
2751
|
+
cacheWriteInputTokens: usage.cache_write_input_tokens ?? 0
|
|
2752
|
+
};
|
|
2753
|
+
} catch {}
|
|
2754
|
+
}
|
|
2755
|
+
return;
|
|
2756
|
+
}
|
|
2677
2757
|
function readLatestCodexContextUsage(threadId) {
|
|
2678
2758
|
const path = latestCodexRolloutPath(threadId);
|
|
2679
2759
|
if (!path)
|
|
@@ -2685,6 +2765,17 @@ function readLatestCodexContextUsage(threadId) {
|
|
|
2685
2765
|
return;
|
|
2686
2766
|
}
|
|
2687
2767
|
}
|
|
2768
|
+
function readLatestCodexTokenTotals(threadId) {
|
|
2769
|
+
const path = latestCodexRolloutPath(threadId);
|
|
2770
|
+
if (!path)
|
|
2771
|
+
return;
|
|
2772
|
+
try {
|
|
2773
|
+
return extractLatestCodexTokenTotals(readFileSync6(path, "utf8"));
|
|
2774
|
+
} catch (error) {
|
|
2775
|
+
logger.debug({ error, threadId }, "codex token totals: rollout read failed");
|
|
2776
|
+
return;
|
|
2777
|
+
}
|
|
2778
|
+
}
|
|
2688
2779
|
function migrateCodexRolloutNativeMultiAgentMetadata(threadId) {
|
|
2689
2780
|
const path = latestCodexRolloutPath(threadId);
|
|
2690
2781
|
if (!path)
|
|
@@ -6013,7 +6104,7 @@ var init_browser_profiles = __esm(async () => {
|
|
|
6013
6104
|
|
|
6014
6105
|
// ../../packages/core/src/platform/playwright/manager.ts
|
|
6015
6106
|
import { execFileSync as execFileSync4, spawn as spawn6 } from "child_process";
|
|
6016
|
-
import { createHash as
|
|
6107
|
+
import { createHash as createHash3, randomBytes as randomBytes6, timingSafeEqual as timingSafeEqual3 } from "crypto";
|
|
6017
6108
|
import {
|
|
6018
6109
|
cpSync,
|
|
6019
6110
|
existsSync as existsSync11,
|
|
@@ -6108,7 +6199,7 @@ function parseInstanceKey(instanceKey) {
|
|
|
6108
6199
|
};
|
|
6109
6200
|
}
|
|
6110
6201
|
function portFileName(instanceKey) {
|
|
6111
|
-
return
|
|
6202
|
+
return createHash3("sha256").update(instanceKey).digest("hex").slice(0, 24);
|
|
6112
6203
|
}
|
|
6113
6204
|
function writePortFile(instanceKey, port) {
|
|
6114
6205
|
try {
|
|
@@ -8909,6 +9000,7 @@ var init_tool_format = __esm(() => {
|
|
|
8909
9000
|
var exports_codex_provider = {};
|
|
8910
9001
|
__export(exports_codex_provider, {
|
|
8911
9002
|
toCodexMcpServers: () => toCodexMcpServers,
|
|
9003
|
+
normalizeCodexTurnUsage: () => normalizeCodexTurnUsage,
|
|
8912
9004
|
codexProvider: () => codexProvider
|
|
8913
9005
|
});
|
|
8914
9006
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
@@ -8916,6 +9008,20 @@ import { existsSync as existsSync15, readFileSync as readFileSync14, realpathSyn
|
|
|
8916
9008
|
import { homedir as homedir6 } from "os";
|
|
8917
9009
|
import { dirname as dirname11, isAbsolute as isAbsolute3, join as join16, relative, resolve as resolve12 } from "path";
|
|
8918
9010
|
import { Codex } from "@openai/codex-sdk";
|
|
9011
|
+
function sameCodexUsage(usage, total) {
|
|
9012
|
+
return usage.input_tokens === total.inputTokens && usage.output_tokens === total.outputTokens && (usage.cached_input_tokens ?? 0) === total.cachedInputTokens && (usage.cache_write_input_tokens ?? 0) === total.cacheWriteInputTokens;
|
|
9013
|
+
}
|
|
9014
|
+
function normalizeCodexTurnUsage(usage, baseline, rolloutTotal) {
|
|
9015
|
+
if (!baseline || !rolloutTotal || !sameCodexUsage(usage, rolloutTotal))
|
|
9016
|
+
return usage;
|
|
9017
|
+
const delta = (current2, previous) => current2 >= previous ? current2 - previous : current2;
|
|
9018
|
+
return {
|
|
9019
|
+
input_tokens: delta(rolloutTotal.inputTokens, baseline.inputTokens),
|
|
9020
|
+
output_tokens: delta(rolloutTotal.outputTokens, baseline.outputTokens),
|
|
9021
|
+
cached_input_tokens: delta(rolloutTotal.cachedInputTokens, baseline.cachedInputTokens),
|
|
9022
|
+
cache_write_input_tokens: delta(rolloutTotal.cacheWriteInputTokens, baseline.cacheWriteInputTokens)
|
|
9023
|
+
};
|
|
9024
|
+
}
|
|
8919
9025
|
function mapEffort(effort) {
|
|
8920
9026
|
if (!effort)
|
|
8921
9027
|
return;
|
|
@@ -9315,6 +9421,7 @@ async function* codexProvider(opts) {
|
|
|
9315
9421
|
...opts.effort ? { modelReasoningEffort: mapEffort(opts.effort) } : {}
|
|
9316
9422
|
};
|
|
9317
9423
|
let currentSessionId = opts.sessionId;
|
|
9424
|
+
let usageBaseline = currentSessionId ? readLatestCodexTokenTotals(currentSessionId) : undefined;
|
|
9318
9425
|
let thread = currentSessionId ? codex.resumeThread(currentSessionId, threadOptions) : codex.startThread(threadOptions);
|
|
9319
9426
|
let prompt = promptForThread(opts, true);
|
|
9320
9427
|
let agentTextSoFar = "";
|
|
@@ -9373,6 +9480,7 @@ async function* codexProvider(opts) {
|
|
|
9373
9480
|
thread = codex.startThread(threadOptions);
|
|
9374
9481
|
prompt = promptForThread(opts, true);
|
|
9375
9482
|
currentSessionId = undefined;
|
|
9483
|
+
usageBaseline = undefined;
|
|
9376
9484
|
startResult = await startStreamedWithTracking(thread, prompt, attemptAbort.signal, trackedPids);
|
|
9377
9485
|
}
|
|
9378
9486
|
if (attemptAbort.signal.aborted) {
|
|
@@ -9473,10 +9581,11 @@ async function* codexProvider(opts) {
|
|
|
9473
9581
|
break;
|
|
9474
9582
|
}
|
|
9475
9583
|
case "turn.completed": {
|
|
9476
|
-
const
|
|
9477
|
-
if (!
|
|
9584
|
+
const rawUsage = event.usage;
|
|
9585
|
+
if (!rawUsage)
|
|
9478
9586
|
break;
|
|
9479
9587
|
attemptCompleted = true;
|
|
9588
|
+
const usage = normalizeCodexTurnUsage(rawUsage, usageBaseline, currentSessionId ? readLatestCodexTokenTotals(currentSessionId) : undefined);
|
|
9480
9589
|
const contextUsage = currentSessionId ? readLatestCodexContextUsage(currentSessionId) : undefined;
|
|
9481
9590
|
yield {
|
|
9482
9591
|
type: "result",
|
|
@@ -9485,6 +9594,7 @@ async function* codexProvider(opts) {
|
|
|
9485
9594
|
usage: {
|
|
9486
9595
|
inputTokens: usage.input_tokens,
|
|
9487
9596
|
outputTokens: usage.output_tokens,
|
|
9597
|
+
cacheCreationInputTokens: usage.cache_write_input_tokens,
|
|
9488
9598
|
cacheReadInputTokens: usage.cached_input_tokens,
|
|
9489
9599
|
...contextUsage
|
|
9490
9600
|
}
|
|
@@ -9677,6 +9787,7 @@ function maestroProvider(opts) {
|
|
|
9677
9787
|
...opts,
|
|
9678
9788
|
enableToolSearch: !opts.toolPolicy && opts.enableToolSearch !== false,
|
|
9679
9789
|
toolResultTruncation: buildMaestroToolResultTruncation(opts),
|
|
9790
|
+
ephemeralSystemPrompt: opts.ephemeralSystemPrompt,
|
|
9680
9791
|
apiKeyOverrides: resolveMaestroApiKeyOverrides(userId),
|
|
9681
9792
|
agent: "maestro",
|
|
9682
9793
|
disallowedTools: buildMaestroDisallowedTools(callerDisallowedTools, opts.toolPolicy),
|
|
@@ -11839,7 +11950,7 @@ __export(exports_derive, {
|
|
|
11839
11950
|
TopicForkCompactionError: () => TopicForkCompactionError,
|
|
11840
11951
|
TopicDeriveBusyError: () => TopicDeriveBusyError
|
|
11841
11952
|
});
|
|
11842
|
-
import { createHash as
|
|
11953
|
+
import { createHash as createHash4, randomUUID as randomUUID11 } from "crypto";
|
|
11843
11954
|
import { mkdirSync as mkdirSync14, rmSync as rmSync5, unlinkSync as unlinkSync13 } from "fs";
|
|
11844
11955
|
function getTopics() {
|
|
11845
11956
|
return listTopics().filter((topic) => !isLegacySharedGeneral(topic.id));
|
|
@@ -11905,7 +12016,7 @@ function captureForkSnapshot(sourceTopicId, userId, topicTitle) {
|
|
|
11905
12016
|
maxRowid: messageRows.at(-1)?.rowid ?? 0
|
|
11906
12017
|
},
|
|
11907
12018
|
active: isTopicRunning(sourceTopicId),
|
|
11908
|
-
canonicalDigest:
|
|
12019
|
+
canonicalDigest: createHash4("sha256").update(entries.map((entry) => JSON.stringify(entry)).join(`
|
|
11909
12020
|
`)).digest("hex")
|
|
11910
12021
|
};
|
|
11911
12022
|
}
|
|
@@ -12398,7 +12509,7 @@ __export(exports_session_asks, {
|
|
|
12398
12509
|
clearPendingAsk: () => clearPendingAsk,
|
|
12399
12510
|
PENDING_ASK_TTL_MS: () => PENDING_ASK_TTL_MS
|
|
12400
12511
|
});
|
|
12401
|
-
import { createHash as
|
|
12512
|
+
import { createHash as createHash5 } from "crypto";
|
|
12402
12513
|
import {
|
|
12403
12514
|
closeSync as closeSync3,
|
|
12404
12515
|
mkdirSync as mkdirSync16,
|
|
@@ -12412,14 +12523,14 @@ import {
|
|
|
12412
12523
|
import { dirname as dirname14, join as join25 } from "path";
|
|
12413
12524
|
function pendingAskDir(userId) {
|
|
12414
12525
|
const rawUserId = String(userId);
|
|
12415
|
-
const safeUserId = /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${
|
|
12526
|
+
const safeUserId = /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash5("sha256").update(rawUserId).digest("hex")}`;
|
|
12416
12527
|
return join25(resolveStorageSessionAsksDir(), safeUserId);
|
|
12417
12528
|
}
|
|
12418
12529
|
function encodeAskKey(key) {
|
|
12419
12530
|
return JSON.stringify([key.from, key.to]);
|
|
12420
12531
|
}
|
|
12421
12532
|
function pendingAskPath(key) {
|
|
12422
|
-
const digest =
|
|
12533
|
+
const digest = createHash5("sha256").update(encodeAskKey(key)).digest("hex");
|
|
12423
12534
|
return join25(pendingAskDir(key.userId), `${ASK_FILENAME_PREFIX}${digest}.pending`);
|
|
12424
12535
|
}
|
|
12425
12536
|
function v2PendingAskPath(key) {
|
|
@@ -13920,7 +14031,7 @@ var init_ask_user_gates = __esm(async () => {
|
|
|
13920
14031
|
});
|
|
13921
14032
|
|
|
13922
14033
|
// ../../packages/core/src/agents/mcp-tools/ask-user.ts
|
|
13923
|
-
import { createHash as
|
|
14034
|
+
import { createHash as createHash6, randomUUID as randomUUID14 } from "crypto";
|
|
13924
14035
|
import { z as z3 } from "zod";
|
|
13925
14036
|
function normalizeAskText(value2, maxChars) {
|
|
13926
14037
|
if (typeof value2 !== "string")
|
|
@@ -13957,7 +14068,7 @@ function normalizeAskUserQuestionInput(input) {
|
|
|
13957
14068
|
return { question, choices };
|
|
13958
14069
|
}
|
|
13959
14070
|
function askBodyHash(question, choices) {
|
|
13960
|
-
return
|
|
14071
|
+
return createHash6("sha256").update(JSON.stringify({ question, choices })).digest("hex");
|
|
13961
14072
|
}
|
|
13962
14073
|
function answerToolResult(answer) {
|
|
13963
14074
|
if (!answer.userId)
|
|
@@ -14585,7 +14696,7 @@ var init_visuals = __esm(async () => {
|
|
|
14585
14696
|
});
|
|
14586
14697
|
|
|
14587
14698
|
// ../../packages/core/src/storage/token-stats.ts
|
|
14588
|
-
import { createHash as
|
|
14699
|
+
import { createHash as createHash7 } from "crypto";
|
|
14589
14700
|
import { mkdirSync as mkdirSync18 } from "fs";
|
|
14590
14701
|
import { join as join27 } from "path";
|
|
14591
14702
|
function emptyBucket() {
|
|
@@ -14594,12 +14705,13 @@ function emptyBucket() {
|
|
|
14594
14705
|
outputTokens: 0,
|
|
14595
14706
|
cacheCreationInputTokens: 0,
|
|
14596
14707
|
cacheReadInputTokens: 0,
|
|
14597
|
-
queries: 0
|
|
14708
|
+
queries: 0,
|
|
14709
|
+
estimatedCostUsd: 0
|
|
14598
14710
|
};
|
|
14599
14711
|
}
|
|
14600
14712
|
function tokenStatsFileId(userId) {
|
|
14601
14713
|
const rawUserId = String(userId);
|
|
14602
|
-
return /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${
|
|
14714
|
+
return /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash7("sha256").update(rawUserId).digest("hex")}`;
|
|
14603
14715
|
}
|
|
14604
14716
|
function queriesPath(userId) {
|
|
14605
14717
|
const fileId = tokenStatsFileId(userId);
|
|
@@ -14621,16 +14733,41 @@ function loadRecords(userId) {
|
|
|
14621
14733
|
}
|
|
14622
14734
|
}
|
|
14623
14735
|
function calcCost(b) {
|
|
14624
|
-
return b.
|
|
14736
|
+
return b.estimatedCostUsd;
|
|
14737
|
+
}
|
|
14738
|
+
function estimateUsageCost(agent, model, usage) {
|
|
14739
|
+
const prices = TOKEN_PRICES[`${agent}:${model}`];
|
|
14740
|
+
if (!prices)
|
|
14741
|
+
return 0;
|
|
14742
|
+
return (usage.inputTokens * prices.input + usage.outputTokens * prices.output + (agent === "claude" ? usage.cacheCreationInputTokens * (prices.cacheWrite ?? prices.input) : 0) + usage.cacheReadInputTokens * prices.cacheRead) / 1e6;
|
|
14625
14743
|
}
|
|
14626
|
-
function
|
|
14744
|
+
function isQueryRecord(value2) {
|
|
14745
|
+
if (!value2 || typeof value2 !== "object")
|
|
14746
|
+
return false;
|
|
14747
|
+
const record = value2;
|
|
14748
|
+
return record.schemaVersion === 2 && typeof record.timestamp === "string" && typeof record.session === "string" && typeof record.topicId === "string" && typeof record.agent === "string" && typeof record.model === "string" && typeof record.inputTokens === "number" && typeof record.outputTokens === "number" && typeof record.cacheCreationInputTokens === "number" && typeof record.cacheReadInputTokens === "number" && typeof record.estimatedCostUsd === "number";
|
|
14749
|
+
}
|
|
14750
|
+
function recordUsage(userId, session, usage, context) {
|
|
14751
|
+
const cacheReadInputTokens = usage.cacheReadInputTokens ?? 0;
|
|
14752
|
+
const inputTokens = context.agent === "claude" ? usage.inputTokens : Math.max(0, usage.inputTokens - cacheReadInputTokens);
|
|
14753
|
+
const normalized = {
|
|
14754
|
+
inputTokens,
|
|
14755
|
+
outputTokens: usage.outputTokens,
|
|
14756
|
+
cacheCreationInputTokens: usage.cacheCreationInputTokens ?? 0,
|
|
14757
|
+
cacheReadInputTokens
|
|
14758
|
+
};
|
|
14627
14759
|
const record = {
|
|
14760
|
+
schemaVersion: 2,
|
|
14628
14761
|
timestamp: new Date().toISOString(),
|
|
14629
14762
|
session,
|
|
14630
|
-
|
|
14631
|
-
|
|
14632
|
-
|
|
14633
|
-
|
|
14763
|
+
topicId: context.topicId,
|
|
14764
|
+
...context.providerSessionId ? { providerSessionId: context.providerSessionId } : {},
|
|
14765
|
+
agent: context.agent,
|
|
14766
|
+
model: context.model,
|
|
14767
|
+
...normalized,
|
|
14768
|
+
...usage.contextTokens !== undefined ? { contextTokens: usage.contextTokens } : {},
|
|
14769
|
+
...usage.contextWindow !== undefined ? { contextWindow: usage.contextWindow } : {},
|
|
14770
|
+
estimatedCostUsd: usage.costUsd ?? estimateUsageCost(context.agent, context.model, normalized)
|
|
14634
14771
|
};
|
|
14635
14772
|
try {
|
|
14636
14773
|
appendJsonlEntry(queriesPath(userId), record);
|
|
@@ -14644,12 +14781,26 @@ function getStats(userId, from, to) {
|
|
|
14644
14781
|
const toTs = to ? new Date(to).getTime() : Infinity;
|
|
14645
14782
|
if (from && Number.isNaN(fromTs) || to && Number.isNaN(toTs)) {
|
|
14646
14783
|
logger.warn({ from, to }, "token-stats: Invalid date range, returning empty");
|
|
14647
|
-
return {
|
|
14784
|
+
return {
|
|
14785
|
+
total: emptyBucket(),
|
|
14786
|
+
byHour: {},
|
|
14787
|
+
bySession: {},
|
|
14788
|
+
currentSessions: [],
|
|
14789
|
+
ignoredLegacyRecords: 0,
|
|
14790
|
+
estimatedCostUsd: 0
|
|
14791
|
+
};
|
|
14648
14792
|
}
|
|
14649
14793
|
const total = emptyBucket();
|
|
14650
14794
|
const byHour = {};
|
|
14651
14795
|
const bySession = {};
|
|
14652
|
-
|
|
14796
|
+
const currentSessions = new Map;
|
|
14797
|
+
let ignoredLegacyRecords = 0;
|
|
14798
|
+
for (const raw of records) {
|
|
14799
|
+
if (!isQueryRecord(raw)) {
|
|
14800
|
+
ignoredLegacyRecords += 1;
|
|
14801
|
+
continue;
|
|
14802
|
+
}
|
|
14803
|
+
const r = raw;
|
|
14653
14804
|
const ts = new Date(r.timestamp).getTime();
|
|
14654
14805
|
if (ts < fromTs || ts > toTs)
|
|
14655
14806
|
continue;
|
|
@@ -14664,14 +14815,47 @@ function getStats(userId, from, to) {
|
|
|
14664
14815
|
bucket.cacheCreationInputTokens += r.cacheCreationInputTokens;
|
|
14665
14816
|
bucket.cacheReadInputTokens += r.cacheReadInputTokens;
|
|
14666
14817
|
bucket.queries += 1;
|
|
14818
|
+
bucket.estimatedCostUsd += r.estimatedCostUsd;
|
|
14819
|
+
}
|
|
14820
|
+
if (r.contextTokens !== undefined && r.contextWindow !== undefined && r.contextWindow > 0) {
|
|
14821
|
+
currentSessions.set(r.topicId, {
|
|
14822
|
+
timestamp: r.timestamp,
|
|
14823
|
+
topicId: r.topicId,
|
|
14824
|
+
topicTitle: r.session,
|
|
14825
|
+
...r.providerSessionId ? { providerSessionId: r.providerSessionId } : {},
|
|
14826
|
+
agent: r.agent,
|
|
14827
|
+
model: r.model,
|
|
14828
|
+
contextTokens: r.contextTokens,
|
|
14829
|
+
contextWindow: r.contextWindow
|
|
14830
|
+
});
|
|
14667
14831
|
}
|
|
14668
14832
|
}
|
|
14669
|
-
return {
|
|
14833
|
+
return {
|
|
14834
|
+
total,
|
|
14835
|
+
byHour,
|
|
14836
|
+
bySession,
|
|
14837
|
+
currentSessions: [...currentSessions.values()].sort((a, b) => b.timestamp.localeCompare(a.timestamp)),
|
|
14838
|
+
ignoredLegacyRecords,
|
|
14839
|
+
estimatedCostUsd: calcCost(total)
|
|
14840
|
+
};
|
|
14670
14841
|
}
|
|
14842
|
+
var TOKEN_PRICES;
|
|
14671
14843
|
var init_token_stats = __esm(async () => {
|
|
14672
14844
|
init_jsonl();
|
|
14673
14845
|
init_logger();
|
|
14674
14846
|
await init_storage_host();
|
|
14847
|
+
TOKEN_PRICES = {
|
|
14848
|
+
"codex:gpt-5.6-sol": { input: 5, cacheRead: 0.5, output: 30 },
|
|
14849
|
+
"codex:gpt-5.6-terra": { input: 2.5, cacheRead: 0.25, output: 15 },
|
|
14850
|
+
"codex:gpt-5.6-luna": { input: 1, cacheRead: 0.1, output: 6 },
|
|
14851
|
+
"claude:fable": { input: 10, cacheWrite: 12.5, cacheRead: 1, output: 50 },
|
|
14852
|
+
"claude:opus": { input: 5, cacheWrite: 6.25, cacheRead: 0.5, output: 25 },
|
|
14853
|
+
"claude:sonnet": { input: 2, cacheWrite: 2.5, cacheRead: 0.2, output: 10 },
|
|
14854
|
+
"maestro:kimi-k3": { input: 3, cacheRead: 0.3, output: 15 },
|
|
14855
|
+
"maestro:kimi-k2.7-code": { input: 0.95, cacheRead: 0.19, output: 4 },
|
|
14856
|
+
"maestro:deepseek-pro": { input: 0.435, cacheRead: 0.003625, output: 0.87 },
|
|
14857
|
+
"maestro:deepseek-flash": { input: 0.14, cacheRead: 0.0028, output: 0.28 }
|
|
14858
|
+
};
|
|
14675
14859
|
});
|
|
14676
14860
|
|
|
14677
14861
|
// ../../packages/core/src/runtime/turn-event-stream.ts
|
|
@@ -14700,6 +14884,9 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
14700
14884
|
let pendingSawDelta = false;
|
|
14701
14885
|
let accumulatedText = "";
|
|
14702
14886
|
let pendingText = "";
|
|
14887
|
+
let assistantContextTokens = 0;
|
|
14888
|
+
let toolContextTokens = 0;
|
|
14889
|
+
let lastContextProgressAt = 0;
|
|
14703
14890
|
let lastVisibleMessageId = null;
|
|
14704
14891
|
const visibleMessageIds = [];
|
|
14705
14892
|
let lastTaskPanelText = null;
|
|
@@ -14710,6 +14897,28 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
14710
14897
|
const toolSummaryOptions = {
|
|
14711
14898
|
cwd: control.injectParams?.cwd ?? workspaceCwdFor(topicId)
|
|
14712
14899
|
};
|
|
14900
|
+
const recordEventUsage = (usage) => {
|
|
14901
|
+
recordUsage(userId, topicTitle, usage, {
|
|
14902
|
+
topicId,
|
|
14903
|
+
...control.sessionId ? { providerSessionId: control.sessionId } : {},
|
|
14904
|
+
agent: agentType,
|
|
14905
|
+
model
|
|
14906
|
+
});
|
|
14907
|
+
};
|
|
14908
|
+
const broadcastContextProgress = (force = false) => {
|
|
14909
|
+
if (silent)
|
|
14910
|
+
return;
|
|
14911
|
+
const now = Date.now();
|
|
14912
|
+
if (!force && lastContextProgressAt > 0 && now - lastContextProgressAt < 250)
|
|
14913
|
+
return;
|
|
14914
|
+
lastContextProgressAt = now;
|
|
14915
|
+
hub.broadcastAiStatus(topicId, {
|
|
14916
|
+
kind: "context_progress",
|
|
14917
|
+
queryId,
|
|
14918
|
+
assistantTokens: assistantContextTokens,
|
|
14919
|
+
toolTokens: toolContextTokens
|
|
14920
|
+
});
|
|
14921
|
+
};
|
|
14713
14922
|
const nextSyntheticToolUseId = () => `tool-${queryId}-${++syntheticToolCounter}`;
|
|
14714
14923
|
const bindToolUseId = (providerToolUseId, fallback) => {
|
|
14715
14924
|
const providerId = normalizeToolUseId(providerToolUseId);
|
|
@@ -14819,6 +15028,8 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
14819
15028
|
const incoming = event.content;
|
|
14820
15029
|
accumulatedText += incoming;
|
|
14821
15030
|
pendingText += incoming;
|
|
15031
|
+
assistantContextTokens = estimateTextTokens(accumulatedText);
|
|
15032
|
+
broadcastContextProgress();
|
|
14822
15033
|
break;
|
|
14823
15034
|
}
|
|
14824
15035
|
case "text":
|
|
@@ -14826,10 +15037,15 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
14826
15037
|
const incoming = event.content;
|
|
14827
15038
|
accumulatedText += incoming;
|
|
14828
15039
|
pendingText += incoming;
|
|
15040
|
+
assistantContextTokens = estimateTextTokens(accumulatedText);
|
|
15041
|
+
broadcastContextProgress();
|
|
14829
15042
|
}
|
|
14830
15043
|
break;
|
|
14831
15044
|
case "tool_use":
|
|
14832
15045
|
emitPendingAssistantMessage();
|
|
15046
|
+
toolContextTokens += estimateTextTokens(`${event.name}
|
|
15047
|
+
${JSON.stringify(event.input ?? {})}`);
|
|
15048
|
+
broadcastContextProgress(true);
|
|
14833
15049
|
if (isVisualsShowHtmlTool(event.name)) {
|
|
14834
15050
|
const input = event.input;
|
|
14835
15051
|
if (typeof input.html !== "string" || input.html.trim().length === 0) {
|
|
@@ -14983,6 +15199,8 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
14983
15199
|
}
|
|
14984
15200
|
break;
|
|
14985
15201
|
case "tool_result":
|
|
15202
|
+
toolContextTokens += estimateTextTokens(event.content);
|
|
15203
|
+
broadcastContextProgress(true);
|
|
14986
15204
|
if (isVisualToolResultHandled(event.toolUseId))
|
|
14987
15205
|
break;
|
|
14988
15206
|
if (!silent) {
|
|
@@ -15028,7 +15246,7 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
15028
15246
|
break;
|
|
15029
15247
|
case "result":
|
|
15030
15248
|
if (event.usage)
|
|
15031
|
-
|
|
15249
|
+
recordEventUsage(event.usage);
|
|
15032
15250
|
{
|
|
15033
15251
|
const usage = event.usage ? {
|
|
15034
15252
|
input: event.usage.inputTokens,
|
|
@@ -15078,6 +15296,8 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
15078
15296
|
}
|
|
15079
15297
|
break;
|
|
15080
15298
|
case "error":
|
|
15299
|
+
if (event.usage)
|
|
15300
|
+
recordEventUsage(event.usage);
|
|
15081
15301
|
logger.warn({ topicId, queryId, agentType, model, silent, error: event.content }, "ai: provider returned error");
|
|
15082
15302
|
terminalEmitted = true;
|
|
15083
15303
|
errorOccurred = true;
|
|
@@ -15366,6 +15586,7 @@ __export(exports_turn_runner, {
|
|
|
15366
15586
|
channelTranscriptSpeaker: () => channelTranscriptSpeaker,
|
|
15367
15587
|
canonicalModelId: () => canonicalModelId,
|
|
15368
15588
|
buildVideoHtml: () => buildVideoHtml,
|
|
15589
|
+
buildTurnReminderQuery: () => buildTurnReminderQuery,
|
|
15369
15590
|
buildMermaidHtml: () => buildMermaidHtml,
|
|
15370
15591
|
buildMentionOnlyChannelPrompt: () => buildMentionOnlyChannelPrompt,
|
|
15371
15592
|
buildImageHtml: () => buildImageHtml,
|
|
@@ -15391,6 +15612,18 @@ function withDefaultPlaywright(configuredMcp, isManager) {
|
|
|
15391
15612
|
enabled.add("background-bash");
|
|
15392
15613
|
return [...enabled];
|
|
15393
15614
|
}
|
|
15615
|
+
function buildTurnReminderQuery(agent, prompt, reminders) {
|
|
15616
|
+
const reminderPrompt = reminders.join(`
|
|
15617
|
+
|
|
15618
|
+
`);
|
|
15619
|
+
if (!reminderPrompt)
|
|
15620
|
+
return { prompt };
|
|
15621
|
+
if (agent === "maestro")
|
|
15622
|
+
return { prompt, ephemeralSystemPrompt: reminderPrompt };
|
|
15623
|
+
return { prompt: `${prompt}
|
|
15624
|
+
|
|
15625
|
+
${reminderPrompt}` };
|
|
15626
|
+
}
|
|
15394
15627
|
function appendSystemMessage(topicId, text2) {
|
|
15395
15628
|
const message = {
|
|
15396
15629
|
id: randomUUID16(),
|
|
@@ -16338,15 +16571,11 @@ function startAiTurn(params) {
|
|
|
16338
16571
|
if (consumePlaywrightUnavailable(userId, topic.title)) {
|
|
16339
16572
|
turnReminders.push("<system-reminder>Playwright browser tools are UNAVAILABLE this turn. The `mcp__playwright__*` tools have been removed from this turn's catalog because the long-lived browser MCP could not be prepared. Do not attempt to call browser tools. If browser interaction is required, ask the user to retry shortly or use a non-browser alternative.</system-reminder>");
|
|
16340
16573
|
}
|
|
16341
|
-
const
|
|
16342
|
-
|
|
16343
|
-
${turnReminders.join(`
|
|
16344
|
-
|
|
16345
|
-
`)}` : agentPrompt;
|
|
16574
|
+
const reminderQuery = buildTurnReminderQuery(agentKind, agentPrompt, turnReminders);
|
|
16346
16575
|
try {
|
|
16347
16576
|
yield* runAgent({
|
|
16348
16577
|
agent: agentKind,
|
|
16349
|
-
|
|
16578
|
+
...reminderQuery,
|
|
16350
16579
|
attachments: promptAttachments,
|
|
16351
16580
|
cwd: workspaceCwd,
|
|
16352
16581
|
systemPrompt,
|
|
@@ -19551,7 +19780,7 @@ function createTokenStatsMcpServer(context, host = defaultTokenStatsMcpHost) {
|
|
|
19551
19780
|
throw new Error("token-stats MCP requires userId");
|
|
19552
19781
|
const server = new McpServer6({ name: "token-stats", version: "1.0.0" });
|
|
19553
19782
|
server.tool("get_usage_stats", [
|
|
19554
|
-
"Claude \uC0AC\uC6A9\uB7C9
|
|
19783
|
+
"Claude/Codex/Maestro \uC0AC\uC6A9\uB7C9\uACFC provider session\uC758 \uCD5C\uC2E0 context \uC810\uC720\uC728\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4. \uD604\uC7AC \uC2E4\uD589 \uC911\uC778 turn\uC740 \uC644\uB8CC \uD6C4 \uC9D1\uACC4\uB429\uB2C8\uB2E4.",
|
|
19555
19784
|
"",
|
|
19556
19785
|
"from/to \uC0DD\uB7B5 \uC2DC \uC804\uCCB4 \uAE30\uAC04. \uC790\uC5F0\uC5B4 \uC2DC\uAC04 \uD45C\uD604\uC744 ISO \uD615\uC2DD\uC73C\uB85C \uBCC0\uD658\uD574\uC11C \uB118\uACA8\uC8FC\uC138\uC694.",
|
|
19557
19786
|
" \uC608: '\uC9C0\uB09C 3\uC2DC\uAC04' \u2192 from = \uD604\uC7AC -3h",
|
|
@@ -19565,18 +19794,36 @@ function createTokenStatsMcpServer(context, host = defaultTokenStatsMcpHost) {
|
|
|
19565
19794
|
to: z7.string().optional().describe("\uC885\uB8CC \uC2DC\uAC01 ISO 8601. \uC0DD\uB7B5 \uC2DC \uD604\uC7AC"),
|
|
19566
19795
|
groupBy: z7.enum(["hour", "session"]).optional().describe("\uC9D1\uACC4 \uAE30\uC900. \uAE30\uBCF8\uAC12: hour")
|
|
19567
19796
|
}, async ({ from, to, groupBy = "hour" }) => {
|
|
19568
|
-
const
|
|
19797
|
+
const snapshot = host.getStats(context.userId, from, to);
|
|
19798
|
+
const {
|
|
19799
|
+
total,
|
|
19800
|
+
byHour,
|
|
19801
|
+
bySession,
|
|
19802
|
+
currentSessions = [],
|
|
19803
|
+
ignoredLegacyRecords = 0,
|
|
19804
|
+
estimatedCostUsd
|
|
19805
|
+
} = snapshot;
|
|
19569
19806
|
const lines = [
|
|
19570
|
-
"\uD83D\uDCCA
|
|
19807
|
+
"\uD83D\uDCCA Agent \uC0AC\uC6A9\uB7C9",
|
|
19571
19808
|
from || to ? `\uAE30\uAC04: ${from ?? "\uC804\uCCB4"} ~ ${to ?? "\uD604\uC7AC"}` : "\uAE30\uAC04: \uC804\uCCB4",
|
|
19572
19809
|
"",
|
|
19573
19810
|
`\uCFFC\uB9AC \uD69F\uC218: ${total.queries.toLocaleString()}\uD68C`,
|
|
19574
|
-
`\
|
|
19811
|
+
`\uCE90\uC2DC \uBBF8\uC801\uC911 \uC785\uB825: ${total.inputTokens.toLocaleString()}`,
|
|
19575
19812
|
`\uCD9C\uB825 \uD1A0\uD070: ${total.outputTokens.toLocaleString()}`,
|
|
19576
19813
|
`\uCE90\uC2DC \uC4F0\uAE30: ${total.cacheCreationInputTokens.toLocaleString()}`,
|
|
19577
19814
|
`\uCE90\uC2DC \uC77D\uAE30: ${total.cacheReadInputTokens.toLocaleString()}`,
|
|
19578
19815
|
`\uC608\uC0C1 \uBE44\uC6A9: $${estimatedCostUsd.toFixed(4)} USD`
|
|
19579
19816
|
];
|
|
19817
|
+
if (ignoredLegacyRecords > 0) {
|
|
19818
|
+
lines.push(`\uAD6C\uD615 \uB808\uCF54\uB4DC \uC81C\uC678: ${ignoredLegacyRecords.toLocaleString()}\uAC74`);
|
|
19819
|
+
}
|
|
19820
|
+
if (currentSessions.length > 0) {
|
|
19821
|
+
lines.push("", `\uD83D\uDCD0 \uD604\uC7AC context (${currentSessions.length}\uAC1C provider session)`);
|
|
19822
|
+
for (const current3 of currentSessions) {
|
|
19823
|
+
const percent = current3.contextTokens / current3.contextWindow * 100;
|
|
19824
|
+
lines.push(` ${current3.topicTitle} \xB7 ${current3.agent}/${current3.model} ${current3.contextTokens.toLocaleString()} / ${current3.contextWindow.toLocaleString()} (${percent.toFixed(1)}%)`);
|
|
19825
|
+
}
|
|
19826
|
+
}
|
|
19580
19827
|
const extraSummaryLines = host.extraSummaryLines?.(context.userId) ?? [];
|
|
19581
19828
|
if (extraSummaryLines.length > 0)
|
|
19582
19829
|
lines.push("", ...extraSummaryLines);
|
|
@@ -19584,7 +19831,7 @@ function createTokenStatsMcpServer(context, host = defaultTokenStatsMcpHost) {
|
|
|
19584
19831
|
const sorted = Object.entries(bySession).map(([name, bucket]) => ({ name, ...bucket, cost: host.calcCost(bucket) })).sort((left, right) => right.cost - left.cost);
|
|
19585
19832
|
lines.push("", `\uD83D\uDDC2 \uC138\uC158\uBCC4 \uC0AC\uC6A9\uB7C9 (${sorted.length}\uAC1C)`);
|
|
19586
19833
|
for (const session of sorted) {
|
|
19587
|
-
lines.push(` ${session.name} \uCFFC\uB9AC ${session.queries}\uD68C \uC785\uB825 ${session.inputTokens.toLocaleString()} / \uCD9C\uB825 ${session.outputTokens.toLocaleString()} $${session.cost.toFixed(4)}`);
|
|
19834
|
+
lines.push(` ${session.name} \uCFFC\uB9AC ${session.queries}\uD68C \uCE90\uC2DC \uBBF8\uC801\uC911 \uC785\uB825 ${session.inputTokens.toLocaleString()} / \uCE90\uC2DC \uC77D\uAE30 ${session.cacheReadInputTokens.toLocaleString()} / \uCD9C\uB825 ${session.outputTokens.toLocaleString()} $${session.cost.toFixed(4)}`);
|
|
19588
19835
|
}
|
|
19589
19836
|
} else {
|
|
19590
19837
|
const hours = Object.keys(byHour).sort();
|
|
@@ -19696,4 +19943,4 @@ export {
|
|
|
19696
19943
|
createAgentHealthMcpServer
|
|
19697
19944
|
};
|
|
19698
19945
|
|
|
19699
|
-
//# debugId=
|
|
19946
|
+
//# debugId=AD1DC675E382EEA164756E2164756E21
|