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
+11 -3
View File
@@ -80,6 +80,8 @@ describe('configSchema — server', () => {
expect(result.server.queue.mode).toBe('collect');
expect(result.server.queue.cap).toBe(50);
expect(result.server.queue.overflow).toBe('drop_old');
expect(result.server.queue.debounce_ms).toBe(0);
expect(result.server.queue.summarize_overflow).toBe(true);
expect(result.server.queue.overrides.channels).toEqual({});
expect(result.server.queue.overrides.sessions).toEqual({});
});
@@ -89,15 +91,19 @@ describe('configSchema — server', () => {
...minimalConfig,
server: {
queue: {
mode: 'steer',
mode: 'steer_backlog',
cap: 10,
overflow: 'drop_new',
debounce_ms: 250,
summarize_overflow: false,
},
},
});
expect(result.server.queue.mode).toBe('steer');
expect(result.server.queue.mode).toBe('steer_backlog');
expect(result.server.queue.cap).toBe(10);
expect(result.server.queue.overflow).toBe('drop_new');
expect(result.server.queue.debounce_ms).toBe(250);
expect(result.server.queue.summarize_overflow).toBe(false);
});
it('accepts queue override settings', () => {
@@ -110,7 +116,7 @@ describe('configSchema — server', () => {
ws: { mode: 'collect', cap: 5 },
},
sessions: {
'ws:vip-user': { mode: 'interrupt', overflow: 'drop_new' },
'ws:vip-user': { mode: 'interrupt', overflow: 'drop_new', debounce_ms: 1000, summarize_overflow: false },
},
},
},
@@ -120,6 +126,8 @@ describe('configSchema — server', () => {
expect(result.server.queue.overrides.channels.ws.cap).toBe(5);
expect(result.server.queue.overrides.sessions['ws:vip-user'].mode).toBe('interrupt');
expect(result.server.queue.overrides.sessions['ws:vip-user'].overflow).toBe('drop_new');
expect(result.server.queue.overrides.sessions['ws:vip-user'].debounce_ms).toBe(1000);
expect(result.server.queue.overrides.sessions['ws:vip-user'].summarize_overflow).toBe(false);
});
it('defaults discovery settings', () => {
+11 -3
View File
@@ -34,27 +34,35 @@ const wsRateLimitSchema = z.object({
const laneQueueSchema = z.object({
/** Queue behavior for concurrent requests in the same session lane. */
mode: z.enum(['collect', 'steer', 'interrupt']).default('collect'),
mode: z.enum(['collect', 'followup', 'steer', 'steer_backlog', 'interrupt']).default('collect'),
/** Max queued (pending) requests per lane. */
cap: z.number().min(1).max(1000).default(50),
/** Overflow strategy when cap is reached. */
overflow: z.enum(['drop_old', 'drop_new']).default('drop_old'),
/** Debounce window before starting next queued request (ms). */
debounce_ms: z.number().min(0).max(60_000).default(0),
/** Include contextual summary details in overflow rejections. */
summarize_overflow: z.boolean().default(true),
/** Optional per-channel/per-session queue policy overrides. */
overrides: z.object({
channels: z.record(
z.string(),
z.object({
mode: z.enum(['collect', 'steer', 'interrupt']).optional(),
mode: z.enum(['collect', 'followup', 'steer', 'steer_backlog', 'interrupt']).optional(),
cap: z.number().min(1).max(1000).optional(),
overflow: z.enum(['drop_old', 'drop_new']).optional(),
debounce_ms: z.number().min(0).max(60_000).optional(),
summarize_overflow: z.boolean().optional(),
}),
).default({}),
sessions: z.record(
z.string(),
z.object({
mode: z.enum(['collect', 'steer', 'interrupt']).optional(),
mode: z.enum(['collect', 'followup', 'steer', 'steer_backlog', 'interrupt']).optional(),
cap: z.number().min(1).max(1000).optional(),
overflow: z.enum(['drop_old', 'drop_new']).optional(),
debounce_ms: z.number().min(0).max(60_000).optional(),
summarize_overflow: z.boolean().optional(),
}),
).default({}),
}).default({}),