troxy-cli 1.29.57 → 1.29.59
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "troxy-cli",
|
|
3
|
-
"version": "1.29.
|
|
3
|
+
"version": "1.29.59",
|
|
4
4
|
"description": "A secure control layer for AI agents: policies across payments, messages, logins, destructive actions, model usage, and secrets, all enforceable from the CLI",
|
|
5
5
|
"homepage": "https://troxy.io",
|
|
6
6
|
"bugs": {
|
|
@@ -252,6 +252,15 @@ function addTurn(totals, start, end, ratio) {
|
|
|
252
252
|
return { ...t, paid: t.paid + paid, full: t.full + paid * ratio, meter }; // keeps t.kept
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
+
// kept_usd from the server is the whole session's total, but paid only counts turns since
|
|
256
|
+
// the mod began tracking. Count only what arrived after the first reading (the first turn's
|
|
257
|
+
// own clearing is missed, so this undercounts slightly rather than inflating the multiplier).
|
|
258
|
+
function withKept(t, keptUsd) {
|
|
259
|
+
if (!(keptUsd >= 0)) return {};
|
|
260
|
+
const keptBase = t.keptBase === undefined ? keptUsd : t.keptBase;
|
|
261
|
+
return { keptBase, kept: Math.max(0, keptUsd - keptBase) };
|
|
262
|
+
}
|
|
263
|
+
|
|
255
264
|
// Idle compaction: shrink a big session just before its prompt cache expires (1h), so
|
|
256
265
|
// the summary reads the conversation from cache (~0.1x) and the user comes back to a
|
|
257
266
|
// small session instead of re-sending the whole thing. Never while the plan meter is
|
|
@@ -541,9 +550,7 @@ export function register(on) {
|
|
|
541
550
|
try {
|
|
542
551
|
const { value } = await $.state.get(SAVED);
|
|
543
552
|
const totals = addTurn(value, start, await snapshot($), ratio);
|
|
544
|
-
|
|
545
|
-
// since the mod started tracking; close enough once the session has a few turns.
|
|
546
|
-
if (savings && savings.kept_usd >= 0) totals.kept = savings.kept_usd;
|
|
553
|
+
if (savings) Object.assign(totals, withKept(totals, savings.kept_usd));
|
|
547
554
|
await $.state.set(SAVED, totals);
|
|
548
555
|
const line = sessionLine(totals);
|
|
549
556
|
if (line) await $.state.set(LINE, line);
|
|
@@ -557,4 +564,4 @@ export function register(on) {
|
|
|
557
564
|
}
|
|
558
565
|
|
|
559
566
|
// Exported for tests only - not part of the mod's runtime contract.
|
|
560
|
-
export const _internal = { askedFor, rememberAsked, asked, armCompact, cancelCompact, toDomainAndFields, guardBash, failClosed, parseScore, asRequest, pickModel, troxyCommand, modRouteFile, estimateTokens, MODELS, savedLine, sessionLine, addTurn, statusText, compactPlan, savingsText, fetchSavings, scorePrompt, routeStep, stepModel, HOLD_PROMPTS };
|
|
567
|
+
export const _internal = { askedFor, rememberAsked, asked, armCompact, cancelCompact, toDomainAndFields, guardBash, failClosed, parseScore, asRequest, pickModel, troxyCommand, modRouteFile, estimateTokens, MODELS, savedLine, sessionLine, addTurn, withKept, statusText, compactPlan, savingsText, fetchSavings, scorePrompt, routeStep, stepModel, HOLD_PROMPTS };
|
|
@@ -92,6 +92,14 @@ test('addTurn: a session total from its own turns, a routed one counted at the a
|
|
|
92
92
|
t = addTurn({ ...t, kept: 1.5 }, { cost: 2, meter: {} }, { cost: 2, meter: {} }, 1);
|
|
93
93
|
assert.equal(t.kept, 1.5);
|
|
94
94
|
assert.match(sessionLine(t), /your bar lasts 3\.0x longer · 5h: 3 instead of 9/);
|
|
95
|
+
// Server total of a session already 28 dollars deep: only growth after the first reading counts.
|
|
96
|
+
const { withKept } = _internal;
|
|
97
|
+
let k = { paid: 1, full: 1, meter: {} };
|
|
98
|
+
Object.assign(k, withKept(k, 28));
|
|
99
|
+
assert.deepEqual([k.keptBase, k.kept], [28, 0]);
|
|
100
|
+
Object.assign(k, withKept(k, 29.5));
|
|
101
|
+
assert.deepEqual([k.keptBase, k.kept], [28, 1.5]);
|
|
102
|
+
assert.deepEqual(withKept(k, undefined), {});
|
|
95
103
|
// No routed turn yet: no band.
|
|
96
104
|
assert.equal(sessionLine(addTurn(undefined, { cost: 0, meter: {} }, { cost: 1, meter: {} }, 1)), undefined);
|
|
97
105
|
});
|
package/src/tls-ca.js
CHANGED
|
@@ -187,11 +187,11 @@ export function ensureInterceptionCerts(dir, { hostname, leafDnsNames, leafRenew
|
|
|
187
187
|
: null;
|
|
188
188
|
const leafStillHealthy = existingLeaf?.certPem
|
|
189
189
|
&& certIsValid(existingLeaf.certPem)
|
|
190
|
-
&& !certExpiresWithin(existingLeaf.certPem, leafRenewWithinDays)
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
190
|
+
&& !certExpiresWithin(existingLeaf.certPem, leafRenewWithinDays);
|
|
191
|
+
// Skipped: forge.pki.certificateFromPem(caCertPem).verify(existingLeaf.certPem)
|
|
192
|
+
// node-forge RSA signature verification is vulnerable (GHSA-86w9-cpqp-85rv, unfixed).
|
|
193
|
+
// For this local cert: CA and leaf are both generated by Troxy, stored in secret files.
|
|
194
|
+
// If the CA changes, TLS will fail on next use and the user restarts. Low risk.
|
|
195
195
|
if (leafStillHealthy) {
|
|
196
196
|
({ certPem: leafCertPem, keyPem: leafKeyPem } = existingLeaf);
|
|
197
197
|
} else {
|