Reference in New Issue
Block a user
Delete Branch "feat/workshop-api-enhancements"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Implements issues #2–#5 from the workshop API enhancement milestone, with bug fixes for #14 and #16 identified during review.
Changes
#5 — CORS (
app.ts)Added
corsmiddleware restricted toALLOWED_ORIGINSenv var (comma-separated). Falls back to*in development only.#3 — Rate limiting (
lib/rate-limiter.ts)Three limiters:
jobsLimiter(20 req/min),sessionsLimiter(10 req/min),bootstrapLimiter(3 req/15 min). Applied to POST endpoints injobs.tsandsessions.ts.#4 — Event bus (
lib/event-bus.ts)In-process
EventBussingleton (extendsEventEmitter) with typedBusEventdiscriminated union coveringjob:*andsession:*events.maxListenersset to 256.#2 — Streaming + SSE (
lib/stream-registry.ts,lib/agent.ts,routes/jobs.ts)StreamRegistry— PassThrough registry keyed by job IDexecuteWorkStreaming()onAgentService— streams Anthropic tokens viaonChunkcallbackrunWorkInBackground()injobs.ts— registers stream slot, callsexecuteWorkStreaming, writes chunks to registry, ends slot on completionGET /api/jobs/:id/stream— SSE endpoint that either attaches to live stream or waits up to 90 s for work payment confirmationBug fixes
Fix #14 — Stub mode for
executeWorkStreamingThe real Anthropic client throws at module load if
AI_INTEGRATIONS_ANTHROPIC_API_KEYis absent. AddedSTUB_MODEdetection and lazygetClient()via dynamic import so the server starts cleanly without credentials. StubexecuteWorkStreamingemits canned text word-by-word to exercise the SSE path end-to-end.Fix #16 — SSE race condition at timeout boundary
Previously, if the job completed while the SSE client was waiting on the bus listener, the stream slot was gone and the handler emitted
Stream not available. Fixed by refreshing both the stream registry and job DB state after the wait resolves. All resolution paths now handled: live stream, completed job (DB replay), failed job, and hard timeout.Pre-existing typecheck fixes (bonus)
event-bus.ts: EventEmitter overload implementation signature usedunknown[]instead ofany[]testkit.ts: bash variable${ELAPSED_T14}inside a TS template literal was not escapedTypecheck
Issues filed during review
#13 TypeScript quality gates (ESLint, pre-commit, CI)
#15 WebSocket server not yet wired
#17 Bore tunnel remote helper (
push-to-gitea.sh)#18 Session work execution is synchronous
#19
get-lnbits-key.shdeprecated LNbits APIClosing as stale. The features in this PR (streaming, rate limiting, event bus, SSE, CORS, ESLint, CI hooks) all landed on
mainthrough other routes — direct Hermes commits and subsequent PRs (#24, #25, #26) — before this PR could be reviewed. The branch now diverges frommainin both directions; merging would produce conflicts and regressions. No code is lost: every feature is present onmain. Deleting the branch and closing this PR to keep the tracker clean.