vibeostheog 0.23.55 → 0.23.56
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 +8 -0
- package/package.json +1 -1
- package/src/lib/hooks/chat-transform.js +27 -29
- package/src/lib/hooks/footer.js +1 -0
- package/src/lib/hooks/shared-footer.js +18 -2
- package/src/lib/hooks/tool-execute.js +11 -11
- package/src/lib/trinity-tool.js +15 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## 0.23.56
|
|
2
|
+
- fix: softer dopamine-style communication layer with compact vector-change storytelling and calmer footer pulses
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
## 0.23.55
|
|
6
|
+
- feat: add single-file bundle build (esbuild) + fix vibelitex schema deployment
|
|
7
|
+
|
|
8
|
+
|
|
1
9
|
## 0.23.54
|
|
2
10
|
- test: make blackboxSelectMode test resilient to API response format
|
|
3
11
|
- test: fix e2e tests for vibelitex mode (budget → vibelitex)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibeostheog",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.56",
|
|
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",
|
|
@@ -497,20 +497,19 @@ const C7_URGENCY = {
|
|
|
497
497
|
function context7Directive(cv) {
|
|
498
498
|
const urgency = cv?.context7_urgency || "preferred";
|
|
499
499
|
return "[cost policy] If mcp__context7__resolve-library-id and mcp__context7__get-library-docs " +
|
|
500
|
-
"
|
|
501
|
-
"when looking up library or framework documentation " +
|
|
500
|
+
"are available, prefer them over WebFetch/WebSearch for library and framework docs " +
|
|
502
501
|
"(docs.*, readthedocs.*, npmjs.com/package/*, pypi.org/project/*, pkg.go.dev, /api/reference/). " +
|
|
503
|
-
"
|
|
504
|
-
"This saves
|
|
502
|
+
"Use the cheapest accurate source first. " +
|
|
503
|
+
"This usually saves about $0.06/turn." +
|
|
505
504
|
(C7_URGENCY[urgency] || "");
|
|
506
505
|
}
|
|
507
506
|
function thinkingDirective(level) {
|
|
508
507
|
const credit = loadCredit();
|
|
509
508
|
const creditNote = `credit ${credit}%`;
|
|
510
509
|
if (level === "brief") {
|
|
511
|
-
return `[thinking policy] Reasoning depth: BRIEF (manually set, ${creditNote}).
|
|
510
|
+
return `[thinking policy] Reasoning depth: BRIEF (manually set, ${creditNote}). Keep the answer crisp and only expand when the task truly needs it.`;
|
|
512
511
|
}
|
|
513
|
-
return `[thinking policy] Reasoning depth: OFF (manually set, ${creditNote}).
|
|
512
|
+
return `[thinking policy] Reasoning depth: OFF (manually set, ${creditNote}). Respond directly, avoid extra scratch work, and reserve extended thinking for when the user asks for it.`;
|
|
514
513
|
}
|
|
515
514
|
function orchestratorDirective(cv, sel) {
|
|
516
515
|
const tierBias = cv?.tier_bias || "auto";
|
|
@@ -525,10 +524,10 @@ function orchestratorDirective(cv, sel) {
|
|
|
525
524
|
const compatibilityMode = sel?.onboarding_mode === "assist";
|
|
526
525
|
return `[AI ORCHESTRATOR AGENT] You are an AI orchestrator agent. ` +
|
|
527
526
|
`Delegate heavy work to Task subagents (runs on ${targetModel}). ` +
|
|
528
|
-
`Your role
|
|
527
|
+
`Your role is to verify, fill gaps, and synthesize cleanly. ` +
|
|
529
528
|
(compatibilityMode
|
|
530
|
-
? "Compatibility mode is active
|
|
531
|
-
: "
|
|
529
|
+
? "Compatibility mode is active, so direct Write/Edit stays available until strict guardrails are enabled."
|
|
530
|
+
: "Write/Edit tools are blocked on this tier; delegate implementation work to Task subagents.") +
|
|
532
531
|
` Always display the vibeOS cost footer.` +
|
|
533
532
|
(tierBias !== "auto" ? ` [tier routing] This turn is biased toward ${tierBias} tier.` : "");
|
|
534
533
|
}
|
|
@@ -541,8 +540,8 @@ function tddDirective(cv, sel) {
|
|
|
541
540
|
const tddMode = cv?.tdd_mode || (sel.tdd_strict ? "strict" : "normal");
|
|
542
541
|
const tddFocus = cv?.tdd_focus || [];
|
|
543
542
|
const focusNote = tddFocus.length > 0 ? ` Focus: ${tddFocus.join(", ")}.` : "";
|
|
544
|
-
return `[tdd enforcement: ${tddMode}] Auto-create skeleton tests for source files being written
|
|
545
|
-
"When
|
|
543
|
+
return `[tdd enforcement: ${tddMode}] Auto-create skeleton tests for source files being written or edited.${TDD_NOTES[tddMode] || ""}${focusNote} ` +
|
|
544
|
+
"When the work changes code, keep the test path visible and make the next test step obvious.";
|
|
546
545
|
}
|
|
547
546
|
function flowDirective(cv, sel) {
|
|
548
547
|
const flowMode = cv?.flow_mode || (sel.flow_enforce ? "normal" : "audit");
|
|
@@ -550,14 +549,14 @@ function flowDirective(cv, sel) {
|
|
|
550
549
|
const enforceNote = sel.flow_enforce ? " TODO/FIXME extraction is active." : "";
|
|
551
550
|
const focusNote = flowFocus.length > 0 ? ` Focus rules: ${flowFocus.join(", ")}.` : "";
|
|
552
551
|
return `[flow enforcement: ${flowMode}] Development flow rules are active: write/edit operations are checked against project conventions.${enforceNote}${focusNote} ` +
|
|
553
|
-
"
|
|
552
|
+
"Stay close to the existing code patterns, naming style, and project structure.";
|
|
554
553
|
}
|
|
555
554
|
function flowTodosDirective() {
|
|
556
555
|
const pendingTodos = loadTodos().filter((t) => t.status === "pending").length;
|
|
557
556
|
if (pendingTodos === 0)
|
|
558
557
|
return null;
|
|
559
|
-
return "[vibeOS] " + pendingTodos + " extracted TODO/FIXME items are
|
|
560
|
-
"
|
|
558
|
+
return "[vibeOS] " + pendingTodos + " extracted TODO/FIXME items are waiting. " +
|
|
559
|
+
"If useful, call `todowrite` so they land in the native task list.";
|
|
561
560
|
}
|
|
562
561
|
function patternDirective(fp) {
|
|
563
562
|
const patterns = promotedProjectPatterns(fp);
|
|
@@ -586,8 +585,8 @@ function welcomeDirective() {
|
|
|
586
585
|
const active = sel.active_slot || "medium";
|
|
587
586
|
const current = currentModel || "(unknown)";
|
|
588
587
|
return "[vibeOS] Active plugin. Slot: " + active + " (" + current + "). " +
|
|
589
|
-
"Use trinity
|
|
590
|
-
"
|
|
588
|
+
"Use `trinity status` for a quick check, `trinity help` for the full command list, " +
|
|
589
|
+
"or `trinity set`, `trinity mode`, and `trinity rebuild` to move forward.";
|
|
591
590
|
}
|
|
592
591
|
function contextBudgetDirective(_input, output) {
|
|
593
592
|
const ctxBudget = estimateContextBudget(_input, output);
|
|
@@ -595,7 +594,7 @@ function contextBudgetDirective(_input, output) {
|
|
|
595
594
|
return null;
|
|
596
595
|
const severity = ctxBudget.pct > 90 ? "CRITICAL" : "WARNING";
|
|
597
596
|
return `[context budget: ${severity}] Context window is ${ctxBudget.pct}% full (~${ctxBudget.estimatedTokens} tokens). ` +
|
|
598
|
-
"
|
|
597
|
+
"Use Task subagents for heavy work, compress tool output, or start a fresh session before context gets cramped.";
|
|
599
598
|
}
|
|
600
599
|
export const onSystemTransform = async (_input, output) => {
|
|
601
600
|
if (!loadSelection().enabled)
|
|
@@ -720,12 +719,11 @@ export const onSystemTransform = async (_input, output) => {
|
|
|
720
719
|
}
|
|
721
720
|
const stressMitigationDirective = rawStress > 0.7
|
|
722
721
|
? "[stress mitigation: CRITICAL] The user's message shows very high stress indicators. " +
|
|
723
|
-
"Stay calm, structured, and thorough.
|
|
724
|
-
"
|
|
725
|
-
"This is the most important directive in your system prompt for this turn."
|
|
722
|
+
"Stay calm, structured, and thorough. Lead with the answer, keep steps explicit, and avoid playful language or overload. " +
|
|
723
|
+
"Do not mirror the user's urgency."
|
|
726
724
|
: rawStress > 0.4
|
|
727
725
|
? "[stress mitigation: elevated] The user's message has elevated stress indicators. " +
|
|
728
|
-
"
|
|
726
|
+
"Keep the response structured, readable, and lightly reassuring."
|
|
729
727
|
: null;
|
|
730
728
|
if (stressMitigationDirective) {
|
|
731
729
|
pushSystem(output, stressMitigationDirective);
|
|
@@ -738,13 +736,13 @@ export const onSystemTransform = async (_input, output) => {
|
|
|
738
736
|
const tpl = TEMPLATES[_currentTemplate] || TEMPLATES[DEFAULT_TEMPLATE];
|
|
739
737
|
let fused = tpl.directive;
|
|
740
738
|
if (sel.delegation_enforce && _controlVector?.enforcement_mode !== "relaxed") {
|
|
741
|
-
fused += "
|
|
739
|
+
fused += " Write/Edit stays blocked on brain tier. Delegate implementation to Task subagents and use parallel calls for independent work.";
|
|
742
740
|
}
|
|
743
741
|
if (sel.tdd_enforce && _controlVector?.tdd_mode !== "lazy") {
|
|
744
|
-
fused += "
|
|
742
|
+
fused += " Keep test skeletons ready for changed source files.";
|
|
745
743
|
}
|
|
746
744
|
if (sel.flow_enabled && _controlVector?.flow_mode !== "audit") {
|
|
747
|
-
fused += "
|
|
745
|
+
fused += " Stay close to existing code conventions and project patterns.";
|
|
748
746
|
}
|
|
749
747
|
pushSystem(output, fused);
|
|
750
748
|
}
|
|
@@ -768,7 +766,7 @@ export const onSystemTransform = async (_input, output) => {
|
|
|
768
766
|
if (currentRegime !== prevRegime) {
|
|
769
767
|
_prevBlackboxRegime = currentRegime;
|
|
770
768
|
pushSystem(output, "[decision engine] Resolution: " + (res.resolution || "unresolved") + " " +
|
|
771
|
-
"(" + currentRegime + "). Momentum: " + ((res.momentum || 0) > 0 ? "positive" : (res.momentum || 0) < 0 ? "negative" : "
|
|
769
|
+
"(" + currentRegime + "). Momentum: " + ((res.momentum || 0) > 0 ? "↗ positive" : (res.momentum || 0) < 0 ? "↘ negative" : "→ steady") + ".");
|
|
772
770
|
if (res.is_looping && res.loop_intervention_level && res.loop_intervention_level !== "none") {
|
|
773
771
|
const severity = res.loop_intervention_level === "escalated" ? "CRITICAL"
|
|
774
772
|
: res.loop_intervention_level === "assertive" ? "WARNING" : "NOTICE";
|
|
@@ -832,18 +830,18 @@ export const onSystemTransform = async (_input, output) => {
|
|
|
832
830
|
catch { }
|
|
833
831
|
if (!oneShot("vibeos_dashboard_instruct")) {
|
|
834
832
|
pushSystem(output, "[vibeOS dashboard display] When the trinity tool returns output starting with '[vibeOS-dashboard]', " +
|
|
835
|
-
"
|
|
833
|
+
"use the question tool to display that data in a clean, human-readable format. " +
|
|
836
834
|
"Use the question field (not the header) to show the dashboard data. " +
|
|
837
835
|
"Format it with clear sections separated by blank lines, aligned columns with spaces, " +
|
|
838
|
-
"and plain text only
|
|
836
|
+
"and plain text only. " +
|
|
839
837
|
"The header should be 'vibeOS Dashboard'. " +
|
|
840
838
|
"Include only one option in options: {label: 'Dismiss', description: ''}. " +
|
|
841
839
|
"Strip the '[vibeOS-dashboard]' marker line before displaying.");
|
|
842
840
|
}
|
|
843
841
|
if (!oneShot("vibeos_dopamine_style_" + fp)) {
|
|
844
|
-
pushSystem(output, "[tool style: dopamine] When calling the bash tool, use a short, progress-focused description " +
|
|
842
|
+
pushSystem(output, "[tool style: dopamine] When calling the bash tool, use a short, calm, progress-focused description " +
|
|
845
843
|
"that names the user-visible milestone being advanced. Combine independent bash commands into a single " +
|
|
846
|
-
"call with && or ;.
|
|
844
|
+
"call with && or ;. Keep the wording human and avoid hype or raw technical labels.");
|
|
847
845
|
}
|
|
848
846
|
}
|
|
849
847
|
catch (err) {
|
package/src/lib/hooks/footer.js
CHANGED
|
@@ -20,6 +20,20 @@ export function resolveBrand(optMode, activeSlot) {
|
|
|
20
20
|
export function resolveTierIcon(slot) {
|
|
21
21
|
return TIER_ICON[slot] || "\u26A1";
|
|
22
22
|
}
|
|
23
|
+
export function trendGlyph(trend) {
|
|
24
|
+
if (trend === "up")
|
|
25
|
+
return "↗";
|
|
26
|
+
if (trend === "down")
|
|
27
|
+
return "↘";
|
|
28
|
+
return "→";
|
|
29
|
+
}
|
|
30
|
+
export function formatSavingsPulse(amountUsd, trend) {
|
|
31
|
+
const amount = Number(amountUsd || 0);
|
|
32
|
+
if (!Number.isFinite(amount) || amount <= 0)
|
|
33
|
+
return "";
|
|
34
|
+
const arrow = trendGlyph(trend);
|
|
35
|
+
return `$${amount.toFixed(2)} saved${arrow !== "→" ? ` ${arrow}` : ""}`;
|
|
36
|
+
}
|
|
23
37
|
export function buildEnforcementTags(opts) {
|
|
24
38
|
const tags = [];
|
|
25
39
|
if (opts.bbMode === "relaxed") {
|
|
@@ -40,11 +54,13 @@ export function buildEnforcementTags(opts) {
|
|
|
40
54
|
return tags;
|
|
41
55
|
}
|
|
42
56
|
export function buildFooterLine(input) {
|
|
43
|
-
const { activeSlot, sessionSlot, providerLabel, modelName, ltTotal, vibeBrand, optMode, flashIcon, enfTags, vectorChangedSlot } = input;
|
|
57
|
+
const { activeSlot, sessionSlot, providerLabel, modelName, ltTotal, ltTrend, vibeBrand, optMode, flashIcon, enfTags, vectorChangedSlot } = input;
|
|
44
58
|
const tierIcon = resolveTierIcon(activeSlot);
|
|
45
59
|
let line = `\u2014 ${tierIcon} ${activeSlot} | ${providerLabel} | ${modelName}`;
|
|
46
60
|
if (ltTotal > 0) {
|
|
47
|
-
|
|
61
|
+
const savingsPulse = formatSavingsPulse(ltTotal, ltTrend);
|
|
62
|
+
if (savingsPulse)
|
|
63
|
+
line += ` | ${savingsPulse}`;
|
|
48
64
|
}
|
|
49
65
|
line += ` | ${vibeBrand}${flashIcon}`;
|
|
50
66
|
if (optMode && optMode !== "auto") {
|
|
@@ -3,7 +3,7 @@ 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, TRINITY_BRAIN, cacheSavePer1MInputTokens,
|
|
6
|
+
import { classify, modelCostPerTurn, isModelFree, detectContext7, isDocsTarget, shortModelName, formatUsd, _refreshModel, readConfig, resolveDisplayModelId, TRINITY_CHEAP, TRINITY_MEDIUM, TRINITY_BRAIN, cacheSavePer1MInputTokens, modelToSlotLabel, resolveExecutionIdentity, modelDisplayName, } from "../pricing.js";
|
|
7
7
|
import { latestUserIntent } from "./chat-transform.js";
|
|
8
8
|
import { loadSessionOptMode } from "../selection-manager.js";
|
|
9
9
|
import { loadOptimizationMode } from "../turn-classify.js";
|
|
@@ -530,7 +530,7 @@ export const onToolExecuteBefore = async (input, output) => {
|
|
|
530
530
|
_mutateBlockedToolArgs(t, argSources, checkPath, output);
|
|
531
531
|
if (shouldLogWarn(`${t}|protect|${checkPath}`))
|
|
532
532
|
console.error(`[vibeOS] [protection] BLOCKED direct ${t} in self-protected directory: ${checkPath}`);
|
|
533
|
-
pendingUiNote =
|
|
533
|
+
pendingUiNote = `[LOCK] Self-modification paused: ${basename(checkPath)} is in a protected project tree. Use a manual git workflow.`;
|
|
534
534
|
enforcementBlocked = true;
|
|
535
535
|
return;
|
|
536
536
|
}
|
|
@@ -544,11 +544,11 @@ export const onToolExecuteBefore = async (input, output) => {
|
|
|
544
544
|
if (costDetector.checkAnomaly(fullModelName, modelCost)) {
|
|
545
545
|
const avg = costDetector.currentAnomalyMean;
|
|
546
546
|
const ratio = avg > 0 ? (modelCost / avg).toFixed(1) : "?";
|
|
547
|
-
const msg = `Cost spike: ${shortModelName(fullModelName)} at $${modelCost.toFixed(4)}/turn — ${ratio}x
|
|
547
|
+
const msg = `Cost spike: ${shortModelName(fullModelName)} at $${modelCost.toFixed(4)}/turn — ${ratio}x above the recent average of $${avg.toFixed(4)}. Switch to \`trinity medium\` or \`trinity cheap\` to keep momentum.`;
|
|
548
548
|
if (shouldLogWarn(`${t}|cost-anomaly|${fullModelName}|${modelCost.toFixed(4)}`)) {
|
|
549
549
|
console.error(`[vibeOS] [cost-anomaly] ${msg}`);
|
|
550
550
|
}
|
|
551
|
-
pendingUiNote =
|
|
551
|
+
pendingUiNote = `[SLOW DOWN] ${msg}`;
|
|
552
552
|
enforcementBlocked = true;
|
|
553
553
|
return;
|
|
554
554
|
}
|
|
@@ -557,8 +557,7 @@ export const onToolExecuteBefore = async (input, output) => {
|
|
|
557
557
|
// Credit < 40%: non-task tool — record and nudge to step aside.
|
|
558
558
|
if (_credit < 40 && !compatibilityMode) {
|
|
559
559
|
const total = recordSaving(t, "credit<40% high-tier", _estOpus, { firstWord: _firstWord });
|
|
560
|
-
const
|
|
561
|
-
const msg = `⚠ [vibeOS] Credit: ${_credit}% — switching to medium saves ~$${_estOpus.toFixed(3)}/turn. Run \`trinity medium\`.`;
|
|
560
|
+
const msg = `[vibeOS] Credit is at ${_credit}%. Quick win: switch to medium to save about ~$${_estOpus.toFixed(3)}/turn.`;
|
|
562
561
|
if (shouldLogWarn(`${t}|credit|${_tierWord}`) && process.env.VIBEOS_DEBUG_DELEGATION === "1") {
|
|
563
562
|
console.error(`[vibeOS] [delegation] ${msg}`);
|
|
564
563
|
}
|
|
@@ -585,7 +584,7 @@ export const onToolExecuteBefore = async (input, output) => {
|
|
|
585
584
|
if (isBlocked) {
|
|
586
585
|
_mutateBlockedToolArgs(tLower, argSources, originalPath, output);
|
|
587
586
|
const total = recordSaving(t, "delegation enforced", savings, { firstWord: _firstWord });
|
|
588
|
-
pendingUiNote =
|
|
587
|
+
pendingUiNote = `[ENF] Brain-tier direct ${t} paused. Delegate via Task or switch to \`trinity medium\`.`;
|
|
589
588
|
enforcementBlocked = true;
|
|
590
589
|
if (shouldLogWarn(`${t}|enforced|${_tierWord}`))
|
|
591
590
|
console.error(`[vibeOS] [enforcement] BLOCKED direct ${t} on high tier → delegate via Task`);
|
|
@@ -594,7 +593,7 @@ export const onToolExecuteBefore = async (input, output) => {
|
|
|
594
593
|
}
|
|
595
594
|
const total = recordSaving(t, "direct edit", _estEdit, { firstWord: _firstWord });
|
|
596
595
|
if (!compatibilityMode) {
|
|
597
|
-
const msg = `[vibeOS] ${_tierWord} tier direct ${t} — save ~$${_estEdit.toFixed(3)} by delegating to Task.
|
|
596
|
+
const msg = `[vibeOS] ${_tierWord} tier direct ${t} — save about ~$${_estEdit.toFixed(3)} by delegating to Task. Try \`trinity medium\`.`;
|
|
598
597
|
if (shouldLogWarn(`${t}|direct|${_tierWord}`) && process.env.VIBEOS_DEBUG_DELEGATION === "1") {
|
|
599
598
|
console.error(`[vibeOS] [delegation] ${msg}`);
|
|
600
599
|
}
|
|
@@ -623,11 +622,11 @@ export const onToolExecuteBefore = async (input, output) => {
|
|
|
623
622
|
writeFileSync(CONTEXT7_INSTALL_FLAG, "");
|
|
624
623
|
}
|
|
625
624
|
catch { }
|
|
626
|
-
console.error(`[vibeOS]
|
|
625
|
+
console.error(`[vibeOS] Small win: install context7 MCP to save about ~$0.06/turn on docs: \`claude mcp add context7 npx @upstash/context7-mcp\``);
|
|
627
626
|
}
|
|
628
627
|
else if (!context7AlertedThisSession) {
|
|
629
628
|
context7AlertedThisSession = true;
|
|
630
|
-
console.error(`[vibeOS]
|
|
629
|
+
console.error(`[vibeOS] context7 is still off — about ~$${(missed ?? 0).toFixed(2)} in savings slipped this session.`);
|
|
631
630
|
}
|
|
632
631
|
}
|
|
633
632
|
}
|
|
@@ -637,7 +636,7 @@ export const onToolExecuteBefore = async (input, output) => {
|
|
|
637
636
|
const n = softQuotaCounts[t];
|
|
638
637
|
if (n === SOFT_QUOTA_LIMIT + 1) {
|
|
639
638
|
const total = recordSaving(t, `soft quota exceeded (limit ${SOFT_QUOTA_LIMIT})`, SAVE_EST.SOFT_QUOTA);
|
|
640
|
-
console.error(`[vibeOS] Bash usage
|
|
639
|
+
console.error(`[vibeOS] Bash usage is getting heavy (${n}/${SOFT_QUOTA_LIMIT}) — hand the next step to a Task subagent.`);
|
|
641
640
|
}
|
|
642
641
|
return;
|
|
643
642
|
}
|
|
@@ -720,6 +719,7 @@ export const onToolExecuteAfter = async (input, output) => {
|
|
|
720
719
|
providerLabel: execution.provider_label,
|
|
721
720
|
modelName: modelDisplayName(execution.model),
|
|
722
721
|
ltTotal,
|
|
722
|
+
ltTrend: sv.sesTrend,
|
|
723
723
|
vibeBrand,
|
|
724
724
|
optMode: optModeFooter,
|
|
725
725
|
flashIcon,
|
package/src/lib/trinity-tool.js
CHANGED
|
@@ -16,25 +16,25 @@ const CREDIT_MIN_OK = 40;
|
|
|
16
16
|
export function createTrinityTool(deps) {
|
|
17
17
|
return {
|
|
18
18
|
description: "Control the vibeOS plugin and active model slot. " +
|
|
19
|
-
"Use action='status' to see current state. " +
|
|
20
|
-
"Use action='enable' or 'disable' to toggle the plugin
|
|
21
|
-
"Use action='set' with slot='brain'|'medium'|'cheap' to switch model tiers " +
|
|
22
|
-
"(writes opencode.json — active immediately). " +
|
|
19
|
+
"Use action='status' to see the current state. " +
|
|
20
|
+
"Use action='enable' or 'disable' to toggle the plugin immediately. " +
|
|
21
|
+
"Use action='set' with slot='brain'|'medium'|'cheap' to switch model tiers (writes opencode.json). " +
|
|
23
22
|
"Use action='mode' with slot='vibeultrax'|'vibeqmax'|'vibemax'|'budget'|'quality'|'speed'|'longrun'|'auto'|'balanced'|'audit'|'forensic' to switch optimization mode. " +
|
|
24
23
|
"Use action='thinking' with level='full'|'brief'|'off'. " +
|
|
25
|
-
"Use action='rebuild' to
|
|
24
|
+
"Use action='rebuild' to detect available models from configured providers and reassign brain/medium/cheap slots. " +
|
|
26
25
|
"Use action='flow' with slot='on'|'off' to toggle flow enforcer, or action='flow' alone for audit. " +
|
|
27
26
|
"Use action='flow' with slot='enforce' and level='on'|'off' to toggle auto-extract TODOs. " +
|
|
28
|
-
"Use action='enforce' with slot='on'|'off' to toggle delegation enforcement
|
|
27
|
+
"Use action='enforce' with slot='on'|'off' to toggle delegation enforcement. " +
|
|
29
28
|
"Use action='tdd' with slot='on'|'off' to toggle auto-create test skeletons. " +
|
|
30
29
|
"Use action='tdd' with slot='strict' and level='on'|'off' to toggle strict failing TODO test templates. " +
|
|
31
30
|
"Use action='tdd' alone for audit. " +
|
|
32
31
|
"Use action='setup' to create a compatibility profile for first-time users. " +
|
|
33
32
|
"Use action='project' to show per-project analytics and optimization suggestions. " +
|
|
34
33
|
"Use action='patterns' to inspect learned project patterns or slot='clear' to clear them. " +
|
|
35
|
-
"Use action='guard' to
|
|
34
|
+
"Use action='guard' to keep AGENTS.md and README.md current. " +
|
|
35
|
+
"Use action='api-token' with token='<new_token>' to update the API token or token='invalidate' to disable the embedded alpha token. " +
|
|
36
36
|
"Use action='api-bootstrap-token' with token='<new_token>' to store an alpha bootstrap token and exchange it for a normal API token on alpha builds. " +
|
|
37
|
-
"Call this when the user says things like 'switch to medium', 'use cheap model', 'disable plugin', 'trinity status'.",
|
|
37
|
+
"Call this when the user says things like 'switch to medium', 'use cheap model', 'disable plugin', or 'trinity status'.",
|
|
38
38
|
args: {
|
|
39
39
|
action: deps.tool.schema.enum(["status", "enable", "disable", "set", "mode", "thinking", "flow", "tdd", "setup", "project", "patterns", "rebuild", "diagnose", "help", "enforce", "repair-state", "blackbox", "report", "target", "guard", "api-token", "api-bootstrap-token", "todo", "todo-done", "todo-sync"]).optional(),
|
|
40
40
|
slot: deps.tool.schema.enum(["brain", "medium", "cheap", "budget", "quality", "speed", "longrun", "auto", "balanced", "audit", "forensic", "vibeultrax", "vibeqmax", "vibemax", "vibelitex", "on", "off", "enforce", "strict", "preview", "apply", "clear", "savings"]).optional(),
|
|
@@ -152,7 +152,7 @@ export function createTrinityTool(deps) {
|
|
|
152
152
|
try {
|
|
153
153
|
const res = deps._latestBlackboxState || deps.getBlackboxResolution();
|
|
154
154
|
if (res && res.n_interactions > 3) {
|
|
155
|
-
const momentumIcon = res.momentum > MOMENTUM_SIGNIFICANT_THRESHOLD ? "
|
|
155
|
+
const momentumIcon = res.momentum > MOMENTUM_SIGNIFICANT_THRESHOLD ? "↗" : res.momentum > 0 ? "↑" : res.momentum < -MOMENTUM_SIGNIFICANT_THRESHOLD ? "↘" : res.momentum < 0 ? "↓" : "→";
|
|
156
156
|
const loopTag = res.is_looping ? " (loop)" : "";
|
|
157
157
|
decisionLine = `${res.resolution} ${res.sub_regime} ${momentumIcon}${loopTag}`;
|
|
158
158
|
}
|
|
@@ -177,7 +177,7 @@ export function createTrinityTool(deps) {
|
|
|
177
177
|
` Flow: ${sel.flow_enabled !== false ? "ON" : "OFF"}${sel.flow_enforce ? " (extract)" : ""}`,
|
|
178
178
|
` TDD: ${sel.tdd_enforce ? "ON" : "OFF"}${sel.tdd_strict !== false ? " strict" : ""}${sel.tdd_quality !== false ? " quality" : ""}`,
|
|
179
179
|
` Enforce: ${sel.delegation_enforce ? "ON" : "OFF"}${sel.onboarding_mode === "assist" ? " (compatibility)" : " (mandatory)"}`,
|
|
180
|
-
` Lock: ${deps._modelLocked ?
|
|
180
|
+
` Lock: ${deps._modelLocked ? `LOCK ON${lockedSlot ? ` (${lockedSlot})` : ""}${lockedModel ? ` ${lockedModel}` : ""}` : "LOCK OFF"}`,
|
|
181
181
|
` Compatibility: ${onboardingMode === "assist" ? "ASSIST (soft defaults, progressive activation)" : "STRICT (full guardrails)"}`,
|
|
182
182
|
`|`,
|
|
183
183
|
`All-time savings:`,
|
|
@@ -351,7 +351,7 @@ export function createTrinityTool(deps) {
|
|
|
351
351
|
if (ok)
|
|
352
352
|
deps.writeSelection("onboarding_mode", "strict");
|
|
353
353
|
return ok
|
|
354
|
-
?
|
|
354
|
+
? `Delegation enforcement ENABLED \u2014 direct writes/edits are blocked on brain tier`
|
|
355
355
|
: `\u274c Failed to write model-tiers.json`;
|
|
356
356
|
}
|
|
357
357
|
const sel = deps.loadSelection();
|
|
@@ -365,14 +365,14 @@ export function createTrinityTool(deps) {
|
|
|
365
365
|
deps._lockedSlot = lockSlot;
|
|
366
366
|
deps._lockedModel = lockModel;
|
|
367
367
|
console.error(`[vibeOS] model LOCKED \u2014 ${lockModel} (${deps.currentTier}) will not auto-reconcile with config`);
|
|
368
|
-
return
|
|
368
|
+
return `LOCK ON \u2014 ${lockModel} will not change unless you force with \`trinity set\` or \`trinity lock off\`.`;
|
|
369
369
|
}
|
|
370
370
|
if (slot === "off") {
|
|
371
371
|
deps._modelLocked = false;
|
|
372
372
|
deps._lockedSlot = null;
|
|
373
373
|
deps._lockedModel = null;
|
|
374
374
|
console.error(`[vibeOS] model UNLOCKED \u2014 auto-reconcile re-enabled`);
|
|
375
|
-
return
|
|
375
|
+
return `LOCK OFF \u2014 will auto-follow OpenCode config changes.`;
|
|
376
376
|
}
|
|
377
377
|
return `\u{1F512} Model lock: ${deps._modelLocked ? "ON (fixed per session)" : "OFF (follows config)"}\nUse \`trinity lock on\` or \`trinity lock off\` to toggle.\nLock is per-session (resets on restart).`;
|
|
378
378
|
}
|
|
@@ -587,12 +587,12 @@ export function createTrinityTool(deps) {
|
|
|
587
587
|
suggestions.push(`\ud83d\udca1 Credit at ${credit}% \u2014 switch to medium/cheap slot with \`trinity medium\``);
|
|
588
588
|
}
|
|
589
589
|
if (suggestions.length > 0) {
|
|
590
|
-
lines.push(`\
|
|
590
|
+
lines.push(`\nSmall wins:`);
|
|
591
591
|
for (const s of suggestions)
|
|
592
592
|
lines.push(` ${s}`);
|
|
593
593
|
}
|
|
594
594
|
else {
|
|
595
|
-
lines.push(`\n\u2705 No optimization suggestions \u2014 looking good
|
|
595
|
+
lines.push(`\n\u2705 No optimization suggestions \u2014 looking good.`);
|
|
596
596
|
}
|
|
597
597
|
lines.push(`\n${L.repeat(40)}`);
|
|
598
598
|
lines.push(`Run \`trinity help\` for all commands | \`research-audit\` for deep fetch analysis`);
|