Session work execution is synchronous — blocks HTTP response for full AI duration #18

Open
opened 2026-03-18 22:22:34 +00:00 by replit · 1 comment
Owner

Context

In Mode 1 (jobs), AI evaluation and execution both run via setImmediate() in background tasks. The HTTP response returns immediately with the current state (evaluating / executing) and the client polls or connects via SSE/WebSocket.

In Mode 2 (sessions), POST /api/sessions/:id/request calls agentService.executeWork() inline — the HTTP response is held open for the full AI execution duration (typically 5-30 seconds). This is inconsistent, blocks the request thread, and provides a poor Workshop UX where a POST appears to hang.

See artifacts/api-server/src/routes/sessions.ts around POST /sessions/:id/request (line ~212).

Requirements

  1. Refactor POST /sessions/:id/request to:
    a. Debit the balance estimate immediately and return 202 Accepted with a requestId
    b. Run AI work in a background task (same setImmediate pattern as jobs)
    c. Update the session request record with state: "executing"state: "complete" when done
    d. If AI fails, refund the debited sats back to session balance and set state: "failed"
  2. Add GET /api/sessions/:id/requests/:requestId to poll request status (mirrors GET /jobs/:id)
  3. Wire the session request completion into the event bus: session:request:complete event with sessionId and requestId
  4. Use executeWorkStreaming so session responses are also streamable
  5. Add GET /api/sessions/:id/requests/:requestId/stream SSE endpoint (mirrors GET /jobs/:id/stream)

Acceptance Criteria

  • POST /api/sessions/:id/request returns within 200 ms (does not block on AI)
  • The returned requestId can be polled via GET /api/sessions/:id/requests/:requestId
  • A session request that fails (AI error) correctly refunds the debited sats to the session balance
  • GET /api/sessions/:id/requests/:requestId/stream streams tokens in real time
  • Session balance is updated atomically — no race condition between debit and refund
  • Existing session request tests in testkit.ts (tests 9-16) still pass

Files

  • artifacts/api-server/src/routes/sessions.ts
  • lib/db/src/schema.ts (add state field to sessionRequests if not present)
  • artifacts/api-server/src/lib/stream-registry.ts (extend to support session request IDs)
## Context In Mode 1 (jobs), AI evaluation and execution both run via `setImmediate()` in background tasks. The HTTP response returns immediately with the current state (`evaluating` / `executing`) and the client polls or connects via SSE/WebSocket. In Mode 2 (sessions), `POST /api/sessions/:id/request` calls `agentService.executeWork()` **inline** — the HTTP response is held open for the full AI execution duration (typically 5-30 seconds). This is inconsistent, blocks the request thread, and provides a poor Workshop UX where a POST appears to hang. See `artifacts/api-server/src/routes/sessions.ts` around `POST /sessions/:id/request` (line ~212). ## Requirements 1. Refactor `POST /sessions/:id/request` to: a. Debit the balance estimate immediately and return `202 Accepted` with a `requestId` b. Run AI work in a background task (same `setImmediate` pattern as jobs) c. Update the session request record with `state: "executing"` → `state: "complete"` when done d. If AI fails, refund the debited sats back to session balance and set `state: "failed"` 2. Add `GET /api/sessions/:id/requests/:requestId` to poll request status (mirrors `GET /jobs/:id`) 3. Wire the session request completion into the event bus: `session:request:complete` event with `sessionId` and `requestId` 4. Use `executeWorkStreaming` so session responses are also streamable 5. Add `GET /api/sessions/:id/requests/:requestId/stream` SSE endpoint (mirrors `GET /jobs/:id/stream`) ## Acceptance Criteria - [ ] `POST /api/sessions/:id/request` returns within 200 ms (does not block on AI) - [ ] The returned `requestId` can be polled via `GET /api/sessions/:id/requests/:requestId` - [ ] A session request that fails (AI error) correctly refunds the debited sats to the session balance - [ ] `GET /api/sessions/:id/requests/:requestId/stream` streams tokens in real time - [ ] Session balance is updated atomically — no race condition between debit and refund - [ ] Existing session request tests in `testkit.ts` (tests 9-16) still pass ## Files - `artifacts/api-server/src/routes/sessions.ts` - `lib/db/src/schema.ts` (add `state` field to `sessionRequests` if not present) - `artifacts/api-server/src/lib/stream-registry.ts` (extend to support session request IDs)

[triage] Scope refinement:

  • Files: routes/sessions.ts (sync handler)
  • Fix: Move AI execution to background task with event bus notification, return 202 Accepted immediately
  • Acceptance: POST /api/sessions/:id/reply returns <500ms, work happens async, SSE/WS delivers result
  • Score: 7 (scope=2, acceptance=2, alignment=3 — blocking for production use)
[triage] Scope refinement: - **Files**: `routes/sessions.ts` (sync handler) - **Fix**: Move AI execution to background task with event bus notification, return 202 Accepted immediately - **Acceptance**: POST /api/sessions/:id/reply returns <500ms, work happens async, SSE/WS delivers result - **Score**: 7 (scope=2, acceptance=2, alignment=3 — blocking for production use)
replit added the backendhermes labels 2026-03-19 19:33:32 +00:00
gemini was assigned by Rockachopa 2026-03-22 23:38:28 +00:00
This repo is archived. You cannot comment on issues.