Commit Graph
23 Commits
Author SHA1 Message Date
User 458eb13c89 feat(backend): enforce user-owned sessions 2026-07-16 18:32:52 +02:00
User 6747f6f8a0 fix: serialize session lifecycle transitions 2026-07-15 01:37:42 +02:00
User 08b1f4909e fix: make session resume atomic across restarts 2026-07-15 00:42:35 +02:00
User 2b4797f133 fix: harden resume and SSE replay 2026-07-15 00:06:00 +02:00
User d2d8029ff2 fix(security): sanitize session bootstrap failures 2026-07-14 23:13:21 +02:00
User df1e7dea9c fix(resume): recover cleanly after Pi exits 2026-07-14 21:35:50 +02:00
User b1d1284cc8 fix(backend): restart idle Pi sessions on resume 2026-07-14 20:44:59 +02:00
User 3d23d0543c fix(backend): validate configured model provider pair 2026-07-14 18:39:37 +02:00
User c7474f3852 fix: restore model activity reasoning stream 2026-07-14 15:03:07 +02:00
User 6dbf93fff9 feat: harden runtime readiness and session workflow 2026-07-14 10:27:25 +02:00
User dfe2774a1a fix(sse): buffer session events for late subscribers + clear on close
The Pi process produces events immediately after session creation, but
the browser's SSE connection may not be open yet (React re-render delay,
navigation). The hub discarded events with no subscribers, so the user
saw a blank session.

- Ring-buffer up to 200 events per session; replay on subscribe
- hub.clear(id) on POST /sessions/:id/close frees memory
2026-07-13 00:01:11 +02:00
marcopan 7628eaa579 fix(docker): run real questions through trusted Pi gate 2026-07-12 19:20:10 +02:00
marcopan 767df63a33 feat(deploy): add portable external-service stack 2026-07-11 22:12:21 +02:00
marcopan a791919925 fix(backend): check read-only 409 before the Ollama preflight on resume 2026-06-29 20:06:03 +02:00
marcopanandClaude Sonnet 4.6 90a26dafce feat(backend): Ollama embeddings preflight on session create/resume (503 hard-fail)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 19:37:39 +02:00
marcopanandClaude Opus 4.8 bd29ac517c feat(backend): rename/group/archive/unarchive/delete/documents routes + resume read-only guard
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 12:32:52 +02:00
marcopanandClaude Opus 4.8 ec36ee421a feat(backend): POST /sessions applies global settings, body is question-only
workspace/provider/model/thinking now come from getSettings() injected into
sessionRoutes; the request body supplies only question+name. Also teaches
fake_pi_rpc to respond to set_model and set_thinking_level RPC commands so
tests that pass real model settings don't hang.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 16:16:08 +02:00
marcopanandClaude Opus 4.8 bfbb017413 feat(backend): /settings GET+PUT, /models PiModel shape, app wiring
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 16:09:04 +02:00
marcopanandClaude Sonnet 4.6 1171181f9a test(frontend): Playwright e2e F1 vs backend+fake-pi (hermetic)
Adds a real-browser Playwright e2e of the full F1 disambiguation loop,
driven against the real backend + fake binaries (no VPN, no real Pi, no Python).

- frontend/e2e/fixtures/fake-tht.mjs: stubs tht CLI (session new/list/show)
- frontend/e2e/fixtures/fake-pi.mjs: wraps harness fake-pi-rpc with f1_disambiguation.json
- frontend/playwright.config.ts: two webServer entries (backend:8799, frontend:5199)
- frontend/e2e/f1.spec.ts: open app → create session → wait for SelectWidget → respond

Bug fixes discovered during e2e:
- useSessionStream: add addEventListener for named SSE events (backend sends
  'event: ui_request' etc.; onmessage only fires for unnamed 'event: message')
- FakeEventSource: add no-op addEventListener/removeEventListener stubs
- backend SSE route: add CORS headers manually in writeHead() since
  reply.raw bypasses the @fastify/cors onSend hook
- backend: install and register @fastify/cors for all non-SSE routes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 13:27:00 +02:00
marcopanandClaude Sonnet 4.6 b16c94e30b feat(backend): resume + venv PATH + end-to-end F1 smoke (fake-pi-rpc)
- 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>
2026-06-27 21:37:24 +02:00
marcopanandClaude Sonnet 4.6 d630cac3ab feat(task-10): SQL routes + /workspaces + /models + fix sql preview path bug
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>
2026-06-27 21:31:35 +02:00
marcopanandClaude Sonnet 4.6 061002f85c fix(backend): forward workspace to tht config selection (MVP backend-side)
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>
2026-06-27 21:26:09 +02:00
marcopanandClaude Sonnet 4.6 b4b26e313b feat(backend): session routes + SSE + response/steer wiring
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>
2026-06-27 21:19:19 +02:00