@pellux/goodvibes-agent 0.1.47 → 0.1.48
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 +12 -10
- package/README.md +3 -23
- package/docs/README.md +0 -2
- package/package.json +1 -3
- package/src/cli/completion.ts +0 -1
- package/src/cli/help.ts +0 -12
- package/src/cli/management.ts +0 -6
- package/src/cli/package-verification.ts +0 -1
- package/src/cli/parser.ts +0 -4
- package/src/cli/types.ts +0 -1
- package/src/input/agent-workspace-channels.ts +214 -0
- package/src/input/agent-workspace-setup.ts +121 -0
- package/src/input/agent-workspace.ts +34 -209
- package/src/input/commands/experience-runtime.ts +2 -25
- package/src/input/commands/remote-runtime.ts +5 -5
- package/src/input/commands.ts +0 -2
- package/src/input/onboarding/onboarding-wizard-steps.ts +7 -7
- package/src/panels/provider-health-domains.ts +1 -1
- package/src/panels/remote-panel.ts +2 -2
- package/src/renderer/agent-workspace.ts +38 -10
- package/src/tools/agent-context-policy.ts +2 -2
- package/src/verification/live-verifier.ts +0 -15
- package/src/version.ts +1 -1
- package/docs/operator-capability-benchmark.md +0 -106
- package/src/cli/capabilities-command.ts +0 -173
- package/src/config/goodvibes-home-audit.ts +0 -465
- package/src/input/commands/capabilities-runtime.ts +0 -102
- package/src/operator/capability-benchmark.ts +0 -244
- package/src/operator/daemon-capability-audit.ts +0 -1534
|
@@ -5,6 +5,16 @@ import { AgentPersonaRegistry } from '../agent/persona-registry.ts';
|
|
|
5
5
|
import { AgentRoutineRegistry } from '../agent/routine-registry.ts';
|
|
6
6
|
import { AgentSkillRegistry } from '../agent/skill-registry.ts';
|
|
7
7
|
import { getAgentRuntimeProfilesRoot, listAgentRuntimeProfiles, listAgentRuntimeProfileTemplates } from '../agent/runtime-profile.ts';
|
|
8
|
+
import {
|
|
9
|
+
buildAgentWorkspaceChannels,
|
|
10
|
+
type AgentWorkspaceChannelStatus,
|
|
11
|
+
} from './agent-workspace-channels.ts';
|
|
12
|
+
import {
|
|
13
|
+
buildAgentWorkspaceSetupChecklist,
|
|
14
|
+
type AgentWorkspaceSetupChecklistItem,
|
|
15
|
+
} from './agent-workspace-setup.ts';
|
|
16
|
+
|
|
17
|
+
export type { AgentWorkspaceChannelRisk, AgentWorkspaceChannelStatus } from './agent-workspace-channels.ts';
|
|
8
18
|
|
|
9
19
|
export const AGENT_WORKSPACE_MODAL_NAME = 'agentWorkspace';
|
|
10
20
|
|
|
@@ -32,20 +42,6 @@ export interface AgentWorkspaceCategory {
|
|
|
32
42
|
|
|
33
43
|
export type AgentWorkspaceCommandDispatcher = (command: string) => void;
|
|
34
44
|
|
|
35
|
-
export type AgentWorkspaceChannelRisk = 'dm' | 'group' | 'public' | 'webhook' | 'bridge';
|
|
36
|
-
|
|
37
|
-
export interface AgentWorkspaceChannelStatus {
|
|
38
|
-
readonly id: string;
|
|
39
|
-
readonly label: string;
|
|
40
|
-
readonly enabled: boolean;
|
|
41
|
-
readonly ready: boolean;
|
|
42
|
-
readonly missingConfigCount: number;
|
|
43
|
-
readonly defaultTarget: 'configured' | 'missing' | 'not-required';
|
|
44
|
-
readonly delivery: 'disabled' | 'blocked' | 'explicit-target' | 'default-ready';
|
|
45
|
-
readonly risk: AgentWorkspaceChannelRisk;
|
|
46
|
-
readonly riskLabel: string;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
45
|
export type AgentWorkspaceActionResultKind = 'guidance' | 'blocked' | 'dispatched' | 'refreshed' | 'error';
|
|
50
46
|
|
|
51
47
|
export interface AgentWorkspaceActionResult {
|
|
@@ -100,139 +96,10 @@ export interface AgentWorkspaceRuntimeSnapshot {
|
|
|
100
96
|
readonly runtimeStarterTemplateCount: number;
|
|
101
97
|
readonly localStarterTemplateCount: number;
|
|
102
98
|
readonly configProfileCount: number;
|
|
99
|
+
readonly setupChecklist: readonly AgentWorkspaceSetupChecklistItem[];
|
|
103
100
|
readonly warnings: readonly string[];
|
|
104
101
|
}
|
|
105
102
|
|
|
106
|
-
interface AgentWorkspaceChannelSpec {
|
|
107
|
-
readonly id: string;
|
|
108
|
-
readonly label: string;
|
|
109
|
-
readonly enabledKey: string;
|
|
110
|
-
readonly requiredKeys: readonly string[];
|
|
111
|
-
readonly defaultTargetKeys: readonly string[];
|
|
112
|
-
readonly risk: AgentWorkspaceChannelRisk;
|
|
113
|
-
readonly riskLabel: string;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const AGENT_WORKSPACE_CHANNEL_SPECS: readonly AgentWorkspaceChannelSpec[] = [
|
|
117
|
-
{
|
|
118
|
-
id: 'slack',
|
|
119
|
-
label: 'Slack',
|
|
120
|
-
enabledKey: 'surfaces.slack.enabled',
|
|
121
|
-
requiredKeys: ['surfaces.slack.botToken', 'surfaces.slack.signingSecret'],
|
|
122
|
-
defaultTargetKeys: ['surfaces.slack.defaultChannel'],
|
|
123
|
-
risk: 'group',
|
|
124
|
-
riskLabel: 'workspace/group channel',
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
id: 'discord',
|
|
128
|
-
label: 'Discord',
|
|
129
|
-
enabledKey: 'surfaces.discord.enabled',
|
|
130
|
-
requiredKeys: ['surfaces.discord.botToken', 'surfaces.discord.publicKey', 'surfaces.discord.applicationId'],
|
|
131
|
-
defaultTargetKeys: ['surfaces.discord.defaultChannelId'],
|
|
132
|
-
risk: 'group',
|
|
133
|
-
riskLabel: 'server/channel delivery',
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
id: 'telegram',
|
|
137
|
-
label: 'Telegram',
|
|
138
|
-
enabledKey: 'surfaces.telegram.enabled',
|
|
139
|
-
requiredKeys: ['surfaces.telegram.botToken'],
|
|
140
|
-
defaultTargetKeys: ['surfaces.telegram.defaultChatId'],
|
|
141
|
-
risk: 'dm',
|
|
142
|
-
riskLabel: 'bot DM/group delivery',
|
|
143
|
-
},
|
|
144
|
-
{
|
|
145
|
-
id: 'ntfy',
|
|
146
|
-
label: 'ntfy',
|
|
147
|
-
enabledKey: 'surfaces.ntfy.enabled',
|
|
148
|
-
requiredKeys: ['surfaces.ntfy.baseUrl', 'surfaces.ntfy.chatTopic', 'surfaces.ntfy.agentTopic'],
|
|
149
|
-
defaultTargetKeys: ['surfaces.ntfy.topic'],
|
|
150
|
-
risk: 'public',
|
|
151
|
-
riskLabel: 'topic-based public/private feed',
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
id: 'googleChat',
|
|
155
|
-
label: 'Google Chat',
|
|
156
|
-
enabledKey: 'surfaces.googleChat.enabled',
|
|
157
|
-
requiredKeys: ['surfaces.googleChat.webhookUrl', 'surfaces.googleChat.verificationToken'],
|
|
158
|
-
defaultTargetKeys: ['surfaces.googleChat.spaceId'],
|
|
159
|
-
risk: 'group',
|
|
160
|
-
riskLabel: 'space delivery',
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
id: 'signal',
|
|
164
|
-
label: 'Signal',
|
|
165
|
-
enabledKey: 'surfaces.signal.enabled',
|
|
166
|
-
requiredKeys: ['surfaces.signal.bridgeUrl', 'surfaces.signal.account'],
|
|
167
|
-
defaultTargetKeys: ['surfaces.signal.defaultRecipient'],
|
|
168
|
-
risk: 'bridge',
|
|
169
|
-
riskLabel: 'private bridge delivery',
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
id: 'whatsapp',
|
|
173
|
-
label: 'WhatsApp',
|
|
174
|
-
enabledKey: 'surfaces.whatsapp.enabled',
|
|
175
|
-
requiredKeys: ['surfaces.whatsapp.accessToken', 'surfaces.whatsapp.verifyToken', 'surfaces.whatsapp.phoneNumberId'],
|
|
176
|
-
defaultTargetKeys: ['surfaces.whatsapp.defaultRecipient'],
|
|
177
|
-
risk: 'dm',
|
|
178
|
-
riskLabel: 'phone-number delivery',
|
|
179
|
-
},
|
|
180
|
-
{
|
|
181
|
-
id: 'imessage',
|
|
182
|
-
label: 'iMessage',
|
|
183
|
-
enabledKey: 'surfaces.imessage.enabled',
|
|
184
|
-
requiredKeys: ['surfaces.imessage.bridgeUrl', 'surfaces.imessage.account'],
|
|
185
|
-
defaultTargetKeys: ['surfaces.imessage.defaultChatId'],
|
|
186
|
-
risk: 'bridge',
|
|
187
|
-
riskLabel: 'Apple bridge delivery',
|
|
188
|
-
},
|
|
189
|
-
{
|
|
190
|
-
id: 'bluebubbles',
|
|
191
|
-
label: 'BlueBubbles',
|
|
192
|
-
enabledKey: 'surfaces.bluebubbles.enabled',
|
|
193
|
-
requiredKeys: ['surfaces.bluebubbles.serverUrl', 'surfaces.bluebubbles.password'],
|
|
194
|
-
defaultTargetKeys: ['surfaces.bluebubbles.defaultChatGuid'],
|
|
195
|
-
risk: 'bridge',
|
|
196
|
-
riskLabel: 'iMessage bridge delivery',
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
id: 'msteams',
|
|
200
|
-
label: 'Microsoft Teams',
|
|
201
|
-
enabledKey: 'surfaces.msteams.enabled',
|
|
202
|
-
requiredKeys: ['surfaces.msteams.appId', 'surfaces.msteams.appPassword'],
|
|
203
|
-
defaultTargetKeys: ['surfaces.msteams.defaultConversationId', 'surfaces.msteams.defaultChannelId'],
|
|
204
|
-
risk: 'group',
|
|
205
|
-
riskLabel: 'tenant/channel delivery',
|
|
206
|
-
},
|
|
207
|
-
{
|
|
208
|
-
id: 'mattermost',
|
|
209
|
-
label: 'Mattermost',
|
|
210
|
-
enabledKey: 'surfaces.mattermost.enabled',
|
|
211
|
-
requiredKeys: ['surfaces.mattermost.baseUrl', 'surfaces.mattermost.botToken'],
|
|
212
|
-
defaultTargetKeys: ['surfaces.mattermost.defaultChannelId'],
|
|
213
|
-
risk: 'group',
|
|
214
|
-
riskLabel: 'team/channel delivery',
|
|
215
|
-
},
|
|
216
|
-
{
|
|
217
|
-
id: 'matrix',
|
|
218
|
-
label: 'Matrix',
|
|
219
|
-
enabledKey: 'surfaces.matrix.enabled',
|
|
220
|
-
requiredKeys: ['surfaces.matrix.homeserverUrl', 'surfaces.matrix.accessToken'],
|
|
221
|
-
defaultTargetKeys: ['surfaces.matrix.defaultRoomId'],
|
|
222
|
-
risk: 'group',
|
|
223
|
-
riskLabel: 'room delivery',
|
|
224
|
-
},
|
|
225
|
-
{
|
|
226
|
-
id: 'webhook',
|
|
227
|
-
label: 'Webhook',
|
|
228
|
-
enabledKey: 'surfaces.webhook.enabled',
|
|
229
|
-
requiredKeys: ['surfaces.webhook.defaultTarget'],
|
|
230
|
-
defaultTargetKeys: ['surfaces.webhook.defaultTarget'],
|
|
231
|
-
risk: 'webhook',
|
|
232
|
-
riskLabel: 'external HTTP delivery',
|
|
233
|
-
},
|
|
234
|
-
];
|
|
235
|
-
|
|
236
103
|
function readConfigString(context: CommandContext, key: string, fallback: string): string {
|
|
237
104
|
try {
|
|
238
105
|
const configManager = context.platform?.configManager as unknown as AgentWorkspaceConfigReader | undefined;
|
|
@@ -270,48 +137,6 @@ function readConfigBoolean(context: CommandContext, key: string, fallback: boole
|
|
|
270
137
|
}
|
|
271
138
|
}
|
|
272
139
|
|
|
273
|
-
function hasConfigValue(context: CommandContext, key: string): boolean {
|
|
274
|
-
try {
|
|
275
|
-
const configManager = context.platform?.configManager as unknown as AgentWorkspaceConfigReader | undefined;
|
|
276
|
-
const value = configManager?.get(key);
|
|
277
|
-
if (typeof value === 'string') return value.trim().length > 0;
|
|
278
|
-
if (typeof value === 'number') return Number.isFinite(value);
|
|
279
|
-
if (typeof value === 'boolean') return value;
|
|
280
|
-
return value !== null && value !== undefined;
|
|
281
|
-
} catch {
|
|
282
|
-
return false;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
function buildChannelStatus(context: CommandContext, spec: AgentWorkspaceChannelSpec): AgentWorkspaceChannelStatus {
|
|
287
|
-
const enabled = readConfigBoolean(context, spec.enabledKey, false);
|
|
288
|
-
const missingConfigCount = spec.requiredKeys.filter((key) => !hasConfigValue(context, key)).length;
|
|
289
|
-
const defaultTarget = spec.defaultTargetKeys.length === 0
|
|
290
|
-
? 'not-required'
|
|
291
|
-
: spec.defaultTargetKeys.some((key) => hasConfigValue(context, key))
|
|
292
|
-
? 'configured'
|
|
293
|
-
: 'missing';
|
|
294
|
-
const ready = enabled && missingConfigCount === 0;
|
|
295
|
-
const delivery = !enabled
|
|
296
|
-
? 'disabled'
|
|
297
|
-
: !ready
|
|
298
|
-
? 'blocked'
|
|
299
|
-
: defaultTarget === 'configured'
|
|
300
|
-
? 'default-ready'
|
|
301
|
-
: 'explicit-target';
|
|
302
|
-
return {
|
|
303
|
-
id: spec.id,
|
|
304
|
-
label: spec.label,
|
|
305
|
-
enabled,
|
|
306
|
-
ready,
|
|
307
|
-
missingConfigCount,
|
|
308
|
-
defaultTarget,
|
|
309
|
-
delivery,
|
|
310
|
-
risk: spec.risk,
|
|
311
|
-
riskLabel: spec.riskLabel,
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
|
|
315
140
|
function inferActiveRuntimeProfile(homeDirectory: string): string {
|
|
316
141
|
const marker = `${sep}.goodvibes${sep}agent${sep}profile-homes${sep}`;
|
|
317
142
|
return homeDirectory.includes(marker) ? basename(homeDirectory) : '(default home)';
|
|
@@ -408,6 +233,24 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
|
|
|
408
233
|
const ttsVoice = readConfigString(context, 'tts.voice', '(voice default)');
|
|
409
234
|
const ttsLlmProvider = readConfigString(context, 'tts.llmProvider', '');
|
|
410
235
|
const ttsLlmModel = readConfigString(context, 'tts.llmModel', '');
|
|
236
|
+
const daemonBaseUrl = `http://${host}:${port}`;
|
|
237
|
+
const channels = buildAgentWorkspaceChannels(context);
|
|
238
|
+
const setupChecklist = buildAgentWorkspaceSetupChecklist({
|
|
239
|
+
provider,
|
|
240
|
+
model,
|
|
241
|
+
daemonBaseUrl,
|
|
242
|
+
sessionMemoryCount,
|
|
243
|
+
routineCount: routineSnapshot.count,
|
|
244
|
+
enabledRoutineCount: routineSnapshot.enabled,
|
|
245
|
+
skillCount: skillSnapshot.count,
|
|
246
|
+
enabledSkillCount: skillSnapshot.enabled,
|
|
247
|
+
activePersonaName: personaSnapshot.activeName,
|
|
248
|
+
readyChannelCount: channels.filter((channel) => channel.ready).length,
|
|
249
|
+
voiceProviderCount: voiceProviders.length,
|
|
250
|
+
mediaProviderCount: mediaProviders.length,
|
|
251
|
+
runtimeProfileCount: runtimeProfiles.length,
|
|
252
|
+
runtimeStarterTemplateCount: runtimeStarterTemplates.length,
|
|
253
|
+
});
|
|
411
254
|
|
|
412
255
|
return {
|
|
413
256
|
provider,
|
|
@@ -416,7 +259,7 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
|
|
|
416
259
|
sessionId: context.session?.runtime?.sessionId ?? 'unknown',
|
|
417
260
|
workingDirectory: context.workspace?.shellPaths?.workingDirectory ?? 'unavailable',
|
|
418
261
|
homeDirectory: context.workspace?.shellPaths?.homeDirectory ?? 'unavailable',
|
|
419
|
-
daemonBaseUrl
|
|
262
|
+
daemonBaseUrl,
|
|
420
263
|
daemonOwnership: 'external',
|
|
421
264
|
sessionMemoryCount,
|
|
422
265
|
localRoutineCount: routineSnapshot.count,
|
|
@@ -429,7 +272,7 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
|
|
|
429
272
|
knowledgeIsolation: 'agent-only',
|
|
430
273
|
executionPolicy: 'serial-proactive',
|
|
431
274
|
wrfcPolicy: 'explicit-build-delegation-only',
|
|
432
|
-
channels
|
|
275
|
+
channels,
|
|
433
276
|
voiceProviderCount: voiceProviders.length,
|
|
434
277
|
voiceStreamingProviderCount: voiceProviders.filter((entry) => entry.capabilities.includes('tts-stream')).length,
|
|
435
278
|
voiceSttProviderCount: voiceProviders.filter((entry) => entry.capabilities.includes('stt')).length,
|
|
@@ -449,6 +292,7 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
|
|
|
449
292
|
runtimeStarterTemplateCount: runtimeStarterTemplates.length,
|
|
450
293
|
localStarterTemplateCount: runtimeStarterTemplates.filter((template) => template.source === 'local').length,
|
|
451
294
|
configProfileCount,
|
|
295
|
+
setupChecklist,
|
|
452
296
|
warnings,
|
|
453
297
|
};
|
|
454
298
|
}
|
|
@@ -480,24 +324,6 @@ export const AGENT_WORKSPACE_CATEGORIES: readonly AgentWorkspaceCategory[] = [
|
|
|
480
324
|
{ id: 'auth', label: 'Auth review', detail: 'Review authentication posture without printing token values.', command: '/auth review', kind: 'command', safety: 'read-only' },
|
|
481
325
|
],
|
|
482
326
|
},
|
|
483
|
-
{
|
|
484
|
-
id: 'capabilities',
|
|
485
|
-
group: 'SETUP',
|
|
486
|
-
label: 'Capabilities',
|
|
487
|
-
summary: 'OpenClaw/Hermes benchmark and live daemon coverage.',
|
|
488
|
-
detail: 'Use this area to measure both layers: what GoodVibes Agent makes usable, and what the externally owned GoodVibes daemon actually exposes through public routes. Agent Knowledge is checked only through /api/goodvibes-agent/knowledge/*.',
|
|
489
|
-
actions: [
|
|
490
|
-
{ id: 'capabilities-benchmark', label: 'Benchmark report', detail: 'Show the OpenClaw/Hermes parity benchmark with Agent posture, setup commands, usage paths, and remaining product gaps.', command: '/capabilities', kind: 'command', safety: 'read-only' },
|
|
491
|
-
{ id: 'capabilities-daemon', label: 'Live daemon audit', detail: 'Inspect the public daemon method catalog plus isolated Agent Knowledge route coverage. Does not query default Knowledge/Wiki or HomeGraph.', command: '/capabilities daemon', kind: 'command', safety: 'read-only' },
|
|
492
|
-
{ id: 'capabilities-daemon-gaps', label: 'Daemon gap plan', detail: 'Classify live daemon coverage into platform gaps, Agent route gaps, route-risk reviews, and Agent UX work without querying default Knowledge/Wiki or HomeGraph.', command: '/capabilities daemon gaps', kind: 'command', safety: 'read-only' },
|
|
493
|
-
{ id: 'capabilities-daemon-risk', label: 'Route risk review', detail: 'Inspect daemon read-only, mutating, dangerous, and authenticated route metadata for approval-center planning.', command: '/capabilities daemon risk', kind: 'command', safety: 'read-only' },
|
|
494
|
-
{ id: 'capabilities-daemon-inventory', label: 'Full method inventory', detail: 'List every public daemon method by category, HTTP posture, access, and dangerous flag without querying default Knowledge/Wiki or HomeGraph.', command: '/capabilities daemon inventory', kind: 'command', safety: 'read-only' },
|
|
495
|
-
{ id: 'capabilities-daemon-coverage', label: 'UX coverage matrix', detail: 'Map every public daemon method to Agent UX coverage: usable, read-only, explicit confirmation, blocked, or not surfaced.', command: '/capabilities daemon coverage', kind: 'command', safety: 'read-only' },
|
|
496
|
-
{ id: 'capabilities-daemon-knowledge', label: 'Knowledge coverage', detail: 'Filter the live daemon audit to the isolated Agent Knowledge segment.', command: '/capabilities daemon knowledge', kind: 'command', safety: 'read-only' },
|
|
497
|
-
{ id: 'capabilities-daemon-channels', label: 'Channel coverage', detail: 'Filter the live daemon audit to channel and delivery gateway route coverage.', command: '/capabilities daemon channels', kind: 'command', safety: 'read-only' },
|
|
498
|
-
{ id: 'capabilities-daemon-automation', label: 'Automation coverage', detail: 'Filter the live daemon audit to automation, schedule, run, and capacity route coverage.', command: '/capabilities daemon automation', kind: 'command', safety: 'read-only' },
|
|
499
|
-
],
|
|
500
|
-
},
|
|
501
327
|
{
|
|
502
328
|
id: 'channels',
|
|
503
329
|
group: 'SETUP',
|
|
@@ -532,7 +358,7 @@ export const AGENT_WORKSPACE_CATEGORIES: readonly AgentWorkspaceCategory[] = [
|
|
|
532
358
|
group: 'SETUP',
|
|
533
359
|
label: 'Voice, Media & Nodes',
|
|
534
360
|
summary: 'Voice, TTS, image input, browser surface, and node/remote posture.',
|
|
535
|
-
detail: '
|
|
361
|
+
detail: 'Voice, media, browser, and node surfaces are first-class operator surfaces. Agent uses the GoodVibes voice/media/provider/browser/remote bones while keeping daemon ownership external and side effects explicit.',
|
|
536
362
|
actions: [
|
|
537
363
|
{ id: 'tts-config', label: 'Configure live TTS', detail: 'Open the TUI-derived config workspace at the TTS settings group.', command: '/config tts', kind: 'command', safety: 'safe' },
|
|
538
364
|
{ id: 'tts-provider', label: 'Choose TTS provider', detail: 'Open provider/model routing for spoken responses through the settings flow.', command: '/config tts.provider', kind: 'command', safety: 'safe' },
|
|
@@ -548,7 +374,7 @@ export const AGENT_WORKSPACE_CATEGORIES: readonly AgentWorkspaceCategory[] = [
|
|
|
548
374
|
group: 'SETUP',
|
|
549
375
|
label: 'Profiles & Portability',
|
|
550
376
|
summary: 'Isolated Agent homes, config profiles, and setup bundles.',
|
|
551
|
-
detail: '
|
|
377
|
+
detail: 'Profiles isolate agent state. GoodVibes Agent exposes named runtime homes, config profile pickers, profile-sync bundles, setup transfer bundles, and support bundles while keeping the daemon external.',
|
|
552
378
|
actions: [
|
|
553
379
|
{ id: 'profiles-open', label: 'Open config profiles', detail: 'Open the TUI-derived config profile picker for display/provider/behavior profile files.', command: '/profiles', kind: 'command', safety: 'safe' },
|
|
554
380
|
{ id: 'runtime-profile-guide', label: 'Starter authoring guide', detail: 'Open the Agent-local starter authoring flow inside the TUI command surface.', command: '/agent-profile guide', kind: 'command', safety: 'safe' },
|
|
@@ -584,7 +410,6 @@ export const AGENT_WORKSPACE_CATEGORIES: readonly AgentWorkspaceCategory[] = [
|
|
|
584
410
|
{ id: 'workplan', label: 'Open work plan', detail: 'Open the workspace-scoped work plan panel.', command: '/workplan panel', kind: 'command', safety: 'read-only' },
|
|
585
411
|
{ id: 'workplan-list', label: 'List work plan', detail: 'Print a concise work plan summary.', command: '/workplan list', kind: 'command', safety: 'read-only' },
|
|
586
412
|
{ id: 'approvals', label: 'Review approvals', detail: 'Open/read approval posture. This workspace does not approve or deny requests.', command: '/approval open', kind: 'command', safety: 'read-only' },
|
|
587
|
-
{ id: 'approval-risk', label: 'Route risk review', detail: 'Inspect daemon route risk and dangerous method metadata without approving, denying, or mutating requests.', command: '/approval risk', kind: 'command', safety: 'read-only' },
|
|
588
413
|
],
|
|
589
414
|
},
|
|
590
415
|
{
|
|
@@ -4,13 +4,6 @@ import type { CommandRegistry } from '../command-registry.ts';
|
|
|
4
4
|
import { requirePanelManager, requireShellPaths } from './runtime-services.ts';
|
|
5
5
|
import { requireYesFlag, stripYesFlag } from './confirmation.ts';
|
|
6
6
|
import { resolveAgentDaemonConnection } from '../../agent/routine-schedule-promotion.ts';
|
|
7
|
-
import {
|
|
8
|
-
buildDaemonCapabilityRouteRiskReport,
|
|
9
|
-
fetchLiveDaemonCapabilityAudit,
|
|
10
|
-
filterDaemonCapabilityRouteRiskAreas,
|
|
11
|
-
renderDaemonCapabilityFailure,
|
|
12
|
-
renderDaemonCapabilityRouteRisk,
|
|
13
|
-
} from '../../operator/daemon-capability-audit.ts';
|
|
14
7
|
|
|
15
8
|
interface VoiceBundle {
|
|
16
9
|
readonly version: 1;
|
|
@@ -186,7 +179,7 @@ export function registerExperienceRuntimeCommands(registry: CommandRegistry): vo
|
|
|
186
179
|
name: 'approval',
|
|
187
180
|
aliases: ['approvals'],
|
|
188
181
|
description: 'Review action-specific approval classes and the specialized security UX matrix',
|
|
189
|
-
usage: '[matrix|
|
|
182
|
+
usage: '[matrix|review <kind>]',
|
|
190
183
|
async handler(args, ctx) {
|
|
191
184
|
const sub = (args[0] ?? 'matrix').toLowerCase();
|
|
192
185
|
if (sub === 'open' || sub === 'panel') {
|
|
@@ -213,25 +206,9 @@ export function registerExperienceRuntimeCommands(registry: CommandRegistry): vo
|
|
|
213
206
|
ctx.print([
|
|
214
207
|
'Approval Matrix',
|
|
215
208
|
...matrix.map(([kind, summary]) => ` ${kind.padEnd(10)} ${summary}`),
|
|
216
|
-
'',
|
|
217
|
-
'Live daemon route risk: /approval risk',
|
|
218
209
|
].join('\n'));
|
|
219
210
|
return;
|
|
220
211
|
}
|
|
221
|
-
if (sub === 'risk' || sub === 'route-risk') {
|
|
222
|
-
const shellPaths = requireShellPaths(ctx);
|
|
223
|
-
const connection = resolveAgentDaemonConnection(ctx.platform.configManager, shellPaths.homeDirectory);
|
|
224
|
-
const audit = await fetchLiveDaemonCapabilityAudit(connection);
|
|
225
|
-
if (!audit.ok) {
|
|
226
|
-
ctx.print(renderDaemonCapabilityFailure(audit));
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
const report = buildDaemonCapabilityRouteRiskReport(audit);
|
|
230
|
-
const query = args.slice(1).join(' ').trim() || undefined;
|
|
231
|
-
const areas = filterDaemonCapabilityRouteRiskAreas(report.areas, query);
|
|
232
|
-
ctx.print(renderDaemonCapabilityRouteRisk(report, areas));
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
212
|
if (sub === 'review') {
|
|
236
213
|
const kind = (args[1] ?? '').toLowerCase();
|
|
237
214
|
const entry = matrix.find(([id]) => id === kind);
|
|
@@ -246,7 +223,7 @@ export function registerExperienceRuntimeCommands(registry: CommandRegistry): vo
|
|
|
246
223
|
].join('\n'));
|
|
247
224
|
return;
|
|
248
225
|
}
|
|
249
|
-
ctx.print('Usage: /approval [open|matrix|
|
|
226
|
+
ctx.print('Usage: /approval [open|matrix|review <kind>]');
|
|
250
227
|
},
|
|
251
228
|
});
|
|
252
229
|
|
|
@@ -46,7 +46,7 @@ export function registerRemoteRuntimeCommands(registry: CommandRegistry): void {
|
|
|
46
46
|
name: 'remote',
|
|
47
47
|
aliases: [],
|
|
48
48
|
description: 'Inspect, dispatch, and review self-hosted remote runners and artifacts',
|
|
49
|
-
usage: '[list | show [agentId] | supervisor [runnerId] |
|
|
49
|
+
usage: '[list | show [agentId] | supervisor [runnerId] | support [runnerId] | recover [runnerId] | setup [export <path> --yes] | env [export <path> --yes] | tunnel [review|export <path> --yes] | bootstrap [export <path> --yes|inspect <path>] | session <export|inspect|import> <path> [--yes] | pool <list|show|create|assign|unassign> ... | dispatch [template] <description> | dispatch-pool <pool> [template] <description> | contract [agentId] | cancel <agentId> | export <agentId> [path] --yes | artifact list | artifact show <id> | artifact export <id> [path] --yes | review <id> | rerun-local <id> | import <path> --yes]',
|
|
50
50
|
async handler(args, ctx) {
|
|
51
51
|
if (args.length === 0) {
|
|
52
52
|
if (ctx.openRemotePanel) {
|
|
@@ -131,7 +131,7 @@ export function registerRemoteRuntimeCommands(registry: CommandRegistry): void {
|
|
|
131
131
|
` messageCount: ${selected.messageCount}`,
|
|
132
132
|
` errorCount: ${selected.errorCount}`,
|
|
133
133
|
...(selected.lastError ? [` lastError: ${selected.lastError}`] : []),
|
|
134
|
-
'
|
|
134
|
+
' runner support:',
|
|
135
135
|
...selected.capabilities.map((capability) => ` ${capability.id}: ${capability.supported ? 'yes' : 'no'} (${capability.detail})`),
|
|
136
136
|
' recovery:',
|
|
137
137
|
...selected.recovery.map((action) => ` ${action.command} — ${action.reason}`),
|
|
@@ -139,7 +139,7 @@ export function registerRemoteRuntimeCommands(registry: CommandRegistry): void {
|
|
|
139
139
|
return;
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
if (subcommand === '
|
|
142
|
+
if (subcommand === 'support') {
|
|
143
143
|
const snapshot = peerSnapshot.supervisor;
|
|
144
144
|
const runnerId = args[1];
|
|
145
145
|
const selected = runnerId
|
|
@@ -150,14 +150,14 @@ export function registerRemoteRuntimeCommands(registry: CommandRegistry): void {
|
|
|
150
150
|
return;
|
|
151
151
|
}
|
|
152
152
|
ctx.print([
|
|
153
|
-
`Remote
|
|
153
|
+
`Remote Support ${selected.runnerId}`,
|
|
154
154
|
` label: ${selected.label}`,
|
|
155
155
|
` transport: ${selected.transportState}`,
|
|
156
156
|
` executionProtocol: ${selected.negotiation.executionProtocol}`,
|
|
157
157
|
` reviewMode: ${selected.negotiation.reviewMode}`,
|
|
158
158
|
` communicationLane: ${selected.negotiation.communicationLane}`,
|
|
159
159
|
` trustClass: ${selected.negotiation.trustClass}`,
|
|
160
|
-
'
|
|
160
|
+
' runner support:',
|
|
161
161
|
...selected.capabilities.map((capability) => (
|
|
162
162
|
` ${capability.id}: ${capability.supported ? 'supported' : 'missing'} — ${capability.detail}`
|
|
163
163
|
)),
|
package/src/input/commands.ts
CHANGED
|
@@ -59,7 +59,6 @@ import { registerDelegationRuntimeCommands } from './commands/delegation-runtime
|
|
|
59
59
|
import { registerPersonasRuntimeCommands } from './commands/personas-runtime.ts';
|
|
60
60
|
import { registerAgentSkillsRuntimeCommands } from './commands/agent-skills-runtime.ts';
|
|
61
61
|
import { registerRoutinesRuntimeCommands } from './commands/routines-runtime.ts';
|
|
62
|
-
import { registerCapabilitiesRuntimeCommands } from './commands/capabilities-runtime.ts';
|
|
63
62
|
|
|
64
63
|
/**
|
|
65
64
|
* registerBuiltinCommands - Register all built-in slash commands into the registry.
|
|
@@ -69,7 +68,6 @@ export function registerBuiltinCommands(registry: CommandRegistry): void {
|
|
|
69
68
|
registerShellCoreCommands(registry);
|
|
70
69
|
registerAgentWorkspaceRuntimeCommands(registry);
|
|
71
70
|
registerAgentRuntimeProfileRuntimeCommands(registry);
|
|
72
|
-
registerCapabilitiesRuntimeCommands(registry);
|
|
73
71
|
registerPersonasRuntimeCommands(registry);
|
|
74
72
|
registerAgentSkillsRuntimeCommands(registry);
|
|
75
73
|
registerRoutinesRuntimeCommands(registry);
|
|
@@ -114,7 +114,7 @@ export function buildCapabilitiesStep(controller: OnboardingWizardController): O
|
|
|
114
114
|
kind: 'action',
|
|
115
115
|
id: 'capabilities.select-all',
|
|
116
116
|
action: 'select-all-capabilities',
|
|
117
|
-
label: 'Review external-daemon
|
|
117
|
+
label: 'Review external-daemon surfaces',
|
|
118
118
|
hint: 'Review browser, LAN, webhooks/events, and external app surfaces without letting Agent own daemon lifecycle.',
|
|
119
119
|
defaultValue: 'Action',
|
|
120
120
|
},
|
|
@@ -123,17 +123,17 @@ export function buildCapabilitiesStep(controller: OnboardingWizardController): O
|
|
|
123
123
|
id: 'capabilities.clear',
|
|
124
124
|
action: 'clear-capabilities',
|
|
125
125
|
label: 'Keep Agent local-only',
|
|
126
|
-
hint: 'Clear external-daemon
|
|
126
|
+
hint: 'Clear external-daemon surfaces and keep Agent work in this terminal conversation.',
|
|
127
127
|
defaultValue: 'Action',
|
|
128
128
|
},
|
|
129
129
|
];
|
|
130
130
|
|
|
131
131
|
return {
|
|
132
132
|
id: 'capabilities',
|
|
133
|
-
title: 'Choose GoodVibes
|
|
133
|
+
title: 'Choose GoodVibes surfaces',
|
|
134
134
|
shortLabel: 'Capabilities',
|
|
135
|
-
description: 'Choose what Agent should prepare locally. Daemon-backed
|
|
136
|
-
summaryTitle: 'Selected
|
|
135
|
+
description: 'Choose what Agent should prepare locally. Daemon-backed surfaces are reviewed as external dependencies; Agent does not enable service mode or autostart.',
|
|
136
|
+
summaryTitle: 'Selected surfaces',
|
|
137
137
|
summaryLines: [
|
|
138
138
|
`${selectedCount}/${capabilities.length} option(s) selected`,
|
|
139
139
|
`Mode: ${controller.mode === 'edit' ? 'edit existing shell state' : controller.mode === 'reopen' ? 'reopen review flow' : 'new setup'}`,
|
|
@@ -327,7 +327,7 @@ export function buildExternalServicesStep(controller: OnboardingWizardController
|
|
|
327
327
|
id: 'external-services.clear',
|
|
328
328
|
action: 'clear-external-surfaces',
|
|
329
329
|
label: 'Clear all external surfaces',
|
|
330
|
-
hint: 'Hide all external surface setup screens. The HTTP listener can still be enabled separately by webhook/event
|
|
330
|
+
hint: 'Hide all external surface setup screens. The HTTP listener can still be enabled separately by webhook/event settings.',
|
|
331
331
|
defaultValue: 'Action',
|
|
332
332
|
},
|
|
333
333
|
{
|
|
@@ -705,7 +705,7 @@ export function buildAccountsStep(controller: OnboardingWizardController): Onboa
|
|
|
705
705
|
? 'An existing local auth admin user was detected and will be kept.'
|
|
706
706
|
: controller.hasLocalAuthUser()
|
|
707
707
|
? 'Existing local auth users were detected and will be kept.'
|
|
708
|
-
: 'No server-backed
|
|
708
|
+
: 'No server-backed surface is selected, so local auth is not required.',
|
|
709
709
|
defaultValue: needsAuthBootstrap
|
|
710
710
|
? controller.hasBootstrapCredentialPresent() ? 'Bootstrap replacement required' : 'Local admin required'
|
|
711
711
|
: controller.hasAdminAuthUser() ? 'Admin detected' : controller.hasLocalAuthUser() ? 'Local auth detected' : 'Not required',
|
|
@@ -104,7 +104,7 @@ export function buildProviderHealthDomainSummaries(
|
|
|
104
104
|
.slice(0, 3)
|
|
105
105
|
.map((entry) => `${entry.runnerId}: transport=${entry.transportState} heartbeat=${entry.heartbeat.status}${entry.lastError ? ` error=${entry.lastError}` : ''}`),
|
|
106
106
|
nextSteps: remote.supervisor.degradedConnections > 0
|
|
107
|
-
? ['/remote supervisor', '/remote recover <runnerId>', '/remote
|
|
107
|
+
? ['/remote supervisor', '/remote recover <runnerId>', '/remote support']
|
|
108
108
|
: ['/remote supervisor'],
|
|
109
109
|
});
|
|
110
110
|
|
|
@@ -204,8 +204,8 @@ export class RemotePanel extends BasePanel {
|
|
|
204
204
|
]));
|
|
205
205
|
}
|
|
206
206
|
postureLines.push(
|
|
207
|
-
buildGuidanceLine(width, '/remote recover', 'resume remote state with runner
|
|
208
|
-
buildGuidanceLine(width, '/remote
|
|
207
|
+
buildGuidanceLine(width, '/remote recover', 'resume remote state with runner support and disconnect recovery hints', C),
|
|
208
|
+
buildGuidanceLine(width, '/remote support', 'inspect transport support before routing remote work or reattaching a session', C),
|
|
209
209
|
);
|
|
210
210
|
|
|
211
211
|
const footerLines = [
|
|
@@ -72,6 +72,33 @@ function actionCommand(action: AgentWorkspaceAction): string {
|
|
|
72
72
|
|
|
73
73
|
type ContextLine = { readonly text: string; readonly fg?: string; readonly bold?: boolean; readonly dim?: boolean };
|
|
74
74
|
|
|
75
|
+
function setupStatusColor(status: AgentWorkspaceRuntimeSnapshot['setupChecklist'][number]['status']): string {
|
|
76
|
+
if (status === 'ready') return PALETTE.good;
|
|
77
|
+
if (status === 'recommended') return PALETTE.warn;
|
|
78
|
+
if (status === 'blocked') return PALETTE.bad;
|
|
79
|
+
return PALETTE.muted;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function setupChecklistLines(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLine[] {
|
|
83
|
+
const readyCount = snapshot.setupChecklist.filter((item) => item.status === 'ready').length;
|
|
84
|
+
const recommendedCount = snapshot.setupChecklist.filter((item) => item.status === 'recommended').length;
|
|
85
|
+
const blockedCount = snapshot.setupChecklist.filter((item) => item.status === 'blocked').length;
|
|
86
|
+
const lines: ContextLine[] = [
|
|
87
|
+
{ text: 'Setup Checklist', fg: PALETTE.title, bold: true },
|
|
88
|
+
{ text: `${readyCount}/${snapshot.setupChecklist.length} ready; ${recommendedCount} recommended; ${blockedCount} blocked`, fg: blockedCount > 0 ? PALETTE.warn : PALETTE.info },
|
|
89
|
+
];
|
|
90
|
+
for (const item of snapshot.setupChecklist) {
|
|
91
|
+
const command = item.command ? ` -> ${item.command}` : '';
|
|
92
|
+
lines.push({
|
|
93
|
+
text: `${item.status.toUpperCase()} ${item.label}${command}`,
|
|
94
|
+
fg: setupStatusColor(item.status),
|
|
95
|
+
bold: item.status === 'blocked',
|
|
96
|
+
});
|
|
97
|
+
lines.push({ text: ` ${item.detail}`, fg: PALETTE.muted });
|
|
98
|
+
}
|
|
99
|
+
return lines;
|
|
100
|
+
}
|
|
101
|
+
|
|
75
102
|
function snapshotLines(category: AgentWorkspaceCategory, snapshot: AgentWorkspaceRuntimeSnapshot | null): ContextLine[] {
|
|
76
103
|
if (!snapshot) return [{ text: 'Runtime context is not loaded yet.', fg: PALETTE.warn }];
|
|
77
104
|
const base: ContextLine[] = [{ text: 'Live Agent Context', fg: PALETTE.title, bold: true }];
|
|
@@ -87,14 +114,8 @@ function snapshotLines(category: AgentWorkspaceCategory, snapshot: AgentWorkspac
|
|
|
87
114
|
{ text: `Daemon ownership: ${snapshot.daemonOwnership}; Agent never starts or restarts it`, fg: PALETTE.good },
|
|
88
115
|
{ text: `Workspace: ${snapshot.workingDirectory}`, fg: PALETTE.muted },
|
|
89
116
|
{ text: `Home: ${snapshot.homeDirectory}`, fg: PALETTE.muted },
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
base.push(
|
|
93
|
-
{ text: `External daemon: ${snapshot.daemonBaseUrl}`, fg: PALETTE.info },
|
|
94
|
-
{ text: 'Live audit source: /api/control-plane/methods plus /api/goodvibes-agent/knowledge/status.', fg: PALETTE.info },
|
|
95
|
-
{ text: 'Isolation: no default Knowledge/Wiki, HomeGraph, or Home Assistant route is used for Agent Knowledge coverage.', fg: PALETTE.good },
|
|
96
|
-
{ text: 'Readiness meaning: daemon route coverage is platform capability; missing Agent UX remains a product gap to close here.', fg: PALETTE.muted },
|
|
97
|
-
{ text: 'Use filtered audits for knowledge, channels, automation, voice/media/nodes, providers, MCP/tools, approvals, or sessions.', fg: PALETTE.muted },
|
|
117
|
+
{ text: '' },
|
|
118
|
+
...setupChecklistLines(snapshot),
|
|
98
119
|
);
|
|
99
120
|
} else if (category.id === 'channels') {
|
|
100
121
|
const enabledCount = snapshot.channels.filter((channel) => channel.enabled).length;
|
|
@@ -275,10 +296,17 @@ function footerText(workspace: AgentWorkspace): string {
|
|
|
275
296
|
}
|
|
276
297
|
|
|
277
298
|
export function renderAgentWorkspace(workspace: AgentWorkspace, width: number, height: number): Line[] {
|
|
278
|
-
const layoutOptions = { width, height, leftWidth: width < 90 ? undefined : 30, contextRatio: 0.62, minContextRows: 10 };
|
|
279
|
-
const metrics = getFullscreenWorkspaceMetrics(layoutOptions);
|
|
280
299
|
const category = workspace.selectedCategory;
|
|
281
300
|
const action = workspace.selectedAction;
|
|
301
|
+
const setupCategory = category.id === 'setup';
|
|
302
|
+
const layoutOptions = {
|
|
303
|
+
width,
|
|
304
|
+
height,
|
|
305
|
+
leftWidth: width < 90 ? undefined : 30,
|
|
306
|
+
contextRatio: setupCategory ? 0.86 : 0.62,
|
|
307
|
+
minContextRows: setupCategory ? 18 : 10,
|
|
308
|
+
};
|
|
309
|
+
const metrics = getFullscreenWorkspaceMetrics(layoutOptions);
|
|
282
310
|
|
|
283
311
|
return renderFullscreenWorkspace({
|
|
284
312
|
width,
|
|
@@ -3,13 +3,13 @@ import type { Tool } from '@pellux/goodvibes-sdk/platform/types';
|
|
|
3
3
|
const CONTEXT_TOOL_DENIAL = [
|
|
4
4
|
'GoodVibes Agent does not expose copied GoodVibes runtime context through model tools in the main conversation.',
|
|
5
5
|
'The copied context tool can describe TUI/default runtime assumptions that are not the Agent product boundary.',
|
|
6
|
-
'Use explicit Agent CLI/slash commands such as status, compat,
|
|
6
|
+
'Use explicit Agent CLI/slash commands such as status, compat, setup, and isolated Agent Knowledge instead.',
|
|
7
7
|
].join(' ');
|
|
8
8
|
|
|
9
9
|
export function wrapBlockedContextToolForAgentPolicy(tool: Tool): void {
|
|
10
10
|
tool.definition.description = [
|
|
11
11
|
'Blocked in GoodVibes Agent main conversation: copied runtime context.',
|
|
12
|
-
'Use explicit Agent CLI/slash status, compat,
|
|
12
|
+
'Use explicit Agent CLI/slash status, compat, setup, and Agent Knowledge commands for product-scoped context.',
|
|
13
13
|
'Default Knowledge/Wiki, HomeGraph, and copied TUI runtime assumptions are not Agent fallbacks.',
|
|
14
14
|
].join(' ');
|
|
15
15
|
tool.definition.sideEffects = [];
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { join, resolve } from 'node:path';
|
|
3
3
|
import { spawn } from 'node:child_process';
|
|
4
|
-
import { auditGoodVibesHome } from '../config/goodvibes-home-audit.ts';
|
|
5
4
|
import { buildVerificationLedger } from './verification-ledger.ts';
|
|
6
5
|
import { SDK_VERSION } from '../version.ts';
|
|
7
6
|
|
|
@@ -309,20 +308,6 @@ export async function buildLiveVerificationReport(options: LiveVerificationOptio
|
|
|
309
308
|
detail: `${ledger.totals.localBehaviorPercent}% local behavior verified; ${ledger.totals.externalOutcomeRequired} item(s) require external outcomes.`,
|
|
310
309
|
});
|
|
311
310
|
|
|
312
|
-
const audit = await auditGoodVibesHome({ homeDir });
|
|
313
|
-
const staleCandidates = audit.settings?.staleCandidates?.length ?? 0;
|
|
314
|
-
checks.push({
|
|
315
|
-
id: 'goodvibes-home-audit',
|
|
316
|
-
title: 'GoodVibes home ownership/settings audit',
|
|
317
|
-
status: audit.findings.length === 0 && staleCandidates === 0 ? 'pass' : 'warn',
|
|
318
|
-
summary: audit.findings.length === 0
|
|
319
|
-
? 'No ownership, stale-setting, or secret-permission findings.'
|
|
320
|
-
: `${audit.findings.length} audit finding(s).`,
|
|
321
|
-
detail: audit.findings.length === 0
|
|
322
|
-
? `${audit.settings?.recognizedKeyCount ?? 0} current schema key(s), ${staleCandidates} stale candidate(s).`
|
|
323
|
-
: audit.findings.map((finding) => `${finding.severity}: ${finding.message}`).join('\n'),
|
|
324
|
-
});
|
|
325
|
-
|
|
326
311
|
checks.push({
|
|
327
312
|
id: 'compiled-cli-present',
|
|
328
313
|
title: 'Compiled GoodVibes Agent CLI binary',
|
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.1.
|
|
9
|
+
let _version = '0.1.48';
|
|
10
10
|
let _sdkVersion = '0.33.35';
|
|
11
11
|
try {
|
|
12
12
|
const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', 'package.json'), 'utf-8')) as {
|