@pellux/goodvibes-agent 0.1.114 → 0.1.117

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 (168) hide show
  1. package/CHANGELOG.md +41 -650
  2. package/README.md +40 -50
  3. package/dist/package/main.js +38224 -35673
  4. package/docs/README.md +5 -4
  5. package/docs/{connected-services.md → connected-host.md} +18 -10
  6. package/docs/getting-started.md +43 -42
  7. package/docs/release-and-publishing.md +6 -4
  8. package/package.json +3 -3
  9. package/src/agent/behavior-discovery-summary.ts +165 -0
  10. package/src/agent/persona-discovery.ts +1 -3
  11. package/src/agent/persona-registry.ts +5 -3
  12. package/src/agent/reminder-schedule-format.ts +6 -6
  13. package/src/agent/reminder-schedule.ts +1 -1
  14. package/src/agent/routine-registry.ts +43 -4
  15. package/src/agent/routine-schedule-format.ts +6 -6
  16. package/src/agent/routine-schedule-promotion.ts +1 -1
  17. package/src/agent/routine-schedule-receipts.ts +1 -1
  18. package/src/agent/runtime-profile-starters.ts +331 -0
  19. package/src/agent/runtime-profile.ts +228 -330
  20. package/src/agent/skill-registry.ts +190 -13
  21. package/src/cli/agent-knowledge-command.ts +2 -2
  22. package/src/cli/agent-knowledge-format.ts +2 -2
  23. package/src/cli/agent-knowledge-runtime.ts +1 -1
  24. package/src/cli/bundle-command.ts +1 -1
  25. package/src/cli/entrypoint.ts +16 -7
  26. package/src/cli/help.ts +26 -19
  27. package/src/cli/local-library-command.ts +75 -21
  28. package/src/cli/management-commands.ts +7 -6
  29. package/src/cli/management.ts +6 -51
  30. package/src/cli/parser.ts +23 -2
  31. package/src/cli/profiles-command.ts +247 -1
  32. package/src/cli/routines-command.ts +139 -11
  33. package/src/cli/service-posture.ts +11 -11
  34. package/src/cli/status.ts +21 -25
  35. package/src/input/agent-workspace-access-command-editor-submission.ts +149 -0
  36. package/src/input/agent-workspace-access-command-editors.ts +170 -0
  37. package/src/input/agent-workspace-activation.ts +2 -1
  38. package/src/input/agent-workspace-basic-command-editor-submission.ts +787 -0
  39. package/src/input/agent-workspace-basic-command-editors.ts +524 -459
  40. package/src/input/agent-workspace-categories.ts +177 -14
  41. package/src/input/agent-workspace-channel-command-editor-submission.ts +49 -0
  42. package/src/input/agent-workspace-channel-command-editors.ts +47 -0
  43. package/src/input/agent-workspace-command-editor.ts +25 -1
  44. package/src/input/agent-workspace-delegation-editor-submission.ts +55 -0
  45. package/src/input/agent-workspace-editors.ts +27 -0
  46. package/src/input/agent-workspace-knowledge-command-editor-submission.ts +132 -0
  47. package/src/input/agent-workspace-knowledge-command-editors.ts +110 -0
  48. package/src/input/agent-workspace-learned-behavior.ts +67 -0
  49. package/src/input/agent-workspace-library-command-editor-submission.ts +50 -0
  50. package/src/input/agent-workspace-library-command-editors.ts +35 -0
  51. package/src/input/agent-workspace-mcp-command-editor-submission.ts +95 -0
  52. package/src/input/agent-workspace-memory-command-editor-submission.ts +232 -0
  53. package/src/input/agent-workspace-memory-command-editors.ts +180 -0
  54. package/src/input/agent-workspace-navigation.ts +45 -0
  55. package/src/input/agent-workspace-notify-editor-submission.ts +107 -0
  56. package/src/input/agent-workspace-operations-command-editor-submission.ts +146 -0
  57. package/src/input/agent-workspace-operations-command-editors.ts +119 -0
  58. package/src/input/agent-workspace-provider-command-editor-submission.ts +155 -0
  59. package/src/input/agent-workspace-provider-command-editors.ts +93 -0
  60. package/src/input/agent-workspace-requirements.ts +11 -0
  61. package/src/input/agent-workspace-secret-editor-submission.ts +153 -0
  62. package/src/input/agent-workspace-session-command-editor-submission.ts +199 -0
  63. package/src/input/agent-workspace-session-command-editors.ts +249 -0
  64. package/src/input/agent-workspace-setup.ts +49 -19
  65. package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +101 -0
  66. package/src/input/agent-workspace-skill-bundle-command-editors.ts +110 -0
  67. package/src/input/agent-workspace-snapshot.ts +56 -8
  68. package/src/input/agent-workspace-task-command-editor-submission.ts +61 -0
  69. package/src/input/agent-workspace-task-command-editors.ts +47 -0
  70. package/src/input/agent-workspace-types.ts +124 -0
  71. package/src/input/agent-workspace-voice-media.ts +1 -1
  72. package/src/input/agent-workspace-workplan-editor-submission.ts +153 -0
  73. package/src/input/agent-workspace.ts +47 -37
  74. package/src/input/command-registry.ts +1 -1
  75. package/src/input/commands/agent-runtime-profile-runtime.ts +160 -6
  76. package/src/input/commands/agent-skills-runtime.ts +76 -12
  77. package/src/input/commands/agent-workspace-runtime.ts +4 -3
  78. package/src/input/commands/brief-runtime.ts +38 -9
  79. package/src/input/commands/channels-runtime.ts +3 -3
  80. package/src/input/commands/compat-runtime.ts +32 -0
  81. package/src/input/commands/health-runtime.ts +22 -24
  82. package/src/input/commands/knowledge.ts +26 -5
  83. package/src/input/commands/local-provider-runtime.ts +7 -3
  84. package/src/input/commands/local-setup-review.ts +4 -14
  85. package/src/input/commands/mcp-runtime.ts +8 -12
  86. package/src/input/commands/operator-runtime.ts +8 -67
  87. package/src/input/commands/personas-runtime.ts +1 -1
  88. package/src/input/commands/platform-access-runtime.ts +7 -70
  89. package/src/input/commands/policy-dispatch.ts +1 -1
  90. package/src/input/commands/policy.ts +1 -5
  91. package/src/input/commands/product-runtime.ts +2 -2
  92. package/src/input/commands/qrcode-runtime.ts +6 -4
  93. package/src/input/commands/routines-runtime.ts +44 -6
  94. package/src/input/commands/runtime-services.ts +1 -14
  95. package/src/input/commands/security-runtime.ts +3 -8
  96. package/src/input/commands/session-content.ts +1 -1
  97. package/src/input/commands/session-workflow.ts +5 -14
  98. package/src/input/commands/shell-core.ts +8 -2
  99. package/src/input/commands/subscription-runtime.ts +1 -6
  100. package/src/input/commands/support-bundle-runtime.ts +53 -0
  101. package/src/input/commands/tasks-runtime.ts +2 -2
  102. package/src/input/commands.ts +4 -0
  103. package/src/input/feed-context-factory.ts +0 -1
  104. package/src/input/handler-content-actions.ts +0 -25
  105. package/src/input/handler-feed.ts +0 -2
  106. package/src/input/handler-interactions.ts +2 -31
  107. package/src/input/handler-onboarding.ts +29 -12
  108. package/src/input/handler-shortcuts.ts +1 -3
  109. package/src/input/handler.ts +4 -7
  110. package/src/input/keybindings.ts +9 -9
  111. package/src/input/mcp-workspace.ts +90 -26
  112. package/src/input/onboarding/handler-onboarding-routes.ts +3 -1
  113. package/src/input/onboarding/onboarding-wizard-apply.ts +49 -0
  114. package/src/input/onboarding/onboarding-wizard-helpers.ts +1 -1
  115. package/src/input/onboarding/onboarding-wizard-operator-steps.ts +126 -11
  116. package/src/input/onboarding/onboarding-wizard-steps.ts +15 -8
  117. package/src/input/onboarding/onboarding-wizard-types.ts +1 -0
  118. package/src/input/onboarding/onboarding-wizard.ts +19 -2
  119. package/src/input/profile-picker-modal.ts +2 -2
  120. package/src/input/settings-modal-agent-policy.ts +6 -6
  121. package/src/input/settings-modal-subscriptions.ts +3 -3
  122. package/src/input/settings-modal.ts +14 -14
  123. package/src/main.ts +0 -2
  124. package/src/panels/automation-control-panel.ts +3 -3
  125. package/src/panels/builtin/agent.ts +1 -1
  126. package/src/panels/builtin/operations.ts +2 -2
  127. package/src/panels/builtin/session.ts +26 -18
  128. package/src/panels/builtin/shared.ts +6 -6
  129. package/src/panels/project-planning-panel.ts +1 -1
  130. package/src/panels/provider-health-domains.ts +3 -3
  131. package/src/panels/qr-panel.ts +44 -20
  132. package/src/panels/subscription-panel.ts +3 -3
  133. package/src/panels/system-messages-panel.ts +2 -2
  134. package/src/panels/tasks-panel.ts +4 -4
  135. package/src/planning/project-planning-coordinator.ts +2 -2
  136. package/src/renderer/agent-workspace.ts +52 -5
  137. package/src/renderer/block-actions.ts +1 -3
  138. package/src/renderer/help-overlay.ts +13 -8
  139. package/src/renderer/mcp-workspace.ts +32 -13
  140. package/src/renderer/model-picker-overlay.ts +0 -1
  141. package/src/renderer/model-workspace.ts +0 -2
  142. package/src/renderer/onboarding/onboarding-wizard.ts +20 -4
  143. package/src/renderer/panel-picker-overlay.ts +1 -1
  144. package/src/renderer/profile-picker-modal.ts +2 -2
  145. package/src/renderer/settings-modal-helpers.ts +23 -23
  146. package/src/renderer/settings-modal.ts +18 -18
  147. package/src/renderer/system-message.ts +1 -1
  148. package/src/runtime/agent-runtime-events.ts +129 -0
  149. package/src/runtime/bootstrap-command-parts.ts +3 -2
  150. package/src/runtime/bootstrap-core.ts +4 -64
  151. package/src/runtime/bootstrap-shell.ts +42 -4
  152. package/src/runtime/bootstrap.ts +8 -27
  153. package/src/runtime/connected-host-auth.ts +42 -0
  154. package/src/runtime/diagnostics/panels/panel-resources.ts +1 -1
  155. package/src/runtime/index.ts +1 -5
  156. package/src/runtime/onboarding/apply.ts +213 -0
  157. package/src/runtime/onboarding/derivation.ts +25 -6
  158. package/src/runtime/onboarding/snapshot.ts +4 -2
  159. package/src/runtime/onboarding/types.ts +28 -1
  160. package/src/runtime/onboarding/verify.ts +81 -2
  161. package/src/runtime/operator-token-cleanup.ts +2 -2
  162. package/src/runtime/services.ts +27 -12
  163. package/src/shell/service-settings-sync.ts +7 -7
  164. package/src/shell/ui-openers.ts +27 -38
  165. package/src/tools/agent-local-registry-tool.ts +10 -4
  166. package/src/tools/agent-tool-policy-guard.ts +5 -7
  167. package/src/version.ts +1 -1
  168. package/src/cli/package-verification.ts +0 -274
