@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.
- package/CHANGELOG.md +41 -650
- package/README.md +40 -50
- package/dist/package/main.js +38224 -35673
- package/docs/README.md +5 -4
- package/docs/{connected-services.md → connected-host.md} +18 -10
- package/docs/getting-started.md +43 -42
- package/docs/release-and-publishing.md +6 -4
- package/package.json +3 -3
- package/src/agent/behavior-discovery-summary.ts +165 -0
- package/src/agent/persona-discovery.ts +1 -3
- package/src/agent/persona-registry.ts +5 -3
- package/src/agent/reminder-schedule-format.ts +6 -6
- package/src/agent/reminder-schedule.ts +1 -1
- package/src/agent/routine-registry.ts +43 -4
- package/src/agent/routine-schedule-format.ts +6 -6
- package/src/agent/routine-schedule-promotion.ts +1 -1
- package/src/agent/routine-schedule-receipts.ts +1 -1
- package/src/agent/runtime-profile-starters.ts +331 -0
- package/src/agent/runtime-profile.ts +228 -330
- package/src/agent/skill-registry.ts +190 -13
- package/src/cli/agent-knowledge-command.ts +2 -2
- package/src/cli/agent-knowledge-format.ts +2 -2
- package/src/cli/agent-knowledge-runtime.ts +1 -1
- package/src/cli/bundle-command.ts +1 -1
- package/src/cli/entrypoint.ts +16 -7
- package/src/cli/help.ts +26 -19
- package/src/cli/local-library-command.ts +75 -21
- package/src/cli/management-commands.ts +7 -6
- package/src/cli/management.ts +6 -51
- package/src/cli/parser.ts +23 -2
- package/src/cli/profiles-command.ts +247 -1
- package/src/cli/routines-command.ts +139 -11
- package/src/cli/service-posture.ts +11 -11
- package/src/cli/status.ts +21 -25
- package/src/input/agent-workspace-access-command-editor-submission.ts +149 -0
- package/src/input/agent-workspace-access-command-editors.ts +170 -0
- package/src/input/agent-workspace-activation.ts +2 -1
- package/src/input/agent-workspace-basic-command-editor-submission.ts +787 -0
- package/src/input/agent-workspace-basic-command-editors.ts +524 -459
- package/src/input/agent-workspace-categories.ts +177 -14
- package/src/input/agent-workspace-channel-command-editor-submission.ts +49 -0
- package/src/input/agent-workspace-channel-command-editors.ts +47 -0
- package/src/input/agent-workspace-command-editor.ts +25 -1
- package/src/input/agent-workspace-delegation-editor-submission.ts +55 -0
- package/src/input/agent-workspace-editors.ts +27 -0
- package/src/input/agent-workspace-knowledge-command-editor-submission.ts +132 -0
- package/src/input/agent-workspace-knowledge-command-editors.ts +110 -0
- package/src/input/agent-workspace-learned-behavior.ts +67 -0
- package/src/input/agent-workspace-library-command-editor-submission.ts +50 -0
- package/src/input/agent-workspace-library-command-editors.ts +35 -0
- package/src/input/agent-workspace-mcp-command-editor-submission.ts +95 -0
- package/src/input/agent-workspace-memory-command-editor-submission.ts +232 -0
- package/src/input/agent-workspace-memory-command-editors.ts +180 -0
- package/src/input/agent-workspace-navigation.ts +45 -0
- package/src/input/agent-workspace-notify-editor-submission.ts +107 -0
- package/src/input/agent-workspace-operations-command-editor-submission.ts +146 -0
- package/src/input/agent-workspace-operations-command-editors.ts +119 -0
- package/src/input/agent-workspace-provider-command-editor-submission.ts +155 -0
- package/src/input/agent-workspace-provider-command-editors.ts +93 -0
- package/src/input/agent-workspace-requirements.ts +11 -0
- package/src/input/agent-workspace-secret-editor-submission.ts +153 -0
- package/src/input/agent-workspace-session-command-editor-submission.ts +199 -0
- package/src/input/agent-workspace-session-command-editors.ts +249 -0
- package/src/input/agent-workspace-setup.ts +49 -19
- package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +101 -0
- package/src/input/agent-workspace-skill-bundle-command-editors.ts +110 -0
- package/src/input/agent-workspace-snapshot.ts +56 -8
- package/src/input/agent-workspace-task-command-editor-submission.ts +61 -0
- package/src/input/agent-workspace-task-command-editors.ts +47 -0
- package/src/input/agent-workspace-types.ts +124 -0
- package/src/input/agent-workspace-voice-media.ts +1 -1
- package/src/input/agent-workspace-workplan-editor-submission.ts +153 -0
- package/src/input/agent-workspace.ts +47 -37
- package/src/input/command-registry.ts +1 -1
- package/src/input/commands/agent-runtime-profile-runtime.ts +160 -6
- package/src/input/commands/agent-skills-runtime.ts +76 -12
- package/src/input/commands/agent-workspace-runtime.ts +4 -3
- package/src/input/commands/brief-runtime.ts +38 -9
- package/src/input/commands/channels-runtime.ts +3 -3
- package/src/input/commands/compat-runtime.ts +32 -0
- package/src/input/commands/health-runtime.ts +22 -24
- package/src/input/commands/knowledge.ts +26 -5
- package/src/input/commands/local-provider-runtime.ts +7 -3
- package/src/input/commands/local-setup-review.ts +4 -14
- package/src/input/commands/mcp-runtime.ts +8 -12
- package/src/input/commands/operator-runtime.ts +8 -67
- package/src/input/commands/personas-runtime.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +7 -70
- package/src/input/commands/policy-dispatch.ts +1 -1
- package/src/input/commands/policy.ts +1 -5
- package/src/input/commands/product-runtime.ts +2 -2
- package/src/input/commands/qrcode-runtime.ts +6 -4
- package/src/input/commands/routines-runtime.ts +44 -6
- package/src/input/commands/runtime-services.ts +1 -14
- package/src/input/commands/security-runtime.ts +3 -8
- package/src/input/commands/session-content.ts +1 -1
- package/src/input/commands/session-workflow.ts +5 -14
- package/src/input/commands/shell-core.ts +8 -2
- package/src/input/commands/subscription-runtime.ts +1 -6
- package/src/input/commands/support-bundle-runtime.ts +53 -0
- package/src/input/commands/tasks-runtime.ts +2 -2
- package/src/input/commands.ts +4 -0
- package/src/input/feed-context-factory.ts +0 -1
- package/src/input/handler-content-actions.ts +0 -25
- package/src/input/handler-feed.ts +0 -2
- package/src/input/handler-interactions.ts +2 -31
- package/src/input/handler-onboarding.ts +29 -12
- package/src/input/handler-shortcuts.ts +1 -3
- package/src/input/handler.ts +4 -7
- package/src/input/keybindings.ts +9 -9
- package/src/input/mcp-workspace.ts +90 -26
- package/src/input/onboarding/handler-onboarding-routes.ts +3 -1
- package/src/input/onboarding/onboarding-wizard-apply.ts +49 -0
- package/src/input/onboarding/onboarding-wizard-helpers.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-operator-steps.ts +126 -11
- package/src/input/onboarding/onboarding-wizard-steps.ts +15 -8
- package/src/input/onboarding/onboarding-wizard-types.ts +1 -0
- package/src/input/onboarding/onboarding-wizard.ts +19 -2
- package/src/input/profile-picker-modal.ts +2 -2
- package/src/input/settings-modal-agent-policy.ts +6 -6
- package/src/input/settings-modal-subscriptions.ts +3 -3
- package/src/input/settings-modal.ts +14 -14
- package/src/main.ts +0 -2
- package/src/panels/automation-control-panel.ts +3 -3
- package/src/panels/builtin/agent.ts +1 -1
- package/src/panels/builtin/operations.ts +2 -2
- package/src/panels/builtin/session.ts +26 -18
- package/src/panels/builtin/shared.ts +6 -6
- package/src/panels/project-planning-panel.ts +1 -1
- package/src/panels/provider-health-domains.ts +3 -3
- package/src/panels/qr-panel.ts +44 -20
- package/src/panels/subscription-panel.ts +3 -3
- package/src/panels/system-messages-panel.ts +2 -2
- package/src/panels/tasks-panel.ts +4 -4
- package/src/planning/project-planning-coordinator.ts +2 -2
- package/src/renderer/agent-workspace.ts +52 -5
- package/src/renderer/block-actions.ts +1 -3
- package/src/renderer/help-overlay.ts +13 -8
- package/src/renderer/mcp-workspace.ts +32 -13
- package/src/renderer/model-picker-overlay.ts +0 -1
- package/src/renderer/model-workspace.ts +0 -2
- package/src/renderer/onboarding/onboarding-wizard.ts +20 -4
- package/src/renderer/panel-picker-overlay.ts +1 -1
- package/src/renderer/profile-picker-modal.ts +2 -2
- package/src/renderer/settings-modal-helpers.ts +23 -23
- package/src/renderer/settings-modal.ts +18 -18
- package/src/renderer/system-message.ts +1 -1
- package/src/runtime/agent-runtime-events.ts +129 -0
- package/src/runtime/bootstrap-command-parts.ts +3 -2
- package/src/runtime/bootstrap-core.ts +4 -64
- package/src/runtime/bootstrap-shell.ts +42 -4
- package/src/runtime/bootstrap.ts +8 -27
- package/src/runtime/connected-host-auth.ts +42 -0
- package/src/runtime/diagnostics/panels/panel-resources.ts +1 -1
- package/src/runtime/index.ts +1 -5
- package/src/runtime/onboarding/apply.ts +213 -0
- package/src/runtime/onboarding/derivation.ts +25 -6
- package/src/runtime/onboarding/snapshot.ts +4 -2
- package/src/runtime/onboarding/types.ts +28 -1
- package/src/runtime/onboarding/verify.ts +81 -2
- package/src/runtime/operator-token-cleanup.ts +2 -2
- package/src/runtime/services.ts +27 -12
- package/src/shell/service-settings-sync.ts +7 -7
- package/src/shell/ui-openers.ts +27 -38
- package/src/tools/agent-local-registry-tool.ts +10 -4
- package/src/tools/agent-tool-policy-guard.ts +5 -7
- package/src/version.ts +1 -1
- package/src/cli/package-verification.ts +0 -274
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
86
|
+
!hasLocalSkillBehavior
|
|
76
87
|
? 'Create reusable procedures with /agent-skills create or import reviewed skill files.'
|
|
77
|
-
:
|
|
78
|
-
|
|
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
|
-
:
|
|
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
|
-
|
|
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
|
|
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
|
|
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-
|
|
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,
|
|
24
|
-
usage: '[review|setup|
|
|
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:
|
|
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
|
|
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-
|
|
101
|
-
' owner: connected GoodVibes
|
|
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-
|
|
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>', '
|
|
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-
|
|
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:
|
|
260
|
-
lines.push(' /health
|
|
261
|
-
lines.push('
|
|
262
|
-
lines.push(' verify: /health
|
|
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,
|
|
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
|
-
? ['', '
|
|
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
|
-
`
|
|
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-
|
|
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) => `
|
|
337
|
+
...(snapshot.serviceIssues.length > 0 ? ['', ...snapshot.serviceIssues.map((issue) => ` host integration: ${issue}`)] : []),
|
|
339
338
|
'',
|
|
340
339
|
'Next steps:',
|
|
341
340
|
' /health review',
|
|
342
|
-
' /health
|
|
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
|
-
|
|
207
|
-
|
|
215
|
+
if (args.length === 0 && context.openAgentWorkspace) {
|
|
216
|
+
context.openAgentWorkspace('knowledge');
|
|
208
217
|
return;
|
|
209
218
|
}
|
|
210
|
-
|
|
211
|
-
|
|
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:
|
|
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:
|
|
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
|
|
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: '
|
|
83
|
+
area: 'host',
|
|
84
84
|
message: (services.length === 0 && oauthProviderCount === 0 && builtinSubscriptionProviderCount === 0)
|
|
85
|
-
? 'no
|
|
85
|
+
? 'no connected host integrations configured'
|
|
86
86
|
: serviceIssues.length === 0
|
|
87
|
-
? `${services.length}
|
|
88
|
-
: `${serviceIssues.length}
|
|
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 {
|