feat(gateway): complete openclaw phase1 queue parity v2

This commit is contained in:
William Valentin
2026-02-16 12:04:33 -08:00
parent 78da226542
commit 813a0dc5c5
19 changed files with 678 additions and 53 deletions
+45 -1
View File
@@ -1,6 +1,6 @@
import { describe, it, expect, vi } from 'vitest';
import { createElevateCommand, createModelCommand } from './index.js';
import { createElevateCommand, createModelCommand, createQueueCommand } from './index.js';
describe('builtin /model command', () => {
it('passes through the full argument string', async () => {
@@ -67,3 +67,47 @@ describe('builtin /elevate command', () => {
expect(result).toEqual({ handled: true, text: 'status' });
});
});
describe('builtin /queue command', () => {
it('shows queue status with no args', async () => {
const cmd = createQueueCommand();
const getQueue = vi.fn(() => 'queue status');
const result = await cmd.execute([], {
channel: 'test',
senderId: 'user',
sessionId: 's1',
rawInput: '/queue',
services: { getQueue },
});
expect(getQueue).toHaveBeenCalledOnce();
expect(result).toEqual({ handled: true, text: 'queue status' });
});
it('passes through set operations', async () => {
const cmd = createQueueCommand();
const setQueue = vi.fn(() => 'updated');
const result = await cmd.execute(['set', 'mode', 'followup'], {
channel: 'test',
senderId: 'user',
sessionId: 's1',
rawInput: '/queue set mode followup',
services: { setQueue },
});
expect(setQueue).toHaveBeenCalledWith('mode followup');
expect(result).toEqual({ handled: true, text: 'updated' });
});
it('calls reset operation', async () => {
const cmd = createQueueCommand();
const resetQueue = vi.fn(() => 'reset');
const result = await cmd.execute(['reset'], {
channel: 'test',
senderId: 'user',
sessionId: 's1',
rawInput: '/queue reset',
services: { resetQueue },
});
expect(resetQueue).toHaveBeenCalledOnce();
expect(result).toEqual({ handled: true, text: 'reset' });
});
});
+31
View File
@@ -149,6 +149,36 @@ export function createElevateCommand(): CommandDefinition {
};
}
export function createQueueCommand(): CommandDefinition {
return {
name: 'queue',
description: 'Inspect or update per-session queue policy',
execute: async (args, ctx) => {
if (args.length === 0 || args[0] === 'show') {
if (!ctx.services?.getQueue) {
return notAvailable('Queue command');
}
return { handled: true, text: await ctx.services.getQueue() };
}
const [action, ...rest] = args;
if (action === 'reset') {
if (!ctx.services?.resetQueue) {
return notAvailable('Queue command');
}
return { handled: true, text: await ctx.services.resetQueue() };
}
if (!ctx.services?.setQueue) {
return notAvailable('Queue command');
}
const input = action === 'set' ? rest.join(' ') : args.join(' ');
return { handled: true, text: await ctx.services.setQueue(input) };
},
};
}
export function registerBuiltinCommands(registry: CommandRegistry): void {
registry.register(createHelpCommand(registry));
registry.register(createStatusCommand());
@@ -157,4 +187,5 @@ export function registerBuiltinCommands(registry: CommandRegistry): void {
registry.register(createCompactCommand());
registry.register(createResetCommand());
registry.register(createElevateCommand());
registry.register(createQueueCommand());
}
+1
View File
@@ -7,5 +7,6 @@ export {
createModelCommand,
createCompactCommand,
createResetCommand,
createQueueCommand,
registerBuiltinCommands,
} from './builtin/index.js';
+4
View File
@@ -28,4 +28,8 @@ export interface CommandServices {
getElevation?: () => Promise<string> | string;
setElevation?: (input: string) => Promise<string> | string;
getQueue?: () => Promise<string> | string;
setQueue?: (input: string) => Promise<string> | string;
resetQueue?: () => Promise<string> | string;
}