@pellux/goodvibes-agent 0.1.107 → 0.1.109
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 +42 -13
- package/README.md +27 -11
- package/docs/README.md +5 -5
- package/docs/{runtime-connection.md → connected-services.md} +8 -8
- package/docs/getting-started.md +28 -12
- package/docs/release-and-publishing.md +4 -4
- package/package.json +2 -12
- package/src/agent/memory-prompt.ts +35 -0
- package/src/agent/reminder-schedule-format.ts +75 -0
- package/src/agent/reminder-schedule.ts +494 -0
- package/src/agent/routine-schedule-format.ts +7 -7
- package/src/agent/routine-schedule-promotion.ts +1 -1
- package/src/agent/routine-schedule-receipts.ts +1 -1
- package/src/agent/skill-discovery.ts +2 -0
- package/src/cli/agent-knowledge-args.ts +93 -0
- package/src/cli/agent-knowledge-command.ts +200 -369
- package/src/cli/agent-knowledge-format.ts +58 -7
- package/src/cli/agent-knowledge-methods.ts +84 -0
- package/src/cli/agent-knowledge-runtime.ts +240 -0
- package/src/cli/completion.ts +0 -2
- package/src/cli/config-overrides.ts +2 -2
- package/src/cli/help.ts +34 -15
- package/src/cli/management-commands.ts +2 -2
- package/src/cli/management.ts +8 -8
- package/src/cli/package-verification.ts +7 -3
- package/src/cli/parser.ts +10 -4
- package/src/cli/service-posture.ts +6 -6
- package/src/cli/status.ts +32 -32
- package/src/input/agent-workspace-activation.ts +24 -13
- package/src/input/agent-workspace-basic-command-editors.ts +448 -0
- package/src/input/agent-workspace-categories.ts +42 -34
- package/src/input/agent-workspace-channels.ts +3 -3
- package/src/input/agent-workspace-command-editor.ts +65 -0
- package/src/input/agent-workspace-editors.ts +17 -2
- package/src/input/agent-workspace-knowledge-query-editor.ts +74 -0
- package/src/input/agent-workspace-knowledge-url-editor.ts +95 -0
- package/src/input/agent-workspace-reminder-schedule-editor.ts +125 -0
- package/src/input/agent-workspace-routine-schedule-editor.ts +127 -0
- package/src/input/agent-workspace-setup.ts +2 -2
- package/src/input/agent-workspace-snapshot.ts +5 -2
- package/src/input/agent-workspace-types.ts +21 -2
- package/src/input/agent-workspace-voice-media.ts +5 -5
- package/src/input/agent-workspace.ts +39 -2
- package/src/input/commands/agent-runtime-profile-runtime.ts +1 -1
- package/src/input/commands/agent-skills-runtime.ts +94 -2
- package/src/input/commands/brief-runtime.ts +126 -0
- package/src/input/commands/channels-runtime.ts +47 -0
- package/src/input/commands/health-runtime.ts +10 -10
- package/src/input/commands/knowledge.ts +176 -1
- package/src/input/commands/planning-runtime.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +10 -10
- package/src/input/commands/policy-dispatch.ts +1 -1
- package/src/input/commands/schedule-runtime.ts +42 -5
- package/src/input/commands/security-runtime.ts +1 -1
- package/src/input/commands/session-content.ts +1 -1
- package/src/input/commands/session-workflow.ts +1 -1
- package/src/input/commands/shell-core.ts +4 -2
- package/src/input/commands/tasks-runtime.ts +3 -3
- package/src/input/commands.ts +4 -0
- package/src/input/handler-onboarding.ts +4 -4
- package/src/input/handler.ts +3 -2
- package/src/input/onboarding/onboarding-wizard-helpers.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-operator-steps.ts +13 -13
- package/src/input/onboarding/onboarding-wizard-steps.ts +8 -8
- package/src/input/settings-modal-agent-policy.ts +1 -1
- package/src/input/slash-command-parser.ts +60 -0
- package/src/panels/builtin/agent.ts +1 -1
- package/src/panels/builtin/operations.ts +2 -2
- package/src/panels/provider-account-snapshot.ts +1 -1
- package/src/panels/provider-health-domains.ts +6 -6
- package/src/panels/subscription-panel.ts +1 -1
- package/src/panels/tasks-panel.ts +3 -3
- package/src/renderer/agent-workspace.ts +44 -31
- package/src/renderer/help-overlay.ts +1 -1
- package/src/renderer/settings-modal.ts +13 -13
- package/src/runtime/bootstrap-core.ts +1 -1
- package/src/runtime/bootstrap-hook-bridge.ts +1 -1
- package/src/runtime/bootstrap.ts +11 -9
- package/src/runtime/index.ts +2 -2
- package/src/runtime/onboarding/derivation.ts +6 -6
- package/src/shell/service-settings-sync.ts +1 -1
- package/src/tools/agent-local-registry-tool.ts +208 -9
- package/src/version.ts +1 -1
|
@@ -144,7 +144,7 @@ export function registerSessionContentCommands(registry: CommandRegistry): void
|
|
|
144
144
|
if (meta.title) ctx.session.conversationManager.title = meta.title;
|
|
145
145
|
ctx.session.conversationManager.rebuildHistory();
|
|
146
146
|
ctx.renderRequest();
|
|
147
|
-
ctx.print(`Session loaded: ${args[0]} (${messages.length} messages)${agentRecords.length > 0 ? ` [ignored ${agentRecords.length}
|
|
147
|
+
ctx.print(`Session loaded: ${args[0]} (${messages.length} messages)${agentRecords.length > 0 ? ` [ignored ${agentRecords.length} service-owned local agent record${agentRecords.length !== 1 ? 's' : ''}]` : ''}`);
|
|
148
148
|
} catch (e) {
|
|
149
149
|
ctx.print(`Failed to load session: ${summarizeError(e)}`);
|
|
150
150
|
}
|
|
@@ -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(' Remote re-entry:
|
|
267
|
+
ctx.print(' Remote re-entry: handle remote runner recovery outside Agent; 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.');
|
|
@@ -116,13 +116,15 @@ export function registerShellCoreCommands(registry: CommandRegistry): void {
|
|
|
116
116
|
const items: SelectionItem[] = [
|
|
117
117
|
{ id: '/agent', label: '/agent', detail: 'Open the Agent operator workspace', category: 'Agent Operator' },
|
|
118
118
|
{ id: '/home', label: '/home', detail: 'Alias for the Agent operator workspace', category: 'Agent Operator' },
|
|
119
|
+
{ id: '/brief', label: '/brief', detail: 'Show a concise Agent operator briefing and next actions', category: 'Agent Operator' },
|
|
119
120
|
{ id: '/knowledge', label: '/knowledge', detail: 'Inspect isolated Agent Knowledge status, ask/search, and ingest flows', category: 'Agent Operator' },
|
|
120
121
|
{ id: '/memory', label: '/memory', detail: 'Review local Agent memory records', category: 'Agent Operator' },
|
|
121
122
|
{ id: '/personas', label: '/personas', detail: 'Create, review, and activate local Agent personas', category: 'Agent Operator' },
|
|
122
123
|
{ id: '/agent-skills', label: '/agent-skills', detail: 'Create, review, and enable reusable Agent skills', category: 'Agent Operator' },
|
|
123
124
|
{ id: '/routines', label: '/routines', detail: 'Create, review, start, and promote Agent routines explicitly', category: 'Agent Operator' },
|
|
124
125
|
{ id: '/delegate', label: '/delegate [task]', detail: 'Explicit build/fix/review handoff to GoodVibes TUI', category: 'Agent Operator' },
|
|
125
|
-
{ id: '/
|
|
126
|
+
{ id: '/channels', label: '/channels', detail: 'Inspect messaging-channel readiness without sending messages', category: 'Agent Operator' },
|
|
127
|
+
{ id: '/pair', label: '/pair', detail: 'Pair companion clients through connected GoodVibes services', category: 'Agent Operator' },
|
|
126
128
|
{ id: '/model', label: '/model [id]', detail: 'Select LLM model', category: 'Model & Provider' },
|
|
127
129
|
{ id: '/provider', label: '/provider [name]', detail: 'Switch provider', category: 'Model & Provider' },
|
|
128
130
|
{ id: '/effort', label: '/effort [level]', detail: 'Reasoning effort (instant/low/medium/high)', category: 'Model & Provider' },
|
|
@@ -170,7 +172,7 @@ export function registerShellCoreCommands(registry: CommandRegistry): void {
|
|
|
170
172
|
});
|
|
171
173
|
return;
|
|
172
174
|
}
|
|
173
|
-
ctx.print('Use /help to open the help modal. Commands: /agent, /knowledge, /memory, /personas, /agent-skills, /routines, /delegate, /model, /provider, /config, /paste, /sessions, /bookmarks, /save, /load, /undo, /redo, /retry, /clear, /reset, /compact, /export, /title, /effort, /expand, /collapse, /quit');
|
|
175
|
+
ctx.print('Use /help to open the help modal. Commands: /agent, /brief, /knowledge, /memory, /personas, /agent-skills, /routines, /channels, /delegate, /model, /provider, /config, /paste, /sessions, /bookmarks, /save, /load, /undo, /redo, /retry, /clear, /reset, /compact, /export, /title, /effort, /expand, /collapse, /quit');
|
|
174
176
|
},
|
|
175
177
|
});
|
|
176
178
|
|
|
@@ -16,10 +16,10 @@ const BLOCKED_TASK_MUTATIONS: ReadonlySet<string> = new Set([
|
|
|
16
16
|
function printTaskMutationBlocked(print: (text: string) => void, subcommand: string): void {
|
|
17
17
|
print([
|
|
18
18
|
`Task mutation "${subcommand}" is blocked in GoodVibes Agent.`,
|
|
19
|
-
' policy:
|
|
19
|
+
' policy: connected-service tasks are read-only from the Agent TUI; normal work stays in the main conversation.',
|
|
20
20
|
' durable tasks: use /workplan for visible planning and task tracking.',
|
|
21
21
|
' build/fix/review: use /delegate <task> to hand explicit implementation work to GoodVibes TUI.',
|
|
22
|
-
' result: no local
|
|
22
|
+
' result: no local task state was changed.',
|
|
23
23
|
].join('\n'));
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -51,7 +51,7 @@ export function registerTasksRuntimeCommands(registry: CommandRegistry): void {
|
|
|
51
51
|
registry.register({
|
|
52
52
|
name: 'tasks',
|
|
53
53
|
aliases: ['task'],
|
|
54
|
-
description: 'Inspect
|
|
54
|
+
description: 'Inspect connected-service tasks without starting or mutating local background work',
|
|
55
55
|
usage: '[list [status|kind] | show <taskId> | output <taskId>]',
|
|
56
56
|
handler(args, ctx) {
|
|
57
57
|
if (args.length === 0) {
|
package/src/input/commands.ts
CHANGED
|
@@ -35,6 +35,8 @@ import { registerDelegationRuntimeCommands } from './commands/delegation-runtime
|
|
|
35
35
|
import { registerPersonasRuntimeCommands } from './commands/personas-runtime.ts';
|
|
36
36
|
import { registerAgentSkillsRuntimeCommands } from './commands/agent-skills-runtime.ts';
|
|
37
37
|
import { registerRoutinesRuntimeCommands } from './commands/routines-runtime.ts';
|
|
38
|
+
import { registerChannelsRuntimeCommands } from './commands/channels-runtime.ts';
|
|
39
|
+
import { registerBriefRuntimeCommands } from './commands/brief-runtime.ts';
|
|
38
40
|
|
|
39
41
|
function registerAgentMemoryCommand(registry: CommandRegistry): void {
|
|
40
42
|
registry.register({
|
|
@@ -56,10 +58,12 @@ function registerAgentMemoryCommand(registry: CommandRegistry): void {
|
|
|
56
58
|
export function registerBuiltinCommands(registry: CommandRegistry): void {
|
|
57
59
|
registerShellCoreCommands(registry);
|
|
58
60
|
registerAgentWorkspaceRuntimeCommands(registry);
|
|
61
|
+
registerBriefRuntimeCommands(registry);
|
|
59
62
|
registerAgentRuntimeProfileRuntimeCommands(registry);
|
|
60
63
|
registerPersonasRuntimeCommands(registry);
|
|
61
64
|
registerAgentSkillsRuntimeCommands(registry);
|
|
62
65
|
registerRoutinesRuntimeCommands(registry);
|
|
66
|
+
registerChannelsRuntimeCommands(registry);
|
|
63
67
|
registerDelegationRuntimeCommands(registry);
|
|
64
68
|
registerConfigCommand(registry);
|
|
65
69
|
registerOperatorRuntimeCommands(registry);
|
|
@@ -487,11 +487,11 @@ export function getOnboardingRuntimePostureForHandler(handler: InputHandler, req
|
|
|
487
487
|
export async function restartOnboardingExternalServicesIfNeededForHandler(handler: InputHandler, request: OnboardingApplyRequest): Promise<OnboardingVerificationItem[]> {
|
|
488
488
|
const externalServices = handler.uiServices.platform.externalServices;
|
|
489
489
|
const state = externalServices?.inspect();
|
|
490
|
-
const serviceStatus = state?.daemonStatus?.reason ?? (state?.daemonRunning ? '
|
|
490
|
+
const serviceStatus = state?.daemonStatus?.reason ?? (state?.daemonRunning ? 'connected GoodVibes services appear active' : 'connected GoodVibes services are not verified from this shell');
|
|
491
491
|
return [{
|
|
492
492
|
id: 'runtime:external-service-owned',
|
|
493
493
|
status: 'pass',
|
|
494
|
-
message: `GoodVibes Agent did not start, stop, restart, or reconfigure
|
|
494
|
+
message: `GoodVibes Agent did not start, stop, restart, or reconfigure connected services. ${serviceStatus}`,
|
|
495
495
|
target: 'service',
|
|
496
496
|
}];
|
|
497
497
|
}
|
|
@@ -503,8 +503,8 @@ export function verifyOnboardingRuntimePostureForHandler(handler: InputHandler,
|
|
|
503
503
|
id: 'runtime:external-service-owned',
|
|
504
504
|
status: 'pass',
|
|
505
505
|
message: externalState
|
|
506
|
-
? 'GoodVibes
|
|
507
|
-
: 'GoodVibes
|
|
506
|
+
? 'Connected GoodVibes services are managed outside Agent; Agent onboarding did not request shutdown, startup, restart, bind, or surface changes.'
|
|
507
|
+
: 'Connected GoodVibes services are managed outside Agent; no local service controller is required for Agent onboarding.',
|
|
508
508
|
target: 'service',
|
|
509
509
|
}];
|
|
510
510
|
}
|
package/src/input/handler.ts
CHANGED
|
@@ -26,6 +26,7 @@ import { BookmarkModal } from './bookmark-modal.ts';
|
|
|
26
26
|
import { SettingsModal } from './settings-modal.ts';
|
|
27
27
|
import { McpWorkspace } from './mcp-workspace.ts';
|
|
28
28
|
import { AgentWorkspace } from './agent-workspace.ts';
|
|
29
|
+
import { parseSlashCommand } from './slash-command-parser.ts';
|
|
29
30
|
import { SessionPickerModal } from './session-picker-modal.ts';
|
|
30
31
|
import { ProfilePickerModal } from './profile-picker-modal.ts';
|
|
31
32
|
import { OnboardingWizardController, type OnboardingWizardAction, type OnboardingWizardMode } from './onboarding/onboarding-wizard.ts';
|
|
@@ -423,9 +424,9 @@ export class InputHandler {
|
|
|
423
424
|
for (let index = this.modalStack.length - 1; index >= 0; index -= 1) {
|
|
424
425
|
if (this.modalStack[index] === 'agentWorkspace') this.modalStack.splice(index, 1);
|
|
425
426
|
}
|
|
426
|
-
const
|
|
427
|
+
const { name, args } = parseSlashCommand(command);
|
|
427
428
|
if (!name) return;
|
|
428
|
-
void context.executeCommand?.(name, args).catch((error: unknown) => {
|
|
429
|
+
void context.executeCommand?.(name, [...args]).catch((error: unknown) => {
|
|
429
430
|
context.print(`Agent workspace command failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
430
431
|
this.requestRender();
|
|
431
432
|
});
|
|
@@ -49,7 +49,7 @@ export function buildDefaultDerivedState(): OnboardingStepDerivationState {
|
|
|
49
49
|
required: false,
|
|
50
50
|
accepted: false,
|
|
51
51
|
reason: 'not-needed',
|
|
52
|
-
detail: 'No
|
|
52
|
+
detail: 'No connected-service auth signal needs confirmation.',
|
|
53
53
|
},
|
|
54
54
|
},
|
|
55
55
|
};
|
|
@@ -5,10 +5,10 @@ export function buildCommunicationStep(): OnboardingWizardStepDefinition {
|
|
|
5
5
|
id: 'agent-communication',
|
|
6
6
|
title: 'Channels and notifications',
|
|
7
7
|
shortLabel: 'Channels',
|
|
8
|
-
description: 'Prepare
|
|
8
|
+
description: 'Prepare companion pairing, messaging-channel readiness, notification delivery, and safe outbound communication for day-one Agent use.',
|
|
9
9
|
summaryTitle: 'Communication posture',
|
|
10
10
|
summaryLines: [
|
|
11
|
-
'Companion chat: paired through
|
|
11
|
+
'Companion chat: paired through connected GoodVibes services',
|
|
12
12
|
'Channel accounts: inspect readiness before using them',
|
|
13
13
|
'Outbound messages: explicit user action only',
|
|
14
14
|
],
|
|
@@ -17,14 +17,14 @@ export function buildCommunicationStep(): OnboardingWizardStepDefinition {
|
|
|
17
17
|
kind: 'status',
|
|
18
18
|
id: 'agent-communication.companion',
|
|
19
19
|
label: 'Companion pairing',
|
|
20
|
-
hint: 'Use /pair from the Agent workspace to pair companion clients through
|
|
21
|
-
defaultValue: '
|
|
20
|
+
hint: 'Use /pair from the Agent workspace to pair companion clients through connected GoodVibes services.',
|
|
21
|
+
defaultValue: 'Pair when ready',
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
kind: 'status',
|
|
25
25
|
id: 'agent-communication.channels',
|
|
26
26
|
label: 'Messaging channels',
|
|
27
|
-
hint: 'Use the Channels workspace to inspect account readiness, delivery posture, and recent communication without changing
|
|
27
|
+
hint: 'Use the Channels workspace to inspect account readiness, delivery posture, and recent communication without changing connection state.',
|
|
28
28
|
defaultValue: 'Inspectable',
|
|
29
29
|
},
|
|
30
30
|
{
|
|
@@ -38,7 +38,7 @@ export function buildCommunicationStep(): OnboardingWizardStepDefinition {
|
|
|
38
38
|
kind: 'status',
|
|
39
39
|
id: 'agent-communication.inbound-policy',
|
|
40
40
|
label: 'Inbound command policy',
|
|
41
|
-
hint: 'Incoming channel commands stay constrained by
|
|
41
|
+
hint: 'Incoming channel commands stay constrained by Agent policy, allowlists, and account posture.',
|
|
42
42
|
defaultValue: 'Policy gated',
|
|
43
43
|
},
|
|
44
44
|
],
|
|
@@ -50,7 +50,7 @@ export function buildToolsStep(): OnboardingWizardStepDefinition {
|
|
|
50
50
|
id: 'agent-tools',
|
|
51
51
|
title: 'Tools and MCP',
|
|
52
52
|
shortLabel: 'Tools',
|
|
53
|
-
description: 'Review tool access for the Agent operator: MCP
|
|
53
|
+
description: 'Review tool access for the Agent operator: MCP connections, browser/media helpers, safe read-only inspection, and explicit approval before side effects.',
|
|
54
54
|
summaryTitle: 'Tool posture',
|
|
55
55
|
summaryLines: [
|
|
56
56
|
'MCP and tools: inspect before use',
|
|
@@ -61,8 +61,8 @@ export function buildToolsStep(): OnboardingWizardStepDefinition {
|
|
|
61
61
|
{
|
|
62
62
|
kind: 'status',
|
|
63
63
|
id: 'agent-tools.mcp',
|
|
64
|
-
label: 'MCP
|
|
65
|
-
hint: 'Use /mcp servers and the Agent workspace Tools area to inspect connected servers, roles, and tool readiness.',
|
|
64
|
+
label: 'MCP connections and tools',
|
|
65
|
+
hint: 'Use /mcp servers and the Agent workspace Tools area to inspect connected MCP servers, roles, and tool readiness.',
|
|
66
66
|
defaultValue: 'Inspectable',
|
|
67
67
|
},
|
|
68
68
|
{
|
|
@@ -178,11 +178,11 @@ export function buildAutomationStep(): OnboardingWizardStepDefinition {
|
|
|
178
178
|
id: 'agent-automation',
|
|
179
179
|
title: 'Routines and automation',
|
|
180
180
|
shortLabel: 'Routines',
|
|
181
|
-
description: 'Set the Agent automation posture: local routines run in the main conversation, while
|
|
181
|
+
description: 'Set the Agent automation posture: local routines run in the main conversation, while connected schedules remain explicit.',
|
|
182
182
|
summaryTitle: 'Routine and schedule posture',
|
|
183
183
|
summaryLines: [
|
|
184
184
|
'Local routines: reusable main-conversation workflows',
|
|
185
|
-
'
|
|
185
|
+
'Connected schedules: explicit promotion only',
|
|
186
186
|
'Runs/cancels/retries: command-confirmed side effects',
|
|
187
187
|
],
|
|
188
188
|
fields: [
|
|
@@ -204,7 +204,7 @@ export function buildAutomationStep(): OnboardingWizardStepDefinition {
|
|
|
204
204
|
kind: 'status',
|
|
205
205
|
id: 'agent-automation.schedule-promotion',
|
|
206
206
|
label: 'Routine-to-schedule promotion',
|
|
207
|
-
hint: 'Creating
|
|
207
|
+
hint: 'Creating connected schedules from routines requires a reviewed routine, a real timing expression, optional delivery target, and explicit confirmation.',
|
|
208
208
|
defaultValue: 'Explicit command',
|
|
209
209
|
},
|
|
210
210
|
{
|
|
@@ -223,7 +223,7 @@ export function buildVoiceMediaStep(): OnboardingWizardStepDefinition {
|
|
|
223
223
|
id: 'agent-voice-media',
|
|
224
224
|
title: 'Voice and media',
|
|
225
225
|
shortLabel: 'Voice',
|
|
226
|
-
description: 'Prepare voice, speech, image input, and media understanding as Agent operator tools
|
|
226
|
+
description: 'Prepare voice, speech, image input, and media understanding as optional Agent operator tools.',
|
|
227
227
|
summaryTitle: 'Voice and media posture',
|
|
228
228
|
summaryLines: [
|
|
229
229
|
'Voice and speech: optional operator tools',
|
|
@@ -114,10 +114,10 @@ function buildReviewReadinessFields(controller: OnboardingWizardController): rea
|
|
|
114
114
|
{
|
|
115
115
|
kind: 'status',
|
|
116
116
|
id: 'review.readiness.connection',
|
|
117
|
-
label: '
|
|
117
|
+
label: 'Connected services snapshot',
|
|
118
118
|
hint: collectionIssues > 0
|
|
119
119
|
? `${collectionIssues} setup snapshot issue(s) need attention before this Agent is day-one ready.`
|
|
120
|
-
: 'The setup snapshot loaded cleanly from
|
|
120
|
+
: 'The setup snapshot loaded cleanly from connected GoodVibes services.',
|
|
121
121
|
defaultValue: collectionIssues > 0 ? 'Needs attention' : 'Ready',
|
|
122
122
|
spacerBeforeRows: 1,
|
|
123
123
|
},
|
|
@@ -160,7 +160,7 @@ function buildReviewReadinessFields(controller: OnboardingWizardController): rea
|
|
|
160
160
|
kind: 'status',
|
|
161
161
|
id: 'review.readiness.automation',
|
|
162
162
|
label: 'Routines and schedules',
|
|
163
|
-
hint: automation?.detail ?? 'Local routines run in the main conversation;
|
|
163
|
+
hint: automation?.detail ?? 'Local routines run in the main conversation; connected schedules require explicit promotion and confirmation.',
|
|
164
164
|
defaultValue: automation?.selected ? 'Review configured' : 'Local first',
|
|
165
165
|
},
|
|
166
166
|
{
|
|
@@ -211,7 +211,7 @@ export function buildAgentSetupStep(controller: OnboardingWizardController): Onb
|
|
|
211
211
|
summaryLines: [
|
|
212
212
|
'Agent owns the operator TUI and local behavior registry.',
|
|
213
213
|
'Optional starter profile: create an isolated Agent home from setup.',
|
|
214
|
-
'
|
|
214
|
+
'Setup here changes only Agent-owned settings and local state.',
|
|
215
215
|
`Secret policy: ${controller.getStringFieldValue('agent-setup.secret-policy', secretPolicy)}`,
|
|
216
216
|
collectionIssues > 0 ? `${collectionIssues} setup snapshot issue(s)` : 'Setup snapshot collected cleanly',
|
|
217
217
|
],
|
|
@@ -226,11 +226,11 @@ export function buildAgentSetupStep(controller: OnboardingWizardController): Onb
|
|
|
226
226
|
{
|
|
227
227
|
kind: 'status',
|
|
228
228
|
id: 'agent-setup.connection',
|
|
229
|
-
label: 'GoodVibes
|
|
229
|
+
label: 'Connected GoodVibes services',
|
|
230
230
|
hint: collectionIssues > 0
|
|
231
231
|
? `${collectionIssues} setup snapshot issue(s) were reported. Status and doctor commands show connection details.`
|
|
232
|
-
: 'Agent
|
|
233
|
-
defaultValue: collectionIssues > 0 ? `${collectionIssues} issue(s)` : '
|
|
232
|
+
: 'Agent uses connected GoodVibes services for companion chat, work plans, approvals, automation, and Agent Knowledge.',
|
|
233
|
+
defaultValue: collectionIssues > 0 ? `${collectionIssues} issue(s)` : 'Connected',
|
|
234
234
|
},
|
|
235
235
|
{
|
|
236
236
|
kind: 'radio',
|
|
@@ -514,7 +514,7 @@ export function buildReviewStep(controller: OnboardingWizardController): Onboard
|
|
|
514
514
|
id: 'review.apply',
|
|
515
515
|
action: 'apply',
|
|
516
516
|
label: 'Apply Agent settings and verify',
|
|
517
|
-
hint: 'Persist
|
|
517
|
+
hint: 'Persist Agent-owned settings and verify that setup did not request non-Agent entrypoints, default wiki access, or non-Agent knowledge setup.',
|
|
518
518
|
defaultValue: 'Ready',
|
|
519
519
|
},
|
|
520
520
|
],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const AGENT_EXTERNAL_DAEMON_SETTING_LOCK_REASON = 'GoodVibes Agent
|
|
1
|
+
export const AGENT_EXTERNAL_DAEMON_SETTING_LOCK_REASON = 'GoodVibes Agent uses connected GoodVibes services. Change service lifecycle and bind posture from the owning host; Agent settings are read-only for those controls.';
|
|
2
2
|
|
|
3
3
|
const AGENT_HIDDEN_SETTING_PREFIXES = [
|
|
4
4
|
['cloud', 'flare.'].join(''),
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export interface ParsedSlashCommand {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly args: readonly string[];
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function parseSlashCommand(command: string): ParsedSlashCommand {
|
|
7
|
+
const tokens = tokenizeSlashCommand(command.trim().replace(/^\//, ''));
|
|
8
|
+
return {
|
|
9
|
+
name: tokens[0] ?? '',
|
|
10
|
+
args: tokens.slice(1),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function tokenizeSlashCommand(command: string): readonly string[] {
|
|
15
|
+
const tokens: string[] = [];
|
|
16
|
+
let current = '';
|
|
17
|
+
let quote: '"' | "'" | null = null;
|
|
18
|
+
let escaping = false;
|
|
19
|
+
|
|
20
|
+
for (const char of command) {
|
|
21
|
+
if (escaping) {
|
|
22
|
+
current += char;
|
|
23
|
+
escaping = false;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (char === '\\') {
|
|
27
|
+
escaping = true;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (quote) {
|
|
31
|
+
if (char === quote) {
|
|
32
|
+
quote = null;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
current += char;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (char === '"' || char === "'") {
|
|
39
|
+
quote = char;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (/\s/.test(char)) {
|
|
43
|
+
if (current.length > 0) {
|
|
44
|
+
tokens.push(current);
|
|
45
|
+
current = '';
|
|
46
|
+
}
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
current += char;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (escaping) current += '\\';
|
|
53
|
+
if (current.length > 0) tokens.push(current);
|
|
54
|
+
return tokens;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function quoteSlashCommandArg(value: string): string {
|
|
58
|
+
if (/^[A-Za-z0-9._/:=@,+-]+$/.test(value)) return value;
|
|
59
|
+
return `"${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
60
|
+
}
|
|
@@ -80,7 +80,7 @@ export function registerAgentPanels(manager: PanelManager, deps: ResolvedBuiltin
|
|
|
80
80
|
name: 'Schedule',
|
|
81
81
|
icon: 'Z',
|
|
82
82
|
category: 'agent',
|
|
83
|
-
description: 'Read-only schedule posture from
|
|
83
|
+
description: 'Read-only schedule posture from connected GoodVibes services; local Agent schedule mutation is blocked',
|
|
84
84
|
factory: () => new SchedulePanel(requireAutomationManager(deps)),
|
|
85
85
|
});
|
|
86
86
|
}
|
|
@@ -45,7 +45,7 @@ export function registerOperationsPanels(manager: PanelManager, deps: ResolvedBu
|
|
|
45
45
|
name: 'Automation',
|
|
46
46
|
icon: 'M',
|
|
47
47
|
category: 'monitoring',
|
|
48
|
-
description: 'Read-only automation jobs, runs, deliveries, and failure posture from
|
|
48
|
+
description: 'Read-only automation jobs, runs, deliveries, and failure posture from connected GoodVibes services',
|
|
49
49
|
factory: () => new AutomationControlPanel(ui.readModels.automation),
|
|
50
50
|
});
|
|
51
51
|
|
|
@@ -81,7 +81,7 @@ export function registerOperationsPanels(manager: PanelManager, deps: ResolvedBu
|
|
|
81
81
|
name: 'Tasks',
|
|
82
82
|
icon: 'J',
|
|
83
83
|
category: 'monitoring',
|
|
84
|
-
description: 'Queued, running, blocked, failed, and completed task summaries from
|
|
84
|
+
description: 'Queued, running, blocked, failed, and completed task summaries from connected GoodVibes services',
|
|
85
85
|
factory: () => new TasksPanel(ui.readModels.tasks),
|
|
86
86
|
});
|
|
87
87
|
|
|
@@ -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 /settings or the
|
|
220
|
+
recommendedActions.push(`Repair service OAuth credentials for ${providerId} in /settings or the owning GoodVibes host.`);
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
return {
|
|
@@ -46,13 +46,13 @@ export function buildProviderHealthDomainSummaries(
|
|
|
46
46
|
name: 'auth',
|
|
47
47
|
level: auth.bootstrapCredentialPresent ? 'warn' : 'info',
|
|
48
48
|
summary: auth.bootstrapCredentialPresent
|
|
49
|
-
? '
|
|
50
|
-
: '
|
|
49
|
+
? 'connected-service bootstrap credential visible in local compatibility state'
|
|
50
|
+
: 'connected-service auth administration belongs outside Agent',
|
|
51
51
|
next: '/auth review',
|
|
52
52
|
details: [
|
|
53
|
-
'GoodVibes Agent does not create, delete, rotate, revoke, or clear
|
|
53
|
+
'GoodVibes Agent does not create, delete, rotate, revoke, or clear connected-service auth users or sessions.',
|
|
54
54
|
`${auth.userCount} compatibility user record(s) and ${auth.sessionCount} session record(s) are visible for diagnostics only.`,
|
|
55
|
-
auth.bootstrapCredentialPresent ? '
|
|
55
|
+
auth.bootstrapCredentialPresent ? 'Bootstrap cleanup must be done in the owning GoodVibes host.' : '',
|
|
56
56
|
].filter(Boolean),
|
|
57
57
|
nextSteps: auth.bootstrapCredentialPresent
|
|
58
58
|
? ['/auth review', '/provider', '/subscription providers']
|
|
@@ -64,10 +64,10 @@ export function buildProviderHealthDomainSummaries(
|
|
|
64
64
|
name: 'settings',
|
|
65
65
|
level: !settings.available ? 'info' : settingIssueCount > 0 ? 'warn' : 'good',
|
|
66
66
|
summary: !settings.available
|
|
67
|
-
? 'settings
|
|
67
|
+
? 'settings API unavailable'
|
|
68
68
|
: settingIssueCount > 0
|
|
69
69
|
? `${settings.conflictCount} conflicts / ${settings.recentFailureCount} failures${settings.hasStagedManagedBundle ? ' / staged bundle' : ''}`
|
|
70
|
-
: 'settings
|
|
70
|
+
: 'settings API clean',
|
|
71
71
|
next: settingIssueCount > 0 ? '/settings' : '/config <key>',
|
|
72
72
|
details: [
|
|
73
73
|
settings.conflictCount > 0 ? `${settings.conflictCount} unresolved import conflict(s)` : '',
|
|
@@ -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: '/auth review', summary: 'inspect
|
|
83
|
+
{ command: '/auth review', summary: 'inspect connected-service auth posture without exposing token values' },
|
|
84
84
|
];
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -183,9 +183,9 @@ export class TasksPanel extends ScrollableListPanel<RuntimeTask> {
|
|
|
183
183
|
sections: [{
|
|
184
184
|
lines: buildEmptyState(
|
|
185
185
|
width,
|
|
186
|
-
'
|
|
187
|
-
'Use the Tasks panel with
|
|
188
|
-
[{ command: '/tasks', summary: 'inspect
|
|
186
|
+
' Task store not wired into this panel yet.',
|
|
187
|
+
'Use the Tasks panel with live connected-service task state to review active execution, cancellations, retries, and completion results.',
|
|
188
|
+
[{ command: '/tasks', summary: 'inspect connected-service tasks without starting background work' }],
|
|
189
189
|
C,
|
|
190
190
|
),
|
|
191
191
|
}],
|
|
@@ -196,8 +196,8 @@ function snapshotLines(workspace: AgentWorkspace, category: AgentWorkspaceCatego
|
|
|
196
196
|
);
|
|
197
197
|
} else if (category.id === 'setup') {
|
|
198
198
|
base.push(
|
|
199
|
-
{ text: `
|
|
200
|
-
{ text:
|
|
199
|
+
{ text: `Connection: ${snapshot.runtimeBaseUrl}`, fg: PALETTE.info },
|
|
200
|
+
{ text: 'Agent role: interactive operator TUI; setup changes here are Agent-local.', fg: PALETTE.good },
|
|
201
201
|
...setupChecklistLines(snapshot),
|
|
202
202
|
{ text: '' },
|
|
203
203
|
{ text: `Workspace: ${snapshot.workingDirectory}`, fg: PALETTE.muted },
|
|
@@ -218,13 +218,13 @@ function snapshotLines(workspace: AgentWorkspace, category: AgentWorkspaceCatego
|
|
|
218
218
|
...snapshot.channels.filter((channel) => !channel.enabled),
|
|
219
219
|
].slice(0, 6);
|
|
220
220
|
base.push(
|
|
221
|
-
{ text: `GoodVibes
|
|
221
|
+
{ text: `GoodVibes API: ${snapshot.runtimeBaseUrl}`, fg: PALETTE.info },
|
|
222
222
|
{ text: `Readiness: ${readyCount}/${snapshot.channels.length} ready; ${enabledCount} enabled; ${configuredDefaults} default target(s) configured.`, fg: PALETTE.info },
|
|
223
223
|
{ text: `Ready channels: ${readyChannels.join(', ') || 'none'}.`, fg: readyChannels.length > 0 ? PALETTE.good : PALETTE.warn },
|
|
224
224
|
{ text: `Needs default target: ${needsTarget.map((channel) => `${channel.label} -> ${channel.defaultTargetKeys.join('|')}`).join(', ') || 'none'}.`, fg: needsTarget.length > 0 ? PALETTE.warn : PALETTE.muted },
|
|
225
225
|
{ text: `Needs config: ${needsConfig.map((channel) => `${channel.label} -> ${channel.missingRequiredKeys.join('|')}`).join(', ') || 'none'}.`, fg: needsConfig.length > 0 ? PALETTE.warn : PALETTE.muted },
|
|
226
226
|
{ text: `Disabled channels: ${disabledPreview || 'none'}${disabledSuffix}.`, fg: PALETTE.dim },
|
|
227
|
-
{ text: 'Safety: no secret values; sends and public exposure require explicit user action and
|
|
227
|
+
{ text: 'Safety: no secret values; sends and public exposure require explicit user action and Agent policy.', fg: PALETTE.warn },
|
|
228
228
|
);
|
|
229
229
|
for (const channel of orderedChannels) {
|
|
230
230
|
const ready = channel.ready ? 'ready' : `${channel.missingConfigCount} missing`;
|
|
@@ -297,13 +297,13 @@ function snapshotLines(workspace: AgentWorkspace, category: AgentWorkspaceCatego
|
|
|
297
297
|
{ text: '' },
|
|
298
298
|
{ text: 'Named Agent profiles isolate local config, sessions, memory, personas, skills, routines, setup, and bundles.', fg: PALETTE.good },
|
|
299
299
|
{ text: 'Starter authoring: browse, export, edit, import, and create Agent profiles from inside this workspace.', fg: PALETTE.info },
|
|
300
|
-
{ text: '
|
|
300
|
+
{ text: 'Connected GoodVibes services stay shared unless the owning host is configured separately.', fg: PALETTE.warn },
|
|
301
301
|
{ text: 'Portable bundles require explicit export/import commands with real paths and --yes.', fg: PALETTE.muted },
|
|
302
302
|
);
|
|
303
303
|
} else if (category.id === 'memory') {
|
|
304
304
|
base.push(
|
|
305
305
|
{ text: `Session memories: ${snapshot.sessionMemoryCount}`, fg: PALETTE.info },
|
|
306
|
-
{ text: `Agent memory: ${snapshot.localMemoryCount}; review queue: ${snapshot.localMemoryReviewQueueCount}`, fg: PALETTE.info },
|
|
306
|
+
{ text: `Agent memory: ${snapshot.localMemoryCount}; prompt-active: ${snapshot.localMemoryPromptActiveCount}; review queue: ${snapshot.localMemoryReviewQueueCount}`, fg: PALETTE.info },
|
|
307
307
|
{ text: `Local routines: ${snapshot.localRoutineCount}; enabled: ${snapshot.enabledRoutineCount}`, fg: PALETTE.info },
|
|
308
308
|
{ text: `Local skills: ${snapshot.localSkillCount}; enabled: ${snapshot.enabledSkillCount}; bundles: ${snapshot.localSkillBundleCount}; active skills: ${snapshot.activeSkillCount}`, fg: PALETTE.info },
|
|
309
309
|
{ text: `Local personas: ${snapshot.localPersonaCount}; active: ${snapshot.activePersonaName}`, fg: PALETTE.info },
|
|
@@ -334,7 +334,7 @@ function snapshotLines(workspace: AgentWorkspace, category: AgentWorkspaceCatego
|
|
|
334
334
|
base.push(
|
|
335
335
|
{ text: `Routines: ${snapshot.localRoutineCount}; enabled: ${snapshot.enabledRoutineCount}`, fg: PALETTE.info },
|
|
336
336
|
{ text: 'Routines are repeatable main-conversation workflows. Starting one does not create hidden jobs.', fg: PALETTE.good },
|
|
337
|
-
{ text: 'Scheduling a reviewed routine is explicit and
|
|
337
|
+
{ text: 'Scheduling a reviewed routine is explicit and requires a confirmed schedule command.', fg: PALETTE.warn },
|
|
338
338
|
{ text: '' },
|
|
339
339
|
...localLibraryLines('Routine Library', snapshot.localRoutines, 'No local routines yet. Create one here with Create routine.', workspace.selectedLocalLibraryItem('routine')?.id ?? null),
|
|
340
340
|
);
|
|
@@ -346,7 +346,8 @@ function snapshotLines(workspace: AgentWorkspace, category: AgentWorkspaceCatego
|
|
|
346
346
|
} else if (category.id === 'automation') {
|
|
347
347
|
base.push(
|
|
348
348
|
{ text: 'Automation and schedules default to read-only observability.', fg: PALETTE.info },
|
|
349
|
-
{ text: '
|
|
349
|
+
{ text: 'Confirmed reminders and routine promotion use connected schedules only.', fg: PALETTE.info },
|
|
350
|
+
{ text: 'Local scheduler mutation/run controls remain blocked.', fg: PALETTE.warn },
|
|
350
351
|
);
|
|
351
352
|
} else if (category.id === 'delegate') {
|
|
352
353
|
base.push(
|
|
@@ -430,34 +431,46 @@ function buildEditorRows(editor: AgentWorkspaceLocalEditor, width: number, heigh
|
|
|
430
431
|
{ text: editor.message, fg: PALETTE.info },
|
|
431
432
|
{ text: '' },
|
|
432
433
|
];
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
selected,
|
|
443
|
-
fg: color,
|
|
444
|
-
bold: selected,
|
|
445
|
-
});
|
|
446
|
-
const valueLines = value.split('\n');
|
|
447
|
-
for (const valueLine of valueLines.slice(0, 4)) {
|
|
448
|
-
for (const wrapped of wrapText(` ${valueLine}`, Math.max(1, width - 2))) {
|
|
449
|
-
rows.push({ text: wrapped, fg: field.value.length > 0 ? PALETTE.text : PALETTE.dim, dim: field.value.length === 0 });
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
if (valueLines.length > 4) rows.push({ text: ` ${valueLines.length - 4} more line(s)`, fg: PALETTE.dim, dim: true });
|
|
453
|
-
rows.push({ text: ` ${field.hint}`, fg: PALETTE.dim, dim: true });
|
|
434
|
+
const footerRows: WorkspaceRow[] = [
|
|
435
|
+
{ text: '' },
|
|
436
|
+
{ text: 'Enter next/save · Up/Down field · Backspace edit · Ctrl-J newline · Esc cancel', fg: PALETTE.muted },
|
|
437
|
+
];
|
|
438
|
+
const visibleFields = Math.max(1, Math.floor(Math.max(1, height - rows.length - footerRows.length) / 3));
|
|
439
|
+
const window = stableWindow(editor.fields.length, editor.selectedFieldIndex, visibleFields);
|
|
440
|
+
if (window.start > 0) rows.push({ text: `${GLYPHS.navigation.moreAbove} ${window.start} more field(s) above`, kind: 'more', fg: PALETTE.dim, dim: true });
|
|
441
|
+
for (let index = window.start; index < window.end; index += 1) {
|
|
442
|
+
rows.push(...buildEditorFieldRows(editor, index, width));
|
|
454
443
|
}
|
|
455
|
-
rows.push({ text: '' });
|
|
456
|
-
rows.push(
|
|
444
|
+
if (window.end < editor.fields.length) rows.push({ text: `${GLYPHS.navigation.moreBelow} ${editor.fields.length - window.end} more field(s) below`, kind: 'more', fg: PALETTE.dim, dim: true });
|
|
445
|
+
rows.push(...footerRows);
|
|
457
446
|
while (rows.length < height) rows.push({ text: '', kind: 'empty' });
|
|
458
447
|
return rows.slice(0, height);
|
|
459
448
|
}
|
|
460
449
|
|
|
450
|
+
function buildEditorFieldRows(editor: AgentWorkspaceLocalEditor, index: number, width: number): WorkspaceRow[] {
|
|
451
|
+
const field = editor.fields[index]!;
|
|
452
|
+
const selected = index === editor.selectedFieldIndex;
|
|
453
|
+
const marker = selected ? GLYPHS.navigation.selected : ' ';
|
|
454
|
+
const required = field.required ? ' *' : '';
|
|
455
|
+
const value = field.value.length > 0 ? field.value : '(empty)';
|
|
456
|
+
const color = selected ? PALETTE.text : field.value.length > 0 ? PALETTE.info : PALETTE.muted;
|
|
457
|
+
const rows: WorkspaceRow[] = [{
|
|
458
|
+
text: `${marker} ${field.label}${required}`,
|
|
459
|
+
selected,
|
|
460
|
+
fg: color,
|
|
461
|
+
bold: selected,
|
|
462
|
+
}];
|
|
463
|
+
const valueLines = value.split('\n');
|
|
464
|
+
for (const valueLine of valueLines.slice(0, 4)) {
|
|
465
|
+
for (const wrapped of wrapText(` ${valueLine}`, Math.max(1, width - 2))) {
|
|
466
|
+
rows.push({ text: wrapped, fg: field.value.length > 0 ? PALETTE.text : PALETTE.dim, dim: field.value.length === 0 });
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
if (valueLines.length > 4) rows.push({ text: ` ${valueLines.length - 4} more line(s)`, fg: PALETTE.dim, dim: true });
|
|
470
|
+
rows.push({ text: ` ${field.hint}`, fg: PALETTE.dim, dim: true });
|
|
471
|
+
return rows;
|
|
472
|
+
}
|
|
473
|
+
|
|
461
474
|
function buildActionRows(workspace: AgentWorkspace, width: number, height: number): WorkspaceRow[] {
|
|
462
475
|
if (workspace.localEditor) return buildEditorRows(workspace.localEditor, width, height);
|
|
463
476
|
const rows: WorkspaceRow[] = [];
|
|
@@ -78,7 +78,7 @@ export function renderHelpOverlay(
|
|
|
78
78
|
['routines', '', 'Manage reusable main-conversation routines'],
|
|
79
79
|
['workplan', '', 'Inspect shared work-plan state'],
|
|
80
80
|
['approval', '', 'Review and explicitly act on approvals'],
|
|
81
|
-
['schedule', '',
|
|
81
|
+
['schedule', 'remind', 'Create confirmed reminders or inspect schedules'],
|
|
82
82
|
['delegate', '', 'Explicitly hand build/fix/review work to GoodVibes TUI'],
|
|
83
83
|
['mcp', '', 'Inspect MCP servers and tool readiness'],
|
|
84
84
|
['provider', '', 'Choose provider or model family'],
|