feat: add seq cursor, work_items, provider fallback, and delivery reliability

Major reliability improvements to the message processing pipeline:

- Add messages.seq monotonic cursor replacing timestamp-based cursors,
  preventing message loss from timestamp collisions with LIMIT queries
- Add work_items table separating agent production from delivery,
  enabling delivery retry without re-running the agent
- Propagate Discord send failures instead of silently swallowing them
- Add Claude 429 → Kimi K2.5 automatic provider fallback with cooldown
- Fix follow-up turn state reset in live index.ts path (not just
  message-runtime.ts) to prevent final output from being lost
- Add restart context tracking for graceful restart announcements
- Lazy migration from timestamp cursors to seq cursors for existing data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Eyejoker
2026-03-23 00:11:32 +09:00
parent dd15585941
commit b647502a10
19 changed files with 2782 additions and 209 deletions

View File

@@ -414,6 +414,30 @@ describe('GroupQueue', () => {
await vi.advanceTimersByTimeAsync(10);
});
it('sendMessage touches active run activity after piping follow-up', async () => {
let resolveProcess: () => void;
const touch = vi.fn();
const processMessages = vi.fn(async () => {
await new Promise<void>((resolve) => {
resolveProcess = resolve;
});
return true;
});
queue.setProcessMessagesFn(processMessages);
queue.enqueueMessageCheck('group1@g.us');
await vi.advanceTimersByTimeAsync(10);
queue.registerProcess('group1@g.us', {} as any, 'agent-1', 'test-group');
queue.setActivityTouch('group1@g.us', touch);
expect(queue.sendMessage('group1@g.us', 'hello')).toBe(true);
expect(touch).toHaveBeenCalledTimes(1);
resolveProcess!();
await vi.advanceTimersByTimeAsync(10);
});
it('sendMessage returns false for task agents so user messages queue up', async () => {
let resolveTask: () => void;