@osovv/vv-opencode 1.3.2 → 1.3.3

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,11 @@
1
+ ## <small>1.3.3 (2026-08-19)</small>
2
+
3
+ ### Summary
4
+
5
+ In this release the TUI branding footer is upgraded to show a single combined version line in the sidebar — `• OpenCode <version> · vvoc vX.Y.Z` — replacing the previous standalone vvoc label in the bottom app bar. The new footer reads the OpenCode version from the running app, renders with the active theme colors, and deliberately wins the sidebar footer slot so it appears in a native-looking, always-visible location. This makes it easier for users to see at a glance which OpenCode and vvoc versions are active in a session.
6
+
7
+ * feat(tui): render combined OpenCode and vvoc versions in the sidebar footer ([ea5aa66](https://github.com/osovv/vv-opencode/commit/ea5aa66))
8
+
1
9
  ## <small>1.3.2 (2026-08-19)</small>
2
10
 
3
11
  ### Summary
package/README.md CHANGED
@@ -183,7 +183,7 @@ OpenCode is a strong, flexible base for agentic coding, but it intentionally lea
183
183
  | **WebToolsPlugin** | Register the provider-neutral `web_search` and `web_fetch` tools, return direct image/PDF attachments, and hide OpenCode's built-in web tools at runtime unless the user explicitly configured their permissions. |
184
184
  | **ContextTuiPlugin** | Add a native scrollable `/context` dialog with measured usage plus detailed observable per-tool and per-MCP schema/history estimates, explicitly marking data that OpenCode does not expose. |
185
185
  | **ToolHistoryCompactionPlugin** | Shrink the replayed conversation context non-destructively by compacting old tool outputs in the model replay (old reads to `[Read <file>, lines X-Y]`, over-budget ephemeral outputs pruned), while retaining web/search/skill knowledge results. |
186
- | **AnalyticsPlugin** | Persist per-step token and cache telemetry with vvoc/OpenCode version attribution, show a live `cache NN%` indicator next to the session prompt plus a `vvoc vX.Y.Z` label in the bottom app bar, and answer "did my cache optimizations help?" via `vvoc analytics cache-hit-rate`. |
186
+ | **AnalyticsPlugin** | Persist per-step token and cache telemetry with vvoc/OpenCode version attribution, show a live `cache NN%` indicator next to the session prompt plus a combined OpenCode/vvoc version line in the sidebar footer, and answer "did my cache optimizations help?" via `vvoc analytics cache-hit-rate`. |
187
187
 
188
188
  Workflow work items are opened with explicit intent. For implementation loops, controllers use:
189
189
 
@@ -265,7 +265,7 @@ Set `outputMaxChars` to `0` to disable pruning, or `"enabled": false` to disable
265
265
 
266
266
  `AnalyticsPlugin` records one line per completed model step — fresh input, cache read, cache write, output, reasoning, recorded cost — to `$XDG_DATA_HOME/vvoc/analytics/usage-YYYY-MM.jsonl`, attributed with the vvoc version, the OpenCode version (from session telemetry), project, provider, model, and agent. Telemetry never leaves the machine; disable collection with `"plugins": { "analytics": false }` and delete old monthly files freely.
267
267
 
268
- In the TUI you get a live `cache NN%` indicator next to the session prompt (green at 80%+, yellow at 50%+, red below, muted `n/a` before the first cache-eligible step) and a `vvoc vX.Y.Z` label in the bottom app bar. Both use append-mode host slots, so OpenCode's own footer and prompt content stay intact. The indicator is per-session and computed in memory.
268
+ In the TUI you get a live `cache NN%` indicator next to the session prompt (green at 80%+, yellow at 50%+, red below, muted `n/a` before the first cache-eligible step) and a combined footer line `• OpenCode <version> · vvoc vX.Y.Z` in the sidebar (the stock version line, extended with the vvoc version). The indicator is per-session and computed in memory.
269
269
 
270
270
  Retrospective analysis lives in the CLI:
271
271
 
@@ -1,19 +1,29 @@
1
1
  import type { JSX } from "@opentui/solid";
2
2
  import type { RGBA } from "@opentui/core";
3
3
  import type { TuiPluginApi } from "@opencode-ai/plugin/tui";
4
+ export type BrandingVersionInfo = {
5
+ opencodeVersion: string;
6
+ vvocLabel: string;
7
+ };
8
+ export type BrandingColors = {
9
+ muted: RGBA;
10
+ success: RGBA;
11
+ text: RGBA;
12
+ };
4
13
  export type BrandingDependencies = {
5
- /** Renders the label node; defaults to the muted text element. */
6
- renderLabel: (text: string, color: RGBA) => JSX.Element;
14
+ /** Renders the combined version line; defaults to the native-looking OpenCode footer line extended with the vvoc label. */
15
+ renderLabel: (info: BrandingVersionInfo, colors: BrandingColors) => JSX.Element;
7
16
  };
8
- /** The rendered label, e.g. "vvoc v1.2.11". */
17
+ /** The vvoc label text, e.g. "vvoc v1.2.11". */
9
18
  export declare function brandingFooterLabel(): string;
10
19
  /**
11
- * Registers the branding label in the "app_bottom" host slot.
20
+ * Registers the combined version line in the "sidebar_footer" host slot.
12
21
  *
13
- * app_bottom renders in append mode at the bottom of the app on every screen,
14
- * so the label coexists with any other plugin content and never displaces the
15
- * OpenCode sidebar or home footers (those slots are single_winner and owned by
16
- * OpenCode's internal footer plugins). Always on (independent of analytics
22
+ * sidebar_footer renders in single_winner mode: only the first registered
23
+ * plugin (lowest order) is displayed. OpenCode's internal footer registers
24
+ * with order 100; this plugin uses order 50 so it deterministically wins the
25
+ * slot and renders the stock-looking footer line extended with the vvoc
26
+ * version ("• OpenCode <oc> · vvoc v<x>"). Always on (independent of analytics
17
27
  * config); returns silently when the slot API is unavailable or registration
18
28
  * fails.
19
29
  */
@@ -1,20 +1,21 @@
1
- import { jsx as _jsx } from "@opentui/solid/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@opentui/solid/jsx-runtime";
2
2
  import { getPackageVersionSync } from "../../lib/package.js";
3
3
  const DEFAULT_DEPENDENCIES = {
4
- renderLabel: (text, color) => (_jsx("text", { children: _jsx("span", { style: { fg: color }, children: text }) })),
4
+ renderLabel: (info, colors) => (_jsxs("text", { fg: colors.muted, children: [_jsx("span", { style: { fg: colors.success }, children: "\u2022" }), " ", _jsx("b", { children: "Open" }), _jsx("span", { style: { fg: colors.text }, children: _jsx("b", { children: "Code" }) }), " ", _jsx("span", { children: info.opencodeVersion }), _jsxs("span", { children: [" \u00B7 ", info.vvocLabel] })] })),
5
5
  };
6
- /** The rendered label, e.g. "vvoc v1.2.11". */
6
+ /** The vvoc label text, e.g. "vvoc v1.2.11". */
7
7
  export function brandingFooterLabel() {
8
8
  return `vvoc v${getPackageVersionSync()}`;
9
9
  }
10
10
  // START_BLOCK_REGISTER_BRANDING_FOOTER
11
11
  /**
12
- * Registers the branding label in the "app_bottom" host slot.
12
+ * Registers the combined version line in the "sidebar_footer" host slot.
13
13
  *
14
- * app_bottom renders in append mode at the bottom of the app on every screen,
15
- * so the label coexists with any other plugin content and never displaces the
16
- * OpenCode sidebar or home footers (those slots are single_winner and owned by
17
- * OpenCode's internal footer plugins). Always on (independent of analytics
14
+ * sidebar_footer renders in single_winner mode: only the first registered
15
+ * plugin (lowest order) is displayed. OpenCode's internal footer registers
16
+ * with order 100; this plugin uses order 50 so it deterministically wins the
17
+ * slot and renders the stock-looking footer line extended with the vvoc
18
+ * version ("• OpenCode <oc> · vvoc v<x>"). Always on (independent of analytics
18
19
  * config); returns silently when the slot API is unavailable or registration
19
20
  * fails.
20
21
  */
@@ -26,17 +27,18 @@ export function registerBrandingFooter(api, dependencies = DEFAULT_DEPENDENCIES)
26
27
  // the SDK's TuiSlotPlugin type still types id as never; cast bridges the two.
27
28
  const plugin = {
28
29
  id: "vvoc-branding",
29
- order: 1000,
30
+ order: 50,
30
31
  slots: {
31
- app_bottom: (ctx) => {
32
- return dependencies.renderLabel(brandingFooterLabel(), ctx.theme.current.textMuted);
32
+ sidebar_footer: (ctx) => {
33
+ const theme = ctx.theme.current;
34
+ return dependencies.renderLabel({ opencodeVersion: api.app.version, vvocLabel: brandingFooterLabel() }, { muted: theme.textMuted, success: theme.success, text: theme.text });
33
35
  },
34
36
  },
35
37
  };
36
38
  api.slots.register(plugin);
37
39
  }
38
40
  catch {
39
- // Fail-soft: no label for this session.
41
+ // Fail-soft: no combined footer for this session.
40
42
  }
41
43
  }
42
44
  //# sourceMappingURL=footer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"footer.js","sourceRoot":"","sources":["../../../src/tui/branding/footer.tsx"],"names":[],"mappings":";AAwBA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAO7D,MAAM,oBAAoB,GAAyB;IACjD,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAC5B,yBACE,eAAM,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,YAAG,IAAI,GAAQ,GACpC,CACR;CACF,CAAC;AAEF,+CAA+C;AAC/C,MAAM,UAAU,mBAAmB;IACjC,OAAO,SAAS,qBAAqB,EAAE,EAAE,CAAC;AAC5C,CAAC;AAED,uCAAuC;AACvC;;;;;;;;;GASG;AACH,MAAM,UAAU,sBAAsB,CACpC,GAAiB,EACjB,eAAqC,oBAAoB;IAEzD,IAAI,OAAO,GAAG,CAAC,KAAK,EAAE,QAAQ,KAAK,UAAU;QAAE,OAAO;IACtD,IAAI,CAAC;QACH,8EAA8E;QAC9E,8EAA8E;QAC9E,MAAM,MAAM,GAAG;YACb,EAAE,EAAE,eAAe;YACnB,KAAK,EAAE,IAAI;YACX,KAAK,EAAE;gBACL,UAAU,EAAE,CAAC,GAAmB,EAAE,EAAE;oBAClC,OAAO,YAAY,CAAC,WAAW,CAAC,mBAAmB,EAAE,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;gBACtF,CAAC;aACF;SAC6D,CAAC;QACjE,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,wCAAwC;IAC1C,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"footer.js","sourceRoot":"","sources":["../../../src/tui/branding/footer.tsx"],"names":[],"mappings":";AA0BA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAkB7D,MAAM,oBAAoB,GAAyB;IACjD,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAC7B,gBAAM,EAAE,EAAE,MAAM,CAAC,KAAK,aACpB,eAAM,KAAK,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,OAAO,EAAE,uBAAU,OAAC,+BAAW,EACzD,eAAM,KAAK,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,IAAI,EAAE,YAC9B,+BAAW,GACN,EAAC,GAAG,EACX,yBAAO,IAAI,CAAC,eAAe,GAAQ,EACnC,uCAAU,IAAI,CAAC,SAAS,IAAQ,IAC3B,CACR;CACF,CAAC;AAEF,gDAAgD;AAChD,MAAM,UAAU,mBAAmB;IACjC,OAAO,SAAS,qBAAqB,EAAE,EAAE,CAAC;AAC5C,CAAC;AAED,uCAAuC;AACvC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CACpC,GAAiB,EACjB,eAAqC,oBAAoB;IAEzD,IAAI,OAAO,GAAG,CAAC,KAAK,EAAE,QAAQ,KAAK,UAAU;QAAE,OAAO;IACtD,IAAI,CAAC;QACH,8EAA8E;QAC9E,8EAA8E;QAC9E,MAAM,MAAM,GAAG;YACb,EAAE,EAAE,eAAe;YACnB,KAAK,EAAE,EAAE;YACT,KAAK,EAAE;gBACL,cAAc,EAAE,CAAC,GAAmB,EAAE,EAAE;oBACtC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;oBAChC,OAAO,YAAY,CAAC,WAAW,CAC7B,EAAE,eAAe,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,EAAE,EACtE,EAAE,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CACrE,CAAC;gBACJ,CAAC;aACF;SAC6D,CAAC;QACjE,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,kDAAkD;IACpD,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@osovv/vv-opencode",
3
- "version": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "description": "A curated, opinionated set of OpenCode plugins for spec-first, review-driven, safer agentic development.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://cdn.jsdelivr.net/npm/@osovv/vv-opencode@1.3.2/schemas/vvoc/v3.json",
3
+ "$id": "https://cdn.jsdelivr.net/npm/@osovv/vv-opencode@1.3.3/schemas/vvoc/v3.json",
4
4
  "title": "vvoc config",
5
5
  "description": "Canonical vvoc configuration document.",
6
6
  "type": "object",