@pellux/goodvibes-tui 0.19.29 → 0.19.31

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,17 @@ All notable changes to GoodVibes TUI.
4
4
 
5
5
  ---
6
6
 
7
+ ## [0.19.31] — 2026-04-25
8
+
9
+ ### Changes
10
+ - 2508d632 chore: wire sdk service secret updates
11
+
12
+ ## [0.19.30] — 2026-04-25
13
+
14
+ ### Changes
15
+ - 4aeed7a9 chore: wire sdk ntfy origin correlation
16
+ - 62b9efd4 docs: remove onboarding wizard WIP notice from README
17
+
7
18
  ## [0.19.29] — 2026-04-24
8
19
 
9
20
  ### Changes
package/README.md CHANGED
@@ -1,10 +1,8 @@
1
- > **ATTENTION:** Currently updating the Onboarding Wizard - Expect problems with starting the TUI until this work is complete!
2
-
3
1
  # goodvibes-tui
4
2
 
5
3
  [![CI](https://github.com/mgd34msu/goodvibes-tui/actions/workflows/ci.yml/badge.svg)](https://github.com/mgd34msu/goodvibes-tui/actions/workflows/ci.yml)
6
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
- [![Version](https://img.shields.io/badge/version-0.19.29-blue.svg)](https://github.com/mgd34msu/goodvibes-tui)
5
+ [![Version](https://img.shields.io/badge/version-0.19.31-blue.svg)](https://github.com/mgd34msu/goodvibes-tui)
8
6
 
9
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.
10
8
 
@@ -838,7 +836,7 @@ Key commands:
838
836
  - `/profilesync`
839
837
  - `/setup transfer export|inspect|import`
840
838
 
841
- Service entries can use existing `tokenKey` fields, a SecretRef in the key field, or explicit `tokenRef` / `passwordRef` / `webhookUrlRef` / `signingSecretRef` / `publicKeyRef` fields:
839
+ Service entries can use existing `tokenKey` fields, a SecretRef in the key field, or explicit `tokenRef` / `passwordRef` / `webhookUrlRef` / `signingSecretRef` / `publicKeyRef` / `appTokenRef` fields:
842
840
 
843
841
  ```json
844
842
  {
@@ -846,11 +844,18 @@ Service entries can use existing `tokenKey` fields, a SecretRef in the key field
846
844
  "name": "slack",
847
845
  "authType": "bearer",
848
846
  "tokenKey": "SLACK_BOT_TOKEN",
847
+ "appTokenKey": "SLACK_APP_TOKEN",
849
848
  "tokenRef": {
850
849
  "source": "vaultwarden",
851
850
  "item": "GoodVibes Slack",
852
851
  "field": "password",
853
852
  "server": "https://vault.example.test"
853
+ },
854
+ "appTokenRef": {
855
+ "source": "vaultwarden",
856
+ "item": "GoodVibes Slack App",
857
+ "field": "password",
858
+ "server": "https://vault.example.test"
854
859
  }
855
860
  }
856
861
  }
@@ -3,7 +3,7 @@
3
3
  "product": {
4
4
  "id": "goodvibes",
5
5
  "surface": "operator",
6
- "version": "0.25.4"
6
+ "version": "0.25.6"
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": "0.19.29",
3
+ "version": "0.19.31",
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",
@@ -91,7 +91,7 @@
91
91
  "@anthropic-ai/vertex-sdk": "^0.16.0",
92
92
  "@ast-grep/napi": "^0.42.0",
93
93
  "@aws/bedrock-token-generator": "^1.1.0",
94
- "@pellux/goodvibes-sdk": "^0.25.4",
94
+ "@pellux/goodvibes-sdk": "^0.25.6",
95
95
  "bash-language-server": "^5.6.0",
96
96
  "fuse.js": "^7.1.0",
97
97
  "graphql": "^16.13.2",
@@ -1,3 +1,7 @@
1
1
  // Thin TUI wrapper — re-exports the SDK Orchestrator unchanged.
2
2
  // The SDK class already contains all behaviour including getSpinner().
3
- export { Orchestrator, type OrchestratorOptions } from '@pellux/goodvibes-sdk/platform/core/orchestrator';
3
+ export {
4
+ Orchestrator,
5
+ type OrchestratorOptions,
6
+ type OrchestratorUserInputOptions,
7
+ } from '@pellux/goodvibes-sdk/platform/core/orchestrator';
@@ -41,6 +41,7 @@ export function registerServicesRuntimeCommands(registry: CommandRegistry): void
41
41
  ` webhookUrl: ${inspection.hasWebhookUrl ? 'present' : 'missing'}`,
42
42
  ` signingSecret: ${inspection.hasSigningSecret ? 'present' : 'missing'}`,
43
43
  ` publicKey: ${inspection.hasPublicKey ? 'present' : 'missing'}`,
44
+ ` appToken: ${inspection.hasAppToken ? 'present' : 'missing'}`,
44
45
  ].join('\n'));
45
46
  return;
46
47
  }
@@ -195,6 +195,8 @@ export class ServicesPanel extends ScrollableListPanel<ServicePanelEntry> {
195
195
  ...buildStatusPill(inspect.hasWebhookUrl ? 'good' : 'info', inspect.hasWebhookUrl ? 'present' : 'missing'),
196
196
  [' Signing secret: ', C.label],
197
197
  ...buildStatusPill(inspect.hasSigningSecret ? 'good' : 'info', inspect.hasSigningSecret ? 'present' : 'missing'),
198
+ [' App token: ', C.label],
199
+ ...buildStatusPill(inspect.hasAppToken ? 'good' : 'info', inspect.hasAppToken ? 'present' : 'missing'),
198
200
  ]));
199
201
  if (selected.lastTest) {
200
202
  detailLines.push(buildPanelLine(width, [
@@ -11,6 +11,7 @@ import { Compositor } from '../renderer/compositor.ts';
11
11
  import type { PermissionRequestHandler } from '@pellux/goodvibes-sdk/platform/permissions/prompt';
12
12
  import type { SystemMessageRouter } from '../core/system-message-router.ts';
13
13
  import type { ConversationFollowUpItem } from '@pellux/goodvibes-sdk/platform/core/conversation-follow-ups';
14
+ import type { OrchestratorUserInputOptions } from '../core/orchestrator.ts';
14
15
  import type { ControlPlaneRecentEvent } from '@pellux/goodvibes-sdk/platform/control-plane/gateway';
15
16
  import type { MutableRuntimeState } from '@pellux/goodvibes-sdk/platform/runtime/mutable-runtime-state';
16
17
  import type { BootstrapOptions } from './context.ts';
@@ -55,12 +56,32 @@ export interface BootstrapCoreState {
55
56
  * When non-null, COMPANION_MESSAGE_RECEIVED fires a real LLM turn via
56
57
  * orchestrator.handleUserInput() instead of only appending the user message.
57
58
  */
58
- readonly orchestratorHandleUserInputRef: { value: ((text: string) => void) | null };
59
+ readonly orchestratorHandleUserInputRef: { value: ((text: string, options?: OrchestratorUserInputOptions) => void) | null };
59
60
  readonly requestRender: () => void;
60
61
  readonly setRenderRequest: (fn: () => void) => void;
61
62
  readonly runtimeSessionIdRef: { value: string };
62
63
  }
63
64
 
65
+ export type CompanionMessagePayload = Extract<SessionEvent, { type: 'COMPANION_MESSAGE_RECEIVED' }>;
66
+
67
+ export function companionMessageToOrchestratorInputOptions(
68
+ payload: CompanionMessagePayload,
69
+ ): OrchestratorUserInputOptions {
70
+ const metadata = payload.metadata;
71
+ const surface = typeof metadata?.surface === 'string' ? metadata.surface : undefined;
72
+ const topic = typeof metadata?.topic === 'string' ? metadata.topic : undefined;
73
+
74
+ return {
75
+ origin: {
76
+ source: payload.source,
77
+ messageId: payload.messageId,
78
+ ...(surface ? { surface } : {}),
79
+ ...(topic ? { topic } : {}),
80
+ ...(metadata ? { metadata } : {}),
81
+ },
82
+ };
83
+ }
84
+
64
85
  export async function initializeBootstrapCore(
65
86
  stdout: NodeJS.WriteStream,
66
87
  options: BootstrapOptions,
@@ -362,13 +383,17 @@ export async function initializeBootstrapCore(
362
383
  // The fallback (ref not yet set) adds the message to the conversation view only —
363
384
  // this path is unreachable in practice because the event bus is not connected to
364
385
  // any live HTTP traffic until after the orchestrator is wired in bootstrap.ts.
365
- const orchestratorHandleUserInputRef: { value: ((text: string) => void) | null } = { value: null };
386
+ const orchestratorHandleUserInputRef: {
387
+ value: ((text: string, options?: OrchestratorUserInputOptions) => void) | null;
388
+ } = { value: null };
366
389
  runtimeUnsubs.push(runtimeBus.on<Extract<SessionEvent, { type: 'COMPANION_MESSAGE_RECEIVED' }>>(
367
390
  'COMPANION_MESSAGE_RECEIVED',
368
391
  ({ payload }) => {
369
392
  if (orchestratorHandleUserInputRef.value) {
370
393
  // Delegate to the orchestrator: adds user message + fires a real LLM turn.
371
- orchestratorHandleUserInputRef.value(payload.body);
394
+ // Preserve surface origin metadata so the SDK can correlate replies back
395
+ // to the originating external channel, including ntfy chat topics.
396
+ orchestratorHandleUserInputRef.value(payload.body, companionMessageToOrchestratorInputOptions(payload));
372
397
  } else {
373
398
  // Fallback: render the user message immediately (orchestrator not yet ready).
374
399
  conversation.addUserMessage(payload.body);
@@ -11,7 +11,7 @@
11
11
  */
12
12
  import { join } from 'node:path';
13
13
  import net from 'node:net';
14
- import { Orchestrator } from '../core/orchestrator.ts';
14
+ import { Orchestrator, type OrchestratorUserInputOptions } from '../core/orchestrator.ts';
15
15
  import { AcpManager } from '@pellux/goodvibes-sdk/platform/acp/manager';
16
16
  import { getTierPromptSupplement, getTierForContextWindow } from '@pellux/goodvibes-sdk/platform/providers/tier-prompts';
17
17
  import { logger } from '@pellux/goodvibes-sdk/platform/utils/logger';
@@ -195,8 +195,10 @@ export async function bootstrapRuntime(
195
195
  return supplement ? runtime.systemPrompt + '\n\n' + supplement : runtime.systemPrompt;
196
196
  },
197
197
  hookDispatcher,
198
+ flagManager: services.featureFlags,
198
199
  requestRender: () => orchestratorRefs.requestRender(),
199
200
  runtimeBus,
201
+ sessionId: runtime.sessionId,
200
202
  services: {
201
203
  agentManager: services.agentManager,
202
204
  wrfcController: services.wrfcController,
@@ -204,8 +206,8 @@ export async function bootstrapRuntime(
204
206
  });
205
207
  conversationFollowUpRef.value = (item) => orchestrator.enqueueConversationFollowUp(item);
206
208
  // Wire orchestratorHandleUserInputRef so COMPANION_MESSAGE_RECEIVED fires a real LLM turn.
207
- orchestratorHandleUserInputRef.value = (text: string) => {
208
- orchestrator.handleUserInput(text).catch((err: unknown) => {
209
+ orchestratorHandleUserInputRef.value = (text: string, options?: OrchestratorUserInputOptions) => {
210
+ orchestrator.handleUserInput(text, undefined, options).catch((err: unknown) => {
209
211
  logger.debug('companion handleUserInput safety catch', { error: String(err) });
210
212
  });
211
213
  };
@@ -211,7 +211,7 @@ function hasRemoteDeviceAccess(snapshot: OnboardingSnapshotState): boolean {
211
211
  function hasWebhookOrEventIngress(snapshot: OnboardingSnapshotState): boolean {
212
212
  return snapshot.bindSettings.httpListenerEnabled
213
213
  || hasInboundEventSurface(snapshot)
214
- || snapshot.services.services.some((service) => service.hasWebhookUrl || service.hasSigningSecret || service.hasPublicKey);
214
+ || snapshot.services.services.some((service) => service.hasWebhookUrl || service.hasSigningSecret || service.hasPublicKey || service.hasAppToken);
215
215
  }
216
216
 
217
217
  function getProviderIdentityIds(snapshot: OnboardingSnapshotState): Set<string> {
@@ -122,6 +122,7 @@ async function buildServicesSnapshot(
122
122
  hasWebhookUrl: inspection?.hasWebhookUrl ?? false,
123
123
  hasSigningSecret: inspection?.hasSigningSecret ?? false,
124
124
  hasPublicKey: inspection?.hasPublicKey ?? false,
125
+ hasAppToken: inspection?.hasAppToken ?? false,
125
126
  } satisfies OnboardingServiceState,
126
127
  issue: null,
127
128
  };
@@ -139,6 +140,7 @@ async function buildServicesSnapshot(
139
140
  hasWebhookUrl: false,
140
141
  hasSigningSecret: false,
141
142
  hasPublicKey: false,
143
+ hasAppToken: false,
142
144
  } satisfies OnboardingServiceState,
143
145
  issue: {
144
146
  area: 'services',
@@ -75,6 +75,7 @@ export interface OnboardingServiceState {
75
75
  readonly hasWebhookUrl: boolean;
76
76
  readonly hasSigningSecret: boolean;
77
77
  readonly hasPublicKey: boolean;
78
+ readonly hasAppToken: boolean;
78
79
  }
79
80
 
80
81
  export interface OnboardingServicesSnapshot {
@@ -417,6 +417,7 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
417
417
  const projectIndex = new ProjectIndex(workingDirectory);
418
418
  const channelDeliveryRouter = new ChannelDeliveryRouter({
419
419
  configManager,
420
+ secretsManager,
420
421
  serviceRegistry,
421
422
  artifactStore,
422
423
  });
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 = '0.19.29';
9
+ let _version = '0.19.31';
10
10
  try {
11
11
  const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', 'package.json'), 'utf-8'));
12
12
  _version = pkg.version ?? _version;