@sagentlab/navarch-runtime 0.1.30 → 0.1.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/claude.cjs +7 -1
- package/dist/adapters/codex.cjs +1 -0
- package/dist/adapters/opencode.cjs +5 -0
- package/dist/exit-conditions.cjs +31 -4
- package/dist/prompt.cjs +2 -1
- package/dist/session.cjs +17 -0
- package/package.json +1 -1
package/dist/adapters/claude.cjs
CHANGED
|
@@ -93,7 +93,13 @@ function attachUsage(result) {
|
|
|
93
93
|
if (!parsed)
|
|
94
94
|
return result;
|
|
95
95
|
const usage = (0, exit_conditions_cjs_1.extractUsageFromClaudeJson)(parsed);
|
|
96
|
-
return {
|
|
96
|
+
return {
|
|
97
|
+
...result,
|
|
98
|
+
tokensIn: usage.tokensIn,
|
|
99
|
+
tokensOut: usage.tokensOut,
|
|
100
|
+
cacheHitTokensIn: usage.cacheHitTokensIn,
|
|
101
|
+
costUsd: usage.costUsd,
|
|
102
|
+
};
|
|
97
103
|
}
|
|
98
104
|
async function runOnHost(options, args) {
|
|
99
105
|
return new Promise((resolve) => {
|
package/dist/adapters/codex.cjs
CHANGED
|
@@ -156,6 +156,7 @@ function attachUsage(result, model) {
|
|
|
156
156
|
// measured zero — leave the fields unset so aggregation skips them.
|
|
157
157
|
...(usage.tokensIn !== undefined ? { tokensIn: usage.tokensIn } : {}),
|
|
158
158
|
...(usage.tokensOut !== undefined ? { tokensOut: usage.tokensOut } : {}),
|
|
159
|
+
...(usage.cacheHitTokensIn !== undefined ? { cacheHitTokensIn: usage.cacheHitTokensIn } : {}),
|
|
159
160
|
...(costUsd !== undefined ? { costUsd } : {}),
|
|
160
161
|
...(reportText !== undefined ? { reportText } : {}),
|
|
161
162
|
};
|
|
@@ -123,6 +123,7 @@ function attachOpenCodeOutput(result) {
|
|
|
123
123
|
return result;
|
|
124
124
|
let tokensIn;
|
|
125
125
|
let tokensOut;
|
|
126
|
+
let cacheHitTokensIn;
|
|
126
127
|
let costUsd;
|
|
127
128
|
let finalMessageId;
|
|
128
129
|
const textByMessage = new Map();
|
|
@@ -144,6 +145,9 @@ function attachOpenCodeOutput(result) {
|
|
|
144
145
|
const cost = nonNegativeMetric(part.cost);
|
|
145
146
|
if (input !== undefined || cacheRead !== undefined || cacheWrite !== undefined) {
|
|
146
147
|
tokensIn = (tokensIn ?? 0) + (input ?? 0) + (cacheRead ?? 0) + (cacheWrite ?? 0);
|
|
148
|
+
// Cache reads are the "hit" component of tokensIn; cache writes count
|
|
149
|
+
// as misses (AdapterResult.cacheHitTokensIn semantics).
|
|
150
|
+
cacheHitTokensIn = (cacheHitTokensIn ?? 0) + (cacheRead ?? 0);
|
|
147
151
|
}
|
|
148
152
|
if (output !== undefined)
|
|
149
153
|
tokensOut = (tokensOut ?? 0) + output;
|
|
@@ -157,6 +161,7 @@ function attachOpenCodeOutput(result) {
|
|
|
157
161
|
...result,
|
|
158
162
|
...(tokensIn !== undefined ? { tokensIn } : {}),
|
|
159
163
|
...(tokensOut !== undefined ? { tokensOut } : {}),
|
|
164
|
+
...(cacheHitTokensIn !== undefined ? { cacheHitTokensIn } : {}),
|
|
160
165
|
...(costUsd !== undefined ? { costUsd } : {}),
|
|
161
166
|
...(reportText ? { reportText } : {}),
|
|
162
167
|
};
|
package/dist/exit-conditions.cjs
CHANGED
|
@@ -52,6 +52,8 @@ function parseClaudeJsonResult(stdout) {
|
|
|
52
52
|
* no cache breakdown, so the components are folded together here rather
|
|
53
53
|
* than dropped). Cost prefers `total_cost_usd` (the field name used in
|
|
54
54
|
* multi-turn/agentic CLI output) and falls back to `cost_usd`.
|
|
55
|
+
* `cacheHitTokensIn` is the cache-read component of that sum -- cache writes
|
|
56
|
+
* count as misses, matching sessions.cache_miss_input_tokens semantics.
|
|
55
57
|
*/
|
|
56
58
|
function extractUsageFromClaudeJson(parsed) {
|
|
57
59
|
const usage = parsed.usage ?? {};
|
|
@@ -60,7 +62,7 @@ function extractUsageFromClaudeJson(parsed) {
|
|
|
60
62
|
(usage.cache_read_input_tokens ?? 0);
|
|
61
63
|
const tokensOut = usage.output_tokens ?? 0;
|
|
62
64
|
const costUsd = parsed.total_cost_usd ?? parsed.cost_usd ?? 0;
|
|
63
|
-
return { tokensIn, tokensOut, costUsd };
|
|
65
|
+
return { tokensIn, tokensOut, cacheHitTokensIn: usage.cache_read_input_tokens ?? 0, costUsd };
|
|
64
66
|
}
|
|
65
67
|
/**
|
|
66
68
|
* Best-effort line-by-line parse of `codex exec --json` stdout into the
|
|
@@ -105,15 +107,21 @@ function parseCodexJsonEvents(stdout) {
|
|
|
105
107
|
function extractUsageFromCodexEvents(events) {
|
|
106
108
|
let turnTokensIn = 0;
|
|
107
109
|
let turnTokensOut = 0;
|
|
110
|
+
let turnCacheHit = 0;
|
|
108
111
|
let sawTurnUsage = false;
|
|
109
112
|
let legacyTokensIn;
|
|
110
113
|
let legacyTokensOut;
|
|
114
|
+
let legacyCacheHit;
|
|
111
115
|
let costUsd;
|
|
112
116
|
for (const event of events) {
|
|
113
117
|
if (event.type === "turn.completed" && event.usage) {
|
|
114
118
|
sawTurnUsage = true;
|
|
115
119
|
turnTokensIn += event.usage.input_tokens ?? 0;
|
|
116
120
|
turnTokensOut += event.usage.output_tokens ?? 0;
|
|
121
|
+
// cached_input_tokens is a component of input_tokens in the verified
|
|
122
|
+
// stream (see codex-pricing.cts priceUsage) -- same inclusive
|
|
123
|
+
// semantics as AdapterResult.cacheHitTokensIn.
|
|
124
|
+
turnCacheHit += event.usage.cached_input_tokens ?? 0;
|
|
117
125
|
if (typeof event.usage.total_cost_usd === "number") {
|
|
118
126
|
costUsd = (costUsd ?? 0) + event.usage.total_cost_usd;
|
|
119
127
|
}
|
|
@@ -124,6 +132,9 @@ function extractUsageFromCodexEvents(events) {
|
|
|
124
132
|
? (nested.input_tokens ?? 0)
|
|
125
133
|
: (event.msg.input_tokens ?? 0) + (event.msg.cached_input_tokens ?? 0);
|
|
126
134
|
legacyTokensOut = nested?.output_tokens ?? event.msg.output_tokens ?? 0;
|
|
135
|
+
legacyCacheHit = nested
|
|
136
|
+
? (nested.cached_input_tokens ?? 0)
|
|
137
|
+
: (event.msg.cached_input_tokens ?? 0);
|
|
127
138
|
if (typeof nested?.total_cost_usd === "number")
|
|
128
139
|
costUsd = nested.total_cost_usd;
|
|
129
140
|
}
|
|
@@ -132,6 +143,7 @@ function extractUsageFromCodexEvents(events) {
|
|
|
132
143
|
if (total) {
|
|
133
144
|
legacyTokensIn = total.input_tokens ?? 0;
|
|
134
145
|
legacyTokensOut = total.output_tokens ?? 0;
|
|
146
|
+
legacyCacheHit = total.cached_input_tokens ?? 0;
|
|
135
147
|
if (typeof total.total_cost_usd === "number")
|
|
136
148
|
costUsd = total.total_cost_usd;
|
|
137
149
|
}
|
|
@@ -140,9 +152,24 @@ function extractUsageFromCodexEvents(events) {
|
|
|
140
152
|
costUsd = event.msg.total_cost_usd;
|
|
141
153
|
}
|
|
142
154
|
}
|
|
143
|
-
if (sawTurnUsage)
|
|
144
|
-
return {
|
|
145
|
-
|
|
155
|
+
if (sawTurnUsage) {
|
|
156
|
+
return {
|
|
157
|
+
tokensIn: turnTokensIn,
|
|
158
|
+
tokensOut: turnTokensOut,
|
|
159
|
+
// Clamp like codex-pricing.cts: a malformed event must not report more
|
|
160
|
+
// cache reads than input tokens.
|
|
161
|
+
cacheHitTokensIn: Math.min(turnCacheHit, turnTokensIn),
|
|
162
|
+
costUsd,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
tokensIn: legacyTokensIn,
|
|
167
|
+
tokensOut: legacyTokensOut,
|
|
168
|
+
...(legacyTokensIn !== undefined && legacyCacheHit !== undefined
|
|
169
|
+
? { cacheHitTokensIn: Math.min(legacyCacheHit, legacyTokensIn) }
|
|
170
|
+
: {}),
|
|
171
|
+
costUsd,
|
|
172
|
+
};
|
|
146
173
|
}
|
|
147
174
|
/** The last completed agent message, with legacy `msg.agent_message` fallback. */
|
|
148
175
|
function extractFinalMessageFromCodexEvents(events) {
|
package/dist/prompt.cjs
CHANGED
|
@@ -36,7 +36,8 @@ function renderPrompt(task, bundle) {
|
|
|
36
36
|
if (bundle.depends_on_reports.length > 0) {
|
|
37
37
|
sections.push("## Prior task reports (depends_on)");
|
|
38
38
|
for (const report of bundle.depends_on_reports) {
|
|
39
|
-
|
|
39
|
+
const source = report.github_issue_url ? ` (${report.github_issue_url})` : "";
|
|
40
|
+
sections.push(`- ${report.task_id}${source}: ${report.report_summary ?? report.summary}`);
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
sections.push("## Playbook");
|
package/dist/session.cjs
CHANGED
|
@@ -400,6 +400,7 @@ async function runClaimedSession(deps, claimed, sessionId, lifecycle) {
|
|
|
400
400
|
...turnResult,
|
|
401
401
|
tokensIn: sumReportedUsage(attempts, "tokensIn"),
|
|
402
402
|
tokensOut: sumReportedUsage(attempts, "tokensOut"),
|
|
403
|
+
cacheHitTokensIn: sumReportedUsage(attempts, "cacheHitTokensIn"),
|
|
403
404
|
costUsd: sumReportedUsage(attempts, "costUsd"),
|
|
404
405
|
};
|
|
405
406
|
const mapping = (0, exit_conditions_cjs_1.mapExitCondition)({
|
|
@@ -468,6 +469,7 @@ async function runClaimedSession(deps, claimed, sessionId, lifecycle) {
|
|
|
468
469
|
...(result.tokensIn !== undefined ? { tokens_in: result.tokensIn } : {}),
|
|
469
470
|
...(result.tokensOut !== undefined ? { tokens_out: result.tokensOut } : {}),
|
|
470
471
|
...(result.costUsd !== undefined ? { cost_usd: result.costUsd } : {}),
|
|
472
|
+
...cacheSplitFields(result.tokensIn, result.cacheHitTokensIn),
|
|
471
473
|
},
|
|
472
474
|
transcript_url: transcriptUrl,
|
|
473
475
|
exit_status: mapping.exitStatus,
|
|
@@ -593,6 +595,21 @@ function adapterCommand(config, runtime) {
|
|
|
593
595
|
return { bin: config.opencodeBin, extraArgs: config.opencodeExtraArgs };
|
|
594
596
|
}
|
|
595
597
|
}
|
|
598
|
+
/**
|
|
599
|
+
* The wire-shape prompt-cache split derived from adapter usage, or {} when no
|
|
600
|
+
* attempt reported a cache breakdown. The control plane persists the split
|
|
601
|
+
* only when hit + miss equals tokens_in (dispatch-service.ts
|
|
602
|
+
* byoCacheSplitOrNull), so the miss half is derived from the same summed
|
|
603
|
+
* total rather than reported independently. An attempt that reported tokens
|
|
604
|
+
* without a breakdown (plain-text fallback) inflates the miss half -- those
|
|
605
|
+
* tokens are "uncached or unknown", never fabricated hits.
|
|
606
|
+
*/
|
|
607
|
+
function cacheSplitFields(tokensIn, cacheHitTokensIn) {
|
|
608
|
+
if (tokensIn === undefined || cacheHitTokensIn === undefined)
|
|
609
|
+
return {};
|
|
610
|
+
const hit = Math.min(cacheHitTokensIn, tokensIn);
|
|
611
|
+
return { cache_hit_input_tokens: hit, cache_miss_input_tokens: tokensIn - hit };
|
|
612
|
+
}
|
|
596
613
|
function sumReportedUsage(attempts, key) {
|
|
597
614
|
const reported = attempts.flatMap((attempt) => {
|
|
598
615
|
const value = attempt[key];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sagentlab/navarch-runtime",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.32",
|
|
4
4
|
"description": "Navarch machine-side session manager: claims delivery tasks and runs them through Claude Code, Codex, Gemini, or OpenCode.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"license": "MIT",
|