@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.
Files changed (36) hide show
  1. package/CHANGELOG.md +18 -10
  2. package/README.md +3 -23
  3. package/docs/README.md +0 -2
  4. package/package.json +1 -3
  5. package/src/cli/completion.ts +0 -1
  6. package/src/cli/help.ts +0 -12
  7. package/src/cli/management.ts +0 -6
  8. package/src/cli/package-verification.ts +0 -1
  9. package/src/cli/parser.ts +0 -4
  10. package/src/cli/types.ts +0 -1
  11. package/src/input/agent-workspace-channels.ts +214 -0
  12. package/src/input/agent-workspace-setup.ts +121 -0
  13. package/src/input/agent-workspace.ts +75 -210
  14. package/src/input/commands/experience-runtime.ts +2 -25
  15. package/src/input/commands/remote-runtime.ts +5 -5
  16. package/src/input/commands.ts +0 -2
  17. package/src/input/onboarding/onboarding-wizard-steps.ts +7 -7
  18. package/src/panels/builtin/knowledge.ts +3 -3
  19. package/src/panels/builtin/shared.ts +3 -0
  20. package/src/panels/knowledge-panel.ts +80 -9
  21. package/src/panels/provider-health-domains.ts +1 -1
  22. package/src/panels/remote-panel.ts +2 -2
  23. package/src/renderer/agent-workspace.ts +39 -10
  24. package/src/runtime/bootstrap-core.ts +2 -0
  25. package/src/runtime/bootstrap-shell.ts +1 -0
  26. package/src/runtime/bootstrap.ts +1 -0
  27. package/src/tools/agent-context-policy.ts +2 -2
  28. package/src/tools/agent-local-registry-tool.ts +341 -0
  29. package/src/verification/live-verifier.ts +0 -15
  30. package/src/version.ts +1 -1
  31. package/docs/operator-capability-benchmark.md +0 -106
  32. package/src/cli/capabilities-command.ts +0 -173
  33. package/src/config/goodvibes-home-audit.ts +0 -465
  34. package/src/input/commands/capabilities-runtime.ts +0 -102
  35. package/src/operator/capability-benchmark.ts +0 -244
  36. 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 Map daemon methods to Agent UX coverage
18
+ - 2bb2b8a Internal cleanup before operator UX work
8
19
 
9
20
  ## 0.1.46 - 2026-05-31
10
21
 
11
- - e0addfe Add full daemon capability inventory
22
+ - e0addfe Internal cleanup before operator UX work
12
23
 
13
24
  ## 0.1.45 - 2026-05-31
14
25
 
15
- - 0aa4b3e Add daemon route risk approval review
26
+ - 0aa4b3e Approval UX cleanup
16
27
 
17
28
  ## 0.1.44 - 2026-05-31
18
29
 
19
- - fdee09e Add daemon capability gap report
30
+ - fdee09e Internal cleanup before operator UX work
20
31
 
21
32
  ## 0.1.43 - 2026-05-31
22
33
 
23
- - 3afba9c Add daemon route risk coverage
34
+ - 3afba9c Approval UX cleanup
24
35
 
25
36
  ## 0.1.42 - 2026-05-31
26
37
 
27
- - 3c84649 Surface daemon capabilities in Agent workspace
38
+ - 3c84649 Agent workspace cleanup
28
39
 
29
40
  ## 0.1.41 - 2026-05-31
30
41
 
31
- - c108e13 Add live daemon capability audit
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 capabilities
19
- goodvibes-agent capabilities daemon
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, live daemon capability coverage, knowledge, local memory/skills, work-plan/approval review, automation observability, and explicit build delegation to GoodVibes TUI.
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.47",
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",
@@ -15,7 +15,6 @@ const COMMANDS = [
15
15
  'routines',
16
16
  'auth',
17
17
  'compat',
18
- 'capabilities',
19
18
  'knowledge',
20
19
  'ask',
21
20
  'search',
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',
@@ -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);
@@ -41,7 +41,6 @@ const REQUIRED_TARBALL_PATHS = [
41
41
  '.goodvibes/GOODVIBES.md',
42
42
  'docs/README.md',
43
43
  'docs/getting-started.md',
44
- 'docs/operator-capability-benchmark.md',
45
44
  'docs/deployment-and-services.md',
46
45
  'docs/release-and-publishing.md',
47
46
  ] as const;
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
@@ -13,7 +13,6 @@ export type GoodVibesCliCommand =
13
13
  | 'routines'
14
14
  | 'auth'
15
15
  | 'compat'
16
- | 'capabilities'
17
16
  | 'knowledge'
18
17
  | 'ask'
19
18
  | 'search'
@@ -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
+ }