auto-model-router 0.4.6 → 0.4.7
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.
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
},
|
|
8
8
|
"metadata": {
|
|
9
9
|
"description": "auto-model-router: a local cost/complexity-aware model router for Oh My Pi, backed by OpenRouter",
|
|
10
|
-
"version": "0.4.
|
|
10
|
+
"version": "0.4.7",
|
|
11
11
|
"pluginRoot": "."
|
|
12
12
|
},
|
|
13
13
|
"plugins": [
|
|
14
14
|
{
|
|
15
15
|
"name": "auto-model-router",
|
|
16
16
|
"description": "Local cost/complexity-aware model router for Oh My Pi, backed by OpenRouter. Runs in-process, routes per turn by price and task complexity, with budget caps, mid-stream escalation, and cache-aware hysteresis.",
|
|
17
|
-
"version": "0.4.
|
|
17
|
+
"version": "0.4.7",
|
|
18
18
|
"author": {
|
|
19
19
|
"name": "drewappling",
|
|
20
20
|
"email": "drewappling@gmail.com"
|
|
@@ -273,9 +273,11 @@ def _why_text(e: Dict[str, Any]) -> str:
|
|
|
273
273
|
pt, ct = usage.get("promptTokens", 0) or 0, usage.get("cachedTokens", 0) or 0
|
|
274
274
|
cache = f"{round(100 * ct / pt)}%" if pt else "n/a"
|
|
275
275
|
cost = e.get("reportedUsd")
|
|
276
|
+
if cost is None:
|
|
277
|
+
cost = e.get("predictedUsd") or 0
|
|
276
278
|
lines = [
|
|
277
279
|
f"last turn: {e.get('servedSlug') or e.get('slug')} [{e.get('tier')}] · {e.get('classificationSource')} (confidence {e.get('confidence')})",
|
|
278
|
-
f"cost ${cost
|
|
280
|
+
f"cost ${float(cost):.5f} · cache hit {cache} · latency {e.get('latencyMs')}ms",
|
|
279
281
|
]
|
|
280
282
|
for r in e.get("reasons") or []:
|
|
281
283
|
lines.append(f" - {r}")
|
package/package.json
CHANGED
package/src/server/digest.ts
CHANGED
|
@@ -121,6 +121,14 @@ interface RecentDigest {
|
|
|
121
121
|
atMs: number;
|
|
122
122
|
ledgerId: string;
|
|
123
123
|
rerun: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Whether the call that PRODUCED this digest has been seen. A tool_result
|
|
126
|
+
* digest is made before the next request, and that request's last
|
|
127
|
+
* assistant message carries the producing call; it must not count as a
|
|
128
|
+
* re-run. A compaction digest covers a call already in history, so its
|
|
129
|
+
* origin counts as seen from the start.
|
|
130
|
+
*/
|
|
131
|
+
originSeen: boolean;
|
|
124
132
|
}
|
|
125
133
|
const RERUN_WINDOW_MS = 2 * 3_600_000;
|
|
126
134
|
const RECENT_PER_SESSION = 50;
|
|
@@ -261,7 +269,7 @@ export function createDigester(deps: DigesterDeps): Digester {
|
|
|
261
269
|
if (text === "" || text.length >= inputBytes * 0.9) return { digested: false, reason: "digest did not shrink the output" };
|
|
262
270
|
if (req.ompSessionId !== "") {
|
|
263
271
|
const list = recent.get(req.ompSessionId) ?? [];
|
|
264
|
-
list.push({ tool: req.toolName.toLowerCase(), arg: primaryArg(JSON.stringify(req.input)), atMs: startedAt, ledgerId: entry.id, rerun: false });
|
|
272
|
+
list.push({ tool: req.toolName.toLowerCase(), arg: primaryArg(JSON.stringify(req.input)), atMs: startedAt, ledgerId: entry.id, rerun: false, originSeen: source === "compaction" });
|
|
265
273
|
recent.set(req.ompSessionId, list.slice(-RECENT_PER_SESSION));
|
|
266
274
|
}
|
|
267
275
|
return {
|
|
@@ -284,6 +292,11 @@ export function createDigester(deps: DigesterDeps): Digester {
|
|
|
284
292
|
if (arg === null) continue;
|
|
285
293
|
for (const d of list) {
|
|
286
294
|
if (d.rerun || d.tool !== tool || d.arg !== arg || nowMs - d.atMs > RERUN_WINDOW_MS) continue;
|
|
295
|
+
if (!d.originSeen) {
|
|
296
|
+
// The producing call, arriving in the next request's history.
|
|
297
|
+
d.originSeen = true;
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
287
300
|
d.rerun = true;
|
|
288
301
|
marked++;
|
|
289
302
|
try {
|
package/test/digest.test.ts
CHANGED
|
@@ -198,6 +198,9 @@ describe("createDigester", () => {
|
|
|
198
198
|
expect(dg.noteToolCalls("omp-1", [{ name: "read", argsJson: '{"path":"src/b.ts"}' }, { name: "grep", argsJson: '{"pattern":"src/a.ts"}' }])).toBe(0);
|
|
199
199
|
expect(dg.noteToolCalls("omp-2", [{ name: "read", argsJson: '{"path":"src/a.ts"}' }])).toBe(0);
|
|
200
200
|
expect(row().wasted).toBe(false);
|
|
201
|
+
// The next request carries the call that PRODUCED the digest in its last assistant message: not a re-run.
|
|
202
|
+
expect(dg.noteToolCalls("omp-1", [{ name: "read", argsJson: '{"path":"src/a.ts","offset":1}' }])).toBe(0);
|
|
203
|
+
expect(row().wasted).toBe(false);
|
|
201
204
|
// The same read again (case-insensitive tool name, any other args): the agent wanted the full output.
|
|
202
205
|
expect(dg.noteToolCalls("omp-1", [{ name: "Read", argsJson: '{"path":"src/a.ts","limit":50}' }])).toBe(1);
|
|
203
206
|
expect(row().wasted).toBe(true);
|