diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 862b2686..87d4d05d 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -17,8 +17,8 @@ ### Cloud Providers -- [ ] **CLOUD-01**: User gets working AI via Puter.js with zero API keys and no sign-up required -- [ ] **CLOUD-02**: Puter.js integrated as server-proxied adapter (not browser-direct) with full cost tracking +- [x] **CLOUD-01**: User gets working AI via Puter.js with zero API keys and no sign-up required +- [x] **CLOUD-02**: Puter.js integrated as server-proxied adapter (not browser-direct) with full cost tracking - [ ] **CLOUD-03**: User can sign in via Google OAuth to access Gemini free tier - [ ] **CLOUD-04**: System auto-detects installed tools (Hermes, Claude Code, OpenClaw) and pre-fills configuration - [ ] **CLOUD-05**: User can enter API keys for subscription providers during onboarding @@ -73,8 +73,8 @@ | ONBD-02 | Phase 30 | Complete | | ONBD-03 | Phase 30 | Complete | | ONBD-07 | Phase 30 | Complete | -| CLOUD-01 | Phase 31 | Pending | -| CLOUD-02 | Phase 31 | Pending | +| CLOUD-01 | Phase 31 | Complete | +| CLOUD-02 | Phase 31 | Complete | | CLOUD-03 | Phase 31 | Pending | | CLOUD-04 | Phase 31 | Pending | | CLOUD-05 | Phase 31 | Pending | diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 1f07f86a..2fb03352 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -127,8 +127,8 @@ Plans: **Plans**: 4 plans Plans: -- [ ] 31-01-PLAN.md — Puter proxy service, routes, unit tests, and app.ts wiring -- [ ] 31-02-PLAN.md — Google OAuth PKCE service, routes, API key storage route +- [x] 31-01-PLAN.md — Puter proxy service, routes, unit tests, and app.ts wiring +- [x] 31-02-PLAN.md — Google OAuth PKCE service, routes, API key storage route - [ ] 31-03-PLAN.md — Provider Selection UI step, PuterAuthButton, GoogleOAuthButton, ApiKeyEntryForm, 4-step wizard wiring - [ ] 31-04-PLAN.md — Google OAuth claim endpoint, human verification of full onboarding flow **UI hint**: yes @@ -222,7 +222,7 @@ All 21 v1.5 requirements are mapped to exactly one phase. No orphans. | 28. Ollama Integration & Agent Surface | v1.4 | 3/3 | Complete | 2026-04-02 | | 29. Default Provider & End-to-End | v1.4 | 2/2 | Complete | 2026-04-02 | | 30. Hardware Detection + Mode Selection | v1.5 | 2/2 | Complete | 2026-04-03 | -| 31. Puter.js Zero-Config Cloud | v1.5 | 0/4 | Not started | - | +| 31. Puter.js Zero-Config Cloud | v1.5 | 2/4 | In Progress| | | 32. Multi-Step Onboarding Wizard | v1.5 | 0/TBD | Not started | - | | 33. Persistent Memory + Personal Assistant Mode | v1.5 | 0/TBD | Not started | - | | 34. Voice | v1.5 | 0/TBD | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index cefcdf7e..97630301 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -2,15 +2,15 @@ gsd_state_version: 1.0 milestone: v1.5 milestone_name: Smart Onboarding + Personal AI Assistant -status: verifying -stopped_at: Completed 30-hardware-detection-mode-selection/30-02 (all 3 tasks, human-verify approved) -last_updated: "2026-04-03T00:00:09.253Z" +status: executing +stopped_at: Completed 31-puter.js-zero-config-cloud/31-01 +last_updated: "2026-04-03T00:37:39.937Z" last_activity: 2026-04-03 progress: total_phases: 6 completed_phases: 1 - total_plans: 2 - completed_plans: 2 + total_plans: 6 + completed_plans: 4 percent: 0 --- @@ -21,13 +21,13 @@ progress: See: .planning/PROJECT.md (updated 2026-04-02) **Core value:** A fresh onboard asks for ONE thing (root directory), auto-creates PM + Engineer agents, and drops you in the dashboard. -**Current focus:** Phase 30 — hardware-detection-mode-selection +**Current focus:** Phase 31 — puter.js-zero-config-cloud ## Current Position -Phase: 31 -Plan: Not started -Status: Phase complete — human verification approved 2026-04-02 +Phase: 31 (puter.js-zero-config-cloud) — EXECUTING +Plan: 3 of 4 +Status: Ready to execute Last activity: 2026-04-03 Progress: [__________] 0% @@ -54,6 +54,8 @@ Progress: [__________] 0% *Updated after each plan completion* | Phase 30-hardware-detection-mode-selection P01 | 15 | 2 tasks | 8 files | | Phase 30-hardware-detection-mode-selection P02 | 15 | 2 tasks | 6 files | +| Phase 31-puter.js-zero-config-cloud P01 | 4 | 2 tasks | 4 files | +| Phase 31-puter.js-zero-config-cloud P02 | 202 | 3 tasks | 4 files | ## Accumulated Context @@ -73,6 +75,7 @@ Key constraints for v1.5 (established at roadmap): - [Phase 30-hardware-detection-mode-selection]: Hardware routes mounted before api Router to bypass boardMutationGuard; Apple Silicon detection via process.platform + cpuModel.startsWith('Apple') without calling si.graphics(); Promise.race 3s timeout on GPU probe for cpu_only fallback - [Phase 30-hardware-detection-mode-selection]: Hardware probe is non-blocking — wizard step 1 always has an enabled Continue button regardless of probe outcome - [Phase 30-hardware-detection-mode-selection]: Mode save on wizard completion is non-blocking — wrapped in try/catch, defaults to 'both' on failure +- [Phase 31-puter.js-zero-config-cloud]: agentId is optional in puterProxyService.chatStream — cost recording skipped when null/undefined to avoid FK violation in cost_events ### Pending Todos @@ -87,6 +90,6 @@ None yet. ## Session Continuity -Last session: 2026-04-02T23:54:51.280Z -Stopped at: Completed 30-hardware-detection-mode-selection/30-02 (all 3 tasks, human-verify approved) +Last session: 2026-04-03T00:37:30.288Z +Stopped at: Completed 31-puter.js-zero-config-cloud/31-01 Resume file: None diff --git a/.planning/phases/31-puter.js-zero-config-cloud/31-01-SUMMARY.md b/.planning/phases/31-puter.js-zero-config-cloud/31-01-SUMMARY.md new file mode 100644 index 00000000..626003e5 --- /dev/null +++ b/.planning/phases/31-puter.js-zero-config-cloud/31-01-SUMMARY.md @@ -0,0 +1,71 @@ +--- +phase: 31-puter.js-zero-config-cloud +plan: "01" +subsystem: server +tags: [puter, proxy, sse, streaming, cost-tracking, secrets] +dependency_graph: + requires: [] + provides: [puterProxyService, puterProxyRoutes] + affects: [server/src/app.ts] +tech_stack: + added: [] + patterns: [SSE streaming, AsyncGenerator, secretService token storage, conditional cost recording] +key_files: + created: + - server/src/services/puter-proxy.ts + - server/src/routes/puter-proxy.ts + - server/src/__tests__/31-puter-proxy.test.ts + modified: + - server/src/app.ts +decisions: + - "agentId is optional in chatStream — cost recording skipped when null/undefined to avoid FK violation in cost_events" + - "PUTER_DEFAULT_MODEL set to claude-3-5-haiku-20241022 matching Puter's OpenAI-compat endpoint" + - "Non-blocking cost recording via .catch(() => {}) pattern — stream completes regardless of cost event persistence" +metrics: + duration: 4m + completed: 2026-04-03 + tasks_completed: 2 + files_changed: 4 +requirements: [CLOUD-01, CLOUD-02] +--- + +# Phase 31 Plan 01: Puter Proxy Service + Routes Summary + +JWT auth with Puter token stored via secretService and relayed as Bearer header to Puter's OpenAI-compatible SSE endpoint with conditional cost tracking. + +## What Was Built + +**`server/src/services/puter-proxy.ts`** — `puterProxyService(db)` factory with: +- `storeToken(companyId, token)`: create-or-rotate idempotent token storage via `secretService` with name `puter_auth_token`, provider `local_encrypted` +- `resolveToken(companyId)`: retrieves and resolves latest secret version; throws `unprocessable` if not configured +- `chatStream(companyId, agentId, messages, model, signal)`: AsyncGenerator that POSTs to `https://api.puter.com/puterai/openai/v1/chat/completions` with `stream: true` and `stream_options: { include_usage: true }`, parses SSE lines, yields content tokens, records cost event (only when agentId is truthy) + +**`server/src/routes/puter-proxy.ts`** — `puterProxyRoutes(db)` Express Router with: +- `POST /puter-proxy/token` — board auth, stores token, returns `{ ok: true }` +- `POST /puter-proxy/chat` — board auth, SSE headers, streams tokens as `data: { token: "..." }`, sends `data: { done: true }` on completion + +**`server/src/app.ts`** — import and mount `api.use(puterProxyRoutes(db))` after `costRoutes`, inside boardMutationGuard. + +**`server/src/__tests__/31-puter-proxy.test.ts`** — 10 vitest tests covering all behaviors (token create/rotate, token resolve, Puter fetch headers, SSE yielding, cost recording with agentId, cost skip without agentId, route 200/SSE/optional-agentId). + +## Verification + +- All 10 tests passing: `npx vitest run src/__tests__/31-puter-proxy.test.ts` +- All 14 acceptance criteria pass (grep checks) +- New files produce zero TypeScript errors (pre-existing plugin-sdk errors unrelated to this plan) + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] Test 4 mock missing return value for createEvent** +- **Found during:** GREEN phase test run — Test 4 passed agentId="agent-1" triggering cost recording but mockCreateEvent had no configured return (returns undefined after vi.clearAllMocks) +- **Fix:** Added `mockCreateEvent.mockResolvedValue({ id: "ev-1" })` to Test 4 setup +- **Files modified:** server/src/__tests__/31-puter-proxy.test.ts +- **Commit:** 13bc39b1 + +## Known Stubs + +None — all data paths are wired. The Puter token is resolved from secretService on every call (no stub). + +## Self-Check: PASSED