@pellux/goodvibes-tui 0.20.3 → 0.22.0

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.
Files changed (142) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/README.md +23 -2
  3. package/docs/foundation-artifacts/operator-contract.json +78 -1
  4. package/package.json +4 -2
  5. package/src/audio/spoken-turn-controller.ts +31 -1
  6. package/src/audio/spoken-turn-wiring.ts +26 -4
  7. package/src/cli/bundle-command.ts +1 -1
  8. package/src/cli/completions/generate.ts +658 -0
  9. package/src/cli/config-overrides.ts +68 -0
  10. package/src/cli/entrypoint.ts +6 -0
  11. package/src/cli/help.ts +4 -2
  12. package/src/cli/management-commands.ts +1 -1
  13. package/src/cli/management.ts +1 -8
  14. package/src/cli/parser.ts +31 -18
  15. package/src/cli/service-command.ts +1 -1
  16. package/src/cli/surface-command.ts +1 -1
  17. package/src/cli/tui-startup.ts +72 -10
  18. package/src/cli/types.ts +14 -3
  19. package/src/cli-flags.ts +1 -0
  20. package/src/config/atomic-write.ts +70 -0
  21. package/src/config/goodvibes-home-audit.ts +2 -0
  22. package/src/config/read-versioned.ts +115 -0
  23. package/src/core/context-auto-compact.ts +77 -0
  24. package/src/core/conversation-rendering.ts +49 -15
  25. package/src/core/conversation.ts +101 -16
  26. package/src/core/format-user-error.ts +192 -0
  27. package/src/core/stream-event-wiring.ts +144 -0
  28. package/src/core/stream-stall-watchdog.ts +103 -0
  29. package/src/core/system-message-router.ts +5 -1
  30. package/src/core/turn-event-wiring.ts +124 -0
  31. package/src/daemon/cli.ts +5 -0
  32. package/src/export/cost-utils.ts +71 -0
  33. package/src/export/gist-uploader.ts +136 -0
  34. package/src/input/command-registry.ts +32 -1
  35. package/src/input/commands/control-room-runtime.ts +10 -10
  36. package/src/input/commands/experience-runtime.ts +5 -4
  37. package/src/input/commands/knowledge.ts +1 -1
  38. package/src/input/commands/local-auth-runtime.ts +27 -5
  39. package/src/input/commands/local-setup.ts +4 -6
  40. package/src/input/commands/memory-product-runtime.ts +8 -6
  41. package/src/input/commands/operator-panel-runtime.ts +1 -1
  42. package/src/input/commands/operator-runtime.ts +3 -10
  43. package/src/input/commands/{integration-runtime.ts → plugin-runtime.ts} +1 -1
  44. package/src/input/commands/provider.ts +57 -3
  45. package/src/input/commands/recall-review.ts +26 -2
  46. package/src/input/commands/services-runtime.ts +2 -2
  47. package/src/input/commands/session-workflow.ts +8 -16
  48. package/src/input/commands/session.ts +70 -20
  49. package/src/input/commands/share-runtime.ts +99 -12
  50. package/src/input/commands/tts-runtime.ts +30 -4
  51. package/src/input/commands.ts +2 -4
  52. package/src/input/delete-key-policy.ts +46 -0
  53. package/src/input/feed-context-factory.ts +2 -0
  54. package/src/input/handler-feed.ts +3 -0
  55. package/src/input/handler-interactions.ts +2 -15
  56. package/src/input/handler-modal-routes.ts +128 -12
  57. package/src/input/handler-modal-token-routes.ts +22 -5
  58. package/src/input/handler-onboarding-cloudflare.ts +1 -1
  59. package/src/input/handler-onboarding.ts +73 -69
  60. package/src/input/handler-types.ts +163 -0
  61. package/src/input/handler.ts +6 -2
  62. package/src/input/input-history.ts +76 -6
  63. package/src/input/model-picker-filter.ts +265 -0
  64. package/src/input/model-picker-items.ts +208 -0
  65. package/src/input/model-picker.ts +92 -325
  66. package/src/input/onboarding/handler-onboarding-routes.ts +7 -2
  67. package/src/input/onboarding/onboarding-verification-helpers.ts +76 -0
  68. package/src/input/onboarding/onboarding-wizard-apply.ts +14 -4
  69. package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +16 -2
  70. package/src/input/onboarding/onboarding-wizard-cloudflare.ts +8 -8
  71. package/src/input/onboarding/onboarding-wizard-external-surface-extra-specs.ts +1 -1
  72. package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +2 -29
  73. package/src/input/onboarding/onboarding-wizard-rules.ts +28 -28
  74. package/src/input/onboarding/onboarding-wizard-state.ts +20 -20
  75. package/src/input/onboarding/onboarding-wizard-steps.ts +24 -25
  76. package/src/input/onboarding/onboarding-wizard-types.ts +145 -3
  77. package/src/input/onboarding/onboarding-wizard-validation.ts +77 -0
  78. package/src/input/onboarding/onboarding-wizard.ts +3 -3
  79. package/src/input/settings-modal-behavior.ts +5 -0
  80. package/src/input/settings-modal-data.ts +378 -0
  81. package/src/input/settings-modal-mutations.ts +157 -0
  82. package/src/input/settings-modal-reset.ts +154 -0
  83. package/src/input/settings-modal.ts +236 -232
  84. package/src/main.ts +93 -85
  85. package/src/panels/agent-inspector-panel.ts +120 -18
  86. package/src/panels/agent-inspector-shared.ts +29 -0
  87. package/src/panels/builtin/agent.ts +4 -1
  88. package/src/panels/builtin/development.ts +5 -1
  89. package/src/panels/builtin/knowledge.ts +14 -13
  90. package/src/panels/builtin/operations.ts +22 -1
  91. package/src/panels/builtin/shared.ts +7 -0
  92. package/src/panels/cockpit-panel.ts +123 -3
  93. package/src/panels/cockpit-read-model.ts +232 -0
  94. package/src/panels/confirm-state.ts +27 -12
  95. package/src/panels/cost-tracker-panel.ts +23 -67
  96. package/src/panels/eval-panel.ts +10 -9
  97. package/src/panels/index.ts +1 -1
  98. package/src/panels/knowledge-graph-panel.ts +84 -0
  99. package/src/panels/local-auth-panel.ts +124 -4
  100. package/src/panels/memory-panel.ts +370 -40
  101. package/src/panels/project-planning-panel.ts +42 -4
  102. package/src/panels/search-focus.ts +11 -5
  103. package/src/panels/session-maintenance.ts +66 -15
  104. package/src/panels/subscription-panel.ts +33 -25
  105. package/src/panels/types.ts +28 -1
  106. package/src/panels/wrfc-panel.ts +224 -41
  107. package/src/renderer/agent-detail-modal.ts +118 -13
  108. package/src/renderer/code-block.ts +10 -2
  109. package/src/renderer/compositor.ts +18 -4
  110. package/src/renderer/context-inspector.ts +1 -5
  111. package/src/renderer/context-status-hint.ts +54 -0
  112. package/src/renderer/diff.ts +94 -21
  113. package/src/renderer/markdown.ts +29 -13
  114. package/src/renderer/settings-modal-helpers.ts +1 -1
  115. package/src/renderer/settings-modal.ts +90 -10
  116. package/src/renderer/shell-surface.ts +10 -0
  117. package/src/renderer/syntax-highlighter.ts +10 -3
  118. package/src/renderer/term-caps.ts +318 -0
  119. package/src/renderer/theme.ts +158 -0
  120. package/src/renderer/tool-call.ts +12 -2
  121. package/src/renderer/ui-factory.ts +50 -6
  122. package/src/runtime/bootstrap-command-context.ts +1 -0
  123. package/src/runtime/bootstrap-command-parts.ts +18 -0
  124. package/src/runtime/bootstrap-core.ts +145 -13
  125. package/src/runtime/bootstrap-shell.ts +11 -0
  126. package/src/runtime/bootstrap.ts +9 -0
  127. package/src/runtime/onboarding/apply.ts +4 -6
  128. package/src/runtime/onboarding/index.ts +1 -0
  129. package/src/runtime/onboarding/markers.ts +42 -49
  130. package/src/runtime/onboarding/progress.ts +148 -0
  131. package/src/runtime/onboarding/state.ts +133 -55
  132. package/src/runtime/onboarding/types.ts +20 -0
  133. package/src/runtime/services.ts +27 -1
  134. package/src/runtime/wrfc-persistence.ts +237 -0
  135. package/src/shell/blocking-input.ts +20 -5
  136. package/src/tools/wrfc-agent-guard.ts +64 -3
  137. package/src/utils/format-elapsed.ts +30 -0
  138. package/src/utils/terminal-width.ts +45 -0
  139. package/src/version.ts +1 -1
  140. package/src/work-plans/work-plan-store.ts +4 -6
  141. package/src/panels/knowledge-panel.ts +0 -345
  142. package/src/planning/project-planning-coordinator.ts +0 -543
