vibeostheog 0.19.8 → 0.19.9
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/CHANGELOG.md +3 -0
- package/package.json +1 -1
- package/src/index.js +38 -23
- package/src/lib/hooks/footer.js +27 -23
- package/src/lib/hooks/tool-execute.js +13 -2
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibeostheog",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.9",
|
|
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/index.js
CHANGED
|
@@ -3802,7 +3802,7 @@ var MODEL_USD_PER_TURN = {
|
|
|
3802
3802
|
"haiku": 22e-4,
|
|
3803
3803
|
// ── DeepSeek (OC platform + OpenRouter) ──────────────────
|
|
3804
3804
|
"deepseek/deepseek-v4-pro": 57e-5,
|
|
3805
|
-
"deepseek/deepseek-v4-flash":
|
|
3805
|
+
"deepseek/deepseek-v4-flash": 182e-6,
|
|
3806
3806
|
"deepseek/deepseek-chat": 182e-6,
|
|
3807
3807
|
"deepseek-chat": 182e-6,
|
|
3808
3808
|
"deepseek/deepseek-v3": 182e-6,
|
|
@@ -8624,16 +8624,17 @@ async function _appendFooter(input, output, directory3) {
|
|
|
8624
8624
|
let _footerStress = 0;
|
|
8625
8625
|
if (latestUserIntent)
|
|
8626
8626
|
_footerStress = scoreStress(latestUserIntent);
|
|
8627
|
-
|
|
8628
|
-
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
8627
|
+
try {
|
|
8628
|
+
const cfg = await client.config.get("model");
|
|
8629
|
+
if (cfg) {
|
|
8630
|
+
const cfgModel = String(cfg);
|
|
8631
|
+
if (cfgModel !== currentModel) {
|
|
8632
|
+
setCurrentModel(cfgModel);
|
|
8633
|
+
setCurrentTier(classify(cfgModel));
|
|
8633
8634
|
console.error(`[vibeOS] client-detected model: ${currentModel} (tier=${currentTier})`);
|
|
8634
8635
|
}
|
|
8635
|
-
} catch {
|
|
8636
8636
|
}
|
|
8637
|
+
} catch {
|
|
8637
8638
|
}
|
|
8638
8639
|
try {
|
|
8639
8640
|
const messageID = input?.messageID || input?.messageId || input?.message?.id || output?.messageID || output?.messageId || output?.message?.id || null;
|
|
@@ -8650,12 +8651,23 @@ async function _appendFooter(input, output, directory3) {
|
|
|
8650
8651
|
const sessionSlot = loadSessionSlot(_OC_SID5);
|
|
8651
8652
|
const slot = sessionSlot || loadSelection3().active_slot || "brain";
|
|
8652
8653
|
const brainModel = slot === "brain" ? TRINITY_BRAIN || currentModel : slot === "medium" ? TRINITY_MEDIUM || currentModel : TRINITY_CHEAP || currentModel || "";
|
|
8653
|
-
let
|
|
8654
|
+
let liveModel = "";
|
|
8655
|
+
try {
|
|
8656
|
+
const cfg = await client.config.get("model");
|
|
8657
|
+
if (cfg)
|
|
8658
|
+
liveModel = String(cfg);
|
|
8659
|
+
} catch {
|
|
8660
|
+
}
|
|
8661
|
+
if (!liveModel) {
|
|
8662
|
+
liveModel = readConfig(directory3) || readConfig(join14(process.env.HOME || "", ".config", "opencode")) || process?.env?.OPENCODE_MODEL || "";
|
|
8663
|
+
}
|
|
8664
|
+
const displayModel = liveModel || currentModel || brainModel;
|
|
8665
|
+
let modelTag = `[${shortModelName(displayModel)}]`;
|
|
8654
8666
|
const _workerModel = slot === "brain" ? TRINITY_MEDIUM : null;
|
|
8655
8667
|
const totalTurns = (sesModelTurns?.brain || 0) + (sesModelTurns?.worker || 0);
|
|
8656
8668
|
if (_workerModel && _workerModel !== brainModel) {
|
|
8657
8669
|
const brainPct = Math.round((sesModelTurns?.brain || 0) / (totalTurns || 1) * 100);
|
|
8658
|
-
modelTag = `[${shortModelName(
|
|
8670
|
+
modelTag = `[${shortModelName(displayModel)} ${brainPct}% \u2192 ${shortModelName(_workerModel)} ${100 - brainPct}%]`;
|
|
8659
8671
|
}
|
|
8660
8672
|
_autoReportCount = (_autoReportCount || 0) + 1;
|
|
8661
8673
|
if (_autoReportCount % 5 === 0) {
|
|
@@ -8718,19 +8730,9 @@ async function _appendFooter(input, output, directory3) {
|
|
|
8718
8730
|
if (stripped !== text)
|
|
8719
8731
|
return;
|
|
8720
8732
|
const ltTotal = ltTasks + ltCache;
|
|
8721
|
-
const modeVerbMap = {
|
|
8722
|
-
balanced: "routing",
|
|
8723
|
-
budget: "saving",
|
|
8724
|
-
quality: "focusing",
|
|
8725
|
-
speed: "moving",
|
|
8726
|
-
longrun: "pacing",
|
|
8727
|
-
auto: "vibing",
|
|
8728
|
-
"web-research": "researching",
|
|
8729
|
-
forensic: "investigating"
|
|
8730
|
-
};
|
|
8731
8733
|
const optMode = (resolvedMode || "budget").toLowerCase();
|
|
8732
|
-
const
|
|
8733
|
-
let vibeLine = `\u2014 ${flashIcon ? `${flashIcon} ` : ""}
|
|
8734
|
+
const modeLabel = optMode === "quality" ? "quality" : optMode === "speed" ? "speed" : optMode === "longrun" ? "longrun" : "";
|
|
8735
|
+
let vibeLine = `\u2014 ${flashIcon ? `${flashIcon} ` : ""}run: ${shortModelName(displayModel)}`;
|
|
8734
8736
|
if (ltTotal > 0) {
|
|
8735
8737
|
vibeLine += ` | $${formatUsd(ltTotal)} saved`;
|
|
8736
8738
|
}
|
|
@@ -8742,6 +8744,8 @@ async function _appendFooter(input, output, directory3) {
|
|
|
8742
8744
|
} else if (problemStreak > 0) {
|
|
8743
8745
|
vibeLine += ` | recovery ${problemStreak}`;
|
|
8744
8746
|
}
|
|
8747
|
+
if (modeLabel)
|
|
8748
|
+
vibeLine += ` | ${modeLabel}`;
|
|
8745
8749
|
vibeLine += ` | VIBE${flashIcon ? " \u26A1" : ""}`;
|
|
8746
8750
|
if (_footerStress > 0.4) {
|
|
8747
8751
|
const stressLabel = _footerStress > 0.7 ? "high" : "elevated";
|
|
@@ -10652,8 +10656,19 @@ var onToolExecuteAfter = async (input, output) => {
|
|
|
10652
10656
|
stressTag = ` stress:${label}`;
|
|
10653
10657
|
}
|
|
10654
10658
|
}
|
|
10659
|
+
let liveModel = "";
|
|
10660
|
+
try {
|
|
10661
|
+
const cfg = await client.config.get("model");
|
|
10662
|
+
if (cfg)
|
|
10663
|
+
liveModel = String(cfg);
|
|
10664
|
+
} catch {
|
|
10665
|
+
}
|
|
10666
|
+
if (!liveModel) {
|
|
10667
|
+
liveModel = readConfig(projectDirectory) || readConfig(join16(process.env.HOME || "", ".config", "opencode")) || process?.env?.OPENCODE_MODEL || "";
|
|
10668
|
+
}
|
|
10669
|
+
const displayModel = liveModel || currentModel;
|
|
10655
10670
|
if (ltTotal > 0) {
|
|
10656
|
-
_footerText = `\u2014 ${flashIcon ? `${flashIcon} ` : ""}
|
|
10671
|
+
_footerText = `\u2014 ${flashIcon ? `${flashIcon} ` : ""}run: ${shortModelName(displayModel)} | $${formatUsd(ltTotal)} saved | VIBE${flashIcon ? " \u26A1" : ""} \u2014
|
|
10657
10672
|
|
|
10658
10673
|
`;
|
|
10659
10674
|
} else {
|
package/src/lib/hooks/footer.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
import { readFileSync, appendFileSync, mkdirSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import { classify, _refreshModel, TRINITY_BRAIN, TRINITY_MEDIUM, TRINITY_CHEAP, shortModelName, roundUsd, formatUsd } from "../pricing.js";
|
|
4
|
+
import { classify, _refreshModel, readConfig, TRINITY_BRAIN, TRINITY_MEDIUM, TRINITY_CHEAP, shortModelName, roundUsd, formatUsd } from "../pricing.js";
|
|
5
5
|
import { latestUserIntent } from "./chat-transform.js";
|
|
6
6
|
import { scoreStress, resolveEnforcementMode, detectOutcomeSignal, getBlackboxTracker, syncOutcomeToApi, loadOptimizationMode, classifyTurnSimple } from "../turn-classify.js";
|
|
7
7
|
import { peekBudgetFirstMode, recordBudgetFirstOutcome } from "../mode-policy.js";
|
|
@@ -139,18 +139,19 @@ async function _appendFooter(input, output, directory) {
|
|
|
139
139
|
let _footerStress = 0;
|
|
140
140
|
if (latestUserIntent)
|
|
141
141
|
_footerStress = scoreStress(latestUserIntent);
|
|
142
|
-
//
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
142
|
+
// Always prefer the live OpenCode model setting when available.
|
|
143
|
+
try {
|
|
144
|
+
const cfg = await client.config.get("model");
|
|
145
|
+
if (cfg) {
|
|
146
|
+
const cfgModel = String(cfg);
|
|
147
|
+
if (cfgModel !== currentModel) {
|
|
148
|
+
setCurrentModel(cfgModel);
|
|
149
|
+
setCurrentTier(classify(cfgModel));
|
|
149
150
|
console.error(`[vibeOS] client-detected model: ${currentModel} (tier=${currentTier})`);
|
|
150
151
|
}
|
|
151
152
|
}
|
|
152
|
-
catch { /* client.config may not be available */ }
|
|
153
153
|
}
|
|
154
|
+
catch { /* client.config may not be available */ }
|
|
154
155
|
try {
|
|
155
156
|
const messageID = input?.messageID ||
|
|
156
157
|
input?.messageId ||
|
|
@@ -175,12 +176,23 @@ async function _appendFooter(input, output, directory) {
|
|
|
175
176
|
const sessionSlot = loadSessionSlot(_OC_SID);
|
|
176
177
|
const slot = sessionSlot || loadSelection().active_slot || "brain";
|
|
177
178
|
const brainModel = slot === "brain" ? (TRINITY_BRAIN || currentModel) : slot === "medium" ? (TRINITY_MEDIUM || currentModel) : (TRINITY_CHEAP || currentModel || "");
|
|
178
|
-
let
|
|
179
|
+
let liveModel = "";
|
|
180
|
+
try {
|
|
181
|
+
const cfg = await client.config.get("model");
|
|
182
|
+
if (cfg)
|
|
183
|
+
liveModel = String(cfg);
|
|
184
|
+
}
|
|
185
|
+
catch { }
|
|
186
|
+
if (!liveModel) {
|
|
187
|
+
liveModel = readConfig(directory) || readConfig(join(process.env.HOME || "", ".config", "opencode")) || process?.env?.OPENCODE_MODEL || "";
|
|
188
|
+
}
|
|
189
|
+
const displayModel = liveModel || currentModel || brainModel;
|
|
190
|
+
let modelTag = `[${shortModelName(displayModel)}]`;
|
|
179
191
|
const _workerModel = slot === "brain" ? TRINITY_MEDIUM : null;
|
|
180
192
|
const totalTurns = (sesModelTurns?.brain || 0) + (sesModelTurns?.worker || 0);
|
|
181
193
|
if (_workerModel && _workerModel !== brainModel) {
|
|
182
194
|
const brainPct = Math.round(((sesModelTurns?.brain || 0) / (totalTurns || 1)) * 100);
|
|
183
|
-
modelTag = `[${shortModelName(
|
|
195
|
+
modelTag = `[${shortModelName(displayModel)} ${brainPct}% → ${shortModelName(_workerModel)} ${100 - brainPct}%]`;
|
|
184
196
|
}
|
|
185
197
|
_autoReportCount = (_autoReportCount || 0) + 1;
|
|
186
198
|
if (_autoReportCount % 5 === 0) {
|
|
@@ -248,19 +260,9 @@ async function _appendFooter(input, output, directory) {
|
|
|
248
260
|
return;
|
|
249
261
|
const ltTotal = ltTasks + ltCache;
|
|
250
262
|
// Build dopamine footer
|
|
251
|
-
const modeVerbMap = {
|
|
252
|
-
balanced: 'routing',
|
|
253
|
-
budget: 'saving',
|
|
254
|
-
quality: 'focusing',
|
|
255
|
-
speed: 'moving',
|
|
256
|
-
longrun: 'pacing',
|
|
257
|
-
auto: 'vibing',
|
|
258
|
-
'web-research': 'researching',
|
|
259
|
-
forensic: 'investigating',
|
|
260
|
-
};
|
|
261
263
|
const optMode = (resolvedMode || 'budget').toLowerCase();
|
|
262
|
-
const
|
|
263
|
-
let vibeLine = `— ${flashIcon ? `${flashIcon} ` : ""}
|
|
264
|
+
const modeLabel = optMode === "quality" ? "quality" : optMode === "speed" ? "speed" : optMode === "longrun" ? "longrun" : "";
|
|
265
|
+
let vibeLine = `— ${flashIcon ? `${flashIcon} ` : ""}run: ${shortModelName(displayModel)}`;
|
|
264
266
|
if (ltTotal > 0) {
|
|
265
267
|
vibeLine += ` | $${formatUsd(ltTotal)} saved`;
|
|
266
268
|
}
|
|
@@ -273,6 +275,8 @@ async function _appendFooter(input, output, directory) {
|
|
|
273
275
|
else if (problemStreak > 0) {
|
|
274
276
|
vibeLine += ` | recovery ${problemStreak}`;
|
|
275
277
|
}
|
|
278
|
+
if (modeLabel)
|
|
279
|
+
vibeLine += ` | ${modeLabel}`;
|
|
276
280
|
vibeLine += ` | VIBE${flashIcon ? ' ⚡' : ''}`;
|
|
277
281
|
if (_footerStress > 0.4) {
|
|
278
282
|
const stressLabel = _footerStress > 0.7 ? 'high' : 'elevated';
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { writeFileSync, appendFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
3
3
|
import { join, dirname, basename } from 'node:path';
|
|
4
4
|
import { currentTier, currentModel, setCurrentModel, setCurrentTier, _OC_SID, _modelLocked, loadSelection, readLifetimeSavings, recordCacheSaving, recordMissedContext7, getScratchpadHit, recordScratchpadObservation, recordPrivacyTelemetry, updateState, SAVINGS_LEDGER_FILE, CONTEXT7_INSTALL_FLAG, SOFT_QUOTA_LIMIT, upsertTodo, ML_ENABLED, _mlGraph, _cacheDb, _mlSavePending, ML_CONFIDENCE_THRESHOLD, setMlSavePending, saveMLState, SCRATCHPAD_TOOLS, applyDecadence, } from '../state.js';
|
|
5
|
-
import { classify, modelCostPerTurn, isModelFree, detectContext7, isDocsTarget, shortModelName, formatUsd, _refreshModel, TRINITY_CHEAP, TRINITY_MEDIUM, trendDisplay, modelToSlotLabel, } from '../pricing.js';
|
|
5
|
+
import { classify, modelCostPerTurn, isModelFree, detectContext7, isDocsTarget, shortModelName, formatUsd, _refreshModel, readConfig, TRINITY_CHEAP, TRINITY_MEDIUM, trendDisplay, modelToSlotLabel, } from '../pricing.js';
|
|
6
6
|
import { latestUserIntent } from './chat-transform.js';
|
|
7
7
|
import { scoreStress, extractFirstWordFromArgs, shouldLogWarn, isUserAskingForTests, resolveEnforcementMode, getLearnedExploratoryWords, noteTaskRoutingLearning, } from '../turn-classify.js';
|
|
8
8
|
import { saveReport } from '../reporting.js';
|
|
@@ -604,8 +604,19 @@ export const onToolExecuteAfter = async (input, output) => {
|
|
|
604
604
|
stressTag = ` stress:${label}`;
|
|
605
605
|
}
|
|
606
606
|
}
|
|
607
|
+
let liveModel = "";
|
|
608
|
+
try {
|
|
609
|
+
const cfg = await client.config.get("model");
|
|
610
|
+
if (cfg)
|
|
611
|
+
liveModel = String(cfg);
|
|
612
|
+
}
|
|
613
|
+
catch { }
|
|
614
|
+
if (!liveModel) {
|
|
615
|
+
liveModel = readConfig(projectDirectory) || readConfig(join(process.env.HOME || "", ".config", "opencode")) || process?.env?.OPENCODE_MODEL || "";
|
|
616
|
+
}
|
|
617
|
+
const displayModel = liveModel || currentModel;
|
|
607
618
|
if (ltTotal > 0) {
|
|
608
|
-
_footerText = `— ${flashIcon ? `${flashIcon} ` : ""}
|
|
619
|
+
_footerText = `— ${flashIcon ? `${flashIcon} ` : ""}run: ${shortModelName(displayModel)} | $${formatUsd(ltTotal)} saved | VIBE${flashIcon ? " ⚡" : ""} —\n\n`;
|
|
609
620
|
}
|
|
610
621
|
else {
|
|
611
622
|
_footerText = `${statusLine}${stressTag}\n\n`;
|