feat: command palette, UI polish, and file reorganization - #10
Conversation
- Add CommandPalette component with keyboard shortcut support - Improve SpreadsheetGrid, ChatPanel, MenuBar, ConditionalFormatDialog - Add workbookJson import/export with tests - Rename src/ai/skills/ to src/ai/analysis/ (clearer naming) - Rename src/data/skills.ts to src/data/chatPresets.ts - Update AI modules (brain, queryEngine, sheetProfile, responseBuilder) - Add recommended VS Code extensions
Reviewer's GuideAdds a keyboard-driven command palette, workbook JSON backup/restore utilities with tests, AI action preview UX in the grid, conditional formatting data bar support, and aligns AI analysis modules and tests while tightening type safety and editor setup. Sequence diagram for keyboard-driven command palette and chat focussequenceDiagram
actor User
participant App
participant CommandPalette
participant Document
participant ChatPanel
User->>Document: keydown (Ctrl/Cmd+K)
Document->>App: keydown handler
App-->>App: setShowCommandPalette(true)
App->>CommandPalette: render open=true
User->>CommandPalette: select Focus chat input
CommandPalette-->>App: onFocusChat()
App-->>App: setShowChat(true), setIsMobileChatOpen(true)
App->>Document: dispatch smartsht:focus-chat
Document->>ChatPanel: smartsht:focus-chat event
ChatPanel-->>ChatPanel: inputRef.focus()
Sequence diagram for AI action previews and apply/reject in SpreadsheetGridsequenceDiagram
participant Agent
participant responseBuilder
participant Store
participant SpreadsheetGrid
actor User
Agent->>responseBuilder: toolResultToChatMessage(result, previewContext)
responseBuilder-->>Store: addMessage(ChatMessage with actions and preview)
SpreadsheetGrid->>Store: useStore()
SpreadsheetGrid-->>SpreadsheetGrid: findActivePendingPreview(messages)
SpreadsheetGrid-->>User: render AI staged banner and cell highlights
User->>SpreadsheetGrid: click Apply
SpreadsheetGrid->>Store: applyAction(pendingPreview.action.id)
Store-->>SpreadsheetGrid: updated workbook, messages
User->>SpreadsheetGrid: click Reject
SpreadsheetGrid->>Store: rejectAction(pendingPreview.action.id)
Store-->>SpreadsheetGrid: cleared pendingPreview
Flow diagram for workbook JSON backup and restore utilitiesflowchart TD
A[WorkbookData] --> B[serializeWorkbookPackage]
B --> C[exportWorkbookToJson]
C --> D[Download .smartsht.json]
E[JSON file] --> F[importWorkbookFromJsonFile]
F --> G[parseWorkbookJson]
G --> H[normalizeImportedWorkbook]
H --> I[WorkbookData loaded via loadWorkbookData]
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Warning Review limit reached
Next review available in: 54 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (28)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…env) Record the 10 review items that couldn't be verified in a sandbox (live LLM keys, DB/S3/AWS, ONNX models, browser matrix, load). Notes where this session already added coverage (real-engine test tier for #1, SSRF hardening + tests for #9) and resolves two from code: #6 PM2 cwd is set in the committed server/ecosystem.config.cjs (models resolve correctly when started via it), and #10 vite.config sets no allowedHosts (strict default; dev server not deployed).
… guards, real-engine tests, docs (#22) * deploy: frontend rollback, stale-vector regen via phrase hash, single-source phrases - deploy.sh: extract mirror_frontend(); rebuild+remirror frontend from PREV_COMMIT on health-check rollback so the live SPA matches the API. - intent-vectors.bin format v2: embed FNV-1a hash of the phrase set. Client rejects a binary whose hash no longer matches (falls back to runtime bootstrap); precompute self-skips when current, regenerates when stale. - deploy.sh always runs model:precompute when the model is present (was gated on file absence, which shipped stale vectors after a phrase edit). - Eliminate INTENT_PHRASES duplication: single source in shared/intentPhrases.js imported by both intentEmbeddings.ts and precompute-embeddings.mjs. - Update intentVectorsBin.test.ts to v2 format; add stale-hash and parity tests. * intent parser return with question * fix(parser): claim bare 'add a row' for clarification; align README with real instant-op coverage The addRow branch required trailing values, so the README's own 'add a row' example fell through to the LLM. Make the values capture optional and return a clarifying question when a row has no values (add_row rejects empty rows, so we ask instead of emitting a failing call). Valued rows still parse straight to add_row. Rewrite the Intent Parser section to name operations that are genuinely instant (sort, formatting, set cell, add a row of values, delete a row, find & replace, percentage tweaks) and note totals/group-bys are matched locally by the goal router. Drops the implication that bare add-a-row, hide/freeze/merge are instant. Add a parser.gaps regression covering the bare 'add a row' clarification. * docs: clarify local/open-mode run and that Clerk/Stripe keys are for hosted deploys only The app runs fully without auth when VITE_CLERK_PUBLISHABLE_KEY is blank, but a fresh clone had no explanation of this and the .env.example _live_ placeholders read as required. Add a 'Running locally' README section and inline .env.example notes explaining open mode, and that Clerk/Stripe/cloud-sync are only needed for a self-hosted gated instance using the operator's own keys. * fix(server): harden BYOK against SSRF (redirects, DNS rebinding, IP-encoding bypasses) The BYOK baseUrl validator only string-matched hostnames, and the outbound fetches followed redirects by default. A user could reach internal services / the cloud metadata endpoint via: a public URL that 302s to an internal address; a public DNS name resolving to a private IP (rebinding); or alternate IP encodings (decimal/octal/hex/IPv6-mapped) that dodged the string checks. Fixes: (1) isPublicHttpsByokUrl now canonicalizes IP literals and checks full private/loopback/link-local/CGNAT/ULA/IPv4-mapped ranges; (2) new async assertPublicByokHost resolves the host and rejects private resolved IPs, wired into both BYOK call sites before fetch; (3) both openaiCompatible fetches use redirect:'manual' and refuse 3xx/opaqueredirect. Adds regression tests. Full server suite 317/317. * chore(deps): remove xlsx CDN SPOF, patch server audit findings, gate CI audit at critical + weekly advisory sweep Vendor the official SheetJS xlsx-0.20.3 tarball (SHA512 matches the lockfile integrity byte-for-byte) and pin xlsx to file:vendor/, so installs no longer depend on cdn.sheetjs.com uptime (which was hard-failing CI and deploy.sh on outages/proxies). Apply available server audit fixes: nanoid 3.3.16->3.3.18 (GHSA-2v37-7h3g-55p8, high) and qs 6.15.3->6.16.0 (two moderate). Lockfile-only transitive bumps; npm audit --prefix server now clean; server suite 317/317. CI: replace 'npm audit --audit-level=high || true' with 'npm audit --audit-level=critical' (no || true) so critical fixable advisories fail the build, and add a scheduled/dispatch advisory-only 'audit' job that opens/updates a dependencies-labeled issue on high-or-worse findings instead of blocking PRs. * docs(deploy): note vendored xlsx tarball must survive checkout xlsx is now pinned to file:vendor/xlsx-0.20.3.tgz, so npm ci resolves it from the committed tarball. Add a Pending item in PRODUCTION-TODO.md and an inline comment at deploy.sh's npm ci step so a future deploy doesn't drop vendor/ and break the install. * fix(persistence): surface localStorage quota/failure and quarantine corrupt state instead of silent data loss savePersistedState swallowed all errors, so a full localStorage silently no-oped every 400ms autosave while the user believed work was saved. loadPersistedState returned null on any parse error, discarding all workbooks + chat with no recovery. Now: savePersistedState returns a LocalSaveResult (ok | quota | error) and main.tsx surfaces a single non-blocking toast per quota episode; loadPersistedState quarantines the raw payload to smartsht-state-v1.corrupt before returning null. persistence.ts stays UI-free. Adds 4 tests (8/8 pass); typecheck clean. * docs: record deferred persistence follow-ups (LRU eviction, IndexedDB migration) Capture the two persistence improvements deliberately left out of 04b3a62, with scope, gotchas, and the stability tradeoff for the IndexedDB move, so they can be picked up later without re-deriving the context. * fix(health): add strict readiness (503 on DB/S3/Clerk down) and gate deploy.sh on it /health always returned 200 and its ok flag reflected only AI-provider liveness, so deploy.sh's curl -sf gate reported a DB-broken deploy healthy and never rolled back. Add ?strict=1 which returns 503 unless db.ok && s3.ok && clerk.ok (mirrors config.ts criticality: cloud save/sharing/versions/usage need DB+S3, auth needs Clerk). AI providers and Stripe stay informational — they degrade gracefully, so gating rollback on them would revert a healthy deploy. Plain /health is unchanged for liveness probes. deploy.sh now curls /health?strict=1. Adds 6 tests; server suite 323/323. * docs(deploy): note strict health gate requires DB/S3/Clerk on next deploy deploy.sh now gates rollback on /health?strict=1 (503 unless DB+S3+Clerk healthy). Record in PRODUCTION-TODO so a 503-driven rollback is read as a real subsystem outage, not a false alarm, and note AI providers/Stripe are excluded from the gate. * test(engine): add real-WASM integration tier and clearly label the stubbed unit tier Every vitest run aliased the WASM formula engine to a toy stub (arithmetic + SUM + single refs), so the real engine — dependency graph, recalc, cross-sheet refs, circular detection, error propagation — had zero automated coverage even though the auditor, grid, and chat actions depend on it. Rename the stub to formualizer.stub.ts with a header stating it is not the real engine. Add vitest.integration.config.ts (vite-plugin-wasm, no alias, only *.realengine.test.ts) and src/engine/formualizer.realengine.test.ts (8 tests: recalc after edit, multi-hop propagation, cross-sheet refs, #CIRC!, #DIV/0!, #NAME? — all verified against the real engine). Add npm script test:realengine and wire it into CI. Exclude *.realengine.test.ts from the stubbed unit tier so it isn't run against the stub. Unit tier 1463/1463, real-engine tier 8/8. WASM-in-Node proved viable, so no Playwright fallback needed. Structural insert/delete ref-rewrite was dropped: not an API this engine exposes. * docs(deploy): correct build-artifact shape; assert wasm in deploy; gzip wasm DEPLOY.md claimed the frontend is a single dist/index.html and showed a cp dist/index.html snippet that would 404 the WASM engines. In reality vite-plugin-singlefile inlines JS/CSS but the build emits external .wasm engines (formualizer ~8.6MB, ONNX ~27MB) + worker bundles under dist/assets/. Correct the docs (artifact list, ls verify, rsync the whole tree, /var/www layout). deploy.sh: assert dist/assets contains .wasm after the build (fail → rollback) so a broken build can't ship an engine-less SPA. nginx: add application/wasm to gzip_types so the large binaries are compressed in transit (~4x); brotli left as a documented opt-in since ngx_brotli may be absent and would fail nginx -t. Verified already-handled (no change): wasm 30d cache + hashed names, lazy ONNX worker spawn, SW version-keyed cache eviction. * chore: repo hygiene - drop tsc dumps & unused assets, untrack ignored dirs, fix Node version & stale roadmap Remove committed debugging leftovers (tsc-output.txt, tsc-result.txt) and 32 unused src/assets image files (verified zero references repo-wide). Untrack .idea/.vscode/.junie/docs/superpowers via git rm --cached to honor .gitignore (files kept locally). README: Node prerequisite 20+ -> 22+ to match package.json engines and CI. Refresh the stale roadmap: auto-insights on import, auditor auto-run, and the cell inspector are already shipped (verified) - move them to a shipped note and list the real next items (guided navigation) from roadmap-v1.md. typecheck clean after removals. * docs: sync GROQ_MODEL to live prod (qwen3.6-27b), complete README env table, drop stale model:setup marker Verified against the live server: /opt/smartsht/.env has GROQ_MODEL=qwen/qwen3.6-27b, but server/.env.production, both .env.example files, and the README said openai/gpt-oss-120b. Align all four to the live value (config.ts keeps gpt-oss-120b only as its unset-fallback default; qwen3.6-27b is already in KNOWN_GROQ_MODELS). README config: mark server/.env.example + docs/ENV.md as the authoritative full env list, note the table is a starter subset, and add the missing CLERK_*/STRIPE_*/DATABASE_URL/S3_*/AWS_*/TRUST_PROXY/WORKBOOK_BODY_LIMIT/FREE_CLOUD_WORKBOOK_LIMIT/MAX_WORKBOOK_VERSIONS rows. Remove the stray '##deprecated' on npm run model:setup. PRODUCTION-TODO: add a follow-up to verify at runtime which .env file and model ids/paths the smartsht-api process actually loads, since this drift was only caught by manual SSH. * docs: capture verification backlog (items needing a live/integration env) Record the 10 review items that couldn't be verified in a sandbox (live LLM keys, DB/S3/AWS, ONNX models, browser matrix, load). Notes where this session already added coverage (real-engine test tier for #1, SSRF hardening + tests for #9) and resolves two from code: #6 PM2 cwd is set in the committed server/ecosystem.config.cjs (models resolve correctly when started via it), and #10 vite.config sets no allowedHosts (strict default; dev server not deployed).
UI and organizational improvements.
Changes:
Summary by Sourcery
Introduce a keyboard-driven command palette, JSON workbook backup/restore, and AI action previews, while refining conditional formatting, analysis modules, and UI copy.
New Features:
Enhancements:
Build:
Documentation:
Tests:
Chores: