feat: add session-scoped workflow approval gate commands
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
|
||||
import { createContextCommand, createElevateCommand, createModelCommand, createQueueCommand, createResearchCommand, createTransferCommand } from './index.js';
|
||||
import { createApproveCommand, createApprovalsCommand, createContextCommand, createDenyCommand, createElevateCommand, createModelCommand, createQueueCommand, createResearchCommand, createTransferCommand } from './index.js';
|
||||
|
||||
describe('builtin /model command', () => {
|
||||
it('passes through the full argument string', async () => {
|
||||
@@ -197,3 +197,47 @@ describe('builtin /transfer command', () => {
|
||||
expect(result).toEqual({ handled: true, text: 'Transfer command is not available in this session.' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('builtin approval commands', () => {
|
||||
it('calls getApprovals for /approvals', async () => {
|
||||
const cmd = createApprovalsCommand();
|
||||
const getApprovals = vi.fn(() => '1 pending');
|
||||
const result = await cmd.execute([], {
|
||||
channel: 'test',
|
||||
senderId: 'user',
|
||||
sessionId: 's1',
|
||||
rawInput: '/approvals',
|
||||
services: { getApprovals },
|
||||
});
|
||||
expect(getApprovals).toHaveBeenCalledOnce();
|
||||
expect(result).toEqual({ handled: true, text: '1 pending' });
|
||||
});
|
||||
|
||||
it('passes raw input to approvePending for /approve', async () => {
|
||||
const cmd = createApproveCommand();
|
||||
const approvePending = vi.fn(() => 'approved');
|
||||
const result = await cmd.execute(['abc-123'], {
|
||||
channel: 'test',
|
||||
senderId: 'user',
|
||||
sessionId: 's1',
|
||||
rawInput: '/approve abc-123',
|
||||
services: { approvePending },
|
||||
});
|
||||
expect(approvePending).toHaveBeenCalledWith('abc-123');
|
||||
expect(result).toEqual({ handled: true, text: 'approved' });
|
||||
});
|
||||
|
||||
it('passes raw input to denyPending for /deny', async () => {
|
||||
const cmd = createDenyCommand();
|
||||
const denyPending = vi.fn(() => 'denied');
|
||||
const result = await cmd.execute(['abc-123', 'too', 'risky'], {
|
||||
channel: 'test',
|
||||
senderId: 'user',
|
||||
sessionId: 's1',
|
||||
rawInput: '/deny abc-123 too risky',
|
||||
services: { denyPending },
|
||||
});
|
||||
expect(denyPending).toHaveBeenCalledWith('abc-123 too risky');
|
||||
expect(result).toEqual({ handled: true, text: 'denied' });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -236,6 +236,54 @@ export function createTransferCommand(): CommandDefinition {
|
||||
};
|
||||
}
|
||||
|
||||
export function createApprovalsCommand(): CommandDefinition {
|
||||
return {
|
||||
name: 'approvals',
|
||||
description: 'Show pending approval gates for this session',
|
||||
execute: async (_args, ctx) => {
|
||||
if (!ctx.services?.getApprovals) {
|
||||
return notAvailable('Approvals command');
|
||||
}
|
||||
return {
|
||||
handled: true,
|
||||
text: await ctx.services.getApprovals(),
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function createApproveCommand(): CommandDefinition {
|
||||
return {
|
||||
name: 'approve',
|
||||
description: 'Approve a pending gate (latest by default, or by id)',
|
||||
execute: async (args, ctx) => {
|
||||
if (!ctx.services?.approvePending) {
|
||||
return notAvailable('Approve command');
|
||||
}
|
||||
return {
|
||||
handled: true,
|
||||
text: await ctx.services.approvePending(args.join(' ').trim()),
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function createDenyCommand(): CommandDefinition {
|
||||
return {
|
||||
name: 'deny',
|
||||
description: 'Deny a pending gate (latest by default, optional id and reason)',
|
||||
execute: async (args, ctx) => {
|
||||
if (!ctx.services?.denyPending) {
|
||||
return notAvailable('Deny command');
|
||||
}
|
||||
return {
|
||||
handled: true,
|
||||
text: await ctx.services.denyPending(args.join(' ').trim()),
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function registerBuiltinCommands(registry: CommandRegistry): void {
|
||||
registry.register(createHelpCommand(registry));
|
||||
registry.register(createStatusCommand());
|
||||
@@ -248,4 +296,7 @@ export function registerBuiltinCommands(registry: CommandRegistry): void {
|
||||
registry.register(createElevateCommand());
|
||||
registry.register(createQueueCommand());
|
||||
registry.register(createTransferCommand());
|
||||
registry.register(createApprovalsCommand());
|
||||
registry.register(createApproveCommand());
|
||||
registry.register(createDenyCommand());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user