@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
@@ -0,0 +1,101 @@
1
+ import type { AgentWorkspaceActionResult, AgentWorkspaceLocalEditor } from './agent-workspace-types.ts';
2
+ import type { AgentWorkspaceSkillBundleCommandEditorKind } from './agent-workspace-skill-bundle-command-editors.ts';
3
+ import { isAgentWorkspaceSkillBundleCommandEditorKind } from './agent-workspace-skill-bundle-command-editors.ts';
4
+ import { quoteSlashCommandArg } from './slash-command-parser.ts';
5
+
6
+ type AgentWorkspaceFieldReader = (fieldId: string) => string;
7
+
8
+ export type AgentWorkspaceSkillBundleCommandEditorSubmission =
9
+ | {
10
+ readonly kind: 'editor';
11
+ readonly editor: AgentWorkspaceLocalEditor;
12
+ readonly status: string;
13
+ readonly actionResult?: AgentWorkspaceActionResult;
14
+ }
15
+ | {
16
+ readonly kind: 'dispatch';
17
+ readonly command: string;
18
+ readonly status: string;
19
+ readonly actionResult: AgentWorkspaceActionResult;
20
+ };
21
+
22
+ export function isAgentWorkspaceSkillBundleCommandSubmissionKind(kind: string): kind is AgentWorkspaceSkillBundleCommandEditorKind {
23
+ return isAgentWorkspaceSkillBundleCommandEditorKind(kind as AgentWorkspaceSkillBundleCommandEditorKind);
24
+ }
25
+
26
+ function isAffirmative(value: string): boolean {
27
+ return /^(y|yes|true)$/i.test(value.trim());
28
+ }
29
+
30
+ function unconfirmed(editor: AgentWorkspaceLocalEditor, message: string): AgentWorkspaceSkillBundleCommandEditorSubmission {
31
+ return {
32
+ kind: 'editor',
33
+ editor: { ...editor, message },
34
+ status: message,
35
+ };
36
+ }
37
+
38
+ function dispatch(command: string, title: string, detail: string, safety: AgentWorkspaceActionResult['safety']): AgentWorkspaceSkillBundleCommandEditorSubmission {
39
+ return {
40
+ kind: 'dispatch',
41
+ command,
42
+ status: `${title}.`,
43
+ actionResult: { kind: 'dispatched', title, detail, command, safety },
44
+ };
45
+ }
46
+
47
+ export function buildAgentWorkspaceSkillBundleCommandEditorSubmission(
48
+ editor: AgentWorkspaceLocalEditor,
49
+ readField: AgentWorkspaceFieldReader,
50
+ ): AgentWorkspaceSkillBundleCommandEditorSubmission {
51
+ if (editor.kind === 'skill-bundle-search') {
52
+ const query = readField('query').trim();
53
+ const command = query.length > 0 ? `/agent-skills bundle search ${quoteSlashCommandArg(query)}` : '/agent-skills bundle search';
54
+ return dispatch(command, 'Opening skill bundle search', 'The workspace handed a read-only skill bundle search command to the shell-owned command router.', 'read-only');
55
+ }
56
+ if (editor.kind === 'skill-bundle-show') {
57
+ return dispatch(
58
+ `/agent-skills bundle show ${quoteSlashCommandArg(readField('id'))}`,
59
+ 'Opening skill bundle detail',
60
+ 'The workspace handed a read-only skill bundle detail command to the shell-owned command router.',
61
+ 'read-only',
62
+ );
63
+ }
64
+ if (editor.kind === 'skill-bundle-update') {
65
+ if (!isAffirmative(readField('confirm'))) return unconfirmed(editor, 'Skill bundle update not confirmed. Type yes, then press Enter.');
66
+ const parts = ['/agent-skills', 'bundle', 'update', quoteSlashCommandArg(readField('id'))];
67
+ const name = readField('name');
68
+ const description = readField('description');
69
+ const skills = readField('skills');
70
+ if (name.length > 0) parts.push('--name', quoteSlashCommandArg(name));
71
+ if (description.length > 0) parts.push('--description', quoteSlashCommandArg(description));
72
+ if (skills.length > 0) parts.push('--skills', quoteSlashCommandArg(skills));
73
+ return dispatch(parts.join(' '), 'Opening skill bundle update', 'The workspace handed a confirmed skill bundle update command to the shell-owned command router.', 'safe');
74
+ }
75
+ if (editor.kind === 'skill-bundle-enable' || editor.kind === 'skill-bundle-disable' || editor.kind === 'skill-bundle-review') {
76
+ if (!isAffirmative(readField('confirm'))) return unconfirmed(editor, 'Skill bundle action not confirmed. Type yes, then press Enter.');
77
+ const verb = editor.kind.replace('skill-bundle-', '');
78
+ return dispatch(
79
+ `/agent-skills bundle ${verb} ${quoteSlashCommandArg(readField('id'))}`,
80
+ `Opening skill bundle ${verb}`,
81
+ `The workspace handed a confirmed skill bundle ${verb} command to the shell-owned command router.`,
82
+ 'safe',
83
+ );
84
+ }
85
+ if (editor.kind === 'skill-bundle-stale') {
86
+ if (!isAffirmative(readField('confirm'))) return unconfirmed(editor, 'Skill bundle stale action not confirmed. Type yes, then press Enter.');
87
+ return dispatch(
88
+ `/agent-skills bundle stale ${quoteSlashCommandArg(readField('id'))} ${quoteSlashCommandArg(readField('reason'))}`,
89
+ 'Opening skill bundle stale review',
90
+ 'The workspace handed a confirmed skill bundle stale command to the shell-owned command router.',
91
+ 'safe',
92
+ );
93
+ }
94
+ if (!isAffirmative(readField('confirm'))) return unconfirmed(editor, 'Skill bundle delete not confirmed. Type yes, then press Enter.');
95
+ return dispatch(
96
+ `/agent-skills bundle delete ${quoteSlashCommandArg(readField('id'))} --yes`,
97
+ 'Opening skill bundle delete',
98
+ 'The workspace handed a confirmed skill bundle delete command to the shell-owned command router.',
99
+ 'safe',
100
+ );
101
+ }
@@ -0,0 +1,110 @@
1
+ import type { AgentWorkspaceEditorKind, AgentWorkspaceLocalEditor } from './agent-workspace-types.ts';
2
+
3
+ export type AgentWorkspaceSkillBundleCommandEditorKind = Extract<
4
+ AgentWorkspaceEditorKind,
5
+ | 'skill-bundle-search'
6
+ | 'skill-bundle-show'
7
+ | 'skill-bundle-update'
8
+ | 'skill-bundle-enable'
9
+ | 'skill-bundle-disable'
10
+ | 'skill-bundle-review'
11
+ | 'skill-bundle-stale'
12
+ | 'skill-bundle-delete'
13
+ >;
14
+
15
+ export function isAgentWorkspaceSkillBundleCommandEditorKind(kind: AgentWorkspaceEditorKind): kind is AgentWorkspaceSkillBundleCommandEditorKind {
16
+ return kind === 'skill-bundle-search'
17
+ || kind === 'skill-bundle-show'
18
+ || kind === 'skill-bundle-update'
19
+ || kind === 'skill-bundle-enable'
20
+ || kind === 'skill-bundle-disable'
21
+ || kind === 'skill-bundle-review'
22
+ || kind === 'skill-bundle-stale'
23
+ || kind === 'skill-bundle-delete';
24
+ }
25
+
26
+ export function createAgentWorkspaceSkillBundleCommandEditor(kind: AgentWorkspaceSkillBundleCommandEditorKind): AgentWorkspaceLocalEditor {
27
+ if (kind === 'skill-bundle-search') {
28
+ return {
29
+ kind,
30
+ mode: 'create',
31
+ title: 'Search Skill Bundles',
32
+ selectedFieldIndex: 0,
33
+ message: 'Search local Agent skill bundles by name, description, or member skill.',
34
+ fields: [
35
+ { id: 'query', label: 'Search query', value: '', required: false, multiline: false, hint: 'Optional text query. Blank lists every bundle.' },
36
+ ],
37
+ };
38
+ }
39
+ if (kind === 'skill-bundle-show') {
40
+ return {
41
+ kind,
42
+ mode: 'create',
43
+ title: 'Show Skill Bundle',
44
+ selectedFieldIndex: 0,
45
+ message: 'Show one local Agent skill bundle with readiness and member skills.',
46
+ fields: [
47
+ { id: 'id', label: 'Bundle id', value: '', required: true, multiline: false, hint: 'Existing local skill bundle id.' },
48
+ ],
49
+ };
50
+ }
51
+ if (kind === 'skill-bundle-update') {
52
+ return {
53
+ kind,
54
+ mode: 'update',
55
+ title: 'Update Skill Bundle',
56
+ selectedFieldIndex: 0,
57
+ message: 'Update one local Agent skill bundle. Type yes on the final field to confirm.',
58
+ fields: [
59
+ { id: 'id', label: 'Bundle id', value: '', required: true, multiline: false, hint: 'Existing local skill bundle id.' },
60
+ { id: 'name', label: 'Name', value: '', required: false, multiline: false, hint: 'Optional replacement name.' },
61
+ { id: 'description', label: 'Description', value: '', required: false, multiline: false, hint: 'Optional replacement one-line description.' },
62
+ { id: 'skills', label: 'Skill ids', value: '', required: false, multiline: false, hint: 'Optional replacement comma-separated local skill ids.' },
63
+ { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /agent-skills bundle update.' },
64
+ ],
65
+ };
66
+ }
67
+ if (kind === 'skill-bundle-stale') {
68
+ return {
69
+ kind,
70
+ mode: 'update',
71
+ title: 'Mark Skill Bundle Stale',
72
+ selectedFieldIndex: 0,
73
+ message: 'Mark one local Agent skill bundle stale with a review reason. Type yes on the final field to confirm.',
74
+ fields: [
75
+ { id: 'id', label: 'Bundle id', value: '', required: true, multiline: false, hint: 'Existing local skill bundle id.' },
76
+ { id: 'reason', label: 'Reason', value: '', required: true, multiline: true, hint: 'Why this bundle needs review. Ctrl-J inserts a new line.' },
77
+ { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /agent-skills bundle stale.' },
78
+ ],
79
+ };
80
+ }
81
+ if (kind === 'skill-bundle-delete') {
82
+ return {
83
+ kind,
84
+ mode: 'delete',
85
+ title: 'Delete Skill Bundle',
86
+ selectedFieldIndex: 0,
87
+ message: 'Delete one local Agent skill bundle. This does not delete member skills. Type yes to confirm.',
88
+ fields: [
89
+ { id: 'id', label: 'Bundle id', value: '', required: true, multiline: false, hint: 'Existing local skill bundle id.' },
90
+ { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /agent-skills bundle delete with --yes.' },
91
+ ],
92
+ };
93
+ }
94
+ const verb = kind === 'skill-bundle-enable'
95
+ ? 'Enable'
96
+ : kind === 'skill-bundle-disable'
97
+ ? 'Disable'
98
+ : 'Review';
99
+ return {
100
+ kind,
101
+ mode: 'update',
102
+ title: `${verb} Skill Bundle`,
103
+ selectedFieldIndex: 0,
104
+ message: `${verb} one local Agent skill bundle. Type yes on the final field to confirm.`,
105
+ fields: [
106
+ { id: 'id', label: 'Bundle id', value: '', required: true, multiline: false, hint: 'Existing local skill bundle id.' },
107
+ { id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: `Type yes to run /agent-skills bundle ${verb.toLowerCase()}.` },
108
+ ],
109
+ };
110
+ }
@@ -2,10 +2,18 @@ import { basename, sep } from 'node:path';
2
2
  import type { MemoryRecord } from '@pellux/goodvibes-sdk/platform/state';
3
3
  import type { CommandContext } from './command-registry.ts';
4
4
  import { AgentPersonaRegistry, type AgentPersonaRecord } from '../agent/persona-registry.ts';
5
- import { AgentRoutineRegistry, type AgentRoutineRecord } from '../agent/routine-registry.ts';
6
- import { AgentSkillRegistry, type AgentSkillBundleRecord, type AgentSkillRecord } from '../agent/skill-registry.ts';
5
+ import { AgentRoutineRegistry, evaluateAgentRoutineReadiness, type AgentRoutineRecord } from '../agent/routine-registry.ts';
6
+ import {
7
+ AgentSkillRegistry,
8
+ evaluateAgentSkillBundleReadiness,
9
+ evaluateAgentSkillReadiness,
10
+ formatAgentSkillRequirement,
11
+ type AgentSkillBundleRecord,
12
+ type AgentSkillRecord,
13
+ } from '../agent/skill-registry.ts';
14
+ import { summarizeAgentBehaviorDiscovery } from '../agent/behavior-discovery-summary.ts';
7
15
  import { isPromptActiveMemory } from '../agent/memory-prompt.ts';
8
- import { getAgentRuntimeProfilesRoot, listAgentRuntimeProfiles, listAgentRuntimeProfileTemplates } from '../agent/runtime-profile.ts';
16
+ import { getAgentRuntimeProfilesRoot, listAgentRuntimeProfiles, listAgentRuntimeProfileTemplates, readAgentRuntimeProfileSelection } from '../agent/runtime-profile.ts';
9
17
  import { buildAgentWorkspaceChannels } from './agent-workspace-channels.ts';
10
18
  import { buildAgentWorkspaceSetupChecklist } from './agent-workspace-setup.ts';
11
19
  import { buildAgentWorkspaceVoiceMediaReadiness, type AgentWorkspaceVoiceMediaProviderDescriptor } from './agent-workspace-voice-media.ts';
@@ -62,6 +70,12 @@ function inferActiveRuntimeProfile(homeDirectory: string): string {
62
70
  return homeDirectory.includes(marker) ? basename(homeDirectory) : '(default home)';
63
71
  }
64
72
 
73
+ function inferRuntimeProfileBaseHome(homeDirectory: string): string {
74
+ const marker = `${sep}.goodvibes${sep}agent${sep}profile-homes${sep}`;
75
+ const markerIndex = homeDirectory.indexOf(marker);
76
+ return markerIndex >= 0 ? homeDirectory.slice(0, markerIndex) : homeDirectory;
77
+ }
78
+
65
79
  function summarizePersonaItem(persona: AgentPersonaRecord, activePersonaId: string | null): AgentWorkspaceLocalLibraryItem {
66
80
  return {
67
81
  id: persona.id,
@@ -76,6 +90,7 @@ function summarizePersonaItem(persona: AgentPersonaRecord, activePersonaId: stri
76
90
  }
77
91
 
78
92
  function summarizeSkillItem(skill: AgentSkillRecord): AgentWorkspaceLocalLibraryItem {
93
+ const readiness = evaluateAgentSkillReadiness(skill);
79
94
  return {
80
95
  id: skill.id,
81
96
  name: skill.name,
@@ -85,10 +100,18 @@ function summarizeSkillItem(skill: AgentSkillRecord): AgentWorkspaceLocalLibrary
85
100
  tags: skill.tags,
86
101
  triggers: skill.triggers,
87
102
  enabled: skill.enabled,
103
+ requirementCount: skill.requirements.length,
104
+ missingRequirementCount: readiness.missing.length,
105
+ missingRequirements: readiness.missing.map(formatAgentSkillRequirement),
88
106
  };
89
107
  }
90
108
 
91
- function summarizeSkillBundleItem(bundle: AgentSkillBundleRecord): AgentWorkspaceLocalLibraryItem {
109
+ function summarizeSkillBundleItem(bundle: AgentSkillBundleRecord, skills: readonly AgentSkillRecord[]): AgentWorkspaceLocalLibraryItem {
110
+ const readiness = evaluateAgentSkillBundleReadiness(bundle, skills);
111
+ const missing = [
112
+ ...readiness.missingRequirements.map(formatAgentSkillRequirement),
113
+ ...readiness.missingSkillIds.map((skillId) => `skill:${skillId}`),
114
+ ];
92
115
  return {
93
116
  id: bundle.id,
94
117
  name: bundle.name,
@@ -98,10 +121,14 @@ function summarizeSkillBundleItem(bundle: AgentSkillBundleRecord): AgentWorkspac
98
121
  tags: bundle.skillIds,
99
122
  triggers: [],
100
123
  enabled: bundle.enabled,
124
+ requirementCount: readiness.includedSkills.reduce((total, skill) => total + skill.requirements.length, 0) + readiness.missingSkillIds.length,
125
+ missingRequirementCount: missing.length,
126
+ missingRequirements: missing,
101
127
  };
102
128
  }
103
129
 
104
130
  function summarizeRoutineItem(routine: AgentRoutineRecord): AgentWorkspaceLocalLibraryItem {
131
+ const readiness = evaluateAgentRoutineReadiness(routine);
105
132
  return {
106
133
  id: routine.id,
107
134
  name: routine.name,
@@ -111,6 +138,9 @@ function summarizeRoutineItem(routine: AgentRoutineRecord): AgentWorkspaceLocalL
111
138
  tags: routine.tags,
112
139
  triggers: routine.triggers,
113
140
  enabled: routine.enabled,
141
+ requirementCount: routine.requirements.length,
142
+ missingRequirementCount: readiness.missing.length,
143
+ missingRequirements: readiness.missing.map(formatAgentSkillRequirement),
114
144
  startCount: routine.startCount,
115
145
  };
116
146
  }
@@ -213,7 +243,7 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
213
243
  bundleCount: snapshot.bundles.length,
214
244
  enabledBundleCount: snapshot.enabledBundles.length,
215
245
  items: snapshot.skills.map(summarizeSkillItem),
216
- bundleItems: snapshot.bundles.map(summarizeSkillBundleItem),
246
+ bundleItems: snapshot.bundles.map((bundle) => summarizeSkillBundleItem(bundle, snapshot.skills)),
217
247
  };
218
248
  } catch {
219
249
  return { count: 0, enabled: 0, active: 0, bundleCount: 0, enabledBundleCount: 0, items: [], bundleItems: [] };
@@ -233,20 +263,29 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
233
263
  return { count: 0, enabled: 0, items: [] };
234
264
  }
235
265
  })();
266
+ const discoveredBehavior = summarizeAgentBehaviorDiscovery(context.workspace?.shellPaths);
267
+ const profileBaseHome = inferRuntimeProfileBaseHome(context.workspace?.shellPaths?.homeDirectory ?? '');
236
268
  const runtimeProfiles = (() => {
237
269
  try {
238
- return listAgentRuntimeProfiles(context.workspace?.shellPaths?.homeDirectory ?? '');
270
+ return listAgentRuntimeProfiles(profileBaseHome);
239
271
  } catch {
240
272
  return [];
241
273
  }
242
274
  })();
243
275
  const runtimeStarterTemplates = (() => {
244
276
  try {
245
- return listAgentRuntimeProfileTemplates(context.workspace?.shellPaths?.homeDirectory ?? '');
277
+ return listAgentRuntimeProfileTemplates(profileBaseHome);
246
278
  } catch {
247
279
  return [];
248
280
  }
249
281
  })();
282
+ const selectedRuntimeProfile = (() => {
283
+ try {
284
+ return readAgentRuntimeProfileSelection(profileBaseHome);
285
+ } catch {
286
+ return null;
287
+ }
288
+ })();
250
289
  const voiceProviders = (() => {
251
290
  try {
252
291
  return context.platform?.voiceProviderRegistry?.list?.() ?? [];
@@ -312,11 +351,16 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
312
351
  localMemoryReviewQueueCount: memorySnapshot.reviewQueueCount,
313
352
  routineCount: routineSnapshot.count,
314
353
  enabledRoutineCount: routineSnapshot.enabled,
354
+ missingRoutineRequirementCount: routineSnapshot.items.reduce((total, item) => total + (item.missingRequirementCount ?? 0), 0),
315
355
  skillCount: skillSnapshot.count,
316
356
  enabledSkillCount: skillSnapshot.enabled,
317
357
  skillBundleCount: skillSnapshot.bundleCount,
318
358
  enabledSkillBundleCount: skillSnapshot.enabledBundleCount,
359
+ missingSkillRequirementCount: skillSnapshot.items.reduce((total, item) => total + (item.missingRequirementCount ?? 0), 0),
319
360
  activePersonaName: personaSnapshot.activeName,
361
+ discoveredPersonas: discoveredBehavior.personas,
362
+ discoveredSkills: discoveredBehavior.skills,
363
+ discoveredRoutines: discoveredBehavior.routines,
320
364
  readyChannelCount: channels.filter((channel) => channel.ready).length,
321
365
  voiceProviderCount: voiceProviders.length,
322
366
  mediaProviderCount: mediaProviders.length,
@@ -351,6 +395,7 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
351
395
  localPersonaCount: personaSnapshot.count,
352
396
  activePersonaName: personaSnapshot.activeName,
353
397
  localPersonas: personaSnapshot.items,
398
+ discoveredBehavior,
354
399
  knowledgeRoute: '/api/goodvibes-agent/knowledge',
355
400
  knowledgeIsolation: 'agent-only',
356
401
  executionPolicy: 'serial-proactive',
@@ -375,9 +420,12 @@ export function buildAgentWorkspaceRuntimeSnapshot(context: CommandContext): Age
375
420
  browserToolExposureEnabled: readConfigBoolean(context, 'web.enabled', false),
376
421
  browserToolPublicBaseUrl: readConfigString(context, 'web.publicBaseUrl', '(not configured)'),
377
422
  activeRuntimeProfile: inferActiveRuntimeProfile(context.workspace?.shellPaths?.homeDirectory ?? ''),
423
+ selectedRuntimeProfile: selectedRuntimeProfile?.id ?? null,
424
+ selectedRuntimeProfileExists: selectedRuntimeProfile?.exists ?? false,
425
+ selectedRuntimeProfileSelectedAt: selectedRuntimeProfile?.selectedAt ?? null,
378
426
  runtimeProfileCount: runtimeProfiles.length,
379
427
  runtimeProfiles: runtimeProfiles.map(summarizeRuntimeProfile),
380
- runtimeProfileRoot: getAgentRuntimeProfilesRoot(context.workspace?.shellPaths?.homeDirectory ?? ''),
428
+ runtimeProfileRoot: getAgentRuntimeProfilesRoot(profileBaseHome),
381
429
  runtimeStarterTemplateCount: runtimeStarterTemplates.length,
382
430
  localStarterTemplateCount: runtimeStarterTemplates.filter((template) => template.source === 'local').length,
383
431
  runtimeStarterTemplates: runtimeStarterTemplates.map(summarizeStarterTemplate),
@@ -0,0 +1,61 @@
1
+ import type { AgentWorkspaceActionResult, AgentWorkspaceEditorKind, AgentWorkspaceLocalEditor } from './agent-workspace-types.ts';
2
+ import type { AgentWorkspaceTaskCommandEditorKind } from './agent-workspace-task-command-editors.ts';
3
+ import { isAgentWorkspaceTaskCommandEditorKind } from './agent-workspace-task-command-editors.ts';
4
+ import { quoteSlashCommandArg } from './slash-command-parser.ts';
5
+
6
+ type AgentWorkspaceFieldReader = (fieldId: string) => string;
7
+
8
+ export type AgentWorkspaceTaskCommandEditorSubmission =
9
+ | {
10
+ readonly kind: 'editor';
11
+ readonly editor: AgentWorkspaceLocalEditor;
12
+ readonly status: string;
13
+ readonly actionResult?: AgentWorkspaceActionResult;
14
+ }
15
+ | {
16
+ readonly kind: 'dispatch';
17
+ readonly command: string;
18
+ readonly status: string;
19
+ readonly actionResult: AgentWorkspaceActionResult;
20
+ };
21
+
22
+ export function isAgentWorkspaceTaskCommandSubmissionKind(kind: AgentWorkspaceEditorKind): kind is AgentWorkspaceTaskCommandEditorKind {
23
+ return isAgentWorkspaceTaskCommandEditorKind(kind);
24
+ }
25
+
26
+ export function buildAgentWorkspaceTaskCommandEditorSubmission(
27
+ editor: AgentWorkspaceLocalEditor,
28
+ readField: AgentWorkspaceFieldReader,
29
+ ): AgentWorkspaceTaskCommandEditorSubmission {
30
+ if (editor.kind === 'task-list-filter') {
31
+ const filter = readField('filter');
32
+ const command = filter.length > 0 ? `/tasks list ${quoteSlashCommandArg(filter)}` : '/tasks list';
33
+ return {
34
+ kind: 'dispatch',
35
+ command,
36
+ status: 'Opening filtered task list.',
37
+ actionResult: {
38
+ kind: 'dispatched',
39
+ title: 'Opening filtered task list',
40
+ detail: 'The workspace handed read-only connected-host task listing to the shell-owned command router.',
41
+ command,
42
+ safety: 'read-only',
43
+ },
44
+ };
45
+ }
46
+ const subcommand = editor.kind === 'task-output' ? 'output' : 'show';
47
+ const command = `/tasks ${subcommand} ${quoteSlashCommandArg(readField('taskId'))}`;
48
+ const title = editor.kind === 'task-output' ? 'Opening task output' : 'Opening task inspection';
49
+ return {
50
+ kind: 'dispatch',
51
+ command,
52
+ status: `${title}.`,
53
+ actionResult: {
54
+ kind: 'dispatched',
55
+ title,
56
+ detail: 'The workspace handed read-only connected-host task inspection to the shell-owned command router.',
57
+ command,
58
+ safety: 'read-only',
59
+ },
60
+ };
61
+ }
@@ -0,0 +1,47 @@
1
+ import type { AgentWorkspaceEditorKind, AgentWorkspaceLocalEditor } from './agent-workspace-types.ts';
2
+
3
+ export type AgentWorkspaceTaskCommandEditorKind = Extract<
4
+ AgentWorkspaceEditorKind,
5
+ 'task-list-filter' | 'task-show' | 'task-output'
6
+ >;
7
+
8
+ export function isAgentWorkspaceTaskCommandEditorKind(kind: AgentWorkspaceEditorKind): kind is AgentWorkspaceTaskCommandEditorKind {
9
+ return kind === 'task-list-filter' || kind === 'task-show' || kind === 'task-output';
10
+ }
11
+
12
+ export function createAgentWorkspaceTaskCommandEditor(kind: AgentWorkspaceTaskCommandEditorKind): AgentWorkspaceLocalEditor {
13
+ if (kind === 'task-list-filter') {
14
+ return {
15
+ kind,
16
+ mode: 'create',
17
+ title: 'Filter Runtime Tasks',
18
+ selectedFieldIndex: 0,
19
+ message: 'List connected-host tasks filtered by status or kind. This is read-only and never creates, retries, or cancels tasks.',
20
+ fields: [
21
+ { id: 'filter', label: 'Status or kind', value: '', required: false, multiline: false, hint: 'Optional task status or kind. Blank lists recent tasks.' },
22
+ ],
23
+ };
24
+ }
25
+ if (kind === 'task-output') {
26
+ return {
27
+ kind,
28
+ mode: 'create',
29
+ title: 'Show Task Output',
30
+ selectedFieldIndex: 0,
31
+ message: 'Print one connected-host task output from the Agent workspace. This is read-only and does not retry, cancel, or mutate the task.',
32
+ fields: [
33
+ { id: 'taskId', label: 'Task id', value: '', required: true, multiline: false, hint: 'Connected-host task id from Runtime tasks.' },
34
+ ],
35
+ };
36
+ }
37
+ return {
38
+ kind,
39
+ mode: 'create',
40
+ title: 'Inspect Runtime Task',
41
+ selectedFieldIndex: 0,
42
+ message: 'Inspect one connected-host task from the Agent workspace. This is read-only and does not retry, cancel, or mutate the task.',
43
+ fields: [
44
+ { id: 'taskId', label: 'Task id', value: '', required: true, multiline: false, hint: 'Connected-host task id from Runtime tasks.' },
45
+ ],
46
+ };
47
+ }
@@ -1,6 +1,7 @@
1
1
  import type { AgentWorkspaceChannelStatus } from './agent-workspace-channels.ts';
2
2
  import type { AgentWorkspaceSetupChecklistItem } from './agent-workspace-setup.ts';
3
3
  import type { AgentWorkspaceVoiceMediaReadiness } from './agent-workspace-voice-media.ts';
4
+ import type { AgentBehaviorDiscoverySnapshot } from '../agent/behavior-discovery-summary.ts';
4
5
 
5
6
  export const AGENT_WORKSPACE_MODAL_NAME = 'agentWorkspace';
6
7
 
@@ -13,24 +14,139 @@ export type AgentWorkspaceLocalEditorKind = 'memory' | 'persona' | 'skill' | 'ro
13
14
  export type AgentWorkspaceEditorKind =
14
15
  | AgentWorkspaceLocalEditorKind
15
16
  | 'knowledge-url'
17
+ | 'knowledge-urls'
16
18
  | 'knowledge-file'
17
19
  | 'knowledge-bookmarks'
18
20
  | 'knowledge-browser-history'
19
21
  | 'knowledge-connector-ingest'
22
+ | 'knowledge-connector-show'
23
+ | 'knowledge-connector-doctor'
24
+ | 'knowledge-reindex'
20
25
  | 'knowledge-search'
21
26
  | 'knowledge-ask'
27
+ | 'knowledge-get'
28
+ | 'knowledge-map'
29
+ | 'knowledge-review-issue'
30
+ | 'knowledge-consolidate'
31
+ | 'knowledge-packet'
32
+ | 'knowledge-explain'
33
+ | 'memory-search'
34
+ | 'memory-get'
35
+ | 'memory-explain'
36
+ | 'memory-promote'
37
+ | 'memory-link'
38
+ | 'memory-export'
39
+ | 'memory-import'
40
+ | 'memory-handoff-export'
41
+ | 'memory-handoff-inspect'
42
+ | 'memory-handoff-import'
43
+ | 'memory-vector-rebuild'
44
+ | 'persona-search'
45
+ | 'persona-show'
46
+ | 'skill-search'
47
+ | 'skill-show'
48
+ | 'routine-search'
49
+ | 'routine-show'
50
+ | 'plan-seed'
22
51
  | 'mcp-server'
52
+ | 'mcp-tools-server'
53
+ | 'mcp-repair'
23
54
  | 'notify-webhook'
24
55
  | 'notify-webhook-remove'
56
+ | 'notify-webhook-clear'
25
57
  | 'notify-webhook-test'
58
+ | 'secret-set'
59
+ | 'secret-link'
60
+ | 'secret-test'
61
+ | 'secret-delete'
26
62
  | 'tts-prompt'
27
63
  | 'image-input'
28
64
  | 'skill-bundle'
65
+ | 'skill-bundle-search'
66
+ | 'skill-bundle-show'
67
+ | 'skill-bundle-update'
68
+ | 'skill-bundle-enable'
69
+ | 'skill-bundle-disable'
70
+ | 'skill-bundle-review'
71
+ | 'skill-bundle-stale'
72
+ | 'skill-bundle-delete'
29
73
  | 'persona-discovery-import'
30
74
  | 'routine-discovery-import'
31
75
  | 'skill-discovery-import'
76
+ | 'learned-behavior'
32
77
  | 'profile-template-export'
33
78
  | 'profile-template-import'
79
+ | 'profile-template-show'
80
+ | 'profile-template-from-discovered'
81
+ | 'profile-from-discovered'
82
+ | 'profile-show'
83
+ | 'profile-default'
84
+ | 'profile-default-clear'
85
+ | 'profile-delete'
86
+ | 'provider-add'
87
+ | 'provider-remove'
88
+ | 'provider-use'
89
+ | 'provider-inspect'
90
+ | 'provider-routes'
91
+ | 'provider-account-repair'
92
+ | 'auth-show'
93
+ | 'auth-repair'
94
+ | 'auth-bundle-export'
95
+ | 'auth-bundle-inspect'
96
+ | 'trust-bundle-export'
97
+ | 'trust-bundle-inspect'
98
+ | 'support-bundle-export'
99
+ | 'support-bundle-inspect'
100
+ | 'support-bundle-import'
101
+ | 'subscription-inspect'
102
+ | 'subscription-login-start'
103
+ | 'subscription-login-finish'
104
+ | 'subscription-logout'
105
+ | 'subscription-bundle-export'
106
+ | 'subscription-bundle-inspect'
107
+ | 'voice-enable'
108
+ | 'voice-disable'
109
+ | 'voice-bundle-export'
110
+ | 'voice-bundle-inspect'
111
+ | 'conversation-export'
112
+ | 'conversation-events'
113
+ | 'conversation-groups'
114
+ | 'conversation-find'
115
+ | 'effort-level'
116
+ | 'channel-show'
117
+ | 'channel-doctor'
118
+ | 'channel-setup'
119
+ | 'session-save'
120
+ | 'session-load'
121
+ | 'session-rename'
122
+ | 'session-resume'
123
+ | 'session-info'
124
+ | 'session-export-saved'
125
+ | 'session-search'
126
+ | 'session-delete'
127
+ | 'session-fork'
128
+ | 'session-graph'
129
+ | 'task-list-filter'
130
+ | 'task-show'
131
+ | 'task-output'
132
+ | 'plan-show'
133
+ | 'plan-approve'
134
+ | 'plan-override'
135
+ | 'plan-clear'
136
+ | 'health-repair'
137
+ | 'approval-review'
138
+ | 'routine-receipt'
139
+ | 'schedule-receipt'
140
+ | 'mode-preset'
141
+ | 'mode-domain'
142
+ | 'model-pin'
143
+ | 'model-unpin'
144
+ | 'delegate-task'
145
+ | 'workplan-add'
146
+ | 'workplan-show'
147
+ | 'workplan-status'
148
+ | 'workplan-delete'
149
+ | 'workplan-clear-completed'
34
150
  | 'routine-schedule'
35
151
  | 'reminder-schedule';
36
152
 
@@ -63,6 +179,7 @@ export interface AgentWorkspaceEditorField {
63
179
  readonly required: boolean;
64
180
  readonly multiline: boolean;
65
181
  readonly hint: string;
182
+ readonly redact?: boolean;
66
183
  }
67
184
 
68
185
  export interface AgentWorkspaceLocalEditor {
@@ -123,6 +240,9 @@ export interface AgentWorkspaceLocalLibraryItem {
123
240
  readonly confidence?: number;
124
241
  readonly active?: boolean;
125
242
  readonly enabled?: boolean;
243
+ readonly requirementCount?: number;
244
+ readonly missingRequirementCount?: number;
245
+ readonly missingRequirements?: readonly string[];
126
246
  readonly startCount?: number;
127
247
  }
128
248
 
@@ -171,6 +291,7 @@ export interface AgentWorkspaceRuntimeSnapshot {
171
291
  readonly localPersonaCount: number;
172
292
  readonly activePersonaName: string;
173
293
  readonly localPersonas: readonly AgentWorkspaceLocalLibraryItem[];
294
+ readonly discoveredBehavior: AgentBehaviorDiscoverySnapshot;
174
295
  readonly knowledgeRoute: '/api/goodvibes-agent/knowledge';
175
296
  readonly knowledgeIsolation: 'agent-only';
176
297
  readonly executionPolicy: 'serial-proactive';
@@ -195,6 +316,9 @@ export interface AgentWorkspaceRuntimeSnapshot {
195
316
  readonly browserToolExposureEnabled: boolean;
196
317
  readonly browserToolPublicBaseUrl: string;
197
318
  readonly activeRuntimeProfile: string;
319
+ readonly selectedRuntimeProfile: string | null;
320
+ readonly selectedRuntimeProfileExists: boolean;
321
+ readonly selectedRuntimeProfileSelectedAt: string | null;
198
322
  readonly runtimeProfileCount: number;
199
323
  readonly runtimeProfiles: readonly AgentWorkspaceRuntimeProfileItem[];
200
324
  readonly runtimeProfileRoot: string;
@@ -150,7 +150,7 @@ function missingSelectedProviderStatus(selectedProviderId: string): AgentWorkspa
150
150
  secretKeyOptions: [],
151
151
  configuredSecretKeys: [],
152
152
  missingSecretKeyOptions: [],
153
- nextStep: `Selected TTS provider ${selectedProviderId} is not registered in connected GoodVibes services.`,
153
+ nextStep: `Selected TTS provider ${selectedProviderId} is not registered by the connected GoodVibes host.`,
154
154
  };
155
155
  }
156
156