@pellux/goodvibes-agent 0.1.31 → 0.1.32
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 +4 -0
- package/docs/operator-capability-benchmark.md +2 -2
- package/package.json +1 -1
- package/src/input/agent-workspace.ts +60 -0
- package/src/input/command-registry.ts +3 -1
- package/src/operator/capability-benchmark.ts +6 -6
- package/src/renderer/agent-workspace.ts +10 -0
- package/src/runtime/bootstrap-command-context.ts +4 -1
- package/src/runtime/bootstrap-command-parts.ts +4 -1
- package/src/runtime/bootstrap-shell.ts +1 -0
- package/src/version.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -55,7 +55,7 @@ Primary sources used for the benchmark:
|
|
|
55
55
|
| Skills/procedural memory | Skills directories, registries, skill lifecycle | Local Agent skills with review/stale/source/provenance fields |
|
|
56
56
|
| Scheduling | Natural-language cron, run/pause/resume/edit/remove, delivery | Guarded automation/schedule routes plus local routines; hidden model scheduling blocked |
|
|
57
57
|
| Tools/MCP | Broad toolsets, MCP, browser, media, terminal, files | GoodVibes SDK tools with Agent policy guards and MCP/provider integrations |
|
|
58
|
-
| Voice/media/canvas/nodes | Voice, TTS, mobile nodes, live canvas, browser automation | GoodVibes media/voice/browser primitives
|
|
58
|
+
| Voice/media/canvas/nodes | Voice, TTS, mobile nodes, live canvas, browser automation | GoodVibes media/voice/browser/node primitives with an Agent workspace for setup, image input, browser posture, MCP, and remote/node inspection |
|
|
59
59
|
| Build/code work | Direct terminal/file/code tools and subagents | Explicit delegation to GoodVibes TUI; local WRFC/spawn fanout blocked |
|
|
60
60
|
| Profiles | Independent profiles with own config/memory/skills/gateway | `GOODVIBES_AGENT_HOME` and named `--agent-profile` homes isolate Agent-local state; daemon remains external |
|
|
61
61
|
| Security | DM pairing, approvals, sandboxing, allowlists | Daemon approvals, auth diagnostics, secret refs, confirmation gates, model-tool policy |
|
|
@@ -76,7 +76,7 @@ GoodVibes Agent should exceed OpenClaw/Hermes by making these properties true fr
|
|
|
76
76
|
- Live daemon account health and last delivery errors in the Channels workspace once a stable read-only route is available.
|
|
77
77
|
- Artifact and multimodal Agent Knowledge ingest affordances once Agent-specific routes are stable.
|
|
78
78
|
- Profile-aware onboarding summaries and profile export/import shortcuts from the Agent workspace.
|
|
79
|
-
-
|
|
79
|
+
- Artifact and multimodal Agent Knowledge ingestion when the isolated Agent route accepts artifact-backed media.
|
|
80
80
|
- Delegation receipts and artifact review inside the operator workspace.
|
|
81
81
|
- Approval center with route risk labels and saved policy presets.
|
|
82
82
|
- Intent-gated tool exposure so the model sees fewer irrelevant tools per turn while retaining broad capability coverage.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pellux/goodvibes-agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.32",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Near-fork GoodVibes operator assistant with the GoodVibes TUI shell, renderer, input, fullscreen workspace, and daemon-connected Agent product brain.",
|
|
6
6
|
"type": "module",
|
|
@@ -79,6 +79,19 @@ export interface AgentWorkspaceRuntimeSnapshot {
|
|
|
79
79
|
readonly executionPolicy: 'serial-proactive';
|
|
80
80
|
readonly wrfcPolicy: 'explicit-build-delegation-only';
|
|
81
81
|
readonly channels: readonly AgentWorkspaceChannelStatus[];
|
|
82
|
+
readonly voiceProviderCount: number;
|
|
83
|
+
readonly voiceStreamingProviderCount: number;
|
|
84
|
+
readonly voiceSttProviderCount: number;
|
|
85
|
+
readonly voiceRealtimeProviderCount: number;
|
|
86
|
+
readonly ttsProvider: string;
|
|
87
|
+
readonly ttsVoice: string;
|
|
88
|
+
readonly ttsResponseModel: string;
|
|
89
|
+
readonly voiceSurfaceEnabled: boolean;
|
|
90
|
+
readonly mediaProviderCount: number;
|
|
91
|
+
readonly mediaUnderstandingProviderCount: number;
|
|
92
|
+
readonly mediaGenerationProviderCount: number;
|
|
93
|
+
readonly browserSurfaceEnabled: boolean;
|
|
94
|
+
readonly browserSurfacePublicBaseUrl: string;
|
|
82
95
|
readonly warnings: readonly string[];
|
|
83
96
|
}
|
|
84
97
|
|
|
@@ -340,9 +353,27 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
|
|
|
340
353
|
return { count: 0, enabled: 0 };
|
|
341
354
|
}
|
|
342
355
|
})();
|
|
356
|
+
const voiceProviders = (() => {
|
|
357
|
+
try {
|
|
358
|
+
return context.platform?.voiceProviderRegistry?.list?.() ?? [];
|
|
359
|
+
} catch {
|
|
360
|
+
return [];
|
|
361
|
+
}
|
|
362
|
+
})();
|
|
363
|
+
const mediaProviders = (() => {
|
|
364
|
+
try {
|
|
365
|
+
return context.platform?.mediaProviderRegistry?.list?.() ?? [];
|
|
366
|
+
} catch {
|
|
367
|
+
return [];
|
|
368
|
+
}
|
|
369
|
+
})();
|
|
343
370
|
const warnings: string[] = [];
|
|
344
371
|
if (provider === 'unknown' || model === 'unknown') warnings.push('Provider/model unavailable in this runtime context.');
|
|
345
372
|
if (!context.executeCommand) warnings.push('Command dispatch is unavailable; workspace actions will show guidance only.');
|
|
373
|
+
const ttsProvider = readConfigString(context, 'tts.provider', '(provider default)');
|
|
374
|
+
const ttsVoice = readConfigString(context, 'tts.voice', '(voice default)');
|
|
375
|
+
const ttsLlmProvider = readConfigString(context, 'tts.llmProvider', '');
|
|
376
|
+
const ttsLlmModel = readConfigString(context, 'tts.llmModel', '');
|
|
346
377
|
|
|
347
378
|
return {
|
|
348
379
|
provider,
|
|
@@ -365,6 +396,19 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
|
|
|
365
396
|
executionPolicy: 'serial-proactive',
|
|
366
397
|
wrfcPolicy: 'explicit-build-delegation-only',
|
|
367
398
|
channels: AGENT_WORKSPACE_CHANNEL_SPECS.map((spec) => buildChannelStatus(context, spec)),
|
|
399
|
+
voiceProviderCount: voiceProviders.length,
|
|
400
|
+
voiceStreamingProviderCount: voiceProviders.filter((entry) => entry.capabilities.includes('tts-stream')).length,
|
|
401
|
+
voiceSttProviderCount: voiceProviders.filter((entry) => entry.capabilities.includes('stt')).length,
|
|
402
|
+
voiceRealtimeProviderCount: voiceProviders.filter((entry) => entry.capabilities.includes('realtime')).length,
|
|
403
|
+
ttsProvider,
|
|
404
|
+
ttsVoice,
|
|
405
|
+
ttsResponseModel: ttsLlmProvider && ttsLlmModel ? `${ttsLlmProvider}/${ttsLlmModel}` : '(chat route)',
|
|
406
|
+
voiceSurfaceEnabled: readConfigBoolean(context, 'ui.voiceEnabled', false),
|
|
407
|
+
mediaProviderCount: mediaProviders.length,
|
|
408
|
+
mediaUnderstandingProviderCount: mediaProviders.filter((entry) => entry.capabilities.includes('understand')).length,
|
|
409
|
+
mediaGenerationProviderCount: mediaProviders.filter((entry) => entry.capabilities.includes('generate')).length,
|
|
410
|
+
browserSurfaceEnabled: readConfigBoolean(context, 'web.enabled', false),
|
|
411
|
+
browserSurfacePublicBaseUrl: readConfigString(context, 'web.publicBaseUrl', '(not configured)'),
|
|
368
412
|
warnings,
|
|
369
413
|
};
|
|
370
414
|
}
|
|
@@ -425,6 +469,22 @@ export const AGENT_WORKSPACE_CATEGORIES: readonly AgentWorkspaceCategory[] = [
|
|
|
425
469
|
{ id: 'knowledge-ask', label: 'Ask Agent knowledge', detail: 'Close this workspace and run /knowledge ask <question> or ask normally in chat.', kind: 'guidance', safety: 'read-only' },
|
|
426
470
|
],
|
|
427
471
|
},
|
|
472
|
+
{
|
|
473
|
+
id: 'voice-media',
|
|
474
|
+
group: 'SETUP',
|
|
475
|
+
label: 'Voice, Media & Nodes',
|
|
476
|
+
summary: 'Voice, TTS, image input, browser surface, and node/remote posture.',
|
|
477
|
+
detail: 'Hermes and OpenClaw expose voice, media, browser, and node surfaces as first-class operator capabilities. Agent uses the GoodVibes voice/media/provider/browser/remote bones while keeping daemon ownership external and side effects explicit.',
|
|
478
|
+
actions: [
|
|
479
|
+
{ 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' },
|
|
480
|
+
{ 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' },
|
|
481
|
+
{ id: 'tts-speak', label: 'Speak a prompt', detail: 'Submit a normal assistant turn and play the reply through configured live TTS. Close this workspace and provide real prompt text.', command: '/tts <prompt>', kind: 'command', safety: 'safe' },
|
|
482
|
+
{ id: 'image-attach', label: 'Attach image input', detail: 'Attach an image to the next assistant turn. Close this workspace and provide a real path and prompt.', command: '/image <path> <prompt>', kind: 'command', safety: 'safe' },
|
|
483
|
+
{ id: 'browser-surface', label: 'Browser surface status', detail: 'Inspect browser/web posture through setup diagnostics without starting listeners or daemon services.', command: '/setup services', kind: 'command', safety: 'read-only' },
|
|
484
|
+
{ id: 'mcp-browser', label: 'Browser MCP tools', detail: 'Inspect MCP servers and tools, including browser/automation roles, without mutating server setup.', command: '/mcp servers', kind: 'command', safety: 'read-only' },
|
|
485
|
+
{ id: 'node-posture', label: 'Node/remote posture', detail: 'Inspect remote runner/node posture. Dispatch remains blocked unless the task is explicit build delegation to TUI.', command: '/remote list', kind: 'command', safety: 'read-only' },
|
|
486
|
+
],
|
|
487
|
+
},
|
|
428
488
|
{
|
|
429
489
|
id: 'memory',
|
|
430
490
|
group: 'LEARN',
|
|
@@ -20,6 +20,7 @@ import type { OperatorClient } from '@/runtime/index.ts';
|
|
|
20
20
|
import type { PeerClient } from '@/runtime/index.ts';
|
|
21
21
|
import type { DirectTransport } from '@/runtime/index.ts';
|
|
22
22
|
import type { VoiceProviderRegistry, VoiceService } from '@pellux/goodvibes-sdk/platform/voice';
|
|
23
|
+
import type { MediaProviderRegistry } from '@pellux/goodvibes-sdk/platform/media';
|
|
23
24
|
import type {
|
|
24
25
|
CommandWorkspaceShellServices,
|
|
25
26
|
} from '@/runtime/index.ts';
|
|
@@ -163,6 +164,7 @@ export interface CommandPlatformConfigServices {
|
|
|
163
164
|
readonly configManager: ConfigManager;
|
|
164
165
|
readonly voiceProviderRegistry?: VoiceProviderRegistry;
|
|
165
166
|
readonly voiceService?: VoiceService;
|
|
167
|
+
readonly mediaProviderRegistry?: MediaProviderRegistry;
|
|
166
168
|
}
|
|
167
169
|
|
|
168
170
|
export interface CommandPlatformServices
|
|
@@ -256,7 +258,7 @@ export class CommandRegistry {
|
|
|
256
258
|
}
|
|
257
259
|
|
|
258
260
|
/**
|
|
259
|
-
* get - Look up a command by its primary name or
|
|
261
|
+
* get - Look up a command by its primary name or alias. O(1) for both.
|
|
260
262
|
*/
|
|
261
263
|
get(name: string): SlashCommand | undefined {
|
|
262
264
|
return this.commands.get(name) ?? this.aliasIndex.get(name);
|
|
@@ -133,14 +133,14 @@ export const OPERATOR_CAPABILITY_BENCHMARKS: readonly OperatorCapabilityBenchmar
|
|
|
133
133
|
{
|
|
134
134
|
id: 'voice-media-canvas',
|
|
135
135
|
title: 'Voice, Media, Canvas, And Nodes',
|
|
136
|
-
posture: '
|
|
136
|
+
posture: 'configurable',
|
|
137
137
|
competitors: ['openclaw', 'hermes'],
|
|
138
138
|
competitorBaseline: 'Voice/TTS, mobile nodes, live canvas, browser automation, image/video generation, and multimodal analysis.',
|
|
139
|
-
goodvibesAgent: '
|
|
140
|
-
configure: ['/
|
|
141
|
-
use: ['/tts
|
|
142
|
-
exceedsBy: ['Shared GoodVibes media/provider substrate', '
|
|
143
|
-
next: ['
|
|
139
|
+
goodvibesAgent: 'Uses GoodVibes voice/media/browser/node primitives and exposes an Agent workspace for TTS setup, image input, browser/web posture, MCP browser tools, and node/remote inspection.',
|
|
140
|
+
configure: ['/agent → Voice, Media & Nodes', '/config tts', '/voice review', '/mcp servers'],
|
|
141
|
+
use: ['/tts <prompt>', '/image <path> <prompt>', '/remote list'],
|
|
142
|
+
exceedsBy: ['Shared GoodVibes media/provider substrate', 'fullscreen setup visibility', 'read-only browser/node posture by default', 'template commands that cannot run without real target values'],
|
|
143
|
+
next: ['Add artifact and multimodal Agent Knowledge ingestion once the isolated Agent knowledge route accepts artifact-backed media.'],
|
|
144
144
|
},
|
|
145
145
|
{
|
|
146
146
|
id: 'explicit-build-delegation',
|
|
@@ -117,6 +117,16 @@ function snapshotLines(category: AgentWorkspaceCategory, snapshot: AgentWorkspac
|
|
|
117
117
|
{ text: 'Review: queue, issues, candidates, reports, reindex, and consolidation stay inside the Agent segment.', fg: PALETTE.muted },
|
|
118
118
|
{ text: 'Agent-owned content appears here only after explicit Agent knowledge ingestion.', fg: PALETTE.muted },
|
|
119
119
|
);
|
|
120
|
+
} else if (category.id === 'voice-media') {
|
|
121
|
+
base.push(
|
|
122
|
+
{ text: `Voice providers: ${snapshot.voiceProviderCount}; streaming TTS: ${snapshot.voiceStreamingProviderCount}; STT: ${snapshot.voiceSttProviderCount}; realtime: ${snapshot.voiceRealtimeProviderCount}.`, fg: PALETTE.info },
|
|
123
|
+
{ text: `Voice surface: ${snapshot.voiceSurfaceEnabled ? 'enabled' : 'disabled'}; use /voice review for portable voice posture.`, fg: snapshot.voiceSurfaceEnabled ? PALETTE.warn : PALETTE.muted },
|
|
124
|
+
{ text: `TTS config: provider ${snapshot.ttsProvider}; voice ${snapshot.ttsVoice}; response model ${snapshot.ttsResponseModel}.`, fg: PALETTE.info },
|
|
125
|
+
{ text: `Media providers: ${snapshot.mediaProviderCount}; understanding: ${snapshot.mediaUnderstandingProviderCount}; generation: ${snapshot.mediaGenerationProviderCount}.`, fg: PALETTE.info },
|
|
126
|
+
{ text: `Browser surface: ${snapshot.browserSurfaceEnabled ? 'enabled' : 'disabled'}; public base URL ${snapshot.browserSurfacePublicBaseUrl}.`, fg: snapshot.browserSurfaceEnabled ? PALETTE.warn : PALETTE.muted },
|
|
127
|
+
{ text: 'Node/remote posture is read-only here; build dispatch remains explicit TUI delegation.', fg: PALETTE.good },
|
|
128
|
+
{ text: 'Image input uses prompt attachments; media generation/provider setup stays behind explicit commands and configured providers.', fg: PALETTE.muted },
|
|
129
|
+
);
|
|
120
130
|
} else if (category.id === 'memory') {
|
|
121
131
|
base.push(
|
|
122
132
|
{ text: `Session memories: ${snapshot.sessionMemoryCount}`, fg: PALETTE.info },
|
|
@@ -38,6 +38,7 @@ import type { OperatorClient } from '@/runtime/index.ts';
|
|
|
38
38
|
import type { PeerClient } from '@/runtime/index.ts';
|
|
39
39
|
import type { DirectTransport } from '@/runtime/index.ts';
|
|
40
40
|
import type { VoiceProviderRegistry, VoiceService } from '@pellux/goodvibes-sdk/platform/voice';
|
|
41
|
+
import type { MediaProviderRegistry } from '@pellux/goodvibes-sdk/platform/media';
|
|
41
42
|
import {
|
|
42
43
|
createBootstrapCommandActions,
|
|
43
44
|
createBootstrapCommandClientsSection,
|
|
@@ -61,6 +62,7 @@ export type CreateBootstrapCommandContextOptions = {
|
|
|
61
62
|
mcpRegistry: McpRegistry;
|
|
62
63
|
voiceProviderRegistry?: VoiceProviderRegistry;
|
|
63
64
|
voiceService?: VoiceService;
|
|
65
|
+
mediaProviderRegistry?: MediaProviderRegistry;
|
|
64
66
|
forensicsRegistry: ForensicsRegistry;
|
|
65
67
|
policyRuntimeState: PolicyRuntimeState;
|
|
66
68
|
readModels: UiReadModels;
|
|
@@ -130,6 +132,7 @@ export function createBootstrapCommandContext(
|
|
|
130
132
|
mcpRegistry,
|
|
131
133
|
voiceProviderRegistry,
|
|
132
134
|
voiceService,
|
|
135
|
+
mediaProviderRegistry,
|
|
133
136
|
forensicsRegistry,
|
|
134
137
|
policyRuntimeState,
|
|
135
138
|
readModels,
|
|
@@ -237,7 +240,7 @@ export function createBootstrapCommandContext(
|
|
|
237
240
|
projectPlanningProjectId,
|
|
238
241
|
workPlanStore,
|
|
239
242
|
}, shellServices);
|
|
240
|
-
const platform = createBootstrapCommandPlatformSection({ configManager, voiceProviderRegistry, voiceService }, shellServices);
|
|
243
|
+
const platform = createBootstrapCommandPlatformSection({ configManager, voiceProviderRegistry, voiceService, mediaProviderRegistry }, shellServices);
|
|
241
244
|
const extensions = createBootstrapCommandExtensionsSection({
|
|
242
245
|
toolRegistry,
|
|
243
246
|
mcpRegistry,
|
|
@@ -41,6 +41,7 @@ import type { OperatorClient } from '@/runtime/index.ts';
|
|
|
41
41
|
import type { PeerClient } from '@/runtime/index.ts';
|
|
42
42
|
import type { DirectTransport } from '@/runtime/index.ts';
|
|
43
43
|
import type { VoiceProviderRegistry, VoiceService } from '@pellux/goodvibes-sdk/platform/voice';
|
|
44
|
+
import type { MediaProviderRegistry } from '@pellux/goodvibes-sdk/platform/media';
|
|
44
45
|
import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
|
|
45
46
|
|
|
46
47
|
export type BootstrapCommandSessionSection = CommandContext['session'];
|
|
@@ -77,6 +78,7 @@ export interface BootstrapCommandSectionOptions {
|
|
|
77
78
|
readonly mcpRegistry: McpRegistry;
|
|
78
79
|
readonly voiceProviderRegistry?: VoiceProviderRegistry;
|
|
79
80
|
readonly voiceService?: VoiceService;
|
|
81
|
+
readonly mediaProviderRegistry?: MediaProviderRegistry;
|
|
80
82
|
readonly forensicsRegistry: ForensicsRegistry;
|
|
81
83
|
readonly policyRuntimeState: PolicyRuntimeState;
|
|
82
84
|
readonly readModels: UiReadModels;
|
|
@@ -334,7 +336,7 @@ export function createBootstrapCommandWorkspaceSection(
|
|
|
334
336
|
export function createBootstrapCommandPlatformSection(
|
|
335
337
|
options: Pick<
|
|
336
338
|
BootstrapCommandSectionOptions,
|
|
337
|
-
'configManager' | 'voiceProviderRegistry' | 'voiceService'
|
|
339
|
+
'configManager' | 'voiceProviderRegistry' | 'voiceService' | 'mediaProviderRegistry'
|
|
338
340
|
>,
|
|
339
341
|
shellServices: BootstrapCommandShellServices,
|
|
340
342
|
): BootstrapCommandPlatformSection {
|
|
@@ -343,6 +345,7 @@ export function createBootstrapCommandPlatformSection(
|
|
|
343
345
|
configManager: options.configManager,
|
|
344
346
|
voiceProviderRegistry: options.voiceProviderRegistry,
|
|
345
347
|
voiceService: options.voiceService,
|
|
348
|
+
mediaProviderRegistry: options.mediaProviderRegistry,
|
|
346
349
|
...shellServices.platform,
|
|
347
350
|
};
|
|
348
351
|
}
|
|
@@ -195,6 +195,7 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
195
195
|
mcpRegistry: services.mcpRegistry,
|
|
196
196
|
voiceProviderRegistry: services.voiceProviders,
|
|
197
197
|
voiceService: services.voiceService,
|
|
198
|
+
mediaProviderRegistry: services.mediaProviders,
|
|
198
199
|
forensicsRegistry,
|
|
199
200
|
policyRuntimeState,
|
|
200
201
|
readModels: uiServices.readModels,
|
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.32';
|
|
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 {
|