HTTP routes
Generated from the route constants and dispatcher in packages/web/src/server/index.ts, with handler contracts from server/follow.ts, server/bundle-route.ts, and server/logs-route.ts.
Every /api/threads/:threadId… route also reads the X-Enso-Project header (#395): a page names a new thread’s project with it, and an id that is no registered project is a 400 before the route runs.
Parser limitation: discovery recognizes top-level
const *_ROUTE = /…/declarations plus directrequest.methodbranches usingurl === …orurl.startsWith(…). Statuses, input shapes, classes, acquisition, and self-logging are intentionally explicit checked metadata rather than inferred behavior.
| Method | Rendered path | Handler / factory | Input shape | Success | Named error statuses | Class | Builds / acquires? | Logs itself? | Source |
|---|---|---|---|---|---|---|---|---|---|
| GET | /api/about |
createAboutRoute → about |
none | 200 EnsoBundleAbout JSON |
403 untrusted origin | observation | no | no | packages/web/src/server/index.ts:1129packages/web/src/server/bundle-route.ts:169 |
| POST | /api/logs |
respondToBrowserLogs → receiveBrowserLogs |
body: EnsoBrowserLogBatch |
204 empty | 400 malformed batch; 403 untrusted origin; 413 body too large; 500 body-read failure | browser-log-ingest | no | no | packages/web/src/server/index.ts:1151packages/web/src/server/logs-route.ts:29 |
| GET | /api/logs/bundle* |
createBundleRoute → bundle |
query: optional thread id/prefix |
200 Markdown attachment | 400 malformed thread filter; 403 untrusted origin | observation | no | no | packages/web/src/server/index.ts:1136packages/web/src/server/bundle-route.ts:98 |
| GET | /api/logs/stats |
createLogStatsRoute → stats |
none | 200 EnsoDayStats JSON |
403 untrusted origin | observation | no | no | packages/web/src/server/index.ts:1145packages/web/src/server/logs-stats-route.ts:62 |
| GET | /api/logs/tail* |
followLogTail |
query: optional level, thread id/prefix, process, since duration, from byte offset with the day it belongs to |
200 SSE stream of EnsoLogTailFrame; a read the server cannot do ends it with an error event |
400 unknown level, malformed thread filter, malformed since or from; 403 untrusted origin | observation | no | no | packages/web/src/server/index.ts:1140packages/web/src/server/logs-tail-route.ts:152 |
| GET | /api/mode |
respondWithFreshThreadMode |
none | 200 permission-mode JSON | 403 untrusted origin | static | no | no | packages/web/src/server/index.ts:1117 |
| GET | /api/projects |
respondWithProjects |
none | 200 EnsoProject[] JSON — the launch project first, then the registered ones |
403 untrusted origin | observation | no | no | packages/web/src/server/index.ts:1042 |
| POST | /api/projects |
respondToProjectRegistration → ProjectRegistry.register |
body: EnsoProjectRegistration — an absolute path strictly under a root enso.config.json declares (projects.roots), optional title |
201 EnsoProject JSON when registered; 200 when the directory already is a project |
400 malformed body; 403 untrusted origin; 413 body too large; 422 refused, with the reason — not absolute, missing, not a directory, a root itself, outside every root (resolved through symlinks), or inside a hidden directory; 500 handler failure | control | no | yes | packages/web/src/server/index.ts:1046 |
| DELETE | /api/projects/:projectId |
respondToProjectRemoval → ProjectRegistry.remove |
path: projectId (sixteen hex digits) |
204 empty — the registration is forgotten; its sessions stay on disk and are served again if the directory is registered again | 403 untrusted origin; 404 no registered project with that id; 409 the launch project, or a thread in the project is running | control | no | yes | packages/web/src/server/index.ts:79 |
| GET | /api/projects/browse* |
respondWithBrowse → ProjectRegistry.browse |
query: optional path — a directory inside a declared root; absent, the roots themselves |
200 EnsoDirectoryListing JSON — the directories under it that are inside a root and not hidden (symlinks resolved), which already are projects, and whether this one may be added |
403 untrusted origin; 422 refused, with the reason — not absolute, missing, not a directory, outside every root, or inside a hidden directory | observation | no | no | packages/web/src/server/index.ts:1050 |
| GET | /api/stored-threads |
respondWithStoredThreads |
none | 200 EnsoStoredThread[] JSON |
403 untrusted origin; 500 handler failure | observation | no | no | packages/web/src/server/index.ts:1125 |
| GET | /api/threads |
respondWithThreads |
none | 200 EnsoThreadSummary[] JSON |
403 untrusted origin | observation | no | no | packages/web/src/server/index.ts:1121 |
| GET | /api/threads/:threadId |
respondWithThread |
path: threadId |
200 JSON | 400 malformed thread id; 403 untrusted origin; 404 no live session | observation | no | no | packages/web/src/server/index.ts:54 |
| POST | /api/threads/:threadId/abort |
respondToAbort → abortThread |
path: threadId; no body |
200 EnsoAbortReceipt JSON |
400 malformed thread id; 403 untrusted origin; 404 no live session; 409 nothing running | control | no | yes | packages/web/src/server/index.ts:71packages/web/src/server/follow.ts:668 |
| POST | /api/threads/:threadId/command |
respondToHostCommand → runHostCommand |
path: threadId; body: EnsoHostCommandRun — model with provider/id, thinking with a level, login with provider/authType, logout with a provider, compact with nothing; a view row (context) is the page’s to open, never run |
204 empty for a setting (the change arrives on the follow as model); 202 empty for a flow or action (login, logout, compact) — started, its questions and progress arrive on the follow as dialogs and notify lines |
400 malformed id/body; 403 untrusted origin; 409 thread busy; 413 body too large; 422 unknown command, model or level, a provider without credentials, or a view (/context) the page opens itself; 500 handler failure |
control | yes | yes | packages/web/src/server/index.ts:75 |
| GET | /api/threads/:threadId/commands |
respondWithThreadCommands |
path: threadId |
200 EnsoThreadCommands JSON — source says live, remembered or none |
400 malformed thread id; 403 untrusted origin | observation | no | no | packages/web/src/server/index.ts:60 |
| POST | /api/threads/:threadId/configure |
respondToConfigure → configureThread |
path: threadId; body: EnsoSessionConfiguration — optional model (provider/id), thinking (a level that model supports) and mode; applied in that order under one lease, a value equal to the current one left alone |
204 empty — every step applied (the changes arrive on the follow as model and permission-mode) |
400 malformed id/body; 403 untrusted origin; 409 thread busy; 413 body too large; 422 JSON EnsoConfigurationRefusal — the step that refused (model, thinking, mode) and the reason, the steps before it applied; 500 handler failure |
control | yes | yes | packages/web/src/server/index.ts:77 |
| GET | /api/threads/:threadId/context |
respondWithThreadContext |
path: threadId |
200 EnsoThreadContext JSON — pi’s branch, request by request, and its context meter |
400 malformed thread id; 403 untrusted origin; 404 no session; 500 handler failure | observation | no | no | packages/web/src/server/index.ts:64 |
| GET | /api/threads/:threadId/context/:request |
respondWithContextRequest |
path: threadId, request (a turn number or next) |
200 EnsoContextRequestDetail JSON — one request’s context, element by element |
400 malformed thread id; 403 untrusted origin; 404 no session or no such turn; 500 handler failure | observation | no | no | packages/web/src/server/index.ts:66 |
| POST | /api/threads/:threadId/dialog |
respondToDialog → answerThreadDialog |
path: threadId; body: DialogAnswer |
204 empty | 400 malformed id/body; 403 untrusted origin; 404 no live question; 413 body too large; 422 answer refused; 500 handler failure | control | no | yes | packages/web/src/server/index.ts:70packages/web/src/server/follow.ts:363 |
| GET | /api/threads/:threadId/events |
respondWithThreadEvents |
path: threadId |
200 EnsoThreadEvents JSON |
400 malformed thread id; 403 untrusted origin; 404 no live session | observation | no | no | packages/web/src/server/index.ts:56 |
| GET | /api/threads/:threadId/follow |
followThread |
path: threadId |
200 SSE stream | 400 malformed thread id; 403 untrusted origin; 500 handler failure | observation | no | no | packages/web/src/server/index.ts:68packages/web/src/server/follow.ts:166 |
| GET | /api/threads/:threadId/history |
respondWithThreadHistory |
path: threadId |
200 EnsoThreadHistory JSON |
400 malformed thread id; 403 untrusted origin; 404 no session; 500 handler failure | observation | no | no | packages/web/src/server/index.ts:58 |
| POST | /api/threads/:threadId/mode |
respondToModeChange → changeThreadMode |
path: threadId; body: EnsoPermissionModeChange |
204 empty; the change arrives on the follow as permission-mode |
400 malformed id/body; 403 untrusted origin; 409 thread busy; 413 body too large; 422 mode not offered; 500 handler failure | control | yes | yes | packages/web/src/server/index.ts:73packages/web/src/server/follow.ts:399 |
| POST | /api/threads/:threadId/prompt |
respondToPrompt → promptThread |
path: threadId; body: EnsoPromptBody |
202 EnsoPromptReceipt JSON |
400 malformed id/body or unavailable command; 403 untrusted origin; 413 body too large; 500 handler failure | control | yes | yes | packages/web/src/server/index.ts:69packages/web/src/server/follow.ts:265 |
| GET | /api/threads/:threadId/stats |
respondWithThreadStats |
path: threadId |
200 EnsoThreadStats JSON — pi’s session for the numbers, the log’s day files for the times |
400 malformed thread id; 403 untrusted origin; 404 no session; 500 handler failure | observation | no | no | packages/web/src/server/index.ts:62 |
Detected 15 regex route constants and 11 literal dispatcher routes; metadata is exhaustive for both sets.