vibeostheog 0.25.54 → 0.25.55

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 CHANGED
@@ -1,3 +1,50 @@
1
+ ## 0.25.55
2
+ - fix: persist cascade depth from backend route so footer shows cascade icon (#369)
3
+ - fix: make the cascade real — canonical blackbox records, live audit trail, durable bridges (#366)
4
+ - fix: stop config.update/opencode.json mid-turn writes that abort OpenCode turns (#365)
5
+ - fix: stop mid-turn opencode.json writes that abort OpenCode turns (#357)
6
+ - fix: stop vibeultrax from over-triggering stall recovery (#354)
7
+ - fix: clean up legacy config stubs before turns (#353)
8
+ - fix: unify vibe primary agent topology (#352)
9
+ - fix: add tool-call loop circuit-breaker to stop runaway bash poll loops (#350)
10
+ - fix: remove VIBEOS_API_DISABLED=true persistence from disk (#348)
11
+ - fix: allow explicit setting of embedded API token (#347)
12
+ - fix: deploy script never overwrites VIBEOS_HOME/.env.production (#346)
13
+ - fix: api hot-path deadline + blackbox state consolidation + spec contract (#345)
14
+ - fix: persist cascade depth/root to blackbox state across turns (#343)
15
+ - fix: prevent stale .js shadowing and cascade de-escalation (#342)
16
+ - fix: consolidate runtime OpenCode home resolution to single ~/.opencode (#338)
17
+ - fix: single source of truth for the footer — kill the "always cut" fallback (#331)
18
+ - fix: force pipeline repair when manual mode pipeline is collapsed (#330)
19
+ - fix: force pipeline repair when manual mode pipeline is collapsed
20
+ - fix: footer bail-out + pipeline collapse (#329)
21
+ - refactor: split maintainability boundaries into focused modules (#358)
22
+ - refactor: consolidate safeJsonParse to one canonical helper (#356)
23
+ - chore: untrack internal-only MD files from repo (#351)
24
+ fix cascade: complex prompts at any confidence route to brain tier (#368)
25
+ Fix local loop authority (#367)
26
+ Fix mega test loader paths and spec claims (#364)
27
+ Narrow shell loop guard to polling (#363)
28
+ Suppress repeated LOOPING notices (#362)
29
+ Make LOOPING sticky across authoritative state writes (#361)
30
+ Show cascade escalation labels (#360)
31
+ Unify session events under VIBEOS_HOME (#359)
32
+ Fix/api client consolidation (#355)
33
+ Migrate test suite to TS and fix buildFooterAlert null crash (#344)
34
+ Migrate repo to TS-only sources (#341)
35
+ Codex/fix cascade authority (#340)
36
+ Consolidate vibeOS skill install (#339)
37
+ Bind vibe tiers to live OpenCode agents (#337)
38
+ Fix VibeUltraX cheap-tier default via the OpenCode dropdown lever (#336)
39
+ Fix VibeUltraX cascade with tier subagents (#335)
40
+ Fix VibeUltraX live root state (#334)
41
+ Fix VibeUltraX cascade routing (#333)
42
+ Fix live control vector persistence (#332)
43
+ Revert "fix: force pipeline repair when manual mode pipeline is collapsed"
44
+ Fix blackbox session-id fragmentation freezing all sessions at INIT (#328)
45
+ Fix footer runtime probe path (#327)
46
+
47
+
1
48
  ## 0.25.53
2
49
  - fix: add project/blackbox cards to home summary, fix template source detection, expand recommendations (#302)
3
50
  Merge release v0.25.52 into master
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
- # vibeOS for OpenCode -- Innocence v0.25.52
1
+ # vibeOS for OpenCode -- Innocence v0.25.55
2
2
 
3
3
  A quality-first control plane for AI-assisted coding.
4
4
 
5
5
  When AI coding is cheap, you use more of it. That is the upside of the current moment -- the marginal cost of a code suggestion has collapsed. But volume does not equal quality. The more you delegate to AI, the more often a mediocre suggestion slips through: a half-implemented fix, a fabricated API call, a test that passes only because the assertions are stubs. The quality problem gets worse as the cost problem gets better. vibeOS exists to solve the quality problem. The savings are a side effect.
6
6
 
7
- OpenCode Desktop gives you access to the most capable language models ever created -- Opus, Sonnet, DeepSeek v4 Pro -- but running them on every single turn adds up fast. More importantly, routing every turn through the most expensive model does not guarantee the best output. A cheap model proposing, a mid-tier model reviewing, and a top-tier model polishing often produces better results than a single expensive model guessing alone. vibeOS makes that routing decision automatically, on every turn, based on what you are actually doing.
7
+ OpenCode Desktop gives you access to the most capable language models ever created -- Opus, Sonnet, DeepSeek v4 Pro -- but running them on every single turn adds up fast. More importantly, routing every turn through the most expensive model does not guarantee the best output. vibeOS keeps one primary `vibe` agent in the dropdown, lets same-provider tier changes swap in-thread, and delegates cross-provider tier work to tier subagents without rewriting the active agent every turn.
8
8
 
9
9
  The real system is smaller than the feature list makes it sound:
10
10
 
@@ -33,17 +33,17 @@ The lie detector flags when the assistant claims success without evidence. The l
33
33
 
34
34
  ## The Cascade Engine
35
35
 
36
- vibeOS uses a three-tier cascade to route every turn through the cheapest model that can produce a quality result.
36
+ vibeOS uses a single primary `vibe` agent plus three tier subagents to route every turn through the cheapest model that can produce a quality result.
37
37
 
38
38
  ### How It Works
39
39
 
40
- 1. **Cheap proposal** -- Your configured cheap slot generates an initial response (e.g., a local Ollama model via `vibe set cheap magiccoder:7b`, or any API model).
41
- 2. **Flash review** -- A mid-tier model (DeepSeek v4 Flash) critiques and refines the proposal.
42
- 3. **Pro polish** -- The brain-tier model (DeepSeek v4 Pro) applies a final quality pass on complex sections.
40
+ 1. **Cheap proposal** -- The unified `vibe` primary starts on your configured cheap slot (e.g., a local Ollama model via `vibe set cheap magiccoder:7b`, or any API model).
41
+ 2. **Flash review** -- The medium tier runs as a subagent and critiques/refines the proposal without changing the dropdown agent.
42
+ 3. **Pro polish** -- The brain tier runs as a subagent on complex sections; cross-provider work delegates there instead of flipping the active agent.
43
43
 
44
44
  Not every turn goes through all three stages. The cascade router estimates input difficulty and routes simple queries directly to the cheap tier. Complex reasoning, multi-file edits, and ambiguous instructions escalate to medium or brain. The router learns from session outcomes and calibrates its thresholds over time.
45
45
 
46
- Benchmarked at **107% of raw brain quality at 58% of cost**. Local inference is free; only the Flash and Pro stages incur API costs. This is the first routing strategy that Pareto-dominates the raw brain baseline -- better quality, lower cost.
46
+ Benchmarked at **107% of raw brain quality at 58% of cost**. Local inference is free; only the Flash and Pro stages incur API costs. This is the first routing strategy that Pareto-dominates the raw brain baseline -- better quality, lower cost, without per-turn agent churn.
47
47
 
48
48
  ### Research Foundation
49
49
 
@@ -68,7 +68,7 @@ A real-time stress scoring pipeline analyzes user messages for frustration signa
68
68
 
69
69
  ### Pattern Learner
70
70
 
71
- Per-project friction and routine tracking. The learner watches repeated tool failures, recovery loops, and stable workflows, then stores the result locally first. Cross-project hints are merged later into `global-learning.json` so the client can stay small while still learning.
71
+ Per-project friction and routine tracking. The learner watches repeated tool failures, recovery loops, and stable workflows, then stores the result locally first. Cross-project hints are merged later into `VIBEOS_HOME/global-learning.json` so the client can stay small while still learning.
72
72
 
73
73
  ### Context Compression
74
74
 
@@ -107,7 +107,7 @@ The smart cache predicts whether a tool query will hit scratchpad cache before e
107
107
 
108
108
  The prediction engine (`predictCacheHit`) computes a confidence score and returns whether caching is worthwhile, estimated savings, and the most similar cached entries. Per-tool hit rates are tracked with exponential decay (DECAY = 0.9) so recent performance matters more than historical averages.
109
109
 
110
- Cache state persists across sessions in `~/.claude/global-learning.json` with a 7-day TTL eviction. The prediction results feed into the delegation enforcer's cost calculations and appear in the live footer savings display.
110
+ Cache state persists across sessions in `VIBEOS_HOME/global-learning.json` with a 7-day TTL eviction. The prediction results feed into the delegation enforcer's cost calculations and appear in the live footer savings display.
111
111
 
112
112
  ### Pivot and Counter-Pivot
113
113
 
@@ -157,13 +157,13 @@ DeepSeek Chat costs $0/turn when routed through the Direct DeepSeek provider (no
157
157
 
158
158
  | Policy | Quality vs Brain | Cost vs Brain | Savings | Method |
159
159
  |--------|-----------------|--------------|---------|--------|
160
- | VibeUltraX | 107% | 0.58x | 42% | cheap -> medium -> brain cascade |
160
+ | VibeUltraX | 107% | 0.58x | 42% | vibe primary + tier subagents |
161
161
  | VibeQMaX | ~100% | 0.50x | 50% | same model, framework optimizations |
162
162
  | Raw Brain | 100% | 1.00x | - | baseline |
163
163
  | VibeMaX | ~75% | 0.18x | 82% | trained cascade (conservative escalate) |
164
164
  | Budget | ~40% | 0.00x | 100% | direct routing |
165
165
 
166
- **VibeUltraX** -- Default mode. Cheap slot proposes, medium reviews, brain refines. 107% quality at 58% cost.
166
+ **VibeUltraX** -- Default mode. The unified `vibe` primary starts on cheap, medium and brain run as subagents, and same-provider escalations stay in-thread. 107% quality at 58% cost.
167
167
 
168
168
  **VibeQMaX** -- Routes strategic turns through v4 Pro with full thinking, strict enforcement, strict flow checks, and quality TDD. Write/edit delegated per enforcement rules. Blended cost ~$0.00029/turn (50% of brain baseline).
169
169
 
@@ -177,7 +177,7 @@ DeepSeek Chat costs $0/turn when routed through the Direct DeepSeek provider (no
177
177
  |------|-------|----------|-------------|------|-----|
178
178
  | Raw Brain | v4 Pro | full | - | - | - |
179
179
  | VibeQMaX | v4 Pro | full | strict | strict | quality |
180
- | VibeUltraX | cascade (cheap->medium->brain) | auto | auto | auto | auto |
180
+ | VibeUltraX | vibe primary + tier subagents | auto | auto | auto | auto |
181
181
  | VibeMaX | v4 Flash (auto-escalate) | auto | auto | auto | auto |
182
182
  | Speed | v4 Flash | off | relaxed | audit | lazy |
183
183
  | Budget | DeepSeek Chat | off | relaxed | audit | lazy |
@@ -201,7 +201,7 @@ Stress > 1.5 escalates any regime to quality mode regardless of the above mappin
201
201
  | Delegation enforcement | Blocks write/edit on brain tier, routes to cheaper tiers transparently |
202
202
  | Live savings footer | Tier, provider, model name, total savings, mode -- one line of reassurance |
203
203
  | Web dashboard | Session-first SolidJS SPA with executive Home summary, session actions, per-session templates, polling refresh for model split, savings, session history, controls |
204
- | Trinity runtime | Update tier slots through the native OpenCode config path, change optimization mode, toggle subsystems live |
204
+ | Trinity runtime | Update tier slots and keep the unified vibe primary plus tier subagents synced through the native OpenCode config path, change optimization mode, toggle subsystems live |
205
205
  | Flow enforcer | Pattern-rule checks on write/edit. Extracts TODO/FIXME into append-only queue. |
206
206
  | TDD enforcer | Auto-creates test skeletons for changed source. Strict mode fails TODO tests. |
207
207
  | Pattern learner | Tracks recurring struggle/routine patterns per project, cross-project too |
@@ -222,7 +222,7 @@ Stress > 1.5 escalates any regime to quality mode regardless of the above mappin
222
222
  | Claim verification | Scans assistant output for made-up references, validates against codebase |
223
223
  | Token compression | Web fetch output stripped to 30% of original size -- verbose lines, bullet prefixes, and blank lines collapsed. Tool output history compressed to cold-storage references after the hot window (last 10 messages). Project memory condensed to single-line directives for system prompts. |
224
224
  | Rotation memory | Scratchpad files age through a four-stage lifecycle: fresh (< 5 min, full content), warm (5 min - 24 hr, 500-char summary), cold (24 - 48 hr, 200-char summary), expired (> 48 hr, deleted). Rotation runs opportunistically on every tool execution, throttled to once per minute. Cache hits degrade gracefully over time instead of failing abruptly. |
225
- | Smart cache | Predicts whether a tool query will hit scratchpad cache using composite similarity scoring (Jaccard + cosine bigram + weighted keyword overlap). Per-tool hit rates tracked with exponential decay. Estimated savings calculated and displayed in the live footer. Cache entries persisted across sessions via global-learning.json with 7-day TTL eviction. |
225
+ | Smart cache | Predicts whether a tool query will hit scratchpad cache using composite similarity scoring (Jaccard + cosine bigram + weighted keyword overlap). Per-tool hit rates tracked with exponential decay. Estimated savings calculated and displayed in the live footer. Cache entries persisted across sessions via `VIBEOS_HOME/global-learning.json` with 7-day TTL eviction. |
226
226
  | Pivot / counter-pivot | Detects when you switch topics mid-session (forward pivot) and when you return to a previously abandoned workflow (counter-pivot). Forward pivots snapshot the old workflow context and downgrade to budget mode. Counter-pivots restore files, decisions, blockers, and code snippets from cached workflow snapshots into the system prompt. |
227
227
  | Deferred reports | saveReport deferred to setTimeout to avoid blocking tool output |
228
228
  | Stress gauge footer | Live indicator in footer -- ▁▂▃▅▆█ (none/minimal/calm/elevated/high/critical) |
@@ -302,9 +302,9 @@ vibeOS hooks into OpenCode Desktop through 8 extension points:
302
302
  | experimental.session.compacting | Preserves savings state |
303
303
  | shell.env | Injects OPENCODE_MODEL_TIER and OPENCODE_MODEL |
304
304
 
305
- ### State Files (~/.claude/)
305
+ ### State Files (`VIBEOS_HOME/`)
306
306
 
307
- The plugin persists state to ~/.claude/ for cross-session continuity:
307
+ The plugin persists state to `VIBEOS_HOME/` for cross-session continuity:
308
308
 
309
309
  - **delegation-state.json** -- Sessions, warns, cache hits, lifetime totals
310
310
  - **model-tiers.json** -- Brain/medium/cheap model IDs
@@ -406,6 +406,19 @@ The footer is the primary status line, appended to every assistant response. It
406
406
  | ⟡ medium | Active slot changed to medium this turn |
407
407
  | ⟡ brain | Active slot changed to brain this turn |
408
408
 
409
+ #### Alert Tags
410
+
411
+ The alert is part of the one footer (it is **not** a separate line). When present it renders
412
+ after the enforcement tags and before the stress gauge. Multiple alerts join with ` · `.
413
+ This table is the single source of truth — `buildFooterAlert()` must match it exactly.
414
+
415
+ | Alert | Trigger |
416
+ |-------|---------|
417
+ | ⚠ api degraded | API latency is degraded / the backend is unhealthy this turn |
418
+ | ⚠ switch pending | A tier switch is deferred and will apply at the next turn boundary |
419
+ | ⚠ model drift | The live model is outside the cascade tiers and differs from the expected slot model |
420
+ | ⚠ model unreachable | The last model call failed with a network error (EHOSTUNREACH / ENOTFOUND / ETIMEDOUT) |
421
+
409
422
  **Segments (left to right):**
410
423
 
411
424
  | Segment | Format | Example | Meaning |
@@ -418,6 +431,7 @@ The footer is the primary status line, appended to every assistant response. It
418
431
  | Brand + mode label | VibeBrand . modeLabel | VibeUltraX . Quality | Requested mode + regime-derived label |
419
432
  | Cascade icon | >>> or >> | >>> | VibeUltraX cascade depth >= 3 |
420
433
  | Enforcement tags | guarded, flow steady, tests live | guarded | Guard state summary |
434
+ | Alert tags | ⚠ alert · ⚠ alert | ⚠ model drift | Live status alerts (see Alert Tags) |
421
435
  | Stress gauge | gaugeChar | _ | Current stress level |
422
436
  | Vector pulse | slot | cheap | Active slot changed this turn |
423
437
 
package/bin/setup.js CHANGED
@@ -1,47 +1,153 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ // src/bin/setup.ts
3
4
  import { execSync } from "node:child_process";
4
- import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
5
- import { dirname, resolve } from "node:path";
5
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2, mkdirSync as mkdirSync2, renameSync as renameSync2 } from "node:fs";
6
+ import { dirname as dirname2, resolve } from "node:path";
6
7
  import { fileURLToPath } from "node:url";
7
- import { resolveOpenCodeHome, resolveOpenCodeHomes } from "../scripts/lib/opencode-homes.mjs";
8
8
 
9
- const __dirname = dirname(fileURLToPath(import.meta.url));
10
- const root = resolve(__dirname, "..");
11
- const args = process.argv.slice(2);
12
- const command = args.find(a => !a.startsWith("-")) ?? "setup";
13
- const isInstallCommand = command === "setup" || command === "set";
14
- const isProject = args.includes("--project");
15
- const isYes = args.includes("--yes") || args.includes("-y");
9
+ // scripts/lib/opencode-homes.mjs
10
+ import { join } from "node:path";
11
+ import { homedir } from "node:os";
12
+ function resolveOpenCodeHomes({ home = homedir() } = {}) {
13
+ const override = process.env.VIBEOS_OPENCODE_HOME;
14
+ if (override) return [override];
15
+ return [join(home, ".opencode")];
16
+ }
17
+ function resolveOpenCodeHome(opts = {}) {
18
+ return resolveOpenCodeHomes(opts)[0];
19
+ }
16
20
 
21
+ // scripts/lib/vibe-tier-agents.mjs
22
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync } from "node:fs";
23
+ import { dirname, join as join2 } from "node:path";
24
+ import { homedir as homedir2 } from "node:os";
25
+ var VIBE_TIER_AGENT_BY_SLOT = {
26
+ cheap: "vibe-cheap",
27
+ medium: "vibe-medium",
28
+ brain: "vibe-brain"
29
+ };
30
+ var VIBE_PRIMARY_AGENT = "vibe";
31
+ function readJson(path) {
32
+ if (!existsSync(path)) return {};
33
+ try {
34
+ const raw = readFileSync(path, "utf8");
35
+ const cleaned = raw.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
36
+ const parsed = JSON.parse(cleaned);
37
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
38
+ } catch {
39
+ return {};
40
+ }
41
+ }
42
+ function readTiers(home = homedir2()) {
43
+ return readJson(join2(process.env.VIBEOS_HOME || join2(home, ".claude"), "model-tiers.json"));
44
+ }
45
+ function primaryAgent(model, existing = {}) {
46
+ return {
47
+ ...existing && typeof existing === "object" ? existing : {},
48
+ description: "VibeUltraX primary agent",
49
+ mode: "primary",
50
+ model,
51
+ permission: {
52
+ read: "allow",
53
+ edit: "allow",
54
+ glob: "allow",
55
+ grep: "allow",
56
+ list: "allow",
57
+ bash: "allow",
58
+ task: "allow",
59
+ webfetch: "allow",
60
+ websearch: "allow",
61
+ ...existing?.permission && typeof existing.permission === "object" ? existing.permission : {}
62
+ }
63
+ };
64
+ }
65
+ function tierAgent(slot, model, existing = {}) {
66
+ return {
67
+ ...existing && typeof existing === "object" ? existing : {},
68
+ description: `VibeUltraX ${slot} tier subagent`,
69
+ mode: "subagent",
70
+ model,
71
+ permission: {
72
+ read: "allow",
73
+ edit: "allow",
74
+ glob: "allow",
75
+ grep: "allow",
76
+ list: "allow",
77
+ bash: "allow",
78
+ task: "allow",
79
+ webfetch: "allow",
80
+ websearch: "allow",
81
+ ...existing?.permission && typeof existing.permission === "object" ? existing.permission : {}
82
+ }
83
+ };
84
+ }
85
+ function installVibeTierAgentsInConfig(config, tiers = readTiers()) {
86
+ if (!config || typeof config !== "object" || Array.isArray(config)) return false;
87
+ const trinity = tiers?.trinity || {};
88
+ config.$schema ||= "https://opencode.ai/config.json";
89
+ config.agent = config.agent && typeof config.agent === "object" ? config.agent : {};
90
+ let changed = false;
91
+ const primaryModel = String(trinity?.cheap?.oc || "").trim();
92
+ if (primaryModel) {
93
+ const existing = config.agent[VIBE_PRIMARY_AGENT];
94
+ const next = primaryAgent(primaryModel, existing);
95
+ if (JSON.stringify(existing || null) !== JSON.stringify(next)) {
96
+ config.agent[VIBE_PRIMARY_AGENT] = next;
97
+ changed = true;
98
+ }
99
+ if (config.default_agent !== VIBE_PRIMARY_AGENT) {
100
+ config.default_agent = VIBE_PRIMARY_AGENT;
101
+ changed = true;
102
+ }
103
+ }
104
+ for (const slot of ["cheap", "medium", "brain"]) {
105
+ const model = String(trinity?.[slot]?.oc || "").trim();
106
+ const name = VIBE_TIER_AGENT_BY_SLOT[slot];
107
+ if (!model || !name) continue;
108
+ const existing = config.agent[name];
109
+ const next = tierAgent(slot, model, existing);
110
+ if (JSON.stringify(existing || null) !== JSON.stringify(next)) {
111
+ config.agent[name] = next;
112
+ changed = true;
113
+ }
114
+ }
115
+ return changed;
116
+ }
117
+
118
+ // src/bin/setup.ts
119
+ var __dirname = dirname2(fileURLToPath(import.meta.url));
120
+ var root = resolve(__dirname, "..");
121
+ var args = process.argv.slice(2);
122
+ var command = args.find((a) => !a.startsWith("-")) ?? "setup";
123
+ var isInstallCommand = command === "setup" || command === "set";
124
+ var isProject = args.includes("--project");
125
+ var writeLine = (text = "") => {
126
+ process.stdout.write(text + "\n");
127
+ };
17
128
  if (!isInstallCommand || args.includes("--help") || args.includes("-h")) {
18
129
  console.error("Usage: npx vibeostheog set [--project]");
19
130
  console.error(" npx vibeostheog setup [--project]");
20
131
  process.exit(1);
21
132
  }
22
-
23
- console.log("");
24
- console.log("vibeOS — cost-aware delegation enforcer for OpenCode");
25
- console.log("");
26
- console.log("Installing to:");
27
- for (const h of resolveOpenCodeHomes({ cwd: process.cwd() })) console.log(" " + h);
28
- console.log("");
29
-
30
- // Deploy plugin files to ~/.config/opencode/plugins/ and register globally
31
- const deployScript = resolve(root, "scripts", "deploy.mjs");
32
- if (!existsSync(deployScript)) {
133
+ writeLine();
134
+ writeLine("vibeOS \u2014 cost-aware delegation enforcer for OpenCode");
135
+ writeLine();
136
+ writeLine("Installing to:");
137
+ for (const h of resolveOpenCodeHomes({ cwd: process.cwd() })) writeLine(" " + h);
138
+ writeLine();
139
+ var deployScript = resolve(root, "scripts", "deploy.mjs");
140
+ if (!existsSync2(deployScript)) {
33
141
  console.error("Fatal: scripts/deploy.mjs not found at", deployScript);
34
142
  process.exit(1);
35
143
  }
36
144
  execSync(`node "${deployScript}"`, { stdio: "inherit", cwd: process.cwd() });
37
-
38
- // For per-project setup, also register in project-level opencode.json
39
145
  if (isProject) {
40
146
  const configPath = resolve(process.cwd(), "opencode.json");
41
147
  let config = {};
42
- if (existsSync(configPath)) {
148
+ if (existsSync2(configPath)) {
43
149
  try {
44
- config = JSON.parse(readFileSync(configPath, "utf8"));
150
+ config = JSON.parse(readFileSync2(configPath, "utf8"));
45
151
  } catch {
46
152
  config = {};
47
153
  }
@@ -52,13 +158,13 @@ if (isProject) {
52
158
  const installHome = resolveOpenCodeHome({ cwd: process.cwd() });
53
159
  const pluginRef = resolve(installHome, "plugins", "vibeOS.js");
54
160
  config.plugin = config.plugin.filter((p) => !(typeof p === "string" && p.includes("vibeOS")));
55
- if (!config.plugin.includes(pluginRef)) {
56
- config.plugin.push(pluginRef);
57
- mkdirSync(dirname(configPath), { recursive: true });
58
- writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
59
- }
60
- console.log(`vibeOS registered in ${configPath}`);
161
+ installVibeTierAgentsInConfig(config);
162
+ if (!config.plugin.includes(pluginRef)) config.plugin.push(pluginRef);
163
+ mkdirSync2(dirname2(configPath), { recursive: true });
164
+ const tmp = `${configPath}.tmp.${process.pid}.${Date.now()}`;
165
+ writeFileSync2(tmp, JSON.stringify(config, null, 2) + "\n");
166
+ renameSync2(tmp, configPath);
167
+ writeLine(`vibeOS registered in ${configPath}`);
61
168
  }
62
-
63
- console.log("");
64
- console.log("Done. Restart OpenCode to activate the plugin.");
169
+ writeLine();
170
+ writeLine("Done. Restart OpenCode to activate the plugin.");
@@ -1 +1 @@
1
- window.__VIBEOS_DASHBOARD_BASE__ = "http://127.0.0.1:63452";
1
+ window.__VIBEOS_DASHBOARD_BASE__ = "http://127.0.0.1:53088";