@@ -25,6 +25,7 @@ export class SpokenTurnController {
25
25
  private readonly abortControllers = new Set<AbortController>();
26
26
  private timer: ReturnType<typeof setInterval> | null = null;
27
27
  private errorReportedForTurn = false;
28
+ private noPlayerNoticed = false;
28
29
  private readonly voiceService: Pick<VoiceService, 'synthesizeStream'>;
29
30
  private readonly configManager: Pick<ConfigManager, 'get'>;
30
31
  private readonly player: StreamingAudioPlayer;
@@ -48,9 +49,14 @@ export class SpokenTurnController {
48
49
  if (!normalized) return false;
49
50
  this.stop();
50
51
  if (!this.player.available) {
51
- this.notify?.('[TTS] Text response will continue, but live audio is unavailable. Install mpv or ffplay.');
52
+ if (!this.noPlayerNoticed) {
53
+ this.noPlayerNoticed = true;
54
+ this.notify?.('[TTS] Text response will continue, but live audio is unavailable. Install mpv or ffplay.');
55
+ }
52
56
  return false;
53
57
  }
58
+ // Reset the no-player notice if player becomes available again.
59
+ this.noPlayerNoticed = false;
54
60
  this.pendingPrompt = normalized;
55
61
  return true;
56
62
  }
@@ -169,10 +175,15 @@ export class SpokenTurnController {
169
175
  }
170
176
 
171
177
  private synthesize(text: string, turnId: string, sequence: number, signal: AbortSignal): Promise<VoiceSynthesisStreamResult> {
178
+ // tts.speed: VoiceSynthesisRequest accepts speed (number | undefined).
179
+ // No ConfigKey for tts.speed exists in the current SDK schema — pending
180
+ // SDK schema addition. Speed is not threaded from config until that key
181
+ // is added. See docs/voice-and-live-tts.md § Speed.
172
182
  return this.voiceService.synthesizeStream(readOptionalConfigString(this.configManager, 'tts.provider'), {
173
183
  text,
174
184
  voiceId: readOptionalConfigString(this.configManager, 'tts.voice'),
175
185
  format: 'mp3',
186
+ speed: readOptionalConfigNumber(this.configManager, 'tts.speed'),
176
187
  signal,
177
188
  metadata: {
178
189
  source: 'goodvibes-tui',
@@ -201,3 +212,22 @@ function readOptionalConfigString(configManager: Pick<ConfigManager, 'get'>, key
201
212
  const value = String(configManager.get(key) ?? '').trim();
202
213
  return value || undefined;
203
214
  }
215
+
216
+ /**
217
+ * readOptionalConfigNumber — reads a numeric config value by key.
218
+ *
219
+ * `tts.speed` is not yet a ConfigKey in the SDK schema. This helper accepts
220
+ * a string key and casts it, returning undefined when the value is absent,
221
+ * zero, or not a finite positive number. Once `tts.speed` is added to the
222
+ * SDK schema the cast can be removed and the key typed statically.
223
+ *
224
+ * SDK handoff note: add { key: 'tts.speed', type: 'number', default: 1,
225
+ * description: '...' } to schema-domain-core.js and `tts: { ..., speed: 1 }`
226
+ * to DEFAULT_CONFIG.tts to complete this feature.
227
+ */
228
+ function readOptionalConfigNumber(configManager: Pick<ConfigManager, 'get'>, key: string): number | undefined {
229
+ // Cast required: key is not yet a valid ConfigKey in the SDK schema.
230
+ const raw = configManager.get(key as ConfigKey);
231
+ const value = typeof raw === 'number' ? raw : parseFloat(String(raw ?? ''));
232
+ return isFinite(value) && value > 0 ? value : undefined;
233
+ }
@@ -1,6 +1,7 @@
1
1
  import type { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
2
2
  import type { UiRuntimeEvents } from '@/runtime/index.ts';
3
3
  import type { VoiceService } from '@pellux/goodvibes-sdk/platform/voice';
4
+ import type { StreamingAudioPlayer } from './player.ts';
4
5
  import { LocalStreamingAudioPlayer } from './player.ts';
5
6
  import { SpokenTurnController } from './spoken-turn-controller.ts';
6
7
 
@@ -11,23 +12,44 @@ export interface SpokenTurnRuntime {
11
12
  }
12
13
 
13
14
  export interface WireSpokenTurnRuntimeOptions {
14
- readonly voiceService: VoiceService;
15
- readonly configManager: ConfigManager;
15
+ readonly voiceService: Pick<VoiceService, 'synthesizeStream'>;
16
+ readonly configManager: Pick<ConfigManager, 'get'>;
16
17
  readonly events: UiRuntimeEvents;
17
18
  readonly notify: (message: string) => void;
19
+ /**
20
+ * Optional player factory — injected in tests to avoid spawning real
21
+ * subprocesses. Defaults to LocalStreamingAudioPlayer.
22
+ */
23
+ readonly playerFactory?: () => StreamingAudioPlayer;
18
24
  }
19
25
 
26
+ /**
27
+ * wireSpokenTurnRuntime — wires the spoken-turn pipeline against the runtime
28
+ * event bus.
29
+ *
30
+ * Always-speak mode: when `ui.voiceEnabled` is true in config, every
31
+ * TURN_SUBMITTED event arms the turn for spoken output automatically — the
32
+ * user does not need to prefix the prompt with /tts. The availability check
33
+ * inside SpokenTurnController still gates gracefully when no player is found.
34
+ */
20
35
  export function wireSpokenTurnRuntime(options: WireSpokenTurnRuntimeOptions): SpokenTurnRuntime {
36
+ const player = options.playerFactory ? options.playerFactory() : new LocalStreamingAudioPlayer();
21
37
  const controller = new SpokenTurnController({
22
38
  voiceService: options.voiceService,
23
39
  configManager: options.configManager,
24
- player: new LocalStreamingAudioPlayer(),
40
+ player,
25
41
  notify: options.notify,
26
42
  });
27
43
 
28
44
  const turns = options.events.turns;
29
45
  const unsubs = [
30
- turns.on('TURN_SUBMITTED', (event) => controller.handleTurnEvent(event)),
46
+ turns.on('TURN_SUBMITTED', (event) => {
47
+ // Always-speak mode: auto-arm when ui.voiceEnabled is set.
48
+ if (options.configManager.get('ui.voiceEnabled')) {
49
+ controller.submitNextTurn(event.prompt);
50
+ }
51
+ controller.handleTurnEvent(event);
52
+ }),
31
53
  turns.on('PREFLIGHT_FAIL', (event) => controller.handleTurnEvent(event)),
32
54
  turns.on('STREAM_DELTA', (event) => controller.handleTurnEvent(event)),
33
55
  turns.on('STREAM_END', (event) => controller.handleTurnEvent(event)),
@@ -9,7 +9,7 @@ import { getOnboardingCheckMarkerPath } from '../runtime/onboarding/index.ts';
9
9
  import { CONFIG_SCHEMA } from '../config/index.ts';
10
10
  import { SecretsManager } from '../config/secrets.ts';
11
11
  import type { ConfigKey } from '../config/index.ts';
12
- import type { CliCommandRuntime } from './management.ts';
12
+ import type { CliCommandRuntime } from './types.ts';
13
13
  import type { CliCommandOutput } from './types.ts';
14
14
  import { getPackageVersion } from './help.ts';
15
15
  import { classifyProviderSetup } from './provider-classification.ts';