@pellux/goodvibes-agent 0.1.47 → 0.1.49
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 +18 -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 +75 -210
- 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/builtin/knowledge.ts +3 -3
- package/src/panels/builtin/shared.ts +3 -0
- package/src/panels/knowledge-panel.ts +80 -9
- package/src/panels/provider-health-domains.ts +1 -1
- package/src/panels/remote-panel.ts +2 -2
- package/src/renderer/agent-workspace.ts +39 -10
- package/src/runtime/bootstrap-core.ts +2 -0
- package/src/runtime/bootstrap-shell.ts +1 -0
- package/src/runtime/bootstrap.ts +1 -0
- package/src/tools/agent-context-policy.ts +2 -2
- package/src/tools/agent-local-registry-tool.ts +341 -0
- 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
package/CHANGELOG.md
CHANGED
|
@@ -2,33 +2,44 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to GoodVibes Agent will be recorded here.
|
|
4
4
|
|
|
5
|
+
## 0.1.49 - 2026-05-31
|
|
6
|
+
|
|
7
|
+
- 445e694 Show isolated Agent Knowledge in TUI panel
|
|
8
|
+
- 632d951 Add agent-local registry tool
|
|
9
|
+
- 4832355 Make agent setup workspace actionable
|
|
10
|
+
|
|
11
|
+
## 0.1.48 - 2026-05-31
|
|
12
|
+
|
|
13
|
+
- 67f8ce0 Remove audit remnants and surface setup checklist
|
|
14
|
+
- 34c3d0b Remove internal development-only surfaces
|
|
15
|
+
|
|
5
16
|
## 0.1.47 - 2026-05-31
|
|
6
17
|
|
|
7
|
-
- 2bb2b8a
|
|
18
|
+
- 2bb2b8a Internal cleanup before operator UX work
|
|
8
19
|
|
|
9
20
|
## 0.1.46 - 2026-05-31
|
|
10
21
|
|
|
11
|
-
- e0addfe
|
|
22
|
+
- e0addfe Internal cleanup before operator UX work
|
|
12
23
|
|
|
13
24
|
## 0.1.45 - 2026-05-31
|
|
14
25
|
|
|
15
|
-
- 0aa4b3e
|
|
26
|
+
- 0aa4b3e Approval UX cleanup
|
|
16
27
|
|
|
17
28
|
## 0.1.44 - 2026-05-31
|
|
18
29
|
|
|
19
|
-
- fdee09e
|
|
30
|
+
- fdee09e Internal cleanup before operator UX work
|
|
20
31
|
|
|
21
32
|
## 0.1.43 - 2026-05-31
|
|
22
33
|
|
|
23
|
-
- 3afba9c
|
|
34
|
+
- 3afba9c Approval UX cleanup
|
|
24
35
|
|
|
25
36
|
## 0.1.42 - 2026-05-31
|
|
26
37
|
|
|
27
|
-
- 3c84649
|
|
38
|
+
- 3c84649 Agent workspace cleanup
|
|
28
39
|
|
|
29
40
|
## 0.1.41 - 2026-05-31
|
|
30
41
|
|
|
31
|
-
- c108e13
|
|
42
|
+
- c108e13 Internal cleanup before operator UX work
|
|
32
43
|
|
|
33
44
|
## 0.1.40 - 2026-05-31
|
|
34
45
|
|
|
@@ -41,7 +52,6 @@ All notable changes to GoodVibes Agent will be recorded here.
|
|
|
41
52
|
## 0.1.38 - 2026-05-31
|
|
42
53
|
|
|
43
54
|
- 072503c Add routine schedule promotion receipts
|
|
44
|
-
- 5bb9801 Update automation capability benchmark
|
|
45
55
|
|
|
46
56
|
## 0.1.37 - 2026-05-31
|
|
47
57
|
|
|
@@ -85,8 +95,6 @@ All notable changes to GoodVibes Agent will be recorded here.
|
|
|
85
95
|
|
|
86
96
|
## 0.1.27 - 2026-05-31
|
|
87
97
|
|
|
88
|
-
- b5be172 Add capabilities CLI handler
|
|
89
|
-
- cafe1fb Add Agent capability benchmark surface
|
|
90
98
|
|
|
91
99
|
## 0.1.26 - 2026-05-31
|
|
92
100
|
|
package/README.md
CHANGED
|
@@ -15,12 +15,8 @@ Install the public alpha package with Bun:
|
|
|
15
15
|
bun add -g @pellux/goodvibes-agent
|
|
16
16
|
goodvibes-agent --help
|
|
17
17
|
goodvibes-agent status
|
|
18
|
-
goodvibes-agent
|
|
19
|
-
goodvibes-agent
|
|
20
|
-
goodvibes-agent capabilities daemon gaps
|
|
21
|
-
goodvibes-agent capabilities daemon risk
|
|
22
|
-
goodvibes-agent capabilities daemon inventory
|
|
23
|
-
goodvibes-agent capabilities daemon coverage
|
|
18
|
+
goodvibes-agent profiles templates
|
|
19
|
+
goodvibes-agent knowledge status
|
|
24
20
|
```
|
|
25
21
|
|
|
26
22
|
If Bun reports untrusted lifecycle dependencies, trust only the package and dependencies required by this package:
|
|
@@ -47,9 +43,7 @@ bun run package:install-check
|
|
|
47
43
|
bun run publish:check
|
|
48
44
|
```
|
|
49
45
|
|
|
50
|
-
Inside the Agent TUI, use `/agent`, `/home`, or `/operator` to open the operator workspace. It is the Agent-first fullscreen surface for setup, status,
|
|
51
|
-
|
|
52
|
-
Use `goodvibes-agent capabilities` or `/capabilities` to inspect the OpenClaw/Hermes benchmark, current Agent posture, configuration commands, usage paths, and remaining gaps. Use `goodvibes-agent capabilities daemon` or `/capabilities daemon` for a live read-only audit of the GoodVibes daemon method catalog, route risk posture, and isolated Agent Knowledge route coverage. Use `goodvibes-agent capabilities daemon inventory` for the full public daemon method inventory grouped by category, access, HTTP posture, and dangerous flags. Use `goodvibes-agent capabilities daemon coverage` to map every daemon method to Agent UX posture: usable, read-only observable, explicit-confirmation, blocked, or not surfaced. Use `goodvibes-agent capabilities daemon gaps` or `/capabilities daemon gaps` to turn that live daemon audit into a prioritized gap plan that separates missing daemon routes from Agent UX work. Use `goodvibes-agent capabilities daemon risk` or `/approval risk` for route-risk-aware approval posture without mutating approval state.
|
|
46
|
+
Inside the Agent TUI, use `/agent`, `/home`, or `/operator` to open the operator workspace. It is the Agent-first fullscreen surface for setup, status, knowledge, local memory/skills, work-plan/approval review, automation observability, and explicit build delegation to GoodVibes TUI.
|
|
53
47
|
|
|
54
48
|
Inside the workspace, use `/agent-profile guide` to author custom profile starters without leaving the Agent TUI. The guided flow lists starters, exports starter JSON, imports edited local starters, and creates isolated runtime profiles from them.
|
|
55
49
|
|
|
@@ -86,19 +80,6 @@ Starting a routine records local usage and prints its steps; it does not spawn b
|
|
|
86
80
|
|
|
87
81
|
Start or restart the daemon from GoodVibes TUI or the daemon host before launching Agent. Agent status and companion/knowledge routes connect to that external daemon, normally on `http://127.0.0.1:3421`.
|
|
88
82
|
|
|
89
|
-
To verify what the running daemon can expose for the Agent/OpenClaw/Hermes capability benchmark:
|
|
90
|
-
|
|
91
|
-
```sh
|
|
92
|
-
goodvibes-agent capabilities daemon
|
|
93
|
-
goodvibes-agent capabilities daemon --json
|
|
94
|
-
goodvibes-agent capabilities daemon gaps
|
|
95
|
-
goodvibes-agent capabilities daemon risk
|
|
96
|
-
goodvibes-agent capabilities daemon inventory
|
|
97
|
-
goodvibes-agent capabilities daemon coverage
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
This audit checks `/api/control-plane/methods` and `/api/goodvibes-agent/knowledge/status`. The gap plan, route-risk review, and full method inventory are derived from read-only daemon calls. None of these commands query default Knowledge/Wiki or HomeGraph.
|
|
101
|
-
|
|
102
83
|
Agent intentionally blocks daemon lifecycle commands:
|
|
103
84
|
|
|
104
85
|
```sh
|
|
@@ -122,7 +103,6 @@ GoodVibes TUI owns coding execution: file edits, git/worktree workflows, coding
|
|
|
122
103
|
Package-facing docs are intentionally narrow during the near-fork baseline:
|
|
123
104
|
|
|
124
105
|
- [Getting Started](docs/getting-started.md)
|
|
125
|
-
- [Operator Capability Benchmark](docs/operator-capability-benchmark.md)
|
|
126
106
|
- [Deployment And Services](docs/deployment-and-services.md)
|
|
127
107
|
- [Release And Publishing](docs/release-and-publishing.md)
|
|
128
108
|
|
package/docs/README.md
CHANGED
|
@@ -7,7 +7,6 @@ GoodVibes Agent is a near-fork of the GoodVibes terminal foundation with a diffe
|
|
|
7
7
|
Current package docs:
|
|
8
8
|
|
|
9
9
|
- [Getting Started](getting-started.md)
|
|
10
|
-
- [Operator Capability Benchmark](operator-capability-benchmark.md)
|
|
11
10
|
- [Deployment And Services](deployment-and-services.md)
|
|
12
11
|
- [Release And Publishing](release-and-publishing.md)
|
|
13
12
|
|
|
@@ -19,7 +18,6 @@ Important baseline constraints:
|
|
|
19
18
|
- Agent connects to an externally managed daemon.
|
|
20
19
|
- Agent does not start, stop, restart, install, uninstall, or own daemon/listener/web/service lifecycle.
|
|
21
20
|
- Agent Knowledge/Wiki uses only `/api/goodvibes-agent/knowledge/*`; there is no default Knowledge/Wiki, HomeGraph, or Home Assistant fallback.
|
|
22
|
-
- Agent exposes `goodvibes-agent capabilities` and `/capabilities` to compare OpenClaw/Hermes capability targets against current Agent readiness and configuration paths.
|
|
23
21
|
- Agent supports isolated runtime homes with `GOODVIBES_AGENT_HOME=<path>` and named profile homes with `goodvibes-agent profiles create <name> --template <starter> --yes` plus `--agent-profile <name>`.
|
|
24
22
|
- Agent ships starter profile templates for household, research, travel, operations, and personal productivity local state; `profiles templates export/import` and `/agent-profile guide` support local custom starters.
|
|
25
23
|
- Local personas, routines, and Agent skills are stored under the Agent surface root and are injected only into the serial Agent conversation.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pellux/goodvibes-agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.49",
|
|
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",
|
|
@@ -33,7 +33,6 @@
|
|
|
33
33
|
"CHANGELOG.md",
|
|
34
34
|
"docs/README.md",
|
|
35
35
|
"docs/getting-started.md",
|
|
36
|
-
"docs/operator-capability-benchmark.md",
|
|
37
36
|
"docs/deployment-and-services.md",
|
|
38
37
|
"docs/release-and-publishing.md"
|
|
39
38
|
],
|
|
@@ -64,7 +63,6 @@
|
|
|
64
63
|
"build:all": "bun run scripts/build.ts --all",
|
|
65
64
|
"perf:check": "bun run scripts/perf-check.ts",
|
|
66
65
|
"architecture:check": "bun run scripts/check-architecture.ts",
|
|
67
|
-
"audit:home": "bun run scripts/audit-goodvibes-home.ts",
|
|
68
66
|
"foundation:artifacts": "bun run scripts/export-foundation-artifacts.ts",
|
|
69
67
|
"verification:ledger": "bun run scripts/verification-ledger.ts",
|
|
70
68
|
"verification:live": "bun run scripts/verify-live.ts",
|
package/src/cli/completion.ts
CHANGED
package/src/cli/help.ts
CHANGED
|
@@ -42,7 +42,6 @@ export function renderGoodVibesHelp(binary = 'goodvibes-agent'): string {
|
|
|
42
42
|
' routines Inspect local routines and explicitly promote one to a daemon schedule',
|
|
43
43
|
' auth Inspect and manage local users, sessions, and bootstrap auth',
|
|
44
44
|
' compat Inspect Agent SDK pin, daemon version, and Agent knowledge route readiness',
|
|
45
|
-
' capabilities Show OpenClaw/Hermes benchmark and live daemon coverage',
|
|
46
45
|
' knowledge Use isolated Agent Knowledge/Wiki routes',
|
|
47
46
|
' ask|search Shortcuts for isolated Agent Knowledge ask/search',
|
|
48
47
|
' delegate Explicitly delegate build/fix/review work to GoodVibes TUI',
|
|
@@ -101,12 +100,6 @@ export function renderGoodVibesHelp(binary = 'goodvibes-agent'): string {
|
|
|
101
100
|
` ${binary} --agent-profile household`,
|
|
102
101
|
` ${binary} routines promote daily-operations-sweep --cron "0 9 * * *" --timezone America/Chicago --yes`,
|
|
103
102
|
` ${binary} compat`,
|
|
104
|
-
` ${binary} capabilities`,
|
|
105
|
-
` ${binary} capabilities daemon`,
|
|
106
|
-
` ${binary} capabilities daemon gaps`,
|
|
107
|
-
` ${binary} capabilities daemon risk`,
|
|
108
|
-
` ${binary} capabilities daemon inventory`,
|
|
109
|
-
` ${binary} capabilities daemon coverage`,
|
|
110
103
|
` ${binary} knowledge status`,
|
|
111
104
|
` ${binary} knowledge ask "What is GoodVibes Agent?"`,
|
|
112
105
|
` ${binary} ask "What is GoodVibes Agent?"`,
|
|
@@ -200,11 +193,6 @@ const COMMAND_HELP: Record<string, CommandHelp> = {
|
|
|
200
193
|
summary: 'Inspect package SDK pin, live daemon version, and Agent-specific knowledge route readiness.',
|
|
201
194
|
examples: ['compat', 'compat --json'],
|
|
202
195
|
},
|
|
203
|
-
capabilities: {
|
|
204
|
-
usage: ['capabilities [openclaw|hermes|query]', 'capabilities daemon [query]', 'capabilities daemon gaps [query]', 'capabilities daemon risk [query]', 'capabilities daemon inventory [query]', 'capabilities daemon coverage [query]', 'capabilities --json'],
|
|
205
|
-
summary: 'Show the OpenClaw/Hermes capability benchmark, Agent readiness, live GoodVibes daemon method coverage, route risk, and daemon-measured product gaps.',
|
|
206
|
-
examples: ['capabilities', 'capabilities hermes', 'capabilities daemon', 'capabilities daemon gaps', 'capabilities daemon risk --json', 'capabilities daemon inventory channels --json', 'capabilities daemon coverage not_surfaced'],
|
|
207
|
-
},
|
|
208
196
|
knowledge: {
|
|
209
197
|
usage: [
|
|
210
198
|
'knowledge status',
|
package/src/cli/management.ts
CHANGED
|
@@ -33,7 +33,6 @@ import { handleBundleCommand } from './bundle-command.ts';
|
|
|
33
33
|
import { buildListenerTestResult, formatListenerTestResult, handleSurfacesCommand } from './surface-command.ts';
|
|
34
34
|
import { buildControlPlaneStatusResult, formatControlPlaneStatus, handleSecrets, handleSessions, handleTasks, renderPairing, renderRemote, renderSubscriptions, renderWeb } from './management-commands.ts';
|
|
35
35
|
import { handleAgentKnowledgeCommand, handleAgentKnowledgeShortcutCommand, handleCompatCommand, handleDelegateCommand } from './agent-knowledge-command.ts';
|
|
36
|
-
import { handleCapabilitiesCommand } from './capabilities-command.ts';
|
|
37
36
|
import { handleProfilesCommand } from './profiles-command.ts';
|
|
38
37
|
import { handleRoutinesCommand } from './routines-command.ts';
|
|
39
38
|
import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
|
|
@@ -701,11 +700,6 @@ export async function handleGoodVibesCliCommand(runtime: CliCommandRuntime): Pro
|
|
|
701
700
|
console.log(result.output);
|
|
702
701
|
return { handled: true, exitCode: result.exitCode };
|
|
703
702
|
}
|
|
704
|
-
case 'capabilities': {
|
|
705
|
-
const result = await handleCapabilitiesCommand(runtime);
|
|
706
|
-
console.log(result.output);
|
|
707
|
-
return { handled: true, exitCode: result.exitCode };
|
|
708
|
-
}
|
|
709
703
|
case 'profiles': {
|
|
710
704
|
const result = await handleProfilesCommand(runtime);
|
|
711
705
|
console.log(result.output);
|
package/src/cli/parser.ts
CHANGED
|
@@ -32,10 +32,6 @@ const COMMAND_ALIASES: Readonly<Record<string, GoodVibesCliCommand>> = {
|
|
|
32
32
|
auth: 'auth',
|
|
33
33
|
compat: 'compat',
|
|
34
34
|
compatibility: 'compat',
|
|
35
|
-
capabilities: 'capabilities',
|
|
36
|
-
capability: 'capabilities',
|
|
37
|
-
caps: 'capabilities',
|
|
38
|
-
benchmark: 'capabilities',
|
|
39
35
|
knowledge: 'knowledge',
|
|
40
36
|
know: 'knowledge',
|
|
41
37
|
kb: 'knowledge',
|
package/src/cli/types.ts
CHANGED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import type { CommandContext } from './command-registry.ts';
|
|
2
|
+
|
|
3
|
+
export type AgentWorkspaceChannelRisk = 'dm' | 'group' | 'public' | 'webhook' | 'bridge';
|
|
4
|
+
|
|
5
|
+
export interface AgentWorkspaceChannelStatus {
|
|
6
|
+
readonly id: string;
|
|
7
|
+
readonly label: string;
|
|
8
|
+
readonly enabled: boolean;
|
|
9
|
+
readonly ready: boolean;
|
|
10
|
+
readonly missingConfigCount: number;
|
|
11
|
+
readonly defaultTarget: 'configured' | 'missing' | 'not-required';
|
|
12
|
+
readonly delivery: 'disabled' | 'blocked' | 'explicit-target' | 'default-ready';
|
|
13
|
+
readonly risk: AgentWorkspaceChannelRisk;
|
|
14
|
+
readonly riskLabel: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface AgentWorkspaceConfigReader {
|
|
18
|
+
get(key: string): unknown;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface AgentWorkspaceChannelSpec {
|
|
22
|
+
readonly id: string;
|
|
23
|
+
readonly label: string;
|
|
24
|
+
readonly enabledKey: string;
|
|
25
|
+
readonly requiredKeys: readonly string[];
|
|
26
|
+
readonly defaultTargetKeys: readonly string[];
|
|
27
|
+
readonly risk: AgentWorkspaceChannelRisk;
|
|
28
|
+
readonly riskLabel: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const AGENT_WORKSPACE_CHANNEL_SPECS: readonly AgentWorkspaceChannelSpec[] = [
|
|
32
|
+
{
|
|
33
|
+
id: 'slack',
|
|
34
|
+
label: 'Slack',
|
|
35
|
+
enabledKey: 'surfaces.slack.enabled',
|
|
36
|
+
requiredKeys: ['surfaces.slack.botToken', 'surfaces.slack.signingSecret'],
|
|
37
|
+
defaultTargetKeys: ['surfaces.slack.defaultChannel'],
|
|
38
|
+
risk: 'group',
|
|
39
|
+
riskLabel: 'workspace/group channel',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: 'discord',
|
|
43
|
+
label: 'Discord',
|
|
44
|
+
enabledKey: 'surfaces.discord.enabled',
|
|
45
|
+
requiredKeys: ['surfaces.discord.botToken', 'surfaces.discord.publicKey', 'surfaces.discord.applicationId'],
|
|
46
|
+
defaultTargetKeys: ['surfaces.discord.defaultChannelId'],
|
|
47
|
+
risk: 'group',
|
|
48
|
+
riskLabel: 'server/channel delivery',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: 'telegram',
|
|
52
|
+
label: 'Telegram',
|
|
53
|
+
enabledKey: 'surfaces.telegram.enabled',
|
|
54
|
+
requiredKeys: ['surfaces.telegram.botToken'],
|
|
55
|
+
defaultTargetKeys: ['surfaces.telegram.defaultChatId'],
|
|
56
|
+
risk: 'dm',
|
|
57
|
+
riskLabel: 'bot DM/group delivery',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: 'ntfy',
|
|
61
|
+
label: 'ntfy',
|
|
62
|
+
enabledKey: 'surfaces.ntfy.enabled',
|
|
63
|
+
requiredKeys: ['surfaces.ntfy.baseUrl', 'surfaces.ntfy.chatTopic', 'surfaces.ntfy.agentTopic'],
|
|
64
|
+
defaultTargetKeys: ['surfaces.ntfy.topic'],
|
|
65
|
+
risk: 'public',
|
|
66
|
+
riskLabel: 'topic-based public/private feed',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: 'googleChat',
|
|
70
|
+
label: 'Google Chat',
|
|
71
|
+
enabledKey: 'surfaces.googleChat.enabled',
|
|
72
|
+
requiredKeys: ['surfaces.googleChat.webhookUrl', 'surfaces.googleChat.verificationToken'],
|
|
73
|
+
defaultTargetKeys: ['surfaces.googleChat.spaceId'],
|
|
74
|
+
risk: 'group',
|
|
75
|
+
riskLabel: 'space delivery',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: 'signal',
|
|
79
|
+
label: 'Signal',
|
|
80
|
+
enabledKey: 'surfaces.signal.enabled',
|
|
81
|
+
requiredKeys: ['surfaces.signal.bridgeUrl', 'surfaces.signal.account'],
|
|
82
|
+
defaultTargetKeys: ['surfaces.signal.defaultRecipient'],
|
|
83
|
+
risk: 'bridge',
|
|
84
|
+
riskLabel: 'private bridge delivery',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
id: 'whatsapp',
|
|
88
|
+
label: 'WhatsApp',
|
|
89
|
+
enabledKey: 'surfaces.whatsapp.enabled',
|
|
90
|
+
requiredKeys: ['surfaces.whatsapp.accessToken', 'surfaces.whatsapp.verifyToken', 'surfaces.whatsapp.phoneNumberId'],
|
|
91
|
+
defaultTargetKeys: ['surfaces.whatsapp.defaultRecipient'],
|
|
92
|
+
risk: 'dm',
|
|
93
|
+
riskLabel: 'phone-number delivery',
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: 'imessage',
|
|
97
|
+
label: 'iMessage',
|
|
98
|
+
enabledKey: 'surfaces.imessage.enabled',
|
|
99
|
+
requiredKeys: ['surfaces.imessage.bridgeUrl', 'surfaces.imessage.account'],
|
|
100
|
+
defaultTargetKeys: ['surfaces.imessage.defaultChatId'],
|
|
101
|
+
risk: 'bridge',
|
|
102
|
+
riskLabel: 'Apple bridge delivery',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
id: 'bluebubbles',
|
|
106
|
+
label: 'BlueBubbles',
|
|
107
|
+
enabledKey: 'surfaces.bluebubbles.enabled',
|
|
108
|
+
requiredKeys: ['surfaces.bluebubbles.serverUrl', 'surfaces.bluebubbles.password'],
|
|
109
|
+
defaultTargetKeys: ['surfaces.bluebubbles.defaultChatGuid'],
|
|
110
|
+
risk: 'bridge',
|
|
111
|
+
riskLabel: 'iMessage bridge delivery',
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
id: 'msteams',
|
|
115
|
+
label: 'Microsoft Teams',
|
|
116
|
+
enabledKey: 'surfaces.msteams.enabled',
|
|
117
|
+
requiredKeys: ['surfaces.msteams.appId', 'surfaces.msteams.appPassword'],
|
|
118
|
+
defaultTargetKeys: ['surfaces.msteams.defaultConversationId', 'surfaces.msteams.defaultChannelId'],
|
|
119
|
+
risk: 'group',
|
|
120
|
+
riskLabel: 'tenant/channel delivery',
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
id: 'mattermost',
|
|
124
|
+
label: 'Mattermost',
|
|
125
|
+
enabledKey: 'surfaces.mattermost.enabled',
|
|
126
|
+
requiredKeys: ['surfaces.mattermost.baseUrl', 'surfaces.mattermost.botToken'],
|
|
127
|
+
defaultTargetKeys: ['surfaces.mattermost.defaultChannelId'],
|
|
128
|
+
risk: 'group',
|
|
129
|
+
riskLabel: 'team/channel delivery',
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
id: 'matrix',
|
|
133
|
+
label: 'Matrix',
|
|
134
|
+
enabledKey: 'surfaces.matrix.enabled',
|
|
135
|
+
requiredKeys: ['surfaces.matrix.homeserverUrl', 'surfaces.matrix.accessToken'],
|
|
136
|
+
defaultTargetKeys: ['surfaces.matrix.defaultRoomId'],
|
|
137
|
+
risk: 'group',
|
|
138
|
+
riskLabel: 'room delivery',
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
id: 'webhook',
|
|
142
|
+
label: 'Webhook',
|
|
143
|
+
enabledKey: 'surfaces.webhook.enabled',
|
|
144
|
+
requiredKeys: ['surfaces.webhook.defaultTarget'],
|
|
145
|
+
defaultTargetKeys: ['surfaces.webhook.defaultTarget'],
|
|
146
|
+
risk: 'webhook',
|
|
147
|
+
riskLabel: 'external HTTP delivery',
|
|
148
|
+
},
|
|
149
|
+
];
|
|
150
|
+
|
|
151
|
+
function configValue(context: CommandContext, key: string): unknown {
|
|
152
|
+
const configManager = context.platform?.configManager as AgentWorkspaceConfigReader | undefined;
|
|
153
|
+
return configManager?.get(key);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function readConfigBoolean(context: CommandContext, key: string, fallback: boolean): boolean {
|
|
157
|
+
try {
|
|
158
|
+
const value = configValue(context, key);
|
|
159
|
+
if (typeof value === 'boolean') return value;
|
|
160
|
+
if (typeof value === 'string') {
|
|
161
|
+
const normalized = value.trim().toLowerCase();
|
|
162
|
+
if (normalized === 'true') return true;
|
|
163
|
+
if (normalized === 'false') return false;
|
|
164
|
+
}
|
|
165
|
+
return fallback;
|
|
166
|
+
} catch {
|
|
167
|
+
return fallback;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function hasConfigValue(context: CommandContext, key: string): boolean {
|
|
172
|
+
try {
|
|
173
|
+
const value = configValue(context, key);
|
|
174
|
+
if (typeof value === 'string') return value.trim().length > 0;
|
|
175
|
+
if (typeof value === 'number') return Number.isFinite(value);
|
|
176
|
+
if (typeof value === 'boolean') return value;
|
|
177
|
+
return value !== null && value !== undefined;
|
|
178
|
+
} catch {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function buildChannelStatus(context: CommandContext, spec: AgentWorkspaceChannelSpec): AgentWorkspaceChannelStatus {
|
|
184
|
+
const enabled = readConfigBoolean(context, spec.enabledKey, false);
|
|
185
|
+
const missingConfigCount = spec.requiredKeys.filter((key) => !hasConfigValue(context, key)).length;
|
|
186
|
+
const defaultTarget = spec.defaultTargetKeys.length === 0
|
|
187
|
+
? 'not-required'
|
|
188
|
+
: spec.defaultTargetKeys.some((key) => hasConfigValue(context, key))
|
|
189
|
+
? 'configured'
|
|
190
|
+
: 'missing';
|
|
191
|
+
const ready = enabled && missingConfigCount === 0;
|
|
192
|
+
const delivery = !enabled
|
|
193
|
+
? 'disabled'
|
|
194
|
+
: !ready
|
|
195
|
+
? 'blocked'
|
|
196
|
+
: defaultTarget === 'configured'
|
|
197
|
+
? 'default-ready'
|
|
198
|
+
: 'explicit-target';
|
|
199
|
+
return {
|
|
200
|
+
id: spec.id,
|
|
201
|
+
label: spec.label,
|
|
202
|
+
enabled,
|
|
203
|
+
ready,
|
|
204
|
+
missingConfigCount,
|
|
205
|
+
defaultTarget,
|
|
206
|
+
delivery,
|
|
207
|
+
risk: spec.risk,
|
|
208
|
+
riskLabel: spec.riskLabel,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export function buildAgentWorkspaceChannels(context: CommandContext): readonly AgentWorkspaceChannelStatus[] {
|
|
213
|
+
return AGENT_WORKSPACE_CHANNEL_SPECS.map((spec) => buildChannelStatus(context, spec));
|
|
214
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
export type AgentWorkspaceSetupStatus = 'ready' | 'recommended' | 'optional' | 'blocked';
|
|
2
|
+
|
|
3
|
+
export interface AgentWorkspaceSetupChecklistItem {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly label: string;
|
|
6
|
+
readonly status: AgentWorkspaceSetupStatus;
|
|
7
|
+
readonly detail: string;
|
|
8
|
+
readonly command?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface AgentWorkspaceSetupChecklistInput {
|
|
12
|
+
readonly provider: string;
|
|
13
|
+
readonly model: string;
|
|
14
|
+
readonly daemonBaseUrl: string;
|
|
15
|
+
readonly sessionMemoryCount: number;
|
|
16
|
+
readonly routineCount: number;
|
|
17
|
+
readonly enabledRoutineCount: number;
|
|
18
|
+
readonly skillCount: number;
|
|
19
|
+
readonly enabledSkillCount: number;
|
|
20
|
+
readonly activePersonaName: string;
|
|
21
|
+
readonly readyChannelCount: number;
|
|
22
|
+
readonly voiceProviderCount: number;
|
|
23
|
+
readonly mediaProviderCount: number;
|
|
24
|
+
readonly runtimeProfileCount: number;
|
|
25
|
+
readonly runtimeStarterTemplateCount: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function setupStatusForCount(count: number, ready: AgentWorkspaceSetupStatus, empty: AgentWorkspaceSetupStatus): AgentWorkspaceSetupStatus {
|
|
29
|
+
return count > 0 ? ready : empty;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChecklistInput): readonly AgentWorkspaceSetupChecklistItem[] {
|
|
33
|
+
const providerReady = input.provider !== 'unknown' && input.model !== 'unknown';
|
|
34
|
+
const hasActivePersona = input.activePersonaName !== '(none)' && input.activePersonaName !== '(unavailable)';
|
|
35
|
+
return [
|
|
36
|
+
{
|
|
37
|
+
id: 'daemon',
|
|
38
|
+
label: 'External daemon',
|
|
39
|
+
status: 'ready',
|
|
40
|
+
detail: `Agent will connect to ${input.daemonBaseUrl}; daemon lifecycle stays external.`,
|
|
41
|
+
command: '/status',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: 'provider-model',
|
|
45
|
+
label: 'Provider and model',
|
|
46
|
+
status: providerReady ? 'ready' : 'blocked',
|
|
47
|
+
detail: providerReady
|
|
48
|
+
? `Current chat route is ${input.provider} / ${input.model}.`
|
|
49
|
+
: 'Choose a provider and model before relying on assistant turns.',
|
|
50
|
+
command: '/model',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: 'agent-knowledge',
|
|
54
|
+
label: 'Agent Knowledge',
|
|
55
|
+
status: 'recommended',
|
|
56
|
+
detail: 'Check isolated Agent Knowledge status, then ingest source-backed material into the Agent segment only.',
|
|
57
|
+
command: '/knowledge status',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: 'profile',
|
|
61
|
+
label: 'Runtime profile',
|
|
62
|
+
status: setupStatusForCount(input.runtimeProfileCount, 'ready', 'optional'),
|
|
63
|
+
detail: input.runtimeProfileCount > 0
|
|
64
|
+
? `${input.runtimeProfileCount} isolated runtime profile(s) are available.`
|
|
65
|
+
: `${input.runtimeStarterTemplateCount} starter template(s) are available if this machine needs separate operator identities.`,
|
|
66
|
+
command: '/agent-profile templates',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: 'persona',
|
|
70
|
+
label: 'Persona',
|
|
71
|
+
status: hasActivePersona ? 'ready' : 'recommended',
|
|
72
|
+
detail: hasActivePersona
|
|
73
|
+
? `Active persona: ${input.activePersonaName}.`
|
|
74
|
+
: 'Create or choose a persona to make the assistant voice and policy explicit.',
|
|
75
|
+
command: '/personas',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: 'skills',
|
|
79
|
+
label: 'Skills',
|
|
80
|
+
status: setupStatusForCount(input.enabledSkillCount, 'ready', input.skillCount > 0 ? 'recommended' : 'optional'),
|
|
81
|
+
detail: input.skillCount > 0
|
|
82
|
+
? `${input.enabledSkillCount}/${input.skillCount} local skill(s) enabled.`
|
|
83
|
+
: 'Create reusable local skills for repeated workflows.',
|
|
84
|
+
command: '/agent-skills',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
id: 'routines',
|
|
88
|
+
label: 'Routines',
|
|
89
|
+
status: setupStatusForCount(input.enabledRoutineCount, 'ready', input.routineCount > 0 ? 'recommended' : 'optional'),
|
|
90
|
+
detail: input.routineCount > 0
|
|
91
|
+
? `${input.enabledRoutineCount}/${input.routineCount} local routine(s) enabled.`
|
|
92
|
+
: 'Create local routines first; promote schedules only with explicit confirmation.',
|
|
93
|
+
command: '/routines',
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: 'memory',
|
|
97
|
+
label: 'Local memory',
|
|
98
|
+
status: setupStatusForCount(input.sessionMemoryCount, 'ready', 'optional'),
|
|
99
|
+
detail: input.sessionMemoryCount > 0
|
|
100
|
+
? `${input.sessionMemoryCount} session memory record(s) are available.`
|
|
101
|
+
: 'Memory starts empty; durable facts should be stored deliberately and never include secrets.',
|
|
102
|
+
command: '/memory',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
id: 'channels',
|
|
106
|
+
label: 'Channels',
|
|
107
|
+
status: setupStatusForCount(input.readyChannelCount, 'ready', 'optional'),
|
|
108
|
+
detail: input.readyChannelCount > 0
|
|
109
|
+
? `${input.readyChannelCount} external channel(s) are ready.`
|
|
110
|
+
: 'Pair or review channels only when you want the assistant reachable outside this terminal.',
|
|
111
|
+
command: '/pair',
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
id: 'voice-media',
|
|
115
|
+
label: 'Voice and media',
|
|
116
|
+
status: input.voiceProviderCount > 0 || input.mediaProviderCount > 0 ? 'ready' : 'optional',
|
|
117
|
+
detail: `${input.voiceProviderCount} voice provider(s), ${input.mediaProviderCount} media provider(s). Configure these only when useful.`,
|
|
118
|
+
command: '/config tts',
|
|
119
|
+
},
|
|
120
|
+
];
|
|
121
|
+
}
|