negotium 0.2.14 → 0.2.16
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 +178 -26
- package/dist/agent-helpers.js.map +8 -8
- package/dist/{chunk-5g5a63vv.js → chunk-5cpdbbeh.js} +56 -6
- package/dist/{chunk-5g5a63vv.js.map → chunk-5cpdbbeh.js.map} +4 -4
- package/dist/hosted-agent.js +118 -9
- package/dist/hosted-agent.js.map +6 -6
- package/dist/main.js +389 -50
- package/dist/main.js.map +15 -15
- package/dist/mcp-factories.js +247 -36
- package/dist/mcp-factories.js.map +9 -9
- 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/rollout/codex.ts +62 -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/public-helpers.ts +8 -0
- package/dist/runtime/src/runtime/turn-event-stream.ts +17 -2
- package/dist/runtime/src/storage/token-stats.ts +200 -19
- package/dist/runtime/src/version.ts +1 -1
- package/dist/runtime-helpers.js +443 -30
- package/dist/runtime-helpers.js.map +9 -3
- package/dist/storage.js +112 -11
- package/dist/storage.js.map +3 -3
- package/dist/types/packages/core/src/agents/codex-provider.d.ts +13 -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/bashrs-completions.d.ts +50 -0
- package/dist/types/packages/core/src/runtime/public-helpers.d.ts +2 -0
- package/dist/types/packages/core/src/storage/token-stats.d.ts +35 -6
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/agent-helpers.js
CHANGED
|
@@ -474,7 +474,7 @@ var init_canonical_bridge_config = __esm(() => {
|
|
|
474
474
|
});
|
|
475
475
|
|
|
476
476
|
// ../../packages/core/src/mcp/runtime-spec.ts
|
|
477
|
-
import { createHmac, timingSafeEqual } from "crypto";
|
|
477
|
+
import { createHash, createHmac, timingSafeEqual } from "crypto";
|
|
478
478
|
function encodeTokenPart(value) {
|
|
479
479
|
return Buffer.from(JSON.stringify(value), "utf-8").toString("base64url");
|
|
480
480
|
}
|
|
@@ -507,19 +507,69 @@ function buildRuntimeMcpSpec(agent, ctx) {
|
|
|
507
507
|
return {
|
|
508
508
|
type: "sse",
|
|
509
509
|
url: `${base}/sse?${query}`,
|
|
510
|
-
timeout: CLAUDE_MCP_TOOL_TIMEOUT_MS
|
|
510
|
+
timeout: CLAUDE_MCP_TOOL_TIMEOUT_MS,
|
|
511
|
+
...agent === "maestro" ? { lifecycle: "turn" } : {}
|
|
511
512
|
};
|
|
512
513
|
}
|
|
514
|
+
function hostedMcpCacheIdentity(surface, ctx) {
|
|
515
|
+
let semanticContext;
|
|
516
|
+
switch (surface) {
|
|
517
|
+
case "system-health":
|
|
518
|
+
semanticContext = {};
|
|
519
|
+
break;
|
|
520
|
+
case "token-stats":
|
|
521
|
+
case "agent-health":
|
|
522
|
+
semanticContext = { userId: ctx.userId };
|
|
523
|
+
break;
|
|
524
|
+
case "task":
|
|
525
|
+
semanticContext = {
|
|
526
|
+
userId: ctx.userId,
|
|
527
|
+
topicTitle: ctx.topicTitle,
|
|
528
|
+
topicId: ctx.topicId ?? null
|
|
529
|
+
};
|
|
530
|
+
break;
|
|
531
|
+
case "wiki":
|
|
532
|
+
case "skills":
|
|
533
|
+
semanticContext = {
|
|
534
|
+
userId: ctx.userId,
|
|
535
|
+
topicId: ctx.wikiTopicId ?? ctx.topicId ?? null
|
|
536
|
+
};
|
|
537
|
+
break;
|
|
538
|
+
case "vault":
|
|
539
|
+
semanticContext = { userId: ctx.userId, cwd: ctx.cwd, agent: ctx.agent };
|
|
540
|
+
break;
|
|
541
|
+
case "session-comm":
|
|
542
|
+
semanticContext = {
|
|
543
|
+
userId: ctx.userId,
|
|
544
|
+
topicTitle: ctx.topicTitle,
|
|
545
|
+
topicId: ctx.topicId ?? null,
|
|
546
|
+
subagentParentTopicId: ctx.subagentParentTopicId ?? null,
|
|
547
|
+
depth: ctx.depth ?? 0,
|
|
548
|
+
silent: ctx.silent ?? false,
|
|
549
|
+
agent: ctx.agent,
|
|
550
|
+
peerBridge: ctx.peerBridge ?? null
|
|
551
|
+
};
|
|
552
|
+
break;
|
|
553
|
+
}
|
|
554
|
+
const digest = createHash("sha256").update(JSON.stringify([surface, semanticContext])).digest("hex").slice(0, 24);
|
|
555
|
+
return `hosted:${surface}:${digest}`;
|
|
556
|
+
}
|
|
513
557
|
function buildHostedMcpSpec(agent, surface, ctx) {
|
|
514
558
|
const token = issueHostedMcpToken(surface, ctx);
|
|
515
559
|
const base = `http://127.0.0.1:${runtimePort}${RUNTIME_MCP_BASE_PATH}/${surface}`;
|
|
516
560
|
const query = `token=${encodeURIComponent(token)}`;
|
|
517
561
|
if (agent === "codex")
|
|
518
562
|
return { url: `${base}/mcp?${query}` };
|
|
563
|
+
const queryBound = surface === "session-comm" && (ctx.silent === true || ctx.peerBridge !== undefined);
|
|
564
|
+
const lifecycle = queryBound ? "turn" : surface === "session-comm" ? "session" : "process";
|
|
519
565
|
return {
|
|
520
566
|
type: "sse",
|
|
521
567
|
url: `${base}/sse?${query}`,
|
|
522
|
-
timeout: CLAUDE_MCP_TOOL_TIMEOUT_MS
|
|
568
|
+
timeout: CLAUDE_MCP_TOOL_TIMEOUT_MS,
|
|
569
|
+
...agent === "maestro" ? {
|
|
570
|
+
lifecycle,
|
|
571
|
+
cacheKey: hostedMcpCacheIdentity(surface, ctx)
|
|
572
|
+
} : {}
|
|
523
573
|
};
|
|
524
574
|
}
|
|
525
575
|
var RUNTIME_MCP_KEY = "runtime", RUNTIME_MCP_BASE_PATH = "/mcp/runtime", TOKEN_TTL_MS, CLAUDE_MCP_TOOL_TIMEOUT_MS = 600000, runtimePort;
|
|
@@ -1372,9 +1422,9 @@ var init_sqlite = __esm(async () => {
|
|
|
1372
1422
|
});
|
|
1373
1423
|
|
|
1374
1424
|
// ../../packages/core/src/storage/vault-crypto-core.ts
|
|
1375
|
-
import { createCipheriv, createDecipheriv, createHash, randomBytes as randomBytes3 } from "crypto";
|
|
1425
|
+
import { createCipheriv, createDecipheriv, createHash as createHash2, randomBytes as randomBytes3 } from "crypto";
|
|
1376
1426
|
function encryptionKey(masterKey) {
|
|
1377
|
-
return
|
|
1427
|
+
return createHash2("sha256").update("otium-vault-value-v1\x00", "utf8").update(masterKey, "utf8").digest().subarray(0, KEY_BYTES);
|
|
1378
1428
|
}
|
|
1379
1429
|
function aad(userId, key) {
|
|
1380
1430
|
return Buffer.from(`${userId}\x00${key.toUpperCase()}`, "utf8");
|
|
@@ -2173,7 +2223,7 @@ var init_claude_registry = __esm(() => {
|
|
|
2173
2223
|
});
|
|
2174
2224
|
|
|
2175
2225
|
// ../../packages/core/src/version.ts
|
|
2176
|
-
var NEGOTIUM_VERSION = "0.2.
|
|
2226
|
+
var NEGOTIUM_VERSION = "0.2.16";
|
|
2177
2227
|
|
|
2178
2228
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
2179
2229
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -2631,6 +2681,36 @@ function extractLatestCodexContextUsage(jsonl) {
|
|
|
2631
2681
|
}
|
|
2632
2682
|
return;
|
|
2633
2683
|
}
|
|
2684
|
+
function extractLatestCodexTokenTotals(jsonl) {
|
|
2685
|
+
const lines = jsonl.trimEnd().split(`
|
|
2686
|
+
`);
|
|
2687
|
+
for (let index = lines.length - 1;index >= 0; index -= 1) {
|
|
2688
|
+
try {
|
|
2689
|
+
const entry = JSON.parse(lines[index] ?? "");
|
|
2690
|
+
if (entry.type !== "event_msg" || entry.payload?.type !== "token_count")
|
|
2691
|
+
continue;
|
|
2692
|
+
const usage = entry.payload.info?.total_token_usage;
|
|
2693
|
+
if (!usage)
|
|
2694
|
+
continue;
|
|
2695
|
+
const values = [
|
|
2696
|
+
usage.input_tokens,
|
|
2697
|
+
usage.output_tokens,
|
|
2698
|
+
usage.cached_input_tokens,
|
|
2699
|
+
usage.cache_write_input_tokens
|
|
2700
|
+
];
|
|
2701
|
+
if (values.some((value) => value !== undefined && (!Number.isFinite(value) || value < 0))) {
|
|
2702
|
+
continue;
|
|
2703
|
+
}
|
|
2704
|
+
return {
|
|
2705
|
+
inputTokens: usage.input_tokens ?? 0,
|
|
2706
|
+
outputTokens: usage.output_tokens ?? 0,
|
|
2707
|
+
cachedInputTokens: usage.cached_input_tokens ?? 0,
|
|
2708
|
+
cacheWriteInputTokens: usage.cache_write_input_tokens ?? 0
|
|
2709
|
+
};
|
|
2710
|
+
} catch {}
|
|
2711
|
+
}
|
|
2712
|
+
return;
|
|
2713
|
+
}
|
|
2634
2714
|
function readLatestCodexContextUsage(threadId) {
|
|
2635
2715
|
const path = latestCodexRolloutPath(threadId);
|
|
2636
2716
|
if (!path)
|
|
@@ -2642,6 +2722,17 @@ function readLatestCodexContextUsage(threadId) {
|
|
|
2642
2722
|
return;
|
|
2643
2723
|
}
|
|
2644
2724
|
}
|
|
2725
|
+
function readLatestCodexTokenTotals(threadId) {
|
|
2726
|
+
const path = latestCodexRolloutPath(threadId);
|
|
2727
|
+
if (!path)
|
|
2728
|
+
return;
|
|
2729
|
+
try {
|
|
2730
|
+
return extractLatestCodexTokenTotals(readFileSync5(path, "utf8"));
|
|
2731
|
+
} catch (error) {
|
|
2732
|
+
logger.debug({ error, threadId }, "codex token totals: rollout read failed");
|
|
2733
|
+
return;
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2645
2736
|
function migrateCodexRolloutNativeMultiAgentMetadata(threadId) {
|
|
2646
2737
|
const path = latestCodexRolloutPath(threadId);
|
|
2647
2738
|
if (!path)
|
|
@@ -4956,6 +5047,7 @@ var init_tool_format = __esm(() => {
|
|
|
4956
5047
|
var exports_codex_provider = {};
|
|
4957
5048
|
__export(exports_codex_provider, {
|
|
4958
5049
|
toCodexMcpServers: () => toCodexMcpServers,
|
|
5050
|
+
normalizeCodexTurnUsage: () => normalizeCodexTurnUsage,
|
|
4959
5051
|
codexProvider: () => codexProvider
|
|
4960
5052
|
});
|
|
4961
5053
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
@@ -4963,6 +5055,20 @@ import { existsSync as existsSync11, readFileSync as readFileSync11, realpathSyn
|
|
|
4963
5055
|
import { homedir as homedir6 } from "os";
|
|
4964
5056
|
import { dirname as dirname9, isAbsolute as isAbsolute2, join as join12, relative, resolve as resolve8 } from "path";
|
|
4965
5057
|
import { Codex } from "@openai/codex-sdk";
|
|
5058
|
+
function sameCodexUsage(usage, total) {
|
|
5059
|
+
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;
|
|
5060
|
+
}
|
|
5061
|
+
function normalizeCodexTurnUsage(usage, baseline, rolloutTotal) {
|
|
5062
|
+
if (!baseline || !rolloutTotal || !sameCodexUsage(usage, rolloutTotal))
|
|
5063
|
+
return usage;
|
|
5064
|
+
const delta = (current, previous) => current >= previous ? current - previous : current;
|
|
5065
|
+
return {
|
|
5066
|
+
input_tokens: delta(rolloutTotal.inputTokens, baseline.inputTokens),
|
|
5067
|
+
output_tokens: delta(rolloutTotal.outputTokens, baseline.outputTokens),
|
|
5068
|
+
cached_input_tokens: delta(rolloutTotal.cachedInputTokens, baseline.cachedInputTokens),
|
|
5069
|
+
cache_write_input_tokens: delta(rolloutTotal.cacheWriteInputTokens, baseline.cacheWriteInputTokens)
|
|
5070
|
+
};
|
|
5071
|
+
}
|
|
4966
5072
|
function mapEffort(effort) {
|
|
4967
5073
|
if (!effort)
|
|
4968
5074
|
return;
|
|
@@ -5362,6 +5468,7 @@ async function* codexProvider(opts) {
|
|
|
5362
5468
|
...opts.effort ? { modelReasoningEffort: mapEffort(opts.effort) } : {}
|
|
5363
5469
|
};
|
|
5364
5470
|
let currentSessionId = opts.sessionId;
|
|
5471
|
+
let usageBaseline = currentSessionId ? readLatestCodexTokenTotals(currentSessionId) : undefined;
|
|
5365
5472
|
let thread = currentSessionId ? codex.resumeThread(currentSessionId, threadOptions) : codex.startThread(threadOptions);
|
|
5366
5473
|
let prompt = promptForThread(opts, true);
|
|
5367
5474
|
let agentTextSoFar = "";
|
|
@@ -5420,6 +5527,7 @@ async function* codexProvider(opts) {
|
|
|
5420
5527
|
thread = codex.startThread(threadOptions);
|
|
5421
5528
|
prompt = promptForThread(opts, true);
|
|
5422
5529
|
currentSessionId = undefined;
|
|
5530
|
+
usageBaseline = undefined;
|
|
5423
5531
|
startResult = await startStreamedWithTracking(thread, prompt, attemptAbort.signal, trackedPids);
|
|
5424
5532
|
}
|
|
5425
5533
|
if (attemptAbort.signal.aborted) {
|
|
@@ -5520,10 +5628,11 @@ async function* codexProvider(opts) {
|
|
|
5520
5628
|
break;
|
|
5521
5629
|
}
|
|
5522
5630
|
case "turn.completed": {
|
|
5523
|
-
const
|
|
5524
|
-
if (!
|
|
5631
|
+
const rawUsage = event.usage;
|
|
5632
|
+
if (!rawUsage)
|
|
5525
5633
|
break;
|
|
5526
5634
|
attemptCompleted = true;
|
|
5635
|
+
const usage = normalizeCodexTurnUsage(rawUsage, usageBaseline, currentSessionId ? readLatestCodexTokenTotals(currentSessionId) : undefined);
|
|
5527
5636
|
const contextUsage = currentSessionId ? readLatestCodexContextUsage(currentSessionId) : undefined;
|
|
5528
5637
|
yield {
|
|
5529
5638
|
type: "result",
|
|
@@ -5532,6 +5641,7 @@ async function* codexProvider(opts) {
|
|
|
5532
5641
|
usage: {
|
|
5533
5642
|
inputTokens: usage.input_tokens,
|
|
5534
5643
|
outputTokens: usage.output_tokens,
|
|
5644
|
+
cacheCreationInputTokens: usage.cache_write_input_tokens,
|
|
5535
5645
|
cacheReadInputTokens: usage.cached_input_tokens,
|
|
5536
5646
|
...contextUsage
|
|
5537
5647
|
}
|
|
@@ -9750,7 +9860,7 @@ var init_runtime_process_leases = __esm(async () => {
|
|
|
9750
9860
|
});
|
|
9751
9861
|
|
|
9752
9862
|
// ../../packages/core/src/agents/mcp-tools/ask-user.ts
|
|
9753
|
-
import { createHash as
|
|
9863
|
+
import { createHash as createHash3, randomUUID as randomUUID9 } from "crypto";
|
|
9754
9864
|
import { z } from "zod";
|
|
9755
9865
|
function normalizeAskText(value, maxChars) {
|
|
9756
9866
|
if (typeof value !== "string")
|
|
@@ -9787,7 +9897,7 @@ function normalizeAskUserQuestionInput(input) {
|
|
|
9787
9897
|
return { question, choices };
|
|
9788
9898
|
}
|
|
9789
9899
|
function askBodyHash(question, choices) {
|
|
9790
|
-
return
|
|
9900
|
+
return createHash3("sha256").update(JSON.stringify({ question, choices })).digest("hex");
|
|
9791
9901
|
}
|
|
9792
9902
|
function answerToolResult(answer) {
|
|
9793
9903
|
if (!answer.userId)
|
|
@@ -10807,7 +10917,7 @@ var init_browser_profiles = __esm(async () => {
|
|
|
10807
10917
|
|
|
10808
10918
|
// ../../packages/core/src/platform/playwright/manager.ts
|
|
10809
10919
|
import { execFileSync as execFileSync7, spawn as spawn5 } from "child_process";
|
|
10810
|
-
import { createHash as
|
|
10920
|
+
import { createHash as createHash4, randomBytes as randomBytes6, timingSafeEqual as timingSafeEqual3 } from "crypto";
|
|
10811
10921
|
import {
|
|
10812
10922
|
cpSync,
|
|
10813
10923
|
existsSync as existsSync17,
|
|
@@ -10902,7 +11012,7 @@ function parseInstanceKey(instanceKey) {
|
|
|
10902
11012
|
};
|
|
10903
11013
|
}
|
|
10904
11014
|
function portFileName(instanceKey) {
|
|
10905
|
-
return
|
|
11015
|
+
return createHash4("sha256").update(instanceKey).digest("hex").slice(0, 24);
|
|
10906
11016
|
}
|
|
10907
11017
|
function writePortFile(instanceKey, port) {
|
|
10908
11018
|
try {
|
|
@@ -12495,7 +12605,7 @@ __export(exports_derive, {
|
|
|
12495
12605
|
TopicForkCompactionError: () => TopicForkCompactionError,
|
|
12496
12606
|
TopicDeriveBusyError: () => TopicDeriveBusyError
|
|
12497
12607
|
});
|
|
12498
|
-
import { createHash as
|
|
12608
|
+
import { createHash as createHash5, randomUUID as randomUUID12 } from "crypto";
|
|
12499
12609
|
import { mkdirSync as mkdirSync13, rmSync as rmSync5, unlinkSync as unlinkSync13 } from "fs";
|
|
12500
12610
|
function getTopics() {
|
|
12501
12611
|
return listTopics().filter((topic) => !isLegacySharedGeneral(topic.id));
|
|
@@ -12561,7 +12671,7 @@ function captureForkSnapshot(sourceTopicId, userId, topicTitle) {
|
|
|
12561
12671
|
maxRowid: messageRows.at(-1)?.rowid ?? 0
|
|
12562
12672
|
},
|
|
12563
12673
|
active: isTopicRunning(sourceTopicId),
|
|
12564
|
-
canonicalDigest:
|
|
12674
|
+
canonicalDigest: createHash5("sha256").update(entries.map((entry) => JSON.stringify(entry)).join(`
|
|
12565
12675
|
`)).digest("hex")
|
|
12566
12676
|
};
|
|
12567
12677
|
}
|
|
@@ -13054,7 +13164,7 @@ __export(exports_session_asks, {
|
|
|
13054
13164
|
clearPendingAsk: () => clearPendingAsk,
|
|
13055
13165
|
PENDING_ASK_TTL_MS: () => PENDING_ASK_TTL_MS
|
|
13056
13166
|
});
|
|
13057
|
-
import { createHash as
|
|
13167
|
+
import { createHash as createHash6 } from "crypto";
|
|
13058
13168
|
import {
|
|
13059
13169
|
closeSync as closeSync2,
|
|
13060
13170
|
mkdirSync as mkdirSync15,
|
|
@@ -13068,14 +13178,14 @@ import {
|
|
|
13068
13178
|
import { dirname as dirname13, join as join24 } from "path";
|
|
13069
13179
|
function pendingAskDir(userId) {
|
|
13070
13180
|
const rawUserId = String(userId);
|
|
13071
|
-
const safeUserId = /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${
|
|
13181
|
+
const safeUserId = /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash6("sha256").update(rawUserId).digest("hex")}`;
|
|
13072
13182
|
return join24(resolveStorageSessionAsksDir(), safeUserId);
|
|
13073
13183
|
}
|
|
13074
13184
|
function encodeAskKey(key) {
|
|
13075
13185
|
return JSON.stringify([key.from, key.to]);
|
|
13076
13186
|
}
|
|
13077
13187
|
function pendingAskPath(key) {
|
|
13078
|
-
const digest =
|
|
13188
|
+
const digest = createHash6("sha256").update(encodeAskKey(key)).digest("hex");
|
|
13079
13189
|
return join24(pendingAskDir(key.userId), `${ASK_FILENAME_PREFIX}${digest}.pending`);
|
|
13080
13190
|
}
|
|
13081
13191
|
function v2PendingAskPath(key) {
|
|
@@ -14654,12 +14764,12 @@ var init_visuals = __esm(async () => {
|
|
|
14654
14764
|
});
|
|
14655
14765
|
|
|
14656
14766
|
// ../../packages/core/src/storage/token-stats.ts
|
|
14657
|
-
import { createHash as
|
|
14767
|
+
import { createHash as createHash7 } from "crypto";
|
|
14658
14768
|
import { mkdirSync as mkdirSync17 } from "fs";
|
|
14659
14769
|
import { join as join26 } from "path";
|
|
14660
14770
|
function tokenStatsFileId(userId) {
|
|
14661
14771
|
const rawUserId = String(userId);
|
|
14662
|
-
return /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${
|
|
14772
|
+
return /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash7("sha256").update(rawUserId).digest("hex")}`;
|
|
14663
14773
|
}
|
|
14664
14774
|
function queriesPath(userId) {
|
|
14665
14775
|
const fileId = tokenStatsFileId(userId);
|
|
@@ -14667,14 +14777,33 @@ function queriesPath(userId) {
|
|
|
14667
14777
|
mkdirSync17(logDir, { recursive: true });
|
|
14668
14778
|
return join26(logDir, `token-queries-${fileId}.jsonl`);
|
|
14669
14779
|
}
|
|
14670
|
-
function
|
|
14780
|
+
function estimateUsageCost(agent, model, usage) {
|
|
14781
|
+
const prices = TOKEN_PRICES[`${agent}:${model}`];
|
|
14782
|
+
if (!prices)
|
|
14783
|
+
return 0;
|
|
14784
|
+
return (usage.inputTokens * prices.input + usage.outputTokens * prices.output + (agent === "claude" ? usage.cacheCreationInputTokens * (prices.cacheWrite ?? prices.input) : 0) + usage.cacheReadInputTokens * prices.cacheRead) / 1e6;
|
|
14785
|
+
}
|
|
14786
|
+
function recordUsage(userId, session, usage, context) {
|
|
14787
|
+
const cacheReadInputTokens = usage.cacheReadInputTokens ?? 0;
|
|
14788
|
+
const inputTokens = context.agent === "claude" ? usage.inputTokens : Math.max(0, usage.inputTokens - cacheReadInputTokens);
|
|
14789
|
+
const normalized = {
|
|
14790
|
+
inputTokens,
|
|
14791
|
+
outputTokens: usage.outputTokens,
|
|
14792
|
+
cacheCreationInputTokens: usage.cacheCreationInputTokens ?? 0,
|
|
14793
|
+
cacheReadInputTokens
|
|
14794
|
+
};
|
|
14671
14795
|
const record = {
|
|
14796
|
+
schemaVersion: 2,
|
|
14672
14797
|
timestamp: new Date().toISOString(),
|
|
14673
14798
|
session,
|
|
14674
|
-
|
|
14675
|
-
|
|
14676
|
-
|
|
14677
|
-
|
|
14799
|
+
topicId: context.topicId,
|
|
14800
|
+
...context.providerSessionId ? { providerSessionId: context.providerSessionId } : {},
|
|
14801
|
+
agent: context.agent,
|
|
14802
|
+
model: context.model,
|
|
14803
|
+
...normalized,
|
|
14804
|
+
...usage.contextTokens !== undefined ? { contextTokens: usage.contextTokens } : {},
|
|
14805
|
+
...usage.contextWindow !== undefined ? { contextWindow: usage.contextWindow } : {},
|
|
14806
|
+
estimatedCostUsd: usage.costUsd ?? estimateUsageCost(context.agent, context.model, normalized)
|
|
14678
14807
|
};
|
|
14679
14808
|
try {
|
|
14680
14809
|
appendJsonlEntry(queriesPath(userId), record);
|
|
@@ -14682,10 +14811,23 @@ function recordUsage(userId, session, usage) {
|
|
|
14682
14811
|
logger.warn({ err: e, userId }, "token-stats: Failed to record");
|
|
14683
14812
|
}
|
|
14684
14813
|
}
|
|
14814
|
+
var TOKEN_PRICES;
|
|
14685
14815
|
var init_token_stats = __esm(async () => {
|
|
14686
14816
|
init_jsonl();
|
|
14687
14817
|
init_logger();
|
|
14688
14818
|
await init_storage_host();
|
|
14819
|
+
TOKEN_PRICES = {
|
|
14820
|
+
"codex:gpt-5.6-sol": { input: 5, cacheRead: 0.5, output: 30 },
|
|
14821
|
+
"codex:gpt-5.6-terra": { input: 2.5, cacheRead: 0.25, output: 15 },
|
|
14822
|
+
"codex:gpt-5.6-luna": { input: 1, cacheRead: 0.1, output: 6 },
|
|
14823
|
+
"claude:fable": { input: 10, cacheWrite: 12.5, cacheRead: 1, output: 50 },
|
|
14824
|
+
"claude:opus": { input: 5, cacheWrite: 6.25, cacheRead: 0.5, output: 25 },
|
|
14825
|
+
"claude:sonnet": { input: 2, cacheWrite: 2.5, cacheRead: 0.2, output: 10 },
|
|
14826
|
+
"maestro:kimi-k3": { input: 3, cacheRead: 0.3, output: 15 },
|
|
14827
|
+
"maestro:kimi-k2.7-code": { input: 0.95, cacheRead: 0.19, output: 4 },
|
|
14828
|
+
"maestro:deepseek-pro": { input: 0.435, cacheRead: 0.003625, output: 0.87 },
|
|
14829
|
+
"maestro:deepseek-flash": { input: 0.14, cacheRead: 0.0028, output: 0.28 }
|
|
14830
|
+
};
|
|
14689
14831
|
});
|
|
14690
14832
|
|
|
14691
14833
|
// ../../packages/core/src/runtime/turn-event-stream.ts
|
|
@@ -14724,6 +14866,14 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
14724
14866
|
const toolSummaryOptions = {
|
|
14725
14867
|
cwd: control.injectParams?.cwd ?? workspaceCwdFor(topicId)
|
|
14726
14868
|
};
|
|
14869
|
+
const recordEventUsage = (usage) => {
|
|
14870
|
+
recordUsage(userId, topicTitle, usage, {
|
|
14871
|
+
topicId,
|
|
14872
|
+
...control.sessionId ? { providerSessionId: control.sessionId } : {},
|
|
14873
|
+
agent: agentType,
|
|
14874
|
+
model
|
|
14875
|
+
});
|
|
14876
|
+
};
|
|
14727
14877
|
const nextSyntheticToolUseId = () => `tool-${queryId}-${++syntheticToolCounter}`;
|
|
14728
14878
|
const bindToolUseId = (providerToolUseId, fallback) => {
|
|
14729
14879
|
const providerId = normalizeToolUseId(providerToolUseId);
|
|
@@ -15042,7 +15192,7 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
15042
15192
|
break;
|
|
15043
15193
|
case "result":
|
|
15044
15194
|
if (event.usage)
|
|
15045
|
-
|
|
15195
|
+
recordEventUsage(event.usage);
|
|
15046
15196
|
{
|
|
15047
15197
|
const usage = event.usage ? {
|
|
15048
15198
|
input: event.usage.inputTokens,
|
|
@@ -15092,6 +15242,8 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
15092
15242
|
}
|
|
15093
15243
|
break;
|
|
15094
15244
|
case "error":
|
|
15245
|
+
if (event.usage)
|
|
15246
|
+
recordEventUsage(event.usage);
|
|
15095
15247
|
logger.warn({ topicId, queryId, agentType, model, silent, error: event.content }, "ai: provider returned error");
|
|
15096
15248
|
terminalEmitted = true;
|
|
15097
15249
|
errorOccurred = true;
|
|
@@ -18579,4 +18731,4 @@ export {
|
|
|
18579
18731
|
DEFAULT_SELF_CONFIG_PRODUCT
|
|
18580
18732
|
};
|
|
18581
18733
|
|
|
18582
|
-
//# debugId=
|
|
18734
|
+
//# debugId=969112A1E458C75264756E2164756E21
|