vibeostheog 0.23.7 → 0.23.11
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 +3 -3
- package/src/index.js +4 -4
- package/src/lib/hooks/chat-transform.js +39 -5
- package/src/lib/hooks/footer.js +7 -3
- package/src/lib/hooks/tool-execute.js +48 -5
- package/src/lib/mode-router.js +10 -3
- package/src/lib/selection-manager.js +14 -0
- package/src/lib/state.js +87 -7
- package/src/lib/trinity-tool.js +57 -14
- package/src/lib/turn-classify.js +11 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibeostheog",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.11",
|
|
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",
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"checkpoint:validate": "node scripts/checkpoint-validate.mjs",
|
|
15
15
|
"test:scripts": "node --test scripts/tests/checkpoint-validate.test.mjs tests/release-pack.test.mjs",
|
|
16
16
|
"ts:audit": "node scripts/ts-audit.mjs",
|
|
17
|
-
"test": "VIBEOS_MCP_PORT=0 node --test --test-timeout=240000 tests/deep_integration.test.mjs tests/production_regressions.test.mjs tests/release_hardening_tigerteam.test.mjs tests/test_api_migration.neutral.test.mjs tests/test_const_assignment_regression.test.mjs tests/test_delegation_enforcer.test.mjs tests/test_diagnose_cmd.test.mjs tests/test_install_and_recovery.test.mjs tests/test_internals_stress_patterns_offtopic.test.mjs tests/test_saveos_e2e_cleanup.test.mjs tests/test_tdd_enforcer.test.mjs tests/test_10fixes_regression.test.mjs tests/test_cross_session_regression.test.mjs tests/test_mega_all_fixes.test.mjs tests/test_smart_cache_regression.test.mjs src/tests/*.test.js src/utils/tests/*.test.mjs \"src/vibeOS-lib/tests/auto-select-mode.test.mjs\" \"src/vibeOS-lib/tests/blackbox-regression.test.mjs\" \"src/vibeOS-lib/tests/blackbox-smoke.test.mjs\" \"src/vibeOS-lib/tests/budget-first-mode.test.mjs\" \"src/vibeOS-lib/tests/flow-enforcer.test.mjs\" \"src/vibeOS-lib/tests/flow-secrets.test.mjs\" \"src/vibeOS-lib/tests/session-metrics.test.mjs\" \"src/vibeOS-lib/tests/test_stress.test.mjs\" tests/test_trinity_mega_regression.test.mjs tests/test_multisession_mega.test.mjs",
|
|
18
|
-
"test:ci": "VIBEOS_MCP_PORT=0 node --test --test-timeout=
|
|
17
|
+
"test": "VIBEOS_MCP_PORT=0 node --test --test-timeout=240000 tests/deep_integration.test.mjs tests/production_regressions.test.mjs tests/release_hardening_tigerteam.test.mjs tests/test_api_migration.neutral.test.mjs tests/test_const_assignment_regression.test.mjs tests/test_delegation_enforcer.test.mjs tests/test_diagnose_cmd.test.mjs tests/test_install_and_recovery.test.mjs tests/test_internals_stress_patterns_offtopic.test.mjs tests/test_saveos_e2e_cleanup.test.mjs tests/test_tdd_enforcer.test.mjs tests/test_10fixes_regression.test.mjs tests/test_cross_session_regression.test.mjs tests/test_mega_all_fixes.test.mjs tests/test_smart_cache_regression.test.mjs src/tests/*.test.js src/utils/tests/*.test.mjs \"src/vibeOS-lib/tests/auto-select-mode.test.mjs\" \"src/vibeOS-lib/tests/blackbox-regression.test.mjs\" \"src/vibeOS-lib/tests/blackbox-smoke.test.mjs\" \"src/vibeOS-lib/tests/budget-first-mode.test.mjs\" \"src/vibeOS-lib/tests/flow-enforcer.test.mjs\" \"src/vibeOS-lib/tests/flow-secrets.test.mjs\" \"src/vibeOS-lib/tests/session-metrics.test.mjs\" \"src/vibeOS-lib/tests/test_stress.test.mjs\" tests/test_trinity_mega_regression.test.mjs tests/test_multisession_mega.test.mjs tests/test_blackbox_default_enabled.test.mjs tests/test_mega_regressions.test.mjs",
|
|
18
|
+
"test:ci": "VIBEOS_MCP_PORT=0 node --test --test-timeout=120000 tests/production_regressions.test.mjs tests/release_hardening_tigerteam.test.mjs tests/test_const_assignment_regression.test.mjs tests/test_diagnose_cmd.test.mjs tests/test_install_and_recovery.test.mjs tests/test_saveos_e2e_cleanup.test.mjs tests/test_tdd_enforcer.test.mjs tests/test_10fixes_regression.test.mjs tests/test_cross_session_regression.test.mjs tests/test_mega_all_fixes.test.mjs tests/test_smart_cache_regression.test.mjs src/tests/*.test.js src/utils/tests/*.test.mjs \"src/vibeOS-lib/tests/auto-select-mode.test.mjs\" \"src/vibeOS-lib/tests/blackbox-regression.test.mjs\" \"src/vibeOS-lib/tests/blackbox-smoke.test.mjs\" \"src/vibeOS-lib/tests/budget-first-mode.test.mjs\" \"src/vibeOS-lib/tests/flow-enforcer.test.mjs\" \"src/vibeOS-lib/tests/flow-secrets.test.mjs\" \"src/vibeOS-lib/tests/session-metrics.test.mjs\" \"src/vibeOS-lib/tests/test_stress.test.mjs\" tests/test_blackbox_default_enabled.test.mjs tests/test_mega_regressions.test.mjs tests/test_delegation_enforcer.test.mjs tests/test_first_install_autoconfig.mjs tests/deep_integration.test.mjs tests/e2e_workflows.test.mjs tests/integration_cross_module.test.mjs tests/privacy_telemetry.test.mjs tests/release-pack.test.mjs tests/test_api_migration.neutral.test.mjs tests/test_internals_stress_patterns_offtopic.test.mjs tests/test_ml_cache_mega.test.mjs tests/test_mode_brand.test.mjs tests/test_multisession_mega.test.mjs tests/test_trinity_mega_regression.test.mjs",
|
|
19
19
|
"guard": "bash plugins/vibetheog-guard/scripts/run-guard.sh",
|
|
20
20
|
"guard:full": "VIBETHEOG_GUARD_FULL=1 bash plugins/vibetheog-guard/scripts/run-guard.sh",
|
|
21
21
|
"hook:precommit": "bash plugins/vibetheog-guard/hooks/pre-commit.sh",
|
package/src/index.js
CHANGED
|
@@ -19,7 +19,7 @@ import { safeJsonParse, readFullState, loadSelection, writeSelection, readLifeti
|
|
|
19
19
|
import { researchAudit } from "./lib/research-audit.js";
|
|
20
20
|
import { buildStatusPayload, buildSavingsPayload, buildSessionCheckout, diagnoseStructuredFromText, projectStructuredFromText, } from "./lib/runtime-surface.js";
|
|
21
21
|
import { saveReport, listReports, readReport } from "./lib/reporting.js";
|
|
22
|
-
import { writeSessionSlot } from "./lib/selection-manager.js";
|
|
22
|
+
import { writeSessionSlot, writeSessionOptMode } from "./lib/selection-manager.js";
|
|
23
23
|
import { loadCredit, thinkingLevel, _lazyRefresh, _readAuth } from "./lib/credit-api.js";
|
|
24
24
|
import { createTrinityTool } from "./lib/trinity-tool.js";
|
|
25
25
|
import { classifyAndRankModels, modelToCcAlias, discoverAvailableModels, probeModel } from "./lib/trinity-rebuild.js";
|
|
@@ -286,7 +286,7 @@ export async function DelegationEnforcer({ client, directory } = {}) {
|
|
|
286
286
|
console.error(`[vibeOS] LOADED cwd=${directory}`);
|
|
287
287
|
const hookHome = process.env.HOME || USER_HOME;
|
|
288
288
|
const hookFp = projectFingerprint(directory || "");
|
|
289
|
-
|
|
289
|
+
if (!globalThis.__vibeOS_sessionId) { globalThis.__vibeOS_sessionId = `opencode-${process.pid || "x"}-${Date.now()}`; } const hookSessionId = globalThis.__vibeOS_sessionId;
|
|
290
290
|
setVibeOSHomeContext(join(hookHome, ".claude"));
|
|
291
291
|
setCurrentSessionId(hookSessionId);
|
|
292
292
|
if (hookFp) {
|
|
@@ -434,7 +434,7 @@ export async function DelegationEnforcer({ client, directory } = {}) {
|
|
|
434
434
|
projectPatternRows, promotedProjectPatterns, detectTechStack, ensureProjectDocs,
|
|
435
435
|
discoverAvailableModels, classifyAndRankModels, modelToCcAlias, probeModel,
|
|
436
436
|
setBlackboxEnabled, loadBlackboxState, saveBlackboxState,
|
|
437
|
-
reportsIndex: reportsIndexStable, saveReportsIndex: saveReportsIndexStable, backupFile: backupFileStable, writeSessionSlot, _refreshModel,
|
|
437
|
+
reportsIndex: reportsIndexStable, saveReportsIndex: saveReportsIndexStable, backupFile: backupFileStable, writeSessionSlot, writeSessionOptMode, _refreshModel,
|
|
438
438
|
setApiToken,
|
|
439
439
|
setApiBootstrapToken,
|
|
440
440
|
ensureBootstrapExchange,
|
|
@@ -790,7 +790,7 @@ export default { id: "vibeOS", server: DelegationEnforcer };
|
|
|
790
790
|
export { researchAudit } from "./lib/research-audit.js";
|
|
791
791
|
export { saveReport, listReports, readReport } from "./lib/reporting.js";
|
|
792
792
|
export { applySlot, modelCostPerTurn, isModelFree, isDocsTarget, detectContext7, loadTierRegexes, classify, _refreshModel, HIGH_TIER_RE, MID_TIER_RE, PLACEHOLDER_RE, TRINITY_BRAIN, TRINITY_MEDIUM, TRINITY_CHEAP, setTrinityBrain, setTrinityMedium, setTrinityCheap, trendDisplay, } from "./lib/pricing.js";
|
|
793
|
-
export { getScratchpadHit, getSessionScratchpadDir, getSessionIndexPath } from "./lib/state.js";
|
|
793
|
+
export { getScratchpadHit, getSessionScratchpadDir, getSessionIndexPath, setCurrentModel, setCurrentTier } from "./lib/state.js";
|
|
794
794
|
export { extractExports, buildTestSkeleton, enforceTestFile, buildTestReminder } from "./lib/tdd-enforcer.js";
|
|
795
795
|
export { classifyAndRankModels, modelToCcAlias } from "./lib/trinity-rebuild.js";
|
|
796
796
|
export { scoreStress, detectTechStack, loadBlackboxState, saveBlackboxState, getBlackboxResolution, } from "./lib/turn-classify.js";
|
|
@@ -4,10 +4,11 @@ import { join, basename } from "node:path";
|
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
5
5
|
import { currentModel, currentProjectFingerprint, currentProjectName, _blackboxEnabled, loadSelection, writeSelection, safeJsonParse, applyDecadence, getSessionScratchpadDir, ensureSessionScratchpadDirs, indexAppend, briefedProjects, getActiveJobForProject, loadTodos, promotedProjectPatterns, detectTechStack, projectFingerprint, SCRATCHPAD_ROOT, TRINITY_OPENCODE_CONFIG, TIERS_FILE, loadGlobalLearning, setCurrentProjectFingerprint, setCurrentProjectName, stableJson, TOOL_NAME_NORMALIZE, _cacheDb, recordCacheSaving, } from "../state.js";
|
|
6
6
|
import { applySlot, TRINITY_CHEAP, TRINITY_MEDIUM, cacheSavePer1MInputTokens, } from "../pricing.js";
|
|
7
|
-
import { scoreStress, classifyTurnSimple, loadOptimizationMode, saveOptimizationMode, selectOptimizationModeRemote, computeControlVector, getBlackboxTracker, loadBlackboxState as loadBlackboxStateFromCtx, saveBlackboxState as saveBlackboxStateToCtx, extractLastUserText, isLikelyOffTopic, fetchBlackboxEnrichment, estimateContextBudget, buildControlHistoryEntry, } from "../turn-classify.js";
|
|
7
|
+
import { scoreStress, classifyTurnSimple, loadOptimizationMode, saveOptimizationMode, selectOptimizationModeRemote, computeControlVector, getBlackboxTracker, loadBlackboxState as loadBlackboxStateFromCtx, saveBlackboxState as saveBlackboxStateToCtx, extractLastUserText, isLikelyOffTopic, fetchBlackboxEnrichment, estimateContextBudget, buildControlHistoryEntry, setBlackboxEnabled, } from "../turn-classify.js";
|
|
8
8
|
import { applyBudgetFirstMode, peekBudgetFirstMode } from "../mode-policy.js";
|
|
9
|
+
import { BRANDED_MODES, RUNTIME_MODES } from "../mode-router.js";
|
|
9
10
|
import { addCacheEntry, extractRecentCacheOutputs } from "../../vibeOS-lib/smart-cache.js";
|
|
10
|
-
import { remoteCall } from "../api-client.js";
|
|
11
|
+
import { remoteCall, isApiConnected } from "../api-client.js";
|
|
11
12
|
import { loadCredit } from "../credit-api.js";
|
|
12
13
|
import { loadSessionOptMode, loadSessionSlot, writeSessionSlot } from "../selection-manager.js";
|
|
13
14
|
import { noteProjectPattern } from "../index-helpers.js";
|
|
@@ -160,12 +161,34 @@ export function syncControlSettings(cv, options = {}) {
|
|
|
160
161
|
const sid = _OC_SID;
|
|
161
162
|
const persistOptimizationMode = options.persistOptimizationMode !== false;
|
|
162
163
|
const currentSel = loadSelection();
|
|
163
|
-
const
|
|
164
|
+
const userSetMode = loadSessionOptMode(sid + "_opt");
|
|
165
|
+
const userOptMode = userSetMode || loadOptimizationMode();
|
|
166
|
+
const isManualMode = userSetMode && userOptMode !== "auto";
|
|
164
167
|
const writeIf = (key, val) => {
|
|
165
168
|
const sel = loadSelection();
|
|
166
169
|
if (sel[key] !== val)
|
|
167
170
|
writeSelection(key, val);
|
|
168
171
|
};
|
|
172
|
+
if (isManualMode) {
|
|
173
|
+
const allEntries = [...BRANDED_MODES, ...RUNTIME_MODES];
|
|
174
|
+
const modeEntry = allEntries.find((e) => e.id === userOptMode);
|
|
175
|
+
if (modeEntry) {
|
|
176
|
+
writeIf("delegation_enforce", modeEntry.enforcement === "strict" || modeEntry.enforcement === "on");
|
|
177
|
+
writeIf("flow_enabled", modeEntry.flow === "strict" || modeEntry.flow === "on" || modeEntry.flow === "audit");
|
|
178
|
+
writeIf("flow_enforce", modeEntry.flow === "strict" || modeEntry.flow === "on");
|
|
179
|
+
writeIf("tdd_enforce", modeEntry.tdd === "quality" || modeEntry.tdd === "on" || modeEntry.tdd === "strict");
|
|
180
|
+
writeIf("tdd_strict", modeEntry.tdd === "strict");
|
|
181
|
+
if (modeEntry.thinking)
|
|
182
|
+
writeIf("thinking_level", modeEntry.thinking);
|
|
183
|
+
const rawTier = modeEntry.pipeline[0] || "cheap";
|
|
184
|
+
const allowedTiers = new Set(["brain", "medium", "cheap"]);
|
|
185
|
+
const slot = allowedTiers.has(rawTier) ? rawTier : "cheap";
|
|
186
|
+
writeIf("active_slot", slot);
|
|
187
|
+
writeIf("active_pipeline", JSON.stringify(modeEntry.pipeline));
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
const compatibilityMode = currentSel.onboarding_mode === "assist";
|
|
169
192
|
writeIf("delegation_enforce", compatibilityMode ? cv.enforcement_mode === "strict" : true);
|
|
170
193
|
if (compatibilityMode) {
|
|
171
194
|
writeIf("flow_enabled", cv.flow_mode === "strict");
|
|
@@ -193,8 +216,6 @@ export function syncControlSettings(cv, options = {}) {
|
|
|
193
216
|
}
|
|
194
217
|
if (cv.thinking_mode && currentSel.thinking_level !== "full")
|
|
195
218
|
writeIf("thinking_level", cv.thinking_mode);
|
|
196
|
-
const userSetMode = loadSessionOptMode(sid + "_opt");
|
|
197
|
-
const userOptMode = userSetMode || loadOptimizationMode();
|
|
198
219
|
if (persistOptimizationMode && cv.optimization_mode && userOptMode !== "auto") {
|
|
199
220
|
if (userOptMode !== cv.optimization_mode && !userSetMode) {
|
|
200
221
|
writeSessionSlot(sid + "_opt", cv.optimization_mode);
|
|
@@ -592,6 +613,19 @@ export const onSystemTransform = async (_input, output) => {
|
|
|
592
613
|
const system = output?.system;
|
|
593
614
|
if (!Array.isArray(system))
|
|
594
615
|
return;
|
|
616
|
+
if (isApiConnected()) {
|
|
617
|
+
try {
|
|
618
|
+
const bb = loadBlackboxStateFromCtx();
|
|
619
|
+
if (!bb.enabled || _blackboxEnabled === false) {
|
|
620
|
+
setBlackboxEnabled(true);
|
|
621
|
+
if (!bb.enabled) {
|
|
622
|
+
bb.enabled = true;
|
|
623
|
+
saveBlackboxStateToCtx(bb);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
catch { }
|
|
628
|
+
}
|
|
595
629
|
const sel = loadSelection();
|
|
596
630
|
syncControlSettings(_controlVector, { persistOptimizationMode: optimizationDecision.shouldPersistRequestedMode });
|
|
597
631
|
const fp = ensureProjectContext(hookDirectory);
|
package/src/lib/hooks/footer.js
CHANGED
|
@@ -283,11 +283,15 @@ async function _appendFooter(input, output, directory) {
|
|
|
283
283
|
const ltTotal = ltTasks + ltCache;
|
|
284
284
|
const modeCapitalized = (mode) => mode.charAt(0).toUpperCase() + mode.slice(1);
|
|
285
285
|
const optMode = (resolvedMode || "budget").toLowerCase();
|
|
286
|
-
const
|
|
287
|
-
const
|
|
286
|
+
const brandMap = { vibeultrax: "VibeUltraX", vibeqmax: "VibeQMaX", vibemax: "VibeMaX" };
|
|
287
|
+
const brandedToRuntime = { vibeultrax: "Quality", vibeqmax: "Quality", vibemax: "Speed" };
|
|
288
|
+
const vibeBrand = brandMap[optModeFooter] || (execution.quality === "brain" ? "VibeQMaX" : "VibeMaX");
|
|
289
|
+
const modeLabel = modeCapitalized(brandedToRuntime[optMode] || optMode);
|
|
288
290
|
const qualityIcon = execution.quality === "brain" ? "🧠" : execution.quality === "medium" ? "⚙" : execution.quality === "free" ? "🎁" : "⚡";
|
|
289
291
|
const flashIcon = isApiConnected() ? " ⚡" : "";
|
|
290
|
-
|
|
292
|
+
const selProvider = selNowFooter.selected_provider || execution.provider_label;
|
|
293
|
+
const selModel = selNowFooter.executed_model || execution.model;
|
|
294
|
+
let vibeLine = `— ${qualityIcon} ${execution.quality} | ${selProvider} | ${modelDisplayName(selModel)}`;
|
|
291
295
|
if (ltTotal > 0) {
|
|
292
296
|
vibeLine += ` | $${formatUsd(ltTotal)}`;
|
|
293
297
|
}
|
|
@@ -3,15 +3,22 @@ import { writeFileSync, appendFileSync, existsSync, mkdirSync } from "node:fs";
|
|
|
3
3
|
import { join, dirname, basename } from "node:path";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
5
5
|
import { currentTier, currentModel, setCurrentModel, setCurrentTier, _OC_SID, _modelLocked, loadSelection, readLifetimeSavings, recordCacheSaving, recordMissedContext7, getScratchpadHit, recordScratchpadObservation, recordPrivacyTelemetry, updateState, getSessionScratchpadDir, ensureSessionScratchpadDirs, SAVINGS_LEDGER_FILE, CONTEXT7_INSTALL_FLAG, SOFT_QUOTA_LIMIT, upsertTodo, ML_ENABLED, _mlGraph, _cacheDb, _mlSavePending, ML_CONFIDENCE_THRESHOLD, setMlSavePending, saveMLState, SCRATCHPAD_TOOLS, SCRATCHPAD_GLOBAL_DIR, TOOL_NAME_NORMALIZE, stableJson, applyDecadence, } from "../state.js";
|
|
6
|
-
import { classify, modelCostPerTurn, isModelFree, detectContext7, isDocsTarget, shortModelName, formatUsd, _refreshModel, readConfig, resolveDisplayModelId, TRINITY_CHEAP, TRINITY_MEDIUM, cacheSavePer1MInputTokens, trendDisplay, modelToSlotLabel, resolveExecutionIdentity,
|
|
6
|
+
import { classify, modelCostPerTurn, isModelFree, detectContext7, isDocsTarget, shortModelName, formatUsd, _refreshModel, readConfig, resolveDisplayModelId, TRINITY_CHEAP, TRINITY_MEDIUM, TRINITY_BRAIN, cacheSavePer1MInputTokens, trendDisplay, modelToSlotLabel, resolveExecutionIdentity, modelDisplayName, } from "../pricing.js";
|
|
7
7
|
import { latestUserIntent } from "./chat-transform.js";
|
|
8
|
+
import { loadSessionOptMode } from "../selection-manager.js";
|
|
9
|
+
import { loadOptimizationMode } from "../turn-classify.js";
|
|
10
|
+
function modeCapitalized(mode) {
|
|
11
|
+
if (!mode)
|
|
12
|
+
return "Budget";
|
|
13
|
+
return mode.charAt(0).toUpperCase() + mode.slice(1);
|
|
14
|
+
}
|
|
8
15
|
import { scoreStress, extractFirstWordFromArgs, shouldLogWarn, isUserAskingForTests, resolveEnforcementMode, getLearnedExploratoryWords, noteTaskRoutingLearning, incrementTurnCounter, } from "../turn-classify.js";
|
|
9
16
|
import { saveReport } from "../reporting.js";
|
|
10
17
|
import { loadCredit } from "../credit-api.js";
|
|
11
18
|
import { remoteCall, VIBEOS_API_ENABLED } from "../api-client.js";
|
|
12
19
|
import { getCostAnomalyDetector } from "../cost-anomaly.js";
|
|
13
20
|
import { checkFlowRules } from "../../vibeOS-lib/flow-enforcer.js";
|
|
14
|
-
import { computeDifficulty, addRouteEdge, predictBestModel, hashQuery } from "../../vibeOS-lib/ml-router.js";
|
|
21
|
+
import { computeDifficulty, cascadeDecide, addRouteEdge, predictBestModel, hashQuery } from "../../vibeOS-lib/ml-router.js";
|
|
15
22
|
import { addCacheEntry, recordCacheStats, predictCacheHit } from "../../vibeOS-lib/smart-cache.js";
|
|
16
23
|
import { buildTestReminder, enforceTestFile } from "../tdd-enforcer.js";
|
|
17
24
|
import { setActiveJobFromTaskPrompt, observeToolPattern, compressText, recordSaving } from "../index-helpers.js";
|
|
@@ -412,6 +419,33 @@ export const onToolExecuteBefore = async (input, output) => {
|
|
|
412
419
|
console.error(`[vibeOS] ML router error: ${mlErr.message}`);
|
|
413
420
|
}
|
|
414
421
|
}
|
|
422
|
+
const activePipeline = loadSelection().active_pipeline;
|
|
423
|
+
if (activePipeline && Array.isArray(activePipeline) && activePipeline.length > 1 && TRINITY_CHEAP && TRINITY_MEDIUM) {
|
|
424
|
+
try {
|
|
425
|
+
const cheapCost = 0.001;
|
|
426
|
+
const mediumCost = 0.005;
|
|
427
|
+
const brainCost = 0.02;
|
|
428
|
+
const cascadeResult = cascadeDecide(_prompt, cheapCost, mediumCost, brainCost, 0.85);
|
|
429
|
+
const tierMap = { cheap: TRINITY_CHEAP, medium: TRINITY_MEDIUM, brain: TRINITY_BRAIN || TRINITY_MEDIUM, local: TRINITY_CHEAP };
|
|
430
|
+
const pipelineModels = activePipeline.map(t => tierMap[t] || TRINITY_CHEAP);
|
|
431
|
+
if (cascadeResult.escalate && pipelineModels.length > 1) {
|
|
432
|
+
const escalated = pipelineModels[1];
|
|
433
|
+
if (escalated && escalated !== currentModel && (!_target || escalated !== _target)) {
|
|
434
|
+
_target = escalated;
|
|
435
|
+
console.error(`[vibeOS] 🔀 Cascade escalate: ${cascadeResult.reason} → ${escalated}`);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
else if (cascadeResult.useCheap && !_target) {
|
|
439
|
+
_target = pipelineModels[0];
|
|
440
|
+
if (_target && _target !== currentModel) {
|
|
441
|
+
console.error(`[vibeOS] 🔀 Cascade cheap: ${cascadeResult.reason} → ${_target}`);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
catch (cascadeErr) {
|
|
446
|
+
console.error(`[vibeOS] Cascade router error: ${cascadeErr.message}`);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
415
449
|
if (_target)
|
|
416
450
|
noteTaskRoutingLearning(_firstWord, _target, _exploratoryTarget ? "exploratory" : `tier:${currentTier}`);
|
|
417
451
|
if (_target && targetArgs?.model !== _target) {
|
|
@@ -690,11 +724,20 @@ export const onToolExecuteAfter = async (input, output) => {
|
|
|
690
724
|
setCurrentTier(classify(resolvedModel));
|
|
691
725
|
}
|
|
692
726
|
const execution = resolveExecutionIdentity(input?.args?.model || resolvedModel || "", projectDirectory);
|
|
693
|
-
|
|
727
|
+
const { BRANDED_MODES, RUNTIME_MODES } = await import("../mode-router.js");
|
|
728
|
+
const brandMap = { vibeultrax: "VibeUltraX", vibeqmax: "VibeQMaX", vibemax: "VibeMaX" };
|
|
729
|
+
const brandedToRuntime = { vibeultrax: "Quality", vibeqmax: "Quality", vibemax: "Speed" };
|
|
730
|
+
const currentSel = loadSelection();
|
|
731
|
+
const currentSid = _OC_SID;
|
|
732
|
+
const optModeFooter = loadSessionOptMode(currentSid + "_opt") || loadOptimizationMode() || "budget";
|
|
733
|
+
const vibeBrand = brandMap[optModeFooter] || (execution.quality === "brain" ? "VibeQMaX" : "VibeMaX");
|
|
734
|
+
const qualityIcon = execution.quality === "brain" ? "\u{1F9E0}" : execution.quality === "medium" ? "\u2699" : execution.quality === "free" ? "\u{1F381}" : "\u26A1";
|
|
735
|
+
const modeLabel = modeCapitalized(brandedToRuntime[optModeFooter] || optModeFooter);
|
|
736
|
+
_footerText = `— ${qualityIcon} ${execution.quality} | ${currentSel.selected_provider || execution.provider_label} | ${modelDisplayName(currentSel.executed_model || execution.model)}`;
|
|
694
737
|
if (ltTotal > 0) {
|
|
695
|
-
_footerText += ` | $${formatUsd(ltTotal)}
|
|
738
|
+
_footerText += ` | $${formatUsd(ltTotal)}`;
|
|
696
739
|
}
|
|
697
|
-
_footerText += ` |
|
|
740
|
+
_footerText += ` | ${vibeBrand}${flashIcon} ${modeLabel} —\n\n`;
|
|
698
741
|
output.title = _footerText.trim();
|
|
699
742
|
if (typeof output?.output === "string")
|
|
700
743
|
output.output = _footerText + output.output;
|
package/src/lib/mode-router.js
CHANGED
|
@@ -67,11 +67,18 @@ export const RUNTIME_MODES = [
|
|
|
67
67
|
desc: "Brain tier security audit. OWASP validation.",
|
|
68
68
|
},
|
|
69
69
|
{
|
|
70
|
-
id: "longrun", index:
|
|
70
|
+
id: "longrun", index: 6, name: "Longrun", icon: "\u{1F4C8}",
|
|
71
|
+
pipeline: ["cheap"],
|
|
72
|
+
thinking: "off", tdd: "off", enforcement: "off", flow: "off",
|
|
73
|
+
qualityVsBrain: 15, costVsBrain: 100,
|
|
74
|
+
desc: "Extended sessions. Cheap tier only.",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: "forensic", index: 7, name: "Forensic", icon: "\u{1F52C}",
|
|
71
78
|
pipeline: ["brain"],
|
|
72
79
|
thinking: "full", tdd: "quality", enforcement: "strict", flow: "strict",
|
|
73
|
-
qualityVsBrain: 100, costVsBrain:
|
|
74
|
-
desc: "
|
|
80
|
+
qualityVsBrain: 100, costVsBrain: 65,
|
|
81
|
+
desc: "Deep analysis and web research. Full audit trail.",
|
|
75
82
|
},
|
|
76
83
|
];
|
|
77
84
|
export const RAW_MODE = {
|
|
@@ -57,6 +57,8 @@ export function loadSelection() {
|
|
|
57
57
|
return {
|
|
58
58
|
enabled: j?.selection?.enabled !== false,
|
|
59
59
|
active_slot: j?.selection?.active_slot || null,
|
|
60
|
+
active_pipeline: j?.selection?.active_pipeline || null,
|
|
61
|
+
optimization_mode: j?.selection?.optimization_mode || null,
|
|
60
62
|
thinking_level: j?.selection?.thinking_level || "off",
|
|
61
63
|
flow_enabled: j?.selection?.flow_enabled === true,
|
|
62
64
|
tdd_enforce: j?.selection?.tdd_enforce === true,
|
|
@@ -140,6 +142,18 @@ export function loadSessionOptMode(sid) {
|
|
|
140
142
|
return null;
|
|
141
143
|
}
|
|
142
144
|
}
|
|
145
|
+
export function loadGlobalOptMode() {
|
|
146
|
+
try {
|
|
147
|
+
const sel = loadSelection();
|
|
148
|
+
return sel.optimization_mode || null;
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
export function saveGlobalOptMode(mode) {
|
|
155
|
+
return writeSelection("optimization_mode", mode);
|
|
156
|
+
}
|
|
143
157
|
export function writeSessionOptMode(sid, mode) {
|
|
144
158
|
const BLACKBOX_FILE = join(getVibeOSHome(), "blackbox-state.json");
|
|
145
159
|
try {
|
package/src/lib/state.js
CHANGED
|
@@ -113,6 +113,14 @@ const warnCoalesceCounters = new Map();
|
|
|
113
113
|
let _savingsCache = null;
|
|
114
114
|
let _savingsCacheMtime = 0;
|
|
115
115
|
let _ledgerReconciledMtime = 0;
|
|
116
|
+
let _ledgerTotalsCache = {
|
|
117
|
+
mtime: 0,
|
|
118
|
+
size: 0,
|
|
119
|
+
delegation: 0,
|
|
120
|
+
cache: 0,
|
|
121
|
+
context7: 0,
|
|
122
|
+
entries: 0,
|
|
123
|
+
};
|
|
116
124
|
function invalidateSavingsCache() {
|
|
117
125
|
_savingsCache = null;
|
|
118
126
|
_savingsCacheMtime = 0;
|
|
@@ -1617,16 +1625,82 @@ function getTodos() {
|
|
|
1617
1625
|
function readLedgerTotals() {
|
|
1618
1626
|
const empty = { delegation: 0, cache: 0, context7: 0, total: 0, entries: 0 };
|
|
1619
1627
|
try {
|
|
1620
|
-
if (!existsSync(SAVINGS_LEDGER_FILE))
|
|
1628
|
+
if (!existsSync(SAVINGS_LEDGER_FILE)) {
|
|
1629
|
+
_ledgerTotalsCache = { mtime: 0, size: 0, delegation: 0, cache: 0, context7: 0, entries: 0 };
|
|
1621
1630
|
return empty;
|
|
1622
|
-
|
|
1623
|
-
|
|
1631
|
+
}
|
|
1632
|
+
const st = statSync(SAVINGS_LEDGER_FILE);
|
|
1633
|
+
if (st.size > 10485760) {
|
|
1634
|
+
_handleStateCorruption(SAVINGS_LEDGER_FILE);
|
|
1624
1635
|
return empty;
|
|
1636
|
+
}
|
|
1637
|
+
if (st.size === 0) {
|
|
1638
|
+
_ledgerTotalsCache = { mtime: st.mtimeMs, size: 0, delegation: 0, cache: 0, context7: 0, entries: 0 };
|
|
1639
|
+
return empty;
|
|
1640
|
+
}
|
|
1641
|
+
if (_ledgerTotalsCache.mtime === st.mtimeMs && _ledgerTotalsCache.size === st.size) {
|
|
1642
|
+
return {
|
|
1643
|
+
delegation: Math.round(_ledgerTotalsCache.delegation * 1000) / 1000,
|
|
1644
|
+
cache: Math.round(_ledgerTotalsCache.cache * 1000) / 1000,
|
|
1645
|
+
context7: Math.round(_ledgerTotalsCache.context7 * 1000) / 1000,
|
|
1646
|
+
total: Math.round((_ledgerTotalsCache.delegation + _ledgerTotalsCache.cache) * 1000) / 1000,
|
|
1647
|
+
entries: _ledgerTotalsCache.entries,
|
|
1648
|
+
};
|
|
1649
|
+
}
|
|
1625
1650
|
let delegation = 0;
|
|
1626
1651
|
let cache = 0;
|
|
1627
1652
|
let context7 = 0;
|
|
1628
1653
|
let entries = 0;
|
|
1629
|
-
|
|
1654
|
+
let raw = "";
|
|
1655
|
+
let incremental = _ledgerTotalsCache.size > 0 && st.size >= _ledgerTotalsCache.size && _ledgerTotalsCache.mtime > 0;
|
|
1656
|
+
if (incremental) {
|
|
1657
|
+
const deltaSize = st.size - _ledgerTotalsCache.size;
|
|
1658
|
+
if (deltaSize > 0) {
|
|
1659
|
+
const fd = openSync(SAVINGS_LEDGER_FILE, "r");
|
|
1660
|
+
try {
|
|
1661
|
+
const buf = Buffer.allocUnsafe(deltaSize);
|
|
1662
|
+
const bytesRead = readSync(fd, buf, 0, deltaSize, _ledgerTotalsCache.size);
|
|
1663
|
+
raw = buf.toString("utf-8", 0, bytesRead);
|
|
1664
|
+
}
|
|
1665
|
+
finally {
|
|
1666
|
+
try {
|
|
1667
|
+
closeSync(fd);
|
|
1668
|
+
}
|
|
1669
|
+
catch { }
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
else {
|
|
1673
|
+
incremental = false;
|
|
1674
|
+
}
|
|
1675
|
+
delegation = _ledgerTotalsCache.delegation;
|
|
1676
|
+
cache = _ledgerTotalsCache.cache;
|
|
1677
|
+
context7 = _ledgerTotalsCache.context7;
|
|
1678
|
+
entries = _ledgerTotalsCache.entries;
|
|
1679
|
+
}
|
|
1680
|
+
if (!incremental) {
|
|
1681
|
+
raw = readFileSync(SAVINGS_LEDGER_FILE, "utf-8");
|
|
1682
|
+
}
|
|
1683
|
+
if (!raw.trim()) {
|
|
1684
|
+
_ledgerTotalsCache = {
|
|
1685
|
+
mtime: st.mtimeMs,
|
|
1686
|
+
size: st.size,
|
|
1687
|
+
delegation,
|
|
1688
|
+
cache,
|
|
1689
|
+
context7,
|
|
1690
|
+
entries,
|
|
1691
|
+
};
|
|
1692
|
+
return {
|
|
1693
|
+
delegation: Math.round(delegation * 1000) / 1000,
|
|
1694
|
+
cache: Math.round(cache * 1000) / 1000,
|
|
1695
|
+
context7: Math.round(context7 * 1000) / 1000,
|
|
1696
|
+
total: Math.round((delegation + cache) * 1000) / 1000,
|
|
1697
|
+
entries,
|
|
1698
|
+
};
|
|
1699
|
+
}
|
|
1700
|
+
const lines = raw.split("\n");
|
|
1701
|
+
if (raw.endsWith("\n"))
|
|
1702
|
+
lines.pop();
|
|
1703
|
+
for (const line of lines) {
|
|
1630
1704
|
const ln = line.trim();
|
|
1631
1705
|
if (!ln)
|
|
1632
1706
|
continue;
|
|
@@ -1653,6 +1727,7 @@ function readLedgerTotals() {
|
|
|
1653
1727
|
else
|
|
1654
1728
|
delegation += amt;
|
|
1655
1729
|
}
|
|
1730
|
+
_ledgerTotalsCache = { mtime: st.mtimeMs, size: st.size, delegation, cache, context7, entries };
|
|
1656
1731
|
const total = delegation + cache;
|
|
1657
1732
|
return {
|
|
1658
1733
|
delegation: Math.round(delegation * 1000) / 1000,
|
|
@@ -1668,8 +1743,10 @@ function readLedgerTotals() {
|
|
|
1668
1743
|
}
|
|
1669
1744
|
function reconcileStateFromLedger() {
|
|
1670
1745
|
try {
|
|
1671
|
-
const
|
|
1672
|
-
|
|
1746
|
+
const ledgerStat = existsSync(SAVINGS_LEDGER_FILE) ? statSync(SAVINGS_LEDGER_FILE) : null;
|
|
1747
|
+
const ledgerMtime = ledgerStat?.mtimeMs || 0;
|
|
1748
|
+
const ledgerSize = ledgerStat?.size || 0;
|
|
1749
|
+
if (ledgerMtime === _ledgerReconciledMtime && ledgerSize === (_savingsCache?._ledgerSize || 0))
|
|
1673
1750
|
return;
|
|
1674
1751
|
_ledgerReconciledMtime = ledgerMtime;
|
|
1675
1752
|
_flushLedgerBuffer();
|
|
@@ -1694,6 +1771,8 @@ function reconcileStateFromLedger() {
|
|
|
1694
1771
|
s.lifetime.ledger_entries_reconciled = l.entries;
|
|
1695
1772
|
return s;
|
|
1696
1773
|
});
|
|
1774
|
+
_savingsCache = null;
|
|
1775
|
+
_savingsCacheMtime = 0;
|
|
1697
1776
|
invalidateSavingsCache();
|
|
1698
1777
|
}
|
|
1699
1778
|
catch { }
|
|
@@ -1709,7 +1788,8 @@ function readLifetimeSavings() {
|
|
|
1709
1788
|
if (_savingsCache && mtime === _savingsCacheMtime)
|
|
1710
1789
|
return _savingsCache;
|
|
1711
1790
|
const s = safeJsonParse(readFileSync(delegationStateFile, "utf-8"));
|
|
1712
|
-
|
|
1791
|
+
const ledgerSize = existsSync(SAVINGS_LEDGER_FILE) ? statSync(SAVINGS_LEDGER_FILE).size : 0;
|
|
1792
|
+
_savingsCache = { ..._computeSessionMetrics(s, _OC_SID), telemetry: readTelemetrySummary(s, _OC_SID), _ledgerSize: ledgerSize };
|
|
1713
1793
|
_savingsCacheMtime = mtime;
|
|
1714
1794
|
return _savingsCache;
|
|
1715
1795
|
}
|
package/src/lib/trinity-tool.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
|
-
import { join } from "node:path";
|
|
2
|
+
import { join, dirname } 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";
|
|
@@ -20,6 +20,8 @@ export function createTrinityTool(deps) {
|
|
|
20
20
|
"Use action='enable' or 'disable' to toggle the plugin (takes effect immediately, no restart needed). " +
|
|
21
21
|
"Use action='set' with slot='brain'|'medium'|'cheap' to switch model tiers " +
|
|
22
22
|
"(writes opencode.json — active immediately). " +
|
|
23
|
+
"Use action='mode' with slot='vibeultrax'|'vibeqmax'|'vibemax'|'budget'|'quality'|'speed'|'longrun'|'auto'|'balanced'|'audit'|'forensic' to switch optimization mode. " +
|
|
24
|
+
"Use action='thinking' with level='full'|'brief'|'off'. " +
|
|
23
25
|
"Use action='rebuild' to auto-detect available models from all configured providers and reassign brain/medium/cheap slots. " +
|
|
24
26
|
"Use action='flow' with slot='on'|'off' to toggle flow enforcer, or action='flow' alone for audit. " +
|
|
25
27
|
"Use action='flow' with slot='enforce' and level='on'|'off' to toggle auto-extract TODOs. " +
|
|
@@ -48,6 +50,20 @@ export function createTrinityTool(deps) {
|
|
|
48
50
|
slot = action;
|
|
49
51
|
action = "set";
|
|
50
52
|
}
|
|
53
|
+
const _brandedModeIds = ["vibeultrax", "vibeqmax", "vibemax"];
|
|
54
|
+
const _builtInModeIds = ["budget", "quality", "speed", "longrun", "auto", "balanced", "audit", "forensic"];
|
|
55
|
+
if (!action || action === "status") { }
|
|
56
|
+
else if (_brandedModeIds.includes(action) || _builtInModeIds.includes(action)) {
|
|
57
|
+
slot = action;
|
|
58
|
+
action = "mode";
|
|
59
|
+
}
|
|
60
|
+
else if (["full", "brief", "off"].includes(action)) {
|
|
61
|
+
level = action;
|
|
62
|
+
action = "thinking";
|
|
63
|
+
}
|
|
64
|
+
else if (["on", "off"].includes(action) && !slot) {
|
|
65
|
+
slot = action;
|
|
66
|
+
}
|
|
51
67
|
if (action === "status") {
|
|
52
68
|
const sel = deps.loadSelection();
|
|
53
69
|
let tiers = {};
|
|
@@ -58,6 +74,41 @@ export function createTrinityTool(deps) {
|
|
|
58
74
|
let cheapModel = "(unset)";
|
|
59
75
|
const credit = deps.loadCredit();
|
|
60
76
|
const effectiveLevel = sel.thinking_level || deps.thinkingLevel(credit);
|
|
77
|
+
if (deps.currentModel && sel.selected_model && deps.currentModel !== sel.selected_model) {
|
|
78
|
+
try {
|
|
79
|
+
const providers = deps._loadOpenCodeProviders();
|
|
80
|
+
const auth = deps._readAuth();
|
|
81
|
+
const models = await deps.discoverAvailableModels(providers, auth);
|
|
82
|
+
const trinity = buildDeterministicTrinity(models, { selectedModelId: deps.currentModel, selectedTier: sel.active_slot || "brain" });
|
|
83
|
+
if (trinity && trinity.brain) {
|
|
84
|
+
const probed = {
|
|
85
|
+
brain: models.find(m => m.id === trinity.brain) || { id: trinity.brain, cost: deps._modelCost(trinity.brain), tier: deps._modelTier(trinity.brain) },
|
|
86
|
+
medium: models.find(m => m.id === trinity.medium) || { id: trinity.medium, cost: deps._modelCost(trinity.medium), tier: deps._modelTier(trinity.medium) },
|
|
87
|
+
cheap: models.find(m => m.id === trinity.cheap) || { id: trinity.cheap, cost: deps._modelCost(trinity.cheap), tier: deps._modelTier(trinity.cheap) },
|
|
88
|
+
};
|
|
89
|
+
const tiersData = deps.safeJsonParse(deps.readFileSync(deps.TIERS_FILE, "utf-8"));
|
|
90
|
+
tiersData.trinity = {
|
|
91
|
+
brain: { oc: probed.brain.id, cc: deps.modelToCcAlias(probed.brain.id) },
|
|
92
|
+
medium: { oc: probed.medium.id, cc: deps.modelToCcAlias(probed.medium.id) },
|
|
93
|
+
cheap: { oc: probed.cheap.id, cc: deps.modelToCcAlias(probed.cheap.id) },
|
|
94
|
+
};
|
|
95
|
+
tiersData.selection ??= {};
|
|
96
|
+
tiersData.selection.selected_provider = trinity.provider || resolveExecutionIdentity(deps.currentModel, deps.directory)?.provider || "";
|
|
97
|
+
tiersData.selection.selected_model = deps.currentModel;
|
|
98
|
+
tiersData.selection.executed_provider = tiersData.selection.selected_provider;
|
|
99
|
+
tiersData.selection.executed_model = deps.currentModel;
|
|
100
|
+
const _tmp = deps.TIERS_FILE + ".tmp." + Date.now();
|
|
101
|
+
deps.writeFileSync(_tmp, JSON.stringify(tiersData, null, 2) + "\n", "utf-8");
|
|
102
|
+
deps.renameSync(_tmp, deps.TIERS_FILE);
|
|
103
|
+
tiers = tiersData.trinity;
|
|
104
|
+
sel.selected_provider = tiersData.selection.selected_provider;
|
|
105
|
+
sel.selected_model = deps.currentModel;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
console.error("[vibeOS] auto-rebuild on model change failed:", e.message);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
61
112
|
const sv = deps.readLifetimeSavings();
|
|
62
113
|
const ltTotal = (sv.ltTasks || 0) + (sv.ltCache || 0);
|
|
63
114
|
const sesTasks = sv.sesTasks || 0;
|
|
@@ -202,20 +253,22 @@ export function createTrinityTool(deps) {
|
|
|
202
253
|
const ok = deps.saveOptimizationMode(resolvedSlot);
|
|
203
254
|
if (!ok)
|
|
204
255
|
return `Failed to write mode`;
|
|
205
|
-
deps.
|
|
256
|
+
deps.writeSessionOptMode(deps._OC_SID + "_opt", resolvedSlot);
|
|
206
257
|
const allEntries = [...BRANDED_MODES, ...RUNTIME_MODES];
|
|
207
258
|
const modeEntry = allEntries.find(e => e.id === slot);
|
|
208
259
|
if (modeEntry) {
|
|
209
260
|
const rawTier = modeEntry.pipeline[0] || "cheap";
|
|
210
261
|
const tierSlot = new Set(["brain", "medium", "cheap"]).has(rawTier) ? rawTier : "cheap";
|
|
211
262
|
deps.writeSelection("active_slot", tierSlot);
|
|
263
|
+
deps.writeSelection("active_pipeline", modeEntry.pipeline);
|
|
212
264
|
deps.writeSelection("onboarding_mode", modeEntry.tdd === "quality" || modeEntry.enforcement === "strict" ? "strict" : "assist");
|
|
213
265
|
deps.writeSelection("delegation_enforce", modeEntry.enforcement === "strict" || modeEntry.enforcement === "on");
|
|
214
266
|
deps.writeSelection("flow_enabled", modeEntry.flow === "strict" || modeEntry.flow === "on" || modeEntry.flow === "audit");
|
|
215
267
|
deps.writeSelection("flow_enforce", modeEntry.flow === "strict" || modeEntry.flow === "on");
|
|
216
268
|
deps.writeSelection("tdd_enforce", modeEntry.tdd === "quality" || modeEntry.tdd === "on" || modeEntry.tdd === "strict");
|
|
217
269
|
deps.writeSelection("thinking_level", modeEntry.thinking);
|
|
218
|
-
|
|
270
|
+
const pipelineStr = modeEntry.pipeline.join(" → ");
|
|
271
|
+
return `Mode set to ${slot.toUpperCase()}. Tier: ${tierSlot}. Pipeline: ${pipelineStr}`;
|
|
219
272
|
}
|
|
220
273
|
return `Mode set to ${slot.toUpperCase()}.`;
|
|
221
274
|
}
|
|
@@ -408,16 +461,6 @@ export function createTrinityTool(deps) {
|
|
|
408
461
|
tiers.trinity.cheap = { oc: cheap, cc: deps.modelToCcAlias(cheap) };
|
|
409
462
|
deps.mkdirSync(dirname(deps.TIERS_FILE), { recursive: true });
|
|
410
463
|
deps.writeFileSync(deps.TIERS_FILE, JSON.stringify(tiers, null, 2) + "\n");
|
|
411
|
-
try {
|
|
412
|
-
const bbState = deps.loadBlackboxState();
|
|
413
|
-
bbState.enabled = false;
|
|
414
|
-
deps.saveBlackboxState(bbState);
|
|
415
|
-
if (typeof deps.setBlackboxEnabled === "function")
|
|
416
|
-
deps.setBlackboxEnabled(false);
|
|
417
|
-
else
|
|
418
|
-
deps._blackboxEnabled = false;
|
|
419
|
-
}
|
|
420
|
-
catch { }
|
|
421
464
|
if (typeof deps._refreshModel === "function")
|
|
422
465
|
deps._refreshModel(deps.directory);
|
|
423
466
|
const lines = [
|
|
@@ -428,7 +471,7 @@ export function createTrinityTool(deps) {
|
|
|
428
471
|
` Delegation: off`,
|
|
429
472
|
` Flow: off`,
|
|
430
473
|
` TDD: off`,
|
|
431
|
-
` Blackbox:
|
|
474
|
+
` Blackbox: on`,
|
|
432
475
|
];
|
|
433
476
|
if (discovered.length > 0)
|
|
434
477
|
lines.push(` Discovered models: ${discovered.length}`);
|
package/src/lib/turn-classify.js
CHANGED
|
@@ -3,7 +3,7 @@ import { readFileSync, writeFileSync, existsSync, mkdirSync, renameSync } from "
|
|
|
3
3
|
import { join, dirname } from "node:path";
|
|
4
4
|
import { ResolutionTracker } from "../vibeOS-lib/blackbox/index.js";
|
|
5
5
|
import { safeJsonParse, _blackboxEnabled, setBlackboxEnabled as _setGlobalBlackboxEnabled, _OC_SID, currentProjectFingerprint, setCurrentProjectFingerprint, withFileLock, readJsonOrEmpty, validateState, loadBlackboxState, saveBlackboxState, loadGlobalLearning, updateGlobalLearning, getLearnedExploratoryWords, projectFingerprint, loadProjectState, saveProjectState, detectTechStack, ensureProjectBucket, recordMissedContext7 } from "./state.js";
|
|
6
|
-
import { loadSessionOptMode, writeSessionOptMode } from "./selection-manager.js";
|
|
6
|
+
import { loadSessionOptMode, loadGlobalOptMode, saveGlobalOptMode, writeSessionOptMode } from "./selection-manager.js";
|
|
7
7
|
import { getApiClient, isApiFallback } from "./api-client.js";
|
|
8
8
|
export { scoreStress, estimateContextBudget, classifyTurnSimple, tokenizeWords, topKeywords, extractLastUserText, isUserAskingForTests, isLikelyOffTopic, detectOutcomeSignal } from "./classifiers.js";
|
|
9
9
|
function getVibeOSHome() {
|
|
@@ -557,7 +557,12 @@ const DFLT_OPTIMIZATION_MODE = "budget";
|
|
|
557
557
|
export function loadOptimizationMode() {
|
|
558
558
|
try {
|
|
559
559
|
const mode = loadSessionOptMode(_OC_SID);
|
|
560
|
-
|
|
560
|
+
if (mode && mode !== "auto")
|
|
561
|
+
return mode;
|
|
562
|
+
const global = loadGlobalOptMode();
|
|
563
|
+
if (global && global !== "auto")
|
|
564
|
+
return global;
|
|
565
|
+
return DFLT_OPTIMIZATION_MODE;
|
|
561
566
|
}
|
|
562
567
|
catch {
|
|
563
568
|
return DFLT_OPTIMIZATION_MODE;
|
|
@@ -565,7 +570,10 @@ export function loadOptimizationMode() {
|
|
|
565
570
|
}
|
|
566
571
|
export function saveOptimizationMode(mode) {
|
|
567
572
|
try {
|
|
568
|
-
|
|
573
|
+
writeSessionOptMode(_OC_SID, mode);
|
|
574
|
+
if (mode && mode !== "auto")
|
|
575
|
+
saveGlobalOptMode(mode);
|
|
576
|
+
return true;
|
|
569
577
|
}
|
|
570
578
|
catch (err) {
|
|
571
579
|
console.error("[vibeOS] saveOptimizationMode failed: " + err.message);
|