@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 +11 -0
- package/README.md +9 -4
- package/docs/foundation-artifacts/operator-contract.json +1 -1
- package/package.json +2 -2
- package/src/core/orchestrator.ts +5 -1
- package/src/input/commands/services-runtime.ts +1 -0
- package/src/panels/services-panel.ts +2 -0
- package/src/runtime/bootstrap-core.ts +28 -3
- package/src/runtime/bootstrap.ts +5 -3
- package/src/runtime/onboarding/derivation.ts +1 -1
- package/src/runtime/onboarding/snapshot.ts +2 -0
- package/src/runtime/onboarding/types.ts +1 -0
- package/src/runtime/services.ts +1 -0
- package/src/version.ts +1 -1
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
|
[](https://github.com/mgd34msu/goodvibes-tui/actions/workflows/ci.yml)
|
|
6
4
|
[](https://opensource.org/licenses/MIT)
|
|
7
|
-
[](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
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pellux/goodvibes-tui",
|
|
3
|
-
"version": "0.19.
|
|
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.
|
|
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",
|
package/src/core/orchestrator.ts
CHANGED
|
@@ -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 {
|
|
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: {
|
|
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
|
-
|
|
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);
|
package/src/runtime/bootstrap.ts
CHANGED
|
@@ -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',
|
package/src/runtime/services.ts
CHANGED
|
@@ -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.
|
|
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;
|