@pellux/goodvibes-agent 0.1.46 → 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 +15 -9
- package/README.md +3 -21
- package/docs/README.md +0 -2
- package/package.json +1 -3
- package/src/cli/completion.ts +0 -1
- package/src/cli/help.ts +0 -11
- 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 -208
- 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 -104
- package/src/cli/capabilities-command.ts +0 -147
- package/src/config/goodvibes-home-audit.ts +0 -465
- package/src/input/commands/capabilities-runtime.ts +0 -88
- package/src/operator/capability-benchmark.ts +0 -244
- package/src/operator/daemon-capability-audit.ts +0 -1180
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
# Operator Capability Benchmark
|
|
2
|
-
|
|
3
|
-
GoodVibes Agent is built to compete directly with OpenClaw and Hermes Agent in the personal-operator assistant space, while keeping the GoodVibes product boundary explicit:
|
|
4
|
-
|
|
5
|
-
- Agent uses the GoodVibes TUI shell, renderer, input, fullscreen workspace, command registry, and release bones.
|
|
6
|
-
- Agent connects to an externally managed GoodVibes daemon.
|
|
7
|
-
- Agent Knowledge/Wiki uses only `/api/goodvibes-agent/knowledge/*`.
|
|
8
|
-
- Agent never falls back to default Knowledge/Wiki, HomeGraph, or Home Assistant routes.
|
|
9
|
-
- Agent keeps ordinary work serial in the main conversation.
|
|
10
|
-
- Agent delegates explicit build/fix/review work to GoodVibes TUI; WRFC is never default.
|
|
11
|
-
|
|
12
|
-
Use the live benchmark from the package:
|
|
13
|
-
|
|
14
|
-
```sh
|
|
15
|
-
goodvibes-agent capabilities
|
|
16
|
-
goodvibes-agent capabilities --json
|
|
17
|
-
goodvibes-agent capabilities hermes
|
|
18
|
-
goodvibes-agent capabilities daemon
|
|
19
|
-
goodvibes-agent capabilities daemon --json
|
|
20
|
-
goodvibes-agent capabilities daemon gaps
|
|
21
|
-
goodvibes-agent capabilities daemon risk
|
|
22
|
-
goodvibes-agent capabilities daemon inventory
|
|
23
|
-
goodvibes-agent capabilities daemon knowledge
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
Inside the TUI:
|
|
27
|
-
|
|
28
|
-
```text
|
|
29
|
-
/capabilities
|
|
30
|
-
/capabilities openclaw
|
|
31
|
-
/capabilities knowledge
|
|
32
|
-
/capabilities daemon
|
|
33
|
-
/capabilities daemon gaps
|
|
34
|
-
/capabilities daemon inventory
|
|
35
|
-
/approval risk
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Research Baseline
|
|
39
|
-
|
|
40
|
-
Primary sources used for the benchmark:
|
|
41
|
-
|
|
42
|
-
- OpenClaw README: https://github.com/openclaw/openclaw/blob/main/README.md
|
|
43
|
-
- OpenClaw Docs: https://docs.openclaw.ai/
|
|
44
|
-
- OpenClaw Features: https://docs.openclaw.ai/concepts/features
|
|
45
|
-
- OpenClaw FAQ: https://docs.openclaw.ai/help/faq
|
|
46
|
-
- OpenClaw Memory: https://docs.openclaw.ai/concepts/memory
|
|
47
|
-
- Hermes README: https://github.com/NousResearch/hermes-agent
|
|
48
|
-
- Hermes Features Overview: https://hermes-agent.nousresearch.com/docs/user-guide/features/overview/
|
|
49
|
-
- Hermes Tools: https://hermes-agent.nousresearch.com/docs/user-guide/features/tools/
|
|
50
|
-
- Hermes Skills: https://hermes-agent.nousresearch.com/docs/user-guide/features/skills/
|
|
51
|
-
- Hermes Cron: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron/
|
|
52
|
-
- Hermes MCP: https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp/
|
|
53
|
-
- Hermes Voice: https://hermes-agent.nousresearch.com/docs/user-guide/features/voice-mode/
|
|
54
|
-
- Hermes API Server: https://hermes-agent.nousresearch.com/docs/user-guide/features/api-server/
|
|
55
|
-
- Hermes Profiles: https://hermes-agent.nousresearch.com/docs/user-guide/profiles/
|
|
56
|
-
- GoodVibes daemon: `@pellux/goodvibes-sdk@0.33.35` public operator contract plus `/api/goodvibes-agent/knowledge/*`
|
|
57
|
-
|
|
58
|
-
The benchmark measures two different GoodVibes layers:
|
|
59
|
-
|
|
60
|
-
- daemon capability: what the externally owned GoodVibes daemon can already expose through public operator routes;
|
|
61
|
-
- Agent usability: what GoodVibes Agent makes configurable, visible, safe, and usable from day one.
|
|
62
|
-
|
|
63
|
-
If the daemon already has a route but Agent lacks a good setup/workspace/CLI surface, the gap is treated as an Agent product gap rather than a missing platform capability.
|
|
64
|
-
|
|
65
|
-
Use `goodvibes-agent capabilities daemon` for the live read-only daemon audit. It checks the public control-plane method catalog, route risk posture, and the isolated Agent Knowledge status route. Use `goodvibes-agent capabilities daemon inventory` for the full public daemon method inventory grouped by category, access, HTTP method, and dangerous flag. Use `goodvibes-agent capabilities daemon gaps` to convert that daemon-measured audit into a prioritized gap plan with `version_mismatch`, `agent_route_missing`, `required_method_missing`, `route_risk_review`, and `agent_ux_gap` rows. Use `goodvibes-agent capabilities daemon risk` or `/approval risk` for a route-risk-aware approval-center view over read-only, mutating, dangerous, and authenticated route metadata. These commands intentionally avoid default `/api/knowledge/*`, HomeGraph, and Home Assistant routes.
|
|
66
|
-
|
|
67
|
-
## Capability Targets
|
|
68
|
-
|
|
69
|
-
| Area | OpenClaw/Hermes Baseline | GoodVibes Agent Position |
|
|
70
|
-
| --- | --- | --- |
|
|
71
|
-
| Terminal operator UI | Interactive CLI/TUI, commands, sessions | Near-fork GoodVibes TUI compositor/input/fullscreen foundation |
|
|
72
|
-
| Always-on gateway | Gateway/service owns channels, sessions, tools, events | External GoodVibes daemon exposes sessions, companion chat, channels, remote peers, approvals, automation, schedules, artifacts, MCP, providers, voice, media, web search, and isolated Agent Knowledge; Agent never owns daemon lifecycle |
|
|
73
|
-
| Channels | WhatsApp, Telegram, Slack, Discord, Signal, iMessage, web chat | GoodVibes daemon channel and companion surfaces with Agent-side policy, a Channels operator workspace, and per-channel readiness/risk labels |
|
|
74
|
-
| Knowledge/memory | Durable memory, semantic search, wiki/claim layers | Isolated `/api/goodvibes-agent/knowledge/*` routes with workspace ask/search/ingest/review flows plus local memory/skills/personas/routines |
|
|
75
|
-
| Skills/procedural memory | Skills directories, registries, skill lifecycle | Local Agent skills with review/stale/source/provenance fields |
|
|
76
|
-
| Scheduling | Natural-language cron, run/pause/resume/edit/remove, delivery | Local routines can be explicitly promoted to external daemon `schedules.create` with `--yes` and optional explicit delivery targets; redacted local promotion receipts are reviewable and can be reconciled with live `schedules.list`; hidden model scheduling and local scheduler spawns are blocked |
|
|
77
|
-
| Tools/MCP | Broad toolsets, MCP, browser, media, terminal, files | GoodVibes daemon exposes MCP, artifacts, web search, providers, media, multimodal, and channel tool routes; Agent adds policy guards and operator setup surfaces |
|
|
78
|
-
| Voice/media/canvas/nodes | Voice, TTS, mobile nodes, live canvas, browser automation | GoodVibes daemon exposes voice, media, multimodal, artifacts, and remote/node routes; Agent workspace makes setup and posture visible without daemon ownership |
|
|
79
|
-
| Build/code work | Direct terminal/file/code tools and subagents | Explicit delegation to GoodVibes TUI; local WRFC/spawn fanout blocked |
|
|
80
|
-
| Profiles | Independent profiles with own config/memory/skills/gateway | `GOODVIBES_AGENT_HOME` and named `--agent-profile` homes isolate Agent-local state; starter templates seed local personas/skills/routines; starter JSON can be exported/imported for local custom lanes; `/agent-profile guide` brings starter authoring into the Agent workspace; daemon remains external |
|
|
81
|
-
| Security | DM pairing, approvals, sandboxing, allowlists | Daemon approvals, auth diagnostics, secret refs, confirmation gates, model-tool policy |
|
|
82
|
-
|
|
83
|
-
## Exceed Targets
|
|
84
|
-
|
|
85
|
-
GoodVibes Agent should exceed OpenClaw/Hermes by making these properties true from day one:
|
|
86
|
-
|
|
87
|
-
- Capability surfaces are discoverable through `goodvibes-agent capabilities`, `goodvibes-agent capabilities daemon`, `goodvibes-agent capabilities daemon inventory`, `goodvibes-agent capabilities daemon gaps`, `goodvibes-agent capabilities daemon risk`, `/capabilities`, `/capabilities daemon`, `/approval risk`, onboarding, and the operator workspace.
|
|
88
|
-
- Agent Knowledge isolation is a release gate, not a convention.
|
|
89
|
-
- Routine-to-schedule promotion preserves Agent Knowledge isolation, uses only public external daemon schedule routes, supports explicit delivery targets, and stores redacted receipts.
|
|
90
|
-
- Model-visible tools are policy-gated for serial, non-secret, non-destructive use.
|
|
91
|
-
- Personal assistant state is Agent-local unless an explicit Agent Knowledge ingest route is used.
|
|
92
|
-
- Build work is delegated to the product that owns coding execution instead of turning the personal operator into a second coding TUI.
|
|
93
|
-
- Release gates prove package installability, Bun/TypeScript-only source, external-daemon posture, no authored JavaScript, no explicit `any`, and no forbidden default wiki/HomeGraph package-facing docs.
|
|
94
|
-
|
|
95
|
-
## Current Gaps To Close
|
|
96
|
-
|
|
97
|
-
- Live daemon account health and last delivery errors in the Channels workspace once a stable read-only route is available.
|
|
98
|
-
- Artifact and multimodal Agent Knowledge ingest affordances once Agent-specific routes are stable.
|
|
99
|
-
- Visual starter-template editing inside the fullscreen Agent workspace after the command-guided authoring path.
|
|
100
|
-
- Artifact and multimodal Agent Knowledge ingestion when the isolated Agent route accepts artifact-backed media.
|
|
101
|
-
- Deeper live run/delivery history and delivery error surfacing for promoted routines.
|
|
102
|
-
- Delegation receipts and artifact review inside the operator workspace.
|
|
103
|
-
- Saved policy presets for the route-risk-aware approval center.
|
|
104
|
-
- Intent-gated tool exposure so the model sees fewer irrelevant tools per turn while retaining broad capability coverage.
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import type { CliCommandOutput } from './types.ts';
|
|
2
|
-
import type { CliCommandRuntime } from './management.ts';
|
|
3
|
-
import {
|
|
4
|
-
buildOperatorCapabilityBenchmarkReport,
|
|
5
|
-
filterOperatorCapabilities,
|
|
6
|
-
renderOperatorCapabilityBenchmark,
|
|
7
|
-
} from '../operator/capability-benchmark.ts';
|
|
8
|
-
import {
|
|
9
|
-
buildDaemonCapabilityGapReport,
|
|
10
|
-
buildDaemonCapabilityRouteRiskReport,
|
|
11
|
-
fetchLiveDaemonCapabilityAudit,
|
|
12
|
-
fetchLiveDaemonCapabilityInventory,
|
|
13
|
-
filterDaemonCapabilityAuditAreas,
|
|
14
|
-
filterDaemonCapabilityGaps,
|
|
15
|
-
filterDaemonCapabilityInventoryGroups,
|
|
16
|
-
filterDaemonCapabilityRouteRiskAreas,
|
|
17
|
-
renderDaemonCapabilityAudit,
|
|
18
|
-
renderDaemonCapabilityFailure,
|
|
19
|
-
renderDaemonCapabilityGaps,
|
|
20
|
-
renderDaemonCapabilityInventory,
|
|
21
|
-
renderDaemonCapabilityRouteRisk,
|
|
22
|
-
} from '../operator/daemon-capability-audit.ts';
|
|
23
|
-
import { resolveAgentDaemonConnection } from '../agent/routine-schedule-promotion.ts';
|
|
24
|
-
|
|
25
|
-
interface CapabilityCommandArgs {
|
|
26
|
-
readonly mode: 'benchmark' | 'daemon' | 'daemon-gaps' | 'daemon-risk' | 'daemon-inventory';
|
|
27
|
-
readonly query: string | undefined;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function readCapabilityArgs(args: readonly string[]): CapabilityCommandArgs {
|
|
31
|
-
const values = args.filter((arg) => !arg.startsWith('--'));
|
|
32
|
-
if (values[0] === 'gaps') {
|
|
33
|
-
const query = values.slice(1).join(' ').trim();
|
|
34
|
-
return { mode: 'daemon-gaps', query: query.length > 0 ? query : undefined };
|
|
35
|
-
}
|
|
36
|
-
if (values[0] === 'daemon') {
|
|
37
|
-
if (values[1] === 'gaps') {
|
|
38
|
-
const query = values.slice(2).join(' ').trim();
|
|
39
|
-
return { mode: 'daemon-gaps', query: query.length > 0 ? query : undefined };
|
|
40
|
-
}
|
|
41
|
-
if (values[1] === 'risk' || values[1] === 'route-risk') {
|
|
42
|
-
const query = values.slice(2).join(' ').trim();
|
|
43
|
-
return { mode: 'daemon-risk', query: query.length > 0 ? query : undefined };
|
|
44
|
-
}
|
|
45
|
-
if (values[1] === 'inventory' || values[1] === 'methods' || values[1] === 'routes') {
|
|
46
|
-
const query = values.slice(2).join(' ').trim();
|
|
47
|
-
return { mode: 'daemon-inventory', query: query.length > 0 ? query : undefined };
|
|
48
|
-
}
|
|
49
|
-
const query = values.slice(1).join(' ').trim();
|
|
50
|
-
return { mode: 'daemon', query: query.length > 0 ? query : undefined };
|
|
51
|
-
}
|
|
52
|
-
return { mode: 'benchmark', query: values.length > 0 ? values.join(' ') : undefined };
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export async function handleCapabilitiesCommand(runtime: CliCommandRuntime): Promise<CliCommandOutput> {
|
|
56
|
-
const args = readCapabilityArgs(runtime.cli.commandArgs);
|
|
57
|
-
if (args.mode === 'daemon') {
|
|
58
|
-
const connection = resolveAgentDaemonConnection(runtime.configManager, runtime.homeDirectory);
|
|
59
|
-
const audit = await fetchLiveDaemonCapabilityAudit(connection);
|
|
60
|
-
if (!audit.ok) {
|
|
61
|
-
return {
|
|
62
|
-
output: runtime.cli.flags.outputFormat === 'json'
|
|
63
|
-
? JSON.stringify(audit, null, 2)
|
|
64
|
-
: renderDaemonCapabilityFailure(audit),
|
|
65
|
-
exitCode: audit.kind === 'auth_required' || audit.kind === 'daemon_unavailable' ? 1 : 2,
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
const areas = filterDaemonCapabilityAuditAreas(audit.areas, args.query);
|
|
69
|
-
return {
|
|
70
|
-
output: runtime.cli.flags.outputFormat === 'json'
|
|
71
|
-
? JSON.stringify({ ...audit, areas }, null, 2)
|
|
72
|
-
: renderDaemonCapabilityAudit(audit, areas),
|
|
73
|
-
exitCode: 0,
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
if (args.mode === 'daemon-gaps') {
|
|
77
|
-
const connection = resolveAgentDaemonConnection(runtime.configManager, runtime.homeDirectory);
|
|
78
|
-
const audit = await fetchLiveDaemonCapabilityAudit(connection);
|
|
79
|
-
if (!audit.ok) {
|
|
80
|
-
return {
|
|
81
|
-
output: runtime.cli.flags.outputFormat === 'json'
|
|
82
|
-
? JSON.stringify(audit, null, 2)
|
|
83
|
-
: renderDaemonCapabilityFailure(audit),
|
|
84
|
-
exitCode: audit.kind === 'auth_required' || audit.kind === 'daemon_unavailable' ? 1 : 2,
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
const report = buildDaemonCapabilityGapReport(audit);
|
|
88
|
-
const gaps = filterDaemonCapabilityGaps(report.gaps, args.query);
|
|
89
|
-
return {
|
|
90
|
-
output: runtime.cli.flags.outputFormat === 'json'
|
|
91
|
-
? JSON.stringify({ ...report, matchedGapCount: gaps.length, gaps }, null, 2)
|
|
92
|
-
: renderDaemonCapabilityGaps(report, gaps),
|
|
93
|
-
exitCode: 0,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
if (args.mode === 'daemon-risk') {
|
|
97
|
-
const connection = resolveAgentDaemonConnection(runtime.configManager, runtime.homeDirectory);
|
|
98
|
-
const audit = await fetchLiveDaemonCapabilityAudit(connection);
|
|
99
|
-
if (!audit.ok) {
|
|
100
|
-
return {
|
|
101
|
-
output: runtime.cli.flags.outputFormat === 'json'
|
|
102
|
-
? JSON.stringify(audit, null, 2)
|
|
103
|
-
: renderDaemonCapabilityFailure(audit),
|
|
104
|
-
exitCode: audit.kind === 'auth_required' || audit.kind === 'daemon_unavailable' ? 1 : 2,
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
const report = buildDaemonCapabilityRouteRiskReport(audit);
|
|
108
|
-
const areas = filterDaemonCapabilityRouteRiskAreas(report.areas, args.query);
|
|
109
|
-
return {
|
|
110
|
-
output: runtime.cli.flags.outputFormat === 'json'
|
|
111
|
-
? JSON.stringify({ ...report, matchedAreaCount: areas.length, areas }, null, 2)
|
|
112
|
-
: renderDaemonCapabilityRouteRisk(report, areas),
|
|
113
|
-
exitCode: 0,
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
if (args.mode === 'daemon-inventory') {
|
|
117
|
-
const connection = resolveAgentDaemonConnection(runtime.configManager, runtime.homeDirectory);
|
|
118
|
-
const inventory = await fetchLiveDaemonCapabilityInventory(connection);
|
|
119
|
-
if (!inventory.ok) {
|
|
120
|
-
return {
|
|
121
|
-
output: runtime.cli.flags.outputFormat === 'json'
|
|
122
|
-
? JSON.stringify(inventory, null, 2)
|
|
123
|
-
: renderDaemonCapabilityFailure(inventory),
|
|
124
|
-
exitCode: inventory.kind === 'auth_required' || inventory.kind === 'daemon_unavailable' ? 1 : 2,
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
const groups = filterDaemonCapabilityInventoryGroups(inventory.groups, args.query);
|
|
128
|
-
return {
|
|
129
|
-
output: runtime.cli.flags.outputFormat === 'json'
|
|
130
|
-
? JSON.stringify({ ...inventory, matchedGroupCount: groups.length, groups }, null, 2)
|
|
131
|
-
: renderDaemonCapabilityInventory(inventory, groups),
|
|
132
|
-
exitCode: 0,
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
const report = buildOperatorCapabilityBenchmarkReport();
|
|
136
|
-
const capabilities = filterOperatorCapabilities(report.capabilities, args.query);
|
|
137
|
-
if (runtime.cli.flags.outputFormat === 'json') {
|
|
138
|
-
return {
|
|
139
|
-
output: JSON.stringify({ ...report, capabilities }, null, 2),
|
|
140
|
-
exitCode: 0,
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
return {
|
|
144
|
-
output: renderOperatorCapabilityBenchmark(capabilities),
|
|
145
|
-
exitCode: 0,
|
|
146
|
-
};
|
|
147
|
-
}
|