- Add PiProcessManager.resume(sessionId, tht): reads provider/model/thinking
from tht.sessionShow() and calls spawnFor with those values
- Add POST /sessions/:id/resume route: calls mgr.resume then re-wires
bridge.onClientEvent → hub.publish
- Confirm venv PATH already present in real spawn (no change needed)
- Add e2e test: POST /sessions → SSE receives ui_request via pendingWidget
re-emit → POST /sessions/s1/response → 204 (all over real HTTP against
fake-pi-rpc)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Harness:
- preview_cmd FILE positional arg made optional; when omitted with --session,
path is derived via _session_sql_file (mirrors export_cmd) — fixes the
deferred Task-5 bug where the backend passed sessions/<id>/sql_final.sql
relative to harnessDir, which broke for workspace-dependent paths.
- New pytest: test_preview_session_no_file_resolves_sql_final
Backend:
- ThtRunner.sqlPreview: drop positional file arg; use --session only
- New routes/sql.ts: POST /sessions/:id/sql/preview + /export
- New routes/meta.ts: GET /workspaces (yaml scan) + GET /models (injectable
seam + graceful fallback to {models:[]})
- app.ts: register sqlRoutes + metaRoutes; add listModels to BuildAppDeps
- tht-runner.test.ts: add sqlPreview argv assertion (no file path)
- test/routes-sql-meta.test.ts: 9 tests (sql preview/export + meta routes)
Tests: harness 233 passed; backend 29 passed; build clean.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
POST /sessions no longer silently drops `workspace`. ThtRunner.run/json
take an optional workspace; configArg() selects workspaces/<ws>.yaml when
it exists under harnessDir, else falls back to default configPath.
sessionNew threads workspace through. Route forwards b.workspace with an
MVP note (gate/Pi side still single-workspace via symlinked config/tht.yaml).
19/19 tests pass, tsc clean.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Make buildApp injectable (deps.thtRunner + deps.spawnFn); create
src/routes/sessions.ts with all 7 session routes under authPreHandler;
wire bridge.onClientEvent→hub.publish before returning {id} from POST
/sessions; SSE subscribes with pendingWidget safety net.
18/18 tests pass, tsc clean.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Decodes native extension_ui_request (method:input, title=JSON) into
ui_request ClientEvent; encodes respond() as extension_ui_response with
value payload; tracks pending widget; handles notify→info and steer.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implement attachJsonlReader to split streams on \n only, handling
trailing \r, and reassembling lines split across chunk boundaries.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>