@@ -1,4 +1,12 @@
1
- import { AgentSkillRegistry, type AgentSkillBundleRecord, type AgentSkillRecord } from '../../agent/skill-registry.ts';
1
+ import {
2
+ AgentSkillRegistry,
3
+ buildAgentSkillRequirements,
4
+ evaluateAgentSkillBundleReadiness,
5
+ evaluateAgentSkillReadiness,
6
+ formatAgentSkillRequirement,
7
+ type AgentSkillBundleRecord,
8
+ type AgentSkillRecord,
9
+ } from '../../agent/skill-registry.ts';
2
10
  import { discoverSkills, type SkillRecord } from '../../agent/skill-discovery.ts';
3
11
  import type { CommandContext, CommandRegistry } from '../command-registry.ts';
4
12
  import { requireShellPaths } from './runtime-services.ts';
@@ -53,18 +61,28 @@ function requiredFlag(flags: ReadonlyMap<string, string>, key: string): string {
53
61
  function summarizeSkill(skill: AgentSkillRecord): string {
54
62
  const enabled = skill.enabled ? 'enabled' : 'disabled';
55
63
  const tags = skill.tags.length > 0 ? ` tags=${skill.tags.join(',')}` : '';
56
- return ` ${skill.id} ${enabled} ${skill.reviewState} ${skill.name} - ${skill.description}${tags}`;
64
+ const readiness = evaluateAgentSkillReadiness(skill);
65
+ const ready = readiness.ready ? 'ready' : `needs ${readiness.missing.map(formatAgentSkillRequirement).join(',')}`;
66
+ return ` ${skill.id} ${enabled} ${skill.reviewState} ${ready} ${skill.name} - ${skill.description}${tags}`;
57
67
  }
58
68
 
59
- function summarizeBundle(bundle: AgentSkillBundleRecord): string {
69
+ function summarizeBundle(bundle: AgentSkillBundleRecord, skills: readonly AgentSkillRecord[]): string {
60
70
  const enabled = bundle.enabled ? 'enabled' : 'disabled';
61
- return ` ${bundle.id} ${enabled} ${bundle.reviewState} ${bundle.name} - ${bundle.description} skills=${bundle.skillIds.join(',')}`;
71
+ const readiness = evaluateAgentSkillBundleReadiness(bundle, skills);
72
+ const missing = [
73
+ ...readiness.missingRequirements.map(formatAgentSkillRequirement),
74
+ ...readiness.missingSkillIds.map((skillId) => `skill:${skillId}`),
75
+ ];
76
+ const ready = readiness.ready ? 'ready' : `needs ${missing.join(',')}`;
77
+ return ` ${bundle.id} ${enabled} ${bundle.reviewState} ${ready} ${bundle.name} - ${bundle.description} skills=${bundle.skillIds.join(',')}`;
62
78
  }
63
79
 
64
- function renderList(title: string, registry: AgentSkillRegistry, skills: readonly AgentSkillRecord[]): string {
80
+ function renderList(title: string, registry: AgentSkillRegistry, skills: readonly AgentSkillRecord[], emptyMessage?: string): string {
65
81
  const snapshot = registry.snapshot();
66
82
  if (skills.length === 0) {
67
- return `${title}\n No local Agent skills yet. Create one with /agent-skills create --name <name> --description <summary> --procedure <steps>.`;
83
+ return emptyMessage
84
+ ? `${title}\n ${emptyMessage}`
85
+ : `${title}\n No local Agent skills yet. Create one with /agent-skills create --name <name> --description <summary> --procedure <steps>.`;
68
86
  }
69
87
  return [
70
88
  `${title} (${skills.length})`,
@@ -120,6 +138,14 @@ function frontmatterList(skill: SkillRecord, key: string): readonly string[] {
120
138
  return splitList(value);
121
139
  }
122
140
 
141
+ function frontmatterAnyList(skill: SkillRecord, keys: readonly string[]): readonly string[] {
142
+ for (const key of keys) {
143
+ const values = frontmatterList(skill, key);
144
+ if (values.length > 0) return values;
145
+ }
146
+ return [];
147
+ }
148
+
123
149
  async function importDiscoveredSkill(args: readonly string[], ctx: CommandContext, skillRegistry: AgentSkillRegistry): Promise<void> {
124
150
  const parsed = parseSkillArgs(args);
125
151
  const name = parsed.rest.join(' ').trim();
@@ -150,6 +176,10 @@ async function importDiscoveredSkill(args: readonly string[], ctx: CommandContex
150
176
  procedure: discovered.body,
151
177
  triggers: frontmatterList(discovered, 'triggers'),
152
178
  tags: frontmatterList(discovered, 'tags'),
179
+ requirements: buildAgentSkillRequirements({
180
+ env: frontmatterAnyList(discovered, ['requiresEnv', 'requires-env', 'requires_env']),
181
+ commands: frontmatterAnyList(discovered, ['requiresCommands', 'requires-commands', 'requires_commands', 'commands']),
182
+ }),
153
183
  enabled: parsed.flags.get('enabled') === 'true',
154
184
  source: 'imported',
155
185
  provenance: `discovered:${discovered.origin}:${discovered.path}`,
@@ -157,25 +187,31 @@ async function importDiscoveredSkill(args: readonly string[], ctx: CommandContex
157
187
  ctx.print(`Imported Agent skill ${skill.id}: ${skill.name}`);
158
188
  }
159
189
 
160
- function renderBundleList(title: string, registry: AgentSkillRegistry, bundles: readonly AgentSkillBundleRecord[]): string {
190
+ function renderBundleList(title: string, registry: AgentSkillRegistry, bundles: readonly AgentSkillBundleRecord[], emptyMessage?: string): string {
161
191
  const snapshot = registry.snapshot();
162
192
  if (bundles.length === 0) {
163
- return `${title}\n No local Agent skill bundles yet. Create one with /agent-skills bundle create --name <name> --description <summary> --skills <id,id>.`;
193
+ return emptyMessage
194
+ ? `${title}\n ${emptyMessage}`
195
+ : `${title}\n No local Agent skill bundles yet. Create one with /agent-skills bundle create --name <name> --description <summary> --skills <id,id>.`;
164
196
  }
165
197
  return [
166
198
  `${title} (${bundles.length})`,
167
199
  ` store: ${snapshot.path}`,
168
200
  ` enabled bundles: ${snapshot.enabledBundles.length}`,
169
201
  ` active skills: ${snapshot.activeSkills.length}`,
170
- ...bundles.map(summarizeBundle),
202
+ ...bundles.map((bundle) => summarizeBundle(bundle, snapshot.skills)),
171
203
  ].join('\n');
172
204
  }
173
205
 
174
206
  function renderSkill(skill: AgentSkillRecord): string {
207
+ const readiness = evaluateAgentSkillReadiness(skill);
175
208
  return [
176
209
  `Skill ${skill.name}`,
177
210
  ` id: ${skill.id}`,
178
211
  ` enabled: ${skill.enabled ? 'yes' : 'no'}`,
212
+ ` readiness: ${readiness.ready ? 'ready' : 'needs setup'}`,
213
+ ` requirements: ${skill.requirements.map(formatAgentSkillRequirement).join(', ') || '(none)'}`,
214
+ readiness.missing.length > 0 ? ` missing: ${readiness.missing.map(formatAgentSkillRequirement).join(', ')}` : '',
179
215
  ` review: ${skill.reviewState}`,
180
216
  ` source: ${skill.source}`,
181
217
  ` provenance: ${skill.provenance}`,
@@ -195,10 +231,17 @@ function renderBundle(bundle: AgentSkillBundleRecord, registry: AgentSkillRegist
195
231
  const skills = bundle.skillIds
196
232
  .map((skillId) => registry.get(skillId))
197
233
  .filter((skill): skill is AgentSkillRecord => skill !== null);
234
+ const readiness = evaluateAgentSkillBundleReadiness(bundle, registry.snapshot().skills);
235
+ const missing = [
236
+ ...readiness.missingRequirements.map(formatAgentSkillRequirement),
237
+ ...readiness.missingSkillIds.map((skillId) => `skill:${skillId}`),
238
+ ];
198
239
  return [
199
240
  `Skill Bundle ${bundle.name}`,
200
241
  ` id: ${bundle.id}`,
201
242
  ` enabled: ${bundle.enabled ? 'yes' : 'no'}`,
243
+ ` readiness: ${readiness.ready ? 'ready' : 'needs setup'}`,
244
+ missing.length > 0 ? ` missing: ${missing.join(', ')}` : '',
202
245
  ` review: ${bundle.reviewState}`,
203
246
  ` source: ${bundle.source}`,
204
247
  ` provenance: ${bundle.provenance}`,
@@ -228,6 +271,12 @@ function runBundleCommand(args: readonly string[], ctx: CommandContext, skillReg
228
271
  ctx.print(renderBundleList('Enabled Agent Skill Bundles', skillRegistry, snapshot.enabledBundles));
229
272
  return;
230
273
  }
274
+ if (sub === 'attention' || sub === 'needs-setup') {
275
+ const snapshot = skillRegistry.snapshot();
276
+ const bundles = snapshot.bundles.filter((bundle) => !evaluateAgentSkillBundleReadiness(bundle, snapshot.skills).ready);
277
+ ctx.print(renderBundleList('Agent Skill Bundles needing setup', skillRegistry, bundles, 'No local Agent skill bundles need setup.'));
278
+ return;
279
+ }
231
280
  if (sub === 'search') {
232
281
  const query = args.slice(1).join(' ').trim();
233
282
  ctx.print(renderBundleList(query ? `Agent Skill Bundles matching "${query}"` : 'Agent Skill Bundles', skillRegistry, skillRegistry.searchBundles(query)));
@@ -317,7 +366,7 @@ function runBundleCommand(args: readonly string[], ctx: CommandContext, skillReg
317
366
  ctx.print(`Deleted Agent skill bundle ${removed.id}: ${removed.name}`);
318
367
  return;
319
368
  }
320
- ctx.print('Usage: /agent-skills bundle [list|enabled|search|show|create|update|enable|disable|review|stale|delete]');
369
+ ctx.print('Usage: /agent-skills bundle [list|enabled|attention|search|show|create|update|enable|disable|review|stale|delete]');
321
370
  }
322
371
 
323
372
  export async function runAgentSkillsRuntimeCommand(args: readonly string[], ctx: CommandContext): Promise<void> {
@@ -349,6 +398,11 @@ export async function runAgentSkillsRuntimeCommand(args: readonly string[], ctx:
349
398
  ctx.print(renderList('Enabled Agent Skills', skillRegistry, snapshot.enabledSkills));
350
399
  return;
351
400
  }
401
+ if (sub === 'attention' || sub === 'needs-setup') {
402
+ const skills = skillRegistry.list().filter((skill) => !evaluateAgentSkillReadiness(skill).ready);
403
+ ctx.print(renderList('Agent Skills needing setup', skillRegistry, skills, 'No local Agent skills need setup.'));
404
+ return;
405
+ }
352
406
  if (sub === 'search') {
353
407
  const query = args.slice(1).join(' ').trim();
354
408
  ctx.print(renderList(query ? `Agent Skills matching "${query}"` : 'Agent Skills', skillRegistry, skillRegistry.search(query)));
@@ -373,6 +427,10 @@ export async function runAgentSkillsRuntimeCommand(args: readonly string[], ctx:
373
427
  procedure,
374
428
  triggers: splitList(parsed.flags.get('triggers')),
375
429
  tags: splitList(parsed.flags.get('tags')),
430
+ requirements: buildAgentSkillRequirements({
431
+ env: splitList(parsed.flags.get('requires-env')),
432
+ commands: splitList(parsed.flags.get('requires-command') ?? parsed.flags.get('requires-commands')),
433
+ }),
376
434
  enabled: parsed.flags.get('enabled') === 'true',
377
435
  source: 'user',
378
436
  provenance: 'slash-command',
@@ -393,6 +451,12 @@ export async function runAgentSkillsRuntimeCommand(args: readonly string[], ctx:
393
451
  procedure: parsed.flags.get('procedure'),
394
452
  triggers: parsed.flags.has('triggers') ? splitList(parsed.flags.get('triggers')) : undefined,
395
453
  tags: parsed.flags.has('tags') ? splitList(parsed.flags.get('tags')) : undefined,
454
+ requirements: parsed.flags.has('requires-env') || parsed.flags.has('requires-command') || parsed.flags.has('requires-commands')
455
+ ? buildAgentSkillRequirements({
456
+ env: splitList(parsed.flags.get('requires-env')),
457
+ commands: splitList(parsed.flags.get('requires-command') ?? parsed.flags.get('requires-commands')),
458
+ })
459
+ : undefined,
396
460
  provenance: 'slash-command',
397
461
  });
398
462
  ctx.print(`Updated Agent skill ${updated.id}: ${updated.name}`);
@@ -443,7 +507,7 @@ export async function runAgentSkillsRuntimeCommand(args: readonly string[], ctx:
443
507
  ctx.print(`Deleted Agent skill ${removed.id}: ${removed.name}`);
444
508
  return;
445
509
  }
446
- ctx.print('Usage: /agent-skills [list|enabled|discover|import-discovered|search|show|create|update|enable|disable|review|stale|delete|bundle]');
510
+ ctx.print('Usage: /agent-skills [list|enabled|attention|discover|import-discovered|search|show|create|update|enable|disable|review|stale|delete|bundle]');
447
511
  } catch (error) {
448
512
  printError(ctx, error);
449
513
  }
@@ -454,7 +518,7 @@ export function registerAgentSkillsRuntimeCommands(registry: CommandRegistry): v
454
518
  name: 'agent-skills',
455
519
  aliases: ['askills', 'local-skills', 'skills', 'skill'],
456
520
  description: 'Manage local GoodVibes Agent skills',
457
- usage: '[list|enabled|discover|import-discovered <name> --yes|search <query>|show <id>|create --name <name> --description <summary> --procedure <steps>|update <id> [--name ...] [--description ...] [--procedure ...]|enable <id>|disable <id>|review <id>|stale <id> <reason...>|delete <id> --yes|bundle ...]',
521
+ usage: '[list|enabled|attention|discover|import-discovered <name> --yes|search <query>|show <id>|create --name <name> --description <summary> --procedure <steps> [--requires-env A,B] [--requires-command gh,jq]|update <id> [--name ...] [--description ...] [--procedure ...]|enable <id>|disable <id>|review <id>|stale <id> <reason...>|delete <id> --yes|bundle ...]',
458
522
  handler: runAgentSkillsRuntimeCommand,
459
523
  });
460
524
  }
@@ -5,13 +5,14 @@ export function registerAgentWorkspaceRuntimeCommands(registry: CommandRegistry)
5
5
  name: 'agent',
6
6
  aliases: ['home', 'operator'],
7
7
  description: 'Open the GoodVibes Agent operator workspace',
8
- usage: '',
9
- handler(_args, ctx) {
8
+ usage: '[category]',
9
+ argsHint: 'home|setup|channels|tools|knowledge|voice-media|profiles|memory|personas|skills|routines|work|automation|delegate',
10
+ handler(args, ctx) {
10
11
  if (!ctx.openAgentWorkspace) {
11
12
  ctx.print('Agent operator workspace is not available in this runtime.');
12
13
  return;
13
14
  }
14
- ctx.openAgentWorkspace();
15
+ ctx.openAgentWorkspace(args[0]);
15
16
  },
16
17
  });
17
18
  }
@@ -34,6 +34,10 @@ function plural(count: number, singular: string, pluralWord = `${singular}s`): s
34
34
  return `${count} ${count === 1 ? singular : pluralWord}`;
35
35
  }
36
36
 
37
+ function countSetupGaps(items: readonly { readonly missingRequirementCount?: number }[]): number {
38
+ return items.filter((item) => (item.missingRequirementCount ?? 0) > 0).length;
39
+ }
40
+
37
41
  function formatWorkPlanLine(total: number, counts: StatusCounts): string {
38
42
  if (total === 0) return ' work plan: empty';
39
43
  const active = counts.pending + counts.in_progress + counts.blocked;
@@ -62,6 +66,13 @@ export function formatAgentOperatorBriefing(ctx: CommandContext): string {
62
66
  const setupBlocked = countReady(snapshot.setupChecklist, 'blocked');
63
67
  const readyChannels = snapshot.channels.filter((channel) => channel.ready).length;
64
68
  const enabledChannels = snapshot.channels.filter((channel) => channel.enabled).length;
69
+ const channelSetupGaps = snapshot.channels.filter((channel) => channel.enabled && !channel.ready).length;
70
+ const skillSetupGaps = countSetupGaps(snapshot.localSkills);
71
+ const skillBundleSetupGaps = countSetupGaps(snapshot.localSkillBundles);
72
+ const routineSetupGaps = countSetupGaps(snapshot.localRoutines);
73
+ const voiceSetupNeedsReview = snapshot.voiceSurfaceEnabled && snapshot.voiceMediaReadiness.selectedTtsProviderStatus !== 'ready';
74
+ const mediaSetupNeedsReview = snapshot.mediaProviderCount > 0 && snapshot.voiceMediaReadiness.readyMediaProviderCount === 0;
75
+ const hasLocalSkillBehavior = snapshot.localSkillCount > 0 || snapshot.localSkillBundleCount > 0;
65
76
 
66
77
  const nextActions = [
67
78
  snapshot.provider === 'unknown' || snapshot.model === 'unknown'
@@ -72,17 +83,35 @@ export function formatAgentOperatorBriefing(ctx: CommandContext): string {
72
83
  : snapshot.localMemoryReviewQueueCount > 0
73
84
  ? `Review ${plural(snapshot.localMemoryReviewQueueCount, 'memory record')} with /memory queue.`
74
85
  : '',
75
- snapshot.localSkillCount === 0 && snapshot.localSkillBundleCount === 0
86
+ !hasLocalSkillBehavior
76
87
  ? 'Create reusable procedures with /agent-skills create or import reviewed skill files.'
77
- : snapshot.activeSkillCount === 0
78
- ? 'Enable reviewed skills or bundles with /agent-skills enabled and /agent-skills bundle enabled.'
79
- : '',
88
+ : '',
89
+ skillSetupGaps > 0
90
+ ? `Resolve ${plural(skillSetupGaps, 'skill')} with setup gaps from /agent skills.`
91
+ : '',
92
+ skillBundleSetupGaps > 0
93
+ ? `Resolve ${plural(skillBundleSetupGaps, 'skill bundle')} with setup gaps from /agent skills.`
94
+ : '',
95
+ hasLocalSkillBehavior && skillSetupGaps === 0 && skillBundleSetupGaps === 0 && snapshot.activeSkillCount === 0
96
+ ? 'Enable reviewed skills or bundles with /agent-skills enabled and /agent-skills bundle enabled.'
97
+ : '',
80
98
  snapshot.localRoutineCount === 0
81
99
  ? 'Create repeatable workflows with /routines create; promote schedules only with explicit confirmation.'
82
- : snapshot.enabledRoutineCount === 0
100
+ : routineSetupGaps > 0
101
+ ? `Resolve ${plural(routineSetupGaps, 'routine')} with setup gaps from /agent routines.`
102
+ : snapshot.enabledRoutineCount === 0
83
103
  ? 'Enable reviewed routines with /routines enable.'
84
104
  : '',
85
- 'Use /knowledge status, /knowledge search, and explicit ingest forms for Agent Knowledge only.',
105
+ channelSetupGaps > 0
106
+ ? `Review ${plural(channelSetupGaps, 'enabled channel')} needing setup from /agent channels.`
107
+ : '',
108
+ voiceSetupNeedsReview
109
+ ? 'Review voice setup with /agent voice-media before relying on spoken replies.'
110
+ : '',
111
+ mediaSetupNeedsReview
112
+ ? 'Review media provider setup with /agent voice-media before relying on image or media workflows.'
113
+ : '',
114
+ 'Use /agent knowledge for Agent Knowledge status, search, and explicit ingest forms.',
86
115
  'Use /delegate only for explicit build, fix, implementation, or review handoff to GoodVibes TUI.',
87
116
  ].filter((line): line is string => line.length > 0);
88
117
 
@@ -98,9 +127,9 @@ export function formatAgentOperatorBriefing(ctx: CommandContext): string {
98
127
  ` setup: ${setupReady}/${snapshot.setupChecklist.length} ready; ${setupRecommended} recommended; ${setupBlocked} blocked`,
99
128
  ` local memory: ${plural(snapshot.localMemoryCount, 'record')}; prompt-active ${snapshot.localMemoryPromptActiveCount}; review queue ${snapshot.localMemoryReviewQueueCount}`,
100
129
  ` personas: ${plural(snapshot.localPersonaCount, 'persona')}; active ${snapshot.activePersonaName}`,
101
- ` skills: ${snapshot.enabledSkillCount}/${snapshot.localSkillCount} enabled; bundles ${snapshot.enabledSkillBundleCount}/${snapshot.localSkillBundleCount}; active ${snapshot.activeSkillCount}`,
102
- ` routines: ${snapshot.enabledRoutineCount}/${snapshot.localRoutineCount} enabled`,
103
- ` channels: ${readyChannels}/${snapshot.channels.length} ready; ${enabledChannels} enabled`,
130
+ ` skills: ${snapshot.enabledSkillCount}/${snapshot.localSkillCount} enabled; bundles ${snapshot.enabledSkillBundleCount}/${snapshot.localSkillBundleCount}; active ${snapshot.activeSkillCount}; setup gaps ${skillSetupGaps} skill, ${skillBundleSetupGaps} bundle`,
131
+ ` routines: ${snapshot.enabledRoutineCount}/${snapshot.localRoutineCount} enabled; setup gaps ${routineSetupGaps}`,
132
+ ` channels: ${readyChannels}/${snapshot.channels.length} ready; ${enabledChannels} enabled; setup gaps ${channelSetupGaps}`,
104
133
  ` voice/media: ${snapshot.voiceProviderCount} voice, ${snapshot.mediaProviderCount} media; browser tools ${snapshot.voiceMediaReadiness.browserToolState}`,
105
134
  formatWorkPlanLine(workPlan.total, workPlan.counts),
106
135
  ` schedules: ${enabledJobs}/${jobs.length} visible jobs enabled`,
@@ -211,7 +211,7 @@ function formatChannelAccounts(body: unknown): string {
211
211
  ' policy: read-only account posture; secret values are never shown',
212
212
  '',
213
213
  ];
214
- if (accounts.length === 0) return [...lines, ' No channel accounts reported by connected services.'].join('\n');
214
+ if (accounts.length === 0) return [...lines, ' No channel accounts reported by connected host.'].join('\n');
215
215
  for (const account of accounts.slice(0, 20)) {
216
216
  const surface = readString(account, 'surface', 'unknown');
217
217
  const accountId = readString(account, 'accountId', '');
@@ -236,7 +236,7 @@ function formatChannelPolicies(body: unknown): string {
236
236
  ' policy: read-only policy posture; use exact confirmed commands for changes',
237
237
  '',
238
238
  ];
239
- if (policies.length === 0) return [...lines, ' No channel policies reported by connected services.'].join('\n');
239
+ if (policies.length === 0) return [...lines, ' No channel policies reported by connected host.'].join('\n');
240
240
  for (const policy of policies.slice(0, 20)) {
241
241
  const surface = readString(policy, 'surface', 'unknown');
242
242
  const direct = readBoolean(policy, 'allowDirectMessages') ? 'direct=yes' : 'direct=no';
@@ -255,7 +255,7 @@ function formatChannelStatus(body: unknown): string {
255
255
  const lines = [
256
256
  'Connected Channel Status',
257
257
  ` channels: ${channels.length}`,
258
- ' policy: read-only connected-service status',
258
+ ' policy: read-only connected-host status',
259
259
  '',
260
260
  ];
261
261
  if (channels.length === 0) return [...lines, ' No connected channel status reported.'].join('\n');
@@ -0,0 +1,32 @@
1
+ import type { CliCommandRuntime } from '../../cli/management.ts';
2
+ import { handleCompatCommand } from '../../cli/agent-knowledge-command.ts';
3
+ import { parseGoodVibesCli } from '../../cli/parser.ts';
4
+ import type { CommandRegistry } from '../command-registry.ts';
5
+ import { requireShellPaths } from './runtime-services.ts';
6
+
7
+ export function registerCompatRuntimeCommands(registry: CommandRegistry): void {
8
+ registry.register({
9
+ name: 'compat',
10
+ aliases: ['compatibility'],
11
+ description: 'Inspect Agent SDK pin, connected host version, and Agent Knowledge route readiness',
12
+ usage: '[--json]',
13
+ argsHint: '[--json]',
14
+ async handler(args, ctx) {
15
+ const cli = parseGoodVibesCli(['compat', ...args], 'goodvibes-agent');
16
+ if (cli.errors.length > 0) {
17
+ ctx.print(cli.errors.join('\n'));
18
+ return;
19
+ }
20
+
21
+ const shellPaths = requireShellPaths(ctx);
22
+ const runtime: CliCommandRuntime = {
23
+ cli,
24
+ configManager: ctx.platform.configManager,
25
+ workingDirectory: shellPaths.workingDirectory,
26
+ homeDirectory: shellPaths.homeDirectory,
27
+ };
28
+ const result = await handleCompatCommand(runtime);
29
+ ctx.print(result.output);
30
+ },
31
+ });
32
+ }
@@ -20,8 +20,8 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
20
20
  registry.register({
21
21
  name: 'health',
22
22
  aliases: ['doctor'],
23
- description: 'Health workspace for startup posture, service readiness, provider health, and Agent continuity',
24
- usage: '[review|setup|services|provider|accounts|auth|settings|remote|mcp|continuity|maintenance|repair [domain]]',
23
+ description: 'Health workspace for startup posture, connected host readiness, provider health, and Agent continuity',
24
+ usage: '[review|setup|host|provider|accounts|auth|settings|remote|mcp|continuity|maintenance|repair [domain]]',
25
25
  async handler(args, ctx) {
26
26
  const sub = (args[0] ?? 'review').toLowerCase();
27
27
 
@@ -52,7 +52,7 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
52
52
 
53
53
  const readModels = requireReadModels(ctx);
54
54
 
55
- if (sub === 'services') {
55
+ if (sub === 'host' || sub === 'services') {
56
56
  const registry = requireServiceRegistry(ctx);
57
57
  const all = registry.getAll();
58
58
  const keys = Object.keys(all);
@@ -67,10 +67,10 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
67
67
  return findings;
68
68
  });
69
69
  ctx.print([
70
- 'Health Review: Services',
71
- ` configured: ${keys.length}`,
70
+ 'Health Review: Connected Host Integrations',
71
+ ` configured integrations: ${keys.length}`,
72
72
  ` issues: ${issues.length}`,
73
- ...(issues.length > 0 ? issues.map((issue) => ` ${issue}`) : [' all configured services passed readiness checks']),
73
+ ...(issues.length > 0 ? issues.map((issue) => ` ${issue}`) : [' all configured host integrations passed readiness checks']),
74
74
  ].join('\n'));
75
75
  return;
76
76
  }
@@ -97,12 +97,12 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
97
97
  if (sub === 'auth') {
98
98
  const auth = readModels.localAuth.getSnapshot();
99
99
  ctx.print([
100
- 'Health Review: Connected-Service Auth',
101
- ' owner: connected GoodVibes services',
100
+ 'Health Review: Connected-Host Auth',
101
+ ' owner: connected GoodVibes host',
102
102
  ` compatibility users visible: ${auth.userCount}`,
103
103
  ` compatibility sessions visible: ${auth.sessionCount}`,
104
104
  ` bootstrap file signal: ${auth.bootstrapCredentialPresent ? 'present' : 'cleared'}`,
105
- ' Agent action: review provider/subscription auth only; do not mutate connected-service auth users or bootstrap credentials.',
105
+ ' Agent action: review provider/subscription auth only; do not mutate connected-host auth users or bootstrap credentials.',
106
106
  ...(auth.bootstrapCredentialPresent ? [' issue: bootstrap cleanup belongs outside Agent'] : []),
107
107
  ].join('\n'));
108
108
  return;
@@ -237,7 +237,7 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
237
237
  lines.push(' domain: settings');
238
238
  lines.push(...(
239
239
  settings.conflicts.length > 0
240
- ? [' /settings', ' /config <key>', ' service-owned managed setting repair stays external']
240
+ ? [' /settings', ' /config <key>', ' host-owned managed setting repair stays external']
241
241
  : [' no active settings repair actions suggested']
242
242
  ));
243
243
  lines.push(' verify: /health settings');
@@ -246,7 +246,7 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
246
246
  lines.push(' /auth review');
247
247
  lines.push(' /provider');
248
248
  lines.push(' /subscription providers');
249
- lines.push(' connected-service auth users/bootstrap cleanup: manage outside Agent');
249
+ lines.push(' connected-host auth users/bootstrap cleanup: manage outside Agent');
250
250
  lines.push(' verify: /health auth');
251
251
  } else if (domain === 'accounts') {
252
252
  lines.push(' domain: accounts');
@@ -255,11 +255,11 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
255
255
  lines.push(' /accounts repair <provider>');
256
256
  lines.push(' /auth show <provider>');
257
257
  lines.push(' verify: /health accounts');
258
- } else if (domain === 'services') {
259
- lines.push(' domain: services');
260
- lines.push(' /health services');
261
- lines.push(' runtime service repair belongs outside Agent');
262
- lines.push(' verify: /health services');
258
+ } else if (domain === 'host' || domain === 'services') {
259
+ lines.push(' domain: host');
260
+ lines.push(' /health host');
261
+ lines.push(' connected host repair belongs outside Agent');
262
+ lines.push(' verify: /health host');
263
263
  } else if (domain === 'remote') {
264
264
  lines.push(' domain: remote');
265
265
  lines.push(' /delegate <build/fix/review task> for explicit TUI build work');
@@ -284,7 +284,7 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
284
284
  lines.push(' /compact');
285
285
  lines.push(' verify: /health maintenance');
286
286
  } else {
287
- lines.push(' domains: settings, auth, accounts, services, remote, mcp, continuity, maintenance');
287
+ lines.push(' domains: settings, auth, accounts, host, remote, mcp, continuity, maintenance');
288
288
  lines.push(' use: /health repair <domain>');
289
289
  }
290
290
  ctx.print(lines.join('\n'));
@@ -316,7 +316,7 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
316
316
  'Health Review: Setup',
317
317
  ...snapshot.issues.map((issue) => ` [${issue.severity.toUpperCase()}] ${issue.area}: ${issue.message}`),
318
318
  ...(snapshot.serviceIssues.length > 0
319
- ? ['', ' Service issues:', ...snapshot.serviceIssues.map((issue) => ` - ${issue}`)]
319
+ ? ['', ' Connected host integration issues:', ...snapshot.serviceIssues.map((issue) => ` - ${issue}`)]
320
320
  : []),
321
321
  ].join('\n'));
322
322
  return;
@@ -326,24 +326,22 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
326
326
  'Health Review',
327
327
  ` session: ${snapshot.sessionId}`,
328
328
  ` setup issues: ${snapshot.issues.length}`,
329
- ` service issues: ${snapshot.serviceIssues.length}`,
329
+ ` host integration issues: ${snapshot.serviceIssues.length}`,
330
330
  ` active subscriptions: ${snapshot.activeSubscriptionCount}`,
331
331
  ` account issues: ${accountSnapshot.issueCount}`,
332
332
  ` settings conflicts: ${settingsSnapshot.conflicts.length}`,
333
333
  ` managed locks: ${settingsSnapshot.managedLockCount}`,
334
- ` connected-service auth owner: outside Agent`,
335
- ` remote workers: ${snapshot.remoteRunnerCount}`,
334
+ ` connected-host auth owner: outside Agent`,
336
335
  ...formatSessionMaintenanceLines(maintenance, 'guided').map((line) => ` ${line}`),
337
336
  ...(snapshot.issues.length > 0 ? ['', ...snapshot.issues.map((issue) => ` [${issue.severity.toUpperCase()}] ${issue.area}: ${issue.message}`)] : []),
338
- ...(snapshot.serviceIssues.length > 0 ? ['', ...snapshot.serviceIssues.map((issue) => ` service: ${issue}`)] : []),
337
+ ...(snapshot.serviceIssues.length > 0 ? ['', ...snapshot.serviceIssues.map((issue) => ` host integration: ${issue}`)] : []),
339
338
  '',
340
339
  'Next steps:',
341
340
  ' /health review',
342
- ' /health services',
341
+ ' /health host',
343
342
  ' /health accounts',
344
343
  ' /health auth',
345
344
  ' /health settings',
346
- ' /health remote',
347
345
  ' /health maintenance',
348
346
  ' /health repair <domain>',
349
347
  ' /setup',
@@ -1,4 +1,4 @@
1
- import type { KnowledgeService } from '@pellux/goodvibes-sdk/platform/knowledge';
1
+ import type { KnowledgeMapResult, KnowledgeService } from '@pellux/goodvibes-sdk/platform/knowledge';
2
2
  import type { BrowserKnowledgeKind, BrowserKnowledgeSourceKind } from '@pellux/goodvibes-sdk/platform/knowledge';
3
3
  import type { CommandContext, SlashCommand } from '../command-registry.ts';
4
4
  import { requireYesFlag, stripYesFlag } from './confirmation.ts';
@@ -139,6 +139,15 @@ function cleanInline(value: unknown): string {
139
139
  return typeof value === 'string' ? value.replace(/\s+/g, ' ').trim() : '';
140
140
  }
141
141
 
142
+ function formatKnowledgeMap(result: KnowledgeMapResult): string {
143
+ return [
144
+ 'Agent Knowledge map',
145
+ ` nodes: ${result.nodeCount}${result.totalNodeCount !== undefined && result.totalNodeCount !== result.nodeCount ? ` of ${result.totalNodeCount}` : ''}`,
146
+ ` edges: ${result.edgeCount}${result.totalEdgeCount !== undefined && result.totalEdgeCount !== result.edgeCount ? ` of ${result.totalEdgeCount}` : ''}`,
147
+ ' route: /api/goodvibes-agent/knowledge/map',
148
+ ].join('\n');
149
+ }
150
+
142
151
  function nodeLabel(node: { readonly kind?: string; readonly title?: string; readonly summary?: string; readonly confidence?: number }): string {
143
152
  const kind = cleanInline(node.kind) || 'node';
144
153
  const title = cleanInline(node.title) || 'untitled';
@@ -203,12 +212,12 @@ export const knowledgeCommand: SlashCommand = {
203
212
  usage: '<subcommand> [args]',
204
213
  argsHint: 'status|ask|ingest-url --yes|ingest-file --yes|import-bookmarks --yes|list|search|get|queue|review-issue --yes',
205
214
  handler: async (args: string[], context: CommandContext): Promise<void> => {
206
- const knowledge = requireAgentKnowledgeApi(context);
207
- if (!knowledge) {
215
+ if (args.length === 0 && context.openAgentWorkspace) {
216
+ context.openAgentWorkspace('knowledge');
208
217
  return;
209
218
  }
210
- if (args.length === 0 && context.openKnowledgePanel) {
211
- context.openKnowledgePanel();
219
+ const knowledge = requireAgentKnowledgeApi(context);
220
+ if (!knowledge) {
212
221
  return;
213
222
  }
214
223
  const sub = (args[0] ?? 'status').toLowerCase();
@@ -502,6 +511,17 @@ export const knowledgeCommand: SlashCommand = {
502
511
  break;
503
512
  }
504
513
 
514
+ case 'map': {
515
+ const limit = readPositiveIntFlag(rest, '--limit', 50);
516
+ const query = positionalArgs(rest, ['--limit']).join(' ').trim();
517
+ const result = await knowledge.graph.map({
518
+ limit,
519
+ ...(query.length > 0 ? { query } : {}),
520
+ });
521
+ context.print(formatKnowledgeMap(result));
522
+ break;
523
+ }
524
+
505
525
  case 'lint': {
506
526
  const issues = await knowledge.status.lint();
507
527
  if (issues.length === 0) {
@@ -743,6 +763,7 @@ export const knowledgeCommand: SlashCommand = {
743
763
  ' list [--kind <sources|nodes|issues>] [--limit <n>]',
744
764
  ' search <query> [--limit <n>]',
745
765
  ' get <id>',
766
+ ' map [query] [--limit <n>]',
746
767
  ' queue [limit]',
747
768
  ' review-issue <issueId> <accept|reject|resolve|reopen|edit|forget> [--reviewer <name>] [--value <json-object>] --yes',
748
769
  ' candidates [limit]',
@@ -91,13 +91,13 @@ export function registerLocalProviderRuntimeCommands(registry: CommandRegistry):
91
91
  id: defaultModel,
92
92
  displayName: defaultModel,
93
93
  contextWindow: 8192,
94
- capabilities: { toolCalling: true, codeEditing: true, reasoning: false, multimodal: false },
94
+ capabilities: { toolCalling: true, codeEditing: false, reasoning: false, multimodal: false },
95
95
  }]
96
96
  : discoveredModelIds.map((id) => ({
97
97
  id,
98
98
  displayName: id,
99
99
  contextWindow: contextWindows[id] ?? 8192,
100
- capabilities: { toolCalling: true, codeEditing: true, reasoning: false, multimodal: false },
100
+ capabilities: { toolCalling: true, codeEditing: false, reasoning: false, multimodal: false },
101
101
  }));
102
102
  const config: CustomProviderConfig = {
103
103
  name,
@@ -157,6 +157,7 @@ export function registerLocalProviderRuntimeCommands(registry: CommandRegistry):
157
157
  }
158
158
 
159
159
  const providerName = commandArgs[0];
160
+ const requestedModel = commandArgs[1];
160
161
  const providerApi = requireProviderApi(ctx);
161
162
  const selectable = await providerApi.listModels({
162
163
  providerId: providerName,
@@ -168,7 +169,10 @@ export function registerLocalProviderRuntimeCommands(registry: CommandRegistry):
168
169
  return;
169
170
  }
170
171
  try {
171
- const selected = await providerApi.selectModel(match.registryKey);
172
+ const registryKey = requestedModel
173
+ ? requestedModel.includes(':') ? requestedModel : `${providerName}:${requestedModel}`
174
+ : match.registryKey;
175
+ const selected = await providerApi.selectModel(registryKey);
172
176
  ctx.session.runtime.model = selected.registryKey;
173
177
  ctx.session.runtime.provider = selected.providerId;
174
178
  ctx.platform.configManager.set('provider.model', selected.registryKey);
@@ -80,12 +80,12 @@ export async function buildSetupReviewSnapshot(ctx: CommandContext): Promise<Set
80
80
  },
81
81
  {
82
82
  severity: (services.length === 0 && oauthProviderCount === 0 && builtinSubscriptionProviderCount === 0) ? 'warn' : serviceIssues.length === 0 ? 'pass' : 'warn',
83
- area: 'services',
83
+ area: 'host',
84
84
  message: (services.length === 0 && oauthProviderCount === 0 && builtinSubscriptionProviderCount === 0)
85
- ? 'no services configured'
85
+ ? 'no connected host integrations configured'
86
86
  : serviceIssues.length === 0
87
- ? `${services.length} service(s), ${oauthProviderCount + builtinSubscriptionProviderCount} oauth provider(s), ${activeSubscriptionCount} active subscription override(s)`
88
- : `${serviceIssues.length} service configuration issue(s)`,
87
+ ? `${services.length} host integration(s), ${oauthProviderCount + builtinSubscriptionProviderCount} oauth provider(s), ${activeSubscriptionCount} active subscription override(s)`
88
+ : `${serviceIssues.length} host integration configuration issue(s)`,
89
89
  },
90
90
  {
91
91
  severity: quarantinedPluginCount === 0 ? 'pass' : 'warn',
@@ -101,16 +101,6 @@ export async function buildSetupReviewSnapshot(ctx: CommandContext): Promise<Set
101
101
  ? `${quarantinedMcpCount} quarantined, ${elevatedMcpCount} elevated`
102
102
  : `${mcpServers.length} server(s) known`,
103
103
  },
104
- {
105
- severity: managedHookCount > 0 || managedHookChainCount > 0 ? 'pass' : 'warn',
106
- area: 'hooks',
107
- message: `${managedHookCount} managed hook(s), ${managedHookChainCount} chain(s)`,
108
- },
109
- {
110
- severity: remoteRunnerCount > 0 ? 'pass' : 'warn',
111
- area: 'remote',
112
- message: remoteRunnerCount > 0 ? `${remoteRunnerCount} remote worker contract(s)` : 'no remote worker contracts registered',
113
- },
114
104
  ];
115
105
 
116
106
  return {