@pellux/goodvibes-agent 0.1.88 → 0.1.90
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 +8 -0
- package/package.json +1 -1
- package/src/cli/package-verification.ts +35 -0
- package/src/input/agent-workspace-categories.ts +6 -6
- package/src/input/agent-workspace-setup.ts +1 -1
- package/src/input/commands/agent-skills-runtime.ts +5 -1
- package/src/input/commands/health-runtime.ts +12 -15
- package/src/input/commands/mcp-runtime.ts +2 -2
- package/src/input/commands/session-workflow.ts +1 -1
- package/src/panels/approval-panel.ts +1 -1
- package/src/panels/automation-control-panel.ts +1 -1
- package/src/panels/provider-account-snapshot.ts +1 -1
- package/src/panels/provider-health-domains.ts +9 -9
- package/src/panels/session-browser-panel.ts +1 -1
- package/src/panels/session-maintenance.ts +3 -3
- package/src/panels/subscription-panel.ts +1 -1
- package/src/renderer/agent-workspace.ts +1 -1
- package/src/renderer/help-overlay.ts +38 -14
- package/src/renderer/settings-modal.ts +1 -1
- package/src/runtime/bootstrap-hook-bridge.ts +1 -1
- package/src/version.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to GoodVibes Agent will be recorded here.
|
|
4
4
|
|
|
5
|
+
## 0.1.90 - 2026-06-01
|
|
6
|
+
|
|
7
|
+
- 19f67ea Polish Agent command guidance
|
|
8
|
+
|
|
9
|
+
## 0.1.89 - 2026-06-01
|
|
10
|
+
|
|
11
|
+
- 6be201c Fix Agent workspace command targets
|
|
12
|
+
|
|
5
13
|
## 0.1.88 - 2026-06-01
|
|
6
14
|
|
|
7
15
|
- e97d2a2 Fix release test daemon port allocation
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pellux/goodvibes-agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.90",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "GoodVibes personal operator assistant TUI with a proactive Agent product brain, isolated Agent Knowledge, local profiles, routines, skills, personas, and explicit build delegation.",
|
|
6
6
|
"type": "module",
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
2
|
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
+
import { CommandRegistry } from '../input/command-registry.ts';
|
|
5
|
+
import { registerBuiltinCommands } from '../input/commands.ts';
|
|
4
6
|
|
|
5
7
|
export interface PackageCliBinVerification {
|
|
6
8
|
readonly command: 'goodvibes-agent';
|
|
@@ -108,11 +110,40 @@ const PACKAGE_FACING_REQUIRED_TEXT: readonly {
|
|
|
108
110
|
{ path: 'docs/runtime-connection.md', required: ['/api/goodvibes-agent/knowledge'] },
|
|
109
111
|
{ path: 'docs/release-and-publishing.md', required: ['/api/goodvibes-agent/knowledge'] },
|
|
110
112
|
];
|
|
113
|
+
const NON_COMMAND_ROUTE_ROOTS = new Set(['api', 'status']);
|
|
111
114
|
|
|
112
115
|
function readPackageJson(root: string): Record<string, unknown> {
|
|
113
116
|
return JSON.parse(readFileSync(join(root, 'package.json'), 'utf-8')) as Record<string, unknown>;
|
|
114
117
|
}
|
|
115
118
|
|
|
119
|
+
function buildRegisteredSlashCommandNames(): ReadonlySet<string> {
|
|
120
|
+
const registry = new CommandRegistry();
|
|
121
|
+
registerBuiltinCommands(registry);
|
|
122
|
+
const names = new Set<string>();
|
|
123
|
+
for (const command of registry.list()) {
|
|
124
|
+
names.add(command.name);
|
|
125
|
+
for (const alias of command.aliases ?? []) names.add(alias);
|
|
126
|
+
}
|
|
127
|
+
return names;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function verifyPackageFacingSlashCommands(path: string, content: string, registeredCommands: ReadonlySet<string>): readonly string[] {
|
|
131
|
+
const failures: string[] = [];
|
|
132
|
+
const commandPattern = /(^|[\s`([])\/([a-z][a-z0-9_-]*)(?=$|[\s`.,;:)\]])/g;
|
|
133
|
+
const lines = content.split(/\r?\n/);
|
|
134
|
+
for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
|
|
135
|
+
const line = lines[lineIndex] ?? '';
|
|
136
|
+
commandPattern.lastIndex = 0;
|
|
137
|
+
for (let match = commandPattern.exec(line); match !== null; match = commandPattern.exec(line)) {
|
|
138
|
+
const root = match[2] ?? '';
|
|
139
|
+
if (NON_COMMAND_ROUTE_ROOTS.has(root)) continue;
|
|
140
|
+
if (registeredCommands.has(root)) continue;
|
|
141
|
+
failures.push(`package-facing text ${path}:${lineIndex + 1} references unknown Agent slash command: /${root}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return failures;
|
|
145
|
+
}
|
|
146
|
+
|
|
116
147
|
function hasExecutableBit(path: string): boolean {
|
|
117
148
|
return existsSync(path) && (statSync(path).mode & 0o111) !== 0;
|
|
118
149
|
}
|
|
@@ -146,6 +177,7 @@ function registryPackDryRun(root: string): { readonly files: readonly string[];
|
|
|
146
177
|
|
|
147
178
|
export function verifyPackageFacingText(root: string): { readonly checkedPaths: readonly string[]; readonly failures: readonly string[] } {
|
|
148
179
|
const failures: string[] = [];
|
|
180
|
+
const registeredCommands = buildRegisteredSlashCommandNames();
|
|
149
181
|
for (const path of PACKAGE_FACING_TEXT_PATHS) {
|
|
150
182
|
const absolutePath = join(root, path);
|
|
151
183
|
if (!existsSync(absolutePath)) {
|
|
@@ -153,6 +185,9 @@ export function verifyPackageFacingText(root: string): { readonly checkedPaths:
|
|
|
153
185
|
continue;
|
|
154
186
|
}
|
|
155
187
|
const content = readFileSync(absolutePath, 'utf-8');
|
|
188
|
+
if (path !== 'CHANGELOG.md') {
|
|
189
|
+
failures.push(...verifyPackageFacingSlashCommands(path, content, registeredCommands));
|
|
190
|
+
}
|
|
156
191
|
for (const forbidden of PACKAGE_FACING_FORBIDDEN_TEXT) {
|
|
157
192
|
if (content.includes(forbidden)) {
|
|
158
193
|
failures.push(`package-facing text ${path} contains forbidden default/TUI route or policy: ${forbidden}`);
|
|
@@ -49,8 +49,8 @@ export const AGENT_WORKSPACE_CATEGORIES: readonly AgentWorkspaceCategory[] = [
|
|
|
49
49
|
detail: 'Agent uses externally managed channels. Pairing, account inspection, and readiness checks are visible here; inbound delivery and public channel exposure stay policy-gated.',
|
|
50
50
|
actions: [
|
|
51
51
|
{ id: 'pair', label: 'Pair companion', detail: 'Open the QR pairing view for companion app setup.', command: '/pair', kind: 'command', safety: 'safe' },
|
|
52
|
-
{ id: '
|
|
53
|
-
{ id: 'setup-review', label: '
|
|
52
|
+
{ id: 'notification-routes', label: 'Notification routes', detail: 'Inspect configured webhook notification URLs without sending a test message.', command: '/notify list', kind: 'command', safety: 'read-only' },
|
|
53
|
+
{ id: 'setup-review', label: 'Health review', detail: 'Review setup posture without starting inbound endpoints or mutating channel state.', command: '/health review', kind: 'command', safety: 'read-only' },
|
|
54
54
|
{ id: 'channel-safety', label: 'Delivery safety', detail: 'External messages, channel DMs, and public delivery targets require explicit user action and runtime policy. Agent will not silently send or expose channels from this workspace.', kind: 'guidance', safety: 'blocked' },
|
|
55
55
|
],
|
|
56
56
|
},
|
|
@@ -90,14 +90,14 @@ export const AGENT_WORKSPACE_CATEGORIES: readonly AgentWorkspaceCategory[] = [
|
|
|
90
90
|
group: 'SETUP',
|
|
91
91
|
label: 'Profiles',
|
|
92
92
|
summary: 'Isolated Agent homes, config profiles, and setup bundles.',
|
|
93
|
-
detail: 'Profiles isolate Agent state. GoodVibes Agent exposes named homes,
|
|
93
|
+
detail: 'Profiles isolate Agent state. GoodVibes Agent exposes named homes, starter templates, and config profile pickers while keeping the shared runtime external.',
|
|
94
94
|
actions: [
|
|
95
95
|
{ id: 'profiles-open', label: 'Open config profiles', detail: 'Open the config profile picker for display/provider/behavior profile files.', command: '/profiles', kind: 'command', safety: 'safe' },
|
|
96
96
|
{ id: 'runtime-profile-guide', label: 'Starter authoring guide', detail: 'Open the Agent-local starter authoring flow inside the Agent TUI.', command: '/agent-profile guide', kind: 'command', safety: 'safe' },
|
|
97
97
|
{ id: 'runtime-profile-templates', label: 'Browse starter templates', detail: 'List built-in and local Agent starter templates with persona, skill, routine, and source details.', command: '/agent-profile templates', kind: 'command', safety: 'read-only' },
|
|
98
|
-
{ id: 'profile-
|
|
99
|
-
{ id: 'profile-
|
|
100
|
-
{ id: '
|
|
98
|
+
{ id: 'runtime-profile-list', label: 'List Agent profiles', detail: 'List isolated Agent profile homes under this Agent home.', command: '/agent-profile list', kind: 'command', safety: 'read-only' },
|
|
99
|
+
{ id: 'runtime-profile-template-export', label: 'Export starter template', detail: 'Export a starter template JSON file. Requires a real starter id, path, and explicit --yes.', command: '/agent-profile template export <id> <path> --yes', kind: 'command', safety: 'safe' },
|
|
100
|
+
{ id: 'runtime-profile-template-import', label: 'Import starter template', detail: 'Import a reviewed starter template JSON file into this Agent home. Requires a real path and explicit --yes.', command: '/agent-profile template import <path> --yes', kind: 'command', safety: 'safe' },
|
|
101
101
|
{ id: 'runtime-profile-create', label: 'Create Agent profile', detail: 'Open an in-workspace form that creates an isolated Agent home from a built-in or local starter.', editorKind: 'profile', kind: 'editor', safety: 'safe' },
|
|
102
102
|
{ id: 'runtime-profile-template-edit', label: 'Customize starter', detail: 'Export a starter JSON file, edit it, import it as a local starter, then create a profile from it.', command: '/agent-profile template export <id> <path> --yes', kind: 'command', safety: 'safe' },
|
|
103
103
|
{ id: 'runtime-profile-switch', label: 'Switch Agent profile', detail: 'Launch goodvibes-agent --agent-profile <name> to use that isolated Agent home. This workspace cannot switch the current process home after startup.', kind: 'guidance', safety: 'safe' },
|
|
@@ -40,7 +40,7 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
40
40
|
label: 'GoodVibes runtime',
|
|
41
41
|
status: 'ready',
|
|
42
42
|
detail: `Agent will connect to ${input.daemonBaseUrl}; runtime ownership stays outside this product.`,
|
|
43
|
-
command: '/
|
|
43
|
+
command: '/health',
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
id: 'provider-model',
|
|
@@ -238,6 +238,10 @@ function runBundleCommand(args: readonly string[], ctx: CommandContext, skillReg
|
|
|
238
238
|
|
|
239
239
|
export async function runAgentSkillsRuntimeCommand(args: readonly string[], ctx: CommandContext): Promise<void> {
|
|
240
240
|
const sub = (args[0] ?? 'list').toLowerCase();
|
|
241
|
+
if (sub === 'local' || sub === 'agent') {
|
|
242
|
+
await runAgentSkillsRuntimeCommand(args.slice(1), ctx);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
241
245
|
const skillRegistry = registryFromContext(ctx);
|
|
242
246
|
try {
|
|
243
247
|
if (sub === 'bundle' || sub === 'bundles') {
|
|
@@ -356,7 +360,7 @@ export async function runAgentSkillsRuntimeCommand(args: readonly string[], ctx:
|
|
|
356
360
|
export function registerAgentSkillsRuntimeCommands(registry: CommandRegistry): void {
|
|
357
361
|
registry.register({
|
|
358
362
|
name: 'agent-skills',
|
|
359
|
-
aliases: ['askills', 'local-skills'],
|
|
363
|
+
aliases: ['askills', 'local-skills', 'skills', 'skill'],
|
|
360
364
|
description: 'Manage local GoodVibes Agent skills',
|
|
361
365
|
usage: '[list|enabled|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 ...]',
|
|
362
366
|
handler: runAgentSkillsRuntimeCommand,
|
|
@@ -103,9 +103,9 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
|
|
|
103
103
|
` recent failures: ${settings.recentFailureCount}`,
|
|
104
104
|
` staged bundle: ${settings.hasStagedManagedBundle ? 'present' : 'none'}`,
|
|
105
105
|
...(issues.length > 0 ? issues.map((issue) => ` issue: ${issue}`) : [' no active settings-control issues detected']),
|
|
106
|
-
' next: /
|
|
107
|
-
' next: /
|
|
108
|
-
' next: /
|
|
106
|
+
' next: /settings',
|
|
107
|
+
' next: /config <key>',
|
|
108
|
+
' next: /health repair settings',
|
|
109
109
|
].join('\n'));
|
|
110
110
|
return;
|
|
111
111
|
}
|
|
@@ -131,8 +131,8 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
|
|
|
131
131
|
` active connections: ${snapshot.activeConnections}`,
|
|
132
132
|
` degraded: ${snapshot.degradedConnections}`,
|
|
133
133
|
...(issues.length > 0 ? issues.map((issue) => ` issue: ${issue}`) : [' no active remote recovery issues detected']),
|
|
134
|
-
' next: /
|
|
135
|
-
' next:
|
|
134
|
+
' next: /delegate <build/fix/review task> for explicit TUI build work',
|
|
135
|
+
' next: use the external runtime host for remote worker repair',
|
|
136
136
|
].join('\n'));
|
|
137
137
|
return;
|
|
138
138
|
}
|
|
@@ -217,14 +217,14 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
|
|
|
217
217
|
lines.push(' domain: settings');
|
|
218
218
|
lines.push(...(
|
|
219
219
|
settings.conflicts.length > 0
|
|
220
|
-
? [' /
|
|
220
|
+
? [' /settings', ' /config <key>', ' runtime-owned managed setting repair stays external']
|
|
221
221
|
: [' no active settings repair actions suggested']
|
|
222
222
|
));
|
|
223
223
|
lines.push(' verify: /health settings');
|
|
224
224
|
} else if (domain === 'auth') {
|
|
225
225
|
lines.push(' domain: auth');
|
|
226
226
|
lines.push(' /auth review');
|
|
227
|
-
lines.push(' /
|
|
227
|
+
lines.push(' /provider');
|
|
228
228
|
lines.push(' /subscription providers');
|
|
229
229
|
lines.push(' runtime auth users/bootstrap cleanup: use the runtime-owning GoodVibes TUI or host tooling');
|
|
230
230
|
lines.push(' verify: /health auth');
|
|
@@ -237,15 +237,13 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
|
|
|
237
237
|
lines.push(' verify: /health accounts');
|
|
238
238
|
} else if (domain === 'services') {
|
|
239
239
|
lines.push(' domain: services');
|
|
240
|
-
lines.push(' /services doctor');
|
|
241
|
-
lines.push(' /services auth-review');
|
|
242
240
|
lines.push(' /health services');
|
|
241
|
+
lines.push(' runtime service repair belongs to the external GoodVibes runtime host');
|
|
243
242
|
lines.push(' verify: /health services');
|
|
244
243
|
} else if (domain === 'remote') {
|
|
245
244
|
lines.push(' domain: remote');
|
|
246
|
-
lines.push(' /
|
|
247
|
-
lines.push('
|
|
248
|
-
lines.push(' /remote setup');
|
|
245
|
+
lines.push(' /delegate <build/fix/review task> for explicit TUI build work');
|
|
246
|
+
lines.push(' remote runner setup and recovery belong to the external runtime host');
|
|
249
247
|
lines.push(' verify: /health remote');
|
|
250
248
|
} else if (domain === 'mcp') {
|
|
251
249
|
lines.push(' domain: mcp');
|
|
@@ -262,9 +260,8 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
|
|
|
262
260
|
} else if (domain === 'maintenance') {
|
|
263
261
|
lines.push(' domain: maintenance');
|
|
264
262
|
lines.push(' /health maintenance');
|
|
265
|
-
lines.push(' /
|
|
263
|
+
lines.push(' /mode');
|
|
266
264
|
lines.push(' /compact');
|
|
267
|
-
lines.push(' /panel tokens');
|
|
268
265
|
lines.push(' verify: /health maintenance');
|
|
269
266
|
} else {
|
|
270
267
|
lines.push(' domains: settings, auth, accounts, services, remote, mcp, continuity, maintenance');
|
|
@@ -329,7 +326,7 @@ export function registerHealthRuntimeCommands(registry: CommandRegistry): void {
|
|
|
329
326
|
' /health remote',
|
|
330
327
|
' /health maintenance',
|
|
331
328
|
' /health repair <domain>',
|
|
332
|
-
' /
|
|
329
|
+
' /onboarding',
|
|
333
330
|
].join('\n'));
|
|
334
331
|
},
|
|
335
332
|
});
|
|
@@ -202,7 +202,7 @@ export function registerMcpRuntimeCommands(registry: CommandRegistry): void {
|
|
|
202
202
|
...needingAttention.map((server) => (
|
|
203
203
|
` ${server.name} connected=${server.connected ? 'yes' : 'no'} freshness=${server.schemaFreshness} trust=${server.trustMode}`
|
|
204
204
|
)),
|
|
205
|
-
' next: /
|
|
205
|
+
' next: /auth review',
|
|
206
206
|
' next: /mcp repair <server>',
|
|
207
207
|
].join('\n')
|
|
208
208
|
: 'MCP Auth Review\n No MCP servers currently need auth or quarantine recovery.');
|
|
@@ -223,7 +223,7 @@ export function registerMcpRuntimeCommands(registry: CommandRegistry): void {
|
|
|
223
223
|
selected.schemaFreshness === 'quarantined'
|
|
224
224
|
? `/mcp quarantine ${selected.name} approve operator --yes`
|
|
225
225
|
: null,
|
|
226
|
-
!selected.connected ? '/
|
|
226
|
+
!selected.connected ? '/auth review' : null,
|
|
227
227
|
'/mcp review',
|
|
228
228
|
'/health review',
|
|
229
229
|
].filter((entry): entry is string => entry !== null);
|
|
@@ -264,7 +264,7 @@ export async function handleSessionWorkflowCommand(args: string[], ctx: CommandC
|
|
|
264
264
|
ctx.print(` Reopened panels: ${reopenedPanels.join(', ')}`);
|
|
265
265
|
}
|
|
266
266
|
if ((meta.returnContext.remoteRunners?.length ?? 0) > 0) {
|
|
267
|
-
ctx.print(
|
|
267
|
+
ctx.print(' Remote re-entry: use the external runtime host for remote runner recovery; delegate explicit build/fix/review recovery from Agent.');
|
|
268
268
|
}
|
|
269
269
|
if ((meta.returnContext.worktreePaths?.length ?? 0) > 0) {
|
|
270
270
|
ctx.print(' Worktree re-entry: open GoodVibes TUI in the target workspace; delegate explicit build/fix/review recovery from Agent.');
|
|
@@ -20,7 +20,7 @@ const APPROVAL_ROWS = [
|
|
|
20
20
|
['network', 'why prompted: external hosts, fetch scope, egress policy', 'review via /approval review network'],
|
|
21
21
|
['delegate', 'why prompted: recursive agents, spawn ceilings, write-set inheritance', 'review via /approval review delegate'],
|
|
22
22
|
['mcp', 'why prompted: trust escalation, host scope, path scope, coherence mismatch', 'review via /mcp trust and /security'],
|
|
23
|
-
['remote', 'why prompted: runner trust, remote write scope, artifact requirements', 'review
|
|
23
|
+
['remote', 'why prompted: runner trust, remote write scope, artifact requirements', 'review delegated TUI execution context'],
|
|
24
24
|
['hook', 'why prompted: deny/mutate authority, blocking behavior, runner provenance', 'review via /hooks and /security'],
|
|
25
25
|
['plugin', 'why prompted: install/update lifecycle, provenance, capability grants', 'review via /marketplace and /security'],
|
|
26
26
|
] as const;
|
|
@@ -88,7 +88,7 @@ export class AutomationControlPanel extends ScrollableListPanel<AutomationRun> {
|
|
|
88
88
|
protected override getEmptyStateActions(): Array<{ command: string; summary: string }> {
|
|
89
89
|
return [
|
|
90
90
|
{ command: '/schedule list', summary: 'inspect jobs and run history without mutating schedules' },
|
|
91
|
-
{ command: '/
|
|
91
|
+
{ command: '/schedule receipts', summary: 'review Agent routine promotion receipts' },
|
|
92
92
|
];
|
|
93
93
|
}
|
|
94
94
|
|
|
@@ -217,7 +217,7 @@ export async function buildProviderAccountSnapshot(
|
|
|
217
217
|
}
|
|
218
218
|
if (hasServiceOAuth && !serviceOauth?.usable) {
|
|
219
219
|
issues.push('Service OAuth is configured but missing a usable credential.');
|
|
220
|
-
recommendedActions.push(`Repair service OAuth credentials for ${providerId} in /
|
|
220
|
+
recommendedActions.push(`Repair service OAuth credentials for ${providerId} in /settings or the external runtime host.`);
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
return {
|
|
@@ -55,8 +55,8 @@ export function buildProviderHealthDomainSummaries(
|
|
|
55
55
|
auth.bootstrapCredentialPresent ? 'Runtime bootstrap cleanup must be done from the runtime-owning TUI or host tooling.' : '',
|
|
56
56
|
].filter(Boolean),
|
|
57
57
|
nextSteps: auth.bootstrapCredentialPresent
|
|
58
|
-
? ['/auth review', '/
|
|
59
|
-
: ['/auth review', '/
|
|
58
|
+
? ['/auth review', '/provider', '/subscription providers']
|
|
59
|
+
: ['/auth review', '/provider'],
|
|
60
60
|
});
|
|
61
61
|
|
|
62
62
|
const settingIssueCount = settings.conflictCount + settings.recentFailureCount + (settings.hasStagedManagedBundle ? 1 : 0);
|
|
@@ -68,7 +68,7 @@ export function buildProviderHealthDomainSummaries(
|
|
|
68
68
|
: settingIssueCount > 0
|
|
69
69
|
? `${settings.conflictCount} conflicts / ${settings.recentFailureCount} failures${settings.hasStagedManagedBundle ? ' / staged bundle' : ''}`
|
|
70
70
|
: 'settings runtime API clean',
|
|
71
|
-
next: settingIssueCount > 0 ? '/
|
|
71
|
+
next: settingIssueCount > 0 ? '/settings' : '/config <key>',
|
|
72
72
|
details: [
|
|
73
73
|
settings.conflictCount > 0 ? `${settings.conflictCount} unresolved import conflict(s)` : '',
|
|
74
74
|
settings.recentFailureCount > 0 ? `${settings.recentFailureCount} recent sync or managed failure(s)` : '',
|
|
@@ -76,8 +76,8 @@ export function buildProviderHealthDomainSummaries(
|
|
|
76
76
|
settings.managedLockCount > 0 ? `${settings.managedLockCount} managed lock(s) enforced` : '',
|
|
77
77
|
].filter(Boolean),
|
|
78
78
|
nextSteps: settingIssueCount > 0
|
|
79
|
-
? ['/
|
|
80
|
-
: ['/
|
|
79
|
+
? ['/settings', '/config <key>', '/health settings']
|
|
80
|
+
: ['/config <key>'],
|
|
81
81
|
});
|
|
82
82
|
|
|
83
83
|
summaries.push({
|
|
@@ -86,7 +86,7 @@ export function buildProviderHealthDomainSummaries(
|
|
|
86
86
|
summary: remote.supervisor.sessions.length === 0
|
|
87
87
|
? 'no remote sessions tracked'
|
|
88
88
|
: `${remote.supervisor.sessions.length} sessions / ${remote.supervisor.degradedConnections} degraded`,
|
|
89
|
-
next: remote.supervisor.degradedConnections > 0 ? '/
|
|
89
|
+
next: remote.supervisor.degradedConnections > 0 ? '/delegate <build/fix/review task>' : '/health remote',
|
|
90
90
|
details: remote.supervisor.sessions.length === 0
|
|
91
91
|
? ['no remote sessions have been attached yet']
|
|
92
92
|
: remote.supervisor.sessions
|
|
@@ -99,8 +99,8 @@ export function buildProviderHealthDomainSummaries(
|
|
|
99
99
|
.slice(0, 3)
|
|
100
100
|
.map((entry) => `${entry.runnerId}: transport=${entry.transportState} heartbeat=${entry.heartbeat.status}${entry.lastError ? ` error=${entry.lastError}` : ''}`),
|
|
101
101
|
nextSteps: remote.supervisor.degradedConnections > 0
|
|
102
|
-
? ['/
|
|
103
|
-
: ['/remote
|
|
102
|
+
? ['/delegate <build/fix/review task>', '/health remote']
|
|
103
|
+
: ['/health remote'],
|
|
104
104
|
});
|
|
105
105
|
|
|
106
106
|
const degradedServers = security.mcpServers.filter((server) =>
|
|
@@ -141,7 +141,7 @@ export function buildProviderHealthDomainSummaries(
|
|
|
141
141
|
? 'warn'
|
|
142
142
|
: 'good',
|
|
143
143
|
summary: maintenance.summary,
|
|
144
|
-
next: maintenance.nextSteps[0] ?? '/
|
|
144
|
+
next: maintenance.nextSteps[0] ?? '/health maintenance',
|
|
145
145
|
details: maintenance.reasons.slice(0, 3),
|
|
146
146
|
nextSteps: maintenance.nextSteps,
|
|
147
147
|
});
|
|
@@ -266,7 +266,7 @@ export class SessionBrowserPanel extends BasePanel {
|
|
|
266
266
|
...formatReturnContextLines(selected.returnContext).map((line) =>
|
|
267
267
|
buildPanelLine(width, [[' ', DEFAULT_PANEL_PALETTE.dim], [truncateDisplay(line, Math.max(0, width - 2)), DEFAULT_PANEL_PALETTE.dim]])
|
|
268
268
|
),
|
|
269
|
-
buildPanelLine(width, [[' Next ', DEFAULT_PANEL_PALETTE.label], [
|
|
269
|
+
buildPanelLine(width, [[' Next ', DEFAULT_PANEL_PALETTE.label], ['/session resume', DEFAULT_PANEL_PALETTE.dim]]),
|
|
270
270
|
],
|
|
271
271
|
}
|
|
272
272
|
: { title: 'Selected', lines: [] };
|
|
@@ -76,13 +76,13 @@ export function evaluateSessionMaintenance(input: PanelSessionMaintenanceInput):
|
|
|
76
76
|
level = 'needs-repair';
|
|
77
77
|
summary = `Compact now to recover context headroom (${usagePct}% used).`;
|
|
78
78
|
reasons.push(`Context pressure is high at ${usagePct}% usage.`);
|
|
79
|
-
nextSteps.push('/compact', '/
|
|
79
|
+
nextSteps.push('/compact', '/context');
|
|
80
80
|
compactRecommended = true;
|
|
81
81
|
} else if (usagePct >= thresholdPct || remainingTokens <= 15_000) {
|
|
82
82
|
level = 'suggest-compact';
|
|
83
83
|
summary = `Watch context growth (${usagePct}% used).`;
|
|
84
84
|
reasons.push(`Context pressure is climbing at ${usagePct}% usage.`);
|
|
85
|
-
nextSteps.push('/
|
|
85
|
+
nextSteps.push('/context');
|
|
86
86
|
compactRecommended = true;
|
|
87
87
|
} else if (usagePct >= 70 || staleByMessageGrowth) {
|
|
88
88
|
level = 'watch';
|
|
@@ -92,7 +92,7 @@ export function evaluateSessionMaintenance(input: PanelSessionMaintenanceInput):
|
|
|
92
92
|
reasons.push(staleByMessageGrowth
|
|
93
93
|
? `Conversation has grown ${messageCount.toLocaleString()} messages since the last maintenance checkpoint.`
|
|
94
94
|
: `Context usage is climbing toward the ${thresholdPct}% maintenance threshold.`);
|
|
95
|
-
nextSteps.push('/
|
|
95
|
+
nextSteps.push('/context');
|
|
96
96
|
} else {
|
|
97
97
|
reasons.push('Context pressure is currently within the stable operating band.');
|
|
98
98
|
}
|
|
@@ -80,7 +80,7 @@ export class SubscriptionPanel extends ScrollableListPanel<SubscriptionRow> {
|
|
|
80
80
|
return [
|
|
81
81
|
{ command: '/subscription login openai start --yes', summary: 'start the first-class OpenAI subscription flow' },
|
|
82
82
|
{ command: '/login provider <name> start --yes', summary: 'use the front-door auth flow for supported providers' },
|
|
83
|
-
{ command: '/
|
|
83
|
+
{ command: '/auth review', summary: 'inspect runtime auth posture without exposing token values' },
|
|
84
84
|
];
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -232,7 +232,7 @@ function snapshotLines(workspace: AgentWorkspace, category: AgentWorkspaceCatego
|
|
|
232
232
|
});
|
|
233
233
|
}
|
|
234
234
|
base.push({ text: 'Only config key names and readiness state are rendered here.', fg: PALETTE.muted });
|
|
235
|
-
base.push({ text: 'Pairing: use /pair or /qrcode; inspect
|
|
235
|
+
base.push({ text: 'Pairing: use /pair or /qrcode; inspect notification targets with /notify list and health with /health review.', fg: PALETTE.info });
|
|
236
236
|
} else if (category.id === 'knowledge') {
|
|
237
237
|
base.push(
|
|
238
238
|
{ text: `Route family: ${snapshot.knowledgeRoute}/{status,ask,search}`, fg: PALETTE.info },
|
|
@@ -69,21 +69,23 @@ export function renderHelpOverlay(
|
|
|
69
69
|
// Each entry is [commandName, subcommandOrArgHint, description].
|
|
70
70
|
// Commands not registered in the live registry are omitted at render time.
|
|
71
71
|
const FEATURED_COMMANDS: Array<[name: string, argHint: string, desc: string]> = [
|
|
72
|
-
['
|
|
73
|
-
['
|
|
74
|
-
['
|
|
72
|
+
['agent', '', 'Open the Agent operator workspace'],
|
|
73
|
+
['onboarding', '', 'Open Agent setup with current settings preloaded'],
|
|
74
|
+
['knowledge', 'status', 'Inspect isolated Agent Knowledge readiness'],
|
|
75
|
+
['memory', '', 'Manage local Agent memory records'],
|
|
76
|
+
['personas', '', 'Manage serial Agent operating personas'],
|
|
77
|
+
['agent-skills', '', 'Manage local Agent skills and bundles'],
|
|
78
|
+
['routines', '', 'Manage reusable main-conversation routines'],
|
|
79
|
+
['workplan', '', 'Inspect shared work-plan state'],
|
|
80
|
+
['approval', '', 'Review and explicitly act on approvals'],
|
|
81
|
+
['schedule', '', 'Inspect schedules and routine promotion receipts'],
|
|
82
|
+
['delegate', '', 'Explicitly hand build/fix/review work to GoodVibes TUI'],
|
|
83
|
+
['mcp', '', 'Inspect MCP servers and tool readiness'],
|
|
75
84
|
['provider', '', 'Choose provider or model family'],
|
|
85
|
+
['model', '', 'Select the active model route'],
|
|
76
86
|
['subscription', '', 'Review provider logins and subscriptions'],
|
|
77
|
-
['
|
|
78
|
-
['
|
|
79
|
-
['security', '', 'Security review workspace'],
|
|
80
|
-
['policy', '', 'Simulation, lint, and preflight review'],
|
|
81
|
-
['incident', '', 'Incident workspace and export flows'],
|
|
82
|
-
['knowledge', '', 'Durable knowledge and review queue'],
|
|
83
|
-
['hooks', '', 'Hook workbench and runtime activity'],
|
|
84
|
-
['orchestration','', 'Graph and recursive-agent control room'],
|
|
85
|
-
['communication','', 'Structured agent communication workspace'],
|
|
86
|
-
['tasks', '', 'Read-only task view for list/show/pause/resume/output'],
|
|
87
|
+
['secrets', '', 'Manage secret references without printing values'],
|
|
88
|
+
['health', '', 'Run Agent runtime and setup diagnostics'],
|
|
87
89
|
];
|
|
88
90
|
|
|
89
91
|
// Build command rows from featured list, filtering out unregistered commands.
|
|
@@ -115,7 +117,29 @@ export function renderHelpOverlay(
|
|
|
115
117
|
|
|
116
118
|
if (commands && commands.length > 0) {
|
|
117
119
|
commandRows.push('', ' Available Slash Commands', ' ' + '\u2500'.repeat(40));
|
|
118
|
-
const preferred = [
|
|
120
|
+
const preferred = [
|
|
121
|
+
'agent',
|
|
122
|
+
'onboarding',
|
|
123
|
+
'knowledge',
|
|
124
|
+
'memory',
|
|
125
|
+
'personas',
|
|
126
|
+
'agent-skills',
|
|
127
|
+
'routines',
|
|
128
|
+
'workplan',
|
|
129
|
+
'approval',
|
|
130
|
+
'schedule',
|
|
131
|
+
'delegate',
|
|
132
|
+
'mcp',
|
|
133
|
+
'provider',
|
|
134
|
+
'model',
|
|
135
|
+
'subscription',
|
|
136
|
+
'secrets',
|
|
137
|
+
'health',
|
|
138
|
+
'settings',
|
|
139
|
+
'security',
|
|
140
|
+
'policy',
|
|
141
|
+
'tasks',
|
|
142
|
+
];
|
|
119
143
|
const seen = new Set<string>();
|
|
120
144
|
for (const name of preferred) {
|
|
121
145
|
const cmd = commands.find((entry) => entry.name === name);
|
|
@@ -148,7 +148,7 @@ function buildSettingContext(modal: SettingsModal, entry: SettingEntry): string[
|
|
|
148
148
|
];
|
|
149
149
|
|
|
150
150
|
if (entry.locked) lines.push(`Locked: ${entry.lockReason ?? 'This setting is locked by a higher-priority layer.'}`);
|
|
151
|
-
if (entry.conflict) lines.push(`Conflict:
|
|
151
|
+
if (entry.conflict) lines.push(`Conflict: inspect with /settings and resolve runtime-owned sync state in the external host.`);
|
|
152
152
|
|
|
153
153
|
lines.push('', entry.setting.description);
|
|
154
154
|
|
|
@@ -74,7 +74,7 @@ export function createResumeSessionHandler(options: ResumeSessionOptions): (sess
|
|
|
74
74
|
options.conversation.log(`Resume: Reopened panels: ${reopenedPanels.join(', ')}`, { fg: '244' });
|
|
75
75
|
}
|
|
76
76
|
if ((meta.returnContext.remoteRunners?.length ?? 0) > 0) {
|
|
77
|
-
options.conversation.log(
|
|
77
|
+
options.conversation.log('Resume: Remote re-entry belongs to the external runtime host; delegate explicit build/fix/review recovery from Agent.', { fg: '244' });
|
|
78
78
|
}
|
|
79
79
|
if (returnContextMode === 'assisted') {
|
|
80
80
|
const helperModel = new HelperModel({
|
package/src/version.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { join } from 'node:path';
|
|
|
6
6
|
// The prebuild script updates the fallback value before compilation.
|
|
7
7
|
// Uses import.meta.dir (Bun) to locate package.json relative to this file,
|
|
8
8
|
// which is correct regardless of the process working directory.
|
|
9
|
-
let _version = '0.1.
|
|
9
|
+
let _version = '0.1.90';
|
|
10
10
|
let _sdkVersion = '0.33.35';
|
|
11
11
|
try {
|
|
12
12
|
const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', 'package.json'), 'utf-8')) as {
|