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/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.17";
|
|
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
|
}
|
|
@@ -5724,6 +5834,7 @@ function maestroProvider(opts) {
|
|
|
5724
5834
|
...opts,
|
|
5725
5835
|
enableToolSearch: !opts.toolPolicy && opts.enableToolSearch !== false,
|
|
5726
5836
|
toolResultTruncation: buildMaestroToolResultTruncation(opts),
|
|
5837
|
+
ephemeralSystemPrompt: opts.ephemeralSystemPrompt,
|
|
5727
5838
|
apiKeyOverrides: resolveMaestroApiKeyOverrides(userId),
|
|
5728
5839
|
agent: "maestro",
|
|
5729
5840
|
disallowedTools: buildMaestroDisallowedTools(callerDisallowedTools, opts.toolPolicy),
|
|
@@ -9750,7 +9861,7 @@ var init_runtime_process_leases = __esm(async () => {
|
|
|
9750
9861
|
});
|
|
9751
9862
|
|
|
9752
9863
|
// ../../packages/core/src/agents/mcp-tools/ask-user.ts
|
|
9753
|
-
import { createHash as
|
|
9864
|
+
import { createHash as createHash3, randomUUID as randomUUID9 } from "crypto";
|
|
9754
9865
|
import { z } from "zod";
|
|
9755
9866
|
function normalizeAskText(value, maxChars) {
|
|
9756
9867
|
if (typeof value !== "string")
|
|
@@ -9787,7 +9898,7 @@ function normalizeAskUserQuestionInput(input) {
|
|
|
9787
9898
|
return { question, choices };
|
|
9788
9899
|
}
|
|
9789
9900
|
function askBodyHash(question, choices) {
|
|
9790
|
-
return
|
|
9901
|
+
return createHash3("sha256").update(JSON.stringify({ question, choices })).digest("hex");
|
|
9791
9902
|
}
|
|
9792
9903
|
function answerToolResult(answer) {
|
|
9793
9904
|
if (!answer.userId)
|
|
@@ -10807,7 +10918,7 @@ var init_browser_profiles = __esm(async () => {
|
|
|
10807
10918
|
|
|
10808
10919
|
// ../../packages/core/src/platform/playwright/manager.ts
|
|
10809
10920
|
import { execFileSync as execFileSync7, spawn as spawn5 } from "child_process";
|
|
10810
|
-
import { createHash as
|
|
10921
|
+
import { createHash as createHash4, randomBytes as randomBytes6, timingSafeEqual as timingSafeEqual3 } from "crypto";
|
|
10811
10922
|
import {
|
|
10812
10923
|
cpSync,
|
|
10813
10924
|
existsSync as existsSync17,
|
|
@@ -10902,7 +11013,7 @@ function parseInstanceKey(instanceKey) {
|
|
|
10902
11013
|
};
|
|
10903
11014
|
}
|
|
10904
11015
|
function portFileName(instanceKey) {
|
|
10905
|
-
return
|
|
11016
|
+
return createHash4("sha256").update(instanceKey).digest("hex").slice(0, 24);
|
|
10906
11017
|
}
|
|
10907
11018
|
function writePortFile(instanceKey, port) {
|
|
10908
11019
|
try {
|
|
@@ -12495,7 +12606,7 @@ __export(exports_derive, {
|
|
|
12495
12606
|
TopicForkCompactionError: () => TopicForkCompactionError,
|
|
12496
12607
|
TopicDeriveBusyError: () => TopicDeriveBusyError
|
|
12497
12608
|
});
|
|
12498
|
-
import { createHash as
|
|
12609
|
+
import { createHash as createHash5, randomUUID as randomUUID12 } from "crypto";
|
|
12499
12610
|
import { mkdirSync as mkdirSync13, rmSync as rmSync5, unlinkSync as unlinkSync13 } from "fs";
|
|
12500
12611
|
function getTopics() {
|
|
12501
12612
|
return listTopics().filter((topic) => !isLegacySharedGeneral(topic.id));
|
|
@@ -12561,7 +12672,7 @@ function captureForkSnapshot(sourceTopicId, userId, topicTitle) {
|
|
|
12561
12672
|
maxRowid: messageRows.at(-1)?.rowid ?? 0
|
|
12562
12673
|
},
|
|
12563
12674
|
active: isTopicRunning(sourceTopicId),
|
|
12564
|
-
canonicalDigest:
|
|
12675
|
+
canonicalDigest: createHash5("sha256").update(entries.map((entry) => JSON.stringify(entry)).join(`
|
|
12565
12676
|
`)).digest("hex")
|
|
12566
12677
|
};
|
|
12567
12678
|
}
|
|
@@ -13054,7 +13165,7 @@ __export(exports_session_asks, {
|
|
|
13054
13165
|
clearPendingAsk: () => clearPendingAsk,
|
|
13055
13166
|
PENDING_ASK_TTL_MS: () => PENDING_ASK_TTL_MS
|
|
13056
13167
|
});
|
|
13057
|
-
import { createHash as
|
|
13168
|
+
import { createHash as createHash6 } from "crypto";
|
|
13058
13169
|
import {
|
|
13059
13170
|
closeSync as closeSync2,
|
|
13060
13171
|
mkdirSync as mkdirSync15,
|
|
@@ -13068,14 +13179,14 @@ import {
|
|
|
13068
13179
|
import { dirname as dirname13, join as join24 } from "path";
|
|
13069
13180
|
function pendingAskDir(userId) {
|
|
13070
13181
|
const rawUserId = String(userId);
|
|
13071
|
-
const safeUserId = /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${
|
|
13182
|
+
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
13183
|
return join24(resolveStorageSessionAsksDir(), safeUserId);
|
|
13073
13184
|
}
|
|
13074
13185
|
function encodeAskKey(key) {
|
|
13075
13186
|
return JSON.stringify([key.from, key.to]);
|
|
13076
13187
|
}
|
|
13077
13188
|
function pendingAskPath(key) {
|
|
13078
|
-
const digest =
|
|
13189
|
+
const digest = createHash6("sha256").update(encodeAskKey(key)).digest("hex");
|
|
13079
13190
|
return join24(pendingAskDir(key.userId), `${ASK_FILENAME_PREFIX}${digest}.pending`);
|
|
13080
13191
|
}
|
|
13081
13192
|
function v2PendingAskPath(key) {
|
|
@@ -14654,12 +14765,12 @@ var init_visuals = __esm(async () => {
|
|
|
14654
14765
|
});
|
|
14655
14766
|
|
|
14656
14767
|
// ../../packages/core/src/storage/token-stats.ts
|
|
14657
|
-
import { createHash as
|
|
14768
|
+
import { createHash as createHash7 } from "crypto";
|
|
14658
14769
|
import { mkdirSync as mkdirSync17 } from "fs";
|
|
14659
14770
|
import { join as join26 } from "path";
|
|
14660
14771
|
function tokenStatsFileId(userId) {
|
|
14661
14772
|
const rawUserId = String(userId);
|
|
14662
|
-
return /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${
|
|
14773
|
+
return /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash7("sha256").update(rawUserId).digest("hex")}`;
|
|
14663
14774
|
}
|
|
14664
14775
|
function queriesPath(userId) {
|
|
14665
14776
|
const fileId = tokenStatsFileId(userId);
|
|
@@ -14667,14 +14778,33 @@ function queriesPath(userId) {
|
|
|
14667
14778
|
mkdirSync17(logDir, { recursive: true });
|
|
14668
14779
|
return join26(logDir, `token-queries-${fileId}.jsonl`);
|
|
14669
14780
|
}
|
|
14670
|
-
function
|
|
14781
|
+
function estimateUsageCost(agent, model, usage) {
|
|
14782
|
+
const prices = TOKEN_PRICES[`${agent}:${model}`];
|
|
14783
|
+
if (!prices)
|
|
14784
|
+
return 0;
|
|
14785
|
+
return (usage.inputTokens * prices.input + usage.outputTokens * prices.output + (agent === "claude" ? usage.cacheCreationInputTokens * (prices.cacheWrite ?? prices.input) : 0) + usage.cacheReadInputTokens * prices.cacheRead) / 1e6;
|
|
14786
|
+
}
|
|
14787
|
+
function recordUsage(userId, session, usage, context) {
|
|
14788
|
+
const cacheReadInputTokens = usage.cacheReadInputTokens ?? 0;
|
|
14789
|
+
const inputTokens = context.agent === "claude" ? usage.inputTokens : Math.max(0, usage.inputTokens - cacheReadInputTokens);
|
|
14790
|
+
const normalized = {
|
|
14791
|
+
inputTokens,
|
|
14792
|
+
outputTokens: usage.outputTokens,
|
|
14793
|
+
cacheCreationInputTokens: usage.cacheCreationInputTokens ?? 0,
|
|
14794
|
+
cacheReadInputTokens
|
|
14795
|
+
};
|
|
14671
14796
|
const record = {
|
|
14797
|
+
schemaVersion: 2,
|
|
14672
14798
|
timestamp: new Date().toISOString(),
|
|
14673
14799
|
session,
|
|
14674
|
-
|
|
14675
|
-
|
|
14676
|
-
|
|
14677
|
-
|
|
14800
|
+
topicId: context.topicId,
|
|
14801
|
+
...context.providerSessionId ? { providerSessionId: context.providerSessionId } : {},
|
|
14802
|
+
agent: context.agent,
|
|
14803
|
+
model: context.model,
|
|
14804
|
+
...normalized,
|
|
14805
|
+
...usage.contextTokens !== undefined ? { contextTokens: usage.contextTokens } : {},
|
|
14806
|
+
...usage.contextWindow !== undefined ? { contextWindow: usage.contextWindow } : {},
|
|
14807
|
+
estimatedCostUsd: usage.costUsd ?? estimateUsageCost(context.agent, context.model, normalized)
|
|
14678
14808
|
};
|
|
14679
14809
|
try {
|
|
14680
14810
|
appendJsonlEntry(queriesPath(userId), record);
|
|
@@ -14682,10 +14812,23 @@ function recordUsage(userId, session, usage) {
|
|
|
14682
14812
|
logger.warn({ err: e, userId }, "token-stats: Failed to record");
|
|
14683
14813
|
}
|
|
14684
14814
|
}
|
|
14815
|
+
var TOKEN_PRICES;
|
|
14685
14816
|
var init_token_stats = __esm(async () => {
|
|
14686
14817
|
init_jsonl();
|
|
14687
14818
|
init_logger();
|
|
14688
14819
|
await init_storage_host();
|
|
14820
|
+
TOKEN_PRICES = {
|
|
14821
|
+
"codex:gpt-5.6-sol": { input: 5, cacheRead: 0.5, output: 30 },
|
|
14822
|
+
"codex:gpt-5.6-terra": { input: 2.5, cacheRead: 0.25, output: 15 },
|
|
14823
|
+
"codex:gpt-5.6-luna": { input: 1, cacheRead: 0.1, output: 6 },
|
|
14824
|
+
"claude:fable": { input: 10, cacheWrite: 12.5, cacheRead: 1, output: 50 },
|
|
14825
|
+
"claude:opus": { input: 5, cacheWrite: 6.25, cacheRead: 0.5, output: 25 },
|
|
14826
|
+
"claude:sonnet": { input: 2, cacheWrite: 2.5, cacheRead: 0.2, output: 10 },
|
|
14827
|
+
"maestro:kimi-k3": { input: 3, cacheRead: 0.3, output: 15 },
|
|
14828
|
+
"maestro:kimi-k2.7-code": { input: 0.95, cacheRead: 0.19, output: 4 },
|
|
14829
|
+
"maestro:deepseek-pro": { input: 0.435, cacheRead: 0.003625, output: 0.87 },
|
|
14830
|
+
"maestro:deepseek-flash": { input: 0.14, cacheRead: 0.0028, output: 0.28 }
|
|
14831
|
+
};
|
|
14689
14832
|
});
|
|
14690
14833
|
|
|
14691
14834
|
// ../../packages/core/src/runtime/turn-event-stream.ts
|
|
@@ -14714,6 +14857,9 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
14714
14857
|
let pendingSawDelta = false;
|
|
14715
14858
|
let accumulatedText = "";
|
|
14716
14859
|
let pendingText = "";
|
|
14860
|
+
let assistantContextTokens = 0;
|
|
14861
|
+
let toolContextTokens = 0;
|
|
14862
|
+
let lastContextProgressAt = 0;
|
|
14717
14863
|
let lastVisibleMessageId = null;
|
|
14718
14864
|
const visibleMessageIds = [];
|
|
14719
14865
|
let lastTaskPanelText = null;
|
|
@@ -14724,6 +14870,28 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
14724
14870
|
const toolSummaryOptions = {
|
|
14725
14871
|
cwd: control.injectParams?.cwd ?? workspaceCwdFor(topicId)
|
|
14726
14872
|
};
|
|
14873
|
+
const recordEventUsage = (usage) => {
|
|
14874
|
+
recordUsage(userId, topicTitle, usage, {
|
|
14875
|
+
topicId,
|
|
14876
|
+
...control.sessionId ? { providerSessionId: control.sessionId } : {},
|
|
14877
|
+
agent: agentType,
|
|
14878
|
+
model
|
|
14879
|
+
});
|
|
14880
|
+
};
|
|
14881
|
+
const broadcastContextProgress = (force = false) => {
|
|
14882
|
+
if (silent)
|
|
14883
|
+
return;
|
|
14884
|
+
const now = Date.now();
|
|
14885
|
+
if (!force && lastContextProgressAt > 0 && now - lastContextProgressAt < 250)
|
|
14886
|
+
return;
|
|
14887
|
+
lastContextProgressAt = now;
|
|
14888
|
+
hub.broadcastAiStatus(topicId, {
|
|
14889
|
+
kind: "context_progress",
|
|
14890
|
+
queryId,
|
|
14891
|
+
assistantTokens: assistantContextTokens,
|
|
14892
|
+
toolTokens: toolContextTokens
|
|
14893
|
+
});
|
|
14894
|
+
};
|
|
14727
14895
|
const nextSyntheticToolUseId = () => `tool-${queryId}-${++syntheticToolCounter}`;
|
|
14728
14896
|
const bindToolUseId = (providerToolUseId, fallback) => {
|
|
14729
14897
|
const providerId = normalizeToolUseId(providerToolUseId);
|
|
@@ -14833,6 +15001,8 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
14833
15001
|
const incoming = event.content;
|
|
14834
15002
|
accumulatedText += incoming;
|
|
14835
15003
|
pendingText += incoming;
|
|
15004
|
+
assistantContextTokens = estimateTextTokens(accumulatedText);
|
|
15005
|
+
broadcastContextProgress();
|
|
14836
15006
|
break;
|
|
14837
15007
|
}
|
|
14838
15008
|
case "text":
|
|
@@ -14840,10 +15010,15 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
14840
15010
|
const incoming = event.content;
|
|
14841
15011
|
accumulatedText += incoming;
|
|
14842
15012
|
pendingText += incoming;
|
|
15013
|
+
assistantContextTokens = estimateTextTokens(accumulatedText);
|
|
15014
|
+
broadcastContextProgress();
|
|
14843
15015
|
}
|
|
14844
15016
|
break;
|
|
14845
15017
|
case "tool_use":
|
|
14846
15018
|
emitPendingAssistantMessage();
|
|
15019
|
+
toolContextTokens += estimateTextTokens(`${event.name}
|
|
15020
|
+
${JSON.stringify(event.input ?? {})}`);
|
|
15021
|
+
broadcastContextProgress(true);
|
|
14847
15022
|
if (isVisualsShowHtmlTool(event.name)) {
|
|
14848
15023
|
const input = event.input;
|
|
14849
15024
|
if (typeof input.html !== "string" || input.html.trim().length === 0) {
|
|
@@ -14997,6 +15172,8 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
14997
15172
|
}
|
|
14998
15173
|
break;
|
|
14999
15174
|
case "tool_result":
|
|
15175
|
+
toolContextTokens += estimateTextTokens(event.content);
|
|
15176
|
+
broadcastContextProgress(true);
|
|
15000
15177
|
if (isVisualToolResultHandled(event.toolUseId))
|
|
15001
15178
|
break;
|
|
15002
15179
|
if (!silent) {
|
|
@@ -15042,7 +15219,7 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
15042
15219
|
break;
|
|
15043
15220
|
case "result":
|
|
15044
15221
|
if (event.usage)
|
|
15045
|
-
|
|
15222
|
+
recordEventUsage(event.usage);
|
|
15046
15223
|
{
|
|
15047
15224
|
const usage = event.usage ? {
|
|
15048
15225
|
input: event.usage.inputTokens,
|
|
@@ -15092,6 +15269,8 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
15092
15269
|
}
|
|
15093
15270
|
break;
|
|
15094
15271
|
case "error":
|
|
15272
|
+
if (event.usage)
|
|
15273
|
+
recordEventUsage(event.usage);
|
|
15095
15274
|
logger.warn({ topicId, queryId, agentType, model, silent, error: event.content }, "ai: provider returned error");
|
|
15096
15275
|
terminalEmitted = true;
|
|
15097
15276
|
errorOccurred = true;
|
|
@@ -15380,6 +15559,7 @@ __export(exports_turn_runner, {
|
|
|
15380
15559
|
channelTranscriptSpeaker: () => channelTranscriptSpeaker,
|
|
15381
15560
|
canonicalModelId: () => canonicalModelId,
|
|
15382
15561
|
buildVideoHtml: () => buildVideoHtml,
|
|
15562
|
+
buildTurnReminderQuery: () => buildTurnReminderQuery,
|
|
15383
15563
|
buildMermaidHtml: () => buildMermaidHtml,
|
|
15384
15564
|
buildMentionOnlyChannelPrompt: () => buildMentionOnlyChannelPrompt,
|
|
15385
15565
|
buildImageHtml: () => buildImageHtml,
|
|
@@ -15405,6 +15585,18 @@ function withDefaultPlaywright(configuredMcp, isManager) {
|
|
|
15405
15585
|
enabled.add("background-bash");
|
|
15406
15586
|
return [...enabled];
|
|
15407
15587
|
}
|
|
15588
|
+
function buildTurnReminderQuery(agent, prompt, reminders) {
|
|
15589
|
+
const reminderPrompt = reminders.join(`
|
|
15590
|
+
|
|
15591
|
+
`);
|
|
15592
|
+
if (!reminderPrompt)
|
|
15593
|
+
return { prompt };
|
|
15594
|
+
if (agent === "maestro")
|
|
15595
|
+
return { prompt, ephemeralSystemPrompt: reminderPrompt };
|
|
15596
|
+
return { prompt: `${prompt}
|
|
15597
|
+
|
|
15598
|
+
${reminderPrompt}` };
|
|
15599
|
+
}
|
|
15408
15600
|
function appendSystemMessage(topicId, text2) {
|
|
15409
15601
|
const message = {
|
|
15410
15602
|
id: randomUUID16(),
|
|
@@ -16352,15 +16544,11 @@ function startAiTurn(params) {
|
|
|
16352
16544
|
if (consumePlaywrightUnavailable(userId, topic.title)) {
|
|
16353
16545
|
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>");
|
|
16354
16546
|
}
|
|
16355
|
-
const
|
|
16356
|
-
|
|
16357
|
-
${turnReminders.join(`
|
|
16358
|
-
|
|
16359
|
-
`)}` : agentPrompt;
|
|
16547
|
+
const reminderQuery = buildTurnReminderQuery(agentKind, agentPrompt, turnReminders);
|
|
16360
16548
|
try {
|
|
16361
16549
|
yield* runAgent({
|
|
16362
16550
|
agent: agentKind,
|
|
16363
|
-
|
|
16551
|
+
...reminderQuery,
|
|
16364
16552
|
attachments: promptAttachments,
|
|
16365
16553
|
cwd: workspaceCwd,
|
|
16366
16554
|
systemPrompt,
|
|
@@ -18579,4 +18767,4 @@ export {
|
|
|
18579
18767
|
DEFAULT_SELF_CONFIG_PRODUCT
|
|
18580
18768
|
};
|
|
18581
18769
|
|
|
18582
|
-
//# debugId=
|
|
18770
|
+
//# debugId=814F0B0C425F56EA64756E2164756E21
|