@pellux/goodvibes-agent 0.1.63 → 0.1.65
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 +12 -0
- package/README.md +3 -3
- package/docs/getting-started.md +2 -2
- package/docs/release-and-publishing.md +1 -1
- package/package.json +1 -1
- package/src/cli/agent-knowledge-command.ts +1 -1
- package/src/cli/help.ts +3 -3
- package/src/cli/management-commands.ts +7 -7
- package/src/cli/profiles-command.ts +8 -8
- package/src/cli/routines-command.ts +1 -1
- package/src/cli/service-posture.ts +2 -2
- package/src/cli/status.ts +6 -6
- package/src/cli/surface-command.ts +1 -1
- package/src/input/agent-workspace-categories.ts +16 -17
- package/src/input/agent-workspace-setup.ts +4 -4
- package/src/input/agent-workspace.ts +1 -1
- package/src/input/commands/agent-runtime-profile-runtime.ts +10 -10
- package/src/input/commands/local-auth-runtime.ts +1 -1
- package/src/input/commands/operator-runtime.ts +2 -2
- package/src/input/commands/platform-access-runtime.ts +28 -15
- package/src/input/commands/remote-runtime-setup.ts +6 -6
- package/src/input/commands/routines-runtime.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-steps.ts +3 -3
- package/src/panels/automation-control-panel.ts +2 -2
- package/src/panels/builtin/agent.ts +1 -1
- package/src/panels/builtin/operations.ts +5 -5
- package/src/panels/control-plane-panel.ts +10 -10
- package/src/panels/local-auth-panel.ts +1 -1
- package/src/panels/ops-control-panel.ts +3 -3
- package/src/panels/project-planning-panel.ts +2 -2
- package/src/panels/provider-health-domains.ts +2 -2
- package/src/panels/remote-panel.ts +2 -2
- package/src/panels/schedule-panel.ts +1 -1
- package/src/panels/watchers-panel.ts +1 -1
- package/src/renderer/agent-workspace.ts +9 -9
- package/src/renderer/settings-modal-helpers.ts +14 -14
- package/src/renderer/settings-modal.ts +4 -4
- package/src/runtime/bootstrap.ts +8 -8
- package/src/runtime/diagnostics/panels/ops.ts +1 -1
- package/src/runtime/index.ts +2 -2
- package/src/runtime/onboarding/derivation.ts +15 -15
- package/src/version.ts +1 -1
|
@@ -31,13 +31,26 @@ interface UpdateBundle {
|
|
|
31
31
|
interface AuthReviewBundle {
|
|
32
32
|
readonly version: 1;
|
|
33
33
|
readonly exportedAt: number;
|
|
34
|
-
readonly
|
|
34
|
+
readonly runtimeLoginUrl: string;
|
|
35
35
|
readonly listenerLoginUrl: string;
|
|
36
36
|
readonly secretKeys: readonly string[];
|
|
37
37
|
readonly activeSubscriptions: readonly string[];
|
|
38
38
|
readonly pendingSubscriptions: readonly string[];
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
type AuthServiceLoginTarget = 'runtime' | 'listener';
|
|
42
|
+
|
|
43
|
+
function normalizeAuthServiceLoginTarget(value: string | undefined): AuthServiceLoginTarget | null {
|
|
44
|
+
const normalized = value?.trim().toLowerCase();
|
|
45
|
+
if (normalized === 'runtime' || normalized === 'daemon') return 'runtime';
|
|
46
|
+
if (normalized === 'listener' || normalized === 'inbound-listener') return 'listener';
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function authServiceSecretPrefix(target: AuthServiceLoginTarget): string {
|
|
51
|
+
return target === 'runtime' ? 'RUNTIME' : 'LISTENER';
|
|
52
|
+
}
|
|
53
|
+
|
|
41
54
|
function buildSetupLink(surface: string, target?: string): string {
|
|
42
55
|
const params = target ? `?target=${encodeURIComponent(target)}` : '';
|
|
43
56
|
return `goodvibes://open/${surface}${params}`;
|
|
@@ -68,7 +81,7 @@ function inspectAuthBundle(bundle: AuthReviewBundle): string {
|
|
|
68
81
|
return [
|
|
69
82
|
'Auth Review Bundle',
|
|
70
83
|
` exportedAt: ${new Date(bundle.exportedAt).toISOString()}`,
|
|
71
|
-
`
|
|
84
|
+
` runtimeLoginUrl: ${bundle.runtimeLoginUrl}`,
|
|
72
85
|
` listenerLoginUrl: ${bundle.listenerLoginUrl}`,
|
|
73
86
|
` stored secrets: ${bundle.secretKeys.length}`,
|
|
74
87
|
` active subscriptions: ${bundle.activeSubscriptions.length}`,
|
|
@@ -80,7 +93,7 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
80
93
|
registry.register({
|
|
81
94
|
name: 'login',
|
|
82
95
|
description: 'Front-door login flow for provider subscriptions and local service sessions',
|
|
83
|
-
usage: '[provider <name> start|finish <code> --yes|service <
|
|
96
|
+
usage: '[provider <name> start|finish <code> --yes|service <runtime|listener> <baseUrl> <username> <password> [secretKey] --yes]',
|
|
84
97
|
async handler(args, ctx) {
|
|
85
98
|
const parsed = stripYesFlag(args);
|
|
86
99
|
const commandArgs = [...parsed.rest];
|
|
@@ -106,17 +119,17 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
106
119
|
}
|
|
107
120
|
if (target === 'service') {
|
|
108
121
|
if (!parsed.yes) {
|
|
109
|
-
requireYesFlag(ctx, 'store a local service session token', '/login service <
|
|
122
|
+
requireYesFlag(ctx, 'store a local service session token', '/login service <runtime|listener> <baseUrl> <username> <password> [secretKey] --yes');
|
|
110
123
|
return;
|
|
111
124
|
}
|
|
112
125
|
if (ctx.executeCommand) {
|
|
113
126
|
await ctx.executeCommand('auth', ['login', ...commandArgs.slice(1), '--yes']);
|
|
114
127
|
return;
|
|
115
128
|
}
|
|
116
|
-
ctx.print('Use /auth login <
|
|
129
|
+
ctx.print('Use /auth login <runtime|listener> <baseUrl> <username> <password> [secretKey] --yes');
|
|
117
130
|
return;
|
|
118
131
|
}
|
|
119
|
-
ctx.print('Usage: /login [provider <name> start|finish <code> --yes|service <
|
|
132
|
+
ctx.print('Usage: /login [provider <name> start|finish <code> --yes|service <runtime|listener> <baseUrl> <username> <password> [secretKey] --yes]');
|
|
120
133
|
},
|
|
121
134
|
});
|
|
122
135
|
|
|
@@ -293,7 +306,7 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
293
306
|
registry.register({
|
|
294
307
|
name: 'auth',
|
|
295
308
|
description: 'Review auth posture and exchange session login tokens with local services',
|
|
296
|
-
usage: '[review|show <provider>|repair <provider>|bundle export <path> --yes|bundle inspect <path>|login <
|
|
309
|
+
usage: '[review|show <provider>|repair <provider>|bundle export <path> --yes|bundle inspect <path>|login <runtime|listener> <baseUrl> <username> <password> [secretKey] --yes|local <review|panel|add-user --yes|delete-user --yes|rotate-password --yes|revoke-session --yes|clear-bootstrap-file --yes>]',
|
|
297
310
|
async handler(args, ctx) {
|
|
298
311
|
const parsed = stripYesFlag(args);
|
|
299
312
|
const commandArgs = [...parsed.rest];
|
|
@@ -315,7 +328,7 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
315
328
|
const builtinProviders = listBuiltinSubscriptionProviders().map((entry) => entry.provider);
|
|
316
329
|
ctx.print([
|
|
317
330
|
'Auth Review',
|
|
318
|
-
'
|
|
331
|
+
' runtime login route: /login',
|
|
319
332
|
' listener login route: /login',
|
|
320
333
|
` stored secrets: ${snapshot.secretKeyCount}`,
|
|
321
334
|
` built-in providers: ${builtinProviders.length}${builtinProviders.length > 0 ? ` (${builtinProviders.join(', ')})` : ''}`,
|
|
@@ -397,7 +410,7 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
397
410
|
const bundle: AuthReviewBundle = {
|
|
398
411
|
version: 1,
|
|
399
412
|
exportedAt: Date.now(),
|
|
400
|
-
|
|
413
|
+
runtimeLoginUrl: 'http://127.0.0.1:3421/login',
|
|
401
414
|
listenerLoginUrl: 'http://127.0.0.1:3422/login',
|
|
402
415
|
secretKeys,
|
|
403
416
|
activeSubscriptions: subscriptions.list().map((entry) => entry.provider),
|
|
@@ -416,17 +429,17 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
416
429
|
}
|
|
417
430
|
|
|
418
431
|
if (sub === 'login') {
|
|
419
|
-
const target = commandArgs[1];
|
|
432
|
+
const target = normalizeAuthServiceLoginTarget(commandArgs[1]);
|
|
420
433
|
const baseUrl = commandArgs[2];
|
|
421
434
|
const username = commandArgs[3];
|
|
422
435
|
const password = commandArgs[4];
|
|
423
|
-
const secretKey = commandArgs[5] ?? `${target
|
|
424
|
-
if (
|
|
425
|
-
ctx.print('Usage: /auth login <
|
|
436
|
+
const secretKey = commandArgs[5] ?? `${target ? authServiceSecretPrefix(target) : 'SERVICE'}_SESSION_TOKEN`;
|
|
437
|
+
if (!target || !baseUrl || !username || !password) {
|
|
438
|
+
ctx.print('Usage: /auth login <runtime|listener> <baseUrl> <username> <password> [secretKey] --yes');
|
|
426
439
|
return;
|
|
427
440
|
}
|
|
428
441
|
if (!parsed.yes) {
|
|
429
|
-
requireYesFlag(ctx, `store ${target} session token`, '/auth login <
|
|
442
|
+
requireYesFlag(ctx, `store ${target} session token`, '/auth login <runtime|listener> <baseUrl> <username> <password> [secretKey] --yes');
|
|
430
443
|
return;
|
|
431
444
|
}
|
|
432
445
|
const url = new URL('/login', baseUrl).toString();
|
|
@@ -450,7 +463,7 @@ export function registerPlatformAccessRuntimeCommands(registry: CommandRegistry)
|
|
|
450
463
|
return;
|
|
451
464
|
}
|
|
452
465
|
|
|
453
|
-
ctx.print('Usage: /auth [review|show <provider>|bundle export <path> --yes|bundle inspect <path>|login <
|
|
466
|
+
ctx.print('Usage: /auth [review|show <provider>|bundle export <path> --yes|bundle inspect <path>|login <runtime|listener> <baseUrl> <username> <password> [secretKey] --yes|local <review|panel|add-user --yes|delete-user --yes|rotate-password --yes|revoke-session --yes|clear-bootstrap-file --yes>]');
|
|
454
467
|
},
|
|
455
468
|
});
|
|
456
469
|
}
|
|
@@ -43,15 +43,15 @@ export async function handleRemoteSetupCommand(
|
|
|
43
43
|
const lines = [
|
|
44
44
|
'Remote Setup Review',
|
|
45
45
|
` acp agent command: ${command.join(' ')}`,
|
|
46
|
-
`
|
|
47
|
-
`
|
|
46
|
+
` runtime host enabled: ${danger.daemon ? 'yes' : 'no'}`,
|
|
47
|
+
` inbound listener enabled: ${danger.httpListener ? 'yes' : 'no'}`,
|
|
48
48
|
` remote runner contracts: ${remoteRegistry.listContracts().length}`,
|
|
49
49
|
` active acp connections: ${activeConnections.length}`,
|
|
50
50
|
'',
|
|
51
51
|
' guidance:',
|
|
52
52
|
' - set ACP_AGENT_CMD to override the spawned remote agent command',
|
|
53
53
|
' - use /remote env to export a reusable shell snippet',
|
|
54
|
-
' -
|
|
54
|
+
' - runtime-host and inbound-listener posture belongs to the runtime owner, not Agent onboarding',
|
|
55
55
|
];
|
|
56
56
|
if (commandArgs[1]?.toLowerCase() === 'export') {
|
|
57
57
|
const pathArg = commandArgs[2];
|
|
@@ -69,8 +69,8 @@ export async function handleRemoteSetupCommand(
|
|
|
69
69
|
writeFileSync(targetPath, `${JSON.stringify({
|
|
70
70
|
exportedAt: Date.now(),
|
|
71
71
|
acpAgentCommand: command,
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
runtimeHostEnabled: Boolean(danger.daemon),
|
|
73
|
+
inboundListenerEnabled: Boolean(danger.httpListener),
|
|
74
74
|
remoteRunnerContracts: remoteRegistry.listContracts().length,
|
|
75
75
|
}, null, 2)}\n`, 'utf-8');
|
|
76
76
|
ctx.print(`Exported remote setup bundle to ${targetPath}`);
|
|
@@ -111,7 +111,7 @@ export async function handleRemoteSetupCommand(
|
|
|
111
111
|
const mode = commandArgs[1]?.toLowerCase() ?? 'review';
|
|
112
112
|
const lines = [
|
|
113
113
|
'Remote Tunnel Review',
|
|
114
|
-
' transport: self-hosted ACP /
|
|
114
|
+
' transport: self-hosted ACP / runtime relay',
|
|
115
115
|
` session: ${ctx.session.runtime.sessionId}`,
|
|
116
116
|
` active remote connections: ${activeConnections.length}`,
|
|
117
117
|
' guidance: forward ACP agent traffic through your chosen self-hosted tunnel or SSH transport',
|
|
@@ -243,7 +243,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
|
|
|
243
243
|
const routine = routineRegistry.markStarted(id);
|
|
244
244
|
ctx.print([
|
|
245
245
|
`Started Agent routine ${routine.id}: ${routine.name}`,
|
|
246
|
-
' policy: same main conversation; no hidden
|
|
246
|
+
' policy: same main conversation; no hidden job, runtime mutation, or external side effect was started',
|
|
247
247
|
'',
|
|
248
248
|
routine.steps,
|
|
249
249
|
].join('\n'));
|
|
@@ -201,7 +201,7 @@ export function buildAgentSetupStep(controller: OnboardingWizardController): Onb
|
|
|
201
201
|
{
|
|
202
202
|
kind: 'status',
|
|
203
203
|
id: 'agent-setup.profile-guide',
|
|
204
|
-
label: '
|
|
204
|
+
label: 'Agent profiles',
|
|
205
205
|
hint: 'Use /agent-profile guide after setup to create household, research, travel, operations, or custom Agent profiles.',
|
|
206
206
|
defaultValue: 'Local profiles',
|
|
207
207
|
},
|
|
@@ -378,7 +378,7 @@ export function buildLocalStateStep(): OnboardingWizardStepDefinition {
|
|
|
378
378
|
id: 'agent-local-state',
|
|
379
379
|
title: 'Local memory and behavior',
|
|
380
380
|
shortLabel: 'Memory',
|
|
381
|
-
description: 'Review the Agent-local behavior model. Memory, personas, skills, routines, and
|
|
381
|
+
description: 'Review the Agent-local behavior model. Memory, personas, skills, routines, and Agent profiles stay local until a stable shared registry exists.',
|
|
382
382
|
summaryTitle: 'Local Agent state',
|
|
383
383
|
summaryLines: [
|
|
384
384
|
'Memory/personas/skills/routines: local Agent registries',
|
|
@@ -501,7 +501,7 @@ export function buildVoiceMediaStep(): OnboardingWizardStepDefinition {
|
|
|
501
501
|
kind: 'status',
|
|
502
502
|
id: 'agent-voice-media.nodes',
|
|
503
503
|
label: 'Node and device posture',
|
|
504
|
-
hint: 'Remote devices and nodes are inspected
|
|
504
|
+
hint: 'Remote devices and nodes are inspected only when useful. Agent onboarding does not launch runners or background service processes.',
|
|
505
505
|
defaultValue: 'External',
|
|
506
506
|
},
|
|
507
507
|
],
|
|
@@ -88,12 +88,12 @@ 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: '/automation jobs', summary: 'review
|
|
91
|
+
{ command: '/automation jobs', summary: 'review runtime-owned automation jobs from Agent' },
|
|
92
92
|
];
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
public render(width: number, height: number): Line[] {
|
|
96
|
-
const intro = 'Automation jobs, active runs, deliveries, and failure posture across the shared
|
|
96
|
+
const intro = 'Automation jobs, active runs, deliveries, and failure posture across the shared runtime.';
|
|
97
97
|
|
|
98
98
|
if (!this.readModel) {
|
|
99
99
|
const workspace = buildPanelWorkspace(width, height, {
|
|
@@ -97,7 +97,7 @@ export function registerAgentPanels(manager: PanelManager, deps: ResolvedBuiltin
|
|
|
97
97
|
name: 'Schedule',
|
|
98
98
|
icon: 'Z',
|
|
99
99
|
category: 'agent',
|
|
100
|
-
description: 'Read-only schedule posture from the external
|
|
100
|
+
description: 'Read-only schedule posture from the external runtime; local Agent schedule mutation is blocked',
|
|
101
101
|
factory: () => new SchedulePanel(requireAutomationManager(deps)),
|
|
102
102
|
});
|
|
103
103
|
}
|
|
@@ -102,7 +102,7 @@ export function registerOperationsPanels(manager: PanelManager, deps: ResolvedBu
|
|
|
102
102
|
name: 'Automation',
|
|
103
103
|
icon: 'M',
|
|
104
104
|
category: 'monitoring',
|
|
105
|
-
description: 'Automation jobs, runs, deliveries, and failure posture across the
|
|
105
|
+
description: 'Automation jobs, runs, deliveries, and failure posture across the shared runtime',
|
|
106
106
|
factory: () => new AutomationControlPanel(ui.readModels.automation),
|
|
107
107
|
});
|
|
108
108
|
|
|
@@ -126,10 +126,10 @@ export function registerOperationsPanels(manager: PanelManager, deps: ResolvedBu
|
|
|
126
126
|
|
|
127
127
|
manager.registerType({
|
|
128
128
|
id: 'control-plane',
|
|
129
|
-
name: '
|
|
129
|
+
name: 'Runtime Status',
|
|
130
130
|
icon: 'C',
|
|
131
131
|
category: 'monitoring',
|
|
132
|
-
description: '
|
|
132
|
+
description: 'Runtime state, clients, approvals, and recent operator activity',
|
|
133
133
|
factory: () => {
|
|
134
134
|
requireControlPlanePanelDeps(deps);
|
|
135
135
|
return new ControlPlanePanel(ui.readModels.controlPlane);
|
|
@@ -150,7 +150,7 @@ export function registerOperationsPanels(manager: PanelManager, deps: ResolvedBu
|
|
|
150
150
|
name: 'Local Auth',
|
|
151
151
|
icon: 'U',
|
|
152
152
|
category: 'monitoring',
|
|
153
|
-
description: 'Local
|
|
153
|
+
description: 'Local runtime auth users, bootstrap posture, and active sessions',
|
|
154
154
|
factory: () => new LocalAuthPanel(deps.localUserAuthManager),
|
|
155
155
|
});
|
|
156
156
|
|
|
@@ -251,7 +251,7 @@ export function registerOperationsPanels(manager: PanelManager, deps: ResolvedBu
|
|
|
251
251
|
name: 'Remote',
|
|
252
252
|
icon: 'R',
|
|
253
253
|
category: 'monitoring',
|
|
254
|
-
description: '
|
|
254
|
+
description: 'Runtime transport state with active remote connections',
|
|
255
255
|
factory: () => new RemotePanel(ui.readModels.remote),
|
|
256
256
|
});
|
|
257
257
|
|
|
@@ -42,7 +42,7 @@ export class ControlPlanePanel extends ScrollableListPanel<ControlPlaneClient> {
|
|
|
42
42
|
private readonly unsub: (() => void) | null;
|
|
43
43
|
|
|
44
44
|
public constructor(private readonly readModel?: UiReadModel<UiControlPlaneSnapshot>) {
|
|
45
|
-
super('control-plane', '
|
|
45
|
+
super('control-plane', 'Runtime Status', 'C', 'monitoring');
|
|
46
46
|
this.showSelectionGutter = true; // I5: non-color selection affordance
|
|
47
47
|
this.unsub = readModel ? readModel.subscribe(() => this.markDirty()) : null;
|
|
48
48
|
}
|
|
@@ -72,7 +72,7 @@ export class ControlPlanePanel extends ScrollableListPanel<ControlPlaneClient> {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
protected override getEmptyStateMessage(): string {
|
|
75
|
-
return ' No
|
|
75
|
+
return ' No runtime activity recorded.';
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
protected override getEmptyStateActions(): Array<{ command: string; summary: string }> {
|
|
@@ -83,18 +83,18 @@ export class ControlPlanePanel extends ScrollableListPanel<ControlPlaneClient> {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
public render(width: number, height: number): Line[] {
|
|
86
|
-
const intro = 'Shared
|
|
86
|
+
const intro = 'Shared runtime state, live clients, approval pressure, and recent channel session posture.';
|
|
87
87
|
|
|
88
88
|
if (!this.readModel) {
|
|
89
89
|
const workspace = buildPanelWorkspace(width, height, {
|
|
90
|
-
title: '
|
|
90
|
+
title: 'Runtime Status',
|
|
91
91
|
intro,
|
|
92
92
|
sections: [{
|
|
93
93
|
lines: buildEmptyState(
|
|
94
94
|
width,
|
|
95
95
|
' Runtime read model not wired.',
|
|
96
|
-
'This panel needs the shared
|
|
97
|
-
[{ command: '/cockpit', summary: 'use the cockpit while
|
|
96
|
+
'This panel needs the shared runtime read model to inspect clients, requests, and approvals.',
|
|
97
|
+
[{ command: '/cockpit', summary: 'use the cockpit while runtime wiring is unavailable' }],
|
|
98
98
|
C,
|
|
99
99
|
),
|
|
100
100
|
}],
|
|
@@ -123,14 +123,14 @@ export class ControlPlanePanel extends ScrollableListPanel<ControlPlaneClient> {
|
|
|
123
123
|
{ label: 'sessions', value: String(sessions.length), valueColor: sessions.length > 0 ? C.info : C.dim },
|
|
124
124
|
{ label: 'events', value: String(recentEvents.length), valueColor: recentEvents.length > 0 ? C.info : C.dim },
|
|
125
125
|
], C),
|
|
126
|
-
buildGuidanceLine(width, '/cockpit', 'use
|
|
126
|
+
buildGuidanceLine(width, '/cockpit', 'use confirmed runtime actions for interventions while this panel tracks overall posture', C),
|
|
127
127
|
];
|
|
128
128
|
|
|
129
129
|
if (clients.length === 0 && approvals.length === 0 && sessions.length === 0) {
|
|
130
130
|
return this.renderList(width, height, {
|
|
131
|
-
title: '
|
|
131
|
+
title: 'Runtime Status',
|
|
132
132
|
header: headerLines,
|
|
133
|
-
emptyMessage: ' No
|
|
133
|
+
emptyMessage: ' No runtime activity recorded.',
|
|
134
134
|
});
|
|
135
135
|
}
|
|
136
136
|
|
|
@@ -203,7 +203,7 @@ export class ControlPlanePanel extends ScrollableListPanel<ControlPlaneClient> {
|
|
|
203
203
|
footerLines.push(buildPanelLine(width, [[' Up/Down move through connected clients', C.dim]]));
|
|
204
204
|
|
|
205
205
|
return this.renderList(width, height, {
|
|
206
|
-
title: '
|
|
206
|
+
title: 'Runtime Status',
|
|
207
207
|
header: headerLines,
|
|
208
208
|
footer: footerLines,
|
|
209
209
|
});
|
|
@@ -57,7 +57,7 @@ export class LocalAuthPanel extends ScrollableListPanel<LocalAuthUser> {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
public render(width: number, height: number): Line[] {
|
|
60
|
-
const intro = '
|
|
60
|
+
const intro = 'Review local runtime auth users, bootstrap state, and active sessions.';
|
|
61
61
|
const snapshot = this.authManager.inspect();
|
|
62
62
|
const users = this.getItems();
|
|
63
63
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OpsControlPanel — operator
|
|
2
|
+
* OpsControlPanel — operator intervention log panel.
|
|
3
3
|
*
|
|
4
4
|
* Renders the ops audit log sourced from the OpsPanel diagnostics subscriber.
|
|
5
5
|
* Each entry shows: seq, timestamp, action, target, outcome, and optional note.
|
|
@@ -130,7 +130,7 @@ export class OpsControlPanel extends ScrollableListPanel<OpsAuditEntry> {
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
protected override getEmptyStateActions(): Array<{ command: string; summary: string }> {
|
|
133
|
-
return [{ command: '/cockpit', summary: 'open the cockpit and
|
|
133
|
+
return [{ command: '/cockpit', summary: 'open the cockpit and review runtime interventions' }];
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
public render(width: number, height: number): Line[] {
|
|
@@ -142,7 +142,7 @@ export class OpsControlPanel extends ScrollableListPanel<OpsAuditEntry> {
|
|
|
142
142
|
];
|
|
143
143
|
|
|
144
144
|
return this.renderList(width, height, {
|
|
145
|
-
title: 'Operator
|
|
145
|
+
title: 'Operator Interventions',
|
|
146
146
|
header: headerLines,
|
|
147
147
|
footer: footerLines,
|
|
148
148
|
});
|
|
@@ -545,13 +545,13 @@ export class ProjectPlanningPanel extends BasePanel {
|
|
|
545
545
|
id: 'scope-end-to-end',
|
|
546
546
|
label: 'End-to-end required scope',
|
|
547
547
|
detail: 'Let the plan include every component needed to make this work, but avoid unrelated cleanup.',
|
|
548
|
-
answer: 'Scope is everything required to make the requested outcome work end-to-end. Include TUI,
|
|
548
|
+
answer: 'Scope is everything required to make the requested outcome work end-to-end. Include TUI, runtime composition, configuration, docs, and tests if they are required. Do not include unrelated cleanup or broad refactors unless they are necessary for this task.',
|
|
549
549
|
});
|
|
550
550
|
actions.push({
|
|
551
551
|
id: 'scope-agent-first',
|
|
552
552
|
label: 'Agent-first scope',
|
|
553
553
|
detail: 'Fix Agent behavior here; report SDK blockers instead of patching around SDK-owned bugs.',
|
|
554
|
-
answer: 'Scope is Agent-owned behavior first. If a blocker is SDK-owned, report the exact SDK contract/runtime issue instead of patching around it locally. Include
|
|
554
|
+
answer: 'Scope is Agent-owned behavior first. If a blocker is SDK-owned, report the exact SDK contract/runtime issue instead of patching around it locally. Include runtime contracts only where Agent consumes public runtime routes.',
|
|
555
555
|
});
|
|
556
556
|
}
|
|
557
557
|
actions.push({
|
|
@@ -63,10 +63,10 @@ export function buildProviderHealthDomainSummaries(
|
|
|
63
63
|
name: 'settings',
|
|
64
64
|
level: !settings.available ? 'info' : settingIssueCount > 0 ? 'warn' : 'good',
|
|
65
65
|
summary: !settings.available
|
|
66
|
-
? 'settings
|
|
66
|
+
? 'settings runtime API unavailable'
|
|
67
67
|
: settingIssueCount > 0
|
|
68
68
|
? `${settings.conflictCount} conflicts / ${settings.recentFailureCount} failures${settings.hasStagedManagedBundle ? ' / staged bundle' : ''}`
|
|
69
|
-
: 'settings
|
|
69
|
+
: 'settings runtime API clean',
|
|
70
70
|
next: settingIssueCount > 0 ? '/settingssync panel' : '/settingssync show <key>',
|
|
71
71
|
details: [
|
|
72
72
|
settings.conflictCount > 0 ? `${settings.conflictCount} unresolved import conflict(s)` : '',
|
|
@@ -158,7 +158,7 @@ export class RemotePanel extends BasePanel {
|
|
|
158
158
|
|
|
159
159
|
const postureLines: Line[] = [
|
|
160
160
|
buildPanelLine(width, [
|
|
161
|
-
['
|
|
161
|
+
[' runtime ', C.label],
|
|
162
162
|
[daemon.transportState.toUpperCase(), stateColor(daemon.transportState)],
|
|
163
163
|
[' running ', C.label],
|
|
164
164
|
[daemon.isRunning ? 'yes' : 'no', daemon.isRunning ? C.ok : C.dim],
|
|
@@ -199,7 +199,7 @@ export class RemotePanel extends BasePanel {
|
|
|
199
199
|
|
|
200
200
|
if (daemon.lastError) {
|
|
201
201
|
postureLines.push(buildPanelLine(width, [
|
|
202
|
-
['
|
|
202
|
+
[' runtime error ', C.label],
|
|
203
203
|
[daemon.lastError.slice(0, Math.max(0, width - 14)), C.error],
|
|
204
204
|
]));
|
|
205
205
|
}
|
|
@@ -171,7 +171,7 @@ export class SchedulePanel extends BasePanel {
|
|
|
171
171
|
}
|
|
172
172
|
case 'return':
|
|
173
173
|
case ' ': {
|
|
174
|
-
this.setError('Schedule mutation is read-only in GoodVibes Agent; use
|
|
174
|
+
this.setError('Schedule mutation is read-only in GoodVibes Agent; use explicit runtime approval routes later.');
|
|
175
175
|
return true;
|
|
176
176
|
}
|
|
177
177
|
case 'r': {
|
|
@@ -130,7 +130,7 @@ export class WatchersPanel extends ScrollableListPanel<WatcherEntry> {
|
|
|
130
130
|
{ label: 'degraded', value: String(snapshot.totalDegraded), valueColor: snapshot.totalDegraded > 0 ? C.warn : C.dim },
|
|
131
131
|
{ label: 'lagged', value: String(snapshot.totalLagged), valueColor: snapshot.totalLagged > 0 ? C.warn : C.dim },
|
|
132
132
|
], C),
|
|
133
|
-
buildGuidanceLine(width, '/schedule list', 'verify jobs consuming these sources
|
|
133
|
+
buildGuidanceLine(width, '/schedule list', 'verify jobs consuming these sources; Agent keeps watcher lifecycle read-only here', C),
|
|
134
134
|
];
|
|
135
135
|
|
|
136
136
|
if (watchers.length === 0) {
|
|
@@ -153,8 +153,8 @@ function snapshotLines(workspace: AgentWorkspace, category: AgentWorkspaceCatego
|
|
|
153
153
|
);
|
|
154
154
|
} else if (category.id === 'setup') {
|
|
155
155
|
base.push(
|
|
156
|
-
{ text: `
|
|
157
|
-
{ text: `Runtime
|
|
156
|
+
{ text: `GoodVibes runtime: ${snapshot.daemonBaseUrl}`, fg: PALETTE.info },
|
|
157
|
+
{ text: `Runtime owner: ${snapshot.daemonOwnership}; Agent connects but never starts or restarts it`, fg: PALETTE.good },
|
|
158
158
|
{ text: `Workspace: ${snapshot.workingDirectory}`, fg: PALETTE.muted },
|
|
159
159
|
{ text: `Home: ${snapshot.homeDirectory}`, fg: PALETTE.muted },
|
|
160
160
|
{ text: '' },
|
|
@@ -166,7 +166,7 @@ function snapshotLines(workspace: AgentWorkspace, category: AgentWorkspaceCatego
|
|
|
166
166
|
const configuredDefaults = snapshot.channels.filter((channel) => channel.defaultTarget === 'configured').length;
|
|
167
167
|
const disabledChannels = snapshot.channels.filter((channel) => !channel.enabled).map((channel) => channel.label).join(', ');
|
|
168
168
|
base.push(
|
|
169
|
-
{ text: `
|
|
169
|
+
{ text: `GoodVibes runtime: ${snapshot.daemonBaseUrl}`, fg: PALETTE.info },
|
|
170
170
|
{ text: `Readiness: ${readyCount}/${snapshot.channels.length} ready; ${enabledCount} enabled; ${configuredDefaults} default target(s) configured.`, fg: PALETTE.info },
|
|
171
171
|
{ text: `Disabled channels: ${disabledChannels || 'none'}.`, fg: PALETTE.dim },
|
|
172
172
|
{ text: 'Pairing: use /pair or /qrcode for companion setup.', fg: PALETTE.info },
|
|
@@ -195,18 +195,18 @@ function snapshotLines(workspace: AgentWorkspace, category: AgentWorkspaceCatego
|
|
|
195
195
|
{ text: `Voice surface: ${snapshot.voiceSurfaceEnabled ? 'enabled' : 'disabled'}; use /voice review for portable voice posture.`, fg: snapshot.voiceSurfaceEnabled ? PALETTE.warn : PALETTE.muted },
|
|
196
196
|
{ text: `TTS config: provider ${snapshot.ttsProvider}; voice ${snapshot.ttsVoice}; response model ${snapshot.ttsResponseModel}.`, fg: PALETTE.info },
|
|
197
197
|
{ text: `Media providers: ${snapshot.mediaProviderCount}; understanding: ${snapshot.mediaUnderstandingProviderCount}; generation: ${snapshot.mediaGenerationProviderCount}.`, fg: PALETTE.info },
|
|
198
|
-
{ text: `Browser
|
|
199
|
-
{ text: '
|
|
198
|
+
{ text: `Browser tools: ${snapshot.browserSurfaceEnabled ? 'available' : 'not advertised'}; public base URL ${snapshot.browserSurfacePublicBaseUrl}.`, fg: snapshot.browserSurfaceEnabled ? PALETTE.warn : PALETTE.muted },
|
|
199
|
+
{ text: 'Remote runner posture is hidden from this setup surface; build dispatch remains explicit delegation.', fg: PALETTE.good },
|
|
200
200
|
{ text: 'Image input uses prompt attachments; media generation/provider setup stays behind explicit commands and configured providers.', fg: PALETTE.muted },
|
|
201
201
|
);
|
|
202
202
|
} else if (category.id === 'profiles') {
|
|
203
203
|
base.push(
|
|
204
|
-
{ text: `Active
|
|
205
|
-
{ text: `
|
|
206
|
-
{ text: `
|
|
204
|
+
{ text: `Active Agent profile: ${snapshot.activeRuntimeProfile}`, fg: PALETTE.info },
|
|
205
|
+
{ text: `Agent profiles under this home: ${snapshot.runtimeProfileCount}`, fg: PALETTE.info },
|
|
206
|
+
{ text: `Agent profile root: ${snapshot.runtimeProfileRoot}`, fg: PALETTE.muted },
|
|
207
207
|
{ text: `Starter templates: ${snapshot.runtimeStarterTemplateCount}; local custom: ${snapshot.localStarterTemplateCount}`, fg: PALETTE.info },
|
|
208
208
|
{ text: `Config profiles: ${snapshot.configProfileCount}`, fg: PALETTE.info },
|
|
209
|
-
{ text: 'Named
|
|
209
|
+
{ text: 'Named Agent profiles isolate local config, sessions, memory, personas, skills, routines, setup, and bundles.', fg: PALETTE.good },
|
|
210
210
|
{ text: 'Starter authoring: browse, export, edit, import, and create Agent profiles from inside this workspace via /agent-profile.', fg: PALETTE.info },
|
|
211
211
|
{ text: 'The external GoodVibes runtime remains shared unless the owning host is configured separately.', fg: PALETTE.warn },
|
|
212
212
|
{ text: 'Portable bundles require explicit export/import commands with real paths and --yes.', fg: PALETTE.muted },
|
|
@@ -87,7 +87,7 @@ export const CATEGORY_LABELS: Record<(typeof SETTINGS_CATEGORIES)[number], strin
|
|
|
87
87
|
helper: 'Helper',
|
|
88
88
|
tts: 'TTS',
|
|
89
89
|
service: 'Service',
|
|
90
|
-
controlPlane: '
|
|
90
|
+
controlPlane: 'Runtime API',
|
|
91
91
|
httpListener: 'HTTP Listener',
|
|
92
92
|
web: 'Web',
|
|
93
93
|
batch: 'Batch',
|
|
@@ -123,18 +123,18 @@ export const SETTING_LABELS: Partial<Record<string, string>> = {
|
|
|
123
123
|
'helper.enabled': 'Helper Enabled',
|
|
124
124
|
'helper.globalProvider': 'Helper Provider',
|
|
125
125
|
'helper.globalModel': 'Helper Model',
|
|
126
|
-
//
|
|
127
|
-
'controlPlane.enabled': '
|
|
128
|
-
'controlPlane.hostMode': '
|
|
129
|
-
'controlPlane.host': '
|
|
130
|
-
'controlPlane.port': '
|
|
131
|
-
'controlPlane.baseUrl': '
|
|
132
|
-
'controlPlane.streamMode': '
|
|
133
|
-
'controlPlane.allowRemote': '
|
|
134
|
-
'controlPlane.trustProxy': '
|
|
135
|
-
'controlPlane.tls.mode': '
|
|
136
|
-
'controlPlane.tls.certFile': '
|
|
137
|
-
'controlPlane.tls.keyFile': '
|
|
126
|
+
// Runtime API
|
|
127
|
+
'controlPlane.enabled': 'Runtime API Enabled',
|
|
128
|
+
'controlPlane.hostMode': 'Runtime API Host Mode',
|
|
129
|
+
'controlPlane.host': 'Runtime API Host',
|
|
130
|
+
'controlPlane.port': 'Runtime API Port',
|
|
131
|
+
'controlPlane.baseUrl': 'Runtime API Base URL',
|
|
132
|
+
'controlPlane.streamMode': 'Runtime API Stream Mode',
|
|
133
|
+
'controlPlane.allowRemote': 'Runtime API Allow Remote',
|
|
134
|
+
'controlPlane.trustProxy': 'Runtime API Trust Proxy',
|
|
135
|
+
'controlPlane.tls.mode': 'Runtime API TLS Mode',
|
|
136
|
+
'controlPlane.tls.certFile': 'Runtime API TLS Cert',
|
|
137
|
+
'controlPlane.tls.keyFile': 'Runtime API TLS Key',
|
|
138
138
|
// HTTP Listener
|
|
139
139
|
'httpListener.hostMode': 'HTTP Host Mode',
|
|
140
140
|
'httpListener.host': 'HTTP Host',
|
|
@@ -154,7 +154,7 @@ export const SETTING_LABELS: Partial<Record<string, string>> = {
|
|
|
154
154
|
'surfaces.ntfy.topic': 'ntfy Default Delivery Topic',
|
|
155
155
|
'surfaces.ntfy.chatTopic': 'ntfy Chat Topic',
|
|
156
156
|
'surfaces.ntfy.agentTopic': 'ntfy Agent Topic',
|
|
157
|
-
'surfaces.ntfy.remoteTopic': 'ntfy
|
|
157
|
+
'surfaces.ntfy.remoteTopic': 'ntfy Runtime-Only Remote Topic',
|
|
158
158
|
'surfaces.ntfy.token': 'ntfy Token',
|
|
159
159
|
'surfaces.ntfy.defaultPriority': 'ntfy Default Priority',
|
|
160
160
|
};
|
|
@@ -35,7 +35,7 @@ const CATEGORY_INFO: Record<SettingsCategory, string> = {
|
|
|
35
35
|
helper: 'Helper model defaults used by helper subsystems when they do not use the main chat route.',
|
|
36
36
|
tts: 'Text-to-speech provider, voice, and optional spoken-turn LLM overrides.',
|
|
37
37
|
service: 'External GoodVibes runtime service posture. Agent shows these compatibility keys for inspection only and does not install, start, stop, restart, or autostart services.',
|
|
38
|
-
controlPlane: 'External GoodVibes runtime
|
|
38
|
+
controlPlane: 'External GoodVibes runtime API settings for local admin/API access. Agent connects to that runtime and does not mutate its bind posture.',
|
|
39
39
|
httpListener: 'External HTTP listener settings for webhook and integration ingress. Agent does not start or expose the listener.',
|
|
40
40
|
web: 'External browser surface settings. Agent does not own the web listener or network bind lifecycle.',
|
|
41
41
|
batch: 'Batch execution settings reported from the external GoodVibes runtime. Agent does not own remote queue provisioning.',
|
|
@@ -50,7 +50,7 @@ const CATEGORY_INFO: Record<SettingsCategory, string> = {
|
|
|
50
50
|
danger: 'High-impact runtime and listener switches. Agent renders host-owned switches read-only; use GoodVibes TUI or the owning host to change them.',
|
|
51
51
|
tools: 'Tool LLM and helper model routing. Empty provider/model values inherit the active chat route unless a specific helper/tool route is set.',
|
|
52
52
|
flags: 'Feature flags are SDK runtime gates. They are separate from normal config keys because they enable or disable staged runtime behavior.',
|
|
53
|
-
network: 'Read-only view of external GoodVibes runtime
|
|
53
|
+
network: 'Read-only view of external GoodVibes runtime API, HTTP listener, and browser web bind posture plus editable Agent network settings.',
|
|
54
54
|
};
|
|
55
55
|
|
|
56
56
|
const ENUM_VALUE_DESCRIPTIONS: Record<string, Record<string, string>> = {
|
|
@@ -75,9 +75,9 @@ const ENUM_VALUE_DESCRIPTIONS: Record<string, Record<string, string>> = {
|
|
|
75
75
|
plaintext_allowed: 'Allow plaintext fallback when secure storage is unavailable.',
|
|
76
76
|
},
|
|
77
77
|
'batch.mode': {
|
|
78
|
-
off: 'Keep
|
|
78
|
+
off: 'Keep runtime work on the immediate local path.',
|
|
79
79
|
explicit: 'Use batch only when callers explicitly request batch execution.',
|
|
80
|
-
'eligible-by-default': 'Allow eligible
|
|
80
|
+
'eligible-by-default': 'Allow eligible runtime work to use the batch path unless callers opt out.',
|
|
81
81
|
},
|
|
82
82
|
'controlPlane.hostMode': {
|
|
83
83
|
localhost: 'Bind only to this computer.',
|
package/src/runtime/bootstrap.ts
CHANGED
|
@@ -46,8 +46,8 @@ import { buildEnabledRoutinesPrompt } from '../agent/routine-registry.ts';
|
|
|
46
46
|
|
|
47
47
|
const GOODVIBES_AGENT_OPERATOR_POLICY = [
|
|
48
48
|
'## GoodVibes Agent Operator Policy',
|
|
49
|
-
'- Default to serial, proactive assistant work in the main conversation. Answer, inspect, summarize, remember useful non-secret facts, configure local Agent state, use read-only
|
|
50
|
-
'- GoodVibes Agent connects to an externally managed GoodVibes
|
|
49
|
+
'- Default to serial, proactive assistant work in the main conversation. Answer, inspect, summarize, remember useful non-secret facts, configure local Agent state, use read-only runtime/operator routes, and take safe non-destructive actions without spawning local agents or WRFC.',
|
|
50
|
+
'- GoodVibes Agent connects to an externally managed GoodVibes runtime host. Do not start, stop, restart, install, expose, or mutate runtime-host network/listener posture from Agent runtime.',
|
|
51
51
|
'- Use the `agent_local_registry` tool when a reusable persona, skill, or routine would improve future work. Keep those records local, non-secret, source/provenance tagged, and reviewable. Starting a routine means applying its steps in this same serial conversation, not creating a background job.',
|
|
52
52
|
'- WRFC is never the default Agent reasoning path. Do not create local WRFC chains for planning, research, operations, knowledge, memory, configuration, approvals, automation observability, or ordinary assistant work.',
|
|
53
53
|
'- GoodVibes Agent is not the coding TUI. Do not use the `agent` tool to spawn local Engineer, Reviewer, Tester, Verifier, or batch-spawn roots from Agent.',
|
|
@@ -332,8 +332,8 @@ export async function bootstrapRuntime(
|
|
|
332
332
|
port,
|
|
333
333
|
baseUrl: formatHostServiceBaseUrl(host, port),
|
|
334
334
|
reason: service === 'daemon'
|
|
335
|
-
? 'GoodVibes Agent connects to an externally managed GoodVibes
|
|
336
|
-
: 'GoodVibes Agent does not own
|
|
335
|
+
? 'GoodVibes Agent connects to an externally managed GoodVibes runtime host and does not start or restart it.'
|
|
336
|
+
: 'GoodVibes Agent does not own external listener lifecycle.',
|
|
337
337
|
};
|
|
338
338
|
};
|
|
339
339
|
|
|
@@ -373,7 +373,7 @@ export async function bootstrapRuntime(
|
|
|
373
373
|
daemonStatus: createExternalAgentServiceStatus('daemon'),
|
|
374
374
|
httpListenerStatus: createExternalAgentServiceStatus('httpListener'),
|
|
375
375
|
};
|
|
376
|
-
systemMessageRouter.high('[Startup] GoodVibes Agent does not start or restart
|
|
376
|
+
systemMessageRouter.high('[Startup] GoodVibes Agent does not start or restart runtime-host services. Start the GoodVibes runtime from its owner, then refresh status.');
|
|
377
377
|
requestRender();
|
|
378
378
|
return inspectExternalServices();
|
|
379
379
|
},
|
|
@@ -450,8 +450,8 @@ export async function bootstrapRuntime(
|
|
|
450
450
|
});
|
|
451
451
|
bootstrapUnsubs.push(() => mcpAutoReload.stop());
|
|
452
452
|
if (configManager.get('automation.enabled')) {
|
|
453
|
-
logger.warn('Local automation startup is disabled in GoodVibes Agent; use external
|
|
454
|
-
systemMessageRouter.low('[Startup] Local automation runners are disabled in GoodVibes Agent; use read-only automation observability or explicit external-
|
|
453
|
+
logger.warn('Local automation startup is disabled in GoodVibes Agent; use external runtime observability instead.');
|
|
454
|
+
systemMessageRouter.low('[Startup] Local automation runners are disabled in GoodVibes Agent; use read-only automation observability or explicit external-runtime actions.');
|
|
455
455
|
}
|
|
456
456
|
|
|
457
457
|
// ── Phase 12: Session:start lifecycle hook ─────────────────────────────
|
|
@@ -552,7 +552,7 @@ export async function bootstrapRuntime(
|
|
|
552
552
|
},
|
|
553
553
|
};
|
|
554
554
|
|
|
555
|
-
// ── Phase 12b: Operator
|
|
555
|
+
// ── Phase 12b: Operator intervention wiring (feature-gated) ──────────────
|
|
556
556
|
// Wire the OpsControlPlane into CommandContext when the feature flag is enabled.
|
|
557
557
|
// The store and task manager are created unconditionally so they reflect the
|
|
558
558
|
// real runtime state (tasks registered before the flag check are visible).
|