feat: add persisted manual pi backend mode controls

This commit is contained in:
William Valentin
2026-02-23 23:06:40 -08:00
parent 3e5e82c76e
commit 4188c68130
14 changed files with 360 additions and 10 deletions
+30 -1
View File
@@ -1,6 +1,6 @@
import { describe, it, expect, vi } from 'vitest';
import { createApproveCommand, createApprovalsCommand, createContextCommand, createCouncilCommand, createDenyCommand, createElevateCommand, createModelCommand, createQueueCommand, createResearchCommand, createSkillCommand, createStopCommand, createToolsCommand, createTransferCommand } from './index.js';
import { createApproveCommand, createApprovalsCommand, createBackendCommand, createContextCommand, createCouncilCommand, createDenyCommand, createElevateCommand, createModelCommand, createQueueCommand, createResearchCommand, createSkillCommand, createStopCommand, createToolsCommand, createTransferCommand } from './index.js';
describe('builtin /model command', () => {
it('passes through the full argument string', async () => {
@@ -341,3 +341,32 @@ describe('builtin /skill command', () => {
expect(result).toEqual({ handled: true, text: 'ok' });
});
});
describe('builtin /backend command', () => {
it('passes subcommand input to backendCommand service', async () => {
const cmd = createBackendCommand();
const backendCommand = vi.fn(() => 'Pi backend deactivated.');
const result = await cmd.execute(['deactivate', 'pi'], {
channel: 'test',
senderId: 'user',
sessionId: 's1',
rawInput: '/backend deactivate pi',
services: { backendCommand },
});
expect(backendCommand).toHaveBeenCalledWith('deactivate pi');
expect(result).toEqual({ handled: true, text: 'Pi backend deactivated.' });
});
it('returns not-available when service is missing', async () => {
const cmd = createBackendCommand();
const result = await cmd.execute([], {
channel: 'test',
senderId: 'user',
sessionId: 's1',
rawInput: '/backend',
services: {},
});
expect(result).toEqual({ handled: true, text: 'Backend command is not available in this session.' });
});
});
+17
View File
@@ -356,6 +356,22 @@ export function createSkillCommand(): CommandDefinition {
};
}
export function createBackendCommand(): CommandDefinition {
return {
name: 'backend',
description: 'Inspect or control runtime backend mode (status, activate pi, deactivate pi)',
execute: async (args, ctx) => {
if (!ctx.services?.backendCommand) {
return notAvailable('Backend command');
}
return {
handled: true,
text: await ctx.services.backendCommand(args.join(' ').trim()),
};
},
};
}
export function registerBuiltinCommands(registry: CommandRegistry): void {
registry.register(createHelpCommand(registry));
registry.register(createStatusCommand());
@@ -375,4 +391,5 @@ export function registerBuiltinCommands(registry: CommandRegistry): void {
registry.register(createApproveCommand());
registry.register(createDenyCommand());
registry.register(createSkillCommand());
registry.register(createBackendCommand());
}
+1
View File
@@ -16,5 +16,6 @@ export {
createApproveCommand,
createDenyCommand,
createSkillCommand,
createBackendCommand,
registerBuiltinCommands,
} from './builtin/index.js';
+1
View File
@@ -42,4 +42,5 @@ export interface CommandServices {
approvePending?: (input: string) => Promise<string> | string;
denyPending?: (input: string) => Promise<string> | string;
skillCommand?: (input: string) => Promise<string> | string;
backendCommand?: (input: string) => Promise<string> | string;
}