Commit Graph
68 Commits
Author SHA1 Message Date
marcopanandClaude Opus 4.8 f979ada5e7 feat(frontend): open a live session straight to its pending gate
Opening an in-progress session that has a live Pi runtime now reconnects to
its pending gate instead of the empty landing screen that read as "stopped".
Cold/completed sessions keep the read-only documents panel with its explicit
Resume, so a mere click never spawns a runtime. Backend GET /sessions now
reports a per-session `active` flag (live runtime bound) to drive this.

Also:
- "New session" now closes any open session detail panel (left box).
- The model-activity separator can be dragged to a full 50/50 split
  (was capped at 576px); central-min still guards narrow viewports.

Test fixes uncovered along the way:
- Node 25 ships an experimental global localStorage that shadows jsdom's and
  lacks clear(), failing every jsdom test at setup; install a spec-compliant
  in-memory Storage (feature-detected, inert on CI/LTS).
- Fix 4 pre-existing session-mgmt tests that used an ambiguous getByText for a
  session shown in both nav and header; target the nav item by test id.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 22:56:12 +02:00
marcopanandClaude Opus 4.8 c5fd03ed84 feat(backend): let pi self-authenticate providers from its own auth store
The backend injects a single managed model key (THT_MODEL_API_KEY[_FILE]) as
the selected provider's env var, but that key belongs to one provider — so
selecting a second cloud provider (e.g. DeepSeek while the managed key is zai's)
forced the wrong key onto it and failed auth. This is why the model could not be
switched to DeepSeek.

When the selected provider is present in pi's own auth store
(~/.pi/agent/auth.json), skip injection and let pi resolve that provider's key
itself. Deployments without an auth store (containers) yield an empty set, so the
managed-key injection stays authoritative and fail-fast there. authProviders is
injectable into PiProcessManager for deterministic tests.

Verified live: GLM 5.2, DeepSeek V4 Flash, and aritmolab Qwen3.6 all operate through the ThothII model selector.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 18:26:18 +02:00
User 5cacf70a0d fix: bootstrap user preferences without invalidating DWH cache 2026-07-16 20:32:20 +02:00
User ccb3cf4aa9 test: cover user-owned session security boundaries 2026-07-16 19:16:58 +02:00
User cadc4c6947 docs(deploy): document user-owned session cutover 2026-07-16 19:02:58 +02:00
User b454fb478b fix(backend): harden principal child isolation 2026-07-16 18:38:40 +02:00
User 458eb13c89 feat(backend): enforce user-owned sessions 2026-07-16 18:32:52 +02:00
User 0bcec1591b fix: close delete resume and SSE replay races 2026-07-15 02:08:11 +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 e0a97a01f3 feat(backend): expose sanitized tool activity 2026-07-14 22:46:22 +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 aba8666f16 fix(backend): track Pi turn lifecycle 2026-07-14 20:39:45 +02:00
User 0cf86e3540 fix(backend): allow configured local Qwen provider 2026-07-14 18:44:12 +02:00
User 3d23d0543c fix(backend): validate configured model provider pair 2026-07-14 18:39:37 +02:00
User c463de8da2 fix(backend): scope Pi model listing to enabled models 2026-07-14 18:33:15 +02:00
User 1b78f72b64 feat(backend): read Pi enabled model scope 2026-07-14 18:27:55 +02:00
User 333874a755 fix: make join approval atomic 2026-07-14 15:24:06 +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
marcopan 7628eaa579 fix(docker): run real questions through trusted Pi gate 2026-07-12 19:20:10 +02:00
marcopan 8518a73685 fix(security): scrub raw deployment secret values 2026-07-12 11:34:32 +02:00
marcopan d500563963 fix(security): scrub deployment secrets from Pi child 2026-07-12 11:33:13 +02:00
marcopan 3807c65a41 test(config): cover secret bundle inode races 2026-07-12 11:09:09 +02:00
marcopan 5fe74612fb feat(config): load one validated secret bundle 2026-07-12 11:06:19 +02:00
marcopan 2302286ea1 fix(backend): reject compound provider credentials 2026-07-12 08:10:47 +02:00
marcopan f064daef09 fix(backend): harden provider credential isolation 2026-07-12 08:05:51 +02:00
marcopan e40a9d9a56 fix(backend): inject provider credentials from file 2026-07-12 07:53:22 +02:00
marcopan a3a266fd81 fix(deploy): close container final review 2026-07-12 00:44:39 +02:00
marcopan 767df63a33 feat(deploy): add portable external-service stack 2026-07-11 22:12:21 +02:00
marcopan 3ac0623247 fix(backend): make data root config authoritative 2026-07-11 21:35:54 +02:00
marcopan c6c00c336a feat(backend): support container runtime paths 2026-07-11 21:32:33 +02:00
marcopanandClaude Fable 5 2410f01b34 fix(bridge): forward Pi agent_end so the spinner stops at workflow completion
The FE derived 'working' purely as activeSession && !pendingWidget, so the
final workflow turn — the only one that ends without a follow-up gate —
left the spinner on forever (observed live: 21592s after F8 approve).

- SessionBridge maps Pi's agent_end -> SSE system_event {event: agent_end}
- PiProcessManager notifies the client (info error + synthetic agent_end)
  when the child dies unexpectedly; expected teardowns stay silent
- sessionStore tracks agentActive (on: user entry/text_delta/ui_request,
  off: agent_end); AppShell working now requires it; resume sets it
  optimistically

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 10:14:43 +02:00
marcopanandMarco Pancotti ad5a4d938c test(backend): pin schema-linking structured response passthrough 2026-07-06 23:25:00 +02:00
marcopanandClaude Opus 4.8 418187a4ad fix(backend): echo Pi's RPC id so reviewer gates unblock after answer
ctx.ui.input in `pi --mode rpc` correlates extension_ui_response on its own
top-level RPC id (crypto.randomUUID), not the descriptor id the gate carries
in `title`. SessionBridge replied with the descriptor id, so Pi silently
dropped the response and the model never resumed — every reviewer widget hung
after the human answered.

SessionBridge now stores Pi's top-level m.id (pendingPiId) and replies
extension_ui_response{ id: pendingPiId, value: <uiResponse> }; value still
carries the descriptor id so the gate's internal resp.id === descriptor.id
check still holds.

The fake-pi double had masked the bug by forcing m.id == descriptor.id; it now
mirrors real Pi (distinct randomUUID, correlate on it, drop unknown ids), with
a negative regression test. SKILL.md Phase 1 also now steers multi-answer
disambiguation to reviewer_decide (multiselect).

Tests: backend 67/67, tsc clean, fake-pi contract 2/2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 10:43:49 +02:00
marcopanandClaude Opus 4.8 37d40d6680 fix(backend): drop pi --approve flag (removed in pi 0.73 @mariozechner rebrand)
pi 0.73 rpc mode is headless and runs tools without an approval gate; the
removed --approve flag made pi exit with 'Unknown option: --approve', breaking
every session spawn. Spawn args are now just --mode rpc. +regression test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 21:03:48 +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
marcopan a0af089d00 feat(backend): ThtRunner.ollamaEnsure (parses tht ollama ensure --json) 2026-06-29 19:31:49 +02:00
marcopan 790ac71284 feat(backend): spawnFor new/resume prompt mode; resume sends /riprendi-sessione 2026-06-29 12:38:26 +02:00
marcopan 387ae56583 test(backend): make mgr injectable; assert teardown-before-delete ordering 2026-06-29 12:36:29 +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
marcopan 4a63db51e8 feat(backend): ThtRunner session mutation + documents methods 2026-06-29 12:29:14 +02:00
marcopanandClaude Opus 4.8 f59d6d1478 fix(backend): allow PUT in CORS methods so browser can save settings
Found via live browser test: PUT /settings preflight was rejected because
@fastify/cors default methods omit PUT. GET/POST were unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 16:54:30 +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 098915515f fix(backend): deterministic /models fallback test + merge duplicate import
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 16:12:18 +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