vibeostheog 0.22.23 → 0.22.24
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 +1 -1
- package/src/lib/pricing.js +18 -4
- package/src/lib/runtime-state.js +1 -1
- package/src/lib/state.js +4 -2
- package/src/lib/trinity-rebuild.js +14 -5
- package/src/lib/trinity-tool.js +16 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibeostheog",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.24",
|
|
4
4
|
"description": "Cost-aware delegation enforcer for OpenCode. Tracks model usage, routes Task subagents to cheaper tiers, surfaces cumulative savings in chat. Includes research audit, reporting framework, project memory, progressive scratchpad decadence, and trinity CLI for brain/medium/cheap slot switching.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"release": "node scripts/release.mjs",
|
package/src/lib/pricing.js
CHANGED
|
@@ -111,6 +111,12 @@ export function classify(m) {
|
|
|
111
111
|
return "high";
|
|
112
112
|
if (MID_TIER_RE.test(s))
|
|
113
113
|
return "mid";
|
|
114
|
+
// Fallback: strip provider prefix and test bare name
|
|
115
|
+
const bare = s.includes("/") ? s.split("/").slice(1).join("/") : s;
|
|
116
|
+
if (HIGH_TIER_RE.test(bare))
|
|
117
|
+
return "high";
|
|
118
|
+
if (MID_TIER_RE.test(bare))
|
|
119
|
+
return "mid";
|
|
114
120
|
return "budget";
|
|
115
121
|
}
|
|
116
122
|
// Map a model ID to a human-readable label with tier icon.
|
|
@@ -160,9 +166,9 @@ export function resolveExecutionIdentity(modelId, directory = "") {
|
|
|
160
166
|
const normalized = normalizeModelId(resolved || raw);
|
|
161
167
|
const quality = isModelFree(resolved || raw)
|
|
162
168
|
? "free"
|
|
163
|
-
:
|
|
169
|
+
: classify(resolved || raw) === "high"
|
|
164
170
|
? "brain"
|
|
165
|
-
:
|
|
171
|
+
: classify(resolved || raw) === "mid"
|
|
166
172
|
? "medium"
|
|
167
173
|
: "cheap";
|
|
168
174
|
return {
|
|
@@ -260,6 +266,8 @@ export function trendDisplay(sesTrend) {
|
|
|
260
266
|
const CACHE_SAVED_PER_1M_INPUT_TOKENS = 0.10;
|
|
261
267
|
// Approximate bytes per token for JSON/text content (varies 3-6, use 4 as safe estimate).
|
|
262
268
|
const BYTES_PER_TOKEN = 4;
|
|
269
|
+
// Average tokens per turn for cost estimation heuristic.
|
|
270
|
+
const AVG_TOKENS_PER_TURN = 375;
|
|
263
271
|
export function parseOpenRouterInputPer1M(modelRow) {
|
|
264
272
|
const p = modelRow?.pricing || {};
|
|
265
273
|
const inTok = Number(p.prompt ?? p.input ?? p.request);
|
|
@@ -300,7 +308,7 @@ export function cacheSavePer1MInputTokens(model) {
|
|
|
300
308
|
}
|
|
301
309
|
const turnCost = modelCostPerTurn(model);
|
|
302
310
|
if (Number.isFinite(turnCost) && turnCost > 0) {
|
|
303
|
-
return Math.round(turnCost *
|
|
311
|
+
return Math.round(turnCost * AVG_TOKENS_PER_TURN * 100) / 100;
|
|
304
312
|
}
|
|
305
313
|
return CACHE_SAVED_PER_1M_INPUT_TOKENS;
|
|
306
314
|
}
|
|
@@ -929,7 +937,13 @@ function resolveConfiguredModelId(model, configs = []) {
|
|
|
929
937
|
matches.add(id);
|
|
930
938
|
}
|
|
931
939
|
}
|
|
932
|
-
|
|
940
|
+
if (matches.size === 0)
|
|
941
|
+
return raw;
|
|
942
|
+
if (matches.size === 1)
|
|
943
|
+
return [...matches][0];
|
|
944
|
+
// Multiple providers have this model — prefer provider-qualified name over bare
|
|
945
|
+
const qualified = [...matches].find(m => m.includes("/"));
|
|
946
|
+
return qualified || raw;
|
|
933
947
|
}
|
|
934
948
|
export function resolveDisplayModelId(model, directory = "") {
|
|
935
949
|
const raw = String(model || "").trim();
|
package/src/lib/runtime-state.js
CHANGED
package/src/lib/state.js
CHANGED
|
@@ -47,6 +47,8 @@ const MAX_SCRATCHPAD_FILES = 1000;
|
|
|
47
47
|
const MAX_SCRATCHPAD_BYTES = 10 * 1024 * 1024;
|
|
48
48
|
const MAX_SESSION_SCRATCHPAD_FILES = 200;
|
|
49
49
|
const MAX_SESSION_SCRATCHPAD_BYTES = 2 * 1024 * 1024;
|
|
50
|
+
const MAX_PTR_CANDIDATES = 50;
|
|
51
|
+
const SUMMARY_HEAD_TRUNCATE = 500;
|
|
50
52
|
function getVibeOSHome() {
|
|
51
53
|
return VIBEOS_CONTEXT.getStore()?.home || process.env.VIBEOS_HOME || join(process.env.HOME || "", ".claude");
|
|
52
54
|
}
|
|
@@ -839,7 +841,7 @@ function scanRecentScratchpad(dir, titleCase, maxScan = 2000) {
|
|
|
839
841
|
const ptrFiles = entries.filter(e => e.endsWith(".ptr"));
|
|
840
842
|
const ptrCandidates = [];
|
|
841
843
|
for (const pf of ptrFiles) {
|
|
842
|
-
if (ptrCandidates.length >=
|
|
844
|
+
if (ptrCandidates.length >= MAX_PTR_CANDIDATES)
|
|
843
845
|
break;
|
|
844
846
|
try {
|
|
845
847
|
const st = statSync(join(dir, pf));
|
|
@@ -1011,7 +1013,7 @@ function _pruneScratchpadDir(targetDir, opts = {}) {
|
|
|
1011
1013
|
if (!existsSync(summaryPath))
|
|
1012
1014
|
try {
|
|
1013
1015
|
const content = readFileSync(fullPath, "utf-8");
|
|
1014
|
-
writeFileSync(summaryPath, content.slice(0,
|
|
1016
|
+
writeFileSync(summaryPath, content.slice(0, SUMMARY_HEAD_TRUNCATE).replace(/\n+/g, " ").trim() + (content.length > SUMMARY_HEAD_TRUNCATE ? "…" : ""));
|
|
1015
1017
|
}
|
|
1016
1018
|
catch { }
|
|
1017
1019
|
const head = _readHead(fullPath);
|
|
@@ -210,11 +210,20 @@ function _modelCost(id) {
|
|
|
210
210
|
function _modelTier(id) {
|
|
211
211
|
if (!id)
|
|
212
212
|
return "budget";
|
|
213
|
+
// Test both the full provider-qualified ID and the bare name
|
|
213
214
|
const high = HIGH_TIER_RE?.test?.(id);
|
|
214
215
|
if (high)
|
|
215
216
|
return "high";
|
|
216
217
|
const mid = MID_TIER_RE?.test?.(id);
|
|
217
|
-
|
|
218
|
+
if (mid)
|
|
219
|
+
return "mid";
|
|
220
|
+
// Fallback: strip provider prefix and test bare name
|
|
221
|
+
const bare = String(id).includes("/") ? String(id).split("/").slice(1).join("/") : String(id);
|
|
222
|
+
if (HIGH_TIER_RE?.test?.(bare))
|
|
223
|
+
return "high";
|
|
224
|
+
if (MID_TIER_RE?.test?.(bare))
|
|
225
|
+
return "mid";
|
|
226
|
+
return "budget";
|
|
218
227
|
}
|
|
219
228
|
export async function discoverAvailableModels(providers, auth) {
|
|
220
229
|
const all = collectConfiguredProviderModels(providers);
|
|
@@ -319,12 +328,12 @@ export function classifyAndRankModels(models) {
|
|
|
319
328
|
}
|
|
320
329
|
if (unique.length === 0)
|
|
321
330
|
return null;
|
|
322
|
-
const
|
|
331
|
+
const normalizeModelIdLocal = (id) => String(id || "").toLowerCase()
|
|
323
332
|
.replace(/\./g, "-")
|
|
324
333
|
.replace(/^(openrouter|opencode|deepseek|anthropic|google)\//, "");
|
|
325
|
-
const isDeprecatedDeepseekChat = (id) =>
|
|
334
|
+
const isDeprecatedDeepseekChat = (id) => normalizeModelIdLocal(id).includes("deepseek-chat");
|
|
326
335
|
const hasReplacementDeepseek = unique.some((m) => {
|
|
327
|
-
const raw =
|
|
336
|
+
const raw = normalizeModelIdLocal(m.id);
|
|
328
337
|
return raw.startsWith("deepseek-") && !raw.includes("deepseek-chat");
|
|
329
338
|
});
|
|
330
339
|
const ranked = hasReplacementDeepseek
|
|
@@ -333,7 +342,7 @@ export function classifyAndRankModels(models) {
|
|
|
333
342
|
if (ranked.length === 0)
|
|
334
343
|
return null;
|
|
335
344
|
const modelPreference = (id) => {
|
|
336
|
-
const raw =
|
|
345
|
+
const raw = normalizeModelIdLocal(id);
|
|
337
346
|
if (raw.includes("deepseek-v4-flash"))
|
|
338
347
|
return 2;
|
|
339
348
|
if (raw.includes("deepseek-chat"))
|
package/src/lib/trinity-tool.js
CHANGED
|
@@ -3,6 +3,16 @@ import { join } from "node:path";
|
|
|
3
3
|
import { LABEL_MODES, buildDeterministicTrinity, resolveExecutionIdentity } from "./pricing.js";
|
|
4
4
|
import { BRANDED_MODES, RUNTIME_MODES } from "./mode-router.js";
|
|
5
5
|
import { invalidateApiToken } from "./api-client.js";
|
|
6
|
+
// ── Named constants (magic number extraction) ────────────────────────
|
|
7
|
+
const MIN_TOOL_BREAKDOWN_THRESHOLD = 0.005;
|
|
8
|
+
const STRESS_GAUGE_CRITICAL = 0.85;
|
|
9
|
+
const STRESS_GAUGE_HIGH = 0.7;
|
|
10
|
+
const STRESS_GAUGE_ELEVATED = 0.5;
|
|
11
|
+
const STRESS_GAUGE_CALM = 0.3;
|
|
12
|
+
const STRESS_GAUGE_MIN = 0.1;
|
|
13
|
+
const MOMENTUM_SIGNIFICANT_THRESHOLD = 0.3;
|
|
14
|
+
const DIAGNOSE_BUDGET_LINES = 50;
|
|
15
|
+
const CREDIT_MIN_OK = 40;
|
|
6
16
|
export function createTrinityTool(deps) {
|
|
7
17
|
return {
|
|
8
18
|
description: "Control the vibeOS plugin and active model slot. " +
|
|
@@ -57,7 +67,7 @@ export function createTrinityTool(deps) {
|
|
|
57
67
|
const sesRate = sv.sesRatePerHour || 0;
|
|
58
68
|
const missedC7 = sv.missedC7 || 0;
|
|
59
69
|
const toolBreakdown = sv.sesToolBreakdown || {};
|
|
60
|
-
const topTools = Object.entries(toolBreakdown).filter(([, v]) => v >
|
|
70
|
+
const topTools = Object.entries(toolBreakdown).filter(([, v]) => v > MIN_TOOL_BREAKDOWN_THRESHOLD).sort((a, b) => b[1] - a[1]).slice(0, 5);
|
|
61
71
|
const brainModel = tiers?.brain?.oc || "(unset)";
|
|
62
72
|
const mediumModel = tiers?.medium?.oc || "(unset)";
|
|
63
73
|
cheapModel = tiers?.cheap?.oc || cheapModel;
|
|
@@ -66,8 +76,8 @@ export function createTrinityTool(deps) {
|
|
|
66
76
|
const lockedModel = deps._lockedModel || null;
|
|
67
77
|
const onboardingMode = sel.onboarding_mode || "strict";
|
|
68
78
|
const stressScore = deps.latestUserIntent ? deps.scoreStress(deps.latestUserIntent) : 0;
|
|
69
|
-
const stressBar = stressScore >
|
|
70
|
-
const stressLabel = stressScore >
|
|
79
|
+
const stressBar = stressScore > STRESS_GAUGE_CRITICAL ? "█" : stressScore > STRESS_GAUGE_HIGH ? "▆" : stressScore > STRESS_GAUGE_ELEVATED ? "▅" : stressScore > STRESS_GAUGE_CALM ? "▃" : stressScore > STRESS_GAUGE_MIN ? "▂" : "▁";
|
|
80
|
+
const stressLabel = stressScore > STRESS_GAUGE_HIGH ? "high" : stressScore > 0.4 ? "elevated" : stressScore > STRESS_GAUGE_MIN ? "calm" : "none";
|
|
71
81
|
const totalTurns = (sv.sesModelTurns?.brain || 0) + (sv.sesModelTurns?.worker || 0);
|
|
72
82
|
const brainPct = totalTurns > 0 ? Math.round((sv.sesModelTurns.brain / totalTurns) * 100) : 0;
|
|
73
83
|
const workerPct = 100 - brainPct;
|
|
@@ -80,7 +90,7 @@ export function createTrinityTool(deps) {
|
|
|
80
90
|
try {
|
|
81
91
|
const res = deps._latestBlackboxState || deps.getBlackboxResolution();
|
|
82
92
|
if (res && res.n_interactions > 3) {
|
|
83
|
-
const momentumIcon = res.momentum >
|
|
93
|
+
const momentumIcon = res.momentum > MOMENTUM_SIGNIFICANT_THRESHOLD ? "up up" : res.momentum > 0 ? "up" : res.momentum < -MOMENTUM_SIGNIFICANT_THRESHOLD ? "down down" : res.momentum < 0 ? "down" : "flat";
|
|
84
94
|
const loopTag = res.is_looping ? " (loop)" : "";
|
|
85
95
|
decisionLine = `${res.resolution} ${res.sub_regime} ${momentumIcon}${loopTag}`;
|
|
86
96
|
}
|
|
@@ -863,7 +873,7 @@ export function createTrinityTool(deps) {
|
|
|
863
873
|
results.push({ ok: false, okLabel: "\u274c", label: "model probe", detail: "no current model detected" });
|
|
864
874
|
}
|
|
865
875
|
const credit = deps.loadCredit();
|
|
866
|
-
let budget =
|
|
876
|
+
let budget = DIAGNOSE_BUDGET_LINES;
|
|
867
877
|
let totalBal = 0;
|
|
868
878
|
try {
|
|
869
879
|
const j = deps.safeJsonParse(deps.readFileSync(deps.TIERS_FILE, "utf-8"));
|
|
@@ -886,7 +896,7 @@ export function createTrinityTool(deps) {
|
|
|
886
896
|
: runway.turnsRemaining != null && runway.costPerTurn != null
|
|
887
897
|
? `${Number(runway.turnsRemaining).toLocaleString()} turns on ${cheapModel} @ $${deps.formatUsd(runway.costPerTurn)}/turn`
|
|
888
898
|
: "n/a";
|
|
889
|
-
const creditOk = credit >=
|
|
899
|
+
const creditOk = credit >= CREDIT_MIN_OK;
|
|
890
900
|
results.push({
|
|
891
901
|
ok: creditOk, okLabel: creditOk ? "\u2705" : "\u274c",
|
|
892
902
|
label: "credits",
|