feat(setup): surface operator-pack status and add operations runbook
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import type { Prompter } from './prompts.js';
|
||||
import type { ConfigBuilder } from './config.js';
|
||||
import { renderSummary } from './summary.js';
|
||||
import { renderOperatorPackStatus, renderSummary } from './summary.js';
|
||||
import { setupProviders } from './providers.js';
|
||||
import { setupChannels } from './channels.js';
|
||||
import { setupMemory } from './memory.js';
|
||||
@@ -28,9 +28,11 @@ const SECTION_HANDLERS: Record<string, (p: Prompter, b: ConfigBuilder) => Promis
|
||||
|
||||
export async function runMenu(p: Prompter, builder: ConfigBuilder): Promise<void> {
|
||||
while (true) {
|
||||
const config = builder.build();
|
||||
p.println();
|
||||
p.println('Flynn Setup — Current Configuration');
|
||||
p.println(renderSummary(builder.build()));
|
||||
p.println(renderSummary(config));
|
||||
p.println(` ${renderOperatorPackStatus(config)}`);
|
||||
p.println();
|
||||
p.println('What would you like to configure?');
|
||||
for (let i = 0; i < MENU_OPTIONS.length; i++) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { renderSummary } from './summary.js';
|
||||
import { renderOperatorPackStatus, renderSummary } from './summary.js';
|
||||
import type { SetupConfig } from './config.js';
|
||||
|
||||
describe('renderSummary', () => {
|
||||
@@ -24,4 +24,43 @@ describe('renderSummary', () => {
|
||||
expect(output).toContain('Automation: heartbeat, daily-briefing, minio-sync');
|
||||
expect(output).toContain('Backup: enabled (cron 0 2 * * *)');
|
||||
});
|
||||
|
||||
it('renders compact operator pack status line with routing when enabled', () => {
|
||||
const config = {
|
||||
models: {
|
||||
default: { provider: 'anthropic', model: 'claude-sonnet' },
|
||||
},
|
||||
server: { port: 18800, localhost: true },
|
||||
automation: {
|
||||
heartbeat: {
|
||||
enabled: true,
|
||||
notify: { channel: 'telegram', peer: '123' },
|
||||
},
|
||||
daily_briefing: { enabled: true },
|
||||
},
|
||||
backup: {
|
||||
enabled: true,
|
||||
notify: { channel: 'telegram', peer: '123' },
|
||||
},
|
||||
} as unknown as SetupConfig;
|
||||
|
||||
expect(renderOperatorPackStatus(config)).toBe('Operator Pack: enabled (telegram/123)');
|
||||
});
|
||||
|
||||
it('renders compact operator pack status line as disabled when partial config', () => {
|
||||
const config = {
|
||||
models: {
|
||||
default: { provider: 'anthropic', model: 'claude-sonnet' },
|
||||
},
|
||||
server: { port: 18800, localhost: true },
|
||||
automation: {
|
||||
heartbeat: { enabled: true },
|
||||
},
|
||||
backup: {
|
||||
enabled: true,
|
||||
},
|
||||
} as unknown as SetupConfig;
|
||||
|
||||
expect(renderOperatorPackStatus(config)).toBe('Operator Pack: disabled');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
import type { SetupConfig } from './config.js';
|
||||
|
||||
export function renderOperatorPackStatus(config: SetupConfig): string {
|
||||
const automation = config.automation ?? {};
|
||||
const backup = config.backup;
|
||||
const enabled = Boolean(
|
||||
backup?.enabled
|
||||
&& automation.heartbeat?.enabled
|
||||
&& automation.daily_briefing?.enabled,
|
||||
);
|
||||
|
||||
if (!enabled) {
|
||||
return 'Operator Pack: disabled';
|
||||
}
|
||||
|
||||
const notify = backup?.notify ?? (automation.heartbeat as { notify?: { channel?: string; peer?: string } } | undefined)?.notify;
|
||||
if (notify?.channel && notify?.peer) {
|
||||
return `Operator Pack: enabled (${notify.channel}/${notify.peer})`;
|
||||
}
|
||||
|
||||
return 'Operator Pack: enabled';
|
||||
}
|
||||
|
||||
export function renderSummary(config: SetupConfig): string {
|
||||
const lines: string[] = [];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user