@pellux/goodvibes-tui 1.19.4 → 1.19.5

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
@@ -4,6 +4,14 @@ All notable changes to GoodVibes TUI.
4
4
 
5
5
  ---
6
6
 
7
+ ## [1.19.5] - 2026-07-18
8
+
9
+ ### Changes
10
+
11
+ Fixed: command results no longer print the credential-scrub env-var name list ("withheld: ...") on every collapsed line — the dominant transcript noise for anyone with several API keys exported. The full detail remains in the expanded result payload.
12
+ Fixed: the encrypted secrets store can no longer be silently orphaned by key changes — key generation is race-safe, writes refuse a stale cached key (and restore a missing keyfile), and a mismatched store now reports exactly which key wrote it.
13
+ Updated: bundled platform runtime to 1.11.4.
14
+
7
15
  ## [1.19.4] - 2026-07-17
8
16
 
9
17
  ### Changes
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![CI](https://github.com/mgd34msu/goodvibes-tui/actions/workflows/ci.yml/badge.svg)](https://github.com/mgd34msu/goodvibes-tui/actions/workflows/ci.yml)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
- [![Version](https://img.shields.io/badge/version-1.19.4-blue.svg)](https://github.com/mgd34msu/goodvibes-tui)
5
+ [![Version](https://img.shields.io/badge/version-1.19.5-blue.svg)](https://github.com/mgd34msu/goodvibes-tui)
6
6
 
7
7
  A terminal-native AI coding, operations, automation, knowledge, and integration console with a typed runtime, omnichannel surfaces, structured memory/knowledge, and a raw ANSI renderer.
8
8
 
@@ -3,7 +3,7 @@
3
3
  "product": {
4
4
  "id": "goodvibes",
5
5
  "surface": "operator",
6
- "version": "1.11.3"
6
+ "version": "1.11.4"
7
7
  },
8
8
  "auth": {
9
9
  "modes": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pellux/goodvibes-tui",
3
- "version": "1.19.4",
3
+ "version": "1.19.5",
4
4
  "description": "Terminal-native GoodVibes product for coding, operations, automation, knowledge, channels, and daemon-backed control-plane workflows.",
5
5
  "type": "module",
6
6
  "main": "src/main.ts",
@@ -104,8 +104,8 @@
104
104
  "@anthropic-ai/vertex-sdk": "^0.16.0",
105
105
  "@ast-grep/napi": "^0.42.0",
106
106
  "@aws/bedrock-token-generator": "^1.1.0",
107
- "@pellux/goodvibes-sdk": "1.11.3",
108
- "@pellux/goodvibes-terminal-shell": "1.11.3",
107
+ "@pellux/goodvibes-sdk": "1.11.4",
108
+ "@pellux/goodvibes-terminal-shell": "1.11.4",
109
109
  "bash-language-server": "^5.6.0",
110
110
  "fuse.js": "^7.1.0",
111
111
  "graphql": "^16.13.2",
@@ -131,10 +131,10 @@
131
131
  "typescript": "^5.9.3"
132
132
  },
133
133
  "optionalDependencies": {
134
- "@pellux/goodvibes-tui-linux-x64": "1.19.4",
135
- "@pellux/goodvibes-tui-linux-arm64": "1.19.4",
136
- "@pellux/goodvibes-tui-darwin-x64": "1.19.4",
137
- "@pellux/goodvibes-tui-darwin-arm64": "1.19.4"
134
+ "@pellux/goodvibes-tui-linux-x64": "1.19.5",
135
+ "@pellux/goodvibes-tui-linux-arm64": "1.19.5",
136
+ "@pellux/goodvibes-tui-darwin-x64": "1.19.5",
137
+ "@pellux/goodvibes-tui-darwin-arm64": "1.19.5"
138
138
  },
139
139
  "trustedDependencies": [],
140
140
  "overrides": {
@@ -93,21 +93,12 @@ function summarizeEdit(obj: Record<string, unknown>): string | null {
93
93
  return `${verb} ${applied} edit${applied === 1 ? '' : 's'}${target}${failText}`;
94
94
  }
95
95
 
96
- /** Credential-bearing env-var names withheld from the spawn (never values). Empty when the field is absent/empty. */
97
- function withheldEnvNames(obj: Record<string, unknown>): string[] {
98
- const raw = obj.withheld_env;
99
- if (!Array.isArray(raw)) return [];
100
- return raw.filter((n): n is string => typeof n === 'string' && n.length > 0);
101
- }
102
-
103
- /** Compact "withheld: NAME, NAME, …" suffix, capped so a long scrub list doesn't dominate the collapsed line. */
104
- function withheldEnvSuffix(names: readonly string[]): string {
105
- if (names.length === 0) return '';
106
- const MAX_SHOWN = 3;
107
- const shown = names.slice(0, MAX_SHOWN).join(', ');
108
- const more = names.length > MAX_SHOWN ? `, +${names.length - MAX_SHOWN} more` : '';
109
- return ` · withheld: ${shown}${more}`;
110
- }
96
+ // The credential scrub's withheld_env report stays OUT of the collapsed line
97
+ // entirely. It withholds the same standing set of names on every spawn, so any
98
+ // per-result rendering repeats identical env-var noise all session long — the
99
+ // dominant transcript spam for anyone with several keys exported. The report
100
+ // only matters when a command fails because a needed credential was scrubbed,
101
+ // and for that case the full name list is one expand away in the raw payload.
111
102
 
112
103
  /**
113
104
  * Compact per-command exec-sandbox suffix: `sandboxed` fields are present
@@ -141,17 +132,16 @@ function summarizeExecOne(obj: Record<string, unknown>): string | null {
141
132
  const exit = obj.exit_code;
142
133
  const dur = asNumber(obj.duration_ms);
143
134
  const durText = dur !== undefined ? ` · ${formatDuration(dur)}` : '';
144
- const withheldText = withheldEnvSuffix(withheldEnvNames(obj));
145
135
  const sandboxText = sandboxSuffix(obj);
146
- if (obj.timed_out === true) return `timed out${durText}${withheldText}${sandboxText}`;
147
- if (obj.cancelled === true) return `cancelled${durText}${withheldText}${sandboxText}`;
136
+ if (obj.timed_out === true) return `timed out${durText}${sandboxText}`;
137
+ if (obj.cancelled === true) return `cancelled${durText}${sandboxText}`;
148
138
  const stdout = typeof obj.stdout === 'string' ? obj.stdout : '';
149
139
  const lineCount = stdout.length === 0
150
140
  ? 0
151
141
  : stdout.replace(/\n$/, '').split('\n').length;
152
142
  const lineText = lineCount > 0 ? ` · ${lineCount} line${lineCount === 1 ? '' : 's'}` : '';
153
143
  const code = typeof exit === 'number' ? String(exit) : '?';
154
- return `exit ${code}${durText}${lineText}${withheldText}${sandboxText}`;
144
+ return `exit ${code}${durText}${lineText}${sandboxText}`;
155
145
  }
156
146
 
157
147
  /** exec: single { cmd, exit_code, ... } or multi { commands: [...], total }. */
@@ -161,15 +151,6 @@ function summarizeExec(obj: Record<string, unknown>): string | null {
161
151
  const failed = obj.commands.filter(
162
152
  (c) => c && typeof c === 'object' && (c as Record<string, unknown>).success === false,
163
153
  ).length;
164
- // Union of withheld names across every command in the batch — the scrub
165
- // runs per-spawn, so different commands can withhold different names.
166
- const withheldAcrossCommands = new Set<string>();
167
- for (const c of obj.commands) {
168
- if (c && typeof c === 'object') {
169
- for (const name of withheldEnvNames(c as Record<string, unknown>)) withheldAcrossCommands.add(name);
170
- }
171
- }
172
- const withheldText = withheldEnvSuffix([...withheldAcrossCommands]);
173
154
  // Count sandboxed commands across the batch — a compact "N sandboxed" beats
174
155
  // repeating each command's full boundary detail on the collapsed line.
175
156
  const sandboxedCount = obj.commands.filter(
@@ -177,8 +158,8 @@ function summarizeExec(obj: Record<string, unknown>): string | null {
177
158
  ).length;
178
159
  const sandboxText = sandboxedCount > 0 ? ` · ${sandboxedCount} sandboxed` : '';
179
160
  return failed > 0
180
- ? `${total} commands · ${failed} failed${withheldText}${sandboxText}`
181
- : `${total} commands · all ok${withheldText}${sandboxText}`;
161
+ ? `${total} commands · ${failed} failed${sandboxText}`
162
+ : `${total} commands · all ok${sandboxText}`;
182
163
  }
183
164
  if ('exit_code' in obj || 'timed_out' in obj || 'cancelled' in obj) {
184
165
  return summarizeExecOne(obj);
package/src/version.ts CHANGED
@@ -6,7 +6,7 @@ import { join } from 'node:path';
6
6
  // The prebuild script updates the fallback value before compilation.
7
7
  // Uses import.meta.dir (Bun) to locate package.json relative to this file,
8
8
  // which is correct regardless of the process working directory.
9
- let _version = '1.19.4';
9
+ let _version = '1.19.5';
10
10
  try {
11
11
  const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', 'package.json'), 'utf-8'));
12
12
  // Only trust a version read from OUR OWN package.json. A Bun single-file