@workerdeck/core 2.8.0 → 2.10.0
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/build/index.d.mts +39 -9
- package/build/index.mjs +293 -46
- package/build/index.mjs.map +1 -1
- package/package.json +3 -3
package/build/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { createHash, randomUUID } from "node:crypto";
|
|
3
3
|
import { getSessionInfo, getSessionMessages, listSessions, query } from "@anthropic-ai/claude-agent-sdk";
|
|
4
|
-
import { CHECKLIST_TEXT_MAX, ENGINE_CAPABILITIES, PROTOCOL_VERSION, SUBAGENT_HISTORY, TOOL_RESULT_HEAD_CHARS, contextReading, imagePartRef, parseTodoWriteInput, replayCoalesceKey, replayRetains, sanitizeToolTitle, snapshotRetains, transcriptActivity, transcriptContent, transcriptProse } from "@workerdeck/protocol";
|
|
4
|
+
import { CHECKLIST_TEXT_MAX, ENGINE_CAPABILITIES, PROTOCOL_VERSION, SUBAGENT_HISTORY, TOOL_RESULT_HEAD_CHARS, addTokenUsage, byModelTotalTokens, canonicalModel, contextReading, costOfByModel, emptyTokenUsage, imagePartRef, mergeByModel, parseTodoWriteInput, replayCoalesceKey, replayRetains, sanitizeToolTitle, snapshotRetains, tokenUsageFromWire, totalTokens, transcriptActivity, transcriptContent, transcriptProse } from "@workerdeck/protocol";
|
|
5
5
|
import { ToolLoopAgent, generateText, isStepCount, tool } from "ai";
|
|
6
6
|
import { execFile, spawn } from "node:child_process";
|
|
7
7
|
import { appendFileSync, existsSync, mkdirSync, readFileSync, realpathSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
@@ -273,6 +273,18 @@ function parseUnifiedDiff(diff, path) {
|
|
|
273
273
|
}
|
|
274
274
|
//#endregion
|
|
275
275
|
//#region src/lib/normalize.ts
|
|
276
|
+
function byModelFromSdk(modelUsage) {
|
|
277
|
+
if (!modelUsage) return;
|
|
278
|
+
const out = {};
|
|
279
|
+
for (const [model, entry] of Object.entries(modelUsage)) out[entry.canonicalModel ?? canonicalModel(model)] = {
|
|
280
|
+
...emptyTokenUsage(),
|
|
281
|
+
input: Math.max(0, entry.inputTokens ?? 0),
|
|
282
|
+
output: Math.max(0, entry.outputTokens ?? 0),
|
|
283
|
+
cacheWrite5m: Math.max(0, entry.cacheCreationInputTokens ?? 0),
|
|
284
|
+
cacheRead: Math.max(0, entry.cacheReadInputTokens ?? 0)
|
|
285
|
+
};
|
|
286
|
+
return Object.keys(out).length === 0 ? void 0 : out;
|
|
287
|
+
}
|
|
276
288
|
const FAMILY_ORDER = [
|
|
277
289
|
"fable",
|
|
278
290
|
"opus",
|
|
@@ -445,7 +457,8 @@ function normalizeSdkMessage(msg) {
|
|
|
445
457
|
totalCostUsd: msg.total_cost_usd,
|
|
446
458
|
result: msg.subtype === "success" ? msg.result : void 0,
|
|
447
459
|
errors: msg.subtype === "success" ? void 0 : msg.errors,
|
|
448
|
-
usage: msg.usage
|
|
460
|
+
usage: msg.usage,
|
|
461
|
+
usageByModel: byModelFromSdk(msg.modelUsage)
|
|
449
462
|
};
|
|
450
463
|
case "conversation_reset": return {
|
|
451
464
|
type: "conversation_reset",
|
|
@@ -480,6 +493,157 @@ function resolveApprovalTimeoutMs(session, fallback) {
|
|
|
480
493
|
return value === void 0 || value === null || value <= 0 ? void 0 : value;
|
|
481
494
|
}
|
|
482
495
|
//#endregion
|
|
496
|
+
//#region src/lib/cost-ledger.ts
|
|
497
|
+
function emptyBucket() {
|
|
498
|
+
return {
|
|
499
|
+
byModel: {},
|
|
500
|
+
reportedUsd: void 0
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
function bucketOf(figures) {
|
|
504
|
+
return {
|
|
505
|
+
byModel: figures.byModel ?? {},
|
|
506
|
+
reportedUsd: figures.reportedCostUsd
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
function figuresOf(bucket) {
|
|
510
|
+
return {
|
|
511
|
+
byModel: Object.keys(bucket.byModel).length === 0 ? void 0 : bucket.byModel,
|
|
512
|
+
reportedCostUsd: bucket.reportedUsd
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
function addBuckets(into, add) {
|
|
516
|
+
const reportedUsd = into.reportedUsd === void 0 && add.reportedUsd === void 0 ? void 0 : (into.reportedUsd ?? 0) + (add.reportedUsd ?? 0);
|
|
517
|
+
return {
|
|
518
|
+
byModel: mergeByModel(into.byModel, add.byModel),
|
|
519
|
+
reportedUsd
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
function subtractUsage(from, part) {
|
|
523
|
+
return {
|
|
524
|
+
input: Math.max(0, from.input - part.input),
|
|
525
|
+
output: Math.max(0, from.output - part.output),
|
|
526
|
+
cacheWrite5m: Math.max(0, from.cacheWrite5m - part.cacheWrite5m),
|
|
527
|
+
cacheWrite1h: Math.max(0, from.cacheWrite1h - part.cacheWrite1h),
|
|
528
|
+
cacheRead: Math.max(0, from.cacheRead - part.cacheRead)
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
function subtractBuckets(from, part) {
|
|
532
|
+
const byModel = {};
|
|
533
|
+
for (const [model, usage] of Object.entries(from.byModel)) {
|
|
534
|
+
const taken = part.byModel[model];
|
|
535
|
+
const rest = taken ? subtractUsage(usage, taken) : usage;
|
|
536
|
+
if (totalTokens(rest) > 0) byModel[model] = rest;
|
|
537
|
+
}
|
|
538
|
+
return {
|
|
539
|
+
byModel,
|
|
540
|
+
reportedUsd: from.reportedUsd === void 0 ? void 0 : Math.max(0, from.reportedUsd - (part.reportedUsd ?? 0))
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
function isEmpty(bucket) {
|
|
544
|
+
return byModelTotalTokens(bucket.byModel) === 0 && !((bucket.reportedUsd ?? 0) > 0);
|
|
545
|
+
}
|
|
546
|
+
function canonicalByModel(byModel) {
|
|
547
|
+
const out = {};
|
|
548
|
+
for (const [model, usage] of Object.entries(byModel)) {
|
|
549
|
+
const key = canonicalModel(model);
|
|
550
|
+
out[key] = addTokenUsage(out[key] ?? emptyTokenUsage(), usage);
|
|
551
|
+
}
|
|
552
|
+
return out;
|
|
553
|
+
}
|
|
554
|
+
function coversUsage(have, need) {
|
|
555
|
+
return have.input >= need.input && have.output >= need.output && have.cacheWrite5m >= need.cacheWrite5m && have.cacheWrite1h >= need.cacheWrite1h && have.cacheRead >= need.cacheRead;
|
|
556
|
+
}
|
|
557
|
+
function covers(reading, baseline) {
|
|
558
|
+
let compared = false;
|
|
559
|
+
if (baseline.reportedUsd !== void 0 && reading.reportedUsd !== void 0) {
|
|
560
|
+
if (reading.reportedUsd < baseline.reportedUsd) return false;
|
|
561
|
+
compared = true;
|
|
562
|
+
}
|
|
563
|
+
if (byModelTotalTokens(reading.byModel) > 0 && byModelTotalTokens(baseline.byModel) > 0) {
|
|
564
|
+
const have = canonicalByModel(reading.byModel);
|
|
565
|
+
for (const [model, need] of Object.entries(canonicalByModel(baseline.byModel))) {
|
|
566
|
+
if (totalTokens(need) === 0) continue;
|
|
567
|
+
const got = have[model];
|
|
568
|
+
if (!got || !coversUsage(got, need)) return false;
|
|
569
|
+
}
|
|
570
|
+
compared = true;
|
|
571
|
+
}
|
|
572
|
+
return compared;
|
|
573
|
+
}
|
|
574
|
+
var CostLedger = class {
|
|
575
|
+
#carried = emptyBucket();
|
|
576
|
+
#pending;
|
|
577
|
+
#current = emptyBucket();
|
|
578
|
+
carry(state) {
|
|
579
|
+
if (!state) return;
|
|
580
|
+
this.#carried = addBuckets(this.#carried, bucketOf(state));
|
|
581
|
+
}
|
|
582
|
+
carryUnlessRestored(state) {
|
|
583
|
+
if (!state) return;
|
|
584
|
+
const whole = bucketOf(state);
|
|
585
|
+
const lifetime = state.lifetime ? bucketOf(state.lifetime) : whole;
|
|
586
|
+
if (state.lifetime) this.#carried = addBuckets(this.#carried, subtractBuckets(whole, lifetime));
|
|
587
|
+
this.#pending = addBuckets(this.#pending ?? emptyBucket(), lifetime);
|
|
588
|
+
}
|
|
589
|
+
observeCumulative(byModel, reportedCostUsd) {
|
|
590
|
+
const reading = {
|
|
591
|
+
byModel: byModel ?? {},
|
|
592
|
+
reportedUsd: reportedCostUsd
|
|
593
|
+
};
|
|
594
|
+
if (this.#pending && !isEmpty(reading)) {
|
|
595
|
+
if (!covers(reading, this.#pending)) this.#carried = addBuckets(this.#carried, this.#pending);
|
|
596
|
+
this.#pending = void 0;
|
|
597
|
+
}
|
|
598
|
+
if (byModel !== void 0) this.#current = {
|
|
599
|
+
...this.#current,
|
|
600
|
+
byModel
|
|
601
|
+
};
|
|
602
|
+
if (reportedCostUsd !== void 0) this.#current = {
|
|
603
|
+
...this.#current,
|
|
604
|
+
reportedUsd: reportedCostUsd
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
observeDelta(byModel) {
|
|
608
|
+
this.#current = {
|
|
609
|
+
...this.#current,
|
|
610
|
+
byModel: mergeByModel(this.#current.byModel, byModel)
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
rollover() {
|
|
614
|
+
this.#carried = addBuckets(this.#carried, this.#lifetime());
|
|
615
|
+
this.#pending = void 0;
|
|
616
|
+
this.#current = emptyBucket();
|
|
617
|
+
}
|
|
618
|
+
get byModel() {
|
|
619
|
+
return figuresOf(this.#total()).byModel;
|
|
620
|
+
}
|
|
621
|
+
get breakdown() {
|
|
622
|
+
return costOfByModel(this.byModel ?? {});
|
|
623
|
+
}
|
|
624
|
+
get costUsd() {
|
|
625
|
+
const byModel = this.byModel;
|
|
626
|
+
if (!byModel) return;
|
|
627
|
+
const cost = costOfByModel(byModel);
|
|
628
|
+
return cost.unpriced ? void 0 : cost.total;
|
|
629
|
+
}
|
|
630
|
+
get reportedCostUsd() {
|
|
631
|
+
return this.#total().reportedUsd;
|
|
632
|
+
}
|
|
633
|
+
snapshot() {
|
|
634
|
+
return {
|
|
635
|
+
...figuresOf(this.#total()),
|
|
636
|
+
lifetime: figuresOf(this.#lifetime())
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
#lifetime() {
|
|
640
|
+
return addBuckets(this.#pending ?? emptyBucket(), this.#current);
|
|
641
|
+
}
|
|
642
|
+
#total() {
|
|
643
|
+
return addBuckets(this.#carried, this.#lifetime());
|
|
644
|
+
}
|
|
645
|
+
};
|
|
646
|
+
//#endregion
|
|
483
647
|
//#region src/lib/event-log.ts
|
|
484
648
|
var EventLog = class {
|
|
485
649
|
#events = [];
|
|
@@ -904,6 +1068,7 @@ function toolUseBlocks(content) {
|
|
|
904
1068
|
}
|
|
905
1069
|
//#endregion
|
|
906
1070
|
//#region src/engines/claude/runner.ts
|
|
1071
|
+
const USAGE_REFRESH_MIN_MS = 6e4;
|
|
907
1072
|
var SessionRunner = class {
|
|
908
1073
|
id;
|
|
909
1074
|
createdAt;
|
|
@@ -920,7 +1085,7 @@ var SessionRunner = class {
|
|
|
920
1085
|
#pending = /* @__PURE__ */ new Map();
|
|
921
1086
|
#turnOverWhileBlocked = false;
|
|
922
1087
|
#subagents = new SubagentTracker();
|
|
923
|
-
#
|
|
1088
|
+
#cost = new CostLedger();
|
|
924
1089
|
#numTurns;
|
|
925
1090
|
#input = new InputQueue();
|
|
926
1091
|
#pendingLocalCommands = [];
|
|
@@ -929,8 +1094,11 @@ var SessionRunner = class {
|
|
|
929
1094
|
#idleWhileCompacting = false;
|
|
930
1095
|
#query;
|
|
931
1096
|
#capabilitiesEmitted = false;
|
|
1097
|
+
#models;
|
|
1098
|
+
#defaultModel;
|
|
932
1099
|
#subscriptionType;
|
|
933
1100
|
#engineTitle;
|
|
1101
|
+
#lastRateLimitPoll = 0;
|
|
934
1102
|
#started = false;
|
|
935
1103
|
#closed = false;
|
|
936
1104
|
#runPromise;
|
|
@@ -982,7 +1150,9 @@ var SessionRunner = class {
|
|
|
982
1150
|
meta: this.#config.meta,
|
|
983
1151
|
scope: this.#config.scope,
|
|
984
1152
|
title: sessionTitle(this.#config, this.#engineTitle),
|
|
985
|
-
totalCostUsd: this.#
|
|
1153
|
+
totalCostUsd: this.#cost.reportedCostUsd,
|
|
1154
|
+
costUsd: this.#cost.costUsd,
|
|
1155
|
+
usageByModel: this.#cost.byModel,
|
|
986
1156
|
numTurns: this.#numTurns,
|
|
987
1157
|
lastActivityAt: this.#log.lastActivityAt
|
|
988
1158
|
};
|
|
@@ -990,6 +1160,12 @@ var SessionRunner = class {
|
|
|
990
1160
|
setTitle(title) {
|
|
991
1161
|
this.#config = withTitle(this.#config, title);
|
|
992
1162
|
}
|
|
1163
|
+
carryCost(state) {
|
|
1164
|
+
this.#cost.carryUnlessRestored(state);
|
|
1165
|
+
}
|
|
1166
|
+
costState() {
|
|
1167
|
+
return this.#cost.snapshot();
|
|
1168
|
+
}
|
|
993
1169
|
start() {
|
|
994
1170
|
if (this.#started) return this.#runPromise;
|
|
995
1171
|
this.#started = true;
|
|
@@ -1254,6 +1430,10 @@ var SessionRunner = class {
|
|
|
1254
1430
|
else if (msg.state === "running") this.#setStatus("running");
|
|
1255
1431
|
return;
|
|
1256
1432
|
}
|
|
1433
|
+
if (msg.type === "system" && msg.subtype === "commands_changed") {
|
|
1434
|
+
if (this.#capabilitiesEmitted && !this.#closed) this.#emitCapabilities(msg.commands);
|
|
1435
|
+
return;
|
|
1436
|
+
}
|
|
1257
1437
|
if (msg.type === "system" && msg.subtype === "status") this.#handleCompactionStatus(msg);
|
|
1258
1438
|
if (msg.type === "system" && msg.subtype === "compact_boundary") {
|
|
1259
1439
|
const meta = msg.compact_metadata;
|
|
@@ -1269,6 +1449,7 @@ var SessionRunner = class {
|
|
|
1269
1449
|
if (body) {
|
|
1270
1450
|
this.#emit(body);
|
|
1271
1451
|
if (body.type === "conversation_reset") {
|
|
1452
|
+
this.#cost.rollover();
|
|
1272
1453
|
this.#pendingLocalCommands = [];
|
|
1273
1454
|
if (body.sdkSessionId) this.#sdkSessionId = body.sdkSessionId;
|
|
1274
1455
|
this.#fetchContextUsage();
|
|
@@ -1276,7 +1457,10 @@ var SessionRunner = class {
|
|
|
1276
1457
|
if (body.type === "turn_result") {
|
|
1277
1458
|
this.#compactionTurns += 1;
|
|
1278
1459
|
if (this.#compactionTurns > 1) this.#settleCompaction();
|
|
1279
|
-
this.#
|
|
1460
|
+
this.#cost.observeCumulative(body.usageByModel, body.totalCostUsd);
|
|
1461
|
+
body.totalCostUsd = this.#cost.reportedCostUsd ?? body.totalCostUsd;
|
|
1462
|
+
body.usageByModel = this.#cost.byModel;
|
|
1463
|
+
body.costUsd = this.#cost.costUsd;
|
|
1280
1464
|
this.#numTurns = body.numTurns;
|
|
1281
1465
|
if (this.#pending.size === 0) this.#setStatus("idle");
|
|
1282
1466
|
else this.#turnOverWhileBlocked = true;
|
|
@@ -1330,19 +1514,24 @@ var SessionRunner = class {
|
|
|
1330
1514
|
const [models, commands] = await Promise.all([query.supportedModels(), query.supportedCommands()]);
|
|
1331
1515
|
if (this.#closed || this.#capabilitiesEmitted) return;
|
|
1332
1516
|
this.#capabilitiesEmitted = true;
|
|
1333
|
-
this.#
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
defaultModel: defaultModelFromSdk(models),
|
|
1337
|
-
commands: commands.map((c) => ({
|
|
1338
|
-
name: c.name,
|
|
1339
|
-
description: c.description,
|
|
1340
|
-
argumentHint: c.argumentHint,
|
|
1341
|
-
aliases: c.aliases
|
|
1342
|
-
}))
|
|
1343
|
-
});
|
|
1517
|
+
this.#models = modelOptionsFromSdk(models);
|
|
1518
|
+
this.#defaultModel = defaultModelFromSdk(models);
|
|
1519
|
+
this.#emitCapabilities(commands);
|
|
1344
1520
|
} catch {}
|
|
1345
1521
|
}
|
|
1522
|
+
#emitCapabilities(commands) {
|
|
1523
|
+
this.#emit({
|
|
1524
|
+
type: "capabilities",
|
|
1525
|
+
models: this.#models ?? [],
|
|
1526
|
+
defaultModel: this.#defaultModel,
|
|
1527
|
+
commands: commands.map((c) => ({
|
|
1528
|
+
name: c.name,
|
|
1529
|
+
description: c.description,
|
|
1530
|
+
argumentHint: c.argumentHint,
|
|
1531
|
+
aliases: c.aliases
|
|
1532
|
+
}))
|
|
1533
|
+
});
|
|
1534
|
+
}
|
|
1346
1535
|
async #fetchEngineTitle() {
|
|
1347
1536
|
if (hostTitle(this.#config.meta)) return;
|
|
1348
1537
|
const sdkSessionId = this.#sdkSessionId;
|
|
@@ -1378,7 +1567,12 @@ var SessionRunner = class {
|
|
|
1378
1567
|
});
|
|
1379
1568
|
} catch {}
|
|
1380
1569
|
}
|
|
1570
|
+
async refreshUsage(minIntervalMs = USAGE_REFRESH_MIN_MS) {
|
|
1571
|
+
if (Date.now() - this.#lastRateLimitPoll < minIntervalMs) return;
|
|
1572
|
+
await this.#fetchRateLimits();
|
|
1573
|
+
}
|
|
1381
1574
|
async #fetchRateLimits() {
|
|
1575
|
+
this.#lastRateLimitPoll = Date.now();
|
|
1382
1576
|
const query = this.#query;
|
|
1383
1577
|
const fetchUsage = query?.usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET;
|
|
1384
1578
|
if (typeof fetchUsage !== "function") return;
|
|
@@ -1569,12 +1763,7 @@ var AiSdkRunner = class {
|
|
|
1569
1763
|
#abort;
|
|
1570
1764
|
#turnAccum;
|
|
1571
1765
|
#numTurns = 0;
|
|
1572
|
-
#
|
|
1573
|
-
input: 0,
|
|
1574
|
-
output: 0,
|
|
1575
|
-
cacheWrite: 0,
|
|
1576
|
-
cacheRead: 0
|
|
1577
|
-
};
|
|
1766
|
+
#cost = new CostLedger();
|
|
1578
1767
|
#started = false;
|
|
1579
1768
|
#closed = false;
|
|
1580
1769
|
#parked = false;
|
|
@@ -1598,10 +1787,15 @@ var AiSdkRunner = class {
|
|
|
1598
1787
|
this.#log.restore(snapshot.events, snapshot.seq, state.lastActivityAt);
|
|
1599
1788
|
this.#messages = [...state.messages];
|
|
1600
1789
|
this.#pendingLocalCommands = [...state.pendingLocalCommands ?? []];
|
|
1601
|
-
for (const call of state.pendingToolCalls)
|
|
1790
|
+
for (const call of state.pendingToolCalls) {
|
|
1791
|
+
const legacy = call.deferred;
|
|
1792
|
+
this.#pendingToolCalls.set(call.toolCallId, legacy === void 0 ? call : {
|
|
1793
|
+
...call,
|
|
1794
|
+
parkable: call.parkable ?? legacy
|
|
1795
|
+
});
|
|
1796
|
+
}
|
|
1602
1797
|
this.#dispatched = new Set(state.dispatched);
|
|
1603
1798
|
this.#numTurns = state.numTurns;
|
|
1604
|
-
this.#totalUsage = { ...state.totalUsage };
|
|
1605
1799
|
this.#turnAccum = state.turnAccum ? { ...state.turnAccum } : void 0;
|
|
1606
1800
|
if (this.#turnAccum && state.parkedAt !== void 0) this.#turnAccum.startedAt += Date.now() - state.parkedAt;
|
|
1607
1801
|
this.#permissionMode = state.permissionMode;
|
|
@@ -1654,9 +1848,20 @@ var AiSdkRunner = class {
|
|
|
1654
1848
|
scope: this.#config.scope,
|
|
1655
1849
|
title: sessionTitle(this.#config),
|
|
1656
1850
|
numTurns: this.#numTurns || void 0,
|
|
1851
|
+
costUsd: this.#cost.costUsd,
|
|
1852
|
+
usageByModel: this.#cost.byModel,
|
|
1657
1853
|
lastActivityAt: this.#log.lastActivityAt
|
|
1658
1854
|
};
|
|
1659
1855
|
}
|
|
1856
|
+
carryCost(state) {
|
|
1857
|
+
this.#cost.carry(state);
|
|
1858
|
+
}
|
|
1859
|
+
costState() {
|
|
1860
|
+
return this.#cost.snapshot();
|
|
1861
|
+
}
|
|
1862
|
+
#turnByModel(accum) {
|
|
1863
|
+
return { [this.#modelId() ?? "unknown"]: tokenUsageFromWire(turnUsage(accum)) };
|
|
1864
|
+
}
|
|
1660
1865
|
start() {
|
|
1661
1866
|
if (this.#started) return this.#turnChain;
|
|
1662
1867
|
this.#started = true;
|
|
@@ -1694,7 +1899,6 @@ var AiSdkRunner = class {
|
|
|
1694
1899
|
pendingToolCalls: [...this.#pendingToolCalls.values()],
|
|
1695
1900
|
dispatched: [...this.#dispatched],
|
|
1696
1901
|
numTurns: this.#numTurns,
|
|
1697
|
-
totalUsage: { ...this.#totalUsage },
|
|
1698
1902
|
turnAccum: this.#turnAccum ? { ...this.#turnAccum } : void 0,
|
|
1699
1903
|
permissionMode: this.#permissionMode,
|
|
1700
1904
|
model: this.#modelAlias,
|
|
@@ -2072,14 +2276,14 @@ var AiSdkRunner = class {
|
|
|
2072
2276
|
signal: this.#abort?.signal
|
|
2073
2277
|
};
|
|
2074
2278
|
const profile = executor.describe?.(toolCall) ?? {};
|
|
2075
|
-
call.
|
|
2279
|
+
call.parkable = profile.deferred === true ? true : void 0;
|
|
2076
2280
|
call.expiresAt = profile.timeoutMs === void 0 ? void 0 : Date.now() + profile.timeoutMs;
|
|
2077
2281
|
this.#emit({
|
|
2078
2282
|
type: "execution_dispatched",
|
|
2079
2283
|
executionId: call.toolCallId,
|
|
2080
2284
|
toolName: call.toolName,
|
|
2081
2285
|
backend: profile.backend ?? this.#config.executionBackend ?? "server",
|
|
2082
|
-
deferred: call.
|
|
2286
|
+
deferred: call.parkable,
|
|
2083
2287
|
expiresAt: call.expiresAt
|
|
2084
2288
|
});
|
|
2085
2289
|
const promise = executor.dispatch(toolCall).then((dispatch) => {
|
|
@@ -2092,7 +2296,7 @@ var AiSdkRunner = class {
|
|
|
2092
2296
|
});
|
|
2093
2297
|
});
|
|
2094
2298
|
return {
|
|
2095
|
-
deferred: call.
|
|
2299
|
+
deferred: call.parkable === true,
|
|
2096
2300
|
promise
|
|
2097
2301
|
};
|
|
2098
2302
|
}
|
|
@@ -2102,7 +2306,7 @@ var AiSdkRunner = class {
|
|
|
2102
2306
|
}
|
|
2103
2307
|
#restingOnDeferred() {
|
|
2104
2308
|
if (this.#pendingToolCalls.size === 0) return false;
|
|
2105
|
-
for (const call of this.#pendingToolCalls.values()) if (call.
|
|
2309
|
+
for (const call of this.#pendingToolCalls.values()) if (call.parkable !== true) return false;
|
|
2106
2310
|
return true;
|
|
2107
2311
|
}
|
|
2108
2312
|
#applyExecutionResult(executionId, result) {
|
|
@@ -2340,10 +2544,8 @@ var AiSdkRunner = class {
|
|
|
2340
2544
|
cacheRead: 0
|
|
2341
2545
|
};
|
|
2342
2546
|
this.#numTurns += 1;
|
|
2343
|
-
this.#
|
|
2344
|
-
this.#
|
|
2345
|
-
this.#totalUsage.cacheWrite += accum.cacheWrite;
|
|
2346
|
-
this.#totalUsage.cacheRead += accum.cacheRead;
|
|
2547
|
+
const byModel = this.#turnByModel(accum);
|
|
2548
|
+
this.#cost.observeDelta(byModel);
|
|
2347
2549
|
this.#emit({
|
|
2348
2550
|
type: "turn_result",
|
|
2349
2551
|
subtype: "success",
|
|
@@ -2352,7 +2554,9 @@ var AiSdkRunner = class {
|
|
|
2352
2554
|
numTurns: this.#numTurns,
|
|
2353
2555
|
totalCostUsd: 0,
|
|
2354
2556
|
result: text,
|
|
2355
|
-
usage: turnUsage(accum)
|
|
2557
|
+
usage: turnUsage(accum),
|
|
2558
|
+
usageByModel: this.#cost.byModel,
|
|
2559
|
+
costUsd: this.#cost.costUsd
|
|
2356
2560
|
});
|
|
2357
2561
|
this.#turnAccum = void 0;
|
|
2358
2562
|
this.#setStatus("idle");
|
|
@@ -3999,6 +4203,29 @@ function skillInfo(skill) {
|
|
|
3999
4203
|
enabled: skill.enabled !== false
|
|
4000
4204
|
};
|
|
4001
4205
|
}
|
|
4206
|
+
const SKILL_MENTION = /(^|[^A-Za-z0-9_$-])\$([a-z0-9][a-z0-9-]*)(?![A-Za-z0-9_-])/g;
|
|
4207
|
+
function withSkillItems(input, paths) {
|
|
4208
|
+
const present = new Set(input.flatMap((item) => item.type === "skill" ? [item.name] : []));
|
|
4209
|
+
const added = [];
|
|
4210
|
+
for (const item of input) {
|
|
4211
|
+
if (item.type !== "text") continue;
|
|
4212
|
+
for (const match of item.text.matchAll(SKILL_MENTION)) {
|
|
4213
|
+
const name = match[2];
|
|
4214
|
+
const path = paths.get(name);
|
|
4215
|
+
if (path === void 0 || present.has(name)) continue;
|
|
4216
|
+
present.add(name);
|
|
4217
|
+
added.push({
|
|
4218
|
+
type: "skill",
|
|
4219
|
+
name,
|
|
4220
|
+
path
|
|
4221
|
+
});
|
|
4222
|
+
}
|
|
4223
|
+
}
|
|
4224
|
+
return added.length > 0 ? [...input, ...added] : [...input];
|
|
4225
|
+
}
|
|
4226
|
+
function mentionsSkill(input) {
|
|
4227
|
+
return input.some((item) => item.type === "text" && /(^|[^A-Za-z0-9_$-])\$[a-z0-9]/.test(item.text));
|
|
4228
|
+
}
|
|
4002
4229
|
function mcpStatusOf(authStatus, update, hasTools) {
|
|
4003
4230
|
if (update?.status === "failed") return update.failureReason === "reauthenticationRequired" ? "needs-auth" : "failed";
|
|
4004
4231
|
if (update?.status === "cancelled") return "failed";
|
|
@@ -4227,7 +4454,7 @@ var CodexRunner = class {
|
|
|
4227
4454
|
#workspaceWrite;
|
|
4228
4455
|
#threadLoaded = false;
|
|
4229
4456
|
#numTurns = 0;
|
|
4230
|
-
#
|
|
4457
|
+
#cost = new CostLedger();
|
|
4231
4458
|
#started = false;
|
|
4232
4459
|
#closed = false;
|
|
4233
4460
|
#imageDir;
|
|
@@ -4237,6 +4464,7 @@ var CodexRunner = class {
|
|
|
4237
4464
|
#replayingHistory = false;
|
|
4238
4465
|
#skillsFingerprint;
|
|
4239
4466
|
#skillsRefresh;
|
|
4467
|
+
#skillPaths = /* @__PURE__ */ new Map();
|
|
4240
4468
|
#producedPaths = /* @__PURE__ */ new Set();
|
|
4241
4469
|
#mcpStatus = /* @__PURE__ */ new Map();
|
|
4242
4470
|
#agents = new CodexAgentTracker();
|
|
@@ -4294,7 +4522,9 @@ var CodexRunner = class {
|
|
|
4294
4522
|
meta: this.#config.meta,
|
|
4295
4523
|
scope: this.#config.scope,
|
|
4296
4524
|
title: sessionTitle(this.#config),
|
|
4297
|
-
totalCostUsd: this.#
|
|
4525
|
+
totalCostUsd: this.#cost.reportedCostUsd,
|
|
4526
|
+
costUsd: this.#cost.costUsd,
|
|
4527
|
+
usageByModel: this.#cost.byModel,
|
|
4298
4528
|
numTurns: this.#numTurns || void 0,
|
|
4299
4529
|
lastActivityAt: this.#log.lastActivityAt,
|
|
4300
4530
|
subagents: this.#agents.list(),
|
|
@@ -4304,6 +4534,12 @@ var CodexRunner = class {
|
|
|
4304
4534
|
setTitle(title) {
|
|
4305
4535
|
this.#config = withTitle(this.#config, title);
|
|
4306
4536
|
}
|
|
4537
|
+
carryCost(state) {
|
|
4538
|
+
this.#cost.carry(state);
|
|
4539
|
+
}
|
|
4540
|
+
costState() {
|
|
4541
|
+
return this.#cost.snapshot();
|
|
4542
|
+
}
|
|
4307
4543
|
start() {
|
|
4308
4544
|
if (this.#started) return this.#turnChain;
|
|
4309
4545
|
this.#started = true;
|
|
@@ -4460,7 +4696,7 @@ var CodexRunner = class {
|
|
|
4460
4696
|
type: "text",
|
|
4461
4697
|
text: context
|
|
4462
4698
|
});
|
|
4463
|
-
return parts;
|
|
4699
|
+
return withSkillItems(parts, this.#skillPaths);
|
|
4464
4700
|
}
|
|
4465
4701
|
queueLocalCommand(result) {
|
|
4466
4702
|
if (this.#closed) throw new Error("session is closed");
|
|
@@ -4692,11 +4928,14 @@ var CodexRunner = class {
|
|
|
4692
4928
|
const entries = Array.isArray(result?.data) ? result.data : [];
|
|
4693
4929
|
const seen = /* @__PURE__ */ new Set();
|
|
4694
4930
|
const skills = [];
|
|
4931
|
+
const paths = /* @__PURE__ */ new Map();
|
|
4695
4932
|
for (const entry of entries) for (const skill of entry?.skills ?? []) {
|
|
4696
4933
|
if (typeof skill?.name !== "string" || seen.has(skill.name)) continue;
|
|
4697
4934
|
seen.add(skill.name);
|
|
4698
4935
|
skills.push(skillInfo(skill));
|
|
4936
|
+
if (typeof skill.path === "string" && skill.path) paths.set(skill.name, skill.path);
|
|
4699
4937
|
}
|
|
4938
|
+
this.#skillPaths = paths;
|
|
4700
4939
|
skills.sort((a, b) => a.name.localeCompare(b.name));
|
|
4701
4940
|
const fingerprint = JSON.stringify(skills);
|
|
4702
4941
|
if (fingerprint === this.#skillsFingerprint) return;
|
|
@@ -4848,6 +5087,10 @@ var CodexRunner = class {
|
|
|
4848
5087
|
this.#activeTurn = active;
|
|
4849
5088
|
try {
|
|
4850
5089
|
const connection = await this.#ensureThread();
|
|
5090
|
+
if (mentionsSkill(turn.input)) {
|
|
5091
|
+
await this.#skillsRefresh;
|
|
5092
|
+
turn.input = withSkillItems(turn.input, this.#skillPaths);
|
|
5093
|
+
}
|
|
4851
5094
|
const params = {
|
|
4852
5095
|
threadId: this.#sdkSessionId,
|
|
4853
5096
|
input: turn.input,
|
|
@@ -5395,23 +5638,27 @@ var CodexRunner = class {
|
|
|
5395
5638
|
message: "Turn ended"
|
|
5396
5639
|
}, "policy");
|
|
5397
5640
|
this.#numTurns += 1;
|
|
5398
|
-
this.#totalCostUsd = 0;
|
|
5399
5641
|
const usage = active.sawUsage ? active.usage : void 0;
|
|
5642
|
+
const wire = usage ? {
|
|
5643
|
+
input_tokens: Math.max(0, usage.inputTokens - usage.cachedInputTokens),
|
|
5644
|
+
output_tokens: usage.outputTokens + usage.reasoningOutputTokens,
|
|
5645
|
+
cache_creation_input_tokens: usage.cacheWriteInputTokens ?? 0,
|
|
5646
|
+
cache_read_input_tokens: usage.cachedInputTokens
|
|
5647
|
+
} : void 0;
|
|
5648
|
+
const turnByModel = wire ? { [this.#model ?? this.#resolvedModel ?? "unknown"]: tokenUsageFromWire(wire) } : void 0;
|
|
5649
|
+
if (turnByModel) this.#cost.observeDelta(turnByModel);
|
|
5400
5650
|
this.#emit({
|
|
5401
5651
|
type: "turn_result",
|
|
5402
5652
|
subtype: kind === "success" ? "success" : "error_during_execution",
|
|
5403
5653
|
isError: kind !== "success",
|
|
5404
5654
|
durationMs: Date.now() - startedAt,
|
|
5405
5655
|
numTurns: this.#numTurns,
|
|
5406
|
-
totalCostUsd: 0,
|
|
5656
|
+
totalCostUsd: this.#cost.reportedCostUsd ?? 0,
|
|
5407
5657
|
result: kind === "success" ? active.finalText ?? "" : void 0,
|
|
5408
5658
|
errors,
|
|
5409
|
-
usage:
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
cache_creation_input_tokens: usage.cacheWriteInputTokens ?? 0,
|
|
5413
|
-
cache_read_input_tokens: usage.cachedInputTokens
|
|
5414
|
-
} : void 0
|
|
5659
|
+
usage: wire,
|
|
5660
|
+
usageByModel: this.#cost.byModel,
|
|
5661
|
+
costUsd: this.#cost.costUsd
|
|
5415
5662
|
});
|
|
5416
5663
|
this.#emitContextUsage(active);
|
|
5417
5664
|
this.#setStatus("idle");
|
|
@@ -5783,6 +6030,6 @@ function getEngineAdapter(engine) {
|
|
|
5783
6030
|
return ADAPTERS[engine ?? "claude"];
|
|
5784
6031
|
}
|
|
5785
6032
|
//#endregion
|
|
5786
|
-
export { AiSdkRunner, BrowserBridgeExecutor, CLAUDE_CATALOG, CODEX_CATALOG, CodexRunner, DeferredExecutor, InputQueue, JsonRpcError, JsonRpcStdioConnection, PendingRequestRegistry, QuickJsExecutor, SUPPORTED_ATTACHMENT_TYPES, SessionRunner, attachmentContentBlocks, attachmentKind, attachmentRef, checkClaudeAuth, claudeAdapter, codexAdapter, connectAppServer, connectMcpTools, createEngineSession, createToolContext, createWebFetch, getEngineAdapter, htmlToMarkdown, isHostAllowed, isPrivateAddress, listCodexSessions, localCommandContext, localCommandTranscript, mcpStatusInfo, modelOptionsFromSdk, normalizeMediaType, normalizeSdkMessage, providerAdapter, replaySlice, resolveBundledClaudeExecutable, resolveBundledCodexExecutable, toApiMessage, toExecutionResult, truncateResultBlocks, withHostTools, withMcpTools };
|
|
6033
|
+
export { AiSdkRunner, BrowserBridgeExecutor, CLAUDE_CATALOG, CODEX_CATALOG, CodexRunner, CostLedger, DeferredExecutor, InputQueue, JsonRpcError, JsonRpcStdioConnection, PendingRequestRegistry, QuickJsExecutor, SUPPORTED_ATTACHMENT_TYPES, SessionRunner, attachmentContentBlocks, attachmentKind, attachmentRef, checkClaudeAuth, claudeAdapter, codexAdapter, connectAppServer, connectMcpTools, createEngineSession, createToolContext, createWebFetch, getEngineAdapter, htmlToMarkdown, isHostAllowed, isPrivateAddress, listCodexSessions, localCommandContext, localCommandTranscript, mcpStatusInfo, modelOptionsFromSdk, normalizeMediaType, normalizeSdkMessage, providerAdapter, replaySlice, resolveBundledClaudeExecutable, resolveBundledCodexExecutable, toApiMessage, toExecutionResult, truncateResultBlocks, withHostTools, withMcpTools };
|
|
5787
6034
|
|
|
5788
6035
|
//# sourceMappingURL=index.mjs.map
|